diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..c60aedf7a --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: db4s diff --git a/.github/ISSUE_TEMPLATE/Bug_report.yaml b/.github/ISSUE_TEMPLATE/Bug_report.yaml new file mode 100644 index 000000000..59a689364 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_report.yaml @@ -0,0 +1,83 @@ +name: Bug Report +description: Create a report to help us improve +title: "[Bug]: " +labels: [] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + - type: textarea + id: what-did-you-do + attributes: + label: What did you do? + description: Tell us, what did you do before the issue appeared? + placeholder: I selected/clicked/opened... + validations: + required: true + - type: textarea + id: what-did-you-expect + attributes: + label: What did you expect to see? + description: Also tell us, what did you expect to happen? + placeholder: I expected that... + validations: + required: true + - type: textarea + id: what-happened + attributes: + label: What did you see instead? + description: Finally tell us, what happened, that you did not expect? Screenshots or video recordings help. + placeholder: What happened instead was... + validations: + required: true + - type: dropdown + id: version + attributes: + label: DB4S Version + description: What version of DB Browser for SQLite are you running? + options: + - 3.13.1 + - 3.13.0 + - 3.12.2 + - 3.12.1 + - 3.12.0 + - 3.11.x + - 3.13.99 (nightly) + - Other + validations: + required: true + - type: dropdown + id: os + attributes: + label: What OS are you seeing the problem on? + multiple: true + options: + - Windows + - Linux + - MacOS + - Other + validations: + required: true + - type: input + id: os-version + attributes: + label: OS version + description: "Identify the OS version" + placeholder: "Windows 10, Ubuntu Linux 20.04..." + validations: + required: false + - type: textarea + id: logs + attributes: + label: Relevant log output + description: Please copy and paste any relevant log output (console, "SQL Log" pane, etc.). This will be automatically formatted into code, so no need for backticks. + render: shell + - type: checkboxes + id: terms + attributes: + label: Prevention against duplicate issues + description: By submitting this issue, you confirm that you have searched for similar issues before opening a new one. You could comment or subscribe to the found issue. + options: + - label: I have searched for similar issues + required: true diff --git a/.github/ISSUE_TEMPLATE/Feature_request.yaml b/.github/ISSUE_TEMPLATE/Feature_request.yaml new file mode 100644 index 000000000..451d405ec --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_request.yaml @@ -0,0 +1,27 @@ +name: Feature Request +description: Suggest an idea or request a new feature. +title: "[Feature]: " +labels: [] +body: + - type: markdown + attributes: + value: | + Thanks for coming here to suggest a new feature. Please answer these questions before submitting your feature request. + - type: textarea + id: description + attributes: + label: Describe the new feature + validations: + required: true + - type: textarea + id: examples + attributes: + label: Does this feature exist in another product or project? Please provide a link + validations: + required: false + - type: textarea + id: screenshot + attributes: + label: Do you have a screenshot? Please add screenshots to help explain your idea. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..43cbedbe0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: GitHub Community Support + url: https://github.com/sqlitebrowser/sqlitebrowser/discussions + about: Please ask and answer questions here. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..5ace4600a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..5694ae2eb --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,80 @@ +name: "CodeQL" + +on: + push: + branches: ["master"] + pull_request: + # The branches below must be a subset of the branches above + branches: ["master"] + schedule: + - cron: "14 22 * * 6" + +jobs: + analyze: + name: Analyze + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: ["cpp", "python"] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - if: matrix.language == 'cpp' + name: Install dependencies + run: | + sudo apt-get update + sudo apt install build-essential git cmake libsqlite3-dev qtchooser qt5-qmake qtbase5-dev-tools qttools5-dev-tools libsqlcipher-dev qtbase5-dev libqt5scintilla2-dev libqcustomplot-dev qttools5-dev + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + 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. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + - if: matrix.language == 'cpp' + name: Build C++ + run: | + mkdir build && cd build + cmake -Dsqlcipher=1 -Wno-dev .. + make + sudo make install + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + - if: matrix.language != 'cpp' + name: Autobuild + uses: github/codeql-action/autobuild@v4 + + # â„¹ï¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/cppcmake-macos.yml b/.github/workflows/cppcmake-macos.yml new file mode 100644 index 000000000..5ad2bc02c --- /dev/null +++ b/.github/workflows/cppcmake-macos.yml @@ -0,0 +1,127 @@ +name: Build (macOS) + +on: + workflow_call: + inputs: + NIGHTLY: + default: false + type: boolean + workflow_dispatch: + +jobs: + build: + name: ${{ matrix.os }} (${{ matrix.bundle }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + bundle: [SQLCipher, SQLite] + os: [macos-14] + env: + MACOSX_DEPLOYMENT_TARGET: 10.13 + steps: + - name: Checkout + uses: actions/checkout@v6 + + # Uninstall Mono, which is included by default in GitHub-hosted macOS runners, + # as it interferes with referencing our own compiled SQLite libraries. + - name: Uninstall Mono + run: | + sudo rm -rfv /Library/Frameworks/Mono.framework + sudo pkgutil --forget com.xamarin.mono-MDK.pkg + sudo rm -v /etc/paths.d/mono-commands + + - name: Install dependencies + run: | + brew tap sqlitebrowser/tap + brew install sqlb-qt@5 sqlb-sqlcipher sqlb-sqlite ninja + npm install -g appdmg + + - name: Configure build + run: | + if [ "${{ inputs.NIGHTLY }}" = "true" ]; then + if [ "${{ matrix.bundle }}" = "SQLCipher" ]; then + sed -i "" 's/"DB Browser for SQLite"/"DB Browser for SQLCipher Nightly"/' config/platform_apple.cmake + else + sed -i "" 's/"DB Browser for SQLite"/"DB Browser for SQLite Nightly"/' config/platform_apple.cmake + fi + else + if [ "${{ matrix.bundle }}" = "SQLCipher" ]; then + sed -i "" 's/"DB Browser for SQLite"/"DB Browser for SQLCipher-dev-'$(git rev-parse --short --verify HEAD)'"/' config/platform_apple.cmake + else + sed -i "" 's/"DB Browser for SQLite"/"DB Browser for SQLite-dev-'$(git rev-parse --short --verify HEAD)'"/' config/platform_apple.cmake + fi + fi + + mkdir -v build && cd build + cmake -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_STANDARD=14 \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -DcustomTap=1 \ + -DENABLE_TESTING=ON \ + -Dsqlcipher=${{ matrix.bundle == 'SQLCipher' }} .. + + - name: Build + working-directory: ./build + run: ninja + + - name: Tests + working-directory: ./build + run: ninja test + + - name: Build Extension + run: clang -I /opt/homebrew/opt/sqlb-sqlite/include -L /opt/homebrew/opt/sqlb-sqlite/lib -fno-common -dynamiclib src/extensions/extension-formats.c + + - if: github.event_name != 'pull_request' + name: Notarization + id: notarization + run: chmod +x ./installer/macos/notarize.sh && ./installer/macos/notarize.sh + env: + APPLE_ID: ${{ secrets.MACOS_CODESIGN_APPLE_ID }} + APPLE_PW: ${{ secrets.MACOS_CODESIGN_APPLE_PW }} + DEV_ID: ${{ secrets.MACOS_CODESIGN_DEV_ID }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + KEYCHAIN_PW: ${{ secrets.MACOS_CODESIGN_KEYCHAIN_PW }} + P12: ${{ secrets.MACOS_CODESIGN_P12 }} + P12_PW: ${{ secrets.MACOS_CODESIGN_P12_PW }} + NIGHTLY: ${{ inputs.NIGHTLY || false }} + SQLCIPHER: ${{ matrix.bundle == 'SQLCipher'}} + TEAM_ID: ${{ secrets.MACOS_CODESIGN_TEAM_ID }} + + - if: steps.notarization.conclusion != 'skipped' + name: Clear Keychain + run: security delete-keychain $RUNNER_TEMP/app-signing.keychain-db + continue-on-error: true + + - if: github.event_name != 'pull_request' && github.workflow != 'Build (macOS)' + name: Upload artifacts + uses: actions/upload-artifact@v7 + with: + name: build-artifacts-${{ matrix.os }}-${{ matrix.bundle }} + path: DB.Browser.for.*.dmg + retention-days: 1 + + - if: github.event_name == 'workflow_dispatch' && github.workflow == 'Build (macOS)' + name: Release + uses: softprops/action-gh-release@v2 + with: + files: DB.Browser.for.*.dmg + prerelease: true + tag_name: ${{ github.sha }}-macos + + - name: Summary + run: | + QT_VERSION=$($(brew --prefix sqlb-qt@5)/bin/qmake --version | awk '/Using Qt version/ {print $4}') + if [ "${{ matrix.bundle }}" = "SQLCipher" ]; then + OPENSSL_VERSION=$($(brew --prefix sqlb-openssl@3)/bin/openssl version | awk '{print $2}') + SQLCIPHER_VERSION=$($(brew --prefix sqlb-sqlcipher)/bin/sqlcipher ":memory:" "PRAGMA cipher_version;" | awk '{print $1}') + SQLITE_VERSION="Not applicable" + else + OPENSSL_VERSION="Not applicable" + SQLCIPHER_VERSION="Not applicable" + SQLITE_VERSION=$($(brew --prefix sqlb-sqlite)/bin/sqlite3 --version | awk '{print $1}') + fi + + echo "## Libaries used" >> $GITHUB_STEP_SUMMARY + echo "OpenSSL: $OPENSSL_VERSION, Qt: $QT_VERSION, SQLCipher: $SQLCIPHER_VERSION, SQLite: $SQLITE_VERSION" >> $GITHUB_STEP_SUMMARY \ No newline at end of file diff --git a/.github/workflows/cppcmake-ubuntu.yml b/.github/workflows/cppcmake-ubuntu.yml new file mode 100644 index 000000000..d2df24e26 --- /dev/null +++ b/.github/workflows/cppcmake-ubuntu.yml @@ -0,0 +1,130 @@ +# KEEP THE RUNNER OS AS LOW AS POSSIBLE. +# If built on the latest OS, it may not run on previous OS versions. +# Related: https://docs.appimage.org/reference/best-practices.html#binaries-compiled-on-old-enough-base-system + +name: Build (Ubuntu) + +on: + workflow_call: + inputs: + NIGHTLY: + default: false + type: boolean + workflow_dispatch: + +jobs: + build: + name: ${{ matrix.os }} (${{ matrix.bundle }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + bundle: [SQLCipher, SQLite] + os: [ubuntu-22.04, ubuntu-22.04-arm] + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Install and cache dependencies + uses: awalsh128/cache-apt-pkgs-action@v1.6.0 + with: + packages: libfuse2 libqcustomplot-dev libqscintilla2-qt5-dev libqt5svg5 ninja-build qttools5-dev + version: ${{ matrix.os }} + + - if: matrix.bundle == 'SQLCipher' + name: Build SQLCipher + working-directory: ${{ runner.temp }} + run: | + git clone https://github.com/sqlcipher/sqlcipher && cd sqlcipher && git checkout $(git describe --tags --abbrev=0) + LDFLAGS="-lcrypto -Wl,-soname,libsqlcipher.so.0" ./configure --prefix=./prefix --with-tempstore=yes --enable-load-extension --disable-tcl CFLAGS="-DSQLITE_EXTRA_INIT=sqlcipher_extra_init -DSQLITE_EXTRA_SHUTDOWN=sqlcipher_extra_shutdown -DSQLCIPHER_CRYPTO_OPENSSL -DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_GEOPOLY -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_SNAPSHOT=1 -DSQLITE_ENABLE_STAT4 -DSQLITE_HAS_CODEC -DSQLITE_SOUNDEX" + make -j2 && sudo make install -j2 + cp ${GITHUB_WORKSPACE}/installer/linux/sqlcipher_rename.sh . + chmod +x sqlcipher_rename.sh && sudo ./sqlcipher_rename.sh + + - if: matrix.bundle == 'SQLite' + name: Build SQLite + run: | + TARBALL=$(curl -s https://sqlite.org/download.html | awk '// {print}' | grep 'sqlite-autoconf' | cut -d ',' -f 3) + SHA3=$(curl -s https://sqlite.org/download.html | awk '// {print}' | grep 'sqlite-autoconf' | cut -d ',' -f 5) + curl -LsS -o sqlite.tar.gz https://sqlite.org/${TARBALL} + VERIFY=$(openssl dgst -sha3-256 sqlite.tar.gz | cut -d ' ' -f 2) + if [ "$SHA3" != "$VERIFY" ]; then + echo "::error::SQLite tarball checksum mismatch." + exit 1 + fi + tar -xzf sqlite.tar.gz && cd sqlite-autoconf-* + + CPPFLAGS="-DSQLITE_ENABLE_COLUMN_METADATA=1 -DSQLITE_MAX_VARIABLE_NUMBER=250000 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_STAT4=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_SOUNDEX=1 -DSQLITE_ENABLE_MATH_FUNCTIONS=1 -DSQLITE_MAX_ATTACHED=125 -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 -DSQLITE_ENABLE_SNAPSHOT=1" ./configure --disable-shared + make -j2 && sudo make install -j2 + + - name: Configure build + run: | + mkdir -v appbuild appdir && cd appbuild + cmake -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_PREFIX_PATH=$RUNNER_TEMP/sqlcipher/prefix \ + -DCMAKE_INSTALL_PREFIX:PATH=../appdir/usr \ + -DENABLE_TESTING=ON \ + -DFORCE_INTERNAL_QSCINTILLA=ON \ + -Dsqlcipher=${{ matrix.bundle == 'SQLCipher' }} .. + + - name: Build + working-directory: ./appbuild + run: ninja install + + - name: Tests + working-directory: ./appbuild + run: ninja test + + - name: Build AppImage + run: | + wget -c -nv "https://github.com/linuxdeploy/linuxdeploy/releases/download/1-alpha-20240109-1/linuxdeploy-$(uname -m).AppImage" + wget -c -nv "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/1-alpha-20240109-1/linuxdeploy-plugin-qt-$(uname -m).AppImage" + chmod a+x "linuxdeploy-$(uname -m).AppImage" "linuxdeploy-plugin-qt-$(uname -m).AppImage" + if [ "${{ inputs.NIGHTLY }}" = "true" ]; then + export VERSION=$(date +%Y%m%d) + else + export VERSION=$(printf "dev-`git -C . rev-parse --short HEAD`") + fi + LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib;$RUNNER_TEMP/sqlcipher/prefix/lib" "./linuxdeploy-$(uname -m).AppImage" --appdir=appdir --desktop-file=appdir/usr/share/applications/sqlitebrowser.desktop --plugin qt --output appimage + + - name: Rename a file + run: | + for i in DB_Browser_for_SQLite*; do mv "$i" "${i//_/.}"; done + if [ "${{ matrix.bundle }}" = "SQLCipher" ]; then + export FILE=$(ls DB.Browser.for.SQLite*.AppImage) + export FILE=${FILE/SQLite/SQLCipher} + mv -v DB.Browser.for.SQLite*.AppImage $FILE + fi + + - if: github.event_name != 'pull_request' && github.workflow != 'Build (Ubuntu)' + name: Upload artifacts + uses: actions/upload-artifact@v7 + with: + name: build-artifacts-${{ matrix.os }}-${{ matrix.bundle }} + path: DB.Browser.for.*.AppImage + retention-days: 1 + + - if: github.event_name == 'workflow_dispatch' && github.workflow == 'Build (Ubuntu)' + name: Release + uses: softprops/action-gh-release@v2 + with: + files: DB.Browser.for.*.AppImage + prerelease: true + tag_name: ${{ github.sha }}-ubuntu + + - name: Summary + run: | + QT_VERSION=$(qmake --version | awk '/Using Qt version/ {print $4}') + if [ "${{ matrix.bundle }}" = "SQLCipher" ]; then + OPENSSL_VERSION=$(openssl version | awk '{print $2}') + SQLCIPHER_VERSION=$($RUNNER_TEMP/sqlcipher/prefix/bin/sqlcipher ":memory:" "PRAGMA cipher_version;" | awk '{print $1}') + SQLITE_VERSION="Not applicable" + else + OPENSSL_VERSION="Not applicable" + SQLCIPHER_VERSION="Not applicable" + SQLITE_VERSION=$(/usr/local/bin/sqlite3 --version | awk '{print $1}') + fi + + echo "## Libaries used" >> $GITHUB_STEP_SUMMARY + echo "OpenSSL: $OPENSSL_VERSION, Qt: $QT_VERSION, SQLCipher: $SQLCIPHER_VERSION, SQLite: $SQLITE_VERSION" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/cppcmake-windows.yml b/.github/workflows/cppcmake-windows.yml new file mode 100644 index 000000000..9cd2b70ae --- /dev/null +++ b/.github/workflows/cppcmake-windows.yml @@ -0,0 +1,216 @@ +name: Build (Windows) + +on: + workflow_call: + inputs: + NIGHTLY: + default: false + type: boolean + workflow_dispatch: + +jobs: + build: + name: ${{ matrix.os }}-${{ matrix.arch }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + arch: [x86, x64] + os: [windows-2022] + env: + GH_TOKEN: ${{ github.token }} + OPENSSL_VERSION: 1.1.1.2100 + QT_VERSION: 5.15.2 + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Install dependencies + run: | + choco install --no-progress ninja + if ("${{ matrix.arch }}" -eq "x86") { + choco install --no-progress openssl --x86 --version=${{ env.OPENSSL_VERSION}} + } else { + choco install --no-progress openssl --version=${{ env.OPENSSL_VERSION}} + } + + # When building SQLCipher, if we specify a path to OpenSSL and + # there are spaces in the path, an error will occur, so to + # avoid this, create the symlink. + New-Item -Path C:\dev -ItemType Directory + if ("${{ matrix.arch }}" -eq "x86") { + New-Item -Path "C:\dev\OpenSSL" -ItemType SymbolicLink -Value "C:\Program Files (x86)\OpenSSL-Win32\" + } else { + New-Item -Path "C:\dev\OpenSSL" -ItemType SymbolicLink -Value "C:\Program Files\OpenSSL" + } + + - name: Install Qt + uses: jurplel/install-qt-action@v4 + with: + arch: ${{ matrix.arch == 'x86' && 'win32_msvc2019' || matrix.arch == 'x64' && 'win64_msvc2019_64'}} + cache: true + cache-key-prefix: "cache" + version: ${{ env.QT_VERSION }} + + - name: Install VS2019 + run: choco install visualstudio2019community --package-parameters "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.Windows10SDK.19041 --add Microsoft.VisualStudio.Component.VC.Redist.MSM" + + - name: Setup MSVC + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{ matrix.arch == 'x86' && 'amd64_x86' || matrix.arch == 'x64' && 'amd64'}} + vsversion: 2019 + + - name: Build SQLite + run: | + $htmlContent = Invoke-WebRequest -Uri "https://sqlite.org/download.html" | Select-Object -ExpandProperty Content + $regex = [regex]::new('PRODUCT,(\d+\.\d+\.\d+),(\d+/sqlite-amalgamation-\d+\.zip),\d+,(.+)') + $match = $regex.Match($htmlContent) + $relativeUrl = $match.Groups[2].Value + $downloadLink = "https://sqlite.org/$relativeUrl" + Invoke-WebRequest -Uri $downloadLink -OutFile 'sqlite.zip' + Expand-Archive -Path sqlite.zip -DestinationPath C:\dev\ + Move-Item -Path C:\dev\sqlite-amalgamation-* C:\dev\SQLite\ + cd C:\dev\SQLite + cl sqlite3.c -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_STAT4 -DSQLITE_SOUNDEX -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_GEOPOLY -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_MATH_FUNCTIONS -DSQLITE_MAX_ATTACHED=125 -DSQLITE_API="__declspec(dllexport)" -link -dll -out:sqlite3.dll + + - name: Download SQLean extension + run: | + if ("${{ matrix.arch }}" -eq "x86") { + # sqlean has discontinued x86 support starting from v0.28.0 + gh release download 0.27.4 --pattern "sqlean-win-x86.zip" --repo "nalgeon/sqlean" + Expand-Archive -Path sqlean-win-x86.zip -DestinationPath .\sqlean + } else { + gh release download --pattern "sqlean-win-x64.zip" --repo "nalgeon/sqlean" + Expand-Archive -Path sqlean-win-x64.zip -DestinationPath .\sqlean + } + + - name: Build 'formats' Extensions + run: | + cp .\src\extensions\extension-formats.c C:\dev\SQLite\ + cp .\src\extensions\extension-formats.def C:\dev\SQLite\ + cd C:\dev\SQLite + cl /MD extension-formats.c -link -dll -def:extension-formats.def -out:formats.dll + + - name: Build SQLCipher + run: | + cd C:\dev + Invoke-WebRequest -Uri https://github.com/sqlcipher/sqlcipher/archive/refs/tags/v4.6.1.zip -OutFile 'sqlcipher.zip' + Expand-Archive -Path sqlcipher.zip -DestinationPath C:\dev\ + Move-Item -Path C:\dev\sqlcipher-4.6.1 C:\dev\SQLCipher\ + cd SQLCipher + nmake /f Makefile.msc sqlcipher.dll USE_AMALGAMATION=1 NO_TCL=1 SQLITE3DLL=sqlcipher.dll SQLITE3LIB=sqlcipher.lib SQLITE3EXE=sqlcipher.exe LTLINKOPTS="C:\dev\OpenSSL\lib\libcrypto.lib" OPT_FEATURE_FLAGS="-DSQLITE_TEMP_STORE=2 -DSQLITE_HAS_CODEC=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_STAT4=1 -DSQLITE_SOUNDEX=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_RTREE=1 -DSQLCIPHER_CRYPTO_OPENSSL=1 -DSQLITE_MAX_ATTACHED=125 -IC:\dev\OpenSSL\include" + mkdir sqlcipher + copy sqlite3.h sqlcipher + + - name: Configure build (SQLite) + run: | + mkdir release-sqlite && cd release-sqlite + cmake -G "Ninja Multi-Config" -DCMAKE_PREFIX_PATH="C:\dev\SQLite" ..\ + + - name: Build (SQLite) + run: | + cd release-sqlite + cmake --build . --config Release + + - name: Configure build (SQLCipher) + run: | + mkdir release-sqlcipher && cd release-sqlcipher + cmake -G "Ninja Multi-Config" -Dsqlcipher=1 -DCMAKE_PREFIX_PATH="C:\dev\OpenSSL;C:\dev\SQLCipher" ..\ + + - name: Build (SQLCipher) + run: | + cd release-sqlcipher + cmake --build . --config Release + + - if: github.event_name != 'pull_request' + name: Create MSI + env: + ExePath: ${{ github.workspace }} + OpenSSLPath: C:\dev\OpenSSL + SQLCipherPath: C:\dev\SQLCipher + SqleanPath: ${{ github.workspace }}\sqlean + SQLitePath: C:\dev\SQLite + run: | + cd installer/windows + ./build.cmd "${{ matrix.arch }}".ToLower() + $DATE=$(Get-Date -Format "yyyyMMdd") + if ("${{ inputs.NIGHTLY }}" -eq "true") { + mv DB.Browser.for.SQLite-*.msi "DB.Browser.for.SQLite-$DATE-${{ matrix.arch }}.msi" + } else { + mv DB.Browser.for.SQLite-*.msi "DB.Browser.for.SQLite-dev-$(git rev-parse --short HEAD)-${{ matrix.arch }}.msi" + } + + - if: github.event_name != 'pull_request' + name: Upload artifacts for code signing with SignPath + id: unsigned-artifacts + uses: actions/upload-artifact@v7 + with: + name: build-artifacts-${{ matrix.os }}-${{ matrix.arch }}-unsigned + path: installer\windows\DB.Browser.for.SQLite-*.msi + + # Change the signing-policy-slug when you release an RC, RTM or stable release. + - if: github.event_name != 'pull_request' + name: Code signing with SignPath + uses: signpath/github-action-submit-signing-request@v2 + with: + api-token: '${{ secrets.SIGNPATH_API_TOKEN }}' + github-artifact-id: '${{ steps.unsigned-artifacts.outputs.artifact-id }}' + organization-id: '${{ secrets.SIGNPATH_ORGANIZATION_ID }}' + output-artifact-directory: .\installer\windows + project-slug: 'sqlitebrowser' + signing-policy-slug: 'test-signing' + wait-for-completion: true + + - if: github.event_name != 'pull_request' + name: Create ZIP + run: | + $DATE=$(Get-Date -Format "yyyyMMdd") + if ("${{ inputs.NIGHTLY }}" -eq "true") { + $FILENAME_FORMAT="DB.Browser.for.SQLite-$DATE-${{ matrix.arch }}.zip" + } else { + $FILENAME_FORMAT="DB.Browser.for.SQLite-dev-$(git rev-parse --short HEAD)-${{ matrix.arch }}.zip" + } + Start-Process msiexec.exe -ArgumentList "/a $(dir installer\windows\DB.Browser.for.SQLite-*.msi) /q TARGETDIR=$PWD\target\" -Wait + if ("${{ matrix.arch }}" -eq "x86") { + move target\System\* "target\DB Browser for SQLite\" + } else { + move target\System64\* "target\DB Browser for SQLite\" + } + Compress-Archive -Path "target\DB Browser for SQLite\*" -DestinationPath $FILENAME_FORMAT + + - if: github.event_name != 'pull_request' && github.workflow != 'Build (Windows)' + name: Prepare artifacts + run: | + mkdir build-artifacts + move installer\windows\DB.Browser.for.SQLite-*.msi build-artifacts\ + move DB.Browser.for.SQLite-*.zip build-artifacts\ + Compress-Archive -Path build-artifacts\* -DestinationPath build-artifacts-${{ matrix.arch }}.zip + + - if: github.event_name != 'pull_request' && github.workflow != 'Build (Windows)' + name: Upload artifacts + uses: actions/upload-artifact@v7 + with: + name: build-artifacts-${{ matrix.os }}-${{ matrix.arch }} + path: build-artifacts-${{ matrix.arch }}.zip + + - if: github.event_name == 'workflow_dispatch' && github.workflow == 'Build (Windows)' + name: Release + uses: softprops/action-gh-release@v2 + with: + files: installer/windows/DB.Browser.for.SQLite-*.msi, DB.Browser.for.SQLite-*.zip + prerelease: true + tag_name: ${{ github.sha }}-windows + + - name: Summary + run: | + $OPENSSL_VERSION=(C:\dev\OpenSSL\bin\openssl version) -replace "OpenSSL ([\d\.]+[a-z]+) .*", '$1' + $QT_VERSION = & "$env:QT_ROOT_DIR\bin\qmake.exe" --version | Select-String "Using Qt version" | ForEach-Object { $_.ToString().Split()[3] } + $SQLCIPHER_VERSION=(Get-Item "C:\dev\SQLCipher\sqlcipher.dll").VersionInfo.FileVersion + Select-String -Path "C:\dev\SQLite\sqlite3.h" -Pattern '#define SQLITE_VERSION\s+"([\d\.]+)"' | ForEach-Object { + ($_ -match '"([\d\.]+)"') | Out-Null + $SQLITE_VERSION=$matches[1] + } + + echo "## Libaries used" >> $env:GITHUB_STEP_SUMMARY + echo "OpenSSL: $OPENSSL_VERSION, Qt: $QT_VERSION, SQLCipher: $SQLCIPHER_VERSION, SQLite: $SQLITE_VERSION" >> $env:GITHUB_STEP_SUMMARY diff --git a/.github/workflows/cppcmake-windows_on_arm.yml b/.github/workflows/cppcmake-windows_on_arm.yml new file mode 100644 index 000000000..4e18aab53 --- /dev/null +++ b/.github/workflows/cppcmake-windows_on_arm.yml @@ -0,0 +1,225 @@ +# NOTES: This CI workflow is scheduled to be integrated with the existing Windows CI workflow in the future. + +name: Build (Windows on ARM) + +on: + workflow_call: + inputs: + NIGHTLY: + default: false + type: boolean + workflow_dispatch: + +jobs: + build: + name: ${{ matrix.os }}-arm64 + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [windows-11-arm] + env: + GH_TOKEN: ${{ github.token }} + QT_VERSION: 6.8.3 + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Install dependencies + run: | + choco install --no-progress ninja wixtoolset + + Invoke-WebRequest -Uri "https://slproweb.com/download/WinUniversalOpenSSL-3_6_1.exe" -OutFile WinUniversalOpenSSL-3_6_1.exe + Start-Process -FilePath .\WinUniversalOpenSSL-3_6_1.exe -ArgumentList '/ALLUSERS /verysilent /dir="C:\dev\OpenSSL"' -Wait + + - name: Install Qt + uses: jurplel/install-qt-action@v4 + with: + arch: 'win64_msvc2022_arm64' + cache: true + cache-key-prefix: 'cache' + modules: 'debug_info qt5compat qtactiveqt qtcharts qtconnectivity qtgraphs qtgrpc qthttpserver qtimageformats qtlanguageserver qtlocation qtlottie qtmultimedia qtnetworkauth qtpositioning qtquick3d qtquick3dphysics qtquicktimeline qtremoteobjects qtscxml qtsensors qtserialbus qtserialport qtshadertools qtspeech qtvirtualkeyboard qtwebchannel qtwebsockets' + version: ${{ env.QT_VERSION }} + + - name: Setup MSVC + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: arm64 + vsversion: 2022 + + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: CLANGARM64 + update: true + install: >- + curl + git + make + mingw-w64-clang-aarch64-clang + unzip + + - name: Build SQLite + run: | + $htmlContent = Invoke-WebRequest -Uri "https://sqlite.org/download.html" | Select-Object -ExpandProperty Content + $regex = [regex]::new('PRODUCT,(\d+\.\d+\.\d+),(\d+/sqlite-amalgamation-\d+\.zip),\d+,(.+)') + $match = $regex.Match($htmlContent) + $relativeUrl = $match.Groups[2].Value + $downloadLink = "https://sqlite.org/$relativeUrl" + Invoke-WebRequest -Uri $downloadLink -OutFile 'sqlite.zip' + Expand-Archive -Path sqlite.zip -DestinationPath C:\dev\ + Move-Item -Path C:\dev\sqlite-amalgamation-* C:\dev\SQLite\ + cd C:\dev\SQLite + cl sqlite3.c -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_STAT4 -DSQLITE_SOUNDEX -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_GEOPOLY -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_MATH_FUNCTIONS -DSQLITE_MAX_ATTACHED=125 -DSQLITE_API="__declspec(dllexport)" -link -dll -out:sqlite3.dll + + - name: Build SQLean extension + shell: msys2 {0} + run: | + git clone https://www.github.com/nalgeon/sqlean /c/dev/sqlean + cd /c/dev/sqlean + cp /c/a/sqlitebrowser/sqlitebrowser/installer/windows_on_arm/add_sqlean_arm64_target.patch . + git apply --ignore-space-change --ignore-whitespace add_sqlean_arm64_target.patch + make prepare-dist + make download-sqlite + make download-external + make compile-windows-arm64 + + - name: Build 'formats' Extensions + run: | + cp .\src\extensions\extension-formats.c C:\dev\SQLite\ + cp .\src\extensions\extension-formats.def C:\dev\SQLite\ + cd C:\dev\SQLite + cl /MD extension-formats.c -link -dll -def:extension-formats.def -out:formats.dll + + - name: Setup MSVC + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + vsversion: 2022 + + - name: Build x64 binaries for build SQLCipher + run: | + git clone https://www.github.com/sqlcipher/sqlcipher C:\dev\SQLCipher --branch v4.6.1 + cd C:\dev\SQLCipher + nmake /f Makefile.msc lemon.exe mkkeywordhash.exe mksourceid.exe src-verify.exe USE_AMALGAMATION=1 NO_TCL=1 SQLITE3DLL=sqlcipher.dll SQLITE3LIB=sqlcipher.lib SQLITE3EXE=sqlcipher.exe LTLINKOPTS="C:\dev\OpenSSL\lib\VC\x64\MD\libcrypto.lib" OPT_FEATURE_FLAGS="-DSQLITE_TEMP_STORE=2 -DSQLITE_HAS_CODEC=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_STAT4=1 -DSQLITE_SOUNDEX=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_RTREE=1 -DSQLCIPHER_CRYPTO_OPENSSL=1 -DSQLITE_MAX_ATTACHED=125 -IC:\dev\OpenSSL\include\x64" + + - name: Setup MSVC + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: arm64 + vsversion: 2022 + + - name: Build SQLCipher + run: | + cd C:\dev\SQLCipher + nmake /f Makefile.msc sqlcipher.dll USE_AMALGAMATION=1 NO_TCL=1 SQLITE3DLL=sqlcipher.dll SQLITE3LIB=sqlcipher.lib SQLITE3EXE=sqlcipher.exe LTLINKOPTS="C:\dev\OpenSSL\lib\VC\arm64\MD\libcrypto.lib" OPT_FEATURE_FLAGS="-DSQLITE_TEMP_STORE=2 -DSQLITE_HAS_CODEC=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_STAT4=1 -DSQLITE_SOUNDEX=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_RTREE=1 -DSQLCIPHER_CRYPTO_OPENSSL=1 -DSQLITE_MAX_ATTACHED=125 -IC:\dev\OpenSSL\include\arm64" + mkdir sqlcipher + copy sqlite3.h sqlcipher + mv VERSION VERSION.txt + + - name: Configure build (SQLite) + run: | + mkdir release-sqlite && cd release-sqlite + cmake -G "Ninja Multi-Config" -DCMAKE_PREFIX_PATH="C:\dev\SQLite" -DQT_MAJOR=Qt6 ..\ + + - name: Build (SQLite) + run: | + cd release-sqlite + cmake --build . --config Release + + - name: Configure build (SQLCipher) + run: | + mkdir release-sqlcipher && cd release-sqlcipher + cmake -G "Ninja Multi-Config" -Dsqlcipher=1 -DCMAKE_PREFIX_PATH="C:\dev\OpenSSL;C:\dev\SQLCipher" -DQT_MAJOR=Qt6 ..\ + + - name: Build (SQLCipher) + run: | + cd release-sqlcipher + cmake --build . --config Release + + - if: github.event_name != 'pull_request' + name: Create MSI + env: + ExePath: ${{ github.workspace }} + OpenSSLPath: C:\dev\OpenSSL + SQLCipherPath: C:\dev\SQLCipher + SqleanPath: C:\dev\sqlean + SQLitePath: C:\dev\SQLite + run: | + cd installer\windows_on_arm + ./build.cmd + $DATE=$(Get-Date -Format "yyyyMMdd") + if ("${{ inputs.NIGHTLY }}" -eq "true") { + mv DB.Browser.for.SQLite-*.msi "DB.Browser.for.SQLite-$DATE-arm64.msi" + } else { + mv DB.Browser.for.SQLite-*.msi "DB.Browser.for.SQLite-dev-$(git rev-parse --short HEAD)-arm64.msi" + } + + - if: github.event_name != 'pull_request' + name: Upload artifacts for code signing with SignPath + id: unsigned-artifacts + uses: actions/upload-artifact@v7 + with: + name: build-artifacts-${{ matrix.os }}-arm64-unsigned + path: installer\windows_on_arm\DB.Browser.for.SQLite-*.msi + + # Change the signing-policy-slug when you release an RC, RTM or stable release. + - if: github.event_name != 'pull_request' + name: Code signing with SignPath + uses: signpath/github-action-submit-signing-request@v2 + with: + api-token: '${{ secrets.SIGNPATH_API_TOKEN }}' + github-artifact-id: '${{ steps.unsigned-artifacts.outputs.artifact-id }}' + organization-id: '${{ secrets.SIGNPATH_ORGANIZATION_ID }}' + output-artifact-directory: .\installer\windows + project-slug: 'sqlitebrowser' + signing-policy-slug: 'test-signing' + wait-for-completion: true + + - if: github.event_name != 'pull_request' + name: Create ZIP + run: | + $DATE=$(Get-Date -Format "yyyyMMdd") + if ("${{ inputs.NIGHTLY }}" -eq "true") { + $FILENAME_FORMAT="DB.Browser.for.SQLite-$DATE-arm64.zip" + } else { + $FILENAME_FORMAT="DB.Browser.for.SQLite-dev-$(git rev-parse --short HEAD)-arm64.zip" + } + Start-Process msiexec.exe -ArgumentList "/a $(dir installer\windows_on_arm\DB.Browser.for.SQLite-*.msi) /q TARGETDIR=$PWD\target\" -Wait + Compress-Archive -Path "target\DB Browser for SQLite\*" -DestinationPath $FILENAME_FORMAT + + - if: github.event_name != 'pull_request' && github.workflow != 'Build (Windows)' + name: Prepare artifacts + run: | + mkdir build-artifacts + move installer\windows_on_arm\DB.Browser.for.SQLite-*.msi build-artifacts\ + move DB.Browser.for.SQLite-*.zip build-artifacts\ + Compress-Archive -Path build-artifacts\* -DestinationPath build-artifacts-arm64.zip + + - if: github.event_name != 'pull_request' && github.workflow != 'Build (Windows)' + name: Upload artifacts + uses: actions/upload-artifact@v7 + with: + name: build-artifacts-${{ matrix.os }}-arm64 + path: build-artifacts-arm64.zip + + - if: github.event_name == 'workflow_dispatch' && github.workflow == 'Build (Windows)' + name: Release + uses: softprops/action-gh-release@v2 + with: + files: installer/windows_on_arm/DB.Browser.for.SQLite-*.msi, DB.Browser.for.SQLite-*.zip + prerelease: true + tag_name: ${{ github.sha }}-windows + + - name: Summary + run: | + $OPENSSL_VERSION=(C:\dev\OpenSSL\bin\arm64\openssl version) -replace "OpenSSL ([\d\.]+[a-z]+) .*", '$1' + $QT_VERSION = & "$env:QT_ROOT_DIR\bin\qmake.exe" --version | Select-String "Using Qt version" | ForEach-Object { $_.ToString().Split()[3] } + $SQLCIPHER_VERSION=(Get-Item "C:\dev\SQLCipher\sqlcipher.dll").VersionInfo.FileVersion + Select-String -Path "C:\dev\SQLite\sqlite3.h" -Pattern '#define SQLITE_VERSION\s+"([\d\.]+)"' | ForEach-Object { + ($_ -match '"([\d\.]+)"') | Out-Null + $SQLITE_VERSION=$matches[1] + } + + echo "## Libaries used" >> $env:GITHUB_STEP_SUMMARY + echo "OpenSSL: $OPENSSL_VERSION, Qt: $QT_VERSION, SQLCipher: $SQLCIPHER_VERSION, SQLite: $SQLITE_VERSION" >> $env:GITHUB_STEP_SUMMARY diff --git a/.github/workflows/cppcmake.yml b/.github/workflows/cppcmake.yml new file mode 100644 index 000000000..f5478db07 --- /dev/null +++ b/.github/workflows/cppcmake.yml @@ -0,0 +1,107 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + schedule: + - cron: '0 0 * * *' # Every day at midnight UTC + workflow_dispatch: + inputs: + NIGHTLY: + description: 'Run as a nightly build' + default: false + required: true + type: boolean + +run-name: "${{ (github.event_name == 'schedule' || inputs.NIGHTLY == true) && 'Build and Deploy Nightly Builds' || github.event.head_commit.message}}" + +jobs: + check-skippable: + name: Check Skippable + runs-on: ubuntu-24.04 + outputs: + skip: ${{ steps.set-skippable.outputs.skippable || 'false' }} + steps: + - uses: actions/checkout@v6 + + - name: Check and set skippable + id: set-skippable + continue-on-error: true + run: | + if [ "${{ github.event_name }}" = "schedule" ]; then + git fetch origin tag nightly + LAST_COMMIT_HASH=$(git rev-list -n 1 nightly) + if [ "$(git rev-parse HEAD)" = "$LAST_COMMIT_HASH" ]; then + echo "::notice::No new commits since last nightly build, skipping this build." + echo "skippable=true" >> $GITHUB_OUTPUT + fi + else + echo "skippable=false" >> $GITHUB_OUTPUT + fi + + build-macos: + needs: check-skippable + if: needs.check-skippable.outputs.skip != 'true' + uses: ./.github/workflows/cppcmake-macos.yml + secrets: inherit + with: + NIGHTLY: ${{ github.event_name == 'schedule' || inputs.NIGHTLY == true }} + + build-ubuntu: + needs: check-skippable + if: needs.check-skippable.outputs.skip != 'true' + uses: ./.github/workflows/cppcmake-ubuntu.yml + with: + NIGHTLY: ${{ github.event_name == 'schedule' || inputs.NIGHTLY == true }} + + build-windows: + needs: check-skippable + if: needs.check-skippable.outputs.skip != 'true' + uses: ./.github/workflows/cppcmake-windows.yml + secrets: inherit + with: + NIGHTLY: ${{ github.event_name == 'schedule' || inputs.NIGHTLY == true }} + + build-windows_on_arm: + needs: check-skippable + if: needs.check-skippable.outputs.skip != 'true' + uses: ./.github/workflows/cppcmake-windows_on_arm.yml + secrets: inherit + with: + NIGHTLY: ${{ github.event_name == 'schedule' || inputs.NIGHTLY == true }} + + release: + if: github.event_name != 'pull_request' + needs: [build-macos, build-ubuntu, build-windows, build-windows_on_arm] + name: Release + runs-on: ubuntu-24.04 + env: + GH_TOKEN: ${{ github.token }} + tag_name: ${{ (github.event_name == 'schedule' || inputs.NIGHTLY == true) && 'nightly' || 'continuous' }} + steps: + - name: Delete existing tag and release + run: gh release delete ${{ env.tag_name }} --cleanup-tag --yes --repo $GITHUB_REPOSITORY + continue-on-error: true + + - run: mkdir -v target + + - name: Download artifacts + uses: actions/download-artifact@v8 + with: + path: target + + - name: Remove unsigned Windows build + run: rm -rfv target/*unsigned* + + - run: find target -type f -exec mv -v {} target \; + + - name: Unarchive Windows's build artifacts + run: for f in target/*.zip; do unzip -d target/ "$f" && rm -v "$f"; done + + - name: Release + uses: softprops/action-gh-release@v2 + with: + files: target/* + prerelease: true + tag_name: ${{ env.tag_name }} diff --git a/.github/workflows/winget.yml b/.github/workflows/winget.yml new file mode 100644 index 000000000..8e4f5b859 --- /dev/null +++ b/.github/workflows/winget.yml @@ -0,0 +1,15 @@ +name: Publish to WinGet + +on: + release: + types: [released] + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: vedantmgoyal9/winget-releaser@main + with: + identifier: DBBrowserForSQLite.DBBrowserForSQLite + installers-regex: '\.msi$' # Only .msi files + token: ${{ secrets.WINGET_TOKEN }} diff --git a/.gitignore b/.gitignore index 60376ad15..87518e350 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ Makefile sqlitebrowser.pro.user +.qmake.stash CMakeLists.txt.user CMakeFiles *.cmake @@ -15,11 +16,13 @@ src/sqlitebrowser src/Makefile* src/debug src/release -src/gen_version.h # ignore compiled translation files src/translations/*.qm +# ignore compiled macOS app +src/*.app/ + # no one needs the txt file src/grammar/sqlite3TokenTypes.txt diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 26d56e53c..000000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: cpp -compiler: - - gcc - - clang - -before_install: - - sudo add-apt-repository ppa:likemartinma/devel -y - - sudo apt-get update -qq - - sudo apt-get install -qq libqt4-dev libsqlite3-dev libsqlcipher-dev libantlr-dev - -script: - - mkdir build - - mkdir build_cipher - - cd build - - cmake -DENABLE_TESTING=ON .. - - make - - ctest -V - - cd ../build_cipher - - cmake -DENABLE_TESTING=ON -Dsqlcipher=1 .. - - make - - ctest -V - -matrix: - fast_finish: true diff --git a/BUILDING.md b/BUILDING.md index 349c77f9c..d8805a9e3 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -1,95 +1,145 @@ ## BUILD INSTRUCTIONS AND REQUIREMENTS -DB Browser for SQLite requires Qt as well as SQLite. For more information on Qt -please consult http://www.qt.io and for SQLite please see https://sqlite.org/. +DB Browser for SQLite requires Qt as well as SQLite.
+For more information on Qt please consult http://www.qt.io and for SQLite please see https://sqlite.org/. + +Please note that all versions after 3.12.1 will require: +* A C++ compiler with support for C++14 or later +* Qt 5.15.9 later + +Without these or with older versions you won't be able to compile DB Browser for +SQLite any more.
This applies to all platforms. However, most likely you won't +have to worry about these as most systems meet these requirements today. + +If you can, please use Qt 5.15.9 or any later version.
Even though Qt +5.5 and 5.6 are supported by us, there might be glitches and minor problems +when using them.
+Also, it is not possible to build universal binary for macOS using Qt versions lower than 5.15.9. + +The wiki has information that is a bit more detailed or less common, but may be useful: https://github.com/sqlitebrowser/sqlitebrowser/wiki + +---- +- [BUILD INSTRUCTIONS AND REQUIREMENTS](#build-instructions-and-requirements) + - [Linux](#linux) + - [Generic Linux and FreeBSD](#generic-linux-and-freebsd) + - [CentOS / Fedora Linux](#centos--fedora-linux) + - [Debian / Ubuntu Linux](#debian--ubuntu-linux) + - [OpenSUSE](#opensuse) + - [macOS](#macos) + - [Build an `.app` bundle](#build-an-app-bundle) + - [Windows](#windows) + - [Compiling on Windows with MSVC](#compiling-on-windows-with-msvc) + - [Cross compiling for Windows](#cross-compiling-for-windows) +- [Build with SQLCipher support](#build-with-sqlcipher-support) +- [Building and running the Unit Tests](#building-and-running-the-unit-tests) + - [Build the unit tests](#build-the-unit-tests) + - [Run the unit tests](#run-the-unit-tests) +---- + +### Linux +#### Generic Linux and FreeBSD + +The only requirements for building this code are the presence of Qt5 and +SQLite 3.
Qt can be included as a static or shared library, depending on the +current Qt configuration on the building machine. -### Generic Linux and FreeBSD +Provided you have Qt and cmake installed and configured, simply run: -The GPL version of Qt is available in almost all Linux distributions as a -default package. + cmake . -The only requirements for building this code are the presence of Qt and -sqlite3. Qt can be included as a static or shared library, depending on the -current Qt configuration on the building machine. +There is one potential problem... several Linux distributions provide a +QScintilla package compiled for (only) Qt4. If it's present it can confuse +CMake, which will use it during compiling. The resulting program just crashes +instead of running. If you experience that kind of crash, try using this +cmake command instead when compiling: -Provided you have Qt and cmake installed and configured, simply run: + cmake -DFORCE_INTERNAL_QSCINTILLA=ON - $ cmake . +That tells cmake to compile QScintilla itself, using the source code version +we bundle. -followed by: +After the cmake line, run this: - $ make + make in the main directory. This will generate the sqlitebrowser (or `sqlitebrowser.exe`, or `sqlitebrowser.app`) application in the src subdirectory. On some distributions you can then install this in the correct places by running: - $ sudo make install + sudo make install The same process works for building the code in any platform supported by Qt (including other Unix systems with X11.) -### Ubuntu Linux +#### CentOS / Fedora Linux + +>**Note** - On CentOS or an older version of Fedora, you may need to use `yum` instead of `dnf`.
+>**Note 2** - On CentOS 7.x, you need to replace the `qwt-qt5-devel` package name with +`qt5-qtbase-devel` in the `dnf install` line.
+>**Note 3** - On CentOS 8 (Stream), you need to replace the `qt-devel` package name with `qt5-devel` in the `dnf install` line below.
+>Make sure the `PowerTools` repo is enabled. For further information: https://access.redhat.com/discussions/5417621 -**1**. Make sure the `build-essential`, `cmake`, `libqt4-dev` and `libsqlite3-dev` - packages are installed.
-**2**. Download the DB Browser for SQLite source code.
-**3**. Open a terminal in the source code directory.
-**4**. Run these commands:
```bash -$ mkdir build -$ cd build -$ cmake .. -$ make -$ sudo make install +sudo dnf install cmake gcc-c++ git qt-devel qt5-linguist qwt-qt5-devel sqlite-devel +git clone https://github.com/sqlitebrowser/sqlitebrowser +cd sqlitebrowser +mkdir build && cd build +cmake .. +make +sudo make install ``` -**5**. This should complete without errors, giving you a binary file called - 'sqlitebrowser'. -Done. :) +This should complete without errors, and `sqlitebrowser` should now be launch-able from the command line. -### CentOS / Fedora Linux +#### Debian / Ubuntu Linux -**1**. Make sure the `qt-devel`, `ant-antlr`, `sqlite-devel`, and `antlr-C++` packages are installed.
-``` -$ sudo dnf install qt-devel ant-antlr sqlite-devel antlr-C++ -``` - -**Note** - If on CentOS or an older version of Fedora, you may need to use `yum` instead of `dnf` - -**2**. Download the DB Browser for SQLite source code.
-**3**. Open a terminal in the source code directory.
-**4**. Run these commands:
```bash -$ cmake . && make && sudo make install +sudo apt install build-essential cmake git libqcustomplot-dev libqt5scintilla2-dev libsqlcipher-dev \ + libsqlite3-dev qt5-qmake qtbase5-dev qtbase5-dev-tools qtchooser qttools5-dev qttools5-dev-tools +git clone https://github.com/sqlitebrowser/sqlitebrowser +cd sqlitebrowser +mkdir build && cd build +cmake .. +make +sudo make install ``` -**5**. This should complete without errors, and `sqlitebrowser` should now be launch-able from the command line. -### MacOS X +>**Note** - Use `cmake -DFORCE_INTERNAL_QSCINTILLA=ON -Dsqlcipher=1 -Wno-dev ..`
+>if you're using Debian and meet errors during compiling. -The application can be compiled to a single executable binary file, similar to -other command line utilities. Or it can be compiled to a .app bundle, suitable -for placing in /Applications. +This should complete without errors, giving you an executable file called `sqlitebrowser`. Done. :) -### Building a single executable binary +> Also, we have a CI workflow for Ubuntu, you can check it out [here](https://github.com/sqlitebrowser/sqlitebrowser/blob/master/.github/workflows/build-ubuntu.yml) -This is incredibly easy using [Homebrew](http://brew.sh). Just run this command: +#### OpenSUSE - $ brew install sqlitebrowser +```bash +zypper in -y build build, cmake, gcc, gcc-c++, git-core, libQt5Core5, libQt5Core5-32bit, libqt5-qtbase, libqt5-qtbase-devel, libqt5-qttools, libqt5-qttools-devel, libsqlite3-0, sqlcipher-devel, sqlite3-devel +git clone https://github.com/sqlitebrowser/sqlitebrowser +cd sqlitebrowser +mkdir build && cd build +cmake -DFORCE_INTERNAL_QSCINTILLA=ON .. +make +sudo make install +``` -And you're done. A "sqlitebrowser" command should now be available in your PATH, -and can also be launched through Spotlight. +### macOS -### Building an .app bundle +#### Build an `.app` bundle +The application can be compiled to an .app bundle, suitable for placing in +/Applications. -Building an .app bundle version takes a bit more effort, but isn't too hard. -It requires SQLite and Qt 4.x/5.x to be installed first. These are the +Building an .app bundle version takes a bit more effort, but isn't too hard.
+It requires SQLite and at least Qt 5.15.9 to be installed first. These are the [Homebrew](http://brew.sh) steps, though other package managers should work: - $ brew install sqlite --with-functions --without-readline - $ brew install qt - $ brew link sqlite3 --force +```bash +brew tap sqlitebrowser/tap +# If you are using Apple Silicon Mac +brew install sqlb-qt@5 sqlb-sqlcipher sqlb-sqlite +``` +> You can don't need SQLCipher support, you can skip `sqlb-sqlcipher`. Then it's just a matter of getting the source: @@ -100,36 +150,31 @@ its name (eg ~/tmp/foo'), as compiling will error out. And compiling it: - $ cd sqlitebrowser - $ qmake - $ make - $ brew unlink sqlite3 - $ mv src/sqlitebrowser.app /Applications/ - -An icon for "sqlitebrowser" should now be in your main OSX Applications -list, ready to launch. - -**Note 2** - There have been occasional [reports of compilation problems on OSX -10.9](https://github.com/sqlitebrowser/sqlitebrowser/issues/38), with the -'make' step complaining about no targets. This seems to be solvable by -running: - - $ qmake -spec macx-g++ +```bash +cd sqlitebrowser +mkdir build && cd build +cmake -DcustomTap=1 .. +cmake --build . +mv DB\ Browser\ for\ SQLite.app /Applications +``` -or: +> If you want to build universal binary, change the `cmake` command to
+> `cmake -DcustomTap=1 -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" ..`
+> Of course, this requires you to have an Apple Silicon Mac. - $ qmake -spec macx-llvm +An icon for "DB Browser for SQLite" should now be in your main macOS Applications list, ready to launch. -(before the 'make' step) +> Also, we have a CI workflow for macOS, you can check it out [here](https://github.com/sqlitebrowser/sqlitebrowser/blob/master/.github/workflows/cppcmake-macos.yml) -### Compiling on Windows with MSVC +### Windows +#### Compiling on Windows with MSVC Complete setup, build, and packaging instructions with MSVC 2013 x64 are online here:     https://github.com/sqlitebrowser/sqlitebrowser/wiki/Setting-up-a-Win64-development-environment-for-DB4S -### Cross compiling for Windows +#### Cross compiling for Windows These are instructions to cross compile within a Linux system a Windows binary and installer. @@ -142,35 +187,37 @@ Requirements: Get the following mxe packages: - $ make gcc sqlite qt nsis + make gcc sqlite qt nsis After successful compilation go into your mxedir/usr/bin and add 3 symlinks: - $ ln -s i686-pc-mingw32-windres windres - $ ln -s i686-pc-mingw32-makensis makensis - $ ln -s /usr/bin/lrelease + ln -s i686-pc-mingw32-windres windres + ln -s i686-pc-mingw32-makensis makensis + ln -s /usr/bin/lrelease Now cd into your sqlitebrowser source directory and create a build directory for the windows binary and create the correct makefiles: - $ mkdir build-win - $ cd build-win - $ cmake -DCMAKE_TOOLCHAIN_FILE=/path to mxe/usr/i686-pc-mingw32/share/cmake/mxe-conf.cmake .. + mkdir build-win + cd build-win + cmake -DCMAKE_TOOLCHAIN_FILE=/path to mxe/usr/i686-pc-mingw32/share/cmake/mxe-conf.cmake .. Before compiling we have to add the mxe/usr/bin directory to the PATH (so windres and makensis can be found): - $ export PATH=/path to mxe/usr/bin:$PATH + export PATH=/path to mxe/usr/bin:$PATH Now compile: - $ make + make + +If you additionally want an NSIS installer: -If you additionaly want an NSIS installer: + make package - $ make package +Done. -done. +> Also, we have a CI workflow for Windows, you can check it out [here](https://github.com/sqlitebrowser/sqlitebrowser/blob/master/.github/workflows/build-windows.yml) ## Build with SQLCipher support @@ -181,19 +228,18 @@ databases. Before compiling make sure you have the necessary SQLCipher development files installed. On Linux this can usually be accomplished by just installing the correct package (e.g. 'libsqlcipher-dev' on Debian-based distributions). On -MacOS X the easiest way is to install it via Homebrew ('brew install +macOS the easiest way is to install it via Homebrew ('brew install sqlcipher'). On Windows unfortunately it's a bit more difficult: You'll have to download and compile the code as described on the [SQLCipher website](https://www.zetetic.net/sqlcipher/) before you can proceed. If SQLCipher is installed, simply follow the standard instructions for your platform but enable the 'sqlcipher' build option by replacing any calls to -cmake and qmake like this: +cmake like this: ``` If it says... Change it to... cmake cmake -Dsqlcipher=1 cmake .. cmake -Dsqlcipher=1 .. -qmake qmake CONFIG+=sqlcipher ``` ## Building and running the Unit Tests @@ -202,15 +248,14 @@ DB Browser for SQLite has unit tests in the "src/tests" subdirectory. ### Build the unit tests -The unit tests are enabled using the cmake variable `ENABLE_TESTING`; +The unit tests are enabled using the cmake variable `ENABLE_TESTING`
it can be passed when running `cmake` to configure sqlitebrowser, for example like this: ```bash -$ mkdir build -$ cd build -$ cmake -DENABLE_TESTING=ON .. -$ make +mkdir build && cd build +cmake -DENABLE_TESTING=ON .. +make ``` ### Run the unit tests diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..6ea8f53ae --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +# CHANGELOG for DB4S + +For changes in the current codebase, see the following wiki page: +> https://github.com/sqlitebrowser/sqlitebrowser/wiki/CHANGELOG diff --git a/CMakeLists.txt b/CMakeLists.txt index 742f2b85c..1a17f534a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,385 +1,307 @@ -project(sqlitebrowser) -cmake_minimum_required(VERSION 2.8.7) +cmake_minimum_required(VERSION 3.16) -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}") - -OPTION(USE_QT5 FALSE "Build with qt5") -OPTION(ENABLE_TESTING FALSE "Enable the unit tests") +project(sqlitebrowser + VERSION 3.13.99 + DESCRIPTION "GUI editor for SQLite databases" + LANGUAGES CXX +) -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release") -endif() +include(GNUInstallDirs) -if(WIN32 AND MSVC) - if(CMAKE_CL_64) - set(SQLITE3_PATH "C:/dev/SQLite") - set(QT5_PATH "C:/dev/Qt/5.6/msvc2013_64") - set(OPENSSL_PATH "C:/dev/OpenSSL-Win64") - set(VSREDIST "vcredist_x64.exe") - else() - set(QT5_PATH "E:/Qt/Qt5.5.1/5.5/msvc2013") - set(SQLITE3_PATH "E:/libs/sqlite3") - set(OPENSSL_PATH "E:/libs/openssl-1.0.2a-i386-win32") - set(VSREDIST "vcredist_x86.exe") - endif() - set(USE_QT5 TRUE) - set(CMAKE_PREFIX_PATH "${QT5_PATH};${SQLITE3_PATH}") -endif() +include(config/options.cmake) -find_package(Antlr2) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) +add_executable(${PROJECT_NAME}) -set(QHEXEDIT_DIR libs/qhexedit) -set(QCUSTOMPLOT_DIR libs/qcustomplot-source) -set(QSCINTILLA_DIR libs/qscintilla/Qt4Qt5) -if(NOT ANTLR2_FOUND) - set(ANTLR_DIR libs/antlr-2.7.7) - add_subdirectory(${ANTLR_DIR}) -endif() -add_subdirectory(${QHEXEDIT_DIR}) -add_subdirectory(${QCUSTOMPLOT_DIR}) -add_subdirectory(${QSCINTILLA_DIR}) - -if(USE_QT5) - find_package(Qt5Widgets REQUIRED) - find_package(Qt5LinguistTools REQUIRED) - set(CMAKE_AUTOMOC ON) - set(CMAKE_INCLUDE_CURRENT_DIR ON) +if(QT_MAJOR STREQUAL "Qt5") + set(CMAKE_CXX_STANDARD 14) +elseif(QT_MAJOR STREQUAL "Qt6") + set(CMAKE_CXX_STANDARD 17) else() - find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED) - include("${QT_USE_FILE}") - add_definitions(${QT_DEFINITIONS}) + message(FATAL_ERROR "Uknown Qt Version: ${QT_MAJOR}") endif() -if(ENABLE_TESTING) - enable_testing() +set(CMAKE_CXX_STANDARD_REQUIRED True) + +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}") + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release") endif() -set(SQLB_HDR - src/version.h - src/sqlitetypes.h - src/csvparser.h - src/sqlite.h - src/grammar/sqlite3TokenTypes.hpp - src/grammar/Sqlite3Lexer.hpp - src/grammar/Sqlite3Parser.hpp +set_target_properties(${PROJECT_NAME} PROPERTIES + WIN32_EXECUTABLE ON + MACOSX_BUNDLE ON ) -set(SQLB_MOC_HDR - src/sqlitedb.h - src/AboutDialog.h - src/CreateIndexDialog.h - src/EditDialog.h - src/EditTableDialog.h - src/ExportCsvDialog.h - src/ExtendedTableWidget.h - src/FilterTableHeader.h - src/ImportCsvDialog.h - src/MainWindow.h - src/PreferencesDialog.h - src/SqlExecutionArea.h - src/VacuumDialog.h - src/sqlitetablemodel.h - src/sqltextedit.h - src/DbStructureModel.h - src/Application.h - src/CipherDialog.h - src/ExportSqlDialog.h - src/SqlUiLexer.h - src/FileDialog.h - src/ColumnDisplayFormatDialog.h - src/FilterLineEdit.h +execute_process( + COMMAND git -C ${CMAKE_CURRENT_SOURCE_DIR} rev-parse --short --verify HEAD + OUTPUT_VARIABLE GIT_COMMIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET ) -set(SQLB_SRC - src/AboutDialog.cpp - src/CreateIndexDialog.cpp - src/EditDialog.cpp - src/EditTableDialog.cpp - src/ExportCsvDialog.cpp - src/ExtendedTableWidget.cpp - src/FilterTableHeader.cpp - src/ImportCsvDialog.cpp - src/MainWindow.cpp - src/PreferencesDialog.cpp - src/SqlExecutionArea.cpp - src/VacuumDialog.cpp - src/sqlitedb.cpp - src/sqlitetablemodel.cpp - src/sqlitetypes.cpp - src/sqltextedit.cpp - src/csvparser.cpp - src/DbStructureModel.cpp - src/grammar/Sqlite3Lexer.cpp - src/grammar/Sqlite3Parser.cpp - src/main.cpp - src/Application.cpp - src/CipherDialog.cpp - src/ExportSqlDialog.cpp - src/SqlUiLexer.cpp - src/FileDialog.cpp - src/ColumnDisplayFormatDialog.cpp - src/FilterLineEdit.cpp +if (GIT_COMMIT_HASH STREQUAL "") + MESSAGE(WARNING "Could not determine git commit hash") + set(GIT_COMMIT_HASH "Unknown") +endif() + +add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}") +if(NOT BUILD_STABLE_VERSION) + # BUILD_VERSION is the current date in YYYYMMDD format. It is only + # used by the nightly version to add the date of the build. + # Default defined in Version.h.in + string(TIMESTAMP BUILD_VERSION "%Y%m%d") + target_compile_definitions(${PROJECT_NAME} PRIVATE BUILD_VERSION=${BUILD_VERSION}) +endif() + +include(config/platform.cmake) + +find_package(${QT_MAJOR} REQUIRED COMPONENTS Concurrent Gui LinguistTools Network PrintSupport Test Widgets Xml) +set(QT_LIBS + ${QT_MAJOR}::Gui + ${QT_MAJOR}::Test + ${QT_MAJOR}::PrintSupport + ${QT_MAJOR}::Widgets + ${QT_MAJOR}::Network + ${QT_MAJOR}::Concurrent + ${QT_MAJOR}::Xml ) +if(QT_MAJOR STREQUAL "Qt6") + find_package(Qt6 REQUIRED COMPONENTS Core5Compat) + list(APPEND QT_LIBS Qt6::Core5Compat) + set_target_properties(${PROJECT_NAME} PROPERTIES + AUTOUIC_OPTIONS "--connections=string" + ) +endif() + +target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE ${CMAKE_CURRENT_LIST_DIR}/libs/json) +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} src) + +include(config/3dparty.cmake) + +# SQLCipher option +if(sqlcipher) + add_definitions(-DENABLE_SQLCIPHER) + find_package(SQLCipher REQUIRED) + include_directories(SYSTEM "${SQLCIPHER_INCLUDE_DIR}/sqlcipher") + set(LIBSQLITE_NAME SQLCipher::SQLCipher) +else() + find_package(SQLite3 REQUIRED) + set(LIBSQLITE_NAME SQLite::SQLite3) +endif() -set(SQLB_FORMS - src/AboutDialog.ui - src/CreateIndexDialog.ui - src/EditDialog.ui - src/EditTableDialog.ui - src/ExportCsvDialog.ui - src/ImportCsvDialog.ui - src/MainWindow.ui - src/PreferencesDialog.ui - src/SqlExecutionArea.ui - src/VacuumDialog.ui - src/CipherDialog.ui - src/ExportSqlDialog.ui - src/ColumnDisplayFormatDialog.ui +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/version.h.in + ${CMAKE_CURRENT_BINARY_DIR}/version.h ) -set(SQLB_RESOURCES - src/icons/icons.qrc - src/translations/flags/flags.qrc - src/translations/translations.qrc +target_sources(${PROJECT_NAME} + PRIVATE + src/sql/sqlitetypes.h + src/sql/Query.h + src/sql/ObjectIdentifier.h + src/csvparser.h + src/sqlite.h + src/Data.h + src/IconCache.h + src/sql/parser/ParserDriver.h + src/sql/parser/sqlite3_lexer.h + src/sql/parser/sqlite3_location.h + src/sql/parser/sqlite3_parser.hpp ) -set(SQLB_MISC - src/grammar/sqlite3.g +target_sources(${PROJECT_NAME} + PRIVATE + src/sqlitedb.h + src/AboutDialog.h + src/EditIndexDialog.h + src/EditDialog.h + src/EditTableDialog.h + src/AddRecordDialog.h + src/ExportDataDialog.h + src/ExtendedTableWidget.h + src/FilterTableHeader.h + src/ImportCsvDialog.h + src/MainWindow.h + src/Settings.h + src/PreferencesDialog.h + src/SqlExecutionArea.h + src/VacuumDialog.h + src/sqlitetablemodel.h + src/RowLoader.h + src/RowCache.h + src/sqltextedit.h + src/docktextedit.h + src/DbStructureModel.h + src/dbstructureqitemviewfacade.h + src/Application.h + src/CipherDialog.h + src/ExportSqlDialog.h + src/SqlUiLexer.h + src/FileDialog.h + src/ColumnDisplayFormatDialog.h + src/FilterLineEdit.h + src/ForeignKeyEditorDelegate.h + src/PlotDock.h + src/FindReplaceDialog.h + src/ExtendedScintilla.h + src/FileExtensionManager.h + src/CondFormatManager.h + src/CipherSettings.h + src/Palette.h + src/CondFormat.h + src/RunSql.h + src/ProxyDialog.h + src/SelectItemsPopup.h + src/TableBrowser.h + src/ImageViewer.h + src/RemoteNetwork.h + src/TableBrowserDock.h ) -# Translation files -set(SQLB_TSS - "${CMAKE_SOURCE_DIR}/src/translations/sqlb_zh.ts" - "${CMAKE_SOURCE_DIR}/src/translations/sqlb_zh_TW.ts" - "${CMAKE_SOURCE_DIR}/src/translations/sqlb_de.ts" - "${CMAKE_SOURCE_DIR}/src/translations/sqlb_es_ES.ts" - "${CMAKE_SOURCE_DIR}/src/translations/sqlb_fr.ts" - "${CMAKE_SOURCE_DIR}/src/translations/sqlb_ru.ts" - "${CMAKE_SOURCE_DIR}/src/translations/sqlb_pt_BR.ts" - "${CMAKE_SOURCE_DIR}/src/translations/sqlb_en_GB.ts" - "${CMAKE_SOURCE_DIR}/src/translations/sqlb_ko_KR.ts" - "${CMAKE_SOURCE_DIR}/src/translations/sqlb_tr.ts" +target_sources(${PROJECT_NAME} + PRIVATE + src/AboutDialog.cpp + src/EditIndexDialog.cpp + src/EditDialog.cpp + src/EditTableDialog.cpp + src/AddRecordDialog.cpp + src/ExportDataDialog.cpp + src/ExtendedTableWidget.cpp + src/FilterTableHeader.cpp + src/ImportCsvDialog.cpp + src/MainWindow.cpp + src/Settings.cpp + src/PreferencesDialog.cpp + src/SqlExecutionArea.cpp + src/VacuumDialog.cpp + src/sqlitedb.cpp + src/sqlitetablemodel.cpp + src/RowLoader.cpp + src/sql/sqlitetypes.cpp + src/sql/Query.cpp + src/sql/ObjectIdentifier.cpp + src/sqltextedit.cpp + src/docktextedit.cpp + src/csvparser.cpp + src/DbStructureModel.cpp + src/dbstructureqitemviewfacade.cpp + src/main.cpp + src/Application.cpp + src/CipherDialog.cpp + src/ExportSqlDialog.cpp + src/SqlUiLexer.cpp + src/FileDialog.cpp + src/ColumnDisplayFormatDialog.cpp + src/FilterLineEdit.cpp + src/ForeignKeyEditorDelegate.cpp + src/PlotDock.cpp + src/FindReplaceDialog.cpp + src/ExtendedScintilla.cpp + src/FileExtensionManager.cpp + src/CondFormatManager.cpp + src/Data.cpp + src/CipherSettings.cpp + src/Palette.cpp + src/CondFormat.cpp + src/RunSql.cpp + src/ProxyDialog.cpp + src/IconCache.cpp + src/SelectItemsPopup.cpp + src/TableBrowser.cpp + src/sql/parser/ParserDriver.cpp + src/sql/parser/sqlite3_lexer.cpp + src/sql/parser/sqlite3_parser.cpp + src/ImageViewer.cpp + src/RemoteNetwork.cpp + src/TableBrowserDock.cpp ) -if(USE_QT5) - qt5_wrap_ui(SQLB_FORM_HDR ${SQLB_FORMS}) - if(SQLB_TSS) - # add translations - foreach(SQLB_TS ${SQLB_TSS}) - SET_SOURCE_FILES_PROPERTIES("${SQLB_TS}" PROPERTIES OUTPUT_LOCATION "${CMAKE_SOURCE_DIR}/src/translations") - endforeach(SQLB_TS ${SQLB_TSS}) - qt5_add_translation(SQLB_QMS ${SQLB_TSS}) - endif(SQLB_TSS) - qt5_add_resources(SQLB_RESOURCES_RCC ${SQLB_RESOURCES}) -else() - QT4_WRAP_CPP(SQLB_MOC ${SQLB_MOC_HDR}) - QT4_WRAP_UI(SQLB_FORM_HDR ${SQLB_FORMS}) - if(SQLB_TSS) - # add translations - foreach(SQLB_TS ${SQLB_TSS}) - SET_SOURCE_FILES_PROPERTIES("${SQLB_TS}" PROPERTIES OUTPUT_LOCATION "${CMAKE_SOURCE_DIR}/src/translations") - endforeach(SQLB_TS ${SQLB_TSS}) - QT4_ADD_TRANSLATION(SQLB_QMS ${SQLB_TSS}) - endif(SQLB_TSS) - QT4_ADD_RESOURCES(SQLB_RESOURCES_RCC ${SQLB_RESOURCES}) -endif() +source_group("Qt UI" "src/.*\.ui$") +target_sources(${PROJECT_NAME} + PRIVATE + src/AboutDialog.ui + src/EditIndexDialog.ui + src/EditDialog.ui + src/EditTableDialog.ui + src/AddRecordDialog.ui + src/ExportDataDialog.ui + src/ImportCsvDialog.ui + src/MainWindow.ui + src/PreferencesDialog.ui + src/SqlExecutionArea.ui + src/VacuumDialog.ui + src/CipherDialog.ui + src/ExportSqlDialog.ui + src/ColumnDisplayFormatDialog.ui + src/PlotDock.ui + src/FindReplaceDialog.ui + src/FileExtensionManager.ui + src/CondFormatManager.ui + src/ProxyDialog.ui + src/SelectItemsPopup.ui + src/TableBrowser.ui + src/ImageViewer.ui +) +include(config/translations.cmake) -#icon and correct libs/subsystem for windows -if(WIN32) - #enable version check for windows - add_definitions(-DCHECKNEWVERSION) - - IF( MINGW ) - # resource compilation for MinGW - ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/sqlbicon.o" - COMMAND windres "-I${CMAKE_CURRENT_SOURCE_DIR}" "-i${CMAKE_CURRENT_SOURCE_DIR}/src/winapp.rc" -o "${CMAKE_CURRENT_BINARY_DIR}/sqlbicon.o" VERBATIM) - set(SQLB_SRC ${SQLB_SRC} "${CMAKE_CURRENT_BINARY_DIR}/sqlbicon.o") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-subsystem,windows") - set(WIN32_STATIC_LINK -Wl,-Bstatic -lssl -lcrypto -lws2_32) - set(ADDITIONAL_LIBS lzma) - ELSE( MINGW ) - set(SQLB_SRC ${SQLB_SRC} "${CMAKE_CURRENT_SOURCE_DIR}/src/winapp.rc") - ENDIF( MINGW ) -endif(WIN32) - -#enable version check for MacOS -if(APPLE) - add_definitions(-DCHECKNEWVERSION) -endif(APPLE) +source_group("Qt Resources" "src/.*\.qrc$") +target_sources(${PROJECT_NAME} + PRIVATE -# SQLCipher option -if(sqlcipher) - add_definitions(-DENABLE_SQLCIPHER) - set(LIBSQLITE_NAME sqlcipher) -else(sqlcipher) - set(LIBSQLITE_NAME sqlite3) -endif(sqlcipher) - -# add extra library path for MacOS and FreeBSD -set(EXTRAPATH APPLE OR ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") -if(EXTRAPATH) - find_library(LIBSQLITE ${LIBSQLITE_NAME} HINTS /usr/local/lib /usr/local/opt/sqlite/lib) - set(ADDITIONAL_INCLUDE_PATHS /usr/local/include /usr/local/opt/sqlite/include) -else(EXTRAPATH) - find_library(LIBSQLITE ${LIBSQLITE_NAME}) -endif(EXTRAPATH) - -if(WIN32 AND MSVC) - find_path(SQLITE3_INCLUDE_DIR sqlite3.h) - find_file(SQLITE3_DLL sqlite3.dll) - include_directories(${SQLITE3_INCLUDE_DIR}) -endif() + # General + src/sql/parser/sqlite3_parser.yy + src/sql/parser/sqlite3_lexer.ll -include_directories( - "${CMAKE_CURRENT_BINARY_DIR}" - ${QHEXEDIT_DIR} - ${QCUSTOMPLOT_DIR} - ${QSCINTILLA_DIR} - ${ADDITIONAL_INCLUDE_PATHS} - src) -if(ANTLR2_FOUND) - include_directories(${ANTLR2_INCLUDE_DIRS}) -else() - include_directories(${ANTLR_DIR}) -endif() + # Graphics + src/icons/icons.qrc -add_executable(${PROJECT_NAME} - ${SQLB_HDR} - ${SQLB_SRC} - ${SQLB_FORM_HDR} - ${SQLB_MOC} - ${SQLB_RESOURCES_RCC} - ${SQLB_MISC}) - -if(USE_QT5) - qt5_use_modules(${PROJECT_NAME} Gui Widgets Network Test PrintSupport) - set(QT_LIBRARIES "") -endif() -add_dependencies(${PROJECT_NAME} qhexedit qcustomplot qscintilla2) -if(NOT ANTLR2_FOUND) - add_dependencies(${PROJECT_NAME} antlr) -endif() + # Translations + src/translations/flags/flags.qrc + src/translations/translations.qrc -link_directories( - "${CMAKE_CURRENT_BINARY_DIR}/${ANTLR_DIR}" - "${CMAKE_CURRENT_BINARY_DIR}/${QHEXEDIT_DIR}" - "${CMAKE_CURRENT_BINARY_DIR}/${QCUSTOMPLOT_DIR}" - "${CMAKE_CURRENT_BINARY_DIR}/${QSCINTILLA_DIR}") -if(NOT ANTLR2_FOUND) - link_directories("${CMAKE_CURRENT_BINARY_DIR}/${ANTLR_DIR}") -endif() + # Styles + src/qdarkstyle/dark/darkstyle.qrc + src/qdarkstyle/light/lightstyle.qrc +) target_link_libraries(${PROJECT_NAME} - qhexedit - qcustomplot - qscintilla2 - ${QT_LIBRARIES} - ${WIN32_STATIC_LINK} - ${LIBSQLITE} - ${ADDITIONAL_LIBS}) -if(ANTLR2_FOUND) - target_link_libraries(${PROJECT_NAME} ${ANTLR2_LIBRARIES}) -else() - target_link_libraries(${PROJECT_NAME} antlr) -endif() - -if(WIN32 AND MSVC) - set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE") - set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE") - set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE") - set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_DEFINITIONS_RELWITHDEBINFO "_CONSOLE") - set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup") - set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS") - set(CMAKE_GENERATOR_TOOLSET "v120_xp" CACHE STRING "Platform Toolset" FORCE) -endif() + PRIVATE + ${QT_LIBS} + QHexEdit::QHexEdit QCustomPlot::QCustomPlot QScintilla::QScintilla + ${LIBSQLITE_NAME} + ${PLATFORM_LIBS} +) -install(TARGETS ${PROJECT_NAME} - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib) - +include(config/install.cmake) if(ENABLE_TESTING) - add_subdirectory(src/tests) + enable_testing() + add_subdirectory(src/tests) endif() -if(UNIX AND NOT APPLE) - install(FILES src/icons/${PROJECT_NAME}.png - DESTINATION share/icons/hicolor/256x256/apps/) - - install(FILES distri/${PROJECT_NAME}.desktop - DESTINATION share/applications/) - - install(FILES distri/${PROJECT_NAME}.desktop.appdata.xml - DESTINATION share/appdata/) -endif(UNIX AND NOT APPLE) - -if(WIN32 AND MSVC) - set(QT5_BIN_PATH ${QT5_PATH}/bin) - # The Qt5 Debug configuration library files have a 'd' postfix - install(FILES - ${QT5_BIN_PATH}/Qt5Cored.dll - ${QT5_BIN_PATH}/Qt5Guid.dll - ${QT5_BIN_PATH}/Qt5Networkd.dll - ${QT5_BIN_PATH}/Qt5PrintSupportd.dll - ${QT5_BIN_PATH}/Qt5Widgetsd.dll - DESTINATION bin - CONFIGURATIONS Debug) - # The Qt5 Release configuration files don't have a postfix - install(FILES - ${QT5_BIN_PATH}/Qt5Core.dll - ${QT5_BIN_PATH}/Qt5Gui.dll - ${QT5_BIN_PATH}/Qt5Network.dll - ${QT5_BIN_PATH}/Qt5PrintSupport.dll - ${QT5_BIN_PATH}/Qt5Widgets.dll - DESTINATION bin - CONFIGURATIONS Release) - # The files below are common to all configurations - install(FILES - ${QT5_BIN_PATH}/icudt54.dll - ${QT5_BIN_PATH}/icuin54.dll - ${QT5_BIN_PATH}/icuuc54.dll - ${SQLITE3_DLL} - ${OPENSSL_PATH}/libeay32.dll - ${OPENSSL_PATH}/ssleay32.dll - DESTINATION bin) - install(FILES - ${QT5_PATH}/plugins/platforms/qwindows.dll - DESTINATION bin/platforms) - install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/deps/${VSREDIST} DESTINATION tmp) +# CPack configuration +set(CPACK_STRIP_FILES ON) +set(CPACK_DEBIAN_PACKAGE_PRIORITY optional) +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) +set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) +set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Tristan Stenner ") +set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) +if(APPLE) + set(CPACK_DEFAULT_GEN TBZ2) +elseif(WIN32) + set(CPACK_DEFAULT_GEN ZIP) + set(CPACK_NSIS_MODIFY_PATH ON) + set(CPACK_WIX_CMAKE_PACKAGE_REGISTRY ON) + set(CPACK_WIX_UPGRADE_GUID "78c885a7-e9c8-4ded-9b62-9abe47466950") +elseif(UNIX) + set(CPACK_DEFAULT_GEN DEB) + set(CPACK_SET_DESTDIR 1) + set(CPACK_INSTALL_PREFIX "/usr") endif() - -#cpack -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "DB Browser for SQLite") -set(CPACK_PACKAGE_VENDOR "oldsch00l") -set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md") -set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") -set(CPACK_PACKAGE_VERSION_MAJOR "3") -set(CPACK_PACKAGE_VERSION_MINOR "8") -set(CPACK_PACKAGE_VERSION_PATCH "0") -set(CPACK_PACKAGE_INSTALL_DIRECTORY "SqliteBrowser${CPACK_PACKAGE_VERSION_MAJOR}") -if(WIN32 AND NOT UNIX) - # There is a bug in NSI that does not handle full unix paths properly. Make - # sure there is at least one set of four (4) backlasshes. - set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\src\\\\iconwin.ico") - set(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\sqlitebrowser.exe") - set(CPACK_NSIS_DISPLAY_NAME "DB Browser for SQLite") - set(CPACK_NSIS_HELP_LINK "https:\\\\\\\\github.com\\\\sqlitebrowser\\\\sqlitebrowser") - set(CPACK_NSIS_URL_INFO_ABOUT "https:\\\\\\\\github.com\\\\sqlitebrowser\\\\sqlitebrowser") - set(CPACK_NSIS_CONTACT "peinthor@gmail.com") - set(CPACK_NSIS_MODIFY_PATH OFF) - set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) - set(CPACK_NSIS_MUI_FINISHPAGE_RUN "sqlitebrowser.exe") - - # VS redist - list(APPEND CPACK_NSIS_EXTRA_INSTALL_COMMANDS " - ExecWait '$INSTDIR\\\\tmp\\\\${VSREDIST} /install /passive /quiet' - Delete '$INSTDIR\\\\tmp\\\\${VSREDIST}' - ") -else(WIN32 AND NOT UNIX) - set(CPACK_STRIP_FILES "bin/sqlitebrowser") - set(CPACK_SOURCE_STRIP_FILES "") -endif(WIN32 AND NOT UNIX) -set(CPACK_PACKAGE_EXECUTABLES "sqlitebrowser" "SqliteBrowser") +set(CPACK_GENERATOR ${CPACK_DEFAULT_GEN} CACHE STRING "CPack pkg type(s) to generate") include(CPack) diff --git a/LICENSE b/LICENSE index b6a53db33..da2fad5a2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,1058 +1,9 @@ DB Browser for SQLite is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. -You can modify or redistribute it under the conditions of these -licenses. +Modification or redistribution is permitted under the conditions of these licenses. ------------------------------------------------------------------------ - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. - ------------------------------------------------------------------------ - -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. +Check `LICENSE-GPL-3.0` for the full text of the GNU General Public License Version 3. +Check `LICENSE-MPL-2.0` for the full text of the Mozilla Public License Version 2. +Check `LICENSE-MIT` for the full text of the MIT License. and that is the license for the `nalgeon/sqlean` library. +Check `LICENSE-PLUGINS` for other rights regarding included third-party resources. diff --git a/LICENSE-GPL-3.0 b/LICENSE-GPL-3.0 new file mode 100644 index 000000000..94a9ed024 --- /dev/null +++ b/LICENSE-GPL-3.0 @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 000000000..a386b83d0 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021+ Anton Zhiyanov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSE-MPL-2.0 b/LICENSE-MPL-2.0 new file mode 100644 index 000000000..a612ad981 --- /dev/null +++ b/LICENSE-MPL-2.0 @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/LICENSE-PLUGINS b/LICENSE-PLUGINS new file mode 100644 index 000000000..c95f12893 --- /dev/null +++ b/LICENSE-PLUGINS @@ -0,0 +1,78 @@ +DB Browser for SQLite includes support for TIFF and WebP images. The +support for these comes from the LibTIFF and WebP projects, which have +their own (Open Source) licenses, different to ours. + +LibTIFF - http://www.simplesystems.org/libtiff/ + + Copyright (c) 1988-1997 Sam Leffler + Copyright (c) 1991-1997 Silicon Graphics, Inc. + + Permission to use, copy, modify, distribute, and sell this software and + its documentation for any purpose is hereby granted without fee, provided + that (i) the above copyright notices and this permission notice appear in + all copies of the software and related documentation, and (ii) the names of + Sam Leffler and Silicon Graphics may not be used in any advertising or + publicity relating to the software without the specific, prior written + permission of Sam Leffler and Silicon Graphics. + + THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + OF THIS SOFTWARE. + +WebP - https://developers.google.com/speed/webp/ + + Copyright (c) 2010, Google Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * 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. + + * Neither the name of Google 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 COPYRIGHT HOLDERS AND CONTRIBUTORS + "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 COPYRIGHT + HOLDER OR CONTRIBUTORS 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. + +Icons - https://codefisher.org/pastel-svg/ + +Most of the icons come from the Pastel SVG icon set created by Michael +Buckley. We have obtained a special license (Creative Commons +Attribution Share Alike 4.0 +http://creativecommons.org/licenses/by-sa/4.0/) but you might be +required to redistribute it under Creative Commons Attribution +NonCommercial Share Alike 4.0 +http://creativecommons.org/licenses/by-nc-sa/4.0/ +Check https://codefisher.org/pastel-svg/ for clarification. + +The construction emoji for the icon used in the nightly version come +from the OpenMoji under CC BY-SA 4.0 license. +Check https://openmoji.org/library/emoji-1F6A7/ and +https://openmoji.org/faq/ for clarification. + +Some icons might have other open licenses, check history of the files +under `src/icons`. \ No newline at end of file diff --git a/MAINTAINERS.md b/MAINTAINERS.md new file mode 100644 index 000000000..e6b170b12 --- /dev/null +++ b/MAINTAINERS.md @@ -0,0 +1,5 @@ +Current Maintainers: + - You can check the list of maintainers at: https://github.com/orgs/sqlitebrowser/people + +Release Manager: + - SeongTae Jeong seongtaejg@sqlitebrowser.org 17ABC291B166F699409851AA9503B162E0416CE3 diff --git a/README.md b/README.md index 0c1b3924a..0b327abb6 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,173 @@ # DB Browser for SQLite -[![Build Status](https://travis-ci.org/sqlitebrowser/sqlitebrowser.svg?branch=master)](https://travis-ci.org/sqlitebrowser/sqlitebrowser) +[![Join the chat at https://gitter.im/sqlitebrowser/sqlitebrowser][gitter-img]][gitter] +[![Wiki][wiki-img]][wiki] +[![Patreon][patreon-img]][patreon]
+[![C/C++ CI][ghaction-img]][ghaction] +[![Qt][qt-img]][qt]
+[![CodeQL](https://github.com/sqlitebrowser/sqlitebrowser/actions/workflows/codeql.yml/badge.svg)](https://github.com/sqlitebrowser/sqlitebrowser/actions/workflows/codeql.yml) +[![Coverity][coverity-img]][coverity]
+[![Download][download-img]][download] +[![snapcraft](https://snapcraft.io/sqlitebrowser/badge.svg)](https://snapcraft.io/sqlitebrowser) +[![snapcraft](https://snapcraft.io/sqlitebrowser/trending.svg?name=0)](https://snapcraft.io/sqlitebrowser) ![DB Browser for SQLite Screenshot](https://github.com/sqlitebrowser/sqlitebrowser/raw/master/images/sqlitebrowser.png "DB Browser for SQLite Screenshot") +## Table of Contents +- [DB Browser for SQLite](#db-browser-for-sqlite) + - [Table of Contents](#table-of-contents) + - [What it is](#what-it-is) + - [What it is not](#what-it-is-not) + - [Wiki](#wiki) + - [Continuous, Nightly builds](#continuous-nightly-builds) + - [Windows](#windows) + - [Continuous, Nightly builds](#continuous-nightly-builds-1) + - [macOS](#macos) + - [Stable release](#stable-release) + - [Continuous, Nightly builds](#continuous-nightly-builds-2) + - [Linux](#linux) + - [Arch Linux](#arch-linux) + - [Debian](#debian) + - [Fedora](#fedora) + - [openSUSE](#opensuse) + - [Ubuntu and Derivatives](#ubuntu-and-derivatives) + - [Stable release](#stable-release-1) + - [Nightly builds](#nightly-builds) + - [Other Linux](#other-linux) + - [FreeBSD](#freebsd) + - [Snap packages](#snap-packages) + - [Snap Nightlies](#snap-nightlies) + - [Snap Stable](#snap-stable) + - [Nix Packages](#nix-packages) + - [Flox](#flox) + - [Compiling](#compiling) + - [X (Known as Twitter)](#x-known-as-twitter) + - [Website](#website) + - [Old project page](#old-project-page) + - [Releases](#releases) + - [History](#history) + - [Contributors](#contributors) + - [License](#license) + ## What it is -DB Browser for SQLite is a high quality, visual, open source tool to +_DB Browser for SQLite_ (DB4S) is a high quality, visual, open source tool to create, design, and edit database files compatible with SQLite. -It is for users and developers wanting to create databases, search, and edit -data. It uses a familiar spreadsheet-like interface, and you don't need to -learn complicated SQL commands. +DB4S is for users and developers who want to create, search, and edit +databases. DB4S uses a familiar spreadsheet-like interface, so complicated SQL commands do not have to be learned. Controls and wizards are available for users to: * Create and compact database files * Create, define, modify and delete tables -* Create, define and delete indexes -* Browse, edit, add and delete records +* Create, define, and delete indexes +* Browse, edit, add, and delete records * Search records * Import and export records as text * Import and export tables from/to CSV files * Import and export databases from/to SQL dump files * Issue SQL queries and inspect the results * Examine a log of all SQL commands issued by the application +* Plot simple graphs based on table or query data ## What it is not -This program is not a visual shell for the sqlite command line tool. It does -not require familiarity with SQL commands. It is a tool to be used both by -developers and by end users, and it must remain as simple to use as possible -in order to achieve its goals. +Even though DB4S comes with a spreadsheet-like interface, it is not meant to replace your spreadsheet application. +We implement a few convenience functions which go beyond a simple database frontend but do not add them when they +do not make sense in a database context or are so complex to implement that they will only ever be a poor +replacement for your favorite spreadsheet application. We are a small team with limited time after all. Thanks +for your understanding :) + +## Wiki + +For user and developer documentation, check out our Wiki at: +https://github.com/sqlitebrowser/sqlitebrowser/wiki. + +## Continuous, Nightly builds + +Download continuous builds for AppImage, macOS and Windows here: + +* https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/continuous +> Note: A continuous build is generated when a new commit is added to the `master` branch.
+ +Download nightly builds for Windows and macOS here: + +* https://nightlies.sqlitebrowser.org/latest ## Windows -Windows binaries can be downloaded from here: +Download Windows releases here: + +* https://sqlitebrowser.org/dl/#windows -* https://github.com/sqlitebrowser/sqlitebrowser/releases +Or use Chocolatey: -Nightly builds (uncompress them with [7-Zip](http://www.7-zip.org)) are -available at: +``` +choco install sqlitebrowser +``` -* http://rp.oldsch00l.com/sqlitebrowser/ +Or use winget: -**Note** - If for some reason the standard Windows release doesn't work for -you (eg it gives an error), try the nightly build. It's made using a -different process, and is often a good fallback. :D +``` +winget install -e --id DBBrowserForSQLite.DBBrowserForSQLite +``` -## MacOS X +Or use scoop: +``` +scoop install sqlitebrowser +``` + +#### Continuous, Nightly builds -DB Browser for SQLite works well on MacOS X. +Continuous builds are available here: -* OSX 10.7 (Lion) - 10.11 (El Capitan) are tested and known to work +* https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/continuous + +Nightly builds are available here: +* https://nightlies.sqlitebrowser.org/latest -OSX binaries can be downloaded from here: +## macOS -* https://github.com/sqlitebrowser/sqlitebrowser/releases +DB Browser for SQLite works well on macOS. -Latest OSX binary can be installed via [Homebrew](http://brew.sh/ "Homebrew"): +* macOS 10.15 (Catalina) - 14.0 (Sonoma) are tested and known to work. + +#### Stable release + +Download macOS releases here: + +* https://sqlitebrowser.org/dl/#macos + +The latest macOS binary can be installed via [Homebrew Cask](https://caskroom.github.io/ "Homebrew Cask"): ``` -brew cask install sqlitebrowser +brew install --cask db-browser-for-sqlite ``` -Nightly builds for OSX are available at: +#### Continuous, Nightly builds + +Continuous builds are available here: + +* https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/continuous + +Nightly builds are available here: +* https://nightlies.sqlitebrowser.org/latest -* http://nightlies.sqlitebrowser.org/osx/ +and also you can be installed via [Homebrew Cask](https://caskroom.github.io/ "Homebrew Cask"): + +``` +brew tap homebrew/cask-versions + +# for the version without SQLCipher support +brew install --cask db-browser-for-sqlite-nightly + +# for the version with SQLCipher support +brew install --cask db-browser-for-sqlcipher-nightly +``` + +It also has its own Homebrew tap the include Cask for older version.
+For more information, see the following: https://github.com/sqlitebrowser/homebrew-tap ## Linux @@ -74,25 +175,45 @@ DB Browser for SQLite works well on Linux. ### Arch Linux -Arch Linux provides a package through pacman. +Arch Linux provides an [up to date version](https://archlinux.org/packages/extra/x86_64/sqlitebrowser/) + +Install with the following command: + + sudo pacman -S sqlitebrowser + +### Debian + +Debian focuses more on stability rather than newest features.
+Therefore packages will typically contain an older (but well tested) version, compared to the latest release. + +Update the cache using: + + sudo apt-get update + +Install the package using: + + sudo apt-get install sqlitebrowser ### Fedora -For Fedora version 21, 22, 23 and rawhide (i386 and x86_64) you can install -by issuing: +Install for Fedora (i386 and x86_64) by issuing the following command: - $ sudo dnf install sqlitebrowser + sudo dnf install sqlitebrowser + +### openSUSE + + sudo zypper install sqlitebrowser ### Ubuntu and Derivatives #### Stable release -For Ubuntu and derivaties, [@deepsidhu1313](https://github.com/deepsidhu1313) -provides a PPA with our latest release here: +For Ubuntu and derivatives, [@deepsidhu1313](https://github.com/deepsidhu1313) +provides a PPA with the latest release here: * https://launchpad.net/~linuxgndu/+archive/ubuntu/sqlitebrowser -To add this ppa just type in these commands in terminal: +To add this PPA just type in this command in terminal: sudo add-apt-repository -y ppa:linuxgndu/sqlitebrowser @@ -104,14 +225,7 @@ Install the package using: sudo apt-get install sqlitebrowser -Ubuntu 14.04.X, 15.04.X, 15.10.X and 16.04.X are supported for now (until -Launchpad decides to discontinue build for any series). - -Ubuntu Precise (12.04) and Utopic (14.10) are not supported: -* Precise doesn't have a Qt 5.2 package in its repository by default, which is - a dependency -* Launchpad doesn't support Utopic any more, as that has reached its End of - Life +Packages for Older Ubuntu releases are supported while launchpad keeps building those or if Older Ubuntu release has dependency packages that are required to build the latest version of Sqlitebrowser. We don't remove builds from our ppa repos, so users can still install older version of sqlitebrowser if they like. Alternatively Linux users can also switch to Snap packages if Snap packages are supported by the distro they are using. #### Nightly builds @@ -119,7 +233,7 @@ Nightly builds are available here: * https://launchpad.net/~linuxgndu/+archive/ubuntu/sqlitebrowser-testing -To add this ppa just type in these commands in terminal: +To add this PPA, type these commands into the terminal: sudo add-apt-repository -y ppa:linuxgndu/sqlitebrowser-testing @@ -133,33 +247,61 @@ Install the package using: ### Other Linux -On others you'll need to compile it yourself using the (simple) instructions -in [BUILDING.md](BUILDING.md). +On others, compile DB4S using the instructions in [BUILDING.md](BUILDING.md). ## FreeBSD DB Browser for SQLite works well on FreeBSD, and there is a port for it (thanks -to [lbartoletti](https://github.com/lbartoletti) :smile:). It can be installed -using either this: +to [lbartoletti](https://github.com/lbartoletti) :smile:).
DB4S can be installed +using either this command: + + make -C /usr/ports/databases/sqlitebrowser install + +or this command: + + pkg install sqlitebrowser + +## Snap packages + +[![Get it from the Snap Store](https://snapcraft.io/static/images/badges/en/snap-store-black.svg)](https://snapcraft.io/sqlitebrowser) + +#### Snap Nightlies - # make -C /usr/ports/databases/sqlitebrowser install + snap install sqlitebrowser --edge -or this: +#### Snap Stable - # pkg install sqlitebrowser + snap install sqlitebrowser -### Compiling +## Nix Packages -Instructions for compiling on (at least) Windows, OSX, Linux, and FreeBSD are +`sqlitebrowser` is packaged and available in nixpkgs. +It can be used with the experimental flakes and nix-command features with: + + nix profile install nixpkgs#sqlitebrowser + +Or with the `nix-env` or `nix-shell` commands: + + nix-shell -p sqlitebrowser + +### Flox + +`sqlitebrowser` can be installed into a Flox environment with. + + flox install sqlitebrowser + +## Compiling + +Instructions for compiling on Windows, macOS, Linux, and FreeBSD are in [BUILDING](BUILDING.md). -## Twitter +## X (Known as Twitter) -Follow us on Twitter: https://twitter.com/sqlitebrowser +Follow us on X: https://x.com/sqlitebrowser ## Website -* http://sqlitebrowser.org +* https://sqlitebrowser.org ## Old project page @@ -167,6 +309,18 @@ Follow us on Twitter: https://twitter.com/sqlitebrowser ## Releases +* [Version 3.13.1 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.13.1) - 2024-10-16 +* [Version 3.13.0 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.13.0) - 2024-07-23 +* [Version 3.12.2 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.12.2) - 2021-05-18 +* [Version 3.12.1 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.12.1) - 2020-11-09 +* [Version 3.12.0 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.12.0) - 2020-06-16 +* [Version 3.11.2 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.11.2) - 2019-04-03 +* [Version 3.11.1 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.11.1) - 2019-02-18 +* [Version 3.11.0 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.11.0) - 2019-02-07 +* [Version 3.10.1 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.10.1) - 2017-09-20 +* [Version 3.10.0 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.10.0) - 2017-08-20 +* [Version 3.9.1 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.9.1) - 2016-10-03 +* [Version 3.9.0 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.9.0) - 2016-08-24 * [Version 3.8.0 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.8.0) - 2015-12-25 * [Version 3.7.0 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.7.0) - 2015-06-14 * [Version 3.6.0 released](https://github.com/sqlitebrowser/sqlitebrowser/releases/tag/v3.6.0) - 2015-04-27 @@ -191,7 +345,7 @@ Follow us on Twitter: https://twitter.com/sqlitebrowser ## History This program was developed originally by Mauricio Piacentini -([@piacentini](https://github.com/piacentini)) from Tabuleiro Producoes, as +([@piacentini](https://github.com/piacentini)) from Tabuleiro Producoes as the Arca Database Browser. The original version was used as a free companion tool to the Arca Database Xtra, a commercial product that embeds SQLite databases with some additional extensions to handle compressed and binary data. @@ -211,21 +365,46 @@ became involved, and have been the main driving force from that point. Justin Clift ([@justinclift](https://github.com/justinclift)) helps out with testing on OSX, and started the new github.com/sqlitebrowser organisation on GitHub. -[John T. Haller](http://johnhaller.com), of -[PortableApps.com](http://portableapps.com) fame, created the new logo. He +[John T. Haller](https://johnhaller.com), of +[PortableApps.com](https://portableapps.com) fame, created the new logo. He based it on the Tango icon set (public domain). In August 2014, the project was renamed to "Database Browser for SQLite" at -the request of [Richard Hipp](http://www.hwaci.com/drh) (creator of -[SQLite](http://sqlite.org)), as the previous name was creating unintended +the request of [Richard Hipp](https://www.hwaci.com/drh) (creator of +[SQLite](https://sqlite.org)), as the previous name was creating unintended support issues. In September 2014, the project was renamed to "DB Browser for SQLite", to avoid confusion with an existing application called "Database Browser". +## Contributors + +View the list by going to the [__Contributors__ tab](https://github.com/sqlitebrowser/sqlitebrowser/graphs/contributors). + ## License -DB Browser for SQLite is bi-licensed under the Mozilla Public License -Version 2, as well as the GNU General Public License Version 3 or later. +See the [LICENSE](LICENSE) file for licensing information. + + [gitter-img]: https://badges.gitter.im/sqlitebrowser/sqlitebrowser.svg + [gitter]: https://gitter.im/sqlitebrowser/sqlitebrowser + + [slack-img]: https://img.shields.io/badge/chat-on%20slack-orange.svg + [slack]: https://join.slack.com/t/db4s/shared_invite/enQtMzc3MzY5OTU4NDgzLWRlYjk0ZmE5ZDEzYWVmNDQxYTYxNmJjNWVkMjI3ZmVjZTY2NDBjODY3YzNhNTNmZDVlNWI2ZGFjNTk5MjJkYmU + + [download-img]: https://img.shields.io/github/downloads/sqlitebrowser/sqlitebrowser/total.svg + [download]: https://github.com/sqlitebrowser/sqlitebrowser/releases + + [qt-img]: https://img.shields.io/badge/Qt-cmake-green.svg + [qt]: https://www.qt.io + + [coverity-img]: https://img.shields.io/coverity/scan/11712.svg + [coverity]: https://scan.coverity.com/projects/sqlitebrowser-sqlitebrowser + + [patreon-img]: https://img.shields.io/badge/donate-Patreon-coral.svg + [patreon]: https://www.patreon.com/bePatron?u=11578749 + + [wiki-img]: https://img.shields.io/badge/docs-Wiki-blue.svg + [wiki]: https://github.com/sqlitebrowser/sqlitebrowser/wiki -You can modify or redistribute it under the conditions of these licenses. + [ghaction-img]: https://github.com/sqlitebrowser/sqlitebrowser/actions/workflows/cppcmake.yml/badge.svg + [ghaction]: https://github.com/sqlitebrowser/sqlitebrowser/actions/workflows/cppcmake.yml diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..1329513df --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +## Reporting a Vulnerability +We take security bugs in DB Browser for SQLite and related projects seriously. +We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions. + +We kindly ask that you consider reporting a security vulnerability by doing one of the following: +1. Use the GitHub Security Advisory's ["Report a Vulnerability"](https://github.com/sqlitebrowser/sqlitebrowser/security/advisories/new) tab. +2. Send an email to [security@sqlitebrowser.org](mailto:security@sqlitebrowser.org) diff --git a/cmake/FindAntlr2.cmake b/cmake/FindAntlr2.cmake deleted file mode 100644 index 871b32211..000000000 --- a/cmake/FindAntlr2.cmake +++ /dev/null @@ -1,50 +0,0 @@ -# - try to find Antlr v2 -# Once done this will define: -# -# ANTLR2_FOUND - system has antlr2 -# ANTLR2_INCLUDE_DIRS - the include directories for antlr2 -# ANTLR2_LIBRARIES - Link these to use antl2 -# ANTLR2_EXECUTABLE - The 'antlr' or 'runantlr' executable - -# Copyright (C) 2015, Pino Toscano, -# -# 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 copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. The name of the author may not 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. - - -find_library(ANTLR2_LIBRARY antlr) -set(ANTLR2_LIBRARIES "${ANTLR2_LIBRARY}") - -find_path(ANTLR2_INCLUDE_DIR antlr/AST.hpp) -set(ANTLR2_INCLUDE_DIRS "${ANTLR2_INCLUDE_DIR}") - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Antlr2 DEFAULT_MSG ANTLR2_LIBRARIES ANTLR2_INCLUDE_DIRS) - -find_program(ANTLR2_EXECUTABLE NAMES runantlr runantlr2 antlr) - -mark_as_advanced( - ANTLR2_INCLUDE_DIRS - ANTLR2_LIBRARIES - ANTLR2_EXECUTABLE -) diff --git a/cmake/FindQCustomPlot.cmake b/cmake/FindQCustomPlot.cmake new file mode 100644 index 000000000..abb2eb1c2 --- /dev/null +++ b/cmake/FindQCustomPlot.cmake @@ -0,0 +1,59 @@ +# Attempt to locate QCustomPlot +# Once done this will define: +# +# QCUSTOMPLOT_FOUND - system has QCustomPlot +# QCUSTOMPLOT_INCLUDE_DIRS - the include directories for QCustomPlot +# QCUSTOMPLOT_LIBRARIES - Link these to use QCustomPlot +# +# Copyright (C) 2019, Scott Furry, +# +# 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 copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not 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. + + +find_library(QCustomPlot_LIBRARY NAMES qcustomplot qcustomplot-qt5 QCustomPlot) +set(QCustomPlot_LIBRARIES "${QCustomPlot_LIBRARY}") + +find_path(QCustomPlot_INCLUDE_DIR qcustomplot.h) +set(QCustomPlot_INCLUDE_DIRS "${QCustomPlot_INCLUDE_DIR}") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + QCustomPlot + DEFAULT_MSG + QCustomPlot_LIBRARIES + QCustomPlot_INCLUDE_DIRS +) + +mark_as_advanced( + QCustomPlot_INCLUDE_DIRS + QCustomPlot_LIBRARIES +) + +if (QCustomPlot_FOUND AND NOT TARGET QCustomPlot::QCustomPlot) + add_library(QCustomPlot::QCustomPlot UNKNOWN IMPORTED) + set_target_properties(QCustomPlot::QCustomPlot PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${QCustomPlot_INCLUDE_DIRS} + IMPORTED_LOCATION ${QCustomPlot_LIBRARIES} + ) +endif() diff --git a/cmake/FindQHexEdit.cmake b/cmake/FindQHexEdit.cmake new file mode 100644 index 000000000..0b8c34e4a --- /dev/null +++ b/cmake/FindQHexEdit.cmake @@ -0,0 +1,59 @@ +# Attempt to locate QHexEdit +# Once done this will define: +# +# QHEXEDIT_FOUND - system has QHexEdit +# QHEXEDIT_INCLUDE_DIRS - the include directories for QHexEdit +# QHEXEDIT_LIBRARIES - Link these to use QHexEdit +# +# Copyright (C) 2019, Scott Furry, +# +# 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 copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not 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. + + +find_library(QHexEdit_LIBRARY NAMES qhexedit qhexedit-qt5) +set(QHexEdit_LIBRARIES "${QHexEdit_LIBRARY}") + +find_path(QHexEdit_INCLUDE_DIR qhexedit.h PATH_SUFFIXES qhexedit2) +set(QHexEdit_INCLUDE_DIRS "${QHexEdit_INCLUDE_DIR}") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + QHexEdit + DEFAULT_MSG + QHexEdit_LIBRARIES + QHexEdit_INCLUDE_DIRS +) + +mark_as_advanced( + QHexEdit_INCLUDE_DIRS + QHexEdit_LIBRARIES +) + +if (QHexEdit_FOUND AND NOT TARGET QHexEdit::QHexEdit) + add_library(QHexEdit::QHexEdit UNKNOWN IMPORTED) + set_target_properties(QHexEdit::QHexEdit PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${QHexEdit_INCLUDE_DIRS} + IMPORTED_LOCATION ${QHexEdit_LIBRARIES} + ) +endif() \ No newline at end of file diff --git a/cmake/FindQScintilla.cmake b/cmake/FindQScintilla.cmake new file mode 100644 index 000000000..55dc8a13b --- /dev/null +++ b/cmake/FindQScintilla.cmake @@ -0,0 +1,160 @@ +# QScintilla is a port to Qt of Neil Hodgson's Scintilla C++ editor control +# available at http://www.riverbankcomputing.com/software/qscintilla/ +# +# The module defines the following variables: +# QSCINTILLA_FOUND - the system has QScintilla +# QSCINTILLA_INCLUDE_DIR - where to find qsciscintilla.h +# QSCINTILLA_INCLUDE_DIRS - qscintilla includes +# QSCINTILLA_LIBRARY - where to find the QScintilla library +# QSCINTILLA_LIBRARIES - aditional libraries +# QSCINTILLA_MAJOR_VERSION - major version +# QSCINTILLA_MINOR_VERSION - minor version +# QSCINTILLA_PATCH_VERSION - patch version +# QSCINTILLA_VERSION_STRING - version (ex. 2.6.2) +# QSCINTILLA_ROOT_DIR - root dir (ex. /usr/local) + +#============================================================================= +# Copyright 2010-2013, Julien Schueller +# All rights reserved. +# +# 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. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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 views and conclusions contained in the software and documentation are those +# of the authors and should not be interpreted as representing official policies, +# either expressed or implied, of the FreeBSD Project. +#============================================================================= + +# When using pkg-config, paths may contain odd slash placement. Each +# include directory is pre-processed here. Resultant list variable +# then used for search hinting. Depends on successful find_package(Qt5). +if(QT_MAJOR STREQUAL "Qt6") + set(Qt6QScintillaHintDirs) + if(UNIX) + foreach(item ${Qt6Widgets_INCLUDE_DIRS}) + # remove slash at end of line + STRING(REGEX REPLACE "\\/$" "" item ${item}) + # replace double slashes is single slashes + STRING(REGEX REPLACE "\\/\\/" "/" item ${item}) + list(APPEND Qt6QScintillaHintDirs "${item}/Qsci") + endforeach() + endif() + find_path ( QSCINTILLA_INCLUDE_DIR qsciscintilla.h + HINTS /usr/local/include/Qt6/Qsci + /usr/local/opt/qscintilla2/include/Qt6/Qsci + ${Qt6QScintillaHintDirs} + ) +else() + set(Qt5QScintillaHintDirs) + if(UNIX) + foreach(item ${Qt5Widgets_INCLUDE_DIRS}) + # remove slash at end of line + STRING(REGEX REPLACE "\\/$" "" item ${item}) + # replace double slashes is single slashes + STRING(REGEX REPLACE "\\/\\/" "/" item ${item}) + list(APPEND Qt5QScintillaHintDirs "${item}/Qsci") + endforeach() + endif() + find_path ( QSCINTILLA_INCLUDE_DIR qsciscintilla.h + HINTS /usr/local/include/Qsci + /usr/local/opt/qscintilla2/include/Qsci + ${Qt5QScintillaHintDirs} + ) +endif() + +set ( QSCINTILLA_INCLUDE_DIRS ${QSCINTILLA_INCLUDE_DIR} ) + +# version +set ( _VERSION_FILE ${QSCINTILLA_INCLUDE_DIR}/qsciglobal.h ) + +if ( EXISTS ${_VERSION_FILE} ) + file ( STRINGS ${_VERSION_FILE} _VERSION_LINE REGEX "define[ ]+QSCINTILLA_VERSION_STR" ) + if ( _VERSION_LINE ) + string ( REGEX REPLACE ".*define[ ]+QSCINTILLA_VERSION_STR[ ]+\"(.*)\".*" "\\1" QSCINTILLA_VERSION_STRING "${_VERSION_LINE}" ) + string ( REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\1" QSCINTILLA_MAJOR_VERSION "${QSCINTILLA_VERSION_STRING}" ) + string ( REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\2" QSCINTILLA_MINOR_VERSION "${QSCINTILLA_VERSION_STRING}" ) + string ( REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\3" QSCINTILLA_PATCH_VERSION "${QSCINTILLA_VERSION_STRING}" ) + endif () +endif () + +# check version +set ( _QSCINTILLA_VERSION_MATCH TRUE ) + +if ( QScintilla_FIND_VERSION AND QSCINTILLA_VERSION_STRING ) + if ( QScintilla_FIND_VERSION_EXACT ) + if ( NOT QScintilla_FIND_VERSION VERSION_EQUAL QSCINTILLA_VERSION_STRING ) + set ( _QSCINTILLA_VERSION_MATCH FALSE ) + endif () + else () + if ( QSCINTILLA_VERSION_STRING VERSION_LESS QScintilla_FIND_VERSION ) + set ( _QSCINTILLA_VERSION_MATCH FALSE ) + endif () + endif () +endif () + +if(QT_MAJOR STREQUAL "Qt6") + find_library ( QSCINTILLA_LIBRARY + NAMES qscintilla2_qt6 + HINTS /usr/local/lib /usr/local/opt/qscintilla2/lib + ) +else() + find_library ( QSCINTILLA_LIBRARY + NAMES qscintilla2 qscintilla2_qt5 + HINTS /usr/local/lib /usr/local/opt/qscintilla2/lib + ) +endif() + +set ( QSCINTILLA_LIBRARIES ${QSCINTILLA_LIBRARY} ) + +# try to guess root dir from include dir +if ( QSCINTILLA_INCLUDE_DIR ) + string ( REGEX REPLACE "(.*)/include.*" "\\1" QSCINTILLA_ROOT_DIR ${QSCINTILLA_INCLUDE_DIR} ) +# try to guess root dir from library dir +elseif ( QSCINTILLA_LIBRARY ) + string ( REGEX REPLACE "(.*)/lib[/|32|64].*" "\\1" QSCINTILLA_ROOT_DIR ${QSCINTILLA_LIBRARY} ) +endif () + +# handle the QUIETLY and REQUIRED arguments +include ( FindPackageHandleStandardArgs ) +if ( CMAKE_VERSION VERSION_LESS 2.8.3 ) + find_package_handle_standard_args( QScintilla DEFAULT_MSG QSCINTILLA_LIBRARY QSCINTILLA_INCLUDE_DIR _QSCINTILLA_VERSION_MATCH ) +else () + find_package_handle_standard_args( QScintilla REQUIRED_VARS QSCINTILLA_LIBRARY QSCINTILLA_INCLUDE_DIR _QSCINTILLA_VERSION_MATCH VERSION_VAR QSCINTILLA_VERSION_STRING ) +endif () + +mark_as_advanced ( + QSCINTILLA_LIBRARY + QSCINTILLA_LIBRARIES + QSCINTILLA_INCLUDE_DIR + QSCINTILLA_INCLUDE_DIRS + QSCINTILLA_MAJOR_VERSION + QSCINTILLA_MINOR_VERSION + QSCINTILLA_PATCH_VERSION + QSCINTILLA_VERSION_STRING + QSCINTILLA_ROOT_DIR +) + +if (QScintilla_FOUND AND NOT TARGET QScintilla::QScintilla) + add_library(QScintilla::QScintilla UNKNOWN IMPORTED) + set_target_properties(QScintilla::QScintilla PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${QSCINTILLA_INCLUDE_DIRS} + IMPORTED_LOCATION ${QSCINTILLA_LIBRARIES} + ) +endif() diff --git a/cmake/FindSQLCipher.cmake b/cmake/FindSQLCipher.cmake new file mode 100644 index 000000000..d509f1893 --- /dev/null +++ b/cmake/FindSQLCipher.cmake @@ -0,0 +1,115 @@ +# - Try to find SQLCipher +# Once done this will define +# +# SQLCIPHER_FOUND - system has SQLCipher +# SQLCIPHER_INCLUDE_DIR - the SQLCipher include directory +# SQLCIPHER_LIBRARIES - Link these to use SQLCipher +# SQLCIPHER_DEFINITIONS - Compiler switches required for using SQLCipher +# SQLCIPHER_VERSION - This is set to major.minor.revision (e.g. 3.4.1) +# +# Hints to find SQLCipher +# +# Set SQLCIPHER_ROOT_DIR to the root directory of a SQLCipher installation +# +# The following variables may be set +# +# SQLCIPHER_USE_OPENSSL - Set to ON/OFF to specify whether to search and use OpenSSL. +# Default is OFF. +# SQLCIPHER_OPENSSL_USE_ZLIB - Set to ON/OFF to specify whether to search and use Zlib in OpenSSL +# Default is OFF. + +# Redistribution and use is allowed according to the terms of the BSD license. + +# Copyright (c) 2008, Gilles Caulier, +# Copyright (c) 2014, Christian Dávid, +# +# 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 copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not 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. + +# use pkg-config to get the directories and then use these values +# in the FIND_PATH() and FIND_LIBRARY() calls +if( NOT WIN32 ) + find_package(PkgConfig) + + pkg_check_modules(PC_SQLCIPHER QUIET sqlcipher) + + set(SQLCIPHER_DEFINITIONS ${PC_SQLCIPHER_CFLAGS_OTHER}) +endif( NOT WIN32 ) + +find_path(SQLCIPHER_INCLUDE_DIR NAMES sqlcipher/sqlite3.h + PATHS + ${SQLCIPHER_ROOT_DIR} + ${PC_SQLCIPHER_INCLUDEDIR} + ${PC_SQLCIPHER_INCLUDE_DIRS} + ${CMAKE_INCLUDE_PATH} + PATH_SUFFIXES "include" +) + +find_library(SQLCIPHER_LIBRARY NAMES sqlcipher + PATHS + ${PC_SQLCIPHER_LIBDIR} + ${PC_SQLCIPHER_LIBRARY_DIRS} + ${SQLCIPHER_ROOT_DIR} + PATH_SUFFIXES "lib" +) + +set(SQLCIPHER_LIBRARIES ${SQLCIPHER_LIBRARY}) +set(SQLCIPHER_INCLUDE_DIRS ${SQLCIPHER_INCLUDE_DIR}) + +if (SQLCIPHER_USE_OPENSSL) + find_package(OpenSSL REQUIRED COMPONENTS Crypto) + if (SQLCIPHER_OPENSSL_USE_ZLIB) + find_package(ZLIB REQUIRED) + # Official FindOpenSSL.cmake does not support Zlib + set_target_properties(OpenSSL::Crypto PROPERTIES INTERFACE_LINK_LIBRARIES ZLIB::ZLIB) + endif() + + list(APPEND SQLCIPHER_LIBRARIES ${OPENSSL_LIBRARIES}) + list(APPEND SQLCIPHER_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIRS}) +endif() + + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(SQLCipher + DEFAULT_MSG SQLCIPHER_INCLUDE_DIR SQLCIPHER_LIBRARY) + +# show the SQLCIPHER_INCLUDE_DIR and SQLCIPHER_LIBRARIES variables only in the advanced view +mark_as_advanced(SQLCIPHER_INCLUDE_DIR SQLCIPHER_LIBRARY) + +if (NOT TARGET SQLCipher::SQLCipher) + add_library(SQLCipher::SQLCipher UNKNOWN IMPORTED) + + set_property(TARGET SQLCipher::SQLCipher PROPERTY INTERFACE_COMPILE_DEFINITIONS SQLITE_HAS_CODEC) + set_property(TARGET SQLCipher::SQLCipher APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS "SQLITE_TEMPSTORE=2") + set_target_properties(SQLCipher::SQLCipher PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${SQLCIPHER_INCLUDE_DIRS}" + IMPORTED_INTERFACE_LINK_LANGUAGES "C" + IMPORTED_LOCATION "${SQLCIPHER_LIBRARY}") + + if (SQLCIPHER_USE_OPENSSL) + set_target_properties(SQLCipher::SQLCipher PROPERTIES + INTERFACE_LINK_LIBRARIES OpenSSL::Crypto) + set_property(TARGET SQLCipher::SQLCipher APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS "SQLCIPHER_CRYPTO_OPENSSL") + endif() +endif() diff --git a/config/3dparty.cmake b/config/3dparty.cmake new file mode 100644 index 000000000..f92001f92 --- /dev/null +++ b/config/3dparty.cmake @@ -0,0 +1,23 @@ +if(NOT FORCE_INTERNAL_QSCINTILLA) + find_package(QScintilla 2.8.10) +endif() + +if(NOT FORCE_INTERNAL_QCUSTOMPLOT) + find_package(QCustomPlot) +endif() + +if(NOT FORCE_INTERNAL_QHEXEDIT) + find_package(QHexEdit) +endif() + +if(NOT QSCINTILLA_FOUND) + add_subdirectory(libs/qscintilla_2.14.1/Qt5Qt6) +endif() + +if(NOT QHexEdit_FOUND) + add_subdirectory(libs/qhexedit) +endif() + +if(NOT QCustomPlot_FOUND) + add_subdirectory(libs/qcustomplot-source) +endif() diff --git a/config/install.cmake b/config/install.cmake new file mode 100644 index 000000000..c10c608f7 --- /dev/null +++ b/config/install.cmake @@ -0,0 +1,89 @@ +if(NOT WIN32 AND NOT APPLE) + install(TARGETS ${PROJECT_NAME} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) +endif() + +if(UNIX) + install(FILES src/icons/${PROJECT_NAME}.png + DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/256x256/apps/ + ) + + install(FILES images/logo.svg + DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps/ + RENAME ${PROJECT_NAME}.svg + ) + + install(FILES distri/${PROJECT_NAME}.desktop + DESTINATION ${CMAKE_INSTALL_DATADIR}/applications/ + ) + + install(FILES distri/${PROJECT_NAME}.metainfo.xml + DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo/ + ) +endif() + +if(WIN32) + install(TARGETS ${PROJECT_NAME} + RUNTIME DESTINATION "." + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + + if(sqlcipher) + find_file(DLL_NAME sqlcipher.dll PATH_SUFFIXES bin ../bin ../../bin) + else() + find_file(DLL_NAME sqlite3.dll PATH_SUFFIXES bin ../bin ../../bin) + endif() + + string(REGEX MATCH "^([0-9]+)\.([0-9]+)" SSL_OUT "${OPENSSL_VERSION}") + set(DLL_CRYPTO_NAMES + "libcrypto-${CMAKE_MATCH_1}_${CMAKE_MATCH_2}-x64.dll" + "libcrypto-${CMAKE_MATCH_1}-x64.dll" + "libcrypto-${CMAKE_MATCH_1}_${CMAKE_MATCH_2}.dll" + "libcrypto-${CMAKE_MATCH_1}.dll" + ) + + set(DLL_SSL_NAMES + "libssl-${CMAKE_MATCH_1}_${CMAKE_MATCH_2}-x64.dll" + "libssl-${CMAKE_MATCH_1}-x64.dll" + "libssl-${CMAKE_MATCH_1}_${CMAKE_MATCH_2}.dll" + "libssl-${CMAKE_MATCH_1}.dll" + ) + + find_file(DLL_CRYPTO NAMES ${DLL_CRYPTO_NAMES} PATH_SUFFIXES bin ../bin ../../bin) + find_file(DLL_SSL NAMES ${DLL_SSL_NAMES} PATH_SUFFIXES bin ../bin ../../bin) + + install(FILES + ${DLL_NAME} + ${DLL_CRYPTO} + ${DLL_SSL} + DESTINATION "." + ) + + # The license files + install(FILES + LICENSE + LICENSE-GPL-3.0 + LICENSE-MIT + LICENSE-MPL-2.0 + LICENSE-PLUGINS + DESTINATION licenses + ) + + if(QT_MAJOR STREQUAL "Qt5") + set(OPT_ANGLE "--no-angle") + endif() + + find_file(QT_DEPLOY windeployqt.exe HINTS ${${QT_MAJOR}_DIR}/../../../bin) + if(NOT ${QT_DEPLOY} STREQUAL "QT_DEPLOY-NOTFOUND") + install (CODE + "execute_process(COMMAND_ECHO STDOUT COMMAND ${QT_DEPLOY} + --no-system-d3d-compiler + ${OPT_ANGLE} + --no-opengl-sw + \"\${CMAKE_INSTALL_PREFIX}/$\" + )" + ) + endif() +endif() diff --git a/config/options.cmake b/config/options.cmake new file mode 100644 index 000000000..179fe0c23 --- /dev/null +++ b/config/options.cmake @@ -0,0 +1,9 @@ +set(QT_MAJOR Qt5 CACHE STRING "Major QT version") +OPTION(BUILD_STABLE_VERSION "Don't build the stable version by default" OFF) # Choose between building a stable version or nightly (the default), depending on whether '-DBUILD_STABLE_VERSION=1' is passed on the command line or not. +OPTION(ENABLE_TESTING "Enable the unit tests" OFF) +OPTION(FORCE_INTERNAL_QSCINTILLA "Don't use the distribution's QScintilla library even if there is one" OFF) +OPTION(FORCE_INTERNAL_QCUSTOMPLOT "Don't use distribution's QCustomPlot even if available" ON) +OPTION(FORCE_INTERNAL_QHEXEDIT "Don't use distribution's QHexEdit even if available" ON) +OPTION(ALL_WARNINGS "Enable some useful warning flags" OFF) +OPTION(sqlcipher "Build with SQLCipher library" OFF) +OPTION(customTap "Using SQLCipher, SQLite and Qt installed through our custom Homebrew tap" OFF) diff --git a/config/platform.cmake b/config/platform.cmake new file mode 100644 index 000000000..cca1f7481 --- /dev/null +++ b/config/platform.cmake @@ -0,0 +1,22 @@ +if(WIN32) + include(${CMAKE_CURRENT_LIST_DIR}/platform_win.cmake) + add_definitions(-DCHECKNEWVERSION) +elseif(APPLE) + include(${CMAKE_CURRENT_LIST_DIR}/platform_apple.cmake) + add_definitions(-DCHECKNEWVERSION) +endif() + +if(NOT WIN32) + list(APPEND PLATFORM_LIBS pthread) +endif() + +if(UNIX AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") + list(APPEND PLATFORM_LIBS dl) +endif() + +# add extra library path for MacOS and FreeBSD +set(EXTRAPATH APPLE OR ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") +if(EXTRAPATH) + list(PREPEND CMAKE_PREFIX_PATH /usr/local/opt/sqlite/lib) + list(PREPEND CMAKE_PREFIX_PATH /usr/local/opt/sqlitefts5/lib) +endif() diff --git a/config/platform_apple.cmake b/config/platform_apple.cmake new file mode 100644 index 000000000..bd96ba1ef --- /dev/null +++ b/config/platform_apple.cmake @@ -0,0 +1,31 @@ +if(QT_MAJOR STREQUAL "Qt5") + # For Intel Mac's + if(EXISTS /usr/local/opt/qt5) + list(APPEND CMAKE_PREFIX_PATH "/usr/local/opt/qt5") + endif() + + # For Apple Silicon Mac's + if(EXISTS /opt/homebrew/opt/qt5) + list(APPEND CMAKE_PREFIX_PATH "/opt/homebrew/opt/qt5") + endif() + if(EXISTS /opt/homebrew/opt/sqlitefts5) + list(PREPEND CMAKE_PREFIX_PATH "/opt/homebrew/opt/sqlitefts5") + endif() + + # For Apple Silicon Mac's and install dependencies via our Homebrew tap(sqlitebrowser/homebrew-tap) + if(customTap AND EXISTS /opt/homebrew/opt/) + list(PREPEND CMAKE_PREFIX_PATH "/opt/homebrew/opt/sqlb-qt@5") + list(PREPEND CMAKE_PREFIX_PATH "/opt/homebrew/opt/sqlb-sqlite") + + if(sqlcipher) + list(APPEND SQLCIPHER_INCLUDE_DIR "/opt/homebrew/include") + list(APPEND SQLCIPHER_LIBRARY "/opt/homebrew/opt/sqlb-sqlcipher/lib/libsqlcipher.0.dylib") + endif() + endif() +endif() + +set_target_properties(${PROJECT_NAME} PROPERTIES + BUNDLE True + OUTPUT_NAME "DB Browser for SQLite" + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/src/app.plist +) diff --git a/config/platform_win.cmake b/config/platform_win.cmake new file mode 100644 index 000000000..ba49ee311 --- /dev/null +++ b/config/platform_win.cmake @@ -0,0 +1,35 @@ +if(sqlcipher) + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "DB Browser for SQLCipher") +else() + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "DB Browser for SQLite") +endif() + +if(QT_MAJOR STREQUAL "Qt5") + find_package(OpenSSL 1.1.1 REQUIRED) +else() + find_package(OpenSSL 3.0.0 REQUIRED) +endif() + +if(MSVC) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS,5.02 /ENTRY:mainCRTStartup") + set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS,5.02") + else() + set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS,5.01 /ENTRY:mainCRTStartup") + set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS,5.01") + endif() + + set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE") + set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE") + set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE") + set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_DEFINITIONS_RELWITHDEBINFO "_CONSOLE") + + target_sources(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/winapp.rc") +elseif(MINGW) + # resource compilation for MinGW + add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/sqlbicon.o" + COMMAND windres "-I${CMAKE_CURRENT_BINARY_DIR}" "-i${CMAKE_CURRENT_SOURCE_DIR}/src/winapp.rc" -o "${CMAKE_CURRENT_BINARY_DIR}/sqlbicon.o" VERBATIM + ) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-subsystem,windows") + target_sources(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/sqlbicon.o") +endif() diff --git a/config/translations.cmake b/config/translations.cmake new file mode 100644 index 000000000..3222d14f7 --- /dev/null +++ b/config/translations.cmake @@ -0,0 +1,35 @@ +# Translation files +set(SQLB_TSS + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_ar_SA.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_cs.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_de.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_en_GB.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_es_ES.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_fr.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_id.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_it.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_ja.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_ko_KR.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_nl.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_pl.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_pt_BR.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_ro.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_ru.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_sv.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_tr.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_uk_UA.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_zh.ts" + "${CMAKE_SOURCE_DIR}/src/translations/sqlb_zh_TW.ts" +) + +if(SQLB_TSS) + # add translations + foreach(SQLB_TS ${SQLB_TSS}) + set_source_files_properties("${SQLB_TS}" PROPERTIES OUTPUT_LOCATION "${CMAKE_SOURCE_DIR}/src/translations") + endforeach() + if(COMMAND qt_add_translation) + qt_add_translation(SQLB_QMS ${SQLB_TSS}) + else() + qt5_add_translation(SQLB_QMS ${SQLB_TSS}) + endif() +endif() diff --git a/currentrelease b/currentrelease index 466cf8cf6..f222af6f9 100644 --- a/currentrelease +++ b/currentrelease @@ -1,3 +1,3 @@ -3.8.0 -https://github.com/sqlitebrowser/sqlitebrowser/releases +3.13.1 +https://sqlitebrowser.org/blog/version-3-13-1-released/ diff --git a/distri/mime/packages/db4s-sqbpro.xml b/distri/mime/packages/db4s-sqbpro.xml new file mode 100644 index 000000000..013cb84a1 --- /dev/null +++ b/distri/mime/packages/db4s-sqbpro.xml @@ -0,0 +1,10 @@ + + + + DB Browser for SQLite project file + + + + + + diff --git a/distri/sqlitebrowser.desktop b/distri/sqlitebrowser.desktop index 4e7dbca4f..965211ce4 100644 --- a/distri/sqlitebrowser.desktop +++ b/distri/sqlitebrowser.desktop @@ -2,10 +2,14 @@ Name=DB Browser for SQLite Comment=DB Browser for SQLite is a light GUI editor for SQLite databases Comment[de]=DB Browser for SQLite ist ein GUI-Editor für SQLite-Datenbanken +Comment[fr]=Un éditeur graphique léger pour les bases de données SQLite +Comment[es]=«DB Browser for SQLite» es un editor gráfico de bases de datos SQLite +Keywords=sqlite;database;browser; Exec=sqlitebrowser %f Icon=sqlitebrowser Terminal=false X-MultipleArgs=false Type=Application Categories=Development;Utility;Database; -MimeType=application/sqlitebrowser;application/x-sqlitebrowser;application/x-sqlite2;application/x-sqlite3; +MimeType=application/vnd.db4s-project+xml;application/sqlitebrowser;application/x-sqlitebrowser;application/vnd.sqlite3;application/geopackage+sqlite3;application/x-sqlite2;application/x-sqlite3;text/csv; +StartupWMClass=sqlitebrowser diff --git a/distri/sqlitebrowser.desktop.appdata.xml b/distri/sqlitebrowser.desktop.appdata.xml deleted file mode 100644 index 11a0e99d9..000000000 --- a/distri/sqlitebrowser.desktop.appdata.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - sqlitebrowser.desktop - CC0-1.0 - MPL-2.0 and GPL-3.0+ - DB Browser for SQLite - DB Browser for SQLite is a light GUI editor for SQLite databases - -

DB Browser for SQLite is a high quality, visual, open source tool to create, design, and edit database files compatible with SQLite.

-

It is for users and developers wanting to create databases, search, and edit data. It uses a familiar spreadsheet-like interface, and you don't need to learn complicated SQL commands.

-

Controls and wizards are available for users to:

-
    -
  • Create and compact database files
  • -
  • Create, define, modify and delete tables
  • -
  • Create, define and delete indexes
  • -
  • Browse, edit, add and delete records
  • -
  • Search records
  • -
  • Import and export records as text
  • -
  • Import and export tables from/to CSV files
  • -
  • Import and export databases from/to SQL dump files
  • -
  • Issue SQL queries and inspect the results
  • -
  • Examine a log of all SQL commands issued by the application
  • -
-
- - - https://raw.githubusercontent.com/sqlitebrowser/db4s-screenshots/master/v3.3/gnome3_2-execute.png - DB Browser for SQLite, executing query - - - https://raw.githubusercontent.com/sqlitebrowser/db4s-screenshots/master/v3.3/gnome3_1-plot.png - DB Browser for SQLite, browsing data with plot - - - https://raw.githubusercontent.com/sqlitebrowser/db4s-screenshots/master/v3.3/kde413_2-blob.png - DB Browser for SQLite, browing a blob field - - - https://raw.githubusercontent.com/sqlitebrowser/db4s-screenshots/master/v3.3/kde413_1-create_table.png - DB Browser for SQLite, creating a table - - - http://sqlitebrowser.org/ - https://github.com/sqlitebrowser/sqlitebrowser/issues -
diff --git a/distri/sqlitebrowser.metainfo.xml b/distri/sqlitebrowser.metainfo.xml new file mode 100644 index 000000000..246144f6d --- /dev/null +++ b/distri/sqlitebrowser.metainfo.xml @@ -0,0 +1,63 @@ + + + org.sqlitebrowser.desktop + CC0-1.0 + MPL-2.0 and GPL-3.0+ + + DB Browser for SQLite developers + + DB Browser for SQLite + Light GUI editor for SQLite databases + +

DB Browser for SQLite is a high quality, visual, open source tool to create, design, and edit database files compatible with SQLite.

+

It is for users and developers wanting to create databases, search, and edit data. It uses a familiar spreadsheet-like interface, and you don't need to learn complicated SQL commands.

+

Controls and wizards are available for users to:

+
    +
  • Create and compact database files
  • +
  • Create, define, modify and delete tables
  • +
  • Create, define and delete indexes
  • +
  • Browse, edit, add and delete records
  • +
  • Search records
  • +
  • Import and export records as text
  • +
  • Import and export tables from/to CSV files
  • +
  • Import and export databases from/to SQL dump files
  • +
  • Issue SQL queries and inspect the results
  • +
  • Examine a log of all SQL commands issued by the application
  • +
+
+ + + + https://raw.githubusercontent.com/sqlitebrowser/db4s-screenshots/master/v3.3/gnome3_2-execute.png + DB Browser for SQLite, executing query + + + https://raw.githubusercontent.com/sqlitebrowser/db4s-screenshots/master/v3.3/gnome3_1-plot.png + DB Browser for SQLite, browsing data with plot + + + https://raw.githubusercontent.com/sqlitebrowser/db4s-screenshots/master/v3.3/kde413_2-blob.png + DB Browser for SQLite, browsing a blob field + + + https://raw.githubusercontent.com/sqlitebrowser/db4s-screenshots/master/v3.3/kde413_1-create_table.png + DB Browser for SQLite, creating a table + + + https://sqlitebrowser.org/ + https://github.com/sqlitebrowser/sqlitebrowser/issues + https://github.com/sqlitebrowser/sqlitebrowser/wiki/Frequently-Asked-Questions + https://github.com/sqlitebrowser/sqlitebrowser/wiki + https://www.patreon.com/db4s + https://github.com/sqlitebrowser/sqlitebrowser/wiki/Translations + https://github.com/sqlitebrowser/sqlitebrowser/wiki#for-developers + https://github.com/sqlitebrowser/sqlitebrowser + + + + + + + + sqlitebrowser.desktop +
diff --git a/images/logo-nightly.png b/images/logo-nightly.png new file mode 100644 index 000000000..8bd2211ed Binary files /dev/null and b/images/logo-nightly.png differ diff --git a/images/logo-nightly.svg b/images/logo-nightly.svg new file mode 100644 index 000000000..09e594cec --- /dev/null +++ b/images/logo-nightly.svg @@ -0,0 +1,117 @@ + + logo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xmllogohttps://sqlitebrowser.orgDB Browser for SQLite Logo2020Jun05GPL3+ + + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 000000000..7897a11e5 Binary files /dev/null and b/images/logo.png differ diff --git a/images/logo.svg b/images/logo.svg new file mode 100644 index 000000000..7817ec7a4 --- /dev/null +++ b/images/logo.svg @@ -0,0 +1,391 @@ + + + logo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + logo + + + + + + https://sqlitebrowser.org + + + + + DB Browser for SQLite Logo + 2020Jun05 + + + GPL3+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/sqlitebrowser.png b/images/sqlitebrowser.png index b737b1aa6..c57bd9dae 100644 Binary files a/images/sqlitebrowser.png and b/images/sqlitebrowser.png differ diff --git a/images/sqlitebrowser.svg b/images/sqlitebrowser.svg deleted file mode 100644 index dad9f6da3..000000000 --- a/images/sqlitebrowser.svg +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - Jakub Steiner - - - http://jimmac.musichall.cz - - - battery - apm - acpi - power management - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/installer/linux/sqlcipher_rename.sh b/installer/linux/sqlcipher_rename.sh new file mode 100644 index 000000000..4bc9dca69 --- /dev/null +++ b/installer/linux/sqlcipher_rename.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +# rename.sh +# A script to revert SQLCipher v.4.7.0+ build artifacts being named 'sqlite3'. + +patch_pkgconfig() { + PC_FILE="${1:-sqlite3.pc}" + + if [[ ! -f "$PC_FILE" ]]; then + echo "Error: file not found: $PC_FILE" >&2 + exit 1 + fi + + tmp="$(mktemp)" + trap 'rm -f "$tmp"' EXIT + + awk ' + NR==6 { + if ($0 !~ /\/sqlcipher$/) $0 = $0 "/sqlcipher" + } + NR==8 { + sub(/^Name:[[:space:]]*SQLite[[:space:]]*$/, "Name: SQLCipher") + } + NR==11 { + gsub(/-lsqlite3/, "-lsqlcipher") + } + { print } + ' "$PC_FILE" > "$tmp" + + cp "$tmp" "$PC_FILE" +} + +VERSION=$(cat VERSION) + +mv ./prefix/bin/sqlite3 ./prefix/bin/sqlcipher +mv ./prefix/lib/libsqlite3.a ./prefix/lib/libsqlcipher.a +mv ./prefix/lib/libsqlite3.so.$VERSION ./prefix/lib/libsqlcipher.so.$VERSION +ln -s "$(pwd)/prefix/lib/libsqlcipher.so.$VERSION" ./prefix/lib/libsqlcipher.so +ln -s "$(pwd)/prefix/lib/libsqlcipher.so.$VERSION" ./prefix/lib/libsqlcipher.so.0 +rm ./prefix/lib/libsqlite* +patch_pkgconfig ./prefix/lib/pkgconfig/sqlite3.pc +mv ./prefix/lib/pkgconfig/sqlite3.pc ./prefix/lib/pkgconfig/sqlcipher.pc +mkdir ./prefix/include/sqlcipher +mv ./prefix/include/*.h ./prefix/include/sqlcipher/ +mv ./prefix/share/man/man1/sqlite3.1 ./prefix/share/man/man1/sqlcipher.1 diff --git a/installer/macos/background.png b/installer/macos/background.png new file mode 100644 index 000000000..a329c6a5b Binary files /dev/null and b/installer/macos/background.png differ diff --git a/installer/macos/background@2x.png b/installer/macos/background@2x.png new file mode 100644 index 000000000..a29442d17 Binary files /dev/null and b/installer/macos/background@2x.png differ diff --git a/installer/macos/macapp-nightly.icns b/installer/macos/macapp-nightly.icns new file mode 100644 index 000000000..60aa2030e Binary files /dev/null and b/installer/macos/macapp-nightly.icns differ diff --git a/installer/macos/macapp.icns b/installer/macos/macapp.icns new file mode 100644 index 000000000..3300679d3 Binary files /dev/null and b/installer/macos/macapp.icns differ diff --git a/installer/macos/nightly.json b/installer/macos/nightly.json new file mode 100644 index 000000000..61651ad19 --- /dev/null +++ b/installer/macos/nightly.json @@ -0,0 +1,23 @@ +{ + "title": "Install DB4S Nightly build", + "icon": "macapp-nightly.icns", + "icon-size": 128, + "background": "background.png", + "format": "ULFO", + "window": { + "size": { + "width": 500, + "height": 320 + } + }, + "contents": [ + { "x": 90, "y": 180, "type": "file", "path": "DB Browser for SQLite Nightly.app" }, + { "x": 395, "y": 180, "type": "link", "path": "/Applications" }, + + { "x": 90, "y": 380, "type": "position", "path": ".background" }, + { "x": 240, "y": 380, "type": "position", "path": ".DS_Store" }, + { "x": 400, "y": 380, "type": "position", "path": ".VolumeIcon.icns" }, + { "x": 90, "y": 530, "type": "position", "path": ".Trashes" } + ] +} + diff --git a/installer/macos/notarize.sh b/installer/macos/notarize.sh new file mode 100644 index 000000000..04d8d0f56 --- /dev/null +++ b/installer/macos/notarize.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +# Create a new keychain +CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 +KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db +echo -n "$P12" | base64 --decode -o $CERTIFICATE_PATH +security create-keychain -p "$KEYCHAIN_PW" $KEYCHAIN_PATH +security set-keychain-settings -lut 21600 $KEYCHAIN_PATH +security unlock-keychain -p "$KEYCHAIN_PW" $KEYCHAIN_PATH +security import $CERTIFICATE_PATH -P "$P12_PW" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH +security list-keychain -d user -s $KEYCHAIN_PATH + +# Run macdeployqt +find build -name "DB Browser for SQL*.app" -exec $(brew --prefix sqlb-qt@5)/bin/macdeployqt {} -sign-for-notarization=$DEV_ID \; + +# Add the 'formats' and 'nalgeon/sqlean' extensions to the app bundle +gh auth login --with-token <<< "$GH_TOKEN" +gh release download --pattern "sqlean-macos-x86.zip" --repo "nalgeon/sqlean" +unzip sqlean-macos-x86.zip -d sqlean-macos-x86 +gh release download --pattern "sqlean-macos-arm64.zip" --repo "nalgeon/sqlean" +unzip sqlean-macos-arm64.zip -d sqlean-macos-arm64 +lipo -create sqlean-macos-x86/sqlean.dylib sqlean-macos-arm64/sqlean.dylib -output sqlean.dylib +for TARGET in $(find build -name "DB Browser for SQL*.app" | sed -e 's/ /_/g'); do + TARGET=$(echo $TARGET | sed -e 's/_/ /g') + mkdir "$TARGET/Contents/Extensions" + + arch -x86_64 clang -I /opt/homebrew/opt/sqlb-sqlite/include -L /opt/homebrew/opt/sqlb-sqlite/lib -fno-common -dynamiclib src/extensions/extension-formats.c -o formats_x86_64.dylib + clang -I /opt/homebrew/opt/sqlb-sqlite/include -L /opt/homebrew/opt/sqlb-sqlite/lib -fno-common -dynamiclib src/extensions/extension-formats.c -o formats_arm64.dylib + lipo -create formats_x86_64.dylib formats_arm64.dylib -output "$TARGET/Contents/Extensions/formats.dylib" + + if [ -f "$TARGET/Contents/Extensions/formats.dylib" ]; then + install_name_tool -id "@executable_path/../Extensions/formats.dylib" "$TARGET/Contents/Extensions/formats.dylib" + ln -s formats.dylib "$TARGET/Contents/Extensions/formats.dylib.dylib" + fi + + cp sqlean.dylib "$TARGET/Contents/Extensions/" + if [ -f "$TARGET/Contents/Extensions/sqlean.dylib" ]; then + install_name_tool -id "@executable_path/../Extensions/sqlean.dylib" "$TARGET/Contents/Extensions/sqlean.dylib" + ln -s sqlean.dylib "$TARGET/Contents/Extensions/sqlean.dylib.dylib" + fi +done + +# Copy the license file to the app bundle +for TARGET in $(find build -name "DB Browser for SQL*.app" | sed -e 's/ /_/g'); do + TARGET=$(echo $TARGET | sed -e 's/_/ /g') + cp LICENSE* "$TARGET/Contents/Resources/" +done + +# Copy the translation files to the app bundle +for TARGET in $(find build -name "DB Browser for SQL*.app" | sed -e 's/ /_/g'); do + TARGET=$(echo $TARGET | sed -e 's/_/ /g') + mkdir "$TARGET/Contents/translations" + for i in ar cs de en es fr it ko pl pt pt_BR ru uk zh_CN zh_TW; do + find $(brew --prefix sqlb-qt@5)/translations -name "qt_${i}.qm" 2> /dev/null -exec cp {} "$TARGET/Contents/translations/" \; + find $(brew --prefix sqlb-qt@5)/translations -name "qtbase_${i}.qm" 2> /dev/null -exec cp {} "$TARGET/Contents/translations/" \; + find $(brew --prefix sqlb-qt@5)/translations -name "qtmultimedia_${i}.qm" 2> /dev/null -exec cp {} "$TARGET/Contents/translations/" \; + find $(brew --prefix sqlb-qt@5)/translations -name "qtscript_${i}.qm" 2> /dev/null -exec cp {} "$TARGET/Contents/translations/" \; + find $(brew --prefix sqlb-qt@5)/translations -name "qtxmlpatterns_${i}.qm" 2> /dev/null -exec cp {} "$TARGET/Contents/translations/" \; + done +done + +# Copy the icon file to the app bundle +for TARGET in $(find build -name "DB Browser for SQL*.app" | sed -e 's/ /_/g'); do + TARGET=$(echo $TARGET | sed -e 's/_/ /g') + if [ "$NIGHTLY" = "false" ]; then + cp installer/macos/macapp.icns "$TARGET/Contents/Resources/" + /usr/libexec/PlistBuddy -c "Set :CFBundleIconFile macapp.icns" "$TARGET/Contents/Info.plist" + else + cp installer/macos/macapp-nightly.icns "$TARGET/Contents/Resources/" + /usr/libexec/PlistBuddy -c "Set :CFBundleIconFile macapp-nightly.icns" "$TARGET/Contents/Info.plist" + fi +done + +# Sign the manually added extensions +for TARGET in $(find build -name "DB Browser for SQL*.app" | sed -e 's/ /_/g'); do + TARGET=$(echo $TARGET | sed -e 's/_/ /g') + codesign --sign "$DEV_ID" --deep --force --options=runtime --strict --timestamp "$TARGET/Contents/Extensions/formats.dylib" + codesign --sign "$DEV_ID" --deep --force --options=runtime --strict --timestamp "$TARGET/Contents/Extensions/sqlean.dylib" + codesign --sign "$DEV_ID" --deep --force --options=runtime --strict --timestamp "$TARGET" +done + +# Move app bundle to installer folder for DMG creation +mv build/*.app installer/macos + +# Create the DMG +export DATE=$(date +%Y%m%d) + +if [ "$SQLCIPHER" = "true" ]; then + if [ "$NIGHTLY" = "false" ]; then + # Continuous with SQLCipher + sed -i "" 's/"DB Browser for SQLCipher Nightly.app"/"DB Browser for SQLCipher-dev-'$(git rev-parse --short --verify HEAD)'.app"/' installer/macos/sqlcipher-nightly.json + TARGET="DB.Browser.for.SQLCipher-dev-$(git rev-parse --short --verify HEAD).dmg" + else + # Nightly with SQLCipher + TARGET="DB.Browser.for.SQLCipher-universal_$DATE.dmg" + fi + appdmg --quiet installer/macos/sqlcipher-nightly.json "$TARGET" +else + if [ "$NIGHTLY" = "false" ]; then + # Continuous without SQLCipher + sed -i "" 's/"DB Browser for SQLite Nightly.app"/"DB Browser for SQLite-dev-'$(git rev-parse --short --verify HEAD)'.app"/' installer/macos/nightly.json + TARGET="DB.Browser.for.SQLite-dev-$(git rev-parse --short --verify HEAD).dmg" + else + # Nightly without SQLCipher + TARGET="DB.Browser.for.SQLite-universal_$DATE.dmg" + fi + appdmg --quiet installer/macos/nightly.json "$TARGET" +fi + +codesign --sign "$DEV_ID" --verbose --options=runtime --timestamp "$TARGET" +codesign -vvv --deep --strict --verbose=4 "$TARGET" + +# Notarize the dmg +xcrun notarytool submit *.dmg --apple-id $APPLE_ID --password $APPLE_PW --team-id $TEAM_ID --wait + +# Staple the notarization ticket +xcrun stapler staple *.dmg diff --git a/installer/macos/sqlcipher-nightly.json b/installer/macos/sqlcipher-nightly.json new file mode 100644 index 000000000..7334aae4b --- /dev/null +++ b/installer/macos/sqlcipher-nightly.json @@ -0,0 +1,23 @@ +{ + "title": "Install DB4S Nightly build", + "icon": "macapp-nightly.icns", + "icon-size": 128, + "background": "background.png", + "format": "ULFO", + "window": { + "size": { + "width": 500, + "height": 320 + } + }, + "contents": [ + { "x": 90, "y": 180, "type": "file", "path": "DB Browser for SQLCipher Nightly.app" }, + { "x": 395, "y": 180, "type": "link", "path": "/Applications" }, + + { "x": 90, "y": 380, "type": "position", "path": ".background" }, + { "x": 240, "y": 380, "type": "position", "path": ".DS_Store" }, + { "x": 400, "y": 380, "type": "position", "path": ".VolumeIcon.icns" }, + { "x": 90, "y": 530, "type": "position", "path": ".Trashes" } + ] +} + diff --git a/installer/other/get_nightlies_from_github_actions.sh b/installer/other/get_nightlies_from_github_actions.sh new file mode 100644 index 000000000..627540dad --- /dev/null +++ b/installer/other/get_nightlies_from_github_actions.sh @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: (C) 2024 SeongTae Jeong +# This script downloads the daily build output from GitHub Release, built by GitHub Actions, and archives it on our nightly server. + +#!/usr/bin/env bash + +source /root/.gh_token_secure + +set -ex + +echo "$(TZ=UTC date +"%Y-%m-%d %H:%M:%S %Z"): [START]" +DATE=$(date +%Y%m%d) +echo "Clear the incoming directory" +DOWNLOAD_DIR="/tmp/incoming/" +rm -rfv $DOWNLOAD_DIR +mkdir -v $DOWNLOAD_DIR + +if [ $(ls -l /nightlies/appimage /nightlies/appimage-arm64 | grep -c "$DATE") ] && + [ $(ls -l /nightlies/macos-universal | grep -c "$DATE") ] && + [ $(ls -l /nightlies/win32 /nightlies/win64 | grep -c "$DATE") -ne 0 ]; then + echo "Nightly build already exists" + exit 1 +fi + +if ! gh auth login --with-token <<< "$GH_TOKEN"; then + echo "Unable to authenticate with GitHub" +fi +echo "Successfully authenticated with GitHub" + +IS_BUILD_SUCCESS=$(gh run list --created $(date '+%Y-%m-%d') --limit 1 --event "schedule" --status "success" --workflow "CI" --repo "sqlitebrowser/sqlitebrowser" | wc -l) +if [ $IS_BUILD_SUCCESS -eq 0 ]; then + echo "No successful build found" + exit 1 +fi +echo "Found a successful build" + +if ! gh release download --dir /tmp/incoming/ -R "sqlitebrowser/sqlitebrowser" nightly; then + echo "Unable to download the nightly build" +fi +echo "Successfully downloaded the nightly build" + + +# Check if the downloaded files are as expected +# This case is occuring when the nightly build is skipped +if [ $(ls -l $DOWNLOAD_DIR | grep -c "$DATE") -ne 10 ]; then + echo "Last nightly build is skipped" + exit 1 +fi + +mv -v $DOWNLOAD_DIR*x86.64*AppImage /nightlies/appimage/ +mv -v $DOWNLOAD_DIR*aarch64*AppImage /nightlies/appimage-arm64/ +mv -v $DOWNLOAD_DIR*x86* /nightlies/win32/ +mv -v $DOWNLOAD_DIR*x64* /nightlies/win64/ +mv -v $DOWNLOAD_DIR*dmg /nightlies/macos-universal/ + +rm -v /nightlies/latest/*.AppImage +rm -v /nightlies/latest/*.dmg +rm -v /nightlies/latest/*.msi +rm -v /nightlies/latest/*.zip + +ln -sv /nightlies/appimage/DB.Browser.for.SQLCipher-$DATE-x86.64.AppImage /nightlies/latest/DB.Browser.for.SQLCipher-x86.64.AppImage +ln -sv /nightlies/appimage/DB.Browser.for.SQLite-$DATE-x86.64.AppImage /nightlies/latest/DB.Browser.for.SQLite-x86.64.AppImage +ln -sv /nightlies/appimage-arm64/DB.Browser.for.SQLCipher-$DATE-aarch64.AppImage /nightlies/latest/DB.Browser.for.SQLCipher-aarch64.AppImage +ln -sv /nightlies/appimage-arm64/DB.Browser.for.SQLite-$DATE-aarch64.AppImage /nightlies/latest/DB.Browser.for.SQLite-aarch64.AppImage +ln -sv /nightlies/macos-universal/DB.Browser.for.SQLCipher-universal_$DATE.dmg /nightlies/latest/DB.Browser.for.SQLCipher-universal.dmg +ln -sv /nightlies/macos-universal/DB.Browser.for.SQLite-universal_$DATE.dmg /nightlies/latest/DB.Browser.for.SQLite-universal.dmg +ln -sv /nightlies/win32/DB.Browser.for.SQLite-$DATE-x86.msi /nightlies/latest/DB.Browser.for.SQLite-x86.msi +ln -sv /nightlies/win32/DB.Browser.for.SQLite-$DATE-x86.zip /nightlies/latest/DB.Browser.for.SQLite-x86.zip +ln -sv /nightlies/win64/DB.Browser.for.SQLite-$DATE-x64.msi /nightlies/latest/DB.Browser.for.SQLite-x64.msi +ln -sv /nightlies/win64/DB.Browser.for.SQLite-$DATE-x64.zip /nightlies/latest/DB.Browser.for.SQLite-x64.zip + +echo "[STOP]" diff --git a/installer/other/move_nightlies_into_dirs.sh b/installer/other/move_nightlies_into_dirs.sh new file mode 100644 index 000000000..9e5d8ad6e --- /dev/null +++ b/installer/other/move_nightlies_into_dirs.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Moving the nightly builds into appropriate subdirs. Designed to be +# run automatically from cron, using something like this: +# 10 0 14 * * /usr/local/bin/move_nightlies_into_dirs.sh + +# Retrieve the month number for last month +YEARMONTH=`date -d "last month 13:00" '+%Y-%m'` +YEARMONTHOSX=`date -d "last month 13:00" '+%Y%m'` + +# Create appropriate new subfolders +mkdir /nightlies/macos-universal/${YEARMONTH} +mkdir /nightlies/win32/${YEARMONTH} +mkdir /nightlies/win64/${YEARMONTH} + +# Move builds +mv /nightlies/macos-universal/DB*${YEARMONTHOSX}* /nightlies/macos-universal/night*${YEARMONTHOSX}* /nightlies/macos-universal/${YEARMONTH}/ +mv /nightlies/win32/DB*${YEARMONTH}* /nightlies/win32/${YEARMONTH}/ +mv /nightlies/win64/DB*${YEARMONTH}* /nightlies/win64/${YEARMONTH}/ + +# Fix ownership and SELinux context's +chown -Rh nightlies: /nightlies/macos-universal/${YEARMONTH} /nightlies/win32/${YEARMONTH} /nightlies/win64/${YEARMONTH} + +echo Nightlies moved for $YEARMONTH diff --git a/installer/windows/background.bmp b/installer/windows/background.bmp new file mode 100644 index 000000000..821cb5737 Binary files /dev/null and b/installer/windows/background.bmp differ diff --git a/installer/windows/banner.bmp b/installer/windows/banner.bmp new file mode 100644 index 000000000..b4898aa18 Binary files /dev/null and b/installer/windows/banner.bmp differ diff --git a/installer/windows/build.cmd b/installer/windows/build.cmd new file mode 100644 index 000000000..345b73843 --- /dev/null +++ b/installer/windows/build.cmd @@ -0,0 +1,37 @@ +@echo off + +:: Output file name +set MSI=DB.Browser.for.SQLite-%1 + +:: Set the ARCH based on the first parameter +if "%1"=="" ( + echo ERROR: You must select a build type, either "win64" or "win32" + goto :eof +) else if "%1"=="x86" ( + set ARCH=x86 +) else if "%1"=="x64" ( + set ARCH=x64 +) else ( + echo ERROR: Unknown build type="%1" + goto :eof +) + +:: Suppress some ICE checks +:: - 61 (major upgrade) +:: - 03 & 82 (merge module) +:: - 38 & 43 & 57 (non-advertised shortcuts) +set ICE=-sice:ICE03 -sice:ICE82 -sice:ICE61 -sice:ICE38 -sice:ICE43 -sice:ICE57 + +:: Suppress 'light.exe' warning +:: - 1104 (vcredist merge module installer version) +set LIGHT=-sw1104 + +:: Compile & Link +"%WIX%\bin\candle.exe" -nologo -pedantic -arch %ARCH% product.wxs translations.wxs ui.wxs +"%WIX%\bin\light.exe" -sval -nologo -pedantic %LIGHT% %ICE% -ext WixUIExtension -ext WixUtilExtension -cultures:en-us -loc strings.wxl product.wixobj translations.wixobj ui.wixobj -out %MSI%.msi + +:: Cleanup +del product.wixobj +del translations.wixobj +del ui.wixobj +del %MSI%.wixpdb diff --git a/installer/windows/license.rtf b/installer/windows/license.rtf new file mode 100644 index 000000000..2601ae905 --- /dev/null +++ b/installer/windows/license.rtf @@ -0,0 +1,1179 @@ +{\rtf1\ansi\ansicpg1252\cocoartf2761 +\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Arial-BoldMT;\f1\fswiss\fcharset0 ArialMT;} +{\colortbl;\red255\green255\blue255;} +{\*\expandedcolortbl;;} +\paperw11900\paperh16840\margl1440\margr1440\vieww16560\viewh8400\viewkind0 +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 + +\f0\b\fs28 \cf0 DB Browser for SQLite is bi-licensed under the Mozilla Public License\ +Version 2, as well as the GNU General Public License Version 3 or later.\ +\ +Modification or redistribution is permitted under the conditions of these licenses.\ +\ +Check `LICENSE-GPL-3.0` for the full text of the GNU General Public License Version 3.\ +Check `LICENSE-MPL-2.0` for the full text of the Mozilla Public License Version 2.\ +Check `LICENSE-MIT` for the full text of the MIT License. and that is the license for the `nalgeon/sqlean` library.\ +Check `LICENSE-PLUGINS` for other rights regarding included third-party resources. +\f1\b0\fs24 \ +\ + +\f0\b\fs26 LICENSE-GPL-3.0 +\f1\b0\fs24 \ + GNU GENERAL PUBLIC LICENSE\ + Version 3, 29 June 2007\ +\ + Copyright (C) 2007 Free Software Foundation, Inc. \ + Everyone is permitted to copy and distribute verbatim copies\ + of this license document, but changing it is not allowed.\ +\ + Preamble\ +\ + The GNU General Public License is a free, copyleft license for\ +software and other kinds of works.\ +\ + The licenses for most software and other practical works are designed\ +to take away your freedom to share and change the works. By contrast,\ +the GNU General Public License is intended to guarantee your freedom to\ +share and change all versions of a program--to make sure it remains free\ +software for all its users. We, the Free Software Foundation, use the\ +GNU General Public License for most of our software; it applies also to\ +any other work released this way by its authors. You can apply it to\ +your programs, too.\ +\ + When we speak of free software, we are referring to freedom, not\ +price. Our General Public Licenses are designed to make sure that you\ +have the freedom to distribute copies of free software (and charge for\ +them if you wish), that you receive source code or can get it if you\ +want it, that you can change the software or use pieces of it in new\ +free programs, and that you know you can do these things.\ +\ + To protect your rights, we need to prevent others from denying you\ +these rights or asking you to surrender the rights. Therefore, you have\ +certain responsibilities if you distribute copies of the software, or if\ +you modify it: responsibilities to respect the freedom of others.\ +\ + For example, if you distribute copies of such a program, whether\ +gratis or for a fee, you must pass on to the recipients the same\ +freedoms that you received. You must make sure that they, too, receive\ +or can get the source code. And you must show them these terms so they\ +know their rights.\ +\ + Developers that use the GNU GPL protect your rights with two steps:\ +(1) assert copyright on the software, and (2) offer you this License\ +giving you legal permission to copy, distribute and/or modify it.\ +\ + For the developers' and authors' protection, the GPL clearly explains\ +that there is no warranty for this free software. For both users' and\ +authors' sake, the GPL requires that modified versions be marked as\ +changed, so that their problems will not be attributed erroneously to\ +authors of previous versions.\ +\ + Some devices are designed to deny users access to install or run\ +modified versions of the software inside them, although the manufacturer\ +can do so. This is fundamentally incompatible with the aim of\ +protecting users' freedom to change the software. The systematic\ +pattern of such abuse occurs in the area of products for individuals to\ +use, which is precisely where it is most unacceptable. Therefore, we\ +have designed this version of the GPL to prohibit the practice for those\ +products. If such problems arise substantially in other domains, we\ +stand ready to extend this provision to those domains in future versions\ +of the GPL, as needed to protect the freedom of users.\ +\ + Finally, every program is threatened constantly by software patents.\ +States should not allow patents to restrict development and use of\ +software on general-purpose computers, but in those that do, we wish to\ +avoid the special danger that patents applied to a free program could\ +make it effectively proprietary. To prevent this, the GPL assures that\ +patents cannot be used to render the program non-free.\ +\ + The precise terms and conditions for copying, distribution and\ +modification follow.\ +\ + TERMS AND CONDITIONS\ +\ + 0. Definitions.\ +\ + "This License" refers to version 3 of the GNU General Public License.\ +\ + "Copyright" also means copyright-like laws that apply to other kinds of\ +works, such as semiconductor masks.\ +\ + "The Program" refers to any copyrightable work licensed under this\ +License. Each licensee is addressed as "you". "Licensees" and\ +"recipients" may be individuals or organizations.\ +\ + To "modify" a work means to copy from or adapt all or part of the work\ +in a fashion requiring copyright permission, other than the making of an\ +exact copy. The resulting work is called a "modified version" of the\ +earlier work or a work "based on" the earlier work.\ +\ + A "covered work" means either the unmodified Program or a work based\ +on the Program.\ +\ + To "propagate" a work means to do anything with it that, without\ +permission, would make you directly or secondarily liable for\ +infringement under applicable copyright law, except executing it on a\ +computer or modifying a private copy. Propagation includes copying,\ +distribution (with or without modification), making available to the\ +public, and in some countries other activities as well.\ +\ + To "convey" a work means any kind of propagation that enables other\ +parties to make or receive copies. Mere interaction with a user through\ +a computer network, with no transfer of a copy, is not conveying.\ +\ + An interactive user interface displays "Appropriate Legal Notices"\ +to the extent that it includes a convenient and prominently visible\ +feature that (1) displays an appropriate copyright notice, and (2)\ +tells the user that there is no warranty for the work (except to the\ +extent that warranties are provided), that licensees may convey the\ +work under this License, and how to view a copy of this License. If\ +the interface presents a list of user commands or options, such as a\ +menu, a prominent item in the list meets this criterion.\ +\ + 1. Source Code.\ +\ + The "source code" for a work means the preferred form of the work\ +for making modifications to it. "Object code" means any non-source\ +form of a work.\ +\ + A "Standard Interface" means an interface that either is an official\ +standard defined by a recognized standards body, or, in the case of\ +interfaces specified for a particular programming language, one that\ +is widely used among developers working in that language.\ +\ + The "System Libraries" of an executable work include anything, other\ +than the work as a whole, that (a) is included in the normal form of\ +packaging a Major Component, but which is not part of that Major\ +Component, and (b) serves only to enable use of the work with that\ +Major Component, or to implement a Standard Interface for which an\ +implementation is available to the public in source code form. A\ +"Major Component", in this context, means a major essential component\ +(kernel, window system, and so on) of the specific operating system\ +(if any) on which the executable work runs, or a compiler used to\ +produce the work, or an object code interpreter used to run it.\ +\ + The "Corresponding Source" for a work in object code form means all\ +the source code needed to generate, install, and (for an executable\ +work) run the object code and to modify the work, including scripts to\ +control those activities. However, it does not include the work's\ +System Libraries, or general-purpose tools or generally available free\ +programs which are used unmodified in performing those activities but\ +which are not part of the work. For example, Corresponding Source\ +includes interface definition files associated with source files for\ +the work, and the source code for shared libraries and dynamically\ +linked subprograms that the work is specifically designed to require,\ +such as by intimate data communication or control flow between those\ +subprograms and other parts of the work.\ +\ + The Corresponding Source need not include anything that users\ +can regenerate automatically from other parts of the Corresponding\ +Source.\ +\ + The Corresponding Source for a work in source code form is that\ +same work.\ +\ + 2. Basic Permissions.\ +\ + All rights granted under this License are granted for the term of\ +copyright on the Program, and are irrevocable provided the stated\ +conditions are met. This License explicitly affirms your unlimited\ +permission to run the unmodified Program. The output from running a\ +covered work is covered by this License only if the output, given its\ +content, constitutes a covered work. This License acknowledges your\ +rights of fair use or other equivalent, as provided by copyright law.\ +\ + You may make, run and propagate covered works that you do not\ +convey, without conditions so long as your license otherwise remains\ +in force. You may convey covered works to others for the sole purpose\ +of having them make modifications exclusively for you, or provide you\ +with facilities for running those works, provided that you comply with\ +the terms of this License in conveying all material for which you do\ +not control copyright. Those thus making or running the covered works\ +for you must do so exclusively on your behalf, under your direction\ +and control, on terms that prohibit them from making any copies of\ +your copyrighted material outside their relationship with you.\ +\ + Conveying under any other circumstances is permitted solely under\ +the conditions stated below. Sublicensing is not allowed; section 10\ +makes it unnecessary.\ +\ + 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\ +\ + No covered work shall be deemed part of an effective technological\ +measure under any applicable law fulfilling obligations under article\ +11 of the WIPO copyright treaty adopted on 20 December 1996, or\ +similar laws prohibiting or restricting circumvention of such\ +measures.\ +\ + When you convey a covered work, you waive any legal power to forbid\ +circumvention of technological measures to the extent such circumvention\ +is effected by exercising rights under this License with respect to\ +the covered work, and you disclaim any intention to limit operation or\ +modification of the work as a means of enforcing, against the work's\ +users, your or third parties' legal rights to forbid circumvention of\ +technological measures.\ +\ + 4. Conveying Verbatim Copies.\ +\ + You may convey verbatim copies of the Program's source code as you\ +receive it, in any medium, provided that you conspicuously and\ +appropriately publish on each copy an appropriate copyright notice;\ +keep intact all notices stating that this License and any\ +non-permissive terms added in accord with section 7 apply to the code;\ +keep intact all notices of the absence of any warranty; and give all\ +recipients a copy of this License along with the Program.\ +\ + You may charge any price or no price for each copy that you convey,\ +and you may offer support or warranty protection for a fee.\ +\ + 5. Conveying Modified Source Versions.\ +\ + You may convey a work based on the Program, or the modifications to\ +produce it from the Program, in the form of source code under the\ +terms of section 4, provided that you also meet all of these conditions:\ +\ + a) The work must carry prominent notices stating that you modified\ + it, and giving a relevant date.\ +\ + b) The work must carry prominent notices stating that it is\ + released under this License and any conditions added under section\ + 7. This requirement modifies the requirement in section 4 to\ + "keep intact all notices".\ +\ + c) You must license the entire work, as a whole, under this\ + License to anyone who comes into possession of a copy. This\ + License will therefore apply, along with any applicable section 7\ + additional terms, to the whole of the work, and all its parts,\ + regardless of how they are packaged. This License gives no\ + permission to license the work in any other way, but it does not\ + invalidate such permission if you have separately received it.\ +\ + d) If the work has interactive user interfaces, each must display\ + Appropriate Legal Notices; however, if the Program has interactive\ + interfaces that do not display Appropriate Legal Notices, your\ + work need not make them do so.\ +\ + A compilation of a covered work with other separate and independent\ +works, which are not by their nature extensions of the covered work,\ +and which are not combined with it such as to form a larger program,\ +in or on a volume of a storage or distribution medium, is called an\ +"aggregate" if the compilation and its resulting copyright are not\ +used to limit the access or legal rights of the compilation's users\ +beyond what the individual works permit. Inclusion of a covered work\ +in an aggregate does not cause this License to apply to the other\ +parts of the aggregate.\ +\ + 6. Conveying Non-Source Forms.\ +\ + You may convey a covered work in object code form under the terms\ +of sections 4 and 5, provided that you also convey the\ +machine-readable Corresponding Source under the terms of this License,\ +in one of these ways:\ +\ + a) Convey the object code in, or embodied in, a physical product\ + (including a physical distribution medium), accompanied by the\ + Corresponding Source fixed on a durable physical medium\ + customarily used for software interchange.\ +\ + b) Convey the object code in, or embodied in, a physical product\ + (including a physical distribution medium), accompanied by a\ + written offer, valid for at least three years and valid for as\ + long as you offer spare parts or customer support for that product\ + model, to give anyone who possesses the object code either (1) a\ + copy of the Corresponding Source for all the software in the\ + product that is covered by this License, on a durable physical\ + medium customarily used for software interchange, for a price no\ + more than your reasonable cost of physically performing this\ + conveying of source, or (2) access to copy the\ + Corresponding Source from a network server at no charge.\ +\ + c) Convey individual copies of the object code with a copy of the\ + written offer to provide the Corresponding Source. This\ + alternative is allowed only occasionally and noncommercially, and\ + only if you received the object code with such an offer, in accord\ + with subsection 6b.\ +\ + d) Convey the object code by offering access from a designated\ + place (gratis or for a charge), and offer equivalent access to the\ + Corresponding Source in the same way through the same place at no\ + further charge. You need not require recipients to copy the\ + Corresponding Source along with the object code. If the place to\ + copy the object code is a network server, the Corresponding Source\ + may be on a different server (operated by you or a third party)\ + that supports equivalent copying facilities, provided you maintain\ + clear directions next to the object code saying where to find the\ + Corresponding Source. Regardless of what server hosts the\ + Corresponding Source, you remain obligated to ensure that it is\ + available for as long as needed to satisfy these requirements.\ +\ + e) Convey the object code using peer-to-peer transmission, provided\ + you inform other peers where the object code and Corresponding\ + Source of the work are being offered to the general public at no\ + charge under subsection 6d.\ +\ + A separable portion of the object code, whose source code is excluded\ +from the Corresponding Source as a System Library, need not be\ +included in conveying the object code work.\ +\ + A "User Product" is either (1) a "consumer product", which means any\ +tangible personal property which is normally used for personal, family,\ +or household purposes, or (2) anything designed or sold for incorporation\ +into a dwelling. In determining whether a product is a consumer product,\ +doubtful cases shall be resolved in favor of coverage. For a particular\ +product received by a particular user, "normally used" refers to a\ +typical or common use of that class of product, regardless of the status\ +of the particular user or of the way in which the particular user\ +actually uses, or expects or is expected to use, the product. A product\ +is a consumer product regardless of whether the product has substantial\ +commercial, industrial or non-consumer uses, unless such uses represent\ +the only significant mode of use of the product.\ +\ + "Installation Information" for a User Product means any methods,\ +procedures, authorization keys, or other information required to install\ +and execute modified versions of a covered work in that User Product from\ +a modified version of its Corresponding Source. The information must\ +suffice to ensure that the continued functioning of the modified object\ +code is in no case prevented or interfered with solely because\ +modification has been made.\ +\ + If you convey an object code work under this section in, or with, or\ +specifically for use in, a User Product, and the conveying occurs as\ +part of a transaction in which the right of possession and use of the\ +User Product is transferred to the recipient in perpetuity or for a\ +fixed term (regardless of how the transaction is characterized), the\ +Corresponding Source conveyed under this section must be accompanied\ +by the Installation Information. But this requirement does not apply\ +if neither you nor any third party retains the ability to install\ +modified object code on the User Product (for example, the work has\ +been installed in ROM).\ +\ + The requirement to provide Installation Information does not include a\ +requirement to continue to provide support service, warranty, or updates\ +for a work that has been modified or installed by the recipient, or for\ +the User Product in which it has been modified or installed. Access to a\ +network may be denied when the modification itself materially and\ +adversely affects the operation of the network or violates the rules and\ +protocols for communication across the network.\ +\ + Corresponding Source conveyed, and Installation Information provided,\ +in accord with this section must be in a format that is publicly\ +documented (and with an implementation available to the public in\ +source code form), and must require no special password or key for\ +unpacking, reading or copying.\ +\ + 7. Additional Terms.\ +\ + "Additional permissions" are terms that supplement the terms of this\ +License by making exceptions from one or more of its conditions.\ +Additional permissions that are applicable to the entire Program shall\ +be treated as though they were included in this License, to the extent\ +that they are valid under applicable law. If additional permissions\ +apply only to part of the Program, that part may be used separately\ +under those permissions, but the entire Program remains governed by\ +this License without regard to the additional permissions.\ +\ + When you convey a copy of a covered work, you may at your option\ +remove any additional permissions from that copy, or from any part of\ +it. (Additional permissions may be written to require their own\ +removal in certain cases when you modify the work.) You may place\ +additional permissions on material, added by you to a covered work,\ +for which you have or can give appropriate copyright permission.\ +\ + Notwithstanding any other provision of this License, for material you\ +add to a covered work, you may (if authorized by the copyright holders of\ +that material) supplement the terms of this License with terms:\ +\ + a) Disclaiming warranty or limiting liability differently from the\ + terms of sections 15 and 16 of this License; or\ +\ + b) Requiring preservation of specified reasonable legal notices or\ + author attributions in that material or in the Appropriate Legal\ + Notices displayed by works containing it; or\ +\ + c) Prohibiting misrepresentation of the origin of that material, or\ + requiring that modified versions of such material be marked in\ + reasonable ways as different from the original version; or\ +\ + d) Limiting the use for publicity purposes of names of licensors or\ + authors of the material; or\ +\ + e) Declining to grant rights under trademark law for use of some\ + trade names, trademarks, or service marks; or\ +\ + f) Requiring indemnification of licensors and authors of that\ + material by anyone who conveys the material (or modified versions of\ + it) with contractual assumptions of liability to the recipient, for\ + any liability that these contractual assumptions directly impose on\ + those licensors and authors.\ +\ + All other non-permissive additional terms are considered "further\ +restrictions" within the meaning of section 10. If the Program as you\ +received it, or any part of it, contains a notice stating that it is\ +governed by this License along with a term that is a further\ +restriction, you may remove that term. If a license document contains\ +a further restriction but permits relicensing or conveying under this\ +License, you may add to a covered work material governed by the terms\ +of that license document, provided that the further restriction does\ +not survive such relicensing or conveying.\ +\ + If you add terms to a covered work in accord with this section, you\ +must place, in the relevant source files, a statement of the\ +additional terms that apply to those files, or a notice indicating\ +where to find the applicable terms.\ +\ + Additional terms, permissive or non-permissive, may be stated in the\ +form of a separately written license, or stated as exceptions;\ +the above requirements apply either way.\ +\ + 8. Termination.\ +\ + You may not propagate or modify a covered work except as expressly\ +provided under this License. Any attempt otherwise to propagate or\ +modify it is void, and will automatically terminate your rights under\ +this License (including any patent licenses granted under the third\ +paragraph of section 11).\ +\ + However, if you cease all violation of this License, then your\ +license from a particular copyright holder is reinstated (a)\ +provisionally, unless and until the copyright holder explicitly and\ +finally terminates your license, and (b) permanently, if the copyright\ +holder fails to notify you of the violation by some reasonable means\ +prior to 60 days after the cessation.\ +\ + Moreover, your license from a particular copyright holder is\ +reinstated permanently if the copyright holder notifies you of the\ +violation by some reasonable means, this is the first time you have\ +received notice of violation of this License (for any work) from that\ +copyright holder, and you cure the violation prior to 30 days after\ +your receipt of the notice.\ +\ + Termination of your rights under this section does not terminate the\ +licenses of parties who have received copies or rights from you under\ +this License. If your rights have been terminated and not permanently\ +reinstated, you do not qualify to receive new licenses for the same\ +material under section 10.\ +\ + 9. Acceptance Not Required for Having Copies.\ +\ + You are not required to accept this License in order to receive or\ +run a copy of the Program. Ancillary propagation of a covered work\ +occurring solely as a consequence of using peer-to-peer transmission\ +to receive a copy likewise does not require acceptance. However,\ +nothing other than this License grants you permission to propagate or\ +modify any covered work. These actions infringe copyright if you do\ +not accept this License. Therefore, by modifying or propagating a\ +covered work, you indicate your acceptance of this License to do so.\ +\ + 10. Automatic Licensing of Downstream Recipients.\ +\ + Each time you convey a covered work, the recipient automatically\ +receives a license from the original licensors, to run, modify and\ +propagate that work, subject to this License. You are not responsible\ +for enforcing compliance by third parties with this License.\ +\ + An "entity transaction" is a transaction transferring control of an\ +organization, or substantially all assets of one, or subdividing an\ +organization, or merging organizations. If propagation of a covered\ +work results from an entity transaction, each party to that\ +transaction who receives a copy of the work also receives whatever\ +licenses to the work the party's predecessor in interest had or could\ +give under the previous paragraph, plus a right to possession of the\ +Corresponding Source of the work from the predecessor in interest, if\ +the predecessor has it or can get it with reasonable efforts.\ +\ + You may not impose any further restrictions on the exercise of the\ +rights granted or affirmed under this License. For example, you may\ +not impose a license fee, royalty, or other charge for exercise of\ +rights granted under this License, and you may not initiate litigation\ +(including a cross-claim or counterclaim in a lawsuit) alleging that\ +any patent claim is infringed by making, using, selling, offering for\ +sale, or importing the Program or any portion of it.\ +\ + 11. Patents.\ +\ + A "contributor" is a copyright holder who authorizes use under this\ +License of the Program or a work on which the Program is based. The\ +work thus licensed is called the contributor's "contributor version".\ +\ + A contributor's "essential patent claims" are all patent claims\ +owned or controlled by the contributor, whether already acquired or\ +hereafter acquired, that would be infringed by some manner, permitted\ +by this License, of making, using, or selling its contributor version,\ +but do not include claims that would be infringed only as a\ +consequence of further modification of the contributor version. For\ +purposes of this definition, "control" includes the right to grant\ +patent sublicenses in a manner consistent with the requirements of\ +this License.\ +\ + Each contributor grants you a non-exclusive, worldwide, royalty-free\ +patent license under the contributor's essential patent claims, to\ +make, use, sell, offer for sale, import and otherwise run, modify and\ +propagate the contents of its contributor version.\ +\ + In the following three paragraphs, a "patent license" is any express\ +agreement or commitment, however denominated, not to enforce a patent\ +(such as an express permission to practice a patent or covenant not to\ +sue for patent infringement). To "grant" such a patent license to a\ +party means to make such an agreement or commitment not to enforce a\ +patent against the party.\ +\ + If you convey a covered work, knowingly relying on a patent license,\ +and the Corresponding Source of the work is not available for anyone\ +to copy, free of charge and under the terms of this License, through a\ +publicly available network server or other readily accessible means,\ +then you must either (1) cause the Corresponding Source to be so\ +available, or (2) arrange to deprive yourself of the benefit of the\ +patent license for this particular work, or (3) arrange, in a manner\ +consistent with the requirements of this License, to extend the patent\ +license to downstream recipients. "Knowingly relying" means you have\ +actual knowledge that, but for the patent license, your conveying the\ +covered work in a country, or your recipient's use of the covered work\ +in a country, would infringe one or more identifiable patents in that\ +country that you have reason to believe are valid.\ +\ + If, pursuant to or in connection with a single transaction or\ +arrangement, you convey, or propagate by procuring conveyance of, a\ +covered work, and grant a patent license to some of the parties\ +receiving the covered work authorizing them to use, propagate, modify\ +or convey a specific copy of the covered work, then the patent license\ +you grant is automatically extended to all recipients of the covered\ +work and works based on it.\ +\ + A patent license is "discriminatory" if it does not include within\ +the scope of its coverage, prohibits the exercise of, or is\ +conditioned on the non-exercise of one or more of the rights that are\ +specifically granted under this License. You may not convey a covered\ +work if you are a party to an arrangement with a third party that is\ +in the business of distributing software, under which you make payment\ +to the third party based on the extent of your activity of conveying\ +the work, and under which the third party grants, to any of the\ +parties who would receive the covered work from you, a discriminatory\ +patent license (a) in connection with copies of the covered work\ +conveyed by you (or copies made from those copies), or (b) primarily\ +for and in connection with specific products or compilations that\ +contain the covered work, unless you entered into that arrangement,\ +or that patent license was granted, prior to 28 March 2007.\ +\ + Nothing in this License shall be construed as excluding or limiting\ +any implied license or other defenses to infringement that may\ +otherwise be available to you under applicable patent law.\ +\ + 12. No Surrender of Others' Freedom.\ +\ + If conditions are imposed on you (whether by court order, agreement or\ +otherwise) that contradict the conditions of this License, they do not\ +excuse you from the conditions of this License. If you cannot convey a\ +covered work so as to satisfy simultaneously your obligations under this\ +License and any other pertinent obligations, then as a consequence you may\ +not convey it at all. For example, if you agree to terms that obligate you\ +to collect a royalty for further conveying from those to whom you convey\ +the Program, the only way you could satisfy both those terms and this\ +License would be to refrain entirely from conveying the Program.\ +\ + 13. Use with the GNU Affero General Public License.\ +\ + Notwithstanding any other provision of this License, you have\ +permission to link or combine any covered work with a work licensed\ +under version 3 of the GNU Affero General Public License into a single\ +combined work, and to convey the resulting work. The terms of this\ +License will continue to apply to the part which is the covered work,\ +but the special requirements of the GNU Affero General Public License,\ +section 13, concerning interaction through a network will apply to the\ +combination as such.\ +\ + 14. Revised Versions of this License.\ +\ + The Free Software Foundation may publish revised and/or new versions of\ +the GNU General Public License from time to time. Such new versions will\ +be similar in spirit to the present version, but may differ in detail to\ +address new problems or concerns.\ +\ + Each version is given a distinguishing version number. If the\ +Program specifies that a certain numbered version of the GNU General\ +Public License "or any later version" applies to it, you have the\ +option of following the terms and conditions either of that numbered\ +version or of any later version published by the Free Software\ +Foundation. If the Program does not specify a version number of the\ +GNU General Public License, you may choose any version ever published\ +by the Free Software Foundation.\ +\ + If the Program specifies that a proxy can decide which future\ +versions of the GNU General Public License can be used, that proxy's\ +public statement of acceptance of a version permanently authorizes you\ +to choose that version for the Program.\ +\ + Later license versions may give you additional or different\ +permissions. However, no additional obligations are imposed on any\ +author or copyright holder as a result of your choosing to follow a\ +later version.\ +\ + 15. Disclaimer of Warranty.\ +\ + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\ +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\ +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY\ +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\ +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\ +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\ +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\ +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\ +\ + 16. Limitation of Liability.\ +\ + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\ +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\ +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\ +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\ +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\ +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\ +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\ +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\ +SUCH DAMAGES.\ +\ + 17. Interpretation of Sections 15 and 16.\ +\ + If the disclaimer of warranty and limitation of liability provided\ +above cannot be given local legal effect according to their terms,\ +reviewing courts shall apply local law that most closely approximates\ +an absolute waiver of all civil liability in connection with the\ +Program, unless a warranty or assumption of liability accompanies a\ +copy of the Program in return for a fee.\ +\ + END OF TERMS AND CONDITIONS\ +\ + How to Apply These Terms to Your New Programs\ +\ + If you develop a new program, and you want it to be of the greatest\ +possible use to the public, the best way to achieve this is to make it\ +free software which everyone can redistribute and change under these terms.\ +\ + To do so, attach the following notices to the program. It is safest\ +to attach them to the start of each source file to most effectively\ +state the exclusion of warranty; and each file should have at least\ +the "copyright" line and a pointer to where the full notice is found.\ +\ + \ + Copyright (C) \ +\ + This program is free software: you can redistribute it and/or modify\ + it under the terms of the GNU General Public License as published by\ + the Free Software Foundation, either version 3 of the License, or\ + (at your option) any later version.\ +\ + This program is distributed in the hope that it will be useful,\ + but WITHOUT ANY WARRANTY; without even the implied warranty of\ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\ + GNU General Public License for more details.\ +\ + You should have received a copy of the GNU General Public License\ + along with this program. If not, see .\ +\ +Also add information on how to contact you by electronic and paper mail.\ +\ + If the program does terminal interaction, make it output a short\ +notice like this when it starts in an interactive mode:\ +\ + Copyright (C) \ + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\ + This is free software, and you are welcome to redistribute it\ + under certain conditions; type `show c' for details.\ +\ +The hypothetical commands `show w' and `show c' should show the appropriate\ +parts of the General Public License. Of course, your program's commands\ +might be different; for a GUI interface, you would use an "about box".\ +\ + You should also get your employer (if you work as a programmer) or school,\ +if any, to sign a "copyright disclaimer" for the program, if necessary.\ +For more information on this, and how to apply and follow the GNU GPL, see\ +.\ +\ + The GNU General Public License does not permit incorporating your program\ +into proprietary programs. If your program is a subroutine library, you\ +may consider it more useful to permit linking proprietary applications with\ +the library. If this is what you want to do, use the GNU Lesser General\ +Public License instead of this License. But first, please read\ +.\ +\ + +\f0\b\fs26 LICENSE-MPL-2.0 +\f1\b0\fs24 \ +Mozilla Public License Version 2.0\ +==================================\ +\ +1. Definitions\ +--------------\ +\ +1.1. "Contributor"\ + means each individual or legal entity that creates, contributes to\ + the creation of, or owns Covered Software.\ +\ +1.2. "Contributor Version"\ + means the combination of the Contributions of others (if any) used\ + by a Contributor and that particular Contributor's Contribution.\ +\ +1.3. "Contribution"\ + means Covered Software of a particular Contributor.\ +\ +1.4. "Covered Software"\ + means Source Code Form to which the initial Contributor has attached\ + the notice in Exhibit A, the Executable Form of such Source Code\ + Form, and Modifications of such Source Code Form, in each case\ + including portions thereof.\ +\ +1.5. "Incompatible With Secondary Licenses"\ + means\ +\ + (a) that the initial Contributor has attached the notice described\ + in Exhibit B to the Covered Software; or\ +\ + (b) that the Covered Software was made available under the terms of\ + version 1.1 or earlier of the License, but not also under the\ + terms of a Secondary License.\ +\ +1.6. "Executable Form"\ + means any form of the work other than Source Code Form.\ +\ +1.7. "Larger Work"\ + means a work that combines Covered Software with other material, in\ + a separate file or files, that is not Covered Software.\ +\ +1.8. "License"\ + means this document.\ +\ +1.9. "Licensable"\ + means having the right to grant, to the maximum extent possible,\ + whether at the time of the initial grant or subsequently, any and\ + all of the rights conveyed by this License.\ +\ +1.10. "Modifications"\ + means any of the following:\ +\ + (a) any file in Source Code Form that results from an addition to,\ + deletion from, or modification of the contents of Covered\ + Software; or\ +\ + (b) any new file in Source Code Form that contains any Covered\ + Software.\ +\ +1.11. "Patent Claims" of a Contributor\ + means any patent claim(s), including without limitation, method,\ + process, and apparatus claims, in any patent Licensable by such\ + Contributor that would be infringed, but for the grant of the\ + License, by the making, using, selling, offering for sale, having\ + made, import, or transfer of either its Contributions or its\ + Contributor Version.\ +\ +1.12. "Secondary License"\ + means either the GNU General Public License, Version 2.0, the GNU\ + Lesser General Public License, Version 2.1, the GNU Affero General\ + Public License, Version 3.0, or any later versions of those\ + licenses.\ +\ +1.13. "Source Code Form"\ + means the form of the work preferred for making modifications.\ +\ +1.14. "You" (or "Your")\ + means an individual or a legal entity exercising rights under this\ + License. For legal entities, "You" includes any entity that\ + controls, is controlled by, or is under common control with You. For\ + purposes of this definition, "control" means (a) the power, direct\ + or indirect, to cause the direction or management of such entity,\ + whether by contract or otherwise, or (b) ownership of more than\ + fifty percent (50%) of the outstanding shares or beneficial\ + ownership of such entity.\ +\ +2. License Grants and Conditions\ +--------------------------------\ +\ +2.1. Grants\ +\ +Each Contributor hereby grants You a world-wide, royalty-free,\ +non-exclusive license:\ +\ +(a) under intellectual property rights (other than patent or trademark)\ + Licensable by such Contributor to use, reproduce, make available,\ + modify, display, perform, distribute, and otherwise exploit its\ + Contributions, either on an unmodified basis, with Modifications, or\ + as part of a Larger Work; and\ +\ +(b) under Patent Claims of such Contributor to make, use, sell, offer\ + for sale, have made, import, and otherwise transfer either its\ + Contributions or its Contributor Version.\ +\ +2.2. Effective Date\ +\ +The licenses granted in Section 2.1 with respect to any Contribution\ +become effective for each Contribution on the date the Contributor first\ +distributes such Contribution.\ +\ +2.3. Limitations on Grant Scope\ +\ +The licenses granted in this Section 2 are the only rights granted under\ +this License. No additional rights or licenses will be implied from the\ +distribution or licensing of Covered Software under this License.\ +Notwithstanding Section 2.1(b) above, no patent license is granted by a\ +Contributor:\ +\ +(a) for any code that a Contributor has removed from Covered Software;\ + or\ +\ +(b) for infringements caused by: (i) Your and any other third party's\ + modifications of Covered Software, or (ii) the combination of its\ + Contributions with other software (except as part of its Contributor\ + Version); or\ +\ +(c) under Patent Claims infringed by Covered Software in the absence of\ + its Contributions.\ +\ +This License does not grant any rights in the trademarks, service marks,\ +or logos of any Contributor (except as may be necessary to comply with\ +the notice requirements in Section 3.4).\ +\ +2.4. Subsequent Licenses\ +\ +No Contributor makes additional grants as a result of Your choice to\ +distribute the Covered Software under a subsequent version of this\ +License (see Section 10.2) or under the terms of a Secondary License (if\ +permitted under the terms of Section 3.3).\ +\ +2.5. Representation\ +\ +Each Contributor represents that the Contributor believes its\ +Contributions are its original creation(s) or it has sufficient rights\ +to grant the rights to its Contributions conveyed by this License.\ +\ +2.6. Fair Use\ +\ +This License is not intended to limit any rights You have under\ +applicable copyright doctrines of fair use, fair dealing, or other\ +equivalents.\ +\ +2.7. Conditions\ +\ +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted\ +in Section 2.1.\ +\ +3. Responsibilities\ +-------------------\ +\ +3.1. Distribution of Source Form\ +\ +All distribution of Covered Software in Source Code Form, including any\ +Modifications that You create or to which You contribute, must be under\ +the terms of this License. You must inform recipients that the Source\ +Code Form of the Covered Software is governed by the terms of this\ +License, and how they can obtain a copy of this License. You may not\ +attempt to alter or restrict the recipients' rights in the Source Code\ +Form.\ +\ +3.2. Distribution of Executable Form\ +\ +If You distribute Covered Software in Executable Form then:\ +\ +(a) such Covered Software must also be made available in Source Code\ + Form, as described in Section 3.1, and You must inform recipients of\ + the Executable Form how they can obtain a copy of such Source Code\ + Form by reasonable means in a timely manner, at a charge no more\ + than the cost of distribution to the recipient; and\ +\ +(b) You may distribute such Executable Form under the terms of this\ + License, or sublicense it under different terms, provided that the\ + license for the Executable Form does not attempt to limit or alter\ + the recipients' rights in the Source Code Form under this License.\ +\ +3.3. Distribution of a Larger Work\ +\ +You may create and distribute a Larger Work under terms of Your choice,\ +provided that You also comply with the requirements of this License for\ +the Covered Software. If the Larger Work is a combination of Covered\ +Software with a work governed by one or more Secondary Licenses, and the\ +Covered Software is not Incompatible With Secondary Licenses, this\ +License permits You to additionally distribute such Covered Software\ +under the terms of such Secondary License(s), so that the recipient of\ +the Larger Work may, at their option, further distribute the Covered\ +Software under the terms of either this License or such Secondary\ +License(s).\ +\ +3.4. Notices\ +\ +You may not remove or alter the substance of any license notices\ +(including copyright notices, patent notices, disclaimers of warranty,\ +or limitations of liability) contained within the Source Code Form of\ +the Covered Software, except that You may alter any license notices to\ +the extent required to remedy known factual inaccuracies.\ +\ +3.5. Application of Additional Terms\ +\ +You may choose to offer, and to charge a fee for, warranty, support,\ +indemnity or liability obligations to one or more recipients of Covered\ +Software. However, You may do so only on Your own behalf, and not on\ +behalf of any Contributor. You must make it absolutely clear that any\ +such warranty, support, indemnity, or liability obligation is offered by\ +You alone, and You hereby agree to indemnify every Contributor for any\ +liability incurred by such Contributor as a result of warranty, support,\ +indemnity or liability terms You offer. You may include additional\ +disclaimers of warranty and limitations of liability specific to any\ +jurisdiction.\ +\ +4. Inability to Comply Due to Statute or Regulation\ +---------------------------------------------------\ +\ +If it is impossible for You to comply with any of the terms of this\ +License with respect to some or all of the Covered Software due to\ +statute, judicial order, or regulation then You must: (a) comply with\ +the terms of this License to the maximum extent possible; and (b)\ +describe the limitations and the code they affect. Such description must\ +be placed in a text file included with all distributions of the Covered\ +Software under this License. Except to the extent prohibited by statute\ +or regulation, such description must be sufficiently detailed for a\ +recipient of ordinary skill to be able to understand it.\ +\ +5. Termination\ +--------------\ +\ +5.1. The rights granted under this License will terminate automatically\ +if You fail to comply with any of its terms. However, if You become\ +compliant, then the rights granted under this License from a particular\ +Contributor are reinstated (a) provisionally, unless and until such\ +Contributor explicitly and finally terminates Your grants, and (b) on an\ +ongoing basis, if such Contributor fails to notify You of the\ +non-compliance by some reasonable means prior to 60 days after You have\ +come back into compliance. Moreover, Your grants from a particular\ +Contributor are reinstated on an ongoing basis if such Contributor\ +notifies You of the non-compliance by some reasonable means, this is the\ +first time You have received notice of non-compliance with this License\ +from such Contributor, and You become compliant prior to 30 days after\ +Your receipt of the notice.\ +\ +5.2. If You initiate litigation against any entity by asserting a patent\ +infringement claim (excluding declaratory judgment actions,\ +counter-claims, and cross-claims) alleging that a Contributor Version\ +directly or indirectly infringes any patent, then the rights granted to\ +You by any and all Contributors for the Covered Software under Section\ +2.1 of this License shall terminate.\ +\ +5.3. In the event of termination under Sections 5.1 or 5.2 above, all\ +end user license agreements (excluding distributors and resellers) which\ +have been validly granted by You or Your distributors under this License\ +prior to termination shall survive termination.\ +\ +************************************************************************\ +* *\ +* 6. Disclaimer of Warranty *\ +* ------------------------- *\ +* *\ +* Covered Software is provided under this License on an "as is" *\ +* basis, without warranty of any kind, either expressed, implied, or *\ +* statutory, including, without limitation, warranties that the *\ +* Covered Software is free of defects, merchantable, fit for a *\ +* particular purpose or non-infringing. The entire risk as to the *\ +* quality and performance of the Covered Software is with You. *\ +* Should any Covered Software prove defective in any respect, You *\ +* (not any Contributor) assume the cost of any necessary servicing, *\ +* repair, or correction. This disclaimer of warranty constitutes an *\ +* essential part of this License. No use of any Covered Software is *\ +* authorized under this License except under this disclaimer. *\ +* *\ +************************************************************************\ +\ +************************************************************************\ +* *\ +* 7. Limitation of Liability *\ +* -------------------------- *\ +* *\ +* Under no circumstances and under no legal theory, whether tort *\ +* (including negligence), contract, or otherwise, shall any *\ +* Contributor, or anyone who distributes Covered Software as *\ +* permitted above, be liable to You for any direct, indirect, *\ +* special, incidental, or consequential damages of any character *\ +* including, without limitation, damages for lost profits, loss of *\ +* goodwill, work stoppage, computer failure or malfunction, or any *\ +* and all other commercial damages or losses, even if such party *\ +* shall have been informed of the possibility of such damages. This *\ +* limitation of liability shall not apply to liability for death or *\ +* personal injury resulting from such party's negligence to the *\ +* extent applicable law prohibits such limitation. Some *\ +* jurisdictions do not allow the exclusion or limitation of *\ +* incidental or consequential damages, so this exclusion and *\ +* limitation may not apply to You. *\ +* *\ +************************************************************************\ +\ +8. Litigation\ +-------------\ +\ +Any litigation relating to this License may be brought only in the\ +courts of a jurisdiction where the defendant maintains its principal\ +place of business and such litigation shall be governed by laws of that\ +jurisdiction, without reference to its conflict-of-law provisions.\ +Nothing in this Section shall prevent a party's ability to bring\ +cross-claims or counter-claims.\ +\ +9. Miscellaneous\ +----------------\ +\ +This License represents the complete agreement concerning the subject\ +matter hereof. If any provision of this License is held to be\ +unenforceable, such provision shall be reformed only to the extent\ +necessary to make it enforceable. Any law or regulation which provides\ +that the language of a contract shall be construed against the drafter\ +shall not be used to construe this License against a Contributor.\ +\ +10. Versions of the License\ +---------------------------\ +\ +10.1. New Versions\ +\ +Mozilla Foundation is the license steward. Except as provided in Section\ +10.3, no one other than the license steward has the right to modify or\ +publish new versions of this License. Each version will be given a\ +distinguishing version number.\ +\ +10.2. Effect of New Versions\ +\ +You may distribute the Covered Software under the terms of the version\ +of the License under which You originally received the Covered Software,\ +or under the terms of any subsequent version published by the license\ +steward.\ +\ +10.3. Modified Versions\ +\ +If you create software not governed by this License, and you want to\ +create a new license for such software, you may create and use a\ +modified version of this License if you rename the license and remove\ +any references to the name of the license steward (except to note that\ +such modified license differs from this License).\ +\ +10.4. Distributing Source Code Form that is Incompatible With Secondary\ +Licenses\ +\ +If You choose to distribute Source Code Form that is Incompatible With\ +Secondary Licenses under the terms of this version of the License, the\ +notice described in Exhibit B of this License must be attached.\ +\ +Exhibit A - Source Code Form License Notice\ +-------------------------------------------\ +\ + This Source Code Form is subject to the terms of the Mozilla Public\ + License, v. 2.0. If a copy of the MPL was not distributed with this\ + file, You can obtain one at http://mozilla.org/MPL/2.0/.\ +\ +If it is not possible or desirable to put the notice in a particular\ +file, then You may include the notice in a location (such as a LICENSE\ +file in a relevant directory) where a recipient would be likely to look\ +for such a notice.\ +\ +You may add additional accurate notices of copyright ownership.\ +\ +Exhibit B - "Incompatible With Secondary Licenses" Notice\ +---------------------------------------------------------\ +\ + This Source Code Form is "Incompatible With Secondary Licenses", as\ + defined by the Mozilla Public License, v. 2.0.\ +\ + +\f0\b\fs26 LICENSE-MIT +\f1\b0\fs24 \ +MIT License\ +\ +Copyright (c) 2021+ Anton Zhiyanov \ +\ +Permission is hereby granted, free of charge, to any person obtaining a copy\ +of this software and associated documentation files (the "Software"), to deal\ +in the Software without restriction, including without limitation the rights\ +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ +copies of the Software, and to permit persons to whom the Software is\ +furnished to do so, subject to the following conditions:\ +\ +The above copyright notice and this permission notice shall be included in all\ +copies or substantial portions of the Software.\ +\ +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\ +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\ +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\ +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\ +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\ +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\ +SOFTWARE.\ +\ + +\f0\b\fs26 LICENSE-PLUGINS +\f1\b0\fs24 \ +DB Browser for SQLite includes support for TIFF and WebP images. The\ +support for these comes from the LibTIFF and WebP projects, which have\ +their own (Open Source) licenses, different to ours.\ +\ +LibTIFF - http://www.simplesystems.org/libtiff/\ +\ + Copyright (c) 1988-1997 Sam Leffler\ + Copyright (c) 1991-1997 Silicon Graphics, Inc.\ +\ + Permission to use, copy, modify, distribute, and sell this software and \ + its documentation for any purpose is hereby granted without fee, provided\ + that (i) the above copyright notices and this permission notice appear in\ + all copies of the software and related documentation, and (ii) the names of\ + Sam Leffler and Silicon Graphics may not be used in any advertising or\ + publicity relating to the software without the specific, prior written\ + permission of Sam Leffler and Silicon Graphics.\ +\ + THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, \ + EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY \ + WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. \ +\ + IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR\ + ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,\ + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\ + WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF \ + LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE \ + OF THIS SOFTWARE. \ +\ +WebP - https://developers.google.com/speed/webp/\ +\ + Copyright (c) 2010, Google Inc. All rights reserved.\ +\ + Redistribution and use in source and binary forms, with or without\ + modification, are permitted provided that the following conditions are\ + met:\ +\ + * Redistributions of source code must retain the above copyright\ + notice, this list of conditions and the following disclaimer.\ +\ + * 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.\ +\ + * Neither the name of Google 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 COPYRIGHT HOLDERS AND CONTRIBUTORS\ + "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 COPYRIGHT\ + HOLDER OR CONTRIBUTORS 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.\ +\ +Icons - https://codefisher.org/pastel-svg/\ +\ +Most of the icons come from the Pastel SVG icon set created by Michael\ +Buckley. We have obtained a special license (Creative Commons\ +Attribution Share Alike 4.0\ +http://creativecommons.org/licenses/by-sa/4.0/) but you might be\ +required to redistribute it under Creative Commons Attribution\ +NonCommercial Share Alike 4.0\ +http://creativecommons.org/licenses/by-nc-sa/4.0/\ +Check https://codefisher.org/pastel-svg/ for clarification.\ +\ +The construction emoji for the icon used in the nightly version come\ +from the OpenMoji under CC BY-SA 4.0 license.\ +Check https://openmoji.org/library/emoji-1F6A7/ and\ +https://openmoji.org/faq/ for clarification.\ +\ +Some icons might have other open licenses, check history of the files\ +under `src/icons`.} \ No newline at end of file diff --git a/installer/windows/product.wxs b/installer/windows/product.wxs new file mode 100644 index 000000000..385895a81 --- /dev/null +++ b/installer/windows/product.wxs @@ -0,0 +1,314 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SHORTCUT_SQLITE_DESKTOP + + + + + SHORTCUT_SQLCIPHER_DESKTOP + + + + + + + SHORTCUT_SQLITE_PROGRAMMENU + + + + + SHORTCUT_SQLCIPHER_PROGRAMMENU + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LicenseAccepted = "1" + NOT Installed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSIS_INSTALLDIR + + + + + + + NSIS_INSTALLDIR + + + + + diff --git a/installer/windows/resources/background.xcf b/installer/windows/resources/background.xcf new file mode 100644 index 000000000..ebf51cf0f Binary files /dev/null and b/installer/windows/resources/background.xcf differ diff --git a/installer/windows/resources/banner.xcf b/installer/windows/resources/banner.xcf new file mode 100644 index 000000000..10a3f83b7 Binary files /dev/null and b/installer/windows/resources/banner.xcf differ diff --git a/installer/windows/resources/icon.png b/installer/windows/resources/icon.png new file mode 100644 index 000000000..f6505e913 Binary files /dev/null and b/installer/windows/resources/icon.png differ diff --git a/installer/windows/strings.wxl b/installer/windows/strings.wxl new file mode 100644 index 000000000..f5af817de --- /dev/null +++ b/installer/windows/strings.wxl @@ -0,0 +1,14 @@ + + + This Setup Wizard will install [ProductName] on your computer. If you have a previous version already installed, this installation process will update it. + + + [ProductName] Setup + {\WixUI_Font_Title}Shortcuts + Select the shortcuts for the application. + [ProductName] uses the latest version of SQLite, so you can enjoy all of its new features and bug fixes, but it does not have encryption support. It is also built with SQLCipher as a separate application. SQLCipher is an open source extension to SQLite providing transparent 256-bit AES encryption of database files, but uses a slightly older version of SQLite. Both applications (with and without SQLCipher) are installed and can run concurrently. This page allows you to choose the shortcuts for each application and where to place them. + DB Browser (SQLite) + DB Browser (SQLCipher) + Desktop + Program Menu + diff --git a/installer/windows/translations.wxs b/installer/windows/translations.wxs new file mode 100644 index 000000000..0743a202c --- /dev/null +++ b/installer/windows/translations.wxs @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/installer/windows/ui.wxs b/installer/windows/ui.wxs new file mode 100644 index 000000000..7fee7011f --- /dev/null +++ b/installer/windows/ui.wxs @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + 1 + + + 1 + + + 1 + + + + + diff --git a/installer/windows/variables.wxi b/installer/windows/variables.wxi new file mode 100644 index 000000000..8fc77959a --- /dev/null +++ b/installer/windows/variables.wxi @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/installer/windows_on_arm/add_sqlean_arm64_target.patch b/installer/windows_on_arm/add_sqlean_arm64_target.patch new file mode 100644 index 000000000..400f00896 --- /dev/null +++ b/installer/windows_on_arm/add_sqlean_arm64_target.patch @@ -0,0 +1,45 @@ +diff --git a/Makefile b/Makefile +index 5033c1d..ac038f1 100644 +--- a/Makefile ++++ b/Makefile +@@ -10,11 +10,13 @@ SQLITE_BRANCH := 3.36 + SQLEAN_VERSION := '"$(or $(shell git tag --points-at HEAD),main)"' + + CC ?= gcc ++CC_WIN_ARM64 ?= clang --target=aarch64-w64-mingw32 + CFLAGS ?= + COMMON_CFLAGS := -Isrc -DSQLEAN_VERSION=$(SQLEAN_VERSION) + + LINIX_FLAGS := $(CFLAGS) -z now -z relro -Wall -Wsign-compare -Wno-unknown-pragmas -fPIC -shared $(COMMON_CFLAGS) + WINDO_FLAGS := $(CFLAGS) -shared $(COMMON_CFLAGS) ++WINDO_ARM64_FLAGS := $(CFLAGS) -shared $(COMMON_CFLAGS) + MACOS_FLAGS := $(CFLAGS) -Wall -Wsign-compare -fPIC -dynamiclib $(COMMON_CFLAGS) + CTEST_FLAGS := $(CFLAGS) -Wall -Wsign-compare -Wno-unknown-pragmas -Isrc + +@@ -118,8 +120,26 @@ compile-windows: + gcc -O3 $(WINDO_FLAGS) src/sqlite3-vsv.c src/vsv/*.c -o dist/vsv.dll -lm + gcc -O3 $(WINDO_FLAGS) -include src/regexp/constants.h src/sqlite3-sqlean.c src/crypto/*.c src/define/*.c src/fileio/*.c src/fuzzy/*.c src/math/*.c src/regexp/*.c src/regexp/pcre2/*.c src/stats/*.c src/text/*.c src/text/*/*.c src/time/*.c src/unicode/*.c src/uuid/*.c src/vsv/*.c -o dist/sqlean.dll -lm + ++compile-windows-arm64: ++ mkdir -p dist/arm64 ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) src/sqlite3-crypto.c src/crypto/*.c -o dist/arm64/crypto.dll ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) src/sqlite3-define.c src/define/*.c -o dist/arm64/define.dll ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) src/sqlite3-fileio.c src/fileio/*.c -o dist/arm64/fileio.dll ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) src/sqlite3-fuzzy.c src/fuzzy/*.c -o dist/arm64/fuzzy.dll ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) src/sqlite3-ipaddr.c src/ipaddr/*.c -o dist/arm64/ipaddr.dll -lws2_32 ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) src/sqlite3-math.c src/math/*.c -o dist/arm64/math.dll -lm ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) src/sqlite3-regexp.c -include src/regexp/constants.h src/regexp/*.c src/regexp/pcre2/*.c -o dist/arm64/regexp.dll ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) src/sqlite3-stats.c src/stats/*.c -o dist/arm64/stats.dll -lm ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) src/sqlite3-text.c src/text/*.c src/text/*/*.c -o dist/arm64/text.dll ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) src/sqlite3-time.c src/time/*.c -o dist/arm64/time.dll ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) src/sqlite3-unicode.c src/unicode/*.c -o dist/arm64/unicode.dll ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) src/sqlite3-uuid.c src/uuid/*.c -o dist/arm64/uuid.dll ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) src/sqlite3-vsv.c src/vsv/*.c -o dist/arm64/vsv.dll -lm ++ $(CC_WIN_ARM64) -O3 $(WINDO_ARM64_FLAGS) -include src/regexp/constants.h src/sqlite3-sqlean.c src/crypto/*.c src/define/*.c src/fileio/*.c src/fuzzy/*.c src/math/*.c src/regexp/*.c src/regexp/pcre2/*.c src/stats/*.c src/text/*.c src/text/*/*.c src/time/*.c src/unicode/*.c src/uuid/*.c src/vsv/*.c -o dist/arm64/sqlean.dll -lm ++ + pack-windows: + 7z a -tzip dist/sqlean-win-x64.zip ./dist/*.dll ++ 7z a -tzip dist/sqlean-win-arm64.zip ./dist/arm64/*.dll + + compile-macos: + $(CC) -O3 $(MACOS_FLAGS) src/sqlite3-crypto.c src/crypto/*.c -o dist/crypto.dylib diff --git a/installer/windows_on_arm/background.bmp b/installer/windows_on_arm/background.bmp new file mode 100644 index 000000000..821cb5737 Binary files /dev/null and b/installer/windows_on_arm/background.bmp differ diff --git a/installer/windows_on_arm/banner.bmp b/installer/windows_on_arm/banner.bmp new file mode 100644 index 000000000..b4898aa18 Binary files /dev/null and b/installer/windows_on_arm/banner.bmp differ diff --git a/installer/windows_on_arm/build.cmd b/installer/windows_on_arm/build.cmd new file mode 100644 index 000000000..8a988c490 --- /dev/null +++ b/installer/windows_on_arm/build.cmd @@ -0,0 +1,28 @@ +@echo off + +set "WIX=C:\Program Files (x86)\WiX Toolset v3.14\bin" + +:: Output file name +set MSI=DB.Browser.for.SQLite-%1 + +set ARCH=arm64 + +:: Suppress some ICE checks +:: - 61 (major upgrade) +:: - 03 & 82 (merge module) +:: - 38 & 43 & 57 (non-advertised shortcuts) +set ICE=-sice:ICE03 -sice:ICE82 -sice:ICE61 -sice:ICE38 -sice:ICE43 -sice:ICE57 + +:: Suppress 'light.exe' warning +:: - 1104 (vcredist merge module installer version) +set LIGHT=-sw1104 + +:: Compile & Link +"%WIX%\candle.exe" -nologo -pedantic -arch %ARCH% product.wxs translations.wxs ui.wxs +"%WIX%\light.exe" -sval -nologo -pedantic %LIGHT% %ICE% -ext WixUIExtension -ext WixUtilExtension -cultures:en-us -loc strings.wxl product.wixobj translations.wixobj ui.wixobj -out %MSI%.msi + +:: Cleanup +del product.wixobj +del translations.wixobj +del ui.wixobj +del %MSI%.wixpdb diff --git a/installer/windows_on_arm/license.rtf b/installer/windows_on_arm/license.rtf new file mode 100644 index 000000000..2601ae905 --- /dev/null +++ b/installer/windows_on_arm/license.rtf @@ -0,0 +1,1179 @@ +{\rtf1\ansi\ansicpg1252\cocoartf2761 +\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Arial-BoldMT;\f1\fswiss\fcharset0 ArialMT;} +{\colortbl;\red255\green255\blue255;} +{\*\expandedcolortbl;;} +\paperw11900\paperh16840\margl1440\margr1440\vieww16560\viewh8400\viewkind0 +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 + +\f0\b\fs28 \cf0 DB Browser for SQLite is bi-licensed under the Mozilla Public License\ +Version 2, as well as the GNU General Public License Version 3 or later.\ +\ +Modification or redistribution is permitted under the conditions of these licenses.\ +\ +Check `LICENSE-GPL-3.0` for the full text of the GNU General Public License Version 3.\ +Check `LICENSE-MPL-2.0` for the full text of the Mozilla Public License Version 2.\ +Check `LICENSE-MIT` for the full text of the MIT License. and that is the license for the `nalgeon/sqlean` library.\ +Check `LICENSE-PLUGINS` for other rights regarding included third-party resources. +\f1\b0\fs24 \ +\ + +\f0\b\fs26 LICENSE-GPL-3.0 +\f1\b0\fs24 \ + GNU GENERAL PUBLIC LICENSE\ + Version 3, 29 June 2007\ +\ + Copyright (C) 2007 Free Software Foundation, Inc. \ + Everyone is permitted to copy and distribute verbatim copies\ + of this license document, but changing it is not allowed.\ +\ + Preamble\ +\ + The GNU General Public License is a free, copyleft license for\ +software and other kinds of works.\ +\ + The licenses for most software and other practical works are designed\ +to take away your freedom to share and change the works. By contrast,\ +the GNU General Public License is intended to guarantee your freedom to\ +share and change all versions of a program--to make sure it remains free\ +software for all its users. We, the Free Software Foundation, use the\ +GNU General Public License for most of our software; it applies also to\ +any other work released this way by its authors. You can apply it to\ +your programs, too.\ +\ + When we speak of free software, we are referring to freedom, not\ +price. Our General Public Licenses are designed to make sure that you\ +have the freedom to distribute copies of free software (and charge for\ +them if you wish), that you receive source code or can get it if you\ +want it, that you can change the software or use pieces of it in new\ +free programs, and that you know you can do these things.\ +\ + To protect your rights, we need to prevent others from denying you\ +these rights or asking you to surrender the rights. Therefore, you have\ +certain responsibilities if you distribute copies of the software, or if\ +you modify it: responsibilities to respect the freedom of others.\ +\ + For example, if you distribute copies of such a program, whether\ +gratis or for a fee, you must pass on to the recipients the same\ +freedoms that you received. You must make sure that they, too, receive\ +or can get the source code. And you must show them these terms so they\ +know their rights.\ +\ + Developers that use the GNU GPL protect your rights with two steps:\ +(1) assert copyright on the software, and (2) offer you this License\ +giving you legal permission to copy, distribute and/or modify it.\ +\ + For the developers' and authors' protection, the GPL clearly explains\ +that there is no warranty for this free software. For both users' and\ +authors' sake, the GPL requires that modified versions be marked as\ +changed, so that their problems will not be attributed erroneously to\ +authors of previous versions.\ +\ + Some devices are designed to deny users access to install or run\ +modified versions of the software inside them, although the manufacturer\ +can do so. This is fundamentally incompatible with the aim of\ +protecting users' freedom to change the software. The systematic\ +pattern of such abuse occurs in the area of products for individuals to\ +use, which is precisely where it is most unacceptable. Therefore, we\ +have designed this version of the GPL to prohibit the practice for those\ +products. If such problems arise substantially in other domains, we\ +stand ready to extend this provision to those domains in future versions\ +of the GPL, as needed to protect the freedom of users.\ +\ + Finally, every program is threatened constantly by software patents.\ +States should not allow patents to restrict development and use of\ +software on general-purpose computers, but in those that do, we wish to\ +avoid the special danger that patents applied to a free program could\ +make it effectively proprietary. To prevent this, the GPL assures that\ +patents cannot be used to render the program non-free.\ +\ + The precise terms and conditions for copying, distribution and\ +modification follow.\ +\ + TERMS AND CONDITIONS\ +\ + 0. Definitions.\ +\ + "This License" refers to version 3 of the GNU General Public License.\ +\ + "Copyright" also means copyright-like laws that apply to other kinds of\ +works, such as semiconductor masks.\ +\ + "The Program" refers to any copyrightable work licensed under this\ +License. Each licensee is addressed as "you". "Licensees" and\ +"recipients" may be individuals or organizations.\ +\ + To "modify" a work means to copy from or adapt all or part of the work\ +in a fashion requiring copyright permission, other than the making of an\ +exact copy. The resulting work is called a "modified version" of the\ +earlier work or a work "based on" the earlier work.\ +\ + A "covered work" means either the unmodified Program or a work based\ +on the Program.\ +\ + To "propagate" a work means to do anything with it that, without\ +permission, would make you directly or secondarily liable for\ +infringement under applicable copyright law, except executing it on a\ +computer or modifying a private copy. Propagation includes copying,\ +distribution (with or without modification), making available to the\ +public, and in some countries other activities as well.\ +\ + To "convey" a work means any kind of propagation that enables other\ +parties to make or receive copies. Mere interaction with a user through\ +a computer network, with no transfer of a copy, is not conveying.\ +\ + An interactive user interface displays "Appropriate Legal Notices"\ +to the extent that it includes a convenient and prominently visible\ +feature that (1) displays an appropriate copyright notice, and (2)\ +tells the user that there is no warranty for the work (except to the\ +extent that warranties are provided), that licensees may convey the\ +work under this License, and how to view a copy of this License. If\ +the interface presents a list of user commands or options, such as a\ +menu, a prominent item in the list meets this criterion.\ +\ + 1. Source Code.\ +\ + The "source code" for a work means the preferred form of the work\ +for making modifications to it. "Object code" means any non-source\ +form of a work.\ +\ + A "Standard Interface" means an interface that either is an official\ +standard defined by a recognized standards body, or, in the case of\ +interfaces specified for a particular programming language, one that\ +is widely used among developers working in that language.\ +\ + The "System Libraries" of an executable work include anything, other\ +than the work as a whole, that (a) is included in the normal form of\ +packaging a Major Component, but which is not part of that Major\ +Component, and (b) serves only to enable use of the work with that\ +Major Component, or to implement a Standard Interface for which an\ +implementation is available to the public in source code form. A\ +"Major Component", in this context, means a major essential component\ +(kernel, window system, and so on) of the specific operating system\ +(if any) on which the executable work runs, or a compiler used to\ +produce the work, or an object code interpreter used to run it.\ +\ + The "Corresponding Source" for a work in object code form means all\ +the source code needed to generate, install, and (for an executable\ +work) run the object code and to modify the work, including scripts to\ +control those activities. However, it does not include the work's\ +System Libraries, or general-purpose tools or generally available free\ +programs which are used unmodified in performing those activities but\ +which are not part of the work. For example, Corresponding Source\ +includes interface definition files associated with source files for\ +the work, and the source code for shared libraries and dynamically\ +linked subprograms that the work is specifically designed to require,\ +such as by intimate data communication or control flow between those\ +subprograms and other parts of the work.\ +\ + The Corresponding Source need not include anything that users\ +can regenerate automatically from other parts of the Corresponding\ +Source.\ +\ + The Corresponding Source for a work in source code form is that\ +same work.\ +\ + 2. Basic Permissions.\ +\ + All rights granted under this License are granted for the term of\ +copyright on the Program, and are irrevocable provided the stated\ +conditions are met. This License explicitly affirms your unlimited\ +permission to run the unmodified Program. The output from running a\ +covered work is covered by this License only if the output, given its\ +content, constitutes a covered work. This License acknowledges your\ +rights of fair use or other equivalent, as provided by copyright law.\ +\ + You may make, run and propagate covered works that you do not\ +convey, without conditions so long as your license otherwise remains\ +in force. You may convey covered works to others for the sole purpose\ +of having them make modifications exclusively for you, or provide you\ +with facilities for running those works, provided that you comply with\ +the terms of this License in conveying all material for which you do\ +not control copyright. Those thus making or running the covered works\ +for you must do so exclusively on your behalf, under your direction\ +and control, on terms that prohibit them from making any copies of\ +your copyrighted material outside their relationship with you.\ +\ + Conveying under any other circumstances is permitted solely under\ +the conditions stated below. Sublicensing is not allowed; section 10\ +makes it unnecessary.\ +\ + 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\ +\ + No covered work shall be deemed part of an effective technological\ +measure under any applicable law fulfilling obligations under article\ +11 of the WIPO copyright treaty adopted on 20 December 1996, or\ +similar laws prohibiting or restricting circumvention of such\ +measures.\ +\ + When you convey a covered work, you waive any legal power to forbid\ +circumvention of technological measures to the extent such circumvention\ +is effected by exercising rights under this License with respect to\ +the covered work, and you disclaim any intention to limit operation or\ +modification of the work as a means of enforcing, against the work's\ +users, your or third parties' legal rights to forbid circumvention of\ +technological measures.\ +\ + 4. Conveying Verbatim Copies.\ +\ + You may convey verbatim copies of the Program's source code as you\ +receive it, in any medium, provided that you conspicuously and\ +appropriately publish on each copy an appropriate copyright notice;\ +keep intact all notices stating that this License and any\ +non-permissive terms added in accord with section 7 apply to the code;\ +keep intact all notices of the absence of any warranty; and give all\ +recipients a copy of this License along with the Program.\ +\ + You may charge any price or no price for each copy that you convey,\ +and you may offer support or warranty protection for a fee.\ +\ + 5. Conveying Modified Source Versions.\ +\ + You may convey a work based on the Program, or the modifications to\ +produce it from the Program, in the form of source code under the\ +terms of section 4, provided that you also meet all of these conditions:\ +\ + a) The work must carry prominent notices stating that you modified\ + it, and giving a relevant date.\ +\ + b) The work must carry prominent notices stating that it is\ + released under this License and any conditions added under section\ + 7. This requirement modifies the requirement in section 4 to\ + "keep intact all notices".\ +\ + c) You must license the entire work, as a whole, under this\ + License to anyone who comes into possession of a copy. This\ + License will therefore apply, along with any applicable section 7\ + additional terms, to the whole of the work, and all its parts,\ + regardless of how they are packaged. This License gives no\ + permission to license the work in any other way, but it does not\ + invalidate such permission if you have separately received it.\ +\ + d) If the work has interactive user interfaces, each must display\ + Appropriate Legal Notices; however, if the Program has interactive\ + interfaces that do not display Appropriate Legal Notices, your\ + work need not make them do so.\ +\ + A compilation of a covered work with other separate and independent\ +works, which are not by their nature extensions of the covered work,\ +and which are not combined with it such as to form a larger program,\ +in or on a volume of a storage or distribution medium, is called an\ +"aggregate" if the compilation and its resulting copyright are not\ +used to limit the access or legal rights of the compilation's users\ +beyond what the individual works permit. Inclusion of a covered work\ +in an aggregate does not cause this License to apply to the other\ +parts of the aggregate.\ +\ + 6. Conveying Non-Source Forms.\ +\ + You may convey a covered work in object code form under the terms\ +of sections 4 and 5, provided that you also convey the\ +machine-readable Corresponding Source under the terms of this License,\ +in one of these ways:\ +\ + a) Convey the object code in, or embodied in, a physical product\ + (including a physical distribution medium), accompanied by the\ + Corresponding Source fixed on a durable physical medium\ + customarily used for software interchange.\ +\ + b) Convey the object code in, or embodied in, a physical product\ + (including a physical distribution medium), accompanied by a\ + written offer, valid for at least three years and valid for as\ + long as you offer spare parts or customer support for that product\ + model, to give anyone who possesses the object code either (1) a\ + copy of the Corresponding Source for all the software in the\ + product that is covered by this License, on a durable physical\ + medium customarily used for software interchange, for a price no\ + more than your reasonable cost of physically performing this\ + conveying of source, or (2) access to copy the\ + Corresponding Source from a network server at no charge.\ +\ + c) Convey individual copies of the object code with a copy of the\ + written offer to provide the Corresponding Source. This\ + alternative is allowed only occasionally and noncommercially, and\ + only if you received the object code with such an offer, in accord\ + with subsection 6b.\ +\ + d) Convey the object code by offering access from a designated\ + place (gratis or for a charge), and offer equivalent access to the\ + Corresponding Source in the same way through the same place at no\ + further charge. You need not require recipients to copy the\ + Corresponding Source along with the object code. If the place to\ + copy the object code is a network server, the Corresponding Source\ + may be on a different server (operated by you or a third party)\ + that supports equivalent copying facilities, provided you maintain\ + clear directions next to the object code saying where to find the\ + Corresponding Source. Regardless of what server hosts the\ + Corresponding Source, you remain obligated to ensure that it is\ + available for as long as needed to satisfy these requirements.\ +\ + e) Convey the object code using peer-to-peer transmission, provided\ + you inform other peers where the object code and Corresponding\ + Source of the work are being offered to the general public at no\ + charge under subsection 6d.\ +\ + A separable portion of the object code, whose source code is excluded\ +from the Corresponding Source as a System Library, need not be\ +included in conveying the object code work.\ +\ + A "User Product" is either (1) a "consumer product", which means any\ +tangible personal property which is normally used for personal, family,\ +or household purposes, or (2) anything designed or sold for incorporation\ +into a dwelling. In determining whether a product is a consumer product,\ +doubtful cases shall be resolved in favor of coverage. For a particular\ +product received by a particular user, "normally used" refers to a\ +typical or common use of that class of product, regardless of the status\ +of the particular user or of the way in which the particular user\ +actually uses, or expects or is expected to use, the product. A product\ +is a consumer product regardless of whether the product has substantial\ +commercial, industrial or non-consumer uses, unless such uses represent\ +the only significant mode of use of the product.\ +\ + "Installation Information" for a User Product means any methods,\ +procedures, authorization keys, or other information required to install\ +and execute modified versions of a covered work in that User Product from\ +a modified version of its Corresponding Source. The information must\ +suffice to ensure that the continued functioning of the modified object\ +code is in no case prevented or interfered with solely because\ +modification has been made.\ +\ + If you convey an object code work under this section in, or with, or\ +specifically for use in, a User Product, and the conveying occurs as\ +part of a transaction in which the right of possession and use of the\ +User Product is transferred to the recipient in perpetuity or for a\ +fixed term (regardless of how the transaction is characterized), the\ +Corresponding Source conveyed under this section must be accompanied\ +by the Installation Information. But this requirement does not apply\ +if neither you nor any third party retains the ability to install\ +modified object code on the User Product (for example, the work has\ +been installed in ROM).\ +\ + The requirement to provide Installation Information does not include a\ +requirement to continue to provide support service, warranty, or updates\ +for a work that has been modified or installed by the recipient, or for\ +the User Product in which it has been modified or installed. Access to a\ +network may be denied when the modification itself materially and\ +adversely affects the operation of the network or violates the rules and\ +protocols for communication across the network.\ +\ + Corresponding Source conveyed, and Installation Information provided,\ +in accord with this section must be in a format that is publicly\ +documented (and with an implementation available to the public in\ +source code form), and must require no special password or key for\ +unpacking, reading or copying.\ +\ + 7. Additional Terms.\ +\ + "Additional permissions" are terms that supplement the terms of this\ +License by making exceptions from one or more of its conditions.\ +Additional permissions that are applicable to the entire Program shall\ +be treated as though they were included in this License, to the extent\ +that they are valid under applicable law. If additional permissions\ +apply only to part of the Program, that part may be used separately\ +under those permissions, but the entire Program remains governed by\ +this License without regard to the additional permissions.\ +\ + When you convey a copy of a covered work, you may at your option\ +remove any additional permissions from that copy, or from any part of\ +it. (Additional permissions may be written to require their own\ +removal in certain cases when you modify the work.) You may place\ +additional permissions on material, added by you to a covered work,\ +for which you have or can give appropriate copyright permission.\ +\ + Notwithstanding any other provision of this License, for material you\ +add to a covered work, you may (if authorized by the copyright holders of\ +that material) supplement the terms of this License with terms:\ +\ + a) Disclaiming warranty or limiting liability differently from the\ + terms of sections 15 and 16 of this License; or\ +\ + b) Requiring preservation of specified reasonable legal notices or\ + author attributions in that material or in the Appropriate Legal\ + Notices displayed by works containing it; or\ +\ + c) Prohibiting misrepresentation of the origin of that material, or\ + requiring that modified versions of such material be marked in\ + reasonable ways as different from the original version; or\ +\ + d) Limiting the use for publicity purposes of names of licensors or\ + authors of the material; or\ +\ + e) Declining to grant rights under trademark law for use of some\ + trade names, trademarks, or service marks; or\ +\ + f) Requiring indemnification of licensors and authors of that\ + material by anyone who conveys the material (or modified versions of\ + it) with contractual assumptions of liability to the recipient, for\ + any liability that these contractual assumptions directly impose on\ + those licensors and authors.\ +\ + All other non-permissive additional terms are considered "further\ +restrictions" within the meaning of section 10. If the Program as you\ +received it, or any part of it, contains a notice stating that it is\ +governed by this License along with a term that is a further\ +restriction, you may remove that term. If a license document contains\ +a further restriction but permits relicensing or conveying under this\ +License, you may add to a covered work material governed by the terms\ +of that license document, provided that the further restriction does\ +not survive such relicensing or conveying.\ +\ + If you add terms to a covered work in accord with this section, you\ +must place, in the relevant source files, a statement of the\ +additional terms that apply to those files, or a notice indicating\ +where to find the applicable terms.\ +\ + Additional terms, permissive or non-permissive, may be stated in the\ +form of a separately written license, or stated as exceptions;\ +the above requirements apply either way.\ +\ + 8. Termination.\ +\ + You may not propagate or modify a covered work except as expressly\ +provided under this License. Any attempt otherwise to propagate or\ +modify it is void, and will automatically terminate your rights under\ +this License (including any patent licenses granted under the third\ +paragraph of section 11).\ +\ + However, if you cease all violation of this License, then your\ +license from a particular copyright holder is reinstated (a)\ +provisionally, unless and until the copyright holder explicitly and\ +finally terminates your license, and (b) permanently, if the copyright\ +holder fails to notify you of the violation by some reasonable means\ +prior to 60 days after the cessation.\ +\ + Moreover, your license from a particular copyright holder is\ +reinstated permanently if the copyright holder notifies you of the\ +violation by some reasonable means, this is the first time you have\ +received notice of violation of this License (for any work) from that\ +copyright holder, and you cure the violation prior to 30 days after\ +your receipt of the notice.\ +\ + Termination of your rights under this section does not terminate the\ +licenses of parties who have received copies or rights from you under\ +this License. If your rights have been terminated and not permanently\ +reinstated, you do not qualify to receive new licenses for the same\ +material under section 10.\ +\ + 9. Acceptance Not Required for Having Copies.\ +\ + You are not required to accept this License in order to receive or\ +run a copy of the Program. Ancillary propagation of a covered work\ +occurring solely as a consequence of using peer-to-peer transmission\ +to receive a copy likewise does not require acceptance. However,\ +nothing other than this License grants you permission to propagate or\ +modify any covered work. These actions infringe copyright if you do\ +not accept this License. Therefore, by modifying or propagating a\ +covered work, you indicate your acceptance of this License to do so.\ +\ + 10. Automatic Licensing of Downstream Recipients.\ +\ + Each time you convey a covered work, the recipient automatically\ +receives a license from the original licensors, to run, modify and\ +propagate that work, subject to this License. You are not responsible\ +for enforcing compliance by third parties with this License.\ +\ + An "entity transaction" is a transaction transferring control of an\ +organization, or substantially all assets of one, or subdividing an\ +organization, or merging organizations. If propagation of a covered\ +work results from an entity transaction, each party to that\ +transaction who receives a copy of the work also receives whatever\ +licenses to the work the party's predecessor in interest had or could\ +give under the previous paragraph, plus a right to possession of the\ +Corresponding Source of the work from the predecessor in interest, if\ +the predecessor has it or can get it with reasonable efforts.\ +\ + You may not impose any further restrictions on the exercise of the\ +rights granted or affirmed under this License. For example, you may\ +not impose a license fee, royalty, or other charge for exercise of\ +rights granted under this License, and you may not initiate litigation\ +(including a cross-claim or counterclaim in a lawsuit) alleging that\ +any patent claim is infringed by making, using, selling, offering for\ +sale, or importing the Program or any portion of it.\ +\ + 11. Patents.\ +\ + A "contributor" is a copyright holder who authorizes use under this\ +License of the Program or a work on which the Program is based. The\ +work thus licensed is called the contributor's "contributor version".\ +\ + A contributor's "essential patent claims" are all patent claims\ +owned or controlled by the contributor, whether already acquired or\ +hereafter acquired, that would be infringed by some manner, permitted\ +by this License, of making, using, or selling its contributor version,\ +but do not include claims that would be infringed only as a\ +consequence of further modification of the contributor version. For\ +purposes of this definition, "control" includes the right to grant\ +patent sublicenses in a manner consistent with the requirements of\ +this License.\ +\ + Each contributor grants you a non-exclusive, worldwide, royalty-free\ +patent license under the contributor's essential patent claims, to\ +make, use, sell, offer for sale, import and otherwise run, modify and\ +propagate the contents of its contributor version.\ +\ + In the following three paragraphs, a "patent license" is any express\ +agreement or commitment, however denominated, not to enforce a patent\ +(such as an express permission to practice a patent or covenant not to\ +sue for patent infringement). To "grant" such a patent license to a\ +party means to make such an agreement or commitment not to enforce a\ +patent against the party.\ +\ + If you convey a covered work, knowingly relying on a patent license,\ +and the Corresponding Source of the work is not available for anyone\ +to copy, free of charge and under the terms of this License, through a\ +publicly available network server or other readily accessible means,\ +then you must either (1) cause the Corresponding Source to be so\ +available, or (2) arrange to deprive yourself of the benefit of the\ +patent license for this particular work, or (3) arrange, in a manner\ +consistent with the requirements of this License, to extend the patent\ +license to downstream recipients. "Knowingly relying" means you have\ +actual knowledge that, but for the patent license, your conveying the\ +covered work in a country, or your recipient's use of the covered work\ +in a country, would infringe one or more identifiable patents in that\ +country that you have reason to believe are valid.\ +\ + If, pursuant to or in connection with a single transaction or\ +arrangement, you convey, or propagate by procuring conveyance of, a\ +covered work, and grant a patent license to some of the parties\ +receiving the covered work authorizing them to use, propagate, modify\ +or convey a specific copy of the covered work, then the patent license\ +you grant is automatically extended to all recipients of the covered\ +work and works based on it.\ +\ + A patent license is "discriminatory" if it does not include within\ +the scope of its coverage, prohibits the exercise of, or is\ +conditioned on the non-exercise of one or more of the rights that are\ +specifically granted under this License. You may not convey a covered\ +work if you are a party to an arrangement with a third party that is\ +in the business of distributing software, under which you make payment\ +to the third party based on the extent of your activity of conveying\ +the work, and under which the third party grants, to any of the\ +parties who would receive the covered work from you, a discriminatory\ +patent license (a) in connection with copies of the covered work\ +conveyed by you (or copies made from those copies), or (b) primarily\ +for and in connection with specific products or compilations that\ +contain the covered work, unless you entered into that arrangement,\ +or that patent license was granted, prior to 28 March 2007.\ +\ + Nothing in this License shall be construed as excluding or limiting\ +any implied license or other defenses to infringement that may\ +otherwise be available to you under applicable patent law.\ +\ + 12. No Surrender of Others' Freedom.\ +\ + If conditions are imposed on you (whether by court order, agreement or\ +otherwise) that contradict the conditions of this License, they do not\ +excuse you from the conditions of this License. If you cannot convey a\ +covered work so as to satisfy simultaneously your obligations under this\ +License and any other pertinent obligations, then as a consequence you may\ +not convey it at all. For example, if you agree to terms that obligate you\ +to collect a royalty for further conveying from those to whom you convey\ +the Program, the only way you could satisfy both those terms and this\ +License would be to refrain entirely from conveying the Program.\ +\ + 13. Use with the GNU Affero General Public License.\ +\ + Notwithstanding any other provision of this License, you have\ +permission to link or combine any covered work with a work licensed\ +under version 3 of the GNU Affero General Public License into a single\ +combined work, and to convey the resulting work. The terms of this\ +License will continue to apply to the part which is the covered work,\ +but the special requirements of the GNU Affero General Public License,\ +section 13, concerning interaction through a network will apply to the\ +combination as such.\ +\ + 14. Revised Versions of this License.\ +\ + The Free Software Foundation may publish revised and/or new versions of\ +the GNU General Public License from time to time. Such new versions will\ +be similar in spirit to the present version, but may differ in detail to\ +address new problems or concerns.\ +\ + Each version is given a distinguishing version number. If the\ +Program specifies that a certain numbered version of the GNU General\ +Public License "or any later version" applies to it, you have the\ +option of following the terms and conditions either of that numbered\ +version or of any later version published by the Free Software\ +Foundation. If the Program does not specify a version number of the\ +GNU General Public License, you may choose any version ever published\ +by the Free Software Foundation.\ +\ + If the Program specifies that a proxy can decide which future\ +versions of the GNU General Public License can be used, that proxy's\ +public statement of acceptance of a version permanently authorizes you\ +to choose that version for the Program.\ +\ + Later license versions may give you additional or different\ +permissions. However, no additional obligations are imposed on any\ +author or copyright holder as a result of your choosing to follow a\ +later version.\ +\ + 15. Disclaimer of Warranty.\ +\ + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\ +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\ +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY\ +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\ +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\ +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\ +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\ +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\ +\ + 16. Limitation of Liability.\ +\ + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\ +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\ +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\ +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\ +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\ +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\ +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\ +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\ +SUCH DAMAGES.\ +\ + 17. Interpretation of Sections 15 and 16.\ +\ + If the disclaimer of warranty and limitation of liability provided\ +above cannot be given local legal effect according to their terms,\ +reviewing courts shall apply local law that most closely approximates\ +an absolute waiver of all civil liability in connection with the\ +Program, unless a warranty or assumption of liability accompanies a\ +copy of the Program in return for a fee.\ +\ + END OF TERMS AND CONDITIONS\ +\ + How to Apply These Terms to Your New Programs\ +\ + If you develop a new program, and you want it to be of the greatest\ +possible use to the public, the best way to achieve this is to make it\ +free software which everyone can redistribute and change under these terms.\ +\ + To do so, attach the following notices to the program. It is safest\ +to attach them to the start of each source file to most effectively\ +state the exclusion of warranty; and each file should have at least\ +the "copyright" line and a pointer to where the full notice is found.\ +\ + \ + Copyright (C) \ +\ + This program is free software: you can redistribute it and/or modify\ + it under the terms of the GNU General Public License as published by\ + the Free Software Foundation, either version 3 of the License, or\ + (at your option) any later version.\ +\ + This program is distributed in the hope that it will be useful,\ + but WITHOUT ANY WARRANTY; without even the implied warranty of\ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\ + GNU General Public License for more details.\ +\ + You should have received a copy of the GNU General Public License\ + along with this program. If not, see .\ +\ +Also add information on how to contact you by electronic and paper mail.\ +\ + If the program does terminal interaction, make it output a short\ +notice like this when it starts in an interactive mode:\ +\ + Copyright (C) \ + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\ + This is free software, and you are welcome to redistribute it\ + under certain conditions; type `show c' for details.\ +\ +The hypothetical commands `show w' and `show c' should show the appropriate\ +parts of the General Public License. Of course, your program's commands\ +might be different; for a GUI interface, you would use an "about box".\ +\ + You should also get your employer (if you work as a programmer) or school,\ +if any, to sign a "copyright disclaimer" for the program, if necessary.\ +For more information on this, and how to apply and follow the GNU GPL, see\ +.\ +\ + The GNU General Public License does not permit incorporating your program\ +into proprietary programs. If your program is a subroutine library, you\ +may consider it more useful to permit linking proprietary applications with\ +the library. If this is what you want to do, use the GNU Lesser General\ +Public License instead of this License. But first, please read\ +.\ +\ + +\f0\b\fs26 LICENSE-MPL-2.0 +\f1\b0\fs24 \ +Mozilla Public License Version 2.0\ +==================================\ +\ +1. Definitions\ +--------------\ +\ +1.1. "Contributor"\ + means each individual or legal entity that creates, contributes to\ + the creation of, or owns Covered Software.\ +\ +1.2. "Contributor Version"\ + means the combination of the Contributions of others (if any) used\ + by a Contributor and that particular Contributor's Contribution.\ +\ +1.3. "Contribution"\ + means Covered Software of a particular Contributor.\ +\ +1.4. "Covered Software"\ + means Source Code Form to which the initial Contributor has attached\ + the notice in Exhibit A, the Executable Form of such Source Code\ + Form, and Modifications of such Source Code Form, in each case\ + including portions thereof.\ +\ +1.5. "Incompatible With Secondary Licenses"\ + means\ +\ + (a) that the initial Contributor has attached the notice described\ + in Exhibit B to the Covered Software; or\ +\ + (b) that the Covered Software was made available under the terms of\ + version 1.1 or earlier of the License, but not also under the\ + terms of a Secondary License.\ +\ +1.6. "Executable Form"\ + means any form of the work other than Source Code Form.\ +\ +1.7. "Larger Work"\ + means a work that combines Covered Software with other material, in\ + a separate file or files, that is not Covered Software.\ +\ +1.8. "License"\ + means this document.\ +\ +1.9. "Licensable"\ + means having the right to grant, to the maximum extent possible,\ + whether at the time of the initial grant or subsequently, any and\ + all of the rights conveyed by this License.\ +\ +1.10. "Modifications"\ + means any of the following:\ +\ + (a) any file in Source Code Form that results from an addition to,\ + deletion from, or modification of the contents of Covered\ + Software; or\ +\ + (b) any new file in Source Code Form that contains any Covered\ + Software.\ +\ +1.11. "Patent Claims" of a Contributor\ + means any patent claim(s), including without limitation, method,\ + process, and apparatus claims, in any patent Licensable by such\ + Contributor that would be infringed, but for the grant of the\ + License, by the making, using, selling, offering for sale, having\ + made, import, or transfer of either its Contributions or its\ + Contributor Version.\ +\ +1.12. "Secondary License"\ + means either the GNU General Public License, Version 2.0, the GNU\ + Lesser General Public License, Version 2.1, the GNU Affero General\ + Public License, Version 3.0, or any later versions of those\ + licenses.\ +\ +1.13. "Source Code Form"\ + means the form of the work preferred for making modifications.\ +\ +1.14. "You" (or "Your")\ + means an individual or a legal entity exercising rights under this\ + License. For legal entities, "You" includes any entity that\ + controls, is controlled by, or is under common control with You. For\ + purposes of this definition, "control" means (a) the power, direct\ + or indirect, to cause the direction or management of such entity,\ + whether by contract or otherwise, or (b) ownership of more than\ + fifty percent (50%) of the outstanding shares or beneficial\ + ownership of such entity.\ +\ +2. License Grants and Conditions\ +--------------------------------\ +\ +2.1. Grants\ +\ +Each Contributor hereby grants You a world-wide, royalty-free,\ +non-exclusive license:\ +\ +(a) under intellectual property rights (other than patent or trademark)\ + Licensable by such Contributor to use, reproduce, make available,\ + modify, display, perform, distribute, and otherwise exploit its\ + Contributions, either on an unmodified basis, with Modifications, or\ + as part of a Larger Work; and\ +\ +(b) under Patent Claims of such Contributor to make, use, sell, offer\ + for sale, have made, import, and otherwise transfer either its\ + Contributions or its Contributor Version.\ +\ +2.2. Effective Date\ +\ +The licenses granted in Section 2.1 with respect to any Contribution\ +become effective for each Contribution on the date the Contributor first\ +distributes such Contribution.\ +\ +2.3. Limitations on Grant Scope\ +\ +The licenses granted in this Section 2 are the only rights granted under\ +this License. No additional rights or licenses will be implied from the\ +distribution or licensing of Covered Software under this License.\ +Notwithstanding Section 2.1(b) above, no patent license is granted by a\ +Contributor:\ +\ +(a) for any code that a Contributor has removed from Covered Software;\ + or\ +\ +(b) for infringements caused by: (i) Your and any other third party's\ + modifications of Covered Software, or (ii) the combination of its\ + Contributions with other software (except as part of its Contributor\ + Version); or\ +\ +(c) under Patent Claims infringed by Covered Software in the absence of\ + its Contributions.\ +\ +This License does not grant any rights in the trademarks, service marks,\ +or logos of any Contributor (except as may be necessary to comply with\ +the notice requirements in Section 3.4).\ +\ +2.4. Subsequent Licenses\ +\ +No Contributor makes additional grants as a result of Your choice to\ +distribute the Covered Software under a subsequent version of this\ +License (see Section 10.2) or under the terms of a Secondary License (if\ +permitted under the terms of Section 3.3).\ +\ +2.5. Representation\ +\ +Each Contributor represents that the Contributor believes its\ +Contributions are its original creation(s) or it has sufficient rights\ +to grant the rights to its Contributions conveyed by this License.\ +\ +2.6. Fair Use\ +\ +This License is not intended to limit any rights You have under\ +applicable copyright doctrines of fair use, fair dealing, or other\ +equivalents.\ +\ +2.7. Conditions\ +\ +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted\ +in Section 2.1.\ +\ +3. Responsibilities\ +-------------------\ +\ +3.1. Distribution of Source Form\ +\ +All distribution of Covered Software in Source Code Form, including any\ +Modifications that You create or to which You contribute, must be under\ +the terms of this License. You must inform recipients that the Source\ +Code Form of the Covered Software is governed by the terms of this\ +License, and how they can obtain a copy of this License. You may not\ +attempt to alter or restrict the recipients' rights in the Source Code\ +Form.\ +\ +3.2. Distribution of Executable Form\ +\ +If You distribute Covered Software in Executable Form then:\ +\ +(a) such Covered Software must also be made available in Source Code\ + Form, as described in Section 3.1, and You must inform recipients of\ + the Executable Form how they can obtain a copy of such Source Code\ + Form by reasonable means in a timely manner, at a charge no more\ + than the cost of distribution to the recipient; and\ +\ +(b) You may distribute such Executable Form under the terms of this\ + License, or sublicense it under different terms, provided that the\ + license for the Executable Form does not attempt to limit or alter\ + the recipients' rights in the Source Code Form under this License.\ +\ +3.3. Distribution of a Larger Work\ +\ +You may create and distribute a Larger Work under terms of Your choice,\ +provided that You also comply with the requirements of this License for\ +the Covered Software. If the Larger Work is a combination of Covered\ +Software with a work governed by one or more Secondary Licenses, and the\ +Covered Software is not Incompatible With Secondary Licenses, this\ +License permits You to additionally distribute such Covered Software\ +under the terms of such Secondary License(s), so that the recipient of\ +the Larger Work may, at their option, further distribute the Covered\ +Software under the terms of either this License or such Secondary\ +License(s).\ +\ +3.4. Notices\ +\ +You may not remove or alter the substance of any license notices\ +(including copyright notices, patent notices, disclaimers of warranty,\ +or limitations of liability) contained within the Source Code Form of\ +the Covered Software, except that You may alter any license notices to\ +the extent required to remedy known factual inaccuracies.\ +\ +3.5. Application of Additional Terms\ +\ +You may choose to offer, and to charge a fee for, warranty, support,\ +indemnity or liability obligations to one or more recipients of Covered\ +Software. However, You may do so only on Your own behalf, and not on\ +behalf of any Contributor. You must make it absolutely clear that any\ +such warranty, support, indemnity, or liability obligation is offered by\ +You alone, and You hereby agree to indemnify every Contributor for any\ +liability incurred by such Contributor as a result of warranty, support,\ +indemnity or liability terms You offer. You may include additional\ +disclaimers of warranty and limitations of liability specific to any\ +jurisdiction.\ +\ +4. Inability to Comply Due to Statute or Regulation\ +---------------------------------------------------\ +\ +If it is impossible for You to comply with any of the terms of this\ +License with respect to some or all of the Covered Software due to\ +statute, judicial order, or regulation then You must: (a) comply with\ +the terms of this License to the maximum extent possible; and (b)\ +describe the limitations and the code they affect. Such description must\ +be placed in a text file included with all distributions of the Covered\ +Software under this License. Except to the extent prohibited by statute\ +or regulation, such description must be sufficiently detailed for a\ +recipient of ordinary skill to be able to understand it.\ +\ +5. Termination\ +--------------\ +\ +5.1. The rights granted under this License will terminate automatically\ +if You fail to comply with any of its terms. However, if You become\ +compliant, then the rights granted under this License from a particular\ +Contributor are reinstated (a) provisionally, unless and until such\ +Contributor explicitly and finally terminates Your grants, and (b) on an\ +ongoing basis, if such Contributor fails to notify You of the\ +non-compliance by some reasonable means prior to 60 days after You have\ +come back into compliance. Moreover, Your grants from a particular\ +Contributor are reinstated on an ongoing basis if such Contributor\ +notifies You of the non-compliance by some reasonable means, this is the\ +first time You have received notice of non-compliance with this License\ +from such Contributor, and You become compliant prior to 30 days after\ +Your receipt of the notice.\ +\ +5.2. If You initiate litigation against any entity by asserting a patent\ +infringement claim (excluding declaratory judgment actions,\ +counter-claims, and cross-claims) alleging that a Contributor Version\ +directly or indirectly infringes any patent, then the rights granted to\ +You by any and all Contributors for the Covered Software under Section\ +2.1 of this License shall terminate.\ +\ +5.3. In the event of termination under Sections 5.1 or 5.2 above, all\ +end user license agreements (excluding distributors and resellers) which\ +have been validly granted by You or Your distributors under this License\ +prior to termination shall survive termination.\ +\ +************************************************************************\ +* *\ +* 6. Disclaimer of Warranty *\ +* ------------------------- *\ +* *\ +* Covered Software is provided under this License on an "as is" *\ +* basis, without warranty of any kind, either expressed, implied, or *\ +* statutory, including, without limitation, warranties that the *\ +* Covered Software is free of defects, merchantable, fit for a *\ +* particular purpose or non-infringing. The entire risk as to the *\ +* quality and performance of the Covered Software is with You. *\ +* Should any Covered Software prove defective in any respect, You *\ +* (not any Contributor) assume the cost of any necessary servicing, *\ +* repair, or correction. This disclaimer of warranty constitutes an *\ +* essential part of this License. No use of any Covered Software is *\ +* authorized under this License except under this disclaimer. *\ +* *\ +************************************************************************\ +\ +************************************************************************\ +* *\ +* 7. Limitation of Liability *\ +* -------------------------- *\ +* *\ +* Under no circumstances and under no legal theory, whether tort *\ +* (including negligence), contract, or otherwise, shall any *\ +* Contributor, or anyone who distributes Covered Software as *\ +* permitted above, be liable to You for any direct, indirect, *\ +* special, incidental, or consequential damages of any character *\ +* including, without limitation, damages for lost profits, loss of *\ +* goodwill, work stoppage, computer failure or malfunction, or any *\ +* and all other commercial damages or losses, even if such party *\ +* shall have been informed of the possibility of such damages. This *\ +* limitation of liability shall not apply to liability for death or *\ +* personal injury resulting from such party's negligence to the *\ +* extent applicable law prohibits such limitation. Some *\ +* jurisdictions do not allow the exclusion or limitation of *\ +* incidental or consequential damages, so this exclusion and *\ +* limitation may not apply to You. *\ +* *\ +************************************************************************\ +\ +8. Litigation\ +-------------\ +\ +Any litigation relating to this License may be brought only in the\ +courts of a jurisdiction where the defendant maintains its principal\ +place of business and such litigation shall be governed by laws of that\ +jurisdiction, without reference to its conflict-of-law provisions.\ +Nothing in this Section shall prevent a party's ability to bring\ +cross-claims or counter-claims.\ +\ +9. Miscellaneous\ +----------------\ +\ +This License represents the complete agreement concerning the subject\ +matter hereof. If any provision of this License is held to be\ +unenforceable, such provision shall be reformed only to the extent\ +necessary to make it enforceable. Any law or regulation which provides\ +that the language of a contract shall be construed against the drafter\ +shall not be used to construe this License against a Contributor.\ +\ +10. Versions of the License\ +---------------------------\ +\ +10.1. New Versions\ +\ +Mozilla Foundation is the license steward. Except as provided in Section\ +10.3, no one other than the license steward has the right to modify or\ +publish new versions of this License. Each version will be given a\ +distinguishing version number.\ +\ +10.2. Effect of New Versions\ +\ +You may distribute the Covered Software under the terms of the version\ +of the License under which You originally received the Covered Software,\ +or under the terms of any subsequent version published by the license\ +steward.\ +\ +10.3. Modified Versions\ +\ +If you create software not governed by this License, and you want to\ +create a new license for such software, you may create and use a\ +modified version of this License if you rename the license and remove\ +any references to the name of the license steward (except to note that\ +such modified license differs from this License).\ +\ +10.4. Distributing Source Code Form that is Incompatible With Secondary\ +Licenses\ +\ +If You choose to distribute Source Code Form that is Incompatible With\ +Secondary Licenses under the terms of this version of the License, the\ +notice described in Exhibit B of this License must be attached.\ +\ +Exhibit A - Source Code Form License Notice\ +-------------------------------------------\ +\ + This Source Code Form is subject to the terms of the Mozilla Public\ + License, v. 2.0. If a copy of the MPL was not distributed with this\ + file, You can obtain one at http://mozilla.org/MPL/2.0/.\ +\ +If it is not possible or desirable to put the notice in a particular\ +file, then You may include the notice in a location (such as a LICENSE\ +file in a relevant directory) where a recipient would be likely to look\ +for such a notice.\ +\ +You may add additional accurate notices of copyright ownership.\ +\ +Exhibit B - "Incompatible With Secondary Licenses" Notice\ +---------------------------------------------------------\ +\ + This Source Code Form is "Incompatible With Secondary Licenses", as\ + defined by the Mozilla Public License, v. 2.0.\ +\ + +\f0\b\fs26 LICENSE-MIT +\f1\b0\fs24 \ +MIT License\ +\ +Copyright (c) 2021+ Anton Zhiyanov \ +\ +Permission is hereby granted, free of charge, to any person obtaining a copy\ +of this software and associated documentation files (the "Software"), to deal\ +in the Software without restriction, including without limitation the rights\ +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ +copies of the Software, and to permit persons to whom the Software is\ +furnished to do so, subject to the following conditions:\ +\ +The above copyright notice and this permission notice shall be included in all\ +copies or substantial portions of the Software.\ +\ +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\ +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\ +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\ +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\ +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\ +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\ +SOFTWARE.\ +\ + +\f0\b\fs26 LICENSE-PLUGINS +\f1\b0\fs24 \ +DB Browser for SQLite includes support for TIFF and WebP images. The\ +support for these comes from the LibTIFF and WebP projects, which have\ +their own (Open Source) licenses, different to ours.\ +\ +LibTIFF - http://www.simplesystems.org/libtiff/\ +\ + Copyright (c) 1988-1997 Sam Leffler\ + Copyright (c) 1991-1997 Silicon Graphics, Inc.\ +\ + Permission to use, copy, modify, distribute, and sell this software and \ + its documentation for any purpose is hereby granted without fee, provided\ + that (i) the above copyright notices and this permission notice appear in\ + all copies of the software and related documentation, and (ii) the names of\ + Sam Leffler and Silicon Graphics may not be used in any advertising or\ + publicity relating to the software without the specific, prior written\ + permission of Sam Leffler and Silicon Graphics.\ +\ + THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, \ + EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY \ + WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. \ +\ + IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR\ + ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,\ + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\ + WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF \ + LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE \ + OF THIS SOFTWARE. \ +\ +WebP - https://developers.google.com/speed/webp/\ +\ + Copyright (c) 2010, Google Inc. All rights reserved.\ +\ + Redistribution and use in source and binary forms, with or without\ + modification, are permitted provided that the following conditions are\ + met:\ +\ + * Redistributions of source code must retain the above copyright\ + notice, this list of conditions and the following disclaimer.\ +\ + * 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.\ +\ + * Neither the name of Google 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 COPYRIGHT HOLDERS AND CONTRIBUTORS\ + "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 COPYRIGHT\ + HOLDER OR CONTRIBUTORS 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.\ +\ +Icons - https://codefisher.org/pastel-svg/\ +\ +Most of the icons come from the Pastel SVG icon set created by Michael\ +Buckley. We have obtained a special license (Creative Commons\ +Attribution Share Alike 4.0\ +http://creativecommons.org/licenses/by-sa/4.0/) but you might be\ +required to redistribute it under Creative Commons Attribution\ +NonCommercial Share Alike 4.0\ +http://creativecommons.org/licenses/by-nc-sa/4.0/\ +Check https://codefisher.org/pastel-svg/ for clarification.\ +\ +The construction emoji for the icon used in the nightly version come\ +from the OpenMoji under CC BY-SA 4.0 license.\ +Check https://openmoji.org/library/emoji-1F6A7/ and\ +https://openmoji.org/faq/ for clarification.\ +\ +Some icons might have other open licenses, check history of the files\ +under `src/icons`.} \ No newline at end of file diff --git a/installer/windows_on_arm/product.wxs b/installer/windows_on_arm/product.wxs new file mode 100644 index 000000000..dac12a4ef --- /dev/null +++ b/installer/windows_on_arm/product.wxs @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SHORTCUT_SQLITE_DESKTOP + + + + + SHORTCUT_SQLCIPHER_DESKTOP + + + + + + + SHORTCUT_SQLITE_PROGRAMMENU + + + + + SHORTCUT_SQLCIPHER_PROGRAMMENU + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LicenseAccepted = "1" + NOT Installed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSIS_INSTALLDIR + + + + + + + NSIS_INSTALLDIR + + + + + diff --git a/installer/windows_on_arm/resources/background.xcf b/installer/windows_on_arm/resources/background.xcf new file mode 100644 index 000000000..ebf51cf0f Binary files /dev/null and b/installer/windows_on_arm/resources/background.xcf differ diff --git a/installer/windows_on_arm/resources/banner.xcf b/installer/windows_on_arm/resources/banner.xcf new file mode 100644 index 000000000..10a3f83b7 Binary files /dev/null and b/installer/windows_on_arm/resources/banner.xcf differ diff --git a/installer/windows_on_arm/resources/icon.png b/installer/windows_on_arm/resources/icon.png new file mode 100644 index 000000000..f6505e913 Binary files /dev/null and b/installer/windows_on_arm/resources/icon.png differ diff --git a/installer/windows_on_arm/strings.wxl b/installer/windows_on_arm/strings.wxl new file mode 100644 index 000000000..f5af817de --- /dev/null +++ b/installer/windows_on_arm/strings.wxl @@ -0,0 +1,14 @@ + + + This Setup Wizard will install [ProductName] on your computer. If you have a previous version already installed, this installation process will update it. + + + [ProductName] Setup + {\WixUI_Font_Title}Shortcuts + Select the shortcuts for the application. + [ProductName] uses the latest version of SQLite, so you can enjoy all of its new features and bug fixes, but it does not have encryption support. It is also built with SQLCipher as a separate application. SQLCipher is an open source extension to SQLite providing transparent 256-bit AES encryption of database files, but uses a slightly older version of SQLite. Both applications (with and without SQLCipher) are installed and can run concurrently. This page allows you to choose the shortcuts for each application and where to place them. + DB Browser (SQLite) + DB Browser (SQLCipher) + Desktop + Program Menu + diff --git a/installer/windows_on_arm/translations.wxs b/installer/windows_on_arm/translations.wxs new file mode 100644 index 000000000..0bba89860 --- /dev/null +++ b/installer/windows_on_arm/translations.wxs @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/installer/windows_on_arm/ui.wxs b/installer/windows_on_arm/ui.wxs new file mode 100644 index 000000000..7fee7011f --- /dev/null +++ b/installer/windows_on_arm/ui.wxs @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + 1 + + + 1 + + + 1 + + + + + diff --git a/installer/windows_on_arm/variables.wxi b/installer/windows_on_arm/variables.wxi new file mode 100644 index 000000000..7c65c684e --- /dev/null +++ b/installer/windows_on_arm/variables.wxi @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/DB4S_PATCH_05 b/libs/DB4S_PATCH_05 new file mode 100644 index 000000000..0b956432b --- /dev/null +++ b/libs/DB4S_PATCH_05 @@ -0,0 +1,363 @@ +--- QScintilla_gpl-2.10.8/Qt4Qt5/qscintilla.pro 2018-10-01 15:46:06.000000000 +0200 ++++ qscintilla/Qt4Qt5/qscintilla.pro 2018-11-21 19:51:25.870248673 +0100 +@@ -23,24 +23,12 @@ + !win32:VERSION = 13.2.1 + + TEMPLATE = lib +-CONFIG += qt warn_off thread exceptions hide_symbols +- +-CONFIG(debug, debug|release) { +- mac: { +- TARGET = qscintilla2_qt$${QT_MAJOR_VERSION}_debug +- } else { +- win32: { +- TARGET = qscintilla2_qt$${QT_MAJOR_VERSION}d +- } else { +- TARGET = qscintilla2_qt$${QT_MAJOR_VERSION} +- } +- } +-} else { +- TARGET = qscintilla2_qt$${QT_MAJOR_VERSION} +-} +- ++TARGET = qscintilla2 ++CONFIG += qt warn_off thread exceptions hide_symbols staticlib debug_and_release + INCLUDEPATH += . ../include ../lexlib ../src + ++QMAKE_CXXFLAGS += -std=c++11 ++ + !CONFIG(staticlib) { + DEFINES += QSCINTILLA_MAKE_DLL + } +@@ -59,11 +47,6 @@ + DEFINES += QT_NO_ACCESSIBILITY + } + +-# For old versions of GCC. +-unix:!macx { +- CONFIG += c++11 +-} +- + # Comment this in if you want the internal Scintilla classes to be placed in a + # Scintilla namespace rather than pollute the global namespace. + #DEFINES += SCI_NAMESPACE +@@ -97,69 +80,20 @@ + + HEADERS = \ + ./Qsci/qsciglobal.h \ +- ./Qsci/qsciscintilla.h \ +- ./Qsci/qsciscintillabase.h \ +- ./Qsci/qsciabstractapis.h \ +- ./Qsci/qsciapis.h \ + ./Qsci/qscicommand.h \ + ./Qsci/qscicommandset.h \ + ./Qsci/qscidocument.h \ +- ./Qsci/qscilexer.h \ +- ./Qsci/qscilexeravs.h \ +- ./Qsci/qscilexerbash.h \ +- ./Qsci/qscilexerbatch.h \ +- ./Qsci/qscilexercmake.h \ +- ./Qsci/qscilexercoffeescript.h \ +- ./Qsci/qscilexercpp.h \ +- ./Qsci/qscilexercsharp.h \ +- ./Qsci/qscilexercss.h \ +- ./Qsci/qscilexercustom.h \ +- ./Qsci/qscilexerd.h \ +- ./Qsci/qscilexerdiff.h \ +- ./Qsci/qscilexeredifact.h \ +- ./Qsci/qscilexerfortran.h \ +- ./Qsci/qscilexerfortran77.h \ +- ./Qsci/qscilexerhtml.h \ +- ./Qsci/qscilexeridl.h \ +- ./Qsci/qscilexerjava.h \ +- ./Qsci/qscilexerjavascript.h \ +- ./Qsci/qscilexerjson.h \ +- ./Qsci/qscilexerlua.h \ +- ./Qsci/qscilexermakefile.h \ +- ./Qsci/qscilexermarkdown.h \ +- ./Qsci/qscilexermatlab.h \ +- ./Qsci/qscilexeroctave.h \ +- ./Qsci/qscilexerpascal.h \ +- ./Qsci/qscilexerperl.h \ +- ./Qsci/qscilexerpostscript.h \ +- ./Qsci/qscilexerpo.h \ +- ./Qsci/qscilexerpov.h \ +- ./Qsci/qscilexerproperties.h \ +- ./Qsci/qscilexerpython.h \ +- ./Qsci/qscilexerruby.h \ +- ./Qsci/qscilexerspice.h \ +- ./Qsci/qscilexersql.h \ +- ./Qsci/qscilexertcl.h \ +- ./Qsci/qscilexertex.h \ +- ./Qsci/qscilexerverilog.h \ +- ./Qsci/qscilexervhdl.h \ +- ./Qsci/qscilexerxml.h \ +- ./Qsci/qscilexeryaml.h \ +- ./Qsci/qscimacro.h \ + ./Qsci/qsciprinter.h \ + ./Qsci/qscistyle.h \ + ./Qsci/qscistyledtext.h \ + ListBoxQt.h \ +- SciAccessibility.h \ +- SciClasses.h \ + SciNamespace.h \ +- ScintillaQt.h \ + ../include/ILexer.h \ + ../include/Platform.h \ +- ../include/Sci_Position.h \ + ../include/SciLexer.h \ + ../include/Scintilla.h \ + ../include/ScintillaWidget.h \ ++ ../include/Sci_Position.h \ + ../lexlib/Accessor.h \ + ../lexlib/CharacterCategory.h \ + ../lexlib/CharacterSet.h \ +@@ -170,7 +104,6 @@ + ../lexlib/LexerSimple.h \ + ../lexlib/OptionSet.h \ + ../lexlib/PropSetSimple.h \ +- ../lexlib/StringCopy.h \ + ../lexlib/StyleContext.h \ + ../lexlib/SubStyles.h \ + ../lexlib/WordList.h \ +@@ -184,15 +117,12 @@ + ../src/ContractionState.h \ + ../src/Decoration.h \ + ../src/Document.h \ +- ../src/EditModel.h \ + ../src/Editor.h \ +- ../src/EditView.h \ + ../src/ExternalLexer.h \ + ../src/FontQuality.h \ + ../src/Indicator.h \ + ../src/KeyMap.h \ + ../src/LineMarker.h \ +- ../src/MarginView.h \ + ../src/Partitioning.h \ + ../src/PerLine.h \ + ../src/PositionCache.h \ +@@ -205,7 +135,26 @@ + ../src/UnicodeFromUTF8.h \ + ../src/UniConversion.h \ + ../src/ViewStyle.h \ +- ../src/XPM.h ++ ../src/XPM.h \ ++ ../src/Position.h \ ++ ../src/SparseVector.h \ ++ ./Qsci/qsciscintilla.h \ ++ ./Qsci/qsciscintillabase.h \ ++ ./Qsci/qsciabstractapis.h \ ++ ./Qsci/qsciapis.h \ ++ ./Qsci/qscilexer.h \ ++ ./Qsci/qscilexercustom.h \ ++ ./Qsci/qscilexersql.h \ ++ ./Qsci/qscilexerjson.h \ ++ ./Qsci/qscilexerhtml.h \ ++ ./Qsci/qscilexerxml.h \ ++ ./Qsci/qscilexerjavascript.h \ ++ ./Qsci/qscilexercpp.h \ ++ ./Qsci/qscilexerpython.h \ ++ ./Qsci/qscimacro.h \ ++ SciClasses.h \ ++ ScintillaQt.h \ ++ SciAccessibility.h + + SOURCES = \ + qsciscintilla.cpp \ +@@ -216,161 +165,28 @@ + qscicommandset.cpp \ + qscidocument.cpp \ + qscilexer.cpp \ +- qscilexeravs.cpp \ +- qscilexerbash.cpp \ +- qscilexerbatch.cpp \ +- qscilexercmake.cpp \ +- qscilexercoffeescript.cpp \ +- qscilexercpp.cpp \ +- qscilexercsharp.cpp \ +- qscilexercss.cpp \ + qscilexercustom.cpp \ +- qscilexerd.cpp \ +- qscilexerdiff.cpp \ +- qscilexeredifact.cpp \ +- qscilexerfortran.cpp \ +- qscilexerfortran77.cpp \ ++ qscilexersql.cpp \ ++ qscilexerjson.cpp \ + qscilexerhtml.cpp \ +- qscilexeridl.cpp \ +- qscilexerjava.cpp \ ++ qscilexerxml.cpp \ + qscilexerjavascript.cpp \ +- qscilexerjson.cpp \ +- qscilexerlua.cpp \ +- qscilexermakefile.cpp \ +- qscilexermarkdown.cpp \ +- qscilexermatlab.cpp \ +- qscilexeroctave.cpp \ +- qscilexerpascal.cpp \ +- qscilexerperl.cpp \ +- qscilexerpostscript.cpp \ +- qscilexerpo.cpp \ +- qscilexerpov.cpp \ +- qscilexerproperties.cpp \ ++ qscilexercpp.cpp \ + qscilexerpython.cpp \ +- qscilexerruby.cpp \ +- qscilexerspice.cpp \ +- qscilexersql.cpp \ +- qscilexertcl.cpp \ +- qscilexertex.cpp \ +- qscilexerverilog.cpp \ +- qscilexervhdl.cpp \ +- qscilexerxml.cpp \ +- qscilexeryaml.cpp \ + qscimacro.cpp \ + qsciprinter.cpp \ + qscistyle.cpp \ + qscistyledtext.cpp \ +- MacPasteboardMime.cpp \ +- InputMethod.cpp \ +- SciAccessibility.cpp \ ++ MacPasteboardMime.cpp \ ++ InputMethod.cpp \ + SciClasses.cpp \ + ListBoxQt.cpp \ + PlatQt.cpp \ + ScintillaQt.cpp \ +- ../lexers/LexA68k.cpp \ +- ../lexers/LexAbaqus.cpp \ +- ../lexers/LexAda.cpp \ +- ../lexers/LexAPDL.cpp \ +- ../lexers/LexAsm.cpp \ +- ../lexers/LexAsn1.cpp \ +- ../lexers/LexASY.cpp \ +- ../lexers/LexAU3.cpp \ +- ../lexers/LexAVE.cpp \ +- ../lexers/LexAVS.cpp \ +- ../lexers/LexBaan.cpp \ +- ../lexers/LexBash.cpp \ +- ../lexers/LexBasic.cpp \ +- ../lexers/LexBatch.cpp \ +- ../lexers/LexBibTeX.cpp \ +- ../lexers/LexBullant.cpp \ +- ../lexers/LexCaml.cpp \ +- ../lexers/LexCLW.cpp \ +- ../lexers/LexCmake.cpp \ +- ../lexers/LexCOBOL.cpp \ +- ../lexers/LexCoffeeScript.cpp \ +- ../lexers/LexConf.cpp \ +- ../lexers/LexCPP.cpp \ +- ../lexers/LexCrontab.cpp \ +- ../lexers/LexCsound.cpp \ +- ../lexers/LexCSS.cpp \ +- ../lexers/LexD.cpp \ +- ../lexers/LexDiff.cpp \ +- ../lexers/LexDMAP.cpp \ +- ../lexers/LexDMIS.cpp \ +- ../lexers/LexECL.cpp \ +- ../lexers/LexEDIFACT.cpp \ +- ../lexers/LexEiffel.cpp \ +- ../lexers/LexErlang.cpp \ +- ../lexers/LexErrorList.cpp \ +- ../lexers/LexEScript.cpp \ +- ../lexers/LexFlagship.cpp \ +- ../lexers/LexForth.cpp \ +- ../lexers/LexFortran.cpp \ +- ../lexers/LexGAP.cpp \ +- ../lexers/LexGui4Cli.cpp \ +- ../lexers/LexHaskell.cpp \ +- ../lexers/LexHex.cpp \ +- ../lexers/LexHTML.cpp \ +- ../lexers/LexInno.cpp \ +- ../lexers/LexJSON.cpp \ +- ../lexers/LexKix.cpp \ +- ../lexers/LexKVIrc.cpp \ +- ../lexers/LexLaTeX.cpp \ +- ../lexers/LexLisp.cpp \ +- ../lexers/LexLout.cpp \ +- ../lexers/LexLua.cpp \ +- ../lexers/LexMagik.cpp \ +- ../lexers/LexMake.cpp \ +- ../lexers/LexMarkdown.cpp \ +- ../lexers/LexMatlab.cpp \ +- ../lexers/LexMetapost.cpp \ +- ../lexers/LexMMIXAL.cpp \ +- ../lexers/LexModula.cpp \ +- ../lexers/LexMPT.cpp \ +- ../lexers/LexMSSQL.cpp \ +- ../lexers/LexMySQL.cpp \ +- ../lexers/LexNimrod.cpp \ +- ../lexers/LexNsis.cpp \ +- ../lexers/LexNull.cpp \ +- ../lexers/LexOpal.cpp \ +- ../lexers/LexOScript.cpp \ +- ../lexers/LexPascal.cpp \ +- ../lexers/LexPB.cpp \ +- ../lexers/LexPerl.cpp \ +- ../lexers/LexPLM.cpp \ +- ../lexers/LexPO.cpp \ +- ../lexers/LexPOV.cpp \ +- ../lexers/LexPowerPro.cpp \ +- ../lexers/LexPowerShell.cpp \ +- ../lexers/LexProgress.cpp \ +- ../lexers/LexProps.cpp \ +- ../lexers/LexPS.cpp \ +- ../lexers/LexPython.cpp \ +- ../lexers/LexR.cpp \ +- ../lexers/LexRebol.cpp \ +- ../lexers/LexRegistry.cpp \ +- ../lexers/LexRuby.cpp \ +- ../lexers/LexRust.cpp \ +- ../lexers/LexScriptol.cpp \ +- ../lexers/LexSmalltalk.cpp \ +- ../lexers/LexSML.cpp \ +- ../lexers/LexSorcus.cpp \ +- ../lexers/LexSpecman.cpp \ +- ../lexers/LexSpice.cpp \ ++ SciAccessibility.cpp \ + ../lexers/LexSQL.cpp \ +- ../lexers/LexSTTXT.cpp \ +- ../lexers/LexTACL.cpp \ +- ../lexers/LexTADS3.cpp \ +- ../lexers/LexTAL.cpp \ +- ../lexers/LexTCL.cpp \ +- ../lexers/LexTCMD.cpp \ +- ../lexers/LexTeX.cpp \ +- ../lexers/LexTxt2tags.cpp \ +- ../lexers/LexVB.cpp \ +- ../lexers/LexVerilog.cpp \ +- ../lexers/LexVHDL.cpp \ +- ../lexers/LexVisualProlog.cpp \ +- ../lexers/LexYAML.cpp \ ++ ../lexers/LexJSON.cpp \ ++ ../lexers/LexHTML.cpp \ + ../lexlib/Accessor.cpp \ + ../lexlib/CharacterCategory.cpp \ + ../lexlib/CharacterSet.cpp \ +@@ -391,20 +207,20 @@ + ../src/ContractionState.cpp \ + ../src/Decoration.cpp \ + ../src/Document.cpp \ +- ../src/EditModel.cpp \ + ../src/Editor.cpp \ ++ ../src/EditModel.cpp \ + ../src/EditView.cpp \ + ../src/ExternalLexer.cpp \ + ../src/Indicator.cpp \ +- ../src/KeyMap.cpp \ ++ ../src/KeyMap.cpp \ + ../src/LineMarker.cpp \ + ../src/MarginView.cpp \ + ../src/PerLine.cpp \ + ../src/PositionCache.cpp \ +- ../src/RESearch.cpp \ ++ ../src/RESearch.cpp \ + ../src/RunStyles.cpp \ +- ../src/ScintillaBase.cpp \ +- ../src/Selection.cpp \ ++ ../src/ScintillaBase.cpp \ ++ ../src/Selection.cpp \ + ../src/Style.cpp \ + ../src/UniConversion.cpp \ + ../src/ViewStyle.cpp \ diff --git a/libs/DB4S_PATCH_06 b/libs/DB4S_PATCH_06 new file mode 100644 index 000000000..eff21c8b6 --- /dev/null +++ b/libs/DB4S_PATCH_06 @@ -0,0 +1,131 @@ +--- QScintilla_gpl-2.10.8/src/Catalogue.cpp 2018-10-01 15:41:57.000000000 +0200 ++++ qscintilla/src/Catalogue.cpp 2018-11-18 16:09:52.796704316 +0100 +@@ -77,124 +77,10 @@ + + //++Autogenerated -- run scripts/LexGen.py to regenerate + //**\(\tLINK_LEXER(\*);\n\) +- LINK_LEXER(lmA68k); +- LINK_LEXER(lmAbaqus); +- LINK_LEXER(lmAda); +- LINK_LEXER(lmAPDL); +- LINK_LEXER(lmAs); +- LINK_LEXER(lmAsm); +- LINK_LEXER(lmAsn1); +- LINK_LEXER(lmASY); +- LINK_LEXER(lmAU3); +- LINK_LEXER(lmAVE); +- LINK_LEXER(lmAVS); +- LINK_LEXER(lmBaan); +- LINK_LEXER(lmBash); +- LINK_LEXER(lmBatch); +- LINK_LEXER(lmBibTeX); +- LINK_LEXER(lmBlitzBasic); +- LINK_LEXER(lmBullant); +- LINK_LEXER(lmCaml); +- LINK_LEXER(lmClw); +- LINK_LEXER(lmClwNoCase); +- LINK_LEXER(lmCmake); +- LINK_LEXER(lmCOBOL); +- LINK_LEXER(lmCoffeeScript); +- LINK_LEXER(lmConf); +- LINK_LEXER(lmCPP); +- LINK_LEXER(lmCPPNoCase); +- LINK_LEXER(lmCsound); +- LINK_LEXER(lmCss); +- LINK_LEXER(lmD); +- LINK_LEXER(lmDiff); +- LINK_LEXER(lmDMAP); +- LINK_LEXER(lmDMIS); +- LINK_LEXER(lmECL); +- LINK_LEXER(lmEDIFACT); +- LINK_LEXER(lmEiffel); +- LINK_LEXER(lmEiffelkw); +- LINK_LEXER(lmErlang); +- LINK_LEXER(lmErrorList); +- LINK_LEXER(lmESCRIPT); +- LINK_LEXER(lmF77); +- LINK_LEXER(lmFlagShip); +- LINK_LEXER(lmForth); +- LINK_LEXER(lmFortran); +- LINK_LEXER(lmFreeBasic); +- LINK_LEXER(lmGAP); +- LINK_LEXER(lmGui4Cli); +- LINK_LEXER(lmHaskell); +- LINK_LEXER(lmHTML); +- LINK_LEXER(lmIHex); +- LINK_LEXER(lmInno); +- LINK_LEXER(lmJSON); +- LINK_LEXER(lmKix); +- LINK_LEXER(lmKVIrc); +- LINK_LEXER(lmLatex); +- LINK_LEXER(lmLISP); +- LINK_LEXER(lmLiterateHaskell); +- LINK_LEXER(lmLot); +- LINK_LEXER(lmLout); +- LINK_LEXER(lmLua); +- LINK_LEXER(lmMagikSF); +- LINK_LEXER(lmMake); +- LINK_LEXER(lmMarkdown); +- LINK_LEXER(lmMatlab); +- LINK_LEXER(lmMETAPOST); +- LINK_LEXER(lmMMIXAL); +- LINK_LEXER(lmModula); +- LINK_LEXER(lmMSSQL); +- LINK_LEXER(lmMySQL); +- LINK_LEXER(lmNimrod); +- LINK_LEXER(lmNncrontab); +- LINK_LEXER(lmNsis); +- LINK_LEXER(lmNull); +- LINK_LEXER(lmOctave); +- LINK_LEXER(lmOpal); +- LINK_LEXER(lmOScript); +- LINK_LEXER(lmPascal); +- LINK_LEXER(lmPB); +- LINK_LEXER(lmPerl); +- LINK_LEXER(lmPHPSCRIPT); +- LINK_LEXER(lmPLM); +- LINK_LEXER(lmPO); +- LINK_LEXER(lmPOV); +- LINK_LEXER(lmPowerPro); +- LINK_LEXER(lmPowerShell); +- LINK_LEXER(lmProgress); +- LINK_LEXER(lmProps); +- LINK_LEXER(lmPS); +- LINK_LEXER(lmPureBasic); +- LINK_LEXER(lmPython); +- LINK_LEXER(lmR); +- LINK_LEXER(lmREBOL); +- LINK_LEXER(lmRegistry); +- LINK_LEXER(lmRuby); +- LINK_LEXER(lmRust); +- LINK_LEXER(lmScriptol); +- LINK_LEXER(lmSmalltalk); +- LINK_LEXER(lmSML); +- LINK_LEXER(lmSorc); +- LINK_LEXER(lmSpecman); +- LINK_LEXER(lmSpice); +- LINK_LEXER(lmSQL); +- LINK_LEXER(lmSrec); +- LINK_LEXER(lmSTTXT); +- LINK_LEXER(lmTACL); +- LINK_LEXER(lmTADS3); +- LINK_LEXER(lmTAL); +- LINK_LEXER(lmTCL); +- LINK_LEXER(lmTCMD); +- LINK_LEXER(lmTEHex); +- LINK_LEXER(lmTeX); +- LINK_LEXER(lmTxt2tags); +- LINK_LEXER(lmVB); +- LINK_LEXER(lmVBScript); +- LINK_LEXER(lmVerilog); +- LINK_LEXER(lmVHDL); +- LINK_LEXER(lmVisualProlog); +- LINK_LEXER(lmXML); +- LINK_LEXER(lmYAML); ++ LINK_LEXER(lmSQL); ++ LINK_LEXER(lmJSON); ++ LINK_LEXER(lmHTML); ++ LINK_LEXER(lmXML); + + //--Autogenerated -- end of automatically generated section + diff --git a/libs/antlr-2.7.7/AUTHORS b/libs/antlr-2.7.7/AUTHORS deleted file mode 100644 index 7bdc48522..000000000 --- a/libs/antlr-2.7.7/AUTHORS +++ /dev/null @@ -1,2 +0,0 @@ -Author: - Peter Wells diff --git a/libs/antlr-2.7.7/CMakeLists.txt b/libs/antlr-2.7.7/CMakeLists.txt deleted file mode 100644 index ac09913e9..000000000 --- a/libs/antlr-2.7.7/CMakeLists.txt +++ /dev/null @@ -1,91 +0,0 @@ -cmake_minimum_required(VERSION 2.6) - -set(ANTLR_SRC - src/ANTLRUtil.cpp - src/ASTFactory.cpp - src/ASTNULLType.cpp - src/ASTRefCount.cpp - src/BaseAST.cpp - src/BitSet.cpp - src/CharBuffer.cpp - src/CharScanner.cpp - src/CommonAST.cpp - src/CommonASTWithHiddenTokens.cpp - src/CommonHiddenStreamToken.cpp - src/CommonToken.cpp - src/InputBuffer.cpp - src/LLkParser.cpp - src/MismatchedCharException.cpp - src/MismatchedTokenException.cpp - src/NoViableAltException.cpp - src/NoViableAltForCharException.cpp - src/Parser.cpp - src/RecognitionException.cpp - src/String.cpp - src/Token.cpp - src/TokenBuffer.cpp - src/TokenRefCount.cpp - src/TokenStreamBasicFilter.cpp - src/TokenStreamHiddenTokenFilter.cpp - src/TokenStreamRewriteEngine.cpp - src/TokenStreamSelector.cpp - src/TreeParser.cpp - ) - -set(ANTLR_HDR - antlr/ANTLRException.hpp - antlr/ANTLRUtil.hpp - antlr/AST.hpp - antlr/ASTArray.hpp - antlr/ASTFactory.hpp - antlr/ASTNULLType.hpp - antlr/ASTPair.hpp - antlr/ASTRefCount.hpp - antlr/BaseAST.hpp - antlr/BitSet.hpp - antlr/CharBuffer.hpp - antlr/CharInputBuffer.hpp - antlr/CharScanner.hpp - antlr/CharStreamException.hpp - antlr/CharStreamIOException.hpp - antlr/CircularQueue.hpp - antlr/CommonAST.hpp - antlr/CommonASTWithHiddenTokens.hpp - antlr/CommonHiddenStreamToken.hpp - antlr/CommonToken.hpp - antlr/IOException.hpp - antlr/InputBuffer.hpp - antlr/LLkParser.hpp - antlr/LexerSharedInputState.hpp - antlr/MismatchedCharException.hpp - antlr/MismatchedTokenException.hpp - antlr/NoViableAltException.hpp - antlr/NoViableAltForCharException.hpp - antlr/Parser.hpp - antlr/ParserSharedInputState.hpp - antlr/RecognitionException.hpp - antlr/RefCount.hpp - antlr/SemanticException.hpp - antlr/String.hpp - antlr/Token.hpp - antlr/TokenBuffer.hpp - antlr/TokenRefCount.hpp - antlr/TokenStream.hpp - antlr/TokenStreamBasicFilter.hpp - antlr/TokenStreamException.hpp - antlr/TokenStreamHiddenTokenFilter.hpp - antlr/TokenStreamIOException.hpp - antlr/TokenStreamRecognitionException.hpp - antlr/TokenStreamRetryException.hpp - antlr/TokenStreamRewriteEngine.hpp - antlr/TokenStreamSelector.hpp - antlr/TokenWithIndex.hpp - antlr/TreeParser.hpp - antlr/TreeParserSharedInputState.hpp - antlr/config.hpp - ) - -include_directories(.) - -add_library(antlr ${ANTLR_SRC} ${ANTLR_HDR}) - diff --git a/libs/antlr-2.7.7/LICENSE.txt b/libs/antlr-2.7.7/LICENSE.txt deleted file mode 100644 index 0ec09a95c..000000000 --- a/libs/antlr-2.7.7/LICENSE.txt +++ /dev/null @@ -1,31 +0,0 @@ - -SOFTWARE RIGHTS - -ANTLR 1989-2006 Developed by Terence Parr -Partially supported by University of San Francisco & jGuru.com - -We reserve no legal rights to the ANTLR--it is fully in the -public domain. An individual or company may do whatever -they wish with source code distributed with ANTLR or the -code generated by ANTLR, including the incorporation of -ANTLR, or its output, into commerical software. - -We encourage users to develop software with ANTLR. However, -we do ask that credit is given to us for developing -ANTLR. By "credit", we mean that if you use ANTLR or -incorporate any source code into one of your programs -(commercial product, research project, or otherwise) that -you acknowledge this fact somewhere in the documentation, -research report, etc... If you like ANTLR and have -developed a nice tool with the output, please mention that -you developed it using ANTLR. In addition, we ask that the -headers remain intact in our source code. As long as these -guidelines are kept, we expect to continue enhancing this -system and expect to make other tools available as they are -completed. - -The primary ANTLR guy: - -Terence Parr -parrt@cs.usfca.edu -parrt@antlr.org diff --git a/libs/antlr-2.7.7/README b/libs/antlr-2.7.7/README deleted file mode 100644 index f6e6089dc..000000000 --- a/libs/antlr-2.7.7/README +++ /dev/null @@ -1,191 +0,0 @@ -ANTLR C++ Support Libraries Additional Notes - -1.1 Using Microsoft Visual C++ - -Currently this is still (or again) somewhat experimental. MSVC is not the -development platform and I don't have access to the compiler currently. -YMMV - -Make sure you compile the library *and* your project with the same -settings. (multithreaded/debug/etc.) - -Visual C++ 6 only is supported for static builds. Some hacking and STLPort -is needed to build a DLL (only for experts). - -Visual C++ 7.0 and 7.1 should support both static and DLL builds (DLL -builds might be broken). In general the main problem is getting the right -template instantiations into the DLL. For 7.0 you might have to tweak the -list in lib/cpp/src/dll.cpp. I'm told 7.1 does not need this. - -For a static build (works probably best) - -1. Create a win32 static library project. -2. Enable RTTI. (Run Time Type Information) -3. Add the source files from /antlr/lib/cpp/src to the project - (except dll.cpp) put /antlr/lib/cpp in the search path for - include files. - -For the DLL build (MSVC 7.0 tested) - -* Project settings ("create new project" dialogs) - - Win32 project - - Application Settings - - Application type - - DLL - - Additional options - - Export symbols -* Project properties (change defaults to) - - Configuration Properties - - C/C++ - - General - - Additional Include Directories - - drive:\antlr-2.7.2\lib\cpp - - Preprocessor - - Preprocessor Definitions - - WIN32;_DEBUG;_WINDOWS;_USRDLL;ANTLR_EXPORTS - - Code Generation - - Runtime Library - - Multi-threaded Debug DLL (/MDd) - - Enable Function-Level Linking: - - Yes - - Language - - Enable Run-Time Type Info - - Yes - - Precompiled Headers - - Create/Use Precompiled Headers - -NOTE: Do not use the antlr generated and support library in a multithreaded -way. It was not designed for a multithreaded environment. - -1.3 Building with GCJ - -NOTE: outdated the new Makefiles do not support this anymore. - -It is also possible to build a native binary of ANTLR. This is somewhat -experimental and can be enabled by giving the --enable-gcj option to -configure. You need a recent GCC to do this and even then the constructed -binary crashes on some platforms. - -2. Tested Compilers for this release - -Don't get worried if your favourite compiler is not mentioned here. Any -somewhat recent ISO compliant C++ compiler should have little trouble with -the runtime library. - -*NOTE* this section was not updated for the new configure script/Makefiles some of the things listed here to pass different flags to configure may not work anymore. Check INSTALL.txt or handedit generated scripts after configure. - -2.1 Solaris - -2.1.1 Sun Workshop 6.0 - -Identifies itself as: - - CC: Sun WorkShop 6 2000/08/30 C++ 5.1 Patch 109490-01 - -Compiles out of the box configure using: - - CXX=CC CC=cc AR=CC ARFLAGS="-xar -o" ./configure - -Use CC to make the archive to ensure bundling of template instances. Check -manpage for details. - -2.1.2 GCC - -Tested 3.0.4, 3.2.1, 3.2.3, 3.3.2, 3.4.0. - -All tested gcc are using a recent GNU binutils for linker and assembler. -You will probably run into trouble if you use the solaris -linker/assembler. - -2.2 Windows - -2.2.1 Visual C++ - -Visual C++ 6.0 reported to work well with static build. DLL build not -supported (reported to work when using STLPort in previous ANTLR versions). -I heart that in some cases there could be problems with precompiled headers -and the use of normal '/' in the #include directives (with service pack 5). - -Visual C++ 7.0 reported to work, might need some tweaks for DLL builds due -to some shuffling around in the code. - -Visual C++ 7.1 reported to work, might need some tweaks, see above. - -My current guess is that DLL builds are all over the line broken. A -workaround is to make a DLL from the complete generated parser including -the static ANTLR support library. - -2.2.2 Cygwin/MinGW - -Not expecting any big problems maybe some tweaks needed in configure. - -3. Old notes for a number of compilers - -3.1 SGI Irix 6.5.10 MIPSPro compiler - -You can't compile ANTLR with the MIPSPro compiler on anything < 6.5.10 -because SGI just fixed a big bug dealing with namespaces in that release. - -Note: To get it to compile do basically the following: - - CC=cc CXX=CC CXXFLAGS=-LANG:std ./configure --prefix=/usr/local/antlr - -Note probably dates back to 2.7.0-2.7.1 era. - -3.2 Sun CC 5 - -It may be you'll have to change one or two static_cast()'s to a -C-style cast. (think that's a compiler bug) - -Configure using: - - CXX=CC CC=cc RANLIB="CC -xar" ./configure - -The custom ranlib is needed to get the template instances into the archive. -Check manpages. Maybe the Sun CC 6 instructions above will work as well. - -3.3 GCC on some platforms (Alpha Tru64) - -The -pipe option not supported it seems. Configure using: - -CFLAGS="-W -Wall" ./configure - -Or remove the -pipe's from the generated scripts/Config.make. - -4. IT DOESN'T WORK!? - -4.1 Compile problems - -The ANTLR code uses some relatively new features of C++ which not all -compilers support yet (such as namespaces, and new style standard headers). - -At the moment, you may be able to work around the problem with a few nasty -tricks: - -Try creating some header files like 'iostream' just containing: - -#include - -and compile with an option to define away the word 'std', such as - -CC .... -Dstd= .... - -Also in the antlr subdirectory there's a file config.hpp. Tweak this one to -enable/disable the different bells and whistles used in the rest of the code. -Don't forget to submit those changes back to us (along with compiler info) -so we can incorporate them in our next release! - -4.2 Reporting problems - -When reporting problems please try to be as specific as possible e.g. -mention ANTLR release, and try to provide a clear and minimal example of -what goes wrong and what you expected. - -Bug reports can be done to Terence or the current subsystem maintainers as -mentioned in the doc directory. Another option is to use the mailing list -linked from http://www.antlr.org. - -Before reporting a problem you might want to try with a development -snapshot, there is a link to these in the File Sharing section of - -http://www.antlr.org. diff --git a/libs/antlr-2.7.7/TODO b/libs/antlr-2.7.7/TODO deleted file mode 100644 index 693ec995a..000000000 --- a/libs/antlr-2.7.7/TODO +++ /dev/null @@ -1,83 +0,0 @@ -* ANTLR should issue a warning if you have protected rules and - filter == true or filter=IGNORE in a lexer? - This can be tackled by tracking rule references in a more general approach. - -* Have a look at the doc's. - -* Add allocators to the objects - -* Look more at exception handling - -* TreeParser.cpp around line 76 the MismatchedTokenException here does not - use ttype to improve it's errormessage. Would require changing a bit in - MismatchedTokenException.cpp - -* On Thu, Sep 21, 2000 at 12:33:48AM -0700, John Lambert wrote: - > 1) The literal EOF is not defined and causes the define of EOF_CHAR in - > CharScanner.hpp to fail. - - ANTLR with STL Port. Changing the EOF define to char_traits::eof() - breaks things for gcc-2.95.2. Fix this in next release portably. - http://www.egroups.com/message/antlr-interest/2520 - -* Fix heterogeneous AST stuff. It boils down to adding a method to AST - types that knows how to duplicate the sucker. - -> done clone() added. - Knowing one factory is not enough. - -> done in C++ have a superfactory. - Also look at having to set the astfactory by hand (this is not 100% necessary). - Double check generated code. - http://groups.yahoo.com/group/antlr-interest/message/2496 - -* Look at messageLog stuff Ross Bencina proposed. Looks good at first glance. - http://www.egroups.com/message/antlr-interest/2555 - -* Add RW_STL & CC 4.2 patch from Ulrich Teichert: - See my mailbox.. and these comments from Ross Bencina: - http://www.egroups.com/message/antlr-interest/2494 - -* in action.g (java and C++) ##.initialize / ##->initialize is not - recognized as an assigment to the root node. In the case ## is followed - by ./-> initialize transInfo.assignToRoot should be set to true. - Report by Matthew Ford (12 march 2001) - -* Add TokenLabelType option for generated lexers. Hmmm can already set token - factory. Then again.. you may run into a cast fest.. - -* Fix some #line counting oddities (Mike Barnett) - > nonterm - > { - > ## = #([TOK,"TOK"], - > ... Other stuff ... - > ); - > f(); - > } - generates wrong #line info need to fix action.g a bit better. - -* This one triggers a bug in antlr's codegen. - #perform_action = #( create_tau_ast(#p1->getLine(),#p1->getColumn()), #p1 ); - - #p1 are replaced by p1 in stead of p1_AST. It's really time to rewrite this - mess. - - Workaround: - - RefModest_AST tau = create_tau_ast(#p1->getLine(),#p1->getColumn()); - #perform_action = #( tau, #p1 ); - -* Unicode and related. - - The patch from Jean-Daniel Fekete is an approach. But has some issues. - + It is probably necessary to discern an 'internal' string/char type and - 'external' ones. The external ones are for the lexer input. The - 'internal ones' are for standard antlr error messages etc. Translators - from external to internal should be provided. - Hmm on second thought.. probably not really an issue. - + What should the lexer read? - - Unicode units from a 'unicode reader' in a sense this unicode reader - is a lexer itself. Just reading iconv/iconv_open manpages.. Maybe we - can hide this with iconv in the InputBuffer mechanisms? - - Interpret unicode ourselves. Ugh don't want to think of that right now. - we probably redo something that has been done. Only problem is that we - need something that's portable (C++ case) - + What changes are necessary in the rest of the code to support a wide - character set? Think most should be handled in/below the lexer level. diff --git a/libs/antlr-2.7.7/antlr.pro b/libs/antlr-2.7.7/antlr.pro deleted file mode 100644 index b2430e3be..000000000 --- a/libs/antlr-2.7.7/antlr.pro +++ /dev/null @@ -1,89 +0,0 @@ -TEMPLATE = lib - -CONFIG += staticlib -CONFIG += debug_and_release - -INCLUDEPATH += ./ - -HEADERS += \ - antlr/config.hpp \ - antlr/TreeParserSharedInputState.hpp \ - antlr/TreeParser.hpp \ - antlr/TokenWithIndex.hpp \ - antlr/TokenStreamSelector.hpp \ - antlr/TokenStreamRewriteEngine.hpp \ - antlr/TokenStreamRetryException.hpp \ - antlr/TokenStreamRecognitionException.hpp \ - antlr/TokenStreamIOException.hpp \ - antlr/TokenStreamHiddenTokenFilter.hpp \ - antlr/TokenStreamException.hpp \ - antlr/TokenStreamBasicFilter.hpp \ - antlr/TokenStream.hpp \ - antlr/TokenRefCount.hpp \ - antlr/TokenBuffer.hpp \ - antlr/Token.hpp \ - antlr/String.hpp \ - antlr/SemanticException.hpp \ - antlr/RefCount.hpp \ - antlr/RecognitionException.hpp \ - antlr/ParserSharedInputState.hpp \ - antlr/Parser.hpp \ - antlr/NoViableAltForCharException.hpp \ - antlr/NoViableAltException.hpp \ - antlr/MismatchedTokenException.hpp \ - antlr/MismatchedCharException.hpp \ - antlr/LexerSharedInputState.hpp \ - antlr/LLkParser.hpp \ - antlr/InputBuffer.hpp \ - antlr/IOException.hpp \ - antlr/CommonToken.hpp \ - antlr/CommonHiddenStreamToken.hpp \ - antlr/CommonASTWithHiddenTokens.hpp \ - antlr/CommonAST.hpp \ - antlr/CircularQueue.hpp \ - antlr/CharStreamIOException.hpp \ - antlr/CharStreamException.hpp \ - antlr/CharScanner.hpp \ - antlr/CharInputBuffer.hpp \ - antlr/CharBuffer.hpp \ - antlr/BitSet.hpp \ - antlr/BaseAST.hpp \ - antlr/ASTRefCount.hpp \ - antlr/ASTPair.hpp \ - antlr/ASTNULLType.hpp \ - antlr/ASTFactory.hpp \ - antlr/ASTArray.hpp \ - antlr/AST.hpp \ - antlr/ANTLRUtil.hpp \ - antlr/ANTLRException.hpp - -SOURCES += \ - src/TreeParser.cpp \ - src/TokenStreamSelector.cpp \ - src/TokenStreamRewriteEngine.cpp \ - src/TokenStreamHiddenTokenFilter.cpp \ - src/TokenStreamBasicFilter.cpp \ - src/TokenRefCount.cpp \ - src/TokenBuffer.cpp \ - src/Token.cpp \ - src/String.cpp \ - src/RecognitionException.cpp \ - src/Parser.cpp \ - src/NoViableAltForCharException.cpp \ - src/NoViableAltException.cpp \ - src/MismatchedTokenException.cpp \ - src/MismatchedCharException.cpp \ - src/LLkParser.cpp \ - src/InputBuffer.cpp \ - src/CommonToken.cpp \ - src/CommonHiddenStreamToken.cpp \ - src/CommonASTWithHiddenTokens.cpp \ - src/CommonAST.cpp \ - src/CharScanner.cpp \ - src/CharBuffer.cpp \ - src/BitSet.cpp \ - src/BaseAST.cpp \ - src/ASTRefCount.cpp \ - src/ASTNULLType.cpp \ - src/ASTFactory.cpp \ - src/ANTLRUtil.cpp diff --git a/libs/antlr-2.7.7/antlr/ANTLRException.hpp b/libs/antlr-2.7.7/antlr/ANTLRException.hpp deleted file mode 100644 index c91e927db..000000000 --- a/libs/antlr-2.7.7/antlr/ANTLRException.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef INC_ANTLRException_hpp__ -#define INC_ANTLRException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/ANTLRException.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class ANTLR_API ANTLRException -{ -public: - /// Create ANTLR base exception without error message - ANTLRException() : text("") - { - } - /// Create ANTLR base exception with error message - ANTLRException(const ANTLR_USE_NAMESPACE(std)string& s) - : text(s) - { - } - virtual ~ANTLRException() throw() - { - } - - /** Return complete error message with line/column number info (if present) - * @note for your own exceptions override this one. Call getMessage from - * here to get the 'clean' error message stored in the text attribute. - */ - virtual ANTLR_USE_NAMESPACE(std)string toString() const - { - return text; - } - - /** Return error message without additional info (if present) - * @note when making your own exceptions classes override toString - * and call in toString getMessage which relays the text attribute - * from here. - */ - virtual ANTLR_USE_NAMESPACE(std)string getMessage() const - { - return text; - } -private: - ANTLR_USE_NAMESPACE(std)string text; -}; -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_ANTLRException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/ANTLRUtil.hpp b/libs/antlr-2.7.7/antlr/ANTLRUtil.hpp deleted file mode 100644 index eeb7d0645..000000000 --- a/libs/antlr-2.7.7/antlr/ANTLRUtil.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef INC_ANTLRUtil_hpp__ -#define INC_ANTLRUtil_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id:$ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** Eat whitespace from the input stream - * @param is the stream to read from - */ -ANTLR_USE_NAMESPACE(std)istream& eatwhite( ANTLR_USE_NAMESPACE(std)istream& is ); - -/** Read a string enclosed by '"' from a stream. Also handles escaping of \". - * Skips leading whitespace. - * @param in the istream to read from. - * @returns the string read from file exclusive the '"' - * @throws ios_base::failure if string is badly formatted - */ -ANTLR_USE_NAMESPACE(std)string read_string( ANTLR_USE_NAMESPACE(std)istream& in ); - -/* Read a ([A-Z][0-9][a-z]_)* kindoff thing. Skips leading whitespace. - * @param in the istream to read from. - */ -ANTLR_USE_NAMESPACE(std)string read_identifier( ANTLR_USE_NAMESPACE(std)istream& in ); - -/** Read a attribute="value" thing. Leading whitespace is skipped. - * Between attribute and '=' no whitespace is allowed. After the '=' it is - * permitted. - * @param in the istream to read from. - * @param attribute string the attribute name is put in - * @param value string the value of the attribute is put in - * @throws ios_base::failure if something is fishy. E.g. malformed quoting - * or missing '=' - */ -void read_AttributeNValue( ANTLR_USE_NAMESPACE(std)istream& in, - ANTLR_USE_NAMESPACE(std)string& attribute, - ANTLR_USE_NAMESPACE(std)string& value ); - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif diff --git a/libs/antlr-2.7.7/antlr/AST.hpp b/libs/antlr-2.7.7/antlr/AST.hpp deleted file mode 100644 index c47be5fd8..000000000 --- a/libs/antlr-2.7.7/antlr/AST.hpp +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef INC_AST_hpp__ -#define INC_AST_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/AST.hpp#2 $ - */ - -#include -#include -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -struct ASTRef; - -class ANTLR_API AST { -public: - AST() : ref(0) {} - AST(const AST&) : ref(0) {} - virtual ~AST() {} - - /// Return the type name for this AST node. (for XML output) - virtual const char* typeName( void ) const = 0; - /// Clone this AST node. - virtual RefAST clone( void ) const = 0; - /// Is node t equal to this in terms of token type and text? - virtual bool equals(RefAST t) const = 0; - /** Is t an exact structural and equals() match of this tree. The - * 'this' reference is considered the start of a sibling list. - */ - virtual bool equalsList(RefAST t) const = 0; - - /** Is 't' a subtree of this list? The siblings of the root are NOT ignored. - */ - virtual bool equalsListPartial(RefAST t) const = 0; - /** Is tree rooted at 'this' equal to 't'? The siblings of 'this' are - * ignored. - */ - virtual bool equalsTree(RefAST t) const = 0; - /** Is 't' a subtree of the tree rooted at 'this'? The siblings of - * 'this' are ignored. - */ - virtual bool equalsTreePartial(RefAST t) const = 0; - - /** Walk the tree looking for all exact subtree matches. Return - * a vector of RefAST that lets the caller walk the list - * of subtree roots found herein. - */ - virtual ANTLR_USE_NAMESPACE(std)vector findAll(RefAST t) = 0; - - /** Walk the tree looking for all subtrees. Return - * a vector of RefAST that lets the caller walk the list - * of subtree roots found herein. - */ - virtual ANTLR_USE_NAMESPACE(std)vector findAllPartial(RefAST t) = 0; - - /// Add a node to the end of the child list for this node - virtual void addChild(RefAST c) = 0; - /// Get the number of children. Returns 0 if the node is a leaf - virtual size_t getNumberOfChildren() const = 0; - - /// Get the first child of this node; null if no children - virtual RefAST getFirstChild() const = 0; - /// Get the next sibling in line after this one - virtual RefAST getNextSibling() const = 0; - - /// Get the token text for this node - virtual ANTLR_USE_NAMESPACE(std)string getText() const = 0; - /// Get the token type for this node - virtual int getType() const = 0; - - /** Various initialization routines. Used by several factories to initialize - * an AST element. - */ - virtual void initialize(int t, const ANTLR_USE_NAMESPACE(std)string& txt) = 0; - virtual void initialize(RefAST t) = 0; - virtual void initialize(RefToken t) = 0; - -#ifdef ANTLR_SUPPORT_XML - /** initialize this node from the contents of a stream. - * @param in the stream to read the AST attributes from. - */ - virtual void initialize( ANTLR_USE_NAMESPACE(std)istream& in ) = 0; -#endif - - /// Set the first child of a node. - virtual void setFirstChild(RefAST c) = 0; - /// Set the next sibling after this one. - virtual void setNextSibling(RefAST n) = 0; - - /// Set the token text for this node - virtual void setText(const ANTLR_USE_NAMESPACE(std)string& txt) = 0; - /// Set the token type for this node - virtual void setType(int type) = 0; - - /// Return this AST node as a string - virtual ANTLR_USE_NAMESPACE(std)string toString() const = 0; - - /// Print out a child-sibling tree in LISP notation - virtual ANTLR_USE_NAMESPACE(std)string toStringList() const = 0; - virtual ANTLR_USE_NAMESPACE(std)string toStringTree() const = 0; - -#ifdef ANTLR_SUPPORT_XML - /** get attributes of this node to 'out'. Override to customize XML - * output. - * @param out the stream to write the AST attributes to. - * @returns if a explicit closetag should be written - */ - virtual bool attributesToStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const = 0; - - /** Print a symbol over ostream. Overload this one to customize the XML - * output for AST derived AST-types - * @param output stream - */ - virtual void toStream( ANTLR_USE_NAMESPACE(std)ostream &out ) const = 0; - - /** Dump AST contents in XML format to output stream. - * Works in conjunction with to_stream method. Overload that one is - * derived classes to customize behaviour. - * @param output stream to write to string to put the stuff in. - * @param ast RefAST object to write. - */ - friend ANTLR_USE_NAMESPACE(std)ostream& operator<<( ANTLR_USE_NAMESPACE(std)ostream& output, const RefAST& ast ); -#endif - -private: - friend struct ASTRef; - ASTRef* ref; - - AST(RefAST other); - AST& operator=(const AST& other); - AST& operator=(RefAST other); -}; - -#ifdef ANTLR_SUPPORT_XML -inline ANTLR_USE_NAMESPACE(std)ostream& operator<<( ANTLR_USE_NAMESPACE(std)ostream& output, const RefAST& ast ) -{ - ast->toStream(output); - return output; -} -#endif - -extern ANTLR_API RefAST nullAST; -extern ANTLR_API AST* const nullASTptr; - -#ifdef NEEDS_OPERATOR_LESS_THAN -// RK: apparently needed by MSVC and a SUN CC, up to and including -// 2.7.2 this was undefined ? -inline bool operator<( RefAST l, RefAST r ) -{ - return nullAST == l ? ( nullAST == r ? false : true ) : l->getType() < r->getType(); -} -#endif - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_AST_hpp__ diff --git a/libs/antlr-2.7.7/antlr/ASTArray.hpp b/libs/antlr-2.7.7/antlr/ASTArray.hpp deleted file mode 100644 index d667c33d6..000000000 --- a/libs/antlr-2.7.7/antlr/ASTArray.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef INC_ASTArray_hpp__ -#define INC_ASTArray_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/ASTArray.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** ASTArray is a class that allows ANTLR to - * generate code that can create and initialize an array - * in one expression, like: - * (new ASTArray(3))->add(x)->add(y)->add(z) - */ -class ANTLR_API ASTArray { -public: - int size; // = 0; - ANTLR_USE_NAMESPACE(std)vector array; - - ASTArray(int capacity) - : size(0) - , array(capacity) - { - } - - ASTArray* add(RefAST node) - { - array[size++] = node; - return this; - } -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_ASTArray_hpp__ diff --git a/libs/antlr-2.7.7/antlr/ASTFactory.hpp b/libs/antlr-2.7.7/antlr/ASTFactory.hpp deleted file mode 100644 index 9fdcc2480..000000000 --- a/libs/antlr-2.7.7/antlr/ASTFactory.hpp +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef INC_ASTFactory_hpp__ -#define INC_ASTFactory_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/ASTFactory.hpp#2 $ - */ - -#include -#include -#include -#include - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -// Using these extra types to appease MSVC -typedef RefAST (*factory_type_)(); -typedef ANTLR_USE_NAMESPACE(std)pair< const char*, factory_type_ > factory_descriptor_; -typedef ANTLR_USE_NAMESPACE(std)vector< factory_descriptor_* > factory_descriptor_list_; - -/** AST Super Factory shared by TreeParser and Parser. - * This super factory maintains a map of all AST node types to their respective - * AST factories. One instance should be shared among a parser/treeparser - * chain. - * - * @todo check all this code for possible use of references in - * stead of RefAST's. - */ -class ANTLR_API ASTFactory { -public: - typedef factory_type_ factory_type; - typedef factory_descriptor_ factory_descriptor; - typedef factory_descriptor_list_ factory_descriptor_list; -protected: - /* The mapping of AST node type to factory.. - */ - factory_descriptor default_factory_descriptor; - factory_descriptor_list nodeFactories; -public: - /// Make new factory. Per default (Ref)CommonAST instances are generated. - ASTFactory(); - /** Initialize factory with a non default node type. - * factory_node_name should be the name of the AST node type the factory - * generates. (should exist during the existance of this ASTFactory - * instance) - */ - ASTFactory( const char* factory_node_name, factory_type factory ); - /// Destroy factory - virtual ~ASTFactory(); - - /// Register a node factory for the node type type with name ast_name - void registerFactory( int type, const char* ast_name, factory_type factory ); - /// Set the maximum node (AST) type this factory may encounter - void setMaxNodeType( int type ); - - /// Add a child to the current AST - void addASTChild(ASTPair& currentAST, RefAST child); - /// Create new empty AST node. The right default type shou - virtual RefAST create(); - /// Create AST node of the right type for 'type' - RefAST create(int type); - /// Create AST node of the right type for 'type' and initialize with txt - RefAST create(int type, const ANTLR_USE_NAMESPACE(std)string& txt); - /// Create duplicate of tr - RefAST create(RefAST tr); - /// Create new AST node and initialize contents from a token. - RefAST create(RefToken tok); - /// Create new AST node and initialize contents from a stream. - RefAST create(const ANTLR_USE_NAMESPACE(std)string& txt, ANTLR_USE_NAMESPACE(std)istream& infile ); - /** Deep copy a single node. This function the new clone() methods in the - * AST interface. Returns a new RefAST(nullASTptr) if t is null. - */ - RefAST dup(RefAST t); - /// Duplicate tree including siblings of root. - RefAST dupList(RefAST t); - /** Duplicate a tree, assuming this is a root node of a tree-- - * duplicate that node and what's below; ignore siblings of root node. - */ - RefAST dupTree(RefAST t); - /** Make a tree from a list of nodes. The first element in the - * array is the root. If the root is null, then the tree is - * a simple list not a tree. Handles null children nodes correctly. - * For example, make(a, b, null, c) yields tree (a b c). make(null,a,b) - * yields tree (nil a b). - */ - RefAST make(ANTLR_USE_NAMESPACE(std)vector& nodes); - /** Make a tree from a list of nodes, where the nodes are contained - * in an ASTArray object. The ASTArray is deleted after use. - * @todo FIXME! I have a feeling we can get rid of this ugly ASTArray thing - */ - RefAST make(ASTArray* nodes); - /// Make an AST the root of current AST - void makeASTRoot(ASTPair& currentAST, RefAST root); - - /** Set a new default AST type. - * factory_node_name should be the name of the AST node type the factory - * generates. (should exist during the existance of this ASTFactory - * instance). - * Only change factory between parser runs. You might get unexpected results - * otherwise. - */ - void setASTNodeFactory( const char* factory_node_name, factory_type factory ); - -#ifdef ANTLR_SUPPORT_XML - /** Load a XML AST from stream. Make sure you have all the factories - * registered before use. - * @note this 'XML' stuff is quite rough still. YMMV. - */ - RefAST LoadAST( ANTLR_USE_NAMESPACE(std)istream& infile ); -#endif -protected: - void loadChildren( ANTLR_USE_NAMESPACE(std)istream& infile, RefAST current ); - void loadSiblings( ANTLR_USE_NAMESPACE(std)istream& infile, RefAST current ); - bool checkCloseTag( ANTLR_USE_NAMESPACE(std)istream& infile ); - -#ifdef ANTLR_VECTOR_HAS_AT - /// construct a node of 'type' - inline RefAST getNodeOfType( unsigned int type ) - { - return RefAST(nodeFactories.at(type)->second()); - } - /// get the name of the node 'type' - const char* getASTNodeType( unsigned int type ) - { - return nodeFactories.at(type)->first; - } - /// get the factory used for node 'type' - factory_type getASTNodeFactory( unsigned int type ) - { - return nodeFactories.at(type)->second; - } -#else - inline RefAST getNodeOfType( unsigned int type ) - { - return RefAST(nodeFactories[type]->second()); - } - /// get the name of the node 'type' - const char* getASTNodeType( unsigned int type ) - { - return nodeFactories[type]->first; - } - factory_type getASTNodeFactory( unsigned int type ) - { - return nodeFactories[type]->second; - } -#endif - -private: - // no copying and such.. - ASTFactory( const ASTFactory& ); - ASTFactory& operator=( const ASTFactory& ); -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_ASTFactory_hpp__ diff --git a/libs/antlr-2.7.7/antlr/ASTNULLType.hpp b/libs/antlr-2.7.7/antlr/ASTNULLType.hpp deleted file mode 100644 index ab8901a6d..000000000 --- a/libs/antlr-2.7.7/antlr/ASTNULLType.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef INC_ASTNULLType_hpp__ -#define INC_ASTNULLType_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/ASTNULLType.hpp#2 $ - */ - -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** There is only one instance of this class **/ -class ANTLR_API ASTNULLType : public AST { -public: - const char* typeName( void ) const; - RefAST clone( void ) const; - - void addChild(RefAST c); - size_t getNumberOfChildren() const; - void setFirstChild(RefAST c); - void setNextSibling(RefAST n); - - bool equals(RefAST t) const; - bool equalsList(RefAST t) const; - bool equalsListPartial(RefAST t) const; - bool equalsTree(RefAST t) const; - bool equalsTreePartial(RefAST t) const; - - ANTLR_USE_NAMESPACE(std)vector findAll(RefAST tree); - ANTLR_USE_NAMESPACE(std)vector findAllPartial(RefAST subtree); - - RefAST getFirstChild() const; - RefAST getNextSibling() const; - - ANTLR_USE_NAMESPACE(std)string getText() const; - int getType() const; - - void initialize(int t, const ANTLR_USE_NAMESPACE(std)string& txt); - void initialize(RefAST t); - void initialize(RefToken t); - void initialize(ANTLR_USE_NAMESPACE(std)istream& infile); - - void setText(const ANTLR_USE_NAMESPACE(std)string& text); - void setType(int ttype); - ANTLR_USE_NAMESPACE(std)string toString() const; - ANTLR_USE_NAMESPACE(std)string toStringList() const; - ANTLR_USE_NAMESPACE(std)string toStringTree() const; - - bool attributesToStream( ANTLR_USE_NAMESPACE(std)ostream &out ) const; - void toStream( ANTLR_USE_NAMESPACE(std)ostream &out ) const; -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_ASTNULLType_hpp__ diff --git a/libs/antlr-2.7.7/antlr/ASTPair.hpp b/libs/antlr-2.7.7/antlr/ASTPair.hpp deleted file mode 100644 index ec5425379..000000000 --- a/libs/antlr-2.7.7/antlr/ASTPair.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef INC_ASTPair_hpp__ -#define INC_ASTPair_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/ASTPair.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** ASTPair: utility class used for manipulating a pair of ASTs - * representing the current AST root and current AST sibling. - * This exists to compensate for the lack of pointers or 'var' - * arguments in Java. - * - * OK, so we can do those things in C++, but it seems easier - * to stick with the Java way for now. - */ -class ANTLR_API ASTPair { -public: - RefAST root; // current root of tree - RefAST child; // current child to which siblings are added - - /** Make sure that child is the last sibling */ - void advanceChildToEnd() { - if (child) { - while (child->getNextSibling()) { - child = child->getNextSibling(); - } - } - } -// /** Copy an ASTPair. Don't call it clone() because we want type-safety */ -// ASTPair copy() { -// ASTPair tmp = new ASTPair(); -// tmp.root = root; -// tmp.child = child; -// return tmp; -// } - ANTLR_USE_NAMESPACE(std)string toString() const { - ANTLR_USE_NAMESPACE(std)string r = !root ? ANTLR_USE_NAMESPACE(std)string("null") : root->getText(); - ANTLR_USE_NAMESPACE(std)string c = !child ? ANTLR_USE_NAMESPACE(std)string("null") : child->getText(); - return "["+r+","+c+"]"; - } -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_ASTPair_hpp__ diff --git a/libs/antlr-2.7.7/antlr/ASTRefCount.hpp b/libs/antlr-2.7.7/antlr/ASTRefCount.hpp deleted file mode 100644 index 293f2d5fa..000000000 --- a/libs/antlr-2.7.7/antlr/ASTRefCount.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef INC_ASTRefCount_hpp__ -# define INC_ASTRefCount_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/ASTRefCount.hpp#2 $ - */ - -# include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - - class AST; - -struct ANTLR_API ASTRef -{ - AST* const ptr; - unsigned int count; - - ASTRef(AST* p); - ~ASTRef(); - ASTRef* increment() - { - ++count; - return this; - } - bool decrement() - { - return (--count==0); - } - - static ASTRef* getRef(const AST* p); -private: - ASTRef( const ASTRef& ); - ASTRef& operator=( const ASTRef& ); -}; - -template - class ANTLR_API ASTRefCount -{ -private: - ASTRef* ref; - -public: - ASTRefCount(const AST* p=0) - : ref(p ? ASTRef::getRef(p) : 0) - { - } - ASTRefCount(const ASTRefCount& other) - : ref(other.ref ? other.ref->increment() : 0) - { - } - ~ASTRefCount() - { - if (ref && ref->decrement()) - delete ref; - } - ASTRefCount& operator=(AST* other) - { - ASTRef* tmp = ASTRef::getRef(other); - - if (ref && ref->decrement()) - delete ref; - - ref=tmp; - - return *this; - } - ASTRefCount& operator=(const ASTRefCount& other) - { - if( other.ref != ref ) - { - ASTRef* tmp = other.ref ? other.ref->increment() : 0; - - if (ref && ref->decrement()) - delete ref; - - ref=tmp; - } - return *this; - } - - operator T* () const { return ref ? static_cast(ref->ptr) : 0; } - T* operator->() const { return ref ? static_cast(ref->ptr) : 0; } - T* get() const { return ref ? static_cast(ref->ptr) : 0; } -}; - -typedef ASTRefCount RefAST; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_ASTRefCount_hpp__ diff --git a/libs/antlr-2.7.7/antlr/BaseAST.hpp b/libs/antlr-2.7.7/antlr/BaseAST.hpp deleted file mode 100644 index f048f9543..000000000 --- a/libs/antlr-2.7.7/antlr/BaseAST.hpp +++ /dev/null @@ -1,193 +0,0 @@ -#ifndef INC_BaseAST_hpp__ -#define INC_BaseAST_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/BaseAST.hpp#2 $ - */ - -#include -#include - -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class ANTLR_API BaseAST; -typedef ASTRefCount RefBaseAST; - -class ANTLR_API BaseAST : public AST { -public: - BaseAST() : AST() - { - } - BaseAST(const BaseAST& other) - : AST(other) - { - } - virtual ~BaseAST() - { - } - - /// Return the class name - virtual const char* typeName( void ) const = 0; - - /// Clone this AST node. - virtual RefAST clone( void ) const = 0; - - /// Is node t equal to this in terms of token type and text? - virtual bool equals(RefAST t) const; - - /** Is t an exact structural and equals() match of this tree. The - * 'this' reference is considered the start of a sibling list. - */ - virtual bool equalsList(RefAST t) const; - - /** Is 't' a subtree of this list? The siblings of the root are NOT ignored. - */ - virtual bool equalsListPartial(RefAST t) const; - - /** Is tree rooted at 'this' equal to 't'? The siblings of 'this' are - * ignored. - */ - virtual bool equalsTree(RefAST t) const; - - /** Is 't' a subtree of the tree rooted at 'this'? The siblings of - * 'this' are ignored. - */ - virtual bool equalsTreePartial(RefAST t) const; - - /** Walk the tree looking for all exact subtree matches. Return - * an ASTEnumerator that lets the caller walk the list - * of subtree roots found herein. - */ - virtual ANTLR_USE_NAMESPACE(std)vector findAll(RefAST t); - - /** Walk the tree looking for all subtrees. Return - * an ASTEnumerator that lets the caller walk the list - * of subtree roots found herein. - */ - virtual ANTLR_USE_NAMESPACE(std)vector findAllPartial(RefAST t); - - /// Add a node to the end of the child list for this node - virtual void addChild(RefAST c) - { - if( !c ) - return; - - RefBaseAST tmp = down; - - if (tmp) - { - while (tmp->right) - tmp = tmp->right; - tmp->right = c; - } - else - down = c; - } - - /** Get the number of child nodes of this node (shallow e.g. not of the - * whole tree it spans). - */ - virtual size_t getNumberOfChildren() const; - - /// Get the first child of this node; null if no children - virtual RefAST getFirstChild() const - { - return RefAST(down); - } - /// Get the next sibling in line after this one - virtual RefAST getNextSibling() const - { - return RefAST(right); - } - - /// Get the token text for this node - virtual ANTLR_USE_NAMESPACE(std)string getText() const - { - return ""; - } - /// Get the token type for this node - virtual int getType() const - { - return 0; - } - - /// Remove all children - virtual void removeChildren() - { - down = static_cast(static_cast(nullAST)); - } - - /// Set the first child of a node. - virtual void setFirstChild(RefAST c) - { - down = static_cast(static_cast(c)); - } - - /// Set the next sibling after this one. - virtual void setNextSibling(RefAST n) - { - right = static_cast(static_cast(n)); - } - - /// Set the token text for this node - virtual void setText(const ANTLR_USE_NAMESPACE(std)string& /*txt*/) - { - } - - /// Set the token type for this node - virtual void setType(int /*type*/) - { - } - -#ifdef ANTLR_SUPPORT_XML - /** print attributes of this node to 'out'. Override to customize XML - * output. - * @param out the stream to write the AST attributes to. - */ - virtual bool attributesToStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const; - /** Write this subtree to a stream. Overload this one to customize the XML - * output for AST derived AST-types - * @param output stream - */ - virtual void toStream( ANTLR_USE_NAMESPACE(std)ostream &out ) const; -#endif - - /// Return string representation for the AST - virtual ANTLR_USE_NAMESPACE(std)string toString() const - { - return getText(); - } - - /// Print out a child sibling tree in LISP notation - virtual ANTLR_USE_NAMESPACE(std)string toStringList() const; - virtual ANTLR_USE_NAMESPACE(std)string toStringTree() const; -protected: - RefBaseAST down; - RefBaseAST right; -private: - void doWorkForFindAll(ANTLR_USE_NAMESPACE(std)vector& v, - RefAST target, - bool partialMatch); -}; - -/** Is node t equal to this in terms of token type and text? - */ -inline bool BaseAST::equals(RefAST t) const -{ - if (!t) - return false; - return ((getType() == t->getType()) && (getText() == t->getText())); -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_BaseAST_hpp__ diff --git a/libs/antlr-2.7.7/antlr/BitSet.hpp b/libs/antlr-2.7.7/antlr/BitSet.hpp deleted file mode 100644 index e1869cf42..000000000 --- a/libs/antlr-2.7.7/antlr/BitSet.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef INC_BitSet_hpp__ -#define INC_BitSet_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/BitSet.hpp#2 $ - */ - -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** A BitSet to replace java.util.BitSet. - * Primary differences are that most set operators return new sets - * as opposed to oring and anding "in place". Further, a number of - * operations were added. I cannot contain a BitSet because there - * is no way to access the internal bits (which I need for speed) - * and, because it is final, I cannot subclass to add functionality. - * Consider defining set degree. Without access to the bits, I must - * call a method n times to test the ith bit...ack! - * - * Also seems like or() from util is wrong when size of incoming set is bigger - * than this.length. - * - * This is a C++ version of the Java class described above, with only - * a handful of the methods implemented, because we don't need the - * others at runtime. It's really just a wrapper around vector, - * which should probably be changed to a wrapper around bitset, once - * bitset is more widely available. - * - * @author Terence Parr, MageLang Institute - * @author
Pete Wells - */ -class ANTLR_API BitSet { -private: - ANTLR_USE_NAMESPACE(std)vector storage; - -public: - BitSet( unsigned int nbits=64 ); - BitSet( const unsigned long* bits_, unsigned int nlongs); - ~BitSet(); - - void add( unsigned int el ); - - bool member( unsigned int el ) const; - - ANTLR_USE_NAMESPACE(std)vector toArray() const; -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_BitSet_hpp__ diff --git a/libs/antlr-2.7.7/antlr/CharBuffer.hpp b/libs/antlr-2.7.7/antlr/CharBuffer.hpp deleted file mode 100644 index 57ab3e670..000000000 --- a/libs/antlr-2.7.7/antlr/CharBuffer.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef INC_CharBuffer_hpp__ -#define INC_CharBuffer_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/CharBuffer.hpp#2 $ - */ - -#include - -#include - -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/**A Stream of characters fed to the lexer from a InputStream that can - * be rewound via mark()/rewind() methods. - *

- * A dynamic array is used to buffer up all the input characters. Normally, - * "k" characters are stored in the buffer. More characters may be stored - * during guess mode (testing syntactic predicate), or when LT(i>k) is - * referenced. - * Consumption of characters is deferred. In other words, reading the next - * character is not done by consume(), but deferred until needed by LA or LT. - *

- * - * @see antlr.CharQueue - */ - -class ANTLR_API CharBuffer : public InputBuffer { -public: - /// Create a character buffer - CharBuffer( ANTLR_USE_NAMESPACE(std)istream& input ); - /// Get the next character from the stream - int getChar(); - -protected: - // character source - ANTLR_USE_NAMESPACE(std)istream& input; - -private: - // NOTE: Unimplemented - CharBuffer(const CharBuffer& other); - CharBuffer& operator=(const CharBuffer& other); -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_CharBuffer_hpp__ diff --git a/libs/antlr-2.7.7/antlr/CharInputBuffer.hpp b/libs/antlr-2.7.7/antlr/CharInputBuffer.hpp deleted file mode 100644 index ac2da0cbc..000000000 --- a/libs/antlr-2.7.7/antlr/CharInputBuffer.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef INC_CharInputBuffer_hpp__ -# define INC_CharInputBuffer_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id:$ - */ - -# include -# include - -# ifdef HAS_NOT_CCTYPE_H -# include -# else -# include -# endif - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** CharInputBuffer.hpp provides an InputBuffer for plain character arrays (buffers). - */ -class CharInputBuffer : public InputBuffer -{ -public: - /** Construct a CharInputBuffer.hpp object with a char* buffer of 'size' - * if 'owner' is true, then the buffer will be delete[]-ed on destruction. - * @note it is assumed the buffer was allocated with new[]! - */ - CharInputBuffer( unsigned char* buf, size_t size, bool owner = false ) - : buffer(buf) - , ptr(buf) - , end(buf + size) - , delete_buffer(owner) - { - } - - /** Destructor - * @note If you're using malloced data, then you probably need to change - * this destructor. Or better use this class as template for your own. - */ - ~CharInputBuffer( void ) - { - if( delete_buffer && buffer ) - delete [] buffer; - } - - /** Reset the CharInputBuffer to initial state - * Called from LexerInputState::reset. - * @see LexerInputState - */ - virtual inline void reset( void ) - { - InputBuffer::reset(); - ptr = buffer; - } - - virtual int getChar( void ) - { - return (ptr < end) ? *ptr++ : EOF; - } - -protected: - unsigned char* buffer; ///< the buffer with data - unsigned char* ptr; ///< position ptr into the buffer - unsigned char* end; ///< end sentry for buffer - bool delete_buffer; ///< flag signifying if we have to delete the buffer -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif diff --git a/libs/antlr-2.7.7/antlr/CharScanner.hpp b/libs/antlr-2.7.7/antlr/CharScanner.hpp deleted file mode 100644 index df66447a7..000000000 --- a/libs/antlr-2.7.7/antlr/CharScanner.hpp +++ /dev/null @@ -1,577 +0,0 @@ -#ifndef INC_CharScanner_hpp__ -#define INC_CharScanner_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/CharScanner.hpp#2 $ - */ - -#include - -#include - -#ifdef HAS_NOT_CCTYPE_H -#include -#else -#include -#endif - -#if ( _MSC_VER == 1200 ) -// VC6 seems to need this -// note that this is not a standard C++ include file. -# include -#endif -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class ANTLR_API CharScanner; - -ANTLR_C_USING(tolower) - -#ifdef ANTLR_REALLY_NO_STRCASECMP -// Apparently, neither strcasecmp nor stricmp is standard, and Codewarrior -// on the mac has neither... -inline int strcasecmp(const char *s1, const char *s2) -{ - while (true) - { - char c1 = tolower(*s1++), - c2 = tolower(*s2++); - if (c1 < c2) return -1; - if (c1 > c2) return 1; - if (c1 == 0) return 0; - } -} -#else -#ifdef NO_STRCASECMP -ANTLR_C_USING(stricmp) -#else -#include -ANTLR_C_USING(strcasecmp) -#endif -#endif - -/** Functor for the literals map - */ -class ANTLR_API CharScannerLiteralsLess : public ANTLR_USE_NAMESPACE(std)binary_function { -private: - const CharScanner* scanner; -public: -#ifdef NO_TEMPLATE_PARTS - CharScannerLiteralsLess() {} // not really used, definition to appease MSVC -#endif - CharScannerLiteralsLess(const CharScanner* theScanner) - : scanner(theScanner) - { - } - bool operator() (const ANTLR_USE_NAMESPACE(std)string& x,const ANTLR_USE_NAMESPACE(std)string& y) const; -// defaults are good enough.. - // CharScannerLiteralsLess(const CharScannerLiteralsLess&); - // CharScannerLiteralsLess& operator=(const CharScannerLiteralsLess&); -}; - -/** Superclass of generated lexers - */ -class ANTLR_API CharScanner : public TokenStream { -protected: - typedef RefToken (*factory_type)(); -public: - CharScanner(InputBuffer& cb, bool case_sensitive ); - CharScanner(InputBuffer* cb, bool case_sensitive ); - CharScanner(const LexerSharedInputState& state, bool case_sensitive ); - - virtual ~CharScanner() - { - } - - virtual int LA(unsigned int i); - - virtual void append(char c) - { - if (saveConsumedInput) - { - size_t l = text.length(); - - if ((l%256) == 0) - text.reserve(l+256); - - text.replace(l,0,&c,1); - } - } - - virtual void append(const ANTLR_USE_NAMESPACE(std)string& s) - { - if( saveConsumedInput ) - text += s; - } - - virtual void commit() - { - inputState->getInput().commit(); - } - - /** called by the generated lexer to do error recovery, override to - * customize the behaviour. - */ - virtual void recover(const RecognitionException& ex, const BitSet& tokenSet) - { - (void)ex; - consume(); - consumeUntil(tokenSet); - } - - virtual void consume() - { - if (inputState->guessing == 0) - { - int c = LA(1); - if (caseSensitive) - { - append(c); - } - else - { - // use input.LA(), not LA(), to get original case - // CharScanner.LA() would toLower it. - append(inputState->getInput().LA(1)); - } - - // RK: in a sense I don't like this automatic handling. - if (c == '\t') - tab(); - else - inputState->column++; - } - inputState->getInput().consume(); - } - - /** Consume chars until one matches the given char */ - virtual void consumeUntil(int c) - { - for(;;) - { - int la_1 = LA(1); - if( la_1 == EOF_CHAR || la_1 == c ) - break; - consume(); - } - } - - /** Consume chars until one matches the given set */ - virtual void consumeUntil(const BitSet& set) - { - for(;;) - { - int la_1 = LA(1); - if( la_1 == EOF_CHAR || set.member(la_1) ) - break; - consume(); - } - } - - /// Mark the current position and return a id for it - virtual unsigned int mark() - { - return inputState->getInput().mark(); - } - /// Rewind the scanner to a previously marked position - virtual void rewind(unsigned int pos) - { - inputState->getInput().rewind(pos); - } - - /// See if input contains character 'c' throw MismatchedCharException if not - virtual void match(int c) - { - int la_1 = LA(1); - if ( la_1 != c ) - throw MismatchedCharException(la_1, c, false, this); - consume(); - } - - /** See if input contains element from bitset b - * throw MismatchedCharException if not - */ - virtual void match(const BitSet& b) - { - int la_1 = LA(1); - - if ( !b.member(la_1) ) - throw MismatchedCharException( la_1, b, false, this ); - consume(); - } - - /** See if input contains string 's' throw MismatchedCharException if not - * @note the string cannot match EOF - */ - virtual void match( const char* s ) - { - while( *s != '\0' ) - { - // the & 0xFF is here to prevent sign extension lateron - int la_1 = LA(1), c = (*s++ & 0xFF); - - if ( la_1 != c ) - throw MismatchedCharException(la_1, c, false, this); - - consume(); - } - } - /** See if input contains string 's' throw MismatchedCharException if not - * @note the string cannot match EOF - */ - virtual void match(const ANTLR_USE_NAMESPACE(std)string& s) - { - size_t len = s.length(); - - for (size_t i = 0; i < len; i++) - { - // the & 0xFF is here to prevent sign extension lateron - int la_1 = LA(1), c = (s[i] & 0xFF); - - if ( la_1 != c ) - throw MismatchedCharException(la_1, c, false, this); - - consume(); - } - } - /** See if input does not contain character 'c' - * throw MismatchedCharException if not - */ - virtual void matchNot(int c) - { - int la_1 = LA(1); - - if ( la_1 == c ) - throw MismatchedCharException(la_1, c, true, this); - - consume(); - } - /** See if input contains character in range c1-c2 - * throw MismatchedCharException if not - */ - virtual void matchRange(int c1, int c2) - { - int la_1 = LA(1); - - if ( la_1 < c1 || la_1 > c2 ) - throw MismatchedCharException(la_1, c1, c2, false, this); - - consume(); - } - - virtual bool getCaseSensitive() const - { - return caseSensitive; - } - - virtual void setCaseSensitive(bool t) - { - caseSensitive = t; - } - - virtual bool getCaseSensitiveLiterals() const=0; - - /// Get the line the scanner currently is in (starts at 1) - virtual int getLine() const - { - return inputState->line; - } - - /// set the line number - virtual void setLine(int l) - { - inputState->line = l; - } - - /// Get the column the scanner currently is in (starts at 1) - virtual int getColumn() const - { - return inputState->column; - } - /// set the column number - virtual void setColumn(int c) - { - inputState->column = c; - } - - /// get the filename for the file currently used - virtual const ANTLR_USE_NAMESPACE(std)string& getFilename() const - { - return inputState->filename; - } - /// Set the filename the scanner is using (used in error messages) - virtual void setFilename(const ANTLR_USE_NAMESPACE(std)string& f) - { - inputState->filename = f; - } - - virtual bool getCommitToPath() const - { - return commitToPath; - } - - virtual void setCommitToPath(bool commit) - { - commitToPath = commit; - } - - /** return a copy of the current text buffer */ - virtual const ANTLR_USE_NAMESPACE(std)string& getText() const - { - return text; - } - - virtual void setText(const ANTLR_USE_NAMESPACE(std)string& s) - { - text = s; - } - - virtual void resetText() - { - text = ""; - inputState->tokenStartColumn = inputState->column; - inputState->tokenStartLine = inputState->line; - } - - virtual RefToken getTokenObject() const - { - return _returnToken; - } - - /** Used to keep track of line breaks, needs to be called from - * within generated lexers when a \n \r is encountered. - */ - virtual void newline() - { - ++inputState->line; - inputState->column = 1; - } - - /** Advance the current column number by an appropriate amount according - * to the tabsize. This method needs to be explicitly called from the - * lexer rules encountering tabs. - */ - virtual void tab() - { - int c = getColumn(); - int nc = ( ((c-1)/tabsize) + 1) * tabsize + 1; // calculate tab stop - setColumn( nc ); - } - /// set the tabsize. Returns the old tabsize - int setTabsize( int size ) - { - int oldsize = tabsize; - tabsize = size; - return oldsize; - } - /// Return the tabsize used by the scanner - int getTabSize() const - { - return tabsize; - } - - /** Report exception errors caught in nextToken() */ - virtual void reportError(const RecognitionException& e); - - /** Parser error-reporting function can be overridden in subclass */ - virtual void reportError(const ANTLR_USE_NAMESPACE(std)string& s); - - /** Parser warning-reporting function can be overridden in subclass */ - virtual void reportWarning(const ANTLR_USE_NAMESPACE(std)string& s); - - virtual InputBuffer& getInputBuffer() - { - return inputState->getInput(); - } - - virtual LexerSharedInputState getInputState() - { - return inputState; - } - - /** set the input state for the lexer. - * @note state is a reference counted object, hence no reference */ - virtual void setInputState(LexerSharedInputState state) - { - inputState = state; - } - - /// Set the factory for created tokens - virtual void setTokenObjectFactory(factory_type factory) - { - tokenFactory = factory; - } - - /** Test the token text against the literals table - * Override this method to perform a different literals test - */ - virtual int testLiteralsTable(int ttype) const - { - ANTLR_USE_NAMESPACE(std)map::const_iterator i = literals.find(text); - if (i != literals.end()) - ttype = (*i).second; - return ttype; - } - - /** Test the text passed in against the literals table - * Override this method to perform a different literals test - * This is used primarily when you want to test a portion of - * a token - */ - virtual int testLiteralsTable(const ANTLR_USE_NAMESPACE(std)string& txt,int ttype) const - { - ANTLR_USE_NAMESPACE(std)map::const_iterator i = literals.find(txt); - if (i != literals.end()) - ttype = (*i).second; - return ttype; - } - - /// Override this method to get more specific case handling - virtual int toLower(int c) const - { - // test on EOF_CHAR for buggy (?) STLPort tolower (or HPUX tolower?) - // also VC++ 6.0 does this. (see fix 422 (is reverted by this fix) - // this one is more structural. Maybe make this configurable. - return (c == EOF_CHAR ? EOF_CHAR : tolower(c)); - } - - /** This method is called by YourLexer::nextToken() when the lexer has - * hit EOF condition. EOF is NOT a character. - * This method is not called if EOF is reached during - * syntactic predicate evaluation or during evaluation - * of normal lexical rules, which presumably would be - * an IOException. This traps the "normal" EOF condition. - * - * uponEOF() is called after the complete evaluation of - * the previous token and only if your parser asks - * for another token beyond that last non-EOF token. - * - * You might want to throw token or char stream exceptions - * like: "Heh, premature eof" or a retry stream exception - * ("I found the end of this file, go back to referencing file"). - */ - virtual void uponEOF() - { - } - - /// Methods used to change tracing behavior - virtual void traceIndent(); - virtual void traceIn(const char* rname); - virtual void traceOut(const char* rname); - -#ifndef NO_STATIC_CONSTS - static const int EOF_CHAR = EOF; -#else - enum { - EOF_CHAR = EOF - }; -#endif -protected: - ANTLR_USE_NAMESPACE(std)string text; ///< Text of current token - /// flag indicating wether consume saves characters - bool saveConsumedInput; - factory_type tokenFactory; ///< Factory for tokens - bool caseSensitive; ///< Is this lexer case sensitive - ANTLR_USE_NAMESPACE(std)map literals; // set by subclass - - RefToken _returnToken; ///< used to return tokens w/o using return val - - /// Input state, gives access to input stream, shared among different lexers - LexerSharedInputState inputState; - - /** Used during filter mode to indicate that path is desired. - * A subsequent scan error will report an error as usual - * if acceptPath=true; - */ - bool commitToPath; - - int tabsize; ///< tab size the scanner uses. - - /// Create a new RefToken of type t - virtual RefToken makeToken(int t) - { - RefToken tok = tokenFactory(); - tok->setType(t); - tok->setColumn(inputState->tokenStartColumn); - tok->setLine(inputState->tokenStartLine); - return tok; - } - - /** Tracer class, used when -traceLexer is passed to antlr - */ - class Tracer { - private: - CharScanner* parser; - const char* text; - - Tracer(const Tracer& other); // undefined - Tracer& operator=(const Tracer& other); // undefined - public: - Tracer( CharScanner* p,const char* t ) - : parser(p), text(t) - { - parser->traceIn(text); - } - ~Tracer() - { - parser->traceOut(text); - } - }; - - int traceDepth; -private: - CharScanner( const CharScanner& other ); // undefined - CharScanner& operator=( const CharScanner& other ); // undefined - -#ifndef NO_STATIC_CONSTS - static const int NO_CHAR = 0; -#else - enum { - NO_CHAR = 0 - }; -#endif -}; - -inline int CharScanner::LA(unsigned int i) -{ - int c = inputState->getInput().LA(i); - - if ( caseSensitive ) - return c; - else - return toLower(c); // VC 6 tolower bug caught in toLower. -} - -inline bool CharScannerLiteralsLess::operator() (const ANTLR_USE_NAMESPACE(std)string& x,const ANTLR_USE_NAMESPACE(std)string& y) const -{ - if (scanner->getCaseSensitiveLiterals()) - return ANTLR_USE_NAMESPACE(std)less()(x,y); - else - { -#ifdef NO_STRCASECMP - return (stricmp(x.c_str(),y.c_str())<0); -#else - return (strcasecmp(x.c_str(),y.c_str())<0); -#endif - } -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_CharScanner_hpp__ diff --git a/libs/antlr-2.7.7/antlr/CharStreamException.hpp b/libs/antlr-2.7.7/antlr/CharStreamException.hpp deleted file mode 100644 index ee7ad4372..000000000 --- a/libs/antlr-2.7.7/antlr/CharStreamException.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef INC_CharStreamException_hpp__ -#define INC_CharStreamException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/CharStreamException.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class ANTLR_API CharStreamException : public ANTLRException { -public: - CharStreamException(const ANTLR_USE_NAMESPACE(std)string& s) - : ANTLRException(s) {} - ~CharStreamException() throw() {} -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_CharStreamException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/CharStreamIOException.hpp b/libs/antlr-2.7.7/antlr/CharStreamIOException.hpp deleted file mode 100644 index ebbb0fd67..000000000 --- a/libs/antlr-2.7.7/antlr/CharStreamIOException.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef INC_CharStreamIOException_hpp__ -#define INC_CharStreamIOException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/CharStreamIOException.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class ANTLR_API CharStreamIOException : public CharStreamException { -public: - ANTLR_USE_NAMESPACE(std)exception io; - - CharStreamIOException(ANTLR_USE_NAMESPACE(std)exception& e) - : CharStreamException(e.what()), io(e) {} - ~CharStreamIOException() throw() {} -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_CharStreamIOException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/CircularQueue.hpp b/libs/antlr-2.7.7/antlr/CircularQueue.hpp deleted file mode 100644 index a4d115498..000000000 --- a/libs/antlr-2.7.7/antlr/CircularQueue.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef INC_CircularQueue_hpp__ -#define INC_CircularQueue_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/CircularQueue.hpp#2 $ - */ - -#include -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -// Resize every 5000 items -#define OFFSET_MAX_RESIZE 5000 - -template -class ANTLR_API CircularQueue { -public: - CircularQueue() - : storage() - , m_offset(0) - { - } - ~CircularQueue() - { - } - - /// Clear the queue - inline void clear( void ) - { - m_offset = 0; - storage.clear(); - } - - /// @todo this should use at or should have a check - inline T elementAt( size_t idx ) const - { - return storage[idx+m_offset]; - } - void removeFirst() - { - if (m_offset >= OFFSET_MAX_RESIZE) - { - storage.erase( storage.begin(), storage.begin() + m_offset + 1 ); - m_offset = 0; - } - else - ++m_offset; - } - inline void removeItems( size_t nb ) - { - // it would be nice if we would not get called with nb > entries - // (or to be precise when entries() == 0) - // This case is possible when lexer/parser::recover() calls - // consume+consumeUntil when the queue is empty. - // In recover the consume says to prepare to read another - // character/token. Then in the subsequent consumeUntil the - // LA() call will trigger - // syncConsume which calls this method *before* the same queue - // has been sufficiently filled. - if( nb > entries() ) - nb = entries(); - - if (m_offset >= OFFSET_MAX_RESIZE) - { - storage.erase( storage.begin(), storage.begin() + m_offset + nb ); - m_offset = 0; - } - else - m_offset += nb; - } - inline void append(const T& t) - { - storage.push_back(t); - } - inline size_t entries() const - { - return storage.size() - m_offset; - } - -private: - ANTLR_USE_NAMESPACE(std)vector storage; - size_t m_offset; - - CircularQueue(const CircularQueue&); - const CircularQueue& operator=(const CircularQueue&); -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_CircularQueue_hpp__ diff --git a/libs/antlr-2.7.7/antlr/CommonAST.hpp b/libs/antlr-2.7.7/antlr/CommonAST.hpp deleted file mode 100644 index ab16aa2c8..000000000 --- a/libs/antlr-2.7.7/antlr/CommonAST.hpp +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef INC_CommonAST_hpp__ -#define INC_CommonAST_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/CommonAST.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class ANTLR_API CommonAST : public BaseAST { -public: - CommonAST() - : BaseAST() - , ttype( Token::INVALID_TYPE ) - , text() - { - } - - CommonAST( RefToken t ) - : BaseAST() - , ttype( t->getType() ) - , text( t->getText() ) - { - } - - CommonAST( const CommonAST& other ) - : BaseAST(other) - , ttype(other.ttype) - , text(other.text) - { - } - - virtual ~CommonAST() - { - } - - virtual const char* typeName( void ) const - { - return CommonAST::TYPE_NAME; - } - - /// Clone this AST node. - virtual RefAST clone( void ) const - { - CommonAST *ast = new CommonAST( *this ); - return RefAST(ast); - } - - virtual ANTLR_USE_NAMESPACE(std)string getText() const - { - return text; - } - virtual int getType() const - { - return ttype; - } - - virtual void initialize( int t, const ANTLR_USE_NAMESPACE(std)string& txt ) - { - setType(t); - setText(txt); - } - - virtual void initialize( RefAST t ) - { - setType(t->getType()); - setText(t->getText()); - } - virtual void initialize( RefToken t ) - { - setType(t->getType()); - setText(t->getText()); - } - -#ifdef ANTLR_SUPPORT_XML - virtual void initialize( ANTLR_USE_NAMESPACE(std)istream& in ); -#endif - - virtual void setText( const ANTLR_USE_NAMESPACE(std)string& txt ) - { - text = txt; - } - virtual void setType( int type ) - { - ttype = type; - } - - static RefAST factory(); - - static const char* const TYPE_NAME; -protected: - int ttype; - ANTLR_USE_NAMESPACE(std)string text; -}; - -typedef ASTRefCount RefCommonAST; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_CommonAST_hpp__ diff --git a/libs/antlr-2.7.7/antlr/CommonASTWithHiddenTokens.hpp b/libs/antlr-2.7.7/antlr/CommonASTWithHiddenTokens.hpp deleted file mode 100644 index 8fa4d93a7..000000000 --- a/libs/antlr-2.7.7/antlr/CommonASTWithHiddenTokens.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef INC_CommonASTWithHiddenTokens_hpp__ -#define INC_CommonASTWithHiddenTokens_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/CommonASTWithHiddenTokens.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** A CommonAST whose initialization copies hidden token - * information from the Token used to create a node. - */ -class ANTLR_API CommonASTWithHiddenTokens : public CommonAST { -public: - CommonASTWithHiddenTokens(); - virtual ~CommonASTWithHiddenTokens(); - virtual const char* typeName( void ) const - { - return CommonASTWithHiddenTokens::TYPE_NAME; - } - /// Clone this AST node. - virtual RefAST clone( void ) const; - - // Borland C++ builder seems to need the decl's of the first two... - virtual void initialize(int t,const ANTLR_USE_NAMESPACE(std)string& txt); - virtual void initialize(RefAST t); - virtual void initialize(RefToken t); - - virtual RefToken getHiddenAfter() const - { - return hiddenAfter; - } - - virtual RefToken getHiddenBefore() const - { - return hiddenBefore; - } - - static RefAST factory(); - - static const char* const TYPE_NAME; -protected: - RefToken hiddenBefore,hiddenAfter; // references to hidden tokens -}; - -typedef ASTRefCount RefCommonASTWithHiddenTokens; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_CommonASTWithHiddenTokens_hpp__ diff --git a/libs/antlr-2.7.7/antlr/CommonHiddenStreamToken.hpp b/libs/antlr-2.7.7/antlr/CommonHiddenStreamToken.hpp deleted file mode 100644 index 30a7015e6..000000000 --- a/libs/antlr-2.7.7/antlr/CommonHiddenStreamToken.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef INC_CommonHiddenStreamToken_hpp__ -#define INC_CommonHiddenStreamToken_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/CommonHiddenStreamToken.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class ANTLR_API CommonHiddenStreamToken : public CommonToken { -protected: - RefToken hiddenBefore; - RefToken hiddenAfter; - -public: - CommonHiddenStreamToken(); - CommonHiddenStreamToken(int t, const ANTLR_USE_NAMESPACE(std)string& txt); - CommonHiddenStreamToken(const ANTLR_USE_NAMESPACE(std)string& s); - - RefToken getHiddenAfter(); - RefToken getHiddenBefore(); - - static RefToken factory(); - - void setHiddenAfter(RefToken t); - void setHiddenBefore(RefToken t); -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_CommonHiddenStreamToken_hpp__ diff --git a/libs/antlr-2.7.7/antlr/CommonToken.hpp b/libs/antlr-2.7.7/antlr/CommonToken.hpp deleted file mode 100644 index 8a032d71e..000000000 --- a/libs/antlr-2.7.7/antlr/CommonToken.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef INC_CommonToken_hpp__ -#define INC_CommonToken_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/CommonToken.hpp#2 $ - */ - -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class ANTLR_API CommonToken : public Token { -public: - CommonToken(); - CommonToken(int t, const ANTLR_USE_NAMESPACE(std)string& txt); - CommonToken(const ANTLR_USE_NAMESPACE(std)string& s); - - /// return contents of token - virtual ANTLR_USE_NAMESPACE(std)string getText() const - { - return text; - } - - /// set contents of token - virtual void setText(const ANTLR_USE_NAMESPACE(std)string& s) - { - text = s; - } - - /** get the line the token is at (starting at 1) - * @see CharScanner::newline() - * @see CharScanner::tab() - */ - virtual int getLine() const - { - return line; - } - /** gt the column the token is at (starting at 1) - * @see CharScanner::newline() - * @see CharScanner::tab() - */ - virtual int getColumn() const - { - return col; - } - - /// set line for token - virtual void setLine(int l) - { - line = l; - } - /// set column for token - virtual void setColumn(int c) - { - col = c; - } - - virtual ANTLR_USE_NAMESPACE(std)string toString() const; - static RefToken factory(); - -protected: - // most tokens will want line and text information - int line; - int col; - ANTLR_USE_NAMESPACE(std)string text; - -private: - CommonToken(const CommonToken&); - const CommonToken& operator=(const CommonToken&); -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_CommonToken_hpp__ diff --git a/libs/antlr-2.7.7/antlr/IOException.hpp b/libs/antlr-2.7.7/antlr/IOException.hpp deleted file mode 100644 index ed87f8acf..000000000 --- a/libs/antlr-2.7.7/antlr/IOException.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef INC_IOException_hpp__ -#define INC_IOException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id:$ - */ - -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** Generic IOException used inside support code. (thrown by XML I/O routs) - * basically this is something I'm using since a lot of compilers don't - * support ios_base::failure. - */ -class ANTLR_API IOException : public ANTLRException -{ -public: - ANTLR_USE_NAMESPACE(std)exception io; - - IOException( ANTLR_USE_NAMESPACE(std)exception& e ) - : ANTLRException(e.what()) - { - } - IOException( const ANTLR_USE_NAMESPACE(std)string& mesg ) - : ANTLRException(mesg) - { - } - virtual ~IOException() throw() - { - } -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_IOException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/InputBuffer.hpp b/libs/antlr-2.7.7/antlr/InputBuffer.hpp deleted file mode 100644 index f557f40b5..000000000 --- a/libs/antlr-2.7.7/antlr/InputBuffer.hpp +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef INC_InputBuffer_hpp__ -#define INC_InputBuffer_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/InputBuffer.hpp#2 $ - */ - -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** A Stream of characters fed to the lexer from a InputStream that can - * be rewound via mark()/rewind() methods. - *

- * A dynamic array is used to buffer up all the input characters. Normally, - * "k" characters are stored in the buffer. More characters may be stored during - * guess mode (testing syntactic predicate), or when LT(i>k) is referenced. - * Consumption of characters is deferred. In other words, reading the next - * character is not done by conume(), but deferred until needed by LA or LT. - *

- * - * @see antlr.CharQueue - */ -class ANTLR_API InputBuffer { -public: - /** Create a character buffer */ - InputBuffer() - : nMarkers(0) - , markerOffset(0) - , numToConsume(0) - { - } - - virtual ~InputBuffer() - { - } - - /// Reset the input buffer to empty state - virtual inline void reset( void ) - { - nMarkers = 0; - markerOffset = 0; - numToConsume = 0; - queue.clear(); - } - - /** This method updates the state of the input buffer so that - * the text matched since the most recent mark() is no longer - * held by the buffer. So, you either do a mark/rewind for - * failed predicate or mark/commit to keep on parsing without - * rewinding the input. - */ - inline void commit( void ) - { - nMarkers--; - } - - /** Mark another character for deferred consumption */ - virtual inline void consume() - { - numToConsume++; - } - - /** Ensure that the character buffer is sufficiently full */ - virtual void fill(unsigned int amount); - - /** Override this in subclasses to get the next character */ - virtual int getChar()=0; - - /** Get a lookahead character */ - virtual inline int LA(unsigned int i) - { - fill(i); - return queue.elementAt(markerOffset + i - 1); - } - - /** Return an integer marker that can be used to rewind the buffer to - * its current state. - */ - virtual unsigned int mark(); - /// Are there any marks active in the InputBuffer - virtual inline bool isMarked() const - { - return (nMarkers != 0); - } - /** Rewind the character buffer to a marker. - * @param mark Marker returned previously from mark() - */ - virtual void rewind(unsigned int mark); - - /** Get the number of non-consumed characters - */ - virtual unsigned int entries() const; - - ANTLR_USE_NAMESPACE(std)string getLAChars() const; - - ANTLR_USE_NAMESPACE(std)string getMarkedChars() const; - -protected: - // char source - // leave to subclasses - - // Number of active markers - unsigned int nMarkers; // = 0; - - // Additional offset used when markers are active - unsigned int markerOffset; // = 0; - - // Number of calls to consume() since last LA() or LT() call - unsigned int numToConsume; // = 0; - - // Circular queue - CircularQueue queue; - - /** Sync up deferred consumption */ - void syncConsume(); - -private: - InputBuffer(const InputBuffer& other); - InputBuffer& operator=(const InputBuffer& other); -}; - -/** Sync up deferred consumption */ -inline void InputBuffer::syncConsume() { - if (numToConsume > 0) - { - if (nMarkers > 0) - markerOffset += numToConsume; - else - queue.removeItems( numToConsume ); - numToConsume = 0; - } -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_InputBuffer_hpp__ diff --git a/libs/antlr-2.7.7/antlr/LLkParser.hpp b/libs/antlr-2.7.7/antlr/LLkParser.hpp deleted file mode 100644 index ef9181a61..000000000 --- a/libs/antlr-2.7.7/antlr/LLkParser.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef INC_LLkParser_hpp__ -#define INC_LLkParser_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/LLkParser.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/**An LL(k) parser. - * - * @see antlr.Token - * @see antlr.TokenBuffer - * @see antlr.LL1Parser - */ -class ANTLR_API LLkParser : public Parser { -public: - LLkParser(const ParserSharedInputState& lexer, int k_); - - LLkParser(TokenBuffer& tokenBuf, int k_); - - LLkParser(TokenStream& lexer, int k_); - - /** Consume another token from the input stream. Can only write sequentially! - * If you need 3 tokens ahead, you must consume() 3 times. - *

- * Note that it is possible to overwrite tokens that have not been matched. - * For example, calling consume() 3 times when k=2, means that the first token - * consumed will be overwritten with the 3rd. - */ - virtual inline void consume() - { - inputState->getInput().consume(); - } - - virtual inline int LA(unsigned int i) - { - return inputState->getInput().LA(i); - } - - virtual inline RefToken LT(unsigned int i) - { - return inputState->getInput().LT(i); - } -protected: - /// the lookahead this LL(k) parser is using. - int k; -private: - void trace(const char* ee, const char* rname); -public: - virtual void traceIn(const char* rname); - virtual void traceOut(const char* rname); -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_LLkParser_hpp__ diff --git a/libs/antlr-2.7.7/antlr/LexerSharedInputState.hpp b/libs/antlr-2.7.7/antlr/LexerSharedInputState.hpp deleted file mode 100644 index ff082dc20..000000000 --- a/libs/antlr-2.7.7/antlr/LexerSharedInputState.hpp +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef INC_LexerSharedInputState_hpp__ -#define INC_LexerSharedInputState_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/LexerSharedInputState.hpp#2 $ - */ - -#include -#include -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** This object contains the data associated with an - * input stream of characters. Multiple lexers - * share a single LexerSharedInputState to lex - * the same input stream. - */ -class ANTLR_API LexerInputState { -public: - /** Construct a new LexerInputState - * @param inbuf the InputBuffer to read from. The object is deleted together - * with the LexerInputState object. - */ - LexerInputState(InputBuffer* inbuf) - : column(1) - , line(1) - , tokenStartColumn(1) - , tokenStartLine(1) - , guessing(0) - , filename("") - , input(inbuf) - , inputResponsible(true) - { - } - - /** Construct a new LexerInputState - * @param inbuf the InputBuffer to read from. - */ - LexerInputState(InputBuffer& inbuf) - : column(1) - , line(1) - , tokenStartColumn(1) - , tokenStartLine(1) - , guessing(0) - , filename("") - , input(&inbuf) - , inputResponsible(false) - { - } - - /** Construct a new LexerInputState - * @param in an istream to read from. - * @see antlr.CharBuffer - */ - LexerInputState(ANTLR_USE_NAMESPACE(std)istream& in) - : column(1) - , line(1) - , tokenStartColumn(1) - , tokenStartLine(1) - , guessing(0) - , filename("") - , input(new CharBuffer(in)) - , inputResponsible(true) - { - } - - /** Reset the LexerInputState with a specified stream and filename. - * This method is a hack, dunno what I was thinking when I added it. - * This should actually be done in a subclass. - * @deprecated - */ - virtual void initialize( ANTLR_USE_NAMESPACE(std)istream& in, const char* file = "" ) - { - column = 1; - line = 1; - tokenStartColumn = 1; - tokenStartLine = 1; - guessing = 0; - filename = file; - - if( input && inputResponsible ) - delete input; - - input = new CharBuffer(in); - inputResponsible = true; - } - - /** Reset the LexerInputState to initial state. - * The underlying InputBuffer is also reset. - */ - virtual void reset( void ) - { - column = 1; - line = 1; - tokenStartColumn = 1; - tokenStartLine = 1; - guessing = 0; - input->reset(); - } - - /** Set the file position of the SharedLexerInputState. - * @param line_ line number to be set - * @param column_ column number to be set - */ - void setPosition( int line_, int column_ ) - { - line = line_; - column = column_; - } - - virtual ~LexerInputState() - { - if (inputResponsible) - delete input; - } - - int column; - int line; - int tokenStartColumn; - int tokenStartLine; - int guessing; - /** What file (if known) caused the problem? */ - ANTLR_USE_NAMESPACE(std)string filename; - InputBuffer& getInput(); -private: - /// Input buffer we use - InputBuffer* input; - /// Who is responsible for cleaning up the InputBuffer? - bool inputResponsible; - - // we don't want these: - LexerInputState(const LexerInputState&); - LexerInputState& operator=(const LexerInputState&); -}; - -inline InputBuffer& LexerInputState::getInput() -{ - return *input; -} - -/// A reference counted LexerInputState object -typedef RefCount LexerSharedInputState; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_LexerSharedInputState_hpp__ diff --git a/libs/antlr-2.7.7/antlr/MismatchedCharException.hpp b/libs/antlr-2.7.7/antlr/MismatchedCharException.hpp deleted file mode 100644 index 450541297..000000000 --- a/libs/antlr-2.7.7/antlr/MismatchedCharException.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef INC_MismatchedCharException_hpp__ -#define INC_MismatchedCharException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/MismatchedCharException.hpp#2 $ - */ - -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class CharScanner; - -class ANTLR_API MismatchedCharException : public RecognitionException { -public: - // Types of chars -#ifndef NO_STATIC_CONSTS - static const int CHAR = 1; - static const int NOT_CHAR = 2; - static const int RANGE = 3; - static const int NOT_RANGE = 4; - static const int SET = 5; - static const int NOT_SET = 6; -#else - enum { - CHAR = 1, - NOT_CHAR = 2, - RANGE = 3, - NOT_RANGE = 4, - SET = 5, - NOT_SET = 6 - }; -#endif - -public: - // One of the above - int mismatchType; - - // what was found on the input stream - int foundChar; - - // For CHAR/NOT_CHAR and RANGE/NOT_RANGE - int expecting; - - // For RANGE/NOT_RANGE (expecting is lower bound of range) - int upper; - - // For SET/NOT_SET - BitSet set; - -protected: - // who knows...they may want to ask scanner questions - CharScanner* scanner; - -public: - MismatchedCharException(); - - // Expected range / not range - MismatchedCharException( - int c, - int lower, - int upper_, - bool matchNot, - CharScanner* scanner_ - ); - - // Expected token / not token - MismatchedCharException( - int c, - int expecting_, - bool matchNot, - CharScanner* scanner_ - ); - - // Expected BitSet / not BitSet - MismatchedCharException( - int c, - BitSet set_, - bool matchNot, - CharScanner* scanner_ - ); - - ~MismatchedCharException() throw() {} - - /** - * Returns a clean error message (no line number/column information) - */ - ANTLR_USE_NAMESPACE(std)string getMessage() const; -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_MismatchedCharException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/MismatchedTokenException.hpp b/libs/antlr-2.7.7/antlr/MismatchedTokenException.hpp deleted file mode 100644 index 4631f50b2..000000000 --- a/libs/antlr-2.7.7/antlr/MismatchedTokenException.hpp +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef INC_MismatchedTokenException_hpp__ -#define INC_MismatchedTokenException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/MismatchedTokenException.hpp#2 $ - */ - -#include -#include -#include -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class ANTLR_API MismatchedTokenException : public RecognitionException { -public: - MismatchedTokenException(); - - /// Expected range / not range - MismatchedTokenException( - const char* const* tokenNames_, - const int numTokens_, - RefAST node_, - int lower, - int upper_, - bool matchNot - ); - - // Expected token / not token - MismatchedTokenException( - const char* const* tokenNames_, - const int numTokens_, - RefAST node_, - int expecting_, - bool matchNot - ); - - // Expected BitSet / not BitSet - MismatchedTokenException( - const char* const* tokenNames_, - const int numTokens_, - RefAST node_, - BitSet set_, - bool matchNot - ); - - // Expected range / not range - MismatchedTokenException( - const char* const* tokenNames_, - const int numTokens_, - RefToken token_, - int lower, - int upper_, - bool matchNot, - const ANTLR_USE_NAMESPACE(std)string& fileName_ - ); - - // Expected token / not token - MismatchedTokenException( - const char* const* tokenNames_, - const int numTokens_, - RefToken token_, - int expecting_, - bool matchNot, - const ANTLR_USE_NAMESPACE(std)string& fileName_ - ); - - // Expected BitSet / not BitSet - MismatchedTokenException( - const char* const* tokenNames_, - const int numTokens_, - RefToken token_, - BitSet set_, - bool matchNot, - const ANTLR_USE_NAMESPACE(std)string& fileName_ - ); - ~MismatchedTokenException() throw() {} - - /** - * Returns a clean error message (no line number/column information) - */ - ANTLR_USE_NAMESPACE(std)string getMessage() const; - -public: - /// The token that was encountered - const RefToken token; - /// The offending AST node if tree walking - const RefAST node; - /// taken from node or token object - ANTLR_USE_NAMESPACE(std)string tokenText; - - /// Types of tokens -#ifndef NO_STATIC_CONSTS - static const int TOKEN = 1; - static const int NOT_TOKEN = 2; - static const int RANGE = 3; - static const int NOT_RANGE = 4; - static const int SET = 5; - static const int NOT_SET = 6; -#else - enum { - TOKEN = 1, - NOT_TOKEN = 2, - RANGE = 3, - NOT_RANGE = 4, - SET = 5, - NOT_SET = 6 - }; -#endif - -public: - /// One of the above - int mismatchType; - - /// For TOKEN/NOT_TOKEN and RANGE/NOT_RANGE - int expecting; - - /// For RANGE/NOT_RANGE (expecting is lower bound of range) - int upper; - - /// For SET/NOT_SET - BitSet set; - -private: - /// Token names array for formatting - const char* const* tokenNames; - /// Max number of tokens in tokenNames - const int numTokens; - /// Return token name for tokenType - ANTLR_USE_NAMESPACE(std)string tokenName(int tokenType) const; -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_MismatchedTokenException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/NoViableAltException.hpp b/libs/antlr-2.7.7/antlr/NoViableAltException.hpp deleted file mode 100644 index e3677ded4..000000000 --- a/libs/antlr-2.7.7/antlr/NoViableAltException.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef INC_NoViableAltException_hpp__ -#define INC_NoViableAltException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/NoViableAltException.hpp#2 $ - */ - -#include -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class ANTLR_API NoViableAltException : public RecognitionException { -public: - const RefToken token; - const RefAST node; // handles parsing and treeparsing - - NoViableAltException(RefAST t); - NoViableAltException(RefToken t,const ANTLR_USE_NAMESPACE(std)string& fileName_); - - ~NoViableAltException() throw() {} - - /** - * Returns a clean error message (no line number/column information) - */ - ANTLR_USE_NAMESPACE(std)string getMessage() const; -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_NoViableAltException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/NoViableAltForCharException.hpp b/libs/antlr-2.7.7/antlr/NoViableAltForCharException.hpp deleted file mode 100644 index d61c18b09..000000000 --- a/libs/antlr-2.7.7/antlr/NoViableAltForCharException.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef INC_NoViableAltForCharException_hpp__ -# define INC_NoViableAltForCharException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/NoViableAltForCharException.hpp#2 $ - */ - -# include -# include -# include - -# ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr -{ -# endif - -class ANTLR_API NoViableAltForCharException : public RecognitionException -{ -public: - NoViableAltForCharException(int c, CharScanner* scanner); - NoViableAltForCharException(int c, const ANTLR_USE_NAMESPACE(std)string& fileName_, - int line_, int column_); - - virtual ~NoViableAltForCharException() throw() - { - } - - /// Returns a clean error message (no line number/column information) - ANTLR_USE_NAMESPACE(std)string getMessage() const; -protected: - int foundChar; -}; - -# ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -# endif - -#endif //INC_NoViableAltForCharException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/Parser.hpp b/libs/antlr-2.7.7/antlr/Parser.hpp deleted file mode 100644 index 3eefab501..000000000 --- a/libs/antlr-2.7.7/antlr/Parser.hpp +++ /dev/null @@ -1,320 +0,0 @@ -#ifndef INC_Parser_hpp__ -#define INC_Parser_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/Parser.hpp#2 $ - */ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -extern bool DEBUG_PARSER; - -/** A generic ANTLR parser (LL(k) for k>=1) containing a bunch of - * utility routines useful at any lookahead depth. We distinguish between - * the LL(1) and LL(k) parsers because of efficiency. This may not be - * necessary in the near future. - * - * Each parser object contains the state of the parse including a lookahead - * cache (the form of which is determined by the subclass), whether or - * not the parser is in guess mode, where tokens come from, etc... - * - *

- * During guess mode, the current lookahead token(s) and token type(s) - * cache must be saved because the token stream may not have been informed - * to save the token (via mark) before the try block. - * Guessing is started by: - *

    - *
  1. saving the lookahead cache. - *
  2. marking the current position in the TokenBuffer. - *
  3. increasing the guessing level. - *
- * - * After guessing, the parser state is restored by: - *
    - *
  1. restoring the lookahead cache. - *
  2. rewinding the TokenBuffer. - *
  3. decreasing the guessing level. - *
- * - * @see antlr.Token - * @see antlr.TokenBuffer - * @see antlr.TokenStream - * @see antlr.LL1Parser - * @see antlr.LLkParser - * - * @todo add constructors with ASTFactory. - */ -class ANTLR_API Parser { -protected: - Parser(TokenBuffer& input) - : inputState(new ParserInputState(input)), astFactory(0), traceDepth(0) - { - } - Parser(TokenBuffer* input) - : inputState(new ParserInputState(input)), astFactory(0), traceDepth(0) - { - } - Parser(const ParserSharedInputState& state) - : inputState(state), astFactory(0), traceDepth(0) - { - } -public: - virtual ~Parser() - { - } - - /** Return the token type of the ith token of lookahead where i=1 - * is the current token being examined by the parser (i.e., it - * has not been matched yet). - */ - virtual int LA(unsigned int i)=0; - - /// Return the i-th token of lookahead - virtual RefToken LT(unsigned int i)=0; - - /** DEPRECATED! Specify the factory to be used during tree building. (Compulsory) - * Setting the factory is nowadays compulsory. - * @see setASTFactory - */ - virtual void setASTNodeFactory( ASTFactory *factory ) - { - astFactory = factory; - } - /** Specify the factory to be used during tree building. (Compulsory) - * Setting the factory is nowadays compulsory. - */ - virtual void setASTFactory( ASTFactory *factory ) - { - astFactory = factory; - } - /** Return a pointer to the ASTFactory used. - * So you might use it in subsequent treewalkers or to reload AST's - * from disk. - */ - virtual ASTFactory* getASTFactory() - { - return astFactory; - } - /** Get the root AST node of the generated AST. When using a custom AST type - * or heterogenous AST's, you'll have to convert it to the right type - * yourself. - */ - virtual RefAST getAST() = 0; - - /// Return the filename of the input file. - virtual inline ANTLR_USE_NAMESPACE(std)string getFilename() const - { - return inputState->filename; - } - /// Set the filename of the input file (used for error reporting). - virtual void setFilename(const ANTLR_USE_NAMESPACE(std)string& f) - { - inputState->filename = f; - } - - virtual void setInputState(ParserSharedInputState state) - { - inputState = state; - } - virtual inline ParserSharedInputState getInputState() const - { - return inputState; - } - - /// Get another token object from the token stream - virtual void consume()=0; - /// Consume tokens until one matches the given token - virtual void consumeUntil(int tokenType) - { - while (LA(1) != Token::EOF_TYPE && LA(1) != tokenType) - consume(); - } - - /// Consume tokens until one matches the given token set - virtual void consumeUntil(const BitSet& set) - { - while (LA(1) != Token::EOF_TYPE && !set.member(LA(1))) - consume(); - } - - /** Make sure current lookahead symbol matches token type t. - * Throw an exception upon mismatch, which is catch by either the - * error handler or by the syntactic predicate. - */ - virtual void match(int t) - { - if ( DEBUG_PARSER ) - { - traceIndent(); - ANTLR_USE_NAMESPACE(std)cout << "enter match(" << t << ") with LA(1)=" << LA(1) << ANTLR_USE_NAMESPACE(std)endl; - } - if ( LA(1) != t ) - { - if ( DEBUG_PARSER ) - { - traceIndent(); - ANTLR_USE_NAMESPACE(std)cout << "token mismatch: " << LA(1) << "!=" << t << ANTLR_USE_NAMESPACE(std)endl; - } - throw MismatchedTokenException(getTokenNames(), getNumTokens(), LT(1), t, false, getFilename()); - } - else - { - // mark token as consumed -- fetch next token deferred until LA/LT - consume(); - } - } - - virtual void matchNot(int t) - { - if ( LA(1)==t ) - { - // Throws inverted-sense exception - throw MismatchedTokenException(getTokenNames(), getNumTokens(), LT(1), t, true, getFilename()); - } - else - { - // mark token as consumed -- fetch next token deferred until LA/LT - consume(); - } - } - - /** Make sure current lookahead symbol matches the given set - * Throw an exception upon mismatch, which is catch by either the - * error handler or by the syntactic predicate. - */ - virtual void match(const BitSet& b) - { - if ( DEBUG_PARSER ) - { - traceIndent(); - ANTLR_USE_NAMESPACE(std)cout << "enter match(" << "bitset" /*b.toString()*/ - << ") with LA(1)=" << LA(1) << ANTLR_USE_NAMESPACE(std)endl; - } - if ( !b.member(LA(1)) ) - { - if ( DEBUG_PARSER ) - { - traceIndent(); - ANTLR_USE_NAMESPACE(std)cout << "token mismatch: " << LA(1) << " not member of " - << "bitset" /*b.toString()*/ << ANTLR_USE_NAMESPACE(std)endl; - } - throw MismatchedTokenException(getTokenNames(), getNumTokens(), LT(1), b, false, getFilename()); - } - else - { - // mark token as consumed -- fetch next token deferred until LA/LT - consume(); - } - } - - /** Mark a spot in the input and return the position. - * Forwarded to TokenBuffer. - */ - virtual inline unsigned int mark() - { - return inputState->getInput().mark(); - } - /// rewind to a previously marked position - virtual inline void rewind(unsigned int pos) - { - inputState->getInput().rewind(pos); - } - /** called by the generated parser to do error recovery, override to - * customize the behaviour. - */ - virtual void recover(const RecognitionException& ex, const BitSet& tokenSet) - { - (void)ex; - consume(); - consumeUntil(tokenSet); - } - - /// Parser error-reporting function can be overridden in subclass - virtual void reportError(const RecognitionException& ex); - /// Parser error-reporting function can be overridden in subclass - virtual void reportError(const ANTLR_USE_NAMESPACE(std)string& s); - /// Parser warning-reporting function can be overridden in subclass - virtual void reportWarning(const ANTLR_USE_NAMESPACE(std)string& s); - - /// get the token name for the token number 'num' - virtual const char* getTokenName(int num) const = 0; - /// get a vector with all token names - virtual const char* const* getTokenNames() const = 0; - /** Get the number of tokens defined. - * This one should be overridden in subclasses. - */ - virtual int getNumTokens(void) const = 0; - - /** Set or change the input token buffer */ -// void setTokenBuffer(TokenBuffer* t); - - virtual void traceIndent(); - virtual void traceIn(const char* rname); - virtual void traceOut(const char* rname); -protected: -// void setTokenNames(const char** tokenNames_); - - ParserSharedInputState inputState; - -// /// AST return value for a rule is squirreled away here -// RefAST returnAST; - - /// AST support code; parser and treeparser delegate to this object - ASTFactory *astFactory; - - // used to keep track of the indentation for the trace - int traceDepth; - - /** Utility class which allows tracing to work even when exceptions are - * thrown. - */ - class Tracer { /*{{{*/ - private: - Parser* parser; - const char* text; - public: - Tracer(Parser* p,const char * t) - : parser(p), text(t) - { - parser->traceIn(text); - } - ~Tracer() - { -#ifdef ANTLR_CXX_SUPPORTS_UNCAUGHT_EXCEPTION - // Only give trace if there's no uncaught exception.. - if(!ANTLR_USE_NAMESPACE(std)uncaught_exception()) -#endif - parser->traceOut(text); - } - private: - Tracer(const Tracer&); // undefined - const Tracer& operator=(const Tracer&); // undefined - /*}}}*/ - }; -private: - Parser(const Parser&); // undefined - const Parser& operator=(const Parser&); // undefined -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_Parser_hpp__ diff --git a/libs/antlr-2.7.7/antlr/ParserSharedInputState.hpp b/libs/antlr-2.7.7/antlr/ParserSharedInputState.hpp deleted file mode 100644 index d1f8d1518..000000000 --- a/libs/antlr-2.7.7/antlr/ParserSharedInputState.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef INC_ParserSharedInputState_hpp__ -#define INC_ParserSharedInputState_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/ParserSharedInputState.hpp#2 $ - */ - -#include -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** This object contains the data associated with an - * input stream of tokens. Multiple parsers - * share a single ParserSharedInputState to parse - * the same stream of tokens. - */ -class ANTLR_API ParserInputState { -public: - /** Construct a new ParserInputState - * @param in the TokenBuffer to read from. The object is deleted together - * with the ParserInputState object. - */ - ParserInputState( TokenBuffer* in ) - : guessing(0) - , filename() - , input(in) - , inputResponsible(true) - { - } - /** Construct a new ParserInputState - * @param in the TokenBuffer to read from. - */ - ParserInputState( TokenBuffer& in ) - : guessing(0) - , filename("") - , input(&in) - , inputResponsible(false) - { - } - - virtual ~ParserInputState() - { - if (inputResponsible) - delete input; - } - - TokenBuffer& getInput( void ) - { - return *input; - } - - /// Reset the ParserInputState and the underlying TokenBuffer - void reset( void ) - { - input->reset(); - guessing = 0; - } - -public: - /** Are we guessing (guessing>0)? */ - int guessing; - /** What file (if known) caused the problem? - * @todo wrap this one.. - */ - ANTLR_USE_NAMESPACE(std)string filename; -private: - /** Where to get token objects */ - TokenBuffer* input; - /// Do we need to free the TokenBuffer or is it owned by another.. - bool inputResponsible; - - // we don't want these: - ParserInputState(const ParserInputState&); - ParserInputState& operator=(const ParserInputState&); -}; - -/// A reference counted ParserInputState -typedef RefCount ParserSharedInputState; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_ParserSharedInputState_hpp__ diff --git a/libs/antlr-2.7.7/antlr/RecognitionException.hpp b/libs/antlr-2.7.7/antlr/RecognitionException.hpp deleted file mode 100644 index c131831b6..000000000 --- a/libs/antlr-2.7.7/antlr/RecognitionException.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef INC_RecognitionException_hpp__ -# define INC_RecognitionException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/RecognitionException.hpp#2 $ - */ - -# include -# include - -# ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr -{ -# endif - class ANTLR_API RecognitionException : public ANTLRException - { - public: - RecognitionException(); - RecognitionException(const ANTLR_USE_NAMESPACE(std)string& s); - RecognitionException(const ANTLR_USE_NAMESPACE(std)string& s, - const ANTLR_USE_NAMESPACE(std)string& fileName, - int line, int column ); - - virtual ~RecognitionException() throw() - { - } - - /// Return file where mishap occurred. - virtual ANTLR_USE_NAMESPACE(std)string getFilename() const throw() - { - return fileName; - } - /** - * @return the line number that this exception happened on. - */ - virtual int getLine() const throw() - { - return line; - } - /** - * @return the column number that this exception happened on. - */ - virtual int getColumn() const throw() - { - return column; - } - - /// Return complete error message with line/column number info (if present) - virtual ANTLR_USE_NAMESPACE(std)string toString() const; - - /// See what file/line/column info is present and return it as a string - virtual ANTLR_USE_NAMESPACE(std)string getFileLineColumnString() const; - protected: - ANTLR_USE_NAMESPACE(std)string fileName; // not used by treeparsers - int line; // not used by treeparsers - int column; // not used by treeparsers - }; - -# ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -# endif - -#endif //INC_RecognitionException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/RefCount.hpp b/libs/antlr-2.7.7/antlr/RefCount.hpp deleted file mode 100644 index 4a98d92cb..000000000 --- a/libs/antlr-2.7.7/antlr/RefCount.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef INC_RefCount_hpp__ -#define INC_RefCount_hpp__ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/RefCount.hpp#2 $ - */ - -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -template -class ANTLR_API RefCount { -private: - struct Ref { - T* const ptr; - unsigned int count; - - Ref(T* p) : ptr(p), count(1) {} - ~Ref() {delete ptr;} - Ref* increment() {++count;return this;} - bool decrement() {return (--count==0);} - private: - Ref(const Ref&); - Ref& operator=(const Ref&); - }* ref; - -public: - explicit RefCount(T* p = 0) - : ref(p ? new Ref(p) : 0) - { - } - RefCount(const RefCount& other) - : ref(other.ref ? other.ref->increment() : 0) - { - } - ~RefCount() - { - if (ref && ref->decrement()) - delete ref; - } - RefCount& operator=(const RefCount& other) - { - Ref* tmp = other.ref ? other.ref->increment() : 0; - if (ref && ref->decrement()) - delete ref; - ref = tmp; - return *this; - } - - operator T* () const - { - return ref ? ref->ptr : 0; - } - - T* operator->() const - { - return ref ? ref->ptr : 0; - } - - T* get() const - { - return ref ? ref->ptr : 0; - } - - template operator RefCount() - { - return RefCount(ref); - } -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_RefCount_hpp__ diff --git a/libs/antlr-2.7.7/antlr/SemanticException.hpp b/libs/antlr-2.7.7/antlr/SemanticException.hpp deleted file mode 100644 index c8e9ea395..000000000 --- a/libs/antlr-2.7.7/antlr/SemanticException.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef INC_SemanticException_hpp__ -#define INC_SemanticException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/SemanticException.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class ANTLR_API SemanticException : public RecognitionException { -public: - SemanticException(const ANTLR_USE_NAMESPACE(std)string& s) - : RecognitionException(s) - { - } - SemanticException(const ANTLR_USE_NAMESPACE(std)string& s, - const ANTLR_USE_NAMESPACE(std)string& fileName_, - int line_,int column_) - : RecognitionException(s,fileName_,line_,column_) - { - } - - ~SemanticException() throw() - { - } -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_SemanticException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/String.hpp b/libs/antlr-2.7.7/antlr/String.hpp deleted file mode 100644 index b3da3c33d..000000000 --- a/libs/antlr-2.7.7/antlr/String.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef INC_String_hpp__ -#define INC_String_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/String.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -ANTLR_API ANTLR_USE_NAMESPACE(std)string operator+( const ANTLR_USE_NAMESPACE(std)string& lhs, const int rhs ); -ANTLR_API ANTLR_USE_NAMESPACE(std)string operator+( const ANTLR_USE_NAMESPACE(std)string& lhs, size_t rhs ); - -ANTLR_API ANTLR_USE_NAMESPACE(std)string charName( int ch ); - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_String_hpp__ diff --git a/libs/antlr-2.7.7/antlr/Token.hpp b/libs/antlr-2.7.7/antlr/Token.hpp deleted file mode 100644 index 33406425f..000000000 --- a/libs/antlr-2.7.7/antlr/Token.hpp +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef INC_Token_hpp__ -#define INC_Token_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/Token.hpp#2 $ - */ - -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -struct TokenRef; - -/** A token is minimally a token type. Subclasses can add the text matched - * for the token and line info. - */ -class ANTLR_API Token -{ -public: - // constants -#ifndef NO_STATIC_CONSTS - static const int MIN_USER_TYPE = 4; - static const int NULL_TREE_LOOKAHEAD = 3; - static const int INVALID_TYPE = 0; - static const int EOF_TYPE = 1; - static const int SKIP = -1; -#else - enum { - MIN_USER_TYPE = 4, - NULL_TREE_LOOKAHEAD = 3, - INVALID_TYPE = 0, - EOF_TYPE = 1, - SKIP = -1 - }; -#endif - - Token() - : ref(0) - , type(INVALID_TYPE) - { - } - Token(int t) - : ref(0) - , type(t) - { - } - Token(int t, const ANTLR_USE_NAMESPACE(std)string& txt) - : ref(0) - , type(t) - { - setText(txt); - } - virtual ~Token() - { - } - - virtual int getColumn() const; - virtual int getLine() const; - virtual ANTLR_USE_NAMESPACE(std)string getText() const; - virtual const ANTLR_USE_NAMESPACE(std)string& getFilename() const; - virtual int getType() const; - - virtual void setColumn(int c); - - virtual void setLine(int l); - virtual void setText(const ANTLR_USE_NAMESPACE(std)string& t); - virtual void setType(int t); - - virtual void setFilename( const std::string& file ); - - virtual ANTLR_USE_NAMESPACE(std)string toString() const; - -private: - friend struct TokenRef; - TokenRef* ref; - - int type; ///< the type of the token - - Token(RefToken other); - Token& operator=(const Token& other); - Token& operator=(RefToken other); - - Token(const Token&); -}; - -extern ANTLR_API RefToken nullToken; - -#ifdef NEEDS_OPERATOR_LESS_THAN -// RK: Added after 2.7.2 previously it was undefined. -// AL: what to return if l and/or r point to nullToken??? -inline bool operator<( RefToken l, RefToken r ) -{ - return nullToken == l ? ( nullToken == r ? false : true ) : l->getType() < r->getType(); -} -#endif - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_Token_hpp__ diff --git a/libs/antlr-2.7.7/antlr/TokenBuffer.hpp b/libs/antlr-2.7.7/antlr/TokenBuffer.hpp deleted file mode 100644 index 948243f3e..000000000 --- a/libs/antlr-2.7.7/antlr/TokenBuffer.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef INC_TokenBuffer_hpp__ -#define INC_TokenBuffer_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/TokenBuffer.hpp#2 $ - */ - -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/**A Stream of Token objects fed to the parser from a TokenStream that can - * be rewound via mark()/rewind() methods. - *

- * A dynamic array is used to buffer up all the input tokens. Normally, - * "k" tokens are stored in the buffer. More tokens may be stored during - * guess mode (testing syntactic predicate), or when LT(i>k) is referenced. - * Consumption of tokens is deferred. In other words, reading the next - * token is not done by conume(), but deferred until needed by LA or LT. - *

- * - * @todo: see if we can integrate this one with InputBuffer into one template - * or so. - * - * @see antlr.Token - * @see antlr.TokenStream - * @see antlr.TokenQueue - */ -class ANTLR_API TokenBuffer { -public: - /** Create a token buffer */ - TokenBuffer(TokenStream& input_); - virtual ~TokenBuffer(); - - /// Reset the input buffer to empty state - inline void reset( void ) - { - nMarkers = 0; - markerOffset = 0; - numToConsume = 0; - queue.clear(); - } - - /** Get a lookahead token value */ - int LA( unsigned int i ); - - /** Get a lookahead token */ - RefToken LT( unsigned int i ); - - /** Return an integer marker that can be used to rewind the buffer to - * its current state. - */ - unsigned int mark(); - - /**Rewind the token buffer to a marker. - * @param mark Marker returned previously from mark() - */ - void rewind(unsigned int mark); - - /** Mark another token for deferred consumption */ - inline void consume() - { - numToConsume++; - } - - /// Return the number of entries in the TokenBuffer - virtual unsigned int entries() const; - -private: - /** Ensure that the token buffer is sufficiently full */ - void fill(unsigned int amount); - /** Sync up deferred consumption */ - void syncConsume(); - -protected: - /// Token source - TokenStream& input; - - /// Number of active markers - unsigned int nMarkers; - - /// Additional offset used when markers are active - unsigned int markerOffset; - - /// Number of calls to consume() since last LA() or LT() call - unsigned int numToConsume; - - /// Circular queue with Tokens - CircularQueue queue; - -private: - TokenBuffer(const TokenBuffer& other); - const TokenBuffer& operator=(const TokenBuffer& other); -}; - -/** Sync up deferred consumption */ -inline void TokenBuffer::syncConsume() -{ - if (numToConsume > 0) - { - if (nMarkers > 0) - markerOffset += numToConsume; - else - queue.removeItems( numToConsume ); - - numToConsume = 0; - } -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_TokenBuffer_hpp__ diff --git a/libs/antlr-2.7.7/antlr/TokenRefCount.hpp b/libs/antlr-2.7.7/antlr/TokenRefCount.hpp deleted file mode 100644 index 9ccbb98c8..000000000 --- a/libs/antlr-2.7.7/antlr/TokenRefCount.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef INC_TokenRefCount_hpp__ -# define INC_TokenRefCount_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id:$ - */ - -# include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class Token; - -struct ANTLR_API TokenRef -{ - Token* const ptr; - unsigned int count; - - TokenRef(Token* p); - ~TokenRef(); - TokenRef* increment() - { - ++count; - return this; - } - bool decrement() - { - return (--count==0); - } - - static TokenRef* getRef(const Token* p); -private: - TokenRef( const TokenRef& ); - TokenRef& operator=( const TokenRef& ); -}; - -template - class ANTLR_API TokenRefCount -{ -private: - TokenRef* ref; - -public: - TokenRefCount(const Token* p=0) - : ref(p ? TokenRef::getRef(p) : 0) - { - } - TokenRefCount(const TokenRefCount& other) - : ref(other.ref ? other.ref->increment() : 0) - { - } - ~TokenRefCount() - { - if (ref && ref->decrement()) - delete ref; - } - TokenRefCount& operator=(Token* other) - { - TokenRef* tmp = TokenRef::getRef(other); - - if (ref && ref->decrement()) - delete ref; - - ref=tmp; - - return *this; - } - TokenRefCount& operator=(const TokenRefCount& other) - { - if( other.ref != ref ) - { - TokenRef* tmp = other.ref ? other.ref->increment() : 0; - - if (ref && ref->decrement()) - delete ref; - - ref=tmp; - } - return *this; - } - - operator T* () const { return ref ? static_cast(ref->ptr) : 0; } - T* operator->() const { return ref ? static_cast(ref->ptr) : 0; } - T* get() const { return ref ? static_cast(ref->ptr) : 0; } -}; - -typedef TokenRefCount RefToken; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_TokenRefCount_hpp__ diff --git a/libs/antlr-2.7.7/antlr/TokenStream.hpp b/libs/antlr-2.7.7/antlr/TokenStream.hpp deleted file mode 100644 index 3bec59863..000000000 --- a/libs/antlr-2.7.7/antlr/TokenStream.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef INC_TokenStream_hpp__ -#define INC_TokenStream_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/TokenStream.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** This interface allows any object to pretend it is a stream - * of tokens. - * @author Terence Parr, MageLang Institute - */ -class ANTLR_API TokenStream { -public: - virtual RefToken nextToken()=0; - virtual ~TokenStream() - { - } -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_TokenStream_hpp__ diff --git a/libs/antlr-2.7.7/antlr/TokenStreamBasicFilter.hpp b/libs/antlr-2.7.7/antlr/TokenStreamBasicFilter.hpp deleted file mode 100644 index 839f97e5c..000000000 --- a/libs/antlr-2.7.7/antlr/TokenStreamBasicFilter.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef INC_TokenStreamBasicFilter_hpp__ -#define INC_TokenStreamBasicFilter_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/TokenStreamBasicFilter.hpp#2 $ - */ - -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** This object is a TokenStream that passes through all - * tokens except for those that you tell it to discard. - * There is no buffering of the tokens. - */ -class ANTLR_API TokenStreamBasicFilter : public TokenStream { - /** The set of token types to discard */ -protected: - BitSet discardMask; - - /** The input stream */ -protected: - TokenStream* input; - -public: - TokenStreamBasicFilter(TokenStream& input_); - - void discard(int ttype); - - void discard(const BitSet& mask); - - RefToken nextToken(); -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_TokenStreamBasicFilter_hpp__ diff --git a/libs/antlr-2.7.7/antlr/TokenStreamException.hpp b/libs/antlr-2.7.7/antlr/TokenStreamException.hpp deleted file mode 100644 index a3f4d5488..000000000 --- a/libs/antlr-2.7.7/antlr/TokenStreamException.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef INC_TokenStreamException_hpp__ -#define INC_TokenStreamException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/TokenStreamException.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** Baseclass for exceptions thrown by classes implementing the TokenStream - * interface. - * @see TokenStream - */ -class ANTLR_API TokenStreamException : public ANTLRException { -public: - TokenStreamException() - : ANTLRException() - { - } - TokenStreamException(const ANTLR_USE_NAMESPACE(std)string& s) - : ANTLRException(s) - { - } - virtual ~TokenStreamException() throw() - { - } -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_TokenStreamException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/TokenStreamHiddenTokenFilter.hpp b/libs/antlr-2.7.7/antlr/TokenStreamHiddenTokenFilter.hpp deleted file mode 100644 index 7ab5c8264..000000000 --- a/libs/antlr-2.7.7/antlr/TokenStreamHiddenTokenFilter.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef INC_TokenStreamHiddenTokenFilter_hpp__ -#define INC_TokenStreamHiddenTokenFilter_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/TokenStreamHiddenTokenFilter.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/**This object filters a token stream coming from a lexer - * or another TokenStream so that only certain token channels - * get transmitted to the parser. - * - * Any of the channels can be filtered off as "hidden" channels whose - * tokens can be accessed from the parser. - */ -class ANTLR_API TokenStreamHiddenTokenFilter : public TokenStreamBasicFilter { - // protected BitSet discardMask; -protected: - BitSet hideMask; - -private: - RefToken nextMonitoredToken; - -protected: - /** track tail of hidden list emanating from previous - * monitored token - */ - RefToken lastHiddenToken; - - RefToken firstHidden; // = null; - -public: - TokenStreamHiddenTokenFilter(TokenStream& input); - -protected: - void consume(); - -private: - void consumeFirst(); - -public: - BitSet getDiscardMask() const; - - /** Return a ptr to the hidden token appearing immediately after - * token t in the input stream. - */ - RefToken getHiddenAfter(RefToken t); - - /** Return a ptr to the hidden token appearing immediately before - * token t in the input stream. - */ - RefToken getHiddenBefore(RefToken t); - - BitSet getHideMask() const; - - /** Return the first hidden token if one appears - * before any monitored token. - */ - RefToken getInitialHiddenToken(); - - void hide(int m); - - void hide(const BitSet& mask); - -protected: - RefToken LA(int i); - -public: -/** Return the next monitored token. - * Test the token following the monitored token. - * If following is another monitored token, save it - * for the next invocation of nextToken (like a single - * lookahead token) and return it then. - * If following is unmonitored, nondiscarded (hidden) - * channel token, add it to the monitored token. - * - * Note: EOF must be a monitored Token. - */ - RefToken nextToken(); -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_TokenStreamHiddenTokenFilter_hpp__ diff --git a/libs/antlr-2.7.7/antlr/TokenStreamIOException.hpp b/libs/antlr-2.7.7/antlr/TokenStreamIOException.hpp deleted file mode 100644 index 29f508bf8..000000000 --- a/libs/antlr-2.7.7/antlr/TokenStreamIOException.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef INC_TokenStreamIOException_hpp__ -#define INC_TokenStreamIOException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/TokenStreamIOException.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class TokenStreamIOException : public TokenStreamException { -public: - TokenStreamIOException() - : TokenStreamException() - { - } - TokenStreamIOException(const ANTLR_USE_NAMESPACE(std)exception& e) - : TokenStreamException(e.what()) - , io(e) - { - } - ~TokenStreamIOException() throw() - { - } -private: - ANTLR_USE_NAMESPACE(std)exception io; -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_TokenStreamIOException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/TokenStreamRecognitionException.hpp b/libs/antlr-2.7.7/antlr/TokenStreamRecognitionException.hpp deleted file mode 100644 index 396857891..000000000 --- a/libs/antlr-2.7.7/antlr/TokenStreamRecognitionException.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef INC_TokenStreamRecognitionException_hpp__ -#define INC_TokenStreamRecognitionException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/TokenStreamRecognitionException.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** Exception thrown from generated lexers when there's no default error - * handler specified. - * @see TokenStream - */ -class TokenStreamRecognitionException : public TokenStreamException { -public: - TokenStreamRecognitionException(RecognitionException& re) - : TokenStreamException(re.getMessage()) - , recog(re) - { - } - virtual ~TokenStreamRecognitionException() throw() - { - } - virtual ANTLR_USE_NAMESPACE(std)string toString() const - { - return recog.getFileLineColumnString()+getMessage(); - } - - virtual ANTLR_USE_NAMESPACE(std)string getFilename() const throw() - { - return recog.getFilename(); - } - virtual int getLine() const throw() - { - return recog.getLine(); - } - virtual int getColumn() const throw() - { - return recog.getColumn(); - } -private: - RecognitionException recog; -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_TokenStreamRecognitionException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/TokenStreamRetryException.hpp b/libs/antlr-2.7.7/antlr/TokenStreamRetryException.hpp deleted file mode 100644 index 7d17b3cda..000000000 --- a/libs/antlr-2.7.7/antlr/TokenStreamRetryException.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef INC_TokenStreamRetryException_hpp__ -#define INC_TokenStreamRetryException_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/TokenStreamRetryException.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class TokenStreamRetryException : public TokenStreamException { -public: - TokenStreamRetryException() {} - ~TokenStreamRetryException() throw() {} -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_TokenStreamRetryException_hpp__ diff --git a/libs/antlr-2.7.7/antlr/TokenStreamRewriteEngine.hpp b/libs/antlr-2.7.7/antlr/TokenStreamRewriteEngine.hpp deleted file mode 100644 index 9fab08c28..000000000 --- a/libs/antlr-2.7.7/antlr/TokenStreamRewriteEngine.hpp +++ /dev/null @@ -1,439 +0,0 @@ -#ifndef INC_TokenStreamRewriteEngine_hpp__ -#define INC_TokenStreamRewriteEngine_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** This token stream tracks the *entire* token stream coming from - * a lexer, but does not pass on the whitespace (or whatever else - * you want to discard) to the parser. - * - * This class can then be asked for the ith token in the input stream. - * Useful for dumping out the input stream exactly after doing some - * augmentation or other manipulations. Tokens are index from 0..n-1 - * - * You can insert stuff, replace, and delete chunks. Note that the - * operations are done lazily--only if you convert the buffer to a - * String. This is very efficient because you are not moving data around - * all the time. As the buffer of tokens is converted to strings, the - * toString() method(s) check to see if there is an operation at the - * current index. If so, the operation is done and then normal String - * rendering continues on the buffer. This is like having multiple Turing - * machine instruction streams (programs) operating on a single input tape. :) - * - * Since the operations are done lazily at toString-time, operations do not - * screw up the token index values. That is, an insert operation at token - * index i does not change the index values for tokens i+1..n-1. - * - * Because operations never actually alter the buffer, you may always get - * the original token stream back without undoing anything. Since - * the instructions are queued up, you can easily simulate transactions and - * roll back any changes if there is an error just by removing instructions. - * For example, - * - * TokenStreamRewriteEngine rewriteEngine = - * new TokenStreamRewriteEngine(lexer); - * JavaRecognizer parser = new JavaRecognizer(rewriteEngine); - * ... - * rewriteEngine.insertAfter("pass1", t, "foobar");} - * rewriteEngine.insertAfter("pass2", u, "start");} - * System.out.println(rewriteEngine.toString("pass1")); - * System.out.println(rewriteEngine.toString("pass2")); - * - * You can also have multiple "instruction streams" and get multiple - * rewrites from a single pass over the input. Just name the instruction - * streams and use that name again when printing the buffer. This could be - * useful for generating a C file and also its header file--all from the - * same buffer. - * - * If you don't use named rewrite streams, a "default" stream is used. - * - * Terence Parr, parrt@cs.usfca.edu - * University of San Francisco - * February 2004 - */ -class TokenStreamRewriteEngine : public TokenStream -{ -public: - typedef ANTLR_USE_NAMESPACE(std)vector token_list; - static const char* DEFAULT_PROGRAM_NAME; -#ifndef NO_STATIC_CONSTS - static const size_t MIN_TOKEN_INDEX; - static const int PROGRAM_INIT_SIZE; -#else - enum { - MIN_TOKEN_INDEX = 0, - PROGRAM_INIT_SIZE = 100 - }; -#endif - - struct tokenToStream { - tokenToStream( ANTLR_USE_NAMESPACE(std)ostream& o ) : out(o) {} - template void operator() ( const T& t ) { - out << t->getText(); - } - ANTLR_USE_NAMESPACE(std)ostream& out; - }; - - class RewriteOperation { - protected: - RewriteOperation( size_t idx, const ANTLR_USE_NAMESPACE(std)string& txt ) - : index(idx), text(txt) - { - } - public: - virtual ~RewriteOperation() - { - } - /** Execute the rewrite operation by possibly adding to the buffer. - * Return the index of the next token to operate on. - */ - virtual size_t execute( ANTLR_USE_NAMESPACE(std)ostream& /* out */ ) { - return index; - } - virtual size_t getIndex() const { - return index; - } - virtual const char* type() const { - return "RewriteOperation"; - } - protected: - size_t index; - ANTLR_USE_NAMESPACE(std)string text; - }; - - struct executeOperation { - ANTLR_USE_NAMESPACE(std)ostream& out; - executeOperation( ANTLR_USE_NAMESPACE(std)ostream& s ) : out(s) {} - void operator () ( RewriteOperation* t ) { - t->execute(out); - } - }; - - /// list of rewrite operations - typedef ANTLR_USE_NAMESPACE(std)list operation_list; - /// map program name to tuple - typedef ANTLR_USE_NAMESPACE(std)map program_map; - - class InsertBeforeOp : public RewriteOperation - { - public: - InsertBeforeOp( size_t index, const ANTLR_USE_NAMESPACE(std)string& text ) - : RewriteOperation(index, text) - { - } - virtual ~InsertBeforeOp() {} - virtual size_t execute( ANTLR_USE_NAMESPACE(std)ostream& out ) - { - out << text; - return index; - } - virtual const char* type() const { - return "InsertBeforeOp"; - } - }; - - class ReplaceOp : public RewriteOperation - { - public: - ReplaceOp(size_t from, size_t to, ANTLR_USE_NAMESPACE(std)string text) - : RewriteOperation(from,text) - , lastIndex(to) - { - } - virtual ~ReplaceOp() {} - virtual size_t execute( ANTLR_USE_NAMESPACE(std)ostream& out ) { - out << text; - return lastIndex+1; - } - virtual const char* type() const { - return "ReplaceOp"; - } - protected: - size_t lastIndex; - }; - - class DeleteOp : public ReplaceOp { - public: - DeleteOp(size_t from, size_t to) - : ReplaceOp(from,to,"") - { - } - virtual const char* type() const { - return "DeleteOp"; - } - }; - - TokenStreamRewriteEngine(TokenStream& upstream); - - TokenStreamRewriteEngine(TokenStream& upstream, size_t initialSize); - - RefToken nextToken( void ); - - void rollback(size_t instructionIndex) { - rollback(DEFAULT_PROGRAM_NAME, instructionIndex); - } - - /** Rollback the instruction stream for a program so that - * the indicated instruction (via instructionIndex) is no - * longer in the stream. UNTESTED! - */ - void rollback(const ANTLR_USE_NAMESPACE(std)string& programName, - size_t instructionIndex ); - - void deleteProgram() { - deleteProgram(DEFAULT_PROGRAM_NAME); - } - - /** Reset the program so that no instructions exist */ - void deleteProgram(const ANTLR_USE_NAMESPACE(std)string& programName) { - rollback(programName, MIN_TOKEN_INDEX); - } - - void insertAfter( RefTokenWithIndex t, - const ANTLR_USE_NAMESPACE(std)string& text ) - { - insertAfter(DEFAULT_PROGRAM_NAME, t, text); - } - - void insertAfter(size_t index, const ANTLR_USE_NAMESPACE(std)string& text) { - insertAfter(DEFAULT_PROGRAM_NAME, index, text); - } - - void insertAfter( const ANTLR_USE_NAMESPACE(std)string& programName, - RefTokenWithIndex t, - const ANTLR_USE_NAMESPACE(std)string& text ) - { - insertAfter(programName, t->getIndex(), text); - } - - void insertAfter( const ANTLR_USE_NAMESPACE(std)string& programName, - size_t index, - const ANTLR_USE_NAMESPACE(std)string& text ) - { - // to insert after, just insert before next index (even if past end) - insertBefore(programName,index+1, text); - } - - void insertBefore( RefTokenWithIndex t, - const ANTLR_USE_NAMESPACE(std)string& text ) - { - // std::cout << "insertBefore index " << t->getIndex() << " " << text << std::endl; - insertBefore(DEFAULT_PROGRAM_NAME, t, text); - } - - void insertBefore(size_t index, const ANTLR_USE_NAMESPACE(std)string& text) { - insertBefore(DEFAULT_PROGRAM_NAME, index, text); - } - - void insertBefore( const ANTLR_USE_NAMESPACE(std)string& programName, - RefTokenWithIndex t, - const ANTLR_USE_NAMESPACE(std)string& text ) - { - insertBefore(programName, t->getIndex(), text); - } - - void insertBefore( const ANTLR_USE_NAMESPACE(std)string& programName, - size_t index, - const ANTLR_USE_NAMESPACE(std)string& text ) - { - addToSortedRewriteList(programName, new InsertBeforeOp(index,text)); - } - - void replace(size_t index, const ANTLR_USE_NAMESPACE(std)string& text) - { - replace(DEFAULT_PROGRAM_NAME, index, index, text); - } - - void replace( size_t from, size_t to, - const ANTLR_USE_NAMESPACE(std)string& text) - { - replace(DEFAULT_PROGRAM_NAME, from, to, text); - } - - void replace( RefTokenWithIndex indexT, - const ANTLR_USE_NAMESPACE(std)string& text ) - { - replace(DEFAULT_PROGRAM_NAME, indexT->getIndex(), indexT->getIndex(), text); - } - - void replace( RefTokenWithIndex from, - RefTokenWithIndex to, - const ANTLR_USE_NAMESPACE(std)string& text ) - { - replace(DEFAULT_PROGRAM_NAME, from, to, text); - } - - void replace(const ANTLR_USE_NAMESPACE(std)string& programName, - size_t from, size_t to, - const ANTLR_USE_NAMESPACE(std)string& text ) - { - addToSortedRewriteList(programName,new ReplaceOp(from, to, text)); - } - - void replace( const ANTLR_USE_NAMESPACE(std)string& programName, - RefTokenWithIndex from, - RefTokenWithIndex to, - const ANTLR_USE_NAMESPACE(std)string& text ) - { - replace(programName, - from->getIndex(), - to->getIndex(), - text); - } - - void remove(size_t index) { - remove(DEFAULT_PROGRAM_NAME, index, index); - } - - void remove(size_t from, size_t to) { - remove(DEFAULT_PROGRAM_NAME, from, to); - } - - void remove(RefTokenWithIndex indexT) { - remove(DEFAULT_PROGRAM_NAME, indexT, indexT); - } - - void remove(RefTokenWithIndex from, RefTokenWithIndex to) { - remove(DEFAULT_PROGRAM_NAME, from, to); - } - - void remove( const ANTLR_USE_NAMESPACE(std)string& programName, - size_t from, size_t to) - { - replace(programName,from,to,""); - } - - void remove( const ANTLR_USE_NAMESPACE(std)string& programName, - RefTokenWithIndex from, RefTokenWithIndex to ) - { - replace(programName,from,to,""); - } - - void discard(int ttype) { - discardMask.add(ttype); - } - - RefToken getToken( size_t i ) - { - return RefToken(tokens.at(i)); - } - - size_t getTokenStreamSize() const { - return tokens.size(); - } - - void originalToStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const { - ANTLR_USE_NAMESPACE(std)for_each( tokens.begin(), tokens.end(), tokenToStream(out) ); - } - - void originalToStream( ANTLR_USE_NAMESPACE(std)ostream& out, - size_t start, size_t end ) const; - - void toStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const { - toStream( out, MIN_TOKEN_INDEX, getTokenStreamSize()); - } - - void toStream( ANTLR_USE_NAMESPACE(std)ostream& out, - const ANTLR_USE_NAMESPACE(std)string& programName ) const - { - toStream( out, programName, MIN_TOKEN_INDEX, getTokenStreamSize()); - } - - void toStream( ANTLR_USE_NAMESPACE(std)ostream& out, - size_t start, size_t end ) const - { - toStream(out, DEFAULT_PROGRAM_NAME, start, end); - } - - void toStream( ANTLR_USE_NAMESPACE(std)ostream& out, - const ANTLR_USE_NAMESPACE(std)string& programName, - size_t firstToken, size_t lastToken ) const; - - void toDebugStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const { - toDebugStream( out, MIN_TOKEN_INDEX, getTokenStreamSize()); - } - - void toDebugStream( ANTLR_USE_NAMESPACE(std)ostream& out, - size_t start, size_t end ) const; - - size_t getLastRewriteTokenIndex() const { - return getLastRewriteTokenIndex(DEFAULT_PROGRAM_NAME); - } - - /** Return the last index for the program named programName - * return 0 if the program does not exist or the program is empty. - * (Note this is different from the java implementation that returns -1) - */ - size_t getLastRewriteTokenIndex(const ANTLR_USE_NAMESPACE(std)string& programName) const { - program_map::const_iterator rewrites = programs.find(programName); - - if( rewrites == programs.end() ) - return 0; - - const operation_list& prog = rewrites->second; - if( !prog.empty() ) - { - operation_list::const_iterator last = prog.end(); - --last; - return (*last)->getIndex(); - } - return 0; - } - -protected: - /** If op.index > lastRewriteTokenIndexes, just add to the end. - * Otherwise, do linear */ - void addToSortedRewriteList(RewriteOperation* op) { - addToSortedRewriteList(DEFAULT_PROGRAM_NAME, op); - } - - void addToSortedRewriteList( const ANTLR_USE_NAMESPACE(std)string& programName, - RewriteOperation* op ); - -protected: - /** Who do we suck tokens from? */ - TokenStream& stream; - /** track index of tokens */ - size_t index; - - /** Track the incoming list of tokens */ - token_list tokens; - - /** You may have multiple, named streams of rewrite operations. - * I'm calling these things "programs." - * Maps String (name) -> rewrite (List) - */ - program_map programs; - - /** Which (whitespace) token(s) to throw out */ - BitSet discardMask; -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif diff --git a/libs/antlr-2.7.7/antlr/TokenStreamSelector.hpp b/libs/antlr-2.7.7/antlr/TokenStreamSelector.hpp deleted file mode 100644 index 4d4dd577b..000000000 --- a/libs/antlr-2.7.7/antlr/TokenStreamSelector.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef INC_TokenStreamSelector_hpp__ -#define INC_TokenStreamSelector_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/TokenStreamSelector.hpp#2 $ - */ - -#include -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** A token stream MUX (multiplexor) knows about n token streams - * and can multiplex them onto the same channel for use by token - * stream consumer like a parser. This is a way to have multiple - * lexers break up the same input stream for a single parser. - * Or, you can have multiple instances of the same lexer handle - * multiple input streams; this works great for includes. - */ -class ANTLR_API TokenStreamSelector : public TokenStream { -protected: - /** The set of inputs to the MUX */ -#ifdef OS_NO_ALLOCATOR - typedef ANTLR_USE_NAMESPACE(std)less lessp; - typedef ANTLR_USE_NAMESPACE(std)map inputStreamNames_coll; -#else - typedef ANTLR_USE_NAMESPACE(std)map inputStreamNames_coll; -#endif - inputStreamNames_coll inputStreamNames; - - /** The currently-selected token stream input */ - TokenStream* input; - - /** Used to track stack of input streams */ -#ifdef OS_NO_ALLOCATOR - typedef ANTLR_USE_NAMESPACE(std)stack > streamStack_coll; -#else - typedef ANTLR_USE_NAMESPACE(std)stack streamStack_coll; -#endif - streamStack_coll streamStack; - -public: - TokenStreamSelector(); - ~TokenStreamSelector(); - - void addInputStream(TokenStream* stream, const ANTLR_USE_NAMESPACE(std)string& key); - - /// Return the stream from which tokens are being pulled at the moment. - TokenStream* getCurrentStream() const; - - TokenStream* getStream(const ANTLR_USE_NAMESPACE(std)string& sname) const; - - RefToken nextToken(); - - TokenStream* pop(); - - void push(TokenStream* stream); - - void push(const ANTLR_USE_NAMESPACE(std)string& sname); - - /** Abort recognition of current Token and try again. - * A stream can push a new stream (for include files - * for example, and then retry(), which will cause - * the current stream to abort back to this.nextToken(). - * this.nextToken() then asks for a token from the - * current stream, which is the new "substream." - */ - void retry(); - - /** Set the stream without pushing old stream */ - void select(TokenStream* stream); - - void select(const ANTLR_USE_NAMESPACE(std)string& sname); -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_TokenStreamSelector_hpp__ diff --git a/libs/antlr-2.7.7/antlr/TokenWithIndex.hpp b/libs/antlr-2.7.7/antlr/TokenWithIndex.hpp deleted file mode 100644 index e4a3e37e8..000000000 --- a/libs/antlr-2.7.7/antlr/TokenWithIndex.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef INC_TokenWithIndex_hpp__ -#define INC_TokenWithIndex_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id:$ - */ - -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class ANTLR_API TokenWithIndex : public ANTLR_USE_NAMESPACE(antlr)CommonToken { -public: - // static size_t count; - TokenWithIndex() : CommonToken(), index(0) - { - // std::cout << __PRETTY_FUNCTION__ << std::endl; - // count++; - } - TokenWithIndex(int t, const ANTLR_USE_NAMESPACE(std)string& txt) - : CommonToken(t,txt) - , index(0) - { - // std::cout << __PRETTY_FUNCTION__ << std::endl; - // count++; - } - TokenWithIndex(const ANTLR_USE_NAMESPACE(std)string& s) - : CommonToken(s) - , index(0) - { - // std::cout << __PRETTY_FUNCTION__ << std::endl; - // count++; - } - ~TokenWithIndex() - { - // count--; - } - void setIndex( size_t idx ) - { - index = idx; - } - size_t getIndex( void ) const - { - return index; - } - - ANTLR_USE_NAMESPACE(std)string toString() const - { - return ANTLR_USE_NAMESPACE(std)string("[")+ - index+ - ":\""+ - getText()+"\",<"+ - getType()+">,line="+ - getLine()+",column="+ - getColumn()+"]"; - } - - static RefToken factory() - { - return RefToken(new TokenWithIndex()); - } - -protected: - size_t index; - -private: - TokenWithIndex(const TokenWithIndex&); - const TokenWithIndex& operator=(const TokenWithIndex&); -}; - -typedef TokenRefCount RefTokenWithIndex; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_CommonToken_hpp__ diff --git a/libs/antlr-2.7.7/antlr/TreeParser.hpp b/libs/antlr-2.7.7/antlr/TreeParser.hpp deleted file mode 100644 index b7dc54867..000000000 --- a/libs/antlr-2.7.7/antlr/TreeParser.hpp +++ /dev/null @@ -1,155 +0,0 @@ -#ifndef INC_TreeParser_hpp__ -#define INC_TreeParser_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/TreeParser.hpp#2 $ - */ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -class ANTLR_API TreeParser { -public: - TreeParser() - : astFactory(0) - , inputState(new TreeParserInputState()) - , traceDepth(0) - { - } - - TreeParser(const TreeParserSharedInputState& state) - : astFactory(0) - , inputState(state) - , traceDepth(0) - { - } - - virtual ~TreeParser() - { - } - - /// Get the AST return value squirreled away in the parser - virtual RefAST getAST() = 0; - - /** Make sure current lookahead symbol matches the given set - * Throw an exception upon mismatch, which is caught by either the - * error handler or by a syntactic predicate. - */ - virtual void match(RefAST t, const BitSet& b) - { - if ( !t || t==ASTNULL || !b.member(t->getType()) ) - throw MismatchedTokenException( getTokenNames(), getNumTokens(), - t, b, false ); - } - - /** Specify the AST factory to be used during tree building. (Compulsory) - * Setting the factory is compulsory (if you intend to modify - * the tree in the treeparser). The AST Factory is shared between - * parser (who builds the initial AST) and treeparser. - * @see Parser::getASTFactory() - */ - virtual void setASTFactory(ASTFactory* factory) - { - astFactory = factory; - } - /// Return pointer to ASTFactory - virtual ASTFactory* getASTFactory() const - { - return astFactory; - } - /// Get the name for token 'num' - virtual const char* getTokenName(int num) const = 0; - /// Return the number of tokens defined - virtual int getNumTokens() const = 0; - /// Return an array of getNumTokens() token names - virtual const char* const* getTokenNames() const = 0; - - /// Parser error-reporting function can be overridden in subclass - virtual void reportError(const RecognitionException& ex); - /// Parser error-reporting function can be overridden in subclass - virtual void reportError(const ANTLR_USE_NAMESPACE(std)string& s); - /// Parser warning-reporting function can be overridden in subclass - virtual void reportWarning(const ANTLR_USE_NAMESPACE(std)string& s); - - /// These are used during when traceTreeParser commandline option is passed. - virtual void traceIndent(); - virtual void traceIn(const char* rname, RefAST t); - virtual void traceOut(const char* rname, RefAST t); - - /** The AST Null object; the parsing cursor is set to this when - * it is found to be null. This way, we can test the - * token type of a node without having to have tests for 0 - * everywhere. - */ - static RefAST ASTNULL; - -protected: - virtual void match(RefAST t, int ttype) - { - if (!t || t == ASTNULL || t->getType() != ttype ) - throw MismatchedTokenException( getTokenNames(), getNumTokens(), - t, ttype, false ); - } - - virtual void matchNot(RefAST t, int ttype) - { - if ( !t || t == ASTNULL || t->getType() == ttype ) - throw MismatchedTokenException( getTokenNames(), getNumTokens(), - t, ttype, true ); - } - - /** AST support code; parser and treeparser delegate to this object */ - ASTFactory* astFactory; - - /// The input state of this tree parser. - TreeParserSharedInputState inputState; - - /** Used to keep track of indent depth with -traceTreeParser */ - int traceDepth; - - /** Utility class which allows tracing to work even when exceptions are - * thrown. - */ - class Tracer { - private: - TreeParser* parser; - const char* text; - RefAST tree; - public: - Tracer(TreeParser* p, const char* t, RefAST a) - : parser(p), text(t), tree(a) - { - parser->traceIn(text,tree); - } - ~Tracer() - { - parser->traceOut(text,tree); - } - private: - Tracer(const Tracer&); // undefined - const Tracer& operator=(const Tracer&); // undefined - }; - -private: - // no copying of treeparser instantiations... - TreeParser(const TreeParser& other); - TreeParser& operator=(const TreeParser& other); -}; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_TreeParser_hpp__ diff --git a/libs/antlr-2.7.7/antlr/TreeParserSharedInputState.hpp b/libs/antlr-2.7.7/antlr/TreeParserSharedInputState.hpp deleted file mode 100644 index 5e7c4c283..000000000 --- a/libs/antlr-2.7.7/antlr/TreeParserSharedInputState.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef INC_TreeParserSharedInputState_hpp__ -#define INC_TreeParserSharedInputState_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/TreeParserSharedInputState.hpp#2 $ - */ - -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** This object contains the data associated with an - * input AST. Multiple parsers - * share a single TreeParserSharedInputState to parse - * the same tree or to have the parser walk multiple - * trees. - */ -class ANTLR_API TreeParserInputState { -public: - TreeParserInputState() : guessing(0) {} - virtual ~TreeParserInputState() {} - -public: - /** Are we guessing (guessing>0)? */ - int guessing; //= 0; - -private: - // we don't want these: - TreeParserInputState(const TreeParserInputState&); - TreeParserInputState& operator=(const TreeParserInputState&); -}; - -typedef RefCount TreeParserSharedInputState; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -#endif //INC_TreeParserSharedInputState_hpp__ diff --git a/libs/antlr-2.7.7/antlr/config.hpp b/libs/antlr-2.7.7/antlr/config.hpp deleted file mode 100644 index e33695093..000000000 --- a/libs/antlr-2.7.7/antlr/config.hpp +++ /dev/null @@ -1,290 +0,0 @@ -#ifndef INC_config_hpp__ -#define INC_config_hpp__ - -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/antlr/config.hpp#2 $ - */ - -/* - * Just a simple configuration file to differentiate between the - * various compilers used and reconfigure stuff for any oddities of the - * compiler in question. - * - * These are the defaults. Per compiler these are amended. - */ -#define ANTLR_USE_NAMESPACE(_x_) _x_:: -#define ANTLR_USING_NAMESPACE(_x_) using namespace _x_; -#define ANTLR_CXX_SUPPORTS_NAMESPACE 1 -#define ANTLR_C_USING(_x_) -#define ANTLR_API -#ifndef CUSTOM_API -# define CUSTOM_API -#endif -#define ANTLR_IOS_BASE ios_base -/** define if cctype functions/macros need a std:: prefix. A lot of compilers - * define these as macros, in which case something barfs. - */ -#define ANTLR_CCTYPE_NEEDS_STD - -/// Define if C++ compiler supports std::uncaught_exception -#define ANTLR_CXX_SUPPORTS_UNCAUGHT_EXCEPTION - -#define ANTLR_ATOI_IN_STD - -/******************************************************************************/ -/*{{{ Microsoft Visual C++ */ -// NOTE: If you provide patches for a specific MSVC version guard them for -// the specific version!!!! -// _MSC_VER == 1100 for Microsoft Visual C++ 5.0 -// _MSC_VER == 1200 for Microsoft Visual C++ 6.0 -// _MSC_VER == 1300 for Microsoft Visual C++ 7.0 -#if defined(_MSC_VER) - -# if _MSC_VER < 1300 -# define NOMINMAX -# pragma warning(disable : 4786) -# define min _cpp_min -# endif - -// This warning really gets on my nerves. -// It's the one about symbol longer than 256 chars, and it happens -// all the time with STL. -# pragma warning( disable : 4786 4231 ) -// this shuts up some DLL interface warnings for STL -# pragma warning( disable : 4251 ) - -# ifdef ANTLR_CXX_USE_STLPORT -# undef ANTLR_CXX_SUPPORTS_UNCAUGHT_EXCEPTION -# endif - -# if ( _MSC_VER < 1300 ) && ( defined(ANTLR_EXPORTS) || defined(ANTLR_IMPORTS) ) -# error "DLL Build not supported on these MSVC versions." -// see comment in lib/cpp/src/dll.cpp -# endif - -// For the DLL support originally contributed by Stephen Naughton -// If you are building statically leave ANTLR_EXPORTS/ANTLR_IMPORTS undefined -// If you are building the DLL define ANTLR_EXPORTS -// If you are compiling code to be used with the DLL define ANTLR_IMPORTS -# ifdef ANTLR_EXPORTS -# undef ANTLR_API -# define ANTLR_API __declspec(dllexport) -# endif - -# ifdef ANTLR_IMPORTS -# undef ANTLR_API -# define ANTLR_API __declspec(dllimport) -# endif - -# if ( _MSC_VER < 1200 ) -// supposedly only for MSVC5 and before... -// Using vector requires operator<(X,X) to be defined -# define NEEDS_OPERATOR_LESS_THAN -# endif - -// VC6 -# if ( _MSC_VER == 1200 ) -# undef ANTLR_ATOI_IN_STD -# endif - -# if ( _MSC_VER < 1310 ) -// Supposedly only for MSVC7 and before... -// Not allowed to put 'static const int XXX=20;' in a class definition -# define NO_STATIC_CONSTS -# define NO_TEMPLATE_PARTS -# endif - -// No strcasecmp in the C library (so use stricmp instead) -// - Anyone know which is in which standard? -# define NO_STRCASECMP -# undef ANTLR_CCTYPE_NEEDS_STD -# define NO_STATIC_CONSTS -#endif // End of Microsoft Visual C++ - -/*}}}*/ -/******************************************************************************/ -/*{{{ SunPro Compiler (Using OBJECTSPACE STL) - *****************************************************************************/ -#ifdef __SUNPRO_CC - -# if (__SUNPRO_CC >= 0x500) - -# define NEEDS_OPERATOR_LESS_THAN -# define NO_TEMPLATE_PARTS - -# else - -# undef namespace -# define namespace - -# if (__SUNPRO_CC == 0x420) - -/* This code is specif to SunWspro Compiler 4.2, and will compile with - the objectspace 2.1 toolkit for Solaris2.6 */ -# define HAS_NOT_CASSERT_H -# define HAS_NOT_CSTRING_H -# define HAS_NOT_CCTYPE_H -# define HAS_NOT_CSTDIO_H -# define HAS_OSTREAM_H - -/* #define OS_SOLARIS_2_6 - #define OS_NO_WSTRING - #define OS_NO_ALLOCATORS - #define OS_MULTI_THREADED - #define OS_SOLARIS_NATIVE - #define OS_REALTIME - #define __OSVERSION__=5 - #define SVR4 - */ - -// ObjectSpace + some specific templates constructions with stl. -/* #define OS_NO_ALLOCATOR */ - -// This great compiler does not have the namespace feature. -# undef ANTLR_USE_NAMESPACE -# define ANTLR_USE_NAMESPACE(_x_) -# undef ANTLR_USING_NAMESPACE -# define ANTLR_USING_NAMESPACE(_x_) -# undef ANTLR_CXX_SUPPORTS_NAMESPACE -# endif // End __SUNPRO_CC == 0x420 - -# undef explicit -# define explicit - -# define exception os_exception -# define bad_exception os_bad_exception - -// Not allowed to put 'static const int XXX=20;' in a class definition -# define NO_STATIC_CONSTS -// Using vector requires operator<(X,X) to be defined -# define NEEDS_OPERATOR_LESS_THAN - -# endif - -# undef ANTLR_CCTYPE_NEEDS_STD - -#endif // end __SUNPRO_CC -/*}}}*/ -/*****************************************************************************/ -/*{{{ Inprise C++ Builder 3.0 - *****************************************************************************/ -#ifdef __BCPLUSPLUS__ -# define NO_TEMPLATE_PARTS -# define NO_STRCASECMP -# undef ANTLR_CCTYPE_NEEDS_STD -#endif // End of C++ Builder 3.0 -/*}}}*/ -/*****************************************************************************/ -/*{{{ IBM VisualAge C++ ( which includes the Dinkumware C++ Library ) - *****************************************************************************/ -#ifdef __IBMCPP__ - -// No strcasecmp in the C library (so use stricmp instead) -// - Anyone know which is in which standard? -#if (defined(_AIX) && (__IBMCPP__ >= 600)) -# define NO_STATIC_CONSTS -#else -# define NO_STRCASECMP -# undef ANTLR_CCTYPE_NEEDS_STD -#endif - -#endif // end IBM VisualAge C++ -/*}}}*/ -/*****************************************************************************/ -/*{{{ Metrowerks Codewarrior - *****************************************************************************/ -#ifdef __MWERKS__ -# if (__MWERKS__ <= 0x2201) -# define NO_TEMPLATE_PARTS -# endif - -// CW 6.0 and 7.0 still do not have it. -# define ANTLR_REALLY_NO_STRCASECMP - -# undef ANTLR_C_USING -# define ANTLR_C_USING(_x_) using std:: ## _x_; - -# define ANTLR_CCTYPE_NEEDS_STD -# undef ANTLR_CXX_SUPPORTS_UNCAUGHT_EXCEPTION - -#endif // End of Metrowerks Codewarrior -/*}}}*/ -/*****************************************************************************/ -/*{{{ SGI Irix 6.5.10 MIPSPro compiler - *****************************************************************************/ -// (contributed by Anna Winkler) -// Note: you can't compile ANTLR with the MIPSPro compiler on -// anything < 6.5.10 because SGI just fixed a big bug dealing with -// namespaces in that release. -#ifdef __sgi -# define HAS_NOT_CCTYPE_H -# define HAS_NOT_CSTRING_H -# define HAS_NOT_CSTDIO_H -# undef ANTLR_CCTYPE_NEEDS_STD -#endif // End IRIX MIPSPro -/*}}}*/ -/*****************************************************************************/ -/*{{{ G++ in various incarnations - *****************************************************************************/ -// With the gcc-2.95 and 3.0 being in the near future we should start handling -// incompatabilities between the various libstdc++'s. -#if defined(__GNUC__) || defined(__GNUG__) -// gcc 2 branch.. -# if (__GNUC__ == 2 ) -# if (__GNUC_MINOR__ <= 8 ) -# undef ANTLR_USE_NAMESPACE -# define ANTLR_USE_NAMESPACE(_x_) -# undef ANTLR_USING_NAMESPACE -# define ANTLR_USING_NAMESPACE(_x_) -# undef ANTLR_CXX_SUPPORTS_NAMESPACE -# endif -# if (__GNUC_MINOR__ > 8 && __GNUC_MINOR__ <= 95 ) -# undef ANTLR_IOS_BASE -# define ANTLR_IOS_BASE ios -# undef ANTLR_CCTYPE_NEEDS_STD -// compiling with -ansi ? -# ifdef __STRICT_ANSI__ -# undef ANTLR_REALLY_NO_STRCASECMP -# define ANTLR_REALLY_NO_STRCASECMP -# endif -# else -// experimental .96 .97 branches.. -# undef ANTLR_CCTYPE_NEEDS_STD -# endif -# endif -#endif // ! __GNUC__ -/*}}}*/ -/*****************************************************************************/ -/*{{{ Digital CXX (Tru64) - *****************************************************************************/ -#ifdef __DECCXX -#define __USE_STD_IOSTREAM -#endif -/*}}}*/ -/*****************************************************************************/ -#ifdef __BORLANDC__ -# if __BORLANDC__ >= 560 -# include -# include -# define ANTLR_CCTYPE_NEEDS_STD -# else -# error "sorry, compiler is too old - consider an update." -# endif -#endif - -// Redefine these for backwards compatability.. -#undef ANTLR_BEGIN_NAMESPACE -#undef ANTLR_END_NAMESPACE - -#if ANTLR_CXX_SUPPORTS_NAMESPACE == 1 -# define ANTLR_BEGIN_NAMESPACE(_x_) namespace _x_ { -# define ANTLR_END_NAMESPACE } -#else -# define ANTLR_BEGIN_NAMESPACE(_x_) -# define ANTLR_END_NAMESPACE -#endif - -#endif //INC_config_hpp__ diff --git a/libs/antlr-2.7.7/doxygen.cfg b/libs/antlr-2.7.7/doxygen.cfg deleted file mode 100644 index c88da52c6..000000000 --- a/libs/antlr-2.7.7/doxygen.cfg +++ /dev/null @@ -1,101 +0,0 @@ -# -# Doxygen config file for ANTLR's C++ support libraries. -# -# Thanks to Bill Zheng for parts of this. -# -PROJECT_NAME = "ANTLR Support Libraries 2.7.1+" -# Input files: -INPUT = antlr src -RECURSIVE = YES -FILE_PATTERNS = *.cpp *.h *.hpp -JAVADOC_AUTOBRIEF = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. -MACRO_EXPANSION = YES - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. -INCLUDE_PATH = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. -PREDEFINED = "ANTLR_USE_NAMESPACE(_x_)=_x_::" \ - "ANTLR_USING_NAMESPACE(_x_)=using namespace _x_;" \ - "ANTLR_C_USING(_x_)=" \ - "ANTLR_API=" - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED tag. -EXPAND_ONLY_PREDEF = YES - -# Output options -OUTPUT_DIRECTORY = gen_doc -PAPER_TYPE = a4wide -#PAPER_TYPE = a4 -TAB_SIZE = 3 -CASE_SENSE_NAMES = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. -REPEAT_BRIEF = YES - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. -INTERNAL_DOCS = NO - -# if the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# reimplements. -INHERIT_DOCS = YES - -# if the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. -INLINE_INFO = YES - -# Dot and friends... -HAVE_DOT = YES -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -EXTRACT_ALL = YES -EXTRACT_STATIC = YES -EXTRACT_PRIVATE = YES -# HTML output and friends... -GENERATE_HTML = YES -# Tree view gives too much trouble with various browsers. -GENERATE_TREEVIEW = NO -# Latex output and friends... -GENERATE_LATEX = NO -PDF_HYPERLINKS = YES -GENERATE_MAN = NO -GENERATE_RTF = NO -# Control of convenience stuff -GENERATE_TODOLIST = YES -# Control over warnings etc. Unset EXTRACT_ALL to get this to work -WARN_IF_UNDOCUMENTED = YES -WARNINGS = YES -QUIET = YES diff --git a/libs/antlr-2.7.7/src/ANTLRUtil.cpp b/libs/antlr-2.7.7/src/ANTLRUtil.cpp deleted file mode 100644 index 489ac5907..000000000 --- a/libs/antlr-2.7.7/src/ANTLRUtil.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id:$ - */ - -#include -#include - -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** Eat whitespace from the input stream - * @param is the stream to read from - */ -ANTLR_USE_NAMESPACE(std)istream& eatwhite( ANTLR_USE_NAMESPACE(std)istream& is ) -{ - char c; - while( is.get(c) ) - { -#ifdef ANTLR_CCTYPE_NEEDS_STD - if( !ANTLR_USE_NAMESPACE(std)isspace(c) ) -#else - if( !isspace(c) ) -#endif - { - is.putback(c); - break; - } - } - return is; -} - -/** Read a string enclosed by '"' from a stream. Also handles escaping of \". - * Skips leading whitespace. - * @param in the istream to read from. - * @returns the string read from file exclusive the '"' - * @throws IOException if string is badly formatted - */ -ANTLR_USE_NAMESPACE(std)string read_string( ANTLR_USE_NAMESPACE(std)istream& in ) -{ - char ch; - ANTLR_USE_NAMESPACE(std)string ret(""); - // States for a simple state machine... - enum { START, READING, ESCAPE, FINISHED }; - int state = START; - - eatwhite(in); - - while( state != FINISHED && in.get(ch) ) - { - switch( state ) - { - case START: - // start state: check wether starting with " then switch to READING - if( ch != '"' ) - throw IOException("string must start with '\"'"); - state = READING; - continue; - case READING: - // reading state: look out for escape sequences and closing " - if( ch == '\\' ) // got escape sequence - { - state = ESCAPE; - continue; - } - if( ch == '"' ) // close quote -> stop - { - state = FINISHED; - continue; - } - ret += ch; // else append... - continue; - case ESCAPE: - switch(ch) - { - case '\\': - ret += ch; - state = READING; - continue; - case '"': - ret += ch; - state = READING; - continue; - case '0': - ret += '\0'; - state = READING; - continue; - default: // unrecognized escape is not mapped - ret += '\\'; - ret += ch; - state = READING; - continue; - } - } - } - if( state != FINISHED ) - throw IOException("badly formatted string: "+ret); - - return ret; -} - -/* Read a ([A-Z][0-9][a-z]_)* kindoff thing. Skips leading whitespace. - * @param in the istream to read from. - */ -ANTLR_USE_NAMESPACE(std)string read_identifier( ANTLR_USE_NAMESPACE(std)istream& in ) -{ - char ch; - ANTLR_USE_NAMESPACE(std)string ret(""); - - eatwhite(in); - - while( in.get(ch) ) - { -#ifdef ANTLR_CCTYPE_NEEDS_STD - if( ANTLR_USE_NAMESPACE(std)isupper(ch) || - ANTLR_USE_NAMESPACE(std)islower(ch) || - ANTLR_USE_NAMESPACE(std)isdigit(ch) || - ch == '_' ) -#else - if( isupper(ch) || islower(ch) || isdigit(ch) || ch == '_' ) -#endif - ret += ch; - else - { - in.putback(ch); - break; - } - } - return ret; -} - -/** Read a attribute="value" thing. Leading whitespace is skipped. - * Between attribute and '=' no whitespace is allowed. After the '=' it is - * permitted. - * @param in the istream to read from. - * @param attribute string the attribute name is put in - * @param value string the value of the attribute is put in - * @throws IOException if something is fishy. E.g. malformed quoting - * or missing '=' - */ -void read_AttributeNValue( ANTLR_USE_NAMESPACE(std)istream& in, - ANTLR_USE_NAMESPACE(std)string& attribute, - ANTLR_USE_NAMESPACE(std)string& value ) -{ - attribute = read_identifier(in); - - char ch; - if( in.get(ch) && ch == '=' ) - value = read_string(in); - else - throw IOException("invalid attribute=value thing "+attribute); -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/ASTFactory.cpp b/libs/antlr-2.7.7/src/ASTFactory.cpp deleted file mode 100644 index 29451a408..000000000 --- a/libs/antlr-2.7.7/src/ASTFactory.cpp +++ /dev/null @@ -1,504 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/ASTFactory.cpp#2 $ - */ - -#include "antlr/CommonAST.hpp" -#include "antlr/ANTLRException.hpp" -#include "antlr/IOException.hpp" -#include "antlr/ASTFactory.hpp" -#include "antlr/ANTLRUtil.hpp" - -#include -#include - -using namespace std; - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** AST Support code shared by TreeParser and Parser. - * We use delegation to share code (and have only one - * bit of code to maintain) rather than subclassing - * or superclassing (forces AST support code to be - * loaded even when you don't want to do AST stuff). - * - * This class collects all factories of AST types used inside the code. - * New AST node types are registered with the registerFactory method. - * On creation of an ASTFactory object a default AST node factory may be - * specified. - * - * When registering types gaps between different types are filled with entries - * for the default factory. - */ - -/// Initialize factory -ASTFactory::ASTFactory() -: default_factory_descriptor(ANTLR_USE_NAMESPACE(std)make_pair(CommonAST::TYPE_NAME,&CommonAST::factory)) -{ - nodeFactories.resize( Token::MIN_USER_TYPE, &default_factory_descriptor ); -} - -/** Initialize factory with a non default node type. - * factory_node_name should be the name of the AST node type the factory - * generates. (should exist during the existance of this ASTFactory instance) - */ -ASTFactory::ASTFactory( const char* factory_node_name, factory_type fact ) -: default_factory_descriptor(ANTLR_USE_NAMESPACE(std)make_pair(factory_node_name, fact)) -{ - nodeFactories.resize( Token::MIN_USER_TYPE, &default_factory_descriptor ); -} - -/// Delete ASTFactory -ASTFactory::~ASTFactory() -{ - factory_descriptor_list::iterator i = nodeFactories.begin(); - - while( i != nodeFactories.end() ) - { - if( *i != &default_factory_descriptor ) - delete *i; - i++; - } -} - -/// Register a factory for a given AST type -void ASTFactory::registerFactory( int type, const char* ast_name, factory_type factory ) -{ - // check validity of arguments... - if( type < Token::MIN_USER_TYPE ) - throw ANTLRException("Internal parser error invalid type passed to RegisterFactory"); - if( factory == 0 ) - throw ANTLRException("Internal parser error 0 factory passed to RegisterFactory"); - - // resize up to and including 'type' and initalize any gaps to default - // factory. - if( nodeFactories.size() < (static_cast(type)+1) ) - nodeFactories.resize( type+1, &default_factory_descriptor ); - - // And add new thing.. - nodeFactories[type] = new ANTLR_USE_NAMESPACE(std)pair( ast_name, factory ); -} - -void ASTFactory::setMaxNodeType( int type ) -{ - if( nodeFactories.size() < (static_cast(type)+1) ) - nodeFactories.resize( type+1, &default_factory_descriptor ); -} - -/** Create a new empty AST node; if the user did not specify - * an AST node type, then create a default one: CommonAST. - */ -RefAST ASTFactory::create() -{ - RefAST node = nodeFactories[0]->second(); - node->setType(Token::INVALID_TYPE); - return node; -} - -RefAST ASTFactory::create(int type) -{ - RefAST t = nodeFactories[type]->second(); - t->initialize(type,""); - return t; -} - -RefAST ASTFactory::create(int type, const ANTLR_USE_NAMESPACE(std)string& txt) -{ - RefAST t = nodeFactories[type]->second(); - t->initialize(type,txt); - return t; -} - -#ifdef ANTLR_SUPPORT_XML -RefAST ASTFactory::create(const ANTLR_USE_NAMESPACE(std)string& type_name, ANTLR_USE_NAMESPACE(std)istream& infile ) -{ - factory_descriptor_list::iterator fact = nodeFactories.begin(); - - while( fact != nodeFactories.end() ) - { - if( type_name == (*fact)->first ) - { - RefAST t = (*fact)->second(); - t->initialize(infile); - return t; - } - fact++; - } - - string error = "ASTFactory::create: Unknown AST type '" + type_name + "'"; - throw ANTLRException(error); -} -#endif - -/** Create a new empty AST node; if the user did not specify - * an AST node type, then create a default one: CommonAST. - */ -RefAST ASTFactory::create(RefAST tr) -{ - if (!tr) - return nullAST; - -// cout << "create(tr)" << endl; - - RefAST t = nodeFactories[tr->getType()]->second(); - t->initialize(tr); - return t; -} - -RefAST ASTFactory::create(RefToken tok) -{ -// cout << "create( tok="<< tok->getType() << ", " << tok->getText() << ")" << nodeFactories.size() << endl; - RefAST t = nodeFactories[tok->getType()]->second(); - t->initialize(tok); - return t; -} - -/** Add a child to the current AST */ -void ASTFactory::addASTChild(ASTPair& currentAST, RefAST child) -{ - if (child) - { - if (!currentAST.root) - { - // Make new child the current root - currentAST.root = child; - } - else - { - if (!currentAST.child) - { - // Add new child to current root - currentAST.root->setFirstChild(child); - } - else - { - currentAST.child->setNextSibling(child); - } - } - // Make new child the current child - currentAST.child = child; - currentAST.advanceChildToEnd(); - } -} - -/** Deep copy a single node. This function the new clone() methods in the AST - * interface. Returns nullAST if t is null. - */ -RefAST ASTFactory::dup(RefAST t) -{ - if( t ) - return t->clone(); - else - return RefAST(nullASTptr); -} - -/** Duplicate tree including siblings of root. */ -RefAST ASTFactory::dupList(RefAST t) -{ - RefAST result = dupTree(t); // if t == null, then result==null - RefAST nt = result; - - while( t ) - { // for each sibling of the root - t = t->getNextSibling(); - nt->setNextSibling(dupTree(t)); // dup each subtree, building new tree - nt = nt->getNextSibling(); - } - return result; -} - -/** Duplicate a tree, assuming this is a root node of a tree - * duplicate that node and what's below; ignore siblings of root node. - */ -RefAST ASTFactory::dupTree(RefAST t) -{ - RefAST result = dup(t); // make copy of root - // copy all children of root. - if( t ) - result->setFirstChild( dupList(t->getFirstChild()) ); - return result; -} - -/** Make a tree from a list of nodes. The first element in the - * array is the root. If the root is null, then the tree is - * a simple list not a tree. Handles null children nodes correctly. - * For example, make(a, b, null, c) yields tree (a b c). make(null,a,b) - * yields tree (nil a b). - */ -RefAST ASTFactory::make(ANTLR_USE_NAMESPACE(std)vector& nodes) -{ - if ( nodes.size() == 0 ) - return RefAST(nullASTptr); - - RefAST root = nodes[0]; - RefAST tail = RefAST(nullASTptr); - - if( root ) - root->setFirstChild(RefAST(nullASTptr)); // don't leave any old pointers set - - // link in children; - for( unsigned int i = 1; i < nodes.size(); i++ ) - { - if ( nodes[i] == 0 ) // ignore null nodes - continue; - - if ( root == 0 ) // Set the root and set it up for a flat list - root = tail = nodes[i]; - else if ( tail == 0 ) - { - root->setFirstChild(nodes[i]); - tail = root->getFirstChild(); - } - else - { - tail->setNextSibling(nodes[i]); - tail = tail->getNextSibling(); - } - - if( tail ) // RK: I cannot fathom why this missing check didn't bite anyone else... - { - // Chase tail to last sibling - while (tail->getNextSibling()) - tail = tail->getNextSibling(); - } - } - - return root; -} - -/** Make a tree from a list of nodes, where the nodes are contained - * in an ASTArray object - */ -RefAST ASTFactory::make(ASTArray* nodes) -{ - RefAST ret = make(nodes->array); - delete nodes; - return ret; -} - -/// Make an AST the root of current AST -void ASTFactory::makeASTRoot( ASTPair& currentAST, RefAST root ) -{ - if (root) - { - // Add the current root as a child of new root - root->addChild(currentAST.root); - // The new current child is the last sibling of the old root - currentAST.child = currentAST.root; - currentAST.advanceChildToEnd(); - // Set the new root - currentAST.root = root; - } -} - -void ASTFactory::setASTNodeFactory( const char* factory_node_name, - factory_type factory ) -{ - default_factory_descriptor.first = factory_node_name; - default_factory_descriptor.second = factory; -} - -#ifdef ANTLR_SUPPORT_XML -bool ASTFactory::checkCloseTag( ANTLR_USE_NAMESPACE(std)istream& in ) -{ - char ch; - - if( in.get(ch) ) - { - if( ch == '<' ) - { - char ch2; - if( in.get(ch2) ) - { - if( ch2 == '/' ) - { - in.putback(ch2); - in.putback(ch); - return true; - } - in.putback(ch2); - in.putback(ch); - return false; - } - } - in.putback(ch); - return false; - } - return false; -} - -void ASTFactory::loadChildren( ANTLR_USE_NAMESPACE(std)istream& infile, - RefAST current ) -{ - char ch; - - for(;;) // for all children of this node.... - { - eatwhite(infile); - - infile.get(ch); // '<' - if( ch != '<' ) - { - string error = "Invalid XML file... no '<' found ("; - error += ch + ")"; - throw IOException(error); - } - - infile.get(ch); // / or text.... - - if( ch == '/' ) // check for close tag... - { - string temp; - - // read until '>' and see if it matches the open tag... if not trouble - temp = read_identifier( infile ); - - if( strcmp(temp.c_str(), current->typeName() ) != 0 ) - { - string error = "Invalid XML file... close tag does not match start tag: "; - error += current->typeName(); - error += " closed by " + temp; - throw IOException(error); - } - - infile.get(ch); // must be a '>' - - if( ch != '>' ) - { - string error = "Invalid XML file... no '>' found ("; - error += ch + ")"; - throw IOException(error); - } - // close tag => exit loop - break; - } - - // put our 'look ahead' back where it came from - infile.putback(ch); - infile.putback('<'); - - // and recurse into the tree... - RefAST child = LoadAST(infile); - - current->addChild( child ); - } -} - -void ASTFactory::loadSiblings(ANTLR_USE_NAMESPACE(std)istream& infile, - RefAST current ) -{ - for(;;) - { - eatwhite(infile); - - if( infile.eof() ) - break; - - if( checkCloseTag(infile) ) - break; - - RefAST sibling = LoadAST(infile); - current->setNextSibling(sibling); - } -} - -RefAST ASTFactory::LoadAST( ANTLR_USE_NAMESPACE(std)istream& infile ) -{ - RefAST current = nullAST; - char ch; - - eatwhite(infile); - - if( !infile.get(ch) ) - return nullAST; - - if( ch != '<' ) - { - string error = "Invalid XML file... no '<' found ("; - error += ch + ")"; - throw IOException(error); - } - - string ast_type = read_identifier(infile); - - // create the ast of type 'ast_type' - current = create( ast_type, infile ); - if( current == nullAST ) - { - string error = "Unsuported AST type: " + ast_type; - throw IOException(error); - } - - eatwhite(infile); - - infile.get(ch); - - // now if we have a '/' here it's a single node. If it's a '>' we get - // a tree with children - - if( ch == '/' ) - { - infile.get(ch); // get the closing '>' - if( ch != '>' ) - { - string error = "Invalid XML file... no '>' found after '/' ("; - error += ch + ")"; - throw IOException(error); - } - - // get the rest on this level - loadSiblings( infile, current ); - - return current; - } - - // and finaly see if we got the close tag... - if( ch != '>' ) - { - string error = "Invalid XML file... no '>' found ("; - error += ch + ")"; - throw IOException(error); - } - - // handle the ones below this level.. - loadChildren( infile, current ); - - // load the rest on this level... - loadSiblings( infile, current ); - - return current; -} -#endif // ANTLR_SUPPORT_XML - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -/* Heterogeneous AST/XML-I/O ramblings... - * - * So there is some heterogeneous AST support.... - * basically in the code generators a new custom ast is generated without - * going throug the factory. It also expects the RefXAST to be defined. - * - * Is it maybe better to register all AST types with the ASTFactory class - * together with the respective factory methods. - * - * More and more I get the impression that hetero ast was a kindoff hack - * on top of ANTLR's normal AST system. - * - * The heteroast stuff will generate trouble for all astFactory.create( ... ) - * invocations. Most of this is handled via getASTCreateString methods in the - * codegenerator. At the moment getASTCreateString(GrammarAtom, String) has - * slightly to little info to do it's job (ok the hack that is in now - * works, but it's an ugly hack) - * - * An extra caveat is the 'nice' action.g thing. Which also judiciously calls - * getASTCreateString methods because it handles the #( ... ) syntax. - * And converts that to ASTFactory calls. - * - * - */ diff --git a/libs/antlr-2.7.7/src/ASTNULLType.cpp b/libs/antlr-2.7.7/src/ASTNULLType.cpp deleted file mode 100644 index 9e5426cb2..000000000 --- a/libs/antlr-2.7.7/src/ASTNULLType.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id:$ - */ - -#include "antlr/config.hpp" -#include "antlr/AST.hpp" -#include "antlr/ASTNULLType.hpp" - -#include - -ANTLR_USING_NAMESPACE(std) - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -RefAST ASTNULLType::clone( void ) const -{ - return RefAST(this); -} - -void ASTNULLType::addChild( RefAST ) -{ -} - -size_t ASTNULLType::getNumberOfChildren() const -{ - return 0; -} - -bool ASTNULLType::equals( RefAST ) const -{ - return false; -} - -bool ASTNULLType::equalsList( RefAST ) const -{ - return false; -} - -bool ASTNULLType::equalsListPartial( RefAST ) const -{ - return false; -} - -bool ASTNULLType::equalsTree( RefAST ) const -{ - return false; -} - -bool ASTNULLType::equalsTreePartial( RefAST ) const -{ - return false; -} - -vector ASTNULLType::findAll( RefAST ) -{ - return vector(); -} - -vector ASTNULLType::findAllPartial( RefAST ) -{ - return vector(); -} - -RefAST ASTNULLType::getFirstChild() const -{ - return this; -} - -RefAST ASTNULLType::getNextSibling() const -{ - return this; -} - -string ASTNULLType::getText() const -{ - return ""; -} - -int ASTNULLType::getType() const -{ - return Token::NULL_TREE_LOOKAHEAD; -} - -void ASTNULLType::initialize( int, const string& ) -{ -} - -void ASTNULLType::initialize( RefAST ) -{ -} - -void ASTNULLType::initialize( RefToken ) -{ -} - -#ifdef ANTLR_SUPPORT_XML -void ASTNULLType::initialize( istream& ) -{ -} -#endif - -void ASTNULLType::setFirstChild( RefAST ) -{ -} - -void ASTNULLType::setNextSibling( RefAST ) -{ -} - -void ASTNULLType::setText( const string& ) -{ -} - -void ASTNULLType::setType( int ) -{ -} - -string ASTNULLType::toString() const -{ - return getText(); -} - -string ASTNULLType::toStringList() const -{ - return getText(); -} - -string ASTNULLType::toStringTree() const -{ - return getText(); -} - -#ifdef ANTLR_SUPPORT_XML -bool ASTNULLType::attributesToStream( ostream& ) const -{ - return false; -} - -void ASTNULLType::toStream( ostream& out ) const -{ - out << "" << endl; -} -#endif - -const char* ASTNULLType::typeName( void ) const -{ - return "ASTNULLType"; -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/ASTRefCount.cpp b/libs/antlr-2.7.7/src/ASTRefCount.cpp deleted file mode 100644 index 340005bc7..000000000 --- a/libs/antlr-2.7.7/src/ASTRefCount.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/ASTRefCount.cpp#2 $ - */ -#include "antlr/ASTRefCount.hpp" -#include "antlr/AST.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -ASTRef::ASTRef(AST* p) -: ptr(p), count(1) -{ - if (p && !p->ref) - p->ref = this; -} - -ASTRef::~ASTRef() -{ - delete ptr; -} - -ASTRef* ASTRef::getRef(const AST* p) -{ - if (p) { - AST* pp = const_cast(p); - if (pp->ref) - return pp->ref->increment(); - else - return new ASTRef(pp); - } else - return 0; -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - diff --git a/libs/antlr-2.7.7/src/BaseAST.cpp b/libs/antlr-2.7.7/src/BaseAST.cpp deleted file mode 100644 index 397933b3e..000000000 --- a/libs/antlr-2.7.7/src/BaseAST.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/BaseAST.cpp#2 $ - */ - -#include "antlr/config.hpp" - -#include - -#include "antlr/AST.hpp" -#include "antlr/BaseAST.hpp" - -ANTLR_USING_NAMESPACE(std) -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -size_t BaseAST::getNumberOfChildren() const -{ - RefBaseAST t = this->down; - size_t n = 0; - if( t ) - { - n = 1; - while( t->right ) - { - t = t->right; - n++; - } - return n; - } - return n; -} - -void BaseAST::doWorkForFindAll( - ANTLR_USE_NAMESPACE(std)vector& v, - RefAST target,bool partialMatch) -{ - // Start walking sibling lists, looking for matches. - for (RefAST sibling=this; - sibling; - sibling=sibling->getNextSibling()) - { - if ( (partialMatch && sibling->equalsTreePartial(target)) || - (!partialMatch && sibling->equalsTree(target)) ) { - v.push_back(sibling); - } - // regardless of match or not, check any children for matches - if ( sibling->getFirstChild() ) { - RefBaseAST(sibling->getFirstChild())->doWorkForFindAll(v, target, partialMatch); - } - } -} - -/** Is t an exact structural and equals() match of this tree. The - * 'this' reference is considered the start of a sibling list. - */ -bool BaseAST::equalsList(RefAST t) const -{ - // the empty tree is not a match of any non-null tree. - if (!t) - return false; - - // Otherwise, start walking sibling lists. First mismatch, return false. - RefAST sibling=this; - for (;sibling && t; - sibling=sibling->getNextSibling(), t=t->getNextSibling()) { - // as a quick optimization, check roots first. - if (!sibling->equals(t)) - return false; - // if roots match, do full list match test on children. - if (sibling->getFirstChild()) { - if (!sibling->getFirstChild()->equalsList(t->getFirstChild())) - return false; - } - // sibling has no kids, make sure t doesn't either - else if (t->getFirstChild()) - return false; - } - - if (!sibling && !t) - return true; - - // one sibling list has more than the other - return false; -} - -/** Is 'sub' a subtree of this list? - * The siblings of the root are NOT ignored. - */ -bool BaseAST::equalsListPartial(RefAST sub) const -{ - // the empty tree is always a subset of any tree. - if (!sub) - return true; - - // Otherwise, start walking sibling lists. First mismatch, return false. - RefAST sibling=this; - for (;sibling && sub; - sibling=sibling->getNextSibling(), sub=sub->getNextSibling()) { - // as a quick optimization, check roots first. - if (!sibling->equals(sub)) - return false; - // if roots match, do partial list match test on children. - if (sibling->getFirstChild()) - if (!sibling->getFirstChild()->equalsListPartial(sub->getFirstChild())) - return false; - } - - if (!sibling && sub) - // nothing left to match in this tree, but subtree has more - return false; - - // either both are null or sibling has more, but subtree doesn't - return true; -} - -/** Is tree rooted at 'this' equal to 't'? The siblings - * of 'this' are ignored. - */ -bool BaseAST::equalsTree(RefAST t) const -{ - // check roots first - if (!equals(t)) - return false; - // if roots match, do full list match test on children. - if (getFirstChild()) { - if (!getFirstChild()->equalsList(t->getFirstChild())) - return false; - } - // sibling has no kids, make sure t doesn't either - else if (t->getFirstChild()) - return false; - - return true; -} - -/** Is 'sub' a subtree of the tree rooted at 'this'? The siblings - * of 'this' are ignored. - */ -bool BaseAST::equalsTreePartial(RefAST sub) const -{ - // the empty tree is always a subset of any tree. - if (!sub) - return true; - - // check roots first - if (!equals(sub)) - return false; - // if roots match, do full list partial match test on children. - if (getFirstChild()) - if (!getFirstChild()->equalsListPartial(sub->getFirstChild())) - return false; - - return true; -} - -/** Walk the tree looking for all exact subtree matches. Return - * an ASTEnumerator that lets the caller walk the list - * of subtree roots found herein. - */ -ANTLR_USE_NAMESPACE(std)vector BaseAST::findAll(RefAST target) -{ - ANTLR_USE_NAMESPACE(std)vector roots; - - // the empty tree cannot result in an enumeration - if (target) { - doWorkForFindAll(roots,target,false); // find all matches recursively - } - - return roots; -} - -/** Walk the tree looking for all subtrees. Return - * an ASTEnumerator that lets the caller walk the list - * of subtree roots found herein. - */ -ANTLR_USE_NAMESPACE(std)vector BaseAST::findAllPartial(RefAST target) -{ - ANTLR_USE_NAMESPACE(std)vector roots; - - // the empty tree cannot result in an enumeration - if (target) - doWorkForFindAll(roots,target,true); // find all matches recursively - - return roots; -} - -ANTLR_USE_NAMESPACE(std)string BaseAST::toStringList() const -{ - ANTLR_USE_NAMESPACE(std)string ts=""; - - if (getFirstChild()) - { - ts+=" ( "; - ts+=toString(); - ts+=getFirstChild()->toStringList(); - ts+=" )"; - } - else - { - ts+=" "; - ts+=toString(); - } - - if (getNextSibling()) - ts+=getNextSibling()->toStringList(); - - return ts; -} - -ANTLR_USE_NAMESPACE(std)string BaseAST::toStringTree() const -{ - ANTLR_USE_NAMESPACE(std)string ts = ""; - - if (getFirstChild()) - { - ts+=" ( "; - ts+=toString(); - ts+=getFirstChild()->toStringList(); - ts+=" )"; - } - else - { - ts+=" "; - ts+=toString(); - } - return ts; -} - -#ifdef ANTLR_SUPPORT_XML -/* This whole XML output stuff needs a little bit more thought - * I'd like to store extra XML data in the node. e.g. for custom ast's - * with for instance symboltable references. This - * should be more pluggable.. - * @returns boolean value indicating wether a closetag should be produced. - */ -bool BaseAST::attributesToStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const -{ - out << "text=\"" << this->getText() - << "\" type=\"" << this->getType() << "\""; - - return false; -} - -void BaseAST::toStream( ANTLR_USE_NAMESPACE(std)ostream& out ) const -{ - for( RefAST node = this; node != 0; node = node->getNextSibling() ) - { - out << "<" << this->typeName() << " "; - - // Write out attributes and if there is extra data... - bool need_close_tag = node->attributesToStream( out ); - - if( need_close_tag ) - { - // got children so write them... - if( node->getFirstChild() != 0 ) - node->getFirstChild()->toStream( out ); - - // and a closing tag.. - out << "typeName() << ">" << endl; - } - } -} -#endif - -// this is nasty, but it makes the code generation easier -ANTLR_API RefAST nullAST; - -#if defined(_MSC_VER) && !defined(__ICL) // Microsoft Visual C++ -extern ANTLR_API AST* const nullASTptr = 0; -#else -ANTLR_API AST* const nullASTptr = 0; -#endif - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/BitSet.cpp b/libs/antlr-2.7.7/src/BitSet.cpp deleted file mode 100644 index d28081347..000000000 --- a/libs/antlr-2.7.7/src/BitSet.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/BitSet.cpp#2 $ - */ -#include "antlr/BitSet.hpp" -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -BitSet::BitSet(unsigned int nbits) -: storage(nbits) -{ - for (unsigned int i = 0; i < nbits ; i++ ) - storage[i] = false; -} - -BitSet::BitSet( const unsigned long* bits_, unsigned int nlongs ) -: storage(nlongs*32) -{ - for ( unsigned int i = 0 ; i < (nlongs * 32); i++) - storage[i] = (bits_[i>>5] & (1UL << (i&31))) ? true : false; -} - -BitSet::~BitSet() -{ -} - -void BitSet::add(unsigned int el) -{ - if( el >= storage.size() ) - storage.resize( el+1, false ); - - storage[el] = true; -} - -bool BitSet::member(unsigned int el) const -{ - if ( el >= storage.size()) - return false; - - return storage[el]; -} - -ANTLR_USE_NAMESPACE(std)vector BitSet::toArray() const -{ - ANTLR_USE_NAMESPACE(std)vector elems; - for (unsigned int i = 0; i < storage.size(); i++) - { - if (storage[i]) - elems.push_back(i); - } - - return elems; -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/CharBuffer.cpp b/libs/antlr-2.7.7/src/CharBuffer.cpp deleted file mode 100644 index 5e1a71e00..000000000 --- a/libs/antlr-2.7.7/src/CharBuffer.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/CharBuffer.cpp#2 $ - */ - -#include "antlr/CharBuffer.hpp" -#include - -//#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/* RK: Per default istream does not throw exceptions. This can be - * enabled with: - * stream.exceptions(ios_base::badbit|ios_base::failbit|ios_base::eofbit); - * - * We could try catching the bad/fail stuff. But handling eof via this is - * not a good idea. EOF is best handled as a 'normal' character. - * - * So this does not work yet with gcc... Comment it until I get to a platform - * that does.. - */ - -/** Create a character buffer. Enable fail and bad exceptions, if supported - * by platform. */ -CharBuffer::CharBuffer(ANTLR_USE_NAMESPACE(std)istream& input_) -: input(input_) -{ -// input.exceptions(ANTLR_USE_NAMESPACE(std)ios_base::badbit| -// ANTLR_USE_NAMESPACE(std)ios_base::failbit); -} - -/** Get the next character from the stream. May throw CharStreamIOException - * when something bad happens (not EOF) (if supported by platform). - */ -int CharBuffer::getChar() -{ -// try { - return input.get(); -// } -// catch (ANTLR_USE_NAMESPACE(std)ios_base::failure& e) { -// throw CharStreamIOException(e); -// } -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/CharScanner.cpp b/libs/antlr-2.7.7/src/CharScanner.cpp deleted file mode 100644 index 6d2431399..000000000 --- a/libs/antlr-2.7.7/src/CharScanner.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/CharScanner.cpp#2 $ - */ - -#include - -#include "antlr/CharScanner.hpp" -#include "antlr/CommonToken.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif -ANTLR_C_USING(exit) - -CharScanner::CharScanner(InputBuffer& cb, bool case_sensitive ) - : saveConsumedInput(true) //, caseSensitiveLiterals(true) - , caseSensitive(case_sensitive) - , literals(CharScannerLiteralsLess(this)) - , inputState(new LexerInputState(cb)) - , commitToPath(false) - , tabsize(8) - , traceDepth(0) -{ - setTokenObjectFactory(&CommonToken::factory); -} - -CharScanner::CharScanner(InputBuffer* cb, bool case_sensitive ) - : saveConsumedInput(true) //, caseSensitiveLiterals(true) - , caseSensitive(case_sensitive) - , literals(CharScannerLiteralsLess(this)) - , inputState(new LexerInputState(cb)) - , commitToPath(false) - , tabsize(8) - , traceDepth(0) -{ - setTokenObjectFactory(&CommonToken::factory); -} - -CharScanner::CharScanner( const LexerSharedInputState& state, bool case_sensitive ) - : saveConsumedInput(true) //, caseSensitiveLiterals(true) - , caseSensitive(case_sensitive) - , literals(CharScannerLiteralsLess(this)) - , inputState(state) - , commitToPath(false) - , tabsize(8) - , traceDepth(0) -{ - setTokenObjectFactory(&CommonToken::factory); -} - -/** Report exception errors caught in nextToken() */ -void CharScanner::reportError(const RecognitionException& ex) -{ - ANTLR_USE_NAMESPACE(std)cerr << ex.toString().c_str() << ANTLR_USE_NAMESPACE(std)endl; -} - -/** Parser error-reporting function can be overridden in subclass */ -void CharScanner::reportError(const ANTLR_USE_NAMESPACE(std)string& s) -{ - if (getFilename() == "") - ANTLR_USE_NAMESPACE(std)cerr << "error: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; - else - ANTLR_USE_NAMESPACE(std)cerr << getFilename().c_str() << ": error: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; -} - -/** Parser warning-reporting function can be overridden in subclass */ -void CharScanner::reportWarning(const ANTLR_USE_NAMESPACE(std)string& s) -{ - if (getFilename() == "") - ANTLR_USE_NAMESPACE(std)cerr << "warning: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; - else - ANTLR_USE_NAMESPACE(std)cerr << getFilename().c_str() << ": warning: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; -} - -void CharScanner::traceIndent() -{ - for( int i = 0; i < traceDepth; i++ ) - ANTLR_USE_NAMESPACE(std)cout << " "; -} - -void CharScanner::traceIn(const char* rname) -{ - traceDepth++; - traceIndent(); - ANTLR_USE_NAMESPACE(std)cout << "> lexer " << rname - << "; c==" << LA(1) << ANTLR_USE_NAMESPACE(std)endl; -} - -void CharScanner::traceOut(const char* rname) -{ - traceIndent(); - ANTLR_USE_NAMESPACE(std)cout << "< lexer " << rname - << "; c==" << LA(1) << ANTLR_USE_NAMESPACE(std)endl; - traceDepth--; -} - -#ifndef NO_STATIC_CONSTS -const int CharScanner::NO_CHAR; -const int CharScanner::EOF_CHAR; -#endif - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - diff --git a/libs/antlr-2.7.7/src/CommonAST.cpp b/libs/antlr-2.7.7/src/CommonAST.cpp deleted file mode 100644 index 69d9ee915..000000000 --- a/libs/antlr-2.7.7/src/CommonAST.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/CommonAST.cpp#2 $ - */ -#include "antlr/config.hpp" - -#include -#include - -#include "antlr/CommonAST.hpp" -#include "antlr/ANTLRUtil.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -const char* const CommonAST::TYPE_NAME = "CommonAST"; - -#ifdef ANTLR_SUPPORT_XML -void CommonAST::initialize( ANTLR_USE_NAMESPACE(std)istream& in ) -{ - ANTLR_USE_NAMESPACE(std)string t1, t2, text; - - // text - read_AttributeNValue( in, t1, text ); - - read_AttributeNValue( in, t1, t2 ); -#ifdef ANTLR_ATOI_IN_STD - int type = ANTLR_USE_NAMESPACE(std)atoi(t2.c_str()); -#else - int type = atoi(t2.c_str()); -#endif - - // initialize first part of AST. - this->initialize( type, text ); -} -#endif - -RefAST CommonAST::factory() -{ - return RefAST(new CommonAST); -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - diff --git a/libs/antlr-2.7.7/src/CommonASTWithHiddenTokens.cpp b/libs/antlr-2.7.7/src/CommonASTWithHiddenTokens.cpp deleted file mode 100644 index db2377bb9..000000000 --- a/libs/antlr-2.7.7/src/CommonASTWithHiddenTokens.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/CommonASTWithHiddenTokens.cpp#2 $ - */ -#include "antlr/config.hpp" -#include "antlr/AST.hpp" -#include "antlr/BaseAST.hpp" -#include "antlr/CommonAST.hpp" -#include "antlr/CommonASTWithHiddenTokens.hpp" -#include "antlr/CommonHiddenStreamToken.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -const char* const CommonASTWithHiddenTokens::TYPE_NAME = "CommonASTWithHiddenTokens"; -// RK: Do not put constructor and destructor into the header file here.. -// this triggers something very obscure in gcc 2.95.3 (and 3.0) -// missing vtables and stuff. -// Although this may be a problem with with binutils. -CommonASTWithHiddenTokens::CommonASTWithHiddenTokens() -: CommonAST() -{ -} - -CommonASTWithHiddenTokens::~CommonASTWithHiddenTokens() -{ -} - -void CommonASTWithHiddenTokens::initialize(int t,const ANTLR_USE_NAMESPACE(std)string& txt) -{ - CommonAST::initialize(t,txt); -} - -void CommonASTWithHiddenTokens::initialize(RefAST t) -{ - CommonAST::initialize(t); - hiddenBefore = RefCommonASTWithHiddenTokens(t)->getHiddenBefore(); - hiddenAfter = RefCommonASTWithHiddenTokens(t)->getHiddenAfter(); -} - -void CommonASTWithHiddenTokens::initialize(RefToken t) -{ - CommonAST::initialize(t); - hiddenBefore = static_cast(t.get())->getHiddenBefore(); - hiddenAfter = static_cast(t.get())->getHiddenAfter(); -} - -RefAST CommonASTWithHiddenTokens::factory() -{ - return RefAST(new CommonASTWithHiddenTokens); -} - -RefAST CommonASTWithHiddenTokens::clone( void ) const -{ - CommonASTWithHiddenTokens *ast = new CommonASTWithHiddenTokens( *this ); - return RefAST(ast); -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/CommonHiddenStreamToken.cpp b/libs/antlr-2.7.7/src/CommonHiddenStreamToken.cpp deleted file mode 100644 index adf386bc3..000000000 --- a/libs/antlr-2.7.7/src/CommonHiddenStreamToken.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/CommonHiddenStreamToken.cpp#2 $ - */ -#include "antlr/CommonHiddenStreamToken.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -CommonHiddenStreamToken::CommonHiddenStreamToken() -: CommonToken() -{ -} - -CommonHiddenStreamToken::CommonHiddenStreamToken(int t, const ANTLR_USE_NAMESPACE(std)string& txt) -: CommonToken(t,txt) -{ -} - -CommonHiddenStreamToken::CommonHiddenStreamToken(const ANTLR_USE_NAMESPACE(std)string& s) -: CommonToken(s) -{ -} - -RefToken CommonHiddenStreamToken::getHiddenAfter() -{ - return hiddenAfter; -} - -RefToken CommonHiddenStreamToken::getHiddenBefore() -{ - return hiddenBefore; -} - -RefToken CommonHiddenStreamToken::factory() -{ - return RefToken(new CommonHiddenStreamToken); -} - -void CommonHiddenStreamToken::setHiddenAfter(RefToken t) -{ - hiddenAfter = t; -} - -void CommonHiddenStreamToken::setHiddenBefore(RefToken t) -{ - hiddenBefore = t; -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - diff --git a/libs/antlr-2.7.7/src/CommonToken.cpp b/libs/antlr-2.7.7/src/CommonToken.cpp deleted file mode 100644 index d49a0e286..000000000 --- a/libs/antlr-2.7.7/src/CommonToken.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/CommonToken.cpp#2 $ - */ - -#include "antlr/CommonToken.hpp" -#include "antlr/String.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -CommonToken::CommonToken() : Token(), line(1), col(1), text("") -{} - -CommonToken::CommonToken(int t, const ANTLR_USE_NAMESPACE(std)string& txt) -: Token(t) -, line(1) -, col(1) -, text(txt) -{} - -CommonToken::CommonToken(const ANTLR_USE_NAMESPACE(std)string& s) -: Token() -, line(1) -, col(1) -, text(s) -{} - -ANTLR_USE_NAMESPACE(std)string CommonToken::toString() const -{ - return "[\""+getText()+"\",<"+getType()+">,line="+getLine()+",column="+getColumn()+"]"; -} - -RefToken CommonToken::factory() -{ - return RefToken(new CommonToken); -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - diff --git a/libs/antlr-2.7.7/src/InputBuffer.cpp b/libs/antlr-2.7.7/src/InputBuffer.cpp deleted file mode 100644 index bf34e5dd9..000000000 --- a/libs/antlr-2.7.7/src/InputBuffer.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/InputBuffer.cpp#2 $ - */ - -#include "antlr/config.hpp" -#include "antlr/InputBuffer.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** Ensure that the character buffer is sufficiently full */ -void InputBuffer::fill(unsigned int amount) -{ - syncConsume(); - // Fill the buffer sufficiently to hold needed characters - while (queue.entries() < amount + markerOffset) - { - // Append the next character - queue.append(getChar()); - } -} - -/** get the current lookahead characters as a string - * @warning it may treat 0 and EOF values wrong - */ -ANTLR_USE_NAMESPACE(std)string InputBuffer::getLAChars( void ) const -{ - ANTLR_USE_NAMESPACE(std)string ret; - - for(unsigned int i = markerOffset; i < queue.entries(); i++) - ret += queue.elementAt(i); - - return ret; -} - -/** get the current marked characters as a string - * @warning it may treat 0 and EOF values wrong - */ -ANTLR_USE_NAMESPACE(std)string InputBuffer::getMarkedChars( void ) const -{ - ANTLR_USE_NAMESPACE(std)string ret; - - for(unsigned int i = 0; i < markerOffset; i++) - ret += queue.elementAt(i); - - return ret; -} - -/** Return an integer marker that can be used to rewind the buffer to - * its current state. - */ -unsigned int InputBuffer::mark() -{ - syncConsume(); - nMarkers++; - return markerOffset; -} - -/** Rewind the character buffer to a marker. - * @param mark Marker returned previously from mark() - */ -void InputBuffer::rewind(unsigned int mark) -{ - syncConsume(); - markerOffset = mark; - nMarkers--; -} - -unsigned int InputBuffer::entries() const -{ - //assert(queue.entries() >= markerOffset); - return queue.entries() - markerOffset; -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/LLkParser.cpp b/libs/antlr-2.7.7/src/LLkParser.cpp deleted file mode 100644 index 39926dc1f..000000000 --- a/libs/antlr-2.7.7/src/LLkParser.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/LLkParser.cpp#2 $ - */ - -#include "antlr/LLkParser.hpp" -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -ANTLR_USING_NAMESPACE(std) - -/**An LL(k) parser. - * - * @see antlr.Token - * @see antlr.TokenBuffer - * @see antlr.LL1Parser - */ - -// LLkParser(int k_); - -LLkParser::LLkParser(const ParserSharedInputState& state, int k_) -: Parser(state), k(k_) -{ -} - -LLkParser::LLkParser(TokenBuffer& tokenBuf, int k_) -: Parser(tokenBuf), k(k_) -{ -} - -LLkParser::LLkParser(TokenStream& lexer, int k_) -: Parser(new TokenBuffer(lexer)), k(k_) -{ -} - -void LLkParser::trace(const char* ee, const char* rname) -{ - traceIndent(); - - cout << ee << rname << ((inputState->guessing>0)?"; [guessing]":"; "); - - for (int i = 1; i <= k; i++) - { - if (i != 1) { - cout << ", "; - } - cout << "LA(" << i << ")=="; - - string temp; - - try { - temp = LT(i)->getText().c_str(); - } - catch( ANTLRException& ae ) - { - temp = "[error: "; - temp += ae.toString(); - temp += ']'; - } - cout << temp; - } - - cout << endl; -} - -void LLkParser::traceIn(const char* rname) -{ - traceDepth++; - trace("> ",rname); -} - -void LLkParser::traceOut(const char* rname) -{ - trace("< ",rname); - traceDepth--; -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/MismatchedCharException.cpp b/libs/antlr-2.7.7/src/MismatchedCharException.cpp deleted file mode 100644 index 6ca66e06f..000000000 --- a/libs/antlr-2.7.7/src/MismatchedCharException.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/MismatchedCharException.cpp#2 $ - */ - -#include "antlr/CharScanner.hpp" -#include "antlr/MismatchedCharException.hpp" -#include "antlr/String.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -MismatchedCharException::MismatchedCharException() - : RecognitionException("Mismatched char") -{} - -// Expected range / not range -MismatchedCharException::MismatchedCharException( - int c, - int lower, - int upper_, - bool matchNot, - CharScanner* scanner_ -) : RecognitionException("Mismatched char", - scanner_->getFilename(), - scanner_->getLine(), scanner_->getColumn()) - , mismatchType(matchNot ? NOT_RANGE : RANGE) - , foundChar(c) - , expecting(lower) - , upper(upper_) - , scanner(scanner_) -{ -} - -// Expected token / not token -MismatchedCharException::MismatchedCharException( - int c, - int expecting_, - bool matchNot, - CharScanner* scanner_ -) : RecognitionException("Mismatched char", - scanner_->getFilename(), - scanner_->getLine(), scanner_->getColumn()) - , mismatchType(matchNot ? NOT_CHAR : CHAR) - , foundChar(c) - , expecting(expecting_) - , scanner(scanner_) -{ -} - -// Expected BitSet / not BitSet -MismatchedCharException::MismatchedCharException( - int c, - BitSet set_, - bool matchNot, - CharScanner* scanner_ -) : RecognitionException("Mismatched char", - scanner_->getFilename(), - scanner_->getLine(), scanner_->getColumn()) - , mismatchType(matchNot ? NOT_SET : SET) - , foundChar(c) - , set(set_) - , scanner(scanner_) -{ -} - -ANTLR_USE_NAMESPACE(std)string MismatchedCharException::getMessage() const -{ - ANTLR_USE_NAMESPACE(std)string s; - - switch (mismatchType) { - case CHAR : - s += "expecting '" + charName(expecting) + "', found '" + charName(foundChar) + "'"; - break; - case NOT_CHAR : - s += "expecting anything but '" + charName(expecting) + "'; got it anyway"; - break; - case RANGE : - s += "expecting token in range: '" + charName(expecting) + "'..'" + charName(upper) + "', found '" + charName(foundChar) + "'"; - break; - case NOT_RANGE : - s += "expecting token NOT in range: " + charName(expecting) + "'..'" + charName(upper) + "', found '" + charName(foundChar) + "'"; - break; - case SET : - case NOT_SET : - { - s += ANTLR_USE_NAMESPACE(std)string("expecting ") + (mismatchType == NOT_SET ? "NOT " : "") + "one of ("; - ANTLR_USE_NAMESPACE(std)vector elems = set.toArray(); - for ( unsigned int i = 0; i < elems.size(); i++ ) - { - s += " '"; - s += charName(elems[i]); - s += "'"; - } - s += "), found '" + charName(foundChar) + "'"; - } - break; - default : - s += RecognitionException::getMessage(); - break; - } - - return s; -} - -#ifndef NO_STATIC_CONSTS -const int MismatchedCharException::CHAR; -const int MismatchedCharException::NOT_CHAR; -const int MismatchedCharException::RANGE; -const int MismatchedCharException::NOT_RANGE; -const int MismatchedCharException::SET; -const int MismatchedCharException::NOT_SET; -#endif - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/MismatchedTokenException.cpp b/libs/antlr-2.7.7/src/MismatchedTokenException.cpp deleted file mode 100644 index 8fae8f07c..000000000 --- a/libs/antlr-2.7.7/src/MismatchedTokenException.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/MismatchedTokenException.cpp#2 $ - */ - -#include "antlr/MismatchedTokenException.hpp" -#include "antlr/String.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -MismatchedTokenException::MismatchedTokenException() - : RecognitionException("Mismatched Token: expecting any AST node","",-1,-1) - , token(0) - , node(nullASTptr) - , tokenNames(0) - , numTokens(0) -{ -} - -// Expected range / not range -MismatchedTokenException::MismatchedTokenException( - const char* const* tokenNames_, - const int numTokens_, - RefAST node_, - int lower, - int upper_, - bool matchNot -) : RecognitionException("Mismatched Token","",-1,-1) - , token(0) - , node(node_) - , tokenText( (node_ ? node_->toString(): ANTLR_USE_NAMESPACE(std)string("")) ) - , mismatchType(matchNot ? NOT_RANGE : RANGE) - , expecting(lower) - , upper(upper_) - , tokenNames(tokenNames_) - , numTokens(numTokens_) -{ -} - -// Expected token / not token -MismatchedTokenException::MismatchedTokenException( - const char* const* tokenNames_, - const int numTokens_, - RefAST node_, - int expecting_, - bool matchNot -) : RecognitionException("Mismatched Token","",-1,-1) - , token(0) - , node(node_) - , tokenText( (node_ ? node_->toString(): ANTLR_USE_NAMESPACE(std)string("")) ) - , mismatchType(matchNot ? NOT_TOKEN : TOKEN) - , expecting(expecting_) - , tokenNames(tokenNames_) - , numTokens(numTokens_) -{ -} - -// Expected BitSet / not BitSet -MismatchedTokenException::MismatchedTokenException( - const char* const* tokenNames_, - const int numTokens_, - RefAST node_, - BitSet set_, - bool matchNot -) : RecognitionException("Mismatched Token","",-1,-1) - , token(0) - , node(node_) - , tokenText( (node_ ? node_->toString(): ANTLR_USE_NAMESPACE(std)string("")) ) - , mismatchType(matchNot ? NOT_SET : SET) - , set(set_) - , tokenNames(tokenNames_) - , numTokens(numTokens_) -{ -} - -// Expected range / not range -MismatchedTokenException::MismatchedTokenException( - const char* const* tokenNames_, - const int numTokens_, - RefToken token_, - int lower, - int upper_, - bool matchNot, - const ANTLR_USE_NAMESPACE(std)string& fileName_ -) : RecognitionException("Mismatched Token",fileName_,token_->getLine(),token_->getColumn()) - , token(token_) - , node(nullASTptr) - , tokenText(token_->getText()) - , mismatchType(matchNot ? NOT_RANGE : RANGE) - , expecting(lower) - , upper(upper_) - , tokenNames(tokenNames_) - , numTokens(numTokens_) -{ -} - -// Expected token / not token -MismatchedTokenException::MismatchedTokenException( - const char* const* tokenNames_, - const int numTokens_, - RefToken token_, - int expecting_, - bool matchNot, - const ANTLR_USE_NAMESPACE(std)string& fileName_ -) : RecognitionException("Mismatched Token",fileName_,token_->getLine(),token_->getColumn()) - , token(token_) - , node(nullASTptr) - , tokenText(token_->getText()) - , mismatchType(matchNot ? NOT_TOKEN : TOKEN) - , expecting(expecting_) - , tokenNames(tokenNames_) - , numTokens(numTokens_) -{ -} - -// Expected BitSet / not BitSet -MismatchedTokenException::MismatchedTokenException( - const char* const* tokenNames_, - const int numTokens_, - RefToken token_, - BitSet set_, - bool matchNot, - const ANTLR_USE_NAMESPACE(std)string& fileName_ -) : RecognitionException("Mismatched Token",fileName_,token_->getLine(),token_->getColumn()) - , token(token_) - , node(nullASTptr) - , tokenText(token_->getText()) - , mismatchType(matchNot ? NOT_SET : SET) - , set(set_) - , tokenNames(tokenNames_) - , numTokens(numTokens_) -{ -} - -ANTLR_USE_NAMESPACE(std)string MismatchedTokenException::getMessage() const -{ - ANTLR_USE_NAMESPACE(std)string s; - switch (mismatchType) { - case TOKEN: - s += "expecting " + tokenName(expecting) + ", found '" + tokenText + "'"; - break; - case NOT_TOKEN: - s += "expecting anything but " + tokenName(expecting) + "; got it anyway"; - break; - case RANGE: - s += "expecting token in range: " + tokenName(expecting) + ".." + tokenName(upper) + ", found '" + tokenText + "'"; - break; - case NOT_RANGE: - s += "expecting token NOT in range: " + tokenName(expecting) + ".." + tokenName(upper) + ", found '" + tokenText + "'"; - break; - case SET: - case NOT_SET: - { - s += ANTLR_USE_NAMESPACE(std)string("expecting ") + (mismatchType == NOT_SET ? "NOT " : "") + "one of ("; - ANTLR_USE_NAMESPACE(std)vector elems = set.toArray(); - for ( unsigned int i = 0; i < elems.size(); i++ ) - { - s += " "; - s += tokenName(elems[i]); - } - s += "), found '" + tokenText + "'"; - } - break; - default: - s = RecognitionException::getMessage(); - break; - } - return s; -} - -ANTLR_USE_NAMESPACE(std)string MismatchedTokenException::tokenName(int tokenType) const -{ - if (tokenType == Token::INVALID_TYPE) - return ""; - else if (tokenType < 0 || tokenType >= numTokens) - return ANTLR_USE_NAMESPACE(std)string("<") + tokenType + ">"; - else - return tokenNames[tokenType]; -} - -#ifndef NO_STATIC_CONSTS -const int MismatchedTokenException::TOKEN; -const int MismatchedTokenException::NOT_TOKEN; -const int MismatchedTokenException::RANGE; -const int MismatchedTokenException::NOT_RANGE; -const int MismatchedTokenException::SET; -const int MismatchedTokenException::NOT_SET; -#endif - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/NoViableAltException.cpp b/libs/antlr-2.7.7/src/NoViableAltException.cpp deleted file mode 100644 index a41779d60..000000000 --- a/libs/antlr-2.7.7/src/NoViableAltException.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/NoViableAltException.cpp#2 $ - */ - -#include "antlr/NoViableAltException.hpp" -#include "antlr/String.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -ANTLR_USING_NAMESPACE(std) - -NoViableAltException::NoViableAltException(RefAST t) - : RecognitionException("NoViableAlt","",-1,-1), - token(0), node(t) -{ -} - -NoViableAltException::NoViableAltException( - RefToken t, - const ANTLR_USE_NAMESPACE(std)string& fileName_ -) : RecognitionException("NoViableAlt",fileName_,t->getLine(),t->getColumn()), - token(t), node(nullASTptr) -{ -} - -ANTLR_USE_NAMESPACE(std)string NoViableAltException::getMessage() const -{ - if (token) - { - if( token->getType() == Token::EOF_TYPE ) - return string("unexpected end of file"); - else if( token->getType() == Token::NULL_TREE_LOOKAHEAD ) - return string("unexpected end of tree"); - else - return string("unexpected token: ")+token->getText(); - } - - // must a tree parser error if token==null - if (!node) - return "unexpected end of subtree"; - - return string("unexpected AST node: ")+node->toString(); -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/NoViableAltForCharException.cpp b/libs/antlr-2.7.7/src/NoViableAltForCharException.cpp deleted file mode 100644 index 0b2cf2d54..000000000 --- a/libs/antlr-2.7.7/src/NoViableAltForCharException.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/NoViableAltForCharException.cpp#2 $ - */ - -#include "antlr/NoViableAltForCharException.hpp" -#include "antlr/String.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -NoViableAltForCharException::NoViableAltForCharException(int c, CharScanner* scanner) - : RecognitionException("NoViableAlt", - scanner->getFilename(), - scanner->getLine(),scanner->getColumn()), - foundChar(c) -{ -} - -NoViableAltForCharException::NoViableAltForCharException( - int c, - const ANTLR_USE_NAMESPACE(std)string& fileName_, - int line_, int column_) - : RecognitionException("NoViableAlt",fileName_,line_,column_), - foundChar(c) -{ -} - -ANTLR_USE_NAMESPACE(std)string NoViableAltForCharException::getMessage() const -{ - return ANTLR_USE_NAMESPACE(std)string("unexpected char: ")+charName(foundChar); -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/Parser.cpp b/libs/antlr-2.7.7/src/Parser.cpp deleted file mode 100644 index 02a68e72c..000000000 --- a/libs/antlr-2.7.7/src/Parser.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/Parser.cpp#2 $ - */ - -#include "antlr/Parser.hpp" - -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** A generic ANTLR parser (LL(k) for k>=1) containing a bunch of - * utility routines useful at any lookahead depth. We distinguish between - * the LL(1) and LL(k) parsers because of efficiency. This may not be - * necessary in the near future. - * - * Each parser object contains the state of the parse including a lookahead - * cache (the form of which is determined by the subclass), whether or - * not the parser is in guess mode, where tokens come from, etc... - * - *

- * During guess mode, the current lookahead token(s) and token type(s) - * cache must be saved because the token stream may not have been informed - * to save the token (via mark) before the try block. - * Guessing is started by: - *

    - *
  1. saving the lookahead cache. - *
  2. marking the current position in the TokenBuffer. - *
  3. increasing the guessing level. - *
- * - * After guessing, the parser state is restored by: - *
    - *
  1. restoring the lookahead cache. - *
  2. rewinding the TokenBuffer. - *
  3. decreasing the guessing level. - *
- * - * @see antlr.Token - * @see antlr.TokenBuffer - * @see antlr.TokenStream - * @see antlr.LL1Parser - * @see antlr.LLkParser - */ - -bool DEBUG_PARSER = false; - -/** Parser error-reporting function can be overridden in subclass */ -void Parser::reportError(const RecognitionException& ex) -{ - ANTLR_USE_NAMESPACE(std)cerr << ex.toString().c_str() << ANTLR_USE_NAMESPACE(std)endl; -} - -/** Parser error-reporting function can be overridden in subclass */ -void Parser::reportError(const ANTLR_USE_NAMESPACE(std)string& s) -{ - if ( getFilename()=="" ) - ANTLR_USE_NAMESPACE(std)cerr << "error: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; - else - ANTLR_USE_NAMESPACE(std)cerr << getFilename().c_str() << ": error: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; -} - -/** Parser warning-reporting function can be overridden in subclass */ -void Parser::reportWarning(const ANTLR_USE_NAMESPACE(std)string& s) -{ - if ( getFilename()=="" ) - ANTLR_USE_NAMESPACE(std)cerr << "warning: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; - else - ANTLR_USE_NAMESPACE(std)cerr << getFilename().c_str() << ": warning: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; -} - -/** Set or change the input token buffer */ -// void setTokenBuffer(TokenBuffer* t); - -void Parser::traceIndent() -{ - for( int i = 0; i < traceDepth; i++ ) - ANTLR_USE_NAMESPACE(std)cout << " "; -} - -void Parser::traceIn(const char* rname) -{ - traceDepth++; - - for( int i = 0; i < traceDepth; i++ ) - ANTLR_USE_NAMESPACE(std)cout << " "; - - ANTLR_USE_NAMESPACE(std)cout << "> " << rname - << "; LA(1)==" << LT(1)->getText().c_str() - << ((inputState->guessing>0)?" [guessing]":"") - << ANTLR_USE_NAMESPACE(std)endl; -} - -void Parser::traceOut(const char* rname) -{ - for( int i = 0; i < traceDepth; i++ ) - ANTLR_USE_NAMESPACE(std)cout << " "; - - ANTLR_USE_NAMESPACE(std)cout << "< " << rname - << "; LA(1)==" << LT(1)->getText().c_str() - << ((inputState->guessing>0)?" [guessing]":"") - << ANTLR_USE_NAMESPACE(std)endl; - - traceDepth--; -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/RecognitionException.cpp b/libs/antlr-2.7.7/src/RecognitionException.cpp deleted file mode 100644 index c078c5c67..000000000 --- a/libs/antlr-2.7.7/src/RecognitionException.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/RecognitionException.cpp#2 $ - */ - -#include "antlr/RecognitionException.hpp" -#include "antlr/String.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -RecognitionException::RecognitionException() -: ANTLRException("parsing error") -, line(-1) -, column(-1) -{ -} - -RecognitionException::RecognitionException(const ANTLR_USE_NAMESPACE(std)string& s) -: ANTLRException(s) -, line(-1) -, column(-1) -{ -} - -RecognitionException::RecognitionException(const ANTLR_USE_NAMESPACE(std)string& s, - const ANTLR_USE_NAMESPACE(std)string& fileName_, - int line_,int column_) -: ANTLRException(s) -, fileName(fileName_) -, line(line_) -, column(column_) -{ -} - -ANTLR_USE_NAMESPACE(std)string RecognitionException::getFileLineColumnString() const -{ - ANTLR_USE_NAMESPACE(std)string fileLineColumnString; - - if ( fileName.length() > 0 ) - fileLineColumnString = fileName + ":"; - - if ( line != -1 ) - { - if ( fileName.length() == 0 ) - fileLineColumnString = fileLineColumnString + "line "; - - fileLineColumnString = fileLineColumnString + line; - - if ( column != -1 ) - fileLineColumnString = fileLineColumnString + ":" + column; - - fileLineColumnString = fileLineColumnString + ":"; - } - - fileLineColumnString = fileLineColumnString + " "; - - return fileLineColumnString; -} - -ANTLR_USE_NAMESPACE(std)string RecognitionException::toString() const -{ - return getFileLineColumnString()+getMessage(); -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/String.cpp b/libs/antlr-2.7.7/src/String.cpp deleted file mode 100644 index e07b5fb5d..000000000 --- a/libs/antlr-2.7.7/src/String.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/String.cpp#2 $ - */ - -#include "antlr/String.hpp" - -#include - -#ifdef HAS_NOT_CSTDIO_H -#include -#else -#include -#endif - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -// wh: hack for Borland C++ 5.6 -#if __BORLANDC__ - using std::sprintf; -#endif - - -// RK: should be using snprintf actually... (or stringstream) -ANTLR_C_USING(sprintf) - -ANTLR_USE_NAMESPACE(std)string operator+( const ANTLR_USE_NAMESPACE(std)string& lhs, const int rhs ) -{ - char tmp[100]; - sprintf(tmp,"%d",rhs); - return lhs+tmp; -} - -ANTLR_USE_NAMESPACE(std)string operator+( const ANTLR_USE_NAMESPACE(std)string& lhs, size_t rhs ) -{ - char tmp[100]; - sprintf(tmp,"%zu",rhs); - return lhs+tmp; -} - -/** Convert character to readable string - */ -ANTLR_USE_NAMESPACE(std)string charName(int ch) -{ - if (ch == EOF) - return "EOF"; - else - { - ANTLR_USE_NAMESPACE(std)string s; - - // when you think you've seen it all.. an isprint that crashes... - ch = ch & 0xFF; -#ifdef ANTLR_CCTYPE_NEEDS_STD - if( ANTLR_USE_NAMESPACE(std)isprint( ch ) ) -#else - if( isprint( ch ) ) -#endif - { - s.append("'"); - s += ch; - s.append("'"); -// s += "'"+ch+"'"; - } - else - { - s += "0x"; - - unsigned int t = ch >> 4; - if( t < 10 ) - s += t | 0x30; - else - s += t + 0x37; - t = ch & 0xF; - if( t < 10 ) - s += t | 0x30; - else - s += t + 0x37; - } - return s; - } -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - diff --git a/libs/antlr-2.7.7/src/Token.cpp b/libs/antlr-2.7.7/src/Token.cpp deleted file mode 100644 index 8104813fd..000000000 --- a/libs/antlr-2.7.7/src/Token.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/Token.cpp#2 $ - */ - -#include "antlr/Token.hpp" -#include "antlr/String.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -int Token::getColumn() const -{ - return 0; -} - -int Token::getLine() const -{ - return 0; -} - -ANTLR_USE_NAMESPACE(std)string Token::getText() const -{ - return ""; -} - -int Token::getType() const -{ - return type; -} - -void Token::setColumn(int) -{ -} - -void Token::setLine(int) -{ -} - -void Token::setText(const ANTLR_USE_NAMESPACE(std)string&) -{ -} - -void Token::setType(int t) -{ - type = t; -} - -void Token::setFilename(const ANTLR_USE_NAMESPACE(std)string&) -{ -} - -ANTLR_USE_NAMESPACE(std)string emptyString(""); - -const ANTLR_USE_NAMESPACE(std)string& Token::getFilename() const -{ - return emptyString; -} - -ANTLR_USE_NAMESPACE(std)string Token::toString() const -{ - return "[\""+getText()+"\",<"+type+">]"; -} - -ANTLR_API RefToken nullToken; - -#ifndef NO_STATIC_CONSTS -const int Token::MIN_USER_TYPE; -const int Token::NULL_TREE_LOOKAHEAD; -const int Token::INVALID_TYPE; -const int Token::EOF_TYPE; -const int Token::SKIP; -#endif - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/TokenBuffer.cpp b/libs/antlr-2.7.7/src/TokenBuffer.cpp deleted file mode 100644 index 96e4ada59..000000000 --- a/libs/antlr-2.7.7/src/TokenBuffer.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/TokenBuffer.cpp#2 $ - */ - -#include "antlr/TokenBuffer.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/**A Stream of Token objects fed to the parser from a TokenStream that can - * be rewound via mark()/rewind() methods. - *

- * A dynamic array is used to buffer up all the input tokens. Normally, - * "k" tokens are stored in the buffer. More tokens may be stored during - * guess mode (testing syntactic predicate), or when LT(i>k) is referenced. - * Consumption of tokens is deferred. In other words, reading the next - * token is not done by conume(), but deferred until needed by LA or LT. - *

- * - * @see antlr.Token - * @see antlr.TokenStream - * @see antlr.TokenQueue - */ - -/** Create a token buffer */ -TokenBuffer::TokenBuffer( TokenStream& inp ) -: input(inp) -, nMarkers(0) -, markerOffset(0) -, numToConsume(0) -{ -} - -TokenBuffer::~TokenBuffer( void ) -{ -} - -/** Ensure that the token buffer is sufficiently full */ -void TokenBuffer::fill(unsigned int amount) -{ - syncConsume(); - // Fill the buffer sufficiently to hold needed tokens - while (queue.entries() < (amount + markerOffset)) - { - // Append the next token - queue.append(input.nextToken()); - } -} - -/** Get a lookahead token value */ -int TokenBuffer::LA(unsigned int i) -{ - fill(i); - return queue.elementAt(markerOffset+i-1)->getType(); -} - -/** Get a lookahead token */ -RefToken TokenBuffer::LT(unsigned int i) -{ - fill(i); - return queue.elementAt(markerOffset+i-1); -} - -/** Return an integer marker that can be used to rewind the buffer to - * its current state. - */ -unsigned int TokenBuffer::mark() -{ - syncConsume(); - nMarkers++; - return markerOffset; -} - -/**Rewind the token buffer to a marker. - * @param mark Marker returned previously from mark() - */ -void TokenBuffer::rewind(unsigned int mark) -{ - syncConsume(); - markerOffset=mark; - nMarkers--; -} - -/// Get number of non-consumed tokens -unsigned int TokenBuffer::entries() const -{ - return queue.entries() - markerOffset; -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE - } -#endif diff --git a/libs/antlr-2.7.7/src/TokenRefCount.cpp b/libs/antlr-2.7.7/src/TokenRefCount.cpp deleted file mode 100644 index 0afb0f84d..000000000 --- a/libs/antlr-2.7.7/src/TokenRefCount.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id:$ - */ -#include "antlr/TokenRefCount.hpp" -#include "antlr/Token.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -TokenRef::TokenRef(Token* p) -: ptr(p), count(1) -{ - if (p && !p->ref) - p->ref = this; -} - -TokenRef::~TokenRef() -{ - delete ptr; -} - -TokenRef* TokenRef::getRef(const Token* p) -{ - if (p) { - Token* pp = const_cast(p); - if (pp->ref) - return pp->ref->increment(); - else - return new TokenRef(pp); - } else - return 0; -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - diff --git a/libs/antlr-2.7.7/src/TokenStreamBasicFilter.cpp b/libs/antlr-2.7.7/src/TokenStreamBasicFilter.cpp deleted file mode 100644 index af3068958..000000000 --- a/libs/antlr-2.7.7/src/TokenStreamBasicFilter.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/TokenStreamBasicFilter.cpp#2 $ - */ -#include "antlr/TokenStreamBasicFilter.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** This object is a TokenStream that passes through all - * tokens except for those that you tell it to discard. - * There is no buffering of the tokens. - */ -TokenStreamBasicFilter::TokenStreamBasicFilter(TokenStream& input_) -: input(&input_) -{ -} - -void TokenStreamBasicFilter::discard(int ttype) -{ - discardMask.add(ttype); -} - -void TokenStreamBasicFilter::discard(const BitSet& mask) -{ - discardMask = mask; -} - -RefToken TokenStreamBasicFilter::nextToken() -{ - RefToken tok = input->nextToken(); - while ( tok && discardMask.member(tok->getType()) ) { - tok = input->nextToken(); - } - return tok; -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - diff --git a/libs/antlr-2.7.7/src/TokenStreamHiddenTokenFilter.cpp b/libs/antlr-2.7.7/src/TokenStreamHiddenTokenFilter.cpp deleted file mode 100644 index 2c3b69d08..000000000 --- a/libs/antlr-2.7.7/src/TokenStreamHiddenTokenFilter.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/TokenStreamHiddenTokenFilter.cpp#2 $ - */ -#include "antlr/TokenStreamHiddenTokenFilter.hpp" -#include "antlr/CommonHiddenStreamToken.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/**This object filters a token stream coming from a lexer - * or another TokenStream so that only certain token channels - * get transmitted to the parser. - * - * Any of the channels can be filtered off as "hidden" channels whose - * tokens can be accessed from the parser. - */ - -TokenStreamHiddenTokenFilter::TokenStreamHiddenTokenFilter(TokenStream& input) -: TokenStreamBasicFilter(input) -{ -} - -void TokenStreamHiddenTokenFilter::consume() -{ - nextMonitoredToken = input->nextToken(); -} - -void TokenStreamHiddenTokenFilter::consumeFirst() -{ - consume(); - - // Handle situation where hidden or discarded tokens - // appear first in input stream - RefToken p; - // while hidden or discarded scarf tokens - while ( hideMask.member(LA(1)->getType()) || discardMask.member(LA(1)->getType()) ) { - if ( hideMask.member(LA(1)->getType()) ) { - if ( !p ) { - p = LA(1); - } - else { - static_cast(p.get())->setHiddenAfter(LA(1)); - static_cast(LA(1).get())->setHiddenBefore(p); // double-link - p = LA(1); - } - lastHiddenToken = p; - if (!firstHidden) - firstHidden = p; // record hidden token if first - } - consume(); - } -} - -BitSet TokenStreamHiddenTokenFilter::getDiscardMask() const -{ - return discardMask; -} - -/** Return a ptr to the hidden token appearing immediately after - * token t in the input stream. - */ -RefToken TokenStreamHiddenTokenFilter::getHiddenAfter(RefToken t) -{ - return static_cast(t.get())->getHiddenAfter(); -} - -/** Return a ptr to the hidden token appearing immediately before - * token t in the input stream. - */ -RefToken TokenStreamHiddenTokenFilter::getHiddenBefore(RefToken t) -{ - return static_cast(t.get())->getHiddenBefore(); -} - -BitSet TokenStreamHiddenTokenFilter::getHideMask() const -{ - return hideMask; -} - -/** Return the first hidden token if one appears - * before any monitored token. - */ -RefToken TokenStreamHiddenTokenFilter::getInitialHiddenToken() -{ - return firstHidden; -} - -void TokenStreamHiddenTokenFilter::hide(int m) -{ - hideMask.add(m); -} - -void TokenStreamHiddenTokenFilter::hide(const BitSet& mask) -{ - hideMask = mask; -} - -RefToken TokenStreamHiddenTokenFilter::LA(int) -{ - return nextMonitoredToken; -} - -/** Return the next monitored token. -* Test the token following the monitored token. -* If following is another monitored token, save it -* for the next invocation of nextToken (like a single -* lookahead token) and return it then. -* If following is unmonitored, nondiscarded (hidden) -* channel token, add it to the monitored token. -* -* Note: EOF must be a monitored Token. -*/ -RefToken TokenStreamHiddenTokenFilter::nextToken() -{ - // handle an initial condition; don't want to get lookahead - // token of this splitter until first call to nextToken - if ( !LA(1) ) { - consumeFirst(); - } - - // we always consume hidden tokens after monitored, thus, - // upon entry LA(1) is a monitored token. - RefToken monitored = LA(1); - // point to hidden tokens found during last invocation - static_cast(monitored.get())->setHiddenBefore(lastHiddenToken); - lastHiddenToken = nullToken; - - // Look for hidden tokens, hook them into list emanating - // from the monitored tokens. - consume(); - RefToken p = monitored; - // while hidden or discarded scarf tokens - while ( hideMask.member(LA(1)->getType()) || discardMask.member(LA(1)->getType()) ) { - if ( hideMask.member(LA(1)->getType()) ) { - // attach the hidden token to the monitored in a chain - // link forwards - static_cast(p.get())->setHiddenAfter(LA(1)); - // link backwards - if (p != monitored) { //hidden cannot point to monitored tokens - static_cast(LA(1).get())->setHiddenBefore(p); - } - p = lastHiddenToken = LA(1); - } - consume(); - } - return monitored; -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - diff --git a/libs/antlr-2.7.7/src/TokenStreamRewriteEngine.cpp b/libs/antlr-2.7.7/src/TokenStreamRewriteEngine.cpp deleted file mode 100644 index 2f171eb6e..000000000 --- a/libs/antlr-2.7.7/src/TokenStreamRewriteEngine.cpp +++ /dev/null @@ -1,214 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -#ifndef NO_STATIC_CONSTS -const size_t TokenStreamRewriteEngine::MIN_TOKEN_INDEX = 0; -const int TokenStreamRewriteEngine::PROGRAM_INIT_SIZE = 100; -#endif - -const char* TokenStreamRewriteEngine::DEFAULT_PROGRAM_NAME = "default"; - -namespace { - - struct compareOperationIndex { - typedef TokenStreamRewriteEngine::RewriteOperation RewriteOperation; - bool operator() ( const RewriteOperation* a, const RewriteOperation* b ) const - { - return a->getIndex() < b->getIndex(); - } - }; - struct dumpTokenWithIndex { - dumpTokenWithIndex( ANTLR_USE_NAMESPACE(std)ostream& o ) : out(o) {} - void operator() ( const RefTokenWithIndex& t ) { - out << "[txt='" << t->getText() << "' tp=" << t->getType() << " idx=" << t->getIndex() << "]\n"; - } - ANTLR_USE_NAMESPACE(std)ostream& out; - }; -} - -TokenStreamRewriteEngine::TokenStreamRewriteEngine(TokenStream& upstream) -: stream(upstream) -, index(MIN_TOKEN_INDEX) -, tokens() -, programs() -, discardMask() -{ -} - -TokenStreamRewriteEngine::TokenStreamRewriteEngine(TokenStream& upstream, size_t initialSize ) -: stream(upstream) -, index(MIN_TOKEN_INDEX) -, tokens(initialSize) -, programs() -, discardMask() -{ -} - -RefToken TokenStreamRewriteEngine::nextToken( void ) -{ - RefTokenWithIndex t; - // suck tokens until end of stream or we find a non-discarded token - do { - t = RefTokenWithIndex(stream.nextToken()); - if ( t ) - { - t->setIndex(index); // what is t's index in list? - if ( t->getType() != Token::EOF_TYPE ) { - tokens.push_back(t); // track all tokens except EOF - } - index++; // move to next position - } - } while ( t && discardMask.member(t->getType()) ); - return RefToken(t); -} - -void TokenStreamRewriteEngine::rollback( const std::string& programName, - size_t instructionIndex ) -{ - program_map::iterator rewrite = programs.find(programName); - if( rewrite != programs.end() ) - { - operation_list& prog = rewrite->second; - operation_list::iterator - j = prog.begin(), - end = prog.end(); - - std::advance(j,instructionIndex); - if( j != end ) - prog.erase(j, end); - } -} - -void TokenStreamRewriteEngine::originalToStream( std::ostream& out, - size_t start, - size_t end ) const -{ - token_list::const_iterator s = tokens.begin(); - std::advance( s, start ); - token_list::const_iterator e = s; - std::advance( e, end-start ); - std::for_each( s, e, tokenToStream(out) ); -} - -void TokenStreamRewriteEngine::toStream( std::ostream& out, - const std::string& programName, - size_t firstToken, - size_t lastToken ) const -{ - if( tokens.size() == 0 ) - return; - - program_map::const_iterator rewriter = programs.find(programName); - - if ( rewriter == programs.end() ) - return; - - // get the prog and some iterators in it... - const operation_list& prog = rewriter->second; - operation_list::const_iterator - rewriteOpIndex = prog.begin(), - rewriteOpEnd = prog.end(); - - size_t tokenCursor = firstToken; - // make sure we don't run out of the tokens we have... - if( lastToken > (tokens.size() - 1) ) - lastToken = tokens.size() - 1; - - while ( tokenCursor <= lastToken ) - { -// std::cout << "tokenCursor = " << tokenCursor << " first prog index = " << (*rewriteOpIndex)->getIndex() << std::endl; - - if( rewriteOpIndex != rewriteOpEnd ) - { - size_t up_to_here = std::min(lastToken,(*rewriteOpIndex)->getIndex()); - while( tokenCursor < up_to_here ) - out << tokens[tokenCursor++]->getText(); - } - while ( rewriteOpIndex != rewriteOpEnd && - tokenCursor == (*rewriteOpIndex)->getIndex() && - tokenCursor <= lastToken ) - { - tokenCursor = (*rewriteOpIndex)->execute(out); - ++rewriteOpIndex; - } - if( tokenCursor <= lastToken ) - out << tokens[tokenCursor++]->getText(); - } - // std::cout << "Handling tail operations # left = " << std::distance(rewriteOpIndex,rewriteOpEnd) << std::endl; - // now see if there are operations (append) beyond last token index - std::for_each( rewriteOpIndex, rewriteOpEnd, executeOperation(out) ); - rewriteOpIndex = rewriteOpEnd; -} - -void TokenStreamRewriteEngine::toDebugStream( std::ostream& out, - size_t start, - size_t end ) const -{ - token_list::const_iterator s = tokens.begin(); - std::advance( s, start ); - token_list::const_iterator e = s; - std::advance( e, end-start ); - std::for_each( s, e, dumpTokenWithIndex(out) ); -} - -void TokenStreamRewriteEngine::addToSortedRewriteList( const std::string& programName, - RewriteOperation* op ) -{ - program_map::iterator rewrites = programs.find(programName); - // check if we got the program already.. - if ( rewrites == programs.end() ) - { - // no prog make a new one... - operation_list ops; - ops.push_back(op); - programs.insert(std::make_pair(programName,ops)); - return; - } - operation_list& prog = rewrites->second; - - if( prog.empty() ) - { - prog.push_back(op); - return; - } - - operation_list::iterator i, end = prog.end(); - i = end; - --i; - // if at or beyond last op's index, just append - if ( op->getIndex() >= (*i)->getIndex() ) { - prog.push_back(op); // append to list of operations - return; - } - i = prog.begin(); - - if( i != end ) - { - operation_list::iterator pos = std::upper_bound( i, end, op, compareOperationIndex() ); - prog.insert(pos,op); - } - else - prog.push_back(op); -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/TokenStreamSelector.cpp b/libs/antlr-2.7.7/src/TokenStreamSelector.cpp deleted file mode 100644 index 254a9a9f9..000000000 --- a/libs/antlr-2.7.7/src/TokenStreamSelector.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/TokenStreamSelector.cpp#2 $ - */ -#include "antlr/TokenStreamSelector.hpp" -#include "antlr/TokenStreamRetryException.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** A token stream MUX (multiplexor) knows about n token streams - * and can multiplex them onto the same channel for use by token - * stream consumer like a parser. This is a way to have multiple - * lexers break up the same input stream for a single parser. - * Or, you can have multiple instances of the same lexer handle - * multiple input streams; this works great for includes. - */ - -TokenStreamSelector::TokenStreamSelector() -: input(0) -{ -} - -TokenStreamSelector::~TokenStreamSelector() -{ -} - -void TokenStreamSelector::addInputStream(TokenStream* stream, const ANTLR_USE_NAMESPACE(std)string& key) -{ - inputStreamNames[key] = stream; -} - -TokenStream* TokenStreamSelector::getCurrentStream() const -{ - return input; -} - -TokenStream* TokenStreamSelector::getStream(const ANTLR_USE_NAMESPACE(std)string& sname) const -{ - inputStreamNames_coll::const_iterator i = inputStreamNames.find(sname); - if (i == inputStreamNames.end()) { - throw ANTLR_USE_NAMESPACE(std)string("TokenStream ")+sname+" not found"; - } - return (*i).second; -} - -RefToken TokenStreamSelector::nextToken() -{ - // keep looking for a token until you don't - // get a retry exception - for (;;) { - try { - return input->nextToken(); - } - catch (TokenStreamRetryException&) { - // just retry "forever" - } - } -} - -TokenStream* TokenStreamSelector::pop() -{ - TokenStream* stream = streamStack.top(); - streamStack.pop(); - select(stream); - return stream; -} - -void TokenStreamSelector::push(TokenStream* stream) -{ - streamStack.push(input); - select(stream); -} - -void TokenStreamSelector::push(const ANTLR_USE_NAMESPACE(std)string& sname) -{ - streamStack.push(input); - select(sname); -} - -void TokenStreamSelector::retry() -{ - throw TokenStreamRetryException(); -} - -/** Set the stream without pushing old stream */ -void TokenStreamSelector::select(TokenStream* stream) -{ - input = stream; -} - -void TokenStreamSelector::select(const ANTLR_USE_NAMESPACE(std)string& sname) -{ - inputStreamNames_coll::const_iterator i = inputStreamNames.find(sname); - if (i == inputStreamNames.end()) { - throw ANTLR_USE_NAMESPACE(std)string("TokenStream ")+sname+" not found"; - } - input = (*i).second; -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - diff --git a/libs/antlr-2.7.7/src/TreeParser.cpp b/libs/antlr-2.7.7/src/TreeParser.cpp deleted file mode 100644 index 7abdef41b..000000000 --- a/libs/antlr-2.7.7/src/TreeParser.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id: //depot/code/org.antlr/release/antlr-2.7.7/lib/cpp/src/TreeParser.cpp#2 $ - */ - -#include "antlr/TreeParser.hpp" -#include "antlr/ASTNULLType.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -/** The AST Null object; the parsing cursor is set to this when - * it is found to be null. This way, we can test the - * token type of a node without having to have tests for null - * everywhere. - */ -RefAST TreeParser::ASTNULL(new ASTNULLType); - -/** Parser error-reporting function can be overridden in subclass */ -void TreeParser::reportError(const RecognitionException& ex) -{ - ANTLR_USE_NAMESPACE(std)cerr << ex.toString().c_str() << ANTLR_USE_NAMESPACE(std)endl; -} - -/** Parser error-reporting function can be overridden in subclass */ -void TreeParser::reportError(const ANTLR_USE_NAMESPACE(std)string& s) -{ - ANTLR_USE_NAMESPACE(std)cerr << "error: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; -} - -/** Parser warning-reporting function can be overridden in subclass */ -void TreeParser::reportWarning(const ANTLR_USE_NAMESPACE(std)string& s) -{ - ANTLR_USE_NAMESPACE(std)cerr << "warning: " << s.c_str() << ANTLR_USE_NAMESPACE(std)endl; -} - -/** Procedure to write out an indent for traceIn and traceOut */ -void TreeParser::traceIndent() -{ - for( int i = 0; i < traceDepth; i++ ) - ANTLR_USE_NAMESPACE(std)cout << " "; -} - -void TreeParser::traceIn(const char* rname, RefAST t) -{ - traceDepth++; - traceIndent(); - - ANTLR_USE_NAMESPACE(std)cout << "> " << rname - << "(" << (t ? t->toString().c_str() : "null") << ")" - << ((inputState->guessing>0)?" [guessing]":"") - << ANTLR_USE_NAMESPACE(std)endl; -} - -void TreeParser::traceOut(const char* rname, RefAST t) -{ - traceIndent(); - - ANTLR_USE_NAMESPACE(std)cout << "< " << rname - << "(" << (t ? t->toString().c_str() : "null") << ")" - << ((inputState->guessing>0)?" [guessing]":"") - << ANTLR_USE_NAMESPACE(std)endl; - - traceDepth--; -} - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif diff --git a/libs/antlr-2.7.7/src/dll.cpp b/libs/antlr-2.7.7/src/dll.cpp deleted file mode 100644 index 020a9d8aa..000000000 --- a/libs/antlr-2.7.7/src/dll.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* ANTLR Translator Generator - * Project led by Terence Parr at http://www.jGuru.com - * Software rights: http://www.antlr.org/license.html - * - * $Id:$ - */ - -/* - * DLL stub for MSVC++. Based upon versions of Stephen Naughton and Michael - * T. Richter - */ - -// RK: Uncommented by instruction of Alexander Lenski -//#if _MSC_VER > 1000 -//# pragma once -//#endif // _MSC_VER > 1000 - -// Exclude rarely-used stuff from Windows headers -#define WIN32_LEAN_AND_MEAN - -#include - -#if defined( _MSC_VER ) && ( _MSC_VER < 1300 ) -# error "DLL Build not supported on old MSVC's" -// Ok it seems to be possible with STLPort in stead of the vanilla MSVC STL -// implementation. This needs some work though. (and don't try it if you're -// not that familiar with compilers/building C++ DLL's in windows) -#endif - -#include -#include "antlr/config.hpp" -#include "antlr/Token.hpp" -#include "antlr/CircularQueue.hpp" - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -namespace antlr { -#endif - -// Take care of necessary implicit instantiations of templates from STL - -// This should take care of MSVC 7.0 -#if defined( _MSC_VER ) && ( _MSC_VER == 1300 ) - -// these come from AST.hpp -template class ANTLR_API ASTRefCount< AST >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< RefAST >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< RefAST >; -//template ANTLR_API int operator<( ASTRefCount< AST >, ASTRefCount< AST > ); - -// ASTFactory.hpp -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< factory_descriptor_* >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const char*, factory_type_ > >; -template struct ANTLR_API ANTLR_USE_NAMESPACE(std)pair< const char*, factory_type_ >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Vector_val< factory_descriptor_*, ANTLR_USE_NAMESPACE(std)allocator< factory_descriptor_* > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< factory_descriptor_* >; - -// BitSet.hpp -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< bool >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Vector_val< bool, ANTLR_USE_NAMESPACE(std)allocator< bool > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< bool >; - -// CharScanner.hpp -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< ANTLR_USE_NAMESPACE(std)string, int > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)_Tree_nod< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >, false > >::_Node >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)_Tree_ptr< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >, false > >::_Nodeptr >; -template struct ANTLR_API ANTLR_USE_NAMESPACE(std)pair< ANTLR_USE_NAMESPACE(std)string, int >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >,false >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree_nod< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >,false > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree_ptr< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >,false > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree_val< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >,false > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, int > >,false > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)map< ANTLR_USE_NAMESPACE(std)string, int, CharScannerLiteralsLess >; - -// CircularQueue.hpp -// RK: it might well be that a load of these ints need to be unsigned ints -// (made some more stuff unsigned) -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< int >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Vector_val< int, ANTLR_USE_NAMESPACE(std)allocator< int > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< int >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< int, ANTLR_USE_NAMESPACE(std)allocator< int > >; -// template ANTLR_API inline int CircularQueue< int >::entries() const; - -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< RefToken >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Vector_val< RefToken, ANTLR_USE_NAMESPACE(std)allocator< RefToken > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< RefToken >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)vector< RefToken, ANTLR_USE_NAMESPACE(std)allocator< RefToken > >; -// template ANTLR_API inline int CircularQueue< RefToken >::entries() const; - -// CommonAST.hpp -template class ANTLR_API ASTRefCount< CommonAST >; - -// CommonASTWithHiddenTokenTypes.hpp -template class ANTLR_API ASTRefCount< CommonASTWithHiddenTokens >; - -// LexerSharedInputState.hpp -template class ANTLR_API RefCount< LexerInputState >; - -// ParserSharedInputState.hpp -template class ANTLR_API RefCount< ParserInputState >; - -// TokenStreamSelector.hpp -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< ANTLR_USE_NAMESPACE(std)string, TokenStream* > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)_Tree_nod< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >, false > >::_Node >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)_Tree_ptr< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >, false > >::_Nodeptr >; -template struct ANTLR_API ANTLR_USE_NAMESPACE(std)pair< ANTLR_USE_NAMESPACE(std)string, TokenStream* >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >,false >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree_nod< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >,false > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree_ptr< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >,false > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree_val< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >,false > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Tree< ANTLR_USE_NAMESPACE(std)_Tmap_traits< ANTLR_USE_NAMESPACE(std)string, TokenStream*, ANTLR_USE_NAMESPACE(std)less< ANTLR_USE_NAMESPACE(std)string >, ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)pair< const ANTLR_USE_NAMESPACE(std)string, TokenStream* > >,false > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)map< ANTLR_USE_NAMESPACE(std)string, TokenStream* >; - -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< TokenStream* >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)allocator< ANTLR_USE_NAMESPACE(std)_Deque_map< TokenStream* , ANTLR_USE_NAMESPACE(std)allocator< TokenStream* > >::_Tptr >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Deque_map< TokenStream*, ANTLR_USE_NAMESPACE(std)allocator< TokenStream* > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)_Deque_val< TokenStream*, ANTLR_USE_NAMESPACE(std)allocator< TokenStream* > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)deque< TokenStream*, ANTLR_USE_NAMESPACE(std)allocator< TokenStream* > >; -template class ANTLR_API ANTLR_USE_NAMESPACE(std)stack< TokenStream*, ANTLR_USE_NAMESPACE(std)deque >; - -#elif defined( _MSC_VER ) && ( _MSC_VER == 1310 ) -// Instantiations for MSVC 7.1 -template class ANTLR_API CircularQueue< int >; -template class ANTLR_API CircularQueue< RefToken >; - -// #else future msvc's - -#endif - -#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE -} -#endif - -BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) -{ - return TRUE; -} diff --git a/libs/json/CMakeLists.txt b/libs/json/CMakeLists.txt new file mode 100644 index 000000000..ec0b7e9df --- /dev/null +++ b/libs/json/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(JSON11_HDR + json.hpp +) diff --git a/libs/json/ChangeLog.md b/libs/json/ChangeLog.md new file mode 100644 index 000000000..92df98220 --- /dev/null +++ b/libs/json/ChangeLog.md @@ -0,0 +1,2661 @@ +# Changelog +All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). + +## [3.10.4](https://github.com/nlohmann/json/releases/tag/3.10.4) (2021-10-16) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.10.3...3.10.4) + +- Compiler error in output serializer due to 'incompatible initializer' [\#3081](https://github.com/nlohmann/json/issues/3081) +- Strange behaviour when using std::sort on std::vector\ [\#3080](https://github.com/nlohmann/json/issues/3080) +- Unhandled exception: nlohmann::detail::parse\_error [\#3078](https://github.com/nlohmann/json/issues/3078) +- explicit constructor with default does not compile [\#3077](https://github.com/nlohmann/json/issues/3077) +- Parse an object but get an array using GCC [\#3076](https://github.com/nlohmann/json/issues/3076) +- Version 3.10.3 breaks backward-compatibility with 3.10.2 [\#3070](https://github.com/nlohmann/json/issues/3070) +- Feature request, Add to\_json/from\_json to align with other to/from binary api. [\#3067](https://github.com/nlohmann/json/issues/3067) +- vcpkg is out of date [\#3066](https://github.com/nlohmann/json/issues/3066) + +- Revert invalid fix [\#3082](https://github.com/nlohmann/json/pull/3082) ([nlohmann](https://github.com/nlohmann)) +- Allow to use get with explicit constructor [\#3079](https://github.com/nlohmann/json/pull/3079) ([nlohmann](https://github.com/nlohmann)) +- fix std::filesystem::path regression [\#3073](https://github.com/nlohmann/json/pull/3073) ([theodelrieu](https://github.com/theodelrieu)) +- Fix Clang version [\#3040](https://github.com/nlohmann/json/pull/3040) ([nlohmann](https://github.com/nlohmann)) +- Fix assertion failure for JSON\_DIAGNOSTICS [\#3037](https://github.com/nlohmann/json/pull/3037) ([carlsmedstad](https://github.com/carlsmedstad)) +- meta: fix is\_compatible/constructible traits [\#3020](https://github.com/nlohmann/json/pull/3020) ([theodelrieu](https://github.com/theodelrieu)) +- Set parent pointers for values inserted via update\(\) \(fixes \#3007\). [\#3008](https://github.com/nlohmann/json/pull/3008) ([AnthonyVH](https://github.com/AnthonyVH)) +- Allow allocators for output\_vector\_adapter [\#2989](https://github.com/nlohmann/json/pull/2989) ([nlohmann](https://github.com/nlohmann)) +- Re-add Clang 12 [\#2986](https://github.com/nlohmann/json/pull/2986) ([nlohmann](https://github.com/nlohmann)) +- Use new Docker image [\#2981](https://github.com/nlohmann/json/pull/2981) ([nlohmann](https://github.com/nlohmann)) +- Fix -Wunused warnings on JSON\_DIAGNOSTICS [\#2976](https://github.com/nlohmann/json/pull/2976) ([gcerretani](https://github.com/gcerretani)) +- Update docset generation script [\#2967](https://github.com/nlohmann/json/pull/2967) ([nlohmann](https://github.com/nlohmann)) + +## [v3.10.3](https://github.com/nlohmann/json/releases/tag/v3.10.3) (2021-10-08) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.10.2...v3.10.3) + +- Parsing an emtpy string returns a string with size 1 instead of expected 0 [\#3057](https://github.com/nlohmann/json/issues/3057) +- Linking error "duplicate symbol: std::type\_info::operator==" on static build with MinGW [\#3042](https://github.com/nlohmann/json/issues/3042) +- Yet another assertion failure when inserting into arrays with JSON\_DIAGNOSTICS set [\#3032](https://github.com/nlohmann/json/issues/3032) +- accept and parse function not work well with a pure number string [\#3029](https://github.com/nlohmann/json/issues/3029) +- push\_back doesn't work for serializing containers [\#3027](https://github.com/nlohmann/json/issues/3027) +- Strange behaviour when creating array with single element [\#3025](https://github.com/nlohmann/json/issues/3025) +- Input ordered\_json doesn't work [\#3023](https://github.com/nlohmann/json/issues/3023) +- Issue iterating through 'items' [\#3021](https://github.com/nlohmann/json/issues/3021) +- Cannot spell the namespace right [\#3015](https://github.com/nlohmann/json/issues/3015) +- JSON Parse error when reading json object from file [\#3011](https://github.com/nlohmann/json/issues/3011) +- Parent pointer not properly set when using update\(\) [\#3007](https://github.com/nlohmann/json/issues/3007) +- Overwriting terminated null character [\#3001](https://github.com/nlohmann/json/issues/3001) +- 'operator =' is ambiguous on VS2017 [\#2997](https://github.com/nlohmann/json/issues/2997) +- JSON Patch for Array Elements [\#2994](https://github.com/nlohmann/json/issues/2994) +- JSON Parse throwing error [\#2983](https://github.com/nlohmann/json/issues/2983) +- to\_{binary format} does not provide a mechanism for specifying a custom allocator for the returned type. [\#2982](https://github.com/nlohmann/json/issues/2982) +- 3.10.1 zip json.hpp has version number 3.10.0 instead of 3.10.1 [\#2973](https://github.com/nlohmann/json/issues/2973) +- Assertion failure when serializing array with JSON\_DIAGNOSTICS set [\#2926](https://github.com/nlohmann/json/issues/2926) + +## [v3.10.2](https://github.com/nlohmann/json/releases/tag/v3.10.2) (2021-08-26) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.10.1...v3.10.2) + +- Annoying -Wundef on new JSON\_DIAGNOSTICS macro [\#2975](https://github.com/nlohmann/json/issues/2975) +- += issue with multiple redirection. [\#2970](https://github.com/nlohmann/json/issues/2970) +- "incomplete type ‘nlohmann::detail::wide\_string\_input\_helper" compilation error [\#2969](https://github.com/nlohmann/json/issues/2969) + +## [v3.10.1](https://github.com/nlohmann/json/releases/tag/v3.10.1) (2021-08-24) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.10.0...v3.10.1) + +- JSON\_DIAGNOSTICS assertion for ordered\_json [\#2962](https://github.com/nlohmann/json/issues/2962) +- Inserting in unordered json using a pointer retains the leading slash [\#2958](https://github.com/nlohmann/json/issues/2958) +- Test \#9: test-cbor test case sample.json fails in debug mode - Stack overflow [\#2955](https://github.com/nlohmann/json/issues/2955) +- 3.10.0 broke at least the Bear project [\#2953](https://github.com/nlohmann/json/issues/2953) +- 2 tests fail in 3.10.0: cmake\_fetch\_content\_configure, cmake\_fetch\_content\_build [\#2951](https://github.com/nlohmann/json/issues/2951) +- ctest \(58+60,/67 cmake\_import\_configure\) fails when build with -D JSON\_Install:BOOL=OFF because of missing nlohmann\_jsonTargets.cmake [\#2946](https://github.com/nlohmann/json/issues/2946) +- Document vcpkg usage [\#2944](https://github.com/nlohmann/json/issues/2944) +- Linker error LNK2005 when compiling \(x64\) json-3.10.0.zip with Visual Studio 2019 16.11.1 [\#2941](https://github.com/nlohmann/json/issues/2941) +- Move Travis jobs to travis-ci.com [\#2938](https://github.com/nlohmann/json/issues/2938) + +- Fixed typo in docs/api/basic\_json/parse.md [\#2968](https://github.com/nlohmann/json/pull/2968) ([mb0202](https://github.com/mb0202)) +- Add link to Homebrew package [\#2966](https://github.com/nlohmann/json/pull/2966) ([nlohmann](https://github.com/nlohmann)) +- Fix parent update for diagnostics with ordered\_json [\#2963](https://github.com/nlohmann/json/pull/2963) ([nlohmann](https://github.com/nlohmann)) +- Set stack size for some unit tests when using MSVC [\#2961](https://github.com/nlohmann/json/pull/2961) ([nlohmann](https://github.com/nlohmann)) +- Add regression test [\#2960](https://github.com/nlohmann/json/pull/2960) ([nlohmann](https://github.com/nlohmann)) +- Update Travis badge [\#2959](https://github.com/nlohmann/json/pull/2959) ([nlohmann](https://github.com/nlohmann)) +- Fix some extra ";" clang warnings [\#2957](https://github.com/nlohmann/json/pull/2957) ([Hallot](https://github.com/Hallot)) +- Add documentation for integration via vcpkg [\#2954](https://github.com/nlohmann/json/pull/2954) ([nlohmann](https://github.com/nlohmann)) +- Avoid duplicate AppVeyor builds [\#2952](https://github.com/nlohmann/json/pull/2952) ([nlohmann](https://github.com/nlohmann)) +- 🚨 fix gdb\_pretty\_printer failure on basic types [\#2950](https://github.com/nlohmann/json/pull/2950) ([senyai](https://github.com/senyai)) +- Add header to use value\_t [\#2948](https://github.com/nlohmann/json/pull/2948) ([nlohmann](https://github.com/nlohmann)) +- Skip some tests if JSON\_Install is not set [\#2947](https://github.com/nlohmann/json/pull/2947) ([nlohmann](https://github.com/nlohmann)) +- Remove outdated json\_unit test binary [\#2945](https://github.com/nlohmann/json/pull/2945) ([nlohmann](https://github.com/nlohmann)) +- Updating the Homebrew Command [\#2943](https://github.com/nlohmann/json/pull/2943) ([amirmasoudabdol](https://github.com/amirmasoudabdol)) + +## [v3.10.0](https://github.com/nlohmann/json/releases/tag/v3.10.0) (2021-08-17) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.9.1...v3.10.0) + +- Latest version 3.9.1 uses throw instead of JSON\_THROW in the amalgamated json.hpp file [\#2934](https://github.com/nlohmann/json/issues/2934) +- Copy to a variable inside a Structure [\#2933](https://github.com/nlohmann/json/issues/2933) +- warning C4068: unknown pragma 'GCC' on MSVC/cl [\#2924](https://github.com/nlohmann/json/issues/2924) +- Errors during ninja test [\#2918](https://github.com/nlohmann/json/issues/2918) +- compiler warning: "not return a value" [\#2917](https://github.com/nlohmann/json/issues/2917) +- Comparison floating points causes warning [\#2909](https://github.com/nlohmann/json/issues/2909) +- Why can't I have std::vector\ testList? [\#2900](https://github.com/nlohmann/json/issues/2900) +- \[json.hpp\] from releases doesnt work [\#2897](https://github.com/nlohmann/json/issues/2897) +- g++ \(11\) -Wuseless-cast gives lots of warnings [\#2893](https://github.com/nlohmann/json/issues/2893) +- Cannot serialize and immediatly deserialize json to/from bson [\#2892](https://github.com/nlohmann/json/issues/2892) +- Floating-point precision conversion error [\#2876](https://github.com/nlohmann/json/issues/2876) +- How to avoid escaping for an already escaped string in .dump\(\) [\#2870](https://github.com/nlohmann/json/issues/2870) +- can't parse std::vector\ [\#2869](https://github.com/nlohmann/json/issues/2869) +- ASAN detects memory leaks [\#2865](https://github.com/nlohmann/json/issues/2865) +- Binary subtype field cannot represent all CBOR tags [\#2863](https://github.com/nlohmann/json/issues/2863) +- string literals possibly being parsed as another type due to the presence of only digits and full-stops [\#2852](https://github.com/nlohmann/json/issues/2852) +- json::parse\(\) works only with absolute paths [\#2851](https://github.com/nlohmann/json/issues/2851) +- Compiler Warnings on Raspberry Pi OS [\#2850](https://github.com/nlohmann/json/issues/2850) +- Braced initialization and aggregate initialization behavior is different for `json::array()` function call. [\#2848](https://github.com/nlohmann/json/issues/2848) +- 3.9.1: test suite is failing [\#2845](https://github.com/nlohmann/json/issues/2845) +- Documentation for macro JSON\_NO\_IO is missing [\#2842](https://github.com/nlohmann/json/issues/2842) +- Assertion failure when inserting into arrays with JSON\_DIAGNOSTICS set [\#2838](https://github.com/nlohmann/json/issues/2838) +- HELP! There is a memory leak in the code?! [\#2837](https://github.com/nlohmann/json/issues/2837) +- Elegant conversion of a 2-D-json array to a standard C++ array [\#2805](https://github.com/nlohmann/json/issues/2805) +- Swift Package Manager support [\#2802](https://github.com/nlohmann/json/issues/2802) +- Referencing a subkey which doesn't exist gives crash [\#2797](https://github.com/nlohmann/json/issues/2797) +- Failed benchmark due to renamed branch [\#2796](https://github.com/nlohmann/json/issues/2796) +- Build Errors with VS 2019 and json Version 3.9.1 when attempting to replicate SAX Example [\#2782](https://github.com/nlohmann/json/issues/2782) +- Value with spaces cannot be parsed [\#2781](https://github.com/nlohmann/json/issues/2781) +- \[Question\] CBOR rfc support. [\#2779](https://github.com/nlohmann/json/issues/2779) +- Using JSON.hpp header file in Visual Studio 2013 \(C++ Project\) [\#2775](https://github.com/nlohmann/json/issues/2775) +- compilation error on clang-8 + C++17 [\#2759](https://github.com/nlohmann/json/issues/2759) +- Undefined symbol EOF [\#2755](https://github.com/nlohmann/json/issues/2755) +- Parsing a string into json object behaves differently under g++ and MinGW compilers. [\#2746](https://github.com/nlohmann/json/issues/2746) +- big git history size [\#2742](https://github.com/nlohmann/json/issues/2742) +- How to get reference of std::vector\ [\#2735](https://github.com/nlohmann/json/issues/2735) +- CMake failure in VS2019 Community [\#2734](https://github.com/nlohmann/json/issues/2734) +- Possibility to use with custom c++ version to use in intel sgx enclaves [\#2730](https://github.com/nlohmann/json/issues/2730) +- Possibility to use without the dependency to file io and streams to use in intel sgx enclaves [\#2728](https://github.com/nlohmann/json/issues/2728) +- error C2784& error C2839... in my visual studio 2015 compiler [\#2726](https://github.com/nlohmann/json/issues/2726) +- `-fno-expection` not respected anymore in 3.9.1 [\#2725](https://github.com/nlohmann/json/issues/2725) +- When exceptions disabled with JSON\_NOEXCEPTION, lib just aborts without any message [\#2724](https://github.com/nlohmann/json/issues/2724) +- Critical error detected c0000374 on windows10 msvc 2019 16.8.5 [\#2710](https://github.com/nlohmann/json/issues/2710) +- unused parameter error/warning [\#2706](https://github.com/nlohmann/json/issues/2706) +- How to store data into a Map from json file [\#2691](https://github.com/nlohmann/json/issues/2691) +- Tests do not compile with pre-release glibc [\#2686](https://github.com/nlohmann/json/issues/2686) +- compile errors .... chromium-style [\#2680](https://github.com/nlohmann/json/issues/2680) +- .dump\(\) not allowing compact form [\#2678](https://github.com/nlohmann/json/issues/2678) +- error: no matching function for call to ‘nlohmann::basic\_json\<\>::value\(int, std::set\&\)’ [\#2671](https://github.com/nlohmann/json/issues/2671) +- Compiler warning: unused parameter [\#2668](https://github.com/nlohmann/json/issues/2668) +- Deserializing to a struct as shown on the project homepage throws compile time errors [\#2665](https://github.com/nlohmann/json/issues/2665) +- Unable to compile on MSVC 2019 with SDL checking enabled: This function or variable may be unsafe [\#2664](https://github.com/nlohmann/json/issues/2664) +- terminating with uncaught exception of type nlohmann::detail::type\_error: \[json.exception.type\_error.302\] type must be array, but is object [\#2661](https://github.com/nlohmann/json/issues/2661) +- unused-parameter on OSX when Diagnostics is off [\#2658](https://github.com/nlohmann/json/issues/2658) +- std::pair wrong serialization [\#2655](https://github.com/nlohmann/json/issues/2655) +- The result of json is\_number\_integer\(\) function is wrong when read a json file [\#2653](https://github.com/nlohmann/json/issues/2653) +- 2 backslash cause problem [\#2652](https://github.com/nlohmann/json/issues/2652) +- No support for using an external/system copy of Hedley [\#2651](https://github.com/nlohmann/json/issues/2651) +- error: incomplete type 'qfloat16' used in type trait expression [\#2650](https://github.com/nlohmann/json/issues/2650) +- Unused variable in exception class when not using improved diagnostics [\#2646](https://github.com/nlohmann/json/issues/2646) +- I am trying to do this - converting from wstring works incorrectly! [\#2642](https://github.com/nlohmann/json/issues/2642) +- Exception 207 On ARM Processor During Literal String Parsing [\#2634](https://github.com/nlohmann/json/issues/2634) +- double free or corruption \(!prev\) error on Json push\_back and write [\#2632](https://github.com/nlohmann/json/issues/2632) +- nlohmann::detail::parse\_error: syntax error while parsing CBOR string: expected length specification \(0x60-0x7B\) or indefinite string type \(0x7F\) [\#2629](https://github.com/nlohmann/json/issues/2629) +- please allow disabling implicit conversions in non-single-file use [\#2621](https://github.com/nlohmann/json/issues/2621) +- Preserve decimal formatting [\#2618](https://github.com/nlohmann/json/issues/2618) +- Visual Studio Visual Assist code issues reported by VA code inspection of file json.hpp [\#2615](https://github.com/nlohmann/json/issues/2615) +- Missing get function and no viable overloaded '=' on mac [\#2610](https://github.com/nlohmann/json/issues/2610) +- corruption when parse from string [\#2603](https://github.com/nlohmann/json/issues/2603) +- Parse from byte-vector results in compile error [\#2602](https://github.com/nlohmann/json/issues/2602) +- Memory leak when working on ARM Linux [\#2601](https://github.com/nlohmann/json/issues/2601) +- Unhandled exception in test-cbor.exe Stack overflow when debugging project with Visual Studio 2019 16.7.7 compiled with c++17 or c++latest [\#2598](https://github.com/nlohmann/json/issues/2598) +- Error in download\_test\_data.vcxproj when compiling with Visual Studio 2019 16.7.7 Professional msbuild on Windows 10 2004 Professional [\#2594](https://github.com/nlohmann/json/issues/2594) +- Warnings C4715 and C4127 when building json-3.9.1 with Visual Studio 2019 16.7.7 [\#2592](https://github.com/nlohmann/json/issues/2592) +- I tried some change to dump\(\) for \[1,2,3...\] [\#2584](https://github.com/nlohmann/json/issues/2584) +- try/catch block does not catch parsing error [\#2579](https://github.com/nlohmann/json/issues/2579) +- Serializing uint64\_t is broken for large values [\#2578](https://github.com/nlohmann/json/issues/2578) +- deserializing arrays should be part of the library [\#2575](https://github.com/nlohmann/json/issues/2575) +- Deserialization to std::array with non-default constructable types fails [\#2574](https://github.com/nlohmann/json/issues/2574) +- Compilation error when trying to use same type for number\_integer\_t and number\_unsigned\_t in basic\_json template specification. [\#2573](https://github.com/nlohmann/json/issues/2573) +- compiler error: directive output may be truncated writing between 2 and 8 bytes [\#2572](https://github.com/nlohmann/json/issues/2572) +- Incorrect convert map to json when key cannot construct an string i.e. int [\#2564](https://github.com/nlohmann/json/issues/2564) +- no matching function for call to ‘nlohmann::basic\_json\<\>::basic\_json\(\\)’ [\#2559](https://github.com/nlohmann/json/issues/2559) +- type\_error factory creates a dangling pointer \(in VisualStudio 2019\) [\#2535](https://github.com/nlohmann/json/issues/2535) +- Cannot assign from ordered\_json vector\ to value in not ordered json [\#2528](https://github.com/nlohmann/json/issues/2528) +- Qt6: Break changes [\#2519](https://github.com/nlohmann/json/issues/2519) +- valgrind memcheck Illegal instruction when use nlohmann::json::parse [\#2518](https://github.com/nlohmann/json/issues/2518) +- Buffer overflow [\#2515](https://github.com/nlohmann/json/issues/2515) +- Including CTest in the top-level CMakeLists.txt sets BUILD\_TESTING=ON for parent projects [\#2513](https://github.com/nlohmann/json/issues/2513) +- Compilation error when using NLOHMANN\_JSON\_SERIALIZE\_ENUM ordered\_json on libc++ [\#2491](https://github.com/nlohmann/json/issues/2491) +- Missing "void insert\( InputIt first, InputIt last \);" overload in nlohmann::ordered\_map [\#2490](https://github.com/nlohmann/json/issues/2490) +- Could not find a package configuration file provided by "nlohmann\_json" [\#2482](https://github.com/nlohmann/json/issues/2482) +- json becomes empty for unknown reason [\#2470](https://github.com/nlohmann/json/issues/2470) +- Using std::wstring as StringType fails compiling [\#2459](https://github.com/nlohmann/json/issues/2459) +- Sample code in GIF slide outdated \(cannot use emplace\(\) with array\) [\#2457](https://github.com/nlohmann/json/issues/2457) +- from\_json\ is treated as an array on latest MSVC [\#2453](https://github.com/nlohmann/json/issues/2453) +- MemorySanitizer: use-of-uninitialized-value [\#2449](https://github.com/nlohmann/json/issues/2449) +- I need help [\#2441](https://github.com/nlohmann/json/issues/2441) +- type conversion failing with clang ext\_vector\_type [\#2436](https://github.com/nlohmann/json/issues/2436) +- json::parse\(\) can't be resolved under specific circumstances [\#2427](https://github.com/nlohmann/json/issues/2427) +- from\_\*\(ptr, len\) deprecation [\#2426](https://github.com/nlohmann/json/issues/2426) +- Error ONLY in release mode [\#2425](https://github.com/nlohmann/json/issues/2425) +- "Custom data source" exemple make no sense [\#2423](https://github.com/nlohmann/json/issues/2423) +- Compile errors [\#2421](https://github.com/nlohmann/json/issues/2421) +- Refuses to compile in project [\#2419](https://github.com/nlohmann/json/issues/2419) +- Compilation failure of tests with C++20 standard \(caused by change of u8 literals\) [\#2413](https://github.com/nlohmann/json/issues/2413) +- No matching function for call to 'input\_adapter' under Xcode of with nlohmann version 3.9.1 [\#2412](https://github.com/nlohmann/json/issues/2412) +- Git tags are not valid semvers [\#2409](https://github.com/nlohmann/json/issues/2409) +- after dump, stderr output disappear [\#2403](https://github.com/nlohmann/json/issues/2403) +- Using custom string. [\#2398](https://github.com/nlohmann/json/issues/2398) +- value\(\) throws unhandled exception for partially specified json object [\#2393](https://github.com/nlohmann/json/issues/2393) +- assertion on runtime causes program to stop when accessing const json with missing key [\#2392](https://github.com/nlohmann/json/issues/2392) +- Usage with -fno-elide-constructors causes dump\(\) output to be array of `null`s [\#2387](https://github.com/nlohmann/json/issues/2387) +- Build fails with clang-cl due to override of CMAKE\_CXX\_COMPILER\(?\) [\#2384](https://github.com/nlohmann/json/issues/2384) +- std::optional not working with primitive types [\#2383](https://github.com/nlohmann/json/issues/2383) +- Unexpected array when initializing a json const& on gcc 4.8.5 using uniform syntax [\#2370](https://github.com/nlohmann/json/issues/2370) +- setprecision support [\#2362](https://github.com/nlohmann/json/issues/2362) +- json::parse\(allow\_exceptions = false\) documentation is misleading. [\#2360](https://github.com/nlohmann/json/issues/2360) +- std::begin and std::end usage without specifying std namespace [\#2359](https://github.com/nlohmann/json/issues/2359) +- Custom object conversion to json hangs in background thread [\#2358](https://github.com/nlohmann/json/issues/2358) +- Add support of nullable fields to NLOHMANN\_DEFINE\_TYPE\_NON\_INTRUSIVE and NLOHMANN\_DEFINE\_TYPE\_INTRUSIVE [\#2356](https://github.com/nlohmann/json/issues/2356) +- the portfile for the vcpkg is not working. [\#2351](https://github.com/nlohmann/json/issues/2351) +- Compiler warns of implicit fallthrough when defining preprocessor macro NDEBUG [\#2348](https://github.com/nlohmann/json/issues/2348) +- Compile error on Intel compiler running in Windows [\#2346](https://github.com/nlohmann/json/issues/2346) +- Build error caused by overwriting CMAKE\_CXX\_COMPILER [\#2343](https://github.com/nlohmann/json/issues/2343) +- Error: an attribute list cannot appear here JSON\_HEDLEY\_DEPRECATED\_FOR [\#2342](https://github.com/nlohmann/json/issues/2342) +- compiler warning [\#2341](https://github.com/nlohmann/json/issues/2341) +- 3.9.0: tests make build non-reproducible [\#2324](https://github.com/nlohmann/json/issues/2324) +- Initialization different between gcc/clang [\#2311](https://github.com/nlohmann/json/issues/2311) +- Attempt to `get()` a numeric value as a type which cannot represent it should throw [\#2310](https://github.com/nlohmann/json/issues/2310) +- Surprising behaviour with overloaded operators [\#2256](https://github.com/nlohmann/json/issues/2256) +- ADL issue in input\_adapter [\#2248](https://github.com/nlohmann/json/issues/2248) +- Output adapters should be templated. [\#2172](https://github.com/nlohmann/json/issues/2172) +- error when using nlohmann::json, std::function and std::bind [\#2147](https://github.com/nlohmann/json/issues/2147) +- Remove undefined behavior for const operator\[\] [\#2111](https://github.com/nlohmann/json/issues/2111) +- json\({}\) gives null instead of empty object with GCC and -std=c++17 [\#2046](https://github.com/nlohmann/json/issues/2046) +- GDB pretty printing support [\#1952](https://github.com/nlohmann/json/issues/1952) +- Always compile tests with all warnings enabled and error out on warnings [\#1798](https://github.com/nlohmann/json/issues/1798) +- Fixes Cppcheck warnings [\#1759](https://github.com/nlohmann/json/issues/1759) +- How to get position info or parser context with custom from\_json\(\) that may throw exceptions? [\#1508](https://github.com/nlohmann/json/issues/1508) +- Suggestion to improve value\(\) accessors with respect to move semantics [\#1275](https://github.com/nlohmann/json/issues/1275) +- Add Key name to Exception [\#932](https://github.com/nlohmann/json/issues/932) + +- Overwork warning flags [\#2936](https://github.com/nlohmann/json/pull/2936) ([nlohmann](https://github.com/nlohmann)) +- Treat MSVC warnings as errors [\#2930](https://github.com/nlohmann/json/pull/2930) ([nlohmann](https://github.com/nlohmann)) +- All: fix warnings when compiling with -Wswitch-enum [\#2927](https://github.com/nlohmann/json/pull/2927) ([fhuberts](https://github.com/fhuberts)) +- Guard GCC pragmas [\#2925](https://github.com/nlohmann/json/pull/2925) ([nlohmann](https://github.com/nlohmann)) +- Supress -Wfloat-equal on intended float comparisions [\#2911](https://github.com/nlohmann/json/pull/2911) ([Finkman](https://github.com/Finkman)) +- Fix binary subtypes [\#2908](https://github.com/nlohmann/json/pull/2908) ([nlohmann](https://github.com/nlohmann)) +- Fix useless-cast warnings [\#2902](https://github.com/nlohmann/json/pull/2902) ([nlohmann](https://github.com/nlohmann)) +- Add regression test [\#2898](https://github.com/nlohmann/json/pull/2898) ([nlohmann](https://github.com/nlohmann)) +- Refactor Unicode tests [\#2889](https://github.com/nlohmann/json/pull/2889) ([nlohmann](https://github.com/nlohmann)) +- CMake cleanup [\#2885](https://github.com/nlohmann/json/pull/2885) ([nlohmann](https://github.com/nlohmann)) +- Avoid string in case of empty CBOR objects [\#2879](https://github.com/nlohmann/json/pull/2879) ([nlohmann](https://github.com/nlohmann)) +- Suppress C4127 warning in unit-json\_pointer.cpp [\#2875](https://github.com/nlohmann/json/pull/2875) ([nlohmann](https://github.com/nlohmann)) +- Fix truncation warning [\#2874](https://github.com/nlohmann/json/pull/2874) ([nlohmann](https://github.com/nlohmann)) +- Fix memory leak in to\_json [\#2872](https://github.com/nlohmann/json/pull/2872) ([nlohmann](https://github.com/nlohmann)) +- Fix assertion failure in diagnostics [\#2866](https://github.com/nlohmann/json/pull/2866) ([nlohmann](https://github.com/nlohmann)) +- Update documentation [\#2861](https://github.com/nlohmann/json/pull/2861) ([nlohmann](https://github.com/nlohmann)) +- Consistency with `using` in README.md [\#2826](https://github.com/nlohmann/json/pull/2826) ([justanotheranonymoususer](https://github.com/justanotheranonymoususer)) +- Properly constrain the basic\_json conversion operator [\#2825](https://github.com/nlohmann/json/pull/2825) ([ldionne](https://github.com/ldionne)) +- Fix CI [\#2817](https://github.com/nlohmann/json/pull/2817) ([nlohmann](https://github.com/nlohmann)) +- Specified git branch for google benchmark fetch in benchmark test [\#2795](https://github.com/nlohmann/json/pull/2795) ([grafail](https://github.com/grafail)) +- Add C++ standards to macOS matrix [\#2790](https://github.com/nlohmann/json/pull/2790) ([nlohmann](https://github.com/nlohmann)) +- Update URLs to HTTPS [\#2789](https://github.com/nlohmann/json/pull/2789) ([TotalCaesar659](https://github.com/TotalCaesar659)) +- Link to Conan Center package added [\#2771](https://github.com/nlohmann/json/pull/2771) ([offa](https://github.com/offa)) +- Keep consistent formatting [\#2770](https://github.com/nlohmann/json/pull/2770) ([jasmcaus](https://github.com/jasmcaus)) +- Add a cmake option to use SYSTEM in target\_include\_directories [\#2762](https://github.com/nlohmann/json/pull/2762) ([jpl-mac](https://github.com/jpl-mac)) +- replace EOF with std::char\_traits\::eof\(\) [\#2756](https://github.com/nlohmann/json/pull/2756) ([nlohmann](https://github.com/nlohmann)) +- Fix typo in README [\#2754](https://github.com/nlohmann/json/pull/2754) ([mortenfyhn](https://github.com/mortenfyhn)) +- Update documentation [\#2749](https://github.com/nlohmann/json/pull/2749) ([nlohmann](https://github.com/nlohmann)) +- Add documentation for numbers [\#2747](https://github.com/nlohmann/json/pull/2747) ([nlohmann](https://github.com/nlohmann)) +- Use Clang 12 in CI [\#2737](https://github.com/nlohmann/json/pull/2737) ([nlohmann](https://github.com/nlohmann)) +- Fixes \#2730 [\#2731](https://github.com/nlohmann/json/pull/2731) ([theShmoo](https://github.com/theShmoo)) +- Possibility to use without the dependency to file io and streams to use in intel sgx enclaves [\#2729](https://github.com/nlohmann/json/pull/2729) ([theShmoo](https://github.com/theShmoo)) +- Update json.hpp [\#2707](https://github.com/nlohmann/json/pull/2707) ([raduteo](https://github.com/raduteo)) +- pkg-config.pc.in: Don't concatenate paths [\#2690](https://github.com/nlohmann/json/pull/2690) ([doronbehar](https://github.com/doronbehar)) +- add more CI steps [\#2689](https://github.com/nlohmann/json/pull/2689) ([nlohmann](https://github.com/nlohmann)) +- Update doctest from 2.4.4 to 2.4.6 \(fixes \#2686\) [\#2687](https://github.com/nlohmann/json/pull/2687) ([musicinmybrain](https://github.com/musicinmybrain)) +- License fix [\#2683](https://github.com/nlohmann/json/pull/2683) ([nlohmann](https://github.com/nlohmann)) +- Update parse\_exceptions.md - correct `json::exception::parse_error` [\#2679](https://github.com/nlohmann/json/pull/2679) ([frasermarlow](https://github.com/frasermarlow)) +- Remove HEDLEY annotation from exception::what\(\) [\#2673](https://github.com/nlohmann/json/pull/2673) ([remyjette](https://github.com/remyjette)) +- Fix amount of entries in the json object [\#2659](https://github.com/nlohmann/json/pull/2659) ([abbaswasim](https://github.com/abbaswasim)) +- Fix missing 1.78 in example in README.md [\#2625](https://github.com/nlohmann/json/pull/2625) ([wawiesel](https://github.com/wawiesel)) +- Add GDB pretty printer [\#2607](https://github.com/nlohmann/json/pull/2607) ([nlohmann](https://github.com/nlohmann)) +- readme: fix tilde character display [\#2582](https://github.com/nlohmann/json/pull/2582) ([bl-ue](https://github.com/bl-ue)) +- Add support for deserialization of STL containers of non-default constructable types \(fixes \#2574\). [\#2576](https://github.com/nlohmann/json/pull/2576) ([AnthonyVH](https://github.com/AnthonyVH)) +- Better diagnostics [\#2562](https://github.com/nlohmann/json/pull/2562) ([nlohmann](https://github.com/nlohmann)) +- CI targets [\#2561](https://github.com/nlohmann/json/pull/2561) ([nlohmann](https://github.com/nlohmann)) +- Add switch to skip non-reproducible tests. [\#2560](https://github.com/nlohmann/json/pull/2560) ([nlohmann](https://github.com/nlohmann)) +- Fix compilation of input\_adapter\(container\) in edge cases [\#2553](https://github.com/nlohmann/json/pull/2553) ([jasujm](https://github.com/jasujm)) +- Allow parsing from std::byte containers [\#2550](https://github.com/nlohmann/json/pull/2550) ([nlohmann](https://github.com/nlohmann)) +- Travis doesn't run any tests in C++17 mode [\#2540](https://github.com/nlohmann/json/pull/2540) ([karzhenkov](https://github.com/karzhenkov)) +- Doctest is updated to v2.4.3 [\#2538](https://github.com/nlohmann/json/pull/2538) ([YarikTH](https://github.com/YarikTH)) +- Fix warnings [\#2537](https://github.com/nlohmann/json/pull/2537) ([nlohmann](https://github.com/nlohmann)) +- Fix a shadowing warning [\#2536](https://github.com/nlohmann/json/pull/2536) ([nlohmann](https://github.com/nlohmann)) +- Clarify license of is\_complete\_type implementation [\#2534](https://github.com/nlohmann/json/pull/2534) ([nlohmann](https://github.com/nlohmann)) +- Do not unconditionally redefine C++14 constructs [\#2533](https://github.com/nlohmann/json/pull/2533) ([nlohmann](https://github.com/nlohmann)) +- Doctest is updated to v2.4.1 [\#2525](https://github.com/nlohmann/json/pull/2525) ([YarikTH](https://github.com/YarikTH)) +- Add MAIN\_PROJECT check for test and install options [\#2514](https://github.com/nlohmann/json/pull/2514) ([globberwops](https://github.com/globberwops)) +- Ranged insert test section is added in unit-ordered\_json.cpp [\#2512](https://github.com/nlohmann/json/pull/2512) ([YarikTH](https://github.com/YarikTH)) +- Add asserts to suppress C28020 [\#2447](https://github.com/nlohmann/json/pull/2447) ([jbzdarkid](https://github.com/jbzdarkid)) +- Change argument name "subtype" in byte\_container\_with\_subtype [\#2444](https://github.com/nlohmann/json/pull/2444) ([linev](https://github.com/linev)) +- 📠add CPM.Cmake example [\#2406](https://github.com/nlohmann/json/pull/2406) ([leozz37](https://github.com/leozz37)) +- Fix move constructor of json\_ref [\#2405](https://github.com/nlohmann/json/pull/2405) ([karzhenkov](https://github.com/karzhenkov)) +- Properly select "Release" build for Travis [\#2375](https://github.com/nlohmann/json/pull/2375) ([karzhenkov](https://github.com/karzhenkov)) +- Update Hedley [\#2367](https://github.com/nlohmann/json/pull/2367) ([nlohmann](https://github.com/nlohmann)) +- Fix and extend documentation of discarded values [\#2363](https://github.com/nlohmann/json/pull/2363) ([nlohmann](https://github.com/nlohmann)) +- Fix typos in documentation [\#2354](https://github.com/nlohmann/json/pull/2354) ([rbuch](https://github.com/rbuch)) +- Remove "\#define private public" from tests [\#2352](https://github.com/nlohmann/json/pull/2352) ([nlohmann](https://github.com/nlohmann)) +- Remove -Wimplicit-fallthrough warning [\#2349](https://github.com/nlohmann/json/pull/2349) ([nlohmann](https://github.com/nlohmann)) +- Fix code to work without exceptions [\#2347](https://github.com/nlohmann/json/pull/2347) ([nlohmann](https://github.com/nlohmann)) +- fix cmake script overwriting compiler path [\#2344](https://github.com/nlohmann/json/pull/2344) ([ongjunjie](https://github.com/ongjunjie)) + +## [v3.9.1](https://github.com/nlohmann/json/releases/tag/v3.9.1) (2020-08-06) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.9.0...v3.9.1) + +- Can't parse not formatted JSON. [\#2340](https://github.com/nlohmann/json/issues/2340) +- parse returns desired array contained in array when JSON text begins with square bracket on gcc 7.5.0 [\#2339](https://github.com/nlohmann/json/issues/2339) +- Unexpected deserialization difference between Mac and Linux [\#2338](https://github.com/nlohmann/json/issues/2338) +- Reading ordered\_json from file causes compile error [\#2331](https://github.com/nlohmann/json/issues/2331) +- ignore\_comment=true fails on multiple consecutive lines starting with comments [\#2330](https://github.com/nlohmann/json/issues/2330) +- Update documentation about Homebrew installation and CMake integration - Homebrew [\#2326](https://github.com/nlohmann/json/issues/2326) +- Chinese character initialize error [\#2325](https://github.com/nlohmann/json/issues/2325) +- json.update and vector\does not work with ordered\_json [\#2315](https://github.com/nlohmann/json/issues/2315) +- Ambiguous call to overloaded function [\#2210](https://github.com/nlohmann/json/issues/2210) + +- Fix fallthrough warning [\#2333](https://github.com/nlohmann/json/pull/2333) ([nlohmann](https://github.com/nlohmann)) +- Fix lexer to properly cope with repeated comments [\#2332](https://github.com/nlohmann/json/pull/2332) ([nlohmann](https://github.com/nlohmann)) +- Fix name of Homebrew formula in documentation [\#2327](https://github.com/nlohmann/json/pull/2327) ([nlohmann](https://github.com/nlohmann)) +- fix typo [\#2320](https://github.com/nlohmann/json/pull/2320) ([wx257osn2](https://github.com/wx257osn2)) +- Fix a bug due to missing overloads in ordered\_map container [\#2319](https://github.com/nlohmann/json/pull/2319) ([nlohmann](https://github.com/nlohmann)) +- cmake: install pkg-config file relative to current\_binary\_dir [\#2318](https://github.com/nlohmann/json/pull/2318) ([eli-schwartz](https://github.com/eli-schwartz)) +- Fixed installation of pkg-config file on other than Ubuntu [\#2314](https://github.com/nlohmann/json/pull/2314) ([xvitaly](https://github.com/xvitaly)) + +## [v3.9.0](https://github.com/nlohmann/json/releases/tag/v3.9.0) (2020-07-27) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.8.0...v3.9.0) + +- Unknown Type Name clang error when using NLOHMANN\_DEFINE\_TYPE\_NON\_INTRUSIVE [\#2313](https://github.com/nlohmann/json/issues/2313) +- Clang 10.0 / GCC 10.1 warnings on disabled exceptions [\#2304](https://github.com/nlohmann/json/issues/2304) +- Application stalls indefinitely with message byte size 10 [\#2293](https://github.com/nlohmann/json/issues/2293) +- linker error [\#2292](https://github.com/nlohmann/json/issues/2292) +- Add support for high-precision numbers in UBJSON encoding [\#2286](https://github.com/nlohmann/json/issues/2286) +- NLOHMANN\_DEFINE\_TYPE\_NON\_INTRUSIVE fails if the length of the argument is 10 [\#2280](https://github.com/nlohmann/json/issues/2280) +- Custom types : MACRO expansion bug [\#2267](https://github.com/nlohmann/json/issues/2267) +- to/from\_json Failing To Convert String [\#2238](https://github.com/nlohmann/json/issues/2238) +- clang 9.0 report warning: unused type alias 'size\_type' \[-Wunused-local-typedef\] [\#2221](https://github.com/nlohmann/json/issues/2221) +- Enormous array created when working with map\ [\#2220](https://github.com/nlohmann/json/issues/2220) +- Can I disable sorting of json values [\#2219](https://github.com/nlohmann/json/issues/2219) +- Getting Qt types to work [\#2217](https://github.com/nlohmann/json/issues/2217) +- Convert to Qt QVariant [\#2216](https://github.com/nlohmann/json/issues/2216) +- How to custom serialize same data type of vector? [\#2215](https://github.com/nlohmann/json/issues/2215) +- json constructor does not support std::optional [\#2214](https://github.com/nlohmann/json/issues/2214) +- Failing to Parse Valid JSON [\#2209](https://github.com/nlohmann/json/issues/2209) +- \(De-\)Serialization of std::variant with namespaces [\#2208](https://github.com/nlohmann/json/issues/2208) +- Addint support for complex type [\#2207](https://github.com/nlohmann/json/issues/2207) +- array\_index possible out of range [\#2205](https://github.com/nlohmann/json/issues/2205) +- Object deserialized as array [\#2204](https://github.com/nlohmann/json/issues/2204) +- Sending to a function a reference to a sub-branch [\#2200](https://github.com/nlohmann/json/issues/2200) +- How to Serialize derived class to JSON object? [\#2199](https://github.com/nlohmann/json/issues/2199) +- JSON incorrectly serialized [\#2198](https://github.com/nlohmann/json/issues/2198) +- Exception Unhandled out\_of\_range error [\#2197](https://github.com/nlohmann/json/issues/2197) +- msgpack serialisation : float is treated as 64bit float, not 32bit float. [\#2196](https://github.com/nlohmann/json/issues/2196) +- Is it possible to use compile-time type guarantees for JSON structures? [\#2195](https://github.com/nlohmann/json/issues/2195) +- Question : performance against python dict [\#2194](https://github.com/nlohmann/json/issues/2194) +- vs2017 compile error [\#2192](https://github.com/nlohmann/json/issues/2192) +- Check if a key exists [\#2191](https://github.com/nlohmann/json/issues/2191) +- Failed to run tests due to missing test data on builders without Internet access [\#2190](https://github.com/nlohmann/json/issues/2190) +- 3.8.0: unit-cbor.cpp test failures [\#2189](https://github.com/nlohmann/json/issues/2189) +- 'nlohmann/json.hpp' file not found [\#2188](https://github.com/nlohmann/json/issues/2188) +- How to send json data over the wire? [\#2185](https://github.com/nlohmann/json/issues/2185) +- Ubuntu 16 not supporting nlohmann/json? [\#2184](https://github.com/nlohmann/json/issues/2184) +- .get\ causing emdash errors [\#2180](https://github.com/nlohmann/json/issues/2180) +- Object properties should not be re-sorted alphabetically [\#2179](https://github.com/nlohmann/json/issues/2179) +- Custom type registration : instrusive API [\#2175](https://github.com/nlohmann/json/issues/2175) +- Many version of the function "void to\_json\(json& j, const MyStruct& struct\)" [\#2171](https://github.com/nlohmann/json/issues/2171) +- How should strings be escaped? [\#2155](https://github.com/nlohmann/json/issues/2155) +- Adding a value to an existing json puts it at the beginning instead of the end [\#2149](https://github.com/nlohmann/json/issues/2149) +- The header file is big, can we use what we need. [\#2134](https://github.com/nlohmann/json/issues/2134) +- Changing the default format for unordered\_map \(or other set\) [\#2132](https://github.com/nlohmann/json/issues/2132) +- Getting size of deserialized bson document [\#2131](https://github.com/nlohmann/json/issues/2131) +- implicit conversion failure [\#2128](https://github.com/nlohmann/json/issues/2128) +- Error thrown when parsing in a subclass [\#2124](https://github.com/nlohmann/json/issues/2124) +- explicit conversion to string not considered for std::map keys in GCC8 [\#2096](https://github.com/nlohmann/json/issues/2096) +- Add support for JSONC [\#2061](https://github.com/nlohmann/json/issues/2061) +- Library provides template arg for string\_type but assumes std::string in some places [\#2059](https://github.com/nlohmann/json/issues/2059) +- incremental parsing with sax\_parser [\#2030](https://github.com/nlohmann/json/issues/2030) +- Question about flatten and unflatten [\#1989](https://github.com/nlohmann/json/issues/1989) +- CBOR parser doesn't skip tags [\#1968](https://github.com/nlohmann/json/issues/1968) +- Compilation failure using Clang on Windows [\#1898](https://github.com/nlohmann/json/issues/1898) +- Fail to build when including json.hpp as a system include [\#1818](https://github.com/nlohmann/json/issues/1818) +- Parsing string into json doesn't preserve the order correctly. [\#1817](https://github.com/nlohmann/json/issues/1817) +- \[C++17\] Allow std::optional to convert to nlohmann::json [\#1749](https://github.com/nlohmann/json/issues/1749) +- How can I save json object in file in order? [\#1717](https://github.com/nlohmann/json/issues/1717) +- Support for Comments [\#1513](https://github.com/nlohmann/json/issues/1513) +- clang compiler: error : unknown type name 'not' [\#1119](https://github.com/nlohmann/json/issues/1119) +- dump\(\) without alphabetical order [\#1106](https://github.com/nlohmann/json/issues/1106) +- operator T\(\) considered harmful [\#958](https://github.com/nlohmann/json/issues/958) +- Order of the elements in JSON object [\#952](https://github.com/nlohmann/json/issues/952) +- How to prevent alphabetical sorting of data? [\#727](https://github.com/nlohmann/json/issues/727) +- Why is an object ordering values by Alphabetical Order? [\#660](https://github.com/nlohmann/json/issues/660) +- Feature request: Comments [\#597](https://github.com/nlohmann/json/issues/597) +- Head Elements Sorting [\#543](https://github.com/nlohmann/json/issues/543) +- Automatic ordered JSON [\#424](https://github.com/nlohmann/json/issues/424) +- Support for comments. [\#376](https://github.com/nlohmann/json/issues/376) +- Optional comment support. [\#363](https://github.com/nlohmann/json/issues/363) +- Strip comments / Minify [\#294](https://github.com/nlohmann/json/issues/294) +- maintaining order of keys during iteration [\#106](https://github.com/nlohmann/json/issues/106) + +- Update documentation [\#2312](https://github.com/nlohmann/json/pull/2312) ([nlohmann](https://github.com/nlohmann)) +- Fix bug in CBOR tag handling [\#2308](https://github.com/nlohmann/json/pull/2308) ([nlohmann](https://github.com/nlohmann)) +- added inline to NLOHMANN\_DEFINE\_TYPE\_NON\_INTRUSIVE macro [\#2306](https://github.com/nlohmann/json/pull/2306) ([jwittbrodt](https://github.com/jwittbrodt)) +- fixes unused variable 'ex' for \#2304 [\#2305](https://github.com/nlohmann/json/pull/2305) ([AODQ](https://github.com/AODQ)) +- Cleanup [\#2303](https://github.com/nlohmann/json/pull/2303) ([nlohmann](https://github.com/nlohmann)) +- Add test with multiple translation units [\#2301](https://github.com/nlohmann/json/pull/2301) ([nlohmann](https://github.com/nlohmann)) +- Merge GitHub actions [\#2300](https://github.com/nlohmann/json/pull/2300) ([nlohmann](https://github.com/nlohmann)) +- Fix unused parameter [\#2299](https://github.com/nlohmann/json/pull/2299) ([nlohmann](https://github.com/nlohmann)) +- Add support for high-precision numbers in UBJSON encoding [\#2297](https://github.com/nlohmann/json/pull/2297) ([nlohmann](https://github.com/nlohmann)) +- fix eof for get\_binary and get\_string [\#2294](https://github.com/nlohmann/json/pull/2294) ([jprochazk](https://github.com/jprochazk)) +- Serialisation macros: increase upper bound on number of member variables [\#2287](https://github.com/nlohmann/json/pull/2287) ([pfeatherstone](https://github.com/pfeatherstone)) +- add inline specifier for detail::combine [\#2285](https://github.com/nlohmann/json/pull/2285) ([T0b1-iOS](https://github.com/T0b1-iOS)) +- Add static assertion for missing binary function in SAX interface [\#2282](https://github.com/nlohmann/json/pull/2282) ([nlohmann](https://github.com/nlohmann)) +- Add test for target\_include\_directories [\#2279](https://github.com/nlohmann/json/pull/2279) ([nlohmann](https://github.com/nlohmann)) +- Clean up maintainer Makefiles and fix some linter warnings [\#2274](https://github.com/nlohmann/json/pull/2274) ([nlohmann](https://github.com/nlohmann)) +- Add option to ignore CBOR tags [\#2273](https://github.com/nlohmann/json/pull/2273) ([nlohmann](https://github.com/nlohmann)) +- Hash function without allocation [\#2269](https://github.com/nlohmann/json/pull/2269) ([nlohmann](https://github.com/nlohmann)) +- Add ClangCL for MSVC [\#2268](https://github.com/nlohmann/json/pull/2268) ([t-b](https://github.com/t-b)) +- Makefile: Always use SED variable [\#2264](https://github.com/nlohmann/json/pull/2264) ([t-b](https://github.com/t-b)) +- Add Xcode 12 CI [\#2262](https://github.com/nlohmann/json/pull/2262) ([nlohmann](https://github.com/nlohmann)) +- Make library work with Clang on Windows [\#2259](https://github.com/nlohmann/json/pull/2259) ([nlohmann](https://github.com/nlohmann)) +- Add ordered\_json specialization with ordered object keys [\#2258](https://github.com/nlohmann/json/pull/2258) ([nlohmann](https://github.com/nlohmann)) +- Add pkg-config file [\#2253](https://github.com/nlohmann/json/pull/2253) ([ericonr](https://github.com/ericonr)) +- Fix regression from \#2181 [\#2251](https://github.com/nlohmann/json/pull/2251) ([nlohmann](https://github.com/nlohmann)) +- Tag binary values in cbor if set [\#2244](https://github.com/nlohmann/json/pull/2244) ([matthewbauer](https://github.com/matthewbauer)) +- Make assert configurable via JSON\_ASSERT [\#2242](https://github.com/nlohmann/json/pull/2242) ([nlohmann](https://github.com/nlohmann)) +- Add specialization of get\_to [\#2233](https://github.com/nlohmann/json/pull/2233) ([nlohmann](https://github.com/nlohmann)) +- Refine documentation of error\_handler parameter [\#2232](https://github.com/nlohmann/json/pull/2232) ([nlohmann](https://github.com/nlohmann)) +- Simplify conversion from/to custom types [\#2225](https://github.com/nlohmann/json/pull/2225) ([nlohmann](https://github.com/nlohmann)) +- Remove unused typedefs [\#2224](https://github.com/nlohmann/json/pull/2224) ([nlohmann](https://github.com/nlohmann)) +- Enable CMake policy CMP0077 [\#2222](https://github.com/nlohmann/json/pull/2222) ([alexreinking](https://github.com/alexreinking)) +- Add option to ignore comments in parse/accept functions [\#2212](https://github.com/nlohmann/json/pull/2212) ([nlohmann](https://github.com/nlohmann)) +- Fix Clang-Tidy warnings [\#2211](https://github.com/nlohmann/json/pull/2211) ([nlohmann](https://github.com/nlohmann)) +- Simple ordered\_json that works on all supported compilers [\#2206](https://github.com/nlohmann/json/pull/2206) ([gatopeich](https://github.com/gatopeich)) +- Use unsigned indizies for array index in json pointer [\#2203](https://github.com/nlohmann/json/pull/2203) ([t-b](https://github.com/t-b)) +- Add option to not rely on Internet connectivity during test stage [\#2202](https://github.com/nlohmann/json/pull/2202) ([nlohmann](https://github.com/nlohmann)) +- Serialize floating-point numbers with 32 bit when possible \(MessagePack\) [\#2201](https://github.com/nlohmann/json/pull/2201) ([nlohmann](https://github.com/nlohmann)) +- Fix consistency in function `int_to_string()` [\#2193](https://github.com/nlohmann/json/pull/2193) ([dota17](https://github.com/dota17)) +- Fix issue\#1275 [\#2181](https://github.com/nlohmann/json/pull/2181) ([dota17](https://github.com/dota17)) +- C++20 support by removing swap specialization [\#2176](https://github.com/nlohmann/json/pull/2176) ([gracicot](https://github.com/gracicot)) +- Feat/explicit conversion operator [\#1559](https://github.com/nlohmann/json/pull/1559) ([theodelrieu](https://github.com/theodelrieu)) + +## [v3.8.0](https://github.com/nlohmann/json/releases/tag/v3.8.0) (2020-06-14) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.7.3...v3.8.0) + +- sorry delete this issue, i'm stupid [\#2187](https://github.com/nlohmann/json/issues/2187) +- Append to a std::nlohmann::json type [\#2186](https://github.com/nlohmann/json/issues/2186) +- Some troubles to compile the last revision [\#2177](https://github.com/nlohmann/json/issues/2177) +- ​\#​ Top level CMakeLists.txt​ +​project​\(FOO\) +... +​option​\(FOO\_USE\_EXTERNAL\_JSON ​"Use an external JSON library"​ ​OFF​\) +... +​add\_subdirectory​\(thirdparty\) +... +​add\_library​\(foo ...\) +... +​\#​ Note that the namespaced target will always be available regardless of the​ +​\#​ import method​ +​target\_link\_libraries​\(foo ​PRIVATE​ nlohmann\_json::nlohmann\_json\) [\#2170](https://github.com/nlohmann/json/issues/2170) +- https://www.github.com/nlohmann/json/tree/develop/include%2Fnlohmann%2Fjson\_fwd.hpp [\#2169](https://github.com/nlohmann/json/issues/2169) +- templated from\_json of non primitive types causes gcc error [\#2168](https://github.com/nlohmann/json/issues/2168) +- few warnings/errors in copy assignment [\#2167](https://github.com/nlohmann/json/issues/2167) +- Different output when upgrading from clang 9 to clang 10 [\#2166](https://github.com/nlohmann/json/issues/2166) +- Cannot build with VS 2019 / C++17 [\#2163](https://github.com/nlohmann/json/issues/2163) +- Q: When I received an illegal string,How the program knows? [\#2162](https://github.com/nlohmann/json/issues/2162) +- Problem while reading a json file [\#2161](https://github.com/nlohmann/json/issues/2161) +- converting std::chrono::system\_clock::time\_point to json. [\#2159](https://github.com/nlohmann/json/issues/2159) +- how to parse vector\ format [\#2157](https://github.com/nlohmann/json/issues/2157) +- nlohmann::json and =nullptr [\#2156](https://github.com/nlohmann/json/issues/2156) +- test-cbor fails [\#2154](https://github.com/nlohmann/json/issues/2154) +- Accessing array inside array syntax? [\#2151](https://github.com/nlohmann/json/issues/2151) +- Best way to catch errors when querying json [\#2150](https://github.com/nlohmann/json/issues/2150) +- JSON Data Mapping Key-Value from other Key-Value [\#2148](https://github.com/nlohmann/json/issues/2148) +- Conflicts with std \ compiling with GCC 10 [\#2146](https://github.com/nlohmann/json/issues/2146) +- Incorrect CMake FetchContent example [\#2142](https://github.com/nlohmann/json/issues/2142) +- Help for a Beginner? [\#2141](https://github.com/nlohmann/json/issues/2141) +- Read Json from File [\#2139](https://github.com/nlohmann/json/issues/2139) +- How to feed a predefined integer value into json string [\#2138](https://github.com/nlohmann/json/issues/2138) +- getting json array inside json object [\#2135](https://github.com/nlohmann/json/issues/2135) +- Add .contains example to doc [\#2133](https://github.com/nlohmann/json/issues/2133) +- Is it safe to return string.c\_str\(\) received from get\(\)? [\#2130](https://github.com/nlohmann/json/issues/2130) +- GCC 10: Compilation error when including any before including json header in C++17 mode [\#2129](https://github.com/nlohmann/json/issues/2129) +- Intersection of two json files [\#2127](https://github.com/nlohmann/json/issues/2127) +- App crashes when dump method called for non ascii chars. [\#2126](https://github.com/nlohmann/json/issues/2126) +- iterator based erase method [\#2122](https://github.com/nlohmann/json/issues/2122) +- quick and convenient api to get/set nested json values [\#2120](https://github.com/nlohmann/json/issues/2120) +- assigning nullptr to std::string [\#2118](https://github.com/nlohmann/json/issues/2118) +- usless\_cast warnings with gcc 9.3 and 10.1 \(C++17\) [\#2114](https://github.com/nlohmann/json/issues/2114) +- clang 10 warning [\#2113](https://github.com/nlohmann/json/issues/2113) +- Possible incorrect \_MSC\_VER reference [\#2112](https://github.com/nlohmann/json/issues/2112) +- warning under gcc 10.1 [\#2110](https://github.com/nlohmann/json/issues/2110) +- Wdeprecated-declarations from GCC v10.1.0 [\#2109](https://github.com/nlohmann/json/issues/2109) +- Global std::vector from json [\#2108](https://github.com/nlohmann/json/issues/2108) +- heap-buffer-overflow when using nlohmann/json, ASAN, and gtest [\#2107](https://github.com/nlohmann/json/issues/2107) +- exception 0x770DC5AF when i read an special char in json file [\#2106](https://github.com/nlohmann/json/issues/2106) +- json::parse\(\) fails to parse a dump\(2,' '\) output, yet does successfully parse dump\(\) [\#2105](https://github.com/nlohmann/json/issues/2105) +- run test-udt error in MSVC 19.16.27034.0 [\#2103](https://github.com/nlohmann/json/issues/2103) +- Unable to dump to stringstream [\#2102](https://github.com/nlohmann/json/issues/2102) +- Can't ad an object in another objet [\#2101](https://github.com/nlohmann/json/issues/2101) +- Implicit conversion causes "cannot use operator\[\] with a string argument with string" [\#2098](https://github.com/nlohmann/json/issues/2098) +- C++20: char8\_t [\#2097](https://github.com/nlohmann/json/issues/2097) +- Compilation issues when included in project [\#2094](https://github.com/nlohmann/json/issues/2094) +- string value with null character causes infinite loop [\#2093](https://github.com/nlohmann/json/issues/2093) +- corrupted size vs. prev\_size \(aborted\) [\#2092](https://github.com/nlohmann/json/issues/2092) +- Get string field content without return std::string copy [\#2091](https://github.com/nlohmann/json/issues/2091) +- JSON Comments \(JSON 5\) [\#2090](https://github.com/nlohmann/json/issues/2090) +- Remove \#include \ [\#2089](https://github.com/nlohmann/json/issues/2089) +- JSON library as a git submodule [\#2088](https://github.com/nlohmann/json/issues/2088) +- Apple Clang 11.0.3 on MacOS Catalina 10.15.4 not compiling [\#2087](https://github.com/nlohmann/json/issues/2087) +- Value function return empty object even if it exist [\#2086](https://github.com/nlohmann/json/issues/2086) +- Cannot debug but Run works [\#2085](https://github.com/nlohmann/json/issues/2085) +- Question about serialization. [\#2084](https://github.com/nlohmann/json/issues/2084) +- How to include in an external project [\#2083](https://github.com/nlohmann/json/issues/2083) +- Missing tests for binary values [\#2082](https://github.com/nlohmann/json/issues/2082) +- How to override default string serialization? [\#2079](https://github.com/nlohmann/json/issues/2079) +- Can't have a json type as a property in an arbitrary type [\#2078](https://github.com/nlohmann/json/issues/2078) +- New release? [\#2075](https://github.com/nlohmann/json/issues/2075) +- CMake FetchContent \> Updating the documentation? [\#2073](https://github.com/nlohmann/json/issues/2073) +- How to convert STL Vector \(of user defined type\) to Json [\#2072](https://github.com/nlohmann/json/issues/2072) +- how to make an array of objects [\#2070](https://github.com/nlohmann/json/issues/2070) +- ‘\_\_int64’ was not declared [\#2068](https://github.com/nlohmann/json/issues/2068) +- \[json.exception.type\_error.317\] cannot serialize binary data to text JSON [\#2067](https://github.com/nlohmann/json/issues/2067) +- Unexpected end of input; expected '\[', '{', or a literal [\#2066](https://github.com/nlohmann/json/issues/2066) +- Json structure can be nested? [\#2065](https://github.com/nlohmann/json/issues/2065) +- Bug: returning reference to local temporary object [\#2064](https://github.com/nlohmann/json/issues/2064) +- Allow to use non strict parsing [\#2063](https://github.com/nlohmann/json/issues/2063) +- Crashing on json::at [\#2062](https://github.com/nlohmann/json/issues/2062) +- How to convert a const std::vector\ message to a json, to be able to parse it and extract information from it? Can you point to any examples? [\#2058](https://github.com/nlohmann/json/issues/2058) +- Nice library [\#2057](https://github.com/nlohmann/json/issues/2057) +- json.hpp:15372:22: error: expected unqualified-id if \(not std::isfinite\(x\)\): Started getting this bug after updating my XCode [\#2056](https://github.com/nlohmann/json/issues/2056) +- Confused as how I can extract the values from the JSON object. [\#2055](https://github.com/nlohmann/json/issues/2055) +- Warnings with GCC 10 [\#2052](https://github.com/nlohmann/json/issues/2052) +- Warnings with Clang 10 [\#2049](https://github.com/nlohmann/json/issues/2049) +- Update doctest [\#2048](https://github.com/nlohmann/json/issues/2048) +- Unclear error message: "cannot use operator\[\] with a string argument with array" [\#2047](https://github.com/nlohmann/json/issues/2047) +- Serializing std::variant\\> [\#2045](https://github.com/nlohmann/json/issues/2045) +- Crash when parse big jsonfile [\#2042](https://github.com/nlohmann/json/issues/2042) +- How to check if a key exists without silently generating null objects on the path [\#2041](https://github.com/nlohmann/json/issues/2041) +- Crash when traversing over items\(\) of temporary json objects [\#2040](https://github.com/nlohmann/json/issues/2040) +- How to parse multiple line value ? [\#2039](https://github.com/nlohmann/json/issues/2039) +- SAX API uses unsigned std::size\_t but -1 if element size is not known; [\#2037](https://github.com/nlohmann/json/issues/2037) +- How to parse big decimal data [\#2036](https://github.com/nlohmann/json/issues/2036) +- how use template \ struct adl\_serializer [\#2035](https://github.com/nlohmann/json/issues/2035) +- auto iterator returned by find to handle value depending if is string or numeric. [\#2032](https://github.com/nlohmann/json/issues/2032) +- pass find returned iterator to numeric variable. [\#2031](https://github.com/nlohmann/json/issues/2031) +- Parse error on valid json file [\#2029](https://github.com/nlohmann/json/issues/2029) +- Is here any elegant way to combine serialization and deserialization code? [\#2028](https://github.com/nlohmann/json/issues/2028) +- Notes about dump function [\#2027](https://github.com/nlohmann/json/issues/2027) +- Different JSON printouts for empty dictionary on Linux and Mac. [\#2026](https://github.com/nlohmann/json/issues/2026) +- easier way to get exception reason out of json\_sax\_dom\_callback\_parser without exceptions [\#2024](https://github.com/nlohmann/json/issues/2024) +- Using fifo\_map with base class and derived class [\#2023](https://github.com/nlohmann/json/issues/2023) +- Error reading JSON File [\#2022](https://github.com/nlohmann/json/issues/2022) +- Parse causing crash on android. Cannot catch. [\#2021](https://github.com/nlohmann/json/issues/2021) +- Extra backslashes in nested json [\#2020](https://github.com/nlohmann/json/issues/2020) +- How to create patch for merge\_patch input ? [\#2018](https://github.com/nlohmann/json/issues/2018) +- CppUTest/include/CppUTestExt/MockSupport.h:40: error: default argument for ‘MockFailureReporter\* failureReporterForThisCall’ has type ‘void\*’ [\#2017](https://github.com/nlohmann/json/issues/2017) +- including another file [\#2016](https://github.com/nlohmann/json/issues/2016) +- GNU PREREQ Error with gcc 9.3.0 [\#2015](https://github.com/nlohmann/json/issues/2015) +- Parse error: json.exception.parse\_error.101 - invalid string: ill-formed UTF-8 byte [\#2014](https://github.com/nlohmann/json/issues/2014) +- Add more flexibility to basic\_json's ObjectType \(and ArrayType\) [\#2013](https://github.com/nlohmann/json/issues/2013) +- afl persistent mode [\#2012](https://github.com/nlohmann/json/issues/2012) +- Compiler Errors under VS2019 in Appveyor CI [\#2009](https://github.com/nlohmann/json/issues/2009) +- Another compilation failure with Visual Studio [\#2007](https://github.com/nlohmann/json/issues/2007) +- Implicit cast to std::string broken again with VS2019 16.5.0 [\#2006](https://github.com/nlohmann/json/issues/2006) +- error: no matching member function for call to 'AddRaw' [\#2005](https://github.com/nlohmann/json/issues/2005) +- When I re-create an object again after the network request, an error is reported [\#2003](https://github.com/nlohmann/json/issues/2003) +- How to merge \(and not replace\) different Json::Value objects in jsoncpp [\#2001](https://github.com/nlohmann/json/issues/2001) +- scalar transforms to list [\#2000](https://github.com/nlohmann/json/issues/2000) +- Dump JSON containing multibyte characters [\#1999](https://github.com/nlohmann/json/issues/1999) +- Build error when modify value [\#1998](https://github.com/nlohmann/json/issues/1998) +- How do i include a vector of pointers in my json? [\#1997](https://github.com/nlohmann/json/issues/1997) +- Compiler error wrt incomplete types changed in gcc8.3.0-26 [\#1996](https://github.com/nlohmann/json/issues/1996) +- NaN-like comparison behavior of discarded is inconvenient [\#1988](https://github.com/nlohmann/json/issues/1988) +- Maintaining JSON package in my CMake [\#1987](https://github.com/nlohmann/json/issues/1987) +- reading int number and string number [\#1986](https://github.com/nlohmann/json/issues/1986) +- Build error: keyword is hidden by macro definition! [\#1985](https://github.com/nlohmann/json/issues/1985) +- JSON patch diff for op=add formation is not as per standard \(RFC 6902\) [\#1983](https://github.com/nlohmann/json/issues/1983) +- json\_pointer.contains\(\) exception is incorrectly raised [\#1982](https://github.com/nlohmann/json/issues/1982) +- Error with non existing key [\#1981](https://github.com/nlohmann/json/issues/1981) +- Closed [\#1978](https://github.com/nlohmann/json/issues/1978) +- Where is the library built and what is the name? [\#1977](https://github.com/nlohmann/json/issues/1977) +- The cmake\_import example does not build [\#1976](https://github.com/nlohmann/json/issues/1976) +- Dumping core when reading invalid file [\#1975](https://github.com/nlohmann/json/issues/1975) +- Abort in dump\(\) method [\#1973](https://github.com/nlohmann/json/issues/1973) +- Unclear docs regarding parser\_callback\_t callbacks [\#1972](https://github.com/nlohmann/json/issues/1972) +- Possible memory leak on push\_back [\#1971](https://github.com/nlohmann/json/issues/1971) +- Is it possible to get a safe mutable reference/pointer to internal variant used in nlohmann json? [\#1970](https://github.com/nlohmann/json/issues/1970) +- Getting a flatten json to map\ [\#1957](https://github.com/nlohmann/json/issues/1957) +- forced type conversion or lexical cast without exception. [\#1955](https://github.com/nlohmann/json/issues/1955) +- Add json\_view type support to avoid excessive copying [\#1954](https://github.com/nlohmann/json/issues/1954) +- Adding "examples" section for real-life usages [\#1953](https://github.com/nlohmann/json/issues/1953) +- Add nlohmann::json::key\_type [\#1951](https://github.com/nlohmann/json/issues/1951) +- cannot use operator\[\] with a string argument with string [\#1949](https://github.com/nlohmann/json/issues/1949) +- std::ifstream \>\> json error [\#1948](https://github.com/nlohmann/json/issues/1948) +- Cannot update json data in an iterator? [\#1947](https://github.com/nlohmann/json/issues/1947) +- How can i build this library in VS 2017? [\#1943](https://github.com/nlohmann/json/issues/1943) +- json\_pointer.contains\(\) exceptions when path not found [\#1942](https://github.com/nlohmann/json/issues/1942) +- Nested objects serialize/deserialize [\#1941](https://github.com/nlohmann/json/issues/1941) +- Compile warning on architectures that are not x86 [\#1939](https://github.com/nlohmann/json/issues/1939) +- Version of nlohmann-json-dev in debian packages [\#1938](https://github.com/nlohmann/json/issues/1938) +- Create a json object for every cycle [\#1937](https://github.com/nlohmann/json/issues/1937) +- How to get the object name? [\#1936](https://github.com/nlohmann/json/issues/1936) +- Reserve and resize function for basic json [\#1935](https://github.com/nlohmann/json/issues/1935) +- How to use json parse in tsl::ordread\_map? [\#1934](https://github.com/nlohmann/json/issues/1934) +- C++14 support is not enabled with msvc2015 [\#1932](https://github.com/nlohmann/json/issues/1932) +- Need help with to\_json for derived class, keep getting "cannot use operator" [\#1931](https://github.com/nlohmann/json/issues/1931) +- How to handle std::vector\ [\#1930](https://github.com/nlohmann/json/issues/1930) +- Heap corruption issue [\#1929](https://github.com/nlohmann/json/issues/1929) +- Add `std::wistream` support. [\#1928](https://github.com/nlohmann/json/issues/1928) +- This i can write and read any file thanks [\#1927](https://github.com/nlohmann/json/issues/1927) +- How can I get this simple example working? [\#1926](https://github.com/nlohmann/json/issues/1926) +- emplace\_back does not seems to work with the int 0 [\#1925](https://github.com/nlohmann/json/issues/1925) +- Why nlohmann does not release memory [\#1924](https://github.com/nlohmann/json/issues/1924) +- Is it possible to have template `json::parse` with `noexcept` specifier? [\#1922](https://github.com/nlohmann/json/issues/1922) +- JSON to wstring? [\#1921](https://github.com/nlohmann/json/issues/1921) +- GCC 10 tests build failure [\#1920](https://github.com/nlohmann/json/issues/1920) +- Size of binary json representations [\#1919](https://github.com/nlohmann/json/issues/1919) +- Accessing strings \(for example in keys or values\) without having the lib create a copy of it. [\#1916](https://github.com/nlohmann/json/issues/1916) +- operator== documentation should show how to apply custom comparison function [\#1915](https://github.com/nlohmann/json/issues/1915) +- char8\_t and std::u8string support [\#1914](https://github.com/nlohmann/json/issues/1914) +- std::is\_pod is deprecated in C++20 [\#1913](https://github.com/nlohmann/json/issues/1913) +- Incomplete types reported by \(experimental\) GCC10 [\#1912](https://github.com/nlohmann/json/issues/1912) +- Compile warnings on MSVC 14.2 [\#1911](https://github.com/nlohmann/json/issues/1911) +- How to parse json file with type composition of std::optional and std::variant [\#1910](https://github.com/nlohmann/json/issues/1910) +- why root\_schema be implemented as unique\_ptr in json-validator.cpp,could I use it as shared\_ptr? [\#1908](https://github.com/nlohmann/json/issues/1908) +- compile error in gcc-6.3.0 [\#1906](https://github.com/nlohmann/json/issues/1906) +- Scalar constexpr is odr-used when used as json initializer [\#1905](https://github.com/nlohmann/json/issues/1905) +- install Slack app [\#1904](https://github.com/nlohmann/json/issues/1904) +- typo in a comment [\#1903](https://github.com/nlohmann/json/issues/1903) +- Watch JSON variables in Debug [\#1902](https://github.com/nlohmann/json/issues/1902) +- does Json sdk cares about dfc dfd utf8 issue? [\#1901](https://github.com/nlohmann/json/issues/1901) +- Allow multiple line string value in JSON [\#1897](https://github.com/nlohmann/json/issues/1897) +- Writing map to json file [\#1896](https://github.com/nlohmann/json/issues/1896) +- Small documentation mistake [\#1895](https://github.com/nlohmann/json/issues/1895) +- why static function `parse` cann't find in visual studio 2019 [\#1894](https://github.com/nlohmann/json/issues/1894) +- Best way to handle json files with missing key value pairs. [\#1893](https://github.com/nlohmann/json/issues/1893) +- accessing json object as multimap [\#1892](https://github.com/nlohmann/json/issues/1892) +- What is the best way to parse vec3s into glm::vec3 [\#1891](https://github.com/nlohmann/json/issues/1891) +- Get array of items without using vector [\#1890](https://github.com/nlohmann/json/issues/1890) +- Build errors \(clang 11.0.0\) on macOS 10.15.2 [\#1889](https://github.com/nlohmann/json/issues/1889) +- Multiple arrays to vectors help [\#1888](https://github.com/nlohmann/json/issues/1888) +- json::parse\(begin, end\) parse error on first character using uchar\* [\#1887](https://github.com/nlohmann/json/issues/1887) +- issue in free\(\) [\#1886](https://github.com/nlohmann/json/issues/1886) +- is\_number\_unsigned\(\) returns false for positive integers \(int or 0 or 1 literals\) [\#1885](https://github.com/nlohmann/json/issues/1885) +- MSVC build failure with /Zc:\_\_cplusplus and C++17 [\#1883](https://github.com/nlohmann/json/issues/1883) +- RFC 6901 op:replace & arrays [\#1882](https://github.com/nlohmann/json/issues/1882) +- Problem with serialization of my custom template doubly-linked list [\#1881](https://github.com/nlohmann/json/issues/1881) +- is\_array\(\) is True, but raise 'cannot use operator\[\] for object iterators' [\#1880](https://github.com/nlohmann/json/issues/1880) +- Serialize dynamic array [\#1879](https://github.com/nlohmann/json/issues/1879) +- Serialization of struct object. [\#1877](https://github.com/nlohmann/json/issues/1877) +- warning:c4503 [\#1875](https://github.com/nlohmann/json/issues/1875) +- Why are flattened empty objects/arrays not representable? [\#1874](https://github.com/nlohmann/json/issues/1874) +- Container Overflow \(ASAN\) when using operator \>\> on an ifs [\#1873](https://github.com/nlohmann/json/issues/1873) +- Sub-array to vector or map object? [\#1870](https://github.com/nlohmann/json/issues/1870) +- WIP: QT \(cute\) type supports [\#1869](https://github.com/nlohmann/json/issues/1869) +- Compiler flags to disable features and shrink code size [\#1868](https://github.com/nlohmann/json/issues/1868) +- null strings [\#1867](https://github.com/nlohmann/json/issues/1867) +- Struct with array of struct and \_\_attribute\_\_\(\(packed\)\) [\#1866](https://github.com/nlohmann/json/issues/1866) +- Best way to extract numbers in the string? [\#1865](https://github.com/nlohmann/json/issues/1865) +- Displaying \\?\Volume{guid} from string to json giving error [\#1864](https://github.com/nlohmann/json/issues/1864) +- not working when compiling as x86 [\#1863](https://github.com/nlohmann/json/issues/1863) +- Skipping evaluation of log line expressions with a macro, is it possible? [\#1862](https://github.com/nlohmann/json/issues/1862) +- Suppress warnings [\#1861](https://github.com/nlohmann/json/issues/1861) +- conflit with g++ compile option -mwindows [\#1860](https://github.com/nlohmann/json/issues/1860) +- How to serialize nested classes to semi-flat JSON object? [\#1859](https://github.com/nlohmann/json/issues/1859) +- Memory Requirement for large json file [\#1858](https://github.com/nlohmann/json/issues/1858) +- Query a binary format \(BSON, CBOR, MessagePack, UBJSON\) [\#1856](https://github.com/nlohmann/json/issues/1856) +- Documentation on operator\[\] behavior with missing keys [\#1855](https://github.com/nlohmann/json/issues/1855) +- Problem in converting string into JSON; Can't parse successfully. [\#1854](https://github.com/nlohmann/json/issues/1854) +- json.at\_or\_default\(key, defaultval\) [\#1852](https://github.com/nlohmann/json/issues/1852) +- please improve the enum conversion documentation \(my example gist provided\) [\#1851](https://github.com/nlohmann/json/issues/1851) +- Default value returned on ValueType nlohmann::basic\_json::value \(const typename object\_t::key\_type& key, const ValueType& default\_value\) [\#1850](https://github.com/nlohmann/json/issues/1850) +- Accounting for arbitrary precision numerical literals [\#1849](https://github.com/nlohmann/json/issues/1849) +- While trying to make a simple array, I get a nested array instead [\#1848](https://github.com/nlohmann/json/issues/1848) +- How to reuse the parser and serializer intermediate storage? [\#1847](https://github.com/nlohmann/json/issues/1847) +- Too much content in json.hpp leads to slow compilation [\#1845](https://github.com/nlohmann/json/issues/1845) +- Cannot read some data in json file [\#1843](https://github.com/nlohmann/json/issues/1843) +- Precompiled JSON library? [\#1842](https://github.com/nlohmann/json/issues/1842) +- Please change assert into throw\(maybe\) in line 17946 [\#1841](https://github.com/nlohmann/json/issues/1841) +- JSON for modern C++ ECCN information [\#1840](https://github.com/nlohmann/json/issues/1840) +- CI: reduce build time for Travis valgrind [\#1836](https://github.com/nlohmann/json/issues/1836) +- How do I traverse a json object and add new elements into the hierarchy [\#1834](https://github.com/nlohmann/json/issues/1834) +- Invalid UTF-8 byte at index 1: 0x65 [\#1831](https://github.com/nlohmann/json/issues/1831) +- Serialize big data in json [\#1828](https://github.com/nlohmann/json/issues/1828) +- Backslash '\' in value causes exception [\#1827](https://github.com/nlohmann/json/issues/1827) +- from\_json for non default constructible class with dependency injection [\#1819](https://github.com/nlohmann/json/issues/1819) +- Semi-frequent timeouts in `test-unicode_all` with 3.6.1 \(aarch64\) [\#1816](https://github.com/nlohmann/json/issues/1816) +- input\_adapter not user extensible [\#1813](https://github.com/nlohmann/json/issues/1813) +- crash at json::destroy on android [\#1812](https://github.com/nlohmann/json/issues/1812) +- Logs are repeating while cmake [\#1809](https://github.com/nlohmann/json/issues/1809) +- Add a the possibility to add dynamic json objects [\#1795](https://github.com/nlohmann/json/issues/1795) +- Unnecessary test data file in the release [\#1790](https://github.com/nlohmann/json/issues/1790) +- Add support for parse stack limiting [\#1788](https://github.com/nlohmann/json/issues/1788) +- GCC -Wuseless-cast warnings [\#1777](https://github.com/nlohmann/json/issues/1777) +- compilation issue with NVCC 9.0 [\#1773](https://github.com/nlohmann/json/issues/1773) +- Unexpected behavior with fifo\_map json when copy and append [\#1763](https://github.com/nlohmann/json/issues/1763) +- Parse error [\#1761](https://github.com/nlohmann/json/issues/1761) +- Assignment \(using value\(\)\) to nonexistent element behaves differently on Xcode 8 vs Xcode 10 [\#1758](https://github.com/nlohmann/json/issues/1758) +- Readme out of date [\#1756](https://github.com/nlohmann/json/issues/1756) +- cmake\_\* tests don't use the build system's compiler [\#1747](https://github.com/nlohmann/json/issues/1747) +- Static assertions for template type properties required [\#1729](https://github.com/nlohmann/json/issues/1729) +- Use float and possibly half in json::to\_cbor [\#1719](https://github.com/nlohmann/json/issues/1719) +- json::from\_cbor does not respect allow\_exceptions = false when input is string literal [\#1715](https://github.com/nlohmann/json/issues/1715) +- /Zc:\_\_cplusplus leads to C2416 [\#1695](https://github.com/nlohmann/json/issues/1695) +- `unflatten` vs objects with number-ish keys [\#1575](https://github.com/nlohmann/json/issues/1575) +- A "thinner" source code tar as part of release? [\#1572](https://github.com/nlohmann/json/issues/1572) +- Repository is almost 450MB [\#1497](https://github.com/nlohmann/json/issues/1497) +- Substantial performance penalty caused by polymorphic input adapter [\#1457](https://github.com/nlohmann/json/issues/1457) +- Move tests to a separate repo [\#1235](https://github.com/nlohmann/json/issues/1235) +- reduce repos size [\#1185](https://github.com/nlohmann/json/issues/1185) +- CMakeLists.txt in release zips? [\#1184](https://github.com/nlohmann/json/issues/1184) +- Minimal branch? [\#1066](https://github.com/nlohmann/json/issues/1066) +- Move test blobs to a submodule? [\#732](https://github.com/nlohmann/json/issues/732) +- \[Question\] When using this as git submodule, will it clone the whole thing include test data and benchmark? [\#620](https://github.com/nlohmann/json/issues/620) +- Need to improve ignores.. [\#567](https://github.com/nlohmann/json/issues/567) +- Minimal repository \(current size very large\) [\#556](https://github.com/nlohmann/json/issues/556) +- For a header-only library you have to clone 214MB [\#482](https://github.com/nlohmann/json/issues/482) +- 17 MB / 90 MB repo size!? [\#96](https://github.com/nlohmann/json/issues/96) + +- Improve parse\_ubjson\_fuzzer [\#2182](https://github.com/nlohmann/json/pull/2182) ([tanuj208](https://github.com/tanuj208)) +- Add input adapter tests [\#2178](https://github.com/nlohmann/json/pull/2178) ([nlohmann](https://github.com/nlohmann)) +- Fix warnings [\#2174](https://github.com/nlohmann/json/pull/2174) ([nlohmann](https://github.com/nlohmann)) +- Fix PR\#1006 [\#2158](https://github.com/nlohmann/json/pull/2158) ([dota17](https://github.com/dota17)) +- Fix issue\#1972 [\#2153](https://github.com/nlohmann/json/pull/2153) ([dota17](https://github.com/dota17)) +- Update URLs to HTTPS [\#2152](https://github.com/nlohmann/json/pull/2152) ([TotalCaesar659](https://github.com/TotalCaesar659)) +- Fix Issue\#1813: user defined input adapters [\#2145](https://github.com/nlohmann/json/pull/2145) ([FrancoisChabot](https://github.com/FrancoisChabot)) +- Fix issue\#1939: Cast character to unsigned for comparison [\#2144](https://github.com/nlohmann/json/pull/2144) ([XyFreak](https://github.com/XyFreak)) +- Fix issue\#2142: readme: fix typo in CMake FetchContent example [\#2143](https://github.com/nlohmann/json/pull/2143) ([quentin-dev](https://github.com/quentin-dev)) +- Respect allow\_exceptions=false for binary formats [\#2140](https://github.com/nlohmann/json/pull/2140) ([nlohmann](https://github.com/nlohmann)) +- Fix issue 2112 [\#2137](https://github.com/nlohmann/json/pull/2137) ([dota17](https://github.com/dota17)) +- Add bleeding edge GCC to CI [\#2136](https://github.com/nlohmann/json/pull/2136) ([aokellermann](https://github.com/aokellermann)) +- Clean up implementation of binary type [\#2125](https://github.com/nlohmann/json/pull/2125) ([nlohmann](https://github.com/nlohmann)) +- Fixed a compilation error in MSVC [\#2121](https://github.com/nlohmann/json/pull/2121) ([gistrec](https://github.com/gistrec)) +- Overwork CI [\#2119](https://github.com/nlohmann/json/pull/2119) ([nlohmann](https://github.com/nlohmann)) +- Fix warnings from Clang 10 and GCC 9 [\#2116](https://github.com/nlohmann/json/pull/2116) ([nlohmann](https://github.com/nlohmann)) +- Do not include \ when using C++17 [\#2115](https://github.com/nlohmann/json/pull/2115) ([nlohmann](https://github.com/nlohmann)) +- Fix issue\#2086: disallow json::value\_t type parameter in value\(\) [\#2104](https://github.com/nlohmann/json/pull/2104) ([dota17](https://github.com/dota17)) +- Fix Coveralls integration [\#2100](https://github.com/nlohmann/json/pull/2100) ([nlohmann](https://github.com/nlohmann)) +- Add tests for binary values [\#2099](https://github.com/nlohmann/json/pull/2099) ([nlohmann](https://github.com/nlohmann)) +- Use external test data [\#2081](https://github.com/nlohmann/json/pull/2081) ([nlohmann](https://github.com/nlohmann)) +- Remove Doozer CI [\#2080](https://github.com/nlohmann/json/pull/2080) ([nlohmann](https://github.com/nlohmann)) +- Fix README.md. Missing ``` [\#2077](https://github.com/nlohmann/json/pull/2077) ([ArthurSonzogni](https://github.com/ArthurSonzogni)) +- Fix error message about invalid surrogate pairs [\#2076](https://github.com/nlohmann/json/pull/2076) ([rmisev](https://github.com/rmisev)) +- Add CMake fetchcontent documentation and tests [\#2074](https://github.com/nlohmann/json/pull/2074) ([ArthurSonzogni](https://github.com/ArthurSonzogni)) +- Properly pass serialize\_binary to dump function [\#2071](https://github.com/nlohmann/json/pull/2071) ([nlohmann](https://github.com/nlohmann)) +- Fix returning reference to local temporary object [\#2069](https://github.com/nlohmann/json/pull/2069) ([nlohmann](https://github.com/nlohmann)) +- updated wandbox link [\#2060](https://github.com/nlohmann/json/pull/2060) ([alexandermyasnikov](https://github.com/alexandermyasnikov)) +- Fix bug in diff function [\#2054](https://github.com/nlohmann/json/pull/2054) ([nlohmann](https://github.com/nlohmann)) +- Fix GCC compiler warnings [\#2053](https://github.com/nlohmann/json/pull/2053) ([nlohmann](https://github.com/nlohmann)) +- Fix Clang compiler warnings [\#2051](https://github.com/nlohmann/json/pull/2051) ([nlohmann](https://github.com/nlohmann)) +- Update doctest to 2.3.7 [\#2050](https://github.com/nlohmann/json/pull/2050) ([nlohmann](https://github.com/nlohmann)) +- Fix issue\#1719 [\#2044](https://github.com/nlohmann/json/pull/2044) ([dota17](https://github.com/dota17)) +- Add missing testcase about NaN in unit-constructor1.cpp [\#2043](https://github.com/nlohmann/json/pull/2043) ([dota17](https://github.com/dota17)) +- Templatize basic\_json constructor from json\_ref [\#2034](https://github.com/nlohmann/json/pull/2034) ([ArtemSarmini](https://github.com/ArtemSarmini)) +- Replace deprecated std::is\_pod [\#2033](https://github.com/nlohmann/json/pull/2033) ([nlohmann](https://github.com/nlohmann)) +- Fixes \#1971 \(memory leak in basic\_json::push\_back\) [\#2025](https://github.com/nlohmann/json/pull/2025) ([ArtemSarmini](https://github.com/ArtemSarmini)) +- fix \#1982:json\_pointer.contains\(\) exception is incorrectly raised [\#2019](https://github.com/nlohmann/json/pull/2019) ([dota17](https://github.com/dota17)) +- Update LICENSE.MIT [\#2010](https://github.com/nlohmann/json/pull/2010) ([magamig](https://github.com/magamig)) +- PR for \#2006 to test in AppVeyor. [\#2008](https://github.com/nlohmann/json/pull/2008) ([garethsb](https://github.com/garethsb)) +- Added wsjcpp.yml [\#2004](https://github.com/nlohmann/json/pull/2004) ([sea-kg](https://github.com/sea-kg)) +- fix error 'setw' is not a member of 'std' in Wandbox example [\#2002](https://github.com/nlohmann/json/pull/2002) ([alexandermyasnikov](https://github.com/alexandermyasnikov)) +- catch exceptions for json\_pointer : ..../+99 [\#1990](https://github.com/nlohmann/json/pull/1990) ([dota17](https://github.com/dota17)) +- Modify the document about operator== [\#1984](https://github.com/nlohmann/json/pull/1984) ([dota17](https://github.com/dota17)) +- Rename argument array\_index to array\_indx in json\_pointer methods [\#1980](https://github.com/nlohmann/json/pull/1980) ([linev](https://github.com/linev)) +- README: Fix string representation of `dump`ed `json` [\#1979](https://github.com/nlohmann/json/pull/1979) ([alex-weej](https://github.com/alex-weej)) +- fix warnings in serializer.hpp for VS2019 [\#1969](https://github.com/nlohmann/json/pull/1969) ([dota17](https://github.com/dota17)) +- Fix C26451 warnnings in to\_chars.hpp [\#1967](https://github.com/nlohmann/json/pull/1967) ([dota17](https://github.com/dota17)) +- appveyor.yml: Compile and test with latest version for \_\_cplusplus ma… [\#1958](https://github.com/nlohmann/json/pull/1958) ([t-b](https://github.com/t-b)) +- Fix typo in examples [\#1956](https://github.com/nlohmann/json/pull/1956) ([dota17](https://github.com/dota17)) +- templated input adapters [\#1950](https://github.com/nlohmann/json/pull/1950) ([FrancoisChabot](https://github.com/FrancoisChabot)) +- Update README.md : add a FAQ about memory release [\#1933](https://github.com/nlohmann/json/pull/1933) ([dota17](https://github.com/dota17)) +- Some typos [\#1923](https://github.com/nlohmann/json/pull/1923) ([Coeur](https://github.com/Coeur)) +- Fix link to parse function in README [\#1918](https://github.com/nlohmann/json/pull/1918) ([kastiglione](https://github.com/kastiglione)) +- Readme: Updated links to hunter repo & docs [\#1917](https://github.com/nlohmann/json/pull/1917) ([jothepro](https://github.com/jothepro)) +- Adds instruction for using Build2's package manager [\#1909](https://github.com/nlohmann/json/pull/1909) ([Klaim](https://github.com/Klaim)) +- Update README.md [\#1907](https://github.com/nlohmann/json/pull/1907) ([pauljurczak](https://github.com/pauljurczak)) +- Fix warning: ignoring return value [\#1871](https://github.com/nlohmann/json/pull/1871) ([sonulohani](https://github.com/sonulohani)) +- docs: add central repository as conan source to readme [\#1857](https://github.com/nlohmann/json/pull/1857) ([gocarlos](https://github.com/gocarlos)) +- README: Package in MSYS2 renamed to nlohmann-json [\#1853](https://github.com/nlohmann/json/pull/1853) ([podsvirov](https://github.com/podsvirov)) +- Fix msvc warnings [\#1846](https://github.com/nlohmann/json/pull/1846) ([MBalszun](https://github.com/MBalszun)) +- Update tests that generate CMake projects to use main project's C++ compiler [\#1844](https://github.com/nlohmann/json/pull/1844) ([Tridacnid](https://github.com/Tridacnid)) +- make CMake's version config file architecture-independent [\#1746](https://github.com/nlohmann/json/pull/1746) ([uhoreg](https://github.com/uhoreg)) +- Add binary type support to all binary file formats, as well as an internally represented binary type [\#1662](https://github.com/nlohmann/json/pull/1662) ([OmnipotentEntity](https://github.com/OmnipotentEntity)) + +## [v3.7.3](https://github.com/nlohmann/json/releases/tag/v3.7.3) (2019-11-17) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.7.2...v3.7.3) + +- Project branches [\#1839](https://github.com/nlohmann/json/issues/1839) +- Quadratic destruction complexity introduced in \#1436 [\#1837](https://github.com/nlohmann/json/issues/1837) +- Trying to open a file [\#1814](https://github.com/nlohmann/json/issues/1814) +- Comparing data type with value\_t::number\_integer fails [\#1783](https://github.com/nlohmann/json/issues/1783) +- CMake version config file is architecture-dependent [\#1697](https://github.com/nlohmann/json/issues/1697) + +- Fix quadratic destruction complexity [\#1838](https://github.com/nlohmann/json/pull/1838) ([nickaein](https://github.com/nickaein)) + +## [v3.7.2](https://github.com/nlohmann/json/releases/tag/v3.7.2) (2019-11-10) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.7.1...v3.7.2) + +- Segmentation fault in destructor in case of large inputs [\#1835](https://github.com/nlohmann/json/issues/1835) +- type\_name\(\) is not consistent with type\(\) [\#1833](https://github.com/nlohmann/json/issues/1833) +- json::parse is not a member [\#1832](https://github.com/nlohmann/json/issues/1832) +- How do you deal with json\* ? [\#1829](https://github.com/nlohmann/json/issues/1829) +- Combined find\_package/add\_subdirectory not linking libraries [\#1771](https://github.com/nlohmann/json/issues/1771) +- example code for ifstream reading a json file results in no operator error [\#1766](https://github.com/nlohmann/json/issues/1766) +- Warning: unsequenced modification and access to 'range' [\#1674](https://github.com/nlohmann/json/issues/1674) +- Segmentation fault \(stack overflow\) due to unbounded recursion [\#1419](https://github.com/nlohmann/json/issues/1419) +- Stack-overflow \(OSS-Fuzz 4234\) [\#832](https://github.com/nlohmann/json/issues/832) + +- Configure WhiteSource Bolt for GitHub [\#1830](https://github.com/nlohmann/json/pull/1830) ([whitesource-bolt-for-github[bot]](https://github.com/apps/whitesource-bolt-for-github)) +- Prevent stackoverflow caused by recursive deconstruction [\#1436](https://github.com/nlohmann/json/pull/1436) ([nickaein](https://github.com/nickaein)) + +## [v3.7.1](https://github.com/nlohmann/json/releases/tag/v3.7.1) (2019-11-06) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.7.0...v3.7.1) + +- std::is\_constructible is always true with tuple [\#1825](https://github.com/nlohmann/json/issues/1825) +- Can't compile from\_json\(std::valarray\\). [\#1824](https://github.com/nlohmann/json/issues/1824) +- json class should have a get\_or member function [\#1823](https://github.com/nlohmann/json/issues/1823) +- NLOHMANN\_JSON\_SERIALIZE\_ENUM macro capture's json objects by value [\#1822](https://github.com/nlohmann/json/issues/1822) +- Parse fails when number literals start with zero [\#1820](https://github.com/nlohmann/json/issues/1820) +- Weird behaviour of `contains` with `json_pointer` [\#1815](https://github.com/nlohmann/json/issues/1815) +- strange behaviour with json\_pointer and .contains\(\) [\#1811](https://github.com/nlohmann/json/issues/1811) +- Can \#1695 be re-opened? [\#1808](https://github.com/nlohmann/json/issues/1808) +- Merge two json objects [\#1807](https://github.com/nlohmann/json/issues/1807) +- std::is\_constructible\\> when to\_json not defined [\#1805](https://github.com/nlohmann/json/issues/1805) +- Private data on parsing [\#1802](https://github.com/nlohmann/json/issues/1802) +- Capturing Line and Position when querying [\#1800](https://github.com/nlohmann/json/issues/1800) +- json error on parsing DBL\_MAX from string [\#1796](https://github.com/nlohmann/json/issues/1796) +- De/Serialisation of vector of tupple object with nested obect need Help please [\#1794](https://github.com/nlohmann/json/issues/1794) +- Output json is corrupted [\#1793](https://github.com/nlohmann/json/issues/1793) +- variable name byte sometimes used as a \#define [\#1792](https://github.com/nlohmann/json/issues/1792) +- Can't read json file [\#1791](https://github.com/nlohmann/json/issues/1791) +- Problems with special German letters [\#1789](https://github.com/nlohmann/json/issues/1789) +- Support for trailing commas [\#1787](https://github.com/nlohmann/json/issues/1787) +- json\_pointer construction bug [\#1786](https://github.com/nlohmann/json/issues/1786) +- Visual Studio 2017 warning [\#1784](https://github.com/nlohmann/json/issues/1784) +- ciso646 header become obsolete [\#1782](https://github.com/nlohmann/json/issues/1782) +- Migrate LGTM.com installation from OAuth to GitHub App [\#1781](https://github.com/nlohmann/json/issues/1781) +- JSON comparison, contains and operator& [\#1778](https://github.com/nlohmann/json/issues/1778) +- pass a json object to a class contructor adds an array around the object [\#1776](https://github.com/nlohmann/json/issues/1776) +- 'Float' number\_float\_function\_t template parameter name conflicts with C '\#define Float float' [\#1775](https://github.com/nlohmann/json/issues/1775) +- A weird building problem :-\( [\#1774](https://github.com/nlohmann/json/issues/1774) +- What is this json\_ref? [\#1772](https://github.com/nlohmann/json/issues/1772) +- Interoperability with other languages [\#1770](https://github.com/nlohmann/json/issues/1770) +- Json dump [\#1768](https://github.com/nlohmann/json/issues/1768) +- json\_pointer\<\>::back\(\) should be const [\#1764](https://github.com/nlohmann/json/issues/1764) +- How to get value from array [\#1762](https://github.com/nlohmann/json/issues/1762) +- Merge two jsons [\#1757](https://github.com/nlohmann/json/issues/1757) +- Unable to locate nlohmann\_jsonConfig.cmake [\#1755](https://github.com/nlohmann/json/issues/1755) +- json.hpp won;t compile VS2019 CLR/CLI app but does in console app [\#1754](https://github.com/nlohmann/json/issues/1754) +- \[Nested Json Objects\] Segmentation fault [\#1753](https://github.com/nlohmann/json/issues/1753) +- remove/replace assert with exceptions [\#1752](https://github.com/nlohmann/json/issues/1752) +- Add array support for update\(\) function [\#1751](https://github.com/nlohmann/json/issues/1751) +- Is there a reason the `get_to` method is defined in `include/nlohmann/json.hpp` but not in `single_include/nlohmann/json.hpp`? [\#1750](https://github.com/nlohmann/json/issues/1750) +- how to validate json object before calling dump\(\) [\#1748](https://github.com/nlohmann/json/issues/1748) +- Unable to invoke accessors on json objects in lldb [\#1745](https://github.com/nlohmann/json/issues/1745) +- Escaping string before parsing [\#1743](https://github.com/nlohmann/json/issues/1743) +- Construction in a member initializer list using curly braces is set as 'array' [\#1742](https://github.com/nlohmann/json/issues/1742) +- Read a subkey from json object [\#1740](https://github.com/nlohmann/json/issues/1740) +- Serialize vector of glm:vec2 [\#1739](https://github.com/nlohmann/json/issues/1739) +- Support nlohmann::basic\_json::value with JSON\_NOEXCEPTION [\#1738](https://github.com/nlohmann/json/issues/1738) +- how to know the parse is error [\#1737](https://github.com/nlohmann/json/issues/1737) +- How to check if a given key exists in a JSON object [\#1736](https://github.com/nlohmann/json/issues/1736) +- Allow The Colon Key-Value Delimiter To Have A Space Before It \[@ READ ONLY\] [\#1735](https://github.com/nlohmann/json/issues/1735) +- Allow Tail { "Key": "Value" } Comma \[@ READ ONLY\] [\#1734](https://github.com/nlohmann/json/issues/1734) +- No-throw json::value\(\) [\#1733](https://github.com/nlohmann/json/issues/1733) +- JsonObject.dump\(\) [\#1732](https://github.com/nlohmann/json/issues/1732) +- basic\_json has no member "parse" [\#1731](https://github.com/nlohmann/json/issues/1731) +- Exception "type must be string, but is array" [\#1730](https://github.com/nlohmann/json/issues/1730) +- json::contains usage to find a path [\#1727](https://github.com/nlohmann/json/issues/1727) +- How to create JSON Object from my Structures of Data and Json File from that Object [\#1726](https://github.com/nlohmann/json/issues/1726) +- please provide an API to read JSON from file directly. [\#1725](https://github.com/nlohmann/json/issues/1725) +- How to modify a value stored at a key? [\#1723](https://github.com/nlohmann/json/issues/1723) +- CMake not correctly finding the configuration package for 3.7.0 [\#1721](https://github.com/nlohmann/json/issues/1721) +- name typo in the "spack package management" section of README.md [\#1720](https://github.com/nlohmann/json/issues/1720) +- How to add json to another json? [\#1718](https://github.com/nlohmann/json/issues/1718) +- json::parse\(\) ubsan regression with v3.7.0 [\#1716](https://github.com/nlohmann/json/issues/1716) +- What I am doing wrong?!? [\#1714](https://github.com/nlohmann/json/issues/1714) +- Potential memory leak detected by Valgrind [\#1713](https://github.com/nlohmann/json/issues/1713) +- json::parse is not thread safe? [\#1712](https://github.com/nlohmann/json/issues/1712) +- static analysis alarm by cppcheck [\#1711](https://github.com/nlohmann/json/issues/1711) +- The compilation time is slow [\#1710](https://github.com/nlohmann/json/issues/1710) +- not linking properly with cmake [\#1709](https://github.com/nlohmann/json/issues/1709) +- Error in dump\(\) with int64\_t minimum value [\#1708](https://github.com/nlohmann/json/issues/1708) +- Crash on trying to deserialize json string on 3ds homebrew [\#1707](https://github.com/nlohmann/json/issues/1707) +- Can't compile VS2019. 13 Errors [\#1706](https://github.com/nlohmann/json/issues/1706) +- find an object that matches the search criteria [\#1705](https://github.com/nlohmann/json/issues/1705) +- IntelliSense goes crazy on VS2019 [\#1704](https://github.com/nlohmann/json/issues/1704) +- Installing on Ubuntu 16.04 [\#1703](https://github.com/nlohmann/json/issues/1703) +- Where is json::parse now? [\#1702](https://github.com/nlohmann/json/issues/1702) +- Forward header should't be amalgamated [\#1700](https://github.com/nlohmann/json/issues/1700) +- Json support for Cmake version 2.8.12 [\#1699](https://github.com/nlohmann/json/issues/1699) +- Intruisive scientific notation when using .dump\(\); [\#1698](https://github.com/nlohmann/json/issues/1698) +- Is there support for automatic serialization/deserialization? [\#1696](https://github.com/nlohmann/json/issues/1696) +- on MSVC dump\(\) will hard crash for larger json [\#1693](https://github.com/nlohmann/json/issues/1693) +- puzzled implicit conversions [\#1692](https://github.com/nlohmann/json/issues/1692) +- Information: My project uses this awesome library [\#1691](https://github.com/nlohmann/json/issues/1691) +- Consider listing files explicitly instead of using GLOB [\#1686](https://github.com/nlohmann/json/issues/1686) +- Failing tests on MSVC with VS2019 15.9.13 x64 [\#1685](https://github.com/nlohmann/json/issues/1685) +- Consider putting the user-defined literals in a namespace [\#1682](https://github.com/nlohmann/json/issues/1682) +- Change from v2 to v3. Encoding with cp1252 [\#1680](https://github.com/nlohmann/json/issues/1680) +- How to add Fifo\_map into json using Cmake [\#1679](https://github.com/nlohmann/json/issues/1679) +- include.zip should contain meson.build [\#1672](https://github.com/nlohmann/json/issues/1672) +- \[Question\] How do I parse JSON into custom types? [\#1669](https://github.com/nlohmann/json/issues/1669) +- Binary \(0x05\) data type for BSON to JSON conversion [\#1668](https://github.com/nlohmann/json/issues/1668) +- Possible to call dump from lldb? [\#1666](https://github.com/nlohmann/json/issues/1666) +- Segmentation fault when linked with libunwind [\#1665](https://github.com/nlohmann/json/issues/1665) +- Should I include single-header after my to\_json and from\_json custom functions declaration? Why not? [\#1663](https://github.com/nlohmann/json/issues/1663) +- Errors/Warnings in VS 2019 when Including Header File [\#1659](https://github.com/nlohmann/json/issues/1659) +- Return null object from object's const operator\[\] as well. [\#1658](https://github.com/nlohmann/json/issues/1658) +- Can't stream json object in to std::basic\_stringstream\ [\#1656](https://github.com/nlohmann/json/issues/1656) +- C2440 in vs2015 cannot convert from 'initializer-list' to nlohmann::basic\_json [\#1655](https://github.com/nlohmann/json/issues/1655) +- Issues around get and pointers [\#1653](https://github.com/nlohmann/json/issues/1653) +- Non-member operator== breaks enum \(de\)serialization [\#1647](https://github.com/nlohmann/json/issues/1647) +- Valgrind: bytes in 1 blocks are definitely lost [\#1646](https://github.com/nlohmann/json/issues/1646) +- Convenient way to make 'basic\_json' accept 'QString' as an key type as well? [\#1640](https://github.com/nlohmann/json/issues/1640) +- mongodb: nan, inf [\#1599](https://github.com/nlohmann/json/issues/1599) +- Error in adl\_serializer [\#1590](https://github.com/nlohmann/json/issues/1590) +- Injecting class during serialization [\#1584](https://github.com/nlohmann/json/issues/1584) +- output\_adapter not user extensible [\#1534](https://github.com/nlohmann/json/issues/1534) +- Inclusion of nlohmann/json.hpp causes OS/ABI to change on Linux [\#1410](https://github.com/nlohmann/json/issues/1410) +- Add library versioning using inline namespaces [\#1394](https://github.com/nlohmann/json/issues/1394) +- CBOR byte string support [\#1129](https://github.com/nlohmann/json/issues/1129) +- How to deserialize array with derived objects [\#716](https://github.com/nlohmann/json/issues/716) + +- Add restriction for tuple specialization of to\_json [\#1826](https://github.com/nlohmann/json/pull/1826) ([cbegue](https://github.com/cbegue)) +- Fix for \#1647 [\#1821](https://github.com/nlohmann/json/pull/1821) ([AnthonyVH](https://github.com/AnthonyVH)) +- Fix issue \#1805 [\#1806](https://github.com/nlohmann/json/pull/1806) ([cbegue](https://github.com/cbegue)) +- Fix some spelling errors - mostly in comments & documentation. [\#1803](https://github.com/nlohmann/json/pull/1803) ([flopp](https://github.com/flopp)) +- Update Hedley to v11. [\#1799](https://github.com/nlohmann/json/pull/1799) ([nemequ](https://github.com/nemequ)) +- iteration\_proxy: Fix integer truncation from std::size\_t to int [\#1797](https://github.com/nlohmann/json/pull/1797) ([t-b](https://github.com/t-b)) +- appveyor.yml: Add MSVC 16 2019 support [\#1780](https://github.com/nlohmann/json/pull/1780) ([t-b](https://github.com/t-b)) +- test/CMakeLists.txt: Use an explicit list instead of GLOB [\#1779](https://github.com/nlohmann/json/pull/1779) ([t-b](https://github.com/t-b)) +- Make json\_pointer::back const \(resolves \#1764\) [\#1769](https://github.com/nlohmann/json/pull/1769) ([chris0x44](https://github.com/chris0x44)) +- did you mean 'serialization'? [\#1767](https://github.com/nlohmann/json/pull/1767) ([0xflotus](https://github.com/0xflotus)) +- Allow items\(\) to be used with custom string [\#1765](https://github.com/nlohmann/json/pull/1765) ([crazyjul](https://github.com/crazyjul)) +- Cppcheck fixes [\#1760](https://github.com/nlohmann/json/pull/1760) ([Xav83](https://github.com/Xav83)) +- Fix and add test's for SFINAE problem [\#1741](https://github.com/nlohmann/json/pull/1741) ([tete17](https://github.com/tete17)) +- Fix clang sanitizer invocation [\#1728](https://github.com/nlohmann/json/pull/1728) ([t-b](https://github.com/t-b)) +- Add gcc 9 and compile with experimental C++20 support [\#1724](https://github.com/nlohmann/json/pull/1724) ([t-b](https://github.com/t-b)) +- Fix int64 min issue [\#1722](https://github.com/nlohmann/json/pull/1722) ([t-b](https://github.com/t-b)) +- release: add singleinclude and meson.build to include.zip [\#1694](https://github.com/nlohmann/json/pull/1694) ([eli-schwartz](https://github.com/eli-schwartz)) + +## [v3.7.0](https://github.com/nlohmann/json/releases/tag/v3.7.0) (2019-07-28) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.6.1...v3.7.0) + +- How can I retrieve uknown strings from json file in my C++ program. [\#1684](https://github.com/nlohmann/json/issues/1684) +- contains\(\) is sometimes causing stack-based buffer overrun exceptions [\#1683](https://github.com/nlohmann/json/issues/1683) +- How to deserialize arrays from json [\#1681](https://github.com/nlohmann/json/issues/1681) +- Compilation failed in VS2015 [\#1678](https://github.com/nlohmann/json/issues/1678) +- Why the compiled object file is so huge? [\#1677](https://github.com/nlohmann/json/issues/1677) +- From Version 2.1.1 to 3.6.1 serialize std::set [\#1676](https://github.com/nlohmann/json/issues/1676) +- Qt deprecation model halting compiltion [\#1675](https://github.com/nlohmann/json/issues/1675) +- Build For Raspberry pi , Rapbery with new Compiler C++17 [\#1671](https://github.com/nlohmann/json/issues/1671) +- Build from Raspberry pi [\#1667](https://github.com/nlohmann/json/issues/1667) +- Can not translate map with integer key to dict string ? [\#1664](https://github.com/nlohmann/json/issues/1664) +- Double type converts to scientific notation [\#1661](https://github.com/nlohmann/json/issues/1661) +- Missing v3.6.1 tag on master branch [\#1657](https://github.com/nlohmann/json/issues/1657) +- Support Fleese Binary Data Format [\#1654](https://github.com/nlohmann/json/issues/1654) +- Suggestion: replace alternative tokens for !, && and || with their symbols [\#1652](https://github.com/nlohmann/json/issues/1652) +- Build failure test-allocator.vcxproj [\#1651](https://github.com/nlohmann/json/issues/1651) +- How to provide function json& to\_json\(\) which is similar as 'void to\_json\(json&j, const CObject& obj\)' ? [\#1650](https://github.com/nlohmann/json/issues/1650) +- Can't throw exception when starting file is a number [\#1649](https://github.com/nlohmann/json/issues/1649) +- to\_json / from\_json with nested type [\#1648](https://github.com/nlohmann/json/issues/1648) +- How to create a json object from a std::string, created by j.dump? [\#1645](https://github.com/nlohmann/json/issues/1645) +- Problem getting vector \(array\) of strings [\#1644](https://github.com/nlohmann/json/issues/1644) +- json.hpp compilation issue with other typedefs with same name [\#1642](https://github.com/nlohmann/json/issues/1642) +- nlohmann::adl\_serializer\::to\_json no matching overloaded function found [\#1641](https://github.com/nlohmann/json/issues/1641) +- overwrite adl\_serializer\ to change behaviour [\#1638](https://github.com/nlohmann/json/issues/1638) +- json.SelectToken\("Manufacturers.Products.Price"\); [\#1637](https://github.com/nlohmann/json/issues/1637) +- Add json type as value [\#1636](https://github.com/nlohmann/json/issues/1636) +- Unit conversion test error: conversion from 'nlohmann::json' to non-scalar type 'std::string\_view' requested [\#1634](https://github.com/nlohmann/json/issues/1634) +- nlohmann VS JsonCpp by C++17 [\#1633](https://github.com/nlohmann/json/issues/1633) +- To integrate an inline helper function that return type name as string [\#1632](https://github.com/nlohmann/json/issues/1632) +- Return JSON as reference [\#1631](https://github.com/nlohmann/json/issues/1631) +- Updating from an older version causes problems with assing a json object to a struct [\#1630](https://github.com/nlohmann/json/issues/1630) +- Can without default constructor function for user defined classes when only to\_json is needed? [\#1629](https://github.com/nlohmann/json/issues/1629) +- Compilation fails with clang 6.x-8.x in C++14 mode [\#1628](https://github.com/nlohmann/json/issues/1628) +- Treating floating point as string [\#1627](https://github.com/nlohmann/json/issues/1627) +- error parsing character Ã¥ [\#1626](https://github.com/nlohmann/json/issues/1626) +- \[Help\] How to Improve Json Output Performance with Large Json Arrays [\#1624](https://github.com/nlohmann/json/issues/1624) +- Suggested link changes for reporting new issues \[blob/develop/REAME.md and blob/develop/.github/CONTRIBUTING.md\] [\#1623](https://github.com/nlohmann/json/issues/1623) +- Broken link to issue template in CONTRIBUTING.md [\#1622](https://github.com/nlohmann/json/issues/1622) +- Missing word in README.md file [\#1621](https://github.com/nlohmann/json/issues/1621) +- Package manager instructions in README for brew is incorrect [\#1620](https://github.com/nlohmann/json/issues/1620) +- Building with Visual Studio 2019 [\#1619](https://github.com/nlohmann/json/issues/1619) +- Precedence of to\_json and builtin harmful [\#1617](https://github.com/nlohmann/json/issues/1617) +- The type json is missing from the html documentation [\#1616](https://github.com/nlohmann/json/issues/1616) +- variant is not support in Release 3.6.1? [\#1615](https://github.com/nlohmann/json/issues/1615) +- Replace assert with throw for const operator\[\] [\#1614](https://github.com/nlohmann/json/issues/1614) +- Memory Overhead is Too High \(10x or more\) [\#1613](https://github.com/nlohmann/json/issues/1613) +- program crash everytime, when other data type incomming in json stream as expected [\#1612](https://github.com/nlohmann/json/issues/1612) +- Improved Enum Support [\#1611](https://github.com/nlohmann/json/issues/1611) +- is it possible convert json object back to stl container ? [\#1610](https://github.com/nlohmann/json/issues/1610) +- Add C++17-like emplace.back\(\) for arrays. [\#1609](https://github.com/nlohmann/json/issues/1609) +- is\_nothrow\_copy\_constructible fails for json::const\_iterator on MSVC2015 x86 Debug build [\#1608](https://github.com/nlohmann/json/issues/1608) +- Reading and writing array elements [\#1607](https://github.com/nlohmann/json/issues/1607) +- Converting json::value to int [\#1605](https://github.com/nlohmann/json/issues/1605) +- I have a vector of keys and and a string of value and i want to create nested json array [\#1604](https://github.com/nlohmann/json/issues/1604) +- In compatible JSON object from nlohmann::json to nohman::json - unexpected end of input; expected '\[', '{', or a literal [\#1603](https://github.com/nlohmann/json/issues/1603) +- json parser crash if having a large number integer in message [\#1602](https://github.com/nlohmann/json/issues/1602) +- Value method with undocumented throwing 302 exception [\#1601](https://github.com/nlohmann/json/issues/1601) +- Accessing value with json pointer adds key if not existing [\#1600](https://github.com/nlohmann/json/issues/1600) +- README.md broken link to project documentation [\#1597](https://github.com/nlohmann/json/issues/1597) +- Random Kudos: Thanks for your work on this! [\#1596](https://github.com/nlohmann/json/issues/1596) +- json::parse return value and errors [\#1595](https://github.com/nlohmann/json/issues/1595) +- initializer list constructor makes curly brace initialization fragile [\#1594](https://github.com/nlohmann/json/issues/1594) +- trying to log message for missing keyword, difference between \["foo"\] and at\("foo"\) [\#1593](https://github.com/nlohmann/json/issues/1593) +- std::string and std::wstring `to_json` [\#1592](https://github.com/nlohmann/json/issues/1592) +- I have a C structure which I need to convert to a JSON. How do I do it? Haven't found proper examples so far. [\#1591](https://github.com/nlohmann/json/issues/1591) +- dump\_escaped possible error ? [\#1589](https://github.com/nlohmann/json/issues/1589) +- json::parse\(\) into a vector\ results in unhandled exception [\#1587](https://github.com/nlohmann/json/issues/1587) +- push\_back\(\)/emplace\_back\(\) on array invalidates pointers to existing array items [\#1586](https://github.com/nlohmann/json/issues/1586) +- Getting nlohmann::detail::parse\_error on JSON generated by nlohmann::json not sure why [\#1583](https://github.com/nlohmann/json/issues/1583) +- getting error terminate called after throwing an instance of 'std::domain\_error' what\(\): cannot use at\(\) with string [\#1582](https://github.com/nlohmann/json/issues/1582) +- how i create json file [\#1581](https://github.com/nlohmann/json/issues/1581) +- prevent rounding of double datatype values [\#1580](https://github.com/nlohmann/json/issues/1580) +- Documentation Container Overview Doesn't Reference Const Methods [\#1579](https://github.com/nlohmann/json/issues/1579) +- Writing an array into a nlohmann::json object [\#1578](https://github.com/nlohmann/json/issues/1578) +- compilation error when using with another library [\#1577](https://github.com/nlohmann/json/issues/1577) +- Homebrew on OSX doesn't install cmake config file [\#1576](https://github.com/nlohmann/json/issues/1576) +- JSON Parse Out of Range Error [\#1574](https://github.com/nlohmann/json/issues/1574) +- Integrating into existing CMake Project [\#1573](https://github.com/nlohmann/json/issues/1573) +- conversion to std::string failed [\#1571](https://github.com/nlohmann/json/issues/1571) +- jPtr operation does not throw [\#1569](https://github.com/nlohmann/json/issues/1569) +- How to generate dll file for this project [\#1568](https://github.com/nlohmann/json/issues/1568) +- how to pass variable data to json in c [\#1567](https://github.com/nlohmann/json/issues/1567) +- I want to achieve an upgraded function. [\#1566](https://github.com/nlohmann/json/issues/1566) +- How to determine the type of elements read from a JSON array? [\#1564](https://github.com/nlohmann/json/issues/1564) +- try\_get\_to [\#1563](https://github.com/nlohmann/json/issues/1563) +- example code compile error [\#1562](https://github.com/nlohmann/json/issues/1562) +- How to iterate over nested json object [\#1561](https://github.com/nlohmann/json/issues/1561) +- Build Option/Separate Function to Allow to Throw on Duplicate Keys [\#1560](https://github.com/nlohmann/json/issues/1560) +- Compiler Switches -Weffc++ & -Wshadow are throwing errors [\#1558](https://github.com/nlohmann/json/issues/1558) +- warning: use of the 'nodiscard' attribute is a C++17 extension [\#1557](https://github.com/nlohmann/json/issues/1557) +- Import/Export compressed JSON files [\#1556](https://github.com/nlohmann/json/issues/1556) +- GDB renderers for json library [\#1554](https://github.com/nlohmann/json/issues/1554) +- Is it possible to construct a json string object from a binary buffer? [\#1553](https://github.com/nlohmann/json/issues/1553) +- json objects in list [\#1552](https://github.com/nlohmann/json/issues/1552) +- Matrix output [\#1550](https://github.com/nlohmann/json/issues/1550) +- Using json merge\_patch on ordered non-alphanumeric datasets [\#1549](https://github.com/nlohmann/json/issues/1549) +- Invalid parsed value for big integer [\#1548](https://github.com/nlohmann/json/issues/1548) +- Integrating with android ndk issues. [\#1547](https://github.com/nlohmann/json/issues/1547) +- add noexcept json::value\("key", default\) method variant? [\#1546](https://github.com/nlohmann/json/issues/1546) +- Thank you! 🙌 [\#1545](https://github.com/nlohmann/json/issues/1545) +- Output and input matrix [\#1544](https://github.com/nlohmann/json/issues/1544) +- Add regression tests for MSVC [\#1543](https://github.com/nlohmann/json/issues/1543) +- \[Help Needed!\] Season of Docs [\#1542](https://github.com/nlohmann/json/issues/1542) +- program still abort\(\) or exit\(\) with try catch [\#1541](https://github.com/nlohmann/json/issues/1541) +- Have a json::type\_error exception because of JSON object [\#1540](https://github.com/nlohmann/json/issues/1540) +- Using versioned namespaces [\#1539](https://github.com/nlohmann/json/issues/1539) +- Quoted numbers [\#1538](https://github.com/nlohmann/json/issues/1538) +- Reading a JSON file into an object [\#1537](https://github.com/nlohmann/json/issues/1537) +- Releases 3.6.0 and 3.6.1 don't build on conda / windows [\#1536](https://github.com/nlohmann/json/issues/1536) +- \[Clang\] warning: use of the 'nodiscard' attribute is a C++17 extension \[-Wc++17-extensions\] [\#1535](https://github.com/nlohmann/json/issues/1535) +- wchar\_t/std::wstring json can be created but not accessed [\#1533](https://github.com/nlohmann/json/issues/1533) +- json stringify [\#1532](https://github.com/nlohmann/json/issues/1532) +- How can I use it from gcc on RPI [\#1528](https://github.com/nlohmann/json/issues/1528) +- std::pair treated as an array instead of key-value in `std::vector>` [\#1520](https://github.com/nlohmann/json/issues/1520) +- Excessive Memory Usage for Large Json File [\#1516](https://github.com/nlohmann/json/issues/1516) +- SAX dumper [\#1512](https://github.com/nlohmann/json/issues/1512) +- Conversion to user type containing a std::vector not working with documented approach [\#1511](https://github.com/nlohmann/json/issues/1511) +- Inconsistent use of type alias. [\#1507](https://github.com/nlohmann/json/issues/1507) +- Is there a current way to represent strings as json int? [\#1503](https://github.com/nlohmann/json/issues/1503) +- Intermittent issues with loadJSON [\#1484](https://github.com/nlohmann/json/issues/1484) +- use json construct std::string [\#1462](https://github.com/nlohmann/json/issues/1462) +- JSON Creation [\#1461](https://github.com/nlohmann/json/issues/1461) +- Null bytes in files are treated like EOF [\#1095](https://github.com/nlohmann/json/issues/1095) +- Feature: to\_string\(const json& j\); [\#916](https://github.com/nlohmann/json/issues/916) + +- Use GNUInstallDirs instead of hard-coded path. [\#1673](https://github.com/nlohmann/json/pull/1673) ([ghost](https://github.com/ghost)) +- Package Manager: MSYS2 \(pacman\) [\#1670](https://github.com/nlohmann/json/pull/1670) ([podsvirov](https://github.com/podsvirov)) +- Fix json.hpp compilation issue with other typedefs with same name \(Issue \#1642\) [\#1643](https://github.com/nlohmann/json/pull/1643) ([kevinlul](https://github.com/kevinlul)) +- Add explicit conversion from json to std::string\_view in conversion unit test [\#1639](https://github.com/nlohmann/json/pull/1639) ([taylorhoward92](https://github.com/taylorhoward92)) +- Minor fixes in docs [\#1625](https://github.com/nlohmann/json/pull/1625) ([nickaein](https://github.com/nickaein)) +- Fix broken links to documentation [\#1598](https://github.com/nlohmann/json/pull/1598) ([nickaein](https://github.com/nickaein)) +- Added to\_string and added basic tests [\#1585](https://github.com/nlohmann/json/pull/1585) ([Macr0Nerd](https://github.com/Macr0Nerd)) +- Regression tests for MSVC [\#1570](https://github.com/nlohmann/json/pull/1570) ([nickaein](https://github.com/nickaein)) +- Fix/1511 [\#1555](https://github.com/nlohmann/json/pull/1555) ([theodelrieu](https://github.com/theodelrieu)) +- Remove C++17 extension warning from clang; \#1535 [\#1551](https://github.com/nlohmann/json/pull/1551) ([heavywatal](https://github.com/heavywatal)) +- moved from Catch to doctest for unit tests [\#1439](https://github.com/nlohmann/json/pull/1439) ([onqtam](https://github.com/onqtam)) + +## [v3.6.1](https://github.com/nlohmann/json/releases/tag/v3.6.1) (2019-03-20) + +[Full Changelog](https://github.com/nlohmann/json/compare/3.6.1...v3.6.1) + +## [3.6.1](https://github.com/nlohmann/json/releases/tag/3.6.1) (2019-03-20) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.6.0...3.6.1) + +- Failed to build with \ [\#1531](https://github.com/nlohmann/json/issues/1531) +- Compiling 3.6.0 with GCC \> 7, array vs std::array \#590 is back [\#1530](https://github.com/nlohmann/json/issues/1530) +- 3.6.0: warning: missing initializer for member 'std::array\::\_M\_elems' \[-Wmissing-field-initializers\] [\#1527](https://github.com/nlohmann/json/issues/1527) +- unable to parse json [\#1525](https://github.com/nlohmann/json/issues/1525) + +## [v3.6.0](https://github.com/nlohmann/json/releases/tag/v3.6.0) (2019-03-19) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.5.0...v3.6.0) + +- How can I turn a string of a json array into a json array? [\#1526](https://github.com/nlohmann/json/issues/1526) +- Minor: missing a std:: namespace tag [\#1521](https://github.com/nlohmann/json/issues/1521) +- how to precision to four decimal for double when use to\_json [\#1519](https://github.com/nlohmann/json/issues/1519) +- error parse [\#1518](https://github.com/nlohmann/json/issues/1518) +- Compile error: template argument deduction/substitution failed [\#1515](https://github.com/nlohmann/json/issues/1515) +- std::complex type [\#1510](https://github.com/nlohmann/json/issues/1510) +- CBOR byte string support [\#1509](https://github.com/nlohmann/json/issues/1509) +- Compilation error getting a std::pair\<\> on latest VS 2017 compiler [\#1506](https://github.com/nlohmann/json/issues/1506) +- "Integration" section of documentation needs update? [\#1505](https://github.com/nlohmann/json/issues/1505) +- Json object from string from a TCP socket [\#1504](https://github.com/nlohmann/json/issues/1504) +- MSVC warning C4946 \("reinterpret\_cast used between related classes"\) compiling json.hpp [\#1502](https://github.com/nlohmann/json/issues/1502) +- How to programmatically fill an n-th dimensional JSON object? [\#1501](https://github.com/nlohmann/json/issues/1501) +- Error compiling with clang and `JSON_NOEXCEPTION`: need to include `cstdlib` [\#1500](https://github.com/nlohmann/json/issues/1500) +- The code compiles unsuccessfully with android-ndk-r10e [\#1499](https://github.com/nlohmann/json/issues/1499) +- Cmake 3.1 in develop, when is it likely to make it into a stable release? [\#1498](https://github.com/nlohmann/json/issues/1498) +- Some Help please object inside array [\#1494](https://github.com/nlohmann/json/issues/1494) +- How to get data into vector of user-defined type from a Json object [\#1493](https://github.com/nlohmann/json/issues/1493) +- how to find subelement without loop [\#1490](https://github.com/nlohmann/json/issues/1490) +- json to std::map [\#1487](https://github.com/nlohmann/json/issues/1487) +- Type in README.md [\#1486](https://github.com/nlohmann/json/issues/1486) +- Error in parsing and reading msgpack-lite [\#1485](https://github.com/nlohmann/json/issues/1485) +- Compiling issues with libc 2.12 [\#1483](https://github.com/nlohmann/json/issues/1483) +- How do I use reference or pointer binding values? [\#1482](https://github.com/nlohmann/json/issues/1482) +- Compilation fails in MSVC with the Microsoft Language Extensions disabled [\#1481](https://github.com/nlohmann/json/issues/1481) +- Functional visit [\#1480](https://github.com/nlohmann/json/issues/1480) +- \[Question\] Unescaped dump [\#1479](https://github.com/nlohmann/json/issues/1479) +- Some Help please [\#1478](https://github.com/nlohmann/json/issues/1478) +- Global variables are stored within the JSON file, how do I declare them as global variables when I read them out in my C++ program? [\#1476](https://github.com/nlohmann/json/issues/1476) +- Unable to modify one of the values within the JSON file, and save it [\#1475](https://github.com/nlohmann/json/issues/1475) +- Documentation of parse function has two identical @pre causes [\#1473](https://github.com/nlohmann/json/issues/1473) +- GCC 9.0 build failure [\#1472](https://github.com/nlohmann/json/issues/1472) +- Can we have an `exists()` method? [\#1471](https://github.com/nlohmann/json/issues/1471) +- How to parse multi object json from file? [\#1470](https://github.com/nlohmann/json/issues/1470) +- How to returns the name of the upper object? [\#1467](https://github.com/nlohmann/json/issues/1467) +- Error: "tuple\_size" has already been declared in the current scope [\#1466](https://github.com/nlohmann/json/issues/1466) +- Checking keys of two jsons against eachother [\#1465](https://github.com/nlohmann/json/issues/1465) +- Disable installation when used as meson subproject [\#1463](https://github.com/nlohmann/json/issues/1463) +- Unpack list of integers to a std::vector\ [\#1460](https://github.com/nlohmann/json/issues/1460) +- Implement DRY definition of JSON representation of a c++ class [\#1459](https://github.com/nlohmann/json/issues/1459) +- json.exception.type\_error.305 with GCC 4.9 when using C++ {} initializer [\#1458](https://github.com/nlohmann/json/issues/1458) +- API to convert an "uninitialized" json into an empty object or empty array [\#1456](https://github.com/nlohmann/json/issues/1456) +- How to parse a vector of objects with const attributes [\#1453](https://github.com/nlohmann/json/issues/1453) +- NLOHMANN\_JSON\_SERIALIZE\_ENUM potentially requires duplicate definitions [\#1450](https://github.com/nlohmann/json/issues/1450) +- Question about making json object from file directory [\#1449](https://github.com/nlohmann/json/issues/1449) +- .get\(\) throws error if used with userdefined structs in unordered\_map [\#1448](https://github.com/nlohmann/json/issues/1448) +- Integer Overflow \(OSS-Fuzz 12506\) [\#1447](https://github.com/nlohmann/json/issues/1447) +- If a string has too many invalid UTF-8 characters, json::dump attempts to index an array out of bounds. [\#1445](https://github.com/nlohmann/json/issues/1445) +- Setting values of .JSON file [\#1444](https://github.com/nlohmann/json/issues/1444) +- alias object\_t::key\_type in basic\_json [\#1442](https://github.com/nlohmann/json/issues/1442) +- Latest Ubuntu package is 2.1.1 [\#1438](https://github.com/nlohmann/json/issues/1438) +- lexer.hpp\(1363\) '\_snprintf': is not a member | Visualstudio 2017 [\#1437](https://github.com/nlohmann/json/issues/1437) +- Static method invites inadvertent logic error. [\#1433](https://github.com/nlohmann/json/issues/1433) +- EOS compilation produces "fatal error: 'nlohmann/json.hpp' file not found" [\#1432](https://github.com/nlohmann/json/issues/1432) +- Support for bad commas [\#1429](https://github.com/nlohmann/json/issues/1429) +- Please have one base exception class for all json exceptions [\#1427](https://github.com/nlohmann/json/issues/1427) +- Compilation warning: 'tuple\_size' defined as a class template here but previously declared as a struct template [\#1426](https://github.com/nlohmann/json/issues/1426) +- Which version can be used with GCC 4.8.2 ? [\#1424](https://github.com/nlohmann/json/issues/1424) +- Ignore nullptr values on constructing json object from a container [\#1422](https://github.com/nlohmann/json/issues/1422) +- Support for custom float precision via unquoted strings [\#1421](https://github.com/nlohmann/json/issues/1421) +- It is possible to call `json::find` with a json\_pointer as argument. This causes runtime UB/crash. [\#1418](https://github.com/nlohmann/json/issues/1418) +- Dump throwing exception [\#1416](https://github.com/nlohmann/json/issues/1416) +- Build error [\#1415](https://github.com/nlohmann/json/issues/1415) +- Append version to include.zip [\#1412](https://github.com/nlohmann/json/issues/1412) +- error C2039: '\_snprintf': is not a member of 'std' - Windows [\#1408](https://github.com/nlohmann/json/issues/1408) +- Deserializing to vector [\#1407](https://github.com/nlohmann/json/issues/1407) +- Efficient way to set a `json` object as value into another `json` key [\#1406](https://github.com/nlohmann/json/issues/1406) +- Document return value of parse\(\) when allow\_exceptions == false and parsing fails [\#1405](https://github.com/nlohmann/json/issues/1405) +- Unexpected behaviour with structured binding [\#1404](https://github.com/nlohmann/json/issues/1404) +- Which native types does get\\(\) allow? [\#1403](https://github.com/nlohmann/json/issues/1403) +- Add something like Json::StaticString [\#1402](https://github.com/nlohmann/json/issues/1402) +- -Wmismatched-tags in 3.5.0? [\#1401](https://github.com/nlohmann/json/issues/1401) +- Coverity Scan reports an UNCAUGHT\_EXCEPT issue [\#1400](https://github.com/nlohmann/json/issues/1400) +- fff [\#1399](https://github.com/nlohmann/json/issues/1399) +- sorry this is not an issue, just a Question, How to change a key value in a file and save it ? [\#1398](https://github.com/nlohmann/json/issues/1398) +- appveyor x64 builds appear to be using Win32 toolset [\#1374](https://github.com/nlohmann/json/issues/1374) +- Serializing/Deserializing a Class containing a vector of itself [\#1373](https://github.com/nlohmann/json/issues/1373) +- Retrieving array elements. [\#1369](https://github.com/nlohmann/json/issues/1369) +- Deserialize [\#1366](https://github.com/nlohmann/json/issues/1366) +- call of overloaded for push\_back and operator+= is ambiguous [\#1352](https://github.com/nlohmann/json/issues/1352) +- got an error and cann't figure it out [\#1351](https://github.com/nlohmann/json/issues/1351) +- Improve number-to-string conversion [\#1334](https://github.com/nlohmann/json/issues/1334) +- Implicit type conversion error on MSVC [\#1333](https://github.com/nlohmann/json/issues/1333) +- NuGet Package [\#1132](https://github.com/nlohmann/json/issues/1132) + +- Change macros to numeric\_limits [\#1514](https://github.com/nlohmann/json/pull/1514) ([naszta](https://github.com/naszta)) +- fix GCC 7.1.1 - 7.2.1 on CentOS [\#1496](https://github.com/nlohmann/json/pull/1496) ([lieff](https://github.com/lieff)) +- Update Buckaroo instructions in README.md [\#1495](https://github.com/nlohmann/json/pull/1495) ([njlr](https://github.com/njlr)) +- Fix gcc9 build error test/src/unit-allocator.cpp \(Issue \#1472\) [\#1492](https://github.com/nlohmann/json/pull/1492) ([stac47](https://github.com/stac47)) +- Fix typo in README.md [\#1491](https://github.com/nlohmann/json/pull/1491) ([nickaein](https://github.com/nickaein)) +- Do proper endian conversions [\#1489](https://github.com/nlohmann/json/pull/1489) ([andreas-schwab](https://github.com/andreas-schwab)) +- Fix documentation [\#1477](https://github.com/nlohmann/json/pull/1477) ([nickaein](https://github.com/nickaein)) +- Implement contains\(\) member function [\#1474](https://github.com/nlohmann/json/pull/1474) ([nickaein](https://github.com/nickaein)) +- Add operator/= and operator/ to construct a JSON pointer by appending two JSON pointers [\#1469](https://github.com/nlohmann/json/pull/1469) ([garethsb](https://github.com/garethsb)) +- Disable Clang -Wmismatched-tags warning on tuple\_size / tuple\_element [\#1468](https://github.com/nlohmann/json/pull/1468) ([past-due](https://github.com/past-due)) +- Disable installation when used as meson subproject. \#1463 [\#1464](https://github.com/nlohmann/json/pull/1464) ([elvisoric](https://github.com/elvisoric)) +- docs: README typo [\#1455](https://github.com/nlohmann/json/pull/1455) ([wythe](https://github.com/wythe)) +- remove extra semicolon from readme [\#1451](https://github.com/nlohmann/json/pull/1451) ([Afforix](https://github.com/Afforix)) +- attempt to fix \#1445, flush buffer in serializer::dump\_escaped in UTF8\_REJECT case. [\#1446](https://github.com/nlohmann/json/pull/1446) ([scinart](https://github.com/scinart)) +- Use C++11 features supported by CMake 3.1. [\#1441](https://github.com/nlohmann/json/pull/1441) ([iwanders](https://github.com/iwanders)) +- :rotating\_light: fixed unused variable warning [\#1435](https://github.com/nlohmann/json/pull/1435) ([pboettch](https://github.com/pboettch)) +- allow push\_back\(\) and pop\_back\(\) calls on json\_pointer [\#1434](https://github.com/nlohmann/json/pull/1434) ([pboettch](https://github.com/pboettch)) +- Add instructions about using nlohmann/json with the conda package manager [\#1430](https://github.com/nlohmann/json/pull/1430) ([nicoddemus](https://github.com/nicoddemus)) +- Updated year in README.md [\#1425](https://github.com/nlohmann/json/pull/1425) ([jef](https://github.com/jef)) +- Fixed broken links in the README file [\#1423](https://github.com/nlohmann/json/pull/1423) ([skypjack](https://github.com/skypjack)) +- Fixed broken links in the README file [\#1420](https://github.com/nlohmann/json/pull/1420) ([skypjack](https://github.com/skypjack)) +- docs: typo in README [\#1417](https://github.com/nlohmann/json/pull/1417) ([wythe](https://github.com/wythe)) +- Fix x64 target platform for appveyor [\#1414](https://github.com/nlohmann/json/pull/1414) ([nickaein](https://github.com/nickaein)) +- Improve dump\_integer performance [\#1411](https://github.com/nlohmann/json/pull/1411) ([nickaein](https://github.com/nickaein)) +- buildsystem: relax requirement on cmake version [\#1409](https://github.com/nlohmann/json/pull/1409) ([yann-morin-1998](https://github.com/yann-morin-1998)) +- CMake: Optional Install if Embedded [\#1330](https://github.com/nlohmann/json/pull/1330) ([ax3l](https://github.com/ax3l)) + +## [v3.5.0](https://github.com/nlohmann/json/releases/tag/v3.5.0) (2018-12-21) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.4.0...v3.5.0) + +- Copyconstructor inserts original into array with single element [\#1397](https://github.com/nlohmann/json/issues/1397) +- Get value without explicit typecasting [\#1395](https://github.com/nlohmann/json/issues/1395) +- Big file parsing [\#1393](https://github.com/nlohmann/json/issues/1393) +- some static analysis warning at line 11317 [\#1390](https://github.com/nlohmann/json/issues/1390) +- Adding Structured Binding Support [\#1388](https://github.com/nlohmann/json/issues/1388) +- map\ exhibits unexpected behavior [\#1387](https://github.com/nlohmann/json/issues/1387) +- Error Code Return [\#1386](https://github.com/nlohmann/json/issues/1386) +- using unordered\_map as object type [\#1385](https://github.com/nlohmann/json/issues/1385) +- float precision [\#1384](https://github.com/nlohmann/json/issues/1384) +- \[json.exception.type\_error.316\] invalid UTF-8 byte at index 1: 0xC3 [\#1383](https://github.com/nlohmann/json/issues/1383) +- Inconsistent Constructor \(GCC vs. Clang\) [\#1381](https://github.com/nlohmann/json/issues/1381) +- \#define or || [\#1379](https://github.com/nlohmann/json/issues/1379) +- How to iterate inside the values ? [\#1377](https://github.com/nlohmann/json/issues/1377) +- items\(\) unable to get the elements [\#1375](https://github.com/nlohmann/json/issues/1375) +- conversion json to std::map doesn't work for types \ [\#1372](https://github.com/nlohmann/json/issues/1372) +- A minor issue in the build instructions [\#1371](https://github.com/nlohmann/json/issues/1371) +- Using this library without stream ? [\#1370](https://github.com/nlohmann/json/issues/1370) +- Writing and reading BSON data [\#1368](https://github.com/nlohmann/json/issues/1368) +- Retrieving array elements from object type iterator. [\#1367](https://github.com/nlohmann/json/issues/1367) +- json::dump\(\) silently crashes if items contain accented letters [\#1365](https://github.com/nlohmann/json/issues/1365) +- warnings in MSVC \(2015\) in 3.4.0 related to bool... [\#1364](https://github.com/nlohmann/json/issues/1364) +- Cant compile with -C++17 and beyond compiler options [\#1362](https://github.com/nlohmann/json/issues/1362) +- json to concrete type conversion through reference or pointer fails [\#1361](https://github.com/nlohmann/json/issues/1361) +- the first attributes of JSON string is misplaced [\#1360](https://github.com/nlohmann/json/issues/1360) +- Copy-construct using initializer-list converts objects to arrays [\#1359](https://github.com/nlohmann/json/issues/1359) +- About value\(key, default\_value\) and operator\[\]\(key\) [\#1358](https://github.com/nlohmann/json/issues/1358) +- Problem with printing json response object [\#1356](https://github.com/nlohmann/json/issues/1356) +- Serializing pointer segfaults [\#1355](https://github.com/nlohmann/json/issues/1355) +- Read `long long int` data as a number. [\#1354](https://github.com/nlohmann/json/issues/1354) +- eclipse oxygen in ubuntu get\ is ambiguous [\#1353](https://github.com/nlohmann/json/issues/1353) +- Can't build on Visual Studio 2017 v15.8.9 [\#1350](https://github.com/nlohmann/json/issues/1350) +- cannot parse from string? [\#1349](https://github.com/nlohmann/json/issues/1349) +- Error: out\_of\_range [\#1348](https://github.com/nlohmann/json/issues/1348) +- expansion pattern 'CompatibleObjectType' contains no argument packs, with CUDA 10 [\#1347](https://github.com/nlohmann/json/issues/1347) +- Unable to update a value for a nested\(multi-level\) json file [\#1344](https://github.com/nlohmann/json/issues/1344) +- Fails to compile when std::iterator\_traits is not SFINAE friendly. [\#1341](https://github.com/nlohmann/json/issues/1341) +- EOF flag not set on exhausted input streams. [\#1340](https://github.com/nlohmann/json/issues/1340) +- Shadowed Member in merge\_patch [\#1339](https://github.com/nlohmann/json/issues/1339) +- Periods/literal dots in keys? [\#1338](https://github.com/nlohmann/json/issues/1338) +- Protect macro expansion of commonly defined macros [\#1337](https://github.com/nlohmann/json/issues/1337) +- How to validate an input before parsing? [\#1336](https://github.com/nlohmann/json/issues/1336) +- Non-verifying dump\(\) alternative for debugging/logging needed [\#1335](https://github.com/nlohmann/json/issues/1335) +- Json Libarary is not responding for me in c++ [\#1332](https://github.com/nlohmann/json/issues/1332) +- Question - how to find an object in an array [\#1331](https://github.com/nlohmann/json/issues/1331) +- Nesting additional data in json object [\#1328](https://github.com/nlohmann/json/issues/1328) +- can to\_json\(\) be defined inside a class? [\#1324](https://github.com/nlohmann/json/issues/1324) +- CodeBlocks IDE can't find `json.hpp` header [\#1318](https://github.com/nlohmann/json/issues/1318) +- Change json\_pointer to provide an iterator begin/end/etc, don't use vectors, and also enable string\_view [\#1312](https://github.com/nlohmann/json/issues/1312) +- Xcode - adding it to library [\#1300](https://github.com/nlohmann/json/issues/1300) +- unicode: accept char16\_t, char32\_t sequences [\#1298](https://github.com/nlohmann/json/issues/1298) +- unicode: char16\_t\* is compiler error, but char16\_t\[\] is accepted [\#1297](https://github.com/nlohmann/json/issues/1297) +- Dockerfile Project Help Needed [\#1296](https://github.com/nlohmann/json/issues/1296) +- Comparisons between large unsigned and negative signed integers [\#1295](https://github.com/nlohmann/json/issues/1295) +- CMake alias to `nlohmann::json` [\#1291](https://github.com/nlohmann/json/issues/1291) +- Release zips without tests [\#1285](https://github.com/nlohmann/json/issues/1285) +- separate object\_t::key\_type from basic\_json::key\_type, and use an allocator which returns object\_t::key\_type [\#1274](https://github.com/nlohmann/json/issues/1274) +- Is there a nice way to associate external values with json elements? [\#1256](https://github.com/nlohmann/json/issues/1256) +- Delete by json\_pointer [\#1248](https://github.com/nlohmann/json/issues/1248) +- Expose lexer, as a StAX parser [\#1219](https://github.com/nlohmann/json/issues/1219) +- Subclassing json\(\) & error on recursive load [\#1201](https://github.com/nlohmann/json/issues/1201) +- Check value for existence by json\_pointer [\#1194](https://github.com/nlohmann/json/issues/1194) + +- Feature/add file input adapter [\#1392](https://github.com/nlohmann/json/pull/1392) ([dumarjo](https://github.com/dumarjo)) +- Added Support for Structured Bindings [\#1391](https://github.com/nlohmann/json/pull/1391) ([pratikpc](https://github.com/pratikpc)) +- Link to issue \#958 broken [\#1382](https://github.com/nlohmann/json/pull/1382) ([kjpus](https://github.com/kjpus)) +- readme: fix typo [\#1380](https://github.com/nlohmann/json/pull/1380) ([manu-chroma](https://github.com/manu-chroma)) +- recommend using explicit from JSON conversions [\#1363](https://github.com/nlohmann/json/pull/1363) ([theodelrieu](https://github.com/theodelrieu)) +- Fix merge\_patch shadow warning [\#1346](https://github.com/nlohmann/json/pull/1346) ([ax3l](https://github.com/ax3l)) +- Allow installation via Meson [\#1345](https://github.com/nlohmann/json/pull/1345) ([mpoquet](https://github.com/mpoquet)) +- Set eofbit on exhausted input stream. [\#1343](https://github.com/nlohmann/json/pull/1343) ([mefyl](https://github.com/mefyl)) +- Add a SFINAE friendly iterator\_traits and use that instead. [\#1342](https://github.com/nlohmann/json/pull/1342) ([dgavedissian](https://github.com/dgavedissian)) +- Fix EOL Whitespaces & CMake Spelling [\#1329](https://github.com/nlohmann/json/pull/1329) ([ax3l](https://github.com/ax3l)) + +## [v3.4.0](https://github.com/nlohmann/json/releases/tag/v3.4.0) (2018-10-30) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.3.0...v3.4.0) + +- Big uint64\_t values are serialized wrong [\#1327](https://github.com/nlohmann/json/issues/1327) +- \[Question\] Efficient check for equivalency? [\#1325](https://github.com/nlohmann/json/issues/1325) +- Can't use ifstream and .clear\(\) [\#1321](https://github.com/nlohmann/json/issues/1321) +- \[Warning\] -Wparentheses on line 555 on single\_include [\#1319](https://github.com/nlohmann/json/issues/1319) +- Compilation error using at and find with enum struct [\#1316](https://github.com/nlohmann/json/issues/1316) +- Parsing JSON from a web address [\#1311](https://github.com/nlohmann/json/issues/1311) +- How to convert JSON to Struct with embeded subject [\#1310](https://github.com/nlohmann/json/issues/1310) +- Null safety/coalescing function? [\#1309](https://github.com/nlohmann/json/issues/1309) +- Building fails using single include file: json.hpp [\#1308](https://github.com/nlohmann/json/issues/1308) +- json::parse\(std::string\) Exception inside packaged Lib [\#1306](https://github.com/nlohmann/json/issues/1306) +- Problem in Dockerfile with installation of library [\#1304](https://github.com/nlohmann/json/issues/1304) +- compile error in from\_json converting to container with std::pair [\#1299](https://github.com/nlohmann/json/issues/1299) +- Json that I am trying to parse, and I am lost Structure Array below top level [\#1293](https://github.com/nlohmann/json/issues/1293) +- Serializing std::variant causes stack overflow [\#1292](https://github.com/nlohmann/json/issues/1292) +- How do I go about customising from\_json to support \_\_int128\_t/\_\_uint128\_t? [\#1290](https://github.com/nlohmann/json/issues/1290) +- merge\_patch: inconsistent behaviour merging empty sub-object [\#1289](https://github.com/nlohmann/json/issues/1289) +- Buffer over/underrun using UBJson? [\#1288](https://github.com/nlohmann/json/issues/1288) +- Enable the latest C++ standard with Visual Studio [\#1287](https://github.com/nlohmann/json/issues/1287) +- truncation of constant value in to\_cbor\(\) [\#1286](https://github.com/nlohmann/json/issues/1286) +- eosio.wasmsdk error [\#1284](https://github.com/nlohmann/json/issues/1284) +- use the same interface for writing arrays and non-arrays [\#1283](https://github.com/nlohmann/json/issues/1283) +- How to read json file with optional entries and entries with different types [\#1281](https://github.com/nlohmann/json/issues/1281) +- merge result not as espected [\#1279](https://github.com/nlohmann/json/issues/1279) +- how to get only "name" from below json [\#1278](https://github.com/nlohmann/json/issues/1278) +- syntax error on right json string [\#1276](https://github.com/nlohmann/json/issues/1276) +- Parsing JSON Array where members have no key, using custom types [\#1267](https://github.com/nlohmann/json/issues/1267) +- I get a json exception periodically from json::parse for the same json [\#1263](https://github.com/nlohmann/json/issues/1263) +- serialize std::variant\<...\> [\#1261](https://github.com/nlohmann/json/issues/1261) +- GCC 8.2.1. Compilation error: invalid conversion from... [\#1246](https://github.com/nlohmann/json/issues/1246) +- BSON support [\#1244](https://github.com/nlohmann/json/issues/1244) +- enum to json mapping [\#1208](https://github.com/nlohmann/json/issues/1208) +- Soften the landing when dumping non-UTF8 strings \(type\_error.316 exception\) [\#1198](https://github.com/nlohmann/json/issues/1198) + +- Add macro to define enum/JSON mapping [\#1323](https://github.com/nlohmann/json/pull/1323) ([nlohmann](https://github.com/nlohmann)) +- Add BSON support [\#1320](https://github.com/nlohmann/json/pull/1320) ([nlohmann](https://github.com/nlohmann)) +- Properly convert constants to CharType [\#1315](https://github.com/nlohmann/json/pull/1315) ([nlohmann](https://github.com/nlohmann)) +- Allow to set error handler for decoding errors [\#1314](https://github.com/nlohmann/json/pull/1314) ([nlohmann](https://github.com/nlohmann)) +- Add Meson related info to README [\#1305](https://github.com/nlohmann/json/pull/1305) ([koponomarenko](https://github.com/koponomarenko)) +- Improve diagnostic messages for binary formats [\#1303](https://github.com/nlohmann/json/pull/1303) ([nlohmann](https://github.com/nlohmann)) +- add new is\_constructible\_\* traits used in from\_json [\#1301](https://github.com/nlohmann/json/pull/1301) ([theodelrieu](https://github.com/theodelrieu)) +- add constraints for variadic json\_ref constructors [\#1294](https://github.com/nlohmann/json/pull/1294) ([theodelrieu](https://github.com/theodelrieu)) +- Improve diagnostic messages [\#1282](https://github.com/nlohmann/json/pull/1282) ([nlohmann](https://github.com/nlohmann)) +- Removed linter warnings [\#1280](https://github.com/nlohmann/json/pull/1280) ([nlohmann](https://github.com/nlohmann)) +- Thirdparty benchmark: Fix Clang detection. [\#1277](https://github.com/nlohmann/json/pull/1277) ([Lord-Kamina](https://github.com/Lord-Kamina)) + +## [v3.3.0](https://github.com/nlohmann/json/releases/tag/v3.3.0) (2018-10-05) + +[Full Changelog](https://github.com/nlohmann/json/compare/3.3.0...v3.3.0) + +- Fix warning C4127: conditional expression is constant [\#1272](https://github.com/nlohmann/json/pull/1272) ([antonioborondo](https://github.com/antonioborondo)) +- Turn off additional deprecation warnings for GCC. [\#1271](https://github.com/nlohmann/json/pull/1271) ([chuckatkins](https://github.com/chuckatkins)) +- docs: Add additional CMake documentation [\#1270](https://github.com/nlohmann/json/pull/1270) ([chuckatkins](https://github.com/chuckatkins)) +- unit-testsuites.cpp: fix hangup if file not found [\#1262](https://github.com/nlohmann/json/pull/1262) ([knilch0r](https://github.com/knilch0r)) +- Fix broken cmake imported target alias [\#1260](https://github.com/nlohmann/json/pull/1260) ([chuckatkins](https://github.com/chuckatkins)) +- GCC 48 [\#1257](https://github.com/nlohmann/json/pull/1257) ([henryiii](https://github.com/henryiii)) +- Add version and license to meson.build [\#1252](https://github.com/nlohmann/json/pull/1252) ([koponomarenko](https://github.com/koponomarenko)) +- \#1179 Reordered the code. It seems to stop clang 3.4.2 in RHEL 7 from crash… [\#1249](https://github.com/nlohmann/json/pull/1249) ([LEgregius](https://github.com/LEgregius)) +- Use a version check to provide backwards comatible CMake imported target names [\#1245](https://github.com/nlohmann/json/pull/1245) ([chuckatkins](https://github.com/chuckatkins)) +- Fix issue \#1237 [\#1238](https://github.com/nlohmann/json/pull/1238) ([theodelrieu](https://github.com/theodelrieu)) +- Add a get overload taking a parameter. [\#1231](https://github.com/nlohmann/json/pull/1231) ([theodelrieu](https://github.com/theodelrieu)) +- Move lambda out of unevaluated context [\#1230](https://github.com/nlohmann/json/pull/1230) ([mandreyel](https://github.com/mandreyel)) +- Remove static asserts [\#1228](https://github.com/nlohmann/json/pull/1228) ([theodelrieu](https://github.com/theodelrieu)) +- Better error 305 [\#1221](https://github.com/nlohmann/json/pull/1221) ([rivertam](https://github.com/rivertam)) +- Fix \#1213 [\#1214](https://github.com/nlohmann/json/pull/1214) ([simnalamburt](https://github.com/simnalamburt)) +- Export package to allow builds without installing [\#1202](https://github.com/nlohmann/json/pull/1202) ([dennisfischer](https://github.com/dennisfischer)) + +## [3.3.0](https://github.com/nlohmann/json/releases/tag/3.3.0) (2018-10-05) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.2.0...3.3.0) + +- When key is not found print the key name into error too [\#1273](https://github.com/nlohmann/json/issues/1273) +- Visual Studio 2017 15.8.5 "conditional expression is constant" warning on Line 1851 in json.hpp [\#1268](https://github.com/nlohmann/json/issues/1268) +- how can we get this working on WSL? [\#1264](https://github.com/nlohmann/json/issues/1264) +- Help needed [\#1259](https://github.com/nlohmann/json/issues/1259) +- A way to get to a JSON values "key" [\#1258](https://github.com/nlohmann/json/issues/1258) +- While compiling got 76 errors [\#1255](https://github.com/nlohmann/json/issues/1255) +- Two blackslashes on json output file [\#1253](https://github.com/nlohmann/json/issues/1253) +- Including nlohmann the badwrong way. [\#1250](https://github.com/nlohmann/json/issues/1250) +- how to build with clang? [\#1247](https://github.com/nlohmann/json/issues/1247) +- Cmake target\_link\_libraries unable to find nlohmann\_json since version 3.2.0 [\#1243](https://github.com/nlohmann/json/issues/1243) +- \[Question\] Access to end\(\) iterator reference [\#1242](https://github.com/nlohmann/json/issues/1242) +- Parsing different json format [\#1241](https://github.com/nlohmann/json/issues/1241) +- Parsing Multiple JSON Files [\#1240](https://github.com/nlohmann/json/issues/1240) +- Doesn't compile under C++17 [\#1239](https://github.com/nlohmann/json/issues/1239) +- Conversion operator for nlohmann::json is not SFINAE friendly [\#1237](https://github.com/nlohmann/json/issues/1237) +- Custom deserialization of number\_float\_t [\#1236](https://github.com/nlohmann/json/issues/1236) +- deprecated-declarations warnings when compiling tests with GCC 8.2.1. [\#1233](https://github.com/nlohmann/json/issues/1233) +- Incomplete type with json\_fwd.hpp [\#1232](https://github.com/nlohmann/json/issues/1232) +- Parse Error [\#1229](https://github.com/nlohmann/json/issues/1229) +- json::get function with argument [\#1227](https://github.com/nlohmann/json/issues/1227) +- questions regarding from\_json [\#1226](https://github.com/nlohmann/json/issues/1226) +- Lambda in unevaluated context [\#1225](https://github.com/nlohmann/json/issues/1225) +- NLohmann doesn't compile when enabling strict warning policies [\#1224](https://github.com/nlohmann/json/issues/1224) +- Creating array of objects [\#1223](https://github.com/nlohmann/json/issues/1223) +- Somewhat unhelpful error message "cannot use operator\[\] with object" [\#1220](https://github.com/nlohmann/json/issues/1220) +- single\_include json.hpp [\#1218](https://github.com/nlohmann/json/issues/1218) +- Maps with enum class keys which are convertible to JSON strings should be converted to JSON dictionaries [\#1217](https://github.com/nlohmann/json/issues/1217) +- Adding JSON Array to the Array [\#1216](https://github.com/nlohmann/json/issues/1216) +- Best way to output a vector of a given type to json [\#1215](https://github.com/nlohmann/json/issues/1215) +- compiler warning: double definition of macro JSON\_INTERNAL\_CATCH [\#1213](https://github.com/nlohmann/json/issues/1213) +- Compilation error when using MOCK\_METHOD1 from GMock and nlohmann::json [\#1212](https://github.com/nlohmann/json/issues/1212) +- Issues parsing a previously encoded binary \(non-UTF8\) string. [\#1211](https://github.com/nlohmann/json/issues/1211) +- Yet another ordering question: char \* and parse\(\) [\#1209](https://github.com/nlohmann/json/issues/1209) +- Error using gcc 8.1.0 on Ubuntu 14.04 [\#1207](https://github.com/nlohmann/json/issues/1207) +- "type must be string, but is " std::string\(j.type\_name\(\) [\#1206](https://github.com/nlohmann/json/issues/1206) +- Returning empty json object from a function of type const json& ? [\#1205](https://github.com/nlohmann/json/issues/1205) +- VS2017 compiler suggests using constexpr if [\#1204](https://github.com/nlohmann/json/issues/1204) +- Template instatiation error on compiling [\#1203](https://github.com/nlohmann/json/issues/1203) +- BUG - json dump field with unicode -\> array of ints \(instead of string\) [\#1197](https://github.com/nlohmann/json/issues/1197) +- Compile error using Code::Blocks // mingw-w64 GCC 8.1.0 - "Incomplete Type" [\#1193](https://github.com/nlohmann/json/issues/1193) +- SEGFAULT on arm target [\#1190](https://github.com/nlohmann/json/issues/1190) +- Compiler crash with old Clang [\#1179](https://github.com/nlohmann/json/issues/1179) +- Custom Precision on floating point numbers [\#1170](https://github.com/nlohmann/json/issues/1170) +- Can we have a json\_view class like std::string\_view? [\#1158](https://github.com/nlohmann/json/issues/1158) +- improve error handling [\#1152](https://github.com/nlohmann/json/issues/1152) +- We should remove static\_asserts [\#960](https://github.com/nlohmann/json/issues/960) + +## [v3.2.0](https://github.com/nlohmann/json/releases/tag/v3.2.0) (2018-08-20) + +[Full Changelog](https://github.com/nlohmann/json/compare/3.2.0...v3.2.0) + +- Fix -Wno-sometimes-uninitialized by initializing "result" in parse\_sax [\#1200](https://github.com/nlohmann/json/pull/1200) ([thyu](https://github.com/thyu)) +- \[RFC\] Introduce a new macro function: JSON\_INTERNAL\_CATCH [\#1187](https://github.com/nlohmann/json/pull/1187) ([simnalamburt](https://github.com/simnalamburt)) +- Fix unit tests that were silently skipped or crashed \(depending on the compiler\) [\#1176](https://github.com/nlohmann/json/pull/1176) ([grembo](https://github.com/grembo)) +- Refactor/no virtual sax [\#1153](https://github.com/nlohmann/json/pull/1153) ([theodelrieu](https://github.com/theodelrieu)) +- Fixed compiler error in VS 2015 for debug mode [\#1151](https://github.com/nlohmann/json/pull/1151) ([sonulohani](https://github.com/sonulohani)) +- Fix links to cppreference named requirements \(formerly concepts\) [\#1144](https://github.com/nlohmann/json/pull/1144) ([jrakow](https://github.com/jrakow)) +- meson: fix include directory [\#1142](https://github.com/nlohmann/json/pull/1142) ([jrakow](https://github.com/jrakow)) +- Feature/unordered map conversion [\#1138](https://github.com/nlohmann/json/pull/1138) ([theodelrieu](https://github.com/theodelrieu)) +- fixed compile error for \#1045 [\#1134](https://github.com/nlohmann/json/pull/1134) ([Daniel599](https://github.com/Daniel599)) +- test \(non\)equality for alt\_string implementation [\#1130](https://github.com/nlohmann/json/pull/1130) ([agrianius](https://github.com/agrianius)) +- remove stringstream dependency [\#1117](https://github.com/nlohmann/json/pull/1117) ([TinyTinni](https://github.com/TinyTinni)) +- Provide a from\_json overload for std::map [\#1089](https://github.com/nlohmann/json/pull/1089) ([theodelrieu](https://github.com/theodelrieu)) +- fix typo in README [\#1078](https://github.com/nlohmann/json/pull/1078) ([martin-mfg](https://github.com/martin-mfg)) +- Fix typo [\#1058](https://github.com/nlohmann/json/pull/1058) ([dns13](https://github.com/dns13)) +- Misc cmake packaging enhancements [\#1048](https://github.com/nlohmann/json/pull/1048) ([chuckatkins](https://github.com/chuckatkins)) +- Fixed incorrect LLVM version number in README [\#1047](https://github.com/nlohmann/json/pull/1047) ([jammehcow](https://github.com/jammehcow)) +- Fix trivial typo in comment. [\#1043](https://github.com/nlohmann/json/pull/1043) ([coryan](https://github.com/coryan)) +- Package Manager: Spack [\#1041](https://github.com/nlohmann/json/pull/1041) ([ax3l](https://github.com/ax3l)) +- CMake: 3.8+ is Sufficient [\#1040](https://github.com/nlohmann/json/pull/1040) ([ax3l](https://github.com/ax3l)) +- Added support for string\_view in C++17 [\#1028](https://github.com/nlohmann/json/pull/1028) ([gracicot](https://github.com/gracicot)) +- Added public target\_compile\_features for auto and constexpr [\#1026](https://github.com/nlohmann/json/pull/1026) ([ktonon](https://github.com/ktonon)) + +## [3.2.0](https://github.com/nlohmann/json/releases/tag/3.2.0) (2018-08-20) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.1.2...3.2.0) + +- Am I doing this wrong? Getting an empty string [\#1199](https://github.com/nlohmann/json/issues/1199) +- Incompatible Pointer Type [\#1196](https://github.com/nlohmann/json/issues/1196) +- json.exception.type\_error.316 [\#1195](https://github.com/nlohmann/json/issues/1195) +- Strange warnings in Code::Blocks 17.12, GNU GCC [\#1192](https://github.com/nlohmann/json/issues/1192) +- \[Question\] Current place in code to change floating point resolution [\#1191](https://github.com/nlohmann/json/issues/1191) +- Add key name when throwing type error [\#1189](https://github.com/nlohmann/json/issues/1189) +- Not able to include in visual studio code? [\#1188](https://github.com/nlohmann/json/issues/1188) +- Get an Index or row number of an element [\#1186](https://github.com/nlohmann/json/issues/1186) +- Difference between `merge_patch` and `update` [\#1183](https://github.com/nlohmann/json/issues/1183) +- Is there a way to get an element from a JSON without throwing an exception on failure? [\#1182](https://github.com/nlohmann/json/issues/1182) +- to\_string? [\#1181](https://github.com/nlohmann/json/issues/1181) +- How to cache a json object's pointer into a map? [\#1180](https://github.com/nlohmann/json/issues/1180) +- Can this library work within a Qt project for Android using Qt Creator? [\#1178](https://github.com/nlohmann/json/issues/1178) +- How to get all keys of one object? [\#1177](https://github.com/nlohmann/json/issues/1177) +- How can I only parse the first level and get the value as string? [\#1175](https://github.com/nlohmann/json/issues/1175) +- I have a query regarding nlohmann::basic\_json::basic\_json [\#1174](https://github.com/nlohmann/json/issues/1174) +- unordered\_map with vectors won't convert to json? [\#1173](https://github.com/nlohmann/json/issues/1173) +- return json objects from functions [\#1172](https://github.com/nlohmann/json/issues/1172) +- Problem when exporting to CBOR [\#1171](https://github.com/nlohmann/json/issues/1171) +- Roundtripping null to nullptr does not work [\#1169](https://github.com/nlohmann/json/issues/1169) +- MSVC fails to compile std::swap specialization for nlohmann::json [\#1168](https://github.com/nlohmann/json/issues/1168) +- Unexpected behaviour of is\_null - Part II [\#1167](https://github.com/nlohmann/json/issues/1167) +- Floating point imprecision [\#1166](https://github.com/nlohmann/json/issues/1166) +- Combine json objects into one? [\#1165](https://github.com/nlohmann/json/issues/1165) +- Is there any way to know if the object has changed? [\#1164](https://github.com/nlohmann/json/issues/1164) +- Value throws on null string [\#1163](https://github.com/nlohmann/json/issues/1163) +- Weird template issue in large project [\#1162](https://github.com/nlohmann/json/issues/1162) +- \_json returns a different result vs ::parse [\#1161](https://github.com/nlohmann/json/issues/1161) +- Showing difference between two json objects [\#1160](https://github.com/nlohmann/json/issues/1160) +- no instance of overloaded function "std::swap" matches the specified type [\#1159](https://github.com/nlohmann/json/issues/1159) +- resize\(...\)? [\#1157](https://github.com/nlohmann/json/issues/1157) +- Issue with struct nested in class' to\_json [\#1155](https://github.com/nlohmann/json/issues/1155) +- Deserialize std::map with std::nan [\#1154](https://github.com/nlohmann/json/issues/1154) +- Parse throwing errors [\#1149](https://github.com/nlohmann/json/issues/1149) +- cocoapod integration [\#1148](https://github.com/nlohmann/json/issues/1148) +- wstring parsing [\#1147](https://github.com/nlohmann/json/issues/1147) +- Is it possible to dump a two-dimensional array to "\[\[null\],\[1,2,3\]\]"? [\#1146](https://github.com/nlohmann/json/issues/1146) +- Want to write a class member variable and a struct variable \( this structure is inside the class\) to the json file [\#1145](https://github.com/nlohmann/json/issues/1145) +- Does json support converting an instance of a struct into json string? [\#1143](https://github.com/nlohmann/json/issues/1143) +- \#Most efficient way to search for child parameters \(recursive find?\) [\#1141](https://github.com/nlohmann/json/issues/1141) +- could not find to\_json\(\) method in T's namespace [\#1140](https://github.com/nlohmann/json/issues/1140) +- chars get treated as JSON numbers not JSON strings [\#1139](https://github.com/nlohmann/json/issues/1139) +- How do I count number of objects in array? [\#1137](https://github.com/nlohmann/json/issues/1137) +- Serializing a vector of classes? [\#1136](https://github.com/nlohmann/json/issues/1136) +- Compile error. Unable convert form nullptr to nullptr&& [\#1135](https://github.com/nlohmann/json/issues/1135) +- std::unordered\_map in struct, serialization [\#1133](https://github.com/nlohmann/json/issues/1133) +- dump\(\) can't handle umlauts [\#1131](https://github.com/nlohmann/json/issues/1131) +- Add a way to get a key reference from the iterator [\#1127](https://github.com/nlohmann/json/issues/1127) +- can't not parse "\\“ string [\#1123](https://github.com/nlohmann/json/issues/1123) +- if json file contain Internationalization chars , get exception [\#1122](https://github.com/nlohmann/json/issues/1122) +- How to use a json::iterator dereferenced value in code? [\#1120](https://github.com/nlohmann/json/issues/1120) +- Disable implicit conversions from json to std::initializer\_list\ for any T [\#1118](https://github.com/nlohmann/json/issues/1118) +- Implicit conversions to complex types can lead to surprising and confusing errors [\#1116](https://github.com/nlohmann/json/issues/1116) +- How can I write from\_json for a complex datatype that is not default constructible? [\#1115](https://github.com/nlohmann/json/issues/1115) +- Compile error in VS2015 when compiling unit-conversions.cpp [\#1114](https://github.com/nlohmann/json/issues/1114) +- ADL Serializer for std::any / boost::any [\#1113](https://github.com/nlohmann/json/issues/1113) +- Unexpected behaviour of is\_null [\#1112](https://github.com/nlohmann/json/issues/1112) +- How to resolve " undefined reference to `std::\_\_throw\_bad\_cast\(\)'" [\#1111](https://github.com/nlohmann/json/issues/1111) +- cannot compile on ubuntu 18.04 and 16.04 [\#1110](https://github.com/nlohmann/json/issues/1110) +- JSON representation for floating point values has too many digits [\#1109](https://github.com/nlohmann/json/issues/1109) +- Not working for classes containing "\_declspec\(dllimport\)" in their declaration [\#1108](https://github.com/nlohmann/json/issues/1108) +- Get keys from json object [\#1107](https://github.com/nlohmann/json/issues/1107) +- Cannot deserialize types using std::ratio [\#1105](https://github.com/nlohmann/json/issues/1105) +- i want to learn json [\#1104](https://github.com/nlohmann/json/issues/1104) +- Type checking during compile [\#1103](https://github.com/nlohmann/json/issues/1103) +- Iterate through sub items [\#1102](https://github.com/nlohmann/json/issues/1102) +- cppcheck failing for version 3.1.2 [\#1101](https://github.com/nlohmann/json/issues/1101) +- Deserializing std::map [\#1100](https://github.com/nlohmann/json/issues/1100) +- accessing key by reference [\#1098](https://github.com/nlohmann/json/issues/1098) +- clang 3.8.0 croaks while trying to compile with debug symbols [\#1097](https://github.com/nlohmann/json/issues/1097) +- Serialize a list of class objects with json [\#1096](https://github.com/nlohmann/json/issues/1096) +- Small question [\#1094](https://github.com/nlohmann/json/issues/1094) +- Upgrading to 3.x: to\_/from\_json with enum class [\#1093](https://github.com/nlohmann/json/issues/1093) +- Q: few questions about json construction [\#1092](https://github.com/nlohmann/json/issues/1092) +- general crayCC compilation failure [\#1091](https://github.com/nlohmann/json/issues/1091) +- Merge Patch clears original data [\#1090](https://github.com/nlohmann/json/issues/1090) +- \[Question\] how to use nlohmann/json in c++? [\#1088](https://github.com/nlohmann/json/issues/1088) +- C++17 decomposition declaration support [\#1087](https://github.com/nlohmann/json/issues/1087) +- \[Question\] Access multi-level json objects [\#1086](https://github.com/nlohmann/json/issues/1086) +- Serializing vector [\#1085](https://github.com/nlohmann/json/issues/1085) +- update nested value in multi hierarchy json object [\#1084](https://github.com/nlohmann/json/issues/1084) +- Overriding default values? [\#1083](https://github.com/nlohmann/json/issues/1083) +- detail namespace collision with Cereal? [\#1082](https://github.com/nlohmann/json/issues/1082) +- Error using json.dump\(\); [\#1081](https://github.com/nlohmann/json/issues/1081) +- Consuming TCP Stream [\#1080](https://github.com/nlohmann/json/issues/1080) +- Compilation error with strong typed enums in map in combination with namespaces [\#1079](https://github.com/nlohmann/json/issues/1079) +- cassert error [\#1076](https://github.com/nlohmann/json/issues/1076) +- Valid json data not being parsed [\#1075](https://github.com/nlohmann/json/issues/1075) +- Feature request :: Better testing for key existance without try/catch [\#1074](https://github.com/nlohmann/json/issues/1074) +- Hi, I have input like a.b.c and want to convert it to \"a\"{\"b\": \"c\"} form. Any suggestions how do I do this? Thanks. [\#1073](https://github.com/nlohmann/json/issues/1073) +- ADL deserializer not picked up for non default-constructible type [\#1072](https://github.com/nlohmann/json/issues/1072) +- Deserializing std::array doesn't compiler \(no insert\(\)\) [\#1071](https://github.com/nlohmann/json/issues/1071) +- Serializing OpenCV Mat problem [\#1070](https://github.com/nlohmann/json/issues/1070) +- Compilation error with ICPC compiler [\#1068](https://github.com/nlohmann/json/issues/1068) +- Not existing value, crash [\#1065](https://github.com/nlohmann/json/issues/1065) +- cyryllic symbols [\#1064](https://github.com/nlohmann/json/issues/1064) +- newbie usage question [\#1063](https://github.com/nlohmann/json/issues/1063) +- Trying j\["strTest"\] = "%A" produces "strTest": "-0X1.CCCCCCCCCCCCCP+205" [\#1062](https://github.com/nlohmann/json/issues/1062) +- convert json value to std::string??? [\#1061](https://github.com/nlohmann/json/issues/1061) +- Commented out test cases, should they be removed? [\#1060](https://github.com/nlohmann/json/issues/1060) +- different behaviour between clang and gcc with braced initialization [\#1059](https://github.com/nlohmann/json/issues/1059) +- json array: initialize with prescribed size and `resize` method. [\#1057](https://github.com/nlohmann/json/issues/1057) +- Is it possible to use exceptions istead of assertions? [\#1056](https://github.com/nlohmann/json/issues/1056) +- when using assign operator in with json object a static assertion fails.. [\#1055](https://github.com/nlohmann/json/issues/1055) +- Iterate over leafs of a JSON data structure: enrich the JSON pointer API [\#1054](https://github.com/nlohmann/json/issues/1054) +- \[Feature request\] Access by path [\#1053](https://github.com/nlohmann/json/issues/1053) +- document that implicit js -\> primitive conversion does not work for std::string::value\_type and why [\#1052](https://github.com/nlohmann/json/issues/1052) +- error: ‘BasicJsonType’ in namespace ‘::’ does not name a type [\#1051](https://github.com/nlohmann/json/issues/1051) +- Destructor is called when filling object through assignement [\#1050](https://github.com/nlohmann/json/issues/1050) +- Is this thing thread safe for reads? [\#1049](https://github.com/nlohmann/json/issues/1049) +- clang-tidy: Call to virtual function during construction [\#1046](https://github.com/nlohmann/json/issues/1046) +- Using STL algorithms with JSON containers with expected results? [\#1045](https://github.com/nlohmann/json/issues/1045) +- Usage with gtest/gmock not working as expected [\#1044](https://github.com/nlohmann/json/issues/1044) +- Consequences of from\_json / to\_json being in namespace of data struct. [\#1042](https://github.com/nlohmann/json/issues/1042) +- const\_reference operator\[\]\(const typename object\_t::key\_type& key\) const throw instead of assert [\#1039](https://github.com/nlohmann/json/issues/1039) +- Trying to retrieve data from nested objects [\#1038](https://github.com/nlohmann/json/issues/1038) +- Direct download link for json\_fwd.hpp? [\#1037](https://github.com/nlohmann/json/issues/1037) +- I know the library supports UTF-8, but failed to dump the value [\#1036](https://github.com/nlohmann/json/issues/1036) +- Putting a Vec3-like vector into a json object [\#1035](https://github.com/nlohmann/json/issues/1035) +- Ternary operator crash [\#1034](https://github.com/nlohmann/json/issues/1034) +- Issued with Clion Inspection Resolution since 2018.1 [\#1033](https://github.com/nlohmann/json/issues/1033) +- Some testcases fail and one never finishes [\#1032](https://github.com/nlohmann/json/issues/1032) +- Can this class work with wchar\_t / std::wstring? [\#1031](https://github.com/nlohmann/json/issues/1031) +- Makefile: Valgrind flags have no effect [\#1030](https://github.com/nlohmann/json/issues/1030) +- 「==〠Should be 「\>〠[\#1029](https://github.com/nlohmann/json/issues/1029) +- HOCON reader? [\#1027](https://github.com/nlohmann/json/issues/1027) +- add json string in previous string?? [\#1025](https://github.com/nlohmann/json/issues/1025) +- RFC: fluent parsing interface [\#1023](https://github.com/nlohmann/json/issues/1023) +- Does it support chinese character? [\#1022](https://github.com/nlohmann/json/issues/1022) +- to/from\_msgpack only works with standard typization [\#1021](https://github.com/nlohmann/json/issues/1021) +- Build failure using latest clang and GCC compilers [\#1020](https://github.com/nlohmann/json/issues/1020) +- can two json objects be concatenated? [\#1019](https://github.com/nlohmann/json/issues/1019) +- Erase by integer index [\#1018](https://github.com/nlohmann/json/issues/1018) +- Function find overload taking a json\_pointer [\#1017](https://github.com/nlohmann/json/issues/1017) +- I think should implement an parser function [\#1016](https://github.com/nlohmann/json/issues/1016) +- Readme gif [\#1015](https://github.com/nlohmann/json/issues/1015) +- Python bindings [\#1014](https://github.com/nlohmann/json/issues/1014) +- how to add two json string in single object?? [\#1012](https://github.com/nlohmann/json/issues/1012) +- how to serialize class Object \(convert data in object into json\)?? [\#1011](https://github.com/nlohmann/json/issues/1011) +- Enable forward declaration of json by making json a class instead of a using declaration [\#997](https://github.com/nlohmann/json/issues/997) +- compilation error while using intel c++ compiler 2018 [\#994](https://github.com/nlohmann/json/issues/994) +- How to create a json variable? [\#990](https://github.com/nlohmann/json/issues/990) +- istream \>\> json --- 1st character skipped in stream [\#976](https://github.com/nlohmann/json/issues/976) +- Add a SAX parser [\#971](https://github.com/nlohmann/json/issues/971) +- How to solve large json file? [\#927](https://github.com/nlohmann/json/issues/927) +- json\_pointer public push\_back, pop\_back [\#837](https://github.com/nlohmann/json/issues/837) +- Using input\_adapter in a slightly unexpected way [\#834](https://github.com/nlohmann/json/issues/834) + +## [v3.1.2](https://github.com/nlohmann/json/releases/tag/v3.1.2) (2018-03-14) + +[Full Changelog](https://github.com/nlohmann/json/compare/3.1.2...v3.1.2) + +- Allowing for user-defined string type in lexer/parser [\#1009](https://github.com/nlohmann/json/pull/1009) ([nlohmann](https://github.com/nlohmann)) +- dump to alternative string type, as defined in basic\_json template [\#1006](https://github.com/nlohmann/json/pull/1006) ([agrianius](https://github.com/agrianius)) +- Fix memory leak during parser callback [\#1001](https://github.com/nlohmann/json/pull/1001) ([nlohmann](https://github.com/nlohmann)) +- fixed misprinted condition detected by PVS Studio. [\#992](https://github.com/nlohmann/json/pull/992) ([bogemic](https://github.com/bogemic)) +- Fix/basic json conversion [\#986](https://github.com/nlohmann/json/pull/986) ([theodelrieu](https://github.com/theodelrieu)) +- Make integration section concise [\#981](https://github.com/nlohmann/json/pull/981) ([wla80](https://github.com/wla80)) + +## [3.1.2](https://github.com/nlohmann/json/releases/tag/3.1.2) (2018-03-14) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.1.1...3.1.2) + +- STL containers are always serialized to a nested array like \[\[1,2,3\]\] [\#1013](https://github.com/nlohmann/json/issues/1013) +- The library doesn't want to insert an unordered\_map [\#1010](https://github.com/nlohmann/json/issues/1010) +- Convert Json to uint8\_t [\#1008](https://github.com/nlohmann/json/issues/1008) +- How to compare two JSON objects? [\#1007](https://github.com/nlohmann/json/issues/1007) +- Syntax checking [\#1003](https://github.com/nlohmann/json/issues/1003) +- more than one operator '=' matches these operands [\#1002](https://github.com/nlohmann/json/issues/1002) +- How to check if key existed [\#1000](https://github.com/nlohmann/json/issues/1000) +- nlohmann::json::parse exhaust memory in go binding [\#999](https://github.com/nlohmann/json/issues/999) +- Range-based iteration over a non-array object [\#998](https://github.com/nlohmann/json/issues/998) +- get\ for types that are not default constructible [\#996](https://github.com/nlohmann/json/issues/996) +- Prevent Null values to appear in .dump\(\) [\#995](https://github.com/nlohmann/json/issues/995) +- number parsing [\#993](https://github.com/nlohmann/json/issues/993) +- C2664 \(C++/CLR\) cannot convert 'nullptr' to 'nullptr &&' [\#987](https://github.com/nlohmann/json/issues/987) +- Uniform initialization from another json object differs between gcc and clang. [\#985](https://github.com/nlohmann/json/issues/985) +- Problem with adding the lib as a submodule [\#983](https://github.com/nlohmann/json/issues/983) +- UTF-8/Unicode error [\#982](https://github.com/nlohmann/json/issues/982) +- "forcing MSVC stacktrace to show which T we're talking about." error [\#980](https://github.com/nlohmann/json/issues/980) +- reverse order of serialization [\#979](https://github.com/nlohmann/json/issues/979) +- Assigning between different json types [\#977](https://github.com/nlohmann/json/issues/977) +- Support serialisation of `unique_ptr<>` and `shared_ptr<>` [\#975](https://github.com/nlohmann/json/issues/975) +- Unexpected end of input \(not same as one before\) [\#974](https://github.com/nlohmann/json/issues/974) +- Segfault on direct initializing json object [\#973](https://github.com/nlohmann/json/issues/973) +- Segmentation fault on G++ when trying to assign json string literal to custom json type. [\#972](https://github.com/nlohmann/json/issues/972) +- os\_defines.h:44:19: error: missing binary operator before token "\(" [\#970](https://github.com/nlohmann/json/issues/970) +- Passing an iteration object by reference to a function [\#967](https://github.com/nlohmann/json/issues/967) +- Json and fmt::lib's format\_arg\(\) [\#964](https://github.com/nlohmann/json/issues/964) + +## [v3.1.1](https://github.com/nlohmann/json/releases/tag/v3.1.1) (2018-02-13) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.1.0...v3.1.1) + +- Updation of child object isn't reflected in parent Object [\#968](https://github.com/nlohmann/json/issues/968) +- How to add user defined C++ path to sublime text [\#966](https://github.com/nlohmann/json/issues/966) +- fast number parsing [\#965](https://github.com/nlohmann/json/issues/965) +- With non-unique keys, later stored entries are not taken into account anymore [\#963](https://github.com/nlohmann/json/issues/963) +- Timeout \(OSS-Fuzz 6034\) [\#962](https://github.com/nlohmann/json/issues/962) +- Incorrect parsing of indefinite length CBOR strings. [\#961](https://github.com/nlohmann/json/issues/961) +- Reload a json file at runtime without emptying my std::ifstream [\#959](https://github.com/nlohmann/json/issues/959) +- Split headers should be part of the release [\#956](https://github.com/nlohmann/json/issues/956) +- Coveralls shows no coverage data [\#953](https://github.com/nlohmann/json/issues/953) +- Feature request: Implicit conversion to bool [\#951](https://github.com/nlohmann/json/issues/951) +- converting json to vector of type with templated constructor [\#924](https://github.com/nlohmann/json/issues/924) +- No structured bindings support? [\#901](https://github.com/nlohmann/json/issues/901) +- \[Request\] Macro generating from\_json\(\) and to\_json\(\) [\#895](https://github.com/nlohmann/json/issues/895) +- basic\_json::value throws exception instead of returning default value [\#871](https://github.com/nlohmann/json/issues/871) + +- Fix constraints on from\_json\(CompatibleArrayType\) [\#969](https://github.com/nlohmann/json/pull/969) ([theodelrieu](https://github.com/theodelrieu)) +- Make coveralls watch the include folder [\#957](https://github.com/nlohmann/json/pull/957) ([theodelrieu](https://github.com/theodelrieu)) +- Fix links in README.md [\#955](https://github.com/nlohmann/json/pull/955) ([patrikhuber](https://github.com/patrikhuber)) +- Add a note about installing the library with cget [\#954](https://github.com/nlohmann/json/pull/954) ([pfultz2](https://github.com/pfultz2)) + +## [v3.1.0](https://github.com/nlohmann/json/releases/tag/v3.1.0) (2018-02-01) + +[Full Changelog](https://github.com/nlohmann/json/compare/3.1.0...v3.1.0) + +- Templatize std::string in binary\_reader \#941 [\#950](https://github.com/nlohmann/json/pull/950) ([kaidokert](https://github.com/kaidokert)) +- fix cmake install directory \(for real this time\) [\#944](https://github.com/nlohmann/json/pull/944) ([theodelrieu](https://github.com/theodelrieu)) +- Allow overriding THROW/CATCH/TRY macros with no-exceptions \#938 [\#940](https://github.com/nlohmann/json/pull/940) ([kaidokert](https://github.com/kaidokert)) +- Removed compiler warning about unused variable 'kMinExp' [\#936](https://github.com/nlohmann/json/pull/936) ([zerodefect](https://github.com/zerodefect)) +- Fix a typo in README.md [\#930](https://github.com/nlohmann/json/pull/930) ([Pipeliner](https://github.com/Pipeliner)) +- Howto installation of json\_fwd.hpp \(fixes \#923\) [\#925](https://github.com/nlohmann/json/pull/925) ([zerodefect](https://github.com/zerodefect)) +- fix sfinae on basic\_json UDT constructor [\#919](https://github.com/nlohmann/json/pull/919) ([theodelrieu](https://github.com/theodelrieu)) +- Floating-point formatting [\#915](https://github.com/nlohmann/json/pull/915) ([abolz](https://github.com/abolz)) +- Fix/cmake install [\#911](https://github.com/nlohmann/json/pull/911) ([theodelrieu](https://github.com/theodelrieu)) +- fix link to the documentation of the emplace function [\#900](https://github.com/nlohmann/json/pull/900) ([Dobiasd](https://github.com/Dobiasd)) +- JSON Merge Patch \(RFC 7396\) [\#876](https://github.com/nlohmann/json/pull/876) ([nlohmann](https://github.com/nlohmann)) +- Refactor/split it [\#700](https://github.com/nlohmann/json/pull/700) ([theodelrieu](https://github.com/theodelrieu)) + +## [3.1.0](https://github.com/nlohmann/json/releases/tag/3.1.0) (2018-02-01) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.0.1...3.1.0) + +- I have a proposal [\#949](https://github.com/nlohmann/json/issues/949) +- VERSION define\(s\) [\#948](https://github.com/nlohmann/json/issues/948) +- v3.0.1 compile error in icc 16.0.4 [\#947](https://github.com/nlohmann/json/issues/947) +- Use in VS2017 15.5.5 [\#946](https://github.com/nlohmann/json/issues/946) +- Process for reporting Security Bugs? [\#945](https://github.com/nlohmann/json/issues/945) +- Please expose a NLOHMANN\_JSON\_VERSION macro [\#943](https://github.com/nlohmann/json/issues/943) +- Change header include directory to nlohmann/json [\#942](https://github.com/nlohmann/json/issues/942) +- string\_type in binary\_reader [\#941](https://github.com/nlohmann/json/issues/941) +- compile error with clang 5.0 -std=c++1z and no string\_view [\#939](https://github.com/nlohmann/json/issues/939) +- Allow overriding JSON\_THROW to something else than abort\(\) [\#938](https://github.com/nlohmann/json/issues/938) +- Handle invalid string in Json file [\#937](https://github.com/nlohmann/json/issues/937) +- Unused variable 'kMinExp' [\#935](https://github.com/nlohmann/json/issues/935) +- yytext is already defined [\#933](https://github.com/nlohmann/json/issues/933) +- Equality operator fails [\#931](https://github.com/nlohmann/json/issues/931) +- use in visual studio 2015 [\#929](https://github.com/nlohmann/json/issues/929) +- Relative includes of json\_fwd.hpp in detail/meta.hpp. \[Develop branch\] [\#928](https://github.com/nlohmann/json/issues/928) +- GCC 7.x issue [\#926](https://github.com/nlohmann/json/issues/926) +- json\_fwd.hpp not installed [\#923](https://github.com/nlohmann/json/issues/923) +- Use Google Benchmarks [\#921](https://github.com/nlohmann/json/issues/921) +- Move class json\_pointer to separate file [\#920](https://github.com/nlohmann/json/issues/920) +- Unable to locate 'to\_json\(\)' and 'from\_json\(\)' methods in the same namespace [\#917](https://github.com/nlohmann/json/issues/917) +- \[answered\]Read key1 from .value example [\#914](https://github.com/nlohmann/json/issues/914) +- Don't use `define private public` in test files [\#913](https://github.com/nlohmann/json/issues/913) +- value\(\) template argument type deduction [\#912](https://github.com/nlohmann/json/issues/912) +- Installation path is incorrect [\#910](https://github.com/nlohmann/json/issues/910) +- H [\#909](https://github.com/nlohmann/json/issues/909) +- Build failure using clang 5 [\#908](https://github.com/nlohmann/json/issues/908) +- Amalgate [\#907](https://github.com/nlohmann/json/issues/907) +- Update documentation and tests wrt. split headers [\#906](https://github.com/nlohmann/json/issues/906) +- Lib not working on ubuntu 16.04 [\#905](https://github.com/nlohmann/json/issues/905) +- Problem when writing to file. [\#904](https://github.com/nlohmann/json/issues/904) +- C2864 error when compiling with VS2015 and VS 2017 [\#903](https://github.com/nlohmann/json/issues/903) +- \[json.exception.type\_error.304\] cannot use at\(\) with object [\#902](https://github.com/nlohmann/json/issues/902) +- How do I forward nlohmann::json declaration? [\#899](https://github.com/nlohmann/json/issues/899) +- How to effectively store binary data? [\#898](https://github.com/nlohmann/json/issues/898) +- How to get the length of a JSON string without retrieving its std::string? [\#897](https://github.com/nlohmann/json/issues/897) +- Regression Tests Failure using "ctest" [\#887](https://github.com/nlohmann/json/issues/887) +- Discuss: add JSON Merge Patch \(RFC 7396\)? [\#877](https://github.com/nlohmann/json/issues/877) +- Discuss: replace static "iterator\_wrapper" function with "items" member function [\#874](https://github.com/nlohmann/json/issues/874) +- Make optional user-data available in from\_json [\#864](https://github.com/nlohmann/json/issues/864) +- Casting to std::string not working in VS2015 [\#861](https://github.com/nlohmann/json/issues/861) +- Sequential reading of JSON arrays [\#851](https://github.com/nlohmann/json/issues/851) +- Idea: Handle Multimaps Better [\#816](https://github.com/nlohmann/json/issues/816) +- Floating point rounding [\#777](https://github.com/nlohmann/json/issues/777) +- Loss of precision when serializing \ [\#360](https://github.com/nlohmann/json/issues/360) + +## [v3.0.1](https://github.com/nlohmann/json/releases/tag/v3.0.1) (2017-12-29) + +[Full Changelog](https://github.com/nlohmann/json/compare/3.0.1...v3.0.1) + +- Includes CTest module/adds BUILD\_TESTING option [\#885](https://github.com/nlohmann/json/pull/885) ([TinyTinni](https://github.com/TinyTinni)) +- Fix MSVC warning C4819 [\#882](https://github.com/nlohmann/json/pull/882) ([erengy](https://github.com/erengy)) +- Merge branch 'develop' into coverity\_scan [\#880](https://github.com/nlohmann/json/pull/880) ([nlohmann](https://github.com/nlohmann)) +- :wrench: Fix up a few more effc++ items [\#858](https://github.com/nlohmann/json/pull/858) ([mattismyname](https://github.com/mattismyname)) + +## [3.0.1](https://github.com/nlohmann/json/releases/tag/3.0.1) (2017-12-29) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.0.0...3.0.1) + +- Problem parsing array to global vector [\#896](https://github.com/nlohmann/json/issues/896) +- Invalid RFC6902 copy operation succeeds [\#894](https://github.com/nlohmann/json/issues/894) +- How to rename a key during looping? [\#893](https://github.com/nlohmann/json/issues/893) +- clang++-6.0 \(6.0.0-svn321357-1\) warning [\#892](https://github.com/nlohmann/json/issues/892) +- Make json.hpp aware of the modules TS? [\#891](https://github.com/nlohmann/json/issues/891) +- All enum values not handled in switch cases. \( -Wswitch-enum \) [\#889](https://github.com/nlohmann/json/issues/889) +- JSON Pointer resolve failure resulting in incorrect exception code [\#888](https://github.com/nlohmann/json/issues/888) +- Unexpected nested arrays from std::vector [\#886](https://github.com/nlohmann/json/issues/886) +- erase multiple elements from a json object [\#884](https://github.com/nlohmann/json/issues/884) +- Container function overview in Doxygen is not updated [\#883](https://github.com/nlohmann/json/issues/883) +- How to use this for binary file uploads [\#881](https://github.com/nlohmann/json/issues/881) +- Allow setting JSON\_BuildTests=OFF from parent CMakeLists.txt [\#846](https://github.com/nlohmann/json/issues/846) +- Unit test fails for local-independent str-to-num [\#845](https://github.com/nlohmann/json/issues/845) +- Another idea about type support [\#774](https://github.com/nlohmann/json/issues/774) + +## [v3.0.0](https://github.com/nlohmann/json/releases/tag/v3.0.0) (2017-12-17) + +[Full Changelog](https://github.com/nlohmann/json/compare/3.0.0...v3.0.0) + +- :white\_check\_mark: re-added tests for algorithms [\#879](https://github.com/nlohmann/json/pull/879) ([nlohmann](https://github.com/nlohmann)) +- Overworked library toward 3.0.0 release [\#875](https://github.com/nlohmann/json/pull/875) ([nlohmann](https://github.com/nlohmann)) +- :rotating\_light: remove C4996 warnings \#872 [\#873](https://github.com/nlohmann/json/pull/873) ([nlohmann](https://github.com/nlohmann)) +- :boom: throwing an exception in case dump encounters a non-UTF-8 string \#838 [\#870](https://github.com/nlohmann/json/pull/870) ([nlohmann](https://github.com/nlohmann)) +- :memo: fixing documentation \#867 [\#868](https://github.com/nlohmann/json/pull/868) ([nlohmann](https://github.com/nlohmann)) +- iter\_impl template conformance with C++17 [\#860](https://github.com/nlohmann/json/pull/860) ([bogemic](https://github.com/bogemic)) +- Std allocator conformance cpp17 [\#856](https://github.com/nlohmann/json/pull/856) ([bogemic](https://github.com/bogemic)) +- cmake: use BUILD\_INTERFACE/INSTALL\_INTERFACE [\#855](https://github.com/nlohmann/json/pull/855) ([theodelrieu](https://github.com/theodelrieu)) +- to/from\_json: add a MSVC-specific static\_assert to force a stacktrace [\#854](https://github.com/nlohmann/json/pull/854) ([theodelrieu](https://github.com/theodelrieu)) +- Add .natvis for MSVC debug view [\#844](https://github.com/nlohmann/json/pull/844) ([TinyTinni](https://github.com/TinyTinni)) +- Updated hunter package links [\#829](https://github.com/nlohmann/json/pull/829) ([jowr](https://github.com/jowr)) +- Typos README [\#811](https://github.com/nlohmann/json/pull/811) ([Itja](https://github.com/Itja)) +- add forwarding references to json\_ref constructor [\#807](https://github.com/nlohmann/json/pull/807) ([theodelrieu](https://github.com/theodelrieu)) +- Add transparent comparator and perfect forwarding support to find\(\) and count\(\) [\#795](https://github.com/nlohmann/json/pull/795) ([jseward](https://github.com/jseward)) +- Error : 'identifier "size\_t" is undefined' in linux [\#793](https://github.com/nlohmann/json/pull/793) ([sonulohani](https://github.com/sonulohani)) +- Fix Visual Studio 2017 warnings [\#788](https://github.com/nlohmann/json/pull/788) ([jseward](https://github.com/jseward)) +- Fix warning C4706 on Visual Studio 2017 [\#785](https://github.com/nlohmann/json/pull/785) ([jseward](https://github.com/jseward)) +- Set GENERATE\_TAGFILE in Doxyfile [\#783](https://github.com/nlohmann/json/pull/783) ([eld00d](https://github.com/eld00d)) +- using more CMake [\#765](https://github.com/nlohmann/json/pull/765) ([nlohmann](https://github.com/nlohmann)) +- Simplified istream handing \#367 [\#764](https://github.com/nlohmann/json/pull/764) ([pjkundert](https://github.com/pjkundert)) +- Add info for the vcpkg package. [\#753](https://github.com/nlohmann/json/pull/753) ([gregmarr](https://github.com/gregmarr)) +- fix from\_json implementation for pair/tuple [\#708](https://github.com/nlohmann/json/pull/708) ([theodelrieu](https://github.com/theodelrieu)) +- Update json.hpp [\#686](https://github.com/nlohmann/json/pull/686) ([GoWebProd](https://github.com/GoWebProd)) +- Remove duplicate word [\#685](https://github.com/nlohmann/json/pull/685) ([daixtrose](https://github.com/daixtrose)) +- To fix compilation issue for intel OSX compiler [\#682](https://github.com/nlohmann/json/pull/682) ([kbthomp1](https://github.com/kbthomp1)) +- Digraph warning [\#679](https://github.com/nlohmann/json/pull/679) ([traits](https://github.com/traits)) +- massage -\> message [\#678](https://github.com/nlohmann/json/pull/678) ([DmitryKuk](https://github.com/DmitryKuk)) +- Fix "not constraint" grammar in docs [\#674](https://github.com/nlohmann/json/pull/674) ([wincent](https://github.com/wincent)) +- Add documentation for integration with CMake and hunter [\#671](https://github.com/nlohmann/json/pull/671) ([dan-42](https://github.com/dan-42)) +- REFACTOR: rewrite CMakeLists.txt for better inlcude and reuse [\#669](https://github.com/nlohmann/json/pull/669) ([dan-42](https://github.com/dan-42)) +- enable\_testing only if the JSON\_BuildTests is ON [\#666](https://github.com/nlohmann/json/pull/666) ([effolkronium](https://github.com/effolkronium)) +- Support moving from rvalues in std::initializer\_list [\#663](https://github.com/nlohmann/json/pull/663) ([himikof](https://github.com/himikof)) +- add ensure\_ascii parameter to dump. \#330 [\#654](https://github.com/nlohmann/json/pull/654) ([ryanjmulder](https://github.com/ryanjmulder)) +- Rename BuildTests to JSON\_BuildTests [\#652](https://github.com/nlohmann/json/pull/652) ([olegendo](https://github.com/olegendo)) +- Don't include \, use std::make\_shared [\#650](https://github.com/nlohmann/json/pull/650) ([olegendo](https://github.com/olegendo)) +- Refacto/split basic json [\#643](https://github.com/nlohmann/json/pull/643) ([theodelrieu](https://github.com/theodelrieu)) +- fix typo in operator\_\_notequal example [\#630](https://github.com/nlohmann/json/pull/630) ([Chocobo1](https://github.com/Chocobo1)) +- Fix MSVC warning C4819 [\#629](https://github.com/nlohmann/json/pull/629) ([Chocobo1](https://github.com/Chocobo1)) +- \[BugFix\] Add parentheses around std::min [\#626](https://github.com/nlohmann/json/pull/626) ([koemeet](https://github.com/koemeet)) +- add pair/tuple conversions [\#624](https://github.com/nlohmann/json/pull/624) ([theodelrieu](https://github.com/theodelrieu)) +- remove std::pair support [\#615](https://github.com/nlohmann/json/pull/615) ([theodelrieu](https://github.com/theodelrieu)) +- Add pair support, fix CompatibleObject conversions \(fixes \#600\) [\#609](https://github.com/nlohmann/json/pull/609) ([theodelrieu](https://github.com/theodelrieu)) +- \#550 Fix iterator related compiling issues for Intel icc [\#598](https://github.com/nlohmann/json/pull/598) ([HenryRLee](https://github.com/HenryRLee)) +- Issue \#593 Fix the arithmetic operators in the iterator and reverse iterator [\#595](https://github.com/nlohmann/json/pull/595) ([HenryRLee](https://github.com/HenryRLee)) +- fix doxygen error of basic\_json::get\(\) [\#583](https://github.com/nlohmann/json/pull/583) ([zhaohuaxishi](https://github.com/zhaohuaxishi)) +- Fixing assignement for iterator wrapper second, and adding unit test [\#579](https://github.com/nlohmann/json/pull/579) ([Type1J](https://github.com/Type1J)) +- Adding first and second properties to iteration\_proxy\_internal [\#578](https://github.com/nlohmann/json/pull/578) ([Type1J](https://github.com/Type1J)) +- Adding support for Meson. [\#576](https://github.com/nlohmann/json/pull/576) ([Type1J](https://github.com/Type1J)) +- add enum class default conversions [\#545](https://github.com/nlohmann/json/pull/545) ([theodelrieu](https://github.com/theodelrieu)) +- Properly pop diagnostics [\#540](https://github.com/nlohmann/json/pull/540) ([tinloaf](https://github.com/tinloaf)) +- Add Visual Studio 17 image to appveyor build matrix [\#536](https://github.com/nlohmann/json/pull/536) ([vpetrigo](https://github.com/vpetrigo)) +- UTF8 encoding enhancement [\#534](https://github.com/nlohmann/json/pull/534) ([TedLyngmo](https://github.com/TedLyngmo)) +- Fix typo [\#530](https://github.com/nlohmann/json/pull/530) ([berkus](https://github.com/berkus)) +- Make exception base class visible in basic\_json [\#526](https://github.com/nlohmann/json/pull/526) ([krzysztofwos](https://github.com/krzysztofwos)) +- :art: Namespace `uint8_t` from the C++ stdlib [\#510](https://github.com/nlohmann/json/pull/510) ([alex-weej](https://github.com/alex-weej)) +- add to\_json method for C arrays [\#508](https://github.com/nlohmann/json/pull/508) ([theodelrieu](https://github.com/theodelrieu)) +- Fix -Weffc++ warnings \(GNU 6.3.1\) [\#496](https://github.com/nlohmann/json/pull/496) ([TedLyngmo](https://github.com/TedLyngmo)) + +## [3.0.0](https://github.com/nlohmann/json/releases/tag/3.0.0) (2017-12-17) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.1.1...3.0.0) + +- unicode strings [\#878](https://github.com/nlohmann/json/issues/878) +- Visual Studio 2017 15.5 C++17 std::allocator deprecations [\#872](https://github.com/nlohmann/json/issues/872) +- Typo "excpetion" [\#869](https://github.com/nlohmann/json/issues/869) +- Explicit array example in README.md incorrect [\#867](https://github.com/nlohmann/json/issues/867) +- why don't you release this from Feb. ? [\#865](https://github.com/nlohmann/json/issues/865) +- json::parse throws std::invalid\_argument when processing string generated by json::dump\(\) [\#863](https://github.com/nlohmann/json/issues/863) +- code analysis: potential bug? [\#859](https://github.com/nlohmann/json/issues/859) +- MSVC2017, 15.5 new issues. [\#857](https://github.com/nlohmann/json/issues/857) +- very basic: fetching string value/content without quotes [\#853](https://github.com/nlohmann/json/issues/853) +- Ambiguous function call to get with pointer type and constant json object in VS2015 \(15.4.4\) [\#852](https://github.com/nlohmann/json/issues/852) +- How to put object in the array as a member? [\#850](https://github.com/nlohmann/json/issues/850) +- misclick, please ignore [\#849](https://github.com/nlohmann/json/issues/849) +- Make XML great again. [\#847](https://github.com/nlohmann/json/issues/847) +- Converting to array not working [\#843](https://github.com/nlohmann/json/issues/843) +- Iteration weirdness [\#842](https://github.com/nlohmann/json/issues/842) +- Use reference or pointer as Object value [\#841](https://github.com/nlohmann/json/issues/841) +- Ambiguity in parsing nested maps [\#840](https://github.com/nlohmann/json/issues/840) +- could not find from\_json\(\) method in T's namespace [\#839](https://github.com/nlohmann/json/issues/839) +- Incorrect parse error with binary data in keys? [\#838](https://github.com/nlohmann/json/issues/838) +- using dump\(\) when std::wstring is StringType with VS2017 [\#836](https://github.com/nlohmann/json/issues/836) +- Show the path of the currently parsed value when an error occurs [\#835](https://github.com/nlohmann/json/issues/835) +- Repetitive data type while reading [\#833](https://github.com/nlohmann/json/issues/833) +- Storing multiple types inside map [\#831](https://github.com/nlohmann/json/issues/831) +- Application terminating [\#830](https://github.com/nlohmann/json/issues/830) +- Missing CMake hunter package? [\#828](https://github.com/nlohmann/json/issues/828) +- std::map\ from json object yields C2665: 'std::pair\::pair': none of the 2 overloads could convert all the argument types [\#827](https://github.com/nlohmann/json/issues/827) +- object.dump gives quoted string, want to use .dump\(\) to generate javascripts. [\#826](https://github.com/nlohmann/json/issues/826) +- Assertion failed on \["NoExistKey"\] of an not existing key of const json& [\#825](https://github.com/nlohmann/json/issues/825) +- vs2015 error : static member will remain uninitialized at runtime but use in constant-expressions is supported [\#824](https://github.com/nlohmann/json/issues/824) +- Code Checking Warnings from json.hpp on VS2017 Community [\#821](https://github.com/nlohmann/json/issues/821) +- Missing iostream in try online [\#820](https://github.com/nlohmann/json/issues/820) +- Floating point value loses decimal point during dump [\#818](https://github.com/nlohmann/json/issues/818) +- Conan package for the library [\#817](https://github.com/nlohmann/json/issues/817) +- stream error [\#815](https://github.com/nlohmann/json/issues/815) +- Link error when using find\(\) on the latest commit [\#814](https://github.com/nlohmann/json/issues/814) +- ABI issue with json object between 2 shared libraries [\#813](https://github.com/nlohmann/json/issues/813) +- scan\_string\(\) return token\_type::parse\_error; when parse ansi file [\#812](https://github.com/nlohmann/json/issues/812) +- segfault when using fifo\_map with json [\#810](https://github.com/nlohmann/json/issues/810) +- This shit is shit [\#809](https://github.com/nlohmann/json/issues/809) +- \_finite and \_isnan are no members of "std" [\#808](https://github.com/nlohmann/json/issues/808) +- how to print out the line which causing exception? [\#806](https://github.com/nlohmann/json/issues/806) +- {} uses copy constructor, while = does not [\#805](https://github.com/nlohmann/json/issues/805) +- json.hpp:8955: multiple definition of function that is not defined twice or more. [\#804](https://github.com/nlohmann/json/issues/804) +- \[question\] to\_json for base and derived class [\#803](https://github.com/nlohmann/json/issues/803) +- Misleading error message - unexpected '"' - on incorrect utf-8 symbol [\#802](https://github.com/nlohmann/json/issues/802) +- json data = std::string\_view\("hi"\); doesn't work? [\#801](https://github.com/nlohmann/json/issues/801) +- Thread safety of parse\(\) [\#800](https://github.com/nlohmann/json/issues/800) +- Numbers as strings [\#799](https://github.com/nlohmann/json/issues/799) +- Tests failing on arm [\#797](https://github.com/nlohmann/json/issues/797) +- Using your library \(without modification\) in another library [\#796](https://github.com/nlohmann/json/issues/796) +- Iterating over sub-object [\#794](https://github.com/nlohmann/json/issues/794) +- how to get the json object again from which printed by the method of dump\(\) [\#792](https://github.com/nlohmann/json/issues/792) +- ppa to include source [\#791](https://github.com/nlohmann/json/issues/791) +- Different include paths in macOS and Ubuntu [\#790](https://github.com/nlohmann/json/issues/790) +- Missing break after line 12886 in switch/case [\#789](https://github.com/nlohmann/json/issues/789) +- All unit tests fail? [\#787](https://github.com/nlohmann/json/issues/787) +- More use of move semantics in deserialization [\#786](https://github.com/nlohmann/json/issues/786) +- warning C4706 - Visual Studio 2017 \(/W4\) [\#784](https://github.com/nlohmann/json/issues/784) +- Compile error in clang 5.0 [\#782](https://github.com/nlohmann/json/issues/782) +- Error Installing appium\_lib with Ruby v2.4.2 Due to JSON [\#781](https://github.com/nlohmann/json/issues/781) +- ::get\\(\) fails in new\(er\) release \[MSVC\] [\#780](https://github.com/nlohmann/json/issues/780) +- Type Conversion [\#779](https://github.com/nlohmann/json/issues/779) +- Segfault on nested parsing [\#778](https://github.com/nlohmann/json/issues/778) +- Build warnings: shadowing exception id [\#776](https://github.com/nlohmann/json/issues/776) +- multi-level JSON support. [\#775](https://github.com/nlohmann/json/issues/775) +- SIGABRT on dump\(\) [\#773](https://github.com/nlohmann/json/issues/773) +- \[Question\] Custom StringType template parameter \(possibility for a KeyType template parameter\) [\#772](https://github.com/nlohmann/json/issues/772) +- constexpr ALL the Things! [\#771](https://github.com/nlohmann/json/issues/771) +- error: ‘BasicJsonType’ in namespace ‘::’ does not name a type [\#770](https://github.com/nlohmann/json/issues/770) +- Program calls abort function [\#769](https://github.com/nlohmann/json/issues/769) +- \[Question\] Floating point resolution config during dump\(\) ? [\#768](https://github.com/nlohmann/json/issues/768) +- make check - no test ran [\#767](https://github.com/nlohmann/json/issues/767) +- The library cannot work properly with custom allocator based containers [\#766](https://github.com/nlohmann/json/issues/766) +- Documentation or feature request. [\#763](https://github.com/nlohmann/json/issues/763) +- warnings in msvc about mix/max macro while windows.h is used in the project [\#762](https://github.com/nlohmann/json/issues/762) +- std::signbit ambiguous [\#761](https://github.com/nlohmann/json/issues/761) +- How to use value for std::experimental::optional type? [\#760](https://github.com/nlohmann/json/issues/760) +- Cannot load json file properly [\#759](https://github.com/nlohmann/json/issues/759) +- Compilation error with unordered\_map\< int, int \> [\#758](https://github.com/nlohmann/json/issues/758) +- CBOR string [\#757](https://github.com/nlohmann/json/issues/757) +- Proposal: out\_of\_range should be a subclass of std::out\_of\_range [\#756](https://github.com/nlohmann/json/issues/756) +- Compiling with icpc [\#755](https://github.com/nlohmann/json/issues/755) +- Getter is setting the value to null if the key does not exist [\#754](https://github.com/nlohmann/json/issues/754) +- parsing works sometimes and crashes others [\#752](https://github.com/nlohmann/json/issues/752) +- Static\_assert failed "incompatible pointer type" with Xcode [\#751](https://github.com/nlohmann/json/issues/751) +- user-defined literal operator not found [\#750](https://github.com/nlohmann/json/issues/750) +- getting clean string from it.key\(\) [\#748](https://github.com/nlohmann/json/issues/748) +- Best method for exploring and obtaining values of nested json objects when the names are not known beforehand? [\#747](https://github.com/nlohmann/json/issues/747) +- null char at the end of string [\#746](https://github.com/nlohmann/json/issues/746) +- Incorrect sample for operator \>\> in docs [\#745](https://github.com/nlohmann/json/issues/745) +- User-friendly documentation [\#744](https://github.com/nlohmann/json/issues/744) +- Retrieve all values that match a json path [\#743](https://github.com/nlohmann/json/issues/743) +- Compilation issue with gcc 7.2 [\#742](https://github.com/nlohmann/json/issues/742) +- CMake target nlohmann\_json does not have src into its interface includes [\#741](https://github.com/nlohmann/json/issues/741) +- Error when serializing empty json: type must be string, but is object [\#740](https://github.com/nlohmann/json/issues/740) +- Conversion error for std::map\ [\#739](https://github.com/nlohmann/json/issues/739) +- Dumping Json to file as array [\#738](https://github.com/nlohmann/json/issues/738) +- nesting json objects [\#737](https://github.com/nlohmann/json/issues/737) +- where to find general help? [\#736](https://github.com/nlohmann/json/issues/736) +- Compilation Error on Clang 5.0 Upgrade [\#735](https://github.com/nlohmann/json/issues/735) +- Compilation error with std::map\ on vs 2015 [\#734](https://github.com/nlohmann/json/issues/734) +- Benchmarks for Binary formats [\#733](https://github.com/nlohmann/json/issues/733) +- Support \n symbols in json string. [\#731](https://github.com/nlohmann/json/issues/731) +- Project's name is too generic and hard to search for [\#730](https://github.com/nlohmann/json/issues/730) +- Visual Studio 2015 IntelliTrace problems [\#729](https://github.com/nlohmann/json/issues/729) +- How to erase nested objects inside other objects? [\#728](https://github.com/nlohmann/json/issues/728) +- Serialization for CBOR [\#726](https://github.com/nlohmann/json/issues/726) +- Using json Object as value in a map [\#725](https://github.com/nlohmann/json/issues/725) +- std::regex and nlohmann::json value [\#724](https://github.com/nlohmann/json/issues/724) +- Warnings when compiling with VisualStudio 2015 [\#723](https://github.com/nlohmann/json/issues/723) +- Has this lib the unicode \(wstring\) support? [\#722](https://github.com/nlohmann/json/issues/722) +- When will be 3.0 in master? [\#721](https://github.com/nlohmann/json/issues/721) +- Determine the type from error message. [\#720](https://github.com/nlohmann/json/issues/720) +- Compile-Error C2100 \(MS VS2015\) in line 887 json.hpp [\#719](https://github.com/nlohmann/json/issues/719) +- from\_json not working for boost::optional example [\#718](https://github.com/nlohmann/json/issues/718) +- about from\_json and to\_json function [\#717](https://github.com/nlohmann/json/issues/717) +- How to detect parse failure? [\#715](https://github.com/nlohmann/json/issues/715) +- Parse throw std::ios\_base::failure exception when failbit set to true [\#714](https://github.com/nlohmann/json/issues/714) +- Is there a way of format just making a pretty print without changing the key's orders ? [\#713](https://github.com/nlohmann/json/issues/713) +- Serialization of array of not same model items [\#712](https://github.com/nlohmann/json/issues/712) +- pointer to json parse vector [\#711](https://github.com/nlohmann/json/issues/711) +- Gtest SEH Exception [\#709](https://github.com/nlohmann/json/issues/709) +- broken from\_json implementation for pair and tuple [\#707](https://github.com/nlohmann/json/issues/707) +- Unevaluated lambda in assert breaks gcc 7 build [\#705](https://github.com/nlohmann/json/issues/705) +- Issues when adding values to firebase database [\#704](https://github.com/nlohmann/json/issues/704) +- Floating point equality - revisited [\#703](https://github.com/nlohmann/json/issues/703) +- Conversion from valarray\ to json fails to build [\#702](https://github.com/nlohmann/json/issues/702) +- internal compiler error \(gcc7\) [\#701](https://github.com/nlohmann/json/issues/701) +- One build system to rule them all [\#698](https://github.com/nlohmann/json/issues/698) +- Generated nlohmann\_jsonConfig.cmake does not set JSON\_INCLUDE\_DIR [\#695](https://github.com/nlohmann/json/issues/695) +- support the Chinese language in json string [\#694](https://github.com/nlohmann/json/issues/694) +- NaN problem within develop branch [\#693](https://github.com/nlohmann/json/issues/693) +- Please post example of specialization for boost::filesystem [\#692](https://github.com/nlohmann/json/issues/692) +- Impossible to do an array of composite objects [\#691](https://github.com/nlohmann/json/issues/691) +- How to save json to file? [\#690](https://github.com/nlohmann/json/issues/690) +- my simple json parser [\#689](https://github.com/nlohmann/json/issues/689) +- problem with new struct parsing syntax [\#688](https://github.com/nlohmann/json/issues/688) +- Parse error while parse the json string contains UTF 8 encoded document bytes string [\#684](https://github.com/nlohmann/json/issues/684) +- \[question\] how to get a string value by pointer [\#683](https://github.com/nlohmann/json/issues/683) +- create json object from string variable [\#681](https://github.com/nlohmann/json/issues/681) +- adl\_serializer and CRTP [\#680](https://github.com/nlohmann/json/issues/680) +- Is there a way to control the precision of serialized floating point numbers? [\#677](https://github.com/nlohmann/json/issues/677) +- Is there a way to get the path of a value? [\#676](https://github.com/nlohmann/json/issues/676) +- Could the parser locate errors to line? [\#675](https://github.com/nlohmann/json/issues/675) +- There is performance inefficiency found by coverity tool json2.1.1/include/nlohmann/json.hpp [\#673](https://github.com/nlohmann/json/issues/673) +- include problem, when cmake on osx [\#672](https://github.com/nlohmann/json/issues/672) +- Operator= ambiguous in C++1z and GCC 7.1.1 [\#670](https://github.com/nlohmann/json/issues/670) +- should't the cmake install target be to nlohman/json.hpp [\#668](https://github.com/nlohmann/json/issues/668) +- deserialise from `std::vector` [\#667](https://github.com/nlohmann/json/issues/667) +- How to iterate? [\#665](https://github.com/nlohmann/json/issues/665) +- could this json lib work on windows? [\#664](https://github.com/nlohmann/json/issues/664) +- How does from\_json work? [\#662](https://github.com/nlohmann/json/issues/662) +- insert\(or merge\) object should replace same key , not ignore [\#661](https://github.com/nlohmann/json/issues/661) +- Parse method doesn't handle newlines. [\#659](https://github.com/nlohmann/json/issues/659) +- Compilation "note" on GCC 6 ARM [\#658](https://github.com/nlohmann/json/issues/658) +- Adding additional push\_back/operator+= rvalue overloads for JSON object [\#657](https://github.com/nlohmann/json/issues/657) +- dump's parameter "ensure\_ascii" creates too long sequences [\#656](https://github.com/nlohmann/json/issues/656) +- Question: parsing `void *` [\#655](https://github.com/nlohmann/json/issues/655) +- how should I check a string is valid JSON string ? [\#653](https://github.com/nlohmann/json/issues/653) +- Question: thread safety of read only accesses [\#651](https://github.com/nlohmann/json/issues/651) +- Eclipse: Method 'size' could not be resolved [\#649](https://github.com/nlohmann/json/issues/649) +- Update/Add object fields [\#648](https://github.com/nlohmann/json/issues/648) +- No exception raised for Out Of Range input of numbers [\#647](https://github.com/nlohmann/json/issues/647) +- Package Name [\#646](https://github.com/nlohmann/json/issues/646) +- What is the meaning of operator\[\]\(T\* key\) [\#645](https://github.com/nlohmann/json/issues/645) +- Which is the correct way to json objects as parameters to functions? [\#644](https://github.com/nlohmann/json/issues/644) +- Method to get string representations of values [\#642](https://github.com/nlohmann/json/issues/642) +- CBOR serialization of a given JSON value does not serialize [\#641](https://github.com/nlohmann/json/issues/641) +- Are we forced to use "-fexceptions" flag in android ndk project [\#640](https://github.com/nlohmann/json/issues/640) +- Comparison of objects containing floats [\#639](https://github.com/nlohmann/json/issues/639) +- 'localeconv' is not supported by NDK for SDK \<=20 [\#638](https://github.com/nlohmann/json/issues/638) +- \[Question\] cLion integration [\#637](https://github.com/nlohmann/json/issues/637) +- How to construct an iteratable usage in nlohmann json? [\#636](https://github.com/nlohmann/json/issues/636) +- \[Question\] copy assign json-container to vector [\#635](https://github.com/nlohmann/json/issues/635) +- Get size without .dump\(\) [\#634](https://github.com/nlohmann/json/issues/634) +- Segmentation fault when parsing invalid json file [\#633](https://github.com/nlohmann/json/issues/633) +- How to serialize from json to vector\? [\#632](https://github.com/nlohmann/json/issues/632) +- no member named 'thousands\_sep' in 'lconv' [\#631](https://github.com/nlohmann/json/issues/631) +- \[Question\] Any fork for \(the unsupported\) Visual Studio 2012 version? [\#628](https://github.com/nlohmann/json/issues/628) +- Dependency injection in serializer [\#627](https://github.com/nlohmann/json/issues/627) +- from\_json for std::array [\#625](https://github.com/nlohmann/json/issues/625) +- Discussion: How to structure the parsing function families [\#623](https://github.com/nlohmann/json/issues/623) +- Question: How to erase subtree [\#622](https://github.com/nlohmann/json/issues/622) +- Insertion into nested json field [\#621](https://github.com/nlohmann/json/issues/621) +- Question: return static json object from function [\#618](https://github.com/nlohmann/json/issues/618) +- icc16 error [\#617](https://github.com/nlohmann/json/issues/617) +- \[-Wdeprecated-declarations\] in row `j >> ss;` in file `json.hpp:7405:26` and FAILED unit tests with MinGWx64! [\#616](https://github.com/nlohmann/json/issues/616) +- to\_json for pairs, tuples [\#614](https://github.com/nlohmann/json/issues/614) +- Using uninitialized memory 'buf' in line 11173 v2.1.1? [\#613](https://github.com/nlohmann/json/issues/613) +- How to parse multiple same Keys of JSON and save them? [\#612](https://github.com/nlohmann/json/issues/612) +- "Multiple declarations" error when using types defined with `typedef` [\#611](https://github.com/nlohmann/json/issues/611) +- 2.1.1+ breaks compilation of shared\_ptr\ == 0 [\#610](https://github.com/nlohmann/json/issues/610) +- a bug of inheritance ? [\#608](https://github.com/nlohmann/json/issues/608) +- std::map key conversion with to\_json [\#607](https://github.com/nlohmann/json/issues/607) +- json.hpp:6384:62: error: wrong number of template arguments \(1, should be 2\) [\#606](https://github.com/nlohmann/json/issues/606) +- Incremental parsing: Where's the push version? [\#605](https://github.com/nlohmann/json/issues/605) +- Is there a way to validate the structure of a json object ? [\#604](https://github.com/nlohmann/json/issues/604) +- \[Question\] Issue when using Appveyor when compiling library [\#603](https://github.com/nlohmann/json/issues/603) +- BOM not skipped when using json:parse\(iterator\) [\#602](https://github.com/nlohmann/json/issues/602) +- Use of the binary type in CBOR and Message Pack [\#601](https://github.com/nlohmann/json/issues/601) +- Newbie issue: how does one convert a map in Json back to std::map? [\#600](https://github.com/nlohmann/json/issues/600) +- Plugin system [\#599](https://github.com/nlohmann/json/issues/599) +- Using custom types for scalars? [\#596](https://github.com/nlohmann/json/issues/596) +- Issues with the arithmetic in iterator and reverse iterator [\#593](https://github.com/nlohmann/json/issues/593) +- not enough examples [\#592](https://github.com/nlohmann/json/issues/592) +- in-class initialization for type 'const T' is not yet implemented [\#591](https://github.com/nlohmann/json/issues/591) +- compiling with gcc 7 -\> error on bool operator \< [\#590](https://github.com/nlohmann/json/issues/590) +- Parsing from stream leads to an array [\#589](https://github.com/nlohmann/json/issues/589) +- Buggy support for binary string data [\#587](https://github.com/nlohmann/json/issues/587) +- C++17's ambiguous conversion [\#586](https://github.com/nlohmann/json/issues/586) +- How does the messagepack encoding/decoding compare to msgpack-cpp in terms of performance? [\#585](https://github.com/nlohmann/json/issues/585) +- is it possible to check existence of a value deep in hierarchy? [\#584](https://github.com/nlohmann/json/issues/584) +- loading from a stream and exceptions [\#582](https://github.com/nlohmann/json/issues/582) +- Visual Studio seems not to have all min\(\) function versions [\#581](https://github.com/nlohmann/json/issues/581) +- Supporting of the json schema [\#580](https://github.com/nlohmann/json/issues/580) +- Stack-overflow \(OSS-Fuzz 1444\) [\#577](https://github.com/nlohmann/json/issues/577) +- Heap-buffer-overflow \(OSS-Fuzz 1400\) [\#575](https://github.com/nlohmann/json/issues/575) +- JSON escape quotes [\#574](https://github.com/nlohmann/json/issues/574) +- error: static\_assert failed [\#573](https://github.com/nlohmann/json/issues/573) +- Storing floats, and round trip serialisation/deserialisation diffs [\#572](https://github.com/nlohmann/json/issues/572) +- JSON.getLong produces inconsistent results [\#571](https://github.com/nlohmann/json/issues/571) +- Request: Object.at\(\) with default return value [\#570](https://github.com/nlohmann/json/issues/570) +- Internal structure gets corrupted while parsing [\#569](https://github.com/nlohmann/json/issues/569) +- create template \ basic\_json from\_cbor\(Iter begin, Iter end\) [\#568](https://github.com/nlohmann/json/issues/568) +- Conan.io [\#566](https://github.com/nlohmann/json/issues/566) +- contradictory documentation regarding json::find [\#565](https://github.com/nlohmann/json/issues/565) +- Unexpected '\"' in middle of array [\#564](https://github.com/nlohmann/json/issues/564) +- Support parse std::pair to Json object [\#563](https://github.com/nlohmann/json/issues/563) +- json and Microsoft Visual c++ Compiler Nov 2012 CTP [\#562](https://github.com/nlohmann/json/issues/562) +- from\_json declaration order and exceptions [\#561](https://github.com/nlohmann/json/issues/561) +- Tip: Don't upgrade to VS2017 if using json initializer list constructs [\#559](https://github.com/nlohmann/json/issues/559) +- parse error - unexpected end of input [\#558](https://github.com/nlohmann/json/issues/558) +- Cant modify existing numbers inside a json object [\#557](https://github.com/nlohmann/json/issues/557) +- Better support for SAX style serialize and deserialize in new version? [\#554](https://github.com/nlohmann/json/issues/554) +- Cannot convert from json array to std::array [\#553](https://github.com/nlohmann/json/issues/553) +- Do not define an unnamed namespace in a header file \(DCL59-CPP\) [\#552](https://github.com/nlohmann/json/issues/552) +- Parse error on known good json file [\#551](https://github.com/nlohmann/json/issues/551) +- Warning on Intel compiler \(icc 17\) [\#550](https://github.com/nlohmann/json/issues/550) +- multiple versions of 'vsnprintf' [\#549](https://github.com/nlohmann/json/issues/549) +- illegal indirection [\#548](https://github.com/nlohmann/json/issues/548) +- Ambiguous compare operators with clang-5.0 [\#547](https://github.com/nlohmann/json/issues/547) +- Using tsl::ordered\_map [\#546](https://github.com/nlohmann/json/issues/546) +- Compiler support errors are inconvenient [\#544](https://github.com/nlohmann/json/issues/544) +- Duplicate symbols error happens while to\_json/from\_json method implemented inside entity definition header file [\#542](https://github.com/nlohmann/json/issues/542) +- consider adding a bool json::is\_valid\(std::string const&\) non-member function [\#541](https://github.com/nlohmann/json/issues/541) +- Help request [\#539](https://github.com/nlohmann/json/issues/539) +- How to deal with missing keys in `from_json`? [\#538](https://github.com/nlohmann/json/issues/538) +- recursive from\_msgpack implementation will stack overflow [\#537](https://github.com/nlohmann/json/issues/537) +- Exception objects must be nothrow copy constructible \(ERR60-CPP\) [\#531](https://github.com/nlohmann/json/issues/531) +- Support for multiple root elements [\#529](https://github.com/nlohmann/json/issues/529) +- Port has\_shape from dropbox/json11 [\#528](https://github.com/nlohmann/json/issues/528) +- dump\_float: truncation from ptrdiff\_t to long [\#527](https://github.com/nlohmann/json/issues/527) +- Make exception base class visible in basic\_json [\#525](https://github.com/nlohmann/json/issues/525) +- msgpack unit test failures on ppc64 arch [\#524](https://github.com/nlohmann/json/issues/524) +- How about split the implementation out, and only leave the interface? [\#523](https://github.com/nlohmann/json/issues/523) +- VC++2017 not enough actual parameters for macro 'max' [\#522](https://github.com/nlohmann/json/issues/522) +- crash on empty ifstream [\#521](https://github.com/nlohmann/json/issues/521) +- Suggestion: Support tabs for indentation when serializing to stream. [\#520](https://github.com/nlohmann/json/issues/520) +- Abrt in get\_number \(OSS-Fuzz 885\) [\#519](https://github.com/nlohmann/json/issues/519) +- Abrt on unknown address \(OSS-Fuzz 884\) [\#518](https://github.com/nlohmann/json/issues/518) +- Stack-overflow \(OSS-Fuzz 869\) [\#517](https://github.com/nlohmann/json/issues/517) +- Assertion error \(OSS-Fuzz 868\) [\#516](https://github.com/nlohmann/json/issues/516) +- NaN to json and back [\#515](https://github.com/nlohmann/json/issues/515) +- Comparison of NaN [\#514](https://github.com/nlohmann/json/issues/514) +- why it's not possible to serialize c++11 enums directly [\#513](https://github.com/nlohmann/json/issues/513) +- clang compile error: use of overloaded operator '\<=' is ambiguous with \(nlohmann::json{{"a", 5}}\)\["a"\] \<= 10 [\#512](https://github.com/nlohmann/json/issues/512) +- Why not also look inside the type for \(static\) to\_json and from\_json funtions? [\#511](https://github.com/nlohmann/json/issues/511) +- Parser issues [\#509](https://github.com/nlohmann/json/issues/509) +- I may not understand [\#507](https://github.com/nlohmann/json/issues/507) +- VS2017 min / max problem for 2.1.1 [\#506](https://github.com/nlohmann/json/issues/506) +- CBOR/MessagePack is not read until the end [\#505](https://github.com/nlohmann/json/issues/505) +- Assertion error \(OSS-Fuzz 856\) [\#504](https://github.com/nlohmann/json/issues/504) +- Return position in parse error exceptions [\#503](https://github.com/nlohmann/json/issues/503) +- conversion from/to C array is not supported [\#502](https://github.com/nlohmann/json/issues/502) +- error C2338: could not find to\_json\(\) method in T's namespace [\#501](https://github.com/nlohmann/json/issues/501) +- Test suite fails in en\_GB.UTF-8 [\#500](https://github.com/nlohmann/json/issues/500) +- cannot use operator\[\] with number [\#499](https://github.com/nlohmann/json/issues/499) +- consider using \_\_cpp\_exceptions and/or \_\_EXCEPTIONS to disable/enable exception support [\#498](https://github.com/nlohmann/json/issues/498) +- Stack-overflow \(OSS-Fuzz issue 814\) [\#497](https://github.com/nlohmann/json/issues/497) +- Using in Unreal Engine - handling custom types conversion [\#495](https://github.com/nlohmann/json/issues/495) +- Conversion from vector\ to json fails to build [\#494](https://github.com/nlohmann/json/issues/494) +- fill\_line\_buffer incorrectly tests m\_stream for eof but not fail or bad bits [\#493](https://github.com/nlohmann/json/issues/493) +- Compiling with \_GLIBCXX\_DEBUG yields iterator-comparison warnings during tests [\#492](https://github.com/nlohmann/json/issues/492) +- crapy interface [\#491](https://github.com/nlohmann/json/issues/491) +- Fix Visual Studo 2013 builds. [\#490](https://github.com/nlohmann/json/issues/490) +- Failed to compile with -D\_GLIBCXX\_PARALLEL [\#489](https://github.com/nlohmann/json/issues/489) +- Input several field with the same name [\#488](https://github.com/nlohmann/json/issues/488) +- read in .json file yields strange sizes [\#487](https://github.com/nlohmann/json/issues/487) +- json::value\_t can't be a map's key type in VC++ 2015 [\#486](https://github.com/nlohmann/json/issues/486) +- Using fifo\_map [\#485](https://github.com/nlohmann/json/issues/485) +- Cannot get float pointer for value stored as `0` [\#484](https://github.com/nlohmann/json/issues/484) +- byte string support [\#483](https://github.com/nlohmann/json/issues/483) +- https://github.com/nlohmann/json\#execute-unit-tests [\#481](https://github.com/nlohmann/json/issues/481) +- Remove deprecated constructor basic\_json\(std::istream&\) [\#480](https://github.com/nlohmann/json/issues/480) +- writing the binary json file? [\#479](https://github.com/nlohmann/json/issues/479) +- CBOR/MessagePack from uint8\_t \* and size [\#478](https://github.com/nlohmann/json/issues/478) +- Streaming binary representations [\#477](https://github.com/nlohmann/json/issues/477) +- Reuse memory in to\_cbor and to\_msgpack functions [\#476](https://github.com/nlohmann/json/issues/476) +- Error Using JSON Library with arrays C++ [\#475](https://github.com/nlohmann/json/issues/475) +- Moving forward to version 3.0.0 [\#474](https://github.com/nlohmann/json/issues/474) +- Inconsistent behavior in conversion to array type [\#473](https://github.com/nlohmann/json/issues/473) +- Create a \[key:member\_pointer\] map to ease parsing custom types [\#471](https://github.com/nlohmann/json/issues/471) +- MSVC 2015 update 2 [\#469](https://github.com/nlohmann/json/issues/469) +- VS2017 implicit to std::string conversion fix. [\#464](https://github.com/nlohmann/json/issues/464) +- How to make sure a string or string literal is a valid JSON? [\#458](https://github.com/nlohmann/json/issues/458) +- basic\_json templated on a "policy" class [\#456](https://github.com/nlohmann/json/issues/456) +- json::value\(const json\_pointer&, ValueType\) requires exceptions to return the default value. [\#440](https://github.com/nlohmann/json/issues/440) +- is it possible merge two json object [\#428](https://github.com/nlohmann/json/issues/428) +- Is it possible to turn this into a shared library? [\#420](https://github.com/nlohmann/json/issues/420) +- Further thoughts on performance improvements [\#418](https://github.com/nlohmann/json/issues/418) +- nan number stored as null [\#388](https://github.com/nlohmann/json/issues/388) +- Behavior of operator\>\> should more closely resemble that of built-in overloads. [\#367](https://github.com/nlohmann/json/issues/367) +- Request: range-based-for over a json-object to expose .first/.second [\#350](https://github.com/nlohmann/json/issues/350) +- feature wish: JSONPath [\#343](https://github.com/nlohmann/json/issues/343) +- UTF-8/Unicode escape and dump [\#330](https://github.com/nlohmann/json/issues/330) +- Serialized value not always can be parsed. [\#329](https://github.com/nlohmann/json/issues/329) +- Is there a way to forward declare nlohmann::json? [\#314](https://github.com/nlohmann/json/issues/314) +- Exception line [\#301](https://github.com/nlohmann/json/issues/301) +- Do not throw exception when default\_value's type does not match the actual type [\#278](https://github.com/nlohmann/json/issues/278) +- dump\(\) method doesn't work with a custom allocator [\#268](https://github.com/nlohmann/json/issues/268) +- Readme documentation enhancements [\#248](https://github.com/nlohmann/json/issues/248) +- Use user-defined exceptions [\#244](https://github.com/nlohmann/json/issues/244) +- Incorrect C++11 allocator model support [\#161](https://github.com/nlohmann/json/issues/161) + +## [v2.1.1](https://github.com/nlohmann/json/releases/tag/v2.1.1) (2017-02-25) + +[Full Changelog](https://github.com/nlohmann/json/compare/2.1.1...v2.1.1) + +- Speedup CI builds using cotire [\#461](https://github.com/nlohmann/json/pull/461) ([tusharpm](https://github.com/tusharpm)) +- TurpentineDistillery feature/locale independent str to num [\#450](https://github.com/nlohmann/json/pull/450) ([nlohmann](https://github.com/nlohmann)) +- README: adjust boost::optional example [\#439](https://github.com/nlohmann/json/pull/439) ([jaredgrubb](https://github.com/jaredgrubb)) +- fix \#414 - comparing to 0 literal [\#415](https://github.com/nlohmann/json/pull/415) ([stanmihai4](https://github.com/stanmihai4)) +- locale-independent num-to-str [\#378](https://github.com/nlohmann/json/pull/378) ([TurpentineDistillery](https://github.com/TurpentineDistillery)) + +## [2.1.1](https://github.com/nlohmann/json/releases/tag/2.1.1) (2017-02-25) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.1.0...2.1.1) + +- warning in the library [\#472](https://github.com/nlohmann/json/issues/472) +- How to create an array of Objects? [\#470](https://github.com/nlohmann/json/issues/470) +- \[Bug?\] Cannot get int pointer, but int64\_t works [\#468](https://github.com/nlohmann/json/issues/468) +- Illegal indirection [\#467](https://github.com/nlohmann/json/issues/467) +- in vs can't find linkageId [\#466](https://github.com/nlohmann/json/issues/466) +- Roundtrip error while parsing "1000000000000000010E5" [\#465](https://github.com/nlohmann/json/issues/465) +- C4996 error and warning with Visual Studio [\#463](https://github.com/nlohmann/json/issues/463) +- Support startIndex for from\_cbor/from\_msgpack [\#462](https://github.com/nlohmann/json/issues/462) +- question: monospace font used in feature slideshow? [\#460](https://github.com/nlohmann/json/issues/460) +- Object.keys\(\) [\#459](https://github.com/nlohmann/json/issues/459) +- Use “, “ as delimiter for json-objects. [\#457](https://github.com/nlohmann/json/issues/457) +- Enum -\> string during serialization and vice versa [\#455](https://github.com/nlohmann/json/issues/455) +- doubles are printed as integers [\#454](https://github.com/nlohmann/json/issues/454) +- Warnings with Visual Studio c++ \(VS2015 Update 3\) [\#453](https://github.com/nlohmann/json/issues/453) +- Heap-buffer-overflow \(OSS-Fuzz issue 585\) [\#452](https://github.com/nlohmann/json/issues/452) +- use of undeclared identifier 'UINT8\_MAX' [\#451](https://github.com/nlohmann/json/issues/451) +- Question on the lifetime managment of objects at the lower levels [\#449](https://github.com/nlohmann/json/issues/449) +- Json should not be constructible with 'json\*' [\#448](https://github.com/nlohmann/json/issues/448) +- Move value\_t to namespace scope [\#447](https://github.com/nlohmann/json/issues/447) +- Typo in README.md [\#446](https://github.com/nlohmann/json/issues/446) +- make check compilation is unneccesarily slow [\#445](https://github.com/nlohmann/json/issues/445) +- Problem in dump\(\) in json.h caused by ss.imbue [\#444](https://github.com/nlohmann/json/issues/444) +- I want to create Windows Application in Visual Studio 2015 c++, and i have a problem [\#443](https://github.com/nlohmann/json/issues/443) +- Implicit conversion issues [\#442](https://github.com/nlohmann/json/issues/442) +- Parsing of floats locale dependent [\#302](https://github.com/nlohmann/json/issues/302) + +## [v2.1.0](https://github.com/nlohmann/json/releases/tag/v2.1.0) (2017-01-28) + +[Full Changelog](https://github.com/nlohmann/json/compare/2.1.0...v2.1.0) + +- conversion from/to user-defined types [\#435](https://github.com/nlohmann/json/pull/435) ([nlohmann](https://github.com/nlohmann)) +- Fix documentation error [\#430](https://github.com/nlohmann/json/pull/430) ([vjon](https://github.com/vjon)) + +## [2.1.0](https://github.com/nlohmann/json/releases/tag/2.1.0) (2017-01-28) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.10...2.1.0) + +- Parsing multiple JSON objects from a string or stream [\#438](https://github.com/nlohmann/json/issues/438) +- Use-of-uninitialized-value \(OSS-Fuzz issue 477\) [\#437](https://github.com/nlohmann/json/issues/437) +- add `reserve` function for array to reserve memory before adding json values into it [\#436](https://github.com/nlohmann/json/issues/436) +- Typo in examples page [\#434](https://github.com/nlohmann/json/issues/434) +- avoid malformed json [\#433](https://github.com/nlohmann/json/issues/433) +- How to add json objects to a map? [\#432](https://github.com/nlohmann/json/issues/432) +- create json instance from raw json \(unsigned char\*\) [\#431](https://github.com/nlohmann/json/issues/431) +- Getting std::invalid\_argument: stream error when following example [\#429](https://github.com/nlohmann/json/issues/429) +- Forward declare-only header? [\#427](https://github.com/nlohmann/json/issues/427) +- Implicit conversion from array to object [\#425](https://github.com/nlohmann/json/issues/425) +- error C4996: 'strerror' when reading file [\#422](https://github.com/nlohmann/json/issues/422) +- Get an error - JSON pointer must be empty or begin with '/' [\#421](https://github.com/nlohmann/json/issues/421) +- size parameter for parse\(\) [\#419](https://github.com/nlohmann/json/issues/419) +- json.hpp forcibly defines GCC\_VERSION [\#417](https://github.com/nlohmann/json/issues/417) +- Use-of-uninitialized-value \(OSS-Fuzz issue 377\) [\#416](https://github.com/nlohmann/json/issues/416) +- comparing to 0 literal [\#414](https://github.com/nlohmann/json/issues/414) +- Single char converted to ASCII code instead of string [\#413](https://github.com/nlohmann/json/issues/413) +- How to know if a string was parsed as utf-8? [\#406](https://github.com/nlohmann/json/issues/406) +- Overloaded += to add objects to an array makes no sense? [\#404](https://github.com/nlohmann/json/issues/404) +- Finding a value in an array [\#399](https://github.com/nlohmann/json/issues/399) +- add release information in static function [\#397](https://github.com/nlohmann/json/issues/397) +- Optimize memory usage of json objects in combination with binary serialization [\#373](https://github.com/nlohmann/json/issues/373) +- Conversion operators not considered [\#369](https://github.com/nlohmann/json/issues/369) +- Append ".0" to serialized floating\_point values that are digits-only. [\#362](https://github.com/nlohmann/json/issues/362) +- Add a customization point for user-defined types [\#328](https://github.com/nlohmann/json/issues/328) +- Conformance report for reference [\#307](https://github.com/nlohmann/json/issues/307) +- Document the best way to serialize/deserialize user defined types to json [\#298](https://github.com/nlohmann/json/issues/298) +- Add StringView template typename to basic\_json [\#297](https://github.com/nlohmann/json/issues/297) +- \[Improvement\] Add option to remove exceptions [\#296](https://github.com/nlohmann/json/issues/296) +- Performance in miloyip/nativejson-benchmark [\#202](https://github.com/nlohmann/json/issues/202) + +## [v2.0.10](https://github.com/nlohmann/json/releases/tag/v2.0.10) (2017-01-02) + +[Full Changelog](https://github.com/nlohmann/json/compare/2.0.10...v2.0.10) + +- Feature/clang sanitize [\#410](https://github.com/nlohmann/json/pull/410) ([Daniel599](https://github.com/Daniel599)) +- Add Doozer build badge [\#400](https://github.com/nlohmann/json/pull/400) ([andoma](https://github.com/andoma)) + +## [2.0.10](https://github.com/nlohmann/json/releases/tag/2.0.10) (2017-01-02) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.9...2.0.10) + +- Heap-buffer-overflow \(OSS-Fuzz issue 367\) [\#412](https://github.com/nlohmann/json/issues/412) +- Heap-buffer-overflow \(OSS-Fuzz issue 366\) [\#411](https://github.com/nlohmann/json/issues/411) +- Use-of-uninitialized-value \(OSS-Fuzz issue 347\) [\#409](https://github.com/nlohmann/json/issues/409) +- Heap-buffer-overflow \(OSS-Fuzz issue 344\) [\#408](https://github.com/nlohmann/json/issues/408) +- Heap-buffer-overflow \(OSS-Fuzz issue 343\) [\#407](https://github.com/nlohmann/json/issues/407) +- Heap-buffer-overflow \(OSS-Fuzz issue 342\) [\#405](https://github.com/nlohmann/json/issues/405) +- strerror throwing error in compiler VS2015 [\#403](https://github.com/nlohmann/json/issues/403) +- json::parse of std::string being underlined by Visual Studio [\#402](https://github.com/nlohmann/json/issues/402) +- Explicitly getting string without .dump\(\) [\#401](https://github.com/nlohmann/json/issues/401) +- Possible to speed up json::parse? [\#398](https://github.com/nlohmann/json/issues/398) +- the alphabetic order in the code influence console\_output. [\#396](https://github.com/nlohmann/json/issues/396) +- Execute tests with clang sanitizers [\#394](https://github.com/nlohmann/json/issues/394) +- Check if library can be used with ETL [\#361](https://github.com/nlohmann/json/issues/361) + +## [v2.0.9](https://github.com/nlohmann/json/releases/tag/v2.0.9) (2016-12-16) + +[Full Changelog](https://github.com/nlohmann/json/compare/2.0.9...v2.0.9) + +- Replace class iterator and const\_iterator by using a single template class to reduce code. [\#395](https://github.com/nlohmann/json/pull/395) ([Bosswestfalen](https://github.com/Bosswestfalen)) +- Clang: quiet a warning [\#391](https://github.com/nlohmann/json/pull/391) ([jaredgrubb](https://github.com/jaredgrubb)) +- Fix issue \#380: Signed integer overflow check [\#390](https://github.com/nlohmann/json/pull/390) ([qwename](https://github.com/qwename)) + +## [2.0.9](https://github.com/nlohmann/json/releases/tag/2.0.9) (2016-12-16) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.8...2.0.9) + +- \#pragma GCC diagnostic ignored "-Wdocumentation" [\#393](https://github.com/nlohmann/json/issues/393) +- How to parse this json file and write separate sub object as json files? [\#392](https://github.com/nlohmann/json/issues/392) +- Integer-overflow \(OSS-Fuzz issue 267\) [\#389](https://github.com/nlohmann/json/issues/389) +- Implement indefinite-length types from RFC 7049 [\#387](https://github.com/nlohmann/json/issues/387) +- template parameter "T" is not used in declaring the parameter types of function template [\#386](https://github.com/nlohmann/json/issues/386) +- Serializing json instances containing already serialized string values without escaping [\#385](https://github.com/nlohmann/json/issues/385) +- Add test cases from RFC 7049 [\#384](https://github.com/nlohmann/json/issues/384) +- Add a table of contents to the README file [\#383](https://github.com/nlohmann/json/issues/383) +- Update FAQ section in the guidelines for contributing [\#382](https://github.com/nlohmann/json/issues/382) +- Allow for forward declaring nlohmann::json [\#381](https://github.com/nlohmann/json/issues/381) +- Bug in overflow detection when parsing integers [\#380](https://github.com/nlohmann/json/issues/380) +- A unique name to mention the library? [\#377](https://github.com/nlohmann/json/issues/377) +- Non-unique keys in objects. [\#375](https://github.com/nlohmann/json/issues/375) +- Request: binary serialization/deserialization [\#358](https://github.com/nlohmann/json/issues/358) + +## [v2.0.8](https://github.com/nlohmann/json/releases/tag/v2.0.8) (2016-12-02) + +[Full Changelog](https://github.com/nlohmann/json/compare/2.0.8...v2.0.8) + +## [2.0.8](https://github.com/nlohmann/json/releases/tag/2.0.8) (2016-12-02) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.7...2.0.8) + +- Reading from file [\#374](https://github.com/nlohmann/json/issues/374) +- Compiler warnings? [\#372](https://github.com/nlohmann/json/issues/372) +- docs: how to release a json object in memory? [\#371](https://github.com/nlohmann/json/issues/371) +- crash in dump [\#370](https://github.com/nlohmann/json/issues/370) +- Coverity issue \(FORWARD\_NULL\) in lexer\(std::istream& s\) [\#368](https://github.com/nlohmann/json/issues/368) +- json::parse on failed stream gets stuck [\#366](https://github.com/nlohmann/json/issues/366) +- Performance improvements [\#365](https://github.com/nlohmann/json/issues/365) +- 'to\_string' is not a member of 'std' [\#364](https://github.com/nlohmann/json/issues/364) +- Crash in dump\(\) from a static object [\#359](https://github.com/nlohmann/json/issues/359) +- json::parse\(...\) vs json j; j.parse\(...\) [\#357](https://github.com/nlohmann/json/issues/357) +- Hi, is there any method to dump json to string with the insert order rather than alphabets [\#356](https://github.com/nlohmann/json/issues/356) +- Provide an example of reading from an json with only a key that has an array of strings. [\#354](https://github.com/nlohmann/json/issues/354) +- Request: access with default value. [\#353](https://github.com/nlohmann/json/issues/353) +- {} and \[\] causes parser error. [\#352](https://github.com/nlohmann/json/issues/352) +- Reading a JSON file into a JSON object [\#351](https://github.com/nlohmann/json/issues/351) +- Request: 'emplace\_back' [\#349](https://github.com/nlohmann/json/issues/349) +- Is it possible to stream data through the json parser without storing everything in memory? [\#347](https://github.com/nlohmann/json/issues/347) +- pure virtual conversion operator [\#346](https://github.com/nlohmann/json/issues/346) +- Floating point precision lost [\#345](https://github.com/nlohmann/json/issues/345) +- unit-conversions SIGSEGV on armv7hl [\#303](https://github.com/nlohmann/json/issues/303) +- Coverity scan fails [\#299](https://github.com/nlohmann/json/issues/299) +- Using QString as string type [\#274](https://github.com/nlohmann/json/issues/274) + +## [v2.0.7](https://github.com/nlohmann/json/releases/tag/v2.0.7) (2016-11-02) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.6...v2.0.7) + +- JSON5 [\#348](https://github.com/nlohmann/json/issues/348) +- Check "Parsing JSON is a Minefield" [\#344](https://github.com/nlohmann/json/issues/344) +- Allow hex numbers [\#342](https://github.com/nlohmann/json/issues/342) +- Convert strings to numbers [\#341](https://github.com/nlohmann/json/issues/341) +- ""-operators ignore the length parameter [\#340](https://github.com/nlohmann/json/issues/340) +- JSON into std::tuple [\#339](https://github.com/nlohmann/json/issues/339) +- JSON into vector [\#335](https://github.com/nlohmann/json/issues/335) +- Installing with Homebrew on Mac Errors \(El Capitan\) [\#331](https://github.com/nlohmann/json/issues/331) +- g++ make check results in error [\#312](https://github.com/nlohmann/json/issues/312) +- Cannot convert from 'json' to 'char' [\#276](https://github.com/nlohmann/json/issues/276) +- Please add a Pretty-Print option for arrays to stay always in one line [\#229](https://github.com/nlohmann/json/issues/229) +- Conversion to STL map\\> gives error [\#220](https://github.com/nlohmann/json/issues/220) +- std::unorderd\_map cannot be used as ObjectType [\#164](https://github.com/nlohmann/json/issues/164) + +- fix minor grammar/style issue in README.md [\#336](https://github.com/nlohmann/json/pull/336) ([seeekr](https://github.com/seeekr)) + +## [v2.0.6](https://github.com/nlohmann/json/releases/tag/v2.0.6) (2016-10-15) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.5...v2.0.6) + +- How to handle json files? [\#333](https://github.com/nlohmann/json/issues/333) +- This file requires compiler and library support .... [\#332](https://github.com/nlohmann/json/issues/332) +- Segmentation fault on saving json to file [\#326](https://github.com/nlohmann/json/issues/326) +- parse error - unexpected \ with 2.0.5 [\#325](https://github.com/nlohmann/json/issues/325) +- Add nested object capability to pointers [\#323](https://github.com/nlohmann/json/issues/323) +- Fix usage examples' comments for std::multiset [\#322](https://github.com/nlohmann/json/issues/322) +- json\_unit runs forever when executed in build directory [\#319](https://github.com/nlohmann/json/issues/319) +- Visual studio 2015 update3 true != TRUE [\#317](https://github.com/nlohmann/json/issues/317) +- releasing single header file in compressed format [\#316](https://github.com/nlohmann/json/issues/316) +- json object from std::ifstream [\#315](https://github.com/nlohmann/json/issues/315) + +- make has\_mapped\_type struct friendly [\#324](https://github.com/nlohmann/json/pull/324) ([vpetrigo](https://github.com/vpetrigo)) +- Fix usage examples' comments for std::multiset [\#321](https://github.com/nlohmann/json/pull/321) ([vasild](https://github.com/vasild)) +- Include dir relocation [\#318](https://github.com/nlohmann/json/pull/318) ([ChristophJud](https://github.com/ChristophJud)) +- trivial documentation fix [\#313](https://github.com/nlohmann/json/pull/313) ([5tefan](https://github.com/5tefan)) + +## [v2.0.5](https://github.com/nlohmann/json/releases/tag/v2.0.5) (2016-09-14) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.4...v2.0.5) + +- \[feature request\]: schema validator and comments [\#311](https://github.com/nlohmann/json/issues/311) +- make json\_benchmarks no longer working in 2.0.4 [\#310](https://github.com/nlohmann/json/issues/310) +- Segmentation fault \(core dumped\) [\#309](https://github.com/nlohmann/json/issues/309) +- No matching member function for call to 'get\_impl' [\#308](https://github.com/nlohmann/json/issues/308) + +## [v2.0.4](https://github.com/nlohmann/json/releases/tag/v2.0.4) (2016-09-11) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.3...v2.0.4) + +- Parsing fails without space at end of file [\#306](https://github.com/nlohmann/json/issues/306) +- json schema validator [\#305](https://github.com/nlohmann/json/issues/305) +- Unused variable warning [\#304](https://github.com/nlohmann/json/issues/304) + +## [v2.0.3](https://github.com/nlohmann/json/releases/tag/v2.0.3) (2016-08-31) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.2...v2.0.3) + +- warning C4706: assignment within conditional expression [\#295](https://github.com/nlohmann/json/issues/295) +- Q: Is it possible to build json tree from already UTF8 encoded values? [\#293](https://github.com/nlohmann/json/issues/293) +- Equality operator results in array when assigned object [\#292](https://github.com/nlohmann/json/issues/292) +- Support for integers not from the range \[-\(2\*\*53\)+1, \(2\*\*53\)-1\] in parser [\#291](https://github.com/nlohmann/json/issues/291) +- Support for iterator-range parsing [\#290](https://github.com/nlohmann/json/issues/290) +- Horribly inconsistent behavior between const/non-const reference in operator \[\] \(\) [\#289](https://github.com/nlohmann/json/issues/289) +- Silently get numbers into smaller types [\#288](https://github.com/nlohmann/json/issues/288) +- Incorrect parsing of large int64\_t numbers [\#287](https://github.com/nlohmann/json/issues/287) +- \[question\]: macro to disable floating point support [\#284](https://github.com/nlohmann/json/issues/284) + +- unit-constructor1.cpp: Fix floating point truncation warning [\#300](https://github.com/nlohmann/json/pull/300) ([t-b](https://github.com/t-b)) + +## [v2.0.2](https://github.com/nlohmann/json/releases/tag/v2.0.2) (2016-07-31) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.1...v2.0.2) + +- can function dump\(\) return string in the order I push in the json object ? [\#286](https://github.com/nlohmann/json/issues/286) +- Error on the Mac: Undefined symbols for architecture x86\_64 [\#285](https://github.com/nlohmann/json/issues/285) +- value\(\) does not work with \_json\_pointer types [\#283](https://github.com/nlohmann/json/issues/283) +- Build error for std::int64 [\#282](https://github.com/nlohmann/json/issues/282) +- strings can't be accessed after dump\(\)-\>parse\(\) - type is lost [\#281](https://github.com/nlohmann/json/issues/281) +- Easy serialization of classes [\#280](https://github.com/nlohmann/json/issues/280) +- recursive data structures [\#277](https://github.com/nlohmann/json/issues/277) +- hexify\(\) function emits conversion warning [\#270](https://github.com/nlohmann/json/issues/270) + +- let the makefile choose the correct sed [\#279](https://github.com/nlohmann/json/pull/279) ([murinicanor](https://github.com/murinicanor)) +- Update hexify to use array lookup instead of ternary \(\#270\) [\#275](https://github.com/nlohmann/json/pull/275) ([dtoma](https://github.com/dtoma)) + +## [v2.0.1](https://github.com/nlohmann/json/releases/tag/v2.0.1) (2016-06-28) + +[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.0...v2.0.1) + +- Compilation error. [\#273](https://github.com/nlohmann/json/issues/273) +- dump\(\) performance degradation in v2 [\#272](https://github.com/nlohmann/json/issues/272) + +- fixed a tiny typo [\#271](https://github.com/nlohmann/json/pull/271) ([feroldi](https://github.com/feroldi)) + +## [v2.0.0](https://github.com/nlohmann/json/releases/tag/v2.0.0) (2016-06-23) + +[Full Changelog](https://github.com/nlohmann/json/compare/v1.1.0...v2.0.0) + +- json::diff generates incorrect patch when removing multiple array elements. [\#269](https://github.com/nlohmann/json/issues/269) +- Docs - What does Json\[key\] return? [\#267](https://github.com/nlohmann/json/issues/267) +- Compiler Errors With JSON.hpp [\#265](https://github.com/nlohmann/json/issues/265) +- Ambiguous push\_back and operator+= overloads [\#263](https://github.com/nlohmann/json/issues/263) +- Preseving order of items in json [\#262](https://github.com/nlohmann/json/issues/262) +- '\' char problem in strings [\#261](https://github.com/nlohmann/json/issues/261) +- VS2015 compile fail [\#260](https://github.com/nlohmann/json/issues/260) +- -Wconversion warning [\#259](https://github.com/nlohmann/json/issues/259) +- Maybe a bug [\#258](https://github.com/nlohmann/json/issues/258) +- Few tests failed on Visual C++ 2015 [\#257](https://github.com/nlohmann/json/issues/257) +- Access keys when iteration with new for loop C++11 [\#256](https://github.com/nlohmann/json/issues/256) +- multiline text values [\#255](https://github.com/nlohmann/json/issues/255) +- Error when using json in g++ [\#254](https://github.com/nlohmann/json/issues/254) +- is the release 2.0? [\#253](https://github.com/nlohmann/json/issues/253) +- concatenate objects [\#252](https://github.com/nlohmann/json/issues/252) +- Encoding [\#251](https://github.com/nlohmann/json/issues/251) +- Unable to build example for constructing json object with stringstreams [\#250](https://github.com/nlohmann/json/issues/250) +- Hexadecimal support [\#249](https://github.com/nlohmann/json/issues/249) +- Update long-term goals [\#246](https://github.com/nlohmann/json/issues/246) +- Contribution To This Json Project [\#245](https://github.com/nlohmann/json/issues/245) +- Trouble using parser with initial dictionary [\#243](https://github.com/nlohmann/json/issues/243) +- Unit test fails when doing a CMake out-of-tree build [\#241](https://github.com/nlohmann/json/issues/241) +- -Wconversion warnings [\#239](https://github.com/nlohmann/json/issues/239) +- Additional integration options [\#237](https://github.com/nlohmann/json/issues/237) +- .get\\(\) works for non spaced string but returns as array for spaced/longer strings [\#236](https://github.com/nlohmann/json/issues/236) +- ambiguous overload for 'push\_back' and 'operator+=' [\#235](https://github.com/nlohmann/json/issues/235) +- Can't use basic\_json::iterator as a base iterator for std::move\_iterator [\#233](https://github.com/nlohmann/json/issues/233) +- json object's creation can freezes execution [\#231](https://github.com/nlohmann/json/issues/231) +- Incorrect dumping of parsed numbers with exponents, but without decimal places [\#230](https://github.com/nlohmann/json/issues/230) +- double values are serialized with commas as decimal points [\#228](https://github.com/nlohmann/json/issues/228) +- Move semantics with std::initializer\_list [\#225](https://github.com/nlohmann/json/issues/225) +- replace emplace [\#224](https://github.com/nlohmann/json/issues/224) +- abort during getline in yyfill [\#223](https://github.com/nlohmann/json/issues/223) +- free\(\): invalid pointer error in GCC 5.2.1 [\#221](https://github.com/nlohmann/json/issues/221) +- Error compile Android NDK error: 'strtof' is not a member of 'std' [\#219](https://github.com/nlohmann/json/issues/219) +- Wrong link in the README.md [\#217](https://github.com/nlohmann/json/issues/217) +- Wide character strings not supported [\#216](https://github.com/nlohmann/json/issues/216) +- Memory allocations using range-based for loops [\#214](https://github.com/nlohmann/json/issues/214) +- would you like to support gcc 4.8.1? [\#211](https://github.com/nlohmann/json/issues/211) +- Reading concatenated json's from an istream [\#210](https://github.com/nlohmann/json/issues/210) +- Conflicting typedef of ssize\_t on Windows 32 bit when using Boost.Python [\#204](https://github.com/nlohmann/json/issues/204) +- Inconsistency between operator\[\] and push\_back [\#203](https://github.com/nlohmann/json/issues/203) +- Small bugs in json.hpp \(get\_number\) and unit.cpp \(non-standard integer type test\) [\#199](https://github.com/nlohmann/json/issues/199) +- GCC/clang floating point parsing bug in strtod\(\) [\#195](https://github.com/nlohmann/json/issues/195) +- What is within scope? [\#192](https://github.com/nlohmann/json/issues/192) +- Bugs in miloyip/nativejson-benchmark: roundtrips [\#187](https://github.com/nlohmann/json/issues/187) +- Floating point exceptions [\#181](https://github.com/nlohmann/json/issues/181) +- Integer conversion to unsigned [\#178](https://github.com/nlohmann/json/issues/178) +- map string string fails to compile [\#176](https://github.com/nlohmann/json/issues/176) +- In basic\_json::basic\_json\(const CompatibleArrayType& val\), the requirement of CompatibleArrayType is not strict enough. [\#174](https://github.com/nlohmann/json/issues/174) +- Provide a FAQ [\#163](https://github.com/nlohmann/json/issues/163) +- Implicit assignment to std::string fails [\#144](https://github.com/nlohmann/json/issues/144) + +- Fix Issue \#265 [\#266](https://github.com/nlohmann/json/pull/266) ([06needhamt](https://github.com/06needhamt)) +- Define CMake/CTest tests [\#247](https://github.com/nlohmann/json/pull/247) ([robertmrk](https://github.com/robertmrk)) +- Out of tree builds and a few other miscellaneous CMake cleanups. [\#242](https://github.com/nlohmann/json/pull/242) ([ChrisKitching](https://github.com/ChrisKitching)) +- Implement additional integration options [\#238](https://github.com/nlohmann/json/pull/238) ([robertmrk](https://github.com/robertmrk)) +- make serialization locale-independent [\#232](https://github.com/nlohmann/json/pull/232) ([nlohmann](https://github.com/nlohmann)) +- fixes \#223 by updating README.md [\#227](https://github.com/nlohmann/json/pull/227) ([kevin--](https://github.com/kevin--)) +- Use namespace std for int64\_t and uint64\_t [\#226](https://github.com/nlohmann/json/pull/226) ([lv-zheng](https://github.com/lv-zheng)) +- Added missing cerrno header to fix ERANGE compile error on android [\#222](https://github.com/nlohmann/json/pull/222) ([Teemperor](https://github.com/Teemperor)) +- Corrected readme [\#218](https://github.com/nlohmann/json/pull/218) ([Annihil](https://github.com/Annihil)) +- Create PULL\_REQUEST\_TEMPLATE.md [\#213](https://github.com/nlohmann/json/pull/213) ([whackashoe](https://github.com/whackashoe)) +- fixed noexcept; added constexpr [\#208](https://github.com/nlohmann/json/pull/208) ([nlohmann](https://github.com/nlohmann)) +- Add support for afl-fuzz testing [\#207](https://github.com/nlohmann/json/pull/207) ([mykter](https://github.com/mykter)) +- replaced ssize\_t occurrences with auto \(addresses \#204\) [\#205](https://github.com/nlohmann/json/pull/205) ([nlohmann](https://github.com/nlohmann)) +- Fixed issue \#199 - Small bugs in json.hpp \(get\_number\) and unit.cpp \(non-standard integer type test\) [\#200](https://github.com/nlohmann/json/pull/200) ([twelsby](https://github.com/twelsby)) +- Fix broken link [\#197](https://github.com/nlohmann/json/pull/197) ([vog](https://github.com/vog)) +- Issue \#195 - update Travis to Trusty due to gcc/clang strtod\(\) bug [\#196](https://github.com/nlohmann/json/pull/196) ([twelsby](https://github.com/twelsby)) +- Issue \#178 - Extending support to full uint64\_t/int64\_t range and unsigned type \(updated\) [\#193](https://github.com/nlohmann/json/pull/193) ([twelsby](https://github.com/twelsby)) + +## [v1.1.0](https://github.com/nlohmann/json/releases/tag/v1.1.0) (2016-01-24) + +[Full Changelog](https://github.com/nlohmann/json/compare/v1.0.0...v1.1.0) + +- Small error in pull \#185 [\#194](https://github.com/nlohmann/json/issues/194) +- Bugs in miloyip/nativejson-benchmark: floating-point parsing [\#186](https://github.com/nlohmann/json/issues/186) +- Floating point equality [\#185](https://github.com/nlohmann/json/issues/185) +- Unused variables in catch [\#180](https://github.com/nlohmann/json/issues/180) +- Typo in documentation [\#179](https://github.com/nlohmann/json/issues/179) +- JSON performance benchmark comparision [\#177](https://github.com/nlohmann/json/issues/177) +- Since re2c is often ignored in pull requests, it may make sense to make a contributing.md file [\#175](https://github.com/nlohmann/json/issues/175) +- Question about exceptions [\#173](https://github.com/nlohmann/json/issues/173) +- Android? [\#172](https://github.com/nlohmann/json/issues/172) +- Cannot index by key of type static constexpr const char\* [\#171](https://github.com/nlohmann/json/issues/171) +- Add assertions [\#168](https://github.com/nlohmann/json/issues/168) +- MSVC 2015 build fails when attempting to compare object\_t [\#167](https://github.com/nlohmann/json/issues/167) +- Member detector is not portable [\#166](https://github.com/nlohmann/json/issues/166) +- Unnecessary const\_cast [\#162](https://github.com/nlohmann/json/issues/162) +- Question about get\_ref\(\) [\#128](https://github.com/nlohmann/json/issues/128) +- range based for loop for objects [\#83](https://github.com/nlohmann/json/issues/83) +- Consider submitting this to the Boost Library Incubator [\#66](https://github.com/nlohmann/json/issues/66) + +- Fixed Issue \#186 - add strto\(f|d|ld\) overload wrappers, "-0.0" special case and FP trailing zero [\#191](https://github.com/nlohmann/json/pull/191) ([twelsby](https://github.com/twelsby)) +- Issue \#185 - remove approx\(\) and use \#pragma to kill warnings [\#190](https://github.com/nlohmann/json/pull/190) ([twelsby](https://github.com/twelsby)) +- Fixed Issue \#171 - added two extra template overloads of operator\[\] for T\* arguments [\#189](https://github.com/nlohmann/json/pull/189) ([twelsby](https://github.com/twelsby)) +- Fixed issue \#167 - removed operator ValueType\(\) condition for VS2015 [\#188](https://github.com/nlohmann/json/pull/188) ([twelsby](https://github.com/twelsby)) +- Implementation of get\_ref\(\) [\#184](https://github.com/nlohmann/json/pull/184) ([dariomt](https://github.com/dariomt)) +- Fixed some typos in CONTRIBUTING.md [\#182](https://github.com/nlohmann/json/pull/182) ([nibroc](https://github.com/nibroc)) + +## [v1.0.0](https://github.com/nlohmann/json/releases/tag/v1.0.0) (2015-12-27) + +[Full Changelog](https://github.com/nlohmann/json/compare/v1.0.0-rc1...v1.0.0) + +- add key name to exception [\#160](https://github.com/nlohmann/json/issues/160) +- Getting member discarding qualifyer [\#159](https://github.com/nlohmann/json/issues/159) +- basic\_json::iterator::value\(\) output includes quotes while basic\_json::iterator::key\(\) doesn't [\#158](https://github.com/nlohmann/json/issues/158) +- Indexing `const basic_json<>` with `const basic_string` [\#157](https://github.com/nlohmann/json/issues/157) +- token\_type\_name\(token\_type t\): not all control paths return a value [\#156](https://github.com/nlohmann/json/issues/156) +- prevent json.hpp from emitting compiler warnings [\#154](https://github.com/nlohmann/json/issues/154) +- json::parse\(string\) does not check utf8 bom [\#152](https://github.com/nlohmann/json/issues/152) +- unsigned 64bit values output as signed [\#151](https://github.com/nlohmann/json/issues/151) +- Wish feature: json5 [\#150](https://github.com/nlohmann/json/issues/150) +- Unable to compile on MSVC 2015 with SDL checking enabled: This function or variable may be unsafe. [\#149](https://github.com/nlohmann/json/issues/149) +- "Json Object" type does not keep object order [\#148](https://github.com/nlohmann/json/issues/148) +- dump\(\) convert strings encoded by utf-8 to shift-jis on windows 10. [\#147](https://github.com/nlohmann/json/issues/147) +- Unable to get field names in a json object [\#145](https://github.com/nlohmann/json/issues/145) +- Question: Is the use of incomplete type correct? [\#138](https://github.com/nlohmann/json/issues/138) +- json.hpp:5746:32: error: 'to\_string' is not a member of 'std' [\#136](https://github.com/nlohmann/json/issues/136) +- Bug in basic\_json::operator\[\] const overload [\#135](https://github.com/nlohmann/json/issues/135) +- wrong enable\_if for const pointer \(instead of pointer-to-const\) [\#134](https://github.com/nlohmann/json/issues/134) +- overload of at\(\) with default value [\#133](https://github.com/nlohmann/json/issues/133) +- Splitting source [\#132](https://github.com/nlohmann/json/issues/132) +- Question about get\_ptr\(\) [\#127](https://github.com/nlohmann/json/issues/127) +- Visual Studio 14 Debug assertion failed [\#125](https://github.com/nlohmann/json/issues/125) +- Memory leak in face of exceptions [\#118](https://github.com/nlohmann/json/issues/118) +- Find and Count for arrays [\#117](https://github.com/nlohmann/json/issues/117) +- dynamically constructing an arbitrarily nested object [\#114](https://github.com/nlohmann/json/issues/114) +- Returning any data type [\#113](https://github.com/nlohmann/json/issues/113) +- Compile error with g++ 4.9.3 cygwin 64-bit [\#112](https://github.com/nlohmann/json/issues/112) +- insert json array issue with gcc4.8.2 [\#110](https://github.com/nlohmann/json/issues/110) +- error: unterminated raw string [\#109](https://github.com/nlohmann/json/issues/109) +- vector\ copy constructor really weird [\#108](https://github.com/nlohmann/json/issues/108) +- \[clang-3.6.2\] string/sstream with number to json issue [\#107](https://github.com/nlohmann/json/issues/107) +- object field accessors [\#103](https://github.com/nlohmann/json/issues/103) +- v8pp and json [\#95](https://github.com/nlohmann/json/issues/95) +- Wishlist [\#65](https://github.com/nlohmann/json/issues/65) +- Windows/Visual Studio \(through 2013\) is unsupported [\#62](https://github.com/nlohmann/json/issues/62) + +- Replace sprintf with hex function, this fixes \#149 [\#153](https://github.com/nlohmann/json/pull/153) ([whackashoe](https://github.com/whackashoe)) +- Fix character skipping after a surrogate pair [\#146](https://github.com/nlohmann/json/pull/146) ([robertmrk](https://github.com/robertmrk)) +- Detect correctly pointer-to-const [\#137](https://github.com/nlohmann/json/pull/137) ([dariomt](https://github.com/dariomt)) +- disabled "CopyAssignable" test for MSVC in Debug mode, see \#125 [\#131](https://github.com/nlohmann/json/pull/131) ([dariomt](https://github.com/dariomt)) +- removed stream operator for iterator, resolution for \#125 [\#130](https://github.com/nlohmann/json/pull/130) ([dariomt](https://github.com/dariomt)) +- fixed typos in comments for examples [\#129](https://github.com/nlohmann/json/pull/129) ([dariomt](https://github.com/dariomt)) +- Remove superfluous inefficiency [\#126](https://github.com/nlohmann/json/pull/126) ([d-frey](https://github.com/d-frey)) +- remove invalid parameter '-stdlib=libc++' in CMakeLists.txt [\#124](https://github.com/nlohmann/json/pull/124) ([emvivre](https://github.com/emvivre)) +- exception-safe object creation, fixes \#118 [\#122](https://github.com/nlohmann/json/pull/122) ([d-frey](https://github.com/d-frey)) +- Fix small oversight. [\#121](https://github.com/nlohmann/json/pull/121) ([ColinH](https://github.com/ColinH)) +- Overload parse\(\) to accept an rvalue reference [\#120](https://github.com/nlohmann/json/pull/120) ([silverweed](https://github.com/silverweed)) +- Use the right variable name in doc string [\#115](https://github.com/nlohmann/json/pull/115) ([whoshuu](https://github.com/whoshuu)) + +## [v1.0.0-rc1](https://github.com/nlohmann/json/releases/tag/v1.0.0-rc1) (2015-07-26) + +[Full Changelog](https://github.com/nlohmann/json/compare/4502e7e51c0569419c26e75fbdd5748170603e54...v1.0.0-rc1) + +- Finish documenting the public interface in Doxygen [\#102](https://github.com/nlohmann/json/issues/102) +- Binary string causes numbers to be dumped as hex [\#101](https://github.com/nlohmann/json/issues/101) +- failed to iterator json object with reverse\_iterator [\#100](https://github.com/nlohmann/json/issues/100) +- 'noexcept' : unknown override specifier [\#99](https://github.com/nlohmann/json/issues/99) +- json float parsing problem [\#98](https://github.com/nlohmann/json/issues/98) +- Adjust wording to JSON RFC [\#97](https://github.com/nlohmann/json/issues/97) +- static analysis warnings [\#94](https://github.com/nlohmann/json/issues/94) +- reverse\_iterator operator inheritance problem [\#93](https://github.com/nlohmann/json/issues/93) +- init error [\#92](https://github.com/nlohmann/json/issues/92) +- access by \(const\) reference [\#91](https://github.com/nlohmann/json/issues/91) +- is\_integer and is\_float tests [\#90](https://github.com/nlohmann/json/issues/90) +- Nonstandard integer type [\#89](https://github.com/nlohmann/json/issues/89) +- static library build [\#84](https://github.com/nlohmann/json/issues/84) +- lexer::get\_number return NAN [\#82](https://github.com/nlohmann/json/issues/82) +- MinGW have no std::to\_string [\#80](https://github.com/nlohmann/json/issues/80) +- Incorrect behaviour of basic\_json::count method [\#78](https://github.com/nlohmann/json/issues/78) +- Invoking is\_array\(\) function creates "null" value [\#77](https://github.com/nlohmann/json/issues/77) +- dump\(\) / parse\(\) not idempotent [\#76](https://github.com/nlohmann/json/issues/76) +- Handle infinity and NaN cases [\#70](https://github.com/nlohmann/json/issues/70) +- errors in g++-4.8.1 [\#68](https://github.com/nlohmann/json/issues/68) +- Keys when iterating over objects [\#67](https://github.com/nlohmann/json/issues/67) +- Compilation results in tons of warnings [\#64](https://github.com/nlohmann/json/issues/64) +- Complete brief documentation [\#61](https://github.com/nlohmann/json/issues/61) +- Double quotation mark is not parsed correctly [\#60](https://github.com/nlohmann/json/issues/60) +- Get coverage back to 100% [\#58](https://github.com/nlohmann/json/issues/58) +- erase elements using iterators [\#57](https://github.com/nlohmann/json/issues/57) +- Removing item from array [\#56](https://github.com/nlohmann/json/issues/56) +- Serialize/Deserialize like PHP? [\#55](https://github.com/nlohmann/json/issues/55) +- Numbers as keys [\#54](https://github.com/nlohmann/json/issues/54) +- Why are elements alphabetized on key while iterating? [\#53](https://github.com/nlohmann/json/issues/53) +- Document erase, count, and iterators key and value [\#52](https://github.com/nlohmann/json/issues/52) +- Do not use std::to\_string [\#51](https://github.com/nlohmann/json/issues/51) +- Supported compilers [\#50](https://github.com/nlohmann/json/issues/50) +- Confused about iterating through json objects [\#49](https://github.com/nlohmann/json/issues/49) +- Use non-member begin/end [\#48](https://github.com/nlohmann/json/issues/48) +- Erase key [\#47](https://github.com/nlohmann/json/issues/47) +- Key iterator [\#46](https://github.com/nlohmann/json/issues/46) +- Add count member function [\#45](https://github.com/nlohmann/json/issues/45) +- Problem getting vector \(array\) of strings [\#44](https://github.com/nlohmann/json/issues/44) +- Compilation error due to assuming that private=public [\#43](https://github.com/nlohmann/json/issues/43) +- Use of deprecated implicit copy constructor [\#42](https://github.com/nlohmann/json/issues/42) +- Printing attribute names [\#39](https://github.com/nlohmann/json/issues/39) +- dumping a small number\_float just outputs 0.000000 [\#37](https://github.com/nlohmann/json/issues/37) +- find is error [\#32](https://github.com/nlohmann/json/issues/32) +- Avoid using spaces when encoding without pretty print [\#31](https://github.com/nlohmann/json/issues/31) +- Cannot encode long numbers [\#30](https://github.com/nlohmann/json/issues/30) +- segmentation fault when iterating over empty arrays/objects [\#28](https://github.com/nlohmann/json/issues/28) +- Creating an empty array [\#27](https://github.com/nlohmann/json/issues/27) +- Custom allocator support [\#25](https://github.com/nlohmann/json/issues/25) +- make the type of the used string container customizable [\#20](https://github.com/nlohmann/json/issues/20) +- Improper parsing of JSON string "\\" [\#17](https://github.com/nlohmann/json/issues/17) +- create a header-only version [\#16](https://github.com/nlohmann/json/issues/16) +- Don't return "const values" [\#15](https://github.com/nlohmann/json/issues/15) +- Add to\_string overload for indentation [\#13](https://github.com/nlohmann/json/issues/13) +- string parser does not recognize uncompliant strings [\#12](https://github.com/nlohmann/json/issues/12) +- possible double-free in find function [\#11](https://github.com/nlohmann/json/issues/11) +- UTF-8 encoding/deconding/testing [\#10](https://github.com/nlohmann/json/issues/10) +- move code into namespace [\#9](https://github.com/nlohmann/json/issues/9) +- free functions for explicit objects and arrays in initializer lists [\#8](https://github.com/nlohmann/json/issues/8) +- unique\_ptr for ownership [\#7](https://github.com/nlohmann/json/issues/7) +- Add unit tests [\#4](https://github.com/nlohmann/json/issues/4) +- Drop C++98 support [\#3](https://github.com/nlohmann/json/issues/3) +- Test case coverage [\#2](https://github.com/nlohmann/json/issues/2) +- Runtime error in Travis job [\#1](https://github.com/nlohmann/json/issues/1) + +- Keyword 'inline' is useless when member functions are defined in headers [\#87](https://github.com/nlohmann/json/pull/87) ([ahamez](https://github.com/ahamez)) +- Remove useless typename [\#86](https://github.com/nlohmann/json/pull/86) ([ahamez](https://github.com/ahamez)) +- Avoid warning with Xcode's clang [\#85](https://github.com/nlohmann/json/pull/85) ([ahamez](https://github.com/ahamez)) +- Fix typos [\#73](https://github.com/nlohmann/json/pull/73) ([aqnouch](https://github.com/aqnouch)) +- Replace `default_callback` function with `nullptr` and check for null… [\#72](https://github.com/nlohmann/json/pull/72) ([aburgh](https://github.com/aburgh)) +- support enum [\#71](https://github.com/nlohmann/json/pull/71) ([likebeta](https://github.com/likebeta)) +- Fix performance regression introduced with the parsing callback feature. [\#69](https://github.com/nlohmann/json/pull/69) ([aburgh](https://github.com/aburgh)) +- Improve the implementations of the comparission-operators [\#63](https://github.com/nlohmann/json/pull/63) ([Florianjw](https://github.com/Florianjw)) +- Fix compilation of json\_unit with GCC 5 [\#59](https://github.com/nlohmann/json/pull/59) ([dkopecek](https://github.com/dkopecek)) +- Parse streams incrementally. [\#40](https://github.com/nlohmann/json/pull/40) ([aburgh](https://github.com/aburgh)) +- Feature/small float serialization [\#38](https://github.com/nlohmann/json/pull/38) ([jrandall](https://github.com/jrandall)) +- template version with re2c scanner [\#36](https://github.com/nlohmann/json/pull/36) ([nlohmann](https://github.com/nlohmann)) +- more descriptive documentation in example [\#33](https://github.com/nlohmann/json/pull/33) ([luxe](https://github.com/luxe)) +- Fix string conversion under Clang [\#26](https://github.com/nlohmann/json/pull/26) ([wancw](https://github.com/wancw)) +- Fixed dumping of strings [\#24](https://github.com/nlohmann/json/pull/24) ([Teemperor](https://github.com/Teemperor)) +- Added a remark to the readme that coverage is GCC only for now [\#23](https://github.com/nlohmann/json/pull/23) ([Teemperor](https://github.com/Teemperor)) +- Unicode escaping [\#22](https://github.com/nlohmann/json/pull/22) ([Teemperor](https://github.com/Teemperor)) +- Implemented the JSON spec for string parsing for everything but the \uXXXX escaping [\#21](https://github.com/nlohmann/json/pull/21) ([Teemperor](https://github.com/Teemperor)) +- add the std iterator typedefs to iterator and const\_iterator [\#19](https://github.com/nlohmann/json/pull/19) ([kirkshoop](https://github.com/kirkshoop)) +- Fixed escaped quotes [\#18](https://github.com/nlohmann/json/pull/18) ([Teemperor](https://github.com/Teemperor)) +- Fix double delete on std::bad\_alloc exception [\#14](https://github.com/nlohmann/json/pull/14) ([elliotgoodrich](https://github.com/elliotgoodrich)) +- Added CMake and lcov [\#6](https://github.com/nlohmann/json/pull/6) ([Teemperor](https://github.com/Teemperor)) +- Version 2.0 [\#5](https://github.com/nlohmann/json/pull/5) ([nlohmann](https://github.com/nlohmann)) + + + +\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* diff --git a/libs/json/LICENSE.MIT b/libs/json/LICENSE.MIT new file mode 100644 index 000000000..f0622d6dc --- /dev/null +++ b/libs/json/LICENSE.MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-2021 Niels Lohmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libs/json/README.md b/libs/json/README.md new file mode 100644 index 000000000..cb43b4f16 --- /dev/null +++ b/libs/json/README.md @@ -0,0 +1,1711 @@ +[![JSON for Modern C++](https://raw.githubusercontent.com/nlohmann/json/master/doc/json.gif)](https://github.com/nlohmann/json/releases) + +[![Build Status](https://app.travis-ci.com/nlohmann/json.svg?branch=develop)](https://app.travis-ci.com/nlohmann/json) +[![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?svg=true)](https://ci.appveyor.com/project/nlohmann/json) +[![Ubuntu](https://github.com/nlohmann/json/workflows/Ubuntu/badge.svg)](https://github.com/nlohmann/json/actions?query=workflow%3AUbuntu) +[![macOS](https://github.com/nlohmann/json/workflows/macOS/badge.svg)](https://github.com/nlohmann/json/actions?query=workflow%3AmacOS) +[![Windows](https://github.com/nlohmann/json/workflows/Windows/badge.svg)](https://github.com/nlohmann/json/actions?query=workflow%3AWindows) +[![Coverage Status](https://coveralls.io/repos/github/nlohmann/json/badge.svg?branch=develop)](https://coveralls.io/github/nlohmann/json?branch=develop) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json) +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/e0d1a9d5d6fd46fcb655c4cb930bb3e8)](https://www.codacy.com/gh/nlohmann/json/dashboard?utm_source=github.com&utm_medium=referral&utm_content=nlohmann/json&utm_campaign=Badge_Grade) +[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/nlohmann/json.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/nlohmann/json/context:cpp) +[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/json.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json) +[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/1mp10JbaANo6FUc7) +[![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](https://nlohmann.github.io/json/doxygen/index.html) +[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT) +[![GitHub Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases) +[![GitHub Downloads](https://img.shields.io/github/downloads/nlohmann/json/total)](https://github.com/nlohmann/json/releases) +[![GitHub Issues](https://img.shields.io/github/issues/nlohmann/json.svg)](https://github.com/nlohmann/json/issues) +[![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/nlohmann/json.svg)](https://isitmaintained.com/project/nlohmann/json "Average time to resolve an issue") +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/289/badge)](https://bestpractices.coreinfrastructure.org/projects/289) +[![GitHub Sponsors](https://img.shields.io/badge/GitHub-Sponsors-ff69b4)](https://github.com/sponsors/nlohmann) + +- [Design goals](#design-goals) +- [Sponsors](#sponsors) +- [Support](#support) ([documentation](https://json.nlohmann.me), [FAQ](http://127.0.0.1:8000/home/faq/), [discussions](https://github.com/nlohmann/json/discussions), [API](https://json.nlohmann.me/api/basic_json/), [bug issues](https://github.com/nlohmann/json/issues)) +- [Examples](#examples) + - [JSON as first-class data type](#json-as-first-class-data-type) + - [Serialization / Deserialization](#serialization--deserialization) + - [STL-like access](#stl-like-access) + - [Conversion from STL containers](#conversion-from-stl-containers) + - [JSON Pointer and JSON Patch](#json-pointer-and-json-patch) + - [JSON Merge Patch](#json-merge-patch) + - [Implicit conversions](#implicit-conversions) + - [Conversions to/from arbitrary types](#arbitrary-types-conversions) + - [Specializing enum conversion](#specializing-enum-conversion) + - [Binary formats (BSON, CBOR, MessagePack, and UBJSON)](#binary-formats-bson-cbor-messagepack-and-ubjson) +- [Supported compilers](#supported-compilers) +- [Integration](#integration) + - [CMake](#cmake) + - [Package Managers](#package-managers) + - [Pkg-config](#pkg-config) +- [License](#license) +- [Contact](#contact) +- [Thanks](#thanks) +- [Used third-party tools](#used-third-party-tools) +- [Projects using JSON for Modern C++](#projects-using-json-for-modern-c) +- [Notes](#notes) +- [Execute unit tests](#execute-unit-tests) + +## Design goals + +There are myriads of [JSON](https://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals: + +- **Intuitive syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of modern C++ to achieve the same feeling in your code. Check out the [examples below](#examples) and you'll know what I mean. + +- **Trivial integration**. Our whole code consists of a single header file [`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp). That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings. + +- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/tree/develop/test/src) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](https://valgrind.org) and the [Clang Sanitizers](https://clang.llvm.org/docs/index.html) that there are no memory leaks. [Google OSS-Fuzz](https://github.com/google/oss-fuzz/tree/master/projects/json) additionally runs fuzz tests against all parsers 24/7, effectively executing billions of tests so far. To maintain high quality, the project is following the [Core Infrastructure Initiative (CII) best practices](https://bestpractices.coreinfrastructure.org/projects/289). + +Other aspects were not so important to us: + +- **Memory efficiency**. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). The default generalization uses the following C++ data types: `std::string` for strings, `int64_t`, `uint64_t` or `double` for numbers, `std::map` for objects, `std::vector` for arrays, and `bool` for Booleans. However, you can template the generalized class `basic_json` to your needs. + +- **Speed**. There are certainly [faster JSON libraries](https://github.com/miloyip/nativejson-benchmark#parsing-time) out there. However, if your goal is to speed up your development by adding JSON support with a single header, then this library is the way to go. If you know how to use a `std::vector` or `std::map`, you are already set. + +See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information. + + +## Sponsors + +You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nlohmann). + +### :label: Named Sponsors + +- [Michael Hartmann](https://github.com/reFX-Mike) +- [Stefan Hagen](https://github.com/sthagen) +- [Steve Sperandeo](https://github.com/homer6) +- [Robert Jefe Lindstädt](https://github.com/eljefedelrodeodeljefe) +- [Steve Wagner](https://github.com/ciroque) + +Thanks everyone! + +## Support + +:question: If you have a **question**, please check if it is already answered in the [**FAQ**](https://json.nlohmann.me/home/faq/) or the [**Q&A**](https://github.com/nlohmann/json/discussions/categories/q-a) section. If not, please [**ask a new question**](https://github.com/nlohmann/json/discussions/new) there. + +:books: If you want to **learn more** about how to use the library, check out the rest of the [**README**](#examples), have a look at [**code examples**](https://github.com/nlohmann/json/tree/develop/doc/examples), or browse through the [**help pages**](https://json.nlohmann.me). + +:construction: If you want to understand the **API** better, check out the [**API Reference**](https://json.nlohmann.me/api/basic_json/) or the [**Doxygen documentation**](https://json.nlohmann.me/doxygen/index.html). + +:bug: If you found a **bug**, please check the [**FAQ**](https://json.nlohmann.me/home/faq/) if it is a known issue or the result of a design decision. Please also have a look at the [**issue list**](https://github.com/nlohmann/json/issues) before you [**create a new issue**](https://github.com/nlohmann/json/issues/new/choose). Please provide as many information as possible to help us understand and reproduce your issue. + +There is also a [**docset**](https://github.com/Kapeli/Dash-User-Contributions/tree/master/docsets/JSON_for_Modern_C%2B%2B) for the documentation browsers [Dash](https://kapeli.com/dash), [Velocity](https://velocity.silverlakesoftware.com), and [Zeal](https://zealdocs.org) that contains the full [documentation](https://json.nlohmann.me) as offline resource. + +## Examples + +Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/api/basic_json/emplace/)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)). + +### JSON as first-class data type + +Here are some examples to give you an idea how to use the class. + +Assume you want to create the JSON object + +```json +{ + "pi": 3.141, + "happy": true, + "name": "Niels", + "nothing": null, + "answer": { + "everything": 42 + }, + "list": [1, 0, 2], + "object": { + "currency": "USD", + "value": 42.99 + } +} +``` + +With this library, you could write: + +```cpp +// create an empty structure (null) +json j; + +// add a number that is stored as double (note the implicit conversion of j to an object) +j["pi"] = 3.141; + +// add a Boolean that is stored as bool +j["happy"] = true; + +// add a string that is stored as std::string +j["name"] = "Niels"; + +// add another null object by passing nullptr +j["nothing"] = nullptr; + +// add an object inside the object +j["answer"]["everything"] = 42; + +// add an array that is stored as std::vector (using an initializer list) +j["list"] = { 1, 0, 2 }; + +// add another object (using an initializer list of pairs) +j["object"] = { {"currency", "USD"}, {"value", 42.99} }; + +// instead, you could also write (which looks very similar to the JSON above) +json j2 = { + {"pi", 3.141}, + {"happy", true}, + {"name", "Niels"}, + {"nothing", nullptr}, + {"answer", { + {"everything", 42} + }}, + {"list", {1, 0, 2}}, + {"object", { + {"currency", "USD"}, + {"value", 42.99} + }} +}; +``` + +Note that in all these cases, you never need to "tell" the compiler which JSON value type you want to use. If you want to be explicit or express some edge cases, the functions [`json::array()`](https://nlohmann.github.io/json/api/basic_json/array/) and [`json::object()`](https://nlohmann.github.io/json/api/basic_json/object/) will help: + +```cpp +// a way to express the empty array [] +json empty_array_explicit = json::array(); + +// ways to express the empty object {} +json empty_object_implicit = json({}); +json empty_object_explicit = json::object(); + +// a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]] +json array_not_object = json::array({ {"currency", "USD"}, {"value", 42.99} }); +``` + +### Serialization / Deserialization + +#### To/from strings + +You can create a JSON value (deserialization) by appending `_json` to a string literal: + +```cpp +// create object from string literal +json j = "{ \"happy\": true, \"pi\": 3.141 }"_json; + +// or even nicer with a raw string literal +auto j2 = R"( + { + "happy": true, + "pi": 3.141 + } +)"_json; +``` + +Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string `"{ "happy": true, "pi": 3.141 }"` rather than parsing the actual object. + +The above example can also be expressed explicitly using [`json::parse()`](https://nlohmann.github.io/json/api/basic_json/parse/): + +```cpp +// parse explicitly +auto j3 = json::parse(R"({"happy": true, "pi": 3.141})"); +``` + +You can also get a string representation of a JSON value (serialize): + +```cpp +// explicit conversion to string +std::string s = j.dump(); // {"happy":true,"pi":3.141} + +// serialization with pretty printing +// pass in the amount of spaces to indent +std::cout << j.dump(4) << std::endl; +// { +// "happy": true, +// "pi": 3.141 +// } +``` + +Note the difference between serialization and assignment: + +```cpp +// store a string in a JSON value +json j_string = "this is a string"; + +// retrieve the string value +auto cpp_string = j_string.get(); +// retrieve the string value (alternative when an variable already exists) +std::string cpp_string2; +j_string.get_to(cpp_string2); + +// retrieve the serialized value (explicit JSON serialization) +std::string serialized_string = j_string.dump(); + +// output of original string +std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get() << '\n'; +// output of serialized value +std::cout << j_string << " == " << serialized_string << std::endl; +``` + +[`.dump()`](https://nlohmann.github.io/json/api/basic_json/dump/) returns the originally stored string value. + +Note the library only supports UTF-8. When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers. + +#### To/from streams (e.g. files, string streams) + +You can also use streams to serialize and deserialize: + +```cpp +// deserialize from standard input +json j; +std::cin >> j; + +// serialize to standard output +std::cout << j; + +// the setw manipulator was overloaded to set the indentation for pretty printing +std::cout << std::setw(4) << j << std::endl; +``` + +These operators work for any subclasses of `std::istream` or `std::ostream`. Here is the same example with files: + +```cpp +// read a JSON file +std::ifstream i("file.json"); +json j; +i >> j; + +// write prettified JSON to another file +std::ofstream o("pretty.json"); +o << std::setw(4) << j << std::endl; +``` + +Please note that setting the exception bit for `failbit` is inappropriate for this use case. It will result in program termination due to the `noexcept` specifier in use. + +#### Read from iterator range + +You can also parse JSON from an iterator range; that is, from any container accessible by iterators whose `value_type` is an integral type of 1, 2 or 4 bytes, which will be interpreted as UTF-8, UTF-16 and UTF-32 respectively. For instance, a `std::vector`, or a `std::list`: + +```cpp +std::vector v = {'t', 'r', 'u', 'e'}; +json j = json::parse(v.begin(), v.end()); +``` + +You may leave the iterators for the range [begin, end): + +```cpp +std::vector v = {'t', 'r', 'u', 'e'}; +json j = json::parse(v); +``` + +#### Custom data source + +Since the parse function accepts arbitrary iterator ranges, you can provide your own data sources by implementing the `LegacyInputIterator` concept. + +```cpp +struct MyContainer { + void advance(); + const char& get_current(); +}; + +struct MyIterator { + using difference_type = std::ptrdiff_t; + using value_type = char; + using pointer = const char*; + using reference = const char&; + using iterator_category = std::input_iterator_tag; + + MyIterator& operator++() { + MyContainer.advance(); + return *this; + } + + bool operator!=(const MyIterator& rhs) const { + return rhs.target != target; + } + + reference operator*() const { + return target.get_current(); + } + + MyContainer* target = nullptr; +}; + +MyIterator begin(MyContainer& tgt) { + return MyIterator{&tgt}; +} + +MyIterator end(const MyContainer&) { + return {}; +} + +void foo() { + MyContainer c; + json j = json::parse(c); +} +``` + +#### SAX interface + +The library uses a SAX-like interface with the following functions: + +```cpp +// called when null is parsed +bool null(); + +// called when a boolean is parsed; value is passed +bool boolean(bool val); + +// called when a signed or unsigned integer number is parsed; value is passed +bool number_integer(number_integer_t val); +bool number_unsigned(number_unsigned_t val); + +// called when a floating-point number is parsed; value and original string is passed +bool number_float(number_float_t val, const string_t& s); + +// called when a string is parsed; value is passed and can be safely moved away +bool string(string_t& val); +// called when a binary value is parsed; value is passed and can be safely moved away +bool binary(binary_t& val); + +// called when an object or array begins or ends, resp. The number of elements is passed (or -1 if not known) +bool start_object(std::size_t elements); +bool end_object(); +bool start_array(std::size_t elements); +bool end_array(); +// called when an object key is parsed; value is passed and can be safely moved away +bool key(string_t& val); + +// called when a parse error occurs; byte position, the last token, and an exception is passed +bool parse_error(std::size_t position, const std::string& last_token, const detail::exception& ex); +``` + +The return value of each function determines whether parsing should proceed. + +To implement your own SAX handler, proceed as follows: + +1. Implement the SAX interface in a class. You can use class `nlohmann::json_sax` as base class, but you can also use any class where the functions described above are implemented and public. +2. Create an object of your SAX interface class, e.g. `my_sax`. +3. Call `bool json::sax_parse(input, &my_sax)`; where the first parameter can be any input like a string or an input stream and the second parameter is a pointer to your SAX interface. + +Note the `sax_parse` function only returns a `bool` indicating the result of the last executed SAX event. It does not return a `json` value - it is up to you to decide what to do with the SAX events. Furthermore, no exceptions are thrown in case of a parse error - it is up to you what to do with the exception object passed to your `parse_error` implementation. Internally, the SAX interface is used for the DOM parser (class `json_sax_dom_parser`) as well as the acceptor (`json_sax_acceptor`), see file [`json_sax.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/detail/input/json_sax.hpp). + +### STL-like access + +We designed the JSON class to behave just like an STL container. In fact, it satisfies the [**ReversibleContainer**](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) requirement. + +```cpp +// create an array using push_back +json j; +j.push_back("foo"); +j.push_back(1); +j.push_back(true); + +// also use emplace_back +j.emplace_back(1.78); + +// iterate the array +for (json::iterator it = j.begin(); it != j.end(); ++it) { + std::cout << *it << '\n'; +} + +// range-based for +for (auto& element : j) { + std::cout << element << '\n'; +} + +// getter/setter +const auto tmp = j[0].get(); +j[1] = 42; +bool foo = j.at(2); + +// comparison +j == R"(["foo", 1, true, 1.78])"_json; // true + +// other stuff +j.size(); // 4 entries +j.empty(); // false +j.type(); // json::value_t::array +j.clear(); // the array is empty again + +// convenience type checkers +j.is_null(); +j.is_boolean(); +j.is_number(); +j.is_object(); +j.is_array(); +j.is_string(); + +// create an object +json o; +o["foo"] = 23; +o["bar"] = false; +o["baz"] = 3.141; + +// also use emplace +o.emplace("weather", "sunny"); + +// special iterator member functions for objects +for (json::iterator it = o.begin(); it != o.end(); ++it) { + std::cout << it.key() << " : " << it.value() << "\n"; +} + +// the same code as range for +for (auto& el : o.items()) { + std::cout << el.key() << " : " << el.value() << "\n"; +} + +// even easier with structured bindings (C++17) +for (auto& [key, value] : o.items()) { + std::cout << key << " : " << value << "\n"; +} + +// find an entry +if (o.contains("foo")) { + // there is an entry with key "foo" +} + +// or via find and an iterator +if (o.find("foo") != o.end()) { + // there is an entry with key "foo" +} + +// or simpler using count() +int foo_present = o.count("foo"); // 1 +int fob_present = o.count("fob"); // 0 + +// delete an entry +o.erase("foo"); +``` + + +### Conversion from STL containers + +Any sequence container (`std::array`, `std::vector`, `std::deque`, `std::forward_list`, `std::list`) whose values can be used to construct JSON values (e.g., integers, floating point numbers, Booleans, string types, or again STL containers described in this section) can be used to create a JSON array. The same holds for similar associative containers (`std::set`, `std::multiset`, `std::unordered_set`, `std::unordered_multiset`), but in these cases the order of the elements of the array depends on how the elements are ordered in the respective STL container. + +```cpp +std::vector c_vector {1, 2, 3, 4}; +json j_vec(c_vector); +// [1, 2, 3, 4] + +std::deque c_deque {1.2, 2.3, 3.4, 5.6}; +json j_deque(c_deque); +// [1.2, 2.3, 3.4, 5.6] + +std::list c_list {true, true, false, true}; +json j_list(c_list); +// [true, true, false, true] + +std::forward_list c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543}; +json j_flist(c_flist); +// [12345678909876, 23456789098765, 34567890987654, 45678909876543] + +std::array c_array {{1, 2, 3, 4}}; +json j_array(c_array); +// [1, 2, 3, 4] + +std::set c_set {"one", "two", "three", "four", "one"}; +json j_set(c_set); // only one entry for "one" is used +// ["four", "one", "three", "two"] + +std::unordered_set c_uset {"one", "two", "three", "four", "one"}; +json j_uset(c_uset); // only one entry for "one" is used +// maybe ["two", "three", "four", "one"] + +std::multiset c_mset {"one", "two", "one", "four"}; +json j_mset(c_mset); // both entries for "one" are used +// maybe ["one", "two", "one", "four"] + +std::unordered_multiset c_umset {"one", "two", "one", "four"}; +json j_umset(c_umset); // both entries for "one" are used +// maybe ["one", "two", "one", "four"] +``` + +Likewise, any associative key-value containers (`std::map`, `std::multimap`, `std::unordered_map`, `std::unordered_multimap`) whose keys can construct an `std::string` and whose values can be used to construct JSON values (see examples above) can be used to create a JSON object. Note that in case of multimaps only one key is used in the JSON object and the value depends on the internal order of the STL container. + +```cpp +std::map c_map { {"one", 1}, {"two", 2}, {"three", 3} }; +json j_map(c_map); +// {"one": 1, "three": 3, "two": 2 } + +std::unordered_map c_umap { {"one", 1.2}, {"two", 2.3}, {"three", 3.4} }; +json j_umap(c_umap); +// {"one": 1.2, "two": 2.3, "three": 3.4} + +std::multimap c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; +json j_mmap(c_mmap); // only one entry for key "three" is used +// maybe {"one": true, "two": true, "three": true} + +std::unordered_multimap c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} }; +json j_ummap(c_ummap); // only one entry for key "three" is used +// maybe {"one": true, "two": true, "three": true} +``` + +### JSON Pointer and JSON Patch + +The library supports **JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) as alternative means to address structured values. On top of this, **JSON Patch** ([RFC 6902](https://tools.ietf.org/html/rfc6902)) allows to describe differences between two JSON values - effectively allowing patch and diff operations known from Unix. + +```cpp +// a JSON value +json j_original = R"({ + "baz": ["one", "two", "three"], + "foo": "bar" +})"_json; + +// access members with a JSON pointer (RFC 6901) +j_original["/baz/1"_json_pointer]; +// "two" + +// a JSON patch (RFC 6902) +json j_patch = R"([ + { "op": "replace", "path": "/baz", "value": "boo" }, + { "op": "add", "path": "/hello", "value": ["world"] }, + { "op": "remove", "path": "/foo"} +])"_json; + +// apply the patch +json j_result = j_original.patch(j_patch); +// { +// "baz": "boo", +// "hello": ["world"] +// } + +// calculate a JSON patch from two JSON values +json::diff(j_result, j_original); +// [ +// { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] }, +// { "op": "remove","path": "/hello" }, +// { "op": "add", "path": "/foo", "value": "bar" } +// ] +``` + +### JSON Merge Patch + +The library supports **JSON Merge Patch** ([RFC 7386](https://tools.ietf.org/html/rfc7386)) as a patch format. Instead of using JSON Pointer (see above) to specify values to be manipulated, it describes the changes using a syntax that closely mimics the document being modified. + +```cpp +// a JSON value +json j_document = R"({ + "a": "b", + "c": { + "d": "e", + "f": "g" + } +})"_json; + +// a patch +json j_patch = R"({ + "a":"z", + "c": { + "f": null + } +})"_json; + +// apply the patch +j_document.merge_patch(j_patch); +// { +// "a": "z", +// "c": { +// "d": "e" +// } +// } +``` + +### Implicit conversions + +Supported types can be implicitly converted to JSON values. + +It is recommended to **NOT USE** implicit conversions **FROM** a JSON value. +You can find more details about this recommendation [here](https://www.github.com/nlohmann/json/issues/958). +You can switch off implicit conversions by defining `JSON_USE_IMPLICIT_CONVERSIONS` to `0` before including the `json.hpp` header. When using CMake, you can also achieve this by setting the option `JSON_ImplicitConversions` to `OFF`. + +```cpp +// strings +std::string s1 = "Hello, world!"; +json js = s1; +auto s2 = js.get(); +// NOT RECOMMENDED +std::string s3 = js; +std::string s4; +s4 = js; + +// Booleans +bool b1 = true; +json jb = b1; +auto b2 = jb.get(); +// NOT RECOMMENDED +bool b3 = jb; +bool b4; +b4 = jb; + +// numbers +int i = 42; +json jn = i; +auto f = jn.get(); +// NOT RECOMMENDED +double f2 = jb; +double f3; +f3 = jb; + +// etc. +``` + +Note that `char` types are not automatically converted to JSON strings, but to integer numbers. A conversion to a string must be specified explicitly: + +```cpp +char ch = 'A'; // ASCII value 65 +json j_default = ch; // stores integer number 65 +json j_string = std::string(1, ch); // stores string "A" +``` + +### Arbitrary types conversions + +Every type can be serialized in JSON, not just STL containers and scalar types. Usually, you would do something along those lines: + +```cpp +namespace ns { + // a simple struct to model a person + struct person { + std::string name; + std::string address; + int age; + }; +} + +ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + +// convert to JSON: copy each value into the JSON object +json j; +j["name"] = p.name; +j["address"] = p.address; +j["age"] = p.age; + +// ... + +// convert from JSON: copy each value from the JSON object +ns::person p { + j["name"].get(), + j["address"].get(), + j["age"].get() +}; +``` + +It works, but that's quite a lot of boilerplate... Fortunately, there's a better way: + +```cpp +// create a person +ns::person p {"Ned Flanders", "744 Evergreen Terrace", 60}; + +// conversion: person -> json +json j = p; + +std::cout << j << std::endl; +// {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} + +// conversion: json -> person +auto p2 = j.get(); + +// that's it +assert(p == p2); +``` + +#### Basic usage + +To make this work with one of your types, you only need to provide two functions: + +```cpp +using json = nlohmann::json; + +namespace ns { + void to_json(json& j, const person& p) { + j = json{{"name", p.name}, {"address", p.address}, {"age", p.age}}; + } + + void from_json(const json& j, person& p) { + j.at("name").get_to(p.name); + j.at("address").get_to(p.address); + j.at("age").get_to(p.age); + } +} // namespace ns +``` + +That's all! When calling the `json` constructor with your type, your custom `to_json` method will be automatically called. +Likewise, when calling `get()` or `get_to(your_type&)`, the `from_json` method will be called. + +Some important things: + +* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined). +* Those methods **MUST** be available (e.g., proper headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise. +* When using `get()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.) +* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/api/basic_json/at/) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. +* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these. + +#### Simplify your life with macros + +If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate. + +There are two macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object: + +- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)` is to be defined inside of the namespace of the class/struct to create code for. +- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)` is to be defined inside of the class/struct to create code for. This macro can also access private members. + +In both macros, the first parameter is the name of the class/struct, and all remaining parameters name the members. + +##### Examples + +The `to_json`/`from_json` functions for the `person` struct above can be created with: + +```cpp +namespace ns { + NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age) +} +``` + +Here is an example with private members, where `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is needed: + +```cpp +namespace ns { + class address { + private: + std::string street; + int housenumber; + int postcode; + + public: + NLOHMANN_DEFINE_TYPE_INTRUSIVE(address, street, housenumber, postcode) + }; +} +``` + +#### How do I convert third-party types? + +This requires a bit more advanced technique. But first, let's see how this conversion mechanism works: + +The library uses **JSON Serializers** to convert types to json. +The default serializer for `nlohmann::json` is `nlohmann::adl_serializer` (ADL means [Argument-Dependent Lookup](https://en.cppreference.com/w/cpp/language/adl)). + +It is implemented like this (simplified): + +```cpp +template +struct adl_serializer { + static void to_json(json& j, const T& value) { + // calls the "to_json" method in T's namespace + } + + static void from_json(const json& j, T& value) { + // same thing, but with the "from_json" method + } +}; +``` + +This serializer works fine when you have control over the type's namespace. However, what about `boost::optional` or `std::filesystem::path` (C++17)? Hijacking the `boost` namespace is pretty bad, and it's illegal to add something other than template specializations to `std`... + +To solve this, you need to add a specialization of `adl_serializer` to the `nlohmann` namespace, here's an example: + +```cpp +// partial specialization (full specialization works too) +namespace nlohmann { + template + struct adl_serializer> { + static void to_json(json& j, const boost::optional& opt) { + if (opt == boost::none) { + j = nullptr; + } else { + j = *opt; // this will call adl_serializer::to_json which will + // find the free function to_json in T's namespace! + } + } + + static void from_json(const json& j, boost::optional& opt) { + if (j.is_null()) { + opt = boost::none; + } else { + opt = j.get(); // same as above, but with + // adl_serializer::from_json + } + } + }; +} +``` + +#### How can I use `get()` for non-default constructible/non-copyable types? + +There is a way, if your type is [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload: + +```cpp +struct move_only_type { + move_only_type() = delete; + move_only_type(int ii): i(ii) {} + move_only_type(const move_only_type&) = delete; + move_only_type(move_only_type&&) = default; + + int i; +}; + +namespace nlohmann { + template <> + struct adl_serializer { + // note: the return type is no longer 'void', and the method only takes + // one argument + static move_only_type from_json(const json& j) { + return {j.get()}; + } + + // Here's the catch! You must provide a to_json method! Otherwise you + // will not be able to convert move_only_type to json, since you fully + // specialized adl_serializer on that type + static void to_json(json& j, move_only_type t) { + j = t.i; + } + }; +} +``` + +#### Can I write my own serializer? (Advanced use) + +Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/test/src/unit-udt.cpp) in the test suite, to see a few examples. + +If you write your own serializer, you'll need to do a few things: + +- use a different `basic_json` alias than `nlohmann::json` (the last template parameter of `basic_json` is the `JSONSerializer`) +- use your `basic_json` alias (or a template parameter) in all your `to_json`/`from_json` methods +- use `nlohmann::to_json` and `nlohmann::from_json` when you need ADL + +Here is an example, without simplifications, that only accepts types with a size <= 32, and uses ADL. + +```cpp +// You should use void as a second template argument +// if you don't need compile-time checks on T +template::type> +struct less_than_32_serializer { + template + static void to_json(BasicJsonType& j, T value) { + // we want to use ADL, and call the correct to_json overload + using nlohmann::to_json; // this method is called by adl_serializer, + // this is where the magic happens + to_json(j, value); + } + + template + static void from_json(const BasicJsonType& j, T& value) { + // same thing here + using nlohmann::from_json; + from_json(j, value); + } +}; +``` + +Be **very** careful when reimplementing your serializer, you can stack overflow if you don't pay attention: + +```cpp +template +struct bad_serializer +{ + template + static void to_json(BasicJsonType& j, const T& value) { + // this calls BasicJsonType::json_serializer::to_json(j, value); + // if BasicJsonType::json_serializer == bad_serializer ... oops! + j = value; + } + + template + static void to_json(const BasicJsonType& j, T& value) { + // this calls BasicJsonType::json_serializer::from_json(j, value); + // if BasicJsonType::json_serializer == bad_serializer ... oops! + value = j.template get(); // oops! + } +}; +``` + +### Specializing enum conversion + +By default, enum values are serialized to JSON as integers. In some cases this could result in undesired behavior. If an enum is modified or re-ordered after data has been serialized to JSON, the later de-serialized JSON data may be undefined or a different enum value than was originally intended. + +It is possible to more precisely specify how a given enum is mapped to and from JSON as shown below: + +```cpp +// example enum type declaration +enum TaskState { + TS_STOPPED, + TS_RUNNING, + TS_COMPLETED, + TS_INVALID=-1, +}; + +// map TaskState values to JSON as strings +NLOHMANN_JSON_SERIALIZE_ENUM( TaskState, { + {TS_INVALID, nullptr}, + {TS_STOPPED, "stopped"}, + {TS_RUNNING, "running"}, + {TS_COMPLETED, "completed"}, +}) +``` + +The `NLOHMANN_JSON_SERIALIZE_ENUM()` macro declares a set of `to_json()` / `from_json()` functions for type `TaskState` while avoiding repetition and boilerplate serialization code. + +**Usage:** + +```cpp +// enum to JSON as string +json j = TS_STOPPED; +assert(j == "stopped"); + +// json string to enum +json j3 = "running"; +assert(j3.get() == TS_RUNNING); + +// undefined json value to enum (where the first map entry above is the default) +json jPi = 3.14; +assert(jPi.get() == TS_INVALID ); +``` + +Just as in [Arbitrary Type Conversions](#arbitrary-types-conversions) above, +- `NLOHMANN_JSON_SERIALIZE_ENUM()` MUST be declared in your enum type's namespace (which can be the global namespace), or the library will not be able to locate it and it will default to integer serialization. +- It MUST be available (e.g., proper headers must be included) everywhere you use the conversions. + +Other Important points: +- When using `get()`, undefined JSON values will default to the first pair specified in your map. Select this default pair carefully. +- If an enum or JSON value is specified more than once in your map, the first matching occurrence from the top of the map will be returned when converting to or from JSON. + +### Binary formats (BSON, CBOR, MessagePack, and UBJSON) + +Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [BSON](https://bsonspec.org) (Binary JSON), [CBOR](https://cbor.io) (Concise Binary Object Representation), [MessagePack](https://msgpack.org), and [UBJSON](https://ubjson.org) (Universal Binary JSON Specification) to efficiently encode JSON values to byte vectors and to decode such vectors. + +```cpp +// create a JSON value +json j = R"({"compact": true, "schema": 0})"_json; + +// serialize to BSON +std::vector v_bson = json::to_bson(j); + +// 0x1B, 0x00, 0x00, 0x00, 0x08, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0x00, 0x01, 0x10, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + +// roundtrip +json j_from_bson = json::from_bson(v_bson); + +// serialize to CBOR +std::vector v_cbor = json::to_cbor(j); + +// 0xA2, 0x67, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0xF5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x00 + +// roundtrip +json j_from_cbor = json::from_cbor(v_cbor); + +// serialize to MessagePack +std::vector v_msgpack = json::to_msgpack(j); + +// 0x82, 0xA7, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0xC3, 0xA6, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x00 + +// roundtrip +json j_from_msgpack = json::from_msgpack(v_msgpack); + +// serialize to UBJSON +std::vector v_ubjson = json::to_ubjson(j); + +// 0x7B, 0x69, 0x07, 0x63, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0x54, 0x69, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6D, 0x61, 0x69, 0x00, 0x7D + +// roundtrip +json j_from_ubjson = json::from_ubjson(v_ubjson); +``` + +The library also supports binary types from BSON, CBOR (byte strings), and MessagePack (bin, ext, fixext). They are stored by default as `std::vector` to be processed outside of the library. + +```cpp +// CBOR byte string with payload 0xCAFE +std::vector v = {0x42, 0xCA, 0xFE}; + +// read value +json j = json::from_cbor(v); + +// the JSON value has type binary +j.is_binary(); // true + +// get reference to stored binary value +auto& binary = j.get_binary(); + +// the binary value has no subtype (CBOR has no binary subtypes) +binary.has_subtype(); // false + +// access std::vector member functions +binary.size(); // 2 +binary[0]; // 0xCA +binary[1]; // 0xFE + +// set subtype to 0x10 +binary.set_subtype(0x10); + +// serialize to MessagePack +auto cbor = json::to_msgpack(j); // 0xD5 (fixext2), 0x10, 0xCA, 0xFE +``` + + +## Supported compilers + +Though it's 2021 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work: + +- GCC 4.8 - 11.0 (and possibly later) +- Clang 3.4 - 13.0 (and possibly later) +- Apple Clang 9.1 - 12.4 (and possibly later) +- Intel C++ Compiler 17.0.2 (and possibly later) +- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later) +- Microsoft Visual C++ 2017 / Build Tools 15.5.180.51428 (and possibly later) +- Microsoft Visual C++ 2019 / Build Tools 16.3.1+1def00d3d (and possibly later) + +I would be happy to learn about other compilers/versions. + +Please note: + +- GCC 4.8 has a bug [57824](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824)): multiline raw strings cannot be the arguments to macros. Don't use multiline raw strings directly in macros with this compiler. +- Android defaults to using very old compilers and C++ libraries. To fix this, add the following to your `Application.mk`. This will switch to the LLVM C++ library, the Clang compiler, and enable C++11 and other features disabled by default. + + ``` + APP_STL := c++_shared + NDK_TOOLCHAIN_VERSION := clang3.6 + APP_CPPFLAGS += -frtti -fexceptions + ``` + + The code compiles successfully with [Android NDK](https://developer.android.com/ndk/index.html?hl=ml), Revision 9 - 11 (and possibly later) and [CrystaX's Android NDK](https://www.crystax.net/en/android/ndk) version 10. + +- For GCC running on MinGW or Android SDK, the error `'to_string' is not a member of 'std'` (or similarly, for `strtod` or `strtof`) may occur. Note this is not an issue with the code, but rather with the compiler itself. On Android, see above to build with a newer environment. For MinGW, please refer to [this site](https://tehsausage.com/mingw-to-string) and [this discussion](https://github.com/nlohmann/json/issues/136) for information on how to fix this bug. For Android NDK using `APP_STL := gnustl_static`, please refer to [this discussion](https://github.com/nlohmann/json/issues/219). + +- Unsupported versions of GCC and Clang are rejected by `#error` directives. This can be switched off by defining `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`. Note that you can expect no support in this case. + +The following compilers are currently used in continuous integration at [Travis](https://travis-ci.org/nlohmann/json), [AppVeyor](https://ci.appveyor.com/project/nlohmann/json), [Drone CI](https://cloud.drone.io/nlohmann/json), and [GitHub Actions](https://github.com/nlohmann/json/actions): + +| Compiler | Operating System | CI Provider | +|-------------------------------------------------------------------|--------------------|----------------| +| Apple Clang 10.0.1 (clang-1001.0.46.4); Xcode 10.2.1 | macOS 10.14.4 | Travis | +| Apple Clang 10.0.1 (clang-1001.0.46.4); Xcode 10.3 | macOS 10.15.7 | GitHub Actions | +| Apple Clang 11.0.0 (clang-1100.0.33.12); Xcode 11.2.1 | macOS 10.15.7 | GitHub Actions | +| Apple Clang 11.0.0 (clang-1100.0.33.17); Xcode 11.3.1 | macOS 10.15.7 | GitHub Actions | +| Apple Clang 11.0.3 (clang-1103.0.32.59); Xcode 11.4.1 | macOS 10.15.7 | GitHub Actions | +| Apple Clang 11.0.3 (clang-1103.0.32.62); Xcode 11.5 | macOS 10.15.7 | GitHub Actions | +| Apple Clang 11.0.3 (clang-1103.0.32.62); Xcode 11.6 | macOS 10.15.7 | GitHub Actions | +| Apple Clang 11.0.3 (clang-1103.0.32.62); Xcode 11.7 | macOS 10.15.7 | GitHub Actions | +| Apple Clang 12.0.0 (clang-1200.0.32.2); Xcode 12 | macOS 10.15.7 | GitHub Actions | +| Apple Clang 12.0.0 (clang-1200.0.32.21); Xcode 12.1 | macOS 10.15.7 | GitHub Actions | +| Apple Clang 12.0.0 (clang-1200.0.32.21); Xcode 12.1.1 | macOS 10.15.7 | GitHub Actions | +| Apple Clang 12.0.0 (clang-1200.0.32.27); Xcode 12.2 | macOS 10.15.7 | GitHub Actions | +| Apple Clang 12.0.0 (clang-1200.0.32.28); Xcode 12.3 | macOS 10.15.7 | GitHub Actions | +| Apple Clang 12.0.0 (clang-1200.0.32.29); Xcode 12.4 | macOS 10.15.7 | GitHub Actions | +| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions | +| GCC 4.9.3 (Ubuntu 4.9.3-13ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions | +| GCC 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.12) | Ubuntu 20.04.2 LTS | GitHub Actions | +| GCC 6.5.0 (Ubuntu 6.5.0-2ubuntu1~14.04.1) | Ubuntu 14.04.5 LTS | Travis | +| GCC 7.5.0 (Ubuntu 7.5.0-6ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions | +| GCC 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions | +| GCC 8.1.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions | +| GCC 8.4.0 (Ubuntu 8.4.0-3ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions | +| GCC 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04) | Ubuntu 20.04.2 LTS | GitHub Actions | +| GCC 10.2.0 (Ubuntu 10.2.0-5ubuntu1~20.04) | Ubuntu 20.04.2 LTS | GitHub Actions | +| GCC 11.0.1 20210321 (experimental) | Ubuntu 20.04.2 LTS | GitHub Actions | +| GCC 11.1.0 | Ubuntu (aarch64) | Drone CI | +| Clang 3.5.2 (3.5.2-3ubuntu1) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 3.6.2 (3.6.2-3ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 3.7.1 (3.7.1-2ubuntu2) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 3.8.0 (3.8.0-2ubuntu4) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 3.9.1 (3.9.1-4ubuntu3\~16.04.2) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 4.0.0 (4.0.0-1ubuntu1\~16.04.2) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 5.0.0 (5.0.0-3\~16.04.1) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 6.0.1 (6.0.1-14) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 7.0.1 (7.0.1-12) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 8.0.1 (8.0.1-9) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 9.0.1 (9.0.1-12) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 10.0.0 (10.0.0-4ubuntu1) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 10.0.0 with GNU-like command-line | Windows-10.0.17763 | GitHub Actions | +| Clang 11.0.0 with GNU-like command-line | Windows-10.0.17763 | GitHub Actions | +| Clang 11.0.0 with MSVC-like command-line | Windows-10.0.17763 | GitHub Actions | +| Clang 11.0.0 (11.0.0-2~ubuntu20.04.1) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 12.0.0 (12.0.0-3ubuntu1~20.04.3) | Ubuntu 20.04.2 LTS | GitHub Actions | +| Clang 13.0.0 (13.0.0-++20210828094952+9c49fee5e7ac-1exp120210828075752.71 | Ubuntu 20.04.2 LTS | GitHub Actions | +| Visual Studio 14 2015 MSVC 19.0.24241.7 (Build Engine version 14.0.25420.1) | Windows-6.3.9600 | AppVeyor | +| Visual Studio 15 2017 MSVC 19.16.27035.0 (Build Engine version 15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | AppVeyor | +| Visual Studio 15 2017 MSVC 19.16.27045.0 (Build Engine version 15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | GitHub Actions | +| Visual Studio 16 2019 MSVC 19.28.29912.0 (Build Engine version 16.9.0+57a23d249 for .NET Framework) | Windows-10.0.17763 | GitHub Actions | +| Visual Studio 16 2019 MSVC 19.28.29912.0 (Build Engine version 16.9.0+57a23d249 for .NET Framework) | Windows-10.0.17763 | AppVeyor | + + +## Integration + +[`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp) is the single required file in `single_include/nlohmann` or [released here](https://github.com/nlohmann/json/releases). You need to add + +```cpp +#include + +// for convenience +using json = nlohmann::json; +``` + +to the files you want to process JSON and set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang). + +You can further use file [`include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/json_fwd.hpp) for forward-declarations. The installation of json_fwd.hpp (as part of cmake's install step), can be achieved by setting `-DJSON_MultipleHeaders=ON`. + +### CMake + +You can also use the `nlohmann_json::nlohmann_json` interface target in CMake. This target populates the appropriate usage requirements for `INTERFACE_INCLUDE_DIRECTORIES` to point to the appropriate include directories and `INTERFACE_COMPILE_FEATURES` for the necessary C++11 flags. + +#### External + +To use this library from a CMake project, you can locate it directly with `find_package()` and use the namespaced imported target from the generated package configuration: + +```cmake +# CMakeLists.txt +find_package(nlohmann_json 3.2.0 REQUIRED) +... +add_library(foo ...) +... +target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json) +``` + +The package configuration file, `nlohmann_jsonConfig.cmake`, can be used either from an install tree or directly out of the build tree. + +#### Embedded + +To embed the library directly into an existing CMake project, place the entire source tree in a subdirectory and call `add_subdirectory()` in your `CMakeLists.txt` file: + +```cmake +# Typically you don't care so much for a third party library's tests to be +# run from your own project's code. +set(JSON_BuildTests OFF CACHE INTERNAL "") + +# If you only include this third party in PRIVATE source files, you do not +# need to install it when your main project gets installed. +# set(JSON_Install OFF CACHE INTERNAL "") + +# Don't use include(nlohmann_json/CMakeLists.txt) since that carries with it +# unintended consequences that will break the build. It's generally +# discouraged (although not necessarily well documented as such) to use +# include(...) for pulling in other CMake projects anyways. +add_subdirectory(nlohmann_json) +... +add_library(foo ...) +... +target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json) +``` + +##### Embedded (FetchContent) + +Since CMake v3.11, +[FetchContent](https://cmake.org/cmake/help/v3.11/module/FetchContent.html) can +be used to automatically download the repository as a dependency at configure time. + +Example: +```cmake +include(FetchContent) + +FetchContent_Declare(json + GIT_REPOSITORY https://github.com/nlohmann/json.git + GIT_TAG v3.7.3) + +FetchContent_GetProperties(json) +if(NOT json_POPULATED) + FetchContent_Populate(json) + add_subdirectory(${json_SOURCE_DIR} ${json_BINARY_DIR} EXCLUDE_FROM_ALL) +endif() + +target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json) +``` + +**Note**: The repository https://github.com/nlohmann/json download size is huge. +It contains all the dataset used for the benchmarks. You might want to depend on +a smaller repository. For instance, you might want to replace the URL above by +https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent + +#### Supporting Both + +To allow your project to support either an externally supplied or an embedded JSON library, you can use a pattern akin to the following: + +``` cmake +# Top level CMakeLists.txt +project(FOO) +... +option(FOO_USE_EXTERNAL_JSON "Use an external JSON library" OFF) +... +add_subdirectory(thirdparty) +... +add_library(foo ...) +... +# Note that the namespaced target will always be available regardless of the +# import method +target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json) +``` +```cmake +# thirdparty/CMakeLists.txt +... +if(FOO_USE_EXTERNAL_JSON) + find_package(nlohmann_json 3.2.0 REQUIRED) +else() + set(JSON_BuildTests OFF CACHE INTERNAL "") + add_subdirectory(nlohmann_json) +endif() +... +``` + +`thirdparty/nlohmann_json` is then a complete copy of this source tree. + +### Package Managers + +:beer: If you are using OS X and [Homebrew](https://brew.sh), just type `brew install nlohmann-json` and you're set. If you want the bleeding edge rather than the latest release, use `brew install nlohmann-json --HEAD`. See [nlohmann-json](https://formulae.brew.sh/formula/nlohmann-json) for more information. + +If you are using the [Meson Build System](https://mesonbuild.com), add this source tree as a [meson subproject](https://mesonbuild.com/Subprojects.html#using-a-subproject). You may also use the `include.zip` published in this project's [Releases](https://github.com/nlohmann/json/releases) to reduce the size of the vendored source tree. Alternatively, you can get a wrap file by downloading it from [Meson WrapDB](https://wrapdb.mesonbuild.com/nlohmann_json), or simply use `meson wrap install nlohmann_json`. Please see the meson project for any issues regarding the packaging. + +The provided meson.build can also be used as an alternative to cmake for installing `nlohmann_json` system-wide in which case a pkg-config file is installed. To use it, simply have your build system require the `nlohmann_json` pkg-config dependency. In Meson, it is preferred to use the [`dependency()`](https://mesonbuild.com/Reference-manual.html#dependency) object with a subproject fallback, rather than using the subproject directly. + +If you are using [Conan](https://www.conan.io/) to manage your dependencies, merely add [`nlohmann_json/x.y.z`](https://conan.io/center/nlohmann_json) to your `conanfile`'s requires, where `x.y.z` is the release version you want to use. Please file issues [here](https://github.com/conan-io/conan-center-index/issues) if you experience problems with the packages. + +If you are using [Spack](https://www.spack.io/) to manage your dependencies, you can use the [`nlohmann-json` package](https://spack.readthedocs.io/en/latest/package_list.html#nlohmann-json). Please see the [spack project](https://github.com/spack/spack) for any issues regarding the packaging. + +If you are using [hunter](https://github.com/cpp-pm/hunter) on your project for external dependencies, then you can use the [nlohmann_json package](https://hunter.readthedocs.io/en/latest/packages/pkg/nlohmann_json.html). Please see the hunter project for any issues regarding the packaging. + +If you are using [Buckaroo](https://buckaroo.pm), you can install this library's module with `buckaroo add github.com/buckaroo-pm/nlohmann-json`. Please file issues [here](https://github.com/buckaroo-pm/nlohmann-json). There is a demo repo [here](https://github.com/njlr/buckaroo-nholmann-json-example). + +If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project for external dependencies, then you can install the [nlohmann-json package](https://github.com/Microsoft/vcpkg/tree/master/ports/nlohmann-json) with `vcpkg install nlohmann-json` and follow the then displayed descriptions. Please see the vcpkg project for any issues regarding the packaging. + +If you are using [cget](https://cget.readthedocs.io/en/latest/), you can install the latest development version with `cget install nlohmann/json`. A specific version can be installed with `cget install nlohmann/json@v3.1.0`. Also, the multiple header version can be installed by adding the `-DJSON_MultipleHeaders=ON` flag (i.e., `cget install nlohmann/json -DJSON_MultipleHeaders=ON`). + +If you are using [CocoaPods](https://cocoapods.org), you can use the library by adding pod `"nlohmann_json", '~>3.1.2'` to your podfile (see [an example](https://bitbucket.org/benman/nlohmann_json-cocoapod/src/master/)). Please file issues [here](https://bitbucket.org/benman/nlohmann_json-cocoapod/issues?status=new&status=open). + +If you are using [NuGet](https://www.nuget.org), you can use the package [nlohmann.json](https://www.nuget.org/packages/nlohmann.json/). Please check [this extensive description](https://github.com/nlohmann/json/issues/1132#issuecomment-452250255) on how to use the package. Please files issues [here](https://github.com/hnkb/nlohmann-json-nuget/issues). + +If you are using [conda](https://conda.io/), you can use the package [nlohmann_json](https://github.com/conda-forge/nlohmann_json-feedstock) from [conda-forge](https://conda-forge.org) executing `conda install -c conda-forge nlohmann_json`. Please file issues [here](https://github.com/conda-forge/nlohmann_json-feedstock/issues). + +If you are using [MSYS2](https://www.msys2.org/), you can use the [mingw-w64-nlohmann-json](https://packages.msys2.org/base/mingw-w64-nlohmann-json) package, just type `pacman -S mingw-w64-i686-nlohmann-json` or `pacman -S mingw-w64-x86_64-nlohmann-json` for installation. Please file issues [here](https://github.com/msys2/MINGW-packages/issues/new?title=%5Bnlohmann-json%5D) if you experience problems with the packages. + +If you are using [MacPorts](https://ports.macports.org), execute `sudo port install nlohmann-json` to install the [nlohmann-json](https://ports.macports.org/port/nlohmann-json/) package. + +If you are using [`build2`](https://build2.org), you can use the [`nlohmann-json`](https://cppget.org/nlohmann-json) package from the public repository https://cppget.org or directly from the [package's sources repository](https://github.com/build2-packaging/nlohmann-json). In your project's `manifest` file, just add `depends: nlohmann-json` (probably with some [version constraints](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml#guide-add-remove-deps)). If you are not familiar with using dependencies in `build2`, [please read this introduction](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml). +Please file issues [here](https://github.com/build2-packaging/nlohmann-json) if you experience problems with the packages. + +If you are using [`wsjcpp`](https://wsjcpp.org), you can use the command `wsjcpp install "https://github.com/nlohmann/json:develop"` to get the latest version. Note you can change the branch ":develop" to an existing tag or another branch. + +If you are using [`CPM.cmake`](https://github.com/TheLartians/CPM.cmake), you can check this [`example`](https://github.com/TheLartians/CPM.cmake/tree/master/examples/json). After [adding CPM script](https://github.com/TheLartians/CPM.cmake#adding-cpm) to your project, implement the following snippet to your CMake: + +```cmake +CPMAddPackage( + NAME nlohmann_json + GITHUB_REPOSITORY nlohmann/json + VERSION 3.9.1) +``` + +### Pkg-config + +If you are using bare Makefiles, you can use `pkg-config` to generate the include flags that point to where the library is installed: + +```sh +pkg-config nlohmann_json --cflags +``` + +Users of the Meson build system will also be able to use a system wide library, which will be found by `pkg-config`: + +```meson +json = dependency('nlohmann_json', required: true) +``` + + +## License + + + +The class is licensed under the [MIT License](https://opensource.org/licenses/MIT): + +Copyright © 2013-2021 [Niels Lohmann](https://nlohmann.me) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Softwareâ€), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +* * * + +The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Björn Hoehrmann](https://bjoern.hoehrmann.de/) + +The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/) + +The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/). + +The class contains parts of [Google Abseil](https://github.com/abseil/abseil-cpp) which is licensed under the [Apache 2.0 License](https://opensource.org/licenses/Apache-2.0). + +## Contact + +If you have questions regarding the library, I would like to invite you to [open an issue at GitHub](https://github.com/nlohmann/json/issues/new/choose). Please describe your request, problem, or question as detailed as possible, and also mention the version of the library you are using as well as the version of your compiler and operating system. Opening an issue at GitHub allows other users and contributors to this library to collaborate. For instance, I have little experience with MSVC, and most issues in this regard have been solved by a growing community. If you have a look at the [closed issues](https://github.com/nlohmann/json/issues?q=is%3Aissue+is%3Aclosed), you will see that we react quite timely in most cases. + +Only if your request would contain confidential information, please [send me an email](mailto:mail@nlohmann.me). For encrypted messages, please use [this key](https://keybase.io/nlohmann/pgp_keys.asc). + +## Security + +[Commits by Niels Lohmann](https://github.com/nlohmann/json/commits) and [releases](https://github.com/nlohmann/json/releases) are signed with this [PGP Key](https://keybase.io/nlohmann/pgp_keys.asc?fingerprint=797167ae41c0a6d9232e48457f3cea63ae251b69). + +## Thanks + +I deeply appreciate the help of the following people. + + + +- [Teemperor](https://github.com/Teemperor) implemented CMake support and lcov integration, realized escape and Unicode handling in the string parser, and fixed the JSON serialization. +- [elliotgoodrich](https://github.com/elliotgoodrich) fixed an issue with double deletion in the iterator classes. +- [kirkshoop](https://github.com/kirkshoop) made the iterators of the class composable to other libraries. +- [wancw](https://github.com/wanwc) fixed a bug that hindered the class to compile with Clang. +- Tomas Ã…blad found a bug in the iterator implementation. +- [Joshua C. Randall](https://github.com/jrandall) fixed a bug in the floating-point serialization. +- [Aaron Burghardt](https://github.com/aburgh) implemented code to parse streams incrementally. Furthermore, he greatly improved the parser class by allowing the definition of a filter function to discard undesired elements while parsing. +- [Daniel KopeÄek](https://github.com/dkopecek) fixed a bug in the compilation with GCC 5.0. +- [Florian Weber](https://github.com/Florianjw) fixed a bug in and improved the performance of the comparison operators. +- [Eric Cornelius](https://github.com/EricMCornelius) pointed out a bug in the handling with NaN and infinity values. He also improved the performance of the string escaping. +- [易æ€é¾™](https://github.com/likebeta) implemented a conversion from anonymous enums. +- [kepkin](https://github.com/kepkin) patiently pushed forward the support for Microsoft Visual studio. +- [gregmarr](https://github.com/gregmarr) simplified the implementation of reverse iterators and helped with numerous hints and improvements. In particular, he pushed forward the implementation of user-defined types. +- [Caio Luppi](https://github.com/caiovlp) fixed a bug in the Unicode handling. +- [dariomt](https://github.com/dariomt) fixed some typos in the examples. +- [Daniel Frey](https://github.com/d-frey) cleaned up some pointers and implemented exception-safe memory allocation. +- [Colin Hirsch](https://github.com/ColinH) took care of a small namespace issue. +- [Huu Nguyen](https://github.com/whoshuu) correct a variable name in the documentation. +- [Silverweed](https://github.com/silverweed) overloaded `parse()` to accept an rvalue reference. +- [dariomt](https://github.com/dariomt) fixed a subtlety in MSVC type support and implemented the `get_ref()` function to get a reference to stored values. +- [ZahlGraf](https://github.com/ZahlGraf) added a workaround that allows compilation using Android NDK. +- [whackashoe](https://github.com/whackashoe) replaced a function that was marked as unsafe by Visual Studio. +- [406345](https://github.com/406345) fixed two small warnings. +- [Glen Fernandes](https://github.com/glenfe) noted a potential portability problem in the `has_mapped_type` function. +- [Corbin Hughes](https://github.com/nibroc) fixed some typos in the contribution guidelines. +- [twelsby](https://github.com/twelsby) fixed the array subscript operator, an issue that failed the MSVC build, and floating-point parsing/dumping. He further added support for unsigned integer numbers and implemented better roundtrip support for parsed numbers. +- [Volker Diels-Grabsch](https://github.com/vog) fixed a link in the README file. +- [msm-](https://github.com/msm-) added support for American Fuzzy Lop. +- [Annihil](https://github.com/Annihil) fixed an example in the README file. +- [Themercee](https://github.com/Themercee) noted a wrong URL in the README file. +- [Lv Zheng](https://github.com/lv-zheng) fixed a namespace issue with `int64_t` and `uint64_t`. +- [abc100m](https://github.com/abc100m) analyzed the issues with GCC 4.8 and proposed a [partial solution](https://github.com/nlohmann/json/pull/212). +- [zewt](https://github.com/zewt) added useful notes to the README file about Android. +- [Róbert Márki](https://github.com/robertmrk) added a fix to use move iterators and improved the integration via CMake. +- [Chris Kitching](https://github.com/ChrisKitching) cleaned up the CMake files. +- [Tom Needham](https://github.com/06needhamt) fixed a subtle bug with MSVC 2015 which was also proposed by [Michael K.](https://github.com/Epidal). +- [Mário Feroldi](https://github.com/thelostt) fixed a small typo. +- [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release. +- [Damien](https://github.com/dtoma) fixed one of the last conversion warnings. +- [Thomas Braun](https://github.com/t-b) fixed a warning in a test case and adjusted MSVC calls in the CI. +- [Théo DELRIEU](https://github.com/theodelrieu) patiently and constructively oversaw the long way toward [iterator-range parsing](https://github.com/nlohmann/json/issues/290). He also implemented the magic behind the serialization/deserialization of user-defined types and split the single header file into smaller chunks. +- [Stefan](https://github.com/5tefan) fixed a minor issue in the documentation. +- [Vasil Dimov](https://github.com/vasild) fixed the documentation regarding conversions from `std::multiset`. +- [ChristophJud](https://github.com/ChristophJud) overworked the CMake files to ease project inclusion. +- [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable and added Visual Studio 17 to the build matrix. +- [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file. +- [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function. +- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](https://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser, improved the benchmarking code, and realized locale-independent number parsing and printing. +- [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan. +- [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning. +- [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check. +- [Bosswestfalen](https://github.com/Bosswestfalen) merged two iterator classes into a smaller one. +- [Daniel599](https://github.com/Daniel599) helped to get Travis execute the tests with Clang's sanitizers. +- [Jonathan Lee](https://github.com/vjon) fixed an example in the README file. +- [gnzlbg](https://github.com/gnzlbg) supported the implementation of user-defined types. +- [Alexej Harm](https://github.com/qis) helped to get the user-defined types working with Visual Studio. +- [Jared Grubb](https://github.com/jaredgrubb) supported the implementation of user-defined types. +- [EnricoBilla](https://github.com/EnricoBilla) noted a typo in an example. +- [Martin HoÅ™eňovský](https://github.com/horenmar) found a way for a 2x speedup for the compilation time of the test suite. +- [ukhegg](https://github.com/ukhegg) found proposed an improvement for the examples section. +- [rswanson-ihi](https://github.com/rswanson-ihi) noted a typo in the README. +- [Mihai Stan](https://github.com/stanmihai4) fixed a bug in the comparison with `nullptr`s. +- [Tushar Maheshwari](https://github.com/tusharpm) added [cotire](https://github.com/sakra/cotire) support to speed up the compilation. +- [TedLyngmo](https://github.com/TedLyngmo) noted a typo in the README, removed unnecessary bit arithmetic, and fixed some `-Weffc++` warnings. +- [Krzysztof WoÅ›](https://github.com/krzysztofwos) made exceptions more visible. +- [ftillier](https://github.com/ftillier) fixed a compiler warning. +- [tinloaf](https://github.com/tinloaf) made sure all pushed warnings are properly popped. +- [Fytch](https://github.com/Fytch) found a bug in the documentation. +- [Jay Sistar](https://github.com/Type1J) implemented a Meson build description. +- [Henry Lee](https://github.com/HenryRLee) fixed a warning in ICC and improved the iterator implementation. +- [Vincent Thiery](https://github.com/vthiery) maintains a package for the Conan package manager. +- [Steffen](https://github.com/koemeet) fixed a potential issue with MSVC and `std::min`. +- [Mike Tzou](https://github.com/Chocobo1) fixed some typos. +- [amrcode](https://github.com/amrcode) noted a misleading documentation about comparison of floats. +- [Oleg Endo](https://github.com/olegendo) reduced the memory consumption by replacing `` with ``. +- [dan-42](https://github.com/dan-42) cleaned up the CMake files to simplify including/reusing of the library. +- [Nikita Ofitserov](https://github.com/himikof) allowed for moving values from initializer lists. +- [Greg Hurrell](https://github.com/wincent) fixed a typo. +- [Dmitry Kukovinets](https://github.com/DmitryKuk) fixed a typo. +- [kbthomp1](https://github.com/kbthomp1) fixed an issue related to the Intel OSX compiler. +- [Markus Werle](https://github.com/daixtrose) fixed a typo. +- [WebProdPP](https://github.com/WebProdPP) fixed a subtle error in a precondition check. +- [Alex](https://github.com/leha-bot) noted an error in a code sample. +- [Tom de Geus](https://github.com/tdegeus) reported some warnings with ICC and helped fixing them. +- [Perry Kundert](https://github.com/pjkundert) simplified reading from input streams. +- [Sonu Lohani](https://github.com/sonulohani) fixed a small compilation error. +- [Jamie Seward](https://github.com/jseward) fixed all MSVC warnings. +- [Nate Vargas](https://github.com/eld00d) added a Doxygen tag file. +- [pvleuven](https://github.com/pvleuven) helped fixing a warning in ICC. +- [Pavel](https://github.com/crea7or) helped fixing some warnings in MSVC. +- [Jamie Seward](https://github.com/jseward) avoided unnecessary string copies in `find()` and `count()`. +- [Mitja](https://github.com/Itja) fixed some typos. +- [Jorrit Wronski](https://github.com/jowr) updated the Hunter package links. +- [Matthias Möller](https://github.com/TinyTinni) added a `.natvis` for the MSVC debug view. +- [bogemic](https://github.com/bogemic) fixed some C++17 deprecation warnings. +- [Eren Okka](https://github.com/erengy) fixed some MSVC warnings. +- [abolz](https://github.com/abolz) integrated the Grisu2 algorithm for proper floating-point formatting, allowing more roundtrip checks to succeed. +- [Vadim Evard](https://github.com/Pipeliner) fixed a Markdown issue in the README. +- [zerodefect](https://github.com/zerodefect) fixed a compiler warning. +- [Kert](https://github.com/kaidokert) allowed to template the string type in the serialization and added the possibility to override the exceptional behavior. +- [mark-99](https://github.com/mark-99) helped fixing an ICC error. +- [Patrik Huber](https://github.com/patrikhuber) fixed links in the README file. +- [johnfb](https://github.com/johnfb) found a bug in the implementation of CBOR's indefinite length strings. +- [Paul Fultz II](https://github.com/pfultz2) added a note on the cget package manager. +- [Wilson Lin](https://github.com/wla80) made the integration section of the README more concise. +- [RalfBielig](https://github.com/ralfbielig) detected and fixed a memory leak in the parser callback. +- [agrianius](https://github.com/agrianius) allowed to dump JSON to an alternative string type. +- [Kevin Tonon](https://github.com/ktonon) overworked the C++11 compiler checks in CMake. +- [Axel Huebl](https://github.com/ax3l) simplified a CMake check and added support for the [Spack package manager](https://spack.io). +- [Carlos O'Ryan](https://github.com/coryan) fixed a typo. +- [James Upjohn](https://github.com/jammehcow) fixed a version number in the compilers section. +- [Chuck Atkins](https://github.com/chuckatkins) adjusted the CMake files to the CMake packaging guidelines and provided documentation for the CMake integration. +- [Jan Schöppach](https://github.com/dns13) fixed a typo. +- [martin-mfg](https://github.com/martin-mfg) fixed a typo. +- [Matthias Möller](https://github.com/TinyTinni) removed the dependency from `std::stringstream`. +- [agrianius](https://github.com/agrianius) added code to use alternative string implementations. +- [Daniel599](https://github.com/Daniel599) allowed to use more algorithms with the `items()` function. +- [Julius Rakow](https://github.com/jrakow) fixed the Meson include directory and fixed the links to [cppreference.com](cppreference.com). +- [Sonu Lohani](https://github.com/sonulohani) fixed the compilation with MSVC 2015 in debug mode. +- [grembo](https://github.com/grembo) fixed the test suite and re-enabled several test cases. +- [Hyeon Kim](https://github.com/simnalamburt) introduced the macro `JSON_INTERNAL_CATCH` to control the exception handling inside the library. +- [thyu](https://github.com/thyu) fixed a compiler warning. +- [David Guthrie](https://github.com/LEgregius) fixed a subtle compilation error with Clang 3.4.2. +- [Dennis Fischer](https://github.com/dennisfischer) allowed to call `find_package` without installing the library. +- [Hyeon Kim](https://github.com/simnalamburt) fixed an issue with a double macro definition. +- [Ben Berman](https://github.com/rivertam) made some error messages more understandable. +- [zakalibit](https://github.com/zakalibit) fixed a compilation problem with the Intel C++ compiler. +- [mandreyel](https://github.com/mandreyel) fixed a compilation problem. +- [Kostiantyn Ponomarenko](https://github.com/koponomarenko) added version and license information to the Meson build file. +- [Henry Schreiner](https://github.com/henryiii) added support for GCC 4.8. +- [knilch](https://github.com/knilch0r) made sure the test suite does not stall when run in the wrong directory. +- [Antonio Borondo](https://github.com/antonioborondo) fixed an MSVC 2017 warning. +- [Dan Gendreau](https://github.com/dgendreau) implemented the `NLOHMANN_JSON_SERIALIZE_ENUM` macro to quickly define a enum/JSON mapping. +- [efp](https://github.com/efp) added line and column information to parse errors. +- [julian-becker](https://github.com/julian-becker) added BSON support. +- [Pratik Chowdhury](https://github.com/pratikpc) added support for structured bindings. +- [David Avedissian](https://github.com/davedissian) added support for Clang 5.0.1 (PS4 version). +- [Jonathan Dumaresq](https://github.com/dumarjo) implemented an input adapter to read from `FILE*`. +- [kjpus](https://github.com/kjpus) fixed a link in the documentation. +- [Manvendra Singh](https://github.com/manu-chroma) fixed a typo in the documentation. +- [ziggurat29](https://github.com/ziggurat29) fixed an MSVC warning. +- [Sylvain Corlay](https://github.com/SylvainCorlay) added code to avoid an issue with MSVC. +- [mefyl](https://github.com/mefyl) fixed a bug when JSON was parsed from an input stream. +- [Millian Poquet](https://github.com/mpoquet) allowed to install the library via Meson. +- [Michael Behrns-Miller](https://github.com/moodboom) found an issue with a missing namespace. +- [Nasztanovics Ferenc](https://github.com/naszta) fixed a compilation issue with libc 2.12. +- [Andreas Schwab](https://github.com/andreas-schwab) fixed the endian conversion. +- [Mark-Dunning](https://github.com/Mark-Dunning) fixed a warning in MSVC. +- [Gareth Sylvester-Bradley](https://github.com/garethsb-sony) added `operator/` for JSON Pointers. +- [John-Mark](https://github.com/johnmarkwayve) noted a missing header. +- [Vitaly Zaitsev](https://github.com/xvitaly) fixed compilation with GCC 9.0. +- [Laurent Stacul](https://github.com/stac47) fixed compilation with GCC 9.0. +- [Ivor Wanders](https://github.com/iwanders) helped reducing the CMake requirement to version 3.1. +- [njlr](https://github.com/njlr) updated the Buckaroo instructions. +- [Lion](https://github.com/lieff) fixed a compilation issue with GCC 7 on CentOS. +- [Isaac Nickaein](https://github.com/nickaein) improved the integer serialization performance and implemented the `contains()` function. +- [past-due](https://github.com/past-due) suppressed an unfixable warning. +- [Elvis Oric](https://github.com/elvisoric) improved Meson support. +- [MatÄ›j Plch](https://github.com/Afforix) fixed an example in the README. +- [Mark Beckwith](https://github.com/wythe) fixed a typo. +- [scinart](https://github.com/scinart) fixed bug in the serializer. +- [Patrick Boettcher](https://github.com/pboettch) implemented `push_back()` and `pop_back()` for JSON Pointers. +- [Bruno Oliveira](https://github.com/nicoddemus) added support for Conda. +- [Michele Caini](https://github.com/skypjack) fixed links in the README. +- [Hani](https://github.com/hnkb) documented how to install the library with NuGet. +- [Mark Beckwith](https://github.com/wythe) fixed a typo. +- [yann-morin-1998](https://github.com/yann-morin-1998) helped reducing the CMake requirement to version 3.1. +- [Konstantin Podsvirov](https://github.com/podsvirov) maintains a package for the MSYS2 software distro. +- [remyabel](https://github.com/remyabel) added GNUInstallDirs to the CMake files. +- [Taylor Howard](https://github.com/taylorhoward92) fixed a unit test. +- [Gabe Ron](https://github.com/Macr0Nerd) implemented the `to_string` method. +- [Watal M. Iwasaki](https://github.com/heavywatal) fixed a Clang warning. +- [Viktor Kirilov](https://github.com/onqtam) switched the unit tests from [Catch](https://github.com/philsquared/Catch) to [doctest](https://github.com/onqtam/doctest) +- [Juncheng E](https://github.com/ejcjason) fixed a typo. +- [tete17](https://github.com/tete17) fixed a bug in the `contains` function. +- [Xav83](https://github.com/Xav83) fixed some cppcheck warnings. +- [0xflotus](https://github.com/0xflotus) fixed some typos. +- [Christian Deneke](https://github.com/chris0x44) added a const version of `json_pointer::back`. +- [Julien Hamaide](https://github.com/crazyjul) made the `items()` function work with custom string types. +- [Evan Nemerson](https://github.com/nemequ) updated fixed a bug in Hedley and updated this library accordingly. +- [Florian Pigorsch](https://github.com/flopp) fixed a lot of typos. +- [Camille Bégué](https://github.com/cbegue) fixed an issue in the conversion from `std::pair` and `std::tuple` to `json`. +- [Anthony VH](https://github.com/AnthonyVH) fixed a compile error in an enum deserialization. +- [Yuriy Vountesmery](https://github.com/ua-code-dragon) noted a subtle bug in a preprocessor check. +- [Chen](https://github.com/dota17) fixed numerous issues in the library. +- [Antony Kellermann](https://github.com/aokellermann) added a CI step for GCC 10.1. +- [Alex](https://github.com/gistrec) fixed an MSVC warning. +- [Rainer](https://github.com/rvjr) proposed an improvement in the floating-point serialization in CBOR. +- [Francois Chabot](https://github.com/FrancoisChabot) made performance improvements in the input adapters. +- [Arthur Sonzogni](https://github.com/ArthurSonzogni) documented how the library can be included via `FetchContent`. +- [Rimas MiseviÄius](https://github.com/rmisev) fixed an error message. +- [Alexander Myasnikov](https://github.com/alexandermyasnikov) fixed some examples and a link in the README. +- [Hubert Chathi](https://github.com/uhoreg) made CMake's version config file architecture-independent. +- [OmnipotentEntity](https://github.com/OmnipotentEntity) implemented the binary values for CBOR, MessagePack, BSON, and UBJSON. +- [ArtemSarmini](https://github.com/ArtemSarmini) fixed a compilation issue with GCC 10 and fixed a leak. +- [Evgenii Sopov](https://github.com/sea-kg) integrated the library to the wsjcpp package manager. +- [Sergey Linev](https://github.com/linev) fixed a compiler warning. +- [Miguel Magalhães](https://github.com/magamig) fixed the year in the copyright. +- [Gareth Sylvester-Bradley](https://github.com/garethsb-sony) fixed a compilation issue with MSVC. +- [Alexander “weej†Jones](https://github.com/alex-weej) fixed an example in the README. +- [Antoine CÅ“ur](https://github.com/Coeur) fixed some typos in the documentation. +- [jothepro](https://github.com/jothepro) updated links to the Hunter package. +- [Dave Lee](https://github.com/kastiglione) fixed link in the README. +- [Joël Lamotte](https://github.com/Klaim) added instruction for using Build2's package manager. +- [Paul Jurczak](https://github.com/pauljurczak) fixed an example in the README. +- [Sonu Lohani](https://github.com/sonulohani) fixed a warning. +- [Carlos Gomes Martinho](https://github.com/gocarlos) updated the Conan package source. +- [Konstantin Podsvirov](https://github.com/podsvirov) fixed the MSYS2 package documentation. +- [Tridacnid](https://github.com/Tridacnid) improved the CMake tests. +- [Michael](https://github.com/MBalszun) fixed MSVC warnings. +- [Quentin Barbarat](https://github.com/quentin-dev) fixed an example in the documentation. +- [XyFreak](https://github.com/XyFreak) fixed a compiler warning. +- [TotalCaesar659](https://github.com/TotalCaesar659) fixed links in the README. +- [Tanuj Garg](https://github.com/tanuj208) improved the fuzzer coverage for UBSAN input. +- [AODQ](https://github.com/AODQ) fixed a compiler warning. +- [jwittbrodt](https://github.com/jwittbrodt) made `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` inline. +- [pfeatherstone](https://github.com/pfeatherstone) improved the upper bound of arguments of the `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`/`NLOHMANN_DEFINE_TYPE_INTRUSIVE` macros. +- [Jan Procházka](https://github.com/jprochazk) fixed a bug in the CBOR parser for binary and string values. +- [T0b1-iOS](https://github.com/T0b1-iOS) fixed a bug in the new hash implementation. +- [Matthew Bauer](https://github.com/matthewbauer) adjusted the CBOR writer to create tags for binary subtypes. +- [gatopeich](https://github.com/gatopeich) implemented an ordered map container for `nlohmann::ordered_json`. +- [Érico Nogueira Rolim](https://github.com/ericonr) added support for pkg-config. +- [KonanM](https://github.com/KonanM) proposed an implementation for the `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`/`NLOHMANN_DEFINE_TYPE_INTRUSIVE` macros. +- [Guillaume Racicot](https://github.com/gracicot) implemented `string_view` support and allowed C++20 support. +- [Alex Reinking](https://github.com/alexreinking) improved CMake support for `FetchContent`. +- [Hannes Domani](https://github.com/ssbssa) provided a GDB pretty printer. +- Lars Wirzenius reviewed the README file. +- [Jun Jie](https://github.com/ongjunjie) fixed a compiler path in the CMake scripts. +- [Ronak Buch](https://github.com/rbuch) fixed typos in the documentation. +- [Alexander Karzhenkov](https://github.com/karzhenkov) fixed a move constructor and the Travis builds. +- [Leonardo Lima](https://github.com/leozz37) added CPM.Cmake support. +- [Joseph Blackman](https://github.com/jbzdarkid) fixed a warning. +- [Yaroslav](https://github.com/YarikTH) updated doctest and implemented unit tests. +- [Martin Stump](https://github.com/globberwops) fixed a bug in the CMake files. +- [Jaakko Moisio](https://github.com/jasujm) fixed a bug in the input adapters. +- [bl-ue](https://github.com/bl-ue) fixed some Markdown issues in the README file. +- [William A. Wieselquist](https://github.com/wawiesel) fixed an example from the README. +- [abbaswasim](https://github.com/abbaswasim) fixed an example from the README. +- [Remy Jette](https://github.com/remyjette) fixed a warning. +- [Fraser](https://github.com/frasermarlow) fixed the documentation. +- [Ben Beasley](https://github.com/musicinmybrain) updated doctest. +- [Doron Behar](https://github.com/doronbehar) fixed pkg-config.pc. +- [raduteo](https://github.com/raduteo) fixed a warning. +- [David Pfahler](https://github.com/theShmoo) added the possibility to compile the library without I/O support. +- [Morten Fyhn Amundsen](https://github.com/mortenfyhn) fixed a typo. +- [jpl-mac](https://github.com/jpl-mac) allowed to treat the library as a system header in CMake. +- [Jason Dsouza](https://github.com/jasmcaus) fixed the indentation of the CMake file. +- [offa](https://github.com/offa) added a link to Conan Center to the documentation. +- [TotalCaesar659](https://github.com/TotalCaesar659) updated the links in the documentation to use HTTPS. +- [Rafail Giavrimis](https://github.com/grafail) fixed the Google Benchmark default branch. +- [Louis Dionne](https://github.com/ldionne) fixed a conversion operator. +- [justanotheranonymoususer](https://github.com/justanotheranonymoususer) made the examples in the README more consistent. +- [Finkman](https://github.com/Finkman) suppressed some `-Wfloat-equal` warnings. +- [Ferry Huberts](https://github.com/fhuberts) fixed `-Wswitch-enum` warnings. +- [Arseniy Terekhin](https://github.com/senyai) made the GDB pretty-printer robust against unset variable names. +- [Amir Masoud Abdol](https://github.com/amirmasoudabdol) updated the Homebrew command as nlohmann/json is now in homebrew-core. +- [Hallot](https://github.com/Hallot) fixed some `-Wextra-semi-stmt warnings`. +- [Giovanni Cerretani](https://github.com/gcerretani) fixed `-Wunused` warnings on `JSON_DIAGNOSTICS`. +- [Bogdan Popescu](https://github.com/Kapeli) hosts the [docset](https://github.com/Kapeli/Dash-User-Contributions/tree/master/docsets/JSON_for_Modern_C%2B%2B) for offline documentation viewers. +- [Carl Smedstad](https://github.com/carlsmedstad) fixed an assertion error when using `JSON_DIAGNOSTICS`. + +Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. + + +## Used third-party tools + +The library itself consists of a single header file licensed under the MIT license. However, it is built, tested, documented, and whatnot using a lot of third-party tools and services. Thanks a lot! + +- [**amalgamate.py - Amalgamate C source and header files**](https://github.com/edlund/amalgamate) to create a single header file +- [**American fuzzy lop**](https://lcamtuf.coredump.cx/afl/) for fuzz testing +- [**AppVeyor**](https://www.appveyor.com) for [continuous integration](https://ci.appveyor.com/project/nlohmann/json) on Windows +- [**Artistic Style**](http://astyle.sourceforge.net) for automatic source code indentation +- [**Clang**](https://clang.llvm.org) for compilation with code sanitizers +- [**CMake**](https://cmake.org) for build automation +- [**Codacity**](https://www.codacy.com) for further [code analysis](https://www.codacy.com/app/nlohmann/json) +- [**Coveralls**](https://coveralls.io) to measure [code coverage](https://coveralls.io/github/nlohmann/json) +- [**Coverity Scan**](https://scan.coverity.com) for [static analysis](https://scan.coverity.com/projects/nlohmann-json) +- [**cppcheck**](http://cppcheck.sourceforge.net) for static analysis +- [**doctest**](https://github.com/onqtam/doctest) for the unit tests +- [**Doxygen**](https://www.doxygen.nl/index.html) to generate [documentation](https://nlohmann.github.io/json/doxygen/index.html) +- [**git-update-ghpages**](https://github.com/rstacruz/git-update-ghpages) to upload the documentation to gh-pages +- [**GitHub Changelog Generator**](https://github.com/skywinder/github-changelog-generator) to generate the [ChangeLog](https://github.com/nlohmann/json/blob/develop/ChangeLog.md) +- [**Google Benchmark**](https://github.com/google/benchmark) to implement the benchmarks +- [**Hedley**](https://nemequ.github.io/hedley/) to avoid re-inventing several compiler-agnostic feature macros +- [**lcov**](http://ltp.sourceforge.net/coverage/lcov.php) to process coverage information and create a HTML view +- [**libFuzzer**](https://llvm.org/docs/LibFuzzer.html) to implement fuzz testing for OSS-Fuzz +- [**OSS-Fuzz**](https://github.com/google/oss-fuzz) for continuous fuzz testing of the library ([project repository](https://github.com/google/oss-fuzz/tree/master/projects/json)) +- [**Probot**](https://probot.github.io) for automating maintainer tasks such as closing stale issues, requesting missing information, or detecting toxic comments. +- [**send_to_wandbox**](https://github.com/nlohmann/json/blob/develop/doc/scripts/send_to_wandbox.py) to send code examples to [Wandbox](https://wandbox.org) +- [**Travis**](https://travis-ci.org) for [continuous integration](https://travis-ci.org/nlohmann/json) on Linux and macOS +- [**Valgrind**](https://valgrind.org) to check for correct memory management +- [**Wandbox**](https://wandbox.org) for [online examples](https://wandbox.org/permlink/1mp10JbaANo6FUc7) + + +## Projects using JSON for Modern C++ + +The library is currently used in Apple macOS Sierra and iOS 10. I am not sure what they are using the library for, but I am happy that it runs on so many devices. + + +## Notes + +### Character encoding + +The library supports **Unicode input** as follows: + +- Only **UTF-8** encoded input is supported which is the default encoding for JSON according to [RFC 8259](https://tools.ietf.org/html/rfc8259.html#section-8.1). +- `std::u16string` and `std::u32string` can be parsed, assuming UTF-16 and UTF-32 encoding, respectively. These encodings are not supported when reading from files or other input containers. +- Other encodings such as Latin-1 or ISO 8859-1 are **not** supported and will yield parse or serialization errors. +- [Unicode noncharacters](https://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library. +- Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors. +- The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs. +- When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers. +- To store wide strings (e.g., `std::wstring`), you need to convert them to a a UTF-8 encoded `std::string` before, see [an example](https://json.nlohmann.me/home/faq/#wide-string-handling). + +### Comments in JSON + +This library does not support comments by default. It does so for three reasons: + +1. Comments are not part of the [JSON specification](https://tools.ietf.org/html/rfc8259). You may argue that `//` or `/* */` are allowed in JavaScript, but JSON is not JavaScript. +2. This was not an oversight: Douglas Crockford [wrote on this](https://plus.google.com/118095276221607585885/posts/RK8qyGVaGSr) in May 2012: + + > I removed comments from JSON because I saw people were using them to hold parsing directives, a practice which would have destroyed interoperability. I know that the lack of comments makes some people sad, but it shouldn't. + + > Suppose you are using JSON to keep configuration files, which you would like to annotate. Go ahead and insert all the comments you like. Then pipe it through JSMin before handing it to your JSON parser. + +3. It is dangerous for interoperability if some libraries would add comment support while others don't. Please check [The Harmful Consequences of the Robustness Principle](https://tools.ietf.org/html/draft-iab-protocol-maintenance-01) on this. + +However, you can pass set parameter `ignore_comments` to true in the `parse` function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace. + +### Order of object keys + +By default, the library does not preserve the **insertion order of object elements**. This is standards-compliant, as the [JSON standard](https://tools.ietf.org/html/rfc8259.html) defines objects as "an unordered collection of zero or more name/value pairs". + +If you do want to preserve the insertion order, you can try the type [`nlohmann::ordered_json`](https://github.com/nlohmann/json/issues/2179). Alternatively, you can use a more sophisticated ordered map like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) ([integration](https://github.com/nlohmann/json/issues/546#issuecomment-304447518)) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)). + +### Memory Release + +We checked with Valgrind and the Address Sanitizer (ASAN) that there are no memory leaks. + +If you find that a parsing program with this library does not release memory, please consider the following case and it maybe unrelated to this library. + +**Your program is compiled with glibc.** There is a tunable threshold that glibc uses to decide whether to actually return memory to the system or whether to cache it for later reuse. If in your program you make lots of small allocations and those small allocations are not a contiguous block and are presumably below the threshold, then they will not get returned to the OS. +Here is a related issue [#1924](https://github.com/nlohmann/json/issues/1924). + +### Further notes + +- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/api/basic_json/operator%5B%5D/) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/api/basic_json/at/). Furthermore, you can define `JSON_ASSERT(x)` to replace calls to `assert(x)`. +- As the exact type of a number is not defined in the [JSON specification](https://tools.ietf.org/html/rfc8259.html), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions. +- The code can be compiled without C++ **runtime type identification** features; that is, you can use the `-fno-rtti` compiler flag. +- **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `throw`), `JSON_TRY_USER` (overriding `try`), and `JSON_CATCH_USER` (overriding `catch`). Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior. Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824). + +## Execute unit tests + +To compile and run the tests, you need to execute + +```sh +$ mkdir build +$ cd build +$ cmake .. -DJSON_BuildTests=On +$ cmake --build . +$ ctest --output-on-failure +``` + +Note that during the `ctest` stage, several JSON test files are downloaded from an [external repository](https://github.com/nlohmann/json_test_data). If policies forbid downloading artifacts during testing, you can download the files yourself and pass the directory with the test files via `-DJSON_TestDataDirectory=path` to CMake. Then, no Internet connectivity is required. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information. + +In case you have downloaded the library rather than checked out the code via Git, test `cmake_fetch_content_configure` will fail. Please execute `ctest -LE git_required` to skip these tests. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information. + +Some tests change the installed files and hence make the whole process not reproducible. Please execute `ctest -LE not_reproducible` to skip these tests. See [issue #2324](https://github.com/nlohmann/json/issues/2324) for more information. + +Note you need to call `cmake -LE "not_reproducible|git_required"` to exclude both labels. See [issue #2596](https://github.com/nlohmann/json/issues/2596) for more information. + +As Intel compilers use unsafe floating point optimization by default, the unit tests may fail. Use flag [`/fp:precise`](https://software.intel.com/content/www/us/en/develop/documentation/cpp-compiler-developer-guide-and-reference/top/compiler-reference/compiler-options/compiler-option-details/floating-point-options/fp-model-fp.html) then. diff --git a/libs/json/json.hpp b/libs/json/json.hpp new file mode 100644 index 000000000..87475ab31 --- /dev/null +++ b/libs/json/json.hpp @@ -0,0 +1,26753 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 3.10.4 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +Licensed under the MIT License . +SPDX-License-Identifier: MIT +Copyright (c) 2013-2019 Niels Lohmann . + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#define NLOHMANN_JSON_VERSION_MAJOR 3 +#define NLOHMANN_JSON_VERSION_MINOR 10 +#define NLOHMANN_JSON_VERSION_PATCH 4 + +#include // all_of, find, for_each +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO +#include // random_access_iterator_tag +#include // unique_ptr +#include // accumulate +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include + + +#include +#include + +// #include + + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include + + +#include // exception +#include // runtime_error +#include // to_string +#include // vector + +// #include + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +namespace nlohmann +{ +namespace detail +{ +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 +*/ +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +} +} // namespace detail +} // namespace nlohmann + +// #include + + +#include +// #include + + +#include // declval, pair +// #include + + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to + * the public domain worldwide. This software is distributed without + * any warranty. + * + * For details, see . + * SPDX-License-Identifier: CC0-1.0 + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif +#else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + +// #include + + +#include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; +} // namespace detail +} // namespace nlohmann + + +// https://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ +namespace detail +{ +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; +} // namespace detail +} // namespace nlohmann + + +// This file contains all internal macro definitions +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow to disable exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// allow to override assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer, \ + class BinaryType> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + + +// inspired from https://stackoverflow.com/a/26745591 +// allows to call any std function as if (e.g. with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + + +namespace nlohmann +{ +namespace detail +{ + +/*! +@brief replace all occurrences of a substring by another string + +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f + +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** + +@since version 2.0.0 +*/ +inline void replace_substring(std::string& s, const std::string& f, + const std::string& t) +{ + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != std::string::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} +} + +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +inline std::string escape(std::string s) +{ + replace_substring(s, "~", "~0"); + replace_substring(s, "/", "~1"); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +static void unescape(std::string& s) +{ + replace_substring(s, "~1", "/"); + replace_substring(s, "~0", "~"); +} + +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // size_t + +namespace nlohmann +{ +namespace detail +{ +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +} // namespace nlohmann + +// #include + + +namespace nlohmann +{ +namespace detail +{ +//////////////// +// exceptions // +//////////////// + +/*! +@brief general exception of the @ref basic_json class + +This class is an extension of `std::exception` objects with a member @a id for +exception ids. It is used as the base class for all exceptions thrown by the +@ref basic_json class. This class can hence be used as "wildcard" to catch +exceptions. + +Subclasses: +- @ref parse_error for exceptions indicating a parse error +- @ref invalid_iterator for exceptions indicating errors with iterators +- @ref type_error for exceptions indicating executing a member function with + a wrong type +- @ref out_of_range for exceptions indicating access out of the defined range +- @ref other_error for exceptions indicating other library errors + +@internal +@note To have nothrow-copy-constructible exceptions, we internally use + `std::runtime_error` which can cope with arbitrary-length error messages. + Intermediate strings are built with static functions and then passed to + the actual constructor. +@endinternal + +@liveexample{The following code shows how arbitrary library exceptions can be +caught.,exception} + +@since version 3.0.0 +*/ +class exception : public std::exception +{ + public: + /// returns the explanatory string + const char* what() const noexcept override + { + return m.what(); + } + + /// the id of the exception + const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) + + protected: + JSON_HEDLEY_NON_NULL(3) + exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} + + static std::string name(const std::string& ename, int id_) + { + return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + } + + template + static std::string diagnostics(const BasicJsonType& leaf_element) + { +#if JSON_DIAGNOSTICS + std::vector tokens; + for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent) + { + switch (current->m_parent->type()) + { + case value_t::array: + { + for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) + { + if (¤t->m_parent->m_value.array->operator[](i) == current) + { + tokens.emplace_back(std::to_string(i)); + break; + } + } + break; + } + + case value_t::object: + { + for (const auto& element : *current->m_parent->m_value.object) + { + if (&element.second == current) + { + tokens.emplace_back(element.first.c_str()); + break; + } + } + break; + } + + case value_t::null: // LCOV_EXCL_LINE + case value_t::string: // LCOV_EXCL_LINE + case value_t::boolean: // LCOV_EXCL_LINE + case value_t::number_integer: // LCOV_EXCL_LINE + case value_t::number_unsigned: // LCOV_EXCL_LINE + case value_t::number_float: // LCOV_EXCL_LINE + case value_t::binary: // LCOV_EXCL_LINE + case value_t::discarded: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + break; // LCOV_EXCL_LINE + } + } + + if (tokens.empty()) + { + return ""; + } + + return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, + [](const std::string & a, const std::string & b) + { + return a + "/" + detail::escape(b); + }) + ") "; +#else + static_cast(leaf_element); + return ""; +#endif + } + + private: + /// an exception object as storage for error messages + std::runtime_error m; +}; + +/*! +@brief exception indicating a parse error + +This exception is thrown by the library when a parse error occurs. Parse errors +can occur during the deserialization of JSON text, CBOR, MessagePack, as well +as when using JSON Patch. + +Member @a byte holds the byte index of the last read character in the input +file. + +Exceptions have ids 1xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. +json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. +json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. +json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. +json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. +json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. +json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. +json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. +json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. +json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. +json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. +json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. +json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). +json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed. + +@note For an input with n bytes, 1 is the index of the first character and n+1 + is the index of the terminating null byte or the end of file. This also + holds true when reading a byte vector (CBOR or MessagePack). + +@liveexample{The following code shows how a `parse_error` exception can be +caught.,parse_error} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class parse_error : public exception +{ + public: + /*! + @brief create a parse error exception + @param[in] id_ the id of the exception + @param[in] pos the position where the error occurred (or with + chars_read_total=0 if the position cannot be + determined) + @param[in] what_arg the explanatory string + @return parse_error object + */ + template + static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + exception::diagnostics(context) + what_arg; + return parse_error(id_, pos.chars_read_total, w.c_str()); + } + + template + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + + ": " + exception::diagnostics(context) + what_arg; + return parse_error(id_, byte_, w.c_str()); + } + + /*! + @brief byte index of the parse error + + The byte index of the last read character in the input file. + + @note For an input with n bytes, 1 is the index of the first character and + n+1 is the index of the terminating null byte or the end of file. + This also holds true when reading a byte vector (CBOR or MessagePack). + */ + const std::size_t byte; + + private: + parse_error(int id_, std::size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) {} + + static std::string position_string(const position_t& pos) + { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } +}; + +/*! +@brief exception indicating errors with iterators + +This exception is thrown if iterators passed to a library function do not match +the expected semantics. + +Exceptions have ids 2xx. + +name / id | example message | description +----------------------------------- | --------------- | ------------------------- +json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. +json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. +json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. +json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. +json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. +json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. +json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. +json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. +json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. +json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). + +@liveexample{The following code shows how an `invalid_iterator` exception can be +caught.,invalid_iterator} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class invalid_iterator : public exception +{ + public: + template + static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg; + return invalid_iterator(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + invalid_iterator(int id_, const char* what_arg) + : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating executing a member function with a wrong type + +This exception is thrown in case of a type error; that is, a library function is +executed on a JSON value whose type does not match the expected semantics. + +Exceptions have ids 3xx. + +name / id | example message | description +----------------------------- | --------------- | ------------------------- +json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. +json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. +json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. +json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. +json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. +json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. +json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. +json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. +json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. +json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. +json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. +json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. +json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. +json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. +json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. +json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | +json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | + +@liveexample{The following code shows how a `type_error` exception can be +caught.,type_error} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class type_error : public exception +{ + public: + template + static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg; + return type_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating access out of the defined range + +This exception is thrown in case a library function is called on an input +parameter that exceeds the expected range, for instance in case of array +indices or nonexisting object keys. + +Exceptions have ids 4xx. + +name / id | example message | description +------------------------------- | --------------- | ------------------------- +json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. +json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. +json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. +json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. +json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. +json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. +json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) | +json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | +json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | + +@liveexample{The following code shows how an `out_of_range` exception can be +caught.,out_of_range} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class out_of_range : public exception +{ + public: + template + static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg; + return out_of_range(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating other library errors + +This exception is thrown in case of errors that cannot be classified with the +other exception types. + +Exceptions have ids 5xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range + +@liveexample{The following code shows how an `other_error` exception can be +caught.,other_error} + +@since version 3.0.0 +*/ +class other_error : public exception +{ + public: + template + static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context) + { + std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg; + return other_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +namespace nlohmann +{ +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static constexpr T value{}; +}; + +template +constexpr T static_const::value; + +} // namespace detail +} // namespace nlohmann + +// #include + + +namespace nlohmann +{ +namespace detail +{ +// dispatching helper struct +template struct identity_tag {}; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#include // tuple + +// #include + + +// #include + + +#include // random_access_iterator_tag + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; +} // namespace detail +} // namespace nlohmann + +// #include + + +// #include + + +namespace nlohmann +{ +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); +} // namespace nlohmann + +// #include + + +// #include + + +namespace nlohmann +{ +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); +} // namespace nlohmann + +// #include + +// #include + +// #include +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ +#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + +#include // int64_t, uint64_t +#include // map +#include // allocator +#include // string +#include // vector + +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +namespace nlohmann +{ +/*! +@brief default JSONSerializer template argument + +This serializer ignores the template arguments and uses ADL +([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) +for serialization. +*/ +template +struct adl_serializer; + +template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector> +class basic_json; + +/*! +@brief JSON Pointer + +A JSON pointer defines a string syntax for identifying a specific value +within a JSON document. It can be used with functions `at` and +`operator[]`. Furthermore, JSON pointers are the base for JSON patches. + +@sa [RFC 6901](https://tools.ietf.org/html/rfc6901) + +@since version 2.0.0 +*/ +template +class json_pointer; + +/*! +@brief default JSON class + +This type is the default specialization of the @ref basic_json class which +uses the standard template types. + +@since version 1.0.0 +*/ +using json = basic_json<>; + +template +struct ordered_map; + +/*! +@brief ordered JSON class + +This type preserves the insertion order of object keys. + +@since version 3.9.0 +*/ +using ordered_json = basic_json; + +} // namespace nlohmann + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + +namespace nlohmann +{ +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ +///////////// +// helpers // +///////////// + +// Note to maintainers: +// +// Every trait in this file expects a non CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e. those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g. to_json(BasicJsonType&, const T&)) + +template struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; + +////////////////////// +// json_ref helpers // +////////////////////// + +template +class json_ref; + +template +struct is_json_ref : std::false_type {}; + +template +struct is_json_ref> : std::true_type {}; + +////////////////////////// +// aliases for detected // +////////////////////////// + +template +using mapped_type_t = typename T::mapped_type; + +template +using key_type_t = typename T::key_type; + +template +using value_type_t = typename T::value_type; + +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + +template +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; + +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; + +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B1 { }; +template +struct conjunction +: std::conditional, B1>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g. clang 3.5 or gcc 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + + +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to using it in this library. + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + is_constructible::value && + is_constructible::value; +}; + +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; + +template +struct is_constructible_object_type_impl : std::false_type {}; + +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + static constexpr bool value = + (is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; + +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; + +template +struct is_compatible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_constructible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_compatible_array_type_impl : std::false_type {}; + +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < + is_detected::value&& + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> +{ + static constexpr bool value = + is_constructible>::value; +}; + +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; + +template +struct is_constructible_array_type_impl : std::false_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& + is_complete_type < + detected_t>::value >> +{ + using value_type = range_value_t; + + static constexpr bool value = + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; +}; + +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; + +template +struct is_compatible_type_impl: std::false_type {}; + +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; + +template +struct is_compatible_type + : is_compatible_type_impl {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; + +// a naive helper to check if a type is an ordered_map (exploits the fact that +// ordered_map inherits capacity() from std::vector) +template +struct is_ordered_map +{ + using one = char; + + struct two + { + char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + }; + + template static one test( decltype(&C::capacity) ) ; + template static two test(...); + + enum { value = sizeof(test(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) +}; + +// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) +template < typename T, typename U, enable_if_t < !std::is_same::value, int > = 0 > +T conditional_static_cast(U value) +{ + return static_cast(value); +} + +template::value, int> = 0> +T conditional_static_cast(U value) +{ + return value; +} + +} // namespace detail +} // namespace nlohmann + +// #include + + +#ifdef JSON_HAS_CPP_17 + #include +#endif + +namespace nlohmann +{ +namespace detail +{ +template +void from_json(const BasicJsonType& j, typename std::nullptr_t& n) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_null())) + { + JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j)); + } + n = nullptr; +} + +// overloads for basic_json template parameters +template < typename BasicJsonType, typename ArithmeticType, + enable_if_t < std::is_arithmetic::value&& + !std::is_same::value, + int > = 0 > +void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::boolean: + case value_t::binary: + case value_t::discarded: + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); + } +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) + { + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j)); + } + b = *j.template get_ptr(); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); + } + s = *j.template get_ptr(); +} + +template < + typename BasicJsonType, typename ConstructibleStringType, + enable_if_t < + is_constructible_string_type::value&& + !std::is_same::value, + int > = 0 > +void from_json(const BasicJsonType& j, ConstructibleStringType& s) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); + } + + s = *j.template get_ptr(); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) +{ + get_arithmetic_value(j, val); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) +{ + get_arithmetic_value(j, val); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) +{ + get_arithmetic_value(j, val); +} + +template::value, int> = 0> +void from_json(const BasicJsonType& j, EnumType& e) +{ + typename std::underlying_type::type val; + get_arithmetic_value(j, val); + e = static_cast(val); +} + +// forward_list doesn't have an insert method +template::value, int> = 0> +void from_json(const BasicJsonType& j, std::forward_list& l) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + l.clear(); + std::transform(j.rbegin(), j.rend(), + std::front_inserter(l), [](const BasicJsonType & i) + { + return i.template get(); + }); +} + +// valarray doesn't have an insert method +template::value, int> = 0> +void from_json(const BasicJsonType& j, std::valarray& l) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + l.resize(j.size()); + std::transform(j.begin(), j.end(), std::begin(l), + [](const BasicJsonType & elem) + { + return elem.template get(); + }); +} + +template +auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +-> decltype(j.template get(), void()) +{ + for (std::size_t i = 0; i < N; ++i) + { + arr[i] = j.at(i).template get(); + } +} + +template +void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) +{ + arr = *j.template get_ptr(); +} + +template +auto from_json_array_impl(const BasicJsonType& j, std::array& arr, + priority_tag<2> /*unused*/) +-> decltype(j.template get(), void()) +{ + for (std::size_t i = 0; i < N; ++i) + { + arr[i] = j.at(i).template get(); + } +} + +template::value, + int> = 0> +auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) +-> decltype( + arr.reserve(std::declval()), + j.template get(), + void()) +{ + using std::end; + + ConstructibleArrayType ret; + ret.reserve(j.size()); + std::transform(j.begin(), j.end(), + std::inserter(ret, end(ret)), [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); + arr = std::move(ret); +} + +template::value, + int> = 0> +void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, + priority_tag<0> /*unused*/) +{ + using std::end; + + ConstructibleArrayType ret; + std::transform( + j.begin(), j.end(), std::inserter(ret, end(ret)), + [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); + arr = std::move(ret); +} + +template < typename BasicJsonType, typename ConstructibleArrayType, + enable_if_t < + is_constructible_array_type::value&& + !is_constructible_object_type::value&& + !is_constructible_string_type::value&& + !std::is_same::value&& + !is_basic_json::value, + int > = 0 > +auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) +-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), +j.template get(), +void()) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + + from_json_array_impl(j, arr, priority_tag<3> {}); +} + +template < typename BasicJsonType, typename T, std::size_t... Idx > +std::array from_json_inplace_array_impl(BasicJsonType&& j, + identity_tag> /*unused*/, index_sequence /*unused*/) +{ + return { { std::forward(j).at(Idx).template get()... } }; +} + +template < typename BasicJsonType, typename T, std::size_t N > +auto from_json(BasicJsonType&& j, identity_tag> tag) +-> decltype(from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {})) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + + return from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {}); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) + { + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j)); + } + + bin = *j.template get_ptr(); +} + +template::value, int> = 0> +void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_object())) + { + JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j)); + } + + ConstructibleObjectType ret; + const auto* inner_object = j.template get_ptr(); + using value_type = typename ConstructibleObjectType::value_type; + std::transform( + inner_object->begin(), inner_object->end(), + std::inserter(ret, ret.begin()), + [](typename BasicJsonType::object_t::value_type const & p) + { + return value_type(p.first, p.second.template get()); + }); + obj = std::move(ret); +} + +// overload for arithmetic types, not chosen for basic_json template arguments +// (BooleanType, etc..); note: Is it really necessary to provide explicit +// overloads for boolean_t etc. in case of a custom BooleanType which is not +// an arithmetic type? +template < typename BasicJsonType, typename ArithmeticType, + enable_if_t < + std::is_arithmetic::value&& + !std::is_same::value&& + !std::is_same::value&& + !std::is_same::value&& + !std::is_same::value, + int > = 0 > +void from_json(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::boolean: + { + val = static_cast(*j.template get_ptr()); + break; + } + + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::string: + case value_t::binary: + case value_t::discarded: + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); + } +} + +template +std::tuple from_json_tuple_impl_base(BasicJsonType&& j, index_sequence /*unused*/) +{ + return std::make_tuple(std::forward(j).at(Idx).template get()...); +} + +template < typename BasicJsonType, class A1, class A2 > +std::pair from_json_tuple_impl(BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<0> /*unused*/) +{ + return {std::forward(j).at(0).template get(), + std::forward(j).at(1).template get()}; +} + +template +void from_json_tuple_impl(BasicJsonType&& j, std::pair& p, priority_tag<1> /*unused*/) +{ + p = from_json_tuple_impl(std::forward(j), identity_tag> {}, priority_tag<0> {}); +} + +template +std::tuple from_json_tuple_impl(BasicJsonType&& j, identity_tag> /*unused*/, priority_tag<2> /*unused*/) +{ + return from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); +} + +template +void from_json_tuple_impl(BasicJsonType&& j, std::tuple& t, priority_tag<3> /*unused*/) +{ + t = from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); +} + +template +auto from_json(BasicJsonType&& j, TupleRelated&& t) +-> decltype(from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {})) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + + return from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {}); +} + +template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, + typename = enable_if_t < !std::is_constructible < + typename BasicJsonType::string_t, Key >::value >> +void from_json(const BasicJsonType& j, std::map& m) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + m.clear(); + for (const auto& p : j) + { + if (JSON_HEDLEY_UNLIKELY(!p.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } +} + +template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, + typename = enable_if_t < !std::is_constructible < + typename BasicJsonType::string_t, Key >::value >> +void from_json(const BasicJsonType& j, std::unordered_map& m) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + } + m.clear(); + for (const auto& p : j) + { + if (JSON_HEDLEY_UNLIKELY(!p.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } +} + +#ifdef JSON_HAS_CPP_17 +template +void from_json(const BasicJsonType& j, std::filesystem::path& p) +{ + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); + } + p = *j.template get_ptr(); +} +#endif + +struct from_json_fn +{ + template + auto operator()(const BasicJsonType& j, T&& val) const + noexcept(noexcept(from_json(j, std::forward(val)))) + -> decltype(from_json(j, std::forward(val))) + { + return from_json(j, std::forward(val)); + } +}; +} // namespace detail + +/// namespace to hold default `from_json` function +/// to see why this is required: +/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html +namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) +{ +constexpr const auto& from_json = detail::static_const::value; // NOLINT(misc-definitions-in-headers) +} // namespace +} // namespace nlohmann + +// #include + + +#include // copy +#include // begin, end +#include // string +#include // tuple, get +#include // is_same, is_constructible, is_floating_point, is_enum, underlying_type +#include // move, forward, declval, pair +#include // valarray +#include // vector + +// #include + +// #include + + +#include // size_t +#include // input_iterator_tag +#include // string, to_string +#include // tuple_size, get, tuple_element +#include // move + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +void int_to_string( string_type& target, std::size_t value ) +{ + // For ADL + using std::to_string; + target = to_string(value); +} +template class iteration_proxy_value +{ + public: + using difference_type = std::ptrdiff_t; + using value_type = iteration_proxy_value; + using pointer = value_type * ; + using reference = value_type & ; + using iterator_category = std::input_iterator_tag; + using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; + + private: + /// the iterator + IteratorType anchor; + /// an index for arrays (used to create key names) + std::size_t array_index = 0; + /// last stringified array index + mutable std::size_t array_index_last = 0; + /// a string representation of the array index + mutable string_type array_index_str = "0"; + /// an empty string (to return a reference for primitive values) + const string_type empty_str{}; + + public: + explicit iteration_proxy_value(IteratorType it) noexcept + : anchor(std::move(it)) + {} + + /// dereference operator (needed for range-based for) + iteration_proxy_value& operator*() + { + return *this; + } + + /// increment operator (needed for range-based for) + iteration_proxy_value& operator++() + { + ++anchor; + ++array_index; + + return *this; + } + + /// equality operator (needed for InputIterator) + bool operator==(const iteration_proxy_value& o) const + { + return anchor == o.anchor; + } + + /// inequality operator (needed for range-based for) + bool operator!=(const iteration_proxy_value& o) const + { + return anchor != o.anchor; + } + + /// return key of the iterator + const string_type& key() const + { + JSON_ASSERT(anchor.m_object != nullptr); + + switch (anchor.m_object->type()) + { + // use integer array index as key + case value_t::array: + { + if (array_index != array_index_last) + { + int_to_string( array_index_str, array_index ); + array_index_last = array_index; + } + return array_index_str; + } + + // use key from the object + case value_t::object: + return anchor.key(); + + // use an empty key for all primitive types + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return empty_str; + } + } + + /// return value of the iterator + typename IteratorType::reference value() const + { + return anchor.value(); + } +}; + +/// proxy class for the items() function +template class iteration_proxy +{ + private: + /// the container to iterate + typename IteratorType::reference container; + + public: + /// construct iteration proxy from a container + explicit iteration_proxy(typename IteratorType::reference cont) noexcept + : container(cont) {} + + /// return iterator begin (needed for range-based for) + iteration_proxy_value begin() noexcept + { + return iteration_proxy_value(container.begin()); + } + + /// return iterator end (needed for range-based for) + iteration_proxy_value end() noexcept + { + return iteration_proxy_value(container.end()); + } +}; +// Structured Bindings Support +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +template = 0> +auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.key()) +{ + return i.key(); +} +// Structured Bindings Support +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +template = 0> +auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.value()) +{ + return i.value(); +} +} // namespace detail +} // namespace nlohmann + +// The Addition to the STD Namespace is required to add +// Structured Bindings Support to the iteration_proxy_value class +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +namespace std +{ +#if defined(__clang__) + // Fix: https://github.com/nlohmann/json/issues/1401 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wmismatched-tags" +#endif +template +class tuple_size<::nlohmann::detail::iteration_proxy_value> + : public std::integral_constant {}; + +template +class tuple_element> +{ + public: + using type = decltype( + get(std::declval < + ::nlohmann::detail::iteration_proxy_value> ())); +}; +#if defined(__clang__) + #pragma clang diagnostic pop +#endif +} // namespace std + +// #include + +// #include + +// #include + + +#ifdef JSON_HAS_CPP_17 + #include +#endif + +namespace nlohmann +{ +namespace detail +{ +////////////////// +// constructors // +////////////////// + +/* + * Note all external_constructor<>::construct functions need to call + * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an + * allocated value (e.g., a string). See bug issue + * https://github.com/nlohmann/json/issues/2865 for more information. + */ + +template struct external_constructor; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::boolean; + j.m_value = b; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value = s; + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value = std::move(s); + j.assert_invariant(); + } + + template < typename BasicJsonType, typename CompatibleStringType, + enable_if_t < !std::is_same::value, + int > = 0 > + static void construct(BasicJsonType& j, const CompatibleStringType& str) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value.string = j.template create(str); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::binary; + j.m_value = typename BasicJsonType::binary_t(b); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::binary; + j.m_value = typename BasicJsonType::binary_t(std::move(b)); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::number_float; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::number_unsigned; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::number_integer; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = arr; + j.set_parents(); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = std::move(arr); + j.set_parents(); + j.assert_invariant(); + } + + template < typename BasicJsonType, typename CompatibleArrayType, + enable_if_t < !std::is_same::value, + int > = 0 > + static void construct(BasicJsonType& j, const CompatibleArrayType& arr) + { + using std::begin; + using std::end; + + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value.array = j.template create(begin(arr), end(arr)); + j.set_parents(); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, const std::vector& arr) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->reserve(arr.size()); + for (const bool x : arr) + { + j.m_value.array->push_back(x); + j.set_parent(j.m_value.array->back()); + } + j.assert_invariant(); + } + + template::value, int> = 0> + static void construct(BasicJsonType& j, const std::valarray& arr) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->resize(arr.size()); + if (arr.size() > 0) + { + std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); + } + j.set_parents(); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value = obj; + j.set_parents(); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) + { + j.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value = std::move(obj); + j.set_parents(); + j.assert_invariant(); + } + + template < typename BasicJsonType, typename CompatibleObjectType, + enable_if_t < !std::is_same::value, int > = 0 > + static void construct(BasicJsonType& j, const CompatibleObjectType& obj) + { + using std::begin; + using std::end; + + j.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value.object = j.template create(begin(obj), end(obj)); + j.set_parents(); + j.assert_invariant(); + } +}; + +///////////// +// to_json // +///////////// + +template::value, int> = 0> +void to_json(BasicJsonType& j, T b) noexcept +{ + external_constructor::construct(j, b); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, const CompatibleString& s) +{ + external_constructor::construct(j, s); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) +{ + external_constructor::construct(j, std::move(s)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, FloatType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, EnumType e) noexcept +{ + using underlying_type = typename std::underlying_type::type; + external_constructor::construct(j, static_cast(e)); +} + +template +void to_json(BasicJsonType& j, const std::vector& e) +{ + external_constructor::construct(j, e); +} + +template < typename BasicJsonType, typename CompatibleArrayType, + enable_if_t < is_compatible_array_type::value&& + !is_compatible_object_type::value&& + !is_compatible_string_type::value&& + !std::is_same::value&& + !is_basic_json::value, + int > = 0 > +void to_json(BasicJsonType& j, const CompatibleArrayType& arr) +{ + external_constructor::construct(j, arr); +} + +template +void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) +{ + external_constructor::construct(j, bin); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, const std::valarray& arr) +{ + external_constructor::construct(j, std::move(arr)); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) +{ + external_constructor::construct(j, std::move(arr)); +} + +template < typename BasicJsonType, typename CompatibleObjectType, + enable_if_t < is_compatible_object_type::value&& !is_basic_json::value, int > = 0 > +void to_json(BasicJsonType& j, const CompatibleObjectType& obj) +{ + external_constructor::construct(j, obj); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) +{ + external_constructor::construct(j, std::move(obj)); +} + +template < + typename BasicJsonType, typename T, std::size_t N, + enable_if_t < !std::is_constructible::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + int > = 0 > +void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +{ + external_constructor::construct(j, arr); +} + +template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > +void to_json(BasicJsonType& j, const std::pair& p) +{ + j = { p.first, p.second }; +} + +// for https://github.com/nlohmann/json/pull/1134 +template>::value, int> = 0> +void to_json(BasicJsonType& j, const T& b) +{ + j = { {b.key(), b.value()} }; +} + +template +void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) +{ + j = { std::get(t)... }; +} + +template::value, int > = 0> +void to_json(BasicJsonType& j, const T& t) +{ + to_json_tuple_impl(j, t, make_index_sequence::value> {}); +} + +#ifdef JSON_HAS_CPP_17 +template +void to_json(BasicJsonType& j, const std::filesystem::path& p) +{ + j = p.string(); +} +#endif + +struct to_json_fn +{ + template + auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) + -> decltype(to_json(j, std::forward(val)), void()) + { + return to_json(j, std::forward(val)); + } +}; +} // namespace detail + +/// namespace to hold default `to_json` function +/// to see why this is required: +/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html +namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) +{ +constexpr const auto& to_json = detail::static_const::value; // NOLINT(misc-definitions-in-headers) +} // namespace +} // namespace nlohmann + +// #include + +// #include + + +namespace nlohmann +{ + +template +struct adl_serializer +{ + /*! + @brief convert a JSON value to any value type + + This function is usually called by the `get()` function of the + @ref basic_json class (either explicit or via conversion operators). + + @note This function is chosen for default-constructible value types. + + @param[in] j JSON value to read from + @param[in,out] val value to write to + */ + template + static auto from_json(BasicJsonType && j, TargetType& val) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), val))) + -> decltype(::nlohmann::from_json(std::forward(j), val), void()) + { + ::nlohmann::from_json(std::forward(j), val); + } + + /*! + @brief convert a JSON value to any value type + + This function is usually called by the `get()` function of the + @ref basic_json class (either explicit or via conversion operators). + + @note This function is chosen for value types which are not default-constructible. + + @param[in] j JSON value to read from + + @return copy of the JSON value, converted to @a ValueType + */ + template + static auto from_json(BasicJsonType && j) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), detail::identity_tag {}))) + -> decltype(::nlohmann::from_json(std::forward(j), detail::identity_tag {})) + { + return ::nlohmann::from_json(std::forward(j), detail::identity_tag {}); + } + + /*! + @brief convert any value type to a JSON value + + This function is usually called by the constructors of the @ref basic_json + class. + + @param[in,out] j JSON value to write to + @param[in] val value to read from + */ + template + static auto to_json(BasicJsonType& j, TargetType && val) noexcept( + noexcept(::nlohmann::to_json(j, std::forward(val)))) + -> decltype(::nlohmann::to_json(j, std::forward(val)), void()) + { + ::nlohmann::to_json(j, std::forward(val)); + } +}; +} // namespace nlohmann + +// #include + + +#include // uint8_t, uint64_t +#include // tie +#include // move + +namespace nlohmann +{ + +/*! +@brief an internal type for a backed binary type + +This type extends the template parameter @a BinaryType provided to `basic_json` +with a subtype used by BSON and MessagePack. This type exists so that the user +does not have to specify a type themselves with a specific naming scheme in +order to override the binary type. + +@tparam BinaryType container to store bytes (`std::vector` by + default) + +@since version 3.8.0; changed type of subtypes to std::uint64_t in 3.10.0. +*/ +template +class byte_container_with_subtype : public BinaryType +{ + public: + /// the type of the underlying container + using container_type = BinaryType; + /// the type of the subtype + using subtype_type = std::uint64_t; + + byte_container_with_subtype() noexcept(noexcept(container_type())) + : container_type() + {} + + byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b))) + : container_type(b) + {} + + byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b)))) + : container_type(std::move(b)) + {} + + byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b))) + : container_type(b) + , m_subtype(subtype_) + , m_has_subtype(true) + {} + + byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b)))) + : container_type(std::move(b)) + , m_subtype(subtype_) + , m_has_subtype(true) + {} + + bool operator==(const byte_container_with_subtype& rhs) const + { + return std::tie(static_cast(*this), m_subtype, m_has_subtype) == + std::tie(static_cast(rhs), rhs.m_subtype, rhs.m_has_subtype); + } + + bool operator!=(const byte_container_with_subtype& rhs) const + { + return !(rhs == *this); + } + + /*! + @brief sets the binary subtype + + Sets the binary subtype of the value, also flags a binary JSON value as + having a subtype, which has implications for serialization. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @sa see @ref subtype() -- return the binary subtype + @sa see @ref clear_subtype() -- clears the binary subtype + @sa see @ref has_subtype() -- returns whether or not the binary value has a + subtype + + @since version 3.8.0 + */ + void set_subtype(subtype_type subtype_) noexcept + { + m_subtype = subtype_; + m_has_subtype = true; + } + + /*! + @brief return the binary subtype + + Returns the numerical subtype of the value if it has a subtype. If it does + not have a subtype, this function will return subtype_type(-1) as a sentinel + value. + + @return the numerical subtype of the binary value + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @sa see @ref set_subtype() -- sets the binary subtype + @sa see @ref clear_subtype() -- clears the binary subtype + @sa see @ref has_subtype() -- returns whether or not the binary value has a + subtype + + @since version 3.8.0; fixed return value to properly return + subtype_type(-1) as documented in version 3.10.0 + */ + constexpr subtype_type subtype() const noexcept + { + return m_has_subtype ? m_subtype : subtype_type(-1); + } + + /*! + @brief return whether the value has a subtype + + @return whether the value has a subtype + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @sa see @ref subtype() -- return the binary subtype + @sa see @ref set_subtype() -- sets the binary subtype + @sa see @ref clear_subtype() -- clears the binary subtype + + @since version 3.8.0 + */ + constexpr bool has_subtype() const noexcept + { + return m_has_subtype; + } + + /*! + @brief clears the binary subtype + + Clears the binary subtype and flags the value as not having a subtype, which + has implications for serialization; for instance MessagePack will prefer the + bin family over the ext family. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @sa see @ref subtype() -- return the binary subtype + @sa see @ref set_subtype() -- sets the binary subtype + @sa see @ref has_subtype() -- returns whether or not the binary value has a + subtype + + @since version 3.8.0 + */ + void clear_subtype() noexcept + { + m_subtype = 0; + m_has_subtype = false; + } + + private: + subtype_type m_subtype = 0; + bool m_has_subtype = false; +}; + +} // namespace nlohmann + +// #include + +// #include + +// #include + +// #include + + +#include // uint8_t +#include // size_t +#include // hash + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ + +// boost::hash_combine +inline std::size_t combine(std::size_t seed, std::size_t h) noexcept +{ + seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); + return seed; +} + +/*! +@brief hash a JSON value + +The hash function tries to rely on std::hash where possible. Furthermore, the +type of the JSON value is taken into account to have different hash values for +null, 0, 0U, and false, etc. + +@tparam BasicJsonType basic_json specialization +@param j JSON value to hash +@return hash value of j +*/ +template +std::size_t hash(const BasicJsonType& j) +{ + using string_t = typename BasicJsonType::string_t; + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + + const auto type = static_cast(j.type()); + switch (j.type()) + { + case BasicJsonType::value_t::null: + case BasicJsonType::value_t::discarded: + { + return combine(type, 0); + } + + case BasicJsonType::value_t::object: + { + auto seed = combine(type, j.size()); + for (const auto& element : j.items()) + { + const auto h = std::hash {}(element.key()); + seed = combine(seed, h); + seed = combine(seed, hash(element.value())); + } + return seed; + } + + case BasicJsonType::value_t::array: + { + auto seed = combine(type, j.size()); + for (const auto& element : j) + { + seed = combine(seed, hash(element)); + } + return seed; + } + + case BasicJsonType::value_t::string: + { + const auto h = std::hash {}(j.template get_ref()); + return combine(type, h); + } + + case BasicJsonType::value_t::boolean: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::number_integer: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::number_unsigned: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::number_float: + { + const auto h = std::hash {}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::binary: + { + auto seed = combine(type, j.get_binary().size()); + const auto h = std::hash {}(j.get_binary().has_subtype()); + seed = combine(seed, h); + seed = combine(seed, static_cast(j.get_binary().subtype())); + for (const auto byte : j.get_binary()) + { + seed = combine(seed, std::hash {}(byte)); + } + return seed; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return 0; // LCOV_EXCL_LINE + } +} + +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // generate_n +#include // array +#include // ldexp +#include // size_t +#include // uint8_t, uint16_t, uint32_t, uint64_t +#include // snprintf +#include // memcpy +#include // back_inserter +#include // numeric_limits +#include // char_traits, string +#include // make_pair, move +#include // vector + +// #include + +// #include + + +#include // array +#include // size_t +#include // strlen +#include // begin, end, iterator_traits, random_access_iterator_tag, distance, next +#include // shared_ptr, make_shared, addressof +#include // accumulate +#include // string, char_traits +#include // enable_if, is_base_of, is_pointer, is_integral, remove_pointer +#include // pair, declval + +#ifndef JSON_NO_IO + #include // FILE * + #include // istream +#endif // JSON_NO_IO + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/// the supported input formats +enum class input_format_t { json, cbor, msgpack, ubjson, bson }; + +//////////////////// +// input adapters // +//////////////////// + +#ifndef JSON_NO_IO +/*! +Input adapter for stdio file access. This adapter read only 1 byte and do not use any + buffer. This adapter is a very low level adapter. +*/ +class file_input_adapter +{ + public: + using char_type = char; + + JSON_HEDLEY_NON_NULL(2) + explicit file_input_adapter(std::FILE* f) noexcept + : m_file(f) + {} + + // make class move-only + file_input_adapter(const file_input_adapter&) = delete; + file_input_adapter(file_input_adapter&&) noexcept = default; + file_input_adapter& operator=(const file_input_adapter&) = delete; + file_input_adapter& operator=(file_input_adapter&&) = delete; + ~file_input_adapter() = default; + + std::char_traits::int_type get_character() noexcept + { + return std::fgetc(m_file); + } + + private: + /// the file pointer to read from + std::FILE* m_file; +}; + + +/*! +Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at +beginning of input. Does not support changing the underlying std::streambuf +in mid-input. Maintains underlying std::istream and std::streambuf to support +subsequent use of standard std::istream operations to process any input +characters following those used in parsing the JSON input. Clears the +std::istream flags; any input errors (e.g., EOF) will be detected by the first +subsequent call for input from the std::istream. +*/ +class input_stream_adapter +{ + public: + using char_type = char; + + ~input_stream_adapter() + { + // clear stream flags; we use underlying streambuf I/O, do not + // maintain ifstream flags, except eof + if (is != nullptr) + { + is->clear(is->rdstate() & std::ios::eofbit); + } + } + + explicit input_stream_adapter(std::istream& i) + : is(&i), sb(i.rdbuf()) + {} + + // delete because of pointer members + input_stream_adapter(const input_stream_adapter&) = delete; + input_stream_adapter& operator=(input_stream_adapter&) = delete; + input_stream_adapter& operator=(input_stream_adapter&&) = delete; + + input_stream_adapter(input_stream_adapter&& rhs) noexcept + : is(rhs.is), sb(rhs.sb) + { + rhs.is = nullptr; + rhs.sb = nullptr; + } + + // std::istream/std::streambuf use std::char_traits::to_int_type, to + // ensure that std::char_traits::eof() and the character 0xFF do not + // end up as the same value, eg. 0xFFFFFFFF. + std::char_traits::int_type get_character() + { + auto res = sb->sbumpc(); + // set eof manually, as we don't use the istream interface. + if (JSON_HEDLEY_UNLIKELY(res == std::char_traits::eof())) + { + is->clear(is->rdstate() | std::ios::eofbit); + } + return res; + } + + private: + /// the associated input stream + std::istream* is = nullptr; + std::streambuf* sb = nullptr; +}; +#endif // JSON_NO_IO + +// General-purpose iterator-based adapter. It might not be as fast as +// theoretically possible for some containers, but it is extremely versatile. +template +class iterator_input_adapter +{ + public: + using char_type = typename std::iterator_traits::value_type; + + iterator_input_adapter(IteratorType first, IteratorType last) + : current(std::move(first)), end(std::move(last)) + {} + + typename std::char_traits::int_type get_character() + { + if (JSON_HEDLEY_LIKELY(current != end)) + { + auto result = std::char_traits::to_int_type(*current); + std::advance(current, 1); + return result; + } + + return std::char_traits::eof(); + } + + private: + IteratorType current; + IteratorType end; + + template + friend struct wide_string_input_helper; + + bool empty() const + { + return current == end; + } +}; + + +template +struct wide_string_input_helper; + +template +struct wide_string_input_helper +{ + // UTF-32 + static void fill_buffer(BaseInputAdapter& input, + std::array::int_type, 4>& utf8_bytes, + size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) + { + utf8_bytes_index = 0; + + if (JSON_HEDLEY_UNLIKELY(input.empty())) + { + utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const auto wc = input.get_character(); + + // UTF-32 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u) & 0x1Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 2; + } + else if (wc <= 0xFFFF) + { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u) & 0x0Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 3; + } + else if (wc <= 0x10FFFF) + { + utf8_bytes[0] = static_cast::int_type>(0xF0u | ((static_cast(wc) >> 18u) & 0x07u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 4; + } + else + { + // unknown character + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + } + } +}; + +template +struct wide_string_input_helper +{ + // UTF-16 + static void fill_buffer(BaseInputAdapter& input, + std::array::int_type, 4>& utf8_bytes, + size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) + { + utf8_bytes_index = 0; + + if (JSON_HEDLEY_UNLIKELY(input.empty())) + { + utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const auto wc = input.get_character(); + + // UTF-16 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 2; + } + else if (0xD800 > wc || wc >= 0xE000) + { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 3; + } + else + { + if (JSON_HEDLEY_UNLIKELY(!input.empty())) + { + const auto wc2 = static_cast(input.get_character()); + const auto charcode = 0x10000u + (((static_cast(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); + utf8_bytes[0] = static_cast::int_type>(0xF0u | (charcode >> 18u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (charcode & 0x3Fu)); + utf8_bytes_filled = 4; + } + else + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + } + } + } +}; + +// Wraps another input apdater to convert wide character types into individual bytes. +template +class wide_string_input_adapter +{ + public: + using char_type = char; + + wide_string_input_adapter(BaseInputAdapter base) + : base_adapter(base) {} + + typename std::char_traits::int_type get_character() noexcept + { + // check if buffer needs to be filled + if (utf8_bytes_index == utf8_bytes_filled) + { + fill_buffer(); + + JSON_ASSERT(utf8_bytes_filled > 0); + JSON_ASSERT(utf8_bytes_index == 0); + } + + // use buffer + JSON_ASSERT(utf8_bytes_filled > 0); + JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); + return utf8_bytes[utf8_bytes_index++]; + } + + private: + BaseInputAdapter base_adapter; + + template + void fill_buffer() + { + wide_string_input_helper::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); + } + + /// a buffer for UTF-8 bytes + std::array::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; + + /// index to the utf8_codes array for the next valid byte + std::size_t utf8_bytes_index = 0; + /// number of valid bytes in the utf8_codes array + std::size_t utf8_bytes_filled = 0; +}; + + +template +struct iterator_input_adapter_factory +{ + using iterator_type = IteratorType; + using char_type = typename std::iterator_traits::value_type; + using adapter_type = iterator_input_adapter; + + static adapter_type create(IteratorType first, IteratorType last) + { + return adapter_type(std::move(first), std::move(last)); + } +}; + +template +struct is_iterator_of_multibyte +{ + using value_type = typename std::iterator_traits::value_type; + enum + { + value = sizeof(value_type) > 1 + }; +}; + +template +struct iterator_input_adapter_factory::value>> +{ + using iterator_type = IteratorType; + using char_type = typename std::iterator_traits::value_type; + using base_adapter_type = iterator_input_adapter; + using adapter_type = wide_string_input_adapter; + + static adapter_type create(IteratorType first, IteratorType last) + { + return adapter_type(base_adapter_type(std::move(first), std::move(last))); + } +}; + +// General purpose iterator-based input +template +typename iterator_input_adapter_factory::adapter_type input_adapter(IteratorType first, IteratorType last) +{ + using factory_type = iterator_input_adapter_factory; + return factory_type::create(first, last); +} + +// Convenience shorthand from container to iterator +// Enables ADL on begin(container) and end(container) +// Encloses the using declarations in namespace for not to leak them to outside scope + +namespace container_input_adapter_factory_impl +{ + +using std::begin; +using std::end; + +template +struct container_input_adapter_factory {}; + +template +struct container_input_adapter_factory< ContainerType, + void_t()), end(std::declval()))>> + { + using adapter_type = decltype(input_adapter(begin(std::declval()), end(std::declval()))); + + static adapter_type create(const ContainerType& container) +{ + return input_adapter(begin(container), end(container)); +} + }; + +} // namespace container_input_adapter_factory_impl + +template +typename container_input_adapter_factory_impl::container_input_adapter_factory::adapter_type input_adapter(const ContainerType& container) +{ + return container_input_adapter_factory_impl::container_input_adapter_factory::create(container); +} + +#ifndef JSON_NO_IO +// Special cases with fast paths +inline file_input_adapter input_adapter(std::FILE* file) +{ + return file_input_adapter(file); +} + +inline input_stream_adapter input_adapter(std::istream& stream) +{ + return input_stream_adapter(stream); +} + +inline input_stream_adapter input_adapter(std::istream&& stream) +{ + return input_stream_adapter(stream); +} +#endif // JSON_NO_IO + +using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval(), std::declval())); + +// Null-delimited strings, and the like. +template < typename CharT, + typename std::enable_if < + std::is_pointer::value&& + !std::is_array::value&& + std::is_integral::type>::value&& + sizeof(typename std::remove_pointer::type) == 1, + int >::type = 0 > +contiguous_bytes_input_adapter input_adapter(CharT b) +{ + auto length = std::strlen(reinterpret_cast(b)); + const auto* ptr = reinterpret_cast(b); + return input_adapter(ptr, ptr + length); +} + +template +auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +{ + return input_adapter(array, array + N); +} + +// This class only handles inputs of input_buffer_adapter type. +// It's required so that expressions like {ptr, len} can be implicitely casted +// to the correct adapter. +class span_input_adapter +{ + public: + template < typename CharT, + typename std::enable_if < + std::is_pointer::value&& + std::is_integral::type>::value&& + sizeof(typename std::remove_pointer::type) == 1, + int >::type = 0 > + span_input_adapter(CharT b, std::size_t l) + : ia(reinterpret_cast(b), reinterpret_cast(b) + l) {} + + template::iterator_category, std::random_access_iterator_tag>::value, + int>::type = 0> + span_input_adapter(IteratorType first, IteratorType last) + : ia(input_adapter(first, last)) {} + + contiguous_bytes_input_adapter&& get() + { + return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) + } + + private: + contiguous_bytes_input_adapter ia; +}; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include +#include // string +#include // move +#include // vector + +// #include + +// #include + + +namespace nlohmann +{ + +/*! +@brief SAX interface + +This class describes the SAX interface used by @ref nlohmann::json::sax_parse. +Each function is called in different situations while the input is parsed. The +boolean return value informs the parser whether to continue processing the +input. +*/ +template +struct json_sax +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + /*! + @brief a null value was read + @return whether parsing should proceed + */ + virtual bool null() = 0; + + /*! + @brief a boolean value was read + @param[in] val boolean value + @return whether parsing should proceed + */ + virtual bool boolean(bool val) = 0; + + /*! + @brief an integer number was read + @param[in] val integer value + @return whether parsing should proceed + */ + virtual bool number_integer(number_integer_t val) = 0; + + /*! + @brief an unsigned integer number was read + @param[in] val unsigned integer value + @return whether parsing should proceed + */ + virtual bool number_unsigned(number_unsigned_t val) = 0; + + /*! + @brief an floating-point number was read + @param[in] val floating-point value + @param[in] s raw token value + @return whether parsing should proceed + */ + virtual bool number_float(number_float_t val, const string_t& s) = 0; + + /*! + @brief a string was read + @param[in] val string value + @return whether parsing should proceed + @note It is safe to move the passed string. + */ + virtual bool string(string_t& val) = 0; + + /*! + @brief a binary string was read + @param[in] val binary value + @return whether parsing should proceed + @note It is safe to move the passed binary. + */ + virtual bool binary(binary_t& val) = 0; + + /*! + @brief the beginning of an object was read + @param[in] elements number of object elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_object(std::size_t elements) = 0; + + /*! + @brief an object key was read + @param[in] val object key + @return whether parsing should proceed + @note It is safe to move the passed string. + */ + virtual bool key(string_t& val) = 0; + + /*! + @brief the end of an object was read + @return whether parsing should proceed + */ + virtual bool end_object() = 0; + + /*! + @brief the beginning of an array was read + @param[in] elements number of array elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_array(std::size_t elements) = 0; + + /*! + @brief the end of an array was read + @return whether parsing should proceed + */ + virtual bool end_array() = 0; + + /*! + @brief a parse error occurred + @param[in] position the position in the input where the error occurs + @param[in] last_token the last read token + @param[in] ex an exception object describing the error + @return whether parsing should proceed (must return false) + */ + virtual bool parse_error(std::size_t position, + const std::string& last_token, + const detail::exception& ex) = 0; + + json_sax() = default; + json_sax(const json_sax&) = default; + json_sax(json_sax&&) noexcept = default; + json_sax& operator=(const json_sax&) = default; + json_sax& operator=(json_sax&&) noexcept = default; + virtual ~json_sax() = default; +}; + + +namespace detail +{ +/*! +@brief SAX implementation to create a JSON value from SAX events + +This class implements the @ref json_sax interface and processes the SAX events +to create a JSON value which makes it basically a DOM parser. The structure or +hierarchy of the JSON value is managed by the stack `ref_stack` which contains +a pointer to the respective array or object for each recursion depth. + +After successful parsing, the value that is passed by reference to the +constructor contains the parsed value. + +@tparam BasicJsonType the JSON type +*/ +template +class json_sax_dom_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + /*! + @param[in,out] r reference to a JSON value that is manipulated while + parsing + @param[in] allow_exceptions_ whether parse errors yield exceptions + */ + explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) + : root(r), allow_exceptions(allow_exceptions_) + {} + + // make class move-only + json_sax_dom_parser(const json_sax_dom_parser&) = delete; + json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; + json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~json_sax_dom_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool binary(binary_t& val) + { + handle_value(std::move(val)); + return true; + } + + bool start_object(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); + + if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); + } + + return true; + } + + bool key(string_t& val) + { + // add null at given key and store the reference for later + object_element = &(ref_stack.back()->m_value.object->operator[](val)); + return true; + } + + bool end_object() + { + ref_stack.back()->set_parents(); + ref_stack.pop_back(); + return true; + } + + bool start_array(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); + + if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); + } + + return true; + } + + bool end_array() + { + ref_stack.back()->set_parents(); + ref_stack.pop_back(); + return true; + } + + template + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const Exception& ex) + { + errored = true; + static_cast(ex); + if (allow_exceptions) + { + JSON_THROW(ex); + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + */ + template + JSON_HEDLEY_RETURNS_NON_NULL + BasicJsonType* handle_value(Value&& v) + { + if (ref_stack.empty()) + { + root = BasicJsonType(std::forward(v)); + return &root; + } + + JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); + + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->emplace_back(std::forward(v)); + return &(ref_stack.back()->m_value.array->back()); + } + + JSON_ASSERT(ref_stack.back()->is_object()); + JSON_ASSERT(object_element); + *object_element = BasicJsonType(std::forward(v)); + return object_element; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; + +template +class json_sax_dom_callback_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using parser_callback_t = typename BasicJsonType::parser_callback_t; + using parse_event_t = typename BasicJsonType::parse_event_t; + + json_sax_dom_callback_parser(BasicJsonType& r, + const parser_callback_t cb, + const bool allow_exceptions_ = true) + : root(r), callback(cb), allow_exceptions(allow_exceptions_) + { + keep_stack.push_back(true); + } + + // make class move-only + json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~json_sax_dom_callback_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool binary(binary_t& val) + { + handle_value(std::move(val)); + return true; + } + + bool start_object(std::size_t len) + { + // check callback for object start + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::object, true); + ref_stack.push_back(val.second); + + // check object limit + if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); + } + + return true; + } + + bool key(string_t& val) + { + BasicJsonType k = BasicJsonType(val); + + // check callback for key + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::key, k); + key_keep_stack.push_back(keep); + + // add discarded value at given key and store the reference for later + if (keep && ref_stack.back()) + { + object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); + } + + return true; + } + + bool end_object() + { + if (ref_stack.back()) + { + if (!callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) + { + // discard object + *ref_stack.back() = discarded; + } + else + { + ref_stack.back()->set_parents(); + } + } + + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(!keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) + { + // remove discarded value + for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) + { + if (it->is_discarded()) + { + ref_stack.back()->erase(it); + break; + } + } + } + + return true; + } + + bool start_array(std::size_t len) + { + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::array, true); + ref_stack.push_back(val.second); + + // check array limit + if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); + } + + return true; + } + + bool end_array() + { + bool keep = true; + + if (ref_stack.back()) + { + keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); + if (keep) + { + ref_stack.back()->set_parents(); + } + else + { + // discard array + *ref_stack.back() = discarded; + } + } + + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(!keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + // remove discarded value + if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->pop_back(); + } + + return true; + } + + template + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const Exception& ex) + { + errored = true; + static_cast(ex); + if (allow_exceptions) + { + JSON_THROW(ex); + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @param[in] v value to add to the JSON value we build during parsing + @param[in] skip_callback whether we should skip calling the callback + function; this is required after start_array() and + start_object() SAX events, because otherwise we would call the + callback function with an empty array or object, respectively. + + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + + @return pair of boolean (whether value should be kept) and pointer (to the + passed value in the ref_stack hierarchy; nullptr if not kept) + */ + template + std::pair handle_value(Value&& v, const bool skip_callback = false) + { + JSON_ASSERT(!keep_stack.empty()); + + // do not handle this value if we know it would be added to a discarded + // container + if (!keep_stack.back()) + { + return {false, nullptr}; + } + + // create value + auto value = BasicJsonType(std::forward(v)); + + // check callback + const bool keep = skip_callback || callback(static_cast(ref_stack.size()), parse_event_t::value, value); + + // do not handle this value if we just learnt it shall be discarded + if (!keep) + { + return {false, nullptr}; + } + + if (ref_stack.empty()) + { + root = std::move(value); + return {true, &root}; + } + + // skip this value if we already decided to skip the parent + // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) + if (!ref_stack.back()) + { + return {false, nullptr}; + } + + // we now only expect arrays and objects + JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); + + // array + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->emplace_back(std::move(value)); + return {true, &(ref_stack.back()->m_value.array->back())}; + } + + // object + JSON_ASSERT(ref_stack.back()->is_object()); + // check if we should store an element for the current key + JSON_ASSERT(!key_keep_stack.empty()); + const bool store_element = key_keep_stack.back(); + key_keep_stack.pop_back(); + + if (!store_element) + { + return {false, nullptr}; + } + + JSON_ASSERT(object_element); + *object_element = std::move(value); + return {true, object_element}; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// stack to manage which values to keep + std::vector keep_stack {}; + /// stack to manage which object keys to keep + std::vector key_keep_stack {}; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// callback function + const parser_callback_t callback = nullptr; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; + /// a discarded value for the callback + BasicJsonType discarded = BasicJsonType::value_t::discarded; +}; + +template +class json_sax_acceptor +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + bool null() + { + return true; + } + + bool boolean(bool /*unused*/) + { + return true; + } + + bool number_integer(number_integer_t /*unused*/) + { + return true; + } + + bool number_unsigned(number_unsigned_t /*unused*/) + { + return true; + } + + bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) + { + return true; + } + + bool string(string_t& /*unused*/) + { + return true; + } + + bool binary(binary_t& /*unused*/) + { + return true; + } + + bool start_object(std::size_t /*unused*/ = std::size_t(-1)) + { + return true; + } + + bool key(string_t& /*unused*/) + { + return true; + } + + bool end_object() + { + return true; + } + + bool start_array(std::size_t /*unused*/ = std::size_t(-1)) + { + return true; + } + + bool end_array() + { + return true; + } + + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) + { + return false; + } +}; +} // namespace detail + +} // namespace nlohmann + +// #include + + +#include // array +#include // localeconv +#include // size_t +#include // snprintf +#include // strtof, strtod, strtold, strtoll, strtoull +#include // initializer_list +#include // char_traits, string +#include // move +#include // vector + +// #include + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/////////// +// lexer // +/////////// + +template +class lexer_base +{ + public: + /// token types for the parser + enum class token_type + { + uninitialized, ///< indicating the scanner is uninitialized + literal_true, ///< the `true` literal + literal_false, ///< the `false` literal + literal_null, ///< the `null` literal + value_string, ///< a string -- use get_string() for actual value + value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value + value_integer, ///< a signed integer -- use get_number_integer() for actual value + value_float, ///< an floating point number -- use get_number_float() for actual value + begin_array, ///< the character for array begin `[` + begin_object, ///< the character for object begin `{` + end_array, ///< the character for array end `]` + end_object, ///< the character for object end `}` + name_separator, ///< the name separator `:` + value_separator, ///< the value separator `,` + parse_error, ///< indicating a parse error + end_of_input, ///< indicating the end of the input buffer + literal_or_value ///< a literal or the begin of a value (only for diagnostics) + }; + + /// return name of values of type token_type (only used for errors) + JSON_HEDLEY_RETURNS_NON_NULL + JSON_HEDLEY_CONST + static const char* token_type_name(const token_type t) noexcept + { + switch (t) + { + case token_type::uninitialized: + return ""; + case token_type::literal_true: + return "true literal"; + case token_type::literal_false: + return "false literal"; + case token_type::literal_null: + return "null literal"; + case token_type::value_string: + return "string literal"; + case token_type::value_unsigned: + case token_type::value_integer: + case token_type::value_float: + return "number literal"; + case token_type::begin_array: + return "'['"; + case token_type::begin_object: + return "'{'"; + case token_type::end_array: + return "']'"; + case token_type::end_object: + return "'}'"; + case token_type::name_separator: + return "':'"; + case token_type::value_separator: + return "','"; + case token_type::parse_error: + return ""; + case token_type::end_of_input: + return "end of input"; + case token_type::literal_or_value: + return "'[', '{', or a literal"; + // LCOV_EXCL_START + default: // catch non-enum values + return "unknown token"; + // LCOV_EXCL_STOP + } + } +}; +/*! +@brief lexical analysis + +This class organizes the lexical analysis during JSON deserialization. +*/ +template +class lexer : public lexer_base +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using char_type = typename InputAdapterType::char_type; + using char_int_type = typename std::char_traits::int_type; + + public: + using token_type = typename lexer_base::token_type; + + explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept + : ia(std::move(adapter)) + , ignore_comments(ignore_comments_) + , decimal_point_char(static_cast(get_decimal_point())) + {} + + // delete because of pointer members + lexer(const lexer&) = delete; + lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + lexer& operator=(lexer&) = delete; + lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~lexer() = default; + + private: + ///////////////////// + // locales + ///////////////////// + + /// return the locale-dependent decimal point + JSON_HEDLEY_PURE + static char get_decimal_point() noexcept + { + const auto* loc = localeconv(); + JSON_ASSERT(loc != nullptr); + return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); + } + + ///////////////////// + // scan functions + ///////////////////// + + /*! + @brief get codepoint from 4 hex characters following `\u` + + For input "\u c1 c2 c3 c4" the codepoint is: + (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 + = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) + + Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' + must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The + conversion is done by subtracting the offset (0x30, 0x37, and 0x57) + between the ASCII value of the character and the desired integer value. + + @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or + non-hex character) + */ + int get_codepoint() + { + // this function only makes sense after reading `\u` + JSON_ASSERT(current == 'u'); + int codepoint = 0; + + const auto factors = { 12u, 8u, 4u, 0u }; + for (const auto factor : factors) + { + get(); + + if (current >= '0' && current <= '9') + { + codepoint += static_cast((static_cast(current) - 0x30u) << factor); + } + else if (current >= 'A' && current <= 'F') + { + codepoint += static_cast((static_cast(current) - 0x37u) << factor); + } + else if (current >= 'a' && current <= 'f') + { + codepoint += static_cast((static_cast(current) - 0x57u) << factor); + } + else + { + return -1; + } + } + + JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF); + return codepoint; + } + + /*! + @brief check if the next byte(s) are inside a given range + + Adds the current byte and, for each passed range, reads a new byte and + checks if it is inside the range. If a violation was detected, set up an + error message and return false. Otherwise, return true. + + @param[in] ranges list of integers; interpreted as list of pairs of + inclusive lower and upper bound, respectively + + @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, + 1, 2, or 3 pairs. This precondition is enforced by an assertion. + + @return true if and only if no range violation was detected + */ + bool next_byte_in_range(std::initializer_list ranges) + { + JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); + add(current); + + for (auto range = ranges.begin(); range != ranges.end(); ++range) + { + get(); + if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) + { + add(current); + } + else + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return false; + } + } + + return true; + } + + /*! + @brief scan a string literal + + This function scans a string according to Sect. 7 of RFC 8259. While + scanning, bytes are escaped and copied into buffer token_buffer. Then the + function returns successfully, token_buffer is *not* null-terminated (as it + may contain \0 bytes), and token_buffer.size() is the number of bytes in the + string. + + @return token_type::value_string if string could be successfully scanned, + token_type::parse_error otherwise + + @note In case of errors, variable error_message contains a textual + description. + */ + token_type scan_string() + { + // reset token_buffer (ignore opening quote) + reset(); + + // we entered the function by reading an open quote + JSON_ASSERT(current == '\"'); + + while (true) + { + // get next character + switch (get()) + { + // end of file while parsing string + case std::char_traits::eof(): + { + error_message = "invalid string: missing closing quote"; + return token_type::parse_error; + } + + // closing quote + case '\"': + { + return token_type::value_string; + } + + // escapes + case '\\': + { + switch (get()) + { + // quotation mark + case '\"': + add('\"'); + break; + // reverse solidus + case '\\': + add('\\'); + break; + // solidus + case '/': + add('/'); + break; + // backspace + case 'b': + add('\b'); + break; + // form feed + case 'f': + add('\f'); + break; + // line feed + case 'n': + add('\n'); + break; + // carriage return + case 'r': + add('\r'); + break; + // tab + case 't': + add('\t'); + break; + + // unicode escapes + case 'u': + { + const int codepoint1 = get_codepoint(); + int codepoint = codepoint1; // start with codepoint1 + + if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if code point is a high surrogate + if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) + { + // expect next \uxxxx entry + if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) + { + const int codepoint2 = get_codepoint(); + + if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if codepoint2 is a low surrogate + if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) + { + // overwrite codepoint + codepoint = static_cast( + // high surrogate occupies the most significant 22 bits + (static_cast(codepoint1) << 10u) + // low surrogate occupies the least significant 15 bits + + static_cast(codepoint2) + // there is still the 0xD800, 0xDC00 and 0x10000 noise + // in the result so we have to subtract with: + // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 + - 0x35FDC00u); + } + else + { + error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) + { + error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; + return token_type::parse_error; + } + } + + // result of the above calculation yields a proper codepoint + JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); + + // translate codepoint into bytes + if (codepoint < 0x80) + { + // 1-byte characters: 0xxxxxxx (ASCII) + add(static_cast(codepoint)); + } + else if (codepoint <= 0x7FF) + { + // 2-byte characters: 110xxxxx 10xxxxxx + add(static_cast(0xC0u | (static_cast(codepoint) >> 6u))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + else if (codepoint <= 0xFFFF) + { + // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx + add(static_cast(0xE0u | (static_cast(codepoint) >> 12u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + else + { + // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + add(static_cast(0xF0u | (static_cast(codepoint) >> 18u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 12u) & 0x3Fu))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + + break; + } + + // other characters after escape + default: + error_message = "invalid string: forbidden character after backslash"; + return token_type::parse_error; + } + + break; + } + + // invalid control characters + case 0x00: + { + error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; + return token_type::parse_error; + } + + case 0x01: + { + error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; + return token_type::parse_error; + } + + case 0x02: + { + error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; + return token_type::parse_error; + } + + case 0x03: + { + error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; + return token_type::parse_error; + } + + case 0x04: + { + error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; + return token_type::parse_error; + } + + case 0x05: + { + error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; + return token_type::parse_error; + } + + case 0x06: + { + error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; + return token_type::parse_error; + } + + case 0x07: + { + error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; + return token_type::parse_error; + } + + case 0x08: + { + error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; + return token_type::parse_error; + } + + case 0x09: + { + error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; + return token_type::parse_error; + } + + case 0x0A: + { + error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; + return token_type::parse_error; + } + + case 0x0B: + { + error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; + return token_type::parse_error; + } + + case 0x0C: + { + error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; + return token_type::parse_error; + } + + case 0x0D: + { + error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; + return token_type::parse_error; + } + + case 0x0E: + { + error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; + return token_type::parse_error; + } + + case 0x0F: + { + error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; + return token_type::parse_error; + } + + case 0x10: + { + error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; + return token_type::parse_error; + } + + case 0x11: + { + error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; + return token_type::parse_error; + } + + case 0x12: + { + error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; + return token_type::parse_error; + } + + case 0x13: + { + error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; + return token_type::parse_error; + } + + case 0x14: + { + error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; + return token_type::parse_error; + } + + case 0x15: + { + error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; + return token_type::parse_error; + } + + case 0x16: + { + error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; + return token_type::parse_error; + } + + case 0x17: + { + error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; + return token_type::parse_error; + } + + case 0x18: + { + error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; + return token_type::parse_error; + } + + case 0x19: + { + error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; + return token_type::parse_error; + } + + case 0x1A: + { + error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; + return token_type::parse_error; + } + + case 0x1B: + { + error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; + return token_type::parse_error; + } + + case 0x1C: + { + error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; + return token_type::parse_error; + } + + case 0x1D: + { + error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; + return token_type::parse_error; + } + + case 0x1E: + { + error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; + return token_type::parse_error; + } + + case 0x1F: + { + error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; + return token_type::parse_error; + } + + // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) + case 0x20: + case 0x21: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + { + add(current); + break; + } + + // U+0080..U+07FF: bytes C2..DF 80..BF + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: + { + if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) + { + return token_type::parse_error; + } + break; + } + + // U+0800..U+0FFF: bytes E0 A0..BF 80..BF + case 0xE0: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF + // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xEE: + case 0xEF: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+D000..U+D7FF: bytes ED 80..9F 80..BF + case 0xED: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + case 0xF0: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + case 0xF1: + case 0xF2: + case 0xF3: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + case 0xF4: + { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // remaining bytes (80..C1 and F5..FF) are ill-formed + default: + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return token_type::parse_error; + } + } + } + } + + /*! + * @brief scan a comment + * @return whether comment could be scanned successfully + */ + bool scan_comment() + { + switch (get()) + { + // single-line comments skip input until a newline or EOF is read + case '/': + { + while (true) + { + switch (get()) + { + case '\n': + case '\r': + case std::char_traits::eof(): + case '\0': + return true; + + default: + break; + } + } + } + + // multi-line comments skip input until */ is read + case '*': + { + while (true) + { + switch (get()) + { + case std::char_traits::eof(): + case '\0': + { + error_message = "invalid comment; missing closing '*/'"; + return false; + } + + case '*': + { + switch (get()) + { + case '/': + return true; + + default: + { + unget(); + continue; + } + } + } + + default: + continue; + } + } + } + + // unexpected character after reading '/' + default: + { + error_message = "invalid comment; expecting '/' or '*' after '/'"; + return false; + } + } + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(float& f, const char* str, char** endptr) noexcept + { + f = std::strtof(str, endptr); + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(double& f, const char* str, char** endptr) noexcept + { + f = std::strtod(str, endptr); + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(long double& f, const char* str, char** endptr) noexcept + { + f = std::strtold(str, endptr); + } + + /*! + @brief scan a number literal + + This function scans a string according to Sect. 6 of RFC 8259. + + The function is realized with a deterministic finite state machine derived + from the grammar described in RFC 8259. Starting in state "init", the + input is read and used to determined the next state. Only state "done" + accepts the number. State "error" is a trap state to model errors. In the + table below, "anything" means any character but the ones listed before. + + state | 0 | 1-9 | e E | + | - | . | anything + ---------|----------|----------|----------|---------|---------|----------|----------- + init | zero | any1 | [error] | [error] | minus | [error] | [error] + minus | zero | any1 | [error] | [error] | [error] | [error] | [error] + zero | done | done | exponent | done | done | decimal1 | done + any1 | any1 | any1 | exponent | done | done | decimal1 | done + decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error] + decimal2 | decimal2 | decimal2 | exponent | done | done | done | done + exponent | any2 | any2 | [error] | sign | sign | [error] | [error] + sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] + any2 | any2 | any2 | done | done | done | done | done + + The state machine is realized with one label per state (prefixed with + "scan_number_") and `goto` statements between them. The state machine + contains cycles, but any cycle can be left when EOF is read. Therefore, + the function is guaranteed to terminate. + + During scanning, the read bytes are stored in token_buffer. This string is + then converted to a signed integer, an unsigned integer, or a + floating-point number. + + @return token_type::value_unsigned, token_type::value_integer, or + token_type::value_float if number could be successfully scanned, + token_type::parse_error otherwise + + @note The scanner is independent of the current locale. Internally, the + locale's decimal point is used instead of `.` to work with the + locale-dependent converters. + */ + token_type scan_number() // lgtm [cpp/use-of-goto] + { + // reset token_buffer to store the number's bytes + reset(); + + // the type of the parsed number; initially set to unsigned; will be + // changed if minus sign, decimal point or exponent is read + token_type number_type = token_type::value_unsigned; + + // state (init): we just found out we need to scan a number + switch (current) + { + case '-': + { + add(current); + goto scan_number_minus; + } + + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + // all other characters are rejected outside scan_number() + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + +scan_number_minus: + // state: we just parsed a leading minus sign + number_type = token_type::value_integer; + switch (get()) + { + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + default: + { + error_message = "invalid number; expected digit after '-'"; + return token_type::parse_error; + } + } + +scan_number_zero: + // state: we just parse a zero (maybe with a leading minus sign) + switch (get()) + { + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_any1: + // state: we just parsed a number 0-9 (maybe with a leading minus sign) + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_decimal1: + // state: we just parsed a decimal point + number_type = token_type::value_float; + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + default: + { + error_message = "invalid number; expected digit after '.'"; + return token_type::parse_error; + } + } + +scan_number_decimal2: + // we just parsed at least one number after a decimal point + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_exponent: + // we just parsed an exponent + number_type = token_type::value_float; + switch (get()) + { + case '+': + case '-': + { + add(current); + goto scan_number_sign; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = + "invalid number; expected '+', '-', or digit after exponent"; + return token_type::parse_error; + } + } + +scan_number_sign: + // we just parsed an exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = "invalid number; expected digit after exponent sign"; + return token_type::parse_error; + } + } + +scan_number_any2: + // we just parsed a number after the exponent or exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + goto scan_number_done; + } + +scan_number_done: + // unget the character after the number (we only read it to know that + // we are done scanning a number) + unget(); + + char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + errno = 0; + + // try to parse integers first and fall back to floats + if (number_type == token_type::value_unsigned) + { + const auto x = std::strtoull(token_buffer.data(), &endptr, 10); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_unsigned = static_cast(x); + if (value_unsigned == x) + { + return token_type::value_unsigned; + } + } + } + else if (number_type == token_type::value_integer) + { + const auto x = std::strtoll(token_buffer.data(), &endptr, 10); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_integer = static_cast(x); + if (value_integer == x) + { + return token_type::value_integer; + } + } + } + + // this code is reached if we parse a floating-point number or if an + // integer conversion above failed + strtof(value_float, token_buffer.data(), &endptr); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + return token_type::value_float; + } + + /*! + @param[in] literal_text the literal text to expect + @param[in] length the length of the passed literal text + @param[in] return_type the token type to return on success + */ + JSON_HEDLEY_NON_NULL(2) + token_type scan_literal(const char_type* literal_text, const std::size_t length, + token_type return_type) + { + JSON_ASSERT(std::char_traits::to_char_type(current) == literal_text[0]); + for (std::size_t i = 1; i < length; ++i) + { + if (JSON_HEDLEY_UNLIKELY(std::char_traits::to_char_type(get()) != literal_text[i])) + { + error_message = "invalid literal"; + return token_type::parse_error; + } + } + return return_type; + } + + ///////////////////// + // input management + ///////////////////// + + /// reset token_buffer; current character is beginning of token + void reset() noexcept + { + token_buffer.clear(); + token_string.clear(); + token_string.push_back(std::char_traits::to_char_type(current)); + } + + /* + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a + `std::char_traits::eof()` in that case. Stores the scanned characters + for use in error messages. + + @return character read from the input + */ + char_int_type get() + { + ++position.chars_read_total; + ++position.chars_read_current_line; + + if (next_unget) + { + // just reset the next_unget variable and work with current + next_unget = false; + } + else + { + current = ia.get_character(); + } + + if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) + { + token_string.push_back(std::char_traits::to_char_type(current)); + } + + if (current == '\n') + { + ++position.lines_read; + position.chars_read_current_line = 0; + } + + return current; + } + + /*! + @brief unget current character (read it again on next get) + + We implement unget by setting variable next_unget to true. The input is not + changed - we just simulate ungetting by modifying chars_read_total, + chars_read_current_line, and token_string. The next call to get() will + behave as if the unget character is read again. + */ + void unget() + { + next_unget = true; + + --position.chars_read_total; + + // in case we "unget" a newline, we have to also decrement the lines_read + if (position.chars_read_current_line == 0) + { + if (position.lines_read > 0) + { + --position.lines_read; + } + } + else + { + --position.chars_read_current_line; + } + + if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) + { + JSON_ASSERT(!token_string.empty()); + token_string.pop_back(); + } + } + + /// add a character to token_buffer + void add(char_int_type c) + { + token_buffer.push_back(static_cast(c)); + } + + public: + ///////////////////// + // value getters + ///////////////////// + + /// return integer value + constexpr number_integer_t get_number_integer() const noexcept + { + return value_integer; + } + + /// return unsigned integer value + constexpr number_unsigned_t get_number_unsigned() const noexcept + { + return value_unsigned; + } + + /// return floating-point value + constexpr number_float_t get_number_float() const noexcept + { + return value_float; + } + + /// return current string value (implicitly resets the token; useful only once) + string_t& get_string() + { + return token_buffer; + } + + ///////////////////// + // diagnostics + ///////////////////// + + /// return position of last read token + constexpr position_t get_position() const noexcept + { + return position; + } + + /// return the last read token (for errors only). Will never contain EOF + /// (an arbitrary value that is not a valid char value, often -1), because + /// 255 may legitimately occur. May contain NUL, which should be escaped. + std::string get_token_string() const + { + // escape control characters + std::string result; + for (const auto c : token_string) + { + if (static_cast(c) <= '\x1F') + { + // escape control characters + std::array cs{{}}; + (std::snprintf)(cs.data(), cs.size(), "", static_cast(c)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + result += cs.data(); + } + else + { + // add character as is + result.push_back(static_cast(c)); + } + } + + return result; + } + + /// return syntax error message + JSON_HEDLEY_RETURNS_NON_NULL + constexpr const char* get_error_message() const noexcept + { + return error_message; + } + + ///////////////////// + // actual scanner + ///////////////////// + + /*! + @brief skip the UTF-8 byte order mark + @return true iff there is no BOM or the correct BOM has been skipped + */ + bool skip_bom() + { + if (get() == 0xEF) + { + // check if we completely parse the BOM + return get() == 0xBB && get() == 0xBF; + } + + // the first character is not the beginning of the BOM; unget it to + // process is later + unget(); + return true; + } + + void skip_whitespace() + { + do + { + get(); + } + while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); + } + + token_type scan() + { + // initially, skip the BOM + if (position.chars_read_total == 0 && !skip_bom()) + { + error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; + return token_type::parse_error; + } + + // read next character and ignore whitespace + skip_whitespace(); + + // ignore comments + while (ignore_comments && current == '/') + { + if (!scan_comment()) + { + return token_type::parse_error; + } + + // skip following whitespace + skip_whitespace(); + } + + switch (current) + { + // structural characters + case '[': + return token_type::begin_array; + case ']': + return token_type::end_array; + case '{': + return token_type::begin_object; + case '}': + return token_type::end_object; + case ':': + return token_type::name_separator; + case ',': + return token_type::value_separator; + + // literals + case 't': + { + std::array true_literal = {{char_type('t'), char_type('r'), char_type('u'), char_type('e')}}; + return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); + } + case 'f': + { + std::array false_literal = {{char_type('f'), char_type('a'), char_type('l'), char_type('s'), char_type('e')}}; + return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); + } + case 'n': + { + std::array null_literal = {{char_type('n'), char_type('u'), char_type('l'), char_type('l')}}; + return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); + } + + // string + case '\"': + return scan_string(); + + // number + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return scan_number(); + + // end of input (the null byte is needed when parsing from + // string literals) + case '\0': + case std::char_traits::eof(): + return token_type::end_of_input; + + // error + default: + error_message = "invalid literal"; + return token_type::parse_error; + } + } + + private: + /// input adapter + InputAdapterType ia; + + /// whether comments should be ignored (true) or signaled as errors (false) + const bool ignore_comments = false; + + /// the current character + char_int_type current = std::char_traits::eof(); + + /// whether the next get() call should just return current + bool next_unget = false; + + /// the start position of the current token + position_t position {}; + + /// raw input token string (for error messages) + std::vector token_string {}; + + /// buffer for variable-length tokens (numbers, strings) + string_t token_buffer {}; + + /// a description of occurred lexer errors + const char* error_message = ""; + + // number values + number_integer_t value_integer = 0; + number_unsigned_t value_unsigned = 0; + number_float_t value_float = 0; + + /// the decimal point + const char_int_type decimal_point_char = '.'; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // size_t +#include // declval +#include // string + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +using null_function_t = decltype(std::declval().null()); + +template +using boolean_function_t = + decltype(std::declval().boolean(std::declval())); + +template +using number_integer_function_t = + decltype(std::declval().number_integer(std::declval())); + +template +using number_unsigned_function_t = + decltype(std::declval().number_unsigned(std::declval())); + +template +using number_float_function_t = decltype(std::declval().number_float( + std::declval(), std::declval())); + +template +using string_function_t = + decltype(std::declval().string(std::declval())); + +template +using binary_function_t = + decltype(std::declval().binary(std::declval())); + +template +using start_object_function_t = + decltype(std::declval().start_object(std::declval())); + +template +using key_function_t = + decltype(std::declval().key(std::declval())); + +template +using end_object_function_t = decltype(std::declval().end_object()); + +template +using start_array_function_t = + decltype(std::declval().start_array(std::declval())); + +template +using end_array_function_t = decltype(std::declval().end_array()); + +template +using parse_error_function_t = decltype(std::declval().parse_error( + std::declval(), std::declval(), + std::declval())); + +template +struct is_sax +{ + private: + static_assert(is_basic_json::value, + "BasicJsonType must be of type basic_json<...>"); + + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using exception_t = typename BasicJsonType::exception; + + public: + static constexpr bool value = + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value; +}; + +template +struct is_sax_static_asserts +{ + private: + static_assert(is_basic_json::value, + "BasicJsonType must be of type basic_json<...>"); + + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using exception_t = typename BasicJsonType::exception; + + public: + static_assert(is_detected_exact::value, + "Missing/invalid function: bool null()"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool boolean(bool)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool boolean(bool)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool number_integer(number_integer_t)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool string(string_t&)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool binary(binary_t&)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool start_object(std::size_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool key(string_t&)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool end_object()"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool start_array(std::size_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool end_array()"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool parse_error(std::size_t, const " + "std::string&, const exception&)"); +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ + +/// how to treat CBOR tags +enum class cbor_tag_handler_t +{ + error, ///< throw a parse_error exception in case of a tag + ignore, ///< ignore tags + store ///< store tags as binary type +}; + +/*! +@brief determine system byte order + +@return true if and only if system's byte order is little endian + +@note from https://stackoverflow.com/a/1001328/266378 +*/ +static inline bool little_endianess(int num = 1) noexcept +{ + return *reinterpret_cast(&num) == 1; +} + + +/////////////////// +// binary reader // +/////////////////// + +/*! +@brief deserialization of CBOR, MessagePack, and UBJSON values +*/ +template> +class binary_reader +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using json_sax_t = SAX; + using char_type = typename InputAdapterType::char_type; + using char_int_type = typename std::char_traits::int_type; + + public: + /*! + @brief create a binary reader + + @param[in] adapter input adapter to read from + */ + explicit binary_reader(InputAdapterType&& adapter) noexcept : ia(std::move(adapter)) + { + (void)detail::is_sax_static_asserts {}; + } + + // make class move-only + binary_reader(const binary_reader&) = delete; + binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + binary_reader& operator=(const binary_reader&) = delete; + binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~binary_reader() = default; + + /*! + @param[in] format the binary format to parse + @param[in] sax_ a SAX event processor + @param[in] strict whether to expect the input to be consumed completed + @param[in] tag_handler how to treat CBOR tags + + @return whether parsing was successful + */ + JSON_HEDLEY_NON_NULL(3) + bool sax_parse(const input_format_t format, + json_sax_t* sax_, + const bool strict = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + sax = sax_; + bool result = false; + + switch (format) + { + case input_format_t::bson: + result = parse_bson_internal(); + break; + + case input_format_t::cbor: + result = parse_cbor_internal(true, tag_handler); + break; + + case input_format_t::msgpack: + result = parse_msgpack_internal(); + break; + + case input_format_t::ubjson: + result = parse_ubjson_internal(); + break; + + case input_format_t::json: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + + // strict mode: next byte must be EOF + if (result && strict) + { + if (format == input_format_t::ubjson) + { + get_ignore_noop(); + } + else + { + get(); + } + + if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) + { + return sax->parse_error(chars_read, get_token_string(), + parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType())); + } + } + + return result; + } + + private: + ////////// + // BSON // + ////////// + + /*! + @brief Reads in a BSON-object and passes it to the SAX-parser. + @return whether a valid BSON-value was passed to the SAX parser + */ + bool parse_bson_internal() + { + std::int32_t document_size{}; + get_number(input_format_t::bson, document_size); + + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) + { + return false; + } + + return sax->end_object(); + } + + /*! + @brief Parses a C-style string from the BSON input. + @param[in,out] result A reference to the string variable where the read + string is to be stored. + @return `true` if the \x00-byte indicating the end of the string was + encountered before the EOF; false` indicates an unexpected EOF. + */ + bool get_bson_cstr(string_t& result) + { + auto out = std::back_inserter(result); + while (true) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) + { + return false; + } + if (current == 0x00) + { + return true; + } + *out++ = static_cast(current); + } + } + + /*! + @brief Parses a zero-terminated string of length @a len from the BSON + input. + @param[in] len The length (including the zero-byte at the end) of the + string to be read. + @param[in,out] result A reference to the string variable where the read + string is to be stored. + @tparam NumberType The type of the length @a len + @pre len >= 1 + @return `true` if the string was successfully parsed + */ + template + bool get_bson_string(const NumberType len, string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(len < 1)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), BasicJsonType())); + } + + return get_string(input_format_t::bson, len - static_cast(1), result) && get() != std::char_traits::eof(); + } + + /*! + @brief Parses a byte array input of length @a len from the BSON input. + @param[in] len The length of the byte array to be read. + @param[in,out] result A reference to the binary variable where the read + array is to be stored. + @tparam NumberType The type of the length @a len + @pre len >= 0 + @return `true` if the byte array was successfully parsed + */ + template + bool get_bson_binary(const NumberType len, binary_t& result) + { + if (JSON_HEDLEY_UNLIKELY(len < 0)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), BasicJsonType())); + } + + // All BSON binary values have a subtype + std::uint8_t subtype{}; + get_number(input_format_t::bson, subtype); + result.set_subtype(subtype); + + return get_binary(input_format_t::bson, len, result); + } + + /*! + @brief Read a BSON document element of the given @a element_type. + @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html + @param[in] element_type_parse_position The position in the input stream, + where the `element_type` was read. + @warning Not all BSON element types are supported yet. An unsupported + @a element_type will give rise to a parse_error.114: + Unsupported BSON record type 0x... + @return whether a valid BSON-object/array was passed to the SAX parser + */ + bool parse_bson_element_internal(const char_int_type element_type, + const std::size_t element_type_parse_position) + { + switch (element_type) + { + case 0x01: // double + { + double number{}; + return get_number(input_format_t::bson, number) && sax->number_float(static_cast(number), ""); + } + + case 0x02: // string + { + std::int32_t len{}; + string_t value; + return get_number(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); + } + + case 0x03: // object + { + return parse_bson_internal(); + } + + case 0x04: // array + { + return parse_bson_array(); + } + + case 0x05: // binary + { + std::int32_t len{}; + binary_t value; + return get_number(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); + } + + case 0x08: // boolean + { + return sax->boolean(get() != 0); + } + + case 0x0A: // null + { + return sax->null(); + } + + case 0x10: // int32 + { + std::int32_t value{}; + return get_number(input_format_t::bson, value) && sax->number_integer(value); + } + + case 0x12: // int64 + { + std::int64_t value{}; + return get_number(input_format_t::bson, value) && sax->number_integer(value); + } + + default: // anything else not supported (yet) + { + std::array cr{{}}; + (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), BasicJsonType())); + } + } + } + + /*! + @brief Read a BSON element list (as specified in the BSON-spec) + + The same binary layout is used for objects and arrays, hence it must be + indicated with the argument @a is_array which one is expected + (true --> array, false --> object). + + @param[in] is_array Determines if the element list being read is to be + treated as an object (@a is_array == false), or as an + array (@a is_array == true). + @return whether a valid BSON-object/array was passed to the SAX parser + */ + bool parse_bson_element_list(const bool is_array) + { + string_t key; + + while (auto element_type = get()) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) + { + return false; + } + + const std::size_t element_type_parse_position = chars_read; + if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) + { + return false; + } + + if (!is_array && !sax->key(key)) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) + { + return false; + } + + // get_bson_cstr only appends + key.clear(); + } + + return true; + } + + /*! + @brief Reads an array from the BSON input and passes it to the SAX-parser. + @return whether a valid BSON-array was passed to the SAX parser + */ + bool parse_bson_array() + { + std::int32_t document_size{}; + get_number(input_format_t::bson, document_size); + + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) + { + return false; + } + + return sax->end_array(); + } + + ////////// + // CBOR // + ////////// + + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true) or whether the last read character should + be considered instead (false) + @param[in] tag_handler how CBOR tags should be treated + + @return whether a valid CBOR value was passed to the SAX parser + */ + bool parse_cbor_internal(const bool get_char, + const cbor_tag_handler_t tag_handler) + { + switch (get_char ? get() : current) + { + // EOF + case std::char_traits::eof(): + return unexpect_eof(input_format_t::cbor, "value"); + + // Integer 0x00..0x17 (0..23) + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + return sax->number_unsigned(static_cast(current)); + + case 0x18: // Unsigned integer (one-byte uint8_t follows) + { + std::uint8_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + case 0x19: // Unsigned integer (two-byte uint16_t follows) + { + std::uint16_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + case 0x1A: // Unsigned integer (four-byte uint32_t follows) + { + std::uint32_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + case 0x1B: // Unsigned integer (eight-byte uint64_t follows) + { + std::uint64_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } + + // Negative integer -1-0x00..-1-0x17 (-1..-24) + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + return sax->number_integer(static_cast(0x20 - 1 - current)); + + case 0x38: // Negative integer (one-byte uint8_t follows) + { + std::uint8_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } + + case 0x39: // Negative integer -1-n (two-byte uint16_t follows) + { + std::uint16_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } + + case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) + { + std::uint32_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } + + case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) + { + std::uint64_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) + - static_cast(number)); + } + + // Binary data (0x00..0x17 bytes follow) + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: // Binary data (one-byte uint8_t for n follows) + case 0x59: // Binary data (two-byte uint16_t for n follow) + case 0x5A: // Binary data (four-byte uint32_t for n follow) + case 0x5B: // Binary data (eight-byte uint64_t for n follow) + case 0x5F: // Binary data (indefinite length) + { + binary_t b; + return get_cbor_binary(b) && sax->binary(b); + } + + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + case 0x7F: // UTF-8 string (indefinite length) + { + string_t s; + return get_cbor_string(s) && sax->string(s); + } + + // array (0x00..0x17 data items follow) + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + return get_cbor_array(static_cast(static_cast(current) & 0x1Fu), tag_handler); + + case 0x98: // array (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } + + case 0x99: // array (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } + + case 0x9A: // array (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } + + case 0x9B: // array (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(detail::conditional_static_cast(len), tag_handler); + } + + case 0x9F: // array (indefinite length) + return get_cbor_array(std::size_t(-1), tag_handler); + + // map (0x00..0x17 pairs of data items follow) + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + return get_cbor_object(static_cast(static_cast(current) & 0x1Fu), tag_handler); + + case 0xB8: // map (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } + + case 0xB9: // map (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } + + case 0xBA: // map (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } + + case 0xBB: // map (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(detail::conditional_static_cast(len), tag_handler); + } + + case 0xBF: // map (indefinite length) + return get_cbor_object(std::size_t(-1), tag_handler); + + case 0xC6: // tagged item + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD8: // tagged item (1 bytes follow) + case 0xD9: // tagged item (2 bytes follow) + case 0xDA: // tagged item (4 bytes follow) + case 0xDB: // tagged item (8 bytes follow) + { + switch (tag_handler) + { + case cbor_tag_handler_t::error: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + } + + case cbor_tag_handler_t::ignore: + { + // ignore binary subtype + switch (current) + { + case 0xD8: + { + std::uint8_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + case 0xD9: + { + std::uint16_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + case 0xDA: + { + std::uint32_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + case 0xDB: + { + std::uint64_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); + break; + } + default: + break; + } + return parse_cbor_internal(true, tag_handler); + } + + case cbor_tag_handler_t::store: + { + binary_t b; + // use binary subtype and store in binary container + switch (current) + { + case 0xD8: + { + std::uint8_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xD9: + { + std::uint16_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xDA: + { + std::uint32_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xDB: + { + std::uint64_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + default: + return parse_cbor_internal(true, tag_handler); + } + get(); + return get_cbor_binary(b) && sax->binary(b); + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return false; // LCOV_EXCL_LINE + } + } + + case 0xF4: // false + return sax->boolean(false); + + case 0xF5: // true + return sax->boolean(true); + + case 0xF6: // null + return sax->null(); + + case 0xF9: // Half-Precision Float (two-byte IEEE 754) + { + const auto byte1_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) + { + return false; + } + const auto byte2_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) + { + return false; + } + + const auto byte1 = static_cast(byte1_raw); + const auto byte2 = static_cast(byte2_raw); + + // code from RFC 7049, Appendix D, Figure 3: + // As half-precision floating-point numbers were only added + // to IEEE 754 in 2008, today's programming platforms often + // still only have limited support for them. It is very + // easy to include at least decoding support for them even + // without such support. An example of a small decoder for + // half-precision floating-point numbers in the C language + // is shown in Fig. 3. + const auto half = static_cast((byte1 << 8u) + byte2); + const double val = [&half] + { + const int exp = (half >> 10u) & 0x1Fu; + const unsigned int mant = half & 0x3FFu; + JSON_ASSERT(0 <= exp&& exp <= 32); + JSON_ASSERT(mant <= 1024); + switch (exp) + { + case 0: + return std::ldexp(mant, -24); + case 31: + return (mant == 0) + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); + default: + return std::ldexp(mant + 1024, exp - 25); + } + }(); + return sax->number_float((half & 0x8000u) != 0 + ? static_cast(-val) + : static_cast(val), ""); + } + + case 0xFA: // Single-Precision Float (four-byte IEEE 754) + { + float number{}; + return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + } + + case 0xFB: // Double-Precision Float (eight-byte IEEE 754) + { + double number{}; + return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + } + + default: // anything else (0xFF is handled inside the other types) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + } + } + } + + /*! + @brief reads a CBOR string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + Additionally, CBOR's strings with indefinite lengths are supported. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_cbor_string(string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) + { + return false; + } + + switch (current) + { + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + { + return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } + + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7F: // UTF-8 string (indefinite length) + { + while (get() != 0xFF) + { + string_t chunk; + if (!get_cbor_string(chunk)) + { + return false; + } + result.append(chunk); + } + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), BasicJsonType())); + } + } + } + + /*! + @brief reads a CBOR byte array + + This function first reads starting bytes to determine the expected + byte array length and then copies this number of bytes into the byte array. + Additionally, CBOR's byte arrays with indefinite lengths are supported. + + @param[out] result created byte array + + @return whether byte array creation completed + */ + bool get_cbor_binary(binary_t& result) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) + { + return false; + } + + switch (current) + { + // Binary data (0x00..0x17 bytes follow) + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + { + return get_binary(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } + + case 0x58: // Binary data (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x59: // Binary data (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5A: // Binary data (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5B: // Binary data (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5F: // Binary data (indefinite length) + { + while (get() != 0xFF) + { + binary_t chunk; + if (!get_cbor_binary(chunk)) + { + return false; + } + result.insert(result.end(), chunk.begin(), chunk.end()); + } + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), BasicJsonType())); + } + } + } + + /*! + @param[in] len the length of the array or std::size_t(-1) for an + array of indefinite size + @param[in] tag_handler how CBOR tags should be treated + @return whether array creation completed + */ + bool get_cbor_array(const std::size_t len, + const cbor_tag_handler_t tag_handler) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) + { + return false; + } + + if (len != std::size_t(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) + { + return false; + } + } + } + else + { + while (get() != 0xFF) + { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) + { + return false; + } + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object or std::size_t(-1) for an + object of indefinite size + @param[in] tag_handler how CBOR tags should be treated + @return whether object creation completed + */ + bool get_cbor_object(const std::size_t len, + const cbor_tag_handler_t tag_handler) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) + { + return false; + } + + if (len != 0) + { + string_t key; + if (len != std::size_t(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) + { + return false; + } + key.clear(); + } + } + else + { + while (get() != 0xFF) + { + if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) + { + return false; + } + key.clear(); + } + } + } + + return sax->end_object(); + } + + ///////////// + // MsgPack // + ///////////// + + /*! + @return whether a valid MessagePack value was passed to the SAX parser + */ + bool parse_msgpack_internal() + { + switch (get()) + { + // EOF + case std::char_traits::eof(): + return unexpect_eof(input_format_t::msgpack, "value"); + + // positive fixint + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + return sax->number_unsigned(static_cast(current)); + + // fixmap + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + return get_msgpack_object(static_cast(static_cast(current) & 0x0Fu)); + + // fixarray + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9A: + case 0x9B: + case 0x9C: + case 0x9D: + case 0x9E: + case 0x9F: + return get_msgpack_array(static_cast(static_cast(current) & 0x0Fu)); + + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + case 0xD9: // str 8 + case 0xDA: // str 16 + case 0xDB: // str 32 + { + string_t s; + return get_msgpack_string(s) && sax->string(s); + } + + case 0xC0: // nil + return sax->null(); + + case 0xC2: // false + return sax->boolean(false); + + case 0xC3: // true + return sax->boolean(true); + + case 0xC4: // bin 8 + case 0xC5: // bin 16 + case 0xC6: // bin 32 + case 0xC7: // ext 8 + case 0xC8: // ext 16 + case 0xC9: // ext 32 + case 0xD4: // fixext 1 + case 0xD5: // fixext 2 + case 0xD6: // fixext 4 + case 0xD7: // fixext 8 + case 0xD8: // fixext 16 + { + binary_t b; + return get_msgpack_binary(b) && sax->binary(b); + } + + case 0xCA: // float 32 + { + float number{}; + return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + } + + case 0xCB: // float 64 + { + double number{}; + return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + } + + case 0xCC: // uint 8 + { + std::uint8_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCD: // uint 16 + { + std::uint16_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCE: // uint 32 + { + std::uint32_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCF: // uint 64 + { + std::uint64_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xD0: // int 8 + { + std::int8_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD1: // int 16 + { + std::int16_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD2: // int 32 + { + std::int32_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD3: // int 64 + { + std::int64_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xDC: // array 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); + } + + case 0xDD: // array 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); + } + + case 0xDE: // map 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); + } + + case 0xDF: // map 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); + } + + // negative fixint + case 0xE0: + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + case 0xF0: + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xF7: + case 0xF8: + case 0xF9: + case 0xFA: + case 0xFB: + case 0xFC: + case 0xFD: + case 0xFE: + case 0xFF: + return sax->number_integer(static_cast(current)); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + } + } + } + + /*! + @brief reads a MessagePack string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_msgpack_string(string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) + { + return false; + } + + switch (current) + { + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + { + return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result); + } + + case 0xD9: // str 8 + { + std::uint8_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + case 0xDA: // str 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + case 0xDB: // str 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), BasicJsonType())); + } + } + } + + /*! + @brief reads a MessagePack byte array + + This function first reads starting bytes to determine the expected + byte array length and then copies this number of bytes into a byte array. + + @param[out] result created byte array + + @return whether byte array creation completed + */ + bool get_msgpack_binary(binary_t& result) + { + // helper function to set the subtype + auto assign_and_return_true = [&result](std::int8_t subtype) + { + result.set_subtype(static_cast(subtype)); + return true; + }; + + switch (current) + { + case 0xC4: // bin 8 + { + std::uint8_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC5: // bin 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC6: // bin 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC7: // ext 8 + { + std::uint8_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xC8: // ext 16 + { + std::uint16_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xC9: // ext 32 + { + std::uint32_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xD4: // fixext 1 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 1, result) && + assign_and_return_true(subtype); + } + + case 0xD5: // fixext 2 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 2, result) && + assign_and_return_true(subtype); + } + + case 0xD6: // fixext 4 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 4, result) && + assign_and_return_true(subtype); + } + + case 0xD7: // fixext 8 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 8, result) && + assign_and_return_true(subtype); + } + + case 0xD8: // fixext 16 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 16, result) && + assign_and_return_true(subtype); + } + + default: // LCOV_EXCL_LINE + return false; // LCOV_EXCL_LINE + } + } + + /*! + @param[in] len the length of the array + @return whether array creation completed + */ + bool get_msgpack_array(const std::size_t len) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) + { + return false; + } + + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) + { + return false; + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object + @return whether object creation completed + */ + bool get_msgpack_object(const std::size_t len) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) + { + return false; + } + + string_t key; + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) + { + return false; + } + key.clear(); + } + + return sax->end_object(); + } + + //////////// + // UBJSON // + //////////// + + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether a valid UBJSON value was passed to the SAX parser + */ + bool parse_ubjson_internal(const bool get_char = true) + { + return get_ubjson_value(get_char ? get_ignore_noop() : current); + } + + /*! + @brief reads a UBJSON string + + This function is either called after reading the 'S' byte explicitly + indicating a string, or in case of an object key where the 'S' byte can be + left out. + + @param[out] result created string + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether string creation completed + */ + bool get_ubjson_string(string_t& result, const bool get_char = true) + { + if (get_char) + { + get(); // TODO(niels): may we ignore N here? + } + + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) + { + return false; + } + + switch (current) + { + case 'U': + { + std::uint8_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'i': + { + std::int8_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'I': + { + std::int16_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'l': + { + std::int32_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'L': + { + std::int64_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + default: + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), BasicJsonType())); + } + } + + /*! + @param[out] result determined size + @return whether size determination completed + */ + bool get_ubjson_size_value(std::size_t& result) + { + switch (get_ignore_noop()) + { + case 'U': + { + std::uint8_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'i': + { + std::int8_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char + return true; + } + + case 'I': + { + std::int16_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'l': + { + std::int32_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'L': + { + std::int64_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), BasicJsonType())); + } + } + } + + /*! + @brief determine the type and size for a container + + In the optimized UBJSON format, a type and a size can be provided to allow + for a more compact representation. + + @param[out] result pair of the size and the type + + @return whether pair creation completed + */ + bool get_ubjson_size_type(std::pair& result) + { + result.first = string_t::npos; // size + result.second = 0; // type + + get_ignore_noop(); + + if (current == '$') + { + result.second = get(); // must not ignore 'N', because 'N' maybe the type + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type"))) + { + return false; + } + + get_ignore_noop(); + if (JSON_HEDLEY_UNLIKELY(current != '#')) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) + { + return false; + } + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), BasicJsonType())); + } + + return get_ubjson_size_value(result.first); + } + + if (current == '#') + { + return get_ubjson_size_value(result.first); + } + + return true; + } + + /*! + @param prefix the previously read or set type prefix + @return whether value creation completed + */ + bool get_ubjson_value(const char_int_type prefix) + { + switch (prefix) + { + case std::char_traits::eof(): // EOF + return unexpect_eof(input_format_t::ubjson, "value"); + + case 'T': // true + return sax->boolean(true); + case 'F': // false + return sax->boolean(false); + + case 'Z': // null + return sax->null(); + + case 'U': + { + std::uint8_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number); + } + + case 'i': + { + std::int8_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } + + case 'I': + { + std::int16_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } + + case 'l': + { + std::int32_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } + + case 'L': + { + std::int64_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } + + case 'd': + { + float number{}; + return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); + } + + case 'D': + { + double number{}; + return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); + } + + case 'H': + { + return get_ubjson_high_precision_number(); + } + + case 'C': // char + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char"))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(current > 127)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), BasicJsonType())); + } + string_t s(1, static_cast(current)); + return sax->string(s); + } + + case 'S': // string + { + string_t s; + return get_ubjson_string(s) && sax->string(s); + } + + case '[': // array + return get_ubjson_array(); + + case '{': // object + return get_ubjson_object(); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + } + } + } + + /*! + @return whether array creation completed + */ + bool get_ubjson_array() + { + std::pair size_and_type; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) + { + return false; + } + + if (size_and_type.first != string_t::npos) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + if (size_and_type.second != 'N') + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) + { + return false; + } + } + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) + { + return false; + } + } + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) + { + return false; + } + + while (current != ']') + { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) + { + return false; + } + get_ignore_noop(); + } + } + + return sax->end_array(); + } + + /*! + @return whether object creation completed + */ + bool get_ubjson_object() + { + std::pair size_and_type; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) + { + return false; + } + + string_t key; + if (size_and_type.first != string_t::npos) + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) + { + return false; + } + key.clear(); + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) + { + return false; + } + key.clear(); + } + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) + { + return false; + } + + while (current != '}') + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) + { + return false; + } + get_ignore_noop(); + key.clear(); + } + } + + return sax->end_object(); + } + + // Note, no reader for UBJSON binary types is implemented because they do + // not exist + + bool get_ubjson_high_precision_number() + { + // get size of following number string + std::size_t size{}; + auto res = get_ubjson_size_value(size); + if (JSON_HEDLEY_UNLIKELY(!res)) + { + return res; + } + + // get number string + std::vector number_vector; + for (std::size_t i = 0; i < size; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number"))) + { + return false; + } + number_vector.push_back(static_cast(current)); + } + + // parse number string + using ia_type = decltype(detail::input_adapter(number_vector)); + auto number_lexer = detail::lexer(detail::input_adapter(number_vector), false); + const auto result_number = number_lexer.scan(); + const auto number_string = number_lexer.get_token_string(); + const auto result_remainder = number_lexer.scan(); + + using token_type = typename detail::lexer_base::token_type; + + if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) + { + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType())); + } + + switch (result_number) + { + case token_type::value_integer: + return sax->number_integer(number_lexer.get_number_integer()); + case token_type::value_unsigned: + return sax->number_unsigned(number_lexer.get_number_unsigned()); + case token_type::value_float: + return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); + case token_type::uninitialized: + case token_type::literal_true: + case token_type::literal_false: + case token_type::literal_null: + case token_type::value_string: + case token_type::begin_array: + case token_type::begin_object: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::parse_error: + case token_type::end_of_input: + case token_type::literal_or_value: + default: + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType())); + } + } + + /////////////////////// + // Utility functions // + /////////////////////// + + /*! + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a -'ve valued + `std::char_traits::eof()` in that case. + + @return character read from the input + */ + char_int_type get() + { + ++chars_read; + return current = ia.get_character(); + } + + /*! + @return character read from the input after ignoring all 'N' entries + */ + char_int_type get_ignore_noop() + { + do + { + get(); + } + while (current == 'N'); + + return current; + } + + /* + @brief read a number from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[out] result number of type @a NumberType + + @return whether conversion completed + + @note This function needs to respect the system's endianess, because + bytes in CBOR, MessagePack, and UBJSON are stored in network order + (big endian) and therefore need reordering on little endian systems. + */ + template + bool get_number(const input_format_t format, NumberType& result) + { + // step 1: read input into array with system's byte order + std::array vec{}; + for (std::size_t i = 0; i < sizeof(NumberType); ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) + { + return false; + } + + // reverse byte order prior to conversion if necessary + if (is_little_endian != InputIsLittleEndian) + { + vec[sizeof(NumberType) - i - 1] = static_cast(current); + } + else + { + vec[i] = static_cast(current); // LCOV_EXCL_LINE + } + } + + // step 2: convert array into number of type T and return + std::memcpy(&result, vec.data(), sizeof(NumberType)); + return true; + } + + /*! + @brief create a string by reading characters from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[in] len number of characters to read + @param[out] result string created by reading @a len bytes + + @return whether string creation completed + + @note We can not reserve @a len bytes for the result, because @a len + may be too large. Usually, @ref unexpect_eof() detects the end of + the input before we run out of string memory. + */ + template + bool get_string(const input_format_t format, + const NumberType len, + string_t& result) + { + bool success = true; + for (NumberType i = 0; i < len; i++) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) + { + success = false; + break; + } + result.push_back(static_cast(current)); + } + return success; + } + + /*! + @brief create a byte array by reading bytes from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[in] len number of bytes to read + @param[out] result byte array created by reading @a len bytes + + @return whether byte array creation completed + + @note We can not reserve @a len bytes for the result, because @a len + may be too large. Usually, @ref unexpect_eof() detects the end of + the input before we run out of memory. + */ + template + bool get_binary(const input_format_t format, + const NumberType len, + binary_t& result) + { + bool success = true; + for (NumberType i = 0; i < len; i++) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) + { + success = false; + break; + } + result.push_back(static_cast(current)); + } + return success; + } + + /*! + @param[in] format the current format (for diagnostics) + @param[in] context further context information (for diagnostics) + @return whether the last read character is not EOF + */ + JSON_HEDLEY_NON_NULL(3) + bool unexpect_eof(const input_format_t format, const char* context) const + { + if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof())) + { + return sax->parse_error(chars_read, "", + parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType())); + } + return true; + } + + /*! + @return a string representation of the last read byte + */ + std::string get_token_string() const + { + std::array cr{{}}; + (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(current)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + return std::string{cr.data()}; + } + + /*! + @param[in] format the current format + @param[in] detail a detailed error message + @param[in] context further context information + @return a message string to use in the parse_error exceptions + */ + std::string exception_message(const input_format_t format, + const std::string& detail, + const std::string& context) const + { + std::string error_msg = "syntax error while parsing "; + + switch (format) + { + case input_format_t::cbor: + error_msg += "CBOR"; + break; + + case input_format_t::msgpack: + error_msg += "MessagePack"; + break; + + case input_format_t::ubjson: + error_msg += "UBJSON"; + break; + + case input_format_t::bson: + error_msg += "BSON"; + break; + + case input_format_t::json: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + + return error_msg + " " + context + ": " + detail; + } + + private: + /// input adapter + InputAdapterType ia; + + /// the current character + char_int_type current = std::char_traits::eof(); + + /// the number of characters read + std::size_t chars_read = 0; + + /// whether we can assume little endianess + const bool is_little_endian = little_endianess(); + + /// the SAX parser + json_sax_t* sax = nullptr; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + + +#include // isfinite +#include // uint8_t +#include // function +#include // string +#include // move +#include // vector + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +//////////// +// parser // +//////////// + +enum class parse_event_t : std::uint8_t +{ + /// the parser read `{` and started to process a JSON object + object_start, + /// the parser read `}` and finished processing a JSON object + object_end, + /// the parser read `[` and started to process a JSON array + array_start, + /// the parser read `]` and finished processing a JSON array + array_end, + /// the parser read a key of a value in an object + key, + /// the parser finished reading a JSON value + value +}; + +template +using parser_callback_t = + std::function; + +/*! +@brief syntax analysis + +This class implements a recursive descent parser. +*/ +template +class parser +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using lexer_t = lexer; + using token_type = typename lexer_t::token_type; + + public: + /// a parser reading from an input adapter + explicit parser(InputAdapterType&& adapter, + const parser_callback_t cb = nullptr, + const bool allow_exceptions_ = true, + const bool skip_comments = false) + : callback(cb) + , m_lexer(std::move(adapter), skip_comments) + , allow_exceptions(allow_exceptions_) + { + // read first token + get_token(); + } + + /*! + @brief public parser interface + + @param[in] strict whether to expect the last token to be EOF + @param[in,out] result parsed JSON value + + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + */ + void parse(const bool strict, BasicJsonType& result) + { + if (callback) + { + json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); + sax_parse_internal(&sdp); + + // in strict mode, input must be completely read + if (strict && (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"), BasicJsonType())); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + + // set top-level value to null if it was discarded by the callback + // function + if (result.is_discarded()) + { + result = nullptr; + } + } + else + { + json_sax_dom_parser sdp(result, allow_exceptions); + sax_parse_internal(&sdp); + + // in strict mode, input must be completely read + if (strict && (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType())); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + } + + result.assert_invariant(); + } + + /*! + @brief public accept interface + + @param[in] strict whether to expect the last token to be EOF + @return whether the input is a proper JSON text + */ + bool accept(const bool strict = true) + { + json_sax_acceptor sax_acceptor; + return sax_parse(&sax_acceptor, strict); + } + + template + JSON_HEDLEY_NON_NULL(2) + bool sax_parse(SAX* sax, const bool strict = true) + { + (void)detail::is_sax_static_asserts {}; + const bool result = sax_parse_internal(sax); + + // strict mode: next byte must be EOF + if (result && strict && (get_token() != token_type::end_of_input)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType())); + } + + return result; + } + + private: + template + JSON_HEDLEY_NON_NULL(2) + bool sax_parse_internal(SAX* sax) + { + // stack to remember the hierarchy of structured values we are parsing + // true = array; false = object + std::vector states; + // value to avoid a goto (see comment where set to true) + bool skip_to_state_evaluation = false; + + while (true) + { + if (!skip_to_state_evaluation) + { + // invariant: get_token() was called before each iteration + switch (last_token) + { + case token_type::begin_object: + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) + { + return false; + } + + // closing } -> we are done + if (get_token() == token_type::end_object) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) + { + return false; + } + break; + } + + // parse key + if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType())); + } + if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) + { + return false; + } + + // parse separator (:) + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType())); + } + + // remember we are now inside an object + states.push_back(false); + + // parse values + get_token(); + continue; + } + + case token_type::begin_array: + { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) + { + return false; + } + + // closing ] -> we are done + if (get_token() == token_type::end_array) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) + { + return false; + } + break; + } + + // remember we are now inside an array + states.push_back(true); + + // parse values (no need to call get_token) + continue; + } + + case token_type::value_float: + { + const auto res = m_lexer.get_number_float(); + + if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", BasicJsonType())); + } + + if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) + { + return false; + } + + break; + } + + case token_type::literal_false: + { + if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) + { + return false; + } + break; + } + + case token_type::literal_null: + { + if (JSON_HEDLEY_UNLIKELY(!sax->null())) + { + return false; + } + break; + } + + case token_type::literal_true: + { + if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) + { + return false; + } + break; + } + + case token_type::value_integer: + { + if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) + { + return false; + } + break; + } + + case token_type::value_string: + { + if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) + { + return false; + } + break; + } + + case token_type::value_unsigned: + { + if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) + { + return false; + } + break; + } + + case token_type::parse_error: + { + // using "uninitialized" to avoid "expected" message + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType())); + } + + case token_type::uninitialized: + case token_type::end_array: + case token_type::end_object: + case token_type::name_separator: + case token_type::value_separator: + case token_type::end_of_input: + case token_type::literal_or_value: + default: // the last token was unexpected + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), BasicJsonType())); + } + } + } + else + { + skip_to_state_evaluation = false; + } + + // we reached this line after we successfully parsed a value + if (states.empty()) + { + // empty stack: we reached the end of the hierarchy: done + return true; + } + + if (states.back()) // array + { + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse a new value + get_token(); + continue; + } + + // closing ] + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) + { + return false; + } + + // We are done with this array. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + JSON_ASSERT(!states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), BasicJsonType())); + } + + // states.back() is false -> object + + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse key + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType())); + } + + if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) + { + return false; + } + + // parse separator (:) + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType())); + } + + // parse values + get_token(); + continue; + } + + // closing } + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) + { + if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) + { + return false; + } + + // We are done with this object. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + JSON_ASSERT(!states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), BasicJsonType())); + } + } + + /// get next token from lexer + token_type get_token() + { + return last_token = m_lexer.scan(); + } + + std::string exception_message(const token_type expected, const std::string& context) + { + std::string error_msg = "syntax error "; + + if (!context.empty()) + { + error_msg += "while parsing " + context + " "; + } + + error_msg += "- "; + + if (last_token == token_type::parse_error) + { + error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + + m_lexer.get_token_string() + "'"; + } + else + { + error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token)); + } + + if (expected != token_type::uninitialized) + { + error_msg += "; expected " + std::string(lexer_t::token_type_name(expected)); + } + + return error_msg; + } + + private: + /// callback function + const parser_callback_t callback = nullptr; + /// the type of the last read token + token_type last_token = token_type::uninitialized; + /// the lexer + lexer_t m_lexer; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; + +} // namespace detail +} // namespace nlohmann + +// #include + + +// #include + + +#include // ptrdiff_t +#include // numeric_limits + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/* +@brief an iterator for primitive JSON types + +This class models an iterator for primitive JSON types (boolean, number, +string). It's only purpose is to allow the iterator/const_iterator classes +to "iterate" over primitive values. Internally, the iterator is modeled by +a `difference_type` variable. Value begin_value (`0`) models the begin, +end_value (`1`) models past the end. +*/ +class primitive_iterator_t +{ + private: + using difference_type = std::ptrdiff_t; + static constexpr difference_type begin_value = 0; + static constexpr difference_type end_value = begin_value + 1; + + JSON_PRIVATE_UNLESS_TESTED: + /// iterator as signed integer type + difference_type m_it = (std::numeric_limits::min)(); + + public: + constexpr difference_type get_value() const noexcept + { + return m_it; + } + + /// set iterator to a defined beginning + void set_begin() noexcept + { + m_it = begin_value; + } + + /// set iterator to a defined past the end + void set_end() noexcept + { + m_it = end_value; + } + + /// return whether the iterator can be dereferenced + constexpr bool is_begin() const noexcept + { + return m_it == begin_value; + } + + /// return whether the iterator is at end + constexpr bool is_end() const noexcept + { + return m_it == end_value; + } + + friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it == rhs.m_it; + } + + friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it < rhs.m_it; + } + + primitive_iterator_t operator+(difference_type n) noexcept + { + auto result = *this; + result += n; + return result; + } + + friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it - rhs.m_it; + } + + primitive_iterator_t& operator++() noexcept + { + ++m_it; + return *this; + } + + primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type) + { + auto result = *this; + ++m_it; + return result; + } + + primitive_iterator_t& operator--() noexcept + { + --m_it; + return *this; + } + + primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type) + { + auto result = *this; + --m_it; + return result; + } + + primitive_iterator_t& operator+=(difference_type n) noexcept + { + m_it += n; + return *this; + } + + primitive_iterator_t& operator-=(difference_type n) noexcept + { + m_it -= n; + return *this; + } +}; +} // namespace detail +} // namespace nlohmann + + +namespace nlohmann +{ +namespace detail +{ +/*! +@brief an iterator value + +@note This structure could easily be a union, but MSVC currently does not allow +unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. +*/ +template struct internal_iterator +{ + /// iterator for JSON objects + typename BasicJsonType::object_t::iterator object_iterator {}; + /// iterator for JSON arrays + typename BasicJsonType::array_t::iterator array_iterator {}; + /// generic iterator for all other types + primitive_iterator_t primitive_iterator {}; +}; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next +#include // conditional, is_const, remove_const + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +// forward declare, to be able to friend it later on +template class iteration_proxy; +template class iteration_proxy_value; + +/*! +@brief a template for a bidirectional iterator for the @ref basic_json class +This class implements a both iterators (iterator and const_iterator) for the +@ref basic_json class. +@note An iterator is called *initialized* when a pointer to a JSON value has + been set (e.g., by a constructor or a copy assignment). If the iterator is + default-constructed, it is *uninitialized* and most methods are undefined. + **The library uses assertions to detect calls on uninitialized iterators.** +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). +@since version 1.0.0, simplified in version 2.0.9, change to bidirectional + iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) +*/ +template +class iter_impl +{ + /// the iterator with BasicJsonType of different const-ness + using other_iter_impl = iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; + /// allow basic_json to access private members + friend other_iter_impl; + friend BasicJsonType; + friend iteration_proxy; + friend iteration_proxy_value; + + using object_t = typename BasicJsonType::object_t; + using array_t = typename BasicJsonType::array_t; + // make sure BasicJsonType is basic_json or const basic_json + static_assert(is_basic_json::type>::value, + "iter_impl only accepts (const) basic_json"); + + public: + + /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. + /// The C++ Standard has never required user-defined iterators to derive from std::iterator. + /// A user-defined iterator should provide publicly accessible typedefs named + /// iterator_category, value_type, difference_type, pointer, and reference. + /// Note that value_type is required to be non-const, even for constant iterators. + using iterator_category = std::bidirectional_iterator_tag; + + /// the type of the values when the iterator is dereferenced + using value_type = typename BasicJsonType::value_type; + /// a type to represent differences between iterators + using difference_type = typename BasicJsonType::difference_type; + /// defines a pointer to the type iterated over (value_type) + using pointer = typename std::conditional::value, + typename BasicJsonType::const_pointer, + typename BasicJsonType::pointer>::type; + /// defines a reference to the type iterated over (value_type) + using reference = + typename std::conditional::value, + typename BasicJsonType::const_reference, + typename BasicJsonType::reference>::type; + + iter_impl() = default; + ~iter_impl() = default; + iter_impl(iter_impl&&) noexcept = default; + iter_impl& operator=(iter_impl&&) noexcept = default; + + /*! + @brief constructor for a given JSON instance + @param[in] object pointer to a JSON object for this iterator + @pre object != nullptr + @post The iterator is initialized; i.e. `m_object != nullptr`. + */ + explicit iter_impl(pointer object) noexcept : m_object(object) + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = typename object_t::iterator(); + break; + } + + case value_t::array: + { + m_it.array_iterator = typename array_t::iterator(); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator = primitive_iterator_t(); + break; + } + } + } + + /*! + @note The conventional copy constructor and copy assignment are implicitly + defined. Combined with the following converting constructor and + assignment, they support: (1) copy from iterator to iterator, (2) + copy from const iterator to const iterator, and (3) conversion from + iterator to const iterator. However conversion from const iterator + to iterator is not defined. + */ + + /*! + @brief const copy constructor + @param[in] other const iterator to copy from + @note This copy constructor had to be defined explicitly to circumvent a bug + occurring on msvc v19.0 compiler (VS 2015) debug build. For more + information refer to: https://github.com/nlohmann/json/issues/1608 + */ + iter_impl(const iter_impl& other) noexcept + : m_object(other.m_object), m_it(other.m_it) + {} + + /*! + @brief converting assignment + @param[in] other const iterator to copy from + @return const/non-const iterator + @note It is not checked whether @a other is initialized. + */ + iter_impl& operator=(const iter_impl& other) noexcept + { + if (&other != this) + { + m_object = other.m_object; + m_it = other.m_it; + } + return *this; + } + + /*! + @brief converting constructor + @param[in] other non-const iterator to copy from + @note It is not checked whether @a other is initialized. + */ + iter_impl(const iter_impl::type>& other) noexcept + : m_object(other.m_object), m_it(other.m_it) + {} + + /*! + @brief converting assignment + @param[in] other non-const iterator to copy from + @return const/non-const iterator + @note It is not checked whether @a other is initialized. + */ + iter_impl& operator=(const iter_impl::type>& other) noexcept // NOLINT(cert-oop54-cpp) + { + m_object = other.m_object; + m_it = other.m_it; + return *this; + } + + JSON_PRIVATE_UNLESS_TESTED: + /*! + @brief set the iterator to the first value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_begin() noexcept + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_value.object->begin(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_value.array->begin(); + break; + } + + case value_t::null: + { + // set to end so begin()==end() is true: null is empty + m_it.primitive_iterator.set_end(); + break; + } + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator.set_begin(); + break; + } + } + } + + /*! + @brief set the iterator past the last value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_end() noexcept + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_value.object->end(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_value.array->end(); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator.set_end(); + break; + } + } + } + + public: + /*! + @brief return a reference to the value pointed to by the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator*() const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); + return m_it.object_iterator->second; + } + + case value_t::array: + { + JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); + return *m_it.array_iterator; + } + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + } + } + } + + /*! + @brief dereference the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + pointer operator->() const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); + return &(m_it.object_iterator->second); + } + + case value_t::array: + { + JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); + return &*m_it.array_iterator; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) + { + return m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + } + } + } + + /*! + @brief post-increment (it++) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl const operator++(int) // NOLINT(readability-const-return-type) + { + auto result = *this; + ++(*this); + return result; + } + + /*! + @brief pre-increment (++it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator++() + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, 1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, 1); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + ++m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief post-decrement (it--) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl const operator--(int) // NOLINT(readability-const-return-type) + { + auto result = *this; + --(*this); + return result; + } + + /*! + @brief pre-decrement (--it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator--() + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, -1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, -1); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + --m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief comparison: equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > + bool operator==(const IterImpl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); + } + + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + return (m_it.object_iterator == other.m_it.object_iterator); + + case value_t::array: + return (m_it.array_iterator == other.m_it.array_iterator); + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return (m_it.primitive_iterator == other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: not equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > + bool operator!=(const IterImpl& other) const + { + return !operator==(other); + } + + /*! + @brief comparison: smaller + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<(const iter_impl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); + } + + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object)); + + case value_t::array: + return (m_it.array_iterator < other.m_it.array_iterator); + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return (m_it.primitive_iterator < other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: less than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<=(const iter_impl& other) const + { + return !other.operator < (*this); + } + + /*! + @brief comparison: greater than + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>(const iter_impl& other) const + { + return !operator<=(other); + } + + /*! + @brief comparison: greater than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>=(const iter_impl& other) const + { + return !operator<(other); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator+=(difference_type i) + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); + + case value_t::array: + { + std::advance(m_it.array_iterator, i); + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + m_it.primitive_iterator += i; + break; + } + } + + return *this; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator-=(difference_type i) + { + return operator+=(-i); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator+(difference_type i) const + { + auto result = *this; + result += i; + return result; + } + + /*! + @brief addition of distance and iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + friend iter_impl operator+(difference_type i, const iter_impl& it) + { + auto result = it; + result += i; + return result; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator-(difference_type i) const + { + auto result = *this; + result -= i; + return result; + } + + /*! + @brief return difference + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + difference_type operator-(const iter_impl& other) const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); + + case value_t::array: + return m_it.array_iterator - other.m_it.array_iterator; + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + return m_it.primitive_iterator - other.m_it.primitive_iterator; + } + } + + /*! + @brief access to successor + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator[](difference_type n) const + { + JSON_ASSERT(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object)); + + case value_t::array: + return *std::next(m_it.array_iterator, n); + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + } + } + } + + /*! + @brief return the key of an object iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + const typename object_t::key_type& key() const + { + JSON_ASSERT(m_object != nullptr); + + if (JSON_HEDLEY_LIKELY(m_object->is_object())) + { + return m_it.object_iterator->first; + } + + JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object)); + } + + /*! + @brief return the value of an iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference value() const + { + return operator*(); + } + + JSON_PRIVATE_UNLESS_TESTED: + /// associated JSON instance + pointer m_object = nullptr; + /// the actual iterator of the associated instance + internal_iterator::type> m_it {}; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // ptrdiff_t +#include // reverse_iterator +#include // declval + +namespace nlohmann +{ +namespace detail +{ +////////////////////// +// reverse_iterator // +////////////////////// + +/*! +@brief a template for a reverse iterator class + +@tparam Base the base iterator type to reverse. Valid types are @ref +iterator (to create @ref reverse_iterator) and @ref const_iterator (to +create @ref const_reverse_iterator). + +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). +- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): + It is possible to write to the pointed-to element (only if @a Base is + @ref iterator). + +@since version 1.0.0 +*/ +template +class json_reverse_iterator : public std::reverse_iterator +{ + public: + using difference_type = std::ptrdiff_t; + /// shortcut to the reverse iterator adapter + using base_iterator = std::reverse_iterator; + /// the reference type for the pointed-to element + using reference = typename Base::reference; + + /// create reverse iterator from iterator + explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept + : base_iterator(it) {} + + /// create reverse iterator from base class + explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} + + /// post-increment (it++) + json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type) + { + return static_cast(base_iterator::operator++(1)); + } + + /// pre-increment (++it) + json_reverse_iterator& operator++() + { + return static_cast(base_iterator::operator++()); + } + + /// post-decrement (it--) + json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type) + { + return static_cast(base_iterator::operator--(1)); + } + + /// pre-decrement (--it) + json_reverse_iterator& operator--() + { + return static_cast(base_iterator::operator--()); + } + + /// add to iterator + json_reverse_iterator& operator+=(difference_type i) + { + return static_cast(base_iterator::operator+=(i)); + } + + /// add to iterator + json_reverse_iterator operator+(difference_type i) const + { + return static_cast(base_iterator::operator+(i)); + } + + /// subtract from iterator + json_reverse_iterator operator-(difference_type i) const + { + return static_cast(base_iterator::operator-(i)); + } + + /// return difference + difference_type operator-(const json_reverse_iterator& other) const + { + return base_iterator(*this) - base_iterator(other); + } + + /// access to successor + reference operator[](difference_type n) const + { + return *(this->operator+(n)); + } + + /// return the key of an object iterator + auto key() const -> decltype(std::declval().key()) + { + auto it = --this->base(); + return it.key(); + } + + /// return the value of an iterator + reference value() const + { + auto it = --this->base(); + return it.operator * (); + } +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // all_of +#include // isdigit +#include // max +#include // accumulate +#include // string +#include // move +#include // vector + +// #include + +// #include + +// #include + +// #include + + +namespace nlohmann +{ +template +class json_pointer +{ + // allow basic_json to access private members + NLOHMANN_BASIC_JSON_TPL_DECLARATION + friend class basic_json; + + public: + /*! + @brief create JSON pointer + + Create a JSON pointer according to the syntax described in + [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3). + + @param[in] s string representing the JSON pointer; if omitted, the empty + string is assumed which references the whole JSON value + + @throw parse_error.107 if the given JSON pointer @a s is nonempty and does + not begin with a slash (`/`); see example below + + @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is + not followed by `0` (representing `~`) or `1` (representing `/`); see + example below + + @liveexample{The example shows the construction several valid JSON pointers + as well as the exceptional behavior.,json_pointer} + + @since version 2.0.0 + */ + explicit json_pointer(const std::string& s = "") + : reference_tokens(split(s)) + {} + + /*! + @brief return a string representation of the JSON pointer + + @invariant For each JSON pointer `ptr`, it holds: + @code {.cpp} + ptr == json_pointer(ptr.to_string()); + @endcode + + @return a string representation of the JSON pointer + + @liveexample{The example shows the result of `to_string`.,json_pointer__to_string} + + @since version 2.0.0 + */ + std::string to_string() const + { + return std::accumulate(reference_tokens.begin(), reference_tokens.end(), + std::string{}, + [](const std::string & a, const std::string & b) + { + return a + "/" + detail::escape(b); + }); + } + + /// @copydoc to_string() + operator std::string() const + { + return to_string(); + } + + /*! + @brief append another JSON pointer at the end of this JSON pointer + + @param[in] ptr JSON pointer to append + @return JSON pointer with @a ptr appended + + @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} + + @complexity Linear in the length of @a ptr. + + @sa see @ref operator/=(std::string) to append a reference token + @sa see @ref operator/=(std::size_t) to append an array index + @sa see @ref operator/(const json_pointer&, const json_pointer&) for a binary operator + + @since version 3.6.0 + */ + json_pointer& operator/=(const json_pointer& ptr) + { + reference_tokens.insert(reference_tokens.end(), + ptr.reference_tokens.begin(), + ptr.reference_tokens.end()); + return *this; + } + + /*! + @brief append an unescaped reference token at the end of this JSON pointer + + @param[in] token reference token to append + @return JSON pointer with @a token appended without escaping @a token + + @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} + + @complexity Amortized constant. + + @sa see @ref operator/=(const json_pointer&) to append a JSON pointer + @sa see @ref operator/=(std::size_t) to append an array index + @sa see @ref operator/(const json_pointer&, std::size_t) for a binary operator + + @since version 3.6.0 + */ + json_pointer& operator/=(std::string token) + { + push_back(std::move(token)); + return *this; + } + + /*! + @brief append an array index at the end of this JSON pointer + + @param[in] array_idx array index to append + @return JSON pointer with @a array_idx appended + + @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} + + @complexity Amortized constant. + + @sa see @ref operator/=(const json_pointer&) to append a JSON pointer + @sa see @ref operator/=(std::string) to append a reference token + @sa see @ref operator/(const json_pointer&, std::string) for a binary operator + + @since version 3.6.0 + */ + json_pointer& operator/=(std::size_t array_idx) + { + return *this /= std::to_string(array_idx); + } + + /*! + @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer + + @param[in] lhs JSON pointer + @param[in] rhs JSON pointer + @return a new JSON pointer with @a rhs appended to @a lhs + + @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} + + @complexity Linear in the length of @a lhs and @a rhs. + + @sa see @ref operator/=(const json_pointer&) to append a JSON pointer + + @since version 3.6.0 + */ + friend json_pointer operator/(const json_pointer& lhs, + const json_pointer& rhs) + { + return json_pointer(lhs) /= rhs; + } + + /*! + @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer + + @param[in] ptr JSON pointer + @param[in] token reference token + @return a new JSON pointer with unescaped @a token appended to @a ptr + + @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} + + @complexity Linear in the length of @a ptr. + + @sa see @ref operator/=(std::string) to append a reference token + + @since version 3.6.0 + */ + friend json_pointer operator/(const json_pointer& ptr, std::string token) // NOLINT(performance-unnecessary-value-param) + { + return json_pointer(ptr) /= std::move(token); + } + + /*! + @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer + + @param[in] ptr JSON pointer + @param[in] array_idx array index + @return a new JSON pointer with @a array_idx appended to @a ptr + + @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} + + @complexity Linear in the length of @a ptr. + + @sa see @ref operator/=(std::size_t) to append an array index + + @since version 3.6.0 + */ + friend json_pointer operator/(const json_pointer& ptr, std::size_t array_idx) + { + return json_pointer(ptr) /= array_idx; + } + + /*! + @brief returns the parent of this JSON pointer + + @return parent of this JSON pointer; in case this JSON pointer is the root, + the root itself is returned + + @complexity Linear in the length of the JSON pointer. + + @liveexample{The example shows the result of `parent_pointer` for different + JSON Pointers.,json_pointer__parent_pointer} + + @since version 3.6.0 + */ + json_pointer parent_pointer() const + { + if (empty()) + { + return *this; + } + + json_pointer res = *this; + res.pop_back(); + return res; + } + + /*! + @brief remove last reference token + + @pre not `empty()` + + @liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back} + + @complexity Constant. + + @throw out_of_range.405 if JSON pointer has no parent + + @since version 3.6.0 + */ + void pop_back() + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + } + + reference_tokens.pop_back(); + } + + /*! + @brief return last reference token + + @pre not `empty()` + @return last reference token + + @liveexample{The example shows the usage of `back`.,json_pointer__back} + + @complexity Constant. + + @throw out_of_range.405 if JSON pointer has no parent + + @since version 3.6.0 + */ + const std::string& back() const + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + } + + return reference_tokens.back(); + } + + /*! + @brief append an unescaped token at the end of the reference pointer + + @param[in] token token to add + + @complexity Amortized constant. + + @liveexample{The example shows the result of `push_back` for different + JSON Pointers.,json_pointer__push_back} + + @since version 3.6.0 + */ + void push_back(const std::string& token) + { + reference_tokens.push_back(token); + } + + /// @copydoc push_back(const std::string&) + void push_back(std::string&& token) + { + reference_tokens.push_back(std::move(token)); + } + + /*! + @brief return whether pointer points to the root document + + @return true iff the JSON pointer points to the root document + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @liveexample{The example shows the result of `empty` for different JSON + Pointers.,json_pointer__empty} + + @since version 3.6.0 + */ + bool empty() const noexcept + { + return reference_tokens.empty(); + } + + private: + /*! + @param[in] s reference token to be converted into an array index + + @return integer representation of @a s + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index begins not with a digit + @throw out_of_range.404 if string @a s could not be converted to an integer + @throw out_of_range.410 if an array index exceeds size_type + */ + static typename BasicJsonType::size_type array_index(const std::string& s) + { + using size_type = typename BasicJsonType::size_type; + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType())); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType())); + } + + std::size_t processed_chars = 0; + unsigned long long res = 0; // NOLINT(runtime/int) + JSON_TRY + { + res = std::stoull(s, &processed_chars); + } + JSON_CATCH(std::out_of_range&) + { + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); + } + + // check if the string was completely read + if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) + { + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); + } + + // only triggered on special platforms (like 32bit), see also + // https://github.com/nlohmann/json/pull/2203 + if (res >= static_cast((std::numeric_limits::max)())) // NOLINT(runtime/int) + { + JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE + } + + return static_cast(res); + } + + JSON_PRIVATE_UNLESS_TESTED: + json_pointer top() const + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + } + + json_pointer result = *this; + result.reference_tokens = {reference_tokens[0]}; + return result; + } + + private: + /*! + @brief create and return a reference to the pointed to value + + @complexity Linear in the number of reference tokens. + + @throw parse_error.109 if array index is not a number + @throw type_error.313 if value cannot be unflattened + */ + BasicJsonType& get_and_create(BasicJsonType& j) const + { + auto* result = &j; + + // in case no reference tokens exist, return a reference to the JSON value + // j which will be overwritten by a primitive value + for (const auto& reference_token : reference_tokens) + { + switch (result->type()) + { + case detail::value_t::null: + { + if (reference_token == "0") + { + // start a new array if reference token is 0 + result = &result->operator[](0); + } + else + { + // start a new object otherwise + result = &result->operator[](reference_token); + } + break; + } + + case detail::value_t::object: + { + // create an entry in the object + result = &result->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + // create an entry in the array + result = &result->operator[](array_index(reference_token)); + break; + } + + /* + The following code is only reached if there exists a reference + token _and_ the current value is primitive. In this case, we have + an error situation, because primitive values may only occur as + single value; that is, with an empty list of reference tokens. + */ + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j)); + } + } + + return *result; + } + + /*! + @brief return a reference to the pointed to value + + @note This version does not throw if a value is not present, but tries to + create nested values instead. For instance, calling this function + with pointer `"/this/that"` on a null value is equivalent to calling + `operator[]("this").operator[]("that")` on that value, effectively + changing the null value to an object. + + @param[in] ptr a JSON value + + @return reference to the JSON value pointed to by the JSON pointer + + @complexity Linear in the length of the JSON pointer. + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + BasicJsonType& get_unchecked(BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + // convert null values to arrays or objects before continuing + if (ptr->is_null()) + { + // check if reference token is a number + const bool nums = + std::all_of(reference_token.begin(), reference_token.end(), + [](const unsigned char x) + { + return std::isdigit(x); + }); + + // change value to array for numbers or "-" or to object otherwise + *ptr = (nums || reference_token == "-") + ? detail::value_t::array + : detail::value_t::object; + } + + switch (ptr->type()) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (reference_token == "-") + { + // explicitly treat "-" as index beyond the end + ptr = &ptr->operator[](ptr->m_value.array->size()); + } + else + { + // convert array index to number; unchecked access + ptr = &ptr->operator[](array_index(reference_token)); + } + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + BasicJsonType& get_checked(BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range", *ptr)); + } + + // note: at performs range check + ptr = &ptr->at(array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + } + } + + return *ptr; + } + + /*! + @brief return a const reference to the pointed to value + + @param[in] ptr a JSON value + + @return const reference to the JSON value pointed to by the JSON + pointer + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" cannot be used for const access + JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr)); + } + + // use unchecked array access + ptr = &ptr->operator[](array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + const BasicJsonType& get_checked(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range", *ptr)); + } + + // note: at performs range check + ptr = &ptr->at(array_index(reference_token)); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + */ + bool contains(const BasicJsonType* ptr) const + { + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + if (!ptr->contains(reference_token)) + { + // we did not find the key in the object + return false; + } + + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) + { + // invalid char + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) + { + if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) + { + // first char should be between '1' and '9' + return false; + } + for (std::size_t i = 1; i < reference_token.size(); i++) + { + if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) + { + // other char should be between '0' and '9' + return false; + } + } + } + + const auto idx = array_index(reference_token); + if (idx >= ptr->size()) + { + // index out of range + return false; + } + + ptr = &ptr->operator[](idx); + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + { + // we do not expect primitive values if there is still a + // reference token to process + return false; + } + } + } + + // no reference token left means we found a primitive value + return true; + } + + /*! + @brief split the string input to reference tokens + + @note This function is only called by the json_pointer constructor. + All exceptions below are documented there. + + @throw parse_error.107 if the pointer is not empty or begins with '/' + @throw parse_error.108 if character '~' is not followed by '0' or '1' + */ + static std::vector split(const std::string& reference_string) + { + std::vector result; + + // special case: empty reference string -> no reference tokens + if (reference_string.empty()) + { + return result; + } + + // check if nonempty reference string begins with slash + if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) + { + JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType())); + } + + // extract the reference tokens: + // - slash: position of the last read slash (or end of string) + // - start: position after the previous slash + for ( + // search for the first slash after the first character + std::size_t slash = reference_string.find_first_of('/', 1), + // set the beginning of the first reference token + start = 1; + // we can stop if start == 0 (if slash == std::string::npos) + start != 0; + // set the beginning of the next reference token + // (will eventually be 0 if slash == std::string::npos) + start = (slash == std::string::npos) ? 0 : slash + 1, + // find next slash + slash = reference_string.find_first_of('/', start)) + { + // use the text between the beginning of the reference token + // (start) and the last slash (slash). + auto reference_token = reference_string.substr(start, slash - start); + + // check reference tokens are properly escaped + for (std::size_t pos = reference_token.find_first_of('~'); + pos != std::string::npos; + pos = reference_token.find_first_of('~', pos + 1)) + { + JSON_ASSERT(reference_token[pos] == '~'); + + // ~ must be followed by 0 or 1 + if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || + (reference_token[pos + 1] != '0' && + reference_token[pos + 1] != '1'))) + { + JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType())); + } + } + + // finally, store the reference token + detail::unescape(reference_token); + result.push_back(reference_token); + } + + return result; + } + + private: + /*! + @param[in] reference_string the reference string to the current value + @param[in] value the value to consider + @param[in,out] result the result object to insert values to + + @note Empty objects or arrays are flattened to `null`. + */ + static void flatten(const std::string& reference_string, + const BasicJsonType& value, + BasicJsonType& result) + { + switch (value.type()) + { + case detail::value_t::array: + { + if (value.m_value.array->empty()) + { + // flatten empty array as null + result[reference_string] = nullptr; + } + else + { + // iterate array and use index as reference string + for (std::size_t i = 0; i < value.m_value.array->size(); ++i) + { + flatten(reference_string + "/" + std::to_string(i), + value.m_value.array->operator[](i), result); + } + } + break; + } + + case detail::value_t::object: + { + if (value.m_value.object->empty()) + { + // flatten empty object as null + result[reference_string] = nullptr; + } + else + { + // iterate object and use keys as reference string + for (const auto& element : *value.m_value.object) + { + flatten(reference_string + "/" + detail::escape(element.first), element.second, result); + } + } + break; + } + + case detail::value_t::null: + case detail::value_t::string: + case detail::value_t::boolean: + case detail::value_t::number_integer: + case detail::value_t::number_unsigned: + case detail::value_t::number_float: + case detail::value_t::binary: + case detail::value_t::discarded: + default: + { + // add primitive value with its reference string + result[reference_string] = value; + break; + } + } + } + + /*! + @param[in] value flattened JSON + + @return unflattened JSON + + @throw parse_error.109 if array index is not a number + @throw type_error.314 if value is not an object + @throw type_error.315 if object values are not primitive + @throw type_error.313 if value cannot be unflattened + */ + static BasicJsonType + unflatten(const BasicJsonType& value) + { + if (JSON_HEDLEY_UNLIKELY(!value.is_object())) + { + JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value)); + } + + BasicJsonType result; + + // iterate the JSON object values + for (const auto& element : *value.m_value.object) + { + if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) + { + JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second)); + } + + // assign value to reference pointed to by JSON pointer; Note that if + // the JSON pointer is "" (i.e., points to the whole value), function + // get_and_create returns a reference to result itself. An assignment + // will then create a primitive value. + json_pointer(element.first).get_and_create(result) = element.second; + } + + return result; + } + + /*! + @brief compares two JSON pointers for equality + + @param[in] lhs JSON pointer to compare + @param[in] rhs JSON pointer to compare + @return whether @a lhs is equal to @a rhs + + @complexity Linear in the length of the JSON pointer + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + */ + friend bool operator==(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return lhs.reference_tokens == rhs.reference_tokens; + } + + /*! + @brief compares two JSON pointers for inequality + + @param[in] lhs JSON pointer to compare + @param[in] rhs JSON pointer to compare + @return whether @a lhs is not equal @a rhs + + @complexity Linear in the length of the JSON pointer + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + */ + friend bool operator!=(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return !(lhs == rhs); + } + + /// the reference tokens + std::vector reference_tokens; +}; +} // namespace nlohmann + +// #include + + +#include +#include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +class json_ref +{ + public: + using value_type = BasicJsonType; + + json_ref(value_type&& value) + : owned_value(std::move(value)) + {} + + json_ref(const value_type& value) + : value_ref(&value) + {} + + json_ref(std::initializer_list init) + : owned_value(init) + {} + + template < + class... Args, + enable_if_t::value, int> = 0 > + json_ref(Args && ... args) + : owned_value(std::forward(args)...) + {} + + // class should be movable only + json_ref(json_ref&&) noexcept = default; + json_ref(const json_ref&) = delete; + json_ref& operator=(const json_ref&) = delete; + json_ref& operator=(json_ref&&) = delete; + ~json_ref() = default; + + value_type moved_or_copied() const + { + if (value_ref == nullptr) + { + return std::move(owned_value); + } + return *value_ref; + } + + value_type const& operator*() const + { + return value_ref ? *value_ref : owned_value; + } + + value_type const* operator->() const + { + return &** this; + } + + private: + mutable value_type owned_value = nullptr; + value_type const* value_ref = nullptr; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + +// #include + +// #include + + +#include // reverse +#include // array +#include // isnan, isinf +#include // uint8_t, uint16_t, uint32_t, uint64_t +#include // memcpy +#include // numeric_limits +#include // string +#include // move + +// #include + +// #include + +// #include + + +#include // copy +#include // size_t +#include // back_inserter +#include // shared_ptr, make_shared +#include // basic_string +#include // vector + +#ifndef JSON_NO_IO + #include // streamsize + #include // basic_ostream +#endif // JSON_NO_IO + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/// abstract output adapter interface +template struct output_adapter_protocol +{ + virtual void write_character(CharType c) = 0; + virtual void write_characters(const CharType* s, std::size_t length) = 0; + virtual ~output_adapter_protocol() = default; + + output_adapter_protocol() = default; + output_adapter_protocol(const output_adapter_protocol&) = default; + output_adapter_protocol(output_adapter_protocol&&) noexcept = default; + output_adapter_protocol& operator=(const output_adapter_protocol&) = default; + output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default; +}; + +/// a type to simplify interfaces +template +using output_adapter_t = std::shared_ptr>; + +/// output adapter for byte vectors +template> +class output_vector_adapter : public output_adapter_protocol +{ + public: + explicit output_vector_adapter(std::vector& vec) noexcept + : v(vec) + {} + + void write_character(CharType c) override + { + v.push_back(c); + } + + JSON_HEDLEY_NON_NULL(2) + void write_characters(const CharType* s, std::size_t length) override + { + std::copy(s, s + length, std::back_inserter(v)); + } + + private: + std::vector& v; +}; + +#ifndef JSON_NO_IO +/// output adapter for output streams +template +class output_stream_adapter : public output_adapter_protocol +{ + public: + explicit output_stream_adapter(std::basic_ostream& s) noexcept + : stream(s) + {} + + void write_character(CharType c) override + { + stream.put(c); + } + + JSON_HEDLEY_NON_NULL(2) + void write_characters(const CharType* s, std::size_t length) override + { + stream.write(s, static_cast(length)); + } + + private: + std::basic_ostream& stream; +}; +#endif // JSON_NO_IO + +/// output adapter for basic_string +template> +class output_string_adapter : public output_adapter_protocol +{ + public: + explicit output_string_adapter(StringType& s) noexcept + : str(s) + {} + + void write_character(CharType c) override + { + str.push_back(c); + } + + JSON_HEDLEY_NON_NULL(2) + void write_characters(const CharType* s, std::size_t length) override + { + str.append(s, length); + } + + private: + StringType& str; +}; + +template> +class output_adapter +{ + public: + template> + output_adapter(std::vector& vec) + : oa(std::make_shared>(vec)) {} + +#ifndef JSON_NO_IO + output_adapter(std::basic_ostream& s) + : oa(std::make_shared>(s)) {} +#endif // JSON_NO_IO + + output_adapter(StringType& s) + : oa(std::make_shared>(s)) {} + + operator output_adapter_t() + { + return oa; + } + + private: + output_adapter_t oa = nullptr; +}; +} // namespace detail +} // namespace nlohmann + + +namespace nlohmann +{ +namespace detail +{ +/////////////////// +// binary writer // +/////////////////// + +/*! +@brief serialization to CBOR and MessagePack values +*/ +template +class binary_writer +{ + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using number_float_t = typename BasicJsonType::number_float_t; + + public: + /*! + @brief create a binary writer + + @param[in] adapter output adapter to write to + */ + explicit binary_writer(output_adapter_t adapter) : oa(std::move(adapter)) + { + JSON_ASSERT(oa); + } + + /*! + @param[in] j JSON value to serialize + @pre j.type() == value_t::object + */ + void write_bson(const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::object: + { + write_bson_object(*j.m_value.object); + break; + } + + case value_t::null: + case value_t::array: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j)); + } + } + } + + /*! + @param[in] j JSON value to serialize + */ + void write_cbor(const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::null: + { + oa->write_character(to_char_type(0xF6)); + break; + } + + case value_t::boolean: + { + oa->write_character(j.m_value.boolean + ? to_char_type(0xF5) + : to_char_type(0xF4)); + break; + } + + case value_t::number_integer: + { + if (j.m_value.number_integer >= 0) + { + // CBOR does not differentiate between positive signed + // integers and unsigned integers. Therefore, we used the + // code from the value_t::number_unsigned case here. + if (j.m_value.number_integer <= 0x17) + { + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x18)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x19)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x1A)); + write_number(static_cast(j.m_value.number_integer)); + } + else + { + oa->write_character(to_char_type(0x1B)); + write_number(static_cast(j.m_value.number_integer)); + } + } + else + { + // The conversions below encode the sign in the first + // byte, and the value is converted to a positive number. + const auto positive_number = -1 - j.m_value.number_integer; + if (j.m_value.number_integer >= -24) + { + write_number(static_cast(0x20 + positive_number)); + } + else if (positive_number <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x38)); + write_number(static_cast(positive_number)); + } + else if (positive_number <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x39)); + write_number(static_cast(positive_number)); + } + else if (positive_number <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x3A)); + write_number(static_cast(positive_number)); + } + else + { + oa->write_character(to_char_type(0x3B)); + write_number(static_cast(positive_number)); + } + } + break; + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned <= 0x17) + { + write_number(static_cast(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x18)); + write_number(static_cast(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x19)); + write_number(static_cast(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x1A)); + write_number(static_cast(j.m_value.number_unsigned)); + } + else + { + oa->write_character(to_char_type(0x1B)); + write_number(static_cast(j.m_value.number_unsigned)); + } + break; + } + + case value_t::number_float: + { + if (std::isnan(j.m_value.number_float)) + { + // NaN is 0xf97e00 in CBOR + oa->write_character(to_char_type(0xF9)); + oa->write_character(to_char_type(0x7E)); + oa->write_character(to_char_type(0x00)); + } + else if (std::isinf(j.m_value.number_float)) + { + // Infinity is 0xf97c00, -Infinity is 0xf9fc00 + oa->write_character(to_char_type(0xf9)); + oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); + oa->write_character(to_char_type(0x00)); + } + else + { + write_compact_float(j.m_value.number_float, detail::input_format_t::cbor); + } + break; + } + + case value_t::string: + { + // step 1: write control byte and the string length + const auto N = j.m_value.string->size(); + if (N <= 0x17) + { + write_number(static_cast(0x60 + N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x78)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x79)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x7A)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x7B)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write the string + oa->write_characters( + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); + break; + } + + case value_t::array: + { + // step 1: write control byte and the array size + const auto N = j.m_value.array->size(); + if (N <= 0x17) + { + write_number(static_cast(0x80 + N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x98)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x99)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x9A)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x9B)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + for (const auto& el : *j.m_value.array) + { + write_cbor(el); + } + break; + } + + case value_t::binary: + { + if (j.m_value.binary->has_subtype()) + { + if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + { + write_number(static_cast(0xd8)); + write_number(static_cast(j.m_value.binary->subtype())); + } + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + { + write_number(static_cast(0xd9)); + write_number(static_cast(j.m_value.binary->subtype())); + } + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + { + write_number(static_cast(0xda)); + write_number(static_cast(j.m_value.binary->subtype())); + } + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) + { + write_number(static_cast(0xdb)); + write_number(static_cast(j.m_value.binary->subtype())); + } + } + + // step 1: write control byte and the binary array size + const auto N = j.m_value.binary->size(); + if (N <= 0x17) + { + write_number(static_cast(0x40 + N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x58)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x59)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x5A)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0x5B)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + oa->write_characters( + reinterpret_cast(j.m_value.binary->data()), + N); + + break; + } + + case value_t::object: + { + // step 1: write control byte and the object size + const auto N = j.m_value.object->size(); + if (N <= 0x17) + { + write_number(static_cast(0xA0 + N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0xB8)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0xB9)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0xBA)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) + { + oa->write_character(to_char_type(0xBB)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + for (const auto& el : *j.m_value.object) + { + write_cbor(el.first); + write_cbor(el.second); + } + break; + } + + case value_t::discarded: + default: + break; + } + } + + /*! + @param[in] j JSON value to serialize + */ + void write_msgpack(const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::null: // nil + { + oa->write_character(to_char_type(0xC0)); + break; + } + + case value_t::boolean: // true and false + { + oa->write_character(j.m_value.boolean + ? to_char_type(0xC3) + : to_char_type(0xC2)); + break; + } + + case value_t::number_integer: + { + if (j.m_value.number_integer >= 0) + { + // MessagePack does not differentiate between positive + // signed integers and unsigned integers. Therefore, we used + // the code from the value_t::number_unsigned case here. + if (j.m_value.number_unsigned < 128) + { + // positive fixnum + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 8 + oa->write_character(to_char_type(0xCC)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 16 + oa->write_character(to_char_type(0xCD)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 32 + oa->write_character(to_char_type(0xCE)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 64 + oa->write_character(to_char_type(0xCF)); + write_number(static_cast(j.m_value.number_integer)); + } + } + else + { + if (j.m_value.number_integer >= -32) + { + // negative fixnum + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) + { + // int 8 + oa->write_character(to_char_type(0xD0)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) + { + // int 16 + oa->write_character(to_char_type(0xD1)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) + { + // int 32 + oa->write_character(to_char_type(0xD2)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) + { + // int 64 + oa->write_character(to_char_type(0xD3)); + write_number(static_cast(j.m_value.number_integer)); + } + } + break; + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned < 128) + { + // positive fixnum + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 8 + oa->write_character(to_char_type(0xCC)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 16 + oa->write_character(to_char_type(0xCD)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 32 + oa->write_character(to_char_type(0xCE)); + write_number(static_cast(j.m_value.number_integer)); + } + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + { + // uint 64 + oa->write_character(to_char_type(0xCF)); + write_number(static_cast(j.m_value.number_integer)); + } + break; + } + + case value_t::number_float: + { + write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack); + break; + } + + case value_t::string: + { + // step 1: write control byte and the string length + const auto N = j.m_value.string->size(); + if (N <= 31) + { + // fixstr + write_number(static_cast(0xA0 | N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // str 8 + oa->write_character(to_char_type(0xD9)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // str 16 + oa->write_character(to_char_type(0xDA)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // str 32 + oa->write_character(to_char_type(0xDB)); + write_number(static_cast(N)); + } + + // step 2: write the string + oa->write_characters( + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); + break; + } + + case value_t::array: + { + // step 1: write control byte and the array size + const auto N = j.m_value.array->size(); + if (N <= 15) + { + // fixarray + write_number(static_cast(0x90 | N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // array 16 + oa->write_character(to_char_type(0xDC)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // array 32 + oa->write_character(to_char_type(0xDD)); + write_number(static_cast(N)); + } + + // step 2: write each element + for (const auto& el : *j.m_value.array) + { + write_msgpack(el); + } + break; + } + + case value_t::binary: + { + // step 0: determine if the binary type has a set subtype to + // determine whether or not to use the ext or fixext types + const bool use_ext = j.m_value.binary->has_subtype(); + + // step 1: write control byte and the byte string length + const auto N = j.m_value.binary->size(); + if (N <= (std::numeric_limits::max)()) + { + std::uint8_t output_type{}; + bool fixed = true; + if (use_ext) + { + switch (N) + { + case 1: + output_type = 0xD4; // fixext 1 + break; + case 2: + output_type = 0xD5; // fixext 2 + break; + case 4: + output_type = 0xD6; // fixext 4 + break; + case 8: + output_type = 0xD7; // fixext 8 + break; + case 16: + output_type = 0xD8; // fixext 16 + break; + default: + output_type = 0xC7; // ext 8 + fixed = false; + break; + } + + } + else + { + output_type = 0xC4; // bin 8 + fixed = false; + } + + oa->write_character(to_char_type(output_type)); + if (!fixed) + { + write_number(static_cast(N)); + } + } + else if (N <= (std::numeric_limits::max)()) + { + std::uint8_t output_type = use_ext + ? 0xC8 // ext 16 + : 0xC5; // bin 16 + + oa->write_character(to_char_type(output_type)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + std::uint8_t output_type = use_ext + ? 0xC9 // ext 32 + : 0xC6; // bin 32 + + oa->write_character(to_char_type(output_type)); + write_number(static_cast(N)); + } + + // step 1.5: if this is an ext type, write the subtype + if (use_ext) + { + write_number(static_cast(j.m_value.binary->subtype())); + } + + // step 2: write the byte string + oa->write_characters( + reinterpret_cast(j.m_value.binary->data()), + N); + + break; + } + + case value_t::object: + { + // step 1: write control byte and the object size + const auto N = j.m_value.object->size(); + if (N <= 15) + { + // fixmap + write_number(static_cast(0x80 | (N & 0xF))); + } + else if (N <= (std::numeric_limits::max)()) + { + // map 16 + oa->write_character(to_char_type(0xDE)); + write_number(static_cast(N)); + } + else if (N <= (std::numeric_limits::max)()) + { + // map 32 + oa->write_character(to_char_type(0xDF)); + write_number(static_cast(N)); + } + + // step 2: write each element + for (const auto& el : *j.m_value.object) + { + write_msgpack(el.first); + write_msgpack(el.second); + } + break; + } + + case value_t::discarded: + default: + break; + } + } + + /*! + @param[in] j JSON value to serialize + @param[in] use_count whether to use '#' prefixes (optimized format) + @param[in] use_type whether to use '$' prefixes (optimized format) + @param[in] add_prefix whether prefixes need to be used for this value + */ + void write_ubjson(const BasicJsonType& j, const bool use_count, + const bool use_type, const bool add_prefix = true) + { + switch (j.type()) + { + case value_t::null: + { + if (add_prefix) + { + oa->write_character(to_char_type('Z')); + } + break; + } + + case value_t::boolean: + { + if (add_prefix) + { + oa->write_character(j.m_value.boolean + ? to_char_type('T') + : to_char_type('F')); + } + break; + } + + case value_t::number_integer: + { + write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix); + break; + } + + case value_t::number_unsigned: + { + write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix); + break; + } + + case value_t::number_float: + { + write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix); + break; + } + + case value_t::string: + { + if (add_prefix) + { + oa->write_character(to_char_type('S')); + } + write_number_with_ubjson_prefix(j.m_value.string->size(), true); + oa->write_characters( + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); + break; + } + + case value_t::array: + { + if (add_prefix) + { + oa->write_character(to_char_type('[')); + } + + bool prefix_required = true; + if (use_type && !j.m_value.array->empty()) + { + JSON_ASSERT(use_count); + const CharType first_prefix = ubjson_prefix(j.front()); + const bool same_prefix = std::all_of(j.begin() + 1, j.end(), + [this, first_prefix](const BasicJsonType & v) + { + return ubjson_prefix(v) == first_prefix; + }); + + if (same_prefix) + { + prefix_required = false; + oa->write_character(to_char_type('$')); + oa->write_character(first_prefix); + } + } + + if (use_count) + { + oa->write_character(to_char_type('#')); + write_number_with_ubjson_prefix(j.m_value.array->size(), true); + } + + for (const auto& el : *j.m_value.array) + { + write_ubjson(el, use_count, use_type, prefix_required); + } + + if (!use_count) + { + oa->write_character(to_char_type(']')); + } + + break; + } + + case value_t::binary: + { + if (add_prefix) + { + oa->write_character(to_char_type('[')); + } + + if (use_type && !j.m_value.binary->empty()) + { + JSON_ASSERT(use_count); + oa->write_character(to_char_type('$')); + oa->write_character('U'); + } + + if (use_count) + { + oa->write_character(to_char_type('#')); + write_number_with_ubjson_prefix(j.m_value.binary->size(), true); + } + + if (use_type) + { + oa->write_characters( + reinterpret_cast(j.m_value.binary->data()), + j.m_value.binary->size()); + } + else + { + for (size_t i = 0; i < j.m_value.binary->size(); ++i) + { + oa->write_character(to_char_type('U')); + oa->write_character(j.m_value.binary->data()[i]); + } + } + + if (!use_count) + { + oa->write_character(to_char_type(']')); + } + + break; + } + + case value_t::object: + { + if (add_prefix) + { + oa->write_character(to_char_type('{')); + } + + bool prefix_required = true; + if (use_type && !j.m_value.object->empty()) + { + JSON_ASSERT(use_count); + const CharType first_prefix = ubjson_prefix(j.front()); + const bool same_prefix = std::all_of(j.begin(), j.end(), + [this, first_prefix](const BasicJsonType & v) + { + return ubjson_prefix(v) == first_prefix; + }); + + if (same_prefix) + { + prefix_required = false; + oa->write_character(to_char_type('$')); + oa->write_character(first_prefix); + } + } + + if (use_count) + { + oa->write_character(to_char_type('#')); + write_number_with_ubjson_prefix(j.m_value.object->size(), true); + } + + for (const auto& el : *j.m_value.object) + { + write_number_with_ubjson_prefix(el.first.size(), true); + oa->write_characters( + reinterpret_cast(el.first.c_str()), + el.first.size()); + write_ubjson(el.second, use_count, use_type, prefix_required); + } + + if (!use_count) + { + oa->write_character(to_char_type('}')); + } + + break; + } + + case value_t::discarded: + default: + break; + } + } + + private: + ////////// + // BSON // + ////////// + + /*! + @return The size of a BSON document entry header, including the id marker + and the entry name size (and its null-terminator). + */ + static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j) + { + const auto it = name.find(static_cast(0)); + if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) + { + JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j)); + static_cast(j); + } + + return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; + } + + /*! + @brief Writes the given @a element_type and @a name to the output adapter + */ + void write_bson_entry_header(const string_t& name, + const std::uint8_t element_type) + { + oa->write_character(to_char_type(element_type)); // boolean + oa->write_characters( + reinterpret_cast(name.c_str()), + name.size() + 1u); + } + + /*! + @brief Writes a BSON element with key @a name and boolean value @a value + */ + void write_bson_boolean(const string_t& name, + const bool value) + { + write_bson_entry_header(name, 0x08); + oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00)); + } + + /*! + @brief Writes a BSON element with key @a name and double value @a value + */ + void write_bson_double(const string_t& name, + const double value) + { + write_bson_entry_header(name, 0x01); + write_number(value); + } + + /*! + @return The size of the BSON-encoded string in @a value + */ + static std::size_t calc_bson_string_size(const string_t& value) + { + return sizeof(std::int32_t) + value.size() + 1ul; + } + + /*! + @brief Writes a BSON element with key @a name and string value @a value + */ + void write_bson_string(const string_t& name, + const string_t& value) + { + write_bson_entry_header(name, 0x02); + + write_number(static_cast(value.size() + 1ul)); + oa->write_characters( + reinterpret_cast(value.c_str()), + value.size() + 1); + } + + /*! + @brief Writes a BSON element with key @a name and null value + */ + void write_bson_null(const string_t& name) + { + write_bson_entry_header(name, 0x0A); + } + + /*! + @return The size of the BSON-encoded integer @a value + */ + static std::size_t calc_bson_integer_size(const std::int64_t value) + { + return (std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)() + ? sizeof(std::int32_t) + : sizeof(std::int64_t); + } + + /*! + @brief Writes a BSON element with key @a name and integer @a value + */ + void write_bson_integer(const string_t& name, + const std::int64_t value) + { + if ((std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)()) + { + write_bson_entry_header(name, 0x10); // int32 + write_number(static_cast(value)); + } + else + { + write_bson_entry_header(name, 0x12); // int64 + write_number(static_cast(value)); + } + } + + /*! + @return The size of the BSON-encoded unsigned integer in @a j + */ + static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept + { + return (value <= static_cast((std::numeric_limits::max)())) + ? sizeof(std::int32_t) + : sizeof(std::int64_t); + } + + /*! + @brief Writes a BSON element with key @a name and unsigned @a value + */ + void write_bson_unsigned(const string_t& name, + const BasicJsonType& j) + { + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + write_bson_entry_header(name, 0x10 /* int32 */); + write_number(static_cast(j.m_value.number_unsigned)); + } + else if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + write_bson_entry_header(name, 0x12 /* int64 */); + write_number(static_cast(j.m_value.number_unsigned)); + } + else + { + JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j)); + } + } + + /*! + @brief Writes a BSON element with key @a name and object @a value + */ + void write_bson_object_entry(const string_t& name, + const typename BasicJsonType::object_t& value) + { + write_bson_entry_header(name, 0x03); // object + write_bson_object(value); + } + + /*! + @return The size of the BSON-encoded array @a value + */ + static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) + { + std::size_t array_index = 0ul; + + const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), std::size_t(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el) + { + return result + calc_bson_element_size(std::to_string(array_index++), el); + }); + + return sizeof(std::int32_t) + embedded_document_size + 1ul; + } + + /*! + @return The size of the BSON-encoded binary array @a value + */ + static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value) + { + return sizeof(std::int32_t) + value.size() + 1ul; + } + + /*! + @brief Writes a BSON element with key @a name and array @a value + */ + void write_bson_array(const string_t& name, + const typename BasicJsonType::array_t& value) + { + write_bson_entry_header(name, 0x04); // array + write_number(static_cast(calc_bson_array_size(value))); + + std::size_t array_index = 0ul; + + for (const auto& el : value) + { + write_bson_element(std::to_string(array_index++), el); + } + + oa->write_character(to_char_type(0x00)); + } + + /*! + @brief Writes a BSON element with key @a name and binary value @a value + */ + void write_bson_binary(const string_t& name, + const binary_t& value) + { + write_bson_entry_header(name, 0x05); + + write_number(static_cast(value.size())); + write_number(value.has_subtype() ? static_cast(value.subtype()) : std::uint8_t(0x00)); + + oa->write_characters(reinterpret_cast(value.data()), value.size()); + } + + /*! + @brief Calculates the size necessary to serialize the JSON value @a j with its @a name + @return The calculated size for the BSON document entry for @a j with the given @a name. + */ + static std::size_t calc_bson_element_size(const string_t& name, + const BasicJsonType& j) + { + const auto header_size = calc_bson_entry_header_size(name, j); + switch (j.type()) + { + case value_t::object: + return header_size + calc_bson_object_size(*j.m_value.object); + + case value_t::array: + return header_size + calc_bson_array_size(*j.m_value.array); + + case value_t::binary: + return header_size + calc_bson_binary_size(*j.m_value.binary); + + case value_t::boolean: + return header_size + 1ul; + + case value_t::number_float: + return header_size + 8ul; + + case value_t::number_integer: + return header_size + calc_bson_integer_size(j.m_value.number_integer); + + case value_t::number_unsigned: + return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); + + case value_t::string: + return header_size + calc_bson_string_size(*j.m_value.string); + + case value_t::null: + return header_size + 0ul; + + // LCOV_EXCL_START + case value_t::discarded: + default: + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + return 0ul; + // LCOV_EXCL_STOP + } + } + + /*! + @brief Serializes the JSON value @a j to BSON and associates it with the + key @a name. + @param name The name to associate with the JSON entity @a j within the + current BSON document + */ + void write_bson_element(const string_t& name, + const BasicJsonType& j) + { + switch (j.type()) + { + case value_t::object: + return write_bson_object_entry(name, *j.m_value.object); + + case value_t::array: + return write_bson_array(name, *j.m_value.array); + + case value_t::binary: + return write_bson_binary(name, *j.m_value.binary); + + case value_t::boolean: + return write_bson_boolean(name, j.m_value.boolean); + + case value_t::number_float: + return write_bson_double(name, j.m_value.number_float); + + case value_t::number_integer: + return write_bson_integer(name, j.m_value.number_integer); + + case value_t::number_unsigned: + return write_bson_unsigned(name, j); + + case value_t::string: + return write_bson_string(name, *j.m_value.string); + + case value_t::null: + return write_bson_null(name); + + // LCOV_EXCL_START + case value_t::discarded: + default: + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) + return; + // LCOV_EXCL_STOP + } + } + + /*! + @brief Calculates the size of the BSON serialization of the given + JSON-object @a j. + @param[in] value JSON value to serialize + @pre value.type() == value_t::object + */ + static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) + { + std::size_t document_size = std::accumulate(value.begin(), value.end(), std::size_t(0), + [](size_t result, const typename BasicJsonType::object_t::value_type & el) + { + return result += calc_bson_element_size(el.first, el.second); + }); + + return sizeof(std::int32_t) + document_size + 1ul; + } + + /*! + @param[in] value JSON value to serialize + @pre value.type() == value_t::object + */ + void write_bson_object(const typename BasicJsonType::object_t& value) + { + write_number(static_cast(calc_bson_object_size(value))); + + for (const auto& el : value) + { + write_bson_element(el.first, el.second); + } + + oa->write_character(to_char_type(0x00)); + } + + ////////// + // CBOR // + ////////// + + static constexpr CharType get_cbor_float_prefix(float /*unused*/) + { + return to_char_type(0xFA); // Single-Precision Float + } + + static constexpr CharType get_cbor_float_prefix(double /*unused*/) + { + return to_char_type(0xFB); // Double-Precision Float + } + + ///////////// + // MsgPack // + ///////////// + + static constexpr CharType get_msgpack_float_prefix(float /*unused*/) + { + return to_char_type(0xCA); // float 32 + } + + static constexpr CharType get_msgpack_float_prefix(double /*unused*/) + { + return to_char_type(0xCB); // float 64 + } + + //////////// + // UBJSON // + //////////// + + // UBJSON: write number (floating point) + template::value, int>::type = 0> + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) + { + if (add_prefix) + { + oa->write_character(get_ubjson_float_prefix(n)); + } + write_number(n); + } + + // UBJSON: write number (unsigned integer) + template::value, int>::type = 0> + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) + { + if (n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('i')); // int8 + } + write_number(static_cast(n)); + } + else if (n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('U')); // uint8 + } + write_number(static_cast(n)); + } + else if (n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('I')); // int16 + } + write_number(static_cast(n)); + } + else if (n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('l')); // int32 + } + write_number(static_cast(n)); + } + else if (n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('L')); // int64 + } + write_number(static_cast(n)); + } + else + { + if (add_prefix) + { + oa->write_character(to_char_type('H')); // high-precision number + } + + const auto number = BasicJsonType(n).dump(); + write_number_with_ubjson_prefix(number.size(), true); + for (std::size_t i = 0; i < number.size(); ++i) + { + oa->write_character(to_char_type(static_cast(number[i]))); + } + } + } + + // UBJSON: write number (signed integer) + template < typename NumberType, typename std::enable_if < + std::is_signed::value&& + !std::is_floating_point::value, int >::type = 0 > + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) + { + if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('i')); // int8 + } + write_number(static_cast(n)); + } + else if (static_cast((std::numeric_limits::min)()) <= n && n <= static_cast((std::numeric_limits::max)())) + { + if (add_prefix) + { + oa->write_character(to_char_type('U')); // uint8 + } + write_number(static_cast(n)); + } + else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('I')); // int16 + } + write_number(static_cast(n)); + } + else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('l')); // int32 + } + write_number(static_cast(n)); + } + else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) + { + if (add_prefix) + { + oa->write_character(to_char_type('L')); // int64 + } + write_number(static_cast(n)); + } + // LCOV_EXCL_START + else + { + if (add_prefix) + { + oa->write_character(to_char_type('H')); // high-precision number + } + + const auto number = BasicJsonType(n).dump(); + write_number_with_ubjson_prefix(number.size(), true); + for (std::size_t i = 0; i < number.size(); ++i) + { + oa->write_character(to_char_type(static_cast(number[i]))); + } + } + // LCOV_EXCL_STOP + } + + /*! + @brief determine the type prefix of container values + */ + CharType ubjson_prefix(const BasicJsonType& j) const noexcept + { + switch (j.type()) + { + case value_t::null: + return 'Z'; + + case value_t::boolean: + return j.m_value.boolean ? 'T' : 'F'; + + case value_t::number_integer: + { + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'i'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'U'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'I'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'l'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) + { + return 'L'; + } + // anything else is treated as high-precision number + return 'H'; // LCOV_EXCL_LINE + } + + case value_t::number_unsigned: + { + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'i'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'U'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'I'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'l'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + { + return 'L'; + } + // anything else is treated as high-precision number + return 'H'; // LCOV_EXCL_LINE + } + + case value_t::number_float: + return get_ubjson_float_prefix(j.m_value.number_float); + + case value_t::string: + return 'S'; + + case value_t::array: // fallthrough + case value_t::binary: + return '['; + + case value_t::object: + return '{'; + + case value_t::discarded: + default: // discarded values + return 'N'; + } + } + + static constexpr CharType get_ubjson_float_prefix(float /*unused*/) + { + return 'd'; // float 32 + } + + static constexpr CharType get_ubjson_float_prefix(double /*unused*/) + { + return 'D'; // float 64 + } + + /////////////////////// + // Utility functions // + /////////////////////// + + /* + @brief write a number to output input + @param[in] n number of type @a NumberType + @tparam NumberType the type of the number + @tparam OutputIsLittleEndian Set to true if output data is + required to be little endian + + @note This function needs to respect the system's endianess, because bytes + in CBOR, MessagePack, and UBJSON are stored in network order (big + endian) and therefore need reordering on little endian systems. + */ + template + void write_number(const NumberType n) + { + // step 1: write number to array of length NumberType + std::array vec{}; + std::memcpy(vec.data(), &n, sizeof(NumberType)); + + // step 2: write array to output (with possible reordering) + if (is_little_endian != OutputIsLittleEndian) + { + // reverse byte order prior to conversion if necessary + std::reverse(vec.begin(), vec.end()); + } + + oa->write_characters(vec.data(), sizeof(NumberType)); + } + + void write_compact_float(const number_float_t n, detail::input_format_t format) + { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + if (static_cast(n) >= static_cast(std::numeric_limits::lowest()) && + static_cast(n) <= static_cast((std::numeric_limits::max)()) && + static_cast(static_cast(n)) == static_cast(n)) + { + oa->write_character(format == detail::input_format_t::cbor + ? get_cbor_float_prefix(static_cast(n)) + : get_msgpack_float_prefix(static_cast(n))); + write_number(static_cast(n)); + } + else + { + oa->write_character(format == detail::input_format_t::cbor + ? get_cbor_float_prefix(n) + : get_msgpack_float_prefix(n)); + write_number(n); + } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + } + + public: + // The following to_char_type functions are implement the conversion + // between uint8_t and CharType. In case CharType is not unsigned, + // such a conversion is required to allow values greater than 128. + // See for a discussion. + template < typename C = CharType, + enable_if_t < std::is_signed::value && std::is_signed::value > * = nullptr > + static constexpr CharType to_char_type(std::uint8_t x) noexcept + { + return *reinterpret_cast(&x); + } + + template < typename C = CharType, + enable_if_t < std::is_signed::value && std::is_unsigned::value > * = nullptr > + static CharType to_char_type(std::uint8_t x) noexcept + { + static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t"); + static_assert(std::is_trivial::value, "CharType must be trivial"); + CharType result; + std::memcpy(&result, &x, sizeof(x)); + return result; + } + + template::value>* = nullptr> + static constexpr CharType to_char_type(std::uint8_t x) noexcept + { + return x; + } + + template < typename InputCharType, typename C = CharType, + enable_if_t < + std::is_signed::value && + std::is_signed::value && + std::is_same::type>::value + > * = nullptr > + static constexpr CharType to_char_type(InputCharType x) noexcept + { + return x; + } + + private: + /// whether we can assume little endianess + const bool is_little_endian = little_endianess(); + + /// the output + output_adapter_t oa = nullptr; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // reverse, remove, fill, find, none_of +#include // array +#include // localeconv, lconv +#include // labs, isfinite, isnan, signbit +#include // size_t, ptrdiff_t +#include // uint8_t +#include // snprintf +#include // numeric_limits +#include // string, char_traits +#include // is_same +#include // move + +// #include + + +#include // array +#include // signbit, isfinite +#include // intN_t, uintN_t +#include // memcpy, memmove +#include // numeric_limits +#include // conditional + +// #include + + +namespace nlohmann +{ +namespace detail +{ + +/*! +@brief implements the Grisu2 algorithm for binary to decimal floating-point +conversion. + +This implementation is a slightly modified version of the reference +implementation which may be obtained from +http://florian.loitsch.com/publications (bench.tar.gz). + +The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. + +For a detailed description of the algorithm see: + +[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with + Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming + Language Design and Implementation, PLDI 2010 +[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", + Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language + Design and Implementation, PLDI 1996 +*/ +namespace dtoa_impl +{ + +template +Target reinterpret_bits(const Source source) +{ + static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); + + Target target; + std::memcpy(&target, &source, sizeof(Source)); + return target; +} + +struct diyfp // f * 2^e +{ + static constexpr int kPrecision = 64; // = q + + std::uint64_t f = 0; + int e = 0; + + constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} + + /*! + @brief returns x - y + @pre x.e == y.e and x.f >= y.f + */ + static diyfp sub(const diyfp& x, const diyfp& y) noexcept + { + JSON_ASSERT(x.e == y.e); + JSON_ASSERT(x.f >= y.f); + + return {x.f - y.f, x.e}; + } + + /*! + @brief returns x * y + @note The result is rounded. (Only the upper q bits are returned.) + */ + static diyfp mul(const diyfp& x, const diyfp& y) noexcept + { + static_assert(kPrecision == 64, "internal error"); + + // Computes: + // f = round((x.f * y.f) / 2^q) + // e = x.e + y.e + q + + // Emulate the 64-bit * 64-bit multiplication: + // + // p = u * v + // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) + // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) + // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) + // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) + // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) + // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) + // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) + // + // (Since Q might be larger than 2^32 - 1) + // + // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) + // + // (Q_hi + H does not overflow a 64-bit int) + // + // = p_lo + 2^64 p_hi + + const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; + const std::uint64_t u_hi = x.f >> 32u; + const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; + const std::uint64_t v_hi = y.f >> 32u; + + const std::uint64_t p0 = u_lo * v_lo; + const std::uint64_t p1 = u_lo * v_hi; + const std::uint64_t p2 = u_hi * v_lo; + const std::uint64_t p3 = u_hi * v_hi; + + const std::uint64_t p0_hi = p0 >> 32u; + const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; + const std::uint64_t p1_hi = p1 >> 32u; + const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; + const std::uint64_t p2_hi = p2 >> 32u; + + std::uint64_t Q = p0_hi + p1_lo + p2_lo; + + // The full product might now be computed as + // + // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) + // p_lo = p0_lo + (Q << 32) + // + // But in this particular case here, the full p_lo is not required. + // Effectively we only need to add the highest bit in p_lo to p_hi (and + // Q_hi + 1 does not overflow). + + Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up + + const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); + + return {h, x.e + y.e + 64}; + } + + /*! + @brief normalize x such that the significand is >= 2^(q-1) + @pre x.f != 0 + */ + static diyfp normalize(diyfp x) noexcept + { + JSON_ASSERT(x.f != 0); + + while ((x.f >> 63u) == 0) + { + x.f <<= 1u; + x.e--; + } + + return x; + } + + /*! + @brief normalize x such that the result has the exponent E + @pre e >= x.e and the upper e - x.e bits of x.f must be zero. + */ + static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept + { + const int delta = x.e - target_exponent; + + JSON_ASSERT(delta >= 0); + JSON_ASSERT(((x.f << delta) >> delta) == x.f); + + return {x.f << delta, target_exponent}; + } +}; + +struct boundaries +{ + diyfp w; + diyfp minus; + diyfp plus; +}; + +/*! +Compute the (normalized) diyfp representing the input number 'value' and its +boundaries. + +@pre value must be finite and positive +*/ +template +boundaries compute_boundaries(FloatType value) +{ + JSON_ASSERT(std::isfinite(value)); + JSON_ASSERT(value > 0); + + // Convert the IEEE representation into a diyfp. + // + // If v is denormal: + // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) + // If v is normalized: + // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) + + static_assert(std::numeric_limits::is_iec559, + "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); + + constexpr int kPrecision = std::numeric_limits::digits; // = p (includes the hidden bit) + constexpr int kBias = std::numeric_limits::max_exponent - 1 + (kPrecision - 1); + constexpr int kMinExp = 1 - kBias; + constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) + + using bits_type = typename std::conditional::type; + + const auto bits = static_cast(reinterpret_bits(value)); + const std::uint64_t E = bits >> (kPrecision - 1); + const std::uint64_t F = bits & (kHiddenBit - 1); + + const bool is_denormal = E == 0; + const diyfp v = is_denormal + ? diyfp(F, kMinExp) + : diyfp(F + kHiddenBit, static_cast(E) - kBias); + + // Compute the boundaries m- and m+ of the floating-point value + // v = f * 2^e. + // + // Determine v- and v+, the floating-point predecessor and successor if v, + // respectively. + // + // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) + // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) + // + // v+ = v + 2^e + // + // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ + // between m- and m+ round to v, regardless of how the input rounding + // algorithm breaks ties. + // + // ---+-------------+-------------+-------------+-------------+--- (A) + // v- m- v m+ v+ + // + // -----------------+------+------+-------------+-------------+--- (B) + // v- m- v m+ v+ + + const bool lower_boundary_is_closer = F == 0 && E > 1; + const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); + const diyfp m_minus = lower_boundary_is_closer + ? diyfp(4 * v.f - 1, v.e - 2) // (B) + : diyfp(2 * v.f - 1, v.e - 1); // (A) + + // Determine the normalized w+ = m+. + const diyfp w_plus = diyfp::normalize(m_plus); + + // Determine w- = m- such that e_(w-) = e_(w+). + const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); + + return {diyfp::normalize(v), w_minus, w_plus}; +} + +// Given normalized diyfp w, Grisu needs to find a (normalized) cached +// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies +// within a certain range [alpha, gamma] (Definition 3.2 from [1]) +// +// alpha <= e = e_c + e_w + q <= gamma +// +// or +// +// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q +// <= f_c * f_w * 2^gamma +// +// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies +// +// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma +// +// or +// +// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) +// +// The choice of (alpha,gamma) determines the size of the table and the form of +// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well +// in practice: +// +// The idea is to cut the number c * w = f * 2^e into two parts, which can be +// processed independently: An integral part p1, and a fractional part p2: +// +// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e +// = (f div 2^-e) + (f mod 2^-e) * 2^e +// = p1 + p2 * 2^e +// +// The conversion of p1 into decimal form requires a series of divisions and +// modulos by (a power of) 10. These operations are faster for 32-bit than for +// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be +// achieved by choosing +// +// -e >= 32 or e <= -32 := gamma +// +// In order to convert the fractional part +// +// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... +// +// into decimal form, the fraction is repeatedly multiplied by 10 and the digits +// d[-i] are extracted in order: +// +// (10 * p2) div 2^-e = d[-1] +// (10 * p2) mod 2^-e = d[-2] / 10^1 + ... +// +// The multiplication by 10 must not overflow. It is sufficient to choose +// +// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. +// +// Since p2 = f mod 2^-e < 2^-e, +// +// -e <= 60 or e >= -60 := alpha + +constexpr int kAlpha = -60; +constexpr int kGamma = -32; + +struct cached_power // c = f * 2^e ~= 10^k +{ + std::uint64_t f; + int e; + int k; +}; + +/*! +For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached +power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c +satisfies (Definition 3.2 from [1]) + + alpha <= e_c + e + q <= gamma. +*/ +inline cached_power get_cached_power_for_binary_exponent(int e) +{ + // Now + // + // alpha <= e_c + e + q <= gamma (1) + // ==> f_c * 2^alpha <= c * 2^e * 2^q + // + // and since the c's are normalized, 2^(q-1) <= f_c, + // + // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) + // ==> 2^(alpha - e - 1) <= c + // + // If c were an exact power of ten, i.e. c = 10^k, one may determine k as + // + // k = ceil( log_10( 2^(alpha - e - 1) ) ) + // = ceil( (alpha - e - 1) * log_10(2) ) + // + // From the paper: + // "In theory the result of the procedure could be wrong since c is rounded, + // and the computation itself is approximated [...]. In practice, however, + // this simple function is sufficient." + // + // For IEEE double precision floating-point numbers converted into + // normalized diyfp's w = f * 2^e, with q = 64, + // + // e >= -1022 (min IEEE exponent) + // -52 (p - 1) + // -52 (p - 1, possibly normalize denormal IEEE numbers) + // -11 (normalize the diyfp) + // = -1137 + // + // and + // + // e <= +1023 (max IEEE exponent) + // -52 (p - 1) + // -11 (normalize the diyfp) + // = 960 + // + // This binary exponent range [-1137,960] results in a decimal exponent + // range [-307,324]. One does not need to store a cached power for each + // k in this range. For each such k it suffices to find a cached power + // such that the exponent of the product lies in [alpha,gamma]. + // This implies that the difference of the decimal exponents of adjacent + // table entries must be less than or equal to + // + // floor( (gamma - alpha) * log_10(2) ) = 8. + // + // (A smaller distance gamma-alpha would require a larger table.) + + // NB: + // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. + + constexpr int kCachedPowersMinDecExp = -300; + constexpr int kCachedPowersDecStep = 8; + + static constexpr std::array kCachedPowers = + { + { + { 0xAB70FE17C79AC6CA, -1060, -300 }, + { 0xFF77B1FCBEBCDC4F, -1034, -292 }, + { 0xBE5691EF416BD60C, -1007, -284 }, + { 0x8DD01FAD907FFC3C, -980, -276 }, + { 0xD3515C2831559A83, -954, -268 }, + { 0x9D71AC8FADA6C9B5, -927, -260 }, + { 0xEA9C227723EE8BCB, -901, -252 }, + { 0xAECC49914078536D, -874, -244 }, + { 0x823C12795DB6CE57, -847, -236 }, + { 0xC21094364DFB5637, -821, -228 }, + { 0x9096EA6F3848984F, -794, -220 }, + { 0xD77485CB25823AC7, -768, -212 }, + { 0xA086CFCD97BF97F4, -741, -204 }, + { 0xEF340A98172AACE5, -715, -196 }, + { 0xB23867FB2A35B28E, -688, -188 }, + { 0x84C8D4DFD2C63F3B, -661, -180 }, + { 0xC5DD44271AD3CDBA, -635, -172 }, + { 0x936B9FCEBB25C996, -608, -164 }, + { 0xDBAC6C247D62A584, -582, -156 }, + { 0xA3AB66580D5FDAF6, -555, -148 }, + { 0xF3E2F893DEC3F126, -529, -140 }, + { 0xB5B5ADA8AAFF80B8, -502, -132 }, + { 0x87625F056C7C4A8B, -475, -124 }, + { 0xC9BCFF6034C13053, -449, -116 }, + { 0x964E858C91BA2655, -422, -108 }, + { 0xDFF9772470297EBD, -396, -100 }, + { 0xA6DFBD9FB8E5B88F, -369, -92 }, + { 0xF8A95FCF88747D94, -343, -84 }, + { 0xB94470938FA89BCF, -316, -76 }, + { 0x8A08F0F8BF0F156B, -289, -68 }, + { 0xCDB02555653131B6, -263, -60 }, + { 0x993FE2C6D07B7FAC, -236, -52 }, + { 0xE45C10C42A2B3B06, -210, -44 }, + { 0xAA242499697392D3, -183, -36 }, + { 0xFD87B5F28300CA0E, -157, -28 }, + { 0xBCE5086492111AEB, -130, -20 }, + { 0x8CBCCC096F5088CC, -103, -12 }, + { 0xD1B71758E219652C, -77, -4 }, + { 0x9C40000000000000, -50, 4 }, + { 0xE8D4A51000000000, -24, 12 }, + { 0xAD78EBC5AC620000, 3, 20 }, + { 0x813F3978F8940984, 30, 28 }, + { 0xC097CE7BC90715B3, 56, 36 }, + { 0x8F7E32CE7BEA5C70, 83, 44 }, + { 0xD5D238A4ABE98068, 109, 52 }, + { 0x9F4F2726179A2245, 136, 60 }, + { 0xED63A231D4C4FB27, 162, 68 }, + { 0xB0DE65388CC8ADA8, 189, 76 }, + { 0x83C7088E1AAB65DB, 216, 84 }, + { 0xC45D1DF942711D9A, 242, 92 }, + { 0x924D692CA61BE758, 269, 100 }, + { 0xDA01EE641A708DEA, 295, 108 }, + { 0xA26DA3999AEF774A, 322, 116 }, + { 0xF209787BB47D6B85, 348, 124 }, + { 0xB454E4A179DD1877, 375, 132 }, + { 0x865B86925B9BC5C2, 402, 140 }, + { 0xC83553C5C8965D3D, 428, 148 }, + { 0x952AB45CFA97A0B3, 455, 156 }, + { 0xDE469FBD99A05FE3, 481, 164 }, + { 0xA59BC234DB398C25, 508, 172 }, + { 0xF6C69A72A3989F5C, 534, 180 }, + { 0xB7DCBF5354E9BECE, 561, 188 }, + { 0x88FCF317F22241E2, 588, 196 }, + { 0xCC20CE9BD35C78A5, 614, 204 }, + { 0x98165AF37B2153DF, 641, 212 }, + { 0xE2A0B5DC971F303A, 667, 220 }, + { 0xA8D9D1535CE3B396, 694, 228 }, + { 0xFB9B7CD9A4A7443C, 720, 236 }, + { 0xBB764C4CA7A44410, 747, 244 }, + { 0x8BAB8EEFB6409C1A, 774, 252 }, + { 0xD01FEF10A657842C, 800, 260 }, + { 0x9B10A4E5E9913129, 827, 268 }, + { 0xE7109BFBA19C0C9D, 853, 276 }, + { 0xAC2820D9623BF429, 880, 284 }, + { 0x80444B5E7AA7CF85, 907, 292 }, + { 0xBF21E44003ACDD2D, 933, 300 }, + { 0x8E679C2F5E44FF8F, 960, 308 }, + { 0xD433179D9C8CB841, 986, 316 }, + { 0x9E19DB92B4E31BA9, 1013, 324 }, + } + }; + + // This computation gives exactly the same results for k as + // k = ceil((kAlpha - e - 1) * 0.30102999566398114) + // for |e| <= 1500, but doesn't require floating-point operations. + // NB: log_10(2) ~= 78913 / 2^18 + JSON_ASSERT(e >= -1500); + JSON_ASSERT(e <= 1500); + const int f = kAlpha - e - 1; + const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); + + const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; + JSON_ASSERT(index >= 0); + JSON_ASSERT(static_cast(index) < kCachedPowers.size()); + + const cached_power cached = kCachedPowers[static_cast(index)]; + JSON_ASSERT(kAlpha <= cached.e + e + 64); + JSON_ASSERT(kGamma >= cached.e + e + 64); + + return cached; +} + +/*! +For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. +For n == 0, returns 1 and sets pow10 := 1. +*/ +inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) +{ + // LCOV_EXCL_START + if (n >= 1000000000) + { + pow10 = 1000000000; + return 10; + } + // LCOV_EXCL_STOP + if (n >= 100000000) + { + pow10 = 100000000; + return 9; + } + if (n >= 10000000) + { + pow10 = 10000000; + return 8; + } + if (n >= 1000000) + { + pow10 = 1000000; + return 7; + } + if (n >= 100000) + { + pow10 = 100000; + return 6; + } + if (n >= 10000) + { + pow10 = 10000; + return 5; + } + if (n >= 1000) + { + pow10 = 1000; + return 4; + } + if (n >= 100) + { + pow10 = 100; + return 3; + } + if (n >= 10) + { + pow10 = 10; + return 2; + } + + pow10 = 1; + return 1; +} + +inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, + std::uint64_t rest, std::uint64_t ten_k) +{ + JSON_ASSERT(len >= 1); + JSON_ASSERT(dist <= delta); + JSON_ASSERT(rest <= delta); + JSON_ASSERT(ten_k > 0); + + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // ten_k + // <------> + // <---- rest ----> + // --------------[------------------+----+--------------]-------------- + // w V + // = buf * 10^k + // + // ten_k represents a unit-in-the-last-place in the decimal representation + // stored in buf. + // Decrement buf by ten_k while this takes buf closer to w. + + // The tests are written in this order to avoid overflow in unsigned + // integer arithmetic. + + while (rest < dist + && delta - rest >= ten_k + && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) + { + JSON_ASSERT(buf[len - 1] != '0'); + buf[len - 1]--; + rest += ten_k; + } +} + +/*! +Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. +M- and M+ must be normalized and share the same exponent -60 <= e <= -32. +*/ +inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, + diyfp M_minus, diyfp w, diyfp M_plus) +{ + static_assert(kAlpha >= -60, "internal error"); + static_assert(kGamma <= -32, "internal error"); + + // Generates the digits (and the exponent) of a decimal floating-point + // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's + // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. + // + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // Grisu2 generates the digits of M+ from left to right and stops as soon as + // V is in [M-,M+]. + + JSON_ASSERT(M_plus.e >= kAlpha); + JSON_ASSERT(M_plus.e <= kGamma); + + std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) + std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) + + // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): + // + // M+ = f * 2^e + // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e + // = ((p1 ) * 2^-e + (p2 )) * 2^e + // = p1 + p2 * 2^e + + const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); + + auto p1 = static_cast(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) + std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e + + // 1) + // + // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] + + JSON_ASSERT(p1 > 0); + + std::uint32_t pow10{}; + const int k = find_largest_pow10(p1, pow10); + + // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) + // + // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) + // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) + // + // M+ = p1 + p2 * 2^e + // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e + // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e + // = d[k-1] * 10^(k-1) + ( rest) * 2^e + // + // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) + // + // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] + // + // but stop as soon as + // + // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e + + int n = k; + while (n > 0) + { + // Invariants: + // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) + // pow10 = 10^(n-1) <= p1 < 10^n + // + const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) + const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) + // + // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e + // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) + // + JSON_ASSERT(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) + // + p1 = r; + n--; + // + // M+ = buffer * 10^n + (p1 + p2 * 2^e) + // pow10 = 10^n + // + + // Now check if enough digits have been generated. + // Compute + // + // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e + // + // Note: + // Since rest and delta share the same exponent e, it suffices to + // compare the significands. + const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; + if (rest <= delta) + { + // V = buffer * 10^n, with M- <= V <= M+. + + decimal_exponent += n; + + // We may now just stop. But instead look if the buffer could be + // decremented to bring V closer to w. + // + // pow10 = 10^n is now 1 ulp in the decimal representation V. + // The rounding procedure works with diyfp's with an implicit + // exponent of e. + // + // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e + // + const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; + grisu2_round(buffer, length, dist, delta, rest, ten_n); + + return; + } + + pow10 /= 10; + // + // pow10 = 10^(n-1) <= p1 < 10^n + // Invariants restored. + } + + // 2) + // + // The digits of the integral part have been generated: + // + // M+ = d[k-1]...d[1]d[0] + p2 * 2^e + // = buffer + p2 * 2^e + // + // Now generate the digits of the fractional part p2 * 2^e. + // + // Note: + // No decimal point is generated: the exponent is adjusted instead. + // + // p2 actually represents the fraction + // + // p2 * 2^e + // = p2 / 2^-e + // = d[-1] / 10^1 + d[-2] / 10^2 + ... + // + // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) + // + // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m + // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) + // + // using + // + // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) + // = ( d) * 2^-e + ( r) + // + // or + // 10^m * p2 * 2^e = d + r * 2^e + // + // i.e. + // + // M+ = buffer + p2 * 2^e + // = buffer + 10^-m * (d + r * 2^e) + // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e + // + // and stop as soon as 10^-m * r * 2^e <= delta * 2^e + + JSON_ASSERT(p2 > delta); + + int m = 0; + for (;;) + { + // Invariant: + // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e + // = buffer * 10^-m + 10^-m * (p2 ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e + // + JSON_ASSERT(p2 <= (std::numeric_limits::max)() / 10); + p2 *= 10; + const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e + const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e + // + // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) + // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + JSON_ASSERT(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + p2 = r; + m++; + // + // M+ = buffer * 10^-m + 10^-m * p2 * 2^e + // Invariant restored. + + // Check if enough digits have been generated. + // + // 10^-m * p2 * 2^e <= delta * 2^e + // p2 * 2^e <= 10^m * delta * 2^e + // p2 <= 10^m * delta + delta *= 10; + dist *= 10; + if (p2 <= delta) + { + break; + } + } + + // V = buffer * 10^-m, with M- <= V <= M+. + + decimal_exponent -= m; + + // 1 ulp in the decimal representation is now 10^-m. + // Since delta and dist are now scaled by 10^m, we need to do the + // same with ulp in order to keep the units in sync. + // + // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e + // + const std::uint64_t ten_m = one.f; + grisu2_round(buffer, length, dist, delta, p2, ten_m); + + // By construction this algorithm generates the shortest possible decimal + // number (Loitsch, Theorem 6.2) which rounds back to w. + // For an input number of precision p, at least + // + // N = 1 + ceil(p * log_10(2)) + // + // decimal digits are sufficient to identify all binary floating-point + // numbers (Matula, "In-and-Out conversions"). + // This implies that the algorithm does not produce more than N decimal + // digits. + // + // N = 17 for p = 53 (IEEE double precision) + // N = 9 for p = 24 (IEEE single precision) +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +JSON_HEDLEY_NON_NULL(1) +inline void grisu2(char* buf, int& len, int& decimal_exponent, + diyfp m_minus, diyfp v, diyfp m_plus) +{ + JSON_ASSERT(m_plus.e == m_minus.e); + JSON_ASSERT(m_plus.e == v.e); + + // --------(-----------------------+-----------------------)-------- (A) + // m- v m+ + // + // --------------------(-----------+-----------------------)-------- (B) + // m- v m+ + // + // First scale v (and m- and m+) such that the exponent is in the range + // [alpha, gamma]. + + const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); + + const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k + + // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] + const diyfp w = diyfp::mul(v, c_minus_k); + const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); + const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); + + // ----(---+---)---------------(---+---)---------------(---+---)---- + // w- w w+ + // = c*m- = c*v = c*m+ + // + // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and + // w+ are now off by a small amount. + // In fact: + // + // w - v * 10^k < 1 ulp + // + // To account for this inaccuracy, add resp. subtract 1 ulp. + // + // --------+---[---------------(---+---)---------------]---+-------- + // w- M- w M+ w+ + // + // Now any number in [M-, M+] (bounds included) will round to w when input, + // regardless of how the input rounding algorithm breaks ties. + // + // And digit_gen generates the shortest possible such number in [M-, M+]. + // Note that this does not mean that Grisu2 always generates the shortest + // possible number in the interval (m-, m+). + const diyfp M_minus(w_minus.f + 1, w_minus.e); + const diyfp M_plus (w_plus.f - 1, w_plus.e ); + + decimal_exponent = -cached.k; // = -(-k) = k + + grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +template +JSON_HEDLEY_NON_NULL(1) +void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) +{ + static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3, + "internal error: not enough precision"); + + JSON_ASSERT(std::isfinite(value)); + JSON_ASSERT(value > 0); + + // If the neighbors (and boundaries) of 'value' are always computed for double-precision + // numbers, all float's can be recovered using strtod (and strtof). However, the resulting + // decimal representations are not exactly "short". + // + // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) + // says "value is converted to a string as if by std::sprintf in the default ("C") locale" + // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars' + // does. + // On the other hand, the documentation for 'std::to_chars' requires that "parsing the + // representation using the corresponding std::from_chars function recovers value exactly". That + // indicates that single precision floating-point numbers should be recovered using + // 'std::strtof'. + // + // NB: If the neighbors are computed for single-precision numbers, there is a single float + // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision + // value is off by 1 ulp. +#if 0 + const boundaries w = compute_boundaries(static_cast(value)); +#else + const boundaries w = compute_boundaries(value); +#endif + + grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); +} + +/*! +@brief appends a decimal representation of e to buf +@return a pointer to the element following the exponent. +@pre -1000 < e < 1000 +*/ +JSON_HEDLEY_NON_NULL(1) +JSON_HEDLEY_RETURNS_NON_NULL +inline char* append_exponent(char* buf, int e) +{ + JSON_ASSERT(e > -1000); + JSON_ASSERT(e < 1000); + + if (e < 0) + { + e = -e; + *buf++ = '-'; + } + else + { + *buf++ = '+'; + } + + auto k = static_cast(e); + if (k < 10) + { + // Always print at least two digits in the exponent. + // This is for compatibility with printf("%g"). + *buf++ = '0'; + *buf++ = static_cast('0' + k); + } + else if (k < 100) + { + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } + else + { + *buf++ = static_cast('0' + k / 100); + k %= 100; + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } + + return buf; +} + +/*! +@brief prettify v = buf * 10^decimal_exponent + +If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point +notation. Otherwise it will be printed in exponential notation. + +@pre min_exp < 0 +@pre max_exp > 0 +*/ +JSON_HEDLEY_NON_NULL(1) +JSON_HEDLEY_RETURNS_NON_NULL +inline char* format_buffer(char* buf, int len, int decimal_exponent, + int min_exp, int max_exp) +{ + JSON_ASSERT(min_exp < 0); + JSON_ASSERT(max_exp > 0); + + const int k = len; + const int n = len + decimal_exponent; + + // v = buf * 10^(n-k) + // k is the length of the buffer (number of decimal digits) + // n is the position of the decimal point relative to the start of the buffer. + + if (k <= n && n <= max_exp) + { + // digits[000] + // len <= max_exp + 2 + + std::memset(buf + k, '0', static_cast(n) - static_cast(k)); + // Make it look like a floating-point number (#362, #378) + buf[n + 0] = '.'; + buf[n + 1] = '0'; + return buf + (static_cast(n) + 2); + } + + if (0 < n && n <= max_exp) + { + // dig.its + // len <= max_digits10 + 1 + + JSON_ASSERT(k > n); + + std::memmove(buf + (static_cast(n) + 1), buf + n, static_cast(k) - static_cast(n)); + buf[n] = '.'; + return buf + (static_cast(k) + 1U); + } + + if (min_exp < n && n <= 0) + { + // 0.[000]digits + // len <= 2 + (-min_exp - 1) + max_digits10 + + std::memmove(buf + (2 + static_cast(-n)), buf, static_cast(k)); + buf[0] = '0'; + buf[1] = '.'; + std::memset(buf + 2, '0', static_cast(-n)); + return buf + (2U + static_cast(-n) + static_cast(k)); + } + + if (k == 1) + { + // dE+123 + // len <= 1 + 5 + + buf += 1; + } + else + { + // d.igitsE+123 + // len <= max_digits10 + 1 + 5 + + std::memmove(buf + 2, buf + 1, static_cast(k) - 1); + buf[1] = '.'; + buf += 1 + static_cast(k); + } + + *buf++ = 'e'; + return append_exponent(buf, n - 1); +} + +} // namespace dtoa_impl + +/*! +@brief generates a decimal representation of the floating-point number value in [first, last). + +The format of the resulting decimal representation is similar to printf's %g +format. Returns an iterator pointing past-the-end of the decimal representation. + +@note The input number must be finite, i.e. NaN's and Inf's are not supported. +@note The buffer must be large enough. +@note The result is NOT null-terminated. +*/ +template +JSON_HEDLEY_NON_NULL(1, 2) +JSON_HEDLEY_RETURNS_NON_NULL +char* to_chars(char* first, const char* last, FloatType value) +{ + static_cast(last); // maybe unused - fix warning + JSON_ASSERT(std::isfinite(value)); + + // Use signbit(value) instead of (value < 0) since signbit works for -0. + if (std::signbit(value)) + { + value = -value; + *first++ = '-'; + } + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + if (value == 0) // +-0 + { + *first++ = '0'; + // Make it look like a floating-point number (#362, #378) + *first++ = '.'; + *first++ = '0'; + return first; + } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + + JSON_ASSERT(last - first >= std::numeric_limits::max_digits10); + + // Compute v = buffer * 10^decimal_exponent. + // The decimal digits are stored in the buffer, which needs to be interpreted + // as an unsigned decimal integer. + // len is the length of the buffer, i.e. the number of decimal digits. + int len = 0; + int decimal_exponent = 0; + dtoa_impl::grisu2(first, len, decimal_exponent, value); + + JSON_ASSERT(len <= std::numeric_limits::max_digits10); + + // Format the buffer like printf("%.*g", prec, value) + constexpr int kMinExp = -4; + // Use digits10 here to increase compatibility with version 2. + constexpr int kMaxExp = std::numeric_limits::digits10; + + JSON_ASSERT(last - first >= kMaxExp + 2); + JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits::max_digits10); + JSON_ASSERT(last - first >= std::numeric_limits::max_digits10 + 6); + + return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); +} + +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +/////////////////// +// serialization // +/////////////////// + +/// how to treat decoding errors +enum class error_handler_t +{ + strict, ///< throw a type_error exception in case of invalid UTF-8 + replace, ///< replace invalid UTF-8 sequences with U+FFFD + ignore ///< ignore invalid UTF-8 sequences +}; + +template +class serializer +{ + using string_t = typename BasicJsonType::string_t; + using number_float_t = typename BasicJsonType::number_float_t; + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using binary_char_t = typename BasicJsonType::binary_t::value_type; + static constexpr std::uint8_t UTF8_ACCEPT = 0; + static constexpr std::uint8_t UTF8_REJECT = 1; + + public: + /*! + @param[in] s output stream to serialize to + @param[in] ichar indentation character to use + @param[in] error_handler_ how to react on decoding errors + */ + serializer(output_adapter_t s, const char ichar, + error_handler_t error_handler_ = error_handler_t::strict) + : o(std::move(s)) + , loc(std::localeconv()) + , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->thousands_sep))) + , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->decimal_point))) + , indent_char(ichar) + , indent_string(512, indent_char) + , error_handler(error_handler_) + {} + + // delete because of pointer members + serializer(const serializer&) = delete; + serializer& operator=(const serializer&) = delete; + serializer(serializer&&) = delete; + serializer& operator=(serializer&&) = delete; + ~serializer() = default; + + /*! + @brief internal implementation of the serialization function + + This function is called by the public member function dump and organizes + the serialization internally. The indentation level is propagated as + additional parameter. In case of arrays and objects, the function is + called recursively. + + - strings and object keys are escaped using `escape_string()` + - integer numbers are converted implicitly via `operator<<` + - floating-point numbers are converted to a string using `"%g"` format + - binary values are serialized as objects containing the subtype and the + byte array + + @param[in] val value to serialize + @param[in] pretty_print whether the output shall be pretty-printed + @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters + in the output are escaped with `\uXXXX` sequences, and the result consists + of ASCII characters only. + @param[in] indent_step the indent level + @param[in] current_indent the current indent level (only used internally) + */ + void dump(const BasicJsonType& val, + const bool pretty_print, + const bool ensure_ascii, + const unsigned int indent_step, + const unsigned int current_indent = 0) + { + switch (val.m_type) + { + case value_t::object: + { + if (val.m_value.object->empty()) + { + o->write_characters("{}", 2); + return; + } + + if (pretty_print) + { + o->write_characters("{\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) + { + indent_string.resize(indent_string.size() * 2, ' '); + } + + // first n-1 elements + auto i = val.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + { + o->write_characters(indent_string.c_str(), new_indent); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\": ", 3); + dump(i->second, true, ensure_ascii, indent_step, new_indent); + o->write_characters(",\n", 2); + } + + // last element + JSON_ASSERT(i != val.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_value.object->cend()); + o->write_characters(indent_string.c_str(), new_indent); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\": ", 3); + dump(i->second, true, ensure_ascii, indent_step, new_indent); + + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character('}'); + } + else + { + o->write_character('{'); + + // first n-1 elements + auto i = val.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) + { + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\":", 2); + dump(i->second, false, ensure_ascii, indent_step, current_indent); + o->write_character(','); + } + + // last element + JSON_ASSERT(i != val.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_value.object->cend()); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\":", 2); + dump(i->second, false, ensure_ascii, indent_step, current_indent); + + o->write_character('}'); + } + + return; + } + + case value_t::array: + { + if (val.m_value.array->empty()) + { + o->write_characters("[]", 2); + return; + } + + if (pretty_print) + { + o->write_characters("[\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) + { + indent_string.resize(indent_string.size() * 2, ' '); + } + + // first n-1 elements + for (auto i = val.m_value.array->cbegin(); + i != val.m_value.array->cend() - 1; ++i) + { + o->write_characters(indent_string.c_str(), new_indent); + dump(*i, true, ensure_ascii, indent_step, new_indent); + o->write_characters(",\n", 2); + } + + // last element + JSON_ASSERT(!val.m_value.array->empty()); + o->write_characters(indent_string.c_str(), new_indent); + dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); + + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character(']'); + } + else + { + o->write_character('['); + + // first n-1 elements + for (auto i = val.m_value.array->cbegin(); + i != val.m_value.array->cend() - 1; ++i) + { + dump(*i, false, ensure_ascii, indent_step, current_indent); + o->write_character(','); + } + + // last element + JSON_ASSERT(!val.m_value.array->empty()); + dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); + + o->write_character(']'); + } + + return; + } + + case value_t::string: + { + o->write_character('\"'); + dump_escaped(*val.m_value.string, ensure_ascii); + o->write_character('\"'); + return; + } + + case value_t::binary: + { + if (pretty_print) + { + o->write_characters("{\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) + { + indent_string.resize(indent_string.size() * 2, ' '); + } + + o->write_characters(indent_string.c_str(), new_indent); + + o->write_characters("\"bytes\": [", 10); + + if (!val.m_value.binary->empty()) + { + for (auto i = val.m_value.binary->cbegin(); + i != val.m_value.binary->cend() - 1; ++i) + { + dump_integer(*i); + o->write_characters(", ", 2); + } + dump_integer(val.m_value.binary->back()); + } + + o->write_characters("],\n", 3); + o->write_characters(indent_string.c_str(), new_indent); + + o->write_characters("\"subtype\": ", 11); + if (val.m_value.binary->has_subtype()) + { + dump_integer(val.m_value.binary->subtype()); + } + else + { + o->write_characters("null", 4); + } + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character('}'); + } + else + { + o->write_characters("{\"bytes\":[", 10); + + if (!val.m_value.binary->empty()) + { + for (auto i = val.m_value.binary->cbegin(); + i != val.m_value.binary->cend() - 1; ++i) + { + dump_integer(*i); + o->write_character(','); + } + dump_integer(val.m_value.binary->back()); + } + + o->write_characters("],\"subtype\":", 12); + if (val.m_value.binary->has_subtype()) + { + dump_integer(val.m_value.binary->subtype()); + o->write_character('}'); + } + else + { + o->write_characters("null}", 5); + } + } + return; + } + + case value_t::boolean: + { + if (val.m_value.boolean) + { + o->write_characters("true", 4); + } + else + { + o->write_characters("false", 5); + } + return; + } + + case value_t::number_integer: + { + dump_integer(val.m_value.number_integer); + return; + } + + case value_t::number_unsigned: + { + dump_integer(val.m_value.number_unsigned); + return; + } + + case value_t::number_float: + { + dump_float(val.m_value.number_float); + return; + } + + case value_t::discarded: + { + o->write_characters("", 11); + return; + } + + case value_t::null: + { + o->write_characters("null", 4); + return; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + } + + JSON_PRIVATE_UNLESS_TESTED: + /*! + @brief dump escaped string + + Escape a string by replacing certain special characters by a sequence of an + escape character (backslash) and another character and other control + characters by a sequence of "\u" followed by a four-digit hex + representation. The escaped string is written to output stream @a o. + + @param[in] s the string to escape + @param[in] ensure_ascii whether to escape non-ASCII characters with + \uXXXX sequences + + @complexity Linear in the length of string @a s. + */ + void dump_escaped(const string_t& s, const bool ensure_ascii) + { + std::uint32_t codepoint{}; + std::uint8_t state = UTF8_ACCEPT; + std::size_t bytes = 0; // number of bytes written to string_buffer + + // number of bytes written at the point of the last valid byte + std::size_t bytes_after_last_accept = 0; + std::size_t undumped_chars = 0; + + for (std::size_t i = 0; i < s.size(); ++i) + { + const auto byte = static_cast(s[i]); + + switch (decode(state, codepoint, byte)) + { + case UTF8_ACCEPT: // decode found a new code point + { + switch (codepoint) + { + case 0x08: // backspace + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'b'; + break; + } + + case 0x09: // horizontal tab + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 't'; + break; + } + + case 0x0A: // newline + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'n'; + break; + } + + case 0x0C: // formfeed + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'f'; + break; + } + + case 0x0D: // carriage return + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'r'; + break; + } + + case 0x22: // quotation mark + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = '\"'; + break; + } + + case 0x5C: // reverse solidus + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = '\\'; + break; + } + + default: + { + // escape control characters (0x00..0x1F) or, if + // ensure_ascii parameter is used, non-ASCII characters + if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) + { + if (codepoint <= 0xFFFF) + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", + static_cast(codepoint)); + bytes += 6; + } + else + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", + static_cast(0xD7C0u + (codepoint >> 10u)), + static_cast(0xDC00u + (codepoint & 0x3FFu))); + bytes += 12; + } + } + else + { + // copy byte to buffer (all previous bytes + // been copied have in default case above) + string_buffer[bytes++] = s[i]; + } + break; + } + } + + // write buffer and reset index; there must be 13 bytes + // left, as this is the maximal number of bytes to be + // written ("\uxxxx\uxxxx\0") for one code point + if (string_buffer.size() - bytes < 13) + { + o->write_characters(string_buffer.data(), bytes); + bytes = 0; + } + + // remember the byte position of this accept + bytes_after_last_accept = bytes; + undumped_chars = 0; + break; + } + + case UTF8_REJECT: // decode found invalid UTF-8 byte + { + switch (error_handler) + { + case error_handler_t::strict: + { + std::string sn(9, '\0'); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + (std::snprintf)(&sn[0], sn.size(), "%.2X", byte); + JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn, BasicJsonType())); + } + + case error_handler_t::ignore: + case error_handler_t::replace: + { + // in case we saw this character the first time, we + // would like to read it again, because the byte + // may be OK for itself, but just not OK for the + // previous sequence + if (undumped_chars > 0) + { + --i; + } + + // reset length buffer to the last accepted index; + // thus removing/ignoring the invalid characters + bytes = bytes_after_last_accept; + + if (error_handler == error_handler_t::replace) + { + // add a replacement character + if (ensure_ascii) + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'u'; + string_buffer[bytes++] = 'f'; + string_buffer[bytes++] = 'f'; + string_buffer[bytes++] = 'f'; + string_buffer[bytes++] = 'd'; + } + else + { + string_buffer[bytes++] = detail::binary_writer::to_char_type('\xEF'); + string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBF'); + string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBD'); + } + + // write buffer and reset index; there must be 13 bytes + // left, as this is the maximal number of bytes to be + // written ("\uxxxx\uxxxx\0") for one code point + if (string_buffer.size() - bytes < 13) + { + o->write_characters(string_buffer.data(), bytes); + bytes = 0; + } + + bytes_after_last_accept = bytes; + } + + undumped_chars = 0; + + // continue processing the string + state = UTF8_ACCEPT; + break; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + break; + } + + default: // decode found yet incomplete multi-byte code point + { + if (!ensure_ascii) + { + // code point will not be escaped - copy byte to buffer + string_buffer[bytes++] = s[i]; + } + ++undumped_chars; + break; + } + } + } + + // we finished processing the string + if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) + { + // write buffer + if (bytes > 0) + { + o->write_characters(string_buffer.data(), bytes); + } + } + else + { + // we finish reading, but do not accept: string was incomplete + switch (error_handler) + { + case error_handler_t::strict: + { + std::string sn(9, '\0'); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast(s.back())); + JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn, BasicJsonType())); + } + + case error_handler_t::ignore: + { + // write all accepted bytes + o->write_characters(string_buffer.data(), bytes_after_last_accept); + break; + } + + case error_handler_t::replace: + { + // write all accepted bytes + o->write_characters(string_buffer.data(), bytes_after_last_accept); + // add a replacement character + if (ensure_ascii) + { + o->write_characters("\\ufffd", 6); + } + else + { + o->write_characters("\xEF\xBF\xBD", 3); + } + break; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + } + } + + private: + /*! + @brief count digits + + Count the number of decimal (base 10) digits for an input unsigned integer. + + @param[in] x unsigned integer number to count its digits + @return number of decimal digits + */ + inline unsigned int count_digits(number_unsigned_t x) noexcept + { + unsigned int n_digits = 1; + for (;;) + { + if (x < 10) + { + return n_digits; + } + if (x < 100) + { + return n_digits + 1; + } + if (x < 1000) + { + return n_digits + 2; + } + if (x < 10000) + { + return n_digits + 3; + } + x = x / 10000u; + n_digits += 4; + } + } + + /*! + @brief dump an integer + + Dump a given integer to output stream @a o. Works internally with + @a number_buffer. + + @param[in] x integer number (signed or unsigned) to dump + @tparam NumberType either @a number_integer_t or @a number_unsigned_t + */ + template < typename NumberType, detail::enable_if_t < + std::is_integral::value || + std::is_same::value || + std::is_same::value || + std::is_same::value, + int > = 0 > + void dump_integer(NumberType x) + { + static constexpr std::array, 100> digits_to_99 + { + { + {{'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'}}, + } + }; + + // special case for "0" + if (x == 0) + { + o->write_character('0'); + return; + } + + // use a pointer to fill the buffer + auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg) + + const bool is_negative = std::is_signed::value && !(x >= 0); // see issue #755 + number_unsigned_t abs_value; + + unsigned int n_chars{}; + + if (is_negative) + { + *buffer_ptr = '-'; + abs_value = remove_sign(static_cast(x)); + + // account one more byte for the minus sign + n_chars = 1 + count_digits(abs_value); + } + else + { + abs_value = static_cast(x); + n_chars = count_digits(abs_value); + } + + // spare 1 byte for '\0' + JSON_ASSERT(n_chars < number_buffer.size() - 1); + + // jump to the end to generate the string from backward + // so we later avoid reversing the result + buffer_ptr += n_chars; + + // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu + // See: https://www.youtube.com/watch?v=o4-CwDo2zpg + while (abs_value >= 100) + { + const auto digits_index = static_cast((abs_value % 100)); + abs_value /= 100; + *(--buffer_ptr) = digits_to_99[digits_index][1]; + *(--buffer_ptr) = digits_to_99[digits_index][0]; + } + + if (abs_value >= 10) + { + const auto digits_index = static_cast(abs_value); + *(--buffer_ptr) = digits_to_99[digits_index][1]; + *(--buffer_ptr) = digits_to_99[digits_index][0]; + } + else + { + *(--buffer_ptr) = static_cast('0' + abs_value); + } + + o->write_characters(number_buffer.data(), n_chars); + } + + /*! + @brief dump a floating-point number + + Dump a given floating-point number to output stream @a o. Works internally + with @a number_buffer. + + @param[in] x floating-point number to dump + */ + void dump_float(number_float_t x) + { + // NaN / inf + if (!std::isfinite(x)) + { + o->write_characters("null", 4); + return; + } + + // If number_float_t is an IEEE-754 single or double precision number, + // use the Grisu2 algorithm to produce short numbers which are + // guaranteed to round-trip, using strtof and strtod, resp. + // + // NB: The test below works if == . + static constexpr bool is_ieee_single_or_double + = (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 24 && std::numeric_limits::max_exponent == 128) || + (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 53 && std::numeric_limits::max_exponent == 1024); + + dump_float(x, std::integral_constant()); + } + + void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) + { + auto* begin = number_buffer.data(); + auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); + + o->write_characters(begin, static_cast(end - begin)); + } + + void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) + { + // get number of digits for a float -> text -> float round-trip + static constexpr auto d = std::numeric_limits::max_digits10; + + // the actual conversion + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); + + // negative value indicates an error + JSON_ASSERT(len > 0); + // check if buffer was large enough + JSON_ASSERT(static_cast(len) < number_buffer.size()); + + // erase thousands separator + if (thousands_sep != '\0') + { + // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081 + const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep); + std::fill(end, number_buffer.end(), '\0'); + JSON_ASSERT((end - number_buffer.begin()) <= len); + len = (end - number_buffer.begin()); + } + + // convert decimal point to '.' + if (decimal_point != '\0' && decimal_point != '.') + { + // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081 + const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); + if (dec_pos != number_buffer.end()) + { + *dec_pos = '.'; + } + } + + o->write_characters(number_buffer.data(), static_cast(len)); + + // determine if need to append ".0" + const bool value_is_int_like = + std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, + [](char c) + { + return c == '.' || c == 'e'; + }); + + if (value_is_int_like) + { + o->write_characters(".0", 2); + } + } + + /*! + @brief check whether a string is UTF-8 encoded + + The function checks each byte of a string whether it is UTF-8 encoded. The + result of the check is stored in the @a state parameter. The function must + be called initially with state 0 (accept). State 1 means the string must + be rejected, because the current byte is not allowed. If the string is + completely processed, but the state is non-zero, the string ended + prematurely; that is, the last byte indicated more bytes should have + followed. + + @param[in,out] state the state of the decoding + @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT) + @param[in] byte next byte to decode + @return new state + + @note The function has been edited: a std::array is used. + + @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann + @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + */ + static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept + { + static const std::array utf8d = + { + { + 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, // 00..1F + 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, // 20..3F + 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, // 40..5F + 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, // 60..7F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF + 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, // C0..DF + 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF + 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF + 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 + 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 + 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 + 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8 + } + }; + + JSON_ASSERT(byte < utf8d.size()); + const std::uint8_t type = utf8d[byte]; + + codep = (state != UTF8_ACCEPT) + ? (byte & 0x3fu) | (codep << 6u) + : (0xFFu >> type) & (byte); + + std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); + JSON_ASSERT(index < 400); + state = utf8d[index]; + return state; + } + + /* + * Overload to make the compiler happy while it is instantiating + * dump_integer for number_unsigned_t. + * Must never be called. + */ + number_unsigned_t remove_sign(number_unsigned_t x) + { + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return x; // LCOV_EXCL_LINE + } + + /* + * Helper function for dump_integer + * + * This function takes a negative signed integer and returns its absolute + * value as unsigned integer. The plus/minus shuffling is necessary as we can + * not directly remove the sign of an arbitrary signed integer as the + * absolute values of INT_MIN and INT_MAX are usually not the same. See + * #1708 for details. + */ + inline number_unsigned_t remove_sign(number_integer_t x) noexcept + { + JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); // NOLINT(misc-redundant-expression) + return static_cast(-(x + 1)) + 1; + } + + private: + /// the output of the serializer + output_adapter_t o = nullptr; + + /// a (hopefully) large enough character buffer + std::array number_buffer{{}}; + + /// the locale + const std::lconv* loc = nullptr; + /// the locale's thousand separator character + const char thousands_sep = '\0'; + /// the locale's decimal point character + const char decimal_point = '\0'; + + /// string buffer + std::array string_buffer{{}}; + + /// the indentation character + const char indent_char; + /// the indentation string + string_t indent_string; + + /// error_handler how to react on decoding errors + const error_handler_t error_handler; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + + +#include // less +#include // initializer_list +#include // input_iterator_tag, iterator_traits +#include // allocator +#include // for out_of_range +#include // enable_if, is_convertible +#include // pair +#include // vector + +// #include + + +namespace nlohmann +{ + +/// ordered_map: a minimal map-like container that preserves insertion order +/// for use within nlohmann::basic_json +template , + class Allocator = std::allocator>> + struct ordered_map : std::vector, Allocator> +{ + using key_type = Key; + using mapped_type = T; + using Container = std::vector, Allocator>; + using typename Container::iterator; + using typename Container::const_iterator; + using typename Container::size_type; + using typename Container::value_type; + + // Explicit constructors instead of `using Container::Container` + // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) + ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {} + template + ordered_map(It first, It last, const Allocator& alloc = Allocator()) + : Container{first, last, alloc} {} + ordered_map(std::initializer_list init, const Allocator& alloc = Allocator() ) + : Container{init, alloc} {} + + std::pair emplace(const key_type& key, T&& t) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return {it, false}; + } + } + Container::emplace_back(key, t); + return {--this->end(), true}; + } + + T& operator[](const Key& key) + { + return emplace(key, T{}).first->second; + } + + const T& operator[](const Key& key) const + { + return at(key); + } + + T& at(const Key& key) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return it->second; + } + } + + JSON_THROW(std::out_of_range("key not found")); + } + + const T& at(const Key& key) const + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return it->second; + } + } + + JSON_THROW(std::out_of_range("key not found")); + } + + size_type erase(const Key& key) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + // Since we cannot move const Keys, re-construct them in place + for (auto next = it; ++next != this->end(); ++it) + { + it->~value_type(); // Destroy but keep allocation + new (&*it) value_type{std::move(*next)}; + } + Container::pop_back(); + return 1; + } + } + return 0; + } + + iterator erase(iterator pos) + { + auto it = pos; + + // Since we cannot move const Keys, re-construct them in place + for (auto next = it; ++next != this->end(); ++it) + { + it->~value_type(); // Destroy but keep allocation + new (&*it) value_type{std::move(*next)}; + } + Container::pop_back(); + return pos; + } + + size_type count(const Key& key) const + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return 1; + } + } + return 0; + } + + iterator find(const Key& key) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return it; + } + } + return Container::end(); + } + + const_iterator find(const Key& key) const + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == key) + { + return it; + } + } + return Container::end(); + } + + std::pair insert( value_type&& value ) + { + return emplace(value.first, std::move(value.second)); + } + + std::pair insert( const value_type& value ) + { + for (auto it = this->begin(); it != this->end(); ++it) + { + if (it->first == value.first) + { + return {it, false}; + } + } + Container::push_back(value); + return {--this->end(), true}; + } + + template + using require_input_iter = typename std::enable_if::iterator_category, + std::input_iterator_tag>::value>::type; + + template> + void insert(InputIt first, InputIt last) + { + for (auto it = first; it != last; ++it) + { + insert(*it); + } + } +}; + +} // namespace nlohmann + + +#if defined(JSON_HAS_CPP_17) + #include +#endif + +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +namespace nlohmann +{ + +/*! +@brief a class to store JSON values + +@tparam ObjectType type for JSON objects (`std::map` by default; will be used +in @ref object_t) +@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used +in @ref array_t) +@tparam StringType type for JSON strings and object keys (`std::string` by +default; will be used in @ref string_t) +@tparam BooleanType type for JSON booleans (`bool` by default; will be used +in @ref boolean_t) +@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by +default; will be used in @ref number_integer_t) +@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c +`uint64_t` by default; will be used in @ref number_unsigned_t) +@tparam NumberFloatType type for JSON floating-point numbers (`double` by +default; will be used in @ref number_float_t) +@tparam BinaryType type for packed binary data for compatibility with binary +serialization formats (`std::vector` by default; will be used in +@ref binary_t) +@tparam AllocatorType type of the allocator to use (`std::allocator` by +default) +@tparam JSONSerializer the serializer to resolve internal calls to `to_json()` +and `from_json()` (@ref adl_serializer by default) + +@requirement The class satisfies the following concept requirements: +- Basic + - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible): + JSON values can be default constructed. The result will be a JSON null + value. + - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible): + A JSON value can be constructed from an rvalue argument. + - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible): + A JSON value can be copy-constructed from an lvalue expression. + - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable): + A JSON value van be assigned from an rvalue argument. + - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable): + A JSON value can be copy-assigned from an lvalue expression. + - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible): + JSON values can be destructed. +- Layout + - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType): + JSON values have + [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout): + All non-static data members are private and standard layout types, the + class has no virtual functions or (virtual) base classes. +- Library-wide + - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable): + JSON values can be compared with `==`, see @ref + operator==(const_reference,const_reference). + - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable): + JSON values can be compared with `<`, see @ref + operator<(const_reference,const_reference). + - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable): + Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of + other compatible types, using unqualified function call @ref swap(). + - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer): + JSON values can be compared against `std::nullptr_t` objects which are used + to model the `null` value. +- Container + - [Container](https://en.cppreference.com/w/cpp/named_req/Container): + JSON values can be used like STL containers and provide iterator access. + - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer); + JSON values can be used like STL containers and provide reverse iterator + access. + +@invariant The member variables @a m_value and @a m_type have the following +relationship: +- If `m_type == value_t::object`, then `m_value.object != nullptr`. +- If `m_type == value_t::array`, then `m_value.array != nullptr`. +- If `m_type == value_t::string`, then `m_value.string != nullptr`. +The invariants are checked by member function assert_invariant(). + +@internal +@note ObjectType trick from https://stackoverflow.com/a/9860911 +@endinternal + +@see [RFC 8259: The JavaScript Object Notation (JSON) Data Interchange +Format](https://tools.ietf.org/html/rfc8259) + +@since version 1.0.0 + +@nosubgrouping +*/ +NLOHMANN_BASIC_JSON_TPL_DECLARATION +class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) +{ + private: + template friend struct detail::external_constructor; + friend ::nlohmann::json_pointer; + + template + friend class ::nlohmann::detail::parser; + friend ::nlohmann::detail::serializer; + template + friend class ::nlohmann::detail::iter_impl; + template + friend class ::nlohmann::detail::binary_writer; + template + friend class ::nlohmann::detail::binary_reader; + template + friend class ::nlohmann::detail::json_sax_dom_parser; + template + friend class ::nlohmann::detail::json_sax_dom_callback_parser; + friend class ::nlohmann::detail::exception; + + /// workaround type for MSVC + using basic_json_t = NLOHMANN_BASIC_JSON_TPL; + + JSON_PRIVATE_UNLESS_TESTED: + // convenience aliases for types residing in namespace detail; + using lexer = ::nlohmann::detail::lexer_base; + + template + static ::nlohmann::detail::parser parser( + InputAdapterType adapter, + detail::parser_callback_tcb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false + ) + { + return ::nlohmann::detail::parser(std::move(adapter), + std::move(cb), allow_exceptions, ignore_comments); + } + + private: + using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; + template + using internal_iterator = ::nlohmann::detail::internal_iterator; + template + using iter_impl = ::nlohmann::detail::iter_impl; + template + using iteration_proxy = ::nlohmann::detail::iteration_proxy; + template using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator; + + template + using output_adapter_t = ::nlohmann::detail::output_adapter_t; + + template + using binary_reader = ::nlohmann::detail::binary_reader; + template using binary_writer = ::nlohmann::detail::binary_writer; + + JSON_PRIVATE_UNLESS_TESTED: + using serializer = ::nlohmann::detail::serializer; + + public: + using value_t = detail::value_t; + /// JSON Pointer, see @ref nlohmann::json_pointer + using json_pointer = ::nlohmann::json_pointer; + template + using json_serializer = JSONSerializer; + /// how to treat decoding errors + using error_handler_t = detail::error_handler_t; + /// how to treat CBOR tags + using cbor_tag_handler_t = detail::cbor_tag_handler_t; + /// helper type for initializer lists of basic_json values + using initializer_list_t = std::initializer_list>; + + using input_format_t = detail::input_format_t; + /// SAX interface type, see @ref nlohmann::json_sax + using json_sax_t = json_sax; + + //////////////// + // exceptions // + //////////////// + + /// @name exceptions + /// Classes to implement user-defined exceptions. + /// @{ + + /// @copydoc detail::exception + using exception = detail::exception; + /// @copydoc detail::parse_error + using parse_error = detail::parse_error; + /// @copydoc detail::invalid_iterator + using invalid_iterator = detail::invalid_iterator; + /// @copydoc detail::type_error + using type_error = detail::type_error; + /// @copydoc detail::out_of_range + using out_of_range = detail::out_of_range; + /// @copydoc detail::other_error + using other_error = detail::other_error; + + /// @} + + + ///////////////////// + // container types // + ///////////////////// + + /// @name container types + /// The canonic container types to use @ref basic_json like any other STL + /// container. + /// @{ + + /// the type of elements in a basic_json container + using value_type = basic_json; + + /// the type of an element reference + using reference = value_type&; + /// the type of an element const reference + using const_reference = const value_type&; + + /// a type to represent differences between iterators + using difference_type = std::ptrdiff_t; + /// a type to represent container sizes + using size_type = std::size_t; + + /// the allocator type + using allocator_type = AllocatorType; + + /// the type of an element pointer + using pointer = typename std::allocator_traits::pointer; + /// the type of an element const pointer + using const_pointer = typename std::allocator_traits::const_pointer; + + /// an iterator for a basic_json container + using iterator = iter_impl; + /// a const iterator for a basic_json container + using const_iterator = iter_impl; + /// a reverse iterator for a basic_json container + using reverse_iterator = json_reverse_iterator; + /// a const reverse iterator for a basic_json container + using const_reverse_iterator = json_reverse_iterator; + + /// @} + + + /*! + @brief returns the allocator associated with the container + */ + static allocator_type get_allocator() + { + return allocator_type(); + } + + /*! + @brief returns version information on the library + + This function returns a JSON object with information about the library, + including the version number and information on the platform and compiler. + + @return JSON object holding version information + key | description + ----------- | --------------- + `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). + `copyright` | The copyright line for the library as string. + `name` | The name of the library as string. + `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. + `url` | The URL of the project as string. + `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string). + + @liveexample{The following code shows an example output of the `meta()` + function.,meta} + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @complexity Constant. + + @since 2.1.0 + */ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json meta() + { + basic_json result; + + result["copyright"] = "(C) 2013-2021 Niels Lohmann"; + result["name"] = "JSON for Modern C++"; + result["url"] = "https://github.com/nlohmann/json"; + result["version"]["string"] = + std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." + + std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." + + std::to_string(NLOHMANN_JSON_VERSION_PATCH); + result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; + result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; + result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; + +#ifdef _WIN32 + result["platform"] = "win32"; +#elif defined __linux__ + result["platform"] = "linux"; +#elif defined __APPLE__ + result["platform"] = "apple"; +#elif defined __unix__ + result["platform"] = "unix"; +#else + result["platform"] = "unknown"; +#endif + +#if defined(__ICC) || defined(__INTEL_COMPILER) + result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; +#elif defined(__clang__) + result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; +#elif defined(__GNUC__) || defined(__GNUG__) + result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; +#elif defined(__HP_cc) || defined(__HP_aCC) + result["compiler"] = "hp" +#elif defined(__IBMCPP__) + result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; +#elif defined(_MSC_VER) + result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; +#elif defined(__PGI) + result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; +#elif defined(__SUNPRO_CC) + result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; +#else + result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; +#endif + +#ifdef __cplusplus + result["compiler"]["c++"] = std::to_string(__cplusplus); +#else + result["compiler"]["c++"] = "unknown"; +#endif + return result; + } + + + /////////////////////////// + // JSON value data types // + /////////////////////////// + + /// @name JSON value data types + /// The data types to store a JSON value. These types are derived from + /// the template arguments passed to class @ref basic_json. + /// @{ + +#if defined(JSON_HAS_CPP_14) + // Use transparent comparator if possible, combined with perfect forwarding + // on find() and count() calls prevents unnecessary string construction. + using object_comparator_t = std::less<>; +#else + using object_comparator_t = std::less; +#endif + + /*! + @brief a type for an object + + [RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON objects as follows: + > An object is an unordered collection of zero or more name/value pairs, + > where a name is a string and a value is a string, number, boolean, null, + > object, or array. + + To store objects in C++, a type is defined by the template parameters + described below. + + @tparam ObjectType the container to store objects (e.g., `std::map` or + `std::unordered_map`) + @tparam StringType the type of the keys or names (e.g., `std::string`). + The comparison function `std::less` is used to order elements + inside the container. + @tparam AllocatorType the allocator to use for objects (e.g., + `std::allocator`) + + #### Default type + + With the default values for @a ObjectType (`std::map`), @a StringType + (`std::string`), and @a AllocatorType (`std::allocator`), the default + value for @a object_t is: + + @code {.cpp} + std::map< + std::string, // key_type + basic_json, // value_type + std::less, // key_compare + std::allocator> // allocator_type + > + @endcode + + #### Behavior + + The choice of @a object_t influences the behavior of the JSON class. With + the default type, objects have the following behavior: + + - When all names are unique, objects will be interoperable in the sense + that all software implementations receiving that object will agree on + the name-value mappings. + - When the names within an object are not unique, it is unspecified which + one of the values for a given key will be chosen. For instance, + `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or + `{"key": 2}`. + - Internally, name/value pairs are stored in lexicographical order of the + names. Objects will also be serialized (see @ref dump) in this order. + For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored + and serialized as `{"a": 2, "b": 1}`. + - When comparing objects, the order of the name/value pairs is irrelevant. + This makes objects interoperable in the sense that they will not be + affected by these differences. For instance, `{"b": 1, "a": 2}` and + `{"a": 2, "b": 1}` will be treated as equal. + + #### Limits + + [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies: + > An implementation may set limits on the maximum depth of nesting. + + In this class, the object's limit of nesting is not explicitly constrained. + However, a maximum depth of nesting may be introduced by the compiler or + runtime environment. A theoretical limit can be queried by calling the + @ref max_size function of a JSON object. + + #### Storage + + Objects are stored as pointers in a @ref basic_json type. That is, for any + access to object values, a pointer of type `object_t*` must be + dereferenced. + + @sa see @ref array_t -- type for an array value + + @since version 1.0.0 + + @note The order name/value pairs are added to the object is *not* + preserved by the library. Therefore, iterating an object may return + name/value pairs in a different order than they were originally stored. In + fact, keys will be traversed in alphabetical order as `std::map` with + `std::less` is used by default. Please note this behavior conforms to [RFC + 8259](https://tools.ietf.org/html/rfc8259), because any order implements the + specified "unordered" nature of JSON objects. + */ + using object_t = ObjectType>>; + + /*! + @brief a type for an array + + [RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON arrays as follows: + > An array is an ordered sequence of zero or more values. + + To store objects in C++, a type is defined by the template parameters + explained below. + + @tparam ArrayType container type to store arrays (e.g., `std::vector` or + `std::list`) + @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) + + #### Default type + + With the default values for @a ArrayType (`std::vector`) and @a + AllocatorType (`std::allocator`), the default value for @a array_t is: + + @code {.cpp} + std::vector< + basic_json, // value_type + std::allocator // allocator_type + > + @endcode + + #### Limits + + [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies: + > An implementation may set limits on the maximum depth of nesting. + + In this class, the array's limit of nesting is not explicitly constrained. + However, a maximum depth of nesting may be introduced by the compiler or + runtime environment. A theoretical limit can be queried by calling the + @ref max_size function of a JSON array. + + #### Storage + + Arrays are stored as pointers in a @ref basic_json type. That is, for any + access to array values, a pointer of type `array_t*` must be dereferenced. + + @sa see @ref object_t -- type for an object value + + @since version 1.0.0 + */ + using array_t = ArrayType>; + + /*! + @brief a type for a string + + [RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON strings as follows: + > A string is a sequence of zero or more Unicode characters. + + To store objects in C++, a type is defined by the template parameter + described below. Unicode values are split by the JSON class into + byte-sized characters during deserialization. + + @tparam StringType the container to store strings (e.g., `std::string`). + Note this container is used for keys/names in objects, see @ref object_t. + + #### Default type + + With the default values for @a StringType (`std::string`), the default + value for @a string_t is: + + @code {.cpp} + std::string + @endcode + + #### Encoding + + Strings are stored in UTF-8 encoding. Therefore, functions like + `std::string::size()` or `std::string::length()` return the number of + bytes in the string rather than the number of characters or glyphs. + + #### String comparison + + [RFC 8259](https://tools.ietf.org/html/rfc8259) states: + > Software implementations are typically required to test names of object + > members for equality. Implementations that transform the textual + > representation into sequences of Unicode code units and then perform the + > comparison numerically, code unit by code unit, are interoperable in the + > sense that implementations will agree in all cases on equality or + > inequality of two strings. For example, implementations that compare + > strings with escaped characters unconverted may incorrectly find that + > `"a\\b"` and `"a\u005Cb"` are not equal. + + This implementation is interoperable as it does compare strings code unit + by code unit. + + #### Storage + + String values are stored as pointers in a @ref basic_json type. That is, + for any access to string values, a pointer of type `string_t*` must be + dereferenced. + + @since version 1.0.0 + */ + using string_t = StringType; + + /*! + @brief a type for a boolean + + [RFC 8259](https://tools.ietf.org/html/rfc8259) implicitly describes a boolean as a + type which differentiates the two literals `true` and `false`. + + To store objects in C++, a type is defined by the template parameter @a + BooleanType which chooses the type to use. + + #### Default type + + With the default values for @a BooleanType (`bool`), the default value for + @a boolean_t is: + + @code {.cpp} + bool + @endcode + + #### Storage + + Boolean values are stored directly inside a @ref basic_json type. + + @since version 1.0.0 + */ + using boolean_t = BooleanType; + + /*! + @brief a type for a number (integer) + + [RFC 8259](https://tools.ietf.org/html/rfc8259) describes numbers as follows: + > The representation of numbers is similar to that used in most + > programming languages. A number is represented in base 10 using decimal + > digits. It contains an integer component that may be prefixed with an + > optional minus sign, which may be followed by a fraction part and/or an + > exponent part. Leading zeros are not allowed. (...) Numeric values that + > cannot be represented in the grammar below (such as Infinity and NaN) + > are not permitted. + + This description includes both integer and floating-point numbers. + However, C++ allows more precise storage if it is known whether the number + is a signed integer, an unsigned integer or a floating-point number. + Therefore, three different types, @ref number_integer_t, @ref + number_unsigned_t and @ref number_float_t are used. + + To store integer numbers in C++, a type is defined by the template + parameter @a NumberIntegerType which chooses the type to use. + + #### Default type + + With the default values for @a NumberIntegerType (`int64_t`), the default + value for @a number_integer_t is: + + @code {.cpp} + int64_t + @endcode + + #### Default behavior + + - The restrictions about leading zeros is not enforced in C++. Instead, + leading zeros in integer literals lead to an interpretation as octal + number. Internally, the value will be stored as decimal number. For + instance, the C++ integer literal `010` will be serialized to `8`. + During deserialization, leading zeros yield an error. + - Not-a-number (NaN) values will be serialized to `null`. + + #### Limits + + [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies: + > An implementation may set limits on the range and precision of numbers. + + When the default type is used, the maximal integer number that can be + stored is `9223372036854775807` (INT64_MAX) and the minimal integer number + that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers + that are out of range will yield over/underflow when used in a + constructor. During deserialization, too large or small integer numbers + will be automatically be stored as @ref number_unsigned_t or @ref + number_float_t. + + [RFC 8259](https://tools.ietf.org/html/rfc8259) further states: + > Note that when such software is used, numbers that are integers and are + > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense + > that implementations will agree exactly on their numeric values. + + As this range is a subrange of the exactly supported range [INT64_MIN, + INT64_MAX], this class's integer type is interoperable. + + #### Storage + + Integer number values are stored directly inside a @ref basic_json type. + + @sa see @ref number_float_t -- type for number values (floating-point) + + @sa see @ref number_unsigned_t -- type for number values (unsigned integer) + + @since version 1.0.0 + */ + using number_integer_t = NumberIntegerType; + + /*! + @brief a type for a number (unsigned) + + [RFC 8259](https://tools.ietf.org/html/rfc8259) describes numbers as follows: + > The representation of numbers is similar to that used in most + > programming languages. A number is represented in base 10 using decimal + > digits. It contains an integer component that may be prefixed with an + > optional minus sign, which may be followed by a fraction part and/or an + > exponent part. Leading zeros are not allowed. (...) Numeric values that + > cannot be represented in the grammar below (such as Infinity and NaN) + > are not permitted. + + This description includes both integer and floating-point numbers. + However, C++ allows more precise storage if it is known whether the number + is a signed integer, an unsigned integer or a floating-point number. + Therefore, three different types, @ref number_integer_t, @ref + number_unsigned_t and @ref number_float_t are used. + + To store unsigned integer numbers in C++, a type is defined by the + template parameter @a NumberUnsignedType which chooses the type to use. + + #### Default type + + With the default values for @a NumberUnsignedType (`uint64_t`), the + default value for @a number_unsigned_t is: + + @code {.cpp} + uint64_t + @endcode + + #### Default behavior + + - The restrictions about leading zeros is not enforced in C++. Instead, + leading zeros in integer literals lead to an interpretation as octal + number. Internally, the value will be stored as decimal number. For + instance, the C++ integer literal `010` will be serialized to `8`. + During deserialization, leading zeros yield an error. + - Not-a-number (NaN) values will be serialized to `null`. + + #### Limits + + [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies: + > An implementation may set limits on the range and precision of numbers. + + When the default type is used, the maximal integer number that can be + stored is `18446744073709551615` (UINT64_MAX) and the minimal integer + number that can be stored is `0`. Integer numbers that are out of range + will yield over/underflow when used in a constructor. During + deserialization, too large or small integer numbers will be automatically + be stored as @ref number_integer_t or @ref number_float_t. + + [RFC 8259](https://tools.ietf.org/html/rfc8259) further states: + > Note that when such software is used, numbers that are integers and are + > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense + > that implementations will agree exactly on their numeric values. + + As this range is a subrange (when considered in conjunction with the + number_integer_t type) of the exactly supported range [0, UINT64_MAX], + this class's integer type is interoperable. + + #### Storage + + Integer number values are stored directly inside a @ref basic_json type. + + @sa see @ref number_float_t -- type for number values (floating-point) + @sa see @ref number_integer_t -- type for number values (integer) + + @since version 2.0.0 + */ + using number_unsigned_t = NumberUnsignedType; + + /*! + @brief a type for a number (floating-point) + + [RFC 8259](https://tools.ietf.org/html/rfc8259) describes numbers as follows: + > The representation of numbers is similar to that used in most + > programming languages. A number is represented in base 10 using decimal + > digits. It contains an integer component that may be prefixed with an + > optional minus sign, which may be followed by a fraction part and/or an + > exponent part. Leading zeros are not allowed. (...) Numeric values that + > cannot be represented in the grammar below (such as Infinity and NaN) + > are not permitted. + + This description includes both integer and floating-point numbers. + However, C++ allows more precise storage if it is known whether the number + is a signed integer, an unsigned integer or a floating-point number. + Therefore, three different types, @ref number_integer_t, @ref + number_unsigned_t and @ref number_float_t are used. + + To store floating-point numbers in C++, a type is defined by the template + parameter @a NumberFloatType which chooses the type to use. + + #### Default type + + With the default values for @a NumberFloatType (`double`), the default + value for @a number_float_t is: + + @code {.cpp} + double + @endcode + + #### Default behavior + + - The restrictions about leading zeros is not enforced in C++. Instead, + leading zeros in floating-point literals will be ignored. Internally, + the value will be stored as decimal number. For instance, the C++ + floating-point literal `01.2` will be serialized to `1.2`. During + deserialization, leading zeros yield an error. + - Not-a-number (NaN) values will be serialized to `null`. + + #### Limits + + [RFC 8259](https://tools.ietf.org/html/rfc8259) states: + > This specification allows implementations to set limits on the range and + > precision of numbers accepted. Since software that implements IEEE + > 754-2008 binary64 (double precision) numbers is generally available and + > widely used, good interoperability can be achieved by implementations + > that expect no more precision or range than these provide, in the sense + > that implementations will approximate JSON numbers within the expected + > precision. + + This implementation does exactly follow this approach, as it uses double + precision floating-point numbers. Note values smaller than + `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` + will be stored as NaN internally and be serialized to `null`. + + #### Storage + + Floating-point number values are stored directly inside a @ref basic_json + type. + + @sa see @ref number_integer_t -- type for number values (integer) + + @sa see @ref number_unsigned_t -- type for number values (unsigned integer) + + @since version 1.0.0 + */ + using number_float_t = NumberFloatType; + + /*! + @brief a type for a packed binary type + + This type is a type designed to carry binary data that appears in various + serialized formats, such as CBOR's Major Type 2, MessagePack's bin, and + BSON's generic binary subtype. This type is NOT a part of standard JSON and + exists solely for compatibility with these binary types. As such, it is + simply defined as an ordered sequence of zero or more byte values. + + Additionally, as an implementation detail, the subtype of the binary data is + carried around as a `std::uint8_t`, which is compatible with both of the + binary data formats that use binary subtyping, (though the specific + numbering is incompatible with each other, and it is up to the user to + translate between them). + + [CBOR's RFC 7049](https://tools.ietf.org/html/rfc7049) describes this type + as: + > Major type 2: a byte string. The string's length in bytes is represented + > following the rules for positive integers (major type 0). + + [MessagePack's documentation on the bin type + family](https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family) + describes this type as: + > Bin format family stores an byte array in 2, 3, or 5 bytes of extra bytes + > in addition to the size of the byte array. + + [BSON's specifications](http://bsonspec.org/spec.html) describe several + binary types; however, this type is intended to represent the generic binary + type which has the description: + > Generic binary subtype - This is the most commonly used binary subtype and + > should be the 'default' for drivers and tools. + + None of these impose any limitations on the internal representation other + than the basic unit of storage be some type of array whose parts are + decomposable into bytes. + + The default representation of this binary format is a + `std::vector`, which is a very common way to represent a byte + array in modern C++. + + #### Default type + + The default values for @a BinaryType is `std::vector` + + #### Storage + + Binary Arrays are stored as pointers in a @ref basic_json type. That is, + for any access to array values, a pointer of the type `binary_t*` must be + dereferenced. + + #### Notes on subtypes + + - CBOR + - Binary values are represented as byte strings. Subtypes are serialized + as tagged values. + - MessagePack + - If a subtype is given and the binary array contains exactly 1, 2, 4, 8, + or 16 elements, the fixext family (fixext1, fixext2, fixext4, fixext8) + is used. For other sizes, the ext family (ext8, ext16, ext32) is used. + The subtype is then added as singed 8-bit integer. + - If no subtype is given, the bin family (bin8, bin16, bin32) is used. + - BSON + - If a subtype is given, it is used and added as unsigned 8-bit integer. + - If no subtype is given, the generic binary subtype 0x00 is used. + + @sa see @ref binary -- create a binary array + + @since version 3.8.0 + */ + using binary_t = nlohmann::byte_container_with_subtype; + /// @} + + private: + + /// helper for exception-safe object creation + template + JSON_HEDLEY_RETURNS_NON_NULL + static T* create(Args&& ... args) + { + AllocatorType alloc; + using AllocatorTraits = std::allocator_traits>; + + auto deleter = [&](T * obj) + { + AllocatorTraits::deallocate(alloc, obj, 1); + }; + std::unique_ptr obj(AllocatorTraits::allocate(alloc, 1), deleter); + AllocatorTraits::construct(alloc, obj.get(), std::forward(args)...); + JSON_ASSERT(obj != nullptr); + return obj.release(); + } + + //////////////////////// + // JSON value storage // + //////////////////////// + + JSON_PRIVATE_UNLESS_TESTED: + /*! + @brief a JSON value + + The actual storage for a JSON value of the @ref basic_json class. This + union combines the different storage types for the JSON value types + defined in @ref value_t. + + JSON type | value_t type | used type + --------- | --------------- | ------------------------ + object | object | pointer to @ref object_t + array | array | pointer to @ref array_t + string | string | pointer to @ref string_t + boolean | boolean | @ref boolean_t + number | number_integer | @ref number_integer_t + number | number_unsigned | @ref number_unsigned_t + number | number_float | @ref number_float_t + binary | binary | pointer to @ref binary_t + null | null | *no value is stored* + + @note Variable-length types (objects, arrays, and strings) are stored as + pointers. The size of the union should not exceed 64 bits if the default + value types are used. + + @since version 1.0.0 + */ + union json_value + { + /// object (stored with pointer to save storage) + object_t* object; + /// array (stored with pointer to save storage) + array_t* array; + /// string (stored with pointer to save storage) + string_t* string; + /// binary (stored with pointer to save storage) + binary_t* binary; + /// boolean + boolean_t boolean; + /// number (integer) + number_integer_t number_integer; + /// number (unsigned integer) + number_unsigned_t number_unsigned; + /// number (floating-point) + number_float_t number_float; + + /// default constructor (for null values) + json_value() = default; + /// constructor for booleans + json_value(boolean_t v) noexcept : boolean(v) {} + /// constructor for numbers (integer) + json_value(number_integer_t v) noexcept : number_integer(v) {} + /// constructor for numbers (unsigned) + json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} + /// constructor for numbers (floating-point) + json_value(number_float_t v) noexcept : number_float(v) {} + /// constructor for empty values of a given type + json_value(value_t t) + { + switch (t) + { + case value_t::object: + { + object = create(); + break; + } + + case value_t::array: + { + array = create(); + break; + } + + case value_t::string: + { + string = create(""); + break; + } + + case value_t::binary: + { + binary = create(); + break; + } + + case value_t::boolean: + { + boolean = boolean_t(false); + break; + } + + case value_t::number_integer: + { + number_integer = number_integer_t(0); + break; + } + + case value_t::number_unsigned: + { + number_unsigned = number_unsigned_t(0); + break; + } + + case value_t::number_float: + { + number_float = number_float_t(0.0); + break; + } + + case value_t::null: + { + object = nullptr; // silence warning, see #821 + break; + } + + case value_t::discarded: + default: + { + object = nullptr; // silence warning, see #821 + if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) + { + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.4", basic_json())); // LCOV_EXCL_LINE + } + break; + } + } + } + + /// constructor for strings + json_value(const string_t& value) + { + string = create(value); + } + + /// constructor for rvalue strings + json_value(string_t&& value) + { + string = create(std::move(value)); + } + + /// constructor for objects + json_value(const object_t& value) + { + object = create(value); + } + + /// constructor for rvalue objects + json_value(object_t&& value) + { + object = create(std::move(value)); + } + + /// constructor for arrays + json_value(const array_t& value) + { + array = create(value); + } + + /// constructor for rvalue arrays + json_value(array_t&& value) + { + array = create(std::move(value)); + } + + /// constructor for binary arrays + json_value(const typename binary_t::container_type& value) + { + binary = create(value); + } + + /// constructor for rvalue binary arrays + json_value(typename binary_t::container_type&& value) + { + binary = create(std::move(value)); + } + + /// constructor for binary arrays (internal type) + json_value(const binary_t& value) + { + binary = create(value); + } + + /// constructor for rvalue binary arrays (internal type) + json_value(binary_t&& value) + { + binary = create(std::move(value)); + } + + void destroy(value_t t) + { + if (t == value_t::array || t == value_t::object) + { + // flatten the current json_value to a heap-allocated stack + std::vector stack; + + // move the top-level items to stack + if (t == value_t::array) + { + stack.reserve(array->size()); + std::move(array->begin(), array->end(), std::back_inserter(stack)); + } + else + { + stack.reserve(object->size()); + for (auto&& it : *object) + { + stack.push_back(std::move(it.second)); + } + } + + while (!stack.empty()) + { + // move the last item to local variable to be processed + basic_json current_item(std::move(stack.back())); + stack.pop_back(); + + // if current_item is array/object, move + // its children to the stack to be processed later + if (current_item.is_array()) + { + std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack)); + + current_item.m_value.array->clear(); + } + else if (current_item.is_object()) + { + for (auto&& it : *current_item.m_value.object) + { + stack.push_back(std::move(it.second)); + } + + current_item.m_value.object->clear(); + } + + // it's now safe that current_item get destructed + // since it doesn't have any children + } + } + + switch (t) + { + case value_t::object: + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, object); + std::allocator_traits::deallocate(alloc, object, 1); + break; + } + + case value_t::array: + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, array); + std::allocator_traits::deallocate(alloc, array, 1); + break; + } + + case value_t::string: + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, string); + std::allocator_traits::deallocate(alloc, string, 1); + break; + } + + case value_t::binary: + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, binary); + std::allocator_traits::deallocate(alloc, binary, 1); + break; + } + + case value_t::null: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::discarded: + default: + { + break; + } + } + } + }; + + private: + /*! + @brief checks the class invariants + + This function asserts the class invariants. It needs to be called at the + end of every constructor to make sure that created objects respect the + invariant. Furthermore, it has to be called each time the type of a JSON + value is changed, because the invariant expresses a relationship between + @a m_type and @a m_value. + + Furthermore, the parent relation is checked for arrays and objects: If + @a check_parents true and the value is an array or object, then the + container's elements must have the current value as parent. + + @param[in] check_parents whether the parent relation should be checked. + The value is true by default and should only be set to false + during destruction of objects when the invariant does not + need to hold. + */ + void assert_invariant(bool check_parents = true) const noexcept + { + JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr); + JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr); + JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr); + JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr); + +#if JSON_DIAGNOSTICS + JSON_TRY + { + // cppcheck-suppress assertWithSideEffect + JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j) + { + return j.m_parent == this; + })); + } + JSON_CATCH(...) {} // LCOV_EXCL_LINE +#endif + static_cast(check_parents); + } + + void set_parents() + { +#if JSON_DIAGNOSTICS + switch (m_type) + { + case value_t::array: + { + for (auto& element : *m_value.array) + { + element.m_parent = this; + } + break; + } + + case value_t::object: + { + for (auto& element : *m_value.object) + { + element.second.m_parent = this; + } + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + break; + } +#endif + } + + iterator set_parents(iterator it, typename iterator::difference_type count) + { +#if JSON_DIAGNOSTICS + for (typename iterator::difference_type i = 0; i < count; ++i) + { + (it + i)->m_parent = this; + } +#else + static_cast(count); +#endif + return it; + } + + reference set_parent(reference j, std::size_t old_capacity = std::size_t(-1)) + { +#if JSON_DIAGNOSTICS + if (old_capacity != std::size_t(-1)) + { + // see https://github.com/nlohmann/json/issues/2838 + JSON_ASSERT(type() == value_t::array); + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + { + // capacity has changed: update all parents + set_parents(); + return j; + } + } + + // ordered_json uses a vector internally, so pointers could have + // been invalidated; see https://github.com/nlohmann/json/issues/2962 +#ifdef JSON_HEDLEY_MSVC_VERSION +#pragma warning(push ) +#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr +#endif + if (detail::is_ordered_map::value) + { + set_parents(); + return j; + } +#ifdef JSON_HEDLEY_MSVC_VERSION +#pragma warning( pop ) +#endif + + j.m_parent = this; +#else + static_cast(j); + static_cast(old_capacity); +#endif + return j; + } + + public: + ////////////////////////// + // JSON parser callback // + ////////////////////////// + + /*! + @brief parser event types + + The parser callback distinguishes the following events: + - `object_start`: the parser read `{` and started to process a JSON object + - `key`: the parser read a key of a value in an object + - `object_end`: the parser read `}` and finished processing a JSON object + - `array_start`: the parser read `[` and started to process a JSON array + - `array_end`: the parser read `]` and finished processing a JSON array + - `value`: the parser finished reading a JSON value + + @image html callback_events.png "Example when certain parse events are triggered" + + @sa see @ref parser_callback_t for more information and examples + */ + using parse_event_t = detail::parse_event_t; + + /*! + @brief per-element parser callback type + + With a parser callback function, the result of parsing a JSON text can be + influenced. When passed to @ref parse, it is called on certain events + (passed as @ref parse_event_t via parameter @a event) with a set recursion + depth @a depth and context JSON value @a parsed. The return value of the + callback function is a boolean indicating whether the element that emitted + the callback shall be kept or not. + + We distinguish six scenarios (determined by the event type) in which the + callback function can be called. The following table describes the values + of the parameters @a depth, @a event, and @a parsed. + + parameter @a event | description | parameter @a depth | parameter @a parsed + ------------------ | ----------- | ------------------ | ------------------- + parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded + parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key + parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object + parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded + parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array + parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value + + @image html callback_events.png "Example when certain parse events are triggered" + + Discarding a value (i.e., returning `false`) has different effects + depending on the context in which function was called: + + - Discarded values in structured types are skipped. That is, the parser + will behave as if the discarded value was never read. + - In case a value outside a structured type is skipped, it is replaced + with `null`. This case happens if the top-level element is skipped. + + @param[in] depth the depth of the recursion during parsing + + @param[in] event an event of type parse_event_t indicating the context in + the callback function has been called + + @param[in,out] parsed the current intermediate parse result; note that + writing to this value has no effect for parse_event_t::key events + + @return Whether the JSON value which called the function during parsing + should be kept (`true`) or not (`false`). In the latter case, it is either + skipped completely or replaced by an empty discarded object. + + @sa see @ref parse for examples + + @since version 1.0.0 + */ + using parser_callback_t = detail::parser_callback_t; + + ////////////////// + // constructors // + ////////////////// + + /// @name constructors and destructors + /// Constructors of class @ref basic_json, copy/move constructor, copy + /// assignment, static functions creating objects, and the destructor. + /// @{ + + /*! + @brief create an empty value with a given type + + Create an empty JSON value with a given type. The value will be default + initialized with an empty value which depends on the type: + + Value type | initial value + ----------- | ------------- + null | `null` + boolean | `false` + string | `""` + number | `0` + object | `{}` + array | `[]` + binary | empty array + + @param[in] v the type of the value to create + + @complexity Constant. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @liveexample{The following code shows the constructor for different @ref + value_t values,basic_json__value_t} + + @sa see @ref clear() -- restores the postcondition of this constructor + + @since version 1.0.0 + */ + basic_json(const value_t v) + : m_type(v), m_value(v) + { + assert_invariant(); + } + + /*! + @brief create a null object + + Create a `null` JSON value. It either takes a null pointer as parameter + (explicitly creating `null`) or no parameter (implicitly creating `null`). + The passed null pointer itself is not read -- it is only used to choose + the right constructor. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this constructor never throws + exceptions. + + @liveexample{The following code shows the constructor with and without a + null pointer parameter.,basic_json__nullptr_t} + + @since version 1.0.0 + */ + basic_json(std::nullptr_t = nullptr) noexcept + : basic_json(value_t::null) + { + assert_invariant(); + } + + /*! + @brief create a JSON value + + This is a "catch all" constructor for all compatible JSON types; that is, + types for which a `to_json()` method exists. The constructor forwards the + parameter @a val to that method (to `json_serializer::to_json` method + with `U = uncvref_t`, to be exact). + + Template type @a CompatibleType includes, but is not limited to, the + following types: + - **arrays**: @ref array_t and all kinds of compatible containers such as + `std::vector`, `std::deque`, `std::list`, `std::forward_list`, + `std::array`, `std::valarray`, `std::set`, `std::unordered_set`, + `std::multiset`, and `std::unordered_multiset` with a `value_type` from + which a @ref basic_json value can be constructed. + - **objects**: @ref object_t and all kinds of compatible associative + containers such as `std::map`, `std::unordered_map`, `std::multimap`, + and `std::unordered_multimap` with a `key_type` compatible to + @ref string_t and a `value_type` from which a @ref basic_json value can + be constructed. + - **strings**: @ref string_t, string literals, and all compatible string + containers can be used. + - **numbers**: @ref number_integer_t, @ref number_unsigned_t, + @ref number_float_t, and all convertible number types such as `int`, + `size_t`, `int64_t`, `float` or `double` can be used. + - **boolean**: @ref boolean_t / `bool` can be used. + - **binary**: @ref binary_t / `std::vector` may be used, + unfortunately because string literals cannot be distinguished from binary + character arrays by the C++ type system, all types compatible with `const + char*` will be directed to the string constructor instead. This is both + for backwards compatibility, and due to the fact that a binary type is not + a standard JSON type. + + See the examples below. + + @tparam CompatibleType a type such that: + - @a CompatibleType is not derived from `std::istream`, + - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move + constructors), + - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments) + - @a CompatibleType is not a @ref basic_json nested type (e.g., + @ref json_pointer, @ref iterator, etc ...) + - `json_serializer` has a `to_json(basic_json_t&, CompatibleType&&)` method + + @tparam U = `uncvref_t` + + @param[in] val the value to be forwarded to the respective constructor + + @complexity Usually linear in the size of the passed @a val, also + depending on the implementation of the called `to_json()` + method. + + @exceptionsafety Depends on the called constructor. For types directly + supported by the library (i.e., all types for which no `to_json()` function + was provided), strong guarantee holds: if an exception is thrown, there are + no changes to any JSON value. + + @liveexample{The following code shows the constructor with several + compatible types.,basic_json__CompatibleType} + + @since version 2.1.0 + */ + template < typename CompatibleType, + typename U = detail::uncvref_t, + detail::enable_if_t < + !detail::is_basic_json::value && detail::is_compatible_type::value, int > = 0 > + basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) + JSONSerializer::to_json(std::declval(), + std::forward(val)))) + { + JSONSerializer::to_json(*this, std::forward(val)); + set_parents(); + assert_invariant(); + } + + /*! + @brief create a JSON value from an existing one + + This is a constructor for existing @ref basic_json types. + It does not hijack copy/move constructors, since the parameter has different + template arguments than the current ones. + + The constructor tries to convert the internal @ref m_value of the parameter. + + @tparam BasicJsonType a type such that: + - @a BasicJsonType is a @ref basic_json type. + - @a BasicJsonType has different template arguments than @ref basic_json_t. + + @param[in] val the @ref basic_json value to be converted. + + @complexity Usually linear in the size of the passed @a val, also + depending on the implementation of the called `to_json()` + method. + + @exceptionsafety Depends on the called constructor. For types directly + supported by the library (i.e., all types for which no `to_json()` function + was provided), strong guarantee holds: if an exception is thrown, there are + no changes to any JSON value. + + @since version 3.2.0 + */ + template < typename BasicJsonType, + detail::enable_if_t < + detail::is_basic_json::value&& !std::is_same::value, int > = 0 > + basic_json(const BasicJsonType& val) + { + using other_boolean_t = typename BasicJsonType::boolean_t; + using other_number_float_t = typename BasicJsonType::number_float_t; + using other_number_integer_t = typename BasicJsonType::number_integer_t; + using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using other_string_t = typename BasicJsonType::string_t; + using other_object_t = typename BasicJsonType::object_t; + using other_array_t = typename BasicJsonType::array_t; + using other_binary_t = typename BasicJsonType::binary_t; + + switch (val.type()) + { + case value_t::boolean: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::number_float: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::number_integer: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::number_unsigned: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::string: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::object: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::array: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::binary: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::null: + *this = nullptr; + break; + case value_t::discarded: + m_type = value_t::discarded; + break; + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + set_parents(); + assert_invariant(); + } + + /*! + @brief create a container (array or object) from an initializer list + + Creates a JSON value of type array or object from the passed initializer + list @a init. In case @a type_deduction is `true` (default), the type of + the JSON value to be created is deducted from the initializer list @a init + according to the following rules: + + 1. If the list is empty, an empty JSON object value `{}` is created. + 2. If the list consists of pairs whose first element is a string, a JSON + object value is created where the first elements of the pairs are + treated as keys and the second elements are as values. + 3. In all other cases, an array is created. + + The rules aim to create the best fit between a C++ initializer list and + JSON values. The rationale is as follows: + + 1. The empty initializer list is written as `{}` which is exactly an empty + JSON object. + 2. C++ has no way of describing mapped types other than to list a list of + pairs. As JSON requires that keys must be of type string, rule 2 is the + weakest constraint one can pose on initializer lists to interpret them + as an object. + 3. In all other cases, the initializer list could not be interpreted as + JSON object type, so interpreting it as JSON array type is safe. + + With the rules described above, the following JSON values cannot be + expressed by an initializer list: + + - the empty array (`[]`): use @ref array(initializer_list_t) + with an empty initializer list in this case + - arrays whose elements satisfy rule 2: use @ref + array(initializer_list_t) with the same initializer list + in this case + + @note When used without parentheses around an empty initializer list, @ref + basic_json() is called instead of this function, yielding the JSON null + value. + + @param[in] init initializer list with JSON values + + @param[in] type_deduction internal parameter; when set to `true`, the type + of the JSON value is deducted from the initializer list @a init; when set + to `false`, the type provided via @a manual_type is forced. This mode is + used by the functions @ref array(initializer_list_t) and + @ref object(initializer_list_t). + + @param[in] manual_type internal parameter; when @a type_deduction is set + to `false`, the created JSON value will use the provided type (only @ref + value_t::array and @ref value_t::object are valid); when @a type_deduction + is set to `true`, this parameter has no effect + + @throw type_error.301 if @a type_deduction is `false`, @a manual_type is + `value_t::object`, but @a init contains an element which is not a pair + whose first element is a string. In this case, the constructor could not + create an object. If @a type_deduction would have be `true`, an array + would have been created. See @ref object(initializer_list_t) + for an example. + + @complexity Linear in the size of the initializer list @a init. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @liveexample{The example below shows how JSON values are created from + initializer lists.,basic_json__list_init_t} + + @sa see @ref array(initializer_list_t) -- create a JSON array + value from an initializer list + @sa see @ref object(initializer_list_t) -- create a JSON object + value from an initializer list + + @since version 1.0.0 + */ + basic_json(initializer_list_t init, + bool type_deduction = true, + value_t manual_type = value_t::array) + { + // check if each element is an array with two elements whose first + // element is a string + bool is_an_object = std::all_of(init.begin(), init.end(), + [](const detail::json_ref& element_ref) + { + return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string(); + }); + + // adjust type if type deduction is not wanted + if (!type_deduction) + { + // if array is wanted, do not create an object though possible + if (manual_type == value_t::array) + { + is_an_object = false; + } + + // if object is wanted but impossible, throw an exception + if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) + { + JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json())); + } + } + + if (is_an_object) + { + // the initializer list is a list of pairs -> create object + m_type = value_t::object; + m_value = value_t::object; + + for (auto& element_ref : init) + { + auto element = element_ref.moved_or_copied(); + m_value.object->emplace( + std::move(*((*element.m_value.array)[0].m_value.string)), + std::move((*element.m_value.array)[1])); + } + } + else + { + // the initializer list describes an array -> create array + m_type = value_t::array; + m_value.array = create(init.begin(), init.end()); + } + + set_parents(); + assert_invariant(); + } + + /*! + @brief explicitly create a binary array (without subtype) + + Creates a JSON binary array value from a given binary container. Binary + values are part of various binary formats, such as CBOR, MessagePack, and + BSON. This constructor is used to create a value for serialization to those + formats. + + @note Note, this function exists because of the difficulty in correctly + specifying the correct template overload in the standard value ctor, as both + JSON arrays and JSON binary arrays are backed with some form of a + `std::vector`. Because JSON binary arrays are a non-standard extension it + was decided that it would be best to prevent automatic initialization of a + binary array type, for backwards compatibility and so it does not happen on + accident. + + @param[in] init container containing bytes to use as binary type + + @return JSON binary array value + + @complexity Linear in the size of @a init. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @since version 3.8.0 + */ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(const typename binary_t::container_type& init) + { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = init; + return res; + } + + /*! + @brief explicitly create a binary array (with subtype) + + Creates a JSON binary array value from a given binary container. Binary + values are part of various binary formats, such as CBOR, MessagePack, and + BSON. This constructor is used to create a value for serialization to those + formats. + + @note Note, this function exists because of the difficulty in correctly + specifying the correct template overload in the standard value ctor, as both + JSON arrays and JSON binary arrays are backed with some form of a + `std::vector`. Because JSON binary arrays are a non-standard extension it + was decided that it would be best to prevent automatic initialization of a + binary array type, for backwards compatibility and so it does not happen on + accident. + + @param[in] init container containing bytes to use as binary type + @param[in] subtype subtype to use in MessagePack and BSON + + @return JSON binary array value + + @complexity Linear in the size of @a init. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @since version 3.8.0 + */ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) + { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = binary_t(init, subtype); + return res; + } + + /// @copydoc binary(const typename binary_t::container_type&) + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(typename binary_t::container_type&& init) + { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = std::move(init); + return res; + } + + /// @copydoc binary(const typename binary_t::container_type&, typename binary_t::subtype_type) + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) + { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = binary_t(std::move(init), subtype); + return res; + } + + /*! + @brief explicitly create an array from an initializer list + + Creates a JSON array value from a given initializer list. That is, given a + list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the + initializer list is empty, the empty array `[]` is created. + + @note This function is only needed to express two edge cases that cannot + be realized with the initializer list constructor (@ref + basic_json(initializer_list_t, bool, value_t)). These cases + are: + 1. creating an array whose elements are all pairs whose first element is a + string -- in this case, the initializer list constructor would create an + object, taking the first elements as keys + 2. creating an empty array -- passing the empty initializer list to the + initializer list constructor yields an empty object + + @param[in] init initializer list with JSON values to create an array from + (optional) + + @return JSON array value + + @complexity Linear in the size of @a init. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @liveexample{The following code shows an example for the `array` + function.,array} + + @sa see @ref basic_json(initializer_list_t, bool, value_t) -- + create a JSON value from an initializer list + @sa see @ref object(initializer_list_t) -- create a JSON object + value from an initializer list + + @since version 1.0.0 + */ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json array(initializer_list_t init = {}) + { + return basic_json(init, false, value_t::array); + } + + /*! + @brief explicitly create an object from an initializer list + + Creates a JSON object value from a given initializer list. The initializer + lists elements must be pairs, and their first elements must be strings. If + the initializer list is empty, the empty object `{}` is created. + + @note This function is only added for symmetry reasons. In contrast to the + related function @ref array(initializer_list_t), there are + no cases which can only be expressed by this function. That is, any + initializer list @a init can also be passed to the initializer list + constructor @ref basic_json(initializer_list_t, bool, value_t). + + @param[in] init initializer list to create an object from (optional) + + @return JSON object value + + @throw type_error.301 if @a init is not a list of pairs whose first + elements are strings. In this case, no object can be created. When such a + value is passed to @ref basic_json(initializer_list_t, bool, value_t), + an array would have been created from the passed initializer list @a init. + See example below. + + @complexity Linear in the size of @a init. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @liveexample{The following code shows an example for the `object` + function.,object} + + @sa see @ref basic_json(initializer_list_t, bool, value_t) -- + create a JSON value from an initializer list + @sa see @ref array(initializer_list_t) -- create a JSON array + value from an initializer list + + @since version 1.0.0 + */ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json object(initializer_list_t init = {}) + { + return basic_json(init, false, value_t::object); + } + + /*! + @brief construct an array with count copies of given value + + Constructs a JSON array value by creating @a cnt copies of a passed value. + In case @a cnt is `0`, an empty array is created. + + @param[in] cnt the number of JSON copies of @a val to create + @param[in] val the JSON value to copy + + @post `std::distance(begin(),end()) == cnt` holds. + + @complexity Linear in @a cnt. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @liveexample{The following code shows examples for the @ref + basic_json(size_type\, const basic_json&) + constructor.,basic_json__size_type_basic_json} + + @since version 1.0.0 + */ + basic_json(size_type cnt, const basic_json& val) + : m_type(value_t::array) + { + m_value.array = create(cnt, val); + set_parents(); + assert_invariant(); + } + + /*! + @brief construct a JSON container given an iterator range + + Constructs the JSON value with the contents of the range `[first, last)`. + The semantics depends on the different types a JSON value can have: + - In case of a null type, invalid_iterator.206 is thrown. + - In case of other primitive types (number, boolean, or string), @a first + must be `begin()` and @a last must be `end()`. In this case, the value is + copied. Otherwise, invalid_iterator.204 is thrown. + - In case of structured types (array, object), the constructor behaves as + similar versions for `std::vector` or `std::map`; that is, a JSON array + or object is constructed from the values in the range. + + @tparam InputIT an input iterator type (@ref iterator or @ref + const_iterator) + + @param[in] first begin of the range to copy from (included) + @param[in] last end of the range to copy from (excluded) + + @pre Iterators @a first and @a last must be initialized. **This + precondition is enforced with an assertion (see warning).** If + assertions are switched off, a violation of this precondition yields + undefined behavior. + + @pre Range `[first, last)` is valid. Usually, this precondition cannot be + checked efficiently. Only certain edge cases are detected; see the + description of the exceptions below. A violation of this precondition + yields undefined behavior. + + @warning A precondition is enforced with a runtime assertion that will + result in calling `std::abort` if this precondition is not met. + Assertions can be disabled by defining `NDEBUG` at compile time. + See https://en.cppreference.com/w/cpp/error/assert for more + information. + + @throw invalid_iterator.201 if iterators @a first and @a last are not + compatible (i.e., do not belong to the same JSON value). In this case, + the range `[first, last)` is undefined. + @throw invalid_iterator.204 if iterators @a first and @a last belong to a + primitive type (number, boolean, or string), but @a first does not point + to the first element any more. In this case, the range `[first, last)` is + undefined. See example code below. + @throw invalid_iterator.206 if iterators @a first and @a last belong to a + null value. In this case, the range `[first, last)` is undefined. + + @complexity Linear in distance between @a first and @a last. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @liveexample{The example below shows several ways to create JSON values by + specifying a subrange with iterators.,basic_json__InputIt_InputIt} + + @since version 1.0.0 + */ + template < class InputIT, typename std::enable_if < + std::is_same::value || + std::is_same::value, int >::type = 0 > + basic_json(InputIT first, InputIT last) + { + JSON_ASSERT(first.m_object != nullptr); + JSON_ASSERT(last.m_object != nullptr); + + // make sure iterator fits the current value + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json())); + } + + // copy type from first iterator + m_type = first.m_object->m_type; + + // check if iterator range is complete for primitive values + switch (m_type) + { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + { + if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() + || !last.m_it.primitive_iterator.is_end())) + { + JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object)); + } + break; + } + + case value_t::null: + case value_t::object: + case value_t::array: + case value_t::binary: + case value_t::discarded: + default: + break; + } + + switch (m_type) + { + case value_t::number_integer: + { + m_value.number_integer = first.m_object->m_value.number_integer; + break; + } + + case value_t::number_unsigned: + { + m_value.number_unsigned = first.m_object->m_value.number_unsigned; + break; + } + + case value_t::number_float: + { + m_value.number_float = first.m_object->m_value.number_float; + break; + } + + case value_t::boolean: + { + m_value.boolean = first.m_object->m_value.boolean; + break; + } + + case value_t::string: + { + m_value = *first.m_object->m_value.string; + break; + } + + case value_t::object: + { + m_value.object = create(first.m_it.object_iterator, + last.m_it.object_iterator); + break; + } + + case value_t::array: + { + m_value.array = create(first.m_it.array_iterator, + last.m_it.array_iterator); + break; + } + + case value_t::binary: + { + m_value = *first.m_object->m_value.binary; + break; + } + + case value_t::null: + case value_t::discarded: + default: + JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object)); + } + + set_parents(); + assert_invariant(); + } + + + /////////////////////////////////////// + // other constructors and destructor // + /////////////////////////////////////// + + template, + std::is_same>::value, int> = 0 > + basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {} + + /*! + @brief copy constructor + + Creates a copy of a given JSON value. + + @param[in] other the JSON value to copy + + @post `*this == other` + + @complexity Linear in the size of @a other. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes to any JSON value. + + @requirement This function helps `basic_json` satisfying the + [Container](https://en.cppreference.com/w/cpp/named_req/Container) + requirements: + - The complexity is linear. + - As postcondition, it holds: `other == basic_json(other)`. + + @liveexample{The following code shows an example for the copy + constructor.,basic_json__basic_json} + + @since version 1.0.0 + */ + basic_json(const basic_json& other) + : m_type(other.m_type) + { + // check of passed value is valid + other.assert_invariant(); + + switch (m_type) + { + case value_t::object: + { + m_value = *other.m_value.object; + break; + } + + case value_t::array: + { + m_value = *other.m_value.array; + break; + } + + case value_t::string: + { + m_value = *other.m_value.string; + break; + } + + case value_t::boolean: + { + m_value = other.m_value.boolean; + break; + } + + case value_t::number_integer: + { + m_value = other.m_value.number_integer; + break; + } + + case value_t::number_unsigned: + { + m_value = other.m_value.number_unsigned; + break; + } + + case value_t::number_float: + { + m_value = other.m_value.number_float; + break; + } + + case value_t::binary: + { + m_value = *other.m_value.binary; + break; + } + + case value_t::null: + case value_t::discarded: + default: + break; + } + + set_parents(); + assert_invariant(); + } + + /*! + @brief move constructor + + Move constructor. Constructs a JSON value with the contents of the given + value @a other using move semantics. It "steals" the resources from @a + other and leaves it as JSON null value. + + @param[in,out] other value to move to this object + + @post `*this` has the same value as @a other before the call. + @post @a other is a JSON null value. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this constructor never throws + exceptions. + + @requirement This function helps `basic_json` satisfying the + [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible) + requirements. + + @liveexample{The code below shows the move constructor explicitly called + via std::move.,basic_json__moveconstructor} + + @since version 1.0.0 + */ + basic_json(basic_json&& other) noexcept + : m_type(std::move(other.m_type)), + m_value(std::move(other.m_value)) + { + // check that passed value is valid + other.assert_invariant(false); + + // invalidate payload + other.m_type = value_t::null; + other.m_value = {}; + + set_parents(); + assert_invariant(); + } + + /*! + @brief copy assignment + + Copy assignment operator. Copies a JSON value via the "copy and swap" + strategy: It is expressed in terms of the copy constructor, destructor, + and the `swap()` member function. + + @param[in] other value to copy from + + @complexity Linear. + + @requirement This function helps `basic_json` satisfying the + [Container](https://en.cppreference.com/w/cpp/named_req/Container) + requirements: + - The complexity is linear. + + @liveexample{The code below shows and example for the copy assignment. It + creates a copy of value `a` which is then swapped with `b`. Finally\, the + copy of `a` (which is the null value after the swap) is + destroyed.,basic_json__copyassignment} + + @since version 1.0.0 + */ + basic_json& operator=(basic_json other) noexcept ( + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value&& + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value + ) + { + // check that passed value is valid + other.assert_invariant(); + + using std::swap; + swap(m_type, other.m_type); + swap(m_value, other.m_value); + + set_parents(); + assert_invariant(); + return *this; + } + + /*! + @brief destructor + + Destroys the JSON value and frees all allocated memory. + + @complexity Linear. + + @requirement This function helps `basic_json` satisfying the + [Container](https://en.cppreference.com/w/cpp/named_req/Container) + requirements: + - The complexity is linear. + - All stored elements are destroyed and all memory is freed. + + @since version 1.0.0 + */ + ~basic_json() noexcept + { + assert_invariant(false); + m_value.destroy(m_type); + } + + /// @} + + public: + /////////////////////// + // object inspection // + /////////////////////// + + /// @name object inspection + /// Functions to inspect the type of a JSON value. + /// @{ + + /*! + @brief serialization + + Serialization function for JSON values. The function tries to mimic + Python's `json.dumps()` function, and currently supports its @a indent + and @a ensure_ascii parameters. + + @param[in] indent If indent is nonnegative, then array elements and object + members will be pretty-printed with that indent level. An indent level of + `0` will only insert newlines. `-1` (the default) selects the most compact + representation. + @param[in] indent_char The character to use for indentation if @a indent is + greater than `0`. The default is ` ` (space). + @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters + in the output are escaped with `\uXXXX` sequences, and the result consists + of ASCII characters only. + @param[in] error_handler how to react on decoding errors; there are three + possible values: `strict` (throws and exception in case a decoding error + occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD), + and `ignore` (ignore invalid UTF-8 sequences during serialization; all + bytes are copied to the output unchanged). + + @return string containing the serialization of the JSON value + + @throw type_error.316 if a string stored inside the JSON value is not + UTF-8 encoded and @a error_handler is set to strict + + @note Binary values are serialized as object containing two keys: + - "bytes": an array of bytes as integers + - "subtype": the subtype as integer or "null" if the binary has no subtype + + @complexity Linear. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @liveexample{The following example shows the effect of different @a indent\, + @a indent_char\, and @a ensure_ascii parameters to the result of the + serialization.,dump} + + @see https://docs.python.org/2/library/json.html#json.dump + + @since version 1.0.0; indentation character @a indent_char, option + @a ensure_ascii and exceptions added in version 3.0.0; error + handlers added in version 3.4.0; serialization of binary values added + in version 3.8.0. + */ + string_t dump(const int indent = -1, + const char indent_char = ' ', + const bool ensure_ascii = false, + const error_handler_t error_handler = error_handler_t::strict) const + { + string_t result; + serializer s(detail::output_adapter(result), indent_char, error_handler); + + if (indent >= 0) + { + s.dump(*this, true, ensure_ascii, static_cast(indent)); + } + else + { + s.dump(*this, false, ensure_ascii, 0); + } + + return result; + } + + /*! + @brief return the type of the JSON value (explicit) + + Return the type of the JSON value as a value from the @ref value_t + enumeration. + + @return the type of the JSON value + Value type | return value + ------------------------- | ------------------------- + null | value_t::null + boolean | value_t::boolean + string | value_t::string + number (integer) | value_t::number_integer + number (unsigned integer) | value_t::number_unsigned + number (floating-point) | value_t::number_float + object | value_t::object + array | value_t::array + binary | value_t::binary + discarded | value_t::discarded + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `type()` for all JSON + types.,type} + + @sa see @ref operator value_t() -- return the type of the JSON value (implicit) + @sa see @ref type_name() -- return the type as string + + @since version 1.0.0 + */ + constexpr value_t type() const noexcept + { + return m_type; + } + + /*! + @brief return whether type is primitive + + This function returns true if and only if the JSON type is primitive + (string, number, boolean, or null). + + @return `true` if type is primitive (string, number, boolean, or null), + `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_primitive()` for all JSON + types.,is_primitive} + + @sa see @ref is_structured() -- returns whether JSON value is structured + @sa see @ref is_null() -- returns whether JSON value is `null` + @sa see @ref is_string() -- returns whether JSON value is a string + @sa see @ref is_boolean() -- returns whether JSON value is a boolean + @sa see @ref is_number() -- returns whether JSON value is a number + @sa see @ref is_binary() -- returns whether JSON value is a binary array + + @since version 1.0.0 + */ + constexpr bool is_primitive() const noexcept + { + return is_null() || is_string() || is_boolean() || is_number() || is_binary(); + } + + /*! + @brief return whether type is structured + + This function returns true if and only if the JSON type is structured + (array or object). + + @return `true` if type is structured (array or object), `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_structured()` for all JSON + types.,is_structured} + + @sa see @ref is_primitive() -- returns whether value is primitive + @sa see @ref is_array() -- returns whether value is an array + @sa see @ref is_object() -- returns whether value is an object + + @since version 1.0.0 + */ + constexpr bool is_structured() const noexcept + { + return is_array() || is_object(); + } + + /*! + @brief return whether value is null + + This function returns true if and only if the JSON value is null. + + @return `true` if type is null, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_null()` for all JSON + types.,is_null} + + @since version 1.0.0 + */ + constexpr bool is_null() const noexcept + { + return m_type == value_t::null; + } + + /*! + @brief return whether value is a boolean + + This function returns true if and only if the JSON value is a boolean. + + @return `true` if type is boolean, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_boolean()` for all JSON + types.,is_boolean} + + @since version 1.0.0 + */ + constexpr bool is_boolean() const noexcept + { + return m_type == value_t::boolean; + } + + /*! + @brief return whether value is a number + + This function returns true if and only if the JSON value is a number. This + includes both integer (signed and unsigned) and floating-point values. + + @return `true` if type is number (regardless whether integer, unsigned + integer or floating-type), `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number()` for all JSON + types.,is_number} + + @sa see @ref is_number_integer() -- check if value is an integer or unsigned + integer number + @sa see @ref is_number_unsigned() -- check if value is an unsigned integer + number + @sa see @ref is_number_float() -- check if value is a floating-point number + + @since version 1.0.0 + */ + constexpr bool is_number() const noexcept + { + return is_number_integer() || is_number_float(); + } + + /*! + @brief return whether value is an integer number + + This function returns true if and only if the JSON value is a signed or + unsigned integer number. This excludes floating-point values. + + @return `true` if type is an integer or unsigned integer number, `false` + otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number_integer()` for all + JSON types.,is_number_integer} + + @sa see @ref is_number() -- check if value is a number + @sa see @ref is_number_unsigned() -- check if value is an unsigned integer + number + @sa see @ref is_number_float() -- check if value is a floating-point number + + @since version 1.0.0 + */ + constexpr bool is_number_integer() const noexcept + { + return m_type == value_t::number_integer || m_type == value_t::number_unsigned; + } + + /*! + @brief return whether value is an unsigned integer number + + This function returns true if and only if the JSON value is an unsigned + integer number. This excludes floating-point and signed integer values. + + @return `true` if type is an unsigned integer number, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number_unsigned()` for all + JSON types.,is_number_unsigned} + + @sa see @ref is_number() -- check if value is a number + @sa see @ref is_number_integer() -- check if value is an integer or unsigned + integer number + @sa see @ref is_number_float() -- check if value is a floating-point number + + @since version 2.0.0 + */ + constexpr bool is_number_unsigned() const noexcept + { + return m_type == value_t::number_unsigned; + } + + /*! + @brief return whether value is a floating-point number + + This function returns true if and only if the JSON value is a + floating-point number. This excludes signed and unsigned integer values. + + @return `true` if type is a floating-point number, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number_float()` for all + JSON types.,is_number_float} + + @sa see @ref is_number() -- check if value is number + @sa see @ref is_number_integer() -- check if value is an integer number + @sa see @ref is_number_unsigned() -- check if value is an unsigned integer + number + + @since version 1.0.0 + */ + constexpr bool is_number_float() const noexcept + { + return m_type == value_t::number_float; + } + + /*! + @brief return whether value is an object + + This function returns true if and only if the JSON value is an object. + + @return `true` if type is object, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_object()` for all JSON + types.,is_object} + + @since version 1.0.0 + */ + constexpr bool is_object() const noexcept + { + return m_type == value_t::object; + } + + /*! + @brief return whether value is an array + + This function returns true if and only if the JSON value is an array. + + @return `true` if type is array, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_array()` for all JSON + types.,is_array} + + @since version 1.0.0 + */ + constexpr bool is_array() const noexcept + { + return m_type == value_t::array; + } + + /*! + @brief return whether value is a string + + This function returns true if and only if the JSON value is a string. + + @return `true` if type is string, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_string()` for all JSON + types.,is_string} + + @since version 1.0.0 + */ + constexpr bool is_string() const noexcept + { + return m_type == value_t::string; + } + + /*! + @brief return whether value is a binary array + + This function returns true if and only if the JSON value is a binary array. + + @return `true` if type is binary array, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_binary()` for all JSON + types.,is_binary} + + @since version 3.8.0 + */ + constexpr bool is_binary() const noexcept + { + return m_type == value_t::binary; + } + + /*! + @brief return whether value is discarded + + This function returns true if and only if the JSON value was discarded + during parsing with a callback function (see @ref parser_callback_t). + + @note This function will always be `false` for JSON values after parsing. + That is, discarded values can only occur during parsing, but will be + removed when inside a structured value or replaced by null in other cases. + + @return `true` if type is discarded, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_discarded()` for all JSON + types.,is_discarded} + + @since version 1.0.0 + */ + constexpr bool is_discarded() const noexcept + { + return m_type == value_t::discarded; + } + + /*! + @brief return the type of the JSON value (implicit) + + Implicitly return the type of the JSON value as a value from the @ref + value_t enumeration. + + @return the type of the JSON value + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies the @ref value_t operator for + all JSON types.,operator__value_t} + + @sa see @ref type() -- return the type of the JSON value (explicit) + @sa see @ref type_name() -- return the type as string + + @since version 1.0.0 + */ + constexpr operator value_t() const noexcept + { + return m_type; + } + + /// @} + + private: + ////////////////// + // value access // + ////////////////// + + /// get a boolean (explicit) + boolean_t get_impl(boolean_t* /*unused*/) const + { + if (JSON_HEDLEY_LIKELY(is_boolean())) + { + return m_value.boolean; + } + + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this)); + } + + /// get a pointer to the value (object) + object_t* get_impl_ptr(object_t* /*unused*/) noexcept + { + return is_object() ? m_value.object : nullptr; + } + + /// get a pointer to the value (object) + constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept + { + return is_object() ? m_value.object : nullptr; + } + + /// get a pointer to the value (array) + array_t* get_impl_ptr(array_t* /*unused*/) noexcept + { + return is_array() ? m_value.array : nullptr; + } + + /// get a pointer to the value (array) + constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept + { + return is_array() ? m_value.array : nullptr; + } + + /// get a pointer to the value (string) + string_t* get_impl_ptr(string_t* /*unused*/) noexcept + { + return is_string() ? m_value.string : nullptr; + } + + /// get a pointer to the value (string) + constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept + { + return is_string() ? m_value.string : nullptr; + } + + /// get a pointer to the value (boolean) + boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept + { + return is_boolean() ? &m_value.boolean : nullptr; + } + + /// get a pointer to the value (boolean) + constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept + { + return is_boolean() ? &m_value.boolean : nullptr; + } + + /// get a pointer to the value (integer number) + number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept + { + return is_number_integer() ? &m_value.number_integer : nullptr; + } + + /// get a pointer to the value (integer number) + constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept + { + return is_number_integer() ? &m_value.number_integer : nullptr; + } + + /// get a pointer to the value (unsigned number) + number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept + { + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + } + + /// get a pointer to the value (unsigned number) + constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept + { + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + } + + /// get a pointer to the value (floating-point number) + number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept + { + return is_number_float() ? &m_value.number_float : nullptr; + } + + /// get a pointer to the value (floating-point number) + constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept + { + return is_number_float() ? &m_value.number_float : nullptr; + } + + /// get a pointer to the value (binary) + binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept + { + return is_binary() ? m_value.binary : nullptr; + } + + /// get a pointer to the value (binary) + constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept + { + return is_binary() ? m_value.binary : nullptr; + } + + /*! + @brief helper function to implement get_ref() + + This function helps to implement get_ref() without code duplication for + const and non-const overloads + + @tparam ThisType will be deduced as `basic_json` or `const basic_json` + + @throw type_error.303 if ReferenceType does not match underlying value + type of the current JSON + */ + template + static ReferenceType get_ref_impl(ThisType& obj) + { + // delegate the call to get_ptr<>() + auto* ptr = obj.template get_ptr::type>(); + + if (JSON_HEDLEY_LIKELY(ptr != nullptr)) + { + return *ptr; + } + + JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj)); + } + + public: + /// @name value access + /// Direct access to the stored value of a JSON value. + /// @{ + + /*! + @brief get a pointer value (implicit) + + Implicit pointer access to the internally stored JSON value. No copies are + made. + + @warning Writing data to the pointee of the result yields an undefined + state. + + @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref + object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, + @ref number_unsigned_t, or @ref number_float_t. Enforced by a static + assertion. + + @return pointer to the internally stored JSON value if the requested + pointer type @a PointerType fits to the JSON value; `nullptr` otherwise + + @complexity Constant. + + @liveexample{The example below shows how pointers to internal values of a + JSON value can be requested. Note that no type conversions are made and a + `nullptr` is returned if the value and the requested pointer type does not + match.,get_ptr} + + @since version 1.0.0 + */ + template::value, int>::type = 0> + auto get_ptr() noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) + { + // delegate the call to get_impl_ptr<>() + return get_impl_ptr(static_cast(nullptr)); + } + + /*! + @brief get a pointer value (implicit) + @copydoc get_ptr() + */ + template < typename PointerType, typename std::enable_if < + std::is_pointer::value&& + std::is_const::type>::value, int >::type = 0 > + constexpr auto get_ptr() const noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) + { + // delegate the call to get_impl_ptr<>() const + return get_impl_ptr(static_cast(nullptr)); + } + + private: + /*! + @brief get a value (explicit) + + Explicit type conversion between the JSON value and a compatible value + which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) + and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). + The value is converted by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + ValueType ret; + JSONSerializer::from_json(*this, ret); + return ret; + @endcode + + This overloads is chosen if: + - @a ValueType is not @ref basic_json, + - @ref json_serializer has a `from_json()` method of the form + `void from_json(const basic_json&, ValueType&)`, and + - @ref json_serializer does not have a `from_json()` method of + the form `ValueType from_json(const basic_json&)` + + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer `from_json()` method throws + + @liveexample{The example below shows several conversions from JSON values + to other types. There a few things to note: (1) Floating-point numbers can + be converted to integers\, (2) A JSON array can be converted to a standard + `std::vector`\, (3) A JSON object can be converted to C++ + associative containers such as `std::unordered_map`.,get__ValueType_const} + + @since version 2.1.0 + */ + template < typename ValueType, + detail::enable_if_t < + detail::is_default_constructible::value&& + detail::has_from_json::value, + int > = 0 > + ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), std::declval()))) + { + auto ret = ValueType(); + JSONSerializer::from_json(*this, ret); + return ret; + } + + /*! + @brief get a value (explicit); special case + + Explicit type conversion between the JSON value and a compatible value + which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) + and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). + The value is converted by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + return JSONSerializer::from_json(*this); + @endcode + + This overloads is chosen if: + - @a ValueType is not @ref basic_json and + - @ref json_serializer has a `from_json()` method of the form + `ValueType from_json(const basic_json&)` + + @note If @ref json_serializer has both overloads of + `from_json()`, this one is chosen. + + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @a ValueType + + @throw what @ref json_serializer `from_json()` method throws + + @since version 2.1.0 + */ + template < typename ValueType, + detail::enable_if_t < + detail::has_non_default_from_json::value, + int > = 0 > + ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( + JSONSerializer::from_json(std::declval()))) + { + return JSONSerializer::from_json(*this); + } + + /*! + @brief get special-case overload + + This overloads converts the current @ref basic_json in a different + @ref basic_json type + + @tparam BasicJsonType == @ref basic_json + + @return a copy of *this, converted into @a BasicJsonType + + @complexity Depending on the implementation of the called `from_json()` + method. + + @since version 3.2.0 + */ + template < typename BasicJsonType, + detail::enable_if_t < + detail::is_basic_json::value, + int > = 0 > + BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const + { + return *this; + } + + /*! + @brief get special-case overload + + This overloads avoids a lot of template boilerplate, it can be seen as the + identity method + + @tparam BasicJsonType == @ref basic_json + + @return a copy of *this + + @complexity Constant. + + @since version 2.1.0 + */ + template::value, + int> = 0> + basic_json get_impl(detail::priority_tag<3> /*unused*/) const + { + return *this; + } + + /*! + @brief get a pointer value (explicit) + @copydoc get() + */ + template::value, + int> = 0> + constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept + -> decltype(std::declval().template get_ptr()) + { + // delegate the call to get_ptr + return get_ptr(); + } + + public: + /*! + @brief get a (pointer) value (explicit) + + Performs explicit type conversion between the JSON value and a compatible value if required. + + - If the requested type is a pointer to the internally stored JSON value that pointer is returned. + No copies are made. + + - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible + from the current @ref basic_json. + + - Otherwise the value is converted by calling the @ref json_serializer `from_json()` + method. + + @tparam ValueTypeCV the provided value type + @tparam ValueType the returned value type + + @return copy of the JSON value, converted to @tparam ValueType if necessary + + @throw what @ref json_serializer `from_json()` method throws if conversion is required + + @since version 2.1.0 + */ + template < typename ValueTypeCV, typename ValueType = detail::uncvref_t> +#if defined(JSON_HAS_CPP_14) + constexpr +#endif + auto get() const noexcept( + noexcept(std::declval().template get_impl(detail::priority_tag<4> {}))) + -> decltype(std::declval().template get_impl(detail::priority_tag<4> {})) + { + // we cannot static_assert on ValueTypeCV being non-const, because + // there is support for get(), which is why we + // still need the uncvref + static_assert(!std::is_reference::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + return get_impl(detail::priority_tag<4> {}); + } + + /*! + @brief get a pointer value (explicit) + + Explicit pointer access to the internally stored JSON value. No copies are + made. + + @warning The pointer becomes invalid if the underlying JSON object + changes. + + @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref + object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, + @ref number_unsigned_t, or @ref number_float_t. + + @return pointer to the internally stored JSON value if the requested + pointer type @a PointerType fits to the JSON value; `nullptr` otherwise + + @complexity Constant. + + @liveexample{The example below shows how pointers to internal values of a + JSON value can be requested. Note that no type conversions are made and a + `nullptr` is returned if the value and the requested pointer type does not + match.,get__PointerType} + + @sa see @ref get_ptr() for explicit pointer-member access + + @since version 1.0.0 + */ + template::value, int>::type = 0> + auto get() noexcept -> decltype(std::declval().template get_ptr()) + { + // delegate the call to get_ptr + return get_ptr(); + } + + /*! + @brief get a value (explicit) + + Explicit type conversion between the JSON value and a compatible value. + The value is filled into the input parameter by calling the @ref json_serializer + `from_json()` method. + + The function is equivalent to executing + @code {.cpp} + ValueType v; + JSONSerializer::from_json(*this, v); + @endcode + + This overloads is chosen if: + - @a ValueType is not @ref basic_json, + - @ref json_serializer has a `from_json()` method of the form + `void from_json(const basic_json&, ValueType&)`, and + + @tparam ValueType the input parameter type. + + @return the input parameter, allowing chaining calls. + + @throw what @ref json_serializer `from_json()` method throws + + @liveexample{The example below shows several conversions from JSON values + to other types. There a few things to note: (1) Floating-point numbers can + be converted to integers\, (2) A JSON array can be converted to a standard + `std::vector`\, (3) A JSON object can be converted to C++ + associative containers such as `std::unordered_map`.,get_to} + + @since version 3.3.0 + */ + template < typename ValueType, + detail::enable_if_t < + !detail::is_basic_json::value&& + detail::has_from_json::value, + int > = 0 > + ValueType & get_to(ValueType& v) const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), v))) + { + JSONSerializer::from_json(*this, v); + return v; + } + + // specialization to allow to call get_to with a basic_json value + // see https://github.com/nlohmann/json/issues/2175 + template::value, + int> = 0> + ValueType & get_to(ValueType& v) const + { + v = *this; + return v; + } + + template < + typename T, std::size_t N, + typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + detail::enable_if_t < + detail::has_from_json::value, int > = 0 > + Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + noexcept(noexcept(JSONSerializer::from_json( + std::declval(), v))) + { + JSONSerializer::from_json(*this, v); + return v; + } + + /*! + @brief get a reference value (implicit) + + Implicit reference access to the internally stored JSON value. No copies + are made. + + @warning Writing data to the referee of the result yields an undefined + state. + + @tparam ReferenceType reference type; must be a reference to @ref array_t, + @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or + @ref number_float_t. Enforced by static assertion. + + @return reference to the internally stored JSON value if the requested + reference type @a ReferenceType fits to the JSON value; throws + type_error.303 otherwise + + @throw type_error.303 in case passed type @a ReferenceType is incompatible + with the stored JSON value; see example below + + @complexity Constant. + + @liveexample{The example shows several calls to `get_ref()`.,get_ref} + + @since version 1.1.0 + */ + template::value, int>::type = 0> + ReferenceType get_ref() + { + // delegate call to get_ref_impl + return get_ref_impl(*this); + } + + /*! + @brief get a reference value (implicit) + @copydoc get_ref() + */ + template < typename ReferenceType, typename std::enable_if < + std::is_reference::value&& + std::is_const::type>::value, int >::type = 0 > + ReferenceType get_ref() const + { + // delegate call to get_ref_impl + return get_ref_impl(*this); + } + + /*! + @brief get a value (implicit) + + Implicit type conversion between the JSON value and a compatible value. + The call is realized by calling @ref get() const. + + @tparam ValueType non-pointer type compatible to the JSON value, for + instance `int` for JSON integer numbers, `bool` for JSON booleans, or + `std::vector` types for JSON arrays. The character type of @ref string_t + as well as an initializer list of this type is excluded to avoid + ambiguities as these types implicitly convert to `std::string`. + + @return copy of the JSON value, converted to type @a ValueType + + @throw type_error.302 in case passed type @a ValueType is incompatible + to the JSON value type (e.g., the JSON value is of type boolean, but a + string is requested); see example below + + @complexity Linear in the size of the JSON value. + + @liveexample{The example below shows several conversions from JSON values + to other types. There a few things to note: (1) Floating-point numbers can + be converted to integers\, (2) A JSON array can be converted to a standard + `std::vector`\, (3) A JSON object can be converted to C++ + associative containers such as `std::unordered_map`.,operator__ValueType} + + @since version 1.0.0 + */ + template < typename ValueType, typename std::enable_if < + detail::conjunction < + detail::negation>, + detail::negation>>, + detail::negation>, + detail::negation>, + detail::negation>>, + +#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) + detail::negation>, +#endif + detail::is_detected_lazy + >::value, int >::type = 0 > + JSON_EXPLICIT operator ValueType() const + { + // delegate the call to get<>() const + return get(); + } + + /*! + @return reference to the binary value + + @throw type_error.302 if the value is not binary + + @sa see @ref is_binary() to check if the value is binary + + @since version 3.8.0 + */ + binary_t& get_binary() + { + if (!is_binary()) + { + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this)); + } + + return *get_ptr(); + } + + /// @copydoc get_binary() + const binary_t& get_binary() const + { + if (!is_binary()) + { + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this)); + } + + return *get_ptr(); + } + + /// @} + + + //////////////////// + // element access // + //////////////////// + + /// @name element access + /// Access to the JSON value. + /// @{ + + /*! + @brief access specified array element with bounds checking + + Returns a reference to the element at specified location @a idx, with + bounds checking. + + @param[in] idx index of the element to access + + @return reference to the element at index @a idx + + @throw type_error.304 if the JSON value is not an array; in this case, + calling `at` with an index makes no sense. See example below. + @throw out_of_range.401 if the index @a idx is out of range of the array; + that is, `idx >= size()`. See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. + + @since version 1.0.0 + + @liveexample{The example below shows how array elements can be read and + written using `at()`. It also demonstrates the different exceptions that + can be thrown.,at__size_type} + */ + reference at(size_type idx) + { + // at only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + JSON_TRY + { + return set_parent(m_value.array->at(idx)); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); + } + } + + /*! + @brief access specified array element with bounds checking + + Returns a const reference to the element at specified location @a idx, + with bounds checking. + + @param[in] idx index of the element to access + + @return const reference to the element at index @a idx + + @throw type_error.304 if the JSON value is not an array; in this case, + calling `at` with an index makes no sense. See example below. + @throw out_of_range.401 if the index @a idx is out of range of the array; + that is, `idx >= size()`. See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. + + @since version 1.0.0 + + @liveexample{The example below shows how array elements can be read using + `at()`. It also demonstrates the different exceptions that can be thrown., + at__size_type_const} + */ + const_reference at(size_type idx) const + { + // at only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + JSON_TRY + { + return m_value.array->at(idx); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); + } + } + + /*! + @brief access specified object element with bounds checking + + Returns a reference to the element at with specified key @a key, with + bounds checking. + + @param[in] key key of the element to access + + @return reference to the element at key @a key + + @throw type_error.304 if the JSON value is not an object; in this case, + calling `at` with a key makes no sense. See example below. + @throw out_of_range.403 if the key @a key is is not stored in the object; + that is, `find(key) == end()`. See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Logarithmic in the size of the container. + + @sa see @ref operator[](const typename object_t::key_type&) for unchecked + access by reference + @sa see @ref value() for access by value with a default value + + @since version 1.0.0 + + @liveexample{The example below shows how object elements can be read and + written using `at()`. It also demonstrates the different exceptions that + can be thrown.,at__object_t_key_type} + */ + reference at(const typename object_t::key_type& key) + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + JSON_TRY + { + return set_parent(m_value.object->at(key)); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); + } + } + + /*! + @brief access specified object element with bounds checking + + Returns a const reference to the element at with specified key @a key, + with bounds checking. + + @param[in] key key of the element to access + + @return const reference to the element at key @a key + + @throw type_error.304 if the JSON value is not an object; in this case, + calling `at` with a key makes no sense. See example below. + @throw out_of_range.403 if the key @a key is is not stored in the object; + that is, `find(key) == end()`. See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Logarithmic in the size of the container. + + @sa see @ref operator[](const typename object_t::key_type&) for unchecked + access by reference + @sa see @ref value() for access by value with a default value + + @since version 1.0.0 + + @liveexample{The example below shows how object elements can be read using + `at()`. It also demonstrates the different exceptions that can be thrown., + at__object_t_key_type_const} + */ + const_reference at(const typename object_t::key_type& key) const + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + JSON_TRY + { + return m_value.object->at(key); + } + JSON_CATCH (std::out_of_range&) + { + // create better exception explanation + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); + } + } + else + { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); + } + } + + /*! + @brief access specified array element + + Returns a reference to the element at specified location @a idx. + + @note If @a idx is beyond the range of the array (i.e., `idx >= size()`), + then the array is silently filled up with `null` values to make `idx` a + valid reference to the last stored element. + + @param[in] idx index of the element to access + + @return reference to the element at index @a idx + + @throw type_error.305 if the JSON value is not an array or null; in that + cases, using the [] operator with an index makes no sense. + + @complexity Constant if @a idx is in the range of the array. Otherwise + linear in `idx - size()`. + + @liveexample{The example below shows how array elements can be read and + written using `[]` operator. Note the addition of `null` + values.,operatorarray__size_type} + + @since version 1.0.0 + */ + reference operator[](size_type idx) + { + // implicitly convert null value to an empty array + if (is_null()) + { + m_type = value_t::array; + m_value.array = create(); + assert_invariant(); + } + + // operator[] only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + // fill up array with null values if given idx is outside range + if (idx >= m_value.array->size()) + { +#if JSON_DIAGNOSTICS + // remember array size & capacity before resizing + const auto old_size = m_value.array->size(); + const auto old_capacity = m_value.array->capacity(); +#endif + m_value.array->resize(idx + 1); + +#if JSON_DIAGNOSTICS + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) + { + // capacity has changed: update all parents + set_parents(); + } + else + { + // set parent for values added above + set_parents(begin() + static_cast(old_size), static_cast(idx + 1 - old_size)); + } +#endif + assert_invariant(); + } + + return m_value.array->operator[](idx); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this)); + } + + /*! + @brief access specified array element + + Returns a const reference to the element at specified location @a idx. + + @param[in] idx index of the element to access + + @return const reference to the element at index @a idx + + @throw type_error.305 if the JSON value is not an array; in that case, + using the [] operator with an index makes no sense. + + @complexity Constant. + + @liveexample{The example below shows how array elements can be read using + the `[]` operator.,operatorarray__size_type_const} + + @since version 1.0.0 + */ + const_reference operator[](size_type idx) const + { + // const operator[] only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + return m_value.array->operator[](idx); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this)); + } + + /*! + @brief access specified object element + + Returns a reference to the element at with specified key @a key. + + @note If @a key is not found in the object, then it is silently added to + the object and filled with a `null` value to make `key` a valid reference. + In case the value was `null` before, it is converted to an object. + + @param[in] key key of the element to access + + @return reference to the element at key @a key + + @throw type_error.305 if the JSON value is not an object or null; in that + cases, using the [] operator with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be read and + written using the `[]` operator.,operatorarray__key_type} + + @sa see @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa see @ref value() for access by value with a default value + + @since version 1.0.0 + */ + reference operator[](const typename object_t::key_type& key) + { + // implicitly convert null value to an empty object + if (is_null()) + { + m_type = value_t::object; + m_value.object = create(); + assert_invariant(); + } + + // operator[] only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + return set_parent(m_value.object->operator[](key)); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); + } + + /*! + @brief read-only access specified object element + + Returns a const reference to the element at with specified key @a key. No + bounds checking is performed. + + @warning If the element with key @a key does not exist, the behavior is + undefined. + + @param[in] key key of the element to access + + @return const reference to the element at key @a key + + @pre The element with key @a key must exist. **This precondition is + enforced with an assertion.** + + @throw type_error.305 if the JSON value is not an object; in that case, + using the [] operator with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be read using + the `[]` operator.,operatorarray__key_type_const} + + @sa see @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa see @ref value() for access by value with a default value + + @since version 1.0.0 + */ + const_reference operator[](const typename object_t::key_type& key) const + { + // const operator[] only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); + } + + /*! + @brief access specified object element + + Returns a reference to the element at with specified key @a key. + + @note If @a key is not found in the object, then it is silently added to + the object and filled with a `null` value to make `key` a valid reference. + In case the value was `null` before, it is converted to an object. + + @param[in] key key of the element to access + + @return reference to the element at key @a key + + @throw type_error.305 if the JSON value is not an object or null; in that + cases, using the [] operator with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be read and + written using the `[]` operator.,operatorarray__key_type} + + @sa see @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa see @ref value() for access by value with a default value + + @since version 1.1.0 + */ + template + JSON_HEDLEY_NON_NULL(2) + reference operator[](T* key) + { + // implicitly convert null to object + if (is_null()) + { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + return set_parent(m_value.object->operator[](key)); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); + } + + /*! + @brief read-only access specified object element + + Returns a const reference to the element at with specified key @a key. No + bounds checking is performed. + + @warning If the element with key @a key does not exist, the behavior is + undefined. + + @param[in] key key of the element to access + + @return const reference to the element at key @a key + + @pre The element with key @a key must exist. **This precondition is + enforced with an assertion.** + + @throw type_error.305 if the JSON value is not an object; in that case, + using the [] operator with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be read using + the `[]` operator.,operatorarray__key_type_const} + + @sa see @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa see @ref value() for access by value with a default value + + @since version 1.1.0 + */ + template + JSON_HEDLEY_NON_NULL(2) + const_reference operator[](T* key) const + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); + } + + /*! + @brief access specified object element with default value + + Returns either a copy of an object's element at the specified key @a key + or a given default value if no element with key @a key exists. + + The function is basically equivalent to executing + @code {.cpp} + try { + return at(key); + } catch(out_of_range) { + return default_value; + } + @endcode + + @note Unlike @ref at(const typename object_t::key_type&), this function + does not throw if the given key @a key was not found. + + @note Unlike @ref operator[](const typename object_t::key_type& key), this + function does not implicitly add an element to the position defined by @a + key. This function is furthermore also applicable to const objects. + + @param[in] key key of the element to access + @param[in] default_value the value to return if @a key is not found + + @tparam ValueType type compatible to JSON values, for instance `int` for + JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for + JSON arrays. Note the type of the expected value at @a key and the default + value @a default_value must be compatible. + + @return copy of the element at key @a key or @a default_value if @a key + is not found + + @throw type_error.302 if @a default_value does not match the type of the + value at @a key + @throw type_error.306 if the JSON value is not an object; in that case, + using `value()` with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be queried + with a default value.,basic_json__value} + + @sa see @ref at(const typename object_t::key_type&) for access by reference + with range checking + @sa see @ref operator[](const typename object_t::key_type&) for unchecked + access by reference + + @since version 1.0.0 + */ + // using std::is_convertible in a std::enable_if will fail when using explicit conversions + template < class ValueType, typename std::enable_if < + detail::is_getable::value + && !std::is_same::value, int >::type = 0 > + ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + // if key is found, return value and given default value otherwise + const auto it = find(key); + if (it != end()) + { + return it->template get(); + } + + return default_value; + } + + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this)); + } + + /*! + @brief overload for a default value of type const char* + @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const + */ + string_t value(const typename object_t::key_type& key, const char* default_value) const + { + return value(key, string_t(default_value)); + } + + /*! + @brief access specified object element via JSON Pointer with default value + + Returns either a copy of an object's element at the specified key @a key + or a given default value if no element with key @a key exists. + + The function is basically equivalent to executing + @code {.cpp} + try { + return at(ptr); + } catch(out_of_range) { + return default_value; + } + @endcode + + @note Unlike @ref at(const json_pointer&), this function does not throw + if the given key @a key was not found. + + @param[in] ptr a JSON pointer to the element to access + @param[in] default_value the value to return if @a ptr found no value + + @tparam ValueType type compatible to JSON values, for instance `int` for + JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for + JSON arrays. Note the type of the expected value at @a key and the default + value @a default_value must be compatible. + + @return copy of the element at key @a key or @a default_value if @a key + is not found + + @throw type_error.302 if @a default_value does not match the type of the + value at @a ptr + @throw type_error.306 if the JSON value is not an object; in that case, + using `value()` with a key makes no sense. + + @complexity Logarithmic in the size of the container. + + @liveexample{The example below shows how object elements can be queried + with a default value.,basic_json__value_ptr} + + @sa see @ref operator[](const json_pointer&) for unchecked access by reference + + @since version 2.0.2 + */ + template::value, int>::type = 0> + ValueType value(const json_pointer& ptr, const ValueType& default_value) const + { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + // if pointer resolves a value, return it or use default value + JSON_TRY + { + return ptr.get_checked(this).template get(); + } + JSON_INTERNAL_CATCH (out_of_range&) + { + return default_value; + } + } + + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this)); + } + + /*! + @brief overload for a default value of type const char* + @copydoc basic_json::value(const json_pointer&, ValueType) const + */ + JSON_HEDLEY_NON_NULL(3) + string_t value(const json_pointer& ptr, const char* default_value) const + { + return value(ptr, string_t(default_value)); + } + + /*! + @brief access the first element + + Returns a reference to the first element in the container. For a JSON + container `c`, the expression `c.front()` is equivalent to `*c.begin()`. + + @return In case of a structured type (array or object), a reference to the + first element is returned. In case of number, string, boolean, or binary + values, a reference to the value is returned. + + @complexity Constant. + + @pre The JSON value must not be `null` (would throw `std::out_of_range`) + or an empty array or object (undefined behavior, **guarded by + assertions**). + @post The JSON value remains unchanged. + + @throw invalid_iterator.214 when called on `null` value + + @liveexample{The following code shows an example for `front()`.,front} + + @sa see @ref back() -- access the last element + + @since version 1.0.0 + */ + reference front() + { + return *begin(); + } + + /*! + @copydoc basic_json::front() + */ + const_reference front() const + { + return *cbegin(); + } + + /*! + @brief access the last element + + Returns a reference to the last element in the container. For a JSON + container `c`, the expression `c.back()` is equivalent to + @code {.cpp} + auto tmp = c.end(); + --tmp; + return *tmp; + @endcode + + @return In case of a structured type (array or object), a reference to the + last element is returned. In case of number, string, boolean, or binary + values, a reference to the value is returned. + + @complexity Constant. + + @pre The JSON value must not be `null` (would throw `std::out_of_range`) + or an empty array or object (undefined behavior, **guarded by + assertions**). + @post The JSON value remains unchanged. + + @throw invalid_iterator.214 when called on a `null` value. See example + below. + + @liveexample{The following code shows an example for `back()`.,back} + + @sa see @ref front() -- access the first element + + @since version 1.0.0 + */ + reference back() + { + auto tmp = end(); + --tmp; + return *tmp; + } + + /*! + @copydoc basic_json::back() + */ + const_reference back() const + { + auto tmp = cend(); + --tmp; + return *tmp; + } + + /*! + @brief remove element given an iterator + + Removes the element specified by iterator @a pos. The iterator @a pos must + be valid and dereferenceable. Thus the `end()` iterator (which is valid, + but is not dereferenceable) cannot be used as a value for @a pos. + + If called on a primitive type other than `null`, the resulting JSON value + will be `null`. + + @param[in] pos iterator to the element to remove + @return Iterator following the last removed element. If the iterator @a + pos refers to the last element, the `end()` iterator is returned. + + @tparam IteratorType an @ref iterator or @ref const_iterator + + @post Invalidates iterators and references at or after the point of the + erase, including the `end()` iterator. + + @throw type_error.307 if called on a `null` value; example: `"cannot use + erase() with null"` + @throw invalid_iterator.202 if called on an iterator which does not belong + to the current JSON value; example: `"iterator does not fit current + value"` + @throw invalid_iterator.205 if called on a primitive type with invalid + iterator (i.e., any iterator which is not `begin()`); example: `"iterator + out of range"` + + @complexity The complexity depends on the type: + - objects: amortized constant + - arrays: linear in distance between @a pos and the end of the container + - strings and binary: linear in the length of the member + - other types: constant + + @liveexample{The example shows the result of `erase()` for different JSON + types.,erase__IteratorType} + + @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in + the given range + @sa see @ref erase(const typename object_t::key_type&) -- removes the element + from an object at the given key + @sa see @ref erase(const size_type) -- removes the element from an array at + the given index + + @since version 1.0.0 + */ + template < class IteratorType, typename std::enable_if < + std::is_same::value || + std::is_same::value, int >::type + = 0 > + IteratorType erase(IteratorType pos) + { + // make sure iterator fits the current value + if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + IteratorType result = end(); + + switch (m_type) + { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + case value_t::binary: + { + if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) + { + JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this)); + } + + if (is_string()) + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, m_value.string); + std::allocator_traits::deallocate(alloc, m_value.string, 1); + m_value.string = nullptr; + } + else if (is_binary()) + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, m_value.binary); + std::allocator_traits::deallocate(alloc, m_value.binary, 1); + m_value.binary = nullptr; + } + + m_type = value_t::null; + assert_invariant(); + break; + } + + case value_t::object: + { + result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); + break; + } + + case value_t::array: + { + result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); + break; + } + + case value_t::null: + case value_t::discarded: + default: + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); + } + + return result; + } + + /*! + @brief remove elements given an iterator range + + Removes the element specified by the range `[first; last)`. The iterator + @a first does not need to be dereferenceable if `first == last`: erasing + an empty range is a no-op. + + If called on a primitive type other than `null`, the resulting JSON value + will be `null`. + + @param[in] first iterator to the beginning of the range to remove + @param[in] last iterator past the end of the range to remove + @return Iterator following the last removed element. If the iterator @a + second refers to the last element, the `end()` iterator is returned. + + @tparam IteratorType an @ref iterator or @ref const_iterator + + @post Invalidates iterators and references at or after the point of the + erase, including the `end()` iterator. + + @throw type_error.307 if called on a `null` value; example: `"cannot use + erase() with null"` + @throw invalid_iterator.203 if called on iterators which does not belong + to the current JSON value; example: `"iterators do not fit current value"` + @throw invalid_iterator.204 if called on a primitive type with invalid + iterators (i.e., if `first != begin()` and `last != end()`); example: + `"iterators out of range"` + + @complexity The complexity depends on the type: + - objects: `log(size()) + std::distance(first, last)` + - arrays: linear in the distance between @a first and @a last, plus linear + in the distance between @a last and end of the container + - strings and binary: linear in the length of the member + - other types: constant + + @liveexample{The example shows the result of `erase()` for different JSON + types.,erase__IteratorType_IteratorType} + + @sa see @ref erase(IteratorType) -- removes the element at a given position + @sa see @ref erase(const typename object_t::key_type&) -- removes the element + from an object at the given key + @sa see @ref erase(const size_type) -- removes the element from an array at + the given index + + @since version 1.0.0 + */ + template < class IteratorType, typename std::enable_if < + std::is_same::value || + std::is_same::value, int >::type + = 0 > + IteratorType erase(IteratorType first, IteratorType last) + { + // make sure iterator fits the current value + if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) + { + JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this)); + } + + IteratorType result = end(); + + switch (m_type) + { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + case value_t::binary: + { + if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() + || !last.m_it.primitive_iterator.is_end())) + { + JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this)); + } + + if (is_string()) + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, m_value.string); + std::allocator_traits::deallocate(alloc, m_value.string, 1); + m_value.string = nullptr; + } + else if (is_binary()) + { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, m_value.binary); + std::allocator_traits::deallocate(alloc, m_value.binary, 1); + m_value.binary = nullptr; + } + + m_type = value_t::null; + assert_invariant(); + break; + } + + case value_t::object: + { + result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, + last.m_it.object_iterator); + break; + } + + case value_t::array: + { + result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, + last.m_it.array_iterator); + break; + } + + case value_t::null: + case value_t::discarded: + default: + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); + } + + return result; + } + + /*! + @brief remove element from a JSON object given a key + + Removes elements from a JSON object with the key value @a key. + + @param[in] key value of the elements to remove + + @return Number of elements removed. If @a ObjectType is the default + `std::map` type, the return value will always be `0` (@a key was not + found) or `1` (@a key was found). + + @post References and iterators to the erased elements are invalidated. + Other references and iterators are not affected. + + @throw type_error.307 when called on a type other than JSON object; + example: `"cannot use erase() with null"` + + @complexity `log(size()) + count(key)` + + @liveexample{The example shows the effect of `erase()`.,erase__key_type} + + @sa see @ref erase(IteratorType) -- removes the element at a given position + @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in + the given range + @sa see @ref erase(const size_type) -- removes the element from an array at + the given index + + @since version 1.0.0 + */ + size_type erase(const typename object_t::key_type& key) + { + // this erase only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + return m_value.object->erase(key); + } + + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); + } + + /*! + @brief remove element from a JSON array given an index + + Removes element from a JSON array at the index @a idx. + + @param[in] idx index of the element to remove + + @throw type_error.307 when called on a type other than JSON object; + example: `"cannot use erase() with null"` + @throw out_of_range.401 when `idx >= size()`; example: `"array index 17 + is out of range"` + + @complexity Linear in distance between @a idx and the end of the container. + + @liveexample{The example shows the effect of `erase()`.,erase__size_type} + + @sa see @ref erase(IteratorType) -- removes the element at a given position + @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in + the given range + @sa see @ref erase(const typename object_t::key_type&) -- removes the element + from an object at the given key + + @since version 1.0.0 + */ + void erase(const size_type idx) + { + // this erase only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + if (JSON_HEDLEY_UNLIKELY(idx >= size())) + { + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); + } + + m_value.array->erase(m_value.array->begin() + static_cast(idx)); + } + else + { + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); + } + } + + /// @} + + + //////////// + // lookup // + //////////// + + /// @name lookup + /// @{ + + /*! + @brief find an element in a JSON object + + Finds an element in a JSON object with key equivalent to @a key. If the + element is not found or the JSON value is not an object, end() is + returned. + + @note This method always returns @ref end() when executed on a JSON type + that is not an object. + + @param[in] key key value of the element to search for. + + @return Iterator to an element with key equivalent to @a key. If no such + element is found or the JSON value is not an object, past-the-end (see + @ref end()) iterator is returned. + + @complexity Logarithmic in the size of the JSON object. + + @liveexample{The example shows how `find()` is used.,find__key_type} + + @sa see @ref contains(KeyT&&) const -- checks whether a key exists + + @since version 1.0.0 + */ + template + iterator find(KeyT&& key) + { + auto result = end(); + + if (is_object()) + { + result.m_it.object_iterator = m_value.object->find(std::forward(key)); + } + + return result; + } + + /*! + @brief find an element in a JSON object + @copydoc find(KeyT&&) + */ + template + const_iterator find(KeyT&& key) const + { + auto result = cend(); + + if (is_object()) + { + result.m_it.object_iterator = m_value.object->find(std::forward(key)); + } + + return result; + } + + /*! + @brief returns the number of occurrences of a key in a JSON object + + Returns the number of elements with key @a key. If ObjectType is the + default `std::map` type, the return value will always be `0` (@a key was + not found) or `1` (@a key was found). + + @note This method always returns `0` when executed on a JSON type that is + not an object. + + @param[in] key key value of the element to count + + @return Number of elements with key @a key. If the JSON value is not an + object, the return value will be `0`. + + @complexity Logarithmic in the size of the JSON object. + + @liveexample{The example shows how `count()` is used.,count} + + @since version 1.0.0 + */ + template + size_type count(KeyT&& key) const + { + // return 0 for all nonobject types + return is_object() ? m_value.object->count(std::forward(key)) : 0; + } + + /*! + @brief check the existence of an element in a JSON object + + Check whether an element exists in a JSON object with key equivalent to + @a key. If the element is not found or the JSON value is not an object, + false is returned. + + @note This method always returns false when executed on a JSON type + that is not an object. + + @param[in] key key value to check its existence. + + @return true if an element with specified @a key exists. If no such + element with such key is found or the JSON value is not an object, + false is returned. + + @complexity Logarithmic in the size of the JSON object. + + @liveexample{The following code shows an example for `contains()`.,contains} + + @sa see @ref find(KeyT&&) -- returns an iterator to an object element + @sa see @ref contains(const json_pointer&) const -- checks the existence for a JSON pointer + + @since version 3.6.0 + */ + template < typename KeyT, typename std::enable_if < + !std::is_same::type, json_pointer>::value, int >::type = 0 > + bool contains(KeyT && key) const + { + return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); + } + + /*! + @brief check the existence of an element in a JSON object given a JSON pointer + + Check whether the given JSON pointer @a ptr can be resolved in the current + JSON value. + + @note This method can be executed on any JSON value type. + + @param[in] ptr JSON pointer to check its existence. + + @return true if the JSON pointer can be resolved to a stored value, false + otherwise. + + @post If `j.contains(ptr)` returns true, it is safe to call `j[ptr]`. + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + + @complexity Logarithmic in the size of the JSON object. + + @liveexample{The following code shows an example for `contains()`.,contains_json_pointer} + + @sa see @ref contains(KeyT &&) const -- checks the existence of a key + + @since version 3.7.0 + */ + bool contains(const json_pointer& ptr) const + { + return ptr.contains(this); + } + + /// @} + + + /////////////// + // iterators // + /////////////// + + /// @name iterators + /// @{ + + /*! + @brief returns an iterator to the first element + + Returns an iterator to the first element. + + @image html range-begin-end.svg "Illustration from cppreference.com" + + @return iterator to the first element + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [Container](https://en.cppreference.com/w/cpp/named_req/Container) + requirements: + - The complexity is constant. + + @liveexample{The following code shows an example for `begin()`.,begin} + + @sa see @ref cbegin() -- returns a const iterator to the beginning + @sa see @ref end() -- returns an iterator to the end + @sa see @ref cend() -- returns a const iterator to the end + + @since version 1.0.0 + */ + iterator begin() noexcept + { + iterator result(this); + result.set_begin(); + return result; + } + + /*! + @copydoc basic_json::cbegin() + */ + const_iterator begin() const noexcept + { + return cbegin(); + } + + /*! + @brief returns a const iterator to the first element + + Returns a const iterator to the first element. + + @image html range-begin-end.svg "Illustration from cppreference.com" + + @return const iterator to the first element + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [Container](https://en.cppreference.com/w/cpp/named_req/Container) + requirements: + - The complexity is constant. + - Has the semantics of `const_cast(*this).begin()`. + + @liveexample{The following code shows an example for `cbegin()`.,cbegin} + + @sa see @ref begin() -- returns an iterator to the beginning + @sa see @ref end() -- returns an iterator to the end + @sa see @ref cend() -- returns a const iterator to the end + + @since version 1.0.0 + */ + const_iterator cbegin() const noexcept + { + const_iterator result(this); + result.set_begin(); + return result; + } + + /*! + @brief returns an iterator to one past the last element + + Returns an iterator to one past the last element. + + @image html range-begin-end.svg "Illustration from cppreference.com" + + @return iterator one past the last element + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [Container](https://en.cppreference.com/w/cpp/named_req/Container) + requirements: + - The complexity is constant. + + @liveexample{The following code shows an example for `end()`.,end} + + @sa see @ref cend() -- returns a const iterator to the end + @sa see @ref begin() -- returns an iterator to the beginning + @sa see @ref cbegin() -- returns a const iterator to the beginning + + @since version 1.0.0 + */ + iterator end() noexcept + { + iterator result(this); + result.set_end(); + return result; + } + + /*! + @copydoc basic_json::cend() + */ + const_iterator end() const noexcept + { + return cend(); + } + + /*! + @brief returns a const iterator to one past the last element + + Returns a const iterator to one past the last element. + + @image html range-begin-end.svg "Illustration from cppreference.com" + + @return const iterator one past the last element + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [Container](https://en.cppreference.com/w/cpp/named_req/Container) + requirements: + - The complexity is constant. + - Has the semantics of `const_cast(*this).end()`. + + @liveexample{The following code shows an example for `cend()`.,cend} + + @sa see @ref end() -- returns an iterator to the end + @sa see @ref begin() -- returns an iterator to the beginning + @sa see @ref cbegin() -- returns a const iterator to the beginning + + @since version 1.0.0 + */ + const_iterator cend() const noexcept + { + const_iterator result(this); + result.set_end(); + return result; + } + + /*! + @brief returns an iterator to the reverse-beginning + + Returns an iterator to the reverse-beginning; that is, the last element. + + @image html range-rbegin-rend.svg "Illustration from cppreference.com" + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) + requirements: + - The complexity is constant. + - Has the semantics of `reverse_iterator(end())`. + + @liveexample{The following code shows an example for `rbegin()`.,rbegin} + + @sa see @ref crbegin() -- returns a const reverse iterator to the beginning + @sa see @ref rend() -- returns a reverse iterator to the end + @sa see @ref crend() -- returns a const reverse iterator to the end + + @since version 1.0.0 + */ + reverse_iterator rbegin() noexcept + { + return reverse_iterator(end()); + } + + /*! + @copydoc basic_json::crbegin() + */ + const_reverse_iterator rbegin() const noexcept + { + return crbegin(); + } + + /*! + @brief returns an iterator to the reverse-end + + Returns an iterator to the reverse-end; that is, one before the first + element. + + @image html range-rbegin-rend.svg "Illustration from cppreference.com" + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) + requirements: + - The complexity is constant. + - Has the semantics of `reverse_iterator(begin())`. + + @liveexample{The following code shows an example for `rend()`.,rend} + + @sa see @ref crend() -- returns a const reverse iterator to the end + @sa see @ref rbegin() -- returns a reverse iterator to the beginning + @sa see @ref crbegin() -- returns a const reverse iterator to the beginning + + @since version 1.0.0 + */ + reverse_iterator rend() noexcept + { + return reverse_iterator(begin()); + } + + /*! + @copydoc basic_json::crend() + */ + const_reverse_iterator rend() const noexcept + { + return crend(); + } + + /*! + @brief returns a const reverse iterator to the last element + + Returns a const iterator to the reverse-beginning; that is, the last + element. + + @image html range-rbegin-rend.svg "Illustration from cppreference.com" + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) + requirements: + - The complexity is constant. + - Has the semantics of `const_cast(*this).rbegin()`. + + @liveexample{The following code shows an example for `crbegin()`.,crbegin} + + @sa see @ref rbegin() -- returns a reverse iterator to the beginning + @sa see @ref rend() -- returns a reverse iterator to the end + @sa see @ref crend() -- returns a const reverse iterator to the end + + @since version 1.0.0 + */ + const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator(cend()); + } + + /*! + @brief returns a const reverse iterator to one before the first + + Returns a const reverse iterator to the reverse-end; that is, one before + the first element. + + @image html range-rbegin-rend.svg "Illustration from cppreference.com" + + @complexity Constant. + + @requirement This function helps `basic_json` satisfying the + [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) + requirements: + - The complexity is constant. + - Has the semantics of `const_cast(*this).rend()`. + + @liveexample{The following code shows an example for `crend()`.,crend} + + @sa see @ref rend() -- returns a reverse iterator to the end + @sa see @ref rbegin() -- returns a reverse iterator to the beginning + @sa see @ref crbegin() -- returns a const reverse iterator to the beginning + + @since version 1.0.0 + */ + const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator(cbegin()); + } + + public: + /*! + @brief wrapper to access iterator member functions in range-based for + + This function allows to access @ref iterator::key() and @ref + iterator::value() during range-based for loops. In these loops, a + reference to the JSON values is returned, so there is no access to the + underlying iterator. + + For loop without iterator_wrapper: + + @code{cpp} + for (auto it = j_object.begin(); it != j_object.end(); ++it) + { + std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; + } + @endcode + + Range-based for loop without iterator proxy: + + @code{cpp} + for (auto it : j_object) + { + // "it" is of type json::reference and has no key() member + std::cout << "value: " << it << '\n'; + } + @endcode + + Range-based for loop with iterator proxy: + + @code{cpp} + for (auto it : json::iterator_wrapper(j_object)) + { + std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; + } + @endcode + + @note When iterating over an array, `key()` will return the index of the + element as string (see example). + + @param[in] ref reference to a JSON value + @return iteration proxy object wrapping @a ref with an interface to use in + range-based for loops + + @liveexample{The following code shows how the wrapper is used,iterator_wrapper} + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. + + @note The name of this function is not yet final and may change in the + future. + + @deprecated This stream operator is deprecated and will be removed in + future 4.0.0 of the library. Please use @ref items() instead; + that is, replace `json::iterator_wrapper(j)` with `j.items()`. + */ + JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) + static iteration_proxy iterator_wrapper(reference ref) noexcept + { + return ref.items(); + } + + /*! + @copydoc iterator_wrapper(reference) + */ + JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) + static iteration_proxy iterator_wrapper(const_reference ref) noexcept + { + return ref.items(); + } + + /*! + @brief helper to access iterator member functions in range-based for + + This function allows to access @ref iterator::key() and @ref + iterator::value() during range-based for loops. In these loops, a + reference to the JSON values is returned, so there is no access to the + underlying iterator. + + For loop without `items()` function: + + @code{cpp} + for (auto it = j_object.begin(); it != j_object.end(); ++it) + { + std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; + } + @endcode + + Range-based for loop without `items()` function: + + @code{cpp} + for (auto it : j_object) + { + // "it" is of type json::reference and has no key() member + std::cout << "value: " << it << '\n'; + } + @endcode + + Range-based for loop with `items()` function: + + @code{cpp} + for (auto& el : j_object.items()) + { + std::cout << "key: " << el.key() << ", value:" << el.value() << '\n'; + } + @endcode + + The `items()` function also allows to use + [structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding) + (C++17): + + @code{cpp} + for (auto& [key, val] : j_object.items()) + { + std::cout << "key: " << key << ", value:" << val << '\n'; + } + @endcode + + @note When iterating over an array, `key()` will return the index of the + element as string (see example). For primitive types (e.g., numbers), + `key()` returns an empty string. + + @warning Using `items()` on temporary objects is dangerous. Make sure the + object's lifetime exeeds the iteration. See + for more + information. + + @return iteration proxy object wrapping @a ref with an interface to use in + range-based for loops + + @liveexample{The following code shows how the function is used.,items} + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. + + @since version 3.1.0, structured bindings support since 3.5.0. + */ + iteration_proxy items() noexcept + { + return iteration_proxy(*this); + } + + /*! + @copydoc items() + */ + iteration_proxy items() const noexcept + { + return iteration_proxy(*this); + } + + /// @} + + + ////////////// + // capacity // + ////////////// + + /// @name capacity + /// @{ + + /*! + @brief checks whether the container is empty. + + Checks if a JSON value has no elements (i.e. whether its @ref size is `0`). + + @return The return value depends on the different types and is + defined as follows: + Value type | return value + ----------- | ------------- + null | `true` + boolean | `false` + string | `false` + number | `false` + binary | `false` + object | result of function `object_t::empty()` + array | result of function `array_t::empty()` + + @liveexample{The following code uses `empty()` to check if a JSON + object contains any elements.,empty} + + @complexity Constant, as long as @ref array_t and @ref object_t satisfy + the Container concept; that is, their `empty()` functions have constant + complexity. + + @iterators No changes. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @note This function does not return whether a string stored as JSON value + is empty - it returns whether the JSON container itself is empty which is + false in the case of a string. + + @requirement This function helps `basic_json` satisfying the + [Container](https://en.cppreference.com/w/cpp/named_req/Container) + requirements: + - The complexity is constant. + - Has the semantics of `begin() == end()`. + + @sa see @ref size() -- returns the number of elements + + @since version 1.0.0 + */ + bool empty() const noexcept + { + switch (m_type) + { + case value_t::null: + { + // null values are empty + return true; + } + + case value_t::array: + { + // delegate call to array_t::empty() + return m_value.array->empty(); + } + + case value_t::object: + { + // delegate call to object_t::empty() + return m_value.object->empty(); + } + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + // all other types are nonempty + return false; + } + } + } + + /*! + @brief returns the number of elements + + Returns the number of elements in a JSON value. + + @return The return value depends on the different types and is + defined as follows: + Value type | return value + ----------- | ------------- + null | `0` + boolean | `1` + string | `1` + number | `1` + binary | `1` + object | result of function object_t::size() + array | result of function array_t::size() + + @liveexample{The following code calls `size()` on the different value + types.,size} + + @complexity Constant, as long as @ref array_t and @ref object_t satisfy + the Container concept; that is, their size() functions have constant + complexity. + + @iterators No changes. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @note This function does not return the length of a string stored as JSON + value - it returns the number of elements in the JSON value which is 1 in + the case of a string. + + @requirement This function helps `basic_json` satisfying the + [Container](https://en.cppreference.com/w/cpp/named_req/Container) + requirements: + - The complexity is constant. + - Has the semantics of `std::distance(begin(), end())`. + + @sa see @ref empty() -- checks whether the container is empty + @sa see @ref max_size() -- returns the maximal number of elements + + @since version 1.0.0 + */ + size_type size() const noexcept + { + switch (m_type) + { + case value_t::null: + { + // null values are empty + return 0; + } + + case value_t::array: + { + // delegate call to array_t::size() + return m_value.array->size(); + } + + case value_t::object: + { + // delegate call to object_t::size() + return m_value.object->size(); + } + + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + // all other types have size 1 + return 1; + } + } + } + + /*! + @brief returns the maximum possible number of elements + + Returns the maximum number of elements a JSON value is able to hold due to + system or library implementation limitations, i.e. `std::distance(begin(), + end())` for the JSON value. + + @return The return value depends on the different types and is + defined as follows: + Value type | return value + ----------- | ------------- + null | `0` (same as `size()`) + boolean | `1` (same as `size()`) + string | `1` (same as `size()`) + number | `1` (same as `size()`) + binary | `1` (same as `size()`) + object | result of function `object_t::max_size()` + array | result of function `array_t::max_size()` + + @liveexample{The following code calls `max_size()` on the different value + types. Note the output is implementation specific.,max_size} + + @complexity Constant, as long as @ref array_t and @ref object_t satisfy + the Container concept; that is, their `max_size()` functions have constant + complexity. + + @iterators No changes. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @requirement This function helps `basic_json` satisfying the + [Container](https://en.cppreference.com/w/cpp/named_req/Container) + requirements: + - The complexity is constant. + - Has the semantics of returning `b.size()` where `b` is the largest + possible JSON value. + + @sa see @ref size() -- returns the number of elements + + @since version 1.0.0 + */ + size_type max_size() const noexcept + { + switch (m_type) + { + case value_t::array: + { + // delegate call to array_t::max_size() + return m_value.array->max_size(); + } + + case value_t::object: + { + // delegate call to object_t::max_size() + return m_value.object->max_size(); + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + // all other types have max_size() == size() + return size(); + } + } + } + + /// @} + + + /////////////// + // modifiers // + /////////////// + + /// @name modifiers + /// @{ + + /*! + @brief clears the contents + + Clears the content of a JSON value and resets it to the default value as + if @ref basic_json(value_t) would have been called with the current value + type from @ref type(): + + Value type | initial value + ----------- | ------------- + null | `null` + boolean | `false` + string | `""` + number | `0` + binary | An empty byte vector + object | `{}` + array | `[]` + + @post Has the same effect as calling + @code {.cpp} + *this = basic_json(type()); + @endcode + + @liveexample{The example below shows the effect of `clear()` to different + JSON types.,clear} + + @complexity Linear in the size of the JSON value. + + @iterators All iterators, pointers and references related to this container + are invalidated. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @sa see @ref basic_json(value_t) -- constructor that creates an object with the + same value than calling `clear()` + + @since version 1.0.0 + */ + void clear() noexcept + { + switch (m_type) + { + case value_t::number_integer: + { + m_value.number_integer = 0; + break; + } + + case value_t::number_unsigned: + { + m_value.number_unsigned = 0; + break; + } + + case value_t::number_float: + { + m_value.number_float = 0.0; + break; + } + + case value_t::boolean: + { + m_value.boolean = false; + break; + } + + case value_t::string: + { + m_value.string->clear(); + break; + } + + case value_t::binary: + { + m_value.binary->clear(); + break; + } + + case value_t::array: + { + m_value.array->clear(); + break; + } + + case value_t::object: + { + m_value.object->clear(); + break; + } + + case value_t::null: + case value_t::discarded: + default: + break; + } + } + + /*! + @brief add an object to an array + + Appends the given element @a val to the end of the JSON value. If the + function is called on a JSON null value, an empty array is created before + appending @a val. + + @param[in] val the value to add to the JSON array + + @throw type_error.308 when called on a type other than JSON array or + null; example: `"cannot use push_back() with number"` + + @complexity Amortized constant. + + @liveexample{The example shows how `push_back()` and `+=` can be used to + add elements to a JSON array. Note how the `null` value was silently + converted to a JSON array.,push_back} + + @since version 1.0.0 + */ + void push_back(basic_json&& val) + { + // push_back only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) + { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); + } + + // transform null object into an array + if (is_null()) + { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array (move semantics) + const auto old_capacity = m_value.array->capacity(); + m_value.array->push_back(std::move(val)); + set_parent(m_value.array->back(), old_capacity); + // if val is moved from, basic_json move constructor marks it null so we do not call the destructor + } + + /*! + @brief add an object to an array + @copydoc push_back(basic_json&&) + */ + reference operator+=(basic_json&& val) + { + push_back(std::move(val)); + return *this; + } + + /*! + @brief add an object to an array + @copydoc push_back(basic_json&&) + */ + void push_back(const basic_json& val) + { + // push_back only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) + { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); + } + + // transform null object into an array + if (is_null()) + { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array + const auto old_capacity = m_value.array->capacity(); + m_value.array->push_back(val); + set_parent(m_value.array->back(), old_capacity); + } + + /*! + @brief add an object to an array + @copydoc push_back(basic_json&&) + */ + reference operator+=(const basic_json& val) + { + push_back(val); + return *this; + } + + /*! + @brief add an object to an object + + Inserts the given element @a val to the JSON object. If the function is + called on a JSON null value, an empty object is created before inserting + @a val. + + @param[in] val the value to add to the JSON object + + @throw type_error.308 when called on a type other than JSON object or + null; example: `"cannot use push_back() with number"` + + @complexity Logarithmic in the size of the container, O(log(`size()`)). + + @liveexample{The example shows how `push_back()` and `+=` can be used to + add elements to a JSON object. Note how the `null` value was silently + converted to a JSON object.,push_back__object_t__value} + + @since version 1.0.0 + */ + void push_back(const typename object_t::value_type& val) + { + // push_back only works for null objects or objects + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) + { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); + } + + // transform null object into an object + if (is_null()) + { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // add element to object + auto res = m_value.object->insert(val); + set_parent(res.first->second); + } + + /*! + @brief add an object to an object + @copydoc push_back(const typename object_t::value_type&) + */ + reference operator+=(const typename object_t::value_type& val) + { + push_back(val); + return *this; + } + + /*! + @brief add an object to an object + + This function allows to use `push_back` with an initializer list. In case + + 1. the current value is an object, + 2. the initializer list @a init contains only two elements, and + 3. the first element of @a init is a string, + + @a init is converted into an object element and added using + @ref push_back(const typename object_t::value_type&). Otherwise, @a init + is converted to a JSON value and added using @ref push_back(basic_json&&). + + @param[in] init an initializer list + + @complexity Linear in the size of the initializer list @a init. + + @note This function is required to resolve an ambiguous overload error, + because pairs like `{"key", "value"}` can be both interpreted as + `object_t::value_type` or `std::initializer_list`, see + https://github.com/nlohmann/json/issues/235 for more information. + + @liveexample{The example shows how initializer lists are treated as + objects when possible.,push_back__initializer_list} + */ + void push_back(initializer_list_t init) + { + if (is_object() && init.size() == 2 && (*init.begin())->is_string()) + { + basic_json&& key = init.begin()->moved_or_copied(); + push_back(typename object_t::value_type( + std::move(key.get_ref()), (init.begin() + 1)->moved_or_copied())); + } + else + { + push_back(basic_json(init)); + } + } + + /*! + @brief add an object to an object + @copydoc push_back(initializer_list_t) + */ + reference operator+=(initializer_list_t init) + { + push_back(init); + return *this; + } + + /*! + @brief add an object to an array + + Creates a JSON value from the passed parameters @a args to the end of the + JSON value. If the function is called on a JSON null value, an empty array + is created before appending the value created from @a args. + + @param[in] args arguments to forward to a constructor of @ref basic_json + @tparam Args compatible types to create a @ref basic_json object + + @return reference to the inserted element + + @throw type_error.311 when called on a type other than JSON array or + null; example: `"cannot use emplace_back() with number"` + + @complexity Amortized constant. + + @liveexample{The example shows how `push_back()` can be used to add + elements to a JSON array. Note how the `null` value was silently converted + to a JSON array.,emplace_back} + + @since version 2.0.8, returns reference since 3.7.0 + */ + template + reference emplace_back(Args&& ... args) + { + // emplace_back only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) + { + JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this)); + } + + // transform null object into an array + if (is_null()) + { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array (perfect forwarding) + const auto old_capacity = m_value.array->capacity(); + m_value.array->emplace_back(std::forward(args)...); + return set_parent(m_value.array->back(), old_capacity); + } + + /*! + @brief add an object to an object if key does not exist + + Inserts a new element into a JSON object constructed in-place with the + given @a args if there is no element with the key in the container. If the + function is called on a JSON null value, an empty object is created before + appending the value created from @a args. + + @param[in] args arguments to forward to a constructor of @ref basic_json + @tparam Args compatible types to create a @ref basic_json object + + @return a pair consisting of an iterator to the inserted element, or the + already-existing element if no insertion happened, and a bool + denoting whether the insertion took place. + + @throw type_error.311 when called on a type other than JSON object or + null; example: `"cannot use emplace() with number"` + + @complexity Logarithmic in the size of the container, O(log(`size()`)). + + @liveexample{The example shows how `emplace()` can be used to add elements + to a JSON object. Note how the `null` value was silently converted to a + JSON object. Further note how no value is added if there was already one + value stored with the same key.,emplace} + + @since version 2.0.8 + */ + template + std::pair emplace(Args&& ... args) + { + // emplace only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) + { + JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this)); + } + + // transform null object into an object + if (is_null()) + { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // add element to array (perfect forwarding) + auto res = m_value.object->emplace(std::forward(args)...); + set_parent(res.first->second); + + // create result iterator and set iterator to the result of emplace + auto it = begin(); + it.m_it.object_iterator = res.first; + + // return pair of iterator and boolean + return {it, res.second}; + } + + /// Helper for insertion of an iterator + /// @note: This uses std::distance to support GCC 4.8, + /// see https://github.com/nlohmann/json/pull/1257 + template + iterator insert_iterator(const_iterator pos, Args&& ... args) + { + iterator result(this); + JSON_ASSERT(m_value.array != nullptr); + + auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); + m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); + result.m_it.array_iterator = m_value.array->begin() + insert_pos; + + // This could have been written as: + // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); + // but the return value of insert is missing in GCC 4.8, so it is written this way instead. + + set_parents(); + return result; + } + + /*! + @brief inserts element + + Inserts element @a val before iterator @a pos. + + @param[in] pos iterator before which the content will be inserted; may be + the end() iterator + @param[in] val element to insert + @return iterator pointing to the inserted @a val. + + @throw type_error.309 if called on JSON values other than arrays; + example: `"cannot use insert() with string"` + @throw invalid_iterator.202 if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` + + @complexity Constant plus linear in the distance between @a pos and end of + the container. + + @liveexample{The example shows how `insert()` is used.,insert} + + @since version 1.0.0 + */ + iterator insert(const_iterator pos, const basic_json& val) + { + // insert only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + // insert to array and return iterator + return insert_iterator(pos, val); + } + + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + /*! + @brief inserts element + @copydoc insert(const_iterator, const basic_json&) + */ + iterator insert(const_iterator pos, basic_json&& val) + { + return insert(pos, val); + } + + /*! + @brief inserts elements + + Inserts @a cnt copies of @a val before iterator @a pos. + + @param[in] pos iterator before which the content will be inserted; may be + the end() iterator + @param[in] cnt number of copies of @a val to insert + @param[in] val element to insert + @return iterator pointing to the first element inserted, or @a pos if + `cnt==0` + + @throw type_error.309 if called on JSON values other than arrays; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` + + @complexity Linear in @a cnt plus linear in the distance between @a pos + and end of the container. + + @liveexample{The example shows how `insert()` is used.,insert__count} + + @since version 1.0.0 + */ + iterator insert(const_iterator pos, size_type cnt, const basic_json& val) + { + // insert only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + // insert to array and return iterator + return insert_iterator(pos, cnt, val); + } + + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + /*! + @brief inserts elements + + Inserts elements from range `[first, last)` before iterator @a pos. + + @param[in] pos iterator before which the content will be inserted; may be + the end() iterator + @param[in] first begin of the range of elements to insert + @param[in] last end of the range of elements to insert + + @throw type_error.309 if called on JSON values other than arrays; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` + @throw invalid_iterator.210 if @a first and @a last do not belong to the + same JSON value; example: `"iterators do not fit"` + @throw invalid_iterator.211 if @a first or @a last are iterators into + container for which insert is called; example: `"passed iterators may not + belong to container"` + + @return iterator pointing to the first element inserted, or @a pos if + `first==last` + + @complexity Linear in `std::distance(first, last)` plus linear in the + distance between @a pos and end of the container. + + @liveexample{The example shows how `insert()` is used.,insert__range} + + @since version 1.0.0 + */ + iterator insert(const_iterator pos, const_iterator first, const_iterator last) + { + // insert only works for arrays + if (JSON_HEDLEY_UNLIKELY(!is_array())) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + // check if range iterators belong to the same JSON object + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); + } + + if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) + { + JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this)); + } + + // insert to array and return iterator + return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); + } + + /*! + @brief inserts elements + + Inserts elements from initializer list @a ilist before iterator @a pos. + + @param[in] pos iterator before which the content will be inserted; may be + the end() iterator + @param[in] ilist initializer list to insert the values from + + @throw type_error.309 if called on JSON values other than arrays; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` + + @return iterator pointing to the first element inserted, or @a pos if + `ilist` is empty + + @complexity Linear in `ilist.size()` plus linear in the distance between + @a pos and end of the container. + + @liveexample{The example shows how `insert()` is used.,insert__ilist} + + @since version 1.0.0 + */ + iterator insert(const_iterator pos, initializer_list_t ilist) + { + // insert only works for arrays + if (JSON_HEDLEY_UNLIKELY(!is_array())) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) + { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); + } + + // insert to array and return iterator + return insert_iterator(pos, ilist.begin(), ilist.end()); + } + + /*! + @brief inserts elements + + Inserts elements from range `[first, last)`. + + @param[in] first begin of the range of elements to insert + @param[in] last end of the range of elements to insert + + @throw type_error.309 if called on JSON values other than objects; example: + `"cannot use insert() with string"` + @throw invalid_iterator.202 if iterator @a first or @a last does does not + point to an object; example: `"iterators first and last must point to + objects"` + @throw invalid_iterator.210 if @a first and @a last do not belong to the + same JSON value; example: `"iterators do not fit"` + + @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number + of elements to insert. + + @liveexample{The example shows how `insert()` is used.,insert__range_object} + + @since version 3.0.0 + */ + void insert(const_iterator first, const_iterator last) + { + // insert only works for objects + if (JSON_HEDLEY_UNLIKELY(!is_object())) + { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); + } + + // check if range iterators belong to the same JSON object + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); + } + + // passed iterators must belong to objects + if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) + { + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this)); + } + + m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); + } + + /*! + @brief updates a JSON object from another object, overwriting existing keys + + Inserts all values from JSON object @a j and overwrites existing keys. + + @param[in] j JSON object to read values from + + @throw type_error.312 if called on JSON values other than objects; example: + `"cannot use update() with string"` + + @complexity O(N*log(size() + N)), where N is the number of elements to + insert. + + @liveexample{The example shows how `update()` is used.,update} + + @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update + + @since version 3.0.0 + */ + void update(const_reference j) + { + // implicitly convert null value to an empty object + if (is_null()) + { + m_type = value_t::object; + m_value.object = create(); + assert_invariant(); + } + + if (JSON_HEDLEY_UNLIKELY(!is_object())) + { + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this)); + } + if (JSON_HEDLEY_UNLIKELY(!j.is_object())) + { + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()), *this)); + } + + for (auto it = j.cbegin(); it != j.cend(); ++it) + { + m_value.object->operator[](it.key()) = it.value(); +#if JSON_DIAGNOSTICS + m_value.object->operator[](it.key()).m_parent = this; +#endif + } + } + + /*! + @brief updates a JSON object from another object, overwriting existing keys + + Inserts all values from from range `[first, last)` and overwrites existing + keys. + + @param[in] first begin of the range of elements to insert + @param[in] last end of the range of elements to insert + + @throw type_error.312 if called on JSON values other than objects; example: + `"cannot use update() with string"` + @throw invalid_iterator.202 if iterator @a first or @a last does does not + point to an object; example: `"iterators first and last must point to + objects"` + @throw invalid_iterator.210 if @a first and @a last do not belong to the + same JSON value; example: `"iterators do not fit"` + + @complexity O(N*log(size() + N)), where N is the number of elements to + insert. + + @liveexample{The example shows how `update()` is used__range.,update} + + @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update + + @since version 3.0.0 + */ + void update(const_iterator first, const_iterator last) + { + // implicitly convert null value to an empty object + if (is_null()) + { + m_type = value_t::object; + m_value.object = create(); + assert_invariant(); + } + + if (JSON_HEDLEY_UNLIKELY(!is_object())) + { + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this)); + } + + // check if range iterators belong to the same JSON object + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) + { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); + } + + // passed iterators must belong to objects + if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object() + || !last.m_object->is_object())) + { + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this)); + } + + for (auto it = first; it != last; ++it) + { + m_value.object->operator[](it.key()) = it.value(); +#if JSON_DIAGNOSTICS + m_value.object->operator[](it.key()).m_parent = this; +#endif + } + } + + /*! + @brief exchanges the values + + Exchanges the contents of the JSON value with those of @a other. Does not + invoke any move, copy, or swap operations on individual elements. All + iterators and references remain valid. The past-the-end iterator is + invalidated. + + @param[in,out] other JSON value to exchange the contents with + + @complexity Constant. + + @liveexample{The example below shows how JSON values can be swapped with + `swap()`.,swap__reference} + + @since version 1.0.0 + */ + void swap(reference other) noexcept ( + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value&& + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value + ) + { + std::swap(m_type, other.m_type); + std::swap(m_value, other.m_value); + + set_parents(); + other.set_parents(); + assert_invariant(); + } + + /*! + @brief exchanges the values + + Exchanges the contents of the JSON value from @a left with those of @a right. Does not + invoke any move, copy, or swap operations on individual elements. All + iterators and references remain valid. The past-the-end iterator is + invalidated. implemented as a friend function callable via ADL. + + @param[in,out] left JSON value to exchange the contents with + @param[in,out] right JSON value to exchange the contents with + + @complexity Constant. + + @liveexample{The example below shows how JSON values can be swapped with + `swap()`.,swap__reference} + + @since version 1.0.0 + */ + friend void swap(reference left, reference right) noexcept ( + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value&& + std::is_nothrow_move_constructible::value&& + std::is_nothrow_move_assignable::value + ) + { + left.swap(right); + } + + /*! + @brief exchanges the values + + Exchanges the contents of a JSON array with those of @a other. Does not + invoke any move, copy, or swap operations on individual elements. All + iterators and references remain valid. The past-the-end iterator is + invalidated. + + @param[in,out] other array to exchange the contents with + + @throw type_error.310 when JSON value is not an array; example: `"cannot + use swap() with string"` + + @complexity Constant. + + @liveexample{The example below shows how arrays can be swapped with + `swap()`.,swap__array_t} + + @since version 1.0.0 + */ + void swap(array_t& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) + { + std::swap(*(m_value.array), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /*! + @brief exchanges the values + + Exchanges the contents of a JSON object with those of @a other. Does not + invoke any move, copy, or swap operations on individual elements. All + iterators and references remain valid. The past-the-end iterator is + invalidated. + + @param[in,out] other object to exchange the contents with + + @throw type_error.310 when JSON value is not an object; example: + `"cannot use swap() with string"` + + @complexity Constant. + + @liveexample{The example below shows how objects can be swapped with + `swap()`.,swap__object_t} + + @since version 1.0.0 + */ + void swap(object_t& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + std::swap(*(m_value.object), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /*! + @brief exchanges the values + + Exchanges the contents of a JSON string with those of @a other. Does not + invoke any move, copy, or swap operations on individual elements. All + iterators and references remain valid. The past-the-end iterator is + invalidated. + + @param[in,out] other string to exchange the contents with + + @throw type_error.310 when JSON value is not a string; example: `"cannot + use swap() with boolean"` + + @complexity Constant. + + @liveexample{The example below shows how strings can be swapped with + `swap()`.,swap__string_t} + + @since version 1.0.0 + */ + void swap(string_t& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for strings + if (JSON_HEDLEY_LIKELY(is_string())) + { + std::swap(*(m_value.string), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /*! + @brief exchanges the values + + Exchanges the contents of a JSON string with those of @a other. Does not + invoke any move, copy, or swap operations on individual elements. All + iterators and references remain valid. The past-the-end iterator is + invalidated. + + @param[in,out] other binary to exchange the contents with + + @throw type_error.310 when JSON value is not a string; example: `"cannot + use swap() with boolean"` + + @complexity Constant. + + @liveexample{The example below shows how strings can be swapped with + `swap()`.,swap__binary_t} + + @since version 3.8.0 + */ + void swap(binary_t& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for strings + if (JSON_HEDLEY_LIKELY(is_binary())) + { + std::swap(*(m_value.binary), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /// @copydoc swap(binary_t&) + void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape) + { + // swap only works for strings + if (JSON_HEDLEY_LIKELY(is_binary())) + { + std::swap(*(m_value.binary), other); + } + else + { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); + } + } + + /// @} + + public: + ////////////////////////////////////////// + // lexicographical comparison operators // + ////////////////////////////////////////// + + /// @name lexicographical comparison operators + /// @{ + + /*! + @brief comparison: equal + + Compares two JSON values for equality according to the following rules: + - Two JSON values are equal if (1) they are from the same type and (2) + their stored values are the same according to their respective + `operator==`. + - Integer and floating-point numbers are automatically converted before + comparison. Note that two NaN values are always treated as unequal. + - Two JSON null values are equal. + + @note Floating-point inside JSON values numbers are compared with + `json::number_float_t::operator==` which is `double::operator==` by + default. To compare floating-point while respecting an epsilon, an alternative + [comparison function](https://github.com/mariokonrad/marnav/blob/master/include/marnav/math/floatingpoint.hpp#L34-#L39) + could be used, for instance + @code {.cpp} + template::value, T>::type> + inline bool is_same(T a, T b, T epsilon = std::numeric_limits::epsilon()) noexcept + { + return std::abs(a - b) <= epsilon; + } + @endcode + Or you can self-defined operator equal function like this: + @code {.cpp} + bool my_equal(const_reference lhs, const_reference rhs) { + const auto lhs_type lhs.type(); + const auto rhs_type rhs.type(); + if (lhs_type == rhs_type) { + switch(lhs_type) + // self_defined case + case value_t::number_float: + return std::abs(lhs - rhs) <= std::numeric_limits::epsilon(); + // other cases remain the same with the original + ... + } + ... + } + @endcode + + @note NaN values never compare equal to themselves or to other NaN values. + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether the values @a lhs and @a rhs are equal + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @complexity Linear. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__equal} + + @since version 1.0.0 + */ + friend bool operator==(const_reference lhs, const_reference rhs) noexcept + { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + + if (lhs_type == rhs_type) + { + switch (lhs_type) + { + case value_t::array: + return *lhs.m_value.array == *rhs.m_value.array; + + case value_t::object: + return *lhs.m_value.object == *rhs.m_value.object; + + case value_t::null: + return true; + + case value_t::string: + return *lhs.m_value.string == *rhs.m_value.string; + + case value_t::boolean: + return lhs.m_value.boolean == rhs.m_value.boolean; + + case value_t::number_integer: + return lhs.m_value.number_integer == rhs.m_value.number_integer; + + case value_t::number_unsigned: + return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; + + case value_t::number_float: + return lhs.m_value.number_float == rhs.m_value.number_float; + + case value_t::binary: + return *lhs.m_value.binary == *rhs.m_value.binary; + + case value_t::discarded: + default: + return false; + } + } + else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_integer) == rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) + { + return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); + } + else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_float == static_cast(rhs.m_value.number_unsigned); + } + else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) + { + return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; + } + else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); + } + + return false; +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + } + + /*! + @brief comparison: equal + @copydoc operator==(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator==(const_reference lhs, ScalarType rhs) noexcept + { + return lhs == basic_json(rhs); + } + + /*! + @brief comparison: equal + @copydoc operator==(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator==(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) == rhs; + } + + /*! + @brief comparison: not equal + + Compares two JSON values for inequality by calculating `not (lhs == rhs)`. + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether the values @a lhs and @a rhs are not equal + + @complexity Linear. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__notequal} + + @since version 1.0.0 + */ + friend bool operator!=(const_reference lhs, const_reference rhs) noexcept + { + return !(lhs == rhs); + } + + /*! + @brief comparison: not equal + @copydoc operator!=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept + { + return lhs != basic_json(rhs); + } + + /*! + @brief comparison: not equal + @copydoc operator!=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) != rhs; + } + + /*! + @brief comparison: less than + + Compares whether one JSON value @a lhs is less than another JSON value @a + rhs according to the following rules: + - If @a lhs and @a rhs have the same type, the values are compared using + the default `<` operator. + - Integer and floating-point numbers are automatically converted before + comparison + - In case @a lhs and @a rhs have different types, the values are ignored + and the order of the types is considered, see + @ref operator<(const value_t, const value_t). + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether @a lhs is less than @a rhs + + @complexity Linear. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__less} + + @since version 1.0.0 + */ + friend bool operator<(const_reference lhs, const_reference rhs) noexcept + { + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); + + if (lhs_type == rhs_type) + { + switch (lhs_type) + { + case value_t::array: + // note parentheses are necessary, see + // https://github.com/nlohmann/json/issues/1530 + return (*lhs.m_value.array) < (*rhs.m_value.array); + + case value_t::object: + return (*lhs.m_value.object) < (*rhs.m_value.object); + + case value_t::null: + return false; + + case value_t::string: + return (*lhs.m_value.string) < (*rhs.m_value.string); + + case value_t::boolean: + return (lhs.m_value.boolean) < (rhs.m_value.boolean); + + case value_t::number_integer: + return (lhs.m_value.number_integer) < (rhs.m_value.number_integer); + + case value_t::number_unsigned: + return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned); + + case value_t::number_float: + return (lhs.m_value.number_float) < (rhs.m_value.number_float); + + case value_t::binary: + return (*lhs.m_value.binary) < (*rhs.m_value.binary); + + case value_t::discarded: + default: + return false; + } + } + else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) + { + return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); + } + else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) + { + return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_float; + } + else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_float < static_cast(rhs.m_value.number_unsigned); + } + else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) + { + return lhs.m_value.number_integer < static_cast(rhs.m_value.number_unsigned); + } + else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) + { + return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; + } + + // We only reach this line if we cannot compare values. In that case, + // we compare types. Note we have to call the operator explicitly, + // because MSVC has problems otherwise. + return operator<(lhs_type, rhs_type); + } + + /*! + @brief comparison: less than + @copydoc operator<(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<(const_reference lhs, ScalarType rhs) noexcept + { + return lhs < basic_json(rhs); + } + + /*! + @brief comparison: less than + @copydoc operator<(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) < rhs; + } + + /*! + @brief comparison: less than or equal + + Compares whether one JSON value @a lhs is less than or equal to another + JSON value by calculating `not (rhs < lhs)`. + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether @a lhs is less than or equal to @a rhs + + @complexity Linear. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__greater} + + @since version 1.0.0 + */ + friend bool operator<=(const_reference lhs, const_reference rhs) noexcept + { + return !(rhs < lhs); + } + + /*! + @brief comparison: less than or equal + @copydoc operator<=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept + { + return lhs <= basic_json(rhs); + } + + /*! + @brief comparison: less than or equal + @copydoc operator<=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) <= rhs; + } + + /*! + @brief comparison: greater than + + Compares whether one JSON value @a lhs is greater than another + JSON value by calculating `not (lhs <= rhs)`. + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether @a lhs is greater than to @a rhs + + @complexity Linear. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__lessequal} + + @since version 1.0.0 + */ + friend bool operator>(const_reference lhs, const_reference rhs) noexcept + { + return !(lhs <= rhs); + } + + /*! + @brief comparison: greater than + @copydoc operator>(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>(const_reference lhs, ScalarType rhs) noexcept + { + return lhs > basic_json(rhs); + } + + /*! + @brief comparison: greater than + @copydoc operator>(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) > rhs; + } + + /*! + @brief comparison: greater than or equal + + Compares whether one JSON value @a lhs is greater than or equal to another + JSON value by calculating `not (lhs < rhs)`. + + @param[in] lhs first JSON value to consider + @param[in] rhs second JSON value to consider + @return whether @a lhs is greater than or equal to @a rhs + + @complexity Linear. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @liveexample{The example demonstrates comparing several JSON + types.,operator__greaterequal} + + @since version 1.0.0 + */ + friend bool operator>=(const_reference lhs, const_reference rhs) noexcept + { + return !(lhs < rhs); + } + + /*! + @brief comparison: greater than or equal + @copydoc operator>=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept + { + return lhs >= basic_json(rhs); + } + + /*! + @brief comparison: greater than or equal + @copydoc operator>=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept + { + return basic_json(lhs) >= rhs; + } + + /// @} + + /////////////////// + // serialization // + /////////////////// + + /// @name serialization + /// @{ +#ifndef JSON_NO_IO + /*! + @brief serialize to stream + + Serialize the given JSON value @a j to the output stream @a o. The JSON + value will be serialized using the @ref dump member function. + + - The indentation of the output can be controlled with the member variable + `width` of the output stream @a o. For instance, using the manipulator + `std::setw(4)` on @a o sets the indentation level to `4` and the + serialization result is the same as calling `dump(4)`. + + - The indentation character can be controlled with the member variable + `fill` of the output stream @a o. For instance, the manipulator + `std::setfill('\\t')` sets indentation to use a tab character rather than + the default space character. + + @param[in,out] o stream to serialize to + @param[in] j JSON value to serialize + + @return the stream @a o + + @throw type_error.316 if a string stored inside the JSON value is not + UTF-8 encoded + + @complexity Linear. + + @liveexample{The example below shows the serialization with different + parameters to `width` to adjust the indentation level.,operator_serialize} + + @since version 1.0.0; indentation character added in version 3.0.0 + */ + friend std::ostream& operator<<(std::ostream& o, const basic_json& j) + { + // read width member and use it as indentation parameter if nonzero + const bool pretty_print = o.width() > 0; + const auto indentation = pretty_print ? o.width() : 0; + + // reset width to 0 for subsequent calls to this stream + o.width(0); + + // do the actual serialization + serializer s(detail::output_adapter(o), o.fill()); + s.dump(j, pretty_print, false, static_cast(indentation)); + return o; + } + + /*! + @brief serialize to stream + @deprecated This stream operator is deprecated and will be removed in + future 4.0.0 of the library. Please use + @ref operator<<(std::ostream&, const basic_json&) + instead; that is, replace calls like `j >> o;` with `o << j;`. + @since version 1.0.0; deprecated since version 3.0.0 + */ + JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) + friend std::ostream& operator>>(const basic_json& j, std::ostream& o) + { + return o << j; + } +#endif // JSON_NO_IO + /// @} + + + ///////////////////// + // deserialization // + ///////////////////// + + /// @name deserialization + /// @{ + + /*! + @brief deserialize from a compatible input + + @tparam InputType A compatible input, for instance + - an std::istream object + - a FILE pointer + - a C-style array of characters + - a pointer to a null-terminated string of single byte characters + - an object obj for which begin(obj) and end(obj) produces a valid pair of + iterators. + + @param[in] i input to read from + @param[in] cb a parser callback function of type @ref parser_callback_t + which is used to control the deserialization by filtering unwanted values + (optional) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + @param[in] ignore_comments whether comments should be ignored and treated + like whitespace (true) or yield a parse error (true); (optional, false by + default) + + @return deserialized JSON value; in case of a parse error and + @a allow_exceptions set to `false`, the return value will be + value_t::discarded. + + @throw parse_error.101 if a parse error occurs; example: `""unexpected end + of input; expected string literal""` + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + + @complexity Linear in the length of the input. The parser is a predictive + LL(1) parser. The complexity can be higher if the parser callback function + @a cb or reading from the input @a i has a super-linear complexity. + + @note A UTF-8 byte order mark is silently ignored. + + @liveexample{The example below demonstrates the `parse()` function reading + from an array.,parse__array__parser_callback_t} + + @liveexample{The example below demonstrates the `parse()` function with + and without callback function.,parse__string__parser_callback_t} + + @liveexample{The example below demonstrates the `parse()` function with + and without callback function.,parse__istream__parser_callback_t} + + @liveexample{The example below demonstrates the `parse()` function reading + from a contiguous container.,parse__contiguouscontainer__parser_callback_t} + + @since version 2.0.3 (contiguous containers); version 3.9.0 allowed to + ignore comments. + */ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json parse(InputType&& i, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false) + { + basic_json result; + parser(detail::input_adapter(std::forward(i)), cb, allow_exceptions, ignore_comments).parse(true, result); + return result; + } + + /*! + @brief deserialize from a pair of character iterators + + The value_type of the iterator must be a integral type with size of 1, 2 or + 4 bytes, which will be interpreted respectively as UTF-8, UTF-16 and UTF-32. + + @param[in] first iterator to start of character range + @param[in] last iterator to end of character range + @param[in] cb a parser callback function of type @ref parser_callback_t + which is used to control the deserialization by filtering unwanted values + (optional) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + @param[in] ignore_comments whether comments should be ignored and treated + like whitespace (true) or yield a parse error (true); (optional, false by + default) + + @return deserialized JSON value; in case of a parse error and + @a allow_exceptions set to `false`, the return value will be + value_t::discarded. + + @throw parse_error.101 if a parse error occurs; example: `""unexpected end + of input; expected string literal""` + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + */ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json parse(IteratorType first, + IteratorType last, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false) + { + basic_json result; + parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); + return result; + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) + static basic_json parse(detail::span_input_adapter&& i, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false) + { + basic_json result; + parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); + return result; + } + + /*! + @brief check if the input is valid JSON + + Unlike the @ref parse(InputType&&, const parser_callback_t,const bool) + function, this function neither throws an exception in case of invalid JSON + input (i.e., a parse error) nor creates diagnostic information. + + @tparam InputType A compatible input, for instance + - an std::istream object + - a FILE pointer + - a C-style array of characters + - a pointer to a null-terminated string of single byte characters + - an object obj for which begin(obj) and end(obj) produces a valid pair of + iterators. + + @param[in] i input to read from + @param[in] ignore_comments whether comments should be ignored and treated + like whitespace (true) or yield a parse error (true); (optional, false by + default) + + @return Whether the input read from @a i is valid JSON. + + @complexity Linear in the length of the input. The parser is a predictive + LL(1) parser. + + @note A UTF-8 byte order mark is silently ignored. + + @liveexample{The example below demonstrates the `accept()` function reading + from a string.,accept__string} + */ + template + static bool accept(InputType&& i, + const bool ignore_comments = false) + { + return parser(detail::input_adapter(std::forward(i)), nullptr, false, ignore_comments).accept(true); + } + + template + static bool accept(IteratorType first, IteratorType last, + const bool ignore_comments = false) + { + return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true); + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) + static bool accept(detail::span_input_adapter&& i, + const bool ignore_comments = false) + { + return parser(i.get(), nullptr, false, ignore_comments).accept(true); + } + + /*! + @brief generate SAX events + + The SAX event lister must follow the interface of @ref json_sax. + + This function reads from a compatible input. Examples are: + - an std::istream object + - a FILE pointer + - a C-style array of characters + - a pointer to a null-terminated string of single byte characters + - an object obj for which begin(obj) and end(obj) produces a valid pair of + iterators. + + @param[in] i input to read from + @param[in,out] sax SAX event listener + @param[in] format the format to parse (JSON, CBOR, MessagePack, or UBJSON) + @param[in] strict whether the input has to be consumed completely + @param[in] ignore_comments whether comments should be ignored and treated + like whitespace (true) or yield a parse error (true); (optional, false by + default); only applies to the JSON file format. + + @return return value of the last processed SAX event + + @throw parse_error.101 if a parse error occurs; example: `""unexpected end + of input; expected string literal""` + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + + @complexity Linear in the length of the input. The parser is a predictive + LL(1) parser. The complexity can be higher if the SAX consumer @a sax has + a super-linear complexity. + + @note A UTF-8 byte order mark is silently ignored. + + @liveexample{The example below demonstrates the `sax_parse()` function + reading from string and processing the events with a user-defined SAX + event consumer.,sax_parse} + + @since version 3.2.0 + */ + template + JSON_HEDLEY_NON_NULL(2) + static bool sax_parse(InputType&& i, SAX* sax, + input_format_t format = input_format_t::json, + const bool strict = true, + const bool ignore_comments = false) + { + auto ia = detail::input_adapter(std::forward(i)); + return format == input_format_t::json + ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) + : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); + } + + template + JSON_HEDLEY_NON_NULL(3) + static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, + input_format_t format = input_format_t::json, + const bool strict = true, + const bool ignore_comments = false) + { + auto ia = detail::input_adapter(std::move(first), std::move(last)); + return format == input_format_t::json + ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) + : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); + } + + template + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) + JSON_HEDLEY_NON_NULL(2) + static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, + input_format_t format = input_format_t::json, + const bool strict = true, + const bool ignore_comments = false) + { + auto ia = i.get(); + return format == input_format_t::json + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); + } +#ifndef JSON_NO_IO + /*! + @brief deserialize from stream + @deprecated This stream operator is deprecated and will be removed in + version 4.0.0 of the library. Please use + @ref operator>>(std::istream&, basic_json&) + instead; that is, replace calls like `j << i;` with `i >> j;`. + @since version 1.0.0; deprecated since version 3.0.0 + */ + JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) + friend std::istream& operator<<(basic_json& j, std::istream& i) + { + return operator>>(i, j); + } + + /*! + @brief deserialize from stream + + Deserializes an input stream to a JSON value. + + @param[in,out] i input stream to read a serialized JSON value from + @param[in,out] j JSON value to write the deserialized input to + + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + + @complexity Linear in the length of the input. The parser is a predictive + LL(1) parser. + + @note A UTF-8 byte order mark is silently ignored. + + @liveexample{The example below shows how a JSON value is constructed by + reading a serialization from a stream.,operator_deserialize} + + @sa parse(std::istream&, const parser_callback_t) for a variant with a + parser callback function to filter values while parsing + + @since version 1.0.0 + */ + friend std::istream& operator>>(std::istream& i, basic_json& j) + { + parser(detail::input_adapter(i)).parse(false, j); + return i; + } +#endif // JSON_NO_IO + /// @} + + /////////////////////////// + // convenience functions // + /////////////////////////// + + /*! + @brief return the type as string + + Returns the type name as string to be used in error messages - usually to + indicate that a function was called on a wrong JSON type. + + @return a string representation of a the @a m_type member: + Value type | return value + ----------- | ------------- + null | `"null"` + boolean | `"boolean"` + string | `"string"` + number | `"number"` (for all number types) + object | `"object"` + array | `"array"` + binary | `"binary"` + discarded | `"discarded"` + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @complexity Constant. + + @liveexample{The following code exemplifies `type_name()` for all JSON + types.,type_name} + + @sa see @ref type() -- return the type of the JSON value + @sa see @ref operator value_t() -- return the type of the JSON value (implicit) + + @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept` + since 3.0.0 + */ + JSON_HEDLEY_RETURNS_NON_NULL + const char* type_name() const noexcept + { + { + switch (m_type) + { + case value_t::null: + return "null"; + case value_t::object: + return "object"; + case value_t::array: + return "array"; + case value_t::string: + return "string"; + case value_t::boolean: + return "boolean"; + case value_t::binary: + return "binary"; + case value_t::discarded: + return "discarded"; + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + default: + return "number"; + } + } + } + + + JSON_PRIVATE_UNLESS_TESTED: + ////////////////////// + // member variables // + ////////////////////// + + /// the type of the current element + value_t m_type = value_t::null; + + /// the value of the current element + json_value m_value = {}; + +#if JSON_DIAGNOSTICS + /// a pointer to a parent value (for debugging purposes) + basic_json* m_parent = nullptr; +#endif + + ////////////////////////////////////////// + // binary serialization/deserialization // + ////////////////////////////////////////// + + /// @name binary serialization/deserialization support + /// @{ + + public: + /*! + @brief create a CBOR serialization of a given JSON value + + Serializes a given JSON value @a j to a byte vector using the CBOR (Concise + Binary Object Representation) serialization format. CBOR is a binary + serialization format which aims to be more compact than JSON itself, yet + more efficient to parse. + + The library uses the following mapping from JSON values types to + CBOR types according to the CBOR specification (RFC 7049): + + JSON value type | value/range | CBOR type | first byte + --------------- | ------------------------------------------ | ---------------------------------- | --------------- + null | `null` | Null | 0xF6 + boolean | `true` | True | 0xF5 + boolean | `false` | False | 0xF4 + number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B + number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A + number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39 + number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38 + number_integer | -24..-1 | Negative integer | 0x20..0x37 + number_integer | 0..23 | Integer | 0x00..0x17 + number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18 + number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 + number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A + number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B + number_unsigned | 0..23 | Integer | 0x00..0x17 + number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18 + number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 + number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A + number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B + number_float | *any value representable by a float* | Single-Precision Float | 0xFA + number_float | *any value NOT representable by a float* | Double-Precision Float | 0xFB + string | *length*: 0..23 | UTF-8 string | 0x60..0x77 + string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78 + string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 + string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A + string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B + array | *size*: 0..23 | array | 0x80..0x97 + array | *size*: 23..255 | array (1 byte follow) | 0x98 + array | *size*: 256..65535 | array (2 bytes follow) | 0x99 + array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A + array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B + object | *size*: 0..23 | map | 0xA0..0xB7 + object | *size*: 23..255 | map (1 byte follow) | 0xB8 + object | *size*: 256..65535 | map (2 bytes follow) | 0xB9 + object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA + object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB + binary | *size*: 0..23 | byte string | 0x40..0x57 + binary | *size*: 23..255 | byte string (1 byte follow) | 0x58 + binary | *size*: 256..65535 | byte string (2 bytes follow) | 0x59 + binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A + binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B + + Binary values with subtype are mapped to tagged values (0xD8..0xDB) + depending on the subtype, followed by a byte string, see "binary" cells + in the table above. + + @note The mapping is **complete** in the sense that any JSON value type + can be converted to a CBOR value. + + @note If NaN or Infinity are stored inside a JSON number, they are + serialized properly. This behavior differs from the @ref dump() + function which serializes NaN or Infinity to `null`. + + @note The following CBOR types are not used in the conversion: + - UTF-8 strings terminated by "break" (0x7F) + - arrays terminated by "break" (0x9F) + - maps terminated by "break" (0xBF) + - byte strings terminated by "break" (0x5F) + - date/time (0xC0..0xC1) + - bignum (0xC2..0xC3) + - decimal fraction (0xC4) + - bigfloat (0xC5) + - expected conversions (0xD5..0xD7) + - simple values (0xE0..0xF3, 0xF8) + - undefined (0xF7) + - half-precision floats (0xF9) + - break (0xFF) + + @param[in] j JSON value to serialize + @return CBOR serialization as byte vector + + @complexity Linear in the size of the JSON value @a j. + + @liveexample{The example shows the serialization of a JSON value to a byte + vector in CBOR format.,to_cbor} + + @sa http://cbor.io + @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the + analogous deserialization + @sa see @ref to_msgpack(const basic_json&) for the related MessagePack format + @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the + related UBJSON format + + @since version 2.0.9; compact representation of floating-point numbers + since version 3.8.0 + */ + static std::vector to_cbor(const basic_json& j) + { + std::vector result; + to_cbor(j, result); + return result; + } + + static void to_cbor(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_cbor(j); + } + + static void to_cbor(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_cbor(j); + } + + /*! + @brief create a MessagePack serialization of a given JSON value + + Serializes a given JSON value @a j to a byte vector using the MessagePack + serialization format. MessagePack is a binary serialization format which + aims to be more compact than JSON itself, yet more efficient to parse. + + The library uses the following mapping from JSON values types to + MessagePack types according to the MessagePack specification: + + JSON value type | value/range | MessagePack type | first byte + --------------- | --------------------------------- | ---------------- | ---------- + null | `null` | nil | 0xC0 + boolean | `true` | true | 0xC3 + boolean | `false` | false | 0xC2 + number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3 + number_integer | -2147483648..-32769 | int32 | 0xD2 + number_integer | -32768..-129 | int16 | 0xD1 + number_integer | -128..-33 | int8 | 0xD0 + number_integer | -32..-1 | negative fixint | 0xE0..0xFF + number_integer | 0..127 | positive fixint | 0x00..0x7F + number_integer | 128..255 | uint 8 | 0xCC + number_integer | 256..65535 | uint 16 | 0xCD + number_integer | 65536..4294967295 | uint 32 | 0xCE + number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF + number_unsigned | 0..127 | positive fixint | 0x00..0x7F + number_unsigned | 128..255 | uint 8 | 0xCC + number_unsigned | 256..65535 | uint 16 | 0xCD + number_unsigned | 65536..4294967295 | uint 32 | 0xCE + number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF + number_float | *any value representable by a float* | float 32 | 0xCA + number_float | *any value NOT representable by a float* | float 64 | 0xCB + string | *length*: 0..31 | fixstr | 0xA0..0xBF + string | *length*: 32..255 | str 8 | 0xD9 + string | *length*: 256..65535 | str 16 | 0xDA + string | *length*: 65536..4294967295 | str 32 | 0xDB + array | *size*: 0..15 | fixarray | 0x90..0x9F + array | *size*: 16..65535 | array 16 | 0xDC + array | *size*: 65536..4294967295 | array 32 | 0xDD + object | *size*: 0..15 | fix map | 0x80..0x8F + object | *size*: 16..65535 | map 16 | 0xDE + object | *size*: 65536..4294967295 | map 32 | 0xDF + binary | *size*: 0..255 | bin 8 | 0xC4 + binary | *size*: 256..65535 | bin 16 | 0xC5 + binary | *size*: 65536..4294967295 | bin 32 | 0xC6 + + @note The mapping is **complete** in the sense that any JSON value type + can be converted to a MessagePack value. + + @note The following values can **not** be converted to a MessagePack value: + - strings with more than 4294967295 bytes + - byte strings with more than 4294967295 bytes + - arrays with more than 4294967295 elements + - objects with more than 4294967295 elements + + @note Any MessagePack output created @ref to_msgpack can be successfully + parsed by @ref from_msgpack. + + @note If NaN or Infinity are stored inside a JSON number, they are + serialized properly. This behavior differs from the @ref dump() + function which serializes NaN or Infinity to `null`. + + @param[in] j JSON value to serialize + @return MessagePack serialization as byte vector + + @complexity Linear in the size of the JSON value @a j. + + @liveexample{The example shows the serialization of a JSON value to a byte + vector in MessagePack format.,to_msgpack} + + @sa http://msgpack.org + @sa see @ref from_msgpack for the analogous deserialization + @sa see @ref to_cbor(const basic_json& for the related CBOR format + @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the + related UBJSON format + + @since version 2.0.9 + */ + static std::vector to_msgpack(const basic_json& j) + { + std::vector result; + to_msgpack(j, result); + return result; + } + + static void to_msgpack(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_msgpack(j); + } + + static void to_msgpack(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_msgpack(j); + } + + /*! + @brief create a UBJSON serialization of a given JSON value + + Serializes a given JSON value @a j to a byte vector using the UBJSON + (Universal Binary JSON) serialization format. UBJSON aims to be more compact + than JSON itself, yet more efficient to parse. + + The library uses the following mapping from JSON values types to + UBJSON types according to the UBJSON specification: + + JSON value type | value/range | UBJSON type | marker + --------------- | --------------------------------- | ----------- | ------ + null | `null` | null | `Z` + boolean | `true` | true | `T` + boolean | `false` | false | `F` + number_integer | -9223372036854775808..-2147483649 | int64 | `L` + number_integer | -2147483648..-32769 | int32 | `l` + number_integer | -32768..-129 | int16 | `I` + number_integer | -128..127 | int8 | `i` + number_integer | 128..255 | uint8 | `U` + number_integer | 256..32767 | int16 | `I` + number_integer | 32768..2147483647 | int32 | `l` + number_integer | 2147483648..9223372036854775807 | int64 | `L` + number_unsigned | 0..127 | int8 | `i` + number_unsigned | 128..255 | uint8 | `U` + number_unsigned | 256..32767 | int16 | `I` + number_unsigned | 32768..2147483647 | int32 | `l` + number_unsigned | 2147483648..9223372036854775807 | int64 | `L` + number_unsigned | 2147483649..18446744073709551615 | high-precision | `H` + number_float | *any value* | float64 | `D` + string | *with shortest length indicator* | string | `S` + array | *see notes on optimized format* | array | `[` + object | *see notes on optimized format* | map | `{` + + @note The mapping is **complete** in the sense that any JSON value type + can be converted to a UBJSON value. + + @note The following values can **not** be converted to a UBJSON value: + - strings with more than 9223372036854775807 bytes (theoretical) + + @note The following markers are not used in the conversion: + - `Z`: no-op values are not created. + - `C`: single-byte strings are serialized with `S` markers. + + @note Any UBJSON output created @ref to_ubjson can be successfully parsed + by @ref from_ubjson. + + @note If NaN or Infinity are stored inside a JSON number, they are + serialized properly. This behavior differs from the @ref dump() + function which serializes NaN or Infinity to `null`. + + @note The optimized formats for containers are supported: Parameter + @a use_size adds size information to the beginning of a container and + removes the closing marker. Parameter @a use_type further checks + whether all elements of a container have the same type and adds the + type marker to the beginning of the container. The @a use_type + parameter must only be used together with @a use_size = true. Note + that @a use_size = true alone may result in larger representations - + the benefit of this parameter is that the receiving side is + immediately informed on the number of elements of the container. + + @note If the JSON data contains the binary type, the value stored is a list + of integers, as suggested by the UBJSON documentation. In particular, + this means that serialization and the deserialization of a JSON + containing binary values into UBJSON and back will result in a + different JSON object. + + @param[in] j JSON value to serialize + @param[in] use_size whether to add size annotations to container types + @param[in] use_type whether to add type annotations to container types + (must be combined with @a use_size = true) + @return UBJSON serialization as byte vector + + @complexity Linear in the size of the JSON value @a j. + + @liveexample{The example shows the serialization of a JSON value to a byte + vector in UBJSON format.,to_ubjson} + + @sa http://ubjson.org + @sa see @ref from_ubjson(InputType&&, const bool, const bool) for the + analogous deserialization + @sa see @ref to_cbor(const basic_json& for the related CBOR format + @sa see @ref to_msgpack(const basic_json&) for the related MessagePack format + + @since version 3.1.0 + */ + static std::vector to_ubjson(const basic_json& j, + const bool use_size = false, + const bool use_type = false) + { + std::vector result; + to_ubjson(j, result, use_size, use_type); + return result; + } + + static void to_ubjson(const basic_json& j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false) + { + binary_writer(o).write_ubjson(j, use_size, use_type); + } + + static void to_ubjson(const basic_json& j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false) + { + binary_writer(o).write_ubjson(j, use_size, use_type); + } + + + /*! + @brief Serializes the given JSON object `j` to BSON and returns a vector + containing the corresponding BSON-representation. + + BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are + stored as a single entity (a so-called document). + + The library uses the following mapping from JSON values types to BSON types: + + JSON value type | value/range | BSON type | marker + --------------- | --------------------------------- | ----------- | ------ + null | `null` | null | 0x0A + boolean | `true`, `false` | boolean | 0x08 + number_integer | -9223372036854775808..-2147483649 | int64 | 0x12 + number_integer | -2147483648..2147483647 | int32 | 0x10 + number_integer | 2147483648..9223372036854775807 | int64 | 0x12 + number_unsigned | 0..2147483647 | int32 | 0x10 + number_unsigned | 2147483648..9223372036854775807 | int64 | 0x12 + number_unsigned | 9223372036854775808..18446744073709551615| -- | -- + number_float | *any value* | double | 0x01 + string | *any value* | string | 0x02 + array | *any value* | document | 0x04 + object | *any value* | document | 0x03 + binary | *any value* | binary | 0x05 + + @warning The mapping is **incomplete**, since only JSON-objects (and things + contained therein) can be serialized to BSON. + Also, integers larger than 9223372036854775807 cannot be serialized to BSON, + and the keys may not contain U+0000, since they are serialized a + zero-terminated c-strings. + + @throw out_of_range.407 if `j.is_number_unsigned() && j.get() > 9223372036854775807` + @throw out_of_range.409 if a key in `j` contains a NULL (U+0000) + @throw type_error.317 if `!j.is_object()` + + @pre The input `j` is required to be an object: `j.is_object() == true`. + + @note Any BSON output created via @ref to_bson can be successfully parsed + by @ref from_bson. + + @param[in] j JSON value to serialize + @return BSON serialization as byte vector + + @complexity Linear in the size of the JSON value @a j. + + @liveexample{The example shows the serialization of a JSON value to a byte + vector in BSON format.,to_bson} + + @sa http://bsonspec.org/spec.html + @sa see @ref from_bson(detail::input_adapter&&, const bool strict) for the + analogous deserialization + @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the + related UBJSON format + @sa see @ref to_cbor(const basic_json&) for the related CBOR format + @sa see @ref to_msgpack(const basic_json&) for the related MessagePack format + */ + static std::vector to_bson(const basic_json& j) + { + std::vector result; + to_bson(j, result); + return result; + } + + /*! + @brief Serializes the given JSON object `j` to BSON and forwards the + corresponding BSON-representation to the given output_adapter `o`. + @param j The JSON object to convert to BSON. + @param o The output adapter that receives the binary BSON representation. + @pre The input `j` shall be an object: `j.is_object() == true` + @sa see @ref to_bson(const basic_json&) + */ + static void to_bson(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_bson(j); + } + + /*! + @copydoc to_bson(const basic_json&, detail::output_adapter) + */ + static void to_bson(const basic_json& j, detail::output_adapter o) + { + binary_writer(o).write_bson(j); + } + + + /*! + @brief create a JSON value from an input in CBOR format + + Deserializes a given input @a i to a JSON value using the CBOR (Concise + Binary Object Representation) serialization format. + + The library maps CBOR types to JSON value types as follows: + + CBOR type | JSON value type | first byte + ---------------------- | --------------- | ---------- + Integer | number_unsigned | 0x00..0x17 + Unsigned integer | number_unsigned | 0x18 + Unsigned integer | number_unsigned | 0x19 + Unsigned integer | number_unsigned | 0x1A + Unsigned integer | number_unsigned | 0x1B + Negative integer | number_integer | 0x20..0x37 + Negative integer | number_integer | 0x38 + Negative integer | number_integer | 0x39 + Negative integer | number_integer | 0x3A + Negative integer | number_integer | 0x3B + Byte string | binary | 0x40..0x57 + Byte string | binary | 0x58 + Byte string | binary | 0x59 + Byte string | binary | 0x5A + Byte string | binary | 0x5B + UTF-8 string | string | 0x60..0x77 + UTF-8 string | string | 0x78 + UTF-8 string | string | 0x79 + UTF-8 string | string | 0x7A + UTF-8 string | string | 0x7B + UTF-8 string | string | 0x7F + array | array | 0x80..0x97 + array | array | 0x98 + array | array | 0x99 + array | array | 0x9A + array | array | 0x9B + array | array | 0x9F + map | object | 0xA0..0xB7 + map | object | 0xB8 + map | object | 0xB9 + map | object | 0xBA + map | object | 0xBB + map | object | 0xBF + False | `false` | 0xF4 + True | `true` | 0xF5 + Null | `null` | 0xF6 + Half-Precision Float | number_float | 0xF9 + Single-Precision Float | number_float | 0xFA + Double-Precision Float | number_float | 0xFB + + @warning The mapping is **incomplete** in the sense that not all CBOR + types can be converted to a JSON value. The following CBOR types + are not supported and will yield parse errors (parse_error.112): + - date/time (0xC0..0xC1) + - bignum (0xC2..0xC3) + - decimal fraction (0xC4) + - bigfloat (0xC5) + - expected conversions (0xD5..0xD7) + - simple values (0xE0..0xF3, 0xF8) + - undefined (0xF7) + + @warning CBOR allows map keys of any type, whereas JSON only allows + strings as keys in object values. Therefore, CBOR maps with keys + other than UTF-8 strings are rejected (parse_error.113). + + @note Any CBOR output created @ref to_cbor can be successfully parsed by + @ref from_cbor. + + @param[in] i an input in CBOR format convertible to an input adapter + @param[in] strict whether to expect the input to be consumed until EOF + (true by default) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + @param[in] tag_handler how to treat CBOR tags (optional, error by default) + + @return deserialized JSON value; in case of a parse error and + @a allow_exceptions set to `false`, the return value will be + value_t::discarded. + + @throw parse_error.110 if the given input ends prematurely or the end of + file was not reached when @a strict was set to true + @throw parse_error.112 if unsupported features from CBOR were + used in the given input @a v or if the input is not valid CBOR + @throw parse_error.113 if a string was expected as map key, but not found + + @complexity Linear in the size of the input @a i. + + @liveexample{The example shows the deserialization of a byte vector in CBOR + format to a JSON value.,from_cbor} + + @sa http://cbor.io + @sa see @ref to_cbor(const basic_json&) for the analogous serialization + @sa see @ref from_msgpack(InputType&&, const bool, const bool) for the + related MessagePack format + @sa see @ref from_ubjson(InputType&&, const bool, const bool) for the + related UBJSON format + + @since version 2.0.9; parameter @a start_index since 2.1.1; changed to + consume input adapters, removed start_index parameter, and added + @a strict parameter since 3.0.0; added @a allow_exceptions parameter + since 3.2.0; added @a tag_handler parameter since 3.9.0. + */ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_cbor(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + return res ? result : basic_json(value_t::discarded); + } + + /*! + @copydoc from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) + */ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_cbor(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + return res ? result : basic_json(value_t::discarded); + } + + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) + static basic_json from_cbor(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); + } + + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) + static basic_json from_cbor(detail::span_input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + return res ? result : basic_json(value_t::discarded); + } + + /*! + @brief create a JSON value from an input in MessagePack format + + Deserializes a given input @a i to a JSON value using the MessagePack + serialization format. + + The library maps MessagePack types to JSON value types as follows: + + MessagePack type | JSON value type | first byte + ---------------- | --------------- | ---------- + positive fixint | number_unsigned | 0x00..0x7F + fixmap | object | 0x80..0x8F + fixarray | array | 0x90..0x9F + fixstr | string | 0xA0..0xBF + nil | `null` | 0xC0 + false | `false` | 0xC2 + true | `true` | 0xC3 + float 32 | number_float | 0xCA + float 64 | number_float | 0xCB + uint 8 | number_unsigned | 0xCC + uint 16 | number_unsigned | 0xCD + uint 32 | number_unsigned | 0xCE + uint 64 | number_unsigned | 0xCF + int 8 | number_integer | 0xD0 + int 16 | number_integer | 0xD1 + int 32 | number_integer | 0xD2 + int 64 | number_integer | 0xD3 + str 8 | string | 0xD9 + str 16 | string | 0xDA + str 32 | string | 0xDB + array 16 | array | 0xDC + array 32 | array | 0xDD + map 16 | object | 0xDE + map 32 | object | 0xDF + bin 8 | binary | 0xC4 + bin 16 | binary | 0xC5 + bin 32 | binary | 0xC6 + ext 8 | binary | 0xC7 + ext 16 | binary | 0xC8 + ext 32 | binary | 0xC9 + fixext 1 | binary | 0xD4 + fixext 2 | binary | 0xD5 + fixext 4 | binary | 0xD6 + fixext 8 | binary | 0xD7 + fixext 16 | binary | 0xD8 + negative fixint | number_integer | 0xE0-0xFF + + @note Any MessagePack output created @ref to_msgpack can be successfully + parsed by @ref from_msgpack. + + @param[in] i an input in MessagePack format convertible to an input + adapter + @param[in] strict whether to expect the input to be consumed until EOF + (true by default) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + + @return deserialized JSON value; in case of a parse error and + @a allow_exceptions set to `false`, the return value will be + value_t::discarded. + + @throw parse_error.110 if the given input ends prematurely or the end of + file was not reached when @a strict was set to true + @throw parse_error.112 if unsupported features from MessagePack were + used in the given input @a i or if the input is not valid MessagePack + @throw parse_error.113 if a string was expected as map key, but not found + + @complexity Linear in the size of the input @a i. + + @liveexample{The example shows the deserialization of a byte vector in + MessagePack format to a JSON value.,from_msgpack} + + @sa http://msgpack.org + @sa see @ref to_msgpack(const basic_json&) for the analogous serialization + @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the + related CBOR format + @sa see @ref from_ubjson(InputType&&, const bool, const bool) for + the related UBJSON format + @sa see @ref from_bson(InputType&&, const bool, const bool) for + the related BSON format + + @since version 2.0.9; parameter @a start_index since 2.1.1; changed to + consume input adapters, removed start_index parameter, and added + @a strict parameter since 3.0.0; added @a allow_exceptions parameter + since 3.2.0 + */ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_msgpack(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /*! + @copydoc from_msgpack(InputType&&, const bool, const bool) + */ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_msgpack(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) + static basic_json from_msgpack(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) + { + return from_msgpack(ptr, ptr + len, strict, allow_exceptions); + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) + static basic_json from_msgpack(detail::span_input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + + /*! + @brief create a JSON value from an input in UBJSON format + + Deserializes a given input @a i to a JSON value using the UBJSON (Universal + Binary JSON) serialization format. + + The library maps UBJSON types to JSON value types as follows: + + UBJSON type | JSON value type | marker + ----------- | --------------------------------------- | ------ + no-op | *no value, next value is read* | `N` + null | `null` | `Z` + false | `false` | `F` + true | `true` | `T` + float32 | number_float | `d` + float64 | number_float | `D` + uint8 | number_unsigned | `U` + int8 | number_integer | `i` + int16 | number_integer | `I` + int32 | number_integer | `l` + int64 | number_integer | `L` + high-precision number | number_integer, number_unsigned, or number_float - depends on number string | 'H' + string | string | `S` + char | string | `C` + array | array (optimized values are supported) | `[` + object | object (optimized values are supported) | `{` + + @note The mapping is **complete** in the sense that any UBJSON value can + be converted to a JSON value. + + @param[in] i an input in UBJSON format convertible to an input adapter + @param[in] strict whether to expect the input to be consumed until EOF + (true by default) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + + @return deserialized JSON value; in case of a parse error and + @a allow_exceptions set to `false`, the return value will be + value_t::discarded. + + @throw parse_error.110 if the given input ends prematurely or the end of + file was not reached when @a strict was set to true + @throw parse_error.112 if a parse error occurs + @throw parse_error.113 if a string could not be parsed successfully + + @complexity Linear in the size of the input @a i. + + @liveexample{The example shows the deserialization of a byte vector in + UBJSON format to a JSON value.,from_ubjson} + + @sa http://ubjson.org + @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the + analogous serialization + @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the + related CBOR format + @sa see @ref from_msgpack(InputType&&, const bool, const bool) for + the related MessagePack format + @sa see @ref from_bson(InputType&&, const bool, const bool) for + the related BSON format + + @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0 + */ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_ubjson(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /*! + @copydoc from_ubjson(InputType&&, const bool, const bool) + */ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_ubjson(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) + static basic_json from_ubjson(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) + { + return from_ubjson(ptr, ptr + len, strict, allow_exceptions); + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) + static basic_json from_ubjson(detail::span_input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + + /*! + @brief Create a JSON value from an input in BSON format + + Deserializes a given input @a i to a JSON value using the BSON (Binary JSON) + serialization format. + + The library maps BSON record types to JSON value types as follows: + + BSON type | BSON marker byte | JSON value type + --------------- | ---------------- | --------------------------- + double | 0x01 | number_float + string | 0x02 | string + document | 0x03 | object + array | 0x04 | array + binary | 0x05 | binary + undefined | 0x06 | still unsupported + ObjectId | 0x07 | still unsupported + boolean | 0x08 | boolean + UTC Date-Time | 0x09 | still unsupported + null | 0x0A | null + Regular Expr. | 0x0B | still unsupported + DB Pointer | 0x0C | still unsupported + JavaScript Code | 0x0D | still unsupported + Symbol | 0x0E | still unsupported + JavaScript Code | 0x0F | still unsupported + int32 | 0x10 | number_integer + Timestamp | 0x11 | still unsupported + 128-bit decimal float | 0x13 | still unsupported + Max Key | 0x7F | still unsupported + Min Key | 0xFF | still unsupported + + @warning The mapping is **incomplete**. The unsupported mappings + are indicated in the table above. + + @param[in] i an input in BSON format convertible to an input adapter + @param[in] strict whether to expect the input to be consumed until EOF + (true by default) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + + @return deserialized JSON value; in case of a parse error and + @a allow_exceptions set to `false`, the return value will be + value_t::discarded. + + @throw parse_error.114 if an unsupported BSON record type is encountered + + @complexity Linear in the size of the input @a i. + + @liveexample{The example shows the deserialization of a byte vector in + BSON format to a JSON value.,from_bson} + + @sa http://bsonspec.org/spec.html + @sa see @ref to_bson(const basic_json&) for the analogous serialization + @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the + related CBOR format + @sa see @ref from_msgpack(InputType&&, const bool, const bool) for + the related MessagePack format + @sa see @ref from_ubjson(InputType&&, const bool, const bool) for the + related UBJSON format + */ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_bson(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + /*! + @copydoc from_bson(InputType&&, const bool, const bool) + */ + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_bson(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) + static basic_json from_bson(const T* ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) + { + return from_bson(ptr, ptr + len, strict, allow_exceptions); + } + + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) + static basic_json from_bson(detail::span_input_adapter&& i, + const bool strict = true, + const bool allow_exceptions = true) + { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + /// @} + + ////////////////////////// + // JSON Pointer support // + ////////////////////////// + + /// @name JSON Pointer functions + /// @{ + + /*! + @brief access specified element via JSON Pointer + + Uses a JSON pointer to retrieve a reference to the respective JSON value. + No bound checking is performed. Similar to @ref operator[](const typename + object_t::key_type&), `null` values are created in arrays and objects if + necessary. + + In particular: + - If the JSON pointer points to an object key that does not exist, it + is created an filled with a `null` value before a reference to it + is returned. + - If the JSON pointer points to an array index that does not exist, it + is created an filled with a `null` value before a reference to it + is returned. All indices between the current maximum and the given + index are also filled with `null`. + - The special value `-` is treated as a synonym for the index past the + end. + + @param[in] ptr a JSON pointer + + @return reference to the element pointed to by @a ptr + + @complexity Constant. + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.404 if the JSON pointer can not be resolved + + @liveexample{The behavior is shown in the example.,operatorjson_pointer} + + @since version 2.0.0 + */ + reference operator[](const json_pointer& ptr) + { + return ptr.get_unchecked(this); + } + + /*! + @brief access specified element via JSON Pointer + + Uses a JSON pointer to retrieve a reference to the respective JSON value. + No bound checking is performed. The function does not change the JSON + value; no `null` values are created. In particular, the special value + `-` yields an exception. + + @param[in] ptr JSON pointer to the desired element + + @return const reference to the element pointed to by @a ptr + + @complexity Constant. + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + + @liveexample{The behavior is shown in the example.,operatorjson_pointer_const} + + @since version 2.0.0 + */ + const_reference operator[](const json_pointer& ptr) const + { + return ptr.get_unchecked(this); + } + + /*! + @brief access specified element via JSON Pointer + + Returns a reference to the element at with specified JSON pointer @a ptr, + with bounds checking. + + @param[in] ptr JSON pointer to the desired element + + @return reference to the element pointed to by @a ptr + + @throw parse_error.106 if an array index in the passed JSON pointer @a ptr + begins with '0'. See example below. + + @throw parse_error.109 if an array index in the passed JSON pointer @a ptr + is not a number. See example below. + + @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr + is out of range. See example below. + + @throw out_of_range.402 if the array index '-' is used in the passed JSON + pointer @a ptr. As `at` provides checked access (and no elements are + implicitly inserted), the index '-' is always invalid. See example below. + + @throw out_of_range.403 if the JSON pointer describes a key of an object + which cannot be found. See example below. + + @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. + See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. + + @since version 2.0.0 + + @liveexample{The behavior is shown in the example.,at_json_pointer} + */ + reference at(const json_pointer& ptr) + { + return ptr.get_checked(this); + } + + /*! + @brief access specified element via JSON Pointer + + Returns a const reference to the element at with specified JSON pointer @a + ptr, with bounds checking. + + @param[in] ptr JSON pointer to the desired element + + @return reference to the element pointed to by @a ptr + + @throw parse_error.106 if an array index in the passed JSON pointer @a ptr + begins with '0'. See example below. + + @throw parse_error.109 if an array index in the passed JSON pointer @a ptr + is not a number. See example below. + + @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr + is out of range. See example below. + + @throw out_of_range.402 if the array index '-' is used in the passed JSON + pointer @a ptr. As `at` provides checked access (and no elements are + implicitly inserted), the index '-' is always invalid. See example below. + + @throw out_of_range.403 if the JSON pointer describes a key of an object + which cannot be found. See example below. + + @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. + See example below. + + @exceptionsafety Strong guarantee: if an exception is thrown, there are no + changes in the JSON value. + + @complexity Constant. + + @since version 2.0.0 + + @liveexample{The behavior is shown in the example.,at_json_pointer_const} + */ + const_reference at(const json_pointer& ptr) const + { + return ptr.get_checked(this); + } + + /*! + @brief return flattened JSON value + + The function creates a JSON object whose keys are JSON pointers (see [RFC + 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all + primitive. The original JSON value can be restored using the @ref + unflatten() function. + + @return an object that maps JSON pointers to primitive values + + @note Empty objects and arrays are flattened to `null` and will not be + reconstructed correctly by the @ref unflatten() function. + + @complexity Linear in the size the JSON value. + + @liveexample{The following code shows how a JSON object is flattened to an + object whose keys consist of JSON pointers.,flatten} + + @sa see @ref unflatten() for the reverse function + + @since version 2.0.0 + */ + basic_json flatten() const + { + basic_json result(value_t::object); + json_pointer::flatten("", *this, result); + return result; + } + + /*! + @brief unflatten a previously flattened JSON value + + The function restores the arbitrary nesting of a JSON value that has been + flattened before using the @ref flatten() function. The JSON value must + meet certain constraints: + 1. The value must be an object. + 2. The keys must be JSON pointers (see + [RFC 6901](https://tools.ietf.org/html/rfc6901)) + 3. The mapped values must be primitive JSON types. + + @return the original JSON from a flattened version + + @note Empty objects and arrays are flattened by @ref flatten() to `null` + values and can not unflattened to their original type. Apart from + this example, for a JSON value `j`, the following is always true: + `j == j.flatten().unflatten()`. + + @complexity Linear in the size the JSON value. + + @throw type_error.314 if value is not an object + @throw type_error.315 if object values are not primitive + + @liveexample{The following code shows how a flattened JSON object is + unflattened into the original nested JSON object.,unflatten} + + @sa see @ref flatten() for the reverse function + + @since version 2.0.0 + */ + basic_json unflatten() const + { + return json_pointer::unflatten(*this); + } + + /// @} + + ////////////////////////// + // JSON Patch functions // + ////////////////////////// + + /// @name JSON Patch functions + /// @{ + + /*! + @brief applies a JSON patch + + [JSON Patch](http://jsonpatch.com) defines a JSON document structure for + expressing a sequence of operations to apply to a JSON) document. With + this function, a JSON Patch is applied to the current JSON value by + executing all operations from the patch. + + @param[in] json_patch JSON patch document + @return patched document + + @note The application of a patch is atomic: Either all operations succeed + and the patched document is returned or an exception is thrown. In + any case, the original value is not changed: the patch is applied + to a copy of the value. + + @throw parse_error.104 if the JSON patch does not consist of an array of + objects + + @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory + attributes are missing); example: `"operation add must have member path"` + + @throw out_of_range.401 if an array index is out of range. + + @throw out_of_range.403 if a JSON pointer inside the patch could not be + resolved successfully in the current JSON value; example: `"key baz not + found"` + + @throw out_of_range.405 if JSON pointer has no parent ("add", "remove", + "move") + + @throw other_error.501 if "test" operation was unsuccessful + + @complexity Linear in the size of the JSON value and the length of the + JSON patch. As usually only a fraction of the JSON value is affected by + the patch, the complexity can usually be neglected. + + @liveexample{The following code shows how a JSON patch is applied to a + value.,patch} + + @sa see @ref diff -- create a JSON patch by comparing two JSON values + + @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) + @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901) + + @since version 2.0.0 + */ + basic_json patch(const basic_json& json_patch) const + { + // make a working copy to apply the patch to + basic_json result = *this; + + // the valid JSON Patch operations + enum class patch_operations {add, remove, replace, move, copy, test, invalid}; + + const auto get_op = [](const std::string & op) + { + if (op == "add") + { + return patch_operations::add; + } + if (op == "remove") + { + return patch_operations::remove; + } + if (op == "replace") + { + return patch_operations::replace; + } + if (op == "move") + { + return patch_operations::move; + } + if (op == "copy") + { + return patch_operations::copy; + } + if (op == "test") + { + return patch_operations::test; + } + + return patch_operations::invalid; + }; + + // wrapper for "add" operation; add value at ptr + const auto operation_add = [&result](json_pointer & ptr, basic_json val) + { + // adding to the root of the target document means replacing it + if (ptr.empty()) + { + result = val; + return; + } + + // make sure the top element of the pointer exists + json_pointer top_pointer = ptr.top(); + if (top_pointer != ptr) + { + result.at(top_pointer); + } + + // get reference to parent of JSON pointer ptr + const auto last_path = ptr.back(); + ptr.pop_back(); + basic_json& parent = result[ptr]; + + switch (parent.m_type) + { + case value_t::null: + case value_t::object: + { + // use operator[] to add value + parent[last_path] = val; + break; + } + + case value_t::array: + { + if (last_path == "-") + { + // special case: append to back + parent.push_back(val); + } + else + { + const auto idx = json_pointer::array_index(last_path); + if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) + { + // avoid undefined behavior + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent)); + } + + // default case: insert add offset + parent.insert(parent.begin() + static_cast(idx), val); + } + break; + } + + // if there exists a parent it cannot be primitive + case value_t::string: // LCOV_EXCL_LINE + case value_t::boolean: // LCOV_EXCL_LINE + case value_t::number_integer: // LCOV_EXCL_LINE + case value_t::number_unsigned: // LCOV_EXCL_LINE + case value_t::number_float: // LCOV_EXCL_LINE + case value_t::binary: // LCOV_EXCL_LINE + case value_t::discarded: // LCOV_EXCL_LINE + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + } + }; + + // wrapper for "remove" operation; remove value at ptr + const auto operation_remove = [this, &result](json_pointer & ptr) + { + // get reference to parent of JSON pointer ptr + const auto last_path = ptr.back(); + ptr.pop_back(); + basic_json& parent = result.at(ptr); + + // remove child + if (parent.is_object()) + { + // perform range check + auto it = parent.find(last_path); + if (JSON_HEDLEY_LIKELY(it != parent.end())) + { + parent.erase(it); + } + else + { + JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this)); + } + } + else if (parent.is_array()) + { + // note erase performs range check + parent.erase(json_pointer::array_index(last_path)); + } + }; + + // type check: top level value must be an array + if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) + { + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch)); + } + + // iterate and apply the operations + for (const auto& val : json_patch) + { + // wrapper to get a value for an operation + const auto get_value = [&val](const std::string & op, + const std::string & member, + bool string_type) -> basic_json & + { + // find value + auto it = val.m_value.object->find(member); + + // context-sensitive error message + const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'"; + + // check if desired value is present + if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) + { + // NOLINTNEXTLINE(performance-inefficient-string-concatenation) + JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val)); + } + + // check if result is of type string + if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) + { + // NOLINTNEXTLINE(performance-inefficient-string-concatenation) + JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val)); + } + + // no error: return value + return it->second; + }; + + // type check: every element of the array must be an object + if (JSON_HEDLEY_UNLIKELY(!val.is_object())) + { + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val)); + } + + // collect mandatory members + const auto op = get_value("op", "op", true).template get(); + const auto path = get_value(op, "path", true).template get(); + json_pointer ptr(path); + + switch (get_op(op)) + { + case patch_operations::add: + { + operation_add(ptr, get_value("add", "value", false)); + break; + } + + case patch_operations::remove: + { + operation_remove(ptr); + break; + } + + case patch_operations::replace: + { + // the "path" location must exist - use at() + result.at(ptr) = get_value("replace", "value", false); + break; + } + + case patch_operations::move: + { + const auto from_path = get_value("move", "from", true).template get(); + json_pointer from_ptr(from_path); + + // the "from" location must exist - use at() + basic_json v = result.at(from_ptr); + + // The move operation is functionally identical to a + // "remove" operation on the "from" location, followed + // immediately by an "add" operation at the target + // location with the value that was just removed. + operation_remove(from_ptr); + operation_add(ptr, v); + break; + } + + case patch_operations::copy: + { + const auto from_path = get_value("copy", "from", true).template get(); + const json_pointer from_ptr(from_path); + + // the "from" location must exist - use at() + basic_json v = result.at(from_ptr); + + // The copy is functionally identical to an "add" + // operation at the target location using the value + // specified in the "from" member. + operation_add(ptr, v); + break; + } + + case patch_operations::test: + { + bool success = false; + JSON_TRY + { + // check if "value" matches the one at "path" + // the "path" location must exist - use at() + success = (result.at(ptr) == get_value("test", "value", false)); + } + JSON_INTERNAL_CATCH (out_of_range&) + { + // ignore out of range errors: success remains false + } + + // throw an exception if test fails + if (JSON_HEDLEY_UNLIKELY(!success)) + { + JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val)); + } + + break; + } + + case patch_operations::invalid: + default: + { + // op must be "add", "remove", "replace", "move", "copy", or + // "test" + JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val)); + } + } + } + + return result; + } + + /*! + @brief creates a diff as a JSON patch + + Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can + be changed into the value @a target by calling @ref patch function. + + @invariant For two JSON values @a source and @a target, the following code + yields always `true`: + @code {.cpp} + source.patch(diff(source, target)) == target; + @endcode + + @note Currently, only `remove`, `add`, and `replace` operations are + generated. + + @param[in] source JSON value to compare from + @param[in] target JSON value to compare against + @param[in] path helper value to create JSON pointers + + @return a JSON patch to convert the @a source to @a target + + @complexity Linear in the lengths of @a source and @a target. + + @liveexample{The following code shows how a JSON patch is created as a + diff for two JSON values.,diff} + + @sa see @ref patch -- apply a JSON patch + @sa see @ref merge_patch -- apply a JSON Merge Patch + + @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) + + @since version 2.0.0 + */ + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json diff(const basic_json& source, const basic_json& target, + const std::string& path = "") + { + // the patch + basic_json result(value_t::array); + + // if the values are the same, return empty patch + if (source == target) + { + return result; + } + + if (source.type() != target.type()) + { + // different types: replace value + result.push_back( + { + {"op", "replace"}, {"path", path}, {"value", target} + }); + return result; + } + + switch (source.type()) + { + case value_t::array: + { + // first pass: traverse common elements + std::size_t i = 0; + while (i < source.size() && i < target.size()) + { + // recursive call to compare array values at index i + auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); + result.insert(result.end(), temp_diff.begin(), temp_diff.end()); + ++i; + } + + // i now reached the end of at least one array + // in a second pass, traverse the remaining elements + + // remove my remaining elements + const auto end_index = static_cast(result.size()); + while (i < source.size()) + { + // add operations in reverse order to avoid invalid + // indices + result.insert(result.begin() + end_index, object( + { + {"op", "remove"}, + {"path", path + "/" + std::to_string(i)} + })); + ++i; + } + + // add other remaining elements + while (i < target.size()) + { + result.push_back( + { + {"op", "add"}, + {"path", path + "/-"}, + {"value", target[i]} + }); + ++i; + } + + break; + } + + case value_t::object: + { + // first pass: traverse this object's elements + for (auto it = source.cbegin(); it != source.cend(); ++it) + { + // escape the key name to be used in a JSON patch + const auto path_key = path + "/" + detail::escape(it.key()); + + if (target.find(it.key()) != target.end()) + { + // recursive call to compare object values at key it + auto temp_diff = diff(it.value(), target[it.key()], path_key); + result.insert(result.end(), temp_diff.begin(), temp_diff.end()); + } + else + { + // found a key that is not in o -> remove it + result.push_back(object( + { + {"op", "remove"}, {"path", path_key} + })); + } + } + + // second pass: traverse other object's elements + for (auto it = target.cbegin(); it != target.cend(); ++it) + { + if (source.find(it.key()) == source.end()) + { + // found a key that is not in this -> add it + const auto path_key = path + "/" + detail::escape(it.key()); + result.push_back( + { + {"op", "add"}, {"path", path_key}, + {"value", it.value()} + }); + } + } + + break; + } + + case value_t::null: + case value_t::string: + case value_t::boolean: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + case value_t::binary: + case value_t::discarded: + default: + { + // both primitive type: replace value + result.push_back( + { + {"op", "replace"}, {"path", path}, {"value", target} + }); + break; + } + } + + return result; + } + + /// @} + + //////////////////////////////// + // JSON Merge Patch functions // + //////////////////////////////// + + /// @name JSON Merge Patch functions + /// @{ + + /*! + @brief applies a JSON Merge Patch + + The merge patch format is primarily intended for use with the HTTP PATCH + method as a means of describing a set of modifications to a target + resource's content. This function applies a merge patch to the current + JSON value. + + The function implements the following algorithm from Section 2 of + [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396): + + ``` + define MergePatch(Target, Patch): + if Patch is an Object: + if Target is not an Object: + Target = {} // Ignore the contents and set it to an empty Object + for each Name/Value pair in Patch: + if Value is null: + if Name exists in Target: + remove the Name/Value pair from Target + else: + Target[Name] = MergePatch(Target[Name], Value) + return Target + else: + return Patch + ``` + + Thereby, `Target` is the current object; that is, the patch is applied to + the current value. + + @param[in] apply_patch the patch to apply + + @complexity Linear in the lengths of @a patch. + + @liveexample{The following code shows how a JSON Merge Patch is applied to + a JSON document.,merge_patch} + + @sa see @ref patch -- apply a JSON patch + @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396) + + @since version 3.0.0 + */ + void merge_patch(const basic_json& apply_patch) + { + if (apply_patch.is_object()) + { + if (!is_object()) + { + *this = object(); + } + for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) + { + if (it.value().is_null()) + { + erase(it.key()); + } + else + { + operator[](it.key()).merge_patch(it.value()); + } + } + } + else + { + *this = apply_patch; + } + } + + /// @} +}; + +/*! +@brief user-defined to_string function for JSON values + +This function implements a user-defined to_string for JSON objects. + +@param[in] j a JSON object +@return a std::string object +*/ + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) +{ + return j.dump(); +} +} // namespace nlohmann + +/////////////////////// +// nonmember support // +/////////////////////// + +// specialization of std::swap, and std::hash +namespace std +{ + +/// hash value for JSON objects +template<> +struct hash +{ + /*! + @brief return a hash value for a JSON object + + @since version 1.0.0 + */ + std::size_t operator()(const nlohmann::json& j) const + { + return nlohmann::detail::hash(j); + } +}; + +/// specialization for std::less +/// @note: do not remove the space after '<', +/// see https://github.com/nlohmann/json/pull/679 +template<> +struct less<::nlohmann::detail::value_t> +{ + /*! + @brief compare two value_t enum values + @since version 3.0.0 + */ + bool operator()(nlohmann::detail::value_t lhs, + nlohmann::detail::value_t rhs) const noexcept + { + return nlohmann::detail::operator<(lhs, rhs); + } +}; + +// C++20 prohibit function specialization in the std namespace. +#ifndef JSON_HAS_CPP_20 + +/*! +@brief exchanges the values of two JSON objects + +@since version 1.0.0 +*/ +template<> +inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name) + is_nothrow_move_constructible::value&& // NOLINT(misc-redundant-expression) + is_nothrow_move_assignable::value + ) +{ + j1.swap(j2); +} + +#endif + +} // namespace std + +/*! +@brief user-defined string literal for JSON values + +This operator implements a user-defined string literal for JSON objects. It +can be used by adding `"_json"` to a string literal and returns a JSON object +if no parse error occurred. + +@param[in] s a string representation of a JSON object +@param[in] n the length of string @a s +@return a JSON object + +@since version 1.0.0 +*/ +JSON_HEDLEY_NON_NULL(1) +inline nlohmann::json operator "" _json(const char* s, std::size_t n) +{ + return nlohmann::json::parse(s, s + n); +} + +/*! +@brief user-defined string literal for JSON pointer + +This operator implements a user-defined string literal for JSON Pointers. It +can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer +object if no parse error occurred. + +@param[in] s a string representation of a JSON Pointer +@param[in] n the length of string @a s +@return a JSON pointer object + +@since version 2.0.0 +*/ +JSON_HEDLEY_NON_NULL(1) +inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) +{ + return nlohmann::json::json_pointer(std::string(s, n)); +} + +// #include + + +// restore clang diagnostic settings +#if defined(__clang__) + #pragma clang diagnostic pop +#endif + +// clean up +#undef JSON_ASSERT +#undef JSON_INTERNAL_CATCH +#undef JSON_CATCH +#undef JSON_THROW +#undef JSON_TRY +#undef JSON_PRIVATE_UNLESS_TESTED +#undef JSON_HAS_CPP_11 +#undef JSON_HAS_CPP_14 +#undef JSON_HAS_CPP_17 +#undef JSON_HAS_CPP_20 +#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION +#undef NLOHMANN_BASIC_JSON_TPL +#undef JSON_EXPLICIT +#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL + +// #include + + +#undef JSON_HEDLEY_ALWAYS_INLINE +#undef JSON_HEDLEY_ARM_VERSION +#undef JSON_HEDLEY_ARM_VERSION_CHECK +#undef JSON_HEDLEY_ARRAY_PARAM +#undef JSON_HEDLEY_ASSUME +#undef JSON_HEDLEY_BEGIN_C_DECLS +#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#undef JSON_HEDLEY_CLANG_HAS_FEATURE +#undef JSON_HEDLEY_CLANG_HAS_WARNING +#undef JSON_HEDLEY_COMPCERT_VERSION +#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#undef JSON_HEDLEY_CONCAT +#undef JSON_HEDLEY_CONCAT3 +#undef JSON_HEDLEY_CONCAT3_EX +#undef JSON_HEDLEY_CONCAT_EX +#undef JSON_HEDLEY_CONST +#undef JSON_HEDLEY_CONSTEXPR +#undef JSON_HEDLEY_CONST_CAST +#undef JSON_HEDLEY_CPP_CAST +#undef JSON_HEDLEY_CRAY_VERSION +#undef JSON_HEDLEY_CRAY_VERSION_CHECK +#undef JSON_HEDLEY_C_DECL +#undef JSON_HEDLEY_DEPRECATED +#undef JSON_HEDLEY_DEPRECATED_FOR +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#undef JSON_HEDLEY_DIAGNOSTIC_POP +#undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#undef JSON_HEDLEY_DMC_VERSION +#undef JSON_HEDLEY_DMC_VERSION_CHECK +#undef JSON_HEDLEY_EMPTY_BASES +#undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#undef JSON_HEDLEY_END_C_DECLS +#undef JSON_HEDLEY_FLAGS +#undef JSON_HEDLEY_FLAGS_CAST +#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#undef JSON_HEDLEY_GCC_HAS_BUILTIN +#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_GCC_HAS_EXTENSION +#undef JSON_HEDLEY_GCC_HAS_FEATURE +#undef JSON_HEDLEY_GCC_HAS_WARNING +#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#undef JSON_HEDLEY_GCC_VERSION +#undef JSON_HEDLEY_GCC_VERSION_CHECK +#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#undef JSON_HEDLEY_GNUC_HAS_FEATURE +#undef JSON_HEDLEY_GNUC_HAS_WARNING +#undef JSON_HEDLEY_GNUC_VERSION +#undef JSON_HEDLEY_GNUC_VERSION_CHECK +#undef JSON_HEDLEY_HAS_ATTRIBUTE +#undef JSON_HEDLEY_HAS_BUILTIN +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_HAS_EXTENSION +#undef JSON_HEDLEY_HAS_FEATURE +#undef JSON_HEDLEY_HAS_WARNING +#undef JSON_HEDLEY_IAR_VERSION +#undef JSON_HEDLEY_IAR_VERSION_CHECK +#undef JSON_HEDLEY_IBM_VERSION +#undef JSON_HEDLEY_IBM_VERSION_CHECK +#undef JSON_HEDLEY_IMPORT +#undef JSON_HEDLEY_INLINE +#undef JSON_HEDLEY_INTEL_CL_VERSION +#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#undef JSON_HEDLEY_INTEL_VERSION +#undef JSON_HEDLEY_INTEL_VERSION_CHECK +#undef JSON_HEDLEY_IS_CONSTANT +#undef JSON_HEDLEY_IS_CONSTEXPR_ +#undef JSON_HEDLEY_LIKELY +#undef JSON_HEDLEY_MALLOC +#undef JSON_HEDLEY_MCST_LCC_VERSION +#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#undef JSON_HEDLEY_MESSAGE +#undef JSON_HEDLEY_MSVC_VERSION +#undef JSON_HEDLEY_MSVC_VERSION_CHECK +#undef JSON_HEDLEY_NEVER_INLINE +#undef JSON_HEDLEY_NON_NULL +#undef JSON_HEDLEY_NO_ESCAPE +#undef JSON_HEDLEY_NO_RETURN +#undef JSON_HEDLEY_NO_THROW +#undef JSON_HEDLEY_NULL +#undef JSON_HEDLEY_PELLES_VERSION +#undef JSON_HEDLEY_PELLES_VERSION_CHECK +#undef JSON_HEDLEY_PGI_VERSION +#undef JSON_HEDLEY_PGI_VERSION_CHECK +#undef JSON_HEDLEY_PREDICT +#undef JSON_HEDLEY_PRINTF_FORMAT +#undef JSON_HEDLEY_PRIVATE +#undef JSON_HEDLEY_PUBLIC +#undef JSON_HEDLEY_PURE +#undef JSON_HEDLEY_REINTERPRET_CAST +#undef JSON_HEDLEY_REQUIRE +#undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#undef JSON_HEDLEY_REQUIRE_MSG +#undef JSON_HEDLEY_RESTRICT +#undef JSON_HEDLEY_RETURNS_NON_NULL +#undef JSON_HEDLEY_SENTINEL +#undef JSON_HEDLEY_STATIC_ASSERT +#undef JSON_HEDLEY_STATIC_CAST +#undef JSON_HEDLEY_STRINGIFY +#undef JSON_HEDLEY_STRINGIFY_EX +#undef JSON_HEDLEY_SUNPRO_VERSION +#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#undef JSON_HEDLEY_TINYC_VERSION +#undef JSON_HEDLEY_TINYC_VERSION_CHECK +#undef JSON_HEDLEY_TI_ARMCL_VERSION +#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL2000_VERSION +#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL430_VERSION +#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL6X_VERSION +#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL7X_VERSION +#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#undef JSON_HEDLEY_TI_CLPRU_VERSION +#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#undef JSON_HEDLEY_TI_VERSION +#undef JSON_HEDLEY_TI_VERSION_CHECK +#undef JSON_HEDLEY_UNAVAILABLE +#undef JSON_HEDLEY_UNLIKELY +#undef JSON_HEDLEY_UNPREDICTABLE +#undef JSON_HEDLEY_UNREACHABLE +#undef JSON_HEDLEY_UNREACHABLE_RETURN +#undef JSON_HEDLEY_VERSION +#undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#undef JSON_HEDLEY_VERSION_DECODE_MINOR +#undef JSON_HEDLEY_VERSION_DECODE_REVISION +#undef JSON_HEDLEY_VERSION_ENCODE +#undef JSON_HEDLEY_WARNING +#undef JSON_HEDLEY_WARN_UNUSED_RESULT +#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#undef JSON_HEDLEY_FALL_THROUGH + + + +#endif // INCLUDE_NLOHMANN_JSON_HPP_ diff --git a/libs/qcustomplot-source/CMakeLists.txt b/libs/qcustomplot-source/CMakeLists.txt index c60eecce0..b6228cf9c 100644 --- a/libs/qcustomplot-source/CMakeLists.txt +++ b/libs/qcustomplot-source/CMakeLists.txt @@ -1,33 +1,21 @@ -cmake_minimum_required(VERSION 2.8.7) +cmake_minimum_required(VERSION 3.16) -if(USE_QT5) - set(CMAKE_AUTOMOC ON) - set(CMAKE_INCLUDE_CURRENT_DIR ON) - find_package(Qt5Widgets REQUIRED) -else() - find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) - include("${QT_USE_FILE}") - add_definitions(${QT_DEFINITIONS}) -endif() +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(QCUSTOMPLOT_SRC - qcustomplot.cpp -) +find_package(${QT_MAJOR} REQUIRED COMPONENTS Widgets PrintSupport) -set(QCUSTOMPLOT_HDR +set(QCUSTOMPLOT_SRC + qcustomplot.cpp ) set(QCUSTOMPLOT_MOC_HDR - qcustomplot.h + qcustomplot.h ) -if(NOT USE_QT5) - QT4_WRAP_CPP(QCUSTOMPLOT_MOC ${QCUSTOMPLOT_MOC_HDR}) -endif() - -add_library(qcustomplot ${QCUSTOMPLOT_SRC} ${QCUSTOMPLOT_HDR} ${QCUSTOMPLOT_MOC}) +add_library(qcustomplot ${QCUSTOMPLOT_SRC} ${QCUSTOMPLOT_MOC_HDR} ${QCUSTOMPLOT_MOC}) -if(USE_QT5) - qt5_use_modules(qcustomplot Widgets PrintSupport) -endif() +target_include_directories(qcustomplot INTERFACE ${CMAKE_CURRENT_LIST_DIR}) +target_link_libraries(qcustomplot ${QT_MAJOR}::Widgets ${QT_MAJOR}::PrintSupport) +add_library(QCustomPlot::QCustomPlot ALIAS qcustomplot) diff --git a/libs/qcustomplot-source/GPL.txt b/libs/qcustomplot-source/GPL.txt old mode 100644 new mode 100755 diff --git a/libs/qcustomplot-source/changelog.txt b/libs/qcustomplot-source/changelog.txt old mode 100644 new mode 100755 index 7acf22a6a..de330e754 --- a/libs/qcustomplot-source/changelog.txt +++ b/libs/qcustomplot-source/changelog.txt @@ -1,3 +1,216 @@ +#### Version 2.1.1 released on 06.11.22 #### + +Added features: + - Qt6.4 Compatibility + +Bugfixes: + - dynamically changing device pixel ratios (e.g. when moving between different DPI screens) is handled properly + - bugfix Colormap autoscaling: recalculateDataBounds() if (0, 0) data point is NaN. + - minor bugfix in getMantissa for certain values due to rounding errors + - Graphs with line style lsImpulse properly ignore NaN data points + - fixed issue where QCP wasn't greyed out together with the rest of the UI on embedded systems when a modal dialog is shown + (QCustomPlot no longer has the Qt::WA_OpaquePaintEvent attribute enabled by default) + +Other: + - in QCPAxisPainterPrivate::getTickLabelData, don't use fixed 'e', but locale aware character of parent plot locale + - Axis rescaling now ignores +/- Inf in data values + - slight performance improvements of QCPColorMap colorization and fills. + +#### Version 2.1.0 released on 29.03.21 #### + +Added features: + - Compatibility up to Qt 6.0 + - Tech Preview: Radial Plots (see setupPolarPlotDemo in examples project) + - QCPAxisTickerDateTime can now be configured with a QTimeZone for adjusting the label display to arbitrary time zones + - QCPColorGradient (and thus also QCPColorMap) now has explicit configurable NaN handling (see QCPColorGradient::setNanHandling) + - added timing/benchmarking method QCustomPlot::replotTime(bool average) which returns the milliseconds per replot + - QCustomPlot::plottableAt has an optional output parameter dataIndex, providing the index of the data point at the probed position + - QCustomPlot::plottableAt template method allows limiting the search to the specified QCPAbstractPlottable subclass T + - QCustomPlot::itemAt template method allows limiting the search to the specified QCPAbstractItem subclass T + - Added Interaction flag QCP::iSelectPlottablesBeyondAxisRect, allows selection of data points very close to (and beyond of) the axes + - QCPAxisTickerDateTime::dateTimeToKey(QDate &) now also takes a TimeSpec to specify the interpretation of the start-of-day + - QCPAxisTickerLog now switches to linear ticks if zoomed in beyond where logarithmic ticks are reasonable + - Added QCustomPlot::afterLayout signal, for user code that crucially depends on layout sizes/positions, right before the draw step during a replot + +Bugfixes: + - Fixed bug where QCPLayer::replot wouldn't issue full replot even though invalidated buffers existed + - Fixed QCPCurve bug causing rendering artifacts when using keys/values smaller than about 1e-12 in some constellations + - Fixed getValueRange when used with explicit keyRange, now doesn't use key range expanded by one point to each side anymore + - Fixed bug of QCPAxis tick label font size change only propagating to the layout after second call to replot + - Fixed bug of QCPTextElement not respecting the configured text alignment flag (setTextFlags) + - Various documentation typos and improvements + +Other: + - QCP Now requires C++11. However, Qt4.6 compatibility is maintained in the QCP 2.x release series + - QCPColorScale is now initialized with gpCold gradient preset, which prevents color maps turning black when linking them to a default-created color scale without explicitly setting a gradient + - QCPLegend::clearItems is now faster in case of many legend items (>1000) + - Modernized expressions and thereby avoided some warnings (e.g. nullptr and casts) + - Switched to foreach (Qt macro) where possible (in preparation for switch to range-based for (C++11), soonest at next major release) + - Work around Qt bug, drawing lines with pen width 1 as slow as with pen widths > 1 (polyfill instead of line algorithm, also on Normal-DPI), by using pen width 0 in such cases. + - Added QCP::Interaction flag iNone=0x000 to allow explicitly specifying no interaction (Avoids QFlags::zero, which was deprecated in Qt5.14) + - QCP is now compatible with defines QT_USE_QSTRINGBUILDER, QT_USE_FAST_CONCATENATION (Qt<4.8), QT_USE_FAST_OPERATOR_PLUS (Qt<4.8) + +#### Version 2.0.1 released on 25.06.18 #### + +Bugfixes: + - Default filling order of QCPLayoutGrid is now foColumnsFirst instead of foRowsFirst, as intended and consistent with QCP1. + Note that this also changes the indexing order of e.g. QCustomPlot::axisRect(int index), compared with 2.0.0. You can change + the filling and thus indexing order yourself by calling QCPLayoutGrid::setFillOrder. + - fixed bug in QCPColorMap, when using alpha in the gradient color stops. Used to draw falsely black data points when the associated data value is exactly + on the first or last color stop. + - QCPDataSelection::enforceType(stDataRange) would erroneously add an empty data range to the selection, if the selection was already empty. + This in turn would cause isEmpty() to erroneously return false. + - fixed hypothetical crash when selectTest is called on a QCPItemCurve which has all of its points at the same position + +Other: + - Various documentation improvements and clarifications + - Prevent conflict with windows.h min/max macros if user forgets to define NOMINMAX + - compiling QCP shared libraries with static Qt is now easier + - added defines QCUSTOMPLOT_VERSION and QCUSTOMPLOT_VERSION_STR (the same way Qt does) to provide the used QCP version number + - added missing Q_DECL_OVERRIDE declarations, thus preventing warnings some compiler settings + - QCPAxisTicker and subclasses are no longer copyable by value, as intended + - QCPBarsGroup constructor is now explicit, as intended + - Qt 5.11 compatibility + +#### Version 2.0.0 released on 04.09.17 #### + +Added major features: + - Axis tick and tick label generation was completely refactored and is now handled in the QCPAxisTicker class (also see QCPAxis::setTicker). Available ticker subclasses for special uses cases: + QCPAxisTicker, QCPAxisTickerFixed, QCPAxisTickerLog, QCPAxisTickerPi, QCPAxisTickerTime, QCPAxisTickerDateTime, QCPAxisTickerText + - Data container is now based on QCPDataContainer template for unified data interface and significantly improved memory footprint and better performance for common use-cases, especially data adding/removing. + - New data selection mechanism allows selection of single data points and data ranges for plottables. See special documentation page "data selection mechanism". + - Rubber band/selection rect for data point selection and axis zooming is now available, see documentation of QCustomPlot::setSelectionRectMode and QCPSelectionRect. For this purpose, the new default + layer "overlay" was introduced, which is now the top layer, and holds the QCustomPlot's QCPSelectionRect instance. + - Data sharing between plottables of the same type (see setData methods taking a QSharedPointer) + - OpenGL hardware acceleration is now available across all Qt versions (including Qt4) in a unified, simple interface, with QCustomPlot::setOpenGl (experimental) + - QCPStatisticalBox can now display a series of statistical boxes instead of only a single one + - New QCPErrorBars plottable allows attaching error bars to any one-dimensional plottable (QCPGraph has thus lost its own error-bar capability) + - QCPColorMap now supports transparency via alpha in its color gradient stops, and via a dedicated cell-wise alpha map (see QCPColorMapData::setAlpha) + - Layers may now be individually replotted (QCPLayer::replot), if the mode (QCPLayer::setMode) is set to lmBuffered. Mutually adjacent lmLogical layers share a single paint buffer to save resources. + By default, the new topmost "overlay" layer which contains the selection rect is an lmBuffered layer. Updating the selection rect is thus very fast, independent of the plot contents. + - QCPLayerable (and thus practically all objects in QCP) now have virtual methods to receive mouse press/move/release/doubleclick/wheel events. Before, only QCPLayoutElement provided them. + this makes it much easier to subclass e.g. items and plottables to provide custom mouse interactions that were cumbersome and awkward with the simpler signal-based interface + +Added minor features: + - High-DPI support for Qt versions 5.0 and up, using device pixel ratio detected by Qt (can be changed manually via QCustomPlot::setBufferDevicePixelRatio). + - QCPGraph and QCPCurve can now be configured to only display every n'th scatter symbol, see ::setScatterSkip() method + - QCPFinancial allows to define bar width in absolute pixels and axis rect ratio, instead of only in plot key coordinates (see QCPFinancial::setWidthType) + - Range dragging/zooming can now be configured to affect more than one axis per orientation (see new overloads of QCPAxisRect::setRangeDragAxes/setRangeZoomAxes) + - Added QCPTextElement (replaces QCPPlotTitle) for general texts in layouts. Provides clicked and doubleClicked signals, as replacement for the removed QCustomPlot::titleClicked/titleDoubleClicked + - Export functions (QCustomPlot::savePng etc.) now support specifying the resolution that will be written to the image file header. This improves operability with other tools which respect metadata. + - Replots can now be queued to the next event loop iteration with replot(QCP::rpQueuedReplot). This way you can successively ask for a replot at multiple code locations without causing redundant replots + - QCPAxisRect::zoom(...) allows to zoom to a specific rectangular region given in pixel coordinates, either affecting all axes or a specified subset of axes. + - QCPRange::bounded returns a bounded range, trying to preserve its size. Works with rangeChanged signal to limit the allowed range (see rangeChanged doc) + - Plottable rescaleValueAxis method (and getValueRange) now take parameter inKeyRange, which allows rescaling of the value axis only with respect to data in the currently visible key range + - plottableClick and plottableDoubleClick signals now carry the clicked data point index as second parameter + - Added QCPAxis::scaleRange overload without "center" argument, which scales around the current axis range center + - Added QCPRange::expand/expanded overloads which take only one double parameter + - Plottables addToLegend/removeFromLegend methods now have overloads that take any QCPLegend, to make working with non-default legends easier (legends that are not QCustomPlot::legend) + - Added QCPStatisticalBox::setWhiskerAntialiased to allow controlling antialiasing state of whiskers independently of quartile box/median line + - The virtual method QCPLayoutElement::layoutChanged() now allows subclasses to react on a move of the layout element between logical positions in the parent layout, or between layouts + - QCPMarginGroup::commonMargin is now virtual, to facilitate subclassing of QCPMarginGroup + - QCPGraph::getPreparedData is now virtual, and thus allows subclasses to easily generate own plotted data, e.g. on-the-fly. + - Added QCPRange qDebug stream operator + - QCPLayoutGrid (and thus QCPLegend) can now wrap rows or columns at specified row/column counts, see setFillOrder, setWrap and the new addElement overload which doesn't have row/column index +Added minor features after beta: + - QCPGraph fill now renders separate fill segments when there are gaps in the graph data (created by inserting NaN values) + - fractional device pixel ratios are now used, if Qt version >= 5.6 + - Axes may now be dragged/zoomed individually by starting the drag/zoom on top of the axis (previously, this required additional code) + - Manual minimum and maximum layout element sizes (setMinimumSize/setMaximumSize) can now affect the inner or the outer rect, see QCPLayoutElement::setSizeConstraintRect + +Bugfixes [Also backported to 1.3.2]: + - Fixed possible crash when having a QCPGraph with scatters only and a non-transparent main/fill brush of the graph + - Fixed QCPItemPixmap not updating internally cached scaled pixmap if new pixmap set with same scaled dimensions + - When using log axis scale and zooming out as far as possible (~1e-280..1e280), axis doesn't end up in (via mouse) unrecoverable range with strange axis ticks anymore + - Axis tick label algorithm for beautifully typeset powers now checks whether "e" in tick label is actually part of a number before converting the exponent to superscript + - Fixed QCustomPlot::moveLayer performing incorrect move and possible crash in certain situations + - Fixed possible crash on QCustomPlot destruction due to wrong QObject-hierarchy. Only occurs if a QCPAxisRect is removed from the normal QCustomPlot destruction hierarchy by taking it out of its layout + - Fixed possible freeze when data values become infinity after coord-to-pixel transformation (e.g. maximally zoomed out log axis), and line style is not solid (e.g. dashed) or phFastPolylines is disabled + - Fixed a few missing enums in meta type system, by unifying usage of Q_ENUMS, Q_FLAGS and Q_DECLARE_METATYPE +Bugfixes [Not in 1.3.2]: + - Fixed QCPItemLine/QCPItemStraightLine not being selectable when defining coords are many orders of magnitude (>1e8) larger than currently viewed range + - Fixed/worked around crash due to bug in QPainter::drawPixmap with very large negative x/y pixel coordinates, when drawing sparse pixmap scatters + - Fixed possible (but unlikely) int overflow in adaptive sampling algorithm, that could cause plot artifacts when using extremely sparse data (with respect to current key axis range). + - Fixed QCPBarsGroup bug which caused stPlotCoords spacing to be wrong with vertical key axes + - A QCPBars axis rescale in the main window constructor (i.e. without well-defined plot size) now falls back to a datapoint-tight rescaling instead of doing nothing (because bar width can't be determined) + - Improved QCPBars stacking when using bars with very large keys and key separation at limit of double precision +Bugfixes after beta: + - fixed QCPCurve vertex optimization algorithm not handling log axes correctly + - upon removing the inner most axis, the offset of the new inner most axis (previously second axis) is now set to the value of the removed axis, instead of leaving a gap + - QCPColorMap now has a default gradient (gpCold) again, instead of an empty and thus black gradient + - doc: black QCPColorMap/QCPColorGradient documentation images fixed + - scatter styles ssDiamond, ssTriangle and ssTriangleInverted now get proper filling with the specified brush + - fixed click signals of plottable/axes/etc. not being emitted properly + - fixed uninitialized scatterSkip on QCPCurve, leading to irregular default appearance of scatter skips + - fixed device pixel ratio not being implemented correctly in cached tick labels + - QCPLayoutElement::setMaximum/setMinimum now is with respect to the inner rect as intended (and documented), instead of the outer rect (and this can now be changed via setSizeConstraintRect) + - fixed dllimport issue on template classes when compiling as shared library with MSVC + + +Summary of backward incompatible changes: + Plottable related: + - Removed QCustomPlot::addPlottable, not needed anymore as plottables now automatically register in their constructor + - Removed QCustomPlot::addItem, not needed anymore as items now automatically register in their constructor + - QCPAbstractPlottable::addToLegend/removeFromLegend are not virtual anymore. If your plottable requires a custom legend item, add it to the legend manually. + - setData/addData method overloads of plottables have changed to facilitate data sharing and new data container (see documentation) + - plottableClick and plottableDoubleClick signals now carry the clicked data point index as second parameter, and the QMouseEvent parameter has moved to third. + Check all your usages of those signals, because Qt's connect method only reports problems during runtime! + - setSelectable now not only limits what can be selected by the user, but limits also any programmatic selection changes via setSelected. + - enum QCPAbstractPlottable::SignDomain has changed namespace to QCP::SignDomain + Axis related: + - Removed QCPAxis::setAutoTicks, setAutoTickCount, setAutoTickLabels, setAutoTickStep, setAutoSubTicks, setTickLabelType, setDateTimeFormat, setDateTimeSpec, + setTickStep, setTickVector, setTickVectorLabels, setSubTickCount in favor of new QCPAxisTicker-based interface + - Added QCPAxis::setSubTicks to enable/disable subticks (manually controlling the subtick count needs subclassing of QCPAxisTicker, e.g. QCPAxisTickerText and QCPAxisTickerLog provide setSubTickCount) + Item related: + - Renamed QCPAbstractItem::rectSelectTest to rectDistance, to prevent confusion with new QCPAbstractPlottable1D::selectTestRect + - Renamed QCPItemAnchor::pixelPoint to QCPItemAnchor::pixelPosition (also affects subclass QCPItemPosition) + General: + - Renamed QCustomPlot::RefreshPriority enums (parameter of the replot() method): rpImmediate to rpImmediateRefresh, rpQueued to rpQueuedRefresh, rpHint to rpRefreshHint + - Renamed QCustomPlot::PlottingHint enum phForceRepaint to phImmediateRefresh + - Removed QCPPlotTitle layout element (See new QCPTextElement for almost drop-in replacement) + - Removed signals QCustomPlot::titleClicked/titleDoubleClicked, replaced by QCPTextElement signals clicked/doubleClicked. + - QCustomPlot::savePdf has changed parameters from (fileName, bool noCosmeticPen, width, height,...) to (fileName, width, height, QCP::ExportPen exportPen,...) + - Virtual methods QCPLayoutElement::mouseMoveEvent/mouseReleaseEvent (which are now introduced already in the superclass QCPLayerable) have gained an additional parameter const QPointF &startPos. + If you have reimplemented these methods, make sure to update your function signatures, otherwise your reimplementations will likely be ignored by the compiler without warning + - Creating a new QCPColorGradient without supplying a preset parameter in the constructor now creates an empty gradient, instead of loading the gpCold preset + +Other: + - Replaced usage of Qt's QVector2D with own QCPVector2D which uses double precision and offers some convenience functions + - Extended relative range to which QCPItemLine/QCPItemStraightLine can be zoomed before vanishing from ~1e9 to ~1e16 + - Removed QCPItemStraightLine::distToStraightLine (replaced by QCPVector2D::distanceToStraightLine) + - Removed QCPAbstractPlottable::distSqrToLine and QCPAbstractItem::distSqrToLine (replaced by QCPVector2D::distanceSquaredToLine) + - Qt5.5 compatibility (If you use PDF export, test your outputs, as output dimensions might change when switching Qt versions -- QCP does not try to emulate previous Qt version behaviour here) + - QCP now includes instead of just because some users had problems with the latter. Please report if you now experience issues due to the new include. + - QCPGraph can now use a brush (filled polygon under the graph data) without having a graph line (line style lsNone) + - QCPFinancial is now two-colored (setTwoColored(true)) by default, and has green/red as default two-colored brushes and pens + - Plottable pixelsToCoords/coordsToPixels methods are now public, and offer transformations from pixel to plot coordinates and vice versa, using the plottable's axes + - Plottable getKeyRange/getValueRange methods are now public + - QCPBarsGroup now always places the QCPBars that was added to the group first towards lower keys, independent of axis orientation or direction (the ordering used to flip with axis orientation) + - Default focus policy for QCustomPlot is now Qt::ClickFocus, instead of Qt::NoFocus. + - tweaked QCPLegend and QCPAbstractLegendItem margins: The items have by default zero own margins, and QCPLegend row- and column spacing was increased to compensate. Legend was made slightly denser by default. + - Used doxygen version is now 1.8.12, and documentation/postprocessing-scripts were adapted accordingly. Expect minor issues and some warnings when using older doxygen. +Other after beta: + - Integrated OpenGL support (QCustomPlot::setOpenGl) is experimental for now, due the strong dependency on the system/graphics driver of the current implementation + - fixed some plot title font sizes in the example projects that were too small due to switch to QCPTextElement + - added missing override specifiers on reimplemented virtual methods + - changed to more intuitive defaults for QCPSelectionDecorator scatter style (now doesn't define an own scatter pen by default) + +#### Version 1.3.2 released on 22.12.15 #### + + Bugfixes [Backported from 2.0.0 branch]: + - Fixed possible crash when having a QCPGraph with scatters only and a non-transparent main/fill brush of the graph + - Fixed QCPItemPixmap not updating internally cached scaled pixmap if new pixmap set with same scaled dimensions + - When using log axis scale and zooming out as far as possible (~1e-280..1e280), axis doesn't end up in (via mouse) unrecoverable range with strange axis ticks anymore + - Axis tick label algorithm for beautifully typeset powers now checks whether "e" in tick label is actually part of a number before converting the exponent to superscript + - Fixed QCustomPlot::moveLayer performing incorrect move and possible crash in certain situations + - Fixed possible crash on QCustomPlot destruction due to wrong QObject-hierarchy. Only occurs if a QCPAxisRect is removed from the normal QCustomPlot destruction hierarchy by taking it out of its layout + - Fixed possible freeze when data values become infinity after coord-to-pixel transformation (e.g. maximally zoomed out log axis), and line style is not solid (e.g. dashed) or phFastPolylines is disabled + + Other [Backported from 2.0.0 branch]: + - A few documentation fixes/improvements + - Qt5.5 compatibility (If you use PDF export, test your outputs, as output dimensions might change when switching Qt versions -- QCP does not try to emulate previous Qt version behaviour here) + - QCP now includes instead of just because some users had problems with the latter. Please report if you now experience issues due to the new include. + #### Version 1.3.1 released on 25.04.15 #### Bugfixes: diff --git a/libs/qcustomplot-source/qcustomplot.cpp b/libs/qcustomplot-source/qcustomplot.cpp index d7e548526..72b5bfb8b 100644 --- a/libs/qcustomplot-source/qcustomplot.cpp +++ b/libs/qcustomplot-source/qcustomplot.cpp @@ -1,7 +1,7 @@ /*************************************************************************** ** ** ** QCustomPlot, an easy to use, modern plotting widget for Qt ** -** Copyright (C) 2011-2015 Emanuel Eichhammer ** +** Copyright (C) 2011-2022 Emanuel Eichhammer ** ** ** ** This program is free software: you can redistribute it and/or modify ** ** it under the terms of the GNU General Public License as published by ** @@ -18,14 +18,261 @@ ** ** **************************************************************************** ** Author: Emanuel Eichhammer ** -** Website/Contact: http://www.qcustomplot.com/ ** -** Date: 25.04.15 ** -** Version: 1.3.1 ** +** Website/Contact: https://www.qcustomplot.com/ ** +** Date: 06.11.22 ** +** Version: 2.1.1 ** ****************************************************************************/ #include "qcustomplot.h" +/* including file 'src/vector2d.cpp' */ +/* modified 2022-11-06T12:45:56, size 7973 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPVector2D +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPVector2D + \brief Represents two doubles as a mathematical 2D vector + + This class acts as a replacement for QVector2D with the advantage of double precision instead of + single, and some convenience methods tailored for the QCustomPlot library. +*/ + +/* start documentation of inline functions */ + +/*! \fn void QCPVector2D::setX(double x) + + Sets the x coordinate of this vector to \a x. + + \see setY +*/ + +/*! \fn void QCPVector2D::setY(double y) + + Sets the y coordinate of this vector to \a y. + + \see setX +*/ + +/*! \fn double QCPVector2D::length() const + + Returns the length of this vector. + + \see lengthSquared +*/ + +/*! \fn double QCPVector2D::lengthSquared() const + + Returns the squared length of this vector. In some situations, e.g. when just trying to find the + shortest vector of a group, this is faster than calculating \ref length, because it avoids + calculation of a square root. + + \see length +*/ + +/*! \fn double QCPVector2D::angle() const + + Returns the angle of the vector in radians. The angle is measured between the positive x line and + the vector, counter-clockwise in a mathematical coordinate system (y axis upwards positive). In + screen/widget coordinates where the y axis is inverted, the angle appears clockwise. +*/ + +/*! \fn QPoint QCPVector2D::toPoint() const + + Returns a QPoint which has the x and y coordinates of this vector, truncating any floating point + information. + + \see toPointF +*/ + +/*! \fn QPointF QCPVector2D::toPointF() const + + Returns a QPointF which has the x and y coordinates of this vector. + + \see toPoint +*/ + +/*! \fn bool QCPVector2D::isNull() const + + Returns whether this vector is null. A vector is null if \c qIsNull returns true for both x and y + coordinates, i.e. if both are binary equal to 0. +*/ + +/*! \fn QCPVector2D QCPVector2D::perpendicular() const + + Returns a vector perpendicular to this vector, with the same length. +*/ + +/*! \fn double QCPVector2D::dot() const + + Returns the dot/scalar product of this vector with the specified vector \a vec. +*/ + +/* end documentation of inline functions */ + +/*! + Creates a QCPVector2D object and initializes the x and y coordinates to 0. +*/ +QCPVector2D::QCPVector2D() : + mX(0), + mY(0) +{ +} + +/*! + Creates a QCPVector2D object and initializes the \a x and \a y coordinates with the specified + values. +*/ +QCPVector2D::QCPVector2D(double x, double y) : + mX(x), + mY(y) +{ +} + +/*! + Creates a QCPVector2D object and initializes the x and y coordinates respective coordinates of + the specified \a point. +*/ +QCPVector2D::QCPVector2D(const QPoint &point) : + mX(point.x()), + mY(point.y()) +{ +} + +/*! + Creates a QCPVector2D object and initializes the x and y coordinates respective coordinates of + the specified \a point. +*/ +QCPVector2D::QCPVector2D(const QPointF &point) : + mX(point.x()), + mY(point.y()) +{ +} + +/*! + Normalizes this vector. After this operation, the length of the vector is equal to 1. + + If the vector has both entries set to zero, this method does nothing. + + \see normalized, length, lengthSquared +*/ +void QCPVector2D::normalize() +{ + if (mX == 0.0 && mY == 0.0) return; + const double lenInv = 1.0/length(); + mX *= lenInv; + mY *= lenInv; +} + +/*! + Returns a normalized version of this vector. The length of the returned vector is equal to 1. + + If the vector has both entries set to zero, this method returns the vector unmodified. + + \see normalize, length, lengthSquared +*/ +QCPVector2D QCPVector2D::normalized() const +{ + if (mX == 0.0 && mY == 0.0) return *this; + const double lenInv = 1.0/length(); + return QCPVector2D(mX*lenInv, mY*lenInv); +} + +/*! \overload + + Returns the squared shortest distance of this vector (interpreted as a point) to the finite line + segment given by \a start and \a end. + + \see distanceToStraightLine +*/ +double QCPVector2D::distanceSquaredToLine(const QCPVector2D &start, const QCPVector2D &end) const +{ + const QCPVector2D v(end-start); + const double vLengthSqr = v.lengthSquared(); + if (!qFuzzyIsNull(vLengthSqr)) + { + const double mu = v.dot(*this-start)/vLengthSqr; + if (mu < 0) + return (*this-start).lengthSquared(); + else if (mu > 1) + return (*this-end).lengthSquared(); + else + return ((start + mu*v)-*this).lengthSquared(); + } else + return (*this-start).lengthSquared(); +} + +/*! \overload + + Returns the squared shortest distance of this vector (interpreted as a point) to the finite line + segment given by \a line. + + \see distanceToStraightLine +*/ +double QCPVector2D::distanceSquaredToLine(const QLineF &line) const +{ + return distanceSquaredToLine(QCPVector2D(line.p1()), QCPVector2D(line.p2())); +} + +/*! + Returns the shortest distance of this vector (interpreted as a point) to the infinite straight + line given by a \a base point and a \a direction vector. + + \see distanceSquaredToLine +*/ +double QCPVector2D::distanceToStraightLine(const QCPVector2D &base, const QCPVector2D &direction) const +{ + return qAbs((*this-base).dot(direction.perpendicular()))/direction.length(); +} + +/*! + Scales this vector by the given \a factor, i.e. the x and y components are multiplied by \a + factor. +*/ +QCPVector2D &QCPVector2D::operator*=(double factor) +{ + mX *= factor; + mY *= factor; + return *this; +} + +/*! + Scales this vector by the given \a divisor, i.e. the x and y components are divided by \a + divisor. +*/ +QCPVector2D &QCPVector2D::operator/=(double divisor) +{ + mX /= divisor; + mY /= divisor; + return *this; +} + +/*! + Adds the given \a vector to this vector component-wise. +*/ +QCPVector2D &QCPVector2D::operator+=(const QCPVector2D &vector) +{ + mX += vector.mX; + mY += vector.mY; + return *this; +} + +/*! + subtracts the given \a vector from this vector component-wise. +*/ +QCPVector2D &QCPVector2D::operator-=(const QCPVector2D &vector) +{ + mX -= vector.mX; + mY -= vector.mY; + return *this; +} +/* end of 'src/vector2d.cpp' */ + + +/* including file 'src/painter.cpp' */ +/* modified 2022-11-06T12:45:56, size 8656 */ //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////// QCPPainter @@ -48,7 +295,6 @@ Creates a new QCPPainter instance and sets default values */ QCPPainter::QCPPainter() : - QPainter(), mModes(pmDefault), mIsAntialiasing(false) { @@ -73,10 +319,6 @@ QCPPainter::QCPPainter(QPaintDevice *device) : #endif } -QCPPainter::~QCPPainter() -{ -} - /*! Sets the pen of the painter and applies certain fixes to it, depending on the mode of this QCPPainter. @@ -243,426 +485,498 @@ void QCPPainter::makeNonCosmetic() QPainter::setPen(p); } } +/* end of 'src/painter.cpp' */ +/* including file 'src/paintbuffer.cpp' */ +/* modified 2022-11-06T12:45:56, size 18915 */ + //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPScatterStyle +//////////////////// QCPAbstractPaintBuffer //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPScatterStyle - \brief Represents the visual appearance of scatter points - - This class holds information about shape, color and size of scatter points. In plottables like - QCPGraph it is used to store how scatter points shall be drawn. For example, \ref - QCPGraph::setScatterStyle takes a QCPScatterStyle instance. - - A scatter style consists of a shape (\ref setShape), a line color (\ref setPen) and possibly a - fill (\ref setBrush), if the shape provides a fillable area. Further, the size of the shape can - be controlled with \ref setSize. +/*! \class QCPAbstractPaintBuffer + \brief The abstract base class for paint buffers, which define the rendering backend - \section QCPScatterStyle-defining Specifying a scatter style - - You can set all these configurations either by calling the respective functions on an instance: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpscatterstyle-creation-1 - - Or you can use one of the various constructors that take different parameter combinations, making - it easy to specify a scatter style in a single call, like so: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpscatterstyle-creation-2 - - \section QCPScatterStyle-undefinedpen Leaving the color/pen up to the plottable - - There are two constructors which leave the pen undefined: \ref QCPScatterStyle() and \ref - QCPScatterStyle(ScatterShape shape, double size). If those constructors are used, a call to \ref - isPenDefined will return false. It leads to scatter points that inherit the pen from the - plottable that uses the scatter style. Thus, if such a scatter style is passed to QCPGraph, the line - color of the graph (\ref QCPGraph::setPen) will be used by the scatter points. This makes - it very convenient to set up typical scatter settings: - - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpscatterstyle-shortcreation + This abstract base class defines the basic interface that a paint buffer needs to provide in + order to be usable by QCustomPlot. - Notice that it wasn't even necessary to explicitly call a QCPScatterStyle constructor. This works - because QCPScatterStyle provides a constructor that can transform a \ref ScatterShape directly - into a QCPScatterStyle instance (that's the \ref QCPScatterStyle(ScatterShape shape, double size) - constructor with a default for \a size). In those cases, C++ allows directly supplying a \ref - ScatterShape, where actually a QCPScatterStyle is expected. - - \section QCPScatterStyle-custompath-and-pixmap Custom shapes and pixmaps - - QCPScatterStyle supports drawing custom shapes and arbitrary pixmaps as scatter points. + A paint buffer manages both a surface to draw onto, and the matching paint device. The size of + the surface can be changed via \ref setSize. External classes (\ref QCustomPlot and \ref + QCPLayer) request a painter via \ref startPainting and then perform the draw calls. Once the + painting is complete, \ref donePainting is called, so the paint buffer implementation can do + clean up if necessary. Before rendering a frame, each paint buffer is usually filled with a color + using \ref clear (usually the color is \c Qt::transparent), to remove the contents of the + previous frame. - For custom shapes, you can provide a QPainterPath with the desired shape to the \ref - setCustomPath function or call the constructor that takes a painter path. The scatter shape will - automatically be set to \ref ssCustom. - - For pixmaps, you call \ref setPixmap with the desired QPixmap. Alternatively you can use the - constructor that takes a QPixmap. The scatter shape will automatically be set to \ref ssPixmap. - Note that \ref setSize does not influence the appearance of the pixmap. + The simplest paint buffer implementation is \ref QCPPaintBufferPixmap which allows regular + software rendering via the raster engine. Hardware accelerated rendering via pixel buffers and + frame buffer objects is provided by \ref QCPPaintBufferGlPbuffer and \ref QCPPaintBufferGlFbo. + They are used automatically if \ref QCustomPlot::setOpenGl is enabled. */ -/* start documentation of inline functions */ +/* start documentation of pure virtual functions */ -/*! \fn bool QCPScatterStyle::isNone() const - - Returns whether the scatter shape is \ref ssNone. - - \see setShape +/*! \fn virtual QCPPainter *QCPAbstractPaintBuffer::startPainting() = 0 + + Returns a \ref QCPPainter which is ready to draw to this buffer. The ownership and thus the + responsibility to delete the painter after the painting operations are complete is given to the + caller of this method. + + Once you are done using the painter, delete the painter and call \ref donePainting. + + While a painter generated with this method is active, you must not call \ref setSize, \ref + setDevicePixelRatio or \ref clear. + + This method may return 0, if a painter couldn't be activated on the buffer. This usually + indicates a problem with the respective painting backend. */ -/*! \fn bool QCPScatterStyle::isPenDefined() const - - Returns whether a pen has been defined for this scatter style. - - The pen is undefined if a constructor is called that does not carry \a pen as parameter. Those are - \ref QCPScatterStyle() and \ref QCPScatterStyle(ScatterShape shape, double size). If the pen is - left undefined, the scatter color will be inherited from the plottable that uses this scatter - style. - - \see setPen +/*! \fn virtual void QCPAbstractPaintBuffer::draw(QCPPainter *painter) const = 0 + + Draws the contents of this buffer with the provided \a painter. This is the method that is used + to finally join all paint buffers and draw them onto the screen. +*/ + +/*! \fn virtual void QCPAbstractPaintBuffer::clear(const QColor &color) = 0 + + Fills the entire buffer with the provided \a color. To have an empty transparent buffer, use the + named color \c Qt::transparent. + + This method must not be called if there is currently a painter (acquired with \ref startPainting) + active. +*/ + +/*! \fn virtual void QCPAbstractPaintBuffer::reallocateBuffer() = 0 + + Reallocates the internal buffer with the currently configured size (\ref setSize) and device + pixel ratio, if applicable (\ref setDevicePixelRatio). It is called as soon as any of those + properties are changed on this paint buffer. + + \note Subclasses of \ref QCPAbstractPaintBuffer must call their reimplementation of this method + in their constructor, to perform the first allocation (this can not be done by the base class + because calling pure virtual methods in base class constructors is not possible). +*/ + +/* end documentation of pure virtual functions */ +/* start documentation of inline functions */ + +/*! \fn virtual void QCPAbstractPaintBuffer::donePainting() + + If you have acquired a \ref QCPPainter to paint onto this paint buffer via \ref startPainting, + call this method as soon as you are done with the painting operations and have deleted the + painter. + + paint buffer subclasses may use this method to perform any type of cleanup that is necessary. The + default implementation does nothing. */ /* end documentation of inline functions */ /*! - Creates a new QCPScatterStyle instance with size set to 6. No shape, pen or brush is defined. - - Since the pen is undefined (\ref isPenDefined returns false), the scatter color will be inherited - from the plottable that uses this scatter style. + Creates a paint buffer and initializes it with the provided \a size and \a devicePixelRatio. + + Subclasses must call their \ref reallocateBuffer implementation in their respective constructors. */ -QCPScatterStyle::QCPScatterStyle() : - mSize(6), - mShape(ssNone), - mPen(Qt::NoPen), - mBrush(Qt::NoBrush), - mPenDefined(false) +QCPAbstractPaintBuffer::QCPAbstractPaintBuffer(const QSize &size, double devicePixelRatio) : + mSize(size), + mDevicePixelRatio(devicePixelRatio), + mInvalidated(true) { } -/*! - Creates a new QCPScatterStyle instance with shape set to \a shape and size to \a size. No pen or - brush is defined. - - Since the pen is undefined (\ref isPenDefined returns false), the scatter color will be inherited - from the plottable that uses this scatter style. -*/ -QCPScatterStyle::QCPScatterStyle(ScatterShape shape, double size) : - mSize(size), - mShape(shape), - mPen(Qt::NoPen), - mBrush(Qt::NoBrush), - mPenDefined(false) +QCPAbstractPaintBuffer::~QCPAbstractPaintBuffer() { } /*! - Creates a new QCPScatterStyle instance with shape set to \a shape, the pen color set to \a color, - and size to \a size. No brush is defined, i.e. the scatter point will not be filled. + Sets the paint buffer size. + + The buffer is reallocated (by calling \ref reallocateBuffer), so any painters that were obtained + by \ref startPainting are invalidated and must not be used after calling this method. + + If \a size is already the current buffer size, this method does nothing. */ -QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, double size) : - mSize(size), - mShape(shape), - mPen(QPen(color)), - mBrush(Qt::NoBrush), - mPenDefined(true) +void QCPAbstractPaintBuffer::setSize(const QSize &size) { + if (mSize != size) + { + mSize = size; + reallocateBuffer(); + } } /*! - Creates a new QCPScatterStyle instance with shape set to \a shape, the pen color set to \a color, - the brush color to \a fill (with a solid pattern), and size to \a size. + Sets the invalidated flag to \a invalidated. + + This mechanism is used internally in conjunction with isolated replotting of \ref QCPLayer + instances (in \ref QCPLayer::lmBuffered mode). If \ref QCPLayer::replot is called on a buffered + layer, i.e. an isolated repaint of only that layer (and its dedicated paint buffer) is requested, + QCustomPlot will decide depending on the invalidated flags of other paint buffers whether it also + replots them, instead of only the layer on which the replot was called. + + The invalidated flag is set to true when \ref QCPLayer association has changed, i.e. if layers + were added or removed from this buffer, or if they were reordered. It is set to false as soon as + all associated \ref QCPLayer instances are drawn onto the buffer. + + Under normal circumstances, it is not necessary to manually call this method. */ -QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size) : - mSize(size), - mShape(shape), - mPen(QPen(color)), - mBrush(QBrush(fill)), - mPenDefined(true) +void QCPAbstractPaintBuffer::setInvalidated(bool invalidated) { + mInvalidated = invalidated; } /*! - Creates a new QCPScatterStyle instance with shape set to \a shape, the pen set to \a pen, the - brush to \a brush, and size to \a size. - - \warning In some cases it might be tempting to directly use a pen style like Qt::NoPen as \a pen - and a color like Qt::blue as \a brush. Notice however, that the corresponding call\n - QCPScatterStyle(QCPScatterShape::ssCircle, Qt::NoPen, Qt::blue, 5)\n - doesn't necessarily lead C++ to use this constructor in some cases, but might mistake - Qt::NoPen for a QColor and use the - \ref QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size) - constructor instead (which will lead to an unexpected look of the scatter points). To prevent - this, be more explicit with the parameter types. For example, use QBrush(Qt::blue) - instead of just Qt::blue, to clearly point out to the compiler that this constructor is - wanted. + Sets the device pixel ratio to \a ratio. This is useful to render on high-DPI output devices. + The ratio is automatically set to the device pixel ratio used by the parent QCustomPlot instance. + + The buffer is reallocated (by calling \ref reallocateBuffer), so any painters that were obtained + by \ref startPainting are invalidated and must not be used after calling this method. + + \note This method is only available for Qt versions 5.4 and higher. */ -QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QPen &pen, const QBrush &brush, double size) : - mSize(size), - mShape(shape), - mPen(pen), - mBrush(brush), - mPenDefined(pen.style() != Qt::NoPen) +void QCPAbstractPaintBuffer::setDevicePixelRatio(double ratio) { + if (!qFuzzyCompare(ratio, mDevicePixelRatio)) + { +#ifdef QCP_DEVICEPIXELRATIO_SUPPORTED + mDevicePixelRatio = ratio; + reallocateBuffer(); +#else + qDebug() << Q_FUNC_INFO << "Device pixel ratios not supported for Qt versions before 5.4"; + mDevicePixelRatio = 1.0; +#endif + } } +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPPaintBufferPixmap +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPPaintBufferPixmap + \brief A paint buffer based on QPixmap, using software raster rendering + + This paint buffer is the default and fall-back paint buffer which uses software rendering and + QPixmap as internal buffer. It is used if \ref QCustomPlot::setOpenGl is false. +*/ + /*! - Creates a new QCPScatterStyle instance which will show the specified \a pixmap. The scatter shape - is set to \ref ssPixmap. + Creates a pixmap paint buffer instancen with the specified \a size and \a devicePixelRatio, if + applicable. */ -QCPScatterStyle::QCPScatterStyle(const QPixmap &pixmap) : - mSize(5), - mShape(ssPixmap), - mPen(Qt::NoPen), - mBrush(Qt::NoBrush), - mPixmap(pixmap), - mPenDefined(false) +QCPPaintBufferPixmap::QCPPaintBufferPixmap(const QSize &size, double devicePixelRatio) : + QCPAbstractPaintBuffer(size, devicePixelRatio) { + QCPPaintBufferPixmap::reallocateBuffer(); } -/*! - Creates a new QCPScatterStyle instance with a custom shape that is defined via \a customPath. The - scatter shape is set to \ref ssCustom. - - The custom shape line will be drawn with \a pen and filled with \a brush. The size has a slightly - different meaning than for built-in scatter points: The custom path will be drawn scaled by a - factor of \a size/6.0. Since the default \a size is 6, the custom path will appear at a its - natural size by default. To double the size of the path for example, set \a size to 12. -*/ -QCPScatterStyle::QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, const QBrush &brush, double size) : - mSize(size), - mShape(ssCustom), - mPen(pen), - mBrush(brush), - mCustomPath(customPath), - mPenDefined(pen.style() != Qt::NoPen) +QCPPaintBufferPixmap::~QCPPaintBufferPixmap() { } -/*! - Sets the size (pixel diameter) of the drawn scatter points to \a size. - - \see setShape -*/ -void QCPScatterStyle::setSize(double size) +/* inherits documentation from base class */ +QCPPainter *QCPPaintBufferPixmap::startPainting() { - mSize = size; + QCPPainter *result = new QCPPainter(&mBuffer); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + result->setRenderHint(QPainter::HighQualityAntialiasing); +#endif + return result; } -/*! - Sets the shape to \a shape. - - Note that the calls \ref setPixmap and \ref setCustomPath automatically set the shape to \ref - ssPixmap and \ref ssCustom, respectively. - - \see setSize -*/ -void QCPScatterStyle::setShape(QCPScatterStyle::ScatterShape shape) +/* inherits documentation from base class */ +void QCPPaintBufferPixmap::draw(QCPPainter *painter) const { - mShape = shape; + if (painter && painter->isActive()) + painter->drawPixmap(0, 0, mBuffer); + else + qDebug() << Q_FUNC_INFO << "invalid or inactive painter passed"; } -/*! - Sets the pen that will be used to draw scatter points to \a pen. - - If the pen was previously undefined (see \ref isPenDefined), the pen is considered defined after - a call to this function, even if \a pen is Qt::NoPen. - - \see setBrush -*/ -void QCPScatterStyle::setPen(const QPen &pen) +/* inherits documentation from base class */ +void QCPPaintBufferPixmap::clear(const QColor &color) { - mPenDefined = true; - mPen = pen; + mBuffer.fill(color); } -/*! - Sets the brush that will be used to fill scatter points to \a brush. Note that not all scatter - shapes have fillable areas. For example, \ref ssPlus does not while \ref ssCircle does. - - \see setPen -*/ -void QCPScatterStyle::setBrush(const QBrush &brush) +/* inherits documentation from base class */ +void QCPPaintBufferPixmap::reallocateBuffer() { - mBrush = brush; + setInvalidated(); + if (!qFuzzyCompare(1.0, mDevicePixelRatio)) + { +#ifdef QCP_DEVICEPIXELRATIO_SUPPORTED + mBuffer = QPixmap(mSize*mDevicePixelRatio); + mBuffer.setDevicePixelRatio(mDevicePixelRatio); +#else + qDebug() << Q_FUNC_INFO << "Device pixel ratios not supported for Qt versions before 5.4"; + mDevicePixelRatio = 1.0; + mBuffer = QPixmap(mSize); +#endif + } else + { + mBuffer = QPixmap(mSize); + } } + +#ifdef QCP_OPENGL_PBUFFER +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPPaintBufferGlPbuffer +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPPaintBufferGlPbuffer + \brief A paint buffer based on OpenGL pixel buffers, using hardware accelerated rendering + + This paint buffer is one of the OpenGL paint buffers which facilitate hardware accelerated plot + rendering. It is based on OpenGL pixel buffers (pbuffer) and is used in Qt versions before 5.0. + (See \ref QCPPaintBufferGlFbo used in newer Qt versions.) + + The OpenGL paint buffers are used if \ref QCustomPlot::setOpenGl is set to true, and if they are + supported by the system. +*/ + /*! - Sets the pixmap that will be drawn as scatter point to \a pixmap. - - Note that \ref setSize does not influence the appearance of the pixmap. - - The scatter shape is automatically set to \ref ssPixmap. + Creates a \ref QCPPaintBufferGlPbuffer instance with the specified \a size and \a + devicePixelRatio, if applicable. + + The parameter \a multisamples defines how many samples are used per pixel. Higher values thus + result in higher quality antialiasing. If the specified \a multisamples value exceeds the + capability of the graphics hardware, the highest supported multisampling is used. */ -void QCPScatterStyle::setPixmap(const QPixmap &pixmap) +QCPPaintBufferGlPbuffer::QCPPaintBufferGlPbuffer(const QSize &size, double devicePixelRatio, int multisamples) : + QCPAbstractPaintBuffer(size, devicePixelRatio), + mGlPBuffer(0), + mMultisamples(qMax(0, multisamples)) { - setShape(ssPixmap); - mPixmap = pixmap; + QCPPaintBufferGlPbuffer::reallocateBuffer(); } -/*! - Sets the custom shape that will be drawn as scatter point to \a customPath. - - The scatter shape is automatically set to \ref ssCustom. -*/ -void QCPScatterStyle::setCustomPath(const QPainterPath &customPath) +QCPPaintBufferGlPbuffer::~QCPPaintBufferGlPbuffer() { - setShape(ssCustom); - mCustomPath = customPath; + if (mGlPBuffer) + delete mGlPBuffer; } -/*! - Applies the pen and the brush of this scatter style to \a painter. If this scatter style has an - undefined pen (\ref isPenDefined), sets the pen of \a painter to \a defaultPen instead. +/* inherits documentation from base class */ +QCPPainter *QCPPaintBufferGlPbuffer::startPainting() +{ + if (!mGlPBuffer->isValid()) + { + qDebug() << Q_FUNC_INFO << "OpenGL frame buffer object doesn't exist, reallocateBuffer was not called?"; + return 0; + } - This function is used by plottables (or any class that wants to draw scatters) just before a - number of scatters with this style shall be drawn with the \a painter. + QCPPainter *result = new QCPPainter(mGlPBuffer); + result->setRenderHint(QPainter::HighQualityAntialiasing); + return result; +} + +/* inherits documentation from base class */ +void QCPPaintBufferGlPbuffer::draw(QCPPainter *painter) const +{ + if (!painter || !painter->isActive()) + { + qDebug() << Q_FUNC_INFO << "invalid or inactive painter passed"; + return; + } + if (!mGlPBuffer->isValid()) + { + qDebug() << Q_FUNC_INFO << "OpenGL pbuffer isn't valid, reallocateBuffer was not called?"; + return; + } + painter->drawImage(0, 0, mGlPBuffer->toImage()); +} + +/* inherits documentation from base class */ +void QCPPaintBufferGlPbuffer::clear(const QColor &color) +{ + if (mGlPBuffer->isValid()) + { + mGlPBuffer->makeCurrent(); + glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + mGlPBuffer->doneCurrent(); + } else + qDebug() << Q_FUNC_INFO << "OpenGL pbuffer invalid or context not current"; +} + +/* inherits documentation from base class */ +void QCPPaintBufferGlPbuffer::reallocateBuffer() +{ + if (mGlPBuffer) + delete mGlPBuffer; - \see drawShape + QGLFormat format; + format.setAlpha(true); + format.setSamples(mMultisamples); + mGlPBuffer = new QGLPixelBuffer(mSize, format); +} +#endif // QCP_OPENGL_PBUFFER + + +#ifdef QCP_OPENGL_FBO +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPPaintBufferGlFbo +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPPaintBufferGlFbo + \brief A paint buffer based on OpenGL frame buffers objects, using hardware accelerated rendering + + This paint buffer is one of the OpenGL paint buffers which facilitate hardware accelerated plot + rendering. It is based on OpenGL frame buffer objects (fbo) and is used in Qt versions 5.0 and + higher. (See \ref QCPPaintBufferGlPbuffer used in older Qt versions.) + + The OpenGL paint buffers are used if \ref QCustomPlot::setOpenGl is set to true, and if they are + supported by the system. */ -void QCPScatterStyle::applyTo(QCPPainter *painter, const QPen &defaultPen) const + +/*! + Creates a \ref QCPPaintBufferGlFbo instance with the specified \a size and \a devicePixelRatio, + if applicable. + + All frame buffer objects shall share one OpenGL context and paint device, which need to be set up + externally and passed via \a glContext and \a glPaintDevice. The set-up is done in \ref + QCustomPlot::setupOpenGl and the context and paint device are managed by the parent QCustomPlot + instance. +*/ +QCPPaintBufferGlFbo::QCPPaintBufferGlFbo(const QSize &size, double devicePixelRatio, QWeakPointer glContext, QWeakPointer glPaintDevice) : + QCPAbstractPaintBuffer(size, devicePixelRatio), + mGlContext(glContext), + mGlPaintDevice(glPaintDevice), + mGlFrameBuffer(0) { - painter->setPen(mPenDefined ? mPen : defaultPen); - painter->setBrush(mBrush); + QCPPaintBufferGlFbo::reallocateBuffer(); } -/*! - Draws the scatter shape with \a painter at position \a pos. - - This function does not modify the pen or the brush on the painter, as \ref applyTo is meant to be - called before scatter points are drawn with \ref drawShape. +QCPPaintBufferGlFbo::~QCPPaintBufferGlFbo() +{ + if (mGlFrameBuffer) + delete mGlFrameBuffer; +} + +/* inherits documentation from base class */ +QCPPainter *QCPPaintBufferGlFbo::startPainting() +{ + QSharedPointer paintDevice = mGlPaintDevice.toStrongRef(); + QSharedPointer context = mGlContext.toStrongRef(); + if (!paintDevice) + { + qDebug() << Q_FUNC_INFO << "OpenGL paint device doesn't exist"; + return 0; + } + if (!context) + { + qDebug() << Q_FUNC_INFO << "OpenGL context doesn't exist"; + return 0; + } + if (!mGlFrameBuffer) + { + qDebug() << Q_FUNC_INFO << "OpenGL frame buffer object doesn't exist, reallocateBuffer was not called?"; + return 0; + } - \see applyTo -*/ -void QCPScatterStyle::drawShape(QCPPainter *painter, QPointF pos) const + if (QOpenGLContext::currentContext() != context.data()) + context->makeCurrent(context->surface()); + mGlFrameBuffer->bind(); + QCPPainter *result = new QCPPainter(paintDevice.data()); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + result->setRenderHint(QPainter::HighQualityAntialiasing); +#endif + return result; +} + +/* inherits documentation from base class */ +void QCPPaintBufferGlFbo::donePainting() { - drawShape(painter, pos.x(), pos.y()); + if (mGlFrameBuffer && mGlFrameBuffer->isBound()) + mGlFrameBuffer->release(); + else + qDebug() << Q_FUNC_INFO << "Either OpenGL frame buffer not valid or was not bound"; } -/*! \overload - Draws the scatter shape with \a painter at position \a x and \a y. -*/ -void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const +/* inherits documentation from base class */ +void QCPPaintBufferGlFbo::draw(QCPPainter *painter) const { - double w = mSize/2.0; - switch (mShape) + if (!painter || !painter->isActive()) { - case ssNone: break; - case ssDot: - { - painter->drawLine(QPointF(x, y), QPointF(x+0.0001, y)); - break; - } - case ssCross: - { - painter->drawLine(QLineF(x-w, y-w, x+w, y+w)); - painter->drawLine(QLineF(x-w, y+w, x+w, y-w)); - break; - } - case ssPlus: - { - painter->drawLine(QLineF(x-w, y, x+w, y)); - painter->drawLine(QLineF( x, y+w, x, y-w)); - break; - } - case ssCircle: - { - painter->drawEllipse(QPointF(x , y), w, w); - break; - } - case ssDisc: - { - QBrush b = painter->brush(); - painter->setBrush(painter->pen().color()); - painter->drawEllipse(QPointF(x , y), w, w); - painter->setBrush(b); - break; - } - case ssSquare: - { - painter->drawRect(QRectF(x-w, y-w, mSize, mSize)); - break; - } - case ssDiamond: - { - painter->drawLine(QLineF(x-w, y, x, y-w)); - painter->drawLine(QLineF( x, y-w, x+w, y)); - painter->drawLine(QLineF(x+w, y, x, y+w)); - painter->drawLine(QLineF( x, y+w, x-w, y)); - break; - } - case ssStar: - { - painter->drawLine(QLineF(x-w, y, x+w, y)); - painter->drawLine(QLineF( x, y+w, x, y-w)); - painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.707, y+w*0.707)); - painter->drawLine(QLineF(x-w*0.707, y+w*0.707, x+w*0.707, y-w*0.707)); - break; - } - case ssTriangle: - { - painter->drawLine(QLineF(x-w, y+0.755*w, x+w, y+0.755*w)); - painter->drawLine(QLineF(x+w, y+0.755*w, x, y-0.977*w)); - painter->drawLine(QLineF( x, y-0.977*w, x-w, y+0.755*w)); - break; - } - case ssTriangleInverted: - { - painter->drawLine(QLineF(x-w, y-0.755*w, x+w, y-0.755*w)); - painter->drawLine(QLineF(x+w, y-0.755*w, x, y+0.977*w)); - painter->drawLine(QLineF( x, y+0.977*w, x-w, y-0.755*w)); - break; - } - case ssCrossSquare: - { - painter->drawLine(QLineF(x-w, y-w, x+w*0.95, y+w*0.95)); - painter->drawLine(QLineF(x-w, y+w*0.95, x+w*0.95, y-w)); - painter->drawRect(QRectF(x-w, y-w, mSize, mSize)); - break; - } - case ssPlusSquare: - { - painter->drawLine(QLineF(x-w, y, x+w*0.95, y)); - painter->drawLine(QLineF( x, y+w, x, y-w)); - painter->drawRect(QRectF(x-w, y-w, mSize, mSize)); - break; - } - case ssCrossCircle: - { - painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.670, y+w*0.670)); - painter->drawLine(QLineF(x-w*0.707, y+w*0.670, x+w*0.670, y-w*0.707)); - painter->drawEllipse(QPointF(x, y), w, w); - break; - } - case ssPlusCircle: - { - painter->drawLine(QLineF(x-w, y, x+w, y)); - painter->drawLine(QLineF( x, y+w, x, y-w)); - painter->drawEllipse(QPointF(x, y), w, w); - break; - } - case ssPeace: - { - painter->drawLine(QLineF(x, y-w, x, y+w)); - painter->drawLine(QLineF(x, y, x-w*0.707, y+w*0.707)); - painter->drawLine(QLineF(x, y, x+w*0.707, y+w*0.707)); - painter->drawEllipse(QPointF(x, y), w, w); - break; - } - case ssPixmap: - { - painter->drawPixmap(x-mPixmap.width()*0.5, y-mPixmap.height()*0.5, mPixmap); - break; - } - case ssCustom: - { - QTransform oldTransform = painter->transform(); - painter->translate(x, y); - painter->scale(mSize/6.0, mSize/6.0); - painter->drawPath(mCustomPath); - painter->setTransform(oldTransform); - break; - } + qDebug() << Q_FUNC_INFO << "invalid or inactive painter passed"; + return; + } + if (!mGlFrameBuffer) + { + qDebug() << Q_FUNC_INFO << "OpenGL frame buffer object doesn't exist, reallocateBuffer was not called?"; + return; + } + painter->drawImage(0, 0, mGlFrameBuffer->toImage()); +} + +/* inherits documentation from base class */ +void QCPPaintBufferGlFbo::clear(const QColor &color) +{ + QSharedPointer context = mGlContext.toStrongRef(); + if (!context) + { + qDebug() << Q_FUNC_INFO << "OpenGL context doesn't exist"; + return; + } + if (!mGlFrameBuffer) + { + qDebug() << Q_FUNC_INFO << "OpenGL frame buffer object doesn't exist, reallocateBuffer was not called?"; + return; + } + + if (QOpenGLContext::currentContext() != context.data()) + context->makeCurrent(context->surface()); + mGlFrameBuffer->bind(); + glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + mGlFrameBuffer->release(); +} + +/* inherits documentation from base class */ +void QCPPaintBufferGlFbo::reallocateBuffer() +{ + // release and delete possibly existing framebuffer: + if (mGlFrameBuffer) + { + if (mGlFrameBuffer->isBound()) + mGlFrameBuffer->release(); + delete mGlFrameBuffer; + mGlFrameBuffer = 0; } + + QSharedPointer paintDevice = mGlPaintDevice.toStrongRef(); + QSharedPointer context = mGlContext.toStrongRef(); + if (!paintDevice) + { + qDebug() << Q_FUNC_INFO << "OpenGL paint device doesn't exist"; + return; + } + if (!context) + { + qDebug() << Q_FUNC_INFO << "OpenGL context doesn't exist"; + return; + } + + // create new fbo with appropriate size: + context->makeCurrent(context->surface()); + QOpenGLFramebufferObjectFormat frameBufferFormat; + frameBufferFormat.setSamples(context->format().samples()); + frameBufferFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + mGlFrameBuffer = new QOpenGLFramebufferObject(mSize*mDevicePixelRatio, frameBufferFormat); + if (paintDevice->size() != mSize*mDevicePixelRatio) + paintDevice->setSize(mSize*mDevicePixelRatio); +#ifdef QCP_DEVICEPIXELRATIO_SUPPORTED + paintDevice->setDevicePixelRatio(mDevicePixelRatio); +#endif } +#endif // QCP_OPENGL_FBO +/* end of 'src/paintbuffer.cpp' */ + +/* including file 'src/layer.cpp' */ +/* modified 2022-11-06T12:45:56, size 37615 */ //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////// QCPLayer @@ -670,44 +984,58 @@ void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const /*! \class QCPLayer \brief A layer that may contain objects, to control the rendering order - + The Layering system of QCustomPlot is the mechanism to control the rendering order of the elements inside the plot. - + It is based on the two classes QCPLayer and QCPLayerable. QCustomPlot holds an ordered list of one or more instances of QCPLayer (see QCustomPlot::addLayer, QCustomPlot::layer, QCustomPlot::moveLayer, etc.). When replotting, QCustomPlot goes through the list of layers - bottom to top and successively draws the layerables of the layers. - + bottom to top and successively draws the layerables of the layers into the paint buffer(s). + A QCPLayer contains an ordered list of QCPLayerable instances. QCPLayerable is an abstract base class from which almost all visible objects derive, like axes, grids, graphs, items, etc. - - Initially, QCustomPlot has five layers: "background", "grid", "main", "axes" and "legend" (in - that order). The top two layers "axes" and "legend" contain the default axes and legend, so they - will be drawn on top. In the middle, there is the "main" layer. It is initially empty and set as - the current layer (see QCustomPlot::setCurrentLayer). This means, all new plottables, items etc. - are created on this layer by default. Then comes the "grid" layer which contains the QCPGrid - instances (which belong tightly to QCPAxis, see \ref QCPAxis::grid). The Axis rect background - shall be drawn behind everything else, thus the default QCPAxisRect instance is placed on the - "background" layer. Of course, the layer affiliation of the individual objects can be changed as - required (\ref QCPLayerable::setLayer). - - Controlling the ordering of objects is easy: Create a new layer in the position you want it to - be, e.g. above "main", with QCustomPlot::addLayer. Then set the current layer with - QCustomPlot::setCurrentLayer to that new layer and finally create the objects normally. They will - be placed on the new layer automatically, due to the current layer setting. Alternatively you - could have also ignored the current layer setting and just moved the objects with - QCPLayerable::setLayer to the desired layer after creating them. - + + \section qcplayer-defaultlayers Default layers + + Initially, QCustomPlot has six layers: "background", "grid", "main", "axes", "legend" and + "overlay" (in that order). On top is the "overlay" layer, which only contains the QCustomPlot's + selection rect (\ref QCustomPlot::selectionRect). The next two layers "axes" and "legend" contain + the default axes and legend, so they will be drawn above plottables. In the middle, there is the + "main" layer. It is initially empty and set as the current layer (see + QCustomPlot::setCurrentLayer). This means, all new plottables, items etc. are created on this + layer by default. Then comes the "grid" layer which contains the QCPGrid instances (which belong + tightly to QCPAxis, see \ref QCPAxis::grid). The Axis rect background shall be drawn behind + everything else, thus the default QCPAxisRect instance is placed on the "background" layer. Of + course, the layer affiliation of the individual objects can be changed as required (\ref + QCPLayerable::setLayer). + + \section qcplayer-ordering Controlling the rendering order via layers + + Controlling the ordering of layerables in the plot is easy: Create a new layer in the position + you want the layerable to be in, e.g. above "main", with \ref QCustomPlot::addLayer. Then set the + current layer with \ref QCustomPlot::setCurrentLayer to that new layer and finally create the + objects normally. They will be placed on the new layer automatically, due to the current layer + setting. Alternatively you could have also ignored the current layer setting and just moved the + objects with \ref QCPLayerable::setLayer to the desired layer after creating them. + It is also possible to move whole layers. For example, If you want the grid to be shown in front of all plottables/items on the "main" layer, just move it above "main" with QCustomPlot::moveLayer. - + The rendering order within one layer is simply by order of creation or insertion. The item created last (or added last to the layer), is drawn on top of all other objects on that layer. - + When a layer is deleted, the objects on it are not deleted with it, but fall on the layer below the deleted layer, see QCustomPlot::removeLayer. + + \section qcplayer-buffering Replotting only a specific layer + + If the layer mode (\ref setMode) is set to \ref lmBuffered, you can replot only this specific + layer by calling \ref replot. In certain situations this can provide better replot performance, + compared with a full replot of all layers. Upon creation of a new layer, the layer mode is + initialized to \ref lmLogical. The only layer that is set to \ref lmBuffered in a new \ref + QCustomPlot instance is the "overlay" layer, containing the selection rect. */ /* start documentation of inline functions */ @@ -741,7 +1069,8 @@ QCPLayer::QCPLayer(QCustomPlot *parentPlot, const QString &layerName) : mParentPlot(parentPlot), mName(layerName), mIndex(-1), // will be set to a proper value by the QCustomPlot layer creation function - mVisible(true) + mVisible(true), + mMode(lmLogical) { // Note: no need to make sure layerName is unique, because layer // management is done with QCustomPlot functions. @@ -755,10 +1084,10 @@ QCPLayer::~QCPLayer() // call QCustomPlot::removeLayer, which moves all layerables off this layer before deleting it.) while (!mChildren.isEmpty()) - mChildren.last()->setLayer(0); // removes itself from mChildren via removeChild() + mChildren.last()->setLayer(nullptr); // removes itself from mChildren via removeChild() if (mParentPlot->currentLayer() == this) - qDebug() << Q_FUNC_INFO << "The parent plot's mCurrentLayer will be a dangling pointer. Should have been set to a valid layer or 0 beforehand."; + qDebug() << Q_FUNC_INFO << "The parent plot's mCurrentLayer will be a dangling pointer. Should have been set to a valid layer or nullptr beforehand."; } /*! @@ -774,6 +1103,114 @@ void QCPLayer::setVisible(bool visible) mVisible = visible; } +/*! + Sets the rendering mode of this layer. + + If \a mode is set to \ref lmBuffered for a layer, it will be given a dedicated paint buffer by + the parent QCustomPlot instance. This means it may be replotted individually by calling \ref + QCPLayer::replot, without needing to replot all other layers. + + Layers which are set to \ref lmLogical (the default) are used only to define the rendering order + and can't be replotted individually. + + Note that each layer which is set to \ref lmBuffered requires additional paint buffers for the + layers below, above and for the layer itself. This increases the memory consumption and + (slightly) decreases the repainting speed because multiple paint buffers need to be joined. So + you should carefully choose which layers benefit from having their own paint buffer. A typical + example would be a layer which contains certain layerables (e.g. items) that need to be changed + and thus replotted regularly, while all other layerables on other layers stay static. By default, + only the topmost layer called "overlay" is in mode \ref lmBuffered, and contains the selection + rect. + + \see replot +*/ +void QCPLayer::setMode(QCPLayer::LayerMode mode) +{ + if (mMode != mode) + { + mMode = mode; + if (QSharedPointer pb = mPaintBuffer.toStrongRef()) + pb->setInvalidated(); + } +} + +/*! \internal + + Draws the contents of this layer with the provided \a painter. + + \see replot, drawToPaintBuffer +*/ +void QCPLayer::draw(QCPPainter *painter) +{ + foreach (QCPLayerable *child, mChildren) + { + if (child->realVisibility()) + { + painter->save(); + painter->setClipRect(child->clipRect().translated(0, -1)); + child->applyDefaultAntialiasingHint(painter); + child->draw(painter); + painter->restore(); + } + } +} + +/*! \internal + + Draws the contents of this layer into the paint buffer which is associated with this layer. The + association is established by the parent QCustomPlot, which manages all paint buffers (see \ref + QCustomPlot::setupPaintBuffers). + + \see draw +*/ +void QCPLayer::drawToPaintBuffer() +{ + if (QSharedPointer pb = mPaintBuffer.toStrongRef()) + { + if (QCPPainter *painter = pb->startPainting()) + { + if (painter->isActive()) + draw(painter); + else + qDebug() << Q_FUNC_INFO << "paint buffer returned inactive painter"; + delete painter; + pb->donePainting(); + } else + qDebug() << Q_FUNC_INFO << "paint buffer returned nullptr painter"; + } else + qDebug() << Q_FUNC_INFO << "no valid paint buffer associated with this layer"; +} + +/*! + If the layer mode (\ref setMode) is set to \ref lmBuffered, this method allows replotting only + the layerables on this specific layer, without the need to replot all other layers (as a call to + \ref QCustomPlot::replot would do). + + QCustomPlot also makes sure to replot all layers instead of only this one, if the layer ordering + or any layerable-layer-association has changed since the last full replot and any other paint + buffers were thus invalidated. + + If the layer mode is \ref lmLogical however, this method simply calls \ref QCustomPlot::replot on + the parent QCustomPlot instance. + + \see draw +*/ +void QCPLayer::replot() +{ + if (mMode == lmBuffered && !mParentPlot->hasInvalidatedPaintBuffers()) + { + if (QSharedPointer pb = mPaintBuffer.toStrongRef()) + { + pb->clear(Qt::transparent); + drawToPaintBuffer(); + pb->setInvalidated(false); // since layer is lmBuffered, we know only this layer is on buffer and we can reset invalidated flag + mParentPlot->update(); + } else + qDebug() << Q_FUNC_INFO << "no valid paint buffer associated with this layer"; + } else + mParentPlot->replot(); +} + /*! \internal Adds the \a layerable to the list of this layer. If \a prepend is set to true, the layerable will @@ -792,6 +1229,8 @@ void QCPLayer::addChild(QCPLayerable *layerable, bool prepend) mChildren.prepend(layerable); else mChildren.append(layerable); + if (QSharedPointer pb = mPaintBuffer.toStrongRef()) + pb->setInvalidated(); } else qDebug() << Q_FUNC_INFO << "layerable is already child of this layer" << reinterpret_cast(layerable); } @@ -807,7 +1246,11 @@ void QCPLayer::addChild(QCPLayerable *layerable, bool prepend) */ void QCPLayer::removeChild(QCPLayerable *layerable) { - if (!mChildren.removeOne(layerable)) + if (mChildren.removeOne(layerable)) + { + if (QSharedPointer pb = mPaintBuffer.toStrongRef()) + pb->setInvalidated(); + } else qDebug() << Q_FUNC_INFO << "layerable is not child of this layer" << reinterpret_cast(layerable); } @@ -837,9 +1280,10 @@ void QCPLayer::removeChild(QCPLayerable *layerable) only get drawn if their parent layerables are visible, too. Note that a parent layerable is not necessarily also the QObject parent for memory management. - Further, a layerable doesn't always have a parent layerable, so this function may return 0. + Further, a layerable doesn't always have a parent layerable, so this function may return \c + nullptr. - A parent layerable is set implicitly with when placed inside layout elements and doesn't need to be + A parent layerable is set implicitly when placed inside layout elements and doesn't need to be set manually by the user. */ @@ -858,9 +1302,9 @@ void QCPLayer::removeChild(QCPLayerable *layerable) default antialiasing hint. First example: QCPGraph has multiple entities that have an antialiasing setting: The graph - line, fills, scatters and error bars. Those can be configured via QCPGraph::setAntialiased, - QCPGraph::setAntialiasedFill, QCPGraph::setAntialiasedScatters etc. Consequently, there isn't - only the QCPGraph::applyDefaultAntialiasingHint function (which corresponds to the graph line's + line, fills and scatters. Those can be configured via QCPGraph::setAntialiased, + QCPGraph::setAntialiasedFill and QCPGraph::setAntialiasedScatters. Consequently, there isn't only + the QCPGraph::applyDefaultAntialiasingHint function (which corresponds to the graph line's antialiasing), but specialized ones like QCPGraph::applyFillAntialiasingHint and QCPGraph::applyScattersAntialiasingHint. So before drawing one of those entities, QCPGraph::draw calls the respective specialized applyAntialiasingHint function. @@ -909,20 +1353,22 @@ void QCPLayer::removeChild(QCPLayerable *layerable) targetLayer is an empty string, it places itself on the current layer of the plot (see \ref QCustomPlot::setCurrentLayer). - It is possible to provide 0 as \a plot. In that case, you should assign a parent plot at a later - time with \ref initializeParentPlot. + It is possible to provide \c nullptr as \a plot. In that case, you should assign a parent plot at + a later time with \ref initializeParentPlot. - The layerable's parent layerable is set to \a parentLayerable, if provided. Direct layerable parents - are mainly used to control visibility in a hierarchy of layerables. This means a layerable is - only drawn, if all its ancestor layerables are also visible. Note that \a parentLayerable does - not become the QObject-parent (for memory management) of this layerable, \a plot does. + The layerable's parent layerable is set to \a parentLayerable, if provided. Direct layerable + parents are mainly used to control visibility in a hierarchy of layerables. This means a + layerable is only drawn, if all its ancestor layerables are also visible. Note that \a + parentLayerable does not become the QObject-parent (for memory management) of this layerable, \a + plot does. It is not uncommon to set the QObject-parent to something else in the constructors of + QCPLayerable subclasses, to guarantee a working destruction hierarchy. */ QCPLayerable::QCPLayerable(QCustomPlot *plot, QString targetLayer, QCPLayerable *parentLayerable) : QObject(plot), mVisible(true), mParentPlot(plot), mParentLayerable(parentLayerable), - mLayer(0), + mLayer(nullptr), mAntialiased(true) { if (mParentPlot) @@ -939,7 +1385,7 @@ QCPLayerable::~QCPLayerable() if (mLayer) { mLayer->removeChild(this); - mLayer = 0; + mLayer = nullptr; } } @@ -957,7 +1403,10 @@ void QCPLayerable::setVisible(bool on) Sets the \a layer of this layerable object. The object will be placed on top of the other objects already on \a layer. - Returns true on success, i.e. if \a layer is a valid layer. + If \a layer is 0, this layerable will not be on any layer and thus not appear in the plot (or + interact/receive events). + + Returns true if the layer of this layerable was successfully changed to \a layer. */ bool QCPLayerable::setLayer(QCPLayer *layer) { @@ -999,16 +1448,13 @@ void QCPLayerable::setAntialiased(bool enabled) /*! Returns whether this layerable is visible, taking the visibility of the layerable parent and the - visibility of the layer this layerable is on into account. This is the method that is consulted - to decide whether a layerable shall be drawn or not. + visibility of this layerable's layer into account. This is the method that is consulted to decide + whether a layerable shall be drawn or not. If this layerable has a direct layerable parent (usually set via hierarchies implemented in - subclasses, like in the case of QCPLayoutElement), this function returns true only if this + subclasses, like in the case of \ref QCPLayoutElement), this function returns true only if this layerable has its visibility set to true and the parent layerable's \ref realVisibility returns true. - - If this layerable doesn't have a direct layerable parent, returns the state of this layerable's - visibility. */ bool QCPLayerable::realVisibility() const { @@ -1034,7 +1480,7 @@ bool QCPLayerable::realVisibility() const The actual setting of the selection state is not done by this function. This is handled by the parent QCustomPlot when the mouseReleaseEvent occurs, and the finally selected object is notified - via the selectEvent/deselectEvent methods. + via the \ref selectEvent/\ref deselectEvent methods. \a details is an optional output parameter. Every layerable subclass may place any information in \a details. This information will be passed to \ref selectEvent when the parent QCustomPlot @@ -1045,9 +1491,14 @@ bool QCPLayerable::realVisibility() const placed in \a details. So in the subsequent \ref selectEvent, the decision which part was selected doesn't have to be done a second time for a single selection operation. - You may pass 0 as \a details to indicate that you are not interested in those selection details. + In the case of 1D Plottables (\ref QCPAbstractPlottable1D, like \ref QCPGraph or \ref QCPBars) \a + details will be set to a \ref QCPDataSelection, describing the closest data point to \a pos. + + You may pass \c nullptr as \a details to indicate that you are not interested in those selection + details. - \see selectEvent, deselectEvent, QCustomPlot::setInteractions + \see selectEvent, deselectEvent, mousePressEvent, wheelEvent, QCustomPlot::setInteractions, + QCPAbstractPlottable1D::selectTestRect */ double QCPLayerable::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { @@ -1060,11 +1511,11 @@ double QCPLayerable::selectTest(const QPointF &pos, bool onlySelectable, QVarian /*! \internal Sets the parent plot of this layerable. Use this function once to set the parent plot if you have - passed 0 in the constructor. It can not be used to move a layerable from one QCustomPlot to - another one. + passed \c nullptr in the constructor. It can not be used to move a layerable from one QCustomPlot + to another one. - Note that, unlike when passing a non-null parent plot in the constructor, this function does not - make \a parentPlot the QObject-parent of this layerable. If you want this, call + Note that, unlike when passing a non \c nullptr parent plot in the constructor, this function + does not make \a parentPlot the QObject-parent of this layerable. If you want this, call QObject::setParent(\a parentPlot) in addition to this function. Further, you will probably want to set a layer (\ref setLayer) after calling this function, to @@ -1157,8 +1608,8 @@ void QCPLayerable::applyAntialiasingHint(QCPPainter *painter, bool localAntialia /*! \internal This function is called by \ref initializeParentPlot, to allow subclasses to react on the setting - of a parent plot. This is the case when 0 was passed as parent plot in the constructor, and the - parent plot is set at a later time. + of a parent plot. This is the case when \c nullptr was passed as parent plot in the constructor, + and the parent plot is set at a later time. For example, QCPLayoutElement/QCPLayout hierarchies may be created independently of any QCustomPlot at first. When they are then added to a layout inside the QCustomPlot, the top level @@ -1205,7 +1656,7 @@ QRect QCPLayerable::clipRect() const if (mParentPlot) return mParentPlot->viewport(); else - return QRect(); + return {}; } /*! \internal @@ -1261,6 +1712,131 @@ void QCPLayerable::deselectEvent(bool *selectionStateChanged) Q_UNUSED(selectionStateChanged) } +/*! + This event gets called when the user presses a mouse button while the cursor is over the + layerable. Whether a cursor is over the layerable is decided by a preceding call to \ref + selectTest. + + The current pixel position of the cursor on the QCustomPlot widget is accessible via \c + event->pos(). The parameter \a details contains layerable-specific details about the hit, which + were generated in the previous call to \ref selectTest. For example, One-dimensional plottables + like \ref QCPGraph or \ref QCPBars convey the clicked data point in the \a details parameter, as + \ref QCPDataSelection packed as QVariant. Multi-part objects convey the specific \c + SelectablePart that was hit (e.g. \ref QCPAxis::SelectablePart in the case of axes). + + QCustomPlot uses an event propagation system that works the same as Qt's system. If your + layerable doesn't reimplement the \ref mousePressEvent or explicitly calls \c event->ignore() in + its reimplementation, the event will be propagated to the next layerable in the stacking order. + + Once a layerable has accepted the \ref mousePressEvent, it is considered the mouse grabber and + will receive all following calls to \ref mouseMoveEvent or \ref mouseReleaseEvent for this mouse + interaction (a "mouse interaction" in this context ends with the release). + + The default implementation does nothing except explicitly ignoring the event with \c + event->ignore(). + + \see mouseMoveEvent, mouseReleaseEvent, mouseDoubleClickEvent, wheelEvent +*/ +void QCPLayerable::mousePressEvent(QMouseEvent *event, const QVariant &details) +{ + Q_UNUSED(details) + event->ignore(); +} + +/*! + This event gets called when the user moves the mouse while holding a mouse button, after this + layerable has become the mouse grabber by accepting the preceding \ref mousePressEvent. + + The current pixel position of the cursor on the QCustomPlot widget is accessible via \c + event->pos(). The parameter \a startPos indicates the position where the initial \ref + mousePressEvent occurred, that started the mouse interaction. + + The default implementation does nothing. + + \see mousePressEvent, mouseReleaseEvent, mouseDoubleClickEvent, wheelEvent +*/ +void QCPLayerable::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) +{ + Q_UNUSED(startPos) + event->ignore(); +} + +/*! + This event gets called when the user releases the mouse button, after this layerable has become + the mouse grabber by accepting the preceding \ref mousePressEvent. + + The current pixel position of the cursor on the QCustomPlot widget is accessible via \c + event->pos(). The parameter \a startPos indicates the position where the initial \ref + mousePressEvent occurred, that started the mouse interaction. + + The default implementation does nothing. + + \see mousePressEvent, mouseMoveEvent, mouseDoubleClickEvent, wheelEvent +*/ +void QCPLayerable::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) +{ + Q_UNUSED(startPos) + event->ignore(); +} + +/*! + This event gets called when the user presses the mouse button a second time in a double-click, + while the cursor is over the layerable. Whether a cursor is over the layerable is decided by a + preceding call to \ref selectTest. + + The \ref mouseDoubleClickEvent is called instead of the second \ref mousePressEvent. So in the + case of a double-click, the event succession is + pressEvent – releaseEvent – doubleClickEvent – releaseEvent. + + The current pixel position of the cursor on the QCustomPlot widget is accessible via \c + event->pos(). The parameter \a details contains layerable-specific details about the hit, which + were generated in the previous call to \ref selectTest. For example, One-dimensional plottables + like \ref QCPGraph or \ref QCPBars convey the clicked data point in the \a details parameter, as + \ref QCPDataSelection packed as QVariant. Multi-part objects convey the specific \c + SelectablePart that was hit (e.g. \ref QCPAxis::SelectablePart in the case of axes). + + Similarly to \ref mousePressEvent, once a layerable has accepted the \ref mouseDoubleClickEvent, + it is considered the mouse grabber and will receive all following calls to \ref mouseMoveEvent + and \ref mouseReleaseEvent for this mouse interaction (a "mouse interaction" in this context ends + with the release). + + The default implementation does nothing except explicitly ignoring the event with \c + event->ignore(). + + \see mousePressEvent, mouseMoveEvent, mouseReleaseEvent, wheelEvent +*/ +void QCPLayerable::mouseDoubleClickEvent(QMouseEvent *event, const QVariant &details) +{ + Q_UNUSED(details) + event->ignore(); +} + +/*! + This event gets called when the user turns the mouse scroll wheel while the cursor is over the + layerable. Whether a cursor is over the layerable is decided by a preceding call to \ref + selectTest. + + The current pixel position of the cursor on the QCustomPlot widget is accessible via \c + event->pos(). + + The \c event->angleDelta() indicates how far the mouse wheel was turned, which is usually +/- 120 + for single rotation steps. However, if the mouse wheel is turned rapidly, multiple steps may + accumulate to one event, making the delta larger. On the other hand, if the wheel has very smooth + steps or none at all, the delta may be smaller. + + The default implementation does nothing. + + \see mousePressEvent, mouseMoveEvent, mouseReleaseEvent, mouseDoubleClickEvent +*/ +void QCPLayerable::wheelEvent(QWheelEvent *event) +{ + event->ignore(); +} +/* end of 'src/layer.cpp' */ + + +/* including file 'src/axis/range.cpp' */ +/* modified 2022-11-06T12:45:56, size 12221 */ //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////// QCPRange @@ -1274,10 +1850,60 @@ void QCPLayerable::deselectEvent(bool *selectionStateChanged) \see QCPAxis::setRange */ +/* start of documentation of inline functions */ + +/*! \fn double QCPRange::size() const + + Returns the size of the range, i.e. \a upper-\a lower +*/ + +/*! \fn double QCPRange::center() const + + Returns the center of the range, i.e. (\a upper+\a lower)*0.5 +*/ + +/*! \fn void QCPRange::normalize() + + Makes sure \a lower is numerically smaller than \a upper. If this is not the case, the values are + swapped. +*/ + +/*! \fn bool QCPRange::contains(double value) const + + Returns true when \a value lies within or exactly on the borders of the range. +*/ + +/*! \fn QCPRange &QCPRange::operator+=(const double& value) + + Adds \a value to both boundaries of the range. +*/ + +/*! \fn QCPRange &QCPRange::operator-=(const double& value) + + Subtracts \a value from both boundaries of the range. +*/ + +/*! \fn QCPRange &QCPRange::operator*=(const double& value) + + Multiplies both boundaries of the range by \a value. +*/ + +/*! \fn QCPRange &QCPRange::operator/=(const double& value) + + Divides both boundaries of the range by \a value. +*/ + +/* end of documentation of inline functions */ + /*! Minimum range size (\a upper - \a lower) the range changing functions will accept. Smaller intervals would cause errors due to the 11-bit exponent of double precision numbers, corresponding to a minimum magnitude of roughly 1e-308. + + \warning Do not use this constant to indicate "arbitrarily small" values in plotting logic (as + values that will appear in the plot)! It is intended only as a bound to compare against, e.g. to + prevent axis ranges from obtaining underflowing ranges. + \see validRange, maxRange */ const double QCPRange::minRange = 1e-280; @@ -1286,8 +1912,11 @@ const double QCPRange::minRange = 1e-280; Maximum values (negative and positive) the range will accept in range-changing functions. Larger absolute values would cause errors due to the 11-bit exponent of double precision numbers, corresponding to a maximum magnitude of roughly 1e308. - Since the number of planck-volumes in the entire visible universe is only ~1e183, this should - be enough. + + \warning Do not use this constant to indicate "arbitrarily large" values in plotting logic (as + values that will appear in the plot)! It is intended only as a bound to compare against, e.g. to + prevent axis ranges from obtaining overflowing ranges. + \see validRange, minRange */ const double QCPRange::maxRange = 1e250; @@ -1302,7 +1931,11 @@ QCPRange::QCPRange() : } /*! \overload + Constructs a range with the specified \a lower and \a upper values. + + The resulting range will be normalized (see \ref normalize), so if \a lower is not numerically + smaller than \a upper, they will be swapped. */ QCPRange::QCPRange(double lower, double upper) : lower(lower), @@ -1311,53 +1944,55 @@ QCPRange::QCPRange(double lower, double upper) : normalize(); } -/*! - Returns the size of the range, i.e. \a upper-\a lower -*/ -double QCPRange::size() const -{ - return upper-lower; -} +/*! \overload -/*! - Returns the center of the range, i.e. (\a upper+\a lower)*0.5 -*/ -double QCPRange::center() const -{ - return (upper+lower)*0.5; -} + Expands this range such that \a otherRange is contained in the new range. It is assumed that both + this range and \a otherRange are normalized (see \ref normalize). -/*! - Makes sure \a lower is numerically smaller than \a upper. If this is not the case, the values - are swapped. -*/ -void QCPRange::normalize() -{ - if (lower > upper) - qSwap(lower, upper); -} + If this range contains NaN as lower or upper bound, it will be replaced by the respective bound + of \a otherRange. -/*! - Expands this range such that \a otherRange is contained in the new range. It is assumed that both - this range and \a otherRange are normalized (see \ref normalize). - If \a otherRange is already inside the current range, this function does nothing. - + \see expanded */ void QCPRange::expand(const QCPRange &otherRange) { - if (lower > otherRange.lower) + if (lower > otherRange.lower || qIsNaN(lower)) lower = otherRange.lower; - if (upper < otherRange.upper) + if (upper < otherRange.upper || qIsNaN(upper)) upper = otherRange.upper; } +/*! \overload + + Expands this range such that \a includeCoord is contained in the new range. It is assumed that + this range is normalized (see \ref normalize). + + If this range contains NaN as lower or upper bound, the respective bound will be set to \a + includeCoord. + + If \a includeCoord is already inside the current range, this function does nothing. + + \see expand +*/ +void QCPRange::expand(double includeCoord) +{ + if (lower > includeCoord || qIsNaN(lower)) + lower = includeCoord; + if (upper < includeCoord || qIsNaN(upper)) + upper = includeCoord; +} + + +/*! \overload -/*! Returns an expanded range that contains this and \a otherRange. It is assumed that both this range and \a otherRange are normalized (see \ref normalize). - + + If this range contains NaN as lower or upper bound, the returned range's bound will be taken from + \a otherRange. + \see expand */ QCPRange QCPRange::expanded(const QCPRange &otherRange) const @@ -1367,6 +2002,54 @@ QCPRange QCPRange::expanded(const QCPRange &otherRange) const return result; } +/*! \overload + + Returns an expanded range that includes the specified \a includeCoord. It is assumed that this + range is normalized (see \ref normalize). + + If this range contains NaN as lower or upper bound, the returned range's bound will be set to \a + includeCoord. + + \see expand +*/ +QCPRange QCPRange::expanded(double includeCoord) const +{ + QCPRange result = *this; + result.expand(includeCoord); + return result; +} + +/*! + Returns this range, possibly modified to not exceed the bounds provided as \a lowerBound and \a + upperBound. If possible, the size of the current range is preserved in the process. + + If the range shall only be bounded at the lower side, you can set \a upperBound to \ref + QCPRange::maxRange. If it shall only be bounded at the upper side, set \a lowerBound to -\ref + QCPRange::maxRange. +*/ +QCPRange QCPRange::bounded(double lowerBound, double upperBound) const +{ + if (lowerBound > upperBound) + qSwap(lowerBound, upperBound); + + QCPRange result(lower, upper); + if (result.lower < lowerBound) + { + result.lower = lowerBound; + result.upper = lowerBound + size(); + if (result.upper > upperBound || qFuzzyCompare(size(), upperBound-lowerBound)) + result.upper = upperBound; + } else if (result.upper > upperBound) + { + result.upper = upperBound; + result.lower = upperBound - size(); + if (result.lower < lowerBound || qFuzzyCompare(size(), upperBound-lowerBound)) + result.lower = lowerBound; + } + + return result; +} + /*! Returns a sanitized version of the range. Sanitized means for logarithmic scales, that the range won't span the positive and negative sign domain, i.e. contain zero. Further @@ -1435,14 +2118,6 @@ QCPRange QCPRange::sanitizedForLinScale() const return sanitizedRange; } -/*! - Returns true when \a value lies within or exactly on the borders of the range. -*/ -bool QCPRange::contains(double value) const -{ - return value >= lower && value <= upper; -} - /*! Checks, whether the specified range is within valid bounds, which are defined as QCPRange::maxRange and QCPRange::minRange. @@ -1453,17 +2128,12 @@ bool QCPRange::contains(double value) const */ bool QCPRange::validRange(double lower, double upper) { - /* return (lower > -maxRange && upper < maxRange && qAbs(lower-upper) > minRange && - (lower < -minRange || lower > minRange) && - (upper < -minRange || upper > minRange)); - */ - return (lower > -maxRange && - upper < maxRange && - qAbs(lower-upper) > minRange && - qAbs(lower-upper) < maxRange); + qAbs(lower-upper) < maxRange && + !(lower > 0 && qIsInf(upper/lower)) && + !(upper < 0 && qIsInf(lower/upper))); } /*! @@ -1477,2277 +2147,10963 @@ bool QCPRange::validRange(double lower, double upper) */ bool QCPRange::validRange(const QCPRange &range) { - /* return (range.lower > -maxRange && range.upper < maxRange && qAbs(range.lower-range.upper) > minRange && qAbs(range.lower-range.upper) < maxRange && - (range.lower < -minRange || range.lower > minRange) && - (range.upper < -minRange || range.upper > minRange)); - */ - return (range.lower > -maxRange && - range.upper < maxRange && - qAbs(range.lower-range.upper) > minRange && - qAbs(range.lower-range.upper) < maxRange); + !(range.lower > 0 && qIsInf(range.upper/range.lower)) && + !(range.upper < 0 && qIsInf(range.lower/range.upper))); } +/* end of 'src/axis/range.cpp' */ + +/* including file 'src/selection.cpp' */ +/* modified 2022-11-06T12:45:56, size 21837 */ //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPMarginGroup +//////////////////// QCPDataRange //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPMarginGroup - \brief A margin group allows synchronization of margin sides if working with multiple layout elements. +/*! \class QCPDataRange + \brief Describes a data range given by begin and end index - QCPMarginGroup allows you to tie a margin side of two or more layout elements together, such that - they will all have the same size, based on the largest required margin in the group. + QCPDataRange holds two integers describing the begin (\ref setBegin) and end (\ref setEnd) index + of a contiguous set of data points. The \a end index corresponds to the data point just after the + last data point of the data range, like in standard iterators. + + Data Ranges are not bound to a certain plottable, thus they can be freely exchanged, created and + modified. If a non-contiguous data set shall be described, the class \ref QCPDataSelection is + used, which holds and manages multiple instances of \ref QCPDataRange. In most situations, \ref + QCPDataSelection is thus used. - \n - \image html QCPMarginGroup.png "Demonstration of QCPMarginGroup" - \n + Both \ref QCPDataRange and \ref QCPDataSelection offer convenience methods to work with them, + e.g. \ref bounded, \ref expanded, \ref intersects, \ref intersection, \ref adjusted, \ref + contains. Further, addition and subtraction operators (defined in \ref QCPDataSelection) can be + used to join/subtract data ranges and data selections (or mixtures), to retrieve a corresponding + \ref QCPDataSelection. - In certain situations it is desirable that margins at specific sides are synchronized across - layout elements. For example, if one QCPAxisRect is below another one in a grid layout, it will - provide a cleaner look to the user if the left and right margins of the two axis rects are of the - same size. The left axis of the top axis rect will then be at the same horizontal position as the - left axis of the lower axis rect, making them appear aligned. The same applies for the right - axes. This is what QCPMarginGroup makes possible. + %QCustomPlot's \ref dataselection "data selection mechanism" is based on \ref QCPDataSelection and + QCPDataRange. - To add/remove a specific side of a layout element to/from a margin group, use the \ref - QCPLayoutElement::setMarginGroup method. To completely break apart the margin group, either call - \ref clear, or just delete the margin group. + \note Do not confuse \ref QCPDataRange with \ref QCPRange. A \ref QCPRange describes an interval + in floating point plot coordinates, e.g. the current axis range. +*/ + +/* start documentation of inline functions */ + +/*! \fn int QCPDataRange::size() const - \section QCPMarginGroup-example Example + Returns the number of data points described by this data range. This is equal to the end index + minus the begin index. - First create a margin group: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpmargingroup-creation-1 - Then set this group on the layout element sides: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpmargingroup-creation-2 - Here, we've used the first two axis rects of the plot and synchronized their left margins with - each other and their right margins with each other. + \see length */ -/* start documentation of inline functions */ +/*! \fn int QCPDataRange::length() const + + Returns the number of data points described by this data range. Equivalent to \ref size. +*/ -/*! \fn QList QCPMarginGroup::elements(QCP::MarginSide side) const +/*! \fn void QCPDataRange::setBegin(int begin) - Returns a list of all layout elements that have their margin \a side associated with this margin - group. + Sets the begin of this data range. The \a begin index points to the first data point that is part + of the data range. + + No checks or corrections are made to ensure the resulting range is valid (\ref isValid). + + \see setEnd +*/ + +/*! \fn void QCPDataRange::setEnd(int end) + + Sets the end of this data range. The \a end index points to the data point just after the last + data point that is part of the data range. + + No checks or corrections are made to ensure the resulting range is valid (\ref isValid). + + \see setBegin +*/ + +/*! \fn bool QCPDataRange::isValid() const + + Returns whether this range is valid. A valid range has a begin index greater or equal to 0, and + an end index greater or equal to the begin index. + + \note Invalid ranges should be avoided and are never the result of any of QCustomPlot's methods + (unless they are themselves fed with invalid ranges). Do not pass invalid ranges to QCustomPlot's + methods. The invalid range is not inherently prevented in QCPDataRange, to allow temporary + invalid begin/end values while manipulating the range. An invalid range is not necessarily empty + (\ref isEmpty), since its \ref length can be negative and thus non-zero. +*/ + +/*! \fn bool QCPDataRange::isEmpty() const + + Returns whether this range is empty, i.e. whether its begin index equals its end index. + + \see size, length +*/ + +/*! \fn QCPDataRange QCPDataRange::adjusted(int changeBegin, int changeEnd) const + + Returns a data range where \a changeBegin and \a changeEnd were added to the begin and end + indices, respectively. */ /* end documentation of inline functions */ /*! - Creates a new QCPMarginGroup instance in \a parentPlot. + Creates an empty QCPDataRange, with begin and end set to 0. */ -QCPMarginGroup::QCPMarginGroup(QCustomPlot *parentPlot) : - QObject(parentPlot), - mParentPlot(parentPlot) +QCPDataRange::QCPDataRange() : + mBegin(0), + mEnd(0) { - mChildren.insert(QCP::msLeft, QList()); - mChildren.insert(QCP::msRight, QList()); - mChildren.insert(QCP::msTop, QList()); - mChildren.insert(QCP::msBottom, QList()); } -QCPMarginGroup::~QCPMarginGroup() +/*! + Creates a QCPDataRange, initialized with the specified \a begin and \a end. + + No checks or corrections are made to ensure the resulting range is valid (\ref isValid). +*/ +QCPDataRange::QCPDataRange(int begin, int end) : + mBegin(begin), + mEnd(end) { - clear(); } /*! - Returns whether this margin group is empty. If this function returns true, no layout elements use - this margin group to synchronize margin sides. + Returns a data range that matches this data range, except that parts exceeding \a other are + excluded. + + This method is very similar to \ref intersection, with one distinction: If this range and the \a + other range share no intersection, the returned data range will be empty with begin and end set + to the respective boundary side of \a other, at which this range is residing. (\ref intersection + would just return a range with begin and end set to 0.) */ -bool QCPMarginGroup::isEmpty() const +QCPDataRange QCPDataRange::bounded(const QCPDataRange &other) const { - QHashIterator > it(mChildren); - while (it.hasNext()) + QCPDataRange result(intersection(other)); + if (result.isEmpty()) // no intersection, preserve respective bounding side of otherRange as both begin and end of return value { - it.next(); - if (!it.value().isEmpty()) - return false; + if (mEnd <= other.mBegin) + result = QCPDataRange(other.mBegin, other.mBegin); + else + result = QCPDataRange(other.mEnd, other.mEnd); } - return true; + return result; } /*! - Clears this margin group. The synchronization of the margin sides that use this margin group is - lifted and they will use their individual margin sizes again. + Returns a data range that contains both this data range as well as \a other. */ -void QCPMarginGroup::clear() +QCPDataRange QCPDataRange::expanded(const QCPDataRange &other) const { - // make all children remove themselves from this margin group: - QHashIterator > it(mChildren); - while (it.hasNext()) - { - it.next(); - const QList elements = it.value(); - for (int i=elements.size()-1; i>=0; --i) - elements.at(i)->setMarginGroup(it.key(), 0); // removes itself from mChildren via removeChild - } + return {qMin(mBegin, other.mBegin), qMax(mEnd, other.mEnd)}; } -/*! \internal +/*! + Returns the data range which is contained in both this data range and \a other. - Returns the synchronized common margin for \a side. This is the margin value that will be used by - the layout element on the respective side, if it is part of this margin group. + This method is very similar to \ref bounded, with one distinction: If this range and the \a other + range share no intersection, the returned data range will be empty with begin and end set to 0. + (\ref bounded would return a range with begin and end set to one of the boundaries of \a other, + depending on which side this range is on.) - The common margin is calculated by requesting the automatic margin (\ref - QCPLayoutElement::calculateAutoMargin) of each element associated with \a side in this margin - group, and choosing the largest returned value. (QCPLayoutElement::minimumMargins is taken into - account, too.) + \see QCPDataSelection::intersection */ -int QCPMarginGroup::commonMargin(QCP::MarginSide side) const +QCPDataRange QCPDataRange::intersection(const QCPDataRange &other) const { - // query all automatic margins of the layout elements in this margin group side and find maximum: - int result = 0; - const QList elements = mChildren.value(side); - for (int i=0; iautoMargins().testFlag(side)) - continue; - int m = qMax(elements.at(i)->calculateAutoMargin(side), QCP::getMarginValue(elements.at(i)->minimumMargins(), side)); - if (m > result) - result = m; - } - return result; + QCPDataRange result(qMax(mBegin, other.mBegin), qMin(mEnd, other.mEnd)); + if (result.isValid()) + return result; + else + return {}; } -/*! \internal - - Adds \a element to the internal list of child elements, for the margin \a side. +/*! + Returns whether this data range and \a other share common data points. - This function does not modify the margin group property of \a element. + \see intersection, contains */ -void QCPMarginGroup::addChild(QCP::MarginSide side, QCPLayoutElement *element) +bool QCPDataRange::intersects(const QCPDataRange &other) const { - if (!mChildren[side].contains(element)) - mChildren[side].append(element); - else - qDebug() << Q_FUNC_INFO << "element is already child of this margin group side" << reinterpret_cast(element); + return !( (mBegin > other.mBegin && mBegin >= other.mEnd) || + (mEnd <= other.mBegin && mEnd < other.mEnd) ); } -/*! \internal - - Removes \a element from the internal list of child elements, for the margin \a side. +/*! + Returns whether all data points of \a other are also contained inside this data range. - This function does not modify the margin group property of \a element. + \see intersects */ -void QCPMarginGroup::removeChild(QCP::MarginSide side, QCPLayoutElement *element) +bool QCPDataRange::contains(const QCPDataRange &other) const { - if (!mChildren[side].removeOne(element)) - qDebug() << Q_FUNC_INFO << "element is not child of this margin group side" << reinterpret_cast(element); + return mBegin <= other.mBegin && mEnd >= other.mEnd; } + //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPLayoutElement +//////////////////// QCPDataSelection //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPLayoutElement - \brief The abstract base class for all objects that form \ref thelayoutsystem "the layout system". +/*! \class QCPDataSelection + \brief Describes a data set by holding multiple QCPDataRange instances - This is an abstract base class. As such, it can't be instantiated directly, rather use one of its subclasses. + QCPDataSelection manages multiple instances of QCPDataRange in order to represent any (possibly + disjoint) set of data selection. - A Layout element is a rectangular object which can be placed in layouts. It has an outer rect - (QCPLayoutElement::outerRect) and an inner rect (\ref QCPLayoutElement::rect). The difference - between outer and inner rect is called its margin. The margin can either be set to automatic or - manual (\ref setAutoMargins) on a per-side basis. If a side is set to manual, that margin can be - set explicitly with \ref setMargins and will stay fixed at that value. If it's set to automatic, - the layout element subclass will control the value itself (via \ref calculateAutoMargin). + The data selection can be modified with addition and subtraction operators which take + QCPDataSelection and QCPDataRange instances, as well as methods such as \ref addDataRange and + \ref clear. Read access is provided by \ref dataRange, \ref dataRanges, \ref dataRangeCount, etc. - Layout elements can be placed in layouts (base class QCPLayout) like QCPLayoutGrid. The top level - layout is reachable via \ref QCustomPlot::plotLayout, and is a \ref QCPLayoutGrid. Since \ref - QCPLayout itself derives from \ref QCPLayoutElement, layouts can be nested. + The method \ref simplify is used to join directly adjacent or even overlapping QCPDataRange + instances. QCPDataSelection automatically simplifies when using the addition/subtraction + operators. The only case when \ref simplify is left to the user, is when calling \ref + addDataRange, with the parameter \a simplify explicitly set to false. This is useful if many data + ranges will be added to the selection successively and the overhead for simplifying after each + iteration shall be avoided. In this case, you should make sure to call \ref simplify after + completing the operation. - Thus in QCustomPlot one can divide layout elements into two categories: The ones that are - invisible by themselves, because they don't draw anything. Their only purpose is to manage the - position and size of other layout elements. This category of layout elements usually use - QCPLayout as base class. Then there is the category of layout elements which actually draw - something. For example, QCPAxisRect, QCPLegend and QCPPlotTitle are of this category. This does - not necessarily mean that the latter category can't have child layout elements. QCPLegend for - instance, actually derives from QCPLayoutGrid and the individual legend items are child layout - elements in the grid layout. -*/ - -/* start documentation of inline functions */ - -/*! \fn QCPLayout *QCPLayoutElement::layout() const + Use \ref enforceType to bring the data selection into a state complying with the constraints for + selections defined in \ref QCP::SelectionType. - Returns the parent layout of this layout element. -*/ - -/*! \fn QRect QCPLayoutElement::rect() const + %QCustomPlot's \ref dataselection "data selection mechanism" is based on QCPDataSelection and + QCPDataRange. - Returns the inner rect of this layout element. The inner rect is the outer rect (\ref - setOuterRect) shrinked by the margins (\ref setMargins, \ref setAutoMargins). + \section qcpdataselection-iterating Iterating over a data selection - In some cases, the area between outer and inner rect is left blank. In other cases the margin - area is used to display peripheral graphics while the main content is in the inner rect. This is - where automatic margin calculation becomes interesting because it allows the layout element to - adapt the margins to the peripheral graphics it wants to draw. For example, \ref QCPAxisRect - draws the axis labels and tick labels in the margin area, thus needs to adjust the margins (if - \ref setAutoMargins is enabled) according to the space required by the labels of the axes. -*/ - -/*! \fn virtual void QCPLayoutElement::mousePressEvent(QMouseEvent *event) + As an example, the following code snippet calculates the average value of a graph's data + \ref QCPAbstractPlottable::selection "selection": - This event is called, if the mouse was pressed while being inside the outer rect of this layout - element. -*/ - -/*! \fn virtual void QCPLayoutElement::mouseMoveEvent(QMouseEvent *event) + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpdataselection-iterating-1 - This event is called, if the mouse is moved inside the outer rect of this layout element. */ -/*! \fn virtual void QCPLayoutElement::mouseReleaseEvent(QMouseEvent *event) +/* start documentation of inline functions */ + +/*! \fn int QCPDataSelection::dataRangeCount() const + + Returns the number of ranges that make up the data selection. The ranges can be accessed by \ref + dataRange via their index. - This event is called, if the mouse was previously pressed inside the outer rect of this layout - element and is now released. + \see dataRange, dataPointCount */ -/*! \fn virtual void QCPLayoutElement::mouseDoubleClickEvent(QMouseEvent *event) +/*! \fn QList QCPDataSelection::dataRanges() const - This event is called, if the mouse is double-clicked inside the outer rect of this layout - element. + Returns all data ranges that make up the data selection. If the data selection is simplified (the + usual state of the selection, see \ref simplify), the ranges are sorted by ascending data point + index. + + \see dataRange */ -/*! \fn virtual void QCPLayoutElement::wheelEvent(QWheelEvent *event) +/*! \fn bool QCPDataSelection::isEmpty() const + + Returns true if there are no data ranges, and thus no data points, in this QCPDataSelection + instance. - This event is called, if the mouse wheel is scrolled while the cursor is inside the rect of this - layout element. + \see dataRangeCount */ /* end documentation of inline functions */ /*! - Creates an instance of QCPLayoutElement and sets default values. + Creates an empty QCPDataSelection. */ -QCPLayoutElement::QCPLayoutElement(QCustomPlot *parentPlot) : - QCPLayerable(parentPlot), // parenthood is changed as soon as layout element gets inserted into a layout (except for top level layout) - mParentLayout(0), - mMinimumSize(), - mMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX), - mRect(0, 0, 0, 0), - mOuterRect(0, 0, 0, 0), - mMargins(0, 0, 0, 0), - mMinimumMargins(0, 0, 0, 0), - mAutoMargins(QCP::msAll) +QCPDataSelection::QCPDataSelection() { } -QCPLayoutElement::~QCPLayoutElement() +/*! + Creates a QCPDataSelection containing the provided \a range. +*/ +QCPDataSelection::QCPDataSelection(const QCPDataRange &range) { - setMarginGroup(QCP::msAll, 0); // unregister at margin groups, if there are any - // unregister at layout: - if (qobject_cast(mParentLayout)) // the qobject_cast is just a safeguard in case the layout forgets to call clear() in its dtor and this dtor is called by QObject dtor - mParentLayout->take(this); + mDataRanges.append(range); } /*! - Sets the outer rect of this layout element. If the layout element is inside a layout, the layout - sets the position and size of this layout element using this function. - - Calling this function externally has no effect, since the layout will overwrite any changes to - the outer rect upon the next replot. - - The layout element will adapt its inner \ref rect by applying the margins inward to the outer rect. - - \see rect + Returns true if this selection is identical (contains the same data ranges with the same begin + and end indices) to \a other. + + Note that both data selections must be in simplified state (the usual state of the selection, see + \ref simplify) for this operator to return correct results. */ -void QCPLayoutElement::setOuterRect(const QRect &rect) +bool QCPDataSelection::operator==(const QCPDataSelection &other) const { - if (mOuterRect != rect) + if (mDataRanges.size() != other.mDataRanges.size()) + return false; + for (int i=0; i= other.end()) + break; // since data ranges are sorted after the simplify() call, no ranges which contain other will come after this + + if (thisEnd > other.begin()) // ranges which don't fulfill this are entirely before other and can be ignored + { + if (thisBegin >= other.begin()) // range leading segment is encompassed + { + if (thisEnd <= other.end()) // range fully encompassed, remove completely + { + mDataRanges.removeAt(i); + continue; + } else // only leading segment is encompassed, trim accordingly + mDataRanges[i].setBegin(other.end()); + } else // leading segment is not encompassed + { + if (thisEnd <= other.end()) // only trailing segment is encompassed, trim accordingly + { + mDataRanges[i].setEnd(other.begin()); + } else // other lies inside this range, so split range + { + mDataRanges[i].setEnd(other.begin()); + mDataRanges.insert(i+1, QCPDataRange(other.end(), thisEnd)); + break; // since data ranges are sorted (and don't overlap) after simplify() call, we're done here + } + } + } + ++i; } + + return *this; } /*! - Sets on which sides the margin shall be calculated automatically. If a side is calculated - automatically, a minimum margin value may be provided with \ref setMinimumMargins. If a side is - set to be controlled manually, the value may be specified with \ref setMargins. - - Margin sides that are under automatic control may participate in a \ref QCPMarginGroup (see \ref - setMarginGroup), to synchronize (align) it with other layout elements in the plot. - - \see setMinimumMargins, setMargins + Returns the total number of data points contained in all data ranges that make up this data + selection. */ -void QCPLayoutElement::setAutoMargins(QCP::MarginSides sides) +int QCPDataSelection::dataPointCount() const { - mAutoMargins = sides; + int result = 0; + foreach (QCPDataRange dataRange, mDataRanges) + result += dataRange.length(); + return result; } /*! - Sets the minimum size for the inner \ref rect of this layout element. A parent layout tries to - respect the \a size here by changing row/column sizes in the layout accordingly. + Returns the data range with the specified \a index. - If the parent layout size is not sufficient to satisfy all minimum size constraints of its child - layout elements, the layout may set a size that is actually smaller than \a size. QCustomPlot - propagates the layout's size constraints to the outside by setting its own minimum QWidget size - accordingly, so violations of \a size should be exceptions. + If the data selection is simplified (the usual state of the selection, see \ref simplify), the + ranges are sorted by ascending data point index. + + \see dataRangeCount */ -void QCPLayoutElement::setMinimumSize(const QSize &size) +QCPDataRange QCPDataSelection::dataRange(int index) const { - if (mMinimumSize != size) + if (index >= 0 && index < mDataRanges.size()) { - mMinimumSize = size; - if (mParentLayout) - mParentLayout->sizeConstraintsChanged(); + return mDataRanges.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "index out of range:" << index; + return {}; } } -/*! \overload - - Sets the minimum size for the inner \ref rect of this layout element. +/*! + Returns a \ref QCPDataRange which spans the entire data selection, including possible + intermediate segments which are not part of the original data selection. */ -void QCPLayoutElement::setMinimumSize(int width, int height) +QCPDataRange QCPDataSelection::span() const { - setMinimumSize(QSize(width, height)); + if (isEmpty()) + return {}; + else + return {mDataRanges.first().begin(), mDataRanges.last().end()}; } /*! - Sets the maximum size for the inner \ref rect of this layout element. A parent layout tries to - respect the \a size here by changing row/column sizes in the layout accordingly. + Adds the given \a dataRange to this data selection. This is equivalent to the += operator but + allows disabling immediate simplification by setting \a simplify to false. This can improve + performance if adding a very large amount of data ranges successively. In this case, make sure to + call \ref simplify manually, after the operation. */ -void QCPLayoutElement::setMaximumSize(const QSize &size) +void QCPDataSelection::addDataRange(const QCPDataRange &dataRange, bool simplify) { - if (mMaximumSize != size) - { - mMaximumSize = size; - if (mParentLayout) - mParentLayout->sizeConstraintsChanged(); - } + mDataRanges.append(dataRange); + if (simplify) + this->simplify(); } -/*! \overload +/*! + Removes all data ranges. The data selection then contains no data points. - Sets the maximum size for the inner \ref rect of this layout element. + \ref isEmpty */ -void QCPLayoutElement::setMaximumSize(int width, int height) +void QCPDataSelection::clear() { - setMaximumSize(QSize(width, height)); + mDataRanges.clear(); } /*! - Sets the margin \a group of the specified margin \a sides. - - Margin groups allow synchronizing specified margins across layout elements, see the documentation - of \ref QCPMarginGroup. - - To unset the margin group of \a sides, set \a group to 0. - - Note that margin groups only work for margin sides that are set to automatic (\ref - setAutoMargins). + Sorts all data ranges by range begin index in ascending order, and then joins directly adjacent + or overlapping ranges. This can reduce the number of individual data ranges in the selection, and + prevents possible double-counting when iterating over the data points held by the data ranges. + + This method is automatically called when using the addition/subtraction operators. The only case + when \ref simplify is left to the user, is when calling \ref addDataRange, with the parameter \a + simplify explicitly set to false. */ -void QCPLayoutElement::setMarginGroup(QCP::MarginSides sides, QCPMarginGroup *group) +void QCPDataSelection::simplify() { - QVector sideVector; - if (sides.testFlag(QCP::msLeft)) sideVector.append(QCP::msLeft); - if (sides.testFlag(QCP::msRight)) sideVector.append(QCP::msRight); - if (sides.testFlag(QCP::msTop)) sideVector.append(QCP::msTop); - if (sides.testFlag(QCP::msBottom)) sideVector.append(QCP::msBottom); + // remove any empty ranges: + for (int i=mDataRanges.size()-1; i>=0; --i) + { + if (mDataRanges.at(i).isEmpty()) + mDataRanges.removeAt(i); + } + if (mDataRanges.isEmpty()) + return; - for (int i=0; i= mDataRanges.at(i).begin()) // range i overlaps/joins with i-1, so expand range i-1 appropriately and remove range i from list { - QCPMarginGroup *oldGroup = marginGroup(side); - if (oldGroup) // unregister at old group - oldGroup->removeChild(side, this); - - if (!group) // if setting to 0, remove hash entry. Else set hash entry to new group and register there - { - mMarginGroups.remove(side); - } else // setting to a new group - { - mMarginGroups[side] = group; - group->addChild(side, this); - } - } + mDataRanges[i-1].setEnd(qMax(mDataRanges.at(i-1).end(), mDataRanges.at(i).end())); + mDataRanges.removeAt(i); + } else + ++i; } } /*! - Updates the layout element and sub-elements. This function is automatically called before every - replot by the parent layout element. It is called multiple times, once for every \ref - UpdatePhase. The phases are run through in the order of the enum values. For details about what - happens at the different phases, see the documentation of \ref UpdatePhase. + Makes sure this data selection conforms to the specified \a type selection type. Before the type + is enforced, \ref simplify is called. - Layout elements that have child elements should call the \ref update method of their child - elements, and pass the current \a phase unchanged. + Depending on \a type, enforcing means adding new data points that were previously not part of the + selection, or removing data points from the selection. If the current selection already conforms + to \a type, the data selection is not changed. - The default implementation executes the automatic margin mechanism in the \ref upMargins phase. - Subclasses should make sure to call the base class implementation. + \see QCP::SelectionType */ -void QCPLayoutElement::update(UpdatePhase phase) +void QCPDataSelection::enforceType(QCP::SelectionType type) { - if (phase == upMargins) + simplify(); + switch (type) { - if (mAutoMargins != QCP::msNone) + case QCP::stNone: { - // set the margins of this layout element according to automatic margin calculation, either directly or via a margin group: - QMargins newMargins = mMargins; - QList allMarginSides = QList() << QCP::msLeft << QCP::msRight << QCP::msTop << QCP::msBottom; - foreach (QCP::MarginSide side, allMarginSides) + mDataRanges.clear(); + break; + } + case QCP::stWhole: + { + // whole selection isn't defined by data range, so don't change anything (is handled in plottable methods) + break; + } + case QCP::stSingleData: + { + // reduce all data ranges to the single first data point: + if (!mDataRanges.isEmpty()) { - if (mAutoMargins.testFlag(side)) // this side's margin shall be calculated automatically - { - if (mMarginGroups.contains(side)) - QCP::setMarginValue(newMargins, side, mMarginGroups[side]->commonMargin(side)); // this side is part of a margin group, so get the margin value from that group - else - QCP::setMarginValue(newMargins, side, calculateAutoMargin(side)); // this side is not part of a group, so calculate the value directly - // apply minimum margin restrictions: - if (QCP::getMarginValue(newMargins, side) < QCP::getMarginValue(mMinimumMargins, side)) - QCP::setMarginValue(newMargins, side, QCP::getMarginValue(mMinimumMargins, side)); - } + if (mDataRanges.size() > 1) + mDataRanges = QList() << mDataRanges.first(); + if (mDataRanges.first().length() > 1) + mDataRanges.first().setEnd(mDataRanges.first().begin()+1); } - setMargins(newMargins); + break; + } + case QCP::stDataRange: + { + if (!isEmpty()) + mDataRanges = QList() << span(); + break; + } + case QCP::stMultipleDataRanges: + { + // this is the selection type that allows all concievable combinations of ranges, so do nothing + break; } } } /*! - Returns the minimum size this layout element (the inner \ref rect) may be compressed to. + Returns true if the data selection \a other is contained entirely in this data selection, i.e. + all data point indices that are in \a other are also in this data selection. - if a minimum size (\ref setMinimumSize) was not set manually, parent layouts consult this - function to determine the minimum allowed size of this layout element. (A manual minimum size is - considered set if it is non-zero.) + \see QCPDataRange::contains */ -QSize QCPLayoutElement::minimumSizeHint() const +bool QCPDataSelection::contains(const QCPDataSelection &other) const { - return mMinimumSize; + if (other.isEmpty()) return false; + + int otherIndex = 0; + int thisIndex = 0; + while (thisIndex < mDataRanges.size() && otherIndex < other.mDataRanges.size()) + { + if (mDataRanges.at(thisIndex).contains(other.mDataRanges.at(otherIndex))) + ++otherIndex; + else + ++thisIndex; + } + return thisIndex < mDataRanges.size(); // if thisIndex ran all the way to the end to find a containing range for the current otherIndex, other is not contained in this } /*! - Returns the maximum size this layout element (the inner \ref rect) may be expanded to. - - if a maximum size (\ref setMaximumSize) was not set manually, parent layouts consult this - function to determine the maximum allowed size of this layout element. (A manual maximum size is - considered set if it is smaller than Qt's QWIDGETSIZE_MAX.) + Returns a data selection containing the points which are both in this data selection and in the + data range \a other. + + A common use case is to limit an unknown data selection to the valid range of a data container, + using \ref QCPDataContainer::dataRange as \a other. One can then safely iterate over the returned + data selection without exceeding the data container's bounds. */ -QSize QCPLayoutElement::maximumSizeHint() const +QCPDataSelection QCPDataSelection::intersection(const QCPDataRange &other) const { - return mMaximumSize; + QCPDataSelection result; + foreach (QCPDataRange dataRange, mDataRanges) + result.addDataRange(dataRange.intersection(other), false); + result.simplify(); + return result; } /*! - Returns a list of all child elements in this layout element. If \a recursive is true, all - sub-child elements are included in the list, too. - - \warning There may be entries with value 0 in the returned list. (For example, QCPLayoutGrid may have - empty cells which yield 0 at the respective index.) + Returns a data selection containing the points which are both in this data selection and in the + data selection \a other. */ -QList QCPLayoutElement::elements(bool recursive) const +QCPDataSelection QCPDataSelection::intersection(const QCPDataSelection &other) const { - Q_UNUSED(recursive) - return QList(); + QCPDataSelection result; + for (int i=0; iselectionTolerance()*0.99; - else - { - qDebug() << Q_FUNC_INFO << "parent plot not defined"; - return -1; - } - } else - return -1; + QCPDataSelection result; + // first unselected segment: + if (mDataRanges.first().begin() != fullRange.begin()) + result.addDataRange(QCPDataRange(fullRange.begin(), mDataRanges.first().begin()), false); + // intermediate unselected segments: + for (int i=1; iparentPlot()) - el->initializeParentPlot(parentPlot); - } -} -/*! \internal - - Returns the margin size for this \a side. It is used if automatic margins is enabled for this \a - side (see \ref setAutoMargins). If a minimum margin was set with \ref setMinimumMargins, the - returned value will not be smaller than the specified minimum margin. - - The default implementation just returns the respective manual margin (\ref setMargins) or the - minimum margin, whichever is larger. -*/ -int QCPLayoutElement::calculateAutoMargin(QCP::MarginSide side) -{ - return qMax(QCP::getMarginValue(mMargins, side), QCP::getMarginValue(mMinimumMargins, side)); -} +/* including file 'src/selectionrect.cpp' */ +/* modified 2022-11-06T12:45:56, size 9215 */ //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPLayout +//////////////////// QCPSelectionRect //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPLayout - \brief The abstract base class for layouts +/*! \class QCPSelectionRect + \brief Provides rect/rubber-band data selection and range zoom interaction - This is an abstract base class for layout elements whose main purpose is to define the position - and size of other child layout elements. In most cases, layouts don't draw anything themselves - (but there are exceptions to this, e.g. QCPLegend). + QCPSelectionRect is used by QCustomPlot when the \ref QCustomPlot::setSelectionRectMode is not + \ref QCP::srmNone. When the user drags the mouse across the plot, the current selection rect + instance (\ref QCustomPlot::setSelectionRect) is forwarded these events and makes sure an + according rect shape is drawn. At the begin, during, and after completion of the interaction, it + emits the corresponding signals \ref started, \ref changed, \ref canceled, and \ref accepted. - QCPLayout derives from QCPLayoutElement, and thus can itself be nested in other layouts. + The QCustomPlot instance connects own slots to the current selection rect instance, in order to + react to an accepted selection rect interaction accordingly. - QCPLayout introduces a common interface for accessing and manipulating the child elements. Those - functions are most notably \ref elementCount, \ref elementAt, \ref takeAt, \ref take, \ref - simplify, \ref removeAt, \ref remove and \ref clear. Individual subclasses may add more functions - to this interface which are more specialized to the form of the layout. For example, \ref - QCPLayoutGrid adds functions that take row and column indices to access cells of the layout grid - more conveniently. - - Since this is an abstract base class, you can't instantiate it directly. Rather use one of its - subclasses like QCPLayoutGrid or QCPLayoutInset. + \ref isActive can be used to check whether the selection rect is currently active. An ongoing + selection interaction can be cancelled programmatically via calling \ref cancel at any time. - For a general introduction to the layout system, see the dedicated documentation page \ref - thelayoutsystem "The Layout System". + The appearance of the selection rect can be controlled via \ref setPen and \ref setBrush. + + If you wish to provide custom behaviour, e.g. a different visual representation of the selection + rect (\ref QCPSelectionRect::draw), you can subclass QCPSelectionRect and pass an instance of + your subclass to \ref QCustomPlot::setSelectionRect. */ -/* start documentation of pure virtual functions */ +/* start of documentation of inline functions */ -/*! \fn virtual int QCPLayout::elementCount() const = 0 - - Returns the number of elements/cells in the layout. - - \see elements, elementAt +/*! \fn bool QCPSelectionRect::isActive() const + + Returns true if there is currently a selection going on, i.e. the user has started dragging a + selection rect, but hasn't released the mouse button yet. + + \see cancel */ -/*! \fn virtual QCPLayoutElement* QCPLayout::elementAt(int index) const = 0 - - Returns the element in the cell with the given \a index. If \a index is invalid, returns 0. - - Note that even if \a index is valid, the respective cell may be empty in some layouts (e.g. - QCPLayoutGrid), so this function may return 0 in those cases. You may use this function to check - whether a cell is empty or not. - - \see elements, elementCount, takeAt +/* end of documentation of inline functions */ +/* start documentation of signals */ + +/*! \fn void QCPSelectionRect::started(QMouseEvent *event); + + This signal is emitted when a selection rect interaction was initiated, i.e. the user just + started dragging the selection rect with the mouse. */ -/*! \fn virtual QCPLayoutElement* QCPLayout::takeAt(int index) = 0 - - Removes the element with the given \a index from the layout and returns it. - - If the \a index is invalid or the cell with that index is empty, returns 0. +/*! \fn void QCPSelectionRect::changed(const QRect &rect, QMouseEvent *event); - Note that some layouts don't remove the respective cell right away but leave an empty cell after - successful removal of the layout element. To collapse empty cells, use \ref simplify. + This signal is emitted while the selection rect interaction is ongoing and the \a rect has + changed its size due to the user moving the mouse. - \see elementAt, take + Note that \a rect may have a negative width or height, if the selection is being dragged to the + upper or left side of the selection rect origin. */ -/*! \fn virtual bool QCPLayout::take(QCPLayoutElement* element) = 0 +/*! \fn void QCPSelectionRect::canceled(const QRect &rect, QInputEvent *event); - Removes the specified \a element from the layout and returns true on success. + This signal is emitted when the selection interaction was cancelled. Note that \a event is \c + nullptr if the selection interaction was cancelled programmatically, by a call to \ref cancel. - If the \a element isn't in this layout, returns false. + The user may cancel the selection interaction by pressing the escape key. In this case, \a event + holds the respective input event. - Note that some layouts don't remove the respective cell right away but leave an empty cell after - successful removal of the layout element. To collapse empty cells, use \ref simplify. + Note that \a rect may have a negative width or height, if the selection is being dragged to the + upper or left side of the selection rect origin. +*/ + +/*! \fn void QCPSelectionRect::accepted(const QRect &rect, QMouseEvent *event); - \see takeAt + This signal is emitted when the selection interaction was completed by the user releasing the + mouse button. + + Note that \a rect may have a negative width or height, if the selection is being dragged to the + upper or left side of the selection rect origin. */ -/* end documentation of pure virtual functions */ +/* end documentation of signals */ /*! - Creates an instance of QCPLayout and sets default values. Note that since QCPLayout - is an abstract base class, it can't be instantiated directly. + Creates a new QCPSelectionRect instance. To make QCustomPlot use the selection rect instance, + pass it to \ref QCustomPlot::setSelectionRect. \a parentPlot should be set to the same + QCustomPlot widget. */ -QCPLayout::QCPLayout() +QCPSelectionRect::QCPSelectionRect(QCustomPlot *parentPlot) : + QCPLayerable(parentPlot), + mPen(QBrush(Qt::gray), 0, Qt::DashLine), + mBrush(Qt::NoBrush), + mActive(false) { } -/*! - First calls the QCPLayoutElement::update base class implementation to update the margins on this - layout. - - Then calls \ref updateLayout which subclasses reimplement to reposition and resize their cells. - - Finally, \ref update is called on all child elements. -*/ -void QCPLayout::update(UpdatePhase phase) +QCPSelectionRect::~QCPSelectionRect() { - QCPLayoutElement::update(phase); - - // set child element rects according to layout: - if (phase == upLayout) - updateLayout(); - - // propagate update call to child elements: - const int elCount = elementCount(); - for (int i=0; iupdate(phase); - } + cancel(); } -/* inherits documentation from base class */ -QList QCPLayout::elements(bool recursive) const +/*! + A convenience function which returns the coordinate range of the provided \a axis, that this + selection rect currently encompasses. +*/ +QCPRange QCPSelectionRect::range(const QCPAxis *axis) const { - const int c = elementCount(); - QList result; -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) - result.reserve(c); -#endif - for (int i=0; ielements(recursive); - } + if (axis->orientation() == Qt::Horizontal) + return {axis->pixelToCoord(mRect.left()), axis->pixelToCoord(mRect.left()+mRect.width())}; + else + return {axis->pixelToCoord(mRect.top()+mRect.height()), axis->pixelToCoord(mRect.top())}; + } else + { + qDebug() << Q_FUNC_INFO << "called with axis zero"; + return {}; } - return result; } /*! - Simplifies the layout by collapsing empty cells. The exact behavior depends on subclasses, the - default implementation does nothing. + Sets the pen that will be used to draw the selection rect outline. - Not all layouts need simplification. For example, QCPLayoutInset doesn't use explicit - simplification while QCPLayoutGrid does. + \see setBrush */ -void QCPLayout::simplify() +void QCPSelectionRect::setPen(const QPen &pen) { + mPen = pen; } /*! - Removes and deletes the element at the provided \a index. Returns true on success. If \a index is - invalid or points to an empty cell, returns false. - - This function internally uses \ref takeAt to remove the element from the layout and then deletes - the returned element. Note that some layouts don't remove the respective cell right away but leave an - empty cell after successful removal of the layout element. To collapse empty cells, use \ref - simplify. + Sets the brush that will be used to fill the selection rect. By default the selection rect is not + filled, i.e. \a brush is Qt::NoBrush. - \see remove, takeAt + \see setPen */ -bool QCPLayout::removeAt(int index) +void QCPSelectionRect::setBrush(const QBrush &brush) { - if (QCPLayoutElement *el = takeAt(index)) - { - delete el; - return true; - } else - return false; + mBrush = brush; } /*! - Removes and deletes the provided \a element. Returns true on success. If \a element is not in the - layout, returns false. - - This function internally uses \ref takeAt to remove the element from the layout and then deletes - the element. Note that some layouts don't remove the respective cell right away but leave an - empty cell after successful removal of the layout element. To collapse empty cells, use \ref - simplify. - - \see removeAt, take + If there is currently a selection interaction going on (\ref isActive), the interaction is + canceled. The selection rect will emit the \ref canceled signal. */ -bool QCPLayout::remove(QCPLayoutElement *element) +void QCPSelectionRect::cancel() { - if (take(element)) + if (mActive) { - delete element; - return true; - } else - return false; + mActive = false; + emit canceled(mRect, nullptr); + } } -/*! - Removes and deletes all layout elements in this layout. Finally calls \ref simplify to make sure - all empty cells are collapsed. +/*! \internal - \see remove, removeAt + This method is called by QCustomPlot to indicate that a selection rect interaction was initiated. + The default implementation sets the selection rect to active, initializes the selection rect + geometry and emits the \ref started signal. */ -void QCPLayout::clear() +void QCPSelectionRect::startSelection(QMouseEvent *event) { - for (int i=elementCount()-1; i>=0; --i) - { - if (elementAt(i)) - removeAt(i); - } - simplify(); + mActive = true; + mRect = QRect(event->pos(), event->pos()); + emit started(event); } -/*! - Subclasses call this method to report changed (minimum/maximum) size constraints. +/*! \internal - If the parent of this layout is again a QCPLayout, forwards the call to the parent's \ref - sizeConstraintsChanged. If the parent is a QWidget (i.e. is the \ref QCustomPlot::plotLayout of - QCustomPlot), calls QWidget::updateGeometry, so if the QCustomPlot widget is inside a Qt QLayout, - it may update itself and resize cells accordingly. + This method is called by QCustomPlot to indicate that an ongoing selection rect interaction needs + to update its geometry. The default implementation updates the rect and emits the \ref changed + signal. */ -void QCPLayout::sizeConstraintsChanged() const +void QCPSelectionRect::moveSelection(QMouseEvent *event) { - if (QWidget *w = qobject_cast(parent())) - w->updateGeometry(); - else if (QCPLayout *l = qobject_cast(parent())) - l->sizeConstraintsChanged(); + mRect.setBottomRight(event->pos()); + emit changed(mRect, event); + layer()->replot(); } /*! \internal - Subclasses reimplement this method to update the position and sizes of the child elements/cells - via calling their \ref QCPLayoutElement::setOuterRect. The default implementation does nothing. - - The geometry used as a reference is the inner \ref rect of this layout. Child elements should stay - within that rect. - - \ref getSectionSizes may help with the reimplementation of this function. - - \see update + This method is called by QCustomPlot to indicate that an ongoing selection rect interaction has + finished by the user releasing the mouse button. The default implementation deactivates the + selection rect and emits the \ref accepted signal. */ -void QCPLayout::updateLayout() +void QCPSelectionRect::endSelection(QMouseEvent *event) { + mRect.setBottomRight(event->pos()); + mActive = false; + emit accepted(mRect, event); } - /*! \internal - Associates \a el with this layout. This is done by setting the \ref QCPLayoutElement::layout, the - \ref QCPLayerable::parentLayerable and the QObject parent to this layout. - - Further, if \a el didn't previously have a parent plot, calls \ref - QCPLayerable::initializeParentPlot on \a el to set the paret plot. - - This method is used by subclass specific methods that add elements to the layout. Note that this - method only changes properties in \a el. The removal from the old layout and the insertion into - the new layout must be done additionally. + This method is called by QCustomPlot when a key has been pressed by the user while the selection + rect interaction is active. The default implementation allows to \ref cancel the interaction by + hitting the escape key. */ -void QCPLayout::adoptElement(QCPLayoutElement *el) +void QCPSelectionRect::keyPressEvent(QKeyEvent *event) { - if (el) + if (event->key() == Qt::Key_Escape && mActive) { - el->mParentLayout = this; - el->setParentLayerable(this); - el->setParent(this); - if (!el->parentPlot()) - el->initializeParentPlot(mParentPlot); - } else - qDebug() << Q_FUNC_INFO << "Null element passed"; + mActive = false; + emit canceled(mRect, event); + } +} + +/* inherits documentation from base class */ +void QCPSelectionRect::applyDefaultAntialiasingHint(QCPPainter *painter) const +{ + applyAntialiasingHint(painter, mAntialiased, QCP::aeOther); } /*! \internal - Disassociates \a el from this layout. This is done by setting the \ref QCPLayoutElement::layout - and the \ref QCPLayerable::parentLayerable to zero. The QObject parent is set to the parent - QCustomPlot. + If the selection rect is active (\ref isActive), draws the selection rect defined by \a mRect. - This method is used by subclass specific methods that remove elements from the layout (e.g. \ref - take or \ref takeAt). Note that this method only changes properties in \a el. The removal from - the old layout must be done additionally. + \seebaseclassmethod */ -void QCPLayout::releaseElement(QCPLayoutElement *el) +void QCPSelectionRect::draw(QCPPainter *painter) { - if (el) + if (mActive) { - el->mParentLayout = 0; - el->setParentLayerable(0); - el->setParent(mParentPlot); - // Note: Don't initializeParentPlot(0) here, because layout element will stay in same parent plot - } else - qDebug() << Q_FUNC_INFO << "Null element passed"; + painter->setPen(mPen); + painter->setBrush(mBrush); + painter->drawRect(mRect); + } } +/* end of 'src/selectionrect.cpp' */ -/*! \internal - - This is a helper function for the implementation of \ref updateLayout in subclasses. - - It calculates the sizes of one-dimensional sections with provided constraints on maximum section - sizes, minimum section sizes, relative stretch factors and the final total size of all sections. + +/* including file 'src/layout.cpp' */ +/* modified 2022-11-06T12:45:56, size 78863 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPMarginGroup +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPMarginGroup + \brief A margin group allows synchronization of margin sides if working with multiple layout elements. - The QVector entries refer to the sections. Thus all QVectors must have the same size. + QCPMarginGroup allows you to tie a margin side of two or more layout elements together, such that + they will all have the same size, based on the largest required margin in the group. - \a maxSizes gives the maximum allowed size of each section. If there shall be no maximum size - imposed, set all vector values to Qt's QWIDGETSIZE_MAX. + \n + \image html QCPMarginGroup.png "Demonstration of QCPMarginGroup" + \n - \a minSizes gives the minimum allowed size of each section. If there shall be no minimum size - imposed, set all vector values to zero. If the \a minSizes entries add up to a value greater than - \a totalSize, sections will be scaled smaller than the proposed minimum sizes. (In other words, - not exceeding the allowed total size is taken to be more important than not going below minimum - section sizes.) + In certain situations it is desirable that margins at specific sides are synchronized across + layout elements. For example, if one QCPAxisRect is below another one in a grid layout, it will + provide a cleaner look to the user if the left and right margins of the two axis rects are of the + same size. The left axis of the top axis rect will then be at the same horizontal position as the + left axis of the lower axis rect, making them appear aligned. The same applies for the right + axes. This is what QCPMarginGroup makes possible. - \a stretchFactors give the relative proportions of the sections to each other. If all sections - shall be scaled equally, set all values equal. If the first section shall be double the size of - each individual other section, set the first number of \a stretchFactors to double the value of - the other individual values (e.g. {2, 1, 1, 1}). + To add/remove a specific side of a layout element to/from a margin group, use the \ref + QCPLayoutElement::setMarginGroup method. To completely break apart the margin group, either call + \ref clear, or just delete the margin group. - \a totalSize is the value that the final section sizes will add up to. Due to rounding, the - actual sum may differ slightly. If you want the section sizes to sum up to exactly that value, - you could distribute the remaining difference on the sections. + \section QCPMarginGroup-example Example - The return value is a QVector containing the section sizes. + First create a margin group: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpmargingroup-creation-1 + Then set this group on the layout element sides: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpmargingroup-creation-2 + Here, we've used the first two axis rects of the plot and synchronized their left margins with + each other and their right margins with each other. */ -QVector QCPLayout::getSectionSizes(QVector maxSizes, QVector minSizes, QVector stretchFactors, int totalSize) const -{ - if (maxSizes.size() != minSizes.size() || minSizes.size() != stretchFactors.size()) - { - qDebug() << Q_FUNC_INFO << "Passed vector sizes aren't equal:" << maxSizes << minSizes << stretchFactors; - return QVector(); - } - if (stretchFactors.isEmpty()) - return QVector(); - int sectionCount = stretchFactors.size(); - QVector sectionSizes(sectionCount); - // if provided total size is forced smaller than total minimum size, ignore minimum sizes (squeeze sections): - int minSizeSum = 0; - for (int i=0; i minimumLockedSections; - QList unfinishedSections; - for (int i=0; i result(sectionCount); - for (int i=0; i QCPMarginGroup::elements(QCP::MarginSide side) const - Row and column insertion can be performed with \ref insertRow and \ref insertColumn. + Returns a list of all layout elements that have their margin \a side associated with this margin + group. */ +/* end documentation of inline functions */ + /*! - Creates an instance of QCPLayoutGrid and sets default values. + Creates a new QCPMarginGroup instance in \a parentPlot. */ -QCPLayoutGrid::QCPLayoutGrid() : - mColumnSpacing(5), - mRowSpacing(5) +QCPMarginGroup::QCPMarginGroup(QCustomPlot *parentPlot) : + QObject(parentPlot), + mParentPlot(parentPlot) { + mChildren.insert(QCP::msLeft, QList()); + mChildren.insert(QCP::msRight, QList()); + mChildren.insert(QCP::msTop, QList()); + mChildren.insert(QCP::msBottom, QList()); } -QCPLayoutGrid::~QCPLayoutGrid() +QCPMarginGroup::~QCPMarginGroup() { - // clear all child layout elements. This is important because only the specific layouts know how - // to handle removing elements (clear calls virtual removeAt method to do that). clear(); } /*! - Returns the element in the cell in \a row and \a column. - - Returns 0 if either the row/column is invalid or if the cell is empty. In those cases, a qDebug - message is printed. To check whether a cell exists and isn't empty, use \ref hasElement. - - \see addElement, hasElement + Returns whether this margin group is empty. If this function returns true, no layout elements use + this margin group to synchronize margin sides. */ -QCPLayoutElement *QCPLayoutGrid::element(int row, int column) const +bool QCPMarginGroup::isEmpty() const { - if (row >= 0 && row < mElements.size()) + QHashIterator > it(mChildren); + while (it.hasNext()) { - if (column >= 0 && column < mElements.first().size()) - { - if (QCPLayoutElement *result = mElements.at(row).at(column)) - return result; - else - qDebug() << Q_FUNC_INFO << "Requested cell is empty. Row:" << row << "Column:" << column; - } else - qDebug() << Q_FUNC_INFO << "Invalid column. Row:" << row << "Column:" << column; - } else - qDebug() << Q_FUNC_INFO << "Invalid row. Row:" << row << "Column:" << column; - return 0; -} - -/*! - Returns the number of rows in the layout. - - \see columnCount -*/ -int QCPLayoutGrid::rowCount() const -{ - return mElements.size(); + it.next(); + if (!it.value().isEmpty()) + return false; + } + return true; } /*! - Returns the number of columns in the layout. - - \see rowCount + Clears this margin group. The synchronization of the margin sides that use this margin group is + lifted and they will use their individual margin sizes again. */ -int QCPLayoutGrid::columnCount() const +void QCPMarginGroup::clear() { - if (mElements.size() > 0) - return mElements.first().size(); - else - return 0; + // make all children remove themselves from this margin group: + QHashIterator > it(mChildren); + while (it.hasNext()) + { + it.next(); + const QList elements = it.value(); + for (int i=elements.size()-1; i>=0; --i) + elements.at(i)->setMarginGroup(it.key(), nullptr); // removes itself from mChildren via removeChild + } } -/*! - Adds the \a element to cell with \a row and \a column. If \a element is already in a layout, it - is first removed from there. If \a row or \a column don't exist yet, the layout is expanded - accordingly. +/*! \internal - Returns true if the element was added successfully, i.e. if the cell at \a row and \a column - didn't already have an element. + Returns the synchronized common margin for \a side. This is the margin value that will be used by + the layout element on the respective side, if it is part of this margin group. - \see element, hasElement, take, remove + The common margin is calculated by requesting the automatic margin (\ref + QCPLayoutElement::calculateAutoMargin) of each element associated with \a side in this margin + group, and choosing the largest returned value. (QCPLayoutElement::minimumMargins is taken into + account, too.) */ -bool QCPLayoutGrid::addElement(int row, int column, QCPLayoutElement *element) +int QCPMarginGroup::commonMargin(QCP::MarginSide side) const { - if (element) + // query all automatic margins of the layout elements in this margin group side and find maximum: + int result = 0; + foreach (QCPLayoutElement *el, mChildren.value(side)) { - if (!hasElement(row, column)) - { - if (element->layout()) // remove from old layout first - element->layout()->take(element); - expandTo(row+1, column+1); - mElements[row][column] = element; - adoptElement(element); - return true; - } else - qDebug() << Q_FUNC_INFO << "There is already an element in the specified row/column:" << row << column; - } else - qDebug() << Q_FUNC_INFO << "Can't add null element to row/column:" << row << column; - return false; + if (!el->autoMargins().testFlag(side)) + continue; + int m = qMax(el->calculateAutoMargin(side), QCP::getMarginValue(el->minimumMargins(), side)); + if (m > result) + result = m; + } + return result; } -/*! - Returns whether the cell at \a row and \a column exists and contains a valid element, i.e. isn't - empty. +/*! \internal - \see element + Adds \a element to the internal list of child elements, for the margin \a side. + + This function does not modify the margin group property of \a element. */ -bool QCPLayoutGrid::hasElement(int row, int column) +void QCPMarginGroup::addChild(QCP::MarginSide side, QCPLayoutElement *element) { - if (row >= 0 && row < rowCount() && column >= 0 && column < columnCount()) - return mElements.at(row).at(column); + if (!mChildren[side].contains(element)) + mChildren[side].append(element); else - return false; + qDebug() << Q_FUNC_INFO << "element is already child of this margin group side" << reinterpret_cast(element); } -/*! - Sets the stretch \a factor of \a column. - - Stretch factors control the relative sizes of rows and columns. Cells will not be resized beyond - their minimum and maximum widths/heights (\ref QCPLayoutElement::setMinimumSize, \ref - QCPLayoutElement::setMaximumSize), regardless of the stretch factor. +/*! \internal - The default stretch factor of newly created rows/columns is 1. + Removes \a element from the internal list of child elements, for the margin \a side. - \see setColumnStretchFactors, setRowStretchFactor + This function does not modify the margin group property of \a element. */ -void QCPLayoutGrid::setColumnStretchFactor(int column, double factor) +void QCPMarginGroup::removeChild(QCP::MarginSide side, QCPLayoutElement *element) { - if (column >= 0 && column < columnCount()) - { - if (factor > 0) - mColumnStretchFactors[column] = factor; - else - qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor; - } else - qDebug() << Q_FUNC_INFO << "Invalid column:" << column; + if (!mChildren[side].removeOne(element)) + qDebug() << Q_FUNC_INFO << "element is not child of this margin group side" << reinterpret_cast(element); } -/*! - Sets the stretch \a factors of all columns. \a factors must have the size \ref columnCount. - - Stretch factors control the relative sizes of rows and columns. Cells will not be resized beyond - their minimum and maximum widths/heights (\ref QCPLayoutElement::setMinimumSize, \ref - QCPLayoutElement::setMaximumSize), regardless of the stretch factor. + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPLayoutElement +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPLayoutElement + \brief The abstract base class for all objects that form \ref thelayoutsystem "the layout system". - The default stretch factor of newly created rows/columns is 1. + This is an abstract base class. As such, it can't be instantiated directly, rather use one of its subclasses. - \see setColumnStretchFactor, setRowStretchFactors + A Layout element is a rectangular object which can be placed in layouts. It has an outer rect + (QCPLayoutElement::outerRect) and an inner rect (\ref QCPLayoutElement::rect). The difference + between outer and inner rect is called its margin. The margin can either be set to automatic or + manual (\ref setAutoMargins) on a per-side basis. If a side is set to manual, that margin can be + set explicitly with \ref setMargins and will stay fixed at that value. If it's set to automatic, + the layout element subclass will control the value itself (via \ref calculateAutoMargin). + + Layout elements can be placed in layouts (base class QCPLayout) like QCPLayoutGrid. The top level + layout is reachable via \ref QCustomPlot::plotLayout, and is a \ref QCPLayoutGrid. Since \ref + QCPLayout itself derives from \ref QCPLayoutElement, layouts can be nested. + + Thus in QCustomPlot one can divide layout elements into two categories: The ones that are + invisible by themselves, because they don't draw anything. Their only purpose is to manage the + position and size of other layout elements. This category of layout elements usually use + QCPLayout as base class. Then there is the category of layout elements which actually draw + something. For example, QCPAxisRect, QCPLegend and QCPTextElement are of this category. This does + not necessarily mean that the latter category can't have child layout elements. QCPLegend for + instance, actually derives from QCPLayoutGrid and the individual legend items are child layout + elements in the grid layout. */ -void QCPLayoutGrid::setColumnStretchFactors(const QList &factors) + +/* start documentation of inline functions */ + +/*! \fn QCPLayout *QCPLayoutElement::layout() const + + Returns the parent layout of this layout element. +*/ + +/*! \fn QRect QCPLayoutElement::rect() const + + Returns the inner rect of this layout element. The inner rect is the outer rect (\ref outerRect, \ref + setOuterRect) shrinked by the margins (\ref setMargins, \ref setAutoMargins). + + In some cases, the area between outer and inner rect is left blank. In other cases the margin + area is used to display peripheral graphics while the main content is in the inner rect. This is + where automatic margin calculation becomes interesting because it allows the layout element to + adapt the margins to the peripheral graphics it wants to draw. For example, \ref QCPAxisRect + draws the axis labels and tick labels in the margin area, thus needs to adjust the margins (if + \ref setAutoMargins is enabled) according to the space required by the labels of the axes. + + \see outerRect +*/ + +/*! \fn QRect QCPLayoutElement::outerRect() const + + Returns the outer rect of this layout element. The outer rect is the inner rect expanded by the + margins (\ref setMargins, \ref setAutoMargins). The outer rect is used (and set via \ref + setOuterRect) by the parent \ref QCPLayout to control the size of this layout element. + + \see rect +*/ + +/* end documentation of inline functions */ + +/*! + Creates an instance of QCPLayoutElement and sets default values. +*/ +QCPLayoutElement::QCPLayoutElement(QCustomPlot *parentPlot) : + QCPLayerable(parentPlot), // parenthood is changed as soon as layout element gets inserted into a layout (except for top level layout) + mParentLayout(nullptr), + mMinimumSize(), + mMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX), + mSizeConstraintRect(scrInnerRect), + mRect(0, 0, 0, 0), + mOuterRect(0, 0, 0, 0), + mMargins(0, 0, 0, 0), + mMinimumMargins(0, 0, 0, 0), + mAutoMargins(QCP::msAll) { - if (factors.size() == mColumnStretchFactors.size()) - { - mColumnStretchFactors = factors; - for (int i=0; i(mParentLayout)) // the qobject_cast is just a safeguard in case the layout forgets to call clear() in its dtor and this dtor is called by QObject dtor + mParentLayout->take(this); } /*! - Sets the stretch \a factor of \a row. + Sets the outer rect of this layout element. If the layout element is inside a layout, the layout + sets the position and size of this layout element using this function. - Stretch factors control the relative sizes of rows and columns. Cells will not be resized beyond - their minimum and maximum widths/heights (\ref QCPLayoutElement::setMinimumSize, \ref - QCPLayoutElement::setMaximumSize), regardless of the stretch factor. + Calling this function externally has no effect, since the layout will overwrite any changes to + the outer rect upon the next replot. - The default stretch factor of newly created rows/columns is 1. + The layout element will adapt its inner \ref rect by applying the margins inward to the outer rect. - \see setColumnStretchFactors, setRowStretchFactor + \see rect */ -void QCPLayoutGrid::setRowStretchFactor(int row, double factor) +void QCPLayoutElement::setOuterRect(const QRect &rect) { - if (row >= 0 && row < rowCount()) + if (mOuterRect != rect) { - if (factor > 0) - mRowStretchFactors[row] = factor; - else - qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor; - } else - qDebug() << Q_FUNC_INFO << "Invalid row:" << row; + mOuterRect = rect; + mRect = mOuterRect.adjusted(mMargins.left(), mMargins.top(), -mMargins.right(), -mMargins.bottom()); + } } /*! - Sets the stretch \a factors of all rows. \a factors must have the size \ref rowCount. - - Stretch factors control the relative sizes of rows and columns. Cells will not be resized beyond - their minimum and maximum widths/heights (\ref QCPLayoutElement::setMinimumSize, \ref - QCPLayoutElement::setMaximumSize), regardless of the stretch factor. + Sets the margins of this layout element. If \ref setAutoMargins is disabled for some or all + sides, this function is used to manually set the margin on those sides. Sides that are still set + to be handled automatically are ignored and may have any value in \a margins. - The default stretch factor of newly created rows/columns is 1. + The margin is the distance between the outer rect (controlled by the parent layout via \ref + setOuterRect) and the inner \ref rect (which usually contains the main content of this layout + element). - \see setRowStretchFactor, setColumnStretchFactors + \see setAutoMargins */ -void QCPLayoutGrid::setRowStretchFactors(const QList &factors) +void QCPLayoutElement::setMargins(const QMargins &margins) { - if (factors.size() == mRowStretchFactors.size()) + if (mMargins != margins) { - mRowStretchFactors = factors; - for (int i=0; i()); - mRowStretchFactors.append(1); - } - // go through rows and expand columns as necessary: - int newColCount = qMax(columnCount(), newColumnCount); - for (int i=0; isizeConstraintsChanged(); } - while (mColumnStretchFactors.size() < newColCount) - mColumnStretchFactors.append(1); +} + +/*! \overload + + Sets the minimum size of this layout element. + + Whether this constraint applies to the inner or the outer rect can be specified with \ref + setSizeConstraintRect (see \ref rect and \ref outerRect). +*/ +void QCPLayoutElement::setMinimumSize(int width, int height) +{ + setMinimumSize(QSize(width, height)); } /*! - Inserts a new row with empty cells at the row index \a newIndex. Valid values for \a newIndex - range from 0 (inserts a row at the top) to \a rowCount (appends a row at the bottom). + Sets the maximum size of this layout element. A parent layout tries to respect the \a size here + by changing row/column sizes in the layout accordingly. - \see insertColumn + Whether this constraint applies to the inner or the outer rect can be specified with \ref + setSizeConstraintRect (see \ref rect and \ref outerRect). */ -void QCPLayoutGrid::insertRow(int newIndex) +void QCPLayoutElement::setMaximumSize(const QSize &size) { - if (mElements.isEmpty() || mElements.first().isEmpty()) // if grid is completely empty, add first cell + if (mMaximumSize != size) { - expandTo(1, 1); - return; + mMaximumSize = size; + if (mParentLayout) + mParentLayout->sizeConstraintsChanged(); } +} + +/*! \overload - if (newIndex < 0) - newIndex = 0; - if (newIndex > rowCount()) - newIndex = rowCount(); + Sets the maximum size of this layout element. - mRowStretchFactors.insert(newIndex, 1); - QList newRow; - for (int col=0; colsizeConstraintsChanged(); } - - if (newIndex < 0) - newIndex = 0; - if (newIndex > columnCount()) - newIndex = columnCount(); - - mColumnStretchFactors.insert(newIndex, 1); - for (int row=0; row minColWidths, minRowHeights, maxColWidths, maxRowHeights; - getMinimumRowColSizes(&minColWidths, &minRowHeights); - getMaximumRowColSizes(&maxColWidths, &maxRowHeights); +/*! + Sets the margin \a group of the specified margin \a sides. - int totalRowSpacing = (rowCount()-1) * mRowSpacing; - int totalColSpacing = (columnCount()-1) * mColumnSpacing; - QVector colWidths = getSectionSizes(maxColWidths, minColWidths, mColumnStretchFactors.toVector(), mRect.width()-totalColSpacing); - QVector rowHeights = getSectionSizes(maxRowHeights, minRowHeights, mRowStretchFactors.toVector(), mRect.height()-totalRowSpacing); + Margin groups allow synchronizing specified margins across layout elements, see the documentation + of \ref QCPMarginGroup. - // go through cells and set rects accordingly: - int yOffset = mRect.top(); - for (int row=0; row 0) - yOffset += rowHeights.at(row-1)+mRowSpacing; - int xOffset = mRect.left(); - for (int col=0; col 0) - xOffset += colWidths.at(col-1)+mColumnSpacing; - if (mElements.at(row).at(col)) - mElements.at(row).at(col)->setOuterRect(QRect(xOffset, yOffset, colWidths.at(col), rowHeights.at(row))); - } - } -} - -/* inherits documentation from base class */ -int QCPLayoutGrid::elementCount() const -{ - return rowCount()*columnCount(); -} - -/* inherits documentation from base class */ -QCPLayoutElement *QCPLayoutGrid::elementAt(int index) const -{ - if (index >= 0 && index < elementCount()) - return mElements.at(index / columnCount()).at(index % columnCount()); - else - return 0; -} - -/* inherits documentation from base class */ -QCPLayoutElement *QCPLayoutGrid::takeAt(int index) -{ - if (QCPLayoutElement *el = elementAt(index)) - { - releaseElement(el); - mElements[index / columnCount()][index % columnCount()] = 0; - return el; - } else - { - qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index; - return 0; - } -} - -/* inherits documentation from base class */ -bool QCPLayoutGrid::take(QCPLayoutElement *element) + To unset the margin group of \a sides, set \a group to \c nullptr. + + Note that margin groups only work for margin sides that are set to automatic (\ref + setAutoMargins). + + \see QCP::MarginSide +*/ +void QCPLayoutElement::setMarginGroup(QCP::MarginSides sides, QCPMarginGroup *group) { - if (element) + QVector sideVector; + if (sides.testFlag(QCP::msLeft)) sideVector.append(QCP::msLeft); + if (sides.testFlag(QCP::msRight)) sideVector.append(QCP::msRight); + if (sides.testFlag(QCP::msTop)) sideVector.append(QCP::msTop); + if (sides.testFlag(QCP::msBottom)) sideVector.append(QCP::msBottom); + + foreach (QCP::MarginSide side, sideVector) { - for (int i=0; iremoveChild(side, this); + + if (!group) // if setting to 0, remove hash entry. Else set hash entry to new group and register there { - takeAt(i); - return true; + mMarginGroups.remove(side); + } else // setting to a new group + { + mMarginGroups[side] = group; + group->addChild(side, this); } } - qDebug() << Q_FUNC_INFO << "Element not in this layout, couldn't take"; - } else - qDebug() << Q_FUNC_INFO << "Can't take null element"; - return false; -} - -/* inherits documentation from base class */ -QList QCPLayoutGrid::elements(bool recursive) const -{ - QList result; - int colC = columnCount(); - int rowC = rowCount(); -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) - result.reserve(colC*rowC); -#endif - for (int row=0; rowelements(recursive); - } } - return result; } /*! - Simplifies the layout by collapsing rows and columns which only contain empty cells. + Updates the layout element and sub-elements. This function is automatically called before every + replot by the parent layout element. It is called multiple times, once for every \ref + UpdatePhase. The phases are run through in the order of the enum values. For details about what + happens at the different phases, see the documentation of \ref UpdatePhase. + + Layout elements that have child elements should call the \ref update method of their child + elements, and pass the current \a phase unchanged. + + The default implementation executes the automatic margin mechanism in the \ref upMargins phase. + Subclasses should make sure to call the base class implementation. */ -void QCPLayoutGrid::simplify() +void QCPLayoutElement::update(UpdatePhase phase) { - // remove rows with only empty cells: - for (int row=rowCount()-1; row>=0; --row) - { - bool hasElements = false; - for (int col=0; col=0; --col) + if (phase == upMargins) { - bool hasElements = false; - for (int row=0; row allMarginSides = QList() << QCP::msLeft << QCP::msRight << QCP::msTop << QCP::msBottom; + foreach (QCP::MarginSide side, allMarginSides) { - hasElements = true; - break; + if (mAutoMargins.testFlag(side)) // this side's margin shall be calculated automatically + { + if (mMarginGroups.contains(side)) + QCP::setMarginValue(newMargins, side, mMarginGroups[side]->commonMargin(side)); // this side is part of a margin group, so get the margin value from that group + else + QCP::setMarginValue(newMargins, side, calculateAutoMargin(side)); // this side is not part of a group, so calculate the value directly + // apply minimum margin restrictions: + if (QCP::getMarginValue(newMargins, side) < QCP::getMarginValue(mMinimumMargins, side)) + QCP::setMarginValue(newMargins, side, QCP::getMarginValue(mMinimumMargins, side)); + } } - } - if (!hasElements) - { - mColumnStretchFactors.removeAt(col); - for (int row=0; row minColWidths, minRowHeights; - getMinimumRowColSizes(&minColWidths, &minRowHeights); - QSize result(0, 0); - for (int i=0; i maxColWidths, maxRowHeights; - getMaximumRowColSizes(&maxColWidths, &maxRowHeights); +/*! + Returns the suggested maximum size this layout element (the \ref outerRect) may be expanded to, + if no manual maximum size is set. - QSize result(0, 0); - for (int i=0; i QCPLayoutElement::elements(bool recursive) const +{ + Q_UNUSED(recursive) + return QList(); +} + +/*! + Layout elements are sensitive to events inside their outer rect. If \a pos is within the outer + rect, this method returns a value corresponding to 0.99 times the parent plot's selection + tolerance. However, layout elements are not selectable by default. So if \a onlySelectable is + true, -1.0 is returned. - This is a helper function for \ref updateLayout. + See \ref QCPLayerable::selectTest for a general explanation of this virtual method. - \see getMaximumRowColSizes + QCPLayoutElement subclasses may reimplement this method to provide more specific selection test + behaviour. */ -void QCPLayoutGrid::getMinimumRowColSizes(QVector *minColWidths, QVector *minRowHeights) const +double QCPLayoutElement::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - *minColWidths = QVector(columnCount(), 0); - *minRowHeights = QVector(rowCount(), 0); - for (int row=0; rowselectionTolerance()*0.99; + else { - if (mElements.at(row).at(col)) - { - QSize minHint = mElements.at(row).at(col)->minimumSizeHint(); - QSize min = mElements.at(row).at(col)->minimumSize(); - QSize final(min.width() > 0 ? min.width() : minHint.width(), min.height() > 0 ? min.height() : minHint.height()); - if (minColWidths->at(col) < final.width()) - (*minColWidths)[col] = final.width(); - if (minRowHeights->at(row) < final.height()) - (*minRowHeights)[row] = final.height(); - } + qDebug() << Q_FUNC_INFO << "parent plot not defined"; + return -1; } - } + } else + return -1; } /*! \internal - Places the maximum column widths and row heights into \a maxColWidths and \a maxRowHeights - respectively. - - The maximum height of a row is the smallest maximum height of any element in that row. The - maximum width of a column is the smallest maximum width of any element in that column. - - This is a helper function for \ref updateLayout. - - \see getMinimumRowColSizes + propagates the parent plot initialization to all child elements, by calling \ref + QCPLayerable::initializeParentPlot on them. */ -void QCPLayoutGrid::getMaximumRowColSizes(QVector *maxColWidths, QVector *maxRowHeights) const +void QCPLayoutElement::parentPlotInitialized(QCustomPlot *parentPlot) { - *maxColWidths = QVector(columnCount(), QWIDGETSIZE_MAX); - *maxRowHeights = QVector(rowCount(), QWIDGETSIZE_MAX); - for (int row=0; rowmaximumSizeHint(); - QSize max = mElements.at(row).at(col)->maximumSize(); - QSize final(max.width() < QWIDGETSIZE_MAX ? max.width() : maxHint.width(), max.height() < QWIDGETSIZE_MAX ? max.height() : maxHint.height()); - if (maxColWidths->at(col) > final.width()) - (*maxColWidths)[col] = final.width(); - if (maxRowHeights->at(row) > final.height()) - (*maxRowHeights)[row] = final.height(); - } - } + if (!el->parentPlot()) + el->initializeParentPlot(parentPlot); } } +/*! \internal + + Returns the margin size for this \a side. It is used if automatic margins is enabled for this \a + side (see \ref setAutoMargins). If a minimum margin was set with \ref setMinimumMargins, the + returned value will not be smaller than the specified minimum margin. + + The default implementation just returns the respective manual margin (\ref setMargins) or the + minimum margin, whichever is larger. +*/ +int QCPLayoutElement::calculateAutoMargin(QCP::MarginSide side) +{ + return qMax(QCP::getMarginValue(mMargins, side), QCP::getMarginValue(mMinimumMargins, side)); +} + +/*! \internal + + This virtual method is called when this layout element was moved to a different QCPLayout, or + when this layout element has changed its logical position (e.g. row and/or column) within the + same QCPLayout. Subclasses may use this to react accordingly. + + Since this method is called after the completion of the move, you can access the new parent + layout via \ref layout(). + + The default implementation does nothing. +*/ +void QCPLayoutElement::layoutChanged() +{ +} //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPLayoutInset +//////////////////// QCPLayout //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPLayoutInset - \brief A layout that places child elements aligned to the border or arbitrarily positioned - - Elements are placed either aligned to the border or at arbitrary position in the area of the - layout. Which placement applies is controlled with the \ref InsetPlacement (\ref - setInsetPlacement). - Elements are added via \ref addElement(QCPLayoutElement *element, Qt::Alignment alignment) or - addElement(QCPLayoutElement *element, const QRectF &rect). If the first method is used, the inset - placement will default to \ref ipBorderAligned and the element will be aligned according to the - \a alignment parameter. The second method defaults to \ref ipFree and allows placing elements at - arbitrary position and size, defined by \a rect. +/*! \class QCPLayout + \brief The abstract base class for layouts - The alignment or rect can be set via \ref setInsetAlignment or \ref setInsetRect, respectively. + This is an abstract base class for layout elements whose main purpose is to define the position + and size of other child layout elements. In most cases, layouts don't draw anything themselves + (but there are exceptions to this, e.g. QCPLegend). - This is the layout that every QCPAxisRect has as \ref QCPAxisRect::insetLayout. + QCPLayout derives from QCPLayoutElement, and thus can itself be nested in other layouts. + + QCPLayout introduces a common interface for accessing and manipulating the child elements. Those + functions are most notably \ref elementCount, \ref elementAt, \ref takeAt, \ref take, \ref + simplify, \ref removeAt, \ref remove and \ref clear. Individual subclasses may add more functions + to this interface which are more specialized to the form of the layout. For example, \ref + QCPLayoutGrid adds functions that take row and column indices to access cells of the layout grid + more conveniently. + + Since this is an abstract base class, you can't instantiate it directly. Rather use one of its + subclasses like QCPLayoutGrid or QCPLayoutInset. + + For a general introduction to the layout system, see the dedicated documentation page \ref + thelayoutsystem "The Layout System". */ -/* start documentation of inline functions */ +/* start documentation of pure virtual functions */ -/*! \fn virtual void QCPLayoutInset::simplify() +/*! \fn virtual int QCPLayout::elementCount() const = 0 - The QCPInsetLayout does not need simplification since it can never have empty cells due to its - linear index structure. This method does nothing. + Returns the number of elements/cells in the layout. + + \see elements, elementAt */ -/* end documentation of inline functions */ +/*! \fn virtual QCPLayoutElement* QCPLayout::elementAt(int index) const = 0 + + Returns the element in the cell with the given \a index. If \a index is invalid, returns \c + nullptr. + + Note that even if \a index is valid, the respective cell may be empty in some layouts (e.g. + QCPLayoutGrid), so this function may return \c nullptr in those cases. You may use this function + to check whether a cell is empty or not. + + \see elements, elementCount, takeAt +*/ -/*! - Creates an instance of QCPLayoutInset and sets default values. +/*! \fn virtual QCPLayoutElement* QCPLayout::takeAt(int index) = 0 + + Removes the element with the given \a index from the layout and returns it. + + If the \a index is invalid or the cell with that index is empty, returns \c nullptr. + + Note that some layouts don't remove the respective cell right away but leave an empty cell after + successful removal of the layout element. To collapse empty cells, use \ref simplify. + + \see elementAt, take */ -QCPLayoutInset::QCPLayoutInset() -{ -} -QCPLayoutInset::~QCPLayoutInset() -{ - // clear all child layout elements. This is important because only the specific layouts know how - // to handle removing elements (clear calls virtual removeAt method to do that). - clear(); -} +/*! \fn virtual bool QCPLayout::take(QCPLayoutElement* element) = 0 + + Removes the specified \a element from the layout and returns true on success. + + If the \a element isn't in this layout, returns false. + + Note that some layouts don't remove the respective cell right away but leave an empty cell after + successful removal of the layout element. To collapse empty cells, use \ref simplify. + + \see takeAt +*/ + +/* end documentation of pure virtual functions */ /*! - Returns the placement type of the element with the specified \a index. + Creates an instance of QCPLayout and sets default values. Note that since QCPLayout + is an abstract base class, it can't be instantiated directly. */ -QCPLayoutInset::InsetPlacement QCPLayoutInset::insetPlacement(int index) const +QCPLayout::QCPLayout() { - if (elementAt(index)) - return mInsetPlacement.at(index); - else - { - qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; - return ipFree; - } } /*! - Returns the alignment of the element with the specified \a index. The alignment only has a - meaning, if the inset placement (\ref setInsetPlacement) is \ref ipBorderAligned. + If \a phase is \ref upLayout, calls \ref updateLayout, which subclasses may reimplement to + reposition and resize their cells. + + Finally, the call is propagated down to all child \ref QCPLayoutElement "QCPLayoutElements". + + For details about this method and the update phases, see the documentation of \ref + QCPLayoutElement::update. */ -Qt::Alignment QCPLayoutInset::insetAlignment(int index) const +void QCPLayout::update(UpdatePhase phase) { - if (elementAt(index)) - return mInsetAlignment.at(index); - else + QCPLayoutElement::update(phase); + + // set child element rects according to layout: + if (phase == upLayout) + updateLayout(); + + // propagate update call to child elements: + const int elCount = elementCount(); + for (int i=0; iupdate(phase); } } -/*! - Returns the rect of the element with the specified \a index. The rect only has a - meaning, if the inset placement (\ref setInsetPlacement) is \ref ipFree. -*/ -QRectF QCPLayoutInset::insetRect(int index) const +/* inherits documentation from base class */ +QList QCPLayout::elements(bool recursive) const { - if (elementAt(index)) - return mInsetRect.at(index); - else + const int c = elementCount(); + QList result; +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + result.reserve(c); +#endif + for (int i=0; ielements(recursive); + } } + return result; } /*! - Sets the inset placement type of the element with the specified \a index to \a placement. + Simplifies the layout by collapsing empty cells. The exact behavior depends on subclasses, the + default implementation does nothing. - \see InsetPlacement + Not all layouts need simplification. For example, QCPLayoutInset doesn't use explicit + simplification while QCPLayoutGrid does. */ -void QCPLayoutInset::setInsetPlacement(int index, QCPLayoutInset::InsetPlacement placement) +void QCPLayout::simplify() { - if (elementAt(index)) - mInsetPlacement[index] = placement; - else - qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; } /*! - If the inset placement (\ref setInsetPlacement) is \ref ipBorderAligned, this function - is used to set the alignment of the element with the specified \a index to \a alignment. + Removes and deletes the element at the provided \a index. Returns true on success. If \a index is + invalid or points to an empty cell, returns false. - \a alignment is an or combination of the following alignment flags: Qt::AlignLeft, - Qt::AlignHCenter, Qt::AlighRight, Qt::AlignTop, Qt::AlignVCenter, Qt::AlignBottom. Any other - alignment flags will be ignored. + This function internally uses \ref takeAt to remove the element from the layout and then deletes + the returned element. Note that some layouts don't remove the respective cell right away but leave an + empty cell after successful removal of the layout element. To collapse empty cells, use \ref + simplify. + + \see remove, takeAt */ -void QCPLayoutInset::setInsetAlignment(int index, Qt::Alignment alignment) +bool QCPLayout::removeAt(int index) { - if (elementAt(index)) - mInsetAlignment[index] = alignment; - else - qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; + if (QCPLayoutElement *el = takeAt(index)) + { + delete el; + return true; + } else + return false; } /*! - If the inset placement (\ref setInsetPlacement) is \ref ipFree, this function is used to set the - position and size of the element with the specified \a index to \a rect. + Removes and deletes the provided \a element. Returns true on success. If \a element is not in the + layout, returns false. - \a rect is given in fractions of the whole inset layout rect. So an inset with rect (0, 0, 1, 1) - will span the entire layout. An inset with rect (0.6, 0.1, 0.35, 0.35) will be in the top right - corner of the layout, with 35% width and height of the parent layout. + This function internally uses \ref takeAt to remove the element from the layout and then deletes + the element. Note that some layouts don't remove the respective cell right away but leave an + empty cell after successful removal of the layout element. To collapse empty cells, use \ref + simplify. - Note that the minimum and maximum sizes of the embedded element (\ref - QCPLayoutElement::setMinimumSize, \ref QCPLayoutElement::setMaximumSize) are enforced. + \see removeAt, take */ -void QCPLayoutInset::setInsetRect(int index, const QRectF &rect) +bool QCPLayout::remove(QCPLayoutElement *element) { - if (elementAt(index)) - mInsetRect[index] = rect; - else - qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; + if (take(element)) + { + delete element; + return true; + } else + return false; } -/* inherits documentation from base class */ -void QCPLayoutInset::updateLayout() +/*! + Removes and deletes all layout elements in this layout. Finally calls \ref simplify to make sure + all empty cells are collapsed. + + \see remove, removeAt +*/ +void QCPLayout::clear() { - for (int i=0; i=0; --i) { - QRect insetRect; - QSize finalMinSize, finalMaxSize; - QSize minSizeHint = mElements.at(i)->minimumSizeHint(); - QSize maxSizeHint = mElements.at(i)->maximumSizeHint(); - finalMinSize.setWidth(mElements.at(i)->minimumSize().width() > 0 ? mElements.at(i)->minimumSize().width() : minSizeHint.width()); - finalMinSize.setHeight(mElements.at(i)->minimumSize().height() > 0 ? mElements.at(i)->minimumSize().height() : minSizeHint.height()); - finalMaxSize.setWidth(mElements.at(i)->maximumSize().width() < QWIDGETSIZE_MAX ? mElements.at(i)->maximumSize().width() : maxSizeHint.width()); - finalMaxSize.setHeight(mElements.at(i)->maximumSize().height() < QWIDGETSIZE_MAX ? mElements.at(i)->maximumSize().height() : maxSizeHint.height()); - if (mInsetPlacement.at(i) == ipFree) - { - insetRect = QRect(rect().x()+rect().width()*mInsetRect.at(i).x(), - rect().y()+rect().height()*mInsetRect.at(i).y(), - rect().width()*mInsetRect.at(i).width(), - rect().height()*mInsetRect.at(i).height()); - if (insetRect.size().width() < finalMinSize.width()) - insetRect.setWidth(finalMinSize.width()); - if (insetRect.size().height() < finalMinSize.height()) - insetRect.setHeight(finalMinSize.height()); - if (insetRect.size().width() > finalMaxSize.width()) - insetRect.setWidth(finalMaxSize.width()); - if (insetRect.size().height() > finalMaxSize.height()) - insetRect.setHeight(finalMaxSize.height()); - } else if (mInsetPlacement.at(i) == ipBorderAligned) - { - insetRect.setSize(finalMinSize); - Qt::Alignment al = mInsetAlignment.at(i); - if (al.testFlag(Qt::AlignLeft)) insetRect.moveLeft(rect().x()); - else if (al.testFlag(Qt::AlignRight)) insetRect.moveRight(rect().x()+rect().width()); - else insetRect.moveLeft(rect().x()+rect().width()*0.5-finalMinSize.width()*0.5); // default to Qt::AlignHCenter - if (al.testFlag(Qt::AlignTop)) insetRect.moveTop(rect().y()); - else if (al.testFlag(Qt::AlignBottom)) insetRect.moveBottom(rect().y()+rect().height()); - else insetRect.moveTop(rect().y()+rect().height()*0.5-finalMinSize.height()*0.5); // default to Qt::AlignVCenter - } - mElements.at(i)->setOuterRect(insetRect); - } -} - -/* inherits documentation from base class */ -int QCPLayoutInset::elementCount() const -{ - return mElements.size(); -} - -/* inherits documentation from base class */ -QCPLayoutElement *QCPLayoutInset::elementAt(int index) const -{ - if (index >= 0 && index < mElements.size()) - return mElements.at(index); - else - return 0; -} - -/* inherits documentation from base class */ -QCPLayoutElement *QCPLayoutInset::takeAt(int index) -{ - if (QCPLayoutElement *el = elementAt(index)) - { - releaseElement(el); - mElements.removeAt(index); - mInsetPlacement.removeAt(index); - mInsetAlignment.removeAt(index); - mInsetRect.removeAt(index); - return el; - } else - { - qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index; - return 0; + if (elementAt(i)) + removeAt(i); } -} - -/* inherits documentation from base class */ -bool QCPLayoutInset::take(QCPLayoutElement *element) -{ - if (element) - { - for (int i=0; irealVisibility() && mElements.at(i)->selectTest(pos, onlySelectable) >= 0) - return mParentPlot->selectionTolerance()*0.99; - } - return -1; + if (QWidget *w = qobject_cast(parent())) + w->updateGeometry(); + else if (QCPLayout *l = qobject_cast(parent())) + l->sizeConstraintsChanged(); } -/*! - Adds the specified \a element to the layout as an inset aligned at the border (\ref - setInsetAlignment is initialized with \ref ipBorderAligned). The alignment is set to \a - alignment. +/*! \internal - \a alignment is an or combination of the following alignment flags: Qt::AlignLeft, - Qt::AlignHCenter, Qt::AlighRight, Qt::AlignTop, Qt::AlignVCenter, Qt::AlignBottom. Any other - alignment flags will be ignored. + Subclasses reimplement this method to update the position and sizes of the child elements/cells + via calling their \ref QCPLayoutElement::setOuterRect. The default implementation does nothing. - \see addElement(QCPLayoutElement *element, const QRectF &rect) -*/ -void QCPLayoutInset::addElement(QCPLayoutElement *element, Qt::Alignment alignment) -{ - if (element) - { - if (element->layout()) // remove from old layout first - element->layout()->take(element); - mElements.append(element); - mInsetPlacement.append(ipBorderAligned); - mInsetAlignment.append(alignment); - mInsetRect.append(QRectF(0.6, 0.6, 0.4, 0.4)); - adoptElement(element); - } else - qDebug() << Q_FUNC_INFO << "Can't add null element"; -} - -/*! - Adds the specified \a element to the layout as an inset with free positioning/sizing (\ref - setInsetAlignment is initialized with \ref ipFree). The position and size is set to \a - rect. + The geometry used as a reference is the inner \ref rect of this layout. Child elements should stay + within that rect. - \a rect is given in fractions of the whole inset layout rect. So an inset with rect (0, 0, 1, 1) - will span the entire layout. An inset with rect (0.6, 0.1, 0.35, 0.35) will be in the top right - corner of the layout, with 35% width and height of the parent layout. + \ref getSectionSizes may help with the reimplementation of this function. - \see addElement(QCPLayoutElement *element, Qt::Alignment alignment) + \see update */ -void QCPLayoutInset::addElement(QCPLayoutElement *element, const QRectF &rect) +void QCPLayout::updateLayout() { - if (element) - { - if (element->layout()) // remove from old layout first - element->layout()->take(element); - mElements.append(element); - mInsetPlacement.append(ipFree); - mInsetAlignment.append(Qt::AlignRight|Qt::AlignTop); - mInsetRect.append(rect); - adoptElement(element); - } else - qDebug() << Q_FUNC_INFO << "Can't add null element"; } -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPLineEnding -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPLineEnding - \brief Handles the different ending decorations for line-like items +/*! \internal - \image html QCPLineEnding.png "The various ending styles currently supported" + Associates \a el with this layout. This is done by setting the \ref QCPLayoutElement::layout, the + \ref QCPLayerable::parentLayerable and the QObject parent to this layout. - For every ending a line-like item has, an instance of this class exists. For example, QCPItemLine - has two endings which can be set with QCPItemLine::setHead and QCPItemLine::setTail. - - The styles themselves are defined via the enum QCPLineEnding::EndingStyle. Most decorations can - be modified regarding width and length, see \ref setWidth and \ref setLength. The direction of - the ending decoration (e.g. direction an arrow is pointing) is controlled by the line-like item. - For example, when both endings of a QCPItemLine are set to be arrows, they will point to opposite - directions, e.g. "outward". This can be changed by \ref setInverted, which would make the - respective arrow point inward. + Further, if \a el didn't previously have a parent plot, calls \ref + QCPLayerable::initializeParentPlot on \a el to set the paret plot. - Note that due to the overloaded QCPLineEnding constructor, you may directly specify a - QCPLineEnding::EndingStyle where actually a QCPLineEnding is expected, e.g. - \snippet documentation/doc-code-snippets/mainwindow.cpp qcplineending-sethead -*/ - -/*! - Creates a QCPLineEnding instance with default values (style \ref esNone). -*/ -QCPLineEnding::QCPLineEnding() : - mStyle(esNone), - mWidth(8), - mLength(10), - mInverted(false) -{ -} - -/*! - Creates a QCPLineEnding instance with the specified values. -*/ -QCPLineEnding::QCPLineEnding(QCPLineEnding::EndingStyle style, double width, double length, bool inverted) : - mStyle(style), - mWidth(width), - mLength(length), - mInverted(inverted) -{ -} - -/*! - Sets the style of the ending decoration. + This method is used by subclass specific methods that add elements to the layout. Note that this + method only changes properties in \a el. The removal from the old layout and the insertion into + the new layout must be done additionally. */ -void QCPLineEnding::setStyle(QCPLineEnding::EndingStyle style) +void QCPLayout::adoptElement(QCPLayoutElement *el) { - mStyle = style; + if (el) + { + el->mParentLayout = this; + el->setParentLayerable(this); + el->setParent(this); + if (!el->parentPlot()) + el->initializeParentPlot(mParentPlot); + el->layoutChanged(); + } else + qDebug() << Q_FUNC_INFO << "Null element passed"; } -/*! - Sets the width of the ending decoration, if the style supports it. On arrows, for example, the - width defines the size perpendicular to the arrow's pointing direction. +/*! \internal - \see setLength -*/ -void QCPLineEnding::setWidth(double width) -{ - mWidth = width; -} - -/*! - Sets the length of the ending decoration, if the style supports it. On arrows, for example, the - length defines the size in pointing direction. + Disassociates \a el from this layout. This is done by setting the \ref QCPLayoutElement::layout + and the \ref QCPLayerable::parentLayerable to zero. The QObject parent is set to the parent + QCustomPlot. - \see setWidth -*/ -void QCPLineEnding::setLength(double length) -{ - mLength = length; -} - -/*! - Sets whether the ending decoration shall be inverted. For example, an arrow decoration will point - inward when \a inverted is set to true. - - Note that also the \a width direction is inverted. For symmetrical ending styles like arrows or - discs, this doesn't make a difference. However, asymmetric styles like \ref esHalfBar are - affected by it, which can be used to control to which side the half bar points to. + This method is used by subclass specific methods that remove elements from the layout (e.g. \ref + take or \ref takeAt). Note that this method only changes properties in \a el. The removal from + the old layout must be done additionally. */ -void QCPLineEnding::setInverted(bool inverted) +void QCPLayout::releaseElement(QCPLayoutElement *el) { - mInverted = inverted; + if (el) + { + el->mParentLayout = nullptr; + el->setParentLayerable(nullptr); + el->setParent(mParentPlot); + // Note: Don't initializeParentPlot(0) here, because layout element will stay in same parent plot + } else + qDebug() << Q_FUNC_INFO << "Null element passed"; } /*! \internal - Returns the maximum pixel radius the ending decoration might cover, starting from the position - the decoration is drawn at (typically a line ending/\ref QCPItemPosition of an item). + This is a helper function for the implementation of \ref updateLayout in subclasses. - This is relevant for clipping. Only omit painting of the decoration when the position where the - decoration is supposed to be drawn is farther away from the clipping rect than the returned - distance. + It calculates the sizes of one-dimensional sections with provided constraints on maximum section + sizes, minimum section sizes, relative stretch factors and the final total size of all sections. + + The QVector entries refer to the sections. Thus all QVectors must have the same size. + + \a maxSizes gives the maximum allowed size of each section. If there shall be no maximum size + imposed, set all vector values to Qt's QWIDGETSIZE_MAX. + + \a minSizes gives the minimum allowed size of each section. If there shall be no minimum size + imposed, set all vector values to zero. If the \a minSizes entries add up to a value greater than + \a totalSize, sections will be scaled smaller than the proposed minimum sizes. (In other words, + not exceeding the allowed total size is taken to be more important than not going below minimum + section sizes.) + + \a stretchFactors give the relative proportions of the sections to each other. If all sections + shall be scaled equally, set all values equal. If the first section shall be double the size of + each individual other section, set the first number of \a stretchFactors to double the value of + the other individual values (e.g. {2, 1, 1, 1}). + + \a totalSize is the value that the final section sizes will add up to. Due to rounding, the + actual sum may differ slightly. If you want the section sizes to sum up to exactly that value, + you could distribute the remaining difference on the sections. + + The return value is a QVector containing the section sizes. +*/ +QVector QCPLayout::getSectionSizes(QVector maxSizes, QVector minSizes, QVector stretchFactors, int totalSize) const +{ + if (maxSizes.size() != minSizes.size() || minSizes.size() != stretchFactors.size()) + { + qDebug() << Q_FUNC_INFO << "Passed vector sizes aren't equal:" << maxSizes << minSizes << stretchFactors; + return QVector(); + } + if (stretchFactors.isEmpty()) + return QVector(); + int sectionCount = stretchFactors.size(); + QVector sectionSizes(sectionCount); + // if provided total size is forced smaller than total minimum size, ignore minimum sizes (squeeze sections): + int minSizeSum = 0; + for (int i=0; i minimumLockedSections; + QList unfinishedSections; + for (int i=0; i result(sectionCount); + for (int i=0; iminimumOuterSizeHint(); + QSize minOuter = el->minimumSize(); // depending on sizeConstraitRect this might be with respect to inner rect, so possibly add margins in next four lines (preserving unset minimum of 0) + if (minOuter.width() > 0 && el->sizeConstraintRect() == QCPLayoutElement::scrInnerRect) + minOuter.rwidth() += el->margins().left() + el->margins().right(); + if (minOuter.height() > 0 && el->sizeConstraintRect() == QCPLayoutElement::scrInnerRect) + minOuter.rheight() += el->margins().top() + el->margins().bottom(); + + return {minOuter.width() > 0 ? minOuter.width() : minOuterHint.width(), + minOuter.height() > 0 ? minOuter.height() : minOuterHint.height()}; +} + +/*! \internal + + This is a helper function for the implementation of subclasses. + + It returns the maximum size that should finally be used for the outer rect of the passed layout + element \a el. + + It takes into account whether a manual maximum size is set (\ref + QCPLayoutElement::setMaximumSize), which size constraint is set (\ref + QCPLayoutElement::setSizeConstraintRect), as well as the maximum size hint, if no manual maximum + size was set (\ref QCPLayoutElement::maximumOuterSizeHint). +*/ +QSize QCPLayout::getFinalMaximumOuterSize(const QCPLayoutElement *el) +{ + QSize maxOuterHint = el->maximumOuterSizeHint(); + QSize maxOuter = el->maximumSize(); // depending on sizeConstraitRect this might be with respect to inner rect, so possibly add margins in next four lines (preserving unset maximum of QWIDGETSIZE_MAX) + if (maxOuter.width() < QWIDGETSIZE_MAX && el->sizeConstraintRect() == QCPLayoutElement::scrInnerRect) + maxOuter.rwidth() += el->margins().left() + el->margins().right(); + if (maxOuter.height() < QWIDGETSIZE_MAX && el->sizeConstraintRect() == QCPLayoutElement::scrInnerRect) + maxOuter.rheight() += el->margins().top() + el->margins().bottom(); + + return {maxOuter.width() < QWIDGETSIZE_MAX ? maxOuter.width() : maxOuterHint.width(), + maxOuter.height() < QWIDGETSIZE_MAX ? maxOuter.height() : maxOuterHint.height()}; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPLayoutGrid +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPLayoutGrid + \brief A layout that arranges child elements in a grid + + Elements are laid out in a grid with configurable stretch factors (\ref setColumnStretchFactor, + \ref setRowStretchFactor) and spacing (\ref setColumnSpacing, \ref setRowSpacing). + + Elements can be added to cells via \ref addElement. The grid is expanded if the specified row or + column doesn't exist yet. Whether a cell contains a valid layout element can be checked with \ref + hasElement, that element can be retrieved with \ref element. If rows and columns that only have + empty cells shall be removed, call \ref simplify. Removal of elements is either done by just + adding the element to a different layout or by using the QCPLayout interface \ref take or \ref + remove. + + If you use \ref addElement(QCPLayoutElement*) without explicit parameters for \a row and \a + column, the grid layout will choose the position according to the current \ref setFillOrder and + the wrapping (\ref setWrap). + + Row and column insertion can be performed with \ref insertRow and \ref insertColumn. +*/ + +/* start documentation of inline functions */ + +/*! \fn int QCPLayoutGrid::rowCount() const + + Returns the number of rows in the layout. + + \see columnCount +*/ + +/*! \fn int QCPLayoutGrid::columnCount() const + + Returns the number of columns in the layout. + + \see rowCount +*/ + +/* end documentation of inline functions */ + +/*! + Creates an instance of QCPLayoutGrid and sets default values. +*/ +QCPLayoutGrid::QCPLayoutGrid() : + mColumnSpacing(5), + mRowSpacing(5), + mWrap(0), + mFillOrder(foColumnsFirst) +{ +} + +QCPLayoutGrid::~QCPLayoutGrid() +{ + // clear all child layout elements. This is important because only the specific layouts know how + // to handle removing elements (clear calls virtual removeAt method to do that). + clear(); +} + +/*! + Returns the element in the cell in \a row and \a column. + + Returns \c nullptr if either the row/column is invalid or if the cell is empty. In those cases, a + qDebug message is printed. To check whether a cell exists and isn't empty, use \ref hasElement. + + \see addElement, hasElement +*/ +QCPLayoutElement *QCPLayoutGrid::element(int row, int column) const +{ + if (row >= 0 && row < mElements.size()) + { + if (column >= 0 && column < mElements.first().size()) + { + if (QCPLayoutElement *result = mElements.at(row).at(column)) + return result; + else + qDebug() << Q_FUNC_INFO << "Requested cell is empty. Row:" << row << "Column:" << column; + } else + qDebug() << Q_FUNC_INFO << "Invalid column. Row:" << row << "Column:" << column; + } else + qDebug() << Q_FUNC_INFO << "Invalid row. Row:" << row << "Column:" << column; + return nullptr; +} + + +/*! \overload + + Adds the \a element to cell with \a row and \a column. If \a element is already in a layout, it + is first removed from there. If \a row or \a column don't exist yet, the layout is expanded + accordingly. + + Returns true if the element was added successfully, i.e. if the cell at \a row and \a column + didn't already have an element. + + Use the overload of this method without explicit row/column index to place the element according + to the configured fill order and wrapping settings. + + \see element, hasElement, take, remove +*/ +bool QCPLayoutGrid::addElement(int row, int column, QCPLayoutElement *element) +{ + if (!hasElement(row, column)) + { + if (element && element->layout()) // remove from old layout first + element->layout()->take(element); + expandTo(row+1, column+1); + mElements[row][column] = element; + if (element) + adoptElement(element); + return true; + } else + qDebug() << Q_FUNC_INFO << "There is already an element in the specified row/column:" << row << column; + return false; +} + +/*! \overload + + Adds the \a element to the next empty cell according to the current fill order (\ref + setFillOrder) and wrapping (\ref setWrap). If \a element is already in a layout, it is first + removed from there. If necessary, the layout is expanded to hold the new element. + + Returns true if the element was added successfully. + + \see setFillOrder, setWrap, element, hasElement, take, remove +*/ +bool QCPLayoutGrid::addElement(QCPLayoutElement *element) +{ + int rowIndex = 0; + int colIndex = 0; + if (mFillOrder == foColumnsFirst) + { + while (hasElement(rowIndex, colIndex)) + { + ++colIndex; + if (colIndex >= mWrap && mWrap > 0) + { + colIndex = 0; + ++rowIndex; + } + } + } else + { + while (hasElement(rowIndex, colIndex)) + { + ++rowIndex; + if (rowIndex >= mWrap && mWrap > 0) + { + rowIndex = 0; + ++colIndex; + } + } + } + return addElement(rowIndex, colIndex, element); +} + +/*! + Returns whether the cell at \a row and \a column exists and contains a valid element, i.e. isn't + empty. + + \see element +*/ +bool QCPLayoutGrid::hasElement(int row, int column) +{ + if (row >= 0 && row < rowCount() && column >= 0 && column < columnCount()) + return mElements.at(row).at(column); + else + return false; +} + +/*! + Sets the stretch \a factor of \a column. + + Stretch factors control the relative sizes of rows and columns. Cells will not be resized beyond + their minimum and maximum widths/heights, regardless of the stretch factor. (see \ref + QCPLayoutElement::setMinimumSize, \ref QCPLayoutElement::setMaximumSize, \ref + QCPLayoutElement::setSizeConstraintRect.) + + The default stretch factor of newly created rows/columns is 1. + + \see setColumnStretchFactors, setRowStretchFactor +*/ +void QCPLayoutGrid::setColumnStretchFactor(int column, double factor) +{ + if (column >= 0 && column < columnCount()) + { + if (factor > 0) + mColumnStretchFactors[column] = factor; + else + qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor; + } else + qDebug() << Q_FUNC_INFO << "Invalid column:" << column; +} + +/*! + Sets the stretch \a factors of all columns. \a factors must have the size \ref columnCount. + + Stretch factors control the relative sizes of rows and columns. Cells will not be resized beyond + their minimum and maximum widths/heights, regardless of the stretch factor. (see \ref + QCPLayoutElement::setMinimumSize, \ref QCPLayoutElement::setMaximumSize, \ref + QCPLayoutElement::setSizeConstraintRect.) + + The default stretch factor of newly created rows/columns is 1. + + \see setColumnStretchFactor, setRowStretchFactors +*/ +void QCPLayoutGrid::setColumnStretchFactors(const QList &factors) +{ + if (factors.size() == mColumnStretchFactors.size()) + { + mColumnStretchFactors = factors; + for (int i=0; i= 0 && row < rowCount()) + { + if (factor > 0) + mRowStretchFactors[row] = factor; + else + qDebug() << Q_FUNC_INFO << "Invalid stretch factor, must be positive:" << factor; + } else + qDebug() << Q_FUNC_INFO << "Invalid row:" << row; +} + +/*! + Sets the stretch \a factors of all rows. \a factors must have the size \ref rowCount. + + Stretch factors control the relative sizes of rows and columns. Cells will not be resized beyond + their minimum and maximum widths/heights, regardless of the stretch factor. (see \ref + QCPLayoutElement::setMinimumSize, \ref QCPLayoutElement::setMaximumSize, \ref + QCPLayoutElement::setSizeConstraintRect.) + + The default stretch factor of newly created rows/columns is 1. + + \see setRowStretchFactor, setColumnStretchFactors +*/ +void QCPLayoutGrid::setRowStretchFactors(const QList &factors) +{ + if (factors.size() == mRowStretchFactors.size()) + { + mRowStretchFactors = factors; + for (int i=0; i tempElements; + if (rearrange) + { + tempElements.reserve(elCount); + for (int i=0; i()); + mRowStretchFactors.append(1); + } + // go through rows and expand columns as necessary: + int newColCount = qMax(columnCount(), newColumnCount); + for (int i=0; i rowCount()) + newIndex = rowCount(); + + mRowStretchFactors.insert(newIndex, 1); + QList newRow; + for (int col=0; col columnCount()) + newIndex = columnCount(); + + mColumnStretchFactors.insert(newIndex, 1); + for (int row=0; row= 0 && row < rowCount()) + { + if (column >= 0 && column < columnCount()) + { + switch (mFillOrder) + { + case foRowsFirst: return column*rowCount() + row; + case foColumnsFirst: return row*columnCount() + column; + } + } else + qDebug() << Q_FUNC_INFO << "row index out of bounds:" << row; + } else + qDebug() << Q_FUNC_INFO << "column index out of bounds:" << column; + return 0; +} + +/*! + Converts the linear index to row and column indices and writes the result to \a row and \a + column. + + The way the cells are indexed depends on \ref setFillOrder. If it is \ref foRowsFirst, the + indices increase left to right and then top to bottom. If it is \ref foColumnsFirst, the indices + increase top to bottom and then left to right. + + If there are no cells (i.e. column or row count is zero), sets \a row and \a column to -1. + + For the retrieved \a row and \a column to be valid, the passed \a index must be valid itself, + i.e. greater or equal to zero and smaller than the current \ref elementCount. + + \see rowColToIndex +*/ +void QCPLayoutGrid::indexToRowCol(int index, int &row, int &column) const +{ + row = -1; + column = -1; + const int nCols = columnCount(); + const int nRows = rowCount(); + if (nCols == 0 || nRows == 0) + return; + if (index < 0 || index >= elementCount()) + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return; + } + + switch (mFillOrder) + { + case foRowsFirst: + { + column = index / nRows; + row = index % nRows; + break; + } + case foColumnsFirst: + { + row = index / nCols; + column = index % nCols; + break; + } + } +} + +/* inherits documentation from base class */ +void QCPLayoutGrid::updateLayout() +{ + QVector minColWidths, minRowHeights, maxColWidths, maxRowHeights; + getMinimumRowColSizes(&minColWidths, &minRowHeights); + getMaximumRowColSizes(&maxColWidths, &maxRowHeights); + + int totalRowSpacing = (rowCount()-1) * mRowSpacing; + int totalColSpacing = (columnCount()-1) * mColumnSpacing; + QVector colWidths = getSectionSizes(maxColWidths, minColWidths, mColumnStretchFactors.toVector(), mRect.width()-totalColSpacing); + QVector rowHeights = getSectionSizes(maxRowHeights, minRowHeights, mRowStretchFactors.toVector(), mRect.height()-totalRowSpacing); + + // go through cells and set rects accordingly: + int yOffset = mRect.top(); + for (int row=0; row 0) + yOffset += rowHeights.at(row-1)+mRowSpacing; + int xOffset = mRect.left(); + for (int col=0; col 0) + xOffset += colWidths.at(col-1)+mColumnSpacing; + if (mElements.at(row).at(col)) + mElements.at(row).at(col)->setOuterRect(QRect(xOffset, yOffset, colWidths.at(col), rowHeights.at(row))); + } + } +} + +/*! + \seebaseclassmethod + + Note that the association of the linear \a index to the row/column based cells depends on the + current setting of \ref setFillOrder. + + \see rowColToIndex +*/ +QCPLayoutElement *QCPLayoutGrid::elementAt(int index) const +{ + if (index >= 0 && index < elementCount()) + { + int row, col; + indexToRowCol(index, row, col); + return mElements.at(row).at(col); + } else + return nullptr; +} + +/*! + \seebaseclassmethod + + Note that the association of the linear \a index to the row/column based cells depends on the + current setting of \ref setFillOrder. + + \see rowColToIndex +*/ +QCPLayoutElement *QCPLayoutGrid::takeAt(int index) +{ + if (QCPLayoutElement *el = elementAt(index)) + { + releaseElement(el); + int row, col; + indexToRowCol(index, row, col); + mElements[row][col] = nullptr; + return el; + } else + { + qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index; + return nullptr; + } +} + +/* inherits documentation from base class */ +bool QCPLayoutGrid::take(QCPLayoutElement *element) +{ + if (element) + { + for (int i=0; i QCPLayoutGrid::elements(bool recursive) const +{ + QList result; + const int elCount = elementCount(); +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + result.reserve(elCount); +#endif + for (int i=0; ielements(recursive); + } + } + return result; +} + +/*! + Simplifies the layout by collapsing rows and columns which only contain empty cells. +*/ +void QCPLayoutGrid::simplify() +{ + // remove rows with only empty cells: + for (int row=rowCount()-1; row>=0; --row) + { + bool hasElements = false; + for (int col=0; col=0; --col) + { + bool hasElements = false; + for (int row=0; row minColWidths, minRowHeights; + getMinimumRowColSizes(&minColWidths, &minRowHeights); + QSize result(0, 0); + foreach (int w, minColWidths) + result.rwidth() += w; + foreach (int h, minRowHeights) + result.rheight() += h; + result.rwidth() += qMax(0, columnCount()-1) * mColumnSpacing; + result.rheight() += qMax(0, rowCount()-1) * mRowSpacing; + result.rwidth() += mMargins.left()+mMargins.right(); + result.rheight() += mMargins.top()+mMargins.bottom(); + return result; +} + +/* inherits documentation from base class */ +QSize QCPLayoutGrid::maximumOuterSizeHint() const +{ + QVector maxColWidths, maxRowHeights; + getMaximumRowColSizes(&maxColWidths, &maxRowHeights); + + QSize result(0, 0); + foreach (int w, maxColWidths) + result.setWidth(qMin(result.width()+w, QWIDGETSIZE_MAX)); + foreach (int h, maxRowHeights) + result.setHeight(qMin(result.height()+h, QWIDGETSIZE_MAX)); + result.rwidth() += qMax(0, columnCount()-1) * mColumnSpacing; + result.rheight() += qMax(0, rowCount()-1) * mRowSpacing; + result.rwidth() += mMargins.left()+mMargins.right(); + result.rheight() += mMargins.top()+mMargins.bottom(); + if (result.height() > QWIDGETSIZE_MAX) + result.setHeight(QWIDGETSIZE_MAX); + if (result.width() > QWIDGETSIZE_MAX) + result.setWidth(QWIDGETSIZE_MAX); + return result; +} + +/*! \internal + + Places the minimum column widths and row heights into \a minColWidths and \a minRowHeights + respectively. + + The minimum height of a row is the largest minimum height of any element's outer rect in that + row. The minimum width of a column is the largest minimum width of any element's outer rect in + that column. + + This is a helper function for \ref updateLayout. + + \see getMaximumRowColSizes +*/ +void QCPLayoutGrid::getMinimumRowColSizes(QVector *minColWidths, QVector *minRowHeights) const +{ + *minColWidths = QVector(columnCount(), 0); + *minRowHeights = QVector(rowCount(), 0); + for (int row=0; rowat(col) < minSize.width()) + (*minColWidths)[col] = minSize.width(); + if (minRowHeights->at(row) < minSize.height()) + (*minRowHeights)[row] = minSize.height(); + } + } + } +} + +/*! \internal + + Places the maximum column widths and row heights into \a maxColWidths and \a maxRowHeights + respectively. + + The maximum height of a row is the smallest maximum height of any element's outer rect in that + row. The maximum width of a column is the smallest maximum width of any element's outer rect in + that column. + + This is a helper function for \ref updateLayout. + + \see getMinimumRowColSizes +*/ +void QCPLayoutGrid::getMaximumRowColSizes(QVector *maxColWidths, QVector *maxRowHeights) const +{ + *maxColWidths = QVector(columnCount(), QWIDGETSIZE_MAX); + *maxRowHeights = QVector(rowCount(), QWIDGETSIZE_MAX); + for (int row=0; rowat(col) > maxSize.width()) + (*maxColWidths)[col] = maxSize.width(); + if (maxRowHeights->at(row) > maxSize.height()) + (*maxRowHeights)[row] = maxSize.height(); + } + } + } +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPLayoutInset +//////////////////////////////////////////////////////////////////////////////////////////////////// +/*! \class QCPLayoutInset + \brief A layout that places child elements aligned to the border or arbitrarily positioned + + Elements are placed either aligned to the border or at arbitrary position in the area of the + layout. Which placement applies is controlled with the \ref InsetPlacement (\ref + setInsetPlacement). + + Elements are added via \ref addElement(QCPLayoutElement *element, Qt::Alignment alignment) or + addElement(QCPLayoutElement *element, const QRectF &rect). If the first method is used, the inset + placement will default to \ref ipBorderAligned and the element will be aligned according to the + \a alignment parameter. The second method defaults to \ref ipFree and allows placing elements at + arbitrary position and size, defined by \a rect. + + The alignment or rect can be set via \ref setInsetAlignment or \ref setInsetRect, respectively. + + This is the layout that every QCPAxisRect has as \ref QCPAxisRect::insetLayout. +*/ + +/* start documentation of inline functions */ + +/*! \fn virtual void QCPLayoutInset::simplify() + + The QCPInsetLayout does not need simplification since it can never have empty cells due to its + linear index structure. This method does nothing. +*/ + +/* end documentation of inline functions */ + +/*! + Creates an instance of QCPLayoutInset and sets default values. +*/ +QCPLayoutInset::QCPLayoutInset() +{ +} + +QCPLayoutInset::~QCPLayoutInset() +{ + // clear all child layout elements. This is important because only the specific layouts know how + // to handle removing elements (clear calls virtual removeAt method to do that). + clear(); +} + +/*! + Returns the placement type of the element with the specified \a index. +*/ +QCPLayoutInset::InsetPlacement QCPLayoutInset::insetPlacement(int index) const +{ + if (elementAt(index)) + return mInsetPlacement.at(index); + else + { + qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; + return ipFree; + } +} + +/*! + Returns the alignment of the element with the specified \a index. The alignment only has a + meaning, if the inset placement (\ref setInsetPlacement) is \ref ipBorderAligned. +*/ +Qt::Alignment QCPLayoutInset::insetAlignment(int index) const +{ + if (elementAt(index)) + return mInsetAlignment.at(index); + else + { + qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; +#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) + return nullptr; +#else + return {}; +#endif + } +} + +/*! + Returns the rect of the element with the specified \a index. The rect only has a + meaning, if the inset placement (\ref setInsetPlacement) is \ref ipFree. +*/ +QRectF QCPLayoutInset::insetRect(int index) const +{ + if (elementAt(index)) + return mInsetRect.at(index); + else + { + qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; + return {}; + } +} + +/*! + Sets the inset placement type of the element with the specified \a index to \a placement. + + \see InsetPlacement +*/ +void QCPLayoutInset::setInsetPlacement(int index, QCPLayoutInset::InsetPlacement placement) +{ + if (elementAt(index)) + mInsetPlacement[index] = placement; + else + qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; +} + +/*! + If the inset placement (\ref setInsetPlacement) is \ref ipBorderAligned, this function + is used to set the alignment of the element with the specified \a index to \a alignment. + + \a alignment is an or combination of the following alignment flags: Qt::AlignLeft, + Qt::AlignHCenter, Qt::AlighRight, Qt::AlignTop, Qt::AlignVCenter, Qt::AlignBottom. Any other + alignment flags will be ignored. +*/ +void QCPLayoutInset::setInsetAlignment(int index, Qt::Alignment alignment) +{ + if (elementAt(index)) + mInsetAlignment[index] = alignment; + else + qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; +} + +/*! + If the inset placement (\ref setInsetPlacement) is \ref ipFree, this function is used to set the + position and size of the element with the specified \a index to \a rect. + + \a rect is given in fractions of the whole inset layout rect. So an inset with rect (0, 0, 1, 1) + will span the entire layout. An inset with rect (0.6, 0.1, 0.35, 0.35) will be in the top right + corner of the layout, with 35% width and height of the parent layout. + + Note that the minimum and maximum sizes of the embedded element (\ref + QCPLayoutElement::setMinimumSize, \ref QCPLayoutElement::setMaximumSize) are enforced. +*/ +void QCPLayoutInset::setInsetRect(int index, const QRectF &rect) +{ + if (elementAt(index)) + mInsetRect[index] = rect; + else + qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; +} + +/* inherits documentation from base class */ +void QCPLayoutInset::updateLayout() +{ + for (int i=0; i finalMaxSize.width()) + insetRect.setWidth(finalMaxSize.width()); + if (insetRect.size().height() > finalMaxSize.height()) + insetRect.setHeight(finalMaxSize.height()); + } else if (mInsetPlacement.at(i) == ipBorderAligned) + { + insetRect.setSize(finalMinSize); + Qt::Alignment al = mInsetAlignment.at(i); + if (al.testFlag(Qt::AlignLeft)) insetRect.moveLeft(rect().x()); + else if (al.testFlag(Qt::AlignRight)) insetRect.moveRight(rect().x()+rect().width()); + else insetRect.moveLeft(int( rect().x()+rect().width()*0.5-finalMinSize.width()*0.5 )); // default to Qt::AlignHCenter + if (al.testFlag(Qt::AlignTop)) insetRect.moveTop(rect().y()); + else if (al.testFlag(Qt::AlignBottom)) insetRect.moveBottom(rect().y()+rect().height()); + else insetRect.moveTop(int( rect().y()+rect().height()*0.5-finalMinSize.height()*0.5 )); // default to Qt::AlignVCenter + } + mElements.at(i)->setOuterRect(insetRect); + } +} + +/* inherits documentation from base class */ +int QCPLayoutInset::elementCount() const +{ + return mElements.size(); +} + +/* inherits documentation from base class */ +QCPLayoutElement *QCPLayoutInset::elementAt(int index) const +{ + if (index >= 0 && index < mElements.size()) + return mElements.at(index); + else + return nullptr; +} + +/* inherits documentation from base class */ +QCPLayoutElement *QCPLayoutInset::takeAt(int index) +{ + if (QCPLayoutElement *el = elementAt(index)) + { + releaseElement(el); + mElements.removeAt(index); + mInsetPlacement.removeAt(index); + mInsetAlignment.removeAt(index); + mInsetRect.removeAt(index); + return el; + } else + { + qDebug() << Q_FUNC_INFO << "Attempt to take invalid index:" << index; + return nullptr; + } +} + +/* inherits documentation from base class */ +bool QCPLayoutInset::take(QCPLayoutElement *element) +{ + if (element) + { + for (int i=0; irealVisibility() && el->selectTest(pos, onlySelectable) >= 0) + return mParentPlot->selectionTolerance()*0.99; + } + return -1; +} + +/*! + Adds the specified \a element to the layout as an inset aligned at the border (\ref + setInsetAlignment is initialized with \ref ipBorderAligned). The alignment is set to \a + alignment. + + \a alignment is an or combination of the following alignment flags: Qt::AlignLeft, + Qt::AlignHCenter, Qt::AlighRight, Qt::AlignTop, Qt::AlignVCenter, Qt::AlignBottom. Any other + alignment flags will be ignored. + + \see addElement(QCPLayoutElement *element, const QRectF &rect) +*/ +void QCPLayoutInset::addElement(QCPLayoutElement *element, Qt::Alignment alignment) +{ + if (element) + { + if (element->layout()) // remove from old layout first + element->layout()->take(element); + mElements.append(element); + mInsetPlacement.append(ipBorderAligned); + mInsetAlignment.append(alignment); + mInsetRect.append(QRectF(0.6, 0.6, 0.4, 0.4)); + adoptElement(element); + } else + qDebug() << Q_FUNC_INFO << "Can't add nullptr element"; +} + +/*! + Adds the specified \a element to the layout as an inset with free positioning/sizing (\ref + setInsetAlignment is initialized with \ref ipFree). The position and size is set to \a + rect. + + \a rect is given in fractions of the whole inset layout rect. So an inset with rect (0, 0, 1, 1) + will span the entire layout. An inset with rect (0.6, 0.1, 0.35, 0.35) will be in the top right + corner of the layout, with 35% width and height of the parent layout. + + \see addElement(QCPLayoutElement *element, Qt::Alignment alignment) +*/ +void QCPLayoutInset::addElement(QCPLayoutElement *element, const QRectF &rect) +{ + if (element) + { + if (element->layout()) // remove from old layout first + element->layout()->take(element); + mElements.append(element); + mInsetPlacement.append(ipFree); + mInsetAlignment.append(Qt::AlignRight|Qt::AlignTop); + mInsetRect.append(rect); + adoptElement(element); + } else + qDebug() << Q_FUNC_INFO << "Can't add nullptr element"; +} +/* end of 'src/layout.cpp' */ + + +/* including file 'src/lineending.cpp' */ +/* modified 2022-11-06T12:45:56, size 11189 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPLineEnding +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPLineEnding + \brief Handles the different ending decorations for line-like items + + \image html QCPLineEnding.png "The various ending styles currently supported" + + For every ending a line-like item has, an instance of this class exists. For example, QCPItemLine + has two endings which can be set with QCPItemLine::setHead and QCPItemLine::setTail. + + The styles themselves are defined via the enum QCPLineEnding::EndingStyle. Most decorations can + be modified regarding width and length, see \ref setWidth and \ref setLength. The direction of + the ending decoration (e.g. direction an arrow is pointing) is controlled by the line-like item. + For example, when both endings of a QCPItemLine are set to be arrows, they will point to opposite + directions, e.g. "outward". This can be changed by \ref setInverted, which would make the + respective arrow point inward. + + Note that due to the overloaded QCPLineEnding constructor, you may directly specify a + QCPLineEnding::EndingStyle where actually a QCPLineEnding is expected, e.g. + \snippet documentation/doc-code-snippets/mainwindow.cpp qcplineending-sethead +*/ + +/*! + Creates a QCPLineEnding instance with default values (style \ref esNone). +*/ +QCPLineEnding::QCPLineEnding() : + mStyle(esNone), + mWidth(8), + mLength(10), + mInverted(false) +{ +} + +/*! + Creates a QCPLineEnding instance with the specified values. +*/ +QCPLineEnding::QCPLineEnding(QCPLineEnding::EndingStyle style, double width, double length, bool inverted) : + mStyle(style), + mWidth(width), + mLength(length), + mInverted(inverted) +{ +} + +/*! + Sets the style of the ending decoration. +*/ +void QCPLineEnding::setStyle(QCPLineEnding::EndingStyle style) +{ + mStyle = style; +} + +/*! + Sets the width of the ending decoration, if the style supports it. On arrows, for example, the + width defines the size perpendicular to the arrow's pointing direction. + + \see setLength +*/ +void QCPLineEnding::setWidth(double width) +{ + mWidth = width; +} + +/*! + Sets the length of the ending decoration, if the style supports it. On arrows, for example, the + length defines the size in pointing direction. + + \see setWidth +*/ +void QCPLineEnding::setLength(double length) +{ + mLength = length; +} + +/*! + Sets whether the ending decoration shall be inverted. For example, an arrow decoration will point + inward when \a inverted is set to true. + + Note that also the \a width direction is inverted. For symmetrical ending styles like arrows or + discs, this doesn't make a difference. However, asymmetric styles like \ref esHalfBar are + affected by it, which can be used to control to which side the half bar points to. +*/ +void QCPLineEnding::setInverted(bool inverted) +{ + mInverted = inverted; +} + +/*! \internal + + Returns the maximum pixel radius the ending decoration might cover, starting from the position + the decoration is drawn at (typically a line ending/\ref QCPItemPosition of an item). + + This is relevant for clipping. Only omit painting of the decoration when the position where the + decoration is supposed to be drawn is farther away from the clipping rect than the returned + distance. +*/ +double QCPLineEnding::boundingDistance() const +{ + switch (mStyle) + { + case esNone: + return 0; + + case esFlatArrow: + case esSpikeArrow: + case esLineArrow: + case esSkewedBar: + return qSqrt(mWidth*mWidth+mLength*mLength); // items that have width and length + + case esDisc: + case esSquare: + case esDiamond: + case esBar: + case esHalfBar: + return mWidth*1.42; // items that only have a width -> width*sqrt(2) + + } + return 0; +} + +/*! + Starting from the origin of this line ending (which is style specific), returns the length + covered by the line ending symbol, in backward direction. + + For example, the \ref esSpikeArrow has a shorter real length than a \ref esFlatArrow, even if + both have the same \ref setLength value, because the spike arrow has an inward curved back, which + reduces the length along its center axis (the drawing origin for arrows is at the tip). + + This function is used for precise, style specific placement of line endings, for example in + QCPAxes. +*/ +double QCPLineEnding::realLength() const +{ + switch (mStyle) + { + case esNone: + case esLineArrow: + case esSkewedBar: + case esBar: + case esHalfBar: + return 0; + + case esFlatArrow: + return mLength; + + case esDisc: + case esSquare: + case esDiamond: + return mWidth*0.5; + + case esSpikeArrow: + return mLength*0.8; + } + return 0; +} + +/*! \internal + + Draws the line ending with the specified \a painter at the position \a pos. The direction of the + line ending is controlled with \a dir. +*/ +void QCPLineEnding::draw(QCPPainter *painter, const QCPVector2D &pos, const QCPVector2D &dir) const +{ + if (mStyle == esNone) + return; + + QCPVector2D lengthVec = dir.normalized() * mLength*(mInverted ? -1 : 1); + if (lengthVec.isNull()) + lengthVec = QCPVector2D(1, 0); + QCPVector2D widthVec = dir.normalized().perpendicular() * mWidth*0.5*(mInverted ? -1 : 1); + + QPen penBackup = painter->pen(); + QBrush brushBackup = painter->brush(); + QPen miterPen = penBackup; + miterPen.setJoinStyle(Qt::MiterJoin); // to make arrow heads spikey + QBrush brush(painter->pen().color(), Qt::SolidPattern); + switch (mStyle) + { + case esNone: break; + case esFlatArrow: + { + QPointF points[3] = {pos.toPointF(), + (pos-lengthVec+widthVec).toPointF(), + (pos-lengthVec-widthVec).toPointF() + }; + painter->setPen(miterPen); + painter->setBrush(brush); + painter->drawConvexPolygon(points, 3); + painter->setBrush(brushBackup); + painter->setPen(penBackup); + break; + } + case esSpikeArrow: + { + QPointF points[4] = {pos.toPointF(), + (pos-lengthVec+widthVec).toPointF(), + (pos-lengthVec*0.8).toPointF(), + (pos-lengthVec-widthVec).toPointF() + }; + painter->setPen(miterPen); + painter->setBrush(brush); + painter->drawConvexPolygon(points, 4); + painter->setBrush(brushBackup); + painter->setPen(penBackup); + break; + } + case esLineArrow: + { + QPointF points[3] = {(pos-lengthVec+widthVec).toPointF(), + pos.toPointF(), + (pos-lengthVec-widthVec).toPointF() + }; + painter->setPen(miterPen); + painter->drawPolyline(points, 3); + painter->setPen(penBackup); + break; + } + case esDisc: + { + painter->setBrush(brush); + painter->drawEllipse(pos.toPointF(), mWidth*0.5, mWidth*0.5); + painter->setBrush(brushBackup); + break; + } + case esSquare: + { + QCPVector2D widthVecPerp = widthVec.perpendicular(); + QPointF points[4] = {(pos-widthVecPerp+widthVec).toPointF(), + (pos-widthVecPerp-widthVec).toPointF(), + (pos+widthVecPerp-widthVec).toPointF(), + (pos+widthVecPerp+widthVec).toPointF() + }; + painter->setPen(miterPen); + painter->setBrush(brush); + painter->drawConvexPolygon(points, 4); + painter->setBrush(brushBackup); + painter->setPen(penBackup); + break; + } + case esDiamond: + { + QCPVector2D widthVecPerp = widthVec.perpendicular(); + QPointF points[4] = {(pos-widthVecPerp).toPointF(), + (pos-widthVec).toPointF(), + (pos+widthVecPerp).toPointF(), + (pos+widthVec).toPointF() + }; + painter->setPen(miterPen); + painter->setBrush(brush); + painter->drawConvexPolygon(points, 4); + painter->setBrush(brushBackup); + painter->setPen(penBackup); + break; + } + case esBar: + { + painter->drawLine((pos+widthVec).toPointF(), (pos-widthVec).toPointF()); + break; + } + case esHalfBar: + { + painter->drawLine((pos+widthVec).toPointF(), pos.toPointF()); + break; + } + case esSkewedBar: + { + QCPVector2D shift; + if (!qFuzzyIsNull(painter->pen().widthF()) || painter->modes().testFlag(QCPPainter::pmNonCosmetic)) + shift = dir.normalized()*qMax(qreal(1.0), painter->pen().widthF())*qreal(0.5); + // if drawing with thick (non-cosmetic) pen, shift bar a little in line direction to prevent line from sticking through bar slightly + painter->drawLine((pos+widthVec+lengthVec*0.2*(mInverted?-1:1)+shift).toPointF(), + (pos-widthVec-lengthVec*0.2*(mInverted?-1:1)+shift).toPointF()); + break; + } + } +} + +/*! \internal + \overload + + Draws the line ending. The direction is controlled with the \a angle parameter in radians. +*/ +void QCPLineEnding::draw(QCPPainter *painter, const QCPVector2D &pos, double angle) const +{ + draw(painter, pos, QCPVector2D(qCos(angle), qSin(angle))); +} +/* end of 'src/lineending.cpp' */ + + +/* including file 'src/axis/labelpainter.cpp' */ +/* modified 2022-11-06T12:45:56, size 27519 */ + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPLabelPainterPrivate +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPLabelPainterPrivate + + \internal + \brief (Private) + + This is a private class and not part of the public QCustomPlot interface. + +*/ + +const QChar QCPLabelPainterPrivate::SymbolDot(183); +const QChar QCPLabelPainterPrivate::SymbolCross(215); + +/*! + Constructs a QCPLabelPainterPrivate instance. Make sure to not create a new + instance on every redraw, to utilize the caching mechanisms. + + the \a parentPlot does not take ownership of the label painter. Make sure + to delete it appropriately. +*/ +QCPLabelPainterPrivate::QCPLabelPainterPrivate(QCustomPlot *parentPlot) : + mAnchorMode(amRectangular), + mAnchorSide(asLeft), + mAnchorReferenceType(artNormal), + mColor(Qt::black), + mPadding(0), + mRotation(0), + mSubstituteExponent(true), + mMultiplicationSymbol(QChar(215)), + mAbbreviateDecimalPowers(false), + mParentPlot(parentPlot), + mLabelCache(16) +{ + analyzeFontMetrics(); +} + +QCPLabelPainterPrivate::~QCPLabelPainterPrivate() +{ +} + +void QCPLabelPainterPrivate::setAnchorSide(AnchorSide side) +{ + mAnchorSide = side; +} + +void QCPLabelPainterPrivate::setAnchorMode(AnchorMode mode) +{ + mAnchorMode = mode; +} + +void QCPLabelPainterPrivate::setAnchorReference(const QPointF &pixelPoint) +{ + mAnchorReference = pixelPoint; +} + +void QCPLabelPainterPrivate::setAnchorReferenceType(AnchorReferenceType type) +{ + mAnchorReferenceType = type; +} + +void QCPLabelPainterPrivate::setFont(const QFont &font) +{ + if (mFont != font) + { + mFont = font; + analyzeFontMetrics(); + } +} + +void QCPLabelPainterPrivate::setColor(const QColor &color) +{ + mColor = color; +} + +void QCPLabelPainterPrivate::setPadding(int padding) +{ + mPadding = padding; +} + +void QCPLabelPainterPrivate::setRotation(double rotation) +{ + mRotation = qBound(-90.0, rotation, 90.0); +} + +void QCPLabelPainterPrivate::setSubstituteExponent(bool enabled) +{ + mSubstituteExponent = enabled; +} + +void QCPLabelPainterPrivate::setMultiplicationSymbol(QChar symbol) +{ + mMultiplicationSymbol = symbol; +} + +void QCPLabelPainterPrivate::setAbbreviateDecimalPowers(bool enabled) +{ + mAbbreviateDecimalPowers = enabled; +} + +void QCPLabelPainterPrivate::setCacheSize(int labelCount) +{ + mLabelCache.setMaxCost(labelCount); +} + +int QCPLabelPainterPrivate::cacheSize() const +{ + return mLabelCache.maxCost(); +} + +void QCPLabelPainterPrivate::drawTickLabel(QCPPainter *painter, const QPointF &tickPos, const QString &text) +{ + double realRotation = mRotation; + + AnchorSide realSide = mAnchorSide; + // for circular axes, the anchor side is determined depending on the quadrant of tickPos with respect to mCircularReference + if (mAnchorMode == amSkewedUpright) + { + realSide = skewedAnchorSide(tickPos, 0.2, 0.3); + } else if (mAnchorMode == amSkewedRotated) // in this mode every label is individually rotated to match circle tangent + { + realSide = skewedAnchorSide(tickPos, 0, 0); + realRotation += QCPVector2D(tickPos-mAnchorReference).angle()/M_PI*180.0; + if (realRotation > 90) realRotation -= 180; + else if (realRotation < -90) realRotation += 180; + } + + realSide = rotationCorrectedSide(realSide, realRotation); // rotation angles may change the true anchor side of the label + drawLabelMaybeCached(painter, mFont, mColor, getAnchorPos(tickPos), realSide, realRotation, text); +} + +/*! \internal + + Returns the size ("margin" in QCPAxisRect context, so measured perpendicular to the axis backbone + direction) needed to fit the axis. +*/ +/* TODO: needed? +int QCPLabelPainterPrivate::size() const +{ + int result = 0; + // get length of tick marks pointing outwards: + if (!tickPositions.isEmpty()) + result += qMax(0, qMax(tickLengthOut, subTickLengthOut)); + + // calculate size of tick labels: + if (tickLabelSide == QCPAxis::lsOutside) + { + QSize tickLabelsSize(0, 0); + if (!tickLabels.isEmpty()) + { + for (int i=0; ibufferDevicePixelRatio())); + result.append(QByteArray::number(mRotation)); + //result.append(QByteArray::number(int(tickLabelSide))); TODO: check whether this is really a cache-invalidating property + result.append(QByteArray::number(int(mSubstituteExponent))); + result.append(QString(mMultiplicationSymbol).toUtf8()); + result.append(mColor.name().toLatin1()+QByteArray::number(mColor.alpha(), 16)); + result.append(mFont.toString().toLatin1()); + return result; +} + +/*! \internal + + Draws a single tick label with the provided \a painter, utilizing the internal label cache to + significantly speed up drawing of labels that were drawn in previous calls. The tick label is + always bound to an axis, the distance to the axis is controllable via \a distanceToAxis in + pixels. The pixel position in the axis direction is passed in the \a position parameter. Hence + for the bottom axis, \a position would indicate the horizontal pixel position (not coordinate), + at which the label should be drawn. + + In order to later draw the axis label in a place that doesn't overlap with the tick labels, the + largest tick label size is needed. This is acquired by passing a \a tickLabelsSize to the \ref + drawTickLabel calls during the process of drawing all tick labels of one axis. In every call, \a + tickLabelsSize is expanded, if the drawn label exceeds the value \a tickLabelsSize currently + holds. + + The label is drawn with the font and pen that are currently set on the \a painter. To draw + superscripted powers, the font is temporarily made smaller by a fixed factor (see \ref + getTickLabelData). +*/ +void QCPLabelPainterPrivate::drawLabelMaybeCached(QCPPainter *painter, const QFont &font, const QColor &color, const QPointF &pos, AnchorSide side, double rotation, const QString &text) +{ + // warning: if you change anything here, also adapt getMaxTickLabelSize() accordingly! + if (text.isEmpty()) return; + QSize finalSize; + + if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && !painter->modes().testFlag(QCPPainter::pmNoCaching)) // label caching enabled + { + QByteArray key = cacheKey(text, color, rotation, side); + CachedLabel *cachedLabel = mLabelCache.take(QString::fromUtf8(key)); // attempt to take label from cache (don't use object() because we want ownership/prevent deletion during our operations, we re-insert it afterwards) + if (!cachedLabel) // no cached label existed, create it + { + LabelData labelData = getTickLabelData(font, color, rotation, side, text); + cachedLabel = createCachedLabel(labelData); + } + // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels): + bool labelClippedByBorder = false; + /* + if (tickLabelSide == QCPAxis::lsOutside) + { + if (QCPAxis::orientation(type) == Qt::Horizontal) + labelClippedByBorder = labelAnchor.x()+cachedLabel->offset.x()+cachedLabel->pixmap.width()/mParentPlot->bufferDevicePixelRatio() > viewportRect.right() || labelAnchor.x()+cachedLabel->offset.x() < viewportRect.left(); + else + labelClippedByBorder = labelAnchor.y()+cachedLabel->offset.y()+cachedLabel->pixmap.height()/mParentPlot->bufferDevicePixelRatio() > viewportRect.bottom() || labelAnchor.y()+cachedLabel->offset.y() < viewportRect.top(); + } + */ + if (!labelClippedByBorder) + { + painter->drawPixmap(pos+cachedLabel->offset, cachedLabel->pixmap); + finalSize = cachedLabel->pixmap.size()/mParentPlot->bufferDevicePixelRatio(); // TODO: collect this in a member rect list? + } + mLabelCache.insert(QString::fromUtf8(key), cachedLabel); + } else // label caching disabled, draw text directly on surface: + { + LabelData labelData = getTickLabelData(font, color, rotation, side, text); + // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels): + bool labelClippedByBorder = false; + /* + if (tickLabelSide == QCPAxis::lsOutside) + { + if (QCPAxis::orientation(type) == Qt::Horizontal) + labelClippedByBorder = finalPosition.x()+(labelData.rotatedTotalBounds.width()+labelData.rotatedTotalBounds.left()) > viewportRect.right() || finalPosition.x()+labelData.rotatedTotalBounds.left() < viewportRect.left(); + else + labelClippedByBorder = finalPosition.y()+(labelData.rotatedTotalBounds.height()+labelData.rotatedTotalBounds.top()) > viewportRect.bottom() || finalPosition.y()+labelData.rotatedTotalBounds.top() < viewportRect.top(); + } + */ + if (!labelClippedByBorder) + { + drawText(painter, pos, labelData); + finalSize = labelData.rotatedTotalBounds.size(); + } + } + /* + // expand passed tickLabelsSize if current tick label is larger: + if (finalSize.width() > tickLabelsSize->width()) + tickLabelsSize->setWidth(finalSize.width()); + if (finalSize.height() > tickLabelsSize->height()) + tickLabelsSize->setHeight(finalSize.height()); + */ +} + +QPointF QCPLabelPainterPrivate::getAnchorPos(const QPointF &tickPos) +{ + switch (mAnchorMode) + { + case amRectangular: + { + switch (mAnchorSide) + { + case asLeft: return tickPos+QPointF(mPadding, 0); + case asRight: return tickPos+QPointF(-mPadding, 0); + case asTop: return tickPos+QPointF(0, mPadding); + case asBottom: return tickPos+QPointF(0, -mPadding); + case asTopLeft: return tickPos+QPointF(mPadding*M_SQRT1_2, mPadding*M_SQRT1_2); + case asTopRight: return tickPos+QPointF(-mPadding*M_SQRT1_2, mPadding*M_SQRT1_2); + case asBottomRight: return tickPos+QPointF(-mPadding*M_SQRT1_2, -mPadding*M_SQRT1_2); + case asBottomLeft: return tickPos+QPointF(mPadding*M_SQRT1_2, -mPadding*M_SQRT1_2); + default: qDebug() << Q_FUNC_INFO << "invalid mode for anchor side: " << mAnchorSide; break; + } + break; + } + case amSkewedUpright: + // fall through + case amSkewedRotated: + { + QCPVector2D anchorNormal(tickPos-mAnchorReference); + if (mAnchorReferenceType == artTangent) + anchorNormal = anchorNormal.perpendicular(); + anchorNormal.normalize(); + return tickPos+(anchorNormal*mPadding).toPointF(); + } + default: qDebug() << Q_FUNC_INFO << "invalid mode for anchor mode: " << mAnchorMode; break; + } + return tickPos; +} + +/*! \internal + + This is a \ref placeTickLabel helper function. + + Draws the tick label specified in \a labelData with \a painter at the pixel positions \a x and \a + y. This function is used by \ref placeTickLabel to create new tick labels for the cache, or to + directly draw the labels on the QCustomPlot surface when label caching is disabled, i.e. when + QCP::phCacheLabels plotting hint is not set. +*/ +void QCPLabelPainterPrivate::drawText(QCPPainter *painter, const QPointF &pos, const LabelData &labelData) const +{ + // backup painter settings that we're about to change: + QTransform oldTransform = painter->transform(); + QFont oldFont = painter->font(); + QPen oldPen = painter->pen(); + + // transform painter to position/rotation: + painter->translate(pos); + painter->setTransform(labelData.transform, true); + + // draw text: + painter->setFont(labelData.baseFont); + painter->setPen(QPen(labelData.color)); + if (!labelData.expPart.isEmpty()) // use superscripted exponent typesetting + { + painter->drawText(0, 0, 0, 0, Qt::TextDontClip, labelData.basePart); + if (!labelData.suffixPart.isEmpty()) + painter->drawText(labelData.baseBounds.width()+1+labelData.expBounds.width(), 0, 0, 0, Qt::TextDontClip, labelData.suffixPart); + painter->setFont(labelData.expFont); + painter->drawText(labelData.baseBounds.width()+1, 0, labelData.expBounds.width(), labelData.expBounds.height(), Qt::TextDontClip, labelData.expPart); + } else + { + painter->drawText(0, 0, labelData.totalBounds.width(), labelData.totalBounds.height(), Qt::TextDontClip | Qt::AlignHCenter, labelData.basePart); + } + + /* Debug code to draw label bounding boxes, baseline, and capheight + painter->save(); + painter->setPen(QPen(QColor(0, 0, 0, 150))); + painter->drawRect(labelData.totalBounds); + const int baseline = labelData.totalBounds.height()-mLetterDescent; + painter->setPen(QPen(QColor(255, 0, 0, 150))); + painter->drawLine(QLineF(0, baseline, labelData.totalBounds.width(), baseline)); + painter->setPen(QPen(QColor(0, 0, 255, 150))); + painter->drawLine(QLineF(0, baseline-mLetterCapHeight, labelData.totalBounds.width(), baseline-mLetterCapHeight)); + painter->restore(); + */ + + // reset painter settings to what it was before: + painter->setTransform(oldTransform); + painter->setFont(oldFont); + painter->setPen(oldPen); +} + +/*! \internal + + This is a \ref placeTickLabel helper function. + + Transforms the passed \a text and \a font to a tickLabelData structure that can then be further + processed by \ref getTickLabelDrawOffset and \ref drawTickLabel. It splits the text into base and + exponent if necessary (member substituteExponent) and calculates appropriate bounding boxes. +*/ +QCPLabelPainterPrivate::LabelData QCPLabelPainterPrivate::getTickLabelData(const QFont &font, const QColor &color, double rotation, AnchorSide side, const QString &text) const +{ + LabelData result; + result.rotation = rotation; + result.side = side; + result.color = color; + + // determine whether beautiful decimal powers should be used + bool useBeautifulPowers = false; + int ePos = -1; // first index of exponent part, text before that will be basePart, text until eLast will be expPart + int eLast = -1; // last index of exponent part, rest of text after this will be suffixPart + if (mSubstituteExponent) + { + ePos = text.indexOf(QLatin1Char('e')); + if (ePos > 0 && text.at(ePos-1).isDigit()) + { + eLast = ePos; + while (eLast+1 < text.size() && (text.at(eLast+1) == QLatin1Char('+') || text.at(eLast+1) == QLatin1Char('-') || text.at(eLast+1).isDigit())) + ++eLast; + if (eLast > ePos) // only if also to right of 'e' is a digit/+/- interpret it as beautifiable power + useBeautifulPowers = true; + } + } + + // calculate text bounding rects and do string preparation for beautiful decimal powers: + result.baseFont = font; + if (result.baseFont.pointSizeF() > 0) // might return -1 if specified with setPixelSize, in that case we can't do correction in next line + result.baseFont.setPointSizeF(result.baseFont.pointSizeF()+0.05); // QFontMetrics.boundingRect has a bug for exact point sizes that make the results oscillate due to internal rounding + + QFontMetrics baseFontMetrics(result.baseFont); + if (useBeautifulPowers) + { + // split text into parts of number/symbol that will be drawn normally and part that will be drawn as exponent: + result.basePart = text.left(ePos); + result.suffixPart = text.mid(eLast+1); // also drawn normally but after exponent + // in log scaling, we want to turn "1*10^n" into "10^n", else add multiplication sign and decimal base: + if (mAbbreviateDecimalPowers && result.basePart == QLatin1String("1")) + result.basePart = QLatin1String("10"); + else + result.basePart += QString(mMultiplicationSymbol) + QLatin1String("10"); + result.expPart = text.mid(ePos+1, eLast-ePos); + // clip "+" and leading zeros off expPart: + while (result.expPart.length() > 2 && result.expPart.at(1) == QLatin1Char('0')) // length > 2 so we leave one zero when numberFormatChar is 'e' + result.expPart.remove(1, 1); + if (!result.expPart.isEmpty() && result.expPart.at(0) == QLatin1Char('+')) + result.expPart.remove(0, 1); + // prepare smaller font for exponent: + result.expFont = font; + if (result.expFont.pointSize() > 0) + result.expFont.setPointSize(result.expFont.pointSize()*0.75); + else + result.expFont.setPixelSize(result.expFont.pixelSize()*0.75); + // calculate bounding rects of base part(s), exponent part and total one: + result.baseBounds = baseFontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.basePart); + result.expBounds = QFontMetrics(result.expFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.expPart); + if (!result.suffixPart.isEmpty()) + result.suffixBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.suffixPart); + result.totalBounds = result.baseBounds.adjusted(0, 0, result.expBounds.width()+result.suffixBounds.width()+2, 0); // +2 consists of the 1 pixel spacing between base and exponent (see drawTickLabel) and an extra pixel to include AA + } else // useBeautifulPowers == false + { + result.basePart = text; + result.totalBounds = baseFontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter, result.basePart); + } + result.totalBounds.moveTopLeft(QPoint(0, 0)); + applyAnchorTransform(result); + result.rotatedTotalBounds = result.transform.mapRect(result.totalBounds); + + return result; +} + +void QCPLabelPainterPrivate::applyAnchorTransform(LabelData &labelData) const +{ + if (!qFuzzyIsNull(labelData.rotation)) + labelData.transform.rotate(labelData.rotation); // rotates effectively clockwise (due to flipped y axis of painter vs widget coordinate system) + + // from now on we translate in rotated label-local coordinate system. + // shift origin of coordinate system to appropriate point on label: + labelData.transform.translate(0, -labelData.totalBounds.height()+mLetterDescent+mLetterCapHeight); // shifts origin to true top of capital (or number) characters + + if (labelData.side == asLeft || labelData.side == asRight) // anchor is centered vertically + labelData.transform.translate(0, -mLetterCapHeight/2.0); + else if (labelData.side == asTop || labelData.side == asBottom) // anchor is centered horizontally + labelData.transform.translate(-labelData.totalBounds.width()/2.0, 0); + + if (labelData.side == asTopRight || labelData.side == asRight || labelData.side == asBottomRight) // anchor is at right + labelData.transform.translate(-labelData.totalBounds.width(), 0); + if (labelData.side == asBottomLeft || labelData.side == asBottom || labelData.side == asBottomRight) // anchor is at bottom (no elseif!) + labelData.transform.translate(0, -mLetterCapHeight); +} + +/*! \internal + + Simulates the steps done by \ref placeTickLabel by calculating bounding boxes of the text label + to be drawn, depending on number format etc. Since only the largest tick label is wanted for the + margin calculation, the passed \a tickLabelsSize is only expanded, if it's currently set to a + smaller width/height. +*/ +/* +void QCPLabelPainterPrivate::getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const +{ + // note: this function must return the same tick label sizes as the placeTickLabel function. + QSize finalSize; + if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && mLabelCache.contains(text)) // label caching enabled and have cached label + { + const CachedLabel *cachedLabel = mLabelCache.object(text); + finalSize = cachedLabel->pixmap.size()/mParentPlot->bufferDevicePixelRatio(); + } else // label caching disabled or no label with this text cached: + { + // TODO: LabelData labelData = getTickLabelData(font, text); + // TODO: finalSize = labelData.rotatedTotalBounds.size(); + } + + // expand passed tickLabelsSize if current tick label is larger: + if (finalSize.width() > tickLabelsSize->width()) + tickLabelsSize->setWidth(finalSize.width()); + if (finalSize.height() > tickLabelsSize->height()) + tickLabelsSize->setHeight(finalSize.height()); +} +*/ + +QCPLabelPainterPrivate::CachedLabel *QCPLabelPainterPrivate::createCachedLabel(const LabelData &labelData) const +{ + CachedLabel *result = new CachedLabel; + + // allocate pixmap with the correct size and pixel ratio: + if (!qFuzzyCompare(1.0, mParentPlot->bufferDevicePixelRatio())) + { + result->pixmap = QPixmap(labelData.rotatedTotalBounds.size()*mParentPlot->bufferDevicePixelRatio()); +#ifdef QCP_DEVICEPIXELRATIO_SUPPORTED +# ifdef QCP_DEVICEPIXELRATIO_FLOAT + result->pixmap.setDevicePixelRatio(mParentPlot->devicePixelRatioF()); +# else + result->pixmap.setDevicePixelRatio(mParentPlot->devicePixelRatio()); +# endif +#endif + } else + result->pixmap = QPixmap(labelData.rotatedTotalBounds.size()); + result->pixmap.fill(Qt::transparent); + + // draw the label into the pixmap + // offset is between label anchor and topleft of cache pixmap, so pixmap can be drawn at pos+offset to make the label anchor appear at pos. + // We use rotatedTotalBounds.topLeft() because rotatedTotalBounds is in a coordinate system where the label anchor is at (0, 0) + result->offset = labelData.rotatedTotalBounds.topLeft(); + QCPPainter cachePainter(&result->pixmap); + drawText(&cachePainter, -result->offset, labelData); + return result; +} + +QByteArray QCPLabelPainterPrivate::cacheKey(const QString &text, const QColor &color, double rotation, AnchorSide side) const +{ + return text.toUtf8()+ + QByteArray::number(color.red()+256*color.green()+65536*color.blue(), 36)+ + QByteArray::number(color.alpha()+256*int(side), 36)+ + QByteArray::number(int(rotation*100), 36); +} + +QCPLabelPainterPrivate::AnchorSide QCPLabelPainterPrivate::skewedAnchorSide(const QPointF &tickPos, double sideExpandHorz, double sideExpandVert) const +{ + QCPVector2D anchorNormal = QCPVector2D(tickPos-mAnchorReference); + if (mAnchorReferenceType == artTangent) + anchorNormal = anchorNormal.perpendicular(); + const double radius = anchorNormal.length(); + const double sideHorz = sideExpandHorz*radius; + const double sideVert = sideExpandVert*radius; + if (anchorNormal.x() > sideHorz) + { + if (anchorNormal.y() > sideVert) return asTopLeft; + else if (anchorNormal.y() < -sideVert) return asBottomLeft; + else return asLeft; + } else if (anchorNormal.x() < -sideHorz) + { + if (anchorNormal.y() > sideVert) return asTopRight; + else if (anchorNormal.y() < -sideVert) return asBottomRight; + else return asRight; + } else + { + if (anchorNormal.y() > 0) return asTop; + else return asBottom; + } + return asBottom; // should never be reached +} + +QCPLabelPainterPrivate::AnchorSide QCPLabelPainterPrivate::rotationCorrectedSide(AnchorSide side, double rotation) const +{ + AnchorSide result = side; + const bool rotateClockwise = rotation > 0; + if (!qFuzzyIsNull(rotation)) + { + if (!qFuzzyCompare(qAbs(rotation), 90)) // avoid graphical collision with anchor tangent (e.g. axis line) when rotating, so change anchor side appropriately: + { + if (side == asTop) result = rotateClockwise ? asLeft : asRight; + else if (side == asBottom) result = rotateClockwise ? asRight : asLeft; + else if (side == asTopLeft) result = rotateClockwise ? asLeft : asTop; + else if (side == asTopRight) result = rotateClockwise ? asTop : asRight; + else if (side == asBottomLeft) result = rotateClockwise ? asBottom : asLeft; + else if (side == asBottomRight) result = rotateClockwise ? asRight : asBottom; + } else // for full rotation by +/-90 degrees, other sides are more appropriate for centering on anchor: + { + if (side == asLeft) result = rotateClockwise ? asBottom : asTop; + else if (side == asRight) result = rotateClockwise ? asTop : asBottom; + else if (side == asTop) result = rotateClockwise ? asLeft : asRight; + else if (side == asBottom) result = rotateClockwise ? asRight : asLeft; + else if (side == asTopLeft) result = rotateClockwise ? asBottomLeft : asTopRight; + else if (side == asTopRight) result = rotateClockwise ? asTopLeft : asBottomRight; + else if (side == asBottomLeft) result = rotateClockwise ? asBottomRight : asTopLeft; + else if (side == asBottomRight) result = rotateClockwise ? asTopRight : asBottomLeft; + } + } + return result; +} + +void QCPLabelPainterPrivate::analyzeFontMetrics() +{ + const QFontMetrics fm(mFont); + mLetterCapHeight = fm.tightBoundingRect(QLatin1String("8")).height(); // this method is slow, that's why we query it only upon font change + mLetterDescent = fm.descent(); +} +/* end of 'src/axis/labelpainter.cpp' */ + + +/* including file 'src/axis/axisticker.cpp' */ +/* modified 2022-11-06T12:45:56, size 18693 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAxisTicker +//////////////////////////////////////////////////////////////////////////////////////////////////// +/*! \class QCPAxisTicker + \brief The base class tick generator used by QCPAxis to create tick positions and tick labels + + Each QCPAxis has an internal QCPAxisTicker (or a subclass) in order to generate tick positions + and tick labels for the current axis range. The ticker of an axis can be set via \ref + QCPAxis::setTicker. Since that method takes a QSharedPointer, multiple + axes can share the same ticker instance. + + This base class generates normal tick coordinates and numeric labels for linear axes. It picks a + reasonable tick step (the separation between ticks) which results in readable tick labels. The + number of ticks that should be approximately generated can be set via \ref setTickCount. + Depending on the current tick step strategy (\ref setTickStepStrategy), the algorithm either + sacrifices readability to better match the specified tick count (\ref + QCPAxisTicker::tssMeetTickCount) or relaxes the tick count in favor of better tick steps (\ref + QCPAxisTicker::tssReadability), which is the default. + + The following more specialized axis ticker subclasses are available, see details in the + respective class documentation: + +

+ + + + + + + +
QCPAxisTickerFixed\image html axisticker-fixed.png
QCPAxisTickerLog\image html axisticker-log.png
QCPAxisTickerPi\image html axisticker-pi.png
QCPAxisTickerText\image html axisticker-text.png
QCPAxisTickerDateTime\image html axisticker-datetime.png
QCPAxisTickerTime\image html axisticker-time.png + \image html axisticker-time2.png
+
+ + \section axisticker-subclassing Creating own axis tickers + + Creating own axis tickers can be achieved very easily by sublassing QCPAxisTicker and + reimplementing some or all of the available virtual methods. + + In the simplest case you might wish to just generate different tick steps than the other tickers, + so you only reimplement the method \ref getTickStep. If you additionally want control over the + string that will be shown as tick label, reimplement \ref getTickLabel. + + If you wish to have complete control, you can generate the tick vectors and tick label vectors + yourself by reimplementing \ref createTickVector and \ref createLabelVector. The default + implementations use the previously mentioned virtual methods \ref getTickStep and \ref + getTickLabel, but your reimplementations don't necessarily need to do so. For example in the case + of unequal tick steps, the method \ref getTickStep loses its usefulness and can be ignored. + + The sub tick count between major ticks can be controlled with \ref getSubTickCount. Full sub tick + placement control is obtained by reimplementing \ref createSubTickVector. + + See the documentation of all these virtual methods in QCPAxisTicker for detailed information + about the parameters and expected return values. +*/ + +/*! + Constructs the ticker and sets reasonable default values. Axis tickers are commonly created + managed by a QSharedPointer, which then can be passed to QCPAxis::setTicker. +*/ +QCPAxisTicker::QCPAxisTicker() : + mTickStepStrategy(tssReadability), + mTickCount(5), + mTickOrigin(0) +{ +} + +QCPAxisTicker::~QCPAxisTicker() +{ + +} + +/*! + Sets which strategy the axis ticker follows when choosing the size of the tick step. For the + available strategies, see \ref TickStepStrategy. +*/ +void QCPAxisTicker::setTickStepStrategy(QCPAxisTicker::TickStepStrategy strategy) +{ + mTickStepStrategy = strategy; +} + +/*! + Sets how many ticks this ticker shall aim to generate across the axis range. Note that \a count + is not guaranteed to be matched exactly, as generating readable tick intervals may conflict with + the requested number of ticks. + + Whether the readability has priority over meeting the requested \a count can be specified with + \ref setTickStepStrategy. +*/ +void QCPAxisTicker::setTickCount(int count) +{ + if (count > 0) + mTickCount = count; + else + qDebug() << Q_FUNC_INFO << "tick count must be greater than zero:" << count; +} + +/*! + Sets the mathematical coordinate (or "offset") of the zeroth tick. This tick coordinate is just a + concept and doesn't need to be inside the currently visible axis range. + + By default \a origin is zero, which for example yields ticks {-5, 0, 5, 10, 15,...} when the tick + step is five. If \a origin is now set to 1 instead, the correspondingly generated ticks would be + {-4, 1, 6, 11, 16,...}. +*/ +void QCPAxisTicker::setTickOrigin(double origin) +{ + mTickOrigin = origin; +} + +/*! + This is the method called by QCPAxis in order to actually generate tick coordinates (\a ticks), + tick label strings (\a tickLabels) and sub tick coordinates (\a subTicks). + + The ticks are generated for the specified \a range. The generated labels typically follow the + specified \a locale, \a formatChar and number \a precision, however this might be different (or + even irrelevant) for certain QCPAxisTicker subclasses. + + The output parameter \a ticks is filled with the generated tick positions in axis coordinates. + The output parameters \a subTicks and \a tickLabels are optional (set them to \c nullptr if not + needed) and are respectively filled with sub tick coordinates, and tick label strings belonging + to \a ticks by index. +*/ +void QCPAxisTicker::generate(const QCPRange &range, const QLocale &locale, QChar formatChar, int precision, QVector &ticks, QVector *subTicks, QVector *tickLabels) +{ + // generate (major) ticks: + double tickStep = getTickStep(range); + ticks = createTickVector(tickStep, range); + trimTicks(range, ticks, true); // trim ticks to visible range plus one outer tick on each side (incase a subclass createTickVector creates more) + + // generate sub ticks between major ticks: + if (subTicks) + { + if (!ticks.isEmpty()) + { + *subTicks = createSubTickVector(getSubTickCount(tickStep), ticks); + trimTicks(range, *subTicks, false); + } else + *subTicks = QVector(); + } + + // finally trim also outliers (no further clipping happens in axis drawing): + trimTicks(range, ticks, false); + // generate labels for visible ticks if requested: + if (tickLabels) + *tickLabels = createLabelVector(ticks, locale, formatChar, precision); +} + +/*! \internal + + Takes the entire currently visible axis range and returns a sensible tick step in + order to provide readable tick labels as well as a reasonable number of tick counts (see \ref + setTickCount, \ref setTickStepStrategy). + + If a QCPAxisTicker subclass only wants a different tick step behaviour than the default + implementation, it should reimplement this method. See \ref cleanMantissa for a possible helper + function. +*/ +double QCPAxisTicker::getTickStep(const QCPRange &range) +{ + double exactStep = range.size()/double(mTickCount+1e-10); // mTickCount ticks on average, the small addition is to prevent jitter on exact integers + return cleanMantissa(exactStep); +} + +/*! \internal + + Takes the \a tickStep, i.e. the distance between two consecutive ticks, and returns + an appropriate number of sub ticks for that specific tick step. + + Note that a returned sub tick count of e.g. 4 will split each tick interval into 5 sections. +*/ +int QCPAxisTicker::getSubTickCount(double tickStep) +{ + int result = 1; // default to 1, if no proper value can be found + + // separate integer and fractional part of mantissa: + double epsilon = 0.01; + double intPartf; + int intPart; + double fracPart = modf(getMantissa(tickStep), &intPartf); + intPart = int(intPartf); + + // handle cases with (almost) integer mantissa: + if (fracPart < epsilon || 1.0-fracPart < epsilon) + { + if (1.0-fracPart < epsilon) + ++intPart; + switch (intPart) + { + case 1: result = 4; break; // 1.0 -> 0.2 substep + case 2: result = 3; break; // 2.0 -> 0.5 substep + case 3: result = 2; break; // 3.0 -> 1.0 substep + case 4: result = 3; break; // 4.0 -> 1.0 substep + case 5: result = 4; break; // 5.0 -> 1.0 substep + case 6: result = 2; break; // 6.0 -> 2.0 substep + case 7: result = 6; break; // 7.0 -> 1.0 substep + case 8: result = 3; break; // 8.0 -> 2.0 substep + case 9: result = 2; break; // 9.0 -> 3.0 substep + } + } else + { + // handle cases with significantly fractional mantissa: + if (qAbs(fracPart-0.5) < epsilon) // *.5 mantissa + { + switch (intPart) + { + case 1: result = 2; break; // 1.5 -> 0.5 substep + case 2: result = 4; break; // 2.5 -> 0.5 substep + case 3: result = 4; break; // 3.5 -> 0.7 substep + case 4: result = 2; break; // 4.5 -> 1.5 substep + case 5: result = 4; break; // 5.5 -> 1.1 substep (won't occur with default getTickStep from here on) + case 6: result = 4; break; // 6.5 -> 1.3 substep + case 7: result = 2; break; // 7.5 -> 2.5 substep + case 8: result = 4; break; // 8.5 -> 1.7 substep + case 9: result = 4; break; // 9.5 -> 1.9 substep + } + } + // if mantissa fraction isn't 0.0 or 0.5, don't bother finding good sub tick marks, leave default + } + + return result; +} + +/*! \internal + + This method returns the tick label string as it should be printed under the \a tick coordinate. + If a textual number is returned, it should respect the provided \a locale, \a formatChar and \a + precision. + + If the returned value contains exponentials of the form "2e5" and beautifully typeset powers is + enabled in the QCPAxis number format (\ref QCPAxis::setNumberFormat), the exponential part will + be formatted accordingly using multiplication symbol and superscript during rendering of the + label automatically. +*/ +QString QCPAxisTicker::getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) +{ + return locale.toString(tick, formatChar.toLatin1(), precision); +} + +/*! \internal + + Returns a vector containing all coordinates of sub ticks that should be drawn. It generates \a + subTickCount sub ticks between each tick pair given in \a ticks. + + If a QCPAxisTicker subclass needs maximal control over the generated sub ticks, it should + reimplement this method. Depending on the purpose of the subclass it doesn't necessarily need to + base its result on \a subTickCount or \a ticks. +*/ +QVector QCPAxisTicker::createSubTickVector(int subTickCount, const QVector &ticks) +{ + QVector result; + if (subTickCount <= 0 || ticks.size() < 2) + return result; + + result.reserve((ticks.size()-1)*subTickCount); + for (int i=1; i QCPAxisTicker::createTickVector(double tickStep, const QCPRange &range) +{ + QVector result; + // Generate tick positions according to tickStep: + qint64 firstStep = qint64(floor((range.lower-mTickOrigin)/tickStep)); // do not use qFloor here, or we'll lose 64 bit precision + qint64 lastStep = qint64(ceil((range.upper-mTickOrigin)/tickStep)); // do not use qCeil here, or we'll lose 64 bit precision + int tickcount = int(lastStep-firstStep+1); + if (tickcount < 0) tickcount = 0; + result.resize(tickcount); + for (int i=0; i QCPAxisTicker::createLabelVector(const QVector &ticks, const QLocale &locale, QChar formatChar, int precision) +{ + QVector result; + result.reserve(ticks.size()); + foreach (double tickCoord, ticks) + result.append(getTickLabel(tickCoord, locale, formatChar, precision)); + return result; +} + +/*! \internal + + Removes tick coordinates from \a ticks which lie outside the specified \a range. If \a + keepOneOutlier is true, it preserves one tick just outside the range on both sides, if present. + + The passed \a ticks must be sorted in ascending order. +*/ +void QCPAxisTicker::trimTicks(const QCPRange &range, QVector &ticks, bool keepOneOutlier) const +{ + bool lowFound = false; + bool highFound = false; + int lowIndex = 0; + int highIndex = -1; + + for (int i=0; i < ticks.size(); ++i) + { + if (ticks.at(i) >= range.lower) + { + lowFound = true; + lowIndex = i; + break; + } + } + for (int i=ticks.size()-1; i >= 0; --i) + { + if (ticks.at(i) <= range.upper) + { + highFound = true; + highIndex = i; + break; + } + } + + if (highFound && lowFound) + { + int trimFront = qMax(0, lowIndex-(keepOneOutlier ? 1 : 0)); + int trimBack = qMax(0, ticks.size()-(keepOneOutlier ? 2 : 1)-highIndex); + if (trimFront > 0 || trimBack > 0) + ticks = ticks.mid(trimFront, ticks.size()-trimFront-trimBack); + } else // all ticks are either all below or all above the range + ticks.clear(); +} + +/*! \internal + + Returns the coordinate contained in \a candidates which is closest to the provided \a target. + + This method assumes \a candidates is not empty and sorted in ascending order. +*/ +double QCPAxisTicker::pickClosest(double target, const QVector &candidates) const +{ + if (candidates.size() == 1) + return candidates.first(); + QVector::const_iterator it = std::lower_bound(candidates.constBegin(), candidates.constEnd(), target); + if (it == candidates.constEnd()) + return *(it-1); + else if (it == candidates.constBegin()) + return *it; + else + return target-*(it-1) < *it-target ? *(it-1) : *it; +} + +/*! \internal + + Returns the decimal mantissa of \a input. Optionally, if \a magnitude is not set to zero, it also + returns the magnitude of \a input as a power of 10. + + For example, an input of 142.6 will return a mantissa of 1.426 and a magnitude of 100. +*/ +double QCPAxisTicker::getMantissa(double input, double *magnitude) const +{ + const double mag = std::pow(10.0, std::floor(std::log10(input))); + if (magnitude) *magnitude = mag; + return input/mag; +} + +/*! \internal + + Returns a number that is close to \a input but has a clean, easier human readable mantissa. How + strongly the mantissa is altered, and thus how strong the result deviates from the original \a + input, depends on the current tick step strategy (see \ref setTickStepStrategy). +*/ +double QCPAxisTicker::cleanMantissa(double input) const +{ + double magnitude; + const double mantissa = getMantissa(input, &magnitude); + switch (mTickStepStrategy) + { + case tssReadability: + { + return pickClosest(mantissa, QVector() << 1.0 << 2.0 << 2.5 << 5.0 << 10.0)*magnitude; + } + case tssMeetTickCount: + { + // this gives effectively a mantissa of 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 8.0, 10.0 + if (mantissa <= 5.0) + return int(mantissa*2)/2.0*magnitude; // round digit after decimal point to 0.5 + else + return int(mantissa/2.0)*2.0*magnitude; // round to first digit in multiples of 2 + } + } + return input; +} +/* end of 'src/axis/axisticker.cpp' */ + + +/* including file 'src/axis/axistickerdatetime.cpp' */ +/* modified 2022-11-06T12:45:56, size 18829 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAxisTickerDateTime +//////////////////////////////////////////////////////////////////////////////////////////////////// +/*! \class QCPAxisTickerDateTime + \brief Specialized axis ticker for calendar dates and times as axis ticks + + \image html axisticker-datetime.png + + This QCPAxisTicker subclass generates ticks that correspond to real calendar dates and times. The + plot axis coordinate is interpreted as Unix Time, so seconds since Epoch (January 1, 1970, 00:00 + UTC). This is also used for example by QDateTime in the toTime_t()/setTime_t() methods + with a precision of one second. Since Qt 4.7, millisecond accuracy can be obtained from QDateTime + by using QDateTime::fromMSecsSinceEpoch()/1000.0. The static methods \ref dateTimeToKey + and \ref keyToDateTime conveniently perform this conversion achieving a precision of one + millisecond on all Qt versions. + + The format of the date/time display in the tick labels is controlled with \ref setDateTimeFormat. + If a different time spec or time zone shall be used for the tick label appearance, see \ref + setDateTimeSpec or \ref setTimeZone, respectively. + + This ticker produces unequal tick spacing in order to provide intuitive date and time-of-day + ticks. For example, if the axis range spans a few years such that there is one tick per year, + ticks will be positioned on 1. January of every year. This is intuitive but, due to leap years, + will result in slightly unequal tick intervals (visually unnoticeable). The same can be seen in + the image above: even though the number of days varies month by month, this ticker generates + ticks on the same day of each month. + + If you would like to change the date/time that is used as a (mathematical) starting date for the + ticks, use the \ref setTickOrigin(const QDateTime &origin) method overload, which takes a + QDateTime. If you pass 15. July, 9:45 to this method, the yearly ticks will end up on 15. July at + 9:45 of every year. + + The ticker can be created and assigned to an axis like this: + \snippet documentation/doc-image-generator/mainwindow.cpp axistickerdatetime-creation + + \note If you rather wish to display relative times in terms of days, hours, minutes, seconds and + milliseconds, and are not interested in the intricacies of real calendar dates with months and + (leap) years, have a look at QCPAxisTickerTime instead. +*/ + +/*! + Constructs the ticker and sets reasonable default values. Axis tickers are commonly created + managed by a QSharedPointer, which then can be passed to QCPAxis::setTicker. +*/ +QCPAxisTickerDateTime::QCPAxisTickerDateTime() : + mDateTimeFormat(QLatin1String("hh:mm:ss\ndd.MM.yy")), + mDateTimeSpec(Qt::LocalTime), + mDateStrategy(dsNone) +{ + setTickCount(4); +} + +/*! + Sets the format in which dates and times are displayed as tick labels. For details about the \a + format string, see the documentation of QDateTime::toString(). + + Typical expressions are + + + + + + + + + + + + + + + + + + + + + + + + +
\c dThe day as a number without a leading zero (1 to 31)
\c ddThe day as a number with a leading zero (01 to 31)
\c dddThe abbreviated localized day name (e.g. 'Mon' to 'Sun'). Uses the system locale to localize the name, i.e. QLocale::system().
\c ddddThe long localized day name (e.g. 'Monday' to 'Sunday'). Uses the system locale to localize the name, i.e. QLocale::system().
\c MThe month as a number without a leading zero (1 to 12)
\c MMThe month as a number with a leading zero (01 to 12)
\c MMMThe abbreviated localized month name (e.g. 'Jan' to 'Dec'). Uses the system locale to localize the name, i.e. QLocale::system().
\c MMMMThe long localized month name (e.g. 'January' to 'December'). Uses the system locale to localize the name, i.e. QLocale::system().
\c yyThe year as a two digit number (00 to 99)
\c yyyyThe year as a four digit number. If the year is negative, a minus sign is prepended, making five characters.
\c hThe hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
\c hhThe hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
\c HThe hour without a leading zero (0 to 23, even with AM/PM display)
\c HHThe hour with a leading zero (00 to 23, even with AM/PM display)
\c mThe minute without a leading zero (0 to 59)
\c mmThe minute with a leading zero (00 to 59)
\c sThe whole second, without any leading zero (0 to 59)
\c ssThe whole second, with a leading zero where applicable (00 to 59)
\c zThe fractional part of the second, to go after a decimal point, without trailing zeroes (0 to 999). Thus "s.z" reports the seconds to full available (millisecond) precision without trailing zeroes.
\c zzzThe fractional part of the second, to millisecond precision, including trailing zeroes where applicable (000 to 999).
\c AP or \c AUse AM/PM display. A/AP will be replaced by an upper-case version of either QLocale::amText() or QLocale::pmText().
\c ap or \c aUse am/pm display. a/ap will be replaced by a lower-case version of either QLocale::amText() or QLocale::pmText().
\c tThe timezone (for example "CEST")
+ + Newlines can be inserted with \c "\n", literal strings (even when containing above expressions) + by encapsulating them using single-quotes. A literal single quote can be generated by using two + consecutive single quotes in the format. + + \see setDateTimeSpec, setTimeZone +*/ +void QCPAxisTickerDateTime::setDateTimeFormat(const QString &format) +{ + mDateTimeFormat = format; +} + +/*! + Sets the time spec that is used for creating the tick labels from corresponding dates/times. + + The default value of QDateTime objects (and also QCPAxisTickerDateTime) is + Qt::LocalTime. However, if the displayed tick labels shall be given in UTC, set \a spec + to Qt::UTC. + + Tick labels corresponding to other time zones can be achieved with \ref setTimeZone (which sets + \a spec to \c Qt::TimeZone internally). Note that if \a spec is afterwards set to not be \c + Qt::TimeZone again, the \ref setTimeZone setting will be ignored accordingly. + + \see setDateTimeFormat, setTimeZone +*/ +void QCPAxisTickerDateTime::setDateTimeSpec(Qt::TimeSpec spec) +{ + mDateTimeSpec = spec; +} + +# if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) +/*! + Sets the time zone that is used for creating the tick labels from corresponding dates/times. The + time spec (\ref setDateTimeSpec) is set to \c Qt::TimeZone. + + \see setDateTimeFormat, setTimeZone +*/ +void QCPAxisTickerDateTime::setTimeZone(const QTimeZone &zone) +{ + mTimeZone = zone; + mDateTimeSpec = Qt::TimeZone; +} +#endif + +/*! + Sets the tick origin (see \ref QCPAxisTicker::setTickOrigin) in seconds since Epoch (1. Jan 1970, + 00:00 UTC). For the date time ticker it might be more intuitive to use the overload which + directly takes a QDateTime, see \ref setTickOrigin(const QDateTime &origin). + + This is useful to define the month/day/time recurring at greater tick interval steps. For + example, If you pass 15. July, 9:45 to this method and the tick interval happens to be one tick + per year, the ticks will end up on 15. July at 9:45 of every year. +*/ +void QCPAxisTickerDateTime::setTickOrigin(double origin) +{ + QCPAxisTicker::setTickOrigin(origin); +} + +/*! + Sets the tick origin (see \ref QCPAxisTicker::setTickOrigin) as a QDateTime \a origin. + + This is useful to define the month/day/time recurring at greater tick interval steps. For + example, If you pass 15. July, 9:45 to this method and the tick interval happens to be one tick + per year, the ticks will end up on 15. July at 9:45 of every year. +*/ +void QCPAxisTickerDateTime::setTickOrigin(const QDateTime &origin) +{ + setTickOrigin(dateTimeToKey(origin)); +} + +/*! \internal + + Returns a sensible tick step with intervals appropriate for a date-time-display, such as weekly, + monthly, bi-monthly, etc. + + Note that this tick step isn't used exactly when generating the tick vector in \ref + createTickVector, but only as a guiding value requiring some correction for each individual tick + interval. Otherwise this would lead to unintuitive date displays, e.g. jumping between first day + in the month to the last day in the previous month from tick to tick, due to the non-uniform + length of months. The same problem arises with leap years. + + \seebaseclassmethod +*/ +double QCPAxisTickerDateTime::getTickStep(const QCPRange &range) +{ + double result = range.size()/double(mTickCount+1e-10); // mTickCount ticks on average, the small addition is to prevent jitter on exact integers + + mDateStrategy = dsNone; // leaving it at dsNone means tick coordinates will not be tuned in any special way in createTickVector + if (result < 1) // ideal tick step is below 1 second -> use normal clean mantissa algorithm in units of seconds + { + result = cleanMantissa(result); + } else if (result < 86400*30.4375*12) // below a year + { + result = pickClosest(result, QVector() + << 1 << 2.5 << 5 << 10 << 15 << 30 << 60 << 2.5*60 << 5*60 << 10*60 << 15*60 << 30*60 << 60*60 // second, minute, hour range + << 3600*2 << 3600*3 << 3600*6 << 3600*12 << 3600*24 // hour to day range + << 86400*2 << 86400*5 << 86400*7 << 86400*14 << 86400*30.4375 << 86400*30.4375*2 << 86400*30.4375*3 << 86400*30.4375*6 << 86400*30.4375*12); // day, week, month range (avg. days per month includes leap years) + if (result > 86400*30.4375-1) // month tick intervals or larger + mDateStrategy = dsUniformDayInMonth; + else if (result > 3600*24-1) // day tick intervals or larger + mDateStrategy = dsUniformTimeInDay; + } else // more than a year, go back to normal clean mantissa algorithm but in units of years + { + const double secondsPerYear = 86400*30.4375*12; // average including leap years + result = cleanMantissa(result/secondsPerYear)*secondsPerYear; + mDateStrategy = dsUniformDayInMonth; + } + return result; +} + +/*! \internal + + Returns a sensible sub tick count with intervals appropriate for a date-time-display, such as weekly, + monthly, bi-monthly, etc. + + \seebaseclassmethod +*/ +int QCPAxisTickerDateTime::getSubTickCount(double tickStep) +{ + int result = QCPAxisTicker::getSubTickCount(tickStep); + switch (qRound(tickStep)) // hand chosen subticks for specific minute/hour/day/week/month range (as specified in getTickStep) + { + case 5*60: result = 4; break; + case 10*60: result = 1; break; + case 15*60: result = 2; break; + case 30*60: result = 1; break; + case 60*60: result = 3; break; + case 3600*2: result = 3; break; + case 3600*3: result = 2; break; + case 3600*6: result = 1; break; + case 3600*12: result = 3; break; + case 3600*24: result = 3; break; + case 86400*2: result = 1; break; + case 86400*5: result = 4; break; + case 86400*7: result = 6; break; + case 86400*14: result = 1; break; + case int(86400*30.4375+0.5): result = 3; break; + case int(86400*30.4375*2+0.5): result = 1; break; + case int(86400*30.4375*3+0.5): result = 2; break; + case int(86400*30.4375*6+0.5): result = 5; break; + case int(86400*30.4375*12+0.5): result = 3; break; + } + return result; +} + +/*! \internal + + Generates a date/time tick label for tick coordinate \a tick, based on the currently set format + (\ref setDateTimeFormat), time spec (\ref setDateTimeSpec), and possibly time zone (\ref + setTimeZone). + + \seebaseclassmethod +*/ +QString QCPAxisTickerDateTime::getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) +{ + Q_UNUSED(precision) + Q_UNUSED(formatChar) +# if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) + if (mDateTimeSpec == Qt::TimeZone) + return locale.toString(keyToDateTime(tick).toTimeZone(mTimeZone), mDateTimeFormat); + else + return locale.toString(keyToDateTime(tick).toTimeSpec(mDateTimeSpec), mDateTimeFormat); +# else + return locale.toString(keyToDateTime(tick).toTimeSpec(mDateTimeSpec), mDateTimeFormat); +# endif +} + +/*! \internal + + Uses the passed \a tickStep as a guiding value and applies corrections in order to obtain + non-uniform tick intervals but intuitive tick labels, e.g. falling on the same day of each month. + + \seebaseclassmethod +*/ +QVector QCPAxisTickerDateTime::createTickVector(double tickStep, const QCPRange &range) +{ + QVector result = QCPAxisTicker::createTickVector(tickStep, range); + if (!result.isEmpty()) + { + if (mDateStrategy == dsUniformTimeInDay) + { + QDateTime uniformDateTime = keyToDateTime(mTickOrigin); // the time of this datetime will be set for all other ticks, if possible + QDateTime tickDateTime; + for (int i=0; i 15) // with leap years involved, date month may jump backwards or forwards, and needs to be corrected before setting day + tickDateTime = tickDateTime.addMonths(-1); + tickDateTime.setDate(QDate(tickDateTime.date().year(), tickDateTime.date().month(), thisUniformDay)); + result[i] = dateTimeToKey(tickDateTime); + } + } + } + return result; +} + +/*! + A convenience method which turns \a key (in seconds since Epoch 1. Jan 1970, 00:00 UTC) into a + QDateTime object. This can be used to turn axis coordinates to actual QDateTimes. + + The accuracy achieved by this method is one millisecond, irrespective of the used Qt version (it + works around the lack of a QDateTime::fromMSecsSinceEpoch in Qt 4.6) + + \see dateTimeToKey +*/ +QDateTime QCPAxisTickerDateTime::keyToDateTime(double key) +{ +# if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) + return QDateTime::fromTime_t(key).addMSecs((key-(qint64)key)*1000); +# else + return QDateTime::fromMSecsSinceEpoch(qint64(key*1000.0)); +# endif +} + +/*! \overload + + A convenience method which turns a QDateTime object into a double value that corresponds to + seconds since Epoch (1. Jan 1970, 00:00 UTC). This is the format used as axis coordinates by + QCPAxisTickerDateTime. + + The accuracy achieved by this method is one millisecond, irrespective of the used Qt version (it + works around the lack of a QDateTime::toMSecsSinceEpoch in Qt 4.6) + + \see keyToDateTime +*/ +double QCPAxisTickerDateTime::dateTimeToKey(const QDateTime &dateTime) +{ +# if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) + return dateTime.toTime_t()+dateTime.time().msec()/1000.0; +# else + return dateTime.toMSecsSinceEpoch()/1000.0; +# endif +} + +/*! \overload + + A convenience method which turns a QDate object into a double value that corresponds to seconds + since Epoch (1. Jan 1970, 00:00 UTC). This is the format used + as axis coordinates by QCPAxisTickerDateTime. + + The returned value will be the start of the passed day of \a date, interpreted in the given \a + timeSpec. + + \see keyToDateTime +*/ +double QCPAxisTickerDateTime::dateTimeToKey(const QDate &date, Qt::TimeSpec timeSpec) +{ +# if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) + return QDateTime(date, QTime(0, 0), timeSpec).toTime_t(); +# elif QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + return QDateTime(date, QTime(0, 0), timeSpec).toMSecsSinceEpoch()/1000.0; +# else + return date.startOfDay(timeSpec).toMSecsSinceEpoch()/1000.0; +# endif +} +/* end of 'src/axis/axistickerdatetime.cpp' */ + + +/* including file 'src/axis/axistickertime.cpp' */ +/* modified 2022-11-06T12:45:56, size 11745 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAxisTickerTime +//////////////////////////////////////////////////////////////////////////////////////////////////// +/*! \class QCPAxisTickerTime + \brief Specialized axis ticker for time spans in units of milliseconds to days + + \image html axisticker-time.png + + This QCPAxisTicker subclass generates ticks that corresponds to time intervals. + + The format of the time display in the tick labels is controlled with \ref setTimeFormat and \ref + setFieldWidth. The time coordinate is in the unit of seconds with respect to the time coordinate + zero. Unlike with QCPAxisTickerDateTime, the ticks don't correspond to a specific calendar date + and time. + + The time can be displayed in milliseconds, seconds, minutes, hours and days. Depending on the + largest available unit in the format specified with \ref setTimeFormat, any time spans above will + be carried in that largest unit. So for example if the format string is "%m:%s" and a tick at + coordinate value 7815 (being 2 hours, 10 minutes and 15 seconds) is created, the resulting tick + label will show "130:15" (130 minutes, 15 seconds). If the format string is "%h:%m:%s", the hour + unit will be used and the label will thus be "02:10:15". Negative times with respect to the axis + zero will carry a leading minus sign. + + The ticker can be created and assigned to an axis like this: + \snippet documentation/doc-image-generator/mainwindow.cpp axistickertime-creation + + Here is an example of a time axis providing time information in days, hours and minutes. Due to + the axis range spanning a few days and the wanted tick count (\ref setTickCount), the ticker + decided to use tick steps of 12 hours: + + \image html axisticker-time2.png + + The format string for this example is + \snippet documentation/doc-image-generator/mainwindow.cpp axistickertime-creation-2 + + \note If you rather wish to display calendar dates and times, have a look at QCPAxisTickerDateTime + instead. +*/ + +/*! + Constructs the ticker and sets reasonable default values. Axis tickers are commonly created + managed by a QSharedPointer, which then can be passed to QCPAxis::setTicker. +*/ +QCPAxisTickerTime::QCPAxisTickerTime() : + mTimeFormat(QLatin1String("%h:%m:%s")), + mSmallestUnit(tuSeconds), + mBiggestUnit(tuHours) +{ + setTickCount(4); + mFieldWidth[tuMilliseconds] = 3; + mFieldWidth[tuSeconds] = 2; + mFieldWidth[tuMinutes] = 2; + mFieldWidth[tuHours] = 2; + mFieldWidth[tuDays] = 1; + + mFormatPattern[tuMilliseconds] = QLatin1String("%z"); + mFormatPattern[tuSeconds] = QLatin1String("%s"); + mFormatPattern[tuMinutes] = QLatin1String("%m"); + mFormatPattern[tuHours] = QLatin1String("%h"); + mFormatPattern[tuDays] = QLatin1String("%d"); +} + +/*! + Sets the format that will be used to display time in the tick labels. + + The available patterns are: + - %%z for milliseconds + - %%s for seconds + - %%m for minutes + - %%h for hours + - %%d for days + + The field width (zero padding) can be controlled for each unit with \ref setFieldWidth. + + The largest unit that appears in \a format will carry all the remaining time of a certain tick + coordinate, even if it overflows the natural limit of the unit. For example, if %%m is the + largest unit it might become larger than 59 in order to consume larger time values. If on the + other hand %%h is available, the minutes will wrap around to zero after 59 and the time will + carry to the hour digit. +*/ +void QCPAxisTickerTime::setTimeFormat(const QString &format) +{ + mTimeFormat = format; + + // determine smallest and biggest unit in format, to optimize unit replacement and allow biggest + // unit to consume remaining time of a tick value and grow beyond its modulo (e.g. min > 59) + mSmallestUnit = tuMilliseconds; + mBiggestUnit = tuMilliseconds; + bool hasSmallest = false; + for (int i = tuMilliseconds; i <= tuDays; ++i) + { + TimeUnit unit = static_cast(i); + if (mTimeFormat.contains(mFormatPattern.value(unit))) + { + if (!hasSmallest) + { + mSmallestUnit = unit; + hasSmallest = true; + } + mBiggestUnit = unit; + } + } +} + +/*! + Sets the field widh of the specified \a unit to be \a width digits, when displayed in the tick + label. If the number for the specific unit is shorter than \a width, it will be padded with an + according number of zeros to the left in order to reach the field width. + + \see setTimeFormat +*/ +void QCPAxisTickerTime::setFieldWidth(QCPAxisTickerTime::TimeUnit unit, int width) +{ + mFieldWidth[unit] = qMax(width, 1); +} + +/*! \internal + + Returns the tick step appropriate for time displays, depending on the provided \a range and the + smallest available time unit in the current format (\ref setTimeFormat). For example if the unit + of seconds isn't available in the format, this method will not generate steps (like 2.5 minutes) + that require sub-minute precision to be displayed correctly. + + \seebaseclassmethod +*/ +double QCPAxisTickerTime::getTickStep(const QCPRange &range) +{ + double result = range.size()/double(mTickCount+1e-10); // mTickCount ticks on average, the small addition is to prevent jitter on exact integers + + if (result < 1) // ideal tick step is below 1 second -> use normal clean mantissa algorithm in units of seconds + { + if (mSmallestUnit == tuMilliseconds) + result = qMax(cleanMantissa(result), 0.001); // smallest tick step is 1 millisecond + else // have no milliseconds available in format, so stick with 1 second tickstep + result = 1.0; + } else if (result < 3600*24) // below a day + { + // the filling of availableSteps seems a bit contorted but it fills in a sorted fashion and thus saves a post-fill sorting run + QVector availableSteps; + // seconds range: + if (mSmallestUnit <= tuSeconds) + availableSteps << 1; + if (mSmallestUnit == tuMilliseconds) + availableSteps << 2.5; // only allow half second steps if milliseconds are there to display it + else if (mSmallestUnit == tuSeconds) + availableSteps << 2; + if (mSmallestUnit <= tuSeconds) + availableSteps << 5 << 10 << 15 << 30; + // minutes range: + if (mSmallestUnit <= tuMinutes) + availableSteps << 1*60; + if (mSmallestUnit <= tuSeconds) + availableSteps << 2.5*60; // only allow half minute steps if seconds are there to display it + else if (mSmallestUnit == tuMinutes) + availableSteps << 2*60; + if (mSmallestUnit <= tuMinutes) + availableSteps << 5*60 << 10*60 << 15*60 << 30*60; + // hours range: + if (mSmallestUnit <= tuHours) + availableSteps << 1*3600 << 2*3600 << 3*3600 << 6*3600 << 12*3600 << 24*3600; + // pick available step that is most appropriate to approximate ideal step: + result = pickClosest(result, availableSteps); + } else // more than a day, go back to normal clean mantissa algorithm but in units of days + { + const double secondsPerDay = 3600*24; + result = cleanMantissa(result/secondsPerDay)*secondsPerDay; + } + return result; +} + +/*! \internal + + Returns the sub tick count appropriate for the provided \a tickStep and time displays. + + \seebaseclassmethod +*/ +int QCPAxisTickerTime::getSubTickCount(double tickStep) +{ + int result = QCPAxisTicker::getSubTickCount(tickStep); + switch (qRound(tickStep)) // hand chosen subticks for specific minute/hour/day range (as specified in getTickStep) + { + case 5*60: result = 4; break; + case 10*60: result = 1; break; + case 15*60: result = 2; break; + case 30*60: result = 1; break; + case 60*60: result = 3; break; + case 3600*2: result = 3; break; + case 3600*3: result = 2; break; + case 3600*6: result = 1; break; + case 3600*12: result = 3; break; + case 3600*24: result = 3; break; + } + return result; +} + +/*! \internal + + Returns the tick label corresponding to the provided \a tick and the configured format and field + widths (\ref setTimeFormat, \ref setFieldWidth). + + \seebaseclassmethod +*/ +QString QCPAxisTickerTime::getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) +{ + Q_UNUSED(precision) + Q_UNUSED(formatChar) + Q_UNUSED(locale) + bool negative = tick < 0; + if (negative) tick *= -1; + double values[tuDays+1]; // contains the msec/sec/min/... value with its respective modulo (e.g. minute 0..59) + double restValues[tuDays+1]; // contains the msec/sec/min/... value as if it's the largest available unit and thus consumes the remaining time + + restValues[tuMilliseconds] = tick*1000; + values[tuMilliseconds] = modf(restValues[tuMilliseconds]/1000, &restValues[tuSeconds])*1000; + values[tuSeconds] = modf(restValues[tuSeconds]/60, &restValues[tuMinutes])*60; + values[tuMinutes] = modf(restValues[tuMinutes]/60, &restValues[tuHours])*60; + values[tuHours] = modf(restValues[tuHours]/24, &restValues[tuDays])*24; + // no need to set values[tuDays] because days are always a rest value (there is no higher unit so it consumes all remaining time) + + QString result = mTimeFormat; + for (int i = mSmallestUnit; i <= mBiggestUnit; ++i) + { + TimeUnit iUnit = static_cast(i); + replaceUnit(result, iUnit, qRound(iUnit == mBiggestUnit ? restValues[iUnit] : values[iUnit])); + } + if (negative) + result.prepend(QLatin1Char('-')); + return result; +} + +/*! \internal + + Replaces all occurrences of the format pattern belonging to \a unit in \a text with the specified + \a value, using the field width as specified with \ref setFieldWidth for the \a unit. +*/ +void QCPAxisTickerTime::replaceUnit(QString &text, QCPAxisTickerTime::TimeUnit unit, int value) const +{ + QString valueStr = QString::number(value); + while (valueStr.size() < mFieldWidth.value(unit)) + valueStr.prepend(QLatin1Char('0')); + + text.replace(mFormatPattern.value(unit), valueStr); +} +/* end of 'src/axis/axistickertime.cpp' */ + + +/* including file 'src/axis/axistickerfixed.cpp' */ +/* modified 2022-11-06T12:45:56, size 5575 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAxisTickerFixed +//////////////////////////////////////////////////////////////////////////////////////////////////// +/*! \class QCPAxisTickerFixed + \brief Specialized axis ticker with a fixed tick step + + \image html axisticker-fixed.png + + This QCPAxisTicker subclass generates ticks with a fixed tick step set with \ref setTickStep. It + is also possible to allow integer multiples and integer powers of the specified tick step with + \ref setScaleStrategy. + + A typical application of this ticker is to make an axis only display integers, by setting the + tick step of the ticker to 1.0 and the scale strategy to \ref ssMultiples. + + Another case is when a certain number has a special meaning and axis ticks should only appear at + multiples of that value. In this case you might also want to consider \ref QCPAxisTickerPi + because despite the name it is not limited to only pi symbols/values. + + The ticker can be created and assigned to an axis like this: + \snippet documentation/doc-image-generator/mainwindow.cpp axistickerfixed-creation +*/ + +/*! + Constructs the ticker and sets reasonable default values. Axis tickers are commonly created + managed by a QSharedPointer, which then can be passed to QCPAxis::setTicker. +*/ +QCPAxisTickerFixed::QCPAxisTickerFixed() : + mTickStep(1.0), + mScaleStrategy(ssNone) +{ +} + +/*! + Sets the fixed tick interval to \a step. + + The axis ticker will only use this tick step when generating axis ticks. This might cause a very + high tick density and overlapping labels if the axis range is zoomed out. Using \ref + setScaleStrategy it is possible to relax the fixed step and also allow multiples or powers of \a + step. This will enable the ticker to reduce the number of ticks to a reasonable amount (see \ref + setTickCount). +*/ +void QCPAxisTickerFixed::setTickStep(double step) +{ + if (step > 0) + mTickStep = step; + else + qDebug() << Q_FUNC_INFO << "tick step must be greater than zero:" << step; +} + +/*! + Sets whether the specified tick step (\ref setTickStep) is absolutely fixed or whether + modifications may be applied to it before calculating the finally used tick step, such as + permitting multiples or powers. See \ref ScaleStrategy for details. + + The default strategy is \ref ssNone, which means the tick step is absolutely fixed. +*/ +void QCPAxisTickerFixed::setScaleStrategy(QCPAxisTickerFixed::ScaleStrategy strategy) +{ + mScaleStrategy = strategy; +} + +/*! \internal + + Determines the actually used tick step from the specified tick step and scale strategy (\ref + setTickStep, \ref setScaleStrategy). + + This method either returns the specified tick step exactly, or, if the scale strategy is not \ref + ssNone, a modification of it to allow varying the number of ticks in the current axis range. + + \seebaseclassmethod +*/ +double QCPAxisTickerFixed::getTickStep(const QCPRange &range) +{ + switch (mScaleStrategy) + { + case ssNone: + { + return mTickStep; + } + case ssMultiples: + { + double exactStep = range.size()/double(mTickCount+1e-10); // mTickCount ticks on average, the small addition is to prevent jitter on exact integers + if (exactStep < mTickStep) + return mTickStep; + else + return qint64(cleanMantissa(exactStep/mTickStep)+0.5)*mTickStep; + } + case ssPowers: + { + double exactStep = range.size()/double(mTickCount+1e-10); // mTickCount ticks on average, the small addition is to prevent jitter on exact integers + return qPow(mTickStep, int(qLn(exactStep)/qLn(mTickStep)+0.5)); + } + } + return mTickStep; +} +/* end of 'src/axis/axistickerfixed.cpp' */ + + +/* including file 'src/axis/axistickertext.cpp' */ +/* modified 2022-11-06T12:45:56, size 8742 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAxisTickerText +//////////////////////////////////////////////////////////////////////////////////////////////////// +/*! \class QCPAxisTickerText + \brief Specialized axis ticker which allows arbitrary labels at specified coordinates + + \image html axisticker-text.png + + This QCPAxisTicker subclass generates ticks which can be directly specified by the user as + coordinates and associated strings. They can be passed as a whole with \ref setTicks or one at a + time with \ref addTick. Alternatively you can directly access the internal storage via \ref ticks + and modify the tick/label data there. + + This is useful for cases where the axis represents categories rather than numerical values. + + If you are updating the ticks of this ticker regularly and in a dynamic fasion (e.g. dependent on + the axis range), it is a sign that you should probably create an own ticker by subclassing + QCPAxisTicker, instead of using this one. + + The ticker can be created and assigned to an axis like this: + \snippet documentation/doc-image-generator/mainwindow.cpp axistickertext-creation +*/ + +/* start of documentation of inline functions */ + +/*! \fn QMap &QCPAxisTickerText::ticks() + + Returns a non-const reference to the internal map which stores the tick coordinates and their + labels. + + You can access the map directly in order to add, remove or manipulate ticks, as an alternative to + using the methods provided by QCPAxisTickerText, such as \ref setTicks and \ref addTick. +*/ + +/* end of documentation of inline functions */ + +/*! + Constructs the ticker and sets reasonable default values. Axis tickers are commonly created + managed by a QSharedPointer, which then can be passed to QCPAxis::setTicker. +*/ +QCPAxisTickerText::QCPAxisTickerText() : + mSubTickCount(0) +{ +} + +/*! \overload + + Sets the ticks that shall appear on the axis. The map key of \a ticks corresponds to the axis + coordinate, and the map value is the string that will appear as tick label. + + An alternative to manipulate ticks is to directly access the internal storage with the \ref ticks + getter. + + \see addTicks, addTick, clear +*/ +void QCPAxisTickerText::setTicks(const QMap &ticks) +{ + mTicks = ticks; +} + +/*! \overload + + Sets the ticks that shall appear on the axis. The entries of \a positions correspond to the axis + coordinates, and the entries of \a labels are the respective strings that will appear as tick + labels. + + \see addTicks, addTick, clear +*/ +void QCPAxisTickerText::setTicks(const QVector &positions, const QVector &labels) +{ + clear(); + addTicks(positions, labels); +} + +/*! + Sets the number of sub ticks that shall appear between ticks. For QCPAxisTickerText, there is no + automatic sub tick count calculation. So if sub ticks are needed, they must be configured with this + method. +*/ +void QCPAxisTickerText::setSubTickCount(int subTicks) +{ + if (subTicks >= 0) + mSubTickCount = subTicks; + else + qDebug() << Q_FUNC_INFO << "sub tick count can't be negative:" << subTicks; +} + +/*! + Clears all ticks. + + An alternative to manipulate ticks is to directly access the internal storage with the \ref ticks + getter. + + \see setTicks, addTicks, addTick +*/ +void QCPAxisTickerText::clear() +{ + mTicks.clear(); +} + +/*! + Adds a single tick to the axis at the given axis coordinate \a position, with the provided tick \a + label. + + \see addTicks, setTicks, clear +*/ +void QCPAxisTickerText::addTick(double position, const QString &label) +{ + mTicks.insert(position, label); +} + +/*! \overload + + Adds the provided \a ticks to the ones already existing. The map key of \a ticks corresponds to + the axis coordinate, and the map value is the string that will appear as tick label. + + An alternative to manipulate ticks is to directly access the internal storage with the \ref ticks + getter. + + \see addTick, setTicks, clear +*/ +void QCPAxisTickerText::addTicks(const QMap &ticks) +{ +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) + mTicks.unite(ticks); +#else + mTicks.insert(ticks); +#endif +} + +/*! \overload + + Adds the provided ticks to the ones already existing. The entries of \a positions correspond to + the axis coordinates, and the entries of \a labels are the respective strings that will appear as + tick labels. + + An alternative to manipulate ticks is to directly access the internal storage with the \ref ticks + getter. + + \see addTick, setTicks, clear +*/ +void QCPAxisTickerText::addTicks(const QVector &positions, const QVector &labels) +{ + if (positions.size() != labels.size()) + qDebug() << Q_FUNC_INFO << "passed unequal length vectors for positions and labels:" << positions.size() << labels.size(); + int n = qMin(positions.size(), labels.size()); + for (int i=0; i QCPAxisTickerText::createTickVector(double tickStep, const QCPRange &range) +{ + Q_UNUSED(tickStep) + QVector result; + if (mTicks.isEmpty()) + return result; + + QMap::const_iterator start = mTicks.lowerBound(range.lower); + QMap::const_iterator end = mTicks.upperBound(range.upper); + // this method should try to give one tick outside of range so proper subticks can be generated: + if (start != mTicks.constBegin()) --start; + if (end != mTicks.constEnd()) ++end; + for (QMap::const_iterator it = start; it != end; ++it) + result.append(it.key()); + + return result; +} +/* end of 'src/axis/axistickertext.cpp' */ + + +/* including file 'src/axis/axistickerpi.cpp' */ +/* modified 2022-11-06T12:45:56, size 11177 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAxisTickerPi +//////////////////////////////////////////////////////////////////////////////////////////////////// +/*! \class QCPAxisTickerPi + \brief Specialized axis ticker to display ticks in units of an arbitrary constant, for example pi + + \image html axisticker-pi.png + + This QCPAxisTicker subclass generates ticks that are expressed with respect to a given symbolic + constant with a numerical value specified with \ref setPiValue and an appearance in the tick + labels specified with \ref setPiSymbol. + + Ticks may be generated at fractions of the symbolic constant. How these fractions appear in the + tick label can be configured with \ref setFractionStyle. + + The ticker can be created and assigned to an axis like this: + \snippet documentation/doc-image-generator/mainwindow.cpp axistickerpi-creation +*/ + +/*! + Constructs the ticker and sets reasonable default values. Axis tickers are commonly created + managed by a QSharedPointer, which then can be passed to QCPAxis::setTicker. +*/ +QCPAxisTickerPi::QCPAxisTickerPi() : + mPiSymbol(QLatin1String(" ")+QChar(0x03C0)), + mPiValue(M_PI), + mPeriodicity(0), + mFractionStyle(fsUnicodeFractions), + mPiTickStep(0) +{ + setTickCount(4); +} + +/*! + Sets how the symbol part (which is always a suffix to the number) shall appear in the axis tick + label. + + If a space shall appear between the number and the symbol, make sure the space is contained in \a + symbol. +*/ +void QCPAxisTickerPi::setPiSymbol(QString symbol) +{ + mPiSymbol = symbol; +} + +/*! + Sets the numerical value that the symbolic constant has. + + This will be used to place the appropriate fractions of the symbol at the respective axis + coordinates. +*/ +void QCPAxisTickerPi::setPiValue(double pi) +{ + mPiValue = pi; +} + +/*! + Sets whether the axis labels shall appear periodicly and if so, at which multiplicity of the + symbolic constant. + + To disable periodicity, set \a multiplesOfPi to zero. + + For example, an axis that identifies 0 with 2pi would set \a multiplesOfPi to two. +*/ +void QCPAxisTickerPi::setPeriodicity(int multiplesOfPi) +{ + mPeriodicity = qAbs(multiplesOfPi); +} + +/*! + Sets how the numerical/fractional part preceding the symbolic constant is displayed in tick + labels. See \ref FractionStyle for the various options. +*/ +void QCPAxisTickerPi::setFractionStyle(QCPAxisTickerPi::FractionStyle style) +{ + mFractionStyle = style; +} + +/*! \internal + + Returns the tick step, using the constant's value (\ref setPiValue) as base unit. In consequence + the numerical/fractional part preceding the symbolic constant is made to have a readable + mantissa. + + \seebaseclassmethod +*/ +double QCPAxisTickerPi::getTickStep(const QCPRange &range) +{ + mPiTickStep = range.size()/mPiValue/double(mTickCount+1e-10); // mTickCount ticks on average, the small addition is to prevent jitter on exact integers + mPiTickStep = cleanMantissa(mPiTickStep); + return mPiTickStep*mPiValue; +} + +/*! \internal + + Returns the sub tick count, using the constant's value (\ref setPiValue) as base unit. In + consequence the sub ticks divide the numerical/fractional part preceding the symbolic constant + reasonably, and not the total tick coordinate. + + \seebaseclassmethod +*/ +int QCPAxisTickerPi::getSubTickCount(double tickStep) +{ + return QCPAxisTicker::getSubTickCount(tickStep/mPiValue); +} + +/*! \internal + + Returns the tick label as a fractional/numerical part and a symbolic string as suffix. The + formatting of the fraction is done according to the specified \ref setFractionStyle. The appended + symbol is specified with \ref setPiSymbol. + + \seebaseclassmethod +*/ +QString QCPAxisTickerPi::getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) +{ + double tickInPis = tick/mPiValue; + if (mPeriodicity > 0) + tickInPis = fmod(tickInPis, mPeriodicity); + + if (mFractionStyle != fsFloatingPoint && mPiTickStep > 0.09 && mPiTickStep < 50) + { + // simply construct fraction from decimal like 1.234 -> 1234/1000 and then simplify fraction, smaller digits are irrelevant due to mPiTickStep conditional above + int denominator = 1000; + int numerator = qRound(tickInPis*denominator); + simplifyFraction(numerator, denominator); + if (qAbs(numerator) == 1 && denominator == 1) + return (numerator < 0 ? QLatin1String("-") : QLatin1String("")) + mPiSymbol.trimmed(); + else if (numerator == 0) + return QLatin1String("0"); + else + return fractionToString(numerator, denominator) + mPiSymbol; + } else + { + if (qFuzzyIsNull(tickInPis)) + return QLatin1String("0"); + else if (qFuzzyCompare(qAbs(tickInPis), 1.0)) + return (tickInPis < 0 ? QLatin1String("-") : QLatin1String("")) + mPiSymbol.trimmed(); + else + return QCPAxisTicker::getTickLabel(tickInPis, locale, formatChar, precision) + mPiSymbol; + } +} + +/*! \internal + + Takes the fraction given by \a numerator and \a denominator and modifies the values to make sure + the fraction is in irreducible form, i.e. numerator and denominator don't share any common + factors which could be cancelled. +*/ +void QCPAxisTickerPi::simplifyFraction(int &numerator, int &denominator) const +{ + if (numerator == 0 || denominator == 0) + return; + + int num = numerator; + int denom = denominator; + while (denom != 0) // euclidean gcd algorithm + { + int oldDenom = denom; + denom = num % denom; + num = oldDenom; + } + // num is now gcd of numerator and denominator + numerator /= num; + denominator /= num; +} + +/*! \internal + + Takes the fraction given by \a numerator and \a denominator and returns a string representation. + The result depends on the configured fraction style (\ref setFractionStyle). + + This method is used to format the numerical/fractional part when generating tick labels. It + simplifies the passed fraction to an irreducible form using \ref simplifyFraction and factors out + any integer parts of the fraction (e.g. "10/4" becomes "2 1/2"). +*/ +QString QCPAxisTickerPi::fractionToString(int numerator, int denominator) const +{ + if (denominator == 0) + { + qDebug() << Q_FUNC_INFO << "called with zero denominator"; + return QString(); + } + if (mFractionStyle == fsFloatingPoint) // should never be the case when calling this function + { + qDebug() << Q_FUNC_INFO << "shouldn't be called with fraction style fsDecimal"; + return QString::number(numerator/double(denominator)); // failsafe + } + int sign = numerator*denominator < 0 ? -1 : 1; + numerator = qAbs(numerator); + denominator = qAbs(denominator); + + if (denominator == 1) + { + return QString::number(sign*numerator); + } else + { + int integerPart = numerator/denominator; + int remainder = numerator%denominator; + if (remainder == 0) + { + return QString::number(sign*integerPart); + } else + { + if (mFractionStyle == fsAsciiFractions) + { + return QString(QLatin1String("%1%2%3/%4")) + .arg(sign == -1 ? QLatin1String("-") : QLatin1String("")) + .arg(integerPart > 0 ? QString::number(integerPart)+QLatin1String(" ") : QString(QLatin1String(""))) + .arg(remainder) + .arg(denominator); + } else if (mFractionStyle == fsUnicodeFractions) + { + return QString(QLatin1String("%1%2%3")) + .arg(sign == -1 ? QLatin1String("-") : QLatin1String("")) + .arg(integerPart > 0 ? QString::number(integerPart) : QLatin1String("")) + .arg(unicodeFraction(remainder, denominator)); + } + } + } + return QString(); +} + +/*! \internal + + Returns the unicode string representation of the fraction given by \a numerator and \a + denominator. This is the representation used in \ref fractionToString when the fraction style + (\ref setFractionStyle) is \ref fsUnicodeFractions. + + This method doesn't use the single-character common fractions but builds each fraction from a + superscript unicode number, the unicode fraction character, and a subscript unicode number. +*/ +QString QCPAxisTickerPi::unicodeFraction(int numerator, int denominator) const +{ + return unicodeSuperscript(numerator)+QChar(0x2044)+unicodeSubscript(denominator); +} + +/*! \internal + + Returns the unicode string representing \a number as superscript. This is used to build + unicode fractions in \ref unicodeFraction. +*/ +QString QCPAxisTickerPi::unicodeSuperscript(int number) const +{ + if (number == 0) + return QString(QChar(0x2070)); + + QString result; + while (number > 0) + { + const int digit = number%10; + switch (digit) + { + case 1: { result.prepend(QChar(0x00B9)); break; } + case 2: { result.prepend(QChar(0x00B2)); break; } + case 3: { result.prepend(QChar(0x00B3)); break; } + default: { result.prepend(QChar(0x2070+digit)); break; } + } + number /= 10; + } + return result; +} + +/*! \internal + + Returns the unicode string representing \a number as subscript. This is used to build unicode + fractions in \ref unicodeFraction. +*/ +QString QCPAxisTickerPi::unicodeSubscript(int number) const +{ + if (number == 0) + return QString(QChar(0x2080)); + + QString result; + while (number > 0) + { + result.prepend(QChar(0x2080+number%10)); + number /= 10; + } + return result; +} +/* end of 'src/axis/axistickerpi.cpp' */ + + +/* including file 'src/axis/axistickerlog.cpp' */ +/* modified 2022-11-06T12:45:56, size 7890 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAxisTickerLog +//////////////////////////////////////////////////////////////////////////////////////////////////// +/*! \class QCPAxisTickerLog + \brief Specialized axis ticker suited for logarithmic axes + + \image html axisticker-log.png + + This QCPAxisTicker subclass generates ticks with unequal tick intervals suited for logarithmic + axis scales. The ticks are placed at powers of the specified log base (\ref setLogBase). + + Especially in the case of a log base equal to 10 (the default), it might be desirable to have + tick labels in the form of powers of ten without mantissa display. To achieve this, set the + number precision (\ref QCPAxis::setNumberPrecision) to zero and the number format (\ref + QCPAxis::setNumberFormat) to scientific (exponential) display with beautifully typeset decimal + powers, so a format string of "eb". This will result in the following axis tick labels: + + \image html axisticker-log-powers.png + + The ticker can be created and assigned to an axis like this: + \snippet documentation/doc-image-generator/mainwindow.cpp axistickerlog-creation + + Note that the nature of logarithmic ticks imply that there exists a smallest possible tick step, + corresponding to one multiplication by the log base. If the user zooms in further than that, no + new ticks would appear, leading to very sparse or even no axis ticks on the axis. To prevent this + situation, this ticker falls back to regular tick generation if the axis range would be covered + by too few logarithmically placed ticks. +*/ + +/*! + Constructs the ticker and sets reasonable default values. Axis tickers are commonly created + managed by a QSharedPointer, which then can be passed to QCPAxis::setTicker. +*/ +QCPAxisTickerLog::QCPAxisTickerLog() : + mLogBase(10.0), + mSubTickCount(8), // generates 10 intervals + mLogBaseLnInv(1.0/qLn(mLogBase)) +{ +} + +/*! + Sets the logarithm base used for tick coordinate generation. The ticks will be placed at integer + powers of \a base. +*/ +void QCPAxisTickerLog::setLogBase(double base) +{ + if (base > 0) + { + mLogBase = base; + mLogBaseLnInv = 1.0/qLn(mLogBase); + } else + qDebug() << Q_FUNC_INFO << "log base has to be greater than zero:" << base; +} + +/*! + Sets the number of sub ticks in a tick interval. Within each interval, the sub ticks are spaced + linearly to provide a better visual guide, so the sub tick density increases toward the higher + tick. + + Note that \a subTicks is the number of sub ticks (not sub intervals) in one tick interval. So in + the case of logarithm base 10 an intuitive sub tick spacing would be achieved with eight sub + ticks (the default). This means e.g. between the ticks 10 and 100 there will be eight ticks, + namely at 20, 30, 40, 50, 60, 70, 80 and 90. +*/ +void QCPAxisTickerLog::setSubTickCount(int subTicks) +{ + if (subTicks >= 0) + mSubTickCount = subTicks; + else + qDebug() << Q_FUNC_INFO << "sub tick count can't be negative:" << subTicks; +} + +/*! \internal + + Returns the sub tick count specified in \ref setSubTickCount. For QCPAxisTickerLog, there is no + automatic sub tick count calculation necessary. + + \seebaseclassmethod +*/ +int QCPAxisTickerLog::getSubTickCount(double tickStep) +{ + Q_UNUSED(tickStep) + return mSubTickCount; +} + +/*! \internal + + Creates ticks with a spacing given by the logarithm base and an increasing integer power in the + provided \a range. The step in which the power increases tick by tick is chosen in order to keep + the total number of ticks as close as possible to the tick count (\ref setTickCount). + + The parameter \a tickStep is ignored for the normal logarithmic ticker generation. Only when + zoomed in very far such that not enough logarithmically placed ticks would be visible, this + function falls back to the regular QCPAxisTicker::createTickVector, which then uses \a tickStep. + + \seebaseclassmethod +*/ +QVector QCPAxisTickerLog::createTickVector(double tickStep, const QCPRange &range) +{ + QVector result; + if (range.lower > 0 && range.upper > 0) // positive range + { + const double baseTickCount = qLn(range.upper/range.lower)*mLogBaseLnInv; + if (baseTickCount < 1.6) // if too few log ticks would be visible in axis range, fall back to regular tick vector generation + return QCPAxisTicker::createTickVector(tickStep, range); + const double exactPowerStep = baseTickCount/double(mTickCount+1e-10); + const double newLogBase = qPow(mLogBase, qMax(int(cleanMantissa(exactPowerStep)), 1)); + double currentTick = qPow(newLogBase, qFloor(qLn(range.lower)/qLn(newLogBase))); + result.append(currentTick); + while (currentTick < range.upper && currentTick > 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case + { + currentTick *= newLogBase; + result.append(currentTick); + } + } else if (range.lower < 0 && range.upper < 0) // negative range + { + const double baseTickCount = qLn(range.lower/range.upper)*mLogBaseLnInv; + if (baseTickCount < 1.6) // if too few log ticks would be visible in axis range, fall back to regular tick vector generation + return QCPAxisTicker::createTickVector(tickStep, range); + const double exactPowerStep = baseTickCount/double(mTickCount+1e-10); + const double newLogBase = qPow(mLogBase, qMax(int(cleanMantissa(exactPowerStep)), 1)); + double currentTick = -qPow(newLogBase, qCeil(qLn(-range.lower)/qLn(newLogBase))); + result.append(currentTick); + while (currentTick < range.upper && currentTick < 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case + { + currentTick /= newLogBase; + result.append(currentTick); + } + } else // invalid range for logarithmic scale, because lower and upper have different sign + { + qDebug() << Q_FUNC_INFO << "Invalid range for logarithmic plot: " << range.lower << ".." << range.upper; + } + + return result; +} +/* end of 'src/axis/axistickerlog.cpp' */ + + +/* including file 'src/axis/axis.cpp' */ +/* modified 2022-11-06T12:45:56, size 99911 */ + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPGrid +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPGrid + \brief Responsible for drawing the grid of a QCPAxis. + + This class is tightly bound to QCPAxis. Every axis owns a grid instance and uses it to draw the + grid lines, sub grid lines and zero-line. You can interact with the grid of an axis via \ref + QCPAxis::grid. Normally, you don't need to create an instance of QCPGrid yourself. + + The axis and grid drawing was split into two classes to allow them to be placed on different + layers (both QCPAxis and QCPGrid inherit from QCPLayerable). Thus it is possible to have the grid + in the background and the axes in the foreground, and any plottables/items in between. This + described situation is the default setup, see the QCPLayer documentation. +*/ + +/*! + Creates a QCPGrid instance and sets default values. + + You shouldn't instantiate grids on their own, since every QCPAxis brings its own QCPGrid. +*/ +QCPGrid::QCPGrid(QCPAxis *parentAxis) : + QCPLayerable(parentAxis->parentPlot(), QString(), parentAxis), + mSubGridVisible{}, + mAntialiasedSubGrid{}, + mAntialiasedZeroLine{}, + mParentAxis(parentAxis) +{ + // warning: this is called in QCPAxis constructor, so parentAxis members should not be accessed/called + setParent(parentAxis); + setPen(QPen(QColor(200,200,200), 0, Qt::DotLine)); + setSubGridPen(QPen(QColor(220,220,220), 0, Qt::DotLine)); + setZeroLinePen(QPen(QColor(200,200,200), 0, Qt::SolidLine)); + setSubGridVisible(false); + setAntialiased(false); + setAntialiasedSubGrid(false); + setAntialiasedZeroLine(false); +} + +/*! + Sets whether grid lines at sub tick marks are drawn. + + \see setSubGridPen +*/ +void QCPGrid::setSubGridVisible(bool visible) +{ + mSubGridVisible = visible; +} + +/*! + Sets whether sub grid lines are drawn antialiased. +*/ +void QCPGrid::setAntialiasedSubGrid(bool enabled) +{ + mAntialiasedSubGrid = enabled; +} + +/*! + Sets whether zero lines are drawn antialiased. +*/ +void QCPGrid::setAntialiasedZeroLine(bool enabled) +{ + mAntialiasedZeroLine = enabled; +} + +/*! + Sets the pen with which (major) grid lines are drawn. +*/ +void QCPGrid::setPen(const QPen &pen) +{ + mPen = pen; +} + +/*! + Sets the pen with which sub grid lines are drawn. +*/ +void QCPGrid::setSubGridPen(const QPen &pen) +{ + mSubGridPen = pen; +} + +/*! + Sets the pen with which zero lines are drawn. + + Zero lines are lines at value coordinate 0 which may be drawn with a different pen than other grid + lines. To disable zero lines and just draw normal grid lines at zero, set \a pen to Qt::NoPen. +*/ +void QCPGrid::setZeroLinePen(const QPen &pen) +{ + mZeroLinePen = pen; +} + +/*! \internal + + A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter + before drawing the major grid lines. + + This is the antialiasing state the painter passed to the \ref draw method is in by default. + + This function takes into account the local setting of the antialiasing flag as well as the + overrides set with \ref QCustomPlot::setAntialiasedElements and \ref + QCustomPlot::setNotAntialiasedElements. + + \see setAntialiased +*/ +void QCPGrid::applyDefaultAntialiasingHint(QCPPainter *painter) const +{ + applyAntialiasingHint(painter, mAntialiased, QCP::aeGrid); +} + +/*! \internal + + Draws grid lines and sub grid lines at the positions of (sub) ticks of the parent axis, spanning + over the complete axis rect. Also draws the zero line, if appropriate (\ref setZeroLinePen). +*/ +void QCPGrid::draw(QCPPainter *painter) +{ + if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; } + + if (mParentAxis->subTicks() && mSubGridVisible) + drawSubGridLines(painter); + drawGridLines(painter); +} + +/*! \internal + + Draws the main grid lines and possibly a zero line with the specified painter. + + This is a helper function called by \ref draw. +*/ +void QCPGrid::drawGridLines(QCPPainter *painter) const +{ + if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; } + + const int tickCount = mParentAxis->mTickVector.size(); + double t; // helper variable, result of coordinate-to-pixel transforms + if (mParentAxis->orientation() == Qt::Horizontal) + { + // draw zeroline: + int zeroLineIndex = -1; + if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0) + { + applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine); + painter->setPen(mZeroLinePen); + double epsilon = mParentAxis->range().size()*1E-6; // for comparing double to zero + for (int i=0; imTickVector.at(i)) < epsilon) + { + zeroLineIndex = i; + t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x + painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top())); + break; + } + } + } + // draw grid lines: + applyDefaultAntialiasingHint(painter); + painter->setPen(mPen); + for (int i=0; icoordToPixel(mParentAxis->mTickVector.at(i)); // x + painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top())); + } + } else + { + // draw zeroline: + int zeroLineIndex = -1; + if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0) + { + applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine); + painter->setPen(mZeroLinePen); + double epsilon = mParentAxis->mRange.size()*1E-6; // for comparing double to zero + for (int i=0; imTickVector.at(i)) < epsilon) + { + zeroLineIndex = i; + t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y + painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t)); + break; + } + } + } + // draw grid lines: + applyDefaultAntialiasingHint(painter); + painter->setPen(mPen); + for (int i=0; icoordToPixel(mParentAxis->mTickVector.at(i)); // y + painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t)); + } + } +} + +/*! \internal + + Draws the sub grid lines with the specified painter. + + This is a helper function called by \ref draw. +*/ +void QCPGrid::drawSubGridLines(QCPPainter *painter) const +{ + if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; } + + applyAntialiasingHint(painter, mAntialiasedSubGrid, QCP::aeSubGrid); + double t; // helper variable, result of coordinate-to-pixel transforms + painter->setPen(mSubGridPen); + if (mParentAxis->orientation() == Qt::Horizontal) + { + foreach (double tickCoord, mParentAxis->mSubTickVector) + { + t = mParentAxis->coordToPixel(tickCoord); // x + painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top())); + } + } else + { + foreach (double tickCoord, mParentAxis->mSubTickVector) + { + t = mParentAxis->coordToPixel(tickCoord); // y + painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t)); + } + } +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAxis +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPAxis + \brief Manages a single axis inside a QCustomPlot. + + Usually doesn't need to be instantiated externally. Access %QCustomPlot's default four axes via + QCustomPlot::xAxis (bottom), QCustomPlot::yAxis (left), QCustomPlot::xAxis2 (top) and + QCustomPlot::yAxis2 (right). + + Axes are always part of an axis rect, see QCPAxisRect. + \image html AxisNamesOverview.png +
Naming convention of axis parts
+ \n + + \image html AxisRectSpacingOverview.png +
Overview of the spacings and paddings that define the geometry of an axis. The dashed gray line + on the left represents the QCustomPlot widget border.
+ + Each axis holds an instance of QCPAxisTicker which is used to generate the tick coordinates and + tick labels. You can access the currently installed \ref ticker or set a new one (possibly one of + the specialized subclasses, or your own subclass) via \ref setTicker. For details, see the + documentation of QCPAxisTicker. +*/ + +/* start of documentation of inline functions */ + +/*! \fn Qt::Orientation QCPAxis::orientation() const + + Returns the orientation of this axis. The axis orientation (horizontal or vertical) is deduced + from the axis type (left, top, right or bottom). + + \see orientation(AxisType type), pixelOrientation +*/ + +/*! \fn QCPGrid *QCPAxis::grid() const + + Returns the \ref QCPGrid instance belonging to this axis. Access it to set details about the way the + grid is displayed. +*/ + +/*! \fn static Qt::Orientation QCPAxis::orientation(AxisType type) + + Returns the orientation of the specified axis type + + \see orientation(), pixelOrientation +*/ + +/*! \fn int QCPAxis::pixelOrientation() const + + Returns which direction points towards higher coordinate values/keys, in pixel space. + + This method returns either 1 or -1. If it returns 1, then going in the positive direction along + the orientation of the axis in pixels corresponds to going from lower to higher axis coordinates. + On the other hand, if this method returns -1, going to smaller pixel values corresponds to going + from lower to higher axis coordinates. + + For example, this is useful to easily shift axis coordinates by a certain amount given in pixels, + without having to care about reversed or vertically aligned axes: + + \code + double newKey = keyAxis->pixelToCoord(keyAxis->coordToPixel(oldKey)+10*keyAxis->pixelOrientation()); + \endcode + + \a newKey will then contain a key that is ten pixels towards higher keys, starting from \a oldKey. +*/ + +/*! \fn QSharedPointer QCPAxis::ticker() const + + Returns a modifiable shared pointer to the currently installed axis ticker. The axis ticker is + responsible for generating the tick positions and tick labels of this axis. You can access the + \ref QCPAxisTicker with this method and modify basic properties such as the approximate tick count + (\ref QCPAxisTicker::setTickCount). + + You can gain more control over the axis ticks by setting a different \ref QCPAxisTicker subclass, see + the documentation there. A new axis ticker can be set with \ref setTicker. + + Since the ticker is stored in the axis as a shared pointer, multiple axes may share the same axis + ticker simply by passing the same shared pointer to multiple axes. + + \see setTicker +*/ + +/* end of documentation of inline functions */ +/* start of documentation of signals */ + +/*! \fn void QCPAxis::rangeChanged(const QCPRange &newRange) + + This signal is emitted when the range of this axis has changed. You can connect it to the \ref + setRange slot of another axis to communicate the new range to the other axis, in order for it to + be synchronized. + + You may also manipulate/correct the range with \ref setRange in a slot connected to this signal. + This is useful if for example a maximum range span shall not be exceeded, or if the lower/upper + range shouldn't go beyond certain values (see \ref QCPRange::bounded). For example, the following + slot would limit the x axis to ranges between 0 and 10: + \code + customPlot->xAxis->setRange(newRange.bounded(0, 10)) + \endcode +*/ + +/*! \fn void QCPAxis::rangeChanged(const QCPRange &newRange, const QCPRange &oldRange) + \overload + + Additionally to the new range, this signal also provides the previous range held by the axis as + \a oldRange. +*/ + +/*! \fn void QCPAxis::scaleTypeChanged(QCPAxis::ScaleType scaleType); + + This signal is emitted when the scale type changes, by calls to \ref setScaleType +*/ + +/*! \fn void QCPAxis::selectionChanged(QCPAxis::SelectableParts selection) + + This signal is emitted when the selection state of this axis has changed, either by user interaction + or by a direct call to \ref setSelectedParts. +*/ + +/*! \fn void QCPAxis::selectableChanged(const QCPAxis::SelectableParts &parts); + + This signal is emitted when the selectability changes, by calls to \ref setSelectableParts +*/ + +/* end of documentation of signals */ + +/*! + Constructs an Axis instance of Type \a type for the axis rect \a parent. + + Usually it isn't necessary to instantiate axes directly, because you can let QCustomPlot create + them for you with \ref QCPAxisRect::addAxis. If you want to use own QCPAxis-subclasses however, + create them manually and then inject them also via \ref QCPAxisRect::addAxis. +*/ +QCPAxis::QCPAxis(QCPAxisRect *parent, AxisType type) : + QCPLayerable(parent->parentPlot(), QString(), parent), + // axis base: + mAxisType(type), + mAxisRect(parent), + mPadding(5), + mOrientation(orientation(type)), + mSelectableParts(spAxis | spTickLabels | spAxisLabel), + mSelectedParts(spNone), + mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + mSelectedBasePen(QPen(Qt::blue, 2)), + // axis label: + mLabel(), + mLabelFont(mParentPlot->font()), + mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)), + mLabelColor(Qt::black), + mSelectedLabelColor(Qt::blue), + // tick labels: + mTickLabels(true), + mTickLabelFont(mParentPlot->font()), + mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)), + mTickLabelColor(Qt::black), + mSelectedTickLabelColor(Qt::blue), + mNumberPrecision(6), + mNumberFormatChar('g'), + mNumberBeautifulPowers(true), + // ticks and subticks: + mTicks(true), + mSubTicks(true), + mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + mSelectedTickPen(QPen(Qt::blue, 2)), + mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + mSelectedSubTickPen(QPen(Qt::blue, 2)), + // scale and range: + mRange(0, 5), + mRangeReversed(false), + mScaleType(stLinear), + // internal members: + mGrid(new QCPGrid(this)), + mAxisPainter(new QCPAxisPainterPrivate(parent->parentPlot())), + mTicker(new QCPAxisTicker), + mCachedMarginValid(false), + mCachedMargin(0), + mDragging(false) +{ + setParent(parent); + mGrid->setVisible(false); + setAntialiased(false); + setLayer(mParentPlot->currentLayer()); // it's actually on that layer already, but we want it in front of the grid, so we place it on there again + + if (type == atTop) + { + setTickLabelPadding(3); + setLabelPadding(6); + } else if (type == atRight) + { + setTickLabelPadding(7); + setLabelPadding(12); + } else if (type == atBottom) + { + setTickLabelPadding(3); + setLabelPadding(3); + } else if (type == atLeft) + { + setTickLabelPadding(5); + setLabelPadding(10); + } +} + +QCPAxis::~QCPAxis() +{ + delete mAxisPainter; + delete mGrid; // delete grid here instead of via parent ~QObject for better defined deletion order +} + +/* No documentation as it is a property getter */ +int QCPAxis::tickLabelPadding() const +{ + return mAxisPainter->tickLabelPadding; +} + +/* No documentation as it is a property getter */ +double QCPAxis::tickLabelRotation() const +{ + return mAxisPainter->tickLabelRotation; +} + +/* No documentation as it is a property getter */ +QCPAxis::LabelSide QCPAxis::tickLabelSide() const +{ + return mAxisPainter->tickLabelSide; +} + +/* No documentation as it is a property getter */ +QString QCPAxis::numberFormat() const +{ + QString result; + result.append(mNumberFormatChar); + if (mNumberBeautifulPowers) + { + result.append(QLatin1Char('b')); + if (mAxisPainter->numberMultiplyCross) + result.append(QLatin1Char('c')); + } + return result; +} + +/* No documentation as it is a property getter */ +int QCPAxis::tickLengthIn() const +{ + return mAxisPainter->tickLengthIn; +} + +/* No documentation as it is a property getter */ +int QCPAxis::tickLengthOut() const +{ + return mAxisPainter->tickLengthOut; +} + +/* No documentation as it is a property getter */ +int QCPAxis::subTickLengthIn() const +{ + return mAxisPainter->subTickLengthIn; +} + +/* No documentation as it is a property getter */ +int QCPAxis::subTickLengthOut() const +{ + return mAxisPainter->subTickLengthOut; +} + +/* No documentation as it is a property getter */ +int QCPAxis::labelPadding() const +{ + return mAxisPainter->labelPadding; +} + +/* No documentation as it is a property getter */ +int QCPAxis::offset() const +{ + return mAxisPainter->offset; +} + +/* No documentation as it is a property getter */ +QCPLineEnding QCPAxis::lowerEnding() const +{ + return mAxisPainter->lowerEnding; +} + +/* No documentation as it is a property getter */ +QCPLineEnding QCPAxis::upperEnding() const +{ + return mAxisPainter->upperEnding; +} + +/*! + Sets whether the axis uses a linear scale or a logarithmic scale. + + Note that this method controls the coordinate transformation. For logarithmic scales, you will + likely also want to use a logarithmic tick spacing and labeling, which can be achieved by setting + the axis ticker to an instance of \ref QCPAxisTickerLog : + + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpaxisticker-log-creation + + See the documentation of \ref QCPAxisTickerLog about the details of logarithmic axis tick + creation. + + \ref setNumberPrecision +*/ +void QCPAxis::setScaleType(QCPAxis::ScaleType type) +{ + if (mScaleType != type) + { + mScaleType = type; + if (mScaleType == stLogarithmic) + setRange(mRange.sanitizedForLogScale()); + mCachedMarginValid = false; + emit scaleTypeChanged(mScaleType); + } +} + +/*! + Sets the range of the axis. + + This slot may be connected with the \ref rangeChanged signal of another axis so this axis + is always synchronized with the other axis range, when it changes. + + To invert the direction of an axis, use \ref setRangeReversed. +*/ +void QCPAxis::setRange(const QCPRange &range) +{ + if (range.lower == mRange.lower && range.upper == mRange.upper) + return; + + if (!QCPRange::validRange(range)) return; + QCPRange oldRange = mRange; + if (mScaleType == stLogarithmic) + { + mRange = range.sanitizedForLogScale(); + } else + { + mRange = range.sanitizedForLinScale(); + } + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); +} + +/*! + Sets whether the user can (de-)select the parts in \a selectable by clicking on the QCustomPlot surface. + (When \ref QCustomPlot::setInteractions contains iSelectAxes.) + + However, even when \a selectable is set to a value not allowing the selection of a specific part, + it is still possible to set the selection of this part manually, by calling \ref setSelectedParts + directly. + + \see SelectablePart, setSelectedParts +*/ +void QCPAxis::setSelectableParts(const SelectableParts &selectable) +{ + if (mSelectableParts != selectable) + { + mSelectableParts = selectable; + emit selectableChanged(mSelectableParts); + } +} + +/*! + Sets the selected state of the respective axis parts described by \ref SelectablePart. When a part + is selected, it uses a different pen/font. + + The entire selection mechanism for axes is handled automatically when \ref + QCustomPlot::setInteractions contains iSelectAxes. You only need to call this function when you + wish to change the selection state manually. + + This function can change the selection state of a part, independent of the \ref setSelectableParts setting. + + emits the \ref selectionChanged signal when \a selected is different from the previous selection state. + + \see SelectablePart, setSelectableParts, selectTest, setSelectedBasePen, setSelectedTickPen, setSelectedSubTickPen, + setSelectedTickLabelFont, setSelectedLabelFont, setSelectedTickLabelColor, setSelectedLabelColor +*/ +void QCPAxis::setSelectedParts(const SelectableParts &selected) +{ + if (mSelectedParts != selected) + { + mSelectedParts = selected; + emit selectionChanged(mSelectedParts); + } +} + +/*! + \overload + + Sets the lower and upper bound of the axis range. + + To invert the direction of an axis, use \ref setRangeReversed. + + There is also a slot to set a range, see \ref setRange(const QCPRange &range). +*/ +void QCPAxis::setRange(double lower, double upper) +{ + if (lower == mRange.lower && upper == mRange.upper) + return; + + if (!QCPRange::validRange(lower, upper)) return; + QCPRange oldRange = mRange; + mRange.lower = lower; + mRange.upper = upper; + if (mScaleType == stLogarithmic) + { + mRange = mRange.sanitizedForLogScale(); + } else + { + mRange = mRange.sanitizedForLinScale(); + } + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); +} + +/*! + \overload + + Sets the range of the axis. + + The \a position coordinate indicates together with the \a alignment parameter, where the new + range will be positioned. \a size defines the size of the new axis range. \a alignment may be + Qt::AlignLeft, Qt::AlignRight or Qt::AlignCenter. This will cause the left border, right border, + or center of the range to be aligned with \a position. Any other values of \a alignment will + default to Qt::AlignCenter. +*/ +void QCPAxis::setRange(double position, double size, Qt::AlignmentFlag alignment) +{ + if (alignment == Qt::AlignLeft) + setRange(position, position+size); + else if (alignment == Qt::AlignRight) + setRange(position-size, position); + else // alignment == Qt::AlignCenter + setRange(position-size/2.0, position+size/2.0); +} + +/*! + Sets the lower bound of the axis range. The upper bound is not changed. + \see setRange +*/ +void QCPAxis::setRangeLower(double lower) +{ + if (mRange.lower == lower) + return; + + QCPRange oldRange = mRange; + mRange.lower = lower; + if (mScaleType == stLogarithmic) + { + mRange = mRange.sanitizedForLogScale(); + } else + { + mRange = mRange.sanitizedForLinScale(); + } + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); +} + +/*! + Sets the upper bound of the axis range. The lower bound is not changed. + \see setRange +*/ +void QCPAxis::setRangeUpper(double upper) +{ + if (mRange.upper == upper) + return; + + QCPRange oldRange = mRange; + mRange.upper = upper; + if (mScaleType == stLogarithmic) + { + mRange = mRange.sanitizedForLogScale(); + } else + { + mRange = mRange.sanitizedForLinScale(); + } + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); +} + +/*! + Sets whether the axis range (direction) is displayed reversed. Normally, the values on horizontal + axes increase left to right, on vertical axes bottom to top. When \a reversed is set to true, the + direction of increasing values is inverted. + + Note that the range and data interface stays the same for reversed axes, e.g. the \a lower part + of the \ref setRange interface will still reference the mathematically smaller number than the \a + upper part. +*/ +void QCPAxis::setRangeReversed(bool reversed) +{ + mRangeReversed = reversed; +} + +/*! + The axis ticker is responsible for generating the tick positions and tick labels. See the + documentation of QCPAxisTicker for details on how to work with axis tickers. + + You can change the tick positioning/labeling behaviour of this axis by setting a different + QCPAxisTicker subclass using this method. If you only wish to modify the currently installed axis + ticker, access it via \ref ticker. + + Since the ticker is stored in the axis as a shared pointer, multiple axes may share the same axis + ticker simply by passing the same shared pointer to multiple axes. + + \see ticker +*/ +void QCPAxis::setTicker(QSharedPointer ticker) +{ + if (ticker) + mTicker = ticker; + else + qDebug() << Q_FUNC_INFO << "can not set nullptr as axis ticker"; + // no need to invalidate margin cache here because produced tick labels are checked for changes in setupTickVector +} + +/*! + Sets whether tick marks are displayed. + + Note that setting \a show to false does not imply that tick labels are invisible, too. To achieve + that, see \ref setTickLabels. + + \see setSubTicks +*/ +void QCPAxis::setTicks(bool show) +{ + if (mTicks != show) + { + mTicks = show; + mCachedMarginValid = false; + } +} + +/*! + Sets whether tick labels are displayed. Tick labels are the numbers drawn next to tick marks. +*/ +void QCPAxis::setTickLabels(bool show) +{ + if (mTickLabels != show) + { + mTickLabels = show; + mCachedMarginValid = false; + if (!mTickLabels) + mTickVectorLabels.clear(); + } +} + +/*! + Sets the distance between the axis base line (including any outward ticks) and the tick labels. + \see setLabelPadding, setPadding +*/ +void QCPAxis::setTickLabelPadding(int padding) +{ + if (mAxisPainter->tickLabelPadding != padding) + { + mAxisPainter->tickLabelPadding = padding; + mCachedMarginValid = false; + } +} + +/*! + Sets the font of the tick labels. + + \see setTickLabels, setTickLabelColor +*/ +void QCPAxis::setTickLabelFont(const QFont &font) +{ + if (font != mTickLabelFont) + { + mTickLabelFont = font; + mCachedMarginValid = false; + } +} + +/*! + Sets the color of the tick labels. + + \see setTickLabels, setTickLabelFont +*/ +void QCPAxis::setTickLabelColor(const QColor &color) +{ + mTickLabelColor = color; +} + +/*! + Sets the rotation of the tick labels. If \a degrees is zero, the labels are drawn normally. Else, + the tick labels are drawn rotated by \a degrees clockwise. The specified angle is bound to values + from -90 to 90 degrees. + + If \a degrees is exactly -90, 0 or 90, the tick labels are centered on the tick coordinate. For + other angles, the label is drawn with an offset such that it seems to point toward or away from + the tick mark. +*/ +void QCPAxis::setTickLabelRotation(double degrees) +{ + if (!qFuzzyIsNull(degrees-mAxisPainter->tickLabelRotation)) + { + mAxisPainter->tickLabelRotation = qBound(-90.0, degrees, 90.0); + mCachedMarginValid = false; + } +} + +/*! + Sets whether the tick labels (numbers) shall appear inside or outside the axis rect. + + The usual and default setting is \ref lsOutside. Very compact plots sometimes require tick labels + to be inside the axis rect, to save space. If \a side is set to \ref lsInside, the tick labels + appear on the inside are additionally clipped to the axis rect. +*/ +void QCPAxis::setTickLabelSide(LabelSide side) +{ + mAxisPainter->tickLabelSide = side; + mCachedMarginValid = false; +} + +/*! + Sets the number format for the numbers in tick labels. This \a formatCode is an extended version + of the format code used e.g. by QString::number() and QLocale::toString(). For reference about + that, see the "Argument Formats" section in the detailed description of the QString class. + + \a formatCode is a string of one, two or three characters. + + The first character is identical to + the normal format code used by Qt. In short, this means: 'e'/'E' scientific format, 'f' fixed + format, 'g'/'G' scientific or fixed, whichever is shorter. For the 'e', 'E', and 'f' formats, + the precision set by \ref setNumberPrecision represents the number of digits after the decimal + point. For the 'g' and 'G' formats, the precision represents the maximum number of significant + digits, trailing zeroes are omitted. + + The second and third characters are optional and specific to QCustomPlot:\n + If the first char was 'e' or 'g', numbers are/might be displayed in the scientific format, e.g. + "5.5e9", which is ugly in a plot. So when the second char of \a formatCode is set to 'b' (for + "beautiful"), those exponential numbers are formatted in a more natural way, i.e. "5.5 + [multiplication sign] 10 [superscript] 9". By default, the multiplication sign is a centered dot. + If instead a cross should be shown (as is usual in the USA), the third char of \a formatCode can + be set to 'c'. The inserted multiplication signs are the UTF-8 characters 215 (0xD7) for the + cross and 183 (0xB7) for the dot. + + Examples for \a formatCode: + \li \c g normal format code behaviour. If number is small, fixed format is used, if number is large, + normal scientific format is used + \li \c gb If number is small, fixed format is used, if number is large, scientific format is used with + beautifully typeset decimal powers and a dot as multiplication sign + \li \c ebc All numbers are in scientific format with beautifully typeset decimal power and a cross as + multiplication sign + \li \c fb illegal format code, since fixed format doesn't support (or need) beautifully typeset decimal + powers. Format code will be reduced to 'f'. + \li \c hello illegal format code, since first char is not 'e', 'E', 'f', 'g' or 'G'. Current format + code will not be changed. +*/ +void QCPAxis::setNumberFormat(const QString &formatCode) +{ + if (formatCode.isEmpty()) + { + qDebug() << Q_FUNC_INFO << "Passed formatCode is empty"; + return; + } + mCachedMarginValid = false; + + // interpret first char as number format char: + QString allowedFormatChars(QLatin1String("eEfgG")); + if (allowedFormatChars.contains(formatCode.at(0))) + { + mNumberFormatChar = QLatin1Char(formatCode.at(0).toLatin1()); + } else + { + qDebug() << Q_FUNC_INFO << "Invalid number format code (first char not in 'eEfgG'):" << formatCode; + return; + } + if (formatCode.length() < 2) + { + mNumberBeautifulPowers = false; + mAxisPainter->numberMultiplyCross = false; + return; + } + + // interpret second char as indicator for beautiful decimal powers: + if (formatCode.at(1) == QLatin1Char('b') && (mNumberFormatChar == QLatin1Char('e') || mNumberFormatChar == QLatin1Char('g'))) + { + mNumberBeautifulPowers = true; + } else + { + qDebug() << Q_FUNC_INFO << "Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode; + return; + } + if (formatCode.length() < 3) + { + mAxisPainter->numberMultiplyCross = false; + return; + } + + // interpret third char as indicator for dot or cross multiplication symbol: + if (formatCode.at(2) == QLatin1Char('c')) + { + mAxisPainter->numberMultiplyCross = true; + } else if (formatCode.at(2) == QLatin1Char('d')) + { + mAxisPainter->numberMultiplyCross = false; + } else + { + qDebug() << Q_FUNC_INFO << "Invalid number format code (third char neither 'c' nor 'd'):" << formatCode; + return; + } +} + +/*! + Sets the precision of the tick label numbers. See QLocale::toString(double i, char f, int prec) + for details. The effect of precisions are most notably for number Formats starting with 'e', see + \ref setNumberFormat +*/ +void QCPAxis::setNumberPrecision(int precision) +{ + if (mNumberPrecision != precision) + { + mNumberPrecision = precision; + mCachedMarginValid = false; + } +} + +/*! + Sets the length of the ticks in pixels. \a inside is the length the ticks will reach inside the + plot and \a outside is the length they will reach outside the plot. If \a outside is greater than + zero, the tick labels and axis label will increase their distance to the axis accordingly, so + they won't collide with the ticks. + + \see setSubTickLength, setTickLengthIn, setTickLengthOut +*/ +void QCPAxis::setTickLength(int inside, int outside) +{ + setTickLengthIn(inside); + setTickLengthOut(outside); +} + +/*! + Sets the length of the inward ticks in pixels. \a inside is the length the ticks will reach + inside the plot. + + \see setTickLengthOut, setTickLength, setSubTickLength +*/ +void QCPAxis::setTickLengthIn(int inside) +{ + if (mAxisPainter->tickLengthIn != inside) + { + mAxisPainter->tickLengthIn = inside; + } +} + +/*! + Sets the length of the outward ticks in pixels. \a outside is the length the ticks will reach + outside the plot. If \a outside is greater than zero, the tick labels and axis label will + increase their distance to the axis accordingly, so they won't collide with the ticks. + + \see setTickLengthIn, setTickLength, setSubTickLength +*/ +void QCPAxis::setTickLengthOut(int outside) +{ + if (mAxisPainter->tickLengthOut != outside) + { + mAxisPainter->tickLengthOut = outside; + mCachedMarginValid = false; // only outside tick length can change margin + } +} + +/*! + Sets whether sub tick marks are displayed. + + Sub ticks are only potentially visible if (major) ticks are also visible (see \ref setTicks) + + \see setTicks +*/ +void QCPAxis::setSubTicks(bool show) +{ + if (mSubTicks != show) + { + mSubTicks = show; + mCachedMarginValid = false; + } +} + +/*! + Sets the length of the subticks in pixels. \a inside is the length the subticks will reach inside + the plot and \a outside is the length they will reach outside the plot. If \a outside is greater + than zero, the tick labels and axis label will increase their distance to the axis accordingly, + so they won't collide with the ticks. + + \see setTickLength, setSubTickLengthIn, setSubTickLengthOut +*/ +void QCPAxis::setSubTickLength(int inside, int outside) +{ + setSubTickLengthIn(inside); + setSubTickLengthOut(outside); +} + +/*! + Sets the length of the inward subticks in pixels. \a inside is the length the subticks will reach inside + the plot. + + \see setSubTickLengthOut, setSubTickLength, setTickLength +*/ +void QCPAxis::setSubTickLengthIn(int inside) +{ + if (mAxisPainter->subTickLengthIn != inside) + { + mAxisPainter->subTickLengthIn = inside; + } +} + +/*! + Sets the length of the outward subticks in pixels. \a outside is the length the subticks will reach + outside the plot. If \a outside is greater than zero, the tick labels will increase their + distance to the axis accordingly, so they won't collide with the ticks. + + \see setSubTickLengthIn, setSubTickLength, setTickLength +*/ +void QCPAxis::setSubTickLengthOut(int outside) +{ + if (mAxisPainter->subTickLengthOut != outside) + { + mAxisPainter->subTickLengthOut = outside; + mCachedMarginValid = false; // only outside tick length can change margin + } +} + +/*! + Sets the pen, the axis base line is drawn with. + + \see setTickPen, setSubTickPen +*/ +void QCPAxis::setBasePen(const QPen &pen) +{ + mBasePen = pen; +} + +/*! + Sets the pen, tick marks will be drawn with. + + \see setTickLength, setBasePen +*/ +void QCPAxis::setTickPen(const QPen &pen) +{ + mTickPen = pen; +} + +/*! + Sets the pen, subtick marks will be drawn with. + + \see setSubTickCount, setSubTickLength, setBasePen +*/ +void QCPAxis::setSubTickPen(const QPen &pen) +{ + mSubTickPen = pen; +} + +/*! + Sets the font of the axis label. + + \see setLabelColor +*/ +void QCPAxis::setLabelFont(const QFont &font) +{ + if (mLabelFont != font) + { + mLabelFont = font; + mCachedMarginValid = false; + } +} + +/*! + Sets the color of the axis label. + + \see setLabelFont +*/ +void QCPAxis::setLabelColor(const QColor &color) +{ + mLabelColor = color; +} + +/*! + Sets the text of the axis label that will be shown below/above or next to the axis, depending on + its orientation. To disable axis labels, pass an empty string as \a str. +*/ +void QCPAxis::setLabel(const QString &str) +{ + if (mLabel != str) + { + mLabel = str; + mCachedMarginValid = false; + } +} + +/*! + Sets the distance between the tick labels and the axis label. + + \see setTickLabelPadding, setPadding +*/ +void QCPAxis::setLabelPadding(int padding) +{ + if (mAxisPainter->labelPadding != padding) + { + mAxisPainter->labelPadding = padding; + mCachedMarginValid = false; + } +} + +/*! + Sets the padding of the axis. + + When \ref QCPAxisRect::setAutoMargins is enabled, the padding is the additional outer most space, + that is left blank. + + The axis padding has no meaning if \ref QCPAxisRect::setAutoMargins is disabled. + + \see setLabelPadding, setTickLabelPadding +*/ +void QCPAxis::setPadding(int padding) +{ + if (mPadding != padding) + { + mPadding = padding; + mCachedMarginValid = false; + } +} + +/*! + Sets the offset the axis has to its axis rect side. + + If an axis rect side has multiple axes and automatic margin calculation is enabled for that side, + only the offset of the inner most axis has meaning (even if it is set to be invisible). The + offset of the other, outer axes is controlled automatically, to place them at appropriate + positions. +*/ +void QCPAxis::setOffset(int offset) +{ + mAxisPainter->offset = offset; +} + +/*! + Sets the font that is used for tick labels when they are selected. + + \see setTickLabelFont, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions +*/ +void QCPAxis::setSelectedTickLabelFont(const QFont &font) +{ + if (font != mSelectedTickLabelFont) + { + mSelectedTickLabelFont = font; + // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts + } +} + +/*! + Sets the font that is used for the axis label when it is selected. + + \see setLabelFont, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions +*/ +void QCPAxis::setSelectedLabelFont(const QFont &font) +{ + mSelectedLabelFont = font; + // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts +} + +/*! + Sets the color that is used for tick labels when they are selected. + + \see setTickLabelColor, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions +*/ +void QCPAxis::setSelectedTickLabelColor(const QColor &color) +{ + if (color != mSelectedTickLabelColor) + { + mSelectedTickLabelColor = color; + } +} + +/*! + Sets the color that is used for the axis label when it is selected. + + \see setLabelColor, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions +*/ +void QCPAxis::setSelectedLabelColor(const QColor &color) +{ + mSelectedLabelColor = color; +} + +/*! + Sets the pen that is used to draw the axis base line when selected. + + \see setBasePen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions +*/ +void QCPAxis::setSelectedBasePen(const QPen &pen) +{ + mSelectedBasePen = pen; +} + +/*! + Sets the pen that is used to draw the (major) ticks when selected. + + \see setTickPen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions +*/ +void QCPAxis::setSelectedTickPen(const QPen &pen) +{ + mSelectedTickPen = pen; +} + +/*! + Sets the pen that is used to draw the subticks when selected. + + \see setSubTickPen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions +*/ +void QCPAxis::setSelectedSubTickPen(const QPen &pen) +{ + mSelectedSubTickPen = pen; +} + +/*! + Sets the style for the lower axis ending. See the documentation of QCPLineEnding for available + styles. + + For horizontal axes, this method refers to the left ending, for vertical axes the bottom ending. + Note that this meaning does not change when the axis range is reversed with \ref + setRangeReversed. + + \see setUpperEnding +*/ +void QCPAxis::setLowerEnding(const QCPLineEnding &ending) +{ + mAxisPainter->lowerEnding = ending; +} + +/*! + Sets the style for the upper axis ending. See the documentation of QCPLineEnding for available + styles. + + For horizontal axes, this method refers to the right ending, for vertical axes the top ending. + Note that this meaning does not change when the axis range is reversed with \ref + setRangeReversed. + + \see setLowerEnding +*/ +void QCPAxis::setUpperEnding(const QCPLineEnding &ending) +{ + mAxisPainter->upperEnding = ending; +} + +/*! + If the scale type (\ref setScaleType) is \ref stLinear, \a diff is added to the lower and upper + bounds of the range. The range is simply moved by \a diff. + + If the scale type is \ref stLogarithmic, the range bounds are multiplied by \a diff. This + corresponds to an apparent "linear" move in logarithmic scaling by a distance of log(diff). +*/ +void QCPAxis::moveRange(double diff) +{ + QCPRange oldRange = mRange; + if (mScaleType == stLinear) + { + mRange.lower += diff; + mRange.upper += diff; + } else // mScaleType == stLogarithmic + { + mRange.lower *= diff; + mRange.upper *= diff; + } + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); +} + +/*! + Scales the range of this axis by \a factor around the center of the current axis range. For + example, if \a factor is 2.0, then the axis range will double its size, and the point at the axis + range center won't have changed its position in the QCustomPlot widget (i.e. coordinates around + the center will have moved symmetrically closer). + + If you wish to scale around a different coordinate than the current axis range center, use the + overload \ref scaleRange(double factor, double center). +*/ +void QCPAxis::scaleRange(double factor) +{ + scaleRange(factor, range().center()); +} + +/*! \overload + + Scales the range of this axis by \a factor around the coordinate \a center. For example, if \a + factor is 2.0, \a center is 1.0, then the axis range will double its size, and the point at + coordinate 1.0 won't have changed its position in the QCustomPlot widget (i.e. coordinates + around 1.0 will have moved symmetrically closer to 1.0). + + \see scaleRange(double factor) +*/ +void QCPAxis::scaleRange(double factor, double center) +{ + QCPRange oldRange = mRange; + if (mScaleType == stLinear) + { + QCPRange newRange; + newRange.lower = (mRange.lower-center)*factor + center; + newRange.upper = (mRange.upper-center)*factor + center; + if (QCPRange::validRange(newRange)) + mRange = newRange.sanitizedForLinScale(); + } else // mScaleType == stLogarithmic + { + if ((mRange.upper < 0 && center < 0) || (mRange.upper > 0 && center > 0)) // make sure center has same sign as range + { + QCPRange newRange; + newRange.lower = qPow(mRange.lower/center, factor)*center; + newRange.upper = qPow(mRange.upper/center, factor)*center; + if (QCPRange::validRange(newRange)) + mRange = newRange.sanitizedForLogScale(); + } else + qDebug() << Q_FUNC_INFO << "Center of scaling operation doesn't lie in same logarithmic sign domain as range:" << center; + } + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); +} + +/*! + Scales the range of this axis to have a certain scale \a ratio to \a otherAxis. The scaling will + be done around the center of the current axis range. + + For example, if \a ratio is 1, this axis is the \a yAxis and \a otherAxis is \a xAxis, graphs + plotted with those axes will appear in a 1:1 aspect ratio, independent of the aspect ratio the + axis rect has. + + This is an operation that changes the range of this axis once, it doesn't fix the scale ratio + indefinitely. Note that calling this function in the constructor of the QCustomPlot's parent + won't have the desired effect, since the widget dimensions aren't defined yet, and a resizeEvent + will follow. +*/ +void QCPAxis::setScaleRatio(const QCPAxis *otherAxis, double ratio) +{ + int otherPixelSize, ownPixelSize; + + if (otherAxis->orientation() == Qt::Horizontal) + otherPixelSize = otherAxis->axisRect()->width(); + else + otherPixelSize = otherAxis->axisRect()->height(); + + if (orientation() == Qt::Horizontal) + ownPixelSize = axisRect()->width(); + else + ownPixelSize = axisRect()->height(); + + double newRangeSize = ratio*otherAxis->range().size()*ownPixelSize/double(otherPixelSize); + setRange(range().center(), newRangeSize, Qt::AlignCenter); +} + +/*! + Changes the axis range such that all plottables associated with this axis are fully visible in + that dimension. + + \see QCPAbstractPlottable::rescaleAxes, QCustomPlot::rescaleAxes +*/ +void QCPAxis::rescale(bool onlyVisiblePlottables) +{ + QCPRange newRange; + bool haveRange = false; + foreach (QCPAbstractPlottable *plottable, plottables()) + { + if (!plottable->realVisibility() && onlyVisiblePlottables) + continue; + QCPRange plottableRange; + bool currentFoundRange; + QCP::SignDomain signDomain = QCP::sdBoth; + if (mScaleType == stLogarithmic) + signDomain = (mRange.upper < 0 ? QCP::sdNegative : QCP::sdPositive); + if (plottable->keyAxis() == this) + plottableRange = plottable->getKeyRange(currentFoundRange, signDomain); + else + plottableRange = plottable->getValueRange(currentFoundRange, signDomain); + if (currentFoundRange) + { + if (!haveRange) + newRange = plottableRange; + else + newRange.expand(plottableRange); + haveRange = true; + } + } + if (haveRange) + { + if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable + { + double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason + if (mScaleType == stLinear) + { + newRange.lower = center-mRange.size()/2.0; + newRange.upper = center+mRange.size()/2.0; + } else // mScaleType == stLogarithmic + { + newRange.lower = center/qSqrt(mRange.upper/mRange.lower); + newRange.upper = center*qSqrt(mRange.upper/mRange.lower); + } + } + setRange(newRange); + } +} + +/*! + Transforms \a value, in pixel coordinates of the QCustomPlot widget, to axis coordinates. +*/ +double QCPAxis::pixelToCoord(double value) const +{ + if (orientation() == Qt::Horizontal) + { + if (mScaleType == stLinear) + { + if (!mRangeReversed) + return (value-mAxisRect->left())/double(mAxisRect->width())*mRange.size()+mRange.lower; + else + return -(value-mAxisRect->left())/double(mAxisRect->width())*mRange.size()+mRange.upper; + } else // mScaleType == stLogarithmic + { + if (!mRangeReversed) + return qPow(mRange.upper/mRange.lower, (value-mAxisRect->left())/double(mAxisRect->width()))*mRange.lower; + else + return qPow(mRange.upper/mRange.lower, (mAxisRect->left()-value)/double(mAxisRect->width()))*mRange.upper; + } + } else // orientation() == Qt::Vertical + { + if (mScaleType == stLinear) + { + if (!mRangeReversed) + return (mAxisRect->bottom()-value)/double(mAxisRect->height())*mRange.size()+mRange.lower; + else + return -(mAxisRect->bottom()-value)/double(mAxisRect->height())*mRange.size()+mRange.upper; + } else // mScaleType == stLogarithmic + { + if (!mRangeReversed) + return qPow(mRange.upper/mRange.lower, (mAxisRect->bottom()-value)/double(mAxisRect->height()))*mRange.lower; + else + return qPow(mRange.upper/mRange.lower, (value-mAxisRect->bottom())/double(mAxisRect->height()))*mRange.upper; + } + } +} + +/*! + Transforms \a value, in coordinates of the axis, to pixel coordinates of the QCustomPlot widget. +*/ +double QCPAxis::coordToPixel(double value) const +{ + if (orientation() == Qt::Horizontal) + { + if (mScaleType == stLinear) + { + if (!mRangeReversed) + return (value-mRange.lower)/mRange.size()*mAxisRect->width()+mAxisRect->left(); + else + return (mRange.upper-value)/mRange.size()*mAxisRect->width()+mAxisRect->left(); + } else // mScaleType == stLogarithmic + { + if (value >= 0.0 && mRange.upper < 0.0) // invalid value for logarithmic scale, just draw it outside visible range + return !mRangeReversed ? mAxisRect->right()+200 : mAxisRect->left()-200; + else if (value <= 0.0 && mRange.upper >= 0.0) // invalid value for logarithmic scale, just draw it outside visible range + return !mRangeReversed ? mAxisRect->left()-200 : mAxisRect->right()+200; + else + { + if (!mRangeReversed) + return qLn(value/mRange.lower)/qLn(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left(); + else + return qLn(mRange.upper/value)/qLn(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left(); + } + } + } else // orientation() == Qt::Vertical + { + if (mScaleType == stLinear) + { + if (!mRangeReversed) + return mAxisRect->bottom()-(value-mRange.lower)/mRange.size()*mAxisRect->height(); + else + return mAxisRect->bottom()-(mRange.upper-value)/mRange.size()*mAxisRect->height(); + } else // mScaleType == stLogarithmic + { + if (value >= 0.0 && mRange.upper < 0.0) // invalid value for logarithmic scale, just draw it outside visible range + return !mRangeReversed ? mAxisRect->top()-200 : mAxisRect->bottom()+200; + else if (value <= 0.0 && mRange.upper >= 0.0) // invalid value for logarithmic scale, just draw it outside visible range + return !mRangeReversed ? mAxisRect->bottom()+200 : mAxisRect->top()-200; + else + { + if (!mRangeReversed) + return mAxisRect->bottom()-qLn(value/mRange.lower)/qLn(mRange.upper/mRange.lower)*mAxisRect->height(); + else + return mAxisRect->bottom()-qLn(mRange.upper/value)/qLn(mRange.upper/mRange.lower)*mAxisRect->height(); + } + } + } +} + +/*! + Returns the part of the axis that is hit by \a pos (in pixels). The return value of this function + is independent of the user-selectable parts defined with \ref setSelectableParts. Further, this + function does not change the current selection state of the axis. + + If the axis is not visible (\ref setVisible), this function always returns \ref spNone. + + \see setSelectedParts, setSelectableParts, QCustomPlot::setInteractions +*/ +QCPAxis::SelectablePart QCPAxis::getPartAt(const QPointF &pos) const +{ + if (!mVisible) + return spNone; + + if (mAxisPainter->axisSelectionBox().contains(pos.toPoint())) + return spAxis; + else if (mAxisPainter->tickLabelsSelectionBox().contains(pos.toPoint())) + return spTickLabels; + else if (mAxisPainter->labelSelectionBox().contains(pos.toPoint())) + return spAxisLabel; + else + return spNone; +} + +/* inherits documentation from base class */ +double QCPAxis::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +{ + if (!mParentPlot) return -1; + SelectablePart part = getPartAt(pos); + if ((onlySelectable && !mSelectableParts.testFlag(part)) || part == spNone) + return -1; + + if (details) + details->setValue(part); + return mParentPlot->selectionTolerance()*0.99; +} + +/*! + Returns a list of all the plottables that have this axis as key or value axis. + + If you are only interested in plottables of type QCPGraph, see \ref graphs. + + \see graphs, items +*/ +QList QCPAxis::plottables() const +{ + QList result; + if (!mParentPlot) return result; + + foreach (QCPAbstractPlottable *plottable, mParentPlot->mPlottables) + { + if (plottable->keyAxis() == this || plottable->valueAxis() == this) + result.append(plottable); + } + return result; +} + +/*! + Returns a list of all the graphs that have this axis as key or value axis. + + \see plottables, items +*/ +QList QCPAxis::graphs() const +{ + QList result; + if (!mParentPlot) return result; + + foreach (QCPGraph *graph, mParentPlot->mGraphs) + { + if (graph->keyAxis() == this || graph->valueAxis() == this) + result.append(graph); + } + return result; +} + +/*! + Returns a list of all the items that are associated with this axis. An item is considered + associated with an axis if at least one of its positions uses the axis as key or value axis. + + \see plottables, graphs +*/ +QList QCPAxis::items() const +{ + QList result; + if (!mParentPlot) return result; + + foreach (QCPAbstractItem *item, mParentPlot->mItems) + { + foreach (QCPItemPosition *position, item->positions()) + { + if (position->keyAxis() == this || position->valueAxis() == this) + { + result.append(item); + break; + } + } + } + return result; +} + +/*! + Transforms a margin side to the logically corresponding axis type. (QCP::msLeft to + QCPAxis::atLeft, QCP::msRight to QCPAxis::atRight, etc.) +*/ +QCPAxis::AxisType QCPAxis::marginSideToAxisType(QCP::MarginSide side) +{ + switch (side) + { + case QCP::msLeft: return atLeft; + case QCP::msRight: return atRight; + case QCP::msTop: return atTop; + case QCP::msBottom: return atBottom; + default: break; + } + qDebug() << Q_FUNC_INFO << "Invalid margin side passed:" << static_cast(side); + return atLeft; +} + +/*! + Returns the axis type that describes the opposite axis of an axis with the specified \a type. +*/ +QCPAxis::AxisType QCPAxis::opposite(QCPAxis::AxisType type) +{ + switch (type) + { + case atLeft: return atRight; + case atRight: return atLeft; + case atBottom: return atTop; + case atTop: return atBottom; + } + qDebug() << Q_FUNC_INFO << "invalid axis type"; + return atLeft; +} + +/* inherits documentation from base class */ +void QCPAxis::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) +{ + Q_UNUSED(event) + SelectablePart part = details.value(); + if (mSelectableParts.testFlag(part)) + { + SelectableParts selBefore = mSelectedParts; + setSelectedParts(additive ? mSelectedParts^part : part); + if (selectionStateChanged) + *selectionStateChanged = mSelectedParts != selBefore; + } +} + +/* inherits documentation from base class */ +void QCPAxis::deselectEvent(bool *selectionStateChanged) +{ + SelectableParts selBefore = mSelectedParts; + setSelectedParts(mSelectedParts & ~mSelectableParts); + if (selectionStateChanged) + *selectionStateChanged = mSelectedParts != selBefore; +} + +/*! \internal + + This mouse event reimplementation provides the functionality to let the user drag individual axes + exclusively, by startig the drag on top of the axis. + + For the axis to accept this event and perform the single axis drag, the parent \ref QCPAxisRect + must be configured accordingly, i.e. it must allow range dragging in the orientation of this axis + (\ref QCPAxisRect::setRangeDrag) and this axis must be a draggable axis (\ref + QCPAxisRect::setRangeDragAxes) + + \seebaseclassmethod + + \note The dragging of possibly multiple axes at once by starting the drag anywhere in the axis + rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::mousePressEvent. +*/ +void QCPAxis::mousePressEvent(QMouseEvent *event, const QVariant &details) +{ + Q_UNUSED(details) + if (!mParentPlot->interactions().testFlag(QCP::iRangeDrag) || + !mAxisRect->rangeDrag().testFlag(orientation()) || + !mAxisRect->rangeDragAxes(orientation()).contains(this)) + { + event->ignore(); + return; + } + + if (event->buttons() & Qt::LeftButton) + { + mDragging = true; + // initialize antialiasing backup in case we start dragging: + if (mParentPlot->noAntialiasingOnDrag()) + { + mAADragBackup = mParentPlot->antialiasedElements(); + mNotAADragBackup = mParentPlot->notAntialiasedElements(); + } + // Mouse range dragging interaction: + if (mParentPlot->interactions().testFlag(QCP::iRangeDrag)) + mDragStartRange = mRange; + } +} + +/*! \internal + + This mouse event reimplementation provides the functionality to let the user drag individual axes + exclusively, by startig the drag on top of the axis. + + \seebaseclassmethod + + \note The dragging of possibly multiple axes at once by starting the drag anywhere in the axis + rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::mousePressEvent. + + \see QCPAxis::mousePressEvent +*/ +void QCPAxis::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) +{ + if (mDragging) + { + const double startPixel = orientation() == Qt::Horizontal ? startPos.x() : startPos.y(); + const double currentPixel = orientation() == Qt::Horizontal ? event->pos().x() : event->pos().y(); + if (mScaleType == QCPAxis::stLinear) + { + const double diff = pixelToCoord(startPixel) - pixelToCoord(currentPixel); + setRange(mDragStartRange.lower+diff, mDragStartRange.upper+diff); + } else if (mScaleType == QCPAxis::stLogarithmic) + { + const double diff = pixelToCoord(startPixel) / pixelToCoord(currentPixel); + setRange(mDragStartRange.lower*diff, mDragStartRange.upper*diff); + } + + if (mParentPlot->noAntialiasingOnDrag()) + mParentPlot->setNotAntialiasedElements(QCP::aeAll); + mParentPlot->replot(QCustomPlot::rpQueuedReplot); + } +} + +/*! \internal + + This mouse event reimplementation provides the functionality to let the user drag individual axes + exclusively, by startig the drag on top of the axis. + + \seebaseclassmethod + + \note The dragging of possibly multiple axes at once by starting the drag anywhere in the axis + rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::mousePressEvent. + + \see QCPAxis::mousePressEvent +*/ +void QCPAxis::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) +{ + Q_UNUSED(event) + Q_UNUSED(startPos) + mDragging = false; + if (mParentPlot->noAntialiasingOnDrag()) + { + mParentPlot->setAntialiasedElements(mAADragBackup); + mParentPlot->setNotAntialiasedElements(mNotAADragBackup); + } +} + +/*! \internal + + This mouse event reimplementation provides the functionality to let the user zoom individual axes + exclusively, by performing the wheel event on top of the axis. + + For the axis to accept this event and perform the single axis zoom, the parent \ref QCPAxisRect + must be configured accordingly, i.e. it must allow range zooming in the orientation of this axis + (\ref QCPAxisRect::setRangeZoom) and this axis must be a zoomable axis (\ref + QCPAxisRect::setRangeZoomAxes) + + \seebaseclassmethod + + \note The zooming of possibly multiple axes at once by performing the wheel event anywhere in the + axis rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::wheelEvent. +*/ +void QCPAxis::wheelEvent(QWheelEvent *event) +{ + // Mouse range zooming interaction: + if (!mParentPlot->interactions().testFlag(QCP::iRangeZoom) || + !mAxisRect->rangeZoom().testFlag(orientation()) || + !mAxisRect->rangeZoomAxes(orientation()).contains(this)) + { + event->ignore(); + return; + } + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + const double delta = event->delta(); +#else + const double delta = event->angleDelta().y(); +#endif + +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + const QPointF pos = event->pos(); +#else + const QPointF pos = event->position(); +#endif + + const double wheelSteps = delta/120.0; // a single step delta is +/-120 usually + const double factor = qPow(mAxisRect->rangeZoomFactor(orientation()), wheelSteps); + scaleRange(factor, pixelToCoord(orientation() == Qt::Horizontal ? pos.x() : pos.y())); + mParentPlot->replot(); +} + +/*! \internal + + A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter + before drawing axis lines. + + This is the antialiasing state the painter passed to the \ref draw method is in by default. + + This function takes into account the local setting of the antialiasing flag as well as the + overrides set with \ref QCustomPlot::setAntialiasedElements and \ref + QCustomPlot::setNotAntialiasedElements. + + \seebaseclassmethod + + \see setAntialiased +*/ +void QCPAxis::applyDefaultAntialiasingHint(QCPPainter *painter) const +{ + applyAntialiasingHint(painter, mAntialiased, QCP::aeAxes); +} + +/*! \internal + + Draws the axis with the specified \a painter, using the internal QCPAxisPainterPrivate instance. + + \seebaseclassmethod +*/ +void QCPAxis::draw(QCPPainter *painter) +{ + QVector subTickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter + QVector tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter + QVector tickLabels; // the final vector passed to QCPAxisPainter + tickPositions.reserve(mTickVector.size()); + tickLabels.reserve(mTickVector.size()); + subTickPositions.reserve(mSubTickVector.size()); + + if (mTicks) + { + for (int i=0; itype = mAxisType; + mAxisPainter->basePen = getBasePen(); + mAxisPainter->labelFont = getLabelFont(); + mAxisPainter->labelColor = getLabelColor(); + mAxisPainter->label = mLabel; + mAxisPainter->substituteExponent = mNumberBeautifulPowers; + mAxisPainter->tickPen = getTickPen(); + mAxisPainter->subTickPen = getSubTickPen(); + mAxisPainter->tickLabelFont = getTickLabelFont(); + mAxisPainter->tickLabelColor = getTickLabelColor(); + mAxisPainter->axisRect = mAxisRect->rect(); + mAxisPainter->viewportRect = mParentPlot->viewport(); + mAxisPainter->abbreviateDecimalPowers = mScaleType == stLogarithmic; + mAxisPainter->reversedEndings = mRangeReversed; + mAxisPainter->tickPositions = tickPositions; + mAxisPainter->tickLabels = tickLabels; + mAxisPainter->subTickPositions = subTickPositions; + mAxisPainter->draw(painter); +} + +/*! \internal + + Prepares the internal tick vector, sub tick vector and tick label vector. This is done by calling + QCPAxisTicker::generate on the currently installed ticker. + + If a change in the label text/count is detected, the cached axis margin is invalidated to make + sure the next margin calculation recalculates the label sizes and returns an up-to-date value. +*/ +void QCPAxis::setupTickVectors() +{ + if (!mParentPlot) return; + if ((!mTicks && !mTickLabels && !mGrid->visible()) || mRange.size() <= 0) return; + + QVector oldLabels = mTickVectorLabels; + mTicker->generate(mRange, mParentPlot->locale(), mNumberFormatChar, mNumberPrecision, mTickVector, mSubTicks ? &mSubTickVector : nullptr, mTickLabels ? &mTickVectorLabels : nullptr); + mCachedMarginValid &= mTickVectorLabels == oldLabels; // if labels have changed, margin might have changed, too +} + +/*! \internal + + Returns the pen that is used to draw the axis base line. Depending on the selection state, this + is either mSelectedBasePen or mBasePen. +*/ +QPen QCPAxis::getBasePen() const +{ + return mSelectedParts.testFlag(spAxis) ? mSelectedBasePen : mBasePen; +} + +/*! \internal + + Returns the pen that is used to draw the (major) ticks. Depending on the selection state, this + is either mSelectedTickPen or mTickPen. +*/ +QPen QCPAxis::getTickPen() const +{ + return mSelectedParts.testFlag(spAxis) ? mSelectedTickPen : mTickPen; +} + +/*! \internal + + Returns the pen that is used to draw the subticks. Depending on the selection state, this + is either mSelectedSubTickPen or mSubTickPen. +*/ +QPen QCPAxis::getSubTickPen() const +{ + return mSelectedParts.testFlag(spAxis) ? mSelectedSubTickPen : mSubTickPen; +} + +/*! \internal + + Returns the font that is used to draw the tick labels. Depending on the selection state, this + is either mSelectedTickLabelFont or mTickLabelFont. +*/ +QFont QCPAxis::getTickLabelFont() const +{ + return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelFont : mTickLabelFont; +} + +/*! \internal + + Returns the font that is used to draw the axis label. Depending on the selection state, this + is either mSelectedLabelFont or mLabelFont. +*/ +QFont QCPAxis::getLabelFont() const +{ + return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelFont : mLabelFont; +} + +/*! \internal + + Returns the color that is used to draw the tick labels. Depending on the selection state, this + is either mSelectedTickLabelColor or mTickLabelColor. +*/ +QColor QCPAxis::getTickLabelColor() const +{ + return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelColor : mTickLabelColor; +} + +/*! \internal + + Returns the color that is used to draw the axis label. Depending on the selection state, this + is either mSelectedLabelColor or mLabelColor. +*/ +QColor QCPAxis::getLabelColor() const +{ + return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelColor : mLabelColor; +} + +/*! \internal + + Returns the appropriate outward margin for this axis. It is needed if \ref + QCPAxisRect::setAutoMargins is set to true on the parent axis rect. An axis with axis type \ref + atLeft will return an appropriate left margin, \ref atBottom will return an appropriate bottom + margin and so forth. For the calculation, this function goes through similar steps as \ref draw, + so changing one function likely requires the modification of the other one as well. + + The margin consists of the outward tick length, tick label padding, tick label size, label + padding, label size, and padding. + + The margin is cached internally, so repeated calls while leaving the axis range, fonts, etc. + unchanged are very fast. +*/ +int QCPAxis::calculateMargin() +{ + if (!mVisible) // if not visible, directly return 0, don't cache 0 because we can't react to setVisible in QCPAxis + return 0; + + if (mCachedMarginValid) + return mCachedMargin; + + // run through similar steps as QCPAxis::draw, and calculate margin needed to fit axis and its labels + int margin = 0; + + QVector tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter + QVector tickLabels; // the final vector passed to QCPAxisPainter + tickPositions.reserve(mTickVector.size()); + tickLabels.reserve(mTickVector.size()); + + if (mTicks) + { + for (int i=0; itype = mAxisType; + mAxisPainter->labelFont = getLabelFont(); + mAxisPainter->label = mLabel; + mAxisPainter->tickLabelFont = mTickLabelFont; + mAxisPainter->axisRect = mAxisRect->rect(); + mAxisPainter->viewportRect = mParentPlot->viewport(); + mAxisPainter->tickPositions = tickPositions; + mAxisPainter->tickLabels = tickLabels; + margin += mAxisPainter->size(); + margin += mPadding; + + mCachedMargin = margin; + mCachedMarginValid = true; + return margin; +} + +/* inherits documentation from base class */ +QCP::Interaction QCPAxis::selectionCategory() const +{ + return QCP::iSelectAxes; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAxisPainterPrivate +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPAxisPainterPrivate + + \internal + \brief (Private) + + This is a private class and not part of the public QCustomPlot interface. + + It is used by QCPAxis to do the low-level drawing of axis backbone, tick marks, tick labels and + axis label. It also buffers the labels to reduce replot times. The parameters are configured by + directly accessing the public member variables. +*/ + +/*! + Constructs a QCPAxisPainterPrivate instance. Make sure to not create a new instance on every + redraw, to utilize the caching mechanisms. +*/ +QCPAxisPainterPrivate::QCPAxisPainterPrivate(QCustomPlot *parentPlot) : + type(QCPAxis::atLeft), + basePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + lowerEnding(QCPLineEnding::esNone), + upperEnding(QCPLineEnding::esNone), + labelPadding(0), + tickLabelPadding(0), + tickLabelRotation(0), + tickLabelSide(QCPAxis::lsOutside), + substituteExponent(true), + numberMultiplyCross(false), + tickLengthIn(5), + tickLengthOut(0), + subTickLengthIn(2), + subTickLengthOut(0), + tickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + subTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + offset(0), + abbreviateDecimalPowers(false), + reversedEndings(false), + mParentPlot(parentPlot), + mLabelCache(16) // cache at most 16 (tick) labels +{ +} + +QCPAxisPainterPrivate::~QCPAxisPainterPrivate() +{ +} + +/*! \internal + + Draws the axis with the specified \a painter. + + The selection boxes (mAxisSelectionBox, mTickLabelsSelectionBox, mLabelSelectionBox) are set + here, too. +*/ +void QCPAxisPainterPrivate::draw(QCPPainter *painter) +{ + QByteArray newHash = generateLabelParameterHash(); + if (newHash != mLabelParameterHash) + { + mLabelCache.clear(); + mLabelParameterHash = newHash; + } + + QPoint origin; + switch (type) + { + case QCPAxis::atLeft: origin = axisRect.bottomLeft() +QPoint(-offset, 0); break; + case QCPAxis::atRight: origin = axisRect.bottomRight()+QPoint(+offset, 0); break; + case QCPAxis::atTop: origin = axisRect.topLeft() +QPoint(0, -offset); break; + case QCPAxis::atBottom: origin = axisRect.bottomLeft() +QPoint(0, +offset); break; + } + + double xCor = 0, yCor = 0; // paint system correction, for pixel exact matches (affects baselines and ticks of top/right axes) + switch (type) + { + case QCPAxis::atTop: yCor = -1; break; + case QCPAxis::atRight: xCor = 1; break; + default: break; + } + int margin = 0; + // draw baseline: + QLineF baseLine; + painter->setPen(basePen); + if (QCPAxis::orientation(type) == Qt::Horizontal) + baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(axisRect.width()+xCor, yCor)); + else + baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(xCor, -axisRect.height()+yCor)); + if (reversedEndings) + baseLine = QLineF(baseLine.p2(), baseLine.p1()); // won't make a difference for line itself, but for line endings later + painter->drawLine(baseLine); + + // draw ticks: + if (!tickPositions.isEmpty()) + { + painter->setPen(tickPen); + int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1; // direction of ticks ("inward" is right for left axis and left for right axis) + if (QCPAxis::orientation(type) == Qt::Horizontal) + { + foreach (double tickPos, tickPositions) + painter->drawLine(QLineF(tickPos+xCor, origin.y()-tickLengthOut*tickDir+yCor, tickPos+xCor, origin.y()+tickLengthIn*tickDir+yCor)); + } else + { + foreach (double tickPos, tickPositions) + painter->drawLine(QLineF(origin.x()-tickLengthOut*tickDir+xCor, tickPos+yCor, origin.x()+tickLengthIn*tickDir+xCor, tickPos+yCor)); + } + } + + // draw subticks: + if (!subTickPositions.isEmpty()) + { + painter->setPen(subTickPen); + // direction of ticks ("inward" is right for left axis and left for right axis) + int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1; + if (QCPAxis::orientation(type) == Qt::Horizontal) + { + foreach (double subTickPos, subTickPositions) + painter->drawLine(QLineF(subTickPos+xCor, origin.y()-subTickLengthOut*tickDir+yCor, subTickPos+xCor, origin.y()+subTickLengthIn*tickDir+yCor)); + } else + { + foreach (double subTickPos, subTickPositions) + painter->drawLine(QLineF(origin.x()-subTickLengthOut*tickDir+xCor, subTickPos+yCor, origin.x()+subTickLengthIn*tickDir+xCor, subTickPos+yCor)); + } + } + margin += qMax(0, qMax(tickLengthOut, subTickLengthOut)); + + // draw axis base endings: + bool antialiasingBackup = painter->antialiasing(); + painter->setAntialiasing(true); // always want endings to be antialiased, even if base and ticks themselves aren't + painter->setBrush(QBrush(basePen.color())); + QCPVector2D baseLineVector(baseLine.dx(), baseLine.dy()); + if (lowerEnding.style() != QCPLineEnding::esNone) + lowerEnding.draw(painter, QCPVector2D(baseLine.p1())-baseLineVector.normalized()*lowerEnding.realLength()*(lowerEnding.inverted()?-1:1), -baseLineVector); + if (upperEnding.style() != QCPLineEnding::esNone) + upperEnding.draw(painter, QCPVector2D(baseLine.p2())+baseLineVector.normalized()*upperEnding.realLength()*(upperEnding.inverted()?-1:1), baseLineVector); + painter->setAntialiasing(antialiasingBackup); + + // tick labels: + QRect oldClipRect; + if (tickLabelSide == QCPAxis::lsInside) // if using inside labels, clip them to the axis rect + { + oldClipRect = painter->clipRegion().boundingRect(); + painter->setClipRect(axisRect); + } + QSize tickLabelsSize(0, 0); // size of largest tick label, for offset calculation of axis label + if (!tickLabels.isEmpty()) + { + if (tickLabelSide == QCPAxis::lsOutside) + margin += tickLabelPadding; + painter->setFont(tickLabelFont); + painter->setPen(QPen(tickLabelColor)); + const int maxLabelIndex = qMin(tickPositions.size(), tickLabels.size()); + int distanceToAxis = margin; + if (tickLabelSide == QCPAxis::lsInside) + distanceToAxis = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding); + for (int i=0; isetClipRect(oldClipRect); + + // axis label: + QRect labelBounds; + if (!label.isEmpty()) + { + margin += labelPadding; + painter->setFont(labelFont); + painter->setPen(QPen(labelColor)); + labelBounds = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip, label); + if (type == QCPAxis::atLeft) + { + QTransform oldTransform = painter->transform(); + painter->translate((origin.x()-margin-labelBounds.height()), origin.y()); + painter->rotate(-90); + painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); + painter->setTransform(oldTransform); + } + else if (type == QCPAxis::atRight) + { + QTransform oldTransform = painter->transform(); + painter->translate((origin.x()+margin+labelBounds.height()), origin.y()-axisRect.height()); + painter->rotate(90); + painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); + painter->setTransform(oldTransform); + } + else if (type == QCPAxis::atTop) + painter->drawText(origin.x(), origin.y()-margin-labelBounds.height(), axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); + else if (type == QCPAxis::atBottom) + painter->drawText(origin.x(), origin.y()+margin, axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); + } + + // set selection boxes: + int selectionTolerance = 0; + if (mParentPlot) + selectionTolerance = mParentPlot->selectionTolerance(); + else + qDebug() << Q_FUNC_INFO << "mParentPlot is null"; + int selAxisOutSize = qMax(qMax(tickLengthOut, subTickLengthOut), selectionTolerance); + int selAxisInSize = selectionTolerance; + int selTickLabelSize; + int selTickLabelOffset; + if (tickLabelSide == QCPAxis::lsOutside) + { + selTickLabelSize = (QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width()); + selTickLabelOffset = qMax(tickLengthOut, subTickLengthOut)+tickLabelPadding; + } else + { + selTickLabelSize = -(QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width()); + selTickLabelOffset = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding); + } + int selLabelSize = labelBounds.height(); + int selLabelOffset = qMax(tickLengthOut, subTickLengthOut)+(!tickLabels.isEmpty() && tickLabelSide == QCPAxis::lsOutside ? tickLabelPadding+selTickLabelSize : 0)+labelPadding; + if (type == QCPAxis::atLeft) + { + mAxisSelectionBox.setCoords(origin.x()-selAxisOutSize, axisRect.top(), origin.x()+selAxisInSize, axisRect.bottom()); + mTickLabelsSelectionBox.setCoords(origin.x()-selTickLabelOffset-selTickLabelSize, axisRect.top(), origin.x()-selTickLabelOffset, axisRect.bottom()); + mLabelSelectionBox.setCoords(origin.x()-selLabelOffset-selLabelSize, axisRect.top(), origin.x()-selLabelOffset, axisRect.bottom()); + } else if (type == QCPAxis::atRight) + { + mAxisSelectionBox.setCoords(origin.x()-selAxisInSize, axisRect.top(), origin.x()+selAxisOutSize, axisRect.bottom()); + mTickLabelsSelectionBox.setCoords(origin.x()+selTickLabelOffset+selTickLabelSize, axisRect.top(), origin.x()+selTickLabelOffset, axisRect.bottom()); + mLabelSelectionBox.setCoords(origin.x()+selLabelOffset+selLabelSize, axisRect.top(), origin.x()+selLabelOffset, axisRect.bottom()); + } else if (type == QCPAxis::atTop) + { + mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisOutSize, axisRect.right(), origin.y()+selAxisInSize); + mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()-selTickLabelOffset-selTickLabelSize, axisRect.right(), origin.y()-selTickLabelOffset); + mLabelSelectionBox.setCoords(axisRect.left(), origin.y()-selLabelOffset-selLabelSize, axisRect.right(), origin.y()-selLabelOffset); + } else if (type == QCPAxis::atBottom) + { + mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisInSize, axisRect.right(), origin.y()+selAxisOutSize); + mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()+selTickLabelOffset+selTickLabelSize, axisRect.right(), origin.y()+selTickLabelOffset); + mLabelSelectionBox.setCoords(axisRect.left(), origin.y()+selLabelOffset+selLabelSize, axisRect.right(), origin.y()+selLabelOffset); + } + mAxisSelectionBox = mAxisSelectionBox.normalized(); + mTickLabelsSelectionBox = mTickLabelsSelectionBox.normalized(); + mLabelSelectionBox = mLabelSelectionBox.normalized(); + // draw hitboxes for debug purposes: + //painter->setBrush(Qt::NoBrush); + //painter->drawRects(QVector() << mAxisSelectionBox << mTickLabelsSelectionBox << mLabelSelectionBox); +} + +/*! \internal + + Returns the size ("margin" in QCPAxisRect context, so measured perpendicular to the axis backbone + direction) needed to fit the axis. +*/ +int QCPAxisPainterPrivate::size() +{ + int result = 0; + + QByteArray newHash = generateLabelParameterHash(); + if (newHash != mLabelParameterHash) + { + mLabelCache.clear(); + mLabelParameterHash = newHash; + } + + // get length of tick marks pointing outwards: + if (!tickPositions.isEmpty()) + result += qMax(0, qMax(tickLengthOut, subTickLengthOut)); + + // calculate size of tick labels: + if (tickLabelSide == QCPAxis::lsOutside) + { + QSize tickLabelsSize(0, 0); + if (!tickLabels.isEmpty()) + { + foreach (const QString &tickLabel, tickLabels) + getMaxTickLabelSize(tickLabelFont, tickLabel, &tickLabelsSize); + result += QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width(); + result += tickLabelPadding; + } + } + + // calculate size of axis label (only height needed, because left/right labels are rotated by 90 degrees): + if (!label.isEmpty()) + { + QFontMetrics fontMetrics(labelFont); + QRect bounds; + bounds = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter | Qt::AlignVCenter, label); + result += bounds.height() + labelPadding; + } + + return result; +} + +/*! \internal + + Clears the internal label cache. Upon the next \ref draw, all labels will be created new. This + method is called automatically in \ref draw, if any parameters have changed that invalidate the + cached labels, such as font, color, etc. +*/ +void QCPAxisPainterPrivate::clearCache() +{ + mLabelCache.clear(); +} + +/*! \internal + + Returns a hash that allows uniquely identifying whether the label parameters have changed such + that the cached labels must be refreshed (\ref clearCache). It is used in \ref draw. If the + return value of this method hasn't changed since the last redraw, the respective label parameters + haven't changed and cached labels may be used. +*/ +QByteArray QCPAxisPainterPrivate::generateLabelParameterHash() const +{ + QByteArray result; + result.append(QByteArray::number(mParentPlot->bufferDevicePixelRatio())); + result.append(QByteArray::number(tickLabelRotation)); + result.append(QByteArray::number(int(tickLabelSide))); + result.append(QByteArray::number(int(substituteExponent))); + result.append(QByteArray::number(int(numberMultiplyCross))); + result.append(tickLabelColor.name().toLatin1()+QByteArray::number(tickLabelColor.alpha(), 16)); + result.append(tickLabelFont.toString().toLatin1()); + return result; +} + +/*! \internal + + Draws a single tick label with the provided \a painter, utilizing the internal label cache to + significantly speed up drawing of labels that were drawn in previous calls. The tick label is + always bound to an axis, the distance to the axis is controllable via \a distanceToAxis in + pixels. The pixel position in the axis direction is passed in the \a position parameter. Hence + for the bottom axis, \a position would indicate the horizontal pixel position (not coordinate), + at which the label should be drawn. + + In order to later draw the axis label in a place that doesn't overlap with the tick labels, the + largest tick label size is needed. This is acquired by passing a \a tickLabelsSize to the \ref + drawTickLabel calls during the process of drawing all tick labels of one axis. In every call, \a + tickLabelsSize is expanded, if the drawn label exceeds the value \a tickLabelsSize currently + holds. + + The label is drawn with the font and pen that are currently set on the \a painter. To draw + superscripted powers, the font is temporarily made smaller by a fixed factor (see \ref + getTickLabelData). +*/ +void QCPAxisPainterPrivate::placeTickLabel(QCPPainter *painter, double position, int distanceToAxis, const QString &text, QSize *tickLabelsSize) +{ + // warning: if you change anything here, also adapt getMaxTickLabelSize() accordingly! + if (text.isEmpty()) return; + QSize finalSize; + QPointF labelAnchor; + switch (type) + { + case QCPAxis::atLeft: labelAnchor = QPointF(axisRect.left()-distanceToAxis-offset, position); break; + case QCPAxis::atRight: labelAnchor = QPointF(axisRect.right()+distanceToAxis+offset, position); break; + case QCPAxis::atTop: labelAnchor = QPointF(position, axisRect.top()-distanceToAxis-offset); break; + case QCPAxis::atBottom: labelAnchor = QPointF(position, axisRect.bottom()+distanceToAxis+offset); break; + } + if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && !painter->modes().testFlag(QCPPainter::pmNoCaching)) // label caching enabled + { + CachedLabel *cachedLabel = mLabelCache.take(text); // attempt to get label from cache + if (!cachedLabel) // no cached label existed, create it + { + cachedLabel = new CachedLabel; + TickLabelData labelData = getTickLabelData(painter->font(), text); + cachedLabel->offset = getTickLabelDrawOffset(labelData)+labelData.rotatedTotalBounds.topLeft(); + if (!qFuzzyCompare(1.0, mParentPlot->bufferDevicePixelRatio())) + { + cachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size()*mParentPlot->bufferDevicePixelRatio()); +#ifdef QCP_DEVICEPIXELRATIO_SUPPORTED +# ifdef QCP_DEVICEPIXELRATIO_FLOAT + cachedLabel->pixmap.setDevicePixelRatio(mParentPlot->devicePixelRatioF()); +# else + cachedLabel->pixmap.setDevicePixelRatio(mParentPlot->devicePixelRatio()); +# endif +#endif + } else + cachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size()); + cachedLabel->pixmap.fill(Qt::transparent); + QCPPainter cachePainter(&cachedLabel->pixmap); + cachePainter.setPen(painter->pen()); + drawTickLabel(&cachePainter, -labelData.rotatedTotalBounds.topLeft().x(), -labelData.rotatedTotalBounds.topLeft().y(), labelData); + } + // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels): + bool labelClippedByBorder = false; + if (tickLabelSide == QCPAxis::lsOutside) + { + if (QCPAxis::orientation(type) == Qt::Horizontal) + labelClippedByBorder = labelAnchor.x()+cachedLabel->offset.x()+cachedLabel->pixmap.width()/mParentPlot->bufferDevicePixelRatio() > viewportRect.right() || labelAnchor.x()+cachedLabel->offset.x() < viewportRect.left(); + else + labelClippedByBorder = labelAnchor.y()+cachedLabel->offset.y()+cachedLabel->pixmap.height()/mParentPlot->bufferDevicePixelRatio() > viewportRect.bottom() || labelAnchor.y()+cachedLabel->offset.y() < viewportRect.top(); + } + if (!labelClippedByBorder) + { + painter->drawPixmap(labelAnchor+cachedLabel->offset, cachedLabel->pixmap); + finalSize = cachedLabel->pixmap.size()/mParentPlot->bufferDevicePixelRatio(); + } + mLabelCache.insert(text, cachedLabel); // return label to cache or insert for the first time if newly created + } else // label caching disabled, draw text directly on surface: + { + TickLabelData labelData = getTickLabelData(painter->font(), text); + QPointF finalPosition = labelAnchor + getTickLabelDrawOffset(labelData); + // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels): + bool labelClippedByBorder = false; + if (tickLabelSide == QCPAxis::lsOutside) + { + if (QCPAxis::orientation(type) == Qt::Horizontal) + labelClippedByBorder = finalPosition.x()+(labelData.rotatedTotalBounds.width()+labelData.rotatedTotalBounds.left()) > viewportRect.right() || finalPosition.x()+labelData.rotatedTotalBounds.left() < viewportRect.left(); + else + labelClippedByBorder = finalPosition.y()+(labelData.rotatedTotalBounds.height()+labelData.rotatedTotalBounds.top()) > viewportRect.bottom() || finalPosition.y()+labelData.rotatedTotalBounds.top() < viewportRect.top(); + } + if (!labelClippedByBorder) + { + drawTickLabel(painter, finalPosition.x(), finalPosition.y(), labelData); + finalSize = labelData.rotatedTotalBounds.size(); + } + } + + // expand passed tickLabelsSize if current tick label is larger: + if (finalSize.width() > tickLabelsSize->width()) + tickLabelsSize->setWidth(finalSize.width()); + if (finalSize.height() > tickLabelsSize->height()) + tickLabelsSize->setHeight(finalSize.height()); +} + +/*! \internal + + This is a \ref placeTickLabel helper function. + + Draws the tick label specified in \a labelData with \a painter at the pixel positions \a x and \a + y. This function is used by \ref placeTickLabel to create new tick labels for the cache, or to + directly draw the labels on the QCustomPlot surface when label caching is disabled, i.e. when + QCP::phCacheLabels plotting hint is not set. +*/ +void QCPAxisPainterPrivate::drawTickLabel(QCPPainter *painter, double x, double y, const TickLabelData &labelData) const +{ + // backup painter settings that we're about to change: + QTransform oldTransform = painter->transform(); + QFont oldFont = painter->font(); + + // transform painter to position/rotation: + painter->translate(x, y); + if (!qFuzzyIsNull(tickLabelRotation)) + painter->rotate(tickLabelRotation); + + // draw text: + if (!labelData.expPart.isEmpty()) // indicator that beautiful powers must be used + { + painter->setFont(labelData.baseFont); + painter->drawText(0, 0, 0, 0, Qt::TextDontClip, labelData.basePart); + if (!labelData.suffixPart.isEmpty()) + painter->drawText(labelData.baseBounds.width()+1+labelData.expBounds.width(), 0, 0, 0, Qt::TextDontClip, labelData.suffixPart); + painter->setFont(labelData.expFont); + painter->drawText(labelData.baseBounds.width()+1, 0, labelData.expBounds.width(), labelData.expBounds.height(), Qt::TextDontClip, labelData.expPart); + } else + { + painter->setFont(labelData.baseFont); + painter->drawText(0, 0, labelData.totalBounds.width(), labelData.totalBounds.height(), Qt::TextDontClip | Qt::AlignHCenter, labelData.basePart); + } + + // reset painter settings to what it was before: + painter->setTransform(oldTransform); + painter->setFont(oldFont); +} + +/*! \internal + + This is a \ref placeTickLabel helper function. + + Transforms the passed \a text and \a font to a tickLabelData structure that can then be further + processed by \ref getTickLabelDrawOffset and \ref drawTickLabel. It splits the text into base and + exponent if necessary (member substituteExponent) and calculates appropriate bounding boxes. +*/ +QCPAxisPainterPrivate::TickLabelData QCPAxisPainterPrivate::getTickLabelData(const QFont &font, const QString &text) const +{ + TickLabelData result; + + // determine whether beautiful decimal powers should be used + bool useBeautifulPowers = false; + int ePos = -1; // first index of exponent part, text before that will be basePart, text until eLast will be expPart + int eLast = -1; // last index of exponent part, rest of text after this will be suffixPart + if (substituteExponent) + { + ePos = text.indexOf(QString(mParentPlot->locale().exponential())); + if (ePos > 0 && text.at(ePos-1).isDigit()) + { + eLast = ePos; + while (eLast+1 < text.size() && (text.at(eLast+1) == QLatin1Char('+') || text.at(eLast+1) == QLatin1Char('-') || text.at(eLast+1).isDigit())) + ++eLast; + if (eLast > ePos) // only if also to right of 'e' is a digit/+/- interpret it as beautifiable power + useBeautifulPowers = true; + } + } + + // calculate text bounding rects and do string preparation for beautiful decimal powers: + result.baseFont = font; + if (result.baseFont.pointSizeF() > 0) // might return -1 if specified with setPixelSize, in that case we can't do correction in next line + result.baseFont.setPointSizeF(result.baseFont.pointSizeF()+0.05); // QFontMetrics.boundingRect has a bug for exact point sizes that make the results oscillate due to internal rounding + if (useBeautifulPowers) + { + // split text into parts of number/symbol that will be drawn normally and part that will be drawn as exponent: + result.basePart = text.left(ePos); + result.suffixPart = text.mid(eLast+1); // also drawn normally but after exponent + // in log scaling, we want to turn "1*10^n" into "10^n", else add multiplication sign and decimal base: + if (abbreviateDecimalPowers && result.basePart == QLatin1String("1")) + result.basePart = QLatin1String("10"); + else + result.basePart += (numberMultiplyCross ? QString(QChar(215)) : QString(QChar(183))) + QLatin1String("10"); + result.expPart = text.mid(ePos+1, eLast-ePos); + // clip "+" and leading zeros off expPart: + while (result.expPart.length() > 2 && result.expPart.at(1) == QLatin1Char('0')) // length > 2 so we leave one zero when numberFormatChar is 'e' + result.expPart.remove(1, 1); + if (!result.expPart.isEmpty() && result.expPart.at(0) == QLatin1Char('+')) + result.expPart.remove(0, 1); + // prepare smaller font for exponent: + result.expFont = font; + if (result.expFont.pointSize() > 0) + result.expFont.setPointSize(int(result.expFont.pointSize()*0.75)); + else + result.expFont.setPixelSize(int(result.expFont.pixelSize()*0.75)); + // calculate bounding rects of base part(s), exponent part and total one: + result.baseBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.basePart); + result.expBounds = QFontMetrics(result.expFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.expPart); + if (!result.suffixPart.isEmpty()) + result.suffixBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.suffixPart); + result.totalBounds = result.baseBounds.adjusted(0, 0, result.expBounds.width()+result.suffixBounds.width()+2, 0); // +2 consists of the 1 pixel spacing between base and exponent (see drawTickLabel) and an extra pixel to include AA + } else // useBeautifulPowers == false + { + result.basePart = text; + result.totalBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter, result.basePart); + } + result.totalBounds.moveTopLeft(QPoint(0, 0)); // want bounding box aligned top left at origin, independent of how it was created, to make further processing simpler + + // calculate possibly different bounding rect after rotation: + result.rotatedTotalBounds = result.totalBounds; + if (!qFuzzyIsNull(tickLabelRotation)) + { + QTransform transform; + transform.rotate(tickLabelRotation); + result.rotatedTotalBounds = transform.mapRect(result.rotatedTotalBounds); + } + + return result; +} + +/*! \internal + + This is a \ref placeTickLabel helper function. + + Calculates the offset at which the top left corner of the specified tick label shall be drawn. + The offset is relative to a point right next to the tick the label belongs to. + + This function is thus responsible for e.g. centering tick labels under ticks and positioning them + appropriately when they are rotated. +*/ +QPointF QCPAxisPainterPrivate::getTickLabelDrawOffset(const TickLabelData &labelData) const +{ + /* + calculate label offset from base point at tick (non-trivial, for best visual appearance): short + explanation for bottom axis: The anchor, i.e. the point in the label that is placed + horizontally under the corresponding tick is always on the label side that is closer to the + axis (e.g. the left side of the text when we're rotating clockwise). On that side, the height + is halved and the resulting point is defined the anchor. This way, a 90 degree rotated text + will be centered under the tick (i.e. displaced horizontally by half its height). At the same + time, a 45 degree rotated text will "point toward" its tick, as is typical for rotated tick + labels. + */ + bool doRotation = !qFuzzyIsNull(tickLabelRotation); + bool flip = qFuzzyCompare(qAbs(tickLabelRotation), 90.0); // perfect +/-90 degree flip. Indicates vertical label centering on vertical axes. + double radians = tickLabelRotation/180.0*M_PI; + double x = 0; + double y = 0; + if ((type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsInside)) // Anchor at right side of tick label + { + if (doRotation) + { + if (tickLabelRotation > 0) + { + x = -qCos(radians)*labelData.totalBounds.width(); + y = flip ? -labelData.totalBounds.width()/2.0 : -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height()/2.0; + } else + { + x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height(); + y = flip ? +labelData.totalBounds.width()/2.0 : +qSin(-radians)*labelData.totalBounds.width()-qCos(-radians)*labelData.totalBounds.height()/2.0; + } + } else + { + x = -labelData.totalBounds.width(); + y = -labelData.totalBounds.height()/2.0; + } + } else if ((type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsInside)) // Anchor at left side of tick label + { + if (doRotation) + { + if (tickLabelRotation > 0) + { + x = +qSin(radians)*labelData.totalBounds.height(); + y = flip ? -labelData.totalBounds.width()/2.0 : -qCos(radians)*labelData.totalBounds.height()/2.0; + } else + { + x = 0; + y = flip ? +labelData.totalBounds.width()/2.0 : -qCos(-radians)*labelData.totalBounds.height()/2.0; + } + } else + { + x = 0; + y = -labelData.totalBounds.height()/2.0; + } + } else if ((type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsInside)) // Anchor at bottom side of tick label + { + if (doRotation) + { + if (tickLabelRotation > 0) + { + x = -qCos(radians)*labelData.totalBounds.width()+qSin(radians)*labelData.totalBounds.height()/2.0; + y = -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height(); + } else + { + x = -qSin(-radians)*labelData.totalBounds.height()/2.0; + y = -qCos(-radians)*labelData.totalBounds.height(); + } + } else + { + x = -labelData.totalBounds.width()/2.0; + y = -labelData.totalBounds.height(); + } + } else if ((type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsInside)) // Anchor at top side of tick label + { + if (doRotation) + { + if (tickLabelRotation > 0) + { + x = +qSin(radians)*labelData.totalBounds.height()/2.0; + y = 0; + } else + { + x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height()/2.0; + y = +qSin(-radians)*labelData.totalBounds.width(); + } + } else + { + x = -labelData.totalBounds.width()/2.0; + y = 0; + } + } + + return {x, y}; +} + +/*! \internal + + Simulates the steps done by \ref placeTickLabel by calculating bounding boxes of the text label + to be drawn, depending on number format etc. Since only the largest tick label is wanted for the + margin calculation, the passed \a tickLabelsSize is only expanded, if it's currently set to a + smaller width/height. +*/ +void QCPAxisPainterPrivate::getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const +{ + // note: this function must return the same tick label sizes as the placeTickLabel function. + QSize finalSize; + if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && mLabelCache.contains(text)) // label caching enabled and have cached label + { + const CachedLabel *cachedLabel = mLabelCache.object(text); + finalSize = cachedLabel->pixmap.size()/mParentPlot->bufferDevicePixelRatio(); + } else // label caching disabled or no label with this text cached: + { + TickLabelData labelData = getTickLabelData(font, text); + finalSize = labelData.rotatedTotalBounds.size(); + } + + // expand passed tickLabelsSize if current tick label is larger: + if (finalSize.width() > tickLabelsSize->width()) + tickLabelsSize->setWidth(finalSize.width()); + if (finalSize.height() > tickLabelsSize->height()) + tickLabelsSize->setHeight(finalSize.height()); +} +/* end of 'src/axis/axis.cpp' */ + + +/* including file 'src/scatterstyle.cpp' */ +/* modified 2022-11-06T12:45:56, size 17466 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPScatterStyle +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPScatterStyle + \brief Represents the visual appearance of scatter points + + This class holds information about shape, color and size of scatter points. In plottables like + QCPGraph it is used to store how scatter points shall be drawn. For example, \ref + QCPGraph::setScatterStyle takes a QCPScatterStyle instance. + + A scatter style consists of a shape (\ref setShape), a line color (\ref setPen) and possibly a + fill (\ref setBrush), if the shape provides a fillable area. Further, the size of the shape can + be controlled with \ref setSize. + + \section QCPScatterStyle-defining Specifying a scatter style + + You can set all these configurations either by calling the respective functions on an instance: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpscatterstyle-creation-1 + + Or you can use one of the various constructors that take different parameter combinations, making + it easy to specify a scatter style in a single call, like so: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpscatterstyle-creation-2 + + \section QCPScatterStyle-undefinedpen Leaving the color/pen up to the plottable + + There are two constructors which leave the pen undefined: \ref QCPScatterStyle() and \ref + QCPScatterStyle(ScatterShape shape, double size). If those constructors are used, a call to \ref + isPenDefined will return false. It leads to scatter points that inherit the pen from the + plottable that uses the scatter style. Thus, if such a scatter style is passed to QCPGraph, the line + color of the graph (\ref QCPGraph::setPen) will be used by the scatter points. This makes + it very convenient to set up typical scatter settings: + + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpscatterstyle-shortcreation + + Notice that it wasn't even necessary to explicitly call a QCPScatterStyle constructor. This works + because QCPScatterStyle provides a constructor that can transform a \ref ScatterShape directly + into a QCPScatterStyle instance (that's the \ref QCPScatterStyle(ScatterShape shape, double size) + constructor with a default for \a size). In those cases, C++ allows directly supplying a \ref + ScatterShape, where actually a QCPScatterStyle is expected. + + \section QCPScatterStyle-custompath-and-pixmap Custom shapes and pixmaps + + QCPScatterStyle supports drawing custom shapes and arbitrary pixmaps as scatter points. + + For custom shapes, you can provide a QPainterPath with the desired shape to the \ref + setCustomPath function or call the constructor that takes a painter path. The scatter shape will + automatically be set to \ref ssCustom. + + For pixmaps, you call \ref setPixmap with the desired QPixmap. Alternatively you can use the + constructor that takes a QPixmap. The scatter shape will automatically be set to \ref ssPixmap. + Note that \ref setSize does not influence the appearance of the pixmap. +*/ + +/* start documentation of inline functions */ + +/*! \fn bool QCPScatterStyle::isNone() const + + Returns whether the scatter shape is \ref ssNone. + + \see setShape +*/ + +/*! \fn bool QCPScatterStyle::isPenDefined() const + + Returns whether a pen has been defined for this scatter style. + + The pen is undefined if a constructor is called that does not carry \a pen as parameter. Those + are \ref QCPScatterStyle() and \ref QCPScatterStyle(ScatterShape shape, double size). If the pen + is undefined, the pen of the respective plottable will be used for drawing scatters. + + If a pen was defined for this scatter style instance, and you now wish to undefine the pen, call + \ref undefinePen. + + \see setPen +*/ + +/* end documentation of inline functions */ + +/*! + Creates a new QCPScatterStyle instance with size set to 6. No shape, pen or brush is defined. + + Since the pen is undefined (\ref isPenDefined returns false), the scatter color will be inherited + from the plottable that uses this scatter style. +*/ +QCPScatterStyle::QCPScatterStyle() : + mSize(6), + mShape(ssNone), + mPen(Qt::NoPen), + mBrush(Qt::NoBrush), + mPenDefined(false) +{ +} + +/*! + Creates a new QCPScatterStyle instance with shape set to \a shape and size to \a size. No pen or + brush is defined. + + Since the pen is undefined (\ref isPenDefined returns false), the scatter color will be inherited + from the plottable that uses this scatter style. +*/ +QCPScatterStyle::QCPScatterStyle(ScatterShape shape, double size) : + mSize(size), + mShape(shape), + mPen(Qt::NoPen), + mBrush(Qt::NoBrush), + mPenDefined(false) +{ +} + +/*! + Creates a new QCPScatterStyle instance with shape set to \a shape, the pen color set to \a color, + and size to \a size. No brush is defined, i.e. the scatter point will not be filled. +*/ +QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, double size) : + mSize(size), + mShape(shape), + mPen(QPen(color)), + mBrush(Qt::NoBrush), + mPenDefined(true) +{ +} + +/*! + Creates a new QCPScatterStyle instance with shape set to \a shape, the pen color set to \a color, + the brush color to \a fill (with a solid pattern), and size to \a size. +*/ +QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size) : + mSize(size), + mShape(shape), + mPen(QPen(color)), + mBrush(QBrush(fill)), + mPenDefined(true) +{ +} + +/*! + Creates a new QCPScatterStyle instance with shape set to \a shape, the pen set to \a pen, the + brush to \a brush, and size to \a size. + + \warning In some cases it might be tempting to directly use a pen style like Qt::NoPen as \a pen + and a color like Qt::blue as \a brush. Notice however, that the corresponding call\n + QCPScatterStyle(QCPScatterShape::ssCircle, Qt::NoPen, Qt::blue, 5)\n + doesn't necessarily lead C++ to use this constructor in some cases, but might mistake + Qt::NoPen for a QColor and use the + \ref QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size) + constructor instead (which will lead to an unexpected look of the scatter points). To prevent + this, be more explicit with the parameter types. For example, use QBrush(Qt::blue) + instead of just Qt::blue, to clearly point out to the compiler that this constructor is + wanted. +*/ +QCPScatterStyle::QCPScatterStyle(ScatterShape shape, const QPen &pen, const QBrush &brush, double size) : + mSize(size), + mShape(shape), + mPen(pen), + mBrush(brush), + mPenDefined(pen.style() != Qt::NoPen) +{ +} + +/*! + Creates a new QCPScatterStyle instance which will show the specified \a pixmap. The scatter shape + is set to \ref ssPixmap. +*/ +QCPScatterStyle::QCPScatterStyle(const QPixmap &pixmap) : + mSize(5), + mShape(ssPixmap), + mPen(Qt::NoPen), + mBrush(Qt::NoBrush), + mPixmap(pixmap), + mPenDefined(false) +{ +} + +/*! + Creates a new QCPScatterStyle instance with a custom shape that is defined via \a customPath. The + scatter shape is set to \ref ssCustom. + + The custom shape line will be drawn with \a pen and filled with \a brush. The size has a slightly + different meaning than for built-in scatter points: The custom path will be drawn scaled by a + factor of \a size/6.0. Since the default \a size is 6, the custom path will appear in its + original size by default. To for example double the size of the path, set \a size to 12. +*/ +QCPScatterStyle::QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, const QBrush &brush, double size) : + mSize(size), + mShape(ssCustom), + mPen(pen), + mBrush(brush), + mCustomPath(customPath), + mPenDefined(pen.style() != Qt::NoPen) +{ +} + +/*! + Copies the specified \a properties from the \a other scatter style to this scatter style. +*/ +void QCPScatterStyle::setFromOther(const QCPScatterStyle &other, ScatterProperties properties) +{ + if (properties.testFlag(spPen)) + { + setPen(other.pen()); + if (!other.isPenDefined()) + undefinePen(); + } + if (properties.testFlag(spBrush)) + setBrush(other.brush()); + if (properties.testFlag(spSize)) + setSize(other.size()); + if (properties.testFlag(spShape)) + { + setShape(other.shape()); + if (other.shape() == ssPixmap) + setPixmap(other.pixmap()); + else if (other.shape() == ssCustom) + setCustomPath(other.customPath()); + } +} + +/*! + Sets the size (pixel diameter) of the drawn scatter points to \a size. + + \see setShape +*/ +void QCPScatterStyle::setSize(double size) +{ + mSize = size; +} + +/*! + Sets the shape to \a shape. + + Note that the calls \ref setPixmap and \ref setCustomPath automatically set the shape to \ref + ssPixmap and \ref ssCustom, respectively. + + \see setSize +*/ +void QCPScatterStyle::setShape(QCPScatterStyle::ScatterShape shape) +{ + mShape = shape; +} + +/*! + Sets the pen that will be used to draw scatter points to \a pen. + + If the pen was previously undefined (see \ref isPenDefined), the pen is considered defined after + a call to this function, even if \a pen is Qt::NoPen. If you have defined a pen + previously by calling this function and now wish to undefine the pen, call \ref undefinePen. + + \see setBrush +*/ +void QCPScatterStyle::setPen(const QPen &pen) +{ + mPenDefined = true; + mPen = pen; +} + +/*! + Sets the brush that will be used to fill scatter points to \a brush. Note that not all scatter + shapes have fillable areas. For example, \ref ssPlus does not while \ref ssCircle does. + + \see setPen +*/ +void QCPScatterStyle::setBrush(const QBrush &brush) +{ + mBrush = brush; +} + +/*! + Sets the pixmap that will be drawn as scatter point to \a pixmap. + + Note that \ref setSize does not influence the appearance of the pixmap. + + The scatter shape is automatically set to \ref ssPixmap. +*/ +void QCPScatterStyle::setPixmap(const QPixmap &pixmap) +{ + setShape(ssPixmap); + mPixmap = pixmap; +} + +/*! + Sets the custom shape that will be drawn as scatter point to \a customPath. + + The scatter shape is automatically set to \ref ssCustom. +*/ +void QCPScatterStyle::setCustomPath(const QPainterPath &customPath) +{ + setShape(ssCustom); + mCustomPath = customPath; +} + +/*! + Sets this scatter style to have an undefined pen (see \ref isPenDefined for what an undefined pen + implies). + + A call to \ref setPen will define a pen. +*/ +void QCPScatterStyle::undefinePen() +{ + mPenDefined = false; +} + +/*! + Applies the pen and the brush of this scatter style to \a painter. If this scatter style has an + undefined pen (\ref isPenDefined), sets the pen of \a painter to \a defaultPen instead. + + This function is used by plottables (or any class that wants to draw scatters) just before a + number of scatters with this style shall be drawn with the \a painter. + + \see drawShape +*/ +void QCPScatterStyle::applyTo(QCPPainter *painter, const QPen &defaultPen) const +{ + painter->setPen(mPenDefined ? mPen : defaultPen); + painter->setBrush(mBrush); +} + +/*! + Draws the scatter shape with \a painter at position \a pos. + + This function does not modify the pen or the brush on the painter, as \ref applyTo is meant to be + called before scatter points are drawn with \ref drawShape. + + \see applyTo +*/ +void QCPScatterStyle::drawShape(QCPPainter *painter, const QPointF &pos) const +{ + drawShape(painter, pos.x(), pos.y()); +} + +/*! \overload + Draws the scatter shape with \a painter at position \a x and \a y. +*/ +void QCPScatterStyle::drawShape(QCPPainter *painter, double x, double y) const +{ + double w = mSize/2.0; + switch (mShape) + { + case ssNone: break; + case ssDot: + { + painter->drawLine(QPointF(x, y), QPointF(x+0.0001, y)); + break; + } + case ssCross: + { + painter->drawLine(QLineF(x-w, y-w, x+w, y+w)); + painter->drawLine(QLineF(x-w, y+w, x+w, y-w)); + break; + } + case ssPlus: + { + painter->drawLine(QLineF(x-w, y, x+w, y)); + painter->drawLine(QLineF( x, y+w, x, y-w)); + break; + } + case ssCircle: + { + painter->drawEllipse(QPointF(x , y), w, w); + break; + } + case ssDisc: + { + QBrush b = painter->brush(); + painter->setBrush(painter->pen().color()); + painter->drawEllipse(QPointF(x , y), w, w); + painter->setBrush(b); + break; + } + case ssSquare: + { + painter->drawRect(QRectF(x-w, y-w, mSize, mSize)); + break; + } + case ssDiamond: + { + QPointF lineArray[4] = {QPointF(x-w, y), + QPointF( x, y-w), + QPointF(x+w, y), + QPointF( x, y+w)}; + painter->drawPolygon(lineArray, 4); + break; + } + case ssStar: + { + painter->drawLine(QLineF(x-w, y, x+w, y)); + painter->drawLine(QLineF( x, y+w, x, y-w)); + painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.707, y+w*0.707)); + painter->drawLine(QLineF(x-w*0.707, y+w*0.707, x+w*0.707, y-w*0.707)); + break; + } + case ssTriangle: + { + QPointF lineArray[3] = {QPointF(x-w, y+0.755*w), + QPointF(x+w, y+0.755*w), + QPointF( x, y-0.977*w)}; + painter->drawPolygon(lineArray, 3); + break; + } + case ssTriangleInverted: + { + QPointF lineArray[3] = {QPointF(x-w, y-0.755*w), + QPointF(x+w, y-0.755*w), + QPointF( x, y+0.977*w)}; + painter->drawPolygon(lineArray, 3); + break; + } + case ssCrossSquare: + { + painter->drawRect(QRectF(x-w, y-w, mSize, mSize)); + painter->drawLine(QLineF(x-w, y-w, x+w*0.95, y+w*0.95)); + painter->drawLine(QLineF(x-w, y+w*0.95, x+w*0.95, y-w)); + break; + } + case ssPlusSquare: + { + painter->drawRect(QRectF(x-w, y-w, mSize, mSize)); + painter->drawLine(QLineF(x-w, y, x+w*0.95, y)); + painter->drawLine(QLineF( x, y+w, x, y-w)); + break; + } + case ssCrossCircle: + { + painter->drawEllipse(QPointF(x, y), w, w); + painter->drawLine(QLineF(x-w*0.707, y-w*0.707, x+w*0.670, y+w*0.670)); + painter->drawLine(QLineF(x-w*0.707, y+w*0.670, x+w*0.670, y-w*0.707)); + break; + } + case ssPlusCircle: + { + painter->drawEllipse(QPointF(x, y), w, w); + painter->drawLine(QLineF(x-w, y, x+w, y)); + painter->drawLine(QLineF( x, y+w, x, y-w)); + break; + } + case ssPeace: + { + painter->drawEllipse(QPointF(x, y), w, w); + painter->drawLine(QLineF(x, y-w, x, y+w)); + painter->drawLine(QLineF(x, y, x-w*0.707, y+w*0.707)); + painter->drawLine(QLineF(x, y, x+w*0.707, y+w*0.707)); + break; + } + case ssPixmap: + { + const double widthHalf = mPixmap.width()*0.5; + const double heightHalf = mPixmap.height()*0.5; +#if QT_VERSION < QT_VERSION_CHECK(4, 8, 0) + const QRectF clipRect = painter->clipRegion().boundingRect().adjusted(-widthHalf, -heightHalf, widthHalf, heightHalf); +#else + const QRectF clipRect = painter->clipBoundingRect().adjusted(-widthHalf, -heightHalf, widthHalf, heightHalf); +#endif + if (clipRect.contains(x, y)) + painter->drawPixmap(qRound(x-widthHalf), qRound(y-heightHalf), mPixmap); + break; + } + case ssCustom: + { + QTransform oldTransform = painter->transform(); + painter->translate(x, y); + painter->scale(mSize/6.0, mSize/6.0); + painter->drawPath(mCustomPath); + painter->setTransform(oldTransform); + break; + } + } +} +/* end of 'src/scatterstyle.cpp' */ + + +/* including file 'src/plottable.cpp' */ +/* modified 2022-11-06T12:45:56, size 38818 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPSelectionDecorator +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPSelectionDecorator + \brief Controls how a plottable's data selection is drawn + + Each \ref QCPAbstractPlottable instance has one \ref QCPSelectionDecorator (accessible via \ref + QCPAbstractPlottable::selectionDecorator) and uses it when drawing selected segments of its data. + + The selection decorator controls both pen (\ref setPen) and brush (\ref setBrush), as well as the + scatter style (\ref setScatterStyle) if the plottable draws scatters. Since a \ref + QCPScatterStyle is itself composed of different properties such as color shape and size, the + decorator allows specifying exactly which of those properties shall be used for the selected data + point, via \ref setUsedScatterProperties. + + A \ref QCPSelectionDecorator subclass instance can be passed to a plottable via \ref + QCPAbstractPlottable::setSelectionDecorator, allowing greater customizability of the appearance + of selected segments. + + Use \ref copyFrom to easily transfer the settings of one decorator to another one. This is + especially useful since plottables take ownership of the passed selection decorator, and thus the + same decorator instance can not be passed to multiple plottables. + + Selection decorators can also themselves perform drawing operations by reimplementing \ref + drawDecoration, which is called by the plottable's draw method. The base class \ref + QCPSelectionDecorator does not make use of this however. For example, \ref + QCPSelectionDecoratorBracket draws brackets around selected data segments. +*/ + +/*! + Creates a new QCPSelectionDecorator instance with default values +*/ +QCPSelectionDecorator::QCPSelectionDecorator() : + mPen(QColor(80, 80, 255), 2.5), + mBrush(Qt::NoBrush), + mUsedScatterProperties(QCPScatterStyle::spNone), + mPlottable(nullptr) +{ +} + +QCPSelectionDecorator::~QCPSelectionDecorator() +{ +} + +/*! + Sets the pen that will be used by the parent plottable to draw selected data segments. +*/ +void QCPSelectionDecorator::setPen(const QPen &pen) +{ + mPen = pen; +} + +/*! + Sets the brush that will be used by the parent plottable to draw selected data segments. +*/ +void QCPSelectionDecorator::setBrush(const QBrush &brush) +{ + mBrush = brush; +} + +/*! + Sets the scatter style that will be used by the parent plottable to draw scatters in selected + data segments. + + \a usedProperties specifies which parts of the passed \a scatterStyle will be used by the + plottable. The used properties can also be changed via \ref setUsedScatterProperties. +*/ +void QCPSelectionDecorator::setScatterStyle(const QCPScatterStyle &scatterStyle, QCPScatterStyle::ScatterProperties usedProperties) +{ + mScatterStyle = scatterStyle; + setUsedScatterProperties(usedProperties); +} + +/*! + Use this method to define which properties of the scatter style (set via \ref setScatterStyle) + will be used for selected data segments. All properties of the scatter style that are not + specified in \a properties will remain as specified in the plottable's original scatter style. + + \see QCPScatterStyle::ScatterProperty +*/ +void QCPSelectionDecorator::setUsedScatterProperties(const QCPScatterStyle::ScatterProperties &properties) +{ + mUsedScatterProperties = properties; +} + +/*! + Sets the pen of \a painter to the pen of this selection decorator. + + \see applyBrush, getFinalScatterStyle +*/ +void QCPSelectionDecorator::applyPen(QCPPainter *painter) const +{ + painter->setPen(mPen); +} + +/*! + Sets the brush of \a painter to the brush of this selection decorator. + + \see applyPen, getFinalScatterStyle +*/ +void QCPSelectionDecorator::applyBrush(QCPPainter *painter) const +{ + painter->setBrush(mBrush); +} + +/*! + Returns the scatter style that the parent plottable shall use for selected scatter points. The + plottable's original (unselected) scatter style must be passed as \a unselectedStyle. Depending + on the setting of \ref setUsedScatterProperties, the returned scatter style is a mixture of this + selecion decorator's scatter style (\ref setScatterStyle), and \a unselectedStyle. + + \see applyPen, applyBrush, setScatterStyle +*/ +QCPScatterStyle QCPSelectionDecorator::getFinalScatterStyle(const QCPScatterStyle &unselectedStyle) const +{ + QCPScatterStyle result(unselectedStyle); + result.setFromOther(mScatterStyle, mUsedScatterProperties); + + // if style shall inherit pen from plottable (has no own pen defined), give it the selected + // plottable pen explicitly, so it doesn't use the unselected plottable pen when used in the + // plottable: + if (!result.isPenDefined()) + result.setPen(mPen); + + return result; +} + +/*! + Copies all properties (e.g. color, fill, scatter style) of the \a other selection decorator to + this selection decorator. +*/ +void QCPSelectionDecorator::copyFrom(const QCPSelectionDecorator *other) +{ + setPen(other->pen()); + setBrush(other->brush()); + setScatterStyle(other->scatterStyle(), other->usedScatterProperties()); +} + +/*! + This method is called by all plottables' draw methods to allow custom selection decorations to be + drawn. Use the passed \a painter to perform the drawing operations. \a selection carries the data + selection for which the decoration shall be drawn. + + The default base class implementation of \ref QCPSelectionDecorator has no special decoration, so + this method does nothing. +*/ +void QCPSelectionDecorator::drawDecoration(QCPPainter *painter, QCPDataSelection selection) +{ + Q_UNUSED(painter) + Q_UNUSED(selection) +} + +/*! \internal + + This method is called as soon as a selection decorator is associated with a plottable, by a call + to \ref QCPAbstractPlottable::setSelectionDecorator. This way the selection decorator can obtain a pointer to the plottable that uses it (e.g. to access + data points via the \ref QCPAbstractPlottable::interface1D interface). + + If the selection decorator was already added to a different plottable before, this method aborts + the registration and returns false. +*/ +bool QCPSelectionDecorator::registerWithPlottable(QCPAbstractPlottable *plottable) +{ + if (!mPlottable) + { + mPlottable = plottable; + return true; + } else + { + qDebug() << Q_FUNC_INFO << "This selection decorator is already registered with plottable:" << reinterpret_cast(mPlottable); + return false; + } +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAbstractPlottable +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPAbstractPlottable + \brief The abstract base class for all data representing objects in a plot. + + It defines a very basic interface like name, pen, brush, visibility etc. Since this class is + abstract, it can't be instantiated. Use one of the subclasses or create a subclass yourself to + create new ways of displaying data (see "Creating own plottables" below). Plottables that display + one-dimensional data (i.e. data points have a single key dimension and one or multiple values at + each key) are based off of the template subclass \ref QCPAbstractPlottable1D, see details + there. + + All further specifics are in the subclasses, for example: + \li A normal graph with possibly a line and/or scatter points \ref QCPGraph + (typically created with \ref QCustomPlot::addGraph) + \li A parametric curve: \ref QCPCurve + \li A bar chart: \ref QCPBars + \li A statistical box plot: \ref QCPStatisticalBox + \li A color encoded two-dimensional map: \ref QCPColorMap + \li An OHLC/Candlestick chart: \ref QCPFinancial + + \section plottables-subclassing Creating own plottables + + Subclassing directly from QCPAbstractPlottable is only recommended if you wish to display + two-dimensional data like \ref QCPColorMap, i.e. two logical key dimensions and one (or more) + data dimensions. If you want to display data with only one logical key dimension, you should + rather derive from \ref QCPAbstractPlottable1D. + + If subclassing QCPAbstractPlottable directly, these are the pure virtual functions you must + implement: + \li \ref selectTest + \li \ref draw + \li \ref drawLegendIcon + \li \ref getKeyRange + \li \ref getValueRange + + See the documentation of those functions for what they need to do. + + For drawing your plot, you can use the \ref coordsToPixels functions to translate a point in plot + coordinates to pixel coordinates. This function is quite convenient, because it takes the + orientation of the key and value axes into account for you (x and y are swapped when the key axis + is vertical and the value axis horizontal). If you are worried about performance (i.e. you need + to translate many points in a loop like QCPGraph), you can directly use \ref + QCPAxis::coordToPixel. However, you must then take care about the orientation of the axis + yourself. + + Here are some important members you inherit from QCPAbstractPlottable: + + + + + + + + + + + + + + + + + + + + + + + + + + +
QCustomPlot *\b mParentPlotA pointer to the parent QCustomPlot instance. The parent plot is inferred from the axes that are passed in the constructor.
QString \b mNameThe name of the plottable.
QPen \b mPenThe generic pen of the plottable. You should use this pen for the most prominent data representing lines in the plottable + (e.g QCPGraph uses this pen for its graph lines and scatters)
QBrush \b mBrushThe generic brush of the plottable. You should use this brush for the most prominent fillable structures in the plottable + (e.g. QCPGraph uses this brush to control filling under the graph)
QPointer<\ref QCPAxis> \b mKeyAxis, \b mValueAxisThe key and value axes this plottable is attached to. Call their QCPAxis::coordToPixel functions to translate coordinates + to pixels in either the key or value dimension. Make sure to check whether the pointer is \c nullptr before using it. If one of + the axes is null, don't draw the plottable.
\ref QCPSelectionDecorator \b mSelectionDecoratorThe currently set selection decorator which specifies how selected data of the plottable shall be drawn and decorated. + When drawing your data, you must consult this decorator for the appropriate pen/brush before drawing unselected/selected data segments. + Finally, you should call its \ref QCPSelectionDecorator::drawDecoration method at the end of your \ref draw implementation.
\ref QCP::SelectionType \b mSelectableIn which composition, if at all, this plottable's data may be selected. Enforcing this setting on the data selection is done + by QCPAbstractPlottable automatically.
\ref QCPDataSelection \b mSelectionHolds the current selection state of the plottable's data, i.e. the selected data ranges (\ref QCPDataRange).
+*/ + +/* start of documentation of inline functions */ + +/*! \fn QCPSelectionDecorator *QCPAbstractPlottable::selectionDecorator() const + + Provides access to the selection decorator of this plottable. The selection decorator controls + how selected data ranges are drawn (e.g. their pen color and fill), see \ref + QCPSelectionDecorator for details. + + If you wish to use an own \ref QCPSelectionDecorator subclass, pass an instance of it to \ref + setSelectionDecorator. +*/ + +/*! \fn bool QCPAbstractPlottable::selected() const + + Returns true if there are any data points of the plottable currently selected. Use \ref selection + to retrieve the current \ref QCPDataSelection. +*/ + +/*! \fn QCPDataSelection QCPAbstractPlottable::selection() const + + Returns a \ref QCPDataSelection encompassing all the data points that are currently selected on + this plottable. + + \see selected, setSelection, setSelectable +*/ + +/*! \fn virtual QCPPlottableInterface1D *QCPAbstractPlottable::interface1D() + + If this plottable is a one-dimensional plottable, i.e. it implements the \ref + QCPPlottableInterface1D, returns the \a this pointer with that type. Otherwise (e.g. in the case + of a \ref QCPColorMap) returns zero. + + You can use this method to gain read access to data coordinates while holding a pointer to the + abstract base class only. +*/ + +/* end of documentation of inline functions */ +/* start of documentation of pure virtual functions */ + +/*! \fn void QCPAbstractPlottable::drawLegendIcon(QCPPainter *painter, const QRect &rect) const = 0 + \internal + + called by QCPLegend::draw (via QCPPlottableLegendItem::draw) to create a graphical representation + of this plottable inside \a rect, next to the plottable name. + + The passed \a painter has its cliprect set to \a rect, so painting outside of \a rect won't + appear outside the legend icon border. +*/ + +/*! \fn QCPRange QCPAbstractPlottable::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const = 0 + + Returns the coordinate range that all data in this plottable span in the key axis dimension. For + logarithmic plots, one can set \a inSignDomain to either \ref QCP::sdNegative or \ref + QCP::sdPositive in order to restrict the returned range to that sign domain. E.g. when only + negative range is wanted, set \a inSignDomain to \ref QCP::sdNegative and all positive points + will be ignored for range calculation. For no restriction, just set \a inSignDomain to \ref + QCP::sdBoth (default). \a foundRange is an output parameter that indicates whether a range could + be found or not. If this is false, you shouldn't use the returned range (e.g. no points in data). + + Note that \a foundRange is not the same as \ref QCPRange::validRange, since the range returned by + this function may have size zero (e.g. when there is only one data point). In this case \a + foundRange would return true, but the returned range is not a valid range in terms of \ref + QCPRange::validRange. + + \see rescaleAxes, getValueRange +*/ + +/*! \fn QCPRange QCPAbstractPlottable::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const = 0 + + Returns the coordinate range that the data points in the specified key range (\a inKeyRange) span + in the value axis dimension. For logarithmic plots, one can set \a inSignDomain to either \ref + QCP::sdNegative or \ref QCP::sdPositive in order to restrict the returned range to that sign + domain. E.g. when only negative range is wanted, set \a inSignDomain to \ref QCP::sdNegative and + all positive points will be ignored for range calculation. For no restriction, just set \a + inSignDomain to \ref QCP::sdBoth (default). \a foundRange is an output parameter that indicates + whether a range could be found or not. If this is false, you shouldn't use the returned range + (e.g. no points in data). + + If \a inKeyRange has both lower and upper bound set to zero (is equal to QCPRange()), + all data points are considered, without any restriction on the keys. + + Note that \a foundRange is not the same as \ref QCPRange::validRange, since the range returned by + this function may have size zero (e.g. when there is only one data point). In this case \a + foundRange would return true, but the returned range is not a valid range in terms of \ref + QCPRange::validRange. + + \see rescaleAxes, getKeyRange +*/ + +/* end of documentation of pure virtual functions */ +/* start of documentation of signals */ + +/*! \fn void QCPAbstractPlottable::selectionChanged(bool selected) + + This signal is emitted when the selection state of this plottable has changed, either by user + interaction or by a direct call to \ref setSelection. The parameter \a selected indicates whether + there are any points selected or not. + + \see selectionChanged(const QCPDataSelection &selection) +*/ + +/*! \fn void QCPAbstractPlottable::selectionChanged(const QCPDataSelection &selection) + + This signal is emitted when the selection state of this plottable has changed, either by user + interaction or by a direct call to \ref setSelection. The parameter \a selection holds the + currently selected data ranges. + + \see selectionChanged(bool selected) +*/ + +/*! \fn void QCPAbstractPlottable::selectableChanged(QCP::SelectionType selectable); + + This signal is emitted when the selectability of this plottable has changed. + + \see setSelectable +*/ + +/* end of documentation of signals */ + +/*! + Constructs an abstract plottable which uses \a keyAxis as its key axis ("x") and \a valueAxis as + its value axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance + and have perpendicular orientations. If either of these restrictions is violated, a corresponding + message is printed to the debug output (qDebug), the construction is not aborted, though. + + Since QCPAbstractPlottable is an abstract class that defines the basic interface to plottables, + it can't be directly instantiated. + + You probably want one of the subclasses like \ref QCPGraph or \ref QCPCurve instead. +*/ +QCPAbstractPlottable::QCPAbstractPlottable(QCPAxis *keyAxis, QCPAxis *valueAxis) : + QCPLayerable(keyAxis->parentPlot(), QString(), keyAxis->axisRect()), + mName(), + mAntialiasedFill(true), + mAntialiasedScatters(true), + mPen(Qt::black), + mBrush(Qt::NoBrush), + mKeyAxis(keyAxis), + mValueAxis(valueAxis), + mSelectable(QCP::stWhole), + mSelectionDecorator(nullptr) +{ + if (keyAxis->parentPlot() != valueAxis->parentPlot()) + qDebug() << Q_FUNC_INFO << "Parent plot of keyAxis is not the same as that of valueAxis."; + if (keyAxis->orientation() == valueAxis->orientation()) + qDebug() << Q_FUNC_INFO << "keyAxis and valueAxis must be orthogonal to each other."; + + mParentPlot->registerPlottable(this); + setSelectionDecorator(new QCPSelectionDecorator); +} + +QCPAbstractPlottable::~QCPAbstractPlottable() +{ + if (mSelectionDecorator) + { + delete mSelectionDecorator; + mSelectionDecorator = nullptr; + } +} + +/*! + The name is the textual representation of this plottable as it is displayed in the legend + (\ref QCPLegend). It may contain any UTF-8 characters, including newlines. +*/ +void QCPAbstractPlottable::setName(const QString &name) +{ + mName = name; +} + +/*! + Sets whether fills of this plottable are drawn antialiased or not. + + Note that this setting may be overridden by \ref QCustomPlot::setAntialiasedElements and \ref + QCustomPlot::setNotAntialiasedElements. +*/ +void QCPAbstractPlottable::setAntialiasedFill(bool enabled) +{ + mAntialiasedFill = enabled; +} + +/*! + Sets whether the scatter symbols of this plottable are drawn antialiased or not. + + Note that this setting may be overridden by \ref QCustomPlot::setAntialiasedElements and \ref + QCustomPlot::setNotAntialiasedElements. +*/ +void QCPAbstractPlottable::setAntialiasedScatters(bool enabled) +{ + mAntialiasedScatters = enabled; +} + +/*! + The pen is used to draw basic lines that make up the plottable representation in the + plot. + + For example, the \ref QCPGraph subclass draws its graph lines with this pen. + + \see setBrush +*/ +void QCPAbstractPlottable::setPen(const QPen &pen) +{ + mPen = pen; +} + +/*! + The brush is used to draw basic fills of the plottable representation in the + plot. The Fill can be a color, gradient or texture, see the usage of QBrush. + + For example, the \ref QCPGraph subclass draws the fill under the graph with this brush, when + it's not set to Qt::NoBrush. + + \see setPen +*/ +void QCPAbstractPlottable::setBrush(const QBrush &brush) +{ + mBrush = brush; +} + +/*! + The key axis of a plottable can be set to any axis of a QCustomPlot, as long as it is orthogonal + to the plottable's value axis. This function performs no checks to make sure this is the case. + The typical mathematical choice is to use the x-axis (QCustomPlot::xAxis) as key axis and the + y-axis (QCustomPlot::yAxis) as value axis. + + Normally, the key and value axes are set in the constructor of the plottable (or \ref + QCustomPlot::addGraph when working with QCPGraphs through the dedicated graph interface). + + \see setValueAxis +*/ +void QCPAbstractPlottable::setKeyAxis(QCPAxis *axis) +{ + mKeyAxis = axis; +} + +/*! + The value axis of a plottable can be set to any axis of a QCustomPlot, as long as it is + orthogonal to the plottable's key axis. This function performs no checks to make sure this is the + case. The typical mathematical choice is to use the x-axis (QCustomPlot::xAxis) as key axis and + the y-axis (QCustomPlot::yAxis) as value axis. + + Normally, the key and value axes are set in the constructor of the plottable (or \ref + QCustomPlot::addGraph when working with QCPGraphs through the dedicated graph interface). + + \see setKeyAxis +*/ +void QCPAbstractPlottable::setValueAxis(QCPAxis *axis) +{ + mValueAxis = axis; +} + + +/*! + Sets which data ranges of this plottable are selected. Selected data ranges are drawn differently + (e.g. color) in the plot. This can be controlled via the selection decorator (see \ref + selectionDecorator). + + The entire selection mechanism for plottables is handled automatically when \ref + QCustomPlot::setInteractions contains iSelectPlottables. You only need to call this function when + you wish to change the selection state programmatically. + + Using \ref setSelectable you can further specify for each plottable whether and to which + granularity it is selectable. If \a selection is not compatible with the current \ref + QCP::SelectionType set via \ref setSelectable, the resulting selection will be adjusted + accordingly (see \ref QCPDataSelection::enforceType). + + emits the \ref selectionChanged signal when \a selected is different from the previous selection state. + + \see setSelectable, selectTest +*/ +void QCPAbstractPlottable::setSelection(QCPDataSelection selection) +{ + selection.enforceType(mSelectable); + if (mSelection != selection) + { + mSelection = selection; + emit selectionChanged(selected()); + emit selectionChanged(mSelection); + } +} + +/*! + Use this method to set an own QCPSelectionDecorator (subclass) instance. This allows you to + customize the visual representation of selected data ranges further than by using the default + QCPSelectionDecorator. + + The plottable takes ownership of the \a decorator. + + The currently set decorator can be accessed via \ref selectionDecorator. +*/ +void QCPAbstractPlottable::setSelectionDecorator(QCPSelectionDecorator *decorator) +{ + if (decorator) + { + if (decorator->registerWithPlottable(this)) + { + delete mSelectionDecorator; // delete old decorator if necessary + mSelectionDecorator = decorator; + } + } else if (mSelectionDecorator) // just clear decorator + { + delete mSelectionDecorator; + mSelectionDecorator = nullptr; + } +} + +/*! + Sets whether and to which granularity this plottable can be selected. + + A selection can happen by clicking on the QCustomPlot surface (When \ref + QCustomPlot::setInteractions contains \ref QCP::iSelectPlottables), by dragging a selection rect + (When \ref QCustomPlot::setSelectionRectMode is \ref QCP::srmSelect), or programmatically by + calling \ref setSelection. + + \see setSelection, QCP::SelectionType +*/ +void QCPAbstractPlottable::setSelectable(QCP::SelectionType selectable) +{ + if (mSelectable != selectable) + { + mSelectable = selectable; + QCPDataSelection oldSelection = mSelection; + mSelection.enforceType(mSelectable); + emit selectableChanged(mSelectable); + if (mSelection != oldSelection) + { + emit selectionChanged(selected()); + emit selectionChanged(mSelection); + } + } +} + + +/*! + Convenience function for transforming a key/value pair to pixels on the QCustomPlot surface, + taking the orientations of the axes associated with this plottable into account (e.g. whether key + represents x or y). + + \a key and \a value are transformed to the coodinates in pixels and are written to \a x and \a y. + + \see pixelsToCoords, QCPAxis::coordToPixel +*/ +void QCPAbstractPlottable::coordsToPixels(double key, double value, double &x, double &y) const +{ + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + if (keyAxis->orientation() == Qt::Horizontal) + { + x = keyAxis->coordToPixel(key); + y = valueAxis->coordToPixel(value); + } else + { + y = keyAxis->coordToPixel(key); + x = valueAxis->coordToPixel(value); + } +} + +/*! \overload + + Transforms the given \a key and \a value to pixel coordinates and returns them in a QPointF. +*/ +const QPointF QCPAbstractPlottable::coordsToPixels(double key, double value) const +{ + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); } + + if (keyAxis->orientation() == Qt::Horizontal) + return QPointF(keyAxis->coordToPixel(key), valueAxis->coordToPixel(value)); + else + return QPointF(valueAxis->coordToPixel(value), keyAxis->coordToPixel(key)); +} + +/*! + Convenience function for transforming a x/y pixel pair on the QCustomPlot surface to plot coordinates, + taking the orientations of the axes associated with this plottable into account (e.g. whether key + represents x or y). + + \a x and \a y are transformed to the plot coodinates and are written to \a key and \a value. + + \see coordsToPixels, QCPAxis::coordToPixel +*/ +void QCPAbstractPlottable::pixelsToCoords(double x, double y, double &key, double &value) const +{ + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + if (keyAxis->orientation() == Qt::Horizontal) + { + key = keyAxis->pixelToCoord(x); + value = valueAxis->pixelToCoord(y); + } else + { + key = keyAxis->pixelToCoord(y); + value = valueAxis->pixelToCoord(x); + } +} + +/*! \overload + + Returns the pixel input \a pixelPos as plot coordinates \a key and \a value. +*/ +void QCPAbstractPlottable::pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const +{ + pixelsToCoords(pixelPos.x(), pixelPos.y(), key, value); +} + +/*! + Rescales the key and value axes associated with this plottable to contain all displayed data, so + the whole plottable is visible. If the scaling of an axis is logarithmic, rescaleAxes will make + sure not to rescale to an illegal range i.e. a range containing different signs and/or zero. + Instead it will stay in the current sign domain and ignore all parts of the plottable that lie + outside of that domain. + + \a onlyEnlarge makes sure the ranges are only expanded, never reduced. So it's possible to show + multiple plottables in their entirety by multiple calls to rescaleAxes where the first call has + \a onlyEnlarge set to false (the default), and all subsequent set to true. + + \see rescaleKeyAxis, rescaleValueAxis, QCustomPlot::rescaleAxes, QCPAxis::rescale +*/ +void QCPAbstractPlottable::rescaleAxes(bool onlyEnlarge) const +{ + rescaleKeyAxis(onlyEnlarge); + rescaleValueAxis(onlyEnlarge); +} + +/*! + Rescales the key axis of the plottable so the whole plottable is visible. + + See \ref rescaleAxes for detailed behaviour. +*/ +void QCPAbstractPlottable::rescaleKeyAxis(bool onlyEnlarge) const +{ + QCPAxis *keyAxis = mKeyAxis.data(); + if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } + + QCP::SignDomain signDomain = QCP::sdBoth; + if (keyAxis->scaleType() == QCPAxis::stLogarithmic) + signDomain = (keyAxis->range().upper < 0 ? QCP::sdNegative : QCP::sdPositive); + + bool foundRange; + QCPRange newRange = getKeyRange(foundRange, signDomain); + if (foundRange) + { + if (onlyEnlarge) + newRange.expand(keyAxis->range()); + if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable + { + double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason + if (keyAxis->scaleType() == QCPAxis::stLinear) + { + newRange.lower = center-keyAxis->range().size()/2.0; + newRange.upper = center+keyAxis->range().size()/2.0; + } else // scaleType() == stLogarithmic + { + newRange.lower = center/qSqrt(keyAxis->range().upper/keyAxis->range().lower); + newRange.upper = center*qSqrt(keyAxis->range().upper/keyAxis->range().lower); + } + } + keyAxis->setRange(newRange); + } +} + +/*! + Rescales the value axis of the plottable so the whole plottable is visible. If \a inKeyRange is + set to true, only the data points which are in the currently visible key axis range are + considered. + + Returns true if the axis was actually scaled. This might not be the case if this plottable has an + invalid range, e.g. because it has no data points. + + See \ref rescaleAxes for detailed behaviour. +*/ +void QCPAbstractPlottable::rescaleValueAxis(bool onlyEnlarge, bool inKeyRange) const +{ + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + QCP::SignDomain signDomain = QCP::sdBoth; + if (valueAxis->scaleType() == QCPAxis::stLogarithmic) + signDomain = (valueAxis->range().upper < 0 ? QCP::sdNegative : QCP::sdPositive); + + bool foundRange; + QCPRange newRange = getValueRange(foundRange, signDomain, inKeyRange ? keyAxis->range() : QCPRange()); + if (foundRange) + { + if (onlyEnlarge) + newRange.expand(valueAxis->range()); + if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable + { + double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason + if (valueAxis->scaleType() == QCPAxis::stLinear) + { + newRange.lower = center-valueAxis->range().size()/2.0; + newRange.upper = center+valueAxis->range().size()/2.0; + } else // scaleType() == stLogarithmic + { + newRange.lower = center/qSqrt(valueAxis->range().upper/valueAxis->range().lower); + newRange.upper = center*qSqrt(valueAxis->range().upper/valueAxis->range().lower); + } + } + valueAxis->setRange(newRange); + } +} + +/*! \overload + + Adds this plottable to the specified \a legend. + + Creates a QCPPlottableLegendItem which is inserted into the legend. Returns true on success, i.e. + when the legend exists and a legend item associated with this plottable isn't already in the + legend. + + If the plottable needs a more specialized representation in the legend, you can create a + corresponding subclass of \ref QCPPlottableLegendItem and add it to the legend manually instead + of calling this method. + + \see removeFromLegend, QCPLegend::addItem +*/ +bool QCPAbstractPlottable::addToLegend(QCPLegend *legend) +{ + if (!legend) + { + qDebug() << Q_FUNC_INFO << "passed legend is null"; + return false; + } + if (legend->parentPlot() != mParentPlot) + { + qDebug() << Q_FUNC_INFO << "passed legend isn't in the same QCustomPlot as this plottable"; + return false; + } + + if (!legend->hasItemWithPlottable(this)) + { + legend->addItem(new QCPPlottableLegendItem(legend, this)); + return true; + } else + return false; +} + +/*! \overload + + Adds this plottable to the legend of the parent QCustomPlot (\ref QCustomPlot::legend). + + \see removeFromLegend +*/ +bool QCPAbstractPlottable::addToLegend() +{ + if (!mParentPlot || !mParentPlot->legend) + return false; + else + return addToLegend(mParentPlot->legend); +} + +/*! \overload + + Removes the plottable from the specifed \a legend. This means the \ref QCPPlottableLegendItem + that is associated with this plottable is removed. + + Returns true on success, i.e. if the legend exists and a legend item associated with this + plottable was found and removed. + + \see addToLegend, QCPLegend::removeItem +*/ +bool QCPAbstractPlottable::removeFromLegend(QCPLegend *legend) const +{ + if (!legend) + { + qDebug() << Q_FUNC_INFO << "passed legend is null"; + return false; + } + + if (QCPPlottableLegendItem *lip = legend->itemWithPlottable(this)) + return legend->removeItem(lip); + else + return false; +} + +/*! \overload + + Removes the plottable from the legend of the parent QCustomPlot. + + \see addToLegend +*/ +bool QCPAbstractPlottable::removeFromLegend() const +{ + if (!mParentPlot || !mParentPlot->legend) + return false; + else + return removeFromLegend(mParentPlot->legend); +} + +/* inherits documentation from base class */ +QRect QCPAbstractPlottable::clipRect() const +{ + if (mKeyAxis && mValueAxis) + return mKeyAxis.data()->axisRect()->rect() & mValueAxis.data()->axisRect()->rect(); + else + return {}; +} + +/* inherits documentation from base class */ +QCP::Interaction QCPAbstractPlottable::selectionCategory() const +{ + return QCP::iSelectPlottables; +} + +/*! \internal + + A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter + before drawing plottable lines. + + This is the antialiasing state the painter passed to the \ref draw method is in by default. + + This function takes into account the local setting of the antialiasing flag as well as the + overrides set with \ref QCustomPlot::setAntialiasedElements and \ref + QCustomPlot::setNotAntialiasedElements. + + \seebaseclassmethod + + \see setAntialiased, applyFillAntialiasingHint, applyScattersAntialiasingHint +*/ +void QCPAbstractPlottable::applyDefaultAntialiasingHint(QCPPainter *painter) const +{ + applyAntialiasingHint(painter, mAntialiased, QCP::aePlottables); +} + +/*! \internal + + A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter + before drawing plottable fills. + + This function takes into account the local setting of the antialiasing flag as well as the + overrides set with \ref QCustomPlot::setAntialiasedElements and \ref + QCustomPlot::setNotAntialiasedElements. + + \see setAntialiased, applyDefaultAntialiasingHint, applyScattersAntialiasingHint +*/ +void QCPAbstractPlottable::applyFillAntialiasingHint(QCPPainter *painter) const +{ + applyAntialiasingHint(painter, mAntialiasedFill, QCP::aeFills); +} + +/*! \internal + + A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter + before drawing plottable scatter points. + + This function takes into account the local setting of the antialiasing flag as well as the + overrides set with \ref QCustomPlot::setAntialiasedElements and \ref + QCustomPlot::setNotAntialiasedElements. + + \see setAntialiased, applyFillAntialiasingHint, applyDefaultAntialiasingHint +*/ +void QCPAbstractPlottable::applyScattersAntialiasingHint(QCPPainter *painter) const +{ + applyAntialiasingHint(painter, mAntialiasedScatters, QCP::aeScatters); +} + +/* inherits documentation from base class */ +void QCPAbstractPlottable::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) +{ + Q_UNUSED(event) + + if (mSelectable != QCP::stNone) + { + QCPDataSelection newSelection = details.value(); + QCPDataSelection selectionBefore = mSelection; + if (additive) + { + if (mSelectable == QCP::stWhole) // in whole selection mode, we toggle to no selection even if currently unselected point was hit + { + if (selected()) + setSelection(QCPDataSelection()); + else + setSelection(newSelection); + } else // in all other selection modes we toggle selections of homogeneously selected/unselected segments + { + if (mSelection.contains(newSelection)) // if entire newSelection is already selected, toggle selection + setSelection(mSelection-newSelection); + else + setSelection(mSelection+newSelection); + } + } else + setSelection(newSelection); + if (selectionStateChanged) + *selectionStateChanged = mSelection != selectionBefore; + } +} + +/* inherits documentation from base class */ +void QCPAbstractPlottable::deselectEvent(bool *selectionStateChanged) +{ + if (mSelectable != QCP::stNone) + { + QCPDataSelection selectionBefore = mSelection; + setSelection(QCPDataSelection()); + if (selectionStateChanged) + *selectionStateChanged = mSelection != selectionBefore; + } +} +/* end of 'src/plottable.cpp' */ + + +/* including file 'src/item.cpp' */ +/* modified 2022-11-06T12:45:56, size 49486 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPItemAnchor +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPItemAnchor + \brief An anchor of an item to which positions can be attached to. + + An item (QCPAbstractItem) may have one or more anchors. Unlike QCPItemPosition, an anchor doesn't + control anything on its item, but provides a way to tie other items via their positions to the + anchor. + + For example, a QCPItemRect is defined by its positions \a topLeft and \a bottomRight. + Additionally it has various anchors like \a top, \a topRight or \a bottomLeft etc. So you can + attach the \a start (which is a QCPItemPosition) of a QCPItemLine to one of the anchors by + calling QCPItemPosition::setParentAnchor on \a start, passing the wanted anchor of the + QCPItemRect. This way the start of the line will now always follow the respective anchor location + on the rect item. + + Note that QCPItemPosition derives from QCPItemAnchor, so every position can also serve as an + anchor to other positions. + + To learn how to provide anchors in your own item subclasses, see the subclassing section of the + QCPAbstractItem documentation. +*/ + +/* start documentation of inline functions */ + +/*! \fn virtual QCPItemPosition *QCPItemAnchor::toQCPItemPosition() + + Returns \c nullptr if this instance is merely a QCPItemAnchor, and a valid pointer of type + QCPItemPosition* if it actually is a QCPItemPosition (which is a subclass of QCPItemAnchor). + + This safe downcast functionality could also be achieved with a dynamic_cast. However, QCustomPlot avoids + dynamic_cast to work with projects that don't have RTTI support enabled (e.g. -fno-rtti flag with + gcc compiler). +*/ + +/* end documentation of inline functions */ + +/*! + Creates a new QCPItemAnchor. You shouldn't create QCPItemAnchor instances directly, even if + you want to make a new item subclass. Use \ref QCPAbstractItem::createAnchor instead, as + explained in the subclassing section of the QCPAbstractItem documentation. +*/ +QCPItemAnchor::QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString &name, int anchorId) : + mName(name), + mParentPlot(parentPlot), + mParentItem(parentItem), + mAnchorId(anchorId) +{ +} + +QCPItemAnchor::~QCPItemAnchor() +{ + // unregister as parent at children: + foreach (QCPItemPosition *child, mChildrenX.values()) + { + if (child->parentAnchorX() == this) + child->setParentAnchorX(nullptr); // this acts back on this anchor and child removes itself from mChildrenX + } + foreach (QCPItemPosition *child, mChildrenY.values()) + { + if (child->parentAnchorY() == this) + child->setParentAnchorY(nullptr); // this acts back on this anchor and child removes itself from mChildrenY + } +} + +/*! + Returns the final absolute pixel position of the QCPItemAnchor on the QCustomPlot surface. + + The pixel information is internally retrieved via QCPAbstractItem::anchorPixelPosition of the + parent item, QCPItemAnchor is just an intermediary. +*/ +QPointF QCPItemAnchor::pixelPosition() const +{ + if (mParentItem) + { + if (mAnchorId > -1) + { + return mParentItem->anchorPixelPosition(mAnchorId); + } else + { + qDebug() << Q_FUNC_INFO << "no valid anchor id set:" << mAnchorId; + return {}; + } + } else + { + qDebug() << Q_FUNC_INFO << "no parent item set"; + return {}; + } +} + +/*! \internal + + Adds \a pos to the childX list of this anchor, which keeps track of which children use this + anchor as parent anchor for the respective coordinate. This is necessary to notify the children + prior to destruction of the anchor. + + Note that this function does not change the parent setting in \a pos. +*/ +void QCPItemAnchor::addChildX(QCPItemPosition *pos) +{ + if (!mChildrenX.contains(pos)) + mChildrenX.insert(pos); + else + qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast(pos); +} + +/*! \internal + + Removes \a pos from the childX list of this anchor. + + Note that this function does not change the parent setting in \a pos. +*/ +void QCPItemAnchor::removeChildX(QCPItemPosition *pos) +{ + if (!mChildrenX.remove(pos)) + qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast(pos); +} + +/*! \internal + + Adds \a pos to the childY list of this anchor, which keeps track of which children use this + anchor as parent anchor for the respective coordinate. This is necessary to notify the children + prior to destruction of the anchor. + + Note that this function does not change the parent setting in \a pos. +*/ +void QCPItemAnchor::addChildY(QCPItemPosition *pos) +{ + if (!mChildrenY.contains(pos)) + mChildrenY.insert(pos); + else + qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast(pos); +} + +/*! \internal + + Removes \a pos from the childY list of this anchor. + + Note that this function does not change the parent setting in \a pos. +*/ +void QCPItemAnchor::removeChildY(QCPItemPosition *pos) +{ + if (!mChildrenY.remove(pos)) + qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast(pos); +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPItemPosition +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPItemPosition + \brief Manages the position of an item. + + Every item has at least one public QCPItemPosition member pointer which provides ways to position the + item on the QCustomPlot surface. Some items have multiple positions, for example QCPItemRect has two: + \a topLeft and \a bottomRight. + + QCPItemPosition has a type (\ref PositionType) that can be set with \ref setType. This type + defines how coordinates passed to \ref setCoords are to be interpreted, e.g. as absolute pixel + coordinates, as plot coordinates of certain axes (\ref QCPItemPosition::setAxes), as fractions of + the axis rect (\ref QCPItemPosition::setAxisRect), etc. For more advanced plots it is also + possible to assign different types per X/Y coordinate of the position (see \ref setTypeX, \ref + setTypeY). This way an item could be positioned for example at a fixed pixel distance from the + top in the Y direction, while following a plot coordinate in the X direction. + + A QCPItemPosition may have a parent QCPItemAnchor, see \ref setParentAnchor. This way you can tie + multiple items together. If the QCPItemPosition has a parent, its coordinates (\ref setCoords) + are considered to be absolute pixels in the reference frame of the parent anchor, where (0, 0) + means directly ontop of the parent anchor. For example, You could attach the \a start position of + a QCPItemLine to the \a bottom anchor of a QCPItemText to make the starting point of the line + always be centered under the text label, no matter where the text is moved to. For more advanced + plots, it is possible to assign different parent anchors per X/Y coordinate of the position, see + \ref setParentAnchorX, \ref setParentAnchorY. This way an item could follow another item in the X + direction but stay at a fixed position in the Y direction. Or even follow item A in X, and item B + in Y. + + Note that every QCPItemPosition inherits from QCPItemAnchor and thus can itself be used as parent + anchor for other positions. + + To set the apparent pixel position on the QCustomPlot surface directly, use \ref setPixelPosition. This + works no matter what type this QCPItemPosition is or what parent-child situation it is in, as \ref + setPixelPosition transforms the coordinates appropriately, to make the position appear at the specified + pixel values. +*/ + +/* start documentation of inline functions */ + +/*! \fn QCPItemPosition::PositionType *QCPItemPosition::type() const + + Returns the current position type. + + If different types were set for X and Y (\ref setTypeX, \ref setTypeY), this method returns the + type of the X coordinate. In that case rather use \a typeX() and \a typeY(). + + \see setType +*/ + +/*! \fn QCPItemAnchor *QCPItemPosition::parentAnchor() const + + Returns the current parent anchor. + + If different parent anchors were set for X and Y (\ref setParentAnchorX, \ref setParentAnchorY), + this method returns the parent anchor of the Y coordinate. In that case rather use \a + parentAnchorX() and \a parentAnchorY(). + + \see setParentAnchor +*/ + +/* end documentation of inline functions */ + +/*! + Creates a new QCPItemPosition. You shouldn't create QCPItemPosition instances directly, even if + you want to make a new item subclass. Use \ref QCPAbstractItem::createPosition instead, as + explained in the subclassing section of the QCPAbstractItem documentation. +*/ +QCPItemPosition::QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString &name) : + QCPItemAnchor(parentPlot, parentItem, name), + mPositionTypeX(ptAbsolute), + mPositionTypeY(ptAbsolute), + mKey(0), + mValue(0), + mParentAnchorX(nullptr), + mParentAnchorY(nullptr) +{ +} + +QCPItemPosition::~QCPItemPosition() +{ + // unregister as parent at children: + // Note: this is done in ~QCPItemAnchor again, but it's important QCPItemPosition does it itself, because only then + // the setParentAnchor(0) call the correct QCPItemPosition::pixelPosition function instead of QCPItemAnchor::pixelPosition + foreach (QCPItemPosition *child, mChildrenX.values()) + { + if (child->parentAnchorX() == this) + child->setParentAnchorX(nullptr); // this acts back on this anchor and child removes itself from mChildrenX + } + foreach (QCPItemPosition *child, mChildrenY.values()) + { + if (child->parentAnchorY() == this) + child->setParentAnchorY(nullptr); // this acts back on this anchor and child removes itself from mChildrenY + } + // unregister as child in parent: + if (mParentAnchorX) + mParentAnchorX->removeChildX(this); + if (mParentAnchorY) + mParentAnchorY->removeChildY(this); +} + +/* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */ +QCPAxisRect *QCPItemPosition::axisRect() const +{ + return mAxisRect.data(); +} + +/*! + Sets the type of the position. The type defines how the coordinates passed to \ref setCoords + should be handled and how the QCPItemPosition should behave in the plot. + + The possible values for \a type can be separated in two main categories: + + \li The position is regarded as a point in plot coordinates. This corresponds to \ref ptPlotCoords + and requires two axes that define the plot coordinate system. They can be specified with \ref setAxes. + By default, the QCustomPlot's x- and yAxis are used. + + \li The position is fixed on the QCustomPlot surface, i.e. independent of axis ranges. This + corresponds to all other types, i.e. \ref ptAbsolute, \ref ptViewportRatio and \ref + ptAxisRectRatio. They differ only in the way the absolute position is described, see the + documentation of \ref PositionType for details. For \ref ptAxisRectRatio, note that you can specify + the axis rect with \ref setAxisRect. By default this is set to the main axis rect. + + Note that the position type \ref ptPlotCoords is only available (and sensible) when the position + has no parent anchor (\ref setParentAnchor). + + If the type is changed, the apparent pixel position on the plot is preserved. This means + the coordinates as retrieved with coords() and set with \ref setCoords may change in the process. + + This method sets the type for both X and Y directions. It is also possible to set different types + for X and Y, see \ref setTypeX, \ref setTypeY. */ -double QCPLineEnding::boundingDistance() const +void QCPItemPosition::setType(QCPItemPosition::PositionType type) { - switch (mStyle) + setTypeX(type); + setTypeY(type); +} + +/*! + This method sets the position type of the X coordinate to \a type. + + For a detailed description of what a position type is, see the documentation of \ref setType. + + \see setType, setTypeY +*/ +void QCPItemPosition::setTypeX(QCPItemPosition::PositionType type) +{ + if (mPositionTypeX != type) { - case esNone: - return 0; - - case esFlatArrow: - case esSpikeArrow: - case esLineArrow: - case esSkewedBar: - return qSqrt(mWidth*mWidth+mLength*mLength); // items that have width and length - - case esDisc: - case esSquare: - case esDiamond: - case esBar: - case esHalfBar: - return mWidth*1.42; // items that only have a width -> width*sqrt(2) + // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect + // were deleted), don't try to recover the pixelPosition() because it would output a qDebug warning. + bool retainPixelPosition = true; + if ((mPositionTypeX == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis)) + retainPixelPosition = false; + if ((mPositionTypeX == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect)) + retainPixelPosition = false; + + QPointF pixel; + if (retainPixelPosition) + pixel = pixelPosition(); + + mPositionTypeX = type; + + if (retainPixelPosition) + setPixelPosition(pixel); + } +} +/*! + This method sets the position type of the Y coordinate to \a type. + + For a detailed description of what a position type is, see the documentation of \ref setType. + + \see setType, setTypeX +*/ +void QCPItemPosition::setTypeY(QCPItemPosition::PositionType type) +{ + if (mPositionTypeY != type) + { + // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect + // were deleted), don't try to recover the pixelPosition() because it would output a qDebug warning. + bool retainPixelPosition = true; + if ((mPositionTypeY == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis)) + retainPixelPosition = false; + if ((mPositionTypeY == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect)) + retainPixelPosition = false; + + QPointF pixel; + if (retainPixelPosition) + pixel = pixelPosition(); + + mPositionTypeY = type; + + if (retainPixelPosition) + setPixelPosition(pixel); } - return 0; } /*! - Starting from the origin of this line ending (which is style specific), returns the length - covered by the line ending symbol, in backward direction. + Sets the parent of this QCPItemPosition to \a parentAnchor. This means the position will now + follow any position changes of the anchor. The local coordinate system of positions with a parent + anchor always is absolute pixels, with (0, 0) being exactly on top of the parent anchor. (Hence + the type shouldn't be set to \ref ptPlotCoords for positions with parent anchors.) + + if \a keepPixelPosition is true, the current pixel position of the QCPItemPosition is preserved + during reparenting. If it's set to false, the coordinates are set to (0, 0), i.e. the position + will be exactly on top of the parent anchor. + + To remove this QCPItemPosition from any parent anchor, set \a parentAnchor to \c nullptr. + + If the QCPItemPosition previously had no parent and the type is \ref ptPlotCoords, the type is + set to \ref ptAbsolute, to keep the position in a valid state. + + This method sets the parent anchor for both X and Y directions. It is also possible to set + different parents for X and Y, see \ref setParentAnchorX, \ref setParentAnchorY. +*/ +bool QCPItemPosition::setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition) +{ + bool successX = setParentAnchorX(parentAnchor, keepPixelPosition); + bool successY = setParentAnchorY(parentAnchor, keepPixelPosition); + return successX && successY; +} + +/*! + This method sets the parent anchor of the X coordinate to \a parentAnchor. + + For a detailed description of what a parent anchor is, see the documentation of \ref setParentAnchor. + + \see setParentAnchor, setParentAnchorY +*/ +bool QCPItemPosition::setParentAnchorX(QCPItemAnchor *parentAnchor, bool keepPixelPosition) +{ + // make sure self is not assigned as parent: + if (parentAnchor == this) + { + qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast(parentAnchor); + return false; + } + // make sure no recursive parent-child-relationships are created: + QCPItemAnchor *currentParent = parentAnchor; + while (currentParent) + { + if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition()) + { + // is a QCPItemPosition, might have further parent, so keep iterating + if (currentParentPos == this) + { + qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast(parentAnchor); + return false; + } + currentParent = currentParentPos->parentAnchorX(); + } else + { + // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the + // same, to prevent a position being child of an anchor which itself depends on the position, + // because they're both on the same item: + if (currentParent->mParentItem == mParentItem) + { + qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast(parentAnchor); + return false; + } + break; + } + } + + // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute: + if (!mParentAnchorX && mPositionTypeX == ptPlotCoords) + setTypeX(ptAbsolute); + + // save pixel position: + QPointF pixelP; + if (keepPixelPosition) + pixelP = pixelPosition(); + // unregister at current parent anchor: + if (mParentAnchorX) + mParentAnchorX->removeChildX(this); + // register at new parent anchor: + if (parentAnchor) + parentAnchor->addChildX(this); + mParentAnchorX = parentAnchor; + // restore pixel position under new parent: + if (keepPixelPosition) + setPixelPosition(pixelP); + else + setCoords(0, coords().y()); + return true; +} + +/*! + This method sets the parent anchor of the Y coordinate to \a parentAnchor. + + For a detailed description of what a parent anchor is, see the documentation of \ref setParentAnchor. + + \see setParentAnchor, setParentAnchorX +*/ +bool QCPItemPosition::setParentAnchorY(QCPItemAnchor *parentAnchor, bool keepPixelPosition) +{ + // make sure self is not assigned as parent: + if (parentAnchor == this) + { + qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast(parentAnchor); + return false; + } + // make sure no recursive parent-child-relationships are created: + QCPItemAnchor *currentParent = parentAnchor; + while (currentParent) + { + if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition()) + { + // is a QCPItemPosition, might have further parent, so keep iterating + if (currentParentPos == this) + { + qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast(parentAnchor); + return false; + } + currentParent = currentParentPos->parentAnchorY(); + } else + { + // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the + // same, to prevent a position being child of an anchor which itself depends on the position, + // because they're both on the same item: + if (currentParent->mParentItem == mParentItem) + { + qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast(parentAnchor); + return false; + } + break; + } + } + + // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute: + if (!mParentAnchorY && mPositionTypeY == ptPlotCoords) + setTypeY(ptAbsolute); + + // save pixel position: + QPointF pixelP; + if (keepPixelPosition) + pixelP = pixelPosition(); + // unregister at current parent anchor: + if (mParentAnchorY) + mParentAnchorY->removeChildY(this); + // register at new parent anchor: + if (parentAnchor) + parentAnchor->addChildY(this); + mParentAnchorY = parentAnchor; + // restore pixel position under new parent: + if (keepPixelPosition) + setPixelPosition(pixelP); + else + setCoords(coords().x(), 0); + return true; +} + +/*! + Sets the coordinates of this QCPItemPosition. What the coordinates mean, is defined by the type + (\ref setType, \ref setTypeX, \ref setTypeY). - For example, the \ref esSpikeArrow has a shorter real length than a \ref esFlatArrow, even if - both have the same \ref setLength value, because the spike arrow has an inward curved back, which - reduces the length along its center axis (the drawing origin for arrows is at the tip). + For example, if the type is \ref ptAbsolute, \a key and \a value mean the x and y pixel position + on the QCustomPlot surface. In that case the origin (0, 0) is in the top left corner of the + QCustomPlot viewport. If the type is \ref ptPlotCoords, \a key and \a value mean a point in the + plot coordinate system defined by the axes set by \ref setAxes. By default those are the + QCustomPlot's xAxis and yAxis. See the documentation of \ref setType for other available + coordinate types and their meaning. - This function is used for precise, style specific placement of line endings, for example in - QCPAxes. + If different types were configured for X and Y (\ref setTypeX, \ref setTypeY), \a key and \a + value must also be provided in the different coordinate systems. Here, the X type refers to \a + key, and the Y type refers to \a value. + + \see setPixelPosition */ -double QCPLineEnding::realLength() const +void QCPItemPosition::setCoords(double key, double value) { - switch (mStyle) - { - case esNone: - case esLineArrow: - case esSkewedBar: - case esBar: - case esHalfBar: - return 0; - - case esFlatArrow: - return mLength; - - case esDisc: - case esSquare: - case esDiamond: - return mWidth*0.5; - - case esSpikeArrow: - return mLength*0.8; - } - return 0; + mKey = key; + mValue = value; } -/*! \internal - - Draws the line ending with the specified \a painter at the position \a pos. The direction of the - line ending is controlled with \a dir. +/*! \overload + + Sets the coordinates as a QPointF \a pos where pos.x has the meaning of \a key and pos.y the + meaning of \a value of the \ref setCoords(double key, double value) method. */ -void QCPLineEnding::draw(QCPPainter *painter, const QVector2D &pos, const QVector2D &dir) const +void QCPItemPosition::setCoords(const QPointF &pos) { - if (mStyle == esNone) - return; + setCoords(pos.x(), pos.y()); +} + +/*! + Returns the final absolute pixel position of the QCPItemPosition on the QCustomPlot surface. It + includes all effects of type (\ref setType) and possible parent anchors (\ref setParentAnchor). + + \see setPixelPosition +*/ +QPointF QCPItemPosition::pixelPosition() const +{ + QPointF result; - QVector2D lengthVec(dir.normalized()); - if (lengthVec.isNull()) - lengthVec = QVector2D(1, 0); - QVector2D widthVec(-lengthVec.y(), lengthVec.x()); - lengthVec *= (float)(mLength*(mInverted ? -1 : 1)); - widthVec *= (float)(mWidth*0.5*(mInverted ? -1 : 1)); + // determine X: + switch (mPositionTypeX) + { + case ptAbsolute: + { + result.rx() = mKey; + if (mParentAnchorX) + result.rx() += mParentAnchorX->pixelPosition().x(); + break; + } + case ptViewportRatio: + { + result.rx() = mKey*mParentPlot->viewport().width(); + if (mParentAnchorX) + result.rx() += mParentAnchorX->pixelPosition().x(); + else + result.rx() += mParentPlot->viewport().left(); + break; + } + case ptAxisRectRatio: + { + if (mAxisRect) + { + result.rx() = mKey*mAxisRect.data()->width(); + if (mParentAnchorX) + result.rx() += mParentAnchorX->pixelPosition().x(); + else + result.rx() += mAxisRect.data()->left(); + } else + qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined"; + break; + } + case ptPlotCoords: + { + if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal) + result.rx() = mKeyAxis.data()->coordToPixel(mKey); + else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal) + result.rx() = mValueAxis.data()->coordToPixel(mValue); + else + qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined"; + break; + } + } - QPen penBackup = painter->pen(); - QBrush brushBackup = painter->brush(); - QPen miterPen = penBackup; - miterPen.setJoinStyle(Qt::MiterJoin); // to make arrow heads spikey - QBrush brush(painter->pen().color(), Qt::SolidPattern); - switch (mStyle) + // determine Y: + switch (mPositionTypeY) { - case esNone: break; - case esFlatArrow: + case ptAbsolute: { - QPointF points[3] = {pos.toPointF(), - (pos-lengthVec+widthVec).toPointF(), - (pos-lengthVec-widthVec).toPointF() - }; - painter->setPen(miterPen); - painter->setBrush(brush); - painter->drawConvexPolygon(points, 3); - painter->setBrush(brushBackup); - painter->setPen(penBackup); + result.ry() = mValue; + if (mParentAnchorY) + result.ry() += mParentAnchorY->pixelPosition().y(); break; } - case esSpikeArrow: + case ptViewportRatio: { - QPointF points[4] = {pos.toPointF(), - (pos-lengthVec+widthVec).toPointF(), - (pos-lengthVec*0.8f).toPointF(), - (pos-lengthVec-widthVec).toPointF() - }; - painter->setPen(miterPen); - painter->setBrush(brush); - painter->drawConvexPolygon(points, 4); - painter->setBrush(brushBackup); - painter->setPen(penBackup); + result.ry() = mValue*mParentPlot->viewport().height(); + if (mParentAnchorY) + result.ry() += mParentAnchorY->pixelPosition().y(); + else + result.ry() += mParentPlot->viewport().top(); break; } - case esLineArrow: + case ptAxisRectRatio: { - QPointF points[3] = {(pos-lengthVec+widthVec).toPointF(), - pos.toPointF(), - (pos-lengthVec-widthVec).toPointF() - }; - painter->setPen(miterPen); - painter->drawPolyline(points, 3); - painter->setPen(penBackup); + if (mAxisRect) + { + result.ry() = mValue*mAxisRect.data()->height(); + if (mParentAnchorY) + result.ry() += mParentAnchorY->pixelPosition().y(); + else + result.ry() += mAxisRect.data()->top(); + } else + qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined"; break; } - case esDisc: + case ptPlotCoords: { - painter->setBrush(brush); - painter->drawEllipse(pos.toPointF(), mWidth*0.5, mWidth*0.5); - painter->setBrush(brushBackup); + if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical) + result.ry() = mKeyAxis.data()->coordToPixel(mKey); + else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical) + result.ry() = mValueAxis.data()->coordToPixel(mValue); + else + qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined"; break; } - case esSquare: + } + + return result; +} + +/*! + When \ref setType is \ref ptPlotCoords, this function may be used to specify the axes the + coordinates set with \ref setCoords relate to. By default they are set to the initial xAxis and + yAxis of the QCustomPlot. +*/ +void QCPItemPosition::setAxes(QCPAxis *keyAxis, QCPAxis *valueAxis) +{ + mKeyAxis = keyAxis; + mValueAxis = valueAxis; +} + +/*! + When \ref setType is \ref ptAxisRectRatio, this function may be used to specify the axis rect the + coordinates set with \ref setCoords relate to. By default this is set to the main axis rect of + the QCustomPlot. +*/ +void QCPItemPosition::setAxisRect(QCPAxisRect *axisRect) +{ + mAxisRect = axisRect; +} + +/*! + Sets the apparent pixel position. This works no matter what type (\ref setType) this + QCPItemPosition is or what parent-child situation it is in, as coordinates are transformed + appropriately, to make the position finally appear at the specified pixel values. + + Only if the type is \ref ptAbsolute and no parent anchor is set, this function's effect is + identical to that of \ref setCoords. + + \see pixelPosition, setCoords +*/ +void QCPItemPosition::setPixelPosition(const QPointF &pixelPosition) +{ + double x = pixelPosition.x(); + double y = pixelPosition.y(); + + switch (mPositionTypeX) + { + case ptAbsolute: { - QVector2D widthVecPerp(-widthVec.y(), widthVec.x()); - QPointF points[4] = {(pos-widthVecPerp+widthVec).toPointF(), - (pos-widthVecPerp-widthVec).toPointF(), - (pos+widthVecPerp-widthVec).toPointF(), - (pos+widthVecPerp+widthVec).toPointF() - }; - painter->setPen(miterPen); - painter->setBrush(brush); - painter->drawConvexPolygon(points, 4); - painter->setBrush(brushBackup); - painter->setPen(penBackup); + if (mParentAnchorX) + x -= mParentAnchorX->pixelPosition().x(); break; } - case esDiamond: + case ptViewportRatio: { - QVector2D widthVecPerp(-widthVec.y(), widthVec.x()); - QPointF points[4] = {(pos-widthVecPerp).toPointF(), - (pos-widthVec).toPointF(), - (pos+widthVecPerp).toPointF(), - (pos+widthVec).toPointF() - }; - painter->setPen(miterPen); - painter->setBrush(brush); - painter->drawConvexPolygon(points, 4); - painter->setBrush(brushBackup); - painter->setPen(penBackup); + if (mParentAnchorX) + x -= mParentAnchorX->pixelPosition().x(); + else + x -= mParentPlot->viewport().left(); + x /= double(mParentPlot->viewport().width()); + break; + } + case ptAxisRectRatio: + { + if (mAxisRect) + { + if (mParentAnchorX) + x -= mParentAnchorX->pixelPosition().x(); + else + x -= mAxisRect.data()->left(); + x /= double(mAxisRect.data()->width()); + } else + qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined"; + break; + } + case ptPlotCoords: + { + if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal) + x = mKeyAxis.data()->pixelToCoord(x); + else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal) + y = mValueAxis.data()->pixelToCoord(x); + else + qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined"; break; } - case esBar: + } + + switch (mPositionTypeY) + { + case ptAbsolute: { - painter->drawLine((pos+widthVec).toPointF(), (pos-widthVec).toPointF()); + if (mParentAnchorY) + y -= mParentAnchorY->pixelPosition().y(); break; } - case esHalfBar: + case ptViewportRatio: { - painter->drawLine((pos+widthVec).toPointF(), pos.toPointF()); + if (mParentAnchorY) + y -= mParentAnchorY->pixelPosition().y(); + else + y -= mParentPlot->viewport().top(); + y /= double(mParentPlot->viewport().height()); break; } - case esSkewedBar: + case ptAxisRectRatio: { - if (qFuzzyIsNull(painter->pen().widthF()) && !painter->modes().testFlag(QCPPainter::pmNonCosmetic)) + if (mAxisRect) { - // if drawing with cosmetic pen (perfectly thin stroke, happens only in vector exports), draw bar exactly on tip of line - painter->drawLine((pos+widthVec+lengthVec*0.2f*(mInverted?-1:1)).toPointF(), - (pos-widthVec-lengthVec*0.2f*(mInverted?-1:1)).toPointF()); + if (mParentAnchorY) + y -= mParentAnchorY->pixelPosition().y(); + else + y -= mAxisRect.data()->top(); + y /= double(mAxisRect.data()->height()); } else - { - // if drawing with thick (non-cosmetic) pen, shift bar a little in line direction to prevent line from sticking through bar slightly - painter->drawLine((pos+widthVec+lengthVec*0.2f*(mInverted?-1:1)+dir.normalized()*qMax(1.0f, (float)painter->pen().widthF())*0.5f).toPointF(), - (pos-widthVec-lengthVec*0.2f*(mInverted?-1:1)+dir.normalized()*qMax(1.0f, (float)painter->pen().widthF())*0.5f).toPointF()); - } + qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined"; + break; + } + case ptPlotCoords: + { + if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical) + x = mKeyAxis.data()->pixelToCoord(y); + else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical) + y = mValueAxis.data()->pixelToCoord(y); + else + qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined"; break; } } + + setCoords(x, y); } -/*! \internal - \overload + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAbstractItem +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPAbstractItem + \brief The abstract base class for all items in a plot. - Draws the line ending. The direction is controlled with the \a angle parameter in radians. + In QCustomPlot, items are supplemental graphical elements that are neither plottables + (QCPAbstractPlottable) nor axes (QCPAxis). While plottables are always tied to two axes and thus + plot coordinates, items can also be placed in absolute coordinates independent of any axes. Each + specific item has at least one QCPItemPosition member which controls the positioning. Some items + are defined by more than one coordinate and thus have two or more QCPItemPosition members (For + example, QCPItemRect has \a topLeft and \a bottomRight). + + This abstract base class defines a very basic interface like visibility and clipping. Since this + class is abstract, it can't be instantiated. Use one of the subclasses or create a subclass + yourself to create new items. + + The built-in items are: + + + + + + + + + + +
QCPItemLineA line defined by a start and an end point. May have different ending styles on each side (e.g. arrows).
QCPItemStraightLineA straight line defined by a start and a direction point. Unlike QCPItemLine, the straight line is infinitely long and has no endings.
QCPItemCurveA curve defined by start, end and two intermediate control points. May have different ending styles on each side (e.g. arrows).
QCPItemRectA rectangle
QCPItemEllipseAn ellipse
QCPItemPixmapAn arbitrary pixmap
QCPItemTextA text label
QCPItemBracketA bracket which may be used to reference/highlight certain parts in the plot.
QCPItemTracerAn item that can be attached to a QCPGraph and sticks to its data points, given a key coordinate.
+ + \section items-clipping Clipping + + Items are by default clipped to the main axis rect (they are only visible inside the axis rect). + To make an item visible outside that axis rect, disable clipping via \ref setClipToAxisRect + "setClipToAxisRect(false)". + + On the other hand if you want the item to be clipped to a different axis rect, specify it via + \ref setClipAxisRect. This clipAxisRect property of an item is only used for clipping behaviour, and + in principle is independent of the coordinate axes the item might be tied to via its position + members (\ref QCPItemPosition::setAxes). However, it is common that the axis rect for clipping + also contains the axes used for the item positions. + + \section items-using Using items + + First you instantiate the item you want to use and add it to the plot: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpitemline-creation-1 + by default, the positions of the item are bound to the x- and y-Axis of the plot. So we can just + set the plot coordinates where the line should start/end: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpitemline-creation-2 + If we don't want the line to be positioned in plot coordinates but a different coordinate system, + e.g. absolute pixel positions on the QCustomPlot surface, we need to change the position type like this: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpitemline-creation-3 + Then we can set the coordinates, this time in pixels: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpitemline-creation-4 + and make the line visible on the entire QCustomPlot, by disabling clipping to the axis rect: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpitemline-creation-5 + + For more advanced plots, it is even possible to set different types and parent anchors per X/Y + coordinate of an item position, using for example \ref QCPItemPosition::setTypeX or \ref + QCPItemPosition::setParentAnchorX. For details, see the documentation of \ref QCPItemPosition. + + \section items-subclassing Creating own items + + To create an own item, you implement a subclass of QCPAbstractItem. These are the pure + virtual functions, you must implement: + \li \ref selectTest + \li \ref draw + + See the documentation of those functions for what they need to do. + + \subsection items-positioning Allowing the item to be positioned + + As mentioned, item positions are represented by QCPItemPosition members. Let's assume the new item shall + have only one point as its position (as opposed to two like a rect or multiple like a polygon). You then add + a public member of type QCPItemPosition like so: + + \code QCPItemPosition * const myPosition;\endcode + + the const makes sure the pointer itself can't be modified from the user of your new item (the QCPItemPosition + instance it points to, can be modified, of course). + The initialization of this pointer is made easy with the \ref createPosition function. Just assign + the return value of this function to each QCPItemPosition in the constructor of your item. \ref createPosition + takes a string which is the name of the position, typically this is identical to the variable name. + For example, the constructor of QCPItemExample could look like this: + + \code + QCPItemExample::QCPItemExample(QCustomPlot *parentPlot) : + QCPAbstractItem(parentPlot), + myPosition(createPosition("myPosition")) + { + // other constructor code + } + \endcode + + \subsection items-drawing The draw function + + To give your item a visual representation, reimplement the \ref draw function and use the passed + QCPPainter to draw the item. You can retrieve the item position in pixel coordinates from the + position member(s) via \ref QCPItemPosition::pixelPosition. + + To optimize performance you should calculate a bounding rect first (don't forget to take the pen + width into account), check whether it intersects the \ref clipRect, and only draw the item at all + if this is the case. + + \subsection items-selection The selectTest function + + Your implementation of the \ref selectTest function may use the helpers \ref + QCPVector2D::distanceSquaredToLine and \ref rectDistance. With these, the implementation of the + selection test becomes significantly simpler for most items. See the documentation of \ref + selectTest for what the function parameters mean and what the function should return. + + \subsection anchors Providing anchors + + Providing anchors (QCPItemAnchor) starts off like adding a position. First you create a public + member, e.g. + + \code QCPItemAnchor * const bottom;\endcode + + and create it in the constructor with the \ref createAnchor function, assigning it a name and an + anchor id (an integer enumerating all anchors on the item, you may create an own enum for this). + Since anchors can be placed anywhere, relative to the item's position(s), your item needs to + provide the position of every anchor with the reimplementation of the \ref anchorPixelPosition(int + anchorId) function. + + In essence the QCPItemAnchor is merely an intermediary that itself asks your item for the pixel + position when anything attached to the anchor needs to know the coordinates. +*/ + +/* start of documentation of inline functions */ + +/*! \fn QList QCPAbstractItem::positions() const + + Returns all positions of the item in a list. + + \see anchors, position +*/ + +/*! \fn QList QCPAbstractItem::anchors() const + + Returns all anchors of the item in a list. Note that since a position (QCPItemPosition) is always + also an anchor, the list will also contain the positions of this item. + + \see positions, anchor +*/ + +/* end of documentation of inline functions */ +/* start documentation of pure virtual functions */ + +/*! \fn void QCPAbstractItem::draw(QCPPainter *painter) = 0 + \internal + + Draws this item with the provided \a painter. + + The cliprect of the provided painter is set to the rect returned by \ref clipRect before this + function is called. The clipRect depends on the clipping settings defined by \ref + setClipToAxisRect and \ref setClipAxisRect. +*/ + +/* end documentation of pure virtual functions */ +/* start documentation of signals */ + +/*! \fn void QCPAbstractItem::selectionChanged(bool selected) + This signal is emitted when the selection state of this item has changed, either by user interaction + or by a direct call to \ref setSelected. +*/ + +/* end documentation of signals */ + +/*! + Base class constructor which initializes base class members. */ -void QCPLineEnding::draw(QCPPainter *painter, const QVector2D &pos, double angle) const +QCPAbstractItem::QCPAbstractItem(QCustomPlot *parentPlot) : + QCPLayerable(parentPlot), + mClipToAxisRect(false), + mSelectable(true), + mSelected(false) { - draw(painter, pos, QVector2D(qCos(angle), qSin(angle))); + parentPlot->registerItem(this); + + QList rects = parentPlot->axisRects(); + if (!rects.isEmpty()) + { + setClipToAxisRect(true); + setClipAxisRect(rects.first()); + } } +QCPAbstractItem::~QCPAbstractItem() +{ + // don't delete mPositions because every position is also an anchor and thus in mAnchors + qDeleteAll(mAnchors); +} -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPGrid -//////////////////////////////////////////////////////////////////////////////////////////////////// +/* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */ +QCPAxisRect *QCPAbstractItem::clipAxisRect() const +{ + return mClipAxisRect.data(); +} -/*! \class QCPGrid - \brief Responsible for drawing the grid of a QCPAxis. - - This class is tightly bound to QCPAxis. Every axis owns a grid instance and uses it to draw the - grid lines, sub grid lines and zero-line. You can interact with the grid of an axis via \ref - QCPAxis::grid. Normally, you don't need to create an instance of QCPGrid yourself. +/*! + Sets whether the item shall be clipped to an axis rect or whether it shall be visible on the + entire QCustomPlot. The axis rect can be set with \ref setClipAxisRect. - The axis and grid drawing was split into two classes to allow them to be placed on different - layers (both QCPAxis and QCPGrid inherit from QCPLayerable). Thus it is possible to have the grid - in the background and the axes in the foreground, and any plottables/items in between. This - described situation is the default setup, see the QCPLayer documentation. + \see setClipAxisRect */ +void QCPAbstractItem::setClipToAxisRect(bool clip) +{ + mClipToAxisRect = clip; + if (mClipToAxisRect) + setParentLayerable(mClipAxisRect.data()); +} /*! - Creates a QCPGrid instance and sets default values. + Sets the clip axis rect. It defines the rect that will be used to clip the item when \ref + setClipToAxisRect is set to true. - You shouldn't instantiate grids on their own, since every QCPAxis brings its own QCPGrid. + \see setClipToAxisRect */ -QCPGrid::QCPGrid(QCPAxis *parentAxis) : - QCPLayerable(parentAxis->parentPlot(), QString(), parentAxis), - mParentAxis(parentAxis) +void QCPAbstractItem::setClipAxisRect(QCPAxisRect *rect) { - // warning: this is called in QCPAxis constructor, so parentAxis members should not be accessed/called - setParent(parentAxis); - setPen(QPen(QColor(200,200,200), 0, Qt::DotLine)); - setSubGridPen(QPen(QColor(220,220,220), 0, Qt::DotLine)); - setZeroLinePen(QPen(QColor(200,200,200), 0, Qt::SolidLine)); - setSubGridVisible(false); - setAntialiased(false); - setAntialiasedSubGrid(false); - setAntialiasedZeroLine(false); + mClipAxisRect = rect; + if (mClipToAxisRect) + setParentLayerable(mClipAxisRect.data()); } /*! - Sets whether grid lines at sub tick marks are drawn. + Sets whether the user can (de-)select this item by clicking on the QCustomPlot surface. + (When \ref QCustomPlot::setInteractions contains QCustomPlot::iSelectItems.) - \see setSubGridPen + However, even when \a selectable was set to false, it is possible to set the selection manually, + by calling \ref setSelected. + + \see QCustomPlot::setInteractions, setSelected */ -void QCPGrid::setSubGridVisible(bool visible) +void QCPAbstractItem::setSelectable(bool selectable) { - mSubGridVisible = visible; + if (mSelectable != selectable) + { + mSelectable = selectable; + emit selectableChanged(mSelectable); + } } /*! - Sets whether sub grid lines are drawn antialiased. + Sets whether this item is selected or not. When selected, it might use a different visual + appearance (e.g. pen and brush), this depends on the specific item though. + + The entire selection mechanism for items is handled automatically when \ref + QCustomPlot::setInteractions contains QCustomPlot::iSelectItems. You only need to call this + function when you wish to change the selection state manually. + + This function can change the selection state even when \ref setSelectable was set to false. + + emits the \ref selectionChanged signal when \a selected is different from the previous selection state. + + \see setSelectable, selectTest */ -void QCPGrid::setAntialiasedSubGrid(bool enabled) +void QCPAbstractItem::setSelected(bool selected) { - mAntialiasedSubGrid = enabled; + if (mSelected != selected) + { + mSelected = selected; + emit selectionChanged(mSelected); + } } /*! - Sets whether zero lines are drawn antialiased. + Returns the QCPItemPosition with the specified \a name. If this item doesn't have a position by + that name, returns \c nullptr. + + This function provides an alternative way to access item positions. Normally, you access + positions direcly by their member pointers (which typically have the same variable name as \a + name). + + \see positions, anchor */ -void QCPGrid::setAntialiasedZeroLine(bool enabled) +QCPItemPosition *QCPAbstractItem::position(const QString &name) const { - mAntialiasedZeroLine = enabled; + foreach (QCPItemPosition *position, mPositions) + { + if (position->name() == name) + return position; + } + qDebug() << Q_FUNC_INFO << "position with name not found:" << name; + return nullptr; } /*! - Sets the pen with which (major) grid lines are drawn. + Returns the QCPItemAnchor with the specified \a name. If this item doesn't have an anchor by + that name, returns \c nullptr. + + This function provides an alternative way to access item anchors. Normally, you access + anchors direcly by their member pointers (which typically have the same variable name as \a + name). + + \see anchors, position */ -void QCPGrid::setPen(const QPen &pen) +QCPItemAnchor *QCPAbstractItem::anchor(const QString &name) const { - mPen = pen; + foreach (QCPItemAnchor *anchor, mAnchors) + { + if (anchor->name() == name) + return anchor; + } + qDebug() << Q_FUNC_INFO << "anchor with name not found:" << name; + return nullptr; } /*! - Sets the pen with which sub grid lines are drawn. + Returns whether this item has an anchor with the specified \a name. + + Note that you can check for positions with this function, too. This is because every position is + also an anchor (QCPItemPosition inherits from QCPItemAnchor). + + \see anchor, position */ -void QCPGrid::setSubGridPen(const QPen &pen) +bool QCPAbstractItem::hasAnchor(const QString &name) const { - mSubGridPen = pen; + foreach (QCPItemAnchor *anchor, mAnchors) + { + if (anchor->name() == name) + return true; + } + return false; } -/*! - Sets the pen with which zero lines are drawn. +/*! \internal - Zero lines are lines at value coordinate 0 which may be drawn with a different pen than other grid - lines. To disable zero lines and just draw normal grid lines at zero, set \a pen to Qt::NoPen. + Returns the rect the visual representation of this item is clipped to. This depends on the + current setting of \ref setClipToAxisRect as well as the axis rect set with \ref setClipAxisRect. + + If the item is not clipped to an axis rect, QCustomPlot's viewport rect is returned. + + \see draw */ -void QCPGrid::setZeroLinePen(const QPen &pen) +QRect QCPAbstractItem::clipRect() const { - mZeroLinePen = pen; + if (mClipToAxisRect && mClipAxisRect) + return mClipAxisRect.data()->rect(); + else + return mParentPlot->viewport(); } /*! \internal A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter - before drawing the major grid lines. + before drawing item lines. This is the antialiasing state the painter passed to the \ref draw method is in by default. @@ -3757,19782 +13113,22417 @@ void QCPGrid::setZeroLinePen(const QPen &pen) \see setAntialiased */ -void QCPGrid::applyDefaultAntialiasingHint(QCPPainter *painter) const +void QCPAbstractItem::applyDefaultAntialiasingHint(QCPPainter *painter) const { - applyAntialiasingHint(painter, mAntialiased, QCP::aeGrid); + applyAntialiasingHint(painter, mAntialiased, QCP::aeItems); } /*! \internal + + A convenience function which returns the selectTest value for a specified \a rect and a specified + click position \a pos. \a filledRect defines whether a click inside the rect should also be + considered a hit or whether only the rect border is sensitive to hits. - Draws grid lines and sub grid lines at the positions of (sub) ticks of the parent axis, spanning - over the complete axis rect. Also draws the zero line, if appropriate (\ref setZeroLinePen). + This function may be used to help with the implementation of the \ref selectTest function for + specific items. + + For example, if your item consists of four rects, call this function four times, once for each + rect, in your \ref selectTest reimplementation. Finally, return the minimum (non -1) of all four + returned values. */ -void QCPGrid::draw(QCPPainter *painter) +double QCPAbstractItem::rectDistance(const QRectF &rect, const QPointF &pos, bool filledRect) const { - if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; } + double result = -1; + + // distance to border: + const QList lines = QList() << QLineF(rect.topLeft(), rect.topRight()) << QLineF(rect.bottomLeft(), rect.bottomRight()) + << QLineF(rect.topLeft(), rect.bottomLeft()) << QLineF(rect.topRight(), rect.bottomRight()); + const QCPVector2D posVec(pos); + double minDistSqr = (std::numeric_limits::max)(); + foreach (const QLineF &line, lines) + { + double distSqr = posVec.distanceSquaredToLine(line.p1(), line.p2()); + if (distSqr < minDistSqr) + minDistSqr = distSqr; + } + result = qSqrt(minDistSqr); - if (mSubGridVisible) - drawSubGridLines(painter); - drawGridLines(painter); + // filled rect, allow click inside to count as hit: + if (filledRect && result > mParentPlot->selectionTolerance()*0.99) + { + if (rect.contains(pos)) + result = mParentPlot->selectionTolerance()*0.99; + } + return result; } /*! \internal + + Returns the pixel position of the anchor with Id \a anchorId. This function must be reimplemented in + item subclasses if they want to provide anchors (QCPItemAnchor). - Draws the main grid lines and possibly a zero line with the specified painter. + For example, if the item has two anchors with id 0 and 1, this function takes one of these anchor + ids and returns the respective pixel points of the specified anchor. - This is a helper function called by \ref draw. + \see createAnchor */ -void QCPGrid::drawGridLines(QCPPainter *painter) const +QPointF QCPAbstractItem::anchorPixelPosition(int anchorId) const { - if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; } + qDebug() << Q_FUNC_INFO << "called on item which shouldn't have any anchors (this method not reimplemented). anchorId" << anchorId; + return {}; +} + +/*! \internal + + Creates a QCPItemPosition, registers it with this item and returns a pointer to it. The specified + \a name must be a unique string that is usually identical to the variable name of the position + member (This is needed to provide the name-based \ref position access to positions). - int lowTick = mParentAxis->mLowestVisibleTick; - int highTick = mParentAxis->mHighestVisibleTick; - double t; // helper variable, result of coordinate-to-pixel transforms - if (mParentAxis->orientation() == Qt::Horizontal) - { - // draw zeroline: - int zeroLineIndex = -1; - if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0) - { - applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine); - painter->setPen(mZeroLinePen); - double epsilon = mParentAxis->range().size()*1E-6; // for comparing double to zero - for (int i=lowTick; i <= highTick; ++i) - { - if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon) - { - zeroLineIndex = i; - t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x - painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top())); - break; - } - } - } - // draw grid lines: - applyDefaultAntialiasingHint(painter); - painter->setPen(mPen); - for (int i=lowTick; i <= highTick; ++i) - { - if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline - t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // x - painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top())); - } - } else - { - // draw zeroline: - int zeroLineIndex = -1; - if (mZeroLinePen.style() != Qt::NoPen && mParentAxis->mRange.lower < 0 && mParentAxis->mRange.upper > 0) - { - applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine); - painter->setPen(mZeroLinePen); - double epsilon = mParentAxis->mRange.size()*1E-6; // for comparing double to zero - for (int i=lowTick; i <= highTick; ++i) - { - if (qAbs(mParentAxis->mTickVector.at(i)) < epsilon) - { - zeroLineIndex = i; - t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y - painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t)); - break; - } - } - } - // draw grid lines: - applyDefaultAntialiasingHint(painter); - painter->setPen(mPen); - for (int i=lowTick; i <= highTick; ++i) - { - if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline - t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y - painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t)); - } - } + Don't delete positions created by this function manually, as the item will take care of it. + + Use this function in the constructor (initialization list) of the specific item subclass to + create each position member. Don't create QCPItemPositions with \b new yourself, because they + won't be registered with the item properly. + + \see createAnchor +*/ +QCPItemPosition *QCPAbstractItem::createPosition(const QString &name) +{ + if (hasAnchor(name)) + qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name; + QCPItemPosition *newPosition = new QCPItemPosition(mParentPlot, this, name); + mPositions.append(newPosition); + mAnchors.append(newPosition); // every position is also an anchor + newPosition->setAxes(mParentPlot->xAxis, mParentPlot->yAxis); + newPosition->setType(QCPItemPosition::ptPlotCoords); + if (mParentPlot->axisRect()) + newPosition->setAxisRect(mParentPlot->axisRect()); + newPosition->setCoords(0, 0); + return newPosition; } /*! \internal + + Creates a QCPItemAnchor, registers it with this item and returns a pointer to it. The specified + \a name must be a unique string that is usually identical to the variable name of the anchor + member (This is needed to provide the name based \ref anchor access to anchors). - Draws the sub grid lines with the specified painter. + The \a anchorId must be a number identifying the created anchor. It is recommended to create an + enum (e.g. "AnchorIndex") for this on each item that uses anchors. This id is used by the anchor + to identify itself when it calls QCPAbstractItem::anchorPixelPosition. That function then returns + the correct pixel coordinates for the passed anchor id. + + Don't delete anchors created by this function manually, as the item will take care of it. + + Use this function in the constructor (initialization list) of the specific item subclass to + create each anchor member. Don't create QCPItemAnchors with \b new yourself, because then they + won't be registered with the item properly. - This is a helper function called by \ref draw. + \see createPosition */ -void QCPGrid::drawSubGridLines(QCPPainter *painter) const +QCPItemAnchor *QCPAbstractItem::createAnchor(const QString &name, int anchorId) { - if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; } - - applyAntialiasingHint(painter, mAntialiasedSubGrid, QCP::aeSubGrid); - double t; // helper variable, result of coordinate-to-pixel transforms - painter->setPen(mSubGridPen); - if (mParentAxis->orientation() == Qt::Horizontal) + if (hasAnchor(name)) + qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name; + QCPItemAnchor *newAnchor = new QCPItemAnchor(mParentPlot, this, name, anchorId); + mAnchors.append(newAnchor); + return newAnchor; +} + +/* inherits documentation from base class */ +void QCPAbstractItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) +{ + Q_UNUSED(event) + Q_UNUSED(details) + if (mSelectable) { - for (int i=0; imSubTickVector.size(); ++i) - { - t = mParentAxis->coordToPixel(mParentAxis->mSubTickVector.at(i)); // x - painter->drawLine(QLineF(t, mParentAxis->mAxisRect->bottom(), t, mParentAxis->mAxisRect->top())); - } - } else + bool selBefore = mSelected; + setSelected(additive ? !mSelected : true); + if (selectionStateChanged) + *selectionStateChanged = mSelected != selBefore; + } +} + +/* inherits documentation from base class */ +void QCPAbstractItem::deselectEvent(bool *selectionStateChanged) +{ + if (mSelectable) { - for (int i=0; imSubTickVector.size(); ++i) - { - t = mParentAxis->coordToPixel(mParentAxis->mSubTickVector.at(i)); // y - painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t)); - } + bool selBefore = mSelected; + setSelected(false); + if (selectionStateChanged) + *selectionStateChanged = mSelected != selBefore; } } +/* inherits documentation from base class */ +QCP::Interaction QCPAbstractItem::selectionCategory() const +{ + return QCP::iSelectItems; +} +/* end of 'src/item.cpp' */ + + +/* including file 'src/core.cpp' */ +/* modified 2022-11-06T12:45:56, size 127625 */ //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPAxis +//////////////////// QCustomPlot //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPAxis - \brief Manages a single axis inside a QCustomPlot. - - Usually doesn't need to be instantiated externally. Access %QCustomPlot's default four axes via - QCustomPlot::xAxis (bottom), QCustomPlot::yAxis (left), QCustomPlot::xAxis2 (top) and - QCustomPlot::yAxis2 (right). +/*! \class QCustomPlot - Axes are always part of an axis rect, see QCPAxisRect. - \image html AxisNamesOverview.png -
Naming convention of axis parts
- \n - - \image html AxisRectSpacingOverview.png -
Overview of the spacings and paddings that define the geometry of an axis. The dashed gray line - on the left represents the QCustomPlot widget border.
- + \brief The central class of the library. This is the QWidget which displays the plot and + interacts with the user. + + For tutorials on how to use QCustomPlot, see the website\n + https://www.qcustomplot.com/ */ /* start of documentation of inline functions */ -/*! \fn Qt::Orientation QCPAxis::orientation() const +/*! \fn QCPSelectionRect *QCustomPlot::selectionRect() const - Returns the orientation of this axis. The axis orientation (horizontal or vertical) is deduced - from the axis type (left, top, right or bottom). + Allows access to the currently used QCPSelectionRect instance (or subclass thereof), that is used + to handle and draw selection rect interactions (see \ref setSelectionRectMode). - \see orientation(AxisType type) + \see setSelectionRect */ -/*! \fn QCPGrid *QCPAxis::grid() const +/*! \fn QCPLayoutGrid *QCustomPlot::plotLayout() const - Returns the \ref QCPGrid instance belonging to this axis. Access it to set details about the way the - grid is displayed. + Returns the top level layout of this QCustomPlot instance. It is a \ref QCPLayoutGrid, initially containing just + one cell with the main QCPAxisRect inside. */ -/*! \fn static Qt::Orientation QCPAxis::orientation(AxisType type) - - Returns the orientation of the specified axis type +/* end of documentation of inline functions */ +/* start of documentation of signals */ + +/*! \fn void QCustomPlot::mouseDoubleClick(QMouseEvent *event) + + This signal is emitted when the QCustomPlot receives a mouse double click event. +*/ + +/*! \fn void QCustomPlot::mousePress(QMouseEvent *event) + + This signal is emitted when the QCustomPlot receives a mouse press event. - \see orientation() + It is emitted before QCustomPlot handles any other mechanism like range dragging. So a slot + connected to this signal can still influence the behaviour e.g. with \ref QCPAxisRect::setRangeDrag or \ref + QCPAxisRect::setRangeDragAxes. */ -/* end of documentation of inline functions */ -/* start of documentation of signals */ +/*! \fn void QCustomPlot::mouseMove(QMouseEvent *event) -/*! \fn void QCPAxis::ticksRequest() + This signal is emitted when the QCustomPlot receives a mouse move event. - This signal is emitted when \ref setAutoTicks is false and the axis is about to generate tick - labels for a replot. + It is emitted before QCustomPlot handles any other mechanism like range dragging. So a slot + connected to this signal can still influence the behaviour e.g. with \ref QCPAxisRect::setRangeDrag or \ref + QCPAxisRect::setRangeDragAxes. - Modifying the tick positions can be done with \ref setTickVector. If you also want to control the - tick labels, set \ref setAutoTickLabels to false and also provide the labels with \ref - setTickVectorLabels. + \warning It is discouraged to change the drag-axes with \ref QCPAxisRect::setRangeDragAxes here, + because the dragging starting point was saved the moment the mouse was pressed. Thus it only has + a meaning for the range drag axes that were set at that moment. If you want to change the drag + axes, consider doing this in the \ref mousePress signal instead. +*/ + +/*! \fn void QCustomPlot::mouseRelease(QMouseEvent *event) + + This signal is emitted when the QCustomPlot receives a mouse release event. - If you only want static ticks you probably don't need this signal, since you can just set the - tick vector (and possibly tick label vector) once. However, if you want to provide ticks (and - maybe labels) dynamically, e.g. depending on the current axis range, connect a slot to this - signal and set the vector/vectors there. + It is emitted before QCustomPlot handles any other mechanisms like object selection. So a + slot connected to this signal can still influence the behaviour e.g. with \ref setInteractions or + \ref QCPAbstractPlottable::setSelectable. */ -/*! \fn void QCPAxis::rangeChanged(const QCPRange &newRange) +/*! \fn void QCustomPlot::mouseWheel(QMouseEvent *event) - This signal is emitted when the range of this axis has changed. You can connect it to the \ref - setRange slot of another axis to communicate the new range to the other axis, in order for it to - be synchronized. + This signal is emitted when the QCustomPlot receives a mouse wheel event. - You may also manipulate/correct the range with \ref setRange in a slot connected to this signal. - This is useful if for example a maximum range span shall not be exceeded, or if the lower/upper - range shouldn't go beyond certain values. For example, the following slot would limit the x axis - to only positive ranges: - \code - if (newRange.lower < 0) - plot->xAxis->setRange(0, newRange.size()); - \endcode + It is emitted before QCustomPlot handles any other mechanisms like range zooming. So a slot + connected to this signal can still influence the behaviour e.g. with \ref QCPAxisRect::setRangeZoom, \ref + QCPAxisRect::setRangeZoomAxes or \ref QCPAxisRect::setRangeZoomFactor. */ -/*! \fn void QCPAxis::rangeChanged(const QCPRange &newRange, const QCPRange &oldRange) - \overload +/*! \fn void QCustomPlot::plottableClick(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event) + + This signal is emitted when a plottable is clicked. + + \a event is the mouse event that caused the click and \a plottable is the plottable that received + the click. The parameter \a dataIndex indicates the data point that was closest to the click + position. + + \see plottableDoubleClick +*/ + +/*! \fn void QCustomPlot::plottableDoubleClick(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event) + + This signal is emitted when a plottable is double clicked. + + \a event is the mouse event that caused the click and \a plottable is the plottable that received + the click. The parameter \a dataIndex indicates the data point that was closest to the click + position. + + \see plottableClick +*/ + +/*! \fn void QCustomPlot::itemClick(QCPAbstractItem *item, QMouseEvent *event) - Additionally to the new range, this signal also provides the previous range held by the axis as - \a oldRange. + This signal is emitted when an item is clicked. + + \a event is the mouse event that caused the click and \a item is the item that received the + click. + + \see itemDoubleClick */ -/*! \fn void QCPAxis::scaleTypeChanged(QCPAxis::ScaleType scaleType); +/*! \fn void QCustomPlot::itemDoubleClick(QCPAbstractItem *item, QMouseEvent *event) - This signal is emitted when the scale type changes, by calls to \ref setScaleType + This signal is emitted when an item is double clicked. + + \a event is the mouse event that caused the click and \a item is the item that received the + click. + + \see itemClick */ -/*! \fn void QCPAxis::selectionChanged(QCPAxis::SelectableParts selection) +/*! \fn void QCustomPlot::axisClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event) - This signal is emitted when the selection state of this axis has changed, either by user interaction - or by a direct call to \ref setSelectedParts. + This signal is emitted when an axis is clicked. + + \a event is the mouse event that caused the click, \a axis is the axis that received the click and + \a part indicates the part of the axis that was clicked. + + \see axisDoubleClick */ -/*! \fn void QCPAxis::selectableChanged(const QCPAxis::SelectableParts &parts); +/*! \fn void QCustomPlot::axisDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event) + + This signal is emitted when an axis is double clicked. - This signal is emitted when the selectability changes, by calls to \ref setSelectableParts + \a event is the mouse event that caused the click, \a axis is the axis that received the click and + \a part indicates the part of the axis that was clicked. + + \see axisClick */ -/* end of documentation of signals */ +/*! \fn void QCustomPlot::legendClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event) -/*! - Constructs an Axis instance of Type \a type for the axis rect \a parent. + This signal is emitted when a legend (item) is clicked. - Usually it isn't necessary to instantiate axes directly, because you can let QCustomPlot create - them for you with \ref QCPAxisRect::addAxis. If you want to use own QCPAxis-subclasses however, - create them manually and then inject them also via \ref QCPAxisRect::addAxis. + \a event is the mouse event that caused the click, \a legend is the legend that received the + click and \a item is the legend item that received the click. If only the legend and no item is + clicked, \a item is \c nullptr. This happens for a click inside the legend padding or the space + between two items. + + \see legendDoubleClick */ -QCPAxis::QCPAxis(QCPAxisRect *parent, AxisType type) : - QCPLayerable(parent->parentPlot(), QString(), parent), - // axis base: - mAxisType(type), - mAxisRect(parent), - mPadding(5), - mOrientation(orientation(type)), - mSelectableParts(spAxis | spTickLabels | spAxisLabel), - mSelectedParts(spNone), - mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), - mSelectedBasePen(QPen(Qt::blue, 2)), - // axis label: - mLabel(), - mLabelFont(mParentPlot->font()), - mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)), - mLabelColor(Qt::black), - mSelectedLabelColor(Qt::blue), - // tick labels: - mTickLabels(true), - mAutoTickLabels(true), - mTickLabelType(ltNumber), - mTickLabelFont(mParentPlot->font()), - mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)), - mTickLabelColor(Qt::black), - mSelectedTickLabelColor(Qt::blue), - mDateTimeFormat(QLatin1String("hh:mm:ss\ndd.MM.yy")), - mDateTimeSpec(Qt::LocalTime), - mNumberPrecision(6), - mNumberFormatChar('g'), - mNumberBeautifulPowers(true), - // ticks and subticks: - mTicks(true), - mTickStep(1), - mSubTickCount(4), - mAutoTickCount(6), - mAutoTicks(true), - mAutoTickStep(true), - mAutoSubTicks(true), - mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), - mSelectedTickPen(QPen(Qt::blue, 2)), - mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), - mSelectedSubTickPen(QPen(Qt::blue, 2)), - // scale and range: - mRange(0, 5), - mRangeReversed(false), - mScaleType(stLinear), - mScaleLogBase(10), - mScaleLogBaseLogInv(1.0/qLn(mScaleLogBase)), - // internal members: - mGrid(new QCPGrid(this)), - mAxisPainter(new QCPAxisPainterPrivate(parent->parentPlot())), - mLowestVisibleTick(0), - mHighestVisibleTick(-1), - mCachedMarginValid(false), - mCachedMargin(0) -{ - mGrid->setVisible(false); - setAntialiased(false); - setLayer(mParentPlot->currentLayer()); // it's actually on that layer already, but we want it in front of the grid, so we place it on there again + +/*! \fn void QCustomPlot::legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event) + + This signal is emitted when a legend (item) is double clicked. + + \a event is the mouse event that caused the click, \a legend is the legend that received the + click and \a item is the legend item that received the click. If only the legend and no item is + clicked, \a item is \c nullptr. This happens for a click inside the legend padding or the space + between two items. + + \see legendClick +*/ + +/*! \fn void QCustomPlot::selectionChangedByUser() - if (type == atTop) - { - setTickLabelPadding(3); - setLabelPadding(6); - } else if (type == atRight) - { - setTickLabelPadding(7); - setLabelPadding(12); - } else if (type == atBottom) - { - setTickLabelPadding(3); - setLabelPadding(3); - } else if (type == atLeft) - { - setTickLabelPadding(5); - setLabelPadding(10); - } -} + This signal is emitted after the user has changed the selection in the QCustomPlot, e.g. by + clicking. It is not emitted when the selection state of an object has changed programmatically by + a direct call to setSelected()/setSelection() on an object or by calling \ref + deselectAll. + + In addition to this signal, selectable objects also provide individual signals, for example \ref + QCPAxis::selectionChanged or \ref QCPAbstractPlottable::selectionChanged. Note that those signals + are emitted even if the selection state is changed programmatically. + + See the documentation of \ref setInteractions for details about the selection mechanism. + + \see selectedPlottables, selectedGraphs, selectedItems, selectedAxes, selectedLegends +*/ -QCPAxis::~QCPAxis() -{ - delete mAxisPainter; - delete mGrid; // delete grid here instead of via parent ~QObject for better defined deletion order -} +/*! \fn void QCustomPlot::beforeReplot() + + This signal is emitted immediately before a replot takes place (caused by a call to the slot \ref + replot). + + It is safe to mutually connect the replot slot with this signal on two QCustomPlots to make them + replot synchronously, it won't cause an infinite recursion. + + \see replot, afterReplot, afterLayout +*/ -/* No documentation as it is a property getter */ -int QCPAxis::tickLabelPadding() const -{ - return mAxisPainter->tickLabelPadding; -} +/*! \fn void QCustomPlot::afterLayout() -/* No documentation as it is a property getter */ -double QCPAxis::tickLabelRotation() const -{ - return mAxisPainter->tickLabelRotation; -} + This signal is emitted immediately after the layout step has been completed, which occurs right + before drawing the plot. This is typically during a call to \ref replot, and in such cases this + signal is emitted in between the signals \ref beforeReplot and \ref afterReplot. Unlike those + signals however, this signal is also emitted during off-screen painting, such as when calling + \ref toPixmap or \ref savePdf. -/* No documentation as it is a property getter */ -QCPAxis::LabelSide QCPAxis::tickLabelSide() const -{ - return mAxisPainter->tickLabelSide; -} + The layout step queries all layouts and layout elements in the plot for their proposed size and + arranges the objects accordingly as preparation for the subsequent drawing step. Through this + signal, you have the opportunity to update certain things in your plot that depend crucially on + the exact dimensions/positioning of layout elements such as axes and axis rects. -/* No documentation as it is a property getter */ -QString QCPAxis::numberFormat() const -{ - QString result; - result.append(mNumberFormatChar); - if (mNumberBeautifulPowers) - { - result.append(QLatin1Char('b')); - if (mAxisPainter->numberMultiplyCross) - result.append(QLatin1Char('c')); - } - return result; -} + \warning However, changing any parameters of this QCustomPlot instance which would normally + affect the layouting (e.g. axis range order of magnitudes, tick label sizes, etc.) will not issue + a second run of the layout step. It will propagate directly to the draw step and may cause + graphical inconsistencies such as overlapping objects, if sizes or positions have changed. -/* No documentation as it is a property getter */ -int QCPAxis::tickLengthIn() const -{ - return mAxisPainter->tickLengthIn; -} + \see updateLayout, beforeReplot, afterReplot +*/ -/* No documentation as it is a property getter */ -int QCPAxis::tickLengthOut() const -{ - return mAxisPainter->tickLengthOut; -} +/*! \fn void QCustomPlot::afterReplot() + + This signal is emitted immediately after a replot has taken place (caused by a call to the slot \ref + replot). + + It is safe to mutually connect the replot slot with this signal on two QCustomPlots to make them + replot synchronously, it won't cause an infinite recursion. + + \see replot, beforeReplot, afterLayout +*/ -/* No documentation as it is a property getter */ -int QCPAxis::subTickLengthIn() const -{ - return mAxisPainter->subTickLengthIn; -} +/* end of documentation of signals */ +/* start of documentation of public members */ -/* No documentation as it is a property getter */ -int QCPAxis::subTickLengthOut() const -{ - return mAxisPainter->subTickLengthOut; -} +/*! \var QCPAxis *QCustomPlot::xAxis -/* No documentation as it is a property getter */ -int QCPAxis::labelPadding() const -{ - return mAxisPainter->labelPadding; -} + A pointer to the primary x Axis (bottom) of the main axis rect of the plot. + + QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref + yAxis2) and the \ref legend. They make it very easy working with plots that only have a single + axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the + layout system\endlink to add multiple axis rects or multiple axes to one side, use the \ref + QCPAxisRect::axis interface to access the new axes. If one of the four default axes or the + default legend is removed due to manipulation of the layout system (e.g. by removing the main + axis rect), the corresponding pointers become \c nullptr. + + If an axis convenience pointer is currently \c nullptr and a new axis rect or a corresponding + axis is added in the place of the main axis rect, QCustomPlot resets the convenience pointers to + the according new axes. Similarly the \ref legend convenience pointer will be reset if a legend + is added after the main legend was removed before. +*/ -/* No documentation as it is a property getter */ -int QCPAxis::offset() const -{ - return mAxisPainter->offset; -} +/*! \var QCPAxis *QCustomPlot::yAxis -/* No documentation as it is a property getter */ -QCPLineEnding QCPAxis::lowerEnding() const -{ - return mAxisPainter->lowerEnding; -} + A pointer to the primary y Axis (left) of the main axis rect of the plot. + + QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref + yAxis2) and the \ref legend. They make it very easy working with plots that only have a single + axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the + layout system\endlink to add multiple axis rects or multiple axes to one side, use the \ref + QCPAxisRect::axis interface to access the new axes. If one of the four default axes or the + default legend is removed due to manipulation of the layout system (e.g. by removing the main + axis rect), the corresponding pointers become \c nullptr. + + If an axis convenience pointer is currently \c nullptr and a new axis rect or a corresponding + axis is added in the place of the main axis rect, QCustomPlot resets the convenience pointers to + the according new axes. Similarly the \ref legend convenience pointer will be reset if a legend + is added after the main legend was removed before. +*/ -/* No documentation as it is a property getter */ -QCPLineEnding QCPAxis::upperEnding() const -{ - return mAxisPainter->upperEnding; -} +/*! \var QCPAxis *QCustomPlot::xAxis2 -/*! - Sets whether the axis uses a linear scale or a logarithmic scale. If \a type is set to \ref - stLogarithmic, the logarithm base can be set with \ref setScaleLogBase. In logarithmic axis - scaling, major tick marks appear at all powers of the logarithm base. Properties like tick step - (\ref setTickStep) don't apply in logarithmic scaling. If you wish a decimal base but less major - ticks, consider choosing a logarithm base of 100, 1000 or even higher. + A pointer to the secondary x Axis (top) of the main axis rect of the plot. Secondary axes are + invisible by default. Use QCPAxis::setVisible to change this (or use \ref + QCPAxisRect::setupFullAxesBox). + + QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref + yAxis2) and the \ref legend. They make it very easy working with plots that only have a single + axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the + layout system\endlink to add multiple axis rects or multiple axes to one side, use the \ref + QCPAxisRect::axis interface to access the new axes. If one of the four default axes or the + default legend is removed due to manipulation of the layout system (e.g. by removing the main + axis rect), the corresponding pointers become \c nullptr. - If \a type is \ref stLogarithmic and the number format (\ref setNumberFormat) uses the 'b' option - (beautifully typeset decimal powers), the display usually is "1 [multiplication sign] 10 - [superscript] n", which looks unnatural for logarithmic scaling (the "1 [multiplication sign]" - part). To only display the decimal power, set the number precision to zero with - \ref setNumberPrecision. + If an axis convenience pointer is currently \c nullptr and a new axis rect or a corresponding + axis is added in the place of the main axis rect, QCustomPlot resets the convenience pointers to + the according new axes. Similarly the \ref legend convenience pointer will be reset if a legend + is added after the main legend was removed before. */ -void QCPAxis::setScaleType(QCPAxis::ScaleType type) -{ - if (mScaleType != type) - { - mScaleType = type; - if (mScaleType == stLogarithmic) - setRange(mRange.sanitizedForLogScale()); - mCachedMarginValid = false; - emit scaleTypeChanged(mScaleType); - } -} -/*! - If \ref setScaleType is set to \ref stLogarithmic, \a base will be the logarithm base of the - scaling. In logarithmic axis scaling, major tick marks appear at all powers of \a base. +/*! \var QCPAxis *QCustomPlot::yAxis2 + + A pointer to the secondary y Axis (right) of the main axis rect of the plot. Secondary axes are + invisible by default. Use QCPAxis::setVisible to change this (or use \ref + QCPAxisRect::setupFullAxesBox). + + QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref + yAxis2) and the \ref legend. They make it very easy working with plots that only have a single + axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the + layout system\endlink to add multiple axis rects or multiple axes to one side, use the \ref + QCPAxisRect::axis interface to access the new axes. If one of the four default axes or the + default legend is removed due to manipulation of the layout system (e.g. by removing the main + axis rect), the corresponding pointers become \c nullptr. - Properties like tick step (\ref setTickStep) don't apply in logarithmic scaling. If you wish a decimal base but - less major ticks, consider choosing \a base 100, 1000 or even higher. + If an axis convenience pointer is currently \c nullptr and a new axis rect or a corresponding + axis is added in the place of the main axis rect, QCustomPlot resets the convenience pointers to + the according new axes. Similarly the \ref legend convenience pointer will be reset if a legend + is added after the main legend was removed before. */ -void QCPAxis::setScaleLogBase(double base) -{ - if (base > 1) - { - mScaleLogBase = base; - mScaleLogBaseLogInv = 1.0/qLn(mScaleLogBase); // buffer for faster baseLog() calculation - mCachedMarginValid = false; - } else - qDebug() << Q_FUNC_INFO << "Invalid logarithmic scale base (must be greater 1):" << base; -} + +/*! \var QCPLegend *QCustomPlot::legend + + A pointer to the default legend of the main axis rect. The legend is invisible by default. Use + QCPLegend::setVisible to change this. + + QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref + yAxis2) and the \ref legend. They make it very easy working with plots that only have a single + axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the + layout system\endlink to add multiple legends to the plot, use the layout system interface to + access the new legend. For example, legends can be placed inside an axis rect's \ref + QCPAxisRect::insetLayout "inset layout", and must then also be accessed via the inset layout. If + the default legend is removed due to manipulation of the layout system (e.g. by removing the main + axis rect), the corresponding pointer becomes \c nullptr. + + If an axis convenience pointer is currently \c nullptr and a new axis rect or a corresponding + axis is added in the place of the main axis rect, QCustomPlot resets the convenience pointers to + the according new axes. Similarly the \ref legend convenience pointer will be reset if a legend + is added after the main legend was removed before. +*/ + +/* end of documentation of public members */ /*! - Sets the range of the axis. + Constructs a QCustomPlot and sets reasonable default values. +*/ +QCustomPlot::QCustomPlot(QWidget *parent) : + QWidget(parent), + xAxis(nullptr), + yAxis(nullptr), + xAxis2(nullptr), + yAxis2(nullptr), + legend(nullptr), + mBufferDevicePixelRatio(1.0), // will be adapted to true value below + mPlotLayout(nullptr), + mAutoAddPlottableToLegend(true), + mAntialiasedElements(QCP::aeNone), + mNotAntialiasedElements(QCP::aeNone), + mInteractions(QCP::iNone), + mSelectionTolerance(8), + mNoAntialiasingOnDrag(false), + mBackgroundBrush(Qt::white, Qt::SolidPattern), + mBackgroundScaled(true), + mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding), + mCurrentLayer(nullptr), + mPlottingHints(QCP::phCacheLabels|QCP::phImmediateRefresh), + mMultiSelectModifier(Qt::ControlModifier), + mSelectionRectMode(QCP::srmNone), + mSelectionRect(nullptr), + mOpenGl(false), + mMouseHasMoved(false), + mMouseEventLayerable(nullptr), + mMouseSignalLayerable(nullptr), + mReplotting(false), + mReplotQueued(false), + mReplotTime(0), + mReplotTimeAverage(0), + mOpenGlMultisamples(16), + mOpenGlAntialiasedElementsBackup(QCP::aeNone), + mOpenGlCacheLabelsBackup(true) +{ + setAttribute(Qt::WA_NoMousePropagation); + setFocusPolicy(Qt::ClickFocus); + setMouseTracking(true); + QLocale currentLocale = locale(); + currentLocale.setNumberOptions(QLocale::OmitGroupSeparator); + setLocale(currentLocale); +#ifdef QCP_DEVICEPIXELRATIO_SUPPORTED +# ifdef QCP_DEVICEPIXELRATIO_FLOAT + setBufferDevicePixelRatio(QWidget::devicePixelRatioF()); +# else + setBufferDevicePixelRatio(QWidget::devicePixelRatio()); +# endif +#endif + + mOpenGlAntialiasedElementsBackup = mAntialiasedElements; + mOpenGlCacheLabelsBackup = mPlottingHints.testFlag(QCP::phCacheLabels); + // create initial layers: + mLayers.append(new QCPLayer(this, QLatin1String("background"))); + mLayers.append(new QCPLayer(this, QLatin1String("grid"))); + mLayers.append(new QCPLayer(this, QLatin1String("main"))); + mLayers.append(new QCPLayer(this, QLatin1String("axes"))); + mLayers.append(new QCPLayer(this, QLatin1String("legend"))); + mLayers.append(new QCPLayer(this, QLatin1String("overlay"))); + updateLayerIndices(); + setCurrentLayer(QLatin1String("main")); + layer(QLatin1String("overlay"))->setMode(QCPLayer::lmBuffered); + + // create initial layout, axis rect and legend: + mPlotLayout = new QCPLayoutGrid; + mPlotLayout->initializeParentPlot(this); + mPlotLayout->setParent(this); // important because if parent is QWidget, QCPLayout::sizeConstraintsChanged will call QWidget::updateGeometry + mPlotLayout->setLayer(QLatin1String("main")); + QCPAxisRect *defaultAxisRect = new QCPAxisRect(this, true); + mPlotLayout->addElement(0, 0, defaultAxisRect); + xAxis = defaultAxisRect->axis(QCPAxis::atBottom); + yAxis = defaultAxisRect->axis(QCPAxis::atLeft); + xAxis2 = defaultAxisRect->axis(QCPAxis::atTop); + yAxis2 = defaultAxisRect->axis(QCPAxis::atRight); + legend = new QCPLegend; + legend->setVisible(false); + defaultAxisRect->insetLayout()->addElement(legend, Qt::AlignRight|Qt::AlignTop); + defaultAxisRect->insetLayout()->setMargins(QMargins(12, 12, 12, 12)); + + defaultAxisRect->setLayer(QLatin1String("background")); + xAxis->setLayer(QLatin1String("axes")); + yAxis->setLayer(QLatin1String("axes")); + xAxis2->setLayer(QLatin1String("axes")); + yAxis2->setLayer(QLatin1String("axes")); + xAxis->grid()->setLayer(QLatin1String("grid")); + yAxis->grid()->setLayer(QLatin1String("grid")); + xAxis2->grid()->setLayer(QLatin1String("grid")); + yAxis2->grid()->setLayer(QLatin1String("grid")); + legend->setLayer(QLatin1String("legend")); - This slot may be connected with the \ref rangeChanged signal of another axis so this axis - is always synchronized with the other axis range, when it changes. + // create selection rect instance: + mSelectionRect = new QCPSelectionRect(this); + mSelectionRect->setLayer(QLatin1String("overlay")); - To invert the direction of an axis, use \ref setRangeReversed. -*/ -void QCPAxis::setRange(const QCPRange &range) -{ - if (range.lower == mRange.lower && range.upper == mRange.upper) - return; + setViewport(rect()); // needs to be called after mPlotLayout has been created - if (!QCPRange::validRange(range)) return; - QCPRange oldRange = mRange; - if (mScaleType == stLogarithmic) - { - mRange = range.sanitizedForLogScale(); - } else - { - mRange = range.sanitizedForLinScale(); - } - mCachedMarginValid = false; - emit rangeChanged(mRange); - emit rangeChanged(mRange, oldRange); + replot(rpQueuedReplot); } -/*! - Sets whether the user can (de-)select the parts in \a selectable by clicking on the QCustomPlot surface. - (When \ref QCustomPlot::setInteractions contains iSelectAxes.) - - However, even when \a selectable is set to a value not allowing the selection of a specific part, - it is still possible to set the selection of this part manually, by calling \ref setSelectedParts - directly. - - \see SelectablePart, setSelectedParts -*/ -void QCPAxis::setSelectableParts(const SelectableParts &selectable) +QCustomPlot::~QCustomPlot() { - if (mSelectableParts != selectable) + clearPlottables(); + clearItems(); + + if (mPlotLayout) { - mSelectableParts = selectable; - emit selectableChanged(mSelectableParts); + delete mPlotLayout; + mPlotLayout = nullptr; } + + mCurrentLayer = nullptr; + qDeleteAll(mLayers); // don't use removeLayer, because it would prevent the last layer to be removed + mLayers.clear(); } /*! - Sets the selected state of the respective axis parts described by \ref SelectablePart. When a part - is selected, it uses a different pen/font. + Sets which elements are forcibly drawn antialiased as an \a or combination of QCP::AntialiasedElement. - The entire selection mechanism for axes is handled automatically when \ref - QCustomPlot::setInteractions contains iSelectAxes. You only need to call this function when you - wish to change the selection state manually. + This overrides the antialiasing settings for whole element groups, normally controlled with the + \a setAntialiasing function on the individual elements. If an element is neither specified in + \ref setAntialiasedElements nor in \ref setNotAntialiasedElements, the antialiasing setting on + each individual element instance is used. - This function can change the selection state of a part, independent of the \ref setSelectableParts setting. + For example, if \a antialiasedElements contains \ref QCP::aePlottables, all plottables will be + drawn antialiased, no matter what the specific QCPAbstractPlottable::setAntialiased value was set + to. - emits the \ref selectionChanged signal when \a selected is different from the previous selection state. + if an element in \a antialiasedElements is already set in \ref setNotAntialiasedElements, it is + removed from there. - \see SelectablePart, setSelectableParts, selectTest, setSelectedBasePen, setSelectedTickPen, setSelectedSubTickPen, - setSelectedTickLabelFont, setSelectedLabelFont, setSelectedTickLabelColor, setSelectedLabelColor + \see setNotAntialiasedElements */ -void QCPAxis::setSelectedParts(const SelectableParts &selected) +void QCustomPlot::setAntialiasedElements(const QCP::AntialiasedElements &antialiasedElements) { - if (mSelectedParts != selected) - { - mSelectedParts = selected; - emit selectionChanged(mSelectedParts); - } + mAntialiasedElements = antialiasedElements; + + // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: + if ((mNotAntialiasedElements & mAntialiasedElements) != 0) + mNotAntialiasedElements |= ~mAntialiasedElements; } /*! - \overload - - Sets the lower and upper bound of the axis range. + Sets whether the specified \a antialiasedElement is forcibly drawn antialiased. - To invert the direction of an axis, use \ref setRangeReversed. + See \ref setAntialiasedElements for details. - There is also a slot to set a range, see \ref setRange(const QCPRange &range). + \see setNotAntialiasedElement */ -void QCPAxis::setRange(double lower, double upper) +void QCustomPlot::setAntialiasedElement(QCP::AntialiasedElement antialiasedElement, bool enabled) { - if (lower == mRange.lower && upper == mRange.upper) - return; + if (!enabled && mAntialiasedElements.testFlag(antialiasedElement)) + mAntialiasedElements &= ~antialiasedElement; + else if (enabled && !mAntialiasedElements.testFlag(antialiasedElement)) + mAntialiasedElements |= antialiasedElement; - if (!QCPRange::validRange(lower, upper)) return; - QCPRange oldRange = mRange; - mRange.lower = lower; - mRange.upper = upper; - if (mScaleType == stLogarithmic) - { - mRange = mRange.sanitizedForLogScale(); - } else - { - mRange = mRange.sanitizedForLinScale(); - } - mCachedMarginValid = false; - emit rangeChanged(mRange); - emit rangeChanged(mRange, oldRange); + // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: + if ((mNotAntialiasedElements & mAntialiasedElements) != 0) + mNotAntialiasedElements |= ~mAntialiasedElements; } /*! - \overload + Sets which elements are forcibly drawn not antialiased as an \a or combination of + QCP::AntialiasedElement. - Sets the range of the axis. + This overrides the antialiasing settings for whole element groups, normally controlled with the + \a setAntialiasing function on the individual elements. If an element is neither specified in + \ref setAntialiasedElements nor in \ref setNotAntialiasedElements, the antialiasing setting on + each individual element instance is used. - The \a position coordinate indicates together with the \a alignment parameter, where the new - range will be positioned. \a size defines the size of the new axis range. \a alignment may be - Qt::AlignLeft, Qt::AlignRight or Qt::AlignCenter. This will cause the left border, right border, - or center of the range to be aligned with \a position. Any other values of \a alignment will - default to Qt::AlignCenter. -*/ -void QCPAxis::setRange(double position, double size, Qt::AlignmentFlag alignment) -{ - if (alignment == Qt::AlignLeft) - setRange(position, position+size); - else if (alignment == Qt::AlignRight) - setRange(position-size, position); - else // alignment == Qt::AlignCenter - setRange(position-size/2.0, position+size/2.0); -} - -/*! - Sets the lower bound of the axis range. The upper bound is not changed. - \see setRange + For example, if \a notAntialiasedElements contains \ref QCP::aePlottables, no plottables will be + drawn antialiased, no matter what the specific QCPAbstractPlottable::setAntialiased value was set + to. + + if an element in \a notAntialiasedElements is already set in \ref setAntialiasedElements, it is + removed from there. + + \see setAntialiasedElements */ -void QCPAxis::setRangeLower(double lower) +void QCustomPlot::setNotAntialiasedElements(const QCP::AntialiasedElements ¬AntialiasedElements) { - if (mRange.lower == lower) - return; + mNotAntialiasedElements = notAntialiasedElements; - QCPRange oldRange = mRange; - mRange.lower = lower; - if (mScaleType == stLogarithmic) - { - mRange = mRange.sanitizedForLogScale(); - } else - { - mRange = mRange.sanitizedForLinScale(); - } - mCachedMarginValid = false; - emit rangeChanged(mRange); - emit rangeChanged(mRange, oldRange); + // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: + if ((mNotAntialiasedElements & mAntialiasedElements) != 0) + mAntialiasedElements |= ~mNotAntialiasedElements; } /*! - Sets the upper bound of the axis range. The lower bound is not changed. - \see setRange + Sets whether the specified \a notAntialiasedElement is forcibly drawn not antialiased. + + See \ref setNotAntialiasedElements for details. + + \see setAntialiasedElement */ -void QCPAxis::setRangeUpper(double upper) +void QCustomPlot::setNotAntialiasedElement(QCP::AntialiasedElement notAntialiasedElement, bool enabled) { - if (mRange.upper == upper) - return; + if (!enabled && mNotAntialiasedElements.testFlag(notAntialiasedElement)) + mNotAntialiasedElements &= ~notAntialiasedElement; + else if (enabled && !mNotAntialiasedElements.testFlag(notAntialiasedElement)) + mNotAntialiasedElements |= notAntialiasedElement; - QCPRange oldRange = mRange; - mRange.upper = upper; - if (mScaleType == stLogarithmic) - { - mRange = mRange.sanitizedForLogScale(); - } else - { - mRange = mRange.sanitizedForLinScale(); - } - mCachedMarginValid = false; - emit rangeChanged(mRange); - emit rangeChanged(mRange, oldRange); + // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: + if ((mNotAntialiasedElements & mAntialiasedElements) != 0) + mAntialiasedElements |= ~mNotAntialiasedElements; } /*! - Sets whether the axis range (direction) is displayed reversed. Normally, the values on horizontal - axes increase left to right, on vertical axes bottom to top. When \a reversed is set to true, the - direction of increasing values is inverted. - - Note that the range and data interface stays the same for reversed axes, e.g. the \a lower part - of the \ref setRange interface will still reference the mathematically smaller number than the \a - upper part. + If set to true, adding a plottable (e.g. a graph) to the QCustomPlot automatically also adds the + plottable to the legend (QCustomPlot::legend). + + \see addGraph, QCPLegend::addItem */ -void QCPAxis::setRangeReversed(bool reversed) +void QCustomPlot::setAutoAddPlottableToLegend(bool on) { - if (mRangeReversed != reversed) - { - mRangeReversed = reversed; - mCachedMarginValid = false; - } + mAutoAddPlottableToLegend = on; } /*! - Sets whether the tick positions should be calculated automatically (either from an automatically - generated tick step or a tick step provided manually via \ref setTickStep, see \ref setAutoTickStep). + Sets the possible interactions of this QCustomPlot as an or-combination of \ref QCP::Interaction + enums. There are the following types of interactions: - If \a on is set to false, you must provide the tick positions manually via \ref setTickVector. - For these manual ticks you may let QCPAxis generate the appropriate labels automatically by - leaving \ref setAutoTickLabels set to true. If you also wish to control the displayed labels - manually, set \ref setAutoTickLabels to false and provide the label strings with \ref - setTickVectorLabels. + Axis range manipulation is controlled via \ref QCP::iRangeDrag and \ref QCP::iRangeZoom. When the + respective interaction is enabled, the user may drag axes ranges and zoom with the mouse wheel. + For details how to control which axes the user may drag/zoom and in what orientations, see \ref + QCPAxisRect::setRangeDrag, \ref QCPAxisRect::setRangeZoom, \ref QCPAxisRect::setRangeDragAxes, + \ref QCPAxisRect::setRangeZoomAxes. - If you need dynamically calculated tick vectors (and possibly tick label vectors), set the - vectors in a slot connected to the \ref ticksRequest signal. + Plottable data selection is controlled by \ref QCP::iSelectPlottables. If \ref + QCP::iSelectPlottables is set, the user may select plottables (graphs, curves, bars,...) and + their data by clicking on them or in their vicinity (\ref setSelectionTolerance). Whether the + user can actually select a plottable and its data can further be restricted with the \ref + QCPAbstractPlottable::setSelectable method on the specific plottable. For details, see the + special page about the \ref dataselection "data selection mechanism". To retrieve a list of all + currently selected plottables, call \ref selectedPlottables. If you're only interested in + QCPGraphs, you may use the convenience function \ref selectedGraphs. - \see setAutoTickLabels, setAutoSubTicks, setAutoTickCount, setAutoTickStep -*/ -void QCPAxis::setAutoTicks(bool on) -{ - if (mAutoTicks != on) - { - mAutoTicks = on; - mCachedMarginValid = false; - } -} - -/*! - When \ref setAutoTickStep is true, \a approximateCount determines how many ticks should be - generated in the visible range, approximately. + Item selection is controlled by \ref QCP::iSelectItems. If \ref QCP::iSelectItems is set, the user + may select items (QCPItemLine, QCPItemText,...) by clicking on them or in their vicinity. To find + out whether a specific item is selected, call QCPAbstractItem::selected(). To retrieve a list of + all currently selected items, call \ref selectedItems. - It's not guaranteed that this number of ticks is met exactly, but approximately within a - tolerance of about two. + Axis selection is controlled with \ref QCP::iSelectAxes. If \ref QCP::iSelectAxes is set, the user + may select parts of the axes by clicking on them. What parts exactly (e.g. Axis base line, tick + labels, axis label) are selectable can be controlled via \ref QCPAxis::setSelectableParts for + each axis. To retrieve a list of all axes that currently contain selected parts, call \ref + selectedAxes. Which parts of an axis are selected, can be retrieved with QCPAxis::selectedParts(). - Only values greater than zero are accepted as \a approximateCount. + Legend selection is controlled with \ref QCP::iSelectLegend. If this is set, the user may + select the legend itself or individual items by clicking on them. What parts exactly are + selectable can be controlled via \ref QCPLegend::setSelectableParts. To find out whether the + legend or any of its child items are selected, check the value of QCPLegend::selectedParts. To + find out which child items are selected, call \ref QCPLegend::selectedItems. - \see setAutoTickStep, setAutoTicks, setAutoSubTicks -*/ -void QCPAxis::setAutoTickCount(int approximateCount) -{ - if (mAutoTickCount != approximateCount) - { - if (approximateCount > 0) - { - mAutoTickCount = approximateCount; - mCachedMarginValid = false; - } else - qDebug() << Q_FUNC_INFO << "approximateCount must be greater than zero:" << approximateCount; - } -} - -/*! - Sets whether the tick labels are generated automatically. Depending on the tick label type (\ref - ltNumber or \ref ltDateTime), the labels will either show the coordinate as floating point - number (\ref setNumberFormat), or a date/time formatted according to \ref setDateTimeFormat. + All other selectable elements The selection of all other selectable objects (e.g. + QCPTextElement, or your own layerable subclasses) is controlled with \ref QCP::iSelectOther. If set, the + user may select those objects by clicking on them. To find out which are currently selected, you + need to check their selected state explicitly. - If \a on is set to false, you should provide the tick labels via \ref setTickVectorLabels. This - is usually used in a combination with \ref setAutoTicks set to false for complete control over - tick positions and labels, e.g. when the ticks should be at multiples of pi and show "2pi", "3pi" - etc. as tick labels. + If the selection state has changed by user interaction, the \ref selectionChangedByUser signal is + emitted. Each selectable object additionally emits an individual selectionChanged signal whenever + their selection state has changed, i.e. not only by user interaction. + + To allow multiple objects to be selected by holding the selection modifier (\ref + setMultiSelectModifier), set the flag \ref QCP::iMultiSelect. - If you need dynamically calculated tick vectors (and possibly tick label vectors), set the - vectors in a slot connected to the \ref ticksRequest signal. + \note In addition to the selection mechanism presented here, QCustomPlot always emits + corresponding signals, when an object is clicked or double clicked. see \ref plottableClick and + \ref plottableDoubleClick for example. - \see setAutoTicks + \see setInteraction, setSelectionTolerance */ -void QCPAxis::setAutoTickLabels(bool on) +void QCustomPlot::setInteractions(const QCP::Interactions &interactions) { - if (mAutoTickLabels != on) - { - mAutoTickLabels = on; - mCachedMarginValid = false; - } + mInteractions = interactions; } /*! - Sets whether the tick step, i.e. the interval between two (major) ticks, is calculated - automatically. If \a on is set to true, the axis finds a tick step that is reasonable for human - readable plots. - - The number of ticks the algorithm aims for within the visible range can be specified with \ref - setAutoTickCount. + Sets the single \a interaction of this QCustomPlot to \a enabled. - If \a on is set to false, you may set the tick step manually with \ref setTickStep. + For details about the interaction system, see \ref setInteractions. - \see setAutoTicks, setAutoSubTicks, setAutoTickCount + \see setInteractions */ -void QCPAxis::setAutoTickStep(bool on) +void QCustomPlot::setInteraction(const QCP::Interaction &interaction, bool enabled) { - if (mAutoTickStep != on) - { - mAutoTickStep = on; - mCachedMarginValid = false; - } + if (!enabled && mInteractions.testFlag(interaction)) + mInteractions &= ~interaction; + else if (enabled && !mInteractions.testFlag(interaction)) + mInteractions |= interaction; } /*! - Sets whether the number of sub ticks in one tick interval is determined automatically. This - works, as long as the tick step mantissa is a multiple of 0.5. When \ref setAutoTickStep is - enabled, this is always the case. + Sets the tolerance that is used to decide whether a click selects an object (e.g. a plottable) or + not. - When \a on is set to false, you may set the sub tick count with \ref setSubTickCount manually. + If the user clicks in the vicinity of the line of e.g. a QCPGraph, it's only regarded as a + potential selection when the minimum distance between the click position and the graph line is + smaller than \a pixels. Objects that are defined by an area (e.g. QCPBars) only react to clicks + directly inside the area and ignore this selection tolerance. In other words, it only has meaning + for parts of objects that are too thin to exactly hit with a click and thus need such a + tolerance. - \see setAutoTickCount, setAutoTicks, setAutoTickStep + \see setInteractions, QCPLayerable::selectTest */ -void QCPAxis::setAutoSubTicks(bool on) +void QCustomPlot::setSelectionTolerance(int pixels) { - if (mAutoSubTicks != on) - { - mAutoSubTicks = on; - mCachedMarginValid = false; - } + mSelectionTolerance = pixels; } /*! - Sets whether tick marks are displayed. - - Note that setting \a show to false does not imply that tick labels are invisible, too. To achieve - that, see \ref setTickLabels. + Sets whether antialiasing is disabled for this QCustomPlot while the user is dragging axes + ranges. If many objects, especially plottables, are drawn antialiased, this greatly improves + performance during dragging. Thus it creates a more responsive user experience. As soon as the + user stops dragging, the last replot is done with normal antialiasing, to restore high image + quality. + + \see setAntialiasedElements, setNotAntialiasedElements */ -void QCPAxis::setTicks(bool show) +void QCustomPlot::setNoAntialiasingOnDrag(bool enabled) { - if (mTicks != show) - { - mTicks = show; - mCachedMarginValid = false; - } + mNoAntialiasingOnDrag = enabled; } /*! - Sets whether tick labels are displayed. Tick labels are the numbers drawn next to tick marks. + Sets the plotting hints for this QCustomPlot instance as an \a or combination of QCP::PlottingHint. + + \see setPlottingHint */ -void QCPAxis::setTickLabels(bool show) +void QCustomPlot::setPlottingHints(const QCP::PlottingHints &hints) { - if (mTickLabels != show) - { - mTickLabels = show; - mCachedMarginValid = false; - } + mPlottingHints = hints; } /*! - Sets the distance between the axis base line (including any outward ticks) and the tick labels. - \see setLabelPadding, setPadding + Sets the specified plotting \a hint to \a enabled. + + \see setPlottingHints */ -void QCPAxis::setTickLabelPadding(int padding) +void QCustomPlot::setPlottingHint(QCP::PlottingHint hint, bool enabled) { - if (mAxisPainter->tickLabelPadding != padding) - { - mAxisPainter->tickLabelPadding = padding; - mCachedMarginValid = false; - } + QCP::PlottingHints newHints = mPlottingHints; + if (!enabled) + newHints &= ~hint; + else + newHints |= hint; + + if (newHints != mPlottingHints) + setPlottingHints(newHints); } /*! - Sets whether the tick labels display numbers or dates/times. - - If \a type is set to \ref ltNumber, the format specifications of \ref setNumberFormat apply. - - If \a type is set to \ref ltDateTime, the format specifications of \ref setDateTimeFormat apply. + Sets the keyboard modifier that will be recognized as multi-select-modifier. - In QCustomPlot, date/time coordinates are double numbers representing the seconds since - 1970-01-01T00:00:00 UTC. This format can be retrieved from QDateTime objects with the - QDateTime::toTime_t() function. Since this only gives a resolution of one second, there is also - the QDateTime::toMSecsSinceEpoch() function which returns the timespan described above in - milliseconds. Divide its return value by 1000.0 to get a value with the format needed for - date/time plotting, with a resolution of one millisecond. + If \ref QCP::iMultiSelect is specified in \ref setInteractions, the user may select multiple + objects (or data points) by clicking on them one after the other while holding down \a modifier. - Using the toMSecsSinceEpoch function allows dates that go back to 2nd January 4713 B.C. - (represented by a negative number), unlike the toTime_t function, which works with unsigned - integers and thus only goes back to 1st January 1970. So both for range and accuracy, use of - toMSecsSinceEpoch()/1000.0 should be preferred as key coordinate for date/time axes. + By default the multi-select-modifier is set to Qt::ControlModifier. - \see setTickLabels + \see setInteractions */ -void QCPAxis::setTickLabelType(LabelType type) +void QCustomPlot::setMultiSelectModifier(Qt::KeyboardModifier modifier) { - if (mTickLabelType != type) - { - mTickLabelType = type; - mCachedMarginValid = false; - } + mMultiSelectModifier = modifier; } /*! - Sets the font of the tick labels. + Sets how QCustomPlot processes mouse click-and-drag interactions by the user. + + If \a mode is \ref QCP::srmNone, the mouse drag is forwarded to the underlying objects. For + example, QCPAxisRect may process a mouse drag by dragging axis ranges, see \ref + QCPAxisRect::setRangeDrag. If \a mode is not \ref QCP::srmNone, the current selection rect (\ref + selectionRect) becomes activated and allows e.g. rect zooming and data point selection. - \see setTickLabels, setTickLabelColor + If you wish to provide your user both with axis range dragging and data selection/range zooming, + use this method to switch between the modes just before the interaction is processed, e.g. in + reaction to the \ref mousePress or \ref mouseMove signals. For example you could check whether + the user is holding a certain keyboard modifier, and then decide which \a mode shall be set. + + If a selection rect interaction is currently active, and \a mode is set to \ref QCP::srmNone, the + interaction is canceled (\ref QCPSelectionRect::cancel). Switching between any of the other modes + will keep the selection rect active. Upon completion of the interaction, the behaviour is as + defined by the currently set \a mode, not the mode that was set when the interaction started. + + \see setInteractions, setSelectionRect, QCPSelectionRect */ -void QCPAxis::setTickLabelFont(const QFont &font) +void QCustomPlot::setSelectionRectMode(QCP::SelectionRectMode mode) { - if (font != mTickLabelFont) + if (mSelectionRect) { - mTickLabelFont = font; - mCachedMarginValid = false; + if (mode == QCP::srmNone) + mSelectionRect->cancel(); // when switching to none, we immediately want to abort a potentially active selection rect + + // disconnect old connections: + if (mSelectionRectMode == QCP::srmSelect) + disconnect(mSelectionRect, SIGNAL(accepted(QRect,QMouseEvent*)), this, SLOT(processRectSelection(QRect,QMouseEvent*))); + else if (mSelectionRectMode == QCP::srmZoom) + disconnect(mSelectionRect, SIGNAL(accepted(QRect,QMouseEvent*)), this, SLOT(processRectZoom(QRect,QMouseEvent*))); + + // establish new ones: + if (mode == QCP::srmSelect) + connect(mSelectionRect, SIGNAL(accepted(QRect,QMouseEvent*)), this, SLOT(processRectSelection(QRect,QMouseEvent*))); + else if (mode == QCP::srmZoom) + connect(mSelectionRect, SIGNAL(accepted(QRect,QMouseEvent*)), this, SLOT(processRectZoom(QRect,QMouseEvent*))); } + + mSelectionRectMode = mode; } /*! - Sets the color of the tick labels. + Sets the \ref QCPSelectionRect instance that QCustomPlot will use if \a mode is not \ref + QCP::srmNone and the user performs a click-and-drag interaction. QCustomPlot takes ownership of + the passed \a selectionRect. It can be accessed later via \ref selectionRect. - \see setTickLabels, setTickLabelFont + This method is useful if you wish to replace the default QCPSelectionRect instance with an + instance of a QCPSelectionRect subclass, to introduce custom behaviour of the selection rect. + + \see setSelectionRectMode */ -void QCPAxis::setTickLabelColor(const QColor &color) +void QCustomPlot::setSelectionRect(QCPSelectionRect *selectionRect) { - if (color != mTickLabelColor) + delete mSelectionRect; + + mSelectionRect = selectionRect; + + if (mSelectionRect) { - mTickLabelColor = color; - mCachedMarginValid = false; + // establish connections with new selection rect: + if (mSelectionRectMode == QCP::srmSelect) + connect(mSelectionRect, SIGNAL(accepted(QRect,QMouseEvent*)), this, SLOT(processRectSelection(QRect,QMouseEvent*))); + else if (mSelectionRectMode == QCP::srmZoom) + connect(mSelectionRect, SIGNAL(accepted(QRect,QMouseEvent*)), this, SLOT(processRectZoom(QRect,QMouseEvent*))); } } /*! - Sets the rotation of the tick labels. If \a degrees is zero, the labels are drawn normally. Else, - the tick labels are drawn rotated by \a degrees clockwise. The specified angle is bound to values - from -90 to 90 degrees. + \warning This is still an experimental feature and its performance depends on the system that it + runs on. Having multiple QCustomPlot widgets in one application with enabled OpenGL rendering + might cause context conflicts on some systems. - If \a degrees is exactly -90, 0 or 90, the tick labels are centered on the tick coordinate. For - other angles, the label is drawn with an offset such that it seems to point toward or away from - the tick mark. + This method allows to enable OpenGL plot rendering, for increased plotting performance of + graphically demanding plots (thick lines, translucent fills, etc.). + + If \a enabled is set to true, QCustomPlot will try to initialize OpenGL and, if successful, + continue plotting with hardware acceleration. The parameter \a multisampling controls how many + samples will be used per pixel, it essentially controls the antialiasing quality. If \a + multisampling is set too high for the current graphics hardware, the maximum allowed value will + be used. + + You can test whether switching to OpenGL rendering was successful by checking whether the + according getter \a QCustomPlot::openGl() returns true. If the OpenGL initialization fails, + rendering continues with the regular software rasterizer, and an according qDebug output is + generated. + + If switching to OpenGL was successful, this method disables label caching (\ref setPlottingHint + "setPlottingHint(QCP::phCacheLabels, false)") and turns on QCustomPlot's antialiasing override + for all elements (\ref setAntialiasedElements "setAntialiasedElements(QCP::aeAll)"), leading to a + higher quality output. The antialiasing override allows for pixel-grid aligned drawing in the + OpenGL paint device. As stated before, in OpenGL rendering the actual antialiasing of the plot is + controlled with \a multisampling. If \a enabled is set to false, the antialiasing/label caching + settings are restored to what they were before OpenGL was enabled, if they weren't altered in the + meantime. + + \note OpenGL support is only enabled if QCustomPlot is compiled with the macro \c QCUSTOMPLOT_USE_OPENGL + defined. This define must be set before including the QCustomPlot header both during compilation + of the QCustomPlot library as well as when compiling your application. It is best to just include + the line DEFINES += QCUSTOMPLOT_USE_OPENGL in the respective qmake project files. + \note If you are using a Qt version before 5.0, you must also add the module "opengl" to your \c + QT variable in the qmake project files. For Qt versions 5.0 and higher, QCustomPlot switches to a + newer OpenGL interface which is already in the "gui" module. */ -void QCPAxis::setTickLabelRotation(double degrees) +void QCustomPlot::setOpenGl(bool enabled, int multisampling) { - if (!qFuzzyIsNull(degrees-mAxisPainter->tickLabelRotation)) + mOpenGlMultisamples = qMax(0, multisampling); +#ifdef QCUSTOMPLOT_USE_OPENGL + mOpenGl = enabled; + if (mOpenGl) { - mAxisPainter->tickLabelRotation = qBound(-90.0, degrees, 90.0); - mCachedMarginValid = false; + if (setupOpenGl()) + { + // backup antialiasing override and labelcaching setting so we can restore upon disabling OpenGL + mOpenGlAntialiasedElementsBackup = mAntialiasedElements; + mOpenGlCacheLabelsBackup = mPlottingHints.testFlag(QCP::phCacheLabels); + // set antialiasing override to antialias all (aligns gl pixel grid properly), and disable label caching (would use software rasterizer for pixmap caches): + setAntialiasedElements(QCP::aeAll); + setPlottingHint(QCP::phCacheLabels, false); + } else + { + qDebug() << Q_FUNC_INFO << "Failed to enable OpenGL, continuing plotting without hardware acceleration."; + mOpenGl = false; + } + } else + { + // restore antialiasing override and labelcaching to what it was before enabling OpenGL, if nobody changed it in the meantime: + if (mAntialiasedElements == QCP::aeAll) + setAntialiasedElements(mOpenGlAntialiasedElementsBackup); + if (!mPlottingHints.testFlag(QCP::phCacheLabels)) + setPlottingHint(QCP::phCacheLabels, mOpenGlCacheLabelsBackup); + freeOpenGl(); } + // recreate all paint buffers: + mPaintBuffers.clear(); + setupPaintBuffers(); +#else + Q_UNUSED(enabled) + qDebug() << Q_FUNC_INFO << "QCustomPlot can't use OpenGL because QCUSTOMPLOT_USE_OPENGL was not defined during compilation (add 'DEFINES += QCUSTOMPLOT_USE_OPENGL' to your qmake .pro file)"; +#endif } /*! - Sets whether the tick labels (numbers) shall appear inside or outside the axis rect. - - The usual and default setting is \ref lsOutside. Very compact plots sometimes require tick labels - to be inside the axis rect, to save space. If \a side is set to \ref lsInside, the tick labels - appear on the inside are additionally clipped to the axis rect. + Sets the viewport of this QCustomPlot. Usually users of QCustomPlot don't need to change the + viewport manually. + + The viewport is the area in which the plot is drawn. All mechanisms, e.g. margin calculation take + the viewport to be the outer border of the plot. The viewport normally is the rect() of the + QCustomPlot widget, i.e. a rect with top left (0, 0) and size of the QCustomPlot widget. + + Don't confuse the viewport with the axis rect (QCustomPlot::axisRect). An axis rect is typically + an area enclosed by four axes, where the graphs/plottables are drawn in. The viewport is larger + and contains also the axes themselves, their tick numbers, their labels, or even additional axis + rects, color scales and other layout elements. + + This function is used to allow arbitrary size exports with \ref toPixmap, \ref savePng, \ref + savePdf, etc. by temporarily changing the viewport size. */ -void QCPAxis::setTickLabelSide(LabelSide side) +void QCustomPlot::setViewport(const QRect &rect) { - mAxisPainter->tickLabelSide = side; - mCachedMarginValid = false; + mViewport = rect; + if (mPlotLayout) + mPlotLayout->setOuterRect(mViewport); } /*! - Sets the format in which dates and times are displayed as tick labels, if \ref setTickLabelType is \ref ltDateTime. - for details about the \a format string, see the documentation of QDateTime::toString(). - - Newlines can be inserted with "\n". - - \see setDateTimeSpec + Sets the device pixel ratio used by the paint buffers of this QCustomPlot instance. + + Normally, this doesn't need to be set manually, because it is initialized with the regular \a + QWidget::devicePixelRatio which is configured by Qt to fit the display device (e.g. 1 for normal + displays, 2 for High-DPI displays). + + Device pixel ratios are supported by Qt only for Qt versions since 5.4. If this method is called + when QCustomPlot is being used with older Qt versions, outputs an according qDebug message and + leaves the internal buffer device pixel ratio at 1.0. */ -void QCPAxis::setDateTimeFormat(const QString &format) +void QCustomPlot::setBufferDevicePixelRatio(double ratio) { - if (mDateTimeFormat != format) + if (!qFuzzyCompare(ratio, mBufferDevicePixelRatio)) { - mDateTimeFormat = format; - mCachedMarginValid = false; +#ifdef QCP_DEVICEPIXELRATIO_SUPPORTED + mBufferDevicePixelRatio = ratio; + foreach (QSharedPointer buffer, mPaintBuffers) + buffer->setDevicePixelRatio(mBufferDevicePixelRatio); + // Note: axis label cache has devicePixelRatio as part of cache hash, so no need to manually clear cache here +#else + qDebug() << Q_FUNC_INFO << "Device pixel ratios not supported for Qt versions before 5.4"; + mBufferDevicePixelRatio = 1.0; +#endif } } /*! - Sets the time spec that is used for the date time values when \ref setTickLabelType is \ref - ltDateTime. + Sets \a pm as the viewport background pixmap (see \ref setViewport). The pixmap is always drawn + below all other objects in the plot. - The default value of QDateTime objects (and also QCustomPlot) is Qt::LocalTime. However, - if the date time values passed to QCustomPlot are given in the UTC spec, set \a - timeSpec to Qt::UTC to get the correct axis labels. + For cases where the provided pixmap doesn't have the same size as the viewport, scaling can be + enabled with \ref setBackgroundScaled and the scaling mode (whether and how the aspect ratio is + preserved) can be set with \ref setBackgroundScaledMode. To set all these options in one call, + consider using the overloaded version of this function. - \see setDateTimeFormat + If a background brush was set with \ref setBackground(const QBrush &brush), the viewport will + first be filled with that brush, before drawing the background pixmap. This can be useful for + background pixmaps with translucent areas. + + \see setBackgroundScaled, setBackgroundScaledMode */ -void QCPAxis::setDateTimeSpec(const Qt::TimeSpec &timeSpec) +void QCustomPlot::setBackground(const QPixmap &pm) { - mDateTimeSpec = timeSpec; + mBackgroundPixmap = pm; + mScaledBackgroundPixmap = QPixmap(); } /*! - Sets the number format for the numbers drawn as tick labels (if tick label type is \ref - ltNumber). This \a formatCode is an extended version of the format code used e.g. by - QString::number() and QLocale::toString(). For reference about that, see the "Argument Formats" - section in the detailed description of the QString class. \a formatCode is a string of one, two - or three characters. The first character is identical to the normal format code used by Qt. In - short, this means: 'e'/'E' scientific format, 'f' fixed format, 'g'/'G' scientific or fixed, - whichever is shorter. - - The second and third characters are optional and specific to QCustomPlot:\n - If the first char was 'e' or 'g', numbers are/might be displayed in the scientific format, e.g. - "5.5e9", which is ugly in a plot. So when the second char of \a formatCode is set to 'b' (for - "beautiful"), those exponential numbers are formatted in a more natural way, i.e. "5.5 - [multiplication sign] 10 [superscript] 9". By default, the multiplication sign is a centered dot. - If instead a cross should be shown (as is usual in the USA), the third char of \a formatCode can - be set to 'c'. The inserted multiplication signs are the UTF-8 characters 215 (0xD7) for the - cross and 183 (0xB7) for the dot. - - If the scale type (\ref setScaleType) is \ref stLogarithmic and the \a formatCode uses the 'b' - option (beautifully typeset decimal powers), the display usually is "1 [multiplication sign] 10 - [superscript] n", which looks unnatural for logarithmic scaling (the "1 [multiplication sign]" - part). To only display the decimal power, set the number precision to zero with \ref - setNumberPrecision. + Sets the background brush of the viewport (see \ref setViewport). + + Before drawing everything else, the background is filled with \a brush. If a background pixmap + was set with \ref setBackground(const QPixmap &pm), this brush will be used to fill the viewport + before the background pixmap is drawn. This can be useful for background pixmaps with translucent + areas. - Examples for \a formatCode: - \li \c g normal format code behaviour. If number is small, fixed format is used, if number is large, - normal scientific format is used - \li \c gb If number is small, fixed format is used, if number is large, scientific format is used with - beautifully typeset decimal powers and a dot as multiplication sign - \li \c ebc All numbers are in scientific format with beautifully typeset decimal power and a cross as - multiplication sign - \li \c fb illegal format code, since fixed format doesn't support (or need) beautifully typeset decimal - powers. Format code will be reduced to 'f'. - \li \c hello illegal format code, since first char is not 'e', 'E', 'f', 'g' or 'G'. Current format - code will not be changed. + Set \a brush to Qt::NoBrush or Qt::Transparent to leave background transparent. This can be + useful for exporting to image formats which support transparency, e.g. \ref savePng. + + \see setBackgroundScaled, setBackgroundScaledMode */ -void QCPAxis::setNumberFormat(const QString &formatCode) +void QCustomPlot::setBackground(const QBrush &brush) { - if (formatCode.isEmpty()) - { - qDebug() << Q_FUNC_INFO << "Passed formatCode is empty"; - return; - } - mCachedMarginValid = false; - - // interpret first char as number format char: - QString allowedFormatChars(QLatin1String("eEfgG")); - if (allowedFormatChars.contains(formatCode.at(0))) - { - mNumberFormatChar = QLatin1Char(formatCode.at(0).toLatin1()); - } else - { - qDebug() << Q_FUNC_INFO << "Invalid number format code (first char not in 'eEfgG'):" << formatCode; - return; - } - if (formatCode.length() < 2) - { - mNumberBeautifulPowers = false; - mAxisPainter->numberMultiplyCross = false; - return; - } - - // interpret second char as indicator for beautiful decimal powers: - if (formatCode.at(1) == QLatin1Char('b') && (mNumberFormatChar == QLatin1Char('e') || mNumberFormatChar == QLatin1Char('g'))) - { - mNumberBeautifulPowers = true; - } else - { - qDebug() << Q_FUNC_INFO << "Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode; - return; - } - if (formatCode.length() < 3) - { - mAxisPainter->numberMultiplyCross = false; - return; - } + mBackgroundBrush = brush; +} + +/*! \overload - // interpret third char as indicator for dot or cross multiplication symbol: - if (formatCode.at(2) == QLatin1Char('c')) - { - mAxisPainter->numberMultiplyCross = true; - } else if (formatCode.at(2) == QLatin1Char('d')) - { - mAxisPainter->numberMultiplyCross = false; - } else - { - qDebug() << Q_FUNC_INFO << "Invalid number format code (third char neither 'c' nor 'd'):" << formatCode; - return; - } + Allows setting the background pixmap of the viewport, whether it shall be scaled and how it + shall be scaled in one call. + + \see setBackground(const QPixmap &pm), setBackgroundScaled, setBackgroundScaledMode +*/ +void QCustomPlot::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode) +{ + mBackgroundPixmap = pm; + mScaledBackgroundPixmap = QPixmap(); + mBackgroundScaled = scaled; + mBackgroundScaledMode = mode; } /*! - Sets the precision of the tick label numbers. See QLocale::toString(double i, char f, int prec) - for details. The effect of precisions are most notably for number Formats starting with 'e', see - \ref setNumberFormat + Sets whether the viewport background pixmap shall be scaled to fit the viewport. If \a scaled is + set to true, control whether and how the aspect ratio of the original pixmap is preserved with + \ref setBackgroundScaledMode. + + Note that the scaled version of the original pixmap is buffered, so there is no performance + penalty on replots. (Except when the viewport dimensions are changed continuously.) + + \see setBackground, setBackgroundScaledMode +*/ +void QCustomPlot::setBackgroundScaled(bool scaled) +{ + mBackgroundScaled = scaled; +} - If the scale type (\ref setScaleType) is \ref stLogarithmic and the number format (\ref - setNumberFormat) uses the 'b' format code (beautifully typeset decimal powers), the display - usually is "1 [multiplication sign] 10 [superscript] n", which looks unnatural for logarithmic - scaling (the redundant "1 [multiplication sign]" part). To only display the decimal power "10 - [superscript] n", set \a precision to zero. +/*! + If scaling of the viewport background pixmap is enabled (\ref setBackgroundScaled), use this + function to define whether and how the aspect ratio of the original pixmap is preserved. + + \see setBackground, setBackgroundScaled */ -void QCPAxis::setNumberPrecision(int precision) +void QCustomPlot::setBackgroundScaledMode(Qt::AspectRatioMode mode) { - if (mNumberPrecision != precision) - { - mNumberPrecision = precision; - mCachedMarginValid = false; - } + mBackgroundScaledMode = mode; } /*! - If \ref setAutoTickStep is set to false, use this function to set the tick step manually. - The tick step is the interval between (major) ticks, in plot coordinates. - \see setSubTickCount + Returns the plottable with \a index. If the index is invalid, returns \c nullptr. + + There is an overloaded version of this function with no parameter which returns the last added + plottable, see QCustomPlot::plottable() + + \see plottableCount */ -void QCPAxis::setTickStep(double step) +QCPAbstractPlottable *QCustomPlot::plottable(int index) { - if (mTickStep != step) + if (index >= 0 && index < mPlottables.size()) { - mTickStep = step; - mCachedMarginValid = false; + return mPlottables.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return nullptr; } } -/*! - If you want full control over what ticks (and possibly labels) the axes show, this function is - used to set the coordinates at which ticks will appear.\ref setAutoTicks must be disabled, else - the provided tick vector will be overwritten with automatically generated tick coordinates upon - replot. The labels of the ticks can be generated automatically when \ref setAutoTickLabels is - left enabled. If it is disabled, you can set the labels manually with \ref setTickVectorLabels. +/*! \overload - \a vec is a vector containing the positions of the ticks, in plot coordinates. + Returns the last plottable that was added to the plot. If there are no plottables in the plot, + returns \c nullptr. - \warning \a vec must be sorted in ascending order, no additional checks are made to ensure this. - - \see setTickVectorLabels + \see plottableCount */ -void QCPAxis::setTickVector(const QVector &vec) +QCPAbstractPlottable *QCustomPlot::plottable() { - // don't check whether mTickVector != vec here, because it takes longer than we would save - mTickVector = vec; - mCachedMarginValid = false; + if (!mPlottables.isEmpty()) + { + return mPlottables.last(); + } else + return nullptr; } /*! - If you want full control over what ticks and labels the axes show, this function is used to set a - number of QStrings that will be displayed at the tick positions which you need to provide with - \ref setTickVector. These two vectors should have the same size. (Note that you need to disable - \ref setAutoTicks and \ref setAutoTickLabels first.) + Removes the specified plottable from the plot and deletes it. If necessary, the corresponding + legend item is also removed from the default legend (QCustomPlot::legend). - \a vec is a vector containing the labels of the ticks. The entries correspond to the respective - indices in the tick vector, passed via \ref setTickVector. + Returns true on success. - \see setTickVector + \see clearPlottables */ -void QCPAxis::setTickVectorLabels(const QVector &vec) +bool QCustomPlot::removePlottable(QCPAbstractPlottable *plottable) { - // don't check whether mTickVectorLabels != vec here, because it takes longer than we would save - mTickVectorLabels = vec; - mCachedMarginValid = false; + if (!mPlottables.contains(plottable)) + { + qDebug() << Q_FUNC_INFO << "plottable not in list:" << reinterpret_cast(plottable); + return false; + } + + // remove plottable from legend: + plottable->removeFromLegend(); + // special handling for QCPGraphs to maintain the simple graph interface: + if (QCPGraph *graph = qobject_cast(plottable)) + mGraphs.removeOne(graph); + // remove plottable: + delete plottable; + mPlottables.removeOne(plottable); + return true; +} + +/*! \overload + + Removes and deletes the plottable by its \a index. +*/ +bool QCustomPlot::removePlottable(int index) +{ + if (index >= 0 && index < mPlottables.size()) + return removePlottable(mPlottables[index]); + else + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return false; + } } /*! - Sets the length of the ticks in pixels. \a inside is the length the ticks will reach inside the - plot and \a outside is the length they will reach outside the plot. If \a outside is greater than - zero, the tick labels and axis label will increase their distance to the axis accordingly, so - they won't collide with the ticks. + Removes all plottables from the plot and deletes them. Corresponding legend items are also + removed from the default legend (QCustomPlot::legend). - \see setSubTickLength, setTickLengthIn, setTickLengthOut + Returns the number of plottables removed. + + \see removePlottable */ -void QCPAxis::setTickLength(int inside, int outside) +int QCustomPlot::clearPlottables() { - setTickLengthIn(inside); - setTickLengthOut(outside); + int c = mPlottables.size(); + for (int i=c-1; i >= 0; --i) + removePlottable(mPlottables[i]); + return c; } /*! - Sets the length of the inward ticks in pixels. \a inside is the length the ticks will reach - inside the plot. + Returns the number of currently existing plottables in the plot - \see setTickLengthOut, setTickLength, setSubTickLength + \see plottable */ -void QCPAxis::setTickLengthIn(int inside) +int QCustomPlot::plottableCount() const { - if (mAxisPainter->tickLengthIn != inside) - { - mAxisPainter->tickLengthIn = inside; - } + return mPlottables.size(); } /*! - Sets the length of the outward ticks in pixels. \a outside is the length the ticks will reach - outside the plot. If \a outside is greater than zero, the tick labels and axis label will - increase their distance to the axis accordingly, so they won't collide with the ticks. + Returns a list of the selected plottables. If no plottables are currently selected, the list is empty. - \see setTickLengthIn, setTickLength, setSubTickLength + There is a convenience function if you're only interested in selected graphs, see \ref selectedGraphs. + + \see setInteractions, QCPAbstractPlottable::setSelectable, QCPAbstractPlottable::setSelection */ -void QCPAxis::setTickLengthOut(int outside) +QList QCustomPlot::selectedPlottables() const { - if (mAxisPainter->tickLengthOut != outside) + QList result; + foreach (QCPAbstractPlottable *plottable, mPlottables) { - mAxisPainter->tickLengthOut = outside; - mCachedMarginValid = false; // only outside tick length can change margin + if (plottable->selected()) + result.append(plottable); } + return result; } /*! - Sets the number of sub ticks in one (major) tick step. A sub tick count of three for example, - divides the tick intervals in four sub intervals. + Returns any plottable at the pixel position \a pos. Since it can capture all plottables, the + return type is the abstract base class of all plottables, QCPAbstractPlottable. - By default, the number of sub ticks is chosen automatically in a reasonable manner as long as the - mantissa of the tick step is a multiple of 0.5. When \ref setAutoTickStep is enabled, this is - always the case. - - If you want to disable automatic sub tick count and use this function to set the count manually, - see \ref setAutoSubTicks. + For details, and if you wish to specify a certain plottable type (e.g. QCPGraph), see the + template method plottableAt() + + \see plottableAt(), itemAt, layoutElementAt */ -void QCPAxis::setSubTickCount(int count) +QCPAbstractPlottable *QCustomPlot::plottableAt(const QPointF &pos, bool onlySelectable, int *dataIndex) const { - mSubTickCount = count; + return plottableAt(pos, onlySelectable, dataIndex); } /*! - Sets the length of the subticks in pixels. \a inside is the length the subticks will reach inside - the plot and \a outside is the length they will reach outside the plot. If \a outside is greater - than zero, the tick labels and axis label will increase their distance to the axis accordingly, - so they won't collide with the ticks. - - \see setTickLength, setSubTickLengthIn, setSubTickLengthOut + Returns whether this QCustomPlot instance contains the \a plottable. */ -void QCPAxis::setSubTickLength(int inside, int outside) +bool QCustomPlot::hasPlottable(QCPAbstractPlottable *plottable) const { - setSubTickLengthIn(inside); - setSubTickLengthOut(outside); + return mPlottables.contains(plottable); } /*! - Sets the length of the inward subticks in pixels. \a inside is the length the subticks will reach inside - the plot. + Returns the graph with \a index. If the index is invalid, returns \c nullptr. - \see setSubTickLengthOut, setSubTickLength, setTickLength + There is an overloaded version of this function with no parameter which returns the last created + graph, see QCustomPlot::graph() + + \see graphCount, addGraph */ -void QCPAxis::setSubTickLengthIn(int inside) +QCPGraph *QCustomPlot::graph(int index) const { - if (mAxisPainter->subTickLengthIn != inside) + if (index >= 0 && index < mGraphs.size()) { - mAxisPainter->subTickLengthIn = inside; + return mGraphs.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return nullptr; } } -/*! - Sets the length of the outward subticks in pixels. \a outside is the length the subticks will reach - outside the plot. If \a outside is greater than zero, the tick labels will increase their - distance to the axis accordingly, so they won't collide with the ticks. +/*! \overload - \see setSubTickLengthIn, setSubTickLength, setTickLength + Returns the last graph, that was created with \ref addGraph. If there are no graphs in the plot, + returns \c nullptr. + + \see graphCount, addGraph */ -void QCPAxis::setSubTickLengthOut(int outside) +QCPGraph *QCustomPlot::graph() const { - if (mAxisPainter->subTickLengthOut != outside) + if (!mGraphs.isEmpty()) { - mAxisPainter->subTickLengthOut = outside; - mCachedMarginValid = false; // only outside tick length can change margin - } + return mGraphs.last(); + } else + return nullptr; } /*! - Sets the pen, the axis base line is drawn with. + Creates a new graph inside the plot. If \a keyAxis and \a valueAxis are left unspecified (0), the + bottom (xAxis) is used as key and the left (yAxis) is used as value axis. If specified, \a + keyAxis and \a valueAxis must reside in this QCustomPlot. - \see setTickPen, setSubTickPen + \a keyAxis will be used as key axis (typically "x") and \a valueAxis as value axis (typically + "y") for the graph. + + Returns a pointer to the newly created graph, or \c nullptr if adding the graph failed. + + \see graph, graphCount, removeGraph, clearGraphs */ -void QCPAxis::setBasePen(const QPen &pen) +QCPGraph *QCustomPlot::addGraph(QCPAxis *keyAxis, QCPAxis *valueAxis) { - mBasePen = pen; + if (!keyAxis) keyAxis = xAxis; + if (!valueAxis) valueAxis = yAxis; + if (!keyAxis || !valueAxis) + { + qDebug() << Q_FUNC_INFO << "can't use default QCustomPlot xAxis or yAxis, because at least one is invalid (has been deleted)"; + return nullptr; + } + if (keyAxis->parentPlot() != this || valueAxis->parentPlot() != this) + { + qDebug() << Q_FUNC_INFO << "passed keyAxis or valueAxis doesn't have this QCustomPlot as parent"; + return nullptr; + } + + QCPGraph *newGraph = new QCPGraph(keyAxis, valueAxis); + newGraph->setName(QLatin1String("Graph ")+QString::number(mGraphs.size())); + return newGraph; } /*! - Sets the pen, tick marks will be drawn with. + Removes the specified \a graph from the plot and deletes it. If necessary, the corresponding + legend item is also removed from the default legend (QCustomPlot::legend). If any other graphs in + the plot have a channel fill set towards the removed graph, the channel fill property of those + graphs is reset to \c nullptr (no channel fill). - \see setTickLength, setBasePen + Returns true on success. + + \see clearGraphs */ -void QCPAxis::setTickPen(const QPen &pen) +bool QCustomPlot::removeGraph(QCPGraph *graph) { - mTickPen = pen; + return removePlottable(graph); } -/*! - Sets the pen, subtick marks will be drawn with. +/*! \overload - \see setSubTickCount, setSubTickLength, setBasePen + Removes and deletes the graph by its \a index. */ -void QCPAxis::setSubTickPen(const QPen &pen) +bool QCustomPlot::removeGraph(int index) { - mSubTickPen = pen; + if (index >= 0 && index < mGraphs.size()) + return removeGraph(mGraphs[index]); + else + return false; } /*! - Sets the font of the axis label. + Removes all graphs from the plot and deletes them. Corresponding legend items are also removed + from the default legend (QCustomPlot::legend). + + Returns the number of graphs removed. - \see setLabelColor + \see removeGraph */ -void QCPAxis::setLabelFont(const QFont &font) +int QCustomPlot::clearGraphs() { - if (mLabelFont != font) - { - mLabelFont = font; - mCachedMarginValid = false; - } + int c = mGraphs.size(); + for (int i=c-1; i >= 0; --i) + removeGraph(mGraphs[i]); + return c; } /*! - Sets the color of the axis label. + Returns the number of currently existing graphs in the plot - \see setLabelFont + \see graph, addGraph */ -void QCPAxis::setLabelColor(const QColor &color) +int QCustomPlot::graphCount() const { - mLabelColor = color; + return mGraphs.size(); } /*! - Sets the text of the axis label that will be shown below/above or next to the axis, depending on - its orientation. To disable axis labels, pass an empty string as \a str. + Returns a list of the selected graphs. If no graphs are currently selected, the list is empty. + + If you are not only interested in selected graphs but other plottables like QCPCurve, QCPBars, + etc., use \ref selectedPlottables. + + \see setInteractions, selectedPlottables, QCPAbstractPlottable::setSelectable, QCPAbstractPlottable::setSelection */ -void QCPAxis::setLabel(const QString &str) +QList QCustomPlot::selectedGraphs() const { - if (mLabel != str) + QList result; + foreach (QCPGraph *graph, mGraphs) { - mLabel = str; - mCachedMarginValid = false; + if (graph->selected()) + result.append(graph); } + return result; } /*! - Sets the distance between the tick labels and the axis label. + Returns the item with \a index. If the index is invalid, returns \c nullptr. - \see setTickLabelPadding, setPadding + There is an overloaded version of this function with no parameter which returns the last added + item, see QCustomPlot::item() + + \see itemCount */ -void QCPAxis::setLabelPadding(int padding) +QCPAbstractItem *QCustomPlot::item(int index) const { - if (mAxisPainter->labelPadding != padding) + if (index >= 0 && index < mItems.size()) { - mAxisPainter->labelPadding = padding; - mCachedMarginValid = false; + return mItems.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return nullptr; } } -/*! - Sets the padding of the axis. - - When \ref QCPAxisRect::setAutoMargins is enabled, the padding is the additional outer most space, - that is left blank. +/*! \overload - The axis padding has no meaning if \ref QCPAxisRect::setAutoMargins is disabled. + Returns the last item that was added to this plot. If there are no items in the plot, + returns \c nullptr. - \see setLabelPadding, setTickLabelPadding + \see itemCount */ -void QCPAxis::setPadding(int padding) +QCPAbstractItem *QCustomPlot::item() const { - if (mPadding != padding) + if (!mItems.isEmpty()) { - mPadding = padding; - mCachedMarginValid = false; - } + return mItems.last(); + } else + return nullptr; } /*! - Sets the offset the axis has to its axis rect side. + Removes the specified item from the plot and deletes it. - If an axis rect side has multiple axes and automatic margin calculation is enabled for that side, - only the offset of the inner most axis has meaning (even if it is set to be invisible). The - offset of the other, outer axes is controlled automatically, to place them at appropriate - positions. + Returns true on success. + + \see clearItems */ -void QCPAxis::setOffset(int offset) +bool QCustomPlot::removeItem(QCPAbstractItem *item) { - mAxisPainter->offset = offset; + if (mItems.contains(item)) + { + delete item; + mItems.removeOne(item); + return true; + } else + { + qDebug() << Q_FUNC_INFO << "item not in list:" << reinterpret_cast(item); + return false; + } } -/*! - Sets the font that is used for tick labels when they are selected. +/*! \overload - \see setTickLabelFont, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions + Removes and deletes the item by its \a index. */ -void QCPAxis::setSelectedTickLabelFont(const QFont &font) +bool QCustomPlot::removeItem(int index) { - if (font != mSelectedTickLabelFont) + if (index >= 0 && index < mItems.size()) + return removeItem(mItems[index]); + else { - mSelectedTickLabelFont = font; - // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return false; } } /*! - Sets the font that is used for the axis label when it is selected. + Removes all items from the plot and deletes them. - \see setLabelFont, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions + Returns the number of items removed. + + \see removeItem */ -void QCPAxis::setSelectedLabelFont(const QFont &font) +int QCustomPlot::clearItems() { - mSelectedLabelFont = font; - // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts + int c = mItems.size(); + for (int i=c-1; i >= 0; --i) + removeItem(mItems[i]); + return c; } /*! - Sets the color that is used for tick labels when they are selected. + Returns the number of currently existing items in the plot - \see setTickLabelColor, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions + \see item */ -void QCPAxis::setSelectedTickLabelColor(const QColor &color) +int QCustomPlot::itemCount() const { - if (color != mSelectedTickLabelColor) - { - mSelectedTickLabelColor = color; - } + return mItems.size(); } /*! - Sets the color that is used for the axis label when it is selected. + Returns a list of the selected items. If no items are currently selected, the list is empty. - \see setLabelColor, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions + \see setInteractions, QCPAbstractItem::setSelectable, QCPAbstractItem::setSelected */ -void QCPAxis::setSelectedLabelColor(const QColor &color) +QList QCustomPlot::selectedItems() const { - mSelectedLabelColor = color; + QList result; + foreach (QCPAbstractItem *item, mItems) + { + if (item->selected()) + result.append(item); + } + return result; } /*! - Sets the pen that is used to draw the axis base line when selected. + Returns the item at the pixel position \a pos. Since it can capture all items, the + return type is the abstract base class of all items, QCPAbstractItem. - \see setBasePen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions + For details, and if you wish to specify a certain item type (e.g. QCPItemLine), see the + template method itemAt() + + \see itemAt(), plottableAt, layoutElementAt */ -void QCPAxis::setSelectedBasePen(const QPen &pen) +QCPAbstractItem *QCustomPlot::itemAt(const QPointF &pos, bool onlySelectable) const { - mSelectedBasePen = pen; + return itemAt(pos, onlySelectable); } /*! - Sets the pen that is used to draw the (major) ticks when selected. + Returns whether this QCustomPlot contains the \a item. - \see setTickPen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions + \see item */ -void QCPAxis::setSelectedTickPen(const QPen &pen) +bool QCustomPlot::hasItem(QCPAbstractItem *item) const { - mSelectedTickPen = pen; + return mItems.contains(item); } /*! - Sets the pen that is used to draw the subticks when selected. + Returns the layer with the specified \a name. If there is no layer with the specified name, \c + nullptr is returned. - \see setSubTickPen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions + Layer names are case-sensitive. + + \see addLayer, moveLayer, removeLayer */ -void QCPAxis::setSelectedSubTickPen(const QPen &pen) +QCPLayer *QCustomPlot::layer(const QString &name) const { - mSelectedSubTickPen = pen; + foreach (QCPLayer *layer, mLayers) + { + if (layer->name() == name) + return layer; + } + return nullptr; } -/*! - Sets the style for the lower axis ending. See the documentation of QCPLineEnding for available - styles. +/*! \overload - For horizontal axes, this method refers to the left ending, for vertical axes the bottom ending. - Note that this meaning does not change when the axis range is reversed with \ref - setRangeReversed. + Returns the layer by \a index. If the index is invalid, \c nullptr is returned. - \see setUpperEnding + \see addLayer, moveLayer, removeLayer */ -void QCPAxis::setLowerEnding(const QCPLineEnding &ending) +QCPLayer *QCustomPlot::layer(int index) const { - mAxisPainter->lowerEnding = ending; + if (index >= 0 && index < mLayers.size()) + { + return mLayers.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return nullptr; + } } /*! - Sets the style for the upper axis ending. See the documentation of QCPLineEnding for available - styles. - - For horizontal axes, this method refers to the right ending, for vertical axes the top ending. - Note that this meaning does not change when the axis range is reversed with \ref - setRangeReversed. - - \see setLowerEnding + Returns the layer that is set as current layer (see \ref setCurrentLayer). */ -void QCPAxis::setUpperEnding(const QCPLineEnding &ending) +QCPLayer *QCustomPlot::currentLayer() const { - mAxisPainter->upperEnding = ending; + return mCurrentLayer; } /*! - If the scale type (\ref setScaleType) is \ref stLinear, \a diff is added to the lower and upper - bounds of the range. The range is simply moved by \a diff. + Sets the layer with the specified \a name to be the current layer. All layerables (\ref + QCPLayerable), e.g. plottables and items, are created on the current layer. - If the scale type is \ref stLogarithmic, the range bounds are multiplied by \a diff. This - corresponds to an apparent "linear" move in logarithmic scaling by a distance of log(diff). + Returns true on success, i.e. if there is a layer with the specified \a name in the QCustomPlot. + + Layer names are case-sensitive. + + \see addLayer, moveLayer, removeLayer, QCPLayerable::setLayer */ -void QCPAxis::moveRange(double diff) +bool QCustomPlot::setCurrentLayer(const QString &name) { - QCPRange oldRange = mRange; - if (mScaleType == stLinear) + if (QCPLayer *newCurrentLayer = layer(name)) { - mRange.lower += diff; - mRange.upper += diff; - } else // mScaleType == stLogarithmic + return setCurrentLayer(newCurrentLayer); + } else { - mRange.lower *= diff; - mRange.upper *= diff; + qDebug() << Q_FUNC_INFO << "layer with name doesn't exist:" << name; + return false; } - mCachedMarginValid = false; - emit rangeChanged(mRange); - emit rangeChanged(mRange, oldRange); } -/*! - Scales the range of this axis by \a factor around the coordinate \a center. For example, if \a - factor is 2.0, \a center is 1.0, then the axis range will double its size, and the point at - coordinate 1.0 won't have changed its position in the QCustomPlot widget (i.e. coordinates - around 1.0 will have moved symmetrically closer to 1.0). +/*! \overload + + Sets the provided \a layer to be the current layer. + + Returns true on success, i.e. when \a layer is a valid layer in the QCustomPlot. + + \see addLayer, moveLayer, removeLayer */ -void QCPAxis::scaleRange(double factor, double center) -{ - QCPRange oldRange = mRange; - if (mScaleType == stLinear) - { - QCPRange newRange; - newRange.lower = (mRange.lower-center)*factor + center; - newRange.upper = (mRange.upper-center)*factor + center; - if (QCPRange::validRange(newRange)) - mRange = newRange.sanitizedForLinScale(); - } else // mScaleType == stLogarithmic - { - if ((mRange.upper < 0 && center < 0) || (mRange.upper > 0 && center > 0)) // make sure center has same sign as range - { - QCPRange newRange; - newRange.lower = qPow(mRange.lower/center, factor)*center; - newRange.upper = qPow(mRange.upper/center, factor)*center; - if (QCPRange::validRange(newRange)) - mRange = newRange.sanitizedForLogScale(); - } else - qDebug() << Q_FUNC_INFO << "Center of scaling operation doesn't lie in same logarithmic sign domain as range:" << center; +bool QCustomPlot::setCurrentLayer(QCPLayer *layer) +{ + if (!mLayers.contains(layer)) + { + qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast(layer); + return false; } - mCachedMarginValid = false; - emit rangeChanged(mRange); - emit rangeChanged(mRange, oldRange); + + mCurrentLayer = layer; + return true; } /*! - Scales the range of this axis to have a certain scale \a ratio to \a otherAxis. The scaling will - be done around the center of the current axis range. - - For example, if \a ratio is 1, this axis is the \a yAxis and \a otherAxis is \a xAxis, graphs - plotted with those axes will appear in a 1:1 aspect ratio, independent of the aspect ratio the - axis rect has. - - This is an operation that changes the range of this axis once, it doesn't fix the scale ratio - indefinitely. Note that calling this function in the constructor of the QCustomPlot's parent - won't have the desired effect, since the widget dimensions aren't defined yet, and a resizeEvent - will follow. + Returns the number of currently existing layers in the plot + + \see layer, addLayer */ -void QCPAxis::setScaleRatio(const QCPAxis *otherAxis, double ratio) +int QCustomPlot::layerCount() const { - int otherPixelSize, ownPixelSize; - - if (otherAxis->orientation() == Qt::Horizontal) - otherPixelSize = otherAxis->axisRect()->width(); - else - otherPixelSize = otherAxis->axisRect()->height(); - - if (orientation() == Qt::Horizontal) - ownPixelSize = axisRect()->width(); - else - ownPixelSize = axisRect()->height(); - - double newRangeSize = ratio*otherAxis->range().size()*ownPixelSize/(double)otherPixelSize; - setRange(range().center(), newRangeSize, Qt::AlignCenter); + return mLayers.size(); } /*! - Changes the axis range such that all plottables associated with this axis are fully visible in - that dimension. + Adds a new layer to this QCustomPlot instance. The new layer will have the name \a name, which + must be unique. Depending on \a insertMode, it is positioned either below or above \a otherLayer. - \see QCPAbstractPlottable::rescaleAxes, QCustomPlot::rescaleAxes + Returns true on success, i.e. if there is no other layer named \a name and \a otherLayer is a + valid layer inside this QCustomPlot. + + If \a otherLayer is 0, the highest layer in the QCustomPlot will be used. + + For an explanation of what layers are in QCustomPlot, see the documentation of \ref QCPLayer. + + \see layer, moveLayer, removeLayer */ -void QCPAxis::rescale(bool onlyVisiblePlottables) +bool QCustomPlot::addLayer(const QString &name, QCPLayer *otherLayer, QCustomPlot::LayerInsertMode insertMode) { - QList p = plottables(); - QCPRange newRange; - bool haveRange = false; - for (int i=0; irealVisibility() && onlyVisiblePlottables) - continue; - QCPRange plottableRange; - bool currentFoundRange; - QCPAbstractPlottable::SignDomain signDomain = QCPAbstractPlottable::sdBoth; - if (mScaleType == stLogarithmic) - signDomain = (mRange.upper < 0 ? QCPAbstractPlottable::sdNegative : QCPAbstractPlottable::sdPositive); - if (p.at(i)->keyAxis() == this) - plottableRange = p.at(i)->getKeyRange(currentFoundRange, signDomain); - else - plottableRange = p.at(i)->getValueRange(currentFoundRange, signDomain); - if (currentFoundRange) - { - if (!haveRange) - newRange = plottableRange; - else - newRange.expand(plottableRange); - haveRange = true; - } + qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast(otherLayer); + return false; } - if (haveRange) + if (layer(name)) { - if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable - { - double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason - if (mScaleType == stLinear) - { - newRange.lower = center-mRange.size()/2.0; - newRange.upper = center+mRange.size()/2.0; - } else // mScaleType == stLogarithmic - { - newRange.lower = center/qSqrt(mRange.upper/mRange.lower); - newRange.upper = center*qSqrt(mRange.upper/mRange.lower); - } - } - setRange(newRange); + qDebug() << Q_FUNC_INFO << "A layer exists already with the name" << name; + return false; } + + QCPLayer *newLayer = new QCPLayer(this, name); + mLayers.insert(otherLayer->index() + (insertMode==limAbove ? 1:0), newLayer); + updateLayerIndices(); + setupPaintBuffers(); // associates new layer with the appropriate paint buffer + return true; } /*! - Transforms \a value, in pixel coordinates of the QCustomPlot widget, to axis coordinates. + Removes the specified \a layer and returns true on success. + + All layerables (e.g. plottables and items) on the removed layer will be moved to the layer below + \a layer. If \a layer is the bottom layer, the layerables are moved to the layer above. In both + cases, the total rendering order of all layerables in the QCustomPlot is preserved. + + If \a layer is the current layer (\ref setCurrentLayer), the layer below (or above, if bottom + layer) becomes the new current layer. + + It is not possible to remove the last layer of the plot. + + \see layer, addLayer, moveLayer */ -double QCPAxis::pixelToCoord(double value) const +bool QCustomPlot::removeLayer(QCPLayer *layer) { - if (orientation() == Qt::Horizontal) + if (!mLayers.contains(layer)) { - if (mScaleType == stLinear) - { - if (!mRangeReversed) - return (value-mAxisRect->left())/(double)mAxisRect->width()*mRange.size()+mRange.lower; - else - return -(value-mAxisRect->left())/(double)mAxisRect->width()*mRange.size()+mRange.upper; - } else // mScaleType == stLogarithmic - { - if (!mRangeReversed) - return qPow(mRange.upper/mRange.lower, (value-mAxisRect->left())/(double)mAxisRect->width())*mRange.lower; - else - return qPow(mRange.upper/mRange.lower, (mAxisRect->left()-value)/(double)mAxisRect->width())*mRange.upper; - } - } else // orientation() == Qt::Vertical + qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast(layer); + return false; + } + if (mLayers.size() < 2) { - if (mScaleType == stLinear) - { - if (!mRangeReversed) - return (mAxisRect->bottom()-value)/(double)mAxisRect->height()*mRange.size()+mRange.lower; - else - return -(mAxisRect->bottom()-value)/(double)mAxisRect->height()*mRange.size()+mRange.upper; - } else // mScaleType == stLogarithmic - { - if (!mRangeReversed) - return qPow(mRange.upper/mRange.lower, (mAxisRect->bottom()-value)/(double)mAxisRect->height())*mRange.lower; - else - return qPow(mRange.upper/mRange.lower, (value-mAxisRect->bottom())/(double)mAxisRect->height())*mRange.upper; - } + qDebug() << Q_FUNC_INFO << "can't remove last layer"; + return false; } + + // append all children of this layer to layer below (if this is lowest layer, prepend to layer above) + int removedIndex = layer->index(); + bool isFirstLayer = removedIndex==0; + QCPLayer *targetLayer = isFirstLayer ? mLayers.at(removedIndex+1) : mLayers.at(removedIndex-1); + QList children = layer->children(); + if (isFirstLayer) // prepend in reverse order (such that relative order stays the same) + std::reverse(children.begin(), children.end()); + foreach (QCPLayerable *child, children) + child->moveToLayer(targetLayer, isFirstLayer); // prepend if isFirstLayer, otherwise append + + // if removed layer is current layer, change current layer to layer below/above: + if (layer == mCurrentLayer) + setCurrentLayer(targetLayer); + + // invalidate the paint buffer that was responsible for this layer: + if (QSharedPointer pb = layer->mPaintBuffer.toStrongRef()) + pb->setInvalidated(); + + // remove layer: + delete layer; + mLayers.removeOne(layer); + updateLayerIndices(); + return true; } /*! - Transforms \a value, in coordinates of the axis, to pixel coordinates of the QCustomPlot widget. + Moves the specified \a layer either above or below \a otherLayer. Whether it's placed above or + below is controlled with \a insertMode. + + Returns true on success, i.e. when both \a layer and \a otherLayer are valid layers in the + QCustomPlot. + + \see layer, addLayer, moveLayer */ -double QCPAxis::coordToPixel(double value) const +bool QCustomPlot::moveLayer(QCPLayer *layer, QCPLayer *otherLayer, QCustomPlot::LayerInsertMode insertMode) { - if (orientation() == Qt::Horizontal) + if (!mLayers.contains(layer)) { - if (mScaleType == stLinear) - { - if (!mRangeReversed) - return (value-mRange.lower)/mRange.size()*mAxisRect->width()+mAxisRect->left(); - else - return (mRange.upper-value)/mRange.size()*mAxisRect->width()+mAxisRect->left(); - } else // mScaleType == stLogarithmic - { - if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it outside visible range - return !mRangeReversed ? mAxisRect->right()+200 : mAxisRect->left()-200; - else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just draw it outside visible range - return !mRangeReversed ? mAxisRect->left()-200 : mAxisRect->right()+200; - else - { - if (!mRangeReversed) - return baseLog(value/mRange.lower)/baseLog(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left(); - else - return baseLog(mRange.upper/value)/baseLog(mRange.upper/mRange.lower)*mAxisRect->width()+mAxisRect->left(); - } - } - } else // orientation() == Qt::Vertical + qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast(layer); + return false; + } + if (!mLayers.contains(otherLayer)) { - if (mScaleType == stLinear) - { - if (!mRangeReversed) - return mAxisRect->bottom()-(value-mRange.lower)/mRange.size()*mAxisRect->height(); - else - return mAxisRect->bottom()-(mRange.upper-value)/mRange.size()*mAxisRect->height(); - } else // mScaleType == stLogarithmic - { - if (value >= 0 && mRange.upper < 0) // invalid value for logarithmic scale, just draw it outside visible range - return !mRangeReversed ? mAxisRect->top()-200 : mAxisRect->bottom()+200; - else if (value <= 0 && mRange.upper > 0) // invalid value for logarithmic scale, just draw it outside visible range - return !mRangeReversed ? mAxisRect->bottom()+200 : mAxisRect->top()-200; - else - { - if (!mRangeReversed) - return mAxisRect->bottom()-baseLog(value/mRange.lower)/baseLog(mRange.upper/mRange.lower)*mAxisRect->height(); - else - return mAxisRect->bottom()-baseLog(mRange.upper/value)/baseLog(mRange.upper/mRange.lower)*mAxisRect->height(); - } - } + qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast(otherLayer); + return false; } -} - -/*! - Returns the part of the axis that is hit by \a pos (in pixels). The return value of this function - is independent of the user-selectable parts defined with \ref setSelectableParts. Further, this - function does not change the current selection state of the axis. - If the axis is not visible (\ref setVisible), this function always returns \ref spNone. + if (layer->index() > otherLayer->index()) + mLayers.move(layer->index(), otherLayer->index() + (insertMode==limAbove ? 1:0)); + else if (layer->index() < otherLayer->index()) + mLayers.move(layer->index(), otherLayer->index() + (insertMode==limAbove ? 0:-1)); - \see setSelectedParts, setSelectableParts, QCustomPlot::setInteractions -*/ -QCPAxis::SelectablePart QCPAxis::getPartAt(const QPointF &pos) const -{ - if (!mVisible) - return spNone; + // invalidate the paint buffers that are responsible for the layers: + if (QSharedPointer pb = layer->mPaintBuffer.toStrongRef()) + pb->setInvalidated(); + if (QSharedPointer pb = otherLayer->mPaintBuffer.toStrongRef()) + pb->setInvalidated(); - if (mAxisPainter->axisSelectionBox().contains(pos.toPoint())) - return spAxis; - else if (mAxisPainter->tickLabelsSelectionBox().contains(pos.toPoint())) - return spTickLabels; - else if (mAxisPainter->labelSelectionBox().contains(pos.toPoint())) - return spAxisLabel; - else - return spNone; + updateLayerIndices(); + return true; } -/* inherits documentation from base class */ -double QCPAxis::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const -{ - if (!mParentPlot) return -1; - SelectablePart part = getPartAt(pos); - if ((onlySelectable && !mSelectableParts.testFlag(part)) || part == spNone) - return -1; +/*! + Returns the number of axis rects in the plot. - if (details) - details->setValue(part); - return mParentPlot->selectionTolerance()*0.99; + All axis rects can be accessed via QCustomPlot::axisRect(). + + Initially, only one axis rect exists in the plot. + + \see axisRect, axisRects +*/ +int QCustomPlot::axisRectCount() const +{ + return axisRects().size(); } /*! - Returns a list of all the plottables that have this axis as key or value axis. + Returns the axis rect with \a index. - If you are only interested in plottables of type QCPGraph, see \ref graphs. + Initially, only one axis rect (with index 0) exists in the plot. If multiple axis rects were + added, all of them may be accessed with this function in a linear fashion (even when they are + nested in a layout hierarchy or inside other axis rects via QCPAxisRect::insetLayout). - \see graphs, items + The order of the axis rects is given by the fill order of the \ref QCPLayout that is holding + them. For example, if the axis rects are in the top level grid layout (accessible via \ref + QCustomPlot::plotLayout), they are ordered from left to right, top to bottom, if the layout's + default \ref QCPLayoutGrid::setFillOrder "setFillOrder" of \ref QCPLayoutGrid::foColumnsFirst + "foColumnsFirst" wasn't changed. + + If you want to access axis rects by their row and column index, use the layout interface. For + example, use \ref QCPLayoutGrid::element of the top level grid layout, and \c qobject_cast the + returned layout element to \ref QCPAxisRect. (See also \ref thelayoutsystem.) + + \see axisRectCount, axisRects, QCPLayoutGrid::setFillOrder */ -QList QCPAxis::plottables() const +QCPAxisRect *QCustomPlot::axisRect(int index) const { - QList result; - if (!mParentPlot) return result; - - for (int i=0; imPlottables.size(); ++i) + const QList rectList = axisRects(); + if (index >= 0 && index < rectList.size()) { - if (mParentPlot->mPlottables.at(i)->keyAxis() == this ||mParentPlot->mPlottables.at(i)->valueAxis() == this) - result.append(mParentPlot->mPlottables.at(i)); + return rectList.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "invalid axis rect index" << index; + return nullptr; } - return result; } /*! - Returns a list of all the graphs that have this axis as key or value axis. + Returns all axis rects in the plot. - \see plottables, items + The order of the axis rects is given by the fill order of the \ref QCPLayout that is holding + them. For example, if the axis rects are in the top level grid layout (accessible via \ref + QCustomPlot::plotLayout), they are ordered from left to right, top to bottom, if the layout's + default \ref QCPLayoutGrid::setFillOrder "setFillOrder" of \ref QCPLayoutGrid::foColumnsFirst + "foColumnsFirst" wasn't changed. + + \see axisRectCount, axisRect, QCPLayoutGrid::setFillOrder */ -QList QCPAxis::graphs() const +QList QCustomPlot::axisRects() const { - QList result; - if (!mParentPlot) return result; + QList result; + QStack elementStack; + if (mPlotLayout) + elementStack.push(mPlotLayout); - for (int i=0; imGraphs.size(); ++i) + while (!elementStack.isEmpty()) { - if (mParentPlot->mGraphs.at(i)->keyAxis() == this || mParentPlot->mGraphs.at(i)->valueAxis() == this) - result.append(mParentPlot->mGraphs.at(i)); + foreach (QCPLayoutElement *element, elementStack.pop()->elements(false)) + { + if (element) + { + elementStack.push(element); + if (QCPAxisRect *ar = qobject_cast(element)) + result.append(ar); + } + } } + return result; } /*! - Returns a list of all the items that are associated with this axis. An item is considered - associated with an axis if at least one of its positions uses the axis as key or value axis. + Returns the layout element at pixel position \a pos. If there is no element at that position, + returns \c nullptr. - \see plottables, graphs + Only visible elements are used. If \ref QCPLayoutElement::setVisible on the element itself or on + any of its parent elements is set to false, it will not be considered. + + \see itemAt, plottableAt */ -QList QCPAxis::items() const +QCPLayoutElement *QCustomPlot::layoutElementAt(const QPointF &pos) const { - QList result; - if (!mParentPlot) return result; - - for (int itemId=0; itemIdmItems.size(); ++itemId) + QCPLayoutElement *currentElement = mPlotLayout; + bool searchSubElements = true; + while (searchSubElements && currentElement) { - QList positions = mParentPlot->mItems.at(itemId)->positions(); - for (int posId=0; posIdelements(false)) { - if (positions.at(posId)->keyAxis() == this || positions.at(posId)->valueAxis() == this) + if (subElement && subElement->realVisibility() && subElement->selectTest(pos, false) >= 0) { - result.append(mParentPlot->mItems.at(itemId)); + currentElement = subElement; + searchSubElements = true; break; } } } - return result; + return currentElement; } /*! - Transforms a margin side to the logically corresponding axis type. (QCP::msLeft to - QCPAxis::atLeft, QCP::msRight to QCPAxis::atRight, etc.) + Returns the layout element of type \ref QCPAxisRect at pixel position \a pos. This method ignores + other layout elements even if they are visually in front of the axis rect (e.g. a \ref + QCPLegend). If there is no axis rect at that position, returns \c nullptr. + + Only visible axis rects are used. If \ref QCPLayoutElement::setVisible on the axis rect itself or + on any of its parent elements is set to false, it will not be considered. + + \see layoutElementAt */ -QCPAxis::AxisType QCPAxis::marginSideToAxisType(QCP::MarginSide side) +QCPAxisRect *QCustomPlot::axisRectAt(const QPointF &pos) const { - switch (side) + QCPAxisRect *result = nullptr; + QCPLayoutElement *currentElement = mPlotLayout; + bool searchSubElements = true; + while (searchSubElements && currentElement) { - case QCP::msLeft: return atLeft; - case QCP::msRight: return atRight; - case QCP::msTop: return atTop; - case QCP::msBottom: return atBottom; - default: break; + searchSubElements = false; + foreach (QCPLayoutElement *subElement, currentElement->elements(false)) + { + if (subElement && subElement->realVisibility() && subElement->selectTest(pos, false) >= 0) + { + currentElement = subElement; + searchSubElements = true; + if (QCPAxisRect *ar = qobject_cast(currentElement)) + result = ar; + break; + } + } } - qDebug() << Q_FUNC_INFO << "Invalid margin side passed:" << (int)side; - return atLeft; + return result; } /*! - Returns the axis type that describes the opposite axis of an axis with the specified \a type. + Returns the axes that currently have selected parts, i.e. whose selection state is not \ref + QCPAxis::spNone. + + \see selectedPlottables, selectedLegends, setInteractions, QCPAxis::setSelectedParts, + QCPAxis::setSelectableParts */ -QCPAxis::AxisType QCPAxis::opposite(QCPAxis::AxisType type) +QList QCustomPlot::selectedAxes() const { - switch (type) + QList result, allAxes; + foreach (QCPAxisRect *rect, axisRects()) + allAxes << rect->axes(); + + foreach (QCPAxis *axis, allAxes) { - case atLeft: return atRight; break; - case atRight: return atLeft; break; - case atBottom: return atTop; break; - case atTop: return atBottom; break; - default: qDebug() << Q_FUNC_INFO << "invalid axis type"; return atLeft; break; + if (axis->selectedParts() != QCPAxis::spNone) + result.append(axis); } + + return result; } -/*! \internal +/*! + Returns the legends that currently have selected parts, i.e. whose selection state is not \ref + QCPLegend::spNone. - This function is called to prepare the tick vector, sub tick vector and tick label vector. If - \ref setAutoTicks is set to true, appropriate tick values are determined automatically via \ref - generateAutoTicks. If it's set to false, the signal ticksRequest is emitted, which can be used to - provide external tick positions. Then the sub tick vectors and tick label vectors are created. + \see selectedPlottables, selectedAxes, setInteractions, QCPLegend::setSelectedParts, + QCPLegend::setSelectableParts, QCPLegend::selectedItems */ -void QCPAxis::setupTickVectors() +QList QCustomPlot::selectedLegends() const { - if (!mParentPlot) return; - if ((!mTicks && !mTickLabels && !mGrid->visible()) || mRange.size() <= 0) return; - - // fill tick vectors, either by auto generating or by notifying user to fill the vectors himself - if (mAutoTicks) - { - generateAutoTicks(); - } else - { - emit ticksRequest(); - } + QList result; - visibleTickBounds(mLowestVisibleTick, mHighestVisibleTick); - if (mTickVector.isEmpty()) - { - mSubTickVector.clear(); - return; - } + QStack elementStack; + if (mPlotLayout) + elementStack.push(mPlotLayout); - // generate subticks between ticks: - mSubTickVector.resize((mTickVector.size()-1)*mSubTickCount); - if (mSubTickCount > 0) + while (!elementStack.isEmpty()) { - double subTickStep = 0; - double subTickPosition = 0; - int subTickIndex = 0; - bool done = false; - int lowTick = mLowestVisibleTick > 0 ? mLowestVisibleTick-1 : mLowestVisibleTick; - int highTick = mHighestVisibleTick < mTickVector.size()-1 ? mHighestVisibleTick+1 : mHighestVisibleTick; - for (int i=lowTick+1; i<=highTick; ++i) + foreach (QCPLayoutElement *subElement, elementStack.pop()->elements(false)) { - subTickStep = (mTickVector.at(i)-mTickVector.at(i-1))/(double)(mSubTickCount+1); - for (int k=1; k<=mSubTickCount; ++k) + if (subElement) { - subTickPosition = mTickVector.at(i-1) + k*subTickStep; - if (subTickPosition < mRange.lower) - continue; - if (subTickPosition > mRange.upper) + elementStack.push(subElement); + if (QCPLegend *leg = qobject_cast(subElement)) { - done = true; - break; + if (leg->selectedParts() != QCPLegend::spNone) + result.append(leg); } - mSubTickVector[subTickIndex] = subTickPosition; - subTickIndex++; } - if (done) break; } - mSubTickVector.resize(subTickIndex); } + + return result; +} - // generate tick labels according to tick positions: - if (mAutoTickLabels) - { - int vecsize = mTickVector.size(); - mTickVectorLabels.resize(vecsize); - if (mTickLabelType == ltNumber) - { - for (int i=mLowestVisibleTick; i<=mHighestVisibleTick; ++i) - mTickVectorLabels[i] = mParentPlot->locale().toString(mTickVector.at(i), mNumberFormatChar.toLatin1(), mNumberPrecision); - } else if (mTickLabelType == ltDateTime) - { - for (int i=mLowestVisibleTick; i<=mHighestVisibleTick; ++i) - { -#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) // use fromMSecsSinceEpoch function if available, to gain sub-second accuracy on tick labels (e.g. for format "hh:mm:ss:zzz") - mTickVectorLabels[i] = mParentPlot->locale().toString(QDateTime::fromTime_t(mTickVector.at(i)).toTimeSpec(mDateTimeSpec), mDateTimeFormat); -#else - mTickVectorLabels[i] = mParentPlot->locale().toString(QDateTime::fromMSecsSinceEpoch(mTickVector.at(i)*1000).toTimeSpec(mDateTimeSpec), mDateTimeFormat); -#endif - } - } - } else // mAutoTickLabels == false +/*! + Deselects all layerables (plottables, items, axes, legends,...) of the QCustomPlot. + + Since calling this function is not a user interaction, this does not emit the \ref + selectionChangedByUser signal. The individual selectionChanged signals are emitted though, if the + objects were previously selected. + + \see setInteractions, selectedPlottables, selectedItems, selectedAxes, selectedLegends +*/ +void QCustomPlot::deselectAll() +{ + foreach (QCPLayer *layer, mLayers) { - if (mAutoTicks) // ticks generated automatically, but not ticklabels, so emit ticksRequest here for labels - { - emit ticksRequest(); - } - // make sure provided tick label vector has correct (minimal) length: - if (mTickVectorLabels.size() < mTickVector.size()) - mTickVectorLabels.resize(mTickVector.size()); + foreach (QCPLayerable *layerable, layer->children()) + layerable->deselectEvent(nullptr); } } -/*! \internal +/*! + Causes a complete replot into the internal paint buffer(s). Finally, the widget surface is + refreshed with the new buffer contents. This is the method that must be called to make changes to + the plot, e.g. on the axis ranges or data points of graphs, visible. + + The parameter \a refreshPriority can be used to fine-tune the timing of the replot. For example + if your application calls \ref replot very quickly in succession (e.g. multiple independent + functions change some aspects of the plot and each wants to make sure the change gets replotted), + it is advisable to set \a refreshPriority to \ref QCustomPlot::rpQueuedReplot. This way, the + actual replotting is deferred to the next event loop iteration. Multiple successive calls of \ref + replot with this priority will only cause a single replot, avoiding redundant replots and + improving performance. + + Under a few circumstances, QCustomPlot causes a replot by itself. Those are resize events of the + QCustomPlot widget and user interactions (object selection and range dragging/zooming). + + Before the replot happens, the signal \ref beforeReplot is emitted. After the replot, \ref + afterReplot is emitted. It is safe to mutually connect the replot slot with any of those two + signals on two QCustomPlots to make them replot synchronously, it won't cause an infinite + recursion. + + If a layer is in mode \ref QCPLayer::lmBuffered (\ref QCPLayer::setMode), it is also possible to + replot only that specific layer via \ref QCPLayer::replot. See the documentation there for + details. - If \ref setAutoTicks is set to true, this function is called by \ref setupTickVectors to - generate reasonable tick positions (and subtick count). The algorithm tries to create - approximately mAutoTickCount ticks (set via \ref setAutoTickCount). - - If the scale is logarithmic, \ref setAutoTickCount is ignored, and one tick is generated at every - power of the current logarithm base, set via \ref setScaleLogBase. + \see replotTime */ -void QCPAxis::generateAutoTicks() +void QCustomPlot::replot(QCustomPlot::RefreshPriority refreshPriority) { - if (mScaleType == stLinear) - { - if (mAutoTickStep) - { - // Generate tick positions according to linear scaling: - mTickStep = mRange.size()/(double)(mAutoTickCount+1e-10); // mAutoTickCount ticks on average, the small addition is to prevent jitter on exact integers - double magnitudeFactor = qPow(10.0, qFloor(qLn(mTickStep)/qLn(10.0))); // get magnitude factor e.g. 0.01, 1, 10, 1000 etc. - double tickStepMantissa = mTickStep/magnitudeFactor; - if (tickStepMantissa < 5) - { - // round digit after decimal point to 0.5 - mTickStep = (int)(tickStepMantissa*2)/2.0*magnitudeFactor; - } else - { - // round to first digit in multiples of 2 - mTickStep = (int)(tickStepMantissa/2.0)*2.0*magnitudeFactor; - } - } - if (mAutoSubTicks) - mSubTickCount = calculateAutoSubTickCount(mTickStep); - // Generate tick positions according to mTickStep: - qint64 firstStep = floor(mRange.lower/mTickStep); // do not use qFloor here, or we'll lose 64 bit precision - qint64 lastStep = ceil(mRange.upper/mTickStep); // do not use qCeil here, or we'll lose 64 bit precision - int tickcount = lastStep-firstStep+1; - if (tickcount < 0) tickcount = 0; - mTickVector.resize(tickcount); - for (int i=0; i 0 && mRange.upper > 0) // positive range - { - double lowerMag = basePow(qFloor(baseLog(mRange.lower))); - double currentMag = lowerMag; - mTickVector.clear(); - mTickVector.append(currentMag); - while (currentMag < mRange.upper && currentMag > 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case - { - currentMag *= mScaleLogBase; - mTickVector.append(currentMag); - } - } else if (mRange.lower < 0 && mRange.upper < 0) // negative range - { - double lowerMag = -basePow(qCeil(baseLog(-mRange.lower))); - double currentMag = lowerMag; - mTickVector.clear(); - mTickVector.append(currentMag); - while (currentMag < mRange.upper && currentMag < 0) // currentMag might be zero for ranges ~1e-300, just cancel in that case - { - currentMag /= mScaleLogBase; - mTickVector.append(currentMag); - } - } else // invalid range for logarithmic scale, because lower and upper have different sign + if (!mReplotQueued) { - mTickVector.clear(); - qDebug() << Q_FUNC_INFO << "Invalid range for logarithmic plot: " << mRange.lower << "-" << mRange.upper; + mReplotQueued = true; + QTimer::singleShot(0, this, SLOT(replot())); } + return; } + + if (mReplotting) // incase signals loop back to replot slot + return; + mReplotting = true; + mReplotQueued = false; + emit beforeReplot(); + +# if QT_VERSION < QT_VERSION_CHECK(4, 8, 0) + QTime replotTimer; + replotTimer.start(); +# else + QElapsedTimer replotTimer; + replotTimer.start(); +# endif + + updateLayout(); + // draw all layered objects (grid, axes, plottables, items, legend,...) into their buffers: + setupPaintBuffers(); + foreach (QCPLayer *layer, mLayers) + layer->drawToPaintBuffer(); + foreach (QSharedPointer buffer, mPaintBuffers) + buffer->setInvalidated(false); + + if ((refreshPriority == rpRefreshHint && mPlottingHints.testFlag(QCP::phImmediateRefresh)) || refreshPriority==rpImmediateRefresh) + repaint(); + else + update(); + +# if QT_VERSION < QT_VERSION_CHECK(4, 8, 0) + mReplotTime = replotTimer.elapsed(); +# else + mReplotTime = replotTimer.nsecsElapsed()*1e-6; +# endif + if (!qFuzzyIsNull(mReplotTimeAverage)) + mReplotTimeAverage = mReplotTimeAverage*0.9 + mReplotTime*0.1; // exponential moving average with a time constant of 10 last replots + else + mReplotTimeAverage = mReplotTime; // no previous replots to average with, so initialize with replot time + + emit afterReplot(); + mReplotting = false; +} + +/*! + Returns the time in milliseconds that the last replot took. If \a average is set to true, an + exponential moving average over the last couple of replots is returned. + + \see replot +*/ +double QCustomPlot::replotTime(bool average) const +{ + return average ? mReplotTimeAverage : mReplotTime; +} + +/*! + Rescales the axes such that all plottables (like graphs) in the plot are fully visible. + + if \a onlyVisiblePlottables is set to true, only the plottables that have their visibility set to true + (QCPLayerable::setVisible), will be used to rescale the axes. + + \see QCPAbstractPlottable::rescaleAxes, QCPAxis::rescale +*/ +void QCustomPlot::rescaleAxes(bool onlyVisiblePlottables) +{ + QList allAxes; + foreach (QCPAxisRect *rect, axisRects()) + allAxes << rect->axes(); + + foreach (QCPAxis *axis, allAxes) + axis->rescale(onlyVisiblePlottables); } -/*! \internal - - Called by generateAutoTicks when \ref setAutoSubTicks is set to true. Depending on the \a - tickStep between two major ticks on the axis, a different number of sub ticks is appropriate. For - Example taking 4 sub ticks for a \a tickStep of 1 makes more sense than taking 5 sub ticks, - because this corresponds to a sub tick step of 0.2, instead of the less intuitive 0.16667. Note - that a subtick count of 4 means dividing the major tick step into 5 sections. - - This is implemented by a hand made lookup for integer tick steps as well as fractional tick steps - with a fractional part of (approximately) 0.5. If a tick step is different (i.e. has no - fractional part close to 0.5), the currently set sub tick count (\ref setSubTickCount) is - returned. +/*! + Saves a PDF with the vectorized plot to the file \a fileName. The axis ratio as well as the scale + of texts and lines will be derived from the specified \a width and \a height. This means, the + output will look like the normal on-screen output of a QCustomPlot widget with the corresponding + pixel width and height. If either \a width or \a height is zero, the exported image will have the + same dimensions as the QCustomPlot widget currently has. + + Setting \a exportPen to \ref QCP::epNoCosmetic allows to disable the use of cosmetic pens when + drawing to the PDF file. Cosmetic pens are pens with numerical width 0, which are always drawn as + a one pixel wide line, no matter what zoom factor is set in the PDF-Viewer. For more information + about cosmetic pens, see the QPainter and QPen documentation. + + The objects of the plot will appear in the current selection state. If you don't want any + selected objects to be painted in their selected look, deselect everything with \ref deselectAll + before calling this function. + + Returns true on success. + + \warning + \li If you plan on editing the exported PDF file with a vector graphics editor like Inkscape, it + is advised to set \a exportPen to \ref QCP::epNoCosmetic to avoid losing those cosmetic lines + (which might be quite many, because cosmetic pens are the default for e.g. axes and tick marks). + \li If calling this function inside the constructor of the parent of the QCustomPlot widget + (i.e. the MainWindow constructor, if QCustomPlot is inside the MainWindow), always provide + explicit non-zero widths and heights. If you leave \a width or \a height as 0 (default), this + function uses the current width and height of the QCustomPlot widget. However, in Qt, these + aren't defined yet inside the constructor, so you would get an image that has strange + widths/heights. + + \a pdfCreator and \a pdfTitle may be used to set the according metadata fields in the resulting + PDF file. + + \note On Android systems, this method does nothing and issues an according qDebug warning + message. This is also the case if for other reasons the define flag \c QT_NO_PRINTER is set. + + \see savePng, saveBmp, saveJpg, saveRastered */ -int QCPAxis::calculateAutoSubTickCount(double tickStep) const +bool QCustomPlot::savePdf(const QString &fileName, int width, int height, QCP::ExportPen exportPen, const QString &pdfCreator, const QString &pdfTitle) { - int result = mSubTickCount; // default to current setting, if no proper value can be found - - // get mantissa of tickstep: - double magnitudeFactor = qPow(10.0, qFloor(qLn(tickStep)/qLn(10.0))); // get magnitude factor e.g. 0.01, 1, 10, 1000 etc. - double tickStepMantissa = tickStep/magnitudeFactor; - - // separate integer and fractional part of mantissa: - double epsilon = 0.01; - double intPartf; - int intPart; - double fracPart = modf(tickStepMantissa, &intPartf); - intPart = intPartf; - - // handle cases with (almost) integer mantissa: - if (fracPart < epsilon || 1.0-fracPart < epsilon) + bool success = false; +#ifdef QT_NO_PRINTER + Q_UNUSED(fileName) + Q_UNUSED(exportPen) + Q_UNUSED(width) + Q_UNUSED(height) + Q_UNUSED(pdfCreator) + Q_UNUSED(pdfTitle) + qDebug() << Q_FUNC_INFO << "Qt was built without printer support (QT_NO_PRINTER). PDF not created."; +#else + int newWidth, newHeight; + if (width == 0 || height == 0) { - if (1.0-fracPart < epsilon) - ++intPart; - switch (intPart) - { - case 1: result = 4; break; // 1.0 -> 0.2 substep - case 2: result = 3; break; // 2.0 -> 0.5 substep - case 3: result = 2; break; // 3.0 -> 1.0 substep - case 4: result = 3; break; // 4.0 -> 1.0 substep - case 5: result = 4; break; // 5.0 -> 1.0 substep - case 6: result = 2; break; // 6.0 -> 2.0 substep - case 7: result = 6; break; // 7.0 -> 1.0 substep - case 8: result = 3; break; // 8.0 -> 2.0 substep - case 9: result = 2; break; // 9.0 -> 3.0 substep - } + newWidth = this->width(); + newHeight = this->height(); } else { - // handle cases with significantly fractional mantissa: - if (qAbs(fracPart-0.5) < epsilon) // *.5 mantissa - { - switch (intPart) - { - case 1: result = 2; break; // 1.5 -> 0.5 substep - case 2: result = 4; break; // 2.5 -> 0.5 substep - case 3: result = 4; break; // 3.5 -> 0.7 substep - case 4: result = 2; break; // 4.5 -> 1.5 substep - case 5: result = 4; break; // 5.5 -> 1.1 substep (won't occur with autoTickStep from here on) - case 6: result = 4; break; // 6.5 -> 1.3 substep - case 7: result = 2; break; // 7.5 -> 2.5 substep - case 8: result = 4; break; // 8.5 -> 1.7 substep - case 9: result = 4; break; // 9.5 -> 1.9 substep - } - } - // if mantissa fraction isnt 0.0 or 0.5, don't bother finding good sub tick marks, leave default + newWidth = width; + newHeight = height; } - return result; -} - -/* inherits documentation from base class */ -void QCPAxis::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) -{ - Q_UNUSED(event) - SelectablePart part = details.value(); - if (mSelectableParts.testFlag(part)) + QPrinter printer(QPrinter::ScreenResolution); + printer.setOutputFileName(fileName); + printer.setOutputFormat(QPrinter::PdfFormat); + printer.setColorMode(QPrinter::Color); + printer.printEngine()->setProperty(QPrintEngine::PPK_Creator, pdfCreator); + printer.printEngine()->setProperty(QPrintEngine::PPK_DocumentName, pdfTitle); + QRect oldViewport = viewport(); + setViewport(QRect(0, 0, newWidth, newHeight)); +#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0) + printer.setFullPage(true); + printer.setPaperSize(viewport().size(), QPrinter::DevicePixel); +#else + QPageLayout pageLayout; + pageLayout.setMode(QPageLayout::FullPageMode); + pageLayout.setOrientation(QPageLayout::Portrait); + pageLayout.setMargins(QMarginsF(0, 0, 0, 0)); + pageLayout.setPageSize(QPageSize(viewport().size(), QPageSize::Point, QString(), QPageSize::ExactMatch)); + printer.setPageLayout(pageLayout); +#endif + QCPPainter printpainter; + if (printpainter.begin(&printer)) { - SelectableParts selBefore = mSelectedParts; - setSelectedParts(additive ? mSelectedParts^part : part); - if (selectionStateChanged) - *selectionStateChanged = mSelectedParts != selBefore; + printpainter.setMode(QCPPainter::pmVectorized); + printpainter.setMode(QCPPainter::pmNoCaching); + printpainter.setMode(QCPPainter::pmNonCosmetic, exportPen==QCP::epNoCosmetic); + printpainter.setWindow(mViewport); + if (mBackgroundBrush.style() != Qt::NoBrush && + mBackgroundBrush.color() != Qt::white && + mBackgroundBrush.color() != Qt::transparent && + mBackgroundBrush.color().alpha() > 0) // draw pdf background color if not white/transparent + printpainter.fillRect(viewport(), mBackgroundBrush); + draw(&printpainter); + printpainter.end(); + success = true; } + setViewport(oldViewport); +#endif // QT_NO_PRINTER + return success; } -/* inherits documentation from base class */ -void QCPAxis::deselectEvent(bool *selectionStateChanged) -{ - SelectableParts selBefore = mSelectedParts; - setSelectedParts(mSelectedParts & ~mSelectableParts); - if (selectionStateChanged) - *selectionStateChanged = mSelectedParts != selBefore; -} +/*! + Saves a PNG image file to \a fileName on disc. The output plot will have the dimensions \a width + and \a height in pixels, multiplied by \a scale. If either \a width or \a height is zero, the + current width and height of the QCustomPlot widget is used instead. Line widths and texts etc. + are not scaled up when larger widths/heights are used. If you want that effect, use the \a scale + parameter. -/*! \internal + For example, if you set both \a width and \a height to 100 and \a scale to 2, you will end up with an + image file of size 200*200 in which all graphical elements are scaled up by factor 2 (line widths, + texts, etc.). This scaling is not done by stretching a 100*100 image, the result will have full + 200*200 pixel resolution. - A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter - before drawing axis lines. + If you use a high scaling factor, it is recommended to enable antialiasing for all elements by + temporarily setting \ref QCustomPlot::setAntialiasedElements to \ref QCP::aeAll as this allows + QCustomPlot to place objects with sub-pixel accuracy. - This is the antialiasing state the painter passed to the \ref draw method is in by default. - - This function takes into account the local setting of the antialiasing flag as well as the - overrides set with \ref QCustomPlot::setAntialiasedElements and \ref - QCustomPlot::setNotAntialiasedElements. - - \see setAntialiased + image compression can be controlled with the \a quality parameter which must be between 0 and 100 + or -1 to use the default setting. + + The \a resolution will be written to the image file header and has no direct consequence for the + quality or the pixel size. However, if opening the image with a tool which respects the metadata, + it will be able to scale the image to match either a given size in real units of length (inch, + centimeters, etc.), or the target display DPI. You can specify in which units \a resolution is + given, by setting \a resolutionUnit. The \a resolution is converted to the format's expected + resolution unit internally. + + Returns true on success. If this function fails, most likely the PNG format isn't supported by + the system, see Qt docs about QImageWriter::supportedImageFormats(). + + The objects of the plot will appear in the current selection state. If you don't want any selected + objects to be painted in their selected look, deselect everything with \ref deselectAll before calling + this function. + + If you want the PNG to have a transparent background, call \ref setBackground(const QBrush &brush) + with no brush (Qt::NoBrush) or a transparent color (Qt::transparent), before saving. + + \warning If calling this function inside the constructor of the parent of the QCustomPlot widget + (i.e. the MainWindow constructor, if QCustomPlot is inside the MainWindow), always provide + explicit non-zero widths and heights. If you leave \a width or \a height as 0 (default), this + function uses the current width and height of the QCustomPlot widget. However, in Qt, these + aren't defined yet inside the constructor, so you would get an image that has strange + widths/heights. + + \see savePdf, saveBmp, saveJpg, saveRastered */ -void QCPAxis::applyDefaultAntialiasingHint(QCPPainter *painter) const +bool QCustomPlot::savePng(const QString &fileName, int width, int height, double scale, int quality, int resolution, QCP::ResolutionUnit resolutionUnit) { - applyAntialiasingHint(painter, mAntialiased, QCP::aeAxes); + return saveRastered(fileName, width, height, scale, "PNG", quality, resolution, resolutionUnit); } -/*! \internal - - Draws the axis with the specified \a painter, using the internal QCPAxisPainterPrivate instance. +/*! + Saves a JPEG image file to \a fileName on disc. The output plot will have the dimensions \a width + and \a height in pixels, multiplied by \a scale. If either \a width or \a height is zero, the + current width and height of the QCustomPlot widget is used instead. Line widths and texts etc. + are not scaled up when larger widths/heights are used. If you want that effect, use the \a scale + parameter. + + For example, if you set both \a width and \a height to 100 and \a scale to 2, you will end up with an + image file of size 200*200 in which all graphical elements are scaled up by factor 2 (line widths, + texts, etc.). This scaling is not done by stretching a 100*100 image, the result will have full + 200*200 pixel resolution. + + If you use a high scaling factor, it is recommended to enable antialiasing for all elements by + temporarily setting \ref QCustomPlot::setAntialiasedElements to \ref QCP::aeAll as this allows + QCustomPlot to place objects with sub-pixel accuracy. + image compression can be controlled with the \a quality parameter which must be between 0 and 100 + or -1 to use the default setting. + + The \a resolution will be written to the image file header and has no direct consequence for the + quality or the pixel size. However, if opening the image with a tool which respects the metadata, + it will be able to scale the image to match either a given size in real units of length (inch, + centimeters, etc.), or the target display DPI. You can specify in which units \a resolution is + given, by setting \a resolutionUnit. The \a resolution is converted to the format's expected + resolution unit internally. + + Returns true on success. If this function fails, most likely the JPEG format isn't supported by + the system, see Qt docs about QImageWriter::supportedImageFormats(). + + The objects of the plot will appear in the current selection state. If you don't want any selected + objects to be painted in their selected look, deselect everything with \ref deselectAll before calling + this function. + + \warning If calling this function inside the constructor of the parent of the QCustomPlot widget + (i.e. the MainWindow constructor, if QCustomPlot is inside the MainWindow), always provide + explicit non-zero widths and heights. If you leave \a width or \a height as 0 (default), this + function uses the current width and height of the QCustomPlot widget. However, in Qt, these + aren't defined yet inside the constructor, so you would get an image that has strange + widths/heights. + + \see savePdf, savePng, saveBmp, saveRastered */ -void QCPAxis::draw(QCPPainter *painter) +bool QCustomPlot::saveJpg(const QString &fileName, int width, int height, double scale, int quality, int resolution, QCP::ResolutionUnit resolutionUnit) { - const int lowTick = mLowestVisibleTick; - const int highTick = mHighestVisibleTick; - QVector subTickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter - QVector tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter - QVector tickLabels; // the final vector passed to QCPAxisPainter - tickPositions.reserve(highTick-lowTick+1); - tickLabels.reserve(highTick-lowTick+1); - subTickPositions.reserve(mSubTickVector.size()); - - if (mTicks) - { - for (int i=lowTick; i<=highTick; ++i) - { - tickPositions.append(coordToPixel(mTickVector.at(i))); - if (mTickLabels) - tickLabels.append(mTickVectorLabels.at(i)); - } - - if (mSubTickCount > 0) - { - const int subTickCount = mSubTickVector.size(); - for (int i=0; itype = mAxisType; - mAxisPainter->basePen = getBasePen(); - mAxisPainter->labelFont = getLabelFont(); - mAxisPainter->labelColor = getLabelColor(); - mAxisPainter->label = mLabel; - mAxisPainter->substituteExponent = mAutoTickLabels && mNumberBeautifulPowers && mTickLabelType == ltNumber; - mAxisPainter->tickPen = getTickPen(); - mAxisPainter->subTickPen = getSubTickPen(); - mAxisPainter->tickLabelFont = getTickLabelFont(); - mAxisPainter->tickLabelColor = getTickLabelColor(); - mAxisPainter->axisRect = mAxisRect->rect(); - mAxisPainter->viewportRect = mParentPlot->viewport(); - mAxisPainter->abbreviateDecimalPowers = mScaleType == stLogarithmic; - mAxisPainter->reversedEndings = mRangeReversed; - mAxisPainter->tickPositions = tickPositions; - mAxisPainter->tickLabels = tickLabels; - mAxisPainter->subTickPositions = subTickPositions; - mAxisPainter->draw(painter); + return saveRastered(fileName, width, height, scale, "JPG", quality, resolution, resolutionUnit); } -/*! \internal - - Returns via \a lowIndex and \a highIndex, which ticks in the current tick vector are visible in - the current range. The return values are indices of the tick vector, not the positions of the - ticks themselves. - - The actual use of this function is when an external tick vector is provided, since it might - exceed far beyond the currently displayed range, and would cause unnecessary calculations e.g. of - subticks. - - If all ticks are outside the axis range, an inverted range is returned, i.e. highIndex will be - smaller than lowIndex. There is one case, where this function returns indices that are not really - visible in the current axis range: When the tick spacing is larger than the axis range size and - one tick is below the axis range and the next tick is already above the axis range. Because in - such cases it is usually desirable to know the tick pair, to draw proper subticks. +/*! + Saves a BMP image file to \a fileName on disc. The output plot will have the dimensions \a width + and \a height in pixels, multiplied by \a scale. If either \a width or \a height is zero, the + current width and height of the QCustomPlot widget is used instead. Line widths and texts etc. + are not scaled up when larger widths/heights are used. If you want that effect, use the \a scale + parameter. + + For example, if you set both \a width and \a height to 100 and \a scale to 2, you will end up with an + image file of size 200*200 in which all graphical elements are scaled up by factor 2 (line widths, + texts, etc.). This scaling is not done by stretching a 100*100 image, the result will have full + 200*200 pixel resolution. + + If you use a high scaling factor, it is recommended to enable antialiasing for all elements by + temporarily setting \ref QCustomPlot::setAntialiasedElements to \ref QCP::aeAll as this allows + QCustomPlot to place objects with sub-pixel accuracy. + + The \a resolution will be written to the image file header and has no direct consequence for the + quality or the pixel size. However, if opening the image with a tool which respects the metadata, + it will be able to scale the image to match either a given size in real units of length (inch, + centimeters, etc.), or the target display DPI. You can specify in which units \a resolution is + given, by setting \a resolutionUnit. The \a resolution is converted to the format's expected + resolution unit internally. + + Returns true on success. If this function fails, most likely the BMP format isn't supported by + the system, see Qt docs about QImageWriter::supportedImageFormats(). + + The objects of the plot will appear in the current selection state. If you don't want any selected + objects to be painted in their selected look, deselect everything with \ref deselectAll before calling + this function. + + \warning If calling this function inside the constructor of the parent of the QCustomPlot widget + (i.e. the MainWindow constructor, if QCustomPlot is inside the MainWindow), always provide + explicit non-zero widths and heights. If you leave \a width or \a height as 0 (default), this + function uses the current width and height of the QCustomPlot widget. However, in Qt, these + aren't defined yet inside the constructor, so you would get an image that has strange + widths/heights. + + \see savePdf, savePng, saveJpg, saveRastered */ -void QCPAxis::visibleTickBounds(int &lowIndex, int &highIndex) const +bool QCustomPlot::saveBmp(const QString &fileName, int width, int height, double scale, int resolution, QCP::ResolutionUnit resolutionUnit) { - bool lowFound = false; - bool highFound = false; - lowIndex = 0; - highIndex = -1; - - for (int i=0; i < mTickVector.size(); ++i) - { - if (mTickVector.at(i) >= mRange.lower) - { - lowFound = true; - lowIndex = i; - break; - } - } - for (int i=mTickVector.size()-1; i >= 0; --i) - { - if (mTickVector.at(i) <= mRange.upper) - { - highFound = true; - highIndex = i; - break; - } - } - - if (!lowFound && highFound) - lowIndex = highIndex+1; - else if (lowFound && !highFound) - highIndex = lowIndex-1; + return saveRastered(fileName, width, height, scale, "BMP", -1, resolution, resolutionUnit); } /*! \internal - A log function with the base mScaleLogBase, used mostly for coordinate transforms in logarithmic - scales with arbitrary log base. Uses the buffered mScaleLogBaseLogInv for faster calculation. - This is set to 1.0/qLn(mScaleLogBase) in \ref setScaleLogBase. - - \see basePow, setScaleLogBase, setScaleType + Returns a minimum size hint that corresponds to the minimum size of the top level layout + (\ref plotLayout). To prevent QCustomPlot from being collapsed to size/width zero, set a minimum + size (setMinimumSize) either on the whole QCustomPlot or on any layout elements inside the plot. + This is especially important, when placed in a QLayout where other components try to take in as + much space as possible (e.g. QMdiArea). */ -double QCPAxis::baseLog(double value) const +QSize QCustomPlot::minimumSizeHint() const { - return qLn(value)*mScaleLogBaseLogInv; + return mPlotLayout->minimumOuterSizeHint(); } /*! \internal - A power function with the base mScaleLogBase, used mostly for coordinate transforms in - logarithmic scales with arbitrary log base. + Returns a size hint that is the same as \ref minimumSizeHint. - \see baseLog, setScaleLogBase, setScaleType */ -double QCPAxis::basePow(double value) const +QSize QCustomPlot::sizeHint() const { - return qPow(mScaleLogBase, value); + return mPlotLayout->minimumOuterSizeHint(); } /*! \internal - Returns the pen that is used to draw the axis base line. Depending on the selection state, this - is either mSelectedBasePen or mBasePen. + Event handler for when the QCustomPlot widget needs repainting. This does not cause a \ref replot, but + draws the internal buffer on the widget surface. */ -QPen QCPAxis::getBasePen() const +void QCustomPlot::paintEvent(QPaintEvent *event) { - return mSelectedParts.testFlag(spAxis) ? mSelectedBasePen : mBasePen; + Q_UNUSED(event) + + // detect if the device pixel ratio has changed (e.g. moving window between different DPI screens), and adapt buffers if necessary: +#ifdef QCP_DEVICEPIXELRATIO_SUPPORTED +# ifdef QCP_DEVICEPIXELRATIO_FLOAT + double newDpr = devicePixelRatioF(); +# else + double newDpr = devicePixelRatio(); +# endif + if (!qFuzzyCompare(mBufferDevicePixelRatio, newDpr)) + { + setBufferDevicePixelRatio(newDpr); + replot(QCustomPlot::rpQueuedRefresh); + return; + } +#endif + + QCPPainter painter(this); + if (painter.isActive()) + { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + painter.setRenderHint(QPainter::HighQualityAntialiasing); // to make Antialiasing look good if using the OpenGL graphicssystem +#endif + if (mBackgroundBrush.style() != Qt::NoBrush) + painter.fillRect(mViewport, mBackgroundBrush); + drawBackground(&painter); + foreach (QSharedPointer buffer, mPaintBuffers) + buffer->draw(&painter); + } } /*! \internal - Returns the pen that is used to draw the (major) ticks. Depending on the selection state, this - is either mSelectedTickPen or mTickPen. + Event handler for a resize of the QCustomPlot widget. The viewport (which becomes the outer rect + of mPlotLayout) is resized appropriately. Finally a \ref replot is performed. */ -QPen QCPAxis::getTickPen() const +void QCustomPlot::resizeEvent(QResizeEvent *event) { - return mSelectedParts.testFlag(spAxis) ? mSelectedTickPen : mTickPen; + Q_UNUSED(event) + // resize and repaint the buffer: + setViewport(rect()); + replot(rpQueuedRefresh); // queued refresh is important here, to prevent painting issues in some contexts (e.g. MDI subwindow) } /*! \internal - Returns the pen that is used to draw the subticks. Depending on the selection state, this - is either mSelectedSubTickPen or mSubTickPen. + Event handler for when a double click occurs. Emits the \ref mouseDoubleClick signal, then + determines the layerable under the cursor and forwards the event to it. Finally, emits the + specialized signals when certain objecs are clicked (e.g. \ref plottableDoubleClick, \ref + axisDoubleClick, etc.). + + \see mousePressEvent, mouseReleaseEvent */ -QPen QCPAxis::getSubTickPen() const +void QCustomPlot::mouseDoubleClickEvent(QMouseEvent *event) { - return mSelectedParts.testFlag(spAxis) ? mSelectedSubTickPen : mSubTickPen; + emit mouseDoubleClick(event); + mMouseHasMoved = false; + mMousePressPos = event->pos(); + + // determine layerable under the cursor (this event is called instead of the second press event in a double-click): + QList details; + QList candidates = layerableListAt(mMousePressPos, false, &details); + for (int i=0; iaccept(); // default impl of QCPLayerable's mouse events ignore the event, in that case propagate to next candidate in list + candidates.at(i)->mouseDoubleClickEvent(event, details.at(i)); + if (event->isAccepted()) + { + mMouseEventLayerable = candidates.at(i); + mMouseEventLayerableDetails = details.at(i); + break; + } + } + + // emit specialized object double click signals: + if (!candidates.isEmpty()) + { + if (QCPAbstractPlottable *ap = qobject_cast(candidates.first())) + { + int dataIndex = 0; + if (!details.first().value().isEmpty()) + dataIndex = details.first().value().dataRange().begin(); + emit plottableDoubleClick(ap, dataIndex, event); + } else if (QCPAxis *ax = qobject_cast(candidates.first())) + emit axisDoubleClick(ax, details.first().value(), event); + else if (QCPAbstractItem *ai = qobject_cast(candidates.first())) + emit itemDoubleClick(ai, event); + else if (QCPLegend *lg = qobject_cast(candidates.first())) + emit legendDoubleClick(lg, nullptr, event); + else if (QCPAbstractLegendItem *li = qobject_cast(candidates.first())) + emit legendDoubleClick(li->parentLegend(), li, event); + } + + event->accept(); // in case QCPLayerable reimplementation manipulates event accepted state. In QWidget event system, QCustomPlot wants to accept the event. } /*! \internal - Returns the font that is used to draw the tick labels. Depending on the selection state, this - is either mSelectedTickLabelFont or mTickLabelFont. -*/ -QFont QCPAxis::getTickLabelFont() const -{ - return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelFont : mTickLabelFont; -} + Event handler for when a mouse button is pressed. Emits the mousePress signal. -/*! \internal + If the current \ref setSelectionRectMode is not \ref QCP::srmNone, passes the event to the + selection rect. Otherwise determines the layerable under the cursor and forwards the event to it. - Returns the font that is used to draw the axis label. Depending on the selection state, this - is either mSelectedLabelFont or mLabelFont. + \see mouseMoveEvent, mouseReleaseEvent */ -QFont QCPAxis::getLabelFont() const +void QCustomPlot::mousePressEvent(QMouseEvent *event) { - return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelFont : mLabelFont; + emit mousePress(event); + // save some state to tell in releaseEvent whether it was a click: + mMouseHasMoved = false; + mMousePressPos = event->pos(); + + if (mSelectionRect && mSelectionRectMode != QCP::srmNone) + { + if (mSelectionRectMode != QCP::srmZoom || qobject_cast(axisRectAt(mMousePressPos))) // in zoom mode only activate selection rect if on an axis rect + mSelectionRect->startSelection(event); + } else + { + // no selection rect interaction, prepare for click signal emission and forward event to layerable under the cursor: + QList details; + QList candidates = layerableListAt(mMousePressPos, false, &details); + if (!candidates.isEmpty()) + { + mMouseSignalLayerable = candidates.first(); // candidate for signal emission is always topmost hit layerable (signal emitted in release event) + mMouseSignalLayerableDetails = details.first(); + } + // forward event to topmost candidate which accepts the event: + for (int i=0; iaccept(); // default impl of QCPLayerable's mouse events call ignore() on the event, in that case propagate to next candidate in list + candidates.at(i)->mousePressEvent(event, details.at(i)); + if (event->isAccepted()) + { + mMouseEventLayerable = candidates.at(i); + mMouseEventLayerableDetails = details.at(i); + break; + } + } + } + + event->accept(); // in case QCPLayerable reimplementation manipulates event accepted state. In QWidget event system, QCustomPlot wants to accept the event. } /*! \internal - Returns the color that is used to draw the tick labels. Depending on the selection state, this - is either mSelectedTickLabelColor or mTickLabelColor. -*/ -QColor QCPAxis::getTickLabelColor() const -{ - return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelColor : mTickLabelColor; -} + Event handler for when the cursor is moved. Emits the \ref mouseMove signal. -/*! \internal + If the selection rect (\ref setSelectionRect) is currently active, the event is forwarded to it + in order to update the rect geometry. - Returns the color that is used to draw the axis label. Depending on the selection state, this - is either mSelectedLabelColor or mLabelColor. + Otherwise, if a layout element has mouse capture focus (a mousePressEvent happened on top of the + layout element before), the mouseMoveEvent is forwarded to that element. + + \see mousePressEvent, mouseReleaseEvent */ -QColor QCPAxis::getLabelColor() const +void QCustomPlot::mouseMoveEvent(QMouseEvent *event) { - return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelColor : mLabelColor; -} - -/*! \internal + emit mouseMove(event); - Returns the appropriate outward margin for this axis. It is needed if \ref - QCPAxisRect::setAutoMargins is set to true on the parent axis rect. An axis with axis type \ref - atLeft will return an appropriate left margin, \ref atBottom will return an appropriate bottom - margin and so forth. For the calculation, this function goes through similar steps as \ref draw, - so changing one function likely requires the modification of the other one as well. + if (!mMouseHasMoved && (mMousePressPos-event->pos()).manhattanLength() > 3) + mMouseHasMoved = true; // moved too far from mouse press position, don't handle as click on mouse release - The margin consists of the outward tick length, tick label padding, tick label size, label - padding, label size, and padding. + if (mSelectionRect && mSelectionRect->isActive()) + mSelectionRect->moveSelection(event); + else if (mMouseEventLayerable) // call event of affected layerable: + mMouseEventLayerable->mouseMoveEvent(event, mMousePressPos); - The margin is cached internally, so repeated calls while leaving the axis range, fonts, etc. - unchanged are very fast. + event->accept(); // in case QCPLayerable reimplementation manipulates event accepted state. In QWidget event system, QCustomPlot wants to accept the event. +} + +/*! \internal + + Event handler for when a mouse button is released. Emits the \ref mouseRelease signal. + + If the mouse was moved less than a certain threshold in any direction since the \ref + mousePressEvent, it is considered a click which causes the selection mechanism (if activated via + \ref setInteractions) to possibly change selection states accordingly. Further, specialized mouse + click signals are emitted (e.g. \ref plottableClick, \ref axisClick, etc.) + + If a layerable is the mouse capturer (a \ref mousePressEvent happened on top of the layerable + before), the \ref mouseReleaseEvent is forwarded to that element. + + \see mousePressEvent, mouseMoveEvent */ -int QCPAxis::calculateMargin() +void QCustomPlot::mouseReleaseEvent(QMouseEvent *event) { - if (!mVisible) // if not visible, directly return 0, don't cache 0 because we can't react to setVisible in QCPAxis - return 0; - - if (mCachedMarginValid) - return mCachedMargin; + emit mouseRelease(event); - // run through similar steps as QCPAxis::draw, and caluclate margin needed to fit axis and its labels - int margin = 0; + if (!mMouseHasMoved) // mouse hasn't moved (much) between press and release, so handle as click + { + if (mSelectionRect && mSelectionRect->isActive()) // a simple click shouldn't successfully finish a selection rect, so cancel it here + mSelectionRect->cancel(); + if (event->button() == Qt::LeftButton) + processPointSelection(event); + + // emit specialized click signals of QCustomPlot instance: + if (QCPAbstractPlottable *ap = qobject_cast(mMouseSignalLayerable)) + { + int dataIndex = 0; + if (!mMouseSignalLayerableDetails.value().isEmpty()) + dataIndex = mMouseSignalLayerableDetails.value().dataRange().begin(); + emit plottableClick(ap, dataIndex, event); + } else if (QCPAxis *ax = qobject_cast(mMouseSignalLayerable)) + emit axisClick(ax, mMouseSignalLayerableDetails.value(), event); + else if (QCPAbstractItem *ai = qobject_cast(mMouseSignalLayerable)) + emit itemClick(ai, event); + else if (QCPLegend *lg = qobject_cast(mMouseSignalLayerable)) + emit legendClick(lg, nullptr, event); + else if (QCPAbstractLegendItem *li = qobject_cast(mMouseSignalLayerable)) + emit legendClick(li->parentLegend(), li, event); + mMouseSignalLayerable = nullptr; + } - int lowTick, highTick; - visibleTickBounds(lowTick, highTick); - QVector tickPositions; // the final coordToPixel transformed vector passed to QCPAxisPainter - QVector tickLabels; // the final vector passed to QCPAxisPainter - tickPositions.reserve(highTick-lowTick+1); - tickLabels.reserve(highTick-lowTick+1); - if (mTicks) + if (mSelectionRect && mSelectionRect->isActive()) // Note: if a click was detected above, the selection rect is canceled there + { + // finish selection rect, the appropriate action will be taken via signal-slot connection: + mSelectionRect->endSelection(event); + } else { - for (int i=lowTick; i<=highTick; ++i) + // call event of affected layerable: + if (mMouseEventLayerable) { - tickPositions.append(coordToPixel(mTickVector.at(i))); - if (mTickLabels) - tickLabels.append(mTickVectorLabels.at(i)); + mMouseEventLayerable->mouseReleaseEvent(event, mMousePressPos); + mMouseEventLayerable = nullptr; } } - // transfer all properties of this axis to QCPAxisPainterPrivate which it needs to calculate the size. - // Note that some axis painter properties are already set by direct feed-through with QCPAxis setters - mAxisPainter->type = mAxisType; - mAxisPainter->labelFont = getLabelFont(); - mAxisPainter->label = mLabel; - mAxisPainter->tickLabelFont = mTickLabelFont; - mAxisPainter->axisRect = mAxisRect->rect(); - mAxisPainter->viewportRect = mParentPlot->viewport(); - mAxisPainter->tickPositions = tickPositions; - mAxisPainter->tickLabels = tickLabels; - margin += mAxisPainter->size(); - margin += mPadding; - - mCachedMargin = margin; - mCachedMarginValid = true; - return margin; + + if (noAntialiasingOnDrag()) + replot(rpQueuedReplot); + + event->accept(); // in case QCPLayerable reimplementation manipulates event accepted state. In QWidget event system, QCustomPlot wants to accept the event. } -/* inherits documentation from base class */ -QCP::Interaction QCPAxis::selectionCategory() const +/*! \internal + + Event handler for mouse wheel events. First, the \ref mouseWheel signal is emitted. Then + determines the affected layerable and forwards the event to it. +*/ +void QCustomPlot::wheelEvent(QWheelEvent *event) { - return QCP::iSelectAxes; + emit mouseWheel(event); + +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + const QPointF pos = event->pos(); +#else + const QPointF pos = event->position(); +#endif + + // forward event to layerable under cursor: + foreach (QCPLayerable *candidate, layerableListAt(pos, false)) + { + event->accept(); // default impl of QCPLayerable's mouse events ignore the event, in that case propagate to next candidate in list + candidate->wheelEvent(event); + if (event->isAccepted()) + break; + } + event->accept(); // in case QCPLayerable reimplementation manipulates event accepted state. In QWidget event system, QCustomPlot wants to accept the event. } - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPAxisPainterPrivate -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPAxisPainterPrivate - - \internal - \brief (Private) - - This is a private class and not part of the public QCustomPlot interface. +/*! \internal - It is used by QCPAxis to do the low-level drawing of axis backbone, tick marks, tick labels and - axis label. It also buffers the labels to reduce replot times. The parameters are configured by - directly accessing the public member variables. -*/ + This function draws the entire plot, including background pixmap, with the specified \a painter. + It does not make use of the paint buffers like \ref replot, so this is the function typically + used by saving/exporting methods such as \ref savePdf or \ref toPainter. -/*! - Constructs a QCPAxisPainterPrivate instance. Make sure to not create a new instance on every - redraw, to utilize the caching mechanisms. + Note that it does not fill the background with the background brush (as the user may specify with + \ref setBackground(const QBrush &brush)), this is up to the respective functions calling this + method. */ -QCPAxisPainterPrivate::QCPAxisPainterPrivate(QCustomPlot *parentPlot) : - type(QCPAxis::atLeft), - basePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), - lowerEnding(QCPLineEnding::esNone), - upperEnding(QCPLineEnding::esNone), - labelPadding(0), - tickLabelPadding(0), - tickLabelRotation(0), - tickLabelSide(QCPAxis::lsOutside), - substituteExponent(true), - numberMultiplyCross(false), - tickLengthIn(5), - tickLengthOut(0), - subTickLengthIn(2), - subTickLengthOut(0), - tickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), - subTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), - offset(0), - abbreviateDecimalPowers(false), - reversedEndings(false), - mParentPlot(parentPlot), - mLabelCache(16) // cache at most 16 (tick) labels +void QCustomPlot::draw(QCPPainter *painter) { + updateLayout(); + + // draw viewport background pixmap: + drawBackground(painter); + + // draw all layered objects (grid, axes, plottables, items, legend,...): + foreach (QCPLayer *layer, mLayers) + layer->draw(painter); + + /* Debug code to draw all layout element rects + foreach (QCPLayoutElement *el, findChildren()) + { + painter->setBrush(Qt::NoBrush); + painter->setPen(QPen(QColor(0, 0, 0, 100), 0, Qt::DashLine)); + painter->drawRect(el->rect()); + painter->setPen(QPen(QColor(255, 0, 0, 100), 0, Qt::DashLine)); + painter->drawRect(el->outerRect()); + } + */ } -QCPAxisPainterPrivate::~QCPAxisPainterPrivate() +/*! \internal + + Performs the layout update steps defined by \ref QCPLayoutElement::UpdatePhase, by calling \ref + QCPLayoutElement::update on the main plot layout. + + Here, the layout elements calculate their positions and margins, and prepare for the following + draw call. +*/ +void QCustomPlot::updateLayout() { + // run through layout phases: + mPlotLayout->update(QCPLayoutElement::upPreparation); + mPlotLayout->update(QCPLayoutElement::upMargins); + mPlotLayout->update(QCPLayoutElement::upLayout); + + emit afterLayout(); } /*! \internal - Draws the axis with the specified \a painter. + Draws the viewport background pixmap of the plot. - The selection boxes (mAxisSelectionBox, mTickLabelsSelectionBox, mLabelSelectionBox) are set - here, too. + If a pixmap was provided via \ref setBackground, this function buffers the scaled version + depending on \ref setBackgroundScaled and \ref setBackgroundScaledMode and then draws it inside + the viewport with the provided \a painter. The scaled version is buffered in + mScaledBackgroundPixmap to prevent expensive rescaling at every redraw. It is only updated, when + the axis rect has changed in a way that requires a rescale of the background pixmap (this is + dependent on the \ref setBackgroundScaledMode), or when a differend axis background pixmap was + set. + + Note that this function does not draw a fill with the background brush + (\ref setBackground(const QBrush &brush)) beneath the pixmap. + + \see setBackground, setBackgroundScaled, setBackgroundScaledMode */ -void QCPAxisPainterPrivate::draw(QCPPainter *painter) +void QCustomPlot::drawBackground(QCPPainter *painter) { - QByteArray newHash = generateLabelParameterHash(); - if (newHash != mLabelParameterHash) - { - mLabelCache.clear(); - mLabelParameterHash = newHash; - } - - QPoint origin; - switch (type) - { - case QCPAxis::atLeft: origin = axisRect.bottomLeft() +QPoint(-offset, 0); break; - case QCPAxis::atRight: origin = axisRect.bottomRight()+QPoint(+offset, 0); break; - case QCPAxis::atTop: origin = axisRect.topLeft() +QPoint(0, -offset); break; - case QCPAxis::atBottom: origin = axisRect.bottomLeft() +QPoint(0, +offset); break; - } + // Note: background color is handled in individual replot/save functions - double xCor = 0, yCor = 0; // paint system correction, for pixel exact matches (affects baselines and ticks of top/right axes) - switch (type) - { - case QCPAxis::atTop: yCor = -1; break; - case QCPAxis::atRight: xCor = 1; break; - default: break; - } - int margin = 0; - // draw baseline: - QLineF baseLine; - painter->setPen(basePen); - if (QCPAxis::orientation(type) == Qt::Horizontal) - baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(axisRect.width()+xCor, yCor)); - else - baseLine.setPoints(origin+QPointF(xCor, yCor), origin+QPointF(xCor, -axisRect.height()+yCor)); - if (reversedEndings) - baseLine = QLineF(baseLine.p2(), baseLine.p1()); // won't make a difference for line itself, but for line endings later - painter->drawLine(baseLine); - - // draw ticks: - if (!tickPositions.isEmpty()) + // draw background pixmap (on top of fill, if brush specified): + if (!mBackgroundPixmap.isNull()) { - painter->setPen(tickPen); - int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1; // direction of ticks ("inward" is right for left axis and left for right axis) - if (QCPAxis::orientation(type) == Qt::Horizontal) + if (mBackgroundScaled) { - for (int i=0; idrawLine(QLineF(tickPositions.at(i)+xCor, origin.y()-tickLengthOut*tickDir+yCor, tickPositions.at(i)+xCor, origin.y()+tickLengthIn*tickDir+yCor)); + // check whether mScaledBackground needs to be updated: + QSize scaledSize(mBackgroundPixmap.size()); + scaledSize.scale(mViewport.size(), mBackgroundScaledMode); + if (mScaledBackgroundPixmap.size() != scaledSize) + mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mViewport.size(), mBackgroundScaledMode, Qt::SmoothTransformation); + painter->drawPixmap(mViewport.topLeft(), mScaledBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height()) & mScaledBackgroundPixmap.rect()); } else { - for (int i=0; idrawLine(QLineF(origin.x()-tickLengthOut*tickDir+xCor, tickPositions.at(i)+yCor, origin.x()+tickLengthIn*tickDir+xCor, tickPositions.at(i)+yCor)); + painter->drawPixmap(mViewport.topLeft(), mBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height())); } } +} + +/*! \internal + + Goes through the layers and makes sure this QCustomPlot instance holds the correct number of + paint buffers and that they have the correct configuration (size, pixel ratio, etc.). + Allocations, reallocations and deletions of paint buffers are performed as necessary. It also + associates the paint buffers with the layers, so they draw themselves into the right buffer when + \ref QCPLayer::drawToPaintBuffer is called. This means it associates adjacent \ref + QCPLayer::lmLogical layers to a mutual paint buffer and creates dedicated paint buffers for + layers in \ref QCPLayer::lmBuffered mode. + + This method uses \ref createPaintBuffer to create new paint buffers. + + After this method, the paint buffers are empty (filled with \c Qt::transparent) and invalidated + (so an attempt to replot only a single buffered layer causes a full replot). + + This method is called in every \ref replot call, prior to actually drawing the layers (into their + associated paint buffer). If the paint buffers don't need changing/reallocating, this method + basically leaves them alone and thus finishes very fast. +*/ +void QCustomPlot::setupPaintBuffers() +{ + int bufferIndex = 0; + if (mPaintBuffers.isEmpty()) + mPaintBuffers.append(QSharedPointer(createPaintBuffer())); - // draw subticks: - if (!subTickPositions.isEmpty()) + for (int layerIndex = 0; layerIndex < mLayers.size(); ++layerIndex) { - painter->setPen(subTickPen); - // direction of ticks ("inward" is right for left axis and left for right axis) - int tickDir = (type == QCPAxis::atBottom || type == QCPAxis::atRight) ? -1 : 1; - if (QCPAxis::orientation(type) == Qt::Horizontal) + QCPLayer *layer = mLayers.at(layerIndex); + if (layer->mode() == QCPLayer::lmLogical) { - for (int i=0; idrawLine(QLineF(subTickPositions.at(i)+xCor, origin.y()-subTickLengthOut*tickDir+yCor, subTickPositions.at(i)+xCor, origin.y()+subTickLengthIn*tickDir+yCor)); - } else + layer->mPaintBuffer = mPaintBuffers.at(bufferIndex).toWeakRef(); + } else if (layer->mode() == QCPLayer::lmBuffered) { - for (int i=0; idrawLine(QLineF(origin.x()-subTickLengthOut*tickDir+xCor, subTickPositions.at(i)+yCor, origin.x()+subTickLengthIn*tickDir+xCor, subTickPositions.at(i)+yCor)); + ++bufferIndex; + if (bufferIndex >= mPaintBuffers.size()) + mPaintBuffers.append(QSharedPointer(createPaintBuffer())); + layer->mPaintBuffer = mPaintBuffers.at(bufferIndex).toWeakRef(); + if (layerIndex < mLayers.size()-1 && mLayers.at(layerIndex+1)->mode() == QCPLayer::lmLogical) // not last layer, and next one is logical, so prepare another buffer for next layerables + { + ++bufferIndex; + if (bufferIndex >= mPaintBuffers.size()) + mPaintBuffers.append(QSharedPointer(createPaintBuffer())); + } } } - margin += qMax(0, qMax(tickLengthOut, subTickLengthOut)); - - // draw axis base endings: - bool antialiasingBackup = painter->antialiasing(); - painter->setAntialiasing(true); // always want endings to be antialiased, even if base and ticks themselves aren't - painter->setBrush(QBrush(basePen.color())); - QVector2D baseLineVector(baseLine.dx(), baseLine.dy()); - if (lowerEnding.style() != QCPLineEnding::esNone) - lowerEnding.draw(painter, QVector2D(baseLine.p1())-baseLineVector.normalized()*lowerEnding.realLength()*(lowerEnding.inverted()?-1:1), -baseLineVector); - if (upperEnding.style() != QCPLineEnding::esNone) - upperEnding.draw(painter, QVector2D(baseLine.p2())+baseLineVector.normalized()*upperEnding.realLength()*(upperEnding.inverted()?-1:1), baseLineVector); - painter->setAntialiasing(antialiasingBackup); - - // tick labels: - QRect oldClipRect; - if (tickLabelSide == QCPAxis::lsInside) // if using inside labels, clip them to the axis rect - { - oldClipRect = painter->clipRegion().boundingRect(); - painter->setClipRect(axisRect); - } - QSize tickLabelsSize(0, 0); // size of largest tick label, for offset calculation of axis label - if (!tickLabels.isEmpty()) - { - if (tickLabelSide == QCPAxis::lsOutside) - margin += tickLabelPadding; - painter->setFont(tickLabelFont); - painter->setPen(QPen(tickLabelColor)); - const int maxLabelIndex = qMin(tickPositions.size(), tickLabels.size()); - int distanceToAxis = margin; - if (tickLabelSide == QCPAxis::lsInside) - distanceToAxis = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding); - for (int i=0; isetClipRect(oldClipRect); - - // axis label: - QRect labelBounds; - if (!label.isEmpty()) + // remove unneeded buffers: + while (mPaintBuffers.size()-1 > bufferIndex) + mPaintBuffers.removeLast(); + // resize buffers to viewport size and clear contents: + foreach (QSharedPointer buffer, mPaintBuffers) { - margin += labelPadding; - painter->setFont(labelFont); - painter->setPen(QPen(labelColor)); - labelBounds = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip, label); - if (type == QCPAxis::atLeft) - { - QTransform oldTransform = painter->transform(); - painter->translate((origin.x()-margin-labelBounds.height()), origin.y()); - painter->rotate(-90); - painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); - painter->setTransform(oldTransform); - } - else if (type == QCPAxis::atRight) - { - QTransform oldTransform = painter->transform(); - painter->translate((origin.x()+margin+labelBounds.height()), origin.y()-axisRect.height()); - painter->rotate(90); - painter->drawText(0, 0, axisRect.height(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); - painter->setTransform(oldTransform); - } - else if (type == QCPAxis::atTop) - painter->drawText(origin.x(), origin.y()-margin-labelBounds.height(), axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); - else if (type == QCPAxis::atBottom) - painter->drawText(origin.x(), origin.y()+margin, axisRect.width(), labelBounds.height(), Qt::TextDontClip | Qt::AlignCenter, label); + buffer->setSize(viewport().size()); // won't do anything if already correct size + buffer->clear(Qt::transparent); + buffer->setInvalidated(); } - - // set selection boxes: - int selectionTolerance = 0; - if (mParentPlot) - selectionTolerance = mParentPlot->selectionTolerance(); - else - qDebug() << Q_FUNC_INFO << "mParentPlot is null"; - int selAxisOutSize = qMax(qMax(tickLengthOut, subTickLengthOut), selectionTolerance); - int selAxisInSize = selectionTolerance; - int selTickLabelSize; - int selTickLabelOffset; - if (tickLabelSide == QCPAxis::lsOutside) +} + +/*! \internal + + This method is used by \ref setupPaintBuffers when it needs to create new paint buffers. + + Depending on the current setting of \ref setOpenGl, and the current Qt version, different + backends (subclasses of \ref QCPAbstractPaintBuffer) are created, initialized with the proper + size and device pixel ratio, and returned. +*/ +QCPAbstractPaintBuffer *QCustomPlot::createPaintBuffer() +{ + if (mOpenGl) { - selTickLabelSize = (QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width()); - selTickLabelOffset = qMax(tickLengthOut, subTickLengthOut)+tickLabelPadding; +#if defined(QCP_OPENGL_FBO) + return new QCPPaintBufferGlFbo(viewport().size(), mBufferDevicePixelRatio, mGlContext, mGlPaintDevice); +#elif defined(QCP_OPENGL_PBUFFER) + return new QCPPaintBufferGlPbuffer(viewport().size(), mBufferDevicePixelRatio, mOpenGlMultisamples); +#else + qDebug() << Q_FUNC_INFO << "OpenGL enabled even though no support for it compiled in, this shouldn't have happened. Falling back to pixmap paint buffer."; + return new QCPPaintBufferPixmap(viewport().size(), mBufferDevicePixelRatio); +#endif } else - { - selTickLabelSize = -(QCPAxis::orientation(type) == Qt::Horizontal ? tickLabelsSize.height() : tickLabelsSize.width()); - selTickLabelOffset = -(qMax(tickLengthIn, subTickLengthIn)+tickLabelPadding); - } - int selLabelSize = labelBounds.height(); - int selLabelOffset = qMax(tickLengthOut, subTickLengthOut)+(!tickLabels.isEmpty() && tickLabelSide == QCPAxis::lsOutside ? tickLabelPadding+selTickLabelSize : 0)+labelPadding; - if (type == QCPAxis::atLeft) - { - mAxisSelectionBox.setCoords(origin.x()-selAxisOutSize, axisRect.top(), origin.x()+selAxisInSize, axisRect.bottom()); - mTickLabelsSelectionBox.setCoords(origin.x()-selTickLabelOffset-selTickLabelSize, axisRect.top(), origin.x()-selTickLabelOffset, axisRect.bottom()); - mLabelSelectionBox.setCoords(origin.x()-selLabelOffset-selLabelSize, axisRect.top(), origin.x()-selLabelOffset, axisRect.bottom()); - } else if (type == QCPAxis::atRight) - { - mAxisSelectionBox.setCoords(origin.x()-selAxisInSize, axisRect.top(), origin.x()+selAxisOutSize, axisRect.bottom()); - mTickLabelsSelectionBox.setCoords(origin.x()+selTickLabelOffset+selTickLabelSize, axisRect.top(), origin.x()+selTickLabelOffset, axisRect.bottom()); - mLabelSelectionBox.setCoords(origin.x()+selLabelOffset+selLabelSize, axisRect.top(), origin.x()+selLabelOffset, axisRect.bottom()); - } else if (type == QCPAxis::atTop) - { - mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisOutSize, axisRect.right(), origin.y()+selAxisInSize); - mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()-selTickLabelOffset-selTickLabelSize, axisRect.right(), origin.y()-selTickLabelOffset); - mLabelSelectionBox.setCoords(axisRect.left(), origin.y()-selLabelOffset-selLabelSize, axisRect.right(), origin.y()-selLabelOffset); - } else if (type == QCPAxis::atBottom) - { - mAxisSelectionBox.setCoords(axisRect.left(), origin.y()-selAxisInSize, axisRect.right(), origin.y()+selAxisOutSize); - mTickLabelsSelectionBox.setCoords(axisRect.left(), origin.y()+selTickLabelOffset+selTickLabelSize, axisRect.right(), origin.y()+selTickLabelOffset); - mLabelSelectionBox.setCoords(axisRect.left(), origin.y()+selLabelOffset+selLabelSize, axisRect.right(), origin.y()+selLabelOffset); - } - mAxisSelectionBox = mAxisSelectionBox.normalized(); - mTickLabelsSelectionBox = mTickLabelsSelectionBox.normalized(); - mLabelSelectionBox = mLabelSelectionBox.normalized(); - // draw hitboxes for debug purposes: - //painter->setBrush(Qt::NoBrush); - //painter->drawRects(QVector() << mAxisSelectionBox << mTickLabelsSelectionBox << mLabelSelectionBox); + return new QCPPaintBufferPixmap(viewport().size(), mBufferDevicePixelRatio); } -/*! \internal - - Returns the size ("margin" in QCPAxisRect context, so measured perpendicular to the axis backbone - direction) needed to fit the axis. +/*! + This method returns whether any of the paint buffers held by this QCustomPlot instance are + invalidated. + + If any buffer is invalidated, a partial replot (\ref QCPLayer::replot) is not allowed and always + causes a full replot (\ref QCustomPlot::replot) of all layers. This is the case when for example + the layer order has changed, new layers were added or removed, layer modes were changed (\ref + QCPLayer::setMode), or layerables were added or removed. + + \see QCPAbstractPaintBuffer::setInvalidated */ -int QCPAxisPainterPrivate::size() const +bool QCustomPlot::hasInvalidatedPaintBuffers() { - int result = 0; - - // get length of tick marks pointing outwards: - if (!tickPositions.isEmpty()) - result += qMax(0, qMax(tickLengthOut, subTickLengthOut)); - - // calculate size of tick labels: - if (tickLabelSide == QCPAxis::lsOutside) + foreach (QSharedPointer buffer, mPaintBuffers) { - QSize tickLabelsSize(0, 0); - if (!tickLabels.isEmpty()) - { - for (int i=0; iinvalidated()) + return true; + } + return false; +} + +/*! \internal + + When \ref setOpenGl is set to true, this method is used to initialize OpenGL (create a context, + surface, paint device). + + Returns true on success. + + If this method is successful, all paint buffers should be deleted and then reallocated by calling + \ref setupPaintBuffers, so the OpenGL-based paint buffer subclasses (\ref + QCPPaintBufferGlPbuffer, \ref QCPPaintBufferGlFbo) are used for subsequent replots. + + \see freeOpenGl +*/ +bool QCustomPlot::setupOpenGl() +{ +#ifdef QCP_OPENGL_FBO + freeOpenGl(); + QSurfaceFormat proposedSurfaceFormat; + proposedSurfaceFormat.setSamples(mOpenGlMultisamples); +#ifdef QCP_OPENGL_OFFSCREENSURFACE + QOffscreenSurface *surface = new QOffscreenSurface; +#else + QWindow *surface = new QWindow; + surface->setSurfaceType(QSurface::OpenGLSurface); +#endif + surface->setFormat(proposedSurfaceFormat); + surface->create(); + mGlSurface = QSharedPointer(surface); + mGlContext = QSharedPointer(new QOpenGLContext); + mGlContext->setFormat(mGlSurface->format()); + if (!mGlContext->create()) + { + qDebug() << Q_FUNC_INFO << "Failed to create OpenGL context"; + mGlContext.clear(); + mGlSurface.clear(); + return false; } - - // calculate size of axis label (only height needed, because left/right labels are rotated by 90 degrees): - if (!label.isEmpty()) + if (!mGlContext->makeCurrent(mGlSurface.data())) // context needs to be current to create paint device { - QFontMetrics fontMetrics(labelFont); - QRect bounds; - bounds = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter | Qt::AlignVCenter, label); - result += bounds.height() + labelPadding; + qDebug() << Q_FUNC_INFO << "Failed to make opengl context current"; + mGlContext.clear(); + mGlSurface.clear(); + return false; } - - return result; + if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()) + { + qDebug() << Q_FUNC_INFO << "OpenGL of this system doesn't support frame buffer objects"; + mGlContext.clear(); + mGlSurface.clear(); + return false; + } + mGlPaintDevice = QSharedPointer(new QOpenGLPaintDevice); + return true; +#elif defined(QCP_OPENGL_PBUFFER) + return QGLFormat::hasOpenGL(); +#else + return false; +#endif +} + +/*! \internal + + When \ref setOpenGl is set to false, this method is used to deinitialize OpenGL (releases the + context and frees resources). + + After OpenGL is disabled, all paint buffers should be deleted and then reallocated by calling + \ref setupPaintBuffers, so the standard software rendering paint buffer subclass (\ref + QCPPaintBufferPixmap) is used for subsequent replots. + + \see setupOpenGl +*/ +void QCustomPlot::freeOpenGl() +{ +#ifdef QCP_OPENGL_FBO + mGlPaintDevice.clear(); + mGlContext.clear(); + mGlSurface.clear(); +#endif } /*! \internal - Clears the internal label cache. Upon the next \ref draw, all labels will be created new. This - method is called automatically in \ref draw, if any parameters have changed that invalidate the - cached labels, such as font, color, etc. + This method is used by \ref QCPAxisRect::removeAxis to report removed axes to the QCustomPlot + so it may clear its QCustomPlot::xAxis, yAxis, xAxis2 and yAxis2 members accordingly. */ -void QCPAxisPainterPrivate::clearCache() +void QCustomPlot::axisRemoved(QCPAxis *axis) { - mLabelCache.clear(); + if (xAxis == axis) + xAxis = nullptr; + if (xAxis2 == axis) + xAxis2 = nullptr; + if (yAxis == axis) + yAxis = nullptr; + if (yAxis2 == axis) + yAxis2 = nullptr; + + // Note: No need to take care of range drag axes and range zoom axes, because they are stored in smart pointers } /*! \internal - Returns a hash that allows uniquely identifying whether the label parameters have changed such - that the cached labels must be refreshed (\ref clearCache). It is used in \ref draw. If the - return value of this method hasn't changed since the last redraw, the respective label parameters - haven't changed and cached labels may be used. + This method is used by the QCPLegend destructor to report legend removal to the QCustomPlot so + it may clear its QCustomPlot::legend member accordingly. */ -QByteArray QCPAxisPainterPrivate::generateLabelParameterHash() const +void QCustomPlot::legendRemoved(QCPLegend *legend) { - QByteArray result; - result.append(QByteArray::number(tickLabelRotation)); - result.append(QByteArray::number((int)tickLabelSide)); - result.append(QByteArray::number((int)substituteExponent)); - result.append(QByteArray::number((int)numberMultiplyCross)); - result.append(tickLabelColor.name().toLatin1()+QByteArray::number(tickLabelColor.alpha(), 16)); - result.append(tickLabelFont.toString().toLatin1()); - return result; + if (this->legend == legend) + this->legend = nullptr; } /*! \internal - Draws a single tick label with the provided \a painter, utilizing the internal label cache to - significantly speed up drawing of labels that were drawn in previous calls. The tick label is - always bound to an axis, the distance to the axis is controllable via \a distanceToAxis in - pixels. The pixel position in the axis direction is passed in the \a position parameter. Hence - for the bottom axis, \a position would indicate the horizontal pixel position (not coordinate), - at which the label should be drawn. + This slot is connected to the selection rect's \ref QCPSelectionRect::accepted signal when \ref + setSelectionRectMode is set to \ref QCP::srmSelect. + + First, it determines which axis rect was the origin of the selection rect judging by the starting + point of the selection. Then it goes through the plottables (\ref QCPAbstractPlottable1D to be + precise) associated with that axis rect and finds the data points that are in \a rect. It does + this by querying their \ref QCPAbstractPlottable1D::selectTestRect method. - In order to later draw the axis label in a place that doesn't overlap with the tick labels, the - largest tick label size is needed. This is acquired by passing a \a tickLabelsSize to the \ref - drawTickLabel calls during the process of drawing all tick labels of one axis. In every call, \a - tickLabelsSize is expanded, if the drawn label exceeds the value \a tickLabelsSize currently - holds. + Then, the actual selection is done by calling the plottables' \ref + QCPAbstractPlottable::selectEvent, placing the found selected data points in the \a details + parameter as QVariant(\ref QCPDataSelection). All plottables that weren't touched by \a + rect receive a \ref QCPAbstractPlottable::deselectEvent. - The label is drawn with the font and pen that are currently set on the \a painter. To draw - superscripted powers, the font is temporarily made smaller by a fixed factor (see \ref - getTickLabelData). + \see processRectZoom */ -void QCPAxisPainterPrivate::placeTickLabel(QCPPainter *painter, double position, int distanceToAxis, const QString &text, QSize *tickLabelsSize) +void QCustomPlot::processRectSelection(QRect rect, QMouseEvent *event) { - // warning: if you change anything here, also adapt getMaxTickLabelSize() accordingly! - if (text.isEmpty()) return; - QSize finalSize; - QPointF labelAnchor; - switch (type) - { - case QCPAxis::atLeft: labelAnchor = QPointF(axisRect.left()-distanceToAxis-offset, position); break; - case QCPAxis::atRight: labelAnchor = QPointF(axisRect.right()+distanceToAxis+offset, position); break; - case QCPAxis::atTop: labelAnchor = QPointF(position, axisRect.top()-distanceToAxis-offset); break; - case QCPAxis::atBottom: labelAnchor = QPointF(position, axisRect.bottom()+distanceToAxis+offset); break; - } - if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && !painter->modes().testFlag(QCPPainter::pmNoCaching)) // label caching enabled - { - CachedLabel *cachedLabel = mLabelCache.take(text); // attempt to get label from cache - if (!cachedLabel) // no cached label existed, create it - { - cachedLabel = new CachedLabel; - TickLabelData labelData = getTickLabelData(painter->font(), text); - cachedLabel->offset = getTickLabelDrawOffset(labelData)+labelData.rotatedTotalBounds.topLeft(); - cachedLabel->pixmap = QPixmap(labelData.rotatedTotalBounds.size()); - cachedLabel->pixmap.fill(Qt::transparent); - QCPPainter cachePainter(&cachedLabel->pixmap); - cachePainter.setPen(painter->pen()); - drawTickLabel(&cachePainter, -labelData.rotatedTotalBounds.topLeft().x(), -labelData.rotatedTotalBounds.topLeft().y(), labelData); - } - // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels): - bool labelClippedByBorder = false; - if (tickLabelSide == QCPAxis::lsOutside) - { - if (QCPAxis::orientation(type) == Qt::Horizontal) - labelClippedByBorder = labelAnchor.x()+cachedLabel->offset.x()+cachedLabel->pixmap.width() > viewportRect.right() || labelAnchor.x()+cachedLabel->offset.x() < viewportRect.left(); - else - labelClippedByBorder = labelAnchor.y()+cachedLabel->offset.y()+cachedLabel->pixmap.height() > viewportRect.bottom() || labelAnchor.y()+cachedLabel->offset.y() < viewportRect.top(); - } - if (!labelClippedByBorder) - { - painter->drawPixmap(labelAnchor+cachedLabel->offset, cachedLabel->pixmap); - finalSize = cachedLabel->pixmap.size(); - } - mLabelCache.insert(text, cachedLabel); // return label to cache or insert for the first time if newly created - } else // label caching disabled, draw text directly on surface: + typedef QPair SelectionCandidate; + typedef QMultiMap SelectionCandidates; // map key is number of selected data points, so we have selections sorted by size + + bool selectionStateChanged = false; + + if (mInteractions.testFlag(QCP::iSelectPlottables)) { - TickLabelData labelData = getTickLabelData(painter->font(), text); - QPointF finalPosition = labelAnchor + getTickLabelDrawOffset(labelData); - // if label would be partly clipped by widget border on sides, don't draw it (only for outside tick labels): - bool labelClippedByBorder = false; - if (tickLabelSide == QCPAxis::lsOutside) - { - if (QCPAxis::orientation(type) == Qt::Horizontal) - labelClippedByBorder = finalPosition.x()+(labelData.rotatedTotalBounds.width()+labelData.rotatedTotalBounds.left()) > viewportRect.right() || finalPosition.x()+labelData.rotatedTotalBounds.left() < viewportRect.left(); - else - labelClippedByBorder = finalPosition.y()+(labelData.rotatedTotalBounds.height()+labelData.rotatedTotalBounds.top()) > viewportRect.bottom() || finalPosition.y()+labelData.rotatedTotalBounds.top() < viewportRect.top(); - } - if (!labelClippedByBorder) + SelectionCandidates potentialSelections; + QRectF rectF(rect.normalized()); + if (QCPAxisRect *affectedAxisRect = axisRectAt(rectF.topLeft())) { - drawTickLabel(painter, finalPosition.x(), finalPosition.y(), labelData); - finalSize = labelData.rotatedTotalBounds.size(); + // determine plottables that were hit by the rect and thus are candidates for selection: + foreach (QCPAbstractPlottable *plottable, affectedAxisRect->plottables()) + { + if (QCPPlottableInterface1D *plottableInterface = plottable->interface1D()) + { + QCPDataSelection dataSel = plottableInterface->selectTestRect(rectF, true); + if (!dataSel.isEmpty()) + potentialSelections.insert(dataSel.dataPointCount(), SelectionCandidate(plottable, dataSel)); + } + } + + if (!mInteractions.testFlag(QCP::iMultiSelect)) + { + // only leave plottable with most selected points in map, since we will only select a single plottable: + if (!potentialSelections.isEmpty()) + { + SelectionCandidates::iterator it = potentialSelections.begin(); + while (it != std::prev(potentialSelections.end())) // erase all except last element + it = potentialSelections.erase(it); + } + } + + bool additive = event->modifiers().testFlag(mMultiSelectModifier); + // deselect all other layerables if not additive selection: + if (!additive) + { + // emit deselection except to those plottables who will be selected afterwards: + foreach (QCPLayer *layer, mLayers) + { + foreach (QCPLayerable *layerable, layer->children()) + { + if ((potentialSelections.isEmpty() || potentialSelections.constBegin()->first != layerable) && mInteractions.testFlag(layerable->selectionCategory())) + { + bool selChanged = false; + layerable->deselectEvent(&selChanged); + selectionStateChanged |= selChanged; + } + } + } + } + + // go through selections in reverse (largest selection first) and emit select events: + SelectionCandidates::const_iterator it = potentialSelections.constEnd(); + while (it != potentialSelections.constBegin()) + { + --it; + if (mInteractions.testFlag(it.value().first->selectionCategory())) + { + bool selChanged = false; + it.value().first->selectEvent(event, additive, QVariant::fromValue(it.value().second), &selChanged); + selectionStateChanged |= selChanged; + } + } } } - // expand passed tickLabelsSize if current tick label is larger: - if (finalSize.width() > tickLabelsSize->width()) - tickLabelsSize->setWidth(finalSize.width()); - if (finalSize.height() > tickLabelsSize->height()) - tickLabelsSize->setHeight(finalSize.height()); + if (selectionStateChanged) + { + emit selectionChangedByUser(); + replot(rpQueuedReplot); + } else if (mSelectionRect) + mSelectionRect->layer()->replot(); } /*! \internal - This is a \ref placeTickLabel helper function. + This slot is connected to the selection rect's \ref QCPSelectionRect::accepted signal when \ref + setSelectionRectMode is set to \ref QCP::srmZoom. + + It determines which axis rect was the origin of the selection rect judging by the starting point + of the selection, and then zooms the axes defined via \ref QCPAxisRect::setRangeZoomAxes to the + provided \a rect (see \ref QCPAxisRect::zoom). - Draws the tick label specified in \a labelData with \a painter at the pixel positions \a x and \a - y. This function is used by \ref placeTickLabel to create new tick labels for the cache, or to - directly draw the labels on the QCustomPlot surface when label caching is disabled, i.e. when - QCP::phCacheLabels plotting hint is not set. + \see processRectSelection */ -void QCPAxisPainterPrivate::drawTickLabel(QCPPainter *painter, double x, double y, const TickLabelData &labelData) const +void QCustomPlot::processRectZoom(QRect rect, QMouseEvent *event) { - // backup painter settings that we're about to change: - QTransform oldTransform = painter->transform(); - QFont oldFont = painter->font(); - - // transform painter to position/rotation: - painter->translate(x, y); - if (!qFuzzyIsNull(tickLabelRotation)) - painter->rotate(tickLabelRotation); - - // draw text: - if (!labelData.expPart.isEmpty()) // indicator that beautiful powers must be used - { - painter->setFont(labelData.baseFont); - painter->drawText(0, 0, 0, 0, Qt::TextDontClip, labelData.basePart); - painter->setFont(labelData.expFont); - painter->drawText(labelData.baseBounds.width()+1, 0, labelData.expBounds.width(), labelData.expBounds.height(), Qt::TextDontClip, labelData.expPart); - } else + Q_UNUSED(event) + if (QCPAxisRect *axisRect = axisRectAt(rect.topLeft())) { - painter->setFont(labelData.baseFont); - painter->drawText(0, 0, labelData.totalBounds.width(), labelData.totalBounds.height(), Qt::TextDontClip | Qt::AlignHCenter, labelData.basePart); + QList affectedAxes = QList() << axisRect->rangeZoomAxes(Qt::Horizontal) << axisRect->rangeZoomAxes(Qt::Vertical); + affectedAxes.removeAll(static_cast(nullptr)); + axisRect->zoom(QRectF(rect), affectedAxes); } - - // reset painter settings to what it was before: - painter->setTransform(oldTransform); - painter->setFont(oldFont); + replot(rpQueuedReplot); // always replot to make selection rect disappear } /*! \internal - - This is a \ref placeTickLabel helper function. - - Transforms the passed \a text and \a font to a tickLabelData structure that can then be further - processed by \ref getTickLabelDrawOffset and \ref drawTickLabel. It splits the text into base and - exponent if necessary (member substituteExponent) and calculates appropriate bounding boxes. + + This method is called when a simple left mouse click was detected on the QCustomPlot surface. + + It first determines the layerable that was hit by the click, and then calls its \ref + QCPLayerable::selectEvent. All other layerables receive a QCPLayerable::deselectEvent (unless the + multi-select modifier was pressed, see \ref setMultiSelectModifier). + + In this method the hit layerable is determined a second time using \ref layerableAt (after the + one in \ref mousePressEvent), because we want \a onlySelectable set to true this time. This + implies that the mouse event grabber (mMouseEventLayerable) may be a different one from the + clicked layerable determined here. For example, if a non-selectable layerable is in front of a + selectable layerable at the click position, the front layerable will receive mouse events but the + selectable one in the back will receive the \ref QCPLayerable::selectEvent. + + \see processRectSelection, QCPLayerable::selectTest */ -QCPAxisPainterPrivate::TickLabelData QCPAxisPainterPrivate::getTickLabelData(const QFont &font, const QString &text) const +void QCustomPlot::processPointSelection(QMouseEvent *event) { - TickLabelData result; - - // determine whether beautiful decimal powers should be used - bool useBeautifulPowers = false; - int ePos = -1; - if (substituteExponent) + QVariant details; + QCPLayerable *clickedLayerable = layerableAt(event->pos(), true, &details); + bool selectionStateChanged = false; + bool additive = mInteractions.testFlag(QCP::iMultiSelect) && event->modifiers().testFlag(mMultiSelectModifier); + // deselect all other layerables if not additive selection: + if (!additive) { - ePos = text.indexOf(QLatin1Char('e')); - if (ePos > -1) - useBeautifulPowers = true; + foreach (QCPLayer *layer, mLayers) + { + foreach (QCPLayerable *layerable, layer->children()) + { + if (layerable != clickedLayerable && mInteractions.testFlag(layerable->selectionCategory())) + { + bool selChanged = false; + layerable->deselectEvent(&selChanged); + selectionStateChanged |= selChanged; + } + } + } } - - // calculate text bounding rects and do string preparation for beautiful decimal powers: - result.baseFont = font; - if (result.baseFont.pointSizeF() > 0) // might return -1 if specified with setPixelSize, in that case we can't do correction in next line - result.baseFont.setPointSizeF(result.baseFont.pointSizeF()+0.05); // QFontMetrics.boundingRect has a bug for exact point sizes that make the results oscillate due to internal rounding - if (useBeautifulPowers) - { - // split text into parts of number/symbol that will be drawn normally and part that will be drawn as exponent: - result.basePart = text.left(ePos); - // in log scaling, we want to turn "1*10^n" into "10^n", else add multiplication sign and decimal base: - if (abbreviateDecimalPowers && result.basePart == QLatin1String("1")) - result.basePart = QLatin1String("10"); - else - result.basePart += (numberMultiplyCross ? QString(QChar(215)) : QString(QChar(183))) + QLatin1String("10"); - result.expPart = text.mid(ePos+1); - // clip "+" and leading zeros off expPart: - while (result.expPart.length() > 2 && result.expPart.at(1) == QLatin1Char('0')) // length > 2 so we leave one zero when numberFormatChar is 'e' - result.expPart.remove(1, 1); - if (!result.expPart.isEmpty() && result.expPart.at(0) == QLatin1Char('+')) - result.expPart.remove(0, 1); - // prepare smaller font for exponent: - result.expFont = font; - if (result.expFont.pointSize() > 0) - result.expFont.setPointSize(result.expFont.pointSize()*0.75); - else - result.expFont.setPixelSize(result.expFont.pixelSize()*0.75); - // calculate bounding rects of base part, exponent part and total one: - result.baseBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.basePart); - result.expBounds = QFontMetrics(result.expFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip, result.expPart); - result.totalBounds = result.baseBounds.adjusted(0, 0, result.expBounds.width()+2, 0); // +2 consists of the 1 pixel spacing between base and exponent (see drawTickLabel) and an extra pixel to include AA - } else // useBeautifulPowers == false + if (clickedLayerable && mInteractions.testFlag(clickedLayerable->selectionCategory())) { - result.basePart = text; - result.totalBounds = QFontMetrics(result.baseFont).boundingRect(0, 0, 0, 0, Qt::TextDontClip | Qt::AlignHCenter, result.basePart); + // a layerable was actually clicked, call its selectEvent: + bool selChanged = false; + clickedLayerable->selectEvent(event, additive, details, &selChanged); + selectionStateChanged |= selChanged; } - result.totalBounds.moveTopLeft(QPoint(0, 0)); // want bounding box aligned top left at origin, independent of how it was created, to make further processing simpler - - // calculate possibly different bounding rect after rotation: - result.rotatedTotalBounds = result.totalBounds; - if (!qFuzzyIsNull(tickLabelRotation)) + if (selectionStateChanged) { - QTransform transform; - transform.rotate(tickLabelRotation); - result.rotatedTotalBounds = transform.mapRect(result.rotatedTotalBounds); + emit selectionChangedByUser(); + replot(rpQueuedReplot); } - - return result; } /*! \internal - This is a \ref placeTickLabel helper function. + Registers the specified plottable with this QCustomPlot and, if \ref setAutoAddPlottableToLegend + is enabled, adds it to the legend (QCustomPlot::legend). QCustomPlot takes ownership of the + plottable. - Calculates the offset at which the top left corner of the specified tick label shall be drawn. - The offset is relative to a point right next to the tick the label belongs to. + Returns true on success, i.e. when \a plottable isn't already in this plot and the parent plot of + \a plottable is this QCustomPlot. - This function is thus responsible for e.g. centering tick labels under ticks and positioning them - appropriately when they are rotated. + This method is called automatically in the QCPAbstractPlottable base class constructor. */ -QPointF QCPAxisPainterPrivate::getTickLabelDrawOffset(const TickLabelData &labelData) const +bool QCustomPlot::registerPlottable(QCPAbstractPlottable *plottable) { - /* - calculate label offset from base point at tick (non-trivial, for best visual appearance): short - explanation for bottom axis: The anchor, i.e. the point in the label that is placed - horizontally under the corresponding tick is always on the label side that is closer to the - axis (e.g. the left side of the text when we're rotating clockwise). On that side, the height - is halved and the resulting point is defined the anchor. This way, a 90 degree rotated text - will be centered under the tick (i.e. displaced horizontally by half its height). At the same - time, a 45 degree rotated text will "point toward" its tick, as is typical for rotated tick - labels. - */ - bool doRotation = !qFuzzyIsNull(tickLabelRotation); - bool flip = qFuzzyCompare(qAbs(tickLabelRotation), 90.0); // perfect +/-90 degree flip. Indicates vertical label centering on vertical axes. - double radians = tickLabelRotation/180.0*M_PI; - int x=0, y=0; - if ((type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsInside)) // Anchor at right side of tick label - { - if (doRotation) - { - if (tickLabelRotation > 0) - { - x = -qCos(radians)*labelData.totalBounds.width(); - y = flip ? -labelData.totalBounds.width()/2.0 : -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height()/2.0; - } else - { - x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height(); - y = flip ? +labelData.totalBounds.width()/2.0 : +qSin(-radians)*labelData.totalBounds.width()-qCos(-radians)*labelData.totalBounds.height()/2.0; - } - } else - { - x = -labelData.totalBounds.width(); - y = -labelData.totalBounds.height()/2.0; - } - } else if ((type == QCPAxis::atRight && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atLeft && tickLabelSide == QCPAxis::lsInside)) // Anchor at left side of tick label - { - if (doRotation) - { - if (tickLabelRotation > 0) - { - x = +qSin(radians)*labelData.totalBounds.height(); - y = flip ? -labelData.totalBounds.width()/2.0 : -qCos(radians)*labelData.totalBounds.height()/2.0; - } else - { - x = 0; - y = flip ? +labelData.totalBounds.width()/2.0 : -qCos(-radians)*labelData.totalBounds.height()/2.0; - } - } else - { - x = 0; - y = -labelData.totalBounds.height()/2.0; - } - } else if ((type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsInside)) // Anchor at bottom side of tick label + if (mPlottables.contains(plottable)) { - if (doRotation) - { - if (tickLabelRotation > 0) - { - x = -qCos(radians)*labelData.totalBounds.width()+qSin(radians)*labelData.totalBounds.height()/2.0; - y = -qSin(radians)*labelData.totalBounds.width()-qCos(radians)*labelData.totalBounds.height(); - } else - { - x = -qSin(-radians)*labelData.totalBounds.height()/2.0; - y = -qCos(-radians)*labelData.totalBounds.height(); - } - } else - { - x = -labelData.totalBounds.width()/2.0; - y = -labelData.totalBounds.height(); - } - } else if ((type == QCPAxis::atBottom && tickLabelSide == QCPAxis::lsOutside) || (type == QCPAxis::atTop && tickLabelSide == QCPAxis::lsInside)) // Anchor at top side of tick label + qDebug() << Q_FUNC_INFO << "plottable already added to this QCustomPlot:" << reinterpret_cast(plottable); + return false; + } + if (plottable->parentPlot() != this) { - if (doRotation) - { - if (tickLabelRotation > 0) - { - x = +qSin(radians)*labelData.totalBounds.height()/2.0; - y = 0; - } else - { - x = -qCos(-radians)*labelData.totalBounds.width()-qSin(-radians)*labelData.totalBounds.height()/2.0; - y = +qSin(-radians)*labelData.totalBounds.width(); - } - } else - { - x = -labelData.totalBounds.width()/2.0; - y = 0; - } + qDebug() << Q_FUNC_INFO << "plottable not created with this QCustomPlot as parent:" << reinterpret_cast(plottable); + return false; } - return QPointF(x, y); + mPlottables.append(plottable); + // possibly add plottable to legend: + if (mAutoAddPlottableToLegend) + plottable->addToLegend(); + if (!plottable->layer()) // usually the layer is already set in the constructor of the plottable (via QCPLayerable constructor) + plottable->setLayer(currentLayer()); + return true; } /*! \internal - Simulates the steps done by \ref placeTickLabel by calculating bounding boxes of the text label - to be drawn, depending on number format etc. Since only the largest tick label is wanted for the - margin calculation, the passed \a tickLabelsSize is only expanded, if it's currently set to a - smaller width/height. + In order to maintain the simplified graph interface of QCustomPlot, this method is called by the + QCPGraph constructor to register itself with this QCustomPlot's internal graph list. Returns true + on success, i.e. if \a graph is valid and wasn't already registered with this QCustomPlot. + + This graph specific registration happens in addition to the call to \ref registerPlottable by the + QCPAbstractPlottable base class. */ -void QCPAxisPainterPrivate::getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const +bool QCustomPlot::registerGraph(QCPGraph *graph) { - // note: this function must return the same tick label sizes as the placeTickLabel function. - QSize finalSize; - if (mParentPlot->plottingHints().testFlag(QCP::phCacheLabels) && mLabelCache.contains(text)) // label caching enabled and have cached label + if (!graph) { - const CachedLabel *cachedLabel = mLabelCache.object(text); - finalSize = cachedLabel->pixmap.size(); - } else // label caching disabled or no label with this text cached: + qDebug() << Q_FUNC_INFO << "passed graph is zero"; + return false; + } + if (mGraphs.contains(graph)) { - TickLabelData labelData = getTickLabelData(font, text); - finalSize = labelData.rotatedTotalBounds.size(); + qDebug() << Q_FUNC_INFO << "graph already registered with this QCustomPlot"; + return false; } - // expand passed tickLabelsSize if current tick label is larger: - if (finalSize.width() > tickLabelsSize->width()) - tickLabelsSize->setWidth(finalSize.width()); - if (finalSize.height() > tickLabelsSize->height()) - tickLabelsSize->setHeight(finalSize.height()); + mGraphs.append(graph); + return true; } -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPAbstractPlottable -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPAbstractPlottable - \brief The abstract base class for all data representing objects in a plot. +/*! \internal - It defines a very basic interface like name, pen, brush, visibility etc. Since this class is - abstract, it can't be instantiated. Use one of the subclasses or create a subclass yourself to - create new ways of displaying data (see "Creating own plottables" below). + Registers the specified item with this QCustomPlot. QCustomPlot takes ownership of the item. - All further specifics are in the subclasses, for example: - \li A normal graph with possibly a line, scatter points and error bars: \ref QCPGraph - (typically created with \ref QCustomPlot::addGraph) - \li A parametric curve: \ref QCPCurve - \li A bar chart: \ref QCPBars - \li A statistical box plot: \ref QCPStatisticalBox - \li A color encoded two-dimensional map: \ref QCPColorMap - \li An OHLC/Candlestick chart: \ref QCPFinancial + Returns true on success, i.e. when \a item wasn't already in the plot and the parent plot of \a + item is this QCustomPlot. - \section plottables-subclassing Creating own plottables + This method is called automatically in the QCPAbstractItem base class constructor. +*/ +bool QCustomPlot::registerItem(QCPAbstractItem *item) +{ + if (mItems.contains(item)) + { + qDebug() << Q_FUNC_INFO << "item already added to this QCustomPlot:" << reinterpret_cast(item); + return false; + } + if (item->parentPlot() != this) + { + qDebug() << Q_FUNC_INFO << "item not created with this QCustomPlot as parent:" << reinterpret_cast(item); + return false; + } - To create an own plottable, you implement a subclass of QCPAbstractPlottable. These are the pure - virtual functions, you must implement: - \li \ref clearData - \li \ref selectTest - \li \ref draw - \li \ref drawLegendIcon - \li \ref getKeyRange - \li \ref getValueRange + mItems.append(item); + if (!item->layer()) // usually the layer is already set in the constructor of the item (via QCPLayerable constructor) + item->setLayer(currentLayer()); + return true; +} + +/*! \internal - See the documentation of those functions for what they need to do. + Assigns all layers their index (QCPLayer::mIndex) in the mLayers list. This method is thus called + after every operation that changes the layer indices, like layer removal, layer creation, layer + moving. +*/ +void QCustomPlot::updateLayerIndices() const +{ + for (int i=0; imIndex = i; +} + +/*! \internal + + Returns the top-most layerable at pixel position \a pos. If \a onlySelectable is set to true, + only those layerables that are selectable will be considered. (Layerable subclasses communicate + their selectability via the QCPLayerable::selectTest method, by returning -1.) + + \a selectionDetails is an output parameter that contains selection specifics of the affected + layerable. This is useful if the respective layerable shall be given a subsequent + QCPLayerable::selectEvent (like in \ref mouseReleaseEvent). \a selectionDetails usually contains + information about which part of the layerable was hit, in multi-part layerables (e.g. + QCPAxis::SelectablePart). If the layerable is a plottable, \a selectionDetails contains a \ref + QCPDataSelection instance with the single data point which is closest to \a pos. - For drawing your plot, you can use the \ref coordsToPixels functions to translate a point in plot - coordinates to pixel coordinates. This function is quite convenient, because it takes the - orientation of the key and value axes into account for you (x and y are swapped when the key axis - is vertical and the value axis horizontal). If you are worried about performance (i.e. you need - to translate many points in a loop like QCPGraph), you can directly use \ref - QCPAxis::coordToPixel. However, you must then take care about the orientation of the axis - yourself. + \see layerableListAt, layoutElementAt, axisRectAt +*/ +QCPLayerable *QCustomPlot::layerableAt(const QPointF &pos, bool onlySelectable, QVariant *selectionDetails) const +{ + QList details; + QList candidates = layerableListAt(pos, onlySelectable, selectionDetails ? &details : nullptr); + if (selectionDetails && !details.isEmpty()) + *selectionDetails = details.first(); + if (!candidates.isEmpty()) + return candidates.first(); + else + return nullptr; +} + +/*! \internal + + Returns the layerables at pixel position \a pos. If \a onlySelectable is set to true, only those + layerables that are selectable will be considered. (Layerable subclasses communicate their + selectability via the QCPLayerable::selectTest method, by returning -1.) + + The returned list is sorted by the layerable/drawing order such that the layerable that appears + on top in the plot is at index 0 of the returned list. If you only need to know the top + layerable, rather use \ref layerableAt. + + \a selectionDetails is an output parameter that contains selection specifics of the affected + layerable. This is useful if the respective layerable shall be given a subsequent + QCPLayerable::selectEvent (like in \ref mouseReleaseEvent). \a selectionDetails usually contains + information about which part of the layerable was hit, in multi-part layerables (e.g. + QCPAxis::SelectablePart). If the layerable is a plottable, \a selectionDetails contains a \ref + QCPDataSelection instance with the single data point which is closest to \a pos. - Here are some important members you inherit from QCPAbstractPlottable: - - - - - - - - - - - - - - - - - - - - - - - - - - -
QCustomPlot *\b mParentPlotA pointer to the parent QCustomPlot instance. The parent plot is inferred from the axes that are passed in the constructor.
QString \b mNameThe name of the plottable.
QPen \b mPenThe generic pen of the plottable. You should use this pen for the most prominent data representing lines in the plottable (e.g QCPGraph uses this pen for its graph lines and scatters)
QPen \b mSelectedPenThe generic pen that should be used when the plottable is selected (hint: \ref mainPen gives you the right pen, depending on selection state).
QBrush \b mBrushThe generic brush of the plottable. You should use this brush for the most prominent fillable structures in the plottable (e.g. QCPGraph uses this brush to control filling under the graph)
QBrush \b mSelectedBrushThe generic brush that should be used when the plottable is selected (hint: \ref mainBrush gives you the right brush, depending on selection state).
QPointer\b mKeyAxis, \b mValueAxisThe key and value axes this plottable is attached to. Call their QCPAxis::coordToPixel functions to translate coordinates to pixels in either the key or value dimension. - Make sure to check whether the pointer is null before using it. If one of the axes is null, don't draw the plottable.
bool \b mSelectedindicates whether the plottable is selected or not.
+ \see layerableAt, layoutElementAt, axisRectAt */ +QList QCustomPlot::layerableListAt(const QPointF &pos, bool onlySelectable, QList *selectionDetails) const +{ + QList result; + for (int layerIndex=mLayers.size()-1; layerIndex>=0; --layerIndex) + { + const QList layerables = mLayers.at(layerIndex)->children(); + for (int i=layerables.size()-1; i>=0; --i) + { + if (!layerables.at(i)->realVisibility()) + continue; + QVariant details; + double dist = layerables.at(i)->selectTest(pos, onlySelectable, selectionDetails ? &details : nullptr); + if (dist >= 0 && dist < selectionTolerance()) + { + result.append(layerables.at(i)); + if (selectionDetails) + selectionDetails->append(details); + } + } + } + return result; +} -/* start of documentation of pure virtual functions */ +/*! + Saves the plot to a rastered image file \a fileName in the image format \a format. The plot is + sized to \a width and \a height in pixels and scaled with \a scale. (width 100 and scale 2.0 lead + to a full resolution file with width 200.) If the \a format supports compression, \a quality may + be between 0 and 100 to control it. + + Returns true on success. If this function fails, most likely the given \a format isn't supported + by the system, see Qt docs about QImageWriter::supportedImageFormats(). -/*! \fn void QCPAbstractPlottable::clearData() = 0 - Clears all data in the plottable. + The \a resolution will be written to the image file header (if the file format supports this) and + has no direct consequence for the quality or the pixel size. However, if opening the image with a + tool which respects the metadata, it will be able to scale the image to match either a given size + in real units of length (inch, centimeters, etc.), or the target display DPI. You can specify in + which units \a resolution is given, by setting \a resolutionUnit. The \a resolution is converted + to the format's expected resolution unit internally. + + \see saveBmp, saveJpg, savePng, savePdf */ +bool QCustomPlot::saveRastered(const QString &fileName, int width, int height, double scale, const char *format, int quality, int resolution, QCP::ResolutionUnit resolutionUnit) +{ + QImage buffer = toPixmap(width, height, scale).toImage(); + + int dotsPerMeter = 0; + switch (resolutionUnit) + { + case QCP::ruDotsPerMeter: dotsPerMeter = resolution; break; + case QCP::ruDotsPerCentimeter: dotsPerMeter = resolution*100; break; + case QCP::ruDotsPerInch: dotsPerMeter = int(resolution/0.0254); break; + } + buffer.setDotsPerMeterX(dotsPerMeter); // this is saved together with some image formats, e.g. PNG, and is relevant when opening image in other tools + buffer.setDotsPerMeterY(dotsPerMeter); // this is saved together with some image formats, e.g. PNG, and is relevant when opening image in other tools + if (!buffer.isNull()) + return buffer.save(fileName, format, quality); + else + return false; +} -/*! \fn void QCPAbstractPlottable::drawLegendIcon(QCPPainter *painter, const QRect &rect) const = 0 - \internal +/*! + Renders the plot to a pixmap and returns it. - called by QCPLegend::draw (via QCPPlottableLegendItem::draw) to create a graphical representation - of this plottable inside \a rect, next to the plottable name. + The plot is sized to \a width and \a height in pixels and scaled with \a scale. (width 100 and + scale 2.0 lead to a full resolution pixmap with width 200.) - The passed \a painter has its cliprect set to \a rect, so painting outside of \a rect won't - appear outside the legend icon border. + \see toPainter, saveRastered, saveBmp, savePng, saveJpg, savePdf */ +QPixmap QCustomPlot::toPixmap(int width, int height, double scale) +{ + // this method is somewhat similar to toPainter. Change something here, and a change in toPainter might be necessary, too. + int newWidth, newHeight; + if (width == 0 || height == 0) + { + newWidth = this->width(); + newHeight = this->height(); + } else + { + newWidth = width; + newHeight = height; + } + int scaledWidth = qRound(scale*newWidth); + int scaledHeight = qRound(scale*newHeight); -/*! \fn QCPRange QCPAbstractPlottable::getKeyRange(bool &foundRange, SignDomain inSignDomain) const = 0 - \internal - - called by rescaleAxes functions to get the full data key bounds. For logarithmic plots, one can - set \a inSignDomain to either \ref sdNegative or \ref sdPositive in order to restrict the - returned range to that sign domain. E.g. when only negative range is wanted, set \a inSignDomain - to \ref sdNegative and all positive points will be ignored for range calculation. For no - restriction, just set \a inSignDomain to \ref sdBoth (default). \a foundRange is an output - parameter that indicates whether a range could be found or not. If this is false, you shouldn't - use the returned range (e.g. no points in data). + QPixmap result(scaledWidth, scaledHeight); + result.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent); // if using non-solid pattern, make transparent now and draw brush pattern later + QCPPainter painter; + painter.begin(&result); + if (painter.isActive()) + { + QRect oldViewport = viewport(); + setViewport(QRect(0, 0, newWidth, newHeight)); + painter.setMode(QCPPainter::pmNoCaching); + if (!qFuzzyCompare(scale, 1.0)) + { + if (scale > 1.0) // for scale < 1 we always want cosmetic pens where possible, because else lines might disappear for very small scales + painter.setMode(QCPPainter::pmNonCosmetic); + painter.scale(scale, scale); + } + if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush) // solid fills were done a few lines above with QPixmap::fill + painter.fillRect(mViewport, mBackgroundBrush); + draw(&painter); + setViewport(oldViewport); + painter.end(); + } else // might happen if pixmap has width or height zero + { + qDebug() << Q_FUNC_INFO << "Couldn't activate painter on pixmap"; + return QPixmap(); + } + return result; +} - Note that \a foundRange is not the same as \ref QCPRange::validRange, since the range returned by - this function may have size zero, which wouldn't count as a valid range. +/*! + Renders the plot using the passed \a painter. - \see rescaleAxes, getValueRange -*/ - -/*! \fn QCPRange QCPAbstractPlottable::getValueRange(bool &foundRange, SignDomain inSignDomain) const = 0 - \internal + The plot is sized to \a width and \a height in pixels. If the \a painter's scale is not 1.0, the resulting plot will + appear scaled accordingly. - called by rescaleAxes functions to get the full data value bounds. For logarithmic plots, one can - set \a inSignDomain to either \ref sdNegative or \ref sdPositive in order to restrict the - returned range to that sign domain. E.g. when only negative range is wanted, set \a inSignDomain - to \ref sdNegative and all positive points will be ignored for range calculation. For no - restriction, just set \a inSignDomain to \ref sdBoth (default). \a foundRange is an output - parameter that indicates whether a range could be found or not. If this is false, you shouldn't - use the returned range (e.g. no points in data). - - Note that \a foundRange is not the same as \ref QCPRange::validRange, since the range returned by - this function may have size zero, which wouldn't count as a valid range. + \note If you are restricted to using a QPainter (instead of QCPPainter), create a temporary QPicture and open a QCPPainter + on it. Then call \ref toPainter with this QCPPainter. After ending the paint operation on the picture, draw it with + the QPainter. This will reproduce the painter actions the QCPPainter took, with a QPainter. - \see rescaleAxes, getKeyRange + \see toPixmap */ +void QCustomPlot::toPainter(QCPPainter *painter, int width, int height) +{ + // this method is somewhat similar to toPixmap. Change something here, and a change in toPixmap might be necessary, too. + int newWidth, newHeight; + if (width == 0 || height == 0) + { + newWidth = this->width(); + newHeight = this->height(); + } else + { + newWidth = width; + newHeight = height; + } -/* end of documentation of pure virtual functions */ -/* start of documentation of signals */ + if (painter->isActive()) + { + QRect oldViewport = viewport(); + setViewport(QRect(0, 0, newWidth, newHeight)); + painter->setMode(QCPPainter::pmNoCaching); + if (mBackgroundBrush.style() != Qt::NoBrush) // unlike in toPixmap, we can't do QPixmap::fill for Qt::SolidPattern brush style, so we also draw solid fills with fillRect here + painter->fillRect(mViewport, mBackgroundBrush); + draw(painter); + setViewport(oldViewport); + } else + qDebug() << Q_FUNC_INFO << "Passed painter is not active"; +} +/* end of 'src/core.cpp' */ -/*! \fn void QCPAbstractPlottable::selectionChanged(bool selected) + +/* including file 'src/colorgradient.cpp' */ +/* modified 2022-11-06T12:45:56, size 25408 */ + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPColorGradient +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPColorGradient + \brief Defines a color gradient for use with e.g. \ref QCPColorMap - This signal is emitted when the selection state of this plottable has changed, either by user - interaction or by a direct call to \ref setSelected. -*/ + This class describes a color gradient which can be used to encode data with color. For example, + QCPColorMap and QCPColorScale have \ref QCPColorMap::setGradient "setGradient" methods which + take an instance of this class. Colors are set with \ref setColorStopAt(double position, const QColor &color) + with a \a position from 0 to 1. In between these defined color positions, the + color will be interpolated linearly either in RGB or HSV space, see \ref setColorInterpolation. -/*! \fn void QCPAbstractPlottable::selectableChanged(bool selectable); + Alternatively, load one of the preset color gradients shown in the image below, with \ref + loadPreset, or by directly specifying the preset in the constructor. - This signal is emitted when the selectability of this plottable has changed. + Apart from red, green and blue components, the gradient also interpolates the alpha values of the + configured color stops. This allows to display some portions of the data range as transparent in + the plot. - \see setSelectable -*/ - -/* end of documentation of signals */ - -/*! - Constructs an abstract plottable which uses \a keyAxis as its key axis ("x") and \a valueAxis as - its value axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance - and have perpendicular orientations. If either of these restrictions is violated, a corresponding - message is printed to the debug output (qDebug), the construction is not aborted, though. + How NaN values are interpreted can be configured with \ref setNanHandling. - Since QCPAbstractPlottable is an abstract class that defines the basic interface to plottables, - it can't be directly instantiated. + \image html QCPColorGradient.png - You probably want one of the subclasses like \ref QCPGraph or \ref QCPCurve instead. + The constructor \ref QCPColorGradient(GradientPreset preset) allows directly converting a \ref + GradientPreset to a QCPColorGradient. This means that you can directly pass \ref GradientPreset + to all the \a setGradient methods, e.g.: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcolorgradient-setgradient + + The total number of levels used in the gradient can be set with \ref setLevelCount. Whether the + color gradient shall be applied periodically (wrapping around) to data values that lie outside + the data range specified on the plottable instance can be controlled with \ref setPeriodic. */ -QCPAbstractPlottable::QCPAbstractPlottable(QCPAxis *keyAxis, QCPAxis *valueAxis) : - QCPLayerable(keyAxis->parentPlot(), QString(), keyAxis->axisRect()), - mName(), - mAntialiasedFill(true), - mAntialiasedScatters(true), - mAntialiasedErrorBars(false), - mPen(Qt::black), - mSelectedPen(Qt::black), - mBrush(Qt::NoBrush), - mSelectedBrush(Qt::NoBrush), - mKeyAxis(keyAxis), - mValueAxis(valueAxis), - mSelectable(true), - mSelected(false) -{ - if (keyAxis->parentPlot() != valueAxis->parentPlot()) - qDebug() << Q_FUNC_INFO << "Parent plot of keyAxis is not the same as that of valueAxis."; - if (keyAxis->orientation() == valueAxis->orientation()) - qDebug() << Q_FUNC_INFO << "keyAxis and valueAxis must be orthogonal to each other."; -} /*! - The name is the textual representation of this plottable as it is displayed in the legend - (\ref QCPLegend). It may contain any UTF-8 characters, including newlines. -*/ -void QCPAbstractPlottable::setName(const QString &name) -{ - mName = name; -} + Constructs a new, empty QCPColorGradient with no predefined color stops. You can add own color + stops with \ref setColorStopAt. -/*! - Sets whether fills of this plottable are drawn antialiased or not. - - Note that this setting may be overridden by \ref QCustomPlot::setAntialiasedElements and \ref - QCustomPlot::setNotAntialiasedElements. + The color level count is initialized to 350. */ -void QCPAbstractPlottable::setAntialiasedFill(bool enabled) +QCPColorGradient::QCPColorGradient() : + mLevelCount(350), + mColorInterpolation(ciRGB), + mNanHandling(nhNone), + mNanColor(Qt::black), + mPeriodic(false), + mColorBufferInvalidated(true) { - mAntialiasedFill = enabled; + mColorBuffer.fill(qRgb(0, 0, 0), mLevelCount); } /*! - Sets whether the scatter symbols of this plottable are drawn antialiased or not. - - Note that this setting may be overridden by \ref QCustomPlot::setAntialiasedElements and \ref - QCustomPlot::setNotAntialiasedElements. + Constructs a new QCPColorGradient initialized with the colors and color interpolation according + to \a preset. + + The color level count is initialized to 350. */ -void QCPAbstractPlottable::setAntialiasedScatters(bool enabled) +QCPColorGradient::QCPColorGradient(GradientPreset preset) : + mLevelCount(350), + mColorInterpolation(ciRGB), + mNanHandling(nhNone), + mNanColor(Qt::black), + mPeriodic(false), + mColorBufferInvalidated(true) { - mAntialiasedScatters = enabled; + mColorBuffer.fill(qRgb(0, 0, 0), mLevelCount); + loadPreset(preset); } -/*! - Sets whether the error bars of this plottable are drawn antialiased or not. - - Note that this setting may be overridden by \ref QCustomPlot::setAntialiasedElements and \ref - QCustomPlot::setNotAntialiasedElements. -*/ -void QCPAbstractPlottable::setAntialiasedErrorBars(bool enabled) +/* undocumented operator */ +bool QCPColorGradient::operator==(const QCPColorGradient &other) const { - mAntialiasedErrorBars = enabled; + return ((other.mLevelCount == this->mLevelCount) && + (other.mColorInterpolation == this->mColorInterpolation) && + (other.mNanHandling == this ->mNanHandling) && + (other.mNanColor == this->mNanColor) && + (other.mPeriodic == this->mPeriodic) && + (other.mColorStops == this->mColorStops)); } - /*! - The pen is used to draw basic lines that make up the plottable representation in the - plot. - - For example, the \ref QCPGraph subclass draws its graph lines with this pen. + Sets the number of discretization levels of the color gradient to \a n. The default is 350 which + is typically enough to create a smooth appearance. The minimum number of levels is 2. - \see setBrush + \image html QCPColorGradient-levelcount.png */ -void QCPAbstractPlottable::setPen(const QPen &pen) +void QCPColorGradient::setLevelCount(int n) { - mPen = pen; + if (n < 2) + { + qDebug() << Q_FUNC_INFO << "n must be greater or equal 2 but was" << n; + n = 2; + } + if (n != mLevelCount) + { + mLevelCount = n; + mColorBufferInvalidated = true; + } } /*! - When the plottable is selected, this pen is used to draw basic lines instead of the normal - pen set via \ref setPen. - - \see setSelected, setSelectable, setSelectedBrush, selectTest + Sets at which positions from 0 to 1 which color shall occur. The positions are the keys, the + colors are the values of the passed QMap \a colorStops. In between these color stops, the color + is interpolated according to \ref setColorInterpolation. + + A more convenient way to create a custom gradient may be to clear all color stops with \ref + clearColorStops (or creating a new, empty QCPColorGradient) and then adding them one by one with + \ref setColorStopAt. + + \see clearColorStops */ -void QCPAbstractPlottable::setSelectedPen(const QPen &pen) +void QCPColorGradient::setColorStops(const QMap &colorStops) { - mSelectedPen = pen; + mColorStops = colorStops; + mColorBufferInvalidated = true; } /*! - The brush is used to draw basic fills of the plottable representation in the - plot. The Fill can be a color, gradient or texture, see the usage of QBrush. + Sets the \a color the gradient will have at the specified \a position (from 0 to 1). In between + these color stops, the color is interpolated according to \ref setColorInterpolation. - For example, the \ref QCPGraph subclass draws the fill under the graph with this brush, when - it's not set to Qt::NoBrush. + \see setColorStops, clearColorStops +*/ +void QCPColorGradient::setColorStopAt(double position, const QColor &color) +{ + mColorStops.insert(position, color); + mColorBufferInvalidated = true; +} - \see setPen +/*! + Sets whether the colors in between the configured color stops (see \ref setColorStopAt) shall be + interpolated linearly in RGB or in HSV color space. + + For example, a sweep in RGB space from red to green will have a muddy brown intermediate color, + whereas in HSV space the intermediate color is yellow. */ -void QCPAbstractPlottable::setBrush(const QBrush &brush) +void QCPColorGradient::setColorInterpolation(QCPColorGradient::ColorInterpolation interpolation) { - mBrush = brush; + if (interpolation != mColorInterpolation) + { + mColorInterpolation = interpolation; + mColorBufferInvalidated = true; + } } /*! - When the plottable is selected, this brush is used to draw fills instead of the normal - brush set via \ref setBrush. - - \see setSelected, setSelectable, setSelectedPen, selectTest + Sets how NaNs in the data are displayed in the plot. + + \see setNanColor */ -void QCPAbstractPlottable::setSelectedBrush(const QBrush &brush) +void QCPColorGradient::setNanHandling(QCPColorGradient::NanHandling handling) { - mSelectedBrush = brush; + mNanHandling = handling; } /*! - The key axis of a plottable can be set to any axis of a QCustomPlot, as long as it is orthogonal - to the plottable's value axis. This function performs no checks to make sure this is the case. - The typical mathematical choice is to use the x-axis (QCustomPlot::xAxis) as key axis and the - y-axis (QCustomPlot::yAxis) as value axis. + Sets the color that NaN data is represented by, if \ref setNanHandling is set + to ref nhNanColor. - Normally, the key and value axes are set in the constructor of the plottable (or \ref - QCustomPlot::addGraph when working with QCPGraphs through the dedicated graph interface). - - \see setValueAxis + \see setNanHandling */ -void QCPAbstractPlottable::setKeyAxis(QCPAxis *axis) +void QCPColorGradient::setNanColor(const QColor &color) { - mKeyAxis = axis; + mNanColor = color; } /*! - The value axis of a plottable can be set to any axis of a QCustomPlot, as long as it is - orthogonal to the plottable's key axis. This function performs no checks to make sure this is the - case. The typical mathematical choice is to use the x-axis (QCustomPlot::xAxis) as key axis and - the y-axis (QCustomPlot::yAxis) as value axis. - - Normally, the key and value axes are set in the constructor of the plottable (or \ref - QCustomPlot::addGraph when working with QCPGraphs through the dedicated graph interface). + Sets whether data points that are outside the configured data range (e.g. \ref + QCPColorMap::setDataRange) are colored by periodically repeating the color gradient or whether + they all have the same color, corresponding to the respective gradient boundary color. - \see setKeyAxis + \image html QCPColorGradient-periodic.png + + As shown in the image above, gradients that have the same start and end color are especially + suitable for a periodic gradient mapping, since they produce smooth color transitions throughout + the color map. A preset that has this property is \ref gpHues. + + In practice, using periodic color gradients makes sense when the data corresponds to a periodic + dimension, such as an angle or a phase. If this is not the case, the color encoding might become + ambiguous, because multiple different data values are shown as the same color. */ -void QCPAbstractPlottable::setValueAxis(QCPAxis *axis) +void QCPColorGradient::setPeriodic(bool enabled) { - mValueAxis = axis; + mPeriodic = enabled; } -/*! - Sets whether the user can (de-)select this plottable by clicking on the QCustomPlot surface. - (When \ref QCustomPlot::setInteractions contains iSelectPlottables.) +/*! \overload - However, even when \a selectable was set to false, it is possible to set the selection manually, - by calling \ref setSelected directly. + This method is used to quickly convert a \a data array to colors. The colors will be output in + the array \a scanLine. Both \a data and \a scanLine must have the length \a n when passed to this + function. The data range that shall be used for mapping the data value to the gradient is passed + in \a range. \a logarithmic indicates whether the data values shall be mapped to colors + logarithmically. + + if \a data actually contains 2D-data linearized via [row*columnCount + column], you can + set \a dataIndexFactor to columnCount to convert a column instead of a row of the data + array, in \a scanLine. \a scanLine will remain a regular (1D) array. This works because \a data + is addressed data[i*dataIndexFactor]. - \see setSelected + Use the overloaded method to additionally provide alpha map data. + + The QRgb values that are placed in \a scanLine have their r, g, and b components premultiplied + with alpha (see QImage::Format_ARGB32_Premultiplied). */ -void QCPAbstractPlottable::setSelectable(bool selectable) +void QCPColorGradient::colorize(const double *data, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor, bool logarithmic) { - if (mSelectable != selectable) + // If you change something here, make sure to also adapt color() and the other colorize() overload + if (!data) { - mSelectable = selectable; - emit selectableChanged(mSelectable); + qDebug() << Q_FUNC_INFO << "null pointer given as data"; + return; + } + if (!scanLine) + { + qDebug() << Q_FUNC_INFO << "null pointer given as scanLine"; + return; + } + if (mColorBufferInvalidated) + updateColorBuffer(); + + const bool skipNanCheck = mNanHandling == nhNone; + const double posToIndexFactor = !logarithmic ? (mLevelCount-1)/range.size() : (mLevelCount-1)/qLn(range.upper/range.lower); + for (int i=0; iscaleType() == QCPAxis::stLogarithmic) - signDomain = (keyAxis->range().upper < 0 ? sdNegative : sdPositive); - - bool foundRange; - QCPRange newRange = getKeyRange(foundRange, signDomain); - if (foundRange) + clearColorStops(); + switch (preset) { - if (onlyEnlarge) - newRange.expand(keyAxis->range()); - if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable - { - double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason - if (keyAxis->scaleType() == QCPAxis::stLinear) - { - newRange.lower = center-keyAxis->range().size()/2.0; - newRange.upper = center+keyAxis->range().size()/2.0; - } else // scaleType() == stLogarithmic - { - newRange.lower = center/qSqrt(keyAxis->range().upper/keyAxis->range().lower); - newRange.upper = center*qSqrt(keyAxis->range().upper/keyAxis->range().lower); - } - } - keyAxis->setRange(newRange); + case gpGrayscale: + setColorInterpolation(ciRGB); + setColorStopAt(0, Qt::black); + setColorStopAt(1, Qt::white); + break; + case gpHot: + setColorInterpolation(ciRGB); + setColorStopAt(0, QColor(50, 0, 0)); + setColorStopAt(0.2, QColor(180, 10, 0)); + setColorStopAt(0.4, QColor(245, 50, 0)); + setColorStopAt(0.6, QColor(255, 150, 10)); + setColorStopAt(0.8, QColor(255, 255, 50)); + setColorStopAt(1, QColor(255, 255, 255)); + break; + case gpCold: + setColorInterpolation(ciRGB); + setColorStopAt(0, QColor(0, 0, 50)); + setColorStopAt(0.2, QColor(0, 10, 180)); + setColorStopAt(0.4, QColor(0, 50, 245)); + setColorStopAt(0.6, QColor(10, 150, 255)); + setColorStopAt(0.8, QColor(50, 255, 255)); + setColorStopAt(1, QColor(255, 255, 255)); + break; + case gpNight: + setColorInterpolation(ciHSV); + setColorStopAt(0, QColor(10, 20, 30)); + setColorStopAt(1, QColor(250, 255, 250)); + break; + case gpCandy: + setColorInterpolation(ciHSV); + setColorStopAt(0, QColor(0, 0, 255)); + setColorStopAt(1, QColor(255, 250, 250)); + break; + case gpGeography: + setColorInterpolation(ciRGB); + setColorStopAt(0, QColor(70, 170, 210)); + setColorStopAt(0.20, QColor(90, 160, 180)); + setColorStopAt(0.25, QColor(45, 130, 175)); + setColorStopAt(0.30, QColor(100, 140, 125)); + setColorStopAt(0.5, QColor(100, 140, 100)); + setColorStopAt(0.6, QColor(130, 145, 120)); + setColorStopAt(0.7, QColor(140, 130, 120)); + setColorStopAt(0.9, QColor(180, 190, 190)); + setColorStopAt(1, QColor(210, 210, 230)); + break; + case gpIon: + setColorInterpolation(ciHSV); + setColorStopAt(0, QColor(50, 10, 10)); + setColorStopAt(0.45, QColor(0, 0, 255)); + setColorStopAt(0.8, QColor(0, 255, 255)); + setColorStopAt(1, QColor(0, 255, 0)); + break; + case gpThermal: + setColorInterpolation(ciRGB); + setColorStopAt(0, QColor(0, 0, 50)); + setColorStopAt(0.15, QColor(20, 0, 120)); + setColorStopAt(0.33, QColor(200, 30, 140)); + setColorStopAt(0.6, QColor(255, 100, 0)); + setColorStopAt(0.85, QColor(255, 255, 40)); + setColorStopAt(1, QColor(255, 255, 255)); + break; + case gpPolar: + setColorInterpolation(ciRGB); + setColorStopAt(0, QColor(50, 255, 255)); + setColorStopAt(0.18, QColor(10, 70, 255)); + setColorStopAt(0.28, QColor(10, 10, 190)); + setColorStopAt(0.5, QColor(0, 0, 0)); + setColorStopAt(0.72, QColor(190, 10, 10)); + setColorStopAt(0.82, QColor(255, 70, 10)); + setColorStopAt(1, QColor(255, 255, 50)); + break; + case gpSpectrum: + setColorInterpolation(ciHSV); + setColorStopAt(0, QColor(50, 0, 50)); + setColorStopAt(0.15, QColor(0, 0, 255)); + setColorStopAt(0.35, QColor(0, 255, 255)); + setColorStopAt(0.6, QColor(255, 255, 0)); + setColorStopAt(0.75, QColor(255, 30, 0)); + setColorStopAt(1, QColor(50, 0, 0)); + break; + case gpJet: + setColorInterpolation(ciRGB); + setColorStopAt(0, QColor(0, 0, 100)); + setColorStopAt(0.15, QColor(0, 50, 255)); + setColorStopAt(0.35, QColor(0, 255, 255)); + setColorStopAt(0.65, QColor(255, 255, 0)); + setColorStopAt(0.85, QColor(255, 30, 0)); + setColorStopAt(1, QColor(100, 0, 0)); + break; + case gpHues: + setColorInterpolation(ciHSV); + setColorStopAt(0, QColor(255, 0, 0)); + setColorStopAt(1.0/3.0, QColor(0, 0, 255)); + setColorStopAt(2.0/3.0, QColor(0, 255, 0)); + setColorStopAt(1, QColor(255, 0, 0)); + break; } } /*! - Rescales the value axis of the plottable so the whole plottable is visible. - - Returns true if the axis was actually scaled. This might not be the case if this plottable has an - invalid range, e.g. because it has no data points. + Clears all color stops. - See \ref rescaleAxes for detailed behaviour. + \see setColorStops, setColorStopAt */ -void QCPAbstractPlottable::rescaleValueAxis(bool onlyEnlarge) const +void QCPColorGradient::clearColorStops() { - QCPAxis *valueAxis = mValueAxis.data(); - if (!valueAxis) { qDebug() << Q_FUNC_INFO << "invalid value axis"; return; } - - SignDomain signDomain = sdBoth; - if (valueAxis->scaleType() == QCPAxis::stLogarithmic) - signDomain = (valueAxis->range().upper < 0 ? sdNegative : sdPositive); - - bool foundRange; - QCPRange newRange = getValueRange(foundRange, signDomain); - if (foundRange) - { - if (onlyEnlarge) - newRange.expand(valueAxis->range()); - if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable - { - double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason - if (valueAxis->scaleType() == QCPAxis::stLinear) - { - newRange.lower = center-valueAxis->range().size()/2.0; - newRange.upper = center+valueAxis->range().size()/2.0; - } else // scaleType() == stLogarithmic - { - newRange.lower = center/qSqrt(valueAxis->range().upper/valueAxis->range().lower); - newRange.upper = center*qSqrt(valueAxis->range().upper/valueAxis->range().lower); - } - } - valueAxis->setRange(newRange); - } + mColorStops.clear(); + mColorBufferInvalidated = true; } /*! - Adds this plottable to the legend of the parent QCustomPlot (QCustomPlot::legend). - - Normally, a QCPPlottableLegendItem is created and inserted into the legend. If the plottable - needs a more specialized representation in the legend, this function will take this into account - and instead create the specialized subclass of QCPAbstractLegendItem. - - Returns true on success, i.e. when the legend exists and a legend item associated with this plottable isn't already in - the legend. - - \see removeFromLegend, QCPLegend::addItem -*/ -bool QCPAbstractPlottable::addToLegend() -{ - if (!mParentPlot || !mParentPlot->legend) - return false; + Returns an inverted gradient. The inverted gradient has all properties as this \ref + QCPColorGradient, but the order of the color stops is inverted. - if (!mParentPlot->legend->hasItemWithPlottable(this)) - { - mParentPlot->legend->addItem(new QCPPlottableLegendItem(mParentPlot->legend, this)); - return true; - } else - return false; -} - -/*! - Removes the plottable from the legend of the parent QCustomPlot. This means the - QCPAbstractLegendItem (usually a QCPPlottableLegendItem) that is associated with this plottable - is removed. - - Returns true on success, i.e. if the legend exists and a legend item associated with this - plottable was found and removed. - - \see addToLegend, QCPLegend::removeItem + \see setColorStops, setColorStopAt */ -bool QCPAbstractPlottable::removeFromLegend() const -{ - if (!mParentPlot->legend) - return false; - - if (QCPPlottableLegendItem *lip = mParentPlot->legend->itemWithPlottable(this)) - return mParentPlot->legend->removeItem(lip); - else - return false; -} - -/* inherits documentation from base class */ -QRect QCPAbstractPlottable::clipRect() const -{ - if (mKeyAxis && mValueAxis) - return mKeyAxis.data()->axisRect()->rect() & mValueAxis.data()->axisRect()->rect(); - else - return QRect(); -} - -/* inherits documentation from base class */ -QCP::Interaction QCPAbstractPlottable::selectionCategory() const +QCPColorGradient QCPColorGradient::inverted() const { - return QCP::iSelectPlottables; + QCPColorGradient result(*this); + result.clearColorStops(); + for (QMap::const_iterator it=mColorStops.constBegin(); it!=mColorStops.constEnd(); ++it) + result.setColorStopAt(1.0-it.key(), it.value()); + return result; } /*! \internal - Convenience function for transforming a key/value pair to pixels on the QCustomPlot surface, - taking the orientations of the axes associated with this plottable into account (e.g. whether key - represents x or y). - - \a key and \a value are transformed to the coodinates in pixels and are written to \a x and \a y. - - \see pixelsToCoords, QCPAxis::coordToPixel + Returns true if the color gradient uses transparency, i.e. if any of the configured color stops + has an alpha value below 255. */ -void QCPAbstractPlottable::coordsToPixels(double key, double value, double &x, double &y) const +bool QCPColorGradient::stopsUseAlpha() const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - if (keyAxis->orientation() == Qt::Horizontal) - { - x = keyAxis->coordToPixel(key); - y = valueAxis->coordToPixel(value); - } else + for (QMap::const_iterator it=mColorStops.constBegin(); it!=mColorStops.constEnd(); ++it) { - y = keyAxis->coordToPixel(key); - x = valueAxis->coordToPixel(value); + if (it.value().alpha() < 255) + return true; } + return false; } /*! \internal - \overload - - Returns the input as pixel coordinates in a QPointF. -*/ -const QPointF QCPAbstractPlottable::coordsToPixels(double key, double value) const -{ - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); } - - if (keyAxis->orientation() == Qt::Horizontal) - return QPointF(keyAxis->coordToPixel(key), valueAxis->coordToPixel(value)); - else - return QPointF(valueAxis->coordToPixel(value), keyAxis->coordToPixel(key)); -} - -/*! \internal - - Convenience function for transforming a x/y pixel pair on the QCustomPlot surface to plot coordinates, - taking the orientations of the axes associated with this plottable into account (e.g. whether key - represents x or y). - \a x and \a y are transformed to the plot coodinates and are written to \a key and \a value. - - \see coordsToPixels, QCPAxis::coordToPixel + Updates the internal color buffer which will be used by \ref colorize and \ref color, to quickly + convert positions to colors. This is where the interpolation between color stops is calculated. */ -void QCPAbstractPlottable::pixelsToCoords(double x, double y, double &key, double &value) const +void QCPColorGradient::updateColorBuffer() { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - if (keyAxis->orientation() == Qt::Horizontal) + if (mColorBuffer.size() != mLevelCount) + mColorBuffer.resize(mLevelCount); + if (mColorStops.size() > 1) { - key = keyAxis->pixelToCoord(x); - value = valueAxis->pixelToCoord(y); - } else + double indexToPosFactor = 1.0/double(mLevelCount-1); + const bool useAlpha = stopsUseAlpha(); + for (int i=0; i::const_iterator it = const_cast*>(&mColorStops)->lowerBound(position); // force using the const lowerBound method + if (it == mColorStops.constEnd()) // position is on or after last stop, use color of last stop + { + if (useAlpha) + { + const QColor col = std::prev(it).value(); + const double alphaPremultiplier = col.alpha()/255.0; // since we use QImage::Format_ARGB32_Premultiplied + mColorBuffer[i] = qRgba(int(col.red()*alphaPremultiplier), + int(col.green()*alphaPremultiplier), + int(col.blue()*alphaPremultiplier), + col.alpha()); + } else + mColorBuffer[i] = std::prev(it).value().rgba(); + } else if (it == mColorStops.constBegin()) // position is on or before first stop, use color of first stop + { + if (useAlpha) + { + const QColor &col = it.value(); + const double alphaPremultiplier = col.alpha()/255.0; // since we use QImage::Format_ARGB32_Premultiplied + mColorBuffer[i] = qRgba(int(col.red()*alphaPremultiplier), + int(col.green()*alphaPremultiplier), + int(col.blue()*alphaPremultiplier), + col.alpha()); + } else + mColorBuffer[i] = it.value().rgba(); + } else // position is in between stops (or on an intermediate stop), interpolate color + { + QMap::const_iterator high = it; + QMap::const_iterator low = std::prev(it); + double t = (position-low.key())/(high.key()-low.key()); // interpolation factor 0..1 + switch (mColorInterpolation) + { + case ciRGB: + { + if (useAlpha) + { + const int alpha = int((1-t)*low.value().alpha() + t*high.value().alpha()); + const double alphaPremultiplier = alpha/255.0; // since we use QImage::Format_ARGB32_Premultiplied + mColorBuffer[i] = qRgba(int( ((1-t)*low.value().red() + t*high.value().red())*alphaPremultiplier ), + int( ((1-t)*low.value().green() + t*high.value().green())*alphaPremultiplier ), + int( ((1-t)*low.value().blue() + t*high.value().blue())*alphaPremultiplier ), + alpha); + } else + { + mColorBuffer[i] = qRgb(int( ((1-t)*low.value().red() + t*high.value().red()) ), + int( ((1-t)*low.value().green() + t*high.value().green()) ), + int( ((1-t)*low.value().blue() + t*high.value().blue())) ); + } + break; + } + case ciHSV: + { + QColor lowHsv = low.value().toHsv(); + QColor highHsv = high.value().toHsv(); + double hue = 0; + double hueDiff = highHsv.hueF()-lowHsv.hueF(); + if (hueDiff > 0.5) + hue = lowHsv.hueF() - t*(1.0-hueDiff); + else if (hueDiff < -0.5) + hue = lowHsv.hueF() + t*(1.0+hueDiff); + else + hue = lowHsv.hueF() + t*hueDiff; + if (hue < 0) hue += 1.0; + else if (hue >= 1.0) hue -= 1.0; + if (useAlpha) + { + const QRgb rgb = QColor::fromHsvF(hue, + (1-t)*lowHsv.saturationF() + t*highHsv.saturationF(), + (1-t)*lowHsv.valueF() + t*highHsv.valueF()).rgb(); + const double alpha = (1-t)*lowHsv.alphaF() + t*highHsv.alphaF(); + mColorBuffer[i] = qRgba(int(qRed(rgb)*alpha), int(qGreen(rgb)*alpha), int(qBlue(rgb)*alpha), int(255*alpha)); + } + else + { + mColorBuffer[i] = QColor::fromHsvF(hue, + (1-t)*lowHsv.saturationF() + t*highHsv.saturationF(), + (1-t)*lowHsv.valueF() + t*highHsv.valueF()).rgb(); + } + break; + } + } + } + } + } else if (mColorStops.size() == 1) { - key = keyAxis->pixelToCoord(y); - value = valueAxis->pixelToCoord(x); + const QRgb rgb = mColorStops.constBegin().value().rgb(); + const double alpha = mColorStops.constBegin().value().alphaF(); + mColorBuffer.fill(qRgba(int(qRed(rgb)*alpha), int(qGreen(rgb)*alpha), int(qBlue(rgb)*alpha), int(255*alpha))); + } else // mColorStops is empty, fill color buffer with black + { + mColorBuffer.fill(qRgb(0, 0, 0)); } + mColorBufferInvalidated = false; } +/* end of 'src/colorgradient.cpp' */ -/*! \internal - \overload - Returns the pixel input \a pixelPos as plot coordinates \a key and \a value. -*/ -void QCPAbstractPlottable::pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const -{ - pixelsToCoords(pixelPos.x(), pixelPos.y(), key, value); -} +/* including file 'src/selectiondecorator-bracket.cpp' */ +/* modified 2022-11-06T12:45:56, size 12308 */ -/*! \internal +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPSelectionDecoratorBracket +//////////////////////////////////////////////////////////////////////////////////////////////////// - Returns the pen that should be used for drawing lines of the plottable. Returns mPen when the - graph is not selected and mSelectedPen when it is. +/*! \class QCPSelectionDecoratorBracket + \brief A selection decorator which draws brackets around each selected data segment + + Additionally to the regular highlighting of selected segments via color, fill and scatter style, + this \ref QCPSelectionDecorator subclass draws markers at the begin and end of each selected data + segment of the plottable. + + The shape of the markers can be controlled with \ref setBracketStyle, \ref setBracketWidth and + \ref setBracketHeight. The color/fill can be controlled with \ref setBracketPen and \ref + setBracketBrush. + + To introduce custom bracket styles, it is only necessary to sublcass \ref + QCPSelectionDecoratorBracket and reimplement \ref drawBracket. The rest will be managed by the + base class. */ -QPen QCPAbstractPlottable::mainPen() const -{ - return mSelected ? mSelectedPen : mPen; -} -/*! \internal - - Returns the brush that should be used for drawing fills of the plottable. Returns mBrush when the - graph is not selected and mSelectedBrush when it is. +/*! + Creates a new QCPSelectionDecoratorBracket instance with default values. */ -QBrush QCPAbstractPlottable::mainBrush() const +QCPSelectionDecoratorBracket::QCPSelectionDecoratorBracket() : + mBracketPen(QPen(Qt::black)), + mBracketBrush(Qt::NoBrush), + mBracketWidth(5), + mBracketHeight(50), + mBracketStyle(bsSquareBracket), + mTangentToData(false), + mTangentAverage(2) { - return mSelected ? mSelectedBrush : mBrush; + } -/*! \internal - - A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter - before drawing plottable lines. - - This is the antialiasing state the painter passed to the \ref draw method is in by default. - - This function takes into account the local setting of the antialiasing flag as well as the - overrides set with \ref QCustomPlot::setAntialiasedElements and \ref - QCustomPlot::setNotAntialiasedElements. - - \see setAntialiased, applyFillAntialiasingHint, applyScattersAntialiasingHint, applyErrorBarsAntialiasingHint -*/ -void QCPAbstractPlottable::applyDefaultAntialiasingHint(QCPPainter *painter) const +QCPSelectionDecoratorBracket::~QCPSelectionDecoratorBracket() { - applyAntialiasingHint(painter, mAntialiased, QCP::aePlottables); } -/*! \internal - - A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter - before drawing plottable fills. - - This function takes into account the local setting of the antialiasing flag as well as the - overrides set with \ref QCustomPlot::setAntialiasedElements and \ref - QCustomPlot::setNotAntialiasedElements. - - \see setAntialiased, applyDefaultAntialiasingHint, applyScattersAntialiasingHint, applyErrorBarsAntialiasingHint +/*! + Sets the pen that will be used to draw the brackets at the beginning and end of each selected + data segment. */ -void QCPAbstractPlottable::applyFillAntialiasingHint(QCPPainter *painter) const +void QCPSelectionDecoratorBracket::setBracketPen(const QPen &pen) { - applyAntialiasingHint(painter, mAntialiasedFill, QCP::aeFills); + mBracketPen = pen; } -/*! \internal - - A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter - before drawing plottable scatter points. - - This function takes into account the local setting of the antialiasing flag as well as the - overrides set with \ref QCustomPlot::setAntialiasedElements and \ref - QCustomPlot::setNotAntialiasedElements. - - \see setAntialiased, applyFillAntialiasingHint, applyDefaultAntialiasingHint, applyErrorBarsAntialiasingHint +/*! + Sets the brush that will be used to draw the brackets at the beginning and end of each selected + data segment. */ -void QCPAbstractPlottable::applyScattersAntialiasingHint(QCPPainter *painter) const +void QCPSelectionDecoratorBracket::setBracketBrush(const QBrush &brush) { - applyAntialiasingHint(painter, mAntialiasedScatters, QCP::aeScatters); + mBracketBrush = brush; } -/*! \internal - - A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter - before drawing plottable error bars. - - This function takes into account the local setting of the antialiasing flag as well as the - overrides set with \ref QCustomPlot::setAntialiasedElements and \ref - QCustomPlot::setNotAntialiasedElements. - - \see setAntialiased, applyFillAntialiasingHint, applyScattersAntialiasingHint, applyDefaultAntialiasingHint +/*! + Sets the width of the drawn bracket. The width dimension is always parallel to the key axis of + the data, or the tangent direction of the current data slope, if \ref setTangentToData is + enabled. */ -void QCPAbstractPlottable::applyErrorBarsAntialiasingHint(QCPPainter *painter) const +void QCPSelectionDecoratorBracket::setBracketWidth(int width) { - applyAntialiasingHint(painter, mAntialiasedErrorBars, QCP::aeErrorBars); + mBracketWidth = width; } -/*! \internal - - Finds the shortest squared distance of \a point to the line segment defined by \a start and \a - end. - - This function may be used to help with the implementation of the \ref selectTest function for - specific plottables. - - \note This function is identical to QCPAbstractItem::distSqrToLine +/*! + Sets the height of the drawn bracket. The height dimension is always perpendicular to the key axis + of the data, or the tangent direction of the current data slope, if \ref setTangentToData is + enabled. */ -double QCPAbstractPlottable::distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const +void QCPSelectionDecoratorBracket::setBracketHeight(int height) { - QVector2D a(start); - QVector2D b(end); - QVector2D p(point); - QVector2D v(b-a); - - double vLengthSqr = v.lengthSquared(); - if (!qFuzzyIsNull(vLengthSqr)) - { - double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr; - if (mu < 0) - return (a-p).lengthSquared(); - else if (mu > 1) - return (b-p).lengthSquared(); - else - return ((a + mu*v)-p).lengthSquared(); - } else - return (a-p).lengthSquared(); + mBracketHeight = height; } -/* inherits documentation from base class */ -void QCPAbstractPlottable::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) +/*! + Sets the shape that the bracket/marker will have. + + \see setBracketWidth, setBracketHeight +*/ +void QCPSelectionDecoratorBracket::setBracketStyle(QCPSelectionDecoratorBracket::BracketStyle style) { - Q_UNUSED(event) - Q_UNUSED(details) - if (mSelectable) - { - bool selBefore = mSelected; - setSelected(additive ? !mSelected : true); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; - } + mBracketStyle = style; } -/* inherits documentation from base class */ -void QCPAbstractPlottable::deselectEvent(bool *selectionStateChanged) +/*! + Sets whether the brackets will be rotated such that they align with the slope of the data at the + position that they appear in. + + For noisy data, it might be more visually appealing to average the slope over multiple data + points. This can be configured via \ref setTangentAverage. +*/ +void QCPSelectionDecoratorBracket::setTangentToData(bool enabled) { - if (mSelectable) - { - bool selBefore = mSelected; - setSelected(false); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; - } + mTangentToData = enabled; } - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPItemAnchor -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPItemAnchor - \brief An anchor of an item to which positions can be attached to. - - An item (QCPAbstractItem) may have one or more anchors. Unlike QCPItemPosition, an anchor doesn't - control anything on its item, but provides a way to tie other items via their positions to the - anchor. - - For example, a QCPItemRect is defined by its positions \a topLeft and \a bottomRight. - Additionally it has various anchors like \a top, \a topRight or \a bottomLeft etc. So you can - attach the \a start (which is a QCPItemPosition) of a QCPItemLine to one of the anchors by - calling QCPItemPosition::setParentAnchor on \a start, passing the wanted anchor of the - QCPItemRect. This way the start of the line will now always follow the respective anchor location - on the rect item. - - Note that QCPItemPosition derives from QCPItemAnchor, so every position can also serve as an - anchor to other positions. +/*! + Controls over how many data points the slope shall be averaged, when brackets shall be aligned + with the data (if \ref setTangentToData is true). - To learn how to provide anchors in your own item subclasses, see the subclassing section of the - QCPAbstractItem documentation. + From the position of the bracket, \a pointCount points towards the selected data range will be + taken into account. The smallest value of \a pointCount is 1, which is effectively equivalent to + disabling \ref setTangentToData. */ +void QCPSelectionDecoratorBracket::setTangentAverage(int pointCount) +{ + mTangentAverage = pointCount; + if (mTangentAverage < 1) + mTangentAverage = 1; +} -/* start documentation of inline functions */ - -/*! \fn virtual QCPItemPosition *QCPItemAnchor::toQCPItemPosition() +/*! + Draws the bracket shape with \a painter. The parameter \a direction is either -1 or 1 and + indicates whether the bracket shall point to the left or the right (i.e. is a closing or opening + bracket, respectively). - Returns 0 if this instance is merely a QCPItemAnchor, and a valid pointer of type QCPItemPosition* if - it actually is a QCPItemPosition (which is a subclass of QCPItemAnchor). + The passed \a painter already contains all transformations that are necessary to position and + rotate the bracket appropriately. Painting operations can be performed as if drawing upright + brackets on flat data with horizontal key axis, with (0, 0) being the center of the bracket. - This safe downcast functionality could also be achieved with a dynamic_cast. However, QCustomPlot avoids - dynamic_cast to work with projects that don't have RTTI support enabled (e.g. -fno-rtti flag with - gcc compiler). -*/ - -/* end documentation of inline functions */ - -/*! - Creates a new QCPItemAnchor. You shouldn't create QCPItemAnchor instances directly, even if - you want to make a new item subclass. Use \ref QCPAbstractItem::createAnchor instead, as - explained in the subclassing section of the QCPAbstractItem documentation. + If you wish to sublcass \ref QCPSelectionDecoratorBracket in order to provide custom bracket + shapes (see \ref QCPSelectionDecoratorBracket::bsUserStyle), this is the method you should + reimplement. */ -QCPItemAnchor::QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name, int anchorId) : - mName(name), - mParentPlot(parentPlot), - mParentItem(parentItem), - mAnchorId(anchorId) -{ -} - -QCPItemAnchor::~QCPItemAnchor() +void QCPSelectionDecoratorBracket::drawBracket(QCPPainter *painter, int direction) const { - // unregister as parent at children: - foreach (QCPItemPosition *child, mChildrenX.toList()) - { - if (child->parentAnchorX() == this) - child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX - } - foreach (QCPItemPosition *child, mChildrenY.toList()) + switch (mBracketStyle) { - if (child->parentAnchorY() == this) - child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY + case bsSquareBracket: + { + painter->drawLine(QLineF(mBracketWidth*direction, -mBracketHeight*0.5, 0, -mBracketHeight*0.5)); + painter->drawLine(QLineF(mBracketWidth*direction, mBracketHeight*0.5, 0, mBracketHeight*0.5)); + painter->drawLine(QLineF(0, -mBracketHeight*0.5, 0, mBracketHeight*0.5)); + break; + } + case bsHalfEllipse: + { + painter->drawArc(QRectF(-mBracketWidth*0.5, -mBracketHeight*0.5, mBracketWidth, mBracketHeight), -90*16, -180*16*direction); + break; + } + case bsEllipse: + { + painter->drawEllipse(QRectF(-mBracketWidth*0.5, -mBracketHeight*0.5, mBracketWidth, mBracketHeight)); + break; + } + case bsPlus: + { + painter->drawLine(QLineF(0, -mBracketHeight*0.5, 0, mBracketHeight*0.5)); + painter->drawLine(QLineF(-mBracketWidth*0.5, 0, mBracketWidth*0.5, 0)); + break; + } + default: + { + qDebug() << Q_FUNC_INFO << "unknown/custom bracket style can't be handeld by default implementation:" << static_cast(mBracketStyle); + break; + } } } /*! - Returns the final absolute pixel position of the QCPItemAnchor on the QCustomPlot surface. + Draws the bracket decoration on the data points at the begin and end of each selected data + segment given in \a seletion. - The pixel information is internally retrieved via QCPAbstractItem::anchorPixelPosition of the - parent item, QCPItemAnchor is just an intermediary. + It uses the method \ref drawBracket to actually draw the shapes. + + \seebaseclassmethod */ -QPointF QCPItemAnchor::pixelPoint() const +void QCPSelectionDecoratorBracket::drawDecoration(QCPPainter *painter, QCPDataSelection selection) { - if (mParentItem) + if (!mPlottable || selection.isEmpty()) return; + + if (QCPPlottableInterface1D *interface1d = mPlottable->interface1D()) { - if (mAnchorId > -1) + foreach (const QCPDataRange &dataRange, selection.dataRanges()) { - return mParentItem->anchorPixelPoint(mAnchorId); - } else - { - qDebug() << Q_FUNC_INFO << "no valid anchor id set:" << mAnchorId; - return QPointF(); + // determine position and (if tangent mode is enabled) angle of brackets: + int openBracketDir = (mPlottable->keyAxis() && !mPlottable->keyAxis()->rangeReversed()) ? 1 : -1; + int closeBracketDir = -openBracketDir; + QPointF openBracketPos = getPixelCoordinates(interface1d, dataRange.begin()); + QPointF closeBracketPos = getPixelCoordinates(interface1d, dataRange.end()-1); + double openBracketAngle = 0; + double closeBracketAngle = 0; + if (mTangentToData) + { + openBracketAngle = getTangentAngle(interface1d, dataRange.begin(), openBracketDir); + closeBracketAngle = getTangentAngle(interface1d, dataRange.end()-1, closeBracketDir); + } + // draw opening bracket: + QTransform oldTransform = painter->transform(); + painter->setPen(mBracketPen); + painter->setBrush(mBracketBrush); + painter->translate(openBracketPos); + painter->rotate(openBracketAngle/M_PI*180.0); + drawBracket(painter, openBracketDir); + painter->setTransform(oldTransform); + // draw closing bracket: + painter->setPen(mBracketPen); + painter->setBrush(mBracketBrush); + painter->translate(closeBracketPos); + painter->rotate(closeBracketAngle/M_PI*180.0); + drawBracket(painter, closeBracketDir); + painter->setTransform(oldTransform); } - } else - { - qDebug() << Q_FUNC_INFO << "no parent item set"; - return QPointF(); } } /*! \internal - - Adds \a pos to the childX list of this anchor, which keeps track of which children use this - anchor as parent anchor for the respective coordinate. This is necessary to notify the children - prior to destruction of the anchor. - Note that this function does not change the parent setting in \a pos. + If \ref setTangentToData is enabled, brackets need to be rotated according to the data slope. + This method returns the angle in radians by which a bracket at the given \a dataIndex must be + rotated. + + The parameter \a direction must be set to either -1 or 1, representing whether it is an opening + or closing bracket. Since for slope calculation multiple data points are required, this defines + the direction in which the algorithm walks, starting at \a dataIndex, to average those data + points. (see \ref setTangentToData and \ref setTangentAverage) + + \a interface1d is the interface to the plottable's data which is used to query data coordinates. */ -void QCPItemAnchor::addChildX(QCPItemPosition *pos) +double QCPSelectionDecoratorBracket::getTangentAngle(const QCPPlottableInterface1D *interface1d, int dataIndex, int direction) const { - if (!mChildrenX.contains(pos)) - mChildrenX.insert(pos); + if (!interface1d || dataIndex < 0 || dataIndex >= interface1d->dataCount()) + return 0; + direction = direction < 0 ? -1 : 1; // enforce direction is either -1 or 1 + + // how many steps we can actually go from index in the given direction without exceeding data bounds: + int averageCount; + if (direction < 0) + averageCount = qMin(mTangentAverage, dataIndex); else - qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast(pos); + averageCount = qMin(mTangentAverage, interface1d->dataCount()-1-dataIndex); + qDebug() << averageCount; + // calculate point average of averageCount points: + QVector points(averageCount); + QPointF pointsAverage; + int currentIndex = dataIndex; + for (int i=0; ikeyAxis(); + QCPAxis *valueAxis = mPlottable->valueAxis(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return {0, 0}; } + + if (keyAxis->orientation() == Qt::Horizontal) + return {keyAxis->coordToPixel(interface1d->dataMainKey(dataIndex)), valueAxis->coordToPixel(interface1d->dataMainValue(dataIndex))}; + else + return {valueAxis->coordToPixel(interface1d->dataMainValue(dataIndex)), keyAxis->coordToPixel(interface1d->dataMainKey(dataIndex))}; +} +/* end of 'src/selectiondecorator-bracket.cpp' */ - Removes \a pos from the childX list of this anchor. + +/* including file 'src/layoutelements/layoutelement-axisrect.cpp' */ +/* modified 2022-11-06T12:45:56, size 47193 */ + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAxisRect +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPAxisRect + \brief Holds multiple axes and arranges them in a rectangular shape. + + This class represents an axis rect, a rectangular area that is bounded on all sides with an + arbitrary number of axes. + + Initially QCustomPlot has one axis rect, accessible via QCustomPlot::axisRect(). However, the + layout system allows to have multiple axis rects, e.g. arranged in a grid layout + (QCustomPlot::plotLayout). + + By default, QCPAxisRect comes with four axes, at bottom, top, left and right. They can be + accessed via \ref axis by providing the respective axis type (\ref QCPAxis::AxisType) and index. + If you need all axes in the axis rect, use \ref axes. The top and right axes are set to be + invisible initially (QCPAxis::setVisible). To add more axes to a side, use \ref addAxis or \ref + addAxes. To remove an axis, use \ref removeAxis. + + The axis rect layerable itself only draws a background pixmap or color, if specified (\ref + setBackground). It is placed on the "background" layer initially (see \ref QCPLayer for an + explanation of the QCustomPlot layer system). The axes that are held by the axis rect can be + placed on other layers, independently of the axis rect. + + Every axis rect has a child layout of type \ref QCPLayoutInset. It is accessible via \ref + insetLayout and can be used to have other layout elements (or even other layouts with multiple + elements) hovering inside the axis rect. + + If an axis rect is clicked and dragged, it processes this by moving certain axis ranges. The + behaviour can be controlled with \ref setRangeDrag and \ref setRangeDragAxes. If the mouse wheel + is scrolled while the cursor is on the axis rect, certain axes are scaled. This is controllable + via \ref setRangeZoom, \ref setRangeZoomAxes and \ref setRangeZoomFactor. These interactions are + only enabled if \ref QCustomPlot::setInteractions contains \ref QCP::iRangeDrag and \ref + QCP::iRangeZoom. - Note that this function does not change the parent setting in \a pos. + \image html AxisRectSpacingOverview.png +
Overview of the spacings and paddings that define the geometry of an axis. The dashed + line on the far left indicates the viewport/widget border.
*/ -void QCPItemAnchor::removeChildX(QCPItemPosition *pos) -{ - if (!mChildrenX.remove(pos)) - qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast(pos); -} -/*! \internal +/* start documentation of inline functions */ - Adds \a pos to the childY list of this anchor, which keeps track of which children use this - anchor as parent anchor for the respective coordinate. This is necessary to notify the children - prior to destruction of the anchor. +/*! \fn QCPLayoutInset *QCPAxisRect::insetLayout() const - Note that this function does not change the parent setting in \a pos. + Returns the inset layout of this axis rect. It can be used to place other layout elements (or + even layouts with multiple other elements) inside/on top of an axis rect. + + \see QCPLayoutInset */ -void QCPItemAnchor::addChildY(QCPItemPosition *pos) -{ - if (!mChildrenY.contains(pos)) - mChildrenY.insert(pos); - else - qDebug() << Q_FUNC_INFO << "provided pos is child already" << reinterpret_cast(pos); -} - -/*! \internal - Removes \a pos from the childY list of this anchor. +/*! \fn int QCPAxisRect::left() const - Note that this function does not change the parent setting in \a pos. + Returns the pixel position of the left border of this axis rect. Margins are not taken into + account here, so the returned value is with respect to the inner \ref rect. */ -void QCPItemAnchor::removeChildY(QCPItemPosition *pos) -{ - if (!mChildrenY.remove(pos)) - qDebug() << Q_FUNC_INFO << "provided pos isn't child" << reinterpret_cast(pos); -} - - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPItemPosition -//////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPItemPosition - \brief Manages the position of an item. +/*! \fn int QCPAxisRect::right() const - Every item has at least one public QCPItemPosition member pointer which provides ways to position the - item on the QCustomPlot surface. Some items have multiple positions, for example QCPItemRect has two: - \a topLeft and \a bottomRight. - - QCPItemPosition has a type (\ref PositionType) that can be set with \ref setType. This type - defines how coordinates passed to \ref setCoords are to be interpreted, e.g. as absolute pixel - coordinates, as plot coordinates of certain axes, etc. For more advanced plots it is also - possible to assign different types per X/Y coordinate of the position (see \ref setTypeX, \ref - setTypeY). This way an item could be positioned at a fixed pixel distance from the top in the Y - direction, while following a plot coordinate in the X direction. + Returns the pixel position of the right border of this axis rect. Margins are not taken into + account here, so the returned value is with respect to the inner \ref rect. +*/ - A QCPItemPosition may have a parent QCPItemAnchor, see \ref setParentAnchor. This way you can tie - multiple items together. If the QCPItemPosition has a parent, its coordinates (\ref setCoords) - are considered to be absolute pixels in the reference frame of the parent anchor, where (0, 0) - means directly ontop of the parent anchor. For example, You could attach the \a start position of - a QCPItemLine to the \a bottom anchor of a QCPItemText to make the starting point of the line - always be centered under the text label, no matter where the text is moved to. For more advanced - plots, it is possible to assign different parent anchors per X/Y coordinate of the position, see - \ref setParentAnchorX, \ref setParentAnchorY. This way an item could follow another item in the X - direction but stay at a fixed position in the Y direction. Or even follow item A in X, and item B - in Y. +/*! \fn int QCPAxisRect::top() const + + Returns the pixel position of the top border of this axis rect. Margins are not taken into + account here, so the returned value is with respect to the inner \ref rect. +*/ - Note that every QCPItemPosition inherits from QCPItemAnchor and thus can itself be used as parent - anchor for other positions. +/*! \fn int QCPAxisRect::bottom() const + + Returns the pixel position of the bottom border of this axis rect. Margins are not taken into + account here, so the returned value is with respect to the inner \ref rect. +*/ - To set the apparent pixel position on the QCustomPlot surface directly, use \ref setPixelPoint. This - works no matter what type this QCPItemPosition is or what parent-child situation it is in, as \ref - setPixelPoint transforms the coordinates appropriately, to make the position appear at the specified - pixel values. +/*! \fn int QCPAxisRect::width() const + + Returns the pixel width of this axis rect. Margins are not taken into account here, so the + returned value is with respect to the inner \ref rect. */ -/* start documentation of inline functions */ +/*! \fn int QCPAxisRect::height() const + + Returns the pixel height of this axis rect. Margins are not taken into account here, so the + returned value is with respect to the inner \ref rect. +*/ -/*! \fn QCPItemPosition::PositionType *QCPItemPosition::type() const +/*! \fn QSize QCPAxisRect::size() const - Returns the current position type. + Returns the pixel size of this axis rect. Margins are not taken into account here, so the + returned value is with respect to the inner \ref rect. +*/ + +/*! \fn QPoint QCPAxisRect::topLeft() const - If different types were set for X and Y (\ref setTypeX, \ref setTypeY), this method returns the - type of the X coordinate. In that case rather use \a typeX() and \a typeY(). + Returns the top left corner of this axis rect in pixels. Margins are not taken into account here, + so the returned value is with respect to the inner \ref rect. +*/ + +/*! \fn QPoint QCPAxisRect::topRight() const - \see setType + Returns the top right corner of this axis rect in pixels. Margins are not taken into account + here, so the returned value is with respect to the inner \ref rect. */ -/*! \fn QCPItemAnchor *QCPItemPosition::parentAnchor() const +/*! \fn QPoint QCPAxisRect::bottomLeft() const - Returns the current parent anchor. + Returns the bottom left corner of this axis rect in pixels. Margins are not taken into account + here, so the returned value is with respect to the inner \ref rect. +*/ + +/*! \fn QPoint QCPAxisRect::bottomRight() const - If different parent anchors were set for X and Y (\ref setParentAnchorX, \ref setParentAnchorY), - this method returns the parent anchor of the Y coordinate. In that case rather use \a - parentAnchorX() and \a parentAnchorY(). + Returns the bottom right corner of this axis rect in pixels. Margins are not taken into account + here, so the returned value is with respect to the inner \ref rect. +*/ + +/*! \fn QPoint QCPAxisRect::center() const - \see setParentAnchor + Returns the center of this axis rect in pixels. Margins are not taken into account here, so the + returned value is with respect to the inner \ref rect. */ /* end documentation of inline functions */ /*! - Creates a new QCPItemPosition. You shouldn't create QCPItemPosition instances directly, even if - you want to make a new item subclass. Use \ref QCPAbstractItem::createPosition instead, as - explained in the subclassing section of the QCPAbstractItem documentation. + Creates a QCPAxisRect instance and sets default values. An axis is added for each of the four + sides, the top and right axes are set invisible initially. */ -QCPItemPosition::QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name) : - QCPItemAnchor(parentPlot, parentItem, name), - mPositionTypeX(ptAbsolute), - mPositionTypeY(ptAbsolute), - mKey(0), - mValue(0), - mParentAnchorX(0), - mParentAnchorY(0) -{ -} - -QCPItemPosition::~QCPItemPosition() +QCPAxisRect::QCPAxisRect(QCustomPlot *parentPlot, bool setupDefaultAxes) : + QCPLayoutElement(parentPlot), + mBackgroundBrush(Qt::NoBrush), + mBackgroundScaled(true), + mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding), + mInsetLayout(new QCPLayoutInset), + mRangeDrag(Qt::Horizontal|Qt::Vertical), + mRangeZoom(Qt::Horizontal|Qt::Vertical), + mRangeZoomFactorHorz(0.85), + mRangeZoomFactorVert(0.85), + mDragging(false) { - // unregister as parent at children: - // Note: this is done in ~QCPItemAnchor again, but it's important QCPItemPosition does it itself, because only then - // the setParentAnchor(0) call the correct QCPItemPosition::pixelPoint function instead of QCPItemAnchor::pixelPoint - foreach (QCPItemPosition *child, mChildrenX.toList()) - { - if (child->parentAnchorX() == this) - child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX - } - foreach (QCPItemPosition *child, mChildrenY.toList()) + mInsetLayout->initializeParentPlot(mParentPlot); + mInsetLayout->setParentLayerable(this); + mInsetLayout->setParent(this); + + setMinimumSize(50, 50); + setMinimumMargins(QMargins(15, 15, 15, 15)); + mAxes.insert(QCPAxis::atLeft, QList()); + mAxes.insert(QCPAxis::atRight, QList()); + mAxes.insert(QCPAxis::atTop, QList()); + mAxes.insert(QCPAxis::atBottom, QList()); + + if (setupDefaultAxes) { - if (child->parentAnchorY() == this) - child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY + QCPAxis *xAxis = addAxis(QCPAxis::atBottom); + QCPAxis *yAxis = addAxis(QCPAxis::atLeft); + QCPAxis *xAxis2 = addAxis(QCPAxis::atTop); + QCPAxis *yAxis2 = addAxis(QCPAxis::atRight); + setRangeDragAxes(xAxis, yAxis); + setRangeZoomAxes(xAxis, yAxis); + xAxis2->setVisible(false); + yAxis2->setVisible(false); + xAxis->grid()->setVisible(true); + yAxis->grid()->setVisible(true); + xAxis2->grid()->setVisible(false); + yAxis2->grid()->setVisible(false); + xAxis2->grid()->setZeroLinePen(Qt::NoPen); + yAxis2->grid()->setZeroLinePen(Qt::NoPen); + xAxis2->grid()->setVisible(false); + yAxis2->grid()->setVisible(false); } - // unregister as child in parent: - if (mParentAnchorX) - mParentAnchorX->removeChildX(this); - if (mParentAnchorY) - mParentAnchorY->removeChildY(this); } -/* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */ -QCPAxisRect *QCPItemPosition::axisRect() const +QCPAxisRect::~QCPAxisRect() { - return mAxisRect.data(); -} - -/*! - Sets the type of the position. The type defines how the coordinates passed to \ref setCoords - should be handled and how the QCPItemPosition should behave in the plot. - - The possible values for \a type can be separated in two main categories: - - \li The position is regarded as a point in plot coordinates. This corresponds to \ref ptPlotCoords - and requires two axes that define the plot coordinate system. They can be specified with \ref setAxes. - By default, the QCustomPlot's x- and yAxis are used. - - \li The position is fixed on the QCustomPlot surface, i.e. independent of axis ranges. This - corresponds to all other types, i.e. \ref ptAbsolute, \ref ptViewportRatio and \ref - ptAxisRectRatio. They differ only in the way the absolute position is described, see the - documentation of \ref PositionType for details. For \ref ptAxisRectRatio, note that you can specify - the axis rect with \ref setAxisRect. By default this is set to the main axis rect. - - Note that the position type \ref ptPlotCoords is only available (and sensible) when the position - has no parent anchor (\ref setParentAnchor). - - If the type is changed, the apparent pixel position on the plot is preserved. This means - the coordinates as retrieved with coords() and set with \ref setCoords may change in the process. + delete mInsetLayout; + mInsetLayout = nullptr; - This method sets the type for both X and Y directions. It is also possible to set different types - for X and Y, see \ref setTypeX, \ref setTypeY. -*/ -void QCPItemPosition::setType(QCPItemPosition::PositionType type) -{ - setTypeX(type); - setTypeY(type); + foreach (QCPAxis *axis, axes()) + removeAxis(axis); } /*! - This method sets the position type of the X coordinate to \a type. - - For a detailed description of what a position type is, see the documentation of \ref setType. + Returns the number of axes on the axis rect side specified with \a type. - \see setType, setTypeY -*/ -void QCPItemPosition::setTypeX(QCPItemPosition::PositionType type) -{ - if (mPositionTypeX != type) - { - // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect - // were deleted), don't try to recover the pixelPoint() because it would output a qDebug warning. - bool retainPixelPosition = true; - if ((mPositionTypeX == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis)) - retainPixelPosition = false; - if ((mPositionTypeX == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect)) - retainPixelPosition = false; - - QPointF pixel; - if (retainPixelPosition) - pixel = pixelPoint(); - - mPositionTypeX = type; - - if (retainPixelPosition) - setPixelPoint(pixel); - } + \see axis +*/ +int QCPAxisRect::axisCount(QCPAxis::AxisType type) const +{ + return mAxes.value(type).size(); } /*! - This method sets the position type of the Y coordinate to \a type. - - For a detailed description of what a position type is, see the documentation of \ref setType. + Returns the axis with the given \a index on the axis rect side specified with \a type. - \see setType, setTypeX + \see axisCount, axes */ -void QCPItemPosition::setTypeY(QCPItemPosition::PositionType type) +QCPAxis *QCPAxisRect::axis(QCPAxis::AxisType type, int index) const { - if (mPositionTypeY != type) + QList ax(mAxes.value(type)); + if (index >= 0 && index < ax.size()) { - // if switching from or to coordinate type that isn't valid (e.g. because axes or axis rect - // were deleted), don't try to recover the pixelPoint() because it would output a qDebug warning. - bool retainPixelPosition = true; - if ((mPositionTypeY == ptPlotCoords || type == ptPlotCoords) && (!mKeyAxis || !mValueAxis)) - retainPixelPosition = false; - if ((mPositionTypeY == ptAxisRectRatio || type == ptAxisRectRatio) && (!mAxisRect)) - retainPixelPosition = false; - - QPointF pixel; - if (retainPixelPosition) - pixel = pixelPoint(); - - mPositionTypeY = type; - - if (retainPixelPosition) - setPixelPoint(pixel); + return ax.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "Axis index out of bounds:" << index; + return nullptr; } } /*! - Sets the parent of this QCPItemPosition to \a parentAnchor. This means the position will now - follow any position changes of the anchor. The local coordinate system of positions with a parent - anchor always is absolute pixels, with (0, 0) being exactly on top of the parent anchor. (Hence - the type shouldn't be set to \ref ptPlotCoords for positions with parent anchors.) - - if \a keepPixelPosition is true, the current pixel position of the QCPItemPosition is preserved - during reparenting. If it's set to false, the coordinates are set to (0, 0), i.e. the position - will be exactly on top of the parent anchor. - - To remove this QCPItemPosition from any parent anchor, set \a parentAnchor to 0. + Returns all axes on the axis rect sides specified with \a types. - If the QCPItemPosition previously had no parent and the type is \ref ptPlotCoords, the type is - set to \ref ptAbsolute, to keep the position in a valid state. + \a types may be a single \ref QCPAxis::AxisType or an or-combination, to get the axes of + multiple sides. - This method sets the parent anchor for both X and Y directions. It is also possible to set - different parents for X and Y, see \ref setParentAnchorX, \ref setParentAnchorY. + \see axis */ -bool QCPItemPosition::setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition) +QList QCPAxisRect::axes(QCPAxis::AxisTypes types) const { - bool successX = setParentAnchorX(parentAnchor, keepPixelPosition); - bool successY = setParentAnchorY(parentAnchor, keepPixelPosition); - return successX && successY; + QList result; + if (types.testFlag(QCPAxis::atLeft)) + result << mAxes.value(QCPAxis::atLeft); + if (types.testFlag(QCPAxis::atRight)) + result << mAxes.value(QCPAxis::atRight); + if (types.testFlag(QCPAxis::atTop)) + result << mAxes.value(QCPAxis::atTop); + if (types.testFlag(QCPAxis::atBottom)) + result << mAxes.value(QCPAxis::atBottom); + return result; } -/*! - This method sets the parent anchor of the X coordinate to \a parentAnchor. - - For a detailed description of what a parent anchor is, see the documentation of \ref setParentAnchor. +/*! \overload - \see setParentAnchor, setParentAnchorY + Returns all axes of this axis rect. */ -bool QCPItemPosition::setParentAnchorX(QCPItemAnchor *parentAnchor, bool keepPixelPosition) +QList QCPAxisRect::axes() const { - // make sure self is not assigned as parent: - if (parentAnchor == this) + QList result; + QHashIterator > it(mAxes); + while (it.hasNext()) { - qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast(parentAnchor); - return false; + it.next(); + result << it.value(); } - // make sure no recursive parent-child-relationships are created: - QCPItemAnchor *currentParent = parentAnchor; - while (currentParent) + return result; +} + +/*! + Adds a new axis to the axis rect side specified with \a type, and returns it. If \a axis is 0, a + new QCPAxis instance is created internally. QCustomPlot owns the returned axis, so if you want to + remove an axis, use \ref removeAxis instead of deleting it manually. + + You may inject QCPAxis instances (or subclasses of QCPAxis) by setting \a axis to an axis that was + previously created outside QCustomPlot. It is important to note that QCustomPlot takes ownership + of the axis, so you may not delete it afterwards. Further, the \a axis must have been created + with this axis rect as parent and with the same axis type as specified in \a type. If this is not + the case, a debug output is generated, the axis is not added, and the method returns \c nullptr. + + This method can not be used to move \a axis between axis rects. The same \a axis instance must + not be added multiple times to the same or different axis rects. + + If an axis rect side already contains one or more axes, the lower and upper endings of the new + axis (\ref QCPAxis::setLowerEnding, \ref QCPAxis::setUpperEnding) are set to \ref + QCPLineEnding::esHalfBar. + + \see addAxes, setupFullAxesBox +*/ +QCPAxis *QCPAxisRect::addAxis(QCPAxis::AxisType type, QCPAxis *axis) +{ + QCPAxis *newAxis = axis; + if (!newAxis) { - if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition()) + newAxis = new QCPAxis(this, type); + } else // user provided existing axis instance, do some sanity checks + { + if (newAxis->axisType() != type) { - // is a QCPItemPosition, might have further parent, so keep iterating - if (currentParentPos == this) - { - qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast(parentAnchor); - return false; - } - currentParent = currentParentPos->parentAnchorX(); - } else + qDebug() << Q_FUNC_INFO << "passed axis has different axis type than specified in type parameter"; + return nullptr; + } + if (newAxis->axisRect() != this) { - // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the - // same, to prevent a position being child of an anchor which itself depends on the position, - // because they're both on the same item: - if (currentParent->mParentItem == mParentItem) - { - qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast(parentAnchor); - return false; - } - break; + qDebug() << Q_FUNC_INFO << "passed axis doesn't have this axis rect as parent axis rect"; + return nullptr; + } + if (axes().contains(newAxis)) + { + qDebug() << Q_FUNC_INFO << "passed axis is already owned by this axis rect"; + return nullptr; } } + if (!mAxes[type].isEmpty()) // multiple axes on one side, add half-bar axis ending to additional axes with offset + { + bool invert = (type == QCPAxis::atRight) || (type == QCPAxis::atBottom); + newAxis->setLowerEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, !invert)); + newAxis->setUpperEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, invert)); + } + mAxes[type].append(newAxis); - // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute: - if (!mParentAnchorX && mPositionTypeX == ptPlotCoords) - setTypeX(ptAbsolute); + // reset convenience axis pointers on parent QCustomPlot if they are unset: + if (mParentPlot && mParentPlot->axisRectCount() > 0 && mParentPlot->axisRect(0) == this) + { + switch (type) + { + case QCPAxis::atBottom: { if (!mParentPlot->xAxis) mParentPlot->xAxis = newAxis; break; } + case QCPAxis::atLeft: { if (!mParentPlot->yAxis) mParentPlot->yAxis = newAxis; break; } + case QCPAxis::atTop: { if (!mParentPlot->xAxis2) mParentPlot->xAxis2 = newAxis; break; } + case QCPAxis::atRight: { if (!mParentPlot->yAxis2) mParentPlot->yAxis2 = newAxis; break; } + } + } - // save pixel position: - QPointF pixelP; - if (keepPixelPosition) - pixelP = pixelPoint(); - // unregister at current parent anchor: - if (mParentAnchorX) - mParentAnchorX->removeChildX(this); - // register at new parent anchor: - if (parentAnchor) - parentAnchor->addChildX(this); - mParentAnchorX = parentAnchor; - // restore pixel position under new parent: - if (keepPixelPosition) - setPixelPoint(pixelP); - else - setCoords(0, coords().y()); - return true; + return newAxis; } /*! - This method sets the parent anchor of the Y coordinate to \a parentAnchor. + Adds a new axis with \ref addAxis to each axis rect side specified in \a types. This may be an + or-combination of QCPAxis::AxisType, so axes can be added to multiple sides at once. - For a detailed description of what a parent anchor is, see the documentation of \ref setParentAnchor. + Returns a list of the added axes. - \see setParentAnchor, setParentAnchorX + \see addAxis, setupFullAxesBox */ -bool QCPItemPosition::setParentAnchorY(QCPItemAnchor *parentAnchor, bool keepPixelPosition) +QList QCPAxisRect::addAxes(QCPAxis::AxisTypes types) { - // make sure self is not assigned as parent: - if (parentAnchor == this) - { - qDebug() << Q_FUNC_INFO << "can't set self as parent anchor" << reinterpret_cast(parentAnchor); - return false; - } - // make sure no recursive parent-child-relationships are created: - QCPItemAnchor *currentParent = parentAnchor; - while (currentParent) + QList result; + if (types.testFlag(QCPAxis::atLeft)) + result << addAxis(QCPAxis::atLeft); + if (types.testFlag(QCPAxis::atRight)) + result << addAxis(QCPAxis::atRight); + if (types.testFlag(QCPAxis::atTop)) + result << addAxis(QCPAxis::atTop); + if (types.testFlag(QCPAxis::atBottom)) + result << addAxis(QCPAxis::atBottom); + return result; +} + +/*! + Removes the specified \a axis from the axis rect and deletes it. + + Returns true on success, i.e. if \a axis was a valid axis in this axis rect. + + \see addAxis +*/ +bool QCPAxisRect::removeAxis(QCPAxis *axis) +{ + // don't access axis->axisType() to provide safety when axis is an invalid pointer, rather go through all axis containers: + QHashIterator > it(mAxes); + while (it.hasNext()) { - if (QCPItemPosition *currentParentPos = currentParent->toQCPItemPosition()) - { - // is a QCPItemPosition, might have further parent, so keep iterating - if (currentParentPos == this) - { - qDebug() << Q_FUNC_INFO << "can't create recursive parent-child-relationship" << reinterpret_cast(parentAnchor); - return false; - } - currentParent = currentParentPos->parentAnchorY(); - } else + it.next(); + if (it.value().contains(axis)) { - // is a QCPItemAnchor, can't have further parent. Now make sure the parent items aren't the - // same, to prevent a position being child of an anchor which itself depends on the position, - // because they're both on the same item: - if (currentParent->mParentItem == mParentItem) - { - qDebug() << Q_FUNC_INFO << "can't set parent to be an anchor which itself depends on this position" << reinterpret_cast(parentAnchor); - return false; - } - break; + if (it.value().first() == axis && it.value().size() > 1) // if removing first axis, transfer axis offset to the new first axis (which at this point is the second axis, if it exists) + it.value()[1]->setOffset(axis->offset()); + mAxes[it.key()].removeOne(axis); + if (qobject_cast(parentPlot())) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the axis rect is not in any layout and thus QObject-child of QCustomPlot) + parentPlot()->axisRemoved(axis); + delete axis; + return true; } - } - - // if previously no parent set and PosType is still ptPlotCoords, set to ptAbsolute: - if (!mParentAnchorY && mPositionTypeY == ptPlotCoords) - setTypeY(ptAbsolute); - - // save pixel position: - QPointF pixelP; - if (keepPixelPosition) - pixelP = pixelPoint(); - // unregister at current parent anchor: - if (mParentAnchorY) - mParentAnchorY->removeChildY(this); - // register at new parent anchor: - if (parentAnchor) - parentAnchor->addChildY(this); - mParentAnchorY = parentAnchor; - // restore pixel position under new parent: - if (keepPixelPosition) - setPixelPoint(pixelP); - else - setCoords(coords().x(), 0); - return true; + } + qDebug() << Q_FUNC_INFO << "Axis isn't in axis rect:" << reinterpret_cast(axis); + return false; } /*! - Sets the coordinates of this QCPItemPosition. What the coordinates mean, is defined by the type - (\ref setType, \ref setTypeX, \ref setTypeY). - - For example, if the type is \ref ptAbsolute, \a key and \a value mean the x and y pixel position - on the QCustomPlot surface. In that case the origin (0, 0) is in the top left corner of the - QCustomPlot viewport. If the type is \ref ptPlotCoords, \a key and \a value mean a point in the - plot coordinate system defined by the axes set by \ref setAxes. By default those are the - QCustomPlot's xAxis and yAxis. See the documentation of \ref setType for other available - coordinate types and their meaning. - - If different types were configured for X and Y (\ref setTypeX, \ref setTypeY), \a key and \a - value must also be provided in the different coordinate systems. Here, the X type refers to \a - key, and the Y type refers to \a value. + Zooms in (or out) to the passed rectangular region \a pixelRect, given in pixel coordinates. - \see setPixelPoint + All axes of this axis rect will have their range zoomed accordingly. If you only wish to zoom + specific axes, use the overloaded version of this method. + + \see QCustomPlot::setSelectionRectMode */ -void QCPItemPosition::setCoords(double key, double value) +void QCPAxisRect::zoom(const QRectF &pixelRect) { - mKey = key; - mValue = value; + zoom(pixelRect, axes()); } /*! \overload - - Sets the coordinates as a QPointF \a pos where pos.x has the meaning of \a key and pos.y the - meaning of \a value of the \ref setCoords(double key, double value) method. + + Zooms in (or out) to the passed rectangular region \a pixelRect, given in pixel coordinates. + + Only the axes passed in \a affectedAxes will have their ranges zoomed accordingly. + + \see QCustomPlot::setSelectionRectMode */ -void QCPItemPosition::setCoords(const QPointF &pos) +void QCPAxisRect::zoom(const QRectF &pixelRect, const QList &affectedAxes) { - setCoords(pos.x(), pos.y()); + foreach (QCPAxis *axis, affectedAxes) + { + if (!axis) + { + qDebug() << Q_FUNC_INFO << "a passed axis was zero"; + continue; + } + QCPRange pixelRange; + if (axis->orientation() == Qt::Horizontal) + pixelRange = QCPRange(pixelRect.left(), pixelRect.right()); + else + pixelRange = QCPRange(pixelRect.top(), pixelRect.bottom()); + axis->setRange(axis->pixelToCoord(pixelRange.lower), axis->pixelToCoord(pixelRange.upper)); + } } /*! - Returns the final absolute pixel position of the QCPItemPosition on the QCustomPlot surface. It - includes all effects of type (\ref setType) and possible parent anchors (\ref setParentAnchor). + Convenience function to create an axis on each side that doesn't have any axes yet and set their + visibility to true. Further, the top/right axes are assigned the following properties of the + bottom/left axes: + + \li range (\ref QCPAxis::setRange) + \li range reversed (\ref QCPAxis::setRangeReversed) + \li scale type (\ref QCPAxis::setScaleType) + \li tick visibility (\ref QCPAxis::setTicks) + \li number format (\ref QCPAxis::setNumberFormat) + \li number precision (\ref QCPAxis::setNumberPrecision) + \li tick count of ticker (\ref QCPAxisTicker::setTickCount) + \li tick origin of ticker (\ref QCPAxisTicker::setTickOrigin) + + Tick label visibility (\ref QCPAxis::setTickLabels) of the right and top axes are set to false. - \see setPixelPoint + If \a connectRanges is true, the \ref QCPAxis::rangeChanged "rangeChanged" signals of the bottom + and left axes are connected to the \ref QCPAxis::setRange slots of the top and right axes. */ -QPointF QCPItemPosition::pixelPoint() const +void QCPAxisRect::setupFullAxesBox(bool connectRanges) { - QPointF result; + QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2; + if (axisCount(QCPAxis::atBottom) == 0) + xAxis = addAxis(QCPAxis::atBottom); + else + xAxis = axis(QCPAxis::atBottom); - // determine X: - switch (mPositionTypeX) - { - case ptAbsolute: - { - result.rx() = mKey; - if (mParentAnchorX) - result.rx() += mParentAnchorX->pixelPoint().x(); - break; - } - case ptViewportRatio: - { - result.rx() = mKey*mParentPlot->viewport().width(); - if (mParentAnchorX) - result.rx() += mParentAnchorX->pixelPoint().x(); - else - result.rx() += mParentPlot->viewport().left(); - break; - } - case ptAxisRectRatio: - { - if (mAxisRect) - { - result.rx() = mKey*mAxisRect.data()->width(); - if (mParentAnchorX) - result.rx() += mParentAnchorX->pixelPoint().x(); - else - result.rx() += mAxisRect.data()->left(); - } else - qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined"; - break; - } - case ptPlotCoords: - { - if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal) - result.rx() = mKeyAxis.data()->coordToPixel(mKey); - else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal) - result.rx() = mValueAxis.data()->coordToPixel(mValue); - else - qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined"; - break; - } - } + if (axisCount(QCPAxis::atLeft) == 0) + yAxis = addAxis(QCPAxis::atLeft); + else + yAxis = axis(QCPAxis::atLeft); - // determine Y: - switch (mPositionTypeY) + if (axisCount(QCPAxis::atTop) == 0) + xAxis2 = addAxis(QCPAxis::atTop); + else + xAxis2 = axis(QCPAxis::atTop); + + if (axisCount(QCPAxis::atRight) == 0) + yAxis2 = addAxis(QCPAxis::atRight); + else + yAxis2 = axis(QCPAxis::atRight); + + xAxis->setVisible(true); + yAxis->setVisible(true); + xAxis2->setVisible(true); + yAxis2->setVisible(true); + xAxis2->setTickLabels(false); + yAxis2->setTickLabels(false); + + xAxis2->setRange(xAxis->range()); + xAxis2->setRangeReversed(xAxis->rangeReversed()); + xAxis2->setScaleType(xAxis->scaleType()); + xAxis2->setTicks(xAxis->ticks()); + xAxis2->setNumberFormat(xAxis->numberFormat()); + xAxis2->setNumberPrecision(xAxis->numberPrecision()); + xAxis2->ticker()->setTickCount(xAxis->ticker()->tickCount()); + xAxis2->ticker()->setTickOrigin(xAxis->ticker()->tickOrigin()); + + yAxis2->setRange(yAxis->range()); + yAxis2->setRangeReversed(yAxis->rangeReversed()); + yAxis2->setScaleType(yAxis->scaleType()); + yAxis2->setTicks(yAxis->ticks()); + yAxis2->setNumberFormat(yAxis->numberFormat()); + yAxis2->setNumberPrecision(yAxis->numberPrecision()); + yAxis2->ticker()->setTickCount(yAxis->ticker()->tickCount()); + yAxis2->ticker()->setTickOrigin(yAxis->ticker()->tickOrigin()); + + if (connectRanges) { - case ptAbsolute: - { - result.ry() = mValue; - if (mParentAnchorY) - result.ry() += mParentAnchorY->pixelPoint().y(); - break; - } - case ptViewportRatio: - { - result.ry() = mValue*mParentPlot->viewport().height(); - if (mParentAnchorY) - result.ry() += mParentAnchorY->pixelPoint().y(); - else - result.ry() += mParentPlot->viewport().top(); - break; - } - case ptAxisRectRatio: - { - if (mAxisRect) - { - result.ry() = mValue*mAxisRect.data()->height(); - if (mParentAnchorY) - result.ry() += mParentAnchorY->pixelPoint().y(); - else - result.ry() += mAxisRect.data()->top(); - } else - qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined"; - break; - } - case ptPlotCoords: - { - if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical) - result.ry() = mKeyAxis.data()->coordToPixel(mKey); - else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical) - result.ry() = mValueAxis.data()->coordToPixel(mValue); - else - qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined"; - break; - } + connect(xAxis, SIGNAL(rangeChanged(QCPRange)), xAxis2, SLOT(setRange(QCPRange))); + connect(yAxis, SIGNAL(rangeChanged(QCPRange)), yAxis2, SLOT(setRange(QCPRange))); } - - return result; -} - -/*! - When \ref setType is \ref ptPlotCoords, this function may be used to specify the axes the - coordinates set with \ref setCoords relate to. By default they are set to the initial xAxis and - yAxis of the QCustomPlot. -*/ -void QCPItemPosition::setAxes(QCPAxis *keyAxis, QCPAxis *valueAxis) -{ - mKeyAxis = keyAxis; - mValueAxis = valueAxis; } /*! - When \ref setType is \ref ptAxisRectRatio, this function may be used to specify the axis rect the - coordinates set with \ref setCoords relate to. By default this is set to the main axis rect of - the QCustomPlot. + Returns a list of all the plottables that are associated with this axis rect. + + A plottable is considered associated with an axis rect if its key or value axis (or both) is in + this axis rect. + + \see graphs, items */ -void QCPItemPosition::setAxisRect(QCPAxisRect *axisRect) +QList QCPAxisRect::plottables() const { - mAxisRect = axisRect; + // Note: don't append all QCPAxis::plottables() into a list, because we might get duplicate entries + QList result; + foreach (QCPAbstractPlottable *plottable, mParentPlot->mPlottables) + { + if (plottable->keyAxis()->axisRect() == this || plottable->valueAxis()->axisRect() == this) + result.append(plottable); + } + return result; } /*! - Sets the apparent pixel position. This works no matter what type (\ref setType) this - QCPItemPosition is or what parent-child situation it is in, as coordinates are transformed - appropriately, to make the position finally appear at the specified pixel values. - - Only if the type is \ref ptAbsolute and no parent anchor is set, this function's effect is - identical to that of \ref setCoords. - - \see pixelPoint, setCoords + Returns a list of all the graphs that are associated with this axis rect. + + A graph is considered associated with an axis rect if its key or value axis (or both) is in + this axis rect. + + \see plottables, items */ -void QCPItemPosition::setPixelPoint(const QPointF &pixelPoint) +QList QCPAxisRect::graphs() const { - double x = pixelPoint.x(); - double y = pixelPoint.y(); - - switch (mPositionTypeX) + // Note: don't append all QCPAxis::graphs() into a list, because we might get duplicate entries + QList result; + foreach (QCPGraph *graph, mParentPlot->mGraphs) { - case ptAbsolute: - { - if (mParentAnchorX) - x -= mParentAnchorX->pixelPoint().x(); - break; - } - case ptViewportRatio: - { - if (mParentAnchorX) - x -= mParentAnchorX->pixelPoint().x(); - else - x -= mParentPlot->viewport().left(); - x /= (double)mParentPlot->viewport().width(); - break; - } - case ptAxisRectRatio: - { - if (mAxisRect) - { - if (mParentAnchorX) - x -= mParentAnchorX->pixelPoint().x(); - else - x -= mAxisRect.data()->left(); - x /= (double)mAxisRect.data()->width(); - } else - qDebug() << Q_FUNC_INFO << "Item position type x is ptAxisRectRatio, but no axis rect was defined"; - break; - } - case ptPlotCoords: - { - if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Horizontal) - x = mKeyAxis.data()->pixelToCoord(x); - else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Horizontal) - y = mValueAxis.data()->pixelToCoord(x); - else - qDebug() << Q_FUNC_INFO << "Item position type x is ptPlotCoords, but no axes were defined"; - break; - } + if (graph->keyAxis()->axisRect() == this || graph->valueAxis()->axisRect() == this) + result.append(graph); } + return result; +} + +/*! + Returns a list of all the items that are associated with this axis rect. - switch (mPositionTypeY) + An item is considered associated with an axis rect if any of its positions has key or value axis + set to an axis that is in this axis rect, or if any of its positions has \ref + QCPItemPosition::setAxisRect set to the axis rect, or if the clip axis rect (\ref + QCPAbstractItem::setClipAxisRect) is set to this axis rect. + + \see plottables, graphs +*/ +QList QCPAxisRect::items() const +{ + // Note: don't just append all QCPAxis::items() into a list, because we might get duplicate entries + // and miss those items that have this axis rect as clipAxisRect. + QList result; + foreach (QCPAbstractItem *item, mParentPlot->mItems) { - case ptAbsolute: + if (item->clipAxisRect() == this) { - if (mParentAnchorY) - y -= mParentAnchorY->pixelPoint().y(); - break; + result.append(item); + continue; } - case ptViewportRatio: + foreach (QCPItemPosition *position, item->positions()) { - if (mParentAnchorY) - y -= mParentAnchorY->pixelPoint().y(); - else - y -= mParentPlot->viewport().top(); - y /= (double)mParentPlot->viewport().height(); - break; + if (position->axisRect() == this || + position->keyAxis()->axisRect() == this || + position->valueAxis()->axisRect() == this) + { + result.append(item); + break; + } } - case ptAxisRectRatio: + } + return result; +} + +/*! + This method is called automatically upon replot and doesn't need to be called by users of + QCPAxisRect. + + Calls the base class implementation to update the margins (see \ref QCPLayoutElement::update), + and finally passes the \ref rect to the inset layout (\ref insetLayout) and calls its + QCPInsetLayout::update function. + + \seebaseclassmethod +*/ +void QCPAxisRect::update(UpdatePhase phase) +{ + QCPLayoutElement::update(phase); + + switch (phase) + { + case upPreparation: { - if (mAxisRect) - { - if (mParentAnchorY) - y -= mParentAnchorY->pixelPoint().y(); - else - y -= mAxisRect.data()->top(); - y /= (double)mAxisRect.data()->height(); - } else - qDebug() << Q_FUNC_INFO << "Item position type y is ptAxisRectRatio, but no axis rect was defined"; + foreach (QCPAxis *axis, axes()) + axis->setupTickVectors(); break; } - case ptPlotCoords: + case upLayout: { - if (mKeyAxis && mKeyAxis.data()->orientation() == Qt::Vertical) - x = mKeyAxis.data()->pixelToCoord(y); - else if (mValueAxis && mValueAxis.data()->orientation() == Qt::Vertical) - y = mValueAxis.data()->pixelToCoord(y); - else - qDebug() << Q_FUNC_INFO << "Item position type y is ptPlotCoords, but no axes were defined"; + mInsetLayout->setOuterRect(rect()); break; } + default: break; } - setCoords(x, y); + // pass update call on to inset layout (doesn't happen automatically, because QCPAxisRect doesn't derive from QCPLayout): + mInsetLayout->update(phase); } +/* inherits documentation from base class */ +QList QCPAxisRect::elements(bool recursive) const +{ + QList result; + if (mInsetLayout) + { + result << mInsetLayout; + if (recursive) + result << mInsetLayout->elements(recursive); + } + return result; +} -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPAbstractItem -//////////////////////////////////////////////////////////////////////////////////////////////////// +/* inherits documentation from base class */ +void QCPAxisRect::applyDefaultAntialiasingHint(QCPPainter *painter) const +{ + painter->setAntialiasing(false); +} -/*! \class QCPAbstractItem - \brief The abstract base class for all items in a plot. - - In QCustomPlot, items are supplemental graphical elements that are neither plottables - (QCPAbstractPlottable) nor axes (QCPAxis). While plottables are always tied to two axes and thus - plot coordinates, items can also be placed in absolute coordinates independent of any axes. Each - specific item has at least one QCPItemPosition member which controls the positioning. Some items - are defined by more than one coordinate and thus have two or more QCPItemPosition members (For - example, QCPItemRect has \a topLeft and \a bottomRight). - - This abstract base class defines a very basic interface like visibility and clipping. Since this - class is abstract, it can't be instantiated. Use one of the subclasses or create a subclass - yourself to create new items. - - The built-in items are: - - - - - - - - - - -
QCPItemLineA line defined by a start and an end point. May have different ending styles on each side (e.g. arrows).
QCPItemStraightLineA straight line defined by a start and a direction point. Unlike QCPItemLine, the straight line is infinitely long and has no endings.
QCPItemCurveA curve defined by start, end and two intermediate control points. May have different ending styles on each side (e.g. arrows).
QCPItemRectA rectangle
QCPItemEllipseAn ellipse
QCPItemPixmapAn arbitrary pixmap
QCPItemTextA text label
QCPItemBracketA bracket which may be used to reference/highlight certain parts in the plot.
QCPItemTracerAn item that can be attached to a QCPGraph and sticks to its data points, given a key coordinate.
- - \section items-clipping Clipping +/* inherits documentation from base class */ +void QCPAxisRect::draw(QCPPainter *painter) +{ + drawBackground(painter); +} - Items are by default clipped to the main axis rect (they are only visible inside the axis rect). - To make an item visible outside that axis rect, disable clipping via \ref setClipToAxisRect - "setClipToAxisRect(false)". +/*! + Sets \a pm as the axis background pixmap. The axis background pixmap will be drawn inside the + axis rect. Since axis rects place themselves on the "background" layer by default, the axis rect + backgrounds are usually drawn below everything else. - On the other hand if you want the item to be clipped to a different axis rect, specify it via - \ref setClipAxisRect. This clipAxisRect property of an item is only used for clipping behaviour, and - in principle is independent of the coordinate axes the item might be tied to via its position - members (\ref QCPItemPosition::setAxes). However, it is common that the axis rect for clipping - also contains the axes used for the item positions. - - \section items-using Using items - - First you instantiate the item you want to use and add it to the plot: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpitemline-creation-1 - by default, the positions of the item are bound to the x- and y-Axis of the plot. So we can just - set the plot coordinates where the line should start/end: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpitemline-creation-2 - If we don't want the line to be positioned in plot coordinates but a different coordinate system, - e.g. absolute pixel positions on the QCustomPlot surface, we need to change the position type like this: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpitemline-creation-3 - Then we can set the coordinates, this time in pixels: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpitemline-creation-4 - and make the line visible on the entire QCustomPlot, by disabling clipping to the axis rect: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpitemline-creation-5 - - For more advanced plots, it is even possible to set different types and parent anchors per X/Y - coordinate of an item position, using for example \ref QCPItemPosition::setTypeX or \ref - QCPItemPosition::setParentAnchorX. For details, see the documentation of \ref QCPItemPosition. - - \section items-subclassing Creating own items - - To create an own item, you implement a subclass of QCPAbstractItem. These are the pure - virtual functions, you must implement: - \li \ref selectTest - \li \ref draw + For cases where the provided pixmap doesn't have the same size as the axis rect, scaling can be + enabled with \ref setBackgroundScaled and the scaling mode (i.e. whether and how the aspect ratio + is preserved) can be set with \ref setBackgroundScaledMode. To set all these options in one call, + consider using the overloaded version of this function. + + Below the pixmap, the axis rect may be optionally filled with a brush, if specified with \ref + setBackground(const QBrush &brush). - See the documentation of those functions for what they need to do. + \see setBackgroundScaled, setBackgroundScaledMode, setBackground(const QBrush &brush) +*/ +void QCPAxisRect::setBackground(const QPixmap &pm) +{ + mBackgroundPixmap = pm; + mScaledBackgroundPixmap = QPixmap(); +} + +/*! \overload - \subsection items-positioning Allowing the item to be positioned + Sets \a brush as the background brush. The axis rect background will be filled with this brush. + Since axis rects place themselves on the "background" layer by default, the axis rect backgrounds + are usually drawn below everything else. + + The brush will be drawn before (under) any background pixmap, which may be specified with \ref + setBackground(const QPixmap &pm). + + To disable drawing of a background brush, set \a brush to Qt::NoBrush. - As mentioned, item positions are represented by QCPItemPosition members. Let's assume the new item shall - have only one point as its position (as opposed to two like a rect or multiple like a polygon). You then add - a public member of type QCPItemPosition like so: + \see setBackground(const QPixmap &pm) +*/ +void QCPAxisRect::setBackground(const QBrush &brush) +{ + mBackgroundBrush = brush; +} + +/*! \overload - \code QCPItemPosition * const myPosition;\endcode + Allows setting the background pixmap of the axis rect, whether it shall be scaled and how it + shall be scaled in one call. + + \see setBackground(const QPixmap &pm), setBackgroundScaled, setBackgroundScaledMode +*/ +void QCPAxisRect::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode) +{ + mBackgroundPixmap = pm; + mScaledBackgroundPixmap = QPixmap(); + mBackgroundScaled = scaled; + mBackgroundScaledMode = mode; +} + +/*! + Sets whether the axis background pixmap shall be scaled to fit the axis rect or not. If \a scaled + is set to true, you may control whether and how the aspect ratio of the original pixmap is + preserved with \ref setBackgroundScaledMode. - the const makes sure the pointer itself can't be modified from the user of your new item (the QCPItemPosition - instance it points to, can be modified, of course). - The initialization of this pointer is made easy with the \ref createPosition function. Just assign - the return value of this function to each QCPItemPosition in the constructor of your item. \ref createPosition - takes a string which is the name of the position, typically this is identical to the variable name. - For example, the constructor of QCPItemExample could look like this: + Note that the scaled version of the original pixmap is buffered, so there is no performance + penalty on replots. (Except when the axis rect dimensions are changed continuously.) - \code - QCPItemExample::QCPItemExample(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - myPosition(createPosition("myPosition")) + \see setBackground, setBackgroundScaledMode +*/ +void QCPAxisRect::setBackgroundScaled(bool scaled) +{ + mBackgroundScaled = scaled; +} + +/*! + If scaling of the axis background pixmap is enabled (\ref setBackgroundScaled), use this function to + define whether and how the aspect ratio of the original pixmap passed to \ref setBackground is preserved. + \see setBackground, setBackgroundScaled +*/ +void QCPAxisRect::setBackgroundScaledMode(Qt::AspectRatioMode mode) +{ + mBackgroundScaledMode = mode; +} + +/*! + Returns the range drag axis of the \a orientation provided. If multiple axes were set, returns + the first one (use \ref rangeDragAxes to retrieve a list with all set axes). + + \see setRangeDragAxes +*/ +QCPAxis *QCPAxisRect::rangeDragAxis(Qt::Orientation orientation) +{ + if (orientation == Qt::Horizontal) + return mRangeDragHorzAxis.isEmpty() ? nullptr : mRangeDragHorzAxis.first().data(); + else + return mRangeDragVertAxis.isEmpty() ? nullptr : mRangeDragVertAxis.first().data(); +} + +/*! + Returns the range zoom axis of the \a orientation provided. If multiple axes were set, returns + the first one (use \ref rangeZoomAxes to retrieve a list with all set axes). + + \see setRangeZoomAxes +*/ +QCPAxis *QCPAxisRect::rangeZoomAxis(Qt::Orientation orientation) +{ + if (orientation == Qt::Horizontal) + return mRangeZoomHorzAxis.isEmpty() ? nullptr : mRangeZoomHorzAxis.first().data(); + else + return mRangeZoomVertAxis.isEmpty() ? nullptr : mRangeZoomVertAxis.first().data(); +} + +/*! + Returns all range drag axes of the \a orientation provided. + + \see rangeZoomAxis, setRangeZoomAxes +*/ +QList QCPAxisRect::rangeDragAxes(Qt::Orientation orientation) +{ + QList result; + if (orientation == Qt::Horizontal) { - // other constructor code + foreach (QPointer axis, mRangeDragHorzAxis) + { + if (!axis.isNull()) + result.append(axis.data()); + } + } else + { + foreach (QPointer axis, mRangeDragVertAxis) + { + if (!axis.isNull()) + result.append(axis.data()); + } } - \endcode - - \subsection items-drawing The draw function + return result; +} + +/*! + Returns all range zoom axes of the \a orientation provided. + + \see rangeDragAxis, setRangeDragAxes +*/ +QList QCPAxisRect::rangeZoomAxes(Qt::Orientation orientation) +{ + QList result; + if (orientation == Qt::Horizontal) + { + foreach (QPointer axis, mRangeZoomHorzAxis) + { + if (!axis.isNull()) + result.append(axis.data()); + } + } else + { + foreach (QPointer axis, mRangeZoomVertAxis) + { + if (!axis.isNull()) + result.append(axis.data()); + } + } + return result; +} + +/*! + Returns the range zoom factor of the \a orientation provided. - To give your item a visual representation, reimplement the \ref draw function and use the passed - QCPPainter to draw the item. You can retrieve the item position in pixel coordinates from the - position member(s) via \ref QCPItemPosition::pixelPoint. + \see setRangeZoomFactor +*/ +double QCPAxisRect::rangeZoomFactor(Qt::Orientation orientation) +{ + return (orientation == Qt::Horizontal ? mRangeZoomFactorHorz : mRangeZoomFactorVert); +} - To optimize performance you should calculate a bounding rect first (don't forget to take the pen - width into account), check whether it intersects the \ref clipRect, and only draw the item at all - if this is the case. +/*! + Sets which axis orientation may be range dragged by the user with mouse interaction. + What orientation corresponds to which specific axis can be set with + \ref setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical). By + default, the horizontal axis is the bottom axis (xAxis) and the vertical axis + is the left axis (yAxis). - \subsection items-selection The selectTest function + To disable range dragging entirely, pass \c nullptr as \a orientations or remove \ref + QCP::iRangeDrag from \ref QCustomPlot::setInteractions. To enable range dragging for both + directions, pass Qt::Horizontal | Qt::Vertical as \a orientations. - Your implementation of the \ref selectTest function may use the helpers \ref distSqrToLine and - \ref rectSelectTest. With these, the implementation of the selection test becomes significantly - simpler for most items. See the documentation of \ref selectTest for what the function parameters - mean and what the function should return. + In addition to setting \a orientations to a non-zero value, make sure \ref QCustomPlot::setInteractions + contains \ref QCP::iRangeDrag to enable the range dragging interaction. - \subsection anchors Providing anchors + \see setRangeZoom, setRangeDragAxes, QCustomPlot::setNoAntialiasingOnDrag +*/ +void QCPAxisRect::setRangeDrag(Qt::Orientations orientations) +{ + mRangeDrag = orientations; +} + +/*! + Sets which axis orientation may be zoomed by the user with the mouse wheel. What orientation + corresponds to which specific axis can be set with \ref setRangeZoomAxes(QCPAxis *horizontal, + QCPAxis *vertical). By default, the horizontal axis is the bottom axis (xAxis) and the vertical + axis is the left axis (yAxis). + + To disable range zooming entirely, pass \c nullptr as \a orientations or remove \ref + QCP::iRangeZoom from \ref QCustomPlot::setInteractions. To enable range zooming for both + directions, pass Qt::Horizontal | Qt::Vertical as \a orientations. - Providing anchors (QCPItemAnchor) starts off like adding a position. First you create a public - member, e.g. + In addition to setting \a orientations to a non-zero value, make sure \ref QCustomPlot::setInteractions + contains \ref QCP::iRangeZoom to enable the range zooming interaction. - \code QCPItemAnchor * const bottom;\endcode + \see setRangeZoomFactor, setRangeZoomAxes, setRangeDrag +*/ +void QCPAxisRect::setRangeZoom(Qt::Orientations orientations) +{ + mRangeZoom = orientations; +} - and create it in the constructor with the \ref createAnchor function, assigning it a name and an - anchor id (an integer enumerating all anchors on the item, you may create an own enum for this). - Since anchors can be placed anywhere, relative to the item's position(s), your item needs to - provide the position of every anchor with the reimplementation of the \ref anchorPixelPoint(int - anchorId) function. +/*! \overload - In essence the QCPItemAnchor is merely an intermediary that itself asks your item for the pixel - position when anything attached to the anchor needs to know the coordinates. + Sets the axes whose range will be dragged when \ref setRangeDrag enables mouse range dragging on + the QCustomPlot widget. Pass \c nullptr if no axis shall be dragged in the respective + orientation. + + Use the overload taking a list of axes, if multiple axes (more than one per orientation) shall + react to dragging interactions. + + \see setRangeZoomAxes */ +void QCPAxisRect::setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical) +{ + QList horz, vert; + if (horizontal) + horz.append(horizontal); + if (vertical) + vert.append(vertical); + setRangeDragAxes(horz, vert); +} -/* start of documentation of inline functions */ +/*! \overload -/*! \fn QList QCPAbstractItem::positions() const - - Returns all positions of the item in a list. - - \see anchors, position + This method allows to set up multiple axes to react to horizontal and vertical dragging. The drag + orientation that the respective axis will react to is deduced from its orientation (\ref + QCPAxis::orientation). + + In the unusual case that you wish to e.g. drag a vertically oriented axis with a horizontal drag + motion, use the overload taking two separate lists for horizontal and vertical dragging. */ +void QCPAxisRect::setRangeDragAxes(QList axes) +{ + QList horz, vert; + foreach (QCPAxis *ax, axes) + { + if (ax->orientation() == Qt::Horizontal) + horz.append(ax); + else + vert.append(ax); + } + setRangeDragAxes(horz, vert); +} -/*! \fn QList QCPAbstractItem::anchors() const - - Returns all anchors of the item in a list. Note that since a position (QCPItemPosition) is always - also an anchor, the list will also contain the positions of this item. - - \see positions, anchor +/*! \overload + + This method allows to set multiple axes up to react to horizontal and vertical dragging, and + define specifically which axis reacts to which drag orientation (irrespective of the axis + orientation). */ +void QCPAxisRect::setRangeDragAxes(QList horizontal, QList vertical) +{ + mRangeDragHorzAxis.clear(); + foreach (QCPAxis *ax, horizontal) + { + QPointer axPointer(ax); + if (!axPointer.isNull()) + mRangeDragHorzAxis.append(axPointer); + else + qDebug() << Q_FUNC_INFO << "invalid axis passed in horizontal list:" << reinterpret_cast(ax); + } + mRangeDragVertAxis.clear(); + foreach (QCPAxis *ax, vertical) + { + QPointer axPointer(ax); + if (!axPointer.isNull()) + mRangeDragVertAxis.append(axPointer); + else + qDebug() << Q_FUNC_INFO << "invalid axis passed in vertical list:" << reinterpret_cast(ax); + } +} -/* end of documentation of inline functions */ -/* start documentation of pure virtual functions */ +/*! + Sets the axes whose range will be zoomed when \ref setRangeZoom enables mouse wheel zooming on + the QCustomPlot widget. Pass \c nullptr if no axis shall be zoomed in the respective orientation. -/*! \fn void QCPAbstractItem::draw(QCPPainter *painter) = 0 - \internal - - Draws this item with the provided \a painter. - - The cliprect of the provided painter is set to the rect returned by \ref clipRect before this - function is called. The clipRect depends on the clipping settings defined by \ref - setClipToAxisRect and \ref setClipAxisRect. + The two axes can be zoomed with different strengths, when different factors are passed to \ref + setRangeZoomFactor(double horizontalFactor, double verticalFactor). + + Use the overload taking a list of axes, if multiple axes (more than one per orientation) shall + react to zooming interactions. + + \see setRangeDragAxes */ +void QCPAxisRect::setRangeZoomAxes(QCPAxis *horizontal, QCPAxis *vertical) +{ + QList horz, vert; + if (horizontal) + horz.append(horizontal); + if (vertical) + vert.append(vertical); + setRangeZoomAxes(horz, vert); +} -/* end documentation of pure virtual functions */ -/* start documentation of signals */ +/*! \overload -/*! \fn void QCPAbstractItem::selectionChanged(bool selected) - This signal is emitted when the selection state of this item has changed, either by user interaction - or by a direct call to \ref setSelected. + This method allows to set up multiple axes to react to horizontal and vertical range zooming. The + zoom orientation that the respective axis will react to is deduced from its orientation (\ref + QCPAxis::orientation). + + In the unusual case that you wish to e.g. zoom a vertically oriented axis with a horizontal zoom + interaction, use the overload taking two separate lists for horizontal and vertical zooming. */ +void QCPAxisRect::setRangeZoomAxes(QList axes) +{ + QList horz, vert; + foreach (QCPAxis *ax, axes) + { + if (ax->orientation() == Qt::Horizontal) + horz.append(ax); + else + vert.append(ax); + } + setRangeZoomAxes(horz, vert); +} -/* end documentation of signals */ +/*! \overload + + This method allows to set multiple axes up to react to horizontal and vertical zooming, and + define specifically which axis reacts to which zoom orientation (irrespective of the axis + orientation). +*/ +void QCPAxisRect::setRangeZoomAxes(QList horizontal, QList vertical) +{ + mRangeZoomHorzAxis.clear(); + foreach (QCPAxis *ax, horizontal) + { + QPointer axPointer(ax); + if (!axPointer.isNull()) + mRangeZoomHorzAxis.append(axPointer); + else + qDebug() << Q_FUNC_INFO << "invalid axis passed in horizontal list:" << reinterpret_cast(ax); + } + mRangeZoomVertAxis.clear(); + foreach (QCPAxis *ax, vertical) + { + QPointer axPointer(ax); + if (!axPointer.isNull()) + mRangeZoomVertAxis.append(axPointer); + else + qDebug() << Q_FUNC_INFO << "invalid axis passed in vertical list:" << reinterpret_cast(ax); + } +} /*! - Base class constructor which initializes base class members. + Sets how strong one rotation step of the mouse wheel zooms, when range zoom was activated with + \ref setRangeZoom. The two parameters \a horizontalFactor and \a verticalFactor provide a way to + let the horizontal axis zoom at different rates than the vertical axis. Which axis is horizontal + and which is vertical, can be set with \ref setRangeZoomAxes. + + When the zoom factor is greater than one, scrolling the mouse wheel backwards (towards the user) + will zoom in (make the currently visible range smaller). For zoom factors smaller than one, the + same scrolling direction will zoom out. */ -QCPAbstractItem::QCPAbstractItem(QCustomPlot *parentPlot) : - QCPLayerable(parentPlot), - mClipToAxisRect(false), - mSelectable(true), - mSelected(false) +void QCPAxisRect::setRangeZoomFactor(double horizontalFactor, double verticalFactor) { - QList rects = parentPlot->axisRects(); - if (rects.size() > 0) + mRangeZoomFactorHorz = horizontalFactor; + mRangeZoomFactorVert = verticalFactor; +} + +/*! \overload + + Sets both the horizontal and vertical zoom \a factor. +*/ +void QCPAxisRect::setRangeZoomFactor(double factor) +{ + mRangeZoomFactorHorz = factor; + mRangeZoomFactorVert = factor; +} + +/*! \internal + + Draws the background of this axis rect. It may consist of a background fill (a QBrush) and a + pixmap. + + If a brush was given via \ref setBackground(const QBrush &brush), this function first draws an + according filling inside the axis rect with the provided \a painter. + + Then, if a pixmap was provided via \ref setBackground, this function buffers the scaled version + depending on \ref setBackgroundScaled and \ref setBackgroundScaledMode and then draws it inside + the axis rect with the provided \a painter. The scaled version is buffered in + mScaledBackgroundPixmap to prevent expensive rescaling at every redraw. It is only updated, when + the axis rect has changed in a way that requires a rescale of the background pixmap (this is + dependent on the \ref setBackgroundScaledMode), or when a differend axis background pixmap was + set. + + \see setBackground, setBackgroundScaled, setBackgroundScaledMode +*/ +void QCPAxisRect::drawBackground(QCPPainter *painter) +{ + // draw background fill: + if (mBackgroundBrush != Qt::NoBrush) + painter->fillRect(mRect, mBackgroundBrush); + + // draw background pixmap (on top of fill, if brush specified): + if (!mBackgroundPixmap.isNull()) + { + if (mBackgroundScaled) + { + // check whether mScaledBackground needs to be updated: + QSize scaledSize(mBackgroundPixmap.size()); + scaledSize.scale(mRect.size(), mBackgroundScaledMode); + if (mScaledBackgroundPixmap.size() != scaledSize) + mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mRect.size(), mBackgroundScaledMode, Qt::SmoothTransformation); + painter->drawPixmap(mRect.topLeft()+QPoint(0, -1), mScaledBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()) & mScaledBackgroundPixmap.rect()); + } else + { + painter->drawPixmap(mRect.topLeft()+QPoint(0, -1), mBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height())); + } + } +} + +/*! \internal + + This function makes sure multiple axes on the side specified with \a type don't collide, but are + distributed according to their respective space requirement (QCPAxis::calculateMargin). + + It does this by setting an appropriate offset (\ref QCPAxis::setOffset) on all axes except the + one with index zero. + + This function is called by \ref calculateAutoMargin. +*/ +void QCPAxisRect::updateAxesOffset(QCPAxis::AxisType type) +{ + const QList axesList = mAxes.value(type); + if (axesList.isEmpty()) + return; + + bool isFirstVisible = !axesList.first()->visible(); // if the first axis is visible, the second axis (which is where the loop starts) isn't the first visible axis, so initialize with false + for (int i=1; ioffset() + axesList.at(i-1)->calculateMargin(); + if (axesList.at(i)->visible()) // only add inner tick length to offset if this axis is visible and it's not the first visible one (might happen if true first axis is invisible) + { + if (!isFirstVisible) + offset += axesList.at(i)->tickLengthIn(); + isFirstVisible = false; + } + axesList.at(i)->setOffset(offset); } } -QCPAbstractItem::~QCPAbstractItem() -{ - // don't delete mPositions because every position is also an anchor and thus in mAnchors - qDeleteAll(mAnchors); -} - -/* can't make this a header inline function, because QPointer breaks with forward declared types, see QTBUG-29588 */ -QCPAxisRect *QCPAbstractItem::clipAxisRect() const +/* inherits documentation from base class */ +int QCPAxisRect::calculateAutoMargin(QCP::MarginSide side) { - return mClipAxisRect.data(); + if (!mAutoMargins.testFlag(side)) + qDebug() << Q_FUNC_INFO << "Called with side that isn't specified as auto margin"; + + updateAxesOffset(QCPAxis::marginSideToAxisType(side)); + + // note: only need to look at the last (outer most) axis to determine the total margin, due to updateAxisOffset call + const QList axesList = mAxes.value(QCPAxis::marginSideToAxisType(side)); + if (!axesList.isEmpty()) + return axesList.last()->offset() + axesList.last()->calculateMargin(); + else + return 0; } -/*! - Sets whether the item shall be clipped to an axis rect or whether it shall be visible on the - entire QCustomPlot. The axis rect can be set with \ref setClipAxisRect. +/*! \internal - \see setClipAxisRect + Reacts to a change in layout to potentially set the convenience axis pointers \ref + QCustomPlot::xAxis, \ref QCustomPlot::yAxis, etc. of the parent QCustomPlot to the respective + axes of this axis rect. This is only done if the respective convenience pointer is currently zero + and if there is no QCPAxisRect at position (0, 0) of the plot layout. + + This automation makes it simpler to replace the main axis rect with a newly created one, without + the need to manually reset the convenience pointers. */ -void QCPAbstractItem::setClipToAxisRect(bool clip) +void QCPAxisRect::layoutChanged() { - mClipToAxisRect = clip; - if (mClipToAxisRect) - setParentLayerable(mClipAxisRect.data()); + if (mParentPlot && mParentPlot->axisRectCount() > 0 && mParentPlot->axisRect(0) == this) + { + if (axisCount(QCPAxis::atBottom) > 0 && !mParentPlot->xAxis) + mParentPlot->xAxis = axis(QCPAxis::atBottom); + if (axisCount(QCPAxis::atLeft) > 0 && !mParentPlot->yAxis) + mParentPlot->yAxis = axis(QCPAxis::atLeft); + if (axisCount(QCPAxis::atTop) > 0 && !mParentPlot->xAxis2) + mParentPlot->xAxis2 = axis(QCPAxis::atTop); + if (axisCount(QCPAxis::atRight) > 0 && !mParentPlot->yAxis2) + mParentPlot->yAxis2 = axis(QCPAxis::atRight); + } } -/*! - Sets the clip axis rect. It defines the rect that will be used to clip the item when \ref - setClipToAxisRect is set to true. +/*! \internal - \see setClipToAxisRect + Event handler for when a mouse button is pressed on the axis rect. If the left mouse button is + pressed, the range dragging interaction is initialized (the actual range manipulation happens in + the \ref mouseMoveEvent). + + The mDragging flag is set to true and some anchor points are set that are needed to determine the + distance the mouse was dragged in the mouse move/release events later. + + \see mouseMoveEvent, mouseReleaseEvent */ -void QCPAbstractItem::setClipAxisRect(QCPAxisRect *rect) +void QCPAxisRect::mousePressEvent(QMouseEvent *event, const QVariant &details) { - mClipAxisRect = rect; - if (mClipToAxisRect) - setParentLayerable(mClipAxisRect.data()); + Q_UNUSED(details) + if (event->buttons() & Qt::LeftButton) + { + mDragging = true; + // initialize antialiasing backup in case we start dragging: + if (mParentPlot->noAntialiasingOnDrag()) + { + mAADragBackup = mParentPlot->antialiasedElements(); + mNotAADragBackup = mParentPlot->notAntialiasedElements(); + } + // Mouse range dragging interaction: + if (mParentPlot->interactions().testFlag(QCP::iRangeDrag)) + { + mDragStartHorzRange.clear(); + foreach (QPointer axis, mRangeDragHorzAxis) + mDragStartHorzRange.append(axis.isNull() ? QCPRange() : axis->range()); + mDragStartVertRange.clear(); + foreach (QPointer axis, mRangeDragVertAxis) + mDragStartVertRange.append(axis.isNull() ? QCPRange() : axis->range()); + } + } } -/*! - Sets whether the user can (de-)select this item by clicking on the QCustomPlot surface. - (When \ref QCustomPlot::setInteractions contains QCustomPlot::iSelectItems.) +/*! \internal - However, even when \a selectable was set to false, it is possible to set the selection manually, - by calling \ref setSelected. + Event handler for when the mouse is moved on the axis rect. If range dragging was activated in a + preceding \ref mousePressEvent, the range is moved accordingly. - \see QCustomPlot::setInteractions, setSelected + \see mousePressEvent, mouseReleaseEvent */ -void QCPAbstractItem::setSelectable(bool selectable) +void QCPAxisRect::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) { - if (mSelectable != selectable) + Q_UNUSED(startPos) + // Mouse range dragging interaction: + if (mDragging && mParentPlot->interactions().testFlag(QCP::iRangeDrag)) { - mSelectable = selectable; - emit selectableChanged(mSelectable); + + if (mRangeDrag.testFlag(Qt::Horizontal)) + { + for (int i=0; i= mDragStartHorzRange.size()) + break; + if (ax->mScaleType == QCPAxis::stLinear) + { + double diff = ax->pixelToCoord(startPos.x()) - ax->pixelToCoord(event->pos().x()); + ax->setRange(mDragStartHorzRange.at(i).lower+diff, mDragStartHorzRange.at(i).upper+diff); + } else if (ax->mScaleType == QCPAxis::stLogarithmic) + { + double diff = ax->pixelToCoord(startPos.x()) / ax->pixelToCoord(event->pos().x()); + ax->setRange(mDragStartHorzRange.at(i).lower*diff, mDragStartHorzRange.at(i).upper*diff); + } + } + } + + if (mRangeDrag.testFlag(Qt::Vertical)) + { + for (int i=0; i= mDragStartVertRange.size()) + break; + if (ax->mScaleType == QCPAxis::stLinear) + { + double diff = ax->pixelToCoord(startPos.y()) - ax->pixelToCoord(event->pos().y()); + ax->setRange(mDragStartVertRange.at(i).lower+diff, mDragStartVertRange.at(i).upper+diff); + } else if (ax->mScaleType == QCPAxis::stLogarithmic) + { + double diff = ax->pixelToCoord(startPos.y()) / ax->pixelToCoord(event->pos().y()); + ax->setRange(mDragStartVertRange.at(i).lower*diff, mDragStartVertRange.at(i).upper*diff); + } + } + } + + if (mRangeDrag != 0) // if either vertical or horizontal drag was enabled, do a replot + { + if (mParentPlot->noAntialiasingOnDrag()) + mParentPlot->setNotAntialiasedElements(QCP::aeAll); + mParentPlot->replot(QCustomPlot::rpQueuedReplot); + } + } } -/*! - Sets whether this item is selected or not. When selected, it might use a different visual - appearance (e.g. pen and brush), this depends on the specific item though. +/* inherits documentation from base class */ +void QCPAxisRect::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) +{ + Q_UNUSED(event) + Q_UNUSED(startPos) + mDragging = false; + if (mParentPlot->noAntialiasingOnDrag()) + { + mParentPlot->setAntialiasedElements(mAADragBackup); + mParentPlot->setNotAntialiasedElements(mNotAADragBackup); + } +} - The entire selection mechanism for items is handled automatically when \ref - QCustomPlot::setInteractions contains QCustomPlot::iSelectItems. You only need to call this - function when you wish to change the selection state manually. - - This function can change the selection state even when \ref setSelectable was set to false. +/*! \internal - emits the \ref selectionChanged signal when \a selected is different from the previous selection state. + Event handler for mouse wheel events. If rangeZoom is Qt::Horizontal, Qt::Vertical or both, the + ranges of the axes defined as rangeZoomHorzAxis and rangeZoomVertAxis are scaled. The center of + the scaling operation is the current cursor position inside the axis rect. The scaling factor is + dependent on the mouse wheel delta (which direction the wheel was rotated) to provide a natural + zooming feel. The Strength of the zoom can be controlled via \ref setRangeZoomFactor. - \see setSelectable, selectTest + Note, that event->angleDelta() is usually +/-120 for single rotation steps. However, if the mouse + wheel is turned rapidly, many steps may bunch up to one event, so the delta may then be multiples + of 120. This is taken into account here, by calculating \a wheelSteps and using it as exponent of + the range zoom factor. This takes care of the wheel direction automatically, by inverting the + factor, when the wheel step is negative (f^-1 = 1/f). */ -void QCPAbstractItem::setSelected(bool selected) +void QCPAxisRect::wheelEvent(QWheelEvent *event) { - if (mSelected != selected) +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + const double delta = event->delta(); +#else + const double delta = event->angleDelta().y(); +#endif + +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + const QPointF pos = event->pos(); +#else + const QPointF pos = event->position(); +#endif + + // Mouse range zooming interaction: + if (mParentPlot->interactions().testFlag(QCP::iRangeZoom)) { - mSelected = selected; - emit selectionChanged(mSelected); + if (mRangeZoom != 0) + { + double factor; + double wheelSteps = delta/120.0; // a single step delta is +/-120 usually + if (mRangeZoom.testFlag(Qt::Horizontal)) + { + factor = qPow(mRangeZoomFactorHorz, wheelSteps); + foreach (QPointer axis, mRangeZoomHorzAxis) + { + if (!axis.isNull()) + axis->scaleRange(factor, axis->pixelToCoord(pos.x())); + } + } + if (mRangeZoom.testFlag(Qt::Vertical)) + { + factor = qPow(mRangeZoomFactorVert, wheelSteps); + foreach (QPointer axis, mRangeZoomVertAxis) + { + if (!axis.isNull()) + axis->scaleRange(factor, axis->pixelToCoord(pos.y())); + } + } + mParentPlot->replot(); + } } } +/* end of 'src/layoutelements/layoutelement-axisrect.cpp' */ -/*! - Returns the QCPItemPosition with the specified \a name. If this item doesn't have a position by - that name, returns 0. + +/* including file 'src/layoutelements/layoutelement-legend.cpp' */ +/* modified 2022-11-06T12:45:56, size 31762 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAbstractLegendItem +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPAbstractLegendItem + \brief The abstract base class for all entries in a QCPLegend. - This function provides an alternative way to access item positions. Normally, you access - positions direcly by their member pointers (which typically have the same variable name as \a - name). + It defines a very basic interface for entries in a QCPLegend. For representing plottables in the + legend, the subclass \ref QCPPlottableLegendItem is more suitable. - \see positions, anchor + Only derive directly from this class when you need absolute freedom (e.g. a custom legend entry + that's not even associated with a plottable). + + You must implement the following pure virtual functions: + \li \ref draw (from QCPLayerable) + + You inherit the following members you may use: + + + + + + + + +
QCPLegend *\b mParentLegendA pointer to the parent QCPLegend.
QFont \b mFontThe generic font of the item. You should use this font for all or at least the most prominent text of the item.
*/ -QCPItemPosition *QCPAbstractItem::position(const QString &name) const + +/* start of documentation of signals */ + +/*! \fn void QCPAbstractLegendItem::selectionChanged(bool selected) + + This signal is emitted when the selection state of this legend item has changed, either by user + interaction or by a direct call to \ref setSelected. +*/ + +/* end of documentation of signals */ + +/*! + Constructs a QCPAbstractLegendItem and associates it with the QCPLegend \a parent. This does not + cause the item to be added to \a parent, so \ref QCPLegend::addItem must be called separately. +*/ +QCPAbstractLegendItem::QCPAbstractLegendItem(QCPLegend *parent) : + QCPLayoutElement(parent->parentPlot()), + mParentLegend(parent), + mFont(parent->font()), + mTextColor(parent->textColor()), + mSelectedFont(parent->selectedFont()), + mSelectedTextColor(parent->selectedTextColor()), + mSelectable(true), + mSelected(false) { - for (int i=0; iname() == name) - return mPositions.at(i); - } - qDebug() << Q_FUNC_INFO << "position with name not found:" << name; - return 0; + setLayer(QLatin1String("legend")); + setMargins(QMargins(0, 0, 0, 0)); } /*! - Returns the QCPItemAnchor with the specified \a name. If this item doesn't have an anchor by - that name, returns 0. - - This function provides an alternative way to access item anchors. Normally, you access - anchors direcly by their member pointers (which typically have the same variable name as \a - name). + Sets the default font of this specific legend item to \a font. - \see anchors, position + \see setTextColor, QCPLegend::setFont */ -QCPItemAnchor *QCPAbstractItem::anchor(const QString &name) const +void QCPAbstractLegendItem::setFont(const QFont &font) { - for (int i=0; iname() == name) - return mAnchors.at(i); - } - qDebug() << Q_FUNC_INFO << "anchor with name not found:" << name; - return 0; + mFont = font; } /*! - Returns whether this item has an anchor with the specified \a name. - - Note that you can check for positions with this function, too. This is because every position is - also an anchor (QCPItemPosition inherits from QCPItemAnchor). + Sets the default text color of this specific legend item to \a color. - \see anchor, position + \see setFont, QCPLegend::setTextColor */ -bool QCPAbstractItem::hasAnchor(const QString &name) const +void QCPAbstractLegendItem::setTextColor(const QColor &color) { - for (int i=0; iname() == name) - return true; - } - return false; + mTextColor = color; } -/*! \internal - - Returns the rect the visual representation of this item is clipped to. This depends on the - current setting of \ref setClipToAxisRect as well as the axis rect set with \ref setClipAxisRect. - - If the item is not clipped to an axis rect, the \ref QCustomPlot::viewport rect is returned. +/*! + When this legend item is selected, \a font is used to draw generic text, instead of the normal + font set with \ref setFont. - \see draw + \see setFont, QCPLegend::setSelectedFont */ -QRect QCPAbstractItem::clipRect() const +void QCPAbstractLegendItem::setSelectedFont(const QFont &font) { - if (mClipToAxisRect && mClipAxisRect) - return mClipAxisRect.data()->rect(); - else - return mParentPlot->viewport(); + mSelectedFont = font; } -/*! \internal - - A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter - before drawing item lines. - - This is the antialiasing state the painter passed to the \ref draw method is in by default. - - This function takes into account the local setting of the antialiasing flag as well as the - overrides set with \ref QCustomPlot::setAntialiasedElements and \ref - QCustomPlot::setNotAntialiasedElements. +/*! + When this legend item is selected, \a color is used to draw generic text, instead of the normal + color set with \ref setTextColor. - \see setAntialiased + \see setTextColor, QCPLegend::setSelectedTextColor */ -void QCPAbstractItem::applyDefaultAntialiasingHint(QCPPainter *painter) const +void QCPAbstractLegendItem::setSelectedTextColor(const QColor &color) { - applyAntialiasingHint(painter, mAntialiased, QCP::aeItems); + mSelectedTextColor = color; } -/*! \internal - - Finds the shortest squared distance of \a point to the line segment defined by \a start and \a - end. - - This function may be used to help with the implementation of the \ref selectTest function for - specific items. - - \note This function is identical to QCPAbstractPlottable::distSqrToLine +/*! + Sets whether this specific legend item is selectable. - \see rectSelectTest + \see setSelectedParts, QCustomPlot::setInteractions */ -double QCPAbstractItem::distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const +void QCPAbstractLegendItem::setSelectable(bool selectable) { - QVector2D a(start); - QVector2D b(end); - QVector2D p(point); - QVector2D v(b-a); - - double vLengthSqr = v.lengthSquared(); - if (!qFuzzyIsNull(vLengthSqr)) + if (mSelectable != selectable) { - double mu = QVector2D::dotProduct(p-a, v)/vLengthSqr; - if (mu < 0) - return (a-p).lengthSquared(); - else if (mu > 1) - return (b-p).lengthSquared(); - else - return ((a + mu*v)-p).lengthSquared(); - } else - return (a-p).lengthSquared(); + mSelectable = selectable; + emit selectableChanged(mSelectable); + } } -/*! \internal - - A convenience function which returns the selectTest value for a specified \a rect and a specified - click position \a pos. \a filledRect defines whether a click inside the rect should also be - considered a hit or whether only the rect border is sensitive to hits. - - This function may be used to help with the implementation of the \ref selectTest function for - specific items. +/*! + Sets whether this specific legend item is selected. - For example, if your item consists of four rects, call this function four times, once for each - rect, in your \ref selectTest reimplementation. Finally, return the minimum of all four returned - values. + It is possible to set the selection state of this item by calling this function directly, even if + setSelectable is set to false. - \see distSqrToLine + \see setSelectableParts, QCustomPlot::setInteractions */ -double QCPAbstractItem::rectSelectTest(const QRectF &rect, const QPointF &pos, bool filledRect) const +void QCPAbstractLegendItem::setSelected(bool selected) { - double result = -1; - - // distance to border: - QList lines; - lines << QLineF(rect.topLeft(), rect.topRight()) << QLineF(rect.bottomLeft(), rect.bottomRight()) - << QLineF(rect.topLeft(), rect.bottomLeft()) << QLineF(rect.topRight(), rect.bottomRight()); - double minDistSqr = std::numeric_limits::max(); - for (int i=0; i mParentPlot->selectionTolerance()*0.99) + if (mSelected != selected) { - if (rect.contains(pos)) - result = mParentPlot->selectionTolerance()*0.99; + mSelected = selected; + emit selectionChanged(mSelected); } - return result; } -/*! \internal - - Returns the pixel position of the anchor with Id \a anchorId. This function must be reimplemented in - item subclasses if they want to provide anchors (QCPItemAnchor). - - For example, if the item has two anchors with id 0 and 1, this function takes one of these anchor - ids and returns the respective pixel points of the specified anchor. - - \see createAnchor -*/ -QPointF QCPAbstractItem::anchorPixelPoint(int anchorId) const +/* inherits documentation from base class */ +double QCPAbstractLegendItem::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - qDebug() << Q_FUNC_INFO << "called on item which shouldn't have any anchors (this method not reimplemented). anchorId" << anchorId; - return QPointF(); + Q_UNUSED(details) + if (!mParentPlot) return -1; + if (onlySelectable && (!mSelectable || !mParentLegend->selectableParts().testFlag(QCPLegend::spItems))) + return -1; + + if (mRect.contains(pos.toPoint())) + return mParentPlot->selectionTolerance()*0.99; + else + return -1; } -/*! \internal - - Creates a QCPItemPosition, registers it with this item and returns a pointer to it. The specified - \a name must be a unique string that is usually identical to the variable name of the position - member (This is needed to provide the name-based \ref position access to positions). - - Don't delete positions created by this function manually, as the item will take care of it. - - Use this function in the constructor (initialization list) of the specific item subclass to - create each position member. Don't create QCPItemPositions with \b new yourself, because they - won't be registered with the item properly. - - \see createAnchor -*/ -QCPItemPosition *QCPAbstractItem::createPosition(const QString &name) +/* inherits documentation from base class */ +void QCPAbstractLegendItem::applyDefaultAntialiasingHint(QCPPainter *painter) const { - if (hasAnchor(name)) - qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name; - QCPItemPosition *newPosition = new QCPItemPosition(mParentPlot, this, name); - mPositions.append(newPosition); - mAnchors.append(newPosition); // every position is also an anchor - newPosition->setAxes(mParentPlot->xAxis, mParentPlot->yAxis); - newPosition->setType(QCPItemPosition::ptPlotCoords); - if (mParentPlot->axisRect()) - newPosition->setAxisRect(mParentPlot->axisRect()); - newPosition->setCoords(0, 0); - return newPosition; + applyAntialiasingHint(painter, mAntialiased, QCP::aeLegendItems); } -/*! \internal - - Creates a QCPItemAnchor, registers it with this item and returns a pointer to it. The specified - \a name must be a unique string that is usually identical to the variable name of the anchor - member (This is needed to provide the name based \ref anchor access to anchors). - - The \a anchorId must be a number identifying the created anchor. It is recommended to create an - enum (e.g. "AnchorIndex") for this on each item that uses anchors. This id is used by the anchor - to identify itself when it calls QCPAbstractItem::anchorPixelPoint. That function then returns - the correct pixel coordinates for the passed anchor id. - - Don't delete anchors created by this function manually, as the item will take care of it. - - Use this function in the constructor (initialization list) of the specific item subclass to - create each anchor member. Don't create QCPItemAnchors with \b new yourself, because then they - won't be registered with the item properly. - - \see createPosition -*/ -QCPItemAnchor *QCPAbstractItem::createAnchor(const QString &name, int anchorId) +/* inherits documentation from base class */ +QRect QCPAbstractLegendItem::clipRect() const { - if (hasAnchor(name)) - qDebug() << Q_FUNC_INFO << "anchor/position with name exists already:" << name; - QCPItemAnchor *newAnchor = new QCPItemAnchor(mParentPlot, this, name, anchorId); - mAnchors.append(newAnchor); - return newAnchor; + return mOuterRect; } /* inherits documentation from base class */ -void QCPAbstractItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) +void QCPAbstractLegendItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) { Q_UNUSED(event) Q_UNUSED(details) - if (mSelectable) + if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems)) { bool selBefore = mSelected; setSelected(additive ? !mSelected : true); if (selectionStateChanged) *selectionStateChanged = mSelected != selBefore; } -} - -/* inherits documentation from base class */ -void QCPAbstractItem::deselectEvent(bool *selectionStateChanged) -{ - if (mSelectable) - { - bool selBefore = mSelected; - setSelected(false); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; - } -} - -/* inherits documentation from base class */ -QCP::Interaction QCPAbstractItem::selectionCategory() const -{ - return QCP::iSelectItems; -} - - -/*! \file */ - - - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCustomPlot -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCustomPlot - - \brief The central class of the library. This is the QWidget which displays the plot and - interacts with the user. - - For tutorials on how to use QCustomPlot, see the website\n - http://www.qcustomplot.com/ -*/ - -/* start of documentation of inline functions */ - -/*! \fn QRect QCustomPlot::viewport() const - - Returns the viewport rect of this QCustomPlot instance. The viewport is the area the plot is - drawn in, all mechanisms, e.g. margin caluclation take the viewport to be the outer border of the - plot. The viewport normally is the rect() of the QCustomPlot widget, i.e. a rect with top left - (0, 0) and size of the QCustomPlot widget. - - Don't confuse the viewport with the axis rect (QCustomPlot::axisRect). An axis rect is typically - an area enclosed by four axes, where the graphs/plottables are drawn in. The viewport is larger - and contains also the axes themselves, their tick numbers, their labels, the plot title etc. - - Only when saving to a file (see \ref savePng, \ref savePdf etc.) the viewport is temporarily - modified to allow saving plots with sizes independent of the current widget size. -*/ - -/*! \fn QCPLayoutGrid *QCustomPlot::plotLayout() const - - Returns the top level layout of this QCustomPlot instance. It is a \ref QCPLayoutGrid, initially containing just - one cell with the main QCPAxisRect inside. -*/ - -/* end of documentation of inline functions */ -/* start of documentation of signals */ - -/*! \fn void QCustomPlot::mouseDoubleClick(QMouseEvent *event) - - This signal is emitted when the QCustomPlot receives a mouse double click event. -*/ - -/*! \fn void QCustomPlot::mousePress(QMouseEvent *event) - - This signal is emitted when the QCustomPlot receives a mouse press event. - - It is emitted before QCustomPlot handles any other mechanism like range dragging. So a slot - connected to this signal can still influence the behaviour e.g. with \ref QCPAxisRect::setRangeDrag or \ref - QCPAxisRect::setRangeDragAxes. -*/ - -/*! \fn void QCustomPlot::mouseMove(QMouseEvent *event) +} - This signal is emitted when the QCustomPlot receives a mouse move event. - - It is emitted before QCustomPlot handles any other mechanism like range dragging. So a slot - connected to this signal can still influence the behaviour e.g. with \ref QCPAxisRect::setRangeDrag or \ref - QCPAxisRect::setRangeDragAxes. - - \warning It is discouraged to change the drag-axes with \ref QCPAxisRect::setRangeDragAxes here, - because the dragging starting point was saved the moment the mouse was pressed. Thus it only has - a meaning for the range drag axes that were set at that moment. If you want to change the drag - axes, consider doing this in the \ref mousePress signal instead. -*/ +/* inherits documentation from base class */ +void QCPAbstractLegendItem::deselectEvent(bool *selectionStateChanged) +{ + if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems)) + { + bool selBefore = mSelected; + setSelected(false); + if (selectionStateChanged) + *selectionStateChanged = mSelected != selBefore; + } +} -/*! \fn void QCustomPlot::mouseRelease(QMouseEvent *event) +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPPlottableLegendItem +//////////////////////////////////////////////////////////////////////////////////////////////////// - This signal is emitted when the QCustomPlot receives a mouse release event. +/*! \class QCPPlottableLegendItem + \brief A legend item representing a plottable with an icon and the plottable name. - It is emitted before QCustomPlot handles any other mechanisms like object selection. So a - slot connected to this signal can still influence the behaviour e.g. with \ref setInteractions or - \ref QCPAbstractPlottable::setSelectable. -*/ - -/*! \fn void QCustomPlot::mouseWheel(QMouseEvent *event) + This is the standard legend item for plottables. It displays an icon of the plottable next to the + plottable name. The icon is drawn by the respective plottable itself (\ref + QCPAbstractPlottable::drawLegendIcon), and tries to give an intuitive symbol for the plottable. + For example, the QCPGraph draws a centered horizontal line and/or a single scatter point in the + middle. + + Legend items of this type are always associated with one plottable (retrievable via the + plottable() function and settable with the constructor). You may change the font of the plottable + name with \ref setFont. Icon padding and border pen is taken from the parent QCPLegend, see \ref + QCPLegend::setIconBorderPen and \ref QCPLegend::setIconTextPadding. - This signal is emitted when the QCustomPlot receives a mouse wheel event. + The function \ref QCPAbstractPlottable::addToLegend/\ref QCPAbstractPlottable::removeFromLegend + creates/removes legend items of this type. - It is emitted before QCustomPlot handles any other mechanisms like range zooming. So a slot - connected to this signal can still influence the behaviour e.g. with \ref QCPAxisRect::setRangeZoom, \ref - QCPAxisRect::setRangeZoomAxes or \ref QCPAxisRect::setRangeZoomFactor. + Since QCPLegend is based on QCPLayoutGrid, a legend item itself is just a subclass of + QCPLayoutElement. While it could be added to a legend (or any other layout) via the normal layout + interface, QCPLegend has specialized functions for handling legend items conveniently, see the + documentation of \ref QCPLegend. */ -/*! \fn void QCustomPlot::plottableClick(QCPAbstractPlottable *plottable, QMouseEvent *event) +/*! + Creates a new legend item associated with \a plottable. - This signal is emitted when a plottable is clicked. - - \a event is the mouse event that caused the click and \a plottable is the plottable that received - the click. + Once it's created, it can be added to the legend via \ref QCPLegend::addItem. - \see plottableDoubleClick + A more convenient way of adding/removing a plottable to/from the legend is via the functions \ref + QCPAbstractPlottable::addToLegend and \ref QCPAbstractPlottable::removeFromLegend. */ +QCPPlottableLegendItem::QCPPlottableLegendItem(QCPLegend *parent, QCPAbstractPlottable *plottable) : + QCPAbstractLegendItem(parent), + mPlottable(plottable) +{ + setAntialiased(false); +} -/*! \fn void QCustomPlot::plottableDoubleClick(QCPAbstractPlottable *plottable, QMouseEvent *event) - - This signal is emitted when a plottable is double clicked. - - \a event is the mouse event that caused the click and \a plottable is the plottable that received - the click. +/*! \internal - \see plottableClick + Returns the pen that shall be used to draw the icon border, taking into account the selection + state of this item. */ +QPen QCPPlottableLegendItem::getIconBorderPen() const +{ + return mSelected ? mParentLegend->selectedIconBorderPen() : mParentLegend->iconBorderPen(); +} -/*! \fn void QCustomPlot::itemClick(QCPAbstractItem *item, QMouseEvent *event) +/*! \internal - This signal is emitted when an item is clicked. + Returns the text color that shall be used to draw text, taking into account the selection state + of this item. +*/ +QColor QCPPlottableLegendItem::getTextColor() const +{ + return mSelected ? mSelectedTextColor : mTextColor; +} - \a event is the mouse event that caused the click and \a item is the item that received the - click. +/*! \internal - \see itemDoubleClick + Returns the font that shall be used to draw text, taking into account the selection state of this + item. */ +QFont QCPPlottableLegendItem::getFont() const +{ + return mSelected ? mSelectedFont : mFont; +} -/*! \fn void QCustomPlot::itemDoubleClick(QCPAbstractItem *item, QMouseEvent *event) - - This signal is emitted when an item is double clicked. - - \a event is the mouse event that caused the click and \a item is the item that received the - click. +/*! \internal - \see itemClick + Draws the item with \a painter. The size and position of the drawn legend item is defined by the + parent layout (typically a \ref QCPLegend) and the \ref minimumOuterSizeHint and \ref + maximumOuterSizeHint of this legend item. */ +void QCPPlottableLegendItem::draw(QCPPainter *painter) +{ + if (!mPlottable) return; + painter->setFont(getFont()); + painter->setPen(QPen(getTextColor())); + QSize iconSize = mParentLegend->iconSize(); + QRect textRect = painter->fontMetrics().boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name()); + QRect iconRect(mRect.topLeft(), iconSize); + int textHeight = qMax(textRect.height(), iconSize.height()); // if text has smaller height than icon, center text vertically in icon height, else align tops + painter->drawText(mRect.x()+iconSize.width()+mParentLegend->iconTextPadding(), mRect.y(), textRect.width(), textHeight, Qt::TextDontClip, mPlottable->name()); + // draw icon: + painter->save(); + painter->setClipRect(iconRect, Qt::IntersectClip); + mPlottable->drawLegendIcon(painter, iconRect); + painter->restore(); + // draw icon border: + if (getIconBorderPen().style() != Qt::NoPen) + { + painter->setPen(getIconBorderPen()); + painter->setBrush(Qt::NoBrush); + int halfPen = qCeil(painter->pen().widthF()*0.5)+1; + painter->setClipRect(mOuterRect.adjusted(-halfPen, -halfPen, halfPen, halfPen)); // extend default clip rect so thicker pens (especially during selection) are not clipped + painter->drawRect(iconRect); + } +} -/*! \fn void QCustomPlot::axisClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event) - - This signal is emitted when an axis is clicked. +/*! \internal - \a event is the mouse event that caused the click, \a axis is the axis that received the click and - \a part indicates the part of the axis that was clicked. + Calculates and returns the size of this item. This includes the icon, the text and the padding in + between. - \see axisDoubleClick + \seebaseclassmethod */ +QSize QCPPlottableLegendItem::minimumOuterSizeHint() const +{ + if (!mPlottable) return {}; + QSize result(0, 0); + QRect textRect; + QFontMetrics fontMetrics(getFont()); + QSize iconSize = mParentLegend->iconSize(); + textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name()); + result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width()); + result.setHeight(qMax(textRect.height(), iconSize.height())); + result.rwidth() += mMargins.left()+mMargins.right(); + result.rheight() += mMargins.top()+mMargins.bottom(); + return result; +} -/*! \fn void QCustomPlot::axisDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event) - This signal is emitted when an axis is double clicked. - - \a event is the mouse event that caused the click, \a axis is the axis that received the click and - \a part indicates the part of the axis that was clicked. - - \see axisClick -*/ +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPLegend +//////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \fn void QCustomPlot::legendClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event) +/*! \class QCPLegend + \brief Manages a legend inside a QCustomPlot. - This signal is emitted when a legend (item) is clicked. - - \a event is the mouse event that caused the click, \a legend is the legend that received the - click and \a item is the legend item that received the click. If only the legend and no item is - clicked, \a item is 0. This happens for a click inside the legend padding or the space between - two items. - - \see legendDoubleClick -*/ + A legend is a small box somewhere in the plot which lists plottables with their name and icon. -/*! \fn void QCustomPlot::legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event) + A legend is populated with legend items by calling \ref QCPAbstractPlottable::addToLegend on the + plottable, for which a legend item shall be created. In the case of the main legend (\ref + QCustomPlot::legend), simply adding plottables to the plot while \ref + QCustomPlot::setAutoAddPlottableToLegend is set to true (the default) creates corresponding + legend items. The legend item associated with a certain plottable can be removed with \ref + QCPAbstractPlottable::removeFromLegend. However, QCPLegend also offers an interface to add and + manipulate legend items directly: \ref item, \ref itemWithPlottable, \ref itemCount, \ref + addItem, \ref removeItem, etc. + + Since \ref QCPLegend derives from \ref QCPLayoutGrid, it can be placed in any position a \ref + QCPLayoutElement may be positioned. The legend items are themselves \ref QCPLayoutElement + "QCPLayoutElements" which are placed in the grid layout of the legend. \ref QCPLegend only adds + an interface specialized for handling child elements of type \ref QCPAbstractLegendItem, as + mentioned above. In principle, any other layout elements may also be added to a legend via the + normal \ref QCPLayoutGrid interface. See the special page about \link thelayoutsystem The Layout + System\endlink for examples on how to add other elements to the legend and move it outside the axis + rect. - This signal is emitted when a legend (item) is double clicked. - - \a event is the mouse event that caused the click, \a legend is the legend that received the - click and \a item is the legend item that received the click. If only the legend and no item is - clicked, \a item is 0. This happens for a click inside the legend padding or the space between - two items. - - \see legendClick + Use the methods \ref setFillOrder and \ref setWrap inherited from \ref QCPLayoutGrid to control + in which order (column first or row first) the legend is filled up when calling \ref addItem, and + at which column or row wrapping occurs. The default fill order for legends is \ref foRowsFirst. + + By default, every QCustomPlot has one legend (\ref QCustomPlot::legend) which is placed in the + inset layout of the main axis rect (\ref QCPAxisRect::insetLayout). To move the legend to another + position inside the axis rect, use the methods of the \ref QCPLayoutInset. To move the legend + outside of the axis rect, place it anywhere else with the \ref QCPLayout/\ref QCPLayoutElement + interface. */ -/*! \fn void QCustomPlot:: titleClick(QMouseEvent *event, QCPPlotTitle *title) +/* start of documentation of signals */ - This signal is emitted when a plot title is clicked. - - \a event is the mouse event that caused the click and \a title is the plot title that received - the click. +/*! \fn void QCPLegend::selectionChanged(QCPLegend::SelectableParts selection); + + This signal is emitted when the selection state of this legend has changed. - \see titleDoubleClick + \see setSelectedParts, setSelectableParts */ -/*! \fn void QCustomPlot::titleDoubleClick(QMouseEvent *event, QCPPlotTitle *title) +/* end of documentation of signals */ - This signal is emitted when a plot title is double clicked. - - \a event is the mouse event that caused the click and \a title is the plot title that received - the click. +/*! + Constructs a new QCPLegend instance with default values. - \see titleClick + Note that by default, QCustomPlot already contains a legend ready to be used as \ref + QCustomPlot::legend */ - -/*! \fn void QCustomPlot::selectionChangedByUser() +QCPLegend::QCPLegend() : + mIconTextPadding{} +{ + setFillOrder(QCPLayoutGrid::foRowsFirst); + setWrap(0); - This signal is emitted after the user has changed the selection in the QCustomPlot, e.g. by - clicking. It is not emitted when the selection state of an object has changed programmatically by - a direct call to setSelected() on an object or by calling \ref deselectAll. + setRowSpacing(3); + setColumnSpacing(8); + setMargins(QMargins(7, 5, 7, 4)); + setAntialiased(false); + setIconSize(32, 18); - In addition to this signal, selectable objects also provide individual signals, for example - QCPAxis::selectionChanged or QCPAbstractPlottable::selectionChanged. Note that those signals are - emitted even if the selection state is changed programmatically. + setIconTextPadding(7); - See the documentation of \ref setInteractions for details about the selection mechanism. + setSelectableParts(spLegendBox | spItems); + setSelectedParts(spNone); - \see selectedPlottables, selectedGraphs, selectedItems, selectedAxes, selectedLegends + setBorderPen(QPen(Qt::black, 0)); + setSelectedBorderPen(QPen(Qt::blue, 2)); + setIconBorderPen(Qt::NoPen); + setSelectedIconBorderPen(QPen(Qt::blue, 2)); + setBrush(Qt::white); + setSelectedBrush(Qt::white); + setTextColor(Qt::black); + setSelectedTextColor(Qt::blue); +} + +QCPLegend::~QCPLegend() +{ + clearItems(); + if (qobject_cast(mParentPlot)) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the legend is not in any layout and thus QObject-child of QCustomPlot) + mParentPlot->legendRemoved(this); +} + +/* no doc for getter, see setSelectedParts */ +QCPLegend::SelectableParts QCPLegend::selectedParts() const +{ + // check whether any legend elements selected, if yes, add spItems to return value + bool hasSelectedItems = false; + for (int i=0; iselected()) + { + hasSelectedItems = true; + break; + } + } + if (hasSelectedItems) + return mSelectedParts | spItems; + else + return mSelectedParts & ~spItems; +} + +/*! + Sets the pen, the border of the entire legend is drawn with. */ +void QCPLegend::setBorderPen(const QPen &pen) +{ + mBorderPen = pen; +} -/*! \fn void QCustomPlot::beforeReplot() - - This signal is emitted immediately before a replot takes place (caused by a call to the slot \ref - replot). +/*! + Sets the brush of the legend background. +*/ +void QCPLegend::setBrush(const QBrush &brush) +{ + mBrush = brush; +} + +/*! + Sets the default font of legend text. Legend items that draw text (e.g. the name of a graph) will + use this font by default. However, a different font can be specified on a per-item-basis by + accessing the specific legend item. - It is safe to mutually connect the replot slot with this signal on two QCustomPlots to make them - replot synchronously, it won't cause an infinite recursion. + This function will also set \a font on all already existing legend items. - \see replot, afterReplot + \see QCPAbstractLegendItem::setFont */ +void QCPLegend::setFont(const QFont &font) +{ + mFont = font; + for (int i=0; isetFont(mFont); + } +} -/*! \fn void QCustomPlot::afterReplot() - - This signal is emitted immediately after a replot has taken place (caused by a call to the slot \ref - replot). +/*! + Sets the default color of legend text. Legend items that draw text (e.g. the name of a graph) + will use this color by default. However, a different colors can be specified on a per-item-basis + by accessing the specific legend item. - It is safe to mutually connect the replot slot with this signal on two QCustomPlots to make them - replot synchronously, it won't cause an infinite recursion. + This function will also set \a color on all already existing legend items. - \see replot, beforeReplot + \see QCPAbstractLegendItem::setTextColor */ +void QCPLegend::setTextColor(const QColor &color) +{ + mTextColor = color; + for (int i=0; isetTextColor(color); + } +} -/* end of documentation of signals */ -/* start of documentation of public members */ - -/*! \var QCPAxis *QCustomPlot::xAxis - - A pointer to the primary x Axis (bottom) of the main axis rect of the plot. - - QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref - yAxis2) and the \ref legend. They make it very easy working with plots that only have a single - axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the - layout system\endlink to add multiple axis rects or multiple axes to one side, use the \ref - QCPAxisRect::axis interface to access the new axes. If one of the four default axes or the - default legend is removed due to manipulation of the layout system (e.g. by removing the main - axis rect), the corresponding pointers become 0. +/*! + Sets the size of legend icons. Legend items that draw an icon (e.g. a visual + representation of the graph) will use this size by default. */ +void QCPLegend::setIconSize(const QSize &size) +{ + mIconSize = size; +} -/*! \var QCPAxis *QCustomPlot::yAxis - - A pointer to the primary y Axis (left) of the main axis rect of the plot. - - QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref - yAxis2) and the \ref legend. They make it very easy working with plots that only have a single - axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the - layout system\endlink to add multiple axis rects or multiple axes to one side, use the \ref - QCPAxisRect::axis interface to access the new axes. If one of the four default axes or the - default legend is removed due to manipulation of the layout system (e.g. by removing the main - axis rect), the corresponding pointers become 0. +/*! \overload */ +void QCPLegend::setIconSize(int width, int height) +{ + mIconSize.setWidth(width); + mIconSize.setHeight(height); +} -/*! \var QCPAxis *QCustomPlot::xAxis2 - - A pointer to the secondary x Axis (top) of the main axis rect of the plot. Secondary axes are - invisible by default. Use QCPAxis::setVisible to change this (or use \ref - QCPAxisRect::setupFullAxesBox). - - QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref - yAxis2) and the \ref legend. They make it very easy working with plots that only have a single - axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the - layout system\endlink to add multiple axis rects or multiple axes to one side, use the \ref - QCPAxisRect::axis interface to access the new axes. If one of the four default axes or the - default legend is removed due to manipulation of the layout system (e.g. by removing the main - axis rect), the corresponding pointers become 0. +/*! + Sets the horizontal space in pixels between the legend icon and the text next to it. + Legend items that draw an icon (e.g. a visual representation of the graph) and text (e.g. the + name of the graph) will use this space by default. */ +void QCPLegend::setIconTextPadding(int padding) +{ + mIconTextPadding = padding; +} -/*! \var QCPAxis *QCustomPlot::yAxis2 - - A pointer to the secondary y Axis (right) of the main axis rect of the plot. Secondary axes are - invisible by default. Use QCPAxis::setVisible to change this (or use \ref - QCPAxisRect::setupFullAxesBox). +/*! + Sets the pen used to draw a border around each legend icon. Legend items that draw an + icon (e.g. a visual representation of the graph) will use this pen by default. - QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref - yAxis2) and the \ref legend. They make it very easy working with plots that only have a single - axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the - layout system\endlink to add multiple axis rects or multiple axes to one side, use the \ref - QCPAxisRect::axis interface to access the new axes. If one of the four default axes or the - default legend is removed due to manipulation of the layout system (e.g. by removing the main - axis rect), the corresponding pointers become 0. + If no border is wanted, set this to \a Qt::NoPen. */ +void QCPLegend::setIconBorderPen(const QPen &pen) +{ + mIconBorderPen = pen; +} -/*! \var QCPLegend *QCustomPlot::legend - - A pointer to the default legend of the main axis rect. The legend is invisible by default. Use - QCPLegend::setVisible to change this. +/*! + Sets whether the user can (de-)select the parts in \a selectable by clicking on the QCustomPlot surface. + (When \ref QCustomPlot::setInteractions contains \ref QCP::iSelectLegend.) - QCustomPlot offers convenient pointers to the axes (\ref xAxis, \ref yAxis, \ref xAxis2, \ref - yAxis2) and the \ref legend. They make it very easy working with plots that only have a single - axis rect and at most one axis at each axis rect side. If you use \link thelayoutsystem the - layout system\endlink to add multiple legends to the plot, use the layout system interface to - access the new legend. For example, legends can be placed inside an axis rect's \ref - QCPAxisRect::insetLayout "inset layout", and must then also be accessed via the inset layout. If - the default legend is removed due to manipulation of the layout system (e.g. by removing the main - axis rect), the corresponding pointer becomes 0. + However, even when \a selectable is set to a value not allowing the selection of a specific part, + it is still possible to set the selection of this part manually, by calling \ref setSelectedParts + directly. + + \see SelectablePart, setSelectedParts */ - -/* end of documentation of public members */ +void QCPLegend::setSelectableParts(const SelectableParts &selectable) +{ + if (mSelectableParts != selectable) + { + mSelectableParts = selectable; + emit selectableChanged(mSelectableParts); + } +} /*! - Constructs a QCustomPlot and sets reasonable default values. -*/ -QCustomPlot::QCustomPlot(QWidget *parent) : - QWidget(parent), - xAxis(0), - yAxis(0), - xAxis2(0), - yAxis2(0), - legend(0), - mPlotLayout(0), - mAutoAddPlottableToLegend(true), - mAntialiasedElements(QCP::aeNone), - mNotAntialiasedElements(QCP::aeNone), - mInteractions(0), - mSelectionTolerance(8), - mNoAntialiasingOnDrag(false), - mBackgroundBrush(Qt::white, Qt::SolidPattern), - mBackgroundScaled(true), - mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding), - mCurrentLayer(0), - mPlottingHints(QCP::phCacheLabels|QCP::phForceRepaint), - mMultiSelectModifier(Qt::ControlModifier), - mPaintBuffer(size()), - mMouseEventElement(0), - mReplotting(false) -{ - setAttribute(Qt::WA_NoMousePropagation); - setAttribute(Qt::WA_OpaquePaintEvent); - setMouseTracking(true); - QLocale currentLocale = locale(); - currentLocale.setNumberOptions(QLocale::OmitGroupSeparator); - setLocale(currentLocale); + Sets the selected state of the respective legend parts described by \ref SelectablePart. When a part + is selected, it uses a different pen/font and brush. If some legend items are selected and \a selected + doesn't contain \ref spItems, those items become deselected. - // create initial layers: - mLayers.append(new QCPLayer(this, QLatin1String("background"))); - mLayers.append(new QCPLayer(this, QLatin1String("grid"))); - mLayers.append(new QCPLayer(this, QLatin1String("main"))); - mLayers.append(new QCPLayer(this, QLatin1String("axes"))); - mLayers.append(new QCPLayer(this, QLatin1String("legend"))); - updateLayerIndices(); - setCurrentLayer(QLatin1String("main")); + The entire selection mechanism is handled automatically when \ref QCustomPlot::setInteractions + contains iSelectLegend. You only need to call this function when you wish to change the selection + state manually. - // create initial layout, axis rect and legend: - mPlotLayout = new QCPLayoutGrid; - mPlotLayout->initializeParentPlot(this); - mPlotLayout->setParent(this); // important because if parent is QWidget, QCPLayout::sizeConstraintsChanged will call QWidget::updateGeometry - mPlotLayout->setLayer(QLatin1String("main")); - QCPAxisRect *defaultAxisRect = new QCPAxisRect(this, true); - mPlotLayout->addElement(0, 0, defaultAxisRect); - xAxis = defaultAxisRect->axis(QCPAxis::atBottom); - yAxis = defaultAxisRect->axis(QCPAxis::atLeft); - xAxis2 = defaultAxisRect->axis(QCPAxis::atTop); - yAxis2 = defaultAxisRect->axis(QCPAxis::atRight); - legend = new QCPLegend; - legend->setVisible(false); - defaultAxisRect->insetLayout()->addElement(legend, Qt::AlignRight|Qt::AlignTop); - defaultAxisRect->insetLayout()->setMargins(QMargins(12, 12, 12, 12)); + This function can change the selection state of a part even when \ref setSelectableParts was set to a + value that actually excludes the part. - defaultAxisRect->setLayer(QLatin1String("background")); - xAxis->setLayer(QLatin1String("axes")); - yAxis->setLayer(QLatin1String("axes")); - xAxis2->setLayer(QLatin1String("axes")); - yAxis2->setLayer(QLatin1String("axes")); - xAxis->grid()->setLayer(QLatin1String("grid")); - yAxis->grid()->setLayer(QLatin1String("grid")); - xAxis2->grid()->setLayer(QLatin1String("grid")); - yAxis2->grid()->setLayer(QLatin1String("grid")); - legend->setLayer(QLatin1String("legend")); + emits the \ref selectionChanged signal when \a selected is different from the previous selection state. - setViewport(rect()); // needs to be called after mPlotLayout has been created + Note that it doesn't make sense to set the selected state \ref spItems here when it wasn't set + before, because there's no way to specify which exact items to newly select. Do this by calling + \ref QCPAbstractLegendItem::setSelected directly on the legend item you wish to select. - replot(); -} - -QCustomPlot::~QCustomPlot() + \see SelectablePart, setSelectableParts, selectTest, setSelectedBorderPen, setSelectedIconBorderPen, setSelectedBrush, + setSelectedFont +*/ +void QCPLegend::setSelectedParts(const SelectableParts &selected) { - clearPlottables(); - clearItems(); + SelectableParts newSelected = selected; + mSelectedParts = this->selectedParts(); // update mSelectedParts in case item selection changed - if (mPlotLayout) + if (mSelectedParts != newSelected) { - delete mPlotLayout; - mPlotLayout = 0; + if (!mSelectedParts.testFlag(spItems) && newSelected.testFlag(spItems)) // attempt to set spItems flag (can't do that) + { + qDebug() << Q_FUNC_INFO << "spItems flag can not be set, it can only be unset with this function"; + newSelected &= ~spItems; + } + if (mSelectedParts.testFlag(spItems) && !newSelected.testFlag(spItems)) // spItems flag was unset, so clear item selection + { + for (int i=0; isetSelected(false); + } + } + mSelectedParts = newSelected; + emit selectionChanged(mSelectedParts); } - - mCurrentLayer = 0; - qDeleteAll(mLayers); // don't use removeLayer, because it would prevent the last layer to be removed - mLayers.clear(); } /*! - Sets which elements are forcibly drawn antialiased as an \a or combination of QCP::AntialiasedElement. - - This overrides the antialiasing settings for whole element groups, normally controlled with the - \a setAntialiasing function on the individual elements. If an element is neither specified in - \ref setAntialiasedElements nor in \ref setNotAntialiasedElements, the antialiasing setting on - each individual element instance is used. - - For example, if \a antialiasedElements contains \ref QCP::aePlottables, all plottables will be - drawn antialiased, no matter what the specific QCPAbstractPlottable::setAntialiased value was set - to. - - if an element in \a antialiasedElements is already set in \ref setNotAntialiasedElements, it is - removed from there. - - \see setNotAntialiasedElements + When the legend box is selected, this pen is used to draw the border instead of the normal pen + set via \ref setBorderPen. + + \see setSelectedParts, setSelectableParts, setSelectedBrush */ -void QCustomPlot::setAntialiasedElements(const QCP::AntialiasedElements &antialiasedElements) +void QCPLegend::setSelectedBorderPen(const QPen &pen) { - mAntialiasedElements = antialiasedElements; - - // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: - if ((mNotAntialiasedElements & mAntialiasedElements) != 0) - mNotAntialiasedElements |= ~mAntialiasedElements; + mSelectedBorderPen = pen; } /*! - Sets whether the specified \a antialiasedElement is forcibly drawn antialiased. - - See \ref setAntialiasedElements for details. - - \see setNotAntialiasedElement + Sets the pen legend items will use to draw their icon borders, when they are selected. + + \see setSelectedParts, setSelectableParts, setSelectedFont */ -void QCustomPlot::setAntialiasedElement(QCP::AntialiasedElement antialiasedElement, bool enabled) +void QCPLegend::setSelectedIconBorderPen(const QPen &pen) { - if (!enabled && mAntialiasedElements.testFlag(antialiasedElement)) - mAntialiasedElements &= ~antialiasedElement; - else if (enabled && !mAntialiasedElements.testFlag(antialiasedElement)) - mAntialiasedElements |= antialiasedElement; - - // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: - if ((mNotAntialiasedElements & mAntialiasedElements) != 0) - mNotAntialiasedElements |= ~mAntialiasedElements; + mSelectedIconBorderPen = pen; } /*! - Sets which elements are forcibly drawn not antialiased as an \a or combination of - QCP::AntialiasedElement. - - This overrides the antialiasing settings for whole element groups, normally controlled with the - \a setAntialiasing function on the individual elements. If an element is neither specified in - \ref setAntialiasedElements nor in \ref setNotAntialiasedElements, the antialiasing setting on - each individual element instance is used. - - For example, if \a notAntialiasedElements contains \ref QCP::aePlottables, no plottables will be - drawn antialiased, no matter what the specific QCPAbstractPlottable::setAntialiased value was set - to. - - if an element in \a notAntialiasedElements is already set in \ref setAntialiasedElements, it is - removed from there. - - \see setAntialiasedElements + When the legend box is selected, this brush is used to draw the legend background instead of the normal brush + set via \ref setBrush. + + \see setSelectedParts, setSelectableParts, setSelectedBorderPen */ -void QCustomPlot::setNotAntialiasedElements(const QCP::AntialiasedElements ¬AntialiasedElements) +void QCPLegend::setSelectedBrush(const QBrush &brush) { - mNotAntialiasedElements = notAntialiasedElements; - - // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: - if ((mNotAntialiasedElements & mAntialiasedElements) != 0) - mAntialiasedElements |= ~mNotAntialiasedElements; + mSelectedBrush = brush; } /*! - Sets whether the specified \a notAntialiasedElement is forcibly drawn not antialiased. - - See \ref setNotAntialiasedElements for details. + Sets the default font that is used by legend items when they are selected. - \see setAntialiasedElement + This function will also set \a font on all already existing legend items. + + \see setFont, QCPAbstractLegendItem::setSelectedFont */ -void QCustomPlot::setNotAntialiasedElement(QCP::AntialiasedElement notAntialiasedElement, bool enabled) +void QCPLegend::setSelectedFont(const QFont &font) { - if (!enabled && mNotAntialiasedElements.testFlag(notAntialiasedElement)) - mNotAntialiasedElements &= ~notAntialiasedElement; - else if (enabled && !mNotAntialiasedElements.testFlag(notAntialiasedElement)) - mNotAntialiasedElements |= notAntialiasedElement; - - // make sure elements aren't in mNotAntialiasedElements and mAntialiasedElements simultaneously: - if ((mNotAntialiasedElements & mAntialiasedElements) != 0) - mAntialiasedElements |= ~mNotAntialiasedElements; + mSelectedFont = font; + for (int i=0; isetSelectedFont(font); + } } /*! - If set to true, adding a plottable (e.g. a graph) to the QCustomPlot automatically also adds the - plottable to the legend (QCustomPlot::legend). + Sets the default text color that is used by legend items when they are selected. - \see addPlottable, addGraph, QCPLegend::addItem + This function will also set \a color on all already existing legend items. + + \see setTextColor, QCPAbstractLegendItem::setSelectedTextColor */ -void QCustomPlot::setAutoAddPlottableToLegend(bool on) +void QCPLegend::setSelectedTextColor(const QColor &color) { - mAutoAddPlottableToLegend = on; + mSelectedTextColor = color; + for (int i=0; isetSelectedTextColor(color); + } } /*! - Sets the possible interactions of this QCustomPlot as an or-combination of \ref QCP::Interaction - enums. There are the following types of interactions: - - Axis range manipulation is controlled via \ref QCP::iRangeDrag and \ref QCP::iRangeZoom. When the - respective interaction is enabled, the user may drag axes ranges and zoom with the mouse wheel. - For details how to control which axes the user may drag/zoom and in what orientations, see \ref - QCPAxisRect::setRangeDrag, \ref QCPAxisRect::setRangeZoom, \ref QCPAxisRect::setRangeDragAxes, - \ref QCPAxisRect::setRangeZoomAxes. - - Plottable selection is controlled by \ref QCP::iSelectPlottables. If \ref QCP::iSelectPlottables is - set, the user may select plottables (graphs, curves, bars,...) by clicking on them or in their - vicinity (\ref setSelectionTolerance). Whether the user can actually select a plottable can - further be restricted with the \ref QCPAbstractPlottable::setSelectable function on the specific - plottable. To find out whether a specific plottable is selected, call - QCPAbstractPlottable::selected(). To retrieve a list of all currently selected plottables, call - \ref selectedPlottables. If you're only interested in QCPGraphs, you may use the convenience - function \ref selectedGraphs. - - Item selection is controlled by \ref QCP::iSelectItems. If \ref QCP::iSelectItems is set, the user - may select items (QCPItemLine, QCPItemText,...) by clicking on them or in their vicinity. To find - out whether a specific item is selected, call QCPAbstractItem::selected(). To retrieve a list of - all currently selected items, call \ref selectedItems. - - Axis selection is controlled with \ref QCP::iSelectAxes. If \ref QCP::iSelectAxes is set, the user - may select parts of the axes by clicking on them. What parts exactly (e.g. Axis base line, tick - labels, axis label) are selectable can be controlled via \ref QCPAxis::setSelectableParts for - each axis. To retrieve a list of all axes that currently contain selected parts, call \ref - selectedAxes. Which parts of an axis are selected, can be retrieved with QCPAxis::selectedParts(). - - Legend selection is controlled with \ref QCP::iSelectLegend. If this is set, the user may - select the legend itself or individual items by clicking on them. What parts exactly are - selectable can be controlled via \ref QCPLegend::setSelectableParts. To find out whether the - legend or any of its child items are selected, check the value of QCPLegend::selectedParts. To - find out which child items are selected, call \ref QCPLegend::selectedItems. - - All other selectable elements The selection of all other selectable objects (e.g. - QCPPlotTitle, or your own layerable subclasses) is controlled with \ref QCP::iSelectOther. If set, the - user may select those objects by clicking on them. To find out which are currently selected, you - need to check their selected state explicitly. - - If the selection state has changed by user interaction, the \ref selectionChangedByUser signal is - emitted. Each selectable object additionally emits an individual selectionChanged signal whenever - their selection state has changed, i.e. not only by user interaction. - - To allow multiple objects to be selected by holding the selection modifier (\ref - setMultiSelectModifier), set the flag \ref QCP::iMultiSelect. - - \note In addition to the selection mechanism presented here, QCustomPlot always emits - corresponding signals, when an object is clicked or double clicked. see \ref plottableClick and - \ref plottableDoubleClick for example. - - \see setInteraction, setSelectionTolerance + Returns the item with index \a i. If non-legend items were added to the legend, and the element + at the specified cell index is not a QCPAbstractLegendItem, returns \c nullptr. + + Note that the linear index depends on the current fill order (\ref setFillOrder). + + \see itemCount, addItem, itemWithPlottable */ -void QCustomPlot::setInteractions(const QCP::Interactions &interactions) +QCPAbstractLegendItem *QCPLegend::item(int index) const { - mInteractions = interactions; + return qobject_cast(elementAt(index)); } /*! - Sets the single \a interaction of this QCustomPlot to \a enabled. - - For details about the interaction system, see \ref setInteractions. + Returns the QCPPlottableLegendItem which is associated with \a plottable (e.g. a \ref QCPGraph*). + If such an item isn't in the legend, returns \c nullptr. - \see setInteractions + \see hasItemWithPlottable */ -void QCustomPlot::setInteraction(const QCP::Interaction &interaction, bool enabled) +QCPPlottableLegendItem *QCPLegend::itemWithPlottable(const QCPAbstractPlottable *plottable) const { - if (!enabled && mInteractions.testFlag(interaction)) - mInteractions &= ~interaction; - else if (enabled && !mInteractions.testFlag(interaction)) - mInteractions |= interaction; + for (int i=0; i(item(i))) + { + if (pli->plottable() == plottable) + return pli; + } + } + return nullptr; } /*! - Sets the tolerance that is used to decide whether a click selects an object (e.g. a plottable) or - not. - - If the user clicks in the vicinity of the line of e.g. a QCPGraph, it's only regarded as a - potential selection when the minimum distance between the click position and the graph line is - smaller than \a pixels. Objects that are defined by an area (e.g. QCPBars) only react to clicks - directly inside the area and ignore this selection tolerance. In other words, it only has meaning - for parts of objects that are too thin to exactly hit with a click and thus need such a - tolerance. - - \see setInteractions, QCPLayerable::selectTest + Returns the number of items currently in the legend. It is identical to the base class + QCPLayoutGrid::elementCount(), and unlike the other "item" interface methods of QCPLegend, + doesn't only address elements which can be cast to QCPAbstractLegendItem. + + Note that if empty cells are in the legend (e.g. by calling methods of the \ref QCPLayoutGrid + base class which allows creating empty cells), they are included in the returned count. + + \see item */ -void QCustomPlot::setSelectionTolerance(int pixels) +int QCPLegend::itemCount() const { - mSelectionTolerance = pixels; + return elementCount(); } /*! - Sets whether antialiasing is disabled for this QCustomPlot while the user is dragging axes - ranges. If many objects, especially plottables, are drawn antialiased, this greatly improves - performance during dragging. Thus it creates a more responsive user experience. As soon as the - user stops dragging, the last replot is done with normal antialiasing, to restore high image - quality. + Returns whether the legend contains \a item. - \see setAntialiasedElements, setNotAntialiasedElements + \see hasItemWithPlottable */ -void QCustomPlot::setNoAntialiasingOnDrag(bool enabled) +bool QCPLegend::hasItem(QCPAbstractLegendItem *item) const { - mNoAntialiasingOnDrag = enabled; + for (int i=0; iitem(i)) + return true; + } + return false; } /*! - Sets the plotting hints for this QCustomPlot instance as an \a or combination of QCP::PlottingHint. + Returns whether the legend contains a QCPPlottableLegendItem which is associated with \a plottable (e.g. a \ref QCPGraph*). + If such an item isn't in the legend, returns false. - \see setPlottingHint + \see itemWithPlottable */ -void QCustomPlot::setPlottingHints(const QCP::PlottingHints &hints) +bool QCPLegend::hasItemWithPlottable(const QCPAbstractPlottable *plottable) const { - mPlottingHints = hints; + return itemWithPlottable(plottable); } /*! - Sets the specified plotting \a hint to \a enabled. - - \see setPlottingHints + Adds \a item to the legend, if it's not present already. The element is arranged according to the + current fill order (\ref setFillOrder) and wrapping (\ref setWrap). + + Returns true on sucess, i.e. if the item wasn't in the list already and has been successfuly added. + + The legend takes ownership of the item. + + \see removeItem, item, hasItem */ -void QCustomPlot::setPlottingHint(QCP::PlottingHint hint, bool enabled) +bool QCPLegend::addItem(QCPAbstractLegendItem *item) { - QCP::PlottingHints newHints = mPlottingHints; - if (!enabled) - newHints &= ~hint; - else - newHints |= hint; - - if (newHints != mPlottingHints) - setPlottingHints(newHints); + return addElement(item); } -/*! - Sets the keyboard modifier that will be recognized as multi-select-modifier. - - If \ref QCP::iMultiSelect is specified in \ref setInteractions, the user may select multiple objects - by clicking on them one after the other while holding down \a modifier. - - By default the multi-select-modifier is set to Qt::ControlModifier. - - \see setInteractions +/*! \overload + + Removes the item with the specified \a index from the legend and deletes it. + + After successful removal, the legend is reordered according to the current fill order (\ref + setFillOrder) and wrapping (\ref setWrap), so no empty cell remains where the removed \a item + was. If you don't want this, rather use the raw element interface of \ref QCPLayoutGrid. + + Returns true, if successful. Unlike \ref QCPLayoutGrid::removeAt, this method only removes + elements derived from \ref QCPAbstractLegendItem. + + \see itemCount, clearItems +*/ +bool QCPLegend::removeItem(int index) +{ + if (QCPAbstractLegendItem *ali = item(index)) + { + bool success = remove(ali); + if (success) + setFillOrder(fillOrder(), true); // gets rid of empty cell by reordering + return success; + } else + return false; +} + +/*! \overload + + Removes \a item from the legend and deletes it. + + After successful removal, the legend is reordered according to the current fill order (\ref + setFillOrder) and wrapping (\ref setWrap), so no empty cell remains where the removed \a item + was. If you don't want this, rather use the raw element interface of \ref QCPLayoutGrid. + + Returns true, if successful. + + \see clearItems */ -void QCustomPlot::setMultiSelectModifier(Qt::KeyboardModifier modifier) +bool QCPLegend::removeItem(QCPAbstractLegendItem *item) { - mMultiSelectModifier = modifier; + bool success = remove(item); + if (success) + setFillOrder(fillOrder(), true); // gets rid of empty cell by reordering + return success; } /*! - Sets the viewport of this QCustomPlot. The Viewport is the area that the top level layout - (QCustomPlot::plotLayout()) uses as its rect. Normally, the viewport is the entire widget rect. - - This function is used to allow arbitrary size exports with \ref toPixmap, \ref savePng, \ref - savePdf, etc. by temporarily changing the viewport size. + Removes all items from the legend. */ -void QCustomPlot::setViewport(const QRect &rect) +void QCPLegend::clearItems() { - mViewport = rect; - if (mPlotLayout) - mPlotLayout->setOuterRect(mViewport); + for (int i=elementCount()-1; i>=0; --i) + { + if (item(i)) + removeAt(i); // don't use removeItem() because it would unnecessarily reorder the whole legend for each item + } + setFillOrder(fillOrder(), true); // get rid of empty cells by reordering once after all items are removed } /*! - Sets \a pm as the viewport background pixmap (see \ref setViewport). The pixmap is always drawn - below all other objects in the plot. - - For cases where the provided pixmap doesn't have the same size as the viewport, scaling can be - enabled with \ref setBackgroundScaled and the scaling mode (whether and how the aspect ratio is - preserved) can be set with \ref setBackgroundScaledMode. To set all these options in one call, - consider using the overloaded version of this function. + Returns the legend items that are currently selected. If no items are selected, + the list is empty. - If a background brush was set with \ref setBackground(const QBrush &brush), the viewport will - first be filled with that brush, before drawing the background pixmap. This can be useful for - background pixmaps with translucent areas. - - \see setBackgroundScaled, setBackgroundScaledMode + \see QCPAbstractLegendItem::setSelected, setSelectable */ -void QCustomPlot::setBackground(const QPixmap &pm) +QList QCPLegend::selectedItems() const { - mBackgroundPixmap = pm; - mScaledBackgroundPixmap = QPixmap(); + QList result; + for (int i=0; iselected()) + result.append(ali); + } + } + return result; } -/*! - Sets the background brush of the viewport (see \ref setViewport). +/*! \internal - Before drawing everything else, the background is filled with \a brush. If a background pixmap - was set with \ref setBackground(const QPixmap &pm), this brush will be used to fill the viewport - before the background pixmap is drawn. This can be useful for background pixmaps with translucent - areas. - - Set \a brush to Qt::NoBrush or Qt::Transparent to leave background transparent. This can be - useful for exporting to image formats which support transparency, e.g. \ref savePng. + A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter + before drawing main legend elements. - \see setBackgroundScaled, setBackgroundScaledMode + This is the antialiasing state the painter passed to the \ref draw method is in by default. + + This function takes into account the local setting of the antialiasing flag as well as the + overrides set with \ref QCustomPlot::setAntialiasedElements and \ref + QCustomPlot::setNotAntialiasedElements. + + \seebaseclassmethod + + \see setAntialiased */ -void QCustomPlot::setBackground(const QBrush &brush) +void QCPLegend::applyDefaultAntialiasingHint(QCPPainter *painter) const { - mBackgroundBrush = brush; + applyAntialiasingHint(painter, mAntialiased, QCP::aeLegend); } -/*! \overload +/*! \internal - Allows setting the background pixmap of the viewport, whether it shall be scaled and how it - shall be scaled in one call. - - \see setBackground(const QPixmap &pm), setBackgroundScaled, setBackgroundScaledMode + Returns the pen used to paint the border of the legend, taking into account the selection state + of the legend box. */ -void QCustomPlot::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode) +QPen QCPLegend::getBorderPen() const { - mBackgroundPixmap = pm; - mScaledBackgroundPixmap = QPixmap(); - mBackgroundScaled = scaled; - mBackgroundScaledMode = mode; + return mSelectedParts.testFlag(spLegendBox) ? mSelectedBorderPen : mBorderPen; } -/*! - Sets whether the viewport background pixmap shall be scaled to fit the viewport. If \a scaled is - set to true, control whether and how the aspect ratio of the original pixmap is preserved with - \ref setBackgroundScaledMode. - - Note that the scaled version of the original pixmap is buffered, so there is no performance - penalty on replots. (Except when the viewport dimensions are changed continuously.) +/*! \internal - \see setBackground, setBackgroundScaledMode + Returns the brush used to paint the background of the legend, taking into account the selection + state of the legend box. */ -void QCustomPlot::setBackgroundScaled(bool scaled) +QBrush QCPLegend::getBrush() const { - mBackgroundScaled = scaled; + return mSelectedParts.testFlag(spLegendBox) ? mSelectedBrush : mBrush; } -/*! - If scaling of the viewport background pixmap is enabled (\ref setBackgroundScaled), use this - function to define whether and how the aspect ratio of the original pixmap is preserved. +/*! \internal - \see setBackground, setBackgroundScaled + Draws the legend box with the provided \a painter. The individual legend items are layerables + themselves, thus are drawn independently. */ -void QCustomPlot::setBackgroundScaledMode(Qt::AspectRatioMode mode) +void QCPLegend::draw(QCPPainter *painter) { - mBackgroundScaledMode = mode; + // draw background rect: + painter->setBrush(getBrush()); + painter->setPen(getBorderPen()); + painter->drawRect(mOuterRect); } -/*! - Returns the plottable with \a index. If the index is invalid, returns 0. - - There is an overloaded version of this function with no parameter which returns the last added - plottable, see QCustomPlot::plottable() - - \see plottableCount, addPlottable -*/ -QCPAbstractPlottable *QCustomPlot::plottable(int index) +/* inherits documentation from base class */ +double QCPLegend::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - if (index >= 0 && index < mPlottables.size()) + if (!mParentPlot) return -1; + if (onlySelectable && !mSelectableParts.testFlag(spLegendBox)) + return -1; + + if (mOuterRect.contains(pos.toPoint())) { - return mPlottables.at(index); - } else + if (details) details->setValue(spLegendBox); + return mParentPlot->selectionTolerance()*0.99; + } + return -1; +} + +/* inherits documentation from base class */ +void QCPLegend::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) +{ + Q_UNUSED(event) + mSelectedParts = selectedParts(); // in case item selection has changed + if (details.value() == spLegendBox && mSelectableParts.testFlag(spLegendBox)) { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return 0; + SelectableParts selBefore = mSelectedParts; + setSelectedParts(additive ? mSelectedParts^spLegendBox : mSelectedParts|spLegendBox); // no need to unset spItems in !additive case, because they will be deselected by QCustomPlot (they're normal QCPLayerables with own deselectEvent) + if (selectionStateChanged) + *selectionStateChanged = mSelectedParts != selBefore; } } -/*! \overload - - Returns the last plottable that was added with \ref addPlottable. If there are no plottables in - the plot, returns 0. - - \see plottableCount, addPlottable -*/ -QCPAbstractPlottable *QCustomPlot::plottable() +/* inherits documentation from base class */ +void QCPLegend::deselectEvent(bool *selectionStateChanged) { - if (!mPlottables.isEmpty()) + mSelectedParts = selectedParts(); // in case item selection has changed + if (mSelectableParts.testFlag(spLegendBox)) { - return mPlottables.last(); - } else - return 0; + SelectableParts selBefore = mSelectedParts; + setSelectedParts(selectedParts() & ~spLegendBox); + if (selectionStateChanged) + *selectionStateChanged = mSelectedParts != selBefore; + } } -/*! - Adds the specified plottable to the plot and, if \ref setAutoAddPlottableToLegend is enabled, to - the legend (QCustomPlot::legend). QCustomPlot takes ownership of the plottable. +/* inherits documentation from base class */ +QCP::Interaction QCPLegend::selectionCategory() const +{ + return QCP::iSelectLegend; +} + +/* inherits documentation from base class */ +QCP::Interaction QCPAbstractLegendItem::selectionCategory() const +{ + return QCP::iSelectLegend; +} + +/* inherits documentation from base class */ +void QCPLegend::parentPlotInitialized(QCustomPlot *parentPlot) +{ + if (parentPlot && !parentPlot->legend) + parentPlot->legend = this; +} +/* end of 'src/layoutelements/layoutelement-legend.cpp' */ + + +/* including file 'src/layoutelements/layoutelement-textelement.cpp' */ +/* modified 2022-11-06T12:45:56, size 12925 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPTextElement +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPTextElement + \brief A layout element displaying a text + + The text may be specified with \ref setText, the formatting can be controlled with \ref setFont, + \ref setTextColor, and \ref setTextFlags. + + A text element can be added as follows: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcptextelement-creation +*/ + +/* start documentation of signals */ + +/*! \fn void QCPTextElement::selectionChanged(bool selected) + + This signal is emitted when the selection state has changed to \a selected, either by user + interaction or by a direct call to \ref setSelected. - Returns true on success, i.e. when \a plottable isn't already in the plot and the parent plot of - \a plottable is this QCustomPlot (the latter is controlled by what axes were passed in the - plottable's constructor). + \see setSelected, setSelectable +*/ + +/*! \fn void QCPTextElement::clicked(QMouseEvent *event) + + This signal is emitted when the text element is clicked. + + \see doubleClicked, selectTest +*/ + +/*! \fn void QCPTextElement::doubleClicked(QMouseEvent *event) + + This signal is emitted when the text element is double clicked. + + \see clicked, selectTest +*/ + +/* end documentation of signals */ + +/*! \overload - \see plottable, plottableCount, removePlottable, clearPlottables + Creates a new QCPTextElement instance and sets default values. The initial text is empty (\ref + setText). */ -bool QCustomPlot::addPlottable(QCPAbstractPlottable *plottable) +QCPTextElement::QCPTextElement(QCustomPlot *parentPlot) : + QCPLayoutElement(parentPlot), + mText(), + mTextFlags(Qt::AlignCenter), + mFont(QFont(QLatin1String("sans serif"), 12)), // will be taken from parentPlot if available, see below + mTextColor(Qt::black), + mSelectedFont(QFont(QLatin1String("sans serif"), 12)), // will be taken from parentPlot if available, see below + mSelectedTextColor(Qt::blue), + mSelectable(false), + mSelected(false) { - if (mPlottables.contains(plottable)) - { - qDebug() << Q_FUNC_INFO << "plottable already added to this QCustomPlot:" << reinterpret_cast(plottable); - return false; - } - if (plottable->parentPlot() != this) + if (parentPlot) { - qDebug() << Q_FUNC_INFO << "plottable not created with this QCustomPlot as parent:" << reinterpret_cast(plottable); - return false; + mFont = parentPlot->font(); + mSelectedFont = parentPlot->font(); } - - mPlottables.append(plottable); - // possibly add plottable to legend: - if (mAutoAddPlottableToLegend) - plottable->addToLegend(); - // special handling for QCPGraphs to maintain the simple graph interface: - if (QCPGraph *graph = qobject_cast(plottable)) - mGraphs.append(graph); - if (!plottable->layer()) // usually the layer is already set in the constructor of the plottable (via QCPLayerable constructor) - plottable->setLayer(currentLayer()); - return true; + setMargins(QMargins(2, 2, 2, 2)); } -/*! - Removes the specified plottable from the plot and, if necessary, from the legend (QCustomPlot::legend). - - Returns true on success. +/*! \overload - \see addPlottable, clearPlottables + Creates a new QCPTextElement instance and sets default values. + + The initial text is set to \a text. */ -bool QCustomPlot::removePlottable(QCPAbstractPlottable *plottable) +QCPTextElement::QCPTextElement(QCustomPlot *parentPlot, const QString &text) : + QCPLayoutElement(parentPlot), + mText(text), + mTextFlags(Qt::AlignCenter), + mFont(QFont(QLatin1String("sans serif"), 12)), // will be taken from parentPlot if available, see below + mTextColor(Qt::black), + mSelectedFont(QFont(QLatin1String("sans serif"), 12)), // will be taken from parentPlot if available, see below + mSelectedTextColor(Qt::blue), + mSelectable(false), + mSelected(false) { - if (!mPlottables.contains(plottable)) + if (parentPlot) { - qDebug() << Q_FUNC_INFO << "plottable not in list:" << reinterpret_cast(plottable); - return false; + mFont = parentPlot->font(); + mSelectedFont = parentPlot->font(); } - - // remove plottable from legend: - plottable->removeFromLegend(); - // special handling for QCPGraphs to maintain the simple graph interface: - if (QCPGraph *graph = qobject_cast(plottable)) - mGraphs.removeOne(graph); - // remove plottable: - delete plottable; - mPlottables.removeOne(plottable); - return true; + setMargins(QMargins(2, 2, 2, 2)); } /*! \overload - Removes the plottable by its \a index. + Creates a new QCPTextElement instance and sets default values. + + The initial text is set to \a text with \a pointSize. */ -bool QCustomPlot::removePlottable(int index) +QCPTextElement::QCPTextElement(QCustomPlot *parentPlot, const QString &text, double pointSize) : + QCPLayoutElement(parentPlot), + mText(text), + mTextFlags(Qt::AlignCenter), + mFont(QFont(QLatin1String("sans serif"), int(pointSize))), // will be taken from parentPlot if available, see below + mTextColor(Qt::black), + mSelectedFont(QFont(QLatin1String("sans serif"), int(pointSize))), // will be taken from parentPlot if available, see below + mSelectedTextColor(Qt::blue), + mSelectable(false), + mSelected(false) { - if (index >= 0 && index < mPlottables.size()) - return removePlottable(mPlottables[index]); - else + mFont.setPointSizeF(pointSize); // set here again as floating point, because constructor above only takes integer + if (parentPlot) { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return false; + mFont = parentPlot->font(); + mFont.setPointSizeF(pointSize); + mSelectedFont = parentPlot->font(); + mSelectedFont.setPointSizeF(pointSize); } + setMargins(QMargins(2, 2, 2, 2)); } -/*! - Removes all plottables from the plot (and the QCustomPlot::legend, if necessary). +/*! \overload - Returns the number of plottables removed. + Creates a new QCPTextElement instance and sets default values. + + The initial text is set to \a text with \a pointSize and the specified \a fontFamily. +*/ +QCPTextElement::QCPTextElement(QCustomPlot *parentPlot, const QString &text, const QString &fontFamily, double pointSize) : + QCPLayoutElement(parentPlot), + mText(text), + mTextFlags(Qt::AlignCenter), + mFont(QFont(fontFamily, int(pointSize))), + mTextColor(Qt::black), + mSelectedFont(QFont(fontFamily, int(pointSize))), + mSelectedTextColor(Qt::blue), + mSelectable(false), + mSelected(false) +{ + mFont.setPointSizeF(pointSize); // set here again as floating point, because constructor above only takes integer + setMargins(QMargins(2, 2, 2, 2)); +} + +/*! \overload - \see removePlottable + Creates a new QCPTextElement instance and sets default values. + + The initial text is set to \a text with the specified \a font. */ -int QCustomPlot::clearPlottables() +QCPTextElement::QCPTextElement(QCustomPlot *parentPlot, const QString &text, const QFont &font) : + QCPLayoutElement(parentPlot), + mText(text), + mTextFlags(Qt::AlignCenter), + mFont(font), + mTextColor(Qt::black), + mSelectedFont(font), + mSelectedTextColor(Qt::blue), + mSelectable(false), + mSelected(false) { - int c = mPlottables.size(); - for (int i=c-1; i >= 0; --i) - removePlottable(mPlottables[i]); - return c; + setMargins(QMargins(2, 2, 2, 2)); } /*! - Returns the number of currently existing plottables in the plot + Sets the text that will be displayed to \a text. Multiple lines can be created by insertion of "\n". - \see plottable, addPlottable + \see setFont, setTextColor, setTextFlags */ -int QCustomPlot::plottableCount() const +void QCPTextElement::setText(const QString &text) { - return mPlottables.size(); + mText = text; } /*! - Returns a list of the selected plottables. If no plottables are currently selected, the list is empty. - - There is a convenience function if you're only interested in selected graphs, see \ref selectedGraphs. + Sets options for text alignment and wrapping behaviour. \a flags is a bitwise OR-combination of + \c Qt::AlignmentFlag and \c Qt::TextFlag enums. - \see setInteractions, QCPAbstractPlottable::setSelectable, QCPAbstractPlottable::setSelected + Possible enums are: + - Qt::AlignLeft + - Qt::AlignRight + - Qt::AlignHCenter + - Qt::AlignJustify + - Qt::AlignTop + - Qt::AlignBottom + - Qt::AlignVCenter + - Qt::AlignCenter + - Qt::TextDontClip + - Qt::TextSingleLine + - Qt::TextExpandTabs + - Qt::TextShowMnemonic + - Qt::TextWordWrap + - Qt::TextIncludeTrailingSpaces */ -QList QCustomPlot::selectedPlottables() const +void QCPTextElement::setTextFlags(int flags) { - QList result; - foreach (QCPAbstractPlottable *plottable, mPlottables) - { - if (plottable->selected()) - result.append(plottable); - } - return result; + mTextFlags = flags; } /*! - Returns the plottable at the pixel position \a pos. Plottables that only consist of single lines - (like graphs) have a tolerance band around them, see \ref setSelectionTolerance. If multiple - plottables come into consideration, the one closest to \a pos is returned. + Sets the \a font of the text. - If \a onlySelectable is true, only plottables that are selectable - (QCPAbstractPlottable::setSelectable) are considered. - - If there is no plottable at \a pos, the return value is 0. - - \see itemAt, layoutElementAt + \see setTextColor, setSelectedFont */ -QCPAbstractPlottable *QCustomPlot::plottableAt(const QPointF &pos, bool onlySelectable) const +void QCPTextElement::setFont(const QFont &font) { - QCPAbstractPlottable *resultPlottable = 0; - double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value - - foreach (QCPAbstractPlottable *plottable, mPlottables) - { - if (onlySelectable && !plottable->selectable()) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPabstractPlottable::selectable - continue; - if ((plottable->keyAxis()->axisRect()->rect() & plottable->valueAxis()->axisRect()->rect()).contains(pos.toPoint())) // only consider clicks inside the rect that is spanned by the plottable's key/value axes - { - double currentDistance = plottable->selectTest(pos, false); - if (currentDistance >= 0 && currentDistance < resultDistance) - { - resultPlottable = plottable; - resultDistance = currentDistance; - } - } - } - - return resultPlottable; + mFont = font; } /*! - Returns whether this QCustomPlot instance contains the \a plottable. + Sets the \a color of the text. - \see addPlottable + \see setFont, setSelectedTextColor */ -bool QCustomPlot::hasPlottable(QCPAbstractPlottable *plottable) const +void QCPTextElement::setTextColor(const QColor &color) { - return mPlottables.contains(plottable); + mTextColor = color; } /*! - Returns the graph with \a index. If the index is invalid, returns 0. - - There is an overloaded version of this function with no parameter which returns the last created - graph, see QCustomPlot::graph() + Sets the \a font of the text that will be used if the text element is selected (\ref setSelected). - \see graphCount, addGraph + \see setFont */ -QCPGraph *QCustomPlot::graph(int index) const +void QCPTextElement::setSelectedFont(const QFont &font) { - if (index >= 0 && index < mGraphs.size()) - { - return mGraphs.at(index); - } else - { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return 0; - } + mSelectedFont = font; } -/*! \overload - - Returns the last graph, that was created with \ref addGraph. If there are no graphs in the plot, - returns 0. +/*! + Sets the \a color of the text that will be used if the text element is selected (\ref setSelected). - \see graphCount, addGraph + \see setTextColor */ -QCPGraph *QCustomPlot::graph() const +void QCPTextElement::setSelectedTextColor(const QColor &color) { - if (!mGraphs.isEmpty()) - { - return mGraphs.last(); - } else - return 0; + mSelectedTextColor = color; } /*! - Creates a new graph inside the plot. If \a keyAxis and \a valueAxis are left unspecified (0), the - bottom (xAxis) is used as key and the left (yAxis) is used as value axis. If specified, \a - keyAxis and \a valueAxis must reside in this QCustomPlot. - - \a keyAxis will be used as key axis (typically "x") and \a valueAxis as value axis (typically - "y") for the graph. - - Returns a pointer to the newly created graph, or 0 if adding the graph failed. - - \see graph, graphCount, removeGraph, clearGraphs + Sets whether the user may select this text element. + + Note that even when \a selectable is set to false, the selection state may be changed + programmatically via \ref setSelected. */ -QCPGraph *QCustomPlot::addGraph(QCPAxis *keyAxis, QCPAxis *valueAxis) +void QCPTextElement::setSelectable(bool selectable) { - if (!keyAxis) keyAxis = xAxis; - if (!valueAxis) valueAxis = yAxis; - if (!keyAxis || !valueAxis) - { - qDebug() << Q_FUNC_INFO << "can't use default QCustomPlot xAxis or yAxis, because at least one is invalid (has been deleted)"; - return 0; - } - if (keyAxis->parentPlot() != this || valueAxis->parentPlot() != this) - { - qDebug() << Q_FUNC_INFO << "passed keyAxis or valueAxis doesn't have this QCustomPlot as parent"; - return 0; - } - - QCPGraph *newGraph = new QCPGraph(keyAxis, valueAxis); - if (addPlottable(newGraph)) - { - newGraph->setName(QLatin1String("Graph ")+QString::number(mGraphs.size())); - return newGraph; - } else + if (mSelectable != selectable) { - delete newGraph; - return 0; + mSelectable = selectable; + emit selectableChanged(mSelectable); } } /*! - Removes the specified \a graph from the plot and, if necessary, from the QCustomPlot::legend. If - any other graphs in the plot have a channel fill set towards the removed graph, the channel fill - property of those graphs is reset to zero (no channel fill). - - Returns true on success. + Sets the selection state of this text element to \a selected. If the selection has changed, \ref + selectionChanged is emitted. - \see clearGraphs + Note that this function can change the selection state independently of the current \ref + setSelectable state. */ -bool QCustomPlot::removeGraph(QCPGraph *graph) +void QCPTextElement::setSelected(bool selected) { - return removePlottable(graph); + if (mSelected != selected) + { + mSelected = selected; + emit selectionChanged(mSelected); + } } -/*! \overload - - Removes the graph by its \a index. -*/ -bool QCustomPlot::removeGraph(int index) +/* inherits documentation from base class */ +void QCPTextElement::applyDefaultAntialiasingHint(QCPPainter *painter) const { - if (index >= 0 && index < mGraphs.size()) - return removeGraph(mGraphs[index]); - else - return false; + applyAntialiasingHint(painter, mAntialiased, QCP::aeOther); } -/*! - Removes all graphs from the plot (and the QCustomPlot::legend, if necessary). +/* inherits documentation from base class */ +void QCPTextElement::draw(QCPPainter *painter) +{ + painter->setFont(mainFont()); + painter->setPen(QPen(mainTextColor())); + painter->drawText(mRect, mTextFlags, mText, &mTextBoundingRect); +} - Returns the number of graphs removed. - - \see removeGraph -*/ -int QCustomPlot::clearGraphs() +/* inherits documentation from base class */ +QSize QCPTextElement::minimumOuterSizeHint() const { - int c = mGraphs.size(); - for (int i=c-1; i >= 0; --i) - removeGraph(mGraphs[i]); - return c; + QFontMetrics metrics(mFont); + QSize result(metrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip, mText).size()); + result.rwidth() += mMargins.left()+mMargins.right(); + result.rheight() += mMargins.top()+mMargins.bottom(); + return result; } -/*! - Returns the number of currently existing graphs in the plot - - \see graph, addGraph -*/ -int QCustomPlot::graphCount() const +/* inherits documentation from base class */ +QSize QCPTextElement::maximumOuterSizeHint() const { - return mGraphs.size(); + QFontMetrics metrics(mFont); + QSize result(metrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip, mText).size()); + result.setWidth(QWIDGETSIZE_MAX); + result.rheight() += mMargins.top()+mMargins.bottom(); + return result; } -/*! - Returns a list of the selected graphs. If no graphs are currently selected, the list is empty. - - If you are not only interested in selected graphs but other plottables like QCPCurve, QCPBars, - etc., use \ref selectedPlottables. - - \see setInteractions, selectedPlottables, QCPAbstractPlottable::setSelectable, QCPAbstractPlottable::setSelected -*/ -QList QCustomPlot::selectedGraphs() const +/* inherits documentation from base class */ +void QCPTextElement::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) { - QList result; - foreach (QCPGraph *graph, mGraphs) + Q_UNUSED(event) + Q_UNUSED(details) + if (mSelectable) { - if (graph->selected()) - result.append(graph); + bool selBefore = mSelected; + setSelected(additive ? !mSelected : true); + if (selectionStateChanged) + *selectionStateChanged = mSelected != selBefore; } - return result; } -/*! - Returns the item with \a index. If the index is invalid, returns 0. - - There is an overloaded version of this function with no parameter which returns the last added - item, see QCustomPlot::item() - - \see itemCount, addItem -*/ -QCPAbstractItem *QCustomPlot::item(int index) const +/* inherits documentation from base class */ +void QCPTextElement::deselectEvent(bool *selectionStateChanged) { - if (index >= 0 && index < mItems.size()) - { - return mItems.at(index); - } else + if (mSelectable) { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return 0; + bool selBefore = mSelected; + setSelected(false); + if (selectionStateChanged) + *selectionStateChanged = mSelected != selBefore; } } -/*! \overload - - Returns the last item, that was added with \ref addItem. If there are no items in the plot, - returns 0. +/*! + Returns 0.99*selectionTolerance (see \ref QCustomPlot::setSelectionTolerance) when \a pos is + within the bounding box of the text element's text. Note that this bounding box is updated in the + draw call. + + If \a pos is outside the text's bounding box or if \a onlySelectable is true and this text + element is not selectable (\ref setSelectable), returns -1. + + \seebaseclassmethod +*/ +double QCPTextElement::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +{ + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; - \see itemCount, addItem + if (mTextBoundingRect.contains(pos.toPoint())) + return mParentPlot->selectionTolerance()*0.99; + else + return -1; +} + +/*! + Accepts the mouse event in order to emit the according click signal in the \ref + mouseReleaseEvent. + + \seebaseclassmethod */ -QCPAbstractItem *QCustomPlot::item() const +void QCPTextElement::mousePressEvent(QMouseEvent *event, const QVariant &details) { - if (!mItems.isEmpty()) - { - return mItems.last(); - } else - return 0; + Q_UNUSED(details) + event->accept(); } /*! - Adds the specified item to the plot. QCustomPlot takes ownership of the item. - - Returns true on success, i.e. when \a item wasn't already in the plot and the parent plot of \a - item is this QCustomPlot. - - \see item, itemCount, removeItem, clearItems + Emits the \ref clicked signal if the cursor hasn't moved by more than a few pixels since the \ref + mousePressEvent. + + \seebaseclassmethod */ -bool QCustomPlot::addItem(QCPAbstractItem *item) +void QCPTextElement::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) { - if (!mItems.contains(item) && item->parentPlot() == this) - { - mItems.append(item); - return true; - } else - { - qDebug() << Q_FUNC_INFO << "item either already in list or not created with this QCustomPlot as parent:" << reinterpret_cast(item); - return false; - } + if ((QPointF(event->pos())-startPos).manhattanLength() <= 3) + emit clicked(event); } /*! - Removes the specified item from the plot. - - Returns true on success. - - \see addItem, clearItems + Emits the \ref doubleClicked signal. + + \seebaseclassmethod */ -bool QCustomPlot::removeItem(QCPAbstractItem *item) +void QCPTextElement::mouseDoubleClickEvent(QMouseEvent *event, const QVariant &details) { - if (mItems.contains(item)) - { - delete item; - mItems.removeOne(item); - return true; - } else - { - qDebug() << Q_FUNC_INFO << "item not in list:" << reinterpret_cast(item); - return false; - } + Q_UNUSED(details) + emit doubleClicked(event); } -/*! \overload +/*! \internal - Removes the item by its \a index. + Returns the main font to be used. This is mSelectedFont if \ref setSelected is set to + true, else mFont is returned. */ -bool QCustomPlot::removeItem(int index) +QFont QCPTextElement::mainFont() const { - if (index >= 0 && index < mItems.size()) - return removeItem(mItems[index]); - else - { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return false; - } + return mSelected ? mSelectedFont : mFont; } -/*! - Removes all items from the plot. - - Returns the number of items removed. +/*! \internal - \see removeItem + Returns the main color to be used. This is mSelectedTextColor if \ref setSelected is set to + true, else mTextColor is returned. */ -int QCustomPlot::clearItems() +QColor QCPTextElement::mainTextColor() const { - int c = mItems.size(); - for (int i=c-1; i >= 0; --i) - removeItem(mItems[i]); - return c; + return mSelected ? mSelectedTextColor : mTextColor; } +/* end of 'src/layoutelements/layoutelement-textelement.cpp' */ -/*! - Returns the number of currently existing items in the plot + +/* including file 'src/layoutelements/layoutelement-colorscale.cpp' */ +/* modified 2022-11-06T12:45:56, size 26531 */ + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPColorScale +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPColorScale + \brief A color scale for use with color coding data such as QCPColorMap + + This layout element can be placed on the plot to correlate a color gradient with data values. It + is usually used in combination with one or multiple \ref QCPColorMap "QCPColorMaps". + + \image html QCPColorScale.png + + The color scale can be either horizontal or vertical, as shown in the image above. The + orientation and the side where the numbers appear is controlled with \ref setType. + + Use \ref QCPColorMap::setColorScale to connect a color map with a color scale. Once they are + connected, they share their gradient, data range and data scale type (\ref setGradient, \ref + setDataRange, \ref setDataScaleType). Multiple color maps may be associated with a single color + scale, to make them all synchronize these properties. + + To have finer control over the number display and axis behaviour, you can directly access the + \ref axis. See the documentation of QCPAxis for details about configuring axes. For example, if + you want to change the number of automatically generated ticks, call + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcolorscale-tickcount + + Placing a color scale next to the main axis rect works like with any other layout element: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcolorscale-creation + In this case we have placed it to the right of the default axis rect, so it wasn't necessary to + call \ref setType, since \ref QCPAxis::atRight is already the default. The text next to the color + scale can be set with \ref setLabel. + + For optimum appearance (like in the image above), it may be desirable to line up the axis rect and + the borders of the color scale. Use a \ref QCPMarginGroup to achieve this: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcolorscale-margingroup - \see item, addItem + Color scales are initialized with a non-zero minimum top and bottom margin (\ref + setMinimumMargins), because vertical color scales are most common and the minimum top/bottom + margin makes sure it keeps some distance to the top/bottom widget border. So if you change to a + horizontal color scale by setting \ref setType to \ref QCPAxis::atBottom or \ref QCPAxis::atTop, you + might want to also change the minimum margins accordingly, e.g. setMinimumMargins(QMargins(6, 0, 6, 0)). */ -int QCustomPlot::itemCount() const -{ - return mItems.size(); -} -/*! - Returns a list of the selected items. If no items are currently selected, the list is empty. +/* start documentation of inline functions */ + +/*! \fn QCPAxis *QCPColorScale::axis() const - \see setInteractions, QCPAbstractItem::setSelectable, QCPAbstractItem::setSelected + Returns the internal \ref QCPAxis instance of this color scale. You can access it to alter the + appearance and behaviour of the axis. \ref QCPColorScale duplicates some properties in its + interface for convenience. Those are \ref setDataRange (\ref QCPAxis::setRange), \ref + setDataScaleType (\ref QCPAxis::setScaleType), and the method \ref setLabel (\ref + QCPAxis::setLabel). As they each are connected, it does not matter whether you use the method on + the QCPColorScale or on its QCPAxis. + + If the type of the color scale is changed with \ref setType, the axis returned by this method + will change, too, to either the left, right, bottom or top axis, depending on which type was set. */ -QList QCustomPlot::selectedItems() const -{ - QList result; - foreach (QCPAbstractItem *item, mItems) - { - if (item->selected()) - result.append(item); - } - return result; -} -/*! - Returns the item at the pixel position \a pos. Items that only consist of single lines (e.g. \ref - QCPItemLine or \ref QCPItemCurve) have a tolerance band around them, see \ref - setSelectionTolerance. If multiple items come into consideration, the one closest to \a pos is - returned. +/* end documentation of signals */ +/* start documentation of signals */ + +/*! \fn void QCPColorScale::dataRangeChanged(const QCPRange &newRange); - If \a onlySelectable is true, only items that are selectable (QCPAbstractItem::setSelectable) are - considered. + This signal is emitted when the data range changes. + + \see setDataRange +*/ + +/*! \fn void QCPColorScale::dataScaleTypeChanged(QCPAxis::ScaleType scaleType); - If there is no item at \a pos, the return value is 0. + This signal is emitted when the data scale type changes. - \see plottableAt, layoutElementAt + \see setDataScaleType */ -QCPAbstractItem *QCustomPlot::itemAt(const QPointF &pos, bool onlySelectable) const -{ - QCPAbstractItem *resultItem = 0; - double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value + +/*! \fn void QCPColorScale::gradientChanged(const QCPColorGradient &newGradient); - foreach (QCPAbstractItem *item, mItems) - { - if (onlySelectable && !item->selectable()) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPAbstractItem::selectable - continue; - if (!item->clipToAxisRect() || item->clipRect().contains(pos.toPoint())) // only consider clicks inside axis cliprect of the item if actually clipped to it - { - double currentDistance = item->selectTest(pos, false); - if (currentDistance >= 0 && currentDistance < resultDistance) - { - resultItem = item; - resultDistance = currentDistance; - } - } - } + This signal is emitted when the gradient changes. - return resultItem; -} + \see setGradient +*/ + +/* end documentation of signals */ /*! - Returns whether this QCustomPlot contains the \a item. - - \see addItem + Constructs a new QCPColorScale. */ -bool QCustomPlot::hasItem(QCPAbstractItem *item) const +QCPColorScale::QCPColorScale(QCustomPlot *parentPlot) : + QCPLayoutElement(parentPlot), + mType(QCPAxis::atTop), // set to atTop such that setType(QCPAxis::atRight) below doesn't skip work because it thinks it's already atRight + mDataScaleType(QCPAxis::stLinear), + mGradient(QCPColorGradient::gpCold), + mBarWidth(20), + mAxisRect(new QCPColorScaleAxisRectPrivate(this)) { - return mItems.contains(item); + setMinimumMargins(QMargins(0, 6, 0, 6)); // for default right color scale types, keep some room at bottom and top (important if no margin group is used) + setType(QCPAxis::atRight); + setDataRange(QCPRange(0, 6)); } -/*! - Returns the layer with the specified \a name. If there is no layer with the specified name, 0 is - returned. - - Layer names are case-sensitive. +QCPColorScale::~QCPColorScale() +{ + delete mAxisRect; +} + +/* undocumented getter */ +QString QCPColorScale::label() const +{ + if (!mColorAxis) + { + qDebug() << Q_FUNC_INFO << "internal color axis undefined"; + return QString(); + } - \see addLayer, moveLayer, removeLayer -*/ -QCPLayer *QCustomPlot::layer(const QString &name) const + return mColorAxis.data()->label(); +} + +/* undocumented getter */ +bool QCPColorScale::rangeDrag() const { - foreach (QCPLayer *layer, mLayers) + if (!mAxisRect) { - if (layer->name() == name) - return layer; + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return false; } - return 0; + + return mAxisRect.data()->rangeDrag().testFlag(QCPAxis::orientation(mType)) && + mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType)) && + mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType); } -/*! \overload +/* undocumented getter */ +bool QCPColorScale::rangeZoom() const +{ + if (!mAxisRect) + { + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return false; + } - Returns the layer by \a index. If the index is invalid, 0 is returned. + return mAxisRect.data()->rangeZoom().testFlag(QCPAxis::orientation(mType)) && + mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType)) && + mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType); +} + +/*! + Sets at which side of the color scale the axis is placed, and thus also its orientation. - \see addLayer, moveLayer, removeLayer + Note that after setting \a type to a different value, the axis returned by \ref axis() will + be a different one. The new axis will adopt the following properties from the previous axis: The + range, scale type, label and ticker (the latter will be shared and not copied). */ -QCPLayer *QCustomPlot::layer(int index) const +void QCPColorScale::setType(QCPAxis::AxisType type) { - if (index >= 0 && index < mLayers.size()) + if (!mAxisRect) { - return mLayers.at(index); - } else + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; + } + if (mType != type) { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return 0; + mType = type; + QCPRange rangeTransfer(0, 6); + QString labelTransfer; + QSharedPointer tickerTransfer; + // transfer/revert some settings on old axis if it exists: + bool doTransfer = !mColorAxis.isNull(); + if (doTransfer) + { + rangeTransfer = mColorAxis.data()->range(); + labelTransfer = mColorAxis.data()->label(); + tickerTransfer = mColorAxis.data()->ticker(); + mColorAxis.data()->setLabel(QString()); + disconnect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); + disconnect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); + } + const QList allAxisTypes = QList() << QCPAxis::atLeft << QCPAxis::atRight << QCPAxis::atBottom << QCPAxis::atTop; + foreach (QCPAxis::AxisType atype, allAxisTypes) + { + mAxisRect.data()->axis(atype)->setTicks(atype == mType); + mAxisRect.data()->axis(atype)->setTickLabels(atype== mType); + } + // set new mColorAxis pointer: + mColorAxis = mAxisRect.data()->axis(mType); + // transfer settings to new axis: + if (doTransfer) + { + mColorAxis.data()->setRange(rangeTransfer); // range transfer necessary if axis changes from vertical to horizontal or vice versa (axes with same orientation are synchronized via signals) + mColorAxis.data()->setLabel(labelTransfer); + mColorAxis.data()->setTicker(tickerTransfer); + } + connect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); + connect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); + mAxisRect.data()->setRangeDragAxes(QList() << mColorAxis.data()); } } /*! - Returns the layer that is set as current layer (see \ref setCurrentLayer). + Sets the range spanned by the color gradient and that is shown by the axis in the color scale. + + It is equivalent to calling QCPColorMap::setDataRange on any of the connected color maps. It is + also equivalent to directly accessing the \ref axis and setting its range with \ref + QCPAxis::setRange. + + \see setDataScaleType, setGradient, rescaleDataRange */ -QCPLayer *QCustomPlot::currentLayer() const +void QCPColorScale::setDataRange(const QCPRange &dataRange) { - return mCurrentLayer; + if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper) + { + mDataRange = dataRange; + if (mColorAxis) + mColorAxis.data()->setRange(mDataRange); + emit dataRangeChanged(mDataRange); + } } /*! - Sets the layer with the specified \a name to be the current layer. All layerables (\ref - QCPLayerable), e.g. plottables and items, are created on the current layer. + Sets the scale type of the color scale, i.e. whether values are associated with colors linearly + or logarithmically. - Returns true on success, i.e. if there is a layer with the specified \a name in the QCustomPlot. + It is equivalent to calling QCPColorMap::setDataScaleType on any of the connected color maps. It is + also equivalent to directly accessing the \ref axis and setting its scale type with \ref + QCPAxis::setScaleType. - Layer names are case-sensitive. + Note that this method controls the coordinate transformation. For logarithmic scales, you will + likely also want to use a logarithmic tick spacing and labeling, which can be achieved by setting + the color scale's \ref axis ticker to an instance of \ref QCPAxisTickerLog : - \see addLayer, moveLayer, removeLayer, QCPLayerable::setLayer + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpaxisticker-log-colorscale + + See the documentation of \ref QCPAxisTickerLog about the details of logarithmic axis tick + creation. + + \see setDataRange, setGradient */ -bool QCustomPlot::setCurrentLayer(const QString &name) +void QCPColorScale::setDataScaleType(QCPAxis::ScaleType scaleType) { - if (QCPLayer *newCurrentLayer = layer(name)) - { - return setCurrentLayer(newCurrentLayer); - } else + if (mDataScaleType != scaleType) { - qDebug() << Q_FUNC_INFO << "layer with name doesn't exist:" << name; - return false; + mDataScaleType = scaleType; + if (mColorAxis) + mColorAxis.data()->setScaleType(mDataScaleType); + if (mDataScaleType == QCPAxis::stLogarithmic) + setDataRange(mDataRange.sanitizedForLogScale()); + emit dataScaleTypeChanged(mDataScaleType); } } -/*! \overload - - Sets the provided \a layer to be the current layer. +/*! + Sets the color gradient that will be used to represent data values. - Returns true on success, i.e. when \a layer is a valid layer in the QCustomPlot. + It is equivalent to calling QCPColorMap::setGradient on any of the connected color maps. - \see addLayer, moveLayer, removeLayer + \see setDataRange, setDataScaleType */ -bool QCustomPlot::setCurrentLayer(QCPLayer *layer) +void QCPColorScale::setGradient(const QCPColorGradient &gradient) { - if (!mLayers.contains(layer)) + if (mGradient != gradient) { - qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast(layer); - return false; + mGradient = gradient; + if (mAxisRect) + mAxisRect.data()->mGradientImageInvalidated = true; + emit gradientChanged(mGradient); } - - mCurrentLayer = layer; - return true; } /*! - Returns the number of currently existing layers in the plot - - \see layer, addLayer + Sets the axis label of the color scale. This is equivalent to calling \ref QCPAxis::setLabel on + the internal \ref axis. */ -int QCustomPlot::layerCount() const +void QCPColorScale::setLabel(const QString &str) { - return mLayers.size(); + if (!mColorAxis) + { + qDebug() << Q_FUNC_INFO << "internal color axis undefined"; + return; + } + + mColorAxis.data()->setLabel(str); } /*! - Adds a new layer to this QCustomPlot instance. The new layer will have the name \a name, which - must be unique. Depending on \a insertMode, it is positioned either below or above \a otherLayer. - - Returns true on success, i.e. if there is no other layer named \a name and \a otherLayer is a - valid layer inside this QCustomPlot. - - If \a otherLayer is 0, the highest layer in the QCustomPlot will be used. - - For an explanation of what layers are in QCustomPlot, see the documentation of \ref QCPLayer. - - \see layer, moveLayer, removeLayer + Sets the width (or height, for horizontal color scales) the bar where the gradient is displayed + will have. */ -bool QCustomPlot::addLayer(const QString &name, QCPLayer *otherLayer, QCustomPlot::LayerInsertMode insertMode) +void QCPColorScale::setBarWidth(int width) { - if (!otherLayer) - otherLayer = mLayers.last(); - if (!mLayers.contains(otherLayer)) - { - qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast(otherLayer); - return false; - } - if (layer(name)) - { - qDebug() << Q_FUNC_INFO << "A layer exists already with the name" << name; - return false; - } - - QCPLayer *newLayer = new QCPLayer(this, name); - mLayers.insert(otherLayer->index() + (insertMode==limAbove ? 1:0), newLayer); - updateLayerIndices(); - return true; + mBarWidth = width; } /*! - Removes the specified \a layer and returns true on success. - - All layerables (e.g. plottables and items) on the removed layer will be moved to the layer below - \a layer. If \a layer is the bottom layer, the layerables are moved to the layer above. In both - cases, the total rendering order of all layerables in the QCustomPlot is preserved. - - If \a layer is the current layer (\ref setCurrentLayer), the layer below (or above, if bottom - layer) becomes the new current layer. - - It is not possible to remove the last layer of the plot. + Sets whether the user can drag the data range (\ref setDataRange). - \see layer, addLayer, moveLayer + Note that \ref QCP::iRangeDrag must be in the QCustomPlot's interactions (\ref + QCustomPlot::setInteractions) to allow range dragging. */ -bool QCustomPlot::removeLayer(QCPLayer *layer) +void QCPColorScale::setRangeDrag(bool enabled) { - if (!mLayers.contains(layer)) - { - qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast(layer); - return false; - } - if (mLayers.size() < 2) + if (!mAxisRect) { - qDebug() << Q_FUNC_INFO << "can't remove last layer"; - return false; + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; } - // append all children of this layer to layer below (if this is lowest layer, prepend to layer above) - int removedIndex = layer->index(); - bool isFirstLayer = removedIndex==0; - QCPLayer *targetLayer = isFirstLayer ? mLayers.at(removedIndex+1) : mLayers.at(removedIndex-1); - QList children = layer->children(); - if (isFirstLayer) // prepend in reverse order (so order relative to each other stays the same) + if (enabled) { - for (int i=children.size()-1; i>=0; --i) - children.at(i)->moveToLayer(targetLayer, true); - } else // append normally + mAxisRect.data()->setRangeDrag(QCPAxis::orientation(mType)); + } else { - for (int i=0; imoveToLayer(targetLayer, false); +#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) + mAxisRect.data()->setRangeDrag(nullptr); +#else + mAxisRect.data()->setRangeDrag({}); +#endif } - // if removed layer is current layer, change current layer to layer below/above: - if (layer == mCurrentLayer) - setCurrentLayer(targetLayer); - // remove layer: - delete layer; - mLayers.removeOne(layer); - updateLayerIndices(); - return true; } /*! - Moves the specified \a layer either above or below \a otherLayer. Whether it's placed above or - below is controlled with \a insertMode. - - Returns true on success, i.e. when both \a layer and \a otherLayer are valid layers in the - QCustomPlot. + Sets whether the user can zoom the data range (\ref setDataRange) by scrolling the mouse wheel. - \see layer, addLayer, moveLayer + Note that \ref QCP::iRangeZoom must be in the QCustomPlot's interactions (\ref + QCustomPlot::setInteractions) to allow range dragging. */ -bool QCustomPlot::moveLayer(QCPLayer *layer, QCPLayer *otherLayer, QCustomPlot::LayerInsertMode insertMode) +void QCPColorScale::setRangeZoom(bool enabled) { - if (!mLayers.contains(layer)) + if (!mAxisRect) { - qDebug() << Q_FUNC_INFO << "layer not a layer of this QCustomPlot:" << reinterpret_cast(layer); - return false; + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; } - if (!mLayers.contains(otherLayer)) + + if (enabled) { - qDebug() << Q_FUNC_INFO << "otherLayer not a layer of this QCustomPlot:" << reinterpret_cast(otherLayer); - return false; + mAxisRect.data()->setRangeZoom(QCPAxis::orientation(mType)); + } else + { +#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) + mAxisRect.data()->setRangeDrag(nullptr); +#else + mAxisRect.data()->setRangeZoom({}); +#endif } - - mLayers.move(layer->index(), otherLayer->index() + (insertMode==limAbove ? 1:0)); - updateLayerIndices(); - return true; } /*! - Returns the number of axis rects in the plot. - - All axis rects can be accessed via QCustomPlot::axisRect(). - - Initially, only one axis rect exists in the plot. - - \see axisRect, axisRects + Returns a list of all the color maps associated with this color scale. */ -int QCustomPlot::axisRectCount() const +QList QCPColorScale::colorMaps() const { - return axisRects().size(); + QList result; + for (int i=0; iplottableCount(); ++i) + { + if (QCPColorMap *cm = qobject_cast(mParentPlot->plottable(i))) + if (cm->colorScale() == this) + result.append(cm); + } + return result; } /*! - Returns the axis rect with \a index. - - Initially, only one axis rect (with index 0) exists in the plot. If multiple axis rects were - added, all of them may be accessed with this function in a linear fashion (even when they are - nested in a layout hierarchy or inside other axis rects via QCPAxisRect::insetLayout). + Changes the data range such that all color maps associated with this color scale are fully mapped + to the gradient in the data dimension. - \see axisRectCount, axisRects + \see setDataRange */ -QCPAxisRect *QCustomPlot::axisRect(int index) const +void QCPColorScale::rescaleDataRange(bool onlyVisibleMaps) { - const QList rectList = axisRects(); - if (index >= 0 && index < rectList.size()) - { - return rectList.at(index); - } else + QList maps = colorMaps(); + QCPRange newRange; + bool haveRange = false; + QCP::SignDomain sign = QCP::sdBoth; + if (mDataScaleType == QCPAxis::stLogarithmic) + sign = (mDataRange.upper < 0 ? QCP::sdNegative : QCP::sdPositive); + foreach (QCPColorMap *map, maps) { - qDebug() << Q_FUNC_INFO << "invalid axis rect index" << index; - return 0; + if (!map->realVisibility() && onlyVisibleMaps) + continue; + QCPRange mapRange; + if (map->colorScale() == this) + { + bool currentFoundRange = true; + mapRange = map->data()->dataBounds(); + if (sign == QCP::sdPositive) + { + if (mapRange.lower <= 0 && mapRange.upper > 0) + mapRange.lower = mapRange.upper*1e-3; + else if (mapRange.lower <= 0 && mapRange.upper <= 0) + currentFoundRange = false; + } else if (sign == QCP::sdNegative) + { + if (mapRange.upper >= 0 && mapRange.lower < 0) + mapRange.upper = mapRange.lower*1e-3; + else if (mapRange.upper >= 0 && mapRange.lower >= 0) + currentFoundRange = false; + } + if (currentFoundRange) + { + if (!haveRange) + newRange = mapRange; + else + newRange.expand(mapRange); + haveRange = true; + } + } } -} - -/*! - Returns all axis rects in the plot. - - \see axisRectCount, axisRect -*/ -QList QCustomPlot::axisRects() const -{ - QList result; - QStack elementStack; - if (mPlotLayout) - elementStack.push(mPlotLayout); - - while (!elementStack.isEmpty()) + if (haveRange) { - foreach (QCPLayoutElement *element, elementStack.pop()->elements(false)) + if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this dimension), shift current range to at least center the data { - if (element) + double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason + if (mDataScaleType == QCPAxis::stLinear) { - elementStack.push(element); - if (QCPAxisRect *ar = qobject_cast(element)) - result.append(ar); + newRange.lower = center-mDataRange.size()/2.0; + newRange.upper = center+mDataRange.size()/2.0; + } else // mScaleType == stLogarithmic + { + newRange.lower = center/qSqrt(mDataRange.upper/mDataRange.lower); + newRange.upper = center*qSqrt(mDataRange.upper/mDataRange.lower); } } + setDataRange(newRange); } - - return result; } -/*! - Returns the layout element at pixel position \a pos. If there is no element at that position, - returns 0. +/* inherits documentation from base class */ +void QCPColorScale::update(UpdatePhase phase) +{ + QCPLayoutElement::update(phase); + if (!mAxisRect) + { + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; + } - Only visible elements are used. If \ref QCPLayoutElement::setVisible on the element itself or on - any of its parent elements is set to false, it will not be considered. + mAxisRect.data()->update(phase); - \see itemAt, plottableAt -*/ -QCPLayoutElement *QCustomPlot::layoutElementAt(const QPointF &pos) const -{ - QCPLayoutElement *currentElement = mPlotLayout; - bool searchSubElements = true; - while (searchSubElements && currentElement) + switch (phase) { - searchSubElements = false; - foreach (QCPLayoutElement *subElement, currentElement->elements(false)) + case upMargins: { - if (subElement && subElement->realVisibility() && subElement->selectTest(pos, false) >= 0) + if (mType == QCPAxis::atBottom || mType == QCPAxis::atTop) { - currentElement = subElement; - searchSubElements = true; - break; + setMaximumSize(QWIDGETSIZE_MAX, mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom()); + setMinimumSize(0, mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom()); + } else + { + setMaximumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right(), QWIDGETSIZE_MAX); + setMinimumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right(), 0); } + break; } + case upLayout: + { + mAxisRect.data()->setOuterRect(rect()); + break; + } + default: break; } - return currentElement; } -/*! - Returns the axes that currently have selected parts, i.e. whose selection state is not \ref - QCPAxis::spNone. - - \see selectedPlottables, selectedLegends, setInteractions, QCPAxis::setSelectedParts, - QCPAxis::setSelectableParts -*/ -QList QCustomPlot::selectedAxes() const +/* inherits documentation from base class */ +void QCPColorScale::applyDefaultAntialiasingHint(QCPPainter *painter) const { - QList result, allAxes; - foreach (QCPAxisRect *rect, axisRects()) - allAxes << rect->axes(); - - foreach (QCPAxis *axis, allAxes) + painter->setAntialiasing(false); +} + +/* inherits documentation from base class */ +void QCPColorScale::mousePressEvent(QMouseEvent *event, const QVariant &details) +{ + if (!mAxisRect) { - if (axis->selectedParts() != QCPAxis::spNone) - result.append(axis); + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; } - - return result; + mAxisRect.data()->mousePressEvent(event, details); } -/*! - Returns the legends that currently have selected parts, i.e. whose selection state is not \ref - QCPLegend::spNone. - - \see selectedPlottables, selectedAxes, setInteractions, QCPLegend::setSelectedParts, - QCPLegend::setSelectableParts, QCPLegend::selectedItems -*/ -QList QCustomPlot::selectedLegends() const +/* inherits documentation from base class */ +void QCPColorScale::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) { - QList result; - - QStack elementStack; - if (mPlotLayout) - elementStack.push(mPlotLayout); - - while (!elementStack.isEmpty()) + if (!mAxisRect) { - foreach (QCPLayoutElement *subElement, elementStack.pop()->elements(false)) - { - if (subElement) - { - elementStack.push(subElement); - if (QCPLegend *leg = qobject_cast(subElement)) - { - if (leg->selectedParts() != QCPLegend::spNone) - result.append(leg); - } - } - } + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; } - - return result; + mAxisRect.data()->mouseMoveEvent(event, startPos); } -/*! - Deselects all layerables (plottables, items, axes, legends,...) of the QCustomPlot. - - Since calling this function is not a user interaction, this does not emit the \ref - selectionChangedByUser signal. The individual selectionChanged signals are emitted though, if the - objects were previously selected. - - \see setInteractions, selectedPlottables, selectedItems, selectedAxes, selectedLegends -*/ -void QCustomPlot::deselectAll() +/* inherits documentation from base class */ +void QCPColorScale::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) { - foreach (QCPLayer *layer, mLayers) + if (!mAxisRect) { - foreach (QCPLayerable *layerable, layer->children()) - layerable->deselectEvent(0); + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; } + mAxisRect.data()->mouseReleaseEvent(event, startPos); } -/*! - Causes a complete replot into the internal buffer. Finally, update() is called, to redraw the - buffer on the QCustomPlot widget surface. This is the method that must be called to make changes, - for example on the axis ranges or data points of graphs, visible. - - Under a few circumstances, QCustomPlot causes a replot by itself. Those are resize events of the - QCustomPlot widget and user interactions (object selection and range dragging/zooming). - - Before the replot happens, the signal \ref beforeReplot is emitted. After the replot, \ref - afterReplot is emitted. It is safe to mutually connect the replot slot with any of those two - signals on two QCustomPlots to make them replot synchronously, it won't cause an infinite - recursion. -*/ -void QCustomPlot::replot(QCustomPlot::RefreshPriority refreshPriority) +/* inherits documentation from base class */ +void QCPColorScale::wheelEvent(QWheelEvent *event) { - if (mReplotting) // incase signals loop back to replot slot - return; - mReplotting = true; - emit beforeReplot(); - - mPaintBuffer.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent); - QCPPainter painter; - painter.begin(&mPaintBuffer); - if (painter.isActive()) + if (!mAxisRect) { - painter.setRenderHint(QPainter::HighQualityAntialiasing); // to make Antialiasing look good if using the OpenGL graphicssystem - if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush) - painter.fillRect(mViewport, mBackgroundBrush); - draw(&painter); - painter.end(); - if ((refreshPriority == rpHint && mPlottingHints.testFlag(QCP::phForceRepaint)) || refreshPriority==rpImmediate) - repaint(); - else - update(); - } else // might happen if QCustomPlot has width or height zero - qDebug() << Q_FUNC_INFO << "Couldn't activate painter on buffer. This usually happens because QCustomPlot has width or height zero."; - - emit afterReplot(); - mReplotting = false; + qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; + return; + } + mAxisRect.data()->wheelEvent(event); } -/*! - Rescales the axes such that all plottables (like graphs) in the plot are fully visible. +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPColorScaleAxisRectPrivate +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPColorScaleAxisRectPrivate + + \internal + \brief An axis rect subclass for use in a QCPColorScale - if \a onlyVisiblePlottables is set to true, only the plottables that have their visibility set to true - (QCPLayerable::setVisible), will be used to rescale the axes. + This is a private class and not part of the public QCustomPlot interface. - \see QCPAbstractPlottable::rescaleAxes, QCPAxis::rescale + It provides the axis rect functionality for the QCPColorScale class. */ -void QCustomPlot::rescaleAxes(bool onlyVisiblePlottables) -{ - QList allAxes; - foreach (QCPAxisRect *rect, axisRects()) - allAxes << rect->axes(); - - foreach (QCPAxis *axis, allAxes) - axis->rescale(onlyVisiblePlottables); -} -/*! - Saves a PDF with the vectorized plot to the file \a fileName. The axis ratio as well as the scale - of texts and lines will be derived from the specified \a width and \a height. This means, the - output will look like the normal on-screen output of a QCustomPlot widget with the corresponding - pixel width and height. If either \a width or \a height is zero, the exported image will have the - same dimensions as the QCustomPlot widget currently has. - \a noCosmeticPen disables the use of cosmetic pens when drawing to the PDF file. Cosmetic pens - are pens with numerical width 0, which are always drawn as a one pixel wide line, no matter what - zoom factor is set in the PDF-Viewer. For more information about cosmetic pens, see the QPainter - and QPen documentation. - - The objects of the plot will appear in the current selection state. If you don't want any - selected objects to be painted in their selected look, deselect everything with \ref deselectAll - before calling this function. +/*! + Creates a new instance, as a child of \a parentColorScale. +*/ +QCPColorScaleAxisRectPrivate::QCPColorScaleAxisRectPrivate(QCPColorScale *parentColorScale) : + QCPAxisRect(parentColorScale->parentPlot(), true), + mParentColorScale(parentColorScale), + mGradientImageInvalidated(true) +{ + setParentLayerable(parentColorScale); + setMinimumMargins(QMargins(0, 0, 0, 0)); + const QList allAxisTypes = QList() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight; + foreach (QCPAxis::AxisType type, allAxisTypes) + { + axis(type)->setVisible(true); + axis(type)->grid()->setVisible(false); + axis(type)->setPadding(0); + connect(axis(type), SIGNAL(selectionChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectionChanged(QCPAxis::SelectableParts))); + connect(axis(type), SIGNAL(selectableChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectableChanged(QCPAxis::SelectableParts))); + } - Returns true on success. - - \warning - \li If you plan on editing the exported PDF file with a vector graphics editor like - Inkscape, it is advised to set \a noCosmeticPen to true to avoid losing those cosmetic lines - (which might be quite many, because cosmetic pens are the default for e.g. axes and tick marks). - \li If calling this function inside the constructor of the parent of the QCustomPlot widget - (i.e. the MainWindow constructor, if QCustomPlot is inside the MainWindow), always provide - explicit non-zero widths and heights. If you leave \a width or \a height as 0 (default), this - function uses the current width and height of the QCustomPlot widget. However, in Qt, these - aren't defined yet inside the constructor, so you would get an image that has strange - widths/heights. + connect(axis(QCPAxis::atLeft), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atRight), SLOT(setRange(QCPRange))); + connect(axis(QCPAxis::atRight), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atLeft), SLOT(setRange(QCPRange))); + connect(axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atTop), SLOT(setRange(QCPRange))); + connect(axis(QCPAxis::atTop), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atBottom), SLOT(setRange(QCPRange))); + connect(axis(QCPAxis::atLeft), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atRight), SLOT(setScaleType(QCPAxis::ScaleType))); + connect(axis(QCPAxis::atRight), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atLeft), SLOT(setScaleType(QCPAxis::ScaleType))); + connect(axis(QCPAxis::atBottom), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atTop), SLOT(setScaleType(QCPAxis::ScaleType))); + connect(axis(QCPAxis::atTop), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atBottom), SLOT(setScaleType(QCPAxis::ScaleType))); - \a pdfCreator and \a pdfTitle may be used to set the according metadata fields in the resulting - PDF file. + // make layer transfers of color scale transfer to axis rect and axes + // the axes must be set after axis rect, such that they appear above color gradient drawn by axis rect: + connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), this, SLOT(setLayer(QCPLayer*))); + foreach (QCPAxis::AxisType type, allAxisTypes) + connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), axis(type), SLOT(setLayer(QCPLayer*))); +} + +/*! \internal - \note On Android systems, this method does nothing and issues an according qDebug warning - message. This is also the case if for other reasons the define flag QT_NO_PRINTER is set. + Updates the color gradient image if necessary, by calling \ref updateGradientImage, then draws + it. Then the axes are drawn by calling the \ref QCPAxisRect::draw base class implementation. - \see savePng, saveBmp, saveJpg, saveRastered + \seebaseclassmethod */ -bool QCustomPlot::savePdf(const QString &fileName, bool noCosmeticPen, int width, int height, const QString &pdfCreator, const QString &pdfTitle) +void QCPColorScaleAxisRectPrivate::draw(QCPPainter *painter) { - bool success = false; -#ifdef QT_NO_PRINTER - Q_UNUSED(fileName) - Q_UNUSED(noCosmeticPen) - Q_UNUSED(width) - Q_UNUSED(height) - Q_UNUSED(pdfCreator) - Q_UNUSED(pdfTitle) - qDebug() << Q_FUNC_INFO << "Qt was built without printer support (QT_NO_PRINTER). PDF not created."; -#else - int newWidth, newHeight; - if (width == 0 || height == 0) - { - newWidth = this->width(); - newHeight = this->height(); - } else - { - newWidth = width; - newHeight = height; - } + if (mGradientImageInvalidated) + updateGradientImage(); - QPrinter printer(QPrinter::ScreenResolution); - printer.setOutputFileName(fileName); - printer.setOutputFormat(QPrinter::PdfFormat); - printer.setColorMode(QPrinter::Color); - printer.printEngine()->setProperty(QPrintEngine::PPK_Creator, pdfCreator); - printer.printEngine()->setProperty(QPrintEngine::PPK_DocumentName, pdfTitle); - QRect oldViewport = viewport(); - setViewport(QRect(0, 0, newWidth, newHeight)); -#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0) - printer.setFullPage(true); - printer.setPaperSize(viewport().size(), QPrinter::DevicePixel); -#else - QPageLayout pageLayout; - pageLayout.setMode(QPageLayout::FullPageMode); - pageLayout.setOrientation(QPageLayout::Portrait); - pageLayout.setMargins(QMarginsF(0, 0, 0, 0)); - pageLayout.setPageSize(QPageSize(viewport().size(), QPageSize::Point, QString(), QPageSize::ExactMatch)); - printer.setPageLayout(pageLayout); -#endif - QCPPainter printpainter; - if (printpainter.begin(&printer)) + bool mirrorHorz = false; + bool mirrorVert = false; + if (mParentColorScale->mColorAxis) { - printpainter.setMode(QCPPainter::pmVectorized); - printpainter.setMode(QCPPainter::pmNoCaching); - printpainter.setMode(QCPPainter::pmNonCosmetic, noCosmeticPen); - printpainter.setWindow(mViewport); - if (mBackgroundBrush.style() != Qt::NoBrush && - mBackgroundBrush.color() != Qt::white && - mBackgroundBrush.color() != Qt::transparent && - mBackgroundBrush.color().alpha() > 0) // draw pdf background color if not white/transparent - printpainter.fillRect(viewport(), mBackgroundBrush); - draw(&printpainter); - printpainter.end(); - success = true; + mirrorHorz = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atBottom || mParentColorScale->type() == QCPAxis::atTop); + mirrorVert = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atLeft || mParentColorScale->type() == QCPAxis::atRight); } - setViewport(oldViewport); -#endif // QT_NO_PRINTER - return success; + + painter->drawImage(rect().adjusted(0, -1, 0, -1), mGradientImage.mirrored(mirrorHorz, mirrorVert)); + QCPAxisRect::draw(painter); } -/*! - Saves a PNG image file to \a fileName on disc. The output plot will have the dimensions \a width - and \a height in pixels. If either \a width or \a height is zero, the exported image will have - the same dimensions as the QCustomPlot widget currently has. Line widths and texts etc. are not - scaled up when larger widths/heights are used. If you want that effect, use the \a scale parameter. +/*! \internal - For example, if you set both \a width and \a height to 100 and \a scale to 2, you will end up with an - image file of size 200*200 in which all graphical elements are scaled up by factor 2 (line widths, - texts, etc.). This scaling is not done by stretching a 100*100 image, the result will have full - 200*200 pixel resolution. + Uses the current gradient of the parent \ref QCPColorScale (specified in the constructor) to + generate a gradient image. This gradient image will be used in the \ref draw method. +*/ +void QCPColorScaleAxisRectPrivate::updateGradientImage() +{ + if (rect().isEmpty()) + return; - If you use a high scaling factor, it is recommended to enable antialiasing for all elements via - temporarily setting \ref QCustomPlot::setAntialiasedElements to \ref QCP::aeAll as this allows - QCustomPlot to place objects with sub-pixel accuracy. + const QImage::Format format = QImage::Format_ARGB32_Premultiplied; + int n = mParentColorScale->mGradient.levelCount(); + int w, h; + QVector data(n); + for (int i=0; imType == QCPAxis::atBottom || mParentColorScale->mType == QCPAxis::atTop) + { + w = n; + h = rect().height(); + mGradientImage = QImage(w, h, format); + QVector pixels; + for (int y=0; y(mGradientImage.scanLine(y))); + mParentColorScale->mGradient.colorize(data.constData(), QCPRange(0, n-1), pixels.first(), n); + for (int y=1; y(mGradientImage.scanLine(y)); + const QRgb lineColor = mParentColorScale->mGradient.color(data[h-1-y], QCPRange(0, n-1)); + for (int x=0; x allAxisTypes = QList() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight; + foreach (QCPAxis::AxisType type, allAxisTypes) + { + if (QCPAxis *senderAxis = qobject_cast(sender())) + if (senderAxis->axisType() == type) + continue; + + if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis)) + { + if (selectedParts.testFlag(QCPAxis::spAxis)) + axis(type)->setSelectedParts(axis(type)->selectedParts() | QCPAxis::spAxis); + else + axis(type)->setSelectedParts(axis(type)->selectedParts() & ~QCPAxis::spAxis); + } + } +} - PNG compression can be controlled with the \a quality parameter which must be between 0 and 100 or - -1 to use the default setting. - - Returns true on success. If this function fails, most likely the PNG format isn't supported by - the system, see Qt docs about QImageWriter::supportedImageFormats(). +/*! \internal - \see savePdf, saveBmp, saveJpg, saveRastered + This slot is connected to the selectableChanged signals of the four axes in the constructor. It + synchronizes the selectability of the axes. */ -bool QCustomPlot::savePng(const QString &fileName, int width, int height, double scale, int quality) +void QCPColorScaleAxisRectPrivate::axisSelectableChanged(QCPAxis::SelectableParts selectableParts) { - return saveRastered(fileName, width, height, scale, "PNG", quality); + // synchronize axis base selectability: + const QList allAxisTypes = QList() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight; + foreach (QCPAxis::AxisType type, allAxisTypes) + { + if (QCPAxis *senderAxis = qobject_cast(sender())) + if (senderAxis->axisType() == type) + continue; + + if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis)) + { + if (selectableParts.testFlag(QCPAxis::spAxis)) + axis(type)->setSelectableParts(axis(type)->selectableParts() | QCPAxis::spAxis); + else + axis(type)->setSelectableParts(axis(type)->selectableParts() & ~QCPAxis::spAxis); + } + } } +/* end of 'src/layoutelements/layoutelement-colorscale.cpp' */ -/*! - Saves a JPG image file to \a fileName on disc. The output plot will have the dimensions \a width - and \a height in pixels. If either \a width or \a height is zero, the exported image will have - the same dimensions as the QCustomPlot widget currently has. Line widths and texts etc. are not - scaled up when larger widths/heights are used. If you want that effect, use the \a scale parameter. - - For example, if you set both \a width and \a height to 100 and \a scale to 2, you will end up with an - image file of size 200*200 in which all graphical elements are scaled up by factor 2 (line widths, - texts, etc.). This scaling is not done by stretching a 100*100 image, the result will have full - 200*200 pixel resolution. - - If you use a high scaling factor, it is recommended to enable antialiasing for all elements via - temporarily setting \ref QCustomPlot::setAntialiasedElements to \ref QCP::aeAll as this allows - QCustomPlot to place objects with sub-pixel accuracy. - \warning If calling this function inside the constructor of the parent of the QCustomPlot widget - (i.e. the MainWindow constructor, if QCustomPlot is inside the MainWindow), always provide - explicit non-zero widths and heights. If you leave \a width or \a height as 0 (default), this - function uses the current width and height of the QCustomPlot widget. However, in Qt, these - aren't defined yet inside the constructor, so you would get an image that has strange - widths/heights. +/* including file 'src/plottables/plottable-graph.cpp' */ +/* modified 2022-11-06T12:45:57, size 74926 */ - The objects of the plot will appear in the current selection state. If you don't want any selected - objects to be painted in their selected look, deselect everything with \ref deselectAll before calling - this function. +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPGraphData +//////////////////////////////////////////////////////////////////////////////////////////////////// - JPG compression can be controlled with the \a quality parameter which must be between 0 and 100 or - -1 to use the default setting. +/*! \class QCPGraphData + \brief Holds the data of one single data point for QCPGraph. - Returns true on success. If this function fails, most likely the JPG format isn't supported by - the system, see Qt docs about QImageWriter::supportedImageFormats(). - - \see savePdf, savePng, saveBmp, saveRastered + The stored data is: + \li \a key: coordinate on the key axis of this data point (this is the \a mainKey and the \a sortKey) + \li \a value: coordinate on the value axis of this data point (this is the \a mainValue) + + The container for storing multiple data points is \ref QCPGraphDataContainer. It is a typedef for + \ref QCPDataContainer with \ref QCPGraphData as the DataType template parameter. See the + documentation there for an explanation regarding the data type's generic methods. + + \see QCPGraphDataContainer */ -bool QCustomPlot::saveJpg(const QString &fileName, int width, int height, double scale, int quality) -{ - return saveRastered(fileName, width, height, scale, "JPG", quality); -} -/*! - Saves a BMP image file to \a fileName on disc. The output plot will have the dimensions \a width - and \a height in pixels. If either \a width or \a height is zero, the exported image will have - the same dimensions as the QCustomPlot widget currently has. Line widths and texts etc. are not - scaled up when larger widths/heights are used. If you want that effect, use the \a scale parameter. +/* start documentation of inline functions */ - For example, if you set both \a width and \a height to 100 and \a scale to 2, you will end up with an - image file of size 200*200 in which all graphical elements are scaled up by factor 2 (line widths, - texts, etc.). This scaling is not done by stretching a 100*100 image, the result will have full - 200*200 pixel resolution. +/*! \fn double QCPGraphData::sortKey() const - If you use a high scaling factor, it is recommended to enable antialiasing for all elements via - temporarily setting \ref QCustomPlot::setAntialiasedElements to \ref QCP::aeAll as this allows - QCustomPlot to place objects with sub-pixel accuracy. + Returns the \a key member of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ - \warning If calling this function inside the constructor of the parent of the QCustomPlot widget - (i.e. the MainWindow constructor, if QCustomPlot is inside the MainWindow), always provide - explicit non-zero widths and heights. If you leave \a width or \a height as 0 (default), this - function uses the current width and height of the QCustomPlot widget. However, in Qt, these - aren't defined yet inside the constructor, so you would get an image that has strange - widths/heights. +/*! \fn static QCPGraphData QCPGraphData::fromSortKey(double sortKey) + + Returns a data point with the specified \a sortKey. All other members are set to zero. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ - The objects of the plot will appear in the current selection state. If you don't want any selected - objects to be painted in their selected look, deselect everything with \ref deselectAll before calling - this function. +/*! \fn static static bool QCPGraphData::sortKeyIsMainKey() - Returns true on success. If this function fails, most likely the BMP format isn't supported by - the system, see Qt docs about QImageWriter::supportedImageFormats(). + Since the member \a key is both the data point key coordinate and the data ordering parameter, + this method returns true. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ - \see savePdf, savePng, saveJpg, saveRastered +/*! \fn double QCPGraphData::mainKey() const + + Returns the \a key member of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -bool QCustomPlot::saveBmp(const QString &fileName, int width, int height, double scale) -{ - return saveRastered(fileName, width, height, scale, "BMP"); -} -/*! \internal +/*! \fn double QCPGraphData::mainValue() const - Returns a minimum size hint that corresponds to the minimum size of the top level layout - (\ref plotLayout). To prevent QCustomPlot from being collapsed to size/width zero, set a minimum - size (setMinimumSize) either on the whole QCustomPlot or on any layout elements inside the plot. - This is especially important, when placed in a QLayout where other components try to take in as - much space as possible (e.g. QMdiArea). + Returns the \a value member of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -QSize QCustomPlot::minimumSizeHint() const -{ - return mPlotLayout->minimumSizeHint(); -} -/*! \internal +/*! \fn QCPRange QCPGraphData::valueRange() const - Returns a size hint that is the same as \ref minimumSizeHint. + Returns a QCPRange with both lower and upper boundary set to \a value of this data point. + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -QSize QCustomPlot::sizeHint() const -{ - return mPlotLayout->minimumSizeHint(); -} -/*! \internal - - Event handler for when the QCustomPlot widget needs repainting. This does not cause a \ref replot, but - draws the internal buffer on the widget surface. +/* end documentation of inline functions */ + +/*! + Constructs a data point with key and value set to zero. */ -void QCustomPlot::paintEvent(QPaintEvent *event) +QCPGraphData::QCPGraphData() : + key(0), + value(0) { - Q_UNUSED(event); - QPainter painter(this); - painter.drawPixmap(0, 0, mPaintBuffer); } -/*! \internal - - Event handler for a resize of the QCustomPlot widget. Causes the internal buffer to be resized to - the new size. The viewport (which becomes the outer rect of mPlotLayout) is resized - appropriately. Finally a \ref replot is performed. +/*! + Constructs a data point with the specified \a key and \a value. */ -void QCustomPlot::resizeEvent(QResizeEvent *event) +QCPGraphData::QCPGraphData(double key, double value) : + key(key), + value(value) { - // resize and repaint the buffer: - mPaintBuffer = QPixmap(event->size()); - setViewport(rect()); - replot(rpQueued); // queued update is important here, to prevent painting issues in some contexts } -/*! \internal + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPGraph +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPGraph + \brief A plottable representing a graph in a plot. + + \image html QCPGraph.png - Event handler for when a double click occurs. Emits the \ref mouseDoubleClick signal, then emits - the specialized signals when certain objecs are clicked (e.g. \ref plottableDoubleClick, \ref - axisDoubleClick, etc.). Finally determines the affected layout element and forwards the event to - it. - - \see mousePressEvent, mouseReleaseEvent -*/ -void QCustomPlot::mouseDoubleClickEvent(QMouseEvent *event) -{ - emit mouseDoubleClick(event); + Usually you create new graphs by calling QCustomPlot::addGraph. The resulting instance can be + accessed via QCustomPlot::graph. + + To plot data, assign it with the \ref setData or \ref addData functions. Alternatively, you can + also access and modify the data via the \ref data method, which returns a pointer to the internal + \ref QCPGraphDataContainer. - QVariant details; - QCPLayerable *clickedLayerable = layerableAt(event->pos(), false, &details); + Graphs are used to display single-valued data. Single-valued means that there should only be one + data point per unique key coordinate. In other words, the graph can't have \a loops. If you do + want to plot non-single-valued curves, rather use the QCPCurve plottable. - // emit specialized object double click signals: - if (QCPAbstractPlottable *ap = qobject_cast(clickedLayerable)) - emit plottableDoubleClick(ap, event); - else if (QCPAxis *ax = qobject_cast(clickedLayerable)) - emit axisDoubleClick(ax, details.value(), event); - else if (QCPAbstractItem *ai = qobject_cast(clickedLayerable)) - emit itemDoubleClick(ai, event); - else if (QCPLegend *lg = qobject_cast(clickedLayerable)) - emit legendDoubleClick(lg, 0, event); - else if (QCPAbstractLegendItem *li = qobject_cast(clickedLayerable)) - emit legendDoubleClick(li->parentLegend(), li, event); - else if (QCPPlotTitle *pt = qobject_cast(clickedLayerable)) - emit titleDoubleClick(event, pt); + Gaps in the graph line can be created by adding data points with NaN as value + (qQNaN() or std::numeric_limits::quiet_NaN()) in between the two data points that shall be + separated. - // call double click event of affected layout element: - if (QCPLayoutElement *el = layoutElementAt(event->pos())) - el->mouseDoubleClickEvent(event); + \section qcpgraph-appearance Changing the appearance - // call release event of affected layout element (as in mouseReleaseEvent, since the mouseDoubleClick replaces the second release event in double click case): - if (mMouseEventElement) - { - mMouseEventElement->mouseReleaseEvent(event); - mMouseEventElement = 0; - } + The appearance of the graph is mainly determined by the line style, scatter style, brush and pen + of the graph (\ref setLineStyle, \ref setScatterStyle, \ref setBrush, \ref setPen). - //QWidget::mouseDoubleClickEvent(event); don't call base class implementation because it would just cause a mousePress/ReleaseEvent, which we don't want. -} - -/*! \internal + \subsection filling Filling under or between graphs - Event handler for when a mouse button is pressed. Emits the mousePress signal. Then determines - the affected layout element and forwards the event to it. + QCPGraph knows two types of fills: Normal graph fills towards the zero-value-line parallel to + the key axis of the graph, and fills between two graphs, called channel fills. To enable a fill, + just set a brush with \ref setBrush which is neither Qt::NoBrush nor fully transparent. - \see mouseMoveEvent, mouseReleaseEvent + By default, a normal fill towards the zero-value-line will be drawn. To set up a channel fill + between this graph and another one, call \ref setChannelFillGraph with the other graph as + parameter. + + \see QCustomPlot::addGraph, QCustomPlot::graph */ -void QCustomPlot::mousePressEvent(QMouseEvent *event) -{ - emit mousePress(event); - mMousePressPos = event->pos(); // need this to determine in releaseEvent whether it was a click (no position change between press and release) - - // call event of affected layout element: - mMouseEventElement = layoutElementAt(event->pos()); - if (mMouseEventElement) - mMouseEventElement->mousePressEvent(event); - - QWidget::mousePressEvent(event); -} -/*! \internal +/* start of documentation of inline functions */ + +/*! \fn QSharedPointer QCPGraph::data() const - Event handler for when the cursor is moved. Emits the \ref mouseMove signal. + Returns a shared pointer to the internal data storage of type \ref QCPGraphDataContainer. You may + use it to directly manipulate the data, which may be more convenient and faster than using the + regular \ref setData or \ref addData methods. +*/ + +/* end of documentation of inline functions */ - If a layout element has mouse capture focus (a mousePressEvent happened on top of the layout - element before), the mouseMoveEvent is forwarded to that element. +/*! + Constructs a graph which uses \a keyAxis as its key axis ("x") and \a valueAxis as its value + axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and not have + the same orientation. If either of these restrictions is violated, a corresponding message is + printed to the debug output (qDebug), the construction is not aborted, though. - \see mousePressEvent, mouseReleaseEvent + The created QCPGraph is automatically registered with the QCustomPlot instance inferred from \a + keyAxis. This QCustomPlot instance takes ownership of the QCPGraph, so do not delete it manually + but use QCustomPlot::removePlottable() instead. + + To directly create a graph inside a plot, you can also use the simpler QCustomPlot::addGraph function. */ -void QCustomPlot::mouseMoveEvent(QMouseEvent *event) +QCPGraph::QCPGraph(QCPAxis *keyAxis, QCPAxis *valueAxis) : + QCPAbstractPlottable1D(keyAxis, valueAxis), + mLineStyle{}, + mScatterSkip{}, + mAdaptiveSampling{} { - emit mouseMove(event); + // special handling for QCPGraphs to maintain the simple graph interface: + mParentPlot->registerGraph(this); - // call event of affected layout element: - if (mMouseEventElement) - mMouseEventElement->mouseMoveEvent(event); + setPen(QPen(Qt::blue, 0)); + setBrush(Qt::NoBrush); - QWidget::mouseMoveEvent(event); + setLineStyle(lsLine); + setScatterSkip(0); + setChannelFillGraph(nullptr); + setAdaptiveSampling(true); } -/*! \internal +QCPGraph::~QCPGraph() +{ +} + +/*! \overload - Event handler for when a mouse button is released. Emits the \ref mouseRelease signal. + Replaces the current data container with the provided \a data container. - If the mouse was moved less than a certain threshold in any direction since the \ref - mousePressEvent, it is considered a click which causes the selection mechanism (if activated via - \ref setInteractions) to possibly change selection states accordingly. Further, specialized mouse - click signals are emitted (e.g. \ref plottableClick, \ref axisClick, etc.) + Since a QSharedPointer is used, multiple QCPGraphs may share the same data container safely. + Modifying the data in the container will then affect all graphs that share the container. Sharing + can be achieved by simply exchanging the data containers wrapped in shared pointers: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpgraph-datasharing-1 - If a layout element has mouse capture focus (a \ref mousePressEvent happened on top of the layout - element before), the \ref mouseReleaseEvent is forwarded to that element. + If you do not wish to share containers, but create a copy from an existing container, rather use + the \ref QCPDataContainer::set method on the graph's data container directly: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpgraph-datasharing-2 - \see mousePressEvent, mouseMoveEvent + \see addData */ -void QCustomPlot::mouseReleaseEvent(QMouseEvent *event) +void QCPGraph::setData(QSharedPointer data) { - emit mouseRelease(event); - bool doReplot = false; - - if ((mMousePressPos-event->pos()).manhattanLength() < 5) // determine whether it was a click operation - { - if (event->button() == Qt::LeftButton) - { - // handle selection mechanism: - QVariant details; - QCPLayerable *clickedLayerable = layerableAt(event->pos(), true, &details); - bool selectionStateChanged = false; - bool additive = mInteractions.testFlag(QCP::iMultiSelect) && event->modifiers().testFlag(mMultiSelectModifier); - // deselect all other layerables if not additive selection: - if (!additive) - { - foreach (QCPLayer *layer, mLayers) - { - foreach (QCPLayerable *layerable, layer->children()) - { - if (layerable != clickedLayerable && mInteractions.testFlag(layerable->selectionCategory())) - { - bool selChanged = false; - layerable->deselectEvent(&selChanged); - selectionStateChanged |= selChanged; - } - } - } - } - if (clickedLayerable && mInteractions.testFlag(clickedLayerable->selectionCategory())) - { - // a layerable was actually clicked, call its selectEvent: - bool selChanged = false; - clickedLayerable->selectEvent(event, additive, details, &selChanged); - selectionStateChanged |= selChanged; - } - if (selectionStateChanged) - { - doReplot = true; - emit selectionChangedByUser(); - } - } - - // emit specialized object click signals: - QVariant details; - QCPLayerable *clickedLayerable = layerableAt(event->pos(), false, &details); // for these signals, selectability is ignored, that's why we call this again with onlySelectable set to false - if (QCPAbstractPlottable *ap = qobject_cast(clickedLayerable)) - emit plottableClick(ap, event); - else if (QCPAxis *ax = qobject_cast(clickedLayerable)) - emit axisClick(ax, details.value(), event); - else if (QCPAbstractItem *ai = qobject_cast(clickedLayerable)) - emit itemClick(ai, event); - else if (QCPLegend *lg = qobject_cast(clickedLayerable)) - emit legendClick(lg, 0, event); - else if (QCPAbstractLegendItem *li = qobject_cast(clickedLayerable)) - emit legendClick(li->parentLegend(), li, event); - else if (QCPPlotTitle *pt = qobject_cast(clickedLayerable)) - emit titleClick(event, pt); - } - - // call event of affected layout element: - if (mMouseEventElement) - { - mMouseEventElement->mouseReleaseEvent(event); - mMouseEventElement = 0; - } - - if (doReplot || noAntialiasingOnDrag()) - replot(); - - QWidget::mouseReleaseEvent(event); + mDataContainer = data; } -/*! \internal +/*! \overload - Event handler for mouse wheel events. First, the \ref mouseWheel signal is emitted. Then - determines the affected layout element and forwards the event to it. + Replaces the current data with the provided points in \a keys and \a values. The provided + vectors should have equal length. Else, the number of added points will be the size of the + smallest vector. + + If you can guarantee that the passed data points are sorted by \a keys in ascending order, you + can set \a alreadySorted to true, to improve performance by saving a sorting run. + \see addData */ -void QCustomPlot::wheelEvent(QWheelEvent *event) +void QCPGraph::setData(const QVector &keys, const QVector &values, bool alreadySorted) { - emit mouseWheel(event); - - // call event of affected layout element: - if (QCPLayoutElement *el = layoutElementAt(event->pos())) - el->wheelEvent(event); - - QWidget::wheelEvent(event); + mDataContainer->clear(); + addData(keys, values, alreadySorted); } -/*! \internal +/*! + Sets how the single data points are connected in the plot. For scatter-only plots, set \a ls to + \ref lsNone and \ref setScatterStyle to the desired scatter style. - This is the main draw function. It draws the entire plot, including background pixmap, with the - specified \a painter. Note that it does not fill the background with the background brush (as the - user may specify with \ref setBackground(const QBrush &brush)), this is up to the respective - functions calling this method (e.g. \ref replot, \ref toPixmap and \ref toPainter). + \see setScatterStyle */ -void QCustomPlot::draw(QCPPainter *painter) +void QCPGraph::setLineStyle(LineStyle ls) { - // run through layout phases: - mPlotLayout->update(QCPLayoutElement::upPreparation); - mPlotLayout->update(QCPLayoutElement::upMargins); - mPlotLayout->update(QCPLayoutElement::upLayout); - - // draw viewport background pixmap: - drawBackground(painter); - - // draw all layered objects (grid, axes, plottables, items, legend,...): - foreach (QCPLayer *layer, mLayers) - { - foreach (QCPLayerable *child, layer->children()) - { - if (child->realVisibility()) - { - painter->save(); - painter->setClipRect(child->clipRect().translated(0, -1)); - child->applyDefaultAntialiasingHint(painter); - child->draw(painter); - painter->restore(); - } - } - } - - /* Debug code to draw all layout element rects - foreach (QCPLayoutElement* el, findChildren()) - { - painter->setBrush(Qt::NoBrush); - painter->setPen(QPen(QColor(0, 0, 0, 100), 0, Qt::DashLine)); - painter->drawRect(el->rect()); - painter->setPen(QPen(QColor(255, 0, 0, 100), 0, Qt::DashLine)); - painter->drawRect(el->outerRect()); - } - */ + mLineStyle = ls; } -/*! \internal - - Draws the viewport background pixmap of the plot. - - If a pixmap was provided via \ref setBackground, this function buffers the scaled version - depending on \ref setBackgroundScaled and \ref setBackgroundScaledMode and then draws it inside - the viewport with the provided \a painter. The scaled version is buffered in - mScaledBackgroundPixmap to prevent expensive rescaling at every redraw. It is only updated, when - the axis rect has changed in a way that requires a rescale of the background pixmap (this is - dependent on the \ref setBackgroundScaledMode), or when a differend axis background pixmap was - set. - - Note that this function does not draw a fill with the background brush (\ref setBackground(const - QBrush &brush)) beneath the pixmap. +/*! + Sets the visual appearance of single data points in the plot. If set to \ref QCPScatterStyle::ssNone, no scatter points + are drawn (e.g. for line-only-plots with appropriate line style). - \see setBackground, setBackgroundScaled, setBackgroundScaledMode + \see QCPScatterStyle, setLineStyle */ -void QCustomPlot::drawBackground(QCPPainter *painter) +void QCPGraph::setScatterStyle(const QCPScatterStyle &style) { - // Note: background color is handled in individual replot/save functions - - // draw background pixmap (on top of fill, if brush specified): - if (!mBackgroundPixmap.isNull()) - { - if (mBackgroundScaled) - { - // check whether mScaledBackground needs to be updated: - QSize scaledSize(mBackgroundPixmap.size()); - scaledSize.scale(mViewport.size(), mBackgroundScaledMode); - if (mScaledBackgroundPixmap.size() != scaledSize) - mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mViewport.size(), mBackgroundScaledMode, Qt::SmoothTransformation); - painter->drawPixmap(mViewport.topLeft(), mScaledBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height()) & mScaledBackgroundPixmap.rect()); - } else - { - painter->drawPixmap(mViewport.topLeft(), mBackgroundPixmap, QRect(0, 0, mViewport.width(), mViewport.height())); - } - } + mScatterStyle = style; } +/*! + If scatters are displayed (scatter style not \ref QCPScatterStyle::ssNone), \a skip number of + scatter points are skipped/not drawn after every drawn scatter point. -/*! \internal + This can be used to make the data appear sparser while for example still having a smooth line, + and to improve performance for very high density plots. + + If \a skip is set to 0 (default), all scatter points are drawn. + + \see setScatterStyle +*/ +void QCPGraph::setScatterSkip(int skip) +{ + mScatterSkip = qMax(0, skip); +} + +/*! + Sets the target graph for filling the area between this graph and \a targetGraph with the current + brush (\ref setBrush). - This method is used by \ref QCPAxisRect::removeAxis to report removed axes to the QCustomPlot - so it may clear its QCustomPlot::xAxis, yAxis, xAxis2 and yAxis2 members accordingly. + When \a targetGraph is set to 0, a normal graph fill to the zero-value-line will be shown. To + disable any filling, set the brush to Qt::NoBrush. + + \see setBrush */ -void QCustomPlot::axisRemoved(QCPAxis *axis) +void QCPGraph::setChannelFillGraph(QCPGraph *targetGraph) { - if (xAxis == axis) - xAxis = 0; - if (xAxis2 == axis) - xAxis2 = 0; - if (yAxis == axis) - yAxis = 0; - if (yAxis2 == axis) - yAxis2 = 0; + // prevent setting channel target to this graph itself: + if (targetGraph == this) + { + qDebug() << Q_FUNC_INFO << "targetGraph is this graph itself"; + mChannelFillGraph = nullptr; + return; + } + // prevent setting channel target to a graph not in the plot: + if (targetGraph && targetGraph->mParentPlot != mParentPlot) + { + qDebug() << Q_FUNC_INFO << "targetGraph not in same plot"; + mChannelFillGraph = nullptr; + return; + } - // Note: No need to take care of range drag axes and range zoom axes, because they are stored in smart pointers + mChannelFillGraph = targetGraph; } -/*! \internal +/*! + Sets whether adaptive sampling shall be used when plotting this graph. QCustomPlot's adaptive + sampling technique can drastically improve the replot performance for graphs with a larger number + of points (e.g. above 10,000), without notably changing the appearance of the graph. - This method is used by the QCPLegend destructor to report legend removal to the QCustomPlot so - it may clear its QCustomPlot::legend member accordingly. -*/ -void QCustomPlot::legendRemoved(QCPLegend *legend) -{ - if (this->legend == legend) - this->legend = 0; -} - -/*! \internal + By default, adaptive sampling is enabled. Even if enabled, QCustomPlot decides whether adaptive + sampling shall actually be used on a per-graph basis. So leaving adaptive sampling enabled has no + disadvantage in almost all cases. - Assigns all layers their index (QCPLayer::mIndex) in the mLayers list. This method is thus called - after every operation that changes the layer indices, like layer removal, layer creation, layer - moving. + \image html adaptive-sampling-line.png "A line plot of 500,000 points without and with adaptive sampling" + + As can be seen, line plots experience no visual degradation from adaptive sampling. Outliers are + reproduced reliably, as well as the overall shape of the data set. The replot time reduces + dramatically though. This allows QCustomPlot to display large amounts of data in realtime. + + \image html adaptive-sampling-scatter.png "A scatter plot of 100,000 points without and with adaptive sampling" + + Care must be taken when using high-density scatter plots in combination with adaptive sampling. + The adaptive sampling algorithm treats scatter plots more carefully than line plots which still + gives a significant reduction of replot times, but not quite as much as for line plots. This is + because scatter plots inherently need more data points to be preserved in order to still resemble + the original, non-adaptive-sampling plot. As shown above, the results still aren't quite + identical, as banding occurs for the outer data points. This is in fact intentional, such that + the boundaries of the data cloud stay visible to the viewer. How strong the banding appears, + depends on the point density, i.e. the number of points in the plot. + + For some situations with scatter plots it might thus be desirable to manually turn adaptive + sampling off. For example, when saving the plot to disk. This can be achieved by setting \a + enabled to false before issuing a command like \ref QCustomPlot::savePng, and setting \a enabled + back to true afterwards. */ -void QCustomPlot::updateLayerIndices() const +void QCPGraph::setAdaptiveSampling(bool enabled) { - for (int i=0; imIndex = i; + mAdaptiveSampling = enabled; } -/*! \internal +/*! \overload - Returns the layerable at pixel position \a pos. If \a onlySelectable is set to true, only those - layerables that are selectable will be considered. (Layerable subclasses communicate their - selectability via the QCPLayerable::selectTest method, by returning -1.) - - \a selectionDetails is an output parameter that contains selection specifics of the affected - layerable. This is useful if the respective layerable shall be given a subsequent - QCPLayerable::selectEvent (like in \ref mouseReleaseEvent). \a selectionDetails usually contains - information about which part of the layerable was hit, in multi-part layerables (e.g. - QCPAxis::SelectablePart). + Adds the provided points in \a keys and \a values to the current data. The provided vectors + should have equal length. Else, the number of added points will be the size of the smallest + vector. + + If you can guarantee that the passed data points are sorted by \a keys in ascending order, you + can set \a alreadySorted to true, to improve performance by saving a sorting run. + + Alternatively, you can also access and modify the data directly via the \ref data method, which + returns a pointer to the internal data container. */ -QCPLayerable *QCustomPlot::layerableAt(const QPointF &pos, bool onlySelectable, QVariant *selectionDetails) const +void QCPGraph::addData(const QVector &keys, const QVector &values, bool alreadySorted) { - for (int layerIndex=mLayers.size()-1; layerIndex>=0; --layerIndex) + if (keys.size() != values.size()) + qDebug() << Q_FUNC_INFO << "keys and values have different sizes:" << keys.size() << values.size(); + const int n = qMin(keys.size(), values.size()); + QVector tempData(n); + QVector::iterator it = tempData.begin(); + const QVector::iterator itEnd = tempData.end(); + int i = 0; + while (it != itEnd) { - const QList layerables = mLayers.at(layerIndex)->children(); - double minimumDistance = selectionTolerance()*1.1; - QCPLayerable *minimumDistanceLayerable = 0; - for (int i=layerables.size()-1; i>=0; --i) - { - if (!layerables.at(i)->realVisibility()) - continue; - QVariant details; - double dist = layerables.at(i)->selectTest(pos, onlySelectable, &details); - if (dist >= 0 && dist < minimumDistance) - { - minimumDistance = dist; - minimumDistanceLayerable = layerables.at(i); - if (selectionDetails) *selectionDetails = details; - } - } - if (minimumDistance < selectionTolerance()) - return minimumDistanceLayerable; + it->key = keys[i]; + it->value = values[i]; + ++it; + ++i; } - return 0; + mDataContainer->add(tempData, alreadySorted); // don't modify tempData beyond this to prevent copy on write } -/*! - Saves the plot to a rastered image file \a fileName in the image format \a format. The plot is - sized to \a width and \a height in pixels and scaled with \a scale. (width 100 and scale 2.0 lead - to a full resolution file with width 200.) If the \a format supports compression, \a quality may - be between 0 and 100 to control it. +/*! \overload - Returns true on success. If this function fails, most likely the given \a format isn't supported - by the system, see Qt docs about QImageWriter::supportedImageFormats(). + Adds the provided data point as \a key and \a value to the current data. - \see saveBmp, saveJpg, savePng, savePdf + Alternatively, you can also access and modify the data directly via the \ref data method, which + returns a pointer to the internal data container. */ -bool QCustomPlot::saveRastered(const QString &fileName, int width, int height, double scale, const char *format, int quality) +void QCPGraph::addData(double key, double value) { - QPixmap buffer = toPixmap(width, height, scale); - if (!buffer.isNull()) - return buffer.save(fileName, format, quality); - else - return false; + mDataContainer->add(QCPGraphData(key, value)); } /*! - Renders the plot to a pixmap and returns it. - - The plot is sized to \a width and \a height in pixels and scaled with \a scale. (width 100 and - scale 2.0 lead to a full resolution pixmap with width 200.) + Implements a selectTest specific to this plottable's point geometry. + + If \a details is not 0, it will be set to a \ref QCPDataSelection, describing the closest data + point to \a pos. - \see toPainter, saveRastered, saveBmp, savePng, saveJpg, savePdf + \seebaseclassmethod \ref QCPAbstractPlottable::selectTest */ -QPixmap QCustomPlot::toPixmap(int width, int height, double scale) +double QCPGraph::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - // this method is somewhat similar to toPainter. Change something here, and a change in toPainter might be necessary, too. - int newWidth, newHeight; - if (width == 0 || height == 0) + if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty()) + return -1; + if (!mKeyAxis || !mValueAxis) + return -1; + + if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect)) { - newWidth = this->width(); - newHeight = this->height(); + QCPGraphDataContainer::const_iterator closestDataPoint = mDataContainer->constEnd(); + double result = pointDistance(pos, closestDataPoint); + if (details) + { + int pointIndex = int(closestDataPoint-mDataContainer->constBegin()); + details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1))); + } + return result; } else - { - newWidth = width; - newHeight = height; - } - int scaledWidth = qRound(scale*newWidth); - int scaledHeight = qRound(scale*newHeight); + return -1; +} - QPixmap result(scaledWidth, scaledHeight); - result.fill(mBackgroundBrush.style() == Qt::SolidPattern ? mBackgroundBrush.color() : Qt::transparent); // if using non-solid pattern, make transparent now and draw brush pattern later - QCPPainter painter; - painter.begin(&result); - if (painter.isActive()) +/* inherits documentation from base class */ +QCPRange QCPGraph::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const +{ + return mDataContainer->keyRange(foundRange, inSignDomain); +} + +/* inherits documentation from base class */ +QCPRange QCPGraph::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const +{ + return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange); +} + +/* inherits documentation from base class */ +void QCPGraph::draw(QCPPainter *painter) +{ + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + if (mKeyAxis.data()->range().size() <= 0 || mDataContainer->isEmpty()) return; + if (mLineStyle == lsNone && mScatterStyle.isNone()) return; + + QVector lines, scatters; // line and (if necessary) scatter pixel coordinates will be stored here while iterating over segments + + // loop over and draw segments of unselected/selected data: + QList selectedSegments, unselectedSegments, allSegments; + getDataSegments(selectedSegments, unselectedSegments); + allSegments << unselectedSegments << selectedSegments; + for (int i=0; i= unselectedSegments.size(); + // get line pixel points appropriate to line style: + QCPDataRange lineDataRange = isSelectedSegment ? allSegments.at(i) : allSegments.at(i).adjusted(-1, 1); // unselected segments extend lines to bordering selected data point (safe to exceed total data bounds in first/last segment, getLines takes care) + getLines(&lines, lineDataRange); + + // check data validity if flag set: +#ifdef QCUSTOMPLOT_CHECK_DATA + QCPGraphDataContainer::const_iterator it; + for (it = mDataContainer->constBegin(); it != mDataContainer->constEnd(); ++it) { - if (scale > 1.0) // for scale < 1 we always want cosmetic pens where possible, because else lines might disappear for very small scales - painter.setMode(QCPPainter::pmNonCosmetic); - painter.scale(scale, scale); + if (QCP::isInvalidData(it->key, it->value)) + qDebug() << Q_FUNC_INFO << "Data point at" << it->key << "invalid." << "Plottable name:" << name(); + } +#endif + + // draw fill of graph: + if (isSelectedSegment && mSelectionDecorator) + mSelectionDecorator->applyBrush(painter); + else + painter->setBrush(mBrush); + painter->setPen(Qt::NoPen); + drawFill(painter, &lines); + + // draw line: + if (mLineStyle != lsNone) + { + if (isSelectedSegment && mSelectionDecorator) + mSelectionDecorator->applyPen(painter); + else + painter->setPen(mPen); + painter->setBrush(Qt::NoBrush); + if (mLineStyle == lsImpulse) + drawImpulsePlot(painter, lines); + else + drawLinePlot(painter, lines); // also step plots can be drawn as a line plot + } + + // draw scatters: + QCPScatterStyle finalScatterStyle = mScatterStyle; + if (isSelectedSegment && mSelectionDecorator) + finalScatterStyle = mSelectionDecorator->getFinalScatterStyle(mScatterStyle); + if (!finalScatterStyle.isNone()) + { + getScatters(&scatters, allSegments.at(i)); + drawScatterPlot(painter, scatters, finalScatterStyle); } - if (mBackgroundBrush.style() != Qt::SolidPattern && mBackgroundBrush.style() != Qt::NoBrush) // solid fills were done a few lines above with QPixmap::fill - painter.fillRect(mViewport, mBackgroundBrush); - draw(&painter); - setViewport(oldViewport); - painter.end(); - } else // might happen if pixmap has width or height zero - { - qDebug() << Q_FUNC_INFO << "Couldn't activate painter on pixmap"; - return QPixmap(); } - return result; + + // draw other selection decoration that isn't just line/scatter pens and brushes: + if (mSelectionDecorator) + mSelectionDecorator->drawDecoration(painter, selection()); } -/*! - Renders the plot using the passed \a painter. - - The plot is sized to \a width and \a height in pixels. If the \a painter's scale is not 1.0, the resulting plot will - appear scaled accordingly. - - \note If you are restricted to using a QPainter (instead of QCPPainter), create a temporary QPicture and open a QCPPainter - on it. Then call \ref toPainter with this QCPPainter. After ending the paint operation on the picture, draw it with - the QPainter. This will reproduce the painter actions the QCPPainter took, with a QPainter. - - \see toPixmap -*/ -void QCustomPlot::toPainter(QCPPainter *painter, int width, int height) +/* inherits documentation from base class */ +void QCPGraph::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const { - // this method is somewhat similar to toPixmap. Change something here, and a change in toPixmap might be necessary, too. - int newWidth, newHeight; - if (width == 0 || height == 0) + // draw fill: + if (mBrush.style() != Qt::NoBrush) { - newWidth = this->width(); - newHeight = this->height(); - } else + applyFillAntialiasingHint(painter); + painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush); + } + // draw line vertically centered: + if (mLineStyle != lsNone) { - newWidth = width; - newHeight = height; + applyDefaultAntialiasingHint(painter); + painter->setPen(mPen); + painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens } - - if (painter->isActive()) + // draw scatter symbol: + if (!mScatterStyle.isNone()) { - QRect oldViewport = viewport(); - setViewport(QRect(0, 0, newWidth, newHeight)); - painter->setMode(QCPPainter::pmNoCaching); - if (mBackgroundBrush.style() != Qt::NoBrush) // unlike in toPixmap, we can't do QPixmap::fill for Qt::SolidPattern brush style, so we also draw solid fills with fillRect here - painter->fillRect(mViewport, mBackgroundBrush); - draw(painter); - setViewport(oldViewport); - } else - qDebug() << Q_FUNC_INFO << "Passed painter is not active"; + applyScattersAntialiasingHint(painter); + // scale scatter pixmap if it's too large to fit in legend icon rect: + if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height())) + { + QCPScatterStyle scaledStyle(mScatterStyle); + scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); + scaledStyle.applyTo(painter, mPen); + scaledStyle.drawShape(painter, QRectF(rect).center()); + } else + { + mScatterStyle.applyTo(painter, mPen); + mScatterStyle.drawShape(painter, QRectF(rect).center()); + } + } } - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPColorGradient -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPColorGradient - \brief Defines a color gradient for use with e.g. \ref QCPColorMap - - This class describes a color gradient which can be used to encode data with color. For example, - QCPColorMap and QCPColorScale have \ref QCPColorMap::setGradient "setGradient" methods which - take an instance of this class. Colors are set with \ref setColorStopAt(double position, const QColor &color) - with a \a position from 0 to 1. In between these defined color positions, the - color will be interpolated linearly either in RGB or HSV space, see \ref setColorInterpolation. - - Alternatively, load one of the preset color gradients shown in the image below, with \ref - loadPreset, or by directly specifying the preset in the constructor. - - \image html QCPColorGradient.png - - The fact that the \ref QCPColorGradient(GradientPreset preset) constructor allows directly - converting a \ref GradientPreset to a QCPColorGradient, you can also directly pass \ref - GradientPreset to all the \a setGradient methods, e.g.: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcolorgradient-setgradient - - The total number of levels used in the gradient can be set with \ref setLevelCount. Whether the - color gradient shall be applied periodically (wrapping around) to data values that lie outside - the data range specified on the plottable instance can be controlled with \ref setPeriodic. -*/ - -/*! - Constructs a new QCPColorGradient initialized with the colors and color interpolation according - to \a preset. - - The color level count is initialized to 350. +/*! \internal + + This method retrieves an optimized set of data points via \ref getOptimizedLineData, and branches + out to the line style specific functions such as \ref dataToLines, \ref dataToStepLeftLines, etc. + according to the line style of the graph. + + \a lines will be filled with points in pixel coordinates, that can be drawn with the according + draw functions like \ref drawLinePlot and \ref drawImpulsePlot. The points returned in \a lines + aren't necessarily the original data points. For example, step line styles require additional + points to form the steps when drawn. If the line style of the graph is \ref lsNone, the \a + lines vector will be empty. + + \a dataRange specifies the beginning and ending data indices that will be taken into account for + conversion. In this function, the specified range may exceed the total data bounds without harm: + a correspondingly trimmed data range will be used. This takes the burden off the user of this + function to check for valid indices in \a dataRange, e.g. when extending ranges coming from \ref + getDataSegments. + + \see getScatters */ -QCPColorGradient::QCPColorGradient(GradientPreset preset) : - mLevelCount(350), - mColorInterpolation(ciRGB), - mPeriodic(false), - mColorBufferInvalidated(true) +void QCPGraph::getLines(QVector *lines, const QCPDataRange &dataRange) const { - mColorBuffer.fill(qRgb(0, 0, 0), mLevelCount); - loadPreset(preset); -} + if (!lines) return; + QCPGraphDataContainer::const_iterator begin, end; + getVisibleDataBounds(begin, end, dataRange); + if (begin == end) + { + lines->clear(); + return; + } + + QVector lineData; + if (mLineStyle != lsNone) + getOptimizedLineData(&lineData, begin, end); + + if (mKeyAxis->rangeReversed() != (mKeyAxis->orientation() == Qt::Vertical)) // make sure key pixels are sorted ascending in lineData (significantly simplifies following processing) + std::reverse(lineData.begin(), lineData.end()); -/* undocumented operator */ -bool QCPColorGradient::operator==(const QCPColorGradient &other) const -{ - return ((other.mLevelCount == this->mLevelCount) && - (other.mColorInterpolation == this->mColorInterpolation) && - (other.mPeriodic == this->mPeriodic) && - (other.mColorStops == this->mColorStops)); + switch (mLineStyle) + { + case lsNone: lines->clear(); break; + case lsLine: *lines = dataToLines(lineData); break; + case lsStepLeft: *lines = dataToStepLeftLines(lineData); break; + case lsStepRight: *lines = dataToStepRightLines(lineData); break; + case lsStepCenter: *lines = dataToStepCenterLines(lineData); break; + case lsImpulse: *lines = dataToImpulseLines(lineData); break; + } } -/*! - Sets the number of discretization levels of the color gradient to \a n. The default is 350 which - is typically enough to create a smooth appearance. - - \image html QCPColorGradient-levelcount.png +/*! \internal + + This method retrieves an optimized set of data points via \ref getOptimizedScatterData and then + converts them to pixel coordinates. The resulting points are returned in \a scatters, and can be + passed to \ref drawScatterPlot. + + \a dataRange specifies the beginning and ending data indices that will be taken into account for + conversion. In this function, the specified range may exceed the total data bounds without harm: + a correspondingly trimmed data range will be used. This takes the burden off the user of this + function to check for valid indices in \a dataRange, e.g. when extending ranges coming from \ref + getDataSegments. */ -void QCPColorGradient::setLevelCount(int n) +void QCPGraph::getScatters(QVector *scatters, const QCPDataRange &dataRange) const { - if (n < 2) + if (!scatters) return; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; scatters->clear(); return; } + + QCPGraphDataContainer::const_iterator begin, end; + getVisibleDataBounds(begin, end, dataRange); + if (begin == end) { - qDebug() << Q_FUNC_INFO << "n must be greater or equal 2 but was" << n; - n = 2; + scatters->clear(); + return; } - if (n != mLevelCount) + + QVector data; + getOptimizedScatterData(&data, begin, end); + + if (mKeyAxis->rangeReversed() != (mKeyAxis->orientation() == Qt::Vertical)) // make sure key pixels are sorted ascending in data (significantly simplifies following processing) + std::reverse(data.begin(), data.end()); + + scatters->resize(data.size()); + if (keyAxis->orientation() == Qt::Vertical) { - mLevelCount = n; - mColorBufferInvalidated = true; + for (int i=0; icoordToPixel(data.at(i).value)); + (*scatters)[i].setY(keyAxis->coordToPixel(data.at(i).key)); + } + } + } else + { + for (int i=0; icoordToPixel(data.at(i).key)); + (*scatters)[i].setY(valueAxis->coordToPixel(data.at(i).value)); + } + } } } -/*! - Sets at which positions from 0 to 1 which color shall occur. The positions are the keys, the - colors are the values of the passed QMap \a colorStops. In between these color stops, the color - is interpolated according to \ref setColorInterpolation. - - A more convenient way to create a custom gradient may be to clear all color stops with \ref - clearColorStops and then adding them one by one with \ref setColorStopAt. +/*! \internal + + Takes raw data points in plot coordinates as \a data, and returns a vector containing pixel + coordinate points which are suitable for drawing the line style \ref lsLine. - \see clearColorStops + The source of \a data is usually \ref getOptimizedLineData, and this method is called in \a + getLines if the line style is set accordingly. + + \see dataToStepLeftLines, dataToStepRightLines, dataToStepCenterLines, dataToImpulseLines, getLines, drawLinePlot */ -void QCPColorGradient::setColorStops(const QMap &colorStops) +QVector QCPGraph::dataToLines(const QVector &data) const { - mColorStops = colorStops; - mColorBufferInvalidated = true; -} + QVector result; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return result; } -/*! - Sets the \a color the gradient will have at the specified \a position (from 0 to 1). In between - these color stops, the color is interpolated according to \ref setColorInterpolation. + result.resize(data.size()); - \see setColorStops, clearColorStops -*/ -void QCPColorGradient::setColorStopAt(double position, const QColor &color) -{ - mColorStops.insert(position, color); - mColorBufferInvalidated = true; + // transform data points to pixels: + if (keyAxis->orientation() == Qt::Vertical) + { + for (int i=0; icoordToPixel(data.at(i).value)); + result[i].setY(keyAxis->coordToPixel(data.at(i).key)); + } + } else // key axis is horizontal + { + for (int i=0; icoordToPixel(data.at(i).key)); + result[i].setY(valueAxis->coordToPixel(data.at(i).value)); + } + } + return result; } -/*! - Sets whether the colors in between the configured color stops (see \ref setColorStopAt) shall be - interpolated linearly in RGB or in HSV color space. +/*! \internal + + Takes raw data points in plot coordinates as \a data, and returns a vector containing pixel + coordinate points which are suitable for drawing the line style \ref lsStepLeft. - For example, a sweep in RGB space from red to green will have a muddy brown intermediate color, - whereas in HSV space the intermediate color is yellow. + The source of \a data is usually \ref getOptimizedLineData, and this method is called in \a + getLines if the line style is set accordingly. + + \see dataToLines, dataToStepRightLines, dataToStepCenterLines, dataToImpulseLines, getLines, drawLinePlot */ -void QCPColorGradient::setColorInterpolation(QCPColorGradient::ColorInterpolation interpolation) +QVector QCPGraph::dataToStepLeftLines(const QVector &data) const { - if (interpolation != mColorInterpolation) + QVector result; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return result; } + + result.resize(data.size()*2); + + // calculate steps from data and transform to pixel coordinates: + if (keyAxis->orientation() == Qt::Vertical) { - mColorInterpolation = interpolation; - mColorBufferInvalidated = true; + double lastValue = valueAxis->coordToPixel(data.first().value); + for (int i=0; icoordToPixel(data.at(i).key); + result[i*2+0].setX(lastValue); + result[i*2+0].setY(key); + lastValue = valueAxis->coordToPixel(data.at(i).value); + result[i*2+1].setX(lastValue); + result[i*2+1].setY(key); + } + } else // key axis is horizontal + { + double lastValue = valueAxis->coordToPixel(data.first().value); + for (int i=0; icoordToPixel(data.at(i).key); + result[i*2+0].setX(key); + result[i*2+0].setY(lastValue); + lastValue = valueAxis->coordToPixel(data.at(i).value); + result[i*2+1].setX(key); + result[i*2+1].setY(lastValue); + } } + return result; } -/*! - Sets whether data points that are outside the configured data range (e.g. \ref - QCPColorMap::setDataRange) are colored by periodically repeating the color gradient or whether - they all have the same color, corresponding to the respective gradient boundary color. - - \image html QCPColorGradient-periodic.png - - As shown in the image above, gradients that have the same start and end color are especially - suitable for a periodic gradient mapping, since they produce smooth color transitions throughout - the color map. A preset that has this property is \ref gpHues. +/*! \internal + + Takes raw data points in plot coordinates as \a data, and returns a vector containing pixel + coordinate points which are suitable for drawing the line style \ref lsStepRight. - In practice, using periodic color gradients makes sense when the data corresponds to a periodic - dimension, such as an angle or a phase. If this is not the case, the color encoding might become - ambiguous, because multiple different data values are shown as the same color. + The source of \a data is usually \ref getOptimizedLineData, and this method is called in \a + getLines if the line style is set accordingly. + + \see dataToLines, dataToStepLeftLines, dataToStepCenterLines, dataToImpulseLines, getLines, drawLinePlot */ -void QCPColorGradient::setPeriodic(bool enabled) +QVector QCPGraph::dataToStepRightLines(const QVector &data) const { - mPeriodic = enabled; + QVector result; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return result; } + + result.resize(data.size()*2); + + // calculate steps from data and transform to pixel coordinates: + if (keyAxis->orientation() == Qt::Vertical) + { + double lastKey = keyAxis->coordToPixel(data.first().key); + for (int i=0; icoordToPixel(data.at(i).value); + result[i*2+0].setX(value); + result[i*2+0].setY(lastKey); + lastKey = keyAxis->coordToPixel(data.at(i).key); + result[i*2+1].setX(value); + result[i*2+1].setY(lastKey); + } + } else // key axis is horizontal + { + double lastKey = keyAxis->coordToPixel(data.first().key); + for (int i=0; icoordToPixel(data.at(i).value); + result[i*2+0].setX(lastKey); + result[i*2+0].setY(value); + lastKey = keyAxis->coordToPixel(data.at(i).key); + result[i*2+1].setX(lastKey); + result[i*2+1].setY(value); + } + } + return result; } -/*! - This method is used to quickly convert a \a data array to colors. The colors will be output in - the array \a scanLine. Both \a data and \a scanLine must have the length \a n when passed to this - function. The data range that shall be used for mapping the data value to the gradient is passed - in \a range. \a logarithmic indicates whether the data values shall be mapped to colors - logarithmically. +/*! \internal + + Takes raw data points in plot coordinates as \a data, and returns a vector containing pixel + coordinate points which are suitable for drawing the line style \ref lsStepCenter. - if \a data actually contains 2D-data linearized via [row*columnCount + column], you can - set \a dataIndexFactor to columnCount to convert a column instead of a row of the data - array, in \a scanLine. \a scanLine will remain a regular (1D) array. This works because \a data - is addressed data[i*dataIndexFactor]. + The source of \a data is usually \ref getOptimizedLineData, and this method is called in \a + getLines if the line style is set accordingly. + + \see dataToLines, dataToStepLeftLines, dataToStepRightLines, dataToImpulseLines, getLines, drawLinePlot */ -void QCPColorGradient::colorize(const double *data, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor, bool logarithmic) +QVector QCPGraph::dataToStepCenterLines(const QVector &data) const { - // If you change something here, make sure to also adapt ::color() - if (!data) + QVector result; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return result; } + + result.resize(data.size()*2); + + // calculate steps from data and transform to pixel coordinates: + if (keyAxis->orientation() == Qt::Vertical) { - qDebug() << Q_FUNC_INFO << "null pointer given as data"; - return; - } - if (!scanLine) + double lastKey = keyAxis->coordToPixel(data.first().key); + double lastValue = valueAxis->coordToPixel(data.first().value); + result[0].setX(lastValue); + result[0].setY(lastKey); + for (int i=1; icoordToPixel(data.at(i).key)+lastKey)*0.5; + result[i*2-1].setX(lastValue); + result[i*2-1].setY(key); + lastValue = valueAxis->coordToPixel(data.at(i).value); + lastKey = keyAxis->coordToPixel(data.at(i).key); + result[i*2+0].setX(lastValue); + result[i*2+0].setY(key); + } + result[data.size()*2-1].setX(lastValue); + result[data.size()*2-1].setY(lastKey); + } else // key axis is horizontal { - qDebug() << Q_FUNC_INFO << "null pointer given as scanLine"; - return; + double lastKey = keyAxis->coordToPixel(data.first().key); + double lastValue = valueAxis->coordToPixel(data.first().value); + result[0].setX(lastKey); + result[0].setY(lastValue); + for (int i=1; icoordToPixel(data.at(i).key)+lastKey)*0.5; + result[i*2-1].setX(key); + result[i*2-1].setY(lastValue); + lastValue = valueAxis->coordToPixel(data.at(i).value); + lastKey = keyAxis->coordToPixel(data.at(i).key); + result[i*2+0].setX(key); + result[i*2+0].setY(lastValue); + } + result[data.size()*2-1].setX(lastKey); + result[data.size()*2-1].setY(lastValue); } - if (mColorBufferInvalidated) - updateColorBuffer(); + return result; +} + +/*! \internal + + Takes raw data points in plot coordinates as \a data, and returns a vector containing pixel + coordinate points which are suitable for drawing the line style \ref lsImpulse. + + The source of \a data is usually \ref getOptimizedLineData, and this method is called in \a + getLines if the line style is set accordingly. + + \see dataToLines, dataToStepLeftLines, dataToStepRightLines, dataToStepCenterLines, getLines, drawImpulsePlot +*/ +QVector QCPGraph::dataToImpulseLines(const QVector &data) const +{ + QVector result; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return result; } + + result.resize(data.size()*2); - if (!logarithmic) + // transform data points to pixels: + if (keyAxis->orientation() == Qt::Vertical) { - const double posToIndexFactor = (mLevelCount-1)/range.size(); - if (mPeriodic) + for (int i=0; icoordToPixel(current.key); + result[i*2+0].setX(valueAxis->coordToPixel(0)); + result[i*2+0].setY(key); + result[i*2+1].setX(valueAxis->coordToPixel(current.value)); + result[i*2+1].setY(key); + } else { - int index = (data[dataIndexFactor*i]-range.lower)*posToIndexFactor; - if (index < 0) - index = 0; - else if (index >= mLevelCount) - index = mLevelCount-1; - scanLine[i] = mColorBuffer.at(index); + result[i*2+0] = QPointF(0, 0); + result[i*2+1] = QPointF(0, 0); } } - } else // logarithmic == true + } else // key axis is horizontal { - if (mPeriodic) + for (int i=0; icoordToPixel(data.at(i).key); + result[i*2+0].setX(key); + result[i*2+0].setY(valueAxis->coordToPixel(0)); + result[i*2+1].setX(key); + result[i*2+1].setY(valueAxis->coordToPixel(data.at(i).value)); + } else { - int index = qLn(data[dataIndexFactor*i]/range.lower)/qLn(range.upper/range.lower)*(mLevelCount-1); - if (index < 0) - index = 0; - else if (index >= mLevelCount) - index = mLevelCount-1; - scanLine[i] = mColorBuffer.at(index); + result[i*2+0] = QPointF(0, 0); + result[i*2+1] = QPointF(0, 0); } } } + return result; } /*! \internal - This method is used to colorize a single data value given in \a position, to colors. The data - range that shall be used for mapping the data value to the gradient is passed in \a range. \a - logarithmic indicates whether the data value shall be mapped to a color logarithmically. + Draws the fill of the graph using the specified \a painter, with the currently set brush. - If an entire array of data values shall be converted, rather use \ref colorize, for better - performance. + Depending on whether a normal fill or a channel fill (\ref setChannelFillGraph) is needed, \ref + getFillPolygon or \ref getChannelFillPolygon are used to find the according fill polygons. + + In order to handle NaN Data points correctly (the fill needs to be split into disjoint areas), + this method first determines a list of non-NaN segments with \ref getNonNanSegments, on which to + operate. In the channel fill case, \ref getOverlappingSegments is used to consolidate the non-NaN + segments of the two involved graphs, before passing the overlapping pairs to \ref + getChannelFillPolygon. + + Pass the points of this graph's line as \a lines, in pixel coordinates. + + \see drawLinePlot, drawImpulsePlot, drawScatterPlot */ -QRgb QCPColorGradient::color(double position, const QCPRange &range, bool logarithmic) +void QCPGraph::drawFill(QCPPainter *painter, QVector *lines) const { - // If you change something here, make sure to also adapt ::colorize() - if (mColorBufferInvalidated) - updateColorBuffer(); - int index = 0; - if (!logarithmic) - index = (position-range.lower)*(mLevelCount-1)/range.size(); - else - index = qLn(position/range.lower)/qLn(range.upper/range.lower)*(mLevelCount-1); - if (mPeriodic) + if (mLineStyle == lsImpulse) return; // fill doesn't make sense for impulse plot + if (painter->brush().style() == Qt::NoBrush || painter->brush().color().alpha() == 0) return; + + applyFillAntialiasingHint(painter); + const QVector segments = getNonNanSegments(lines, keyAxis()->orientation()); + if (!mChannelFillGraph) { - index = index % mLevelCount; - if (index < 0) - index += mLevelCount; + // draw base fill under graph, fill goes all the way to the zero-value-line: + foreach (QCPDataRange segment, segments) + painter->drawPolygon(getFillPolygon(lines, segment)); } else { - if (index < 0) - index = 0; - else if (index >= mLevelCount) - index = mLevelCount-1; + // draw fill between this graph and mChannelFillGraph: + QVector otherLines; + mChannelFillGraph->getLines(&otherLines, QCPDataRange(0, mChannelFillGraph->dataCount())); + if (!otherLines.isEmpty()) + { + QVector otherSegments = getNonNanSegments(&otherLines, mChannelFillGraph->keyAxis()->orientation()); + QVector > segmentPairs = getOverlappingSegments(segments, lines, otherSegments, &otherLines); + for (int i=0; idrawPolygon(getChannelFillPolygon(lines, segmentPairs.at(i).first, &otherLines, segmentPairs.at(i).second)); + } } - return mColorBuffer.at(index); } -/*! - Clears the current color stops and loads the specified \a preset. A preset consists of predefined - color stops and the corresponding color interpolation method. +/*! \internal + + Draws scatter symbols at every point passed in \a scatters, given in pixel coordinates. The + scatters will be drawn with \a painter and have the appearance as specified in \a style. + + \see drawLinePlot, drawImpulsePlot +*/ +void QCPGraph::drawScatterPlot(QCPPainter *painter, const QVector &scatters, const QCPScatterStyle &style) const +{ + applyScattersAntialiasingHint(painter); + style.applyTo(painter, mPen); + foreach (const QPointF &scatter, scatters) + style.drawShape(painter, scatter.x(), scatter.y()); +} + +/*! \internal - The available presets are: - \image html QCPColorGradient.png + Draws lines between the points in \a lines, given in pixel coordinates. + + \see drawScatterPlot, drawImpulsePlot, QCPAbstractPlottable1D::drawPolyline */ -void QCPColorGradient::loadPreset(GradientPreset preset) +void QCPGraph::drawLinePlot(QCPPainter *painter, const QVector &lines) const { - clearColorStops(); - switch (preset) + if (painter->pen().style() != Qt::NoPen && painter->pen().color().alpha() != 0) { - case gpGrayscale: - setColorInterpolation(ciRGB); - setColorStopAt(0, Qt::black); - setColorStopAt(1, Qt::white); - break; - case gpHot: - setColorInterpolation(ciRGB); - setColorStopAt(0, QColor(50, 0, 0)); - setColorStopAt(0.2, QColor(180, 10, 0)); - setColorStopAt(0.4, QColor(245, 50, 0)); - setColorStopAt(0.6, QColor(255, 150, 10)); - setColorStopAt(0.8, QColor(255, 255, 50)); - setColorStopAt(1, QColor(255, 255, 255)); - break; - case gpCold: - setColorInterpolation(ciRGB); - setColorStopAt(0, QColor(0, 0, 50)); - setColorStopAt(0.2, QColor(0, 10, 180)); - setColorStopAt(0.4, QColor(0, 50, 245)); - setColorStopAt(0.6, QColor(10, 150, 255)); - setColorStopAt(0.8, QColor(50, 255, 255)); - setColorStopAt(1, QColor(255, 255, 255)); - break; - case gpNight: - setColorInterpolation(ciHSV); - setColorStopAt(0, QColor(10, 20, 30)); - setColorStopAt(1, QColor(250, 255, 250)); - break; - case gpCandy: - setColorInterpolation(ciHSV); - setColorStopAt(0, QColor(0, 0, 255)); - setColorStopAt(1, QColor(255, 250, 250)); - break; - case gpGeography: - setColorInterpolation(ciRGB); - setColorStopAt(0, QColor(70, 170, 210)); - setColorStopAt(0.20, QColor(90, 160, 180)); - setColorStopAt(0.25, QColor(45, 130, 175)); - setColorStopAt(0.30, QColor(100, 140, 125)); - setColorStopAt(0.5, QColor(100, 140, 100)); - setColorStopAt(0.6, QColor(130, 145, 120)); - setColorStopAt(0.7, QColor(140, 130, 120)); - setColorStopAt(0.9, QColor(180, 190, 190)); - setColorStopAt(1, QColor(210, 210, 230)); - break; - case gpIon: - setColorInterpolation(ciHSV); - setColorStopAt(0, QColor(50, 10, 10)); - setColorStopAt(0.45, QColor(0, 0, 255)); - setColorStopAt(0.8, QColor(0, 255, 255)); - setColorStopAt(1, QColor(0, 255, 0)); - break; - case gpThermal: - setColorInterpolation(ciRGB); - setColorStopAt(0, QColor(0, 0, 50)); - setColorStopAt(0.15, QColor(20, 0, 120)); - setColorStopAt(0.33, QColor(200, 30, 140)); - setColorStopAt(0.6, QColor(255, 100, 0)); - setColorStopAt(0.85, QColor(255, 255, 40)); - setColorStopAt(1, QColor(255, 255, 255)); - break; - case gpPolar: - setColorInterpolation(ciRGB); - setColorStopAt(0, QColor(50, 255, 255)); - setColorStopAt(0.18, QColor(10, 70, 255)); - setColorStopAt(0.28, QColor(10, 10, 190)); - setColorStopAt(0.5, QColor(0, 0, 0)); - setColorStopAt(0.72, QColor(190, 10, 10)); - setColorStopAt(0.82, QColor(255, 70, 10)); - setColorStopAt(1, QColor(255, 255, 50)); - break; - case gpSpectrum: - setColorInterpolation(ciHSV); - setColorStopAt(0, QColor(50, 0, 50)); - setColorStopAt(0.15, QColor(0, 0, 255)); - setColorStopAt(0.35, QColor(0, 255, 255)); - setColorStopAt(0.6, QColor(255, 255, 0)); - setColorStopAt(0.75, QColor(255, 30, 0)); - setColorStopAt(1, QColor(50, 0, 0)); - break; - case gpJet: - setColorInterpolation(ciRGB); - setColorStopAt(0, QColor(0, 0, 100)); - setColorStopAt(0.15, QColor(0, 50, 255)); - setColorStopAt(0.35, QColor(0, 255, 255)); - setColorStopAt(0.65, QColor(255, 255, 0)); - setColorStopAt(0.85, QColor(255, 30, 0)); - setColorStopAt(1, QColor(100, 0, 0)); - break; - case gpHues: - setColorInterpolation(ciHSV); - setColorStopAt(0, QColor(255, 0, 0)); - setColorStopAt(1.0/3.0, QColor(0, 0, 255)); - setColorStopAt(2.0/3.0, QColor(0, 255, 0)); - setColorStopAt(1, QColor(255, 0, 0)); - break; + applyDefaultAntialiasingHint(painter); + drawPolyline(painter, lines); } } -/*! - Clears all color stops. - - \see setColorStops, setColorStopAt +/*! \internal + + Draws impulses from the provided data, i.e. it connects all line pairs in \a lines, given in + pixel coordinates. The \a lines necessary for impulses are generated by \ref dataToImpulseLines + from the regular graph data points. + + \see drawLinePlot, drawScatterPlot */ -void QCPColorGradient::clearColorStops() +void QCPGraph::drawImpulsePlot(QCPPainter *painter, const QVector &lines) const { - mColorStops.clear(); - mColorBufferInvalidated = true; + if (painter->pen().style() != Qt::NoPen && painter->pen().color().alpha() != 0) + { + applyDefaultAntialiasingHint(painter); + QPen oldPen = painter->pen(); + QPen newPen = painter->pen(); + newPen.setCapStyle(Qt::FlatCap); // so impulse line doesn't reach beyond zero-line + painter->setPen(newPen); + painter->drawLines(lines); + painter->setPen(oldPen); + } } -/*! - Returns an inverted gradient. The inverted gradient has all properties as this \ref - QCPColorGradient, but the order of the color stops is inverted. - - \see setColorStops, setColorStopAt +/*! \internal + + Returns via \a lineData the data points that need to be visualized for this graph when plotting + graph lines, taking into consideration the currently visible axis ranges and, if \ref + setAdaptiveSampling is enabled, local point densities. The considered data can be restricted + further by \a begin and \a end, e.g. to only plot a certain segment of the data (see \ref + getDataSegments). + + This method is used by \ref getLines to retrieve the basic working set of data. + + \see getOptimizedScatterData */ -QCPColorGradient QCPColorGradient::inverted() const +void QCPGraph::getOptimizedLineData(QVector *lineData, const QCPGraphDataContainer::const_iterator &begin, const QCPGraphDataContainer::const_iterator &end) const { - QCPColorGradient result(*this); - result.clearColorStops(); - for (QMap::const_iterator it=mColorStops.constBegin(); it!=mColorStops.constEnd(); ++it) - result.setColorStopAt(1.0-it.key(), it.value()); - return result; + if (!lineData) return; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + if (begin == end) return; + + int dataCount = int(end-begin); + int maxCount = (std::numeric_limits::max)(); + if (mAdaptiveSampling) + { + double keyPixelSpan = qAbs(keyAxis->coordToPixel(begin->key)-keyAxis->coordToPixel((end-1)->key)); + if (2*keyPixelSpan+2 < static_cast((std::numeric_limits::max)())) + maxCount = int(2*keyPixelSpan+2); + } + + if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average + { + QCPGraphDataContainer::const_iterator it = begin; + double minValue = it->value; + double maxValue = it->value; + QCPGraphDataContainer::const_iterator currentIntervalFirstPoint = it; + int reversedFactor = keyAxis->pixelOrientation(); // is used to calculate keyEpsilon pixel into the correct direction + int reversedRound = reversedFactor==-1 ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey + double currentIntervalStartKey = keyAxis->pixelToCoord(int(keyAxis->coordToPixel(begin->key)+reversedRound)); + double lastIntervalEndKey = currentIntervalStartKey; + double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates + bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes) + int intervalDataCount = 1; + ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect + while (it != end) + { + if (it->key < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this cluster if necessary + { + if (it->value < minValue) + minValue = it->value; + else if (it->value > maxValue) + maxValue = it->value; + ++intervalDataCount; + } else // new pixel interval started + { + if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster + { + if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point is further away, so first point of this cluster must be at a real data point + lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint->value)); + lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.25, minValue)); + lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.75, maxValue)); + if (it->key > currentIntervalStartKey+keyEpsilon*2) // new pixel started further away from previous cluster, so make sure the last point of the cluster is at a real data point + lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.8, (it-1)->value)); + } else + lineData->append(QCPGraphData(currentIntervalFirstPoint->key, currentIntervalFirstPoint->value)); + lastIntervalEndKey = (it-1)->key; + minValue = it->value; + maxValue = it->value; + currentIntervalFirstPoint = it; + currentIntervalStartKey = keyAxis->pixelToCoord(int(keyAxis->coordToPixel(it->key)+reversedRound)); + if (keyEpsilonVariable) + keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); + intervalDataCount = 1; + } + ++it; + } + // handle last interval: + if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster + { + if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point wasn't a cluster, so first point of this cluster must be at a real data point + lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint->value)); + lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.25, minValue)); + lineData->append(QCPGraphData(currentIntervalStartKey+keyEpsilon*0.75, maxValue)); + } else + lineData->append(QCPGraphData(currentIntervalFirstPoint->key, currentIntervalFirstPoint->value)); + + } else // don't use adaptive sampling algorithm, transfer points one-to-one from the data container into the output + { + lineData->resize(dataCount); + std::copy(begin, end, lineData->begin()); + } } /*! \internal - - Updates the internal color buffer which will be used by \ref colorize and \ref color, to quickly - convert positions to colors. This is where the interpolation between color stops is calculated. + + Returns via \a scatterData the data points that need to be visualized for this graph when + plotting scatter points, taking into consideration the currently visible axis ranges and, if \ref + setAdaptiveSampling is enabled, local point densities. The considered data can be restricted + further by \a begin and \a end, e.g. to only plot a certain segment of the data (see \ref + getDataSegments). + + This method is used by \ref getScatters to retrieve the basic working set of data. + + \see getOptimizedLineData */ -void QCPColorGradient::updateColorBuffer() +void QCPGraph::getOptimizedScatterData(QVector *scatterData, QCPGraphDataContainer::const_iterator begin, QCPGraphDataContainer::const_iterator end) const { - if (mColorBuffer.size() != mLevelCount) - mColorBuffer.resize(mLevelCount); - if (mColorStops.size() > 1) + if (!scatterData) return; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + const int scatterModulo = mScatterSkip+1; + const bool doScatterSkip = mScatterSkip > 0; + int beginIndex = int(begin-mDataContainer->constBegin()); + int endIndex = int(end-mDataContainer->constBegin()); + while (doScatterSkip && begin != end && beginIndex % scatterModulo != 0) // advance begin iterator to first non-skipped scatter { - double indexToPosFactor = 1.0/(double)(mLevelCount-1); - for (int i=0; i::max)(); + if (mAdaptiveSampling) + { + int keyPixelSpan = int(qAbs(keyAxis->coordToPixel(begin->key)-keyAxis->coordToPixel((end-1)->key))); + maxCount = 2*keyPixelSpan+2; + } + + if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average + { + double valueMaxRange = valueAxis->range().upper; + double valueMinRange = valueAxis->range().lower; + QCPGraphDataContainer::const_iterator it = begin; + int itIndex = int(beginIndex); + double minValue = it->value; + double maxValue = it->value; + QCPGraphDataContainer::const_iterator minValueIt = it; + QCPGraphDataContainer::const_iterator maxValueIt = it; + QCPGraphDataContainer::const_iterator currentIntervalStart = it; + int reversedFactor = keyAxis->pixelOrientation(); // is used to calculate keyEpsilon pixel into the correct direction + int reversedRound = reversedFactor==-1 ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey + double currentIntervalStartKey = keyAxis->pixelToCoord(int(keyAxis->coordToPixel(begin->key)+reversedRound)); + double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates + bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes) + int intervalDataCount = 1; + // advance iterator to second (non-skipped) data point because adaptive sampling works in 1 point retrospect: + if (!doScatterSkip) + ++it; + else { - double position = i*indexToPosFactor; - QMap::const_iterator it = mColorStops.lowerBound(position); - if (it == mColorStops.constEnd()) // position is on or after last stop, use color of last stop + itIndex += scatterModulo; + if (itIndex < endIndex) // make sure we didn't jump over end + it += scatterModulo; + else { - mColorBuffer[i] = (it-1).value().rgb(); - } else if (it == mColorStops.constBegin()) // position is on or before first stop, use color of first stop + it = end; + itIndex = endIndex; + } + } + // main loop over data points: + while (it != end) + { + if (it->key < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this pixel if necessary { - mColorBuffer[i] = it.value().rgb(); - } else // position is in between stops (or on an intermediate stop), interpolate color + if (it->value < minValue && it->value > valueMinRange && it->value < valueMaxRange) + { + minValue = it->value; + minValueIt = it; + } else if (it->value > maxValue && it->value > valueMinRange && it->value < valueMaxRange) + { + maxValue = it->value; + maxValueIt = it; + } + ++intervalDataCount; + } else // new pixel started { - QMap::const_iterator high = it; - QMap::const_iterator low = it-1; - double t = (position-low.key())/(high.key()-low.key()); // interpolation factor 0..1 - switch (mColorInterpolation) + if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them { - case ciRGB: + // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): + double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); + int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average + QCPGraphDataContainer::const_iterator intervalIt = currentIntervalStart; + int c = 0; + while (intervalIt != it) { - mColorBuffer[i] = qRgb((1-t)*low.value().red() + t*high.value().red(), - (1-t)*low.value().green() + t*high.value().green(), - (1-t)*low.value().blue() + t*high.value().blue()); - break; + if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt->value > valueMinRange && intervalIt->value < valueMaxRange) + scatterData->append(*intervalIt); + ++c; + if (!doScatterSkip) + ++intervalIt; + else + intervalIt += scatterModulo; // since we know indices of "currentIntervalStart", "intervalIt" and "it" are multiples of scatterModulo, we can't accidentally jump over "it" here } - case ciHSV: + } else if (currentIntervalStart->value > valueMinRange && currentIntervalStart->value < valueMaxRange) + scatterData->append(*currentIntervalStart); + minValue = it->value; + maxValue = it->value; + currentIntervalStart = it; + currentIntervalStartKey = keyAxis->pixelToCoord(int(keyAxis->coordToPixel(it->key)+reversedRound)); + if (keyEpsilonVariable) + keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); + intervalDataCount = 1; + } + // advance to next data point: + if (!doScatterSkip) + ++it; + else + { + itIndex += scatterModulo; + if (itIndex < endIndex) // make sure we didn't jump over end + it += scatterModulo; + else + { + it = end; + itIndex = endIndex; + } + } + } + // handle last interval: + if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them + { + // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): + double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); + int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average + QCPGraphDataContainer::const_iterator intervalIt = currentIntervalStart; + int intervalItIndex = int(intervalIt-mDataContainer->constBegin()); + int c = 0; + while (intervalIt != it) + { + if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt->value > valueMinRange && intervalIt->value < valueMaxRange) + scatterData->append(*intervalIt); + ++c; + if (!doScatterSkip) + ++intervalIt; + else // here we can't guarantee that adding scatterModulo doesn't exceed "it" (because "it" is equal to "end" here, and "end" isn't scatterModulo-aligned), so check via index comparison: + { + intervalItIndex += scatterModulo; + if (intervalItIndex < itIndex) + intervalIt += scatterModulo; + else { - QColor lowHsv = low.value().toHsv(); - QColor highHsv = high.value().toHsv(); - double hue = 0; - double hueDiff = highHsv.hueF()-lowHsv.hueF(); - if (hueDiff > 0.5) - hue = lowHsv.hueF() - t*(1.0-hueDiff); - else if (hueDiff < -0.5) - hue = lowHsv.hueF() + t*(1.0+hueDiff); - else - hue = lowHsv.hueF() + t*hueDiff; - if (hue < 0) hue += 1.0; - else if (hue >= 1.0) hue -= 1.0; - mColorBuffer[i] = QColor::fromHsvF(hue, (1-t)*lowHsv.saturationF() + t*highHsv.saturationF(), (1-t)*lowHsv.valueF() + t*highHsv.valueF()).rgb(); - break; + intervalIt = it; + intervalItIndex = itIndex; } } } + } else if (currentIntervalStart->value > valueMinRange && currentIntervalStart->value < valueMaxRange) + scatterData->append(*currentIntervalStart); + + } else // don't use adaptive sampling algorithm, transfer points one-to-one from the data container into the output + { + QCPGraphDataContainer::const_iterator it = begin; + int itIndex = beginIndex; + scatterData->reserve(dataCount); + while (it != end) + { + scatterData->append(*it); + // advance to next data point: + if (!doScatterSkip) + ++it; + else + { + itIndex += scatterModulo; + if (itIndex < endIndex) + it += scatterModulo; + else + { + it = end; + itIndex = endIndex; + } + } } - } else if (mColorStops.size() == 1) + } +} + +/*! + This method outputs the currently visible data range via \a begin and \a end. The returned range + will also never exceed \a rangeRestriction. + + This method takes into account that the drawing of data lines at the axis rect border always + requires the points just outside the visible axis range. So \a begin and \a end may actually + indicate a range that contains one additional data point to the left and right of the visible + axis range. +*/ +void QCPGraph::getVisibleDataBounds(QCPGraphDataContainer::const_iterator &begin, QCPGraphDataContainer::const_iterator &end, const QCPDataRange &rangeRestriction) const +{ + if (rangeRestriction.isEmpty()) + { + end = mDataContainer->constEnd(); + begin = end; + } else + { + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + // get visible data range: + begin = mDataContainer->findBegin(keyAxis->range().lower); + end = mDataContainer->findEnd(keyAxis->range().upper); + // limit lower/upperEnd to rangeRestriction: + mDataContainer->limitIteratorsToDataRange(begin, end, rangeRestriction); // this also ensures rangeRestriction outside data bounds doesn't break anything + } +} + +/*! \internal + + This method goes through the passed points in \a lineData and returns a list of the segments + which don't contain NaN data points. + + \a keyOrientation defines whether the \a x or \a y member of the passed QPointF is used to check + for NaN. If \a keyOrientation is \c Qt::Horizontal, the \a y member is checked, if it is \c + Qt::Vertical, the \a x member is checked. + + \see getOverlappingSegments, drawFill +*/ +QVector QCPGraph::getNonNanSegments(const QVector *lineData, Qt::Orientation keyOrientation) const +{ + QVector result; + const int n = lineData->size(); + + QCPDataRange currentSegment(-1, -1); + int i = 0; + + if (keyOrientation == Qt::Horizontal) { - mColorBuffer.fill(mColorStops.constBegin().value().rgb()); - } else // mColorStops is empty, fill color buffer with black + while (i < n) + { + while (i < n && qIsNaN(lineData->at(i).y())) // seek next non-NaN data point + ++i; + if (i == n) + break; + currentSegment.setBegin(i++); + while (i < n && !qIsNaN(lineData->at(i).y())) // seek next NaN data point or end of data + ++i; + currentSegment.setEnd(i++); + result.append(currentSegment); + } + } else // keyOrientation == Qt::Vertical { - mColorBuffer.fill(qRgb(0, 0, 0)); + while (i < n) + { + while (i < n && qIsNaN(lineData->at(i).x())) // seek next non-NaN data point + ++i; + if (i == n) + break; + currentSegment.setBegin(i++); + while (i < n && !qIsNaN(lineData->at(i).x())) // seek next NaN data point or end of data + ++i; + currentSegment.setEnd(i++); + result.append(currentSegment); + } } - mColorBufferInvalidated = false; + return result; } +/*! \internal + + This method takes two segment lists (e.g. created by \ref getNonNanSegments) \a thisSegments and + \a otherSegments, and their associated point data \a thisData and \a otherData. -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPAxisRect -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPAxisRect - \brief Holds multiple axes and arranges them in a rectangular shape. + It returns all pairs of segments (the first from \a thisSegments, the second from \a + otherSegments), which overlap in plot coordinates. - This class represents an axis rect, a rectangular area that is bounded on all sides with an - arbitrary number of axes. + This method is useful in the case of a channel fill between two graphs, when only those non-NaN + segments which actually overlap in their key coordinate shall be considered for drawing a channel + fill polygon. - Initially QCustomPlot has one axis rect, accessible via QCustomPlot::axisRect(). However, the - layout system allows to have multiple axis rects, e.g. arranged in a grid layout - (QCustomPlot::plotLayout). + It is assumed that the passed segments in \a thisSegments are ordered ascending by index, and + that the segments don't overlap themselves. The same is assumed for the segments in \a + otherSegments. This is fulfilled when the segments are obtained via \ref getNonNanSegments. - By default, QCPAxisRect comes with four axes, at bottom, top, left and right. They can be - accessed via \ref axis by providing the respective axis type (\ref QCPAxis::AxisType) and index. - If you need all axes in the axis rect, use \ref axes. The top and right axes are set to be - invisible initially (QCPAxis::setVisible). To add more axes to a side, use \ref addAxis or \ref - addAxes. To remove an axis, use \ref removeAxis. + \see getNonNanSegments, segmentsIntersect, drawFill, getChannelFillPolygon +*/ +QVector > QCPGraph::getOverlappingSegments(QVector thisSegments, const QVector *thisData, QVector otherSegments, const QVector *otherData) const +{ + QVector > result; + if (thisData->isEmpty() || otherData->isEmpty() || thisSegments.isEmpty() || otherSegments.isEmpty()) + return result; - The axis rect layerable itself only draws a background pixmap or color, if specified (\ref - setBackground). It is placed on the "background" layer initially (see \ref QCPLayer for an - explanation of the QCustomPlot layer system). The axes that are held by the axis rect can be - placed on other layers, independently of the axis rect. + int thisIndex = 0; + int otherIndex = 0; + const bool verticalKey = mKeyAxis->orientation() == Qt::Vertical; + while (thisIndex < thisSegments.size() && otherIndex < otherSegments.size()) + { + if (thisSegments.at(thisIndex).size() < 2) // segments with fewer than two points won't have a fill anyhow + { + ++thisIndex; + continue; + } + if (otherSegments.at(otherIndex).size() < 2) // segments with fewer than two points won't have a fill anyhow + { + ++otherIndex; + continue; + } + double thisLower, thisUpper, otherLower, otherUpper; + if (!verticalKey) + { + thisLower = thisData->at(thisSegments.at(thisIndex).begin()).x(); + thisUpper = thisData->at(thisSegments.at(thisIndex).end()-1).x(); + otherLower = otherData->at(otherSegments.at(otherIndex).begin()).x(); + otherUpper = otherData->at(otherSegments.at(otherIndex).end()-1).x(); + } else + { + thisLower = thisData->at(thisSegments.at(thisIndex).begin()).y(); + thisUpper = thisData->at(thisSegments.at(thisIndex).end()-1).y(); + otherLower = otherData->at(otherSegments.at(otherIndex).begin()).y(); + otherUpper = otherData->at(otherSegments.at(otherIndex).end()-1).y(); + } + + int bPrecedence; + if (segmentsIntersect(thisLower, thisUpper, otherLower, otherUpper, bPrecedence)) + result.append(QPair(thisSegments.at(thisIndex), otherSegments.at(otherIndex))); + + if (bPrecedence <= 0) // otherSegment doesn't reach as far as thisSegment, so continue with next otherSegment, keeping current thisSegment + ++otherIndex; + else // otherSegment reaches further than thisSegment, so continue with next thisSegment, keeping current otherSegment + ++thisIndex; + } - Every axis rect has a child layout of type \ref QCPLayoutInset. It is accessible via \ref - insetLayout and can be used to have other layout elements (or even other layouts with multiple - elements) hovering inside the axis rect. + return result; +} + +/*! \internal - If an axis rect is clicked and dragged, it processes this by moving certain axis ranges. The - behaviour can be controlled with \ref setRangeDrag and \ref setRangeDragAxes. If the mouse wheel - is scrolled while the cursor is on the axis rect, certain axes are scaled. This is controllable - via \ref setRangeZoom, \ref setRangeZoomAxes and \ref setRangeZoomFactor. These interactions are - only enabled if \ref QCustomPlot::setInteractions contains \ref QCP::iRangeDrag and \ref - QCP::iRangeZoom. + Returns whether the segments defined by the coordinates (aLower, aUpper) and (bLower, bUpper) + have overlap. - \image html AxisRectSpacingOverview.png -
Overview of the spacings and paddings that define the geometry of an axis. The dashed - line on the far left indicates the viewport/widget border.
-*/ - -/* start documentation of inline functions */ - -/*! \fn QCPLayoutInset *QCPAxisRect::insetLayout() const + The output parameter \a bPrecedence indicates whether the \a b segment reaches farther than the + \a a segment or not. If \a bPrecedence returns 1, segment \a b reaches the farthest to higher + coordinates (i.e. bUpper > aUpper). If it returns -1, segment \a a reaches the farthest. Only if + both segment's upper bounds are identical, 0 is returned as \a bPrecedence. - Returns the inset layout of this axis rect. It can be used to place other layout elements (or - even layouts with multiple other elements) inside/on top of an axis rect. + It is assumed that the lower bounds always have smaller or equal values than the upper bounds. - \see QCPLayoutInset + \see getOverlappingSegments */ +bool QCPGraph::segmentsIntersect(double aLower, double aUpper, double bLower, double bUpper, int &bPrecedence) const +{ + bPrecedence = 0; + if (aLower > bUpper) + { + bPrecedence = -1; + return false; + } else if (bLower > aUpper) + { + bPrecedence = 1; + return false; + } else + { + if (aUpper > bUpper) + bPrecedence = -1; + else if (aUpper < bUpper) + bPrecedence = 1; + + return true; + } +} -/*! \fn int QCPAxisRect::left() const +/*! \internal - Returns the pixel position of the left border of this axis rect. Margins are not taken into - account here, so the returned value is with respect to the inner \ref rect. -*/ + Returns the point which closes the fill polygon on the zero-value-line parallel to the key axis. + The logarithmic axis scale case is a bit special, since the zero-value-line in pixel coordinates + is in positive or negative infinity. So this case is handled separately by just closing the fill + polygon on the axis which lies in the direction towards the zero value. -/*! \fn int QCPAxisRect::right() const - - Returns the pixel position of the right border of this axis rect. Margins are not taken into - account here, so the returned value is with respect to the inner \ref rect. + \a matchingDataPoint will provide the key (in pixels) of the returned point. Depending on whether + the key axis of this graph is horizontal or vertical, \a matchingDataPoint will provide the x or + y value of the returned point, respectively. */ - -/*! \fn int QCPAxisRect::top() const +QPointF QCPGraph::getFillBasePoint(QPointF matchingDataPoint) const +{ + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return {}; } - Returns the pixel position of the top border of this axis rect. Margins are not taken into - account here, so the returned value is with respect to the inner \ref rect. -*/ + QPointF result; + if (valueAxis->scaleType() == QCPAxis::stLinear) + { + if (keyAxis->orientation() == Qt::Horizontal) + { + result.setX(matchingDataPoint.x()); + result.setY(valueAxis->coordToPixel(0)); + } else // keyAxis->orientation() == Qt::Vertical + { + result.setX(valueAxis->coordToPixel(0)); + result.setY(matchingDataPoint.y()); + } + } else // valueAxis->mScaleType == QCPAxis::stLogarithmic + { + // In logarithmic scaling we can't just draw to value 0 so we just fill all the way + // to the axis which is in the direction towards 0 + if (keyAxis->orientation() == Qt::Vertical) + { + if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || + (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis + result.setX(keyAxis->axisRect()->right()); + else + result.setX(keyAxis->axisRect()->left()); + result.setY(matchingDataPoint.y()); + } else if (keyAxis->axisType() == QCPAxis::atTop || keyAxis->axisType() == QCPAxis::atBottom) + { + result.setX(matchingDataPoint.x()); + if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || + (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis + result.setY(keyAxis->axisRect()->top()); + else + result.setY(keyAxis->axisRect()->bottom()); + } + } + return result; +} -/*! \fn int QCPAxisRect::bottom() const +/*! \internal - Returns the pixel position of the bottom border of this axis rect. Margins are not taken into - account here, so the returned value is with respect to the inner \ref rect. -*/ - -/*! \fn int QCPAxisRect::width() const + Returns the polygon needed for drawing normal fills between this graph and the key axis. - Returns the pixel width of this axis rect. Margins are not taken into account here, so the - returned value is with respect to the inner \ref rect. -*/ - -/*! \fn int QCPAxisRect::height() const + Pass the graph's data points (in pixel coordinates) as \a lineData, and specify the \a segment + which shall be used for the fill. The collection of \a lineData points described by \a segment + must not contain NaN data points (see \ref getNonNanSegments). - Returns the pixel height of this axis rect. Margins are not taken into account here, so the - returned value is with respect to the inner \ref rect. -*/ + The returned fill polygon will be closed at the key axis (the zero-value line) for linear value + axes. For logarithmic value axes the polygon will reach just beyond the corresponding axis rect + side (see \ref getFillBasePoint). -/*! \fn QSize QCPAxisRect::size() const + For increased performance (due to implicit sharing), keep the returned QPolygonF const. - Returns the pixel size of this axis rect. Margins are not taken into account here, so the - returned value is with respect to the inner \ref rect. + \see drawFill, getNonNanSegments */ - -/*! \fn QPoint QCPAxisRect::topLeft() const +const QPolygonF QCPGraph::getFillPolygon(const QVector *lineData, QCPDataRange segment) const +{ + if (segment.size() < 2) + return QPolygonF(); + QPolygonF result(segment.size()+2); - Returns the top left corner of this axis rect in pixels. Margins are not taken into account here, - so the returned value is with respect to the inner \ref rect. -*/ - -/*! \fn QPoint QCPAxisRect::topRight() const + result[0] = getFillBasePoint(lineData->at(segment.begin())); + std::copy(lineData->constBegin()+segment.begin(), lineData->constBegin()+segment.end(), result.begin()+1); + result[result.size()-1] = getFillBasePoint(lineData->at(segment.end()-1)); - Returns the top right corner of this axis rect in pixels. Margins are not taken into account - here, so the returned value is with respect to the inner \ref rect. -*/ + return result; +} -/*! \fn QPoint QCPAxisRect::bottomLeft() const +/*! \internal - Returns the bottom left corner of this axis rect in pixels. Margins are not taken into account - here, so the returned value is with respect to the inner \ref rect. -*/ - -/*! \fn QPoint QCPAxisRect::bottomRight() const + Returns the polygon needed for drawing (partial) channel fills between this graph and the graph + specified by \ref setChannelFillGraph. - Returns the bottom right corner of this axis rect in pixels. Margins are not taken into account - here, so the returned value is with respect to the inner \ref rect. + The data points of this graph are passed as pixel coordinates via \a thisData, the data of the + other graph as \a otherData. The returned polygon will be calculated for the specified data + segments \a thisSegment and \a otherSegment, pertaining to the respective \a thisData and \a + otherData, respectively. + + The passed \a thisSegment and \a otherSegment should correspond to the segment pairs returned by + \ref getOverlappingSegments, to make sure only segments that actually have key coordinate overlap + need to be processed here. + + For increased performance due to implicit sharing, keep the returned QPolygonF const. + + \see drawFill, getOverlappingSegments, getNonNanSegments */ +const QPolygonF QCPGraph::getChannelFillPolygon(const QVector *thisData, QCPDataRange thisSegment, const QVector *otherData, QCPDataRange otherSegment) const +{ + if (!mChannelFillGraph) + return QPolygonF(); + + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); } + if (!mChannelFillGraph.data()->mKeyAxis) { qDebug() << Q_FUNC_INFO << "channel fill target key axis invalid"; return QPolygonF(); } + + if (mChannelFillGraph.data()->mKeyAxis.data()->orientation() != keyAxis->orientation()) + return QPolygonF(); // don't have same axis orientation, can't fill that (Note: if keyAxis fits, valueAxis will fit too, because it's always orthogonal to keyAxis) + + if (thisData->isEmpty()) return QPolygonF(); + QVector thisSegmentData(thisSegment.size()); + QVector otherSegmentData(otherSegment.size()); + std::copy(thisData->constBegin()+thisSegment.begin(), thisData->constBegin()+thisSegment.end(), thisSegmentData.begin()); + std::copy(otherData->constBegin()+otherSegment.begin(), otherData->constBegin()+otherSegment.end(), otherSegmentData.begin()); + // pointers to be able to swap them, depending which data range needs cropping: + QVector *staticData = &thisSegmentData; + QVector *croppedData = &otherSegmentData; + + // crop both vectors to ranges in which the keys overlap (which coord is key, depends on axisType): + if (keyAxis->orientation() == Qt::Horizontal) + { + // x is key + // crop lower bound: + if (staticData->first().x() < croppedData->first().x()) // other one must be cropped + qSwap(staticData, croppedData); + const int lowBound = findIndexBelowX(croppedData, staticData->first().x()); + if (lowBound == -1) return QPolygonF(); // key ranges have no overlap + croppedData->remove(0, lowBound); + // set lowest point of cropped data to fit exactly key position of first static data point via linear interpolation: + if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation + double slope; + if (!qFuzzyCompare(croppedData->at(1).x(), croppedData->at(0).x())) + slope = (croppedData->at(1).y()-croppedData->at(0).y())/(croppedData->at(1).x()-croppedData->at(0).x()); + else + slope = 0; + (*croppedData)[0].setY(croppedData->at(0).y()+slope*(staticData->first().x()-croppedData->at(0).x())); + (*croppedData)[0].setX(staticData->first().x()); + + // crop upper bound: + if (staticData->last().x() > croppedData->last().x()) // other one must be cropped + qSwap(staticData, croppedData); + int highBound = findIndexAboveX(croppedData, staticData->last().x()); + if (highBound == -1) return QPolygonF(); // key ranges have no overlap + croppedData->remove(highBound+1, croppedData->size()-(highBound+1)); + // set highest point of cropped data to fit exactly key position of last static data point via linear interpolation: + if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation + const int li = croppedData->size()-1; // last index + if (!qFuzzyCompare(croppedData->at(li).x(), croppedData->at(li-1).x())) + slope = (croppedData->at(li).y()-croppedData->at(li-1).y())/(croppedData->at(li).x()-croppedData->at(li-1).x()); + else + slope = 0; + (*croppedData)[li].setY(croppedData->at(li-1).y()+slope*(staticData->last().x()-croppedData->at(li-1).x())); + (*croppedData)[li].setX(staticData->last().x()); + } else // mKeyAxis->orientation() == Qt::Vertical + { + // y is key + // crop lower bound: + if (staticData->first().y() < croppedData->first().y()) // other one must be cropped + qSwap(staticData, croppedData); + int lowBound = findIndexBelowY(croppedData, staticData->first().y()); + if (lowBound == -1) return QPolygonF(); // key ranges have no overlap + croppedData->remove(0, lowBound); + // set lowest point of cropped data to fit exactly key position of first static data point via linear interpolation: + if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation + double slope; + if (!qFuzzyCompare(croppedData->at(1).y(), croppedData->at(0).y())) // avoid division by zero in step plots + slope = (croppedData->at(1).x()-croppedData->at(0).x())/(croppedData->at(1).y()-croppedData->at(0).y()); + else + slope = 0; + (*croppedData)[0].setX(croppedData->at(0).x()+slope*(staticData->first().y()-croppedData->at(0).y())); + (*croppedData)[0].setY(staticData->first().y()); + + // crop upper bound: + if (staticData->last().y() > croppedData->last().y()) // other one must be cropped + qSwap(staticData, croppedData); + int highBound = findIndexAboveY(croppedData, staticData->last().y()); + if (highBound == -1) return QPolygonF(); // key ranges have no overlap + croppedData->remove(highBound+1, croppedData->size()-(highBound+1)); + // set highest point of cropped data to fit exactly key position of last static data point via linear interpolation: + if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation + int li = croppedData->size()-1; // last index + if (!qFuzzyCompare(croppedData->at(li).y(), croppedData->at(li-1).y())) // avoid division by zero in step plots + slope = (croppedData->at(li).x()-croppedData->at(li-1).x())/(croppedData->at(li).y()-croppedData->at(li-1).y()); + else + slope = 0; + (*croppedData)[li].setX(croppedData->at(li-1).x()+slope*(staticData->last().y()-croppedData->at(li-1).y())); + (*croppedData)[li].setY(staticData->last().y()); + } + + // return joined: + for (int i=otherSegmentData.size()-1; i>=0; --i) // insert reversed, otherwise the polygon will be twisted + thisSegmentData << otherSegmentData.at(i); + return QPolygonF(thisSegmentData); +} -/*! \fn QPoint QCPAxisRect::center() const +/*! \internal - Returns the center of this axis rect in pixels. Margins are not taken into account here, so the - returned value is with respect to the inner \ref rect. -*/ - -/* end documentation of inline functions */ + Finds the smallest index of \a data, whose points x value is just above \a x. Assumes x values in + \a data points are ordered ascending, as is ensured by \ref getLines/\ref getScatters if the key + axis is horizontal. -/*! - Creates a QCPAxisRect instance and sets default values. An axis is added for each of the four - sides, the top and right axes are set invisible initially. + Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. */ -QCPAxisRect::QCPAxisRect(QCustomPlot *parentPlot, bool setupDefaultAxes) : - QCPLayoutElement(parentPlot), - mBackgroundBrush(Qt::NoBrush), - mBackgroundScaled(true), - mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding), - mInsetLayout(new QCPLayoutInset), - mRangeDrag(Qt::Horizontal|Qt::Vertical), - mRangeZoom(Qt::Horizontal|Qt::Vertical), - mRangeZoomFactorHorz(0.85), - mRangeZoomFactorVert(0.85), - mDragging(false) +int QCPGraph::findIndexAboveX(const QVector *data, double x) const { - mInsetLayout->initializeParentPlot(mParentPlot); - mInsetLayout->setParentLayerable(this); - mInsetLayout->setParent(this); - - setMinimumSize(50, 50); - setMinimumMargins(QMargins(15, 15, 15, 15)); - mAxes.insert(QCPAxis::atLeft, QList()); - mAxes.insert(QCPAxis::atRight, QList()); - mAxes.insert(QCPAxis::atTop, QList()); - mAxes.insert(QCPAxis::atBottom, QList()); - - if (setupDefaultAxes) + for (int i=data->size()-1; i>=0; --i) { - QCPAxis *xAxis = addAxis(QCPAxis::atBottom); - QCPAxis *yAxis = addAxis(QCPAxis::atLeft); - QCPAxis *xAxis2 = addAxis(QCPAxis::atTop); - QCPAxis *yAxis2 = addAxis(QCPAxis::atRight); - setRangeDragAxes(xAxis, yAxis); - setRangeZoomAxes(xAxis, yAxis); - xAxis2->setVisible(false); - yAxis2->setVisible(false); - xAxis->grid()->setVisible(true); - yAxis->grid()->setVisible(true); - xAxis2->grid()->setVisible(false); - yAxis2->grid()->setVisible(false); - xAxis2->grid()->setZeroLinePen(Qt::NoPen); - yAxis2->grid()->setZeroLinePen(Qt::NoPen); - xAxis2->grid()->setVisible(false); - yAxis2->grid()->setVisible(false); + if (data->at(i).x() < x) + { + if (isize()-1) + return i+1; + else + return data->size()-1; + } } + return -1; } -QCPAxisRect::~QCPAxisRect() -{ - delete mInsetLayout; - mInsetLayout = 0; +/*! \internal - QList axesList = axes(); - for (int i=0; i *data, double x) const { - return mAxes.value(type).size(); + for (int i=0; isize(); ++i) + { + if (data->at(i).x() > x) + { + if (i>0) + return i-1; + else + return 0; + } + } + return -1; } -/*! - Returns the axis with the given \a index on the axis rect side specified with \a type. +/*! \internal - \see axisCount, axes + Finds the smallest index of \a data, whose points y value is just above \a y. Assumes y values in + \a data points are ordered ascending, as is ensured by \ref getLines/\ref getScatters if the key + axis is vertical. + + Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. */ -QCPAxis *QCPAxisRect::axis(QCPAxis::AxisType type, int index) const +int QCPGraph::findIndexAboveY(const QVector *data, double y) const { - QList ax(mAxes.value(type)); - if (index >= 0 && index < ax.size()) - { - return ax.at(index); - } else + for (int i=data->size()-1; i>=0; --i) { - qDebug() << Q_FUNC_INFO << "Axis index out of bounds:" << index; - return 0; + if (data->at(i).y() < y) + { + if (isize()-1) + return i+1; + else + return data->size()-1; + } } + return -1; } -/*! - Returns all axes on the axis rect sides specified with \a types. +/*! \internal - \a types may be a single \ref QCPAxis::AxisType or an or-combination, to get the axes of - multiple sides. + Calculates the minimum distance in pixels the graph's representation has from the given \a + pixelPoint. This is used to determine whether the graph was clicked or not, e.g. in \ref + selectTest. The closest data point to \a pixelPoint is returned in \a closestData. Note that if + the graph has a line representation, the returned distance may be smaller than the distance to + the \a closestData point, since the distance to the graph line is also taken into account. - \see axis + If either the graph has no data or if the line style is \ref lsNone and the scatter style's shape + is \ref QCPScatterStyle::ssNone (i.e. there is no visual representation of the graph), returns -1.0. */ -QList QCPAxisRect::axes(QCPAxis::AxisTypes types) const +double QCPGraph::pointDistance(const QPointF &pixelPoint, QCPGraphDataContainer::const_iterator &closestData) const { - QList result; - if (types.testFlag(QCPAxis::atLeft)) - result << mAxes.value(QCPAxis::atLeft); - if (types.testFlag(QCPAxis::atRight)) - result << mAxes.value(QCPAxis::atRight); - if (types.testFlag(QCPAxis::atTop)) - result << mAxes.value(QCPAxis::atTop); - if (types.testFlag(QCPAxis::atBottom)) - result << mAxes.value(QCPAxis::atBottom); - return result; + closestData = mDataContainer->constEnd(); + if (mDataContainer->isEmpty()) + return -1.0; + if (mLineStyle == lsNone && mScatterStyle.isNone()) + return -1.0; + + // calculate minimum distances to graph data points and find closestData iterator: + double minDistSqr = (std::numeric_limits::max)(); + // determine which key range comes into question, taking selection tolerance around pos into account: + double posKeyMin, posKeyMax, dummy; + pixelsToCoords(pixelPoint-QPointF(mParentPlot->selectionTolerance(), mParentPlot->selectionTolerance()), posKeyMin, dummy); + pixelsToCoords(pixelPoint+QPointF(mParentPlot->selectionTolerance(), mParentPlot->selectionTolerance()), posKeyMax, dummy); + if (posKeyMin > posKeyMax) + qSwap(posKeyMin, posKeyMax); + // iterate over found data points and then choose the one with the shortest distance to pos: + QCPGraphDataContainer::const_iterator begin = mDataContainer->findBegin(posKeyMin, true); + QCPGraphDataContainer::const_iterator end = mDataContainer->findEnd(posKeyMax, true); + for (QCPGraphDataContainer::const_iterator it=begin; it!=end; ++it) + { + const double currentDistSqr = QCPVector2D(coordsToPixels(it->key, it->value)-pixelPoint).lengthSquared(); + if (currentDistSqr < minDistSqr) + { + minDistSqr = currentDistSqr; + closestData = it; + } + } + + // calculate distance to graph line if there is one (if so, will probably be smaller than distance to closest data point): + if (mLineStyle != lsNone) + { + // line displayed, calculate distance to line segments: + QVector lineData; + getLines(&lineData, QCPDataRange(0, dataCount())); // don't limit data range further since with sharp data spikes, line segments may be closer to test point than segments with closer key coordinate + QCPVector2D p(pixelPoint); + const int step = mLineStyle==lsImpulse ? 2 : 1; // impulse plot differs from other line styles in that the lineData points are only pairwise connected + for (int i=0; i QCPAxisRect::axes() const +int QCPGraph::findIndexBelowY(const QVector *data, double y) const { - QList result; - QHashIterator > it(mAxes); - while (it.hasNext()) + for (int i=0; isize(); ++i) { - it.next(); - result << it.value(); + if (data->at(i).y() > y) + { + if (i>0) + return i-1; + else + return 0; + } } - return result; + return -1; } +/* end of 'src/plottables/plottable-graph.cpp' */ -/*! - Adds a new axis to the axis rect side specified with \a type, and returns it. If \a axis is 0, a - new QCPAxis instance is created internally. - You may inject QCPAxis instances (or sublasses of QCPAxis) by setting \a axis to an axis that was - previously created outside QCustomPlot. It is important to note that QCustomPlot takes ownership - of the axis, so you may not delete it afterwards. Further, the \a axis must have been created - with this axis rect as parent and with the same axis type as specified in \a type. If this is not - the case, a debug output is generated, the axis is not added, and the method returns 0. +/* including file 'src/plottables/plottable-curve.cpp' */ +/* modified 2022-11-06T12:45:56, size 63851 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPCurveData +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPCurveData + \brief Holds the data of one single data point for QCPCurve. - This method can not be used to move \a axis between axis rects. The same \a axis instance must - not be added multiple times to the same or different axis rects. + The stored data is: + \li \a t: the free ordering parameter of this curve point, like in the mathematical vector (x(t), y(t)). (This is the \a sortKey) + \li \a key: coordinate on the key axis of this curve point (this is the \a mainKey) + \li \a value: coordinate on the value axis of this curve point (this is the \a mainValue) - If an axis rect side already contains one or more axes, the lower and upper endings of the new - axis (\ref QCPAxis::setLowerEnding, \ref QCPAxis::setUpperEnding) are set to \ref - QCPLineEnding::esHalfBar. + The container for storing multiple data points is \ref QCPCurveDataContainer. It is a typedef for + \ref QCPDataContainer with \ref QCPCurveData as the DataType template parameter. See the + documentation there for an explanation regarding the data type's generic methods. - \see addAxes, setupFullAxesBox + \see QCPCurveDataContainer */ -QCPAxis *QCPAxisRect::addAxis(QCPAxis::AxisType type, QCPAxis *axis) -{ - QCPAxis *newAxis = axis; - if (!newAxis) - { - newAxis = new QCPAxis(this, type); - } else // user provided existing axis instance, do some sanity checks - { - if (newAxis->axisType() != type) - { - qDebug() << Q_FUNC_INFO << "passed axis has different axis type than specified in type parameter"; - return 0; - } - if (newAxis->axisRect() != this) - { - qDebug() << Q_FUNC_INFO << "passed axis doesn't have this axis rect as parent axis rect"; - return 0; - } - if (axes().contains(newAxis)) - { - qDebug() << Q_FUNC_INFO << "passed axis is already owned by this axis rect"; - return 0; - } - } - if (mAxes[type].size() > 0) // multiple axes on one side, add half-bar axis ending to additional axes with offset - { - bool invert = (type == QCPAxis::atRight) || (type == QCPAxis::atBottom); - newAxis->setLowerEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, !invert)); - newAxis->setUpperEnding(QCPLineEnding(QCPLineEnding::esHalfBar, 6, 10, invert)); - } - mAxes[type].append(newAxis); - return newAxis; -} -/*! - Adds a new axis with \ref addAxis to each axis rect side specified in \a types. This may be an - or-combination of QCPAxis::AxisType, so axes can be added to multiple sides at once. +/* start documentation of inline functions */ + +/*! \fn double QCPCurveData::sortKey() const - Returns a list of the added axes. + Returns the \a t member of this data point. - \see addAxis, setupFullAxesBox + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ + +/*! \fn static QCPCurveData QCPCurveData::fromSortKey(double sortKey) + + Returns a data point with the specified \a sortKey (assigned to the data point's \a t member). + All other members are set to zero. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ + +/*! \fn static static bool QCPCurveData::sortKeyIsMainKey() + + Since the member \a key is the data point key coordinate and the member \a t is the data ordering + parameter, this method returns false. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ + +/*! \fn double QCPCurveData::mainKey() const + + Returns the \a key member of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ + +/*! \fn double QCPCurveData::mainValue() const + + Returns the \a value member of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ + +/*! \fn QCPRange QCPCurveData::valueRange() const + + Returns a QCPRange with both lower and upper boundary set to \a value of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ + +/* end documentation of inline functions */ + +/*! + Constructs a curve data point with t, key and value set to zero. */ -QList QCPAxisRect::addAxes(QCPAxis::AxisTypes types) +QCPCurveData::QCPCurveData() : + t(0), + key(0), + value(0) { - QList result; - if (types.testFlag(QCPAxis::atLeft)) - result << addAxis(QCPAxis::atLeft); - if (types.testFlag(QCPAxis::atRight)) - result << addAxis(QCPAxis::atRight); - if (types.testFlag(QCPAxis::atTop)) - result << addAxis(QCPAxis::atTop); - if (types.testFlag(QCPAxis::atBottom)) - result << addAxis(QCPAxis::atBottom); - return result; } /*! - Removes the specified \a axis from the axis rect and deletes it. - - Returns true on success, i.e. if \a axis was a valid axis in this axis rect. - - \see addAxis + Constructs a curve data point with the specified \a t, \a key and \a value. */ -bool QCPAxisRect::removeAxis(QCPAxis *axis) +QCPCurveData::QCPCurveData(double t, double key, double value) : + t(t), + key(key), + value(value) { - // don't access axis->axisType() to provide safety when axis is an invalid pointer, rather go through all axis containers: - QHashIterator > it(mAxes); - while (it.hasNext()) - { - it.next(); - if (it.value().contains(axis)) - { - mAxes[it.key()].removeOne(axis); - if (qobject_cast(parentPlot())) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the axis rect is not in any layout and thus QObject-child of QCustomPlot) - parentPlot()->axisRemoved(axis); - delete axis; - return true; - } - } - qDebug() << Q_FUNC_INFO << "Axis isn't in axis rect:" << reinterpret_cast(axis); - return false; } -/*! - Convenience function to create an axis on each side that doesn't have any axes yet and set their - visibility to true. Further, the top/right axes are assigned the following properties of the - bottom/left axes: + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPCurve +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPCurve + \brief A plottable representing a parametric curve in a plot. - \li range (\ref QCPAxis::setRange) - \li range reversed (\ref QCPAxis::setRangeReversed) - \li scale type (\ref QCPAxis::setScaleType) - \li scale log base (\ref QCPAxis::setScaleLogBase) - \li ticks (\ref QCPAxis::setTicks) - \li auto (major) tick count (\ref QCPAxis::setAutoTickCount) - \li sub tick count (\ref QCPAxis::setSubTickCount) - \li auto sub ticks (\ref QCPAxis::setAutoSubTicks) - \li tick step (\ref QCPAxis::setTickStep) - \li auto tick step (\ref QCPAxis::setAutoTickStep) - \li number format (\ref QCPAxis::setNumberFormat) - \li number precision (\ref QCPAxis::setNumberPrecision) - \li tick label type (\ref QCPAxis::setTickLabelType) - \li date time format (\ref QCPAxis::setDateTimeFormat) - \li date time spec (\ref QCPAxis::setDateTimeSpec) + \image html QCPCurve.png - Tick labels (\ref QCPAxis::setTickLabels) of the right and top axes are set to false. + Unlike QCPGraph, plottables of this type may have multiple points with the same key coordinate, + so their visual representation can have \a loops. This is realized by introducing a third + coordinate \a t, which defines the order of the points described by the other two coordinates \a + x and \a y. - If \a connectRanges is true, the \ref QCPAxis::rangeChanged "rangeChanged" signals of the bottom - and left axes are connected to the \ref QCPAxis::setRange slots of the top and right axes. -*/ -void QCPAxisRect::setupFullAxesBox(bool connectRanges) -{ - QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2; - if (axisCount(QCPAxis::atBottom) == 0) - xAxis = addAxis(QCPAxis::atBottom); - else - xAxis = axis(QCPAxis::atBottom); + To plot data, assign it with the \ref setData or \ref addData functions. Alternatively, you can + also access and modify the curve's data via the \ref data method, which returns a pointer to the + internal \ref QCPCurveDataContainer. - if (axisCount(QCPAxis::atLeft) == 0) - yAxis = addAxis(QCPAxis::atLeft); - else - yAxis = axis(QCPAxis::atLeft); + Gaps in the curve can be created by adding data points with NaN as key and value + (qQNaN() or std::numeric_limits::quiet_NaN()) in between the two data points that shall be + separated. - if (axisCount(QCPAxis::atTop) == 0) - xAxis2 = addAxis(QCPAxis::atTop); - else - xAxis2 = axis(QCPAxis::atTop); + \section qcpcurve-appearance Changing the appearance - if (axisCount(QCPAxis::atRight) == 0) - yAxis2 = addAxis(QCPAxis::atRight); - else - yAxis2 = axis(QCPAxis::atRight); + The appearance of the curve is determined by the pen and the brush (\ref setPen, \ref setBrush). - xAxis->setVisible(true); - yAxis->setVisible(true); - xAxis2->setVisible(true); - yAxis2->setVisible(true); - xAxis2->setTickLabels(false); - yAxis2->setTickLabels(false); + \section qcpcurve-usage Usage - xAxis2->setRange(xAxis->range()); - xAxis2->setRangeReversed(xAxis->rangeReversed()); - xAxis2->setScaleType(xAxis->scaleType()); - xAxis2->setScaleLogBase(xAxis->scaleLogBase()); - xAxis2->setTicks(xAxis->ticks()); - xAxis2->setAutoTickCount(xAxis->autoTickCount()); - xAxis2->setSubTickCount(xAxis->subTickCount()); - xAxis2->setAutoSubTicks(xAxis->autoSubTicks()); - xAxis2->setTickStep(xAxis->tickStep()); - xAxis2->setAutoTickStep(xAxis->autoTickStep()); - xAxis2->setNumberFormat(xAxis->numberFormat()); - xAxis2->setNumberPrecision(xAxis->numberPrecision()); - xAxis2->setTickLabelType(xAxis->tickLabelType()); - xAxis2->setDateTimeFormat(xAxis->dateTimeFormat()); - xAxis2->setDateTimeSpec(xAxis->dateTimeSpec()); + Like all data representing objects in QCustomPlot, the QCPCurve is a plottable + (QCPAbstractPlottable). So the plottable-interface of QCustomPlot applies + (QCustomPlot::plottable, QCustomPlot::removePlottable, etc.) + + Usually, you first create an instance: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcurve-creation-1 + which registers it with the QCustomPlot instance of the passed axes. Note that this QCustomPlot instance takes + ownership of the plottable, so do not delete it manually but use QCustomPlot::removePlottable() instead. + The newly created plottable can be modified, e.g.: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcurve-creation-2 +*/ - yAxis2->setRange(yAxis->range()); - yAxis2->setRangeReversed(yAxis->rangeReversed()); - yAxis2->setScaleType(yAxis->scaleType()); - yAxis2->setScaleLogBase(yAxis->scaleLogBase()); - yAxis2->setTicks(yAxis->ticks()); - yAxis2->setAutoTickCount(yAxis->autoTickCount()); - yAxis2->setSubTickCount(yAxis->subTickCount()); - yAxis2->setAutoSubTicks(yAxis->autoSubTicks()); - yAxis2->setTickStep(yAxis->tickStep()); - yAxis2->setAutoTickStep(yAxis->autoTickStep()); - yAxis2->setNumberFormat(yAxis->numberFormat()); - yAxis2->setNumberPrecision(yAxis->numberPrecision()); - yAxis2->setTickLabelType(yAxis->tickLabelType()); - yAxis2->setDateTimeFormat(yAxis->dateTimeFormat()); - yAxis2->setDateTimeSpec(yAxis->dateTimeSpec()); +/* start of documentation of inline functions */ + +/*! \fn QSharedPointer QCPCurve::data() const - if (connectRanges) - { - connect(xAxis, SIGNAL(rangeChanged(QCPRange)), xAxis2, SLOT(setRange(QCPRange))); - connect(yAxis, SIGNAL(rangeChanged(QCPRange)), yAxis2, SLOT(setRange(QCPRange))); - } -} + Returns a shared pointer to the internal data storage of type \ref QCPCurveDataContainer. You may + use it to directly manipulate the data, which may be more convenient and faster than using the + regular \ref setData or \ref addData methods. +*/ + +/* end of documentation of inline functions */ /*! - Returns a list of all the plottables that are associated with this axis rect. - - A plottable is considered associated with an axis rect if its key or value axis (or both) is in - this axis rect. + Constructs a curve which uses \a keyAxis as its key axis ("x") and \a valueAxis as its value + axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and not have + the same orientation. If either of these restrictions is violated, a corresponding message is + printed to the debug output (qDebug), the construction is not aborted, though. - \see graphs, items + The created QCPCurve is automatically registered with the QCustomPlot instance inferred from \a + keyAxis. This QCustomPlot instance takes ownership of the QCPCurve, so do not delete it manually + but use QCustomPlot::removePlottable() instead. */ -QList QCPAxisRect::plottables() const +QCPCurve::QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis) : + QCPAbstractPlottable1D(keyAxis, valueAxis), + mScatterSkip{}, + mLineStyle{} { - // Note: don't append all QCPAxis::plottables() into a list, because we might get duplicate entries - QList result; - for (int i=0; imPlottables.size(); ++i) - { - if (mParentPlot->mPlottables.at(i)->keyAxis()->axisRect() == this ||mParentPlot->mPlottables.at(i)->valueAxis()->axisRect() == this) - result.append(mParentPlot->mPlottables.at(i)); - } - return result; + // modify inherited properties from abstract plottable: + setPen(QPen(Qt::blue, 0)); + setBrush(Qt::NoBrush); + + setScatterStyle(QCPScatterStyle()); + setLineStyle(lsLine); + setScatterSkip(0); } -/*! - Returns a list of all the graphs that are associated with this axis rect. +QCPCurve::~QCPCurve() +{ +} + +/*! \overload - A graph is considered associated with an axis rect if its key or value axis (or both) is in - this axis rect. + Replaces the current data container with the provided \a data container. - \see plottables, items + Since a QSharedPointer is used, multiple QCPCurves may share the same data container safely. + Modifying the data in the container will then affect all curves that share the container. Sharing + can be achieved by simply exchanging the data containers wrapped in shared pointers: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcurve-datasharing-1 + + If you do not wish to share containers, but create a copy from an existing container, rather use + the \ref QCPDataContainer::set method on the curve's data container directly: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcurve-datasharing-2 + + \see addData */ -QList QCPAxisRect::graphs() const +void QCPCurve::setData(QSharedPointer data) { - // Note: don't append all QCPAxis::graphs() into a list, because we might get duplicate entries - QList result; - for (int i=0; imGraphs.size(); ++i) - { - if (mParentPlot->mGraphs.at(i)->keyAxis()->axisRect() == this || mParentPlot->mGraphs.at(i)->valueAxis()->axisRect() == this) - result.append(mParentPlot->mGraphs.at(i)); - } - return result; + mDataContainer = data; } -/*! - Returns a list of all the items that are associated with this axis rect. +/*! \overload - An item is considered associated with an axis rect if any of its positions has key or value axis - set to an axis that is in this axis rect, or if any of its positions has \ref - QCPItemPosition::setAxisRect set to the axis rect, or if the clip axis rect (\ref - QCPAbstractItem::setClipAxisRect) is set to this axis rect. + Replaces the current data with the provided points in \a t, \a keys and \a values. The provided + vectors should have equal length. Else, the number of added points will be the size of the + smallest vector. - \see plottables, graphs + If you can guarantee that the passed data points are sorted by \a t in ascending order, you can + set \a alreadySorted to true, to improve performance by saving a sorting run. + + \see addData */ -QList QCPAxisRect::items() const +void QCPCurve::setData(const QVector &t, const QVector &keys, const QVector &values, bool alreadySorted) { - // Note: don't just append all QCPAxis::items() into a list, because we might get duplicate entries - // and miss those items that have this axis rect as clipAxisRect. - QList result; - for (int itemId=0; itemIdmItems.size(); ++itemId) - { - if (mParentPlot->mItems.at(itemId)->clipAxisRect() == this) - { - result.append(mParentPlot->mItems.at(itemId)); - continue; - } - QList positions = mParentPlot->mItems.at(itemId)->positions(); - for (int posId=0; posIdaxisRect() == this || - positions.at(posId)->keyAxis()->axisRect() == this || - positions.at(posId)->valueAxis()->axisRect() == this) - { - result.append(mParentPlot->mItems.at(itemId)); - break; - } - } - } - return result; + mDataContainer->clear(); + addData(t, keys, values, alreadySorted); } -/*! - This method is called automatically upon replot and doesn't need to be called by users of - QCPAxisRect. + +/*! \overload - Calls the base class implementation to update the margins (see \ref QCPLayoutElement::update), - and finally passes the \ref rect to the inset layout (\ref insetLayout) and calls its - QCPInsetLayout::update function. -*/ -void QCPAxisRect::update(UpdatePhase phase) -{ - QCPLayoutElement::update(phase); + Replaces the current data with the provided points in \a keys and \a values. The provided vectors + should have equal length. Else, the number of added points will be the size of the smallest + vector. - switch (phase) - { - case upPreparation: - { - QList allAxes = axes(); - for (int i=0; isetupTickVectors(); - break; - } - case upLayout: - { - mInsetLayout->setOuterRect(rect()); - break; - } - default: break; - } + The t parameter of each data point will be set to the integer index of the respective key/value + pair. - // pass update call on to inset layout (doesn't happen automatically, because QCPAxisRect doesn't derive from QCPLayout): - mInsetLayout->update(phase); -} - -/* inherits documentation from base class */ -QList QCPAxisRect::elements(bool recursive) const + \see addData +*/ +void QCPCurve::setData(const QVector &keys, const QVector &values) { - QList result; - if (mInsetLayout) - { - result << mInsetLayout; - if (recursive) - result << mInsetLayout->elements(recursive); - } - return result; + mDataContainer->clear(); + addData(keys, values); } -/* inherits documentation from base class */ -void QCPAxisRect::applyDefaultAntialiasingHint(QCPPainter *painter) const +/*! + Sets the visual appearance of single data points in the plot. If set to \ref + QCPScatterStyle::ssNone, no scatter points are drawn (e.g. for line-only plots with appropriate + line style). + + \see QCPScatterStyle, setLineStyle +*/ +void QCPCurve::setScatterStyle(const QCPScatterStyle &style) { - painter->setAntialiasing(false); + mScatterStyle = style; } -/* inherits documentation from base class */ -void QCPAxisRect::draw(QCPPainter *painter) +/*! + If scatters are displayed (scatter style not \ref QCPScatterStyle::ssNone), \a skip number of + scatter points are skipped/not drawn after every drawn scatter point. + + This can be used to make the data appear sparser while for example still having a smooth line, + and to improve performance for very high density plots. + + If \a skip is set to 0 (default), all scatter points are drawn. + + \see setScatterStyle +*/ +void QCPCurve::setScatterSkip(int skip) { - drawBackground(painter); + mScatterSkip = qMax(0, skip); } /*! - Sets \a pm as the axis background pixmap. The axis background pixmap will be drawn inside the - axis rect. Since axis rects place themselves on the "background" layer by default, the axis rect - backgrounds are usually drawn below everything else. - - For cases where the provided pixmap doesn't have the same size as the axis rect, scaling can be - enabled with \ref setBackgroundScaled and the scaling mode (i.e. whether and how the aspect ratio - is preserved) can be set with \ref setBackgroundScaledMode. To set all these options in one call, - consider using the overloaded version of this function. - - Below the pixmap, the axis rect may be optionally filled with a brush, if specified with \ref - setBackground(const QBrush &brush). + Sets how the single data points are connected in the plot or how they are represented visually + apart from the scatter symbol. For scatter-only plots, set \a style to \ref lsNone and \ref + setScatterStyle to the desired scatter style. - \see setBackgroundScaled, setBackgroundScaledMode, setBackground(const QBrush &brush) + \see setScatterStyle */ -void QCPAxisRect::setBackground(const QPixmap &pm) +void QCPCurve::setLineStyle(QCPCurve::LineStyle style) { - mBackgroundPixmap = pm; - mScaledBackgroundPixmap = QPixmap(); + mLineStyle = style; } /*! \overload - Sets \a brush as the background brush. The axis rect background will be filled with this brush. - Since axis rects place themselves on the "background" layer by default, the axis rect backgrounds - are usually drawn below everything else. - - The brush will be drawn before (under) any background pixmap, which may be specified with \ref - setBackground(const QPixmap &pm). - - To disable drawing of a background brush, set \a brush to Qt::NoBrush. + Adds the provided points in \a t, \a keys and \a values to the current data. The provided vectors + should have equal length. Else, the number of added points will be the size of the smallest + vector. - \see setBackground(const QPixmap &pm) + If you can guarantee that the passed data points are sorted by \a keys in ascending order, you + can set \a alreadySorted to true, to improve performance by saving a sorting run. + + Alternatively, you can also access and modify the data directly via the \ref data method, which + returns a pointer to the internal data container. */ -void QCPAxisRect::setBackground(const QBrush &brush) +void QCPCurve::addData(const QVector &t, const QVector &keys, const QVector &values, bool alreadySorted) { - mBackgroundBrush = brush; + if (t.size() != keys.size() || t.size() != values.size()) + qDebug() << Q_FUNC_INFO << "ts, keys and values have different sizes:" << t.size() << keys.size() << values.size(); + const int n = qMin(qMin(t.size(), keys.size()), values.size()); + QVector tempData(n); + QVector::iterator it = tempData.begin(); + const QVector::iterator itEnd = tempData.end(); + int i = 0; + while (it != itEnd) + { + it->t = t[i]; + it->key = keys[i]; + it->value = values[i]; + ++it; + ++i; + } + mDataContainer->add(tempData, alreadySorted); // don't modify tempData beyond this to prevent copy on write } /*! \overload - Allows setting the background pixmap of the axis rect, whether it shall be scaled and how it - shall be scaled in one call. - - \see setBackground(const QPixmap &pm), setBackgroundScaled, setBackgroundScaledMode + Adds the provided points in \a keys and \a values to the current data. The provided vectors + should have equal length. Else, the number of added points will be the size of the smallest + vector. + + The t parameter of each data point will be set to the integer index of the respective key/value + pair. + + Alternatively, you can also access and modify the data directly via the \ref data method, which + returns a pointer to the internal data container. */ -void QCPAxisRect::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode) +void QCPCurve::addData(const QVector &keys, const QVector &values) { - mBackgroundPixmap = pm; - mScaledBackgroundPixmap = QPixmap(); - mBackgroundScaled = scaled; - mBackgroundScaledMode = mode; + if (keys.size() != values.size()) + qDebug() << Q_FUNC_INFO << "keys and values have different sizes:" << keys.size() << values.size(); + const int n = qMin(keys.size(), values.size()); + double tStart; + if (!mDataContainer->isEmpty()) + tStart = (mDataContainer->constEnd()-1)->t + 1.0; + else + tStart = 0; + QVector tempData(n); + QVector::iterator it = tempData.begin(); + const QVector::iterator itEnd = tempData.end(); + int i = 0; + while (it != itEnd) + { + it->t = tStart + i; + it->key = keys[i]; + it->value = values[i]; + ++it; + ++i; + } + mDataContainer->add(tempData, true); // don't modify tempData beyond this to prevent copy on write } -/*! - Sets whether the axis background pixmap shall be scaled to fit the axis rect or not. If \a scaled - is set to true, you may control whether and how the aspect ratio of the original pixmap is - preserved with \ref setBackgroundScaledMode. - - Note that the scaled version of the original pixmap is buffered, so there is no performance - penalty on replots. (Except when the axis rect dimensions are changed continuously.) +/*! \overload + Adds the provided data point as \a t, \a key and \a value to the current data. - \see setBackground, setBackgroundScaledMode + Alternatively, you can also access and modify the data directly via the \ref data method, which + returns a pointer to the internal data container. */ -void QCPAxisRect::setBackgroundScaled(bool scaled) +void QCPCurve::addData(double t, double key, double value) { - mBackgroundScaled = scaled; + mDataContainer->add(QCPCurveData(t, key, value)); } -/*! - If scaling of the axis background pixmap is enabled (\ref setBackgroundScaled), use this function to - define whether and how the aspect ratio of the original pixmap passed to \ref setBackground is preserved. - \see setBackground, setBackgroundScaled +/*! \overload + + Adds the provided data point as \a key and \a value to the current data. + + The t parameter is generated automatically by increments of 1 for each point, starting at the + highest t of previously existing data or 0, if the curve data is empty. + + Alternatively, you can also access and modify the data directly via the \ref data method, which + returns a pointer to the internal data container. */ -void QCPAxisRect::setBackgroundScaledMode(Qt::AspectRatioMode mode) +void QCPCurve::addData(double key, double value) { - mBackgroundScaledMode = mode; + if (!mDataContainer->isEmpty()) + mDataContainer->add(QCPCurveData((mDataContainer->constEnd()-1)->t + 1.0, key, value)); + else + mDataContainer->add(QCPCurveData(0.0, key, value)); } /*! - Returns the range drag axis of the \a orientation provided. + Implements a selectTest specific to this plottable's point geometry. + + If \a details is not 0, it will be set to a \ref QCPDataSelection, describing the closest data + point to \a pos. - \see setRangeDragAxes + \seebaseclassmethod \ref QCPAbstractPlottable::selectTest */ -QCPAxis *QCPAxisRect::rangeDragAxis(Qt::Orientation orientation) +double QCPCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - return (orientation == Qt::Horizontal ? mRangeDragHorzAxis.data() : mRangeDragVertAxis.data()); + if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty()) + return -1; + if (!mKeyAxis || !mValueAxis) + return -1; + + if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect)) + { + QCPCurveDataContainer::const_iterator closestDataPoint = mDataContainer->constEnd(); + double result = pointDistance(pos, closestDataPoint); + if (details) + { + int pointIndex = int( closestDataPoint-mDataContainer->constBegin() ); + details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1))); + } + return result; + } else + return -1; } -/*! - Returns the range zoom axis of the \a orientation provided. - - \see setRangeZoomAxes -*/ -QCPAxis *QCPAxisRect::rangeZoomAxis(Qt::Orientation orientation) +/* inherits documentation from base class */ +QCPRange QCPCurve::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const { - return (orientation == Qt::Horizontal ? mRangeZoomHorzAxis.data() : mRangeZoomVertAxis.data()); + return mDataContainer->keyRange(foundRange, inSignDomain); } -/*! - Returns the range zoom factor of the \a orientation provided. - - \see setRangeZoomFactor -*/ -double QCPAxisRect::rangeZoomFactor(Qt::Orientation orientation) +/* inherits documentation from base class */ +QCPRange QCPCurve::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const { - return (orientation == Qt::Horizontal ? mRangeZoomFactorHorz : mRangeZoomFactorVert); + return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange); } -/*! - Sets which axis orientation may be range dragged by the user with mouse interaction. - What orientation corresponds to which specific axis can be set with - \ref setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical). By - default, the horizontal axis is the bottom axis (xAxis) and the vertical axis - is the left axis (yAxis). +/* inherits documentation from base class */ +void QCPCurve::draw(QCPPainter *painter) +{ + if (mDataContainer->isEmpty()) return; - To disable range dragging entirely, pass 0 as \a orientations or remove \ref QCP::iRangeDrag from \ref - QCustomPlot::setInteractions. To enable range dragging for both directions, pass Qt::Horizontal | - Qt::Vertical as \a orientations. + // allocate line vector: + QVector lines, scatters; - In addition to setting \a orientations to a non-zero value, make sure \ref QCustomPlot::setInteractions - contains \ref QCP::iRangeDrag to enable the range dragging interaction. + // loop over and draw segments of unselected/selected data: + QList selectedSegments, unselectedSegments, allSegments; + getDataSegments(selectedSegments, unselectedSegments); + allSegments << unselectedSegments << selectedSegments; + for (int i=0; i= unselectedSegments.size(); + + // fill with curve data: + QPen finalCurvePen = mPen; // determine the final pen already here, because the line optimization depends on its stroke width + if (isSelectedSegment && mSelectionDecorator) + finalCurvePen = mSelectionDecorator->pen(); + + QCPDataRange lineDataRange = isSelectedSegment ? allSegments.at(i) : allSegments.at(i).adjusted(-1, 1); // unselected segments extend lines to bordering selected data point (safe to exceed total data bounds in first/last segment, getCurveLines takes care) + getCurveLines(&lines, lineDataRange, finalCurvePen.widthF()); + + // check data validity if flag set: + #ifdef QCUSTOMPLOT_CHECK_DATA + for (QCPCurveDataContainer::const_iterator it = mDataContainer->constBegin(); it != mDataContainer->constEnd(); ++it) + { + if (QCP::isInvalidData(it->t) || + QCP::isInvalidData(it->key, it->value)) + qDebug() << Q_FUNC_INFO << "Data point at" << it->key << "invalid." << "Plottable name:" << name(); + } + #endif + + // draw curve fill: + applyFillAntialiasingHint(painter); + if (isSelectedSegment && mSelectionDecorator) + mSelectionDecorator->applyBrush(painter); + else + painter->setBrush(mBrush); + painter->setPen(Qt::NoPen); + if (painter->brush().style() != Qt::NoBrush && painter->brush().color().alpha() != 0) + painter->drawPolygon(QPolygonF(lines)); + + // draw curve line: + if (mLineStyle != lsNone) + { + painter->setPen(finalCurvePen); + painter->setBrush(Qt::NoBrush); + drawCurveLine(painter, lines); + } + + // draw scatters: + QCPScatterStyle finalScatterStyle = mScatterStyle; + if (isSelectedSegment && mSelectionDecorator) + finalScatterStyle = mSelectionDecorator->getFinalScatterStyle(mScatterStyle); + if (!finalScatterStyle.isNone()) + { + getScatters(&scatters, allSegments.at(i), finalScatterStyle.size()); + drawScatterPlot(painter, scatters, finalScatterStyle); + } + } - \see setRangeZoom, setRangeDragAxes, QCustomPlot::setNoAntialiasingOnDrag + // draw other selection decoration that isn't just line/scatter pens and brushes: + if (mSelectionDecorator) + mSelectionDecorator->drawDecoration(painter, selection()); +} + +/* inherits documentation from base class */ +void QCPCurve::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const +{ + // draw fill: + if (mBrush.style() != Qt::NoBrush) + { + applyFillAntialiasingHint(painter); + painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush); + } + // draw line vertically centered: + if (mLineStyle != lsNone) + { + applyDefaultAntialiasingHint(painter); + painter->setPen(mPen); + painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens + } + // draw scatter symbol: + if (!mScatterStyle.isNone()) + { + applyScattersAntialiasingHint(painter); + // scale scatter pixmap if it's too large to fit in legend icon rect: + if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height())) + { + QCPScatterStyle scaledStyle(mScatterStyle); + scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); + scaledStyle.applyTo(painter, mPen); + scaledStyle.drawShape(painter, QRectF(rect).center()); + } else + { + mScatterStyle.applyTo(painter, mPen); + mScatterStyle.drawShape(painter, QRectF(rect).center()); + } + } +} + +/*! \internal + + Draws lines between the points in \a lines, given in pixel coordinates. + + \see drawScatterPlot, getCurveLines */ -void QCPAxisRect::setRangeDrag(Qt::Orientations orientations) +void QCPCurve::drawCurveLine(QCPPainter *painter, const QVector &lines) const { - mRangeDrag = orientations; + if (painter->pen().style() != Qt::NoPen && painter->pen().color().alpha() != 0) + { + applyDefaultAntialiasingHint(painter); + drawPolyline(painter, lines); + } } -/*! - Sets which axis orientation may be zoomed by the user with the mouse wheel. What orientation - corresponds to which specific axis can be set with \ref setRangeZoomAxes(QCPAxis *horizontal, - QCPAxis *vertical). By default, the horizontal axis is the bottom axis (xAxis) and the vertical - axis is the left axis (yAxis). +/*! \internal - To disable range zooming entirely, pass 0 as \a orientations or remove \ref QCP::iRangeZoom from \ref - QCustomPlot::setInteractions. To enable range zooming for both directions, pass Qt::Horizontal | - Qt::Vertical as \a orientations. - - In addition to setting \a orientations to a non-zero value, make sure \ref QCustomPlot::setInteractions - contains \ref QCP::iRangeZoom to enable the range zooming interaction. - - \see setRangeZoomFactor, setRangeZoomAxes, setRangeDrag + Draws scatter symbols at every point passed in \a points, given in pixel coordinates. The + scatters will be drawn with \a painter and have the appearance as specified in \a style. + + \see drawCurveLine, getCurveLines */ -void QCPAxisRect::setRangeZoom(Qt::Orientations orientations) +void QCPCurve::drawScatterPlot(QCPPainter *painter, const QVector &points, const QCPScatterStyle &style) const { - mRangeZoom = orientations; + // draw scatter point symbols: + applyScattersAntialiasingHint(painter); + style.applyTo(painter, mPen); + foreach (const QPointF &point, points) + if (!qIsNaN(point.x()) && !qIsNaN(point.y())) + style.drawShape(painter, point); +} + +/*! \internal + + Called by \ref draw to generate points in pixel coordinates which represent the line of the + curve. + + Line segments that aren't visible in the current axis rect are handled in an optimized way. They + are projected onto a rectangle slightly larger than the visible axis rect and simplified + regarding point count. The algorithm makes sure to preserve appearance of lines and fills inside + the visible axis rect by generating new temporary points on the outer rect if necessary. + + \a lines will be filled with points in pixel coordinates, that can be drawn with \ref + drawCurveLine. + + \a dataRange specifies the beginning and ending data indices that will be taken into account for + conversion. In this function, the specified range may exceed the total data bounds without harm: + a correspondingly trimmed data range will be used. This takes the burden off the user of this + function to check for valid indices in \a dataRange, e.g. when extending ranges coming from \ref + getDataSegments. + + \a penWidth specifies the pen width that will be used to later draw the lines generated by this + function. This is needed here to calculate an accordingly wider margin around the axis rect when + performing the line optimization. + + Methods that are also involved in the algorithm are: \ref getRegion, \ref getOptimizedPoint, \ref + getOptimizedCornerPoints \ref mayTraverse, \ref getTraverse, \ref getTraverseCornerPoints. + + \see drawCurveLine, drawScatterPlot +*/ +void QCPCurve::getCurveLines(QVector *lines, const QCPDataRange &dataRange, double penWidth) const +{ + if (!lines) return; + lines->clear(); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + // add margins to rect to compensate for stroke width + const double strokeMargin = qMax(qreal(1.0), qreal(penWidth*0.75)); // stroke radius + 50% safety + const double keyMin = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().lower)-strokeMargin*keyAxis->pixelOrientation()); + const double keyMax = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().upper)+strokeMargin*keyAxis->pixelOrientation()); + const double valueMin = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().lower)-strokeMargin*valueAxis->pixelOrientation()); + const double valueMax = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().upper)+strokeMargin*valueAxis->pixelOrientation()); + QCPCurveDataContainer::const_iterator itBegin = mDataContainer->constBegin(); + QCPCurveDataContainer::const_iterator itEnd = mDataContainer->constEnd(); + mDataContainer->limitIteratorsToDataRange(itBegin, itEnd, dataRange); + if (itBegin == itEnd) + return; + QCPCurveDataContainer::const_iterator it = itBegin; + QCPCurveDataContainer::const_iterator prevIt = itEnd-1; + int prevRegion = getRegion(prevIt->key, prevIt->value, keyMin, valueMax, keyMax, valueMin); + QVector trailingPoints; // points that must be applied after all other points (are generated only when handling first point to get virtual segment between last and first point right) + while (it != itEnd) + { + const int currentRegion = getRegion(it->key, it->value, keyMin, valueMax, keyMax, valueMin); + if (currentRegion != prevRegion) // changed region, possibly need to add some optimized edge points or original points if entering R + { + if (currentRegion != 5) // segment doesn't end in R, so it's a candidate for removal + { + QPointF crossA, crossB; + if (prevRegion == 5) // we're coming from R, so add this point optimized + { + lines->append(getOptimizedPoint(currentRegion, it->key, it->value, prevIt->key, prevIt->value, keyMin, valueMax, keyMax, valueMin)); + // in the situations 5->1/7/9/3 the segment may leave R and directly cross through two outer regions. In these cases we need to add an additional corner point + *lines << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin); + } else if (mayTraverse(prevRegion, currentRegion) && + getTraverse(prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin, crossA, crossB)) + { + // add the two cross points optimized if segment crosses R and if segment isn't virtual zeroth segment between last and first curve point: + QVector beforeTraverseCornerPoints, afterTraverseCornerPoints; + getTraverseCornerPoints(prevRegion, currentRegion, keyMin, valueMax, keyMax, valueMin, beforeTraverseCornerPoints, afterTraverseCornerPoints); + if (it != itBegin) + { + *lines << beforeTraverseCornerPoints; + lines->append(crossA); + lines->append(crossB); + *lines << afterTraverseCornerPoints; + } else + { + lines->append(crossB); + *lines << afterTraverseCornerPoints; + trailingPoints << beforeTraverseCornerPoints << crossA ; + } + } else // doesn't cross R, line is just moving around in outside regions, so only need to add optimized point(s) at the boundary corner(s) + { + *lines << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin); + } + } else // segment does end in R, so we add previous point optimized and this point at original position + { + if (it == itBegin) // it is first point in curve and prevIt is last one. So save optimized point for adding it to the lineData in the end + trailingPoints << getOptimizedPoint(prevRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin); + else + lines->append(getOptimizedPoint(prevRegion, prevIt->key, prevIt->value, it->key, it->value, keyMin, valueMax, keyMax, valueMin)); + lines->append(coordsToPixels(it->key, it->value)); + } + } else // region didn't change + { + if (currentRegion == 5) // still in R, keep adding original points + { + lines->append(coordsToPixels(it->key, it->value)); + } else // still outside R, no need to add anything + { + // see how this is not doing anything? That's the main optimization... + } + } + prevIt = it; + prevRegion = currentRegion; + ++it; + } + *lines << trailingPoints; } -/*! - Sets the axes whose range will be dragged when \ref setRangeDrag enables mouse range dragging - on the QCustomPlot widget. - - \see setRangeZoomAxes -*/ -void QCPAxisRect::setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical) -{ - mRangeDragHorzAxis = horizontal; - mRangeDragVertAxis = vertical; -} +/*! \internal -/*! - Sets the axes whose range will be zoomed when \ref setRangeZoom enables mouse wheel zooming on the - QCustomPlot widget. The two axes can be zoomed with different strengths, when different factors - are passed to \ref setRangeZoomFactor(double horizontalFactor, double verticalFactor). - - \see setRangeDragAxes + Called by \ref draw to generate points in pixel coordinates which represent the scatters of the + curve. If a scatter skip is configured (\ref setScatterSkip), the returned points are accordingly + sparser. + + Scatters that aren't visible in the current axis rect are optimized away. + + \a scatters will be filled with points in pixel coordinates, that can be drawn with \ref + drawScatterPlot. + + \a dataRange specifies the beginning and ending data indices that will be taken into account for + conversion. + + \a scatterWidth specifies the scatter width that will be used to later draw the scatters at pixel + coordinates generated by this function. This is needed here to calculate an accordingly wider + margin around the axis rect when performing the data point reduction. + + \see draw, drawScatterPlot */ -void QCPAxisRect::setRangeZoomAxes(QCPAxis *horizontal, QCPAxis *vertical) +void QCPCurve::getScatters(QVector *scatters, const QCPDataRange &dataRange, double scatterWidth) const { - mRangeZoomHorzAxis = horizontal; - mRangeZoomVertAxis = vertical; + if (!scatters) return; + scatters->clear(); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + QCPCurveDataContainer::const_iterator begin = mDataContainer->constBegin(); + QCPCurveDataContainer::const_iterator end = mDataContainer->constEnd(); + mDataContainer->limitIteratorsToDataRange(begin, end, dataRange); + if (begin == end) + return; + const int scatterModulo = mScatterSkip+1; + const bool doScatterSkip = mScatterSkip > 0; + int endIndex = int( end-mDataContainer->constBegin() ); + + QCPRange keyRange = keyAxis->range(); + QCPRange valueRange = valueAxis->range(); + // extend range to include width of scatter symbols: + keyRange.lower = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyRange.lower)-scatterWidth*keyAxis->pixelOrientation()); + keyRange.upper = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyRange.upper)+scatterWidth*keyAxis->pixelOrientation()); + valueRange.lower = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueRange.lower)-scatterWidth*valueAxis->pixelOrientation()); + valueRange.upper = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueRange.upper)+scatterWidth*valueAxis->pixelOrientation()); + + QCPCurveDataContainer::const_iterator it = begin; + int itIndex = int( begin-mDataContainer->constBegin() ); + while (doScatterSkip && it != end && itIndex % scatterModulo != 0) // advance begin iterator to first non-skipped scatter + { + ++itIndex; + ++it; + } + if (keyAxis->orientation() == Qt::Vertical) + { + while (it != end) + { + if (!qIsNaN(it->value) && keyRange.contains(it->key) && valueRange.contains(it->value)) + scatters->append(QPointF(valueAxis->coordToPixel(it->value), keyAxis->coordToPixel(it->key))); + + // advance iterator to next (non-skipped) data point: + if (!doScatterSkip) + ++it; + else + { + itIndex += scatterModulo; + if (itIndex < endIndex) // make sure we didn't jump over end + it += scatterModulo; + else + { + it = end; + itIndex = endIndex; + } + } + } + } else + { + while (it != end) + { + if (!qIsNaN(it->value) && keyRange.contains(it->key) && valueRange.contains(it->value)) + scatters->append(QPointF(keyAxis->coordToPixel(it->key), valueAxis->coordToPixel(it->value))); + + // advance iterator to next (non-skipped) data point: + if (!doScatterSkip) + ++it; + else + { + itIndex += scatterModulo; + if (itIndex < endIndex) // make sure we didn't jump over end + it += scatterModulo; + else + { + it = end; + itIndex = endIndex; + } + } + } + } } -/*! - Sets how strong one rotation step of the mouse wheel zooms, when range zoom was activated with - \ref setRangeZoom. The two parameters \a horizontalFactor and \a verticalFactor provide a way to - let the horizontal axis zoom at different rates than the vertical axis. Which axis is horizontal - and which is vertical, can be set with \ref setRangeZoomAxes. +/*! \internal - When the zoom factor is greater than one, scrolling the mouse wheel backwards (towards the user) - will zoom in (make the currently visible range smaller). For zoom factors smaller than one, the - same scrolling direction will zoom out. + This function is part of the curve optimization algorithm of \ref getCurveLines. + + It returns the region of the given point (\a key, \a value) with respect to a rectangle defined + by \a keyMin, \a keyMax, \a valueMin, and \a valueMax. + + The regions are enumerated from top to bottom (\a valueMin to \a valueMax) and left to right (\a + keyMin to \a keyMax): + + + + + +
147
258
369
+ + With the rectangle being region 5, and the outer regions extending infinitely outwards. In the + curve optimization algorithm, region 5 is considered to be the visible portion of the plot. */ -void QCPAxisRect::setRangeZoomFactor(double horizontalFactor, double verticalFactor) +int QCPCurve::getRegion(double key, double value, double keyMin, double valueMax, double keyMax, double valueMin) const { - mRangeZoomFactorHorz = horizontalFactor; - mRangeZoomFactorVert = verticalFactor; + if (key < keyMin) // region 123 + { + if (value > valueMax) + return 1; + else if (value < valueMin) + return 3; + else + return 2; + } else if (key > keyMax) // region 789 + { + if (value > valueMax) + return 7; + else if (value < valueMin) + return 9; + else + return 8; + } else // region 456 + { + if (value > valueMax) + return 4; + else if (value < valueMin) + return 6; + else + return 5; + } } -/*! \overload +/*! \internal - Sets both the horizontal and vertical zoom \a factor. + This function is part of the curve optimization algorithm of \ref getCurveLines. + + This method is used in case the current segment passes from inside the visible rect (region 5, + see \ref getRegion) to any of the outer regions (\a otherRegion). The current segment is given by + the line connecting (\a key, \a value) with (\a otherKey, \a otherValue). + + It returns the intersection point of the segment with the border of region 5. + + For this function it doesn't matter whether (\a key, \a value) is the point inside region 5 or + whether it's (\a otherKey, \a otherValue), i.e. whether the segment is coming from region 5 or + leaving it. It is important though that \a otherRegion correctly identifies the other region not + equal to 5. */ -void QCPAxisRect::setRangeZoomFactor(double factor) -{ - mRangeZoomFactorHorz = factor; - mRangeZoomFactorVert = factor; +QPointF QCPCurve::getOptimizedPoint(int otherRegion, double otherKey, double otherValue, double key, double value, double keyMin, double valueMax, double keyMax, double valueMin) const +{ + // The intersection point interpolation here is done in pixel coordinates, so we don't need to + // differentiate between different axis scale types. Note that the nomenclature + // top/left/bottom/right/min/max is with respect to the rect in plot coordinates, wich may be + // different in pixel coordinates (horz/vert key axes, reversed ranges) + + const double keyMinPx = mKeyAxis->coordToPixel(keyMin); + const double keyMaxPx = mKeyAxis->coordToPixel(keyMax); + const double valueMinPx = mValueAxis->coordToPixel(valueMin); + const double valueMaxPx = mValueAxis->coordToPixel(valueMax); + const double otherValuePx = mValueAxis->coordToPixel(otherValue); + const double valuePx = mValueAxis->coordToPixel(value); + const double otherKeyPx = mKeyAxis->coordToPixel(otherKey); + const double keyPx = mKeyAxis->coordToPixel(key); + double intersectKeyPx = keyMinPx; // initial key just a fail-safe + double intersectValuePx = valueMinPx; // initial value just a fail-safe + switch (otherRegion) + { + case 1: // top and left edge + { + intersectValuePx = valueMaxPx; + intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx); + if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether top edge is not intersected, then it must be left edge (qMin/qMax necessary since axes may be reversed) + { + intersectKeyPx = keyMinPx; + intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx); + } + break; + } + case 2: // left edge + { + intersectKeyPx = keyMinPx; + intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx); + break; + } + case 3: // bottom and left edge + { + intersectValuePx = valueMinPx; + intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx); + if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether bottom edge is not intersected, then it must be left edge (qMin/qMax necessary since axes may be reversed) + { + intersectKeyPx = keyMinPx; + intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx); + } + break; + } + case 4: // top edge + { + intersectValuePx = valueMaxPx; + intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx); + break; + } + case 5: + { + break; // case 5 shouldn't happen for this function but we add it anyway to prevent potential discontinuity in branch table + } + case 6: // bottom edge + { + intersectValuePx = valueMinPx; + intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx); + break; + } + case 7: // top and right edge + { + intersectValuePx = valueMaxPx; + intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx); + if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether top edge is not intersected, then it must be right edge (qMin/qMax necessary since axes may be reversed) + { + intersectKeyPx = keyMaxPx; + intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx); + } + break; + } + case 8: // right edge + { + intersectKeyPx = keyMaxPx; + intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx); + break; + } + case 9: // bottom and right edge + { + intersectValuePx = valueMinPx; + intersectKeyPx = otherKeyPx + (keyPx-otherKeyPx)/(valuePx-otherValuePx)*(intersectValuePx-otherValuePx); + if (intersectKeyPx < qMin(keyMinPx, keyMaxPx) || intersectKeyPx > qMax(keyMinPx, keyMaxPx)) // check whether bottom edge is not intersected, then it must be right edge (qMin/qMax necessary since axes may be reversed) + { + intersectKeyPx = keyMaxPx; + intersectValuePx = otherValuePx + (valuePx-otherValuePx)/(keyPx-otherKeyPx)*(intersectKeyPx-otherKeyPx); + } + break; + } + } + if (mKeyAxis->orientation() == Qt::Horizontal) + return {intersectKeyPx, intersectValuePx}; + else + return {intersectValuePx, intersectKeyPx}; } /*! \internal - Draws the background of this axis rect. It may consist of a background fill (a QBrush) and a - pixmap. - - If a brush was given via \ref setBackground(const QBrush &brush), this function first draws an - according filling inside the axis rect with the provided \a painter. + This function is part of the curve optimization algorithm of \ref getCurveLines. - Then, if a pixmap was provided via \ref setBackground, this function buffers the scaled version - depending on \ref setBackgroundScaled and \ref setBackgroundScaledMode and then draws it inside - the axis rect with the provided \a painter. The scaled version is buffered in - mScaledBackgroundPixmap to prevent expensive rescaling at every redraw. It is only updated, when - the axis rect has changed in a way that requires a rescale of the background pixmap (this is - dependant on the \ref setBackgroundScaledMode), or when a differend axis backgroud pixmap was - set. + In situations where a single segment skips over multiple regions it might become necessary to add + extra points at the corners of region 5 (see \ref getRegion) such that the optimized segment + doesn't unintentionally cut through the visible area of the axis rect and create plot artifacts. + This method provides these points that must be added, assuming the original segment doesn't + start, end, or traverse region 5. (Corner points where region 5 is traversed are calculated by + \ref getTraverseCornerPoints.) - \see setBackground, setBackgroundScaled, setBackgroundScaledMode + For example, consider a segment which directly goes from region 4 to 2 but originally is far out + to the top left such that it doesn't cross region 5. Naively optimizing these points by + projecting them on the top and left borders of region 5 will create a segment that surely crosses + 5, creating a visual artifact in the plot. This method prevents this by providing extra points at + the top left corner, making the optimized curve correctly pass from region 4 to 1 to 2 without + traversing 5. */ -void QCPAxisRect::drawBackground(QCPPainter *painter) +QVector QCPCurve::getOptimizedCornerPoints(int prevRegion, int currentRegion, double prevKey, double prevValue, double key, double value, double keyMin, double valueMax, double keyMax, double valueMin) const { - // draw background fill: - if (mBackgroundBrush != Qt::NoBrush) - painter->fillRect(mRect, mBackgroundBrush); - - // draw background pixmap (on top of fill, if brush specified): - if (!mBackgroundPixmap.isNull()) + QVector result; + switch (prevRegion) { - if (mBackgroundScaled) + case 1: + { + switch (currentRegion) + { + case 2: { result << coordsToPixels(keyMin, valueMax); break; } + case 4: { result << coordsToPixels(keyMin, valueMax); break; } + case 3: { result << coordsToPixels(keyMin, valueMax) << coordsToPixels(keyMin, valueMin); break; } + case 7: { result << coordsToPixels(keyMin, valueMax) << coordsToPixels(keyMax, valueMax); break; } + case 6: { result << coordsToPixels(keyMin, valueMax) << coordsToPixels(keyMin, valueMin); result.append(result.last()); break; } + case 8: { result << coordsToPixels(keyMin, valueMax) << coordsToPixels(keyMax, valueMax); result.append(result.last()); break; } + case 9: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points + if ((value-prevValue)/(key-prevKey)*(keyMin-key)+value < valueMin) // segment passes below R + { result << coordsToPixels(keyMin, valueMax) << coordsToPixels(keyMin, valueMin); result.append(result.last()); result << coordsToPixels(keyMax, valueMin); } + else + { result << coordsToPixels(keyMin, valueMax) << coordsToPixels(keyMax, valueMax); result.append(result.last()); result << coordsToPixels(keyMax, valueMin); } + break; + } + } + break; + } + case 2: + { + switch (currentRegion) + { + case 1: { result << coordsToPixels(keyMin, valueMax); break; } + case 3: { result << coordsToPixels(keyMin, valueMin); break; } + case 4: { result << coordsToPixels(keyMin, valueMax); result.append(result.last()); break; } + case 6: { result << coordsToPixels(keyMin, valueMin); result.append(result.last()); break; } + case 7: { result << coordsToPixels(keyMin, valueMax); result.append(result.last()); result << coordsToPixels(keyMax, valueMax); break; } + case 9: { result << coordsToPixels(keyMin, valueMin); result.append(result.last()); result << coordsToPixels(keyMax, valueMin); break; } + } + break; + } + case 3: + { + switch (currentRegion) + { + case 2: { result << coordsToPixels(keyMin, valueMin); break; } + case 6: { result << coordsToPixels(keyMin, valueMin); break; } + case 1: { result << coordsToPixels(keyMin, valueMin) << coordsToPixels(keyMin, valueMax); break; } + case 9: { result << coordsToPixels(keyMin, valueMin) << coordsToPixels(keyMax, valueMin); break; } + case 4: { result << coordsToPixels(keyMin, valueMin) << coordsToPixels(keyMin, valueMax); result.append(result.last()); break; } + case 8: { result << coordsToPixels(keyMin, valueMin) << coordsToPixels(keyMax, valueMin); result.append(result.last()); break; } + case 7: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points + if ((value-prevValue)/(key-prevKey)*(keyMax-key)+value < valueMin) // segment passes below R + { result << coordsToPixels(keyMin, valueMin) << coordsToPixels(keyMax, valueMin); result.append(result.last()); result << coordsToPixels(keyMax, valueMax); } + else + { result << coordsToPixels(keyMin, valueMin) << coordsToPixels(keyMin, valueMax); result.append(result.last()); result << coordsToPixels(keyMax, valueMax); } + break; + } + } + break; + } + case 4: + { + switch (currentRegion) + { + case 1: { result << coordsToPixels(keyMin, valueMax); break; } + case 7: { result << coordsToPixels(keyMax, valueMax); break; } + case 2: { result << coordsToPixels(keyMin, valueMax); result.append(result.last()); break; } + case 8: { result << coordsToPixels(keyMax, valueMax); result.append(result.last()); break; } + case 3: { result << coordsToPixels(keyMin, valueMax); result.append(result.last()); result << coordsToPixels(keyMin, valueMin); break; } + case 9: { result << coordsToPixels(keyMax, valueMax); result.append(result.last()); result << coordsToPixels(keyMax, valueMin); break; } + } + break; + } + case 5: + { + switch (currentRegion) + { + case 1: { result << coordsToPixels(keyMin, valueMax); break; } + case 7: { result << coordsToPixels(keyMax, valueMax); break; } + case 9: { result << coordsToPixels(keyMax, valueMin); break; } + case 3: { result << coordsToPixels(keyMin, valueMin); break; } + } + break; + } + case 6: + { + switch (currentRegion) + { + case 3: { result << coordsToPixels(keyMin, valueMin); break; } + case 9: { result << coordsToPixels(keyMax, valueMin); break; } + case 2: { result << coordsToPixels(keyMin, valueMin); result.append(result.last()); break; } + case 8: { result << coordsToPixels(keyMax, valueMin); result.append(result.last()); break; } + case 1: { result << coordsToPixels(keyMin, valueMin); result.append(result.last()); result << coordsToPixels(keyMin, valueMax); break; } + case 7: { result << coordsToPixels(keyMax, valueMin); result.append(result.last()); result << coordsToPixels(keyMax, valueMax); break; } + } + break; + } + case 7: + { + switch (currentRegion) + { + case 4: { result << coordsToPixels(keyMax, valueMax); break; } + case 8: { result << coordsToPixels(keyMax, valueMax); break; } + case 1: { result << coordsToPixels(keyMax, valueMax) << coordsToPixels(keyMin, valueMax); break; } + case 9: { result << coordsToPixels(keyMax, valueMax) << coordsToPixels(keyMax, valueMin); break; } + case 2: { result << coordsToPixels(keyMax, valueMax) << coordsToPixels(keyMin, valueMax); result.append(result.last()); break; } + case 6: { result << coordsToPixels(keyMax, valueMax) << coordsToPixels(keyMax, valueMin); result.append(result.last()); break; } + case 3: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points + if ((value-prevValue)/(key-prevKey)*(keyMax-key)+value < valueMin) // segment passes below R + { result << coordsToPixels(keyMax, valueMax) << coordsToPixels(keyMax, valueMin); result.append(result.last()); result << coordsToPixels(keyMin, valueMin); } + else + { result << coordsToPixels(keyMax, valueMax) << coordsToPixels(keyMin, valueMax); result.append(result.last()); result << coordsToPixels(keyMin, valueMin); } + break; + } + } + break; + } + case 8: { - // check whether mScaledBackground needs to be updated: - QSize scaledSize(mBackgroundPixmap.size()); - scaledSize.scale(mRect.size(), mBackgroundScaledMode); - if (mScaledBackgroundPixmap.size() != scaledSize) - mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mRect.size(), mBackgroundScaledMode, Qt::SmoothTransformation); - painter->drawPixmap(mRect.topLeft()+QPoint(0, -1), mScaledBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()) & mScaledBackgroundPixmap.rect()); - } else + switch (currentRegion) + { + case 7: { result << coordsToPixels(keyMax, valueMax); break; } + case 9: { result << coordsToPixels(keyMax, valueMin); break; } + case 4: { result << coordsToPixels(keyMax, valueMax); result.append(result.last()); break; } + case 6: { result << coordsToPixels(keyMax, valueMin); result.append(result.last()); break; } + case 1: { result << coordsToPixels(keyMax, valueMax); result.append(result.last()); result << coordsToPixels(keyMin, valueMax); break; } + case 3: { result << coordsToPixels(keyMax, valueMin); result.append(result.last()); result << coordsToPixels(keyMin, valueMin); break; } + } + break; + } + case 9: { - painter->drawPixmap(mRect.topLeft()+QPoint(0, -1), mBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height())); + switch (currentRegion) + { + case 6: { result << coordsToPixels(keyMax, valueMin); break; } + case 8: { result << coordsToPixels(keyMax, valueMin); break; } + case 3: { result << coordsToPixels(keyMax, valueMin) << coordsToPixels(keyMin, valueMin); break; } + case 7: { result << coordsToPixels(keyMax, valueMin) << coordsToPixels(keyMax, valueMax); break; } + case 2: { result << coordsToPixels(keyMax, valueMin) << coordsToPixels(keyMin, valueMin); result.append(result.last()); break; } + case 4: { result << coordsToPixels(keyMax, valueMin) << coordsToPixels(keyMax, valueMax); result.append(result.last()); break; } + case 1: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points + if ((value-prevValue)/(key-prevKey)*(keyMin-key)+value < valueMin) // segment passes below R + { result << coordsToPixels(keyMax, valueMin) << coordsToPixels(keyMin, valueMin); result.append(result.last()); result << coordsToPixels(keyMin, valueMax); } + else + { result << coordsToPixels(keyMax, valueMin) << coordsToPixels(keyMax, valueMax); result.append(result.last()); result << coordsToPixels(keyMin, valueMax); } + break; + } + } + break; } } + return result; } /*! \internal - This function makes sure multiple axes on the side specified with \a type don't collide, but are - distributed according to their respective space requirement (QCPAxis::calculateMargin). + This function is part of the curve optimization algorithm of \ref getCurveLines. - It does this by setting an appropriate offset (\ref QCPAxis::setOffset) on all axes except the - one with index zero. + This method returns whether a segment going from \a prevRegion to \a currentRegion (see \ref + getRegion) may traverse the visible region 5. This function assumes that neither \a prevRegion + nor \a currentRegion is 5 itself. - This function is called by \ref calculateAutoMargin. + If this method returns false, the segment for sure doesn't pass region 5. If it returns true, the + segment may or may not pass region 5 and a more fine-grained calculation must be used (\ref + getTraverse). */ -void QCPAxisRect::updateAxesOffset(QCPAxis::AxisType type) +bool QCPCurve::mayTraverse(int prevRegion, int currentRegion) const { - const QList axesList = mAxes.value(type); - if (axesList.isEmpty()) - return; - - bool isFirstVisible = !axesList.first()->visible(); // if the first axis is visible, the second axis (which is where the loop starts) isn't the first visible axis, so initialize with false - for (int i=1; ioffset() + axesList.at(i-1)->calculateMargin(); - if (axesList.at(i)->visible()) // only add inner tick length to offset if this axis is visible and it's not the first visible one (might happen if true first axis is invisible) + case 1: { - if (!isFirstVisible) - offset += axesList.at(i)->tickLengthIn(); - isFirstVisible = false; + switch (currentRegion) + { + case 4: + case 7: + case 2: + case 3: return false; + default: return true; + } } - axesList.at(i)->setOffset(offset); + case 2: + { + switch (currentRegion) + { + case 1: + case 3: return false; + default: return true; + } + } + case 3: + { + switch (currentRegion) + { + case 1: + case 2: + case 6: + case 9: return false; + default: return true; + } + } + case 4: + { + switch (currentRegion) + { + case 1: + case 7: return false; + default: return true; + } + } + case 5: return false; // should never occur + case 6: + { + switch (currentRegion) + { + case 3: + case 9: return false; + default: return true; + } + } + case 7: + { + switch (currentRegion) + { + case 1: + case 4: + case 8: + case 9: return false; + default: return true; + } + } + case 8: + { + switch (currentRegion) + { + case 7: + case 9: return false; + default: return true; + } + } + case 9: + { + switch (currentRegion) + { + case 3: + case 6: + case 8: + case 7: return false; + default: return true; + } + } + default: return true; } } -/* inherits documentation from base class */ -int QCPAxisRect::calculateAutoMargin(QCP::MarginSide side) -{ - if (!mAutoMargins.testFlag(side)) - qDebug() << Q_FUNC_INFO << "Called with side that isn't specified as auto margin"; - - updateAxesOffset(QCPAxis::marginSideToAxisType(side)); - - // note: only need to look at the last (outer most) axis to determine the total margin, due to updateAxisOffset call - const QList axesList = mAxes.value(QCPAxis::marginSideToAxisType(side)); - if (axesList.size() > 0) - return axesList.last()->offset() + axesList.last()->calculateMargin(); - else - return 0; -} /*! \internal - Event handler for when a mouse button is pressed on the axis rect. If the left mouse button is - pressed, the range dragging interaction is initialized (the actual range manipulation happens in - the \ref mouseMoveEvent). - - The mDragging flag is set to true and some anchor points are set that are needed to determine the - distance the mouse was dragged in the mouse move/release events later. + This function is part of the curve optimization algorithm of \ref getCurveLines. - \see mouseMoveEvent, mouseReleaseEvent + This method assumes that the \ref mayTraverse test has returned true, so there is a chance the + segment defined by (\a prevKey, \a prevValue) and (\a key, \a value) goes through the visible + region 5. + + The return value of this method indicates whether the segment actually traverses region 5 or not. + + If the segment traverses 5, the output parameters \a crossA and \a crossB indicate the entry and + exit points of region 5. They will become the optimized points for that segment. */ -void QCPAxisRect::mousePressEvent(QMouseEvent *event) -{ - mDragStart = event->pos(); // need this even when not LeftButton is pressed, to determine in releaseEvent whether it was a full click (no position change between press and release) - if (event->buttons() & Qt::LeftButton) +bool QCPCurve::getTraverse(double prevKey, double prevValue, double key, double value, double keyMin, double valueMax, double keyMax, double valueMin, QPointF &crossA, QPointF &crossB) const +{ + // The intersection point interpolation here is done in pixel coordinates, so we don't need to + // differentiate between different axis scale types. Note that the nomenclature + // top/left/bottom/right/min/max is with respect to the rect in plot coordinates, wich may be + // different in pixel coordinates (horz/vert key axes, reversed ranges) + + QList intersections; + const double valueMinPx = mValueAxis->coordToPixel(valueMin); + const double valueMaxPx = mValueAxis->coordToPixel(valueMax); + const double keyMinPx = mKeyAxis->coordToPixel(keyMin); + const double keyMaxPx = mKeyAxis->coordToPixel(keyMax); + const double keyPx = mKeyAxis->coordToPixel(key); + const double valuePx = mValueAxis->coordToPixel(value); + const double prevKeyPx = mKeyAxis->coordToPixel(prevKey); + const double prevValuePx = mValueAxis->coordToPixel(prevValue); + if (qFuzzyIsNull(keyPx-prevKeyPx)) // line is parallel to value axis + { + // due to region filter in mayTraverse(), if line is parallel to value or key axis, region 5 is traversed here + intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyPx, valueMinPx) : QPointF(valueMinPx, keyPx)); // direction will be taken care of at end of method + intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyPx, valueMaxPx) : QPointF(valueMaxPx, keyPx)); + } else if (qFuzzyIsNull(valuePx-prevValuePx)) // line is parallel to key axis + { + // due to region filter in mayTraverse(), if line is parallel to value or key axis, region 5 is traversed here + intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyMinPx, valuePx) : QPointF(valuePx, keyMinPx)); // direction will be taken care of at end of method + intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyMaxPx, valuePx) : QPointF(valuePx, keyMaxPx)); + } else // line is skewed { - mDragging = true; - // initialize antialiasing backup in case we start dragging: - if (mParentPlot->noAntialiasingOnDrag()) - { - mAADragBackup = mParentPlot->antialiasedElements(); - mNotAADragBackup = mParentPlot->notAntialiasedElements(); - } - // Mouse range dragging interaction: - if (mParentPlot->interactions().testFlag(QCP::iRangeDrag)) + double gamma; + double keyPerValuePx = (keyPx-prevKeyPx)/(valuePx-prevValuePx); + // check top of rect: + gamma = prevKeyPx + (valueMaxPx-prevValuePx)*keyPerValuePx; + if (gamma >= qMin(keyMinPx, keyMaxPx) && gamma <= qMax(keyMinPx, keyMaxPx)) // qMin/qMax necessary since axes may be reversed + intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(gamma, valueMaxPx) : QPointF(valueMaxPx, gamma)); + // check bottom of rect: + gamma = prevKeyPx + (valueMinPx-prevValuePx)*keyPerValuePx; + if (gamma >= qMin(keyMinPx, keyMaxPx) && gamma <= qMax(keyMinPx, keyMaxPx)) // qMin/qMax necessary since axes may be reversed + intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(gamma, valueMinPx) : QPointF(valueMinPx, gamma)); + const double valuePerKeyPx = 1.0/keyPerValuePx; + // check left of rect: + gamma = prevValuePx + (keyMinPx-prevKeyPx)*valuePerKeyPx; + if (gamma >= qMin(valueMinPx, valueMaxPx) && gamma <= qMax(valueMinPx, valueMaxPx)) // qMin/qMax necessary since axes may be reversed + intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyMinPx, gamma) : QPointF(gamma, keyMinPx)); + // check right of rect: + gamma = prevValuePx + (keyMaxPx-prevKeyPx)*valuePerKeyPx; + if (gamma >= qMin(valueMinPx, valueMaxPx) && gamma <= qMax(valueMinPx, valueMaxPx)) // qMin/qMax necessary since axes may be reversed + intersections.append(mKeyAxis->orientation() == Qt::Horizontal ? QPointF(keyMaxPx, gamma) : QPointF(gamma, keyMaxPx)); + } + + // handle cases where found points isn't exactly 2: + if (intersections.size() > 2) + { + // line probably goes through corner of rect, and we got duplicate points there. single out the point pair with greatest distance in between: + double distSqrMax = 0; + QPointF pv1, pv2; + for (int i=0; irange(); - if (mRangeDragVertAxis) - mDragStartVertRange = mRangeDragVertAxis.data()->range(); + for (int k=i+1; k distSqrMax) + { + pv1 = intersections.at(i); + pv2 = intersections.at(k); + distSqrMax = distSqr; + } + } } + intersections = QList() << pv1 << pv2; + } else if (intersections.size() != 2) + { + // one or even zero points found (shouldn't happen unless line perfectly tangent to corner), no need to draw segment + return false; } + + // possibly re-sort points so optimized point segment has same direction as original segment: + double xDelta = keyPx-prevKeyPx; + double yDelta = valuePx-prevValuePx; + if (mKeyAxis->orientation() != Qt::Horizontal) + qSwap(xDelta, yDelta); + if (xDelta*(intersections.at(1).x()-intersections.at(0).x()) + yDelta*(intersections.at(1).y()-intersections.at(0).y()) < 0) // scalar product of both segments < 0 -> opposite direction + intersections.move(0, 1); + crossA = intersections.at(0); + crossB = intersections.at(1); + return true; } /*! \internal - Event handler for when the mouse is moved on the axis rect. If range dragging was activated in a - preceding \ref mousePressEvent, the range is moved accordingly. + This function is part of the curve optimization algorithm of \ref getCurveLines. - \see mousePressEvent, mouseReleaseEvent + This method assumes that the \ref getTraverse test has returned true, so the segment definitely + traverses the visible region 5 when going from \a prevRegion to \a currentRegion. + + In certain situations it is not sufficient to merely generate the entry and exit points of the + segment into/out of region 5, as \ref getTraverse provides. It may happen that a single segment, in + addition to traversing region 5, skips another region outside of region 5, which makes it + necessary to add an optimized corner point there (very similar to the job \ref + getOptimizedCornerPoints does for segments that are completely in outside regions and don't + traverse 5). + + As an example, consider a segment going from region 1 to region 6, traversing the lower left + corner of region 5. In this configuration, the segment additionally crosses the border between + region 1 and 2 before entering region 5. This makes it necessary to add an additional point in + the top left corner, before adding the optimized traverse points. So in this case, the output + parameter \a beforeTraverse will contain the top left corner point, and \a afterTraverse will be + empty. + + In some cases, such as when going from region 1 to 9, it may even be necessary to add additional + corner points before and after the traverse. Then both \a beforeTraverse and \a afterTraverse + return the respective corner points. */ -void QCPAxisRect::mouseMoveEvent(QMouseEvent *event) +void QCPCurve::getTraverseCornerPoints(int prevRegion, int currentRegion, double keyMin, double valueMax, double keyMax, double valueMin, QVector &beforeTraverse, QVector &afterTraverse) const { - // Mouse range dragging interaction: - if (mDragging && mParentPlot->interactions().testFlag(QCP::iRangeDrag)) + switch (prevRegion) { - if (mRangeDrag.testFlag(Qt::Horizontal)) + case 1: + { + switch (currentRegion) + { + case 6: { beforeTraverse << coordsToPixels(keyMin, valueMax); break; } + case 9: { beforeTraverse << coordsToPixels(keyMin, valueMax); afterTraverse << coordsToPixels(keyMax, valueMin); break; } + case 8: { beforeTraverse << coordsToPixels(keyMin, valueMax); break; } + } + break; + } + case 2: + { + switch (currentRegion) + { + case 7: { afterTraverse << coordsToPixels(keyMax, valueMax); break; } + case 9: { afterTraverse << coordsToPixels(keyMax, valueMin); break; } + } + break; + } + case 3: + { + switch (currentRegion) + { + case 4: { beforeTraverse << coordsToPixels(keyMin, valueMin); break; } + case 7: { beforeTraverse << coordsToPixels(keyMin, valueMin); afterTraverse << coordsToPixels(keyMax, valueMax); break; } + case 8: { beforeTraverse << coordsToPixels(keyMin, valueMin); break; } + } + break; + } + case 4: + { + switch (currentRegion) + { + case 3: { afterTraverse << coordsToPixels(keyMin, valueMin); break; } + case 9: { afterTraverse << coordsToPixels(keyMax, valueMin); break; } + } + break; + } + case 5: { break; } // shouldn't happen because this method only handles full traverses + case 6: { - if (QCPAxis *rangeDragHorzAxis = mRangeDragHorzAxis.data()) + switch (currentRegion) { - if (rangeDragHorzAxis->mScaleType == QCPAxis::stLinear) - { - double diff = rangeDragHorzAxis->pixelToCoord(mDragStart.x()) - rangeDragHorzAxis->pixelToCoord(event->pos().x()); - rangeDragHorzAxis->setRange(mDragStartHorzRange.lower+diff, mDragStartHorzRange.upper+diff); - } else if (rangeDragHorzAxis->mScaleType == QCPAxis::stLogarithmic) - { - double diff = rangeDragHorzAxis->pixelToCoord(mDragStart.x()) / rangeDragHorzAxis->pixelToCoord(event->pos().x()); - rangeDragHorzAxis->setRange(mDragStartHorzRange.lower*diff, mDragStartHorzRange.upper*diff); - } + case 1: { afterTraverse << coordsToPixels(keyMin, valueMax); break; } + case 7: { afterTraverse << coordsToPixels(keyMax, valueMax); break; } } + break; } - if (mRangeDrag.testFlag(Qt::Vertical)) + case 7: { - if (QCPAxis *rangeDragVertAxis = mRangeDragVertAxis.data()) + switch (currentRegion) { - if (rangeDragVertAxis->mScaleType == QCPAxis::stLinear) - { - double diff = rangeDragVertAxis->pixelToCoord(mDragStart.y()) - rangeDragVertAxis->pixelToCoord(event->pos().y()); - rangeDragVertAxis->setRange(mDragStartVertRange.lower+diff, mDragStartVertRange.upper+diff); - } else if (rangeDragVertAxis->mScaleType == QCPAxis::stLogarithmic) - { - double diff = rangeDragVertAxis->pixelToCoord(mDragStart.y()) / rangeDragVertAxis->pixelToCoord(event->pos().y()); - rangeDragVertAxis->setRange(mDragStartVertRange.lower*diff, mDragStartVertRange.upper*diff); - } + case 2: { beforeTraverse << coordsToPixels(keyMax, valueMax); break; } + case 3: { beforeTraverse << coordsToPixels(keyMax, valueMax); afterTraverse << coordsToPixels(keyMin, valueMin); break; } + case 6: { beforeTraverse << coordsToPixels(keyMax, valueMax); break; } } + break; } - if (mRangeDrag != 0) // if either vertical or horizontal drag was enabled, do a replot + case 8: { - if (mParentPlot->noAntialiasingOnDrag()) - mParentPlot->setNotAntialiasedElements(QCP::aeAll); - mParentPlot->replot(); + switch (currentRegion) + { + case 1: { afterTraverse << coordsToPixels(keyMin, valueMax); break; } + case 3: { afterTraverse << coordsToPixels(keyMin, valueMin); break; } + } + break; + } + case 9: + { + switch (currentRegion) + { + case 2: { beforeTraverse << coordsToPixels(keyMax, valueMin); break; } + case 1: { beforeTraverse << coordsToPixels(keyMax, valueMin); afterTraverse << coordsToPixels(keyMin, valueMax); break; } + case 4: { beforeTraverse << coordsToPixels(keyMax, valueMin); break; } + } + break; } - } -} - -/* inherits documentation from base class */ -void QCPAxisRect::mouseReleaseEvent(QMouseEvent *event) -{ - Q_UNUSED(event) - mDragging = false; - if (mParentPlot->noAntialiasingOnDrag()) - { - mParentPlot->setAntialiasedElements(mAADragBackup); - mParentPlot->setNotAntialiasedElements(mNotAADragBackup); } } /*! \internal - Event handler for mouse wheel events. If rangeZoom is Qt::Horizontal, Qt::Vertical or both, the - ranges of the axes defined as rangeZoomHorzAxis and rangeZoomVertAxis are scaled. The center of - the scaling operation is the current cursor position inside the axis rect. The scaling factor is - dependant on the mouse wheel delta (which direction the wheel was rotated) to provide a natural - zooming feel. The Strength of the zoom can be controlled via \ref setRangeZoomFactor. + Calculates the (minimum) distance (in pixels) the curve's representation has from the given \a + pixelPoint in pixels. This is used to determine whether the curve was clicked or not, e.g. in + \ref selectTest. The closest data point to \a pixelPoint is returned in \a closestData. Note that + if the curve has a line representation, the returned distance may be smaller than the distance to + the \a closestData point, since the distance to the curve line is also taken into account. - Note, that event->delta() is usually +/-120 for single rotation steps. However, if the mouse - wheel is turned rapidly, many steps may bunch up to one event, so the event->delta() may then be - multiples of 120. This is taken into account here, by calculating \a wheelSteps and using it as - exponent of the range zoom factor. This takes care of the wheel direction automatically, by - inverting the factor, when the wheel step is negative (f^-1 = 1/f). + If either the curve has no data or if the line style is \ref lsNone and the scatter style's shape + is \ref QCPScatterStyle::ssNone (i.e. there is no visual representation of the curve), returns + -1.0. */ -void QCPAxisRect::wheelEvent(QWheelEvent *event) +double QCPCurve::pointDistance(const QPointF &pixelPoint, QCPCurveDataContainer::const_iterator &closestData) const { - // Mouse range zooming interaction: - if (mParentPlot->interactions().testFlag(QCP::iRangeZoom)) + closestData = mDataContainer->constEnd(); + if (mDataContainer->isEmpty()) + return -1.0; + if (mLineStyle == lsNone && mScatterStyle.isNone()) + return -1.0; + + if (mDataContainer->size() == 1) { - if (mRangeZoom != 0) + QPointF dataPoint = coordsToPixels(mDataContainer->constBegin()->key, mDataContainer->constBegin()->value); + closestData = mDataContainer->constBegin(); + return QCPVector2D(dataPoint-pixelPoint).length(); + } + + // calculate minimum distances to curve data points and find closestData iterator: + double minDistSqr = (std::numeric_limits::max)(); + // iterate over found data points and then choose the one with the shortest distance to pos: + QCPCurveDataContainer::const_iterator begin = mDataContainer->constBegin(); + QCPCurveDataContainer::const_iterator end = mDataContainer->constEnd(); + for (QCPCurveDataContainer::const_iterator it=begin; it!=end; ++it) + { + const double currentDistSqr = QCPVector2D(coordsToPixels(it->key, it->value)-pixelPoint).lengthSquared(); + if (currentDistSqr < minDistSqr) { - double factor; - double wheelSteps = event->delta()/120.0; // a single step delta is +/-120 usually - if (mRangeZoom.testFlag(Qt::Horizontal)) - { - factor = qPow(mRangeZoomFactorHorz, wheelSteps); - if (mRangeZoomHorzAxis.data()) - mRangeZoomHorzAxis.data()->scaleRange(factor, mRangeZoomHorzAxis.data()->pixelToCoord(event->pos().x())); - } - if (mRangeZoom.testFlag(Qt::Vertical)) - { - factor = qPow(mRangeZoomFactorVert, wheelSteps); - if (mRangeZoomVertAxis.data()) - mRangeZoomVertAxis.data()->scaleRange(factor, mRangeZoomVertAxis.data()->pixelToCoord(event->pos().y())); - } - mParentPlot->replot(); + minDistSqr = currentDistSqr; + closestData = it; + } + } + + // calculate distance to line if there is one (if so, will probably be smaller than distance to closest data point): + if (mLineStyle != lsNone) + { + QVector lines; + getCurveLines(&lines, QCPDataRange(0, dataCount()), mParentPlot->selectionTolerance()*1.2); // optimized lines outside axis rect shouldn't respond to clicks at the edge, so use 1.2*tolerance as pen width + for (int i=0; i QCPBarsGroup::bars() const - You inherit the following members you may use: - - - - - - - - -
QCPLegend *\b mParentLegendA pointer to the parent QCPLegend.
QFont \b mFontThe generic font of the item. You should use this font for all or at least the most prominent text of the item.
+ Returns all bars currently in this group. + + \see bars(int index) */ -/* start of documentation of signals */ +/*! \fn int QCPBarsGroup::size() const + + Returns the number of QCPBars plottables that are part of this group. + +*/ -/*! \fn void QCPAbstractLegendItem::selectionChanged(bool selected) +/*! \fn bool QCPBarsGroup::isEmpty() const - This signal is emitted when the selection state of this legend item has changed, either by user - interaction or by a direct call to \ref setSelected. + Returns whether this bars group is empty. + + \see size */ -/* end of documentation of signals */ +/*! \fn bool QCPBarsGroup::contains(QCPBars *bars) + + Returns whether the specified \a bars plottable is part of this group. + +*/ + +/* end of documentation of inline functions */ /*! - Constructs a QCPAbstractLegendItem and associates it with the QCPLegend \a parent. This does not - cause the item to be added to \a parent, so \ref QCPLegend::addItem must be called separately. + Constructs a new bars group for the specified QCustomPlot instance. */ -QCPAbstractLegendItem::QCPAbstractLegendItem(QCPLegend *parent) : - QCPLayoutElement(parent->parentPlot()), - mParentLegend(parent), - mFont(parent->font()), - mTextColor(parent->textColor()), - mSelectedFont(parent->selectedFont()), - mSelectedTextColor(parent->selectedTextColor()), - mSelectable(true), - mSelected(false) +QCPBarsGroup::QCPBarsGroup(QCustomPlot *parentPlot) : + QObject(parentPlot), + mParentPlot(parentPlot), + mSpacingType(stAbsolute), + mSpacing(4) { - setLayer(QLatin1String("legend")); - setMargins(QMargins(8, 2, 8, 2)); +} + +QCPBarsGroup::~QCPBarsGroup() +{ + clear(); } /*! - Sets the default font of this specific legend item to \a font. + Sets how the spacing between adjacent bars is interpreted. See \ref SpacingType. - \see setTextColor, QCPLegend::setFont + The actual spacing can then be specified with \ref setSpacing. + + \see setSpacing */ -void QCPAbstractLegendItem::setFont(const QFont &font) +void QCPBarsGroup::setSpacingType(SpacingType spacingType) { - mFont = font; + mSpacingType = spacingType; } /*! - Sets the default text color of this specific legend item to \a color. - - \see setFont, QCPLegend::setTextColor + Sets the spacing between adjacent bars. What the number passed as \a spacing actually means, is + defined by the current \ref SpacingType, which can be set with \ref setSpacingType. + + \see setSpacingType */ -void QCPAbstractLegendItem::setTextColor(const QColor &color) +void QCPBarsGroup::setSpacing(double spacing) { - mTextColor = color; + mSpacing = spacing; } /*! - When this legend item is selected, \a font is used to draw generic text, instead of the normal - font set with \ref setFont. - - \see setFont, QCPLegend::setSelectedFont + Returns the QCPBars instance with the specified \a index in this group. If no such QCPBars + exists, returns \c nullptr. + + \see bars(), size */ -void QCPAbstractLegendItem::setSelectedFont(const QFont &font) +QCPBars *QCPBarsGroup::bars(int index) const { - mSelectedFont = font; + if (index >= 0 && index < mBars.size()) + { + return mBars.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; + return nullptr; + } } /*! - When this legend item is selected, \a color is used to draw generic text, instead of the normal - color set with \ref setTextColor. - - \see setTextColor, QCPLegend::setSelectedTextColor + Removes all QCPBars plottables from this group. + + \see isEmpty */ -void QCPAbstractLegendItem::setSelectedTextColor(const QColor &color) +void QCPBarsGroup::clear() { - mSelectedTextColor = color; + const QList oldBars = mBars; + foreach (QCPBars *bars, oldBars) + bars->setBarsGroup(nullptr); // removes itself from mBars via removeBars +} + +/*! + Adds the specified \a bars plottable to this group. Alternatively, you can also use \ref + QCPBars::setBarsGroup on the \a bars instance. + + \see insert, remove +*/ +void QCPBarsGroup::append(QCPBars *bars) +{ + if (!bars) + { + qDebug() << Q_FUNC_INFO << "bars is 0"; + return; + } + + if (!mBars.contains(bars)) + bars->setBarsGroup(this); + else + qDebug() << Q_FUNC_INFO << "bars plottable is already in this bars group:" << reinterpret_cast(bars); } /*! - Sets whether this specific legend item is selectable. + Inserts the specified \a bars plottable into this group at the specified index position \a i. + This gives you full control over the ordering of the bars. - \see setSelectedParts, QCustomPlot::setInteractions + \a bars may already be part of this group. In that case, \a bars is just moved to the new index + position. + + \see append, remove */ -void QCPAbstractLegendItem::setSelectable(bool selectable) +void QCPBarsGroup::insert(int i, QCPBars *bars) { - if (mSelectable != selectable) + if (!bars) { - mSelectable = selectable; - emit selectableChanged(mSelectable); + qDebug() << Q_FUNC_INFO << "bars is 0"; + return; } + + // first append to bars list normally: + if (!mBars.contains(bars)) + bars->setBarsGroup(this); + // then move to according position: + mBars.move(mBars.indexOf(bars), qBound(0, i, mBars.size()-1)); } /*! - Sets whether this specific legend item is selected. - - It is possible to set the selection state of this item by calling this function directly, even if - setSelectable is set to false. + Removes the specified \a bars plottable from this group. - \see setSelectableParts, QCustomPlot::setInteractions + \see contains, clear */ -void QCPAbstractLegendItem::setSelected(bool selected) +void QCPBarsGroup::remove(QCPBars *bars) { - if (mSelected != selected) + if (!bars) { - mSelected = selected; - emit selectionChanged(mSelected); + qDebug() << Q_FUNC_INFO << "bars is 0"; + return; } -} - -/* inherits documentation from base class */ -double QCPAbstractLegendItem::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const -{ - Q_UNUSED(details) - if (!mParentPlot) return -1; - if (onlySelectable && (!mSelectable || !mParentLegend->selectableParts().testFlag(QCPLegend::spItems))) - return -1; - if (mRect.contains(pos.toPoint())) - return mParentPlot->selectionTolerance()*0.99; + if (mBars.contains(bars)) + bars->setBarsGroup(nullptr); else - return -1; + qDebug() << Q_FUNC_INFO << "bars plottable is not in this bars group:" << reinterpret_cast(bars); } -/* inherits documentation from base class */ -void QCPAbstractLegendItem::applyDefaultAntialiasingHint(QCPPainter *painter) const +/*! \internal + + Adds the specified \a bars to the internal mBars list of bars. This method does not change the + barsGroup property on \a bars. + + \see unregisterBars +*/ +void QCPBarsGroup::registerBars(QCPBars *bars) { - applyAntialiasingHint(painter, mAntialiased, QCP::aeLegendItems); + if (!mBars.contains(bars)) + mBars.append(bars); } -/* inherits documentation from base class */ -QRect QCPAbstractLegendItem::clipRect() const +/*! \internal + + Removes the specified \a bars from the internal mBars list of bars. This method does not change + the barsGroup property on \a bars. + + \see registerBars +*/ +void QCPBarsGroup::unregisterBars(QCPBars *bars) { - return mOuterRect; + mBars.removeOne(bars); } -/* inherits documentation from base class */ -void QCPAbstractLegendItem::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) +/*! \internal + + Returns the pixel offset in the key dimension the specified \a bars plottable should have at the + given key coordinate \a keyCoord. The offset is relative to the pixel position of the key + coordinate \a keyCoord. +*/ +double QCPBarsGroup::keyPixelOffset(const QCPBars *bars, double keyCoord) { - Q_UNUSED(event) - Q_UNUSED(details) - if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems)) + // find list of all base bars in case some mBars are stacked: + QList baseBars; + foreach (const QCPBars *b, mBars) { - bool selBefore = mSelected; - setSelected(additive ? !mSelected : true); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; + while (b->barBelow()) + b = b->barBelow(); + if (!baseBars.contains(b)) + baseBars.append(b); + } + // find base bar this "bars" is stacked on: + const QCPBars *thisBase = bars; + while (thisBase->barBelow()) + thisBase = thisBase->barBelow(); + + // determine key pixel offset of this base bars considering all other base bars in this barsgroup: + double result = 0; + int index = baseBars.indexOf(thisBase); + if (index >= 0) + { + if (baseBars.size() % 2 == 1 && index == (baseBars.size()-1)/2) // is center bar (int division on purpose) + { + return result; + } else + { + double lowerPixelWidth, upperPixelWidth; + int startIndex; + int dir = (index <= (baseBars.size()-1)/2) ? -1 : 1; // if bar is to lower keys of center, dir is negative + if (baseBars.size() % 2 == 0) // even number of bars + { + startIndex = baseBars.size()/2 + (dir < 0 ? -1 : 0); + result += getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing + } else // uneven number of bars + { + startIndex = (baseBars.size()-1)/2+dir; + baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); + result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar + result += getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing + } + for (int i = startIndex; i != index; i += dir) // add widths and spacings of bars in between center and our bars + { + baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); + result += qAbs(upperPixelWidth-lowerPixelWidth); + result += getPixelSpacing(baseBars.at(i), keyCoord); + } + // finally half of our bars width: + baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); + result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5; + // correct sign of result depending on orientation and direction of key axis: + result *= dir*thisBase->keyAxis()->pixelOrientation(); + } } + return result; } -/* inherits documentation from base class */ -void QCPAbstractLegendItem::deselectEvent(bool *selectionStateChanged) +/*! \internal + + Returns the spacing in pixels which is between this \a bars and the following one, both at the + key coordinate \a keyCoord. + + \note Typically the returned value doesn't depend on \a bars or \a keyCoord. \a bars is only + needed to get access to the key axis transformation and axis rect for the modes \ref + stAxisRectRatio and \ref stPlotCoords. The \a keyCoord is only relevant for spacings given in + \ref stPlotCoords on a logarithmic axis. +*/ +double QCPBarsGroup::getPixelSpacing(const QCPBars *bars, double keyCoord) { - if (mSelectable && mParentLegend->selectableParts().testFlag(QCPLegend::spItems)) + switch (mSpacingType) { - bool selBefore = mSelected; - setSelected(false); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; + case stAbsolute: + { + return mSpacing; + } + case stAxisRectRatio: + { + if (bars->keyAxis()->orientation() == Qt::Horizontal) + return bars->keyAxis()->axisRect()->width()*mSpacing; + else + return bars->keyAxis()->axisRect()->height()*mSpacing; + } + case stPlotCoords: + { + double keyPixel = bars->keyAxis()->coordToPixel(keyCoord); + return qAbs(bars->keyAxis()->coordToPixel(keyCoord+mSpacing)-keyPixel); + } } + return 0; } + //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPPlottableLegendItem +//////////////////// QCPBarsData //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPPlottableLegendItem - \brief A legend item representing a plottable with an icon and the plottable name. +/*! \class QCPBarsData + \brief Holds the data of one single data point (one bar) for QCPBars. - This is the standard legend item for plottables. It displays an icon of the plottable next to the - plottable name. The icon is drawn by the respective plottable itself (\ref - QCPAbstractPlottable::drawLegendIcon), and tries to give an intuitive symbol for the plottable. - For example, the QCPGraph draws a centered horizontal line and/or a single scatter point in the - middle. + The stored data is: + \li \a key: coordinate on the key axis of this bar (this is the \a mainKey and the \a sortKey) + \li \a value: height coordinate on the value axis of this bar (this is the \a mainValue) - Legend items of this type are always associated with one plottable (retrievable via the - plottable() function and settable with the constructor). You may change the font of the plottable - name with \ref setFont. Icon padding and border pen is taken from the parent QCPLegend, see \ref - QCPLegend::setIconBorderPen and \ref QCPLegend::setIconTextPadding. - - The function \ref QCPAbstractPlottable::addToLegend/\ref QCPAbstractPlottable::removeFromLegend - creates/removes legend items of this type in the default implementation. However, these functions - may be reimplemented such that a different kind of legend item (e.g a direct subclass of - QCPAbstractLegendItem) is used for that plottable. + The container for storing multiple data points is \ref QCPBarsDataContainer. It is a typedef for + \ref QCPDataContainer with \ref QCPBarsData as the DataType template parameter. See the + documentation there for an explanation regarding the data type's generic methods. - Since QCPLegend is based on QCPLayoutGrid, a legend item itself is just a subclass of - QCPLayoutElement. While it could be added to a legend (or any other layout) via the normal layout - interface, QCPLegend has specialized functions for handling legend items conveniently, see the - documentation of \ref QCPLegend. + \see QCPBarsDataContainer */ -/*! - Creates a new legend item associated with \a plottable. +/* start documentation of inline functions */ + +/*! \fn double QCPBarsData::sortKey() const - Once it's created, it can be added to the legend via \ref QCPLegend::addItem. + Returns the \a key member of this data point. - A more convenient way of adding/removing a plottable to/from the legend is via the functions \ref - QCPAbstractPlottable::addToLegend and \ref QCPAbstractPlottable::removeFromLegend. + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -QCPPlottableLegendItem::QCPPlottableLegendItem(QCPLegend *parent, QCPAbstractPlottable *plottable) : - QCPAbstractLegendItem(parent), - mPlottable(plottable) -{ -} -/*! \internal +/*! \fn static QCPBarsData QCPBarsData::fromSortKey(double sortKey) - Returns the pen that shall be used to draw the icon border, taking into account the selection - state of this item. + Returns a data point with the specified \a sortKey. All other members are set to zero. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -QPen QCPPlottableLegendItem::getIconBorderPen() const -{ - return mSelected ? mParentLegend->selectedIconBorderPen() : mParentLegend->iconBorderPen(); -} -/*! \internal +/*! \fn static static bool QCPBarsData::sortKeyIsMainKey() - Returns the text color that shall be used to draw text, taking into account the selection state - of this item. + Since the member \a key is both the data point key coordinate and the data ordering parameter, + this method returns true. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -QColor QCPPlottableLegendItem::getTextColor() const -{ - return mSelected ? mSelectedTextColor : mTextColor; -} -/*! \internal +/*! \fn double QCPBarsData::mainKey() const - Returns the font that shall be used to draw text, taking into account the selection state of this - item. + Returns the \a key member of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -QFont QCPPlottableLegendItem::getFont() const -{ - return mSelected ? mSelectedFont : mFont; -} -/*! \internal +/*! \fn double QCPBarsData::mainValue() const - Draws the item with \a painter. The size and position of the drawn legend item is defined by the - parent layout (typically a \ref QCPLegend) and the \ref minimumSizeHint and \ref maximumSizeHint - of this legend item. + Returns the \a value member of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -void QCPPlottableLegendItem::draw(QCPPainter *painter) -{ - if (!mPlottable) return; - painter->setFont(getFont()); - painter->setPen(QPen(getTextColor())); - QSizeF iconSize = mParentLegend->iconSize(); - QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name()); - QRectF iconRect(mRect.topLeft(), iconSize); - int textHeight = qMax(textRect.height(), iconSize.height()); // if text has smaller height than icon, center text vertically in icon height, else align tops - painter->drawText(mRect.x()+iconSize.width()+mParentLegend->iconTextPadding(), mRect.y(), textRect.width(), textHeight, Qt::TextDontClip, mPlottable->name()); - // draw icon: - painter->save(); - painter->setClipRect(iconRect, Qt::IntersectClip); - mPlottable->drawLegendIcon(painter, iconRect); - painter->restore(); - // draw icon border: - if (getIconBorderPen().style() != Qt::NoPen) - { - painter->setPen(getIconBorderPen()); - painter->setBrush(Qt::NoBrush); - painter->drawRect(iconRect); - } + +/*! \fn QCPRange QCPBarsData::valueRange() const + + Returns a QCPRange with both lower and upper boundary set to \a value of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ + +/* end documentation of inline functions */ + +/*! + Constructs a bar data point with key and value set to zero. +*/ +QCPBarsData::QCPBarsData() : + key(0), + value(0) +{ } -/*! \internal - - Calculates and returns the size of this item. This includes the icon, the text and the padding in - between. +/*! + Constructs a bar data point with the specified \a key and \a value. */ -QSize QCPPlottableLegendItem::minimumSizeHint() const +QCPBarsData::QCPBarsData(double key, double value) : + key(key), + value(value) { - if (!mPlottable) return QSize(); - QSize result(0, 0); - QRect textRect; - QFontMetrics fontMetrics(getFont()); - QSize iconSize = mParentLegend->iconSize(); - textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPlottable->name()); - result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width() + mMargins.left() + mMargins.right()); - result.setHeight(qMax(textRect.height(), iconSize.height()) + mMargins.top() + mMargins.bottom()); - return result; } //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPLegend +//////////////////// QCPBars //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPLegend - \brief Manages a legend inside a QCustomPlot. +/*! \class QCPBars + \brief A plottable representing a bar chart in a plot. - A legend is a small box somewhere in the plot which lists plottables with their name and icon. + \image html QCPBars.png - Normally, the legend is populated by calling \ref QCPAbstractPlottable::addToLegend. The - respective legend item can be removed with \ref QCPAbstractPlottable::removeFromLegend. However, - QCPLegend also offers an interface to add and manipulate legend items directly: \ref item, \ref - itemWithPlottable, \ref itemCount, \ref addItem, \ref removeItem, etc. - - The QCPLegend derives from QCPLayoutGrid and as such can be placed in any position a - QCPLayoutElement may be positioned. The legend items are themselves QCPLayoutElements which are - placed in the grid layout of the legend. QCPLegend only adds an interface specialized for - handling child elements of type QCPAbstractLegendItem, as mentioned above. In principle, any - other layout elements may also be added to a legend via the normal \ref QCPLayoutGrid interface. - However, the QCPAbstractLegendItem-Interface will ignore those elements (e.g. \ref itemCount will - only return the number of items with QCPAbstractLegendItems type). - - By default, every QCustomPlot has one legend (QCustomPlot::legend) which is placed in the inset - layout of the main axis rect (\ref QCPAxisRect::insetLayout). To move the legend to another - position inside the axis rect, use the methods of the \ref QCPLayoutInset. To move the legend - outside of the axis rect, place it anywhere else with the QCPLayout/QCPLayoutElement interface. + To plot data, assign it with the \ref setData or \ref addData functions. + + \section qcpbars-appearance Changing the appearance + + The appearance of the bars is determined by the pen and the brush (\ref setPen, \ref setBrush). + The width of the individual bars can be controlled with \ref setWidthType and \ref setWidth. + + Bar charts are stackable. This means, two QCPBars plottables can be placed on top of each other + (see \ref QCPBars::moveAbove). So when two bars are at the same key position, they will appear + stacked. + + If you would like to group multiple QCPBars plottables together so they appear side by side as + shown below, use QCPBarsGroup. + + \image html QCPBarsGroup.png + + \section qcpbars-usage Usage + + Like all data representing objects in QCustomPlot, the QCPBars is a plottable + (QCPAbstractPlottable). So the plottable-interface of QCustomPlot applies + (QCustomPlot::plottable, QCustomPlot::removePlottable, etc.) + + Usually, you first create an instance: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpbars-creation-1 + which registers it with the QCustomPlot instance of the passed axes. Note that this QCustomPlot instance takes + ownership of the plottable, so do not delete it manually but use QCustomPlot::removePlottable() instead. + The newly created plottable can be modified, e.g.: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpbars-creation-2 */ -/* start of documentation of signals */ +/* start of documentation of inline functions */ -/*! \fn void QCPLegend::selectionChanged(QCPLegend::SelectableParts selection); +/*! \fn QSharedPointer QCPBars::data() const + + Returns a shared pointer to the internal data storage of type \ref QCPBarsDataContainer. You may + use it to directly manipulate the data, which may be more convenient and faster than using the + regular \ref setData or \ref addData methods. +*/ - This signal is emitted when the selection state of this legend has changed. +/*! \fn QCPBars *QCPBars::barBelow() const + Returns the bars plottable that is directly below this bars plottable. + If there is no such plottable, returns \c nullptr. - \see setSelectedParts, setSelectableParts + \see barAbove, moveBelow, moveAbove */ -/* end of documentation of signals */ +/*! \fn QCPBars *QCPBars::barAbove() const + Returns the bars plottable that is directly above this bars plottable. + If there is no such plottable, returns \c nullptr. + + \see barBelow, moveBelow, moveAbove +*/ + +/* end of documentation of inline functions */ /*! - Constructs a new QCPLegend instance with \a parentPlot as the containing plot and default values. + Constructs a bar chart which uses \a keyAxis as its key axis ("x") and \a valueAxis as its value + axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and not have + the same orientation. If either of these restrictions is violated, a corresponding message is + printed to the debug output (qDebug), the construction is not aborted, though. - Note that by default, QCustomPlot already contains a legend ready to be used as - QCustomPlot::legend + The created QCPBars is automatically registered with the QCustomPlot instance inferred from \a + keyAxis. This QCustomPlot instance takes ownership of the QCPBars, so do not delete it manually + but use QCustomPlot::removePlottable() instead. */ -QCPLegend::QCPLegend() +QCPBars::QCPBars(QCPAxis *keyAxis, QCPAxis *valueAxis) : + QCPAbstractPlottable1D(keyAxis, valueAxis), + mWidth(0.75), + mWidthType(wtPlotCoords), + mBarsGroup(nullptr), + mBaseValue(0), + mStackingGap(1) { - setRowSpacing(0); - setColumnSpacing(10); - setMargins(QMargins(2, 3, 2, 2)); - setAntialiased(false); - setIconSize(32, 18); - - setIconTextPadding(7); - - setSelectableParts(spLegendBox | spItems); - setSelectedParts(spNone); - - setBorderPen(QPen(Qt::black)); - setSelectedBorderPen(QPen(Qt::blue, 2)); - setIconBorderPen(Qt::NoPen); - setSelectedIconBorderPen(QPen(Qt::blue, 2)); - setBrush(Qt::white); - setSelectedBrush(Qt::white); - setTextColor(Qt::black); - setSelectedTextColor(Qt::blue); + // modify inherited properties from abstract plottable: + mPen.setColor(Qt::blue); + mPen.setStyle(Qt::SolidLine); + mBrush.setColor(QColor(40, 50, 255, 30)); + mBrush.setStyle(Qt::SolidPattern); + mSelectionDecorator->setBrush(QBrush(QColor(160, 160, 255))); } -QCPLegend::~QCPLegend() +QCPBars::~QCPBars() { - clearItems(); - if (qobject_cast(mParentPlot)) // make sure this isn't called from QObject dtor when QCustomPlot is already destructed (happens when the legend is not in any layout and thus QObject-child of QCustomPlot) - mParentPlot->legendRemoved(this); + setBarsGroup(nullptr); + if (mBarBelow || mBarAbove) + connectBars(mBarBelow.data(), mBarAbove.data()); // take this bar out of any stacking } -/* no doc for getter, see setSelectedParts */ -QCPLegend::SelectableParts QCPLegend::selectedParts() const +/*! \overload + + Replaces the current data container with the provided \a data container. + + Since a QSharedPointer is used, multiple QCPBars may share the same data container safely. + Modifying the data in the container will then affect all bars that share the container. Sharing + can be achieved by simply exchanging the data containers wrapped in shared pointers: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpbars-datasharing-1 + + If you do not wish to share containers, but create a copy from an existing container, rather use + the \ref QCPDataContainer::set method on the bar's data container directly: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpbars-datasharing-2 + + \see addData +*/ +void QCPBars::setData(QSharedPointer data) { - // check whether any legend elements selected, if yes, add spItems to return value - bool hasSelectedItems = false; - for (int i=0; iselected()) - { - hasSelectedItems = true; - break; - } - } - if (hasSelectedItems) - return mSelectedParts | spItems; - else - return mSelectedParts & ~spItems; + mDataContainer = data; } -/*! - Sets the pen, the border of the entire legend is drawn with. +/*! \overload + + Replaces the current data with the provided points in \a keys and \a values. The provided + vectors should have equal length. Else, the number of added points will be the size of the + smallest vector. + + If you can guarantee that the passed data points are sorted by \a keys in ascending order, you + can set \a alreadySorted to true, to improve performance by saving a sorting run. + + \see addData */ -void QCPLegend::setBorderPen(const QPen &pen) +void QCPBars::setData(const QVector &keys, const QVector &values, bool alreadySorted) { - mBorderPen = pen; + mDataContainer->clear(); + addData(keys, values, alreadySorted); } /*! - Sets the brush of the legend background. + Sets the width of the bars. + + How the number passed as \a width is interpreted (e.g. screen pixels, plot coordinates,...), + depends on the currently set width type, see \ref setWidthType and \ref WidthType. */ -void QCPLegend::setBrush(const QBrush &brush) +void QCPBars::setWidth(double width) { - mBrush = brush; + mWidth = width; } /*! - Sets the default font of legend text. Legend items that draw text (e.g. the name of a graph) will - use this font by default. However, a different font can be specified on a per-item-basis by - accessing the specific legend item. + Sets how the width of the bars is defined. See the documentation of \ref WidthType for an + explanation of the possible values for \a widthType. - This function will also set \a font on all already existing legend items. + The default value is \ref wtPlotCoords. - \see QCPAbstractLegendItem::setFont + \see setWidth */ -void QCPLegend::setFont(const QFont &font) +void QCPBars::setWidthType(QCPBars::WidthType widthType) { - mFont = font; - for (int i=0; isetFont(mFont); - } + mWidthType = widthType; } /*! - Sets the default color of legend text. Legend items that draw text (e.g. the name of a graph) - will use this color by default. However, a different colors can be specified on a per-item-basis - by accessing the specific legend item. - - This function will also set \a color on all already existing legend items. + Sets to which QCPBarsGroup this QCPBars instance belongs to. Alternatively, you can also use \ref + QCPBarsGroup::append. - \see QCPAbstractLegendItem::setTextColor + To remove this QCPBars from any group, set \a barsGroup to \c nullptr. */ -void QCPLegend::setTextColor(const QColor &color) +void QCPBars::setBarsGroup(QCPBarsGroup *barsGroup) { - mTextColor = color; - for (int i=0; isetTextColor(color); - } + // deregister at old group: + if (mBarsGroup) + mBarsGroup->unregisterBars(this); + mBarsGroup = barsGroup; + // register at new group: + if (mBarsGroup) + mBarsGroup->registerBars(this); } /*! - Sets the size of legend icons. Legend items that draw an icon (e.g. a visual - representation of the graph) will use this size by default. -*/ -void QCPLegend::setIconSize(const QSize &size) -{ - mIconSize = size; -} + Sets the base value of this bars plottable. -/*! \overload + The base value defines where on the value coordinate the bars start. How far the bars extend from + the base value is given by their individual value data. For example, if the base value is set to + 1, a bar with data value 2 will have its lowest point at value coordinate 1 and highest point at + 3. + + For stacked bars, only the base value of the bottom-most QCPBars has meaning. + + The default base value is 0. */ -void QCPLegend::setIconSize(int width, int height) +void QCPBars::setBaseValue(double baseValue) { - mIconSize.setWidth(width); - mIconSize.setHeight(height); + mBaseValue = baseValue; } /*! - Sets the horizontal space in pixels between the legend icon and the text next to it. - Legend items that draw an icon (e.g. a visual representation of the graph) and text (e.g. the - name of the graph) will use this space by default. + If this bars plottable is stacked on top of another bars plottable (\ref moveAbove), this method + allows specifying a distance in \a pixels, by which the drawn bar rectangles will be separated by + the bars below it. */ -void QCPLegend::setIconTextPadding(int padding) +void QCPBars::setStackingGap(double pixels) { - mIconTextPadding = padding; + mStackingGap = pixels; } -/*! - Sets the pen used to draw a border around each legend icon. Legend items that draw an - icon (e.g. a visual representation of the graph) will use this pen by default. +/*! \overload - If no border is wanted, set this to \a Qt::NoPen. + Adds the provided points in \a keys and \a values to the current data. The provided vectors + should have equal length. Else, the number of added points will be the size of the smallest + vector. + + If you can guarantee that the passed data points are sorted by \a keys in ascending order, you + can set \a alreadySorted to true, to improve performance by saving a sorting run. + + Alternatively, you can also access and modify the data directly via the \ref data method, which + returns a pointer to the internal data container. */ -void QCPLegend::setIconBorderPen(const QPen &pen) +void QCPBars::addData(const QVector &keys, const QVector &values, bool alreadySorted) { - mIconBorderPen = pen; + if (keys.size() != values.size()) + qDebug() << Q_FUNC_INFO << "keys and values have different sizes:" << keys.size() << values.size(); + const int n = qMin(keys.size(), values.size()); + QVector tempData(n); + QVector::iterator it = tempData.begin(); + const QVector::iterator itEnd = tempData.end(); + int i = 0; + while (it != itEnd) + { + it->key = keys[i]; + it->value = values[i]; + ++it; + ++i; + } + mDataContainer->add(tempData, alreadySorted); // don't modify tempData beyond this to prevent copy on write } -/*! - Sets whether the user can (de-)select the parts in \a selectable by clicking on the QCustomPlot surface. - (When \ref QCustomPlot::setInteractions contains \ref QCP::iSelectLegend.) - - However, even when \a selectable is set to a value not allowing the selection of a specific part, - it is still possible to set the selection of this part manually, by calling \ref setSelectedParts - directly. +/*! \overload + Adds the provided data point as \a key and \a value to the current data. - \see SelectablePart, setSelectedParts + Alternatively, you can also access and modify the data directly via the \ref data method, which + returns a pointer to the internal data container. */ -void QCPLegend::setSelectableParts(const SelectableParts &selectable) +void QCPBars::addData(double key, double value) { - if (mSelectableParts != selectable) - { - mSelectableParts = selectable; - emit selectableChanged(mSelectableParts); - } + mDataContainer->add(QCPBarsData(key, value)); } /*! - Sets the selected state of the respective legend parts described by \ref SelectablePart. When a part - is selected, it uses a different pen/font and brush. If some legend items are selected and \a selected - doesn't contain \ref spItems, those items become deselected. - - The entire selection mechanism is handled automatically when \ref QCustomPlot::setInteractions - contains iSelectLegend. You only need to call this function when you wish to change the selection - state manually. - - This function can change the selection state of a part even when \ref setSelectableParts was set to a - value that actually excludes the part. + Moves this bars plottable below \a bars. In other words, the bars of this plottable will appear + below the bars of \a bars. The move target \a bars must use the same key and value axis as this + plottable. - emits the \ref selectionChanged signal when \a selected is different from the previous selection state. + Inserting into and removing from existing bar stacking is handled gracefully. If \a bars already + has a bars object below itself, this bars object is inserted between the two. If this bars object + is already between two other bars, the two other bars will be stacked on top of each other after + the operation. - Note that it doesn't make sense to set the selected state \ref spItems here when it wasn't set - before, because there's no way to specify which exact items to newly select. Do this by calling - \ref QCPAbstractLegendItem::setSelected directly on the legend item you wish to select. + To remove this bars plottable from any stacking, set \a bars to \c nullptr. - \see SelectablePart, setSelectableParts, selectTest, setSelectedBorderPen, setSelectedIconBorderPen, setSelectedBrush, - setSelectedFont + \see moveBelow, barAbove, barBelow */ -void QCPLegend::setSelectedParts(const SelectableParts &selected) +void QCPBars::moveBelow(QCPBars *bars) { - SelectableParts newSelected = selected; - mSelectedParts = this->selectedParts(); // update mSelectedParts in case item selection changed - - if (mSelectedParts != newSelected) + if (bars == this) return; + if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data())) { - if (!mSelectedParts.testFlag(spItems) && newSelected.testFlag(spItems)) // attempt to set spItems flag (can't do that) - { - qDebug() << Q_FUNC_INFO << "spItems flag can not be set, it can only be unset with this function"; - newSelected &= ~spItems; - } - if (mSelectedParts.testFlag(spItems) && !newSelected.testFlag(spItems)) // spItems flag was unset, so clear item selection - { - for (int i=0; isetSelected(false); - } - } - mSelectedParts = newSelected; - emit selectionChanged(mSelectedParts); + qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars"; + return; + } + // remove from stacking: + connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0 + // if new bar given, insert this bar below it: + if (bars) + { + if (bars->mBarBelow) + connectBars(bars->mBarBelow.data(), this); + connectBars(this, bars); } } /*! - When the legend box is selected, this pen is used to draw the border instead of the normal pen - set via \ref setBorderPen. - - \see setSelectedParts, setSelectableParts, setSelectedBrush + Moves this bars plottable above \a bars. In other words, the bars of this plottable will appear + above the bars of \a bars. The move target \a bars must use the same key and value axis as this + plottable. + + Inserting into and removing from existing bar stacking is handled gracefully. If \a bars already + has a bars object above itself, this bars object is inserted between the two. If this bars object + is already between two other bars, the two other bars will be stacked on top of each other after + the operation. + + To remove this bars plottable from any stacking, set \a bars to \c nullptr. + + \see moveBelow, barBelow, barAbove */ -void QCPLegend::setSelectedBorderPen(const QPen &pen) +void QCPBars::moveAbove(QCPBars *bars) { - mSelectedBorderPen = pen; + if (bars == this) return; + if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data())) + { + qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars"; + return; + } + // remove from stacking: + connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0 + // if new bar given, insert this bar above it: + if (bars) + { + if (bars->mBarAbove) + connectBars(this, bars->mBarAbove.data()); + connectBars(bars, this); + } } /*! - Sets the pen legend items will use to draw their icon borders, when they are selected. - - \see setSelectedParts, setSelectableParts, setSelectedFont + \copydoc QCPPlottableInterface1D::selectTestRect */ -void QCPLegend::setSelectedIconBorderPen(const QPen &pen) +QCPDataSelection QCPBars::selectTestRect(const QRectF &rect, bool onlySelectable) const { - mSelectedIconBorderPen = pen; + QCPDataSelection result; + if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty()) + return result; + if (!mKeyAxis || !mValueAxis) + return result; + + QCPBarsDataContainer::const_iterator visibleBegin, visibleEnd; + getVisibleDataBounds(visibleBegin, visibleEnd); + + for (QCPBarsDataContainer::const_iterator it=visibleBegin; it!=visibleEnd; ++it) + { + if (rect.intersects(getBarRect(it->key, it->value))) + result.addDataRange(QCPDataRange(int(it-mDataContainer->constBegin()), int(it-mDataContainer->constBegin()+1)), false); + } + result.simplify(); + return result; } /*! - When the legend box is selected, this brush is used to draw the legend background instead of the normal brush - set via \ref setBrush. + Implements a selectTest specific to this plottable's point geometry. - \see setSelectedParts, setSelectableParts, setSelectedBorderPen + If \a details is not 0, it will be set to a \ref QCPDataSelection, describing the closest data + point to \a pos. + + \seebaseclassmethod \ref QCPAbstractPlottable::selectTest */ -void QCPLegend::setSelectedBrush(const QBrush &brush) +double QCPBars::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - mSelectedBrush = brush; + Q_UNUSED(details) + if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty()) + return -1; + if (!mKeyAxis || !mValueAxis) + return -1; + + if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect)) + { + // get visible data range: + QCPBarsDataContainer::const_iterator visibleBegin, visibleEnd; + getVisibleDataBounds(visibleBegin, visibleEnd); + for (QCPBarsDataContainer::const_iterator it=visibleBegin; it!=visibleEnd; ++it) + { + if (getBarRect(it->key, it->value).contains(pos)) + { + if (details) + { + int pointIndex = int(it-mDataContainer->constBegin()); + details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1))); + } + return mParentPlot->selectionTolerance()*0.99; + } + } + } + return -1; } -/*! - Sets the default font that is used by legend items when they are selected. +/* inherits documentation from base class */ +QCPRange QCPBars::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const +{ + /* Note: If this QCPBars uses absolute pixels as width (or is in a QCPBarsGroup with spacing in + absolute pixels), using this method to adapt the key axis range to fit the bars into the + currently visible axis range will not work perfectly. Because in the moment the axis range is + changed to the new range, the fixed pixel widths/spacings will represent different coordinate + spans than before, which in turn would require a different key range to perfectly fit, and so on. + The only solution would be to iteratively approach the perfect fitting axis range, but the + mismatch isn't large enough in most applications, to warrant this here. If a user does need a + better fit, he should call the corresponding axis rescale multiple times in a row. + */ + QCPRange range; + range = mDataContainer->keyRange(foundRange, inSignDomain); - This function will also set \a font on all already existing legend items. - - \see setFont, QCPAbstractLegendItem::setSelectedFont -*/ -void QCPLegend::setSelectedFont(const QFont &font) -{ - mSelectedFont = font; - for (int i=0; isetSelectedFont(font); + double lowerPixelWidth, upperPixelWidth, keyPixel; + // lower range bound: + getPixelWidth(range.lower, lowerPixelWidth, upperPixelWidth); + keyPixel = mKeyAxis.data()->coordToPixel(range.lower) + lowerPixelWidth; + if (mBarsGroup) + keyPixel += mBarsGroup->keyPixelOffset(this, range.lower); + const double lowerCorrected = mKeyAxis.data()->pixelToCoord(keyPixel); + if (!qIsNaN(lowerCorrected) && qIsFinite(lowerCorrected) && range.lower > lowerCorrected) + range.lower = lowerCorrected; + // upper range bound: + getPixelWidth(range.upper, lowerPixelWidth, upperPixelWidth); + keyPixel = mKeyAxis.data()->coordToPixel(range.upper) + upperPixelWidth; + if (mBarsGroup) + keyPixel += mBarsGroup->keyPixelOffset(this, range.upper); + const double upperCorrected = mKeyAxis.data()->pixelToCoord(keyPixel); + if (!qIsNaN(upperCorrected) && qIsFinite(upperCorrected) && range.upper < upperCorrected) + range.upper = upperCorrected; } + return range; } -/*! - Sets the default text color that is used by legend items when they are selected. +/* inherits documentation from base class */ +QCPRange QCPBars::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const +{ + // Note: can't simply use mDataContainer->valueRange here because we need to + // take into account bar base value and possible stacking of multiple bars + QCPRange range; + range.lower = mBaseValue; + range.upper = mBaseValue; + bool haveLower = true; // set to true, because baseValue should always be visible in bar charts + bool haveUpper = true; // set to true, because baseValue should always be visible in bar charts + QCPBarsDataContainer::const_iterator itBegin = mDataContainer->constBegin(); + QCPBarsDataContainer::const_iterator itEnd = mDataContainer->constEnd(); + if (inKeyRange != QCPRange()) + { + itBegin = mDataContainer->findBegin(inKeyRange.lower, false); + itEnd = mDataContainer->findEnd(inKeyRange.upper, false); + } + for (QCPBarsDataContainer::const_iterator it = itBegin; it != itEnd; ++it) + { + const double current = it->value + getStackedBaseValue(it->key, it->value >= 0); + if (qIsNaN(current)) continue; + if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0)) + { + if (current < range.lower || !haveLower) + { + range.lower = current; + haveLower = true; + } + if (current > range.upper || !haveUpper) + { + range.upper = current; + haveUpper = true; + } + } + } - This function will also set \a color on all already existing legend items. + foundRange = true; // return true because bar charts always have the 0-line visible + return range; +} - \see setTextColor, QCPAbstractLegendItem::setSelectedTextColor -*/ -void QCPLegend::setSelectedTextColor(const QColor &color) +/* inherits documentation from base class */ +QPointF QCPBars::dataPixelPosition(int index) const { - mSelectedTextColor = color; - for (int i=0; i= 0 && index < mDataContainer->size()) { - if (item(i)) - item(i)->setSelectedTextColor(color); + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return {}; } + + const QCPDataContainer::const_iterator it = mDataContainer->constBegin()+index; + const double valuePixel = valueAxis->coordToPixel(getStackedBaseValue(it->key, it->value >= 0) + it->value); + const double keyPixel = keyAxis->coordToPixel(it->key) + (mBarsGroup ? mBarsGroup->keyPixelOffset(this, it->key) : 0); + if (keyAxis->orientation() == Qt::Horizontal) + return {keyPixel, valuePixel}; + else + return {valuePixel, keyPixel}; + } else + { + qDebug() << Q_FUNC_INFO << "Index out of bounds" << index; + return {}; } } -/*! - Returns the item with index \a i. +/* inherits documentation from base class */ +void QCPBars::draw(QCPPainter *painter) +{ + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + if (mDataContainer->isEmpty()) return; + + QCPBarsDataContainer::const_iterator visibleBegin, visibleEnd; + getVisibleDataBounds(visibleBegin, visibleEnd); + + // loop over and draw segments of unselected/selected data: + QList selectedSegments, unselectedSegments, allSegments; + getDataSegments(selectedSegments, unselectedSegments); + allSegments << unselectedSegments << selectedSegments; + for (int i=0; i= unselectedSegments.size(); + QCPBarsDataContainer::const_iterator begin = visibleBegin; + QCPBarsDataContainer::const_iterator end = visibleEnd; + mDataContainer->limitIteratorsToDataRange(begin, end, allSegments.at(i)); + if (begin == end) + continue; + + for (QCPBarsDataContainer::const_iterator it=begin; it!=end; ++it) + { + // check data validity if flag set: +#ifdef QCUSTOMPLOT_CHECK_DATA + if (QCP::isInvalidData(it->key, it->value)) + qDebug() << Q_FUNC_INFO << "Data point at" << it->key << "of drawn range invalid." << "Plottable name:" << name(); +#endif + // draw bar: + if (isSelectedSegment && mSelectionDecorator) + { + mSelectionDecorator->applyBrush(painter); + mSelectionDecorator->applyPen(painter); + } else + { + painter->setBrush(mBrush); + painter->setPen(mPen); + } + applyDefaultAntialiasingHint(painter); + painter->drawPolygon(getBarRect(it->key, it->value)); + } + } - \see itemCount -*/ -QCPAbstractLegendItem *QCPLegend::item(int index) const + // draw other selection decoration that isn't just line/scatter pens and brushes: + if (mSelectionDecorator) + mSelectionDecorator->drawDecoration(painter, selection()); +} + +/* inherits documentation from base class */ +void QCPBars::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const { - return qobject_cast(elementAt(index)); + // draw filled rect: + applyDefaultAntialiasingHint(painter); + painter->setBrush(mBrush); + painter->setPen(mPen); + QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67); + r.moveCenter(rect.center()); + painter->drawRect(r); } -/*! - Returns the QCPPlottableLegendItem which is associated with \a plottable (e.g. a \ref QCPGraph*). - If such an item isn't in the legend, returns 0. +/*! \internal - \see hasItemWithPlottable + called by \ref draw to determine which data (key) range is visible at the current key axis range + setting, so only that needs to be processed. It also takes into account the bar width. + + \a begin returns an iterator to the lowest data point that needs to be taken into account when + plotting. Note that in order to get a clean plot all the way to the edge of the axis rect, \a + lower may still be just outside the visible range. + + \a end returns an iterator one higher than the highest visible data point. Same as before, \a end + may also lie just outside of the visible range. + + if the plottable contains no data, both \a begin and \a end point to constEnd. */ -QCPPlottableLegendItem *QCPLegend::itemWithPlottable(const QCPAbstractPlottable *plottable) const +void QCPBars::getVisibleDataBounds(QCPBarsDataContainer::const_iterator &begin, QCPBarsDataContainer::const_iterator &end) const { - for (int i=0; i(item(i))) - { - if (pli->plottable() == plottable) - return pli; - } + qDebug() << Q_FUNC_INFO << "invalid key axis"; + begin = mDataContainer->constEnd(); + end = mDataContainer->constEnd(); + return; + } + if (mDataContainer->isEmpty()) + { + begin = mDataContainer->constEnd(); + end = mDataContainer->constEnd(); + return; + } + + // get visible data range as QMap iterators + begin = mDataContainer->findBegin(mKeyAxis.data()->range().lower); + end = mDataContainer->findEnd(mKeyAxis.data()->range().upper); + double lowerPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().lower); + double upperPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().upper); + bool isVisible = false; + // walk left from begin to find lower bar that actually is completely outside visible pixel range: + QCPBarsDataContainer::const_iterator it = begin; + while (it != mDataContainer->constBegin()) + { + --it; + const QRectF barRect = getBarRect(it->key, it->value); + if (mKeyAxis.data()->orientation() == Qt::Horizontal) + isVisible = ((!mKeyAxis.data()->rangeReversed() && barRect.right() >= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barRect.left() <= lowerPixelBound)); + else // keyaxis is vertical + isVisible = ((!mKeyAxis.data()->rangeReversed() && barRect.top() <= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barRect.bottom() >= lowerPixelBound)); + if (isVisible) + begin = it; + else + break; + } + // walk right from ubound to find upper bar that actually is completely outside visible pixel range: + it = end; + while (it != mDataContainer->constEnd()) + { + const QRectF barRect = getBarRect(it->key, it->value); + if (mKeyAxis.data()->orientation() == Qt::Horizontal) + isVisible = ((!mKeyAxis.data()->rangeReversed() && barRect.left() <= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barRect.right() >= upperPixelBound)); + else // keyaxis is vertical + isVisible = ((!mKeyAxis.data()->rangeReversed() && barRect.bottom() >= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barRect.top() <= upperPixelBound)); + if (isVisible) + end = it+1; + else + break; + ++it; } - return 0; -} - -/*! - Returns the number of items currently in the legend. - \see item -*/ -int QCPLegend::itemCount() const -{ - return elementCount(); } -/*! - Returns whether the legend contains \a itm. +/*! \internal + + Returns the rect in pixel coordinates of a single bar with the specified \a key and \a value. The + rect is shifted according to the bar stacking (see \ref moveAbove) and base value (see \ref + setBaseValue), and to have non-overlapping border lines with the bars stacked below. */ -bool QCPLegend::hasItem(QCPAbstractLegendItem *item) const +QRectF QCPBars::getBarRect(double key, double value) const { - for (int i=0; i= 0); + double basePixel = valueAxis->coordToPixel(base); + double valuePixel = valueAxis->coordToPixel(base+value); + double keyPixel = keyAxis->coordToPixel(key); + if (mBarsGroup) + keyPixel += mBarsGroup->keyPixelOffset(this, key); + double bottomOffset = (mBarBelow && mPen != Qt::NoPen ? 1 : 0)*(mPen.isCosmetic() ? 1 : mPen.widthF()); + bottomOffset += mBarBelow ? mStackingGap : 0; + bottomOffset *= (value<0 ? -1 : 1)*valueAxis->pixelOrientation(); + if (qAbs(valuePixel-basePixel) <= qAbs(bottomOffset)) + bottomOffset = valuePixel-basePixel; + if (keyAxis->orientation() == Qt::Horizontal) { - if (item == this->item(i)) - return true; + return QRectF(QPointF(keyPixel+lowerPixelWidth, valuePixel), QPointF(keyPixel+upperPixelWidth, basePixel+bottomOffset)).normalized(); + } else + { + return QRectF(QPointF(basePixel+bottomOffset, keyPixel+lowerPixelWidth), QPointF(valuePixel, keyPixel+upperPixelWidth)).normalized(); } - return false; } -/*! - Returns whether the legend contains a QCPPlottableLegendItem which is associated with \a plottable (e.g. a \ref QCPGraph*). - If such an item isn't in the legend, returns false. +/*! \internal - \see itemWithPlottable + This function is used to determine the width of the bar at coordinate \a key, according to the + specified width (\ref setWidth) and width type (\ref setWidthType). + + The output parameters \a lower and \a upper return the number of pixels the bar extends to lower + and higher keys, relative to the \a key coordinate (so with a non-reversed horizontal axis, \a + lower is negative and \a upper positive). */ -bool QCPLegend::hasItemWithPlottable(const QCPAbstractPlottable *plottable) const +void QCPBars::getPixelWidth(double key, double &lower, double &upper) const { - return itemWithPlottable(plottable); + lower = 0; + upper = 0; + switch (mWidthType) + { + case wtAbsolute: + { + upper = mWidth*0.5*mKeyAxis.data()->pixelOrientation(); + lower = -upper; + break; + } + case wtAxisRectRatio: + { + if (mKeyAxis && mKeyAxis.data()->axisRect()) + { + if (mKeyAxis.data()->orientation() == Qt::Horizontal) + upper = mKeyAxis.data()->axisRect()->width()*mWidth*0.5*mKeyAxis.data()->pixelOrientation(); + else + upper = mKeyAxis.data()->axisRect()->height()*mWidth*0.5*mKeyAxis.data()->pixelOrientation(); + lower = -upper; + } else + qDebug() << Q_FUNC_INFO << "No key axis or axis rect defined"; + break; + } + case wtPlotCoords: + { + if (mKeyAxis) + { + double keyPixel = mKeyAxis.data()->coordToPixel(key); + upper = mKeyAxis.data()->coordToPixel(key+mWidth*0.5)-keyPixel; + lower = mKeyAxis.data()->coordToPixel(key-mWidth*0.5)-keyPixel; + // no need to qSwap(lower, higher) when range reversed, because higher/lower are gained by + // coordinate transform which includes range direction + } else + qDebug() << Q_FUNC_INFO << "No key axis defined"; + break; + } + } } -/*! - Adds \a item to the legend, if it's not present already. +/*! \internal - Returns true on sucess, i.e. if the item wasn't in the list already and has been successfuly added. + This function is called to find at which value to start drawing the base of a bar at \a key, when + it is stacked on top of another QCPBars (e.g. with \ref moveAbove). - The legend takes ownership of the item. + positive and negative bars are separated per stack (positive are stacked above baseValue upwards, + negative are stacked below baseValue downwards). This can be indicated with \a positive. So if the + bar for which we need the base value is negative, set \a positive to false. */ -bool QCPLegend::addItem(QCPAbstractLegendItem *item) +double QCPBars::getStackedBaseValue(double key, bool positive) const { - if (!hasItem(item)) + if (mBarBelow) { - return addElement(rowCount(), 0, item); + double max = 0; // don't initialize with mBaseValue here because only base value of bottom-most bar has meaning in a bar stack + // find bars of mBarBelow that are approximately at key and find largest one: + double epsilon = qAbs(key)*(sizeof(key)==4 ? 1e-6 : 1e-14); // should be safe even when changed to use float at some point + if (key == 0) + epsilon = (sizeof(key)==4 ? 1e-6 : 1e-14); + QCPBarsDataContainer::const_iterator it = mBarBelow.data()->mDataContainer->findBegin(key-epsilon); + QCPBarsDataContainer::const_iterator itEnd = mBarBelow.data()->mDataContainer->findEnd(key+epsilon); + while (it != itEnd) + { + if (it->key > key-epsilon && it->key < key+epsilon) + { + if ((positive && it->value > max) || + (!positive && it->value < max)) + max = it->value; + } + ++it; + } + // recurse down the bar-stack to find the total height: + return max + mBarBelow.data()->getStackedBaseValue(key, positive); } else - return false; + return mBaseValue; } -/*! - Removes the item with index \a index from the legend. +/*! \internal - Returns true, if successful. + Connects \a below and \a above to each other via their mBarAbove/mBarBelow properties. The bar(s) + currently above lower and below upper will become disconnected to lower/upper. - \see itemCount, clearItems + If lower is zero, upper will be disconnected at the bottom. + If upper is zero, lower will be disconnected at the top. */ -bool QCPLegend::removeItem(int index) +void QCPBars::connectBars(QCPBars *lower, QCPBars *upper) { - if (QCPAbstractLegendItem *ali = item(index)) + if (!lower && !upper) return; + + if (!lower) // disconnect upper at bottom { - bool success = remove(ali); - simplify(); - return success; - } else - return false; + // disconnect old bar below upper: + if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper) + upper->mBarBelow.data()->mBarAbove = nullptr; + upper->mBarBelow = nullptr; + } else if (!upper) // disconnect lower at top + { + // disconnect old bar above lower: + if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower) + lower->mBarAbove.data()->mBarBelow = nullptr; + lower->mBarAbove = nullptr; + } else // connect lower and upper + { + // disconnect old bar above lower: + if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower) + lower->mBarAbove.data()->mBarBelow = nullptr; + // disconnect old bar below upper: + if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper) + upper->mBarBelow.data()->mBarAbove = nullptr; + lower->mBarAbove = upper; + upper->mBarBelow = lower; + } } +/* end of 'src/plottables/plottable-bars.cpp' */ -/*! \overload - - Removes \a item from the legend. - Returns true, if successful. - - \see clearItems -*/ -bool QCPLegend::removeItem(QCPAbstractLegendItem *item) -{ - bool success = remove(item); - simplify(); - return success; -} +/* including file 'src/plottables/plottable-statisticalbox.cpp' */ +/* modified 2022-11-06T12:45:57, size 28951 */ -/*! - Removes all items from the legend. -*/ -void QCPLegend::clearItems() -{ - for (int i=itemCount()-1; i>=0; --i) - removeItem(i); -} +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPStatisticalBoxData +//////////////////////////////////////////////////////////////////////////////////////////////////// -/*! - Returns the legend items that are currently selected. If no items are selected, - the list is empty. +/*! \class QCPStatisticalBoxData + \brief Holds the data of one single data point for QCPStatisticalBox. - \see QCPAbstractLegendItem::setSelected, setSelectable + The stored data is: + + \li \a key: coordinate on the key axis of this data point (this is the \a mainKey and the \a sortKey) + + \li \a minimum: the position of the lower whisker, typically the minimum measurement of the + sample that's not considered an outlier. + + \li \a lowerQuartile: the lower end of the box. The lower and the upper quartiles are the two + statistical quartiles around the median of the sample, they should contain 50% of the sample + data. + + \li \a median: the value of the median mark inside the quartile box. The median separates the + sample data in half (50% of the sample data is below/above the median). (This is the \a mainValue) + + \li \a upperQuartile: the upper end of the box. The lower and the upper quartiles are the two + statistical quartiles around the median of the sample, they should contain 50% of the sample + data. + + \li \a maximum: the position of the upper whisker, typically the maximum measurement of the + sample that's not considered an outlier. + + \li \a outliers: a QVector of outlier values that will be drawn as scatter points at the \a key + coordinate of this data point (see \ref QCPStatisticalBox::setOutlierStyle) + + The container for storing multiple data points is \ref QCPStatisticalBoxDataContainer. It is a + typedef for \ref QCPDataContainer with \ref QCPStatisticalBoxData as the DataType template + parameter. See the documentation there for an explanation regarding the data type's generic + methods. + + \see QCPStatisticalBoxDataContainer */ -QList QCPLegend::selectedItems() const -{ - QList result; - for (int i=0; iselected()) - result.append(ali); - } - } - return result; -} - -/*! \internal - A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter - before drawing main legend elements. +/* start documentation of inline functions */ - This is the antialiasing state the painter passed to the \ref draw method is in by default. +/*! \fn double QCPStatisticalBoxData::sortKey() const - This function takes into account the local setting of the antialiasing flag as well as the - overrides set with \ref QCustomPlot::setAntialiasedElements and \ref - QCustomPlot::setNotAntialiasedElements. + Returns the \a key member of this data point. - \see setAntialiased + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -void QCPLegend::applyDefaultAntialiasingHint(QCPPainter *painter) const -{ - applyAntialiasingHint(painter, mAntialiased, QCP::aeLegend); -} -/*! \internal +/*! \fn static QCPStatisticalBoxData QCPStatisticalBoxData::fromSortKey(double sortKey) - Returns the pen used to paint the border of the legend, taking into account the selection state - of the legend box. + Returns a data point with the specified \a sortKey. All other members are set to zero. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -QPen QCPLegend::getBorderPen() const -{ - return mSelectedParts.testFlag(spLegendBox) ? mSelectedBorderPen : mBorderPen; -} -/*! \internal +/*! \fn static static bool QCPStatisticalBoxData::sortKeyIsMainKey() - Returns the brush used to paint the background of the legend, taking into account the selection - state of the legend box. + Since the member \a key is both the data point key coordinate and the data ordering parameter, + this method returns true. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -QBrush QCPLegend::getBrush() const -{ - return mSelectedParts.testFlag(spLegendBox) ? mSelectedBrush : mBrush; -} -/*! \internal +/*! \fn double QCPStatisticalBoxData::mainKey() const - Draws the legend box with the provided \a painter. The individual legend items are layerables - themselves, thus are drawn independently. + Returns the \a key member of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -void QCPLegend::draw(QCPPainter *painter) -{ - // draw background rect: - painter->setBrush(getBrush()); - painter->setPen(getBorderPen()); - painter->drawRect(mOuterRect); -} -/* inherits documentation from base class */ -double QCPLegend::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const -{ - if (!mParentPlot) return -1; - if (onlySelectable && !mSelectableParts.testFlag(spLegendBox)) - return -1; +/*! \fn double QCPStatisticalBoxData::mainValue() const - if (mOuterRect.contains(pos.toPoint())) - { - if (details) details->setValue(spLegendBox); - return mParentPlot->selectionTolerance()*0.99; - } - return -1; -} - -/* inherits documentation from base class */ -void QCPLegend::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) -{ - Q_UNUSED(event) - mSelectedParts = selectedParts(); // in case item selection has changed - if (details.value() == spLegendBox && mSelectableParts.testFlag(spLegendBox)) - { - SelectableParts selBefore = mSelectedParts; - setSelectedParts(additive ? mSelectedParts^spLegendBox : mSelectedParts|spLegendBox); // no need to unset spItems in !additive case, because they will be deselected by QCustomPlot (they're normal QCPLayerables with own deselectEvent) - if (selectionStateChanged) - *selectionStateChanged = mSelectedParts != selBefore; - } -} + Returns the \a median member of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ -/* inherits documentation from base class */ -void QCPLegend::deselectEvent(bool *selectionStateChanged) -{ - mSelectedParts = selectedParts(); // in case item selection has changed - if (mSelectableParts.testFlag(spLegendBox)) - { - SelectableParts selBefore = mSelectedParts; - setSelectedParts(selectedParts() & ~spLegendBox); - if (selectionStateChanged) - *selectionStateChanged = mSelectedParts != selBefore; - } -} +/*! \fn QCPRange QCPStatisticalBoxData::valueRange() const + + Returns a QCPRange spanning from the \a minimum to the \a maximum member of this statistical box + data point, possibly further expanded by outliers. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ -/* inherits documentation from base class */ -QCP::Interaction QCPLegend::selectionCategory() const -{ - return QCP::iSelectLegend; -} +/* end documentation of inline functions */ -/* inherits documentation from base class */ -QCP::Interaction QCPAbstractLegendItem::selectionCategory() const +/*! + Constructs a data point with key and all values set to zero. +*/ +QCPStatisticalBoxData::QCPStatisticalBoxData() : + key(0), + minimum(0), + lowerQuartile(0), + median(0), + upperQuartile(0), + maximum(0) { - return QCP::iSelectLegend; } -/* inherits documentation from base class */ -void QCPLegend::parentPlotInitialized(QCustomPlot *parentPlot) +/*! + Constructs a data point with the specified \a key, \a minimum, \a lowerQuartile, \a median, \a + upperQuartile, \a maximum and optionally a number of \a outliers. +*/ +QCPStatisticalBoxData::QCPStatisticalBoxData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum, const QVector &outliers) : + key(key), + minimum(minimum), + lowerQuartile(lowerQuartile), + median(median), + upperQuartile(upperQuartile), + maximum(maximum), + outliers(outliers) { - Q_UNUSED(parentPlot) } //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPPlotTitle +//////////////////// QCPStatisticalBox //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPPlotTitle - \brief A layout element displaying a plot title text +/*! \class QCPStatisticalBox + \brief A plottable representing a single statistical box in a plot. + + \image html QCPStatisticalBox.png + + To plot data, assign it with the \ref setData or \ref addData functions. Alternatively, you can + also access and modify the data via the \ref data method, which returns a pointer to the internal + \ref QCPStatisticalBoxDataContainer. + + Additionally each data point can itself have a list of outliers, drawn as scatter points at the + key coordinate of the respective statistical box data point. They can either be set by using the + respective \ref addData(double,double,double,double,double,double,const QVector&) + "addData" method or accessing the individual data points through \ref data, and setting the + QVector outliers of the data points directly. + + \section qcpstatisticalbox-appearance Changing the appearance + + The appearance of each data point box, ranging from the lower to the upper quartile, is + controlled via \ref setPen and \ref setBrush. You may change the width of the boxes with \ref + setWidth in plot coordinates. + + Each data point's visual representation also consists of two whiskers. Whiskers are the lines + which reach from the upper quartile to the maximum, and from the lower quartile to the minimum. + The appearance of the whiskers can be modified with: \ref setWhiskerPen, \ref setWhiskerBarPen, + \ref setWhiskerWidth. The whisker width is the width of the bar perpendicular to the whisker at + the top (for maximum) and bottom (for minimum). If the whisker pen is changed, make sure to set + the \c capStyle to \c Qt::FlatCap. Otherwise the backbone line might exceed the whisker bars by a + few pixels due to the pen cap being not perfectly flat. - The text may be specified with \ref setText, theformatting can be controlled with \ref setFont - and \ref setTextColor. + The median indicator line inside the box has its own pen, \ref setMedianPen. - A plot title can be added as follows: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpplottitle-creation + The outlier data points are drawn as normal scatter points. Their look can be controlled with + \ref setOutlierStyle + + \section qcpstatisticalbox-usage Usage + + Like all data representing objects in QCustomPlot, the QCPStatisticalBox is a plottable + (QCPAbstractPlottable). So the plottable-interface of QCustomPlot applies + (QCustomPlot::plottable, QCustomPlot::removePlottable, etc.) - Since a plot title is a common requirement, QCustomPlot offers specialized selection signals for - easy interaction with QCPPlotTitle. If a layout element of type QCPPlotTitle is clicked, the - signal \ref QCustomPlot::titleClick is emitted. A double click emits the \ref - QCustomPlot::titleDoubleClick signal. + Usually, you first create an instance: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpstatisticalbox-creation-1 + which registers it with the QCustomPlot instance of the passed axes. Note that this QCustomPlot instance takes + ownership of the plottable, so do not delete it manually but use QCustomPlot::removePlottable() instead. + The newly created plottable can be modified, e.g.: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpstatisticalbox-creation-2 */ -/* start documentation of signals */ +/* start documentation of inline functions */ -/*! \fn void QCPPlotTitle::selectionChanged(bool selected) - - This signal is emitted when the selection state has changed to \a selected, either by user - interaction or by a direct call to \ref setSelected. +/*! \fn QSharedPointer QCPStatisticalBox::data() const - \see setSelected, setSelectable + Returns a shared pointer to the internal data storage of type \ref + QCPStatisticalBoxDataContainer. You may use it to directly manipulate the data, which may be more + convenient and faster than using the regular \ref setData or \ref addData methods. */ -/* end documentation of signals */ +/* end documentation of inline functions */ /*! - Creates a new QCPPlotTitle instance and sets default values. The initial text is empty (\ref setText). + Constructs a statistical box which uses \a keyAxis as its key axis ("x") and \a valueAxis as its + value axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and + not have the same orientation. If either of these restrictions is violated, a corresponding + message is printed to the debug output (qDebug), the construction is not aborted, though. - To set the title text in the constructor, rather use \ref QCPPlotTitle(QCustomPlot *parentPlot, const QString &text). + The created QCPStatisticalBox is automatically registered with the QCustomPlot instance inferred + from \a keyAxis. This QCustomPlot instance takes ownership of the QCPStatisticalBox, so do not + delete it manually but use QCustomPlot::removePlottable() instead. */ -QCPPlotTitle::QCPPlotTitle(QCustomPlot *parentPlot) : - QCPLayoutElement(parentPlot), - mFont(QFont(QLatin1String("sans serif"), 13*1.5, QFont::Bold)), - mTextColor(Qt::black), - mSelectedFont(QFont(QLatin1String("sans serif"), 13*1.6, QFont::Bold)), - mSelectedTextColor(Qt::blue), - mSelectable(false), - mSelected(false) +QCPStatisticalBox::QCPStatisticalBox(QCPAxis *keyAxis, QCPAxis *valueAxis) : + QCPAbstractPlottable1D(keyAxis, valueAxis), + mWidth(0.5), + mWhiskerWidth(0.2), + mWhiskerPen(Qt::black, 0, Qt::DashLine, Qt::FlatCap), + mWhiskerBarPen(Qt::black), + mWhiskerAntialiased(false), + mMedianPen(Qt::black, 3, Qt::SolidLine, Qt::FlatCap), + mOutlierStyle(QCPScatterStyle::ssCircle, Qt::blue, 6) { - if (parentPlot) - { - setLayer(parentPlot->currentLayer()); - mFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold); - mSelectedFont = QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold); - } - setMargins(QMargins(5, 5, 5, 0)); + setPen(QPen(Qt::black)); + setBrush(Qt::NoBrush); } /*! \overload - Creates a new QCPPlotTitle instance and sets default values. The initial text is set to \a text. + Replaces the current data container with the provided \a data container. + + Since a QSharedPointer is used, multiple QCPStatisticalBoxes may share the same data container + safely. Modifying the data in the container will then affect all statistical boxes that share the + container. Sharing can be achieved by simply exchanging the data containers wrapped in shared + pointers: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpstatisticalbox-datasharing-1 + + If you do not wish to share containers, but create a copy from an existing container, rather use + the \ref QCPDataContainer::set method on the statistical box data container directly: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpstatisticalbox-datasharing-2 + + \see addData */ -QCPPlotTitle::QCPPlotTitle(QCustomPlot *parentPlot, const QString &text) : - QCPLayoutElement(parentPlot), - mText(text), - mFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.5, QFont::Bold)), - mTextColor(Qt::black), - mSelectedFont(QFont(parentPlot->font().family(), parentPlot->font().pointSize()*1.6, QFont::Bold)), - mSelectedTextColor(Qt::blue), - mSelectable(false), - mSelected(false) +void QCPStatisticalBox::setData(QSharedPointer data) +{ + mDataContainer = data; +} +/*! \overload + + Replaces the current data with the provided points in \a keys, \a minimum, \a lowerQuartile, \a + median, \a upperQuartile and \a maximum. The provided vectors should have equal length. Else, the + number of added points will be the size of the smallest vector. + + If you can guarantee that the passed data points are sorted by \a keys in ascending order, you + can set \a alreadySorted to true, to improve performance by saving a sorting run. + + \see addData +*/ +void QCPStatisticalBox::setData(const QVector &keys, const QVector &minimum, const QVector &lowerQuartile, const QVector &median, const QVector &upperQuartile, const QVector &maximum, bool alreadySorted) { - setLayer(QLatin1String("axes")); - setMargins(QMargins(5, 5, 5, 0)); + mDataContainer->clear(); + addData(keys, minimum, lowerQuartile, median, upperQuartile, maximum, alreadySorted); } /*! - Sets the text that will be displayed to \a text. Multiple lines can be created by insertion of "\n". + Sets the width of the boxes in key coordinates. - \see setFont, setTextColor + \see setWhiskerWidth */ -void QCPPlotTitle::setText(const QString &text) +void QCPStatisticalBox::setWidth(double width) { - mText = text; + mWidth = width; } /*! - Sets the \a font of the title text. + Sets the width of the whiskers in key coordinates. - \see setTextColor, setSelectedFont + Whiskers are the lines which reach from the upper quartile to the maximum, and from the lower + quartile to the minimum. + + \see setWidth */ -void QCPPlotTitle::setFont(const QFont &font) +void QCPStatisticalBox::setWhiskerWidth(double width) { - mFont = font; + mWhiskerWidth = width; } /*! - Sets the \a color of the title text. + Sets the pen used for drawing the whisker backbone. - \see setFont, setSelectedTextColor + Whiskers are the lines which reach from the upper quartile to the maximum, and from the lower + quartile to the minimum. + + Make sure to set the \c capStyle of the passed \a pen to \c Qt::FlatCap. Otherwise the backbone + line might exceed the whisker bars by a few pixels due to the pen cap being not perfectly flat. + + \see setWhiskerBarPen */ -void QCPPlotTitle::setTextColor(const QColor &color) +void QCPStatisticalBox::setWhiskerPen(const QPen &pen) { - mTextColor = color; + mWhiskerPen = pen; } /*! - Sets the \a font of the title text that will be used if the plot title is selected (\ref setSelected). + Sets the pen used for drawing the whisker bars. Those are the lines parallel to the key axis at + each end of the whisker backbone. - \see setFont + Whiskers are the lines which reach from the upper quartile to the maximum, and from the lower + quartile to the minimum. + + \see setWhiskerPen */ -void QCPPlotTitle::setSelectedFont(const QFont &font) +void QCPStatisticalBox::setWhiskerBarPen(const QPen &pen) { - mSelectedFont = font; + mWhiskerBarPen = pen; } /*! - Sets the \a color of the title text that will be used if the plot title is selected (\ref setSelected). - - \see setTextColor + Sets whether the statistical boxes whiskers are drawn with antialiasing or not. + + Note that antialiasing settings may be overridden by QCustomPlot::setAntialiasedElements and + QCustomPlot::setNotAntialiasedElements. */ -void QCPPlotTitle::setSelectedTextColor(const QColor &color) +void QCPStatisticalBox::setWhiskerAntialiased(bool enabled) { - mSelectedTextColor = color; + mWhiskerAntialiased = enabled; } /*! - Sets whether the user may select this plot title to \a selectable. + Sets the pen used for drawing the median indicator line inside the statistical boxes. +*/ +void QCPStatisticalBox::setMedianPen(const QPen &pen) +{ + mMedianPen = pen; +} - Note that even when \a selectable is set to false, the selection state may be changed - programmatically via \ref setSelected. +/*! + Sets the appearance of the outlier data points. + + Outliers can be specified with the method + \ref addData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum, const QVector &outliers) */ -void QCPPlotTitle::setSelectable(bool selectable) +void QCPStatisticalBox::setOutlierStyle(const QCPScatterStyle &style) { - if (mSelectable != selectable) + mOutlierStyle = style; +} + +/*! \overload + + Adds the provided points in \a keys, \a minimum, \a lowerQuartile, \a median, \a upperQuartile and + \a maximum to the current data. The provided vectors should have equal length. Else, the number + of added points will be the size of the smallest vector. + + If you can guarantee that the passed data points are sorted by \a keys in ascending order, you + can set \a alreadySorted to true, to improve performance by saving a sorting run. + + Alternatively, you can also access and modify the data directly via the \ref data method, which + returns a pointer to the internal data container. +*/ +void QCPStatisticalBox::addData(const QVector &keys, const QVector &minimum, const QVector &lowerQuartile, const QVector &median, const QVector &upperQuartile, const QVector &maximum, bool alreadySorted) +{ + if (keys.size() != minimum.size() || minimum.size() != lowerQuartile.size() || lowerQuartile.size() != median.size() || + median.size() != upperQuartile.size() || upperQuartile.size() != maximum.size() || maximum.size() != keys.size()) + qDebug() << Q_FUNC_INFO << "keys, minimum, lowerQuartile, median, upperQuartile, maximum have different sizes:" + << keys.size() << minimum.size() << lowerQuartile.size() << median.size() << upperQuartile.size() << maximum.size(); + const int n = qMin(keys.size(), qMin(minimum.size(), qMin(lowerQuartile.size(), qMin(median.size(), qMin(upperQuartile.size(), maximum.size()))))); + QVector tempData(n); + QVector::iterator it = tempData.begin(); + const QVector::iterator itEnd = tempData.end(); + int i = 0; + while (it != itEnd) { - mSelectable = selectable; - emit selectableChanged(mSelectable); + it->key = keys[i]; + it->minimum = minimum[i]; + it->lowerQuartile = lowerQuartile[i]; + it->median = median[i]; + it->upperQuartile = upperQuartile[i]; + it->maximum = maximum[i]; + ++it; + ++i; } + mDataContainer->add(tempData, alreadySorted); // don't modify tempData beyond this to prevent copy on write +} + +/*! \overload + + Adds the provided data point as \a key, \a minimum, \a lowerQuartile, \a median, \a upperQuartile + and \a maximum to the current data. + + Alternatively, you can also access and modify the data directly via the \ref data method, which + returns a pointer to the internal data container. +*/ +void QCPStatisticalBox::addData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum, const QVector &outliers) +{ + mDataContainer->add(QCPStatisticalBoxData(key, minimum, lowerQuartile, median, upperQuartile, maximum, outliers)); } /*! - Sets the selection state of this plot title to \a selected. If the selection has changed, \ref - selectionChanged is emitted. + \copydoc QCPPlottableInterface1D::selectTestRect +*/ +QCPDataSelection QCPStatisticalBox::selectTestRect(const QRectF &rect, bool onlySelectable) const +{ + QCPDataSelection result; + if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty()) + return result; + if (!mKeyAxis || !mValueAxis) + return result; - Note that this function can change the selection state independently of the current \ref - setSelectable state. + QCPStatisticalBoxDataContainer::const_iterator visibleBegin, visibleEnd; + getVisibleDataBounds(visibleBegin, visibleEnd); + + for (QCPStatisticalBoxDataContainer::const_iterator it=visibleBegin; it!=visibleEnd; ++it) + { + if (rect.intersects(getQuartileBox(it))) + result.addDataRange(QCPDataRange(int(it-mDataContainer->constBegin()), int(it-mDataContainer->constBegin()+1)), false); + } + result.simplify(); + return result; +} + +/*! + Implements a selectTest specific to this plottable's point geometry. + + If \a details is not 0, it will be set to a \ref QCPDataSelection, describing the closest data + point to \a pos. + + \seebaseclassmethod \ref QCPAbstractPlottable::selectTest */ -void QCPPlotTitle::setSelected(bool selected) +double QCPStatisticalBox::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - if (mSelected != selected) + Q_UNUSED(details) + if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty()) + return -1; + if (!mKeyAxis || !mValueAxis) + return -1; + + if (mKeyAxis->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect)) { - mSelected = selected; - emit selectionChanged(mSelected); + // get visible data range: + QCPStatisticalBoxDataContainer::const_iterator visibleBegin, visibleEnd; + QCPStatisticalBoxDataContainer::const_iterator closestDataPoint = mDataContainer->constEnd(); + getVisibleDataBounds(visibleBegin, visibleEnd); + double minDistSqr = (std::numeric_limits::max)(); + for (QCPStatisticalBoxDataContainer::const_iterator it=visibleBegin; it!=visibleEnd; ++it) + { + if (getQuartileBox(it).contains(pos)) // quartile box + { + double currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99; + if (currentDistSqr < minDistSqr) + { + minDistSqr = currentDistSqr; + closestDataPoint = it; + } + } else // whiskers + { + const QVector whiskerBackbones = getWhiskerBackboneLines(it); + const QCPVector2D posVec(pos); + foreach (const QLineF &backbone, whiskerBackbones) + { + double currentDistSqr = posVec.distanceSquaredToLine(backbone); + if (currentDistSqr < minDistSqr) + { + minDistSqr = currentDistSqr; + closestDataPoint = it; + } + } + } + } + if (details) + { + int pointIndex = int(closestDataPoint-mDataContainer->constBegin()); + details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1))); + } + return qSqrt(minDistSqr); } + return -1; } /* inherits documentation from base class */ -void QCPPlotTitle::applyDefaultAntialiasingHint(QCPPainter *painter) const +QCPRange QCPStatisticalBox::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const { - applyAntialiasingHint(painter, mAntialiased, QCP::aeNone); + QCPRange range = mDataContainer->keyRange(foundRange, inSignDomain); + // determine exact range by including width of bars/flags: + if (foundRange) + { + if (inSignDomain != QCP::sdPositive || range.lower-mWidth*0.5 > 0) + range.lower -= mWidth*0.5; + if (inSignDomain != QCP::sdNegative || range.upper+mWidth*0.5 < 0) + range.upper += mWidth*0.5; + } + return range; } /* inherits documentation from base class */ -void QCPPlotTitle::draw(QCPPainter *painter) +QCPRange QCPStatisticalBox::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const { - painter->setFont(mainFont()); - painter->setPen(QPen(mainTextColor())); - painter->drawText(mRect, Qt::AlignCenter, mText, &mTextBoundingRect); + return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange); } /* inherits documentation from base class */ -QSize QCPPlotTitle::minimumSizeHint() const +void QCPStatisticalBox::draw(QCPPainter *painter) { - QFontMetrics metrics(mFont); - QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size(); - result.rwidth() += mMargins.left() + mMargins.right(); - result.rheight() += mMargins.top() + mMargins.bottom(); - return result; + if (mDataContainer->isEmpty()) return; + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + + QCPStatisticalBoxDataContainer::const_iterator visibleBegin, visibleEnd; + getVisibleDataBounds(visibleBegin, visibleEnd); + + // loop over and draw segments of unselected/selected data: + QList selectedSegments, unselectedSegments, allSegments; + getDataSegments(selectedSegments, unselectedSegments); + allSegments << unselectedSegments << selectedSegments; + for (int i=0; i= unselectedSegments.size(); + QCPStatisticalBoxDataContainer::const_iterator begin = visibleBegin; + QCPStatisticalBoxDataContainer::const_iterator end = visibleEnd; + mDataContainer->limitIteratorsToDataRange(begin, end, allSegments.at(i)); + if (begin == end) + continue; + + for (QCPStatisticalBoxDataContainer::const_iterator it=begin; it!=end; ++it) + { + // check data validity if flag set: +# ifdef QCUSTOMPLOT_CHECK_DATA + if (QCP::isInvalidData(it->key, it->minimum) || + QCP::isInvalidData(it->lowerQuartile, it->median) || + QCP::isInvalidData(it->upperQuartile, it->maximum)) + qDebug() << Q_FUNC_INFO << "Data point at" << it->key << "of drawn range has invalid data." << "Plottable name:" << name(); + for (int i=0; ioutliers.size(); ++i) + if (QCP::isInvalidData(it->outliers.at(i))) + qDebug() << Q_FUNC_INFO << "Data point outlier at" << it->key << "of drawn range invalid." << "Plottable name:" << name(); +# endif + + if (isSelectedSegment && mSelectionDecorator) + { + mSelectionDecorator->applyPen(painter); + mSelectionDecorator->applyBrush(painter); + } else + { + painter->setPen(mPen); + painter->setBrush(mBrush); + } + QCPScatterStyle finalOutlierStyle = mOutlierStyle; + if (isSelectedSegment && mSelectionDecorator) + finalOutlierStyle = mSelectionDecorator->getFinalScatterStyle(mOutlierStyle); + drawStatisticalBox(painter, it, finalOutlierStyle); + } + } + + // draw other selection decoration that isn't just line/scatter pens and brushes: + if (mSelectionDecorator) + mSelectionDecorator->drawDecoration(painter, selection()); } /* inherits documentation from base class */ -QSize QCPPlotTitle::maximumSizeHint() const +void QCPStatisticalBox::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const { - QFontMetrics metrics(mFont); - QSize result = metrics.boundingRect(0, 0, 0, 0, Qt::AlignCenter, mText).size(); - result.rheight() += mMargins.top() + mMargins.bottom(); - result.setWidth(QWIDGETSIZE_MAX); - return result; + // draw filled rect: + applyDefaultAntialiasingHint(painter); + painter->setPen(mPen); + painter->setBrush(mBrush); + QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67); + r.moveCenter(rect.center()); + painter->drawRect(r); } -/* inherits documentation from base class */ -void QCPPlotTitle::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) +/*! + Draws the graphical representation of a single statistical box with the data given by the + iterator \a it with the provided \a painter. + + If the statistical box has a set of outlier data points, they are drawn with \a outlierStyle. + + \see getQuartileBox, getWhiskerBackboneLines, getWhiskerBarLines +*/ +void QCPStatisticalBox::drawStatisticalBox(QCPPainter *painter, QCPStatisticalBoxDataContainer::const_iterator it, const QCPScatterStyle &outlierStyle) const { - Q_UNUSED(event) - Q_UNUSED(details) - if (mSelectable) - { - bool selBefore = mSelected; - setSelected(additive ? !mSelected : true); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; - } + // draw quartile box: + applyDefaultAntialiasingHint(painter); + const QRectF quartileBox = getQuartileBox(it); + painter->drawRect(quartileBox); + // draw median line with cliprect set to quartile box: + painter->save(); + painter->setClipRect(quartileBox, Qt::IntersectClip); + painter->setPen(mMedianPen); + painter->drawLine(QLineF(coordsToPixels(it->key-mWidth*0.5, it->median), coordsToPixels(it->key+mWidth*0.5, it->median))); + painter->restore(); + // draw whisker lines: + applyAntialiasingHint(painter, mWhiskerAntialiased, QCP::aePlottables); + painter->setPen(mWhiskerPen); + painter->drawLines(getWhiskerBackboneLines(it)); + painter->setPen(mWhiskerBarPen); + painter->drawLines(getWhiskerBarLines(it)); + // draw outliers: + applyScattersAntialiasingHint(painter); + outlierStyle.applyTo(painter, mPen); + for (int i=0; ioutliers.size(); ++i) + outlierStyle.drawShape(painter, coordsToPixels(it->key, it->outliers.at(i))); } -/* inherits documentation from base class */ -void QCPPlotTitle::deselectEvent(bool *selectionStateChanged) +/*! \internal + + called by \ref draw to determine which data (key) range is visible at the current key axis range + setting, so only that needs to be processed. It also takes into account the bar width. + + \a begin returns an iterator to the lowest data point that needs to be taken into account when + plotting. Note that in order to get a clean plot all the way to the edge of the axis rect, \a + lower may still be just outside the visible range. + + \a end returns an iterator one higher than the highest visible data point. Same as before, \a end + may also lie just outside of the visible range. + + if the plottable contains no data, both \a begin and \a end point to constEnd. +*/ +void QCPStatisticalBox::getVisibleDataBounds(QCPStatisticalBoxDataContainer::const_iterator &begin, QCPStatisticalBoxDataContainer::const_iterator &end) const { - if (mSelectable) + if (!mKeyAxis) { - bool selBefore = mSelected; - setSelected(false); - if (selectionStateChanged) - *selectionStateChanged = mSelected != selBefore; + qDebug() << Q_FUNC_INFO << "invalid key axis"; + begin = mDataContainer->constEnd(); + end = mDataContainer->constEnd(); + return; } + begin = mDataContainer->findBegin(mKeyAxis.data()->range().lower-mWidth*0.5); // subtract half width of box to include partially visible data points + end = mDataContainer->findEnd(mKeyAxis.data()->range().upper+mWidth*0.5); // add half width of box to include partially visible data points } -/* inherits documentation from base class */ -double QCPPlotTitle::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +/*! \internal + + Returns the box in plot coordinates (keys in x, values in y of the returned rect) that covers the + value range from the lower to the upper quartile, of the data given by \a it. + + \see drawStatisticalBox, getWhiskerBackboneLines, getWhiskerBarLines +*/ +QRectF QCPStatisticalBox::getQuartileBox(QCPStatisticalBoxDataContainer::const_iterator it) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - if (mTextBoundingRect.contains(pos.toPoint())) - return mParentPlot->selectionTolerance()*0.99; - else - return -1; + QRectF result; + result.setTopLeft(coordsToPixels(it->key-mWidth*0.5, it->upperQuartile)); + result.setBottomRight(coordsToPixels(it->key+mWidth*0.5, it->lowerQuartile)); + return result; } -/*! \internal - - Returns the main font to be used. This is mSelectedFont if \ref setSelected is set to - true, else mFont is returned. +/*! \internal + + Returns the whisker backbones (keys in x, values in y of the returned lines) that cover the value + range from the minimum to the lower quartile, and from the upper quartile to the maximum of the + data given by \a it. + + \see drawStatisticalBox, getQuartileBox, getWhiskerBarLines */ -QFont QCPPlotTitle::mainFont() const +QVector QCPStatisticalBox::getWhiskerBackboneLines(QCPStatisticalBoxDataContainer::const_iterator it) const { - return mSelected ? mSelectedFont : mFont; + QVector result(2); + result[0].setPoints(coordsToPixels(it->key, it->lowerQuartile), coordsToPixels(it->key, it->minimum)); // min backbone + result[1].setPoints(coordsToPixels(it->key, it->upperQuartile), coordsToPixels(it->key, it->maximum)); // max backbone + return result; } -/*! \internal - - Returns the main color to be used. This is mSelectedTextColor if \ref setSelected is set to - true, else mTextColor is returned. +/*! \internal + + Returns the whisker bars (keys in x, values in y of the returned lines) that are placed at the + end of the whisker backbones, at the minimum and maximum of the data given by \a it. + + \see drawStatisticalBox, getQuartileBox, getWhiskerBackboneLines */ -QColor QCPPlotTitle::mainTextColor() const +QVector QCPStatisticalBox::getWhiskerBarLines(QCPStatisticalBoxDataContainer::const_iterator it) const { - return mSelected ? mSelectedTextColor : mTextColor; + QVector result(2); + result[0].setPoints(coordsToPixels(it->key-mWhiskerWidth*0.5, it->minimum), coordsToPixels(it->key+mWhiskerWidth*0.5, it->minimum)); // min bar + result[1].setPoints(coordsToPixels(it->key-mWhiskerWidth*0.5, it->maximum), coordsToPixels(it->key+mWhiskerWidth*0.5, it->maximum)); // max bar + return result; } +/* end of 'src/plottables/plottable-statisticalbox.cpp' */ + +/* including file 'src/plottables/plottable-colormap.cpp' */ +/* modified 2022-11-06T12:45:56, size 48189 */ //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPColorScale +//////////////////// QCPColorMapData //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPColorScale - \brief A color scale for use with color coding data such as QCPColorMap - - This layout element can be placed on the plot to correlate a color gradient with data values. It - is usually used in combination with one or multiple \ref QCPColorMap "QCPColorMaps". - - \image html QCPColorScale.png - - The color scale can be either horizontal or vertical, as shown in the image above. The - orientation and the side where the numbers appear is controlled with \ref setType. - - Use \ref QCPColorMap::setColorScale to connect a color map with a color scale. Once they are - connected, they share their gradient, data range and data scale type (\ref setGradient, \ref - setDataRange, \ref setDataScaleType). Multiple color maps may be associated with a single color - scale, to make them all synchronize these properties. - - To have finer control over the number display and axis behaviour, you can directly access the - \ref axis. See the documentation of QCPAxis for details about configuring axes. For example, if - you want to change the number of automatically generated ticks, call - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcolorscale-autotickcount - - Placing a color scale next to the main axis rect works like with any other layout element: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcolorscale-creation - In this case we have placed it to the right of the default axis rect, so it wasn't necessary to - call \ref setType, since \ref QCPAxis::atRight is already the default. The text next to the color - scale can be set with \ref setLabel. - - For optimum appearance (like in the image above), it may be desirable to line up the axis rect and - the borders of the color scale. Use a \ref QCPMarginGroup to achieve this: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcolorscale-margingroup +/*! \class QCPColorMapData + \brief Holds the two-dimensional data of a QCPColorMap plottable. - Color scales are initialized with a non-zero minimum top and bottom margin (\ref - setMinimumMargins), because vertical color scales are most common and the minimum top/bottom - margin makes sure it keeps some distance to the top/bottom widget border. So if you change to a - horizontal color scale by setting \ref setType to \ref QCPAxis::atBottom or \ref QCPAxis::atTop, you - might want to also change the minimum margins accordingly, e.g. setMinimumMargins(QMargins(6, 0, 6, 0)). -*/ - -/* start documentation of inline functions */ - -/*! \fn QCPAxis *QCPColorScale::axis() const + This class is a data storage for \ref QCPColorMap. It holds a two-dimensional array, which \ref + QCPColorMap then displays as a 2D image in the plot, where the array values are represented by a + color, depending on the value. - Returns the internal \ref QCPAxis instance of this color scale. You can access it to alter the - appearance and behaviour of the axis. \ref QCPColorScale duplicates some properties in its - interface for convenience. Those are \ref setDataRange (\ref QCPAxis::setRange), \ref - setDataScaleType (\ref QCPAxis::setScaleType), and the method \ref setLabel (\ref - QCPAxis::setLabel). As they each are connected, it does not matter whether you use the method on - the QCPColorScale or on its QCPAxis. + The size of the array can be controlled via \ref setSize (or \ref setKeySize, \ref setValueSize). + Which plot coordinates these cells correspond to can be configured with \ref setRange (or \ref + setKeyRange, \ref setValueRange). - If the type of the color scale is changed with \ref setType, the axis returned by this method - will change, too, to either the left, right, bottom or top axis, depending on which type was set. -*/ - -/* end documentation of signals */ -/* start documentation of signals */ - -/*! \fn void QCPColorScale::dataRangeChanged(QCPRange newRange); + The data cells can be accessed in two ways: They can be directly addressed by an integer index + with \ref setCell. This is the fastest method. Alternatively, they can be addressed by their plot + coordinate with \ref setData. plot coordinate to cell index transformations and vice versa are + provided by the functions \ref coordToCell and \ref cellToCoord. - This signal is emitted when the data range changes. + A \ref QCPColorMapData also holds an on-demand two-dimensional array of alpha values which (if + allocated) has the same size as the data map. It can be accessed via \ref setAlpha, \ref + fillAlpha and \ref clearAlpha. The memory for the alpha map is only allocated if needed, i.e. on + the first call of \ref setAlpha. \ref clearAlpha restores full opacity and frees the alpha map. - \see setDataRange + This class also buffers the minimum and maximum values that are in the data set, to provide + QCPColorMap::rescaleDataRange with the necessary information quickly. Setting a cell to a value + that is greater than the current maximum increases this maximum to the new value. However, + setting the cell that currently holds the maximum value to a smaller value doesn't decrease the + maximum again, because finding the true new maximum would require going through the entire data + array, which might be time consuming. The same holds for the data minimum. This functionality is + given by \ref recalculateDataBounds, such that you can decide when it is sensible to find the + true current minimum and maximum. The method QCPColorMap::rescaleDataRange offers a convenience + parameter \a recalculateDataBounds which may be set to true to automatically call \ref + recalculateDataBounds internally. */ -/*! \fn void QCPColorScale::dataScaleTypeChanged(QCPAxis::ScaleType scaleType); - - This signal is emitted when the data scale type changes. - - \see setDataScaleType -*/ +/* start of documentation of inline functions */ -/*! \fn void QCPColorScale::gradientChanged(QCPColorGradient newGradient); - - This signal is emitted when the gradient changes. +/*! \fn bool QCPColorMapData::isEmpty() const - \see setGradient + Returns whether this instance carries no data. This is equivalent to having a size where at least + one of the dimensions is 0 (see \ref setSize). */ -/* end documentation of signals */ +/* end of documentation of inline functions */ /*! - Constructs a new QCPColorScale. + Constructs a new QCPColorMapData instance. The instance has \a keySize cells in the key direction + and \a valueSize cells in the value direction. These cells will be displayed by the \ref QCPColorMap + at the coordinates \a keyRange and \a valueRange. + + \see setSize, setKeySize, setValueSize, setRange, setKeyRange, setValueRange */ -QCPColorScale::QCPColorScale(QCustomPlot *parentPlot) : - QCPLayoutElement(parentPlot), - mType(QCPAxis::atTop), // set to atTop such that setType(QCPAxis::atRight) below doesn't skip work because it thinks it's already atRight - mDataScaleType(QCPAxis::stLinear), - mBarWidth(20), - mAxisRect(new QCPColorScaleAxisRectPrivate(this)) -{ - setMinimumMargins(QMargins(0, 6, 0, 6)); // for default right color scale types, keep some room at bottom and top (important if no margin group is used) - setType(QCPAxis::atRight); - setDataRange(QCPRange(0, 6)); -} - -QCPColorScale::~QCPColorScale() -{ - delete mAxisRect; -} - -/* undocumented getter */ -QString QCPColorScale::label() const +QCPColorMapData::QCPColorMapData(int keySize, int valueSize, const QCPRange &keyRange, const QCPRange &valueRange) : + mKeySize(0), + mValueSize(0), + mKeyRange(keyRange), + mValueRange(valueRange), + mIsEmpty(true), + mData(nullptr), + mAlpha(nullptr), + mDataModified(true) { - if (!mColorAxis) - { - qDebug() << Q_FUNC_INFO << "internal color axis undefined"; - return QString(); - } - - return mColorAxis.data()->label(); + setSize(keySize, valueSize); + fill(0); } -/* undocumented getter */ -bool QCPColorScale::rangeDrag() const +QCPColorMapData::~QCPColorMapData() { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return false; - } - - return mAxisRect.data()->rangeDrag().testFlag(QCPAxis::orientation(mType)) && - mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType)) && - mAxisRect.data()->rangeDragAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType); + delete[] mData; + delete[] mAlpha; } -/* undocumented getter */ -bool QCPColorScale::rangeZoom() const +/*! + Constructs a new QCPColorMapData instance copying the data and range of \a other. +*/ +QCPColorMapData::QCPColorMapData(const QCPColorMapData &other) : + mKeySize(0), + mValueSize(0), + mIsEmpty(true), + mData(nullptr), + mAlpha(nullptr), + mDataModified(true) { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return false; - } - - return mAxisRect.data()->rangeZoom().testFlag(QCPAxis::orientation(mType)) && - mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType)) && - mAxisRect.data()->rangeZoomAxis(QCPAxis::orientation(mType))->orientation() == QCPAxis::orientation(mType); + *this = other; } /*! - Sets at which side of the color scale the axis is placed, and thus also its orientation. - - Note that after setting \a type to a different value, the axis returned by \ref axis() will - be a different one. The new axis will adopt the following properties from the previous axis: The - range, scale type, log base and label. + Overwrites this color map data instance with the data stored in \a other. The alpha map state is + transferred, too. */ -void QCPColorScale::setType(QCPAxis::AxisType type) +QCPColorMapData &QCPColorMapData::operator=(const QCPColorMapData &other) { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; - } - if (mType != type) + if (&other != this) { - mType = type; - QCPRange rangeTransfer(0, 6); - double logBaseTransfer = 10; - QString labelTransfer; - // revert some settings on old axis: - if (mColorAxis) - { - rangeTransfer = mColorAxis.data()->range(); - labelTransfer = mColorAxis.data()->label(); - logBaseTransfer = mColorAxis.data()->scaleLogBase(); - mColorAxis.data()->setLabel(QString()); - disconnect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); - disconnect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); - } - QList allAxisTypes = QList() << QCPAxis::atLeft << QCPAxis::atRight << QCPAxis::atBottom << QCPAxis::atTop; - foreach (QCPAxis::AxisType atype, allAxisTypes) + const int keySize = other.keySize(); + const int valueSize = other.valueSize(); + if (!other.mAlpha && mAlpha) + clearAlpha(); + setSize(keySize, valueSize); + if (other.mAlpha && !mAlpha) + createAlpha(false); + setRange(other.keyRange(), other.valueRange()); + if (!isEmpty()) { - mAxisRect.data()->axis(atype)->setTicks(atype == mType); - mAxisRect.data()->axis(atype)->setTickLabels(atype== mType); + memcpy(mData, other.mData, sizeof(mData[0])*size_t(keySize*valueSize)); + if (mAlpha) + memcpy(mAlpha, other.mAlpha, sizeof(mAlpha[0])*size_t(keySize*valueSize)); } - // set new mColorAxis pointer: - mColorAxis = mAxisRect.data()->axis(mType); - // transfer settings to new axis: - mColorAxis.data()->setRange(rangeTransfer); // transfer range of old axis to new one (necessary if axis changes from vertical to horizontal or vice versa) - mColorAxis.data()->setLabel(labelTransfer); - mColorAxis.data()->setScaleLogBase(logBaseTransfer); // scaleType is synchronized among axes in realtime via signals (connected in QCPColorScale ctor), so we only need to take care of log base here - connect(mColorAxis.data(), SIGNAL(rangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); - connect(mColorAxis.data(), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); - mAxisRect.data()->setRangeDragAxes(QCPAxis::orientation(mType) == Qt::Horizontal ? mColorAxis.data() : 0, - QCPAxis::orientation(mType) == Qt::Vertical ? mColorAxis.data() : 0); + mDataBounds = other.mDataBounds; + mDataModified = true; } + return *this; +} + +/* undocumented getter */ +double QCPColorMapData::data(double key, double value) +{ + int keyCell = int( (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5 ); + int valueCell = int( (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5 ); + if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize) + return mData[valueCell*mKeySize + keyCell]; + else + return 0; +} + +/* undocumented getter */ +double QCPColorMapData::cell(int keyIndex, int valueIndex) +{ + if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize) + return mData[valueIndex*mKeySize + keyIndex]; + else + return 0; } /*! - Sets the range spanned by the color gradient and that is shown by the axis in the color scale. - - It is equivalent to calling QCPColorMap::setDataRange on any of the connected color maps. It is - also equivalent to directly accessing the \ref axis and setting its range with \ref - QCPAxis::setRange. - - \see setDataScaleType, setGradient, rescaleDataRange + Returns the alpha map value of the cell with the indices \a keyIndex and \a valueIndex. + + If this color map data doesn't have an alpha map (because \ref setAlpha was never called after + creation or after a call to \ref clearAlpha), returns 255, which corresponds to full opacity. + + \see setAlpha */ -void QCPColorScale::setDataRange(const QCPRange &dataRange) +unsigned char QCPColorMapData::alpha(int keyIndex, int valueIndex) { - if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper) - { - mDataRange = dataRange; - if (mColorAxis) - mColorAxis.data()->setRange(mDataRange); - emit dataRangeChanged(mDataRange); - } + if (mAlpha && keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize) + return mAlpha[valueIndex*mKeySize + keyIndex]; + else + return 255; } /*! - Sets the scale type of the color scale, i.e. whether values are linearly associated with colors - or logarithmically. - - It is equivalent to calling QCPColorMap::setDataScaleType on any of the connected color maps. It is - also equivalent to directly accessing the \ref axis and setting its scale type with \ref - QCPAxis::setScaleType. + Resizes the data array to have \a keySize cells in the key dimension and \a valueSize cells in + the value dimension. + + The current data is discarded and the map cells are set to 0, unless the map had already the + requested size. - \see setDataRange, setGradient + Setting at least one of \a keySize or \a valueSize to zero frees the internal data array and \ref + isEmpty returns true. + + \see setRange, setKeySize, setValueSize */ -void QCPColorScale::setDataScaleType(QCPAxis::ScaleType scaleType) +void QCPColorMapData::setSize(int keySize, int valueSize) { - if (mDataScaleType != scaleType) + if (keySize != mKeySize || valueSize != mValueSize) { - mDataScaleType = scaleType; - if (mColorAxis) - mColorAxis.data()->setScaleType(mDataScaleType); - if (mDataScaleType == QCPAxis::stLogarithmic) - setDataRange(mDataRange.sanitizedForLogScale()); - emit dataScaleTypeChanged(mDataScaleType); + mKeySize = keySize; + mValueSize = valueSize; + delete[] mData; + mIsEmpty = mKeySize == 0 || mValueSize == 0; + if (!mIsEmpty) + { +#ifdef __EXCEPTIONS + try { // 2D arrays get memory intensive fast. So if the allocation fails, at least output debug message +#endif + mData = new double[size_t(mKeySize*mValueSize)]; +#ifdef __EXCEPTIONS + } catch (...) { mData = nullptr; } +#endif + if (mData) + fill(0); + else + qDebug() << Q_FUNC_INFO << "out of memory for data dimensions "<< mKeySize << "*" << mValueSize; + } else + mData = nullptr; + + if (mAlpha) // if we had an alpha map, recreate it with new size + createAlpha(); + + mDataModified = true; } } /*! - Sets the color gradient that will be used to represent data values. - - It is equivalent to calling QCPColorMap::setGradient on any of the connected color maps. + Resizes the data array to have \a keySize cells in the key dimension. + + The current data is discarded and the map cells are set to 0, unless the map had already the + requested size. - \see setDataRange, setDataScaleType + Setting \a keySize to zero frees the internal data array and \ref isEmpty returns true. + + \see setKeyRange, setSize, setValueSize */ -void QCPColorScale::setGradient(const QCPColorGradient &gradient) +void QCPColorMapData::setKeySize(int keySize) { - if (mGradient != gradient) - { - mGradient = gradient; - if (mAxisRect) - mAxisRect.data()->mGradientImageInvalidated = true; - emit gradientChanged(mGradient); - } + setSize(keySize, mValueSize); } /*! - Sets the axis label of the color scale. This is equivalent to calling \ref QCPAxis::setLabel on - the internal \ref axis. + Resizes the data array to have \a valueSize cells in the value dimension. + + The current data is discarded and the map cells are set to 0, unless the map had already the + requested size. + + Setting \a valueSize to zero frees the internal data array and \ref isEmpty returns true. + + \see setValueRange, setSize, setKeySize */ -void QCPColorScale::setLabel(const QString &str) +void QCPColorMapData::setValueSize(int valueSize) { - if (!mColorAxis) - { - qDebug() << Q_FUNC_INFO << "internal color axis undefined"; - return; - } - - mColorAxis.data()->setLabel(str); + setSize(mKeySize, valueSize); } /*! - Sets the width (or height, for horizontal color scales) the bar where the gradient is displayed - will have. + Sets the coordinate ranges the data shall be distributed over. This defines the rectangular area + covered by the color map in plot coordinates. + + The outer cells will be centered on the range boundaries given to this function. For example, if + the key size (\ref setKeySize) is 3 and \a keyRange is set to QCPRange(2, 3) there will + be cells centered on the key coordinates 2, 2.5 and 3. + + \see setSize */ -void QCPColorScale::setBarWidth(int width) +void QCPColorMapData::setRange(const QCPRange &keyRange, const QCPRange &valueRange) { - mBarWidth = width; + setKeyRange(keyRange); + setValueRange(valueRange); } /*! - Sets whether the user can drag the data range (\ref setDataRange). + Sets the coordinate range the data shall be distributed over in the key dimension. Together with + the value range, This defines the rectangular area covered by the color map in plot coordinates. - Note that \ref QCP::iRangeDrag must be in the QCustomPlot's interactions (\ref - QCustomPlot::setInteractions) to allow range dragging. + The outer cells will be centered on the range boundaries given to this function. For example, if + the key size (\ref setKeySize) is 3 and \a keyRange is set to QCPRange(2, 3) there will + be cells centered on the key coordinates 2, 2.5 and 3. + + \see setRange, setValueRange, setSize */ -void QCPColorScale::setRangeDrag(bool enabled) +void QCPColorMapData::setKeyRange(const QCPRange &keyRange) { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; - } - - if (enabled) - mAxisRect.data()->setRangeDrag(QCPAxis::orientation(mType)); - else - mAxisRect.data()->setRangeDrag(0); + mKeyRange = keyRange; } /*! - Sets whether the user can zoom the data range (\ref setDataRange) by scrolling the mouse wheel. + Sets the coordinate range the data shall be distributed over in the value dimension. Together with + the key range, This defines the rectangular area covered by the color map in plot coordinates. - Note that \ref QCP::iRangeZoom must be in the QCustomPlot's interactions (\ref - QCustomPlot::setInteractions) to allow range dragging. + The outer cells will be centered on the range boundaries given to this function. For example, if + the value size (\ref setValueSize) is 3 and \a valueRange is set to QCPRange(2, 3) there + will be cells centered on the value coordinates 2, 2.5 and 3. + + \see setRange, setKeyRange, setSize */ -void QCPColorScale::setRangeZoom(bool enabled) +void QCPColorMapData::setValueRange(const QCPRange &valueRange) { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; - } - - if (enabled) - mAxisRect.data()->setRangeZoom(QCPAxis::orientation(mType)); - else - mAxisRect.data()->setRangeZoom(0); + mValueRange = valueRange; } /*! - Returns a list of all the color maps associated with this color scale. + Sets the data of the cell, which lies at the plot coordinates given by \a key and \a value, to \a + z. + + \note The QCPColorMap always displays the data at equal key/value intervals, even if the key or + value axis is set to a logarithmic scaling. If you want to use QCPColorMap with logarithmic axes, + you shouldn't use the \ref QCPColorMapData::setData method as it uses a linear transformation to + determine the cell index. Rather directly access the cell index with \ref + QCPColorMapData::setCell. + + \see setCell, setRange */ -QList QCPColorScale::colorMaps() const +void QCPColorMapData::setData(double key, double value, double z) { - QList result; - for (int i=0; iplottableCount(); ++i) + int keyCell = int( (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5 ); + int valueCell = int( (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5 ); + if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize) { - if (QCPColorMap *cm = qobject_cast(mParentPlot->plottable(i))) - if (cm->colorScale() == this) - result.append(cm); + mData[valueCell*mKeySize + keyCell] = z; + if (z < mDataBounds.lower) + mDataBounds.lower = z; + if (z > mDataBounds.upper) + mDataBounds.upper = z; + mDataModified = true; } - return result; } /*! - Changes the data range such that all color maps associated with this color scale are fully mapped - to the gradient in the data dimension. + Sets the data of the cell with indices \a keyIndex and \a valueIndex to \a z. The indices + enumerate the cells starting from zero, up to the map's size-1 in the respective dimension (see + \ref setSize). - \see setDataRange + In the standard plot configuration (horizontal key axis and vertical value axis, both not + range-reversed), the cell with indices (0, 0) is in the bottom left corner and the cell with + indices (keySize-1, valueSize-1) is in the top right corner of the color map. + + \see setData, setSize */ -void QCPColorScale::rescaleDataRange(bool onlyVisibleMaps) +void QCPColorMapData::setCell(int keyIndex, int valueIndex, double z) { - QList maps = colorMaps(); - QCPRange newRange; - bool haveRange = false; - int sign = 0; // TODO: should change this to QCPAbstractPlottable::SignDomain later (currently is protected, maybe move to QCP namespace) - if (mDataScaleType == QCPAxis::stLogarithmic) - sign = (mDataRange.upper < 0 ? -1 : 1); - for (int i=0; i= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize) { - if (!maps.at(i)->realVisibility() && onlyVisibleMaps) - continue; - QCPRange mapRange; - if (maps.at(i)->colorScale() == this) - { - bool currentFoundRange = true; - mapRange = maps.at(i)->data()->dataBounds(); - if (sign == 1) - { - if (mapRange.lower <= 0 && mapRange.upper > 0) - mapRange.lower = mapRange.upper*1e-3; - else if (mapRange.lower <= 0 && mapRange.upper <= 0) - currentFoundRange = false; - } else if (sign == -1) - { - if (mapRange.upper >= 0 && mapRange.lower < 0) - mapRange.upper = mapRange.lower*1e-3; - else if (mapRange.upper >= 0 && mapRange.lower >= 0) - currentFoundRange = false; - } - if (currentFoundRange) - { - if (!haveRange) - newRange = mapRange; - else - newRange.expand(mapRange); - haveRange = true; - } - } - } - if (haveRange) + mData[valueIndex*mKeySize + keyIndex] = z; + if (z < mDataBounds.lower) + mDataBounds.lower = z; + if (z > mDataBounds.upper) + mDataBounds.upper = z; + mDataModified = true; + } else + qDebug() << Q_FUNC_INFO << "index out of bounds:" << keyIndex << valueIndex; +} + +/*! + Sets the alpha of the color map cell given by \a keyIndex and \a valueIndex to \a alpha. A value + of 0 for \a alpha results in a fully transparent cell, and a value of 255 results in a fully + opaque cell. + + If an alpha map doesn't exist yet for this color map data, it will be created here. If you wish + to restore full opacity and free any allocated memory of the alpha map, call \ref clearAlpha. + + Note that the cell-wise alpha which can be configured here is independent of any alpha configured + in the color map's gradient (\ref QCPColorGradient). If a cell is affected both by the cell-wise + and gradient alpha, the alpha values will be blended accordingly during rendering of the color + map. + + \see fillAlpha, clearAlpha +*/ +void QCPColorMapData::setAlpha(int keyIndex, int valueIndex, unsigned char alpha) +{ + if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize) { - if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this dimension), shift current range to at least center the data + if (mAlpha || createAlpha()) { - double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason - if (mDataScaleType == QCPAxis::stLinear) - { - newRange.lower = center-mDataRange.size()/2.0; - newRange.upper = center+mDataRange.size()/2.0; - } else // mScaleType == stLogarithmic - { - newRange.lower = center/qSqrt(mDataRange.upper/mDataRange.lower); - newRange.upper = center*qSqrt(mDataRange.upper/mDataRange.lower); - } + mAlpha[valueIndex*mKeySize + keyIndex] = alpha; + mDataModified = true; } - setDataRange(newRange); - } + } else + qDebug() << Q_FUNC_INFO << "index out of bounds:" << keyIndex << valueIndex; } -/* inherits documentation from base class */ -void QCPColorScale::update(UpdatePhase phase) -{ - QCPLayoutElement::update(phase); - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; - } +/*! + Goes through the data and updates the buffered minimum and maximum data values. - mAxisRect.data()->update(phase); + Calling this method is only advised if you are about to call \ref QCPColorMap::rescaleDataRange + and can not guarantee that the cells holding the maximum or minimum data haven't been overwritten + with a smaller or larger value respectively, since the buffered maximum/minimum values have been + updated the last time. Why this is the case is explained in the class description (\ref + QCPColorMapData). - switch (phase) + Note that the method \ref QCPColorMap::rescaleDataRange provides a parameter \a + recalculateDataBounds for convenience. Setting this to true will call this method for you, before + doing the rescale. +*/ +void QCPColorMapData::recalculateDataBounds() +{ + if (mKeySize > 0 && mValueSize > 0) { - case upMargins: - { - if (mType == QCPAxis::atBottom || mType == QCPAxis::atTop) - { - setMaximumSize(QWIDGETSIZE_MAX, mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom()+margins().top()+margins().bottom()); - setMinimumSize(0, mBarWidth+mAxisRect.data()->margins().top()+mAxisRect.data()->margins().bottom()+margins().top()+margins().bottom()); - } else - { - setMaximumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right()+margins().left()+margins().right(), QWIDGETSIZE_MAX); - setMinimumSize(mBarWidth+mAxisRect.data()->margins().left()+mAxisRect.data()->margins().right()+margins().left()+margins().right(), 0); - } - break; - } - case upLayout: + double minHeight = std::numeric_limits::max(); + double maxHeight = -std::numeric_limits::max(); + const int dataCount = mValueSize*mKeySize; + for (int i=0; isetOuterRect(rect()); - break; + if (mData[i] > maxHeight) + maxHeight = mData[i]; + if (mData[i] < minHeight) + minHeight = mData[i]; } - default: break; + mDataBounds.lower = minHeight; + mDataBounds.upper = maxHeight; } } -/* inherits documentation from base class */ -void QCPColorScale::applyDefaultAntialiasingHint(QCPPainter *painter) const +/*! + Frees the internal data memory. + + This is equivalent to calling \ref setSize "setSize(0, 0)". +*/ +void QCPColorMapData::clear() { - painter->setAntialiasing(false); + setSize(0, 0); } -/* inherits documentation from base class */ -void QCPColorScale::mousePressEvent(QMouseEvent *event) +/*! + Frees the internal alpha map. The color map will have full opacity again. +*/ +void QCPColorMapData::clearAlpha() { - if (!mAxisRect) + if (mAlpha) { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; + delete[] mAlpha; + mAlpha = nullptr; + mDataModified = true; } - mAxisRect.data()->mousePressEvent(event); } -/* inherits documentation from base class */ -void QCPColorScale::mouseMoveEvent(QMouseEvent *event) +/*! + Sets all cells to the value \a z. +*/ +void QCPColorMapData::fill(double z) { - if (!mAxisRect) - { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; - } - mAxisRect.data()->mouseMoveEvent(event); + const int dataCount = mValueSize*mKeySize; + memset(mData, z, dataCount*sizeof(*mData)); + mDataBounds = QCPRange(z, z); + mDataModified = true; } -/* inherits documentation from base class */ -void QCPColorScale::mouseReleaseEvent(QMouseEvent *event) +/*! + Sets the opacity of all color map cells to \a alpha. A value of 0 for \a alpha results in a fully + transparent color map, and a value of 255 results in a fully opaque color map. + + If you wish to restore opacity to 100% and free any used memory for the alpha map, rather use + \ref clearAlpha. + + \see setAlpha +*/ +void QCPColorMapData::fillAlpha(unsigned char alpha) { - if (!mAxisRect) + if (mAlpha || createAlpha(false)) { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; + const int dataCount = mValueSize*mKeySize; + memset(mAlpha, alpha, dataCount*sizeof(*mAlpha)); + mDataModified = true; } - mAxisRect.data()->mouseReleaseEvent(event); } -/* inherits documentation from base class */ -void QCPColorScale::wheelEvent(QWheelEvent *event) +/*! + Transforms plot coordinates given by \a key and \a value to cell indices of this QCPColorMapData + instance. The resulting cell indices are returned via the output parameters \a keyIndex and \a + valueIndex. + + The retrieved key/value cell indices can then be used for example with \ref setCell. + + If you are only interested in a key or value index, you may pass \c nullptr as \a valueIndex or + \a keyIndex. + + \note The QCPColorMap always displays the data at equal key/value intervals, even if the key or + value axis is set to a logarithmic scaling. If you want to use QCPColorMap with logarithmic axes, + you shouldn't use the \ref QCPColorMapData::coordToCell method as it uses a linear transformation to + determine the cell index. + + \see cellToCoord, QCPAxis::coordToPixel +*/ +void QCPColorMapData::coordToCell(double key, double value, int *keyIndex, int *valueIndex) const { - if (!mAxisRect) + if (keyIndex) + *keyIndex = int( (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5 ); + if (valueIndex) + *valueIndex = int( (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5 ); +} + +/*! + Transforms cell indices given by \a keyIndex and \a valueIndex to cell indices of this QCPColorMapData + instance. The resulting coordinates are returned via the output parameters \a key and \a + value. + + If you are only interested in a key or value coordinate, you may pass \c nullptr as \a key or \a + value. + + \note The QCPColorMap always displays the data at equal key/value intervals, even if the key or + value axis is set to a logarithmic scaling. If you want to use QCPColorMap with logarithmic axes, + you shouldn't use the \ref QCPColorMapData::cellToCoord method as it uses a linear transformation to + determine the cell index. + + \see coordToCell, QCPAxis::pixelToCoord +*/ +void QCPColorMapData::cellToCoord(int keyIndex, int valueIndex, double *key, double *value) const +{ + if (key) + *key = keyIndex/double(mKeySize-1)*(mKeyRange.upper-mKeyRange.lower)+mKeyRange.lower; + if (value) + *value = valueIndex/double(mValueSize-1)*(mValueRange.upper-mValueRange.lower)+mValueRange.lower; +} + +/*! \internal + + Allocates the internal alpha map with the current data map key/value size and, if \a + initializeOpaque is true, initializes all values to 255. If \a initializeOpaque is false, the + values are not initialized at all. In this case, the alpha map should be initialized manually, + e.g. with \ref fillAlpha. + + If an alpha map exists already, it is deleted first. If this color map is empty (has either key + or value size zero, see \ref isEmpty), the alpha map is cleared. + + The return value indicates the existence of the alpha map after the call. So this method returns + true if the data map isn't empty and an alpha map was successfully allocated. +*/ +bool QCPColorMapData::createAlpha(bool initializeOpaque) +{ + clearAlpha(); + if (isEmpty()) + return false; + +#ifdef __EXCEPTIONS + try { // 2D arrays get memory intensive fast. So if the allocation fails, at least output debug message +#endif + mAlpha = new unsigned char[size_t(mKeySize*mValueSize)]; +#ifdef __EXCEPTIONS + } catch (...) { mAlpha = nullptr; } +#endif + if (mAlpha) { - qDebug() << Q_FUNC_INFO << "internal axis rect was deleted"; - return; + if (initializeOpaque) + fillAlpha(255); + return true; + } else + { + qDebug() << Q_FUNC_INFO << "out of memory for data dimensions "<< mKeySize << "*" << mValueSize; + return false; } - mAxisRect.data()->wheelEvent(event); } + //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPColorScaleAxisRectPrivate +//////////////////// QCPColorMap //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPColorScaleAxisRectPrivate +/*! \class QCPColorMap + \brief A plottable representing a two-dimensional color map in a plot. - \internal - \brief An axis rect subclass for use in a QCPColorScale + \image html QCPColorMap.png - This is a private class and not part of the public QCustomPlot interface. + The data is stored in the class \ref QCPColorMapData, which can be accessed via the data() + method. - It provides the axis rect functionality for the QCPColorScale class. + A color map has three dimensions to represent a data point: The \a key dimension, the \a value + dimension and the \a data dimension. As with other plottables such as graphs, \a key and \a value + correspond to two orthogonal axes on the QCustomPlot surface that you specify in the QCPColorMap + constructor. The \a data dimension however is encoded as the color of the point at (\a key, \a + value). + + Set the number of points (or \a cells) in the key/value dimension via \ref + QCPColorMapData::setSize. The plot coordinate range over which these points will be displayed is + specified via \ref QCPColorMapData::setRange. The first cell will be centered on the lower range + boundary and the last cell will be centered on the upper range boundary. The data can be set by + either accessing the cells directly with QCPColorMapData::setCell or by addressing the cells via + their plot coordinates with \ref QCPColorMapData::setData. If possible, you should prefer + setCell, since it doesn't need to do any coordinate transformation and thus performs a bit + better. + + The cell with index (0, 0) is at the bottom left, if the color map uses normal (i.e. not reversed) + key and value axes. + + To show the user which colors correspond to which \a data values, a \ref QCPColorScale is + typically placed to the right of the axis rect. See the documentation there for details on how to + add and use a color scale. + + \section qcpcolormap-appearance Changing the appearance + + Most important to the appearance is the color gradient, which can be specified via \ref + setGradient. See the documentation of \ref QCPColorGradient for details on configuring a color + gradient. + + The \a data range that is mapped to the colors of the gradient can be specified with \ref + setDataRange. To make the data range encompass the whole data set minimum to maximum, call \ref + rescaleDataRange. If your data may contain NaN values, use \ref QCPColorGradient::setNanHandling + to define how they are displayed. + + \section qcpcolormap-transparency Transparency + + Transparency in color maps can be achieved by two mechanisms. On one hand, you can specify alpha + values for color stops of the \ref QCPColorGradient, via the regular QColor interface. This will + cause the color map data which gets mapped to colors around those color stops to appear with the + accordingly interpolated transparency. + + On the other hand you can also directly apply an alpha value to each cell independent of its + data, by using the alpha map feature of \ref QCPColorMapData. The relevant methods are \ref + QCPColorMapData::setAlpha, QCPColorMapData::fillAlpha and \ref QCPColorMapData::clearAlpha(). + + The two transparencies will be joined together in the plot and otherwise not interfere with each + other. They are mixed in a multiplicative matter, so an alpha of e.g. 50% (128/255) in both modes + simultaneously, will result in a total transparency of 25% (64/255). + + \section qcpcolormap-usage Usage + + Like all data representing objects in QCustomPlot, the QCPColorMap is a plottable + (QCPAbstractPlottable). So the plottable-interface of QCustomPlot applies + (QCustomPlot::plottable, QCustomPlot::removePlottable, etc.) + + Usually, you first create an instance: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcolormap-creation-1 + which registers it with the QCustomPlot instance of the passed axes. Note that this QCustomPlot instance takes + ownership of the plottable, so do not delete it manually but use QCustomPlot::removePlottable() instead. + The newly created plottable can be modified, e.g.: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcolormap-creation-2 + + \note The QCPColorMap always displays the data at equal key/value intervals, even if the key or + value axis is set to a logarithmic scaling. If you want to use QCPColorMap with logarithmic axes, + you shouldn't use the \ref QCPColorMapData::setData method as it uses a linear transformation to + determine the cell index. Rather directly access the cell index with \ref + QCPColorMapData::setCell. */ +/* start documentation of inline functions */ -/*! - Creates a new instance, as a child of \a parentColorScale. +/*! \fn QCPColorMapData *QCPColorMap::data() const + + Returns a pointer to the internal data storage of type \ref QCPColorMapData. Access this to + modify data points (cells) and the color map key/value range. + + \see setData */ -QCPColorScaleAxisRectPrivate::QCPColorScaleAxisRectPrivate(QCPColorScale *parentColorScale) : - QCPAxisRect(parentColorScale->parentPlot(), true), - mParentColorScale(parentColorScale), - mGradientImageInvalidated(true) -{ - setParentLayerable(parentColorScale); - setMinimumMargins(QMargins(0, 0, 0, 0)); - QList allAxisTypes = QList() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight; - foreach (QCPAxis::AxisType type, allAxisTypes) - { - axis(type)->setVisible(true); - axis(type)->grid()->setVisible(false); - axis(type)->setPadding(0); - connect(axis(type), SIGNAL(selectionChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectionChanged(QCPAxis::SelectableParts))); - connect(axis(type), SIGNAL(selectableChanged(QCPAxis::SelectableParts)), this, SLOT(axisSelectableChanged(QCPAxis::SelectableParts))); - } - connect(axis(QCPAxis::atLeft), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atRight), SLOT(setRange(QCPRange))); - connect(axis(QCPAxis::atRight), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atLeft), SLOT(setRange(QCPRange))); - connect(axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atTop), SLOT(setRange(QCPRange))); - connect(axis(QCPAxis::atTop), SIGNAL(rangeChanged(QCPRange)), axis(QCPAxis::atBottom), SLOT(setRange(QCPRange))); - connect(axis(QCPAxis::atLeft), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atRight), SLOT(setScaleType(QCPAxis::ScaleType))); - connect(axis(QCPAxis::atRight), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atLeft), SLOT(setScaleType(QCPAxis::ScaleType))); - connect(axis(QCPAxis::atBottom), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atTop), SLOT(setScaleType(QCPAxis::ScaleType))); - connect(axis(QCPAxis::atTop), SIGNAL(scaleTypeChanged(QCPAxis::ScaleType)), axis(QCPAxis::atBottom), SLOT(setScaleType(QCPAxis::ScaleType))); +/* end documentation of inline functions */ + +/* start documentation of signals */ + +/*! \fn void QCPColorMap::dataRangeChanged(const QCPRange &newRange); - // make layer transfers of color scale transfer to axis rect and axes - // the axes must be set after axis rect, such that they appear above color gradient drawn by axis rect: - connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), this, SLOT(setLayer(QCPLayer*))); - foreach (QCPAxis::AxisType type, allAxisTypes) - connect(parentColorScale, SIGNAL(layerChanged(QCPLayer*)), axis(type), SLOT(setLayer(QCPLayer*))); -} + This signal is emitted when the data range changes. + + \see setDataRange +*/ -/*! \internal - Updates the color gradient image if necessary, by calling \ref updateGradientImage, then draws - it. Then the axes are drawn by calling the \ref QCPAxisRect::draw base class implementation. +/*! \fn void QCPColorMap::dataScaleTypeChanged(QCPAxis::ScaleType scaleType); + + This signal is emitted when the data scale type changes. + + \see setDataScaleType */ -void QCPColorScaleAxisRectPrivate::draw(QCPPainter *painter) -{ - if (mGradientImageInvalidated) - updateGradientImage(); + +/*! \fn void QCPColorMap::gradientChanged(const QCPColorGradient &newGradient); - bool mirrorHorz = false; - bool mirrorVert = false; - if (mParentColorScale->mColorAxis) - { - mirrorHorz = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atBottom || mParentColorScale->type() == QCPAxis::atTop); - mirrorVert = mParentColorScale->mColorAxis.data()->rangeReversed() && (mParentColorScale->type() == QCPAxis::atLeft || mParentColorScale->type() == QCPAxis::atRight); - } + This signal is emitted when the gradient changes. - painter->drawImage(rect().adjusted(0, -1, 0, -1), mGradientImage.mirrored(mirrorHorz, mirrorVert)); - QCPAxisRect::draw(painter); + \see setGradient +*/ + +/* end documentation of signals */ + +/*! + Constructs a color map with the specified \a keyAxis and \a valueAxis. + + The created QCPColorMap is automatically registered with the QCustomPlot instance inferred from + \a keyAxis. This QCustomPlot instance takes ownership of the QCPColorMap, so do not delete it + manually but use QCustomPlot::removePlottable() instead. +*/ +QCPColorMap::QCPColorMap(QCPAxis *keyAxis, QCPAxis *valueAxis) : + QCPAbstractPlottable(keyAxis, valueAxis), + mDataScaleType(QCPAxis::stLinear), + mMapData(new QCPColorMapData(10, 10, QCPRange(0, 5), QCPRange(0, 5))), + mGradient(QCPColorGradient::gpCold), + mInterpolate(true), + mTightBoundary(false), + mMapImageInvalidated(true) +{ } -/*! \internal +QCPColorMap::~QCPColorMap() +{ + delete mMapData; +} - Uses the current gradient of the parent \ref QCPColorScale (specified in the constructor) to - generate a gradient image. This gradient image will be used in the \ref draw method. +/*! + Replaces the current \ref data with the provided \a data. + + If \a copy is set to true, the \a data object will only be copied. if false, the color map + takes ownership of the passed data and replaces the internal data pointer with it. This is + significantly faster than copying for large datasets. */ -void QCPColorScaleAxisRectPrivate::updateGradientImage() +void QCPColorMap::setData(QCPColorMapData *data, bool copy) { - if (rect().isEmpty()) + if (mMapData == data) + { + qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); return; - - int n = mParentColorScale->mGradient.levelCount(); - int w, h; - QVector data(n); - for (int i=0; imType == QCPAxis::atBottom || mParentColorScale->mType == QCPAxis::atTop) + } + if (copy) { - w = n; - h = rect().height(); - mGradientImage = QImage(w, h, QImage::Format_RGB32); - QVector pixels; - for (int y=0; y(mGradientImage.scanLine(y))); - mParentColorScale->mGradient.colorize(data.constData(), QCPRange(0, n-1), pixels.first(), n); - for (int y=1; y(mGradientImage.scanLine(y)); - const QRgb lineColor = mParentColorScale->mGradient.color(data[h-1-y], QCPRange(0, n-1)); - for (int x=0; x allAxisTypes = QList() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight; - foreach (QCPAxis::AxisType type, allAxisTypes) + if (!QCPRange::validRange(dataRange)) return; + if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper) { - if (QCPAxis *senderAxis = qobject_cast(sender())) - if (senderAxis->axisType() == type) - continue; - - if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis)) - { - if (selectedParts.testFlag(QCPAxis::spAxis)) - axis(type)->setSelectedParts(axis(type)->selectedParts() | QCPAxis::spAxis); - else - axis(type)->setSelectedParts(axis(type)->selectedParts() & ~QCPAxis::spAxis); - } + if (mDataScaleType == QCPAxis::stLogarithmic) + mDataRange = dataRange.sanitizedForLogScale(); + else + mDataRange = dataRange.sanitizedForLinScale(); + mMapImageInvalidated = true; + emit dataRangeChanged(mDataRange); } } -/*! \internal - - This slot is connected to the selectableChanged signals of the four axes in the constructor. It - synchronizes the selectability of the axes. +/*! + Sets whether the data is correlated with the color gradient linearly or logarithmically. + + \see QCPColorScale::setDataScaleType */ -void QCPColorScaleAxisRectPrivate::axisSelectableChanged(QCPAxis::SelectableParts selectableParts) +void QCPColorMap::setDataScaleType(QCPAxis::ScaleType scaleType) { - // synchronize axis base selectability: - QList allAxisTypes = QList() << QCPAxis::atBottom << QCPAxis::atTop << QCPAxis::atLeft << QCPAxis::atRight; - foreach (QCPAxis::AxisType type, allAxisTypes) + if (mDataScaleType != scaleType) { - if (QCPAxis *senderAxis = qobject_cast(sender())) - if (senderAxis->axisType() == type) - continue; - - if (axis(type)->selectableParts().testFlag(QCPAxis::spAxis)) - { - if (selectableParts.testFlag(QCPAxis::spAxis)) - axis(type)->setSelectableParts(axis(type)->selectableParts() | QCPAxis::spAxis); - else - axis(type)->setSelectableParts(axis(type)->selectableParts() & ~QCPAxis::spAxis); - } + mDataScaleType = scaleType; + mMapImageInvalidated = true; + emit dataScaleTypeChanged(mDataScaleType); + if (mDataScaleType == QCPAxis::stLogarithmic) + setDataRange(mDataRange.sanitizedForLogScale()); } } - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPData -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPData - \brief Holds the data of one single data point for QCPGraph. - - The container for storing multiple data points is \ref QCPDataMap. +/*! + Sets the color gradient that is used to represent the data. For more details on how to create an + own gradient or use one of the preset gradients, see \ref QCPColorGradient. - The stored data is: - \li \a key: coordinate on the key axis of this data point - \li \a value: coordinate on the value axis of this data point - \li \a keyErrorMinus: negative error in the key dimension (for error bars) - \li \a keyErrorPlus: positive error in the key dimension (for error bars) - \li \a valueErrorMinus: negative error in the value dimension (for error bars) - \li \a valueErrorPlus: positive error in the value dimension (for error bars) + The colors defined by the gradient will be used to represent data values in the currently set + data range, see \ref setDataRange. Data points that are outside this data range will either be + colored uniformly with the respective gradient boundary color, or the gradient will repeat, + depending on \ref QCPColorGradient::setPeriodic. - \see QCPDataMap + \see QCPColorScale::setGradient */ +void QCPColorMap::setGradient(const QCPColorGradient &gradient) +{ + if (mGradient != gradient) + { + mGradient = gradient; + mMapImageInvalidated = true; + emit gradientChanged(mGradient); + } +} /*! - Constructs a data point with key, value and all errors set to zero. + Sets whether the color map image shall use bicubic interpolation when displaying the color map + shrinked or expanded, and not at a 1:1 pixel-to-data scale. + + \image html QCPColorMap-interpolate.png "A 10*10 color map, with interpolation and without interpolation enabled" */ -QCPData::QCPData() : - key(0), - value(0), - keyErrorPlus(0), - keyErrorMinus(0), - valueErrorPlus(0), - valueErrorMinus(0) +void QCPColorMap::setInterpolate(bool enabled) { + mInterpolate = enabled; + mMapImageInvalidated = true; // because oversampling factors might need to change } /*! - Constructs a data point with the specified \a key and \a value. All errors are set to zero. + Sets whether the outer most data rows and columns are clipped to the specified key and value + range (see \ref QCPColorMapData::setKeyRange, \ref QCPColorMapData::setValueRange). + + if \a enabled is set to false, the data points at the border of the color map are drawn with the + same width and height as all other data points. Since the data points are represented by + rectangles of one color centered on the data coordinate, this means that the shown color map + extends by half a data point over the specified key/value range in each direction. + + \image html QCPColorMap-tightboundary.png "A color map, with tight boundary enabled and disabled" */ -QCPData::QCPData(double key, double value) : - key(key), - value(value), - keyErrorPlus(0), - keyErrorMinus(0), - valueErrorPlus(0), - valueErrorMinus(0) +void QCPColorMap::setTightBoundary(bool enabled) { + mTightBoundary = enabled; } - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPGraph -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPGraph - \brief A plottable representing a graph in a plot. - - \image html QCPGraph.png - - Usually QCustomPlot creates graphs internally via QCustomPlot::addGraph and the resulting - instance is accessed via QCustomPlot::graph. - - To plot data, assign it with the \ref setData or \ref addData functions. Alternatively, you can - also access and modify the graph's data via the \ref data method, which returns a pointer to the - internal \ref QCPDataMap. - - Graphs are used to display single-valued data. Single-valued means that there should only be one - data point per unique key coordinate. In other words, the graph can't have \a loops. If you do - want to plot non-single-valued curves, rather use the QCPCurve plottable. - - Gaps in the graph line can be created by adding data points with NaN as value - (qQNaN() or std::numeric_limits::quiet_NaN()) in between the two data points that shall be - separated. - - \section appearance Changing the appearance - - The appearance of the graph is mainly determined by the line style, scatter style, brush and pen - of the graph (\ref setLineStyle, \ref setScatterStyle, \ref setBrush, \ref setPen). - - \subsection filling Filling under or between graphs +/*! + Associates the color scale \a colorScale with this color map. - QCPGraph knows two types of fills: Normal graph fills towards the zero-value-line parallel to - the key axis of the graph, and fills between two graphs, called channel fills. To enable a fill, - just set a brush with \ref setBrush which is neither Qt::NoBrush nor fully transparent. + This means that both the color scale and the color map synchronize their gradient, data range and + data scale type (\ref setGradient, \ref setDataRange, \ref setDataScaleType). Multiple color maps + can be associated with one single color scale. This causes the color maps to also synchronize + those properties, via the mutual color scale. - By default, a normal fill towards the zero-value-line will be drawn. To set up a channel fill - between this graph and another one, call \ref setChannelFillGraph with the other graph as - parameter. - - \see QCustomPlot::addGraph, QCustomPlot::graph -*/ - -/* start of documentation of inline functions */ - -/*! \fn QCPDataMap *QCPGraph::data() const + This function causes the color map to adopt the current color gradient, data range and data scale + type of \a colorScale. After this call, you may change these properties at either the color map + or the color scale, and the setting will be applied to both. - Returns a pointer to the internal data storage of type \ref QCPDataMap. You may use it to - directly manipulate the data, which may be more convenient and faster than using the regular \ref - setData or \ref addData methods, in certain situations. + Pass \c nullptr as \a colorScale to disconnect the color scale from this color map again. */ - -/* end of documentation of inline functions */ +void QCPColorMap::setColorScale(QCPColorScale *colorScale) +{ + if (mColorScale) // unconnect signals from old color scale + { + disconnect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange))); + disconnect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType))); + disconnect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient))); + disconnect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); + disconnect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient))); + disconnect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); + } + mColorScale = colorScale; + if (mColorScale) // connect signals to new color scale + { + setGradient(mColorScale.data()->gradient()); + setDataRange(mColorScale.data()->dataRange()); + setDataScaleType(mColorScale.data()->dataScaleType()); + connect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange))); + connect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType))); + connect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient))); + connect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); + connect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient))); + connect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); + } +} /*! - Constructs a graph which uses \a keyAxis as its key axis ("x") and \a valueAxis as its value - axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and not have - the same orientation. If either of these restrictions is violated, a corresponding message is - printed to the debug output (qDebug), the construction is not aborted, though. + Sets the data range (\ref setDataRange) to span the minimum and maximum values that occur in the + current data set. This corresponds to the \ref rescaleKeyAxis or \ref rescaleValueAxis methods, + only for the third data dimension of the color map. - The constructed QCPGraph can be added to the plot with QCustomPlot::addPlottable, QCustomPlot - then takes ownership of the graph. + The minimum and maximum values of the data set are buffered in the internal QCPColorMapData + instance (\ref data). As data is updated via its \ref QCPColorMapData::setCell or \ref + QCPColorMapData::setData, the buffered minimum and maximum values are updated, too. For + performance reasons, however, they are only updated in an expanding fashion. So the buffered + maximum can only increase and the buffered minimum can only decrease. In consequence, changes to + the data that actually lower the maximum of the data set (by overwriting the cell holding the + current maximum with a smaller value), aren't recognized and the buffered maximum overestimates + the true maximum of the data set. The same happens for the buffered minimum. To recalculate the + true minimum and maximum by explicitly looking at each cell, the method + QCPColorMapData::recalculateDataBounds can be used. For convenience, setting the parameter \a + recalculateDataBounds calls this method before setting the data range to the buffered minimum and + maximum. - To directly create a graph inside a plot, you can also use the simpler QCustomPlot::addGraph function. + \see setDataRange */ -QCPGraph::QCPGraph(QCPAxis *keyAxis, QCPAxis *valueAxis) : - QCPAbstractPlottable(keyAxis, valueAxis) -{ - mData = new QCPDataMap; - - setPen(QPen(Qt::blue, 0)); - setErrorPen(QPen(Qt::black)); - setBrush(Qt::NoBrush); - setSelectedPen(QPen(QColor(80, 80, 255), 2.5)); - setSelectedBrush(Qt::NoBrush); - - setLineStyle(lsLine); - setErrorType(etNone); - setErrorBarSize(6); - setErrorBarSkipSymbol(true); - setChannelFillGraph(0); - setAdaptiveSampling(true); -} - -QCPGraph::~QCPGraph() +void QCPColorMap::rescaleDataRange(bool recalculateDataBounds) { - delete mData; + if (recalculateDataBounds) + mMapData->recalculateDataBounds(); + setDataRange(mMapData->dataBounds()); } /*! - Replaces the current data with the provided \a data. + Takes the current appearance of the color map and updates the legend icon, which is used to + represent this color map in the legend (see \ref QCPLegend). - If \a copy is set to true, data points in \a data will only be copied. if false, the graph - takes ownership of the passed data and replaces the internal data pointer with it. This is - significantly faster than copying for large datasets. + The \a transformMode specifies whether the rescaling is done by a faster, low quality image + scaling algorithm (Qt::FastTransformation) or by a slower, higher quality algorithm + (Qt::SmoothTransformation). + + The current color map appearance is scaled down to \a thumbSize. Ideally, this should be equal to + the size of the legend icon (see \ref QCPLegend::setIconSize). If it isn't exactly the configured + legend icon size, the thumb will be rescaled during drawing of the legend item. - Alternatively, you can also access and modify the graph's data via the \ref data method, which - returns a pointer to the internal \ref QCPDataMap. + \see setDataRange */ -void QCPGraph::setData(QCPDataMap *data, bool copy) +void QCPColorMap::updateLegendIcon(Qt::TransformationMode transformMode, const QSize &thumbSize) { - if (mData == data) + if (mMapImage.isNull() && !data()->isEmpty()) + updateMapImage(); // try to update map image if it's null (happens if no draw has happened yet) + + if (!mMapImage.isNull()) // might still be null, e.g. if data is empty, so check here again { - qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); - return; + bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed(); + bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed(); + mLegendIcon = QPixmap::fromImage(mMapImage.mirrored(mirrorX, mirrorY)).scaled(thumbSize, Qt::KeepAspectRatio, transformMode); } - if (copy) - { - *mData = *data; - } else +} + +/* inherits documentation from base class */ +double QCPColorMap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +{ + Q_UNUSED(details) + if ((onlySelectable && mSelectable == QCP::stNone) || mMapData->isEmpty()) + return -1; + if (!mKeyAxis || !mValueAxis) + return -1; + + if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect)) { - delete mData; - mData = data; + double posKey, posValue; + pixelsToCoords(pos, posKey, posValue); + if (mMapData->keyRange().contains(posKey) && mMapData->valueRange().contains(posValue)) + { + if (details) + details->setValue(QCPDataSelection(QCPDataRange(0, 1))); // temporary solution, to facilitate whole-plottable selection. Replace in future version with segmented 2D selection. + return mParentPlot->selectionTolerance()*0.99; + } } + return -1; } -/*! \overload - - Replaces the current data with the provided points in \a key and \a value pairs. The provided - vectors should have equal length. Else, the number of added points will be the size of the - smallest vector. -*/ -void QCPGraph::setData(const QVector &key, const QVector &value) +/* inherits documentation from base class */ +QCPRange QCPColorMap::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - QCPData newData; - for (int i=0; ikeyRange(); + result.normalize(); + if (inSignDomain == QCP::sdPositive) + { + if (result.lower <= 0 && result.upper > 0) + result.lower = result.upper*1e-3; + else if (result.lower <= 0 && result.upper <= 0) + foundRange = false; + } else if (inSignDomain == QCP::sdNegative) { - newData.key = key[i]; - newData.value = value[i]; - mData->insertMulti(newData.key, newData); + if (result.upper >= 0 && result.lower < 0) + result.upper = result.lower*1e-3; + else if (result.upper >= 0 && result.lower >= 0) + foundRange = false; } + return result; } -/*! - Replaces the current data with the provided points in \a key and \a value pairs. Additionally the - symmetrical value error of the data points are set to the values in \a valueError. - For error bars to show appropriately, see \ref setErrorType. - The provided vectors should have equal length. Else, the number of added points will be the size of the - smallest vector. - - For asymmetrical errors (plus different from minus), see the overloaded version of this function. -*/ -void QCPGraph::setDataValueError(const QVector &key, const QVector &value, const QVector &valueError) +/* inherits documentation from base class */ +QCPRange QCPColorMap::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - n = qMin(n, valueError.size()); - QCPData newData; - for (int i=0; ikeyRange().upper < inKeyRange.lower || mMapData->keyRange().lower > inKeyRange.upper) + { + foundRange = false; + return {}; + } + } + + foundRange = true; + QCPRange result = mMapData->valueRange(); + result.normalize(); + if (inSignDomain == QCP::sdPositive) + { + if (result.lower <= 0 && result.upper > 0) + result.lower = result.upper*1e-3; + else if (result.lower <= 0 && result.upper <= 0) + foundRange = false; + } else if (inSignDomain == QCP::sdNegative) { - newData.key = key[i]; - newData.value = value[i]; - newData.valueErrorMinus = valueError[i]; - newData.valueErrorPlus = valueError[i]; - mData->insertMulti(key[i], newData); + if (result.upper >= 0 && result.lower < 0) + result.upper = result.lower*1e-3; + else if (result.upper >= 0 && result.lower >= 0) + foundRange = false; } + return result; } -/*! - \overload - Replaces the current data with the provided points in \a key and \a value pairs. Additionally the - negative value error of the data points are set to the values in \a valueErrorMinus, the positive - value error to \a valueErrorPlus. - For error bars to show appropriately, see \ref setErrorType. - The provided vectors should have equal length. Else, the number of added points will be the size of the - smallest vector. +/*! \internal + + Updates the internal map image buffer by going through the internal \ref QCPColorMapData and + turning the data values into color pixels with \ref QCPColorGradient::colorize. + + This method is called by \ref QCPColorMap::draw if either the data has been modified or the map image + has been invalidated for a different reason (e.g. a change of the data range with \ref + setDataRange). + + If the map cell count is low, the image created will be oversampled in order to avoid a + QPainter::drawImage bug which makes inner pixel boundaries jitter when stretch-drawing images + without smooth transform enabled. Accordingly, oversampling isn't performed if \ref + setInterpolate is true. */ -void QCPGraph::setDataValueError(const QVector &key, const QVector &value, const QVector &valueErrorMinus, const QVector &valueErrorPlus) +void QCPColorMap::updateMapImage() { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - n = qMin(n, valueErrorMinus.size()); - n = qMin(n, valueErrorPlus.size()); - QCPData newData; - for (int i=0; iisEmpty()) return; + + const QImage::Format format = QImage::Format_ARGB32_Premultiplied; + const int keySize = mMapData->keySize(); + const int valueSize = mMapData->valueSize(); + int keyOversamplingFactor = mInterpolate ? 1 : int(1.0+100.0/double(keySize)); // make mMapImage have at least size 100, factor becomes 1 if size > 200 or interpolation is on + int valueOversamplingFactor = mInterpolate ? 1 : int(1.0+100.0/double(valueSize)); // make mMapImage have at least size 100, factor becomes 1 if size > 200 or interpolation is on + + // resize mMapImage to correct dimensions including possible oversampling factors, according to key/value axes orientation: + if (keyAxis->orientation() == Qt::Horizontal && (mMapImage.width() != keySize*keyOversamplingFactor || mMapImage.height() != valueSize*valueOversamplingFactor)) + mMapImage = QImage(QSize(keySize*keyOversamplingFactor, valueSize*valueOversamplingFactor), format); + else if (keyAxis->orientation() == Qt::Vertical && (mMapImage.width() != valueSize*valueOversamplingFactor || mMapImage.height() != keySize*keyOversamplingFactor)) + mMapImage = QImage(QSize(valueSize*valueOversamplingFactor, keySize*keyOversamplingFactor), format); + + if (mMapImage.isNull()) + { + qDebug() << Q_FUNC_INFO << "Couldn't create map image (possibly too large for memory)"; + mMapImage = QImage(QSize(10, 10), format); + mMapImage.fill(Qt::black); + } else { - newData.key = key[i]; - newData.value = value[i]; - newData.valueErrorMinus = valueErrorMinus[i]; - newData.valueErrorPlus = valueErrorPlus[i]; - mData->insertMulti(key[i], newData); + QImage *localMapImage = &mMapImage; // this is the image on which the colorization operates. Either the final mMapImage, or if we need oversampling, mUndersampledMapImage + if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1) + { + // resize undersampled map image to actual key/value cell sizes: + if (keyAxis->orientation() == Qt::Horizontal && (mUndersampledMapImage.width() != keySize || mUndersampledMapImage.height() != valueSize)) + mUndersampledMapImage = QImage(QSize(keySize, valueSize), format); + else if (keyAxis->orientation() == Qt::Vertical && (mUndersampledMapImage.width() != valueSize || mUndersampledMapImage.height() != keySize)) + mUndersampledMapImage = QImage(QSize(valueSize, keySize), format); + localMapImage = &mUndersampledMapImage; // make the colorization run on the undersampled image + } else if (!mUndersampledMapImage.isNull()) + mUndersampledMapImage = QImage(); // don't need oversampling mechanism anymore (map size has changed) but mUndersampledMapImage still has nonzero size, free it + + const double *rawData = mMapData->mData; + const unsigned char *rawAlpha = mMapData->mAlpha; + if (keyAxis->orientation() == Qt::Horizontal) + { + const int lineCount = valueSize; + const int rowCount = keySize; + for (int line=0; line(localMapImage->scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system) + if (rawAlpha) + mGradient.colorize(rawData+line*rowCount, rawAlpha+line*rowCount, mDataRange, pixels, rowCount, 1, mDataScaleType==QCPAxis::stLogarithmic); + else + mGradient.colorize(rawData+line*rowCount, mDataRange, pixels, rowCount, 1, mDataScaleType==QCPAxis::stLogarithmic); + } + } else // keyAxis->orientation() == Qt::Vertical + { + const int lineCount = keySize; + const int rowCount = valueSize; + for (int line=0; line(localMapImage->scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system) + if (rawAlpha) + mGradient.colorize(rawData+line, rawAlpha+line, mDataRange, pixels, rowCount, lineCount, mDataScaleType==QCPAxis::stLogarithmic); + else + mGradient.colorize(rawData+line, mDataRange, pixels, rowCount, lineCount, mDataScaleType==QCPAxis::stLogarithmic); + } + } + + if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1) + { + if (keyAxis->orientation() == Qt::Horizontal) + mMapImage = mUndersampledMapImage.scaled(keySize*keyOversamplingFactor, valueSize*valueOversamplingFactor, Qt::IgnoreAspectRatio, Qt::FastTransformation); + else + mMapImage = mUndersampledMapImage.scaled(valueSize*valueOversamplingFactor, keySize*keyOversamplingFactor, Qt::IgnoreAspectRatio, Qt::FastTransformation); + } } + mMapData->mDataModified = false; + mMapImageInvalidated = false; } -/*! - Replaces the current data with the provided points in \a key and \a value pairs. Additionally the - symmetrical key error of the data points are set to the values in \a keyError. - For error bars to show appropriately, see \ref setErrorType. - The provided vectors should have equal length. Else, the number of added points will be the size of the - smallest vector. - - For asymmetrical errors (plus different from minus), see the overloaded version of this function. -*/ -void QCPGraph::setDataKeyError(const QVector &key, const QVector &value, const QVector &keyError) +/* inherits documentation from base class */ +void QCPColorMap::draw(QCPPainter *painter) { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - n = qMin(n, keyError.size()); - QCPData newData; - for (int i=0; iisEmpty()) return; + if (!mKeyAxis || !mValueAxis) return; + applyDefaultAntialiasingHint(painter); + + if (mMapData->mDataModified || mMapImageInvalidated) + updateMapImage(); + + // use buffer if painting vectorized (PDF): + const bool useBuffer = painter->modes().testFlag(QCPPainter::pmVectorized); + QCPPainter *localPainter = painter; // will be redirected to paint on mapBuffer if painting vectorized + QRectF mapBufferTarget; // the rect in absolute widget coordinates where the visible map portion/buffer will end up in + QPixmap mapBuffer; + if (useBuffer) + { + const double mapBufferPixelRatio = 3; // factor by which DPI is increased in embedded bitmaps + mapBufferTarget = painter->clipRegion().boundingRect(); + mapBuffer = QPixmap((mapBufferTarget.size()*mapBufferPixelRatio).toSize()); + mapBuffer.fill(Qt::transparent); + localPainter = new QCPPainter(&mapBuffer); + localPainter->scale(mapBufferPixelRatio, mapBufferPixelRatio); + localPainter->translate(-mapBufferTarget.topLeft()); + } + + QRectF imageRect = QRectF(coordsToPixels(mMapData->keyRange().lower, mMapData->valueRange().lower), + coordsToPixels(mMapData->keyRange().upper, mMapData->valueRange().upper)).normalized(); + // extend imageRect to contain outer halves/quarters of bordering/cornering pixels (cells are centered on map range boundary): + double halfCellWidth = 0; // in pixels + double halfCellHeight = 0; // in pixels + if (keyAxis()->orientation() == Qt::Horizontal) + { + if (mMapData->keySize() > 1) + halfCellWidth = 0.5*imageRect.width()/double(mMapData->keySize()-1); + if (mMapData->valueSize() > 1) + halfCellHeight = 0.5*imageRect.height()/double(mMapData->valueSize()-1); + } else // keyAxis orientation is Qt::Vertical + { + if (mMapData->keySize() > 1) + halfCellHeight = 0.5*imageRect.height()/double(mMapData->keySize()-1); + if (mMapData->valueSize() > 1) + halfCellWidth = 0.5*imageRect.width()/double(mMapData->valueSize()-1); + } + imageRect.adjust(-halfCellWidth, -halfCellHeight, halfCellWidth, halfCellHeight); + const bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed(); + const bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed(); + const bool smoothBackup = localPainter->renderHints().testFlag(QPainter::SmoothPixmapTransform); + localPainter->setRenderHint(QPainter::SmoothPixmapTransform, mInterpolate); + QRegion clipBackup; + if (mTightBoundary) + { + clipBackup = localPainter->clipRegion(); + QRectF tightClipRect = QRectF(coordsToPixels(mMapData->keyRange().lower, mMapData->valueRange().lower), + coordsToPixels(mMapData->keyRange().upper, mMapData->valueRange().upper)).normalized(); + localPainter->setClipRect(tightClipRect, Qt::IntersectClip); + } + localPainter->drawImage(imageRect, mMapImage.mirrored(mirrorX, mirrorY)); + if (mTightBoundary) + localPainter->setClipRegion(clipBackup); + localPainter->setRenderHint(QPainter::SmoothPixmapTransform, smoothBackup); + + if (useBuffer) // localPainter painted to mapBuffer, so now draw buffer with original painter { - newData.key = key[i]; - newData.value = value[i]; - newData.keyErrorMinus = keyError[i]; - newData.keyErrorPlus = keyError[i]; - mData->insertMulti(key[i], newData); + delete localPainter; + painter->drawPixmap(mapBufferTarget.toRect(), mapBuffer); } } -/*! - \overload - Replaces the current data with the provided points in \a key and \a value pairs. Additionally the - negative key error of the data points are set to the values in \a keyErrorMinus, the positive - key error to \a keyErrorPlus. - For error bars to show appropriately, see \ref setErrorType. - The provided vectors should have equal length. Else, the number of added points will be the size of the - smallest vector. -*/ -void QCPGraph::setDataKeyError(const QVector &key, const QVector &value, const QVector &keyErrorMinus, const QVector &keyErrorPlus) +/* inherits documentation from base class */ +void QCPColorMap::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - n = qMin(n, keyErrorMinus.size()); - n = qMin(n, keyErrorPlus.size()); - QCPData newData; - for (int i=0; iinsertMulti(key[i], newData); + QPixmap scaledIcon = mLegendIcon.scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::FastTransformation); + QRectF iconRect = QRectF(0, 0, scaledIcon.width(), scaledIcon.height()); + iconRect.moveCenter(rect.center()); + painter->drawPixmap(iconRect.topLeft(), scaledIcon); } + /* + // draw frame: + painter->setBrush(Qt::NoBrush); + painter->setPen(Qt::black); + painter->drawRect(rect.adjusted(1, 1, 0, 0)); + */ } +/* end of 'src/plottables/plottable-colormap.cpp' */ -/*! - Replaces the current data with the provided points in \a key and \a value pairs. Additionally the - symmetrical key and value errors of the data points are set to the values in \a keyError and \a valueError. - For error bars to show appropriately, see \ref setErrorType. - The provided vectors should have equal length. Else, the number of added points will be the size of the - smallest vector. + +/* including file 'src/plottables/plottable-financial.cpp' */ +/* modified 2022-11-06T12:45:57, size 42914 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPFinancialData +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPFinancialData + \brief Holds the data of one single data point for QCPFinancial. - For asymmetrical errors (plus different from minus), see the overloaded version of this function. + The stored data is: + \li \a key: coordinate on the key axis of this data point (this is the \a mainKey and the \a sortKey) + \li \a open: The opening value at the data point (this is the \a mainValue) + \li \a high: The high/maximum value at the data point + \li \a low: The low/minimum value at the data point + \li \a close: The closing value at the data point + + The container for storing multiple data points is \ref QCPFinancialDataContainer. It is a typedef + for \ref QCPDataContainer with \ref QCPFinancialData as the DataType template parameter. See the + documentation there for an explanation regarding the data type's generic methods. + + \see QCPFinancialDataContainer */ -void QCPGraph::setDataBothError(const QVector &key, const QVector &value, const QVector &keyError, const QVector &valueError) -{ - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - n = qMin(n, valueError.size()); - n = qMin(n, keyError.size()); - QCPData newData; - for (int i=0; iinsertMulti(key[i], newData); - } -} -/*! - \overload - Replaces the current data with the provided points in \a key and \a value pairs. Additionally the - negative key and value errors of the data points are set to the values in \a keyErrorMinus and \a valueErrorMinus. The positive - key and value errors are set to the values in \a keyErrorPlus \a valueErrorPlus. - For error bars to show appropriately, see \ref setErrorType. - The provided vectors should have equal length. Else, the number of added points will be the size of the - smallest vector. -*/ -void QCPGraph::setDataBothError(const QVector &key, const QVector &value, const QVector &keyErrorMinus, const QVector &keyErrorPlus, const QVector &valueErrorMinus, const QVector &valueErrorPlus) -{ - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - n = qMin(n, valueErrorMinus.size()); - n = qMin(n, valueErrorPlus.size()); - n = qMin(n, keyErrorMinus.size()); - n = qMin(n, keyErrorPlus.size()); - QCPData newData; - for (int i=0; iinsertMulti(key[i], newData); - } -} +/* start documentation of inline functions */ +/*! \fn double QCPFinancialData::sortKey() const + + Returns the \a key member of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ -/*! - Sets how the single data points are connected in the plot. For scatter-only plots, set \a ls to - \ref lsNone and \ref setScatterStyle to the desired scatter style. +/*! \fn static QCPFinancialData QCPFinancialData::fromSortKey(double sortKey) - \see setScatterStyle + Returns a data point with the specified \a sortKey. All other members are set to zero. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -void QCPGraph::setLineStyle(LineStyle ls) -{ - mLineStyle = ls; -} -/*! - Sets the visual appearance of single data points in the plot. If set to \ref QCPScatterStyle::ssNone, no scatter points - are drawn (e.g. for line-only-plots with appropriate line style). +/*! \fn static static bool QCPFinancialData::sortKeyIsMainKey() - \see QCPScatterStyle, setLineStyle + Since the member \a key is both the data point key coordinate and the data ordering parameter, + this method returns true. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -void QCPGraph::setScatterStyle(const QCPScatterStyle &style) -{ - mScatterStyle = style; -} -/*! - Sets which kind of error bars (Key Error, Value Error or both) should be drawn on each data - point. If you set \a errorType to something other than \ref etNone, make sure to actually pass - error data via the specific setData functions along with the data points (e.g. \ref - setDataValueError, \ref setDataKeyError, \ref setDataBothError). +/*! \fn double QCPFinancialData::mainKey() const + + Returns the \a key member of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. +*/ - \see ErrorType +/*! \fn double QCPFinancialData::mainValue() const + + Returns the \a open member of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -void QCPGraph::setErrorType(ErrorType errorType) -{ - mErrorType = errorType; -} -/*! - Sets the pen with which the error bars will be drawn. - \see setErrorBarSize, setErrorType +/*! \fn QCPRange QCPFinancialData::valueRange() const + + Returns a QCPRange spanning from the \a low to the \a high value of this data point. + + For a general explanation of what this method is good for in the context of the data container, + see the documentation of \ref QCPDataContainer. */ -void QCPGraph::setErrorPen(const QPen &pen) -{ - mErrorPen = pen; -} + +/* end documentation of inline functions */ /*! - Sets the width of the handles at both ends of an error bar in pixels. + Constructs a data point with key and all values set to zero. */ -void QCPGraph::setErrorBarSize(double size) +QCPFinancialData::QCPFinancialData() : + key(0), + open(0), + high(0), + low(0), + close(0) { - mErrorBarSize = size; } /*! - If \a enabled is set to true, the error bar will not be drawn as a solid line under the scatter symbol but - leave some free space around the symbol. - - This feature uses the current scatter size (\ref QCPScatterStyle::setSize) to determine the size - of the area to leave blank. So when drawing Pixmaps as scatter points (\ref - QCPScatterStyle::ssPixmap), the scatter size must be set manually to a value corresponding to the - size of the Pixmap, if the error bars should leave gaps to its boundaries. - - \ref setErrorType, setErrorBarSize, setScatterStyle + Constructs a data point with the specified \a key and OHLC values. */ -void QCPGraph::setErrorBarSkipSymbol(bool enabled) +QCPFinancialData::QCPFinancialData(double key, double open, double high, double low, double close) : + key(key), + open(open), + high(high), + low(low), + close(close) { - mErrorBarSkipSymbol = enabled; } -/*! - Sets the target graph for filling the area between this graph and \a targetGraph with the current - brush (\ref setBrush). - - When \a targetGraph is set to 0, a normal graph fill to the zero-value-line will be shown. To - disable any filling, set the brush to Qt::NoBrush. - \see setBrush +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPFinancial +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPFinancial + \brief A plottable representing a financial stock chart + + \image html QCPFinancial.png + + This plottable represents time series data binned to certain intervals, mainly used for stock + charts. The two common representations OHLC (Open-High-Low-Close) bars and Candlesticks can be + set via \ref setChartStyle. + + The data is passed via \ref setData as a set of open/high/low/close values at certain keys + (typically times). This means the data must be already binned appropriately. If data is only + available as a series of values (e.g. \a price against \a time), you can use the static + convenience function \ref timeSeriesToOhlc to generate binned OHLC-data which can then be passed + to \ref setData. + + The width of the OHLC bars/candlesticks can be controlled with \ref setWidth and \ref + setWidthType. A typical choice is to set the width type to \ref wtPlotCoords (the default) and + the width to (or slightly less than) one time bin interval width. + + \section qcpfinancial-appearance Changing the appearance + + Charts can be either single- or two-colored (\ref setTwoColored). If set to be single-colored, + lines are drawn with the plottable's pen (\ref setPen) and fills with the brush (\ref setBrush). + + If set to two-colored, positive changes of the value during an interval (\a close >= \a open) are + represented with a different pen and brush than negative changes (\a close < \a open). These can + be configured with \ref setPenPositive, \ref setPenNegative, \ref setBrushPositive, and \ref + setBrushNegative. In two-colored mode, the normal plottable pen/brush is ignored. Upon selection + however, the normal selected pen/brush (provided by the \ref selectionDecorator) is used, + irrespective of whether the chart is single- or two-colored. + + \section qcpfinancial-usage Usage + + Like all data representing objects in QCustomPlot, the QCPFinancial is a plottable + (QCPAbstractPlottable). So the plottable-interface of QCustomPlot applies + (QCustomPlot::plottable, QCustomPlot::removePlottable, etc.) + + Usually, you first create an instance: + + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpfinancial-creation-1 + which registers it with the QCustomPlot instance of the passed axes. Note that this QCustomPlot + instance takes ownership of the plottable, so do not delete it manually but use + QCustomPlot::removePlottable() instead. The newly created plottable can be modified, e.g.: + + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpfinancial-creation-2 + Here we have used the static helper method \ref timeSeriesToOhlc, to turn a time-price data + series into a 24-hour binned open-high-low-close data series as QCPFinancial uses. */ -void QCPGraph::setChannelFillGraph(QCPGraph *targetGraph) -{ - // prevent setting channel target to this graph itself: - if (targetGraph == this) - { - qDebug() << Q_FUNC_INFO << "targetGraph is this graph itself"; - mChannelFillGraph = 0; - return; - } - // prevent setting channel target to a graph not in the plot: - if (targetGraph && targetGraph->mParentPlot != mParentPlot) - { - qDebug() << Q_FUNC_INFO << "targetGraph not in same plot"; - mChannelFillGraph = 0; - return; - } + +/* start of documentation of inline functions */ + +/*! \fn QCPFinancialDataContainer *QCPFinancial::data() const - mChannelFillGraph = targetGraph; -} + Returns a pointer to the internal data storage of type \ref QCPFinancialDataContainer. You may + use it to directly manipulate the data, which may be more convenient and faster than using the + regular \ref setData or \ref addData methods, in certain situations. +*/ + +/* end of documentation of inline functions */ /*! - Sets whether adaptive sampling shall be used when plotting this graph. QCustomPlot's adaptive - sampling technique can drastically improve the replot performance for graphs with a larger number - of points (e.g. above 10,000), without notably changing the appearance of the graph. - - By default, adaptive sampling is enabled. Even if enabled, QCustomPlot decides whether adaptive - sampling shall actually be used on a per-graph basis. So leaving adaptive sampling enabled has no - disadvantage in almost all cases. - - \image html adaptive-sampling-line.png "A line plot of 500,000 points without and with adaptive sampling" - - As can be seen, line plots experience no visual degradation from adaptive sampling. Outliers are - reproduced reliably, as well as the overall shape of the data set. The replot time reduces - dramatically though. This allows QCustomPlot to display large amounts of data in realtime. - - \image html adaptive-sampling-scatter.png "A scatter plot of 100,000 points without and with adaptive sampling" - - Care must be taken when using high-density scatter plots in combination with adaptive sampling. - The adaptive sampling algorithm treats scatter plots more carefully than line plots which still - gives a significant reduction of replot times, but not quite as much as for line plots. This is - because scatter plots inherently need more data points to be preserved in order to still resemble - the original, non-adaptive-sampling plot. As shown above, the results still aren't quite - identical, as banding occurs for the outer data points. This is in fact intentional, such that - the boundaries of the data cloud stay visible to the viewer. How strong the banding appears, - depends on the point density, i.e. the number of points in the plot. + Constructs a financial chart which uses \a keyAxis as its key axis ("x") and \a valueAxis as its value + axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and not have + the same orientation. If either of these restrictions is violated, a corresponding message is + printed to the debug output (qDebug), the construction is not aborted, though. - For some situations with scatter plots it might thus be desirable to manually turn adaptive - sampling off. For example, when saving the plot to disk. This can be achieved by setting \a - enabled to false before issuing a command like \ref QCustomPlot::savePng, and setting \a enabled - back to true afterwards. + The created QCPFinancial is automatically registered with the QCustomPlot instance inferred from \a + keyAxis. This QCustomPlot instance takes ownership of the QCPFinancial, so do not delete it manually + but use QCustomPlot::removePlottable() instead. */ -void QCPGraph::setAdaptiveSampling(bool enabled) +QCPFinancial::QCPFinancial(QCPAxis *keyAxis, QCPAxis *valueAxis) : + QCPAbstractPlottable1D(keyAxis, valueAxis), + mChartStyle(csCandlestick), + mWidth(0.5), + mWidthType(wtPlotCoords), + mTwoColored(true), + mBrushPositive(QBrush(QColor(50, 160, 0))), + mBrushNegative(QBrush(QColor(180, 0, 15))), + mPenPositive(QPen(QColor(40, 150, 0))), + mPenNegative(QPen(QColor(170, 5, 5))) { - mAdaptiveSampling = enabled; + mSelectionDecorator->setBrush(QBrush(QColor(160, 160, 255))); } -/*! - Adds the provided data points in \a dataMap to the current data. - - Alternatively, you can also access and modify the graph's data via the \ref data method, which - returns a pointer to the internal \ref QCPDataMap. - - \see removeData -*/ -void QCPGraph::addData(const QCPDataMap &dataMap) +QCPFinancial::~QCPFinancial() { - mData->unite(dataMap); } /*! \overload - Adds the provided single data point in \a data to the current data. - Alternatively, you can also access and modify the graph's data via the \ref data method, which - returns a pointer to the internal \ref QCPDataMap. + Replaces the current data container with the provided \a data container. - \see removeData + Since a QSharedPointer is used, multiple QCPFinancials may share the same data container safely. + Modifying the data in the container will then affect all financials that share the container. + Sharing can be achieved by simply exchanging the data containers wrapped in shared pointers: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpfinancial-datasharing-1 + + If you do not wish to share containers, but create a copy from an existing container, rather use + the \ref QCPDataContainer::set method on the financial's data container directly: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpfinancial-datasharing-2 + + \see addData, timeSeriesToOhlc */ -void QCPGraph::addData(const QCPData &data) +void QCPFinancial::setData(QSharedPointer data) { - mData->insertMulti(data.key, data); + mDataContainer = data; } /*! \overload - Adds the provided single data point as \a key and \a value pair to the current data. - Alternatively, you can also access and modify the graph's data via the \ref data method, which - returns a pointer to the internal \ref QCPDataMap. + Replaces the current data with the provided points in \a keys, \a open, \a high, \a low and \a + close. The provided vectors should have equal length. Else, the number of added points will be + the size of the smallest vector. - \see removeData + If you can guarantee that the passed data points are sorted by \a keys in ascending order, you + can set \a alreadySorted to true, to improve performance by saving a sorting run. + + \see addData, timeSeriesToOhlc */ -void QCPGraph::addData(double key, double value) +void QCPFinancial::setData(const QVector &keys, const QVector &open, const QVector &high, const QVector &low, const QVector &close, bool alreadySorted) { - QCPData newData; - newData.key = key; - newData.value = value; - mData->insertMulti(newData.key, newData); + mDataContainer->clear(); + addData(keys, open, high, low, close, alreadySorted); } -/*! \overload - Adds the provided data points as \a key and \a value pairs to the current data. - - Alternatively, you can also access and modify the graph's data via the \ref data method, which - returns a pointer to the internal \ref QCPDataMap. - - \see removeData +/*! + Sets which representation style shall be used to display the OHLC data. */ -void QCPGraph::addData(const QVector &keys, const QVector &values) +void QCPFinancial::setChartStyle(QCPFinancial::ChartStyle style) { - int n = qMin(keys.size(), values.size()); - QCPData newData; - for (int i=0; iinsertMulti(newData.key, newData); - } + mChartStyle = style; } /*! - Removes all data points with keys smaller than \a key. - \see addData, clearData + Sets the width of the individual bars/candlesticks to \a width in plot key coordinates. + + A typical choice is to set it to (or slightly less than) one bin interval width. */ -void QCPGraph::removeDataBefore(double key) +void QCPFinancial::setWidth(double width) { - QCPDataMap::iterator it = mData->begin(); - while (it != mData->end() && it.key() < key) - it = mData->erase(it); + mWidth = width; } /*! - Removes all data points with keys greater than \a key. - \see addData, clearData + Sets how the width of the financial bars is defined. See the documentation of \ref WidthType for + an explanation of the possible values for \a widthType. + + The default value is \ref wtPlotCoords. + + \see setWidth */ -void QCPGraph::removeDataAfter(double key) +void QCPFinancial::setWidthType(QCPFinancial::WidthType widthType) { - if (mData->isEmpty()) return; - QCPDataMap::iterator it = mData->upperBound(key); - while (it != mData->end()) - it = mData->erase(it); + mWidthType = widthType; } /*! - Removes all data points with keys between \a fromKey and \a toKey. - if \a fromKey is greater or equal to \a toKey, the function does nothing. To remove - a single data point with known key, use \ref removeData(double key). + Sets whether this chart shall contrast positive from negative trends per data point by using two + separate colors to draw the respective bars/candlesticks. + + If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref + setBrush). - \see addData, clearData + \see setPenPositive, setPenNegative, setBrushPositive, setBrushNegative */ -void QCPGraph::removeData(double fromKey, double toKey) +void QCPFinancial::setTwoColored(bool twoColored) { - if (fromKey >= toKey || mData->isEmpty()) return; - QCPDataMap::iterator it = mData->upperBound(fromKey); - QCPDataMap::iterator itEnd = mData->upperBound(toKey); - while (it != itEnd) - it = mData->erase(it); + mTwoColored = twoColored; } -/*! \overload +/*! + If \ref setTwoColored is set to true, this function controls the brush that is used to draw fills + of data points with a positive trend (i.e. bars/candlesticks with close >= open). - Removes a single data point at \a key. If the position is not known with absolute precision, - consider using \ref removeData(double fromKey, double toKey) with a small fuzziness interval around - the suspected position, depeding on the precision with which the key is known. - - \see addData, clearData + If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref + setBrush). + + \see setBrushNegative, setPenPositive, setPenNegative */ -void QCPGraph::removeData(double key) +void QCPFinancial::setBrushPositive(const QBrush &brush) { - mData->remove(key); + mBrushPositive = brush; } /*! - Removes all data points. - \see removeData, removeDataAfter, removeDataBefore + If \ref setTwoColored is set to true, this function controls the brush that is used to draw fills + of data points with a negative trend (i.e. bars/candlesticks with close < open). + + If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref + setBrush). + + \see setBrushPositive, setPenNegative, setPenPositive */ -void QCPGraph::clearData() +void QCPFinancial::setBrushNegative(const QBrush &brush) { - mData->clear(); + mBrushNegative = brush; } -/* inherits documentation from base class */ -double QCPGraph::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const -{ - Q_UNUSED(details) - if ((onlySelectable && !mSelectable) || mData->isEmpty()) - return -1; - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } +/*! + If \ref setTwoColored is set to true, this function controls the pen that is used to draw + outlines of data points with a positive trend (i.e. bars/candlesticks with close >= open). - if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) - return pointDistance(pos); - else - return -1; + If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref + setBrush). + + \see setPenNegative, setBrushPositive, setBrushNegative +*/ +void QCPFinancial::setPenPositive(const QPen &pen) +{ + mPenPositive = pen; } -/*! \overload +/*! + If \ref setTwoColored is set to true, this function controls the pen that is used to draw + outlines of data points with a negative trend (i.e. bars/candlesticks with close < open). - Allows to define whether error bars are taken into consideration when determining the new axis - range. + If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref + setBrush). - \see rescaleKeyAxis, rescaleValueAxis, QCPAbstractPlottable::rescaleAxes, QCustomPlot::rescaleAxes + \see setPenPositive, setBrushNegative, setBrushPositive */ -void QCPGraph::rescaleAxes(bool onlyEnlarge, bool includeErrorBars) const +void QCPFinancial::setPenNegative(const QPen &pen) { - rescaleKeyAxis(onlyEnlarge, includeErrorBars); - rescaleValueAxis(onlyEnlarge, includeErrorBars); + mPenNegative = pen; } /*! \overload - Allows to define whether error bars (of kind \ref QCPGraph::etKey) are taken into consideration - when determining the new axis range. - - \see rescaleAxes, QCPAbstractPlottable::rescaleKeyAxis -*/ -void QCPGraph::rescaleKeyAxis(bool onlyEnlarge, bool includeErrorBars) const -{ - // this code is a copy of QCPAbstractPlottable::rescaleKeyAxis with the only change - // that getKeyRange is passed the includeErrorBars value. - if (mData->isEmpty()) return; + Adds the provided points in \a keys, \a open, \a high, \a low and \a close to the current data. + The provided vectors should have equal length. Else, the number of added points will be the size + of the smallest vector. - QCPAxis *keyAxis = mKeyAxis.data(); - if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } - - SignDomain signDomain = sdBoth; - if (keyAxis->scaleType() == QCPAxis::stLogarithmic) - signDomain = (keyAxis->range().upper < 0 ? sdNegative : sdPositive); + If you can guarantee that the passed data points are sorted by \a keys in ascending order, you + can set \a alreadySorted to true, to improve performance by saving a sorting run. - bool foundRange; - QCPRange newRange = getKeyRange(foundRange, signDomain, includeErrorBars); + Alternatively, you can also access and modify the data directly via the \ref data method, which + returns a pointer to the internal data container. - if (foundRange) + \see timeSeriesToOhlc +*/ +void QCPFinancial::addData(const QVector &keys, const QVector &open, const QVector &high, const QVector &low, const QVector &close, bool alreadySorted) +{ + if (keys.size() != open.size() || open.size() != high.size() || high.size() != low.size() || low.size() != close.size() || close.size() != keys.size()) + qDebug() << Q_FUNC_INFO << "keys, open, high, low, close have different sizes:" << keys.size() << open.size() << high.size() << low.size() << close.size(); + const int n = qMin(keys.size(), qMin(open.size(), qMin(high.size(), qMin(low.size(), close.size())))); + QVector tempData(n); + QVector::iterator it = tempData.begin(); + const QVector::iterator itEnd = tempData.end(); + int i = 0; + while (it != itEnd) { - if (onlyEnlarge) - { - if (keyAxis->range().lower < newRange.lower) - newRange.lower = keyAxis->range().lower; - if (keyAxis->range().upper > newRange.upper) - newRange.upper = keyAxis->range().upper; - } - keyAxis->setRange(newRange); + it->key = keys[i]; + it->open = open[i]; + it->high = high[i]; + it->low = low[i]; + it->close = close[i]; + ++it; + ++i; } + mDataContainer->add(tempData, alreadySorted); // don't modify tempData beyond this to prevent copy on write } /*! \overload - Allows to define whether error bars (of kind \ref QCPGraph::etValue) are taken into consideration - when determining the new axis range. + Adds the provided data point as \a key, \a open, \a high, \a low and \a close to the current + data. + + Alternatively, you can also access and modify the data directly via the \ref data method, which + returns a pointer to the internal data container. - \see rescaleAxes, QCPAbstractPlottable::rescaleValueAxis + \see timeSeriesToOhlc */ -void QCPGraph::rescaleValueAxis(bool onlyEnlarge, bool includeErrorBars) const +void QCPFinancial::addData(double key, double open, double high, double low, double close) { - // this code is a copy of QCPAbstractPlottable::rescaleValueAxis with the only change - // is that getValueRange is passed the includeErrorBars value. - if (mData->isEmpty()) return; - - QCPAxis *valueAxis = mValueAxis.data(); - if (!valueAxis) { qDebug() << Q_FUNC_INFO << "invalid value axis"; return; } - - SignDomain signDomain = sdBoth; - if (valueAxis->scaleType() == QCPAxis::stLogarithmic) - signDomain = (valueAxis->range().upper < 0 ? sdNegative : sdPositive); - - bool foundRange; - QCPRange newRange = getValueRange(foundRange, signDomain, includeErrorBars); - - if (foundRange) - { - if (onlyEnlarge) - { - if (valueAxis->range().lower < newRange.lower) - newRange.lower = valueAxis->range().lower; - if (valueAxis->range().upper > newRange.upper) - newRange.upper = valueAxis->range().upper; - } - valueAxis->setRange(newRange); - } + mDataContainer->add(QCPFinancialData(key, open, high, low, close)); } -/* inherits documentation from base class */ -void QCPGraph::draw(QCPPainter *painter) +/*! + \copydoc QCPPlottableInterface1D::selectTestRect +*/ +QCPDataSelection QCPFinancial::selectTestRect(const QRectF &rect, bool onlySelectable) const { - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (mKeyAxis.data()->range().size() <= 0 || mData->isEmpty()) return; - if (mLineStyle == lsNone && mScatterStyle.isNone()) return; - - // allocate line and (if necessary) point vectors: - QVector *lineData = new QVector; - QVector *scatterData = 0; - if (!mScatterStyle.isNone()) - scatterData = new QVector; + QCPDataSelection result; + if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty()) + return result; + if (!mKeyAxis || !mValueAxis) + return result; - // fill vectors with data appropriate to plot style: - getPlotData(lineData, scatterData); + QCPFinancialDataContainer::const_iterator visibleBegin, visibleEnd; + getVisibleDataBounds(visibleBegin, visibleEnd); - // check data validity if flag set: -#ifdef QCUSTOMPLOT_CHECK_DATA - QCPDataMap::const_iterator it; - for (it = mData->constBegin(); it != mData->constEnd(); ++it) + for (QCPFinancialDataContainer::const_iterator it=visibleBegin; it!=visibleEnd; ++it) { - if (QCP::isInvalidData(it.value().key, it.value().value) || - QCP::isInvalidData(it.value().keyErrorPlus, it.value().keyErrorMinus) || - QCP::isInvalidData(it.value().valueErrorPlus, it.value().valueErrorPlus)) - qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name(); + if (rect.intersects(selectionHitBox(it))) + result.addDataRange(QCPDataRange(int(it-mDataContainer->constBegin()), int(it-mDataContainer->constBegin()+1)), false); } -#endif - - // draw fill of graph: - drawFill(painter, lineData); - - // draw line: - if (mLineStyle == lsImpulse) - drawImpulsePlot(painter, lineData); - else if (mLineStyle != lsNone) - drawLinePlot(painter, lineData); // also step plots can be drawn as a line plot - - // draw scatters: - if (scatterData) - drawScatterPlot(painter, scatterData); - - // free allocated line and point vectors: - delete lineData; - if (scatterData) - delete scatterData; + result.simplify(); + return result; } -/* inherits documentation from base class */ -void QCPGraph::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const +/*! + Implements a selectTest specific to this plottable's point geometry. + + If \a details is not 0, it will be set to a \ref QCPDataSelection, describing the closest data + point to \a pos. + + \seebaseclassmethod \ref QCPAbstractPlottable::selectTest +*/ +double QCPFinancial::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - // draw fill: - if (mBrush.style() != Qt::NoBrush) - { - applyFillAntialiasingHint(painter); - painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush); - } - // draw line vertically centered: - if (mLineStyle != lsNone) - { - applyDefaultAntialiasingHint(painter); - painter->setPen(mPen); - painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens - } - // draw scatter symbol: - if (!mScatterStyle.isNone()) + Q_UNUSED(details) + if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty()) + return -1; + if (!mKeyAxis || !mValueAxis) + return -1; + + if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect)) { - applyScattersAntialiasingHint(painter); - // scale scatter pixmap if it's too large to fit in legend icon rect: - if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height())) + // get visible data range: + QCPFinancialDataContainer::const_iterator visibleBegin, visibleEnd; + QCPFinancialDataContainer::const_iterator closestDataPoint = mDataContainer->constEnd(); + getVisibleDataBounds(visibleBegin, visibleEnd); + // perform select test according to configured style: + double result = -1; + switch (mChartStyle) { - QCPScatterStyle scaledStyle(mScatterStyle); - scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); - scaledStyle.applyTo(painter, mPen); - scaledStyle.drawShape(painter, QRectF(rect).center()); - } else + case QCPFinancial::csOhlc: + result = ohlcSelectTest(pos, visibleBegin, visibleEnd, closestDataPoint); break; + case QCPFinancial::csCandlestick: + result = candlestickSelectTest(pos, visibleBegin, visibleEnd, closestDataPoint); break; + } + if (details) { - mScatterStyle.applyTo(painter, mPen); - mScatterStyle.drawShape(painter, QRectF(rect).center()); + int pointIndex = int(closestDataPoint-mDataContainer->constBegin()); + details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1))); } + return result; } + + return -1; } -/*! \internal - - This function branches out to the line style specific "get(...)PlotData" functions, according to - the line style of the graph. - - \a lineData will be filled with raw points that will be drawn with the according draw functions, - e.g. \ref drawLinePlot and \ref drawImpulsePlot. These aren't necessarily the original data - points, since for step plots for example, additional points are needed for drawing lines that - make up steps. If the line style of the graph is \ref lsNone, the \a lineData vector will be left - untouched. - - \a scatterData will be filled with the original data points so \ref drawScatterPlot can draw the - scatter symbols accordingly. If no scatters need to be drawn, i.e. the scatter style's shape is - \ref QCPScatterStyle::ssNone, pass 0 as \a scatterData, and this step will be skipped. - - \see getScatterPlotData, getLinePlotData, getStepLeftPlotData, getStepRightPlotData, - getStepCenterPlotData, getImpulsePlotData -*/ -void QCPGraph::getPlotData(QVector *lineData, QVector *scatterData) const +/* inherits documentation from base class */ +QCPRange QCPFinancial::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const { - switch(mLineStyle) + QCPRange range = mDataContainer->keyRange(foundRange, inSignDomain); + // determine exact range by including width of bars/flags: + if (foundRange) { - case lsNone: getScatterPlotData(scatterData); break; - case lsLine: getLinePlotData(lineData, scatterData); break; - case lsStepLeft: getStepLeftPlotData(lineData, scatterData); break; - case lsStepRight: getStepRightPlotData(lineData, scatterData); break; - case lsStepCenter: getStepCenterPlotData(lineData, scatterData); break; - case lsImpulse: getImpulsePlotData(lineData, scatterData); break; + if (inSignDomain != QCP::sdPositive || range.lower-mWidth*0.5 > 0) + range.lower -= mWidth*0.5; + if (inSignDomain != QCP::sdNegative || range.upper+mWidth*0.5 < 0) + range.upper += mWidth*0.5; } + return range; } -/*! \internal - - If line style is \ref lsNone and the scatter style's shape is not \ref QCPScatterStyle::ssNone, - this function serves at providing the visible data points in \a scatterData, so the \ref - drawScatterPlot function can draw the scatter points accordingly. - - If line style is not \ref lsNone, this function is not called and the data for the scatter points - are (if needed) calculated inside the corresponding other "get(...)PlotData" functions. - - \see drawScatterPlot -*/ -void QCPGraph::getScatterPlotData(QVector *scatterData) const +/* inherits documentation from base class */ +QCPRange QCPFinancial::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const { - getPreparedData(0, scatterData); + return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange); } -/*! \internal +/*! + A convenience function that converts time series data (\a value against \a time) to OHLC binned + data points. The return value can then be passed on to \ref QCPFinancialDataContainer::set(const + QCPFinancialDataContainer&). - Places the raw data points needed for a normal linearly connected graph in \a linePixelData. - - As for all plot data retrieval functions, \a scatterData just contains all unaltered data (scatter) - points that are visible for drawing scatter points, if necessary. If drawing scatter points is - disabled (i.e. the scatter style's shape is \ref QCPScatterStyle::ssNone), pass 0 as \a - scatterData, and the function will skip filling the vector. + The size of the bins can be controlled with \a timeBinSize in the same units as \a time is given. + For example, if the unit of \a time is seconds and single OHLC/Candlesticks should span an hour + each, set \a timeBinSize to 3600. - \see drawLinePlot + \a timeBinOffset allows to control precisely at what \a time coordinate a bin should start. The + value passed as \a timeBinOffset doesn't need to be in the range encompassed by the \a time keys. + It merely defines the mathematical offset/phase of the bins that will be used to process the + data. */ -void QCPGraph::getLinePlotData(QVector *linePixelData, QVector *scatterData) const +QCPFinancialDataContainer QCPFinancial::timeSeriesToOhlc(const QVector &time, const QVector &value, double timeBinSize, double timeBinOffset) { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; } - - QVector lineData; - getPreparedData(&lineData, scatterData); - linePixelData->reserve(lineData.size()+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill - linePixelData->resize(lineData.size()); + QCPFinancialDataContainer data; + int count = qMin(time.size(), value.size()); + if (count == 0) + return QCPFinancialDataContainer(); - // transform lineData points to pixels: - if (keyAxis->orientation() == Qt::Vertical) + QCPFinancialData currentBinData(0, value.first(), value.first(), value.first(), value.first()); + int currentBinIndex = qFloor((time.first()-timeBinOffset)/timeBinSize+0.5); + for (int i=0; icoordToPixel(lineData.at(i).value)); - (*linePixelData)[i].setY(keyAxis->coordToPixel(lineData.at(i).key)); - } - } else // key axis is horizontal - { - for (int i=0; i currentBinData.high) currentBinData.high = value.at(i); + if (i == count-1) // last data point is in current bin, finalize bin: + { + currentBinData.close = value.at(i); + currentBinData.key = timeBinOffset+(index)*timeBinSize; + data.add(currentBinData); + } + } else // data point not anymore in current bin, set close of old and open of new bin, and add old to map: { - (*linePixelData)[i].setX(keyAxis->coordToPixel(lineData.at(i).key)); - (*linePixelData)[i].setY(valueAxis->coordToPixel(lineData.at(i).value)); + // finalize current bin: + currentBinData.close = value.at(i-1); + currentBinData.key = timeBinOffset+(index-1)*timeBinSize; + data.add(currentBinData); + // start next bin: + currentBinIndex = index; + currentBinData.open = value.at(i); + currentBinData.high = value.at(i); + currentBinData.low = value.at(i); } } + + return data; } -/*! - \internal - Places the raw data points needed for a step plot with left oriented steps in \a lineData. - - As for all plot data retrieval functions, \a scatterData just contains all unaltered data (scatter) - points that are visible for drawing scatter points, if necessary. If drawing scatter points is - disabled (i.e. the scatter style's shape is \ref QCPScatterStyle::ssNone), pass 0 as \a - scatterData, and the function will skip filling the vector. - - \see drawLinePlot -*/ -void QCPGraph::getStepLeftPlotData(QVector *linePixelData, QVector *scatterData) const +/* inherits documentation from base class */ +void QCPFinancial::draw(QCPPainter *painter) { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; } - - QVector lineData; - getPreparedData(&lineData, scatterData); - linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill - linePixelData->resize(lineData.size()*2); + // get visible data range: + QCPFinancialDataContainer::const_iterator visibleBegin, visibleEnd; + getVisibleDataBounds(visibleBegin, visibleEnd); + + // loop over and draw segments of unselected/selected data: + QList selectedSegments, unselectedSegments, allSegments; + getDataSegments(selectedSegments, unselectedSegments); + allSegments << unselectedSegments << selectedSegments; + for (int i=0; i= unselectedSegments.size(); + QCPFinancialDataContainer::const_iterator begin = visibleBegin; + QCPFinancialDataContainer::const_iterator end = visibleEnd; + mDataContainer->limitIteratorsToDataRange(begin, end, allSegments.at(i)); + if (begin == end) + continue; + + // draw data segment according to configured style: + switch (mChartStyle) + { + case QCPFinancial::csOhlc: + drawOhlcPlot(painter, begin, end, isSelectedSegment); break; + case QCPFinancial::csCandlestick: + drawCandlestickPlot(painter, begin, end, isSelectedSegment); break; + } + } - // calculate steps from lineData and transform to pixel coordinates: - if (keyAxis->orientation() == Qt::Vertical) + // draw other selection decoration that isn't just line/scatter pens and brushes: + if (mSelectionDecorator) + mSelectionDecorator->drawDecoration(painter, selection()); +} + +/* inherits documentation from base class */ +void QCPFinancial::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const +{ + painter->setAntialiasing(false); // legend icon especially of csCandlestick looks better without antialiasing + if (mChartStyle == csOhlc) { - double lastValue = valueAxis->coordToPixel(lineData.first().value); - double key; - for (int i=0; isetBrush(mBrushPositive); + painter->setPen(mPenPositive); + painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint())); + painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft())); + // draw bottom right half icon with negative color: + painter->setBrush(mBrushNegative); + painter->setPen(mPenNegative); + painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint())); + painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft())); + } else { - key = keyAxis->coordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+0].setX(lastValue); - (*linePixelData)[i*2+0].setY(key); - lastValue = valueAxis->coordToPixel(lineData.at(i).value); - (*linePixelData)[i*2+1].setX(lastValue); - (*linePixelData)[i*2+1].setY(key); + painter->setBrush(mBrush); + painter->setPen(mPen); + painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft())); } - } else // key axis is horizontal + } else if (mChartStyle == csCandlestick) { - double lastValue = valueAxis->coordToPixel(lineData.first().value); - double key; - for (int i=0; isetBrush(mBrushPositive); + painter->setPen(mPenPositive); + painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint())); + painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); + painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft())); + // draw bottom right half icon with negative color: + painter->setBrush(mBrushNegative); + painter->setPen(mPenNegative); + painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint())); + painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); + painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft())); + } else { - key = keyAxis->coordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+0].setX(key); - (*linePixelData)[i*2+0].setY(lastValue); - lastValue = valueAxis->coordToPixel(lineData.at(i).value); - (*linePixelData)[i*2+1].setX(key); - (*linePixelData)[i*2+1].setY(lastValue); + painter->setBrush(mBrush); + painter->setPen(mPen); + painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft())); + painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); + painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft())); } } } -/*! - \internal - Places the raw data points needed for a step plot with right oriented steps in \a lineData. - - As for all plot data retrieval functions, \a scatterData just contains all unaltered data (scatter) - points that are visible for drawing scatter points, if necessary. If drawing scatter points is - disabled (i.e. the scatter style's shape is \ref QCPScatterStyle::ssNone), pass 0 as \a - scatterData, and the function will skip filling the vector. +/*! \internal - \see drawLinePlot + Draws the data from \a begin to \a end-1 as OHLC bars with the provided \a painter. + + This method is a helper function for \ref draw. It is used when the chart style is \ref csOhlc. */ -void QCPGraph::getStepRightPlotData(QVector *linePixelData, QVector *scatterData) const +void QCPFinancial::drawOhlcPlot(QCPPainter *painter, const QCPFinancialDataContainer::const_iterator &begin, const QCPFinancialDataContainer::const_iterator &end, bool isSelected) { QCPAxis *keyAxis = mKeyAxis.data(); QCPAxis *valueAxis = mValueAxis.data(); if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; } - QVector lineData; - getPreparedData(&lineData, scatterData); - linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill - linePixelData->resize(lineData.size()*2); - - // calculate steps from lineData and transform to pixel coordinates: - if (keyAxis->orientation() == Qt::Vertical) + if (keyAxis->orientation() == Qt::Horizontal) { - double lastKey = keyAxis->coordToPixel(lineData.first().key); - double value; - for (int i=0; icoordToPixel(lineData.at(i).value); - (*linePixelData)[i*2+0].setX(value); - (*linePixelData)[i*2+0].setY(lastKey); - lastKey = keyAxis->coordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+1].setX(value); - (*linePixelData)[i*2+1].setY(lastKey); + if (isSelected && mSelectionDecorator) + mSelectionDecorator->applyPen(painter); + else if (mTwoColored) + painter->setPen(it->close >= it->open ? mPenPositive : mPenNegative); + else + painter->setPen(mPen); + double keyPixel = keyAxis->coordToPixel(it->key); + double openPixel = valueAxis->coordToPixel(it->open); + double closePixel = valueAxis->coordToPixel(it->close); + // draw backbone: + painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it->high)), QPointF(keyPixel, valueAxis->coordToPixel(it->low))); + // draw open: + double pixelWidth = getPixelWidth(it->key, keyPixel); // sign of this makes sure open/close are on correct sides + painter->drawLine(QPointF(keyPixel-pixelWidth, openPixel), QPointF(keyPixel, openPixel)); + // draw close: + painter->drawLine(QPointF(keyPixel, closePixel), QPointF(keyPixel+pixelWidth, closePixel)); } - } else // key axis is horizontal + } else { - double lastKey = keyAxis->coordToPixel(lineData.first().key); - double value; - for (int i=0; icoordToPixel(lineData.at(i).value); - (*linePixelData)[i*2+0].setX(lastKey); - (*linePixelData)[i*2+0].setY(value); - lastKey = keyAxis->coordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+1].setX(lastKey); - (*linePixelData)[i*2+1].setY(value); + if (isSelected && mSelectionDecorator) + mSelectionDecorator->applyPen(painter); + else if (mTwoColored) + painter->setPen(it->close >= it->open ? mPenPositive : mPenNegative); + else + painter->setPen(mPen); + double keyPixel = keyAxis->coordToPixel(it->key); + double openPixel = valueAxis->coordToPixel(it->open); + double closePixel = valueAxis->coordToPixel(it->close); + // draw backbone: + painter->drawLine(QPointF(valueAxis->coordToPixel(it->high), keyPixel), QPointF(valueAxis->coordToPixel(it->low), keyPixel)); + // draw open: + double pixelWidth = getPixelWidth(it->key, keyPixel); // sign of this makes sure open/close are on correct sides + painter->drawLine(QPointF(openPixel, keyPixel-pixelWidth), QPointF(openPixel, keyPixel)); + // draw close: + painter->drawLine(QPointF(closePixel, keyPixel), QPointF(closePixel, keyPixel+pixelWidth)); } } } -/*! - \internal - Places the raw data points needed for a step plot with centered steps in \a lineData. - - As for all plot data retrieval functions, \a scatterData just contains all unaltered data (scatter) - points that are visible for drawing scatter points, if necessary. If drawing scatter points is - disabled (i.e. the scatter style's shape is \ref QCPScatterStyle::ssNone), pass 0 as \a - scatterData, and the function will skip filling the vector. +/*! \internal - \see drawLinePlot + Draws the data from \a begin to \a end-1 as Candlesticks with the provided \a painter. + + This method is a helper function for \ref draw. It is used when the chart style is \ref csCandlestick. */ -void QCPGraph::getStepCenterPlotData(QVector *linePixelData, QVector *scatterData) const +void QCPFinancial::drawCandlestickPlot(QCPPainter *painter, const QCPFinancialDataContainer::const_iterator &begin, const QCPFinancialDataContainer::const_iterator &end, bool isSelected) { QCPAxis *keyAxis = mKeyAxis.data(); QCPAxis *valueAxis = mValueAxis.data(); if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as lineData"; return; } - QVector lineData; - getPreparedData(&lineData, scatterData); - linePixelData->reserve(lineData.size()*2+2); // added 2 to reserve memory for lower/upper fill base points that might be needed for fill - linePixelData->resize(lineData.size()*2); - // calculate steps from lineData and transform to pixel coordinates: - if (keyAxis->orientation() == Qt::Vertical) + if (keyAxis->orientation() == Qt::Horizontal) { - double lastKey = keyAxis->coordToPixel(lineData.first().key); - double lastValue = valueAxis->coordToPixel(lineData.first().value); - double key; - (*linePixelData)[0].setX(lastValue); - (*linePixelData)[0].setY(lastKey); - for (int i=1; icoordToPixel(lineData.at(i).key)+lastKey)*0.5; - (*linePixelData)[i*2-1].setX(lastValue); - (*linePixelData)[i*2-1].setY(key); - lastValue = valueAxis->coordToPixel(lineData.at(i).value); - lastKey = keyAxis->coordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+0].setX(lastValue); - (*linePixelData)[i*2+0].setY(key); - } - (*linePixelData)[lineData.size()*2-1].setX(lastValue); - (*linePixelData)[lineData.size()*2-1].setY(lastKey); - } else // key axis is horizontal + for (QCPFinancialDataContainer::const_iterator it = begin; it != end; ++it) + { + if (isSelected && mSelectionDecorator) + { + mSelectionDecorator->applyPen(painter); + mSelectionDecorator->applyBrush(painter); + } else if (mTwoColored) + { + painter->setPen(it->close >= it->open ? mPenPositive : mPenNegative); + painter->setBrush(it->close >= it->open ? mBrushPositive : mBrushNegative); + } else + { + painter->setPen(mPen); + painter->setBrush(mBrush); + } + double keyPixel = keyAxis->coordToPixel(it->key); + double openPixel = valueAxis->coordToPixel(it->open); + double closePixel = valueAxis->coordToPixel(it->close); + // draw high: + painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it->high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it->open, it->close)))); + // draw low: + painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it->low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it->open, it->close)))); + // draw open-close box: + double pixelWidth = getPixelWidth(it->key, keyPixel); + painter->drawRect(QRectF(QPointF(keyPixel-pixelWidth, closePixel), QPointF(keyPixel+pixelWidth, openPixel))); + } + } else // keyAxis->orientation() == Qt::Vertical { - double lastKey = keyAxis->coordToPixel(lineData.first().key); - double lastValue = valueAxis->coordToPixel(lineData.first().value); - double key; - (*linePixelData)[0].setX(lastKey); - (*linePixelData)[0].setY(lastValue); - for (int i=1; icoordToPixel(lineData.at(i).key)+lastKey)*0.5; - (*linePixelData)[i*2-1].setX(key); - (*linePixelData)[i*2-1].setY(lastValue); - lastValue = valueAxis->coordToPixel(lineData.at(i).value); - lastKey = keyAxis->coordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+0].setX(key); - (*linePixelData)[i*2+0].setY(lastValue); + if (isSelected && mSelectionDecorator) + { + mSelectionDecorator->applyPen(painter); + mSelectionDecorator->applyBrush(painter); + } else if (mTwoColored) + { + painter->setPen(it->close >= it->open ? mPenPositive : mPenNegative); + painter->setBrush(it->close >= it->open ? mBrushPositive : mBrushNegative); + } else + { + painter->setPen(mPen); + painter->setBrush(mBrush); + } + double keyPixel = keyAxis->coordToPixel(it->key); + double openPixel = valueAxis->coordToPixel(it->open); + double closePixel = valueAxis->coordToPixel(it->close); + // draw high: + painter->drawLine(QPointF(valueAxis->coordToPixel(it->high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it->open, it->close)), keyPixel)); + // draw low: + painter->drawLine(QPointF(valueAxis->coordToPixel(it->low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it->open, it->close)), keyPixel)); + // draw open-close box: + double pixelWidth = getPixelWidth(it->key, keyPixel); + painter->drawRect(QRectF(QPointF(closePixel, keyPixel-pixelWidth), QPointF(openPixel, keyPixel+pixelWidth))); } - (*linePixelData)[lineData.size()*2-1].setX(lastKey); - (*linePixelData)[lineData.size()*2-1].setY(lastValue); } - } -/*! - \internal - Places the raw data points needed for an impulse plot in \a lineData. +/*! \internal - As for all plot data retrieval functions, \a scatterData just contains all unaltered data (scatter) - points that are visible for drawing scatter points, if necessary. If drawing scatter points is - disabled (i.e. the scatter style's shape is \ref QCPScatterStyle::ssNone), pass 0 as \a - scatterData, and the function will skip filling the vector. - - \see drawImpulsePlot + This function is used to determine the width of the bar at coordinate \a key, according to the + specified width (\ref setWidth) and width type (\ref setWidthType). Provide the pixel position of + \a key in \a keyPixel (because usually this was already calculated via \ref QCPAxis::coordToPixel + when this function is called). + + It returns the number of pixels the bar extends to higher keys, relative to the \a key + coordinate. So with a non-reversed horizontal axis, the return value is positive. With a reversed + horizontal axis, the return value is negative. This is important so the open/close flags on the + \ref csOhlc bar are drawn to the correct side. */ -void QCPGraph::getImpulsePlotData(QVector *linePixelData, QVector *scatterData) const +double QCPFinancial::getPixelWidth(double key, double keyPixel) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (!linePixelData) { qDebug() << Q_FUNC_INFO << "null pointer passed as linePixelData"; return; } - - QVector lineData; - getPreparedData(&lineData, scatterData); - linePixelData->resize(lineData.size()*2); // no need to reserve 2 extra points because impulse plot has no fill - - // transform lineData points to pixels: - if (keyAxis->orientation() == Qt::Vertical) + double result = 0; + switch (mWidthType) { - double zeroPointX = valueAxis->coordToPixel(0); - double key; - for (int i=0; icoordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+0].setX(zeroPointX); - (*linePixelData)[i*2+0].setY(key); - (*linePixelData)[i*2+1].setX(valueAxis->coordToPixel(lineData.at(i).value)); - (*linePixelData)[i*2+1].setY(key); + if (mKeyAxis) + result = mWidth*0.5*mKeyAxis.data()->pixelOrientation(); + break; } - } else // key axis is horizontal - { - double zeroPointY = valueAxis->coordToPixel(0); - double key; - for (int i=0; iaxisRect()) + { + if (mKeyAxis.data()->orientation() == Qt::Horizontal) + result = mKeyAxis.data()->axisRect()->width()*mWidth*0.5*mKeyAxis.data()->pixelOrientation(); + else + result = mKeyAxis.data()->axisRect()->height()*mWidth*0.5*mKeyAxis.data()->pixelOrientation(); + } else + qDebug() << Q_FUNC_INFO << "No key axis or axis rect defined"; + break; + } + case wtPlotCoords: { - key = keyAxis->coordToPixel(lineData.at(i).key); - (*linePixelData)[i*2+0].setX(key); - (*linePixelData)[i*2+0].setY(zeroPointY); - (*linePixelData)[i*2+1].setX(key); - (*linePixelData)[i*2+1].setY(valueAxis->coordToPixel(lineData.at(i).value)); + if (mKeyAxis) + result = mKeyAxis.data()->coordToPixel(key+mWidth*0.5)-keyPixel; + else + qDebug() << Q_FUNC_INFO << "No key axis defined"; + break; } } + return result; } /*! \internal - - Draws the fill of the graph with the specified brush. - - If the fill is a normal fill towards the zero-value-line, only the \a lineData is required (and - two extra points at the zero-value-line, which are added by \ref addFillBasePoints and removed by - \ref removeFillBasePoints after the fill drawing is done). - - If the fill is a channel fill between this QCPGraph and another QCPGraph (mChannelFillGraph), the - more complex polygon is calculated with the \ref getChannelFillPolygon function. - - \see drawLinePlot -*/ -void QCPGraph::drawFill(QCPPainter *painter, QVector *lineData) const -{ - if (mLineStyle == lsImpulse) return; // fill doesn't make sense for impulse plot - if (mainBrush().style() == Qt::NoBrush || mainBrush().color().alpha() == 0) return; - - applyFillAntialiasingHint(painter); - if (!mChannelFillGraph) - { - // draw base fill under graph, fill goes all the way to the zero-value-line: - addFillBasePoints(lineData); - painter->setPen(Qt::NoPen); - painter->setBrush(mainBrush()); - painter->drawPolygon(QPolygonF(*lineData)); - removeFillBasePoints(lineData); - } else - { - // draw channel fill between this graph and mChannelFillGraph: - painter->setPen(Qt::NoPen); - painter->setBrush(mainBrush()); - painter->drawPolygon(getChannelFillPolygon(lineData)); - } -} -/*! \internal - - Draws scatter symbols at every data point passed in \a scatterData. scatter symbols are independent - of the line style and are always drawn if the scatter style's shape is not \ref - QCPScatterStyle::ssNone. Hence, the \a scatterData vector is outputted by all "get(...)PlotData" - functions, together with the (line style dependent) line data. + This method is a helper function for \ref selectTest. It is used to test for selection when the + chart style is \ref csOhlc. It only tests against the data points between \a begin and \a end. - \see drawLinePlot, drawImpulsePlot + Like \ref selectTest, this method returns the shortest distance of \a pos to the graphical + representation of the plottable, and \a closestDataPoint will point to the respective data point. */ -void QCPGraph::drawScatterPlot(QCPPainter *painter, QVector *scatterData) const +double QCPFinancial::ohlcSelectTest(const QPointF &pos, const QCPFinancialDataContainer::const_iterator &begin, const QCPFinancialDataContainer::const_iterator &end, QCPFinancialDataContainer::const_iterator &closestDataPoint) const { + closestDataPoint = mDataContainer->constEnd(); QCPAxis *keyAxis = mKeyAxis.data(); QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - // draw error bars: - if (mErrorType != etNone) - { - applyErrorBarsAntialiasingHint(painter); - painter->setPen(mErrorPen); - if (keyAxis->orientation() == Qt::Vertical) - { - for (int i=0; isize(); ++i) - drawError(painter, valueAxis->coordToPixel(scatterData->at(i).value), keyAxis->coordToPixel(scatterData->at(i).key), scatterData->at(i)); - } else - { - for (int i=0; isize(); ++i) - drawError(painter, keyAxis->coordToPixel(scatterData->at(i).key), valueAxis->coordToPixel(scatterData->at(i).value), scatterData->at(i)); - } - } - - // draw scatter point symbols: - applyScattersAntialiasingHint(painter); - mScatterStyle.applyTo(painter, mPen); - if (keyAxis->orientation() == Qt::Vertical) - { - for (int i=0; isize(); ++i) - if (!qIsNaN(scatterData->at(i).value)) - mScatterStyle.drawShape(painter, valueAxis->coordToPixel(scatterData->at(i).value), keyAxis->coordToPixel(scatterData->at(i).key)); - } else - { - for (int i=0; isize(); ++i) - if (!qIsNaN(scatterData->at(i).value)) - mScatterStyle.drawShape(painter, keyAxis->coordToPixel(scatterData->at(i).key), valueAxis->coordToPixel(scatterData->at(i).value)); - } -} + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } -/*! \internal - - Draws line graphs from the provided data. It connects all points in \a lineData, which was - created by one of the "get(...)PlotData" functions for line styles that require simple line - connections between the point vector they create. These are for example \ref getLinePlotData, - \ref getStepLeftPlotData, \ref getStepRightPlotData and \ref getStepCenterPlotData. - - \see drawScatterPlot, drawImpulsePlot -*/ -void QCPGraph::drawLinePlot(QCPPainter *painter, QVector *lineData) const -{ - // draw line of graph: - if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0) + double minDistSqr = (std::numeric_limits::max)(); + if (keyAxis->orientation() == Qt::Horizontal) { - applyDefaultAntialiasingHint(painter); - painter->setPen(mainPen()); - painter->setBrush(Qt::NoBrush); - - /* Draws polyline in batches, currently not used: - int p = 0; - while (p < lineData->size()) + for (QCPFinancialDataContainer::const_iterator it=begin; it!=end; ++it) { - int batch = qMin(25, lineData->size()-p); - if (p != 0) + double keyPixel = keyAxis->coordToPixel(it->key); + // calculate distance to backbone: + double currentDistSqr = QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(keyPixel, valueAxis->coordToPixel(it->high)), QCPVector2D(keyPixel, valueAxis->coordToPixel(it->low))); + if (currentDistSqr < minDistSqr) { - ++batch; - --p; // to draw the connection lines between two batches + minDistSqr = currentDistSqr; + closestDataPoint = it; } - painter->drawPolyline(lineData->constData()+p, batch); - p += batch; } - */ - - // if drawing solid line and not in PDF, use much faster line drawing instead of polyline: - if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) && - painter->pen().style() == Qt::SolidLine && - !painter->modes().testFlag(QCPPainter::pmVectorized) && - !painter->modes().testFlag(QCPPainter::pmNoCaching)) - { - int i = 0; - bool lastIsNan = false; - const int lineDataSize = lineData->size(); - while (i < lineDataSize && (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x()))) // make sure first point is not NaN - ++i; - ++i; // because drawing works in 1 point retrospect - while (i < lineDataSize) - { - if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line - { - if (!lastIsNan) - painter->drawLine(lineData->at(i-1), lineData->at(i)); - else - lastIsNan = false; - } else - lastIsNan = true; - ++i; - } - } else + } else // keyAxis->orientation() == Qt::Vertical + { + for (QCPFinancialDataContainer::const_iterator it=begin; it!=end; ++it) { - int segmentStart = 0; - int i = 0; - const int lineDataSize = lineData->size(); - while (i < lineDataSize) + double keyPixel = keyAxis->coordToPixel(it->key); + // calculate distance to backbone: + double currentDistSqr = QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(valueAxis->coordToPixel(it->high), keyPixel), QCPVector2D(valueAxis->coordToPixel(it->low), keyPixel)); + if (currentDistSqr < minDistSqr) { - if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line - { - painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point - segmentStart = i+1; - } - ++i; + minDistSqr = currentDistSqr; + closestDataPoint = it; } - // draw last segment: - painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart); } } + return qSqrt(minDistSqr); } /*! \internal - Draws impulses from the provided data, i.e. it connects all line pairs in \a lineData, which was - created by \ref getImpulsePlotData. - - \see drawScatterPlot, drawLinePlot -*/ -void QCPGraph::drawImpulsePlot(QCPPainter *painter, QVector *lineData) const -{ - // draw impulses: - if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0) - { - applyDefaultAntialiasingHint(painter); - QPen pen = mainPen(); - pen.setCapStyle(Qt::FlatCap); // so impulse line doesn't reach beyond zero-line - painter->setPen(pen); - painter->setBrush(Qt::NoBrush); - painter->drawLines(*lineData); - } -} - -/*! \internal - - Returns the \a lineData and \a scatterData that need to be plotted for this graph taking into - consideration the current axis ranges and, if \ref setAdaptiveSampling is enabled, local point - densities. - - 0 may be passed as \a lineData or \a scatterData to indicate that the respective dataset isn't - needed. For example, if the scatter style (\ref setScatterStyle) is \ref QCPScatterStyle::ssNone, \a - scatterData should be 0 to prevent unnecessary calculations. + This method is a helper function for \ref selectTest. It is used to test for selection when the + chart style is \ref csCandlestick. It only tests against the data points between \a begin and \a + end. - This method is used by the various "get(...)PlotData" methods to get the basic working set of data. + Like \ref selectTest, this method returns the shortest distance of \a pos to the graphical + representation of the plottable, and \a closestDataPoint will point to the respective data point. */ -void QCPGraph::getPreparedData(QVector *lineData, QVector *scatterData) const +double QCPFinancial::candlestickSelectTest(const QPointF &pos, const QCPFinancialDataContainer::const_iterator &begin, const QCPFinancialDataContainer::const_iterator &end, QCPFinancialDataContainer::const_iterator &closestDataPoint) const { + closestDataPoint = mDataContainer->constEnd(); QCPAxis *keyAxis = mKeyAxis.data(); QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - // get visible data range: - QCPDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point - getVisibleDataBounds(lower, upper); - if (lower == mData->constEnd() || upper == mData->constEnd()) - return; - - // count points in visible range, taking into account that we only need to count to the limit maxCount if using adaptive sampling: - int maxCount = std::numeric_limits::max(); - if (mAdaptiveSampling) - { - int keyPixelSpan = qAbs(keyAxis->coordToPixel(lower.key())-keyAxis->coordToPixel(upper.key())); - maxCount = 2*keyPixelSpan+2; - } - int dataCount = countDataInBounds(lower, upper, maxCount); - - if (mAdaptiveSampling && dataCount >= maxCount) // use adaptive sampling only if there are at least two points per pixel on average + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } + + double minDistSqr = (std::numeric_limits::max)(); + if (keyAxis->orientation() == Qt::Horizontal) { - if (lineData) - { - QCPDataMap::const_iterator it = lower; - QCPDataMap::const_iterator upperEnd = upper+1; - double minValue = it.value().value; - double maxValue = it.value().value; - QCPDataMap::const_iterator currentIntervalFirstPoint = it; - int reversedFactor = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction - int reversedRound = keyAxis->rangeReversed() != (keyAxis->orientation()==Qt::Vertical) ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey - double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(lower.key())+reversedRound)); - double lastIntervalEndKey = currentIntervalStartKey; - double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates - bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes) - int intervalDataCount = 1; - ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect - while (it != upperEnd) - { - if (it.key() < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this cluster if necessary - { - if (it.value().value < minValue) - minValue = it.value().value; - else if (it.value().value > maxValue) - maxValue = it.value().value; - ++intervalDataCount; - } else // new pixel interval started - { - if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster - { - if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point is further away, so first point of this cluster must be at a real data point - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value)); - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue)); - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue)); - if (it.key() > currentIntervalStartKey+keyEpsilon*2) // new pixel started further away from previous cluster, so make sure the last point of the cluster is at a real data point - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.8, (it-1).value().value)); - } else - lineData->append(QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value)); - lastIntervalEndKey = (it-1).value().key; - minValue = it.value().value; - maxValue = it.value().value; - currentIntervalFirstPoint = it; - currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(it.key())+reversedRound)); - if (keyEpsilonVariable) - keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); - intervalDataCount = 1; - } - ++it; - } - // handle last interval: - if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them to a cluster + for (QCPFinancialDataContainer::const_iterator it=begin; it!=end; ++it) + { + double currentDistSqr; + // determine whether pos is in open-close-box: + QCPRange boxKeyRange(it->key-mWidth*0.5, it->key+mWidth*0.5); + QCPRange boxValueRange(it->close, it->open); + double posKey, posValue; + pixelsToCoords(pos, posKey, posValue); + if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box { - if (lastIntervalEndKey < currentIntervalStartKey-keyEpsilon) // last point wasn't a cluster, so first point of this cluster must be at a real data point - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.2, currentIntervalFirstPoint.value().value)); - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.25, minValue)); - lineData->append(QCPData(currentIntervalStartKey+keyEpsilon*0.75, maxValue)); + currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99; } else - lineData->append(QCPData(currentIntervalFirstPoint.key(), currentIntervalFirstPoint.value().value)); - } - - if (scatterData) - { - double valueMaxRange = valueAxis->range().upper; - double valueMinRange = valueAxis->range().lower; - QCPDataMap::const_iterator it = lower; - QCPDataMap::const_iterator upperEnd = upper+1; - double minValue = it.value().value; - double maxValue = it.value().value; - QCPDataMap::const_iterator minValueIt = it; - QCPDataMap::const_iterator maxValueIt = it; - QCPDataMap::const_iterator currentIntervalStart = it; - int reversedFactor = keyAxis->rangeReversed() ? -1 : 1; // is used to calculate keyEpsilon pixel into the correct direction - int reversedRound = keyAxis->rangeReversed() ? 1 : 0; // is used to switch between floor (normal) and ceil (reversed) rounding of currentIntervalStartKey - double currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(lower.key())+reversedRound)); - double keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); // interval of one pixel on screen when mapped to plot key coordinates - bool keyEpsilonVariable = keyAxis->scaleType() == QCPAxis::stLogarithmic; // indicates whether keyEpsilon needs to be updated after every interval (for log axes) - int intervalDataCount = 1; - ++it; // advance iterator to second data point because adaptive sampling works in 1 point retrospect - while (it != upperEnd) { - if (it.key() < currentIntervalStartKey+keyEpsilon) // data point is still within same pixel, so skip it and expand value span of this pixel if necessary - { - if (it.value().value < minValue && it.value().value > valueMinRange && it.value().value < valueMaxRange) - { - minValue = it.value().value; - minValueIt = it; - } else if (it.value().value > maxValue && it.value().value > valueMinRange && it.value().value < valueMaxRange) - { - maxValue = it.value().value; - maxValueIt = it; - } - ++intervalDataCount; - } else // new pixel started - { - if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them - { - // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): - double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); - int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average - QCPDataMap::const_iterator intervalIt = currentIntervalStart; - int c = 0; - while (intervalIt != it) - { - if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange) - scatterData->append(intervalIt.value()); - ++c; - ++intervalIt; - } - } else if (currentIntervalStart.value().value > valueMinRange && currentIntervalStart.value().value < valueMaxRange) - scatterData->append(currentIntervalStart.value()); - minValue = it.value().value; - maxValue = it.value().value; - currentIntervalStart = it; - currentIntervalStartKey = keyAxis->pixelToCoord((int)(keyAxis->coordToPixel(it.key())+reversedRound)); - if (keyEpsilonVariable) - keyEpsilon = qAbs(currentIntervalStartKey-keyAxis->pixelToCoord(keyAxis->coordToPixel(currentIntervalStartKey)+1.0*reversedFactor)); - intervalDataCount = 1; - } - ++it; + // calculate distance to high/low lines: + double keyPixel = keyAxis->coordToPixel(it->key); + double highLineDistSqr = QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(keyPixel, valueAxis->coordToPixel(it->high)), QCPVector2D(keyPixel, valueAxis->coordToPixel(qMax(it->open, it->close)))); + double lowLineDistSqr = QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(keyPixel, valueAxis->coordToPixel(it->low)), QCPVector2D(keyPixel, valueAxis->coordToPixel(qMin(it->open, it->close)))); + currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr); } - // handle last interval: - if (intervalDataCount >= 2) // last pixel had multiple data points, consolidate them - { - // determine value pixel span and add as many points in interval to maintain certain vertical data density (this is specific to scatter plot): - double valuePixelSpan = qAbs(valueAxis->coordToPixel(minValue)-valueAxis->coordToPixel(maxValue)); - int dataModulo = qMax(1, qRound(intervalDataCount/(valuePixelSpan/4.0))); // approximately every 4 value pixels one data point on average - QCPDataMap::const_iterator intervalIt = currentIntervalStart; - int c = 0; - while (intervalIt != it) - { - if ((c % dataModulo == 0 || intervalIt == minValueIt || intervalIt == maxValueIt) && intervalIt.value().value > valueMinRange && intervalIt.value().value < valueMaxRange) - scatterData->append(intervalIt.value()); - ++c; - ++intervalIt; - } - } else if (currentIntervalStart.value().value > valueMinRange && currentIntervalStart.value().value < valueMaxRange) - scatterData->append(currentIntervalStart.value()); - } - } else // don't use adaptive sampling algorithm, transfer points one-to-one from the map into the output parameters - { - QVector *dataVector = 0; - if (lineData) - dataVector = lineData; - else if (scatterData) - dataVector = scatterData; - if (dataVector) - { - QCPDataMap::const_iterator it = lower; - QCPDataMap::const_iterator upperEnd = upper+1; - dataVector->reserve(dataCount+2); // +2 for possible fill end points - while (it != upperEnd) + if (currentDistSqr < minDistSqr) { - dataVector->append(it.value()); - ++it; + minDistSqr = currentDistSqr; + closestDataPoint = it; } } - if (lineData && scatterData) - *scatterData = *dataVector; - } -} - -/*! \internal - - called by the scatter drawing function (\ref drawScatterPlot) to draw the error bars on one data - point. \a x and \a y pixel positions of the data point are passed since they are already known in - pixel coordinates in the drawing function, so we save some extra coordToPixel transforms here. \a - data is therefore only used for the errors, not key and value. -*/ -void QCPGraph::drawError(QCPPainter *painter, double x, double y, const QCPData &data) const -{ - if (qIsNaN(data.value)) - return; - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - double a, b; // positions of error bar bounds in pixels - double barWidthHalf = mErrorBarSize*0.5; - double skipSymbolMargin = mScatterStyle.size(); // pixels left blank per side, when mErrorBarSkipSymbol is true - - if (keyAxis->orientation() == Qt::Vertical) + } else // keyAxis->orientation() == Qt::Vertical { - // draw key error vertically and value error horizontally - if (mErrorType == etKey || mErrorType == etBoth) + for (QCPFinancialDataContainer::const_iterator it=begin; it!=end; ++it) { - a = keyAxis->coordToPixel(data.key-data.keyErrorMinus); - b = keyAxis->coordToPixel(data.key+data.keyErrorPlus); - if (keyAxis->rangeReversed()) - qSwap(a,b); - // draw spine: - if (mErrorBarSkipSymbol) - { - if (a-y > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin - painter->drawLine(QLineF(x, a, x, y+skipSymbolMargin)); - if (y-b > skipSymbolMargin) - painter->drawLine(QLineF(x, y-skipSymbolMargin, x, b)); - } else - painter->drawLine(QLineF(x, a, x, b)); - // draw handles: - painter->drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a)); - painter->drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b)); - } - if (mErrorType == etValue || mErrorType == etBoth) - { - a = valueAxis->coordToPixel(data.value-data.valueErrorMinus); - b = valueAxis->coordToPixel(data.value+data.valueErrorPlus); - if (valueAxis->rangeReversed()) - qSwap(a,b); - // draw spine: - if (mErrorBarSkipSymbol) + double currentDistSqr; + // determine whether pos is in open-close-box: + QCPRange boxKeyRange(it->key-mWidth*0.5, it->key+mWidth*0.5); + QCPRange boxValueRange(it->close, it->open); + double posKey, posValue; + pixelsToCoords(pos, posKey, posValue); + if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box { - if (x-a > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin - painter->drawLine(QLineF(a, y, x-skipSymbolMargin, y)); - if (b-x > skipSymbolMargin) - painter->drawLine(QLineF(x+skipSymbolMargin, y, b, y)); + currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99; } else - painter->drawLine(QLineF(a, y, b, y)); - // draw handles: - painter->drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf)); - painter->drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf)); - } - } else // mKeyAxis->orientation() is Qt::Horizontal - { - // draw value error vertically and key error horizontally - if (mErrorType == etKey || mErrorType == etBoth) - { - a = keyAxis->coordToPixel(data.key-data.keyErrorMinus); - b = keyAxis->coordToPixel(data.key+data.keyErrorPlus); - if (keyAxis->rangeReversed()) - qSwap(a,b); - // draw spine: - if (mErrorBarSkipSymbol) { - if (x-a > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin - painter->drawLine(QLineF(a, y, x-skipSymbolMargin, y)); - if (b-x > skipSymbolMargin) - painter->drawLine(QLineF(x+skipSymbolMargin, y, b, y)); - } else - painter->drawLine(QLineF(a, y, b, y)); - // draw handles: - painter->drawLine(QLineF(a, y-barWidthHalf, a, y+barWidthHalf)); - painter->drawLine(QLineF(b, y-barWidthHalf, b, y+barWidthHalf)); - } - if (mErrorType == etValue || mErrorType == etBoth) - { - a = valueAxis->coordToPixel(data.value-data.valueErrorMinus); - b = valueAxis->coordToPixel(data.value+data.valueErrorPlus); - if (valueAxis->rangeReversed()) - qSwap(a,b); - // draw spine: - if (mErrorBarSkipSymbol) + // calculate distance to high/low lines: + double keyPixel = keyAxis->coordToPixel(it->key); + double highLineDistSqr = QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(valueAxis->coordToPixel(it->high), keyPixel), QCPVector2D(valueAxis->coordToPixel(qMax(it->open, it->close)), keyPixel)); + double lowLineDistSqr = QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(valueAxis->coordToPixel(it->low), keyPixel), QCPVector2D(valueAxis->coordToPixel(qMin(it->open, it->close)), keyPixel)); + currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr); + } + if (currentDistSqr < minDistSqr) { - if (a-y > skipSymbolMargin) // don't draw spine if error is so small it's within skipSymbolmargin - painter->drawLine(QLineF(x, a, x, y+skipSymbolMargin)); - if (y-b > skipSymbolMargin) - painter->drawLine(QLineF(x, y-skipSymbolMargin, x, b)); - } else - painter->drawLine(QLineF(x, a, x, b)); - // draw handles: - painter->drawLine(QLineF(x-barWidthHalf, a, x+barWidthHalf, a)); - painter->drawLine(QLineF(x-barWidthHalf, b, x+barWidthHalf, b)); + minDistSqr = currentDistSqr; + closestDataPoint = it; + } } } + return qSqrt(minDistSqr); } -/*! \internal +/*! \internal - called by \ref getPreparedData to determine which data (key) range is visible at the current key + called by the drawing methods to determine which data (key) range is visible at the current key axis range setting, so only that needs to be processed. - \a lower returns an iterator to the lowest data point that needs to be taken into account when + \a begin returns an iterator to the lowest data point that needs to be taken into account when plotting. Note that in order to get a clean plot all the way to the edge of the axis rect, \a - lower may still be just outside the visible range. + begin may still be just outside the visible range. - \a upper returns an iterator to the highest data point. Same as before, \a upper may also lie - just outside of the visible range. + \a end returns the iterator just above the highest data point that needs to be taken into + account. Same as before, \a end may also lie just outside of the visible range - if the graph contains no data, both \a lower and \a upper point to constEnd. + if the plottable contains no data, both \a begin and \a end point to \c constEnd. */ -void QCPGraph::getVisibleDataBounds(QCPDataMap::const_iterator &lower, QCPDataMap::const_iterator &upper) const +void QCPFinancial::getVisibleDataBounds(QCPFinancialDataContainer::const_iterator &begin, QCPFinancialDataContainer::const_iterator &end) const { - if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } - if (mData->isEmpty()) + if (!mKeyAxis) { - lower = mData->constEnd(); - upper = mData->constEnd(); + qDebug() << Q_FUNC_INFO << "invalid key axis"; + begin = mDataContainer->constEnd(); + end = mDataContainer->constEnd(); return; } - - // get visible data range as QMap iterators - QCPDataMap::const_iterator lbound = mData->lowerBound(mKeyAxis.data()->range().lower); - QCPDataMap::const_iterator ubound = mData->upperBound(mKeyAxis.data()->range().upper); - bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range - bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range - - lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn - upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn + begin = mDataContainer->findBegin(mKeyAxis.data()->range().lower-mWidth*0.5); // subtract half width of ohlc/candlestick to include partially visible data points + end = mDataContainer->findEnd(mKeyAxis.data()->range().upper+mWidth*0.5); // add half width of ohlc/candlestick to include partially visible data points } /*! \internal + + Returns the hit box in pixel coordinates that will be used for data selection with the selection + rect (\ref selectTestRect), of the data point given by \a it. +*/ +QRectF QCPFinancial::selectionHitBox(QCPFinancialDataContainer::const_iterator it) const +{ + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return {}; } - Counts the number of data points between \a lower and \a upper (including them), up to a maximum - of \a maxCount. - - This function is used by \ref getPreparedData to determine whether adaptive sampling shall be - used (if enabled via \ref setAdaptiveSampling) or not. This is also why counting of data points - only needs to be done until \a maxCount is reached, which should be set to the number of data - points at which adaptive sampling sets in. + double keyPixel = keyAxis->coordToPixel(it->key); + double highPixel = valueAxis->coordToPixel(it->high); + double lowPixel = valueAxis->coordToPixel(it->low); + double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it->key-mWidth*0.5); + if (keyAxis->orientation() == Qt::Horizontal) + return QRectF(keyPixel-keyWidthPixels, highPixel, keyWidthPixels*2, lowPixel-highPixel).normalized(); + else + return QRectF(highPixel, keyPixel-keyWidthPixels, lowPixel-highPixel, keyWidthPixels*2).normalized(); +} +/* end of 'src/plottables/plottable-financial.cpp' */ + + +/* including file 'src/plottables/plottable-errorbar.cpp' */ +/* modified 2022-11-06T12:45:56, size 37679 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPErrorBarsData +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPErrorBarsData + \brief Holds the data of one single error bar for QCPErrorBars. + + The stored data is: + \li \a errorMinus: how much the error bar extends towards negative coordinates from the data + point position + \li \a errorPlus: how much the error bar extends towards positive coordinates from the data point + position + + The container for storing the error bar information is \ref QCPErrorBarsDataContainer. It is a + typedef for QVector<\ref QCPErrorBarsData>. + + \see QCPErrorBarsDataContainer +*/ + +/*! + Constructs an error bar with errors set to zero. */ -int QCPGraph::countDataInBounds(const QCPDataMap::const_iterator &lower, const QCPDataMap::const_iterator &upper, int maxCount) const +QCPErrorBarsData::QCPErrorBarsData() : + errorMinus(0), + errorPlus(0) { - if (upper == mData->constEnd() && lower == mData->constEnd()) - return 0; - QCPDataMap::const_iterator it = lower; - int count = 1; - while (it != upper && count < maxCount) - { - ++it; - ++count; - } - return count; } -/*! \internal - - The line data vector generated by e.g. getLinePlotData contains only the line that connects the - data points. If the graph needs to be filled, two additional points need to be added at the - value-zero-line in the lower and upper key positions of the graph. This function calculates these - points and adds them to the end of \a lineData. Since the fill is typically drawn before the line - stroke, these added points need to be removed again after the fill is done, with the - removeFillBasePoints function. - - The expanding of \a lineData by two points will not cause unnecessary memory reallocations, - because the data vector generation functions (getLinePlotData etc.) reserve two extra points when - they allocate memory for \a lineData. - - \see removeFillBasePoints, lowerFillBasePoint, upperFillBasePoint +/*! + Constructs an error bar with equal \a error in both negative and positive direction. */ -void QCPGraph::addFillBasePoints(QVector *lineData) const +QCPErrorBarsData::QCPErrorBarsData(double error) : + errorMinus(error), + errorPlus(error) { - if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } - - // append points that close the polygon fill at the key axis: - if (mKeyAxis.data()->orientation() == Qt::Vertical) - { - *lineData << upperFillBasePoint(lineData->last().y()); - *lineData << lowerFillBasePoint(lineData->first().y()); - } else - { - *lineData << upperFillBasePoint(lineData->last().x()); - *lineData << lowerFillBasePoint(lineData->first().x()); - } } -/*! \internal - - removes the two points from \a lineData that were added by \ref addFillBasePoints. - - \see addFillBasePoints, lowerFillBasePoint, upperFillBasePoint +/*! + Constructs an error bar with negative and positive errors set to \a errorMinus and \a errorPlus, + respectively. */ -void QCPGraph::removeFillBasePoints(QVector *lineData) const +QCPErrorBarsData::QCPErrorBarsData(double errorMinus, double errorPlus) : + errorMinus(errorMinus), + errorPlus(errorPlus) { - lineData->remove(lineData->size()-2, 2); } -/*! \internal - - called by \ref addFillBasePoints to conveniently assign the point which closes the fill polygon - on the lower side of the zero-value-line parallel to the key axis. The logarithmic axis scale - case is a bit special, since the zero-value-line in pixel coordinates is in positive or negative - infinity. So this case is handled separately by just closing the fill polygon on the axis which - lies in the direction towards the zero value. - - \a lowerKey will be the the key (in pixels) of the returned point. Depending on whether the key - axis is horizontal or vertical, \a lowerKey will end up as the x or y value of the returned - point, respectively. - - \see upperFillBasePoint, addFillBasePoints + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPErrorBars +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPErrorBars + \brief A plottable that adds a set of error bars to other plottables. + + \image html QCPErrorBars.png + + The \ref QCPErrorBars plottable can be attached to other one-dimensional plottables (e.g. \ref + QCPGraph, \ref QCPCurve, \ref QCPBars, etc.) and equips them with error bars. + + Use \ref setDataPlottable to define for which plottable the \ref QCPErrorBars shall display the + error bars. The orientation of the error bars can be controlled with \ref setErrorType. + + By using \ref setData, you can supply the actual error data, either as symmetric error or + plus/minus asymmetric errors. \ref QCPErrorBars only stores the error data. The absolute + key/value position of each error bar will be adopted from the configured data plottable. The + error data of the \ref QCPErrorBars are associated one-to-one via their index to the data points + of the data plottable. You can directly access and manipulate the error bar data via \ref data. + + Set either of the plus/minus errors to NaN (qQNaN() or + std::numeric_limits::quiet_NaN()) to not show the respective error bar on the data point at + that index. + + \section qcperrorbars-appearance Changing the appearance + + The appearance of the error bars is defined by the pen (\ref setPen), and the width of the + whiskers (\ref setWhiskerWidth). Further, the error bar backbones may leave a gap around the data + point center to prevent that error bars are drawn too close to or even through scatter points. + This gap size can be controlled via \ref setSymbolGap. +*/ + +/* start of documentation of inline functions */ + +/*! \fn QSharedPointer QCPErrorBars::data() const + + Returns a shared pointer to the internal data storage of type \ref QCPErrorBarsDataContainer. You + may use it to directly manipulate the error values, which may be more convenient and faster than + using the regular \ref setData methods. +*/ + +/* end of documentation of inline functions */ + +/*! + Constructs an error bars plottable which uses \a keyAxis as its key axis ("x") and \a valueAxis as its value + axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and not have + the same orientation. If either of these restrictions is violated, a corresponding message is + printed to the debug output (qDebug), the construction is not aborted, though. + + It is also important that the \a keyAxis and \a valueAxis are the same for the error bars + plottable and the data plottable that the error bars shall be drawn on (\ref setDataPlottable). + + The created \ref QCPErrorBars is automatically registered with the QCustomPlot instance inferred + from \a keyAxis. This QCustomPlot instance takes ownership of the \ref QCPErrorBars, so do not + delete it manually but use \ref QCustomPlot::removePlottable() instead. */ -QPointF QCPGraph::lowerFillBasePoint(double lowerKey) const +QCPErrorBars::QCPErrorBars(QCPAxis *keyAxis, QCPAxis *valueAxis) : + QCPAbstractPlottable(keyAxis, valueAxis), + mDataContainer(new QVector), + mErrorType(etValueError), + mWhiskerWidth(9), + mSymbolGap(10) { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); } - - QPointF point; - if (valueAxis->scaleType() == QCPAxis::stLinear) - { - if (keyAxis->axisType() == QCPAxis::atLeft) - { - point.setX(valueAxis->coordToPixel(0)); - point.setY(lowerKey); - } else if (keyAxis->axisType() == QCPAxis::atRight) - { - point.setX(valueAxis->coordToPixel(0)); - point.setY(lowerKey); - } else if (keyAxis->axisType() == QCPAxis::atTop) - { - point.setX(lowerKey); - point.setY(valueAxis->coordToPixel(0)); - } else if (keyAxis->axisType() == QCPAxis::atBottom) - { - point.setX(lowerKey); - point.setY(valueAxis->coordToPixel(0)); - } - } else // valueAxis->mScaleType == QCPAxis::stLogarithmic - { - // In logarithmic scaling we can't just draw to value zero so we just fill all the way - // to the axis which is in the direction towards zero - if (keyAxis->orientation() == Qt::Vertical) - { - if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || - (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis - point.setX(keyAxis->axisRect()->right()); - else - point.setX(keyAxis->axisRect()->left()); - point.setY(lowerKey); - } else if (keyAxis->axisType() == QCPAxis::atTop || keyAxis->axisType() == QCPAxis::atBottom) - { - point.setX(lowerKey); - if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || - (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis - point.setY(keyAxis->axisRect()->top()); - else - point.setY(keyAxis->axisRect()->bottom()); - } - } - return point; + setPen(QPen(Qt::black, 0)); + setBrush(Qt::NoBrush); } -/*! \internal - - called by \ref addFillBasePoints to conveniently assign the point which closes the fill - polygon on the upper side of the zero-value-line parallel to the key axis. The logarithmic axis - scale case is a bit special, since the zero-value-line in pixel coordinates is in positive or - negative infinity. So this case is handled separately by just closing the fill polygon on the - axis which lies in the direction towards the zero value. +QCPErrorBars::~QCPErrorBars() +{ +} - \a upperKey will be the the key (in pixels) of the returned point. Depending on whether the key - axis is horizontal or vertical, \a upperKey will end up as the x or y value of the returned - point, respectively. - - \see lowerFillBasePoint, addFillBasePoints +/*! \overload + + Replaces the current data container with the provided \a data container. + + Since a QSharedPointer is used, multiple \ref QCPErrorBars instances may share the same data + container safely. Modifying the data in the container will then affect all \ref QCPErrorBars + instances that share the container. Sharing can be achieved by simply exchanging the data + containers wrapped in shared pointers: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcperrorbars-datasharing-1 + + If you do not wish to share containers, but create a copy from an existing container, assign the + data containers directly: + \snippet documentation/doc-code-snippets/mainwindow.cpp qcperrorbars-datasharing-2 + (This uses different notation compared with other plottables, because the \ref QCPErrorBars + uses a \c QVector as its data container, instead of a \ref QCPDataContainer.) + + \see addData */ -QPointF QCPGraph::upperFillBasePoint(double upperKey) const +void QCPErrorBars::setData(QSharedPointer data) { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPointF(); } - - QPointF point; - if (valueAxis->scaleType() == QCPAxis::stLinear) - { - if (keyAxis->axisType() == QCPAxis::atLeft) - { - point.setX(valueAxis->coordToPixel(0)); - point.setY(upperKey); - } else if (keyAxis->axisType() == QCPAxis::atRight) - { - point.setX(valueAxis->coordToPixel(0)); - point.setY(upperKey); - } else if (keyAxis->axisType() == QCPAxis::atTop) - { - point.setX(upperKey); - point.setY(valueAxis->coordToPixel(0)); - } else if (keyAxis->axisType() == QCPAxis::atBottom) - { - point.setX(upperKey); - point.setY(valueAxis->coordToPixel(0)); - } - } else // valueAxis->mScaleType == QCPAxis::stLogarithmic - { - // In logarithmic scaling we can't just draw to value 0 so we just fill all the way - // to the axis which is in the direction towards 0 - if (keyAxis->orientation() == Qt::Vertical) - { - if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || - (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis - point.setX(keyAxis->axisRect()->right()); - else - point.setX(keyAxis->axisRect()->left()); - point.setY(upperKey); - } else if (keyAxis->axisType() == QCPAxis::atTop || keyAxis->axisType() == QCPAxis::atBottom) - { - point.setX(upperKey); - if ((valueAxis->range().upper < 0 && !valueAxis->rangeReversed()) || - (valueAxis->range().upper > 0 && valueAxis->rangeReversed())) // if range is negative, zero is on opposite side of key axis - point.setY(keyAxis->axisRect()->top()); - else - point.setY(keyAxis->axisRect()->bottom()); - } - } - return point; + mDataContainer = data; } -/*! \internal - - Generates the polygon needed for drawing channel fills between this graph (data passed via \a - lineData) and the graph specified by mChannelFillGraph (data generated by calling its \ref - getPlotData function). May return an empty polygon if the key ranges have no overlap or fill - target graph and this graph don't have same orientation (i.e. both key axes horizontal or both - key axes vertical). For increased performance (due to implicit sharing), keep the returned - QPolygonF const. +/*! \overload + + Sets symmetrical error values as specified in \a error. The errors will be associated one-to-one + by the data point index to the associated data plottable (\ref setDataPlottable). + + You can directly access and manipulate the error bar data via \ref data. + + \see addData */ -const QPolygonF QCPGraph::getChannelFillPolygon(const QVector *lineData) const +void QCPErrorBars::setData(const QVector &error) { - if (!mChannelFillGraph) - return QPolygonF(); - - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); } - if (!mChannelFillGraph.data()->mKeyAxis) { qDebug() << Q_FUNC_INFO << "channel fill target key axis invalid"; return QPolygonF(); } - - if (mChannelFillGraph.data()->mKeyAxis.data()->orientation() != keyAxis->orientation()) - return QPolygonF(); // don't have same axis orientation, can't fill that (Note: if keyAxis fits, valueAxis will fit too, because it's always orthogonal to keyAxis) - - if (lineData->isEmpty()) return QPolygonF(); - QVector otherData; - mChannelFillGraph.data()->getPlotData(&otherData, 0); - if (otherData.isEmpty()) return QPolygonF(); - QVector thisData; - thisData.reserve(lineData->size()+otherData.size()); // because we will join both vectors at end of this function - for (int i=0; isize(); ++i) // don't use the vector<<(vector), it squeezes internally, which ruins the performance tuning with reserve() - thisData << lineData->at(i); - - // pointers to be able to swap them, depending which data range needs cropping: - QVector *staticData = &thisData; - QVector *croppedData = &otherData; - - // crop both vectors to ranges in which the keys overlap (which coord is key, depends on axisType): - if (keyAxis->orientation() == Qt::Horizontal) - { - // x is key - // if an axis range is reversed, the data point keys will be descending. Reverse them, since following algorithm assumes ascending keys: - if (staticData->first().x() > staticData->last().x()) - { - int size = staticData->size(); - for (int i=0; ifirst().x() > croppedData->last().x()) - { - int size = croppedData->size(); - for (int i=0; ifirst().x() < croppedData->first().x()) // other one must be cropped - qSwap(staticData, croppedData); - int lowBound = findIndexBelowX(croppedData, staticData->first().x()); - if (lowBound == -1) return QPolygonF(); // key ranges have no overlap - croppedData->remove(0, lowBound); - // set lowest point of cropped data to fit exactly key position of first static data - // point via linear interpolation: - if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation - double slope; - if (croppedData->at(1).x()-croppedData->at(0).x() != 0) - slope = (croppedData->at(1).y()-croppedData->at(0).y())/(croppedData->at(1).x()-croppedData->at(0).x()); - else - slope = 0; - (*croppedData)[0].setY(croppedData->at(0).y()+slope*(staticData->first().x()-croppedData->at(0).x())); - (*croppedData)[0].setX(staticData->first().x()); - - // crop upper bound: - if (staticData->last().x() > croppedData->last().x()) // other one must be cropped - qSwap(staticData, croppedData); - int highBound = findIndexAboveX(croppedData, staticData->last().x()); - if (highBound == -1) return QPolygonF(); // key ranges have no overlap - croppedData->remove(highBound+1, croppedData->size()-(highBound+1)); - // set highest point of cropped data to fit exactly key position of last static data - // point via linear interpolation: - if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation - int li = croppedData->size()-1; // last index - if (croppedData->at(li).x()-croppedData->at(li-1).x() != 0) - slope = (croppedData->at(li).y()-croppedData->at(li-1).y())/(croppedData->at(li).x()-croppedData->at(li-1).x()); - else - slope = 0; - (*croppedData)[li].setY(croppedData->at(li-1).y()+slope*(staticData->last().x()-croppedData->at(li-1).x())); - (*croppedData)[li].setX(staticData->last().x()); - } else // mKeyAxis->orientation() == Qt::Vertical + mDataContainer->clear(); + addData(error); +} + +/*! \overload + + Sets asymmetrical errors as specified in \a errorMinus and \a errorPlus. The errors will be + associated one-to-one by the data point index to the associated data plottable (\ref + setDataPlottable). + + You can directly access and manipulate the error bar data via \ref data. + + \see addData +*/ +void QCPErrorBars::setData(const QVector &errorMinus, const QVector &errorPlus) +{ + mDataContainer->clear(); + addData(errorMinus, errorPlus); +} + +/*! + Sets the data plottable to which the error bars will be applied. The error values specified e.g. + via \ref setData will be associated one-to-one by the data point index to the data points of \a + plottable. This means that the error bars will adopt the key/value coordinates of the data point + with the same index. + + The passed \a plottable must be a one-dimensional plottable, i.e. it must implement the \ref + QCPPlottableInterface1D. Further, it must not be a \ref QCPErrorBars instance itself. If either + of these restrictions is violated, a corresponding qDebug output is generated, and the data + plottable of this \ref QCPErrorBars instance is set to zero. + + For proper display, care must also be taken that the key and value axes of the \a plottable match + those configured for this \ref QCPErrorBars instance. +*/ +void QCPErrorBars::setDataPlottable(QCPAbstractPlottable *plottable) +{ + if (plottable && qobject_cast(plottable)) { - // y is key - // similar to "x is key" but switched x,y. Further, lower/upper meaning is inverted compared to x, - // because in pixel coordinates, y increases from top to bottom, not bottom to top like data coordinate. - // if an axis range is reversed, the data point keys will be descending. Reverse them, since following algorithm assumes ascending keys: - if (staticData->first().y() < staticData->last().y()) - { - int size = staticData->size(); - for (int i=0; ifirst().y() < croppedData->last().y()) - { - int size = croppedData->size(); - for (int i=0; ifirst().y() > croppedData->first().y()) // other one must be cropped - qSwap(staticData, croppedData); - int lowBound = findIndexAboveY(croppedData, staticData->first().y()); - if (lowBound == -1) return QPolygonF(); // key ranges have no overlap - croppedData->remove(0, lowBound); - // set lowest point of cropped data to fit exactly key position of first static data - // point via linear interpolation: - if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation - double slope; - if (croppedData->at(1).y()-croppedData->at(0).y() != 0) // avoid division by zero in step plots - slope = (croppedData->at(1).x()-croppedData->at(0).x())/(croppedData->at(1).y()-croppedData->at(0).y()); - else - slope = 0; - (*croppedData)[0].setX(croppedData->at(0).x()+slope*(staticData->first().y()-croppedData->at(0).y())); - (*croppedData)[0].setY(staticData->first().y()); - - // crop upper bound: - if (staticData->last().y() < croppedData->last().y()) // other one must be cropped - qSwap(staticData, croppedData); - int highBound = findIndexBelowY(croppedData, staticData->last().y()); - if (highBound == -1) return QPolygonF(); // key ranges have no overlap - croppedData->remove(highBound+1, croppedData->size()-(highBound+1)); - // set highest point of cropped data to fit exactly key position of last static data - // point via linear interpolation: - if (croppedData->size() < 2) return QPolygonF(); // need at least two points for interpolation - int li = croppedData->size()-1; // last index - if (croppedData->at(li).y()-croppedData->at(li-1).y() != 0) // avoid division by zero in step plots - slope = (croppedData->at(li).x()-croppedData->at(li-1).x())/(croppedData->at(li).y()-croppedData->at(li-1).y()); - else - slope = 0; - (*croppedData)[li].setX(croppedData->at(li-1).x()+slope*(staticData->last().y()-croppedData->at(li-1).y())); - (*croppedData)[li].setY(staticData->last().y()); + mDataPlottable = nullptr; + qDebug() << Q_FUNC_INFO << "can't set another QCPErrorBars instance as data plottable"; + return; + } + if (plottable && !plottable->interface1D()) + { + mDataPlottable = nullptr; + qDebug() << Q_FUNC_INFO << "passed plottable doesn't implement 1d interface, can't associate with QCPErrorBars"; + return; } - // return joined: - for (int i=otherData.size()-1; i>=0; --i) // insert reversed, otherwise the polygon will be twisted - thisData << otherData.at(i); - return QPolygonF(thisData); + mDataPlottable = plottable; } -/*! \internal - - Finds the smallest index of \a data, whose points x value is just above \a x. Assumes x values in - \a data points are ordered ascending, as is the case when plotting with horizontal key axis. +/*! + Sets in which orientation the error bars shall appear on the data points. If your data needs both + error dimensions, create two \ref QCPErrorBars with different \a type. +*/ +void QCPErrorBars::setErrorType(ErrorType type) +{ + mErrorType = type; +} - Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. +/*! + Sets the width of the whiskers (the short bars at the end of the actual error bar backbones) to + \a pixels. */ -int QCPGraph::findIndexAboveX(const QVector *data, double x) const +void QCPErrorBars::setWhiskerWidth(double pixels) { - for (int i=data->size()-1; i>=0; --i) - { - if (data->at(i).x() < x) - { - if (isize()-1) - return i+1; - else - return data->size()-1; - } - } - return -1; + mWhiskerWidth = pixels; } -/*! \internal - - Finds the highest index of \a data, whose points x value is just below \a x. Assumes x values in - \a data points are ordered ascending, as is the case when plotting with horizontal key axis. - - Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. +/*! + Sets the gap diameter around the data points that will be left out when drawing the error bar + backbones. This gap prevents that error bars are drawn too close to or even through scatter + points. */ -int QCPGraph::findIndexBelowX(const QVector *data, double x) const +void QCPErrorBars::setSymbolGap(double pixels) { - for (int i=0; isize(); ++i) - { - if (data->at(i).x() > x) - { - if (i>0) - return i-1; - else - return 0; - } - } - return -1; + mSymbolGap = pixels; } -/*! \internal - - Finds the smallest index of \a data, whose points y value is just above \a y. Assumes y values in - \a data points are ordered descending, as is the case when plotting with vertical key axis. - - Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. +/*! \overload + + Adds symmetrical error values as specified in \a error. The errors will be associated one-to-one + by the data point index to the associated data plottable (\ref setDataPlottable). + + You can directly access and manipulate the error bar data via \ref data. + + \see setData */ -int QCPGraph::findIndexAboveY(const QVector *data, double y) const +void QCPErrorBars::addData(const QVector &error) { - for (int i=0; isize(); ++i) - { - if (data->at(i).y() < y) - { - if (i>0) - return i-1; - else - return 0; - } - } - return -1; + addData(error, error); } -/*! \internal - - Calculates the (minimum) distance (in pixels) the graph's representation has from the given \a - pixelPoint in pixels. This is used to determine whether the graph was clicked or not, e.g. in - \ref selectTest. - - If either the graph has no data or if the line style is \ref lsNone and the scatter style's shape - is \ref QCPScatterStyle::ssNone (i.e. there is no visual representation of the graph), returns -1.0. +/*! \overload + + Adds asymmetrical errors as specified in \a errorMinus and \a errorPlus. The errors will be + associated one-to-one by the data point index to the associated data plottable (\ref + setDataPlottable). + + You can directly access and manipulate the error bar data via \ref data. + + \see setData */ -double QCPGraph::pointDistance(const QPointF &pixelPoint) const +void QCPErrorBars::addData(const QVector &errorMinus, const QVector &errorPlus) { - if (mData->isEmpty()) - return -1.0; - if (mLineStyle == lsNone && mScatterStyle.isNone()) - return -1.0; - - // calculate minimum distances to graph representation: - if (mLineStyle == lsNone) + if (errorMinus.size() != errorPlus.size()) + qDebug() << Q_FUNC_INFO << "minus and plus error vectors have different sizes:" << errorMinus.size() << errorPlus.size(); + const int n = qMin(errorMinus.size(), errorPlus.size()); + mDataContainer->reserve(n); + for (int i=0; iappend(QCPErrorBarsData(errorMinus.at(i), errorPlus.at(i))); +} + +/*! \overload + + Adds a single symmetrical error bar as specified in \a error. The errors will be associated + one-to-one by the data point index to the associated data plottable (\ref setDataPlottable). + + You can directly access and manipulate the error bar data via \ref data. + + \see setData +*/ +void QCPErrorBars::addData(double error) +{ + mDataContainer->append(QCPErrorBarsData(error)); +} + +/*! \overload + + Adds a single asymmetrical error bar as specified in \a errorMinus and \a errorPlus. The errors + will be associated one-to-one by the data point index to the associated data plottable (\ref + setDataPlottable). + + You can directly access and manipulate the error bar data via \ref data. + + \see setData +*/ +void QCPErrorBars::addData(double errorMinus, double errorPlus) +{ + mDataContainer->append(QCPErrorBarsData(errorMinus, errorPlus)); +} + +/* inherits documentation from base class */ +int QCPErrorBars::dataCount() const +{ + return mDataContainer->size(); +} + +/* inherits documentation from base class */ +double QCPErrorBars::dataMainKey(int index) const +{ + if (mDataPlottable) + return mDataPlottable->interface1D()->dataMainKey(index); + else + qDebug() << Q_FUNC_INFO << "no data plottable set"; + return 0; +} + +/* inherits documentation from base class */ +double QCPErrorBars::dataSortKey(int index) const +{ + if (mDataPlottable) + return mDataPlottable->interface1D()->dataSortKey(index); + else + qDebug() << Q_FUNC_INFO << "no data plottable set"; + return 0; +} + +/* inherits documentation from base class */ +double QCPErrorBars::dataMainValue(int index) const +{ + if (mDataPlottable) + return mDataPlottable->interface1D()->dataMainValue(index); + else + qDebug() << Q_FUNC_INFO << "no data plottable set"; + return 0; +} + +/* inherits documentation from base class */ +QCPRange QCPErrorBars::dataValueRange(int index) const +{ + if (mDataPlottable) { - // no line displayed, only calculate distance to scatter points: - QVector scatterData; - getScatterPlotData(&scatterData); - if (scatterData.size() > 0) - { - double minDistSqr = std::numeric_limits::max(); - for (int i=0; iinterface1D()->dataMainValue(index); + if (index >= 0 && index < mDataContainer->size() && mErrorType == etValueError) + return {value-mDataContainer->at(index).errorMinus, value+mDataContainer->at(index).errorPlus}; + else + return {value, value}; } else { - // line displayed, calculate distance to line segments: - QVector lineData; - getPlotData(&lineData, 0); // unlike with getScatterPlotData we get pixel coordinates here - if (lineData.size() > 1) // at least one line segment, compare distance to line segments - { - double minDistSqr = std::numeric_limits::max(); - if (mLineStyle == lsImpulse) - { - // impulse plot differs from other line styles in that the lineData points are only pairwise connected: - for (int i=0; i 0) // only single data point, calculate distance to that point - { - return QVector2D(lineData.at(0)-pixelPoint).length(); - } else // no data available in view to calculate distance to - return -1.0; + qDebug() << Q_FUNC_INFO << "no data plottable set"; + return {}; } } -/*! \internal - - Finds the highest index of \a data, whose points y value is just below \a y. Assumes y values in - \a data points are ordered descending, as is the case when plotting with vertical key axis (since - keys are ordered ascending). +/* inherits documentation from base class */ +QPointF QCPErrorBars::dataPixelPosition(int index) const +{ + if (mDataPlottable) + return mDataPlottable->interface1D()->dataPixelPosition(index); + else + qDebug() << Q_FUNC_INFO << "no data plottable set"; + return {}; +} - Used to calculate the channel fill polygon, see \ref getChannelFillPolygon. +/* inherits documentation from base class */ +bool QCPErrorBars::sortKeyIsMainKey() const +{ + if (mDataPlottable) + { + return mDataPlottable->interface1D()->sortKeyIsMainKey(); + } else + { + qDebug() << Q_FUNC_INFO << "no data plottable set"; + return true; + } +} + +/*! + \copydoc QCPPlottableInterface1D::selectTestRect */ -int QCPGraph::findIndexBelowY(const QVector *data, double y) const +QCPDataSelection QCPErrorBars::selectTestRect(const QRectF &rect, bool onlySelectable) const { - for (int i=data->size()-1; i>=0; --i) + QCPDataSelection result; + if (!mDataPlottable) + return result; + if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty()) + return result; + if (!mKeyAxis || !mValueAxis) + return result; + + QCPErrorBarsDataContainer::const_iterator visibleBegin, visibleEnd; + getVisibleDataBounds(visibleBegin, visibleEnd, QCPDataRange(0, dataCount())); + + QVector backbones, whiskers; + for (QCPErrorBarsDataContainer::const_iterator it=visibleBegin; it!=visibleEnd; ++it) { - if (data->at(i).y() > y) + backbones.clear(); + whiskers.clear(); + getErrorBarLines(it, backbones, whiskers); + foreach (const QLineF &backbone, backbones) { - if (isize()-1) - return i+1; - else - return data->size()-1; + if (rectIntersectsLine(rect, backbone)) + { + result.addDataRange(QCPDataRange(int(it-mDataContainer->constBegin()), int(it-mDataContainer->constBegin()+1)), false); + break; + } } } - return -1; + result.simplify(); + return result; } /* inherits documentation from base class */ -QCPRange QCPGraph::getKeyRange(bool &foundRange, SignDomain inSignDomain) const +int QCPErrorBars::findBegin(double sortKey, bool expandedRange) const { - // just call the specialized version which takes an additional argument whether error bars - // should also be taken into consideration for range calculation. We set this to true here. - return getKeyRange(foundRange, inSignDomain, true); + if (mDataPlottable) + { + if (mDataContainer->isEmpty()) + return 0; + int beginIndex = mDataPlottable->interface1D()->findBegin(sortKey, expandedRange); + if (beginIndex >= mDataContainer->size()) + beginIndex = mDataContainer->size()-1; + return beginIndex; + } else + qDebug() << Q_FUNC_INFO << "no data plottable set"; + return 0; } /* inherits documentation from base class */ -QCPRange QCPGraph::getValueRange(bool &foundRange, SignDomain inSignDomain) const +int QCPErrorBars::findEnd(double sortKey, bool expandedRange) const { - // just call the specialized version which takes an additional argument whether error bars - // should also be taken into consideration for range calculation. We set this to true here. - return getValueRange(foundRange, inSignDomain, true); + if (mDataPlottable) + { + if (mDataContainer->isEmpty()) + return 0; + int endIndex = mDataPlottable->interface1D()->findEnd(sortKey, expandedRange); + if (endIndex > mDataContainer->size()) + endIndex = mDataContainer->size(); + return endIndex; + } else + qDebug() << Q_FUNC_INFO << "no data plottable set"; + return 0; } -/*! \overload - - Allows to specify whether the error bars should be included in the range calculation. +/*! + Implements a selectTest specific to this plottable's point geometry. + + If \a details is not 0, it will be set to a \ref QCPDataSelection, describing the closest data + point to \a pos. - \see getKeyRange(bool &foundRange, SignDomain inSignDomain) + \seebaseclassmethod \ref QCPAbstractPlottable::selectTest */ -QCPRange QCPGraph::getKeyRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const +double QCPErrorBars::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - QCPRange range; - bool haveLower = false; - bool haveUpper = false; + if (!mDataPlottable) return -1; - double current, currentErrorMinus, currentErrorPlus; + if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty()) + return -1; + if (!mKeyAxis || !mValueAxis) + return -1; - if (inSignDomain == sdBoth) // range may be anywhere + if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint()) || mParentPlot->interactions().testFlag(QCP::iSelectPlottablesBeyondAxisRect)) { - QCPDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) + QCPErrorBarsDataContainer::const_iterator closestDataPoint = mDataContainer->constEnd(); + double result = pointDistance(pos, closestDataPoint); + if (details) { - if (!qIsNaN(it.value().value)) - { - current = it.value().key; - currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0); - currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0); - if (current-currentErrorMinus < range.lower || !haveLower) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if (current+currentErrorPlus > range.upper || !haveUpper) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - } - ++it; + int pointIndex = int(closestDataPoint-mDataContainer->constBegin()); + details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1))); + } + return result; + } else + return -1; +} + +/* inherits documentation from base class */ +void QCPErrorBars::draw(QCPPainter *painter) +{ + if (!mDataPlottable) return; + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + if (mKeyAxis.data()->range().size() <= 0 || mDataContainer->isEmpty()) return; + + // if the sort key isn't the main key, we must check the visibility for each data point/error bar individually + // (getVisibleDataBounds applies range restriction, but otherwise can only return full data range): + bool checkPointVisibility = !mDataPlottable->interface1D()->sortKeyIsMainKey(); + + // check data validity if flag set: +#ifdef QCUSTOMPLOT_CHECK_DATA + QCPErrorBarsDataContainer::const_iterator it; + for (it = mDataContainer->constBegin(); it != mDataContainer->constEnd(); ++it) + { + if (QCP::isInvalidData(it->errorMinus, it->errorPlus)) + qDebug() << Q_FUNC_INFO << "Data point at index" << it-mDataContainer->constBegin() << "invalid." << "Plottable name:" << name(); + } +#endif + + applyDefaultAntialiasingHint(painter); + painter->setBrush(Qt::NoBrush); + // loop over and draw segments of unselected/selected data: + QList selectedSegments, unselectedSegments, allSegments; + getDataSegments(selectedSegments, unselectedSegments); + allSegments << unselectedSegments << selectedSegments; + QVector backbones, whiskers; + for (int i=0; i= unselectedSegments.size(); + if (isSelectedSegment && mSelectionDecorator) + mSelectionDecorator->applyPen(painter); + else + painter->setPen(mPen); + if (painter->pen().capStyle() == Qt::SquareCap) + { + QPen capFixPen(painter->pen()); + capFixPen.setCapStyle(Qt::FlatCap); + painter->setPen(capFixPen); } - } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain + backbones.clear(); + whiskers.clear(); + for (QCPErrorBarsDataContainer::const_iterator it=begin; it!=end; ++it) + { + if (!checkPointVisibility || errorBarVisible(int(it-mDataContainer->constBegin()))) + getErrorBarLines(it, backbones, whiskers); + } + painter->drawLines(backbones); + painter->drawLines(whiskers); + } + + // draw other selection decoration that isn't just line/scatter pens and brushes: + if (mSelectionDecorator) + mSelectionDecorator->drawDecoration(painter, selection()); +} + +/* inherits documentation from base class */ +void QCPErrorBars::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const +{ + applyDefaultAntialiasingHint(painter); + painter->setPen(mPen); + if (mErrorType == etValueError && mValueAxis && mValueAxis->orientation() == Qt::Vertical) + { + painter->drawLine(QLineF(rect.center().x(), rect.top()+2, rect.center().x(), rect.bottom()-1)); + painter->drawLine(QLineF(rect.center().x()-4, rect.top()+2, rect.center().x()+4, rect.top()+2)); + painter->drawLine(QLineF(rect.center().x()-4, rect.bottom()-1, rect.center().x()+4, rect.bottom()-1)); + } else + { + painter->drawLine(QLineF(rect.left()+2, rect.center().y(), rect.right()-2, rect.center().y())); + painter->drawLine(QLineF(rect.left()+2, rect.center().y()-4, rect.left()+2, rect.center().y()+4)); + painter->drawLine(QLineF(rect.right()-2, rect.center().y()-4, rect.right()-2, rect.center().y()+4)); + } +} + +/* inherits documentation from base class */ +QCPRange QCPErrorBars::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const +{ + if (!mDataPlottable) + { + foundRange = false; + return {}; + } + + QCPRange range; + bool haveLower = false; + bool haveUpper = false; + QCPErrorBarsDataContainer::const_iterator it; + for (it = mDataContainer->constBegin(); it != mDataContainer->constEnd(); ++it) { - QCPDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) + if (mErrorType == etValueError) { - if (!qIsNaN(it.value().value)) + // error bar doesn't extend in key dimension (except whisker but we ignore that here), so only use data point center + const double current = mDataPlottable->interface1D()->dataMainKey(int(it-mDataContainer->constBegin())); + if (qIsNaN(current)) continue; + if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0)) { - current = it.value().key; - currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0); - currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0); - if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0) + if (current < range.lower || !haveLower) { - range.lower = current-currentErrorMinus; + range.lower = current; haveLower = true; } - if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0) + if (current > range.upper || !haveUpper) { - range.upper = current+currentErrorPlus; + range.upper = current; haveUpper = true; } - if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point. - { - if ((current < range.lower || !haveLower) && current < 0) - { - range.lower = current; - haveLower = true; - } - if ((current > range.upper || !haveUpper) && current < 0) - { - range.upper = current; - haveUpper = true; - } - } } - ++it; - } - } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain - { - QCPDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) + } else // mErrorType == etKeyError { - if (!qIsNaN(it.value().value)) + const double dataKey = mDataPlottable->interface1D()->dataMainKey(int(it-mDataContainer->constBegin())); + if (qIsNaN(dataKey)) continue; + // plus error: + double current = dataKey + (qIsNaN(it->errorPlus) ? 0 : it->errorPlus); + if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0)) { - current = it.value().key; - currentErrorMinus = (includeErrors ? it.value().keyErrorMinus : 0); - currentErrorPlus = (includeErrors ? it.value().keyErrorPlus : 0); - if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0) + if (current > range.upper || !haveUpper) { - range.upper = current+currentErrorPlus; + range.upper = current; haveUpper = true; } - if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point. + } + // minus error: + current = dataKey - (qIsNaN(it->errorMinus) ? 0 : it->errorMinus); + if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0)) + { + if (current < range.lower || !haveLower) { - if ((current < range.lower || !haveLower) && current > 0) - { - range.lower = current; - haveLower = true; - } - if ((current > range.upper || !haveUpper) && current > 0) - { - range.upper = current; - haveUpper = true; - } + range.lower = current; + haveLower = true; } } - ++it; } } + if (haveUpper && !haveLower) + { + range.lower = range.upper; + haveLower = true; + } else if (haveLower && !haveUpper) + { + range.upper = range.lower; + haveUpper = true; + } + foundRange = haveLower && haveUpper; return range; } -/*! \overload - - Allows to specify whether the error bars should be included in the range calculation. - - \see getValueRange(bool &foundRange, SignDomain inSignDomain) -*/ -QCPRange QCPGraph::getValueRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const +/* inherits documentation from base class */ +QCPRange QCPErrorBars::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const { + if (!mDataPlottable) + { + foundRange = false; + return {}; + } + QCPRange range; + const bool restrictKeyRange = inKeyRange != QCPRange(); bool haveLower = false; bool haveUpper = false; - - double current, currentErrorMinus, currentErrorPlus; - - if (inSignDomain == sdBoth) // range may be anywhere + QCPErrorBarsDataContainer::const_iterator itBegin = mDataContainer->constBegin(); + QCPErrorBarsDataContainer::const_iterator itEnd = mDataContainer->constEnd(); + if (mDataPlottable->interface1D()->sortKeyIsMainKey() && restrictKeyRange) { - QCPDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) + itBegin = mDataContainer->constBegin()+findBegin(inKeyRange.lower, false); + itEnd = mDataContainer->constBegin()+findEnd(inKeyRange.upper, false); + } + for (QCPErrorBarsDataContainer::const_iterator it = itBegin; it != itEnd; ++it) + { + if (restrictKeyRange) + { + const double dataKey = mDataPlottable->interface1D()->dataMainKey(int(it-mDataContainer->constBegin())); + if (dataKey < inKeyRange.lower || dataKey > inKeyRange.upper) + continue; + } + if (mErrorType == etValueError) { - current = it.value().value; - if (!qIsNaN(current)) + const double dataValue = mDataPlottable->interface1D()->dataMainValue(int(it-mDataContainer->constBegin())); + if (qIsNaN(dataValue)) continue; + // plus error: + double current = dataValue + (qIsNaN(it->errorPlus) ? 0 : it->errorPlus); + if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0)) { - currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0); - currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0); - if (current-currentErrorMinus < range.lower || !haveLower) - { - range.lower = current-currentErrorMinus; - haveLower = true; - } - if (current+currentErrorPlus > range.upper || !haveUpper) + if (current > range.upper || !haveUpper) { - range.upper = current+currentErrorPlus; + range.upper = current; haveUpper = true; } } - ++it; - } - } else if (inSignDomain == sdNegative) // range may only be in the negative sign domain - { - QCPDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().value; - if (!qIsNaN(current)) + // minus error: + current = dataValue - (qIsNaN(it->errorMinus) ? 0 : it->errorMinus); + if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0)) { - currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0); - currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0); - if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus < 0) + if (current < range.lower || !haveLower) { - range.lower = current-currentErrorMinus; + range.lower = current; haveLower = true; } - if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus < 0) - { - range.upper = current+currentErrorPlus; - haveUpper = true; - } - if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to get that point. - { - if ((current < range.lower || !haveLower) && current < 0) - { - range.lower = current; - haveLower = true; - } - if ((current > range.upper || !haveUpper) && current < 0) - { - range.upper = current; - haveUpper = true; - } - } } - ++it; - } - } else if (inSignDomain == sdPositive) // range may only be in the positive sign domain - { - QCPDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) + } else // mErrorType == etKeyError { - current = it.value().value; - if (!qIsNaN(current)) + // error bar doesn't extend in value dimension (except whisker but we ignore that here), so only use data point center + const double current = mDataPlottable->interface1D()->dataMainValue(int(it-mDataContainer->constBegin())); + if (qIsNaN(current)) continue; + if (inSignDomain == QCP::sdBoth || (inSignDomain == QCP::sdNegative && current < 0) || (inSignDomain == QCP::sdPositive && current > 0)) { - currentErrorMinus = (includeErrors ? it.value().valueErrorMinus : 0); - currentErrorPlus = (includeErrors ? it.value().valueErrorPlus : 0); - if ((current-currentErrorMinus < range.lower || !haveLower) && current-currentErrorMinus > 0) + if (current < range.lower || !haveLower) { - range.lower = current-currentErrorMinus; + range.lower = current; haveLower = true; } - if ((current+currentErrorPlus > range.upper || !haveUpper) && current+currentErrorPlus > 0) + if (current > range.upper || !haveUpper) { - range.upper = current+currentErrorPlus; + range.upper = current; haveUpper = true; } - if (includeErrors) // in case point is in valid sign domain but errobars stretch beyond it, we still want to geht that point. - { - if ((current < range.lower || !haveLower) && current > 0) - { - range.lower = current; - haveLower = true; - } - if ((current > range.upper || !haveUpper) && current > 0) - { - range.upper = current; - haveUpper = true; - } - } } - ++it; } } + if (haveUpper && !haveLower) + { + range.lower = range.upper; + haveLower = true; + } else if (haveLower && !haveUpper) + { + range.upper = range.lower; + haveUpper = true; + } + foundRange = haveLower && haveUpper; return range; } +/*! \internal -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPCurveData -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPCurveData - \brief Holds the data of one single data point for QCPCurve. - - The container for storing multiple data points is \ref QCPCurveDataMap. - - The stored data is: - \li \a t: the free parameter of the curve at this curve point (cp. the mathematical vector (x(t), y(t))) - \li \a key: coordinate on the key axis of this curve point - \li \a value: coordinate on the value axis of this curve point - - \see QCPCurveDataMap -*/ + Calculates the lines that make up the error bar belonging to the data point \a it. -/*! - Constructs a curve data point with t, key and value set to zero. -*/ -QCPCurveData::QCPCurveData() : - t(0), - key(0), - value(0) -{ -} + The resulting lines are added to \a backbones and \a whiskers. The vectors are not cleared, so + calling this method with different \a it but the same \a backbones and \a whiskers allows to + accumulate lines for multiple data points. -/*! - Constructs a curve data point with the specified \a t, \a key and \a value. + This method assumes that \a it is a valid iterator within the bounds of this \ref QCPErrorBars + instance and within the bounds of the associated data plottable. */ -QCPCurveData::QCPCurveData(double t, double key, double value) : - t(t), - key(key), - value(value) +void QCPErrorBars::getErrorBarLines(QCPErrorBarsDataContainer::const_iterator it, QVector &backbones, QVector &whiskers) const { -} - - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPCurve -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPCurve - \brief A plottable representing a parametric curve in a plot. - - \image html QCPCurve.png + if (!mDataPlottable) return; - Unlike QCPGraph, plottables of this type may have multiple points with the same key coordinate, - so their visual representation can have \a loops. This is realized by introducing a third - coordinate \a t, which defines the order of the points described by the other two coordinates \a - x and \a y. + int index = int(it-mDataContainer->constBegin()); + QPointF centerPixel = mDataPlottable->interface1D()->dataPixelPosition(index); + if (qIsNaN(centerPixel.x()) || qIsNaN(centerPixel.y())) + return; + QCPAxis *errorAxis = mErrorType == etValueError ? mValueAxis.data() : mKeyAxis.data(); + QCPAxis *orthoAxis = mErrorType == etValueError ? mKeyAxis.data() : mValueAxis.data(); + const double centerErrorAxisPixel = errorAxis->orientation() == Qt::Horizontal ? centerPixel.x() : centerPixel.y(); + const double centerOrthoAxisPixel = orthoAxis->orientation() == Qt::Horizontal ? centerPixel.x() : centerPixel.y(); + const double centerErrorAxisCoord = errorAxis->pixelToCoord(centerErrorAxisPixel); // depending on plottable, this might be different from just mDataPlottable->interface1D()->dataMainKey/Value + const double symbolGap = mSymbolGap*0.5*errorAxis->pixelOrientation(); + // plus error: + double errorStart, errorEnd; + if (!qIsNaN(it->errorPlus)) + { + errorStart = centerErrorAxisPixel+symbolGap; + errorEnd = errorAxis->coordToPixel(centerErrorAxisCoord+it->errorPlus); + if (errorAxis->orientation() == Qt::Vertical) + { + if ((errorStart > errorEnd) != errorAxis->rangeReversed()) + backbones.append(QLineF(centerOrthoAxisPixel, errorStart, centerOrthoAxisPixel, errorEnd)); + whiskers.append(QLineF(centerOrthoAxisPixel-mWhiskerWidth*0.5, errorEnd, centerOrthoAxisPixel+mWhiskerWidth*0.5, errorEnd)); + } else + { + if ((errorStart < errorEnd) != errorAxis->rangeReversed()) + backbones.append(QLineF(errorStart, centerOrthoAxisPixel, errorEnd, centerOrthoAxisPixel)); + whiskers.append(QLineF(errorEnd, centerOrthoAxisPixel-mWhiskerWidth*0.5, errorEnd, centerOrthoAxisPixel+mWhiskerWidth*0.5)); + } + } + // minus error: + if (!qIsNaN(it->errorMinus)) + { + errorStart = centerErrorAxisPixel-symbolGap; + errorEnd = errorAxis->coordToPixel(centerErrorAxisCoord-it->errorMinus); + if (errorAxis->orientation() == Qt::Vertical) + { + if ((errorStart < errorEnd) != errorAxis->rangeReversed()) + backbones.append(QLineF(centerOrthoAxisPixel, errorStart, centerOrthoAxisPixel, errorEnd)); + whiskers.append(QLineF(centerOrthoAxisPixel-mWhiskerWidth*0.5, errorEnd, centerOrthoAxisPixel+mWhiskerWidth*0.5, errorEnd)); + } else + { + if ((errorStart > errorEnd) != errorAxis->rangeReversed()) + backbones.append(QLineF(errorStart, centerOrthoAxisPixel, errorEnd, centerOrthoAxisPixel)); + whiskers.append(QLineF(errorEnd, centerOrthoAxisPixel-mWhiskerWidth*0.5, errorEnd, centerOrthoAxisPixel+mWhiskerWidth*0.5)); + } + } +} - To plot data, assign it with the \ref setData or \ref addData functions. - - Gaps in the curve can be created by adding data points with NaN as key and value - (qQNaN() or std::numeric_limits::quiet_NaN()) in between the two data points that shall be - separated. - - \section appearance Changing the appearance - - The appearance of the curve is determined by the pen and the brush (\ref setPen, \ref setBrush). - \section usage Usage - - Like all data representing objects in QCustomPlot, the QCPCurve is a plottable (QCPAbstractPlottable). So - the plottable-interface of QCustomPlot applies (QCustomPlot::plottable, QCustomPlot::addPlottable, QCustomPlot::removePlottable, etc.) - - Usually, you first create an instance and add it to the customPlot: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcurve-creation-1 - and then modify the properties of the newly created plottable, e.g.: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpcurve-creation-2 -*/ +/*! \internal -/*! - Constructs a curve which uses \a keyAxis as its key axis ("x") and \a valueAxis as its value - axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and not have - the same orientation. If either of these restrictions is violated, a corresponding message is - printed to the debug output (qDebug), the construction is not aborted, though. - - The constructed QCPCurve can be added to the plot with QCustomPlot::addPlottable, QCustomPlot - then takes ownership of the graph. -*/ -QCPCurve::QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis) : - QCPAbstractPlottable(keyAxis, valueAxis) -{ - mData = new QCPCurveDataMap; - mPen.setColor(Qt::blue); - mPen.setStyle(Qt::SolidLine); - mBrush.setColor(Qt::blue); - mBrush.setStyle(Qt::NoBrush); - mSelectedPen = mPen; - mSelectedPen.setWidthF(2.5); - mSelectedPen.setColor(QColor(80, 80, 255)); // lighter than Qt::blue of mPen - mSelectedBrush = mBrush; - - setScatterStyle(QCPScatterStyle()); - setLineStyle(lsLine); -} + This method outputs the currently visible data range via \a begin and \a end. The returned range + will also never exceed \a rangeRestriction. -QCPCurve::~QCPCurve() -{ - delete mData; -} + Since error bars with type \ref etKeyError may extend to arbitrarily positive and negative key + coordinates relative to their data point key, this method checks all outer error bars whether + they truly don't reach into the visible portion of the axis rect, by calling \ref + errorBarVisible. On the other hand error bars with type \ref etValueError that are associated + with data plottables whose sort key is equal to the main key (see \ref qcpdatacontainer-datatype + "QCPDataContainer DataType") can be handled very efficiently by finding the visible range of + error bars through binary search (\ref QCPPlottableInterface1D::findBegin and \ref + QCPPlottableInterface1D::findEnd). -/*! - Replaces the current data with the provided \a data. - - If \a copy is set to true, data points in \a data will only be copied. if false, the plottable - takes ownership of the passed data and replaces the internal data pointer with it. This is - significantly faster than copying for large datasets. + If the plottable's sort key is not equal to the main key, this method returns the full data + range, only restricted by \a rangeRestriction. Drawing optimization then has to be done on a + point-by-point basis in the \ref draw method. */ -void QCPCurve::setData(QCPCurveDataMap *data, bool copy) +void QCPErrorBars::getVisibleDataBounds(QCPErrorBarsDataContainer::const_iterator &begin, QCPErrorBarsDataContainer::const_iterator &end, const QCPDataRange &rangeRestriction) const { - if (mData == data) + QCPAxis *keyAxis = mKeyAxis.data(); + QCPAxis *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { - qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); + qDebug() << Q_FUNC_INFO << "invalid key or value axis"; + end = mDataContainer->constEnd(); + begin = end; return; } - if (copy) + if (!mDataPlottable || rangeRestriction.isEmpty()) { - *mData = *data; - } else + end = mDataContainer->constEnd(); + begin = end; + return; + } + if (!mDataPlottable->interface1D()->sortKeyIsMainKey()) { - delete mData; - mData = data; + // if the sort key isn't the main key, it's not possible to find a contiguous range of visible + // data points, so this method then only applies the range restriction and otherwise returns + // the full data range. Visibility checks must be done on a per-datapoin-basis during drawing + QCPDataRange dataRange(0, mDataContainer->size()); + dataRange = dataRange.bounded(rangeRestriction); + begin = mDataContainer->constBegin()+dataRange.begin(); + end = mDataContainer->constBegin()+dataRange.end(); + return; } -} - -/*! \overload - Replaces the current data with the provided points in \a t, \a key and \a value tuples. The - provided vectors should have equal length. Else, the number of added points will be the size of - the smallest vector. -*/ -void QCPCurve::setData(const QVector &t, const QVector &key, const QVector &value) -{ - mData->clear(); - int n = t.size(); - n = qMin(n, key.size()); - n = qMin(n, value.size()); - QCPCurveData newData; - for (int i=0; isize(), mDataPlottable->interface1D()->dataCount()); + int beginIndex = mDataPlottable->interface1D()->findBegin(keyAxis->range().lower); + int endIndex = mDataPlottable->interface1D()->findEnd(keyAxis->range().upper); + int i = beginIndex; + while (i > 0 && i < n && i > rangeRestriction.begin()) { - newData.t = t[i]; - newData.key = key[i]; - newData.value = value[i]; - mData->insertMulti(newData.t, newData); + if (errorBarVisible(i)) + beginIndex = i; + --i; } + i = endIndex; + while (i >= 0 && i < n && i < rangeRestriction.end()) + { + if (errorBarVisible(i)) + endIndex = i+1; + ++i; + } + QCPDataRange dataRange(beginIndex, endIndex); + dataRange = dataRange.bounded(rangeRestriction.bounded(QCPDataRange(0, mDataContainer->size()))); + begin = mDataContainer->constBegin()+dataRange.begin(); + end = mDataContainer->constBegin()+dataRange.end(); } -/*! \overload - - Replaces the current data with the provided \a key and \a value pairs. The t parameter - of each data point will be set to the integer index of the respective key/value pair. +/*! \internal + + Calculates the minimum distance in pixels the error bars' representation has from the given \a + pixelPoint. This is used to determine whether the error bar was clicked or not, e.g. in \ref + selectTest. The closest data point to \a pixelPoint is returned in \a closestData. */ -void QCPCurve::setData(const QVector &key, const QVector &value) +double QCPErrorBars::pointDistance(const QPointF &pixelPoint, QCPErrorBarsDataContainer::const_iterator &closestData) const { - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - QCPCurveData newData; - for (int i=0; iconstEnd(); + if (!mDataPlottable || mDataContainer->isEmpty()) + return -1.0; + if (!mKeyAxis || !mValueAxis) { - newData.t = i; // no t vector given, so we assign t the index of the key/value pair - newData.key = key[i]; - newData.value = value[i]; - mData->insertMulti(newData.t, newData); + qDebug() << Q_FUNC_INFO << "invalid key or value axis"; + return -1.0; } -} - -/*! - Sets the visual appearance of single data points in the plot. If set to \ref - QCPScatterStyle::ssNone, no scatter points are drawn (e.g. for line-only plots with appropriate - line style). - \see QCPScatterStyle, setLineStyle -*/ -void QCPCurve::setScatterStyle(const QCPScatterStyle &style) -{ - mScatterStyle = style; -} - -/*! - Sets how the single data points are connected in the plot or how they are represented visually - apart from the scatter symbol. For scatter-only plots, set \a style to \ref lsNone and \ref - setScatterStyle to the desired scatter style. + QCPErrorBarsDataContainer::const_iterator begin, end; + getVisibleDataBounds(begin, end, QCPDataRange(0, dataCount())); - \see setScatterStyle -*/ -void QCPCurve::setLineStyle(QCPCurve::LineStyle style) -{ - mLineStyle = style; -} - -/*! - Adds the provided data points in \a dataMap to the current data. - \see removeData -*/ -void QCPCurve::addData(const QCPCurveDataMap &dataMap) -{ - mData->unite(dataMap); -} - -/*! \overload - Adds the provided single data point in \a data to the current data. - \see removeData -*/ -void QCPCurve::addData(const QCPCurveData &data) -{ - mData->insertMulti(data.t, data); + // calculate minimum distances to error backbones (whiskers are ignored for speed) and find closestData iterator: + double minDistSqr = (std::numeric_limits::max)(); + QVector backbones, whiskers; + for (QCPErrorBarsDataContainer::const_iterator it=begin; it!=end; ++it) + { + getErrorBarLines(it, backbones, whiskers); + foreach (const QLineF &backbone, backbones) + { + const double currentDistSqr = QCPVector2D(pixelPoint).distanceSquaredToLine(backbone); + if (currentDistSqr < minDistSqr) + { + minDistSqr = currentDistSqr; + closestData = it; + } + } + } + return qSqrt(minDistSqr); } -/*! \overload - Adds the provided single data point as \a t, \a key and \a value tuple to the current data - \see removeData -*/ -void QCPCurve::addData(double t, double key, double value) -{ - QCPCurveData newData; - newData.t = t; - newData.key = key; - newData.value = value; - mData->insertMulti(newData.t, newData); -} +/*! \internal -/*! \overload - - Adds the provided single data point as \a key and \a value pair to the current data The t - parameter of the data point is set to the t of the last data point plus 1. If there is no last - data point, t will be set to 0. - - \see removeData + \note This method is identical to \ref QCPAbstractPlottable1D::getDataSegments but needs to be + reproduced here since the \ref QCPErrorBars plottable, as a special case that doesn't have its + own key/value data coordinates, doesn't derive from \ref QCPAbstractPlottable1D. See the + documentation there for details. */ -void QCPCurve::addData(double key, double value) +void QCPErrorBars::getDataSegments(QList &selectedSegments, QList &unselectedSegments) const { - QCPCurveData newData; - if (!mData->isEmpty()) - newData.t = (mData->constEnd()-1).key()+1; - else - newData.t = 0; - newData.key = key; - newData.value = value; - mData->insertMulti(newData.t, newData); + selectedSegments.clear(); + unselectedSegments.clear(); + if (mSelectable == QCP::stWhole) // stWhole selection type draws the entire plottable with selected style if mSelection isn't empty + { + if (selected()) + selectedSegments << QCPDataRange(0, dataCount()); + else + unselectedSegments << QCPDataRange(0, dataCount()); + } else + { + QCPDataSelection sel(selection()); + sel.simplify(); + selectedSegments = sel.dataRanges(); + unselectedSegments = sel.inverse(QCPDataRange(0, dataCount())).dataRanges(); + } } -/*! \overload - Adds the provided data points as \a t, \a key and \a value tuples to the current data. - \see removeData +/*! \internal + + Returns whether the error bar at the specified \a index is visible within the current key axis + range. + + This method assumes for performance reasons without checking that the key axis, the value axis, + and the data plottable (\ref setDataPlottable) are not \c nullptr and that \a index is within + valid bounds of this \ref QCPErrorBars instance and the bounds of the data plottable. */ -void QCPCurve::addData(const QVector &ts, const QVector &keys, const QVector &values) +bool QCPErrorBars::errorBarVisible(int index) const { - int n = ts.size(); - n = qMin(n, keys.size()); - n = qMin(n, values.size()); - QCPCurveData newData; - for (int i=0; iinterface1D()->dataPixelPosition(index); + const double centerKeyPixel = mKeyAxis->orientation() == Qt::Horizontal ? centerPixel.x() : centerPixel.y(); + if (qIsNaN(centerKeyPixel)) + return false; + + double keyMin, keyMax; + if (mErrorType == etKeyError) { - newData.t = ts[i]; - newData.key = keys[i]; - newData.value = values[i]; - mData->insertMulti(newData.t, newData); + const double centerKey = mKeyAxis->pixelToCoord(centerKeyPixel); + const double errorPlus = mDataContainer->at(index).errorPlus; + const double errorMinus = mDataContainer->at(index).errorMinus; + keyMax = centerKey+(qIsNaN(errorPlus) ? 0 : errorPlus); + keyMin = centerKey-(qIsNaN(errorMinus) ? 0 : errorMinus); + } else // mErrorType == etValueError + { + keyMax = mKeyAxis->pixelToCoord(centerKeyPixel+mWhiskerWidth*0.5*mKeyAxis->pixelOrientation()); + keyMin = mKeyAxis->pixelToCoord(centerKeyPixel-mWhiskerWidth*0.5*mKeyAxis->pixelOrientation()); } + return ((keyMax > mKeyAxis->range().lower) && (keyMin < mKeyAxis->range().upper)); } -/*! - Removes all data points with curve parameter t smaller than \a t. - \see addData, clearData +/*! \internal + + Returns whether \a line intersects (or is contained in) \a pixelRect. + + \a line is assumed to be either perfectly horizontal or perfectly vertical, as is the case for + error bar lines. */ -void QCPCurve::removeDataBefore(double t) +bool QCPErrorBars::rectIntersectsLine(const QRectF &pixelRect, const QLineF &line) const { - QCPCurveDataMap::iterator it = mData->begin(); - while (it != mData->end() && it.key() < t) - it = mData->erase(it); + if (pixelRect.left() > line.x1() && pixelRect.left() > line.x2()) + return false; + else if (pixelRect.right() < line.x1() && pixelRect.right() < line.x2()) + return false; + else if (pixelRect.top() > line.y1() && pixelRect.top() > line.y2()) + return false; + else if (pixelRect.bottom() < line.y1() && pixelRect.bottom() < line.y2()) + return false; + else + return true; } +/* end of 'src/plottables/plottable-errorbar.cpp' */ -/*! - Removes all data points with curve parameter t greater than \a t. - \see addData, clearData + +/* including file 'src/items/item-straightline.cpp' */ +/* modified 2022-11-06T12:45:56, size 7596 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPItemStraightLine +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPItemStraightLine + \brief A straight line that spans infinitely in both directions + + \image html QCPItemStraightLine.png "Straight line example. Blue dotted circles are anchors, solid blue discs are positions." + + It has two positions, \a point1 and \a point2, which define the straight line. */ -void QCPCurve::removeDataAfter(double t) -{ - if (mData->isEmpty()) return; - QCPCurveDataMap::iterator it = mData->upperBound(t); - while (it != mData->end()) - it = mData->erase(it); -} /*! - Removes all data points with curve parameter t between \a fromt and \a tot. if \a fromt is - greater or equal to \a tot, the function does nothing. To remove a single data point with known - t, use \ref removeData(double t). + Creates a straight line item and sets default values. - \see addData, clearData + The created item is automatically registered with \a parentPlot. This QCustomPlot instance takes + ownership of the item, so do not delete it manually but use QCustomPlot::removeItem() instead. */ -void QCPCurve::removeData(double fromt, double tot) +QCPItemStraightLine::QCPItemStraightLine(QCustomPlot *parentPlot) : + QCPAbstractItem(parentPlot), + point1(createPosition(QLatin1String("point1"))), + point2(createPosition(QLatin1String("point2"))) { - if (fromt >= tot || mData->isEmpty()) return; - QCPCurveDataMap::iterator it = mData->upperBound(fromt); - QCPCurveDataMap::iterator itEnd = mData->upperBound(tot); - while (it != itEnd) - it = mData->erase(it); + point1->setCoords(0, 0); + point2->setCoords(1, 1); + + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue,2)); } -/*! \overload - - Removes a single data point at curve parameter \a t. If the position is not known with absolute - precision, consider using \ref removeData(double fromt, double tot) with a small fuzziness - interval around the suspected position, depeding on the precision with which the curve parameter - is known. +QCPItemStraightLine::~QCPItemStraightLine() +{ +} + +/*! + Sets the pen that will be used to draw the line - \see addData, clearData + \see setSelectedPen */ -void QCPCurve::removeData(double t) +void QCPItemStraightLine::setPen(const QPen &pen) { - mData->remove(t); + mPen = pen; } /*! - Removes all data points. - \see removeData, removeDataAfter, removeDataBefore + Sets the pen that will be used to draw the line when selected + + \see setPen, setSelected */ -void QCPCurve::clearData() +void QCPItemStraightLine::setSelectedPen(const QPen &pen) { - mData->clear(); + mSelectedPen = pen; } /* inherits documentation from base class */ -double QCPCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +double QCPItemStraightLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { Q_UNUSED(details) - if ((onlySelectable && !mSelectable) || mData->isEmpty()) + if (onlySelectable && !mSelectable) return -1; - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } - if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) - return pointDistance(pos); - else - return -1; + return QCPVector2D(pos).distanceToStraightLine(point1->pixelPosition(), point2->pixelPosition()-point1->pixelPosition()); } /* inherits documentation from base class */ -void QCPCurve::draw(QCPPainter *painter) +void QCPItemStraightLine::draw(QCPPainter *painter) { - if (mData->isEmpty()) return; - - // allocate line vector: - QVector *lineData = new QVector; - - // fill with curve data: - getCurveData(lineData); - - // check data validity if flag set: -#ifdef QCUSTOMPLOT_CHECK_DATA - QCPCurveDataMap::const_iterator it; - for (it = mData->constBegin(); it != mData->constEnd(); ++it) - { - if (QCP::isInvalidData(it.value().t) || - QCP::isInvalidData(it.value().key, it.value().value)) - qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "invalid." << "Plottable name:" << name(); - } -#endif - - // draw curve fill: - if (mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) - { - applyFillAntialiasingHint(painter); - painter->setPen(Qt::NoPen); - painter->setBrush(mainBrush()); - painter->drawPolygon(QPolygonF(*lineData)); - } - - // draw curve line: - if (mLineStyle != lsNone && mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0) + QCPVector2D start(point1->pixelPosition()); + QCPVector2D end(point2->pixelPosition()); + // get visible segment of straight line inside clipRect: + int clipPad = qCeil(mainPen().widthF()); + QLineF line = getRectClippedStraightLine(start, end-start, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad)); + // paint visible segment, if existent: + if (!line.isNull()) { - applyDefaultAntialiasingHint(painter); painter->setPen(mainPen()); - painter->setBrush(Qt::NoBrush); - // if drawing solid line and not in PDF, use much faster line drawing instead of polyline: - if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) && - painter->pen().style() == Qt::SolidLine && - !painter->modes().testFlag(QCPPainter::pmVectorized) && - !painter->modes().testFlag(QCPPainter::pmNoCaching)) - { - int i = 0; - bool lastIsNan = false; - const int lineDataSize = lineData->size(); - while (i < lineDataSize && (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x()))) // make sure first point is not NaN - ++i; - ++i; // because drawing works in 1 point retrospect - while (i < lineDataSize) - { - if (!qIsNaN(lineData->at(i).y()) && !qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line - { - if (!lastIsNan) - painter->drawLine(lineData->at(i-1), lineData->at(i)); - else - lastIsNan = false; - } else - lastIsNan = true; - ++i; - } - } else - { - int segmentStart = 0; - int i = 0; - const int lineDataSize = lineData->size(); - while (i < lineDataSize) - { - if (qIsNaN(lineData->at(i).y()) || qIsNaN(lineData->at(i).x())) // NaNs create a gap in the line - { - painter->drawPolyline(lineData->constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point - segmentStart = i+1; - } - ++i; - } - // draw last segment: - painter->drawPolyline(lineData->constData()+segmentStart, lineDataSize-segmentStart); - } - } - - // draw scatters: - if (!mScatterStyle.isNone()) - drawScatterPlot(painter, lineData); - - // free allocated line data: - delete lineData; -} - -/* inherits documentation from base class */ -void QCPCurve::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const -{ - // draw fill: - if (mBrush.style() != Qt::NoBrush) - { - applyFillAntialiasingHint(painter); - painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush); - } - // draw line vertically centered: - if (mLineStyle != lsNone) - { - applyDefaultAntialiasingHint(painter); - painter->setPen(mPen); - painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens - } - // draw scatter symbol: - if (!mScatterStyle.isNone()) - { - applyScattersAntialiasingHint(painter); - // scale scatter pixmap if it's too large to fit in legend icon rect: - if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height())) - { - QCPScatterStyle scaledStyle(mScatterStyle); - scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); - scaledStyle.applyTo(painter, mPen); - scaledStyle.drawShape(painter, QRectF(rect).center()); - } else - { - mScatterStyle.applyTo(painter, mPen); - mScatterStyle.drawShape(painter, QRectF(rect).center()); - } + painter->drawLine(line); } } /*! \internal - - Draws scatter symbols at every data point passed in \a pointData. scatter symbols are independent of - the line style and are always drawn if scatter shape is not \ref QCPScatterStyle::ssNone. -*/ -void QCPCurve::drawScatterPlot(QCPPainter *painter, const QVector *pointData) const -{ - // draw scatter point symbols: - applyScattersAntialiasingHint(painter); - mScatterStyle.applyTo(painter, mPen); - for (int i=0; isize(); ++i) - if (!qIsNaN(pointData->at(i).x()) && !qIsNaN(pointData->at(i).y())) - mScatterStyle.drawShape(painter, pointData->at(i)); -} - -/*! \internal - - called by QCPCurve::draw to generate a point vector (in pixel coordinates) which represents the - line of the curve. - Line segments that aren't visible in the current axis rect are handled in an optimized way. They - are projected onto a rectangle slightly larger than the visible axis rect and simplified - regarding point count. The algorithm makes sure to preserve appearance of lines and fills inside - the visible axis rect by generating new temporary points on the outer rect if necessary. + Returns the section of the straight line defined by \a base and direction vector \a + vec, that is visible in the specified \a rect. - Methods that are also involved in the algorithm are: \ref getRegion, \ref getOptimizedPoint, \ref - getOptimizedCornerPoints \ref mayTraverse, \ref getTraverse, \ref getTraverseCornerPoints. + This is a helper function for \ref draw. */ -void QCPCurve::getCurveData(QVector *lineData) const +QLineF QCPItemStraightLine::getRectClippedStraightLine(const QCPVector2D &base, const QCPVector2D &vec, const QRect &rect) const { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - // add margins to rect to compensate for stroke width - double strokeMargin = qMax(qreal(1.0), qreal(mainPen().widthF()*0.75)); // stroke radius + 50% safety - if (!mScatterStyle.isNone()) - strokeMargin = qMax(strokeMargin, mScatterStyle.size()); - double rectLeft = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().lower)-strokeMargin*((keyAxis->orientation()==Qt::Vertical)!=keyAxis->rangeReversed()?-1:1)); - double rectRight = keyAxis->pixelToCoord(keyAxis->coordToPixel(keyAxis->range().upper)+strokeMargin*((keyAxis->orientation()==Qt::Vertical)!=keyAxis->rangeReversed()?-1:1)); - double rectBottom = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().lower)+strokeMargin*((valueAxis->orientation()==Qt::Horizontal)!=valueAxis->rangeReversed()?-1:1)); - double rectTop = valueAxis->pixelToCoord(valueAxis->coordToPixel(valueAxis->range().upper)-strokeMargin*((valueAxis->orientation()==Qt::Horizontal)!=valueAxis->rangeReversed()?-1:1)); - int currentRegion; - QCPCurveDataMap::const_iterator it = mData->constBegin(); - QCPCurveDataMap::const_iterator prevIt = mData->constEnd()-1; - int prevRegion = getRegion(prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom); - QVector trailingPoints; // points that must be applied after all other points (are generated only when handling first point to get virtual segment between last and first point right) - while (it != mData->constEnd()) + double bx, by; + double gamma; + QLineF result; + if (vec.x() == 0 && vec.y() == 0) + return result; + if (qFuzzyIsNull(vec.x())) // line is vertical { - currentRegion = getRegion(it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom); - if (currentRegion != prevRegion) // changed region, possibly need to add some optimized edge points or original points if entering R + // check top of rect: + bx = rect.left(); + by = rect.top(); + gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y(); + if (gamma >= 0 && gamma <= rect.width()) + result.setLine(bx+gamma, rect.top(), bx+gamma, rect.bottom()); // no need to check bottom because we know line is vertical + } else if (qFuzzyIsNull(vec.y())) // line is horizontal + { + // check left of rect: + bx = rect.left(); + by = rect.top(); + gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x(); + if (gamma >= 0 && gamma <= rect.height()) + result.setLine(rect.left(), by+gamma, rect.right(), by+gamma); // no need to check right because we know line is horizontal + } else // line is skewed + { + QList pointVectors; + // check top of rect: + bx = rect.left(); + by = rect.top(); + gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y(); + if (gamma >= 0 && gamma <= rect.width()) + pointVectors.append(QCPVector2D(bx+gamma, by)); + // check bottom of rect: + bx = rect.left(); + by = rect.bottom(); + gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y(); + if (gamma >= 0 && gamma <= rect.width()) + pointVectors.append(QCPVector2D(bx+gamma, by)); + // check left of rect: + bx = rect.left(); + by = rect.top(); + gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x(); + if (gamma >= 0 && gamma <= rect.height()) + pointVectors.append(QCPVector2D(bx, by+gamma)); + // check right of rect: + bx = rect.right(); + by = rect.top(); + gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x(); + if (gamma >= 0 && gamma <= rect.height()) + pointVectors.append(QCPVector2D(bx, by+gamma)); + + // evaluate points: + if (pointVectors.size() == 2) { - if (currentRegion != 5) // segment doesn't end in R, so it's a candidate for removal + result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF()); + } else if (pointVectors.size() > 2) + { + // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance: + double distSqrMax = 0; + QCPVector2D pv1, pv2; + for (int i=0; iappend(getOptimizedPoint(currentRegion, it.value().key, it.value().value, prevIt.value().key, prevIt.value().value, rectLeft, rectTop, rectRight, rectBottom)); - // in the situations 5->1/7/9/3 the segment may leave R and directly cross through two outer regions. In these cases we need to add an additional corner point - *lineData << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom); - } else if (mayTraverse(prevRegion, currentRegion) && - getTraverse(prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom, crossA, crossB)) + for (int k=i+1; k beforeTraverseCornerPoints, afterTraverseCornerPoints; - getTraverseCornerPoints(prevRegion, currentRegion, rectLeft, rectTop, rectRight, rectBottom, beforeTraverseCornerPoints, afterTraverseCornerPoints); - if (it != mData->constBegin()) - { - *lineData << beforeTraverseCornerPoints; - lineData->append(crossA); - lineData->append(crossB); - *lineData << afterTraverseCornerPoints; - } else + double distSqr = (pointVectors.at(i)-pointVectors.at(k)).lengthSquared(); + if (distSqr > distSqrMax) { - lineData->append(crossB); - *lineData << afterTraverseCornerPoints; - trailingPoints << beforeTraverseCornerPoints << crossA ; + pv1 = pointVectors.at(i); + pv2 = pointVectors.at(k); + distSqrMax = distSqr; } - } else // doesn't cross R, line is just moving around in outside regions, so only need to add optimized point(s) at the boundary corner(s) - { - *lineData << getOptimizedCornerPoints(prevRegion, currentRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom); } - } else // segment does end in R, so we add previous point optimized and this point at original position - { - if (it == mData->constBegin()) // it is first point in curve and prevIt is last one. So save optimized point for adding it to the lineData in the end - trailingPoints << getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom); - else - lineData->append(getOptimizedPoint(prevRegion, prevIt.value().key, prevIt.value().value, it.value().key, it.value().value, rectLeft, rectTop, rectRight, rectBottom)); - lineData->append(coordsToPixels(it.value().key, it.value().value)); - } - } else // region didn't change - { - if (currentRegion == 5) // still in R, keep adding original points - { - lineData->append(coordsToPixels(it.value().key, it.value().value)); - } else // still outside R, no need to add anything - { - // see how this is not doing anything? That's the main optimization... } - } - prevIt = it; - prevRegion = currentRegion; - ++it; + result.setPoints(pv1.toPointF(), pv2.toPointF()); + } } - *lineData << trailingPoints; + return result; } /*! \internal + + Returns the pen that should be used for drawing lines. Returns mPen when the + item is not selected and mSelectedPen when it is. +*/ +QPen QCPItemStraightLine::mainPen() const +{ + return mSelected ? mSelectedPen : mPen; +} +/* end of 'src/items/item-straightline.cpp' */ + + +/* including file 'src/items/item-line.cpp' */ +/* modified 2022-11-06T12:45:56, size 8525 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPItemLine +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPItemLine + \brief A line from one point to another + + \image html QCPItemLine.png "Line example. Blue dotted circles are anchors, solid blue discs are positions." + + It has two positions, \a start and \a end, which define the end points of the line. - This function is part of the curve optimization algorithm of \ref getCurveData. + With \ref setHead and \ref setTail you may set different line ending styles, e.g. to create an arrow. +*/ + +/*! + Creates a line item and sets default values. - It returns the region of the given point (\a x, \a y) with respect to a rectangle defined by \a - rectLeft, \a rectTop, \a rectRight, and \a rectBottom. + The created item is automatically registered with \a parentPlot. This QCustomPlot instance takes + ownership of the item, so do not delete it manually but use QCustomPlot::removeItem() instead. +*/ +QCPItemLine::QCPItemLine(QCustomPlot *parentPlot) : + QCPAbstractItem(parentPlot), + start(createPosition(QLatin1String("start"))), + end(createPosition(QLatin1String("end"))) +{ + start->setCoords(0, 0); + end->setCoords(1, 1); - The regions are enumerated from top to bottom and left to right: + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue,2)); +} + +QCPItemLine::~QCPItemLine() +{ +} + +/*! + Sets the pen that will be used to draw the line - - - - -
147
258
369
+ \see setSelectedPen +*/ +void QCPItemLine::setPen(const QPen &pen) +{ + mPen = pen; +} + +/*! + Sets the pen that will be used to draw the line when selected - With the rectangle being region 5, and the outer regions extending infinitely outwards. In the - curve optimization algorithm, region 5 is considered to be the visible portion of the plot. + \see setPen, setSelected */ -int QCPCurve::getRegion(double x, double y, double rectLeft, double rectTop, double rectRight, double rectBottom) const +void QCPItemLine::setSelectedPen(const QPen &pen) { - if (x < rectLeft) // region 123 - { - if (y > rectTop) - return 1; - else if (y < rectBottom) - return 3; - else - return 2; - } else if (x > rectRight) // region 789 - { - if (y > rectTop) - return 7; - else if (y < rectBottom) - return 9; - else - return 8; - } else // region 456 - { - if (y > rectTop) - return 4; - else if (y < rectBottom) - return 6; - else - return 5; - } + mSelectedPen = pen; } -/*! \internal +/*! + Sets the line ending style of the head. The head corresponds to the \a end position. - This function is part of the curve optimization algorithm of \ref getCurveData. + Note that due to the overloaded QCPLineEnding constructor, you may directly specify + a QCPLineEnding::EndingStyle here, e.g. \code setHead(QCPLineEnding::esSpikeArrow) \endcode - This method is used in case the current segment passes from inside the visible rect (region 5, - see \ref getRegion) to any of the outer regions (\a otherRegion). The current segment is given by - the line connecting (\a key, \a value) with (\a otherKey, \a otherValue). + \see setTail +*/ +void QCPItemLine::setHead(const QCPLineEnding &head) +{ + mHead = head; +} + +/*! + Sets the line ending style of the tail. The tail corresponds to the \a start position. - It returns the intersection point of the segment with the border of region 5. + Note that due to the overloaded QCPLineEnding constructor, you may directly specify + a QCPLineEnding::EndingStyle here, e.g. \code setTail(QCPLineEnding::esSpikeArrow) \endcode - For this function it doesn't matter whether (\a key, \a value) is the point inside region 5 or - whether it's (\a otherKey, \a otherValue), i.e. whether the segment is coming from region 5 or - leaving it. It is important though that \a otherRegion correctly identifies the other region not - equal to 5. + \see setHead */ -QPointF QCPCurve::getOptimizedPoint(int otherRegion, double otherKey, double otherValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const +void QCPItemLine::setTail(const QCPLineEnding &tail) { - double intersectKey = rectLeft; // initial value is just fail-safe - double intersectValue = rectTop; // initial value is just fail-safe - switch (otherRegion) + mTail = tail; +} + +/* inherits documentation from base class */ +double QCPItemLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +{ + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + + return qSqrt(QCPVector2D(pos).distanceSquaredToLine(start->pixelPosition(), end->pixelPosition())); +} + +/* inherits documentation from base class */ +void QCPItemLine::draw(QCPPainter *painter) +{ + QCPVector2D startVec(start->pixelPosition()); + QCPVector2D endVec(end->pixelPosition()); + if (qFuzzyIsNull((startVec-endVec).lengthSquared())) + return; + // get visible segment of straight line inside clipRect: + int clipPad = int(qMax(mHead.boundingDistance(), mTail.boundingDistance())); + clipPad = qMax(clipPad, qCeil(mainPen().widthF())); + QLineF line = getRectClippedLine(startVec, endVec, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad)); + // paint visible segment, if existent: + if (!line.isNull()) { - case 1: // top and left edge - { - intersectValue = rectTop; - intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue); - if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other: - { - intersectKey = rectLeft; - intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey); - } - break; - } - case 2: // left edge - { - intersectKey = rectLeft; - intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey); - break; - } - case 3: // bottom and left edge - { - intersectValue = rectBottom; - intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue); - if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other: - { - intersectKey = rectLeft; - intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey); - } - break; - } - case 4: // top edge - { - intersectValue = rectTop; - intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue); - break; - } - case 5: - { - break; // case 5 shouldn't happen for this function but we add it anyway to prevent potential discontinuity in branch table - } - case 6: // bottom edge - { - intersectValue = rectBottom; - intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue); - break; - } - case 7: // top and right edge - { - intersectValue = rectTop; - intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue); - if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other: - { - intersectKey = rectRight; - intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey); - } - break; - } - case 8: // right edge - { - intersectKey = rectRight; - intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey); - break; - } - case 9: // bottom and right edge - { - intersectValue = rectBottom; - intersectKey = otherKey + (key-otherKey)/(value-otherValue)*(intersectValue-otherValue); - if (intersectKey < rectLeft || intersectKey > rectRight) // doesn't intersect, so must intersect other: - { - intersectKey = rectRight; - intersectValue = otherValue + (value-otherValue)/(key-otherKey)*(intersectKey-otherKey); - } - break; - } + painter->setPen(mainPen()); + painter->drawLine(line); + painter->setBrush(Qt::SolidPattern); + if (mTail.style() != QCPLineEnding::esNone) + mTail.draw(painter, startVec, startVec-endVec); + if (mHead.style() != QCPLineEnding::esNone) + mHead.draw(painter, endVec, endVec-startVec); } - return coordsToPixels(intersectKey, intersectValue); } /*! \internal + + Returns the section of the line defined by \a start and \a end, that is visible in the specified + \a rect. - This function is part of the curve optimization algorithm of \ref getCurveData. - - In situations where a single segment skips over multiple regions it might become necessary to add - extra points at the corners of region 5 (see \ref getRegion) such that the optimized segment - doesn't unintentionally cut through the visible area of the axis rect and create plot artifacts. - This method provides these points that must be added, assuming the original segment doesn't - start, end, or traverse region 5. (Corner points where region 5 is traversed are calculated by - \ref getTraverseCornerPoints.) - - For example, consider a segment which directly goes from region 4 to 2 but originally is far out - to the top left such that it doesn't cross region 5. Naively optimizing these points by - projecting them on the top and left borders of region 5 will create a segment that surely crosses - 5, creating a visual artifact in the plot. This method prevents this by providing extra points at - the top left corner, making the optimized curve correctly pass from region 4 to 1 to 2 without - traversing 5. + This is a helper function for \ref draw. */ -QVector QCPCurve::getOptimizedCornerPoints(int prevRegion, int currentRegion, double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const +QLineF QCPItemLine::getRectClippedLine(const QCPVector2D &start, const QCPVector2D &end, const QRect &rect) const { - QVector result; - switch (prevRegion) + bool containsStart = rect.contains(qRound(start.x()), qRound(start.y())); + bool containsEnd = rect.contains(qRound(end.x()), qRound(end.y())); + if (containsStart && containsEnd) + return {start.toPointF(), end.toPointF()}; + + QCPVector2D base = start; + QCPVector2D vec = end-start; + double bx, by; + double gamma, mu; + QLineF result; + QList pointVectors; + + if (!qFuzzyIsNull(vec.y())) // line is not horizontal { - case 1: - { - switch (currentRegion) - { - case 2: { result << coordsToPixels(rectLeft, rectTop); break; } - case 4: { result << coordsToPixels(rectLeft, rectTop); break; } - case 3: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); break; } - case 7: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); break; } - case 6: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; } - case 8: { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; } - case 9: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points - if ((value-prevValue)/(key-prevKey)*(rectLeft-key)+value < rectBottom) // segment passes below R - { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); } - else - { result << coordsToPixels(rectLeft, rectTop) << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); } - break; - } - } - break; - } - case 2: - { - switch (currentRegion) - { - case 1: { result << coordsToPixels(rectLeft, rectTop); break; } - case 3: { result << coordsToPixels(rectLeft, rectBottom); break; } - case 4: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; } - case 6: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; } - case 7: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); break; } - case 9: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); break; } - } - break; - } - case 3: - { - switch (currentRegion) - { - case 2: { result << coordsToPixels(rectLeft, rectBottom); break; } - case 6: { result << coordsToPixels(rectLeft, rectBottom); break; } - case 1: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); break; } - case 9: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); break; } - case 4: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; } - case 8: { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; } - case 7: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points - if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom) // segment passes below R - { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); } - else - { result << coordsToPixels(rectLeft, rectBottom) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); } - break; - } - } - break; - } - case 4: - { - switch (currentRegion) - { - case 1: { result << coordsToPixels(rectLeft, rectTop); break; } - case 7: { result << coordsToPixels(rectRight, rectTop); break; } - case 2: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; } - case 8: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; } - case 3: { result << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); break; } - case 9: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectRight, rectBottom); break; } - } - break; - } - case 5: + // check top of rect: + bx = rect.left(); + by = rect.top(); + mu = (by-base.y())/vec.y(); + if (mu >= 0 && mu <= 1) { - switch (currentRegion) - { - case 1: { result << coordsToPixels(rectLeft, rectTop); break; } - case 7: { result << coordsToPixels(rectRight, rectTop); break; } - case 9: { result << coordsToPixels(rectRight, rectBottom); break; } - case 3: { result << coordsToPixels(rectLeft, rectBottom); break; } - } - break; + gamma = base.x()-bx + mu*vec.x(); + if (gamma >= 0 && gamma <= rect.width()) + pointVectors.append(QCPVector2D(bx+gamma, by)); } - case 6: + // check bottom of rect: + bx = rect.left(); + by = rect.bottom(); + mu = (by-base.y())/vec.y(); + if (mu >= 0 && mu <= 1) { - switch (currentRegion) - { - case 3: { result << coordsToPixels(rectLeft, rectBottom); break; } - case 9: { result << coordsToPixels(rectRight, rectBottom); break; } - case 2: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); break; } - case 8: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; } - case 1: { result << coordsToPixels(rectLeft, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); break; } - case 7: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectRight, rectTop); break; } - } - break; + gamma = base.x()-bx + mu*vec.x(); + if (gamma >= 0 && gamma <= rect.width()) + pointVectors.append(QCPVector2D(bx+gamma, by)); } - case 7: + } + if (!qFuzzyIsNull(vec.x())) // line is not vertical + { + // check left of rect: + bx = rect.left(); + by = rect.top(); + mu = (bx-base.x())/vec.x(); + if (mu >= 0 && mu <= 1) { - switch (currentRegion) - { - case 4: { result << coordsToPixels(rectRight, rectTop); break; } - case 8: { result << coordsToPixels(rectRight, rectTop); break; } - case 1: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); break; } - case 9: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); break; } - case 2: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); break; } - case 6: { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; } - case 3: { // in this case we need another distinction of cases: segment may pass below or above rect, requiring either bottom right or top left corner points - if ((value-prevValue)/(key-prevKey)*(rectRight-key)+value < rectBottom) // segment passes below R - { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); } - else - { result << coordsToPixels(rectRight, rectTop) << coordsToPixels(rectLeft, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); } - break; - } - } - break; + gamma = base.y()-by + mu*vec.y(); + if (gamma >= 0 && gamma <= rect.height()) + pointVectors.append(QCPVector2D(bx, by+gamma)); } - case 8: + // check right of rect: + bx = rect.right(); + by = rect.top(); + mu = (bx-base.x())/vec.x(); + if (mu >= 0 && mu <= 1) { - switch (currentRegion) - { - case 7: { result << coordsToPixels(rectRight, rectTop); break; } - case 9: { result << coordsToPixels(rectRight, rectBottom); break; } - case 4: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); break; } - case 6: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); break; } - case 1: { result << coordsToPixels(rectRight, rectTop); result.append(result.last()); result << coordsToPixels(rectLeft, rectTop); break; } - case 3: { result << coordsToPixels(rectRight, rectBottom); result.append(result.last()); result << coordsToPixels(rectLeft, rectBottom); break; } - } - break; + gamma = base.y()-by + mu*vec.y(); + if (gamma >= 0 && gamma <= rect.height()) + pointVectors.append(QCPVector2D(bx, by+gamma)); } - case 9: + } + + if (containsStart) + pointVectors.append(start); + if (containsEnd) + pointVectors.append(end); + + // evaluate points: + if (pointVectors.size() == 2) + { + result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF()); + } else if (pointVectors.size() > 2) + { + // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance: + double distSqrMax = 0; + QCPVector2D pv1, pv2; + for (int i=0; i distSqrMax) + { + pv1 = pointVectors.at(i); + pv2 = pointVectors.at(k); + distSqrMax = distSqr; } } - break; } + result.setPoints(pv1.toPointF(), pv2.toPointF()); } return result; } /*! \internal + + Returns the pen that should be used for drawing lines. Returns mPen when the + item is not selected and mSelectedPen when it is. +*/ +QPen QCPItemLine::mainPen() const +{ + return mSelected ? mSelectedPen : mPen; +} +/* end of 'src/items/item-line.cpp' */ + + +/* including file 'src/items/item-curve.cpp' */ +/* modified 2022-11-06T12:45:56, size 7273 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPItemCurve +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPItemCurve + \brief A curved line from one point to another + + \image html QCPItemCurve.png "Curve example. Blue dotted circles are anchors, solid blue discs are positions." + + It has four positions, \a start and \a end, which define the end points of the line, and two + control points which define the direction the line exits from the start and the direction from + which it approaches the end: \a startDir and \a endDir. - This function is part of the curve optimization algorithm of \ref getCurveData. + With \ref setHead and \ref setTail you may set different line ending styles, e.g. to create an + arrow. - This method returns whether a segment going from \a prevRegion to \a currentRegion (see \ref - getRegion) may traverse the visible region 5. This function assumes that neither \a prevRegion - nor \a currentRegion is 5 itself. + Often it is desirable for the control points to stay at fixed relative positions to the start/end + point. This can be achieved by setting the parent anchor e.g. of \a startDir simply to \a start, + and then specify the desired pixel offset with QCPItemPosition::setCoords on \a startDir. +*/ + +/*! + Creates a curve item and sets default values. - If this method returns false, the segment for sure doesn't pass region 5. If it returns true, the - segment may or may not pass region 5 and a more fine-grained calculation must be used (\ref - getTraverse). + The created item is automatically registered with \a parentPlot. This QCustomPlot instance takes + ownership of the item, so do not delete it manually but use QCustomPlot::removeItem() instead. */ -bool QCPCurve::mayTraverse(int prevRegion, int currentRegion) const +QCPItemCurve::QCPItemCurve(QCustomPlot *parentPlot) : + QCPAbstractItem(parentPlot), + start(createPosition(QLatin1String("start"))), + startDir(createPosition(QLatin1String("startDir"))), + endDir(createPosition(QLatin1String("endDir"))), + end(createPosition(QLatin1String("end"))) { - switch (prevRegion) - { - case 1: - { - switch (currentRegion) - { - case 4: - case 7: - case 2: - case 3: return false; - default: return true; - } - } - case 2: - { - switch (currentRegion) - { - case 1: - case 3: return false; - default: return true; - } - } - case 3: - { - switch (currentRegion) - { - case 1: - case 2: - case 6: - case 9: return false; - default: return true; - } - } - case 4: - { - switch (currentRegion) - { - case 1: - case 7: return false; - default: return true; - } - } - case 5: return false; // should never occur - case 6: - { - switch (currentRegion) - { - case 3: - case 9: return false; - default: return true; - } - } - case 7: - { - switch (currentRegion) - { - case 1: - case 4: - case 8: - case 9: return false; - default: return true; - } - } - case 8: - { - switch (currentRegion) - { - case 7: - case 9: return false; - default: return true; - } - } - case 9: - { - switch (currentRegion) - { - case 3: - case 6: - case 8: - case 7: return false; - default: return true; - } - } - default: return true; - } + start->setCoords(0, 0); + startDir->setCoords(0.5, 0); + endDir->setCoords(0, 0.5); + end->setCoords(1, 1); + + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue,2)); } +QCPItemCurve::~QCPItemCurve() +{ +} -/*! \internal +/*! + Sets the pen that will be used to draw the line + + \see setSelectedPen +*/ +void QCPItemCurve::setPen(const QPen &pen) +{ + mPen = pen; +} + +/*! + Sets the pen that will be used to draw the line when selected - This function is part of the curve optimization algorithm of \ref getCurveData. + \see setPen, setSelected +*/ +void QCPItemCurve::setSelectedPen(const QPen &pen) +{ + mSelectedPen = pen; +} + +/*! + Sets the line ending style of the head. The head corresponds to the \a end position. - This method assumes that the \ref mayTraverse test has returned true, so there is a chance the - segment defined by (\a prevKey, \a prevValue) and (\a key, \a value) goes through the visible - region 5. + Note that due to the overloaded QCPLineEnding constructor, you may directly specify + a QCPLineEnding::EndingStyle here, e.g. \code setHead(QCPLineEnding::esSpikeArrow) \endcode - The return value of this method indicates whether the segment actually traverses region 5 or not. + \see setTail +*/ +void QCPItemCurve::setHead(const QCPLineEnding &head) +{ + mHead = head; +} + +/*! + Sets the line ending style of the tail. The tail corresponds to the \a start position. - If the segment traverses 5, the output parameters \a crossA and \a crossB indicate the entry and - exit points of region 5. They will become the optimized points for that segment. + Note that due to the overloaded QCPLineEnding constructor, you may directly specify + a QCPLineEnding::EndingStyle here, e.g. \code setTail(QCPLineEnding::esSpikeArrow) \endcode + + \see setHead */ -bool QCPCurve::getTraverse(double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom, QPointF &crossA, QPointF &crossB) const +void QCPItemCurve::setTail(const QCPLineEnding &tail) { - QList intersections; // x of QPointF corresponds to key and y to value - if (qFuzzyIsNull(key-prevKey)) // line is parallel to value axis - { - // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is traversed here - intersections.append(QPointF(key, rectBottom)); // direction will be taken care of at end of method - intersections.append(QPointF(key, rectTop)); - } else if (qFuzzyIsNull(value-prevValue)) // line is parallel to key axis - { - // due to region filter in mayTraverseR(), if line is parallel to value or key axis, R is traversed here - intersections.append(QPointF(rectLeft, value)); // direction will be taken care of at end of method - intersections.append(QPointF(rectRight, value)); - } else // line is skewed - { - double gamma; - double keyPerValue = (key-prevKey)/(value-prevValue); - // check top of rect: - gamma = prevKey + (rectTop-prevValue)*keyPerValue; - if (gamma >= rectLeft && gamma <= rectRight) - intersections.append(QPointF(gamma, rectTop)); - // check bottom of rect: - gamma = prevKey + (rectBottom-prevValue)*keyPerValue; - if (gamma >= rectLeft && gamma <= rectRight) - intersections.append(QPointF(gamma, rectBottom)); - double valuePerKey = 1.0/keyPerValue; - // check left of rect: - gamma = prevValue + (rectLeft-prevKey)*valuePerKey; - if (gamma >= rectBottom && gamma <= rectTop) - intersections.append(QPointF(rectLeft, gamma)); - // check right of rect: - gamma = prevValue + (rectRight-prevKey)*valuePerKey; - if (gamma >= rectBottom && gamma <= rectTop) - intersections.append(QPointF(rectRight, gamma)); - } + mTail = tail; +} + +/* inherits documentation from base class */ +double QCPItemCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +{ + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; - // handle cases where found points isn't exactly 2: - if (intersections.size() > 2) + QPointF startVec(start->pixelPosition()); + QPointF startDirVec(startDir->pixelPosition()); + QPointF endDirVec(endDir->pixelPosition()); + QPointF endVec(end->pixelPosition()); + + QPainterPath cubicPath(startVec); + cubicPath.cubicTo(startDirVec, endDirVec, endVec); + + QList polygons = cubicPath.toSubpathPolygons(); + if (polygons.isEmpty()) + return -1; + const QPolygonF polygon = polygons.first(); + QCPVector2D p(pos); + double minDistSqr = (std::numeric_limits::max)(); + for (int i=1; i distSqrMax) - { - pv1 = intersections.at(i); - pv2 = intersections.at(k); - distSqrMax = distSqr; - } - } - } - intersections = QList() << pv1 << pv2; - } else if (intersections.size() != 2) + double distSqr = p.distanceSquaredToLine(polygon.at(i-1), polygon.at(i)); + if (distSqr < minDistSqr) + minDistSqr = distSqr; + } + return qSqrt(minDistSqr); +} + +/* inherits documentation from base class */ +void QCPItemCurve::draw(QCPPainter *painter) +{ + QCPVector2D startVec(start->pixelPosition()); + QCPVector2D startDirVec(startDir->pixelPosition()); + QCPVector2D endDirVec(endDir->pixelPosition()); + QCPVector2D endVec(end->pixelPosition()); + if ((endVec-startVec).length() > 1e10) // too large curves cause crash + return; + + QPainterPath cubicPath(startVec.toPointF()); + cubicPath.cubicTo(startDirVec.toPointF(), endDirVec.toPointF(), endVec.toPointF()); + + // paint visible segment, if existent: + const int clipEnlarge = qCeil(mainPen().widthF()); + QRect clip = clipRect().adjusted(-clipEnlarge, -clipEnlarge, clipEnlarge, clipEnlarge); + QRect cubicRect = cubicPath.controlPointRect().toRect(); + if (cubicRect.isEmpty()) // may happen when start and end exactly on same x or y position + cubicRect.adjust(0, 0, 1, 1); + if (clip.intersects(cubicRect)) { - // one or even zero points found (shouldn't happen unless line perfectly tangent to corner), no need to draw segment - return false; + painter->setPen(mainPen()); + painter->drawPath(cubicPath); + painter->setBrush(Qt::SolidPattern); + if (mTail.style() != QCPLineEnding::esNone) + mTail.draw(painter, startVec, M_PI-cubicPath.angleAtPercent(0)/180.0*M_PI); + if (mHead.style() != QCPLineEnding::esNone) + mHead.draw(painter, endVec, -cubicPath.angleAtPercent(1)/180.0*M_PI); } - - // possibly re-sort points so optimized point segment has same direction as original segment: - if ((key-prevKey)*(intersections.at(1).x()-intersections.at(0).x()) + (value-prevValue)*(intersections.at(1).y()-intersections.at(0).y()) < 0) // scalar product of both segments < 0 -> opposite direction - intersections.move(0, 1); - crossA = coordsToPixels(intersections.at(0).x(), intersections.at(0).y()); - crossB = coordsToPixels(intersections.at(1).x(), intersections.at(1).y()); - return true; } /*! \internal + + Returns the pen that should be used for drawing lines. Returns mPen when the + item is not selected and mSelectedPen when it is. +*/ +QPen QCPItemCurve::mainPen() const +{ + return mSelected ? mSelectedPen : mPen; +} +/* end of 'src/items/item-curve.cpp' */ + + +/* including file 'src/items/item-rect.cpp' */ +/* modified 2022-11-06T12:45:56, size 6472 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPItemRect +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPItemRect + \brief A rectangle + + \image html QCPItemRect.png "Rectangle example. Blue dotted circles are anchors, solid blue discs are positions." + + It has two positions, \a topLeft and \a bottomRight, which define the rectangle. +*/ + +/*! + Creates a rectangle item and sets default values. - This function is part of the curve optimization algorithm of \ref getCurveData. + The created item is automatically registered with \a parentPlot. This QCustomPlot instance takes + ownership of the item, so do not delete it manually but use QCustomPlot::removeItem() instead. +*/ +QCPItemRect::QCPItemRect(QCustomPlot *parentPlot) : + QCPAbstractItem(parentPlot), + topLeft(createPosition(QLatin1String("topLeft"))), + bottomRight(createPosition(QLatin1String("bottomRight"))), + top(createAnchor(QLatin1String("top"), aiTop)), + topRight(createAnchor(QLatin1String("topRight"), aiTopRight)), + right(createAnchor(QLatin1String("right"), aiRight)), + bottom(createAnchor(QLatin1String("bottom"), aiBottom)), + bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)), + left(createAnchor(QLatin1String("left"), aiLeft)) +{ + topLeft->setCoords(0, 1); + bottomRight->setCoords(1, 0); - This method assumes that the \ref getTraverse test has returned true, so the segment definitely - traverses the visible region 5 when going from \a prevRegion to \a currentRegion. + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue,2)); + setBrush(Qt::NoBrush); + setSelectedBrush(Qt::NoBrush); +} + +QCPItemRect::~QCPItemRect() +{ +} + +/*! + Sets the pen that will be used to draw the line of the rectangle - In certain situations it is not sufficient to merely generate the entry and exit points of the - segment into/out of region 5, as \ref getTraverse provides. It may happen that a single segment, in - addition to traversing region 5, skips another region outside of region 5, which makes it - necessary to add an optimized corner point there (very similar to the job \ref - getOptimizedCornerPoints does for segments that are completely in outside regions and don't - traverse 5). + \see setSelectedPen, setBrush +*/ +void QCPItemRect::setPen(const QPen &pen) +{ + mPen = pen; +} + +/*! + Sets the pen that will be used to draw the line of the rectangle when selected - As an example, consider a segment going from region 1 to region 6, traversing the lower left - corner of region 5. In this configuration, the segment additionally crosses the border between - region 1 and 2 before entering region 5. This makes it necessary to add an additional point in - the top left corner, before adding the optimized traverse points. So in this case, the output - parameter \a beforeTraverse will contain the top left corner point, and \a afterTraverse will be - empty. + \see setPen, setSelected +*/ +void QCPItemRect::setSelectedPen(const QPen &pen) +{ + mSelectedPen = pen; +} + +/*! + Sets the brush that will be used to fill the rectangle. To disable filling, set \a brush to + Qt::NoBrush. - In some cases, such as when going from region 1 to 9, it may even be necessary to add additional - corner points before and after the traverse. Then both \a beforeTraverse and \a afterTraverse - return the respective corner points. + \see setSelectedBrush, setPen */ -void QCPCurve::getTraverseCornerPoints(int prevRegion, int currentRegion, double rectLeft, double rectTop, double rectRight, double rectBottom, QVector &beforeTraverse, QVector &afterTraverse) const +void QCPItemRect::setBrush(const QBrush &brush) { - switch (prevRegion) - { - case 1: - { - switch (currentRegion) - { - case 6: { beforeTraverse << coordsToPixels(rectLeft, rectTop); break; } - case 9: { beforeTraverse << coordsToPixels(rectLeft, rectTop); afterTraverse << coordsToPixels(rectRight, rectBottom); break; } - case 8: { beforeTraverse << coordsToPixels(rectLeft, rectTop); break; } - } - break; - } - case 2: - { - switch (currentRegion) - { - case 7: { afterTraverse << coordsToPixels(rectRight, rectTop); break; } - case 9: { afterTraverse << coordsToPixels(rectRight, rectBottom); break; } - } - break; - } - case 3: - { - switch (currentRegion) - { - case 4: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); break; } - case 7: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); afterTraverse << coordsToPixels(rectRight, rectTop); break; } - case 8: { beforeTraverse << coordsToPixels(rectLeft, rectBottom); break; } - } - break; - } - case 4: - { - switch (currentRegion) - { - case 3: { afterTraverse << coordsToPixels(rectLeft, rectBottom); break; } - case 9: { afterTraverse << coordsToPixels(rectRight, rectBottom); break; } - } - break; - } - case 5: { break; } // shouldn't happen because this method only handles full traverses - case 6: - { - switch (currentRegion) - { - case 1: { afterTraverse << coordsToPixels(rectLeft, rectTop); break; } - case 7: { afterTraverse << coordsToPixels(rectRight, rectTop); break; } - } - break; - } - case 7: - { - switch (currentRegion) - { - case 2: { beforeTraverse << coordsToPixels(rectRight, rectTop); break; } - case 3: { beforeTraverse << coordsToPixels(rectRight, rectTop); afterTraverse << coordsToPixels(rectLeft, rectBottom); break; } - case 6: { beforeTraverse << coordsToPixels(rectRight, rectTop); break; } - } - break; - } - case 8: - { - switch (currentRegion) - { - case 1: { afterTraverse << coordsToPixels(rectLeft, rectTop); break; } - case 3: { afterTraverse << coordsToPixels(rectLeft, rectBottom); break; } - } - break; - } - case 9: - { - switch (currentRegion) - { - case 2: { beforeTraverse << coordsToPixels(rectRight, rectBottom); break; } - case 1: { beforeTraverse << coordsToPixels(rectRight, rectBottom); afterTraverse << coordsToPixels(rectLeft, rectTop); break; } - case 4: { beforeTraverse << coordsToPixels(rectRight, rectBottom); break; } - } - break; - } - } + mBrush = brush; } -/*! \internal +/*! + Sets the brush that will be used to fill the rectangle when selected. To disable filling, set \a + brush to Qt::NoBrush. - Calculates the (minimum) distance (in pixels) the curve's representation has from the given \a - pixelPoint in pixels. This is used to determine whether the curve was clicked or not, e.g. in - \ref selectTest. + \see setBrush */ -double QCPCurve::pointDistance(const QPointF &pixelPoint) const +void QCPItemRect::setSelectedBrush(const QBrush &brush) { - if (mData->isEmpty()) - { - qDebug() << Q_FUNC_INFO << "requested point distance on curve" << mName << "without data"; - return 500; - } - if (mData->size() == 1) - { - QPointF dataPoint = coordsToPixels(mData->constBegin().key(), mData->constBegin().value().value); - return QVector2D(dataPoint-pixelPoint).length(); - } + mSelectedBrush = brush; +} + +/* inherits documentation from base class */ +double QCPItemRect::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +{ + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; - // calculate minimum distance to line segments: - QVector *lineData = new QVector; - getCurveData(lineData); - double minDistSqr = std::numeric_limits::max(); - for (int i=0; isize()-1; ++i) + QRectF rect = QRectF(topLeft->pixelPosition(), bottomRight->pixelPosition()).normalized(); + bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0; + return rectDistance(rect, pos, filledRect); +} + +/* inherits documentation from base class */ +void QCPItemRect::draw(QCPPainter *painter) +{ + QPointF p1 = topLeft->pixelPosition(); + QPointF p2 = bottomRight->pixelPosition(); + if (p1.toPoint() == p2.toPoint()) + return; + QRectF rect = QRectF(p1, p2).normalized(); + double clipPad = mainPen().widthF(); + QRectF boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad); + if (boundingRect.intersects(clipRect())) // only draw if bounding rect of rect item is visible in cliprect { - double currentDistSqr = distSqrToLine(lineData->at(i), lineData->at(i+1), pixelPoint); - if (currentDistSqr < minDistSqr) - minDistSqr = currentDistSqr; + painter->setPen(mainPen()); + painter->setBrush(mainBrush()); + painter->drawRect(rect); } - delete lineData; - return qSqrt(minDistSqr); } /* inherits documentation from base class */ -QCPRange QCPCurve::getKeyRange(bool &foundRange, SignDomain inSignDomain) const +QPointF QCPItemRect::anchorPixelPosition(int anchorId) const { - QCPRange range; - bool haveLower = false; - bool haveUpper = false; - - double current; - - QCPCurveDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) + QRectF rect = QRectF(topLeft->pixelPosition(), bottomRight->pixelPosition()); + switch (anchorId) { - current = it.value().key; - if (!qIsNaN(current) && !qIsNaN(it.value().value)) - { - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) - { - if (current < range.lower || !haveLower) - { - range.lower = current; - haveLower = true; - } - if (current > range.upper || !haveUpper) - { - range.upper = current; - haveUpper = true; - } - } - } - ++it; + case aiTop: return (rect.topLeft()+rect.topRight())*0.5; + case aiTopRight: return rect.topRight(); + case aiRight: return (rect.topRight()+rect.bottomRight())*0.5; + case aiBottom: return (rect.bottomLeft()+rect.bottomRight())*0.5; + case aiBottomLeft: return rect.bottomLeft(); + case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5; } - foundRange = haveLower && haveUpper; - return range; + qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; + return {}; } -/* inherits documentation from base class */ -QCPRange QCPCurve::getValueRange(bool &foundRange, SignDomain inSignDomain) const +/*! \internal + + Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected + and mSelectedPen when it is. +*/ +QPen QCPItemRect::mainPen() const { - QCPRange range; - bool haveLower = false; - bool haveUpper = false; - - double current; - - QCPCurveDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().value; - if (!qIsNaN(current) && !qIsNaN(it.value().key)) - { - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) - { - if (current < range.lower || !haveLower) - { - range.lower = current; - haveLower = true; - } - if (current > range.upper || !haveUpper) - { - range.upper = current; - haveUpper = true; - } - } - } - ++it; - } - - foundRange = haveLower && haveUpper; - return range; + return mSelected ? mSelectedPen : mPen; +} + +/*! \internal + + Returns the brush that should be used for drawing fills of the item. Returns mBrush when the item + is not selected and mSelectedBrush when it is. +*/ +QBrush QCPItemRect::mainBrush() const +{ + return mSelected ? mSelectedBrush : mBrush; } +/* end of 'src/items/item-rect.cpp' */ + +/* including file 'src/items/item-text.cpp' */ +/* modified 2022-11-06T12:45:56, size 13335 */ //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPBarsGroup +//////////////////// QCPItemText //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPBarsGroup - \brief Groups multiple QCPBars together so they appear side by side - - \image html QCPBarsGroup.png - - When showing multiple QCPBars in one plot which have bars at identical keys, it may be desirable - to have them appearing next to each other at each key. This is what adding the respective QCPBars - plottables to a QCPBarsGroup achieves. (An alternative approach is to stack them on top of each - other, see \ref QCPBars::moveAbove.) - - \section qcpbarsgroup-usage Usage - - To add a QCPBars plottable to the group, create a new group and then add the respective bars - intances: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpbarsgroup-creation - Alternatively to appending to the group like shown above, you can also set the group on the - QCPBars plottable via \ref QCPBars::setBarsGroup. - - The spacing between the bars can be configured via \ref setSpacingType and \ref setSpacing. The - bars in this group appear in the plot in the order they were appended. To insert a bars plottable - at a certain index position, or to reposition a bars plottable which is already in the group, use - \ref insert. +/*! \class QCPItemText + \brief A text label + + \image html QCPItemText.png "Text example. Blue dotted circles are anchors, solid blue discs are positions." + + Its position is defined by the member \a position and the setting of \ref setPositionAlignment. + The latter controls which part of the text rect shall be aligned with \a position. - To remove specific bars from the group, use either \ref remove or call \ref - QCPBars::setBarsGroup "QCPBars::setBarsGroup(0)" on the respective bars plottable. + The text alignment itself (i.e. left, center, right) can be controlled with \ref + setTextAlignment. - To clear the entire group, call \ref clear, or simply delete the group. + The text may be rotated around the \a position point with \ref setRotation. +*/ + +/*! + Creates a text item and sets default values. - \section qcpbarsgroup-example Example + The created item is automatically registered with \a parentPlot. This QCustomPlot instance takes + ownership of the item, so do not delete it manually but use QCustomPlot::removeItem() instead. +*/ +QCPItemText::QCPItemText(QCustomPlot *parentPlot) : + QCPAbstractItem(parentPlot), + position(createPosition(QLatin1String("position"))), + topLeft(createAnchor(QLatin1String("topLeft"), aiTopLeft)), + top(createAnchor(QLatin1String("top"), aiTop)), + topRight(createAnchor(QLatin1String("topRight"), aiTopRight)), + right(createAnchor(QLatin1String("right"), aiRight)), + bottomRight(createAnchor(QLatin1String("bottomRight"), aiBottomRight)), + bottom(createAnchor(QLatin1String("bottom"), aiBottom)), + bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)), + left(createAnchor(QLatin1String("left"), aiLeft)), + mText(QLatin1String("text")), + mPositionAlignment(Qt::AlignCenter), + mTextAlignment(Qt::AlignTop|Qt::AlignHCenter), + mRotation(0) +{ + position->setCoords(0, 0); - The image above is generated with the following code: - \snippet documentation/doc-image-generator/mainwindow.cpp qcpbarsgroup-example + setPen(Qt::NoPen); + setSelectedPen(Qt::NoPen); + setBrush(Qt::NoBrush); + setSelectedBrush(Qt::NoBrush); + setColor(Qt::black); + setSelectedColor(Qt::blue); +} + +QCPItemText::~QCPItemText() +{ +} + +/*! + Sets the color of the text. */ +void QCPItemText::setColor(const QColor &color) +{ + mColor = color; +} -/* start of documentation of inline functions */ +/*! + Sets the color of the text that will be used when the item is selected. +*/ +void QCPItemText::setSelectedColor(const QColor &color) +{ + mSelectedColor = color; +} -/*! \fn QList QCPBarsGroup::bars() const +/*! + Sets the pen that will be used do draw a rectangular border around the text. To disable the + border, set \a pen to Qt::NoPen. - Returns all bars currently in this group. + \see setSelectedPen, setBrush, setPadding +*/ +void QCPItemText::setPen(const QPen &pen) +{ + mPen = pen; +} + +/*! + Sets the pen that will be used do draw a rectangular border around the text, when the item is + selected. To disable the border, set \a pen to Qt::NoPen. - \see bars(int index) + \see setPen */ +void QCPItemText::setSelectedPen(const QPen &pen) +{ + mSelectedPen = pen; +} -/*! \fn int QCPBarsGroup::size() const +/*! + Sets the brush that will be used do fill the background of the text. To disable the + background, set \a brush to Qt::NoBrush. - Returns the number of QCPBars plottables that are part of this group. + \see setSelectedBrush, setPen, setPadding +*/ +void QCPItemText::setBrush(const QBrush &brush) +{ + mBrush = brush; +} + +/*! + Sets the brush that will be used do fill the background of the text, when the item is selected. To disable the + background, set \a brush to Qt::NoBrush. + \see setBrush */ +void QCPItemText::setSelectedBrush(const QBrush &brush) +{ + mSelectedBrush = brush; +} -/*! \fn bool QCPBarsGroup::isEmpty() const +/*! + Sets the font of the text. - Returns whether this bars group is empty. + \see setSelectedFont, setColor +*/ +void QCPItemText::setFont(const QFont &font) +{ + mFont = font; +} + +/*! + Sets the font of the text that will be used when the item is selected. - \see size + \see setFont +*/ +void QCPItemText::setSelectedFont(const QFont &font) +{ + mSelectedFont = font; +} + +/*! + Sets the text that will be displayed. Multi-line texts are supported by inserting a line break + character, e.g. '\n'. + + \see setFont, setColor, setTextAlignment */ +void QCPItemText::setText(const QString &text) +{ + mText = text; +} -/*! \fn bool QCPBarsGroup::contains(QCPBars *bars) +/*! + Sets which point of the text rect shall be aligned with \a position. - Returns whether the specified \a bars plottable is part of this group. + Examples: + \li If \a alignment is Qt::AlignHCenter | Qt::AlignTop, the text will be positioned such + that the top of the text rect will be horizontally centered on \a position. + \li If \a alignment is Qt::AlignLeft | Qt::AlignBottom, \a position will indicate the + bottom left corner of the text rect. + If you want to control the alignment of (multi-lined) text within the text rect, use \ref + setTextAlignment. +*/ +void QCPItemText::setPositionAlignment(Qt::Alignment alignment) +{ + mPositionAlignment = alignment; +} + +/*! + Controls how (multi-lined) text is aligned inside the text rect (typically Qt::AlignLeft, Qt::AlignCenter or Qt::AlignRight). */ +void QCPItemText::setTextAlignment(Qt::Alignment alignment) +{ + mTextAlignment = alignment; +} -/* end of documentation of inline functions */ +/*! + Sets the angle in degrees by which the text (and the text rectangle, if visible) will be rotated + around \a position. +*/ +void QCPItemText::setRotation(double degrees) +{ + mRotation = degrees; +} /*! - Constructs a new bars group for the specified QCustomPlot instance. + Sets the distance between the border of the text rectangle and the text. The appearance (and + visibility) of the text rectangle can be controlled with \ref setPen and \ref setBrush. */ -QCPBarsGroup::QCPBarsGroup(QCustomPlot *parentPlot) : - QObject(parentPlot), - mParentPlot(parentPlot), - mSpacingType(stAbsolute), - mSpacing(4) +void QCPItemText::setPadding(const QMargins &padding) { + mPadding = padding; } -QCPBarsGroup::~QCPBarsGroup() +/* inherits documentation from base class */ +double QCPItemText::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - clear(); + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + + // The rect may be rotated, so we transform the actual clicked pos to the rotated + // coordinate system, so we can use the normal rectDistance function for non-rotated rects: + QPointF positionPixels(position->pixelPosition()); + QTransform inputTransform; + inputTransform.translate(positionPixels.x(), positionPixels.y()); + inputTransform.rotate(-mRotation); + inputTransform.translate(-positionPixels.x(), -positionPixels.y()); + QPointF rotatedPos = inputTransform.map(pos); + QFontMetrics fontMetrics(mFont); + QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText); + QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom()); + QPointF textPos = getTextDrawPoint(positionPixels, textBoxRect, mPositionAlignment); + textBoxRect.moveTopLeft(textPos.toPoint()); + + return rectDistance(textBoxRect, rotatedPos, true); } -/*! - Sets how the spacing between adjacent bars is interpreted. See \ref SpacingType. +/* inherits documentation from base class */ +void QCPItemText::draw(QCPPainter *painter) +{ + QPointF pos(position->pixelPosition()); + QTransform transform = painter->transform(); + transform.translate(pos.x(), pos.y()); + if (!qFuzzyIsNull(mRotation)) + transform.rotate(mRotation); + painter->setFont(mainFont()); + QRect textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText); + QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom()); + QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation + textRect.moveTopLeft(textPos.toPoint()+QPoint(mPadding.left(), mPadding.top())); + textBoxRect.moveTopLeft(textPos.toPoint()); + int clipPad = qCeil(mainPen().widthF()); + QRect boundingRect = textBoxRect.adjusted(-clipPad, -clipPad, clipPad, clipPad); + if (transform.mapRect(boundingRect).intersects(painter->transform().mapRect(clipRect()))) + { + painter->setTransform(transform); + if ((mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) || + (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)) + { + painter->setPen(mainPen()); + painter->setBrush(mainBrush()); + painter->drawRect(textBoxRect); + } + painter->setBrush(Qt::NoBrush); + painter->setPen(QPen(mainColor())); + painter->drawText(textRect, Qt::TextDontClip|mTextAlignment, mText); + } +} + +/* inherits documentation from base class */ +QPointF QCPItemText::anchorPixelPosition(int anchorId) const +{ + // get actual rect points (pretty much copied from draw function): + QPointF pos(position->pixelPosition()); + QTransform transform; + transform.translate(pos.x(), pos.y()); + if (!qFuzzyIsNull(mRotation)) + transform.rotate(mRotation); + QFontMetrics fontMetrics(mainFont()); + QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText); + QRectF textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom()); + QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation + textBoxRect.moveTopLeft(textPos.toPoint()); + QPolygonF rectPoly = transform.map(QPolygonF(textBoxRect)); - The actual spacing can then be specified with \ref setSpacing. + switch (anchorId) + { + case aiTopLeft: return rectPoly.at(0); + case aiTop: return (rectPoly.at(0)+rectPoly.at(1))*0.5; + case aiTopRight: return rectPoly.at(1); + case aiRight: return (rectPoly.at(1)+rectPoly.at(2))*0.5; + case aiBottomRight: return rectPoly.at(2); + case aiBottom: return (rectPoly.at(2)+rectPoly.at(3))*0.5; + case aiBottomLeft: return rectPoly.at(3); + case aiLeft: return (rectPoly.at(3)+rectPoly.at(0))*0.5; + } + + qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; + return {}; +} - \see setSpacing +/*! \internal + + Returns the point that must be given to the QPainter::drawText function (which expects the top + left point of the text rect), according to the position \a pos, the text bounding box \a rect and + the requested \a positionAlignment. + + For example, if \a positionAlignment is Qt::AlignLeft | Qt::AlignBottom the returned point + will be shifted upward by the height of \a rect, starting from \a pos. So if the text is finally + drawn at that point, the lower left corner of the resulting text rect is at \a pos. */ -void QCPBarsGroup::setSpacingType(SpacingType spacingType) +QPointF QCPItemText::getTextDrawPoint(const QPointF &pos, const QRectF &rect, Qt::Alignment positionAlignment) const { - mSpacingType = spacingType; + if (positionAlignment == 0 || positionAlignment == (Qt::AlignLeft|Qt::AlignTop)) + return pos; + + QPointF result = pos; // start at top left + if (positionAlignment.testFlag(Qt::AlignHCenter)) + result.rx() -= rect.width()/2.0; + else if (positionAlignment.testFlag(Qt::AlignRight)) + result.rx() -= rect.width(); + if (positionAlignment.testFlag(Qt::AlignVCenter)) + result.ry() -= rect.height()/2.0; + else if (positionAlignment.testFlag(Qt::AlignBottom)) + result.ry() -= rect.height(); + return result; } -/*! - Sets the spacing between adjacent bars. What the number passed as \a spacing actually means, is - defined by the current \ref SpacingType, which can be set with \ref setSpacingType. +/*! \internal - \see setSpacingType + Returns the font that should be used for drawing text. Returns mFont when the item is not selected + and mSelectedFont when it is. */ -void QCPBarsGroup::setSpacing(double spacing) +QFont QCPItemText::mainFont() const { - mSpacing = spacing; + return mSelected ? mSelectedFont : mFont; } -/*! - Returns the QCPBars instance with the specified \a index in this group. If no such QCPBars - exists, returns 0. +/*! \internal - \see bars(), size + Returns the color that should be used for drawing text. Returns mColor when the item is not + selected and mSelectedColor when it is. */ -QCPBars *QCPBarsGroup::bars(int index) const +QColor QCPItemText::mainColor() const { - if (index >= 0 && index < mBars.size()) - { - return mBars.at(index); - } else - { - qDebug() << Q_FUNC_INFO << "index out of bounds:" << index; - return 0; - } + return mSelected ? mSelectedColor : mColor; } -/*! - Removes all QCPBars plottables from this group. +/*! \internal - \see isEmpty + Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected + and mSelectedPen when it is. */ -void QCPBarsGroup::clear() +QPen QCPItemText::mainPen() const { - foreach (QCPBars *bars, mBars) // since foreach takes a copy, removing bars in the loop is okay - bars->setBarsGroup(0); // removes itself via removeBars + return mSelected ? mSelectedPen : mPen; } -/*! - Adds the specified \a bars plottable to this group. Alternatively, you can also use \ref - QCPBars::setBarsGroup on the \a bars instance. +/*! \internal - \see insert, remove + Returns the brush that should be used for drawing fills of the item. Returns mBrush when the item + is not selected and mSelectedBrush when it is. */ -void QCPBarsGroup::append(QCPBars *bars) +QBrush QCPItemText::mainBrush() const { - if (!bars) - { - qDebug() << Q_FUNC_INFO << "bars is 0"; - return; - } - - if (!mBars.contains(bars)) - bars->setBarsGroup(this); - else - qDebug() << Q_FUNC_INFO << "bars plottable is already in this bars group:" << reinterpret_cast(bars); + return mSelected ? mSelectedBrush : mBrush; } +/* end of 'src/items/item-text.cpp' */ + + +/* including file 'src/items/item-ellipse.cpp' */ +/* modified 2022-11-06T12:45:56, size 7881 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPItemEllipse +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPItemEllipse + \brief An ellipse + + \image html QCPItemEllipse.png "Ellipse example. Blue dotted circles are anchors, solid blue discs are positions." + + It has two positions, \a topLeft and \a bottomRight, which define the rect the ellipse will be drawn in. +*/ /*! - Inserts the specified \a bars plottable into this group at the specified index position \a i. - This gives you full control over the ordering of the bars. + Creates an ellipse item and sets default values. - \a bars may already be part of this group. In that case, \a bars is just moved to the new index - position. - - \see append, remove + The created item is automatically registered with \a parentPlot. This QCustomPlot instance takes + ownership of the item, so do not delete it manually but use QCustomPlot::removeItem() instead. */ -void QCPBarsGroup::insert(int i, QCPBars *bars) +QCPItemEllipse::QCPItemEllipse(QCustomPlot *parentPlot) : + QCPAbstractItem(parentPlot), + topLeft(createPosition(QLatin1String("topLeft"))), + bottomRight(createPosition(QLatin1String("bottomRight"))), + topLeftRim(createAnchor(QLatin1String("topLeftRim"), aiTopLeftRim)), + top(createAnchor(QLatin1String("top"), aiTop)), + topRightRim(createAnchor(QLatin1String("topRightRim"), aiTopRightRim)), + right(createAnchor(QLatin1String("right"), aiRight)), + bottomRightRim(createAnchor(QLatin1String("bottomRightRim"), aiBottomRightRim)), + bottom(createAnchor(QLatin1String("bottom"), aiBottom)), + bottomLeftRim(createAnchor(QLatin1String("bottomLeftRim"), aiBottomLeftRim)), + left(createAnchor(QLatin1String("left"), aiLeft)), + center(createAnchor(QLatin1String("center"), aiCenter)) { - if (!bars) - { - qDebug() << Q_FUNC_INFO << "bars is 0"; - return; - } + topLeft->setCoords(0, 1); + bottomRight->setCoords(1, 0); - // first append to bars list normally: - if (!mBars.contains(bars)) - bars->setBarsGroup(this); - // then move to according position: - mBars.move(mBars.indexOf(bars), qBound(0, i, mBars.size()-1)); + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue, 2)); + setBrush(Qt::NoBrush); + setSelectedBrush(Qt::NoBrush); +} + +QCPItemEllipse::~QCPItemEllipse() +{ } /*! - Removes the specified \a bars plottable from this group. + Sets the pen that will be used to draw the line of the ellipse - \see contains, clear + \see setSelectedPen, setBrush */ -void QCPBarsGroup::remove(QCPBars *bars) -{ - if (!bars) - { - qDebug() << Q_FUNC_INFO << "bars is 0"; - return; - } - - if (mBars.contains(bars)) - bars->setBarsGroup(0); - else - qDebug() << Q_FUNC_INFO << "bars plottable is not in this bars group:" << reinterpret_cast(bars); +void QCPItemEllipse::setPen(const QPen &pen) +{ + mPen = pen; } -/*! \internal - - Adds the specified \a bars to the internal mBars list of bars. This method does not change the - barsGroup property on \a bars. +/*! + Sets the pen that will be used to draw the line of the ellipse when selected - \see unregisterBars + \see setPen, setSelected */ -void QCPBarsGroup::registerBars(QCPBars *bars) +void QCPItemEllipse::setSelectedPen(const QPen &pen) { - if (!mBars.contains(bars)) - mBars.append(bars); + mSelectedPen = pen; } -/*! \internal - - Removes the specified \a bars from the internal mBars list of bars. This method does not change - the barsGroup property on \a bars. +/*! + Sets the brush that will be used to fill the ellipse. To disable filling, set \a brush to + Qt::NoBrush. - \see registerBars + \see setSelectedBrush, setPen */ -void QCPBarsGroup::unregisterBars(QCPBars *bars) +void QCPItemEllipse::setBrush(const QBrush &brush) { - mBars.removeOne(bars); + mBrush = brush; } -/*! \internal +/*! + Sets the brush that will be used to fill the ellipse when selected. To disable filling, set \a + brush to Qt::NoBrush. - Returns the pixel offset in the key dimension the specified \a bars plottable should have at the - given key coordinate \a keyCoord. The offset is relative to the pixel position of the key - coordinate \a keyCoord. + \see setBrush */ -double QCPBarsGroup::keyPixelOffset(const QCPBars *bars, double keyCoord) +void QCPItemEllipse::setSelectedBrush(const QBrush &brush) { - // find list of all base bars in case some mBars are stacked: - QList baseBars; - foreach (const QCPBars *b, mBars) - { - while (b->barBelow()) - b = b->barBelow(); - if (!baseBars.contains(b)) - baseBars.append(b); - } - // find base bar this "bars" is stacked on: - const QCPBars *thisBase = bars; - while (thisBase->barBelow()) - thisBase = thisBase->barBelow(); + mSelectedBrush = brush; +} + +/* inherits documentation from base class */ +double QCPItemEllipse::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +{ + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; - // determine key pixel offset of this base bars considering all other base bars in this barsgroup: - double result = 0; - int index = baseBars.indexOf(thisBase); - if (index >= 0) + QPointF p1 = topLeft->pixelPosition(); + QPointF p2 = bottomRight->pixelPosition(); + QPointF center((p1+p2)/2.0); + double a = qAbs(p1.x()-p2.x())/2.0; + double b = qAbs(p1.y()-p2.y())/2.0; + double x = pos.x()-center.x(); + double y = pos.y()-center.y(); + + // distance to border: + double c = 1.0/qSqrt(x*x/(a*a)+y*y/(b*b)); + double result = qAbs(c-1)*qSqrt(x*x+y*y); + // filled ellipse, allow click inside to count as hit: + if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0) { - int startIndex; - double lowerPixelWidth, upperPixelWidth; - if (baseBars.size() % 2 == 1 && index == (baseBars.size()-1)/2) // is center bar (int division on purpose) - { - return result; - } else if (index < (baseBars.size()-1)/2.0) // bar is to the left of center - { - if (baseBars.size() % 2 == 0) // even number of bars - { - startIndex = baseBars.size()/2-1; - result -= getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing - } else // uneven number of bars - { - startIndex = (baseBars.size()-1)/2-1; - baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); - result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar - result -= getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing - } - for (int i=startIndex; i>index; --i) // add widths and spacings of bars in between center and our bars - { - baseBars.at(i)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); - result -= qAbs(upperPixelWidth-lowerPixelWidth); - result -= getPixelSpacing(baseBars.at(i), keyCoord); - } - // finally half of our bars width: - baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); - result -= qAbs(upperPixelWidth-lowerPixelWidth)*0.5; - } else // bar is to the right of center - { - if (baseBars.size() % 2 == 0) // even number of bars - { - startIndex = baseBars.size()/2; - result += getPixelSpacing(baseBars.at(startIndex), keyCoord)*0.5; // half of middle spacing - } else // uneven number of bars - { - startIndex = (baseBars.size()-1)/2+1; - baseBars.at((baseBars.size()-1)/2)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); - result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5; // half of center bar - result += getPixelSpacing(baseBars.at((baseBars.size()-1)/2), keyCoord); // center bar spacing - } - for (int i=startIndex; igetPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); - result += qAbs(upperPixelWidth-lowerPixelWidth); - result += getPixelSpacing(baseBars.at(i), keyCoord); - } - // finally half of our bars width: - baseBars.at(index)->getPixelWidth(keyCoord, lowerPixelWidth, upperPixelWidth); - result += qAbs(upperPixelWidth-lowerPixelWidth)*0.5; - } + if (x*x/(a*a) + y*y/(b*b) <= 1) + result = mParentPlot->selectionTolerance()*0.99; } return result; } -/*! \internal - - Returns the spacing in pixels which is between this \a bars and the following one, both at the - key coordinate \a keyCoord. - - \note Typically the returned value doesn't depend on \a bars or \a keyCoord. \a bars is only - needed to get acces to the key axis transformation and axis rect for the modes \ref - stAxisRectRatio and \ref stPlotCoords. The \a keyCoord is only relevant for spacings given in - \ref stPlotCoords on a logarithmic axis. -*/ -double QCPBarsGroup::getPixelSpacing(const QCPBars *bars, double keyCoord) +/* inherits documentation from base class */ +void QCPItemEllipse::draw(QCPPainter *painter) { - switch (mSpacingType) + QPointF p1 = topLeft->pixelPosition(); + QPointF p2 = bottomRight->pixelPosition(); + if (p1.toPoint() == p2.toPoint()) + return; + QRectF ellipseRect = QRectF(p1, p2).normalized(); + const int clipEnlarge = qCeil(mainPen().widthF()); + QRect clip = clipRect().adjusted(-clipEnlarge, -clipEnlarge, clipEnlarge, clipEnlarge); + if (ellipseRect.intersects(clip)) // only draw if bounding rect of ellipse is visible in cliprect { - case stAbsolute: - { - return mSpacing; - } - case stAxisRectRatio: + painter->setPen(mainPen()); + painter->setBrush(mainBrush()); +#ifdef __EXCEPTIONS + try // drawEllipse sometimes throws exceptions if ellipse is too big { - if (bars->keyAxis()->orientation() == Qt::Horizontal) - return bars->keyAxis()->axisRect()->width()*mSpacing; - else - return bars->keyAxis()->axisRect()->height()*mSpacing; - } - case stPlotCoords: +#endif + painter->drawEllipse(ellipseRect); +#ifdef __EXCEPTIONS + } catch (...) { - double keyPixel = bars->keyAxis()->coordToPixel(keyCoord); - return bars->keyAxis()->coordToPixel(keyCoord+mSpacing)-keyPixel; + qDebug() << Q_FUNC_INFO << "Item too large for memory, setting invisible"; + setVisible(false); } +#endif } - return 0; } - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPBarData -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPBarData - \brief Holds the data of one single data point (one bar) for QCPBars. - - The container for storing multiple data points is \ref QCPBarDataMap. - - The stored data is: - \li \a key: coordinate on the key axis of this bar - \li \a value: height coordinate on the value axis of this bar +/* inherits documentation from base class */ +QPointF QCPItemEllipse::anchorPixelPosition(int anchorId) const +{ + QRectF rect = QRectF(topLeft->pixelPosition(), bottomRight->pixelPosition()); + switch (anchorId) + { + case aiTopLeftRim: return rect.center()+(rect.topLeft()-rect.center())*1/qSqrt(2); + case aiTop: return (rect.topLeft()+rect.topRight())*0.5; + case aiTopRightRim: return rect.center()+(rect.topRight()-rect.center())*1/qSqrt(2); + case aiRight: return (rect.topRight()+rect.bottomRight())*0.5; + case aiBottomRightRim: return rect.center()+(rect.bottomRight()-rect.center())*1/qSqrt(2); + case aiBottom: return (rect.bottomLeft()+rect.bottomRight())*0.5; + case aiBottomLeftRim: return rect.center()+(rect.bottomLeft()-rect.center())*1/qSqrt(2); + case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5; + case aiCenter: return (rect.topLeft()+rect.bottomRight())*0.5; + } - \see QCPBarDataaMap -*/ + qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; + return {}; +} -/*! - Constructs a bar data point with key and value set to zero. +/*! \internal + + Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected + and mSelectedPen when it is. */ -QCPBarData::QCPBarData() : - key(0), - value(0) +QPen QCPItemEllipse::mainPen() const { + return mSelected ? mSelectedPen : mPen; } -/*! - Constructs a bar data point with the specified \a key and \a value. +/*! \internal + + Returns the brush that should be used for drawing fills of the item. Returns mBrush when the item + is not selected and mSelectedBrush when it is. */ -QCPBarData::QCPBarData(double key, double value) : - key(key), - value(value) +QBrush QCPItemEllipse::mainBrush() const { + return mSelected ? mSelectedBrush : mBrush; } +/* end of 'src/items/item-ellipse.cpp' */ + +/* including file 'src/items/item-pixmap.cpp' */ +/* modified 2022-11-06T12:45:56, size 10622 */ //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPBars +//////////////////// QCPItemPixmap //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPBars - \brief A plottable representing a bar chart in a plot. - - \image html QCPBars.png - - To plot data, assign it with the \ref setData or \ref addData functions. - - \section appearance Changing the appearance - - The appearance of the bars is determined by the pen and the brush (\ref setPen, \ref setBrush). - The width of the individual bars can be controlled with \ref setWidthType and \ref setWidth. - - Bar charts are stackable. This means, two QCPBars plottables can be placed on top of each other - (see \ref QCPBars::moveAbove). So when two bars are at the same key position, they will appear - stacked. - - If you would like to group multiple QCPBars plottables together so they appear side by side as - shown below, use QCPBarsGroup. - - \image html QCPBarsGroup.png - - \section usage Usage - - Like all data representing objects in QCustomPlot, the QCPBars is a plottable - (QCPAbstractPlottable). So the plottable-interface of QCustomPlot applies - (QCustomPlot::plottable, QCustomPlot::addPlottable, QCustomPlot::removePlottable, etc.) - - Usually, you first create an instance: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpbars-creation-1 - add it to the customPlot with QCustomPlot::addPlottable: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpbars-creation-2 - and then modify the properties of the newly created plottable, e.g.: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpbars-creation-3 -*/ - -/* start of documentation of inline functions */ +/*! \class QCPItemPixmap + \brief An arbitrary pixmap -/*! \fn QCPBars *QCPBars::barBelow() const - Returns the bars plottable that is directly below this bars plottable. - If there is no such plottable, returns 0. - - \see barAbove, moveBelow, moveAbove -*/ + \image html QCPItemPixmap.png "Pixmap example. Blue dotted circles are anchors, solid blue discs are positions." -/*! \fn QCPBars *QCPBars::barAbove() const - Returns the bars plottable that is directly above this bars plottable. - If there is no such plottable, returns 0. + It has two positions, \a topLeft and \a bottomRight, which define the rectangle the pixmap will + be drawn in. Depending on the scale setting (\ref setScaled), the pixmap will be either scaled to + fit the rectangle or be drawn aligned to the topLeft position. - \see barBelow, moveBelow, moveAbove -*/ - -/* end of documentation of inline functions */ - -/*! - Constructs a bar chart which uses \a keyAxis as its key axis ("x") and \a valueAxis as its value - axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and not have - the same orientation. If either of these restrictions is violated, a corresponding message is - printed to the debug output (qDebug), the construction is not aborted, though. + If scaling is enabled and \a topLeft is further to the bottom/right than \a bottomRight (as shown + on the right side of the example image), the pixmap will be flipped in the respective + orientations. +*/ + +/*! + Creates a rectangle item and sets default values. - The constructed QCPBars can be added to the plot with QCustomPlot::addPlottable, QCustomPlot - then takes ownership of the bar chart. + The created item is automatically registered with \a parentPlot. This QCustomPlot instance takes + ownership of the item, so do not delete it manually but use QCustomPlot::removeItem() instead. */ -QCPBars::QCPBars(QCPAxis *keyAxis, QCPAxis *valueAxis) : - QCPAbstractPlottable(keyAxis, valueAxis), - mData(new QCPBarDataMap), - mWidth(0.75), - mWidthType(wtPlotCoords), - mBarsGroup(0), - mBaseValue(0) +QCPItemPixmap::QCPItemPixmap(QCustomPlot *parentPlot) : + QCPAbstractItem(parentPlot), + topLeft(createPosition(QLatin1String("topLeft"))), + bottomRight(createPosition(QLatin1String("bottomRight"))), + top(createAnchor(QLatin1String("top"), aiTop)), + topRight(createAnchor(QLatin1String("topRight"), aiTopRight)), + right(createAnchor(QLatin1String("right"), aiRight)), + bottom(createAnchor(QLatin1String("bottom"), aiBottom)), + bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)), + left(createAnchor(QLatin1String("left"), aiLeft)), + mScaled(false), + mScaledPixmapInvalidated(true), + mAspectRatioMode(Qt::KeepAspectRatio), + mTransformationMode(Qt::SmoothTransformation) { - // modify inherited properties from abstract plottable: - mPen.setColor(Qt::blue); - mPen.setStyle(Qt::SolidLine); - mBrush.setColor(QColor(40, 50, 255, 30)); - mBrush.setStyle(Qt::SolidPattern); - mSelectedPen = mPen; - mSelectedPen.setWidthF(2.5); - mSelectedPen.setColor(QColor(80, 80, 255)); // lighter than Qt::blue of mPen - mSelectedBrush = mBrush; + topLeft->setCoords(0, 1); + bottomRight->setCoords(1, 0); + + setPen(Qt::NoPen); + setSelectedPen(QPen(Qt::blue)); } -QCPBars::~QCPBars() +QCPItemPixmap::~QCPItemPixmap() { - setBarsGroup(0); - if (mBarBelow || mBarAbove) - connectBars(mBarBelow.data(), mBarAbove.data()); // take this bar out of any stacking - delete mData; } /*! - Sets the width of the bars. + Sets the pixmap that will be displayed. +*/ +void QCPItemPixmap::setPixmap(const QPixmap &pixmap) +{ + mPixmap = pixmap; + mScaledPixmapInvalidated = true; + if (mPixmap.isNull()) + qDebug() << Q_FUNC_INFO << "pixmap is null"; +} - How the number passed as \a width is interpreted (e.g. screen pixels, plot coordinates,...), - depends on the currently set width type, see \ref setWidthType and \ref WidthType. +/*! + Sets whether the pixmap will be scaled to fit the rectangle defined by the \a topLeft and \a + bottomRight positions. */ -void QCPBars::setWidth(double width) +void QCPItemPixmap::setScaled(bool scaled, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode) { - mWidth = width; + mScaled = scaled; + mAspectRatioMode = aspectRatioMode; + mTransformationMode = transformationMode; + mScaledPixmapInvalidated = true; } /*! - Sets how the width of the bars is defined. See the documentation of \ref WidthType for an - explanation of the possible values for \a widthType. - - The default value is \ref wtPlotCoords. + Sets the pen that will be used to draw a border around the pixmap. - \see setWidth + \see setSelectedPen, setBrush */ -void QCPBars::setWidthType(QCPBars::WidthType widthType) +void QCPItemPixmap::setPen(const QPen &pen) { - mWidthType = widthType; + mPen = pen; } /*! - Sets to which QCPBarsGroup this QCPBars instance belongs to. Alternatively, you can also use \ref - QCPBarsGroup::append. + Sets the pen that will be used to draw a border around the pixmap when selected - To remove this QCPBars from any group, set \a barsGroup to 0. + \see setPen, setSelected */ -void QCPBars::setBarsGroup(QCPBarsGroup *barsGroup) +void QCPItemPixmap::setSelectedPen(const QPen &pen) { - // deregister at old group: - if (mBarsGroup) - mBarsGroup->unregisterBars(this); - mBarsGroup = barsGroup; - // register at new group: - if (mBarsGroup) - mBarsGroup->registerBars(this); + mSelectedPen = pen; } -/*! - Sets the base value of this bars plottable. +/* inherits documentation from base class */ +double QCPItemPixmap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +{ + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; + + return rectDistance(getFinalRect(), pos, true); +} - The base value defines where on the value coordinate the bars start. How far the bars extend from - the base value is given by their individual value data. For example, if the base value is set to - 1, a bar with data value 2 will have its lowest point at value coordinate 1 and highest point at - 3. +/* inherits documentation from base class */ +void QCPItemPixmap::draw(QCPPainter *painter) +{ + bool flipHorz = false; + bool flipVert = false; + QRect rect = getFinalRect(&flipHorz, &flipVert); + int clipPad = mainPen().style() == Qt::NoPen ? 0 : qCeil(mainPen().widthF()); + QRect boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad); + if (boundingRect.intersects(clipRect())) + { + updateScaledPixmap(rect, flipHorz, flipVert); + painter->drawPixmap(rect.topLeft(), mScaled ? mScaledPixmap : mPixmap); + QPen pen = mainPen(); + if (pen.style() != Qt::NoPen) + { + painter->setPen(pen); + painter->setBrush(Qt::NoBrush); + painter->drawRect(rect); + } + } +} + +/* inherits documentation from base class */ +QPointF QCPItemPixmap::anchorPixelPosition(int anchorId) const +{ + bool flipHorz = false; + bool flipVert = false; + QRect rect = getFinalRect(&flipHorz, &flipVert); + // we actually want denormal rects (negative width/height) here, so restore + // the flipped state: + if (flipHorz) + rect.adjust(rect.width(), 0, -rect.width(), 0); + if (flipVert) + rect.adjust(0, rect.height(), 0, -rect.height()); - For stacked bars, only the base value of the bottom-most QCPBars has meaning. + switch (anchorId) + { + case aiTop: return (rect.topLeft()+rect.topRight())*0.5; + case aiTopRight: return rect.topRight(); + case aiRight: return (rect.topRight()+rect.bottomRight())*0.5; + case aiBottom: return (rect.bottomLeft()+rect.bottomRight())*0.5; + case aiBottomLeft: return rect.bottomLeft(); + case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5; + } - The default base value is 0. + qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; + return {}; +} + +/*! \internal + + Creates the buffered scaled image (\a mScaledPixmap) to fit the specified \a finalRect. The + parameters \a flipHorz and \a flipVert control whether the resulting image shall be flipped + horizontally or vertically. (This is used when \a topLeft is further to the bottom/right than \a + bottomRight.) + + This function only creates the scaled pixmap when the buffered pixmap has a different size than + the expected result, so calling this function repeatedly, e.g. in the \ref draw function, does + not cause expensive rescaling every time. + + If scaling is disabled, sets mScaledPixmap to a null QPixmap. */ -void QCPBars::setBaseValue(double baseValue) +void QCPItemPixmap::updateScaledPixmap(QRect finalRect, bool flipHorz, bool flipVert) { - mBaseValue = baseValue; + if (mPixmap.isNull()) + return; + + if (mScaled) + { +#ifdef QCP_DEVICEPIXELRATIO_SUPPORTED + double devicePixelRatio = mPixmap.devicePixelRatio(); +#else + double devicePixelRatio = 1.0; +#endif + if (finalRect.isNull()) + finalRect = getFinalRect(&flipHorz, &flipVert); + if (mScaledPixmapInvalidated || finalRect.size() != mScaledPixmap.size()/devicePixelRatio) + { + mScaledPixmap = mPixmap.scaled(finalRect.size()*devicePixelRatio, mAspectRatioMode, mTransformationMode); + if (flipHorz || flipVert) + mScaledPixmap = QPixmap::fromImage(mScaledPixmap.toImage().mirrored(flipHorz, flipVert)); +#ifdef QCP_DEVICEPIXELRATIO_SUPPORTED + mScaledPixmap.setDevicePixelRatio(devicePixelRatio); +#endif + } + } else if (!mScaledPixmap.isNull()) + mScaledPixmap = QPixmap(); + mScaledPixmapInvalidated = false; } -/*! - Replaces the current data with the provided \a data. +/*! \internal - If \a copy is set to true, data points in \a data will only be copied. if false, the plottable - takes ownership of the passed data and replaces the internal data pointer with it. This is - significantly faster than copying for large datasets. + Returns the final (tight) rect the pixmap is drawn in, depending on the current item positions + and scaling settings. + + The output parameters \a flippedHorz and \a flippedVert return whether the pixmap should be drawn + flipped horizontally or vertically in the returned rect. (The returned rect itself is always + normalized, i.e. the top left corner of the rect is actually further to the top/left than the + bottom right corner). This is the case when the item position \a topLeft is further to the + bottom/right than \a bottomRight. + + If scaling is disabled, returns a rect with size of the original pixmap and the top left corner + aligned with the item position \a topLeft. The position \a bottomRight is ignored. */ -void QCPBars::setData(QCPBarDataMap *data, bool copy) +QRect QCPItemPixmap::getFinalRect(bool *flippedHorz, bool *flippedVert) const { - if (mData == data) - { - qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); - return; - } - if (copy) + QRect result; + bool flipHorz = false; + bool flipVert = false; + QPoint p1 = topLeft->pixelPosition().toPoint(); + QPoint p2 = bottomRight->pixelPosition().toPoint(); + if (p1 == p2) + return {p1, QSize(0, 0)}; + if (mScaled) { - *mData = *data; + QSize newSize = QSize(p2.x()-p1.x(), p2.y()-p1.y()); + QPoint topLeft = p1; + if (newSize.width() < 0) + { + flipHorz = true; + newSize.rwidth() *= -1; + topLeft.setX(p2.x()); + } + if (newSize.height() < 0) + { + flipVert = true; + newSize.rheight() *= -1; + topLeft.setY(p2.y()); + } + QSize scaledSize = mPixmap.size(); +#ifdef QCP_DEVICEPIXELRATIO_SUPPORTED + scaledSize /= mPixmap.devicePixelRatio(); + scaledSize.scale(newSize*mPixmap.devicePixelRatio(), mAspectRatioMode); +#else + scaledSize.scale(newSize, mAspectRatioMode); +#endif + result = QRect(topLeft, scaledSize); } else { - delete mData; - mData = data; +#ifdef QCP_DEVICEPIXELRATIO_SUPPORTED + result = QRect(p1, mPixmap.size()/mPixmap.devicePixelRatio()); +#else + result = QRect(p1, mPixmap.size()); +#endif } + if (flippedHorz) + *flippedHorz = flipHorz; + if (flippedVert) + *flippedVert = flipVert; + return result; } -/*! \overload +/*! \internal + + Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected + and mSelectedPen when it is. +*/ +QPen QCPItemPixmap::mainPen() const +{ + return mSelected ? mSelectedPen : mPen; +} +/* end of 'src/items/item-pixmap.cpp' */ + + +/* including file 'src/items/item-tracer.cpp' */ +/* modified 2022-11-06T12:45:56, size 14645 */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPItemTracer +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPItemTracer + \brief Item that sticks to QCPGraph data points + + \image html QCPItemTracer.png "Tracer example. Blue dotted circles are anchors, solid blue discs are positions." + + The tracer can be connected with a QCPGraph via \ref setGraph. Then it will automatically adopt + the coordinate axes of the graph and update its \a position to be on the graph's data. This means + the key stays controllable via \ref setGraphKey, but the value will follow the graph data. If a + QCPGraph is connected, note that setting the coordinates of the tracer item directly via \a + position will have no effect because they will be overriden in the next redraw (this is when the + coordinate update happens). + + If the specified key in \ref setGraphKey is outside the key bounds of the graph, the tracer will + stay at the corresponding end of the graph. + + With \ref setInterpolating you may specify whether the tracer may only stay exactly on data + points or whether it interpolates data points linearly, if given a key that lies between two data + points of the graph. - Replaces the current data with the provided points in \a key and \a value tuples. The - provided vectors should have equal length. Else, the number of added points will be the size of - the smallest vector. + The tracer has different visual styles, see \ref setStyle. It is also possible to make the tracer + have no own visual appearance (set the style to \ref tsNone), and just connect other item + positions to the tracer \a position (used as an anchor) via \ref + QCPItemPosition::setParentAnchor. + + \note The tracer position is only automatically updated upon redraws. So when the data of the + graph changes and immediately afterwards (without a redraw) the position coordinates of the + tracer are retrieved, they will not reflect the updated data of the graph. In this case \ref + updatePosition must be called manually, prior to reading the tracer coordinates. */ -void QCPBars::setData(const QVector &key, const QVector &value) -{ - mData->clear(); - int n = key.size(); - n = qMin(n, value.size()); - QCPBarData newData; - for (int i=0; iinsertMulti(newData.key, newData); - } -} /*! - Moves this bars plottable below \a bars. In other words, the bars of this plottable will appear - below the bars of \a bars. The move target \a bars must use the same key and value axis as this - plottable. - - Inserting into and removing from existing bar stacking is handled gracefully. If \a bars already - has a bars object below itself, this bars object is inserted between the two. If this bars object - is already between two other bars, the two other bars will be stacked on top of each other after - the operation. - - To remove this bars plottable from any stacking, set \a bars to 0. + Creates a tracer item and sets default values. - \see moveBelow, barAbove, barBelow + The created item is automatically registered with \a parentPlot. This QCustomPlot instance takes + ownership of the item, so do not delete it manually but use QCustomPlot::removeItem() instead. */ -void QCPBars::moveBelow(QCPBars *bars) +QCPItemTracer::QCPItemTracer(QCustomPlot *parentPlot) : + QCPAbstractItem(parentPlot), + position(createPosition(QLatin1String("position"))), + mSize(6), + mStyle(tsCrosshair), + mGraph(nullptr), + mGraphKey(0), + mInterpolating(false) { - if (bars == this) return; - if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data())) - { - qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars"; - return; - } - // remove from stacking: - connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0 - // if new bar given, insert this bar below it: - if (bars) - { - if (bars->mBarBelow) - connectBars(bars->mBarBelow.data(), this); - connectBars(this, bars); - } + position->setCoords(0, 0); + + setBrush(Qt::NoBrush); + setSelectedBrush(Qt::NoBrush); + setPen(QPen(Qt::black)); + setSelectedPen(QPen(Qt::blue, 2)); } -/*! - Moves this bars plottable above \a bars. In other words, the bars of this plottable will appear - above the bars of \a bars. The move target \a bars must use the same key and value axis as this - plottable. - - Inserting into and removing from existing bar stacking is handled gracefully. If \a bars already - has a bars object below itself, this bars object is inserted between the two. If this bars object - is already between two other bars, the two other bars will be stacked on top of each other after - the operation. - - To remove this bars plottable from any stacking, set \a bars to 0. - - \see moveBelow, barBelow, barAbove -*/ -void QCPBars::moveAbove(QCPBars *bars) +QCPItemTracer::~QCPItemTracer() { - if (bars == this) return; - if (bars && (bars->keyAxis() != mKeyAxis.data() || bars->valueAxis() != mValueAxis.data())) - { - qDebug() << Q_FUNC_INFO << "passed QCPBars* doesn't have same key and value axis as this QCPBars"; - return; - } - // remove from stacking: - connectBars(mBarBelow.data(), mBarAbove.data()); // Note: also works if one (or both) of them is 0 - // if new bar given, insert this bar above it: - if (bars) - { - if (bars->mBarAbove) - connectBars(this, bars->mBarAbove.data()); - connectBars(bars, this); - } } /*! - Adds the provided data points in \a dataMap to the current data. - \see removeData + Sets the pen that will be used to draw the line of the tracer + + \see setSelectedPen, setBrush */ -void QCPBars::addData(const QCPBarDataMap &dataMap) +void QCPItemTracer::setPen(const QPen &pen) { - mData->unite(dataMap); + mPen = pen; } -/*! \overload - Adds the provided single data point in \a data to the current data. - \see removeData +/*! + Sets the pen that will be used to draw the line of the tracer when selected + + \see setPen, setSelected */ -void QCPBars::addData(const QCPBarData &data) +void QCPItemTracer::setSelectedPen(const QPen &pen) { - mData->insertMulti(data.key, data); + mSelectedPen = pen; } -/*! \overload - Adds the provided single data point as \a key and \a value tuple to the current data - \see removeData +/*! + Sets the brush that will be used to draw any fills of the tracer + + \see setSelectedBrush, setPen */ -void QCPBars::addData(double key, double value) +void QCPItemTracer::setBrush(const QBrush &brush) { - QCPBarData newData; - newData.key = key; - newData.value = value; - mData->insertMulti(newData.key, newData); + mBrush = brush; } -/*! \overload - Adds the provided data points as \a key and \a value tuples to the current data. - \see removeData +/*! + Sets the brush that will be used to draw any fills of the tracer, when selected. + + \see setBrush, setSelected */ -void QCPBars::addData(const QVector &keys, const QVector &values) +void QCPItemTracer::setSelectedBrush(const QBrush &brush) { - int n = keys.size(); - n = qMin(n, values.size()); - QCPBarData newData; - for (int i=0; iinsertMulti(newData.key, newData); - } + mSelectedBrush = brush; } /*! - Removes all data points with key smaller than \a key. - \see addData, clearData + Sets the size of the tracer in pixels, if the style supports setting a size (e.g. \ref tsSquare + does, \ref tsCrosshair does not). */ -void QCPBars::removeDataBefore(double key) +void QCPItemTracer::setSize(double size) { - QCPBarDataMap::iterator it = mData->begin(); - while (it != mData->end() && it.key() < key) - it = mData->erase(it); + mSize = size; } /*! - Removes all data points with key greater than \a key. - \see addData, clearData + Sets the style/visual appearance of the tracer. + + If you only want to use the tracer \a position as an anchor for other items, set \a style to + \ref tsNone. */ -void QCPBars::removeDataAfter(double key) +void QCPItemTracer::setStyle(QCPItemTracer::TracerStyle style) { - if (mData->isEmpty()) return; - QCPBarDataMap::iterator it = mData->upperBound(key); - while (it != mData->end()) - it = mData->erase(it); + mStyle = style; } /*! - Removes all data points with key between \a fromKey and \a toKey. if \a fromKey is - greater or equal to \a toKey, the function does nothing. To remove a single data point with known - key, use \ref removeData(double key). + Sets the QCPGraph this tracer sticks to. The tracer \a position will be set to type + QCPItemPosition::ptPlotCoords and the axes will be set to the axes of \a graph. - \see addData, clearData + To free the tracer from any graph, set \a graph to \c nullptr. The tracer \a position can then be + placed freely like any other item position. This is the state the tracer will assume when its + graph gets deleted while still attached to it. + + \see setGraphKey */ -void QCPBars::removeData(double fromKey, double toKey) +void QCPItemTracer::setGraph(QCPGraph *graph) { - if (fromKey >= toKey || mData->isEmpty()) return; - QCPBarDataMap::iterator it = mData->upperBound(fromKey); - QCPBarDataMap::iterator itEnd = mData->upperBound(toKey); - while (it != itEnd) - it = mData->erase(it); + if (graph) + { + if (graph->parentPlot() == mParentPlot) + { + position->setType(QCPItemPosition::ptPlotCoords); + position->setAxes(graph->keyAxis(), graph->valueAxis()); + mGraph = graph; + updatePosition(); + } else + qDebug() << Q_FUNC_INFO << "graph isn't in same QCustomPlot instance as this item"; + } else + { + mGraph = nullptr; + } } -/*! \overload +/*! + Sets the key of the graph's data point the tracer will be positioned at. This is the only free + coordinate of a tracer when attached to a graph. - Removes a single data point at \a key. If the position is not known with absolute precision, - consider using \ref removeData(double fromKey, double toKey) with a small fuzziness interval - around the suspected position, depeding on the precision with which the key is known. + Depending on \ref setInterpolating, the tracer will be either positioned on the data point + closest to \a key, or will stay exactly at \a key and interpolate the value linearly. - \see addData, clearData + \see setGraph, setInterpolating */ -void QCPBars::removeData(double key) +void QCPItemTracer::setGraphKey(double key) { - mData->remove(key); + mGraphKey = key; } /*! - Removes all data points. - \see removeData, removeDataAfter, removeDataBefore + Sets whether the value of the graph's data points shall be interpolated, when positioning the + tracer. + + If \a enabled is set to false and a key is given with \ref setGraphKey, the tracer is placed on + the data point of the graph which is closest to the key, but which is not necessarily exactly + there. If \a enabled is true, the tracer will be positioned exactly at the specified key, and + the appropriate value will be interpolated from the graph's data points linearly. + + \see setGraph, setGraphKey */ -void QCPBars::clearData() +void QCPItemTracer::setInterpolating(bool enabled) { - mData->clear(); + mInterpolating = enabled; } /* inherits documentation from base class */ -double QCPBars::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +double QCPItemTracer::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { Q_UNUSED(details) if (onlySelectable && !mSelectable) return -1; - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } - - if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) - { - QCPBarDataMap::ConstIterator it; - for (it = mData->constBegin(); it != mData->constEnd(); ++it) - { - if (getBarPolygon(it.value().key, it.value().value).boundingRect().contains(pos)) - return mParentPlot->selectionTolerance()*0.99; - } - } - return -1; -} -/* inherits documentation from base class */ -void QCPBars::draw(QCPPainter *painter) -{ - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - if (mData->isEmpty()) return; - - QCPBarDataMap::const_iterator it, lower, upperEnd; - getVisibleDataBounds(lower, upperEnd); - for (it = lower; it != upperEnd; ++it) + QPointF center(position->pixelPosition()); + double w = mSize/2.0; + QRect clip = clipRect(); + switch (mStyle) { - // check data validity if flag set: -#ifdef QCUSTOMPLOT_CHECK_DATA - if (QCP::isInvalidData(it.value().key, it.value().value)) - qDebug() << Q_FUNC_INFO << "Data point at" << it.key() << "of drawn range invalid." << "Plottable name:" << name(); -#endif - QPolygonF barPolygon = getBarPolygon(it.key(), it.value().value); - // draw bar fill: - if (mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) + case tsNone: return -1; + case tsPlus: { - applyFillAntialiasingHint(painter); - painter->setPen(Qt::NoPen); - painter->setBrush(mainBrush()); - painter->drawPolygon(barPolygon); + if (clipRect().intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) + return qSqrt(qMin(QCPVector2D(pos).distanceSquaredToLine(center+QPointF(-w, 0), center+QPointF(w, 0)), + QCPVector2D(pos).distanceSquaredToLine(center+QPointF(0, -w), center+QPointF(0, w)))); + break; } - // draw bar line: - if (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0) + case tsCrosshair: { - applyDefaultAntialiasingHint(painter); - painter->setPen(mainPen()); - painter->setBrush(Qt::NoBrush); - painter->drawPolyline(barPolygon); + return qSqrt(qMin(QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(clip.left(), center.y()), QCPVector2D(clip.right(), center.y())), + QCPVector2D(pos).distanceSquaredToLine(QCPVector2D(center.x(), clip.top()), QCPVector2D(center.x(), clip.bottom())))); } - } -} - -/* inherits documentation from base class */ -void QCPBars::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const -{ - // draw filled rect: - applyDefaultAntialiasingHint(painter); - painter->setBrush(mBrush); - painter->setPen(mPen); - QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67); - r.moveCenter(rect.center()); - painter->drawRect(r); -} - -/*! \internal - - called by \ref draw to determine which data (key) range is visible at the current key axis range - setting, so only that needs to be processed. It also takes into account the bar width. - - \a lower returns an iterator to the lowest data point that needs to be taken into account when - plotting. Note that in order to get a clean plot all the way to the edge of the axis rect, \a - lower may still be just outside the visible range. - - \a upperEnd returns an iterator one higher than the highest visible data point. Same as before, \a - upperEnd may also lie just outside of the visible range. - - if the bars plottable contains no data, both \a lower and \a upperEnd point to constEnd. -*/ -void QCPBars::getVisibleDataBounds(QCPBarDataMap::const_iterator &lower, QCPBarDataMap::const_iterator &upperEnd) const -{ - if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } - if (mData->isEmpty()) - { - lower = mData->constEnd(); - upperEnd = mData->constEnd(); - return; - } - - // get visible data range as QMap iterators - lower = mData->lowerBound(mKeyAxis.data()->range().lower); - upperEnd = mData->upperBound(mKeyAxis.data()->range().upper); - double lowerPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().lower); - double upperPixelBound = mKeyAxis.data()->coordToPixel(mKeyAxis.data()->range().upper); - bool isVisible = false; - // walk left from lbound to find lower bar that actually is completely outside visible pixel range: - QCPBarDataMap::const_iterator it = lower; - while (it != mData->constBegin()) - { - --it; - QRectF barBounds = getBarPolygon(it.value().key, it.value().value).boundingRect(); - if (mKeyAxis.data()->orientation() == Qt::Horizontal) - isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.right() >= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.left() <= lowerPixelBound)); - else // keyaxis is vertical - isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.top() <= lowerPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= lowerPixelBound)); - if (isVisible) - lower = it; - else + case tsCircle: + { + if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) + { + // distance to border: + double centerDist = QCPVector2D(center-pos).length(); + double circleLine = w; + double result = qAbs(centerDist-circleLine); + // filled ellipse, allow click inside to count as hit: + if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0) + { + if (centerDist <= circleLine) + result = mParentPlot->selectionTolerance()*0.99; + } + return result; + } break; - } - // walk right from ubound to find upper bar that actually is completely outside visible pixel range: - it = upperEnd; - while (it != mData->constEnd()) - { - QRectF barBounds = getBarPolygon(upperEnd.value().key, upperEnd.value().value).boundingRect(); - if (mKeyAxis.data()->orientation() == Qt::Horizontal) - isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.left() <= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.right() >= upperPixelBound)); - else // keyaxis is vertical - isVisible = ((!mKeyAxis.data()->rangeReversed() && barBounds.bottom() >= upperPixelBound) || (mKeyAxis.data()->rangeReversed() && barBounds.top() <= upperPixelBound)); - if (isVisible) - upperEnd = it+1; - else + } + case tsSquare: + { + if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) + { + QRectF rect = QRectF(center-QPointF(w, w), center+QPointF(w, w)); + bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0; + return rectDistance(rect, pos, filledRect); + } break; - ++it; + } } + return -1; } -/*! \internal - - Returns the polygon of a single bar with \a key and \a value. The Polygon is open at the bottom - and shifted according to the bar stacking (see \ref moveAbove) and base value (see \ref - setBaseValue). -*/ -QPolygonF QCPBars::getBarPolygon(double key, double value) const +/* inherits documentation from base class */ +void QCPItemTracer::draw(QCPPainter *painter) { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return QPolygonF(); } - - QPolygonF result; - double lowerPixelWidth, upperPixelWidth; - getPixelWidth(key, lowerPixelWidth, upperPixelWidth); - double base = getStackedBaseValue(key, value >= 0); - double basePixel = valueAxis->coordToPixel(base); - double valuePixel = valueAxis->coordToPixel(base+value); - double keyPixel = keyAxis->coordToPixel(key); - if (mBarsGroup) - keyPixel += mBarsGroup->keyPixelOffset(this, key); - if (keyAxis->orientation() == Qt::Horizontal) - { - result << QPointF(keyPixel+lowerPixelWidth, basePixel); - result << QPointF(keyPixel+lowerPixelWidth, valuePixel); - result << QPointF(keyPixel+upperPixelWidth, valuePixel); - result << QPointF(keyPixel+upperPixelWidth, basePixel); - } else - { - result << QPointF(basePixel, keyPixel+lowerPixelWidth); - result << QPointF(valuePixel, keyPixel+lowerPixelWidth); - result << QPointF(valuePixel, keyPixel+upperPixelWidth); - result << QPointF(basePixel, keyPixel+upperPixelWidth); - } - return result; -} + updatePosition(); + if (mStyle == tsNone) + return; -/*! \internal - - This function is used to determine the width of the bar at coordinate \a key, according to the - specified width (\ref setWidth) and width type (\ref setWidthType). - - The output parameters \a lower and \a upper return the number of pixels the bar extends to lower - and higher keys, relative to the \a key coordinate (so with a non-reversed horizontal axis, \a - lower is negative and \a upper positive). -*/ -void QCPBars::getPixelWidth(double key, double &lower, double &upper) const -{ - switch (mWidthType) + painter->setPen(mainPen()); + painter->setBrush(mainBrush()); + QPointF center(position->pixelPosition()); + double w = mSize/2.0; + QRect clip = clipRect(); + switch (mStyle) { - case wtAbsolute: + case tsNone: return; + case tsPlus: { - upper = mWidth*0.5; - lower = -upper; - if (mKeyAxis && (mKeyAxis.data()->rangeReversed() ^ (mKeyAxis.data()->orientation() == Qt::Vertical))) - qSwap(lower, upper); + if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) + { + painter->drawLine(QLineF(center+QPointF(-w, 0), center+QPointF(w, 0))); + painter->drawLine(QLineF(center+QPointF(0, -w), center+QPointF(0, w))); + } break; } - case wtAxisRectRatio: + case tsCrosshair: { - if (mKeyAxis && mKeyAxis.data()->axisRect()) - { - if (mKeyAxis.data()->orientation() == Qt::Horizontal) - upper = mKeyAxis.data()->axisRect()->width()*mWidth*0.5; - else - upper = mKeyAxis.data()->axisRect()->height()*mWidth*0.5; - lower = -upper; - if (mKeyAxis && (mKeyAxis.data()->rangeReversed() ^ (mKeyAxis.data()->orientation() == Qt::Vertical))) - qSwap(lower, upper); - } else - qDebug() << Q_FUNC_INFO << "No key axis or axis rect defined"; + if (center.y() > clip.top() && center.y() < clip.bottom()) + painter->drawLine(QLineF(clip.left(), center.y(), clip.right(), center.y())); + if (center.x() > clip.left() && center.x() < clip.right()) + painter->drawLine(QLineF(center.x(), clip.top(), center.x(), clip.bottom())); break; } - case wtPlotCoords: + case tsCircle: { - if (mKeyAxis) - { - double keyPixel = mKeyAxis.data()->coordToPixel(key); - upper = mKeyAxis.data()->coordToPixel(key+mWidth*0.5)-keyPixel; - lower = mKeyAxis.data()->coordToPixel(key-mWidth*0.5)-keyPixel; - // no need to qSwap(lower, higher) when range reversed, because higher/lower are gained by - // coordinate transform which includes range direction - } else - qDebug() << Q_FUNC_INFO << "No key axis defined"; + if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) + painter->drawEllipse(center, w, w); + break; + } + case tsSquare: + { + if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) + painter->drawRect(QRectF(center-QPointF(w, w), center+QPointF(w, w))); break; } } } -/*! \internal +/*! + If the tracer is connected with a graph (\ref setGraph), this function updates the tracer's \a + position to reside on the graph data, depending on the configured key (\ref setGraphKey). - This function is called to find at which value to start drawing the base of a bar at \a key, when - it is stacked on top of another QCPBars (e.g. with \ref moveAbove). + It is called automatically on every redraw and normally doesn't need to be called manually. One + exception is when you want to read the tracer coordinates via \a position and are not sure that + the graph's data (or the tracer key with \ref setGraphKey) hasn't changed since the last redraw. + In that situation, call this function before accessing \a position, to make sure you don't get + out-of-date coordinates. - positive and negative bars are separated per stack (positive are stacked above baseValue upwards, - negative are stacked below baseValue downwards). This can be indicated with \a positive. So if the - bar for which we need the base value is negative, set \a positive to false. + If there is no graph set on this tracer, this function does nothing. */ -double QCPBars::getStackedBaseValue(double key, bool positive) const +void QCPItemTracer::updatePosition() { - if (mBarBelow) + if (mGraph) { - double max = 0; // don't use mBaseValue here because only base value of bottom-most bar has meaning in a bar stack - // find bars of mBarBelow that are approximately at key and find largest one: - double epsilon = qAbs(key)*1e-6; // should be safe even when changed to use float at some point - if (key == 0) - epsilon = 1e-6; - QCPBarDataMap::const_iterator it = mBarBelow.data()->mData->lowerBound(key-epsilon); - QCPBarDataMap::const_iterator itEnd = mBarBelow.data()->mData->upperBound(key+epsilon); - while (it != itEnd) + if (mParentPlot->hasPlottable(mGraph)) { - if ((positive && it.value().value > max) || - (!positive && it.value().value < max)) - max = it.value().value; - ++it; - } - // recurse down the bar-stack to find the total height: - return max + mBarBelow.data()->getStackedBaseValue(key, positive); - } else - return mBaseValue; + if (mGraph->data()->size() > 1) + { + QCPGraphDataContainer::const_iterator first = mGraph->data()->constBegin(); + QCPGraphDataContainer::const_iterator last = mGraph->data()->constEnd()-1; + if (mGraphKey <= first->key) + position->setCoords(first->key, first->value); + else if (mGraphKey >= last->key) + position->setCoords(last->key, last->value); + else + { + QCPGraphDataContainer::const_iterator it = mGraph->data()->findBegin(mGraphKey); + if (it != mGraph->data()->constEnd()) // mGraphKey is not exactly on last iterator, but somewhere between iterators + { + QCPGraphDataContainer::const_iterator prevIt = it; + ++it; // won't advance to constEnd because we handled that case (mGraphKey >= last->key) before + if (mInterpolating) + { + // interpolate between iterators around mGraphKey: + double slope = 0; + if (!qFuzzyCompare(double(it->key), double(prevIt->key))) + slope = (it->value-prevIt->value)/(it->key-prevIt->key); + position->setCoords(mGraphKey, (mGraphKey-prevIt->key)*slope+prevIt->value); + } else + { + // find iterator with key closest to mGraphKey: + if (mGraphKey < (prevIt->key+it->key)*0.5) + position->setCoords(prevIt->key, prevIt->value); + else + position->setCoords(it->key, it->value); + } + } else // mGraphKey is exactly on last iterator (should actually be caught when comparing first/last keys, but this is a failsafe for fp uncertainty) + position->setCoords(it->key, it->value); + } + } else if (mGraph->data()->size() == 1) + { + QCPGraphDataContainer::const_iterator it = mGraph->data()->constBegin(); + position->setCoords(it->key, it->value); + } else + qDebug() << Q_FUNC_INFO << "graph has no data"; + } else + qDebug() << Q_FUNC_INFO << "graph not contained in QCustomPlot instance (anymore)"; + } } /*! \internal - Connects \a below and \a above to each other via their mBarAbove/mBarBelow properties. The bar(s) - currently above lower and below upper will become disconnected to lower/upper. - - If lower is zero, upper will be disconnected at the bottom. - If upper is zero, lower will be disconnected at the top. + Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected + and mSelectedPen when it is. */ -void QCPBars::connectBars(QCPBars *lower, QCPBars *upper) +QPen QCPItemTracer::mainPen() const { - if (!lower && !upper) return; - - if (!lower) // disconnect upper at bottom - { - // disconnect old bar below upper: - if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper) - upper->mBarBelow.data()->mBarAbove = 0; - upper->mBarBelow = 0; - } else if (!upper) // disconnect lower at top - { - // disconnect old bar above lower: - if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower) - lower->mBarAbove.data()->mBarBelow = 0; - lower->mBarAbove = 0; - } else // connect lower and upper - { - // disconnect old bar above lower: - if (lower->mBarAbove && lower->mBarAbove.data()->mBarBelow.data() == lower) - lower->mBarAbove.data()->mBarBelow = 0; - // disconnect old bar below upper: - if (upper->mBarBelow && upper->mBarBelow.data()->mBarAbove.data() == upper) - upper->mBarBelow.data()->mBarAbove = 0; - lower->mBarAbove = upper; - upper->mBarBelow = lower; - } + return mSelected ? mSelectedPen : mPen; } -/* inherits documentation from base class */ -QCPRange QCPBars::getKeyRange(bool &foundRange, SignDomain inSignDomain) const -{ - QCPRange range; - bool haveLower = false; - bool haveUpper = false; - - double current; - QCPBarDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().key; - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) - { - if (current < range.lower || !haveLower) - { - range.lower = current; - haveLower = true; - } - if (current > range.upper || !haveUpper) - { - range.upper = current; - haveUpper = true; - } - } - ++it; - } - // determine exact range of bars by including bar width and barsgroup offset: - if (haveLower && mKeyAxis) - { - double lowerPixelWidth, upperPixelWidth, keyPixel; - getPixelWidth(range.lower, lowerPixelWidth, upperPixelWidth); - keyPixel = mKeyAxis.data()->coordToPixel(range.lower) + lowerPixelWidth; - if (mBarsGroup) - keyPixel += mBarsGroup->keyPixelOffset(this, range.lower); - range.lower = mKeyAxis.data()->pixelToCoord(keyPixel); - } - if (haveUpper && mKeyAxis) - { - double lowerPixelWidth, upperPixelWidth, keyPixel; - getPixelWidth(range.upper, lowerPixelWidth, upperPixelWidth); - keyPixel = mKeyAxis.data()->coordToPixel(range.upper) + upperPixelWidth; - if (mBarsGroup) - keyPixel += mBarsGroup->keyPixelOffset(this, range.upper); - range.upper = mKeyAxis.data()->pixelToCoord(keyPixel); - } - foundRange = haveLower && haveUpper; - return range; -} +/*! \internal -/* inherits documentation from base class */ -QCPRange QCPBars::getValueRange(bool &foundRange, SignDomain inSignDomain) const + Returns the brush that should be used for drawing fills of the item. Returns mBrush when the item + is not selected and mSelectedBrush when it is. +*/ +QBrush QCPItemTracer::mainBrush() const { - QCPRange range; - range.lower = mBaseValue; - range.upper = mBaseValue; - bool haveLower = true; // set to true, because baseValue should always be visible in bar charts - bool haveUpper = true; // set to true, because baseValue should always be visible in bar charts - double current; - - QCPBarDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().value + getStackedBaseValue(it.value().key, it.value().value >= 0); - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) - { - if (current < range.lower || !haveLower) - { - range.lower = current; - haveLower = true; - } - if (current > range.upper || !haveUpper) - { - range.upper = current; - haveUpper = true; - } - } - ++it; - } - - foundRange = true; // return true because bar charts always have the 0-line visible - return range; + return mSelected ? mSelectedBrush : mBrush; } +/* end of 'src/items/item-tracer.cpp' */ +/* including file 'src/items/item-bracket.cpp' */ +/* modified 2022-11-06T12:45:56, size 10705 */ + //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPStatisticalBox +//////////////////// QCPItemBracket //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPStatisticalBox - \brief A plottable representing a single statistical box in a plot. +/*! \class QCPItemBracket + \brief A bracket for referencing/highlighting certain parts in the plot. - \image html QCPStatisticalBox.png - - To plot data, assign it with the individual parameter functions or use \ref setData to set all - parameters at once. The individual functions are: - \li \ref setMinimum - \li \ref setLowerQuartile - \li \ref setMedian - \li \ref setUpperQuartile - \li \ref setMaximum - - Additionally you can define a list of outliers, drawn as scatter datapoints: - \li \ref setOutliers - - \section appearance Changing the appearance - - The appearance of the box itself is controlled via \ref setPen and \ref setBrush. You may change - the width of the box with \ref setWidth in plot coordinates (not pixels). + \image html QCPItemBracket.png "Bracket example. Blue dotted circles are anchors, solid blue discs are positions." - Analog functions exist for the minimum/maximum-whiskers: \ref setWhiskerPen, \ref - setWhiskerBarPen, \ref setWhiskerWidth. The whisker width is the width of the bar at the top - (maximum) and bottom (minimum). - - The median indicator line has its own pen, \ref setMedianPen. - - If the whisker backbone pen is changed, make sure to set the capStyle to Qt::FlatCap. Else, the - backbone line might exceed the whisker bars by a few pixels due to the pen cap being not - perfectly flat. + It has two positions, \a left and \a right, which define the span of the bracket. If \a left is + actually farther to the left than \a right, the bracket is opened to the bottom, as shown in the + example image. - The Outlier data points are drawn as normal scatter points. Their look can be controlled with - \ref setOutlierStyle + The bracket supports multiple styles via \ref setStyle. The length, i.e. how far the bracket + stretches away from the embraced span, can be controlled with \ref setLength. - \section usage Usage + \image html QCPItemBracket-length.png +
Demonstrating the effect of different values for \ref setLength, for styles \ref + bsCalligraphic and \ref bsSquare. Anchors and positions are displayed for reference.
- Like all data representing objects in QCustomPlot, the QCPStatisticalBox is a plottable. - Usually, you first create an instance and add it to the customPlot: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpstatisticalbox-creation-1 - and then modify the properties of the newly created plottable, e.g.: - \snippet documentation/doc-code-snippets/mainwindow.cpp qcpstatisticalbox-creation-2 + It provides an anchor \a center, to allow connection of other items, e.g. an arrow (QCPItemLine + or QCPItemCurve) or a text label (QCPItemText), to the bracket. */ /*! - Constructs a statistical box which uses \a keyAxis as its key axis ("x") and \a valueAxis as its - value axis ("y"). \a keyAxis and \a valueAxis must reside in the same QCustomPlot instance and - not have the same orientation. If either of these restrictions is violated, a corresponding - message is printed to the debug output (qDebug), the construction is not aborted, though. + Creates a bracket item and sets default values. - The constructed statistical box can be added to the plot with QCustomPlot::addPlottable, - QCustomPlot then takes ownership of the statistical box. + The created item is automatically registered with \a parentPlot. This QCustomPlot instance takes + ownership of the item, so do not delete it manually but use QCustomPlot::removeItem() instead. */ -QCPStatisticalBox::QCPStatisticalBox(QCPAxis *keyAxis, QCPAxis *valueAxis) : - QCPAbstractPlottable(keyAxis, valueAxis), - mKey(0), - mMinimum(0), - mLowerQuartile(0), - mMedian(0), - mUpperQuartile(0), - mMaximum(0) +QCPItemBracket::QCPItemBracket(QCustomPlot *parentPlot) : + QCPAbstractItem(parentPlot), + left(createPosition(QLatin1String("left"))), + right(createPosition(QLatin1String("right"))), + center(createAnchor(QLatin1String("center"), aiCenter)), + mLength(8), + mStyle(bsCalligraphic) { - setOutlierStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, Qt::blue, 6)); - setWhiskerWidth(0.2); - setWidth(0.5); + left->setCoords(0, 0); + right->setCoords(1, 1); setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue, 2.5)); - setMedianPen(QPen(Qt::black, 3, Qt::SolidLine, Qt::FlatCap)); - setWhiskerPen(QPen(Qt::black, 0, Qt::DashLine, Qt::FlatCap)); - setWhiskerBarPen(QPen(Qt::black)); - setBrush(Qt::NoBrush); - setSelectedBrush(Qt::NoBrush); + setSelectedPen(QPen(Qt::blue, 2)); } -/*! - Sets the key coordinate of the statistical box. -*/ -void QCPStatisticalBox::setKey(double key) +QCPItemBracket::~QCPItemBracket() { - mKey = key; } /*! - Sets the parameter "minimum" of the statistical box plot. This is the position of the lower - whisker, typically the minimum measurement of the sample that's not considered an outlier. + Sets the pen that will be used to draw the bracket. + + Note that when the style is \ref bsCalligraphic, only the color will be taken from the pen, the + stroke and width are ignored. To change the apparent stroke width of a calligraphic bracket, use + \ref setLength, which has a similar effect. - \see setMaximum, setWhiskerPen, setWhiskerBarPen, setWhiskerWidth + \see setSelectedPen */ -void QCPStatisticalBox::setMinimum(double value) +void QCPItemBracket::setPen(const QPen &pen) { - mMinimum = value; + mPen = pen; } /*! - Sets the parameter "lower Quartile" of the statistical box plot. This is the lower end of the - box. The lower and the upper quartiles are the two statistical quartiles around the median of the - sample, they contain 50% of the sample data. + Sets the pen that will be used to draw the bracket when selected - \see setUpperQuartile, setPen, setBrush, setWidth + \see setPen, setSelected */ -void QCPStatisticalBox::setLowerQuartile(double value) +void QCPItemBracket::setSelectedPen(const QPen &pen) { - mLowerQuartile = value; + mSelectedPen = pen; } /*! - Sets the parameter "median" of the statistical box plot. This is the value of the median mark - inside the quartile box. The median separates the sample data in half (50% of the sample data is - below/above the median). + Sets the \a length in pixels how far the bracket extends in the direction towards the embraced + span of the bracket (i.e. perpendicular to the left-right-direction) - \see setMedianPen + \image html QCPItemBracket-length.png +
Demonstrating the effect of different values for \ref setLength, for styles \ref + bsCalligraphic and \ref bsSquare. Anchors and positions are displayed for reference.
*/ -void QCPStatisticalBox::setMedian(double value) +void QCPItemBracket::setLength(double length) { - mMedian = value; + mLength = length; } /*! - Sets the parameter "upper Quartile" of the statistical box plot. This is the upper end of the - box. The lower and the upper quartiles are the two statistical quartiles around the median of the - sample, they contain 50% of the sample data. + Sets the style of the bracket, i.e. the shape/visual appearance. - \see setLowerQuartile, setPen, setBrush, setWidth + \see setPen */ -void QCPStatisticalBox::setUpperQuartile(double value) +void QCPItemBracket::setStyle(QCPItemBracket::BracketStyle style) { - mUpperQuartile = value; + mStyle = style; } -/*! - Sets the parameter "maximum" of the statistical box plot. This is the position of the upper - whisker, typically the maximum measurement of the sample that's not considered an outlier. +/* inherits documentation from base class */ +double QCPItemBracket::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +{ + Q_UNUSED(details) + if (onlySelectable && !mSelectable) + return -1; - \see setMinimum, setWhiskerPen, setWhiskerBarPen, setWhiskerWidth -*/ -void QCPStatisticalBox::setMaximum(double value) + QCPVector2D p(pos); + QCPVector2D leftVec(left->pixelPosition()); + QCPVector2D rightVec(right->pixelPosition()); + if (leftVec.toPoint() == rightVec.toPoint()) + return -1; + + QCPVector2D widthVec = (rightVec-leftVec)*0.5; + QCPVector2D lengthVec = widthVec.perpendicular().normalized()*mLength; + QCPVector2D centerVec = (rightVec+leftVec)*0.5-lengthVec; + + switch (mStyle) + { + case QCPItemBracket::bsSquare: + case QCPItemBracket::bsRound: + { + double a = p.distanceSquaredToLine(centerVec-widthVec, centerVec+widthVec); + double b = p.distanceSquaredToLine(centerVec-widthVec+lengthVec, centerVec-widthVec); + double c = p.distanceSquaredToLine(centerVec+widthVec+lengthVec, centerVec+widthVec); + return qSqrt(qMin(qMin(a, b), c)); + } + case QCPItemBracket::bsCurly: + case QCPItemBracket::bsCalligraphic: + { + double a = p.distanceSquaredToLine(centerVec-widthVec*0.75+lengthVec*0.15, centerVec+lengthVec*0.3); + double b = p.distanceSquaredToLine(centerVec-widthVec+lengthVec*0.7, centerVec-widthVec*0.75+lengthVec*0.15); + double c = p.distanceSquaredToLine(centerVec+widthVec*0.75+lengthVec*0.15, centerVec+lengthVec*0.3); + double d = p.distanceSquaredToLine(centerVec+widthVec+lengthVec*0.7, centerVec+widthVec*0.75+lengthVec*0.15); + return qSqrt(qMin(qMin(a, b), qMin(c, d))); + } + } + return -1; +} + +/* inherits documentation from base class */ +void QCPItemBracket::draw(QCPPainter *painter) { - mMaximum = value; + QCPVector2D leftVec(left->pixelPosition()); + QCPVector2D rightVec(right->pixelPosition()); + if (leftVec.toPoint() == rightVec.toPoint()) + return; + + QCPVector2D widthVec = (rightVec-leftVec)*0.5; + QCPVector2D lengthVec = widthVec.perpendicular().normalized()*mLength; + QCPVector2D centerVec = (rightVec+leftVec)*0.5-lengthVec; + + QPolygon boundingPoly; + boundingPoly << leftVec.toPoint() << rightVec.toPoint() + << (rightVec-lengthVec).toPoint() << (leftVec-lengthVec).toPoint(); + const int clipEnlarge = qCeil(mainPen().widthF()); + QRect clip = clipRect().adjusted(-clipEnlarge, -clipEnlarge, clipEnlarge, clipEnlarge); + if (clip.intersects(boundingPoly.boundingRect())) + { + painter->setPen(mainPen()); + switch (mStyle) + { + case bsSquare: + { + painter->drawLine((centerVec+widthVec).toPointF(), (centerVec-widthVec).toPointF()); + painter->drawLine((centerVec+widthVec).toPointF(), (centerVec+widthVec+lengthVec).toPointF()); + painter->drawLine((centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF()); + break; + } + case bsRound: + { + painter->setBrush(Qt::NoBrush); + QPainterPath path; + path.moveTo((centerVec+widthVec+lengthVec).toPointF()); + path.cubicTo((centerVec+widthVec).toPointF(), (centerVec+widthVec).toPointF(), centerVec.toPointF()); + path.cubicTo((centerVec-widthVec).toPointF(), (centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF()); + painter->drawPath(path); + break; + } + case bsCurly: + { + painter->setBrush(Qt::NoBrush); + QPainterPath path; + path.moveTo((centerVec+widthVec+lengthVec).toPointF()); + path.cubicTo((centerVec+widthVec-lengthVec*0.8).toPointF(), (centerVec+0.4*widthVec+lengthVec).toPointF(), centerVec.toPointF()); + path.cubicTo((centerVec-0.4*widthVec+lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8).toPointF(), (centerVec-widthVec+lengthVec).toPointF()); + painter->drawPath(path); + break; + } + case bsCalligraphic: + { + painter->setPen(Qt::NoPen); + painter->setBrush(QBrush(mainPen().color())); + QPainterPath path; + path.moveTo((centerVec+widthVec+lengthVec).toPointF()); + + path.cubicTo((centerVec+widthVec-lengthVec*0.8).toPointF(), (centerVec+0.4*widthVec+0.8*lengthVec).toPointF(), centerVec.toPointF()); + path.cubicTo((centerVec-0.4*widthVec+0.8*lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8).toPointF(), (centerVec-widthVec+lengthVec).toPointF()); + + path.cubicTo((centerVec-widthVec-lengthVec*0.5).toPointF(), (centerVec-0.2*widthVec+1.2*lengthVec).toPointF(), (centerVec+lengthVec*0.2).toPointF()); + path.cubicTo((centerVec+0.2*widthVec+1.2*lengthVec).toPointF(), (centerVec+widthVec-lengthVec*0.5).toPointF(), (centerVec+widthVec+lengthVec).toPointF()); + + painter->drawPath(path); + break; + } + } + } } -/*! - Sets a vector of outlier values that will be drawn as scatters. Any data points in the sample - that are not within the whiskers (\ref setMinimum, \ref setMaximum) should be considered outliers - and displayed as such. +/* inherits documentation from base class */ +QPointF QCPItemBracket::anchorPixelPosition(int anchorId) const +{ + QCPVector2D leftVec(left->pixelPosition()); + QCPVector2D rightVec(right->pixelPosition()); + if (leftVec.toPoint() == rightVec.toPoint()) + return leftVec.toPointF(); - \see setOutlierStyle + QCPVector2D widthVec = (rightVec-leftVec)*0.5; + QCPVector2D lengthVec = widthVec.perpendicular().normalized()*mLength; + QCPVector2D centerVec = (rightVec+leftVec)*0.5-lengthVec; + + switch (anchorId) + { + case aiCenter: + return centerVec.toPointF(); + } + qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; + return {}; +} + +/*! \internal + + Returns the pen that should be used for drawing lines. Returns mPen when the + item is not selected and mSelectedPen when it is. */ -void QCPStatisticalBox::setOutliers(const QVector &values) +QPen QCPItemBracket::mainPen() const { - mOutliers = values; + return mSelected ? mSelectedPen : mPen; } +/* end of 'src/items/item-bracket.cpp' */ -/*! - Sets all parameters of the statistical box plot at once. + +/* including file 'src/polar/radialaxis.cpp' */ +/* modified 2022-11-06T12:45:57, size 49415 */ + + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPPolarAxisRadial +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPPolarAxisRadial + \brief The radial axis inside a radial plot + + \warning In this QCustomPlot version, polar plots are a tech preview. Expect documentation and + functionality to be incomplete, as well as changing public interfaces in the future. - \see setKey, setMinimum, setLowerQuartile, setMedian, setUpperQuartile, setMaximum + Each axis holds an instance of QCPAxisTicker which is used to generate the tick coordinates and + tick labels. You can access the currently installed \ref ticker or set a new one (possibly one of + the specialized subclasses, or your own subclass) via \ref setTicker. For details, see the + documentation of QCPAxisTicker. */ -void QCPStatisticalBox::setData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum) -{ - setKey(key); - setMinimum(minimum); - setLowerQuartile(lowerQuartile); - setMedian(median); - setUpperQuartile(upperQuartile); - setMaximum(maximum); -} -/*! - Sets the width of the box in key coordinates. +/* start of documentation of inline functions */ + +/*! \fn QSharedPointer QCPPolarAxisRadial::ticker() const + + Returns a modifiable shared pointer to the currently installed axis ticker. The axis ticker is + responsible for generating the tick positions and tick labels of this axis. You can access the + \ref QCPAxisTicker with this method and modify basic properties such as the approximate tick count + (\ref QCPAxisTicker::setTickCount). + + You can gain more control over the axis ticks by setting a different \ref QCPAxisTicker subclass, see + the documentation there. A new axis ticker can be set with \ref setTicker. + + Since the ticker is stored in the axis as a shared pointer, multiple axes may share the same axis + ticker simply by passing the same shared pointer to multiple axes. + + \see setTicker +*/ + +/* end of documentation of inline functions */ +/* start of documentation of signals */ + +/*! \fn void QCPPolarAxisRadial::rangeChanged(const QCPRange &newRange) + + This signal is emitted when the range of this axis has changed. You can connect it to the \ref + setRange slot of another axis to communicate the new range to the other axis, in order for it to + be synchronized. - \see setWhiskerWidth + You may also manipulate/correct the range with \ref setRange in a slot connected to this signal. + This is useful if for example a maximum range span shall not be exceeded, or if the lower/upper + range shouldn't go beyond certain values (see \ref QCPRange::bounded). For example, the following + slot would limit the x axis to ranges between 0 and 10: + \code + customPlot->xAxis->setRange(newRange.bounded(0, 10)) + \endcode +*/ + +/*! \fn void QCPPolarAxisRadial::rangeChanged(const QCPRange &newRange, const QCPRange &oldRange) + \overload + + Additionally to the new range, this signal also provides the previous range held by the axis as + \a oldRange. +*/ + +/*! \fn void QCPPolarAxisRadial::scaleTypeChanged(QCPPolarAxisRadial::ScaleType scaleType); + + This signal is emitted when the scale type changes, by calls to \ref setScaleType +*/ + +/*! \fn void QCPPolarAxisRadial::selectionChanged(QCPPolarAxisRadial::SelectableParts selection) + + This signal is emitted when the selection state of this axis has changed, either by user interaction + or by a direct call to \ref setSelectedParts. */ -void QCPStatisticalBox::setWidth(double width) -{ - mWidth = width; -} + +/*! \fn void QCPPolarAxisRadial::selectableChanged(const QCPPolarAxisRadial::SelectableParts &parts); + + This signal is emitted when the selectability changes, by calls to \ref setSelectableParts +*/ + +/* end of documentation of signals */ /*! - Sets the width of the whiskers (\ref setMinimum, \ref setMaximum) in key coordinates. + Constructs an Axis instance of Type \a type for the axis rect \a parent. - \see setWidth + Usually it isn't necessary to instantiate axes directly, because you can let QCustomPlot create + them for you with \ref QCPAxisRect::addAxis. If you want to use own QCPAxis-subclasses however, + create them manually and then inject them also via \ref QCPAxisRect::addAxis. */ -void QCPStatisticalBox::setWhiskerWidth(double width) +QCPPolarAxisRadial::QCPPolarAxisRadial(QCPPolarAxisAngular *parent) : + QCPLayerable(parent->parentPlot(), QString(), parent), + mRangeDrag(true), + mRangeZoom(true), + mRangeZoomFactor(0.85), + // axis base: + mAngularAxis(parent), + mAngle(45), + mAngleReference(arAngularAxis), + mSelectableParts(spAxis | spTickLabels | spAxisLabel), + mSelectedParts(spNone), + mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + mSelectedBasePen(QPen(Qt::blue, 2)), + // axis label: + mLabelPadding(0), + mLabel(), + mLabelFont(mParentPlot->font()), + mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)), + mLabelColor(Qt::black), + mSelectedLabelColor(Qt::blue), + // tick labels: + // mTickLabelPadding(0), in label painter + mTickLabels(true), + // mTickLabelRotation(0), in label painter + mTickLabelFont(mParentPlot->font()), + mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)), + mTickLabelColor(Qt::black), + mSelectedTickLabelColor(Qt::blue), + mNumberPrecision(6), + mNumberFormatChar('g'), + mNumberBeautifulPowers(true), + mNumberMultiplyCross(false), + // ticks and subticks: + mTicks(true), + mSubTicks(true), + mTickLengthIn(5), + mTickLengthOut(0), + mSubTickLengthIn(2), + mSubTickLengthOut(0), + mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + mSelectedTickPen(QPen(Qt::blue, 2)), + mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + mSelectedSubTickPen(QPen(Qt::blue, 2)), + // scale and range: + mRange(0, 5), + mRangeReversed(false), + mScaleType(stLinear), + // internal members: + mRadius(1), // non-zero initial value, will be overwritten in ::update() according to inner rect + mTicker(new QCPAxisTicker), + mLabelPainter(mParentPlot) +{ + setParent(parent); + setAntialiased(true); + + setTickLabelPadding(5); + setTickLabelRotation(0); + setTickLabelMode(lmUpright); + mLabelPainter.setAnchorReferenceType(QCPLabelPainterPrivate::artTangent); + mLabelPainter.setAbbreviateDecimalPowers(false); +} + +QCPPolarAxisRadial::~QCPPolarAxisRadial() { - mWhiskerWidth = width; } -/*! - Sets the pen used for drawing the whisker backbone (That's the line parallel to the value axis). - - Make sure to set the \a pen capStyle to Qt::FlatCap to prevent the whisker backbone from reaching - a few pixels past the whisker bars, when using a non-zero pen width. - - \see setWhiskerBarPen -*/ -void QCPStatisticalBox::setWhiskerPen(const QPen &pen) +QCPPolarAxisRadial::LabelMode QCPPolarAxisRadial::tickLabelMode() const { - mWhiskerPen = pen; + switch (mLabelPainter.anchorMode()) + { + case QCPLabelPainterPrivate::amSkewedUpright: return lmUpright; + case QCPLabelPainterPrivate::amSkewedRotated: return lmRotated; + default: qDebug() << Q_FUNC_INFO << "invalid mode for polar axis"; break; + } + return lmUpright; } -/*! - Sets the pen used for drawing the whisker bars (Those are the lines parallel to the key axis at - each end of the whisker backbone). - - \see setWhiskerPen -*/ -void QCPStatisticalBox::setWhiskerBarPen(const QPen &pen) +/* No documentation as it is a property getter */ +QString QCPPolarAxisRadial::numberFormat() const { - mWhiskerBarPen = pen; + QString result; + result.append(mNumberFormatChar); + if (mNumberBeautifulPowers) + { + result.append(QLatin1Char('b')); + if (mNumberMultiplyCross) + result.append(QLatin1Char('c')); + } + return result; } -/*! - Sets the pen used for drawing the median indicator line inside the statistical box. -*/ -void QCPStatisticalBox::setMedianPen(const QPen &pen) +/* No documentation as it is a property getter */ +int QCPPolarAxisRadial::tickLengthIn() const { - mMedianPen = pen; + return mTickLengthIn; } -/*! - Sets the appearance of the outlier data points. - - \see setOutliers -*/ -void QCPStatisticalBox::setOutlierStyle(const QCPScatterStyle &style) +/* No documentation as it is a property getter */ +int QCPPolarAxisRadial::tickLengthOut() const { - mOutlierStyle = style; + return mTickLengthOut; } -/* inherits documentation from base class */ -void QCPStatisticalBox::clearData() +/* No documentation as it is a property getter */ +int QCPPolarAxisRadial::subTickLengthIn() const { - setOutliers(QVector()); - setKey(0); - setMinimum(0); - setLowerQuartile(0); - setMedian(0); - setUpperQuartile(0); - setMaximum(0); + return mSubTickLengthIn; } -/* inherits documentation from base class */ -double QCPStatisticalBox::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +/* No documentation as it is a property getter */ +int QCPPolarAxisRadial::subTickLengthOut() const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } - - if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) - { - double posKey, posValue; - pixelsToCoords(pos, posKey, posValue); - // quartile box: - QCPRange keyRange(mKey-mWidth*0.5, mKey+mWidth*0.5); - QCPRange valueRange(mLowerQuartile, mUpperQuartile); - if (keyRange.contains(posKey) && valueRange.contains(posValue)) - return mParentPlot->selectionTolerance()*0.99; - - // min/max whiskers: - if (QCPRange(mMinimum, mMaximum).contains(posValue)) - return qAbs(mKeyAxis.data()->coordToPixel(mKey)-mKeyAxis.data()->coordToPixel(posKey)); - } - return -1; + return mSubTickLengthOut; } -/* inherits documentation from base class */ -void QCPStatisticalBox::draw(QCPPainter *painter) +/* No documentation as it is a property getter */ +int QCPPolarAxisRadial::labelPadding() const { - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + return mLabelPadding; +} - // check data validity if flag set: -#ifdef QCUSTOMPLOT_CHECK_DATA - if (QCP::isInvalidData(mKey, mMedian) || - QCP::isInvalidData(mLowerQuartile, mUpperQuartile) || - QCP::isInvalidData(mMinimum, mMaximum)) - qDebug() << Q_FUNC_INFO << "Data point at" << mKey << "of drawn range has invalid data." << "Plottable name:" << name(); - for (int i=0; isave(); - painter->setClipRect(quartileBox, Qt::IntersectClip); - drawMedian(painter); - painter->restore(); - - drawWhiskers(painter); - drawOutliers(painter); +void QCPPolarAxisRadial::setRangeDrag(bool enabled) +{ + mRangeDrag = enabled; } -/* inherits documentation from base class */ -void QCPStatisticalBox::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const +void QCPPolarAxisRadial::setRangeZoom(bool enabled) { - // draw filled rect: - applyDefaultAntialiasingHint(painter); - painter->setPen(mPen); - painter->setBrush(mBrush); - QRectF r = QRectF(0, 0, rect.width()*0.67, rect.height()*0.67); - r.moveCenter(rect.center()); - painter->drawRect(r); + mRangeZoom = enabled; } -/*! \internal - - Draws the quartile box. \a box is an output parameter that returns the quartile box (in pixel - coordinates) which is used to set the clip rect of the painter before calling \ref drawMedian (so - the median doesn't draw outside the quartile box). -*/ -void QCPStatisticalBox::drawQuartileBox(QCPPainter *painter, QRectF *quartileBox) const +void QCPPolarAxisRadial::setRangeZoomFactor(double factor) { - QRectF box; - box.setTopLeft(coordsToPixels(mKey-mWidth*0.5, mUpperQuartile)); - box.setBottomRight(coordsToPixels(mKey+mWidth*0.5, mLowerQuartile)); - applyDefaultAntialiasingHint(painter); - painter->setPen(mainPen()); - painter->setBrush(mainBrush()); - painter->drawRect(box); - if (quartileBox) - *quartileBox = box; + mRangeZoomFactor = factor; } -/*! \internal +/*! + Sets whether the axis uses a linear scale or a logarithmic scale. - Draws the median line inside the quartile box. + Note that this method controls the coordinate transformation. For logarithmic scales, you will + likely also want to use a logarithmic tick spacing and labeling, which can be achieved by setting + the axis ticker to an instance of \ref QCPAxisTickerLog : + + \snippet documentation/doc-code-snippets/mainwindow.cpp qcpaxisticker-log-creation + + See the documentation of \ref QCPAxisTickerLog about the details of logarithmic axis tick + creation. + + \ref setNumberPrecision */ -void QCPStatisticalBox::drawMedian(QCPPainter *painter) const +void QCPPolarAxisRadial::setScaleType(QCPPolarAxisRadial::ScaleType type) { - QLineF medianLine; - medianLine.setP1(coordsToPixels(mKey-mWidth*0.5, mMedian)); - medianLine.setP2(coordsToPixels(mKey+mWidth*0.5, mMedian)); - applyDefaultAntialiasingHint(painter); - painter->setPen(mMedianPen); - painter->drawLine(medianLine); + if (mScaleType != type) + { + mScaleType = type; + if (mScaleType == stLogarithmic) + setRange(mRange.sanitizedForLogScale()); + //mCachedMarginValid = false; + emit scaleTypeChanged(mScaleType); + } } -/*! \internal +/*! + Sets the range of the axis. + + This slot may be connected with the \ref rangeChanged signal of another axis so this axis + is always synchronized with the other axis range, when it changes. - Draws both whisker backbones and bars. + To invert the direction of an axis, use \ref setRangeReversed. */ -void QCPStatisticalBox::drawWhiskers(QCPPainter *painter) const +void QCPPolarAxisRadial::setRange(const QCPRange &range) { - QLineF backboneMin, backboneMax, barMin, barMax; - backboneMax.setPoints(coordsToPixels(mKey, mUpperQuartile), coordsToPixels(mKey, mMaximum)); - backboneMin.setPoints(coordsToPixels(mKey, mLowerQuartile), coordsToPixels(mKey, mMinimum)); - barMax.setPoints(coordsToPixels(mKey-mWhiskerWidth*0.5, mMaximum), coordsToPixels(mKey+mWhiskerWidth*0.5, mMaximum)); - barMin.setPoints(coordsToPixels(mKey-mWhiskerWidth*0.5, mMinimum), coordsToPixels(mKey+mWhiskerWidth*0.5, mMinimum)); - applyErrorBarsAntialiasingHint(painter); - painter->setPen(mWhiskerPen); - painter->drawLine(backboneMin); - painter->drawLine(backboneMax); - painter->setPen(mWhiskerBarPen); - painter->drawLine(barMin); - painter->drawLine(barMax); + if (range.lower == mRange.lower && range.upper == mRange.upper) + return; + + if (!QCPRange::validRange(range)) return; + QCPRange oldRange = mRange; + if (mScaleType == stLogarithmic) + { + mRange = range.sanitizedForLogScale(); + } else + { + mRange = range.sanitizedForLinScale(); + } + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } -/*! \internal +/*! + Sets whether the user can (de-)select the parts in \a selectable by clicking on the QCustomPlot surface. + (When \ref QCustomPlot::setInteractions contains iSelectAxes.) + + However, even when \a selectable is set to a value not allowing the selection of a specific part, + it is still possible to set the selection of this part manually, by calling \ref setSelectedParts + directly. - Draws the outlier scatter points. + \see SelectablePart, setSelectedParts */ -void QCPStatisticalBox::drawOutliers(QCPPainter *painter) const +void QCPPolarAxisRadial::setSelectableParts(const SelectableParts &selectable) { - applyScattersAntialiasingHint(painter); - mOutlierStyle.applyTo(painter, mPen); - for (int i=0; i 0) - return QCPRange(mKey-mWidth*0.5, mKey+mWidth*0.5); - else if (mKey > 0) - return QCPRange(mKey, mKey+mWidth*0.5); - else - { - foundRange = false; - return QCPRange(); - } + mSelectedParts = selected; + emit selectionChanged(mSelectedParts); } - foundRange = false; - return QCPRange(); } -/* inherits documentation from base class */ -QCPRange QCPStatisticalBox::getValueRange(bool &foundRange, SignDomain inSignDomain) const +/*! + \overload + + Sets the lower and upper bound of the axis range. + + To invert the direction of an axis, use \ref setRangeReversed. + + There is also a slot to set a range, see \ref setRange(const QCPRange &range). +*/ +void QCPPolarAxisRadial::setRange(double lower, double upper) { - QVector values; // values that must be considered (i.e. all outliers and the five box-parameters) - values.reserve(mOutliers.size() + 5); - values << mMaximum << mUpperQuartile << mMedian << mLowerQuartile << mMinimum; - values << mOutliers; - // go through values and find the ones in legal range: - bool haveUpper = false; - bool haveLower = false; - double upper = 0; - double lower = 0; - for (int i=0; i 0) || - (inSignDomain == sdBoth)) - { - if (values.at(i) > upper || !haveUpper) - { - upper = values.at(i); - haveUpper = true; - } - if (values.at(i) < lower || !haveLower) - { - lower = values.at(i); - haveLower = true; - } - } - } - // return the bounds if we found some sensible values: - if (haveLower && haveUpper) + if (lower == mRange.lower && upper == mRange.upper) + return; + + if (!QCPRange::validRange(lower, upper)) return; + QCPRange oldRange = mRange; + mRange.lower = lower; + mRange.upper = upper; + if (mScaleType == stLogarithmic) { - foundRange = true; - return QCPRange(lower, upper); - } else // might happen if all values are in other sign domain + mRange = mRange.sanitizedForLogScale(); + } else { - foundRange = false; - return QCPRange(); + mRange = mRange.sanitizedForLinScale(); } + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPColorMapData -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPColorMapData - \brief Holds the two-dimensional data of a QCPColorMap plottable. - - This class is a data storage for \ref QCPColorMap. It holds a two-dimensional array, which \ref - QCPColorMap then displays as a 2D image in the plot, where the array values are represented by a - color, depending on the value. - - The size of the array can be controlled via \ref setSize (or \ref setKeySize, \ref setValueSize). - Which plot coordinates these cells correspond to can be configured with \ref setRange (or \ref - setKeyRange, \ref setValueRange). +/*! + \overload - The data cells can be accessed in two ways: They can be directly addressed by an integer index - with \ref setCell. This is the fastest method. Alternatively, they can be addressed by their plot - coordinate with \ref setData. plot coordinate to cell index transformations and vice versa are - provided by the functions \ref coordToCell and \ref cellToCoord. + Sets the range of the axis. - This class also buffers the minimum and maximum values that are in the data set, to provide - QCPColorMap::rescaleDataRange with the necessary information quickly. Setting a cell to a value - that is greater than the current maximum increases this maximum to the new value. However, - setting the cell that currently holds the maximum value to a smaller value doesn't decrease the - maximum again, because finding the true new maximum would require going through the entire data - array, which might be time consuming. The same holds for the data minimum. This functionality is - given by \ref recalculateDataBounds, such that you can decide when it is sensible to find the - true current minimum and maximum. The method QCPColorMap::rescaleDataRange offers a convenience - parameter \a recalculateDataBounds which may be set to true to automatically call \ref - recalculateDataBounds internally. + The \a position coordinate indicates together with the \a alignment parameter, where the new + range will be positioned. \a size defines the size of the new axis range. \a alignment may be + Qt::AlignLeft, Qt::AlignRight or Qt::AlignCenter. This will cause the left border, right border, + or center of the range to be aligned with \a position. Any other values of \a alignment will + default to Qt::AlignCenter. */ +void QCPPolarAxisRadial::setRange(double position, double size, Qt::AlignmentFlag alignment) +{ + if (alignment == Qt::AlignLeft) + setRange(position, position+size); + else if (alignment == Qt::AlignRight) + setRange(position-size, position); + else // alignment == Qt::AlignCenter + setRange(position-size/2.0, position+size/2.0); +} -/* start of documentation of inline functions */ +/*! + Sets the lower bound of the axis range. The upper bound is not changed. + \see setRange +*/ +void QCPPolarAxisRadial::setRangeLower(double lower) +{ + if (mRange.lower == lower) + return; + + QCPRange oldRange = mRange; + mRange.lower = lower; + if (mScaleType == stLogarithmic) + { + mRange = mRange.sanitizedForLogScale(); + } else + { + mRange = mRange.sanitizedForLinScale(); + } + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); +} -/*! \fn bool QCPColorMapData::isEmpty() const - - Returns whether this instance carries no data. This is equivalent to having a size where at least - one of the dimensions is 0 (see \ref setSize). +/*! + Sets the upper bound of the axis range. The lower bound is not changed. + \see setRange */ - -/* end of documentation of inline functions */ +void QCPPolarAxisRadial::setRangeUpper(double upper) +{ + if (mRange.upper == upper) + return; + + QCPRange oldRange = mRange; + mRange.upper = upper; + if (mScaleType == stLogarithmic) + { + mRange = mRange.sanitizedForLogScale(); + } else + { + mRange = mRange.sanitizedForLinScale(); + } + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); +} /*! - Constructs a new QCPColorMapData instance. The instance has \a keySize cells in the key direction - and \a valueSize cells in the value direction. These cells will be displayed by the \ref QCPColorMap - at the coordinates \a keyRange and \a valueRange. - - \see setSize, setKeySize, setValueSize, setRange, setKeyRange, setValueRange + Sets whether the axis range (direction) is displayed reversed. Normally, the values on horizontal + axes increase left to right, on vertical axes bottom to top. When \a reversed is set to true, the + direction of increasing values is inverted. + + Note that the range and data interface stays the same for reversed axes, e.g. the \a lower part + of the \ref setRange interface will still reference the mathematically smaller number than the \a + upper part. */ -QCPColorMapData::QCPColorMapData(int keySize, int valueSize, const QCPRange &keyRange, const QCPRange &valueRange) : - mKeySize(0), - mValueSize(0), - mKeyRange(keyRange), - mValueRange(valueRange), - mIsEmpty(true), - mData(0), - mDataModified(true) +void QCPPolarAxisRadial::setRangeReversed(bool reversed) { - setSize(keySize, valueSize); - fill(0); + mRangeReversed = reversed; } -QCPColorMapData::~QCPColorMapData() +void QCPPolarAxisRadial::setAngle(double degrees) { - if (mData) - delete[] mData; + mAngle = degrees; +} + +void QCPPolarAxisRadial::setAngleReference(AngleReference reference) +{ + mAngleReference = reference; } /*! - Constructs a new QCPColorMapData instance copying the data and range of \a other. + The axis ticker is responsible for generating the tick positions and tick labels. See the + documentation of QCPAxisTicker for details on how to work with axis tickers. + + You can change the tick positioning/labeling behaviour of this axis by setting a different + QCPAxisTicker subclass using this method. If you only wish to modify the currently installed axis + ticker, access it via \ref ticker. + + Since the ticker is stored in the axis as a shared pointer, multiple axes may share the same axis + ticker simply by passing the same shared pointer to multiple axes. + + \see ticker */ -QCPColorMapData::QCPColorMapData(const QCPColorMapData &other) : - mKeySize(0), - mValueSize(0), - mIsEmpty(true), - mData(0), - mDataModified(true) +void QCPPolarAxisRadial::setTicker(QSharedPointer ticker) { - *this = other; + if (ticker) + mTicker = ticker; + else + qDebug() << Q_FUNC_INFO << "can not set 0 as axis ticker"; + // no need to invalidate margin cache here because produced tick labels are checked for changes in setupTickVector } /*! - Overwrites this color map data instance with the data stored in \a other. + Sets whether tick marks are displayed. + + Note that setting \a show to false does not imply that tick labels are invisible, too. To achieve + that, see \ref setTickLabels. + + \see setSubTicks */ -QCPColorMapData &QCPColorMapData::operator=(const QCPColorMapData &other) +void QCPPolarAxisRadial::setTicks(bool show) { - if (&other != this) + if (mTicks != show) { - const int keySize = other.keySize(); - const int valueSize = other.valueSize(); - setSize(keySize, valueSize); - setRange(other.keyRange(), other.valueRange()); - if (!mIsEmpty) - memcpy(mData, other.mData, sizeof(mData[0])*keySize*valueSize); - mDataBounds = other.mDataBounds; - mDataModified = true; + mTicks = show; + //mCachedMarginValid = false; } - return *this; } -/* undocumented getter */ -double QCPColorMapData::data(double key, double value) +/*! + Sets whether tick labels are displayed. Tick labels are the numbers drawn next to tick marks. +*/ +void QCPPolarAxisRadial::setTickLabels(bool show) { - int keyCell = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5; - int valueCell = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5; - if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize) - return mData[valueCell*mKeySize + keyCell]; - else - return 0; + if (mTickLabels != show) + { + mTickLabels = show; + //mCachedMarginValid = false; + if (!mTickLabels) + mTickVectorLabels.clear(); + } } -/* undocumented getter */ -double QCPColorMapData::cell(int keyIndex, int valueIndex) +/*! + Sets the distance between the axis base line (including any outward ticks) and the tick labels. + \see setLabelPadding, setPadding +*/ +void QCPPolarAxisRadial::setTickLabelPadding(int padding) { - if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize) - return mData[valueIndex*mKeySize + keyIndex]; - else - return 0; + mLabelPainter.setPadding(padding); } /*! - Resizes the data array to have \a keySize cells in the key dimension and \a valueSize cells in - the value dimension. - - The current data is discarded and the map cells are set to 0, unless the map had already the - requested size. + Sets the font of the tick labels. - Setting at least one of \a keySize or \a valueSize to zero frees the internal data array and \ref - isEmpty returns true. - - \see setRange, setKeySize, setValueSize + \see setTickLabels, setTickLabelColor */ -void QCPColorMapData::setSize(int keySize, int valueSize) +void QCPPolarAxisRadial::setTickLabelFont(const QFont &font) { - if (keySize != mKeySize || valueSize != mValueSize) + if (font != mTickLabelFont) { - mKeySize = keySize; - mValueSize = valueSize; - if (mData) - delete[] mData; - mIsEmpty = mKeySize == 0 || mValueSize == 0; - if (!mIsEmpty) - { -#ifdef __EXCEPTIONS - try { // 2D arrays get memory intensive fast. So if the allocation fails, at least output debug message -#endif - mData = new double[mKeySize*mValueSize]; -#ifdef __EXCEPTIONS - } catch (...) { mData = 0; } -#endif - if (mData) - fill(0); - else - qDebug() << Q_FUNC_INFO << "out of memory for data dimensions "<< mKeySize << "*" << mValueSize; - } else - mData = 0; - mDataModified = true; + mTickLabelFont = font; + //mCachedMarginValid = false; } } /*! - Resizes the data array to have \a keySize cells in the key dimension. - - The current data is discarded and the map cells are set to 0, unless the map had already the - requested size. + Sets the color of the tick labels. - Setting \a keySize to zero frees the internal data array and \ref isEmpty returns true. - - \see setKeyRange, setSize, setValueSize + \see setTickLabels, setTickLabelFont */ -void QCPColorMapData::setKeySize(int keySize) +void QCPPolarAxisRadial::setTickLabelColor(const QColor &color) { - setSize(keySize, mValueSize); + mTickLabelColor = color; } /*! - Resizes the data array to have \a valueSize cells in the value dimension. - - The current data is discarded and the map cells are set to 0, unless the map had already the - requested size. + Sets the rotation of the tick labels. If \a degrees is zero, the labels are drawn normally. Else, + the tick labels are drawn rotated by \a degrees clockwise. The specified angle is bound to values + from -90 to 90 degrees. - Setting \a valueSize to zero frees the internal data array and \ref isEmpty returns true. - - \see setValueRange, setSize, setKeySize + If \a degrees is exactly -90, 0 or 90, the tick labels are centered on the tick coordinate. For + other angles, the label is drawn with an offset such that it seems to point toward or away from + the tick mark. */ -void QCPColorMapData::setValueSize(int valueSize) +void QCPPolarAxisRadial::setTickLabelRotation(double degrees) { - setSize(mKeySize, valueSize); + mLabelPainter.setRotation(degrees); +} + +void QCPPolarAxisRadial::setTickLabelMode(LabelMode mode) +{ + switch (mode) + { + case lmUpright: mLabelPainter.setAnchorMode(QCPLabelPainterPrivate::amSkewedUpright); break; + case lmRotated: mLabelPainter.setAnchorMode(QCPLabelPainterPrivate::amSkewedRotated); break; + } } /*! - Sets the coordinate ranges the data shall be distributed over. This defines the rectangular area - covered by the color map in plot coordinates. + Sets the number format for the numbers in tick labels. This \a formatCode is an extended version + of the format code used e.g. by QString::number() and QLocale::toString(). For reference about + that, see the "Argument Formats" section in the detailed description of the QString class. - The outer cells will be centered on the range boundaries given to this function. For example, if - the key size (\ref setKeySize) is 3 and \a keyRange is set to QCPRange(2, 3) there will - be cells centered on the key coordinates 2, 2.5 and 3. - - \see setSize + \a formatCode is a string of one, two or three characters. The first character is identical to + the normal format code used by Qt. In short, this means: 'e'/'E' scientific format, 'f' fixed + format, 'g'/'G' scientific or fixed, whichever is shorter. + + The second and third characters are optional and specific to QCustomPlot:\n + If the first char was 'e' or 'g', numbers are/might be displayed in the scientific format, e.g. + "5.5e9", which is ugly in a plot. So when the second char of \a formatCode is set to 'b' (for + "beautiful"), those exponential numbers are formatted in a more natural way, i.e. "5.5 + [multiplication sign] 10 [superscript] 9". By default, the multiplication sign is a centered dot. + If instead a cross should be shown (as is usual in the USA), the third char of \a formatCode can + be set to 'c'. The inserted multiplication signs are the UTF-8 characters 215 (0xD7) for the + cross and 183 (0xB7) for the dot. + + Examples for \a formatCode: + \li \c g normal format code behaviour. If number is small, fixed format is used, if number is large, + normal scientific format is used + \li \c gb If number is small, fixed format is used, if number is large, scientific format is used with + beautifully typeset decimal powers and a dot as multiplication sign + \li \c ebc All numbers are in scientific format with beautifully typeset decimal power and a cross as + multiplication sign + \li \c fb illegal format code, since fixed format doesn't support (or need) beautifully typeset decimal + powers. Format code will be reduced to 'f'. + \li \c hello illegal format code, since first char is not 'e', 'E', 'f', 'g' or 'G'. Current format + code will not be changed. */ -void QCPColorMapData::setRange(const QCPRange &keyRange, const QCPRange &valueRange) +void QCPPolarAxisRadial::setNumberFormat(const QString &formatCode) { - setKeyRange(keyRange); - setValueRange(valueRange); + if (formatCode.isEmpty()) + { + qDebug() << Q_FUNC_INFO << "Passed formatCode is empty"; + return; + } + //mCachedMarginValid = false; + + // interpret first char as number format char: + QString allowedFormatChars(QLatin1String("eEfgG")); + if (allowedFormatChars.contains(formatCode.at(0))) + { + mNumberFormatChar = QLatin1Char(formatCode.at(0).toLatin1()); + } else + { + qDebug() << Q_FUNC_INFO << "Invalid number format code (first char not in 'eEfgG'):" << formatCode; + return; + } + + if (formatCode.length() < 2) + { + mNumberBeautifulPowers = false; + mNumberMultiplyCross = false; + } else + { + // interpret second char as indicator for beautiful decimal powers: + if (formatCode.at(1) == QLatin1Char('b') && (mNumberFormatChar == QLatin1Char('e') || mNumberFormatChar == QLatin1Char('g'))) + mNumberBeautifulPowers = true; + else + qDebug() << Q_FUNC_INFO << "Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode; + + if (formatCode.length() < 3) + { + mNumberMultiplyCross = false; + } else + { + // interpret third char as indicator for dot or cross multiplication symbol: + if (formatCode.at(2) == QLatin1Char('c')) + mNumberMultiplyCross = true; + else if (formatCode.at(2) == QLatin1Char('d')) + mNumberMultiplyCross = false; + else + qDebug() << Q_FUNC_INFO << "Invalid number format code (third char neither 'c' nor 'd'):" << formatCode; + } + } + mLabelPainter.setSubstituteExponent(mNumberBeautifulPowers); + mLabelPainter.setMultiplicationSymbol(mNumberMultiplyCross ? QCPLabelPainterPrivate::SymbolCross : QCPLabelPainterPrivate::SymbolDot); } /*! - Sets the coordinate range the data shall be distributed over in the key dimension. Together with - the value range, This defines the rectangular area covered by the color map in plot coordinates. - - The outer cells will be centered on the range boundaries given to this function. For example, if - the key size (\ref setKeySize) is 3 and \a keyRange is set to QCPRange(2, 3) there will - be cells centered on the key coordinates 2, 2.5 and 3. - - \see setRange, setValueRange, setSize + Sets the precision of the tick label numbers. See QLocale::toString(double i, char f, int prec) + for details. The effect of precisions are most notably for number Formats starting with 'e', see + \ref setNumberFormat */ -void QCPColorMapData::setKeyRange(const QCPRange &keyRange) +void QCPPolarAxisRadial::setNumberPrecision(int precision) { - mKeyRange = keyRange; + if (mNumberPrecision != precision) + { + mNumberPrecision = precision; + //mCachedMarginValid = false; + } } /*! - Sets the coordinate range the data shall be distributed over in the value dimension. Together with - the key range, This defines the rectangular area covered by the color map in plot coordinates. + Sets the length of the ticks in pixels. \a inside is the length the ticks will reach inside the + plot and \a outside is the length they will reach outside the plot. If \a outside is greater than + zero, the tick labels and axis label will increase their distance to the axis accordingly, so + they won't collide with the ticks. - The outer cells will be centered on the range boundaries given to this function. For example, if - the value size (\ref setValueSize) is 3 and \a valueRange is set to QCPRange(2, 3) there - will be cells centered on the value coordinates 2, 2.5 and 3. - - \see setRange, setKeyRange, setSize + \see setSubTickLength, setTickLengthIn, setTickLengthOut */ -void QCPColorMapData::setValueRange(const QCPRange &valueRange) +void QCPPolarAxisRadial::setTickLength(int inside, int outside) { - mValueRange = valueRange; + setTickLengthIn(inside); + setTickLengthOut(outside); } /*! - Sets the data of the cell, which lies at the plot coordinates given by \a key and \a value, to \a - z. + Sets the length of the inward ticks in pixels. \a inside is the length the ticks will reach + inside the plot. - \note The QCPColorMap always displays the data at equal key/value intervals, even if the key or - value axis is set to a logarithmic scaling. If you want to use QCPColorMap with logarithmic axes, - you shouldn't use the \ref QCPColorMapData::setData method as it uses a linear transformation to - determine the cell index. Rather directly access the cell index with \ref - QCPColorMapData::setCell. - - \see setCell, setRange + \see setTickLengthOut, setTickLength, setSubTickLength */ -void QCPColorMapData::setData(double key, double value, double z) +void QCPPolarAxisRadial::setTickLengthIn(int inside) { - int keyCell = (key-mKeyRange.lower)/(mKeyRange.upper-mKeyRange.lower)*(mKeySize-1)+0.5; - int valueCell = (value-mValueRange.lower)/(mValueRange.upper-mValueRange.lower)*(mValueSize-1)+0.5; - if (keyCell >= 0 && keyCell < mKeySize && valueCell >= 0 && valueCell < mValueSize) + if (mTickLengthIn != inside) { - mData[valueCell*mKeySize + keyCell] = z; - if (z < mDataBounds.lower) - mDataBounds.lower = z; - if (z > mDataBounds.upper) - mDataBounds.upper = z; - mDataModified = true; + mTickLengthIn = inside; } } /*! - Sets the data of the cell with indices \a keyIndex and \a valueIndex to \a z. The indices - enumerate the cells starting from zero, up to the map's size-1 in the respective dimension (see - \ref setSize). - - In the standard plot configuration (horizontal key axis and vertical value axis, both not - range-reversed), the cell with indices (0, 0) is in the bottom left corner and the cell with - indices (keySize-1, valueSize-1) is in the top right corner of the color map. + Sets the length of the outward ticks in pixels. \a outside is the length the ticks will reach + outside the plot. If \a outside is greater than zero, the tick labels and axis label will + increase their distance to the axis accordingly, so they won't collide with the ticks. - \see setData, setSize + \see setTickLengthIn, setTickLength, setSubTickLength */ -void QCPColorMapData::setCell(int keyIndex, int valueIndex, double z) +void QCPPolarAxisRadial::setTickLengthOut(int outside) { - if (keyIndex >= 0 && keyIndex < mKeySize && valueIndex >= 0 && valueIndex < mValueSize) + if (mTickLengthOut != outside) { - mData[valueIndex*mKeySize + keyIndex] = z; - if (z < mDataBounds.lower) - mDataBounds.lower = z; - if (z > mDataBounds.upper) - mDataBounds.upper = z; - mDataModified = true; + mTickLengthOut = outside; + //mCachedMarginValid = false; // only outside tick length can change margin } } /*! - Goes through the data and updates the buffered minimum and maximum data values. + Sets whether sub tick marks are displayed. - Calling this method is only advised if you are about to call \ref QCPColorMap::rescaleDataRange - and can not guarantee that the cells holding the maximum or minimum data haven't been overwritten - with a smaller or larger value respectively, since the buffered maximum/minimum values have been - updated the last time. Why this is the case is explained in the class description (\ref - QCPColorMapData). + Sub ticks are only potentially visible if (major) ticks are also visible (see \ref setTicks) - Note that the method \ref QCPColorMap::rescaleDataRange provides a parameter \a - recalculateDataBounds for convenience. Setting this to true will call this method for you, before - doing the rescale. + \see setTicks */ -void QCPColorMapData::recalculateDataBounds() +void QCPPolarAxisRadial::setSubTicks(bool show) { - if (mKeySize > 0 && mValueSize > 0) + if (mSubTicks != show) { - double minHeight = mData[0]; - double maxHeight = mData[0]; - const int dataCount = mValueSize*mKeySize; - for (int i=0; i maxHeight) - maxHeight = mData[i]; - if (mData[i] < minHeight) - minHeight = mData[i]; - } - mDataBounds.lower = minHeight; - mDataBounds.upper = maxHeight; + mSubTicks = show; + //mCachedMarginValid = false; } } /*! - Frees the internal data memory. + Sets the length of the subticks in pixels. \a inside is the length the subticks will reach inside + the plot and \a outside is the length they will reach outside the plot. If \a outside is greater + than zero, the tick labels and axis label will increase their distance to the axis accordingly, + so they won't collide with the ticks. - This is equivalent to calling \ref setSize "setSize(0, 0)". + \see setTickLength, setSubTickLengthIn, setSubTickLengthOut */ -void QCPColorMapData::clear() +void QCPPolarAxisRadial::setSubTickLength(int inside, int outside) { - setSize(0, 0); + setSubTickLengthIn(inside); + setSubTickLengthOut(outside); } /*! - Sets all cells to the value \a z. + Sets the length of the inward subticks in pixels. \a inside is the length the subticks will reach inside + the plot. + + \see setSubTickLengthOut, setSubTickLength, setTickLength */ -void QCPColorMapData::fill(double z) +void QCPPolarAxisRadial::setSubTickLengthIn(int inside) { - const int dataCount = mValueSize*mKeySize; - for (int i=0; i(data); - return; - } - if (copy) - { - *mMapData = *data; - } else + if (mLabelPadding != padding) { - delete mMapData; - mMapData = data; + mLabelPadding = padding; + //mCachedMarginValid = false; } - mMapImageInvalidated = true; } /*! - Sets the data range of this color map to \a dataRange. The data range defines which data values - are mapped to the color gradient. - - To make the data range span the full range of the data set, use \ref rescaleDataRange. + Sets the font that is used for tick labels when they are selected. - \see QCPColorScale::setDataRange + \see setTickLabelFont, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions */ -void QCPColorMap::setDataRange(const QCPRange &dataRange) +void QCPPolarAxisRadial::setSelectedTickLabelFont(const QFont &font) { - if (!QCPRange::validRange(dataRange)) return; - if (mDataRange.lower != dataRange.lower || mDataRange.upper != dataRange.upper) + if (font != mSelectedTickLabelFont) { - if (mDataScaleType == QCPAxis::stLogarithmic) - mDataRange = dataRange.sanitizedForLogScale(); - else - mDataRange = dataRange.sanitizedForLinScale(); - mMapImageInvalidated = true; - emit dataRangeChanged(mDataRange); + mSelectedTickLabelFont = font; + // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts } } /*! - Sets whether the data is correlated with the color gradient linearly or logarithmically. + Sets the font that is used for the axis label when it is selected. - \see QCPColorScale::setDataScaleType + \see setLabelFont, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions */ -void QCPColorMap::setDataScaleType(QCPAxis::ScaleType scaleType) +void QCPPolarAxisRadial::setSelectedLabelFont(const QFont &font) { - if (mDataScaleType != scaleType) - { - mDataScaleType = scaleType; - mMapImageInvalidated = true; - emit dataScaleTypeChanged(mDataScaleType); - if (mDataScaleType == QCPAxis::stLogarithmic) - setDataRange(mDataRange.sanitizedForLogScale()); - } + mSelectedLabelFont = font; + // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts } /*! - Sets the color gradient that is used to represent the data. For more details on how to create an - own gradient or use one of the preset gradients, see \ref QCPColorGradient. - - The colors defined by the gradient will be used to represent data values in the currently set - data range, see \ref setDataRange. Data points that are outside this data range will either be - colored uniformly with the respective gradient boundary color, or the gradient will repeat, - depending on \ref QCPColorGradient::setPeriodic. + Sets the color that is used for tick labels when they are selected. - \see QCPColorScale::setGradient + \see setTickLabelColor, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions */ -void QCPColorMap::setGradient(const QCPColorGradient &gradient) +void QCPPolarAxisRadial::setSelectedTickLabelColor(const QColor &color) { - if (mGradient != gradient) + if (color != mSelectedTickLabelColor) { - mGradient = gradient; - mMapImageInvalidated = true; - emit gradientChanged(mGradient); + mSelectedTickLabelColor = color; } } /*! - Sets whether the color map image shall use bicubic interpolation when displaying the color map - shrinked or expanded, and not at a 1:1 pixel-to-data scale. + Sets the color that is used for the axis label when it is selected. - \image html QCPColorMap-interpolate.png "A 10*10 color map, with interpolation and without interpolation enabled" + \see setLabelColor, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions */ -void QCPColorMap::setInterpolate(bool enabled) +void QCPPolarAxisRadial::setSelectedLabelColor(const QColor &color) { - mInterpolate = enabled; - mMapImageInvalidated = true; // because oversampling factors might need to change + mSelectedLabelColor = color; } /*! - Sets whether the outer most data rows and columns are clipped to the specified key and value - range (see \ref QCPColorMapData::setKeyRange, \ref QCPColorMapData::setValueRange). - - if \a enabled is set to false, the data points at the border of the color map are drawn with the - same width and height as all other data points. Since the data points are represented by - rectangles of one color centered on the data coordinate, this means that the shown color map - extends by half a data point over the specified key/value range in each direction. + Sets the pen that is used to draw the axis base line when selected. - \image html QCPColorMap-tightboundary.png "A color map, with tight boundary enabled and disabled" + \see setBasePen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions */ -void QCPColorMap::setTightBoundary(bool enabled) +void QCPPolarAxisRadial::setSelectedBasePen(const QPen &pen) { - mTightBoundary = enabled; + mSelectedBasePen = pen; } /*! - Associates the color scale \a colorScale with this color map. + Sets the pen that is used to draw the (major) ticks when selected. - This means that both the color scale and the color map synchronize their gradient, data range and - data scale type (\ref setGradient, \ref setDataRange, \ref setDataScaleType). Multiple color maps - can be associated with one single color scale. This causes the color maps to also synchronize - those properties, via the mutual color scale. + \see setTickPen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions +*/ +void QCPPolarAxisRadial::setSelectedTickPen(const QPen &pen) +{ + mSelectedTickPen = pen; +} + +/*! + Sets the pen that is used to draw the subticks when selected. - This function causes the color map to adopt the current color gradient, data range and data scale - type of \a colorScale. After this call, you may change these properties at either the color map - or the color scale, and the setting will be applied to both. + \see setSubTickPen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions +*/ +void QCPPolarAxisRadial::setSelectedSubTickPen(const QPen &pen) +{ + mSelectedSubTickPen = pen; +} + +/*! + If the scale type (\ref setScaleType) is \ref stLinear, \a diff is added to the lower and upper + bounds of the range. The range is simply moved by \a diff. - Pass 0 as \a colorScale to disconnect the color scale from this color map again. + If the scale type is \ref stLogarithmic, the range bounds are multiplied by \a diff. This + corresponds to an apparent "linear" move in logarithmic scaling by a distance of log(diff). */ -void QCPColorMap::setColorScale(QCPColorScale *colorScale) +void QCPPolarAxisRadial::moveRange(double diff) { - if (mColorScale) // unconnect signals from old color scale + QCPRange oldRange = mRange; + if (mScaleType == stLinear) { - disconnect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange))); - disconnect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType))); - disconnect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient))); - disconnect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); - disconnect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient))); - disconnect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); + mRange.lower += diff; + mRange.upper += diff; + } else // mScaleType == stLogarithmic + { + mRange.lower *= diff; + mRange.upper *= diff; } - mColorScale = colorScale; - if (mColorScale) // connect signals to new color scale + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); +} + +/*! + Scales the range of this axis by \a factor around the center of the current axis range. For + example, if \a factor is 2.0, then the axis range will double its size, and the point at the axis + range center won't have changed its position in the QCustomPlot widget (i.e. coordinates around + the center will have moved symmetrically closer). + + If you wish to scale around a different coordinate than the current axis range center, use the + overload \ref scaleRange(double factor, double center). +*/ +void QCPPolarAxisRadial::scaleRange(double factor) +{ + scaleRange(factor, range().center()); +} + +/*! \overload + + Scales the range of this axis by \a factor around the coordinate \a center. For example, if \a + factor is 2.0, \a center is 1.0, then the axis range will double its size, and the point at + coordinate 1.0 won't have changed its position in the QCustomPlot widget (i.e. coordinates + around 1.0 will have moved symmetrically closer to 1.0). + + \see scaleRange(double factor) +*/ +void QCPPolarAxisRadial::scaleRange(double factor, double center) +{ + QCPRange oldRange = mRange; + if (mScaleType == stLinear) { - setGradient(mColorScale.data()->gradient()); - setDataRange(mColorScale.data()->dataRange()); - setDataScaleType(mColorScale.data()->dataScaleType()); - connect(this, SIGNAL(dataRangeChanged(QCPRange)), mColorScale.data(), SLOT(setDataRange(QCPRange))); - connect(this, SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), mColorScale.data(), SLOT(setDataScaleType(QCPAxis::ScaleType))); - connect(this, SIGNAL(gradientChanged(QCPColorGradient)), mColorScale.data(), SLOT(setGradient(QCPColorGradient))); - connect(mColorScale.data(), SIGNAL(dataRangeChanged(QCPRange)), this, SLOT(setDataRange(QCPRange))); - connect(mColorScale.data(), SIGNAL(gradientChanged(QCPColorGradient)), this, SLOT(setGradient(QCPColorGradient))); - connect(mColorScale.data(), SIGNAL(dataScaleTypeChanged(QCPAxis::ScaleType)), this, SLOT(setDataScaleType(QCPAxis::ScaleType))); + QCPRange newRange; + newRange.lower = (mRange.lower-center)*factor + center; + newRange.upper = (mRange.upper-center)*factor + center; + if (QCPRange::validRange(newRange)) + mRange = newRange.sanitizedForLinScale(); + } else // mScaleType == stLogarithmic + { + if ((mRange.upper < 0 && center < 0) || (mRange.upper > 0 && center > 0)) // make sure center has same sign as range + { + QCPRange newRange; + newRange.lower = qPow(mRange.lower/center, factor)*center; + newRange.upper = qPow(mRange.upper/center, factor)*center; + if (QCPRange::validRange(newRange)) + mRange = newRange.sanitizedForLogScale(); + } else + qDebug() << Q_FUNC_INFO << "Center of scaling operation doesn't lie in same logarithmic sign domain as range:" << center; } + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } /*! - Sets the data range (\ref setDataRange) to span the minimum and maximum values that occur in the - current data set. This corresponds to the \ref rescaleKeyAxis or \ref rescaleValueAxis methods, - only for the third data dimension of the color map. - - The minimum and maximum values of the data set are buffered in the internal QCPColorMapData - instance (\ref data). As data is updated via its \ref QCPColorMapData::setCell or \ref - QCPColorMapData::setData, the buffered minimum and maximum values are updated, too. For - performance reasons, however, they are only updated in an expanding fashion. So the buffered - maximum can only increase and the buffered minimum can only decrease. In consequence, changes to - the data that actually lower the maximum of the data set (by overwriting the cell holding the - current maximum with a smaller value), aren't recognized and the buffered maximum overestimates - the true maximum of the data set. The same happens for the buffered minimum. To recalculate the - true minimum and maximum by explicitly looking at each cell, the method - QCPColorMapData::recalculateDataBounds can be used. For convenience, setting the parameter \a - recalculateDataBounds calls this method before setting the data range to the buffered minimum and - maximum. + Changes the axis range such that all plottables associated with this axis are fully visible in + that dimension. - \see setDataRange + \see QCPAbstractPlottable::rescaleAxes, QCustomPlot::rescaleAxes */ -void QCPColorMap::rescaleDataRange(bool recalculateDataBounds) +void QCPPolarAxisRadial::rescale(bool onlyVisiblePlottables) { - if (recalculateDataBounds) - mMapData->recalculateDataBounds(); - setDataRange(mMapData->dataBounds()); + Q_UNUSED(onlyVisiblePlottables) + /* TODO + QList p = plottables(); + QCPRange newRange; + bool haveRange = false; + for (int i=0; irealVisibility() && onlyVisiblePlottables) + continue; + QCPRange plottableRange; + bool currentFoundRange; + QCP::SignDomain signDomain = QCP::sdBoth; + if (mScaleType == stLogarithmic) + signDomain = (mRange.upper < 0 ? QCP::sdNegative : QCP::sdPositive); + if (p.at(i)->keyAxis() == this) + plottableRange = p.at(i)->getKeyRange(currentFoundRange, signDomain); + else + plottableRange = p.at(i)->getValueRange(currentFoundRange, signDomain); + if (currentFoundRange) + { + if (!haveRange) + newRange = plottableRange; + else + newRange.expand(plottableRange); + haveRange = true; + } + } + if (haveRange) + { + if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable + { + double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason + if (mScaleType == stLinear) + { + newRange.lower = center-mRange.size()/2.0; + newRange.upper = center+mRange.size()/2.0; + } else // mScaleType == stLogarithmic + { + newRange.lower = center/qSqrt(mRange.upper/mRange.lower); + newRange.upper = center*qSqrt(mRange.upper/mRange.lower); + } + } + setRange(newRange); + } + */ +} + +/*! + Transforms \a value, in pixel coordinates of the QCustomPlot widget, to axis coordinates. +*/ +void QCPPolarAxisRadial::pixelToCoord(QPointF pixelPos, double &angleCoord, double &radiusCoord) const +{ + QCPVector2D posVector(pixelPos-mCenter); + radiusCoord = radiusToCoord(posVector.length()); + angleCoord = mAngularAxis->angleRadToCoord(posVector.angle()); } /*! - Takes the current appearance of the color map and updates the legend icon, which is used to - represent this color map in the legend (see \ref QCPLegend). - - The \a transformMode specifies whether the rescaling is done by a faster, low quality image - scaling algorithm (Qt::FastTransformation) or by a slower, higher quality algorithm - (Qt::SmoothTransformation). - - The current color map appearance is scaled down to \a thumbSize. Ideally, this should be equal to - the size of the legend icon (see \ref QCPLegend::setIconSize). If it isn't exactly the configured - legend icon size, the thumb will be rescaled during drawing of the legend item. - - \see setDataRange + Transforms \a value, in coordinates of the axis, to pixel coordinates of the QCustomPlot widget. */ -void QCPColorMap::updateLegendIcon(Qt::TransformationMode transformMode, const QSize &thumbSize) +QPointF QCPPolarAxisRadial::coordToPixel(double angleCoord, double radiusCoord) const { - if (mMapImage.isNull() && !data()->isEmpty()) - updateMapImage(); // try to update map image if it's null (happens if no draw has happened yet) - - if (!mMapImage.isNull()) // might still be null, e.g. if data is empty, so check here again + const double radiusPixel = coordToRadius(radiusCoord); + const double angleRad = mAngularAxis->coordToAngleRad(angleCoord); + return QPointF(mCenter.x()+qCos(angleRad)*radiusPixel, mCenter.y()+qSin(angleRad)*radiusPixel); +} + +double QCPPolarAxisRadial::coordToRadius(double coord) const +{ + if (mScaleType == stLinear) { - bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed(); - bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed(); - mLegendIcon = QPixmap::fromImage(mMapImage.mirrored(mirrorX, mirrorY)).scaled(thumbSize, Qt::KeepAspectRatio, transformMode); + if (!mRangeReversed) + return (coord-mRange.lower)/mRange.size()*mRadius; + else + return (mRange.upper-coord)/mRange.size()*mRadius; + } else // mScaleType == stLogarithmic + { + if (coord >= 0.0 && mRange.upper < 0.0) // invalid value for logarithmic scale, just return outside visible range + return !mRangeReversed ? mRadius+200 : mRadius-200; + else if (coord <= 0.0 && mRange.upper >= 0.0) // invalid value for logarithmic scale, just return outside visible range + return !mRangeReversed ? mRadius-200 :mRadius+200; + else + { + if (!mRangeReversed) + return qLn(coord/mRange.lower)/qLn(mRange.upper/mRange.lower)*mRadius; + else + return qLn(mRange.upper/coord)/qLn(mRange.upper/mRange.lower)*mRadius; + } + } +} + +double QCPPolarAxisRadial::radiusToCoord(double radius) const +{ + if (mScaleType == stLinear) + { + if (!mRangeReversed) + return (radius)/mRadius*mRange.size()+mRange.lower; + else + return -(radius)/mRadius*mRange.size()+mRange.upper; + } else // mScaleType == stLogarithmic + { + if (!mRangeReversed) + return qPow(mRange.upper/mRange.lower, (radius)/mRadius)*mRange.lower; + else + return qPow(mRange.upper/mRange.lower, (-radius)/mRadius)*mRange.upper; } } + /*! - Clears the colormap data by calling \ref QCPColorMapData::clear() on the internal data. This also - resizes the map to 0x0 cells. + Returns the part of the axis that is hit by \a pos (in pixels). The return value of this function + is independent of the user-selectable parts defined with \ref setSelectableParts. Further, this + function does not change the current selection state of the axis. + + If the axis is not visible (\ref setVisible), this function always returns \ref spNone. + + \see setSelectedParts, setSelectableParts, QCustomPlot::setInteractions */ -void QCPColorMap::clearData() +QCPPolarAxisRadial::SelectablePart QCPPolarAxisRadial::getPartAt(const QPointF &pos) const { - mMapData->clear(); + Q_UNUSED(pos) // TODO remove later + if (!mVisible) + return spNone; + + /* + TODO: + if (mAxisPainter->axisSelectionBox().contains(pos.toPoint())) + return spAxis; + else if (mAxisPainter->tickLabelsSelectionBox().contains(pos.toPoint())) + return spTickLabels; + else if (mAxisPainter->labelSelectionBox().contains(pos.toPoint())) + return spAxisLabel; + else */ + return spNone; } /* inherits documentation from base class */ -double QCPColorMap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +double QCPPolarAxisRadial::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) + if (!mParentPlot) return -1; + SelectablePart part = getPartAt(pos); + if ((onlySelectable && !mSelectableParts.testFlag(part)) || part == spNone) return -1; - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } - if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) + if (details) + details->setValue(part); + return mParentPlot->selectionTolerance()*0.99; +} + +/* inherits documentation from base class */ +void QCPPolarAxisRadial::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) +{ + Q_UNUSED(event) + SelectablePart part = details.value(); + if (mSelectableParts.testFlag(part)) { - double posKey, posValue; - pixelsToCoords(pos, posKey, posValue); - if (mMapData->keyRange().contains(posKey) && mMapData->valueRange().contains(posValue)) - return mParentPlot->selectionTolerance()*0.99; + SelectableParts selBefore = mSelectedParts; + setSelectedParts(additive ? mSelectedParts^part : part); + if (selectionStateChanged) + *selectionStateChanged = mSelectedParts != selBefore; } - return -1; +} + +/* inherits documentation from base class */ +void QCPPolarAxisRadial::deselectEvent(bool *selectionStateChanged) +{ + SelectableParts selBefore = mSelectedParts; + setSelectedParts(mSelectedParts & ~mSelectableParts); + if (selectionStateChanged) + *selectionStateChanged = mSelectedParts != selBefore; } /*! \internal - Updates the internal map image buffer by going through the internal \ref QCPColorMapData and - turning the data values into color pixels with \ref QCPColorGradient::colorize. + This mouse event reimplementation provides the functionality to let the user drag individual axes + exclusively, by startig the drag on top of the axis. + + For the axis to accept this event and perform the single axis drag, the parent \ref QCPAxisRect + must be configured accordingly, i.e. it must allow range dragging in the orientation of this axis + (\ref QCPAxisRect::setRangeDrag) and this axis must be a draggable axis (\ref + QCPAxisRect::setRangeDragAxes) - This method is called by \ref QCPColorMap::draw if either the data has been modified or the map image - has been invalidated for a different reason (e.g. a change of the data range with \ref - setDataRange). + \seebaseclassmethod - If the map cell count is low, the image created will be oversampled in order to avoid a - QPainter::drawImage bug which makes inner pixel boundaries jitter when stretch-drawing images - without smooth transform enabled. Accordingly, oversampling isn't performed if \ref - setInterpolate is true. + \note The dragging of possibly multiple axes at once by starting the drag anywhere in the axis + rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::mousePressEvent. */ -void QCPColorMap::updateMapImage() +void QCPPolarAxisRadial::mousePressEvent(QMouseEvent *event, const QVariant &details) { - QCPAxis *keyAxis = mKeyAxis.data(); - if (!keyAxis) return; - if (mMapData->isEmpty()) return; - - const int keySize = mMapData->keySize(); - const int valueSize = mMapData->valueSize(); - int keyOversamplingFactor = mInterpolate ? 1 : (int)(1.0+100.0/(double)keySize); // make mMapImage have at least size 100, factor becomes 1 if size > 200 or interpolation is on - int valueOversamplingFactor = mInterpolate ? 1 : (int)(1.0+100.0/(double)valueSize); // make mMapImage have at least size 100, factor becomes 1 if size > 200 or interpolation is on - - // resize mMapImage to correct dimensions including possible oversampling factors, according to key/value axes orientation: - if (keyAxis->orientation() == Qt::Horizontal && (mMapImage.width() != keySize*keyOversamplingFactor || mMapImage.height() != valueSize*valueOversamplingFactor)) - mMapImage = QImage(QSize(keySize*keyOversamplingFactor, valueSize*valueOversamplingFactor), QImage::Format_RGB32); - else if (keyAxis->orientation() == Qt::Vertical && (mMapImage.width() != valueSize*valueOversamplingFactor || mMapImage.height() != keySize*keyOversamplingFactor)) - mMapImage = QImage(QSize(valueSize*valueOversamplingFactor, keySize*keyOversamplingFactor), QImage::Format_RGB32); - - QImage *localMapImage = &mMapImage; // this is the image on which the colorization operates. Either the final mMapImage, or if we need oversampling, mUndersampledMapImage - if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1) + Q_UNUSED(details) + if (!mParentPlot->interactions().testFlag(QCP::iRangeDrag)) { - // resize undersampled map image to actual key/value cell sizes: - if (keyAxis->orientation() == Qt::Horizontal && (mUndersampledMapImage.width() != keySize || mUndersampledMapImage.height() != valueSize)) - mUndersampledMapImage = QImage(QSize(keySize, valueSize), QImage::Format_RGB32); - else if (keyAxis->orientation() == Qt::Vertical && (mUndersampledMapImage.width() != valueSize || mUndersampledMapImage.height() != keySize)) - mUndersampledMapImage = QImage(QSize(valueSize, keySize), QImage::Format_RGB32); - localMapImage = &mUndersampledMapImage; // make the colorization run on the undersampled image - } else if (!mUndersampledMapImage.isNull()) - mUndersampledMapImage = QImage(); // don't need oversampling mechanism anymore (map size has changed) but mUndersampledMapImage still has nonzero size, free it + event->ignore(); + return; + } - const double *rawData = mMapData->mData; - if (keyAxis->orientation() == Qt::Horizontal) + if (event->buttons() & Qt::LeftButton) { - const int lineCount = valueSize; - const int rowCount = keySize; - for (int line=0; linenoAntialiasingOnDrag()) { - QRgb* pixels = reinterpret_cast(localMapImage->scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system) - mGradient.colorize(rawData+line*rowCount, mDataRange, pixels, rowCount, 1, mDataScaleType==QCPAxis::stLogarithmic); + mAADragBackup = mParentPlot->antialiasedElements(); + mNotAADragBackup = mParentPlot->notAntialiasedElements(); } - } else // keyAxis->orientation() == Qt::Vertical + // Mouse range dragging interaction: + if (mParentPlot->interactions().testFlag(QCP::iRangeDrag)) + mDragStartRange = mRange; + } +} + +/*! \internal + + This mouse event reimplementation provides the functionality to let the user drag individual axes + exclusively, by startig the drag on top of the axis. + + \seebaseclassmethod + + \note The dragging of possibly multiple axes at once by starting the drag anywhere in the axis + rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::mousePressEvent. + + \see QCPAxis::mousePressEvent +*/ +void QCPPolarAxisRadial::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) +{ + Q_UNUSED(event) // TODO remove later + Q_UNUSED(startPos) // TODO remove later + if (mDragging) { - const int lineCount = keySize; - const int rowCount = valueSize; - for (int line=0; linepos().x() : event->pos().y(); + if (mScaleType == QCPPolarAxisRadial::stLinear) + { + const double diff = pixelToCoord(startPixel) - pixelToCoord(currentPixel); + setRange(mDragStartRange.lower+diff, mDragStartRange.upper+diff); + } else if (mScaleType == QCPPolarAxisRadial::stLogarithmic) { - QRgb* pixels = reinterpret_cast(localMapImage->scanLine(lineCount-1-line)); // invert scanline index because QImage counts scanlines from top, but our vertical index counts from bottom (mathematical coordinate system) - mGradient.colorize(rawData+line, mDataRange, pixels, rowCount, lineCount, mDataScaleType==QCPAxis::stLogarithmic); + const double diff = pixelToCoord(startPixel) / pixelToCoord(currentPixel); + setRange(mDragStartRange.lower*diff, mDragStartRange.upper*diff); } + */ + + if (mParentPlot->noAntialiasingOnDrag()) + mParentPlot->setNotAntialiasedElements(QCP::aeAll); + mParentPlot->replot(QCustomPlot::rpQueuedReplot); } +} + +/*! \internal - if (keyOversamplingFactor > 1 || valueOversamplingFactor > 1) + This mouse event reimplementation provides the functionality to let the user drag individual axes + exclusively, by startig the drag on top of the axis. + + \seebaseclassmethod + + \note The dragging of possibly multiple axes at once by starting the drag anywhere in the axis + rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::mousePressEvent. + + \see QCPAxis::mousePressEvent +*/ +void QCPPolarAxisRadial::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) +{ + Q_UNUSED(event) + Q_UNUSED(startPos) + mDragging = false; + if (mParentPlot->noAntialiasingOnDrag()) { - if (keyAxis->orientation() == Qt::Horizontal) - mMapImage = mUndersampledMapImage.scaled(keySize*keyOversamplingFactor, valueSize*valueOversamplingFactor, Qt::IgnoreAspectRatio, Qt::FastTransformation); - else - mMapImage = mUndersampledMapImage.scaled(valueSize*valueOversamplingFactor, keySize*keyOversamplingFactor, Qt::IgnoreAspectRatio, Qt::FastTransformation); + mParentPlot->setAntialiasedElements(mAADragBackup); + mParentPlot->setNotAntialiasedElements(mNotAADragBackup); } - mMapData->mDataModified = false; - mMapImageInvalidated = false; } -/* inherits documentation from base class */ -void QCPColorMap::draw(QCPPainter *painter) -{ - if (mMapData->isEmpty()) return; - if (!mKeyAxis || !mValueAxis) return; - applyDefaultAntialiasingHint(painter); +/*! \internal - if (mMapData->mDataModified || mMapImageInvalidated) - updateMapImage(); + This mouse event reimplementation provides the functionality to let the user zoom individual axes + exclusively, by performing the wheel event on top of the axis. + + For the axis to accept this event and perform the single axis zoom, the parent \ref QCPAxisRect + must be configured accordingly, i.e. it must allow range zooming in the orientation of this axis + (\ref QCPAxisRect::setRangeZoom) and this axis must be a zoomable axis (\ref + QCPAxisRect::setRangeZoomAxes) - // use buffer if painting vectorized (PDF): - bool useBuffer = painter->modes().testFlag(QCPPainter::pmVectorized); - QCPPainter *localPainter = painter; // will be redirected to paint on mapBuffer if painting vectorized - QRectF mapBufferTarget; // the rect in absolute widget coordinates where the visible map portion/buffer will end up in - QPixmap mapBuffer; - double mapBufferPixelRatio = 3; // factor by which DPI is increased in embedded bitmaps - if (useBuffer) - { - mapBufferTarget = painter->clipRegion().boundingRect(); - mapBuffer = QPixmap((mapBufferTarget.size()*mapBufferPixelRatio).toSize()); - mapBuffer.fill(Qt::transparent); - localPainter = new QCPPainter(&mapBuffer); - localPainter->scale(mapBufferPixelRatio, mapBufferPixelRatio); - localPainter->translate(-mapBufferTarget.topLeft()); - } + \seebaseclassmethod - QRectF imageRect = QRectF(coordsToPixels(mMapData->keyRange().lower, mMapData->valueRange().lower), - coordsToPixels(mMapData->keyRange().upper, mMapData->valueRange().upper)).normalized(); - // extend imageRect to contain outer halves/quarters of bordering/cornering pixels (cells are centered on map range boundary): - double halfCellWidth = 0; // in pixels - double halfCellHeight = 0; // in pixels - if (keyAxis()->orientation() == Qt::Horizontal) - { - if (mMapData->keySize() > 1) - halfCellWidth = 0.5*imageRect.width()/(double)(mMapData->keySize()-1); - if (mMapData->valueSize() > 1) - halfCellHeight = 0.5*imageRect.height()/(double)(mMapData->valueSize()-1); - } else // keyAxis orientation is Qt::Vertical - { - if (mMapData->keySize() > 1) - halfCellHeight = 0.5*imageRect.height()/(double)(mMapData->keySize()-1); - if (mMapData->valueSize() > 1) - halfCellWidth = 0.5*imageRect.width()/(double)(mMapData->valueSize()-1); - } - imageRect.adjust(-halfCellWidth, -halfCellHeight, halfCellWidth, halfCellHeight); - bool mirrorX = (keyAxis()->orientation() == Qt::Horizontal ? keyAxis() : valueAxis())->rangeReversed(); - bool mirrorY = (valueAxis()->orientation() == Qt::Vertical ? valueAxis() : keyAxis())->rangeReversed(); - bool smoothBackup = localPainter->renderHints().testFlag(QPainter::SmoothPixmapTransform); - localPainter->setRenderHint(QPainter::SmoothPixmapTransform, mInterpolate); - QRegion clipBackup; - if (mTightBoundary) + \note The zooming of possibly multiple axes at once by performing the wheel event anywhere in the + axis rect is handled by the axis rect's mouse event, e.g. \ref QCPAxisRect::wheelEvent. +*/ +void QCPPolarAxisRadial::wheelEvent(QWheelEvent *event) +{ + // Mouse range zooming interaction: + if (!mParentPlot->interactions().testFlag(QCP::iRangeZoom)) { - clipBackup = localPainter->clipRegion(); - QRectF tightClipRect = QRectF(coordsToPixels(mMapData->keyRange().lower, mMapData->valueRange().lower), - coordsToPixels(mMapData->keyRange().upper, mMapData->valueRange().upper)).normalized(); - localPainter->setClipRect(tightClipRect, Qt::IntersectClip); + event->ignore(); + return; } - localPainter->drawImage(imageRect, mMapImage.mirrored(mirrorX, mirrorY)); - if (mTightBoundary) - localPainter->setClipRegion(clipBackup); - localPainter->setRenderHint(QPainter::SmoothPixmapTransform, smoothBackup); - if (useBuffer) // localPainter painted to mapBuffer, so now draw buffer with original painter - { - delete localPainter; - painter->drawPixmap(mapBufferTarget.toRect(), mapBuffer); - } + // TODO: + //const double wheelSteps = event->delta()/120.0; // a single step delta is +/-120 usually + //const double factor = qPow(mRangeZoomFactor, wheelSteps); + //scaleRange(factor, pixelToCoord(orientation() == Qt::Horizontal ? event->pos().x() : event->pos().y())); + mParentPlot->replot(); } -/* inherits documentation from base class */ -void QCPColorMap::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const +void QCPPolarAxisRadial::updateGeometry(const QPointF ¢er, double radius) { - applyDefaultAntialiasingHint(painter); - // draw map thumbnail: - if (!mLegendIcon.isNull()) - { - QPixmap scaledIcon = mLegendIcon.scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::FastTransformation); - QRectF iconRect = QRectF(0, 0, scaledIcon.width(), scaledIcon.height()); - iconRect.moveCenter(rect.center()); - painter->drawPixmap(iconRect.topLeft(), scaledIcon); - } - /* - // draw frame: - painter->setBrush(Qt::NoBrush); - painter->setPen(Qt::black); - painter->drawRect(rect.adjusted(1, 1, 0, 0)); - */ + mCenter = center; + mRadius = radius; + if (mRadius < 1) mRadius = 1; +} + +/*! \internal + + A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter + before drawing axis lines. + + This is the antialiasing state the painter passed to the \ref draw method is in by default. + + This function takes into account the local setting of the antialiasing flag as well as the + overrides set with \ref QCustomPlot::setAntialiasedElements and \ref + QCustomPlot::setNotAntialiasedElements. + + \seebaseclassmethod + + \see setAntialiased +*/ +void QCPPolarAxisRadial::applyDefaultAntialiasingHint(QCPPainter *painter) const +{ + applyAntialiasingHint(painter, mAntialiased, QCP::aeAxes); } -/* inherits documentation from base class */ -QCPRange QCPColorMap::getKeyRange(bool &foundRange, SignDomain inSignDomain) const +/*! \internal + + Draws the axis with the specified \a painter, using the internal QCPAxisPainterPrivate instance. + + \seebaseclassmethod +*/ +void QCPPolarAxisRadial::draw(QCPPainter *painter) { - foundRange = true; - QCPRange result = mMapData->keyRange(); - result.normalize(); - if (inSignDomain == QCPAbstractPlottable::sdPositive) + const double axisAngleRad = (mAngle+(mAngleReference==arAngularAxis ? mAngularAxis->angle() : 0))/180.0*M_PI; + const QPointF axisVector(qCos(axisAngleRad), qSin(axisAngleRad)); // semantically should be QCPVector2D, but we save time in loops when we keep it as QPointF + const QPointF tickNormal = QCPVector2D(axisVector).perpendicular().toPointF(); // semantically should be QCPVector2D, but we save time in loops when we keep it as QPointF + + // draw baseline: + painter->setPen(getBasePen()); + painter->drawLine(QLineF(mCenter, mCenter+axisVector*(mRadius-0.5))); + + // draw subticks: + if (!mSubTickVector.isEmpty()) { - if (result.lower <= 0 && result.upper > 0) - result.lower = result.upper*1e-3; - else if (result.lower <= 0 && result.upper <= 0) - foundRange = false; - } else if (inSignDomain == QCPAbstractPlottable::sdNegative) + painter->setPen(getSubTickPen()); + for (int i=0; idrawLine(QLineF(tickPosition-tickNormal*mSubTickLengthIn, tickPosition+tickNormal*mSubTickLengthOut)); + } + } + + // draw ticks and labels: + if (!mTickVector.isEmpty()) { - if (result.upper >= 0 && result.lower < 0) - result.upper = result.lower*1e-3; - else if (result.upper >= 0 && result.lower >= 0) - foundRange = false; + mLabelPainter.setAnchorReference(mCenter-axisVector); // subtract (normalized) axisVector, just to prevent degenerate tangents for tick label at exact lower axis range + mLabelPainter.setFont(getTickLabelFont()); + mLabelPainter.setColor(getTickLabelColor()); + const QPen ticksPen = getTickPen(); + painter->setPen(ticksPen); + for (int i=0; idrawLine(QLineF(tickPosition-tickNormal*mTickLengthIn, tickPosition+tickNormal*mTickLengthOut)); + // possibly draw tick labels: + if (!mTickVectorLabels.isEmpty()) + { + if ((!mRangeReversed && (i < mTickVectorLabels.count()-1 || mRadius-r > 10)) || + (mRangeReversed && (i > 0 || mRadius-r > 10))) // skip last label if it's closer than 10 pixels to angular axis + mLabelPainter.drawTickLabel(painter, tickPosition+tickNormal*mSubTickLengthOut, mTickVectorLabels.at(i)); + } + } } - return result; } -/* inherits documentation from base class */ -QCPRange QCPColorMap::getValueRange(bool &foundRange, SignDomain inSignDomain) const +/*! \internal + + Prepares the internal tick vector, sub tick vector and tick label vector. This is done by calling + QCPAxisTicker::generate on the currently installed ticker. + + If a change in the label text/count is detected, the cached axis margin is invalidated to make + sure the next margin calculation recalculates the label sizes and returns an up-to-date value. +*/ +void QCPPolarAxisRadial::setupTickVectors() { - foundRange = true; - QCPRange result = mMapData->valueRange(); - result.normalize(); - if (inSignDomain == QCPAbstractPlottable::sdPositive) - { - if (result.lower <= 0 && result.upper > 0) - result.lower = result.upper*1e-3; - else if (result.lower <= 0 && result.upper <= 0) - foundRange = false; - } else if (inSignDomain == QCPAbstractPlottable::sdNegative) - { - if (result.upper >= 0 && result.lower < 0) - result.upper = result.lower*1e-3; - else if (result.upper >= 0 && result.lower >= 0) - foundRange = false; - } - return result; + if (!mParentPlot) return; + if ((!mTicks && !mTickLabels) || mRange.size() <= 0) return; + + mTicker->generate(mRange, mParentPlot->locale(), mNumberFormatChar, mNumberPrecision, mTickVector, mSubTicks ? &mSubTickVector : 0, mTickLabels ? &mTickVectorLabels : 0); } +/*! \internal + + Returns the pen that is used to draw the axis base line. Depending on the selection state, this + is either mSelectedBasePen or mBasePen. +*/ +QPen QCPPolarAxisRadial::getBasePen() const +{ + return mSelectedParts.testFlag(spAxis) ? mSelectedBasePen : mBasePen; +} -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPFinancialData -//////////////////////////////////////////////////////////////////////////////////////////////////// +/*! \internal + + Returns the pen that is used to draw the (major) ticks. Depending on the selection state, this + is either mSelectedTickPen or mTickPen. +*/ +QPen QCPPolarAxisRadial::getTickPen() const +{ + return mSelectedParts.testFlag(spAxis) ? mSelectedTickPen : mTickPen; +} -/*! \class QCPFinancialData - \brief Holds the data of one single data point for QCPFinancial. +/*! \internal - The container for storing multiple data points is \ref QCPFinancialDataMap. + Returns the pen that is used to draw the subticks. Depending on the selection state, this + is either mSelectedSubTickPen or mSubTickPen. +*/ +QPen QCPPolarAxisRadial::getSubTickPen() const +{ + return mSelectedParts.testFlag(spAxis) ? mSelectedSubTickPen : mSubTickPen; +} + +/*! \internal - The stored data is: - \li \a key: coordinate on the key axis of this data point - \li \a open: The opening value at the data point - \li \a high: The high/maximum value at the data point - \li \a low: The low/minimum value at the data point - \li \a close: The closing value at the data point + Returns the font that is used to draw the tick labels. Depending on the selection state, this + is either mSelectedTickLabelFont or mTickLabelFont. +*/ +QFont QCPPolarAxisRadial::getTickLabelFont() const +{ + return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelFont : mTickLabelFont; +} + +/*! \internal - \see QCPFinancialDataMap + Returns the font that is used to draw the axis label. Depending on the selection state, this + is either mSelectedLabelFont or mLabelFont. */ +QFont QCPPolarAxisRadial::getLabelFont() const +{ + return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelFont : mLabelFont; +} -/*! - Constructs a data point with key and all values set to zero. +/*! \internal + + Returns the color that is used to draw the tick labels. Depending on the selection state, this + is either mSelectedTickLabelColor or mTickLabelColor. */ -QCPFinancialData::QCPFinancialData() : - key(0), - open(0), - high(0), - low(0), - close(0) +QColor QCPPolarAxisRadial::getTickLabelColor() const { + return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelColor : mTickLabelColor; } -/*! - Constructs a data point with the specified \a key and OHLC values. +/*! \internal + + Returns the color that is used to draw the axis label. Depending on the selection state, this + is either mSelectedLabelColor or mLabelColor. */ -QCPFinancialData::QCPFinancialData(double key, double open, double high, double low, double close) : - key(key), - open(open), - high(high), - low(low), - close(close) +QColor QCPPolarAxisRadial::getLabelColor() const +{ + return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelColor : mLabelColor; +} + + +/* inherits documentation from base class */ +QCP::Interaction QCPPolarAxisRadial::selectionCategory() const { + return QCP::iSelectAxes; } +/* end of 'src/polar/radialaxis.cpp' */ + + +/* including file 'src/polar/layoutelement-angularaxis.cpp' */ +/* modified 2022-11-06T12:45:57, size 57266 */ //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPFinancial +//////////////////// QCPPolarAxisAngular //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPFinancial - \brief A plottable representing a financial stock chart +/*! \class QCPPolarAxisAngular + \brief The main container for polar plots, representing the angular axis as a circle - \image html QCPFinancial.png + \warning In this QCustomPlot version, polar plots are a tech preview. Expect documentation and + functionality to be incomplete, as well as changing public interfaces in the future. +*/ + +/* start documentation of inline functions */ + +/*! \fn QCPLayoutInset *QCPPolarAxisAngular::insetLayout() const - This plottable represents time series data binned to certain intervals, mainly used for stock - charts. The two common representations OHLC (Open-High-Low-Close) bars and Candlesticks can be - set via \ref setChartStyle. + Returns the inset layout of this axis rect. It can be used to place other layout elements (or + even layouts with multiple other elements) inside/on top of an axis rect. - The data is passed via \ref setData as a set of open/high/low/close values at certain keys - (typically times). This means the data must be already binned appropriately. If data is only - available as a series of values (e.g. \a price against \a time), you can use the static - convenience function \ref timeSeriesToOhlc to generate binned OHLC-data which can then be passed - to \ref setData. + \see QCPLayoutInset +*/ + +/*! \fn int QCPPolarAxisAngular::left() const + + Returns the pixel position of the left border of this axis rect. Margins are not taken into + account here, so the returned value is with respect to the inner \ref rect. +*/ + +/*! \fn int QCPPolarAxisAngular::right() const + + Returns the pixel position of the right border of this axis rect. Margins are not taken into + account here, so the returned value is with respect to the inner \ref rect. +*/ + +/*! \fn int QCPPolarAxisAngular::top() const - The width of the OHLC bars/candlesticks can be controlled with \ref setWidth and is given in plot - key coordinates. A typical choice is to set it to (or slightly less than) one bin interval width. + Returns the pixel position of the top border of this axis rect. Margins are not taken into + account here, so the returned value is with respect to the inner \ref rect. +*/ + +/*! \fn int QCPPolarAxisAngular::bottom() const - \section appearance Changing the appearance + Returns the pixel position of the bottom border of this axis rect. Margins are not taken into + account here, so the returned value is with respect to the inner \ref rect. +*/ + +/*! \fn int QCPPolarAxisAngular::width() const - Charts can be either single- or two-colored (\ref setTwoColored). If set to be single-colored, - lines are drawn with the plottable's pen (\ref setPen) and fills with the brush (\ref setBrush). + Returns the pixel width of this axis rect. Margins are not taken into account here, so the + returned value is with respect to the inner \ref rect. +*/ + +/*! \fn int QCPPolarAxisAngular::height() const + + Returns the pixel height of this axis rect. Margins are not taken into account here, so the + returned value is with respect to the inner \ref rect. +*/ + +/*! \fn QSize QCPPolarAxisAngular::size() const + + Returns the pixel size of this axis rect. Margins are not taken into account here, so the + returned value is with respect to the inner \ref rect. +*/ + +/*! \fn QPoint QCPPolarAxisAngular::topLeft() const + + Returns the top left corner of this axis rect in pixels. Margins are not taken into account here, + so the returned value is with respect to the inner \ref rect. +*/ + +/*! \fn QPoint QCPPolarAxisAngular::topRight() const + + Returns the top right corner of this axis rect in pixels. Margins are not taken into account + here, so the returned value is with respect to the inner \ref rect. +*/ + +/*! \fn QPoint QCPPolarAxisAngular::bottomLeft() const + + Returns the bottom left corner of this axis rect in pixels. Margins are not taken into account + here, so the returned value is with respect to the inner \ref rect. +*/ + +/*! \fn QPoint QCPPolarAxisAngular::bottomRight() const + + Returns the bottom right corner of this axis rect in pixels. Margins are not taken into account + here, so the returned value is with respect to the inner \ref rect. +*/ + +/*! \fn QPoint QCPPolarAxisAngular::center() const + + Returns the center of this axis rect in pixels. Margins are not taken into account here, so the + returned value is with respect to the inner \ref rect. +*/ + +/* end documentation of inline functions */ + +/*! + Creates a QCPPolarAxis instance and sets default values. An axis is added for each of the four + sides, the top and right axes are set invisible initially. +*/ +QCPPolarAxisAngular::QCPPolarAxisAngular(QCustomPlot *parentPlot) : + QCPLayoutElement(parentPlot), + mBackgroundBrush(Qt::NoBrush), + mBackgroundScaled(true), + mBackgroundScaledMode(Qt::KeepAspectRatioByExpanding), + mInsetLayout(new QCPLayoutInset), + mRangeDrag(false), + mRangeZoom(false), + mRangeZoomFactor(0.85), + // axis base: + mAngle(-90), + mAngleRad(mAngle/180.0*M_PI), + mSelectableParts(spAxis | spTickLabels | spAxisLabel), + mSelectedParts(spNone), + mBasePen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + mSelectedBasePen(QPen(Qt::blue, 2)), + // axis label: + mLabelPadding(0), + mLabel(), + mLabelFont(mParentPlot->font()), + mSelectedLabelFont(QFont(mLabelFont.family(), mLabelFont.pointSize(), QFont::Bold)), + mLabelColor(Qt::black), + mSelectedLabelColor(Qt::blue), + // tick labels: + //mTickLabelPadding(0), in label painter + mTickLabels(true), + //mTickLabelRotation(0), in label painter + mTickLabelFont(mParentPlot->font()), + mSelectedTickLabelFont(QFont(mTickLabelFont.family(), mTickLabelFont.pointSize(), QFont::Bold)), + mTickLabelColor(Qt::black), + mSelectedTickLabelColor(Qt::blue), + mNumberPrecision(6), + mNumberFormatChar('g'), + mNumberBeautifulPowers(true), + mNumberMultiplyCross(false), + // ticks and subticks: + mTicks(true), + mSubTicks(true), + mTickLengthIn(5), + mTickLengthOut(0), + mSubTickLengthIn(2), + mSubTickLengthOut(0), + mTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + mSelectedTickPen(QPen(Qt::blue, 2)), + mSubTickPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)), + mSelectedSubTickPen(QPen(Qt::blue, 2)), + // scale and range: + mRange(0, 360), + mRangeReversed(false), + // internal members: + mRadius(1), // non-zero initial value, will be overwritten in ::update() according to inner rect + mGrid(new QCPPolarGrid(this)), + mTicker(new QCPAxisTickerFixed), + mDragging(false), + mLabelPainter(parentPlot) +{ + // TODO: + //mInsetLayout->initializeParentPlot(mParentPlot); + //mInsetLayout->setParentLayerable(this); + //mInsetLayout->setParent(this); + + if (QCPAxisTickerFixed *fixedTicker = mTicker.dynamicCast().data()) + { + fixedTicker->setTickStep(30); + } + setAntialiased(true); + setLayer(mParentPlot->currentLayer()); // it's actually on that layer already, but we want it in front of the grid, so we place it on there again + + setTickLabelPadding(5); + setTickLabelRotation(0); + setTickLabelMode(lmUpright); + mLabelPainter.setAnchorReferenceType(QCPLabelPainterPrivate::artNormal); + mLabelPainter.setAbbreviateDecimalPowers(false); + mLabelPainter.setCacheSize(24); // so we can cache up to 15-degree intervals, polar angular axis uses a bit larger cache than normal axes - If set to two-colored, positive changes of the value during an interval (\a close >= \a open) are - represented with a different pen and brush than negative changes (\a close < \a open). These can - be configured with \ref setPenPositive, \ref setPenNegative, \ref setBrushPositive, and \ref - setBrushNegative. In two-colored mode, the normal plottable pen/brush is ignored. Upon selection - however, the normal selected pen/brush (\ref setSelectedPen, \ref setSelectedBrush) is used, - irrespective of whether the chart is single- or two-colored. + setMinimumSize(50, 50); + setMinimumMargins(QMargins(30, 30, 30, 30)); -*/ - -/* start of documentation of inline functions */ + addRadialAxis(); + mGrid->setRadialAxis(radialAxis()); +} -/*! \fn QCPFinancialDataMap *QCPFinancial::data() const +QCPPolarAxisAngular::~QCPPolarAxisAngular() +{ + delete mGrid; // delete grid here instead of via parent ~QObject for better defined deletion order + mGrid = 0; - Returns a pointer to the internal data storage of type \ref QCPFinancialDataMap. You may use it to - directly manipulate the data, which may be more convenient and faster than using the regular \ref - setData or \ref addData methods, in certain situations. -*/ + delete mInsetLayout; + mInsetLayout = 0; + + QList radialAxesList = radialAxes(); + for (int i=0; i= 0 && index < mRadialAxes.size()) + { + return mRadialAxes.at(index); + } else + { + qDebug() << Q_FUNC_INFO << "Axis index out of bounds:" << index; + return 0; + } } /*! - Replaces the current data with the provided \a data. - - If \a copy is set to true, data points in \a data will only be copied. if false, the plottable - takes ownership of the passed data and replaces the internal data pointer with it. This is - significantly faster than copying for large datasets. + Returns all axes on the axis rect sides specified with \a types. - Alternatively, you can also access and modify the plottable's data via the \ref data method, which - returns a pointer to the internal \ref QCPFinancialDataMap. + \a types may be a single \ref QCPAxis::AxisType or an or-combination, to get the axes of + multiple sides. - \see timeSeriesToOhlc + \see axis */ -void QCPFinancial::setData(QCPFinancialDataMap *data, bool copy) +QList QCPPolarAxisAngular::radialAxes() const { - if (mData == data) - { - qDebug() << Q_FUNC_INFO << "The data pointer is already in (and owned by) this plottable" << reinterpret_cast(data); - return; - } - if (copy) + return mRadialAxes; +} + + +/*! + Adds a new axis to the axis rect side specified with \a type, and returns it. If \a axis is 0, a + new QCPAxis instance is created internally. QCustomPlot owns the returned axis, so if you want to + remove an axis, use \ref removeAxis instead of deleting it manually. + + You may inject QCPAxis instances (or subclasses of QCPAxis) by setting \a axis to an axis that was + previously created outside QCustomPlot. It is important to note that QCustomPlot takes ownership + of the axis, so you may not delete it afterwards. Further, the \a axis must have been created + with this axis rect as parent and with the same axis type as specified in \a type. If this is not + the case, a debug output is generated, the axis is not added, and the method returns 0. + + This method can not be used to move \a axis between axis rects. The same \a axis instance must + not be added multiple times to the same or different axis rects. + + If an axis rect side already contains one or more axes, the lower and upper endings of the new + axis (\ref QCPAxis::setLowerEnding, \ref QCPAxis::setUpperEnding) are set to \ref + QCPLineEnding::esHalfBar. + + \see addAxes, setupFullAxesBox +*/ +QCPPolarAxisRadial *QCPPolarAxisAngular::addRadialAxis(QCPPolarAxisRadial *axis) +{ + QCPPolarAxisRadial *newAxis = axis; + if (!newAxis) { - *mData = *data; - } else + newAxis = new QCPPolarAxisRadial(this); + } else // user provided existing axis instance, do some sanity checks { - delete mData; - mData = data; + if (newAxis->angularAxis() != this) + { + qDebug() << Q_FUNC_INFO << "passed radial axis doesn't have this angular axis as parent angular axis"; + return 0; + } + if (radialAxes().contains(newAxis)) + { + qDebug() << Q_FUNC_INFO << "passed axis is already owned by this angular axis"; + return 0; + } } + mRadialAxes.append(newAxis); + return newAxis; } -/*! \overload +/*! + Removes the specified \a axis from the axis rect and deletes it. - Replaces the current data with the provided open/high/low/close data. The provided vectors should - have equal length. Else, the number of added points will be the size of the smallest vector. + Returns true on success, i.e. if \a axis was a valid axis in this axis rect. - \see timeSeriesToOhlc + \see addAxis */ -void QCPFinancial::setData(const QVector &key, const QVector &open, const QVector &high, const QVector &low, const QVector &close) +bool QCPPolarAxisAngular::removeRadialAxis(QCPPolarAxisRadial *radialAxis) { - mData->clear(); - int n = key.size(); - n = qMin(n, open.size()); - n = qMin(n, high.size()); - n = qMin(n, low.size()); - n = qMin(n, close.size()); - for (int i=0; iinsertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i])); + qDebug() << Q_FUNC_INFO << "Radial axis isn't associated with this angular axis:" << reinterpret_cast(radialAxis); + return false; } } -/*! - Sets which representation style shall be used to display the OHLC data. -*/ -void QCPFinancial::setChartStyle(QCPFinancial::ChartStyle style) +QRegion QCPPolarAxisAngular::exactClipRegion() const { - mChartStyle = style; + return QRegion(mCenter.x()-mRadius, mCenter.y()-mRadius, qRound(2*mRadius), qRound(2*mRadius), QRegion::Ellipse); } /*! - Sets the width of the individual bars/candlesticks to \a width in plot key coordinates. + If the scale type (\ref setScaleType) is \ref stLinear, \a diff is added to the lower and upper + bounds of the range. The range is simply moved by \a diff. - A typical choice is to set it to (or slightly less than) one bin interval width. + If the scale type is \ref stLogarithmic, the range bounds are multiplied by \a diff. This + corresponds to an apparent "linear" move in logarithmic scaling by a distance of log(diff). */ -void QCPFinancial::setWidth(double width) +void QCPPolarAxisAngular::moveRange(double diff) { - mWidth = width; + QCPRange oldRange = mRange; + mRange.lower += diff; + mRange.upper += diff; + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } /*! - Sets whether this chart shall contrast positive from negative trends per data point by using two - separate colors to draw the respective bars/candlesticks. - - If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref - setBrush). - - \see setPenPositive, setPenNegative, setBrushPositive, setBrushNegative + Scales the range of this axis by \a factor around the center of the current axis range. For + example, if \a factor is 2.0, then the axis range will double its size, and the point at the axis + range center won't have changed its position in the QCustomPlot widget (i.e. coordinates around + the center will have moved symmetrically closer). + + If you wish to scale around a different coordinate than the current axis range center, use the + overload \ref scaleRange(double factor, double center). */ -void QCPFinancial::setTwoColored(bool twoColored) +void QCPPolarAxisAngular::scaleRange(double factor) { - mTwoColored = twoColored; + scaleRange(factor, range().center()); +} + +/*! \overload + + Scales the range of this axis by \a factor around the coordinate \a center. For example, if \a + factor is 2.0, \a center is 1.0, then the axis range will double its size, and the point at + coordinate 1.0 won't have changed its position in the QCustomPlot widget (i.e. coordinates + around 1.0 will have moved symmetrically closer to 1.0). + + \see scaleRange(double factor) +*/ +void QCPPolarAxisAngular::scaleRange(double factor, double center) +{ + QCPRange oldRange = mRange; + QCPRange newRange; + newRange.lower = (mRange.lower-center)*factor + center; + newRange.upper = (mRange.upper-center)*factor + center; + if (QCPRange::validRange(newRange)) + mRange = newRange.sanitizedForLinScale(); + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } /*! - If \ref setTwoColored is set to true, this function controls the brush that is used to draw fills - of data points with a positive trend (i.e. bars/candlesticks with close >= open). - - If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref - setBrush). + Changes the axis range such that all plottables associated with this axis are fully visible in + that dimension. - \see setBrushNegative, setPenPositive, setPenNegative + \see QCPAbstractPlottable::rescaleAxes, QCustomPlot::rescaleAxes */ -void QCPFinancial::setBrushPositive(const QBrush &brush) +void QCPPolarAxisAngular::rescale(bool onlyVisiblePlottables) { - mBrushPositive = brush; + QCPRange newRange; + bool haveRange = false; + for (int i=0; irealVisibility() && onlyVisiblePlottables) + continue; + QCPRange range; + bool currentFoundRange; + if (mGraphs.at(i)->keyAxis() == this) + range = mGraphs.at(i)->getKeyRange(currentFoundRange, QCP::sdBoth); + else + range = mGraphs.at(i)->getValueRange(currentFoundRange, QCP::sdBoth); + if (currentFoundRange) + { + if (!haveRange) + newRange = range; + else + newRange.expand(range); + haveRange = true; + } + } + if (haveRange) + { + if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable + { + double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason + newRange.lower = center-mRange.size()/2.0; + newRange.upper = center+mRange.size()/2.0; + } + setRange(newRange); + } } /*! - If \ref setTwoColored is set to true, this function controls the brush that is used to draw fills - of data points with a negative trend (i.e. bars/candlesticks with close < open). - - If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref - setBrush). - - \see setBrushPositive, setPenNegative, setPenPositive + Transforms \a value, in pixel coordinates of the QCustomPlot widget, to axis coordinates. */ -void QCPFinancial::setBrushNegative(const QBrush &brush) +void QCPPolarAxisAngular::pixelToCoord(QPointF pixelPos, double &angleCoord, double &radiusCoord) const { - mBrushNegative = brush; + if (!mRadialAxes.isEmpty()) + mRadialAxes.first()->pixelToCoord(pixelPos, angleCoord, radiusCoord); + else + qDebug() << Q_FUNC_INFO << "no radial axis configured"; } /*! - If \ref setTwoColored is set to true, this function controls the pen that is used to draw - outlines of data points with a positive trend (i.e. bars/candlesticks with close >= open). - - If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref - setBrush). - - \see setPenNegative, setBrushPositive, setBrushNegative + Transforms \a value, in coordinates of the axis, to pixel coordinates of the QCustomPlot widget. */ -void QCPFinancial::setPenPositive(const QPen &pen) +QPointF QCPPolarAxisAngular::coordToPixel(double angleCoord, double radiusCoord) const { - mPenPositive = pen; + if (!mRadialAxes.isEmpty()) + { + return mRadialAxes.first()->coordToPixel(angleCoord, radiusCoord); + } else + { + qDebug() << Q_FUNC_INFO << "no radial axis configured"; + return QPointF(); + } } /*! - If \ref setTwoColored is set to true, this function controls the pen that is used to draw - outlines of data points with a negative trend (i.e. bars/candlesticks with close < open). + Returns the part of the axis that is hit by \a pos (in pixels). The return value of this function + is independent of the user-selectable parts defined with \ref setSelectableParts. Further, this + function does not change the current selection state of the axis. - If \a twoColored is false, the normal plottable's pen and brush are used (\ref setPen, \ref - setBrush). + If the axis is not visible (\ref setVisible), this function always returns \ref spNone. - \see setPenPositive, setBrushNegative, setBrushPositive + \see setSelectedParts, setSelectableParts, QCustomPlot::setInteractions */ -void QCPFinancial::setPenNegative(const QPen &pen) +QCPPolarAxisAngular::SelectablePart QCPPolarAxisAngular::getPartAt(const QPointF &pos) const { - mPenNegative = pen; + Q_UNUSED(pos) // TODO remove later + + if (!mVisible) + return spNone; + + /* + TODO: + if (mAxisPainter->axisSelectionBox().contains(pos.toPoint())) + return spAxis; + else if (mAxisPainter->tickLabelsSelectionBox().contains(pos.toPoint())) + return spTickLabels; + else if (mAxisPainter->labelSelectionBox().contains(pos.toPoint())) + return spAxisLabel; + else */ + return spNone; +} + +/* inherits documentation from base class */ +double QCPPolarAxisAngular::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +{ + /* + if (!mParentPlot) return -1; + SelectablePart part = getPartAt(pos); + if ((onlySelectable && !mSelectableParts.testFlag(part)) || part == spNone) + return -1; + + if (details) + details->setValue(part); + return mParentPlot->selectionTolerance()*0.99; + */ + + Q_UNUSED(details) + + if (onlySelectable) + return -1; + + if (QRectF(mOuterRect).contains(pos)) + { + if (mParentPlot) + return mParentPlot->selectionTolerance()*0.99; + else + { + qDebug() << Q_FUNC_INFO << "parent plot not defined"; + return -1; + } + } else + return -1; } /*! - Adds the provided data points in \a dataMap to the current data. + This method is called automatically upon replot and doesn't need to be called by users of + QCPPolarAxisAngular. - Alternatively, you can also access and modify the data via the \ref data method, which returns a - pointer to the internal \ref QCPFinancialDataMap. + Calls the base class implementation to update the margins (see \ref QCPLayoutElement::update), + and finally passes the \ref rect to the inset layout (\ref insetLayout) and calls its + QCPInsetLayout::update function. - \see removeData + \seebaseclassmethod */ -void QCPFinancial::addData(const QCPFinancialDataMap &dataMap) +void QCPPolarAxisAngular::update(UpdatePhase phase) { - mData->unite(dataMap); -} - -/*! \overload - - Adds the provided single data point in \a data to the current data. + QCPLayoutElement::update(phase); - Alternatively, you can also access and modify the data via the \ref data method, which returns a - pointer to the internal \ref QCPFinancialData. + switch (phase) + { + case upPreparation: + { + setupTickVectors(); + for (int i=0; isetupTickVectors(); + break; + } + case upLayout: + { + mCenter = mRect.center(); + mRadius = 0.5*qMin(qAbs(mRect.width()), qAbs(mRect.height())); + if (mRadius < 1) mRadius = 1; // prevent cases where radius might become 0 which causes trouble + for (int i=0; iupdateGeometry(mCenter, mRadius); + + mInsetLayout->setOuterRect(rect()); + break; + } + default: break; + } - \see removeData -*/ -void QCPFinancial::addData(const QCPFinancialData &data) + // pass update call on to inset layout (doesn't happen automatically, because QCPPolarAxis doesn't derive from QCPLayout): + mInsetLayout->update(phase); +} + +/* inherits documentation from base class */ +QList QCPPolarAxisAngular::elements(bool recursive) const { - mData->insertMulti(data.key, data); + QList result; + if (mInsetLayout) + { + result << mInsetLayout; + if (recursive) + result << mInsetLayout->elements(recursive); + } + return result; } -/*! \overload - - Adds the provided single data point given by \a key, \a open, \a high, \a low, and \a close to - the current data. - - Alternatively, you can also access and modify the data via the \ref data method, which returns a - pointer to the internal \ref QCPFinancialData. +bool QCPPolarAxisAngular::removeGraph(QCPPolarGraph *graph) +{ + if (!mGraphs.contains(graph)) + { + qDebug() << Q_FUNC_INFO << "graph not in list:" << reinterpret_cast(graph); + return false; + } - \see removeData -*/ -void QCPFinancial::addData(double key, double open, double high, double low, double close) + // remove plottable from legend: + graph->removeFromLegend(); + // remove plottable: + delete graph; + mGraphs.removeOne(graph); + return true; +} + +/* inherits documentation from base class */ +void QCPPolarAxisAngular::applyDefaultAntialiasingHint(QCPPainter *painter) const { - mData->insertMulti(key, QCPFinancialData(key, open, high, low, close)); + applyAntialiasingHint(painter, mAntialiased, QCP::aeAxes); } -/*! \overload +/* inherits documentation from base class */ +void QCPPolarAxisAngular::draw(QCPPainter *painter) +{ + drawBackground(painter, mCenter, mRadius); - Adds the provided open/high/low/close data to the current data. + // draw baseline circle: + painter->setPen(getBasePen()); + painter->drawEllipse(mCenter, mRadius, mRadius); - Alternatively, you can also access and modify the data via the \ref data method, which returns a - pointer to the internal \ref QCPFinancialData. + // draw subticks: + if (!mSubTickVector.isEmpty()) + { + painter->setPen(getSubTickPen()); + for (int i=0; idrawLine(mCenter+mSubTickVectorCosSin.at(i)*(mRadius-mSubTickLengthIn), + mCenter+mSubTickVectorCosSin.at(i)*(mRadius+mSubTickLengthOut)); + } + } - \see removeData -*/ -void QCPFinancial::addData(const QVector &key, const QVector &open, const QVector &high, const QVector &low, const QVector &close) -{ - int n = key.size(); - n = qMin(n, open.size()); - n = qMin(n, high.size()); - n = qMin(n, low.size()); - n = qMin(n, close.size()); - for (int i=0; iinsertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i])); + mLabelPainter.setAnchorReference(mCenter); + mLabelPainter.setFont(getTickLabelFont()); + mLabelPainter.setColor(getTickLabelColor()); + const QPen ticksPen = getTickPen(); + painter->setPen(ticksPen); + for (int i=0; idrawLine(mCenter+mTickVectorCosSin.at(i)*(mRadius-mTickLengthIn), outerTick); + // draw tick labels: + if (!mTickVectorLabels.isEmpty()) + { + if (i < mTickVectorLabels.count()-1 || (mTickVectorCosSin.at(i)-mTickVectorCosSin.first()).manhattanLength() > 5/180.0*M_PI) // skip last label if it's closer than approx 5 degrees to first + mLabelPainter.drawTickLabel(painter, outerTick, mTickVectorLabels.at(i)); + } + } } } -/*! - Removes all data points with keys smaller than \a key. - - \see addData, clearData -*/ -void QCPFinancial::removeDataBefore(double key) +/* inherits documentation from base class */ +QCP::Interaction QCPPolarAxisAngular::selectionCategory() const { - QCPFinancialDataMap::iterator it = mData->begin(); - while (it != mData->end() && it.key() < key) - it = mData->erase(it); + return QCP::iSelectAxes; } -/*! - Removes all data points with keys greater than \a key. - - \see addData, clearData -*/ -void QCPFinancial::removeDataAfter(double key) -{ - if (mData->isEmpty()) return; - QCPFinancialDataMap::iterator it = mData->upperBound(key); - while (it != mData->end()) - it = mData->erase(it); -} /*! - Removes all data points with keys between \a fromKey and \a toKey. if \a fromKey is greater or - equal to \a toKey, the function does nothing. To remove a single data point with known key, use - \ref removeData(double key). + Sets \a pm as the axis background pixmap. The axis background pixmap will be drawn inside the + axis rect. Since axis rects place themselves on the "background" layer by default, the axis rect + backgrounds are usually drawn below everything else. + + For cases where the provided pixmap doesn't have the same size as the axis rect, scaling can be + enabled with \ref setBackgroundScaled and the scaling mode (i.e. whether and how the aspect ratio + is preserved) can be set with \ref setBackgroundScaledMode. To set all these options in one call, + consider using the overloaded version of this function. + + Below the pixmap, the axis rect may be optionally filled with a brush, if specified with \ref + setBackground(const QBrush &brush). - \see addData, clearData + \see setBackgroundScaled, setBackgroundScaledMode, setBackground(const QBrush &brush) */ -void QCPFinancial::removeData(double fromKey, double toKey) +void QCPPolarAxisAngular::setBackground(const QPixmap &pm) { - if (fromKey >= toKey || mData->isEmpty()) return; - QCPFinancialDataMap::iterator it = mData->upperBound(fromKey); - QCPFinancialDataMap::iterator itEnd = mData->upperBound(toKey); - while (it != itEnd) - it = mData->erase(it); + mBackgroundPixmap = pm; + mScaledBackgroundPixmap = QPixmap(); } /*! \overload - Removes a single data point at \a key. If the position is not known with absolute precision, - consider using \ref removeData(double fromKey, double toKey) with a small fuzziness interval - around the suspected position, depeding on the precision with which the key is known. + Sets \a brush as the background brush. The axis rect background will be filled with this brush. + Since axis rects place themselves on the "background" layer by default, the axis rect backgrounds + are usually drawn below everything else. - \see addData, clearData -*/ -void QCPFinancial::removeData(double key) -{ - mData->remove(key); -} + The brush will be drawn before (under) any background pixmap, which may be specified with \ref + setBackground(const QPixmap &pm). -/*! - Removes all data points. + To disable drawing of a background brush, set \a brush to Qt::NoBrush. - \see removeData, removeDataAfter, removeDataBefore + \see setBackground(const QPixmap &pm) */ -void QCPFinancial::clearData() +void QCPPolarAxisAngular::setBackground(const QBrush &brush) { - mData->clear(); + mBackgroundBrush = brush; } -/* inherits documentation from base class */ -double QCPFinancial::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const -{ - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } +/*! \overload - if (mKeyAxis.data()->axisRect()->rect().contains(pos.toPoint())) - { - // get visible data range: - QCPFinancialDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point - getVisibleDataBounds(lower, upper); - if (lower == mData->constEnd() || upper == mData->constEnd()) - return -1; - // perform select test according to configured style: - switch (mChartStyle) - { - case QCPFinancial::csOhlc: - return ohlcSelectTest(pos, lower, upper+1); break; - case QCPFinancial::csCandlestick: - return candlestickSelectTest(pos, lower, upper+1); break; - } - } - return -1; + Allows setting the background pixmap of the axis rect, whether it shall be scaled and how it + shall be scaled in one call. + + \see setBackground(const QPixmap &pm), setBackgroundScaled, setBackgroundScaledMode +*/ +void QCPPolarAxisAngular::setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode) +{ + mBackgroundPixmap = pm; + mScaledBackgroundPixmap = QPixmap(); + mBackgroundScaled = scaled; + mBackgroundScaledMode = mode; } /*! - A convenience function that converts time series data (\a value against \a time) to OHLC binned - data points. The return value can then be passed on to \ref setData. + Sets whether the axis background pixmap shall be scaled to fit the axis rect or not. If \a scaled + is set to true, you may control whether and how the aspect ratio of the original pixmap is + preserved with \ref setBackgroundScaledMode. - The size of the bins can be controlled with \a timeBinSize in the same units as \a time is given. - For example, if the unit of \a time is seconds and single OHLC/Candlesticks should span an hour - each, set \a timeBinSize to 3600. + Note that the scaled version of the original pixmap is buffered, so there is no performance + penalty on replots. (Except when the axis rect dimensions are changed continuously.) - \a timeBinOffset allows to control precisely at what \a time coordinate a bin should start. The - value passed as \a timeBinOffset doesn't need to be in the range encompassed by the \a time keys. - It merely defines the mathematical offset/phase of the bins that will be used to process the - data. + \see setBackground, setBackgroundScaledMode */ -QCPFinancialDataMap QCPFinancial::timeSeriesToOhlc(const QVector &time, const QVector &value, double timeBinSize, double timeBinOffset) -{ - QCPFinancialDataMap map; - int count = qMin(time.size(), value.size()); - if (count == 0) - return QCPFinancialDataMap(); - - QCPFinancialData currentBinData(0, value.first(), value.first(), value.first(), value.first()); - int currentBinIndex = qFloor((time.first()-timeBinOffset)/timeBinSize+0.5); - for (int i=0; i currentBinData.high) currentBinData.high = value.at(i); - if (i == count-1) // last data point is in current bin, finalize bin: - { - currentBinData.close = value.at(i); - currentBinData.key = timeBinOffset+(index)*timeBinSize; - map.insert(currentBinData.key, currentBinData); - } - } else // data point not anymore in current bin, set close of old and open of new bin, and add old to map: - { - // finalize current bin: - currentBinData.close = value.at(i-1); - currentBinData.key = timeBinOffset+(index-1)*timeBinSize; - map.insert(currentBinData.key, currentBinData); - // start next bin: - currentBinIndex = index; - currentBinData.open = value.at(i); - currentBinData.high = value.at(i); - currentBinData.low = value.at(i); - } - } - - return map; -} - -/* inherits documentation from base class */ -void QCPFinancial::draw(QCPPainter *painter) +void QCPPolarAxisAngular::setBackgroundScaled(bool scaled) { - // get visible data range: - QCPFinancialDataMap::const_iterator lower, upper; // note that upper is the actual upper point, and not 1 step after the upper point - getVisibleDataBounds(lower, upper); - if (lower == mData->constEnd() || upper == mData->constEnd()) - return; - - // draw visible data range according to configured style: - switch (mChartStyle) - { - case QCPFinancial::csOhlc: - drawOhlcPlot(painter, lower, upper+1); break; - case QCPFinancial::csCandlestick: - drawCandlestickPlot(painter, lower, upper+1); break; - } + mBackgroundScaled = scaled; } -/* inherits documentation from base class */ -void QCPFinancial::drawLegendIcon(QCPPainter *painter, const QRectF &rect) const -{ - painter->setAntialiasing(false); // legend icon especially of csCandlestick looks better without antialiasing - if (mChartStyle == csOhlc) - { - if (mTwoColored) - { - // draw upper left half icon with positive color: - painter->setBrush(mBrushPositive); - painter->setPen(mPenPositive); - painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint())); - painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft())); - // draw bottom right hald icon with negative color: - painter->setBrush(mBrushNegative); - painter->setPen(mPenNegative); - painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint())); - painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft())); - } else - { - painter->setBrush(mBrush); - painter->setPen(mPen); - painter->drawLine(QLineF(0, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.2, rect.height()*0.3, rect.width()*0.2, rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.8, rect.height()*0.5, rect.width()*0.8, rect.height()*0.7).translated(rect.topLeft())); - } - } else if (mChartStyle == csCandlestick) - { - if (mTwoColored) - { - // draw upper left half icon with positive color: - painter->setBrush(mBrushPositive); - painter->setPen(mPenPositive); - painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.topLeft().toPoint())); - painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); - painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft())); - // draw bottom right hald icon with negative color: - painter->setBrush(mBrushNegative); - painter->setPen(mPenNegative); - painter->setClipRegion(QRegion(QPolygon() << rect.bottomLeft().toPoint() << rect.topRight().toPoint() << rect.bottomRight().toPoint())); - painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); - painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft())); - } else - { - painter->setBrush(mBrush); - painter->setPen(mPen); - painter->drawLine(QLineF(0, rect.height()*0.5, rect.width()*0.25, rect.height()*0.5).translated(rect.topLeft())); - painter->drawLine(QLineF(rect.width()*0.75, rect.height()*0.5, rect.width(), rect.height()*0.5).translated(rect.topLeft())); - painter->drawRect(QRectF(rect.width()*0.25, rect.height()*0.25, rect.width()*0.5, rect.height()*0.5).translated(rect.topLeft())); - } - } +/*! + If scaling of the axis background pixmap is enabled (\ref setBackgroundScaled), use this function to + define whether and how the aspect ratio of the original pixmap passed to \ref setBackground is preserved. + \see setBackground, setBackgroundScaled +*/ +void QCPPolarAxisAngular::setBackgroundScaledMode(Qt::AspectRatioMode mode) +{ + mBackgroundScaledMode = mode; } -/* inherits documentation from base class */ -QCPRange QCPFinancial::getKeyRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain) const +void QCPPolarAxisAngular::setRangeDrag(bool enabled) { - QCPRange range; - bool haveLower = false; - bool haveUpper = false; - - double current; - QCPFinancialDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - current = it.value().key; - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && current < 0) || (inSignDomain == sdPositive && current > 0)) - { - if (current < range.lower || !haveLower) - { - range.lower = current; - haveLower = true; - } - if (current > range.upper || !haveUpper) - { - range.upper = current; - haveUpper = true; - } - } - ++it; - } - // determine exact range by including width of bars/flags: - if (haveLower && mKeyAxis) - range.lower = range.lower-mWidth*0.5; - if (haveUpper && mKeyAxis) - range.upper = range.upper+mWidth*0.5; - foundRange = haveLower && haveUpper; - return range; + mRangeDrag = enabled; } -/* inherits documentation from base class */ -QCPRange QCPFinancial::getValueRange(bool &foundRange, QCPAbstractPlottable::SignDomain inSignDomain) const +void QCPPolarAxisAngular::setRangeZoom(bool enabled) { - QCPRange range; - bool haveLower = false; - bool haveUpper = false; + mRangeZoom = enabled; +} + +void QCPPolarAxisAngular::setRangeZoomFactor(double factor) +{ + mRangeZoomFactor = factor; +} + + + + + + + +/*! + Sets the range of the axis. - QCPFinancialDataMap::const_iterator it = mData->constBegin(); - while (it != mData->constEnd()) - { - // high: - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && it.value().high < 0) || (inSignDomain == sdPositive && it.value().high > 0)) - { - if (it.value().high < range.lower || !haveLower) - { - range.lower = it.value().high; - haveLower = true; - } - if (it.value().high > range.upper || !haveUpper) - { - range.upper = it.value().high; - haveUpper = true; - } - } - // low: - if (inSignDomain == sdBoth || (inSignDomain == sdNegative && it.value().low < 0) || (inSignDomain == sdPositive && it.value().low > 0)) - { - if (it.value().low < range.lower || !haveLower) - { - range.lower = it.value().low; - haveLower = true; - } - if (it.value().low > range.upper || !haveUpper) - { - range.upper = it.value().low; - haveUpper = true; - } - } - ++it; - } + This slot may be connected with the \ref rangeChanged signal of another axis so this axis + is always synchronized with the other axis range, when it changes. - foundRange = haveLower && haveUpper; - return range; + To invert the direction of an axis, use \ref setRangeReversed. +*/ +void QCPPolarAxisAngular::setRange(const QCPRange &range) +{ + if (range.lower == mRange.lower && range.upper == mRange.upper) + return; + + if (!QCPRange::validRange(range)) return; + QCPRange oldRange = mRange; + mRange = range.sanitizedForLinScale(); + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } -/*! \internal +/*! + Sets whether the user can (de-)select the parts in \a selectable by clicking on the QCustomPlot surface. + (When \ref QCustomPlot::setInteractions contains iSelectAxes.) - Draws the data from \a begin to \a end as OHLC bars with the provided \a painter. - - This method is a helper function for \ref draw. It is used when the chart style is \ref csOhlc. + However, even when \a selectable is set to a value not allowing the selection of a specific part, + it is still possible to set the selection of this part manually, by calling \ref setSelectedParts + directly. + + \see SelectablePart, setSelectedParts */ -void QCPFinancial::drawOhlcPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) +void QCPPolarAxisAngular::setSelectableParts(const SelectableParts &selectable) { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + if (mSelectableParts != selectable) + { + mSelectableParts = selectable; + emit selectableChanged(mSelectableParts); + } +} + +/*! + Sets the selected state of the respective axis parts described by \ref SelectablePart. When a part + is selected, it uses a different pen/font. - QPen linePen; + The entire selection mechanism for axes is handled automatically when \ref + QCustomPlot::setInteractions contains iSelectAxes. You only need to call this function when you + wish to change the selection state manually. - if (keyAxis->orientation() == Qt::Horizontal) - { - for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it) - { - if (mSelected) - linePen = mSelectedPen; - else if (mTwoColored) - linePen = it.value().close >= it.value().open ? mPenPositive : mPenNegative; - else - linePen = mPen; - painter->setPen(linePen); - double keyPixel = keyAxis->coordToPixel(it.value().key); - double openPixel = valueAxis->coordToPixel(it.value().open); - double closePixel = valueAxis->coordToPixel(it.value().close); - // draw backbone: - painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(it.value().low))); - // draw open: - double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); // sign of this makes sure open/close are on correct sides - painter->drawLine(QPointF(keyPixel-keyWidthPixels, openPixel), QPointF(keyPixel, openPixel)); - // draw close: - painter->drawLine(QPointF(keyPixel, closePixel), QPointF(keyPixel+keyWidthPixels, closePixel)); - } - } else + This function can change the selection state of a part, independent of the \ref setSelectableParts setting. + + emits the \ref selectionChanged signal when \a selected is different from the previous selection state. + + \see SelectablePart, setSelectableParts, selectTest, setSelectedBasePen, setSelectedTickPen, setSelectedSubTickPen, + setSelectedTickLabelFont, setSelectedLabelFont, setSelectedTickLabelColor, setSelectedLabelColor +*/ +void QCPPolarAxisAngular::setSelectedParts(const SelectableParts &selected) +{ + if (mSelectedParts != selected) { - for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it) - { - if (mSelected) - linePen = mSelectedPen; - else if (mTwoColored) - linePen = it.value().close >= it.value().open ? mPenPositive : mPenNegative; - else - linePen = mPen; - painter->setPen(linePen); - double keyPixel = keyAxis->coordToPixel(it.value().key); - double openPixel = valueAxis->coordToPixel(it.value().open); - double closePixel = valueAxis->coordToPixel(it.value().close); - // draw backbone: - painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(it.value().low), keyPixel)); - // draw open: - double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); // sign of this makes sure open/close are on correct sides - painter->drawLine(QPointF(openPixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel)); - // draw close: - painter->drawLine(QPointF(closePixel, keyPixel), QPointF(closePixel, keyPixel+keyWidthPixels)); - } + mSelectedParts = selected; + emit selectionChanged(mSelectedParts); } } -/*! \internal +/*! + \overload - Draws the data from \a begin to \a end as Candlesticks with the provided \a painter. - - This method is a helper function for \ref draw. It is used when the chart style is \ref csCandlestick. + Sets the lower and upper bound of the axis range. + + To invert the direction of an axis, use \ref setRangeReversed. + + There is also a slot to set a range, see \ref setRange(const QCPRange &range). */ -void QCPFinancial::drawCandlestickPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) +void QCPPolarAxisAngular::setRange(double lower, double upper) { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - - QPen linePen; - QBrush boxBrush; + if (lower == mRange.lower && upper == mRange.upper) + return; - if (keyAxis->orientation() == Qt::Horizontal) - { - for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it) - { - if (mSelected) - { - linePen = mSelectedPen; - boxBrush = mSelectedBrush; - } else if (mTwoColored) - { - if (it.value().close >= it.value().open) - { - linePen = mPenPositive; - boxBrush = mBrushPositive; - } else - { - linePen = mPenNegative; - boxBrush = mBrushNegative; - } - } else - { - linePen = mPen; - boxBrush = mBrush; - } - painter->setPen(linePen); - painter->setBrush(boxBrush); - double keyPixel = keyAxis->coordToPixel(it.value().key); - double openPixel = valueAxis->coordToPixel(it.value().open); - double closePixel = valueAxis->coordToPixel(it.value().close); - // draw high: - painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it.value().open, it.value().close)))); - // draw low: - painter->drawLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it.value().open, it.value().close)))); - // draw open-close box: - double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); - painter->drawRect(QRectF(QPointF(keyPixel-keyWidthPixels, closePixel), QPointF(keyPixel+keyWidthPixels, openPixel))); - } - } else // keyAxis->orientation() == Qt::Vertical - { - for (QCPFinancialDataMap::const_iterator it = begin; it != end; ++it) - { - if (mSelected) - { - linePen = mSelectedPen; - boxBrush = mSelectedBrush; - } else if (mTwoColored) - { - if (it.value().close >= it.value().open) - { - linePen = mPenPositive; - boxBrush = mBrushPositive; - } else - { - linePen = mPenNegative; - boxBrush = mBrushNegative; - } - } else - { - linePen = mPen; - boxBrush = mBrush; - } - painter->setPen(linePen); - painter->setBrush(boxBrush); - double keyPixel = keyAxis->coordToPixel(it.value().key); - double openPixel = valueAxis->coordToPixel(it.value().open); - double closePixel = valueAxis->coordToPixel(it.value().close); - // draw high: - painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it.value().open, it.value().close)), keyPixel)); - // draw low: - painter->drawLine(QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it.value().open, it.value().close)), keyPixel)); - // draw open-close box: - double keyWidthPixels = keyPixel-keyAxis->coordToPixel(it.value().key-mWidth*0.5); - painter->drawRect(QRectF(QPointF(closePixel, keyPixel-keyWidthPixels), QPointF(openPixel, keyPixel+keyWidthPixels))); - } - } + if (!QCPRange::validRange(lower, upper)) return; + QCPRange oldRange = mRange; + mRange.lower = lower; + mRange.upper = upper; + mRange = mRange.sanitizedForLinScale(); + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } -/*! \internal +/*! + \overload - This method is a helper function for \ref selectTest. It is used to test for selection when the - chart style is \ref csOhlc. It only tests against the data points between \a begin and \a end. + Sets the range of the axis. + + The \a position coordinate indicates together with the \a alignment parameter, where the new + range will be positioned. \a size defines the size of the new axis range. \a alignment may be + Qt::AlignLeft, Qt::AlignRight or Qt::AlignCenter. This will cause the left border, right border, + or center of the range to be aligned with \a position. Any other values of \a alignment will + default to Qt::AlignCenter. */ -double QCPFinancial::ohlcSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const +void QCPPolarAxisAngular::setRange(double position, double size, Qt::AlignmentFlag alignment) { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } + if (alignment == Qt::AlignLeft) + setRange(position, position+size); + else if (alignment == Qt::AlignRight) + setRange(position-size, position); + else // alignment == Qt::AlignCenter + setRange(position-size/2.0, position+size/2.0); +} - double minDistSqr = std::numeric_limits::max(); - QCPFinancialDataMap::const_iterator it; - if (keyAxis->orientation() == Qt::Horizontal) - { - for (it = begin; it != end; ++it) - { - double keyPixel = keyAxis->coordToPixel(it.value().key); - // calculate distance to backbone: - double currentDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), pos); - if (currentDistSqr < minDistSqr) - minDistSqr = currentDistSqr; - } - } else // keyAxis->orientation() == Qt::Vertical - { - for (it = begin; it != end; ++it) - { - double keyPixel = keyAxis->coordToPixel(it.value().key); - // calculate distance to backbone: - double currentDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), pos); - if (currentDistSqr < minDistSqr) - minDistSqr = currentDistSqr; - } - } - return qSqrt(minDistSqr); +/*! + Sets the lower bound of the axis range. The upper bound is not changed. + \see setRange +*/ +void QCPPolarAxisAngular::setRangeLower(double lower) +{ + if (mRange.lower == lower) + return; + + QCPRange oldRange = mRange; + mRange.lower = lower; + mRange = mRange.sanitizedForLinScale(); + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); +} + +/*! + Sets the upper bound of the axis range. The lower bound is not changed. + \see setRange +*/ +void QCPPolarAxisAngular::setRangeUpper(double upper) +{ + if (mRange.upper == upper) + return; + + QCPRange oldRange = mRange; + mRange.upper = upper; + mRange = mRange.sanitizedForLinScale(); + emit rangeChanged(mRange); + emit rangeChanged(mRange, oldRange); } -/*! \internal - - This method is a helper function for \ref selectTest. It is used to test for selection when the - chart style is \ref csCandlestick. It only tests against the data points between \a begin and \a - end. +/*! + Sets whether the axis range (direction) is displayed reversed. Normally, the values on horizontal + axes increase left to right, on vertical axes bottom to top. When \a reversed is set to true, the + direction of increasing values is inverted. + + Note that the range and data interface stays the same for reversed axes, e.g. the \a lower part + of the \ref setRange interface will still reference the mathematically smaller number than the \a + upper part. */ -double QCPFinancial::candlestickSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const +void QCPPolarAxisAngular::setRangeReversed(bool reversed) { - QCPAxis *keyAxis = mKeyAxis.data(); - QCPAxis *valueAxis = mValueAxis.data(); - if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return -1; } + mRangeReversed = reversed; +} - double minDistSqr = std::numeric_limits::max(); - QCPFinancialDataMap::const_iterator it; - if (keyAxis->orientation() == Qt::Horizontal) - { - for (it = begin; it != end; ++it) - { - double currentDistSqr; - // determine whether pos is in open-close-box: - QCPRange boxKeyRange(it.value().key-mWidth*0.5, it.value().key+mWidth*0.5); - QCPRange boxValueRange(it.value().close, it.value().open); - double posKey, posValue; - pixelsToCoords(pos, posKey, posValue); - if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box - { - currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99; - } else - { - // calculate distance to high/low lines: - double keyPixel = keyAxis->coordToPixel(it.value().key); - double highLineDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().high)), QPointF(keyPixel, valueAxis->coordToPixel(qMax(it.value().open, it.value().close))), pos); - double lowLineDistSqr = distSqrToLine(QPointF(keyPixel, valueAxis->coordToPixel(it.value().low)), QPointF(keyPixel, valueAxis->coordToPixel(qMin(it.value().open, it.value().close))), pos); - currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr); - } - if (currentDistSqr < minDistSqr) - minDistSqr = currentDistSqr; - } - } else // keyAxis->orientation() == Qt::Vertical - { - for (it = begin; it != end; ++it) - { - double currentDistSqr; - // determine whether pos is in open-close-box: - QCPRange boxKeyRange(it.value().key-mWidth*0.5, it.value().key+mWidth*0.5); - QCPRange boxValueRange(it.value().close, it.value().open); - double posKey, posValue; - pixelsToCoords(pos, posKey, posValue); - if (boxKeyRange.contains(posKey) && boxValueRange.contains(posValue)) // is in open-close-box - { - currentDistSqr = mParentPlot->selectionTolerance()*0.99 * mParentPlot->selectionTolerance()*0.99; - } else - { - // calculate distance to high/low lines: - double keyPixel = keyAxis->coordToPixel(it.value().key); - double highLineDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().high), keyPixel), QPointF(valueAxis->coordToPixel(qMax(it.value().open, it.value().close)), keyPixel), pos); - double lowLineDistSqr = distSqrToLine(QPointF(valueAxis->coordToPixel(it.value().low), keyPixel), QPointF(valueAxis->coordToPixel(qMin(it.value().open, it.value().close)), keyPixel), pos); - currentDistSqr = qMin(highLineDistSqr, lowLineDistSqr); - } - if (currentDistSqr < minDistSqr) - minDistSqr = currentDistSqr; - } - } - return qSqrt(minDistSqr); +void QCPPolarAxisAngular::setAngle(double degrees) +{ + mAngle = degrees; + mAngleRad = mAngle/180.0*M_PI; } -/*! \internal - - called by the drawing methods to determine which data (key) range is visible at the current key - axis range setting, so only that needs to be processed. - - \a lower returns an iterator to the lowest data point that needs to be taken into account when - plotting. Note that in order to get a clean plot all the way to the edge of the axis rect, \a - lower may still be just outside the visible range. +/*! + The axis ticker is responsible for generating the tick positions and tick labels. See the + documentation of QCPAxisTicker for details on how to work with axis tickers. - \a upper returns an iterator to the highest data point. Same as before, \a upper may also lie - just outside of the visible range. + You can change the tick positioning/labeling behaviour of this axis by setting a different + QCPAxisTicker subclass using this method. If you only wish to modify the currently installed axis + ticker, access it via \ref ticker. - if the plottable contains no data, both \a lower and \a upper point to constEnd. + Since the ticker is stored in the axis as a shared pointer, multiple axes may share the same axis + ticker simply by passing the same shared pointer to multiple axes. - \see QCPGraph::getVisibleDataBounds + \see ticker */ -void QCPFinancial::getVisibleDataBounds(QCPFinancialDataMap::const_iterator &lower, QCPFinancialDataMap::const_iterator &upper) const +void QCPPolarAxisAngular::setTicker(QSharedPointer ticker) { - if (!mKeyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } - if (mData->isEmpty()) - { - lower = mData->constEnd(); - upper = mData->constEnd(); - return; - } - - // get visible data range as QMap iterators - QCPFinancialDataMap::const_iterator lbound = mData->lowerBound(mKeyAxis.data()->range().lower); - QCPFinancialDataMap::const_iterator ubound = mData->upperBound(mKeyAxis.data()->range().upper); - bool lowoutlier = lbound != mData->constBegin(); // indicates whether there exist points below axis range - bool highoutlier = ubound != mData->constEnd(); // indicates whether there exist points above axis range - - lower = (lowoutlier ? lbound-1 : lbound); // data point range that will be actually drawn - upper = (highoutlier ? ubound : ubound-1); // data point range that will be actually drawn + if (ticker) + mTicker = ticker; + else + qDebug() << Q_FUNC_INFO << "can not set 0 as axis ticker"; + // no need to invalidate margin cache here because produced tick labels are checked for changes in setupTickVector } +/*! + Sets whether tick marks are displayed. -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPItemStraightLine -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPItemStraightLine - \brief A straight line that spans infinitely in both directions - - \image html QCPItemStraightLine.png "Straight line example. Blue dotted circles are anchors, solid blue discs are positions." - - It has two positions, \a point1 and \a point2, which define the straight line. + Note that setting \a show to false does not imply that tick labels are invisible, too. To achieve + that, see \ref setTickLabels. + + \see setSubTicks */ +void QCPPolarAxisAngular::setTicks(bool show) +{ + if (mTicks != show) + { + mTicks = show; + //mCachedMarginValid = false; + } +} /*! - Creates a straight line item and sets default values. - - The constructed item can be added to the plot with QCustomPlot::addItem. + Sets whether tick labels are displayed. Tick labels are the numbers drawn next to tick marks. */ -QCPItemStraightLine::QCPItemStraightLine(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - point1(createPosition(QLatin1String("point1"))), - point2(createPosition(QLatin1String("point2"))) +void QCPPolarAxisAngular::setTickLabels(bool show) { - point1->setCoords(0, 0); - point2->setCoords(1, 1); - - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue,2)); + if (mTickLabels != show) + { + mTickLabels = show; + //mCachedMarginValid = false; + if (!mTickLabels) + mTickVectorLabels.clear(); + } } -QCPItemStraightLine::~QCPItemStraightLine() +/*! + Sets the distance between the axis base line (including any outward ticks) and the tick labels. + \see setLabelPadding, setPadding +*/ +void QCPPolarAxisAngular::setTickLabelPadding(int padding) { + mLabelPainter.setPadding(padding); } /*! - Sets the pen that will be used to draw the line + Sets the font of the tick labels. - \see setSelectedPen + \see setTickLabels, setTickLabelColor */ -void QCPItemStraightLine::setPen(const QPen &pen) +void QCPPolarAxisAngular::setTickLabelFont(const QFont &font) { - mPen = pen; + mTickLabelFont = font; } /*! - Sets the pen that will be used to draw the line when selected + Sets the color of the tick labels. - \see setPen, setSelected + \see setTickLabels, setTickLabelFont */ -void QCPItemStraightLine::setSelectedPen(const QPen &pen) +void QCPPolarAxisAngular::setTickLabelColor(const QColor &color) { - mSelectedPen = pen; + mTickLabelColor = color; } -/* inherits documentation from base class */ -double QCPItemStraightLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const -{ - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; +/*! + Sets the rotation of the tick labels. If \a degrees is zero, the labels are drawn normally. Else, + the tick labels are drawn rotated by \a degrees clockwise. The specified angle is bound to values + from -90 to 90 degrees. - return distToStraightLine(QVector2D(point1->pixelPoint()), QVector2D(point2->pixelPoint()-point1->pixelPoint()), QVector2D(pos)); + If \a degrees is exactly -90, 0 or 90, the tick labels are centered on the tick coordinate. For + other angles, the label is drawn with an offset such that it seems to point toward or away from + the tick mark. +*/ +void QCPPolarAxisAngular::setTickLabelRotation(double degrees) +{ + mLabelPainter.setRotation(degrees); } -/* inherits documentation from base class */ -void QCPItemStraightLine::draw(QCPPainter *painter) +void QCPPolarAxisAngular::setTickLabelMode(LabelMode mode) { - QVector2D start(point1->pixelPoint()); - QVector2D end(point2->pixelPoint()); - // get visible segment of straight line inside clipRect: - double clipPad = mainPen().widthF(); - QLineF line = getRectClippedStraightLine(start, end-start, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad)); - // paint visible segment, if existent: - if (!line.isNull()) + switch (mode) { - painter->setPen(mainPen()); - painter->drawLine(line); + case lmUpright: mLabelPainter.setAnchorMode(QCPLabelPainterPrivate::amSkewedUpright); break; + case lmRotated: mLabelPainter.setAnchorMode(QCPLabelPainterPrivate::amSkewedRotated); break; } } -/*! \internal - - finds the shortest distance of \a point to the straight line defined by the base point \a - base and the direction vector \a vec. +/*! + Sets the number format for the numbers in tick labels. This \a formatCode is an extended version + of the format code used e.g. by QString::number() and QLocale::toString(). For reference about + that, see the "Argument Formats" section in the detailed description of the QString class. - This is a helper function for \ref selectTest. -*/ -double QCPItemStraightLine::distToStraightLine(const QVector2D &base, const QVector2D &vec, const QVector2D &point) const -{ - return qAbs((base.y()-point.y())*vec.x()-(base.x()-point.x())*vec.y())/vec.length(); -} - -/*! \internal - - Returns the section of the straight line defined by \a base and direction vector \a - vec, that is visible in the specified \a rect. + \a formatCode is a string of one, two or three characters. The first character is identical to + the normal format code used by Qt. In short, this means: 'e'/'E' scientific format, 'f' fixed + format, 'g'/'G' scientific or fixed, whichever is shorter. - This is a helper function for \ref draw. + The second and third characters are optional and specific to QCustomPlot:\n If the first char was + 'e' or 'g', numbers are/might be displayed in the scientific format, e.g. "5.5e9", which might be + visually unappealing in a plot. So when the second char of \a formatCode is set to 'b' (for + "beautiful"), those exponential numbers are formatted in a more natural way, i.e. "5.5 + [multiplication sign] 10 [superscript] 9". By default, the multiplication sign is a centered dot. + If instead a cross should be shown (as is usual in the USA), the third char of \a formatCode can + be set to 'c'. The inserted multiplication signs are the UTF-8 characters 215 (0xD7) for the + cross and 183 (0xB7) for the dot. + + Examples for \a formatCode: + \li \c g normal format code behaviour. If number is small, fixed format is used, if number is large, + normal scientific format is used + \li \c gb If number is small, fixed format is used, if number is large, scientific format is used with + beautifully typeset decimal powers and a dot as multiplication sign + \li \c ebc All numbers are in scientific format with beautifully typeset decimal power and a cross as + multiplication sign + \li \c fb illegal format code, since fixed format doesn't support (or need) beautifully typeset decimal + powers. Format code will be reduced to 'f'. + \li \c hello illegal format code, since first char is not 'e', 'E', 'f', 'g' or 'G'. Current format + code will not be changed. */ -QLineF QCPItemStraightLine::getRectClippedStraightLine(const QVector2D &base, const QVector2D &vec, const QRect &rect) const +void QCPPolarAxisAngular::setNumberFormat(const QString &formatCode) { - double bx, by; - double gamma; - QLineF result; - if (vec.x() == 0 && vec.y() == 0) - return result; - if (qFuzzyIsNull(vec.x())) // line is vertical + if (formatCode.isEmpty()) { - // check top of rect: - bx = rect.left(); - by = rect.top(); - gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y(); - if (gamma >= 0 && gamma <= rect.width()) - result.setLine(bx+gamma, rect.top(), bx+gamma, rect.bottom()); // no need to check bottom because we know line is vertical - } else if (qFuzzyIsNull(vec.y())) // line is horizontal + qDebug() << Q_FUNC_INFO << "Passed formatCode is empty"; + return; + } + //mCachedMarginValid = false; + + // interpret first char as number format char: + QString allowedFormatChars(QLatin1String("eEfgG")); + if (allowedFormatChars.contains(formatCode.at(0))) { - // check left of rect: - bx = rect.left(); - by = rect.top(); - gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x(); - if (gamma >= 0 && gamma <= rect.height()) - result.setLine(rect.left(), by+gamma, rect.right(), by+gamma); // no need to check right because we know line is horizontal - } else // line is skewed + mNumberFormatChar = QLatin1Char(formatCode.at(0).toLatin1()); + } else { - QList pointVectors; - // check top of rect: - bx = rect.left(); - by = rect.top(); - gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y(); - if (gamma >= 0 && gamma <= rect.width()) - pointVectors.append(QVector2D(bx+gamma, by)); - // check bottom of rect: - bx = rect.left(); - by = rect.bottom(); - gamma = base.x()-bx + (by-base.y())*vec.x()/vec.y(); - if (gamma >= 0 && gamma <= rect.width()) - pointVectors.append(QVector2D(bx+gamma, by)); - // check left of rect: - bx = rect.left(); - by = rect.top(); - gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x(); - if (gamma >= 0 && gamma <= rect.height()) - pointVectors.append(QVector2D(bx, by+gamma)); - // check right of rect: - bx = rect.right(); - by = rect.top(); - gamma = base.y()-by + (bx-base.x())*vec.y()/vec.x(); - if (gamma >= 0 && gamma <= rect.height()) - pointVectors.append(QVector2D(bx, by+gamma)); + qDebug() << Q_FUNC_INFO << "Invalid number format code (first char not in 'eEfgG'):" << formatCode; + return; + } + + if (formatCode.length() < 2) + { + mNumberBeautifulPowers = false; + mNumberMultiplyCross = false; + } else + { + // interpret second char as indicator for beautiful decimal powers: + if (formatCode.at(1) == QLatin1Char('b') && (mNumberFormatChar == QLatin1Char('e') || mNumberFormatChar == QLatin1Char('g'))) + mNumberBeautifulPowers = true; + else + qDebug() << Q_FUNC_INFO << "Invalid number format code (second char not 'b' or first char neither 'e' nor 'g'):" << formatCode; - // evaluate points: - if (pointVectors.size() == 2) + if (formatCode.length() < 3) { - result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF()); - } else if (pointVectors.size() > 2) + mNumberMultiplyCross = false; + } else { - // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance: - double distSqrMax = 0; - QVector2D pv1, pv2; - for (int i=0; i distSqrMax) - { - pv1 = pointVectors.at(i); - pv2 = pointVectors.at(k); - distSqrMax = distSqr; - } - } - } - result.setPoints(pv1.toPointF(), pv2.toPointF()); + // interpret third char as indicator for dot or cross multiplication symbol: + if (formatCode.at(2) == QLatin1Char('c')) + mNumberMultiplyCross = true; + else if (formatCode.at(2) == QLatin1Char('d')) + mNumberMultiplyCross = false; + else + qDebug() << Q_FUNC_INFO << "Invalid number format code (third char neither 'c' nor 'd'):" << formatCode; } } - return result; + mLabelPainter.setSubstituteExponent(mNumberBeautifulPowers); + mLabelPainter.setMultiplicationSymbol(mNumberMultiplyCross ? QCPLabelPainterPrivate::SymbolCross : QCPLabelPainterPrivate::SymbolDot); } -/*! \internal - - Returns the pen that should be used for drawing lines. Returns mPen when the - item is not selected and mSelectedPen when it is. +/*! + Sets the precision of the tick label numbers. See QLocale::toString(double i, char f, int prec) + for details. The effect of precisions are most notably for number Formats starting with 'e', see + \ref setNumberFormat */ -QPen QCPItemStraightLine::mainPen() const +void QCPPolarAxisAngular::setNumberPrecision(int precision) { - return mSelected ? mSelectedPen : mPen; + if (mNumberPrecision != precision) + { + mNumberPrecision = precision; + //mCachedMarginValid = false; + } } - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPItemLine -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPItemLine - \brief A line from one point to another - - \image html QCPItemLine.png "Line example. Blue dotted circles are anchors, solid blue discs are positions." - - It has two positions, \a start and \a end, which define the end points of the line. - - With \ref setHead and \ref setTail you may set different line ending styles, e.g. to create an arrow. -*/ - /*! - Creates a line item and sets default values. + Sets the length of the ticks in pixels. \a inside is the length the ticks will reach inside the + plot and \a outside is the length they will reach outside the plot. If \a outside is greater than + zero, the tick labels and axis label will increase their distance to the axis accordingly, so + they won't collide with the ticks. - The constructed item can be added to the plot with QCustomPlot::addItem. + \see setSubTickLength, setTickLengthIn, setTickLengthOut */ -QCPItemLine::QCPItemLine(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - start(createPosition(QLatin1String("start"))), - end(createPosition(QLatin1String("end"))) -{ - start->setCoords(0, 0); - end->setCoords(1, 1); - - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue,2)); -} - -QCPItemLine::~QCPItemLine() +void QCPPolarAxisAngular::setTickLength(int inside, int outside) { + setTickLengthIn(inside); + setTickLengthOut(outside); } /*! - Sets the pen that will be used to draw the line + Sets the length of the inward ticks in pixels. \a inside is the length the ticks will reach + inside the plot. - \see setSelectedPen + \see setTickLengthOut, setTickLength, setSubTickLength */ -void QCPItemLine::setPen(const QPen &pen) +void QCPPolarAxisAngular::setTickLengthIn(int inside) { - mPen = pen; + if (mTickLengthIn != inside) + { + mTickLengthIn = inside; + } } /*! - Sets the pen that will be used to draw the line when selected + Sets the length of the outward ticks in pixels. \a outside is the length the ticks will reach + outside the plot. If \a outside is greater than zero, the tick labels and axis label will + increase their distance to the axis accordingly, so they won't collide with the ticks. - \see setPen, setSelected + \see setTickLengthIn, setTickLength, setSubTickLength */ -void QCPItemLine::setSelectedPen(const QPen &pen) +void QCPPolarAxisAngular::setTickLengthOut(int outside) { - mSelectedPen = pen; + if (mTickLengthOut != outside) + { + mTickLengthOut = outside; + //mCachedMarginValid = false; // only outside tick length can change margin + } } /*! - Sets the line ending style of the head. The head corresponds to the \a end position. + Sets whether sub tick marks are displayed. - Note that due to the overloaded QCPLineEnding constructor, you may directly specify - a QCPLineEnding::EndingStyle here, e.g. \code setHead(QCPLineEnding::esSpikeArrow) \endcode + Sub ticks are only potentially visible if (major) ticks are also visible (see \ref setTicks) - \see setTail + \see setTicks */ -void QCPItemLine::setHead(const QCPLineEnding &head) +void QCPPolarAxisAngular::setSubTicks(bool show) { - mHead = head; + if (mSubTicks != show) + { + mSubTicks = show; + //mCachedMarginValid = false; + } } /*! - Sets the line ending style of the tail. The tail corresponds to the \a start position. - - Note that due to the overloaded QCPLineEnding constructor, you may directly specify - a QCPLineEnding::EndingStyle here, e.g. \code setTail(QCPLineEnding::esSpikeArrow) \endcode + Sets the length of the subticks in pixels. \a inside is the length the subticks will reach inside + the plot and \a outside is the length they will reach outside the plot. If \a outside is greater + than zero, the tick labels and axis label will increase their distance to the axis accordingly, + so they won't collide with the ticks. - \see setHead + \see setTickLength, setSubTickLengthIn, setSubTickLengthOut */ -void QCPItemLine::setTail(const QCPLineEnding &tail) +void QCPPolarAxisAngular::setSubTickLength(int inside, int outside) { - mTail = tail; + setSubTickLengthIn(inside); + setSubTickLengthOut(outside); } -/* inherits documentation from base class */ -double QCPItemLine::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const -{ - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; +/*! + Sets the length of the inward subticks in pixels. \a inside is the length the subticks will reach inside + the plot. - return qSqrt(distSqrToLine(start->pixelPoint(), end->pixelPoint(), pos)); -} - -/* inherits documentation from base class */ -void QCPItemLine::draw(QCPPainter *painter) + \see setSubTickLengthOut, setSubTickLength, setTickLength +*/ +void QCPPolarAxisAngular::setSubTickLengthIn(int inside) { - QVector2D startVec(start->pixelPoint()); - QVector2D endVec(end->pixelPoint()); - if (startVec.toPoint() == endVec.toPoint()) - return; - // get visible segment of straight line inside clipRect: - double clipPad = qMax(mHead.boundingDistance(), mTail.boundingDistance()); - clipPad = qMax(clipPad, (double)mainPen().widthF()); - QLineF line = getRectClippedLine(startVec, endVec, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad)); - // paint visible segment, if existent: - if (!line.isNull()) + if (mSubTickLengthIn != inside) { - painter->setPen(mainPen()); - painter->drawLine(line); - painter->setBrush(Qt::SolidPattern); - if (mTail.style() != QCPLineEnding::esNone) - mTail.draw(painter, startVec, startVec-endVec); - if (mHead.style() != QCPLineEnding::esNone) - mHead.draw(painter, endVec, endVec-startVec); + mSubTickLengthIn = inside; } } -/*! \internal - - Returns the section of the line defined by \a start and \a end, that is visible in the specified - \a rect. +/*! + Sets the length of the outward subticks in pixels. \a outside is the length the subticks will reach + outside the plot. If \a outside is greater than zero, the tick labels will increase their + distance to the axis accordingly, so they won't collide with the ticks. - This is a helper function for \ref draw. + \see setSubTickLengthIn, setSubTickLength, setTickLength */ -QLineF QCPItemLine::getRectClippedLine(const QVector2D &start, const QVector2D &end, const QRect &rect) const +void QCPPolarAxisAngular::setSubTickLengthOut(int outside) { - bool containsStart = rect.contains(start.x(), start.y()); - bool containsEnd = rect.contains(end.x(), end.y()); - if (containsStart && containsEnd) - return QLineF(start.toPointF(), end.toPointF()); - - QVector2D base = start; - QVector2D vec = end-start; - double bx, by; - double gamma, mu; - QLineF result; - QList pointVectors; - - if (!qFuzzyIsNull(vec.y())) // line is not horizontal - { - // check top of rect: - bx = rect.left(); - by = rect.top(); - mu = (by-base.y())/vec.y(); - if (mu >= 0 && mu <= 1) - { - gamma = base.x()-bx + mu*vec.x(); - if (gamma >= 0 && gamma <= rect.width()) - pointVectors.append(QVector2D(bx+gamma, by)); - } - // check bottom of rect: - bx = rect.left(); - by = rect.bottom(); - mu = (by-base.y())/vec.y(); - if (mu >= 0 && mu <= 1) - { - gamma = base.x()-bx + mu*vec.x(); - if (gamma >= 0 && gamma <= rect.width()) - pointVectors.append(QVector2D(bx+gamma, by)); - } - } - if (!qFuzzyIsNull(vec.x())) // line is not vertical - { - // check left of rect: - bx = rect.left(); - by = rect.top(); - mu = (bx-base.x())/vec.x(); - if (mu >= 0 && mu <= 1) - { - gamma = base.y()-by + mu*vec.y(); - if (gamma >= 0 && gamma <= rect.height()) - pointVectors.append(QVector2D(bx, by+gamma)); - } - // check right of rect: - bx = rect.right(); - by = rect.top(); - mu = (bx-base.x())/vec.x(); - if (mu >= 0 && mu <= 1) - { - gamma = base.y()-by + mu*vec.y(); - if (gamma >= 0 && gamma <= rect.height()) - pointVectors.append(QVector2D(bx, by+gamma)); - } - } - - if (containsStart) - pointVectors.append(start); - if (containsEnd) - pointVectors.append(end); - - // evaluate points: - if (pointVectors.size() == 2) + if (mSubTickLengthOut != outside) { - result.setPoints(pointVectors.at(0).toPointF(), pointVectors.at(1).toPointF()); - } else if (pointVectors.size() > 2) - { - // line probably goes through corner of rect, and we got two points there. single out the point pair with greatest distance: - double distSqrMax = 0; - QVector2D pv1, pv2; - for (int i=0; i distSqrMax) - { - pv1 = pointVectors.at(i); - pv2 = pointVectors.at(k); - distSqrMax = distSqr; - } - } - } - result.setPoints(pv1.toPointF(), pv2.toPointF()); + mSubTickLengthOut = outside; + //mCachedMarginValid = false; // only outside tick length can change margin } - return result; -} - -/*! \internal - - Returns the pen that should be used for drawing lines. Returns mPen when the - item is not selected and mSelectedPen when it is. -*/ -QPen QCPItemLine::mainPen() const -{ - return mSelected ? mSelectedPen : mPen; } - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPItemCurve -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPItemCurve - \brief A curved line from one point to another - - \image html QCPItemCurve.png "Curve example. Blue dotted circles are anchors, solid blue discs are positions." - - It has four positions, \a start and \a end, which define the end points of the line, and two - control points which define the direction the line exits from the start and the direction from - which it approaches the end: \a startDir and \a endDir. - - With \ref setHead and \ref setTail you may set different line ending styles, e.g. to create an - arrow. - - Often it is desirable for the control points to stay at fixed relative positions to the start/end - point. This can be achieved by setting the parent anchor e.g. of \a startDir simply to \a start, - and then specify the desired pixel offset with QCPItemPosition::setCoords on \a startDir. -*/ - /*! - Creates a curve item and sets default values. - - The constructed item can be added to the plot with QCustomPlot::addItem. -*/ -QCPItemCurve::QCPItemCurve(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - start(createPosition(QLatin1String("start"))), - startDir(createPosition(QLatin1String("startDir"))), - endDir(createPosition(QLatin1String("endDir"))), - end(createPosition(QLatin1String("end"))) -{ - start->setCoords(0, 0); - startDir->setCoords(0.5, 0); - endDir->setCoords(0, 0.5); - end->setCoords(1, 1); - - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue,2)); -} - -QCPItemCurve::~QCPItemCurve() + Sets the pen, the axis base line is drawn with. + + \see setTickPen, setSubTickPen +*/ +void QCPPolarAxisAngular::setBasePen(const QPen &pen) { + mBasePen = pen; } /*! - Sets the pen that will be used to draw the line + Sets the pen, tick marks will be drawn with. - \see setSelectedPen + \see setTickLength, setBasePen */ -void QCPItemCurve::setPen(const QPen &pen) +void QCPPolarAxisAngular::setTickPen(const QPen &pen) { - mPen = pen; + mTickPen = pen; } /*! - Sets the pen that will be used to draw the line when selected + Sets the pen, subtick marks will be drawn with. - \see setPen, setSelected + \see setSubTickCount, setSubTickLength, setBasePen */ -void QCPItemCurve::setSelectedPen(const QPen &pen) +void QCPPolarAxisAngular::setSubTickPen(const QPen &pen) { - mSelectedPen = pen; + mSubTickPen = pen; } /*! - Sets the line ending style of the head. The head corresponds to the \a end position. - - Note that due to the overloaded QCPLineEnding constructor, you may directly specify - a QCPLineEnding::EndingStyle here, e.g. \code setHead(QCPLineEnding::esSpikeArrow) \endcode + Sets the font of the axis label. - \see setTail + \see setLabelColor */ -void QCPItemCurve::setHead(const QCPLineEnding &head) +void QCPPolarAxisAngular::setLabelFont(const QFont &font) { - mHead = head; + if (mLabelFont != font) + { + mLabelFont = font; + //mCachedMarginValid = false; + } } /*! - Sets the line ending style of the tail. The tail corresponds to the \a start position. - - Note that due to the overloaded QCPLineEnding constructor, you may directly specify - a QCPLineEnding::EndingStyle here, e.g. \code setTail(QCPLineEnding::esSpikeArrow) \endcode + Sets the color of the axis label. - \see setHead + \see setLabelFont */ -void QCPItemCurve::setTail(const QCPLineEnding &tail) +void QCPPolarAxisAngular::setLabelColor(const QColor &color) { - mTail = tail; + mLabelColor = color; } -/* inherits documentation from base class */ -double QCPItemCurve::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +/*! + Sets the text of the axis label that will be shown below/above or next to the axis, depending on + its orientation. To disable axis labels, pass an empty string as \a str. +*/ +void QCPPolarAxisAngular::setLabel(const QString &str) { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - QPointF startVec(start->pixelPoint()); - QPointF startDirVec(startDir->pixelPoint()); - QPointF endDirVec(endDir->pixelPoint()); - QPointF endVec(end->pixelPoint()); - - QPainterPath cubicPath(startVec); - cubicPath.cubicTo(startDirVec, endDirVec, endVec); - - QPolygonF polygon = cubicPath.toSubpathPolygons().first(); - double minDistSqr = std::numeric_limits::max(); - for (int i=1; ipixelPoint()); - QPointF startDirVec(startDir->pixelPoint()); - QPointF endDirVec(endDir->pixelPoint()); - QPointF endVec(end->pixelPoint()); - if (QVector2D(endVec-startVec).length() > 1e10f) // too large curves cause crash - return; - - QPainterPath cubicPath(startVec); - cubicPath.cubicTo(startDirVec, endDirVec, endVec); - - // paint visible segment, if existent: - QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF()); - QRect cubicRect = cubicPath.controlPointRect().toRect(); - if (cubicRect.isEmpty()) // may happen when start and end exactly on same x or y position - cubicRect.adjust(0, 0, 1, 1); - if (clip.intersects(cubicRect)) + if (mLabelPadding != padding) { - painter->setPen(mainPen()); - painter->drawPath(cubicPath); - painter->setBrush(Qt::SolidPattern); - if (mTail.style() != QCPLineEnding::esNone) - mTail.draw(painter, QVector2D(startVec), M_PI-cubicPath.angleAtPercent(0)/180.0*M_PI); - if (mHead.style() != QCPLineEnding::esNone) - mHead.draw(painter, QVector2D(endVec), -cubicPath.angleAtPercent(1)/180.0*M_PI); + mLabelPadding = padding; + //mCachedMarginValid = false; } } -/*! \internal - - Returns the pen that should be used for drawing lines. Returns mPen when the - item is not selected and mSelectedPen when it is. +/*! + Sets the font that is used for tick labels when they are selected. + + \see setTickLabelFont, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions */ -QPen QCPItemCurve::mainPen() const +void QCPPolarAxisAngular::setSelectedTickLabelFont(const QFont &font) { - return mSelected ? mSelectedPen : mPen; + if (font != mSelectedTickLabelFont) + { + mSelectedTickLabelFont = font; + // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts + } } - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPItemRect -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPItemRect - \brief A rectangle - - \image html QCPItemRect.png "Rectangle example. Blue dotted circles are anchors, solid blue discs are positions." - - It has two positions, \a topLeft and \a bottomRight, which define the rectangle. -*/ - /*! - Creates a rectangle item and sets default values. + Sets the font that is used for the axis label when it is selected. - The constructed item can be added to the plot with QCustomPlot::addItem. + \see setLabelFont, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions */ -QCPItemRect::QCPItemRect(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - topLeft(createPosition(QLatin1String("topLeft"))), - bottomRight(createPosition(QLatin1String("bottomRight"))), - top(createAnchor(QLatin1String("top"), aiTop)), - topRight(createAnchor(QLatin1String("topRight"), aiTopRight)), - right(createAnchor(QLatin1String("right"), aiRight)), - bottom(createAnchor(QLatin1String("bottom"), aiBottom)), - bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)), - left(createAnchor(QLatin1String("left"), aiLeft)) +void QCPPolarAxisAngular::setSelectedLabelFont(const QFont &font) { - topLeft->setCoords(0, 1); - bottomRight->setCoords(1, 0); - - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue,2)); - setBrush(Qt::NoBrush); - setSelectedBrush(Qt::NoBrush); + mSelectedLabelFont = font; + // don't set mCachedMarginValid to false here because margin calculation is always done with non-selected fonts } -QCPItemRect::~QCPItemRect() +/*! + Sets the color that is used for tick labels when they are selected. + + \see setTickLabelColor, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions +*/ +void QCPPolarAxisAngular::setSelectedTickLabelColor(const QColor &color) { + if (color != mSelectedTickLabelColor) + { + mSelectedTickLabelColor = color; + } } /*! - Sets the pen that will be used to draw the line of the rectangle + Sets the color that is used for the axis label when it is selected. - \see setSelectedPen, setBrush + \see setLabelColor, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions */ -void QCPItemRect::setPen(const QPen &pen) +void QCPPolarAxisAngular::setSelectedLabelColor(const QColor &color) { - mPen = pen; + mSelectedLabelColor = color; } /*! - Sets the pen that will be used to draw the line of the rectangle when selected + Sets the pen that is used to draw the axis base line when selected. - \see setPen, setSelected + \see setBasePen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions */ -void QCPItemRect::setSelectedPen(const QPen &pen) +void QCPPolarAxisAngular::setSelectedBasePen(const QPen &pen) { - mSelectedPen = pen; + mSelectedBasePen = pen; } /*! - Sets the brush that will be used to fill the rectangle. To disable filling, set \a brush to - Qt::NoBrush. + Sets the pen that is used to draw the (major) ticks when selected. - \see setSelectedBrush, setPen + \see setTickPen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions */ -void QCPItemRect::setBrush(const QBrush &brush) +void QCPPolarAxisAngular::setSelectedTickPen(const QPen &pen) { - mBrush = brush; + mSelectedTickPen = pen; } /*! - Sets the brush that will be used to fill the rectangle when selected. To disable filling, set \a - brush to Qt::NoBrush. + Sets the pen that is used to draw the subticks when selected. - \see setBrush + \see setSubTickPen, setSelectableParts, setSelectedParts, QCustomPlot::setInteractions */ -void QCPItemRect::setSelectedBrush(const QBrush &brush) +void QCPPolarAxisAngular::setSelectedSubTickPen(const QPen &pen) { - mSelectedBrush = brush; + mSelectedSubTickPen = pen; } -/* inherits documentation from base class */ -double QCPItemRect::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const -{ - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; +/*! \internal - QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint()).normalized(); - bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0; - return rectSelectTest(rect, pos, filledRect); -} - -/* inherits documentation from base class */ -void QCPItemRect::draw(QCPPainter *painter) + Draws the background of this axis rect. It may consist of a background fill (a QBrush) and a + pixmap. + + If a brush was given via \ref setBackground(const QBrush &brush), this function first draws an + according filling inside the axis rect with the provided \a painter. + + Then, if a pixmap was provided via \ref setBackground, this function buffers the scaled version + depending on \ref setBackgroundScaled and \ref setBackgroundScaledMode and then draws it inside + the axis rect with the provided \a painter. The scaled version is buffered in + mScaledBackgroundPixmap to prevent expensive rescaling at every redraw. It is only updated, when + the axis rect has changed in a way that requires a rescale of the background pixmap (this is + dependent on the \ref setBackgroundScaledMode), or when a differend axis background pixmap was + set. + + \see setBackground, setBackgroundScaled, setBackgroundScaledMode +*/ +void QCPPolarAxisAngular::drawBackground(QCPPainter *painter, const QPointF ¢er, double radius) { - QPointF p1 = topLeft->pixelPoint(); - QPointF p2 = bottomRight->pixelPoint(); - if (p1.toPoint() == p2.toPoint()) - return; - QRectF rect = QRectF(p1, p2).normalized(); - double clipPad = mainPen().widthF(); - QRectF boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad); - if (boundingRect.intersects(clipRect())) // only draw if bounding rect of rect item is visible in cliprect + // draw background fill (don't use circular clip, looks bad): + if (mBackgroundBrush != Qt::NoBrush) { - painter->setPen(mainPen()); - painter->setBrush(mainBrush()); - painter->drawRect(rect); + QPainterPath ellipsePath; + ellipsePath.addEllipse(center, radius, radius); + painter->fillPath(ellipsePath, mBackgroundBrush); + } + + // draw background pixmap (on top of fill, if brush specified): + if (!mBackgroundPixmap.isNull()) + { + QRegion clipCircle(center.x()-radius, center.y()-radius, qRound(2*radius), qRound(2*radius), QRegion::Ellipse); + QRegion originalClip = painter->clipRegion(); + painter->setClipRegion(clipCircle); + if (mBackgroundScaled) + { + // check whether mScaledBackground needs to be updated: + QSize scaledSize(mBackgroundPixmap.size()); + scaledSize.scale(mRect.size(), mBackgroundScaledMode); + if (mScaledBackgroundPixmap.size() != scaledSize) + mScaledBackgroundPixmap = mBackgroundPixmap.scaled(mRect.size(), mBackgroundScaledMode, Qt::SmoothTransformation); + painter->drawPixmap(mRect.topLeft()+QPoint(0, -1), mScaledBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height()) & mScaledBackgroundPixmap.rect()); + } else + { + painter->drawPixmap(mRect.topLeft()+QPoint(0, -1), mBackgroundPixmap, QRect(0, 0, mRect.width(), mRect.height())); + } + painter->setClipRegion(originalClip); } } -/* inherits documentation from base class */ -QPointF QCPItemRect::anchorPixelPoint(int anchorId) const +/*! \internal + + Prepares the internal tick vector, sub tick vector and tick label vector. This is done by calling + QCPAxisTicker::generate on the currently installed ticker. + + If a change in the label text/count is detected, the cached axis margin is invalidated to make + sure the next margin calculation recalculates the label sizes and returns an up-to-date value. +*/ +void QCPPolarAxisAngular::setupTickVectors() { - QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint()); - switch (anchorId) + if (!mParentPlot) return; + if ((!mTicks && !mTickLabels && !mGrid->visible()) || mRange.size() <= 0) return; + + mSubTickVector.clear(); // since we might not pass it to mTicker->generate(), and we don't want old data in there + mTicker->generate(mRange, mParentPlot->locale(), mNumberFormatChar, mNumberPrecision, mTickVector, mSubTicks ? &mSubTickVector : 0, mTickLabels ? &mTickVectorLabels : 0); + + // fill cos/sin buffers which will be used by draw() and QCPPolarGrid::draw(), so we don't have to calculate it twice: + mTickVectorCosSin.resize(mTickVector.size()); + for (int i=0; isetCoords(0, 0); - - setRotation(0); - setTextAlignment(Qt::AlignTop|Qt::AlignHCenter); - setPositionAlignment(Qt::AlignCenter); - setText(QLatin1String("text")); - - setPen(Qt::NoPen); - setSelectedPen(Qt::NoPen); - setBrush(Qt::NoBrush); - setSelectedBrush(Qt::NoBrush); - setColor(Qt::black); - setSelectedColor(Qt::blue); + return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelFont : mLabelFont; } -QCPItemText::~QCPItemText() +/*! \internal + + Returns the color that is used to draw the tick labels. Depending on the selection state, this + is either mSelectedTickLabelColor or mTickLabelColor. +*/ +QColor QCPPolarAxisAngular::getTickLabelColor() const { + return mSelectedParts.testFlag(spTickLabels) ? mSelectedTickLabelColor : mTickLabelColor; } -/*! - Sets the color of the text. +/*! \internal + + Returns the color that is used to draw the axis label. Depending on the selection state, this + is either mSelectedLabelColor or mLabelColor. */ -void QCPItemText::setColor(const QColor &color) +QColor QCPPolarAxisAngular::getLabelColor() const { - mColor = color; + return mSelectedParts.testFlag(spAxisLabel) ? mSelectedLabelColor : mLabelColor; } -/*! - Sets the color of the text that will be used when the item is selected. +/*! \internal + + Event handler for when a mouse button is pressed on the axis rect. If the left mouse button is + pressed, the range dragging interaction is initialized (the actual range manipulation happens in + the \ref mouseMoveEvent). + + The mDragging flag is set to true and some anchor points are set that are needed to determine the + distance the mouse was dragged in the mouse move/release events later. + + \see mouseMoveEvent, mouseReleaseEvent */ -void QCPItemText::setSelectedColor(const QColor &color) +void QCPPolarAxisAngular::mousePressEvent(QMouseEvent *event, const QVariant &details) { - mSelectedColor = color; + Q_UNUSED(details) + if (event->buttons() & Qt::LeftButton) + { + mDragging = true; + // initialize antialiasing backup in case we start dragging: + if (mParentPlot->noAntialiasingOnDrag()) + { + mAADragBackup = mParentPlot->antialiasedElements(); + mNotAADragBackup = mParentPlot->notAntialiasedElements(); + } + // Mouse range dragging interaction: + if (mParentPlot->interactions().testFlag(QCP::iRangeDrag)) + { + mDragAngularStart = range(); + mDragRadialStart.clear(); + for (int i=0; irange()); + } + } } -/*! - Sets the pen that will be used do draw a rectangular border around the text. To disable the - border, set \a pen to Qt::NoPen. +/*! \internal - \see setSelectedPen, setBrush, setPadding + Event handler for when the mouse is moved on the axis rect. If range dragging was activated in a + preceding \ref mousePressEvent, the range is moved accordingly. + + \see mousePressEvent, mouseReleaseEvent */ -void QCPItemText::setPen(const QPen &pen) +void QCPPolarAxisAngular::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) { - mPen = pen; + Q_UNUSED(startPos) + bool doReplot = false; + // Mouse range dragging interaction: + if (mDragging && mParentPlot->interactions().testFlag(QCP::iRangeDrag)) + { + if (mRangeDrag) + { + doReplot = true; + double angleCoordStart, radiusCoordStart; + double angleCoord, radiusCoord; + pixelToCoord(startPos, angleCoordStart, radiusCoordStart); + pixelToCoord(event->pos(), angleCoord, radiusCoord); + double diff = angleCoordStart - angleCoord; + setRange(mDragAngularStart.lower+diff, mDragAngularStart.upper+diff); + } + + for (int i=0; irangeDrag()) + continue; + doReplot = true; + double angleCoordStart, radiusCoordStart; + double angleCoord, radiusCoord; + ax->pixelToCoord(startPos, angleCoordStart, radiusCoordStart); + ax->pixelToCoord(event->pos(), angleCoord, radiusCoord); + if (ax->scaleType() == QCPPolarAxisRadial::stLinear) + { + double diff = radiusCoordStart - radiusCoord; + ax->setRange(mDragRadialStart.at(i).lower+diff, mDragRadialStart.at(i).upper+diff); + } else if (ax->scaleType() == QCPPolarAxisRadial::stLogarithmic) + { + if (radiusCoord != 0) + { + double diff = radiusCoordStart/radiusCoord; + ax->setRange(mDragRadialStart.at(i).lower*diff, mDragRadialStart.at(i).upper*diff); + } + } + } + + if (doReplot) // if either vertical or horizontal drag was enabled, do a replot + { + if (mParentPlot->noAntialiasingOnDrag()) + mParentPlot->setNotAntialiasedElements(QCP::aeAll); + mParentPlot->replot(QCustomPlot::rpQueuedReplot); + } + } } -/*! - Sets the pen that will be used do draw a rectangular border around the text, when the item is - selected. To disable the border, set \a pen to Qt::NoPen. - - \see setPen -*/ -void QCPItemText::setSelectedPen(const QPen &pen) +/* inherits documentation from base class */ +void QCPPolarAxisAngular::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) { - mSelectedPen = pen; + Q_UNUSED(event) + Q_UNUSED(startPos) + mDragging = false; + if (mParentPlot->noAntialiasingOnDrag()) + { + mParentPlot->setAntialiasedElements(mAADragBackup); + mParentPlot->setNotAntialiasedElements(mNotAADragBackup); + } } -/*! - Sets the brush that will be used do fill the background of the text. To disable the - background, set \a brush to Qt::NoBrush. +/*! \internal - \see setSelectedBrush, setPen, setPadding + Event handler for mouse wheel events. If rangeZoom is Qt::Horizontal, Qt::Vertical or both, the + ranges of the axes defined as rangeZoomHorzAxis and rangeZoomVertAxis are scaled. The center of + the scaling operation is the current cursor position inside the axis rect. The scaling factor is + dependent on the mouse wheel delta (which direction the wheel was rotated) to provide a natural + zooming feel. The Strength of the zoom can be controlled via \ref setRangeZoomFactor. + + Note, that event->delta() is usually +/-120 for single rotation steps. However, if the mouse + wheel is turned rapidly, many steps may bunch up to one event, so the event->delta() may then be + multiples of 120. This is taken into account here, by calculating \a wheelSteps and using it as + exponent of the range zoom factor. This takes care of the wheel direction automatically, by + inverting the factor, when the wheel step is negative (f^-1 = 1/f). */ -void QCPItemText::setBrush(const QBrush &brush) +void QCPPolarAxisAngular::wheelEvent(QWheelEvent *event) { - mBrush = brush; + bool doReplot = false; + // Mouse range zooming interaction: + if (mParentPlot->interactions().testFlag(QCP::iRangeZoom)) + { +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + const double delta = event->delta(); +#else + const double delta = event->angleDelta().y(); +#endif + +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + const QPointF pos = event->pos(); +#else + const QPointF pos = event->position(); +#endif + const double wheelSteps = delta/120.0; // a single step delta is +/-120 usually + if (mRangeZoom) + { + double angleCoord, radiusCoord; + pixelToCoord(pos, angleCoord, radiusCoord); + scaleRange(qPow(mRangeZoomFactor, wheelSteps), angleCoord); + } + + for (int i=0; irangeZoom()) + continue; + doReplot = true; + double angleCoord, radiusCoord; + ax->pixelToCoord(pos, angleCoord, radiusCoord); + ax->scaleRange(qPow(ax->rangeZoomFactor(), wheelSteps), radiusCoord); + } + } + if (doReplot) + mParentPlot->replot(); } -/*! - Sets the brush that will be used do fill the background of the text, when the item is selected. To disable the - background, set \a brush to Qt::NoBrush. - - \see setBrush -*/ -void QCPItemText::setSelectedBrush(const QBrush &brush) +bool QCPPolarAxisAngular::registerPolarGraph(QCPPolarGraph *graph) { - mSelectedBrush = brush; + if (mGraphs.contains(graph)) + { + qDebug() << Q_FUNC_INFO << "plottable already added:" << reinterpret_cast(graph); + return false; + } + if (graph->keyAxis() != this) + { + qDebug() << Q_FUNC_INFO << "plottable not created with this as axis:" << reinterpret_cast(graph); + return false; + } + + mGraphs.append(graph); + // possibly add plottable to legend: + if (mParentPlot->autoAddPlottableToLegend()) + graph->addToLegend(); + if (!graph->layer()) // usually the layer is already set in the constructor of the plottable (via QCPLayerable constructor) + graph->setLayer(mParentPlot->currentLayer()); + return true; } +/* end of 'src/polar/layoutelement-angularaxis.cpp' */ + + +/* including file 'src/polar/polargrid.cpp' */ +/* modified 2022-11-06T12:45:57, size 7493 */ + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPPolarGrid +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPPolarGrid + \brief The grid in both angular and radial dimensions for polar plots + + \warning In this QCustomPlot version, polar plots are a tech preview. Expect documentation and + functionality to be incomplete, as well as changing public interfaces in the future. +*/ /*! - Sets the font of the text. + Creates a QCPPolarGrid instance and sets default values. - \see setSelectedFont, setColor + You shouldn't instantiate grids on their own, since every axis brings its own grid. */ -void QCPItemText::setFont(const QFont &font) +QCPPolarGrid::QCPPolarGrid(QCPPolarAxisAngular *parentAxis) : + QCPLayerable(parentAxis->parentPlot(), QString(), parentAxis), + mType(gtNone), + mSubGridType(gtNone), + mAntialiasedSubGrid(true), + mAntialiasedZeroLine(true), + mParentAxis(parentAxis) { - mFont = font; + // warning: this is called in QCPPolarAxisAngular constructor, so parentAxis members should not be accessed/called + setParent(parentAxis); + setType(gtAll); + setSubGridType(gtNone); + + setAngularPen(QPen(QColor(200,200,200), 0, Qt::DotLine)); + setAngularSubGridPen(QPen(QColor(220,220,220), 0, Qt::DotLine)); + + setRadialPen(QPen(QColor(200,200,200), 0, Qt::DotLine)); + setRadialSubGridPen(QPen(QColor(220,220,220), 0, Qt::DotLine)); + setRadialZeroLinePen(QPen(QColor(200,200,200), 0, Qt::SolidLine)); + + setAntialiased(true); } -/*! - Sets the font of the text that will be used when the item is selected. - - \see setFont -*/ -void QCPItemText::setSelectedFont(const QFont &font) +void QCPPolarGrid::setRadialAxis(QCPPolarAxisRadial *axis) { - mSelectedFont = font; + mRadialAxis = axis; } -/*! - Sets the text that will be displayed. Multi-line texts are supported by inserting a line break - character, e.g. '\n'. - - \see setFont, setColor, setTextAlignment -*/ -void QCPItemText::setText(const QString &text) +void QCPPolarGrid::setType(GridTypes type) { - mText = text; + mType = type; +} + +void QCPPolarGrid::setSubGridType(GridTypes type) +{ + mSubGridType = type; } /*! - Sets which point of the text rect shall be aligned with \a position. - - Examples: - \li If \a alignment is Qt::AlignHCenter | Qt::AlignTop, the text will be positioned such - that the top of the text rect will be horizontally centered on \a position. - \li If \a alignment is Qt::AlignLeft | Qt::AlignBottom, \a position will indicate the - bottom left corner of the text rect. - - If you want to control the alignment of (multi-lined) text within the text rect, use \ref - setTextAlignment. + Sets whether sub grid lines are drawn antialiased. */ -void QCPItemText::setPositionAlignment(Qt::Alignment alignment) +void QCPPolarGrid::setAntialiasedSubGrid(bool enabled) { - mPositionAlignment = alignment; + mAntialiasedSubGrid = enabled; } /*! - Controls how (multi-lined) text is aligned inside the text rect (typically Qt::AlignLeft, Qt::AlignCenter or Qt::AlignRight). + Sets whether zero lines are drawn antialiased. */ -void QCPItemText::setTextAlignment(Qt::Alignment alignment) +void QCPPolarGrid::setAntialiasedZeroLine(bool enabled) { - mTextAlignment = alignment; + mAntialiasedZeroLine = enabled; } /*! - Sets the angle in degrees by which the text (and the text rectangle, if visible) will be rotated - around \a position. + Sets the pen with which (major) grid lines are drawn. */ -void QCPItemText::setRotation(double degrees) +void QCPPolarGrid::setAngularPen(const QPen &pen) { - mRotation = degrees; + mAngularPen = pen; } /*! - Sets the distance between the border of the text rectangle and the text. The appearance (and - visibility) of the text rectangle can be controlled with \ref setPen and \ref setBrush. + Sets the pen with which sub grid lines are drawn. */ -void QCPItemText::setPadding(const QMargins &padding) +void QCPPolarGrid::setAngularSubGridPen(const QPen &pen) { - mPadding = padding; + mAngularSubGridPen = pen; } -/* inherits documentation from base class */ -double QCPItemText::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +void QCPPolarGrid::setRadialPen(const QPen &pen) { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - // The rect may be rotated, so we transform the actual clicked pos to the rotated - // coordinate system, so we can use the normal rectSelectTest function for non-rotated rects: - QPointF positionPixels(position->pixelPoint()); - QTransform inputTransform; - inputTransform.translate(positionPixels.x(), positionPixels.y()); - inputTransform.rotate(-mRotation); - inputTransform.translate(-positionPixels.x(), -positionPixels.y()); - QPointF rotatedPos = inputTransform.map(pos); - QFontMetrics fontMetrics(mFont); - QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText); - QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom()); - QPointF textPos = getTextDrawPoint(positionPixels, textBoxRect, mPositionAlignment); - textBoxRect.moveTopLeft(textPos.toPoint()); - - return rectSelectTest(textBoxRect, rotatedPos, true); + mRadialPen = pen; } -/* inherits documentation from base class */ -void QCPItemText::draw(QCPPainter *painter) +void QCPPolarGrid::setRadialSubGridPen(const QPen &pen) { - QPointF pos(position->pixelPoint()); - QTransform transform = painter->transform(); - transform.translate(pos.x(), pos.y()); - if (!qFuzzyIsNull(mRotation)) - transform.rotate(mRotation); - painter->setFont(mainFont()); - QRect textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText); - QRect textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom()); - QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation - textRect.moveTopLeft(textPos.toPoint()+QPoint(mPadding.left(), mPadding.top())); - textBoxRect.moveTopLeft(textPos.toPoint()); - double clipPad = mainPen().widthF(); - QRect boundingRect = textBoxRect.adjusted(-clipPad, -clipPad, clipPad, clipPad); - if (transform.mapRect(boundingRect).intersects(painter->transform().mapRect(clipRect()))) - { - painter->setTransform(transform); - if ((mainBrush().style() != Qt::NoBrush && mainBrush().color().alpha() != 0) || - (mainPen().style() != Qt::NoPen && mainPen().color().alpha() != 0)) - { - painter->setPen(mainPen()); - painter->setBrush(mainBrush()); - painter->drawRect(textBoxRect); - } - painter->setBrush(Qt::NoBrush); - painter->setPen(QPen(mainColor())); - painter->drawText(textRect, Qt::TextDontClip|mTextAlignment, mText); - } + mRadialSubGridPen = pen; } -/* inherits documentation from base class */ -QPointF QCPItemText::anchorPixelPoint(int anchorId) const +void QCPPolarGrid::setRadialZeroLinePen(const QPen &pen) { - // get actual rect points (pretty much copied from draw function): - QPointF pos(position->pixelPoint()); - QTransform transform; - transform.translate(pos.x(), pos.y()); - if (!qFuzzyIsNull(mRotation)) - transform.rotate(mRotation); - QFontMetrics fontMetrics(mainFont()); - QRect textRect = fontMetrics.boundingRect(0, 0, 0, 0, Qt::TextDontClip|mTextAlignment, mText); - QRectF textBoxRect = textRect.adjusted(-mPadding.left(), -mPadding.top(), mPadding.right(), mPadding.bottom()); - QPointF textPos = getTextDrawPoint(QPointF(0, 0), textBoxRect, mPositionAlignment); // 0, 0 because the transform does the translation - textBoxRect.moveTopLeft(textPos.toPoint()); - QPolygonF rectPoly = transform.map(QPolygonF(textBoxRect)); + mRadialZeroLinePen = pen; +} + +/*! \internal + + A convenience function to easily set the QPainter::Antialiased hint on the provided \a painter + before drawing the major grid lines. + + This is the antialiasing state the painter passed to the \ref draw method is in by default. - switch (anchorId) - { - case aiTopLeft: return rectPoly.at(0); - case aiTop: return (rectPoly.at(0)+rectPoly.at(1))*0.5; - case aiTopRight: return rectPoly.at(1); - case aiRight: return (rectPoly.at(1)+rectPoly.at(2))*0.5; - case aiBottomRight: return rectPoly.at(2); - case aiBottom: return (rectPoly.at(2)+rectPoly.at(3))*0.5; - case aiBottomLeft: return rectPoly.at(3); - case aiLeft: return (rectPoly.at(3)+rectPoly.at(0))*0.5; - } + This function takes into account the local setting of the antialiasing flag as well as the + overrides set with \ref QCustomPlot::setAntialiasedElements and \ref + QCustomPlot::setNotAntialiasedElements. - qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; - return QPointF(); + \see setAntialiased +*/ +void QCPPolarGrid::applyDefaultAntialiasingHint(QCPPainter *painter) const +{ + applyAntialiasingHint(painter, mAntialiased, QCP::aeGrid); } /*! \internal - Returns the point that must be given to the QPainter::drawText function (which expects the top - left point of the text rect), according to the position \a pos, the text bounding box \a rect and - the requested \a positionAlignment. - - For example, if \a positionAlignment is Qt::AlignLeft | Qt::AlignBottom the returned point - will be shifted upward by the height of \a rect, starting from \a pos. So if the text is finally - drawn at that point, the lower left corner of the resulting text rect is at \a pos. + Draws grid lines and sub grid lines at the positions of (sub) ticks of the parent axis, spanning + over the complete axis rect. Also draws the zero line, if appropriate (\ref setZeroLinePen). */ -QPointF QCPItemText::getTextDrawPoint(const QPointF &pos, const QRectF &rect, Qt::Alignment positionAlignment) const +void QCPPolarGrid::draw(QCPPainter *painter) { - if (positionAlignment == 0 || positionAlignment == (Qt::AlignLeft|Qt::AlignTop)) - return pos; + if (!mParentAxis) { qDebug() << Q_FUNC_INFO << "invalid parent axis"; return; } - QPointF result = pos; // start at top left - if (positionAlignment.testFlag(Qt::AlignHCenter)) - result.rx() -= rect.width()/2.0; - else if (positionAlignment.testFlag(Qt::AlignRight)) - result.rx() -= rect.width(); - if (positionAlignment.testFlag(Qt::AlignVCenter)) - result.ry() -= rect.height()/2.0; - else if (positionAlignment.testFlag(Qt::AlignBottom)) - result.ry() -= rect.height(); - return result; + const QPointF center = mParentAxis->mCenter; + const double radius = mParentAxis->mRadius; + + painter->setBrush(Qt::NoBrush); + // draw main angular grid: + if (mType.testFlag(gtAngular)) + drawAngularGrid(painter, center, radius, mParentAxis->mTickVectorCosSin, mAngularPen); + // draw main radial grid: + if (mType.testFlag(gtRadial) && mRadialAxis) + drawRadialGrid(painter, center, mRadialAxis->tickVector(), mRadialPen, mRadialZeroLinePen); + + applyAntialiasingHint(painter, mAntialiasedSubGrid, QCP::aeGrid); + // draw sub angular grid: + if (mSubGridType.testFlag(gtAngular)) + drawAngularGrid(painter, center, radius, mParentAxis->mSubTickVectorCosSin, mAngularSubGridPen); + // draw sub radial grid: + if (mSubGridType.testFlag(gtRadial) && mRadialAxis) + drawRadialGrid(painter, center, mRadialAxis->subTickVector(), mRadialSubGridPen); } -/*! \internal +void QCPPolarGrid::drawRadialGrid(QCPPainter *painter, const QPointF ¢er, const QVector &coords, const QPen &pen, const QPen &zeroPen) +{ + if (!mRadialAxis) return; + if (coords.isEmpty()) return; + const bool drawZeroLine = zeroPen != Qt::NoPen; + const double zeroLineEpsilon = qAbs(coords.last()-coords.first())*1e-6; + + painter->setPen(pen); + for (int i=0; icoordToRadius(coords.at(i)); + if (drawZeroLine && qAbs(coords.at(i)) < zeroLineEpsilon) + { + applyAntialiasingHint(painter, mAntialiasedZeroLine, QCP::aeZeroLine); + painter->setPen(zeroPen); + painter->drawEllipse(center, r, r); + painter->setPen(pen); + applyDefaultAntialiasingHint(painter); + } else + { + painter->drawEllipse(center, r, r); + } + } +} - Returns the font that should be used for drawing text. Returns mFont when the item is not selected - and mSelectedFont when it is. -*/ -QFont QCPItemText::mainFont() const +void QCPPolarGrid::drawAngularGrid(QCPPainter *painter, const QPointF ¢er, double radius, const QVector &ticksCosSin, const QPen &pen) { - return mSelected ? mSelectedFont : mFont; + if (ticksCosSin.isEmpty()) return; + + painter->setPen(pen); + for (int i=0; idrawLine(center, center+ticksCosSin.at(i)*radius); } +/* end of 'src/polar/polargrid.cpp' */ -/*! \internal - Returns the color that should be used for drawing text. Returns mColor when the item is not - selected and mSelectedColor when it is. +/* including file 'src/polar/polargraph.cpp' */ +/* modified 2022-11-06T12:45:57, size 44035 */ + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPPolarLegendItem +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPPolarLegendItem + \brief A legend item for polar plots + + \warning In this QCustomPlot version, polar plots are a tech preview. Expect documentation and + functionality to be incomplete, as well as changing public interfaces in the future. */ -QColor QCPItemText::mainColor() const +QCPPolarLegendItem::QCPPolarLegendItem(QCPLegend *parent, QCPPolarGraph *graph) : + QCPAbstractLegendItem(parent), + mPolarGraph(graph) { - return mSelected ? mSelectedColor : mColor; + setAntialiased(false); } -/*! \internal +void QCPPolarLegendItem::draw(QCPPainter *painter) +{ + if (!mPolarGraph) return; + painter->setFont(getFont()); + painter->setPen(QPen(getTextColor())); + QSizeF iconSize = mParentLegend->iconSize(); + QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPolarGraph->name()); + QRectF iconRect(mRect.topLeft(), iconSize); + int textHeight = qMax(textRect.height(), iconSize.height()); // if text has smaller height than icon, center text vertically in icon height, else align tops + painter->drawText(mRect.x()+iconSize.width()+mParentLegend->iconTextPadding(), mRect.y(), textRect.width(), textHeight, Qt::TextDontClip, mPolarGraph->name()); + // draw icon: + painter->save(); + painter->setClipRect(iconRect, Qt::IntersectClip); + mPolarGraph->drawLegendIcon(painter, iconRect); + painter->restore(); + // draw icon border: + if (getIconBorderPen().style() != Qt::NoPen) + { + painter->setPen(getIconBorderPen()); + painter->setBrush(Qt::NoBrush); + int halfPen = qCeil(painter->pen().widthF()*0.5)+1; + painter->setClipRect(mOuterRect.adjusted(-halfPen, -halfPen, halfPen, halfPen)); // extend default clip rect so thicker pens (especially during selection) are not clipped + painter->drawRect(iconRect); + } +} - Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected - and mSelectedPen when it is. -*/ -QPen QCPItemText::mainPen() const +QSize QCPPolarLegendItem::minimumOuterSizeHint() const { - return mSelected ? mSelectedPen : mPen; + if (!mPolarGraph) return QSize(); + QSize result(0, 0); + QRect textRect; + QFontMetrics fontMetrics(getFont()); + QSize iconSize = mParentLegend->iconSize(); + textRect = fontMetrics.boundingRect(0, 0, 0, iconSize.height(), Qt::TextDontClip, mPolarGraph->name()); + result.setWidth(iconSize.width() + mParentLegend->iconTextPadding() + textRect.width()); + result.setHeight(qMax(textRect.height(), iconSize.height())); + result.rwidth() += mMargins.left()+mMargins.right(); + result.rheight() += mMargins.top()+mMargins.bottom(); + return result; } -/*! \internal +QPen QCPPolarLegendItem::getIconBorderPen() const +{ + return mSelected ? mParentLegend->selectedIconBorderPen() : mParentLegend->iconBorderPen(); +} - Returns the brush that should be used for drawing fills of the item. Returns mBrush when the item - is not selected and mSelectedBrush when it is. -*/ -QBrush QCPItemText::mainBrush() const +QColor QCPPolarLegendItem::getTextColor() const { - return mSelected ? mSelectedBrush : mBrush; + return mSelected ? mSelectedTextColor : mTextColor; +} + +QFont QCPPolarLegendItem::getFont() const +{ + return mSelected ? mSelectedFont : mFont; } //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPItemEllipse +//////////////////// QCPPolarGraph //////////////////////////////////////////////////////////////////////////////////////////////////// -/*! \class QCPItemEllipse - \brief An ellipse - - \image html QCPItemEllipse.png "Ellipse example. Blue dotted circles are anchors, solid blue discs are positions." +/*! \class QCPPolarGraph + \brief A radial graph used to display data in polar plots - It has two positions, \a topLeft and \a bottomRight, which define the rect the ellipse will be drawn in. + \warning In this QCustomPlot version, polar plots are a tech preview. Expect documentation and + functionality to be incomplete, as well as changing public interfaces in the future. */ +/* start of documentation of inline functions */ + +// TODO + +/* end of documentation of inline functions */ + /*! - Creates an ellipse item and sets default values. - - The constructed item can be added to the plot with QCustomPlot::addItem. + Constructs a graph which uses \a keyAxis as its angular and \a valueAxis as its radial axis. \a + keyAxis and \a valueAxis must reside in the same QCustomPlot, and the radial axis must be + associated with the angular axis. If either of these restrictions is violated, a corresponding + message is printed to the debug output (qDebug), the construction is not aborted, though. + + The created QCPPolarGraph is automatically registered with the QCustomPlot instance inferred from + \a keyAxis. This QCustomPlot instance takes ownership of the QCPPolarGraph, so do not delete it + manually but use QCPPolarAxisAngular::removeGraph() instead. + + To directly create a QCPPolarGraph inside a plot, you shoud use the QCPPolarAxisAngular::addGraph + method. */ -QCPItemEllipse::QCPItemEllipse(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - topLeft(createPosition(QLatin1String("topLeft"))), - bottomRight(createPosition(QLatin1String("bottomRight"))), - topLeftRim(createAnchor(QLatin1String("topLeftRim"), aiTopLeftRim)), - top(createAnchor(QLatin1String("top"), aiTop)), - topRightRim(createAnchor(QLatin1String("topRightRim"), aiTopRightRim)), - right(createAnchor(QLatin1String("right"), aiRight)), - bottomRightRim(createAnchor(QLatin1String("bottomRightRim"), aiBottomRightRim)), - bottom(createAnchor(QLatin1String("bottom"), aiBottom)), - bottomLeftRim(createAnchor(QLatin1String("bottomLeftRim"), aiBottomLeftRim)), - left(createAnchor(QLatin1String("left"), aiLeft)), - center(createAnchor(QLatin1String("center"), aiCenter)) +QCPPolarGraph::QCPPolarGraph(QCPPolarAxisAngular *keyAxis, QCPPolarAxisRadial *valueAxis) : + QCPLayerable(keyAxis->parentPlot(), QString(), keyAxis), + mDataContainer(new QCPGraphDataContainer), + mName(), + mAntialiasedFill(true), + mAntialiasedScatters(true), + mPen(Qt::black), + mBrush(Qt::NoBrush), + mPeriodic(true), + mKeyAxis(keyAxis), + mValueAxis(valueAxis), + mSelectable(QCP::stWhole) + //mSelectionDecorator(0) // TODO { - topLeft->setCoords(0, 1); - bottomRight->setCoords(1, 0); + if (keyAxis->parentPlot() != valueAxis->parentPlot()) + qDebug() << Q_FUNC_INFO << "Parent plot of keyAxis is not the same as that of valueAxis."; - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue, 2)); + mKeyAxis->registerPolarGraph(this); + + //setSelectionDecorator(new QCPSelectionDecorator); // TODO + + setPen(QPen(Qt::blue, 0)); setBrush(Qt::NoBrush); - setSelectedBrush(Qt::NoBrush); + setLineStyle(lsLine); } -QCPItemEllipse::~QCPItemEllipse() +QCPPolarGraph::~QCPPolarGraph() { + /* TODO + if (mSelectionDecorator) + { + delete mSelectionDecorator; + mSelectionDecorator = 0; + } + */ } /*! - Sets the pen that will be used to draw the line of the ellipse - - \see setSelectedPen, setBrush + The name is the textual representation of this plottable as it is displayed in the legend + (\ref QCPLegend). It may contain any UTF-8 characters, including newlines. */ -void QCPItemEllipse::setPen(const QPen &pen) +void QCPPolarGraph::setName(const QString &name) { - mPen = pen; + mName = name; } /*! - Sets the pen that will be used to draw the line of the ellipse when selected + Sets whether fills of this plottable are drawn antialiased or not. - \see setPen, setSelected + Note that this setting may be overridden by \ref QCustomPlot::setAntialiasedElements and \ref + QCustomPlot::setNotAntialiasedElements. */ -void QCPItemEllipse::setSelectedPen(const QPen &pen) +void QCPPolarGraph::setAntialiasedFill(bool enabled) { - mSelectedPen = pen; + mAntialiasedFill = enabled; } /*! - Sets the brush that will be used to fill the ellipse. To disable filling, set \a brush to - Qt::NoBrush. + Sets whether the scatter symbols of this plottable are drawn antialiased or not. - \see setSelectedBrush, setPen + Note that this setting may be overridden by \ref QCustomPlot::setAntialiasedElements and \ref + QCustomPlot::setNotAntialiasedElements. */ -void QCPItemEllipse::setBrush(const QBrush &brush) +void QCPPolarGraph::setAntialiasedScatters(bool enabled) { - mBrush = brush; + mAntialiasedScatters = enabled; } /*! - Sets the brush that will be used to fill the ellipse when selected. To disable filling, set \a - brush to Qt::NoBrush. + The pen is used to draw basic lines that make up the plottable representation in the + plot. + For example, the \ref QCPGraph subclass draws its graph lines with this pen. + \see setBrush */ -void QCPItemEllipse::setSelectedBrush(const QBrush &brush) +void QCPPolarGraph::setPen(const QPen &pen) { - mSelectedBrush = brush; + mPen = pen; } -/* inherits documentation from base class */ -double QCPItemEllipse::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const -{ - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - double result = -1; - QPointF p1 = topLeft->pixelPoint(); - QPointF p2 = bottomRight->pixelPoint(); - QPointF center((p1+p2)/2.0); - double a = qAbs(p1.x()-p2.x())/2.0; - double b = qAbs(p1.y()-p2.y())/2.0; - double x = pos.x()-center.x(); - double y = pos.y()-center.y(); +/*! + The brush is used to draw basic fills of the plottable representation in the + plot. The Fill can be a color, gradient or texture, see the usage of QBrush. - // distance to border: - double c = 1.0/qSqrt(x*x/(a*a)+y*y/(b*b)); - result = qAbs(c-1)*qSqrt(x*x+y*y); - // filled ellipse, allow click inside to count as hit: - if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0) - { - if (x*x/(a*a) + y*y/(b*b) <= 1) - result = mParentPlot->selectionTolerance()*0.99; - } - return result; -} + For example, the \ref QCPGraph subclass draws the fill under the graph with this brush, when + it's not set to Qt::NoBrush. -/* inherits documentation from base class */ -void QCPItemEllipse::draw(QCPPainter *painter) + \see setPen +*/ +void QCPPolarGraph::setBrush(const QBrush &brush) { - QPointF p1 = topLeft->pixelPoint(); - QPointF p2 = bottomRight->pixelPoint(); - if (p1.toPoint() == p2.toPoint()) - return; - QRectF ellipseRect = QRectF(p1, p2).normalized(); - QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF()); - if (ellipseRect.intersects(clip)) // only draw if bounding rect of ellipse is visible in cliprect - { - painter->setPen(mainPen()); - painter->setBrush(mainBrush()); -#ifdef __EXCEPTIONS - try // drawEllipse sometimes throws exceptions if ellipse is too big - { -#endif - painter->drawEllipse(ellipseRect); -#ifdef __EXCEPTIONS - } catch (...) - { - qDebug() << Q_FUNC_INFO << "Item too large for memory, setting invisible"; - setVisible(false); - } -#endif - } + mBrush = brush; } -/* inherits documentation from base class */ -QPointF QCPItemEllipse::anchorPixelPoint(int anchorId) const +void QCPPolarGraph::setPeriodic(bool enabled) { - QRectF rect = QRectF(topLeft->pixelPoint(), bottomRight->pixelPoint()); - switch (anchorId) - { - case aiTopLeftRim: return rect.center()+(rect.topLeft()-rect.center())*1/qSqrt(2); - case aiTop: return (rect.topLeft()+rect.topRight())*0.5; - case aiTopRightRim: return rect.center()+(rect.topRight()-rect.center())*1/qSqrt(2); - case aiRight: return (rect.topRight()+rect.bottomRight())*0.5; - case aiBottomRightRim: return rect.center()+(rect.bottomRight()-rect.center())*1/qSqrt(2); - case aiBottom: return (rect.bottomLeft()+rect.bottomRight())*0.5; - case aiBottomLeftRim: return rect.center()+(rect.bottomLeft()-rect.center())*1/qSqrt(2); - case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5; - case aiCenter: return (rect.topLeft()+rect.bottomRight())*0.5; - } - - qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; - return QPointF(); + mPeriodic = enabled; } -/*! \internal +/*! + The key axis of a plottable can be set to any axis of a QCustomPlot, as long as it is orthogonal + to the plottable's value axis. This function performs no checks to make sure this is the case. + The typical mathematical choice is to use the x-axis (QCustomPlot::xAxis) as key axis and the + y-axis (QCustomPlot::yAxis) as value axis. + + Normally, the key and value axes are set in the constructor of the plottable (or \ref + QCustomPlot::addGraph when working with QCPGraphs through the dedicated graph interface). - Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected - and mSelectedPen when it is. + \see setValueAxis */ -QPen QCPItemEllipse::mainPen() const +void QCPPolarGraph::setKeyAxis(QCPPolarAxisAngular *axis) { - return mSelected ? mSelectedPen : mPen; + mKeyAxis = axis; } -/*! \internal +/*! + The value axis of a plottable can be set to any axis of a QCustomPlot, as long as it is + orthogonal to the plottable's key axis. This function performs no checks to make sure this is the + case. The typical mathematical choice is to use the x-axis (QCustomPlot::xAxis) as key axis and + the y-axis (QCustomPlot::yAxis) as value axis. - Returns the brush that should be used for drawing fills of the item. Returns mBrush when the item - is not selected and mSelectedBrush when it is. + Normally, the key and value axes are set in the constructor of the plottable (or \ref + QCustomPlot::addGraph when working with QCPGraphs through the dedicated graph interface). + + \see setKeyAxis */ -QBrush QCPItemEllipse::mainBrush() const +void QCPPolarGraph::setValueAxis(QCPPolarAxisRadial *axis) { - return mSelected ? mSelectedBrush : mBrush; + mValueAxis = axis; } - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPItemPixmap -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPItemPixmap - \brief An arbitrary pixmap - - \image html QCPItemPixmap.png "Pixmap example. Blue dotted circles are anchors, solid blue discs are positions." - - It has two positions, \a topLeft and \a bottomRight, which define the rectangle the pixmap will - be drawn in. Depending on the scale setting (\ref setScaled), the pixmap will be either scaled to - fit the rectangle or be drawn aligned to the topLeft position. - - If scaling is enabled and \a topLeft is further to the bottom/right than \a bottomRight (as shown - on the right side of the example image), the pixmap will be flipped in the respective - orientations. -*/ - /*! - Creates a rectangle item and sets default values. + Sets whether and to which granularity this plottable can be selected. + + A selection can happen by clicking on the QCustomPlot surface (When \ref + QCustomPlot::setInteractions contains \ref QCP::iSelectPlottables), by dragging a selection rect + (When \ref QCustomPlot::setSelectionRectMode is \ref QCP::srmSelect), or programmatically by + calling \ref setSelection. - The constructed item can be added to the plot with QCustomPlot::addItem. + \see setSelection, QCP::SelectionType */ -QCPItemPixmap::QCPItemPixmap(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - topLeft(createPosition(QLatin1String("topLeft"))), - bottomRight(createPosition(QLatin1String("bottomRight"))), - top(createAnchor(QLatin1String("top"), aiTop)), - topRight(createAnchor(QLatin1String("topRight"), aiTopRight)), - right(createAnchor(QLatin1String("right"), aiRight)), - bottom(createAnchor(QLatin1String("bottom"), aiBottom)), - bottomLeft(createAnchor(QLatin1String("bottomLeft"), aiBottomLeft)), - left(createAnchor(QLatin1String("left"), aiLeft)) -{ - topLeft->setCoords(0, 1); - bottomRight->setCoords(1, 0); - - setPen(Qt::NoPen); - setSelectedPen(QPen(Qt::blue)); - setScaled(false, Qt::KeepAspectRatio, Qt::SmoothTransformation); -} - -QCPItemPixmap::~QCPItemPixmap() +void QCPPolarGraph::setSelectable(QCP::SelectionType selectable) { + if (mSelectable != selectable) + { + mSelectable = selectable; + QCPDataSelection oldSelection = mSelection; + mSelection.enforceType(mSelectable); + emit selectableChanged(mSelectable); + if (mSelection != oldSelection) + { + emit selectionChanged(selected()); + emit selectionChanged(mSelection); + } + } } /*! - Sets the pixmap that will be displayed. + Sets which data ranges of this plottable are selected. Selected data ranges are drawn differently + (e.g. color) in the plot. This can be controlled via the selection decorator (see \ref + selectionDecorator). + + The entire selection mechanism for plottables is handled automatically when \ref + QCustomPlot::setInteractions contains iSelectPlottables. You only need to call this function when + you wish to change the selection state programmatically. + + Using \ref setSelectable you can further specify for each plottable whether and to which + granularity it is selectable. If \a selection is not compatible with the current \ref + QCP::SelectionType set via \ref setSelectable, the resulting selection will be adjusted + accordingly (see \ref QCPDataSelection::enforceType). + + emits the \ref selectionChanged signal when \a selected is different from the previous selection state. + + \see setSelectable, selectTest */ -void QCPItemPixmap::setPixmap(const QPixmap &pixmap) +void QCPPolarGraph::setSelection(QCPDataSelection selection) { - mPixmap = pixmap; - if (mPixmap.isNull()) - qDebug() << Q_FUNC_INFO << "pixmap is null"; + selection.enforceType(mSelectable); + if (mSelection != selection) + { + mSelection = selection; + emit selectionChanged(selected()); + emit selectionChanged(mSelection); + } } -/*! - Sets whether the pixmap will be scaled to fit the rectangle defined by the \a topLeft and \a - bottomRight positions. +/*! \overload + + Replaces the current data container with the provided \a data container. + + Since a QSharedPointer is used, multiple QCPPolarGraphs may share the same data container safely. + Modifying the data in the container will then affect all graphs that share the container. Sharing + can be achieved by simply exchanging the data containers wrapped in shared pointers: + \snippet documentation/doc-code-snippets/mainwindow.cpp QCPPolarGraph-datasharing-1 + + If you do not wish to share containers, but create a copy from an existing container, rather use + the \ref QCPDataContainer::set method on the graph's data container directly: + \snippet documentation/doc-code-snippets/mainwindow.cpp QCPPolarGraph-datasharing-2 + + \see addData */ -void QCPItemPixmap::setScaled(bool scaled, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode) +void QCPPolarGraph::setData(QSharedPointer data) { - mScaled = scaled; - mAspectRatioMode = aspectRatioMode; - mTransformationMode = transformationMode; - updateScaledPixmap(); + mDataContainer = data; } -/*! - Sets the pen that will be used to draw a border around the pixmap. +/*! \overload - \see setSelectedPen, setBrush + Replaces the current data with the provided points in \a keys and \a values. The provided + vectors should have equal length. Else, the number of added points will be the size of the + smallest vector. + + If you can guarantee that the passed data points are sorted by \a keys in ascending order, you + can set \a alreadySorted to true, to improve performance by saving a sorting run. + + \see addData */ -void QCPItemPixmap::setPen(const QPen &pen) +void QCPPolarGraph::setData(const QVector &keys, const QVector &values, bool alreadySorted) { - mPen = pen; + mDataContainer->clear(); + addData(keys, values, alreadySorted); } /*! - Sets the pen that will be used to draw a border around the pixmap when selected + Sets how the single data points are connected in the plot. For scatter-only plots, set \a ls to + \ref lsNone and \ref setScatterStyle to the desired scatter style. - \see setPen, setSelected + \see setScatterStyle */ -void QCPItemPixmap::setSelectedPen(const QPen &pen) +void QCPPolarGraph::setLineStyle(LineStyle ls) { - mSelectedPen = pen; -} - -/* inherits documentation from base class */ -double QCPItemPixmap::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const -{ - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - return rectSelectTest(getFinalRect(), pos, true); + mLineStyle = ls; } -/* inherits documentation from base class */ -void QCPItemPixmap::draw(QCPPainter *painter) -{ - bool flipHorz = false; - bool flipVert = false; - QRect rect = getFinalRect(&flipHorz, &flipVert); - double clipPad = mainPen().style() == Qt::NoPen ? 0 : mainPen().widthF(); - QRect boundingRect = rect.adjusted(-clipPad, -clipPad, clipPad, clipPad); - if (boundingRect.intersects(clipRect())) - { - updateScaledPixmap(rect, flipHorz, flipVert); - painter->drawPixmap(rect.topLeft(), mScaled ? mScaledPixmap : mPixmap); - QPen pen = mainPen(); - if (pen.style() != Qt::NoPen) - { - painter->setPen(pen); - painter->setBrush(Qt::NoBrush); - painter->drawRect(rect); - } - } +/*! + Sets the visual appearance of single data points in the plot. If set to \ref QCPScatterStyle::ssNone, no scatter points + are drawn (e.g. for line-only-plots with appropriate line style). + + \see QCPScatterStyle, setLineStyle +*/ +void QCPPolarGraph::setScatterStyle(const QCPScatterStyle &style) +{ + mScatterStyle = style; } -/* inherits documentation from base class */ -QPointF QCPItemPixmap::anchorPixelPoint(int anchorId) const +void QCPPolarGraph::addData(const QVector &keys, const QVector &values, bool alreadySorted) { - bool flipHorz; - bool flipVert; - QRect rect = getFinalRect(&flipHorz, &flipVert); - // we actually want denormal rects (negative width/height) here, so restore - // the flipped state: - if (flipHorz) - rect.adjust(rect.width(), 0, -rect.width(), 0); - if (flipVert) - rect.adjust(0, rect.height(), 0, -rect.height()); - - switch (anchorId) + if (keys.size() != values.size()) + qDebug() << Q_FUNC_INFO << "keys and values have different sizes:" << keys.size() << values.size(); + const int n = qMin(keys.size(), values.size()); + QVector tempData(n); + QVector::iterator it = tempData.begin(); + const QVector::iterator itEnd = tempData.end(); + int i = 0; + while (it != itEnd) { - case aiTop: return (rect.topLeft()+rect.topRight())*0.5; - case aiTopRight: return rect.topRight(); - case aiRight: return (rect.topRight()+rect.bottomRight())*0.5; - case aiBottom: return (rect.bottomLeft()+rect.bottomRight())*0.5; - case aiBottomLeft: return rect.bottomLeft(); - case aiLeft: return (rect.topLeft()+rect.bottomLeft())*0.5;; + it->key = keys[i]; + it->value = values[i]; + ++it; + ++i; } - - qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; - return QPointF(); + mDataContainer->add(tempData, alreadySorted); // don't modify tempData beyond this to prevent copy on write } -/*! \internal - - Creates the buffered scaled image (\a mScaledPixmap) to fit the specified \a finalRect. The - parameters \a flipHorz and \a flipVert control whether the resulting image shall be flipped - horizontally or vertically. (This is used when \a topLeft is further to the bottom/right than \a - bottomRight.) +void QCPPolarGraph::addData(double key, double value) +{ + mDataContainer->add(QCPGraphData(key, value)); +} + +/*! + Use this method to set an own QCPSelectionDecorator (subclass) instance. This allows you to + customize the visual representation of selected data ranges further than by using the default + QCPSelectionDecorator. - This function only creates the scaled pixmap when the buffered pixmap has a different size than - the expected result, so calling this function repeatedly, e.g. in the \ref draw function, does - not cause expensive rescaling every time. + The plottable takes ownership of the \a decorator. - If scaling is disabled, sets mScaledPixmap to a null QPixmap. + The currently set decorator can be accessed via \ref selectionDecorator. */ -void QCPItemPixmap::updateScaledPixmap(QRect finalRect, bool flipHorz, bool flipVert) +/* +void QCPPolarGraph::setSelectionDecorator(QCPSelectionDecorator *decorator) { - if (mPixmap.isNull()) - return; - - if (mScaled) + if (decorator) { - if (finalRect.isNull()) - finalRect = getFinalRect(&flipHorz, &flipVert); - if (finalRect.size() != mScaledPixmap.size()) + if (decorator->registerWithPlottable(this)) { - mScaledPixmap = mPixmap.scaled(finalRect.size(), mAspectRatioMode, mTransformationMode); - if (flipHorz || flipVert) - mScaledPixmap = QPixmap::fromImage(mScaledPixmap.toImage().mirrored(flipHorz, flipVert)); + if (mSelectionDecorator) // delete old decorator if necessary + delete mSelectionDecorator; + mSelectionDecorator = decorator; } - } else if (!mScaledPixmap.isNull()) - mScaledPixmap = QPixmap(); + } else if (mSelectionDecorator) // just clear decorator + { + delete mSelectionDecorator; + mSelectionDecorator = 0; + } } - -/*! \internal - - Returns the final (tight) rect the pixmap is drawn in, depending on the current item positions - and scaling settings. - - The output parameters \a flippedHorz and \a flippedVert return whether the pixmap should be drawn - flipped horizontally or vertically in the returned rect. (The returned rect itself is always - normalized, i.e. the top left corner of the rect is actually further to the top/left than the - bottom right corner). This is the case when the item position \a topLeft is further to the - bottom/right than \a bottomRight. - - If scaling is disabled, returns a rect with size of the original pixmap and the top left corner - aligned with the item position \a topLeft. The position \a bottomRight is ignored. */ -QRect QCPItemPixmap::getFinalRect(bool *flippedHorz, bool *flippedVert) const + +void QCPPolarGraph::coordsToPixels(double key, double value, double &x, double &y) const { - QRect result; - bool flipHorz = false; - bool flipVert = false; - QPoint p1 = topLeft->pixelPoint().toPoint(); - QPoint p2 = bottomRight->pixelPoint().toPoint(); - if (p1 == p2) - return QRect(p1, QSize(0, 0)); - if (mScaled) + if (mValueAxis) { - QSize newSize = QSize(p2.x()-p1.x(), p2.y()-p1.y()); - QPoint topLeft = p1; - if (newSize.width() < 0) - { - flipHorz = true; - newSize.rwidth() *= -1; - topLeft.setX(p2.x()); - } - if (newSize.height() < 0) - { - flipVert = true; - newSize.rheight() *= -1; - topLeft.setY(p2.y()); - } - QSize scaledSize = mPixmap.size(); - scaledSize.scale(newSize, mAspectRatioMode); - result = QRect(topLeft, scaledSize); + const QPointF point = mValueAxis->coordToPixel(key, value); + x = point.x(); + y = point.y(); } else { - result = QRect(p1, mPixmap.size()); + qDebug() << Q_FUNC_INFO << "invalid key or value axis"; } - if (flippedHorz) - *flippedHorz = flipHorz; - if (flippedVert) - *flippedVert = flipVert; - return result; } -/*! \internal - - Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected - and mSelectedPen when it is. -*/ -QPen QCPItemPixmap::mainPen() const +const QPointF QCPPolarGraph::coordsToPixels(double key, double value) const { - return mSelected ? mSelectedPen : mPen; + if (mValueAxis) + { + return mValueAxis->coordToPixel(key, value); + } else + { + qDebug() << Q_FUNC_INFO << "invalid key or value axis"; + return QPointF(); + } } +void QCPPolarGraph::pixelsToCoords(double x, double y, double &key, double &value) const +{ + if (mValueAxis) + { + mValueAxis->pixelToCoord(QPointF(x, y), key, value); + } else + { + qDebug() << Q_FUNC_INFO << "invalid key or value axis"; + } +} -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPItemTracer -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPItemTracer - \brief Item that sticks to QCPGraph data points +void QCPPolarGraph::pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const +{ + if (mValueAxis) + { + mValueAxis->pixelToCoord(pixelPos, key, value); + } else + { + qDebug() << Q_FUNC_INFO << "invalid key or value axis"; + } +} - \image html QCPItemTracer.png "Tracer example. Blue dotted circles are anchors, solid blue discs are positions." +void QCPPolarGraph::rescaleAxes(bool onlyEnlarge) const +{ + rescaleKeyAxis(onlyEnlarge); + rescaleValueAxis(onlyEnlarge); +} - The tracer can be connected with a QCPGraph via \ref setGraph. Then it will automatically adopt - the coordinate axes of the graph and update its \a position to be on the graph's data. This means - the key stays controllable via \ref setGraphKey, but the value will follow the graph data. If a - QCPGraph is connected, note that setting the coordinates of the tracer item directly via \a - position will have no effect because they will be overriden in the next redraw (this is when the - coordinate update happens). - - If the specified key in \ref setGraphKey is outside the key bounds of the graph, the tracer will - stay at the corresponding end of the graph. +void QCPPolarGraph::rescaleKeyAxis(bool onlyEnlarge) const +{ + QCPPolarAxisAngular *keyAxis = mKeyAxis.data(); + if (!keyAxis) { qDebug() << Q_FUNC_INFO << "invalid key axis"; return; } - With \ref setInterpolating you may specify whether the tracer may only stay exactly on data - points or whether it interpolates data points linearly, if given a key that lies between two data - points of the graph. + bool foundRange; + QCPRange newRange = getKeyRange(foundRange, QCP::sdBoth); + if (foundRange) + { + if (onlyEnlarge) + newRange.expand(keyAxis->range()); + if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable + { + double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason + newRange.lower = center-keyAxis->range().size()/2.0; + newRange.upper = center+keyAxis->range().size()/2.0; + } + keyAxis->setRange(newRange); + } +} + +void QCPPolarGraph::rescaleValueAxis(bool onlyEnlarge, bool inKeyRange) const +{ + QCPPolarAxisAngular *keyAxis = mKeyAxis.data(); + QCPPolarAxisRadial *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - The tracer has different visual styles, see \ref setStyle. It is also possible to make the tracer - have no own visual appearance (set the style to \ref tsNone), and just connect other item - positions to the tracer \a position (used as an anchor) via \ref - QCPItemPosition::setParentAnchor. + QCP::SignDomain signDomain = QCP::sdBoth; + if (valueAxis->scaleType() == QCPPolarAxisRadial::stLogarithmic) + signDomain = (valueAxis->range().upper < 0 ? QCP::sdNegative : QCP::sdPositive); - \note The tracer position is only automatically updated upon redraws. So when the data of the - graph changes and immediately afterwards (without a redraw) the a position coordinates of the - tracer are retrieved, they will not reflect the updated data of the graph. In this case \ref - updatePosition must be called manually, prior to reading the tracer coordinates. -*/ + bool foundRange; + QCPRange newRange = getValueRange(foundRange, signDomain, inKeyRange ? keyAxis->range() : QCPRange()); + if (foundRange) + { + if (onlyEnlarge) + newRange.expand(valueAxis->range()); + if (!QCPRange::validRange(newRange)) // likely due to range being zero (plottable has only constant data in this axis dimension), shift current range to at least center the plottable + { + double center = (newRange.lower+newRange.upper)*0.5; // upper and lower should be equal anyway, but just to make sure, incase validRange returned false for other reason + if (valueAxis->scaleType() == QCPPolarAxisRadial::stLinear) + { + newRange.lower = center-valueAxis->range().size()/2.0; + newRange.upper = center+valueAxis->range().size()/2.0; + } else // scaleType() == stLogarithmic + { + newRange.lower = center/qSqrt(valueAxis->range().upper/valueAxis->range().lower); + newRange.upper = center*qSqrt(valueAxis->range().upper/valueAxis->range().lower); + } + } + valueAxis->setRange(newRange); + } +} -/*! - Creates a tracer item and sets default values. - - The constructed item can be added to the plot with QCustomPlot::addItem. -*/ -QCPItemTracer::QCPItemTracer(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - position(createPosition(QLatin1String("position"))), - mGraph(0) +bool QCPPolarGraph::addToLegend(QCPLegend *legend) { - position->setCoords(0, 0); - - setBrush(Qt::NoBrush); - setSelectedBrush(Qt::NoBrush); - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue, 2)); - setStyle(tsCrosshair); - setSize(6); - setInterpolating(false); - setGraphKey(0); + if (!legend) + { + qDebug() << Q_FUNC_INFO << "passed legend is null"; + return false; + } + if (legend->parentPlot() != mParentPlot) + { + qDebug() << Q_FUNC_INFO << "passed legend isn't in the same QCustomPlot as this plottable"; + return false; + } + + //if (!legend->hasItemWithPlottable(this)) // TODO + //{ + legend->addItem(new QCPPolarLegendItem(legend, this)); + return true; + //} else + // return false; } -QCPItemTracer::~QCPItemTracer() +bool QCPPolarGraph::addToLegend() { + if (!mParentPlot || !mParentPlot->legend) + return false; + else + return addToLegend(mParentPlot->legend); } -/*! - Sets the pen that will be used to draw the line of the tracer - - \see setSelectedPen, setBrush -*/ -void QCPItemTracer::setPen(const QPen &pen) +bool QCPPolarGraph::removeFromLegend(QCPLegend *legend) const { - mPen = pen; + if (!legend) + { + qDebug() << Q_FUNC_INFO << "passed legend is null"; + return false; + } + + + QCPPolarLegendItem *removableItem = 0; + for (int i=0; iitemCount(); ++i) // TODO: reduce this to code in QCPAbstractPlottable::removeFromLegend once unified + { + if (QCPPolarLegendItem *pli = qobject_cast(legend->item(i))) + { + if (pli->polarGraph() == this) + { + removableItem = pli; + break; + } + } + } + + if (removableItem) + return legend->removeItem(removableItem); + else + return false; } -/*! - Sets the pen that will be used to draw the line of the tracer when selected - - \see setPen, setSelected -*/ -void QCPItemTracer::setSelectedPen(const QPen &pen) +bool QCPPolarGraph::removeFromLegend() const { - mSelectedPen = pen; + if (!mParentPlot || !mParentPlot->legend) + return false; + else + return removeFromLegend(mParentPlot->legend); } -/*! - Sets the brush that will be used to draw any fills of the tracer - - \see setSelectedBrush, setPen -*/ -void QCPItemTracer::setBrush(const QBrush &brush) +double QCPPolarGraph::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const { - mBrush = brush; + if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty()) + return -1; + if (!mKeyAxis || !mValueAxis) + return -1; + + if (mKeyAxis->rect().contains(pos.toPoint())) + { + QCPGraphDataContainer::const_iterator closestDataPoint = mDataContainer->constEnd(); + double result = pointDistance(pos, closestDataPoint); + if (details) + { + int pointIndex = closestDataPoint-mDataContainer->constBegin(); + details->setValue(QCPDataSelection(QCPDataRange(pointIndex, pointIndex+1))); + } + return result; + } else + return -1; } -/*! - Sets the brush that will be used to draw any fills of the tracer, when selected. - - \see setBrush, setSelected -*/ -void QCPItemTracer::setSelectedBrush(const QBrush &brush) +/* inherits documentation from base class */ +QCPRange QCPPolarGraph::getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain) const { - mSelectedBrush = brush; + return mDataContainer->keyRange(foundRange, inSignDomain); } -/*! - Sets the size of the tracer in pixels, if the style supports setting a size (e.g. \ref tsSquare - does, \ref tsCrosshair does not). -*/ -void QCPItemTracer::setSize(double size) +/* inherits documentation from base class */ +QCPRange QCPPolarGraph::getValueRange(bool &foundRange, QCP::SignDomain inSignDomain, const QCPRange &inKeyRange) const { - mSize = size; + return mDataContainer->valueRange(foundRange, inSignDomain, inKeyRange); } -/*! - Sets the style/visual appearance of the tracer. - - If you only want to use the tracer \a position as an anchor for other items, set \a style to - \ref tsNone. -*/ -void QCPItemTracer::setStyle(QCPItemTracer::TracerStyle style) +/* inherits documentation from base class */ +QRect QCPPolarGraph::clipRect() const { - mStyle = style; + if (mKeyAxis) + return mKeyAxis.data()->rect(); + else + return QRect(); } -/*! - Sets the QCPGraph this tracer sticks to. The tracer \a position will be set to type - QCPItemPosition::ptPlotCoords and the axes will be set to the axes of \a graph. +void QCPPolarGraph::draw(QCPPainter *painter) +{ + if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + if (mKeyAxis.data()->range().size() <= 0 || mDataContainer->isEmpty()) return; + if (mLineStyle == lsNone && mScatterStyle.isNone()) return; - To free the tracer from any graph, set \a graph to 0. The tracer \a position can then be placed - freely like any other item position. This is the state the tracer will assume when its graph gets - deleted while still attached to it. + painter->setClipRegion(mKeyAxis->exactClipRegion()); - \see setGraphKey -*/ -void QCPItemTracer::setGraph(QCPGraph *graph) -{ - if (graph) + QVector lines, scatters; // line and (if necessary) scatter pixel coordinates will be stored here while iterating over segments + + // loop over and draw segments of unselected/selected data: + QList selectedSegments, unselectedSegments, allSegments; + getDataSegments(selectedSegments, unselectedSegments); + allSegments << unselectedSegments << selectedSegments; + for (int i=0; iparentPlot() == mParentPlot) + bool isSelectedSegment = i >= unselectedSegments.size(); + // get line pixel points appropriate to line style: + QCPDataRange lineDataRange = isSelectedSegment ? allSegments.at(i) : allSegments.at(i).adjusted(-1, 1); // unselected segments extend lines to bordering selected data point (safe to exceed total data bounds in first/last segment, getLines takes care) + getLines(&lines, lineDataRange); + + // check data validity if flag set: +#ifdef QCUSTOMPLOT_CHECK_DATA + QCPGraphDataContainer::const_iterator it; + for (it = mDataContainer->constBegin(); it != mDataContainer->constEnd(); ++it) { - position->setType(QCPItemPosition::ptPlotCoords); - position->setAxes(graph->keyAxis(), graph->valueAxis()); - mGraph = graph; - updatePosition(); - } else - qDebug() << Q_FUNC_INFO << "graph isn't in same QCustomPlot instance as this item"; - } else - { - mGraph = 0; + if (QCP::isInvalidData(it->key, it->value)) + qDebug() << Q_FUNC_INFO << "Data point at" << it->key << "invalid." << "Plottable name:" << name(); + } +#endif + + // draw fill of graph: + //if (isSelectedSegment && mSelectionDecorator) + // mSelectionDecorator->applyBrush(painter); + //else + painter->setBrush(mBrush); + painter->setPen(Qt::NoPen); + drawFill(painter, &lines); + + + // draw line: + if (mLineStyle != lsNone) + { + //if (isSelectedSegment && mSelectionDecorator) + // mSelectionDecorator->applyPen(painter); + //else + painter->setPen(mPen); + painter->setBrush(Qt::NoBrush); + drawLinePlot(painter, lines); + } + + // draw scatters: + + QCPScatterStyle finalScatterStyle = mScatterStyle; + //if (isSelectedSegment && mSelectionDecorator) + // finalScatterStyle = mSelectionDecorator->getFinalScatterStyle(mScatterStyle); + if (!finalScatterStyle.isNone()) + { + getScatters(&scatters, allSegments.at(i)); + drawScatterPlot(painter, scatters, finalScatterStyle); + } } + + // draw other selection decoration that isn't just line/scatter pens and brushes: + //if (mSelectionDecorator) + // mSelectionDecorator->drawDecoration(painter, selection()); } -/*! - Sets the key of the graph's data point the tracer will be positioned at. This is the only free - coordinate of a tracer when attached to a graph. - - Depending on \ref setInterpolating, the tracer will be either positioned on the data point - closest to \a key, or will stay exactly at \a key and interpolate the value linearly. - - \see setGraph, setInterpolating -*/ -void QCPItemTracer::setGraphKey(double key) +QCP::Interaction QCPPolarGraph::selectionCategory() const { - mGraphKey = key; + return QCP::iSelectPlottables; } -/*! - Sets whether the value of the graph's data points shall be interpolated, when positioning the - tracer. - - If \a enabled is set to false and a key is given with \ref setGraphKey, the tracer is placed on - the data point of the graph which is closest to the key, but which is not necessarily exactly - there. If \a enabled is true, the tracer will be positioned exactly at the specified key, and - the appropriate value will be interpolated from the graph's data points linearly. - - \see setGraph, setGraphKey -*/ -void QCPItemTracer::setInterpolating(bool enabled) +void QCPPolarGraph::applyDefaultAntialiasingHint(QCPPainter *painter) const { - mInterpolating = enabled; + applyAntialiasingHint(painter, mAntialiased, QCP::aePlottables); } /* inherits documentation from base class */ -double QCPItemTracer::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +void QCPPolarGraph::selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; - - QPointF center(position->pixelPoint()); - double w = mSize/2.0; - QRect clip = clipRect(); - switch (mStyle) + Q_UNUSED(event) + + if (mSelectable != QCP::stNone) { - case tsNone: return -1; - case tsPlus: - { - if (clipRect().intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) - return qSqrt(qMin(distSqrToLine(center+QPointF(-w, 0), center+QPointF(w, 0), pos), - distSqrToLine(center+QPointF(0, -w), center+QPointF(0, w), pos))); - break; - } - case tsCrosshair: - { - return qSqrt(qMin(distSqrToLine(QPointF(clip.left(), center.y()), QPointF(clip.right(), center.y()), pos), - distSqrToLine(QPointF(center.x(), clip.top()), QPointF(center.x(), clip.bottom()), pos))); - } - case tsCircle: + QCPDataSelection newSelection = details.value(); + QCPDataSelection selectionBefore = mSelection; + if (additive) { - if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) + if (mSelectable == QCP::stWhole) // in whole selection mode, we toggle to no selection even if currently unselected point was hit { - // distance to border: - double centerDist = QVector2D(center-pos).length(); - double circleLine = w; - double result = qAbs(centerDist-circleLine); - // filled ellipse, allow click inside to count as hit: - if (result > mParentPlot->selectionTolerance()*0.99 && mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0) - { - if (centerDist <= circleLine) - result = mParentPlot->selectionTolerance()*0.99; - } - return result; - } - break; - } - case tsSquare: - { - if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) + if (selected()) + setSelection(QCPDataSelection()); + else + setSelection(newSelection); + } else // in all other selection modes we toggle selections of homogeneously selected/unselected segments { - QRectF rect = QRectF(center-QPointF(w, w), center+QPointF(w, w)); - bool filledRect = mBrush.style() != Qt::NoBrush && mBrush.color().alpha() != 0; - return rectSelectTest(rect, pos, filledRect); + if (mSelection.contains(newSelection)) // if entire newSelection is already selected, toggle selection + setSelection(mSelection-newSelection); + else + setSelection(mSelection+newSelection); } - break; - } + } else + setSelection(newSelection); + if (selectionStateChanged) + *selectionStateChanged = mSelection != selectionBefore; } - return -1; } /* inherits documentation from base class */ -void QCPItemTracer::draw(QCPPainter *painter) +void QCPPolarGraph::deselectEvent(bool *selectionStateChanged) { - updatePosition(); - if (mStyle == tsNone) - return; + if (mSelectable != QCP::stNone) + { + QCPDataSelection selectionBefore = mSelection; + setSelection(QCPDataSelection()); + if (selectionStateChanged) + *selectionStateChanged = mSelection != selectionBefore; + } +} - painter->setPen(mainPen()); - painter->setBrush(mainBrush()); - QPointF center(position->pixelPoint()); - double w = mSize/2.0; - QRect clip = clipRect(); - switch (mStyle) +/*! \internal + + Draws lines between the points in \a lines, given in pixel coordinates. + + \see drawScatterPlot, drawImpulsePlot, QCPAbstractPlottable1D::drawPolyline +*/ +void QCPPolarGraph::drawLinePlot(QCPPainter *painter, const QVector &lines) const +{ + if (painter->pen().style() != Qt::NoPen && painter->pen().color().alpha() != 0) { - case tsNone: return; - case tsPlus: - { - if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) - { - painter->drawLine(QLineF(center+QPointF(-w, 0), center+QPointF(w, 0))); - painter->drawLine(QLineF(center+QPointF(0, -w), center+QPointF(0, w))); - } - break; - } - case tsCrosshair: - { - if (center.y() > clip.top() && center.y() < clip.bottom()) - painter->drawLine(QLineF(clip.left(), center.y(), clip.right(), center.y())); - if (center.x() > clip.left() && center.x() < clip.right()) - painter->drawLine(QLineF(center.x(), clip.top(), center.x(), clip.bottom())); - break; - } - case tsCircle: - { - if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) - painter->drawEllipse(center, w, w); - break; - } - case tsSquare: - { - if (clip.intersects(QRectF(center-QPointF(w, w), center+QPointF(w, w)).toRect())) - painter->drawRect(QRectF(center-QPointF(w, w), center+QPointF(w, w))); - break; - } + applyDefaultAntialiasingHint(painter); + drawPolyline(painter, lines); } } -/*! - If the tracer is connected with a graph (\ref setGraph), this function updates the tracer's \a - position to reside on the graph data, depending on the configured key (\ref setGraphKey). +/*! \internal - It is called automatically on every redraw and normally doesn't need to be called manually. One - exception is when you want to read the tracer coordinates via \a position and are not sure that - the graph's data (or the tracer key with \ref setGraphKey) hasn't changed since the last redraw. - In that situation, call this function before accessing \a position, to make sure you don't get - out-of-date coordinates. + Draws the fill of the graph using the specified \a painter, with the currently set brush. - If there is no graph set on this tracer, this function does nothing. + Depending on whether a normal fill or a channel fill (\ref setChannelFillGraph) is needed, \ref + getFillPolygon or \ref getChannelFillPolygon are used to find the according fill polygons. + + In order to handle NaN Data points correctly (the fill needs to be split into disjoint areas), + this method first determines a list of non-NaN segments with \ref getNonNanSegments, on which to + operate. In the channel fill case, \ref getOverlappingSegments is used to consolidate the non-NaN + segments of the two involved graphs, before passing the overlapping pairs to \ref + getChannelFillPolygon. + + Pass the points of this graph's line as \a lines, in pixel coordinates. + + \see drawLinePlot, drawImpulsePlot, drawScatterPlot */ -void QCPItemTracer::updatePosition() +void QCPPolarGraph::drawFill(QCPPainter *painter, QVector *lines) const { - if (mGraph) + applyFillAntialiasingHint(painter); + if (painter->brush().style() != Qt::NoBrush && painter->brush().color().alpha() != 0) + painter->drawPolygon(QPolygonF(*lines)); +} + +/*! \internal + + Draws scatter symbols at every point passed in \a scatters, given in pixel coordinates. The + scatters will be drawn with \a painter and have the appearance as specified in \a style. + + \see drawLinePlot, drawImpulsePlot +*/ +void QCPPolarGraph::drawScatterPlot(QCPPainter *painter, const QVector &scatters, const QCPScatterStyle &style) const +{ + applyScattersAntialiasingHint(painter); + style.applyTo(painter, mPen); + for (int i=0; ihasPlottable(mGraph)) + applyFillAntialiasingHint(painter); + painter->fillRect(QRectF(rect.left(), rect.top()+rect.height()/2.0, rect.width(), rect.height()/3.0), mBrush); + } + // draw line vertically centered: + if (mLineStyle != lsNone) + { + applyDefaultAntialiasingHint(painter); + painter->setPen(mPen); + painter->drawLine(QLineF(rect.left(), rect.top()+rect.height()/2.0, rect.right()+5, rect.top()+rect.height()/2.0)); // +5 on x2 else last segment is missing from dashed/dotted pens + } + // draw scatter symbol: + if (!mScatterStyle.isNone()) + { + applyScattersAntialiasingHint(painter); + // scale scatter pixmap if it's too large to fit in legend icon rect: + if (mScatterStyle.shape() == QCPScatterStyle::ssPixmap && (mScatterStyle.pixmap().size().width() > rect.width() || mScatterStyle.pixmap().size().height() > rect.height())) { - if (mGraph->data()->size() > 1) - { - QCPDataMap::const_iterator first = mGraph->data()->constBegin(); - QCPDataMap::const_iterator last = mGraph->data()->constEnd()-1; - if (mGraphKey < first.key()) - position->setCoords(first.key(), first.value().value); - else if (mGraphKey > last.key()) - position->setCoords(last.key(), last.value().value); - else - { - QCPDataMap::const_iterator it = mGraph->data()->lowerBound(mGraphKey); - if (it != first) // mGraphKey is somewhere between iterators - { - QCPDataMap::const_iterator prevIt = it-1; - if (mInterpolating) - { - // interpolate between iterators around mGraphKey: - double slope = 0; - if (!qFuzzyCompare((double)it.key(), (double)prevIt.key())) - slope = (it.value().value-prevIt.value().value)/(it.key()-prevIt.key()); - position->setCoords(mGraphKey, (mGraphKey-prevIt.key())*slope+prevIt.value().value); - } else - { - // find iterator with key closest to mGraphKey: - if (mGraphKey < (prevIt.key()+it.key())*0.5) - it = prevIt; - position->setCoords(it.key(), it.value().value); - } - } else // mGraphKey is exactly on first iterator - position->setCoords(it.key(), it.value().value); - } - } else if (mGraph->data()->size() == 1) - { - QCPDataMap::const_iterator it = mGraph->data()->constBegin(); - position->setCoords(it.key(), it.value().value); - } else - qDebug() << Q_FUNC_INFO << "graph has no data"; + QCPScatterStyle scaledStyle(mScatterStyle); + scaledStyle.setPixmap(scaledStyle.pixmap().scaled(rect.size().toSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); + scaledStyle.applyTo(painter, mPen); + scaledStyle.drawShape(painter, QRectF(rect).center()); } else - qDebug() << Q_FUNC_INFO << "graph not contained in QCustomPlot instance (anymore)"; + { + mScatterStyle.applyTo(painter, mPen); + mScatterStyle.drawShape(painter, QRectF(rect).center()); + } } } -/*! \internal - - Returns the pen that should be used for drawing lines. Returns mPen when the item is not selected - and mSelectedPen when it is. -*/ -QPen QCPItemTracer::mainPen() const +void QCPPolarGraph::applyFillAntialiasingHint(QCPPainter *painter) const { - return mSelected ? mSelectedPen : mPen; + applyAntialiasingHint(painter, mAntialiasedFill, QCP::aeFills); } -/*! \internal - - Returns the brush that should be used for drawing fills of the item. Returns mBrush when the item - is not selected and mSelectedBrush when it is. -*/ -QBrush QCPItemTracer::mainBrush() const +void QCPPolarGraph::applyScattersAntialiasingHint(QCPPainter *painter) const { - return mSelected ? mSelectedBrush : mBrush; + applyAntialiasingHint(painter, mAntialiasedScatters, QCP::aeScatters); } - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////// QCPItemBracket -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/*! \class QCPItemBracket - \brief A bracket for referencing/highlighting certain parts in the plot. - - \image html QCPItemBracket.png "Bracket example. Blue dotted circles are anchors, solid blue discs are positions." - - It has two positions, \a left and \a right, which define the span of the bracket. If \a left is - actually farther to the left than \a right, the bracket is opened to the bottom, as shown in the - example image. - - The bracket supports multiple styles via \ref setStyle. The length, i.e. how far the bracket - stretches away from the embraced span, can be controlled with \ref setLength. - - \image html QCPItemBracket-length.png -
Demonstrating the effect of different values for \ref setLength, for styles \ref - bsCalligraphic and \ref bsSquare. Anchors and positions are displayed for reference.
- - It provides an anchor \a center, to allow connection of other items, e.g. an arrow (QCPItemLine - or QCPItemCurve) or a text label (QCPItemText), to the bracket. -*/ - -/*! - Creates a bracket item and sets default values. - - The constructed item can be added to the plot with QCustomPlot::addItem. -*/ -QCPItemBracket::QCPItemBracket(QCustomPlot *parentPlot) : - QCPAbstractItem(parentPlot), - left(createPosition(QLatin1String("left"))), - right(createPosition(QLatin1String("right"))), - center(createAnchor(QLatin1String("center"), aiCenter)) +double QCPPolarGraph::pointDistance(const QPointF &pixelPoint, QCPGraphDataContainer::const_iterator &closestData) const { - left->setCoords(0, 0); - right->setCoords(1, 1); + closestData = mDataContainer->constEnd(); + if (mDataContainer->isEmpty()) + return -1.0; + if (mLineStyle == lsNone && mScatterStyle.isNone()) + return -1.0; - setPen(QPen(Qt::black)); - setSelectedPen(QPen(Qt::blue, 2)); - setLength(8); - setStyle(bsCalligraphic); + // calculate minimum distances to graph data points and find closestData iterator: + double minDistSqr = (std::numeric_limits::max)(); + // determine which key range comes into question, taking selection tolerance around pos into account: + double posKeyMin, posKeyMax, dummy; + pixelsToCoords(pixelPoint-QPointF(mParentPlot->selectionTolerance(), mParentPlot->selectionTolerance()), posKeyMin, dummy); + pixelsToCoords(pixelPoint+QPointF(mParentPlot->selectionTolerance(), mParentPlot->selectionTolerance()), posKeyMax, dummy); + if (posKeyMin > posKeyMax) + qSwap(posKeyMin, posKeyMax); + // iterate over found data points and then choose the one with the shortest distance to pos: + QCPGraphDataContainer::const_iterator begin = mDataContainer->findBegin(posKeyMin, true); + QCPGraphDataContainer::const_iterator end = mDataContainer->findEnd(posKeyMax, true); + for (QCPGraphDataContainer::const_iterator it=begin; it!=end; ++it) + { + const double currentDistSqr = QCPVector2D(coordsToPixels(it->key, it->value)-pixelPoint).lengthSquared(); + if (currentDistSqr < minDistSqr) + { + minDistSqr = currentDistSqr; + closestData = it; + } + } + + // calculate distance to graph line if there is one (if so, will probably be smaller than distance to closest data point): + if (mLineStyle != lsNone) + { + // line displayed, calculate distance to line segments: + QVector lineData; + getLines(&lineData, QCPDataRange(0, dataCount())); + QCPVector2D p(pixelPoint); + for (int i=0; isize(); } -/*! - Sets the pen that will be used to draw the bracket. - - Note that when the style is \ref bsCalligraphic, only the color will be taken from the pen, the - stroke and width are ignored. To change the apparent stroke width of a calligraphic bracket, use - \ref setLength, which has a similar effect. - - \see setSelectedPen -*/ -void QCPItemBracket::setPen(const QPen &pen) +void QCPPolarGraph::getDataSegments(QList &selectedSegments, QList &unselectedSegments) const { - mPen = pen; + selectedSegments.clear(); + unselectedSegments.clear(); + if (mSelectable == QCP::stWhole) // stWhole selection type draws the entire plottable with selected style if mSelection isn't empty + { + if (selected()) + selectedSegments << QCPDataRange(0, dataCount()); + else + unselectedSegments << QCPDataRange(0, dataCount()); + } else + { + QCPDataSelection sel(selection()); + sel.simplify(); + selectedSegments = sel.dataRanges(); + unselectedSegments = sel.inverse(QCPDataRange(0, dataCount())).dataRanges(); + } } -/*! - Sets the pen that will be used to draw the bracket when selected - - \see setPen, setSelected -*/ -void QCPItemBracket::setSelectedPen(const QPen &pen) +void QCPPolarGraph::drawPolyline(QCPPainter *painter, const QVector &lineData) const { - mSelectedPen = pen; + // if drawing solid line and not in PDF, use much faster line drawing instead of polyline: + if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) && + painter->pen().style() == Qt::SolidLine && + !painter->modes().testFlag(QCPPainter::pmVectorized) && + !painter->modes().testFlag(QCPPainter::pmNoCaching)) + { + int i = 0; + bool lastIsNan = false; + const int lineDataSize = lineData.size(); + while (i < lineDataSize && (qIsNaN(lineData.at(i).y()) || qIsNaN(lineData.at(i).x()))) // make sure first point is not NaN + ++i; + ++i; // because drawing works in 1 point retrospect + while (i < lineDataSize) + { + if (!qIsNaN(lineData.at(i).y()) && !qIsNaN(lineData.at(i).x())) // NaNs create a gap in the line + { + if (!lastIsNan) + painter->drawLine(lineData.at(i-1), lineData.at(i)); + else + lastIsNan = false; + } else + lastIsNan = true; + ++i; + } + } else + { + int segmentStart = 0; + int i = 0; + const int lineDataSize = lineData.size(); + while (i < lineDataSize) + { + if (qIsNaN(lineData.at(i).y()) || qIsNaN(lineData.at(i).x()) || qIsInf(lineData.at(i).y())) // NaNs create a gap in the line. Also filter Infs which make drawPolyline block + { + painter->drawPolyline(lineData.constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point + segmentStart = i+1; + } + ++i; + } + // draw last segment: + painter->drawPolyline(lineData.constData()+segmentStart, lineDataSize-segmentStart); + } } -/*! - Sets the \a length in pixels how far the bracket extends in the direction towards the embraced - span of the bracket (i.e. perpendicular to the left-right-direction) - - \image html QCPItemBracket-length.png -
Demonstrating the effect of different values for \ref setLength, for styles \ref - bsCalligraphic and \ref bsSquare. Anchors and positions are displayed for reference.
-*/ -void QCPItemBracket::setLength(double length) +void QCPPolarGraph::getVisibleDataBounds(QCPGraphDataContainer::const_iterator &begin, QCPGraphDataContainer::const_iterator &end, const QCPDataRange &rangeRestriction) const { - mLength = length; + if (rangeRestriction.isEmpty()) + { + end = mDataContainer->constEnd(); + begin = end; + } else + { + QCPPolarAxisAngular *keyAxis = mKeyAxis.data(); + QCPPolarAxisRadial *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } + // get visible data range: + if (mPeriodic) + { + begin = mDataContainer->constBegin(); + end = mDataContainer->constEnd(); + } else + { + begin = mDataContainer->findBegin(keyAxis->range().lower); + end = mDataContainer->findEnd(keyAxis->range().upper); + } + // limit lower/upperEnd to rangeRestriction: + mDataContainer->limitIteratorsToDataRange(begin, end, rangeRestriction); // this also ensures rangeRestriction outside data bounds doesn't break anything + } } -/*! - Sets the style of the bracket, i.e. the shape/visual appearance. - - \see setPen +/*! \internal + + This method retrieves an optimized set of data points via \ref getOptimizedLineData, an branches + out to the line style specific functions such as \ref dataToLines, \ref dataToStepLeftLines, etc. + according to the line style of the graph. + + \a lines will be filled with points in pixel coordinates, that can be drawn with the according + draw functions like \ref drawLinePlot and \ref drawImpulsePlot. The points returned in \a lines + aren't necessarily the original data points. For example, step line styles require additional + points to form the steps when drawn. If the line style of the graph is \ref lsNone, the \a + lines vector will be empty. + + \a dataRange specifies the beginning and ending data indices that will be taken into account for + conversion. In this function, the specified range may exceed the total data bounds without harm: + a correspondingly trimmed data range will be used. This takes the burden off the user of this + function to check for valid indices in \a dataRange, e.g. when extending ranges coming from \ref + getDataSegments. + + \see getScatters */ -void QCPItemBracket::setStyle(QCPItemBracket::BracketStyle style) +void QCPPolarGraph::getLines(QVector *lines, const QCPDataRange &dataRange) const { - mStyle = style; + if (!lines) return; + QCPGraphDataContainer::const_iterator begin, end; + getVisibleDataBounds(begin, end, dataRange); + if (begin == end) + { + lines->clear(); + return; + } + + QVector lineData; + if (mLineStyle != lsNone) + getOptimizedLineData(&lineData, begin, end); + + switch (mLineStyle) + { + case lsNone: lines->clear(); break; + case lsLine: *lines = dataToLines(lineData); break; + } } -/* inherits documentation from base class */ -double QCPItemBracket::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +void QCPPolarGraph::getScatters(QVector *scatters, const QCPDataRange &dataRange) const { - Q_UNUSED(details) - if (onlySelectable && !mSelectable) - return -1; + QCPPolarAxisAngular *keyAxis = mKeyAxis.data(); + QCPPolarAxisRadial *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; } - QVector2D leftVec(left->pixelPoint()); - QVector2D rightVec(right->pixelPoint()); - if (leftVec.toPoint() == rightVec.toPoint()) - return -1; + if (!scatters) return; + QCPGraphDataContainer::const_iterator begin, end; + getVisibleDataBounds(begin, end, dataRange); + if (begin == end) + { + scatters->clear(); + return; + } - QVector2D widthVec = (rightVec-leftVec)*0.5f; - QVector2D lengthVec(-widthVec.y(), widthVec.x()); - lengthVec = lengthVec.normalized()*mLength; - QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec; + QVector data; + getOptimizedScatterData(&data, begin, end); - switch (mStyle) + scatters->resize(data.size()); + for (int i=0; icoordToPixel(data.at(i).key, data.at(i).value); } - return -1; } -/* inherits documentation from base class */ -void QCPItemBracket::draw(QCPPainter *painter) +void QCPPolarGraph::getOptimizedLineData(QVector *lineData, const QCPGraphDataContainer::const_iterator &begin, const QCPGraphDataContainer::const_iterator &end) const { - QVector2D leftVec(left->pixelPoint()); - QVector2D rightVec(right->pixelPoint()); - if (leftVec.toPoint() == rightVec.toPoint()) - return; + lineData->clear(); - QVector2D widthVec = (rightVec-leftVec)*0.5f; - QVector2D lengthVec(-widthVec.y(), widthVec.x()); - lengthVec = lengthVec.normalized()*mLength; - QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec; - - QPolygon boundingPoly; - boundingPoly << leftVec.toPoint() << rightVec.toPoint() - << (rightVec-lengthVec).toPoint() << (leftVec-lengthVec).toPoint(); - QRect clip = clipRect().adjusted(-mainPen().widthF(), -mainPen().widthF(), mainPen().widthF(), mainPen().widthF()); - if (clip.intersects(boundingPoly.boundingRect())) + // TODO: fix for log axes and thick line style + + const QCPRange range = mValueAxis->range(); + bool reversed = mValueAxis->rangeReversed(); + const double clipMargin = range.size()*0.05; // extra distance from visible circle, so optimized outside lines can cover more angle before having to place a dummy point to prevent tangents + const double upperClipValue = range.upper + (reversed ? 0 : range.size()*0.05+clipMargin); // clip slightly outside of actual range to avoid line thicknesses to peek into visible circle + const double lowerClipValue = range.lower - (reversed ? range.size()*0.05+clipMargin : 0); // clip slightly outside of actual range to avoid line thicknesses to peek into visible circle + const double maxKeySkip = qAsin(qSqrt(clipMargin*(clipMargin+2*range.size()))/(range.size()+clipMargin))/M_PI*mKeyAxis->range().size(); // the maximum angle between two points on outer circle (r=clipValue+clipMargin) before connecting line becomes tangent to inner circle (r=clipValue) + double skipBegin = 0; + bool belowRange = false; + bool aboveRange = false; + QCPGraphDataContainer::const_iterator it = begin; + while (it != end) { - painter->setPen(mainPen()); - switch (mStyle) + if (it->value < lowerClipValue) { - case bsSquare: + if (aboveRange) // jumped directly from above to below visible range, draw previous point so entry angle is correct { - painter->drawLine((centerVec+widthVec).toPointF(), (centerVec-widthVec).toPointF()); - painter->drawLine((centerVec+widthVec).toPointF(), (centerVec+widthVec+lengthVec).toPointF()); - painter->drawLine((centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF()); - break; + aboveRange = false; + if (!reversed) // TODO: with inner radius, we'll need else case here with projected border point + lineData->append(*(it-1)); } - case bsRound: + if (!belowRange) { - painter->setBrush(Qt::NoBrush); - QPainterPath path; - path.moveTo((centerVec+widthVec+lengthVec).toPointF()); - path.cubicTo((centerVec+widthVec).toPointF(), (centerVec+widthVec).toPointF(), centerVec.toPointF()); - path.cubicTo((centerVec-widthVec).toPointF(), (centerVec-widthVec).toPointF(), (centerVec-widthVec+lengthVec).toPointF()); - painter->drawPath(path); - break; + skipBegin = it->key; + lineData->append(QCPGraphData(it->key, lowerClipValue)); + belowRange = true; } - case bsCurly: + if (it->key-skipBegin > maxKeySkip) // add dummy point if we're exceeding the maximum skippable angle (to prevent unintentional intersections with visible circle) { - painter->setBrush(Qt::NoBrush); - QPainterPath path; - path.moveTo((centerVec+widthVec+lengthVec).toPointF()); - path.cubicTo((centerVec+widthVec-lengthVec*0.8f).toPointF(), (centerVec+0.4f*widthVec+lengthVec).toPointF(), centerVec.toPointF()); - path.cubicTo((centerVec-0.4f*widthVec+lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8f).toPointF(), (centerVec-widthVec+lengthVec).toPointF()); - painter->drawPath(path); - break; + skipBegin += maxKeySkip; + lineData->append(QCPGraphData(skipBegin, lowerClipValue)); } - case bsCalligraphic: + } else if (it->value > upperClipValue) + { + if (belowRange) // jumped directly from below to above visible range, draw previous point so entry angle is correct (if lower means outer, so if reversed axis) { - painter->setPen(Qt::NoPen); - painter->setBrush(QBrush(mainPen().color())); - QPainterPath path; - path.moveTo((centerVec+widthVec+lengthVec).toPointF()); - - path.cubicTo((centerVec+widthVec-lengthVec*0.8f).toPointF(), (centerVec+0.4f*widthVec+0.8f*lengthVec).toPointF(), centerVec.toPointF()); - path.cubicTo((centerVec-0.4f*widthVec+0.8f*lengthVec).toPointF(), (centerVec-widthVec-lengthVec*0.8f).toPointF(), (centerVec-widthVec+lengthVec).toPointF()); - - path.cubicTo((centerVec-widthVec-lengthVec*0.5f).toPointF(), (centerVec-0.2f*widthVec+1.2f*lengthVec).toPointF(), (centerVec+lengthVec*0.2f).toPointF()); - path.cubicTo((centerVec+0.2f*widthVec+1.2f*lengthVec).toPointF(), (centerVec+widthVec-lengthVec*0.5f).toPointF(), (centerVec+widthVec+lengthVec).toPointF()); - - painter->drawPath(path); - break; + belowRange = false; + if (reversed) + lineData->append(*(it-1)); } + if (!aboveRange) + { + skipBegin = it->key; + lineData->append(QCPGraphData(it->key, upperClipValue)); + aboveRange = true; + } + if (it->key-skipBegin > maxKeySkip) // add dummy point if we're exceeding the maximum skippable angle (to prevent unintentional intersections with visible circle) + { + skipBegin += maxKeySkip; + lineData->append(QCPGraphData(skipBegin, upperClipValue)); + } + } else // value within bounds where we don't optimize away points + { + if (aboveRange) + { + aboveRange = false; + if (!reversed) + lineData->append(*(it-1)); // just entered from above, draw previous point so entry angle is correct (if above means outer, so if not reversed axis) + } + if (belowRange) + { + belowRange = false; + if (reversed) + lineData->append(*(it-1)); // just entered from below, draw previous point so entry angle is correct (if below means outer, so if reversed axis) + } + lineData->append(*it); // inside visible circle, add point normally } + ++it; + } + // to make fill not erratic, add last point normally if it was outside visible circle: + if (aboveRange) + { + aboveRange = false; + if (!reversed) + lineData->append(*(it-1)); // just entered from above, draw previous point so entry angle is correct (if above means outer, so if not reversed axis) + } + if (belowRange) + { + belowRange = false; + if (reversed) + lineData->append(*(it-1)); // just entered from below, draw previous point so entry angle is correct (if below means outer, so if reversed axis) } } -/* inherits documentation from base class */ -QPointF QCPItemBracket::anchorPixelPoint(int anchorId) const +void QCPPolarGraph::getOptimizedScatterData(QVector *scatterData, QCPGraphDataContainer::const_iterator begin, QCPGraphDataContainer::const_iterator end) const { - QVector2D leftVec(left->pixelPoint()); - QVector2D rightVec(right->pixelPoint()); - if (leftVec.toPoint() == rightVec.toPoint()) - return leftVec.toPointF(); - - QVector2D widthVec = (rightVec-leftVec)*0.5f; - QVector2D lengthVec(-widthVec.y(), widthVec.x()); - lengthVec = lengthVec.normalized()*mLength; - QVector2D centerVec = (rightVec+leftVec)*0.5f-lengthVec; + scatterData->clear(); - switch (anchorId) + const QCPRange range = mValueAxis->range(); + bool reversed = mValueAxis->rangeReversed(); + const double clipMargin = range.size()*0.05; + const double upperClipValue = range.upper + (reversed ? 0 : clipMargin); // clip slightly outside of actual range to avoid scatter size to peek into visible circle + const double lowerClipValue = range.lower - (reversed ? clipMargin : 0); // clip slightly outside of actual range to avoid scatter size to peek into visible circle + QCPGraphDataContainer::const_iterator it = begin; + while (it != end) { - case aiCenter: - return centerVec.toPointF(); + if (it->value > lowerClipValue && it->value < upperClipValue) + scatterData->append(*it); + ++it; } - qDebug() << Q_FUNC_INFO << "invalid anchorId" << anchorId; - return QPointF(); } /*! \internal - Returns the pen that should be used for drawing lines. Returns mPen when the - item is not selected and mSelectedPen when it is. + Takes raw data points in plot coordinates as \a data, and returns a vector containing pixel + coordinate points which are suitable for drawing the line style \ref lsLine. + + The source of \a data is usually \ref getOptimizedLineData, and this method is called in \a + getLines if the line style is set accordingly. + + \see dataToStepLeftLines, dataToStepRightLines, dataToStepCenterLines, dataToImpulseLines, getLines, drawLinePlot */ -QPen QCPItemBracket::mainPen() const +QVector QCPPolarGraph::dataToLines(const QVector &data) const { - return mSelected ? mSelectedPen : mPen; + QVector result; + QCPPolarAxisAngular *keyAxis = mKeyAxis.data(); + QCPPolarAxisRadial *valueAxis = mValueAxis.data(); + if (!keyAxis || !valueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return result; } + + // transform data points to pixels: + result.resize(data.size()); + for (int i=0; icoordToPixel(data.at(i).key, data.at(i).value); + return result; } +/* end of 'src/polar/polargraph.cpp' */ + diff --git a/libs/qcustomplot-source/qcustomplot.h b/libs/qcustomplot-source/qcustomplot.h index b33923743..02ed8fb2f 100644 --- a/libs/qcustomplot-source/qcustomplot.h +++ b/libs/qcustomplot-source/qcustomplot.h @@ -1,7 +1,7 @@ /*************************************************************************** ** ** ** QCustomPlot, an easy to use, modern plotting widget for Qt ** -** Copyright (C) 2011-2015 Emanuel Eichhammer ** +** Copyright (C) 2011-2022 Emanuel Eichhammer ** ** ** ** This program is free software: you can redistribute it and/or modify ** ** it under the terms of the GNU General Public License as published by ** @@ -18,40 +18,89 @@ ** ** **************************************************************************** ** Author: Emanuel Eichhammer ** -** Website/Contact: http://www.qcustomplot.com/ ** -** Date: 25.04.15 ** -** Version: 1.3.1 ** +** Website/Contact: https://www.qcustomplot.com/ ** +** Date: 06.11.22 ** +** Version: 2.1.1 ** ****************************************************************************/ #ifndef QCUSTOMPLOT_H #define QCUSTOMPLOT_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include + +// some Qt version/configuration dependent macros to include or exclude certain code paths: +#ifdef QCUSTOMPLOT_USE_OPENGL +# if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +# define QCP_OPENGL_PBUFFER +# else +# define QCP_OPENGL_FBO +# endif +# if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0) +# define QCP_OPENGL_OFFSCREENSURFACE +# endif +#endif + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) +# define QCP_DEVICEPIXELRATIO_SUPPORTED +# if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) +# define QCP_DEVICEPIXELRATIO_FLOAT +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#ifdef QCP_OPENGL_FBO +# include +# if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +# include +# else +# include +# include +# endif +# ifdef QCP_OPENGL_OFFSCREENSURFACE +# include +# else +# include +# endif +#endif +#ifdef QCP_OPENGL_PBUFFER +# include +#endif #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) # include -# include -# include +# include +# include +# include #else # include -# include +# include +# include +#endif +#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0) +# include +#endif +# if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) +# include #endif class QCPPainter; @@ -65,21 +114,30 @@ class QCPAxisPainterPrivate; class QCPAbstractPlottable; class QCPGraph; class QCPAbstractItem; +class QCPPlottableInterface1D; +class QCPLegend; class QCPItemPosition; class QCPLayer; -class QCPPlotTitle; -class QCPLegend; class QCPAbstractLegendItem; +class QCPSelectionRect; class QCPColorMap; class QCPColorScale; class QCPBars; +class QCPPolarAxisRadial; +class QCPPolarAxisAngular; +class QCPPolarGrid; +class QCPPolarGraph; +/* including file 'src/global.h' */ +/* modified 2022-11-06T12:45:57, size 18102 */ -/*! \file */ - +#define QCUSTOMPLOT_VERSION_STR "2.1.1" +#define QCUSTOMPLOT_VERSION 0x020101 // decl definitions for shared library compilation/usage: -#if defined(QCUSTOMPLOT_COMPILE_LIBRARY) +#if defined(QT_STATIC_BUILD) +# define QCP_LIB_DECL +#elif defined(QCUSTOMPLOT_COMPILE_LIBRARY) # define QCP_LIB_DECL Q_DECL_EXPORT #elif defined(QCUSTOMPLOT_USE_LIBRARY) # define QCP_LIB_DECL Q_DECL_IMPORT @@ -87,11 +145,79 @@ class QCPBars; # define QCP_LIB_DECL #endif +// define empty macro for Q_DECL_OVERRIDE if it doesn't exist (Qt < 5) +#ifndef Q_DECL_OVERRIDE +# define Q_DECL_OVERRIDE +#endif + /*! - The QCP Namespace contains general enums and QFlags used throughout the QCustomPlot library + The QCP Namespace contains general enums, QFlags and functions used throughout the QCustomPlot + library. + + It provides QMetaObject-based reflection of its enums and flags via \a QCP::staticMetaObject. */ -namespace QCP -{ + +// Qt version < 6.2.0: to get metatypes Q_GADGET/Q_ENUMS/Q_FLAGS in namespace we have to make it look like a class during moc-run +#if QT_VERSION >= 0x060200 // don't use QT_VERSION_CHECK here, some moc versions don't understand it +namespace QCP { + Q_NAMESPACE // this is how to add the staticMetaObject to namespaces in newer Qt versions +#else // Qt version older than 6.2.0 +# ifndef Q_MOC_RUN +namespace QCP { +# else // not in moc run +class QCP { + Q_GADGET + Q_ENUMS(ExportPen) + Q_ENUMS(ResolutionUnit) + Q_ENUMS(SignDomain) + Q_ENUMS(MarginSide) + Q_ENUMS(AntialiasedElement) + Q_ENUMS(PlottingHint) + Q_ENUMS(Interaction) + Q_ENUMS(SelectionRectMode) + Q_ENUMS(SelectionType) + + Q_FLAGS(AntialiasedElements) + Q_FLAGS(PlottingHints) + Q_FLAGS(MarginSides) + Q_FLAGS(Interactions) +public: +# endif +#endif + + +/*! + Defines the different units in which the image resolution can be specified in the export + functions. + + \see QCustomPlot::savePng, QCustomPlot::saveJpg, QCustomPlot::saveBmp, QCustomPlot::saveRastered +*/ +enum ResolutionUnit { ruDotsPerMeter ///< Resolution is given in dots per meter (dpm) + ,ruDotsPerCentimeter ///< Resolution is given in dots per centimeter (dpcm) + ,ruDotsPerInch ///< Resolution is given in dots per inch (DPI/PPI) + }; + +/*! + Defines how cosmetic pens (pens with numerical width 0) are handled during export. + + \see QCustomPlot::savePdf +*/ +enum ExportPen { epNoCosmetic ///< Cosmetic pens are converted to pens with pixel width 1 when exporting + ,epAllowCosmetic ///< Cosmetic pens are exported normally (e.g. in PDF exports, cosmetic pens always appear as 1 pixel on screen, independent of viewer zoom level) + }; + +/*! + Represents negative and positive sign domain, e.g. for passing to \ref + QCPAbstractPlottable::getKeyRange and \ref QCPAbstractPlottable::getValueRange. + + This is primarily needed when working with logarithmic axis scales, since only one of the sign + domains can be visible at a time. +*/ +enum SignDomain { sdNegative ///< The negative sign domain, i.e. numbers smaller than zero + ,sdBoth ///< Both sign domains, including zero, i.e. all numbers + ,sdPositive ///< The positive sign domain, i.e. numbers greater than zero + }; + /*! Defines the sides of a rectangular entity to which margins can be applied. @@ -120,12 +246,12 @@ enum AntialiasedElement { aeAxes = 0x0001 ///< 0x0001 Axis ba ,aeSubGrid = 0x0004 ///< 0x0004 Sub grid lines ,aeLegend = 0x0008 ///< 0x0008 Legend box ,aeLegendItems = 0x0010 ///< 0x0010 Legend items - ,aePlottables = 0x0020 ///< 0x0020 Main lines of plottables (excluding error bars, see element \ref aeErrorBars) + ,aePlottables = 0x0020 ///< 0x0020 Main lines of plottables ,aeItems = 0x0040 ///< 0x0040 Main lines of items ,aeScatters = 0x0080 ///< 0x0080 Scatter symbols of plottables (excluding scatter symbols of type ssPixmap) - ,aeErrorBars = 0x0100 ///< 0x0100 Error bars - ,aeFills = 0x0200 ///< 0x0200 Borders of fills (e.g. under or between graphs) - ,aeZeroLine = 0x0400 ///< 0x0400 Zero-lines, see \ref QCPGrid::setZeroLinePen + ,aeFills = 0x0100 ///< 0x0100 Borders of fills (e.g. under or between graphs) + ,aeZeroLine = 0x0200 ///< 0x0200 Zero-lines, see \ref QCPGrid::setZeroLinePen + ,aeOther = 0x8000 ///< 0x8000 Other elements that don't fit into any of the existing categories ,aeAll = 0xFFFF ///< 0xFFFF All elements ,aeNone = 0x0000 ///< 0x0000 No elements }; @@ -136,12 +262,12 @@ Q_DECLARE_FLAGS(AntialiasedElements, AntialiasedElement) \see QCustomPlot::setPlottingHints */ -enum PlottingHint { phNone = 0x000 ///< 0x000 No hints are set - ,phFastPolylines = 0x001 ///< 0x001 Graph/Curve lines are drawn with a faster method. This reduces the quality - ///< especially of the line segment joins. (Only relevant for solid line pens.) - ,phForceRepaint = 0x002 ///< 0x002 causes an immediate repaint() instead of a soft update() when QCustomPlot::replot() is called with parameter \ref QCustomPlot::rpHint. - ///< This is set by default to prevent the plot from freezing on fast consecutive replots (e.g. user drags ranges with mouse). - ,phCacheLabels = 0x004 ///< 0x004 axis (tick) labels will be cached as pixmaps, increasing replot performance. +enum PlottingHint { phNone = 0x000 ///< 0x000 No hints are set + ,phFastPolylines = 0x001 ///< 0x001 Graph/Curve lines are drawn with a faster method. This reduces the quality especially of the line segment + ///< joins, thus is most effective for pen sizes larger than 1. It is only used for solid line pens. + ,phImmediateRefresh = 0x002 ///< 0x002 causes an immediate repaint() instead of a soft update() when QCustomPlot::replot() is called with parameter \ref QCustomPlot::rpRefreshHint. + ///< This is set by default to prevent the plot from freezing on fast consecutive replots (e.g. user drags ranges with mouse). + ,phCacheLabels = 0x004 ///< 0x004 axis (tick) labels will be cached as pixmaps, increasing replot performance. }; Q_DECLARE_FLAGS(PlottingHints, PlottingHint) @@ -152,17 +278,55 @@ Q_DECLARE_FLAGS(PlottingHints, PlottingHint) \see QCustomPlot::setInteractions */ -enum Interaction { iRangeDrag = 0x001 ///< 0x001 Axis ranges are draggable (see \ref QCPAxisRect::setRangeDrag, \ref QCPAxisRect::setRangeDragAxes) +enum Interaction { iNone = 0x000 ///< 0x000 None of the interactions are possible + ,iRangeDrag = 0x001 ///< 0x001 Axis ranges are draggable (see \ref QCPAxisRect::setRangeDrag, \ref QCPAxisRect::setRangeDragAxes) ,iRangeZoom = 0x002 ///< 0x002 Axis ranges are zoomable with the mouse wheel (see \ref QCPAxisRect::setRangeZoom, \ref QCPAxisRect::setRangeZoomAxes) ,iMultiSelect = 0x004 ///< 0x004 The user can select multiple objects by holding the modifier set by \ref QCustomPlot::setMultiSelectModifier while clicking ,iSelectPlottables = 0x008 ///< 0x008 Plottables are selectable (e.g. graphs, curves, bars,... see QCPAbstractPlottable) ,iSelectAxes = 0x010 ///< 0x010 Axes are selectable (or parts of them, see QCPAxis::setSelectableParts) ,iSelectLegend = 0x020 ///< 0x020 Legends are selectable (or their child items, see QCPLegend::setSelectableParts) ,iSelectItems = 0x040 ///< 0x040 Items are selectable (Rectangles, Arrows, Textitems, etc. see \ref QCPAbstractItem) - ,iSelectOther = 0x080 ///< 0x080 All other objects are selectable (e.g. your own derived layerables, the plot title,...) + ,iSelectOther = 0x080 ///< 0x080 All other objects are selectable (e.g. your own derived layerables, other layout elements,...) + ,iSelectPlottablesBeyondAxisRect = 0x100 ///< 0x100 When performing plottable selection/hit tests, this flag extends the sensitive area beyond the axis rect }; Q_DECLARE_FLAGS(Interactions, Interaction) +/*! + Defines the behaviour of the selection rect. + + \see QCustomPlot::setSelectionRectMode, QCustomPlot::selectionRect, QCPSelectionRect +*/ +enum SelectionRectMode { srmNone ///< The selection rect is disabled, and all mouse events are forwarded to the underlying objects, e.g. for axis range dragging + ,srmZoom ///< When dragging the mouse, a selection rect becomes active. Upon releasing, the axes that are currently set as range zoom axes (\ref QCPAxisRect::setRangeZoomAxes) will have their ranges zoomed accordingly. + ,srmSelect ///< When dragging the mouse, a selection rect becomes active. Upon releasing, plottable data points that were within the selection rect are selected, if the plottable's selectability setting permits. (See \ref dataselection "data selection mechanism" for details.) + ,srmCustom ///< When dragging the mouse, a selection rect becomes active. It is the programmer's responsibility to connect according slots to the selection rect's signals (e.g. \ref QCPSelectionRect::accepted) in order to process the user interaction. + }; + +/*! + Defines the different ways a plottable can be selected. These images show the effect of the + different selection types, when the indicated selection rect was dragged: + +
+ + + + + + + + +
\image html selectiontype-none.png stNone\image html selectiontype-whole.png stWhole\image html selectiontype-singledata.png stSingleData\image html selectiontype-datarange.png stDataRange\image html selectiontype-multipledataranges.png stMultipleDataRanges
+
+ + \see QCPAbstractPlottable::setSelectable, QCPDataSelection::enforceType +*/ +enum SelectionType { stNone ///< The plottable is not selectable + ,stWhole ///< Selection behaves like \ref stMultipleDataRanges, but if there are any data points selected, the entire plottable is drawn as selected. + ,stSingleData ///< One individual data point can be selected at a time + ,stDataRange ///< Multiple contiguous data points (a data range) can be selected + ,stMultipleDataRanges ///< Any combination of data points/ranges can be selected + }; + /*! \internal Returns whether the specified \a value is considered an invalid data value for plottables (i.e. @@ -223,6 +387,28 @@ inline int getMarginValue(const QMargins &margins, QCP::MarginSide side) return 0; } +// for newer Qt versions we have to declare the enums/flags as metatypes inside the namespace using Q_ENUM_NS/Q_FLAG_NS: +// if you change anything here, don't forget to change it for older Qt versions below, too, +// and at the start of the namespace in the fake moc-run class +#if QT_VERSION >= 0x060200 +Q_ENUM_NS(ExportPen) +Q_ENUM_NS(ResolutionUnit) +Q_ENUM_NS(SignDomain) +Q_ENUM_NS(MarginSide) +Q_ENUM_NS(AntialiasedElement) +Q_ENUM_NS(PlottingHint) +Q_ENUM_NS(Interaction) +Q_ENUM_NS(SelectionRectMode) +Q_ENUM_NS(SelectionType) + +Q_FLAG_NS(AntialiasedElements) +Q_FLAG_NS(PlottingHints) +Q_FLAG_NS(MarginSides) +Q_FLAG_NS(Interactions) +#else +extern const QMetaObject staticMetaObject; +#endif + } // end of namespace QCP Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::AntialiasedElements) @@ -230,84 +416,101 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::PlottingHints) Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::MarginSides) Q_DECLARE_OPERATORS_FOR_FLAGS(QCP::Interactions) +// for older Qt versions we have to declare the enums/flags as metatypes outside the namespace using Q_DECLARE_METATYPE: +// if you change anything here, don't forget to change it for newer Qt versions above, too, +// and at the start of the namespace in the fake moc-run class +#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0) +Q_DECLARE_METATYPE(QCP::ExportPen) +Q_DECLARE_METATYPE(QCP::ResolutionUnit) +Q_DECLARE_METATYPE(QCP::SignDomain) +Q_DECLARE_METATYPE(QCP::MarginSide) +Q_DECLARE_METATYPE(QCP::AntialiasedElement) +Q_DECLARE_METATYPE(QCP::PlottingHint) +Q_DECLARE_METATYPE(QCP::Interaction) +Q_DECLARE_METATYPE(QCP::SelectionRectMode) +Q_DECLARE_METATYPE(QCP::SelectionType) +#endif -class QCP_LIB_DECL QCPScatterStyle -{ - Q_GADGET -public: - /*! - Defines the shape used for scatter points. +/* end of 'src/global.h' */ - On plottables/items that draw scatters, the sizes of these visualizations (with exception of - \ref ssDot and \ref ssPixmap) can be controlled with the \ref setSize function. Scatters are - drawn with the pen and brush specified with \ref setPen and \ref setBrush. - */ - Q_ENUMS(ScatterShape) - enum ScatterShape { ssNone ///< no scatter symbols are drawn (e.g. in QCPGraph, data only represented with lines) - ,ssDot ///< \enumimage{ssDot.png} a single pixel (use \ref ssDisc or \ref ssCircle if you want a round shape with a certain radius) - ,ssCross ///< \enumimage{ssCross.png} a cross - ,ssPlus ///< \enumimage{ssPlus.png} a plus - ,ssCircle ///< \enumimage{ssCircle.png} a circle - ,ssDisc ///< \enumimage{ssDisc.png} a circle which is filled with the pen's color (not the brush as with ssCircle) - ,ssSquare ///< \enumimage{ssSquare.png} a square - ,ssDiamond ///< \enumimage{ssDiamond.png} a diamond - ,ssStar ///< \enumimage{ssStar.png} a star with eight arms, i.e. a combination of cross and plus - ,ssTriangle ///< \enumimage{ssTriangle.png} an equilateral triangle, standing on baseline - ,ssTriangleInverted ///< \enumimage{ssTriangleInverted.png} an equilateral triangle, standing on corner - ,ssCrossSquare ///< \enumimage{ssCrossSquare.png} a square with a cross inside - ,ssPlusSquare ///< \enumimage{ssPlusSquare.png} a square with a plus inside - ,ssCrossCircle ///< \enumimage{ssCrossCircle.png} a circle with a cross inside - ,ssPlusCircle ///< \enumimage{ssPlusCircle.png} a circle with a plus inside - ,ssPeace ///< \enumimage{ssPeace.png} a circle, with one vertical and two downward diagonal lines - ,ssPixmap ///< a custom pixmap specified by \ref setPixmap, centered on the data point coordinates - ,ssCustom ///< custom painter operations are performed per scatter (As QPainterPath, see \ref setCustomPath) - }; - QCPScatterStyle(); - QCPScatterStyle(ScatterShape shape, double size=6); - QCPScatterStyle(ScatterShape shape, const QColor &color, double size); - QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size); - QCPScatterStyle(ScatterShape shape, const QPen &pen, const QBrush &brush, double size); - QCPScatterStyle(const QPixmap &pixmap); - QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, const QBrush &brush=Qt::NoBrush, double size=6); +/* including file 'src/vector2d.h' */ +/* modified 2022-11-06T12:45:56, size 4988 */ + +class QCP_LIB_DECL QCPVector2D +{ +public: + QCPVector2D(); + QCPVector2D(double x, double y); + QCPVector2D(const QPoint &point); + QCPVector2D(const QPointF &point); // getters: - double size() const { return mSize; } - ScatterShape shape() const { return mShape; } - QPen pen() const { return mPen; } - QBrush brush() const { return mBrush; } - QPixmap pixmap() const { return mPixmap; } - QPainterPath customPath() const { return mCustomPath; } - + double x() const { return mX; } + double y() const { return mY; } + double &rx() { return mX; } + double &ry() { return mY; } + // setters: - void setSize(double size); - void setShape(ScatterShape shape); - void setPen(const QPen &pen); - void setBrush(const QBrush &brush); - void setPixmap(const QPixmap &pixmap); - void setCustomPath(const QPainterPath &customPath); - - // non-property methods: - bool isNone() const { return mShape == ssNone; } - bool isPenDefined() const { return mPenDefined; } - void applyTo(QCPPainter *painter, const QPen &defaultPen) const; - void drawShape(QCPPainter *painter, QPointF pos) const; - void drawShape(QCPPainter *painter, double x, double y) const; - -protected: - // property members: - double mSize; - ScatterShape mShape; - QPen mPen; - QBrush mBrush; - QPixmap mPixmap; - QPainterPath mCustomPath; + void setX(double x) { mX = x; } + void setY(double y) { mY = y; } - // non-property members: - bool mPenDefined; + // non-virtual methods: + double length() const { return qSqrt(mX*mX+mY*mY); } + double lengthSquared() const { return mX*mX+mY*mY; } + double angle() const { return qAtan2(mY, mX); } + QPoint toPoint() const { return QPoint(int(mX), int(mY)); } + QPointF toPointF() const { return QPointF(mX, mY); } + + bool isNull() const { return qIsNull(mX) && qIsNull(mY); } + void normalize(); + QCPVector2D normalized() const; + QCPVector2D perpendicular() const { return QCPVector2D(-mY, mX); } + double dot(const QCPVector2D &vec) const { return mX*vec.mX+mY*vec.mY; } + double distanceSquaredToLine(const QCPVector2D &start, const QCPVector2D &end) const; + double distanceSquaredToLine(const QLineF &line) const; + double distanceToStraightLine(const QCPVector2D &base, const QCPVector2D &direction) const; + + QCPVector2D &operator*=(double factor); + QCPVector2D &operator/=(double divisor); + QCPVector2D &operator+=(const QCPVector2D &vector); + QCPVector2D &operator-=(const QCPVector2D &vector); + +private: + // property members: + double mX, mY; + + friend inline const QCPVector2D operator*(double factor, const QCPVector2D &vec); + friend inline const QCPVector2D operator*(const QCPVector2D &vec, double factor); + friend inline const QCPVector2D operator/(const QCPVector2D &vec, double divisor); + friend inline const QCPVector2D operator+(const QCPVector2D &vec1, const QCPVector2D &vec2); + friend inline const QCPVector2D operator-(const QCPVector2D &vec1, const QCPVector2D &vec2); + friend inline const QCPVector2D operator-(const QCPVector2D &vec); }; -Q_DECLARE_TYPEINFO(QCPScatterStyle, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QCPVector2D, Q_MOVABLE_TYPE); + +inline const QCPVector2D operator*(double factor, const QCPVector2D &vec) { return QCPVector2D(vec.mX*factor, vec.mY*factor); } +inline const QCPVector2D operator*(const QCPVector2D &vec, double factor) { return QCPVector2D(vec.mX*factor, vec.mY*factor); } +inline const QCPVector2D operator/(const QCPVector2D &vec, double divisor) { return QCPVector2D(vec.mX/divisor, vec.mY/divisor); } +inline const QCPVector2D operator+(const QCPVector2D &vec1, const QCPVector2D &vec2) { return QCPVector2D(vec1.mX+vec2.mX, vec1.mY+vec2.mY); } +inline const QCPVector2D operator-(const QCPVector2D &vec1, const QCPVector2D &vec2) { return QCPVector2D(vec1.mX-vec2.mX, vec1.mY-vec2.mY); } +inline const QCPVector2D operator-(const QCPVector2D &vec) { return QCPVector2D(-vec.mX, -vec.mY); } +/*! \relates QCPVector2D + + Prints \a vec in a human readable format to the qDebug output. +*/ +inline QDebug operator<< (QDebug d, const QCPVector2D &vec) +{ + d.nospace() << "QCPVector2D(" << vec.x() << ", " << vec.y() << ")"; + return d.space(); +} + +/* end of 'src/vector2d.h' */ + + +/* including file 'src/painter.h' */ +/* modified 2022-11-06T12:45:56, size 4035 */ class QCP_LIB_DECL QCPPainter : public QPainter { @@ -322,12 +525,12 @@ class QCP_LIB_DECL QCPPainter : public QPainter ,pmNoCaching = 0x02 ///< 0x02 Mode for all sorts of exports (e.g. PNG, PDF,...). For example, this prevents using cached pixmap labels ,pmNonCosmetic = 0x04 ///< 0x04 Turns pen widths 0 to 1, i.e. disables cosmetic pens. (A cosmetic pen is always drawn with width 1 pixel in the vector image/pdf viewer, independent of zoom.) }; - Q_FLAGS(PainterMode PainterModes) + Q_ENUMS(PainterMode) + Q_FLAGS(PainterModes) Q_DECLARE_FLAGS(PainterModes, PainterMode) QCPPainter(); - QCPPainter(QPaintDevice *device); - ~QCPPainter(); + explicit QCPPainter(QPaintDevice *device); // getters: bool antialiasing() const { return testRenderHint(QPainter::Antialiasing); } @@ -360,8 +563,122 @@ class QCP_LIB_DECL QCPPainter : public QPainter QStack mAntialiasingStack; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QCPPainter::PainterModes) +Q_DECLARE_METATYPE(QCPPainter::PainterMode) + +/* end of 'src/painter.h' */ + + +/* including file 'src/paintbuffer.h' */ +/* modified 2022-11-06T12:45:56, size 5006 */ + +class QCP_LIB_DECL QCPAbstractPaintBuffer +{ +public: + explicit QCPAbstractPaintBuffer(const QSize &size, double devicePixelRatio); + virtual ~QCPAbstractPaintBuffer(); + + // getters: + QSize size() const { return mSize; } + bool invalidated() const { return mInvalidated; } + double devicePixelRatio() const { return mDevicePixelRatio; } + + // setters: + void setSize(const QSize &size); + void setInvalidated(bool invalidated=true); + void setDevicePixelRatio(double ratio); + + // introduced virtual methods: + virtual QCPPainter *startPainting() = 0; + virtual void donePainting() {} + virtual void draw(QCPPainter *painter) const = 0; + virtual void clear(const QColor &color) = 0; + +protected: + // property members: + QSize mSize; + double mDevicePixelRatio; + + // non-property members: + bool mInvalidated; + + // introduced virtual methods: + virtual void reallocateBuffer() = 0; +}; + + +class QCP_LIB_DECL QCPPaintBufferPixmap : public QCPAbstractPaintBuffer +{ +public: + explicit QCPPaintBufferPixmap(const QSize &size, double devicePixelRatio); + virtual ~QCPPaintBufferPixmap() Q_DECL_OVERRIDE; + + // reimplemented virtual methods: + virtual QCPPainter *startPainting() Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) const Q_DECL_OVERRIDE; + void clear(const QColor &color) Q_DECL_OVERRIDE; + +protected: + // non-property members: + QPixmap mBuffer; + + // reimplemented virtual methods: + virtual void reallocateBuffer() Q_DECL_OVERRIDE; +}; + + +#ifdef QCP_OPENGL_PBUFFER +class QCP_LIB_DECL QCPPaintBufferGlPbuffer : public QCPAbstractPaintBuffer +{ +public: + explicit QCPPaintBufferGlPbuffer(const QSize &size, double devicePixelRatio, int multisamples); + virtual ~QCPPaintBufferGlPbuffer() Q_DECL_OVERRIDE; + + // reimplemented virtual methods: + virtual QCPPainter *startPainting() Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) const Q_DECL_OVERRIDE; + void clear(const QColor &color) Q_DECL_OVERRIDE; + +protected: + // non-property members: + QGLPixelBuffer *mGlPBuffer; + int mMultisamples; + + // reimplemented virtual methods: + virtual void reallocateBuffer() Q_DECL_OVERRIDE; +}; +#endif // QCP_OPENGL_PBUFFER + + +#ifdef QCP_OPENGL_FBO +class QCP_LIB_DECL QCPPaintBufferGlFbo : public QCPAbstractPaintBuffer +{ +public: + explicit QCPPaintBufferGlFbo(const QSize &size, double devicePixelRatio, QWeakPointer glContext, QWeakPointer glPaintDevice); + virtual ~QCPPaintBufferGlFbo() Q_DECL_OVERRIDE; + + // reimplemented virtual methods: + virtual QCPPainter *startPainting() Q_DECL_OVERRIDE; + virtual void donePainting() Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) const Q_DECL_OVERRIDE; + void clear(const QColor &color) Q_DECL_OVERRIDE; + +protected: + // non-property members: + QWeakPointer mGlContext; + QWeakPointer mGlPaintDevice; + QOpenGLFramebufferObject *mGlFrameBuffer; + + // reimplemented virtual methods: + virtual void reallocateBuffer() Q_DECL_OVERRIDE; +}; +#endif // QCP_OPENGL_FBO + +/* end of 'src/paintbuffer.h' */ +/* including file 'src/layer.h' */ +/* modified 2022-11-06T12:45:56, size 7038 */ + class QCP_LIB_DECL QCPLayer : public QObject { Q_OBJECT @@ -371,10 +688,24 @@ class QCP_LIB_DECL QCPLayer : public QObject Q_PROPERTY(int index READ index) Q_PROPERTY(QList children READ children) Q_PROPERTY(bool visible READ visible WRITE setVisible) + Q_PROPERTY(LayerMode mode READ mode WRITE setMode) /// \endcond public: + + /*! + Defines the different rendering modes of a layer. Depending on the mode, certain layers can be + replotted individually, without the need to replot (possibly complex) layerables on other + layers. + + \see setMode + */ + enum LayerMode { lmLogical ///< Layer is used only for rendering order, and shares paint buffer with all other adjacent logical layers. + ,lmBuffered ///< Layer has its own paint buffer and may be replotted individually (see \ref replot). + }; + Q_ENUMS(LayerMode) + QCPLayer(QCustomPlot* parentPlot, const QString &layerName); - ~QCPLayer(); + virtual ~QCPLayer(); // getters: QCustomPlot *parentPlot() const { return mParentPlot; } @@ -382,9 +713,14 @@ class QCP_LIB_DECL QCPLayer : public QObject int index() const { return mIndex; } QList children() const { return mChildren; } bool visible() const { return mVisible; } + LayerMode mode() const { return mMode; } // setters: void setVisible(bool visible); + void setMode(LayerMode mode); + + // non-virtual methods: + void replot(); protected: // property members: @@ -393,8 +729,14 @@ class QCP_LIB_DECL QCPLayer : public QObject int mIndex; QList mChildren; bool mVisible; + LayerMode mMode; + + // non-property members: + QWeakPointer mPaintBuffer; // non-virtual methods: + void draw(QCPPainter *painter); + void drawToPaintBuffer(); void addChild(QCPLayerable *layerable, bool prepend); void removeChild(QCPLayerable *layerable); @@ -404,6 +746,7 @@ class QCP_LIB_DECL QCPLayer : public QObject friend class QCustomPlot; friend class QCPLayerable; }; +Q_DECLARE_METATYPE(QCPLayer::LayerMode) class QCP_LIB_DECL QCPLayerable : public QObject { @@ -416,8 +759,8 @@ class QCP_LIB_DECL QCPLayerable : public QObject Q_PROPERTY(bool antialiased READ antialiased WRITE setAntialiased) /// \endcond public: - QCPLayerable(QCustomPlot *plot, QString targetLayer=QString(), QCPLayerable *parentLayerable=0); - ~QCPLayerable(); + QCPLayerable(QCustomPlot *plot, QString targetLayer=QString(), QCPLayerable *parentLayerable=nullptr); + virtual ~QCPLayerable(); // getters: bool visible() const { return mVisible; } @@ -433,8 +776,8 @@ class QCP_LIB_DECL QCPLayerable : public QObject void setAntialiased(bool enabled); // introduced virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; - + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const; + // non-property methods: bool realVisibility() const; @@ -455,9 +798,15 @@ class QCP_LIB_DECL QCPLayerable : public QObject virtual QRect clipRect() const; virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const = 0; virtual void draw(QCPPainter *painter) = 0; - // events: + // selection events: virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); virtual void deselectEvent(bool *selectionStateChanged); + // low-level mouse events: + virtual void mousePressEvent(QMouseEvent *event, const QVariant &details); + virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos); + virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos); + virtual void mouseDoubleClickEvent(QMouseEvent *event, const QVariant &details); + virtual void wheelEvent(QWheelEvent *event); // non-property methods: void initializeParentPlot(QCustomPlot *parentPlot); @@ -469,9 +818,15 @@ class QCP_LIB_DECL QCPLayerable : public QObject Q_DISABLE_COPY(QCPLayerable) friend class QCustomPlot; + friend class QCPLayer; friend class QCPAxisRect; }; +/* end of 'src/layer.h' */ + + +/* including file 'src/axis/range.h' */ +/* modified 2022-11-06T12:45:56, size 5280 */ class QCP_LIB_DECL QCPRange { @@ -495,46 +850,35 @@ class QCP_LIB_DECL QCPRange friend inline const QCPRange operator*(double value, const QCPRange& range); friend inline const QCPRange operator/(const QCPRange& range, double value); - double size() const; - double center() const; - void normalize(); + double size() const { return upper-lower; } + double center() const { return (upper+lower)*0.5; } + void normalize() { if (lower > upper) qSwap(lower, upper); } void expand(const QCPRange &otherRange); + void expand(double includeCoord); QCPRange expanded(const QCPRange &otherRange) const; + QCPRange expanded(double includeCoord) const; + QCPRange bounded(double lowerBound, double upperBound) const; QCPRange sanitizedForLogScale() const; QCPRange sanitizedForLinScale() const; - bool contains(double value) const; + bool contains(double value) const { return value >= lower && value <= upper; } static bool validRange(double lower, double upper); static bool validRange(const QCPRange &range); - static const double minRange; //1e-280; - static const double maxRange; //1e280; + static const double minRange; + static const double maxRange; }; Q_DECLARE_TYPEINFO(QCPRange, Q_MOVABLE_TYPE); -/* documentation of inline functions */ - -/*! \fn QCPRange &QCPRange::operator+=(const double& value) - - Adds \a value to both boundaries of the range. -*/ - -/*! \fn QCPRange &QCPRange::operator-=(const double& value) - - Subtracts \a value from both boundaries of the range. -*/ - -/*! \fn QCPRange &QCPRange::operator*=(const double& value) - - Multiplies both boundaries of the range by \a value. -*/ +/*! \relates QCPRange -/*! \fn QCPRange &QCPRange::operator/=(const double& value) - - Divides both boundaries of the range by \a value. + Prints \a range in a human readable format to the qDebug output. */ - -/* end documentation of inline functions */ +inline QDebug operator<< (QDebug d, const QCPRange &range) +{ + d.nospace() << "QCPRange(" << range.lower << ", " << range.upper << ")"; + return d.space(); +} /*! Adds \a value to both boundaries of the range. @@ -596,40 +940,305 @@ inline const QCPRange operator/(const QCPRange& range, double value) return result; } +/* end of 'src/axis/range.h' */ -class QCP_LIB_DECL QCPMarginGroup : public QObject + +/* including file 'src/selection.h' */ +/* modified 2022-11-06T12:45:56, size 8569 */ + +class QCP_LIB_DECL QCPDataRange { - Q_OBJECT public: - QCPMarginGroup(QCustomPlot *parentPlot); - ~QCPMarginGroup(); + QCPDataRange(); + QCPDataRange(int begin, int end); - // non-virtual methods: - QList elements(QCP::MarginSide side) const { return mChildren.value(side); } - bool isEmpty() const; - void clear(); + bool operator==(const QCPDataRange& other) const { return mBegin == other.mBegin && mEnd == other.mEnd; } + bool operator!=(const QCPDataRange& other) const { return !(*this == other); } -protected: - // non-property members: - QCustomPlot *mParentPlot; - QHash > mChildren; + // getters: + int begin() const { return mBegin; } + int end() const { return mEnd; } + int size() const { return mEnd-mBegin; } + int length() const { return size(); } - // non-virtual methods: - int commonMargin(QCP::MarginSide side) const; - void addChild(QCP::MarginSide side, QCPLayoutElement *element); - void removeChild(QCP::MarginSide side, QCPLayoutElement *element); + // setters: + void setBegin(int begin) { mBegin = begin; } + void setEnd(int end) { mEnd = end; } -private: - Q_DISABLE_COPY(QCPMarginGroup) + // non-property methods: + bool isValid() const { return (mEnd >= mBegin) && (mBegin >= 0); } + bool isEmpty() const { return length() == 0; } + QCPDataRange bounded(const QCPDataRange &other) const; + QCPDataRange expanded(const QCPDataRange &other) const; + QCPDataRange intersection(const QCPDataRange &other) const; + QCPDataRange adjusted(int changeBegin, int changeEnd) const { return QCPDataRange(mBegin+changeBegin, mEnd+changeEnd); } + bool intersects(const QCPDataRange &other) const; + bool contains(const QCPDataRange &other) const; - friend class QCPLayoutElement; +private: + // property members: + int mBegin, mEnd; + }; +Q_DECLARE_TYPEINFO(QCPDataRange, Q_MOVABLE_TYPE); -class QCP_LIB_DECL QCPLayoutElement : public QCPLayerable +class QCP_LIB_DECL QCPDataSelection { - Q_OBJECT - /// \cond INCLUDE_QPROPERTIES +public: + explicit QCPDataSelection(); + explicit QCPDataSelection(const QCPDataRange &range); + + bool operator==(const QCPDataSelection& other) const; + bool operator!=(const QCPDataSelection& other) const { return !(*this == other); } + QCPDataSelection &operator+=(const QCPDataSelection& other); + QCPDataSelection &operator+=(const QCPDataRange& other); + QCPDataSelection &operator-=(const QCPDataSelection& other); + QCPDataSelection &operator-=(const QCPDataRange& other); + friend inline const QCPDataSelection operator+(const QCPDataSelection& a, const QCPDataSelection& b); + friend inline const QCPDataSelection operator+(const QCPDataRange& a, const QCPDataSelection& b); + friend inline const QCPDataSelection operator+(const QCPDataSelection& a, const QCPDataRange& b); + friend inline const QCPDataSelection operator+(const QCPDataRange& a, const QCPDataRange& b); + friend inline const QCPDataSelection operator-(const QCPDataSelection& a, const QCPDataSelection& b); + friend inline const QCPDataSelection operator-(const QCPDataRange& a, const QCPDataSelection& b); + friend inline const QCPDataSelection operator-(const QCPDataSelection& a, const QCPDataRange& b); + friend inline const QCPDataSelection operator-(const QCPDataRange& a, const QCPDataRange& b); + + // getters: + int dataRangeCount() const { return mDataRanges.size(); } + int dataPointCount() const; + QCPDataRange dataRange(int index=0) const; + QList dataRanges() const { return mDataRanges; } + QCPDataRange span() const; + + // non-property methods: + void addDataRange(const QCPDataRange &dataRange, bool simplify=true); + void clear(); + bool isEmpty() const { return mDataRanges.isEmpty(); } + void simplify(); + void enforceType(QCP::SelectionType type); + bool contains(const QCPDataSelection &other) const; + QCPDataSelection intersection(const QCPDataRange &other) const; + QCPDataSelection intersection(const QCPDataSelection &other) const; + QCPDataSelection inverse(const QCPDataRange &outerRange) const; + +private: + // property members: + QList mDataRanges; + + inline static bool lessThanDataRangeBegin(const QCPDataRange &a, const QCPDataRange &b) { return a.begin() < b.begin(); } +}; +Q_DECLARE_METATYPE(QCPDataSelection) + + +/*! + Return a \ref QCPDataSelection with the data points in \a a joined with the data points in \a b. + The resulting data selection is already simplified (see \ref QCPDataSelection::simplify). +*/ +inline const QCPDataSelection operator+(const QCPDataSelection& a, const QCPDataSelection& b) +{ + QCPDataSelection result(a); + result += b; + return result; +} + +/*! + Return a \ref QCPDataSelection with the data points in \a a joined with the data points in \a b. + The resulting data selection is already simplified (see \ref QCPDataSelection::simplify). +*/ +inline const QCPDataSelection operator+(const QCPDataRange& a, const QCPDataSelection& b) +{ + QCPDataSelection result(a); + result += b; + return result; +} + +/*! + Return a \ref QCPDataSelection with the data points in \a a joined with the data points in \a b. + The resulting data selection is already simplified (see \ref QCPDataSelection::simplify). +*/ +inline const QCPDataSelection operator+(const QCPDataSelection& a, const QCPDataRange& b) +{ + QCPDataSelection result(a); + result += b; + return result; +} + +/*! + Return a \ref QCPDataSelection with the data points in \a a joined with the data points in \a b. + The resulting data selection is already simplified (see \ref QCPDataSelection::simplify). +*/ +inline const QCPDataSelection operator+(const QCPDataRange& a, const QCPDataRange& b) +{ + QCPDataSelection result(a); + result += b; + return result; +} + +/*! + Return a \ref QCPDataSelection with the data points which are in \a a but not in \a b. +*/ +inline const QCPDataSelection operator-(const QCPDataSelection& a, const QCPDataSelection& b) +{ + QCPDataSelection result(a); + result -= b; + return result; +} + +/*! + Return a \ref QCPDataSelection with the data points which are in \a a but not in \a b. +*/ +inline const QCPDataSelection operator-(const QCPDataRange& a, const QCPDataSelection& b) +{ + QCPDataSelection result(a); + result -= b; + return result; +} + +/*! + Return a \ref QCPDataSelection with the data points which are in \a a but not in \a b. +*/ +inline const QCPDataSelection operator-(const QCPDataSelection& a, const QCPDataRange& b) +{ + QCPDataSelection result(a); + result -= b; + return result; +} + +/*! + Return a \ref QCPDataSelection with the data points which are in \a a but not in \a b. +*/ +inline const QCPDataSelection operator-(const QCPDataRange& a, const QCPDataRange& b) +{ + QCPDataSelection result(a); + result -= b; + return result; +} + +/*! \relates QCPDataRange + + Prints \a dataRange in a human readable format to the qDebug output. +*/ +inline QDebug operator<< (QDebug d, const QCPDataRange &dataRange) +{ + d.nospace() << "QCPDataRange(" << dataRange.begin() << ", " << dataRange.end() << ")"; + return d; +} + +/*! \relates QCPDataSelection + + Prints \a selection in a human readable format to the qDebug output. +*/ +inline QDebug operator<< (QDebug d, const QCPDataSelection &selection) +{ + d.nospace() << "QCPDataSelection("; + for (int i=0; i elements(QCP::MarginSide side) const { return mChildren.value(side); } + bool isEmpty() const; + void clear(); + +protected: + // non-property members: + QCustomPlot *mParentPlot; + QHash > mChildren; + + // introduced virtual methods: + virtual int commonMargin(QCP::MarginSide side) const; + + // non-virtual methods: + void addChild(QCP::MarginSide side, QCPLayoutElement *element); + void removeChild(QCP::MarginSide side, QCPLayoutElement *element); + +private: + Q_DISABLE_COPY(QCPMarginGroup) + + friend class QCPLayoutElement; +}; + + +class QCP_LIB_DECL QCPLayoutElement : public QCPLayerable +{ + Q_OBJECT + /// \cond INCLUDE_QPROPERTIES Q_PROPERTY(QCPLayout* layout READ layout) Q_PROPERTY(QRect rect READ rect) Q_PROPERTY(QRect outerRect READ outerRect WRITE setOuterRect) @@ -637,6 +1246,7 @@ class QCP_LIB_DECL QCPLayoutElement : public QCPLayerable Q_PROPERTY(QMargins minimumMargins READ minimumMargins WRITE setMinimumMargins) Q_PROPERTY(QSize minimumSize READ minimumSize WRITE setMinimumSize) Q_PROPERTY(QSize maximumSize READ maximumSize WRITE setMaximumSize) + Q_PROPERTY(SizeConstraintRect sizeConstraintRect READ sizeConstraintRect WRITE setSizeConstraintRect) /// \endcond public: /*! @@ -648,9 +1258,22 @@ class QCP_LIB_DECL QCPLayoutElement : public QCPLayerable ,upLayout ///< Final phase in which the layout system places the rects of the elements }; Q_ENUMS(UpdatePhase) + + /*! + Defines to which rect of a layout element the size constraints that can be set via \ref + setMinimumSize and \ref setMaximumSize apply. The outer rect (\ref outerRect) includes the + margins (e.g. in the case of a QCPAxisRect the axis labels), whereas the inner rect (\ref rect) + does not. + + \see setSizeConstraintRect + */ + enum SizeConstraintRect { scrInnerRect ///< Minimum/Maximum size constraints apply to inner rect + , scrOuterRect ///< Minimum/Maximum size constraints apply to outer rect, thus include layout element margins + }; + Q_ENUMS(SizeConstraintRect) - explicit QCPLayoutElement(QCustomPlot *parentPlot=0); - virtual ~QCPLayoutElement(); + explicit QCPLayoutElement(QCustomPlot *parentPlot=nullptr); + virtual ~QCPLayoutElement() Q_DECL_OVERRIDE; // getters: QCPLayout *layout() const { return mParentLayout; } @@ -661,7 +1284,8 @@ class QCP_LIB_DECL QCPLayoutElement : public QCPLayerable QCP::MarginSides autoMargins() const { return mAutoMargins; } QSize minimumSize() const { return mMinimumSize; } QSize maximumSize() const { return mMaximumSize; } - QCPMarginGroup *marginGroup(QCP::MarginSide side) const { return mMarginGroups.value(side, (QCPMarginGroup*)0); } + SizeConstraintRect sizeConstraintRect() const { return mSizeConstraintRect; } + QCPMarginGroup *marginGroup(QCP::MarginSide side) const { return mMarginGroups.value(side, nullptr); } QHash marginGroups() const { return mMarginGroups; } // setters: @@ -673,21 +1297,23 @@ class QCP_LIB_DECL QCPLayoutElement : public QCPLayerable void setMinimumSize(int width, int height); void setMaximumSize(const QSize &size); void setMaximumSize(int width, int height); + void setSizeConstraintRect(SizeConstraintRect constraintRect); void setMarginGroup(QCP::MarginSides sides, QCPMarginGroup *group); // introduced virtual methods: virtual void update(UpdatePhase phase); - virtual QSize minimumSizeHint() const; - virtual QSize maximumSizeHint() const; + virtual QSize minimumOuterSizeHint() const; + virtual QSize maximumOuterSizeHint() const; virtual QList elements(bool recursive) const; // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; protected: // property members: QCPLayout *mParentLayout; QSize mMinimumSize, mMaximumSize; + SizeConstraintRect mSizeConstraintRect; QRect mRect, mOuterRect; QMargins mMargins, mMinimumMargins; QCP::MarginSides mAutoMargins; @@ -695,17 +1321,12 @@ class QCP_LIB_DECL QCPLayoutElement : public QCPLayerable // introduced virtual methods: virtual int calculateAutoMargin(QCP::MarginSide side); - // events: - virtual void mousePressEvent(QMouseEvent *event) {Q_UNUSED(event)} - virtual void mouseMoveEvent(QMouseEvent *event) {Q_UNUSED(event)} - virtual void mouseReleaseEvent(QMouseEvent *event) {Q_UNUSED(event)} - virtual void mouseDoubleClickEvent(QMouseEvent *event) {Q_UNUSED(event)} - virtual void wheelEvent(QWheelEvent *event) {Q_UNUSED(event)} + virtual void layoutChanged(); // reimplemented virtual methods: - virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const { Q_UNUSED(painter) } - virtual void draw(QCPPainter *painter) { Q_UNUSED(painter) } - virtual void parentPlotInitialized(QCustomPlot *parentPlot); + virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE { Q_UNUSED(painter) } + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE { Q_UNUSED(painter) } + virtual void parentPlotInitialized(QCustomPlot *parentPlot) Q_DECL_OVERRIDE; private: Q_DISABLE_COPY(QCPLayoutElement) @@ -714,6 +1335,7 @@ class QCP_LIB_DECL QCPLayoutElement : public QCPLayerable friend class QCPLayout; friend class QCPMarginGroup; }; +Q_DECLARE_METATYPE(QCPLayoutElement::UpdatePhase) class QCP_LIB_DECL QCPLayout : public QCPLayoutElement @@ -723,8 +1345,8 @@ class QCP_LIB_DECL QCPLayout : public QCPLayoutElement explicit QCPLayout(); // reimplemented virtual methods: - virtual void update(UpdatePhase phase); - virtual QList elements(bool recursive) const; + virtual void update(UpdatePhase phase) Q_DECL_OVERRIDE; + virtual QList elements(bool recursive) const Q_DECL_OVERRIDE; // introduced virtual methods: virtual int elementCount() const = 0; @@ -747,6 +1369,8 @@ class QCP_LIB_DECL QCPLayout : public QCPLayoutElement void adoptElement(QCPLayoutElement *el); void releaseElement(QCPLayoutElement *el); QVector getSectionSizes(QVector maxSizes, QVector minSizes, QVector stretchFactors, int totalSize) const; + static QSize getFinalMinimumOuterSize(const QCPLayoutElement *el); + static QSize getFinalMaximumOuterSize(const QCPLayoutElement *el); private: Q_DISABLE_COPY(QCPLayout) @@ -764,18 +1388,35 @@ class QCP_LIB_DECL QCPLayoutGrid : public QCPLayout Q_PROPERTY(QList rowStretchFactors READ rowStretchFactors WRITE setRowStretchFactors) Q_PROPERTY(int columnSpacing READ columnSpacing WRITE setColumnSpacing) Q_PROPERTY(int rowSpacing READ rowSpacing WRITE setRowSpacing) + Q_PROPERTY(FillOrder fillOrder READ fillOrder WRITE setFillOrder) + Q_PROPERTY(int wrap READ wrap WRITE setWrap) /// \endcond public: + + /*! + Defines in which direction the grid is filled when using \ref addElement(QCPLayoutElement*). + The column/row at which wrapping into the next row/column occurs can be specified with \ref + setWrap. + + \see setFillOrder + */ + enum FillOrder { foRowsFirst ///< Rows are filled first, and a new element is wrapped to the next column if the row count would exceed \ref setWrap. + ,foColumnsFirst ///< Columns are filled first, and a new element is wrapped to the next row if the column count would exceed \ref setWrap. + }; + Q_ENUMS(FillOrder) + explicit QCPLayoutGrid(); - virtual ~QCPLayoutGrid(); + virtual ~QCPLayoutGrid() Q_DECL_OVERRIDE; // getters: - int rowCount() const; - int columnCount() const; + int rowCount() const { return mElements.size(); } + int columnCount() const { return mElements.size() > 0 ? mElements.first().size() : 0; } QList columnStretchFactors() const { return mColumnStretchFactors; } QList rowStretchFactors() const { return mRowStretchFactors; } int columnSpacing() const { return mColumnSpacing; } int rowSpacing() const { return mRowSpacing; } + int wrap() const { return mWrap; } + FillOrder fillOrder() const { return mFillOrder; } // setters: void setColumnStretchFactor(int column, double factor); @@ -784,25 +1425,30 @@ class QCP_LIB_DECL QCPLayoutGrid : public QCPLayout void setRowStretchFactors(const QList &factors); void setColumnSpacing(int pixels); void setRowSpacing(int pixels); + void setWrap(int count); + void setFillOrder(FillOrder order, bool rearrange=true); // reimplemented virtual methods: - virtual void updateLayout(); - virtual int elementCount() const; - virtual QCPLayoutElement* elementAt(int index) const; - virtual QCPLayoutElement* takeAt(int index); - virtual bool take(QCPLayoutElement* element); - virtual QList elements(bool recursive) const; - virtual void simplify(); - virtual QSize minimumSizeHint() const; - virtual QSize maximumSizeHint() const; + virtual void updateLayout() Q_DECL_OVERRIDE; + virtual int elementCount() const Q_DECL_OVERRIDE { return rowCount()*columnCount(); } + virtual QCPLayoutElement* elementAt(int index) const Q_DECL_OVERRIDE; + virtual QCPLayoutElement* takeAt(int index) Q_DECL_OVERRIDE; + virtual bool take(QCPLayoutElement* element) Q_DECL_OVERRIDE; + virtual QList elements(bool recursive) const Q_DECL_OVERRIDE; + virtual void simplify() Q_DECL_OVERRIDE; + virtual QSize minimumOuterSizeHint() const Q_DECL_OVERRIDE; + virtual QSize maximumOuterSizeHint() const Q_DECL_OVERRIDE; // non-virtual methods: QCPLayoutElement *element(int row, int column) const; bool addElement(int row, int column, QCPLayoutElement *element); + bool addElement(QCPLayoutElement *element); bool hasElement(int row, int column); void expandTo(int newRowCount, int newColumnCount); void insertRow(int newIndex); void insertColumn(int newIndex); + int rowColToIndex(int row, int column) const; + void indexToRowCol(int index, int &row, int &column) const; protected: // property members: @@ -810,6 +1456,8 @@ class QCP_LIB_DECL QCPLayoutGrid : public QCPLayout QList mColumnStretchFactors; QList mRowStretchFactors; int mColumnSpacing, mRowSpacing; + int mWrap; + FillOrder mFillOrder; // non-virtual methods: void getMinimumRowColSizes(QVector *minColWidths, QVector *minRowHeights) const; @@ -818,6 +1466,7 @@ class QCP_LIB_DECL QCPLayoutGrid : public QCPLayout private: Q_DISABLE_COPY(QCPLayoutGrid) }; +Q_DECLARE_METATYPE(QCPLayoutGrid::FillOrder) class QCP_LIB_DECL QCPLayoutInset : public QCPLayout @@ -830,9 +1479,10 @@ class QCP_LIB_DECL QCPLayoutInset : public QCPLayout enum InsetPlacement { ipFree ///< The element may be positioned/sized arbitrarily, see \ref setInsetRect ,ipBorderAligned ///< The element is aligned to one of the layout sides, see \ref setInsetAlignment }; + Q_ENUMS(InsetPlacement) explicit QCPLayoutInset(); - virtual ~QCPLayoutInset(); + virtual ~QCPLayoutInset() Q_DECL_OVERRIDE; // getters: InsetPlacement insetPlacement(int index) const; @@ -845,13 +1495,13 @@ class QCP_LIB_DECL QCPLayoutInset : public QCPLayout void setInsetRect(int index, const QRectF &rect); // reimplemented virtual methods: - virtual void updateLayout(); - virtual int elementCount() const; - virtual QCPLayoutElement* elementAt(int index) const; - virtual QCPLayoutElement* takeAt(int index); - virtual bool take(QCPLayoutElement* element); - virtual void simplify() {} - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + virtual void updateLayout() Q_DECL_OVERRIDE; + virtual int elementCount() const Q_DECL_OVERRIDE; + virtual QCPLayoutElement* elementAt(int index) const Q_DECL_OVERRIDE; + virtual QCPLayoutElement* takeAt(int index) Q_DECL_OVERRIDE; + virtual bool take(QCPLayoutElement* element) Q_DECL_OVERRIDE; + virtual void simplify() Q_DECL_OVERRIDE {} + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; // non-virtual methods: void addElement(QCPLayoutElement *element, Qt::Alignment alignment); @@ -867,8 +1517,14 @@ class QCP_LIB_DECL QCPLayoutInset : public QCPLayout private: Q_DISABLE_COPY(QCPLayoutInset) }; +Q_DECLARE_METATYPE(QCPLayoutInset::InsetPlacement) + +/* end of 'src/layout.h' */ +/* including file 'src/lineending.h' */ +/* modified 2022-11-06T12:45:56, size 4426 */ + class QCP_LIB_DECL QCPLineEnding { Q_GADGET @@ -884,18 +1540,18 @@ class QCP_LIB_DECL QCPLineEnding \see QCPItemLine::setHead, QCPItemLine::setTail, QCPItemCurve::setHead, QCPItemCurve::setTail, QCPAxis::setLowerEnding, QCPAxis::setUpperEnding */ - Q_ENUMS(EndingStyle) enum EndingStyle { esNone ///< No ending decoration ,esFlatArrow ///< A filled arrow head with a straight/flat back (a triangle) ,esSpikeArrow ///< A filled arrow head with an indented back ,esLineArrow ///< A non-filled arrow head with open back ,esDisc ///< A filled circle ,esSquare ///< A filled square - ,esDiamond ///< A filled diamond (45° rotated square) + ,esDiamond ///< A filled diamond (45 degrees rotated square) ,esBar ///< A bar perpendicular to the line ,esHalfBar ///< A bar perpendicular to the line, pointing out to only one side (to which side can be changed with \ref setInverted) ,esSkewedBar ///< A bar that is skewed (skew controllable via \ref setLength) }; + Q_ENUMS(EndingStyle) QCPLineEnding(); QCPLineEnding(EndingStyle style, double width=8, double length=10, bool inverted=false); @@ -915,8 +1571,8 @@ class QCP_LIB_DECL QCPLineEnding // non-property methods: double boundingDistance() const; double realLength() const; - void draw(QCPPainter *painter, const QVector2D &pos, const QVector2D &dir) const; - void draw(QCPPainter *painter, const QVector2D &pos, double angle) const; + void draw(QCPPainter *painter, const QCPVector2D &pos, const QCPVector2D &dir) const; + void draw(QCPPainter *painter, const QCPVector2D &pos, double angle) const; protected: // property members: @@ -925,91 +1581,566 @@ class QCP_LIB_DECL QCPLineEnding bool mInverted; }; Q_DECLARE_TYPEINFO(QCPLineEnding, Q_MOVABLE_TYPE); +Q_DECLARE_METATYPE(QCPLineEnding::EndingStyle) +/* end of 'src/lineending.h' */ -class QCP_LIB_DECL QCPGrid :public QCPLayerable + +/* including file 'src/axis/labelpainter.h' */ +/* modified 2022-11-06T12:45:56, size 7086 */ + +class QCPLabelPainterPrivate { - Q_OBJECT - /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(bool subGridVisible READ subGridVisible WRITE setSubGridVisible) - Q_PROPERTY(bool antialiasedSubGrid READ antialiasedSubGrid WRITE setAntialiasedSubGrid) - Q_PROPERTY(bool antialiasedZeroLine READ antialiasedZeroLine WRITE setAntialiasedZeroLine) - Q_PROPERTY(QPen pen READ pen WRITE setPen) - Q_PROPERTY(QPen subGridPen READ subGridPen WRITE setSubGridPen) - Q_PROPERTY(QPen zeroLinePen READ zeroLinePen WRITE setZeroLinePen) - /// \endcond + Q_GADGET public: - QCPGrid(QCPAxis *parentAxis); + /*! + TODO + */ + enum AnchorMode { amRectangular ///< + ,amSkewedUpright ///< + ,amSkewedRotated ///< + }; + Q_ENUMS(AnchorMode) - // getters: - bool subGridVisible() const { return mSubGridVisible; } - bool antialiasedSubGrid() const { return mAntialiasedSubGrid; } - bool antialiasedZeroLine() const { return mAntialiasedZeroLine; } - QPen pen() const { return mPen; } - QPen subGridPen() const { return mSubGridPen; } - QPen zeroLinePen() const { return mZeroLinePen; } + /*! + TODO + */ + enum AnchorReferenceType { artNormal ///< + ,artTangent ///< + }; + Q_ENUMS(AnchorReferenceType) + + /*! + TODO + */ + enum AnchorSide { asLeft ///< + ,asRight ///< + ,asTop ///< + ,asBottom ///< + ,asTopLeft + ,asTopRight + ,asBottomRight + ,asBottomLeft + }; + Q_ENUMS(AnchorSide) + + explicit QCPLabelPainterPrivate(QCustomPlot *parentPlot); + virtual ~QCPLabelPainterPrivate(); // setters: - void setSubGridVisible(bool visible); - void setAntialiasedSubGrid(bool enabled); - void setAntialiasedZeroLine(bool enabled); - void setPen(const QPen &pen); - void setSubGridPen(const QPen &pen); - void setZeroLinePen(const QPen &pen); + void setAnchorSide(AnchorSide side); + void setAnchorMode(AnchorMode mode); + void setAnchorReference(const QPointF &pixelPoint); + void setAnchorReferenceType(AnchorReferenceType type); + void setFont(const QFont &font); + void setColor(const QColor &color); + void setPadding(int padding); + void setRotation(double rotation); + void setSubstituteExponent(bool enabled); + void setMultiplicationSymbol(QChar symbol); + void setAbbreviateDecimalPowers(bool enabled); + void setCacheSize(int labelCount); + + // getters: + AnchorMode anchorMode() const { return mAnchorMode; } + AnchorSide anchorSide() const { return mAnchorSide; } + QPointF anchorReference() const { return mAnchorReference; } + AnchorReferenceType anchorReferenceType() const { return mAnchorReferenceType; } + QFont font() const { return mFont; } + QColor color() const { return mColor; } + int padding() const { return mPadding; } + double rotation() const { return mRotation; } + bool substituteExponent() const { return mSubstituteExponent; } + QChar multiplicationSymbol() const { return mMultiplicationSymbol; } + bool abbreviateDecimalPowers() const { return mAbbreviateDecimalPowers; } + int cacheSize() const; + + //virtual int size() const; + + // non-property methods: + void drawTickLabel(QCPPainter *painter, const QPointF &tickPos, const QString &text); + void clearCache(); + + // constants that may be used with setMultiplicationSymbol: + static const QChar SymbolDot; + static const QChar SymbolCross; protected: + struct CachedLabel + { + QPoint offset; + QPixmap pixmap; + }; + struct LabelData + { + AnchorSide side; + double rotation; // angle in degrees + QTransform transform; // the transform about the label anchor which is at (0, 0). Does not contain final absolute x/y positioning on the plot/axis + QString basePart, expPart, suffixPart; + QRect baseBounds, expBounds, suffixBounds; + QRect totalBounds; // is in a coordinate system where label top left is at (0, 0) + QRect rotatedTotalBounds; // is in a coordinate system where the label anchor is at (0, 0) + QFont baseFont, expFont; + QColor color; + }; + // property members: - bool mSubGridVisible; - bool mAntialiasedSubGrid, mAntialiasedZeroLine; - QPen mPen, mSubGridPen, mZeroLinePen; + AnchorMode mAnchorMode; + AnchorSide mAnchorSide; + QPointF mAnchorReference; + AnchorReferenceType mAnchorReferenceType; + QFont mFont; + QColor mColor; + int mPadding; + double mRotation; // this is the rotation applied uniformly to all labels, not the heterogeneous rotation in amCircularRotated mode + bool mSubstituteExponent; + QChar mMultiplicationSymbol; + bool mAbbreviateDecimalPowers; // non-property members: - QCPAxis *mParentAxis; - - // reimplemented virtual methods: - virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; - virtual void draw(QCPPainter *painter); + QCustomPlot *mParentPlot; + QByteArray mLabelParameterHash; // to determine whether mLabelCache needs to be cleared due to changed parameters + QCache mLabelCache; + QRect mAxisSelectionBox, mTickLabelsSelectionBox, mLabelSelectionBox; + int mLetterCapHeight, mLetterDescent; + // introduced virtual methods: + virtual void drawLabelMaybeCached(QCPPainter *painter, const QFont &font, const QColor &color, const QPointF &pos, AnchorSide side, double rotation, const QString &text); + virtual QByteArray generateLabelParameterHash() const; // TODO: get rid of this in favor of invalidation flag upon setters? + // non-virtual methods: - void drawGridLines(QCPPainter *painter) const; - void drawSubGridLines(QCPPainter *painter) const; - - friend class QCPAxis; + QPointF getAnchorPos(const QPointF &tickPos); + void drawText(QCPPainter *painter, const QPointF &pos, const LabelData &labelData) const; + LabelData getTickLabelData(const QFont &font, const QColor &color, double rotation, AnchorSide side, const QString &text) const; + void applyAnchorTransform(LabelData &labelData) const; + //void getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const; + CachedLabel *createCachedLabel(const LabelData &labelData) const; + QByteArray cacheKey(const QString &text, const QColor &color, double rotation, AnchorSide side) const; + AnchorSide skewedAnchorSide(const QPointF &tickPos, double sideExpandHorz, double sideExpandVert) const; + AnchorSide rotationCorrectedSide(AnchorSide side, double rotation) const; + void analyzeFontMetrics(); }; +Q_DECLARE_METATYPE(QCPLabelPainterPrivate::AnchorMode) +Q_DECLARE_METATYPE(QCPLabelPainterPrivate::AnchorSide) -class QCP_LIB_DECL QCPAxis : public QCPLayerable +/* end of 'src/axis/labelpainter.h' */ + + +/* including file 'src/axis/axisticker.h' */ +/* modified 2022-11-06T12:45:56, size 4230 */ + +class QCP_LIB_DECL QCPAxisTicker { - Q_OBJECT - /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(AxisType axisType READ axisType) - Q_PROPERTY(QCPAxisRect* axisRect READ axisRect) - Q_PROPERTY(ScaleType scaleType READ scaleType WRITE setScaleType NOTIFY scaleTypeChanged) - Q_PROPERTY(double scaleLogBase READ scaleLogBase WRITE setScaleLogBase) - Q_PROPERTY(QCPRange range READ range WRITE setRange NOTIFY rangeChanged) - Q_PROPERTY(bool rangeReversed READ rangeReversed WRITE setRangeReversed) - Q_PROPERTY(bool autoTicks READ autoTicks WRITE setAutoTicks) - Q_PROPERTY(int autoTickCount READ autoTickCount WRITE setAutoTickCount) - Q_PROPERTY(bool autoTickLabels READ autoTickLabels WRITE setAutoTickLabels) - Q_PROPERTY(bool autoTickStep READ autoTickStep WRITE setAutoTickStep) - Q_PROPERTY(bool autoSubTicks READ autoSubTicks WRITE setAutoSubTicks) - Q_PROPERTY(bool ticks READ ticks WRITE setTicks) - Q_PROPERTY(bool tickLabels READ tickLabels WRITE setTickLabels) - Q_PROPERTY(int tickLabelPadding READ tickLabelPadding WRITE setTickLabelPadding) - Q_PROPERTY(LabelType tickLabelType READ tickLabelType WRITE setTickLabelType) - Q_PROPERTY(QFont tickLabelFont READ tickLabelFont WRITE setTickLabelFont) - Q_PROPERTY(QColor tickLabelColor READ tickLabelColor WRITE setTickLabelColor) - Q_PROPERTY(double tickLabelRotation READ tickLabelRotation WRITE setTickLabelRotation) + Q_GADGET +public: + /*! + Defines the strategies that the axis ticker may follow when choosing the size of the tick step. + + \see setTickStepStrategy + */ + enum TickStepStrategy + { + tssReadability ///< A nicely readable tick step is prioritized over matching the requested number of ticks (see \ref setTickCount) + ,tssMeetTickCount ///< Less readable tick steps are allowed which in turn facilitates getting closer to the requested tick count + }; + Q_ENUMS(TickStepStrategy) + + QCPAxisTicker(); + virtual ~QCPAxisTicker(); + + // getters: + TickStepStrategy tickStepStrategy() const { return mTickStepStrategy; } + int tickCount() const { return mTickCount; } + double tickOrigin() const { return mTickOrigin; } + + // setters: + void setTickStepStrategy(TickStepStrategy strategy); + void setTickCount(int count); + void setTickOrigin(double origin); + + // introduced virtual methods: + virtual void generate(const QCPRange &range, const QLocale &locale, QChar formatChar, int precision, QVector &ticks, QVector *subTicks, QVector *tickLabels); + +protected: + // property members: + TickStepStrategy mTickStepStrategy; + int mTickCount; + double mTickOrigin; + + // introduced virtual methods: + virtual double getTickStep(const QCPRange &range); + virtual int getSubTickCount(double tickStep); + virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision); + virtual QVector createTickVector(double tickStep, const QCPRange &range); + virtual QVector createSubTickVector(int subTickCount, const QVector &ticks); + virtual QVector createLabelVector(const QVector &ticks, const QLocale &locale, QChar formatChar, int precision); + + // non-virtual methods: + void trimTicks(const QCPRange &range, QVector &ticks, bool keepOneOutlier) const; + double pickClosest(double target, const QVector &candidates) const; + double getMantissa(double input, double *magnitude=nullptr) const; + double cleanMantissa(double input) const; + +private: + Q_DISABLE_COPY(QCPAxisTicker) + +}; +Q_DECLARE_METATYPE(QCPAxisTicker::TickStepStrategy) +Q_DECLARE_METATYPE(QSharedPointer) + +/* end of 'src/axis/axisticker.h' */ + + +/* including file 'src/axis/axistickerdatetime.h' */ +/* modified 2022-11-06T12:45:56, size 3600 */ + +class QCP_LIB_DECL QCPAxisTickerDateTime : public QCPAxisTicker +{ +public: + QCPAxisTickerDateTime(); + + // getters: + QString dateTimeFormat() const { return mDateTimeFormat; } + Qt::TimeSpec dateTimeSpec() const { return mDateTimeSpec; } +# if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) + QTimeZone timeZone() const { return mTimeZone; } +#endif + + // setters: + void setDateTimeFormat(const QString &format); + void setDateTimeSpec(Qt::TimeSpec spec); +# if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) + void setTimeZone(const QTimeZone &zone); +# endif + void setTickOrigin(double origin); // hides base class method but calls baseclass implementation ("using" throws off IDEs and doxygen) + void setTickOrigin(const QDateTime &origin); + + // static methods: + static QDateTime keyToDateTime(double key); + static double dateTimeToKey(const QDateTime &dateTime); + static double dateTimeToKey(const QDate &date, Qt::TimeSpec timeSpec=Qt::LocalTime); + +protected: + // property members: + QString mDateTimeFormat; + Qt::TimeSpec mDateTimeSpec; +# if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) + QTimeZone mTimeZone; +# endif + // non-property members: + enum DateStrategy {dsNone, dsUniformTimeInDay, dsUniformDayInMonth} mDateStrategy; + + // reimplemented virtual methods: + virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE; + virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE; + virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) Q_DECL_OVERRIDE; + virtual QVector createTickVector(double tickStep, const QCPRange &range) Q_DECL_OVERRIDE; +}; + +/* end of 'src/axis/axistickerdatetime.h' */ + + +/* including file 'src/axis/axistickertime.h' */ +/* modified 2022-11-06T12:45:56, size 3542 */ + +class QCP_LIB_DECL QCPAxisTickerTime : public QCPAxisTicker +{ + Q_GADGET +public: + /*! + Defines the logical units in which fractions of time spans can be expressed. + + \see setFieldWidth, setTimeFormat + */ + enum TimeUnit { tuMilliseconds ///< Milliseconds, one thousandth of a second (%%z in \ref setTimeFormat) + ,tuSeconds ///< Seconds (%%s in \ref setTimeFormat) + ,tuMinutes ///< Minutes (%%m in \ref setTimeFormat) + ,tuHours ///< Hours (%%h in \ref setTimeFormat) + ,tuDays ///< Days (%%d in \ref setTimeFormat) + }; + Q_ENUMS(TimeUnit) + + QCPAxisTickerTime(); + + // getters: + QString timeFormat() const { return mTimeFormat; } + int fieldWidth(TimeUnit unit) const { return mFieldWidth.value(unit); } + + // setters: + void setTimeFormat(const QString &format); + void setFieldWidth(TimeUnit unit, int width); + +protected: + // property members: + QString mTimeFormat; + QHash mFieldWidth; + + // non-property members: + TimeUnit mSmallestUnit, mBiggestUnit; + QHash mFormatPattern; + + // reimplemented virtual methods: + virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE; + virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE; + virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) Q_DECL_OVERRIDE; + + // non-virtual methods: + void replaceUnit(QString &text, TimeUnit unit, int value) const; +}; +Q_DECLARE_METATYPE(QCPAxisTickerTime::TimeUnit) + +/* end of 'src/axis/axistickertime.h' */ + + +/* including file 'src/axis/axistickerfixed.h' */ +/* modified 2022-11-06T12:45:56, size 3308 */ + +class QCP_LIB_DECL QCPAxisTickerFixed : public QCPAxisTicker +{ + Q_GADGET +public: + /*! + Defines how the axis ticker may modify the specified tick step (\ref setTickStep) in order to + control the number of ticks in the axis range. + + \see setScaleStrategy + */ + enum ScaleStrategy { ssNone ///< Modifications are not allowed, the specified tick step is absolutely fixed. This might cause a high tick density and overlapping labels if the axis range is zoomed out. + ,ssMultiples ///< An integer multiple of the specified tick step is allowed. The used factor follows the base class properties of \ref setTickStepStrategy and \ref setTickCount. + ,ssPowers ///< An integer power of the specified tick step is allowed. + }; + Q_ENUMS(ScaleStrategy) + + QCPAxisTickerFixed(); + + // getters: + double tickStep() const { return mTickStep; } + ScaleStrategy scaleStrategy() const { return mScaleStrategy; } + + // setters: + void setTickStep(double step); + void setScaleStrategy(ScaleStrategy strategy); + +protected: + // property members: + double mTickStep; + ScaleStrategy mScaleStrategy; + + // reimplemented virtual methods: + virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE; +}; +Q_DECLARE_METATYPE(QCPAxisTickerFixed::ScaleStrategy) + +/* end of 'src/axis/axistickerfixed.h' */ + + +/* including file 'src/axis/axistickertext.h' */ +/* modified 2022-11-06T12:45:56, size 3090 */ + +class QCP_LIB_DECL QCPAxisTickerText : public QCPAxisTicker +{ +public: + QCPAxisTickerText(); + + // getters: + QMap &ticks() { return mTicks; } + int subTickCount() const { return mSubTickCount; } + + // setters: + void setTicks(const QMap &ticks); + void setTicks(const QVector &positions, const QVector &labels); + void setSubTickCount(int subTicks); + + // non-virtual methods: + void clear(); + void addTick(double position, const QString &label); + void addTicks(const QMap &ticks); + void addTicks(const QVector &positions, const QVector &labels); + +protected: + // property members: + QMap mTicks; + int mSubTickCount; + + // reimplemented virtual methods: + virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE; + virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE; + virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) Q_DECL_OVERRIDE; + virtual QVector createTickVector(double tickStep, const QCPRange &range) Q_DECL_OVERRIDE; +}; + +/* end of 'src/axis/axistickertext.h' */ + + +/* including file 'src/axis/axistickerpi.h' */ +/* modified 2022-11-06T12:45:56, size 3911 */ + +class QCP_LIB_DECL QCPAxisTickerPi : public QCPAxisTicker +{ + Q_GADGET +public: + /*! + Defines how fractions should be displayed in tick labels. + + \see setFractionStyle + */ + enum FractionStyle { fsFloatingPoint ///< Fractions are displayed as regular decimal floating point numbers, e.g. "0.25" or "0.125". + ,fsAsciiFractions ///< Fractions are written as rationals using ASCII characters only, e.g. "1/4" or "1/8" + ,fsUnicodeFractions ///< Fractions are written using sub- and superscript UTF-8 digits and the fraction symbol. + }; + Q_ENUMS(FractionStyle) + + QCPAxisTickerPi(); + + // getters: + QString piSymbol() const { return mPiSymbol; } + double piValue() const { return mPiValue; } + bool periodicity() const { return mPeriodicity; } + FractionStyle fractionStyle() const { return mFractionStyle; } + + // setters: + void setPiSymbol(QString symbol); + void setPiValue(double pi); + void setPeriodicity(int multiplesOfPi); + void setFractionStyle(FractionStyle style); + +protected: + // property members: + QString mPiSymbol; + double mPiValue; + int mPeriodicity; + FractionStyle mFractionStyle; + + // non-property members: + double mPiTickStep; // size of one tick step in units of mPiValue + + // reimplemented virtual methods: + virtual double getTickStep(const QCPRange &range) Q_DECL_OVERRIDE; + virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE; + virtual QString getTickLabel(double tick, const QLocale &locale, QChar formatChar, int precision) Q_DECL_OVERRIDE; + + // non-virtual methods: + void simplifyFraction(int &numerator, int &denominator) const; + QString fractionToString(int numerator, int denominator) const; + QString unicodeFraction(int numerator, int denominator) const; + QString unicodeSuperscript(int number) const; + QString unicodeSubscript(int number) const; +}; +Q_DECLARE_METATYPE(QCPAxisTickerPi::FractionStyle) + +/* end of 'src/axis/axistickerpi.h' */ + + +/* including file 'src/axis/axistickerlog.h' */ +/* modified 2022-11-06T12:45:56, size 2594 */ + +class QCP_LIB_DECL QCPAxisTickerLog : public QCPAxisTicker +{ +public: + QCPAxisTickerLog(); + + // getters: + double logBase() const { return mLogBase; } + int subTickCount() const { return mSubTickCount; } + + // setters: + void setLogBase(double base); + void setSubTickCount(int subTicks); + +protected: + // property members: + double mLogBase; + int mSubTickCount; + + // non-property members: + double mLogBaseLnInv; + + // reimplemented virtual methods: + virtual int getSubTickCount(double tickStep) Q_DECL_OVERRIDE; + virtual QVector createTickVector(double tickStep, const QCPRange &range) Q_DECL_OVERRIDE; +}; + +/* end of 'src/axis/axistickerlog.h' */ + + +/* including file 'src/axis/axis.h' */ +/* modified 2022-11-06T12:45:56, size 20913 */ + +class QCP_LIB_DECL QCPGrid :public QCPLayerable +{ + Q_OBJECT + /// \cond INCLUDE_QPROPERTIES + Q_PROPERTY(bool subGridVisible READ subGridVisible WRITE setSubGridVisible) + Q_PROPERTY(bool antialiasedSubGrid READ antialiasedSubGrid WRITE setAntialiasedSubGrid) + Q_PROPERTY(bool antialiasedZeroLine READ antialiasedZeroLine WRITE setAntialiasedZeroLine) + Q_PROPERTY(QPen pen READ pen WRITE setPen) + Q_PROPERTY(QPen subGridPen READ subGridPen WRITE setSubGridPen) + Q_PROPERTY(QPen zeroLinePen READ zeroLinePen WRITE setZeroLinePen) + /// \endcond +public: + explicit QCPGrid(QCPAxis *parentAxis); + + // getters: + bool subGridVisible() const { return mSubGridVisible; } + bool antialiasedSubGrid() const { return mAntialiasedSubGrid; } + bool antialiasedZeroLine() const { return mAntialiasedZeroLine; } + QPen pen() const { return mPen; } + QPen subGridPen() const { return mSubGridPen; } + QPen zeroLinePen() const { return mZeroLinePen; } + + // setters: + void setSubGridVisible(bool visible); + void setAntialiasedSubGrid(bool enabled); + void setAntialiasedZeroLine(bool enabled); + void setPen(const QPen &pen); + void setSubGridPen(const QPen &pen); + void setZeroLinePen(const QPen &pen); + +protected: + // property members: + bool mSubGridVisible; + bool mAntialiasedSubGrid, mAntialiasedZeroLine; + QPen mPen, mSubGridPen, mZeroLinePen; + + // non-property members: + QCPAxis *mParentAxis; + + // reimplemented virtual methods: + virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + + // non-virtual methods: + void drawGridLines(QCPPainter *painter) const; + void drawSubGridLines(QCPPainter *painter) const; + + friend class QCPAxis; +}; + + +class QCP_LIB_DECL QCPAxis : public QCPLayerable +{ + Q_OBJECT + /// \cond INCLUDE_QPROPERTIES + Q_PROPERTY(AxisType axisType READ axisType) + Q_PROPERTY(QCPAxisRect* axisRect READ axisRect) + Q_PROPERTY(ScaleType scaleType READ scaleType WRITE setScaleType NOTIFY scaleTypeChanged) + Q_PROPERTY(QCPRange range READ range WRITE setRange NOTIFY rangeChanged) + Q_PROPERTY(bool rangeReversed READ rangeReversed WRITE setRangeReversed) + Q_PROPERTY(QSharedPointer ticker READ ticker WRITE setTicker) + Q_PROPERTY(bool ticks READ ticks WRITE setTicks) + Q_PROPERTY(bool tickLabels READ tickLabels WRITE setTickLabels) + Q_PROPERTY(int tickLabelPadding READ tickLabelPadding WRITE setTickLabelPadding) + Q_PROPERTY(QFont tickLabelFont READ tickLabelFont WRITE setTickLabelFont) + Q_PROPERTY(QColor tickLabelColor READ tickLabelColor WRITE setTickLabelColor) + Q_PROPERTY(double tickLabelRotation READ tickLabelRotation WRITE setTickLabelRotation) Q_PROPERTY(LabelSide tickLabelSide READ tickLabelSide WRITE setTickLabelSide) - Q_PROPERTY(QString dateTimeFormat READ dateTimeFormat WRITE setDateTimeFormat) - Q_PROPERTY(Qt::TimeSpec dateTimeSpec READ dateTimeSpec WRITE setDateTimeSpec) Q_PROPERTY(QString numberFormat READ numberFormat WRITE setNumberFormat) Q_PROPERTY(int numberPrecision READ numberPrecision WRITE setNumberPrecision) - Q_PROPERTY(double tickStep READ tickStep WRITE setTickStep) - Q_PROPERTY(QVector tickVector READ tickVector WRITE setTickVector) - Q_PROPERTY(QVector tickVectorLabels READ tickVectorLabels WRITE setTickVectorLabels) + Q_PROPERTY(QVector tickVector READ tickVector) + Q_PROPERTY(QVector tickVectorLabels READ tickVectorLabels) Q_PROPERTY(int tickLengthIn READ tickLengthIn WRITE setTickLengthIn) Q_PROPERTY(int tickLengthOut READ tickLengthOut WRITE setTickLengthOut) - Q_PROPERTY(int subTickCount READ subTickCount WRITE setSubTickCount) + Q_PROPERTY(bool subTicks READ subTicks WRITE setSubTicks) Q_PROPERTY(int subTickLengthIn READ subTickLengthIn WRITE setSubTickLengthIn) Q_PROPERTY(int subTickLengthOut READ subTickLengthOut WRITE setSubTickLengthOut) Q_PROPERTY(QPen basePen READ basePen WRITE setBasePen) @@ -1044,18 +2175,9 @@ class QCP_LIB_DECL QCPAxis : public QCPLayerable ,atTop = 0x04 ///< 0x04 Axis is horizontal and on the top side of the axis rect ,atBottom = 0x08 ///< 0x08 Axis is horizontal and on the bottom side of the axis rect }; - Q_FLAGS(AxisType AxisTypes) + Q_ENUMS(AxisType) + Q_FLAGS(AxisTypes) Q_DECLARE_FLAGS(AxisTypes, AxisType) - /*! - When automatic tick label generation is enabled (\ref setAutoTickLabels), defines how the - coordinate of the tick is interpreted, i.e. translated into a string. - - \see setTickLabelType - */ - enum LabelType { ltNumber ///< Tick coordinate is regarded as normal number and will be displayed as such. (see \ref setNumberFormat) - ,ltDateTime ///< Tick coordinate is regarded as a date/time (seconds since 1970-01-01T00:00:00 UTC) and will be displayed and formatted as such. (for details, see \ref setDateTimeFormat) - }; - Q_ENUMS(LabelType) /*! Defines on which side of the axis the tick labels (numbers) shall appear. @@ -1070,7 +2192,7 @@ class QCP_LIB_DECL QCPAxis : public QCPLayerable \see setScaleType */ enum ScaleType { stLinear ///< Linear scaling - ,stLogarithmic ///< Logarithmic scaling with correspondingly transformed plots and (major) tick marks at every base power (see \ref setScaleLogBase). + ,stLogarithmic ///< Logarithmic scaling with correspondingly transformed axis coordinates (possibly also \ref setTicker to a \ref QCPAxisTickerLog instance). }; Q_ENUMS(ScaleType) /*! @@ -1082,42 +2204,34 @@ class QCP_LIB_DECL QCPAxis : public QCPLayerable ,spTickLabels = 0x002 ///< Tick labels (numbers) of this axis (as a whole, not individually) ,spAxisLabel = 0x004 ///< The axis label }; - Q_FLAGS(SelectablePart SelectableParts) + Q_ENUMS(SelectablePart) + Q_FLAGS(SelectableParts) Q_DECLARE_FLAGS(SelectableParts, SelectablePart) explicit QCPAxis(QCPAxisRect *parent, AxisType type); - virtual ~QCPAxis(); + virtual ~QCPAxis() Q_DECL_OVERRIDE; // getters: AxisType axisType() const { return mAxisType; } QCPAxisRect *axisRect() const { return mAxisRect; } ScaleType scaleType() const { return mScaleType; } - double scaleLogBase() const { return mScaleLogBase; } const QCPRange range() const { return mRange; } bool rangeReversed() const { return mRangeReversed; } - bool autoTicks() const { return mAutoTicks; } - int autoTickCount() const { return mAutoTickCount; } - bool autoTickLabels() const { return mAutoTickLabels; } - bool autoTickStep() const { return mAutoTickStep; } - bool autoSubTicks() const { return mAutoSubTicks; } + QSharedPointer ticker() const { return mTicker; } bool ticks() const { return mTicks; } bool tickLabels() const { return mTickLabels; } int tickLabelPadding() const; - LabelType tickLabelType() const { return mTickLabelType; } QFont tickLabelFont() const { return mTickLabelFont; } QColor tickLabelColor() const { return mTickLabelColor; } double tickLabelRotation() const; LabelSide tickLabelSide() const; - QString dateTimeFormat() const { return mDateTimeFormat; } - Qt::TimeSpec dateTimeSpec() const { return mDateTimeSpec; } QString numberFormat() const; int numberPrecision() const { return mNumberPrecision; } - double tickStep() const { return mTickStep; } QVector tickVector() const { return mTickVector; } QVector tickVectorLabels() const { return mTickVectorLabels; } int tickLengthIn() const; int tickLengthOut() const; - int subTickCount() const { return mSubTickCount; } + bool subTicks() const { return mSubTicks; } int subTickLengthIn() const; int subTickLengthOut() const; QPen basePen() const { return mBasePen; } @@ -1144,37 +2258,26 @@ class QCP_LIB_DECL QCPAxis : public QCPLayerable // setters: Q_SLOT void setScaleType(QCPAxis::ScaleType type); - void setScaleLogBase(double base); Q_SLOT void setRange(const QCPRange &range); void setRange(double lower, double upper); void setRange(double position, double size, Qt::AlignmentFlag alignment); void setRangeLower(double lower); void setRangeUpper(double upper); void setRangeReversed(bool reversed); - void setAutoTicks(bool on); - void setAutoTickCount(int approximateCount); - void setAutoTickLabels(bool on); - void setAutoTickStep(bool on); - void setAutoSubTicks(bool on); + void setTicker(QSharedPointer ticker); void setTicks(bool show); void setTickLabels(bool show); void setTickLabelPadding(int padding); - void setTickLabelType(LabelType type); void setTickLabelFont(const QFont &font); void setTickLabelColor(const QColor &color); void setTickLabelRotation(double degrees); void setTickLabelSide(LabelSide side); - void setDateTimeFormat(const QString &format); - void setDateTimeSpec(const Qt::TimeSpec &timeSpec); void setNumberFormat(const QString &formatCode); void setNumberPrecision(int precision); - void setTickStep(double step); - void setTickVector(const QVector &vec); - void setTickVectorLabels(const QVector &vec); void setTickLength(int inside, int outside=0); void setTickLengthIn(int inside); void setTickLengthOut(int outside); - void setSubTickCount(int count); + void setSubTicks(bool show); void setSubTickLength(int inside, int outside=0); void setSubTickLengthIn(int inside); void setSubTickLengthOut(int outside); @@ -1200,11 +2303,13 @@ class QCP_LIB_DECL QCPAxis : public QCPLayerable void setUpperEnding(const QCPLineEnding &ending); // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; // non-property methods: Qt::Orientation orientation() const { return mOrientation; } + int pixelOrientation() const { return rangeReversed() != (orientation()==Qt::Vertical) ? -1 : 1; } void moveRange(double diff); + void scaleRange(double factor); void scaleRange(double factor, double center); void setScaleRatio(const QCPAxis *otherAxis, double ratio=1.0); void rescale(bool onlyVisiblePlottables=false); @@ -1216,11 +2321,10 @@ class QCP_LIB_DECL QCPAxis : public QCPLayerable QList items() const; static AxisType marginSideToAxisType(QCP::MarginSide side); - static Qt::Orientation orientation(AxisType type) { return type==atBottom||type==atTop ? Qt::Horizontal : Qt::Vertical; } + static Qt::Orientation orientation(AxisType type) { return type==atBottom || type==atTop ? Qt::Horizontal : Qt::Vertical; } static AxisType opposite(AxisType type); signals: - void ticksRequest(); void rangeChanged(const QCPRange &newRange); void rangeChanged(const QCPRange &newRange, const QCPRange &oldRange); void scaleTypeChanged(QCPAxis::ScaleType scaleType); @@ -1245,22 +2349,17 @@ class QCP_LIB_DECL QCPAxis : public QCPLayerable QColor mLabelColor, mSelectedLabelColor; // tick labels: //int mTickLabelPadding; // in QCPAxisPainter - bool mTickLabels, mAutoTickLabels; + bool mTickLabels; //double mTickLabelRotation; // in QCPAxisPainter - LabelType mTickLabelType; QFont mTickLabelFont, mSelectedTickLabelFont; QColor mTickLabelColor, mSelectedTickLabelColor; - QString mDateTimeFormat; - Qt::TimeSpec mDateTimeSpec; int mNumberPrecision; QLatin1Char mNumberFormatChar; bool mNumberBeautifulPowers; //bool mNumberMultiplyCross; // QCPAxisPainter // ticks and subticks: bool mTicks; - double mTickStep; - int mSubTickCount, mAutoTickCount; - bool mAutoTicks, mAutoTickStep, mAutoSubTicks; + bool mSubTicks; //int mTickLengthIn, mTickLengthOut, mSubTickLengthIn, mSubTickLengthOut; // QCPAxisPainter QPen mTickPen, mSelectedTickPen; QPen mSubTickPen, mSelectedSubTickPen; @@ -1268,36 +2367,38 @@ class QCP_LIB_DECL QCPAxis : public QCPLayerable QCPRange mRange; bool mRangeReversed; ScaleType mScaleType; - double mScaleLogBase, mScaleLogBaseLogInv; // non-property members: QCPGrid *mGrid; QCPAxisPainterPrivate *mAxisPainter; - int mLowestVisibleTick, mHighestVisibleTick; + QSharedPointer mTicker; QVector mTickVector; QVector mTickVectorLabels; QVector mSubTickVector; bool mCachedMarginValid; int mCachedMargin; + bool mDragging; + QCPRange mDragStartRange; + QCP::AntialiasedElements mAADragBackup, mNotAADragBackup; // introduced virtual methods: - virtual void setupTickVectors(); - virtual void generateAutoTicks(); - virtual int calculateAutoSubTickCount(double tickStep) const; virtual int calculateMargin(); // reimplemented virtual methods: - virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; - virtual void draw(QCPPainter *painter); - virtual QCP::Interaction selectionCategory() const; + virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE; // events: - virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); - virtual void deselectEvent(bool *selectionStateChanged); + virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE; + virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE; + // mouse events: + virtual void mousePressEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE; + virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE; + virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE; + virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE; // non-virtual methods: - void visibleTickBounds(int &lowIndex, int &highIndex) const; - double baseLog(double value) const; - double basePow(double value) const; + void setupTickVectors(); QPen getBasePen() const; QPen getTickPen() const; QPen getSubTickPen() const; @@ -1315,6 +2416,9 @@ class QCP_LIB_DECL QCPAxis : public QCPLayerable }; Q_DECLARE_OPERATORS_FOR_FLAGS(QCPAxis::SelectableParts) Q_DECLARE_OPERATORS_FOR_FLAGS(QCPAxis::AxisTypes) +Q_DECLARE_METATYPE(QCPAxis::AxisType) +Q_DECLARE_METATYPE(QCPAxis::LabelSide) +Q_DECLARE_METATYPE(QCPAxis::ScaleType) Q_DECLARE_METATYPE(QCPAxis::SelectablePart) @@ -1325,7 +2429,7 @@ class QCPAxisPainterPrivate virtual ~QCPAxisPainterPrivate(); virtual void draw(QCPPainter *painter); - virtual int size() const; + virtual int size(); void clearCache(); QRect axisSelectionBox() const { return mAxisSelectionBox; } @@ -1350,7 +2454,7 @@ class QCPAxisPainterPrivate QFont tickLabelFont; QColor tickLabelColor; QRect axisRect, viewportRect; - double offset; // directly accessed by QCPAxis setters/getters + int offset; // directly accessed by QCPAxis setters/getters bool abbreviateDecimalPowers; bool reversedEndings; @@ -1366,8 +2470,8 @@ class QCPAxisPainterPrivate }; struct TickLabelData { - QString basePart, expPart; - QRect baseBounds, expBounds, totalBounds, rotatedTotalBounds; + QString basePart, expPart, suffixPart; + QRect baseBounds, expBounds, suffixBounds, totalBounds, rotatedTotalBounds; QFont baseFont, expFont; }; QCustomPlot *mParentPlot; @@ -1384,734 +2488,1262 @@ class QCPAxisPainterPrivate virtual void getMaxTickLabelSize(const QFont &font, const QString &text, QSize *tickLabelsSize) const; }; +/* end of 'src/axis/axis.h' */ -class QCP_LIB_DECL QCPAbstractPlottable : public QCPLayerable + +/* including file 'src/scatterstyle.h' */ +/* modified 2022-11-06T12:45:56, size 7275 */ + +class QCP_LIB_DECL QCPScatterStyle { - Q_OBJECT - /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QString name READ name WRITE setName) - Q_PROPERTY(bool antialiasedFill READ antialiasedFill WRITE setAntialiasedFill) - Q_PROPERTY(bool antialiasedScatters READ antialiasedScatters WRITE setAntialiasedScatters) - Q_PROPERTY(bool antialiasedErrorBars READ antialiasedErrorBars WRITE setAntialiasedErrorBars) - Q_PROPERTY(QPen pen READ pen WRITE setPen) - Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) - Q_PROPERTY(QBrush brush READ brush WRITE setBrush) - Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) - Q_PROPERTY(QCPAxis* keyAxis READ keyAxis WRITE setKeyAxis) - Q_PROPERTY(QCPAxis* valueAxis READ valueAxis WRITE setValueAxis) - Q_PROPERTY(bool selectable READ selectable WRITE setSelectable NOTIFY selectableChanged) - Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectionChanged) - /// \endcond + Q_GADGET public: - QCPAbstractPlottable(QCPAxis *keyAxis, QCPAxis *valueAxis); + /*! + Represents the various properties of a scatter style instance. For example, this enum is used + to specify which properties of \ref QCPSelectionDecorator::setScatterStyle will be used when + highlighting selected data points. + + Specific scatter properties can be transferred between \ref QCPScatterStyle instances via \ref + setFromOther. + */ + enum ScatterProperty { spNone = 0x00 ///< 0x00 None + ,spPen = 0x01 ///< 0x01 The pen property, see \ref setPen + ,spBrush = 0x02 ///< 0x02 The brush property, see \ref setBrush + ,spSize = 0x04 ///< 0x04 The size property, see \ref setSize + ,spShape = 0x08 ///< 0x08 The shape property, see \ref setShape + ,spAll = 0xFF ///< 0xFF All properties + }; + Q_ENUMS(ScatterProperty) + Q_FLAGS(ScatterProperties) + Q_DECLARE_FLAGS(ScatterProperties, ScatterProperty) + + /*! + Defines the shape used for scatter points. + + On plottables/items that draw scatters, the sizes of these visualizations (with exception of + \ref ssDot and \ref ssPixmap) can be controlled with the \ref setSize function. Scatters are + drawn with the pen and brush specified with \ref setPen and \ref setBrush. + */ + enum ScatterShape { ssNone ///< no scatter symbols are drawn (e.g. in QCPGraph, data only represented with lines) + ,ssDot ///< \enumimage{ssDot.png} a single pixel (use \ref ssDisc or \ref ssCircle if you want a round shape with a certain radius) + ,ssCross ///< \enumimage{ssCross.png} a cross + ,ssPlus ///< \enumimage{ssPlus.png} a plus + ,ssCircle ///< \enumimage{ssCircle.png} a circle + ,ssDisc ///< \enumimage{ssDisc.png} a circle which is filled with the pen's color (not the brush as with ssCircle) + ,ssSquare ///< \enumimage{ssSquare.png} a square + ,ssDiamond ///< \enumimage{ssDiamond.png} a diamond + ,ssStar ///< \enumimage{ssStar.png} a star with eight arms, i.e. a combination of cross and plus + ,ssTriangle ///< \enumimage{ssTriangle.png} an equilateral triangle, standing on baseline + ,ssTriangleInverted ///< \enumimage{ssTriangleInverted.png} an equilateral triangle, standing on corner + ,ssCrossSquare ///< \enumimage{ssCrossSquare.png} a square with a cross inside + ,ssPlusSquare ///< \enumimage{ssPlusSquare.png} a square with a plus inside + ,ssCrossCircle ///< \enumimage{ssCrossCircle.png} a circle with a cross inside + ,ssPlusCircle ///< \enumimage{ssPlusCircle.png} a circle with a plus inside + ,ssPeace ///< \enumimage{ssPeace.png} a circle, with one vertical and two downward diagonal lines + ,ssPixmap ///< a custom pixmap specified by \ref setPixmap, centered on the data point coordinates + ,ssCustom ///< custom painter operations are performed per scatter (As QPainterPath, see \ref setCustomPath) + }; + Q_ENUMS(ScatterShape) + + QCPScatterStyle(); + QCPScatterStyle(ScatterShape shape, double size=6); + QCPScatterStyle(ScatterShape shape, const QColor &color, double size); + QCPScatterStyle(ScatterShape shape, const QColor &color, const QColor &fill, double size); + QCPScatterStyle(ScatterShape shape, const QPen &pen, const QBrush &brush, double size); + QCPScatterStyle(const QPixmap &pixmap); + QCPScatterStyle(const QPainterPath &customPath, const QPen &pen, const QBrush &brush=Qt::NoBrush, double size=6); // getters: - QString name() const { return mName; } - bool antialiasedFill() const { return mAntialiasedFill; } - bool antialiasedScatters() const { return mAntialiasedScatters; } - bool antialiasedErrorBars() const { return mAntialiasedErrorBars; } + double size() const { return mSize; } + ScatterShape shape() const { return mShape; } QPen pen() const { return mPen; } - QPen selectedPen() const { return mSelectedPen; } QBrush brush() const { return mBrush; } - QBrush selectedBrush() const { return mSelectedBrush; } - QCPAxis *keyAxis() const { return mKeyAxis.data(); } - QCPAxis *valueAxis() const { return mValueAxis.data(); } - bool selectable() const { return mSelectable; } - bool selected() const { return mSelected; } - + QPixmap pixmap() const { return mPixmap; } + QPainterPath customPath() const { return mCustomPath; } + // setters: - void setName(const QString &name); - void setAntialiasedFill(bool enabled); - void setAntialiasedScatters(bool enabled); - void setAntialiasedErrorBars(bool enabled); + void setFromOther(const QCPScatterStyle &other, ScatterProperties properties); + void setSize(double size); + void setShape(ScatterShape shape); void setPen(const QPen &pen); - void setSelectedPen(const QPen &pen); void setBrush(const QBrush &brush); - void setSelectedBrush(const QBrush &brush); - void setKeyAxis(QCPAxis *axis); - void setValueAxis(QCPAxis *axis); - Q_SLOT void setSelectable(bool selectable); - Q_SLOT void setSelected(bool selected); + void setPixmap(const QPixmap &pixmap); + void setCustomPath(const QPainterPath &customPath); - // introduced virtual methods: - virtual void clearData() = 0; - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const = 0; - virtual bool addToLegend(); - virtual bool removeFromLegend() const; - // non-property methods: - void rescaleAxes(bool onlyEnlarge=false) const; - void rescaleKeyAxis(bool onlyEnlarge=false) const; - void rescaleValueAxis(bool onlyEnlarge=false) const; - -signals: - void selectionChanged(bool selected); - void selectableChanged(bool selectable); - + bool isNone() const { return mShape == ssNone; } + bool isPenDefined() const { return mPenDefined; } + void undefinePen(); + void applyTo(QCPPainter *painter, const QPen &defaultPen) const; + void drawShape(QCPPainter *painter, const QPointF &pos) const; + void drawShape(QCPPainter *painter, double x, double y) const; + protected: - /*! - Represents negative and positive sign domain for passing to \ref getKeyRange and \ref getValueRange. - */ - enum SignDomain { sdNegative ///< The negative sign domain, i.e. numbers smaller than zero - ,sdBoth ///< Both sign domains, including zero, i.e. all (rational) numbers - ,sdPositive ///< The positive sign domain, i.e. numbers greater than zero - }; - // property members: - QString mName; - bool mAntialiasedFill, mAntialiasedScatters, mAntialiasedErrorBars; - QPen mPen, mSelectedPen; - QBrush mBrush, mSelectedBrush; - QPointer mKeyAxis, mValueAxis; - bool mSelectable, mSelected; - - // reimplemented virtual methods: - virtual QRect clipRect() const; - virtual void draw(QCPPainter *painter) = 0; - virtual QCP::Interaction selectionCategory() const; - void applyDefaultAntialiasingHint(QCPPainter *painter) const; - // events: - virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); - virtual void deselectEvent(bool *selectionStateChanged); - - // introduced virtual methods: - virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const = 0; - virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const = 0; - virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const = 0; - - // non-virtual methods: - void coordsToPixels(double key, double value, double &x, double &y) const; - const QPointF coordsToPixels(double key, double value) const; - void pixelsToCoords(double x, double y, double &key, double &value) const; - void pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const; - QPen mainPen() const; - QBrush mainBrush() const; - void applyFillAntialiasingHint(QCPPainter *painter) const; - void applyScattersAntialiasingHint(QCPPainter *painter) const; - void applyErrorBarsAntialiasingHint(QCPPainter *painter) const; - double distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const; - -private: - Q_DISABLE_COPY(QCPAbstractPlottable) + double mSize; + ScatterShape mShape; + QPen mPen; + QBrush mBrush; + QPixmap mPixmap; + QPainterPath mCustomPath; - friend class QCustomPlot; - friend class QCPAxis; - friend class QCPPlottableLegendItem; + // non-property members: + bool mPenDefined; }; +Q_DECLARE_TYPEINFO(QCPScatterStyle, Q_MOVABLE_TYPE); +Q_DECLARE_OPERATORS_FOR_FLAGS(QCPScatterStyle::ScatterProperties) +Q_DECLARE_METATYPE(QCPScatterStyle::ScatterProperty) +Q_DECLARE_METATYPE(QCPScatterStyle::ScatterShape) +/* end of 'src/scatterstyle.h' */ -class QCP_LIB_DECL QCPItemAnchor + +/* including file 'src/datacontainer.h' */ +/* modified 2022-11-06T12:45:56, size 34305 */ + +/*! \relates QCPDataContainer + Returns whether the sort key of \a a is less than the sort key of \a b. + + \see QCPDataContainer::sort +*/ +template +inline bool qcpLessThanSortKey(const DataType &a, const DataType &b) { return a.sortKey() < b.sortKey(); } + +template +class QCPDataContainer // no QCP_LIB_DECL, template class ends up in header (cpp included below) { public: - QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name, int anchorId=-1); - virtual ~QCPItemAnchor(); + typedef typename QVector::const_iterator const_iterator; + typedef typename QVector::iterator iterator; + + QCPDataContainer(); // getters: - QString name() const { return mName; } - virtual QPointF pixelPoint() const; + int size() const { return mData.size()-mPreallocSize; } + bool isEmpty() const { return size() == 0; } + bool autoSqueeze() const { return mAutoSqueeze; } + + // setters: + void setAutoSqueeze(bool enabled); + + // non-virtual methods: + void set(const QCPDataContainer &data); + void set(const QVector &data, bool alreadySorted=false); + void add(const QCPDataContainer &data); + void add(const QVector &data, bool alreadySorted=false); + void add(const DataType &data); + void removeBefore(double sortKey); + void removeAfter(double sortKey); + void remove(double sortKeyFrom, double sortKeyTo); + void remove(double sortKey); + void clear(); + void sort(); + void squeeze(bool preAllocation=true, bool postAllocation=true); + + const_iterator constBegin() const { return mData.constBegin()+mPreallocSize; } + const_iterator constEnd() const { return mData.constEnd(); } + iterator begin() { return mData.begin()+mPreallocSize; } + iterator end() { return mData.end(); } + const_iterator findBegin(double sortKey, bool expandedRange=true) const; + const_iterator findEnd(double sortKey, bool expandedRange=true) const; + const_iterator at(int index) const { return constBegin()+qBound(0, index, size()); } + QCPRange keyRange(bool &foundRange, QCP::SignDomain signDomain=QCP::sdBoth); + QCPRange valueRange(bool &foundRange, QCP::SignDomain signDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()); + QCPDataRange dataRange() const { return QCPDataRange(0, size()); } + void limitIteratorsToDataRange(const_iterator &begin, const_iterator &end, const QCPDataRange &dataRange) const; protected: // property members: - QString mName; - - // non-property members: - QCustomPlot *mParentPlot; - QCPAbstractItem *mParentItem; - int mAnchorId; - QSet mChildrenX, mChildrenY; + bool mAutoSqueeze; - // introduced virtual methods: - virtual QCPItemPosition *toQCPItemPosition() { return 0; } + // non-property memebers: + QVector mData; + int mPreallocSize; + int mPreallocIteration; // non-virtual methods: - void addChildX(QCPItemPosition* pos); // called from pos when this anchor is set as parent - void removeChildX(QCPItemPosition *pos); // called from pos when its parent anchor is reset or pos deleted - void addChildY(QCPItemPosition* pos); // called from pos when this anchor is set as parent - void removeChildY(QCPItemPosition *pos); // called from pos when its parent anchor is reset or pos deleted - -private: - Q_DISABLE_COPY(QCPItemAnchor) - - friend class QCPItemPosition; + void preallocateGrow(int minimumPreallocSize); + void performAutoSqueeze(); }; -class QCP_LIB_DECL QCPItemPosition : public QCPItemAnchor -{ -public: - /*! - Defines the ways an item position can be specified. Thus it defines what the numbers passed to - \ref setCoords actually mean. - - \see setType - */ - enum PositionType { ptAbsolute ///< Static positioning in pixels, starting from the top left corner of the viewport/widget. - ,ptViewportRatio ///< Static positioning given by a fraction of the viewport size. For example, if you call setCoords(0, 0), the position will be at the top - ///< left corner of the viewport/widget. setCoords(1, 1) will be at the bottom right corner, setCoords(0.5, 0) will be horizontally centered and - ///< vertically at the top of the viewport/widget, etc. - ,ptAxisRectRatio ///< Static positioning given by a fraction of the axis rect size (see \ref setAxisRect). For example, if you call setCoords(0, 0), the position will be at the top - ///< left corner of the axis rect. setCoords(1, 1) will be at the bottom right corner, setCoords(0.5, 0) will be horizontally centered and - ///< vertically at the top of the axis rect, etc. You can also go beyond the axis rect by providing negative coordinates or coordinates larger than 1. - ,ptPlotCoords ///< Dynamic positioning at a plot coordinate defined by two axes (see \ref setAxes). - }; +// include implementation in header since it is a class template: +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPDataContainer +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPDataContainer + \brief The generic data container for one-dimensional plottables + + This class template provides a fast container for data storage of one-dimensional data. The data + type is specified as template parameter (called \a DataType in the following) and must provide + some methods as described in the \ref qcpdatacontainer-datatype "next section". + + The data is stored in a sorted fashion, which allows very quick lookups by the sorted key as well + as retrieval of ranges (see \ref findBegin, \ref findEnd, \ref keyRange) using binary search. The + container uses a preallocation and a postallocation scheme, such that appending and prepending + data (with respect to the sort key) is very fast and minimizes reallocations. If data is added + which needs to be inserted between existing keys, the merge usually can be done quickly too, + using the fact that existing data is always sorted. The user can further improve performance by + specifying that added data is already itself sorted by key, if he can guarantee that this is the + case (see for example \ref add(const QVector &data, bool alreadySorted)). + + The data can be accessed with the provided const iterators (\ref constBegin, \ref constEnd). If + it is necessary to alter existing data in-place, the non-const iterators can be used (\ref begin, + \ref end). Changing data members that are not the sort key (for most data types called \a key) is + safe from the container's perspective. + + Great care must be taken however if the sort key is modified through the non-const iterators. For + performance reasons, the iterators don't automatically cause a re-sorting upon their + manipulation. It is thus the responsibility of the user to leave the container in a sorted state + when finished with the data manipulation, before calling any other methods on the container. A + complete re-sort (e.g. after finishing all sort key manipulation) can be done by calling \ref + sort. Failing to do so can not be detected by the container efficiently and will cause both + rendering artifacts and potential data loss. + + Implementing one-dimensional plottables that make use of a \ref QCPDataContainer is usually + done by subclassing from \ref QCPAbstractPlottable1D "QCPAbstractPlottable1D", which + introduces an according \a mDataContainer member and some convenience methods. + + \section qcpdatacontainer-datatype Requirements for the DataType template parameter + + The template parameter DataType is the type of the stored data points. It must be + trivially copyable and have the following public methods, preferably inline: + + \li double sortKey() const\n Returns the member variable of this data point that is the + sort key, defining the ordering in the container. Often this variable is simply called \a key. + + \li static DataType fromSortKey(double sortKey)\n Returns a new instance of the data + type initialized with its sort key set to \a sortKey. + + \li static bool sortKeyIsMainKey()\n Returns true if the sort key is equal to the main + key (see method \c mainKey below). For most plottables this is the case. It is not the case for + example for \ref QCPCurve, which uses \a t as sort key and \a key as main key. This is the reason + why QCPCurve unlike QCPGraph can display parametric curves with loops. + + \li double mainKey() const\n Returns the variable of this data point considered the main + key. This is commonly the variable that is used as the coordinate of this data point on the key + axis of the plottable. This method is used for example when determining the automatic axis + rescaling of key axes (\ref QCPAxis::rescale). + + \li double mainValue() const\n Returns the variable of this data point considered the + main value. This is commonly the variable that is used as the coordinate of this data point on + the value axis of the plottable. + + \li QCPRange valueRange() const\n Returns the range this data point spans in the value + axis coordinate. If the data is single-valued (e.g. QCPGraphData), this is simply a range with + both lower and upper set to the main data point value. However if the data points can represent + multiple values at once (e.g QCPFinancialData with its \a high, \a low, \a open and \a close + values at each \a key) this method should return the range those values span. This method is used + for example when determining the automatic axis rescaling of value axes (\ref + QCPAxis::rescale). +*/ + +/* start documentation of inline functions */ + +/*! \fn int QCPDataContainer::size() const - QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name); - virtual ~QCPItemPosition(); + Returns the number of data points in the container. +*/ + +/*! \fn bool QCPDataContainer::isEmpty() const - // getters: - PositionType type() const { return typeX(); } - PositionType typeX() const { return mPositionTypeX; } - PositionType typeY() const { return mPositionTypeY; } - QCPItemAnchor *parentAnchor() const { return parentAnchorX(); } - QCPItemAnchor *parentAnchorX() const { return mParentAnchorX; } - QCPItemAnchor *parentAnchorY() const { return mParentAnchorY; } - double key() const { return mKey; } - double value() const { return mValue; } - QPointF coords() const { return QPointF(mKey, mValue); } - QCPAxis *keyAxis() const { return mKeyAxis.data(); } - QCPAxis *valueAxis() const { return mValueAxis.data(); } - QCPAxisRect *axisRect() const; - virtual QPointF pixelPoint() const; + Returns whether this container holds no data points. +*/ + +/*! \fn QCPDataContainer::const_iterator QCPDataContainer::constBegin() const - // setters: - void setType(PositionType type); - void setTypeX(PositionType type); - void setTypeY(PositionType type); - bool setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false); - bool setParentAnchorX(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false); - bool setParentAnchorY(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false); - void setCoords(double key, double value); - void setCoords(const QPointF &coords); - void setAxes(QCPAxis* keyAxis, QCPAxis* valueAxis); - void setAxisRect(QCPAxisRect *axisRect); - void setPixelPoint(const QPointF &pixelPoint); + Returns a const iterator to the first data point in this container. +*/ + +/*! \fn QCPDataContainer::const_iterator QCPDataContainer::constEnd() const -protected: - // property members: - PositionType mPositionTypeX, mPositionTypeY; - QPointer mKeyAxis, mValueAxis; - QPointer mAxisRect; - double mKey, mValue; - QCPItemAnchor *mParentAnchorX, *mParentAnchorY; + Returns a const iterator to the element past the last data point in this container. +*/ + +/*! \fn QCPDataContainer::iterator QCPDataContainer::begin() const - // reimplemented virtual methods: - virtual QCPItemPosition *toQCPItemPosition() { return this; } + Returns a non-const iterator to the first data point in this container. + + You can manipulate the data points in-place through the non-const iterators, but great care must + be taken when manipulating the sort key of a data point, see \ref sort, or the detailed + description of this class. +*/ + +/*! \fn QCPDataContainer::iterator QCPDataContainer::end() const -private: - Q_DISABLE_COPY(QCPItemPosition) + Returns a non-const iterator to the element past the last data point in this container. -}; + You can manipulate the data points in-place through the non-const iterators, but great care must + be taken when manipulating the sort key of a data point, see \ref sort, or the detailed + description of this class. +*/ +/*! \fn QCPDataContainer::const_iterator QCPDataContainer::at(int index) const -class QCP_LIB_DECL QCPAbstractItem : public QCPLayerable + Returns a const iterator to the element with the specified \a index. If \a index points beyond + the available elements in this container, returns \ref constEnd, i.e. an iterator past the last + valid element. + + You can use this method to easily obtain iterators from a \ref QCPDataRange, see the \ref + dataselection-accessing "data selection page" for an example. +*/ + +/*! \fn QCPDataRange QCPDataContainer::dataRange() const + + Returns a \ref QCPDataRange encompassing the entire data set of this container. This means the + begin index of the returned range is 0, and the end index is \ref size. +*/ + +/* end documentation of inline functions */ + +/*! + Constructs a QCPDataContainer used for plottable classes that represent a series of key-sorted + data +*/ +template +QCPDataContainer::QCPDataContainer() : + mAutoSqueeze(true), + mPreallocSize(0), + mPreallocIteration(0) { - Q_OBJECT - /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(bool clipToAxisRect READ clipToAxisRect WRITE setClipToAxisRect) - Q_PROPERTY(QCPAxisRect* clipAxisRect READ clipAxisRect WRITE setClipAxisRect) - Q_PROPERTY(bool selectable READ selectable WRITE setSelectable NOTIFY selectableChanged) - Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectionChanged) - /// \endcond -public: - QCPAbstractItem(QCustomPlot *parentPlot); - virtual ~QCPAbstractItem(); +} + +/*! + Sets whether the container automatically decides when to release memory from its post- and + preallocation pools when data points are removed. By default this is enabled and for typical + applications shouldn't be changed. - // getters: - bool clipToAxisRect() const { return mClipToAxisRect; } - QCPAxisRect *clipAxisRect() const; - bool selectable() const { return mSelectable; } - bool selected() const { return mSelected; } + If auto squeeze is disabled, you can manually decide when to release pre-/postallocation with + \ref squeeze. +*/ +template +void QCPDataContainer::setAutoSqueeze(bool enabled) +{ + if (mAutoSqueeze != enabled) + { + mAutoSqueeze = enabled; + if (mAutoSqueeze) + performAutoSqueeze(); + } +} + +/*! \overload - // setters: - void setClipToAxisRect(bool clip); - void setClipAxisRect(QCPAxisRect *rect); - Q_SLOT void setSelectable(bool selectable); - Q_SLOT void setSelected(bool selected); + Replaces the current data in this container with the provided \a data. - // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const = 0; + \see add, remove +*/ +template +void QCPDataContainer::set(const QCPDataContainer &data) +{ + clear(); + add(data); +} + +/*! \overload - // non-virtual methods: - QList positions() const { return mPositions; } - QList anchors() const { return mAnchors; } - QCPItemPosition *position(const QString &name) const; - QCPItemAnchor *anchor(const QString &name) const; - bool hasAnchor(const QString &name) const; + Replaces the current data in this container with the provided \a data + + If you can guarantee that the data points in \a data have ascending order with respect to the + DataType's sort key, set \a alreadySorted to true to avoid an unnecessary sorting run. -signals: - void selectionChanged(bool selected); - void selectableChanged(bool selectable); + \see add, remove +*/ +template +void QCPDataContainer::set(const QVector &data, bool alreadySorted) +{ + mData = data; + mPreallocSize = 0; + mPreallocIteration = 0; + if (!alreadySorted) + sort(); +} + +/*! \overload -protected: - // property members: - bool mClipToAxisRect; - QPointer mClipAxisRect; - QList mPositions; - QList mAnchors; - bool mSelectable, mSelected; + Adds the provided \a data to the current data in this container. - // reimplemented virtual methods: - virtual QCP::Interaction selectionCategory() const; - virtual QRect clipRect() const; - virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; - virtual void draw(QCPPainter *painter) = 0; - // events: - virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); - virtual void deselectEvent(bool *selectionStateChanged); + \see set, remove +*/ +template +void QCPDataContainer::add(const QCPDataContainer &data) +{ + if (data.isEmpty()) + return; - // introduced virtual methods: - virtual QPointF anchorPixelPoint(int anchorId) const; + const int n = data.size(); + const int oldSize = size(); - // non-virtual methods: - double distSqrToLine(const QPointF &start, const QPointF &end, const QPointF &point) const; - double rectSelectTest(const QRectF &rect, const QPointF &pos, bool filledRect) const; - QCPItemPosition *createPosition(const QString &name); - QCPItemAnchor *createAnchor(const QString &name, int anchorId); + if (oldSize > 0 && !qcpLessThanSortKey(*constBegin(), *(data.constEnd()-1))) // prepend if new data keys are all smaller than or equal to existing ones + { + if (mPreallocSize < n) + preallocateGrow(n); + mPreallocSize -= n; + std::copy(data.constBegin(), data.constEnd(), begin()); + } else // don't need to prepend, so append and merge if necessary + { + mData.resize(mData.size()+n); + std::copy(data.constBegin(), data.constEnd(), end()-n); + if (oldSize > 0 && !qcpLessThanSortKey(*(constEnd()-n-1), *(constEnd()-n))) // if appended range keys aren't all greater than existing ones, merge the two partitions + std::inplace_merge(begin(), end()-n, end(), qcpLessThanSortKey); + } +} + +/*! + Adds the provided data points in \a data to the current data. -private: - Q_DISABLE_COPY(QCPAbstractItem) + If you can guarantee that the data points in \a data have ascending order with respect to the + DataType's sort key, set \a alreadySorted to true to avoid an unnecessary sorting run. - friend class QCustomPlot; - friend class QCPItemAnchor; -}; + \see set, remove +*/ +template +void QCPDataContainer::add(const QVector &data, bool alreadySorted) +{ + if (data.isEmpty()) + return; + if (isEmpty()) + { + set(data, alreadySorted); + return; + } + + const int n = data.size(); + const int oldSize = size(); + + if (alreadySorted && oldSize > 0 && !qcpLessThanSortKey(*constBegin(), *(data.constEnd()-1))) // prepend if new data is sorted and keys are all smaller than or equal to existing ones + { + if (mPreallocSize < n) + preallocateGrow(n); + mPreallocSize -= n; + std::copy(data.constBegin(), data.constEnd(), begin()); + } else // don't need to prepend, so append and then sort and merge if necessary + { + mData.resize(mData.size()+n); + std::copy(data.constBegin(), data.constEnd(), end()-n); + if (!alreadySorted) // sort appended subrange if it wasn't already sorted + std::sort(end()-n, end(), qcpLessThanSortKey); + if (oldSize > 0 && !qcpLessThanSortKey(*(constEnd()-n-1), *(constEnd()-n))) // if appended range keys aren't all greater than existing ones, merge the two partitions + std::inplace_merge(begin(), end()-n, end(), qcpLessThanSortKey); + } +} +/*! \overload + + Adds the provided single data point to the current data. + + \see remove +*/ +template +void QCPDataContainer::add(const DataType &data) +{ + if (isEmpty() || !qcpLessThanSortKey(data, *(constEnd()-1))) // quickly handle appends if new data key is greater or equal to existing ones + { + mData.append(data); + } else if (qcpLessThanSortKey(data, *constBegin())) // quickly handle prepends using preallocated space + { + if (mPreallocSize < 1) + preallocateGrow(1); + --mPreallocSize; + *begin() = data; + } else // handle inserts, maintaining sorted keys + { + QCPDataContainer::iterator insertionPoint = std::lower_bound(begin(), end(), data, qcpLessThanSortKey); + mData.insert(insertionPoint, data); + } +} -class QCP_LIB_DECL QCustomPlot : public QWidget +/*! + Removes all data points with (sort-)keys smaller than or equal to \a sortKey. + + \see removeAfter, remove, clear +*/ +template +void QCPDataContainer::removeBefore(double sortKey) { - Q_OBJECT - /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QRect viewport READ viewport WRITE setViewport) - Q_PROPERTY(QPixmap background READ background WRITE setBackground) - Q_PROPERTY(bool backgroundScaled READ backgroundScaled WRITE setBackgroundScaled) - Q_PROPERTY(Qt::AspectRatioMode backgroundScaledMode READ backgroundScaledMode WRITE setBackgroundScaledMode) - Q_PROPERTY(QCPLayoutGrid* plotLayout READ plotLayout) - Q_PROPERTY(bool autoAddPlottableToLegend READ autoAddPlottableToLegend WRITE setAutoAddPlottableToLegend) - Q_PROPERTY(int selectionTolerance READ selectionTolerance WRITE setSelectionTolerance) - Q_PROPERTY(bool noAntialiasingOnDrag READ noAntialiasingOnDrag WRITE setNoAntialiasingOnDrag) - Q_PROPERTY(Qt::KeyboardModifier multiSelectModifier READ multiSelectModifier WRITE setMultiSelectModifier) - /// \endcond -public: - /*! - Defines how a layer should be inserted relative to an other layer. + QCPDataContainer::iterator it = begin(); + QCPDataContainer::iterator itEnd = std::lower_bound(begin(), end(), DataType::fromSortKey(sortKey), qcpLessThanSortKey); + mPreallocSize += int(itEnd-it); // don't actually delete, just add it to the preallocated block (if it gets too large, squeeze will take care of it) + if (mAutoSqueeze) + performAutoSqueeze(); +} - \see addLayer, moveLayer - */ - enum LayerInsertMode { limBelow ///< Layer is inserted below other layer - ,limAbove ///< Layer is inserted above other layer - }; - Q_ENUMS(LayerInsertMode) +/*! + Removes all data points with (sort-)keys greater than or equal to \a sortKey. + + \see removeBefore, remove, clear +*/ +template +void QCPDataContainer::removeAfter(double sortKey) +{ + QCPDataContainer::iterator it = std::upper_bound(begin(), end(), DataType::fromSortKey(sortKey), qcpLessThanSortKey); + QCPDataContainer::iterator itEnd = end(); + mData.erase(it, itEnd); // typically adds it to the postallocated block + if (mAutoSqueeze) + performAutoSqueeze(); +} + +/*! + Removes all data points with (sort-)keys between \a sortKeyFrom and \a sortKeyTo. if \a + sortKeyFrom is greater or equal to \a sortKeyTo, the function does nothing. To remove a single + data point with known (sort-)key, use \ref remove(double sortKey). - /*! - Defines with what timing the QCustomPlot surface is refreshed after a replot. + \see removeBefore, removeAfter, clear +*/ +template +void QCPDataContainer::remove(double sortKeyFrom, double sortKeyTo) +{ + if (sortKeyFrom >= sortKeyTo || isEmpty()) + return; + + QCPDataContainer::iterator it = std::lower_bound(begin(), end(), DataType::fromSortKey(sortKeyFrom), qcpLessThanSortKey); + QCPDataContainer::iterator itEnd = std::upper_bound(it, end(), DataType::fromSortKey(sortKeyTo), qcpLessThanSortKey); + mData.erase(it, itEnd); + if (mAutoSqueeze) + performAutoSqueeze(); +} - \see replot - */ - enum RefreshPriority { rpImmediate ///< The QCustomPlot surface is immediately refreshed, by calling QWidget::repaint() after the replot - ,rpQueued ///< Queues the refresh such that it is performed at a slightly delayed point in time after the replot, by calling QWidget::update() after the replot - ,rpHint ///< Whether to use immediate repaint or queued update depends on whether the plotting hint \ref QCP::phForceRepaint is set, see \ref setPlottingHints. - }; +/*! \overload - explicit QCustomPlot(QWidget *parent = 0); - virtual ~QCustomPlot(); + Removes a single data point at \a sortKey. If the position is not known with absolute (binary) + precision, consider using \ref remove(double sortKeyFrom, double sortKeyTo) with a small + fuzziness interval around the suspected position, depeding on the precision with which the + (sort-)key is known. - // getters: - QRect viewport() const { return mViewport; } - QPixmap background() const { return mBackgroundPixmap; } - bool backgroundScaled() const { return mBackgroundScaled; } - Qt::AspectRatioMode backgroundScaledMode() const { return mBackgroundScaledMode; } - QCPLayoutGrid *plotLayout() const { return mPlotLayout; } - QCP::AntialiasedElements antialiasedElements() const { return mAntialiasedElements; } - QCP::AntialiasedElements notAntialiasedElements() const { return mNotAntialiasedElements; } - bool autoAddPlottableToLegend() const { return mAutoAddPlottableToLegend; } - const QCP::Interactions interactions() const { return mInteractions; } - int selectionTolerance() const { return mSelectionTolerance; } - bool noAntialiasingOnDrag() const { return mNoAntialiasingOnDrag; } - QCP::PlottingHints plottingHints() const { return mPlottingHints; } - Qt::KeyboardModifier multiSelectModifier() const { return mMultiSelectModifier; } + \see removeBefore, removeAfter, clear +*/ +template +void QCPDataContainer::remove(double sortKey) +{ + QCPDataContainer::iterator it = std::lower_bound(begin(), end(), DataType::fromSortKey(sortKey), qcpLessThanSortKey); + if (it != end() && it->sortKey() == sortKey) + { + if (it == begin()) + ++mPreallocSize; // don't actually delete, just add it to the preallocated block (if it gets too large, squeeze will take care of it) + else + mData.erase(it); + } + if (mAutoSqueeze) + performAutoSqueeze(); +} - // setters: - void setViewport(const QRect &rect); - void setBackground(const QPixmap &pm); - void setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode=Qt::KeepAspectRatioByExpanding); - void setBackground(const QBrush &brush); - void setBackgroundScaled(bool scaled); - void setBackgroundScaledMode(Qt::AspectRatioMode mode); - void setAntialiasedElements(const QCP::AntialiasedElements &antialiasedElements); - void setAntialiasedElement(QCP::AntialiasedElement antialiasedElement, bool enabled=true); - void setNotAntialiasedElements(const QCP::AntialiasedElements ¬AntialiasedElements); - void setNotAntialiasedElement(QCP::AntialiasedElement notAntialiasedElement, bool enabled=true); - void setAutoAddPlottableToLegend(bool on); - void setInteractions(const QCP::Interactions &interactions); - void setInteraction(const QCP::Interaction &interaction, bool enabled=true); - void setSelectionTolerance(int pixels); - void setNoAntialiasingOnDrag(bool enabled); - void setPlottingHints(const QCP::PlottingHints &hints); - void setPlottingHint(QCP::PlottingHint hint, bool enabled=true); - void setMultiSelectModifier(Qt::KeyboardModifier modifier); +/*! + Removes all data points. - // non-property methods: - // plottable interface: - QCPAbstractPlottable *plottable(int index); - QCPAbstractPlottable *plottable(); - bool addPlottable(QCPAbstractPlottable *plottable); - bool removePlottable(QCPAbstractPlottable *plottable); - bool removePlottable(int index); - int clearPlottables(); - int plottableCount() const; - QList selectedPlottables() const; - QCPAbstractPlottable *plottableAt(const QPointF &pos, bool onlySelectable=false) const; - bool hasPlottable(QCPAbstractPlottable *plottable) const; - - // specialized interface for QCPGraph: - QCPGraph *graph(int index) const; - QCPGraph *graph() const; - QCPGraph *addGraph(QCPAxis *keyAxis=0, QCPAxis *valueAxis=0); - bool removeGraph(QCPGraph *graph); - bool removeGraph(int index); - int clearGraphs(); - int graphCount() const; - QList selectedGraphs() const; + \see remove, removeAfter, removeBefore +*/ +template +void QCPDataContainer::clear() +{ + mData.clear(); + mPreallocIteration = 0; + mPreallocSize = 0; +} - // item interface: - QCPAbstractItem *item(int index) const; - QCPAbstractItem *item() const; - bool addItem(QCPAbstractItem* item); - bool removeItem(QCPAbstractItem *item); - bool removeItem(int index); - int clearItems(); - int itemCount() const; - QList selectedItems() const; - QCPAbstractItem *itemAt(const QPointF &pos, bool onlySelectable=false) const; - bool hasItem(QCPAbstractItem *item) const; +/*! + Re-sorts all data points in the container by their sort key. + + When setting, adding or removing points using the QCPDataContainer interface (\ref set, \ref add, + \ref remove, etc.), the container makes sure to always stay in a sorted state such that a full + resort is never necessary. However, if you choose to directly manipulate the sort key on data + points by accessing and modifying it through the non-const iterators (\ref begin, \ref end), it + is your responsibility to bring the container back into a sorted state before any other methods + are called on it. This can be achieved by calling this method immediately after finishing the + sort key manipulation. +*/ +template +void QCPDataContainer::sort() +{ + std::sort(begin(), end(), qcpLessThanSortKey); +} + +/*! + Frees all unused memory that is currently in the preallocation and postallocation pools. - // layer interface: - QCPLayer *layer(const QString &name) const; - QCPLayer *layer(int index) const; - QCPLayer *currentLayer() const; - bool setCurrentLayer(const QString &name); - bool setCurrentLayer(QCPLayer *layer); - int layerCount() const; - bool addLayer(const QString &name, QCPLayer *otherLayer=0, LayerInsertMode insertMode=limAbove); - bool removeLayer(QCPLayer *layer); - bool moveLayer(QCPLayer *layer, QCPLayer *otherLayer, LayerInsertMode insertMode=limAbove); + Note that QCPDataContainer automatically decides whether squeezing is necessary, if \ref + setAutoSqueeze is left enabled. It should thus not be necessary to use this method for typical + applications. - // axis rect/layout interface: - int axisRectCount() const; - QCPAxisRect* axisRect(int index=0) const; - QList axisRects() const; - QCPLayoutElement* layoutElementAt(const QPointF &pos) const; - Q_SLOT void rescaleAxes(bool onlyVisiblePlottables=false); + The parameters \a preAllocation and \a postAllocation control whether pre- and/or post allocation + should be freed, respectively. +*/ +template +void QCPDataContainer::squeeze(bool preAllocation, bool postAllocation) +{ + if (preAllocation) + { + if (mPreallocSize > 0) + { + std::copy(begin(), end(), mData.begin()); + mData.resize(size()); + mPreallocSize = 0; + } + mPreallocIteration = 0; + } + if (postAllocation) + mData.squeeze(); +} + +/*! + Returns an iterator to the data point with a (sort-)key that is equal to, just below, or just + above \a sortKey. If \a expandedRange is true, the data point just below \a sortKey will be + considered, otherwise the one just above. + + This can be used in conjunction with \ref findEnd to iterate over data points within a given key + range, including or excluding the bounding data points that are just beyond the specified range. + + If \a expandedRange is true but there are no data points below \a sortKey, \ref constBegin is + returned. + + If the container is empty, returns \ref constEnd. + + \see findEnd, QCPPlottableInterface1D::findBegin +*/ +template +typename QCPDataContainer::const_iterator QCPDataContainer::findBegin(double sortKey, bool expandedRange) const +{ + if (isEmpty()) + return constEnd(); - QList selectedAxes() const; - QList selectedLegends() const; - Q_SLOT void deselectAll(); + QCPDataContainer::const_iterator it = std::lower_bound(constBegin(), constEnd(), DataType::fromSortKey(sortKey), qcpLessThanSortKey); + if (expandedRange && it != constBegin()) // also covers it == constEnd case, and we know --constEnd is valid because mData isn't empty + --it; + return it; +} + +/*! + Returns an iterator to the element after the data point with a (sort-)key that is equal to, just + above or just below \a sortKey. If \a expandedRange is true, the data point just above \a sortKey + will be considered, otherwise the one just below. + + This can be used in conjunction with \ref findBegin to iterate over data points within a given + key range, including the bounding data points that are just below and above the specified range. + + If \a expandedRange is true but there are no data points above \a sortKey, \ref constEnd is + returned. + + If the container is empty, \ref constEnd is returned. + + \see findBegin, QCPPlottableInterface1D::findEnd +*/ +template +typename QCPDataContainer::const_iterator QCPDataContainer::findEnd(double sortKey, bool expandedRange) const +{ + if (isEmpty()) + return constEnd(); - bool savePdf(const QString &fileName, bool noCosmeticPen=false, int width=0, int height=0, const QString &pdfCreator=QString(), const QString &pdfTitle=QString()); - bool savePng(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1); - bool saveJpg(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1); - bool saveBmp(const QString &fileName, int width=0, int height=0, double scale=1.0); - bool saveRastered(const QString &fileName, int width, int height, double scale, const char *format, int quality=-1); - QPixmap toPixmap(int width=0, int height=0, double scale=1.0); - void toPainter(QCPPainter *painter, int width=0, int height=0); - Q_SLOT void replot(QCustomPlot::RefreshPriority refreshPriority=QCustomPlot::rpHint); + QCPDataContainer::const_iterator it = std::upper_bound(constBegin(), constEnd(), DataType::fromSortKey(sortKey), qcpLessThanSortKey); + if (expandedRange && it != constEnd()) + ++it; + return it; +} + +/*! + Returns the range encompassed by the (main-)key coordinate of all data points. The output + parameter \a foundRange indicates whether a sensible range was found. If this is false, you + should not use the returned QCPRange (e.g. the data container is empty or all points have the + same key). - QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2; - QCPLegend *legend; + Use \a signDomain to control which sign of the key coordinates should be considered. This is + relevant e.g. for logarithmic plots which can mathematically only display one sign domain at a + time. -signals: - void mouseDoubleClick(QMouseEvent *event); - void mousePress(QMouseEvent *event); - void mouseMove(QMouseEvent *event); - void mouseRelease(QMouseEvent *event); - void mouseWheel(QWheelEvent *event); + If the DataType reports that its main key is equal to the sort key (\a sortKeyIsMainKey), as is + the case for most plottables, this method uses this fact and finds the range very quickly. - void plottableClick(QCPAbstractPlottable *plottable, QMouseEvent *event); - void plottableDoubleClick(QCPAbstractPlottable *plottable, QMouseEvent *event); - void itemClick(QCPAbstractItem *item, QMouseEvent *event); - void itemDoubleClick(QCPAbstractItem *item, QMouseEvent *event); - void axisClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event); - void axisDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event); - void legendClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event); - void legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event); - void titleClick(QMouseEvent *event, QCPPlotTitle *title); - void titleDoubleClick(QMouseEvent *event, QCPPlotTitle *title); + \see valueRange +*/ +template +QCPRange QCPDataContainer::keyRange(bool &foundRange, QCP::SignDomain signDomain) +{ + if (isEmpty()) + { + foundRange = false; + return QCPRange(); + } + QCPRange range; + bool haveLower = false; + bool haveUpper = false; + double current; + + QCPDataContainer::const_iterator it = constBegin(); + QCPDataContainer::const_iterator itEnd = constEnd(); + if (signDomain == QCP::sdBoth) // range may be anywhere + { + if (DataType::sortKeyIsMainKey()) // if DataType is sorted by main key (e.g. QCPGraph, but not QCPCurve), use faster algorithm by finding just first and last key with non-NaN value + { + while (it != itEnd) // find first non-nan going up from left + { + if (!qIsNaN(it->mainValue())) + { + range.lower = it->mainKey(); + haveLower = true; + break; + } + ++it; + } + it = itEnd; + while (it != constBegin()) // find first non-nan going down from right + { + --it; + if (!qIsNaN(it->mainValue())) + { + range.upper = it->mainKey(); + haveUpper = true; + break; + } + } + } else // DataType is not sorted by main key, go through all data points and accordingly expand range + { + while (it != itEnd) + { + if (!qIsNaN(it->mainValue())) + { + current = it->mainKey(); + if (current < range.lower || !haveLower) + { + range.lower = current; + haveLower = true; + } + if (current > range.upper || !haveUpper) + { + range.upper = current; + haveUpper = true; + } + } + ++it; + } + } + } else if (signDomain == QCP::sdNegative) // range may only be in the negative sign domain + { + while (it != itEnd) + { + if (!qIsNaN(it->mainValue())) + { + current = it->mainKey(); + if ((current < range.lower || !haveLower) && current < 0) + { + range.lower = current; + haveLower = true; + } + if ((current > range.upper || !haveUpper) && current < 0) + { + range.upper = current; + haveUpper = true; + } + } + ++it; + } + } else if (signDomain == QCP::sdPositive) // range may only be in the positive sign domain + { + while (it != itEnd) + { + if (!qIsNaN(it->mainValue())) + { + current = it->mainKey(); + if ((current < range.lower || !haveLower) && current > 0) + { + range.lower = current; + haveLower = true; + } + if ((current > range.upper || !haveUpper) && current > 0) + { + range.upper = current; + haveUpper = true; + } + } + ++it; + } + } - void selectionChangedByUser(); - void beforeReplot(); - void afterReplot(); + foundRange = haveLower && haveUpper; + return range; +} + +/*! + Returns the range encompassed by the value coordinates of the data points in the specified key + range (\a inKeyRange), using the full \a DataType::valueRange reported by the data points. The + output parameter \a foundRange indicates whether a sensible range was found. If this is false, + you should not use the returned QCPRange (e.g. the data container is empty or all points have the + same value). -protected: - // property members: - QRect mViewport; - QCPLayoutGrid *mPlotLayout; - bool mAutoAddPlottableToLegend; - QList mPlottables; - QList mGraphs; // extra list of plottables also in mPlottables that are of type QCPGraph - QList mItems; - QList mLayers; - QCP::AntialiasedElements mAntialiasedElements, mNotAntialiasedElements; - QCP::Interactions mInteractions; - int mSelectionTolerance; - bool mNoAntialiasingOnDrag; - QBrush mBackgroundBrush; - QPixmap mBackgroundPixmap; - QPixmap mScaledBackgroundPixmap; - bool mBackgroundScaled; - Qt::AspectRatioMode mBackgroundScaledMode; - QCPLayer *mCurrentLayer; - QCP::PlottingHints mPlottingHints; - Qt::KeyboardModifier mMultiSelectModifier; + Inf and -Inf data values are ignored. + + If \a inKeyRange has both lower and upper bound set to zero (is equal to QCPRange()), + all data points are considered, without any restriction on the keys. + + Use \a signDomain to control which sign of the value coordinates should be considered. This is + relevant e.g. for logarithmic plots which can mathematically only display one sign domain at a + time. + + \see keyRange +*/ +template +QCPRange QCPDataContainer::valueRange(bool &foundRange, QCP::SignDomain signDomain, const QCPRange &inKeyRange) +{ + if (isEmpty()) + { + foundRange = false; + return QCPRange(); + } + QCPRange range; + const bool restrictKeyRange = inKeyRange != QCPRange(); + bool haveLower = false; + bool haveUpper = false; + QCPRange current; + QCPDataContainer::const_iterator itBegin = constBegin(); + QCPDataContainer::const_iterator itEnd = constEnd(); + if (DataType::sortKeyIsMainKey() && restrictKeyRange) + { + itBegin = findBegin(inKeyRange.lower, false); + itEnd = findEnd(inKeyRange.upper, false); + } + if (signDomain == QCP::sdBoth) // range may be anywhere + { + for (QCPDataContainer::const_iterator it = itBegin; it != itEnd; ++it) + { + if (restrictKeyRange && (it->mainKey() < inKeyRange.lower || it->mainKey() > inKeyRange.upper)) + continue; + current = it->valueRange(); + if ((current.lower < range.lower || !haveLower) && !qIsNaN(current.lower) && std::isfinite(current.lower)) + { + range.lower = current.lower; + haveLower = true; + } + if ((current.upper > range.upper || !haveUpper) && !qIsNaN(current.upper) && std::isfinite(current.upper)) + { + range.upper = current.upper; + haveUpper = true; + } + } + } else if (signDomain == QCP::sdNegative) // range may only be in the negative sign domain + { + for (QCPDataContainer::const_iterator it = itBegin; it != itEnd; ++it) + { + if (restrictKeyRange && (it->mainKey() < inKeyRange.lower || it->mainKey() > inKeyRange.upper)) + continue; + current = it->valueRange(); + if ((current.lower < range.lower || !haveLower) && current.lower < 0 && !qIsNaN(current.lower) && std::isfinite(current.lower)) + { + range.lower = current.lower; + haveLower = true; + } + if ((current.upper > range.upper || !haveUpper) && current.upper < 0 && !qIsNaN(current.upper) && std::isfinite(current.upper)) + { + range.upper = current.upper; + haveUpper = true; + } + } + } else if (signDomain == QCP::sdPositive) // range may only be in the positive sign domain + { + for (QCPDataContainer::const_iterator it = itBegin; it != itEnd; ++it) + { + if (restrictKeyRange && (it->mainKey() < inKeyRange.lower || it->mainKey() > inKeyRange.upper)) + continue; + current = it->valueRange(); + if ((current.lower < range.lower || !haveLower) && current.lower > 0 && !qIsNaN(current.lower) && std::isfinite(current.lower)) + { + range.lower = current.lower; + haveLower = true; + } + if ((current.upper > range.upper || !haveUpper) && current.upper > 0 && !qIsNaN(current.upper) && std::isfinite(current.upper)) + { + range.upper = current.upper; + haveUpper = true; + } + } + } - // non-property members: - QPixmap mPaintBuffer; - QPoint mMousePressPos; - QPointer mMouseEventElement; - bool mReplotting; + foundRange = haveLower && haveUpper; + return range; +} + +/*! + Makes sure \a begin and \a end mark a data range that is both within the bounds of this data + container's data, as well as within the specified \a dataRange. The initial range described by + the passed iterators \a begin and \a end is never expanded, only contracted if necessary. - // reimplemented virtual methods: - virtual QSize minimumSizeHint() const; - virtual QSize sizeHint() const; - virtual void paintEvent(QPaintEvent *event); - virtual void resizeEvent(QResizeEvent *event); - virtual void mouseDoubleClickEvent(QMouseEvent *event); - virtual void mousePressEvent(QMouseEvent *event); - virtual void mouseMoveEvent(QMouseEvent *event); - virtual void mouseReleaseEvent(QMouseEvent *event); - virtual void wheelEvent(QWheelEvent *event); + This function doesn't require for \a dataRange to be within the bounds of this data container's + valid range. +*/ +template +void QCPDataContainer::limitIteratorsToDataRange(const_iterator &begin, const_iterator &end, const QCPDataRange &dataRange) const +{ + QCPDataRange iteratorRange(int(begin-constBegin()), int(end-constBegin())); + iteratorRange = iteratorRange.bounded(dataRange.bounded(this->dataRange())); + begin = constBegin()+iteratorRange.begin(); + end = constBegin()+iteratorRange.end(); +} + +/*! \internal - // introduced virtual methods: - virtual void draw(QCPPainter *painter); - virtual void axisRemoved(QCPAxis *axis); - virtual void legendRemoved(QCPLegend *legend); + Increases the preallocation pool to have a size of at least \a minimumPreallocSize. Depending on + the preallocation history, the container will grow by more than requested, to speed up future + consecutive size increases. - // non-virtual methods: - void updateLayerIndices() const; - QCPLayerable *layerableAt(const QPointF &pos, bool onlySelectable, QVariant *selectionDetails=0) const; - void drawBackground(QCPPainter *painter); + if \a minimumPreallocSize is smaller than or equal to the current preallocation pool size, this + method does nothing. +*/ +template +void QCPDataContainer::preallocateGrow(int minimumPreallocSize) +{ + if (minimumPreallocSize <= mPreallocSize) + return; - friend class QCPLegend; - friend class QCPAxis; - friend class QCPLayer; - friend class QCPAxisRect; -}; + int newPreallocSize = minimumPreallocSize; + newPreallocSize += (1u< +void QCPDataContainer::performAutoSqueeze() +{ + const int totalAlloc = mData.capacity(); + const int postAllocSize = totalAlloc-mData.size(); + const int usedSize = size(); + bool shrinkPostAllocation = false; + bool shrinkPreAllocation = false; + if (totalAlloc > 650000) // if allocation is larger, shrink earlier with respect to total used size + { + shrinkPostAllocation = postAllocSize > usedSize*1.5; // QVector grow strategy is 2^n for static data. Watch out not to oscillate! + shrinkPreAllocation = mPreallocSize*10 > usedSize; + } else if (totalAlloc > 1000) // below 10 MiB raw data be generous with preallocated memory, below 1k points don't even bother + { + shrinkPostAllocation = postAllocSize > usedSize*5; + shrinkPreAllocation = mPreallocSize > usedSize*1.5; // preallocation can grow into postallocation, so can be smaller + } + + if (shrinkPreAllocation || shrinkPostAllocation) + squeeze(shrinkPreAllocation, shrinkPostAllocation); +} -class QCP_LIB_DECL QCPColorGradient +/* end of 'src/datacontainer.h' */ + + +/* including file 'src/plottable.h' */ +/* modified 2022-11-06T12:45:56, size 8461 */ + +class QCP_LIB_DECL QCPSelectionDecorator { Q_GADGET public: - /*! - Defines the color spaces in which color interpolation between gradient stops can be performed. - - \see setColorInterpolation - */ - enum ColorInterpolation { ciRGB ///< Color channels red, green and blue are linearly interpolated - ,ciHSV ///< Color channels hue, saturation and value are linearly interpolated (The hue is interpolated over the shortest angle distance) - }; - Q_ENUMS(ColorInterpolation) - - /*! - Defines the available presets that can be loaded with \ref loadPreset. See the documentation - there for an image of the presets. - */ - enum GradientPreset { gpGrayscale ///< Continuous lightness from black to white (suited for non-biased data representation) - ,gpHot ///< Continuous lightness from black over firey colors to white (suited for non-biased data representation) - ,gpCold ///< Continuous lightness from black over icey colors to white (suited for non-biased data representation) - ,gpNight ///< Continuous lightness from black over weak blueish colors to white (suited for non-biased data representation) - ,gpCandy ///< Blue over pink to white - ,gpGeography ///< Colors suitable to represent different elevations on geographical maps - ,gpIon ///< Half hue spectrum from black over purple to blue and finally green (creates banding illusion but allows more precise magnitude estimates) - ,gpThermal ///< Colors suitable for thermal imaging, ranging from dark blue over purple to orange, yellow and white - ,gpPolar ///< Colors suitable to emphasize polarity around the center, with blue for negative, black in the middle and red for positive values - ,gpSpectrum ///< An approximation of the visible light spectrum (creates banding illusion but allows more precise magnitude estimates) - ,gpJet ///< Hue variation similar to a spectrum, often used in numerical visualization (creates banding illusion but allows more precise magnitude estimates) - ,gpHues ///< Full hue cycle, with highest and lowest color red (suitable for periodic data, such as angles and phases, see \ref setPeriodic) - }; - Q_ENUMS(GradientPreset) - - QCPColorGradient(GradientPreset preset=gpCold); - bool operator==(const QCPColorGradient &other) const; - bool operator!=(const QCPColorGradient &other) const { return !(*this == other); } + QCPSelectionDecorator(); + virtual ~QCPSelectionDecorator(); // getters: - int levelCount() const { return mLevelCount; } - QMap colorStops() const { return mColorStops; } - ColorInterpolation colorInterpolation() const { return mColorInterpolation; } - bool periodic() const { return mPeriodic; } + QPen pen() const { return mPen; } + QBrush brush() const { return mBrush; } + QCPScatterStyle scatterStyle() const { return mScatterStyle; } + QCPScatterStyle::ScatterProperties usedScatterProperties() const { return mUsedScatterProperties; } // setters: - void setLevelCount(int n); - void setColorStops(const QMap &colorStops); - void setColorStopAt(double position, const QColor &color); - void setColorInterpolation(ColorInterpolation interpolation); - void setPeriodic(bool enabled); + void setPen(const QPen &pen); + void setBrush(const QBrush &brush); + void setScatterStyle(const QCPScatterStyle &scatterStyle, QCPScatterStyle::ScatterProperties usedProperties=QCPScatterStyle::spPen); + void setUsedScatterProperties(const QCPScatterStyle::ScatterProperties &properties); - // non-property methods: - void colorize(const double *data, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor=1, bool logarithmic=false); - QRgb color(double position, const QCPRange &range, bool logarithmic=false); - void loadPreset(GradientPreset preset); - void clearColorStops(); - QCPColorGradient inverted() const; + // non-virtual methods: + void applyPen(QCPPainter *painter) const; + void applyBrush(QCPPainter *painter) const; + QCPScatterStyle getFinalScatterStyle(const QCPScatterStyle &unselectedStyle) const; -protected: - void updateColorBuffer(); + // introduced virtual methods: + virtual void copyFrom(const QCPSelectionDecorator *other); + virtual void drawDecoration(QCPPainter *painter, QCPDataSelection selection); +protected: // property members: - int mLevelCount; - QMap mColorStops; - ColorInterpolation mColorInterpolation; - bool mPeriodic; - + QPen mPen; + QBrush mBrush; + QCPScatterStyle mScatterStyle; + QCPScatterStyle::ScatterProperties mUsedScatterProperties; // non-property members: - QVector mColorBuffer; - bool mColorBufferInvalidated; + QCPAbstractPlottable *mPlottable; + + // introduced virtual methods: + virtual bool registerWithPlottable(QCPAbstractPlottable *plottable); + +private: + Q_DISABLE_COPY(QCPSelectionDecorator) + friend class QCPAbstractPlottable; }; +Q_DECLARE_METATYPE(QCPSelectionDecorator*) -class QCP_LIB_DECL QCPAxisRect : public QCPLayoutElement +class QCP_LIB_DECL QCPAbstractPlottable : public QCPLayerable { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QPixmap background READ background WRITE setBackground) - Q_PROPERTY(bool backgroundScaled READ backgroundScaled WRITE setBackgroundScaled) - Q_PROPERTY(Qt::AspectRatioMode backgroundScaledMode READ backgroundScaledMode WRITE setBackgroundScaledMode) - Q_PROPERTY(Qt::Orientations rangeDrag READ rangeDrag WRITE setRangeDrag) - Q_PROPERTY(Qt::Orientations rangeZoom READ rangeZoom WRITE setRangeZoom) + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(bool antialiasedFill READ antialiasedFill WRITE setAntialiasedFill) + Q_PROPERTY(bool antialiasedScatters READ antialiasedScatters WRITE setAntialiasedScatters) + Q_PROPERTY(QPen pen READ pen WRITE setPen) + Q_PROPERTY(QBrush brush READ brush WRITE setBrush) + Q_PROPERTY(QCPAxis* keyAxis READ keyAxis WRITE setKeyAxis) + Q_PROPERTY(QCPAxis* valueAxis READ valueAxis WRITE setValueAxis) + Q_PROPERTY(QCP::SelectionType selectable READ selectable WRITE setSelectable NOTIFY selectableChanged) + Q_PROPERTY(QCPDataSelection selection READ selection WRITE setSelection NOTIFY selectionChanged) + Q_PROPERTY(QCPSelectionDecorator* selectionDecorator READ selectionDecorator WRITE setSelectionDecorator) /// \endcond public: - explicit QCPAxisRect(QCustomPlot *parentPlot, bool setupDefaultAxes=true); - virtual ~QCPAxisRect(); + QCPAbstractPlottable(QCPAxis *keyAxis, QCPAxis *valueAxis); + virtual ~QCPAbstractPlottable() Q_DECL_OVERRIDE; // getters: - QPixmap background() const { return mBackgroundPixmap; } - bool backgroundScaled() const { return mBackgroundScaled; } - Qt::AspectRatioMode backgroundScaledMode() const { return mBackgroundScaledMode; } - Qt::Orientations rangeDrag() const { return mRangeDrag; } - Qt::Orientations rangeZoom() const { return mRangeZoom; } - QCPAxis *rangeDragAxis(Qt::Orientation orientation); - QCPAxis *rangeZoomAxis(Qt::Orientation orientation); - double rangeZoomFactor(Qt::Orientation orientation); + QString name() const { return mName; } + bool antialiasedFill() const { return mAntialiasedFill; } + bool antialiasedScatters() const { return mAntialiasedScatters; } + QPen pen() const { return mPen; } + QBrush brush() const { return mBrush; } + QCPAxis *keyAxis() const { return mKeyAxis.data(); } + QCPAxis *valueAxis() const { return mValueAxis.data(); } + QCP::SelectionType selectable() const { return mSelectable; } + bool selected() const { return !mSelection.isEmpty(); } + QCPDataSelection selection() const { return mSelection; } + QCPSelectionDecorator *selectionDecorator() const { return mSelectionDecorator; } // setters: - void setBackground(const QPixmap &pm); - void setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode=Qt::KeepAspectRatioByExpanding); - void setBackground(const QBrush &brush); - void setBackgroundScaled(bool scaled); - void setBackgroundScaledMode(Qt::AspectRatioMode mode); - void setRangeDrag(Qt::Orientations orientations); - void setRangeZoom(Qt::Orientations orientations); - void setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical); - void setRangeZoomAxes(QCPAxis *horizontal, QCPAxis *vertical); - void setRangeZoomFactor(double horizontalFactor, double verticalFactor); - void setRangeZoomFactor(double factor); + void setName(const QString &name); + void setAntialiasedFill(bool enabled); + void setAntialiasedScatters(bool enabled); + void setPen(const QPen &pen); + void setBrush(const QBrush &brush); + void setKeyAxis(QCPAxis *axis); + void setValueAxis(QCPAxis *axis); + Q_SLOT void setSelectable(QCP::SelectionType selectable); + Q_SLOT void setSelection(QCPDataSelection selection); + void setSelectionDecorator(QCPSelectionDecorator *decorator); + + // introduced virtual methods: + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE = 0; // actually introduced in QCPLayerable as non-pure, but we want to force reimplementation for plottables + virtual QCPPlottableInterface1D *interface1D() { return nullptr; } + virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const = 0; + virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const = 0; // non-property methods: - int axisCount(QCPAxis::AxisType type) const; - QCPAxis *axis(QCPAxis::AxisType type, int index=0) const; - QList axes(QCPAxis::AxisTypes types) const; - QList axes() const; - QCPAxis *addAxis(QCPAxis::AxisType type, QCPAxis *axis=0); - QList addAxes(QCPAxis::AxisTypes types); - bool removeAxis(QCPAxis *axis); - QCPLayoutInset *insetLayout() const { return mInsetLayout; } + void coordsToPixels(double key, double value, double &x, double &y) const; + const QPointF coordsToPixels(double key, double value) const; + void pixelsToCoords(double x, double y, double &key, double &value) const; + void pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const; + void rescaleAxes(bool onlyEnlarge=false) const; + void rescaleKeyAxis(bool onlyEnlarge=false) const; + void rescaleValueAxis(bool onlyEnlarge=false, bool inKeyRange=false) const; + bool addToLegend(QCPLegend *legend); + bool addToLegend(); + bool removeFromLegend(QCPLegend *legend) const; + bool removeFromLegend() const; - void setupFullAxesBox(bool connectRanges=false); - QList plottables() const; - QList graphs() const; - QList items() const; +signals: + void selectionChanged(bool selected); + void selectionChanged(const QCPDataSelection &selection); + void selectableChanged(QCP::SelectionType selectable); - // read-only interface imitating a QRect: - int left() const { return mRect.left(); } - int right() const { return mRect.right(); } - int top() const { return mRect.top(); } - int bottom() const { return mRect.bottom(); } - int width() const { return mRect.width(); } - int height() const { return mRect.height(); } - QSize size() const { return mRect.size(); } - QPoint topLeft() const { return mRect.topLeft(); } - QPoint topRight() const { return mRect.topRight(); } - QPoint bottomLeft() const { return mRect.bottomLeft(); } - QPoint bottomRight() const { return mRect.bottomRight(); } - QPoint center() const { return mRect.center(); } +protected: + // property members: + QString mName; + bool mAntialiasedFill, mAntialiasedScatters; + QPen mPen; + QBrush mBrush; + QPointer mKeyAxis, mValueAxis; + QCP::SelectionType mSelectable; + QCPDataSelection mSelection; + QCPSelectionDecorator *mSelectionDecorator; // reimplemented virtual methods: - virtual void update(UpdatePhase phase); - virtual QList elements(bool recursive) const; + virtual QRect clipRect() const Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE = 0; + virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE; + void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE; + // events: + virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE; + virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE; + + // introduced virtual methods: + virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const = 0; + + // non-virtual methods: + void applyFillAntialiasingHint(QCPPainter *painter) const; + void applyScattersAntialiasingHint(QCPPainter *painter) const; + +private: + Q_DISABLE_COPY(QCPAbstractPlottable) + + friend class QCustomPlot; + friend class QCPAxis; + friend class QCPPlottableLegendItem; +}; + + +/* end of 'src/plottable.h' */ + +/* including file 'src/item.h' */ +/* modified 2022-11-06T12:45:56, size 9425 */ + +class QCP_LIB_DECL QCPItemAnchor +{ + Q_GADGET +public: + QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString &name, int anchorId=-1); + virtual ~QCPItemAnchor(); + + // getters: + QString name() const { return mName; } + virtual QPointF pixelPosition() const; + protected: // property members: - QBrush mBackgroundBrush; - QPixmap mBackgroundPixmap; - QPixmap mScaledBackgroundPixmap; - bool mBackgroundScaled; - Qt::AspectRatioMode mBackgroundScaledMode; - QCPLayoutInset *mInsetLayout; - Qt::Orientations mRangeDrag, mRangeZoom; - QPointer mRangeDragHorzAxis, mRangeDragVertAxis, mRangeZoomHorzAxis, mRangeZoomVertAxis; - double mRangeZoomFactorHorz, mRangeZoomFactorVert; + QString mName; + // non-property members: - QCPRange mDragStartHorzRange, mDragStartVertRange; - QCP::AntialiasedElements mAADragBackup, mNotAADragBackup; - QPoint mDragStart; - bool mDragging; - QHash > mAxes; + QCustomPlot *mParentPlot; + QCPAbstractItem *mParentItem; + int mAnchorId; + QSet mChildrenX, mChildrenY; - // reimplemented virtual methods: - virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; - virtual void draw(QCPPainter *painter); - virtual int calculateAutoMargin(QCP::MarginSide side); - // events: - virtual void mousePressEvent(QMouseEvent *event); - virtual void mouseMoveEvent(QMouseEvent *event); - virtual void mouseReleaseEvent(QMouseEvent *event); - virtual void wheelEvent(QWheelEvent *event); + // introduced virtual methods: + virtual QCPItemPosition *toQCPItemPosition() { return nullptr; } - // non-property methods: - void drawBackground(QCPPainter *painter); - void updateAxesOffset(QCPAxis::AxisType type); + // non-virtual methods: + void addChildX(QCPItemPosition* pos); // called from pos when this anchor is set as parent + void removeChildX(QCPItemPosition *pos); // called from pos when its parent anchor is reset or pos deleted + void addChildY(QCPItemPosition* pos); // called from pos when this anchor is set as parent + void removeChildY(QCPItemPosition *pos); // called from pos when its parent anchor is reset or pos deleted private: - Q_DISABLE_COPY(QCPAxisRect) + Q_DISABLE_COPY(QCPItemAnchor) - friend class QCustomPlot; + friend class QCPItemPosition; }; -class QCP_LIB_DECL QCPAbstractLegendItem : public QCPLayoutElement + +class QCP_LIB_DECL QCPItemPosition : public QCPItemAnchor +{ + Q_GADGET +public: + /*! + Defines the ways an item position can be specified. Thus it defines what the numbers passed to + \ref setCoords actually mean. + + \see setType + */ + enum PositionType { ptAbsolute ///< Static positioning in pixels, starting from the top left corner of the viewport/widget. + ,ptViewportRatio ///< Static positioning given by a fraction of the viewport size. For example, if you call setCoords(0, 0), the position will be at the top + ///< left corner of the viewport/widget. setCoords(1, 1) will be at the bottom right corner, setCoords(0.5, 0) will be horizontally centered and + ///< vertically at the top of the viewport/widget, etc. + ,ptAxisRectRatio ///< Static positioning given by a fraction of the axis rect size (see \ref setAxisRect). For example, if you call setCoords(0, 0), the position will be at the top + ///< left corner of the axis rect. setCoords(1, 1) will be at the bottom right corner, setCoords(0.5, 0) will be horizontally centered and + ///< vertically at the top of the axis rect, etc. You can also go beyond the axis rect by providing negative coordinates or coordinates larger than 1. + ,ptPlotCoords ///< Dynamic positioning at a plot coordinate defined by two axes (see \ref setAxes). + }; + Q_ENUMS(PositionType) + + QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString &name); + virtual ~QCPItemPosition() Q_DECL_OVERRIDE; + + // getters: + PositionType type() const { return typeX(); } + PositionType typeX() const { return mPositionTypeX; } + PositionType typeY() const { return mPositionTypeY; } + QCPItemAnchor *parentAnchor() const { return parentAnchorX(); } + QCPItemAnchor *parentAnchorX() const { return mParentAnchorX; } + QCPItemAnchor *parentAnchorY() const { return mParentAnchorY; } + double key() const { return mKey; } + double value() const { return mValue; } + QPointF coords() const { return QPointF(mKey, mValue); } + QCPAxis *keyAxis() const { return mKeyAxis.data(); } + QCPAxis *valueAxis() const { return mValueAxis.data(); } + QCPAxisRect *axisRect() const; + virtual QPointF pixelPosition() const Q_DECL_OVERRIDE; + + // setters: + void setType(PositionType type); + void setTypeX(PositionType type); + void setTypeY(PositionType type); + bool setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false); + bool setParentAnchorX(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false); + bool setParentAnchorY(QCPItemAnchor *parentAnchor, bool keepPixelPosition=false); + void setCoords(double key, double value); + void setCoords(const QPointF &pos); + void setAxes(QCPAxis* keyAxis, QCPAxis* valueAxis); + void setAxisRect(QCPAxisRect *axisRect); + void setPixelPosition(const QPointF &pixelPosition); + +protected: + // property members: + PositionType mPositionTypeX, mPositionTypeY; + QPointer mKeyAxis, mValueAxis; + QPointer mAxisRect; + double mKey, mValue; + QCPItemAnchor *mParentAnchorX, *mParentAnchorY; + + // reimplemented virtual methods: + virtual QCPItemPosition *toQCPItemPosition() Q_DECL_OVERRIDE { return this; } + +private: + Q_DISABLE_COPY(QCPItemPosition) + +}; +Q_DECLARE_METATYPE(QCPItemPosition::PositionType) + + +class QCP_LIB_DECL QCPAbstractItem : public QCPLayerable { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QCPLegend* parentLegend READ parentLegend) - Q_PROPERTY(QFont font READ font WRITE setFont) - Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor) - Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) - Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor) - Q_PROPERTY(bool selectable READ selectable WRITE setSelectable NOTIFY selectionChanged) - Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectableChanged) + Q_PROPERTY(bool clipToAxisRect READ clipToAxisRect WRITE setClipToAxisRect) + Q_PROPERTY(QCPAxisRect* clipAxisRect READ clipAxisRect WRITE setClipAxisRect) + Q_PROPERTY(bool selectable READ selectable WRITE setSelectable NOTIFY selectableChanged) + Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectionChanged) /// \endcond public: - explicit QCPAbstractLegendItem(QCPLegend *parent); + explicit QCPAbstractItem(QCustomPlot *parentPlot); + virtual ~QCPAbstractItem() Q_DECL_OVERRIDE; // getters: - QCPLegend *parentLegend() const { return mParentLegend; } - QFont font() const { return mFont; } - QColor textColor() const { return mTextColor; } - QFont selectedFont() const { return mSelectedFont; } - QColor selectedTextColor() const { return mSelectedTextColor; } + bool clipToAxisRect() const { return mClipToAxisRect; } + QCPAxisRect *clipAxisRect() const; bool selectable() const { return mSelectable; } bool selected() const { return mSelected; } // setters: - void setFont(const QFont &font); - void setTextColor(const QColor &color); - void setSelectedFont(const QFont &font); - void setSelectedTextColor(const QColor &color); + void setClipToAxisRect(bool clip); + void setClipAxisRect(QCPAxisRect *rect); Q_SLOT void setSelectable(bool selectable); Q_SLOT void setSelected(bool selected); // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE = 0; + + // non-virtual methods: + QList positions() const { return mPositions; } + QList anchors() const { return mAnchors; } + QCPItemPosition *position(const QString &name) const; + QCPItemAnchor *anchor(const QString &name) const; + bool hasAnchor(const QString &name) const; signals: void selectionChanged(bool selected); @@ -2119,1649 +3751,4024 @@ class QCP_LIB_DECL QCPAbstractLegendItem : public QCPLayoutElement protected: // property members: - QCPLegend *mParentLegend; - QFont mFont; - QColor mTextColor; - QFont mSelectedFont; - QColor mSelectedTextColor; + bool mClipToAxisRect; + QPointer mClipAxisRect; + QList mPositions; + QList mAnchors; bool mSelectable, mSelected; // reimplemented virtual methods: - virtual QCP::Interaction selectionCategory() const; - virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; - virtual QRect clipRect() const; - virtual void draw(QCPPainter *painter) = 0; + virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE; + virtual QRect clipRect() const Q_DECL_OVERRIDE; + virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE = 0; // events: - virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); - virtual void deselectEvent(bool *selectionStateChanged); + virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE; + virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE; + + // introduced virtual methods: + virtual QPointF anchorPixelPosition(int anchorId) const; + + // non-virtual methods: + double rectDistance(const QRectF &rect, const QPointF &pos, bool filledRect) const; + QCPItemPosition *createPosition(const QString &name); + QCPItemAnchor *createAnchor(const QString &name, int anchorId); private: - Q_DISABLE_COPY(QCPAbstractLegendItem) + Q_DISABLE_COPY(QCPAbstractItem) - friend class QCPLegend; + friend class QCustomPlot; + friend class QCPItemAnchor; }; +/* end of 'src/item.h' */ -class QCP_LIB_DECL QCPPlottableLegendItem : public QCPAbstractLegendItem -{ - Q_OBJECT -public: - QCPPlottableLegendItem(QCPLegend *parent, QCPAbstractPlottable *plottable); - - // getters: - QCPAbstractPlottable *plottable() { return mPlottable; } - -protected: - // property members: - QCPAbstractPlottable *mPlottable; - - // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); - virtual QSize minimumSizeHint() const; - - // non-virtual methods: - QPen getIconBorderPen() const; - QColor getTextColor() const; - QFont getFont() const; -}; +/* including file 'src/core.h' */ +/* modified 2022-11-06T12:45:56, size 19304 */ -class QCP_LIB_DECL QCPLegend : public QCPLayoutGrid +class QCP_LIB_DECL QCustomPlot : public QWidget { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QPen borderPen READ borderPen WRITE setBorderPen) - Q_PROPERTY(QBrush brush READ brush WRITE setBrush) - Q_PROPERTY(QFont font READ font WRITE setFont) - Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor) - Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) - Q_PROPERTY(int iconTextPadding READ iconTextPadding WRITE setIconTextPadding) - Q_PROPERTY(QPen iconBorderPen READ iconBorderPen WRITE setIconBorderPen) - Q_PROPERTY(SelectableParts selectableParts READ selectableParts WRITE setSelectableParts NOTIFY selectionChanged) - Q_PROPERTY(SelectableParts selectedParts READ selectedParts WRITE setSelectedParts NOTIFY selectableChanged) - Q_PROPERTY(QPen selectedBorderPen READ selectedBorderPen WRITE setSelectedBorderPen) - Q_PROPERTY(QPen selectedIconBorderPen READ selectedIconBorderPen WRITE setSelectedIconBorderPen) - Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) - Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) - Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor) + Q_PROPERTY(QRect viewport READ viewport WRITE setViewport) + Q_PROPERTY(QPixmap background READ background WRITE setBackground) + Q_PROPERTY(bool backgroundScaled READ backgroundScaled WRITE setBackgroundScaled) + Q_PROPERTY(Qt::AspectRatioMode backgroundScaledMode READ backgroundScaledMode WRITE setBackgroundScaledMode) + Q_PROPERTY(QCPLayoutGrid* plotLayout READ plotLayout) + Q_PROPERTY(bool autoAddPlottableToLegend READ autoAddPlottableToLegend WRITE setAutoAddPlottableToLegend) + Q_PROPERTY(int selectionTolerance READ selectionTolerance WRITE setSelectionTolerance) + Q_PROPERTY(bool noAntialiasingOnDrag READ noAntialiasingOnDrag WRITE setNoAntialiasingOnDrag) + Q_PROPERTY(Qt::KeyboardModifier multiSelectModifier READ multiSelectModifier WRITE setMultiSelectModifier) + Q_PROPERTY(bool openGl READ openGl WRITE setOpenGl) /// \endcond public: /*! - Defines the selectable parts of a legend - - \see setSelectedParts, setSelectableParts + Defines how a layer should be inserted relative to an other layer. + + \see addLayer, moveLayer */ - enum SelectablePart { spNone = 0x000 ///< 0x000 None - ,spLegendBox = 0x001 ///< 0x001 The legend box (frame) - ,spItems = 0x002 ///< 0x002 Legend items individually (see \ref selectedItems) - }; - Q_FLAGS(SelectablePart SelectableParts) - Q_DECLARE_FLAGS(SelectableParts, SelectablePart) + enum LayerInsertMode { limBelow ///< Layer is inserted below other layer + ,limAbove ///< Layer is inserted above other layer + }; + Q_ENUMS(LayerInsertMode) + + /*! + Defines with what timing the QCustomPlot surface is refreshed after a replot. + + \see replot + */ + enum RefreshPriority { rpImmediateRefresh ///< Replots immediately and repaints the widget immediately by calling QWidget::repaint() after the replot + ,rpQueuedRefresh ///< Replots immediately, but queues the widget repaint, by calling QWidget::update() after the replot. This way multiple redundant widget repaints can be avoided. + ,rpRefreshHint ///< Whether to use immediate or queued refresh depends on whether the plotting hint \ref QCP::phImmediateRefresh is set, see \ref setPlottingHints. + ,rpQueuedReplot ///< Queues the entire replot for the next event loop iteration. This way multiple redundant replots can be avoided. The actual replot is then done with \ref rpRefreshHint priority. + }; + Q_ENUMS(RefreshPriority) + + explicit QCustomPlot(QWidget *parent = nullptr); + virtual ~QCustomPlot() Q_DECL_OVERRIDE; + + // getters: + QRect viewport() const { return mViewport; } + double bufferDevicePixelRatio() const { return mBufferDevicePixelRatio; } + QPixmap background() const { return mBackgroundPixmap; } + bool backgroundScaled() const { return mBackgroundScaled; } + Qt::AspectRatioMode backgroundScaledMode() const { return mBackgroundScaledMode; } + QCPLayoutGrid *plotLayout() const { return mPlotLayout; } + QCP::AntialiasedElements antialiasedElements() const { return mAntialiasedElements; } + QCP::AntialiasedElements notAntialiasedElements() const { return mNotAntialiasedElements; } + bool autoAddPlottableToLegend() const { return mAutoAddPlottableToLegend; } + const QCP::Interactions interactions() const { return mInteractions; } + int selectionTolerance() const { return mSelectionTolerance; } + bool noAntialiasingOnDrag() const { return mNoAntialiasingOnDrag; } + QCP::PlottingHints plottingHints() const { return mPlottingHints; } + Qt::KeyboardModifier multiSelectModifier() const { return mMultiSelectModifier; } + QCP::SelectionRectMode selectionRectMode() const { return mSelectionRectMode; } + QCPSelectionRect *selectionRect() const { return mSelectionRect; } + bool openGl() const { return mOpenGl; } + + // setters: + void setViewport(const QRect &rect); + void setBufferDevicePixelRatio(double ratio); + void setBackground(const QPixmap &pm); + void setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode=Qt::KeepAspectRatioByExpanding); + void setBackground(const QBrush &brush); + void setBackgroundScaled(bool scaled); + void setBackgroundScaledMode(Qt::AspectRatioMode mode); + void setAntialiasedElements(const QCP::AntialiasedElements &antialiasedElements); + void setAntialiasedElement(QCP::AntialiasedElement antialiasedElement, bool enabled=true); + void setNotAntialiasedElements(const QCP::AntialiasedElements ¬AntialiasedElements); + void setNotAntialiasedElement(QCP::AntialiasedElement notAntialiasedElement, bool enabled=true); + void setAutoAddPlottableToLegend(bool on); + void setInteractions(const QCP::Interactions &interactions); + void setInteraction(const QCP::Interaction &interaction, bool enabled=true); + void setSelectionTolerance(int pixels); + void setNoAntialiasingOnDrag(bool enabled); + void setPlottingHints(const QCP::PlottingHints &hints); + void setPlottingHint(QCP::PlottingHint hint, bool enabled=true); + void setMultiSelectModifier(Qt::KeyboardModifier modifier); + void setSelectionRectMode(QCP::SelectionRectMode mode); + void setSelectionRect(QCPSelectionRect *selectionRect); + void setOpenGl(bool enabled, int multisampling=16); + + // non-property methods: + // plottable interface: + QCPAbstractPlottable *plottable(int index); + QCPAbstractPlottable *plottable(); + bool removePlottable(QCPAbstractPlottable *plottable); + bool removePlottable(int index); + int clearPlottables(); + int plottableCount() const; + QList selectedPlottables() const; + template + PlottableType *plottableAt(const QPointF &pos, bool onlySelectable=false, int *dataIndex=nullptr) const; + QCPAbstractPlottable *plottableAt(const QPointF &pos, bool onlySelectable=false, int *dataIndex=nullptr) const; + bool hasPlottable(QCPAbstractPlottable *plottable) const; + + // specialized interface for QCPGraph: + QCPGraph *graph(int index) const; + QCPGraph *graph() const; + QCPGraph *addGraph(QCPAxis *keyAxis=nullptr, QCPAxis *valueAxis=nullptr); + bool removeGraph(QCPGraph *graph); + bool removeGraph(int index); + int clearGraphs(); + int graphCount() const; + QList selectedGraphs() const; + + // item interface: + QCPAbstractItem *item(int index) const; + QCPAbstractItem *item() const; + bool removeItem(QCPAbstractItem *item); + bool removeItem(int index); + int clearItems(); + int itemCount() const; + QList selectedItems() const; + template + ItemType *itemAt(const QPointF &pos, bool onlySelectable=false) const; + QCPAbstractItem *itemAt(const QPointF &pos, bool onlySelectable=false) const; + bool hasItem(QCPAbstractItem *item) const; + + // layer interface: + QCPLayer *layer(const QString &name) const; + QCPLayer *layer(int index) const; + QCPLayer *currentLayer() const; + bool setCurrentLayer(const QString &name); + bool setCurrentLayer(QCPLayer *layer); + int layerCount() const; + bool addLayer(const QString &name, QCPLayer *otherLayer=nullptr, LayerInsertMode insertMode=limAbove); + bool removeLayer(QCPLayer *layer); + bool moveLayer(QCPLayer *layer, QCPLayer *otherLayer, LayerInsertMode insertMode=limAbove); + + // axis rect/layout interface: + int axisRectCount() const; + QCPAxisRect* axisRect(int index=0) const; + QList axisRects() const; + QCPLayoutElement* layoutElementAt(const QPointF &pos) const; + QCPAxisRect* axisRectAt(const QPointF &pos) const; + Q_SLOT void rescaleAxes(bool onlyVisiblePlottables=false); + + QList selectedAxes() const; + QList selectedLegends() const; + Q_SLOT void deselectAll(); + + bool savePdf(const QString &fileName, int width=0, int height=0, QCP::ExportPen exportPen=QCP::epAllowCosmetic, const QString &pdfCreator=QString(), const QString &pdfTitle=QString()); + bool savePng(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch); + bool saveJpg(const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch); + bool saveBmp(const QString &fileName, int width=0, int height=0, double scale=1.0, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch); + bool saveRastered(const QString &fileName, int width, int height, double scale, const char *format, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch); + QPixmap toPixmap(int width=0, int height=0, double scale=1.0); + void toPainter(QCPPainter *painter, int width=0, int height=0); + Q_SLOT void replot(QCustomPlot::RefreshPriority refreshPriority=QCustomPlot::rpRefreshHint); + double replotTime(bool average=false) const; + + QCPAxis *xAxis, *yAxis, *xAxis2, *yAxis2; + QCPLegend *legend; + +signals: + void mouseDoubleClick(QMouseEvent *event); + void mousePress(QMouseEvent *event); + void mouseMove(QMouseEvent *event); + void mouseRelease(QMouseEvent *event); + void mouseWheel(QWheelEvent *event); + + void plottableClick(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event); + void plottableDoubleClick(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event); + void itemClick(QCPAbstractItem *item, QMouseEvent *event); + void itemDoubleClick(QCPAbstractItem *item, QMouseEvent *event); + void axisClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event); + void axisDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event); + void legendClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event); + void legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event); + + void selectionChangedByUser(); + void beforeReplot(); + void afterLayout(); + void afterReplot(); + +protected: + // property members: + QRect mViewport; + double mBufferDevicePixelRatio; + QCPLayoutGrid *mPlotLayout; + bool mAutoAddPlottableToLegend; + QList mPlottables; + QList mGraphs; // extra list of plottables also in mPlottables that are of type QCPGraph + QList mItems; + QList mLayers; + QCP::AntialiasedElements mAntialiasedElements, mNotAntialiasedElements; + QCP::Interactions mInteractions; + int mSelectionTolerance; + bool mNoAntialiasingOnDrag; + QBrush mBackgroundBrush; + QPixmap mBackgroundPixmap; + QPixmap mScaledBackgroundPixmap; + bool mBackgroundScaled; + Qt::AspectRatioMode mBackgroundScaledMode; + QCPLayer *mCurrentLayer; + QCP::PlottingHints mPlottingHints; + Qt::KeyboardModifier mMultiSelectModifier; + QCP::SelectionRectMode mSelectionRectMode; + QCPSelectionRect *mSelectionRect; + bool mOpenGl; + + // non-property members: + QList > mPaintBuffers; + QPoint mMousePressPos; + bool mMouseHasMoved; + QPointer mMouseEventLayerable; + QPointer mMouseSignalLayerable; + QVariant mMouseEventLayerableDetails; + QVariant mMouseSignalLayerableDetails; + bool mReplotting; + bool mReplotQueued; + double mReplotTime, mReplotTimeAverage; + int mOpenGlMultisamples; + QCP::AntialiasedElements mOpenGlAntialiasedElementsBackup; + bool mOpenGlCacheLabelsBackup; +#ifdef QCP_OPENGL_FBO + QSharedPointer mGlContext; + QSharedPointer mGlSurface; + QSharedPointer mGlPaintDevice; +#endif + + // reimplemented virtual methods: + virtual QSize minimumSizeHint() const Q_DECL_OVERRIDE; + virtual QSize sizeHint() const Q_DECL_OVERRIDE; + virtual void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + virtual void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; + virtual void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + virtual void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + virtual void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + virtual void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE; + + // introduced virtual methods: + virtual void draw(QCPPainter *painter); + virtual void updateLayout(); + virtual void axisRemoved(QCPAxis *axis); + virtual void legendRemoved(QCPLegend *legend); + Q_SLOT virtual void processRectSelection(QRect rect, QMouseEvent *event); + Q_SLOT virtual void processRectZoom(QRect rect, QMouseEvent *event); + Q_SLOT virtual void processPointSelection(QMouseEvent *event); + + // non-virtual methods: + bool registerPlottable(QCPAbstractPlottable *plottable); + bool registerGraph(QCPGraph *graph); + bool registerItem(QCPAbstractItem* item); + void updateLayerIndices() const; + QCPLayerable *layerableAt(const QPointF &pos, bool onlySelectable, QVariant *selectionDetails=nullptr) const; + QList layerableListAt(const QPointF &pos, bool onlySelectable, QList *selectionDetails=nullptr) const; + void drawBackground(QCPPainter *painter); + void setupPaintBuffers(); + QCPAbstractPaintBuffer *createPaintBuffer(); + bool hasInvalidatedPaintBuffers(); + bool setupOpenGl(); + void freeOpenGl(); + + friend class QCPLegend; + friend class QCPAxis; + friend class QCPLayer; + friend class QCPAxisRect; + friend class QCPAbstractPlottable; + friend class QCPGraph; + friend class QCPAbstractItem; +}; +Q_DECLARE_METATYPE(QCustomPlot::LayerInsertMode) +Q_DECLARE_METATYPE(QCustomPlot::RefreshPriority) + + +// implementation of template functions: + +/*! + Returns the plottable at the pixel position \a pos. The plottable type (a QCPAbstractPlottable + subclass) that shall be taken into consideration can be specified via the template parameter. + + Plottables that only consist of single lines (like graphs) have a tolerance band around them, see + \ref setSelectionTolerance. If multiple plottables come into consideration, the one closest to \a + pos is returned. + + If \a onlySelectable is true, only plottables that are selectable + (QCPAbstractPlottable::setSelectable) are considered. + + if \a dataIndex is non-null, it is set to the index of the plottable's data point that is closest + to \a pos. + + If there is no plottable of the specified type at \a pos, returns \c nullptr. + + \see itemAt, layoutElementAt +*/ +template +PlottableType *QCustomPlot::plottableAt(const QPointF &pos, bool onlySelectable, int *dataIndex) const +{ + PlottableType *resultPlottable = 0; + QVariant resultDetails; + double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value + + foreach (QCPAbstractPlottable *plottable, mPlottables) + { + PlottableType *currentPlottable = qobject_cast(plottable); + if (!currentPlottable || (onlySelectable && !currentPlottable->selectable())) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPAbstractPlottable::selectable + continue; + if (currentPlottable->clipRect().contains(pos.toPoint())) // only consider clicks where the plottable is actually visible + { + QVariant details; + double currentDistance = currentPlottable->selectTest(pos, false, dataIndex ? &details : nullptr); + if (currentDistance >= 0 && currentDistance < resultDistance) + { + resultPlottable = currentPlottable; + resultDetails = details; + resultDistance = currentDistance; + } + } + } + + if (resultPlottable && dataIndex) + { + QCPDataSelection sel = resultDetails.value(); + if (!sel.isEmpty()) + *dataIndex = sel.dataRange(0).begin(); + } + return resultPlottable; +} + +/*! + Returns the item at the pixel position \a pos. The item type (a QCPAbstractItem subclass) that shall be + taken into consideration can be specified via the template parameter. Items that only consist of single + lines (e.g. \ref QCPItemLine or \ref QCPItemCurve) have a tolerance band around them, see \ref + setSelectionTolerance. If multiple items come into consideration, the one closest to \a pos is returned. + + If \a onlySelectable is true, only items that are selectable (QCPAbstractItem::setSelectable) are + considered. + + If there is no item at \a pos, returns \c nullptr. + + \see plottableAt, layoutElementAt +*/ +template +ItemType *QCustomPlot::itemAt(const QPointF &pos, bool onlySelectable) const +{ + ItemType *resultItem = 0; + double resultDistance = mSelectionTolerance; // only regard clicks with distances smaller than mSelectionTolerance as selections, so initialize with that value + + foreach (QCPAbstractItem *item, mItems) + { + ItemType *currentItem = qobject_cast(item); + if (!currentItem || (onlySelectable && !currentItem->selectable())) // we could have also passed onlySelectable to the selectTest function, but checking here is faster, because we have access to QCPAbstractItem::selectable + continue; + if (!currentItem->clipToAxisRect() || currentItem->clipRect().contains(pos.toPoint())) // only consider clicks inside axis cliprect of the item if actually clipped to it + { + double currentDistance = currentItem->selectTest(pos, false); + if (currentDistance >= 0 && currentDistance < resultDistance) + { + resultItem = currentItem; + resultDistance = currentDistance; + } + } + } + + return resultItem; +} + + + +/* end of 'src/core.h' */ + + +/* including file 'src/plottable1d.h' */ +/* modified 2022-11-06T12:45:56, size 25638 */ + +class QCPPlottableInterface1D +{ +public: + virtual ~QCPPlottableInterface1D() = default; + // introduced pure virtual methods: + virtual int dataCount() const = 0; + virtual double dataMainKey(int index) const = 0; + virtual double dataSortKey(int index) const = 0; + virtual double dataMainValue(int index) const = 0; + virtual QCPRange dataValueRange(int index) const = 0; + virtual QPointF dataPixelPosition(int index) const = 0; + virtual bool sortKeyIsMainKey() const = 0; + virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const = 0; + virtual int findBegin(double sortKey, bool expandedRange=true) const = 0; + virtual int findEnd(double sortKey, bool expandedRange=true) const = 0; +}; + +template +class QCPAbstractPlottable1D : public QCPAbstractPlottable, public QCPPlottableInterface1D // no QCP_LIB_DECL, template class ends up in header (cpp included below) +{ + // No Q_OBJECT macro due to template class + +public: + QCPAbstractPlottable1D(QCPAxis *keyAxis, QCPAxis *valueAxis); + virtual ~QCPAbstractPlottable1D() Q_DECL_OVERRIDE; + + // virtual methods of 1d plottable interface: + virtual int dataCount() const Q_DECL_OVERRIDE; + virtual double dataMainKey(int index) const Q_DECL_OVERRIDE; + virtual double dataSortKey(int index) const Q_DECL_OVERRIDE; + virtual double dataMainValue(int index) const Q_DECL_OVERRIDE; + virtual QCPRange dataValueRange(int index) const Q_DECL_OVERRIDE; + virtual QPointF dataPixelPosition(int index) const Q_DECL_OVERRIDE; + virtual bool sortKeyIsMainKey() const Q_DECL_OVERRIDE; + virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const Q_DECL_OVERRIDE; + virtual int findBegin(double sortKey, bool expandedRange=true) const Q_DECL_OVERRIDE; + virtual int findEnd(double sortKey, bool expandedRange=true) const Q_DECL_OVERRIDE; + + // reimplemented virtual methods: + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + virtual QCPPlottableInterface1D *interface1D() Q_DECL_OVERRIDE { return this; } + +protected: + // property members: + QSharedPointer > mDataContainer; + + // helpers for subclasses: + void getDataSegments(QList &selectedSegments, QList &unselectedSegments) const; + void drawPolyline(QCPPainter *painter, const QVector &lineData) const; + +private: + Q_DISABLE_COPY(QCPAbstractPlottable1D) + +}; + + + +// include implementation in header since it is a class template: +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPPlottableInterface1D +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPPlottableInterface1D + \brief Defines an abstract interface for one-dimensional plottables + + This class contains only pure virtual methods which define a common interface to the data + of one-dimensional plottables. + + For example, it is implemented by the template class \ref QCPAbstractPlottable1D (the preferred + base class for one-dimensional plottables). So if you use that template class as base class of + your one-dimensional plottable, you won't have to care about implementing the 1d interface + yourself. + + If your plottable doesn't derive from \ref QCPAbstractPlottable1D but still wants to provide a 1d + interface (e.g. like \ref QCPErrorBars does), you should inherit from both \ref + QCPAbstractPlottable and \ref QCPPlottableInterface1D and accordingly reimplement the pure + virtual methods of the 1d interface, matching your data container. Also, reimplement \ref + QCPAbstractPlottable::interface1D to return the \c this pointer. + + If you have a \ref QCPAbstractPlottable pointer, you can check whether it implements this + interface by calling \ref QCPAbstractPlottable::interface1D and testing it for a non-zero return + value. If it indeed implements this interface, you may use it to access the plottable's data + without needing to know the exact type of the plottable or its data point type. +*/ + +/* start documentation of pure virtual functions */ + +/*! \fn virtual int QCPPlottableInterface1D::dataCount() const = 0; + + Returns the number of data points of the plottable. +*/ + +/*! \fn virtual QCPDataSelection QCPPlottableInterface1D::selectTestRect(const QRectF &rect, bool onlySelectable) const = 0; + + Returns a data selection containing all the data points of this plottable which are contained (or + hit by) \a rect. This is used mainly in the selection rect interaction for data selection (\ref + dataselection "data selection mechanism"). + + If \a onlySelectable is true, an empty QCPDataSelection is returned if this plottable is not + selectable (i.e. if \ref QCPAbstractPlottable::setSelectable is \ref QCP::stNone). + + \note \a rect must be a normalized rect (positive or zero width and height). This is especially + important when using the rect of \ref QCPSelectionRect::accepted, which is not necessarily + normalized. Use QRect::normalized() when passing a rect which might not be normalized. +*/ + +/*! \fn virtual double QCPPlottableInterface1D::dataMainKey(int index) const = 0 + + Returns the main key of the data point at the given \a index. + + What the main key is, is defined by the plottable's data type. See the \ref + qcpdatacontainer-datatype "QCPDataContainer DataType" documentation for details about this naming + convention. +*/ + +/*! \fn virtual double QCPPlottableInterface1D::dataSortKey(int index) const = 0 + + Returns the sort key of the data point at the given \a index. + + What the sort key is, is defined by the plottable's data type. See the \ref + qcpdatacontainer-datatype "QCPDataContainer DataType" documentation for details about this naming + convention. +*/ + +/*! \fn virtual double QCPPlottableInterface1D::dataMainValue(int index) const = 0 + + Returns the main value of the data point at the given \a index. + + What the main value is, is defined by the plottable's data type. See the \ref + qcpdatacontainer-datatype "QCPDataContainer DataType" documentation for details about this naming + convention. +*/ + +/*! \fn virtual QCPRange QCPPlottableInterface1D::dataValueRange(int index) const = 0 + + Returns the value range of the data point at the given \a index. + + What the value range is, is defined by the plottable's data type. See the \ref + qcpdatacontainer-datatype "QCPDataContainer DataType" documentation for details about this naming + convention. +*/ + +/*! \fn virtual QPointF QCPPlottableInterface1D::dataPixelPosition(int index) const = 0 + + Returns the pixel position on the widget surface at which the data point at the given \a index + appears. + + Usually this corresponds to the point of \ref dataMainKey/\ref dataMainValue, in pixel + coordinates. However, depending on the plottable, this might be a different apparent position + than just a coord-to-pixel transform of those values. For example, \ref QCPBars apparent data + values can be shifted depending on their stacking, bar grouping or configured base value. +*/ + +/*! \fn virtual bool QCPPlottableInterface1D::sortKeyIsMainKey() const = 0 + + Returns whether the sort key (\ref dataSortKey) is identical to the main key (\ref dataMainKey). + + What the sort and main keys are, is defined by the plottable's data type. See the \ref + qcpdatacontainer-datatype "QCPDataContainer DataType" documentation for details about this naming + convention. +*/ + +/*! \fn virtual int QCPPlottableInterface1D::findBegin(double sortKey, bool expandedRange) const = 0 + + Returns the index of the data point with a (sort-)key that is equal to, just below, or just above + \a sortKey. If \a expandedRange is true, the data point just below \a sortKey will be considered, + otherwise the one just above. + + This can be used in conjunction with \ref findEnd to iterate over data points within a given key + range, including or excluding the bounding data points that are just beyond the specified range. + + If \a expandedRange is true but there are no data points below \a sortKey, 0 is returned. + + If the container is empty, returns 0 (in that case, \ref findEnd will also return 0, so a loop + using these methods will not iterate over the index 0). + + \see findEnd, QCPDataContainer::findBegin +*/ + +/*! \fn virtual int QCPPlottableInterface1D::findEnd(double sortKey, bool expandedRange) const = 0 + + Returns the index one after the data point with a (sort-)key that is equal to, just above, or + just below \a sortKey. If \a expandedRange is true, the data point just above \a sortKey will be + considered, otherwise the one just below. + + This can be used in conjunction with \ref findBegin to iterate over data points within a given + key range, including the bounding data points that are just below and above the specified range. + + If \a expandedRange is true but there are no data points above \a sortKey, the index just above the + highest data point is returned. + + If the container is empty, returns 0. + + \see findBegin, QCPDataContainer::findEnd +*/ + +/* end documentation of pure virtual functions */ + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////// QCPAbstractPlottable1D +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/*! \class QCPAbstractPlottable1D + \brief A template base class for plottables with one-dimensional data + + This template class derives from \ref QCPAbstractPlottable and from the abstract interface \ref + QCPPlottableInterface1D. It serves as a base class for all one-dimensional data (i.e. data with + one key dimension), such as \ref QCPGraph and QCPCurve. + + The template parameter \a DataType is the type of the data points of this plottable (e.g. \ref + QCPGraphData or \ref QCPCurveData). The main purpose of this base class is to provide the member + \a mDataContainer (a shared pointer to a \ref QCPDataContainer "QCPDataContainer") and + implement the according virtual methods of the \ref QCPPlottableInterface1D, such that most + subclassed plottables don't need to worry about this anymore. + + Further, it provides a convenience method for retrieving selected/unselected data segments via + \ref getDataSegments. This is useful when subclasses implement their \ref draw method and need to + draw selected segments with a different pen/brush than unselected segments (also see \ref + QCPSelectionDecorator). + + This class implements basic functionality of \ref QCPAbstractPlottable::selectTest and \ref + QCPPlottableInterface1D::selectTestRect, assuming point-like data points, based on the 1D data + interface. In spite of that, most plottable subclasses will want to reimplement those methods + again, to provide a more accurate hit test based on their specific data visualization geometry. +*/ + +/* start documentation of inline functions */ + +/*! \fn QCPPlottableInterface1D *QCPAbstractPlottable1D::interface1D() + + Returns a \ref QCPPlottableInterface1D pointer to this plottable, providing access to its 1D + interface. + + \seebaseclassmethod +*/ + +/* end documentation of inline functions */ + +/*! + Forwards \a keyAxis and \a valueAxis to the \ref QCPAbstractPlottable::QCPAbstractPlottable + "QCPAbstractPlottable" constructor and allocates the \a mDataContainer. +*/ +template +QCPAbstractPlottable1D::QCPAbstractPlottable1D(QCPAxis *keyAxis, QCPAxis *valueAxis) : + QCPAbstractPlottable(keyAxis, valueAxis), + mDataContainer(new QCPDataContainer) +{ +} + +template +QCPAbstractPlottable1D::~QCPAbstractPlottable1D() +{ +} + +/*! + \copydoc QCPPlottableInterface1D::dataCount +*/ +template +int QCPAbstractPlottable1D::dataCount() const +{ + return mDataContainer->size(); +} + +/*! + \copydoc QCPPlottableInterface1D::dataMainKey +*/ +template +double QCPAbstractPlottable1D::dataMainKey(int index) const +{ + if (index >= 0 && index < mDataContainer->size()) + { + return (mDataContainer->constBegin()+index)->mainKey(); + } else + { + qDebug() << Q_FUNC_INFO << "Index out of bounds" << index; + return 0; + } +} + +/*! + \copydoc QCPPlottableInterface1D::dataSortKey +*/ +template +double QCPAbstractPlottable1D::dataSortKey(int index) const +{ + if (index >= 0 && index < mDataContainer->size()) + { + return (mDataContainer->constBegin()+index)->sortKey(); + } else + { + qDebug() << Q_FUNC_INFO << "Index out of bounds" << index; + return 0; + } +} + +/*! + \copydoc QCPPlottableInterface1D::dataMainValue +*/ +template +double QCPAbstractPlottable1D::dataMainValue(int index) const +{ + if (index >= 0 && index < mDataContainer->size()) + { + return (mDataContainer->constBegin()+index)->mainValue(); + } else + { + qDebug() << Q_FUNC_INFO << "Index out of bounds" << index; + return 0; + } +} + +/*! + \copydoc QCPPlottableInterface1D::dataValueRange +*/ +template +QCPRange QCPAbstractPlottable1D::dataValueRange(int index) const +{ + if (index >= 0 && index < mDataContainer->size()) + { + return (mDataContainer->constBegin()+index)->valueRange(); + } else + { + qDebug() << Q_FUNC_INFO << "Index out of bounds" << index; + return QCPRange(0, 0); + } +} + +/*! + \copydoc QCPPlottableInterface1D::dataPixelPosition +*/ +template +QPointF QCPAbstractPlottable1D::dataPixelPosition(int index) const +{ + if (index >= 0 && index < mDataContainer->size()) + { + const typename QCPDataContainer::const_iterator it = mDataContainer->constBegin()+index; + return coordsToPixels(it->mainKey(), it->mainValue()); + } else + { + qDebug() << Q_FUNC_INFO << "Index out of bounds" << index; + return QPointF(); + } +} + +/*! + \copydoc QCPPlottableInterface1D::sortKeyIsMainKey +*/ +template +bool QCPAbstractPlottable1D::sortKeyIsMainKey() const +{ + return DataType::sortKeyIsMainKey(); +} + +/*! + Implements a rect-selection algorithm assuming the data (accessed via the 1D data interface) is + point-like. Most subclasses will want to reimplement this method again, to provide a more + accurate hit test based on the true data visualization geometry. + + \seebaseclassmethod +*/ +template +QCPDataSelection QCPAbstractPlottable1D::selectTestRect(const QRectF &rect, bool onlySelectable) const +{ + QCPDataSelection result; + if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty()) + return result; + if (!mKeyAxis || !mValueAxis) + return result; + + // convert rect given in pixels to ranges given in plot coordinates: + double key1, value1, key2, value2; + pixelsToCoords(rect.topLeft(), key1, value1); + pixelsToCoords(rect.bottomRight(), key2, value2); + QCPRange keyRange(key1, key2); // QCPRange normalizes internally so we don't have to care about whether key1 < key2 + QCPRange valueRange(value1, value2); + typename QCPDataContainer::const_iterator begin = mDataContainer->constBegin(); + typename QCPDataContainer::const_iterator end = mDataContainer->constEnd(); + if (DataType::sortKeyIsMainKey()) // we can assume that data is sorted by main key, so can reduce the searched key interval: + { + begin = mDataContainer->findBegin(keyRange.lower, false); + end = mDataContainer->findEnd(keyRange.upper, false); + } + if (begin == end) + return result; + + int currentSegmentBegin = -1; // -1 means we're currently not in a segment that's contained in rect + for (typename QCPDataContainer::const_iterator it=begin; it!=end; ++it) + { + if (currentSegmentBegin == -1) + { + if (valueRange.contains(it->mainValue()) && keyRange.contains(it->mainKey())) // start segment + currentSegmentBegin = int(it-mDataContainer->constBegin()); + } else if (!valueRange.contains(it->mainValue()) || !keyRange.contains(it->mainKey())) // segment just ended + { + result.addDataRange(QCPDataRange(currentSegmentBegin, int(it-mDataContainer->constBegin())), false); + currentSegmentBegin = -1; + } + } + // process potential last segment: + if (currentSegmentBegin != -1) + result.addDataRange(QCPDataRange(currentSegmentBegin, int(end-mDataContainer->constBegin())), false); + + result.simplify(); + return result; +} + +/*! + \copydoc QCPPlottableInterface1D::findBegin +*/ +template +int QCPAbstractPlottable1D::findBegin(double sortKey, bool expandedRange) const +{ + return int(mDataContainer->findBegin(sortKey, expandedRange)-mDataContainer->constBegin()); +} + +/*! + \copydoc QCPPlottableInterface1D::findEnd +*/ +template +int QCPAbstractPlottable1D::findEnd(double sortKey, bool expandedRange) const +{ + return int(mDataContainer->findEnd(sortKey, expandedRange)-mDataContainer->constBegin()); +} + +/*! + Implements a point-selection algorithm assuming the data (accessed via the 1D data interface) is + point-like. Most subclasses will want to reimplement this method again, to provide a more + accurate hit test based on the true data visualization geometry. + + If \a details is not 0, it will be set to a \ref QCPDataSelection, describing the closest data point + to \a pos. + + \seebaseclassmethod +*/ +template +double QCPAbstractPlottable1D::selectTest(const QPointF &pos, bool onlySelectable, QVariant *details) const +{ + if ((onlySelectable && mSelectable == QCP::stNone) || mDataContainer->isEmpty()) + return -1; + if (!mKeyAxis || !mValueAxis) + return -1; + + QCPDataSelection selectionResult; + double minDistSqr = (std::numeric_limits::max)(); + int minDistIndex = mDataContainer->size(); + + typename QCPDataContainer::const_iterator begin = mDataContainer->constBegin(); + typename QCPDataContainer::const_iterator end = mDataContainer->constEnd(); + if (DataType::sortKeyIsMainKey()) // we can assume that data is sorted by main key, so can reduce the searched key interval: + { + // determine which key range comes into question, taking selection tolerance around pos into account: + double posKeyMin, posKeyMax, dummy; + pixelsToCoords(pos-QPointF(mParentPlot->selectionTolerance(), mParentPlot->selectionTolerance()), posKeyMin, dummy); + pixelsToCoords(pos+QPointF(mParentPlot->selectionTolerance(), mParentPlot->selectionTolerance()), posKeyMax, dummy); + if (posKeyMin > posKeyMax) + qSwap(posKeyMin, posKeyMax); + begin = mDataContainer->findBegin(posKeyMin, true); + end = mDataContainer->findEnd(posKeyMax, true); + } + if (begin == end) + return -1; + QCPRange keyRange(mKeyAxis->range()); + QCPRange valueRange(mValueAxis->range()); + for (typename QCPDataContainer::const_iterator it=begin; it!=end; ++it) + { + const double mainKey = it->mainKey(); + const double mainValue = it->mainValue(); + if (keyRange.contains(mainKey) && valueRange.contains(mainValue)) // make sure data point is inside visible range, for speedup in cases where sort key isn't main key and we iterate over all points + { + const double currentDistSqr = QCPVector2D(coordsToPixels(mainKey, mainValue)-pos).lengthSquared(); + if (currentDistSqr < minDistSqr) + { + minDistSqr = currentDistSqr; + minDistIndex = int(it-mDataContainer->constBegin()); + } + } + } + if (minDistIndex != mDataContainer->size()) + selectionResult.addDataRange(QCPDataRange(minDistIndex, minDistIndex+1), false); + + selectionResult.simplify(); + if (details) + details->setValue(selectionResult); + return qSqrt(minDistSqr); +} + +/*! + Splits all data into selected and unselected segments and outputs them via \a selectedSegments + and \a unselectedSegments, respectively. + + This is useful when subclasses implement their \ref draw method and need to draw selected + segments with a different pen/brush than unselected segments (also see \ref + QCPSelectionDecorator). + + \see setSelection +*/ +template +void QCPAbstractPlottable1D::getDataSegments(QList &selectedSegments, QList &unselectedSegments) const +{ + selectedSegments.clear(); + unselectedSegments.clear(); + if (mSelectable == QCP::stWhole) // stWhole selection type draws the entire plottable with selected style if mSelection isn't empty + { + if (selected()) + selectedSegments << QCPDataRange(0, dataCount()); + else + unselectedSegments << QCPDataRange(0, dataCount()); + } else + { + QCPDataSelection sel(selection()); + sel.simplify(); + selectedSegments = sel.dataRanges(); + unselectedSegments = sel.inverse(QCPDataRange(0, dataCount())).dataRanges(); + } +} + +/*! + A helper method which draws a line with the passed \a painter, according to the pixel data in \a + lineData. NaN points create gaps in the line, as expected from QCustomPlot's plottables (this is + the main difference to QPainter's regular drawPolyline, which handles NaNs by lagging or + crashing). + + Further it uses a faster line drawing technique based on \ref QCPPainter::drawLine rather than \c + QPainter::drawPolyline if the configured \ref QCustomPlot::setPlottingHints() and \a painter + style allows. +*/ +template +void QCPAbstractPlottable1D::drawPolyline(QCPPainter *painter, const QVector &lineData) const +{ + // if drawing lines in plot (instead of PDF), reduce 1px lines to cosmetic, because at least in + // Qt6 drawing of "1px" width lines is much slower even though it has same appearance apart from + // High-DPI. In High-DPI cases people must set a pen width slightly larger than 1.0 to get + // correct DPI scaling of width, but of course with performance penalty. + if (!painter->modes().testFlag(QCPPainter::pmVectorized) && + qFuzzyCompare(painter->pen().widthF(), 1.0)) + { + QPen newPen = painter->pen(); + newPen.setWidth(0); + painter->setPen(newPen); + } + + // if drawing solid line and not in PDF, use much faster line drawing instead of polyline: + if (mParentPlot->plottingHints().testFlag(QCP::phFastPolylines) && + painter->pen().style() == Qt::SolidLine && + !painter->modes().testFlag(QCPPainter::pmVectorized) && + !painter->modes().testFlag(QCPPainter::pmNoCaching)) + { + int i = 0; + bool lastIsNan = false; + const int lineDataSize = lineData.size(); + while (i < lineDataSize && (qIsNaN(lineData.at(i).y()) || qIsNaN(lineData.at(i).x()))) // make sure first point is not NaN + ++i; + ++i; // because drawing works in 1 point retrospect + while (i < lineDataSize) + { + if (!qIsNaN(lineData.at(i).y()) && !qIsNaN(lineData.at(i).x())) // NaNs create a gap in the line + { + if (!lastIsNan) + painter->drawLine(lineData.at(i-1), lineData.at(i)); + else + lastIsNan = false; + } else + lastIsNan = true; + ++i; + } + } else + { + int segmentStart = 0; + int i = 0; + const int lineDataSize = lineData.size(); + while (i < lineDataSize) + { + if (qIsNaN(lineData.at(i).y()) || qIsNaN(lineData.at(i).x()) || qIsInf(lineData.at(i).y())) // NaNs create a gap in the line. Also filter Infs which make drawPolyline block + { + painter->drawPolyline(lineData.constData()+segmentStart, i-segmentStart); // i, because we don't want to include the current NaN point + segmentStart = i+1; + } + ++i; + } + // draw last segment: + painter->drawPolyline(lineData.constData()+segmentStart, lineDataSize-segmentStart); + } +} + + +/* end of 'src/plottable1d.h' */ + + +/* including file 'src/colorgradient.h' */ +/* modified 2022-11-06T12:45:56, size 7262 */ + +class QCP_LIB_DECL QCPColorGradient +{ + Q_GADGET +public: + /*! + Defines the color spaces in which color interpolation between gradient stops can be performed. + + \see setColorInterpolation + */ + enum ColorInterpolation { ciRGB ///< Color channels red, green and blue are linearly interpolated + ,ciHSV ///< Color channels hue, saturation and value are linearly interpolated (The hue is interpolated over the shortest angle distance) + }; + Q_ENUMS(ColorInterpolation) + + /*! + Defines how NaN data points shall appear in the plot. + + \see setNanHandling, setNanColor + */ + enum NanHandling { nhNone ///< NaN data points are not explicitly handled and shouldn't occur in the data (this gives slight performance improvement) + ,nhLowestColor ///< NaN data points appear as the lowest color defined in this QCPColorGradient + ,nhHighestColor ///< NaN data points appear as the highest color defined in this QCPColorGradient + ,nhTransparent ///< NaN data points appear transparent + ,nhNanColor ///< NaN data points appear as the color defined with \ref setNanColor + }; + Q_ENUMS(NanHandling) + + /*! + Defines the available presets that can be loaded with \ref loadPreset. See the documentation + there for an image of the presets. + */ + enum GradientPreset { gpGrayscale ///< Continuous lightness from black to white (suited for non-biased data representation) + ,gpHot ///< Continuous lightness from black over firey colors to white (suited for non-biased data representation) + ,gpCold ///< Continuous lightness from black over icey colors to white (suited for non-biased data representation) + ,gpNight ///< Continuous lightness from black over weak blueish colors to white (suited for non-biased data representation) + ,gpCandy ///< Blue over pink to white + ,gpGeography ///< Colors suitable to represent different elevations on geographical maps + ,gpIon ///< Half hue spectrum from black over purple to blue and finally green (creates banding illusion but allows more precise magnitude estimates) + ,gpThermal ///< Colors suitable for thermal imaging, ranging from dark blue over purple to orange, yellow and white + ,gpPolar ///< Colors suitable to emphasize polarity around the center, with blue for negative, black in the middle and red for positive values + ,gpSpectrum ///< An approximation of the visible light spectrum (creates banding illusion but allows more precise magnitude estimates) + ,gpJet ///< Hue variation similar to a spectrum, often used in numerical visualization (creates banding illusion but allows more precise magnitude estimates) + ,gpHues ///< Full hue cycle, with highest and lowest color red (suitable for periodic data, such as angles and phases, see \ref setPeriodic) + }; + Q_ENUMS(GradientPreset) + + QCPColorGradient(); + QCPColorGradient(GradientPreset preset); + bool operator==(const QCPColorGradient &other) const; + bool operator!=(const QCPColorGradient &other) const { return !(*this == other); } + + // getters: + int levelCount() const { return mLevelCount; } + QMap colorStops() const { return mColorStops; } + ColorInterpolation colorInterpolation() const { return mColorInterpolation; } + NanHandling nanHandling() const { return mNanHandling; } + QColor nanColor() const { return mNanColor; } + bool periodic() const { return mPeriodic; } + + // setters: + void setLevelCount(int n); + void setColorStops(const QMap &colorStops); + void setColorStopAt(double position, const QColor &color); + void setColorInterpolation(ColorInterpolation interpolation); + void setNanHandling(NanHandling handling); + void setNanColor(const QColor &color); + void setPeriodic(bool enabled); + + // non-property methods: + void colorize(const double *data, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor=1, bool logarithmic=false); + void colorize(const double *data, const unsigned char *alpha, const QCPRange &range, QRgb *scanLine, int n, int dataIndexFactor=1, bool logarithmic=false); + QRgb color(double position, const QCPRange &range, bool logarithmic=false); + void loadPreset(GradientPreset preset); + void clearColorStops(); + QCPColorGradient inverted() const; + +protected: + // property members: + int mLevelCount; + QMap mColorStops; + ColorInterpolation mColorInterpolation; + NanHandling mNanHandling; + QColor mNanColor; + bool mPeriodic; + + // non-property members: + QVector mColorBuffer; // have colors premultiplied with alpha (for usage with QImage::Format_ARGB32_Premultiplied) + bool mColorBufferInvalidated; + + // non-virtual methods: + bool stopsUseAlpha() const; + void updateColorBuffer(); +}; +Q_DECLARE_METATYPE(QCPColorGradient::ColorInterpolation) +Q_DECLARE_METATYPE(QCPColorGradient::NanHandling) +Q_DECLARE_METATYPE(QCPColorGradient::GradientPreset) + +/* end of 'src/colorgradient.h' */ + + +/* including file 'src/selectiondecorator-bracket.h' */ +/* modified 2022-11-06T12:45:56, size 4458 */ + +class QCP_LIB_DECL QCPSelectionDecoratorBracket : public QCPSelectionDecorator +{ + Q_GADGET +public: + + /*! + Defines which shape is drawn at the boundaries of selected data ranges. + + Some of the bracket styles further allow specifying a height and/or width, see \ref + setBracketHeight and \ref setBracketWidth. + */ + enum BracketStyle { bsSquareBracket ///< A square bracket is drawn. + ,bsHalfEllipse ///< A half ellipse is drawn. The size of the ellipse is given by the bracket width/height properties. + ,bsEllipse ///< An ellipse is drawn. The size of the ellipse is given by the bracket width/height properties. + ,bsPlus ///< A plus is drawn. + ,bsUserStyle ///< Start custom bracket styles at this index when subclassing and reimplementing \ref drawBracket. + }; + Q_ENUMS(BracketStyle) + + QCPSelectionDecoratorBracket(); + virtual ~QCPSelectionDecoratorBracket() Q_DECL_OVERRIDE; + + // getters: + QPen bracketPen() const { return mBracketPen; } + QBrush bracketBrush() const { return mBracketBrush; } + int bracketWidth() const { return mBracketWidth; } + int bracketHeight() const { return mBracketHeight; } + BracketStyle bracketStyle() const { return mBracketStyle; } + bool tangentToData() const { return mTangentToData; } + int tangentAverage() const { return mTangentAverage; } + + // setters: + void setBracketPen(const QPen &pen); + void setBracketBrush(const QBrush &brush); + void setBracketWidth(int width); + void setBracketHeight(int height); + void setBracketStyle(BracketStyle style); + void setTangentToData(bool enabled); + void setTangentAverage(int pointCount); + + // introduced virtual methods: + virtual void drawBracket(QCPPainter *painter, int direction) const; + + // virtual methods: + virtual void drawDecoration(QCPPainter *painter, QCPDataSelection selection) Q_DECL_OVERRIDE; + +protected: + // property members: + QPen mBracketPen; + QBrush mBracketBrush; + int mBracketWidth; + int mBracketHeight; + BracketStyle mBracketStyle; + bool mTangentToData; + int mTangentAverage; + + // non-virtual methods: + double getTangentAngle(const QCPPlottableInterface1D *interface1d, int dataIndex, int direction) const; + QPointF getPixelCoordinates(const QCPPlottableInterface1D *interface1d, int dataIndex) const; + +}; +Q_DECLARE_METATYPE(QCPSelectionDecoratorBracket::BracketStyle) + +/* end of 'src/selectiondecorator-bracket.h' */ + + +/* including file 'src/layoutelements/layoutelement-axisrect.h' */ +/* modified 2022-11-06T12:45:56, size 7529 */ + +class QCP_LIB_DECL QCPAxisRect : public QCPLayoutElement +{ + Q_OBJECT + /// \cond INCLUDE_QPROPERTIES + Q_PROPERTY(QPixmap background READ background WRITE setBackground) + Q_PROPERTY(bool backgroundScaled READ backgroundScaled WRITE setBackgroundScaled) + Q_PROPERTY(Qt::AspectRatioMode backgroundScaledMode READ backgroundScaledMode WRITE setBackgroundScaledMode) + Q_PROPERTY(Qt::Orientations rangeDrag READ rangeDrag WRITE setRangeDrag) + Q_PROPERTY(Qt::Orientations rangeZoom READ rangeZoom WRITE setRangeZoom) + /// \endcond +public: + explicit QCPAxisRect(QCustomPlot *parentPlot, bool setupDefaultAxes=true); + virtual ~QCPAxisRect() Q_DECL_OVERRIDE; + + // getters: + QPixmap background() const { return mBackgroundPixmap; } + QBrush backgroundBrush() const { return mBackgroundBrush; } + bool backgroundScaled() const { return mBackgroundScaled; } + Qt::AspectRatioMode backgroundScaledMode() const { return mBackgroundScaledMode; } + Qt::Orientations rangeDrag() const { return mRangeDrag; } + Qt::Orientations rangeZoom() const { return mRangeZoom; } + QCPAxis *rangeDragAxis(Qt::Orientation orientation); + QCPAxis *rangeZoomAxis(Qt::Orientation orientation); + QList rangeDragAxes(Qt::Orientation orientation); + QList rangeZoomAxes(Qt::Orientation orientation); + double rangeZoomFactor(Qt::Orientation orientation); + + // setters: + void setBackground(const QPixmap &pm); + void setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode=Qt::KeepAspectRatioByExpanding); + void setBackground(const QBrush &brush); + void setBackgroundScaled(bool scaled); + void setBackgroundScaledMode(Qt::AspectRatioMode mode); + void setRangeDrag(Qt::Orientations orientations); + void setRangeZoom(Qt::Orientations orientations); + void setRangeDragAxes(QCPAxis *horizontal, QCPAxis *vertical); + void setRangeDragAxes(QList axes); + void setRangeDragAxes(QList horizontal, QList vertical); + void setRangeZoomAxes(QCPAxis *horizontal, QCPAxis *vertical); + void setRangeZoomAxes(QList axes); + void setRangeZoomAxes(QList horizontal, QList vertical); + void setRangeZoomFactor(double horizontalFactor, double verticalFactor); + void setRangeZoomFactor(double factor); + + // non-property methods: + int axisCount(QCPAxis::AxisType type) const; + QCPAxis *axis(QCPAxis::AxisType type, int index=0) const; + QList axes(QCPAxis::AxisTypes types) const; + QList axes() const; + QCPAxis *addAxis(QCPAxis::AxisType type, QCPAxis *axis=nullptr); + QList addAxes(QCPAxis::AxisTypes types); + bool removeAxis(QCPAxis *axis); + QCPLayoutInset *insetLayout() const { return mInsetLayout; } + + void zoom(const QRectF &pixelRect); + void zoom(const QRectF &pixelRect, const QList &affectedAxes); + void setupFullAxesBox(bool connectRanges=false); + QList plottables() const; + QList graphs() const; + QList items() const; + + // read-only interface imitating a QRect: + int left() const { return mRect.left(); } + int right() const { return mRect.right(); } + int top() const { return mRect.top(); } + int bottom() const { return mRect.bottom(); } + int width() const { return mRect.width(); } + int height() const { return mRect.height(); } + QSize size() const { return mRect.size(); } + QPoint topLeft() const { return mRect.topLeft(); } + QPoint topRight() const { return mRect.topRight(); } + QPoint bottomLeft() const { return mRect.bottomLeft(); } + QPoint bottomRight() const { return mRect.bottomRight(); } + QPoint center() const { return mRect.center(); } + + // reimplemented virtual methods: + virtual void update(UpdatePhase phase) Q_DECL_OVERRIDE; + virtual QList elements(bool recursive) const Q_DECL_OVERRIDE; + +protected: + // property members: + QBrush mBackgroundBrush; + QPixmap mBackgroundPixmap; + QPixmap mScaledBackgroundPixmap; + bool mBackgroundScaled; + Qt::AspectRatioMode mBackgroundScaledMode; + QCPLayoutInset *mInsetLayout; + Qt::Orientations mRangeDrag, mRangeZoom; + QList > mRangeDragHorzAxis, mRangeDragVertAxis; + QList > mRangeZoomHorzAxis, mRangeZoomVertAxis; + double mRangeZoomFactorHorz, mRangeZoomFactorVert; + + // non-property members: + QList mDragStartHorzRange, mDragStartVertRange; + QCP::AntialiasedElements mAADragBackup, mNotAADragBackup; + bool mDragging; + QHash > mAxes; + + // reimplemented virtual methods: + virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual int calculateAutoMargin(QCP::MarginSide side) Q_DECL_OVERRIDE; + virtual void layoutChanged() Q_DECL_OVERRIDE; + // events: + virtual void mousePressEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE; + virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE; + virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE; + virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE; + + // non-property methods: + void drawBackground(QCPPainter *painter); + void updateAxesOffset(QCPAxis::AxisType type); + +private: + Q_DISABLE_COPY(QCPAxisRect) + + friend class QCustomPlot; +}; + + +/* end of 'src/layoutelements/layoutelement-axisrect.h' */ + + +/* including file 'src/layoutelements/layoutelement-legend.h' */ +/* modified 2022-11-06T12:45:56, size 10425 */ + +class QCP_LIB_DECL QCPAbstractLegendItem : public QCPLayoutElement +{ + Q_OBJECT + /// \cond INCLUDE_QPROPERTIES + Q_PROPERTY(QCPLegend* parentLegend READ parentLegend) + Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor) + Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) + Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor) + Q_PROPERTY(bool selectable READ selectable WRITE setSelectable NOTIFY selectionChanged) + Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectableChanged) + /// \endcond +public: + explicit QCPAbstractLegendItem(QCPLegend *parent); + + // getters: + QCPLegend *parentLegend() const { return mParentLegend; } + QFont font() const { return mFont; } + QColor textColor() const { return mTextColor; } + QFont selectedFont() const { return mSelectedFont; } + QColor selectedTextColor() const { return mSelectedTextColor; } + bool selectable() const { return mSelectable; } + bool selected() const { return mSelected; } + + // setters: + void setFont(const QFont &font); + void setTextColor(const QColor &color); + void setSelectedFont(const QFont &font); + void setSelectedTextColor(const QColor &color); + Q_SLOT void setSelectable(bool selectable); + Q_SLOT void setSelected(bool selected); + + // reimplemented virtual methods: + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + +signals: + void selectionChanged(bool selected); + void selectableChanged(bool selectable); + +protected: + // property members: + QCPLegend *mParentLegend; + QFont mFont; + QColor mTextColor; + QFont mSelectedFont; + QColor mSelectedTextColor; + bool mSelectable, mSelected; + + // reimplemented virtual methods: + virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE; + virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE; + virtual QRect clipRect() const Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE = 0; + // events: + virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE; + virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(QCPAbstractLegendItem) + + friend class QCPLegend; +}; + + +class QCP_LIB_DECL QCPPlottableLegendItem : public QCPAbstractLegendItem +{ + Q_OBJECT +public: + QCPPlottableLegendItem(QCPLegend *parent, QCPAbstractPlottable *plottable); + + // getters: + QCPAbstractPlottable *plottable() { return mPlottable; } + +protected: + // property members: + QCPAbstractPlottable *mPlottable; + + // reimplemented virtual methods: + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual QSize minimumOuterSizeHint() const Q_DECL_OVERRIDE; + + // non-virtual methods: + QPen getIconBorderPen() const; + QColor getTextColor() const; + QFont getFont() const; +}; + + +class QCP_LIB_DECL QCPLegend : public QCPLayoutGrid +{ + Q_OBJECT + /// \cond INCLUDE_QPROPERTIES + Q_PROPERTY(QPen borderPen READ borderPen WRITE setBorderPen) + Q_PROPERTY(QBrush brush READ brush WRITE setBrush) + Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor) + Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) + Q_PROPERTY(int iconTextPadding READ iconTextPadding WRITE setIconTextPadding) + Q_PROPERTY(QPen iconBorderPen READ iconBorderPen WRITE setIconBorderPen) + Q_PROPERTY(SelectableParts selectableParts READ selectableParts WRITE setSelectableParts NOTIFY selectionChanged) + Q_PROPERTY(SelectableParts selectedParts READ selectedParts WRITE setSelectedParts NOTIFY selectableChanged) + Q_PROPERTY(QPen selectedBorderPen READ selectedBorderPen WRITE setSelectedBorderPen) + Q_PROPERTY(QPen selectedIconBorderPen READ selectedIconBorderPen WRITE setSelectedIconBorderPen) + Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) + Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) + Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor) + /// \endcond +public: + /*! + Defines the selectable parts of a legend + + \see setSelectedParts, setSelectableParts + */ + enum SelectablePart { spNone = 0x000 ///< 0x000 None + ,spLegendBox = 0x001 ///< 0x001 The legend box (frame) + ,spItems = 0x002 ///< 0x002 Legend items individually (see \ref selectedItems) + }; + Q_ENUMS(SelectablePart) + Q_FLAGS(SelectableParts) + Q_DECLARE_FLAGS(SelectableParts, SelectablePart) explicit QCPLegend(); - virtual ~QCPLegend(); + virtual ~QCPLegend() Q_DECL_OVERRIDE; + + // getters: + QPen borderPen() const { return mBorderPen; } + QBrush brush() const { return mBrush; } + QFont font() const { return mFont; } + QColor textColor() const { return mTextColor; } + QSize iconSize() const { return mIconSize; } + int iconTextPadding() const { return mIconTextPadding; } + QPen iconBorderPen() const { return mIconBorderPen; } + SelectableParts selectableParts() const { return mSelectableParts; } + SelectableParts selectedParts() const; + QPen selectedBorderPen() const { return mSelectedBorderPen; } + QPen selectedIconBorderPen() const { return mSelectedIconBorderPen; } + QBrush selectedBrush() const { return mSelectedBrush; } + QFont selectedFont() const { return mSelectedFont; } + QColor selectedTextColor() const { return mSelectedTextColor; } + + // setters: + void setBorderPen(const QPen &pen); + void setBrush(const QBrush &brush); + void setFont(const QFont &font); + void setTextColor(const QColor &color); + void setIconSize(const QSize &size); + void setIconSize(int width, int height); + void setIconTextPadding(int padding); + void setIconBorderPen(const QPen &pen); + Q_SLOT void setSelectableParts(const SelectableParts &selectableParts); + Q_SLOT void setSelectedParts(const SelectableParts &selectedParts); + void setSelectedBorderPen(const QPen &pen); + void setSelectedIconBorderPen(const QPen &pen); + void setSelectedBrush(const QBrush &brush); + void setSelectedFont(const QFont &font); + void setSelectedTextColor(const QColor &color); + + // reimplemented virtual methods: + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + + // non-virtual methods: + QCPAbstractLegendItem *item(int index) const; + QCPPlottableLegendItem *itemWithPlottable(const QCPAbstractPlottable *plottable) const; + int itemCount() const; + bool hasItem(QCPAbstractLegendItem *item) const; + bool hasItemWithPlottable(const QCPAbstractPlottable *plottable) const; + bool addItem(QCPAbstractLegendItem *item); + bool removeItem(int index); + bool removeItem(QCPAbstractLegendItem *item); + void clearItems(); + QList selectedItems() const; + +signals: + void selectionChanged(QCPLegend::SelectableParts parts); + void selectableChanged(QCPLegend::SelectableParts parts); + +protected: + // property members: + QPen mBorderPen, mIconBorderPen; + QBrush mBrush; + QFont mFont; + QColor mTextColor; + QSize mIconSize; + int mIconTextPadding; + SelectableParts mSelectedParts, mSelectableParts; + QPen mSelectedBorderPen, mSelectedIconBorderPen; + QBrush mSelectedBrush; + QFont mSelectedFont; + QColor mSelectedTextColor; + + // reimplemented virtual methods: + virtual void parentPlotInitialized(QCustomPlot *parentPlot) Q_DECL_OVERRIDE; + virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE; + virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + // events: + virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE; + virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE; + + // non-virtual methods: + QPen getBorderPen() const; + QBrush getBrush() const; + +private: + Q_DISABLE_COPY(QCPLegend) + + friend class QCustomPlot; + friend class QCPAbstractLegendItem; +}; +Q_DECLARE_OPERATORS_FOR_FLAGS(QCPLegend::SelectableParts) +Q_DECLARE_METATYPE(QCPLegend::SelectablePart) + +/* end of 'src/layoutelements/layoutelement-legend.h' */ + + +/* including file 'src/layoutelements/layoutelement-textelement.h' */ +/* modified 2022-11-06T12:45:56, size 5359 */ + +class QCP_LIB_DECL QCPTextElement : public QCPLayoutElement +{ + Q_OBJECT + /// \cond INCLUDE_QPROPERTIES + Q_PROPERTY(QString text READ text WRITE setText) + Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor) + Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) + Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor) + Q_PROPERTY(bool selectable READ selectable WRITE setSelectable NOTIFY selectableChanged) + Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectionChanged) + /// \endcond +public: + explicit QCPTextElement(QCustomPlot *parentPlot); + QCPTextElement(QCustomPlot *parentPlot, const QString &text); + QCPTextElement(QCustomPlot *parentPlot, const QString &text, double pointSize); + QCPTextElement(QCustomPlot *parentPlot, const QString &text, const QString &fontFamily, double pointSize); + QCPTextElement(QCustomPlot *parentPlot, const QString &text, const QFont &font); + + // getters: + QString text() const { return mText; } + int textFlags() const { return mTextFlags; } + QFont font() const { return mFont; } + QColor textColor() const { return mTextColor; } + QFont selectedFont() const { return mSelectedFont; } + QColor selectedTextColor() const { return mSelectedTextColor; } + bool selectable() const { return mSelectable; } + bool selected() const { return mSelected; } + + // setters: + void setText(const QString &text); + void setTextFlags(int flags); + void setFont(const QFont &font); + void setTextColor(const QColor &color); + void setSelectedFont(const QFont &font); + void setSelectedTextColor(const QColor &color); + Q_SLOT void setSelectable(bool selectable); + Q_SLOT void setSelected(bool selected); + + // reimplemented virtual methods: + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + virtual void mousePressEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE; + virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE; + virtual void mouseDoubleClickEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE; + +signals: + void selectionChanged(bool selected); + void selectableChanged(bool selectable); + void clicked(QMouseEvent *event); + void doubleClicked(QMouseEvent *event); + +protected: + // property members: + QString mText; + int mTextFlags; + QFont mFont; + QColor mTextColor; + QFont mSelectedFont; + QColor mSelectedTextColor; + QRect mTextBoundingRect; + bool mSelectable, mSelected; + + // reimplemented virtual methods: + virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual QSize minimumOuterSizeHint() const Q_DECL_OVERRIDE; + virtual QSize maximumOuterSizeHint() const Q_DECL_OVERRIDE; + // events: + virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE; + virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE; + + // non-virtual methods: + QFont mainFont() const; + QColor mainTextColor() const; + +private: + Q_DISABLE_COPY(QCPTextElement) +}; + + + +/* end of 'src/layoutelements/layoutelement-textelement.h' */ + + +/* including file 'src/layoutelements/layoutelement-colorscale.h' */ +/* modified 2022-11-06T12:45:56, size 5939 */ + + +class QCPColorScaleAxisRectPrivate : public QCPAxisRect +{ + Q_OBJECT +public: + explicit QCPColorScaleAxisRectPrivate(QCPColorScale *parentColorScale); +protected: + QCPColorScale *mParentColorScale; + QImage mGradientImage; + bool mGradientImageInvalidated; + // re-using some methods of QCPAxisRect to make them available to friend class QCPColorScale + using QCPAxisRect::calculateAutoMargin; + using QCPAxisRect::mousePressEvent; + using QCPAxisRect::mouseMoveEvent; + using QCPAxisRect::mouseReleaseEvent; + using QCPAxisRect::wheelEvent; + using QCPAxisRect::update; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + void updateGradientImage(); + Q_SLOT void axisSelectionChanged(QCPAxis::SelectableParts selectedParts); + Q_SLOT void axisSelectableChanged(QCPAxis::SelectableParts selectableParts); + friend class QCPColorScale; +}; + + +class QCP_LIB_DECL QCPColorScale : public QCPLayoutElement +{ + Q_OBJECT + /// \cond INCLUDE_QPROPERTIES + Q_PROPERTY(QCPAxis::AxisType type READ type WRITE setType) + Q_PROPERTY(QCPRange dataRange READ dataRange WRITE setDataRange NOTIFY dataRangeChanged) + Q_PROPERTY(QCPAxis::ScaleType dataScaleType READ dataScaleType WRITE setDataScaleType NOTIFY dataScaleTypeChanged) + Q_PROPERTY(QCPColorGradient gradient READ gradient WRITE setGradient NOTIFY gradientChanged) + Q_PROPERTY(QString label READ label WRITE setLabel) + Q_PROPERTY(int barWidth READ barWidth WRITE setBarWidth) + Q_PROPERTY(bool rangeDrag READ rangeDrag WRITE setRangeDrag) + Q_PROPERTY(bool rangeZoom READ rangeZoom WRITE setRangeZoom) + /// \endcond +public: + explicit QCPColorScale(QCustomPlot *parentPlot); + virtual ~QCPColorScale() Q_DECL_OVERRIDE; + + // getters: + QCPAxis *axis() const { return mColorAxis.data(); } + QCPAxis::AxisType type() const { return mType; } + QCPRange dataRange() const { return mDataRange; } + QCPAxis::ScaleType dataScaleType() const { return mDataScaleType; } + QCPColorGradient gradient() const { return mGradient; } + QString label() const; + int barWidth () const { return mBarWidth; } + bool rangeDrag() const; + bool rangeZoom() const; + + // setters: + void setType(QCPAxis::AxisType type); + Q_SLOT void setDataRange(const QCPRange &dataRange); + Q_SLOT void setDataScaleType(QCPAxis::ScaleType scaleType); + Q_SLOT void setGradient(const QCPColorGradient &gradient); + void setLabel(const QString &str); + void setBarWidth(int width); + void setRangeDrag(bool enabled); + void setRangeZoom(bool enabled); + + // non-property methods: + QList colorMaps() const; + void rescaleDataRange(bool onlyVisibleMaps); + + // reimplemented virtual methods: + virtual void update(UpdatePhase phase) Q_DECL_OVERRIDE; + +signals: + void dataRangeChanged(const QCPRange &newRange); + void dataScaleTypeChanged(QCPAxis::ScaleType scaleType); + void gradientChanged(const QCPColorGradient &newGradient); + +protected: + // property members: + QCPAxis::AxisType mType; + QCPRange mDataRange; + QCPAxis::ScaleType mDataScaleType; + QCPColorGradient mGradient; + int mBarWidth; + + // non-property members: + QPointer mAxisRect; + QPointer mColorAxis; + + // reimplemented virtual methods: + virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE; + // events: + virtual void mousePressEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE; + virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE; + virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE; + virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(QCPColorScale) + + friend class QCPColorScaleAxisRectPrivate; +}; + + +/* end of 'src/layoutelements/layoutelement-colorscale.h' */ + + +/* including file 'src/plottables/plottable-graph.h' */ +/* modified 2022-11-06T12:45:56, size 9316 */ + +class QCP_LIB_DECL QCPGraphData +{ +public: + QCPGraphData(); + QCPGraphData(double key, double value); + + inline double sortKey() const { return key; } + inline static QCPGraphData fromSortKey(double sortKey) { return QCPGraphData(sortKey, 0); } + inline static bool sortKeyIsMainKey() { return true; } + + inline double mainKey() const { return key; } + inline double mainValue() const { return value; } + + inline QCPRange valueRange() const { return QCPRange(value, value); } + + double key, value; +}; +Q_DECLARE_TYPEINFO(QCPGraphData, Q_PRIMITIVE_TYPE); + + +/*! \typedef QCPGraphDataContainer + + Container for storing \ref QCPGraphData points. The data is stored sorted by \a key. + + This template instantiation is the container in which QCPGraph holds its data. For details about + the generic container, see the documentation of the class template \ref QCPDataContainer. + + \see QCPGraphData, QCPGraph::setData +*/ +typedef QCPDataContainer QCPGraphDataContainer; + +class QCP_LIB_DECL QCPGraph : public QCPAbstractPlottable1D +{ + Q_OBJECT + /// \cond INCLUDE_QPROPERTIES + Q_PROPERTY(LineStyle lineStyle READ lineStyle WRITE setLineStyle) + Q_PROPERTY(QCPScatterStyle scatterStyle READ scatterStyle WRITE setScatterStyle) + Q_PROPERTY(int scatterSkip READ scatterSkip WRITE setScatterSkip) + Q_PROPERTY(QCPGraph* channelFillGraph READ channelFillGraph WRITE setChannelFillGraph) + Q_PROPERTY(bool adaptiveSampling READ adaptiveSampling WRITE setAdaptiveSampling) + /// \endcond +public: + /*! + Defines how the graph's line is represented visually in the plot. The line is drawn with the + current pen of the graph (\ref setPen). + \see setLineStyle + */ + enum LineStyle { lsNone ///< data points are not connected with any lines (e.g. data only represented + ///< with symbols according to the scatter style, see \ref setScatterStyle) + ,lsLine ///< data points are connected by a straight line + ,lsStepLeft ///< line is drawn as steps where the step height is the value of the left data point + ,lsStepRight ///< line is drawn as steps where the step height is the value of the right data point + ,lsStepCenter ///< line is drawn as steps where the step is in between two data points + ,lsImpulse ///< each data point is represented by a line parallel to the value axis, which reaches from the data point to the zero-value-line + }; + Q_ENUMS(LineStyle) + + explicit QCPGraph(QCPAxis *keyAxis, QCPAxis *valueAxis); + virtual ~QCPGraph() Q_DECL_OVERRIDE; + + // getters: + QSharedPointer data() const { return mDataContainer; } + LineStyle lineStyle() const { return mLineStyle; } + QCPScatterStyle scatterStyle() const { return mScatterStyle; } + int scatterSkip() const { return mScatterSkip; } + QCPGraph *channelFillGraph() const { return mChannelFillGraph.data(); } + bool adaptiveSampling() const { return mAdaptiveSampling; } + + // setters: + void setData(QSharedPointer data); + void setData(const QVector &keys, const QVector &values, bool alreadySorted=false); + void setLineStyle(LineStyle ls); + void setScatterStyle(const QCPScatterStyle &style); + void setScatterSkip(int skip); + void setChannelFillGraph(QCPGraph *targetGraph); + void setAdaptiveSampling(bool enabled); + + // non-property methods: + void addData(const QVector &keys, const QVector &values, bool alreadySorted=false); + void addData(double key, double value); + + // reimplemented virtual methods: + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE; + virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE; + +protected: + // property members: + LineStyle mLineStyle; + QCPScatterStyle mScatterStyle; + int mScatterSkip; + QPointer mChannelFillGraph; + bool mAdaptiveSampling; + + // reimplemented virtual methods: + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE; + + // introduced virtual methods: + virtual void drawFill(QCPPainter *painter, QVector *lines) const; + virtual void drawScatterPlot(QCPPainter *painter, const QVector &scatters, const QCPScatterStyle &style) const; + virtual void drawLinePlot(QCPPainter *painter, const QVector &lines) const; + virtual void drawImpulsePlot(QCPPainter *painter, const QVector &lines) const; + + virtual void getOptimizedLineData(QVector *lineData, const QCPGraphDataContainer::const_iterator &begin, const QCPGraphDataContainer::const_iterator &end) const; + virtual void getOptimizedScatterData(QVector *scatterData, QCPGraphDataContainer::const_iterator begin, QCPGraphDataContainer::const_iterator end) const; + + // non-virtual methods: + void getVisibleDataBounds(QCPGraphDataContainer::const_iterator &begin, QCPGraphDataContainer::const_iterator &end, const QCPDataRange &rangeRestriction) const; + void getLines(QVector *lines, const QCPDataRange &dataRange) const; + void getScatters(QVector *scatters, const QCPDataRange &dataRange) const; + QVector dataToLines(const QVector &data) const; + QVector dataToStepLeftLines(const QVector &data) const; + QVector dataToStepRightLines(const QVector &data) const; + QVector dataToStepCenterLines(const QVector &data) const; + QVector dataToImpulseLines(const QVector &data) const; + QVector getNonNanSegments(const QVector *lineData, Qt::Orientation keyOrientation) const; + QVector > getOverlappingSegments(QVector thisSegments, const QVector *thisData, QVector otherSegments, const QVector *otherData) const; + bool segmentsIntersect(double aLower, double aUpper, double bLower, double bUpper, int &bPrecedence) const; + QPointF getFillBasePoint(QPointF matchingDataPoint) const; + const QPolygonF getFillPolygon(const QVector *lineData, QCPDataRange segment) const; + const QPolygonF getChannelFillPolygon(const QVector *thisData, QCPDataRange thisSegment, const QVector *otherData, QCPDataRange otherSegment) const; + int findIndexBelowX(const QVector *data, double x) const; + int findIndexAboveX(const QVector *data, double x) const; + int findIndexBelowY(const QVector *data, double y) const; + int findIndexAboveY(const QVector *data, double y) const; + double pointDistance(const QPointF &pixelPoint, QCPGraphDataContainer::const_iterator &closestData) const; + + friend class QCustomPlot; + friend class QCPLegend; +}; +Q_DECLARE_METATYPE(QCPGraph::LineStyle) + +/* end of 'src/plottables/plottable-graph.h' */ + + +/* including file 'src/plottables/plottable-curve.h' */ +/* modified 2022-11-06T12:45:56, size 7434 */ + +class QCP_LIB_DECL QCPCurveData +{ +public: + QCPCurveData(); + QCPCurveData(double t, double key, double value); + + inline double sortKey() const { return t; } + inline static QCPCurveData fromSortKey(double sortKey) { return QCPCurveData(sortKey, 0, 0); } + inline static bool sortKeyIsMainKey() { return false; } + + inline double mainKey() const { return key; } + inline double mainValue() const { return value; } + + inline QCPRange valueRange() const { return QCPRange(value, value); } + + double t, key, value; +}; +Q_DECLARE_TYPEINFO(QCPCurveData, Q_PRIMITIVE_TYPE); + + +/*! \typedef QCPCurveDataContainer + + Container for storing \ref QCPCurveData points. The data is stored sorted by \a t, so the \a + sortKey() (returning \a t) is different from \a mainKey() (returning \a key). + + This template instantiation is the container in which QCPCurve holds its data. For details about + the generic container, see the documentation of the class template \ref QCPDataContainer. + + \see QCPCurveData, QCPCurve::setData +*/ +typedef QCPDataContainer QCPCurveDataContainer; + +class QCP_LIB_DECL QCPCurve : public QCPAbstractPlottable1D +{ + Q_OBJECT + /// \cond INCLUDE_QPROPERTIES + Q_PROPERTY(QCPScatterStyle scatterStyle READ scatterStyle WRITE setScatterStyle) + Q_PROPERTY(int scatterSkip READ scatterSkip WRITE setScatterSkip) + Q_PROPERTY(LineStyle lineStyle READ lineStyle WRITE setLineStyle) + /// \endcond +public: + /*! + Defines how the curve's line is represented visually in the plot. The line is drawn with the + current pen of the curve (\ref setPen). + \see setLineStyle + */ + enum LineStyle { lsNone ///< No line is drawn between data points (e.g. only scatters) + ,lsLine ///< Data points are connected with a straight line + }; + Q_ENUMS(LineStyle) + + explicit QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis); + virtual ~QCPCurve() Q_DECL_OVERRIDE; + + // getters: + QSharedPointer data() const { return mDataContainer; } + QCPScatterStyle scatterStyle() const { return mScatterStyle; } + int scatterSkip() const { return mScatterSkip; } + LineStyle lineStyle() const { return mLineStyle; } + + // setters: + void setData(QSharedPointer data); + void setData(const QVector &t, const QVector &keys, const QVector &values, bool alreadySorted=false); + void setData(const QVector &keys, const QVector &values); + void setScatterStyle(const QCPScatterStyle &style); + void setScatterSkip(int skip); + void setLineStyle(LineStyle style); + + // non-property methods: + void addData(const QVector &t, const QVector &keys, const QVector &values, bool alreadySorted=false); + void addData(const QVector &keys, const QVector &values); + void addData(double t, double key, double value); + void addData(double key, double value); + + // reimplemented virtual methods: + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE; + virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE; + +protected: + // property members: + QCPScatterStyle mScatterStyle; + int mScatterSkip; + LineStyle mLineStyle; + + // reimplemented virtual methods: + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE; + + // introduced virtual methods: + virtual void drawCurveLine(QCPPainter *painter, const QVector &lines) const; + virtual void drawScatterPlot(QCPPainter *painter, const QVector &points, const QCPScatterStyle &style) const; + + // non-virtual methods: + void getCurveLines(QVector *lines, const QCPDataRange &dataRange, double penWidth) const; + void getScatters(QVector *scatters, const QCPDataRange &dataRange, double scatterWidth) const; + int getRegion(double key, double value, double keyMin, double valueMax, double keyMax, double valueMin) const; + QPointF getOptimizedPoint(int otherRegion, double otherKey, double otherValue, double key, double value, double keyMin, double valueMax, double keyMax, double valueMin) const; + QVector getOptimizedCornerPoints(int prevRegion, int currentRegion, double prevKey, double prevValue, double key, double value, double keyMin, double valueMax, double keyMax, double valueMin) const; + bool mayTraverse(int prevRegion, int currentRegion) const; + bool getTraverse(double prevKey, double prevValue, double key, double value, double keyMin, double valueMax, double keyMax, double valueMin, QPointF &crossA, QPointF &crossB) const; + void getTraverseCornerPoints(int prevRegion, int currentRegion, double keyMin, double valueMax, double keyMax, double valueMin, QVector &beforeTraverse, QVector &afterTraverse) const; + double pointDistance(const QPointF &pixelPoint, QCPCurveDataContainer::const_iterator &closestData) const; + + friend class QCustomPlot; + friend class QCPLegend; +}; +Q_DECLARE_METATYPE(QCPCurve::LineStyle) + +/* end of 'src/plottables/plottable-curve.h' */ + + +/* including file 'src/plottables/plottable-bars.h' */ +/* modified 2022-11-06T12:45:56, size 8955 */ + +class QCP_LIB_DECL QCPBarsGroup : public QObject +{ + Q_OBJECT + /// \cond INCLUDE_QPROPERTIES + Q_PROPERTY(SpacingType spacingType READ spacingType WRITE setSpacingType) + Q_PROPERTY(double spacing READ spacing WRITE setSpacing) + /// \endcond +public: + /*! + Defines the ways the spacing between bars in the group can be specified. Thus it defines what + the number passed to \ref setSpacing actually means. + + \see setSpacingType, setSpacing + */ + enum SpacingType { stAbsolute ///< Bar spacing is in absolute pixels + ,stAxisRectRatio ///< Bar spacing is given by a fraction of the axis rect size + ,stPlotCoords ///< Bar spacing is in key coordinates and thus scales with the key axis range + }; + Q_ENUMS(SpacingType) + + explicit QCPBarsGroup(QCustomPlot *parentPlot); + virtual ~QCPBarsGroup(); + + // getters: + SpacingType spacingType() const { return mSpacingType; } + double spacing() const { return mSpacing; } + + // setters: + void setSpacingType(SpacingType spacingType); + void setSpacing(double spacing); + + // non-virtual methods: + QList bars() const { return mBars; } + QCPBars* bars(int index) const; + int size() const { return mBars.size(); } + bool isEmpty() const { return mBars.isEmpty(); } + void clear(); + bool contains(QCPBars *bars) const { return mBars.contains(bars); } + void append(QCPBars *bars); + void insert(int i, QCPBars *bars); + void remove(QCPBars *bars); + +protected: + // non-property members: + QCustomPlot *mParentPlot; + SpacingType mSpacingType; + double mSpacing; + QList mBars; + + // non-virtual methods: + void registerBars(QCPBars *bars); + void unregisterBars(QCPBars *bars); + + // virtual methods: + double keyPixelOffset(const QCPBars *bars, double keyCoord); + double getPixelSpacing(const QCPBars *bars, double keyCoord); + +private: + Q_DISABLE_COPY(QCPBarsGroup) + + friend class QCPBars; +}; +Q_DECLARE_METATYPE(QCPBarsGroup::SpacingType) + + +class QCP_LIB_DECL QCPBarsData +{ +public: + QCPBarsData(); + QCPBarsData(double key, double value); + + inline double sortKey() const { return key; } + inline static QCPBarsData fromSortKey(double sortKey) { return QCPBarsData(sortKey, 0); } + inline static bool sortKeyIsMainKey() { return true; } + + inline double mainKey() const { return key; } + inline double mainValue() const { return value; } + + inline QCPRange valueRange() const { return QCPRange(value, value); } // note that bar base value isn't held in each QCPBarsData and thus can't/shouldn't be returned here + + double key, value; +}; +Q_DECLARE_TYPEINFO(QCPBarsData, Q_PRIMITIVE_TYPE); + + +/*! \typedef QCPBarsDataContainer + + Container for storing \ref QCPBarsData points. The data is stored sorted by \a key. + + This template instantiation is the container in which QCPBars holds its data. For details about + the generic container, see the documentation of the class template \ref QCPDataContainer. + + \see QCPBarsData, QCPBars::setData +*/ +typedef QCPDataContainer QCPBarsDataContainer; + +class QCP_LIB_DECL QCPBars : public QCPAbstractPlottable1D +{ + Q_OBJECT + /// \cond INCLUDE_QPROPERTIES + Q_PROPERTY(double width READ width WRITE setWidth) + Q_PROPERTY(WidthType widthType READ widthType WRITE setWidthType) + Q_PROPERTY(QCPBarsGroup* barsGroup READ barsGroup WRITE setBarsGroup) + Q_PROPERTY(double baseValue READ baseValue WRITE setBaseValue) + Q_PROPERTY(double stackingGap READ stackingGap WRITE setStackingGap) + Q_PROPERTY(QCPBars* barBelow READ barBelow) + Q_PROPERTY(QCPBars* barAbove READ barAbove) + /// \endcond +public: + /*! + Defines the ways the width of the bar can be specified. Thus it defines what the number passed + to \ref setWidth actually means. + + \see setWidthType, setWidth + */ + enum WidthType { wtAbsolute ///< Bar width is in absolute pixels + ,wtAxisRectRatio ///< Bar width is given by a fraction of the axis rect size + ,wtPlotCoords ///< Bar width is in key coordinates and thus scales with the key axis range + }; + Q_ENUMS(WidthType) + + explicit QCPBars(QCPAxis *keyAxis, QCPAxis *valueAxis); + virtual ~QCPBars() Q_DECL_OVERRIDE; // getters: - QPen borderPen() const { return mBorderPen; } - QBrush brush() const { return mBrush; } - QFont font() const { return mFont; } - QColor textColor() const { return mTextColor; } - QSize iconSize() const { return mIconSize; } - int iconTextPadding() const { return mIconTextPadding; } - QPen iconBorderPen() const { return mIconBorderPen; } - SelectableParts selectableParts() const { return mSelectableParts; } - SelectableParts selectedParts() const; - QPen selectedBorderPen() const { return mSelectedBorderPen; } - QPen selectedIconBorderPen() const { return mSelectedIconBorderPen; } - QBrush selectedBrush() const { return mSelectedBrush; } - QFont selectedFont() const { return mSelectedFont; } - QColor selectedTextColor() const { return mSelectedTextColor; } + double width() const { return mWidth; } + WidthType widthType() const { return mWidthType; } + QCPBarsGroup *barsGroup() const { return mBarsGroup; } + double baseValue() const { return mBaseValue; } + double stackingGap() const { return mStackingGap; } + QCPBars *barBelow() const { return mBarBelow.data(); } + QCPBars *barAbove() const { return mBarAbove.data(); } + QSharedPointer data() const { return mDataContainer; } // setters: - void setBorderPen(const QPen &pen); - void setBrush(const QBrush &brush); - void setFont(const QFont &font); - void setTextColor(const QColor &color); - void setIconSize(const QSize &size); - void setIconSize(int width, int height); - void setIconTextPadding(int padding); - void setIconBorderPen(const QPen &pen); - Q_SLOT void setSelectableParts(const SelectableParts &selectableParts); - Q_SLOT void setSelectedParts(const SelectableParts &selectedParts); - void setSelectedBorderPen(const QPen &pen); - void setSelectedIconBorderPen(const QPen &pen); - void setSelectedBrush(const QBrush &brush); - void setSelectedFont(const QFont &font); - void setSelectedTextColor(const QColor &color); - - // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + void setData(QSharedPointer data); + void setData(const QVector &keys, const QVector &values, bool alreadySorted=false); + void setWidth(double width); + void setWidthType(WidthType widthType); + void setBarsGroup(QCPBarsGroup *barsGroup); + void setBaseValue(double baseValue); + void setStackingGap(double pixels); - // non-virtual methods: - QCPAbstractLegendItem *item(int index) const; - QCPPlottableLegendItem *itemWithPlottable(const QCPAbstractPlottable *plottable) const; - int itemCount() const; - bool hasItem(QCPAbstractLegendItem *item) const; - bool hasItemWithPlottable(const QCPAbstractPlottable *plottable) const; - bool addItem(QCPAbstractLegendItem *item); - bool removeItem(int index); - bool removeItem(QCPAbstractLegendItem *item); - void clearItems(); - QList selectedItems() const; + // non-property methods: + void addData(const QVector &keys, const QVector &values, bool alreadySorted=false); + void addData(double key, double value); + void moveBelow(QCPBars *bars); + void moveAbove(QCPBars *bars); -signals: - void selectionChanged(QCPLegend::SelectableParts parts); - void selectableChanged(QCPLegend::SelectableParts parts); + // reimplemented virtual methods: + virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const Q_DECL_OVERRIDE; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE; + virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE; + virtual QPointF dataPixelPosition(int index) const Q_DECL_OVERRIDE; protected: // property members: - QPen mBorderPen, mIconBorderPen; - QBrush mBrush; - QFont mFont; - QColor mTextColor; - QSize mIconSize; - int mIconTextPadding; - SelectableParts mSelectedParts, mSelectableParts; - QPen mSelectedBorderPen, mSelectedIconBorderPen; - QBrush mSelectedBrush; - QFont mSelectedFont; - QColor mSelectedTextColor; + double mWidth; + WidthType mWidthType; + QCPBarsGroup *mBarsGroup; + double mBaseValue; + double mStackingGap; + QPointer mBarBelow, mBarAbove; // reimplemented virtual methods: - virtual void parentPlotInitialized(QCustomPlot *parentPlot); - virtual QCP::Interaction selectionCategory() const; - virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; - virtual void draw(QCPPainter *painter); - // events: - virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); - virtual void deselectEvent(bool *selectionStateChanged); + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE; // non-virtual methods: - QPen getBorderPen() const; - QBrush getBrush() const; - -private: - Q_DISABLE_COPY(QCPLegend) + void getVisibleDataBounds(QCPBarsDataContainer::const_iterator &begin, QCPBarsDataContainer::const_iterator &end) const; + QRectF getBarRect(double key, double value) const; + void getPixelWidth(double key, double &lower, double &upper) const; + double getStackedBaseValue(double key, bool positive) const; + static void connectBars(QCPBars* lower, QCPBars* upper); friend class QCustomPlot; - friend class QCPAbstractLegendItem; + friend class QCPLegend; + friend class QCPBarsGroup; }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QCPLegend::SelectableParts) -Q_DECLARE_METATYPE(QCPLegend::SelectablePart) +Q_DECLARE_METATYPE(QCPBars::WidthType) + +/* end of 'src/plottables/plottable-bars.h' */ + + +/* including file 'src/plottables/plottable-statisticalbox.h' */ +/* modified 2022-11-06T12:45:56, size 7522 */ + +class QCP_LIB_DECL QCPStatisticalBoxData +{ +public: + QCPStatisticalBoxData(); + QCPStatisticalBoxData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum, const QVector& outliers=QVector()); + + inline double sortKey() const { return key; } + inline static QCPStatisticalBoxData fromSortKey(double sortKey) { return QCPStatisticalBoxData(sortKey, 0, 0, 0, 0, 0); } + inline static bool sortKeyIsMainKey() { return true; } + + inline double mainKey() const { return key; } + inline double mainValue() const { return median; } + + inline QCPRange valueRange() const + { + QCPRange result(minimum, maximum); + for (QVector::const_iterator it = outliers.constBegin(); it != outliers.constEnd(); ++it) + result.expand(*it); + return result; + } + + double key, minimum, lowerQuartile, median, upperQuartile, maximum; + QVector outliers; +}; +Q_DECLARE_TYPEINFO(QCPStatisticalBoxData, Q_MOVABLE_TYPE); + +/*! \typedef QCPStatisticalBoxDataContainer + + Container for storing \ref QCPStatisticalBoxData points. The data is stored sorted by \a key. + + This template instantiation is the container in which QCPStatisticalBox holds its data. For + details about the generic container, see the documentation of the class template \ref + QCPDataContainer. + + \see QCPStatisticalBoxData, QCPStatisticalBox::setData +*/ +typedef QCPDataContainer QCPStatisticalBoxDataContainer; -class QCP_LIB_DECL QCPPlotTitle : public QCPLayoutElement +class QCP_LIB_DECL QCPStatisticalBox : public QCPAbstractPlottable1D { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QString text READ text WRITE setText) - Q_PROPERTY(QFont font READ font WRITE setFont) - Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor) - Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) - Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE setSelectedTextColor) - Q_PROPERTY(bool selectable READ selectable WRITE setSelectable NOTIFY selectableChanged) - Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectionChanged) + Q_PROPERTY(double width READ width WRITE setWidth) + Q_PROPERTY(double whiskerWidth READ whiskerWidth WRITE setWhiskerWidth) + Q_PROPERTY(QPen whiskerPen READ whiskerPen WRITE setWhiskerPen) + Q_PROPERTY(QPen whiskerBarPen READ whiskerBarPen WRITE setWhiskerBarPen) + Q_PROPERTY(bool whiskerAntialiased READ whiskerAntialiased WRITE setWhiskerAntialiased) + Q_PROPERTY(QPen medianPen READ medianPen WRITE setMedianPen) + Q_PROPERTY(QCPScatterStyle outlierStyle READ outlierStyle WRITE setOutlierStyle) /// \endcond public: - explicit QCPPlotTitle(QCustomPlot *parentPlot); - explicit QCPPlotTitle(QCustomPlot *parentPlot, const QString &text); + explicit QCPStatisticalBox(QCPAxis *keyAxis, QCPAxis *valueAxis); // getters: - QString text() const { return mText; } - QFont font() const { return mFont; } - QColor textColor() const { return mTextColor; } - QFont selectedFont() const { return mSelectedFont; } - QColor selectedTextColor() const { return mSelectedTextColor; } - bool selectable() const { return mSelectable; } - bool selected() const { return mSelected; } - + QSharedPointer data() const { return mDataContainer; } + double width() const { return mWidth; } + double whiskerWidth() const { return mWhiskerWidth; } + QPen whiskerPen() const { return mWhiskerPen; } + QPen whiskerBarPen() const { return mWhiskerBarPen; } + bool whiskerAntialiased() const { return mWhiskerAntialiased; } + QPen medianPen() const { return mMedianPen; } + QCPScatterStyle outlierStyle() const { return mOutlierStyle; } + // setters: - void setText(const QString &text); - void setFont(const QFont &font); - void setTextColor(const QColor &color); - void setSelectedFont(const QFont &font); - void setSelectedTextColor(const QColor &color); - Q_SLOT void setSelectable(bool selectable); - Q_SLOT void setSelected(bool selected); + void setData(QSharedPointer data); + void setData(const QVector &keys, const QVector &minimum, const QVector &lowerQuartile, const QVector &median, const QVector &upperQuartile, const QVector &maximum, bool alreadySorted=false); + void setWidth(double width); + void setWhiskerWidth(double width); + void setWhiskerPen(const QPen &pen); + void setWhiskerBarPen(const QPen &pen); + void setWhiskerAntialiased(bool enabled); + void setMedianPen(const QPen &pen); + void setOutlierStyle(const QCPScatterStyle &style); - // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + // non-property methods: + void addData(const QVector &keys, const QVector &minimum, const QVector &lowerQuartile, const QVector &median, const QVector &upperQuartile, const QVector &maximum, bool alreadySorted=false); + void addData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum, const QVector &outliers=QVector()); -signals: - void selectionChanged(bool selected); - void selectableChanged(bool selectable); + // reimplemented virtual methods: + virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const Q_DECL_OVERRIDE; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE; + virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE; protected: // property members: - QString mText; - QFont mFont; - QColor mTextColor; - QFont mSelectedFont; - QColor mSelectedTextColor; - QRect mTextBoundingRect; - bool mSelectable, mSelected; + double mWidth; + double mWhiskerWidth; + QPen mWhiskerPen, mWhiskerBarPen; + bool mWhiskerAntialiased; + QPen mMedianPen; + QCPScatterStyle mOutlierStyle; // reimplemented virtual methods: - virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; - virtual void draw(QCPPainter *painter); - virtual QSize minimumSizeHint() const; - virtual QSize maximumSizeHint() const; - // events: - virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); - virtual void deselectEvent(bool *selectionStateChanged); + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE; + + // introduced virtual methods: + virtual void drawStatisticalBox(QCPPainter *painter, QCPStatisticalBoxDataContainer::const_iterator it, const QCPScatterStyle &outlierStyle) const; // non-virtual methods: - QFont mainFont() const; - QColor mainTextColor() const; + void getVisibleDataBounds(QCPStatisticalBoxDataContainer::const_iterator &begin, QCPStatisticalBoxDataContainer::const_iterator &end) const; + QRectF getQuartileBox(QCPStatisticalBoxDataContainer::const_iterator it) const; + QVector getWhiskerBackboneLines(QCPStatisticalBoxDataContainer::const_iterator it) const; + QVector getWhiskerBarLines(QCPStatisticalBoxDataContainer::const_iterator it) const; + + friend class QCustomPlot; + friend class QCPLegend; +}; + +/* end of 'src/plottables/plottable-statisticalbox.h' */ + + +/* including file 'src/plottables/plottable-colormap.h' */ +/* modified 2022-11-06T12:45:56, size 7092 */ + +class QCP_LIB_DECL QCPColorMapData +{ +public: + QCPColorMapData(int keySize, int valueSize, const QCPRange &keyRange, const QCPRange &valueRange); + ~QCPColorMapData(); + QCPColorMapData(const QCPColorMapData &other); + QCPColorMapData &operator=(const QCPColorMapData &other); + + // getters: + int keySize() const { return mKeySize; } + int valueSize() const { return mValueSize; } + QCPRange keyRange() const { return mKeyRange; } + QCPRange valueRange() const { return mValueRange; } + QCPRange dataBounds() const { return mDataBounds; } + double data(double key, double value); + double cell(int keyIndex, int valueIndex); + unsigned char alpha(int keyIndex, int valueIndex); + + // setters: + void setSize(int keySize, int valueSize); + void setKeySize(int keySize); + void setValueSize(int valueSize); + void setRange(const QCPRange &keyRange, const QCPRange &valueRange); + void setKeyRange(const QCPRange &keyRange); + void setValueRange(const QCPRange &valueRange); + void setData(double key, double value, double z); + void setCell(int keyIndex, int valueIndex, double z); + void setAlpha(int keyIndex, int valueIndex, unsigned char alpha); + + // non-property methods: + void recalculateDataBounds(); + void clear(); + void clearAlpha(); + void fill(double z); + void fillAlpha(unsigned char alpha); + bool isEmpty() const { return mIsEmpty; } + void coordToCell(double key, double value, int *keyIndex, int *valueIndex) const; + void cellToCoord(int keyIndex, int valueIndex, double *key, double *value) const; -private: - Q_DISABLE_COPY(QCPPlotTitle) -}; - - -class QCPColorScaleAxisRectPrivate : public QCPAxisRect -{ - Q_OBJECT -public: - explicit QCPColorScaleAxisRectPrivate(QCPColorScale *parentColorScale); protected: - QCPColorScale *mParentColorScale; - QImage mGradientImage; - bool mGradientImageInvalidated; - // re-using some methods of QCPAxisRect to make them available to friend class QCPColorScale - using QCPAxisRect::calculateAutoMargin; - using QCPAxisRect::mousePressEvent; - using QCPAxisRect::mouseMoveEvent; - using QCPAxisRect::mouseReleaseEvent; - using QCPAxisRect::wheelEvent; - using QCPAxisRect::update; - virtual void draw(QCPPainter *painter); - void updateGradientImage(); - Q_SLOT void axisSelectionChanged(QCPAxis::SelectableParts selectedParts); - Q_SLOT void axisSelectableChanged(QCPAxis::SelectableParts selectableParts); - friend class QCPColorScale; + // property members: + int mKeySize, mValueSize; + QCPRange mKeyRange, mValueRange; + bool mIsEmpty; + + // non-property members: + double *mData; + unsigned char *mAlpha; + QCPRange mDataBounds; + bool mDataModified; + + bool createAlpha(bool initializeOpaque=true); + + friend class QCPColorMap; }; -class QCP_LIB_DECL QCPColorScale : public QCPLayoutElement +class QCP_LIB_DECL QCPColorMap : public QCPAbstractPlottable { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QCPAxis::AxisType type READ type WRITE setType) Q_PROPERTY(QCPRange dataRange READ dataRange WRITE setDataRange NOTIFY dataRangeChanged) Q_PROPERTY(QCPAxis::ScaleType dataScaleType READ dataScaleType WRITE setDataScaleType NOTIFY dataScaleTypeChanged) Q_PROPERTY(QCPColorGradient gradient READ gradient WRITE setGradient NOTIFY gradientChanged) - Q_PROPERTY(QString label READ label WRITE setLabel) - Q_PROPERTY(int barWidth READ barWidth WRITE setBarWidth) - Q_PROPERTY(bool rangeDrag READ rangeDrag WRITE setRangeDrag) - Q_PROPERTY(bool rangeZoom READ rangeZoom WRITE setRangeZoom) + Q_PROPERTY(bool interpolate READ interpolate WRITE setInterpolate) + Q_PROPERTY(bool tightBoundary READ tightBoundary WRITE setTightBoundary) + Q_PROPERTY(QCPColorScale* colorScale READ colorScale WRITE setColorScale) /// \endcond public: - explicit QCPColorScale(QCustomPlot *parentPlot); - virtual ~QCPColorScale(); + explicit QCPColorMap(QCPAxis *keyAxis, QCPAxis *valueAxis); + virtual ~QCPColorMap() Q_DECL_OVERRIDE; // getters: - QCPAxis *axis() const { return mColorAxis.data(); } - QCPAxis::AxisType type() const { return mType; } + QCPColorMapData *data() const { return mMapData; } QCPRange dataRange() const { return mDataRange; } QCPAxis::ScaleType dataScaleType() const { return mDataScaleType; } + bool interpolate() const { return mInterpolate; } + bool tightBoundary() const { return mTightBoundary; } QCPColorGradient gradient() const { return mGradient; } - QString label() const; - int barWidth () const { return mBarWidth; } - bool rangeDrag() const; - bool rangeZoom() const; + QCPColorScale *colorScale() const { return mColorScale.data(); } // setters: - void setType(QCPAxis::AxisType type); + void setData(QCPColorMapData *data, bool copy=false); Q_SLOT void setDataRange(const QCPRange &dataRange); Q_SLOT void setDataScaleType(QCPAxis::ScaleType scaleType); Q_SLOT void setGradient(const QCPColorGradient &gradient); - void setLabel(const QString &str); - void setBarWidth(int width); - void setRangeDrag(bool enabled); - void setRangeZoom(bool enabled); + void setInterpolate(bool enabled); + void setTightBoundary(bool enabled); + void setColorScale(QCPColorScale *colorScale); // non-property methods: - QList colorMaps() const; - void rescaleDataRange(bool onlyVisibleMaps); + void rescaleDataRange(bool recalculateDataBounds=false); + Q_SLOT void updateLegendIcon(Qt::TransformationMode transformMode=Qt::SmoothTransformation, const QSize &thumbSize=QSize(32, 18)); // reimplemented virtual methods: - virtual void update(UpdatePhase phase); + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE; + virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE; signals: - void dataRangeChanged(QCPRange newRange); + void dataRangeChanged(const QCPRange &newRange); void dataScaleTypeChanged(QCPAxis::ScaleType scaleType); - void gradientChanged(QCPColorGradient newGradient); - + void gradientChanged(const QCPColorGradient &newGradient); + protected: // property members: - QCPAxis::AxisType mType; QCPRange mDataRange; QCPAxis::ScaleType mDataScaleType; + QCPColorMapData *mMapData; QCPColorGradient mGradient; - int mBarWidth; + bool mInterpolate; + bool mTightBoundary; + QPointer mColorScale; // non-property members: - QPointer mAxisRect; - QPointer mColorAxis; + QImage mMapImage, mUndersampledMapImage; + QPixmap mLegendIcon; + bool mMapImageInvalidated; - // reimplemented virtual methods: - virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const; - // events: - virtual void mousePressEvent(QMouseEvent *event); - virtual void mouseMoveEvent(QMouseEvent *event); - virtual void mouseReleaseEvent(QMouseEvent *event); - virtual void wheelEvent(QWheelEvent *event); + // introduced virtual methods: + virtual void updateMapImage(); -private: - Q_DISABLE_COPY(QCPColorScale) + // reimplemented virtual methods: + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE; - friend class QCPColorScaleAxisRectPrivate; + friend class QCustomPlot; + friend class QCPLegend; }; +/* end of 'src/plottables/plottable-colormap.h' */ -/*! \file */ +/* including file 'src/plottables/plottable-financial.h' */ +/* modified 2022-11-06T12:45:56, size 8644 */ - -class QCP_LIB_DECL QCPData +class QCP_LIB_DECL QCPFinancialData { public: - QCPData(); - QCPData(double key, double value); - double key, value; - double keyErrorPlus, keyErrorMinus; - double valueErrorPlus, valueErrorMinus; + QCPFinancialData(); + QCPFinancialData(double key, double open, double high, double low, double close); + + inline double sortKey() const { return key; } + inline static QCPFinancialData fromSortKey(double sortKey) { return QCPFinancialData(sortKey, 0, 0, 0, 0); } + inline static bool sortKeyIsMainKey() { return true; } + + inline double mainKey() const { return key; } + inline double mainValue() const { return open; } + + inline QCPRange valueRange() const { return QCPRange(low, high); } // open and close must lie between low and high, so we don't need to check them + + double key, open, high, low, close; }; -Q_DECLARE_TYPEINFO(QCPData, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QCPFinancialData, Q_PRIMITIVE_TYPE); -/*! \typedef QCPDataMap - Container for storing \ref QCPData items in a sorted fashion. The key of the map - is the key member of the QCPData instance. + +/*! \typedef QCPFinancialDataContainer + + Container for storing \ref QCPFinancialData points. The data is stored sorted by \a key. - This is the container in which QCPGraph holds its data. - \see QCPData, QCPGraph::setData + This template instantiation is the container in which QCPFinancial holds its data. For details + about the generic container, see the documentation of the class template \ref QCPDataContainer. + + \see QCPFinancialData, QCPFinancial::setData */ -typedef QMap QCPDataMap; -typedef QMapIterator QCPDataMapIterator; -typedef QMutableMapIterator QCPDataMutableMapIterator; - +typedef QCPDataContainer QCPFinancialDataContainer; -class QCP_LIB_DECL QCPGraph : public QCPAbstractPlottable +class QCP_LIB_DECL QCPFinancial : public QCPAbstractPlottable1D { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(LineStyle lineStyle READ lineStyle WRITE setLineStyle) - Q_PROPERTY(QCPScatterStyle scatterStyle READ scatterStyle WRITE setScatterStyle) - Q_PROPERTY(ErrorType errorType READ errorType WRITE setErrorType) - Q_PROPERTY(QPen errorPen READ errorPen WRITE setErrorPen) - Q_PROPERTY(double errorBarSize READ errorBarSize WRITE setErrorBarSize) - Q_PROPERTY(bool errorBarSkipSymbol READ errorBarSkipSymbol WRITE setErrorBarSkipSymbol) - Q_PROPERTY(QCPGraph* channelFillGraph READ channelFillGraph WRITE setChannelFillGraph) - Q_PROPERTY(bool adaptiveSampling READ adaptiveSampling WRITE setAdaptiveSampling) + Q_PROPERTY(ChartStyle chartStyle READ chartStyle WRITE setChartStyle) + Q_PROPERTY(double width READ width WRITE setWidth) + Q_PROPERTY(WidthType widthType READ widthType WRITE setWidthType) + Q_PROPERTY(bool twoColored READ twoColored WRITE setTwoColored) + Q_PROPERTY(QBrush brushPositive READ brushPositive WRITE setBrushPositive) + Q_PROPERTY(QBrush brushNegative READ brushNegative WRITE setBrushNegative) + Q_PROPERTY(QPen penPositive READ penPositive WRITE setPenPositive) + Q_PROPERTY(QPen penNegative READ penNegative WRITE setPenNegative) /// \endcond public: /*! - Defines how the graph's line is represented visually in the plot. The line is drawn with the - current pen of the graph (\ref setPen). - \see setLineStyle + Defines the ways the width of the financial bar can be specified. Thus it defines what the + number passed to \ref setWidth actually means. + + \see setWidthType, setWidth */ - enum LineStyle { lsNone ///< data points are not connected with any lines (e.g. data only represented - ///< with symbols according to the scatter style, see \ref setScatterStyle) - ,lsLine ///< data points are connected by a straight line - ,lsStepLeft ///< line is drawn as steps where the step height is the value of the left data point - ,lsStepRight ///< line is drawn as steps where the step height is the value of the right data point - ,lsStepCenter ///< line is drawn as steps where the step is in between two data points - ,lsImpulse ///< each data point is represented by a line parallel to the value axis, which reaches from the data point to the zero-value-line + enum WidthType { wtAbsolute ///< width is in absolute pixels + ,wtAxisRectRatio ///< width is given by a fraction of the axis rect size + ,wtPlotCoords ///< width is in key coordinates and thus scales with the key axis range }; - Q_ENUMS(LineStyle) + Q_ENUMS(WidthType) + /*! - Defines what kind of error bars are drawn for each data point + Defines the possible representations of OHLC data in the plot. + + \see setChartStyle */ - enum ErrorType { etNone ///< No error bars are shown - ,etKey ///< Error bars for the key dimension of the data point are shown - ,etValue ///< Error bars for the value dimension of the data point are shown - ,etBoth ///< Error bars for both key and value dimensions of the data point are shown - }; - Q_ENUMS(ErrorType) + enum ChartStyle { csOhlc ///< Open-High-Low-Close bar representation + ,csCandlestick ///< Candlestick representation + }; + Q_ENUMS(ChartStyle) - explicit QCPGraph(QCPAxis *keyAxis, QCPAxis *valueAxis); - virtual ~QCPGraph(); + explicit QCPFinancial(QCPAxis *keyAxis, QCPAxis *valueAxis); + virtual ~QCPFinancial() Q_DECL_OVERRIDE; // getters: - QCPDataMap *data() const { return mData; } - LineStyle lineStyle() const { return mLineStyle; } - QCPScatterStyle scatterStyle() const { return mScatterStyle; } - ErrorType errorType() const { return mErrorType; } - QPen errorPen() const { return mErrorPen; } - double errorBarSize() const { return mErrorBarSize; } - bool errorBarSkipSymbol() const { return mErrorBarSkipSymbol; } - QCPGraph *channelFillGraph() const { return mChannelFillGraph.data(); } - bool adaptiveSampling() const { return mAdaptiveSampling; } + QSharedPointer data() const { return mDataContainer; } + ChartStyle chartStyle() const { return mChartStyle; } + double width() const { return mWidth; } + WidthType widthType() const { return mWidthType; } + bool twoColored() const { return mTwoColored; } + QBrush brushPositive() const { return mBrushPositive; } + QBrush brushNegative() const { return mBrushNegative; } + QPen penPositive() const { return mPenPositive; } + QPen penNegative() const { return mPenNegative; } // setters: - void setData(QCPDataMap *data, bool copy=false); - void setData(const QVector &key, const QVector &value); - void setDataKeyError(const QVector &key, const QVector &value, const QVector &keyError); - void setDataKeyError(const QVector &key, const QVector &value, const QVector &keyErrorMinus, const QVector &keyErrorPlus); - void setDataValueError(const QVector &key, const QVector &value, const QVector &valueError); - void setDataValueError(const QVector &key, const QVector &value, const QVector &valueErrorMinus, const QVector &valueErrorPlus); - void setDataBothError(const QVector &key, const QVector &value, const QVector &keyError, const QVector &valueError); - void setDataBothError(const QVector &key, const QVector &value, const QVector &keyErrorMinus, const QVector &keyErrorPlus, const QVector &valueErrorMinus, const QVector &valueErrorPlus); - void setLineStyle(LineStyle ls); - void setScatterStyle(const QCPScatterStyle &style); - void setErrorType(ErrorType errorType); - void setErrorPen(const QPen &pen); - void setErrorBarSize(double size); - void setErrorBarSkipSymbol(bool enabled); - void setChannelFillGraph(QCPGraph *targetGraph); - void setAdaptiveSampling(bool enabled); + void setData(QSharedPointer data); + void setData(const QVector &keys, const QVector &open, const QVector &high, const QVector &low, const QVector &close, bool alreadySorted=false); + void setChartStyle(ChartStyle style); + void setWidth(double width); + void setWidthType(WidthType widthType); + void setTwoColored(bool twoColored); + void setBrushPositive(const QBrush &brush); + void setBrushNegative(const QBrush &brush); + void setPenPositive(const QPen &pen); + void setPenNegative(const QPen &pen); // non-property methods: - void addData(const QCPDataMap &dataMap); - void addData(const QCPData &data); - void addData(double key, double value); - void addData(const QVector &keys, const QVector &values); - void removeDataBefore(double key); - void removeDataAfter(double key); - void removeData(double fromKey, double toKey); - void removeData(double key); + void addData(const QVector &keys, const QVector &open, const QVector &high, const QVector &low, const QVector &close, bool alreadySorted=false); + void addData(double key, double open, double high, double low, double close); // reimplemented virtual methods: - virtual void clearData(); - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; - using QCPAbstractPlottable::rescaleAxes; - using QCPAbstractPlottable::rescaleKeyAxis; - using QCPAbstractPlottable::rescaleValueAxis; - void rescaleAxes(bool onlyEnlarge, bool includeErrorBars) const; // overloads base class interface - void rescaleKeyAxis(bool onlyEnlarge, bool includeErrorBars) const; // overloads base class interface - void rescaleValueAxis(bool onlyEnlarge, bool includeErrorBars) const; // overloads base class interface + virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const Q_DECL_OVERRIDE; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE; + virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE; + + // static methods: + static QCPFinancialDataContainer timeSeriesToOhlc(const QVector &time, const QVector &value, double timeBinSize, double timeBinOffset = 0); protected: // property members: - QCPDataMap *mData; - QPen mErrorPen; - LineStyle mLineStyle; - QCPScatterStyle mScatterStyle; - ErrorType mErrorType; - double mErrorBarSize; - bool mErrorBarSkipSymbol; - QPointer mChannelFillGraph; - bool mAdaptiveSampling; + ChartStyle mChartStyle; + double mWidth; + WidthType mWidthType; + bool mTwoColored; + QBrush mBrushPositive, mBrushNegative; + QPen mPenPositive, mPenNegative; // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); - virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const; - virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; - virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; - virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface - virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain, bool includeErrors) const; // overloads base class interface - - // introduced virtual methods: - virtual void drawFill(QCPPainter *painter, QVector *lineData) const; - virtual void drawScatterPlot(QCPPainter *painter, QVector *scatterData) const; - virtual void drawLinePlot(QCPPainter *painter, QVector *lineData) const; - virtual void drawImpulsePlot(QCPPainter *painter, QVector *lineData) const; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE; // non-virtual methods: - void getPreparedData(QVector *lineData, QVector *scatterData) const; - void getPlotData(QVector *lineData, QVector *scatterData) const; - void getScatterPlotData(QVector *scatterData) const; - void getLinePlotData(QVector *linePixelData, QVector *scatterData) const; - void getStepLeftPlotData(QVector *linePixelData, QVector *scatterData) const; - void getStepRightPlotData(QVector *linePixelData, QVector *scatterData) const; - void getStepCenterPlotData(QVector *linePixelData, QVector *scatterData) const; - void getImpulsePlotData(QVector *linePixelData, QVector *scatterData) const; - void drawError(QCPPainter *painter, double x, double y, const QCPData &data) const; - void getVisibleDataBounds(QCPDataMap::const_iterator &lower, QCPDataMap::const_iterator &upper) const; - int countDataInBounds(const QCPDataMap::const_iterator &lower, const QCPDataMap::const_iterator &upper, int maxCount) const; - void addFillBasePoints(QVector *lineData) const; - void removeFillBasePoints(QVector *lineData) const; - QPointF lowerFillBasePoint(double lowerKey) const; - QPointF upperFillBasePoint(double upperKey) const; - const QPolygonF getChannelFillPolygon(const QVector *lineData) const; - int findIndexBelowX(const QVector *data, double x) const; - int findIndexAboveX(const QVector *data, double x) const; - int findIndexBelowY(const QVector *data, double y) const; - int findIndexAboveY(const QVector *data, double y) const; - double pointDistance(const QPointF &pixelPoint) const; + void drawOhlcPlot(QCPPainter *painter, const QCPFinancialDataContainer::const_iterator &begin, const QCPFinancialDataContainer::const_iterator &end, bool isSelected); + void drawCandlestickPlot(QCPPainter *painter, const QCPFinancialDataContainer::const_iterator &begin, const QCPFinancialDataContainer::const_iterator &end, bool isSelected); + double getPixelWidth(double key, double keyPixel) const; + double ohlcSelectTest(const QPointF &pos, const QCPFinancialDataContainer::const_iterator &begin, const QCPFinancialDataContainer::const_iterator &end, QCPFinancialDataContainer::const_iterator &closestDataPoint) const; + double candlestickSelectTest(const QPointF &pos, const QCPFinancialDataContainer::const_iterator &begin, const QCPFinancialDataContainer::const_iterator &end, QCPFinancialDataContainer::const_iterator &closestDataPoint) const; + void getVisibleDataBounds(QCPFinancialDataContainer::const_iterator &begin, QCPFinancialDataContainer::const_iterator &end) const; + QRectF selectionHitBox(QCPFinancialDataContainer::const_iterator it) const; friend class QCustomPlot; friend class QCPLegend; }; +Q_DECLARE_METATYPE(QCPFinancial::ChartStyle) +/* end of 'src/plottables/plottable-financial.h' */ -/*! \file */ - - - -class QCP_LIB_DECL QCPCurveData -{ -public: - QCPCurveData(); - QCPCurveData(double t, double key, double value); - double t, key, value; -}; -Q_DECLARE_TYPEINFO(QCPCurveData, Q_MOVABLE_TYPE); - -/*! \typedef QCPCurveDataMap - Container for storing \ref QCPCurveData items in a sorted fashion. The key of the map - is the t member of the QCPCurveData instance. - - This is the container in which QCPCurve holds its data. - \see QCPCurveData, QCPCurve::setData -*/ - -typedef QMap QCPCurveDataMap; -typedef QMapIterator QCPCurveDataMapIterator; -typedef QMutableMapIterator QCPCurveDataMutableMapIterator; +/* including file 'src/plottables/plottable-errorbar.h' */ +/* modified 2022-11-06T12:45:56, size 7749 */ -class QCP_LIB_DECL QCPCurve : public QCPAbstractPlottable -{ - Q_OBJECT - /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QCPScatterStyle scatterStyle READ scatterStyle WRITE setScatterStyle) - Q_PROPERTY(LineStyle lineStyle READ lineStyle WRITE setLineStyle) - /// \endcond -public: - /*! - Defines how the curve's line is represented visually in the plot. The line is drawn with the - current pen of the curve (\ref setPen). - \see setLineStyle - */ - enum LineStyle { lsNone ///< No line is drawn between data points (e.g. only scatters) - ,lsLine ///< Data points are connected with a straight line - }; - explicit QCPCurve(QCPAxis *keyAxis, QCPAxis *valueAxis); - virtual ~QCPCurve(); - - // getters: - QCPCurveDataMap *data() const { return mData; } - QCPScatterStyle scatterStyle() const { return mScatterStyle; } - LineStyle lineStyle() const { return mLineStyle; } - - // setters: - void setData(QCPCurveDataMap *data, bool copy=false); - void setData(const QVector &t, const QVector &key, const QVector &value); - void setData(const QVector &key, const QVector &value); - void setScatterStyle(const QCPScatterStyle &style); - void setLineStyle(LineStyle style); - - // non-property methods: - void addData(const QCPCurveDataMap &dataMap); - void addData(const QCPCurveData &data); - void addData(double t, double key, double value); - void addData(double key, double value); - void addData(const QVector &ts, const QVector &keys, const QVector &values); - void removeDataBefore(double t); - void removeDataAfter(double t); - void removeData(double fromt, double tot); - void removeData(double t); - - // reimplemented virtual methods: - virtual void clearData(); - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; - -protected: - // property members: - QCPCurveDataMap *mData; - QCPScatterStyle mScatterStyle; - LineStyle mLineStyle; - - // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); - virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const; - virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; - virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; - - // introduced virtual methods: - virtual void drawScatterPlot(QCPPainter *painter, const QVector *pointData) const; - - // non-virtual methods: - void getCurveData(QVector *lineData) const; - int getRegion(double x, double y, double rectLeft, double rectTop, double rectRight, double rectBottom) const; - QPointF getOptimizedPoint(int prevRegion, double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const; - QVector getOptimizedCornerPoints(int prevRegion, int currentRegion, double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom) const; - bool mayTraverse(int prevRegion, int currentRegion) const; - bool getTraverse(double prevKey, double prevValue, double key, double value, double rectLeft, double rectTop, double rectRight, double rectBottom, QPointF &crossA, QPointF &crossB) const; - void getTraverseCornerPoints(int prevRegion, int currentRegion, double rectLeft, double rectTop, double rectRight, double rectBottom, QVector &beforeTraverse, QVector &afterTraverse) const; - double pointDistance(const QPointF &pixelPoint) const; +class QCP_LIB_DECL QCPErrorBarsData +{ +public: + QCPErrorBarsData(); + explicit QCPErrorBarsData(double error); + QCPErrorBarsData(double errorMinus, double errorPlus); - friend class QCustomPlot; - friend class QCPLegend; + double errorMinus, errorPlus; }; +Q_DECLARE_TYPEINFO(QCPErrorBarsData, Q_PRIMITIVE_TYPE); -/*! \file */ +/*! \typedef QCPErrorBarsDataContainer + Container for storing \ref QCPErrorBarsData points. It is a typedef for QVector<\ref + QCPErrorBarsData>. + This is the container in which \ref QCPErrorBars holds its data. Unlike most other data + containers for plottables, it is not based on \ref QCPDataContainer. This is because the error + bars plottable is special in that it doesn't store its own key and value coordinate per error + bar. It adopts the key and value from the plottable to which the error bars shall be applied + (\ref QCPErrorBars::setDataPlottable). So the stored \ref QCPErrorBarsData doesn't need a + sortable key, but merely an index (as \c QVector provides), which maps one-to-one to the indices + of the other plottable's data. -class QCP_LIB_DECL QCPBarsGroup : public QObject + \see QCPErrorBarsData, QCPErrorBars::setData +*/ +typedef QVector QCPErrorBarsDataContainer; + +class QCP_LIB_DECL QCPErrorBars : public QCPAbstractPlottable, public QCPPlottableInterface1D { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(SpacingType spacingType READ spacingType WRITE setSpacingType) - Q_PROPERTY(double spacing READ spacing WRITE setSpacing) + Q_PROPERTY(QSharedPointer data READ data WRITE setData) + Q_PROPERTY(QCPAbstractPlottable* dataPlottable READ dataPlottable WRITE setDataPlottable) + Q_PROPERTY(ErrorType errorType READ errorType WRITE setErrorType) + Q_PROPERTY(double whiskerWidth READ whiskerWidth WRITE setWhiskerWidth) + Q_PROPERTY(double symbolGap READ symbolGap WRITE setSymbolGap) /// \endcond public: + /*! - Defines the ways the spacing between bars in the group can be specified. Thus it defines what - the number passed to \ref setSpacing actually means. - - \see setSpacingType, setSpacing + Defines in which orientation the error bars shall appear. If your data needs both error + dimensions, create two \ref QCPErrorBars with different \ref ErrorType. + + \see setErrorType */ - enum SpacingType { stAbsolute ///< Bar spacing is in absolute pixels - ,stAxisRectRatio ///< Bar spacing is given by a fraction of the axis rect size - ,stPlotCoords ///< Bar spacing is in key coordinates and thus scales with the key axis range - }; - QCPBarsGroup(QCustomPlot *parentPlot); - ~QCPBarsGroup(); + enum ErrorType { etKeyError ///< The errors are for the key dimension (bars appear parallel to the key axis) + ,etValueError ///< The errors are for the value dimension (bars appear parallel to the value axis) + }; + Q_ENUMS(ErrorType) + explicit QCPErrorBars(QCPAxis *keyAxis, QCPAxis *valueAxis); + virtual ~QCPErrorBars() Q_DECL_OVERRIDE; // getters: - SpacingType spacingType() const { return mSpacingType; } - double spacing() const { return mSpacing; } + QSharedPointer data() const { return mDataContainer; } + QCPAbstractPlottable *dataPlottable() const { return mDataPlottable.data(); } + ErrorType errorType() const { return mErrorType; } + double whiskerWidth() const { return mWhiskerWidth; } + double symbolGap() const { return mSymbolGap; } // setters: - void setSpacingType(SpacingType spacingType); - void setSpacing(double spacing); + void setData(QSharedPointer data); + void setData(const QVector &error); + void setData(const QVector &errorMinus, const QVector &errorPlus); + void setDataPlottable(QCPAbstractPlottable* plottable); + void setErrorType(ErrorType type); + void setWhiskerWidth(double pixels); + void setSymbolGap(double pixels); - // non-virtual methods: - QList bars() const { return mBars; } - QCPBars* bars(int index) const; - int size() const { return mBars.size(); } - bool isEmpty() const { return mBars.isEmpty(); } - void clear(); - bool contains(QCPBars *bars) const { return mBars.contains(bars); } - void append(QCPBars *bars); - void insert(int i, QCPBars *bars); - void remove(QCPBars *bars); + // non-property methods: + void addData(const QVector &error); + void addData(const QVector &errorMinus, const QVector &errorPlus); + void addData(double error); + void addData(double errorMinus, double errorPlus); + + // virtual methods of 1d plottable interface: + virtual int dataCount() const Q_DECL_OVERRIDE; + virtual double dataMainKey(int index) const Q_DECL_OVERRIDE; + virtual double dataSortKey(int index) const Q_DECL_OVERRIDE; + virtual double dataMainValue(int index) const Q_DECL_OVERRIDE; + virtual QCPRange dataValueRange(int index) const Q_DECL_OVERRIDE; + virtual QPointF dataPixelPosition(int index) const Q_DECL_OVERRIDE; + virtual bool sortKeyIsMainKey() const Q_DECL_OVERRIDE; + virtual QCPDataSelection selectTestRect(const QRectF &rect, bool onlySelectable) const Q_DECL_OVERRIDE; + virtual int findBegin(double sortKey, bool expandedRange=true) const Q_DECL_OVERRIDE; + virtual int findEnd(double sortKey, bool expandedRange=true) const Q_DECL_OVERRIDE; -protected: - // non-property members: - QCustomPlot *mParentPlot; - SpacingType mSpacingType; - double mSpacing; - QList mBars; + // reimplemented virtual methods: + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + virtual QCPPlottableInterface1D *interface1D() Q_DECL_OVERRIDE { return this; } - // non-virtual methods: - void registerBars(QCPBars *bars); - void unregisterBars(QCPBars *bars); +protected: + // property members: + QSharedPointer mDataContainer; + QPointer mDataPlottable; + ErrorType mErrorType; + double mWhiskerWidth; + double mSymbolGap; - // virtual methods: - double keyPixelOffset(const QCPBars *bars, double keyCoord); - double getPixelSpacing(const QCPBars *bars, double keyCoord); + // reimplemented virtual methods: + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const Q_DECL_OVERRIDE; + virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const Q_DECL_OVERRIDE; + virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const Q_DECL_OVERRIDE; -private: - Q_DISABLE_COPY(QCPBarsGroup) + // non-virtual methods: + void getErrorBarLines(QCPErrorBarsDataContainer::const_iterator it, QVector &backbones, QVector &whiskers) const; + void getVisibleDataBounds(QCPErrorBarsDataContainer::const_iterator &begin, QCPErrorBarsDataContainer::const_iterator &end, const QCPDataRange &rangeRestriction) const; + double pointDistance(const QPointF &pixelPoint, QCPErrorBarsDataContainer::const_iterator &closestData) const; + // helpers: + void getDataSegments(QList &selectedSegments, QList &unselectedSegments) const; + bool errorBarVisible(int index) const; + bool rectIntersectsLine(const QRectF &pixelRect, const QLineF &line) const; - friend class QCPBars; + friend class QCustomPlot; + friend class QCPLegend; }; +/* end of 'src/plottables/plottable-errorbar.h' */ -class QCP_LIB_DECL QCPBarData -{ -public: - QCPBarData(); - QCPBarData(double key, double value); - double key, value; -}; -Q_DECLARE_TYPEINFO(QCPBarData, Q_MOVABLE_TYPE); -/*! \typedef QCPBarDataMap - Container for storing \ref QCPBarData items in a sorted fashion. The key of the map - is the key member of the QCPBarData instance. - - This is the container in which QCPBars holds its data. - \see QCPBarData, QCPBars::setData -*/ -typedef QMap QCPBarDataMap; -typedef QMapIterator QCPBarDataMapIterator; -typedef QMutableMapIterator QCPBarDataMutableMapIterator; +/* including file 'src/items/item-straightline.h' */ +/* modified 2022-11-06T12:45:56, size 3137 */ - -class QCP_LIB_DECL QCPBars : public QCPAbstractPlottable +class QCP_LIB_DECL QCPItemStraightLine : public QCPAbstractItem { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(double width READ width WRITE setWidth) - Q_PROPERTY(WidthType widthType READ widthType WRITE setWidthType) - Q_PROPERTY(QCPBarsGroup* barsGroup READ barsGroup WRITE setBarsGroup) - Q_PROPERTY(double baseValue READ baseValue WRITE setBaseValue) - Q_PROPERTY(QCPBars* barBelow READ barBelow) - Q_PROPERTY(QCPBars* barAbove READ barAbove) + Q_PROPERTY(QPen pen READ pen WRITE setPen) + Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) /// \endcond public: - /*! - Defines the ways the width of the bar can be specified. Thus it defines what the number passed - to \ref setWidth actually means. - - \see setWidthType, setWidth - */ - enum WidthType { wtAbsolute ///< Bar width is in absolute pixels - ,wtAxisRectRatio ///< Bar width is given by a fraction of the axis rect size - ,wtPlotCoords ///< Bar width is in key coordinates and thus scales with the key axis range - }; - Q_ENUMS(WidthType) - - explicit QCPBars(QCPAxis *keyAxis, QCPAxis *valueAxis); - virtual ~QCPBars(); + explicit QCPItemStraightLine(QCustomPlot *parentPlot); + virtual ~QCPItemStraightLine() Q_DECL_OVERRIDE; // getters: - double width() const { return mWidth; } - WidthType widthType() const { return mWidthType; } - QCPBarsGroup *barsGroup() const { return mBarsGroup; } - double baseValue() const { return mBaseValue; } - QCPBars *barBelow() const { return mBarBelow.data(); } - QCPBars *barAbove() const { return mBarAbove.data(); } - QCPBarDataMap *data() const { return mData; } - - // setters: - void setWidth(double width); - void setWidthType(WidthType widthType); - void setBarsGroup(QCPBarsGroup *barsGroup); - void setBaseValue(double baseValue); - void setData(QCPBarDataMap *data, bool copy=false); - void setData(const QVector &key, const QVector &value); + QPen pen() const { return mPen; } + QPen selectedPen() const { return mSelectedPen; } - // non-property methods: - void moveBelow(QCPBars *bars); - void moveAbove(QCPBars *bars); - void addData(const QCPBarDataMap &dataMap); - void addData(const QCPBarData &data); - void addData(double key, double value); - void addData(const QVector &keys, const QVector &values); - void removeDataBefore(double key); - void removeDataAfter(double key); - void removeData(double fromKey, double toKey); - void removeData(double key); + // setters; + void setPen(const QPen &pen); + void setSelectedPen(const QPen &pen); // reimplemented virtual methods: - virtual void clearData(); - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + + QCPItemPosition * const point1; + QCPItemPosition * const point2; protected: // property members: - QCPBarDataMap *mData; - double mWidth; - WidthType mWidthType; - QCPBarsGroup *mBarsGroup; - double mBaseValue; - QPointer mBarBelow, mBarAbove; + QPen mPen, mSelectedPen; // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); - virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const; - virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; - virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; // non-virtual methods: - void getVisibleDataBounds(QCPBarDataMap::const_iterator &lower, QCPBarDataMap::const_iterator &upperEnd) const; - QPolygonF getBarPolygon(double key, double value) const; - void getPixelWidth(double key, double &lower, double &upper) const; - double getStackedBaseValue(double key, bool positive) const; - static void connectBars(QCPBars* lower, QCPBars* upper); - - friend class QCustomPlot; - friend class QCPLegend; - friend class QCPBarsGroup; + QLineF getRectClippedStraightLine(const QCPVector2D &base, const QCPVector2D &vec, const QRect &rect) const; + QPen mainPen() const; }; - -/*! \file */ +/* end of 'src/items/item-straightline.h' */ +/* including file 'src/items/item-line.h' */ +/* modified 2022-11-06T12:45:56, size 3429 */ -class QCP_LIB_DECL QCPStatisticalBox : public QCPAbstractPlottable +class QCP_LIB_DECL QCPItemLine : public QCPAbstractItem { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(double key READ key WRITE setKey) - Q_PROPERTY(double minimum READ minimum WRITE setMinimum) - Q_PROPERTY(double lowerQuartile READ lowerQuartile WRITE setLowerQuartile) - Q_PROPERTY(double median READ median WRITE setMedian) - Q_PROPERTY(double upperQuartile READ upperQuartile WRITE setUpperQuartile) - Q_PROPERTY(double maximum READ maximum WRITE setMaximum) - Q_PROPERTY(QVector outliers READ outliers WRITE setOutliers) - Q_PROPERTY(double width READ width WRITE setWidth) - Q_PROPERTY(double whiskerWidth READ whiskerWidth WRITE setWhiskerWidth) - Q_PROPERTY(QPen whiskerPen READ whiskerPen WRITE setWhiskerPen) - Q_PROPERTY(QPen whiskerBarPen READ whiskerBarPen WRITE setWhiskerBarPen) - Q_PROPERTY(QPen medianPen READ medianPen WRITE setMedianPen) - Q_PROPERTY(QCPScatterStyle outlierStyle READ outlierStyle WRITE setOutlierStyle) + Q_PROPERTY(QPen pen READ pen WRITE setPen) + Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) + Q_PROPERTY(QCPLineEnding head READ head WRITE setHead) + Q_PROPERTY(QCPLineEnding tail READ tail WRITE setTail) /// \endcond public: - explicit QCPStatisticalBox(QCPAxis *keyAxis, QCPAxis *valueAxis); + explicit QCPItemLine(QCustomPlot *parentPlot); + virtual ~QCPItemLine() Q_DECL_OVERRIDE; // getters: - double key() const { return mKey; } - double minimum() const { return mMinimum; } - double lowerQuartile() const { return mLowerQuartile; } - double median() const { return mMedian; } - double upperQuartile() const { return mUpperQuartile; } - double maximum() const { return mMaximum; } - QVector outliers() const { return mOutliers; } - double width() const { return mWidth; } - double whiskerWidth() const { return mWhiskerWidth; } - QPen whiskerPen() const { return mWhiskerPen; } - QPen whiskerBarPen() const { return mWhiskerBarPen; } - QPen medianPen() const { return mMedianPen; } - QCPScatterStyle outlierStyle() const { return mOutlierStyle; } - - // setters: - void setKey(double key); - void setMinimum(double value); - void setLowerQuartile(double value); - void setMedian(double value); - void setUpperQuartile(double value); - void setMaximum(double value); - void setOutliers(const QVector &values); - void setData(double key, double minimum, double lowerQuartile, double median, double upperQuartile, double maximum); - void setWidth(double width); - void setWhiskerWidth(double width); - void setWhiskerPen(const QPen &pen); - void setWhiskerBarPen(const QPen &pen); - void setMedianPen(const QPen &pen); - void setOutlierStyle(const QCPScatterStyle &style); + QPen pen() const { return mPen; } + QPen selectedPen() const { return mSelectedPen; } + QCPLineEnding head() const { return mHead; } + QCPLineEnding tail() const { return mTail; } - // non-property methods: - virtual void clearData(); - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + // setters; + void setPen(const QPen &pen); + void setSelectedPen(const QPen &pen); + void setHead(const QCPLineEnding &head); + void setTail(const QCPLineEnding &tail); + + // reimplemented virtual methods: + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + + QCPItemPosition * const start; + QCPItemPosition * const end; protected: // property members: - QVector mOutliers; - double mKey, mMinimum, mLowerQuartile, mMedian, mUpperQuartile, mMaximum; - double mWidth; - double mWhiskerWidth; - QPen mWhiskerPen, mWhiskerBarPen, mMedianPen; - QCPScatterStyle mOutlierStyle; + QPen mPen, mSelectedPen; + QCPLineEnding mHead, mTail; // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); - virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const; - virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; - virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; - - // introduced virtual methods: - virtual void drawQuartileBox(QCPPainter *painter, QRectF *quartileBox=0) const; - virtual void drawMedian(QCPPainter *painter) const; - virtual void drawWhiskers(QCPPainter *painter) const; - virtual void drawOutliers(QCPPainter *painter) const; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; - friend class QCustomPlot; - friend class QCPLegend; + // non-virtual methods: + QLineF getRectClippedLine(const QCPVector2D &start, const QCPVector2D &end, const QRect &rect) const; + QPen mainPen() const; }; +/* end of 'src/items/item-line.h' */ -class QCP_LIB_DECL QCPColorMapData + +/* including file 'src/items/item-curve.h' */ +/* modified 2022-11-06T12:45:56, size 3401 */ + +class QCP_LIB_DECL QCPItemCurve : public QCPAbstractItem { + Q_OBJECT + /// \cond INCLUDE_QPROPERTIES + Q_PROPERTY(QPen pen READ pen WRITE setPen) + Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) + Q_PROPERTY(QCPLineEnding head READ head WRITE setHead) + Q_PROPERTY(QCPLineEnding tail READ tail WRITE setTail) + /// \endcond public: - QCPColorMapData(int keySize, int valueSize, const QCPRange &keyRange, const QCPRange &valueRange); - ~QCPColorMapData(); - QCPColorMapData(const QCPColorMapData &other); - QCPColorMapData &operator=(const QCPColorMapData &other); + explicit QCPItemCurve(QCustomPlot *parentPlot); + virtual ~QCPItemCurve() Q_DECL_OVERRIDE; // getters: - int keySize() const { return mKeySize; } - int valueSize() const { return mValueSize; } - QCPRange keyRange() const { return mKeyRange; } - QCPRange valueRange() const { return mValueRange; } - QCPRange dataBounds() const { return mDataBounds; } - double data(double key, double value); - double cell(int keyIndex, int valueIndex); + QPen pen() const { return mPen; } + QPen selectedPen() const { return mSelectedPen; } + QCPLineEnding head() const { return mHead; } + QCPLineEnding tail() const { return mTail; } - // setters: - void setSize(int keySize, int valueSize); - void setKeySize(int keySize); - void setValueSize(int valueSize); - void setRange(const QCPRange &keyRange, const QCPRange &valueRange); - void setKeyRange(const QCPRange &keyRange); - void setValueRange(const QCPRange &valueRange); - void setData(double key, double value, double z); - void setCell(int keyIndex, int valueIndex, double z); + // setters; + void setPen(const QPen &pen); + void setSelectedPen(const QPen &pen); + void setHead(const QCPLineEnding &head); + void setTail(const QCPLineEnding &tail); - // non-property methods: - void recalculateDataBounds(); - void clear(); - void fill(double z); - bool isEmpty() const { return mIsEmpty; } - void coordToCell(double key, double value, int *keyIndex, int *valueIndex) const; - void cellToCoord(int keyIndex, int valueIndex, double *key, double *value) const; + // reimplemented virtual methods: + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + + QCPItemPosition * const start; + QCPItemPosition * const startDir; + QCPItemPosition * const endDir; + QCPItemPosition * const end; protected: // property members: - int mKeySize, mValueSize; - QCPRange mKeyRange, mValueRange; - bool mIsEmpty; - // non-property members: - double *mData; - QCPRange mDataBounds; - bool mDataModified; + QPen mPen, mSelectedPen; + QCPLineEnding mHead, mTail; - friend class QCPColorMap; + // reimplemented virtual methods: + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + + // non-virtual methods: + QPen mainPen() const; }; +/* end of 'src/items/item-curve.h' */ -class QCP_LIB_DECL QCPColorMap : public QCPAbstractPlottable + +/* including file 'src/items/item-rect.h' */ +/* modified 2022-11-06T12:45:56, size 3710 */ + +class QCP_LIB_DECL QCPItemRect : public QCPAbstractItem { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QCPRange dataRange READ dataRange WRITE setDataRange NOTIFY dataRangeChanged) - Q_PROPERTY(QCPAxis::ScaleType dataScaleType READ dataScaleType WRITE setDataScaleType NOTIFY dataScaleTypeChanged) - Q_PROPERTY(QCPColorGradient gradient READ gradient WRITE setGradient NOTIFY gradientChanged) - Q_PROPERTY(bool interpolate READ interpolate WRITE setInterpolate) - Q_PROPERTY(bool tightBoundary READ tightBoundary WRITE setTightBoundary) - Q_PROPERTY(QCPColorScale* colorScale READ colorScale WRITE setColorScale) + Q_PROPERTY(QPen pen READ pen WRITE setPen) + Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) + Q_PROPERTY(QBrush brush READ brush WRITE setBrush) + Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) /// \endcond public: - explicit QCPColorMap(QCPAxis *keyAxis, QCPAxis *valueAxis); - virtual ~QCPColorMap(); + explicit QCPItemRect(QCustomPlot *parentPlot); + virtual ~QCPItemRect() Q_DECL_OVERRIDE; // getters: - QCPColorMapData *data() const { return mMapData; } - QCPRange dataRange() const { return mDataRange; } - QCPAxis::ScaleType dataScaleType() const { return mDataScaleType; } - bool interpolate() const { return mInterpolate; } - bool tightBoundary() const { return mTightBoundary; } - QCPColorGradient gradient() const { return mGradient; } - QCPColorScale *colorScale() const { return mColorScale.data(); } - - // setters: - void setData(QCPColorMapData *data, bool copy=false); - Q_SLOT void setDataRange(const QCPRange &dataRange); - Q_SLOT void setDataScaleType(QCPAxis::ScaleType scaleType); - Q_SLOT void setGradient(const QCPColorGradient &gradient); - void setInterpolate(bool enabled); - void setTightBoundary(bool enabled); - void setColorScale(QCPColorScale *colorScale); + QPen pen() const { return mPen; } + QPen selectedPen() const { return mSelectedPen; } + QBrush brush() const { return mBrush; } + QBrush selectedBrush() const { return mSelectedBrush; } - // non-property methods: - void rescaleDataRange(bool recalculateDataBounds=false); - Q_SLOT void updateLegendIcon(Qt::TransformationMode transformMode=Qt::SmoothTransformation, const QSize &thumbSize=QSize(32, 18)); + // setters; + void setPen(const QPen &pen); + void setSelectedPen(const QPen &pen); + void setBrush(const QBrush &brush); + void setSelectedBrush(const QBrush &brush); // reimplemented virtual methods: - virtual void clearData(); - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; -signals: - void dataRangeChanged(QCPRange newRange); - void dataScaleTypeChanged(QCPAxis::ScaleType scaleType); - void gradientChanged(QCPColorGradient newGradient); + QCPItemPosition * const topLeft; + QCPItemPosition * const bottomRight; + QCPItemAnchor * const top; + QCPItemAnchor * const topRight; + QCPItemAnchor * const right; + QCPItemAnchor * const bottom; + QCPItemAnchor * const bottomLeft; + QCPItemAnchor * const left; protected: - // property members: - QCPRange mDataRange; - QCPAxis::ScaleType mDataScaleType; - QCPColorMapData *mMapData; - QCPColorGradient mGradient; - bool mInterpolate; - bool mTightBoundary; - QPointer mColorScale; - // non-property members: - QImage mMapImage, mUndersampledMapImage; - QPixmap mLegendIcon; - bool mMapImageInvalidated; + enum AnchorIndex {aiTop, aiTopRight, aiRight, aiBottom, aiBottomLeft, aiLeft}; - // introduced virtual methods: - virtual void updateMapImage(); + // property members: + QPen mPen, mSelectedPen; + QBrush mBrush, mSelectedBrush; // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); - virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const; - virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; - virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual QPointF anchorPixelPosition(int anchorId) const Q_DECL_OVERRIDE; - friend class QCustomPlot; - friend class QCPLegend; + // non-virtual methods: + QPen mainPen() const; + QBrush mainBrush() const; }; - -/*! \file */ - +/* end of 'src/items/item-rect.h' */ -class QCP_LIB_DECL QCPFinancialData -{ -public: - QCPFinancialData(); - QCPFinancialData(double key, double open, double high, double low, double close); - double key, open, high, low, close; -}; -Q_DECLARE_TYPEINFO(QCPFinancialData, Q_MOVABLE_TYPE); - -/*! \typedef QCPFinancialDataMap - Container for storing \ref QCPFinancialData items in a sorted fashion. The key of the map - is the key member of the QCPFinancialData instance. - - This is the container in which QCPFinancial holds its data. - \see QCPFinancial, QCPFinancial::setData -*/ -typedef QMap QCPFinancialDataMap; -typedef QMapIterator QCPFinancialDataMapIterator; -typedef QMutableMapIterator QCPFinancialDataMutableMapIterator; +/* including file 'src/items/item-text.h' */ +/* modified 2022-11-06T12:45:56, size 5576 */ - -class QCP_LIB_DECL QCPFinancial : public QCPAbstractPlottable +class QCP_LIB_DECL QCPItemText : public QCPAbstractItem { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(ChartStyle chartStyle READ chartStyle WRITE setChartStyle) - Q_PROPERTY(double width READ width WRITE setWidth) - Q_PROPERTY(bool twoColored READ twoColored WRITE setTwoColored) - Q_PROPERTY(QBrush brushPositive READ brushPositive WRITE setBrushPositive) - Q_PROPERTY(QBrush brushNegative READ brushNegative WRITE setBrushNegative) - Q_PROPERTY(QPen penPositive READ penPositive WRITE setPenPositive) - Q_PROPERTY(QPen penNegative READ penNegative WRITE setPenNegative) + Q_PROPERTY(QColor color READ color WRITE setColor) + Q_PROPERTY(QColor selectedColor READ selectedColor WRITE setSelectedColor) + Q_PROPERTY(QPen pen READ pen WRITE setPen) + Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) + Q_PROPERTY(QBrush brush READ brush WRITE setBrush) + Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) + Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) + Q_PROPERTY(QString text READ text WRITE setText) + Q_PROPERTY(Qt::Alignment positionAlignment READ positionAlignment WRITE setPositionAlignment) + Q_PROPERTY(Qt::Alignment textAlignment READ textAlignment WRITE setTextAlignment) + Q_PROPERTY(double rotation READ rotation WRITE setRotation) + Q_PROPERTY(QMargins padding READ padding WRITE setPadding) /// \endcond public: - /*! - Defines the possible representations of OHLC data in the plot. - - \see setChartStyle - */ - enum ChartStyle { csOhlc ///< Open-High-Low-Close bar representation - ,csCandlestick ///< Candlestick representation - }; - Q_ENUMS(ChartStyle) - - explicit QCPFinancial(QCPAxis *keyAxis, QCPAxis *valueAxis); - virtual ~QCPFinancial(); + explicit QCPItemText(QCustomPlot *parentPlot); + virtual ~QCPItemText() Q_DECL_OVERRIDE; // getters: - QCPFinancialDataMap *data() const { return mData; } - ChartStyle chartStyle() const { return mChartStyle; } - double width() const { return mWidth; } - bool twoColored() const { return mTwoColored; } - QBrush brushPositive() const { return mBrushPositive; } - QBrush brushNegative() const { return mBrushNegative; } - QPen penPositive() const { return mPenPositive; } - QPen penNegative() const { return mPenNegative; } - - - // setters: - void setData(QCPFinancialDataMap *data, bool copy=false); - void setData(const QVector &key, const QVector &open, const QVector &high, const QVector &low, const QVector &close); - void setChartStyle(ChartStyle style); - void setWidth(double width); - void setTwoColored(bool twoColored); - void setBrushPositive(const QBrush &brush); - void setBrushNegative(const QBrush &brush); - void setPenPositive(const QPen &pen); - void setPenNegative(const QPen &pen); + QColor color() const { return mColor; } + QColor selectedColor() const { return mSelectedColor; } + QPen pen() const { return mPen; } + QPen selectedPen() const { return mSelectedPen; } + QBrush brush() const { return mBrush; } + QBrush selectedBrush() const { return mSelectedBrush; } + QFont font() const { return mFont; } + QFont selectedFont() const { return mSelectedFont; } + QString text() const { return mText; } + Qt::Alignment positionAlignment() const { return mPositionAlignment; } + Qt::Alignment textAlignment() const { return mTextAlignment; } + double rotation() const { return mRotation; } + QMargins padding() const { return mPadding; } - // non-property methods: - void addData(const QCPFinancialDataMap &dataMap); - void addData(const QCPFinancialData &data); - void addData(double key, double open, double high, double low, double close); - void addData(const QVector &key, const QVector &open, const QVector &high, const QVector &low, const QVector &close); - void removeDataBefore(double key); - void removeDataAfter(double key); - void removeData(double fromKey, double toKey); - void removeData(double key); + // setters; + void setColor(const QColor &color); + void setSelectedColor(const QColor &color); + void setPen(const QPen &pen); + void setSelectedPen(const QPen &pen); + void setBrush(const QBrush &brush); + void setSelectedBrush(const QBrush &brush); + void setFont(const QFont &font); + void setSelectedFont(const QFont &font); + void setText(const QString &text); + void setPositionAlignment(Qt::Alignment alignment); + void setTextAlignment(Qt::Alignment alignment); + void setRotation(double degrees); + void setPadding(const QMargins &padding); // reimplemented virtual methods: - virtual void clearData(); - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; - // static methods: - static QCPFinancialDataMap timeSeriesToOhlc(const QVector &time, const QVector &value, double timeBinSize, double timeBinOffset = 0); + QCPItemPosition * const position; + QCPItemAnchor * const topLeft; + QCPItemAnchor * const top; + QCPItemAnchor * const topRight; + QCPItemAnchor * const right; + QCPItemAnchor * const bottomRight; + QCPItemAnchor * const bottom; + QCPItemAnchor * const bottomLeft; + QCPItemAnchor * const left; protected: + enum AnchorIndex {aiTopLeft, aiTop, aiTopRight, aiRight, aiBottomRight, aiBottom, aiBottomLeft, aiLeft}; + // property members: - QCPFinancialDataMap *mData; - ChartStyle mChartStyle; - double mWidth; - bool mTwoColored; - QBrush mBrushPositive, mBrushNegative; - QPen mPenPositive, mPenNegative; + QColor mColor, mSelectedColor; + QPen mPen, mSelectedPen; + QBrush mBrush, mSelectedBrush; + QFont mFont, mSelectedFont; + QString mText; + Qt::Alignment mPositionAlignment; + Qt::Alignment mTextAlignment; + double mRotation; + QMargins mPadding; // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); - virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const; - virtual QCPRange getKeyRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; - virtual QCPRange getValueRange(bool &foundRange, SignDomain inSignDomain=sdBoth) const; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual QPointF anchorPixelPosition(int anchorId) const Q_DECL_OVERRIDE; // non-virtual methods: - void drawOhlcPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end); - void drawCandlestickPlot(QCPPainter *painter, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end); - double ohlcSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const; - double candlestickSelectTest(const QPointF &pos, const QCPFinancialDataMap::const_iterator &begin, const QCPFinancialDataMap::const_iterator &end) const; - void getVisibleDataBounds(QCPFinancialDataMap::const_iterator &lower, QCPFinancialDataMap::const_iterator &upper) const; - - friend class QCustomPlot; - friend class QCPLegend; + QPointF getTextDrawPoint(const QPointF &pos, const QRectF &rect, Qt::Alignment positionAlignment) const; + QFont mainFont() const; + QColor mainColor() const; + QPen mainPen() const; + QBrush mainBrush() const; }; +/* end of 'src/items/item-text.h' */ -class QCP_LIB_DECL QCPItemStraightLine : public QCPAbstractItem + +/* including file 'src/items/item-ellipse.h' */ +/* modified 2022-11-06T12:45:56, size 3890 */ + +class QCP_LIB_DECL QCPItemEllipse : public QCPAbstractItem { Q_OBJECT /// \cond INCLUDE_QPROPERTIES Q_PROPERTY(QPen pen READ pen WRITE setPen) Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) + Q_PROPERTY(QBrush brush READ brush WRITE setBrush) + Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) /// \endcond public: - QCPItemStraightLine(QCustomPlot *parentPlot); - virtual ~QCPItemStraightLine(); + explicit QCPItemEllipse(QCustomPlot *parentPlot); + virtual ~QCPItemEllipse() Q_DECL_OVERRIDE; // getters: QPen pen() const { return mPen; } QPen selectedPen() const { return mSelectedPen; } + QBrush brush() const { return mBrush; } + QBrush selectedBrush() const { return mSelectedBrush; } // setters; void setPen(const QPen &pen); void setSelectedPen(const QPen &pen); + void setBrush(const QBrush &brush); + void setSelectedBrush(const QBrush &brush); // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; - QCPItemPosition * const point1; - QCPItemPosition * const point2; + QCPItemPosition * const topLeft; + QCPItemPosition * const bottomRight; + QCPItemAnchor * const topLeftRim; + QCPItemAnchor * const top; + QCPItemAnchor * const topRightRim; + QCPItemAnchor * const right; + QCPItemAnchor * const bottomRightRim; + QCPItemAnchor * const bottom; + QCPItemAnchor * const bottomLeftRim; + QCPItemAnchor * const left; + QCPItemAnchor * const center; protected: + enum AnchorIndex {aiTopLeftRim, aiTop, aiTopRightRim, aiRight, aiBottomRightRim, aiBottom, aiBottomLeftRim, aiLeft, aiCenter}; + // property members: QPen mPen, mSelectedPen; + QBrush mBrush, mSelectedBrush; // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual QPointF anchorPixelPosition(int anchorId) const Q_DECL_OVERRIDE; // non-virtual methods: - double distToStraightLine(const QVector2D &point1, const QVector2D &vec, const QVector2D &point) const; - QLineF getRectClippedStraightLine(const QVector2D &point1, const QVector2D &vec, const QRect &rect) const; QPen mainPen() const; + QBrush mainBrush() const; }; +/* end of 'src/items/item-ellipse.h' */ -class QCP_LIB_DECL QCPItemLine : public QCPAbstractItem + +/* including file 'src/items/item-pixmap.h' */ +/* modified 2022-11-06T12:45:56, size 4407 */ + +class QCP_LIB_DECL QCPItemPixmap : public QCPAbstractItem { Q_OBJECT /// \cond INCLUDE_QPROPERTIES + Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap) + Q_PROPERTY(bool scaled READ scaled WRITE setScaled) + Q_PROPERTY(Qt::AspectRatioMode aspectRatioMode READ aspectRatioMode) + Q_PROPERTY(Qt::TransformationMode transformationMode READ transformationMode) Q_PROPERTY(QPen pen READ pen WRITE setPen) Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) - Q_PROPERTY(QCPLineEnding head READ head WRITE setHead) - Q_PROPERTY(QCPLineEnding tail READ tail WRITE setTail) /// \endcond public: - QCPItemLine(QCustomPlot *parentPlot); - virtual ~QCPItemLine(); + explicit QCPItemPixmap(QCustomPlot *parentPlot); + virtual ~QCPItemPixmap() Q_DECL_OVERRIDE; // getters: + QPixmap pixmap() const { return mPixmap; } + bool scaled() const { return mScaled; } + Qt::AspectRatioMode aspectRatioMode() const { return mAspectRatioMode; } + Qt::TransformationMode transformationMode() const { return mTransformationMode; } QPen pen() const { return mPen; } QPen selectedPen() const { return mSelectedPen; } - QCPLineEnding head() const { return mHead; } - QCPLineEnding tail() const { return mTail; } // setters; + void setPixmap(const QPixmap &pixmap); + void setScaled(bool scaled, Qt::AspectRatioMode aspectRatioMode=Qt::KeepAspectRatio, Qt::TransformationMode transformationMode=Qt::SmoothTransformation); void setPen(const QPen &pen); void setSelectedPen(const QPen &pen); - void setHead(const QCPLineEnding &head); - void setTail(const QCPLineEnding &tail); // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; - QCPItemPosition * const start; - QCPItemPosition * const end; + QCPItemPosition * const topLeft; + QCPItemPosition * const bottomRight; + QCPItemAnchor * const top; + QCPItemAnchor * const topRight; + QCPItemAnchor * const right; + QCPItemAnchor * const bottom; + QCPItemAnchor * const bottomLeft; + QCPItemAnchor * const left; protected: + enum AnchorIndex {aiTop, aiTopRight, aiRight, aiBottom, aiBottomLeft, aiLeft}; + // property members: + QPixmap mPixmap; + QPixmap mScaledPixmap; + bool mScaled; + bool mScaledPixmapInvalidated; + Qt::AspectRatioMode mAspectRatioMode; + Qt::TransformationMode mTransformationMode; QPen mPen, mSelectedPen; - QCPLineEnding mHead, mTail; // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual QPointF anchorPixelPosition(int anchorId) const Q_DECL_OVERRIDE; // non-virtual methods: - QLineF getRectClippedLine(const QVector2D &start, const QVector2D &end, const QRect &rect) const; + void updateScaledPixmap(QRect finalRect=QRect(), bool flipHorz=false, bool flipVert=false); + QRect getFinalRect(bool *flippedHorz=nullptr, bool *flippedVert=nullptr) const; QPen mainPen() const; }; +/* end of 'src/items/item-pixmap.h' */ -class QCP_LIB_DECL QCPItemCurve : public QCPAbstractItem + +/* including file 'src/items/item-tracer.h' */ +/* modified 2022-11-06T12:45:56, size 4811 */ + +class QCP_LIB_DECL QCPItemTracer : public QCPAbstractItem { Q_OBJECT /// \cond INCLUDE_QPROPERTIES Q_PROPERTY(QPen pen READ pen WRITE setPen) Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) - Q_PROPERTY(QCPLineEnding head READ head WRITE setHead) - Q_PROPERTY(QCPLineEnding tail READ tail WRITE setTail) + Q_PROPERTY(QBrush brush READ brush WRITE setBrush) + Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) + Q_PROPERTY(double size READ size WRITE setSize) + Q_PROPERTY(TracerStyle style READ style WRITE setStyle) + Q_PROPERTY(QCPGraph* graph READ graph WRITE setGraph) + Q_PROPERTY(double graphKey READ graphKey WRITE setGraphKey) + Q_PROPERTY(bool interpolating READ interpolating WRITE setInterpolating) /// \endcond public: - QCPItemCurve(QCustomPlot *parentPlot); - virtual ~QCPItemCurve(); - + /*! + The different visual appearances a tracer item can have. Some styles size may be controlled with \ref setSize. + + \see setStyle + */ + enum TracerStyle { tsNone ///< The tracer is not visible + ,tsPlus ///< A plus shaped crosshair with limited size + ,tsCrosshair ///< A plus shaped crosshair which spans the complete axis rect + ,tsCircle ///< A circle + ,tsSquare ///< A square + }; + Q_ENUMS(TracerStyle) + + explicit QCPItemTracer(QCustomPlot *parentPlot); + virtual ~QCPItemTracer() Q_DECL_OVERRIDE; + // getters: QPen pen() const { return mPen; } QPen selectedPen() const { return mSelectedPen; } - QCPLineEnding head() const { return mHead; } - QCPLineEnding tail() const { return mTail; } - + QBrush brush() const { return mBrush; } + QBrush selectedBrush() const { return mSelectedBrush; } + double size() const { return mSize; } + TracerStyle style() const { return mStyle; } + QCPGraph *graph() const { return mGraph; } + double graphKey() const { return mGraphKey; } + bool interpolating() const { return mInterpolating; } + // setters; void setPen(const QPen &pen); void setSelectedPen(const QPen &pen); - void setHead(const QCPLineEnding &head); - void setTail(const QCPLineEnding &tail); - + void setBrush(const QBrush &brush); + void setSelectedBrush(const QBrush &brush); + void setSize(double size); + void setStyle(TracerStyle style); + void setGraph(QCPGraph *graph); + void setGraphKey(double key); + void setInterpolating(bool enabled); + // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; - - QCPItemPosition * const start; - QCPItemPosition * const startDir; - QCPItemPosition * const endDir; - QCPItemPosition * const end; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; + // non-virtual methods: + void updatePosition(); + + QCPItemPosition * const position; + protected: // property members: QPen mPen, mSelectedPen; - QCPLineEnding mHead, mTail; - + QBrush mBrush, mSelectedBrush; + double mSize; + TracerStyle mStyle; + QCPGraph *mGraph; + double mGraphKey; + bool mInterpolating; + // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); - + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + // non-virtual methods: QPen mainPen() const; + QBrush mainBrush() const; }; +Q_DECLARE_METATYPE(QCPItemTracer::TracerStyle) +/* end of 'src/items/item-tracer.h' */ -class QCP_LIB_DECL QCPItemRect : public QCPAbstractItem + +/* including file 'src/items/item-bracket.h' */ +/* modified 2022-11-06T12:45:56, size 3991 */ + +class QCP_LIB_DECL QCPItemBracket : public QCPAbstractItem { Q_OBJECT /// \cond INCLUDE_QPROPERTIES Q_PROPERTY(QPen pen READ pen WRITE setPen) Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) - Q_PROPERTY(QBrush brush READ brush WRITE setBrush) - Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) + Q_PROPERTY(double length READ length WRITE setLength) + Q_PROPERTY(BracketStyle style READ style WRITE setStyle) /// \endcond public: - QCPItemRect(QCustomPlot *parentPlot); - virtual ~QCPItemRect(); + /*! + Defines the various visual shapes of the bracket item. The appearance can be further modified + by \ref setLength and \ref setPen. + + \see setStyle + */ + enum BracketStyle { bsSquare ///< A brace with angled edges + ,bsRound ///< A brace with round edges + ,bsCurly ///< A curly brace + ,bsCalligraphic ///< A curly brace with varying stroke width giving a calligraphic impression + }; + Q_ENUMS(BracketStyle) + + explicit QCPItemBracket(QCustomPlot *parentPlot); + virtual ~QCPItemBracket() Q_DECL_OVERRIDE; // getters: QPen pen() const { return mPen; } QPen selectedPen() const { return mSelectedPen; } - QBrush brush() const { return mBrush; } - QBrush selectedBrush() const { return mSelectedBrush; } + double length() const { return mLength; } + BracketStyle style() const { return mStyle; } // setters; void setPen(const QPen &pen); void setSelectedPen(const QPen &pen); - void setBrush(const QBrush &brush); - void setSelectedBrush(const QBrush &brush); + void setLength(double length); + void setStyle(BracketStyle style); // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=nullptr) const Q_DECL_OVERRIDE; - QCPItemPosition * const topLeft; - QCPItemPosition * const bottomRight; - QCPItemAnchor * const top; - QCPItemAnchor * const topRight; - QCPItemAnchor * const right; - QCPItemAnchor * const bottom; - QCPItemAnchor * const bottomLeft; - QCPItemAnchor * const left; + QCPItemPosition * const left; + QCPItemPosition * const right; + QCPItemAnchor * const center; protected: - enum AnchorIndex {aiTop, aiTopRight, aiRight, aiBottom, aiBottomLeft, aiLeft}; - // property members: + enum AnchorIndex {aiCenter}; QPen mPen, mSelectedPen; - QBrush mBrush, mSelectedBrush; + double mLength; + BracketStyle mStyle; // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); - virtual QPointF anchorPixelPoint(int anchorId) const; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual QPointF anchorPixelPosition(int anchorId) const Q_DECL_OVERRIDE; // non-virtual methods: QPen mainPen() const; - QBrush mainBrush() const; }; +Q_DECLARE_METATYPE(QCPItemBracket::BracketStyle) +/* end of 'src/items/item-bracket.h' */ -class QCP_LIB_DECL QCPItemText : public QCPAbstractItem + +/* including file 'src/polar/radialaxis.h' */ +/* modified 2022-11-06T12:45:56, size 12227 */ + + +class QCP_LIB_DECL QCPPolarAxisRadial : public QCPLayerable { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QColor color READ color WRITE setColor) - Q_PROPERTY(QColor selectedColor READ selectedColor WRITE setSelectedColor) - Q_PROPERTY(QPen pen READ pen WRITE setPen) - Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) - Q_PROPERTY(QBrush brush READ brush WRITE setBrush) - Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) - Q_PROPERTY(QFont font READ font WRITE setFont) - Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont) - Q_PROPERTY(QString text READ text WRITE setText) - Q_PROPERTY(Qt::Alignment positionAlignment READ positionAlignment WRITE setPositionAlignment) - Q_PROPERTY(Qt::Alignment textAlignment READ textAlignment WRITE setTextAlignment) - Q_PROPERTY(double rotation READ rotation WRITE setRotation) - Q_PROPERTY(QMargins padding READ padding WRITE setPadding) + /// \endcond public: - QCPItemText(QCustomPlot *parentPlot); - virtual ~QCPItemText(); + /*! + Defines the reference of the angle at which a radial axis is tilted (\ref setAngle). + */ + enum AngleReference { arAbsolute ///< The axis tilt is given in absolute degrees. The zero is to the right and positive angles are measured counter-clockwise. + ,arAngularAxis ///< The axis tilt is measured in the angular coordinate system given by the parent angular axis. + }; + Q_ENUMS(AngleReference) + /*! + Defines the scale of an axis. + \see setScaleType + */ + enum ScaleType { stLinear ///< Linear scaling + ,stLogarithmic ///< Logarithmic scaling with correspondingly transformed axis coordinates (possibly also \ref setTicker to a \ref QCPAxisTickerLog instance). + }; + Q_ENUMS(ScaleType) + /*! + Defines the selectable parts of an axis. + \see setSelectableParts, setSelectedParts + */ + enum SelectablePart { spNone = 0 ///< None of the selectable parts + ,spAxis = 0x001 ///< The axis backbone and tick marks + ,spTickLabels = 0x002 ///< Tick labels (numbers) of this axis (as a whole, not individually) + ,spAxisLabel = 0x004 ///< The axis label + }; + Q_ENUMS(SelectablePart) + Q_FLAGS(SelectableParts) + Q_DECLARE_FLAGS(SelectableParts, SelectablePart) + + enum LabelMode { lmUpright ///< + ,lmRotated ///< + }; + Q_ENUMS(LabelMode) + + explicit QCPPolarAxisRadial(QCPPolarAxisAngular *parent); + virtual ~QCPPolarAxisRadial(); // getters: - QColor color() const { return mColor; } - QColor selectedColor() const { return mSelectedColor; } - QPen pen() const { return mPen; } - QPen selectedPen() const { return mSelectedPen; } - QBrush brush() const { return mBrush; } - QBrush selectedBrush() const { return mSelectedBrush; } - QFont font() const { return mFont; } - QFont selectedFont() const { return mSelectedFont; } - QString text() const { return mText; } - Qt::Alignment positionAlignment() const { return mPositionAlignment; } - Qt::Alignment textAlignment() const { return mTextAlignment; } - double rotation() const { return mRotation; } - QMargins padding() const { return mPadding; } + bool rangeDrag() const { return mRangeDrag; } + bool rangeZoom() const { return mRangeZoom; } + double rangeZoomFactor() const { return mRangeZoomFactor; } - // setters; - void setColor(const QColor &color); - void setSelectedColor(const QColor &color); - void setPen(const QPen &pen); - void setSelectedPen(const QPen &pen); - void setBrush(const QBrush &brush); - void setSelectedBrush(const QBrush &brush); - void setFont(const QFont &font); - void setSelectedFont(const QFont &font); - void setText(const QString &text); - void setPositionAlignment(Qt::Alignment alignment); - void setTextAlignment(Qt::Alignment alignment); - void setRotation(double degrees); - void setPadding(const QMargins &padding); + QCPPolarAxisAngular *angularAxis() const { return mAngularAxis; } + ScaleType scaleType() const { return mScaleType; } + const QCPRange range() const { return mRange; } + bool rangeReversed() const { return mRangeReversed; } + double angle() const { return mAngle; } + AngleReference angleReference() const { return mAngleReference; } + QSharedPointer ticker() const { return mTicker; } + bool ticks() const { return mTicks; } + bool tickLabels() const { return mTickLabels; } + int tickLabelPadding() const { return mLabelPainter.padding(); } + QFont tickLabelFont() const { return mTickLabelFont; } + QColor tickLabelColor() const { return mTickLabelColor; } + double tickLabelRotation() const { return mLabelPainter.rotation(); } + LabelMode tickLabelMode() const; + QString numberFormat() const; + int numberPrecision() const { return mNumberPrecision; } + QVector tickVector() const { return mTickVector; } + QVector subTickVector() const { return mSubTickVector; } + QVector tickVectorLabels() const { return mTickVectorLabels; } + int tickLengthIn() const; + int tickLengthOut() const; + bool subTicks() const { return mSubTicks; } + int subTickLengthIn() const; + int subTickLengthOut() const; + QPen basePen() const { return mBasePen; } + QPen tickPen() const { return mTickPen; } + QPen subTickPen() const { return mSubTickPen; } + QFont labelFont() const { return mLabelFont; } + QColor labelColor() const { return mLabelColor; } + QString label() const { return mLabel; } + int labelPadding() const; + SelectableParts selectedParts() const { return mSelectedParts; } + SelectableParts selectableParts() const { return mSelectableParts; } + QFont selectedTickLabelFont() const { return mSelectedTickLabelFont; } + QFont selectedLabelFont() const { return mSelectedLabelFont; } + QColor selectedTickLabelColor() const { return mSelectedTickLabelColor; } + QColor selectedLabelColor() const { return mSelectedLabelColor; } + QPen selectedBasePen() const { return mSelectedBasePen; } + QPen selectedTickPen() const { return mSelectedTickPen; } + QPen selectedSubTickPen() const { return mSelectedSubTickPen; } + + // setters: + void setRangeDrag(bool enabled); + void setRangeZoom(bool enabled); + void setRangeZoomFactor(double factor); + + Q_SLOT void setScaleType(QCPPolarAxisRadial::ScaleType type); + Q_SLOT void setRange(const QCPRange &range); + void setRange(double lower, double upper); + void setRange(double position, double size, Qt::AlignmentFlag alignment); + void setRangeLower(double lower); + void setRangeUpper(double upper); + void setRangeReversed(bool reversed); + void setAngle(double degrees); + void setAngleReference(AngleReference reference); + void setTicker(QSharedPointer ticker); + void setTicks(bool show); + void setTickLabels(bool show); + void setTickLabelPadding(int padding); + void setTickLabelFont(const QFont &font); + void setTickLabelColor(const QColor &color); + void setTickLabelRotation(double degrees); + void setTickLabelMode(LabelMode mode); + void setNumberFormat(const QString &formatCode); + void setNumberPrecision(int precision); + void setTickLength(int inside, int outside=0); + void setTickLengthIn(int inside); + void setTickLengthOut(int outside); + void setSubTicks(bool show); + void setSubTickLength(int inside, int outside=0); + void setSubTickLengthIn(int inside); + void setSubTickLengthOut(int outside); + void setBasePen(const QPen &pen); + void setTickPen(const QPen &pen); + void setSubTickPen(const QPen &pen); + void setLabelFont(const QFont &font); + void setLabelColor(const QColor &color); + void setLabel(const QString &str); + void setLabelPadding(int padding); + void setSelectedTickLabelFont(const QFont &font); + void setSelectedLabelFont(const QFont &font); + void setSelectedTickLabelColor(const QColor &color); + void setSelectedLabelColor(const QColor &color); + void setSelectedBasePen(const QPen &pen); + void setSelectedTickPen(const QPen &pen); + void setSelectedSubTickPen(const QPen &pen); + Q_SLOT void setSelectableParts(const QCPPolarAxisRadial::SelectableParts &selectableParts); + Q_SLOT void setSelectedParts(const QCPPolarAxisRadial::SelectableParts &selectedParts); // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const Q_DECL_OVERRIDE; - QCPItemPosition * const position; - QCPItemAnchor * const topLeft; - QCPItemAnchor * const top; - QCPItemAnchor * const topRight; - QCPItemAnchor * const right; - QCPItemAnchor * const bottomRight; - QCPItemAnchor * const bottom; - QCPItemAnchor * const bottomLeft; - QCPItemAnchor * const left; + // non-property methods: + void moveRange(double diff); + void scaleRange(double factor); + void scaleRange(double factor, double center); + void rescale(bool onlyVisiblePlottables=false); + void pixelToCoord(QPointF pixelPos, double &angleCoord, double &radiusCoord) const; + QPointF coordToPixel(double angleCoord, double radiusCoord) const; + double coordToRadius(double coord) const; + double radiusToCoord(double radius) const; + SelectablePart getPartAt(const QPointF &pos) const; +signals: + void rangeChanged(const QCPRange &newRange); + void rangeChanged(const QCPRange &newRange, const QCPRange &oldRange); + void scaleTypeChanged(QCPPolarAxisRadial::ScaleType scaleType); + void selectionChanged(const QCPPolarAxisRadial::SelectableParts &parts); + void selectableChanged(const QCPPolarAxisRadial::SelectableParts &parts); + protected: - enum AnchorIndex {aiTopLeft, aiTop, aiTopRight, aiRight, aiBottomRight, aiBottom, aiBottomLeft, aiLeft}; - // property members: - QColor mColor, mSelectedColor; - QPen mPen, mSelectedPen; - QBrush mBrush, mSelectedBrush; - QFont mFont, mSelectedFont; - QString mText; - Qt::Alignment mPositionAlignment; - Qt::Alignment mTextAlignment; - double mRotation; - QMargins mPadding; + bool mRangeDrag; + bool mRangeZoom; + double mRangeZoomFactor; + + // axis base: + QCPPolarAxisAngular *mAngularAxis; + double mAngle; + AngleReference mAngleReference; + SelectableParts mSelectableParts, mSelectedParts; + QPen mBasePen, mSelectedBasePen; + // axis label: + int mLabelPadding; + QString mLabel; + QFont mLabelFont, mSelectedLabelFont; + QColor mLabelColor, mSelectedLabelColor; + // tick labels: + //int mTickLabelPadding; in label painter + bool mTickLabels; + //double mTickLabelRotation; in label painter + QFont mTickLabelFont, mSelectedTickLabelFont; + QColor mTickLabelColor, mSelectedTickLabelColor; + int mNumberPrecision; + QLatin1Char mNumberFormatChar; + bool mNumberBeautifulPowers; + bool mNumberMultiplyCross; + // ticks and subticks: + bool mTicks; + bool mSubTicks; + int mTickLengthIn, mTickLengthOut, mSubTickLengthIn, mSubTickLengthOut; + QPen mTickPen, mSelectedTickPen; + QPen mSubTickPen, mSelectedSubTickPen; + // scale and range: + QCPRange mRange; + bool mRangeReversed; + ScaleType mScaleType; + + // non-property members: + QPointF mCenter; + double mRadius; + QSharedPointer mTicker; + QVector mTickVector; + QVector mTickVectorLabels; + QVector mSubTickVector; + bool mDragging; + QCPRange mDragStartRange; + QCP::AntialiasedElements mAADragBackup, mNotAADragBackup; + QCPLabelPainterPrivate mLabelPainter; // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); - virtual QPointF anchorPixelPoint(int anchorId) const; + virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE; + // events: + virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged) Q_DECL_OVERRIDE; + virtual void deselectEvent(bool *selectionStateChanged) Q_DECL_OVERRIDE; + // mouse events: + virtual void mousePressEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE; + virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE; + virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE; + virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE; // non-virtual methods: - QPointF getTextDrawPoint(const QPointF &pos, const QRectF &rect, Qt::Alignment positionAlignment) const; - QFont mainFont() const; - QColor mainColor() const; - QPen mainPen() const; - QBrush mainBrush() const; + void updateGeometry(const QPointF ¢er, double radius); + void setupTickVectors(); + QPen getBasePen() const; + QPen getTickPen() const; + QPen getSubTickPen() const; + QFont getTickLabelFont() const; + QFont getLabelFont() const; + QColor getTickLabelColor() const; + QColor getLabelColor() const; + +private: + Q_DISABLE_COPY(QCPPolarAxisRadial) + + friend class QCustomPlot; + friend class QCPPolarAxisAngular; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QCPPolarAxisRadial::SelectableParts) +Q_DECLARE_METATYPE(QCPPolarAxisRadial::AngleReference) +Q_DECLARE_METATYPE(QCPPolarAxisRadial::ScaleType) +Q_DECLARE_METATYPE(QCPPolarAxisRadial::SelectablePart) -class QCP_LIB_DECL QCPItemEllipse : public QCPAbstractItem + +/* end of 'src/polar/radialaxis.h' */ + + +/* including file 'src/polar/layoutelement-angularaxis.h' */ +/* modified 2022-11-06T12:45:56, size 13461 */ + +class QCP_LIB_DECL QCPPolarAxisAngular : public QCPLayoutElement { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QPen pen READ pen WRITE setPen) - Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) - Q_PROPERTY(QBrush brush READ brush WRITE setBrush) - Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) + /// \endcond public: - QCPItemEllipse(QCustomPlot *parentPlot); - virtual ~QCPItemEllipse(); + /*! + Defines the selectable parts of an axis. + \see setSelectableParts, setSelectedParts + */ + enum SelectablePart { spNone = 0 ///< None of the selectable parts + ,spAxis = 0x001 ///< The axis backbone and tick marks + ,spTickLabels = 0x002 ///< Tick labels (numbers) of this axis (as a whole, not individually) + ,spAxisLabel = 0x004 ///< The axis label + }; + Q_ENUMS(SelectablePart) + Q_FLAGS(SelectableParts) + Q_DECLARE_FLAGS(SelectableParts, SelectablePart) + + /*! + TODO + */ + enum LabelMode { lmUpright ///< + ,lmRotated ///< + }; + Q_ENUMS(LabelMode) + + explicit QCPPolarAxisAngular(QCustomPlot *parentPlot); + virtual ~QCPPolarAxisAngular(); // getters: - QPen pen() const { return mPen; } - QPen selectedPen() const { return mSelectedPen; } - QBrush brush() const { return mBrush; } - QBrush selectedBrush() const { return mSelectedBrush; } + QPixmap background() const { return mBackgroundPixmap; } + QBrush backgroundBrush() const { return mBackgroundBrush; } + bool backgroundScaled() const { return mBackgroundScaled; } + Qt::AspectRatioMode backgroundScaledMode() const { return mBackgroundScaledMode; } + bool rangeDrag() const { return mRangeDrag; } + bool rangeZoom() const { return mRangeZoom; } + double rangeZoomFactor() const { return mRangeZoomFactor; } - // setters; - void setPen(const QPen &pen); - void setSelectedPen(const QPen &pen); - void setBrush(const QBrush &brush); - void setSelectedBrush(const QBrush &brush); + const QCPRange range() const { return mRange; } + bool rangeReversed() const { return mRangeReversed; } + double angle() const { return mAngle; } + QSharedPointer ticker() const { return mTicker; } + bool ticks() const { return mTicks; } + bool tickLabels() const { return mTickLabels; } + int tickLabelPadding() const { return mLabelPainter.padding(); } + QFont tickLabelFont() const { return mTickLabelFont; } + QColor tickLabelColor() const { return mTickLabelColor; } + double tickLabelRotation() const { return mLabelPainter.rotation(); } + LabelMode tickLabelMode() const; + QString numberFormat() const; + int numberPrecision() const { return mNumberPrecision; } + QVector tickVector() const { return mTickVector; } + QVector tickVectorLabels() const { return mTickVectorLabels; } + int tickLengthIn() const { return mTickLengthIn; } + int tickLengthOut() const { return mTickLengthOut; } + bool subTicks() const { return mSubTicks; } + int subTickLengthIn() const { return mSubTickLengthIn; } + int subTickLengthOut() const { return mSubTickLengthOut; } + QPen basePen() const { return mBasePen; } + QPen tickPen() const { return mTickPen; } + QPen subTickPen() const { return mSubTickPen; } + QFont labelFont() const { return mLabelFont; } + QColor labelColor() const { return mLabelColor; } + QString label() const { return mLabel; } + int labelPadding() const { return mLabelPadding; } + SelectableParts selectedParts() const { return mSelectedParts; } + SelectableParts selectableParts() const { return mSelectableParts; } + QFont selectedTickLabelFont() const { return mSelectedTickLabelFont; } + QFont selectedLabelFont() const { return mSelectedLabelFont; } + QColor selectedTickLabelColor() const { return mSelectedTickLabelColor; } + QColor selectedLabelColor() const { return mSelectedLabelColor; } + QPen selectedBasePen() const { return mSelectedBasePen; } + QPen selectedTickPen() const { return mSelectedTickPen; } + QPen selectedSubTickPen() const { return mSelectedSubTickPen; } + QCPPolarGrid *grid() const { return mGrid; } + + // setters: + void setBackground(const QPixmap &pm); + void setBackground(const QPixmap &pm, bool scaled, Qt::AspectRatioMode mode=Qt::KeepAspectRatioByExpanding); + void setBackground(const QBrush &brush); + void setBackgroundScaled(bool scaled); + void setBackgroundScaledMode(Qt::AspectRatioMode mode); + void setRangeDrag(bool enabled); + void setRangeZoom(bool enabled); + void setRangeZoomFactor(double factor); + + Q_SLOT void setRange(const QCPRange &range); + void setRange(double lower, double upper); + void setRange(double position, double size, Qt::AlignmentFlag alignment); + void setRangeLower(double lower); + void setRangeUpper(double upper); + void setRangeReversed(bool reversed); + void setAngle(double degrees); + void setTicker(QSharedPointer ticker); + void setTicks(bool show); + void setTickLabels(bool show); + void setTickLabelPadding(int padding); + void setTickLabelFont(const QFont &font); + void setTickLabelColor(const QColor &color); + void setTickLabelRotation(double degrees); + void setTickLabelMode(LabelMode mode); + void setNumberFormat(const QString &formatCode); + void setNumberPrecision(int precision); + void setTickLength(int inside, int outside=0); + void setTickLengthIn(int inside); + void setTickLengthOut(int outside); + void setSubTicks(bool show); + void setSubTickLength(int inside, int outside=0); + void setSubTickLengthIn(int inside); + void setSubTickLengthOut(int outside); + void setBasePen(const QPen &pen); + void setTickPen(const QPen &pen); + void setSubTickPen(const QPen &pen); + void setLabelFont(const QFont &font); + void setLabelColor(const QColor &color); + void setLabel(const QString &str); + void setLabelPadding(int padding); + void setLabelPosition(Qt::AlignmentFlag position); + void setSelectedTickLabelFont(const QFont &font); + void setSelectedLabelFont(const QFont &font); + void setSelectedTickLabelColor(const QColor &color); + void setSelectedLabelColor(const QColor &color); + void setSelectedBasePen(const QPen &pen); + void setSelectedTickPen(const QPen &pen); + void setSelectedSubTickPen(const QPen &pen); + Q_SLOT void setSelectableParts(const QCPPolarAxisAngular::SelectableParts &selectableParts); + Q_SLOT void setSelectedParts(const QCPPolarAxisAngular::SelectableParts &selectedParts); // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const Q_DECL_OVERRIDE; + virtual void update(UpdatePhase phase) Q_DECL_OVERRIDE; + virtual QList elements(bool recursive) const Q_DECL_OVERRIDE; - QCPItemPosition * const topLeft; - QCPItemPosition * const bottomRight; - QCPItemAnchor * const topLeftRim; - QCPItemAnchor * const top; - QCPItemAnchor * const topRightRim; - QCPItemAnchor * const right; - QCPItemAnchor * const bottomRightRim; - QCPItemAnchor * const bottom; - QCPItemAnchor * const bottomLeftRim; - QCPItemAnchor * const left; - QCPItemAnchor * const center; + // non-property methods: + bool removeGraph(QCPPolarGraph *graph); + int radialAxisCount() const; + QCPPolarAxisRadial *radialAxis(int index=0) const; + QList radialAxes() const; + QCPPolarAxisRadial *addRadialAxis(QCPPolarAxisRadial *axis=0); + bool removeRadialAxis(QCPPolarAxisRadial *axis); + QCPLayoutInset *insetLayout() const { return mInsetLayout; } + QRegion exactClipRegion() const; + + void moveRange(double diff); + void scaleRange(double factor); + void scaleRange(double factor, double center); + void rescale(bool onlyVisiblePlottables=false); + double coordToAngleRad(double coord) const { return mAngleRad+(coord-mRange.lower)/mRange.size()*(mRangeReversed ? -2.0*M_PI : 2.0*M_PI); } // mention in doc that return doesn't wrap + double angleRadToCoord(double angleRad) const { return mRange.lower+(angleRad-mAngleRad)/(mRangeReversed ? -2.0*M_PI : 2.0*M_PI)*mRange.size(); } + void pixelToCoord(QPointF pixelPos, double &angleCoord, double &radiusCoord) const; + QPointF coordToPixel(double angleCoord, double radiusCoord) const; + SelectablePart getPartAt(const QPointF &pos) const; + + // read-only interface imitating a QRect: + int left() const { return mRect.left(); } + int right() const { return mRect.right(); } + int top() const { return mRect.top(); } + int bottom() const { return mRect.bottom(); } + int width() const { return mRect.width(); } + int height() const { return mRect.height(); } + QSize size() const { return mRect.size(); } + QPoint topLeft() const { return mRect.topLeft(); } + QPoint topRight() const { return mRect.topRight(); } + QPoint bottomLeft() const { return mRect.bottomLeft(); } + QPoint bottomRight() const { return mRect.bottomRight(); } + QPointF center() const { return mCenter; } + double radius() const { return mRadius; } + +signals: + void rangeChanged(const QCPRange &newRange); + void rangeChanged(const QCPRange &newRange, const QCPRange &oldRange); + void selectionChanged(const QCPPolarAxisAngular::SelectableParts &parts); + void selectableChanged(const QCPPolarAxisAngular::SelectableParts &parts); protected: - enum AnchorIndex {aiTopLeftRim, aiTop, aiTopRightRim, aiRight, aiBottomRightRim, aiBottom, aiBottomLeftRim, aiLeft, aiCenter}; + // property members: + QBrush mBackgroundBrush; + QPixmap mBackgroundPixmap; + QPixmap mScaledBackgroundPixmap; + bool mBackgroundScaled; + Qt::AspectRatioMode mBackgroundScaledMode; + QCPLayoutInset *mInsetLayout; + bool mRangeDrag; + bool mRangeZoom; + double mRangeZoomFactor; + + // axis base: + double mAngle, mAngleRad; + SelectableParts mSelectableParts, mSelectedParts; + QPen mBasePen, mSelectedBasePen; + // axis label: + int mLabelPadding; + QString mLabel; + QFont mLabelFont, mSelectedLabelFont; + QColor mLabelColor, mSelectedLabelColor; + // tick labels: + //int mTickLabelPadding; in label painter + bool mTickLabels; + //double mTickLabelRotation; in label painter + QFont mTickLabelFont, mSelectedTickLabelFont; + QColor mTickLabelColor, mSelectedTickLabelColor; + int mNumberPrecision; + QLatin1Char mNumberFormatChar; + bool mNumberBeautifulPowers; + bool mNumberMultiplyCross; + // ticks and subticks: + bool mTicks; + bool mSubTicks; + int mTickLengthIn, mTickLengthOut, mSubTickLengthIn, mSubTickLengthOut; + QPen mTickPen, mSelectedTickPen; + QPen mSubTickPen, mSelectedSubTickPen; + // scale and range: + QCPRange mRange; + bool mRangeReversed; - // property members: - QPen mPen, mSelectedPen; - QBrush mBrush, mSelectedBrush; + // non-property members: + QPointF mCenter; + double mRadius; + QList mRadialAxes; + QCPPolarGrid *mGrid; + QList mGraphs; + QSharedPointer mTicker; + QVector mTickVector; + QVector mTickVectorLabels; + QVector mTickVectorCosSin; + QVector mSubTickVector; + QVector mSubTickVectorCosSin; + bool mDragging; + QCPRange mDragAngularStart; + QList mDragRadialStart; + QCP::AntialiasedElements mAADragBackup, mNotAADragBackup; + QCPLabelPainterPrivate mLabelPainter; // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); - virtual QPointF anchorPixelPoint(int anchorId) const; + virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual QCP::Interaction selectionCategory() const Q_DECL_OVERRIDE; + // events: + virtual void mousePressEvent(QMouseEvent *event, const QVariant &details) Q_DECL_OVERRIDE; + virtual void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE; + virtual void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) Q_DECL_OVERRIDE; + virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE; // non-virtual methods: - QPen mainPen() const; - QBrush mainBrush() const; + bool registerPolarGraph(QCPPolarGraph *graph); + void drawBackground(QCPPainter *painter, const QPointF ¢er, double radius); + void setupTickVectors(); + QPen getBasePen() const; + QPen getTickPen() const; + QPen getSubTickPen() const; + QFont getTickLabelFont() const; + QFont getLabelFont() const; + QColor getTickLabelColor() const; + QColor getLabelColor() const; + +private: + Q_DISABLE_COPY(QCPPolarAxisAngular) + + friend class QCustomPlot; + friend class QCPPolarGrid; + friend class QCPPolarGraph; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QCPPolarAxisAngular::SelectableParts) +Q_DECLARE_METATYPE(QCPPolarAxisAngular::SelectablePart) +/* end of 'src/polar/layoutelement-angularaxis.h' */ -class QCP_LIB_DECL QCPItemPixmap : public QCPAbstractItem + +/* including file 'src/polar/polargrid.h' */ +/* modified 2022-11-06T12:45:56, size 4506 */ + +class QCP_LIB_DECL QCPPolarGrid :public QCPLayerable { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap) - Q_PROPERTY(bool scaled READ scaled WRITE setScaled) - Q_PROPERTY(Qt::AspectRatioMode aspectRatioMode READ aspectRatioMode) - Q_PROPERTY(Qt::TransformationMode transformationMode READ transformationMode) - Q_PROPERTY(QPen pen READ pen WRITE setPen) - Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) + /// \endcond public: - QCPItemPixmap(QCustomPlot *parentPlot); - virtual ~QCPItemPixmap(); - - // getters: - QPixmap pixmap() const { return mPixmap; } - bool scaled() const { return mScaled; } - Qt::AspectRatioMode aspectRatioMode() const { return mAspectRatioMode; } - Qt::TransformationMode transformationMode() const { return mTransformationMode; } - QPen pen() const { return mPen; } - QPen selectedPen() const { return mSelectedPen; } + /*! + TODO + */ + enum GridType { gtAngular = 0x01 ///< + ,gtRadial = 0x02 ///< + ,gtAll = 0xFF ///< + ,gtNone = 0x00 ///< + }; + Q_ENUMS(GridType) + Q_FLAGS(GridTypes) + Q_DECLARE_FLAGS(GridTypes, GridType) - // setters; - void setPixmap(const QPixmap &pixmap); - void setScaled(bool scaled, Qt::AspectRatioMode aspectRatioMode=Qt::KeepAspectRatio, Qt::TransformationMode transformationMode=Qt::SmoothTransformation); - void setPen(const QPen &pen); - void setSelectedPen(const QPen &pen); + explicit QCPPolarGrid(QCPPolarAxisAngular *parentAxis); - // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + // getters: + QCPPolarAxisRadial *radialAxis() const { return mRadialAxis.data(); } + GridTypes type() const { return mType; } + GridTypes subGridType() const { return mSubGridType; } + bool antialiasedSubGrid() const { return mAntialiasedSubGrid; } + bool antialiasedZeroLine() const { return mAntialiasedZeroLine; } + QPen angularPen() const { return mAngularPen; } + QPen angularSubGridPen() const { return mAngularSubGridPen; } + QPen radialPen() const { return mRadialPen; } + QPen radialSubGridPen() const { return mRadialSubGridPen; } + QPen radialZeroLinePen() const { return mRadialZeroLinePen; } - QCPItemPosition * const topLeft; - QCPItemPosition * const bottomRight; - QCPItemAnchor * const top; - QCPItemAnchor * const topRight; - QCPItemAnchor * const right; - QCPItemAnchor * const bottom; - QCPItemAnchor * const bottomLeft; - QCPItemAnchor * const left; + // setters: + void setRadialAxis(QCPPolarAxisRadial *axis); + void setType(GridTypes type); + void setSubGridType(GridTypes type); + void setAntialiasedSubGrid(bool enabled); + void setAntialiasedZeroLine(bool enabled); + void setAngularPen(const QPen &pen); + void setAngularSubGridPen(const QPen &pen); + void setRadialPen(const QPen &pen); + void setRadialSubGridPen(const QPen &pen); + void setRadialZeroLinePen(const QPen &pen); protected: - enum AnchorIndex {aiTop, aiTopRight, aiRight, aiBottom, aiBottomLeft, aiLeft}; - // property members: - QPixmap mPixmap; - QPixmap mScaledPixmap; - bool mScaled; - Qt::AspectRatioMode mAspectRatioMode; - Qt::TransformationMode mTransformationMode; - QPen mPen, mSelectedPen; + GridTypes mType; + GridTypes mSubGridType; + bool mAntialiasedSubGrid, mAntialiasedZeroLine; + QPen mAngularPen, mAngularSubGridPen; + QPen mRadialPen, mRadialSubGridPen, mRadialZeroLinePen; + + // non-property members: + QCPPolarAxisAngular *mParentAxis; + QPointer mRadialAxis; // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); - virtual QPointF anchorPixelPoint(int anchorId) const; + virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const Q_DECL_OVERRIDE; + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; // non-virtual methods: - void updateScaledPixmap(QRect finalRect=QRect(), bool flipHorz=false, bool flipVert=false); - QRect getFinalRect(bool *flippedHorz=0, bool *flippedVert=0) const; - QPen mainPen() const; + void drawRadialGrid(QCPPainter *painter, const QPointF ¢er, const QVector &coords, const QPen &pen, const QPen &zeroPen=Qt::NoPen); + void drawAngularGrid(QCPPainter *painter, const QPointF ¢er, double radius, const QVector &ticksCosSin, const QPen &pen); + +private: + Q_DISABLE_COPY(QCPPolarGrid) + }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QCPPolarGrid::GridTypes) +Q_DECLARE_METATYPE(QCPPolarGrid::GridType) -class QCP_LIB_DECL QCPItemTracer : public QCPAbstractItem -{ - Q_OBJECT - /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QPen pen READ pen WRITE setPen) - Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) - Q_PROPERTY(QBrush brush READ brush WRITE setBrush) - Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush) - Q_PROPERTY(double size READ size WRITE setSize) - Q_PROPERTY(TracerStyle style READ style WRITE setStyle) - Q_PROPERTY(QCPGraph* graph READ graph WRITE setGraph) - Q_PROPERTY(double graphKey READ graphKey WRITE setGraphKey) - Q_PROPERTY(bool interpolating READ interpolating WRITE setInterpolating) - /// \endcond -public: - /*! - The different visual appearances a tracer item can have. Some styles size may be controlled with \ref setSize. - - \see setStyle - */ - enum TracerStyle { tsNone ///< The tracer is not visible - ,tsPlus ///< A plus shaped crosshair with limited size - ,tsCrosshair ///< A plus shaped crosshair which spans the complete axis rect - ,tsCircle ///< A circle - ,tsSquare ///< A square - }; - Q_ENUMS(TracerStyle) - - QCPItemTracer(QCustomPlot *parentPlot); - virtual ~QCPItemTracer(); - // getters: - QPen pen() const { return mPen; } - QPen selectedPen() const { return mSelectedPen; } - QBrush brush() const { return mBrush; } - QBrush selectedBrush() const { return mSelectedBrush; } - double size() const { return mSize; } - TracerStyle style() const { return mStyle; } - QCPGraph *graph() const { return mGraph; } - double graphKey() const { return mGraphKey; } - bool interpolating() const { return mInterpolating; } +/* end of 'src/polar/polargrid.h' */ - // setters; - void setPen(const QPen &pen); - void setSelectedPen(const QPen &pen); - void setBrush(const QBrush &brush); - void setSelectedBrush(const QBrush &brush); - void setSize(double size); - void setStyle(TracerStyle style); - void setGraph(QCPGraph *graph); - void setGraphKey(double key); - void setInterpolating(bool enabled); - // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; - - // non-virtual methods: - void updatePosition(); +/* including file 'src/polar/polargraph.h' */ +/* modified 2022-11-06T12:45:56, size 9606 */ - QCPItemPosition * const position; +class QCP_LIB_DECL QCPPolarLegendItem : public QCPAbstractLegendItem +{ + Q_OBJECT +public: + QCPPolarLegendItem(QCPLegend *parent, QCPPolarGraph *graph); + + // getters: + QCPPolarGraph *polarGraph() { return mPolarGraph; } + protected: // property members: - QPen mPen, mSelectedPen; - QBrush mBrush, mSelectedBrush; - double mSize; - TracerStyle mStyle; - QCPGraph *mGraph; - double mGraphKey; - bool mInterpolating; - + QCPPolarGraph *mPolarGraph; + // reimplemented virtual methods: - virtual void draw(QCPPainter *painter); - + virtual void draw(QCPPainter *painter) Q_DECL_OVERRIDE; + virtual QSize minimumOuterSizeHint() const Q_DECL_OVERRIDE; + // non-virtual methods: - QPen mainPen() const; - QBrush mainBrush() const; + QPen getIconBorderPen() const; + QColor getTextColor() const; + QFont getFont() const; }; -class QCP_LIB_DECL QCPItemBracket : public QCPAbstractItem +class QCP_LIB_DECL QCPPolarGraph : public QCPLayerable { Q_OBJECT /// \cond INCLUDE_QPROPERTIES - Q_PROPERTY(QPen pen READ pen WRITE setPen) - Q_PROPERTY(QPen selectedPen READ selectedPen WRITE setSelectedPen) - Q_PROPERTY(double length READ length WRITE setLength) - Q_PROPERTY(BracketStyle style READ style WRITE setStyle) + /// \endcond public: - enum BracketStyle { bsSquare ///< A brace with angled edges - ,bsRound ///< A brace with round edges - ,bsCurly ///< A curly brace - ,bsCalligraphic ///< A curly brace with varying stroke width giving a calligraphic impression - }; - - QCPItemBracket(QCustomPlot *parentPlot); - virtual ~QCPItemBracket(); + /*! + Defines how the graph's line is represented visually in the plot. The line is drawn with the + current pen of the graph (\ref setPen). + \see setLineStyle + */ + enum LineStyle { lsNone ///< data points are not connected with any lines (e.g. data only represented + ///< with symbols according to the scatter style, see \ref setScatterStyle) + ,lsLine ///< data points are connected by a straight line + }; + Q_ENUMS(LineStyle) + + QCPPolarGraph(QCPPolarAxisAngular *keyAxis, QCPPolarAxisRadial *valueAxis); + virtual ~QCPPolarGraph(); // getters: + QString name() const { return mName; } + bool antialiasedFill() const { return mAntialiasedFill; } + bool antialiasedScatters() const { return mAntialiasedScatters; } QPen pen() const { return mPen; } - QPen selectedPen() const { return mSelectedPen; } - double length() const { return mLength; } - BracketStyle style() const { return mStyle; } + QBrush brush() const { return mBrush; } + bool periodic() const { return mPeriodic; } + QCPPolarAxisAngular *keyAxis() const { return mKeyAxis.data(); } + QCPPolarAxisRadial *valueAxis() const { return mValueAxis.data(); } + QCP::SelectionType selectable() const { return mSelectable; } + bool selected() const { return !mSelection.isEmpty(); } + QCPDataSelection selection() const { return mSelection; } + //QCPSelectionDecorator *selectionDecorator() const { return mSelectionDecorator; } + QSharedPointer data() const { return mDataContainer; } + LineStyle lineStyle() const { return mLineStyle; } + QCPScatterStyle scatterStyle() const { return mScatterStyle; } - // setters; + // setters: + void setName(const QString &name); + void setAntialiasedFill(bool enabled); + void setAntialiasedScatters(bool enabled); void setPen(const QPen &pen); - void setSelectedPen(const QPen &pen); - void setLength(double length); - void setStyle(BracketStyle style); + void setBrush(const QBrush &brush); + void setPeriodic(bool enabled); + void setKeyAxis(QCPPolarAxisAngular *axis); + void setValueAxis(QCPPolarAxisRadial *axis); + Q_SLOT void setSelectable(QCP::SelectionType selectable); + Q_SLOT void setSelection(QCPDataSelection selection); + //void setSelectionDecorator(QCPSelectionDecorator *decorator); + void setData(QSharedPointer data); + void setData(const QVector &keys, const QVector &values, bool alreadySorted=false); + void setLineStyle(LineStyle ls); + void setScatterStyle(const QCPScatterStyle &style); + + // non-property methods: + void addData(const QVector &keys, const QVector &values, bool alreadySorted=false); + void addData(double key, double value); + void coordsToPixels(double key, double value, double &x, double &y) const; + const QPointF coordsToPixels(double key, double value) const; + void pixelsToCoords(double x, double y, double &key, double &value) const; + void pixelsToCoords(const QPointF &pixelPos, double &key, double &value) const; + void rescaleAxes(bool onlyEnlarge=false) const; + void rescaleKeyAxis(bool onlyEnlarge=false) const; + void rescaleValueAxis(bool onlyEnlarge=false, bool inKeyRange=false) const; + bool addToLegend(QCPLegend *legend); + bool addToLegend(); + bool removeFromLegend(QCPLegend *legend) const; + bool removeFromLegend() const; - // reimplemented virtual methods: - virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; + // introduced virtual methods: + virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const; // actually introduced in QCPLayerable as non-pure, but we want to force reimplementation for plottables + virtual QCPPlottableInterface1D *interface1D() { return 0; } // TODO: return this later, when QCPAbstractPolarPlottable is created + virtual QCPRange getKeyRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth) const; + virtual QCPRange getValueRange(bool &foundRange, QCP::SignDomain inSignDomain=QCP::sdBoth, const QCPRange &inKeyRange=QCPRange()) const; - QCPItemPosition * const left; - QCPItemPosition * const right; - QCPItemAnchor * const center; +signals: + void selectionChanged(bool selected); + void selectionChanged(const QCPDataSelection &selection); + void selectableChanged(QCP::SelectionType selectable); protected: // property members: - enum AnchorIndex {aiCenter}; - QPen mPen, mSelectedPen; - double mLength; - BracketStyle mStyle; + QSharedPointer mDataContainer; + LineStyle mLineStyle; + QCPScatterStyle mScatterStyle; + QString mName; + bool mAntialiasedFill, mAntialiasedScatters; + QPen mPen; + QBrush mBrush; + bool mPeriodic; + QPointer mKeyAxis; + QPointer mValueAxis; + QCP::SelectionType mSelectable; + QCPDataSelection mSelection; + //QCPSelectionDecorator *mSelectionDecorator; - // reimplemented virtual methods: + // introduced virtual methods (later reimplemented TODO from QCPAbstractPolarPlottable): + virtual QRect clipRect() const; virtual void draw(QCPPainter *painter); - virtual QPointF anchorPixelPoint(int anchorId) const; + virtual QCP::Interaction selectionCategory() const; + void applyDefaultAntialiasingHint(QCPPainter *painter) const; + // events: + virtual void selectEvent(QMouseEvent *event, bool additive, const QVariant &details, bool *selectionStateChanged); + virtual void deselectEvent(bool *selectionStateChanged); + // virtual drawing helpers: + virtual void drawLinePlot(QCPPainter *painter, const QVector &lines) const; + virtual void drawFill(QCPPainter *painter, QVector *lines) const; + virtual void drawScatterPlot(QCPPainter *painter, const QVector &scatters, const QCPScatterStyle &style) const; + + // introduced virtual methods: + virtual void drawLegendIcon(QCPPainter *painter, const QRectF &rect) const; // non-virtual methods: - QPen mainPen() const; + void applyFillAntialiasingHint(QCPPainter *painter) const; + void applyScattersAntialiasingHint(QCPPainter *painter) const; + double pointDistance(const QPointF &pixelPoint, QCPGraphDataContainer::const_iterator &closestData) const; + // drawing helpers: + virtual int dataCount() const; + void getDataSegments(QList &selectedSegments, QList &unselectedSegments) const; + void drawPolyline(QCPPainter *painter, const QVector &lineData) const; + void getVisibleDataBounds(QCPGraphDataContainer::const_iterator &begin, QCPGraphDataContainer::const_iterator &end, const QCPDataRange &rangeRestriction) const; + void getLines(QVector *lines, const QCPDataRange &dataRange) const; + void getScatters(QVector *scatters, const QCPDataRange &dataRange) const; + void getOptimizedLineData(QVector *lineData, const QCPGraphDataContainer::const_iterator &begin, const QCPGraphDataContainer::const_iterator &end) const; + void getOptimizedScatterData(QVector *scatterData, QCPGraphDataContainer::const_iterator begin, QCPGraphDataContainer::const_iterator end) const; + QVector dataToLines(const QVector &data) const; + +private: + Q_DISABLE_COPY(QCPPolarGraph) + + friend class QCPPolarLegendItem; }; +/* end of 'src/polar/polargraph.h' */ + + #endif // QCUSTOMPLOT_H diff --git a/libs/qcustomplot-source/qcustomplot.pro b/libs/qcustomplot-source/qcustomplot.pro deleted file mode 100644 index 0a831af40..000000000 --- a/libs/qcustomplot-source/qcustomplot.pro +++ /dev/null @@ -1,13 +0,0 @@ -TEMPLATE = lib - -QT += core gui network -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport - -CONFIG += staticlib -CONFIG += debug_and_release - -HEADERS += \ - qcustomplot.h - -SOURCES += \ - qcustomplot.cpp diff --git a/libs/qhexedit/CMakeLists.txt b/libs/qhexedit/CMakeLists.txt index 286eb0b9e..62e3fc410 100644 --- a/libs/qhexedit/CMakeLists.txt +++ b/libs/qhexedit/CMakeLists.txt @@ -1,39 +1,28 @@ -cmake_minimum_required(VERSION 2.8.7) +cmake_minimum_required(VERSION 3.16) -if(USE_QT5) - set(CMAKE_AUTOMOC ON) - set(CMAKE_INCLUDE_CURRENT_DIR ON) - find_package(Qt5Widgets REQUIRED) -else() - find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) - include("${QT_USE_FILE}") - add_definitions(${QT_DEFINITIONS}) -endif() +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +find_package(${QT_MAJOR} REQUIRED COMPONENTS Widgets) set(QHEXEDIT_SRC - src/commands.cpp src/qhexedit.cpp - src/qhexedit_p.cpp - src/xbytearray.cpp + src/chunks.cpp + src/commands.cpp ) set(QHEXEDIT_HDR + src/chunks.h src/commands.h - src/xbytearray.h ) set(QHEXEDIT_MOC_HDR - src/qhexedit.h - src/qhexedit_p.h + src/qhexedit.h + src/commands.h ) -if(NOT USE_QT5) - QT4_WRAP_CPP(QHEXEDIT_MOC ${QHEXEDIT_MOC_HDR}) -endif() - -add_library(qhexedit ${QHEXEDIT_SRC} ${QHEXEDIT_HDR} ${QHEXEDIT_MOC}) - -if(USE_QT5) - qt5_use_modules(qhexedit Widgets) -endif() +add_library(qhexedit ${QHEXEDIT_SRC} ${QHEXEDIT_HDR} ${QHEXEDIT_MOC_HDR} ${QHEXEDIT_MOC}) +target_include_directories(qhexedit INTERFACE src) +target_link_libraries(qhexedit ${QT_MAJOR}::Widgets) +add_library(QHexEdit::QHexEdit ALIAS qhexedit) diff --git a/libs/qhexedit/qhexedit.pro b/libs/qhexedit/qhexedit.pro deleted file mode 100644 index 6d05d85d3..000000000 --- a/libs/qhexedit/qhexedit.pro +++ /dev/null @@ -1,19 +0,0 @@ -TEMPLATE = lib - -QT += core gui network -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport - -CONFIG += staticlib -CONFIG += debug_and_release - -HEADERS += \ - src/commands.h \ - src/qhexedit.h \ - src/qhexedit_p.h \ - src/xbytearray.h - -SOURCES += \ - src/commands.cpp \ - src/qhexedit.cpp \ - src/qhexedit_p.cpp \ - src/xbytearray.cpp diff --git a/libs/qhexedit/src/chunks.cpp b/libs/qhexedit/src/chunks.cpp new file mode 100644 index 000000000..a4e420bf1 --- /dev/null +++ b/libs/qhexedit/src/chunks.cpp @@ -0,0 +1,323 @@ +#include "chunks.h" +#include + +#define NORMAL 0 +#define HIGHLIGHTED 1 + +#define BUFFER_SIZE 0x10000 +#define CHUNK_SIZE 0x1000 +#define READ_CHUNK_MASK Q_INT64_C(0xfffffffffffff000) + +// ***************************************** Constructors and file settings + +Chunks::Chunks(QObject *parent): QObject(parent) +{ + QBuffer *buf = new QBuffer(this); + setIODevice(*buf); +} + +Chunks::Chunks(QIODevice &ioDevice, QObject *parent): QObject(parent) +{ + setIODevice(ioDevice); +} + +bool Chunks::setIODevice(QIODevice &ioDevice) +{ + _ioDevice = &ioDevice; + bool ok = _ioDevice->open(QIODevice::ReadOnly); + if (ok) // Try to open IODevice + { + _size = _ioDevice->size(); + _ioDevice->close(); + } + else // Fallback is an empty buffer + { + QBuffer *buf = new QBuffer(this); + _ioDevice = buf; + _size = 0; + } + _chunks.clear(); + _pos = 0; + return ok; +} + + +// ***************************************** Getting data out of Chunks + +QByteArray Chunks::data(qint64 pos, qint64 maxSize, QByteArray *highlighted) +{ + qint64 ioDelta = 0; + int chunkIdx = 0; + + Chunk chunk; + QByteArray buffer; + + // Do some checks and some arrangements + if (highlighted) + highlighted->clear(); + + if (pos >= _size) + return buffer; + + if (maxSize < 0) + maxSize = _size; + else + if ((pos + maxSize) > _size) + maxSize = _size - pos; + + _ioDevice->open(QIODevice::ReadOnly); + + while (maxSize > 0) + { + chunk.absPos = LLONG_MAX; + bool chunksLoopOngoing = true; + while ((chunkIdx < _chunks.count()) && chunksLoopOngoing) + { + // In this section, we track changes before our required data and + // we take the editdet data, if availible. ioDelta is a difference + // counter to justify the read pointer to the original data, if + // data in between was deleted or inserted. + + chunk = _chunks[chunkIdx]; + if (chunk.absPos > pos) + chunksLoopOngoing = false; + else + { + chunkIdx += 1; + qint64 count; + qint64 chunkOfs = pos - chunk.absPos; + if (maxSize > ((qint64)chunk.data.size() - chunkOfs)) + { + count = (qint64)chunk.data.size() - chunkOfs; + ioDelta += CHUNK_SIZE - chunk.data.size(); + } + else + count = maxSize; + if (count > 0) + { + buffer += chunk.data.mid(chunkOfs, (int)count); + maxSize -= count; + pos += count; + if (highlighted) + *highlighted += chunk.dataChanged.mid(chunkOfs, (int)count); + } + } + } + + if ((maxSize > 0) && (pos < chunk.absPos)) + { + // In this section, we read data from the original source. This only will + // happen, whe no copied data is available + + qint64 byteCount; + QByteArray readBuffer; + if ((chunk.absPos - pos) > maxSize) + byteCount = maxSize; + else + byteCount = chunk.absPos - pos; + + maxSize -= byteCount; + _ioDevice->seek(pos + ioDelta); + readBuffer = _ioDevice->read(byteCount); + buffer += readBuffer; + if (highlighted) + *highlighted += QByteArray(readBuffer.size(), NORMAL); + pos += readBuffer.size(); + } + } + _ioDevice->close(); + return buffer; +} + +bool Chunks::write(QIODevice &iODevice, qint64 pos, qint64 count) +{ + if (count == -1) + count = _size; + bool ok = iODevice.open(QIODevice::WriteOnly); + if (ok) + { + for (qint64 idx=pos; idx < count; idx += BUFFER_SIZE) + { + QByteArray ba = data(idx, BUFFER_SIZE); + iODevice.write(ba); + } + iODevice.close(); + } + return ok; +} + + +// ***************************************** Set and get highlighting infos + +void Chunks::setDataChanged(qint64 pos, bool dataChanged) +{ + if ((pos < 0) || (pos >= _size)) + return; + int chunkIdx = getChunkIndex(pos); + qint64 posInBa = pos - _chunks[chunkIdx].absPos; + _chunks[chunkIdx].dataChanged[(int)posInBa] = char(dataChanged); +} + +bool Chunks::dataChanged(qint64 pos) +{ + QByteArray highlighted; + data(pos, 1, &highlighted); + return bool(highlighted.at(0)); +} + + +// ***************************************** Search API + +qint64 Chunks::indexOf(const QByteArray &ba, qint64 from) +{ + qint64 result = -1; + QByteArray buffer; + + for (qint64 pos=from; (pos < _size) && (result < 0); pos += BUFFER_SIZE) + { + buffer = data(pos, BUFFER_SIZE + ba.size() - 1); + int findPos = buffer.indexOf(ba); + if (findPos >= 0) + result = pos + (qint64)findPos; + } + return result; +} + +qint64 Chunks::lastIndexOf(const QByteArray &ba, qint64 from) +{ + qint64 result = -1; + QByteArray buffer; + + for (qint64 pos=from; (pos > 0) && (result < 0); pos -= BUFFER_SIZE) + { + qint64 sPos = pos - BUFFER_SIZE - (qint64)ba.size() + 1; + if (sPos < 0) + sPos = 0; + buffer = data(sPos, pos - sPos); + int findPos = buffer.lastIndexOf(ba); + if (findPos >= 0) + result = sPos + (qint64)findPos; + } + return result; +} + + +// ***************************************** Char manipulations + +bool Chunks::insert(qint64 pos, char b) +{ + if ((pos < 0) || (pos > _size)) + return false; + int chunkIdx; + if (pos == _size) + chunkIdx = getChunkIndex(pos-1); + else + chunkIdx = getChunkIndex(pos); + qint64 posInBa = pos - _chunks[chunkIdx].absPos; + _chunks[chunkIdx].data.insert(posInBa, b); + _chunks[chunkIdx].dataChanged.insert(posInBa, char(1)); + for (int idx=chunkIdx+1; idx < _chunks.size(); idx++) + _chunks[idx].absPos += 1; + _size += 1; + _pos = pos; + return true; +} + +bool Chunks::overwrite(qint64 pos, char b) +{ + if ((pos < 0) || (pos >= _size)) + return false; + int chunkIdx = getChunkIndex(pos); + qint64 posInBa = pos - _chunks[chunkIdx].absPos; + _chunks[chunkIdx].data[(int)posInBa] = b; + _chunks[chunkIdx].dataChanged[(int)posInBa] = char(1); + _pos = pos; + return true; +} + +bool Chunks::removeAt(qint64 pos) +{ + if ((pos < 0) || (pos >= _size)) + return false; + int chunkIdx = getChunkIndex(pos); + qint64 posInBa = pos - _chunks[chunkIdx].absPos; + _chunks[chunkIdx].data.remove(posInBa, 1); + _chunks[chunkIdx].dataChanged.remove(posInBa, 1); + for (int idx=chunkIdx+1; idx < _chunks.size(); idx++) + _chunks[idx].absPos -= 1; + _size -= 1; + _pos = pos; + return true; +} + + +// ***************************************** Utility functions + +char Chunks::operator[](qint64 pos) +{ + return data(pos, 1)[0]; +} + +qint64 Chunks::pos() +{ + return _pos; +} + +qint64 Chunks::size() +{ + return _size; +} + +int Chunks::getChunkIndex(qint64 absPos) +{ + // This routine checks, if there is already a copied chunk available. If os, it + // returns a reference to it. If there is no copied chunk available, original + // data will be copied into a new chunk. + + int foundIdx = -1; + int insertIdx = 0; + qint64 ioDelta = 0; + + + for (int idx=0; idx < _chunks.size(); idx++) + { + Chunk chunk = _chunks[idx]; + if ((absPos >= chunk.absPos) && (absPos < (chunk.absPos + chunk.data.size()))) + { + foundIdx = idx; + break; + } + if (absPos < chunk.absPos) + { + insertIdx = idx; + break; + } + ioDelta += chunk.data.size() - CHUNK_SIZE; + insertIdx = idx + 1; + } + + if (foundIdx == -1) + { + Chunk newChunk; + qint64 readAbsPos = absPos - ioDelta; + qint64 readPos = (readAbsPos & READ_CHUNK_MASK); + _ioDevice->open(QIODevice::ReadOnly); + _ioDevice->seek(readPos); + newChunk.data = _ioDevice->read(CHUNK_SIZE); + _ioDevice->close(); + newChunk.absPos = absPos - (readAbsPos - readPos); + newChunk.dataChanged = QByteArray(newChunk.data.size(), char(0)); + _chunks.insert(insertIdx, newChunk); + foundIdx = insertIdx; + } + return foundIdx; +} + + +#ifdef MODUL_TEST +int Chunks::chunkSize() +{ + return _chunks.size(); +} + +#endif diff --git a/libs/qhexedit/src/chunks.h b/libs/qhexedit/src/chunks.h new file mode 100644 index 000000000..43df76ca2 --- /dev/null +++ b/libs/qhexedit/src/chunks.h @@ -0,0 +1,77 @@ +#ifndef CHUNKS_H +#define CHUNKS_H + +/** \cond docNever */ + +/*! The Chunks class is the storage backend for QHexEdit. + * + * When QHexEdit loads data, Chunks access them using a QIODevice interface. When the app uses + * a QByteArray interface, QBuffer is used to provide again a QIODevice like interface. No data + * will be changed, therefore Chunks opens the QIODevice in QIODevice::ReadOnly mode. After every + * access Chunks closes the QIODevice, that's why external applications can overwrite files while + * QHexEdit shows them. + * + * When the the user starts to edit the data, Chunks creates a local copy of a chunk of data (4 + * kilobytes) and notes all changes there. Parallel to that chunk, there is a second chunk, + * which keep track of which bytes are changed and which not. + * + */ + +#include + +struct Chunk +{ + QByteArray data; + QByteArray dataChanged; + qint64 absPos; +}; + +class Chunks: public QObject +{ +Q_OBJECT +public: + // Constructors and file settings + Chunks(QObject *parent); + Chunks(QIODevice &ioDevice, QObject *parent); + bool setIODevice(QIODevice &ioDevice); + + // Getting data out of Chunks + QByteArray data(qint64 pos=0, qint64 count=-1, QByteArray *highlighted=0); + bool write(QIODevice &iODevice, qint64 pos=0, qint64 count=-1); + + // Set and get highlighting infos + void setDataChanged(qint64 pos, bool dataChanged); + bool dataChanged(qint64 pos); + + // Search API + qint64 indexOf(const QByteArray &ba, qint64 from); + qint64 lastIndexOf(const QByteArray &ba, qint64 from); + + // Char manipulations + bool insert(qint64 pos, char b); + bool overwrite(qint64 pos, char b); + bool removeAt(qint64 pos); + + // Utility functions + char operator[](qint64 pos); + qint64 pos(); + qint64 size(); + + +private: + int getChunkIndex(qint64 absPos); + + QIODevice * _ioDevice; + qint64 _pos; + qint64 _size; + QList _chunks; + +#ifdef MODUL_TEST +public: + int chunkSize(); +#endif +}; + +/** \endcond docNever */ + +#endif // CHUNKS_H diff --git a/libs/qhexedit/src/commands.cpp b/libs/qhexedit/src/commands.cpp index 303091d1d..e9530d56c 100644 --- a/libs/qhexedit/src/commands.cpp +++ b/libs/qhexedit/src/commands.cpp @@ -1,9 +1,34 @@ #include "commands.h" +#include -CharCommand::CharCommand(XByteArray * xData, Cmd cmd, int charPos, char newChar, QUndoCommand *parent) + +// Helper class to store single byte commands +class CharCommand : public QUndoCommand +{ +public: + enum CCmd {insert, removeAt, overwrite}; + + CharCommand(Chunks * chunks, CCmd cmd, qint64 charPos, char newChar, + QUndoCommand *parent=0); + + void undo(); + void redo(); + bool mergeWith(const QUndoCommand *command); + int id() const { return 1234; } + +private: + Chunks * _chunks; + qint64 _charPos; + bool _wasChanged; + char _newChar; + char _oldChar; + CCmd _cmd; +}; + +CharCommand::CharCommand(Chunks * chunks, CCmd cmd, qint64 charPos, char newChar, QUndoCommand *parent) : QUndoCommand(parent) { - _xData = xData; + _chunks = chunks; _charPos = charPos; _newChar = newChar; _cmd = cmd; @@ -14,9 +39,9 @@ bool CharCommand::mergeWith(const QUndoCommand *command) const CharCommand *nextCommand = static_cast(command); bool result = false; - if (_cmd != remove) + if (_cmd != CharCommand::removeAt) { - if (nextCommand->_cmd == replace) + if (nextCommand->_cmd == overwrite) if (nextCommand->_charPos == _charPos) { _newChar = nextCommand->_newChar; @@ -31,15 +56,15 @@ void CharCommand::undo() switch (_cmd) { case insert: - _xData->remove(_charPos, 1); + _chunks->removeAt(_charPos); break; - case replace: - _xData->replace(_charPos, _oldChar); - _xData->setDataChanged(_charPos, _wasChanged); + case overwrite: + _chunks->overwrite(_charPos, _oldChar); + _chunks->setDataChanged(_charPos, _wasChanged); break; - case remove: - _xData->insert(_charPos, _oldChar); - _xData->setDataChanged(_charPos, _wasChanged); + case removeAt: + _chunks->insert(_charPos, _oldChar); + _chunks->setDataChanged(_charPos, _wasChanged); break; } } @@ -49,67 +74,92 @@ void CharCommand::redo() switch (_cmd) { case insert: - _xData->insert(_charPos, _newChar); + _chunks->insert(_charPos, _newChar); break; - case replace: - _oldChar = _xData->data()[_charPos]; - _wasChanged = _xData->dataChanged(_charPos); - _xData->replace(_charPos, _newChar); + case overwrite: + _oldChar = (*_chunks)[_charPos]; + _wasChanged = _chunks->dataChanged(_charPos); + _chunks->overwrite(_charPos, _newChar); break; - case remove: - _oldChar = _xData->data()[_charPos]; - _wasChanged = _xData->dataChanged(_charPos); - _xData->remove(_charPos, 1); + case removeAt: + _oldChar = (*_chunks)[_charPos]; + _wasChanged = _chunks->dataChanged(_charPos); + _chunks->removeAt(_charPos); break; } } +UndoStack::UndoStack(Chunks * chunks, QObject * parent) + : QUndoStack(parent) +{ + _chunks = chunks; + _parent = parent; +} +void UndoStack::insert(qint64 pos, char c) +{ + if ((pos >= 0) && (pos <= _chunks->size())) + { + QUndoCommand *cc = new CharCommand(_chunks, CharCommand::insert, pos, c); + this->push(cc); + } +} -ArrayCommand::ArrayCommand(XByteArray * xData, Cmd cmd, int baPos, QByteArray newBa, int len, QUndoCommand *parent) - : QUndoCommand(parent) +void UndoStack::insert(qint64 pos, const QByteArray &ba) { - _cmd = cmd; - _xData = xData; - _baPos = baPos; - _newBa = newBa; - _len = len; + if ((pos >= 0) && (pos <= _chunks->size())) + { + QString txt = QString(tr("Inserting %1 bytes")).arg(ba.size()); + beginMacro(txt); + for (int idx=0; idx < ba.size(); idx++) + { + QUndoCommand *cc = new CharCommand(_chunks, CharCommand::insert, pos + idx, ba.at(idx)); + this->push(cc); + } + endMacro(); + } } -void ArrayCommand::undo() +void UndoStack::removeAt(qint64 pos, qint64 len) { - switch (_cmd) + if ((pos >= 0) && (pos < _chunks->size())) { - case insert: - _xData->remove(_baPos, _newBa.length()); - break; - case replace: - _xData->replace(_baPos, _oldBa); - _xData->setDataChanged(_baPos, _wasChanged); - break; - case remove: - _xData->insert(_baPos, _oldBa); - _xData->setDataChanged(_baPos, _wasChanged); - break; + if (len==1) + { + QUndoCommand *cc = new CharCommand(_chunks, CharCommand::removeAt, pos, char(0)); + this->push(cc); + } + else + { + QString txt = QString(tr("Delete %1 chars")).arg(len); + beginMacro(txt); + for (qint64 cnt=0; cnt= 0) && (pos < _chunks->size())) { - case insert: - _xData->insert(_baPos, _newBa); - break; - case replace: - _oldBa = _xData->data().mid(_baPos, _len); - _wasChanged = _xData->dataChanged(_baPos, _len); - _xData->replace(_baPos, _newBa); - break; - case remove: - _oldBa = _xData->data().mid(_baPos, _len); - _wasChanged = _xData->dataChanged(_baPos, _len); - _xData->remove(_baPos, _len); - break; + QUndoCommand *cc = new CharCommand(_chunks, CharCommand::overwrite, pos, c); + this->push(cc); + } +} + +void UndoStack::overwrite(qint64 pos, int len, const QByteArray &ba) +{ + if ((pos >= 0) && (pos < _chunks->size())) + { + QString txt = QString(tr("Overwrite %1 chars")).arg(len); + beginMacro(txt); + removeAt(pos, len); + insert(pos, ba); + endMacro(); } } diff --git a/libs/qhexedit/src/commands.h b/libs/qhexedit/src/commands.h index 9931b3fb5..40fcfa211 100644 --- a/libs/qhexedit/src/commands.h +++ b/libs/qhexedit/src/commands.h @@ -3,66 +3,43 @@ /** \cond docNever */ -#include +#include -#include "xbytearray.h" +#include "chunks.h" -/*! CharCommand is a class to prived undo/redo functionality in QHexEdit. +/*! CharCommand is a class to provid undo/redo functionality in QHexEdit. A QUndoCommand represents a single editing action on a document. CharCommand -is responsable for manipulations on single chars. It can insert. replace and -remove characters. A manipulation stores allways to actions +is responsable for manipulations on single chars. It can insert. overwrite and +remove characters. A manipulation stores allways two actions 1. redo (or do) action 2. undo action. -CharCommand also supports command compression via mergeWidht(). This allows -the user to execute a undo command contation e.g. 3 steps in a single command. +CharCommand also supports command compression via mergeWidht(). This enables +the user to perform an undo command e.g. 3 steps in a single command. If you for example insert a new byt "34" this means for the editor doing 3 -steps: insert a "00", replace it with "03" and the replace it with "34". These +steps: insert a "00", overwrite it with "03" and the overwrite it with "34". These 3 steps are combined into a single step, insert a "34". -*/ -class CharCommand : public QUndoCommand -{ -public: - enum { Id = 1234 }; - enum Cmd {insert, remove, replace}; - - CharCommand(XByteArray * xData, Cmd cmd, int charPos, char newChar, - QUndoCommand *parent=0); - - void undo(); - void redo(); - bool mergeWith(const QUndoCommand *command); - int id() const { return Id; } -private: - XByteArray * _xData; - int _charPos; - bool _wasChanged; - char _newChar; - char _oldChar; - Cmd _cmd; -}; - -/*! ArrayCommand provides undo/redo functionality for handling binary strings. It -can undo/redo insert, replace and remove binary strins (QByteArrays). +The byte array oriented commands are just put into a set of single byte commands, +which are pooled together with the macroBegin() and macroEnd() functionality of +Qt's QUndoStack. */ -class ArrayCommand : public QUndoCommand + +class UndoStack : public QUndoStack { + Q_OBJECT + public: - enum Cmd {insert, remove, replace}; - ArrayCommand(XByteArray * xData, Cmd cmd, int baPos, QByteArray newBa=QByteArray(), int len=0, - QUndoCommand *parent=0); - void undo(); - void redo(); + UndoStack(Chunks *chunks, QObject * parent=0); + void insert(qint64 pos, char c); + void insert(qint64 pos, const QByteArray &ba); + void removeAt(qint64 pos, qint64 len=1); + void overwrite(qint64 pos, char c); + void overwrite(qint64 pos, int len, const QByteArray &ba); private: - Cmd _cmd; - XByteArray * _xData; - int _baPos; - int _len; - QByteArray _wasChanged; - QByteArray _newBa; - QByteArray _oldBa; + Chunks * _chunks; + QObject * _parent; }; /** \endcond docNever */ diff --git a/libs/qhexedit/src/qhexedit.cpp b/libs/qhexedit/src/qhexedit.cpp index b12624e08..1909e69ca 100644 --- a/libs/qhexedit/src/qhexedit.cpp +++ b/libs/qhexedit/src/qhexedit.cpp @@ -1,180 +1,1145 @@ -#include +#include +#include +#include +#include +#include #include "qhexedit.h" +#include -QHexEdit::QHexEdit(QWidget *parent) : QScrollArea(parent) +// ********************************************************************** Constructor, destructor + +QHexEdit::QHexEdit(QWidget *parent) : QAbstractScrollArea(parent) { - qHexEdit_p = new QHexEditPrivate(this); - setWidget(qHexEdit_p); - setWidgetResizable(true); + _addressArea = true; + _addressWidth = 4; + _asciiArea = true; + _overwriteMode = true; + _highlighting = true; + _readOnly = false; + _cursorPosition = 0; + _lastEventSize = 0; + _hexCharsInLine = 47; + _bytesPerLine = 16; + _editAreaIsAscii = false; + _hexCaps = false; + _dynamicBytesPerLine = false; + + _chunks = new Chunks(this); + _undoStack = new UndoStack(_chunks, this); +#ifdef Q_OS_WIN32 + setFont(QFont("Courier", 10)); +#else + setFont(QFont("Monospace", 10)); +#endif + setAddressAreaColor(this->palette().alternateBase().color()); + setHighlightingColor(QColor(0xff, 0xff, 0x99, 0xff)); + setSelectionColor(this->palette().highlight().color()); + + connect(&_cursorTimer, SIGNAL(timeout()), this, SLOT(updateCursor())); + connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjust())); + connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjust())); + connect(_undoStack, SIGNAL(indexChanged(int)), this, SLOT(dataChangedPrivate(int))); + + _cursorTimer.setInterval(500); + _cursorTimer.start(); + + setAddressWidth(4); + setAddressArea(true); + setAsciiArea(true); + setOverwriteMode(true); + setHighlighting(true); + setReadOnly(false); + + init(); - connect(qHexEdit_p, SIGNAL(currentAddressChanged(int)), this, SIGNAL(currentAddressChanged(int))); - connect(qHexEdit_p, SIGNAL(currentSizeChanged(int)), this, SIGNAL(currentSizeChanged(int))); - connect(qHexEdit_p, SIGNAL(dataChanged()), this, SIGNAL(dataChanged())); - connect(qHexEdit_p, SIGNAL(overwriteModeChanged(bool)), this, SIGNAL(overwriteModeChanged(bool))); - setFocusPolicy(Qt::NoFocus); } -int QHexEdit::indexOf(const QByteArray & ba, int from) const +QHexEdit::~QHexEdit() { - return qHexEdit_p->indexOf(ba, from); } -void QHexEdit::insert(int i, const QByteArray & ba) +// ********************************************************************** Properties + +void QHexEdit::setAddressArea(bool addressArea) { - qHexEdit_p->insert(i, ba); + _addressArea = addressArea; + adjust(); + setCursorPosition(_cursorPosition); + viewport()->update(); } -void QHexEdit::insert(int i, char ch) +bool QHexEdit::addressArea() { - qHexEdit_p->insert(i, ch); + return _addressArea; } -int QHexEdit::lastIndexOf(const QByteArray & ba, int from) const +void QHexEdit::setAddressAreaColor(const QColor &color) { - return qHexEdit_p->lastIndexOf(ba, from); + _addressAreaColor = color; + viewport()->update(); } -void QHexEdit::remove(int pos, int len) +QColor QHexEdit::addressAreaColor() { - qHexEdit_p->remove(pos, len); + return _addressAreaColor; } -void QHexEdit::replace( int pos, int len, const QByteArray & after) +void QHexEdit::setAddressOffset(qint64 addressOffset) { - qHexEdit_p->replace(pos, len, after); + _addressOffset = addressOffset; + adjust(); + setCursorPosition(_cursorPosition); + viewport()->update(); } -QString QHexEdit::toReadableString() +qint64 QHexEdit::addressOffset() { - return qHexEdit_p->toRedableString(); + return _addressOffset; } -QString QHexEdit::selectionToReadableString() +void QHexEdit::setAddressWidth(int addressWidth) { - return qHexEdit_p->selectionToReadableString(); + _addressWidth = addressWidth; + adjust(); + setCursorPosition(_cursorPosition); + viewport()->update(); } -void QHexEdit::setAddressArea(bool addressArea) +int QHexEdit::addressWidth() { - qHexEdit_p->setAddressArea(addressArea); + qint64 size = _chunks->size(); + int n = 1; + if (size > Q_INT64_C(0x100000000)){ n += 8; size /= Q_INT64_C(0x100000000);} + if (size > 0x10000){ n += 4; size /= 0x10000;} + if (size > 0x100){ n += 2; size /= 0x100;} + if (size > 0x10){ n += 1;} + + if (n > _addressWidth) + return n; + else + return _addressWidth; } -void QHexEdit::redo() +void QHexEdit::setAsciiArea(bool asciiArea) { - qHexEdit_p->redo(); + if (!asciiArea) + _editAreaIsAscii = false; + _asciiArea = asciiArea; + adjust(); + setCursorPosition(_cursorPosition); + viewport()->update(); } -void QHexEdit::undo() +bool QHexEdit::asciiArea() { - qHexEdit_p->undo(); + return _asciiArea; } -void QHexEdit::setAddressWidth(int addressWidth) +void QHexEdit::setBytesPerLine(int count) { - qHexEdit_p->setAddressWidth(addressWidth); + _bytesPerLine = count; + _hexCharsInLine = count * 3 - 1; + + adjust(); + setCursorPosition(_cursorPosition); + viewport()->update(); } -void QHexEdit::setAsciiArea(bool asciiArea) +int QHexEdit::bytesPerLine() { - qHexEdit_p->setAsciiArea(asciiArea); + return _bytesPerLine; } -void QHexEdit::setHighlighting(bool mode) +void QHexEdit::setCursorPosition(qint64 position) { - qHexEdit_p->setHighlighting(mode); + // 1. delete old cursor + _blink = false; + viewport()->update(_cursorRect); + + // 2. Check, if cursor in range? + if (position > (_chunks->size() * 2 - 1)) + position = _chunks->size() * 2 - (_overwriteMode ? 1 : 0); + + if (position < 0) + position = 0; + + // 3. Calc new position of cursor + _bPosCurrent = position / 2; + _pxCursorY = ((position / 2 - _bPosFirst) / _bytesPerLine + 1) * _pxCharHeight; + int x = (position % (2 * _bytesPerLine)); + if (_editAreaIsAscii) + { + _pxCursorX = x / 2 * _pxCharWidth + _pxPosAsciiX; + _cursorPosition = position & 0xFFFFFFFFFFFFFFFE; + } else { + _pxCursorX = (((x / 2) * 3) + (x % 2)) * _pxCharWidth + _pxPosHexX; + _cursorPosition = position; + } + + if (_overwriteMode) + _cursorRect = QRect(_pxCursorX - horizontalScrollBar()->value(), _pxCursorY + _pxCursorWidth, _pxCharWidth, _pxCursorWidth); + else + _cursorRect = QRect(_pxCursorX - horizontalScrollBar()->value(), _pxCursorY - _pxCharHeight + 4, _pxCursorWidth, _pxCharHeight); + + // 4. Immediately draw new cursor + _blink = true; + viewport()->update(_cursorRect); + emit currentAddressChanged(_bPosCurrent); } -void QHexEdit::setAddressOffset(int offset) +qint64 QHexEdit::cursorPosition(QPoint pos) { - qHexEdit_p->setAddressOffset(offset); + // Calc cursor position depending on a graphical position + qint64 result = -1; + int posX = pos.x() + horizontalScrollBar()->value(); + int posY = pos.y() - 3; + if ((posX >= _pxPosHexX) && (posX < (_pxPosHexX + (1 + _hexCharsInLine) * _pxCharWidth))) + { + _editAreaIsAscii = false; + int x = (posX - _pxPosHexX) / _pxCharWidth; + x = (x / 3) * 2 + x % 3; + int y = (posY / _pxCharHeight) * 2 * _bytesPerLine; + result = _bPosFirst * 2 + x + y; + } + else + if (_asciiArea && (posX >= _pxPosAsciiX) && (posX < (_pxPosAsciiX + (1 + _bytesPerLine) * _pxCharWidth))) + { + _editAreaIsAscii = true; + int x = 2 * (posX - _pxPosAsciiX) / _pxCharWidth; + int y = (posY / _pxCharHeight) * 2 * _bytesPerLine; + result = _bPosFirst * 2 + x + y; + } + return result; } -int QHexEdit::addressOffset() +qint64 QHexEdit::cursorPosition() { - return qHexEdit_p->addressOffset(); + return _cursorPosition; } -void QHexEdit::setCursorPosition(int cursorPos) +void QHexEdit::setData(const QByteArray &ba) { - // cursorPos in QHexEditPrivate is the position of the textcoursor without - // blanks, means bytePos*2 - qHexEdit_p->setCursorPos(cursorPos*2); + _data = ba; + _bData.setData(_data); + setData(_bData); } -int QHexEdit::cursorPosition() +QByteArray QHexEdit::data() { - return qHexEdit_p->cursorPos() / 2; + return _chunks->data(0, -1); } - -void QHexEdit::setData(const QByteArray &data) +void QHexEdit::setHighlighting(bool highlighting) { - qHexEdit_p->setData(data); + _highlighting = highlighting; + viewport()->update(); } -QByteArray QHexEdit::data() +bool QHexEdit::highlighting() { - return qHexEdit_p->data(); + return _highlighting; } -void QHexEdit::setAddressAreaColor(const QColor &color) +void QHexEdit::setHighlightingColor(const QColor &color) { - qHexEdit_p->setAddressAreaColor(color); + _brushHighlighted = QBrush(color); + _penHighlighted = QPen(viewport()->palette().color(QPalette::WindowText)); + viewport()->update(); } -QColor QHexEdit::addressAreaColor() +QColor QHexEdit::highlightingColor() { - return qHexEdit_p->addressAreaColor(); + return _brushHighlighted.color(); } -void QHexEdit::setHighlightingColor(const QColor &color) +void QHexEdit::setOverwriteMode(bool overwriteMode) { - qHexEdit_p->setHighlightingColor(color); + _overwriteMode = overwriteMode; + emit overwriteModeChanged(overwriteMode); } -QColor QHexEdit::highlightingColor() +bool QHexEdit::overwriteMode() { - return qHexEdit_p->highlightingColor(); + return _overwriteMode; } void QHexEdit::setSelectionColor(const QColor &color) { - qHexEdit_p->setSelectionColor(color); + _brushSelection = QBrush(color); + _penSelection = QPen(Qt::white); + viewport()->update(); } QColor QHexEdit::selectionColor() { - return qHexEdit_p->selectionColor(); + return _brushSelection.color(); } -void QHexEdit::setOverwriteMode(bool overwriteMode) +bool QHexEdit::isReadOnly() { - qHexEdit_p->setOverwriteMode(overwriteMode); + return _readOnly; } -bool QHexEdit::overwriteMode() +void QHexEdit::setReadOnly(bool readOnly) { - return qHexEdit_p->overwriteMode(); + _readOnly = readOnly; } -void QHexEdit::setReadOnly(bool readOnly) +void QHexEdit::setHexCaps(const bool isCaps) { - qHexEdit_p->setReadOnly(readOnly); + if (_hexCaps != isCaps) + { + _hexCaps = isCaps; + viewport()->update(); + } } -bool QHexEdit::isReadOnly() +bool QHexEdit::hexCaps() +{ + return _hexCaps; +} + +void QHexEdit::setDynamicBytesPerLine(const bool isDynamic) +{ + _dynamicBytesPerLine = isDynamic; + resizeEvent(NULL); +} + +bool QHexEdit::dynamicBytesPerLine() { - return qHexEdit_p->isReadOnly(); + return _dynamicBytesPerLine; +} + +// ********************************************************************** Access to data of qhexedit +bool QHexEdit::setData(QIODevice &iODevice) +{ + bool ok = _chunks->setIODevice(iODevice); + init(); + dataChangedPrivate(); + return ok; +} + +QByteArray QHexEdit::dataAt(qint64 pos, qint64 count) +{ + return _chunks->data(pos, count); +} + +bool QHexEdit::write(QIODevice &iODevice, qint64 pos, qint64 count) +{ + return _chunks->write(iODevice, pos, count); +} + +// ********************************************************************** Char handling +void QHexEdit::insert(qint64 index, char ch) +{ + _undoStack->insert(index, ch); + refresh(); +} + +void QHexEdit::remove(qint64 index, qint64 len) +{ + _undoStack->removeAt(index, len); + refresh(); +} + +void QHexEdit::replace(qint64 index, char ch) +{ + _undoStack->overwrite(index, ch); + refresh(); +} + +// ********************************************************************** ByteArray handling +void QHexEdit::insert(qint64 pos, const QByteArray &ba) +{ + _undoStack->insert(pos, ba); + refresh(); +} + +void QHexEdit::replace(qint64 pos, qint64 len, const QByteArray &ba) +{ + _undoStack->overwrite(pos, len, ba); + refresh(); +} + +// ********************************************************************** Utility functions +void QHexEdit::ensureVisible() +{ + if (_cursorPosition < (_bPosFirst * 2)) + verticalScrollBar()->setValue((int)(_cursorPosition / 2 / _bytesPerLine)); + if (_cursorPosition > ((_bPosFirst + (_rowsShown - 1)*_bytesPerLine) * 2)) + verticalScrollBar()->setValue((int)(_cursorPosition / 2 / _bytesPerLine) - _rowsShown + 1); + if (_pxCursorX < horizontalScrollBar()->value()) + horizontalScrollBar()->setValue(_pxCursorX); + if ((_pxCursorX + _pxCharWidth) > (horizontalScrollBar()->value() + viewport()->width())) + horizontalScrollBar()->setValue(_pxCursorX + _pxCharWidth - viewport()->width()); + viewport()->update(); +} + +qint64 QHexEdit::indexOf(const QByteArray &ba, qint64 from) +{ + qint64 pos = _chunks->indexOf(ba, from); + if (pos > -1) + { + qint64 curPos = pos*2; + setCursorPosition(curPos + ba.length()*2); + resetSelection(curPos); + setSelection(curPos + ba.length()*2); + ensureVisible(); + } + return pos; +} + +bool QHexEdit::isModified() +{ + return _modified; +} + +qint64 QHexEdit::lastIndexOf(const QByteArray &ba, qint64 from) +{ + qint64 pos = _chunks->lastIndexOf(ba, from); + if (pos > -1) + { + qint64 curPos = pos*2; + setCursorPosition(curPos - 1); + resetSelection(curPos); + setSelection(curPos + ba.length()*2); + ensureVisible(); + } + return pos; +} + +void QHexEdit::redo() +{ + _undoStack->redo(); + setCursorPosition(_chunks->pos()*(_editAreaIsAscii ? 1 : 2)); + refresh(); +} + +QString QHexEdit::selectionToReadableString() +{ + QByteArray ba = _chunks->data(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()); + return toReadable(ba); +} + +QString QHexEdit::selectedData() +{ + QByteArray ba = _chunks->data(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()).toHex(); + return ba; } void QHexEdit::setFont(const QFont &font) { - qHexEdit_p->setFont(font); + QWidget::setFont(font); + _pxCharWidth = fontMetrics().horizontalAdvance(QLatin1Char('2')); + _pxCharHeight = fontMetrics().height(); + _pxGapAdr = _pxCharWidth / 2; + _pxGapAdrHex = _pxCharWidth; + _pxGapHexAscii = 2 * _pxCharWidth; + _pxCursorWidth = _pxCharHeight / 7; + _pxSelectionSub = _pxCharHeight / 5; + viewport()->update(); +} + +QString QHexEdit::toReadableString() +{ + QByteArray ba = _chunks->data(); + return toReadable(ba); +} + +void QHexEdit::undo() +{ + _undoStack->undo(); + setCursorPosition(_chunks->pos()*(_editAreaIsAscii ? 1 : 2)); + refresh(); +} + +// ********************************************************************** Handle events +void QHexEdit::keyPressEvent(QKeyEvent *event) +{ + // Cursor movements + if (event->matches(QKeySequence::MoveToNextChar)) + { + qint64 pos = _cursorPosition + 1; + if (_editAreaIsAscii) + pos += 1; + setCursorPosition(pos); + resetSelection(pos); + } + if (event->matches(QKeySequence::MoveToPreviousChar)) + { + qint64 pos = _cursorPosition - 1; + if (_editAreaIsAscii) + pos -= 1; + setCursorPosition(pos); + resetSelection(pos); + } + if (event->matches(QKeySequence::MoveToEndOfLine)) + { + qint64 pos = _cursorPosition - (_cursorPosition % (2 * _bytesPerLine)) + (2 * _bytesPerLine) - 1; + setCursorPosition(pos); + resetSelection(_cursorPosition); + } + if (event->matches(QKeySequence::MoveToStartOfLine)) + { + qint64 pos = _cursorPosition - (_cursorPosition % (2 * _bytesPerLine)); + setCursorPosition(pos); + resetSelection(_cursorPosition); + } + if (event->matches(QKeySequence::MoveToPreviousLine)) + { + setCursorPosition(_cursorPosition - (2 * _bytesPerLine)); + resetSelection(_cursorPosition); + } + if (event->matches(QKeySequence::MoveToNextLine)) + { + setCursorPosition(_cursorPosition + (2 * _bytesPerLine)); + resetSelection(_cursorPosition); + } + if (event->matches(QKeySequence::MoveToNextPage)) + { + setCursorPosition(_cursorPosition + (((_rowsShown - 1) * 2 * _bytesPerLine))); + resetSelection(_cursorPosition); + } + if (event->matches(QKeySequence::MoveToPreviousPage)) + { + setCursorPosition(_cursorPosition - (((_rowsShown - 1) * 2 * _bytesPerLine))); + resetSelection(_cursorPosition); + } + if (event->matches(QKeySequence::MoveToEndOfDocument)) + { + setCursorPosition(_chunks->size() * 2 ); + resetSelection(_cursorPosition); + } + if (event->matches(QKeySequence::MoveToStartOfDocument)) + { + setCursorPosition(0); + resetSelection(_cursorPosition); + } + + // Select commands + if (event->matches(QKeySequence::SelectAll)) + { + resetSelection(0); + setSelection(2 * _chunks->size() + 1); + } + if (event->matches(QKeySequence::SelectNextChar)) + { + qint64 pos = _cursorPosition + 1; + if (_editAreaIsAscii) + pos += 1; + setCursorPosition(pos); + setSelection(pos); + } + if (event->matches(QKeySequence::SelectPreviousChar)) + { + qint64 pos = _cursorPosition - 1; + if (_editAreaIsAscii) + pos -= 1; + setSelection(pos); + setCursorPosition(pos); + } + if (event->matches(QKeySequence::SelectEndOfLine)) + { + qint64 pos = _cursorPosition - (_cursorPosition % (2 * _bytesPerLine)) + (2 * _bytesPerLine) - 1; + setCursorPosition(pos); + setSelection(pos); + } + if (event->matches(QKeySequence::SelectStartOfLine)) + { + qint64 pos = _cursorPosition - (_cursorPosition % (2 * _bytesPerLine)); + setCursorPosition(pos); + setSelection(pos); + } + if (event->matches(QKeySequence::SelectPreviousLine)) + { + qint64 pos = _cursorPosition - (2 * _bytesPerLine); + setCursorPosition(pos); + setSelection(pos); + } + if (event->matches(QKeySequence::SelectNextLine)) + { + qint64 pos = _cursorPosition + (2 * _bytesPerLine); + setCursorPosition(pos); + setSelection(pos); + } + if (event->matches(QKeySequence::SelectNextPage)) + { + qint64 pos = _cursorPosition + (((viewport()->height() / _pxCharHeight) - 1) * 2 * _bytesPerLine); + setCursorPosition(pos); + setSelection(pos); + } + if (event->matches(QKeySequence::SelectPreviousPage)) + { + qint64 pos = _cursorPosition - (((viewport()->height() / _pxCharHeight) - 1) * 2 * _bytesPerLine); + setCursorPosition(pos); + setSelection(pos); + } + if (event->matches(QKeySequence::SelectEndOfDocument)) + { + qint64 pos = _chunks->size() * 2; + setCursorPosition(pos); + setSelection(pos); + } + if (event->matches(QKeySequence::SelectStartOfDocument)) + { + qint64 pos = 0; + setCursorPosition(pos); + setSelection(pos); + } + + // Edit Commands + if (!_readOnly) + { + /* Cut */ + if (event->matches(QKeySequence::Cut)) + { + QByteArray ba = _chunks->data(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()).toHex(); + for (qint64 idx = 32; idx < ba.size(); idx +=33) + ba.insert(idx, "\n"); + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(ba); + if (_overwriteMode) + { + qint64 len = getSelectionEnd() - getSelectionBegin(); + replace(getSelectionBegin(), (int)len, QByteArray((int)len, char(0))); + } + else + { + remove(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()); + } + setCursorPosition(2 * getSelectionBegin()); + resetSelection(2 * getSelectionBegin()); + } else + + /* Paste */ + if (event->matches(QKeySequence::Paste)) + { + QClipboard *clipboard = QApplication::clipboard(); + QByteArray ba = QByteArray().fromHex(clipboard->text().toLatin1()); + if (_overwriteMode) + { + ba = ba.left(std::min(ba.size(), (_chunks->size() - _bPosCurrent))); + replace(_bPosCurrent, ba.size(), ba); + } + else + insert(_bPosCurrent, ba); + setCursorPosition(_cursorPosition + 2 * ba.size()); + resetSelection(getSelectionBegin()); + } else + + /* Delete char */ + if (event->matches(QKeySequence::Delete)) + { + if (getSelectionBegin() != getSelectionEnd()) + { + _bPosCurrent = getSelectionBegin(); + if (_overwriteMode) + { + QByteArray ba = QByteArray(getSelectionEnd() - getSelectionBegin(), char(0)); + replace(_bPosCurrent, ba.size(), ba); + } + else + { + remove(_bPosCurrent, getSelectionEnd() - getSelectionBegin()); + } + } + else + { + if (_overwriteMode) + replace(_bPosCurrent, char(0)); + else + remove(_bPosCurrent, 1); + } + setCursorPosition(2 * _bPosCurrent); + resetSelection(2 * _bPosCurrent); + } else + + /* Backspace */ + if ((event->key() == Qt::Key_Backspace) && (event->modifiers() == Qt::NoModifier)) + { + if (getSelectionBegin() != getSelectionEnd()) + { + _bPosCurrent = getSelectionBegin(); + setCursorPosition(2 * _bPosCurrent); + if (_overwriteMode) + { + QByteArray ba = QByteArray(getSelectionEnd() - getSelectionBegin(), char(0)); + replace(_bPosCurrent, ba.size(), ba); + } + else + { + remove(_bPosCurrent, getSelectionEnd() - getSelectionBegin()); + } + resetSelection(2 * _bPosCurrent); + } + else + { + bool behindLastByte = false; + if ((_cursorPosition / 2) == _chunks->size()) + behindLastByte = true; + + _bPosCurrent -= 1; + if (_overwriteMode) + replace(_bPosCurrent, char(0)); + else + remove(_bPosCurrent, 1); + + if (!behindLastByte) + _bPosCurrent -= 1; + + setCursorPosition(2 * _bPosCurrent); + resetSelection(2 * _bPosCurrent); + } + } else + + /* undo */ + if (event->matches(QKeySequence::Undo)) + { + undo(); + } else + + /* redo */ + if (event->matches(QKeySequence::Redo)) + { + redo(); + } else + + if ((QApplication::keyboardModifiers() == Qt::NoModifier) || + (QApplication::keyboardModifiers() == Qt::KeypadModifier) || + (QApplication::keyboardModifiers() == Qt::ShiftModifier) || + (QApplication::keyboardModifiers() == (Qt::AltModifier | Qt::ControlModifier)) || + (QApplication::keyboardModifiers() == Qt::GroupSwitchModifier)) + { + /* Hex and ascii input */ + int key; + if (_editAreaIsAscii) + key = (uchar)event->text()[0].toLatin1(); + else + key = int(event->text()[0].toLower().toLatin1()); + + if ((((key >= '0' && key <= '9') || (key >= 'a' && key <= 'f')) && _editAreaIsAscii == false) + || (key >= ' ' && _editAreaIsAscii)) + { + if (getSelectionBegin() != getSelectionEnd()) + { + if (_overwriteMode) + { + qint64 len = getSelectionEnd() - getSelectionBegin(); + replace(getSelectionBegin(), (int)len, QByteArray((int)len, char(0))); + } else + { + remove(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()); + _bPosCurrent = getSelectionBegin(); + } + setCursorPosition(2 * _bPosCurrent); + resetSelection(2 * _bPosCurrent); + } + + // If insert mode, then insert a byte + if (_overwriteMode == false) + if ((_cursorPosition % 2) == 0) + insert(_bPosCurrent, char(0)); + + // Change content + if (_chunks->size() > 0) + { + char ch = key; + if (!_editAreaIsAscii){ + QByteArray hexValue = _chunks->data(_bPosCurrent, 1).toHex(); + if ((_cursorPosition % 2) == 0) + hexValue[0] = key; + else + hexValue[1] = key; + ch = QByteArray().fromHex(hexValue)[0]; + } + replace(_bPosCurrent, ch); + if (_editAreaIsAscii) + setCursorPosition(_cursorPosition + 2); + else + setCursorPosition(_cursorPosition + 1); + resetSelection(_cursorPosition); + } + } + } + + + } + + /* Copy */ + if (event->matches(QKeySequence::Copy)) + { + QByteArray ba = _chunks->data(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()).toHex(); + for (qint64 idx = 32; idx < ba.size(); idx +=33) + ba.insert(idx, "\n"); + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(ba); + } + + // Switch between insert/overwrite mode + if ((event->key() == Qt::Key_Insert) && (event->modifiers() == Qt::NoModifier)) + { + setOverwriteMode(!overwriteMode()); + setCursorPosition(_cursorPosition); + } + + // switch from hex to ascii edit + if (event->key() == Qt::Key_Tab && !_editAreaIsAscii){ + _editAreaIsAscii = true; + setCursorPosition(_cursorPosition); + } + + // switch from ascii to hex edit + if (event->key() == Qt::Key_Backtab && _editAreaIsAscii){ + _editAreaIsAscii = false; + setCursorPosition(_cursorPosition); + } + + refresh(); +} + +void QHexEdit::mouseMoveEvent(QMouseEvent * event) +{ + _blink = false; + viewport()->update(); + qint64 actPos = cursorPosition(event->pos()); + if (actPos >= 0) + { + setCursorPosition(actPos); + setSelection(actPos); + } +} + +void QHexEdit::mousePressEvent(QMouseEvent * event) +{ + _blink = false; + viewport()->update(); + qint64 cPos = cursorPosition(event->pos()); + if (cPos >= 0) + { + if (event->button() != Qt::RightButton) + resetSelection(cPos); + setCursorPosition(cPos); + } +} + +void QHexEdit::paintEvent(QPaintEvent *event) +{ + QPainter painter(viewport()); + int pxOfsX = horizontalScrollBar()->value(); + + if (event->rect() != _cursorRect) + { + int pxPosStartY = _pxCharHeight; + + // draw some patterns if needed + painter.fillRect(event->rect(), viewport()->palette().color(QPalette::Base)); + if (_addressArea) + painter.fillRect(QRect(-pxOfsX, event->rect().top(), _pxPosHexX - _pxGapAdrHex/2, height()), _addressAreaColor); + if (_asciiArea) + { + int linePos = _pxPosAsciiX - (_pxGapHexAscii / 2); + painter.setPen(Qt::gray); + painter.drawLine(linePos - pxOfsX, event->rect().top(), linePos - pxOfsX, height()); + } + + painter.setPen(viewport()->palette().color(QPalette::WindowText)); + + // paint address area + if (_addressArea) + { + QString address; + for (int row=0, pxPosY = _pxCharHeight; row <= (_dataShown.size()/_bytesPerLine); row++, pxPosY +=_pxCharHeight) + { + address = QString("%1").arg(_bPosFirst + row*_bytesPerLine + _addressOffset, _addrDigits, 16, QChar('0')); + painter.drawText(_pxPosAdrX - pxOfsX, pxPosY, address); + } + } + + // paint hex and ascii area + QPen colStandard = QPen(viewport()->palette().color(QPalette::WindowText)); + + painter.setBackgroundMode(Qt::TransparentMode); + + for (int row = 0, pxPosY = pxPosStartY; row <= _rowsShown; row++, pxPosY +=_pxCharHeight) + { + QByteArray hex; + int pxPosX = _pxPosHexX - pxOfsX; + int pxPosAsciiX2 = _pxPosAsciiX - pxOfsX; + qint64 bPosLine = row * _bytesPerLine; + for (int colIdx = 0; ((bPosLine + colIdx) < _dataShown.size() && (colIdx < _bytesPerLine)); colIdx++) + { + QColor c = viewport()->palette().color(QPalette::Base); + painter.setPen(colStandard); + + qint64 posBa = _bPosFirst + bPosLine + colIdx; + if ((getSelectionBegin() <= posBa) && (getSelectionEnd() > posBa)) + { + c = _brushSelection.color(); + painter.setPen(_penSelection); + } + else + { + if (_highlighting) + if (_markedShown.at((int)(posBa - _bPosFirst))) + { + c = _brushHighlighted.color(); + painter.setPen(_penHighlighted); + } + } + + // render hex value + QRect r; + if (colIdx == 0) + r.setRect(pxPosX, pxPosY - _pxCharHeight + _pxSelectionSub, 2*_pxCharWidth, _pxCharHeight); + else + r.setRect(pxPosX - _pxCharWidth, pxPosY - _pxCharHeight + _pxSelectionSub, 3*_pxCharWidth, _pxCharHeight); + painter.fillRect(r, c); + hex = _hexDataShown.mid((bPosLine + colIdx) * 2, 2); + painter.drawText(pxPosX, pxPosY, hexCaps()?hex.toUpper():hex); + pxPosX += 3*_pxCharWidth; + + // render ascii value + if (_asciiArea) + { + int ch = (uchar)_dataShown.at(bPosLine + colIdx); + if ( ch < ' ' || ch > '~' ) + ch = '.'; + r.setRect(pxPosAsciiX2, pxPosY - _pxCharHeight + _pxSelectionSub, _pxCharWidth, _pxCharHeight); + painter.fillRect(r, c); + painter.drawText(pxPosAsciiX2, pxPosY, QChar(ch)); + pxPosAsciiX2 += _pxCharWidth; + } + } + } + painter.setBackgroundMode(Qt::TransparentMode); + painter.setPen(viewport()->palette().color(QPalette::WindowText)); + } + + // _cursorPosition counts in 2, _bPosFirst counts in 1 + int hexPositionInShowData = _cursorPosition - 2 * _bPosFirst; + + // due to scrolling the cursor can go out of the currently displayed data + if ((hexPositionInShowData >= 0) && (hexPositionInShowData < _hexDataShown.size())) + { + // paint cursor + if (_readOnly) + { + // make the background stick out + QColor color = viewport()->palette().dark().color(); + painter.fillRect(QRect(_pxCursorX - pxOfsX, _pxCursorY - _pxCharHeight + _pxSelectionSub, _pxCharWidth, _pxCharHeight), color); + } + else + { + if (_blink && hasFocus()) + painter.fillRect(_cursorRect, this->palette().color(QPalette::WindowText)); + } + + if (_editAreaIsAscii) + { + // every 2 hex there is 1 ascii + int asciiPositionInShowData = hexPositionInShowData / 2; + int ch = (uchar)_dataShown.at(asciiPositionInShowData); + if (ch < ' ' || ch > '~') + ch = '.'; + painter.drawText(_pxCursorX - pxOfsX, _pxCursorY, QChar(ch)); + } + else + { + painter.drawText(_pxCursorX - pxOfsX, _pxCursorY, _hexDataShown.mid(hexPositionInShowData, 1)); + } + } + + // emit event, if size has changed + if (_lastEventSize != _chunks->size()) + { + _lastEventSize = _chunks->size(); + emit currentSizeChanged(_lastEventSize); + } +} + +void QHexEdit::resizeEvent(QResizeEvent *) +{ + if (_dynamicBytesPerLine) + { + int pxFixGaps = 0; + if (_addressArea) + pxFixGaps = addressWidth() * _pxCharWidth + _pxGapAdr; + pxFixGaps += _pxGapAdrHex; + if (_asciiArea) + pxFixGaps += _pxGapHexAscii; + + // +1 because the last hex value do not have space. so it is effective one char more + int charWidth = (viewport()->width() - pxFixGaps ) / _pxCharWidth + 1; + + // 2 hex alfa-digits 1 space 1 ascii per byte = 4; if ascii is disabled then 3 + // to prevent devision by zero use the min value 1 + setBytesPerLine(std::max(charWidth / (_asciiArea ? 4 : 3),1)); + } + adjust(); +} + +bool QHexEdit::focusNextPrevChild(bool next) +{ + if (_addressArea) + { + if ( (next && _editAreaIsAscii) || (!next && !_editAreaIsAscii )) + return QWidget::focusNextPrevChild(next); + else + return false; + } + else + { + return QWidget::focusNextPrevChild(next); + } +} + +// ********************************************************************** Handle selections +void QHexEdit::resetSelection() +{ + _bSelectionBegin = _bSelectionInit; + _bSelectionEnd = _bSelectionInit; +} + +void QHexEdit::resetSelection(qint64 pos) +{ + pos = pos / 2 ; + if (pos < 0) + pos = 0; + if (pos > _chunks->size()) + pos = _chunks->size(); + + _bSelectionInit = pos; + _bSelectionBegin = pos; + _bSelectionEnd = pos; +} + +void QHexEdit::setSelection(qint64 pos) +{ + pos = pos / 2; + if (pos < 0) + pos = 0; + if (pos > _chunks->size()) + pos = _chunks->size(); + + if (pos >= _bSelectionInit) + { + _bSelectionEnd = pos; + _bSelectionBegin = _bSelectionInit; + } + else + { + _bSelectionBegin = pos; + _bSelectionEnd = _bSelectionInit; + } +} + +qint64 QHexEdit::getSelectionBegin() +{ + return _bSelectionBegin; +} + +qint64 QHexEdit::getSelectionEnd() +{ + return _bSelectionEnd; +} + +// ********************************************************************** Private utility functions +void QHexEdit::init() +{ + _undoStack->clear(); + setAddressOffset(0); + resetSelection(0); + setCursorPosition(0); + verticalScrollBar()->setValue(0); + _modified = false; +} + +void QHexEdit::adjust() +{ + // recalc Graphics + if (_addressArea) + { + _addrDigits = addressWidth(); + _pxPosHexX = _pxGapAdr + _addrDigits*_pxCharWidth + _pxGapAdrHex; + } + else + _pxPosHexX = _pxGapAdrHex; + _pxPosAdrX = _pxGapAdr; + _pxPosAsciiX = _pxPosHexX + _hexCharsInLine * _pxCharWidth + _pxGapHexAscii; + + // set horizontalScrollBar() + int pxWidth = _pxPosAsciiX; + if (_asciiArea) + pxWidth += _bytesPerLine*_pxCharWidth; + horizontalScrollBar()->setRange(0, pxWidth - viewport()->width()); + horizontalScrollBar()->setPageStep(viewport()->width()); + + // set verticalScrollbar() + _rowsShown = ((viewport()->height()-4)/_pxCharHeight); + int lineCount = (int)(_chunks->size() / (qint64)_bytesPerLine) + 1; + verticalScrollBar()->setRange(0, lineCount - _rowsShown); + verticalScrollBar()->setPageStep(_rowsShown); + + int value = verticalScrollBar()->value(); + _bPosFirst = (qint64)value * _bytesPerLine; + _bPosLast = _bPosFirst + (qint64)(_rowsShown * _bytesPerLine) - 1; + if (_bPosLast >= _chunks->size()) + _bPosLast = _chunks->size() - 1; + readBuffers(); + setCursorPosition(_cursorPosition); +} + +void QHexEdit::dataChangedPrivate(int) +{ + _modified = _undoStack->index() != 0; + adjust(); + emit dataChanged(); +} + +void QHexEdit::refresh() +{ + ensureVisible(); + readBuffers(); +} + +void QHexEdit::readBuffers() +{ + _dataShown = _chunks->data(_bPosFirst, _bPosLast - _bPosFirst + _bytesPerLine + 1, &_markedShown); + _hexDataShown = QByteArray(_dataShown.toHex()); +} + +QString QHexEdit::toReadable(const QByteArray &ba) +{ + QString result; + + for (int i=0; i < ba.size(); i += 16) + { + QString addrStr = QString("%1").arg(_addressOffset + i, addressWidth(), 16, QChar('0')); + QString hexStr; + QString ascStr; + for (int j=0; j<16; j++) + { + if ((i + j) < ba.size()) + { + hexStr.append(" ").append(ba.mid(i+j, 1).toHex()); + char ch = ba[i + j]; + if ((ch < 0x20) || (ch > 0x7e)) + ch = '.'; + ascStr.append(QChar(ch)); + } + } + result += addrStr + " " + QString("%1").arg(hexStr, -48) + " " + QString("%1").arg(ascStr, -17) + "\n"; + } + return result; } -const QFont & QHexEdit::font() const +void QHexEdit::updateCursor() { - return qHexEdit_p->font(); + if (_blink) + _blink = false; + else + _blink = true; + viewport()->update(_cursorRect); } diff --git a/libs/qhexedit/src/qhexedit.h b/libs/qhexedit/src/qhexedit.h index 5e8617e33..f2fb0e688 100644 --- a/libs/qhexedit/src/qhexedit.h +++ b/libs/qhexedit/src/qhexedit.h @@ -1,36 +1,45 @@ #ifndef QHEXEDIT_H #define QHEXEDIT_H -#include -#if QT_VERSION >= 0x050000 - #include +#include +#include +#include + +#include "chunks.h" +#include "commands.h" + +#ifdef QHEXEDIT_EXPORTS +#define QHEXEDIT_API Q_DECL_EXPORT +#elif QHEXEDIT_IMPORTS +#define QHEXEDIT_API Q_DECL_IMPORT +#else +#define QHEXEDIT_API #endif -#include "qhexedit_p.h" /** \mainpage QHexEdit is a binary editor widget for Qt. -\version Version 0.6.3 -\image html hexedit.png +\version Version 0.8.6 +\image html qhexedit.png */ -/*! QHexEdit is a hex editor widget written in C++ for the Qt (Qt4) framework. +/** QHexEdit is a hex editor widget written in C++ for the Qt (Qt4, Qt5) framework. It is a simple editor for binary data, just like QPlainTextEdit is for text data. There are sip configuration files included, so it is easy to create -bindings for PyQt and you can use this widget also in python. +bindings for PyQt and you can use this widget also in python 2 and 3. QHexEdit takes the data of a QByteArray (setData()) and shows it. You can use the mouse or the keyboard to navigate inside the widget. If you hit the keys (0..9, a..f) you will change the data. Changed data is highlighted and can be accessed via data(). -Normaly QHexEdit works in the overwrite Mode. You can set overwriteMode(false) +Normally QHexEdit works in the overwrite mode. You can set overwrite mode(false) and insert data. In this case the size of data() increases. It is also possible to delete bytes (del or backspace), here the size of data decreases. You can select data with keyboard hits or mouse movements. The copy-key will -copy the selected data into the clipboard. The cut-key copies also but delets +copy the selected data into the clipboard. The cut-key copies also but deletes it afterwards. In overwrite mode, the paste function overwrites the content of the (does not change the length) data. In insert mode, clipboard data will be inserted. The clipboard content is expected in ASCII Hex notation. Unknown @@ -43,55 +52,88 @@ content for the editor. You can search data inside the content with indexOf() and lastIndexOf(). The replace() function is to change located subdata. This 'replaced' data can also be undone by the undo/redo framework. -This widget can only handle small amounts of data. The size has to be below 10 -megabytes, otherwise the scroll sliders ard not shown and you can't scroll any -more. +QHexEdit is based on QIODevice, that's why QHexEdit can handle big amounts of +data. The size of edited data can be more then two gigabytes without any +restrictions. */ - class QHexEdit : public QScrollArea +class QHEXEDIT_API QHexEdit : public QAbstractScrollArea { Q_OBJECT - /*! Property data holds the content of QHexEdit. Call setData() to set the - content of QHexEdit, data() returns the actual content. + + /*! Property address area switch the address area on or off. Set addressArea true + (show it), false (hide it). */ - Q_PROPERTY(QByteArray data READ data WRITE setData) + Q_PROPERTY(bool addressArea READ addressArea WRITE setAddressArea) + + /*! Property address area color sets (setAddressAreaColor()) the background + color of address areas. You can also read the color (addressAreaColor()). + */ + Q_PROPERTY(QColor addressAreaColor READ addressAreaColor WRITE setAddressAreaColor) /*! Property addressOffset is added to the Numbers of the Address Area. - A offset in the address area (left side) is sometimes usefull, whe you show + A offset in the address area (left side) is sometimes useful, whe you show only a segment of a complete memory picture. With setAddressOffset() you set - this property - with addressOffset() you get the actual value. + this property - with addressOffset() you get the current value. */ - Q_PROPERTY(int addressOffset READ addressOffset WRITE setAddressOffset) + Q_PROPERTY(qint64 addressOffset READ addressOffset WRITE setAddressOffset) - /*! Property address area color sets (setAddressAreaColor()) the backgorund - color of address areas. You can also read the color (addressaAreaColor()). + /*! Set and get the minimum width of the address area, width in characters. */ - Q_PROPERTY(QColor addressAreaColor READ addressAreaColor WRITE setAddressAreaColor) + Q_PROPERTY(int addressWidth READ addressWidth WRITE setAddressWidth) - /*! Porperty cursorPosition sets or gets the position of the editor cursor - in QHexEdit. + /*! Switch the ascii area on (true, show it) or off (false, hide it). */ - Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition) + Q_PROPERTY(bool asciiArea READ asciiArea WRITE setAsciiArea) + + /*! Set and get bytes number per line.*/ + Q_PROPERTY(int bytesPerLine READ bytesPerLine WRITE setBytesPerLine) - /*! Property highlighting color sets (setHighlightingColor()) the backgorund + /*! Property cursorPosition sets or gets the position of the editor cursor + in QHexEdit. Every byte in data has two cursor positions: the lower and upper + Nibble. Maximum cursor position is factor two of data.size(). + */ + Q_PROPERTY(qint64 cursorPosition READ cursorPosition WRITE setCursorPosition) + + /*! Property data holds the content of QHexEdit. Call setData() to set the + content of QHexEdit, data() returns the actual content. When calling setData() + with a QByteArray as argument, QHexEdit creates a internal copy of the data + If you want to edit big files please use setData(), based on QIODevice. + */ + Q_PROPERTY(QByteArray data READ data WRITE setData NOTIFY dataChanged) + + /*! That property defines if the hex values looks as a-f if the value is false(default) + or A-F if value is true. + */ + Q_PROPERTY(bool hexCaps READ hexCaps WRITE setHexCaps) + + /*! Property defines the dynamic calculation of bytesPerLine parameter depends of width of widget. + set this property true to avoid horizontal scrollbars and show the maximal possible data. defalut value is false*/ + Q_PROPERTY(bool dynamicBytesPerLine READ dynamicBytesPerLine WRITE setDynamicBytesPerLine) + + /*! Switch the highlighting feature on or of: true (show it), false (hide it). + */ + Q_PROPERTY(bool highlighting READ highlighting WRITE setHighlighting) + + /*! Property highlighting color sets (setHighlightingColor()) the background color of highlighted text areas. You can also read the color (highlightingColor()). */ Q_PROPERTY(QColor highlightingColor READ highlightingColor WRITE setHighlightingColor) - /*! Property selection color sets (setSelectionColor()) the backgorund - color of selected text areas. You can also read the color - (selectionColor()). - */ - Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor) - - /*! Porperty overwrite mode sets (setOverwriteMode()) or gets (overwriteMode()) the mode + /*! Property overwrite mode sets (setOverwriteMode()) or gets (overwriteMode()) the mode in which the editor works. In overwrite mode the user will overwrite existing data. The size of data will be constant. In insert mode the size will grow, when inserting new data. */ Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode) - /*! Porperty readOnly sets (setReadOnly()) or gets (isReadOnly) the mode + /*! Property selection color sets (setSelectionColor()) the background + color of selected text areas. You can also read the color + (selectionColor()). + */ + Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor) + + /*! Property readOnly sets (setReadOnly()) or gets (isReadOnly) the mode in which the editor works. In readonly mode the the user can only navigate through the data and select data; modifying is not possible. This property's default is false. @@ -101,86 +143,119 @@ more. /*! Set the font of the widget. Please use fixed width fonts like Mono or Courier.*/ Q_PROPERTY(QFont font READ font WRITE setFont) - public: /*! Creates an instance of QHexEdit. \param parent Parent widget of QHexEdit. */ - QHexEdit(QWidget *parent = 0); + QHexEdit(QWidget *parent=0); - /*! Returns the index position of the first occurrence - of the byte array ba in this byte array, searching forward from index position - from. Returns -1 if ba could not be found. In addition to this functionality - of QByteArray the cursorposition is set to the end of found bytearray and - it will be selected. + // Access to data of qhexedit + /*! Sets the data of QHexEdit. The QIODevice will be opened just before reading + and closed immediately afterwards. This is to allow other programs to rewrite + the file while editing it. */ - int indexOf(const QByteArray & ba, int from = 0) const; + bool setData(QIODevice &iODevice); - /*! Inserts a byte array. - \param i Index position, where to insert - \param ba byte array, which is to insert - In overwrite mode, the existing data will be overwritten, in insertmode ba will be - inserted and size of data grows. + /*! Gives back the data as a QByteArray starting at position \param pos and + delivering \param count bytes. */ - void insert(int i, const QByteArray & ba); + QByteArray dataAt(qint64 pos, qint64 count=-1); - /*! Inserts a char. - \param i Index position, where to insert - \param ch Char, which is to insert - In overwrite mode, the existing data will be overwritten, in insertmode ba will be - inserted and size of data grows. + /*! Gives back the data into a \param iODevice starting at position \param pos + and delivering \param count bytes. */ - void insert(int i, char ch); + bool write(QIODevice &iODevice, qint64 pos=0, qint64 count=-1); + - /*! Returns the index position of the last occurrence - of the byte array ba in this byte array, searching backwards from index position - from. Returns -1 if ba could not be found. In addition to this functionality - of QByteArray the cursorposition is set to the beginning of found bytearray and - it will be selected. + // Char handling + /*! Inserts a char. + \param pos Index position, where to insert + \param ch Char, which is to insert + The char will be inserted and size of data grows. */ - int lastIndexOf(const QByteArray & ba, int from = 0) const; + void insert(qint64 pos, char ch); /*! Removes len bytes from the content. \param pos Index position, where to remove \param len Amount of bytes to remove - In overwrite mode, the existing bytes will be overwriten with 0x00. */ - void remove(int pos, int len=1); + void remove(qint64 pos, qint64 len=1); - /*! Replaces len bytes from index position pos with the byte array after. + /*! Replaces a char. + \param pos Index position, where to overwrite + \param ch Char, which is to insert + The char will be overwritten and size remains constant. */ - void replace( int pos, int len, const QByteArray & after); + void replace(qint64 pos, char ch); - /*! Gives back a formatted image of the content of QHexEdit + + // ByteArray handling + + /*! Inserts a byte array. + \param pos Index position, where to insert + \param ba QByteArray, which is to insert + The QByteArray will be inserted and size of data grows. */ - QString toReadableString(); + void insert(qint64 pos, const QByteArray &ba); + + /*! Replaces \param len bytes with a byte array \param ba + \param pos Index position, where to overwrite + \param ba QByteArray, which is inserted + \param len count of bytes to overwrite + The data is overwritten and size of data may change. + */ + void replace(qint64 pos, qint64 len, const QByteArray &ba); + + + // Utility functions + /*! Calc cursor position from graphics position + * \param point from where the cursor position should be calculated + * \return Cursor position + */ + qint64 cursorPosition(QPoint point); + + /*! Ensure the cursor to be visbile + */ + void ensureVisible(); + + /*! Find first occurrence of ba in QHexEdit data + * \param ba Data to find + * \param from Point where the search starts + * \return pos if fond, else -1 + */ + qint64 indexOf(const QByteArray &ba, qint64 from); + + /*! Returns if any changes where done on document + * \return true when document is modified else false + */ + bool isModified(); + + /*! Find last occurrence of ba in QHexEdit data + * \param ba Data to find + * \param from Point where the search starts + * \return pos if fond, else -1 + */ + qint64 lastIndexOf(const QByteArray &ba, qint64 from); /*! Gives back a formatted image of the selected content of QHexEdit */ QString selectionToReadableString(); - /*! \cond docNever */ - void setAddressOffset(int offset); - int addressOffset(); - void setCursorPosition(int cusorPos); - int cursorPosition(); - void setData(QByteArray const &data); - QByteArray data(); - void setAddressAreaColor(QColor const &color); - QColor addressAreaColor(); - void setHighlightingColor(QColor const &color); - QColor highlightingColor(); - void setSelectionColor(QColor const &color); - QColor selectionColor(); - void setOverwriteMode(bool); - bool overwriteMode(); - void setReadOnly(bool); - bool isReadOnly(); - const QFont &font() const; - void setFont(const QFont &); - /*! \endcond docNever */ + /*! Return the selected content of QHexEdit as QByteArray + */ + QString selectedData(); + + /*! Set Font of QHexEdit + * \param font + */ + void setFont(const QFont &font); + + /*! Gives back a formatted image of the content of QHexEdit + */ + QString toReadableString(); + public slots: /*! Redoes the last operation. If there is no operation to redo, i.e. @@ -188,26 +263,6 @@ public slots: */ void redo(); - /*! Set the minimum width of the address area. - \param addressWidth Width in characters. - */ - void setAddressWidth(int addressWidth); - - /*! Switch the address area on or off. - \param addressArea true (show it), false (hide it). - */ - void setAddressArea(bool addressArea); - - /*! Switch the ascii area on or off. - \param asciiArea true (show it), false (hide it). - */ - void setAsciiArea(bool asciiArea); - - /*! Switch the highlighting feature on or of. - \param mode true (show it), false (hide it). - */ - void setHighlighting(bool mode); - /*! Undoes the last operation. If there is no operation to undo, i.e. there is no undo step in the undo/redo history, nothing happens. */ @@ -216,24 +271,153 @@ public slots: signals: /*! Contains the address, where the cursor is located. */ - void currentAddressChanged(int address); + void currentAddressChanged(qint64 address); /*! Contains the size of the data to edit. */ - void currentSizeChanged(int size); + void currentSizeChanged(qint64 size); - /*! The signal is emited every time, the data is changed. */ + /*! The signal is emitted every time, the data is changed. */ void dataChanged(); - /*! The signal is emited every time, the overwrite mode is changed. */ + /*! The signal is emitted every time, the overwrite mode is changed. */ void overwriteModeChanged(bool state); + +/*! \cond docNever */ +public: + ~QHexEdit(); + + // Properties + bool addressArea(); + void setAddressArea(bool addressArea); + + QColor addressAreaColor(); + void setAddressAreaColor(const QColor &color); + + qint64 addressOffset(); + void setAddressOffset(qint64 addressArea); + + int addressWidth(); + void setAddressWidth(int addressWidth); + + bool asciiArea(); + void setAsciiArea(bool asciiArea); + + int bytesPerLine(); + void setBytesPerLine(int count); + + qint64 cursorPosition(); + void setCursorPosition(qint64 position); + + QByteArray data(); + void setData(const QByteArray &ba); + + void setHexCaps(const bool isCaps); + bool hexCaps(); + + void setDynamicBytesPerLine(const bool isDynamic); + bool dynamicBytesPerLine(); + + bool highlighting(); + void setHighlighting(bool mode); + + QColor highlightingColor(); + void setHighlightingColor(const QColor &color); + + bool overwriteMode(); + void setOverwriteMode(bool overwriteMode); + + bool isReadOnly(); + void setReadOnly(bool readOnly); + + QColor selectionColor(); + void setSelectionColor(const QColor &color); + +protected: + // Handle events + void keyPressEvent(QKeyEvent *event); + void mouseMoveEvent(QMouseEvent * event); + void mousePressEvent(QMouseEvent * event); + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *); + virtual bool focusNextPrevChild(bool next); +private: + // Handle selections + void resetSelection(qint64 pos); // set selectionStart and selectionEnd to pos + void resetSelection(); // set selectionEnd to selectionStart + void setSelection(qint64 pos); // set min (if below init) or max (if greater init) + qint64 getSelectionBegin(); + qint64 getSelectionEnd(); + + // Private utility functions + void init(); + void readBuffers(); + QString toReadable(const QByteArray &ba); + +private slots: + void adjust(); // recalc pixel positions + void dataChangedPrivate(int idx=0); // emit dataChanged() signal + void refresh(); // ensureVisible() and readBuffers() + void updateCursor(); // update blinking cursor + private: - /*! \cond docNever */ - QHexEditPrivate *qHexEdit_p; - QHBoxLayout *layout; - QScrollArea *scrollArea; + // Name convention: pixel positions start with _px + int _pxCharWidth, _pxCharHeight; // char dimensions (dependend on font) + int _pxPosHexX; // X-Pos of HeaxArea + int _pxPosAdrX; // X-Pos of Address Area + int _pxPosAsciiX; // X-Pos of Ascii Area + int _pxGapAdr; // gap left from AddressArea + int _pxGapAdrHex; // gap between AddressArea and HexAerea + int _pxGapHexAscii; // gap between HexArea and AsciiArea + int _pxCursorWidth; // cursor width + int _pxSelectionSub; // offset selection rect + int _pxCursorX; // current cursor pos + int _pxCursorY; // current cursor pos + + // Name convention: absolute byte positions in chunks start with _b + qint64 _bSelectionBegin; // first position of Selection + qint64 _bSelectionEnd; // end of Selection + qint64 _bSelectionInit; // memory position of Selection + qint64 _bPosFirst; // position of first byte shown + qint64 _bPosLast; // position of last byte shown + qint64 _bPosCurrent; // current position + + // variables to store the property values + bool _addressArea; // left area of QHexEdit + QColor _addressAreaColor; + int _addressWidth; + bool _asciiArea; + qint64 _addressOffset; + int _bytesPerLine; + int _hexCharsInLine; + bool _highlighting; + bool _overwriteMode; + QBrush _brushSelection; + QPen _penSelection; + QBrush _brushHighlighted; + QPen _penHighlighted; + bool _readOnly; + bool _hexCaps; + bool _dynamicBytesPerLine; + + // other variables + bool _editAreaIsAscii; // flag about the ascii mode edited + int _addrDigits; // real no of addressdigits, may be > addressWidth + bool _blink; // help get cursor blinking + QBuffer _bData; // buffer, when setup with QByteArray + Chunks *_chunks; // IODevice based access to data + QTimer _cursorTimer; // for blinking cursor + qint64 _cursorPosition; // absolute position of cursor, 1 Byte == 2 tics + QRect _cursorRect; // physical dimensions of cursor + QByteArray _data; // QHexEdit's data, when setup with QByteArray + QByteArray _dataShown; // data in the current View + QByteArray _hexDataShown; // data in view, transformed to hex + qint64 _lastEventSize; // size, which was emitted last time + QByteArray _markedShown; // marked data in view + bool _modified; // Is any data in editor modified? + int _rowsShown; // lines of text shown + UndoStack * _undoStack; // Stack to store edit actions for undo/redo /*! \endcond docNever */ }; -#endif - +#endif // QHEXEDIT_H diff --git a/libs/qhexedit/src/qhexedit_p.cpp b/libs/qhexedit/src/qhexedit_p.cpp deleted file mode 100644 index 65f5cbbd7..000000000 --- a/libs/qhexedit/src/qhexedit_p.cpp +++ /dev/null @@ -1,866 +0,0 @@ -#include -#if QT_VERSION >= 0x050000 - #include -#endif - -#include "qhexedit_p.h" -#include "commands.h" - -const int HEXCHARS_IN_LINE = 47; -const int GAP_ADR_HEX = 10; -const int GAP_HEX_ASCII = 16; -const int BYTES_PER_LINE = 16; - -QHexEditPrivate::QHexEditPrivate(QScrollArea *parent) : QWidget(parent) -{ - _undoStack = new QUndoStack(this); - - _scrollArea = parent; - _asciiArea = true; - - setOverwriteMode(true); - setCursorPos(0); - setAddressArea(true); - - setAddressWidth(4); - setAddressOffset(0); - setAsciiArea(true); - setHighlighting(true); - setReadOnly(false); - setAddressAreaColor(QColor(0xd4, 0xd4, 0xd4, 0xff)); - setHighlightingColor(QColor(0xff, 0xff, 0x99, 0xff)); - setSelectionColor(QColor(0x6d, 0x9e, 0xff, 0xff)); - setFont(QFont("Courier", 10)); - - _size = 0; - resetSelection(0); - - setFocusPolicy(Qt::StrongFocus); - - connect(&_cursorTimer, SIGNAL(timeout()), this, SLOT(updateCursor())); - _cursorTimer.setInterval(500); - _cursorTimer.start(); -} - -void QHexEditPrivate::setAddressOffset(int offset) -{ - _xData.setAddressOffset(offset); - adjust(); -} - -int QHexEditPrivate::addressOffset() -{ - return _xData.addressOffset(); -} - -void QHexEditPrivate::setData(const QByteArray &data) -{ - _xData.setData(data); - _undoStack->clear(); - adjust(); - setCursorPos(0); -} - -QByteArray QHexEditPrivate::data() -{ - return _xData.data(); -} - -void QHexEditPrivate::setAddressAreaColor(const QColor &color) -{ - _addressAreaColor = color; - update(); -} - -QColor QHexEditPrivate::addressAreaColor() -{ - return _addressAreaColor; -} - -void QHexEditPrivate::setHighlightingColor(const QColor &color) -{ - _highlightingColor = color; - update(); -} - -QColor QHexEditPrivate::highlightingColor() -{ - return _highlightingColor; -} - -void QHexEditPrivate::setSelectionColor(const QColor &color) -{ - _selectionColor = color; - update(); -} - -QColor QHexEditPrivate::selectionColor() -{ - return _selectionColor; -} - -void QHexEditPrivate::setReadOnly(bool readOnly) -{ - _readOnly = readOnly; -} - -bool QHexEditPrivate::isReadOnly() -{ - return _readOnly; -} - -XByteArray & QHexEditPrivate::xData() -{ - return _xData; -} - -int QHexEditPrivate::indexOf(const QByteArray & ba, int from) -{ - if (from > (_xData.data().length() - 1)) - from = _xData.data().length() - 1; - int idx = _xData.data().indexOf(ba, from); - if (idx > -1) - { - int curPos = idx*2; - setCursorPos(curPos + ba.length()*2); - resetSelection(curPos); - setSelection(curPos + ba.length()*2); - ensureVisible(); - } - return idx; -} - -void QHexEditPrivate::insert(int index, const QByteArray & ba) -{ - if (ba.length() > 0) - { - if (_overwriteMode) - { - QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::replace, index, ba, ba.length()); - _undoStack->push(arrayCommand); - emit dataChanged(); - } - else - { - QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::insert, index, ba, ba.length()); - _undoStack->push(arrayCommand); - emit dataChanged(); - } - } -} - -void QHexEditPrivate::insert(int index, char ch) -{ - QUndoCommand *charCommand = new CharCommand(&_xData, CharCommand::insert, index, ch); - _undoStack->push(charCommand); - emit dataChanged(); -} - -int QHexEditPrivate::lastIndexOf(const QByteArray & ba, int from) -{ - from -= ba.length(); - if (from < 0) - from = 0; - int idx = _xData.data().lastIndexOf(ba, from); - if (idx > -1) - { - int curPos = idx*2; - setCursorPos(curPos); - resetSelection(curPos); - setSelection(curPos + ba.length()*2); - ensureVisible(); - } - return idx; -} - -void QHexEditPrivate::remove(int index, int len) -{ - if (len > 0) - { - if (len == 1) - { - if (_overwriteMode) - { - QUndoCommand *charCommand = new CharCommand(&_xData, CharCommand::replace, index, char(0)); - _undoStack->push(charCommand); - emit dataChanged(); - } - else - { - QUndoCommand *charCommand = new CharCommand(&_xData, CharCommand::remove, index, char(0)); - _undoStack->push(charCommand); - emit dataChanged(); - } - } - else - { - QByteArray ba = QByteArray(len, char(0)); - if (_overwriteMode) - { - QUndoCommand *arrayCommand = new ArrayCommand(&_xData, ArrayCommand::replace, index, ba, ba.length()); - _undoStack->push(arrayCommand); - emit dataChanged(); - } - else - { - QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::remove, index, ba, len); - _undoStack->push(arrayCommand); - emit dataChanged(); - } - } - } -} - -void QHexEditPrivate::replace(int index, char ch) -{ - QUndoCommand *charCommand = new CharCommand(&_xData, CharCommand::replace, index, ch); - _undoStack->push(charCommand); - resetSelection(); - emit dataChanged(); -} - -void QHexEditPrivate::replace(int index, const QByteArray & ba) -{ - QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::replace, index, ba, ba.length()); - _undoStack->push(arrayCommand); - resetSelection(); - emit dataChanged(); -} - -void QHexEditPrivate::replace(int pos, int len, const QByteArray &after) -{ - QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::replace, pos, after, len); - _undoStack->push(arrayCommand); - resetSelection(); - emit dataChanged(); -} - -void QHexEditPrivate::setAddressArea(bool addressArea) -{ - _addressArea = addressArea; - adjust(); - - setCursorPos(_cursorPosition); -} - -void QHexEditPrivate::setAddressWidth(int addressWidth) -{ - _xData.setAddressWidth(addressWidth); - - setCursorPos(_cursorPosition); -} - -void QHexEditPrivate::setAsciiArea(bool asciiArea) -{ - _asciiArea = asciiArea; - adjust(); -} - -void QHexEditPrivate::setFont(const QFont &font) -{ - QWidget::setFont(font); - adjust(); -} - -void QHexEditPrivate::setHighlighting(bool mode) -{ - _highlighting = mode; - update(); -} - -void QHexEditPrivate::setOverwriteMode(bool overwriteMode) -{ - _overwriteMode = overwriteMode; -} - -bool QHexEditPrivate::overwriteMode() -{ - return _overwriteMode; -} - -void QHexEditPrivate::redo() -{ - _undoStack->redo(); - emit dataChanged(); - setCursorPos(_cursorPosition); - update(); -} - -void QHexEditPrivate::undo() -{ - _undoStack->undo(); - emit dataChanged(); - setCursorPos(_cursorPosition); - update(); -} - -QString QHexEditPrivate::toRedableString() -{ - return _xData.toRedableString(); -} - - -QString QHexEditPrivate::selectionToReadableString() -{ - return _xData.toRedableString(getSelectionBegin(), getSelectionEnd()); -} - -void QHexEditPrivate::keyPressEvent(QKeyEvent *event) -{ - int charX = (_cursorX - _xPosHex) / _charWidth; - int posX = (charX / 3) * 2 + (charX % 3); - int posBa = (_cursorY / _charHeight) * BYTES_PER_LINE + posX / 2; - - -/*****************************************************************************/ -/* Cursor movements */ -/*****************************************************************************/ - - if (event->matches(QKeySequence::MoveToNextChar)) - { - setCursorPos(_cursorPosition + 1); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToPreviousChar)) - { - setCursorPos(_cursorPosition - 1); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToEndOfLine)) - { - setCursorPos(_cursorPosition | (2 * BYTES_PER_LINE -1)); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToStartOfLine)) - { - setCursorPos(_cursorPosition - (_cursorPosition % (2 * BYTES_PER_LINE))); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToPreviousLine)) - { - setCursorPos(_cursorPosition - (2 * BYTES_PER_LINE)); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToNextLine)) - { - setCursorPos(_cursorPosition + (2 * BYTES_PER_LINE)); - resetSelection(_cursorPosition); - } - - if (event->matches(QKeySequence::MoveToNextPage)) - { - setCursorPos(_cursorPosition + (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE)); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToPreviousPage)) - { - setCursorPos(_cursorPosition - (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE)); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToEndOfDocument)) - { - setCursorPos(_xData.size() * 2); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToStartOfDocument)) - { - setCursorPos(0); - resetSelection(_cursorPosition); - } - -/*****************************************************************************/ -/* Select commands */ -/*****************************************************************************/ - if (event->matches(QKeySequence::SelectAll)) - { - resetSelection(0); - setSelection(2*_xData.size() + 1); - } - if (event->matches(QKeySequence::SelectNextChar)) - { - int pos = _cursorPosition + 1; - setCursorPos(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectPreviousChar)) - { - int pos = _cursorPosition - 1; - setSelection(pos); - setCursorPos(pos); - } - if (event->matches(QKeySequence::SelectEndOfLine)) - { - int pos = _cursorPosition - (_cursorPosition % (2 * BYTES_PER_LINE)) + (2 * BYTES_PER_LINE); - setCursorPos(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectStartOfLine)) - { - int pos = _cursorPosition - (_cursorPosition % (2 * BYTES_PER_LINE)); - setCursorPos(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectPreviousLine)) - { - int pos = _cursorPosition - (2 * BYTES_PER_LINE); - setCursorPos(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectNextLine)) - { - int pos = _cursorPosition + (2 * BYTES_PER_LINE); - setCursorPos(pos); - setSelection(pos); - } - - if (event->matches(QKeySequence::SelectNextPage)) - { - int pos = _cursorPosition + (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE); - setCursorPos(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectPreviousPage)) - { - int pos = _cursorPosition - (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE); - setCursorPos(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectEndOfDocument)) - { - int pos = _xData.size() * 2; - setCursorPos(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectStartOfDocument)) - { - int pos = 0; - setCursorPos(pos); - setSelection(pos); - } - -/*****************************************************************************/ -/* Edit Commands */ -/*****************************************************************************/ -if (!_readOnly) -{ - /* Hex input */ - int key = int(event->text()[0].toLatin1()); - if ((key>='0' && key<='9') || (key>='a' && key <= 'f')) - { - if (getSelectionBegin() != getSelectionEnd()) - { - posBa = getSelectionBegin(); - remove(posBa, getSelectionEnd() - posBa); - setCursorPos(2*posBa); - resetSelection(2*posBa); - } - - // If insert mode, then insert a byte - if (_overwriteMode == false) - if ((charX % 3) == 0) - { - insert(posBa, char(0)); - } - - // Change content - if (_xData.size() > 0) - { - QByteArray hexValue = _xData.data().mid(posBa, 1).toHex(); - if ((charX % 3) == 0) - hexValue[0] = key; - else - hexValue[1] = key; - - replace(posBa, QByteArray().fromHex(hexValue)[0]); - - setCursorPos(_cursorPosition + 1); - resetSelection(_cursorPosition); - } - } - - /* Cut & Paste */ - if (event->matches(QKeySequence::Cut)) - { - QString result = QString(); - for (int idx = getSelectionBegin(); idx < getSelectionEnd(); idx++) - { - result += _xData.data().mid(idx, 1).toHex() + " "; - if ((idx % 16) == 15) - result.append("\n"); - } - remove(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()); - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(result); - setCursorPos(getSelectionBegin()); - resetSelection(getSelectionBegin()); - } - - if (event->matches(QKeySequence::Paste)) - { - QClipboard *clipboard = QApplication::clipboard(); - QByteArray ba = QByteArray().fromHex(clipboard->text().toLatin1()); - insert(_cursorPosition / 2, ba); - setCursorPos(_cursorPosition + 2 * ba.length()); - resetSelection(getSelectionBegin()); - } - - - /* Delete char */ - if (event->matches(QKeySequence::Delete)) - { - if (getSelectionBegin() != getSelectionEnd()) - { - posBa = getSelectionBegin(); - remove(posBa, getSelectionEnd() - posBa); - setCursorPos(2*posBa); - resetSelection(2*posBa); - } - else - { - if (_overwriteMode) - replace(posBa, char(0)); - else - remove(posBa, 1); - } - } - - /* Backspace */ - if ((event->key() == Qt::Key_Backspace) && (event->modifiers() == Qt::NoModifier)) - { - if (getSelectionBegin() != getSelectionEnd()) - { - posBa = getSelectionBegin(); - remove(posBa, getSelectionEnd() - posBa); - setCursorPos(2*posBa); - resetSelection(2*posBa); - } - else - { - if (posBa > 0) - { - if (_overwriteMode) - replace(posBa - 1, char(0)); - else - remove(posBa - 1, 1); - setCursorPos(_cursorPosition - 2); - } - } - } - - /* undo */ - if (event->matches(QKeySequence::Undo)) - { - undo(); - } - - /* redo */ - if (event->matches(QKeySequence::Redo)) - { - redo(); - } - - } - - if (event->matches(QKeySequence::Copy)) - { - QString result = QString(); - for (int idx = getSelectionBegin(); idx < getSelectionEnd(); idx++) - { - result += _xData.data().mid(idx, 1).toHex() + " "; - if ((idx % 16) == 15) - result.append('\n'); - } - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(result); - } - - // Switch between insert/overwrite mode - if ((event->key() == Qt::Key_Insert) && (event->modifiers() == Qt::NoModifier)) - { - _overwriteMode = !_overwriteMode; - setCursorPos(_cursorPosition); - overwriteModeChanged(_overwriteMode); - } - - ensureVisible(); - update(); -} - -void QHexEditPrivate::mouseMoveEvent(QMouseEvent * event) -{ - _blink = false; - update(); - int actPos = cursorPos(event->pos()); - setCursorPos(actPos); - setSelection(actPos); -} - -void QHexEditPrivate::mousePressEvent(QMouseEvent * event) -{ - _blink = false; - update(); - int cPos = cursorPos(event->pos()); - resetSelection(cPos); - setCursorPos(cPos); -} - -void QHexEditPrivate::paintEvent(QPaintEvent *event) -{ - QPainter painter(this); - - // draw some patterns if needed - painter.fillRect(event->rect(), this->palette().color(QPalette::Base)); - if (_addressArea) - painter.fillRect(QRect(_xPosAdr, event->rect().top(), _xPosHex - GAP_ADR_HEX + 2, height()), _addressAreaColor); - if (_asciiArea) - { - int linePos = _xPosAscii - (GAP_HEX_ASCII / 2); - painter.setPen(Qt::gray); - painter.drawLine(linePos, event->rect().top(), linePos, height()); - } - - painter.setPen(this->palette().color(QPalette::WindowText)); - - // calc position - int firstLineIdx = ((event->rect().top()/ _charHeight) - _charHeight) * BYTES_PER_LINE; - if (firstLineIdx < 0) - firstLineIdx = 0; - int lastLineIdx = ((event->rect().bottom() / _charHeight) + _charHeight) * BYTES_PER_LINE; - if (lastLineIdx > _xData.size()) - lastLineIdx = _xData.size(); - int yPosStart = ((firstLineIdx) / BYTES_PER_LINE) * _charHeight + _charHeight; - - // paint address area - if (_addressArea) - { - for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight) - { - QString address = QString("%1") - .arg(lineIdx + _xData.addressOffset(), _xData.realAddressNumbers(), 16, QChar('0')); - painter.drawText(_xPosAdr, yPos, address); - } - } - - // paint hex area - QByteArray hexBa(_xData.data().mid(firstLineIdx, lastLineIdx - firstLineIdx + 1).toHex()); - QBrush highLighted = QBrush(_highlightingColor); - QPen colHighlighted = QPen(this->palette().color(QPalette::WindowText)); - QBrush selected = QBrush(_selectionColor); - QPen colSelected = QPen(Qt::white); - QPen colStandard = QPen(this->palette().color(QPalette::WindowText)); - - painter.setBackgroundMode(Qt::TransparentMode); - - for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight) - { - QByteArray hex; - int xPos = _xPosHex; - for (int colIdx = 0; ((lineIdx + colIdx) < _xData.size() && (colIdx < BYTES_PER_LINE)); colIdx++) - { - int posBa = lineIdx + colIdx; - if ((getSelectionBegin() <= posBa) && (getSelectionEnd() > posBa)) - { - painter.setBackground(selected); - painter.setBackgroundMode(Qt::OpaqueMode); - painter.setPen(colSelected); - } - else - { - if (_highlighting) - { - // hilight diff bytes - painter.setBackground(highLighted); - if (_xData.dataChanged(posBa)) - { - painter.setPen(colHighlighted); - painter.setBackgroundMode(Qt::OpaqueMode); - } - else - { - painter.setPen(colStandard); - painter.setBackgroundMode(Qt::TransparentMode); - } - } - } - - // render hex value - if (colIdx == 0) - { - hex = hexBa.mid((lineIdx - firstLineIdx) * 2, 2); - painter.drawText(xPos, yPos, hex); - xPos += 2 * _charWidth; - } else { - hex = hexBa.mid((lineIdx + colIdx - firstLineIdx) * 2, 2).prepend(" "); - painter.drawText(xPos, yPos, hex); - xPos += 3 * _charWidth; - } - - } - } - painter.setBackgroundMode(Qt::TransparentMode); - painter.setPen(this->palette().color(QPalette::WindowText)); - - // paint ascii area - if (_asciiArea) - { - for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight) - { - int xPosAscii = _xPosAscii; - for (int colIdx = 0; ((lineIdx + colIdx) < _xData.size() && (colIdx < BYTES_PER_LINE)); colIdx++) - { - painter.drawText(xPosAscii, yPos, _xData.asciiChar(lineIdx + colIdx)); - xPosAscii += _charWidth; - } - } - } - - // paint cursor - if (_blink && !_readOnly && hasFocus()) - { - if (_overwriteMode) - painter.fillRect(_cursorX, _cursorY + _charHeight - 2, _charWidth, 2, this->palette().color(QPalette::WindowText)); - else - painter.fillRect(_cursorX, _cursorY, 2, _charHeight, this->palette().color(QPalette::WindowText)); - } - - if (_size != _xData.size()) - { - _size = _xData.size(); - emit currentSizeChanged(_size); - } -} - -void QHexEditPrivate::setCursorPos(int position) -{ - // delete cursor - _blink = false; - update(); - - // cursor in range? - if (_overwriteMode) - { - if (position > (_xData.size() * 2 - 1)) - position = _xData.size() * 2 - 1; - } else { - if (position > (_xData.size() * 2)) - position = _xData.size() * 2; - } - - if (position < 0) - position = 0; - - // calc position - _cursorPosition = position; - _cursorY = (position / (2 * BYTES_PER_LINE)) * _charHeight + 4; - int x = (position % (2 * BYTES_PER_LINE)); - _cursorX = (((x / 2) * 3) + (x % 2)) * _charWidth + _xPosHex; - - // immiadately draw cursor - _blink = true; - update(); - emit currentAddressChanged(_cursorPosition/2); -} - -int QHexEditPrivate::cursorPos(QPoint pos) -{ - int result = -1; - // find char under cursor - if ((pos.x() >= _xPosHex) && (pos.x() < (_xPosHex + HEXCHARS_IN_LINE * _charWidth))) - { - int x = (pos.x() - _xPosHex) / _charWidth; - if ((x % 3) == 0) - x = (x / 3) * 2; - else - x = ((x / 3) * 2) + 1; - int y = ((pos.y() - 3) / _charHeight) * 2 * BYTES_PER_LINE; - result = x + y; - } - return result; -} - -int QHexEditPrivate::cursorPos() -{ - return _cursorPosition; -} - -void QHexEditPrivate::resetSelection() -{ - _selectionBegin = _selectionInit; - _selectionEnd = _selectionInit; -} - -void QHexEditPrivate::resetSelection(int pos) -{ - if (pos < 0) - pos = 0; - pos = pos / 2; - _selectionInit = pos; - _selectionBegin = pos; - _selectionEnd = pos; -} - -void QHexEditPrivate::setSelection(int pos) -{ - if (pos < 0) - pos = 0; - pos = pos / 2; - if (pos >= _selectionInit) - { - _selectionEnd = pos; - _selectionBegin = _selectionInit; - } - else - { - _selectionBegin = pos; - _selectionEnd = _selectionInit; - } -} - -int QHexEditPrivate::getSelectionBegin() -{ - return _selectionBegin; -} - -int QHexEditPrivate::getSelectionEnd() -{ - return _selectionEnd; -} - - -void QHexEditPrivate::updateCursor() -{ - if (_blink) - _blink = false; - else - _blink = true; - update(_cursorX, _cursorY, _charWidth, _charHeight); -} - -void QHexEditPrivate::adjust() -{ - _charWidth = fontMetrics().width(QLatin1Char('9')); - _charHeight = fontMetrics().height(); - - _xPosAdr = 0; - if (_addressArea) - _xPosHex = _xData.realAddressNumbers()*_charWidth + GAP_ADR_HEX; - else - _xPosHex = 0; - _xPosAscii = _xPosHex + HEXCHARS_IN_LINE * _charWidth + GAP_HEX_ASCII; - - // tell QAbstractScollbar, how big we are - setMinimumHeight(((_xData.size()/16 + 1) * _charHeight) + 5); - if(_asciiArea) - setMinimumWidth(_xPosAscii + (BYTES_PER_LINE * _charWidth)); - else - setMinimumWidth(_xPosHex + HEXCHARS_IN_LINE * _charWidth); - - update(); -} - -void QHexEditPrivate::ensureVisible() -{ - // scrolls to cursorx, cusory (which are set by setCursorPos) - // x-margin is 3 pixels, y-margin is half of charHeight - _scrollArea->ensureVisible(_cursorX, _cursorY + _charHeight/2, 3, _charHeight/2 + 2); -} diff --git a/libs/qhexedit/src/qhexedit_p.h b/libs/qhexedit/src/qhexedit_p.h deleted file mode 100644 index ba192b097..000000000 --- a/libs/qhexedit/src/qhexedit_p.h +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef QHEXEDIT_P_H -#define QHEXEDIT_P_H - -/** \cond docNever */ - - -#include -#if QT_VERSION >= 0x050000 - #include -#endif -#include "xbytearray.h" - -class QHexEditPrivate : public QWidget -{ -Q_OBJECT - -public: - QHexEditPrivate(QScrollArea *parent); - - void setAddressAreaColor(QColor const &color); - QColor addressAreaColor(); - - void setAddressOffset(int offset); - int addressOffset(); - - void setCursorPos(int position); - int cursorPos(); - - void setData(QByteArray const &data); - QByteArray data(); - - void setHighlightingColor(QColor const &color); - QColor highlightingColor(); - - void setOverwriteMode(bool overwriteMode); - bool overwriteMode(); - - void setReadOnly(bool readOnly); - bool isReadOnly(); - - void setSelectionColor(QColor const &color); - QColor selectionColor(); - - XByteArray & xData(); - - int indexOf(const QByteArray & ba, int from = 0); - void insert(int index, const QByteArray & ba); - void insert(int index, char ch); - int lastIndexOf(const QByteArray & ba, int from = 0); - void remove(int index, int len=1); - void replace(int index, char ch); - void replace(int index, const QByteArray & ba); - void replace(int pos, int len, const QByteArray & after); - - void setAddressArea(bool addressArea); - void setAddressWidth(int addressWidth); - void setAsciiArea(bool asciiArea); - void setHighlighting(bool mode); - virtual void setFont(const QFont &font); - - void undo(); - void redo(); - - QString toRedableString(); - QString selectionToReadableString(); - -signals: - void currentAddressChanged(int address); - void currentSizeChanged(int size); - void dataChanged(); - void overwriteModeChanged(bool state); - -protected: - void keyPressEvent(QKeyEvent * event); - void mouseMoveEvent(QMouseEvent * event); - void mousePressEvent(QMouseEvent * event); - - void paintEvent(QPaintEvent *event); - - int cursorPos(QPoint pos); // calc cursorpos from graphics position. DOES NOT STORE POSITION - - void resetSelection(int pos); // set selectionStart and selectionEnd to pos - void resetSelection(); // set selectionEnd to selectionStart - void setSelection(int pos); // set min (if below init) or max (if greater init) - int getSelectionBegin(); - int getSelectionEnd(); - - -private slots: - void updateCursor(); - -private: - void adjust(); - void ensureVisible(); - - QColor _addressAreaColor; - QColor _highlightingColor; - QColor _selectionColor; - QScrollArea *_scrollArea; - QTimer _cursorTimer; - QUndoStack *_undoStack; - - XByteArray _xData; // Hält den Inhalt des Hex Editors - - bool _blink; // true: then cursor blinks - bool _renderingRequired; // Flag to store that rendering is necessary - bool _addressArea; // left area of QHexEdit - bool _asciiArea; // medium area - bool _highlighting; // highlighting of changed bytes - bool _overwriteMode; - bool _readOnly; // true: the user can only look and navigate - - int _charWidth, _charHeight; // char dimensions (dpendend on font) - int _cursorX, _cursorY; // graphics position of the cursor - int _cursorPosition; // character positioin in stream (on byte ends in to steps) - int _xPosAdr, _xPosHex, _xPosAscii; // graphics x-position of the areas - - int _selectionBegin; // First selected char - int _selectionEnd; // Last selected char - int _selectionInit; // That's, where we pressed the mouse button - - int _size; -}; - -/** \endcond docNever */ - -#endif - diff --git a/libs/qhexedit/src/xbytearray.cpp b/libs/qhexedit/src/xbytearray.cpp deleted file mode 100644 index 09a04cfeb..000000000 --- a/libs/qhexedit/src/xbytearray.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include "xbytearray.h" - -XByteArray::XByteArray() -{ - _oldSize = -99; - _addressNumbers = 4; - _addressOffset = 0; - -} - -int XByteArray::addressOffset() -{ - return _addressOffset; -} - -void XByteArray::setAddressOffset(int offset) -{ - _addressOffset = offset; -} - -int XByteArray::addressWidth() -{ - return _addressNumbers; -} - -void XByteArray::setAddressWidth(int width) -{ - if ((width >= 0) && (width<=6)) - { - _addressNumbers = width; - } -} - -QByteArray & XByteArray::data() -{ - return _data; -} - -void XByteArray::setData(QByteArray data) -{ - _data = data; - _changedData = QByteArray(data.length(), char(0)); -} - -bool XByteArray::dataChanged(int i) -{ - return bool(_changedData[i]); -} - -QByteArray XByteArray::dataChanged(int i, int len) -{ - return _changedData.mid(i, len); -} - -void XByteArray::setDataChanged(int i, bool state) -{ - _changedData[i] = char(state); -} - -void XByteArray::setDataChanged(int i, const QByteArray & state) -{ - int length = state.length(); - int len; - if ((i + length) > _changedData.length()) - len = _changedData.length() - i; - else - len = length; - _changedData.replace(i, len, state); -} - -int XByteArray::realAddressNumbers() -{ - if (_oldSize != _data.size()) - { - // is addressNumbers wide enought? - QString test = QString("%1") - .arg(_data.size() + _addressOffset, _addressNumbers, 16, QChar('0')); - _realAddressNumbers = test.size(); - } - return _realAddressNumbers; -} - -int XByteArray::size() -{ - return _data.size(); -} - -QByteArray & XByteArray::insert(int i, char ch) -{ - _data.insert(i, ch); - _changedData.insert(i, char(1)); - return _data; -} - -QByteArray & XByteArray::insert(int i, const QByteArray & ba) -{ - _data.insert(i, ba); - _changedData.insert(i, QByteArray(ba.length(), char(1))); - return _data; -} - -QByteArray & XByteArray::remove(int i, int len) -{ - _data.remove(i, len); - _changedData.remove(i, len); - return _data; -} - -QByteArray & XByteArray::replace(int index, char ch) -{ - _data[index] = ch; - _changedData[index] = char(1); - return _data; -} - -QByteArray & XByteArray::replace(int index, const QByteArray & ba) -{ - int len = ba.length(); - return replace(index, len, ba); -} - -QByteArray & XByteArray::replace(int index, int length, const QByteArray & ba) -{ - int len; - if ((index + length) > _data.length()) - len = _data.length() - index; - else - len = length; - _data.replace(index, len, ba.mid(0, len)); - _changedData.replace(index, len, QByteArray(len, char(1))); - return _data; -} - -QChar XByteArray::asciiChar(int index) -{ - char ch = _data[index]; - if ((ch < 0x20) || (ch > 0x7e)) - ch = '.'; - return QChar(ch); -} - -QString XByteArray::toRedableString(int start, int end) -{ - int adrWidth = realAddressNumbers(); - if (_addressNumbers > adrWidth) - adrWidth = _addressNumbers; - if (end < 0) - end = _data.size(); - - QString result; - for (int i=start; i < end; i += 16) - { - QString adrStr = QString("%1").arg(_addressOffset + i, adrWidth, 16, QChar('0')); - QString hexStr; - QString ascStr; - for (int j=0; j<16; j++) - { - if ((i + j) < _data.size()) - { - hexStr.append(" ").append(_data.mid(i+j, 1).toHex()); - ascStr.append(asciiChar(i+j)); - } - } - result += adrStr + " " + QString("%1").arg(hexStr, -48) + " " + QString("%1").arg(ascStr, -17) + "\n"; - } - return result; -} diff --git a/libs/qhexedit/src/xbytearray.h b/libs/qhexedit/src/xbytearray.h deleted file mode 100644 index 2b67c61b8..000000000 --- a/libs/qhexedit/src/xbytearray.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef XBYTEARRAY_H -#define XBYTEARRAY_H - -/** \cond docNever */ - -#include - -/*! XByteArray represents the content of QHexEcit. -XByteArray comprehend the data itself and informations to store if it was -changed. The QHexEdit component uses these informations to perform nice -rendering of the data - -XByteArray also provides some functionality to insert, replace and remove -single chars and QByteArras. Additionally some functions support rendering -and converting to readable strings. -*/ -class XByteArray -{ -public: - explicit XByteArray(); - - int addressOffset(); - void setAddressOffset(int offset); - - int addressWidth(); - void setAddressWidth(int width); - - QByteArray & data(); - void setData(QByteArray data); - - bool dataChanged(int i); - QByteArray dataChanged(int i, int len); - void setDataChanged(int i, bool state); - void setDataChanged(int i, const QByteArray & state); - - int realAddressNumbers(); - int size(); - - QByteArray & insert(int i, char ch); - QByteArray & insert(int i, const QByteArray & ba); - - QByteArray & remove(int pos, int len); - - QByteArray & replace(int index, char ch); - QByteArray & replace(int index, const QByteArray & ba); - QByteArray & replace(int index, int length, const QByteArray & ba); - - QChar asciiChar(int index); - QString toRedableString(int start=0, int end=-1); - -signals: - -public slots: - -private: - QByteArray _data; - QByteArray _changedData; - - int _addressNumbers; // wanted width of address area - int _addressOffset; // will be added to the real addres inside bytearray - int _realAddressNumbers; // real width of address area (can be greater then wanted width) - int _oldSize; // size of data -}; - -/** \endcond docNever */ -#endif // XBYTEARRAY_H diff --git a/libs/qscintilla/ChangeLog b/libs/qscintilla/ChangeLog deleted file mode 100644 index 823e537a7..000000000 --- a/libs/qscintilla/ChangeLog +++ /dev/null @@ -1,5016 +0,0 @@ -2015-04-20 Phil Thompson - - * .hgtags: - Added tag 2.9 for changeset 41ee8162fa81 - [9817b0a7a4f7] [tip] - - * NEWS: - Released as v2.9. - [41ee8162fa81] [2.9] - -2015-04-14 Phil Thompson - - * qt/qsciscintillabase.cpp: - Fixed a problem notifying when focus is lost to another application - widget. - [41734678234e] - -2015-04-06 Phil Thompson - - * qt/qsciscintillabase.cpp: - Fixed a crash when deleting an instance. - [eb936ad1f826] - -2015-04-05 Phil Thompson - - * qt/qsciscintilla.cpp: - Fixed a problem applying a lexer's styles that manifested itself by - the wrong style being applied to line numbers when using a custom - lexer. - [c91009909b8e] - -2015-04-04 Phil Thompson - - * qt/qscintilla_es.qm, qt/qscintilla_es.ts: - Updated Spanish translations from Jaime. - [d94218e7d47d] - - * qt/ScintillaQt.h: - Fixed some header file dependencies. - [f246e863957f] - - * qt/qscintilla_cs.qm, qt/qscintilla_de.qm, qt/qscintilla_de.ts, - qt/qscintilla_es.qm, qt/qscintilla_fr.qm, qt/qscintilla_pt_br.qm: - Updated German translations from Detlev. - [01f3be277e14] - -2015-04-03 Phil Thompson - - * qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_es.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts: - Updated the .ts translation files. - [659fb035d1c4] - -2015-04-02 Phil Thompson - - * qt/qsciapis.cpp: - Fixed a problem displaying call-tips when auto-completion is - enabled. - [82ec45421a3d] - - * NEWS, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, qt/qsciscintilla.h, - qt/qsciscintillabase.h: - Exposed the remaining new features. - [6e84b61268c5] - -2015-04-01 Phil Thompson - - * NEWS, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.h: - Exposing new Scintilla functionality. - [e0965dc46693] - -2015-03-31 Phil Thompson - - * qt/qscilexerverilog.cpp, qt/qscilexerverilog.h: - Enabled the new styling features of QsciLexerVerilog. - [5be65189b15f] - - * NEWS, Python/sip/qscilexercpp.sip, qt/qscilexercpp.cpp, - qt/qscilexercpp.h: - Completed the updates to QsciLexerCPP. - [a8e24b727d82] - - * NEWS, Python/sip/qscilexercpp.sip, Python/sip/qscilexersql.sip, - Python/sip/qscilexerverilog.sip, Python/sip/qscilexervhdl.sip, - Python/sip/qsciscintillabase.sip, qt/qscilexercpp.cpp, - qt/qscilexercpp.h, qt/qscilexersql.cpp, qt/qscilexersql.h, - qt/qscilexerverilog.cpp, qt/qscilexerverilog.h, - qt/qscilexervhdl.cpp, qt/qscilexervhdl.h, qt/qsciscintillabase.h: - Updated existing lexers with new styles. - [768f8ff280e1] - -2015-03-30 Phil Thompson - - * qt/qsciapis.cpp: - Make sure call tips don't include image types. - [d0830816cda4] - - * qt/ScintillaQt.cpp, qt/ScintillaQt.h: - Fixed the horizontal scrollbar issues, particularly with long lines. - [db8501c0803f] - -2015-03-29 Phil Thompson - - * qt/ScintillaQt.cpp: - Updated the paste support. - [42ad3657d52e] - - * qt/ScintillaQt.cpp, qt/ScintillaQt.h, qt/qsciscintillabase.cpp: - Added support for idle processing. - [ff277e910df7] - -2015-03-27 Phil Thompson - - * NEWS: - Updated the NEWS file. - [64766fb4c800] - - * qt/ScintillaQt.cpp, qt/ScintillaQt.h, qt/qsciscintillabase.cpp, - qt/qsciscintillabase.h: - Add support for fine tickers. - [3e9b89430dc0] - -2015-03-26 Phil Thompson - - * Makefile, Python/sip/qsciabstractapis.sip, Python/sip/qsciapis.sip, - Python/sip/qscicommandset.sip, Python/sip/qscilexer.sip, - Python/sip/qscilexeravs.sip, Python/sip/qscilexerbash.sip, - Python/sip/qscilexerbatch.sip, Python/sip/qscilexercmake.sip, - Python/sip/qscilexercoffeescript.sip, Python/sip/qscilexercpp.sip, - Python/sip/qscilexercsharp.sip, Python/sip/qscilexercss.sip, - Python/sip/qscilexercustom.sip, Python/sip/qscilexerd.sip, - Python/sip/qscilexerdiff.sip, Python/sip/qscilexerfortran.sip, - Python/sip/qscilexerfortran77.sip, Python/sip/qscilexerhtml.sip, - Python/sip/qscilexeridl.sip, Python/sip/qscilexerjava.sip, - Python/sip/qscilexerjavascript.sip, Python/sip/qscilexerlua.sip, - Python/sip/qscilexermakefile.sip, Python/sip/qscilexermatlab.sip, - Python/sip/qscilexeroctave.sip, Python/sip/qscilexerpascal.sip, - Python/sip/qscilexerperl.sip, Python/sip/qscilexerpo.sip, - Python/sip/qscilexerpostscript.sip, Python/sip/qscilexerpov.sip, - Python/sip/qscilexerproperties.sip, Python/sip/qscilexerpython.sip, - Python/sip/qscilexerruby.sip, Python/sip/qscilexerspice.sip, - Python/sip/qscilexersql.sip, Python/sip/qscilexertcl.sip, - Python/sip/qscilexertex.sip, Python/sip/qscilexerverilog.sip, - Python/sip/qscilexervhdl.sip, Python/sip/qscilexerxml.sip, - Python/sip/qscilexeryaml.sip, Python/sip/qscimacro.sip, - Python/sip/qscimod3.sip, Python/sip/qscimod4.sip, - Python/sip/qscimod5.sip, Python/sip/qscimodcommon.sip, - Python/sip/qsciscintilla.sip, Python/sip/qsciscintillabase.sip, - build.py, designer-Qt3/designer.pro, designer- - Qt3/qscintillaplugin.cpp, example-Qt3/application.cpp, example- - Qt3/application.h, example-Qt3/application.pro, example- - Qt3/fileopen.xpm, example-Qt3/fileprint.xpm, example- - Qt3/filesave.xpm, example-Qt3/main.cpp, lib/README, lib/README.doc, - lib/qscintilla.dxy, qt/InputMethod.cpp, qt/ListBoxQt.cpp, - qt/PlatQt.cpp, qt/SciClasses.cpp, qt/SciClasses.h, - qt/ScintillaQt.cpp, qt/ScintillaQt.h, qt/qsciabstractapis.cpp, - qt/qsciabstractapis.h, qt/qsciapis.cpp, qt/qsciapis.h, - qt/qscicommandset.cpp, qt/qscicommandset.h, qt/qscilexer.cpp, - qt/qscilexer.h, qt/qscilexeravs.cpp, qt/qscilexeravs.h, - qt/qscilexerbash.cpp, qt/qscilexerbash.h, qt/qscilexerbatch.cpp, - qt/qscilexerbatch.h, qt/qscilexercmake.cpp, qt/qscilexercmake.h, - qt/qscilexercoffeescript.cpp, qt/qscilexercoffeescript.h, - qt/qscilexercpp.cpp, qt/qscilexercpp.h, qt/qscilexercsharp.cpp, - qt/qscilexercsharp.h, qt/qscilexercss.cpp, qt/qscilexercss.h, - qt/qscilexercustom.cpp, qt/qscilexercustom.h, qt/qscilexerd.cpp, - qt/qscilexerd.h, qt/qscilexerdiff.cpp, qt/qscilexerdiff.h, - qt/qscilexerfortran.cpp, qt/qscilexerfortran.h, - qt/qscilexerfortran77.cpp, qt/qscilexerfortran77.h, - qt/qscilexerhtml.cpp, qt/qscilexerhtml.h, qt/qscilexeridl.cpp, - qt/qscilexeridl.h, qt/qscilexerjava.cpp, qt/qscilexerjava.h, - qt/qscilexerjavascript.cpp, qt/qscilexerjavascript.h, - qt/qscilexerlua.cpp, qt/qscilexerlua.h, qt/qscilexermakefile.cpp, - qt/qscilexermakefile.h, qt/qscilexermatlab.cpp, - qt/qscilexermatlab.h, qt/qscilexeroctave.cpp, qt/qscilexeroctave.h, - qt/qscilexerpascal.cpp, qt/qscilexerpascal.h, qt/qscilexerperl.cpp, - qt/qscilexerperl.h, qt/qscilexerpo.cpp, qt/qscilexerpo.h, - qt/qscilexerpostscript.cpp, qt/qscilexerpostscript.h, - qt/qscilexerpov.cpp, qt/qscilexerpov.h, qt/qscilexerproperties.cpp, - qt/qscilexerproperties.h, qt/qscilexerpython.cpp, - qt/qscilexerpython.h, qt/qscilexerruby.cpp, qt/qscilexerruby.h, - qt/qscilexerspice.cpp, qt/qscilexerspice.h, qt/qscilexersql.cpp, - qt/qscilexersql.h, qt/qscilexertcl.cpp, qt/qscilexertcl.h, - qt/qscilexertex.cpp, qt/qscilexertex.h, qt/qscilexerverilog.cpp, - qt/qscilexerverilog.h, qt/qscilexervhdl.cpp, qt/qscilexervhdl.h, - qt/qscilexerxml.cpp, qt/qscilexerxml.h, qt/qscilexeryaml.cpp, - qt/qscilexeryaml.h, qt/qscimacro.cpp, qt/qscimacro.h, - qt/qsciprinter.cpp, qt/qsciscintilla.cpp, qt/qsciscintilla.h, - qt/qsciscintillabase.cpp, qt/qsciscintillabase.h, qt/qscistyle.cpp, - qt/qscistyledtext.h: - Removed all support for Qt3 and PyQt3. - [b33b2f06716e] - - * Python/configure-old.py, Python/configure.py, designer- - Qt4Qt5/designer.pro, example-Qt4Qt5/application.pro, - qt/ScintillaQt.cpp, qt/ScintillaQt.h, qt/qscintilla.pro: - The updated code now compiles. - [35d05076c62f] - - * cocoa/InfoBar.h, cocoa/InfoBar.mm, cocoa/InfoBarCommunicator.h, - cocoa/PlatCocoa.h, cocoa/PlatCocoa.mm, cocoa/QuartzTextLayout.h, - cocoa/QuartzTextStyle.h, cocoa/ScintillaCocoa.h, - cocoa/ScintillaCocoa.mm, cocoa/ScintillaFramework/ScintillaFramework - .xcodeproj/project.pbxproj, cocoa/ScintillaTest/AppController.h, - cocoa/ScintillaTest/ScintillaTest.xcodeproj/project.pbxproj, - cocoa/ScintillaView.h, cocoa/ScintillaView.mm, - cocoa/checkbuildosx.sh, cppcheck.suppress, doc/ScintillaDoc.html, - doc/ScintillaDownload.html, doc/ScintillaHistory.html, - doc/index.html, gtk/Converter.h, gtk/PlatGTK.cxx, - gtk/ScintillaGTK.cxx, gtk/deps.mak, gtk/makefile, - include/Platform.h, include/SciLexer.h, include/Scintilla.h, - include/Scintilla.iface, lexers/LexAbaqus.cxx, lexers/LexAsm.cxx, - lexers/LexBash.cxx, lexers/LexBasic.cxx, lexers/LexBibTeX.cxx, - lexers/LexCPP.cxx, lexers/LexCmake.cxx, lexers/LexCoffeeScript.cxx, - lexers/LexDMAP.cxx, lexers/LexDMIS.cxx, lexers/LexECL.cxx, - lexers/LexEScript.cxx, lexers/LexForth.cxx, lexers/LexFortran.cxx, - lexers/LexGui4Cli.cxx, lexers/LexHTML.cxx, lexers/LexHaskell.cxx, - lexers/LexHex.cxx, lexers/LexKix.cxx, lexers/LexLua.cxx, - lexers/LexMarkdown.cxx, lexers/LexMatlab.cxx, lexers/LexModula.cxx, - lexers/LexMySQL.cxx, lexers/LexOthers.cxx, lexers/LexPS.cxx, - lexers/LexPerl.cxx, lexers/LexRegistry.cxx, lexers/LexRuby.cxx, - lexers/LexRust.cxx, lexers/LexSQL.cxx, lexers/LexScriptol.cxx, - lexers/LexSpecman.cxx, lexers/LexTCL.cxx, lexers/LexTCMD.cxx, - lexers/LexTxt2tags.cxx, lexers/LexVHDL.cxx, lexers/LexVerilog.cxx, - lexers/LexVisualProlog.cxx, lexlib/Accessor.cxx, lexlib/Accessor.h, - lexlib/CharacterCategory.cxx, lexlib/CharacterSet.cxx, - lexlib/LexAccessor.h, lexlib/LexerBase.cxx, lexlib/LexerModule.cxx, - lexlib/LexerModule.h, lexlib/LexerNoExceptions.cxx, - lexlib/LexerSimple.cxx, lexlib/LexerSimple.h, - lexlib/PropSetSimple.cxx, lexlib/SparseState.h, lexlib/StringCopy.h, - lexlib/StyleContext.cxx, lexlib/StyleContext.h, lexlib/SubStyles.h, - lexlib/WordList.cxx, lexlib/WordList.h, lib/README.doc, - qt/qscintilla.pro, scripts/GenerateCaseConvert.py, - scripts/GenerateCharacterCategory.py, scripts/HFacer.py, - scripts/HeaderOrder.txt, scripts/LexGen.py, - scripts/ScintillaData.py, src/AutoComplete.cxx, src/AutoComplete.h, - src/CallTip.cxx, src/CaseConvert.cxx, src/CaseFolder.cxx, - src/Catalogue.cxx, src/CellBuffer.cxx, src/CellBuffer.h, - src/CharClassify.cxx, src/ContractionState.cxx, - src/ContractionState.h, src/Decoration.cxx, src/Decoration.h, - src/Document.cxx, src/Document.h, src/EditModel.cxx, - src/EditModel.h, src/EditView.cxx, src/EditView.h, src/Editor.cxx, - src/Editor.h, src/ExternalLexer.cxx, src/ExternalLexer.h, - src/FontQuality.h, src/Indicator.cxx, src/Indicator.h, - src/KeyMap.cxx, src/KeyMap.h, src/LineMarker.cxx, src/LineMarker.h, - src/MarginView.cxx, src/MarginView.h, src/Partitioning.h, - src/PerLine.cxx, src/PerLine.h, src/PositionCache.cxx, - src/PositionCache.h, src/RESearch.cxx, src/RESearch.h, - src/ScintillaBase.cxx, src/ScintillaBase.h, src/Selection.cxx, - src/Selection.h, src/SplitVector.h, src/Style.cxx, src/Style.h, - src/UniConversion.cxx, src/UniConversion.h, src/ViewStyle.cxx, - src/ViewStyle.h, src/XPM.cxx, src/XPM.h, test/XiteQt.py, - test/XiteWin.py, test/lexTests.py, test/simpleTests.py, - test/unit/LICENSE_1_0.txt, test/unit/README, - test/unit/SciTE.properties, test/unit/catch.hpp, test/unit/makefile, - test/unit/test.mak, test/unit/testCellBuffer.cxx, - test/unit/testCharClassify.cxx, test/unit/testContractionState.cxx, - test/unit/testDecoration.cxx, test/unit/testPartitioning.cxx, - test/unit/testRunStyles.cxx, test/unit/testSparseState.cxx, - test/unit/testSplitVector.cxx, test/unit/testUnicodeFromUTF8.cxx, - test/unit/unitTest.cxx, version.txt, win32/HanjaDic.cxx, - win32/HanjaDic.h, win32/PlatWin.cxx, win32/PlatWin.h, - win32/SciLexer.vcxproj, win32/ScintRes.rc, win32/ScintillaWin.cxx, - win32/deps.mak, win32/makefile, win32/scintilla.mak: - Added the initial import of Scintilla v3.5.4. - [025db9484942] - - * lib/GPL_EXCEPTION.TXT, lib/GPL_EXCEPTION_ADDENDUM.TXT, - lib/LICENSE.GPL2, lib/LICENSE.GPL3, lib/OPENSOURCE-NOTICE.TXT, - qt/qscintilla_ru.qm, qt/qscintilla_ru.ts: - Merged the 2.8-maint branch into the default. - [efe1067a091a] - -2015-03-19 Phil Thompson - - * qt/qsciscintilla.cpp: - Fixed QsciScintilla::clearMarginText(). - [885b972e38df] <2.8-maint> - -2015-02-14 Phil Thompson - - * Makefile, Python/configure.py: - Installing into a virtual env should now work. The internal build - system supports sip5. - [62d128cc92de] <2.8-maint> - -2015-02-08 Phil Thompson - - * Python/configure.py: - Use sip5 if available. - [6f5e4b0dae8f] <2.8-maint> - -2015-01-02 Phil Thompson - - * Python/configure.py, lib/LICENSE.commercial.short, lib/LICENSE.gpl, - lib/LICENSE.gpl.short, qt/InputMethod.cpp: - Updated the copyright notices. - [50b9b459dc48] <2.8-maint> - - * Python/configure-old.py: - Fixed configure-old.py for previews. - [7ff9140391e4] <2.8-maint> - -2014-12-22 Phil Thompson - - * build.py, lib/LICENSE.GPL3, lib/LICENSE.commercial.short, - lib/LICENSE.gpl, lib/LICENSE.gpl.short: - More license tweaks. - [f3e84d697877] <2.8-maint> - - * build.py, lib/GPL_EXCEPTION.TXT, lib/GPL_EXCEPTION_ADDENDUM.TXT, - lib/LICENSE.GPL2, lib/LICENSE.gpl.short, lib/OPENSOURCE-NOTICE.TXT, - lib/README.doc: - Aligned the GPL licensing with Qt. - [aa58ba575cac] <2.8-maint> - -2014-12-21 Phil Thompson - - * lib/LICENSE.commercial: - Updated the commercial license to v4.0. - [fd91beaa78dd] <2.8-maint> - -2014-11-16 Phil Thompson - - * build.py: - A source package now includes a full ChangeLog. - [ba92c1d5c839] <2.8-maint> - -2014-09-11 Phil Thompson - - * .hgtags: - Added tag 2.8.4 for changeset e18756e8cf86 - [e7f7a594518d] <2.8-maint> - - * .hgignore, NEWS: - Released as v2.8.4. - [e18756e8cf86] [2.8.4] <2.8-maint> - -2014-09-04 Phil Thompson - - * NEWS: - Updated the NEWS file. - [e4e3562b54cb] <2.8-maint> - -2014-09-03 Phil Thompson - - * Python/sip/qsciscintilla.sip, Python/sip/qsciscintillabase.sip, - qt/qscintilla.pro, qt/qsciscintilla.cpp, qt/qsciscintilla.h, - qt/qsciscintillabase.h: - Added the missing SCI_SETHOTSPOTSINGLELINE to QsciScintillaBase. - Added resetHotspotForegroundColor(), resetHotspotBackgroundColor(), - setHotspotForegroundColor(), setHotspotBackgroundColor(), - setHotspotUnderline() and setHotspotWrap() to QsciScintilla. - [2da018f7e48c] <2.8-maint> - -2014-07-31 Phil Thompson - - * qt/qsciscintilla.cpp: - Attempted to improve the auto-indentation behaviour so that the - indentation of a line is maintained if a new line has been inserted - above by pressing enter at the start of the line. - [aafc4a7247fb] <2.8-maint> - -2014-07-11 Phil Thompson - - * Python/configure.py: - Fixed the installation of the .api file. - [aae8494847ff] <2.8-maint> - -2014-07-10 Phil Thompson - - * Python/configure.py, designer-Qt4Qt5/designer.pro, - qt/qscintilla.pro: - Fixes to work around QTBUG-39300. Fix when building with a - configuration file. - [1051e8c260fd] <2.8-maint> - -2014-07-03 Phil Thompson - - * .hgtags: - Added tag 2.8.3 for changeset e9cb8530f97f - [bb531051c8f3] <2.8-maint> - - * NEWS: - Released as v2.8.3. - [e9cb8530f97f] [2.8.3] <2.8-maint> - -2014-07-01 Phil Thompson - - * Python/configure.py: - Fixed a cut-and-paste bug in configure.py. - [5f7c4c6c9a29] <2.8-maint> - - * Python/configure.py: - Updated to the latest build system boilerplate. - [ee0b9a647e7a] <2.8-maint> - -2014-06-30 Phil Thompson - - * Makefile, Python/configure.py: - Updates to the build system and the latest boilerplate configure.py. - [8485111172c7] <2.8-maint> - -2014-06-19 Phil Thompson - - * qt/qscilexercoffeescript.cpp, qt/qscintilla.pro, - qt/qscintilla_cs.qm, qt/qscintilla_de.qm, qt/qscintilla_de.ts, - qt/qscintilla_es.qm, qt/qscintilla_es.ts, qt/qscintilla_fr.qm, - qt/qscintilla_pt_br.qm, qt/qscintilla_ru.qm, qt/qscintilla_ru.ts: - Updated CoffeeScript keywords and German translations from Detlev. - Updated Spanish translations from Jaime. Removed the Russian - translations as none were current. - [978fe16935c4] <2.8-maint> - -2014-06-15 Phil Thompson - - * qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_es.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Updated the translation source files. - [440ab56f1863] <2.8-maint> - -2014-06-09 Phil Thompson - - * Python/sip/qscilexercoffeescript.sip, Python/sip/qscimodcommon.sip, - Python/sip/qsciscintillabase.sip: - Added QsciLexerCoffeeScript to the Python bindings. - [36a6e2123a69] <2.8-maint> - - * qt/qscilexercoffeescript.h: - QsciLexerCoffeeScript property setters are no longer virtual slots. - [eef97550eb16] <2.8-maint> - - * qt/qscilexercoffeescript.cpp, qt/qscilexercoffeescript.h, - qt/qscintilla.pro: - Added the QsciLexerCoffeeScript class. - [0cf56e9cd32a] <2.8-maint> - -2014-06-03 Phil Thompson - - * Python/configure.py: - Fixes for Python v2.6. - [9b7b5393f228] <2.8-maint> - -2014-06-01 Phil Thompson - - * Python/configure.py: - Fixed a regression in configure.py when using the -n or -o options. - [f7b1c9821894] <2.8-maint> - -2014-05-29 Phil Thompson - - * qt/PlatQt.cpp, qt/qsciscintillabase.cpp: - Fixes for Qt3. - [4d0a54024b52] <2.8-maint> - - * qt/PlatQt.cpp, qt/qscilexer.cpp, qt/qscintilla.pro, - qt/qsciscintilla.cpp, qt/qscistyle.cpp: - Font sizes are now handled as floating point values rather than - integers. - [ea017cc2b198] <2.8-maint> - -2014-05-26 Phil Thompson - - * .hgtags: - Added tag 2.8.2 for changeset 5aab3ae01e0e - [6cc6eec7c440] <2.8-maint> - - * NEWS: - Released as v2.8.2. - [5aab3ae01e0e] [2.8.2] <2.8-maint> - - * Python/sip/qsciscintillabase.sip: - Updated the sub-class converter code. - [9b276dae576d] <2.8-maint> - - * Makefile: - Internal build system fixes. - [b29b24829b0b] <2.8-maint> - -2014-05-24 Phil Thompson - - * Makefile, Python/configure.py: - Fixed some build regressions with PyQt4. - [175b657ad031] <2.8-maint> - -2014-05-18 Phil Thompson - - * Makefile: - Updates to the top-level Makefile for the latest Android tools. - [405fb3eb5473] <2.8-maint> - -2014-05-17 Phil Thompson - - * Makefile: - Added the PyQt4 against Qt5 on the iPhone simulator build target. - [c31ae5795eec] <2.8-maint> - -2014-05-16 Phil Thompson - - * Makefile, Python/configure.py: - Use the PyQt .sip files in sysroot when cross-compiling. - [5d8e8b8ddfe5] <2.8-maint> - - * Makefile, Python/configure.py: - Replaced pyqt_sip_flags with pyqt_disabled_features in the - configuration file. - [f209403c183b] <2.8-maint> - -2014-05-15 Phil Thompson - - * Makefile, Python/sip/qscimod5.sip: - The PyQt5 bindings now run on the iOS simulator. - [056871b18335] <2.8-maint> - - * Makefile, Python/configure.py: - Building the Python bindings for the iOS simulator now works. - [9dfcea4447b8] <2.8-maint> - - * Makefile: - Updated the main Makefile for the Qt v5.2 iOS support. - [a619fd411878] <2.8-maint> - -2014-05-14 Phil Thompson - - * Python/configure.py: - Don't create the .api file if it isn't going to be installed. - [79db1145e882] <2.8-maint> - -2014-05-12 Phil Thompson - - * Python/configure.py: - Added the --sysroot, --no-sip-files and --no-qsci-api options to - configure.py. - [10642d7deba9] <2.8-maint> - -2014-05-05 Phil Thompson - - * Makefile: - Updated the internal build system for the combined iOS/Android Qt - installation. - [9097d3096b70] <2.8-maint> - -2014-05-04 Phil Thompson - - * qt/qscintilla_de.qm, qt/qscintilla_de.ts: - Updated German translations from Detlev. - [d4f631ee3aaf] <2.8-maint> - - * qt/qscintilla_es.qm, qt/qscintilla_es.ts: - Updated Spanish translations from Jaime Seuma. - [51350008c8a4] <2.8-maint> - -2014-04-30 Phil Thompson - - * qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_es.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Updated the .ts files. - [4c5f88b22952] <2.8-maint> - -2014-04-29 Phil Thompson - - * Python/sip/qscilexerpo.sip, Python/sip/qscimodcommon.sip, - qt/qscilexerpo.cpp, qt/qscilexerpo.h, qt/qscintilla.pro: - Added the QsciLexerPO class. - [d42e44550d80] <2.8-maint> - - * Python/sip/qscilexeravs.sip, Python/sip/qscimodcommon.sip, - qt/qscilexeravs.cpp, qt/qscilexeravs.h, qt/qscintilla.pro: - Added the QsciLexerAVS class. - [ed6edb6ec205] <2.8-maint> - -2014-04-27 Phil Thompson - - * Python/configure.py: - Fixes for the refactored configure.py. - [21b9fa66338e] <2.8-maint> - - * Python/configure.py: - Initial refactoring of configure.py so that it is implemented as - configurable (and reusable) boilerplate. - [615d75a88db9] <2.8-maint> - -2014-04-24 Phil Thompson - - * Python/sip/qsciscintilla.sip, qt/qscintilla.pro, - qt/qsciscintilla.cpp, qt/qsciscintilla.h: - setEnabled() now implements the expected visual effects. - [3e4254394b08] <2.8-maint> - -2014-03-22 Phil Thompson - - * Python/configure.py: - Fixed the handling of the --pyqt-sip-flags option. Restored the - specification of the Python library directory for Windows. - [3ea496d62b9f] <2.8-maint> - - * Python/configure.py, qt/features/qscintilla2.prf, qt/qscintilla.pro: - Added the --pyqt-sip-flags to configure.py to avoid having to - introspect PyQt. Fixed the .prf file for OS/X. Tweaks to - configure.py so that a configuration file will use the same names as - PyQt5. - [77ff3a21d00a] <2.8-maint> - -2014-03-21 Phil Thompson - - * Makefile, lib/README.doc, qt/qscintilla.pro: - Changes to the .pro file to build a static library without having to - edit it. - [f82637449276] <2.8-maint> - -2014-03-17 Phil Thompson - - * qt/PlatQt.cpp, qt/qsciscintillabase.cpp: - Fixed building against Qt v5.0.x. - [d68e28068b67] <2.8-maint> - -2014-03-14 Phil Thompson - - * .hgtags: - Added tag 2.8.1 for changeset 6bb7ab27c958 - [dfd473e8336b] <2.8-maint> - - * NEWS: - Released as v2.8.1. - [6bb7ab27c958] [2.8.1] <2.8-maint> - - * qt/SciClasses.cpp: - Fixed the display of UTF-8 call tips. - [3f0ca7ba60a0] <2.8-maint> - -2014-03-12 Phil Thompson - - * qsci/api/python/Python-3.4.api: - Added the .api file for Python v3.4. - [3db067b6dcec] <2.8-maint> - -2014-03-05 Phil Thompson - - * qt/PlatQt.cpp: - Revised attempt at the outline of alpha rectangles in case Qt ignore - the alpha of the pen. - [86ab8898503e] <2.8-maint> - - * qt/PlatQt.cpp: - Fixed the setting of the pen when drawing alpha rectangles. - [3f4ff2e8aca3] <2.8-maint> - -2014-02-09 Phil Thompson - - * Python/configure.py: - The Python module now has the correct install name on OS/X. - [eec8c704418a] <2.8-maint> - -2014-02-04 Phil Thompson - - * qt/qscicommand.cpp, qt/qscicommand.h, qt/qsciscintillabase.cpp, - qt/qsciscintillabase.h: - Fixed a problem entering non-ASCII characters that clashed with - Scintilla's SCK_* values. Key_Enter, Key_Backtab, Key_Super_L, - Key_Super_R and Key_Menu are now valid QsciCommand keys. - [94aec4f075df] <2.8-maint> - -2014-01-31 Phil Thompson - - * qt/qsciscintilla.cpp: - Make sure the editor is active after a selection of a user list - entry. - [e0f2106777d0] <2.8-maint> - -2014-01-23 Phil Thompson - - * qt/SciClasses.cpp: - On Linux, single clicking on an item in an auto-completion list now - just selects the itemm (rather than inserting the item) to be - consistent with other platforms. - [d916bbbf6517] <2.8-maint> - - * qt/qsciscintillabase.cpp: - Fix the handling of the auto-completion list when losing focus. - [a67b51ac8611] <2.8-maint> - -2014-01-22 Phil Thompson - - * qt/InputMethod.cpp, qt/qsciscintillabase.cpp: - Fixed building against Qt4. - [bf0a5f984fc1] <2.8-maint> - -2014-01-19 Phil Thompson - - * NEWS: - Updated the NEWS file. - [da2a76da712e] <2.8-maint> - -2014-01-18 Phil Thompson - - * qt/InputMethod.cpp: - Another attempt to fix input events on losing focus. - [6de3ab62fade] <2.8-maint> - - * lib/README.doc: - Added the qmake integration section to the docs. - [2918e4760c36] <2.8-maint> - -2014-01-07 Phil Thompson - - * Makefile: - Added Android to the internal build system. - [3be74b3e89e9] <2.8-maint> - -2014-01-06 Phil Thompson - - * qt/InputMethod.cpp, qt/qsciscintillabase.cpp: - Newlines can now be entered on iOS. - [8d23447dbd4d] <2.8-maint> - -2014-01-05 Phil Thompson - - * qt/InputMethod.cpp: - See if we can detect a input methdo event generated when losing - focus and not to clear the selection. - [8e4216289efe] <2.8-maint> - -2014-01-04 Phil Thompson - - * Python/sip/qsciprinter.sip: - The Python bindings now respect the PyQt_Printer feature. - [c3106f715803] <2.8-maint> - -2014-01-03 Phil Thompson - - * qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Added support for software input panels with Qt v5. - [d4499b61ff04] <2.8-maint> - - * qt/qsciscintilla.cpp: - Disable input methods when read-only (rather than non-UTF8) to be - consistent with Qt. - [f8817d4a47e3] <2.8-maint> - - * qt/qscintilla.pro, qt/qsciprinter.h: - Fixed the .pro file so that QT_NO_PRINTER is set properly and - removed the workaround. - [b5a6709d814a] <2.8-maint> - -2014-01-02 Phil Thompson - - * qt/PlatQt.cpp: - Finally fixed buffered drawing on retina displays. - [f8d23103df70] <2.8-maint> - - * qt/PlatQt.cpp, qt/qsciscintillabase.cpp: - Fixes for buffered drawing on retina displays. (Not yet correct, but - close.) - [a3b36be44112] <2.8-maint> - - * Makefile: - Changed the build system for the example on the iOS simulator so - that qmake is only used to generate the .xcodeproj file. - [179dbf5ba385] <2.8-maint> - - * Makefile: - Added the building of the example to the main Makefile. - [aec2ac3ac591] <2.8-maint> - - * Makefile: - Added iOS simulator targets to the build system. - [72af8241b261] <2.8-maint> - - * Makefile, build.py, lib/LICENSE.GPL2, lib/LICENSE.GPL3, - lib/LICENSE.commercial.short, lib/LICENSE.gpl.short, - qt/InputMethod.cpp: - Updated copyright notices. - [f21e016499fe] <2.8-maint> - - * qt/MacPasteboardMime.cpp, qt/qsciprinter.cpp, qt/qsciprinter.h, - qt/qsciscintillabase.cpp: - Fixes for building for iOS. - [46d25e648b4a] <2.8-maint> - -2013-12-31 Phil Thompson - - * Python/configure.py, build.py, designer-Qt4Qt5/designer.pro, - example-Qt4Qt5/application.pro, lib/README.doc, - qt/features/qscintilla2.prf, qt/qscintilla.pro: - Implemented the qscintilla2.prf feature file and updated everything - to use it. - [c3bfef1a55ad] <2.8-maint> - -2013-12-29 Phil Thompson - - * qt/ScintillaQt.h: - Added some additional header file dependencies. - [7ec67eced9de] <2.8-maint> - -2013-12-21 Phil Thompson - - * qt/MacPasteboardMime.cpp, qt/ScintillaQt.cpp: - Fixes for building against Qt3. - [f25cbda736fd] <2.8-maint> - -2013-12-16 Phil Thompson - - * designer-Qt4Qt5/designer.pro, example-Qt4Qt5/application.pro: - Updated the plugin and example .pro files to work around the qmake - incompatibilities introduced in Qt v5.2.0. - [a14729b2702d] <2.8-maint> - -2013-12-15 Phil Thompson - - * qt/qsciscintillabase.cpp: - Fixed the previous fix. - [6c322fa1b20f] <2.8-maint> - -2013-12-14 Phil Thompson - - * qt/PlatQt.cpp, qt/qsciscintillabase.cpp: - Backed out the attempted fix for retina displays at it needs more - work. As a workaround buffered writes are disabled if a retina - display is detected. - [a1f648d1025e] <2.8-maint> - -2013-12-13 Phil Thompson - - * qt/qscintilla.pro: - Enabled exceptions in the .pro file. - [6e07131f6741] <2.8-maint> - -2013-12-12 Phil Thompson - - * qt/PlatQt.cpp: - Create pixmaps for buffered drawing using the same pixel ratio as - the actual device. - [f4f706006071] <2.8-maint> - -2013-12-09 Phil Thompson - - * qt/qscilexeroctave.cpp: - Updated the keywords defined for the Octave lexer. - [9ccf1c74f266] <2.8-maint> - -2013-12-06 Phil Thompson - - * qt/ScintillaQt.cpp: - More scrollbar fixes. - [194a2142c9b6] <2.8-maint> - -2013-12-05 Phil Thompson - - * qt/ScintillaQt.cpp, qt/qscintilla.pro: - Fixes to the scrollbar visibility handling. - [5e8a96258ab0] <2.8-maint> - -2013-12-04 Phil Thompson - - * qt/PlatQt.cpp: - Fixed the implementation of SurfaceImpl::LogPixelsY() (even though - it is never called). - [9ef0387cfc08] <2.8-maint> - -2013-11-08 Phil Thompson - - * .hgtags: - Added tag 2.8 for changeset 562785a5f685 - [fc52bfaa75c4] - - * NEWS: - Released as v2.8. - [562785a5f685] [2.8] - -2013-11-05 Phil Thompson - - * qt/qscintilla_es.qm, qt/qscintilla_es.ts: - Updated Spanish translations from Jaime Seuma. - [e7a128a28157] - -2013-11-04 Phil Thompson - - * NEWS, Python/sip/qsciscintillabase.sip, qt/ScintillaQt.cpp, - qt/qscilexerpascal.cpp, qt/qsciscintillabase.h: - Added support for the new v3.3.6 features to the low-level API. - [e553c1263387] - - * Makefile, NEWS, cocoa/Framework.mk, cocoa/InfoBar.mm, - cocoa/PlatCocoa.mm, cocoa/SciTest.mk, cocoa/ScintillaCocoa.h, - cocoa/ScintillaCocoa.mm, cocoa/ScintillaFramework/ScintillaFramework - .xcodeproj/project.pbxproj, cocoa/ScintillaView.h, - cocoa/ScintillaView.mm, cocoa/checkbuildosx.sh, cocoa/common.mk, - doc/ScintillaDoc.html, doc/ScintillaDownload.html, - doc/ScintillaHistory.html, doc/index.html, gtk/PlatGTK.cxx, - gtk/ScintillaGTK.cxx, gtk/makefile, include/ILexer.h, - include/Platform.h, include/SciLexer.h, include/Scintilla.h, - include/Scintilla.iface, lexers/LexCPP.cxx, - lexers/LexCoffeeScript.cxx, lexers/LexOthers.cxx, - lexers/LexPascal.cxx, lexers/LexPerl.cxx, lexers/LexRust.cxx, - lexers/LexSQL.cxx, lexers/LexVisualProlog.cxx, - lexlib/StyleContext.h, lexlib/SubStyles.h, lexlib/WordList.cxx, - lib/README.doc, qt/qscintilla.pro, src/Catalogue.cxx, - src/Document.cxx, src/Editor.cxx, src/ScintillaBase.cxx, - src/ScintillaBase.h, src/ViewStyle.cxx, src/ViewStyle.h, - test/XiteQt.py, test/simpleTests.py, version.txt, win32/PlatWin.cxx, - win32/ScintRes.rc, win32/ScintillaWin.cxx, win32/makefile, - win32/scintilla.mak: - Merged Scintilla v3.3.6. - [ada0941dec52] - -2013-10-07 Phil Thompson - - * qt/qscintilla_de.qm, qt/qscintilla_de.ts: - Updated German translations from Detlev. - [6c0af6af651c] - - * Makefile, build.py, qt/MacPasteboardMime.cpp, qt/qscintilla.pro, - qt/qsciscintillabase.cpp: - Reinstated support for rectangular selections on OS/X for Qt v5.2 - and later. - [dbfdf7be4793] - -2013-10-04 Phil Thompson - - * qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_es.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Updated the translation source files. - [7ed4bf7ed4e7] - - * qt/qscilexercpp.cpp: - Added missing descriptions to the C++ lexer settings. - [55d7627bb129] - -2013-10-01 Phil Thompson - - * designer-Qt4Qt5/designer.pro, example-Qt4Qt5/application.pro: - Fixed the building of the Designer plugin and the example for OS/X. - [a67f71b06d3c] - - * NEWS, Python/sip/qsciscintillabase.sip, qt/InputMethod.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.h: - Added the remaining non-provisional Scintilla v3.3.5 features to the - low-level API. - [4e8d0b46ebc0] - - * qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_es.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Updated the translation source files. - [4beefc0d95ec] - - * NEWS, Python/sip/qscilexercpp.sip, Python/sip/qsciscintillabase.sip, - qt/qscilexercpp.cpp, qt/qscilexercpp.h, qt/qsciscintillabase.h: - Updated the lexers for Scintilla v3.3.5. - [fc901a2a491f] - -2013-09-30 Phil Thompson - - * Python/configure-old.py, Python/configure.py, README, - cocoa/InfoBar.mm, cocoa/PlatCocoa.mm, cocoa/ScintillaCocoa.h, - cocoa/ScintillaCocoa.mm, cocoa/ScintillaFramework/ScintillaFramework - .xcodeproj/project.pbxproj, cocoa/ScintillaTest/AppController.mm, - cocoa/ScintillaTest/English.lproj/MainMenu.xib, - cocoa/ScintillaView.h, cocoa/ScintillaView.mm, cppcheck.suppress, - delbin.bat, designer-Qt4Qt5/designer.pro, doc/Lexer.txt, - doc/ScintillaDoc.html, doc/ScintillaDownload.html, - doc/ScintillaHistory.html, doc/ScintillaRelated.html, - doc/ScintillaToDo.html, doc/index.html, example- - Qt4Qt5/application.pro, gtk/Converter.h, gtk/PlatGTK.cxx, - gtk/ScintillaGTK.cxx, gtk/deps.mak, gtk/makefile, include/Face.py, - include/HFacer.py, include/ILexer.h, include/Platform.h, - include/SciLexer.h, include/Scintilla.h, include/Scintilla.iface, - lexers/LexA68k.cxx, lexers/LexAU3.cxx, lexers/LexAVE.cxx, - lexers/LexAda.cxx, lexers/LexAsm.cxx, lexers/LexAsn1.cxx, - lexers/LexBash.cxx, lexers/LexBullant.cxx, lexers/LexCOBOL.cxx, - lexers/LexCPP.cxx, lexers/LexCoffeeScript.cxx, lexers/LexConf.cxx, - lexers/LexCrontab.cxx, lexers/LexCsound.cxx, lexers/LexD.cxx, - lexers/LexECL.cxx, lexers/LexForth.cxx, lexers/LexGAP.cxx, - lexers/LexGui4Cli.cxx, lexers/LexHTML.cxx, lexers/LexHaskell.cxx, - lexers/LexInno.cxx, lexers/LexKVIrc.cxx, lexers/LexLaTeX.cxx, - lexers/LexLisp.cxx, lexers/LexLout.cxx, lexers/LexLua.cxx, - lexers/LexMMIXAL.cxx, lexers/LexMPT.cxx, lexers/LexMSSQL.cxx, - lexers/LexMatlab.cxx, lexers/LexModula.cxx, lexers/LexMySQL.cxx, - lexers/LexNsis.cxx, lexers/LexOpal.cxx, lexers/LexOthers.cxx, - lexers/LexPO.cxx, lexers/LexPerl.cxx, lexers/LexPowerShell.cxx, - lexers/LexPython.cxx, lexers/LexR.cxx, lexers/LexRuby.cxx, - lexers/LexSTTXT.cxx, lexers/LexScriptol.cxx, lexers/LexSpice.cxx, - lexers/LexTCMD.cxx, lexers/LexYAML.cxx, lexlib/Accessor.cxx, - lexlib/Accessor.h, lexlib/CharacterCategory.cxx, - lexlib/CharacterCategory.h, lexlib/CharacterSet.cxx, - lexlib/LexAccessor.h, lexlib/LexerBase.cxx, lexlib/LexerModule.cxx, - lexlib/LexerNoExceptions.cxx, lexlib/LexerNoExceptions.h, - lexlib/LexerSimple.cxx, lexlib/OptionSet.h, - lexlib/PropSetSimple.cxx, lexlib/PropSetSimple.h, - lexlib/StyleContext.cxx, lexlib/StyleContext.h, lexlib/SubStyles.h, - lexlib/WordList.cxx, lexlib/WordList.h, lib/README.doc, - qt/ScintillaQt.cpp, qt/ScintillaQt.h, qt/qscintilla.pro, - qt/qsciscintillabase.cpp, scripts/Face.py, scripts/FileGenerator.py, - scripts/GenerateCaseConvert.py, - scripts/GenerateCharacterCategory.py, scripts/HFacer.py, - scripts/LexGen.py, scripts/ScintillaData.py, src/AutoComplete.cxx, - src/AutoComplete.h, src/CallTip.cxx, src/CallTip.h, - src/CaseConvert.cxx, src/CaseConvert.h, src/CaseFolder.cxx, - src/CaseFolder.h, src/Catalogue.cxx, src/CellBuffer.cxx, - src/CellBuffer.h, src/ContractionState.cxx, src/Decoration.cxx, - src/Decoration.h, src/Document.cxx, src/Document.h, src/Editor.cxx, - src/Editor.h, src/ExternalLexer.cxx, src/FontQuality.h, - src/Indicator.cxx, src/KeyMap.cxx, src/KeyMap.h, src/LexGen.py, - src/LineMarker.cxx, src/LineMarker.h, src/Partitioning.h, - src/PerLine.cxx, src/PerLine.h, src/PositionCache.cxx, - src/PositionCache.h, src/RESearch.cxx, src/RESearch.h, - src/RunStyles.cxx, src/RunStyles.h, src/SVector.h, - src/ScintillaBase.cxx, src/ScintillaBase.h, src/Selection.cxx, - src/SplitVector.h, src/Style.cxx, src/Style.h, - src/UniConversion.cxx, src/UniConversion.h, src/UnicodeFromUTF8.h, - src/ViewStyle.cxx, src/ViewStyle.h, src/XPM.cxx, src/XPM.h, - test/README, test/ScintillaCallable.py, test/XiteQt.py, - test/XiteWin.py, test/examples/x.lua, test/examples/x.lua.styled, - test/examples/x.pl, test/examples/x.pl.styled, test/examples/x.rb, - test/examples/x.rb.styled, test/lexTests.py, - test/performanceTests.py, test/simpleTests.py, - test/unit/testCharClassify.cxx, test/unit/testContractionState.cxx, - test/unit/testPartitioning.cxx, test/unit/testRunStyles.cxx, - test/unit/testSplitVector.cxx, version.txt, win32/PlatWin.cxx, - win32/PlatWin.h, win32/ScintRes.rc, win32/ScintillaWin.cxx, - win32/deps.mak, win32/makefile, win32/scintilla.mak, - win32/scintilla_vc6.mak: - Initial merge of Scintilla v3.3.5. - [40933b62f5ed] - -2013-09-14 Phil Thompson - - * Python/configure-ng.py, Python/configure.py, designer- - Qt4/designer.pro, designer-Qt4/qscintillaplugin.cpp, designer- - Qt4/qscintillaplugin.h: - Merged the 2.7-maint branch with the trunk. - [7288d97c54b0] - -2013-08-17 Phil Thompson - - * Python/sip/qsciscintillabase.sip: - Fixed a missing const in the .sip files. - [8b0425b87953] <2.7-maint> - -2013-06-27 Phil Thompson - - * NEWS, Python/configure-old.py, Python/configure.py, - Python/sip/qsciscintillabase.sip, designer-Qt4Qt5/designer.pro, - example-Qt4Qt5/application.pro, qt/InputMethod.cpp, - qt/qscintilla.pro, qt/qsciscintilla.cpp, qt/qsciscintilla.h, - qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Added support for input methods. - [b97af619044b] <2.7-maint> - -2013-06-16 Phil Thompson - - * .hgtags: - Added tag 2.7.2 for changeset 9ecd14550589 - [2b1f187f29c6] <2.7-maint> - - * NEWS: - Released as v2.7.2. - [9ecd14550589] [2.7.2] <2.7-maint> - -2013-06-12 Phil Thompson - - * Python/configure.py: - Fixed a configure.py bug. - [cb062c6f9189] <2.7-maint> - -2013-05-07 Phil Thompson - - * Makefile, Python/configure.py: - Fixes for the PyQt5 support. - [0714ef531ead] <2.7-maint> - - * Makefile, NEWS, Python/configure.py, Python/sip/qscimod5.sip, - lib/README.doc: - Added support for building against PyQt5. - [c982ff1b86f7] <2.7-maint> - -2013-05-05 Phil Thompson - - * build.py: - Changed the format of the name of a snapshot to match other - packages. - [d1f87bbc8377] <2.7-maint> - -2013-05-04 Phil Thompson - - * qt/PlatQt.cpp: - Significantly improved the performance of measuring the width of - text so that very long lines (100,000 characters) can be handled. - [5c88dc344f69] <2.7-maint> - -2013-04-08 Phil Thompson - - * Python/configure.py: - configure.py now issues a more explicit error message if QtCore - cannot be imported. - [4d0097b1ff05] <2.7-maint> - - * Python/configure.py: - Fixed a qmake warning message from configure.py. - [2363c96edeb0] <2.7-maint> - -2013-04-02 Phil Thompson - - * qt/qsciscintilla.cpp, qt/qsciscintilla.h: - The default EOL mode on OS/X is now EolUnix. Clarified the - documentation for EolMode. - [a436460d0300] <2.7-maint> - -2013-03-15 Phil Thompson - - * Python/configure.py: - Further fixes for configure.py. - [78fa6fef2c76] <2.7-maint> - -2013-03-13 Phil Thompson - - * qt/qscilexer.h: - Clarified the description of QSciLexer::description(). - [688b482379e3] <2.7-maint> - - * Python/configure.py: - Fixed the last (trivial) change. - [0a3494ba669a] <2.7-maint> - -2013-03-12 Phil Thompson - - * Python/configure.py: - configure.py now gives the user more information about the copy of - sip being used. - [5c3be581d62b] <2.7-maint> - -2013-03-07 Phil Thompson - - * Python/configure.py: - On OS/X configure.py will explicitly set the qmake spec to macx-g++ - (Qt4) or macx-clang (Qt5) if the default might be macx-xcode. Added - the --spec option to configure.py. - [36a9bf2fbebd] <2.7-maint> - -2013-03-05 Phil Thompson - - * Python/configure.py: - Minor cosmetic tweaks to configure.py. - [296cd10747b7] <2.7-maint> - - * qt/PlatQt.cpp, qt/SciClasses.cpp, qt/qscicommandset.cpp, - qt/qscintilla.pro, qt/qsciscintillabase.cpp: - Removed the remaining uses of Q_WS_* for Qt v5. - [7fafd5c09eea] <2.7-maint> - -2013-03-01 Phil Thompson - - * .hgtags: - Added tag 2.7.1 for changeset 2583dc3dbc8d - [0674c291eab4] <2.7-maint> - - * NEWS: - Released as v2.7.1. - [2583dc3dbc8d] [2.7.1] <2.7-maint> - -2013-02-28 Phil Thompson - - * lexlib/CharacterSet.h: - Re-applied a fix to the underlying code thay got lost when Scintilla - v3.23 was merged. - [ee9eeec7d796] <2.7-maint> - -2013-02-26 Phil Thompson - - * qt/qsciapis.cpp: - A fix for the regression introduced with the previous fix. - [154428cebb5e] <2.7-maint> - -2013-02-19 Phil Thompson - - * NEWS, qt/qsciapis.cpp, qt/qscintilla.pro: - Fixed an autocompletion bug where there are entries Foo.* and - FooBar. - [620d72d86980] <2.7-maint> - -2013-02-06 Phil Thompson - - * Python/configure.py: - configure.py fixes for Linux. - [031b5b767926] <2.7-maint> - - * Python/configure.py: - Added the --sip-incdir and --pyqt-sipdir options to configure.py and - other fixes for building on Windows. - [517a3d0243fd] <2.7-maint> - - * Makefile, NEWS: - Updated the NEWS file. - [eb00e08e1950] <2.7-maint> - - * Makefile, Python/configure.py: - Fixed configure.py for Qt5. - [7ddb5bf2030c] <2.7-maint> - - * Python/configure-ng.py, Python/configure-old.py, - Python/configure.py, build.py, lib/README.doc: - Completed configure-ng.py and renamed it configure.py. The old - configure.py is now called configure-old.py. - [8d58b2899080] <2.7-maint> - -2013-02-05 Phil Thompson - - * Python/configure-ng.py: - configure-ng.py now uses -fno-exceptions on Linux and OS/X. - configure-ng.py now hides unneeded symbols on Linux. - [391e4f56b009] <2.7-maint> - - * Python/configure-ng.py: - configure-ng.py will now install the .sip and .api files. - [e228d58a670c] <2.7-maint> - - * Python/configure-ng.py: - configure-ng.py will now create a Makefile that will build the - Python module. - [cb47ace62a70] <2.7-maint> - -2013-02-02 Phil Thompson - - * qt/qsciglobal.h: - Use Q_OS_WIN for compatibility for Qt5. - [da752cf4510a] <2.7-maint> - -2013-01-29 Phil Thompson - - * designer-Qt4Qt5/designer.pro, example-Qt4Qt5/application.pro: - Use macx rather than mac in the .pro files. - [ee818a367df7] <2.7-maint> - -2012-12-21 Phil Thompson - - * Python/configure-ng.py, Python/configure.py, designer- - Qt4Qt5/designer.pro, example-Qt4Qt5/application.pro, lib/README.doc, - qt/qscintilla.pro: - Various OS/X fixes so that setting DYLD_LIBRARY_PATH isn't - necessary. - [e7854b8b01e3] <2.7-maint> - -2012-12-19 Phil Thompson - - * build.py, designer-Qt4/designer.pro, designer- - Qt4/qscintillaplugin.cpp, designer-Qt4/qscintillaplugin.h, designer- - Qt4Qt5/designer.pro, designer-Qt4Qt5/qscintillaplugin.cpp, designer- - Qt4Qt5/qscintillaplugin.h, lib/README.doc: - Updated the Designer plugin for Qt5. - [77f575c87ebb] <2.7-maint> - -2012-12-08 Phil Thompson - - * .hgtags: - Added tag 2.7 for changeset 9bab1e7b02e3 - [5600138109ce] - - * NEWS: - Released as v2.7. - [9bab1e7b02e3] [2.7] - -2012-12-07 Phil Thompson - - * qt/qscintilla_es.qm, qt/qscintilla_es.ts: - Updated Spanish translations from Jaime. - [b188c942422c] - - * NEWS: - Updated the NEWS file regarding Qt v5-rc1. - [be9e6b928921] - -2012-12-02 Phil Thompson - - * qt/qsciscintilla.cpp: - A final(?) fix for scroll bars and annotations. - [378f28e5b4b2] - - * Python/configure-ng.py: - More build system changes. - [f53fc8743ff1] - -2012-11-29 Phil Thompson - - * Python/configure-ng.py: - More configure script changes. - [434c9b3185a5] - - * Python/configure-ng.py: - More work on the new configure script. - [3a044732b799] - - * qt/qscintilla_cs.qm, qt/qscintilla_de.qm, qt/qscintilla_de.ts, - qt/qscintilla_es.qm, qt/qscintilla_fr.qm, qt/qscintilla_pt_br.qm, - qt/qscintilla_ru.qm: - Updated German translations from Detlev. - [9dab221845ca] - -2012-11-28 Phil Thompson - - * Python/configure-ng.py, build.py: - Added the start of the SIP v5 compatible build script. - [781d2af60cfc] - -2012-11-27 Phil Thompson - - * Python/configure.py: - Fixed the handling of the 'linux' platform in the Python bindings. - [835d5e3be69e] - -2012-11-26 Phil Thompson - - * qt/qsciscintilla.cpp, qt/qsciscintillabase.cpp, - qt/qsciscintillabase.h: - Worked around Scintilla bugs related to scroll bars and annotations. - [edc190ecc6fc] - - * qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_es.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Updated the translation files. - [ec754f87a735] - - * NEWS, Python/sip/qscilexercss.sip, qt/qscilexercss.cpp, - qt/qscilexercss.h: - Updated the CSS lexer for Scintilla v3.23. - [011fba6d668d] - - * qt/qscilexercpp.h: - Fixed a couple of documentation typos. - [7c2d04c76bd6] - - * NEWS, Python/sip/qscilexercpp.sip, qt/qscilexercpp.cpp, - qt/qscilexercpp.h: - Updated the C++ lexer for Scintilla v3.23. - [ad93ee355639] - -2012-11-24 Phil Thompson - - * Python/sip/qscilexercpp.sip, qt/qscilexercpp.cpp, qt/qscilexercpp.h: - Updated the styles for the C++ lexer. - [153429503998] - -2012-11-23 Phil Thompson - - * NEWS, Python/sip/qsciscintilla.sip, qt/PlatQt.cpp, - qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Added CallTipsPosition, callTipsPosition() and - setCallTipsPosition(). - [7e5602869fee] - - * NEWS, Python/sip/qsciscintilla.sip, qt/qsciscintilla.h: - Added SquigglePixmapIndicator to QsciScintilla::IndicatorStyle. - [ad98a5396151] - - * NEWS, Python/sip/qsciscintilla.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added WrapFlagInMargin to QsciScintilla::WrapVisualFlag. - [a38c75c45fb3] - - * NEWS, qt/PlatQt.cpp, qt/qsciscintilla.cpp, qt/qscistyle.cpp: - Created a back door to pass the Qt weight of a font avoiding lossy - conversions between Qt weights and Scintilla weights. The default - behaviour is now SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE which is a - change but reflects what people really expect. - [78ce86e97ad3] - -2012-11-21 Phil Thompson - - * NEWS, Python/sip/qsciscintillabase.sip, qt/qsciscintillabase.h: - Updated the constants from Scintilla v3.23. - [a3a0768af999] - - * NEWS, Python/configure.py, include/Platform.h, lib/README.doc, - qt/ListBoxQt.cpp, qt/ListBoxQt.h, qt/PlatQt.cpp, qt/SciClasses.cpp, - qt/ScintillaQt.cpp, qt/qscintilla.pro, src/ExternalLexer.h, - src/XPM.cxx, src/XPM.h: - Updated the platform support so that it compiles (but untested). - [abae8e56a6ea] - -2012-11-20 Phil Thompson - - * cocoa/InfoBar.h, cocoa/InfoBar.mm, cocoa/PlatCocoa.h, - cocoa/PlatCocoa.mm, cocoa/QuartzTextStyle.h, - cocoa/QuartzTextStyleAttribute.h, cocoa/ScintillaCocoa.h, - cocoa/ScintillaCocoa.mm, - cocoa/ScintillaFramework/English.lproj/InfoPlist.strings, cocoa/Scin - tillaFramework/ScintillaFramework.xcodeproj/project.pbxproj, - cocoa/ScintillaTest/AppController.mm, - cocoa/ScintillaTest/English.lproj/InfoPlist.strings, - cocoa/ScintillaTest/ScintillaTest.xcodeproj/project.pbxproj, - cocoa/ScintillaView.h, cocoa/ScintillaView.mm, - cocoa/checkbuildosx.sh, delbin.bat, delcvs.bat, - doc/ScintillaDoc.html, doc/ScintillaDownload.html, - doc/ScintillaHistory.html, doc/ScintillaRelated.html, - doc/ScintillaToDo.html, doc/annotations.png, doc/index.html, - doc/styledmargin.png, gtk/PlatGTK.cxx, gtk/ScintillaGTK.cxx, - gtk/makefile, include/Face.py, include/ILexer.h, include/Platform.h, - include/SciLexer.h, include/Scintilla.h, include/Scintilla.iface, - include/ScintillaWidget.h, lexers/LexAVS.cxx, lexers/LexAda.cxx, - lexers/LexAsm.cxx, lexers/LexBash.cxx, lexers/LexBasic.cxx, - lexers/LexCPP.cxx, lexers/LexCSS.cxx, lexers/LexCoffeeScript.cxx, - lexers/LexD.cxx, lexers/LexECL.cxx, lexers/LexFortran.cxx, - lexers/LexHTML.cxx, lexers/LexLua.cxx, lexers/LexMMIXAL.cxx, - lexers/LexMPT.cxx, lexers/LexNsis.cxx, lexers/LexOScript.cxx, - lexers/LexOthers.cxx, lexers/LexPO.cxx, lexers/LexPascal.cxx, - lexers/LexPerl.cxx, lexers/LexRuby.cxx, lexers/LexSQL.cxx, - lexers/LexScriptol.cxx, lexers/LexSpice.cxx, lexers/LexTADS3.cxx, - lexers/LexTCL.cxx, lexers/LexTCMD.cxx, lexers/LexVHDL.cxx, - lexers/LexVisualProlog.cxx, lexers/LexYAML.cxx, - lexlib/CharacterSet.h, lexlib/LexAccessor.h, - lexlib/PropSetSimple.cxx, macosx/ExtInput.cxx, macosx/ExtInput.h, - macosx/PlatMacOSX.cxx, macosx/PlatMacOSX.h, - macosx/QuartzTextLayout.h, macosx/QuartzTextStyle.h, - macosx/QuartzTextStyleAttribute.h, - macosx/SciTest/English.lproj/InfoPlist.strings, - macosx/SciTest/English.lproj/main.xib, macosx/SciTest/Info.plist, - macosx/SciTest/SciTest.xcode/project.pbxproj, - macosx/SciTest/SciTest_Prefix.pch, macosx/SciTest/main.cpp, - macosx/SciTest/version.plist, macosx/ScintillaCallTip.cxx, - macosx/ScintillaCallTip.h, macosx/ScintillaListBox.cxx, - macosx/ScintillaListBox.h, macosx/ScintillaMacOSX.cxx, - macosx/ScintillaMacOSX.h, macosx/TCarbonEvent.cxx, - macosx/TCarbonEvent.h, macosx/TRect.h, macosx/TView.cxx, - macosx/TView.h, macosx/deps.mak, macosx/makefile, - src/AutoComplete.cxx, src/AutoComplete.h, src/CallTip.cxx, - src/CallTip.h, src/Catalogue.cxx, src/CellBuffer.cxx, - src/CellBuffer.h, src/CharClassify.cxx, src/CharClassify.h, - src/Decoration.cxx, src/Document.cxx, src/Document.h, - src/Editor.cxx, src/Editor.h, src/ExternalLexer.h, - src/FontQuality.h, src/Indicator.cxx, src/Indicator.h, - src/LexGen.py, src/LineMarker.cxx, src/LineMarker.h, - src/PerLine.cxx, src/PerLine.h, src/PositionCache.cxx, - src/PositionCache.h, src/RESearch.cxx, src/RunStyles.cxx, - src/SciTE.properties, src/ScintillaBase.cxx, src/ScintillaBase.h, - src/SplitVector.h, src/Style.cxx, src/Style.h, - src/UniConversion.cxx, src/UniConversion.h, src/ViewStyle.cxx, - src/ViewStyle.h, src/XPM.cxx, src/XPM.h, test/README, - test/examples/x.cxx, test/examples/x.cxx.styled, test/lexTests.py, - test/simpleTests.py, test/unit/makefile, - test/unit/testCharClassify.cxx, test/unit/testRunStyles.cxx, tgzsrc, - version.txt, win32/CheckD2D.cxx, win32/PlatWin.cxx, win32/PlatWin.h, - win32/ScintRes.rc, win32/ScintillaWin.cxx, win32/makefile, - win32/scintilla.mak, win32/scintilla_vc6.mak, zipsrc.bat: - Initial merge of Scintilla v3.23. - [b116f361ac01] - - * example-Qt4/application.pro, example-Qt4/application.qrc, example- - Qt4/images/copy.png, example-Qt4/images/cut.png, example- - Qt4/images/new.png, example-Qt4/images/open.png, example- - Qt4/images/paste.png, example-Qt4/images/save.png, example- - Qt4/main.cpp, example-Qt4/mainwindow.cpp, example-Qt4/mainwindow.h: - Merged the 2.6 maintenance branch with the trunk. - [0bf4f7453c68] - -2012-11-14 Phil Thompson - - * Makefile, example-Qt4Qt5/application.pro, qt/qsciscintillabase.cpp: - Fixed the linking of the example on OS/X. - [e1d1f43fae71] <2.6-maint> - -2012-11-12 Phil Thompson - - * Makefile, qt/PlatQt.cpp, qt/qscimacro.cpp, qt/qsciscintilla.cpp, - qt/qscistyle.cpp: - Removed all calls that are deprecated in Qt5. The build system now - supports cross-compilation to the Raspberry Pi. - [afef9d2b3ab1] <2.6-maint> - -2012-11-02 Phil Thompson - - * qt/qscilexersql.h: - Added comments to the QsciLexerSQL documentation stating that - additional keywords must be defined using lower case. - [79a9274b77c3] <2.6-maint> - -2012-10-09 Phil Thompson - - * NEWS, lib/ed.py, qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Added a replace option to the test editor's find commands. Finished - implementing findFirstInSelection(). - [80df6cc89bae] <2.6-maint> - - * lib/ed.py: - Added the Find, Find in Selection and Find Next actions to the test - editor. - [4aad56aedbea] <2.6-maint> - -2012-10-03 Phil Thompson - - * lib/ed.py: - Added an internal copy of the hackable Python test editor. - [a67a6fe99937] <2.6-maint> - -2012-09-27 Phil Thompson - - * lib/gen_python3_api.py, qsci/api/python/Python-3.3.api: - Fixed the gen_python3_api.py script to be able to exclude module - hierachies. Added the API file for Python v3.3. - [06bbb2d1c227] <2.6-maint> - -2012-09-22 Phil Thompson - - * qt/ListBoxQt.cpp: - Fixed a problem building against versions of Qt4 prior to v4.7. - [7bf93d60a50b] <2.6-maint> - -2012-09-18 Phil Thompson - - * NEWS, Python/sip/qsciscintilla.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added setOverwriteMode() and overwriteMode() to QsciScintilla. - [1affc53d2d88] <2.6-maint> - -2012-09-14 Phil Thompson - - * qt/qsciscintillabase.cpp: - Disable the use of QMacPasteboardMime for Qt v5-beta1. - [a6625d5928c6] <2.6-maint> - -2012-08-24 Phil Thompson - - * qt/qscilexerperl.cpp, qt/qscilexerperl.h: - Fixed auto-indentation for Perl. - [5eb1d97f95d6] <2.6-maint> - -2012-08-13 Phil Thompson - - * lexlib/CharacterSet.h: - Removed an incorrect assert() in the main Scintilla code. - [1aaf5e09d4b2] <2.6-maint> - -2012-08-09 Phil Thompson - - * NEWS, Python/sip/qsciscintilla.sip, qt/qscintilla.pro, - qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Added QsciScintilla::wordAtLineIndex(). - [0c5d77aef4f7] <2.6-maint> - -2012-07-19 Phil Thompson - - * qt/qscintilla.pro, qt/qsciscintillabase.cpp: - Fixed key handling on Linux with US international layout which - generates non-ASCII sequences for quote characters. - [061ab2c5bea3] <2.6-maint> - -2012-06-20 Phil Thompson - - * .hgtags: - Added tag 2.6.2 for changeset f9d3d982c20f - [a5bb033cd9e0] <2.6-maint> - - * NEWS: - Released as v2.6.2. - [f9d3d982c20f] [2.6.2] <2.6-maint> - -2012-06-19 Phil Thompson - - * qt/qsciscintillabase.cpp: - Fixed pasting of text in UTF8 mode (and hopefully Latin1 mode as - well). - [6df653daef18] <2.6-maint> - - * qt/qsciscintillabase.cpp: - Rectangular selections are now always encoded as plain/text with an - explicit, and separate, marker to indicate that it is rectangular. - [012a0b2ca89f] <2.6-maint> - -2012-06-09 Phil Thompson - - * qt/qsciscintillabase.cpp: - Used the Mac method of marking rectangular selections as the '\0' - Scintilla hack just doesn't work with Qt. - [75020a35b5eb] <2.6-maint> - - * qt/qscintilla.pro: - Bumped the library version number. - [12f21729e254] <2.6-maint> - -2012-06-07 Phil Thompson - - * qt/qsciscintillabase.cpp: - Improved the support for rectangular selections and the - interoperability with other Scintilla based editors. - [a42942b57fb7] <2.6-maint> - - * qt/qsciscintillabase.cpp: - Fixed the middle button pasting of rectangular selections. - [db58aa6c6d7d] <2.6-maint> - - * qt/qscidocument.cpp: - Fixed a bug that seemed to mean the initial EOL mode was always - UNIX. - [88561cd29a60] <2.6-maint> - - * qt/qsciscintillabase.cpp: - Line endings are properly translated when dropping text. - [d21994584e87] <2.6-maint> - -2012-06-04 Phil Thompson - - * Makefile, qt/qsciprinter.h: - The Python bindings now build against Qt5. - [ff2a74e5aec2] <2.6-maint> - -2012-04-04 Phil Thompson - - * Makefile, NEWS, build.py, example-Qt4/application.pro, example- - Qt4/application.qrc, example-Qt4/images/copy.png, example- - Qt4/images/cut.png, example-Qt4/images/new.png, example- - Qt4/images/open.png, example-Qt4/images/paste.png, example- - Qt4/images/save.png, example-Qt4/main.cpp, example- - Qt4/mainwindow.cpp, example-Qt4/mainwindow.h, example- - Qt4Qt5/application.pro, example-Qt4Qt5/application.qrc, example- - Qt4Qt5/images/copy.png, example-Qt4Qt5/images/cut.png, example- - Qt4Qt5/images/new.png, example-Qt4Qt5/images/open.png, example- - Qt4Qt5/images/paste.png, example-Qt4Qt5/images/save.png, example- - Qt4Qt5/main.cpp, example-Qt4Qt5/mainwindow.cpp, example- - Qt4Qt5/mainwindow.h, lib/LICENSE.GPL2, lib/LICENSE.GPL3, - lib/LICENSE.commercial.short, lib/LICENSE.gpl.short, lib/README, - lib/README.doc, lib/qscintilla.dxy, qt/PlatQt.cpp, - qt/qscintilla.pro: - Ported to Qt v5. - [ff3710487c3e] <2.6-maint> - -2012-04-02 Phil Thompson - - * qt/qsciapis.cpp: - Worked around an obscure Qt (or compiler) bug when handling call - tips. - [e6c7edcfdfb9] <2.6-maint> - -2012-03-04 Phil Thompson - - * Python/sip/qscilexer.sip, Python/sip/qscilexerbash.sip, - Python/sip/qscilexerbatch.sip, Python/sip/qscilexercpp.sip, - Python/sip/qscilexercss.sip, Python/sip/qscilexerd.sip, - Python/sip/qscilexerdiff.sip, Python/sip/qscilexerhtml.sip, - Python/sip/qscilexermakefile.sip, Python/sip/qscilexerperl.sip, - Python/sip/qscilexerpov.sip, Python/sip/qscilexerproperties.sip, - Python/sip/qscilexertex.sip, Python/sip/qscilexerverilog.sip, - qt/qscilexer.h, qt/qscilexerbash.h, qt/qscilexerbatch.h, - qt/qscilexercpp.h, qt/qscilexercss.h, qt/qscilexerd.h, - qt/qscilexerdiff.h, qt/qscilexerhtml.h, qt/qscilexermakefile.h, - qt/qscilexerperl.h, qt/qscilexerpov.h, qt/qscilexerproperties.h, - qt/qscilexertex.h, qt/qscilexerverilog.h: - QSciLexer::wordCharacters() is now part of the public API. - [933ef6a11ee6] <2.6-maint> - -2012-02-23 Phil Thompson - - * qt/qscilexercpp.h: - Updated the documentation for QsciLexerCpp::keywords() so that it - describes which sets are supported. - [4e0cb0250dad] <2.6-maint> - -2012-02-21 Phil Thompson - - * qt/qscintilla.pro, src/Document.cxx: - Some Scintilla fixes for the SCI_NAMESPACE support. - [611ffd016585] <2.6-maint> - -2012-02-10 Phil Thompson - - * .hgtags: - Added tag 2.6.1 for changeset 47d8fdf44946 - [aa843f471972] <2.6-maint> - - * NEWS: - Updated the NEWS file. Released as v2.6.1. - [47d8fdf44946] [2.6.1] <2.6-maint> - -2012-01-26 Phil Thompson - - * qt/qsciscintilla.cpp: - Don't implement shortcut overrides for the standard context menu - shortcuts. Instead leave it to the check against bound keys. - [e8ccaf398640] <2.6-maint> - -2012-01-19 Phil Thompson - - * qt/qsciapis.cpp: - APIs now allow for whitespace between the end of a word and the - opening parenthesis of the argument list. - [b09b25f38411] <2.6-maint> - -2012-01-11 Phil Thompson - - * qt/SciClasses.cpp: - Fixed the handling of auto-completion lists on Windows. - [131138b43c85] <2.6-maint> - -2011-12-07 Phil Thompson - - * Python/sip/qscicommandset.sip, qt/qscicommandset.cpp, - qt/qscicommandset.h, qt/qscintilla.pro: - Improved the Qt v3 port so that the signatures don't need to be - changed. Bumped the .so version number. - [3171bb05b1d8] <2.6-maint> - -2011-12-06 Phil Thompson - - * Makefile, NEWS, Python/sip/qscicommandset.sip, include/Platform.h, - qt/ListBoxQt.cpp, qt/qscicommandset.cpp, qt/qscicommandset.h, - qt/qsciscintilla.cpp, qt/qsciscintilla.h, src/XPM.cxx: - Fixed building against Qt v3. - [74df75a62f5c] <2.6-maint> - -2011-11-21 Phil Thompson - - * NEWS, include/Platform.h, qt/ListBoxQt.cpp, qt/ListBoxQt.h, - qt/PlatQt.cpp, qt/SciClasses.cpp, qt/SciClasses.h, - qt/SciNamespace.h, qt/ScintillaQt.cpp, qt/ScintillaQt.h, - qt/qscintilla.pro, qt/qsciscintilla.h, qt/qsciscintillabase.cpp, - qt/qsciscintillabase.h: - Added support for SCI_NAMESPACE to allow all internal Scintilla - classes to be placed in the Scintilla namespace. - [ab7857131e35] <2.6-maint> - -2011-11-11 Phil Thompson - - * .hgtags: - Added tag 2.6 for changeset 8b119c4f69d0 - [1a5dd31e773e] - - * NEWS, lib/README.doc: - Updated the NEWS file. Updated the introductory documentation. - Released as v2.6. - [8b119c4f69d0] [2.6] - -2011-11-07 Phil Thompson - - * NEWS, Python/sip/qscicommandset.sip, Python/sip/qsciscintilla.sip, - qt/qscicommandset.cpp, qt/qscicommandset.h, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added QsciCommandSet::boundTo(). Ordinary keys and those bound to - commands now override any shortcuts. - [ba98bc555aca] - -2011-10-28 Phil Thompson - - * qt/qscintilla_de.qm, qt/qscintilla_de.ts: - More updated German translations from Detlev. - [9ff20df1997b] - -2011-10-27 Phil Thompson - - * qt/qscintilla_cs.qm, qt/qscintilla_de.qm, qt/qscintilla_de.ts, - qt/qscintilla_es.qm, qt/qscintilla_es.ts, qt/qscintilla_fr.qm, - qt/qscintilla_pt_br.qm, qt/qscintilla_ru.qm: - Updated Spanish translations from Jaime. Updated German translations - from Detlev. - [4903315d96b1] - -2011-10-23 Phil Thompson - - * Python/sip/qscicommand.sip: - Fixed SelectAll in the Python bindings. - [b6f0a46e0eac] - - * qt/ScintillaQt.cpp, qt/qsciscintillabase.cpp: - Fixed drag and drop (specifically so that copying works on OS/X - again). - [6ab90cb63b2b] - -2011-10-22 Phil Thompson - - * qt/PlatQt.cpp: - Fixed a display bug with kerned fonts. - [a746e319d9cd] - - * qt/qsciscintilla.cpp: - The foreground and background colours of selected text are now taken - from the application palette. - [7f6c34ad8d27] - - * NEWS: - Updated the NEWS file. - [1717c6d59b12] - - * Python/sip/qsciscintilla.sip, qt/qscicommand.h, - qt/qscicommandset.cpp, qt/qscintilla_cs.ts, qt/qscintilla_de.ts, - qt/qscintilla_es.ts, qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, - qt/qscintilla_ru.ts, qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Renamed QsciCommand::SelectDocument to SelectAll. Added - QsciScintilla::createStandardContextMenu(). - [c42fa7e83b07] - -2011-10-21 Phil Thompson - - * qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_es.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Updated the .ts files. - [92d0b6ddf371] - - * qt/qscicommandset.cpp: - Completed the OS/X specific key bindings. - [964fa889b807] - -2011-10-20 Phil Thompson - - * qt/qscicommandset.cpp, qt/qsciscintillabase.cpp: - Fixed the support for SCMOD_META. Started to add the correct OS/X - key bindings as the default. - [0073fa86a5a0] - - * Python/sip/qscicommand.sip, qt/qscicommand.h, qt/qscicommandset.cpp: - All available commands are now defined in the standard command set. - [7c7b81b55f0e] - - * Python/sip/qscicommand.sip, qt/qscicommand.h: - Completed the QsciCommand::Command documentation. Added the members - to QsciCommand.Command in the Python bindings. - [0ca6ff576c21] - -2011-10-18 Phil Thompson - - * NEWS, Python/sip/qscicommandset.sip, qt/qscicommand.h, - qt/qscicommandset.cpp, qt/qscicommandset.h: - Added QsciCommandSet::find(). - [e75565018b90] - - * NEWS, Python/sip/qscicommand.sip, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, qt/qscicommand.cpp, - qt/qscicommand.h, qt/qscicommandset.cpp, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.h: - Added Command, command() and execute() to QsciCommand. Backed out - the high level support for moving the selection up and down. - [4852ee57353e] - -2011-10-17 Phil Thompson - - * qt/qscilexersql.cpp: - Fix for the changed fold at else property in the SQL lexer. - [e65a458cd9d8] - - * NEWS, Python/sip/qscilexerpython.sip, qt/qscilexerpython.cpp, - qt/qscilexerpython.h: - Added highlightSubidentifiers() and setHighlightSubidentifiers() to - the Python lexer. - [b397695bc2ab] - - * NEWS, Python/sip/qscilexercpp.sip, qt/qscilexercpp.cpp, - qt/qscilexercpp.h: - Added support for triple quoted strings to the C++ lexer. - [687d04948c5d] - - * NEWS, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.h: - Added low level support for identifiers, scrolling to the start and - end. Added low and hight level support for moving the selection up - and down. - [3ac1ccfad039] - - * NEWS, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.h: - Added low and high level support for margin options. - [f3cd3244cecd] - -2011-10-14 Phil Thompson - - * NEWS, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.h: - Updated the brace matching support to handle indicators. - [7e4a4d3529a8] - - * NEWS, Python/sip/qsciscintillabase.sip, qt/qsciscintillabase.h: - Added SCI_SETEMPTYSELECTION. - [879b97c676a4] - - * NEWS, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.h: - Updated the support for indicators. - [b3643569a827] - - * NEWS, Python/sip/qsciscintillabase.sip, qt/qsciscintillabase.h: - Added SCI_MARKERSETBACKSELECTED and SCI_MARKERENABLEHIGHLIGHT. - [7127ee82d128] - - * NEWS, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.cpp, - qt/qsciscintillabase.h: - Added low and high-level support for RGBA images (ie. QImage). - [7707052913ef] - -2011-10-13 Phil Thompson - - * NEWS, Python/sip/qscilexerlua.sip, qt/qscilexerlua.cpp, - qt/qscilexerlua.h: - Updated the Lua lexer. - [710e50d5692c] - - * NEWS, Python/sip/qscilexerperl.sip, qt/qscilexerperl.cpp, - qt/qscilexerperl.h: - Updated the Perl lexer. - [6d16e2e9354b] - -2011-10-11 Phil Thompson - - * Python/configure.py, cocoa/ScintillaCallTip.h, - cocoa/ScintillaCallTip.mm, cocoa/ScintillaListBox.h, - cocoa/ScintillaListBox.mm, cocoa/res/info_bar_bg.png, - cocoa/res/mac_cursor_busy.png, cocoa/res/mac_cursor_flipped.png, - macosx/SciTest/English.lproj/InfoPlist.strings, - macosx/SciTest/English.lproj/main.nib/classes.nib, - macosx/SciTest/English.lproj/main.nib/info.nib, - macosx/SciTest/English.lproj/main.nib/objects.xib, - macosx/SciTest/English.lproj/main.xib, qt/ListBoxQt.cpp, - qt/ListBoxQt.h, qt/PlatQt.cpp, qt/qscintilla.pro, src/XPM.cxx, - src/XPM.h: - Some fixes left over from the merge of v2.29. Added support for RGBA - images so that the merged version compiles. - [16c6831c337f] - - * cocoa/InfoBar.mm, cocoa/PlatCocoa.h, cocoa/PlatCocoa.mm, - cocoa/QuartzTextLayout.h, cocoa/QuartzTextStyle.h, - cocoa/QuartzTextStyleAttribute.h, cocoa/ScintillaCocoa.h, - cocoa/ScintillaCocoa.mm, cocoa/ScintillaFramework/ScintillaFramework - .xcodeproj/project.pbxproj, cocoa/ScintillaTest/AppController.mm, - cocoa/ScintillaTest/ScintillaTest.xcodeproj/project.pbxproj, - cocoa/ScintillaView.h, cocoa/ScintillaView.mm, doc/SciCoding.html, - doc/ScintillaDoc.html, doc/ScintillaDownload.html, - doc/ScintillaHistory.html, doc/ScintillaRelated.html, - doc/ScintillaToDo.html, doc/index.html, gtk/PlatGTK.cxx, - gtk/ScintillaGTK.cxx, gtk/makefile, include/Platform.h, - include/SciLexer.h, include/Scintilla.h, include/Scintilla.iface, - lexers/LexAU3.cxx, lexers/LexCOBOL.cxx, lexers/LexCPP.cxx, - lexers/LexConf.cxx, lexers/LexHTML.cxx, lexers/LexInno.cxx, - lexers/LexLua.cxx, lexers/LexMagik.cxx, lexers/LexMarkdown.cxx, - lexers/LexMatlab.cxx, lexers/LexModula.cxx, lexers/LexOthers.cxx, - lexers/LexPerl.cxx, lexers/LexPowerPro.cxx, lexers/LexPython.cxx, - lexers/LexSQL.cxx, lexers/LexTeX.cxx, lexers/LexVHDL.cxx, - lexers/LexVerilog.cxx, lexlib/Accessor.cxx, lexlib/CharacterSet.h, - lexlib/PropSetSimple.cxx, lexlib/SparseState.h, - lexlib/StyleContext.h, lexlib/WordList.cxx, macosx/PlatMacOSX.cxx, - macosx/PlatMacOSX.h, macosx/SciTest/SciTest.xcode/project.pbxproj, - macosx/ScintillaMacOSX.h, macosx/makefile, src/CallTip.cxx, - src/ContractionState.cxx, src/ContractionState.h, - src/Decoration.cxx, src/Document.cxx, src/Document.h, - src/Editor.cxx, src/Editor.h, src/Indicator.cxx, src/Indicator.h, - src/KeyMap.cxx, src/KeyMap.h, src/LexGen.py, src/LineMarker.cxx, - src/LineMarker.h, src/PerLine.cxx, src/PositionCache.cxx, - src/PositionCache.h, src/RESearch.cxx, src/RunStyles.cxx, - src/RunStyles.h, src/ScintillaBase.cxx, src/Style.cxx, src/Style.h, - src/ViewStyle.cxx, src/ViewStyle.h, src/XPM.cxx, src/XPM.h, - test/XiteMenu.py, test/XiteWin.py, test/examples/x.html, - test/examples/x.html.styled, test/performanceTests.py, - test/simpleTests.py, test/unit/testContractionState.cxx, - test/unit/testRunStyles.cxx, version.txt, win32/PlatWin.cxx, - win32/ScintRes.rc, win32/ScintillaWin.cxx, win32/scintilla.mak: - Merged Scintilla v2.29. - [750c2c3cef72] - - * Merged the v2.5 maintenance branch back into the trunk. - [eab39863675f] - -2011-06-24 Phil Thompson - - * qt/qscilexer.cpp, qt/qscilexerbash.cpp, qt/qscilexerbatch.cpp, - qt/qscilexercmake.cpp, qt/qscilexercpp.cpp, qt/qscilexercsharp.cpp, - qt/qscilexercss.cpp, qt/qscilexerd.cpp, qt/qscilexerfortran77.cpp, - qt/qscilexerhtml.cpp, qt/qscilexerjavascript.cpp, - qt/qscilexerlua.cpp, qt/qscilexermakefile.cpp, - qt/qscilexermatlab.cpp, qt/qscilexerpascal.cpp, - qt/qscilexerperl.cpp, qt/qscilexerpostscript.cpp, - qt/qscilexerpov.cpp, qt/qscilexerproperties.cpp, - qt/qscilexerpython.cpp, qt/qscilexerruby.cpp, qt/qscilexerspice.cpp, - qt/qscilexersql.cpp, qt/qscilexertcl.cpp, qt/qscilexerverilog.cpp, - qt/qscilexervhdl.cpp, qt/qscilexerxml.cpp, qt/qscilexeryaml.cpp: - Changed the default fonts for MacOS so that they are larger and - similar to the Windows defaults. - [9c37c180ba8d] <2.5-maint> - - * build.py: - Fixed the build system for MacOS as the development platform. - [3352479980c5] <2.5-maint> - -2011-05-13 Phil Thompson - - * lib/README.doc: - Updated the licensing information in the main documentation. - [d31c561e0b7c] <2.5-maint> - - * lib/LICENSE.GPL2, lib/LICENSE.GPL3, lib/LICENSE.gpl.short: - Removed some out of date links from the license information. Updated - the dates of some copyright notices. - [a84451464396] <2.5-maint> - -2011-05-10 Phil Thompson - - * Makefile, Python/sip/qsciscintilla.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added the optional posix flag to QsciScintilla::findFirst(). - [ad6064227d06] <2.5-maint> - -2011-04-29 Phil Thompson - - * Python/configure.py, qt/qscintilla.pro, qt/qsciscintilla.cpp, - qt/qscistyle.cpp, qt/qscistyle.h, qt/qscistyledtext.cpp, - qt/qscistyledtext.h: - Fixed problems with QsciStyle and QsciStyledText when used with more - than one QsciScintilla instance. - [8bac389fb7ae] <2.5-maint> - -2011-04-22 Phil Thompson - - * qt/qsciglobal.h: - Changed the handling of QT_BEGIN_NAMESPACE etc. as it isn't defined - in early versions of Qt v4. - [595c8c6cdfd2] <2.5-maint> - -2011-04-17 Phil Thompson - - * .hgtags: - Added tag 2.5.1 for changeset c8648c2c0c7f - [298153b3d40e] <2.5-maint> - - * NEWS: - Released as v2.5.1. - [c8648c2c0c7f] [2.5.1] <2.5-maint> - -2011-04-16 Phil Thompson - - * qt/qscintilla_de.ts, qt/qscintilla_es.ts: - Updated translations from Detlev and Jaime. - [9436bea546c9] <2.5-maint> - -2011-04-14 Phil Thompson - - * qt/qscintilla_cs.qm, qt/qscintilla_de.qm, qt/qscintilla_es.qm, - qt/qscintilla_fr.qm, qt/qscintilla_pt_br.qm, qt/qscintilla_ru.qm: - Updated the compiled translation files. - [c5d39aca8f51] <2.5-maint> - -2011-04-13 Phil Thompson - - * Python/sip/qscilexermatlab.sip, Python/sip/qscilexeroctave.sip, - Python/sip/qscimodcommon.sip: - Added Python bindings for QsciLexerMatlab abd QsciLexerOctave. - [22d0ed0fab2a] <2.5-maint> - - * NEWS, qt/qscilexermatlab.cpp, qt/qscilexermatlab.h, - qt/qscilexeroctave.cpp, qt/qscilexeroctave.h, qt/qscintilla.pro, - qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_es.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Added QsciLexerMatlab and QsciLexerOctave. - [40d3053334de] <2.5-maint> - -2011-04-09 Phil Thompson - - * Merged the font strategy fix from the trunk. - [d270e1b107d2] <2.5-maint> - - * NEWS: - Updated the NEWS file. - [8f32ff4cdd1f] <2.5-maint> - -2011-04-07 Phil Thompson - - * qt/PlatQt.cpp, qt/qscintilla.pro: - Fixed the handling of the font quality setting so that the default - behavior (particularly on Windows) is the same as earlier versions. - [87ae98d2674b] - -2011-03-29 Phil Thompson - - * .hgtags: - Added tag 2.5 for changeset 9d94a76f783e - [e4807fd91f6c] - - * NEWS: - Released as v2.5. - [9d94a76f783e] [2.5] - -2011-03-28 Phil Thompson - - * NEWS, Python/configure.py: - Added support for the protected-is-public hack to configure.py. - [beee52b8e10a] - -2011-03-27 Phil Thompson - - * qt/PlatQt.cpp: - Fixed an OS/X build problem. - [ac7f1d3c9abe] - -2011-03-26 Phil Thompson - - * NEWS, Python/sip/qsciscintilla.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added replaceSelectedText() to QsciScintilla. - [3c00a19d6571] - -2011-03-25 Phil Thompson - - * Python/configure.py, Python/sip/qsciapis.sip, - Python/sip/qscilexer.sip, Python/sip/qscilexercustom.sip, - Python/sip/qscimod4.sip, Python/sip/qsciprinter.sip, - Python/sip/qsciscintilla.sip, Python/sip/qscistyle.sip, - qt/qsciapis.cpp, qt/qsciapis.h, qt/qscilexercustom.cpp, - qt/qscilexercustom.h, qt/qsciscintilla.cpp, qt/qsciscintilla.h, - qt/qscistyle.cpp, qt/qscistyle.h: - Went through the API making sure all optional arguments had - consistent and meaningful names. Enabled keyword support in the - Python bindings. - [d60fa45e40b7] - -2011-03-23 Phil Thompson - - * qt/qscintilla_de.qm, qt/qscintilla_de.ts, qt/qscintilla_es.qm, - qt/qscintilla_es.ts: - Updated German translations from Detlev. Updated Spanish - translations from Jaime. - [f64c97749375] - -2011-03-21 Phil Thompson - - * lexers/LexModula.cxx, lexlib/SparseState.h, qt/qscintilla_cs.ts, - qt/qscintilla_de.ts, qt/qscintilla_es.ts, qt/qscintilla_fr.ts, - qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts, - test/unit/testSparseState.cxx, vcbuild/SciLexer.dsp: - Updated the translation files. Updated the repository for the new - and removed Scintilla v2.25 files. - [6eb77ba7c57c] - - * NEWS, Python/sip/qscilexercpp.sip, Python/sip/qsciscintillabase.sip, - qt/qscilexercpp.cpp, qt/qscilexercpp.h, qt/qscintilla.pro, - qt/qsciscintillabase.h: - Added support for raw string to the C++ lexer. - [f83112ced877] - - * NEWS, cocoa/Framework.mk, cocoa/PlatCocoa.mm, - cocoa/ScintillaCocoa.mm, cocoa/ScintillaFramework/ScintillaFramework - .xcodeproj/project.pbxproj, cocoa/ScintillaTest/AppController.mm, - cocoa/ScintillaView.h, cocoa/ScintillaView.mm, - doc/ScintillaDownload.html, doc/ScintillaHistory.html, - doc/ScintillaRelated.html, doc/index.html, gtk/PlatGTK.cxx, - gtk/makefile, include/Platform.h, include/SciLexer.h, - include/Scintilla.iface, lexers/LexAsm.cxx, lexers/LexBasic.cxx, - lexers/LexCPP.cxx, lexers/LexD.cxx, lexers/LexFortran.cxx, - lexers/LexOthers.cxx, lexlib/CharacterSet.h, lib/README.doc, - macosx/SciTest/main.cpp, src/AutoComplete.cxx, src/Catalogue.cxx, - src/Document.cxx, src/Editor.cxx, src/LexGen.py, test/unit/makefile, - version.txt, win32/PlatWin.cxx, win32/ScintRes.rc, - win32/scintilla.mak, win32/scintilla_vc6.mak: - Merged Scintilla v2.25. - [e01dec109182] - -2011-03-14 Phil Thompson - - * qt/qscintilla_es.qm, qt/qscintilla_es.ts: - Updated Spanish translations from Jaime Seuma. - [b83a3ca4f3e6] - -2011-03-12 Phil Thompson - - * qt/qscintilla_de.qm, qt/qscintilla_de.ts: - Updated German translations from Detlev. - [e5729134a47b] - -2011-03-11 Phil Thompson - - * qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_es.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Updated the translation source files. - [51e8ee8b1ba9] - - * NEWS, Python/sip/qscilexercpp.sip, qt/qscilexercpp.cpp, - qt/qscilexercpp.h: - Added support for the inactive styles of QsciLexerCPP. - [59b566d322af] - - * qt/qscilexercpp.cpp, qt/qscilexercpp.h: - Inlined all existing property getters in QsciLexerCPP. - [1117e5105e5e] - -2011-03-10 Phil Thompson - - * qt/qsciscintilla.cpp: - Fixed QsciScintilla::setContractedFolds() so that it actually - updates the display to show the new state. - [5079f59a0103] - - * NEWS, Python/sip/qscilexerhtml.sip, qt/qscilexerhtml.cpp, - qt/qscilexerhtml.h: - Updated QsciLexerHTML. - [0707f4bc7855] - - * NEWS, Python/sip/qscilexerproperties.sip, - qt/qscilexerproperties.cpp, qt/qscilexerproperties.h: - Updated QsciLexerProperties. - [1dfe5e2d4913] - - * NEWS, Python/sip/qscilexerpython.sip, Python/sip/qscilexerruby.sip, - Python/sip/qscilexersql.sip, Python/sip/qscilexertcl.sip, - Python/sip/qscilexertex.sip, qt/qscilexerpython.cpp, - qt/qscilexerpython.h, qt/qscilexerruby.h, qt/qscilexersql.h, - qt/qscilexertcl.h, qt/qscilexertex.cpp, qt/qscilexertex.h: - Updated QsciLexerPython. - [bc96868a1a6f] - - * NEWS, Python/sip/qscilexerruby.sip, Python/sip/qscilexersql.sip, - Python/sip/qscilexertcl.sip, Python/sip/qscilexertex.sip, - qt/qscilexerruby.cpp, qt/qscilexerruby.h, qt/qscilexersql.h, - qt/qscilexertcl.h, qt/qscilexertex.h: - The new lexer property setters are no longer virtual slots. - [c3e88383e8d3] - - * qt/qscilexersql.cpp, qt/qscilexersql.h: - Restored the default behaviour of setFoldCompact() for QsciLexerSQL. - [c74aef0f7eb4] - - * NEWS, Python/sip/qscilexertcl.sip, qt/qscilexersql.h, - qt/qscilexertcl.cpp, qt/qscilexertcl.h: - Updated QsciLexerTCL. - [43a150bb40d5] - - * NEWS, Python/sip/qscilexertex.sip, qt/qscilexertex.cpp, - qt/qscilexertex.h: - Updated QsciLexerTeX. - [1457935cee44] - - * qt/qscintilla_cs.qm, qt/qscintilla_de.qm, qt/qscintilla_de.ts, - qt/qscintilla_es.qm, qt/qscintilla_fr.qm, qt/qscintilla_pt_br.qm, - qt/qscintilla_ru.qm: - Updated German translations from Detlev. - [ad4a4bd4855b] - -2011-03-08 Phil Thompson - - * qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_es.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Updated the .ts translation files. - [8d70033d07e2] - - * NEWS, Python/sip/qscilexersql.sip, qt/qscilexersql.cpp, - qt/qscilexersql.h: - Updated QsciLexerSQL. - [8bc79d109c88] - - * NEWS, Python/sip/qscilexercss.sip, qt/qscilexercss.cpp, - qt/qscilexercss.h: - Updated QsciLexerCSS. - [f3adcb31b1a9] - - * NEWS, Python/sip/qscilexerd.sip, qt/qscilexerd.cpp, qt/qscilexerd.h: - Updated QsciLexerD. - [82d8a6561943] - - * Python/sip/qscilexerlua.sip, qt/qscilexerlua.cpp, qt/qscilexerlua.h: - Updated QsciLexerLua. - [103f5881c642] - - * NEWS, Python/sip/qsciscintillabase.sip, qt/ScintillaQt.cpp, - qt/qsciscintillabase.h: - Added support for the QsciScintillaBase::SCN_HOTSPOTRELEASECLICK() - signal. - [1edd56e105cd] - - * Python/sip/qsciscintillabase.sip, qt/qsciscintillabase.h: - Added low-level support for SCLEX_MARKDOWN, SCLEX_TXT2TAGS and - SCLEX_A68K. - [de92a613cea7] - - * Python/sip/qsciscintillabase.sip, qt/qscicommand.cpp, - qt/qsciscintilla.cpp, qt/qsciscintillabase.h: - Added support for SCMOD_SUPER as the Qt Meta key modifier. - [24e745cddeea] - - * NEWS, Python/sip/qsciscintillabase.sip, qt/ScintillaQt.cpp, - qt/qsciscintilla.cpp, qt/qsciscintilla.h, qt/qsciscintillabase.h: - Updated the QsciScintillaBase::SCN_UPDATEUI() signal. Added low- - level support for SC_MOD_LEXERSTATE. - [0a341fcb0545] - - * Python/sip/qsciscintillabase.sip, qt/qsciscintillabase.h: - Added low-level support for the updated property functions. - [f33d9c271992] - - * Python/sip/qsciscintillabase.sip, qt/qsciscintillabase.h: - Added low-level support for SCI_GETLEXERLANGUAGE and - SCI_PRIVATELEXERCALL. - [ac69f8c2ef3b] - - * Python/sip/qsciscintillabase.sip, qt/qsciscintillabase.h: - Added low-level support for the new stick caret options. - [693ac6c68e6f] - - * Python/sip/qsciscintillabase.sip, qt/qsciscintillabase.h: - Added low-level support for SCI_AUTOCGETCURRENTTEXT. - [2634827cdb4e] - - * Python/sip/qsciscintillabase.sip, qt/qsciscintillabase.h: - Added low-level support for SC_SEL_THIN. - [4225a944dc14] - - * qt/qsciscintilla.cpp: - Folding now works again. - [3972053c646e] - -2011-03-07 Phil Thompson - - * Python/sip/qsciscintillabase.sip, qt/qsciscintillabase.h: - Added low-level support for SCI_VERTICALCENTRECARET. - [92d5ecb154d1] - - * NEWS, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.h: - Added setContractedFolds() and contractedFolds() to QsciScintilla. - [46eb254c6200] - - * Python/sip/qsciscintillabase.sip, qt/qsciscintillabase.h: - Added low-level support for SCI_CHANGELEXERSTATE. - [edd899d77aa7] - - * Python/sip/qsciscintillabase.sip, qt/qsciscintilla.h, - qt/qsciscintillabase.h: - Added low-level support for SCI_CHARPOSITIONFROMPOINT and - SCI_CHARPOSITIONFROMPOINTCLOSE. - [5a000cf4bfba] - - * Python/sip/qsciscintillabase.sip, qt/qsciscintillabase.h: - Added low-level support for multiple selections. - [dedda8cbf413] - - * Python/sip/qsciscintillabase.sip, qt/qsciscintillabase.h: - Added SCI_GETTAG. - [775d0058f00e] - - * NEWS, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.h: - Added QsciScintilla::setFirstVisibleLine(). - [8b662ffe3fb6] - - * Python/sip/qsciscintillabase.sip, qt/PlatQt.cpp, - qt/qsciscintillabase.h: - Added low-level support for setting the font quality. - [933e8b01eda6] - - * NEWS, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.h: - Added high-level support for line wrap indentation modes. - [1faa3b2fa31e] - - * NEWS, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.h: - Added high-level support for extra ascent and descent space. Added - high-level support for whitespace size, foreground and background. - [537c551a79ef] - - * Python/sip/qsciscintillabase.sip, qt/PlatQt.cpp, - qt/qsciscintillabase.h: - Updated the low level support for cursors. - [2ce685a89697] - - * NEWS, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, qt/qsciscintilla.h, - qt/qsciscintillabase.h: - Updated the support for markers and added FullRectangle, - LeftRectangle and Underline to the MarkerSymbol enum. - [4c626f8189bf] - -2011-03-06 Phil Thompson - - * NEWS, Python/sip/qsciscintillabase.sip, qt/ScintillaQt.cpp, - qt/ScintillaQt.h, qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Rectangular selections are now fully supported. The signatures of - toMimeData() and fromMimeData() have changed. - [397948f42b2e] - - * NEWS: - Updated the NEWS file. - [bc75b98210f2] - - * .hgignore: - Added the .hgignore file. - [77312a36220e] - - * qt/qsciscintilla.cpp: - Removed the workaround for the broken annotations in Scintilla - v1.78. - [70ab4c4b7c66] - - * qt/ListBoxQt.cpp: - Fixed a regression when displaying an auto-completion list. - [c38d4b97a1ca] - -2011-03-04 Phil Thompson - - * qt/ListBoxQt.cpp, qt/PlatQt.cpp, qt/ScintillaQt.cpp, - qt/ScintillaQt.h, qt/qsciscintillabase.cpp: - Completed the merge of Scintilla v2.24. - [6890939e2da6] - - * build.py, qt/qscintilla.pro: - More build system changes. - [3e9deec76c02] - - * qt/qscintilla.pro, qt/qsciscintilla.cpp: - Updated the .pro file for the changed files and directory structure - in v2.24. - [274cb7017857] - - * License.txt, README, bin/empty.txt, cocoa/Framework.mk, - cocoa/InfoBar.h, cocoa/InfoBar.mm, cocoa/InfoBarCommunicator.h, - cocoa/PlatCocoa.h, cocoa/PlatCocoa.mm, cocoa/QuartzTextLayout.h, - cocoa/QuartzTextStyle.h, cocoa/QuartzTextStyleAttribute.h, - cocoa/SciTest.mk, cocoa/ScintillaCallTip.h, - cocoa/ScintillaCallTip.mm, cocoa/ScintillaCocoa.h, - cocoa/ScintillaCocoa.mm, cocoa/ScintillaFramework/Info.plist, cocoa/ - ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj, - cocoa/ScintillaFramework/Scintilla_Prefix.pch, - cocoa/ScintillaListBox.h, cocoa/ScintillaListBox.mm, - cocoa/ScintillaTest/AppController.h, - cocoa/ScintillaTest/AppController.mm, - cocoa/ScintillaTest/English.lproj/MainMenu.xib, - cocoa/ScintillaTest/Info.plist, cocoa/ScintillaTest/Scintilla- - Info.plist, - cocoa/ScintillaTest/ScintillaTest.xcodeproj/project.pbxproj, - cocoa/ScintillaTest/ScintillaTest_Prefix.pch, - cocoa/ScintillaTest/TestData.sql, cocoa/ScintillaTest/main.m, - cocoa/ScintillaView.h, cocoa/ScintillaView.mm, cocoa/common.mk, - delbin.bat, delcvs.bat, doc/Design.html, doc/Lexer.txt, - doc/SciBreak.jpg, doc/SciCoding.html, doc/SciRest.jpg, - doc/SciTEIco.png, doc/SciWord.jpg, doc/ScintillaDoc.html, - doc/ScintillaDownload.html, doc/ScintillaHistory.html, - doc/ScintillaRelated.html, doc/ScintillaToDo.html, - doc/ScintillaUsage.html, doc/Steps.html, doc/index.html, - gtk/Converter.h, gtk/PlatGTK.cxx, gtk/ScintillaGTK.cxx, - gtk/deps.mak, gtk/makefile, gtk/scintilla-marshal.c, gtk/scintilla- - marshal.h, gtk/scintilla-marshal.list, gtk/scintilla.mak, - include/Accessor.h, include/Face.py, include/HFacer.py, - include/ILexer.h, include/KeyWords.h, include/Platform.h, - include/PropSet.h, include/SString.h, include/SciLexer.h, - include/Scintilla.h, include/Scintilla.iface, - include/ScintillaWidget.h, include/WindowAccessor.h, - lexers/LexA68k.cxx, lexers/LexAPDL.cxx, lexers/LexASY.cxx, - lexers/LexAU3.cxx, lexers/LexAVE.cxx, lexers/LexAbaqus.cxx, - lexers/LexAda.cxx, lexers/LexAsm.cxx, lexers/LexAsn1.cxx, - lexers/LexBaan.cxx, lexers/LexBash.cxx, lexers/LexBasic.cxx, - lexers/LexBullant.cxx, lexers/LexCLW.cxx, lexers/LexCOBOL.cxx, - lexers/LexCPP.cxx, lexers/LexCSS.cxx, lexers/LexCaml.cxx, - lexers/LexCmake.cxx, lexers/LexConf.cxx, lexers/LexCrontab.cxx, - lexers/LexCsound.cxx, lexers/LexD.cxx, lexers/LexEScript.cxx, - lexers/LexEiffel.cxx, lexers/LexErlang.cxx, lexers/LexFlagship.cxx, - lexers/LexForth.cxx, lexers/LexFortran.cxx, lexers/LexGAP.cxx, - lexers/LexGui4Cli.cxx, lexers/LexHTML.cxx, lexers/LexHaskell.cxx, - lexers/LexInno.cxx, lexers/LexKix.cxx, lexers/LexLisp.cxx, - lexers/LexLout.cxx, lexers/LexLua.cxx, lexers/LexMMIXAL.cxx, - lexers/LexMPT.cxx, lexers/LexMSSQL.cxx, lexers/LexMagik.cxx, - lexers/LexMarkdown.cxx, lexers/LexMatlab.cxx, - lexers/LexMetapost.cxx, lexers/LexMySQL.cxx, lexers/LexNimrod.cxx, - lexers/LexNsis.cxx, lexers/LexOpal.cxx, lexers/LexOthers.cxx, - lexers/LexPB.cxx, lexers/LexPLM.cxx, lexers/LexPOV.cxx, - lexers/LexPS.cxx, lexers/LexPascal.cxx, lexers/LexPerl.cxx, - lexers/LexPowerPro.cxx, lexers/LexPowerShell.cxx, - lexers/LexProgress.cxx, lexers/LexPython.cxx, lexers/LexR.cxx, - lexers/LexRebol.cxx, lexers/LexRuby.cxx, lexers/LexSML.cxx, - lexers/LexSQL.cxx, lexers/LexScriptol.cxx, lexers/LexSmalltalk.cxx, - lexers/LexSorcus.cxx, lexers/LexSpecman.cxx, lexers/LexSpice.cxx, - lexers/LexTACL.cxx, lexers/LexTADS3.cxx, lexers/LexTAL.cxx, - lexers/LexTCL.cxx, lexers/LexTeX.cxx, lexers/LexTxt2tags.cxx, - lexers/LexVB.cxx, lexers/LexVHDL.cxx, lexers/LexVerilog.cxx, - lexers/LexYAML.cxx, lexlib/Accessor.cxx, lexlib/Accessor.h, - lexlib/CharacterSet.cxx, lexlib/CharacterSet.h, - lexlib/LexAccessor.h, lexlib/LexerBase.cxx, lexlib/LexerBase.h, - lexlib/LexerModule.cxx, lexlib/LexerModule.h, - lexlib/LexerNoExceptions.cxx, lexlib/LexerNoExceptions.h, - lexlib/LexerSimple.cxx, lexlib/LexerSimple.h, lexlib/OptionSet.h, - lexlib/PropSetSimple.cxx, lexlib/PropSetSimple.h, - lexlib/StyleContext.cxx, lexlib/StyleContext.h, lexlib/WordList.cxx, - lexlib/WordList.h, lib/README.doc, macosx/PlatMacOSX.cxx, - macosx/SciTest/SciTest.xcode/project.pbxproj, - macosx/ScintillaMacOSX.cxx, macosx/ScintillaMacOSX.h, - macosx/deps.mak, macosx/makefile, src/AutoComplete.cxx, - src/AutoComplete.h, src/CallTip.cxx, src/CallTip.h, - src/Catalogue.cxx, src/Catalogue.h, src/CellBuffer.cxx, - src/CellBuffer.h, src/CharClassify.cxx, src/CharClassify.h, - src/CharacterSet.h, src/ContractionState.cxx, - src/ContractionState.h, src/Decoration.h, src/Document.cxx, - src/Document.h, src/DocumentAccessor.cxx, src/DocumentAccessor.h, - src/Editor.cxx, src/Editor.h, src/ExternalLexer.cxx, - src/ExternalLexer.h, src/FontQuality.h, src/Indicator.cxx, - src/Indicator.h, src/KeyMap.cxx, src/KeyMap.h, src/KeyWords.cxx, - src/LexAPDL.cxx, src/LexASY.cxx, src/LexAU3.cxx, src/LexAVE.cxx, - src/LexAbaqus.cxx, src/LexAda.cxx, src/LexAsm.cxx, src/LexAsn1.cxx, - src/LexBaan.cxx, src/LexBash.cxx, src/LexBasic.cxx, - src/LexBullant.cxx, src/LexCLW.cxx, src/LexCOBOL.cxx, - src/LexCPP.cxx, src/LexCSS.cxx, src/LexCaml.cxx, src/LexCmake.cxx, - src/LexConf.cxx, src/LexCrontab.cxx, src/LexCsound.cxx, - src/LexD.cxx, src/LexEScript.cxx, src/LexEiffel.cxx, - src/LexErlang.cxx, src/LexFlagship.cxx, src/LexForth.cxx, - src/LexFortran.cxx, src/LexGAP.cxx, src/LexGen.py, - src/LexGui4Cli.cxx, src/LexHTML.cxx, src/LexHaskell.cxx, - src/LexInno.cxx, src/LexKix.cxx, src/LexLisp.cxx, src/LexLout.cxx, - src/LexLua.cxx, src/LexMMIXAL.cxx, src/LexMPT.cxx, src/LexMSSQL.cxx, - src/LexMagik.cxx, src/LexMatlab.cxx, src/LexMetapost.cxx, - src/LexMySQL.cxx, src/LexNimrod.cxx, src/LexNsis.cxx, - src/LexOpal.cxx, src/LexOthers.cxx, src/LexPB.cxx, src/LexPLM.cxx, - src/LexPOV.cxx, src/LexPS.cxx, src/LexPascal.cxx, src/LexPerl.cxx, - src/LexPowerPro.cxx, src/LexPowerShell.cxx, src/LexProgress.cxx, - src/LexPython.cxx, src/LexR.cxx, src/LexRebol.cxx, src/LexRuby.cxx, - src/LexSML.cxx, src/LexSQL.cxx, src/LexScriptol.cxx, - src/LexSmalltalk.cxx, src/LexSorcus.cxx, src/LexSpecman.cxx, - src/LexSpice.cxx, src/LexTACL.cxx, src/LexTADS3.cxx, src/LexTAL.cxx, - src/LexTCL.cxx, src/LexTeX.cxx, src/LexVB.cxx, src/LexVHDL.cxx, - src/LexVerilog.cxx, src/LexYAML.cxx, src/LineMarker.cxx, - src/LineMarker.h, src/Partitioning.h, src/PerLine.cxx, - src/PerLine.h, src/PositionCache.cxx, src/PositionCache.h, - src/PropSet.cxx, src/RESearch.cxx, src/RESearch.h, - src/RunStyles.cxx, src/SVector.h, src/SciTE.properties, - src/ScintillaBase.cxx, src/ScintillaBase.h, src/Selection.cxx, - src/Selection.h, src/SplitVector.h, src/Style.cxx, src/Style.h, - src/StyleContext.cxx, src/StyleContext.h, src/UniConversion.cxx, - src/UniConversion.h, src/ViewStyle.cxx, src/ViewStyle.h, - src/WindowAccessor.cxx, src/XPM.cxx, src/XPM.h, - test/MessageNumbers.py, test/README, test/XiteMenu.py, - test/XiteWin.py, test/examples/x.asp, test/examples/x.asp.styled, - test/examples/x.cxx, test/examples/x.cxx.styled, test/examples/x.d, - test/examples/x.d.styled, test/examples/x.html, - test/examples/x.html.styled, test/examples/x.php, - test/examples/x.php.styled, test/examples/x.py, - test/examples/x.py.styled, test/examples/x.vb, - test/examples/x.vb.styled, test/lexTests.py, - test/performanceTests.py, test/simpleTests.py, test/unit/README, - test/unit/SciTE.properties, test/unit/makefile, - test/unit/testContractionState.cxx, test/unit/testPartitioning.cxx, - test/unit/testRunStyles.cxx, test/unit/testSplitVector.cxx, - test/unit/unitTest.cxx, test/xite.py, vcbuild/SciLexer.dsp, - version.txt, win32/Margin.cur, win32/PlatWin.cxx, - win32/PlatformRes.h, win32/SciTE.properties, win32/ScintRes.rc, - win32/Scintilla.def, win32/ScintillaWin.cxx, win32/deps.mak, - win32/makefile, win32/scintilla.mak, win32/scintilla_vc6.mak, - zipsrc.bat: - Merged Scintilla v2.24. - [59ca27407fd9] - -2011-03-03 Phil Thompson - - * Python/configure.py, qt/qscintilla.pro: - Updated the .so version number to 6.0.0. - [8ebe3f1fccd4] - - * Makefile: - Switched the build system to Qt v4.7.2. - [47f653394ef0] - - * .hgtags, lib/README.svn: - Merged the v2.4 maintenance branch. - [d00b7d9115d1] - - * qsci/api/python/Python-3.2.api: - Added an API file for Python v3.2. - [8cc94408b710] <2.4-maint> - -2011-02-23 Phil Thompson - - * qt/qsciscintillabase.cpp: - On X11 the control modifier is now used (instead of alt) to trigger - a rectangular selection. - [4bea3b8b8271] <2.4-maint> - -2011-02-22 Phil Thompson - - * qt/qscimacro.cpp: - Fixed a bug with Qt4 when loading a macro that meant that a macro - may not have a terminating '\0'. - [bbec6ef96cd2] <2.4-maint> - -2011-02-06 Phil Thompson - - * lib/LICENSE.commercial.short, lib/LICENSE.gpl.short: - Updated the copyright notices. - [f386964f3853] <2.4-maint> - - * Python/sip/qsciscintilla.sip, qt/qscintilla.pro, - qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Deprecated setAutoCompletionShowSingle(), added - setAutoCompletionUseSingle(). Deprecated autoCompletionShowSingle(), - added autoCompletionUseSingle(). - [7dae1a33b74b] <2.4-maint> - - * qt/qsciscintilla.cpp, qt/qsciscintilla.h: - QsciScintilla::setAutoCompletionCaseSensitivity() is no longer - ignored if a lexer has been set. - [92d3c5f7b825] <2.4-maint> - - * qt/qscintilla.pro, qt/qsciscintillabase.cpp: - Translate Key_Backtab to Shift-Key_Tab before passing to Scintilla. - [fc2d75b26ef8] <2.4-maint> - -2011-01-06 Phil Thompson - - * qt/qscintilla_es.ts: - Updated Spanish translations from Jaime Seuma. - [8921e85723a1] <2.4-maint> - -2010-12-24 Phil Thompson - - * qt/qsciscintilla.h: - Fixed a documentation typo. - [1b951cf8838a] <2.4-maint> - -2010-12-23 Phil Thompson - - * .hgtags: - Added tag 2.4.6 for changeset 1884d76f35b0 - [696037b84e26] <2.4-maint> - - * NEWS: - Released as v2.4.6. - [1884d76f35b0] [2.4.6] <2.4-maint> - -2010-12-21 Phil Thompson - - * qt/qsciscintilla.cpp: - Auto-completion words from documents are now ignored if they are - already included from APIs. - [db48fbf19e7c] <2.4-maint> - - * qt/SciClasses.cpp: - Make sure call tips are redrawn afer being clicked on. - [497ad4605ae3] <2.4-maint> - -2010-11-23 Phil Thompson - - * NEWS, Python/sip/qsciscintilla.sip, qt/qscintilla.pro, - qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Added support for indicators to the high-level API. See the NEWS - file for the details. - [8673b7890874] <2.4-maint> - -2010-11-15 Phil Thompson - - * Python/configure.py: - Added the --no-timestamp option to configure.py. - [61d1b5d28e21] <2.4-maint> - - * qsci/api/python/Python-2.7.api: - Added the API file for Python v2.7. - [5b2c77e7150a] <2.4-maint> - -2010-11-09 Phil Thompson - - * Makefile, qt/PlatQt.cpp: - Applied a fix for calculating character widths under OS/X. Switched - the build system to Qt v4.7.1. - [47a4eff86efa] <2.4-maint> - -2010-11-08 Phil Thompson - - * qt/qscilexercpp.h: - Fixed a bug in the documentation of QsciLexerCPP.GlobalClass. - [3cada289b329] <2.4-maint> - -2010-10-24 Phil Thompson - - * qt/SciClasses.h, qt/ScintillaQt.h, qt/qscicommandset.h, - qt/qsciglobal.h, qt/qscilexer.h, qt/qsciprinter.h, - qt/qsciscintilla.h, qt/qsciscintillabase.h: - Added support for QT_BEGIN_NAMESPACE and QT_END_NAMESPACE. - [a80f0df49f6c] <2.4-maint> - -2010-10-23 Phil Thompson - - * qt/qscintilla_de.qm, qt/qscintilla_de.ts: - Updated German translations from Detlev. - [693d3adf3c3f] <2.4-maint> - -2010-10-21 Phil Thompson - - * Makefile, Python/sip/qscilexerproperties.sip, - qt/qscilexerproperties.cpp, qt/qscilexerproperties.h, - qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_es.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Added support for the Key style to QsciLexerProperties. - [0b2e86015862] <2.4-maint> - -2010-08-31 Phil Thompson - - * .hgtags: - Added tag 2.4.5 for changeset f3f3936e5b86 - [84bb1b0d0674] <2.4-maint> - - * NEWS: - Released as v2.4.5. - [f3f3936e5b86] [2.4.5] <2.4-maint> - -2010-08-21 Phil Thompson - - * NEWS: - Updated the NEWS file. - [80afe6b1504a] <2.4-maint> - -2010-08-20 Phil Thompson - - * Python/sip/qsciscintillabase.sip: - With Python v3, the QsciScintillaBase.SendScintilla() overloads that - take char * arguments now require them to be bytes objects and no - longer allow them to be str objects. - [afa9ac3c487d] <2.4-maint> - -2010-08-14 Phil Thompson - - * Python/sip/qsciscintillabase.sip: - Reverted the addition of the /Encoding/ annotations to - SendScintilla() as it is (probably) not the right solution. - [4cb625284e4f] <2.4-maint> - - * qt/qsciscintilla.cpp: - The entries in user and auto-completion lists should now support - UTF-8. - [112d71cec57a] <2.4-maint> - - * Python/sip/qsciscintillabase.sip: - The QsciScintillaBase.SendScintilla() Python overloads will now - accept unicode strings that can be encoded to UTF-8. - [2f21b97985f2] <2.4-maint> - -2010-07-22 Phil Thompson - - * qt/qscilexerhtml.cpp, qt/qscilexerhtml.h: - Implemented QsciLexerHTML::autoCompletionFillups() to change the - fillups to "/>". - [8d9c1aad1349] <2.4-maint> - - * qt/qsciscintilla.cpp: - Fixed a regression, and the original bug, in - QsciScintilla::clearAnnotations(). - [fd8746ae2198] <2.4-maint> - - * qt/qscistyle.cpp: - QsciStyle now auto-allocates style numbers from 63 rather than - STYLE_MAX because Scintilla only initially creates enough storage - for that number of styles. - [7c69b0a4ee5b] <2.4-maint> - -2010-07-15 Phil Thompson - - * qt/qscilexerverilog.cpp, qt/qscintilla.pro: - Fixed a bug in QsciLexerVerilog that meant that the Keyword style - was being completely ignored. - [09e28404476a] <2.4-maint> - -2010-07-12 Phil Thompson - - * .hgtags: - Added tag 2.4.4 for changeset c61a49005995 - [4c98368d9bea] <2.4-maint> - - * NEWS: - Released as v2.4.4. - [c61a49005995] [2.4.4] <2.4-maint> - -2010-06-08 Phil Thompson - - * Makefile, qt/qsciscintillabase.cpp: - Pop-lists now get removed when the main widget loses focus. - [169fa07f52ab] <2.4-maint> - -2010-06-05 Phil Thompson - - * qt/ScintillaQt.cpp: - Changed SCN_MODIFIED to deal with text being NULL. - [68148fa857ab] <2.4-maint> - -2010-06-03 Phil Thompson - - * qt/ScintillaQt.cpp: - The SCN_MODIFIED signal now tries to make sure that the text passed - is valid. - [90e3461f410f] <2.4-maint> - -2010-04-22 Phil Thompson - - * qt/qsciscintilla.cpp, qt/qsciscintilla.h: - QsciScintilla::markerDefine() now allows existing markers to be - redefined if an explicit marker number is given. - [63f1a7a1d8e2] <2.4-maint> - - * qt/ScintillaQt.cpp, qt/qsciscintilla.cpp, qt/qsciscintillabase.cpp, - qt/qsciscintillabase.h: - Fixed the drag and drop behaviour so that a move automatically turns - into a copy when the mouse leaves the widget. - [4dab09799716] <2.4-maint> - -2010-04-21 Phil Thompson - - * qt/PlatQt.cpp, qt/ScintillaQt.cpp: - Fixed build problems against Qt v3. - [71168072ac9b] <2.4-maint> - - * Python/sip/qsciscintillabase.sip, qt/ScintillaQt.cpp, - qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Added QsciScintillaBase::fromMimeData(). - [b86a15672079] <2.4-maint> - - * Python/sip/qsciscintillabase.sip, qt/ScintillaQt.cpp, - qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Renamed QsciScintillaBase::createMimeData() to toMimeData(). - [6f5837334dde] <2.4-maint> - -2010-04-20 Phil Thompson - - * Python/sip/qsciscintillabase.sip, qt/ScintillaQt.cpp, - qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Added QsciScintillaBase::canInsertFromMimeData(). - [bbba2c1799ef] <2.4-maint> - - * Python/sip/qsciscintillabase.sip, qt/ScintillaQt.cpp, - qt/qscintilla.pro, qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Added QsciScintillaBase::createMimeData(). - [b2c3e3a9b43d] <2.4-maint> - -2010-03-17 Phil Thompson - - * .hgtags: - Added tag 2.4.3 for changeset 786429e0227d - [1931843aec48] <2.4-maint> - - * NEWS, build.py: - Fixed the generation of the change log after tagging a release. - Updated the NEWS file. Released as v2.4.3. - [786429e0227d] [2.4.3] <2.4-maint> - -2010-02-23 Phil Thompson - - * qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Reverted the setting of the alpha component in - setMarkerForegroundColor() (at least until SC_MARK_UNDERLINE is - supported). - [111da2e01c5e] <2.4-maint> - - * qt/PlatQt.cpp, qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Fixed the very broken support for the alpha component with Qt4. - [b1d73c7f447b] <2.4-maint> - - * Python/sip/qsciscintilla.sip, qt/qscintilla.pro, - qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Added QsciScintilla::clearFolds() to clear all current folds - (typically prior to disabling folding). - [4f4266da1962] <2.4-maint> - -2010-02-15 Phil Thompson - - * Makefile: - Switched the build system to Qt v4.6.2. - [f023013b79e4] <2.4-maint> - -2010-02-07 Phil Thompson - - * qt/qscidocument.cpp: - Fixed a bug in the handling of multiple views of a document. - [8b4aa000df1c] <2.4-maint> - -2010-01-31 Phil Thompson - - * Makefile, build.py: - Minor tidy ups for the internal build system. - [c3a41d195b8a] <2.4-maint> - -2010-01-30 Phil Thompson - - * Makefile, Python/configure.py, build.py, lib/README.doc, - lib/README.svn, lib/qscintilla.dxy, qt/qsciglobal.h: - Changes to the internal build system required by the migration to - Mercurial. - [607e474dfd28] <2.4-maint> - -2010-01-29 phil - - * .hgtags: - Import from SVN. - [49d5a0d80211] - -2008-08-31 phil - - * qt/qscintilla_de.qm, qt/qscintilla_de.ts: - Updated German translations from Detlev. - [d2a7db9cb3f6] <2.2-maint> - -2008-08-17 phil - - * Python/sip/qscilexeryaml.sip, Python/sip/qscimodcommon.sip, - qt/qscilexeryaml.cpp, qt/qscilexeryaml.h, qt/qscintilla.pro: - Added the QsciLexerYAML class. - [87f48847405d] <2.2-maint> - - * Python/sip/qsciscintilla.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - The fold margin can now be specified by an extra argument to - QsciScintilla::setFolding(). - [ae43393149f0] <2.2-maint> - - * qt/qscilexerlua.cpp, qt/qscilexerlua.h, qt/qscilexerperl.cpp, - qt/qscilexerperl.h: - Implemented autoCompletionWordSeparators() for QsciLexerPerl and - QsciLexerLua. - [1bfc2fc0fa36] <2.2-maint> - - * qt/ListBoxQt.cpp, qt/ListBoxQt.h, qt/qscintilla_de.qm, - qt/qscintilla_de.ts, qt/qsciscintilla.cpp, qt/qsciscintilla.h: - User lists can now handle entries with embedded spaces. Updated - German translations from Detlev. - [b5e413c95aff] <2.2-maint> - -2008-08-16 phil - - * Python/sip/qscilexerxml.sip, Python/sip/qscimodcommon.sip, - qt/qscilexerhtml.cpp, qt/qscilexerxml.cpp, qt/qscilexerxml.h, - qt/qscintilla.pro: - Added the QsciLexerXML class. - [643a3e847646] <2.2-maint> - - * Python/sip/qscilexerpostscript.sip, Python/sip/qscimodcommon.sip, - qt/qscilexerpostscript.cpp, qt/qscilexerpostscript.h, - qt/qscintilla.pro, qt/qscintilla_de.qm, qt/qscintilla_de.ts: - Added the QsciLexerPostScript class. Updated German translations - from Detlev. - [3e4695d615b0] <2.2-maint> - -2008-08-10 phil - - * Python/sip/qscilexerpascal.sip, Python/sip/qscimodcommon.sip, - qt/qscilexerpascal.cpp, qt/qscilexerpascal.h, qt/qscintilla.pro: - Added the QsciLexerPascal class. - [2712538aa17c] <2.2-maint> - - * Makefile, Python/sip/qscilexerfortran.sip, - Python/sip/qscilexerfortran77.sip, Python/sip/qscimodcommon.sip, - qt/qscilexerfortran.cpp, qt/qscilexerfortran.h, - qt/qscilexerfortran77.cpp, qt/qscilexerfortran77.h, - qt/qscintilla.pro: - Added the QsciLexerFortran77 and QsciLexerFortran classes. - [e72f0ce049ab] <2.2-maint> - -2008-07-03 phil - - * lib/README.doc, qt/qscintilla.pro: - Updated the Windows installation instructions for Qt3. Backed out - the use of version numbers on Windows because it breaks - compatibility with Qt3. (It may go back for Qt4 if that proves not - to be a problem.) - [82b976c98cf9] <2.2-maint> - -2008-06-19 phil - - * build.py, qt/qscintilla.pro: - Added the DLL metadata for Windows. - [0f65670eeb66] <2.2-maint> - -2008-06-16 phil - - * Python/sip/qsciscintillabase.sip, qt/qscintilla.pro, - qt/qsciscintillabase.h: - Added support for the new Scintilla 1.76 features and lexers. - [fff8c7e1940e] <2.2-maint> - - * doc/ScintillaDoc.html, doc/ScintillaDownload.html, - doc/ScintillaHistory.html, doc/ScintillaRelated.html, - doc/index.html, gtk/PlatGTK.cxx, gtk/ScintillaGTK.cxx, gtk/makefile, - gtk/scintilla.mak, include/Platform.h, include/SciLexer.h, - include/Scintilla.h, include/Scintilla.iface, macosx/ExtInput.cxx, - macosx/ExtInput.h, macosx/PlatMacOSX.cxx, macosx/PlatMacOSX.h, - macosx/QuartzTextLayout.h, macosx/QuartzTextStyle.h, - macosx/QuartzTextStyleAttribute.h, macosx/ScintillaMacOSX.cxx, - macosx/ScintillaMacOSX.h, macosx/TView.cxx, macosx/makefile, - src/CellBuffer.cxx, src/Editor.cxx, src/Editor.h, src/KeyWords.cxx, - src/LexCPP.cxx, src/LexGen.py, src/LexMagik.cxx, src/LexMatlab.cxx, - src/LexPerl.cxx, src/LexPowerShell.cxx, src/LineMarker.cxx, - src/RunStyles.cxx, src/RunStyles.h, vcbuild/SciLexer.dsp, - version.txt, win32/PlatWin.cxx, win32/ScintRes.rc, - win32/ScintillaWin.cxx, win32/makefile, win32/scintilla.mak, - win32/scintilla_vc6.mak: - Merged Scintilla v1.76. - [a3a5181efbb0] <2.2-maint> - -2008-06-10 phil - - * Python/configure.py: - Fixed a configuration problem with the Python bindings when building - against a Windows DLL of QScintilla. - [7d9af6e97d2c] <2.2-maint> - -2008-06-07 phil - - * Makefile, lib/LICENSE.commercial, lib/README.doc, qt/qscimacro.cpp, - qt/qscimacro.h: - Fixed a regression in macro recording. - [3a2c8add1382] <2.2-maint> - -2008-03-09 phil - - * lib/qscintilla.dxy: - Fixed the doxygen configuration file for Qt4. - [2d3ab16b71cb] <2.2-maint> - -2008-03-06 phil - - * qt/qscintilla_de.qm, qt/qscintilla_de.ts: - Updated German translations from Detlev. - [478c96e64584] <2.2-maint> - - * include/Platform.h: - By default build with (possibly over-aggressive) assertions - disabled. - [a07535b643ef] <2.2-maint> - -2008-03-05 phil - - * lib/qscintilla.dxy: - Updated the doxygen configuration to remove some warnings. - [bf028c1824c3] <2.2-maint> - -2008-03-04 phil - - * Python/sip/qscilexertcl.sip, Python/sip/qscimodcommon.sip, - qt/qscilexertcl.cpp, qt/qscilexertcl.h, qt/qscintilla.pro: - Added the QsciLexerTCL class. - [a008135167cf] <2.2-maint> - -2008-11-17 phil - - * NEWS: - Released as v2.3.2. - [6ae4c306fcf1] [2.3.2] <2.3-maint> - -2008-11-16 phil - - * qt/qsciscintilla.cpp, qt/qsciscintillabase.h: - The default lexer is now SCLEX_CONTAINER rather than SCLEX_NULL. - [abffc574bda0] <2.3-maint> - -2008-11-14 phil - - * qt/qscilexerpython.cpp, qt/qscilexerxml.cpp, qt/qscintilla.pro: - The XML lexer now styles embedded scripts properly. (An API call to - disable this will be added in a future version.) - [be4308ba5fc9] <2.3-maint> - - * UTF-8-demo.txt, qt/PlatQt.cpp: - Fixed a regression in measuring character widths introduced when - fixing the problem with kerned fonts. - [835cbce25ae2] <2.3-maint> - -2008-11-08 phil - - * NEWS: - Released as v2.3.1. - [91ec01d1c22c] [2.3.1] <2.3-maint> - - * NEWS, Python/sip/qsciscintilla.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added QsciScintilla::wordAtPoint() based on a patch from Andrea - Battisti. - [072c84e5baa7] <2.3-maint> - -2008-11-07 phil - - * qt/qsciscintilla.cpp: - Changing the current lexer while text is displayed should now be - handled properly. (However the XML lexer seems buggy in this - regard.) - [ef0fcd30ff99] <2.3-maint> - - * qt/PlatQt.cpp: - Fixed a bug in the calculation of character positions when kerning - was in effect. This cause the caret to be displayed too far to the - right. - [225bf588aeeb] <2.3-maint> - -2008-11-01 phil - - * NEWS: - Updated the NEWS file. - [3f777fbcaa87] <2.3-maint> - -2008-10-21 phil - - * qt/qscintilla_de.ts: - Updated German translations from Detlev. - [055862970575] <2.3-maint> - -2008-10-20 phil - - * Python/configure.py, Python/sip/qscilexercss.sip, - Python/sip/qscilexerdiff.sip, Python/sip/qsciscintillabase.sip, - qt/ScintillaQt.cpp, qt/qscilexercss.cpp, qt/qscilexercss.h, - qt/qscilexerdiff.cpp, qt/qscilexerdiff.h, qt/qscintilla.pro, - qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_fr.ts, - qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts, qt/qsciscintilla.cpp, - qt/qsciscintillabase.h: - Updated the QScintilla API to accomodate changes in Scintilla v1.77. - [9876dd8de8a4] <2.3-maint> - - * README, doc/ScintillaDoc.html, doc/ScintillaDownload.html, - doc/ScintillaHistory.html, doc/ScintillaRelated.html, - doc/ScintillaToDo.html, doc/index.html, gtk/PlatGTK.cxx, - gtk/ScintillaGTK.cxx, gtk/makefile, gtk/scintilla.mak, - include/SciLexer.h, include/Scintilla.h, include/Scintilla.iface, - macosx/makefile, src/CellBuffer.cxx, src/CellBuffer.h, - src/Document.cxx, src/Document.h, src/Editor.cxx, - src/ExternalLexer.cxx, src/KeyWords.cxx, src/LexAbaqus.cxx, - src/LexAsm.cxx, src/LexBash.cxx, src/LexCPP.cxx, src/LexCSS.cxx, - src/LexFortran.cxx, src/LexGen.py, src/LexHTML.cxx, - src/LexHaskell.cxx, src/LexInno.cxx, src/LexLua.cxx, - src/LexMySQL.cxx, src/LexNsis.cxx, src/LexOthers.cxx, - src/LexPerl.cxx, src/LexProgress.cxx, src/LexRuby.cxx, - src/LexTeX.cxx, src/LexVerilog.cxx, src/LexYAML.cxx, - src/RESearch.cxx, src/RESearch.h, src/RunStyles.h, - src/ScintillaBase.cxx, src/SplitVector.h, vcbuild/SciLexer.dsp, - version.txt, win32/PlatWin.cxx, win32/ScintRes.rc, - win32/ScintillaWin.cxx, win32/makefile, win32/scintilla.mak, - win32/scintilla_vc6.mak: - Initial merge of Scintilla 1.77. - [39acb5c4e434] <2.3-maint> - -2008-10-12 phil - - * qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Applied a patch from Detlev that fixes issues with the document - modification notification and setting different fold margins. - [3af8eefae9f9] <2.3-maint> - - * Python/sip/qscicommand.sip, Python/sip/qscicommandset.sip, - Python/sip/qsciscintilla.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added the read() and write() methods to QsciScintilla in - anticipation of PyQt dropping support for QStrings. This will allow - file to be read and written while keeping the number of conversions - to the minimum. - [85e0d79e204f] <2.3-maint> - - * Python/sip/qsciscintilla.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - QsciScintilla::setSelection() is now implemented using SCI_SETSEL so - that the carat can be left at either the start or the end of the - selection. Exposed QsciScintilla::positionFromLineIndex() and - QsciScintilla::lineIndexFromPosition(). - [acdba5c2e772] <2.3-maint> - -2008-10-04 phil - - * qt/qscidocument.cpp, qt/qscidocument.h, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - The modified status of a document is now maintained on a per - document basis rather than a per editor basis. - [744886134592] <2.3-maint> - -2008-10-02 phil - - * qt/qscilexerpython.cpp: - Added 'with' to the list of keywords in the Python lexer for Python - v2.6. - [e33bbbc426ab] <2.3-maint> - -2010-01-20 phil - - * Makefile, NEWS: - Updated the build system to Qt v4.6.1. Released as v2.4.2. - [73732e5bae08] [2.4.2] <2.4-maint> - -2010-01-18 phil - - * qt/qscintilla_es.qm, qt/qscintilla_es.ts: - Updated Spanish translations from Jaime Seuma. - [3b911e69696d] <2.4-maint> - -2010-01-15 phil - - * Python/configure.py: - The Python bindings now check for SIP v4.10. - [8d5f4957a07c] <2.4-maint> - - * qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_es.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Updated the .ts files. - [15c647ac0c42] <2.4-maint> - - * NEWS, build.py: - Fixed the build system for Qt v3 and v4 prior to v4.5. - [1b5bea85a3bf] <2.4-maint> - -2010-01-14 phil - - * NEWS, lib/LICENSE.commercial.short, lib/LICENSE.gpl.short: - Released as v2.4.1. - [a04b69746aa6] [2.4.1] <2.4-maint> - -2009-12-22 phil - - * lib/gen_python3_api.py, qsci/api/python/Python-3.1.api: - Added the API file for Python v3.1. - [116c24ab58b2] <2.4-maint> - - * NEWS, Python/configure.py: - Added support for automatically generated docstrings. - [3d316b4f222b] <2.4-maint> - -2009-12-11 phil - - * Makefile, qt/PlatQt.cpp: - Fixed a performance problem when displaying very long lines. - [d3fe67ad2eb5] <2.4-maint> - -2009-11-01 phil - - * qt/qsciapis.cpp: - Fixed a possible crash in the handling of call tips. - [6248caa24fec] <2.4-maint> - - * qt/SciClasses.cpp: - Applied the workaround for the autocomplete focus bug under Gnome's - window manager which (appears) to work with current versions of Qt - across all platforms. - [f709f1518e70] <2.4-maint> - - * Makefile, qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Make sure a lexer is fully detached when a QScintilla instance is - destroyed. - [db47764231d2] <2.4-maint> - -2009-08-19 phil - - * lib/LICENSE.gpl.short, qt/qscintilla_de.qm, qt/qscintilla_de.ts: - Updated German translations from Detlev. - [458b60ec031e] <2.4-maint> - -2009-08-09 phil - - * Python/sip/qscilexerverilog.sip, Python/sip/qscimodcommon.sip, - qt/qscilexerverilog.cpp, qt/qscilexerverilog.h, qt/qscintilla.pro: - Added the QsciLexerVerilog class. - [86b2aceac88c] <2.4-maint> - - * Makefile, Python/sip/qscilexerspice.sip, - Python/sip/qscimodcommon.sip, lib/LICENSE.commercial, lib - /OPENSOURCE-NOTICE.TXT, lib/README.doc, qt/qscilexerspice.cpp, - qt/qscilexerspice.h, qt/qscintilla.pro: - Added the QsciLexerSpice class. - [56532ec00839] <2.4-maint> - -2009-06-05 phil - - * NEWS, lib/LICENSE.commercial: - Released as v2.4. - [612b1bcb8223] [2.4] - -2009-06-03 phil - - * NEWS, qt/qscistyledtext.h: - Fixed a bug building on Qt v3. - [88ebc67fdff4] - -2009-05-30 phil - - * qt/ScintillaQt.cpp: - Applied a fix for copying UTF-8 text to the X clipboard from Lars - Reichelt. - [e59fa72c2e2d] - -2009-05-27 phil - - * qt/qscilexercustom.h: - Fixed a missing forward declaration in qscilexercustom.h. - [0018449ee6aa] - -2009-05-25 phil - - * qt/qscilexercustom.cpp: - Don't ask the custom lexer to style zero characters. - [6ae021232f4f] - -2009-05-19 phil - - * NEWS, qt/qscintilla.pro, qt/qscintilla_cs.qm, qt/qscintilla_es.qm, - qt/qscintilla_es.ts, qt/qscintilla_fr.qm, qt/qscintilla_pt_br.qm, - qt/qscintilla_ru.qm: - Added Spanish translations from Jaime Seuma. - [0cdbee8db9af] - - * qt/qsciscintilla.cpp: - A minor fix for ancient C++ compilers. - [0523c3a0e0aa] - -2009-05-18 phil - - * NEWS, Python/sip/qscilexer.sip, Python/sip/qscilexercustom.sip, - Python/sip/qscimodcommon.sip, Python/sip/qsciscintilla.sip, - qt/qscilexer.cpp, qt/qscilexer.h, qt/qscilexercustom.cpp, - qt/qscilexercustom.h, qt/qscintilla.pro, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added QsciScintilla::annotation(). Added QsciLexerCustom (completely - untested) and supporting changes to QsciLexer. - [382d5b86f600] - -2009-05-17 phil - - * qt/qscintilla_cs.ts, qt/qscintilla_de.qm, qt/qscintilla_de.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Updated translations from Detlev. - [0b8c8438e464] - -2009-05-09 phil - - * NEWS, Python/sip/qsciscintilla.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added support for text margins. - [be9db7d41b50] - - * qt/PlatQt.cpp, qt/qsciscintilla.cpp, qt/qsciscintilla.h, - qt/qscistyledtext.cpp, qt/qscistyledtext.h: - Debugged the support for annotations. Tidied up the QString to - Scintilla string conversions. - [573199665222] - -2009-05-08 phil - - * NEWS, Python/sip/qscimodcommon.sip, Python/sip/qsciscintilla.sip, - Python/sip/qscistyle.sip, Python/sip/qscistyledtext.sip, - qt/qscicommand.h, qt/qscimacro.h, qt/qscintilla.pro, - qt/qsciscintilla.cpp, qt/qsciscintilla.h, qt/qscistyle.cpp, - qt/qscistyle.h, qt/qscistyledtext.cpp, qt/qscistyledtext.h: - Implemented the rest of the annotation API - still needs debugging. - [7f23400d2416] - -2009-05-07 phil - - * NEWS, qt/qscintilla.pro, qt/qscistyle.cpp, qt/qscistyle.h: - Added the QsciStyle class. - [bf8e3e02071e] - -2009-05-06 phil - - * qt/qsciscintillabase.cpp: - Fixed the key event handling when the text() is empty and the key() - should be used - only seems to happen with OS/X. - [868a146b019f] - -2009-05-03 phil - - * Makefile, NEWS, Python/configure.py, Python/sip/qscicommand.sip, - Python/sip/qscicommandset.sip, Python/sip/qscilexer.sip, - Python/sip/qscilexercpp.sip, Python/sip/qscilexercss.sip, - Python/sip/qscilexerdiff.sip, Python/sip/qscilexerhtml.sip, - Python/sip/qscilexerpascal.sip, Python/sip/qscilexerperl.sip, - Python/sip/qscilexerpython.sip, Python/sip/qscilexerxml.sip, - Python/sip/qsciscintilla.sip, Python/sip/qsciscintillabase.sip, - README, UTF-8-demo.txt, doc/ScintillaDoc.html, - doc/ScintillaDownload.html, doc/ScintillaHistory.html, - doc/ScintillaRelated.html, doc/ScintillaToDo.html, - doc/annotations.png, doc/index.html, doc/styledmargin.png, - gtk/PlatGTK.cxx, gtk/ScintillaGTK.cxx, gtk/deps.mak, gtk/makefile, - gtk/scintilla.mak, include/Face.py, include/HFacer.py, - include/SciLexer.h, include/Scintilla.h, include/Scintilla.iface, - include/ScintillaWidget.h, lib/LICENSE.commercial, - macosx/PlatMacOSX.cxx, macosx/makefile, qt/PlatQt.cpp, - qt/ScintillaQt.cpp, qt/qsciapis.cpp, qt/qscidocument.cpp, - qt/qscidocument.h, qt/qscilexer.cpp, qt/qscilexer.h, - qt/qscilexercpp.cpp, qt/qscilexercpp.h, qt/qscilexercss.cpp, - qt/qscilexercss.h, qt/qscilexerdiff.cpp, qt/qscilexerdiff.h, - qt/qscilexerhtml.cpp, qt/qscilexerhtml.h, qt/qscilexerpascal.cpp, - qt/qscilexerpascal.h, qt/qscilexerperl.cpp, qt/qscilexerperl.h, - qt/qscilexerpython.cpp, qt/qscilexerpython.h, qt/qscilexerxml.cpp, - qt/qscilexerxml.h, qt/qscintilla.pro, qt/qscintilla_cs.ts, - qt/qscintilla_de.ts, qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, - qt/qscintilla_ru.ts, qt/qsciscintilla.cpp, qt/qsciscintilla.h, - qt/qsciscintillabase.h, src/CellBuffer.cxx, src/CellBuffer.h, - src/Document.cxx, src/Document.h, src/Editor.cxx, src/Editor.h, - src/ExternalLexer.cxx, src/Indicator.cxx, src/Indicator.h, - src/KeyWords.cxx, src/LexAU3.cxx, src/LexAbaqus.cxx, src/LexAsm.cxx, - src/LexBash.cxx, src/LexCOBOL.cxx, src/LexCPP.cxx, src/LexCSS.cxx, - src/LexD.cxx, src/LexFortran.cxx, src/LexGen.py, src/LexHTML.cxx, - src/LexHaskell.cxx, src/LexInno.cxx, src/LexLua.cxx, - src/LexMySQL.cxx, src/LexNimrod.cxx, src/LexNsis.cxx, - src/LexOthers.cxx, src/LexPascal.cxx, src/LexPerl.cxx, - src/LexPowerPro.cxx, src/LexProgress.cxx, src/LexPython.cxx, - src/LexRuby.cxx, src/LexSML.cxx, src/LexSQL.cxx, src/LexSorcus.cxx, - src/LexTACL.cxx, src/LexTADS3.cxx, src/LexTAL.cxx, src/LexTeX.cxx, - src/LexVerilog.cxx, src/LexYAML.cxx, src/PerLine.cxx, src/PerLine.h, - src/PositionCache.cxx, src/RESearch.cxx, src/RESearch.h, - src/RunStyles.h, src/SciTE.properties, src/ScintillaBase.cxx, - src/SplitVector.h, src/UniConversion.cxx, src/ViewStyle.cxx, - src/ViewStyle.h, vcbuild/SciLexer.dsp, version.txt, - win32/PlatWin.cxx, win32/ScintRes.rc, win32/ScintillaWin.cxx, - win32/makefile, win32/scintilla.mak, win32/scintilla_vc6.mak: - Merged the v2.3 branch onto the trunk. - [1bb3d2b01123] - -2008-09-20 phil - - * Makefile, NEWS, lib/README.doc: - Released as v2.3. - [8fd73a9a9d66] [2.3] - -2008-09-17 phil - - * NEWS, Python/sip/qsciscintilla.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added QsciScintilla::apiContext() for further open up the auto- - completion and call tips support. - [a6291ea6dd37] - -2008-09-16 phil - - * Python/configure.py, lib/gen_python_api.py, - qsci/api/python/Python-2.6.api, qt/qsciapis.h: - Added the API file for Python v2.6rc1. Fixed a typo in the help for - the Python bindings configure.py. - [ac10be3cc7fb] - -2008-09-03 phil - - * qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_fr.ts, - qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Updated the i18n .ts files. - [b73beac06e0f] - -2008-09-01 phil - - * lib/README.doc: - Updated the Windows installation notes to cover the need to manually - install the DLL when using Qt3. - [17019ebfab36] - - * lib/README.doc, qt/qsciscintilla.cpp: - Fixed a regression in the highlighting of call tip arguments. - Updated the Windows installation notes to say that any header files - installed from a previous build should first be removed. - [cb3f27b93323] - -2008-08-31 phil - - * NEWS, Python/configure.py, Python/sip/qsciabstractapis.sip, - Python/sip/qsciapis.sip, Python/sip/qscilexer.sip, - Python/sip/qscimodcommon.sip, Python/sip/qsciscintillabase.sip, - qt/qsciabstractapis.cpp, qt/qsciabstractapis.h, qt/qsciapis.cpp, - qt/qsciapis.h, qt/qscilexer.cpp, qt/qscilexer.h, qt/qscintilla.pro, - qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Added the QsciAbstractAPIs class to allow applications to provide - their own implementation of APIs. - [eb5a8a602e5d] - - * Makefile, Python/configure.py, Python/sip/qscilexerfortran.sip, - Python/sip/qscilexerfortran77.sip, Python/sip/qscilexerpascal.sip, - Python/sip/qscilexerpostscript.sip, Python/sip/qscilexertcl.sip, - Python/sip/qscilexerxml.sip, Python/sip/qscilexeryaml.sip, - Python/sip/qscimodcommon.sip, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase.sip, build.py, doc/ScintillaDoc.html, - doc/ScintillaDownload.html, doc/ScintillaHistory.html, - doc/ScintillaRelated.html, doc/index.html, gtk/PlatGTK.cxx, - gtk/ScintillaGTK.cxx, gtk/makefile, gtk/scintilla.mak, - include/Platform.h, include/SciLexer.h, include/Scintilla.h, - include/Scintilla.iface, lib/LICENSE.commercial, lib/README.doc, - lib/qscintilla.dxy, macosx/ExtInput.cxx, macosx/ExtInput.h, - macosx/PlatMacOSX.cxx, macosx/PlatMacOSX.h, - macosx/QuartzTextLayout.h, macosx/QuartzTextStyle.h, - macosx/QuartzTextStyleAttribute.h, macosx/ScintillaMacOSX.cxx, - macosx/ScintillaMacOSX.h, macosx/TView.cxx, macosx/makefile, - qt/ListBoxQt.cpp, qt/ListBoxQt.h, qt/qscilexerfortran.cpp, - qt/qscilexerfortran.h, qt/qscilexerfortran77.cpp, - qt/qscilexerfortran77.h, qt/qscilexerhtml.cpp, qt/qscilexerlua.cpp, - qt/qscilexerlua.h, qt/qscilexerpascal.cpp, qt/qscilexerpascal.h, - qt/qscilexerperl.cpp, qt/qscilexerperl.h, - qt/qscilexerpostscript.cpp, qt/qscilexerpostscript.h, - qt/qscilexertcl.cpp, qt/qscilexertcl.h, qt/qscilexerxml.cpp, - qt/qscilexerxml.h, qt/qscilexeryaml.cpp, qt/qscilexeryaml.h, - qt/qscimacro.cpp, qt/qscimacro.h, qt/qscintilla.pro, - qt/qscintilla_de.qm, qt/qscintilla_de.ts, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.h, src/CellBuffer.cxx, - src/Editor.cxx, src/Editor.h, src/KeyWords.cxx, src/LexCPP.cxx, - src/LexGen.py, src/LexMagik.cxx, src/LexMatlab.cxx, src/LexPerl.cxx, - src/LexPowerShell.cxx, src/LineMarker.cxx, src/RunStyles.cxx, - src/RunStyles.h, vcbuild/SciLexer.dsp, version.txt, - win32/PlatWin.cxx, win32/ScintRes.rc, win32/ScintillaWin.cxx, - win32/makefile, win32/scintilla.mak, win32/scintilla_vc6.mak: - Merged the v2.2 maintenance branch. - [cd784c60bcc7] - -2008-02-27 phil - - * NEWS, build.py, lib/GPL_EXCEPTION.TXT, lib/LICENSE.GPL2, - lib/LICENSE.GPL3, lib/LICENSE.commercial, - lib/LICENSE.commercial.short, lib/LICENSE.gpl, - lib/LICENSE.gpl.short, lib/OPENSOURCE-NOTICE.TXT: - Updated the licenses to be in line with the the current Qt licenses, - including GPL v3. Released as v2.2. - [a039ca791129] [2.2] - -2008-02-23 phil - - * Makefile, qt/PlatQt.cpp: - Switched to Qt v4.3.4. Further tweaks for Windows64 support. - [3ae9686f38e6] - -2008-02-22 phil - - * Makefile, NEWS, Python/sip/qsciscintillabase.sip, qt/PlatQt.cpp, - qt/ScintillaQt.cpp, qt/qscidocument.cpp, qt/qscimacro.cpp, - qt/qscintilla.pro, qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Several fixes for Windows64 support based on a patch from Randall - Frank. - [2c753ee01c42] - -2008-02-09 phil - - * Python/configure.py, lib/README.doc, qt/qscintilla.pro: - It's no longer necessary to set DYLD_LIBRARY_PATH when using the - Python bindings. - [d1098424aed1] - -2008-02-03 phil - - * Python/sip/qscilexerruby.sip: - Added the missing QsciLexerRuby.Error to the Python bindings. - [0b4f06a30251] - -2008-01-20 phil - - * designer-Qt4/qscintillaplugin.cpp, designer-Qt4/qscintillaplugin.h: - Fixed a problem with the Qt4 Designer plugin on Leopard. - [5450a1bc62df] - -2008-01-11 phil - - * qt/SciClasses.cpp, qt/qsciscintillabase.cpp: - Hopefully fixed shortcuts and accelerators when the autocompletion - list is displayed. - [8304a1f4e36b] - -2008-01-06 phil - - * qt/SciClasses.cpp: - Hopefully fixed a bug stopping normal typing when the autocompletion - list is being displayed. - [2db0cc8fa158] - -2008-01-03 phil - - * lib/LICENSE.commercial.short, lib/LICENSE.gpl, - lib/LICENSE.gpl.short, lib/README.doc, qt/qsciscintillabase.cpp: - Fixed a Qt3 compilation bug. Updated the copyright notices. - [cf238f41fb54] - -2007-12-30 phil - - * qt/SciClasses.cpp, qt/SciClasses.h, qt/qsciscintillabase.cpp: - Hopefully fixed the problems with the auto-completion popup on all - platforms (not tested on Mac). - [585aa7e4e59f] - -2007-12-29 phil - - * qt/SciClasses.cpp: - Remove the use of the internal Tooltip widget flag so that the X11 - auto-completion list now has the same problems as the Windows - version. (Prior to fixing the problem properly.) - [93d584d099db] - -2007-12-23 phil - - * qt/ScintillaQt.cpp: - Fixed DND problems with Qt4. - [23f8c1a7c4c7] - - * qt/qsciscintilla.cpp: - Fix from Detlev for an infinite loop caused by calling - getCursorPosition() when Scintilla reports a position past the end - of the text. - [dd99ade93fa6] - -2007-12-05 phil - - * qt/qscilexerperl.cpp, qt/qscintilla_cs.ts, qt/qscintilla_de.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Fixed a silly typo in the updated Perl lexer. - [0e290eb71572] - - * qt/qscintilla_de.qm: - Updated German translations from Detlev. - [e820d3c167f5] - - * Makefile: - Switched the internal build system to Qt v4.3.3. - [df2d877e2422] - -2007-12-04 phil - - * qt/qscintilla_cs.ts, qt/qscintilla_de.ts, qt/qscintilla_fr.ts, - qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Updated the translation source files. - [1fb11f16d750] - - * Python/sip/qscilexerperl.sip, Python/sip/qsciscintillabase.sip, - doc/ScintillaDoc.html, doc/ScintillaDownload.html, - doc/ScintillaHistory.html, doc/ScintillaRelated.html, - doc/index.html, gtk/PlatGTK.cxx, gtk/ScintillaGTK.cxx, gtk/makefile, - gtk/scintilla.mak, include/Platform.h, include/PropSet.h, - include/SciLexer.h, include/Scintilla.h, include/Scintilla.iface, - lib/README.svn, macosx/PlatMacOSX.cxx, macosx/ScintillaMacOSX.h, - macosx/makefile, qt/PlatQt.cpp, qt/qscilexer.cpp, qt/qscilexer.h, - qt/qscilexerperl.cpp, qt/qscilexerperl.h, qt/qscilexerpython.cpp, - qt/qscilexerpython.h, qt/qscintilla.pro, qt/qsciscintilla.cpp, - qt/qsciscintillabase.h, src/CellBuffer.cxx, src/CellBuffer.h, - src/ContractionState.cxx, src/ContractionState.h, src/Document.cxx, - src/Document.h, src/DocumentAccessor.cxx, src/Editor.cxx, - src/Editor.h, src/KeyWords.cxx, src/LexAPDL.cxx, src/LexASY.cxx, - src/LexAU3.cxx, src/LexAbaqus.cxx, src/LexBash.cxx, src/LexCPP.cxx, - src/LexGen.py, src/LexHTML.cxx, src/LexHaskell.cxx, - src/LexMetapost.cxx, src/LexOthers.cxx, src/LexPerl.cxx, - src/LexPython.cxx, src/LexR.cxx, src/LexSQL.cxx, src/LexTeX.cxx, - src/LexYAML.cxx, src/Partitioning.h, src/PositionCache.cxx, - src/PositionCache.h, src/PropSet.cxx, src/RunStyles.cxx, - src/RunStyles.h, src/ScintillaBase.cxx, src/SplitVector.h, - src/ViewStyle.cxx, src/ViewStyle.h, vcbuild/SciLexer.dsp, - version.txt, win32/PlatWin.cxx, win32/ScintRes.rc, - win32/ScintillaWin.cxx, win32/makefile, win32/scintilla.mak, - win32/scintilla_vc6.mak: - Merged Scintilla v1.75. - [8009a4d7275a] - -2007-11-17 phil - - * qt/SciClasses.cpp, qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Bug fixes for selectAll() and getCursorPosition() from Baz Walter. - [80eecca239b4] - -2007-10-24 phil - - * qt/qsciscintilla.cpp: - Fixed folding for HTML. - [bb6fb6065e30] - -2007-10-14 phil - - * build.py, lib/GPL_EXCEPTION.TXT, lib/GPL_EXCEPTION_ADDENDUM.TXT, - lib/LICENSE.gpl, lib/OPENSOURCE-NOTICE.TXT, qt/qscicommandset.cpp: - Control characters that are not bound to commands (or shortcuts) now - default to doing nothing (rather than inserting the character into - the text). Aligned the GPL license with Trolltech's exceptions. - [148432c68762] - -2007-10-12 phil - - * src/LexHTML.cxx: - Fixed the Scintilla HTML lexer's handling of characters >= 0x80. - [c4e271ce8e96] - -2007-10-05 phil - - * qt/qsciscintillabase.cpp: - Used NoSystemBackground rather than OpaquePaintEvent to eliminate - flicker. - [01a22c66304d] - -2007-10-04 phil - - * Makefile, qt/qsciscintillabase.cpp: - Fixed a flashing effect visible with a non-standard background. - Switched to Qt v4.3.2. - [781c58fcba96] - -2007-09-23 phil - - * qt/qsciapis.h, qt/qscicommand.h, qt/qscicommandset.h, - qt/qscidocument.h, qt/qsciglobal.h, qt/qscilexer.h, - qt/qscilexerbash.h, qt/qscilexerbatch.h, qt/qscilexercmake.h, - qt/qscilexercpp.h, qt/qscilexercsharp.h, qt/qscilexercss.h, - qt/qscilexerd.h, qt/qscilexerdiff.h, qt/qscilexerhtml.h, - qt/qscilexeridl.h, qt/qscilexerjava.h, qt/qscilexerjavascript.h, - qt/qscilexerlua.h, qt/qscilexermakefile.h, qt/qscilexerperl.h, - qt/qscilexerpov.h, qt/qscilexerproperties.h, qt/qscilexerpython.h, - qt/qscilexerruby.h, qt/qscilexersql.h, qt/qscilexertex.h, - qt/qscilexervhdl.h, qt/qscimacro.h, qt/qsciprinter.h, - qt/qsciscintilla.h, qt/qsciscintillabase.h: - Made the recent portabilty changes Mac specific as AIX has a problem - with them. - [0de605d4079f] - -2007-09-16 phil - - * qt/qscilexer.cpp: - A lexer's default colour, paper and font are now written to and read - from the settings. - [45277fc76ace] - -2007-09-15 phil - - * lib/README.doc, qt/qsciapis.h, qt/qscicommand.h, - qt/qscicommandset.h, qt/qscidocument.h, qt/qsciglobal.h, - qt/qscilexer.h, qt/qscilexerbash.h, qt/qscilexerbatch.h, - qt/qscilexercmake.h, qt/qscilexercpp.h, qt/qscilexercsharp.h, - qt/qscilexercss.h, qt/qscilexerd.h, qt/qscilexerdiff.h, - qt/qscilexerhtml.h, qt/qscilexeridl.h, qt/qscilexerjava.h, - qt/qscilexerjavascript.h, qt/qscilexerlua.h, qt/qscilexermakefile.h, - qt/qscilexerperl.h, qt/qscilexerpov.h, qt/qscilexerproperties.h, - qt/qscilexerpython.h, qt/qscilexerruby.h, qt/qscilexersql.h, - qt/qscilexertex.h, qt/qscilexervhdl.h, qt/qscimacro.h, - qt/qsciprinter.h, qt/qsciscintilla.h, qt/qsciscintillabase.h: - Fixed the MacOS build problems when using the binary installer - version of Qt. - [e059a923a447] - - * lib/LICENSE.commercial.short, qt/PlatQt.cpp: - Added the missing WaitMouseMoved() implementation on MacOS. - [78d1c8fc37c0] - -2007-09-10 phil - - * qt/qsciscintilla.cpp, qt/qsciscintilla.h: - QsciScintilla::setFont() now calls QWidget::setFont() so that font() - returns the expected value. - [fd4f577c60ea] - -2007-09-02 phil - - * qt/qsciscintilla.cpp: - Fixed problems which the font size of STYLE_DEFAULT not being - updated when the font of style 0 was changed. Hopefully this fixes - the problems with edge columns and indentation guides. - [ddeccb6f64a0] - -2007-08-12 phil - - * Makefile, lib/LICENSE.commercial.short, lib/LICENSE.gpl.short, - qt/qscintilla.pro: - Applied .pro file fix from Dirk Mueller to add a proper install - rule. - [a3a2e49f1042] - -2007-07-22 phil - - * qt/qscilexer.cpp: - Made sure that the backgound colour of areas of the widget with no - text is updated when QsciLexer.setDefaultPaper() is called. - [065558d2430b] - -2007-07-09 phil - - * qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Explicitly set the style for STYLE_DEFAULT when setting a lexer. - [a95fc3357771] - -2007-06-30 phil - - * Python/sip/qsciscintillabase.sip, doc/ScintillaDoc.html, - doc/ScintillaDownload.html, doc/ScintillaHistory.html, - doc/ScintillaRelated.html, doc/index.html, gtk/PlatGTK.cxx, - gtk/ScintillaGTK.cxx, gtk/deps.mak, gtk/makefile, gtk/scintilla.mak, - include/Accessor.h, include/HFacer.py, include/KeyWords.h, - include/Platform.h, include/PropSet.h, include/SString.h, - include/SciLexer.h, include/Scintilla.h, include/Scintilla.iface, - include/WindowAccessor.h, macosx/PlatMacOSX.cxx, - macosx/PlatMacOSX.h, macosx/QuartzTextLayout.h, - macosx/QuartzTextStyle.h, macosx/QuartzTextStyleAttribute.h, - macosx/SciTest/English.lproj/InfoPlist.strings, - macosx/SciTest/English.lproj/main.nib/classes.nib, - macosx/SciTest/English.lproj/main.nib/info.nib, - macosx/SciTest/English.lproj/main.nib/objects.xib, - macosx/SciTest/Info.plist, - macosx/SciTest/SciTest.xcode/project.pbxproj, - macosx/SciTest/SciTest_Prefix.pch, macosx/SciTest/main.cpp, - macosx/SciTest/version.plist, macosx/ScintillaCallTip.cxx, - macosx/ScintillaCallTip.h, macosx/ScintillaListBox.cxx, - macosx/ScintillaListBox.h, macosx/ScintillaMacOSX.cxx, - macosx/ScintillaMacOSX.h, macosx/TCarbonEvent.cxx, - macosx/TCarbonEvent.h, macosx/TRect.h, macosx/TView.cxx, - macosx/TView.h, macosx/deps.mak, macosx/makefile, - qt/ScintillaQt.cpp, qt/ScintillaQt.h, qt/qscintilla.pro, - qt/qsciscintillabase.h, src/AutoComplete.cxx, src/AutoComplete.h, - src/CallTip.cxx, src/CallTip.h, src/CellBuffer.cxx, - src/CellBuffer.h, src/CharacterSet.h, src/ContractionState.cxx, - src/ContractionState.h, src/Decoration.cxx, src/Decoration.h, - src/Document.cxx, src/Document.h, src/DocumentAccessor.cxx, - src/DocumentAccessor.h, src/Editor.cxx, src/Editor.h, - src/ExternalLexer.cxx, src/ExternalLexer.h, src/Indicator.cxx, - src/Indicator.h, src/KeyMap.cxx, src/KeyMap.h, src/KeyWords.cxx, - src/LexAPDL.cxx, src/LexAU3.cxx, src/LexAVE.cxx, src/LexAda.cxx, - src/LexAsm.cxx, src/LexAsn1.cxx, src/LexBaan.cxx, src/LexBash.cxx, - src/LexBasic.cxx, src/LexBullant.cxx, src/LexCLW.cxx, - src/LexCPP.cxx, src/LexCSS.cxx, src/LexCaml.cxx, src/LexCmake.cxx, - src/LexConf.cxx, src/LexCrontab.cxx, src/LexCsound.cxx, - src/LexD.cxx, src/LexEScript.cxx, src/LexEiffel.cxx, - src/LexErlang.cxx, src/LexFlagship.cxx, src/LexForth.cxx, - src/LexFortran.cxx, src/LexGAP.cxx, src/LexGen.py, - src/LexGui4Cli.cxx, src/LexHTML.cxx, src/LexHaskell.cxx, - src/LexInno.cxx, src/LexKix.cxx, src/LexLisp.cxx, src/LexLout.cxx, - src/LexLua.cxx, src/LexMMIXAL.cxx, src/LexMPT.cxx, src/LexMSSQL.cxx, - src/LexMatlab.cxx, src/LexMetapost.cxx, src/LexNsis.cxx, - src/LexOpal.cxx, src/LexOthers.cxx, src/LexPB.cxx, src/LexPLM.cxx, - src/LexPOV.cxx, src/LexPS.cxx, src/LexPascal.cxx, src/LexPerl.cxx, - src/LexProgress.cxx, src/LexPython.cxx, src/LexRebol.cxx, - src/LexRuby.cxx, src/LexSQL.cxx, src/LexScriptol.cxx, - src/LexSmalltalk.cxx, src/LexSpecman.cxx, src/LexSpice.cxx, - src/LexTADS3.cxx, src/LexTCL.cxx, src/LexTeX.cxx, src/LexVB.cxx, - src/LexVHDL.cxx, src/LexVerilog.cxx, src/LexYAML.cxx, - src/LineMarker.cxx, src/LineMarker.h, src/Partitioning.h, - src/PositionCache.cxx, src/PositionCache.h, src/PropSet.cxx, - src/RESearch.cxx, src/RESearch.h, src/RunStyles.cxx, - src/RunStyles.h, src/SVector.h, src/ScintillaBase.cxx, - src/ScintillaBase.h, src/SplitVector.h, src/Style.cxx, src/Style.h, - src/StyleContext.cxx, src/StyleContext.h, src/UniConversion.cxx, - src/UniConversion.h, src/ViewStyle.cxx, src/ViewStyle.h, - src/WindowAccessor.cxx, src/XPM.cxx, src/XPM.h, - vcbuild/SciLexer.dsp, version.txt, win32/PlatWin.cxx, - win32/ScintRes.rc, win32/ScintillaWin.cxx, win32/deps.mak, - win32/makefile, win32/scintilla.mak, win32/scintilla_vc6.mak, - zipsrc.bat: - Merged Scintilla v1.74. - [04dee9c2424f] - - * Python/sip/qscilexerpython.sip, build.py, qt/qscilexer.cpp, - qt/qscilexerbash.cpp, qt/qscilexerpython.cpp, qt/qscilexerpython.h, - qt/qscintilla.pro: - Fixed comment folding in the Bash lexer. A style is properly - restored when read from QSettings. Removed ./Qsci from the qmake - INCLUDEPATH. Removed the Scintilla version number from generated - filenames. Used fully qualified enum names in the Python lexer so - that the QMetaObject is correct. - [6b27a5b211e0] - -2007-06-01 phil - - * NEWS: - Released as v2.1. - [9976edafc5c1] [2.1] - -2007-05-30 phil - - * Makefile: - Switched the internal build system to Qt v4.3.0. - [49284aa376ef] - - * NEWS, Python/configure.py, Python/sip/qscilexer.sip, - Python/sip/qscilexerbash.sip, Python/sip/qscilexerbatch.sip, - Python/sip/qscilexercmake.sip, Python/sip/qscilexercpp.sip, - Python/sip/qscilexercsharp.sip, Python/sip/qscilexercss.sip, - Python/sip/qscilexerd.sip, Python/sip/qscilexerdiff.sip, - Python/sip/qscilexerhtml.sip, Python/sip/qscilexeridl.sip, - Python/sip/qscilexerjavascript.sip, Python/sip/qscilexerlua.sip, - Python/sip/qscilexermakefile.sip, Python/sip/qscilexerperl.sip, - Python/sip/qscilexerpov.sip, Python/sip/qscilexerproperties.sip, - Python/sip/qscilexerpython.sip, Python/sip/qscilexerruby.sip, - Python/sip/qscilexersql.sip, Python/sip/qscilexertex.sip, - Python/sip/qscilexervhdl.sip, Python/sip/qscimodcommon.sip, - build.py, qt/qscilexer.cpp, qt/qscilexer.h, qt/qscilexerbash.cpp, - qt/qscilexerbash.h, qt/qscilexerbatch.cpp, qt/qscilexerbatch.h, - qt/qscilexercmake.cpp, qt/qscilexercmake.h, qt/qscilexercpp.cpp, - qt/qscilexercpp.h, qt/qscilexercsharp.cpp, qt/qscilexercsharp.h, - qt/qscilexercss.cpp, qt/qscilexercss.h, qt/qscilexerd.cpp, - qt/qscilexerd.h, qt/qscilexerdiff.cpp, qt/qscilexerdiff.h, - qt/qscilexerhtml.cpp, qt/qscilexerhtml.h, qt/qscilexeridl.cpp, - qt/qscilexeridl.h, qt/qscilexerjavascript.cpp, - qt/qscilexerjavascript.h, qt/qscilexerlua.cpp, qt/qscilexerlua.h, - qt/qscilexermakefile.cpp, qt/qscilexermakefile.h, - qt/qscilexerperl.cpp, qt/qscilexerperl.h, qt/qscilexerpov.cpp, - qt/qscilexerpov.h, qt/qscilexerproperties.cpp, - qt/qscilexerproperties.h, qt/qscilexerpython.cpp, - qt/qscilexerpython.h, qt/qscilexerruby.cpp, qt/qscilexerruby.h, - qt/qscilexersql.cpp, qt/qscilexersql.h, qt/qscilexertex.cpp, - qt/qscilexertex.h, qt/qscilexervhdl.cpp, qt/qscilexervhdl.h, - qt/qscintilla.pro: - Lexers now remember their style settings. A lexer no longer has to - be the current lexer when changing a style's color, end-of-line - fill, font or paper. The color(), eolFill(), font() and paper() - methods of QsciLexer now return the current values for a style - rather than the default values. The setDefaultColor(), - setDefaultFont() and setDefaultPaper() methods of QsciLexer are no - longer slots and no longer virtual. The defaultColor(), - defaultFont() and defaultPaper() methods of QsciLexer are no longer - virtual. The color(), eolFill(), font() and paper() methods of all - QsciLexer derived classes (except for QsciLexer itself) have been - renamed defaultColor(), defaultEolFill(), defaultFont() and - defaultPaper() respectively. - [38aeee2a5a36] - -2007-05-28 phil - - * qt/qsciscintilla.cpp: - Set the number of style bits after we've set the lexer. - [84cda9af5b00] - - * Python/configure.py: - Fixed the handling of the %Timeline in the Python bindings. - [4b3146d1a236] - -2007-05-27 phil - - * Python/sip/qsciscintillabase.sip: - Updated the sub-class convertor code in the Python bindings for the - Cmake and VHDL lexers. - [6ab6570728a2] - -2007-05-26 phil - - * NEWS: - Updated the NEWS file. Released as v2.0. - [eec9914d8211] [2.0] - -2007-05-19 phil - - * Python/sip/qsciscintillabase.sip, qt/qsciscintilla.cpp, - qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Added basic input method support for Qt4 so that accented characters - now work. (Although there is still a font problem - at least a text - colour problem.) - [6b41f3694999] - - * qt/qsciapis.cpp, qt/qsciapis.h, qt/qsciscintillabase.cpp: - Fixed building against Qt v3. - [9e9ba05de0fb] - -2007-05-17 phil - - * qt/qsciscintilla.cpp: - Fixed an autocompletion problem where an empty list was being - displayed. - [c7214274017c] - -2007-05-16 phil - - * qt/qsciscintilla.cpp: - Fixed a bug where autocompleting from the document was looking for - preceeding non-word characters as well. - [3ee6fd746d49] - - * qt/qsciscintilla.cpp: - Fixed silly typo that broke call tips. - [05213a8933c2] - -2007-05-09 phil - - * qt/qsciscintilla.cpp: - Fiex an autocompletion bug for words that only had preceding - whitespace. - [a8f3339e02c6] - - * Python/configure.py, lib/gen_python_api.py, - qsci/api/python/Python-2.4.api, qsci/api/python/Python-2.5.api, - qt/qsciapis.cpp, qt/qsciapis.h: - Call tips shouldn't now get confused with commas in the text after - the argument list. The included API files for Python should now be - complete and properly exclude anything beginning with an underscore. - The Python bindings configure.py can now install the API file in a - user supplied directory. - [c7e93dc918de] - - * qt/qscintilla_cs.qm, qt/qscintilla_fr.qm, qt/qscintilla_pt_br.qm, - qt/qscintilla_ru.qm: - Ran lrelease on the project. - [c3ce60078221] - - * Makefile, qt/qscintilla_cs.ts, qt/qscintilla_de.ts, - qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts: - Updated the internal build system to Qt v4.3.0rc1. Ran lupdate on - the project. - [6a86e71a4e26] - -2007-05-08 phil - - * Python/sip/qsciscintilla.sip, qt/qsciapis.cpp, qt/qsciapis.h, - qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Call tips will now show all the tips for a function (in all scopes) - if the current context/scope isn't known. - [cbebccc205c7] - - * Python/sip/qsciscintilla.sip, qt/qsciapis.cpp, qt/qsciapis.h, - qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Added callTipsStyle() and setCallTipsStyle() to QsciScintilla. - [59d453b5da8c] - -2007-05-07 phil - - * qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Autocompletion from documents should now work the same as QScintilla - v1. The only difference is that the list does not contain the - preceding context so it is consistent with autocompletion from APIs. - [46de719d325e] - - * qt/qscintilla.pro, qt/qscintilla_cs.qm, qt/qscintilla_cs.ts: - Added the Czech translations from Zdenek Bohm. - [139fd9aee405] - -2007-04-30 phil - - * Python/sip/qsciscintilla.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added QsciScintilla::wordCharacters(). - [d6e56986a031] - -2007-04-29 phil - - * Python/sip/qsciscintilla.sip, Python/sip/qsciscintillabase.sip, - qt/qsciscintilla.cpp, qt/qsciscintilla.h, qt/qsciscintillabase.cpp, - qt/qsciscintillabase.h: - Added lots of consts to QsciScintilla getter methods. - [4aaffa8611ba] - - * Python/configure.py, Python/sip/qsciscintilla.sip, - qt/qscintilla_de.qm, qt/qscintilla_de.ts, qt/qscintilla_fr.ts, - qt/qscintilla_pt_br.ts, qt/qscintilla_ru.ts, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added caseSensitive() and isWordCharacter() to QsciScintilla. - Updated translations from Detlev. - [64223bf97266] - -2007-04-10 phil - - * Python/sip/qscilexercmake.sip, Python/sip/qscilexervhdl.sip, - Python/sip/qscimodcommon.sip, qt/qscilexercmake.cpp, - qt/qscilexercmake.h, qt/qscilexervhdl.cpp, qt/qscilexervhdl.h, - qt/qscintilla.pro: - Added the QsciLexerVHDL class. - [10029339786f] - - * Python/sip/qscilexercmake.sip, Python/sip/qscimodcommon.sip, - qt/qscilexercmake.cpp, qt/qscilexercmake.h, qt/qscintilla.pro: - Added the QsciLexerCmake class. - [c1c911246f75] - -2007-04-09 phil - - * qt/qsciapis.cpp, qt/qsciapis.h, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Finished call tip support. - [b8c717297392] - -2007-04-07 phil - - * qt/qsciapis.cpp, qt/qsciapis.h, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Some refactoring in preparation for getting call tips working. - [6cb925653a80] - -2007-04-06 phil - - * qt/qsciscintilla.cpp: - Fixed autoindenting. - [8d7b93ee4d9e] - -2007-04-05 phil - - * qt/qsciapis.cpp, qt/qsciapis.h, qt/qsciscintilla.cpp: - Fixed autocompletion so that it works with lexers that don't define - word separators, and lexers that are case insensitive. - [66634cf13685] - -2007-04-04 phil - - * qt/ScintillaQt.cpp, qt/qsciscintilla.cpp: - Fixed the horizontal scrollbar when word wrapping. - [021ea1fe8468] - -2007-04-03 phil - - * Python/configure.py, Python/sip/qsciscintillabase.sip, delcvs.bat, - doc/ScintillaDoc.html, doc/ScintillaDownload.html, - doc/ScintillaHistory.html, doc/ScintillaRelated.html, - doc/index.html, gtk/makefile, gtk/scintilla.mak, include/SciLexer.h, - include/Scintilla.h, include/Scintilla.iface, qt/ScintillaQt.cpp, - qt/qscintilla.pro, qt/qsciscintillabase.h, src/Document.cxx, - src/Document.h, src/DocumentAccessor.cxx, src/Editor.cxx, - src/Editor.h, src/ExternalLexer.h, src/KeyWords.cxx, src/LexAU3.cxx, - src/LexBash.cxx, src/LexCmake.cxx, src/LexHTML.cxx, src/LexLua.cxx, - src/LexMSSQL.cxx, src/LexOthers.cxx, src/LexTADS3.cxx, - src/PropSet.cxx, src/RESearch.cxx, src/RESearch.h, - src/SplitVector.h, vcbuild/SciLexer.dsp, version.txt, - win32/PlatWin.cxx, win32/ScintRes.rc, win32/ScintillaWin.cxx, - win32/makefile, win32/scintilla.mak, win32/scintilla_vc6.mak: - Merged Scintilla v1.73. - [2936af6fc62d] - -2007-03-18 phil - - * Makefile, Python/sip/qscilexerd.sip, Python/sip/qscimodcommon.sip, - Python/sip/qsciscintillabase.sip, qt/qscilexerd.cpp, - qt/qscilexerd.h, qt/qscintilla.pro, qt/qscintilla_de.qm, - qt/qscintilla_de.ts, qt/qscintilla_fr.ts, qt/qscintilla_pt_br.ts, - qt/qscintilla_ru.ts: - Switched the internal build system to Qt v4.2.3. Added the D lexer - support from Detlev. - [667e9b81ab4f] - -2007-03-04 phil - - * Makefile, example-Qt4/mainwindow.cpp, qt/PlatQt.cpp, - qt/qsciscintilla.cpp: - Fixed a bug in default font handling. Removed use of QIODevice::Text - in the example as it is unnecessary and a performance hog. Moved the - internal Qt3 build system to Qt v3.3.8. Auto-indentation should now - work (as badly) as it did with QScintilla v1. - [4d3ad4d1f295] - -2007-01-17 phil - - * Python/sip/qsciapis.sip, qt/qsciapis.cpp, qt/qsciapis.h: - Added defaultPreparedName() to QsciAPIs. - [2a3c872122dd] - - * designer-Qt4/qscintillaplugin.cpp: - Fixed the Qt4 Designer plugin include file value. - [ea7cb8634ad2] - -2007-01-16 phil - - * Python/sip/qsciapis.sip, qt/qsciapis.cpp, qt/qsciapis.h: - Added cancelPreparation() and apiPreparationCancelled() to QsciAPIs. - [2d7dd00e3bc0] - - * Python/sip/qsciscintilla.sip, Python/sip/qsciscintillabase.sip, - build.py, lib/LICENSE.commercial.short, lib/LICENSE.gpl.short, - qt/qscintilla.pro, qt/qsciscintilla.cpp, qt/qsciscintilla.h, - qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Updated the copyright notices. Added selectionToEol() and - setSelectionToEol() to QsciScintilla. Added the other 1.72 changes - to the low level API. - [ddcf2d43cf31] - - * doc/SciBreak.jpg, doc/ScintillaDoc.html, doc/ScintillaDownload.html, - doc/ScintillaHistory.html, doc/ScintillaRelated.html, - doc/index.html, gtk/PlatGTK.cxx, gtk/ScintillaGTK.cxx, gtk/makefile, - gtk/scintilla.mak, include/SciLexer.h, include/Scintilla.h, - include/Scintilla.iface, qt/ScintillaQt.h, src/CellBuffer.cxx, - src/CellBuffer.h, src/ContractionState.cxx, src/Document.cxx, - src/Document.h, src/DocumentAccessor.cxx, src/Editor.cxx, - src/Editor.h, src/KeyWords.cxx, src/LexCPP.cxx, src/LexD.cxx, - src/LexGen.py, src/LexHTML.cxx, src/LexInno.cxx, src/LexLua.cxx, - src/LexMatlab.cxx, src/LexNsis.cxx, src/LexOthers.cxx, - src/LexRuby.cxx, src/LexTADS3.cxx, src/Partitioning.h, - src/ScintillaBase.cxx, src/SplitVector.h, src/StyleContext.h, - src/ViewStyle.cxx, src/ViewStyle.h, vcbuild/SciLexer.dsp, - version.txt, win32/ScintRes.rc, win32/ScintillaWin.cxx, - win32/makefile, win32/scintilla.mak, win32/scintilla_vc6.mak: - Merged Scintilla v1.72, but any new features are not yet exploited. - [dcdfde9050a2] - -2007-01-09 phil - - * Python/configure.py: - Fixed bug in configure.py when the -p flag wasn't specified. - [50dc69f2b20d] - -2007-01-04 phil - - * Python/configure.py, Python/sip/qscilexer.sip, qt/qsciapis.cpp, - qt/qsciapis.h, qt/qsciscintilla.cpp: - Backported to Qt v3. Note that this will probably break again in the - future when call tips are redone. - [3bcc4826fc73] - -2007-01-02 phil - - * Python/configure.py, lib/gen_python_api.py, - qsci/api/python/Python-2.4.api, qsci/api/python/Python-2.5.api, - qt/qsciapis.cpp: - Added the Python v2.4 and v2.5 API files. Added the generation of - the QScintilla2.api file. - [49beb92ca721] - -2007-01-01 phil - - * Python/sip/qsciscintilla.sip, qt/qscilexer.h, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added autoCompletionFillupsEnabled() and - setAutoCompletionFillupsEnabled() to QsciScintilla. Updated the - Python bindings. - [7aa946010e9d] - - * Python/sip/qsciapis.sip, qt/qsciapis.cpp, qt/qsciapis.h: - Implemented loadPrepared() and savePrepared() in QsciAPIs. Added - isPrepared() to QsciAPIs. Updated the Python bindings. - [4c5e3d80fec7] - - * Python/sip/qsciapis.sip, qt/qsciapis.cpp, qt/qsciapis.h: - Added installAPIFiles() and stubs for loadPrepared() and - savePrepared() to QsciAPIs. - [93f4dd7222a1] - - * Python/sip/qsciapis.sip: - Added the missing qsciapis.sip file. - [064b524acc93] - - * Python/sip/qscilexer.sip, Python/sip/qscimodcommon.sip, - lib/qscintilla.dxy, qt/qsciapis.cpp, qt/qsciapis.h, - qt/qscilexer.cpp, qt/qscilexer.h: - Fixed the generation of the API documentation. Added apis() and - setAPIs() to QsciLexer. Removed apiAdd(), apiClear(), apiLoad(), - apiRemove(), apiProcessingStarted() and apiProcessingFinished() from - QsciLexer. Added apiPreparationStarted() and - apiPreparationFinished() to QsciAPIs. Made QsciAPIs part of the API - again. Updated the Python bindings. - [851d133b12ff] - -2006-12-20 phil - - * Makefile, qt/qsciapis.cpp, qt/qsciapis.h: - Updated the internal build system to Qt v4.2.2. More work on auto- - completion. - [d4542220e7a2] - -2006-11-26 phil - - * qt/ListBoxQt.cpp, qt/ListBoxQt.h, qt/qsciapis.cpp, qt/qsciapis.h, - qt/qsciscintilla.cpp, qt/qsciscintilla.h: - More work on the auto-completion code. - [37b2d0d2b154] - -2006-11-22 phil - - * qt/qsciapis.cpp, qt/qsciapis.h, qt/qscilexer.cpp, qt/qscilexer.h, - qt/qscilexerbatch.cpp, qt/qscilexerbatch.h, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Changed the handling of case sensitivity in auto-completion lists. - Lexers now say if they are case sensitive. - [b1932fba61ec] - -2006-11-17 phil - - * Makefile, Python/configure.py, Python/sip/qscicommand.sip, - Python/sip/qscicommandset.sip, Python/sip/qscidocument.sip, - Python/sip/qscilexer.sip, Python/sip/qscilexerbash.sip, - Python/sip/qscilexerbatch.sip, Python/sip/qscilexercpp.sip, - Python/sip/qscilexercsharp.sip, Python/sip/qscilexercss.sip, - Python/sip/qscilexerdiff.sip, Python/sip/qscilexerhtml.sip, - Python/sip/qscilexeridl.sip, Python/sip/qscilexerjava.sip, - Python/sip/qscilexerjavascript.sip, Python/sip/qscilexerlua.sip, - Python/sip/qscilexermakefile.sip, Python/sip/qscilexerperl.sip, - Python/sip/qscilexerpov.sip, Python/sip/qscilexerproperties.sip, - Python/sip/qscilexerpython.sip, Python/sip/qscilexerruby.sip, - Python/sip/qscilexersql.sip, Python/sip/qscilexertex.sip, - Python/sip/qscimacro.sip, Python/sip/qsciprinter.sip, - Python/sip/qsciscintilla.sip, Python/sip/qsciscintillabase.sip, - TODO, build.py, designer-Qt3/qscintillaplugin.cpp, designer- - Qt4/qscintillaplugin.cpp, example-Qt3/application.cpp, example- - Qt4/mainwindow.cpp, qt/PlatQt.cpp, qt/ScintillaQt.cpp, - qt/qsciapis.cpp, qt/qsciapis.h, qt/qscicommand.cpp, - qt/qscicommand.h, qt/qscicommandset.cpp, qt/qscicommandset.h, - qt/qscidocument.cpp, qt/qscidocument.h, qt/qscilexer.cpp, - qt/qscilexer.h, qt/qscilexerbash.cpp, qt/qscilexerbash.h, - qt/qscilexerbatch.cpp, qt/qscilexerbatch.h, qt/qscilexercpp.cpp, - qt/qscilexercpp.h, qt/qscilexercsharp.cpp, qt/qscilexercsharp.h, - qt/qscilexercss.cpp, qt/qscilexercss.h, qt/qscilexerdiff.cpp, - qt/qscilexerdiff.h, qt/qscilexerhtml.cpp, qt/qscilexerhtml.h, - qt/qscilexeridl.cpp, qt/qscilexeridl.h, qt/qscilexerjava.cpp, - qt/qscilexerjava.h, qt/qscilexerjavascript.cpp, - qt/qscilexerjavascript.h, qt/qscilexerlua.cpp, qt/qscilexerlua.h, - qt/qscilexermakefile.cpp, qt/qscilexermakefile.h, - qt/qscilexerperl.cpp, qt/qscilexerperl.h, qt/qscilexerpov.cpp, - qt/qscilexerpov.h, qt/qscilexerproperties.cpp, - qt/qscilexerproperties.h, qt/qscilexerpython.cpp, - qt/qscilexerpython.h, qt/qscilexerruby.cpp, qt/qscilexerruby.h, - qt/qscilexersql.cpp, qt/qscilexersql.h, qt/qscilexertex.cpp, - qt/qscilexertex.h, qt/qscimacro.cpp, qt/qscimacro.h, - qt/qscintilla.pro, qt/qsciprinter.cpp, qt/qsciprinter.h, - qt/qsciscintilla.cpp, qt/qsciscintilla.h, qt/qsciscintillabase.cpp, - qt/qsciscintillabase.h: - Fixed the name of the generated source packages. Reorganised so that - the header files are in a separate sub-directory. Updated the - designer plugins and examples for the changing in header file - structure. More work on autocompletion. Basic functionality is - there, but no support for the "current context" yet. - [312e74140bb8] - -2006-11-04 phil - - * designer-Qt4/qscintillaplugin.cpp: - Designer plugin fixes for Qt4 from DavidB. - [920f7af8bec6] - -2006-11-03 phil - - * qt/qscilexer.cpp: - Fixed QsciLexer::setPaper() so that it also sets the background - colour of the default style. - [fcab00732d97] - -2006-10-21 phil - - * Makefile, qt/qsciapis.cpp, qt/qsciapis.h, qt/qsciscintilla.cpp: - Switched the internal build system to Qt v3.3.7 and v4.2.1. - Portability fixes for Qt3. - [512b57958ea4] - -2006-10-20 phil - - * Makefile, build.py, include/Platform.h, lib/README.doc, - qt/PlatQt.cpp, qt/qscimacro.cpp, qt/qscintilla.pro, - qt/qsciscintilla.cpp: - Renamed the base package QScintilla2. Platform portability fixes - from Ulli. The qsci data directory is now installed (where API files - will be kept). - [2a61d65842fb] - -2006-10-13 phil - - * Python/sip/qsciscintilla.sip, qt/qscintilla.pro, - qt/qscintilla_pt_br.qm, qt/qscintilla_pt_br.ts, - qt/qscintilla_ptbr.qm, qt/qscintilla_ptbr.ts, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added QsciScintilla::linesChanged() from Detlev. Removed - QsciScintilla::markerChanged(). Renamed the Brazilian Portugese - translation files. - [5b23de72e063] - - * Makefile, Python/sip/qscilexer.sip, qt/ListBoxQt.cpp, - qt/ListBoxQt.h, qt/ScintillaQt.cpp, qt/qsciapis.cpp, qt/qsciapis.h, - qt/qscilexer.cpp, qt/qscilexer.h, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - Added apiRemove(), apiProcessingStarted() and - apiProcessingFinished() to QsciLexer. - [ef2cb95b868a] - -2006-10-08 phil - - * qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Reset the text and paper colours and font when removing a lexer. - [08ac85b34d80] - - * qt/qsciscintilla.cpp: - Fixed Qt3 specific problem with most recent changes. - [e4ba06e01a1e] - -2006-10-06 phil - - * Python/sip/qsciapis.sip, Python/sip/qscilexer.sip, - Python/sip/qscimodcommon.sip, Python/sip/qsciscintilla.sip, - qt/ListBoxQt.cpp, qt/SciClasses.cpp, qt/qsciapis.cpp, qt/qsciapis.h, - qt/qscilexer.cpp, qt/qscilexer.h, qt/qscilexerbash.cpp, - qt/qscilexerbash.h, qt/qscilexerbatch.cpp, qt/qscilexerbatch.h, - qt/qscilexercpp.cpp, qt/qscilexercpp.h, qt/qscilexercsharp.h, - qt/qscilexercss.cpp, qt/qscilexercss.h, qt/qscilexerdiff.cpp, - qt/qscilexerdiff.h, qt/qscilexerhtml.cpp, qt/qscilexerhtml.h, - qt/qscilexeridl.h, qt/qscilexerjavascript.h, qt/qscilexerlua.cpp, - qt/qscilexerlua.h, qt/qscilexermakefile.cpp, qt/qscilexermakefile.h, - qt/qscilexerperl.cpp, qt/qscilexerperl.h, qt/qscilexerpov.cpp, - qt/qscilexerpov.h, qt/qscilexerproperties.cpp, - qt/qscilexerproperties.h, qt/qscilexerpython.cpp, - qt/qscilexerpython.h, qt/qscilexerruby.cpp, qt/qscilexerruby.h, - qt/qscilexersql.cpp, qt/qscilexersql.h, qt/qscilexertex.cpp, - qt/qscilexertex.h, qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Made QsciAPIs an internal class and instead added apiAdd(), - apiClear() and apiLoad() to QsciLexer. Replaced - setAutoCompletionStartCharacters() with - setAutoCompletionWordSeparators() in QsciScintilla. Removed - autoCompletionFillupsEnabled(), setAutoCompletionFillupsEnabled(), - setAutoCompletionAPIs() and setCallTipsAPIs() from QsciScintilla. - Added AcsNone to QsciScintilla::AutoCompletionSource. Horizontal - scrollbars are displayed as needed in autocompletion lists. Added - QsciScintilla::lexer(). Fixed setFont(), setColor(), setEolFill() - and setPaper() in QsciLexer so that they handle all styles as - documented. Removed all occurences of QString::null. Fixed the - problem with indentation guides not changing when the size of a - space changed. Added the QsciScintilla::markerChanged() signal. - Updated the Python bindings. - [9ae22e152365] - -2006-10-01 phil - - * qt/PlatQt.cpp: - Fixed a silly line drawing bug. - [0f9f5c22421a] - -2006-09-30 phil - - * qt/qscintilla.pro: - Fixes for building on Windows and MacOS/X. - [c16bc6aeba20] - -2006-09-29 phil - - * example-Qt4/application.pro, qt/PlatQt.cpp, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.cpp: - Fixed the documentation bug in QsciScintilla::insert(). Fixed the - mouse shape changing properly. Fixed the drawing of fold markers. - [08af64d93094] - -2006-09-23 phil - - * lib/README: - Improved the README for the pedants amongst us. - [683bdb9a84fc] - - * designer-Qt4/designer.pro, designer-Qt4/qscintillaplugin.cpp, - designer-Qt4/qscintillaplugin.h: - The Qt4 Designer plugin now loads - thanks to DavidB. - [feb5a3618df6] - -2006-09-16 phil - - * build.py, designer-Qt3/designer.pro, designer- - Qt3/qscintillaplugin.cpp, designer-Qt4/designer.pro, designer- - Qt4/qscintillaplugin.cpp, designer/designer.pro, - designer/qscintillaplugin.cpp, lib/README.doc, qt/qsciscintilla.h: - Fixed the Qt3 designer plugin. Added the Qt4 designer plugin based - on Andrius Ozelis's work. (But it doesn't load for me - does anybody - else have a problem?) - [3a0873ed5ff0] - -2006-09-09 phil - - * Python/sip/qsciscintilla.sip, qt/qsciscintilla.cpp, - qt/qsciscintilla.h: - QsciScintilla's setFont(), setColor() and setPaper() now work as - expected when there is no lexer (and have no effect if there is a - lexer). - [65cc713d9ecb] - -2006-08-28 phil - - * qt/ListBoxQt.cpp, qt/PlatQt.cpp: - Fixed a crash when double-clicking on an auto-completion list entry. - [d8eecfc59ca2] - -2006-08-27 phil - - * Python/sip/qsciscintillabase.sip, doc/ScintillaDoc.html, - doc/ScintillaDownload.html, doc/ScintillaHistory.html, - doc/index.html, gtk/Converter.h, gtk/PlatGTK.cxx, - gtk/ScintillaGTK.cxx, qt/ScintillaQt.cpp, qt/qsciscintillabase.h, - src/Editor.cxx, src/LexCPP.cxx, src/LexPerl.cxx, src/LexVB.cxx, - src/StyleContext.h, version.txt, win32/ScintRes.rc, - win32/ScintillaWin.cxx: - Merged Scintilla v1.71. The SCN_DOUBLECLICK() signal now passes the - line and position of the click. - [81c852fed943] - -2006-08-17 phil - - * Python/sip/qsciscintilla.sip, qt/ScintillaQt.cpp: - Fixed pasting when Unicode mode is set. - [9d4a7ccef6f4] - - * build.py: - Fixed the internal build system leaving SVN remnants around. - [96c36a0e94ac] - -2006-07-30 phil - - * NEWS, Python/sip/qsciscintilla.sip, qt/qscicommand.h, - qt/qscicommandset.h, qt/qsciscintilla.cpp, qt/qsciscintilla.h: - Added autoCompletionFillupsEnabled() and - setAutoCompletionFillupsEnabled() to QsciScintilla. Don't auto- - complete numbers. Removed QsciCommandList. - [e9886e5da7c3] - -2006-07-29 phil - - * lib/README.doc, qt/PlatQt.cpp: - Debugged the Qt3 backport - all seems to work. - [1e743e050599] - - * Python/configure.py, Python/sip/qscimod3.sip, - Python/sip/qsciscintillabase.sip, Python/sip/qsciscintillabase4.sip, - build.py, lib/README, lib/README.doc, lib/qscintilla.dxy, - qt/qsciscintillabase.h: - The PyQt3 bindings now work. Updated the documentation and build - system for both Qt3 and Qt4. - [f4fa8a9a35c0] - -2006-07-28 phil - - * Python/sip/qscimodcommon.sip, Python/sip/qsciscintillabase4.sip, - Python/sip/qscitypes.sip, example-Qt3/application.cpp, example- - Qt3/application.h, example-Qt3/application.pro, qt/qscicommand.cpp, - qt/qscicommandset.cpp, qt/qscidocument.cpp, qt/qscimacro.cpp, - qt/qscintilla.pro, qt/qsciprinter.cpp, qt/qsciscintilla.cpp, - qt/qsciscintilla.h, qt/qsciscintillabase.cpp, - qt/qsciscintillabase.h, qt/qscitypes.h: - Backed out the QscoTypes namespace now that the Qt3/4 source code - has been consolidated. - [372c37fa8b9c] - - * qt/qscintilla_de.ts, qt/qscintilla_fr.ts, qt/qscintilla_ptbr.ts, - qt/qscintilla_ru.ts, qt/qsciscintillabase.cpp, - qt/qsciscintillabase.h, qt/qsciscintillabase3.cpp, - qt/qsciscintillabase3.h, qt/qsciscintillabase4.cpp, - qt/qsciscintillabase4.h: - Integated the Qt3 and Qt4 source files. - [4ee1fcf04cd9] - - * Makefile, build.py, lib/README.doc, lib/qscintilla.dxy, - qt/qscintilla.pro, qt/qsciscintillabase.h, - qt/qsciscintillabase3.cpp, qt/qsciscintillabase3.h, - qt/qsciscintillabase4.cpp, qt/qsciscintillabase4.h: - The Qt3 port now compiles, but otherwise untested. - [da227e07e729] - - * Python/sip/qscimacro.sip, lib/README.doc, lib/qscintilla.dxy, - qt/PlatQt.cpp, qt/qscilexermakefile.cpp, qt/qscimacro.cpp, - qt/qscimacro.h, qt/qscintilla.pro, qt/qsciscintillabase.h, - qt/qsciscintillabase3.cpp, qt/qsciscintillabase3.h, - qt/qsciscintillabase4.cpp, qt/qsciscintillabase4.h: - Changes to QsciMacro so that it has a more consistent API across Qt3 - and Qt4. Backported to Qt3 - doesn't yet build because Qt3 qmake - doesn't understand the preprocessor. - [910b415ec4a8] - -2006-07-27 phil - - * build.py, designer/qscintillaplugin.cpp, example-Qt3/README, - example-Qt4/README, lib/README, lib/README.doc, lib/qscintilla.dxy, - qt/qscintilla.pro: - Updated the documentation. - [7774f3e87003] - -2006-07-26 phil - - * Makefile, Python/configure.py, Python/qsciapis.sip, - Python/qscicommand.sip, Python/qscicommandset.sip, - Python/qscidocument.sip, Python/qscilexer.sip, - Python/qscilexerbash.sip, Python/qscilexerbatch.sip, - Python/qscilexercpp.sip, Python/qscilexercsharp.sip, - Python/qscilexercss.sip, Python/qscilexerdiff.sip, - Python/qscilexerhtml.sip, Python/qscilexeridl.sip, - Python/qscilexerjava.sip, Python/qscilexerjavascript.sip, - Python/qscilexerlua.sip, Python/qscilexermakefile.sip, - Python/qscilexerperl.sip, Python/qscilexerpov.sip, - Python/qscilexerproperties.sip, Python/qscilexerpython.sip, - Python/qscilexerruby.sip, Python/qscilexersql.sip, - Python/qscilexertex.sip, Python/qscimacro.sip, Python/qscimod4.sip, - Python/qscimodcommon.sip, Python/qsciprinter.sip, - Python/qsciscintilla.sip, Python/qsciscintillabase4.sip, - Python/qscitypes.sip, Python/sip/qsciapis.sip, - Python/sip/qscicommand.sip, Python/sip/qscicommandset.sip, - Python/sip/qscidocument.sip, Python/sip/qscilexer.sip, - Python/sip/qscilexerbash.sip, Python/sip/qscilexerbatch.sip, - Python/sip/qscilexercpp.sip, Python/sip/qscilexercsharp.sip, - Python/sip/qscilexercss.sip, Python/sip/qscilexerdiff.sip, - Python/sip/qscilexerhtml.sip, Python/sip/qscilexeridl.sip, - Python/sip/qscilexerjava.sip, Python/sip/qscilexerjavascript.sip, - Python/sip/qscilexerlua.sip, Python/sip/qscilexermakefile.sip, - Python/sip/qscilexerperl.sip, Python/sip/qscilexerpov.sip, - Python/sip/qscilexerproperties.sip, Python/sip/qscilexerpython.sip, - Python/sip/qscilexerruby.sip, Python/sip/qscilexersql.sip, - Python/sip/qscilexertex.sip, Python/sip/qscimacro.sip, - Python/sip/qscimod4.sip, Python/sip/qscimodcommon.sip, - Python/sip/qsciprinter.sip, Python/sip/qsciscintilla.sip, - Python/sip/qsciscintillabase4.sip, Python/sip/qscitypes.sip, - build.py, lib/LICENSE.edu, lib/LICENSE.edu.short, lib/README.MacOS: - Changed the build system to add the Python bindings. - [8a56c38c418b] - - * Python/configure.py, Python/qscicommandset.sip, - Python/qscilexerruby.sip, Python/qscilexertex.sip, - Python/qscimod4.sip, Python/qsciscintilla.sip, - Python/qsciscintillabase4.sip, Python/qscitypes.sip: - Debugged the Python bindings - not yet part of the snapshots. - [8e348d9c7d38] - -2006-07-25 phil - - * Python/qsciapis.sip, Python/qscicommand.sip, - Python/qscicommandset.sip, Python/qscidocument.sip, - Python/qscilexer.sip, Python/qscilexerbash.sip, - Python/qscilexerbatch.sip, Python/qscilexercpp.sip, - Python/qscilexercsharp.sip, Python/qscilexercss.sip, - Python/qscilexerdiff.sip, Python/qscilexerhtml.sip, - Python/qscilexeridl.sip, Python/qscilexerjava.sip, - Python/qscilexerjavascript.sip, Python/qscilexerlua.sip, - Python/qscilexermakefile.sip, Python/qscilexerperl.sip, - Python/qscilexerpov.sip, Python/qscilexerproperties.sip, - Python/qscilexerpython.sip, Python/qscilexerruby.sip, - Python/qscilexersql.sip, Python/qscilexertex.sip, - Python/qscimacro.sip, Python/qscimod4.sip, Python/qscimodcommon.sip, - Python/qsciprinter.sip, Python/qsciscintilla.sip, - Python/qsciscintillabase4.sip, Python/qscitypes.sip, qt/qsciapis.h, - qt/qsciglobal.h, qt/qscilexer.h, qt/qscilexerbash.h, - qt/qscilexercpp.h, qt/qscilexerperl.h, qt/qscilexerpython.h, - qt/qscilexersql.h, qt/qsciprinter.h, qt/qsciscintilla.h: - Ported the .sip files from v1. (Not yet part of the snapshot.) - [c03807f9fbab] - - * Makefile, qt/qscintilla-Qt4.pro, qt/qscintilla.pro: - The .pro file should now work with both Qt v3 and v4. - [c99aec4ce73d] - - * Makefile, qt/qscintilla-Qt4.pro, qt/qscintilla.pro, - qt/qsciscintillabase.cpp, qt/qsciscintillabase.h, - qt/qsciscintillabase4.cpp, qt/qsciscintillabase4.h: - Some file reorganisation for when the backport to Qt3 is done. - [c97fb1bdc0e5] - - * qt/qscicommand.cpp, qt/qscicommandset.cpp, qt/qscidocument.cpp, - qt/qscimacro.cpp, qt/qscintilla.pro, qt/qsciprinter.cpp, - qt/qsciscintilla.cpp, qt/qsciscintilla.h, qt/qsciscintillabase.cpp, - qt/qsciscintillabase.h, qt/qscitypes.h: - Moved the Scintilla API enums out of QsciScintillaBase and into the - new QsciTypes namespace. - [6de0ac19e4df] - - * qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Triple clicking now works. - [8ef632d89147] - -2006-07-23 phil - - * qt/qsciscintillabase.cpp: - Fixed incorrect selection after dropping text. - [4c62275c39f4] - - * qt/ScintillaQt.cpp, qt/ScintillaQt.h, qt/qsciscintillabase.cpp: - Dropping text seems (mostly) to work. - [7acc97948229] - -2006-07-22 phil - - * qt/PlatQt.cpp, qt/ScintillaQt.cpp, qt/ScintillaQt.h, - qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Scrollbars now work. The context menu now works. The clipboard and - mouse selection now works. Dragging to external windows now works - (but not dropping). - [73995ec258cd] - -2006-07-18 phil - - * example-Qt4/mainwindow.cpp, example-Qt4/mainwindow.h, qt/PlatQt.cpp, - qt/qextscintillalexerbash.cxx, qt/qextscintillalexerbash.h, - qt/qextscintillalexerbatch.cxx, qt/qextscintillalexerbatch.h, - qt/qextscintillalexercpp.cxx, qt/qextscintillalexercpp.h, - qt/qextscintillalexercsharp.cxx, qt/qextscintillalexercsharp.h, - qt/qextscintillalexercss.cxx, qt/qextscintillalexercss.h, - qt/qextscintillalexerdiff.cxx, qt/qextscintillalexerdiff.h, - qt/qextscintillalexerhtml.cxx, qt/qextscintillalexerhtml.h, - qt/qextscintillalexeridl.cxx, qt/qextscintillalexeridl.h, - qt/qextscintillalexerjava.cxx, qt/qextscintillalexerjava.h, - qt/qextscintillalexerjavascript.cxx, - qt/qextscintillalexerjavascript.h, qt/qextscintillalexerlua.cxx, - qt/qextscintillalexerlua.h, qt/qextscintillalexermakefile.cxx, - qt/qextscintillalexermakefile.h, qt/qextscintillalexerperl.cxx, - qt/qextscintillalexerperl.h, qt/qextscintillalexerpov.cxx, - qt/qextscintillalexerpov.h, qt/qextscintillalexerproperties.cxx, - qt/qextscintillalexerproperties.h, qt/qextscintillalexerpython.cxx, - qt/qextscintillalexerpython.h, qt/qextscintillalexerruby.cxx, - qt/qextscintillalexerruby.h, qt/qextscintillalexersql.cxx, - qt/qextscintillalexersql.h, qt/qextscintillalexertex.cxx, - qt/qextscintillalexertex.h, qt/qextscintillamacro.cxx, - qt/qextscintillamacro.h, qt/qextscintillaprinter.cxx, - qt/qextscintillaprinter.h, qt/qsciapis.h, qt/qscicommand.h, - qt/qscilexer.h, qt/qscilexerbash.cpp, qt/qscilexerbash.h, - qt/qscilexerbatch.cpp, qt/qscilexerbatch.h, qt/qscilexercpp.cpp, - qt/qscilexercpp.h, qt/qscilexercsharp.cpp, qt/qscilexercsharp.h, - qt/qscilexercss.cpp, qt/qscilexercss.h, qt/qscilexerdiff.cpp, - qt/qscilexerdiff.h, qt/qscilexerhtml.cpp, qt/qscilexerhtml.h, - qt/qscilexeridl.cpp, qt/qscilexeridl.h, qt/qscilexerjava.cpp, - qt/qscilexerjava.h, qt/qscilexerjavascript.cpp, - qt/qscilexerjavascript.h, qt/qscilexerlua.cpp, qt/qscilexerlua.h, - qt/qscilexermakefile.cpp, qt/qscilexermakefile.h, - qt/qscilexerperl.cpp, qt/qscilexerperl.h, qt/qscilexerpov.cpp, - qt/qscilexerpov.h, qt/qscilexerproperties.cpp, - qt/qscilexerproperties.h, qt/qscilexerpython.cpp, - qt/qscilexerpython.h, qt/qscilexerruby.cpp, qt/qscilexerruby.h, - qt/qscilexersql.cpp, qt/qscilexersql.h, qt/qscilexertex.cpp, - qt/qscilexertex.h, qt/qscimacro.cpp, qt/qscimacro.h, - qt/qscintilla.pro, qt/qsciprinter.cpp, qt/qsciprinter.h, - qt/qsciscintilla.h: - Ported the rest of the API to Qt4. Finished porting the example to - Qt4. - [de0ede6bbcf5] - -2006-07-17 phil - - * qt/qextscintilla.cxx, qt/qextscintilla.h, qt/qextscintillaapis.cxx, - qt/qextscintillaapis.h, qt/qextscintillacommand.cxx, - qt/qextscintillacommand.h, qt/qextscintillacommandset.cxx, - qt/qextscintillacommandset.h, qt/qextscintilladocument.cxx, - qt/qextscintilladocument.h, qt/qextscintillalexer.cxx, - qt/qextscintillalexer.h, qt/qsciapis.cpp, qt/qsciapis.h, - qt/qscicommand.cpp, qt/qscicommand.h, qt/qscicommandset.cpp, - qt/qscicommandset.h, qt/qscidocument.cpp, qt/qscidocument.h, - qt/qscilexer.cpp, qt/qscilexer.h, qt/qscintilla.pro, - qt/qsciscintilla.cpp, qt/qsciscintilla.h: - More porting to Qt4 - just the lexers remaining. - [07158797bcf2] - - * qt/ListBoxQt.cpp, qt/PlatQt.cpp, qt/SciClasses.cpp, - qt/ScintillaQt.cpp, qt/qscintilla.pro, qt/qsciscintillabase.cpp: - Further Qt4 changes so that Q3Support is no longer needed. - [cb3ca2aee49e] - - * qt/ListBoxQt.cpp, qt/ListBoxQt.h, qt/PlatQt.cpp, qt/SciClasses.cpp, - qt/SciClasses.h, qt/SciListBox.cxx, qt/SciListBox.h, - qt/ScintillaQt.cpp, qt/ScintillaQt.h, qt/qscintilla.pro, - qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Ported the auto-completion list implementation to Qt4. - [1d0d07f7ba3b] - -2006-07-16 phil - - * qt/PlatQt.cpp, qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Drawing now seems Ok. Keyboard support now seems Ok. Start of the - mouse support. - [20a223c3f57e] - -2006-07-12 phil - - * include/Platform.h, qt/PlatQt.cpp, qt/ScintillaQt.cpp: - Painting now seems to happen only within paint events - but - incorrectly. - [a60a10298391] - - * qt/PlatQt.cpp, qt/PlatQt.cxx, qt/ScintillaQt.cpp, - qt/ScintillaQt.cxx, qt/ScintillaQt.h, qt/qscintilla.pro: - Recoded the implementation of surfaces so that painters are only - active during paint events. Not yet debugged. - [d0d91ae8e514] - - * build.py, qt/PlatQt.cxx, qt/ScintillaQt.cxx, qt/ScintillaQt.h, - qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Recoded the handling of key presses so that it doesn't use any Qt3 - specific features and should be backported to QScintilla v1. It also - should work better in Unicode mode. - [c2b96d686ee6] - -2006-07-11 phil - - * Makefile, build.py, example-Qt3/README, example-Qt3/application.cpp, - example-Qt3/application.h, example-Qt3/application.pro, example- - Qt3/fileopen.xpm, example-Qt3/fileprint.xpm, example- - Qt3/filesave.xpm, example-Qt3/main.cpp, example-Qt4/README, example- - Qt4/application.pro, example-Qt4/application.qrc, example- - Qt4/images/copy.png, example-Qt4/images/cut.png, example- - Qt4/images/new.png, example-Qt4/images/open.png, example- - Qt4/images/paste.png, example-Qt4/images/save.png, example- - Qt4/main.cpp, example-Qt4/mainwindow.cpp, example-Qt4/mainwindow.h, - example/README, example/application.cpp, example/application.h, - example/application.pro, example/fileopen.xpm, - example/fileprint.xpm, example/filesave.xpm, example/main.cpp, - qt/PlatQt.cxx, qt/SciListBox.cxx, qt/SciListBox.h, - qt/ScintillaQt.cxx, qt/ScintillaQt.h, qt/qextscintilla.cxx, - qt/qextscintillabase.cxx, qt/qextscintillabase.h, - qt/qextscintillaglobal.h, qt/qsciglobal.h, qt/qscintilla.pro, - qt/qsciscintillabase.cpp, qt/qsciscintillabase.h: - Whole raft of changes starting QScintilla2. - [7f0bd20f2f83] - -2006-07-09 phil - - * qt/qscintilla_de.qm, qt/qscintilla_de.ts, qt/qscintilla_fr.ts, - qt/qscintilla_ptbr.ts, qt/qscintilla_ru.ts: - Updated translations from Detlev. - [c04c167d802e] - -2006-07-08 phil - - * NEWS, qt/qextscintilla.cxx, qt/qextscintilla.h: - Added QextScintilla::isCallTipActive(). - [1f7dcb40db25] - - * lib/LICENSE.commercial.short, lib/LICENSE.edu.short, - lib/LICENSE.gpl.short, qt/qextscintilla.cxx: - Changed the autoindentation to be slightly cleverer when handling - Python. If a lexer does not define block end words then a block - start word is ignored unless it is the last significant word in a - line. - [d5813c13f5da] - -2006-07-02 phil - - * qt/PlatQt.cxx: - Possibly fixed a possible problem with double clicking under - Windows. - [271141bb2b43] - - * NEWS, qt/ScintillaQt.cxx, qt/qextscintilla.cxx, qt/qextscintilla.h: - Added setWrapVisualFlags(), WrapMode::WrapCharacter, WrapVisualFlag - to QextScintilla. The layout cache is now set according to the wrap - mode. Setting a wrap mode now disables the horizontal scrollbar. - [a498b86e7999] - -2006-07-01 phil - - * NEWS, qt/qextscintilla.cxx, qt/qextscintilla.h: - Added cancelList(), firstVisibleLine(), isListActive(), - showUserList(), textHeight() and userListActivated() to - QextScintilla. - [058c7be4bdfe] - - * qt/qextscintilla.cxx: - Auto-completion changed so that subsequent start characters cause - the list to be re-created (containing a subset of the previous one). - [5b534658e638] - -2006-06-28 phil - - * NEWS, qt/SciListBox.cxx, qt/qextscintilla.cxx, qt/qextscintilla.h, - qt/qextscintillaapis.cxx, qt/qextscintillaapis.h, - qt/qextscintillalexer.cxx, qt/qextscintillalexer.h, - qt/qextscintillalexerpython.cxx, qt/qextscintillalexerpython.h: - Handle Key_Enter the same as Key_Return. QextScintilla::foldAll() - can now optionally fold all child fold points. Added - autoCompleteFromAll() and setAutoCompletionStartCharacters() to - QextScintilla. Vastly improved the way auto-completion and call tips - work. - [8b0472aaed61] - -2006-06-25 phil - - * qt/qextscintilla.cxx, qt/qextscintillabase.cxx, - qt/qextscintillalexer.cxx: - The default fore and background colours now default to the - application palette rather than being hardcoded to black and white. - [6cb6b5bef5fc] - - * NEWS, qt/qextscintilla.cxx, qt/qextscintilla.h, - qt/qextscintillalexer.cxx, qt/qextscintillalexer.h: - Added defaultColor() and setDefaultColor() to QextScintillaLexer. - Added color() and setColor() to QextScintilla. Renamed eraseColor() - and setEraseColor() to paper() and setPaper() in QextScintilla. - [c1fbfc192235] - - * NEWS, qt/SciListBox.cxx, qt/qextscintilla.cxx, qt/qextscintilla.h, - qt/qextscintillaapis.cxx, qt/qextscintillaapis.h, - qt/qextscintillabase.h, qt/qextscintillalexer.cxx, - qt/qextscintillalexer.h: - Added a couple of extra SendScintilla overloads. One is needed for - PyQt because of the change in SIP's handling of unsigned values. The - other is needed to solve C++ problems caused by the first. - Autocompletion list entries from APIs may now contain spaces. Added - defaultPaper() and setDefaultPaper() to QextScintillaLexer. Added - eraseColor() and setEraseColor() to QextScintilla. - [34f527ca0f99] - -2006-06-21 phil - - * qt/qextscintilla.cxx, qt/qextscintillalexer.cxx, - qt/qextscintillalexer.h, qt/qextscintillalexerhtml.cxx, - qt/qextscintillalexerhtml.h: - Removed QextScintillaLexer::styleBits() now that - SCI_GETSTYLEBITSNEEDED is available. - [1c6837500560] - - * NEWS, qt/PlatQt.cxx, qt/qextscintilla.cxx, qt/qextscintilla.h: - QextScintilla::setSelectionBackgroundColor(), - QextScintilla::setMarkerBackgroundColor() and - QextScintilla::setCaretLineBackgroundColor() now respect the alpha - component. - [48bae1fffe85] - -2006-06-20 phil - - * NEWS, doc/ScintillaDoc.html, doc/ScintillaDownload.html, - doc/ScintillaHistory.html, doc/index.html, gtk/Converter.h, - gtk/PlatGTK.cxx, gtk/ScintillaGTK.cxx, include/Scintilla.h, - include/Scintilla.iface, qt/qextscintillabase.h, - qt/qextscintillalexerpython.h, src/Editor.cxx, src/Editor.h, - src/ViewStyle.cxx, src/ViewStyle.h, version.txt, win32/ScintRes.rc, - win32/ScintillaWin.cxx: - Merged Scintilla v1.70. - [03ac3edd5dd2] - -2006-06-19 phil - - * qt/qextscintillabase.h, qt/qextscintillalexerlua.h, - qt/qextscintillalexerruby.cxx, qt/qextscintillalexerruby.h, - qt/qextscintillalexersql.h: - Significant, and incompatible, updates to the QextScintillaLexerRuby - class. - [0484fe132d0c] - - * src/PropSet.cxx: - Fix for qsort helpers linkage from Ulli. (Patch sent upstream.) - [2307adf67045] - -2006-06-18 phil - - * qt/qextscintillalexerpython.cxx, qt/qextscintillalexerpython.h: - Ctrl-D is now duplicate selection rather than duplicate line. - Updated the Python lexer to add support for hightlighted identifiers - and decorators. - [52ca24a722ac] - - * qt/qextscintillabase.h, qt/qextscintillacommandset.cxx, - qt/qextscintillalexer.h, qt/qextscintillalexerbash.h, - qt/qextscintillalexerbatch.h, qt/qextscintillalexercpp.h, - qt/qextscintillalexercsharp.h, qt/qextscintillalexercss.h, - qt/qextscintillalexerhtml.h, qt/qextscintillalexeridl.h, - qt/qextscintillalexerjava.h, qt/qextscintillalexerjavascript.h, - qt/qextscintillalexerlua.h, qt/qextscintillalexerperl.h, - qt/qextscintillalexerpov.h, qt/qextscintillalexerpython.h, - qt/qextscintillalexerruby.h, qt/qextscintillalexersql.h, - qt/qextscintillalexertex.h, qt/qscintilla.pro: - Added the Scintilla 1.69 extensions to the low level API. - [e89b98aaaa33] - - * .repoman, build.py, doc/Icons.html, doc/ScintillaDoc.html, - doc/ScintillaDownload.html, doc/ScintillaHistory.html, - doc/ScintillaRelated.html, doc/ScintillaToDo.html, doc/index.html, - gtk/PlatGTK.cxx, gtk/ScintillaGTK.cxx, gtk/deps.mak, gtk/makefile, - gtk/scintilla.mak, include/HFacer.py, include/KeyWords.h, - include/Platform.h, include/PropSet.h, include/SciLexer.h, - include/Scintilla.h, include/Scintilla.iface, - include/ScintillaWidget.h, qt/PlatQt.cxx, qt/ScintillaQt.h, - qt/qscintilla.pro, src/CallTip.cxx, src/CallTip.h, - src/CellBuffer.cxx, src/CellBuffer.h, src/CharClassify.cxx, - src/CharClassify.h, src/ContractionState.cxx, src/Document.cxx, - src/Document.h, src/DocumentAccessor.cxx, src/Editor.cxx, - src/Editor.h, src/ExternalLexer.cxx, src/Indicator.cxx, - src/KeyMap.cxx, src/KeyWords.cxx, src/LexAU3.cxx, src/LexBash.cxx, - src/LexBasic.cxx, src/LexCPP.cxx, src/LexCaml.cxx, - src/LexCsound.cxx, src/LexEiffel.cxx, src/LexGen.py, - src/LexGui4Cli.cxx, src/LexHTML.cxx, src/LexInno.cxx, - src/LexLua.cxx, src/LexMSSQL.cxx, src/LexOpal.cxx, - src/LexOthers.cxx, src/LexPOV.cxx, src/LexPython.cxx, - src/LexRuby.cxx, src/LexSQL.cxx, src/LexSpice.cxx, src/LexTCL.cxx, - src/LexVB.cxx, src/LineMarker.h, src/PropSet.cxx, src/RESearch.cxx, - src/RESearch.h, src/ScintillaBase.cxx, src/StyleContext.h, - src/ViewStyle.cxx, src/ViewStyle.h, src/XPM.cxx, - vcbuild/SciLexer.dsp, version.txt, win32/PlatWin.cxx, - win32/ScintRes.rc, win32/ScintillaWin.cxx, win32/deps.mak, - win32/makefile, win32/scintilla.mak, win32/scintilla_vc6.mak: - Removed the redundant .repoman file. Synced with Scintilla v1.69 - with only the minimal changes needed to compile it. - [6774f137c5a1] - -2006-06-17 phil - - * .repoman, License.txt, Makefile, NEWS, README, TODO, bin/empty.txt, - build.py, delbin.bat, delcvs.bat, designer/designer.pro, - designer/qscintillaplugin.cpp, doc/Design.html, doc/Lexer.txt, - doc/SciBreak.jpg, doc/SciCoding.html, doc/SciRest.jpg, - doc/SciTEIco.png, doc/SciWord.jpg, doc/ScintillaDoc.html, - doc/ScintillaDownload.html, doc/ScintillaHistory.html, - doc/ScintillaRelated.html, doc/ScintillaToDo.html, - doc/ScintillaUsage.html, doc/Steps.html, doc/index.html, - example/README, example/application.cpp, example/application.h, - example/application.pro, example/fileopen.xpm, - example/fileprint.xpm, example/filesave.xpm, example/main.cpp, - gtk/Converter.h, gtk/PlatGTK.cxx, gtk/ScintillaGTK.cxx, - gtk/deps.mak, gtk/makefile, gtk/scintilla-marshal.c, gtk/scintilla- - marshal.h, gtk/scintilla-marshal.list, gtk/scintilla.mak, - include/Accessor.h, include/Face.py, include/HFacer.py, - include/KeyWords.h, include/Platform.h, include/PropSet.h, - include/SString.h, include/SciLexer.h, include/Scintilla.h, - include/Scintilla.iface, include/ScintillaWidget.h, - include/WindowAccessor.h, lib/LICENSE.commercial, - lib/LICENSE.commercial.short, lib/LICENSE.edu, - lib/LICENSE.edu.short, lib/LICENSE.gpl, lib/LICENSE.gpl.short, - lib/README, lib/README.MacOS, lib/qscintilla.dxy, qt/PlatQt.cxx, - qt/SciListBox.cxx, qt/SciListBox.h, qt/ScintillaQt.cxx, - qt/ScintillaQt.h, qt/qextscintilla.cxx, qt/qextscintilla.h, - qt/qextscintillaapis.cxx, qt/qextscintillaapis.h, - qt/qextscintillabase.cxx, qt/qextscintillabase.h, - qt/qextscintillacommand.cxx, qt/qextscintillacommand.h, - qt/qextscintillacommandset.cxx, qt/qextscintillacommandset.h, - qt/qextscintilladocument.cxx, qt/qextscintilladocument.h, - qt/qextscintillaglobal.h, qt/qextscintillalexer.cxx, - qt/qextscintillalexer.h, qt/qextscintillalexerbash.cxx, - qt/qextscintillalexerbash.h, qt/qextscintillalexerbatch.cxx, - qt/qextscintillalexerbatch.h, qt/qextscintillalexercpp.cxx, - qt/qextscintillalexercpp.h, qt/qextscintillalexercsharp.cxx, - qt/qextscintillalexercsharp.h, qt/qextscintillalexercss.cxx, - qt/qextscintillalexercss.h, qt/qextscintillalexerdiff.cxx, - qt/qextscintillalexerdiff.h, qt/qextscintillalexerhtml.cxx, - qt/qextscintillalexerhtml.h, qt/qextscintillalexeridl.cxx, - qt/qextscintillalexeridl.h, qt/qextscintillalexerjava.cxx, - qt/qextscintillalexerjava.h, qt/qextscintillalexerjavascript.cxx, - qt/qextscintillalexerjavascript.h, qt/qextscintillalexerlua.cxx, - qt/qextscintillalexerlua.h, qt/qextscintillalexermakefile.cxx, - qt/qextscintillalexermakefile.h, qt/qextscintillalexerperl.cxx, - qt/qextscintillalexerperl.h, qt/qextscintillalexerpov.cxx, - qt/qextscintillalexerpov.h, qt/qextscintillalexerproperties.cxx, - qt/qextscintillalexerproperties.h, qt/qextscintillalexerpython.cxx, - qt/qextscintillalexerpython.h, qt/qextscintillalexerruby.cxx, - qt/qextscintillalexerruby.h, qt/qextscintillalexersql.cxx, - qt/qextscintillalexersql.h, qt/qextscintillalexertex.cxx, - qt/qextscintillalexertex.h, qt/qextscintillamacro.cxx, - qt/qextscintillamacro.h, qt/qextscintillaprinter.cxx, - qt/qextscintillaprinter.h, qt/qscintilla.pro, qt/qscintilla_de.qm, - qt/qscintilla_de.ts, qt/qscintilla_fr.qm, qt/qscintilla_fr.ts, - qt/qscintilla_ptbr.qm, qt/qscintilla_ptbr.ts, qt/qscintilla_ru.qm, - qt/qscintilla_ru.ts, src/AutoComplete.cxx, src/AutoComplete.h, - src/CallTip.cxx, src/CallTip.h, src/CellBuffer.cxx, - src/CellBuffer.h, src/ContractionState.cxx, src/ContractionState.h, - src/Document.cxx, src/Document.h, src/DocumentAccessor.cxx, - src/DocumentAccessor.h, src/Editor.cxx, src/Editor.h, - src/ExternalLexer.cxx, src/ExternalLexer.h, src/Indicator.cxx, - src/Indicator.h, src/KeyMap.cxx, src/KeyMap.h, src/KeyWords.cxx, - src/LexAPDL.cxx, src/LexAU3.cxx, src/LexAVE.cxx, src/LexAda.cxx, - src/LexAsm.cxx, src/LexAsn1.cxx, src/LexBaan.cxx, src/LexBash.cxx, - src/LexBasic.cxx, src/LexBullant.cxx, src/LexCLW.cxx, - src/LexCPP.cxx, src/LexCSS.cxx, src/LexCaml.cxx, src/LexConf.cxx, - src/LexCrontab.cxx, src/LexCsound.cxx, src/LexEScript.cxx, - src/LexEiffel.cxx, src/LexErlang.cxx, src/LexFlagship.cxx, - src/LexForth.cxx, src/LexFortran.cxx, src/LexGen.py, - src/LexGui4Cli.cxx, src/LexHTML.cxx, src/LexHaskell.cxx, - src/LexKix.cxx, src/LexLisp.cxx, src/LexLout.cxx, src/LexLua.cxx, - src/LexMMIXAL.cxx, src/LexMPT.cxx, src/LexMSSQL.cxx, - src/LexMatlab.cxx, src/LexMetapost.cxx, src/LexNsis.cxx, - src/LexOthers.cxx, src/LexPB.cxx, src/LexPOV.cxx, src/LexPS.cxx, - src/LexPascal.cxx, src/LexPerl.cxx, src/LexPython.cxx, - src/LexRebol.cxx, src/LexRuby.cxx, src/LexSQL.cxx, - src/LexScriptol.cxx, src/LexSmalltalk.cxx, src/LexSpecman.cxx, - src/LexTADS3.cxx, src/LexTeX.cxx, src/LexVB.cxx, src/LexVHDL.cxx, - src/LexVerilog.cxx, src/LexYAML.cxx, src/LineMarker.cxx, - src/LineMarker.h, src/PropSet.cxx, src/RESearch.cxx, src/RESearch.h, - src/SVector.h, src/SciTE.properties, src/ScintillaBase.cxx, - src/ScintillaBase.h, src/Style.cxx, src/Style.h, - src/StyleContext.cxx, src/StyleContext.h, src/UniConversion.cxx, - src/UniConversion.h, src/ViewStyle.cxx, src/ViewStyle.h, - src/WindowAccessor.cxx, src/XPM.cxx, src/XPM.h, tgzsrc, - vcbuild/SciLexer.dsp, version.txt, win32/Margin.cur, - win32/PlatWin.cxx, win32/PlatformRes.h, win32/SciTE.properties, - win32/ScintRes.rc, win32/Scintilla.def, win32/ScintillaWin.cxx, - win32/deps.mak, win32/makefile, win32/scintilla.mak, - win32/scintilla_vc6.mak, zipsrc.bat: - First import of QScintilla - [0521804cd44a] - diff --git a/libs/qscintilla/NEWS b/libs/qscintilla/NEWS deleted file mode 100644 index 52142310e..000000000 --- a/libs/qscintilla/NEWS +++ /dev/null @@ -1,384 +0,0 @@ -v2.9 20th April 2015 - - Based on Scintilla v3.5.4. - - Added UserLiteral, InactiveUserLiteral, TaskMarker, InactiveTaskMarker, - EscapeSequence, InactiveEscapeSequence, setHighlightBackQuotedStrings(), - highlightBackQuotedStrings(), setHighlightEscapeSequences(), - highlightEscapeSequences(), setVerbatimStringEscapeSequencesAllowed() and - verbatimStringEscapeSequencesAllowed() to QsciLexerCPP. - - Added CommentKeyword, DeclareInputPort, DeclareOutputPort, - DeclareInputOutputPort, PortConnection and the inactive versions of all - styles to QsciLexerVerilog. - - Added CommentBlock to QsciLexerVHDL. - - Added AnnotationIndented to QsciScintilla::AnnotationDisplay. - - Added FullBoxIndicator, ThickCompositionIndicator, ThinCompositionIndicator - and TextColorIndicator to QsciScintilla::IndicatorStyle. - - Added setIndicatorHoverForegroundColor() and setIndicatorHoverStyle() to - QsciScintilla. - - Added Bookmark to QsciScintilla::MarkerSymbol. - - Added WrapWhitespace to QsciScintilla::WrapMode. - - Added SCLEX_AS, SCLEX_BIBTEX, SCLEX_DMAP, SCLEX_DMIS, SCLEX_IHEX, - SCLEX_REGISTRY, SCLEX_SREC and SCLEX_TEHEX to QsciScintillaBase. - - Added SCI_CHANGEINSERTION to QsciScintillaBase. - - Added SCI_CLEARTABSTOPS, SCI_ADDTABSTOP and SCI_GETNEXTTABSTOP to - QsciScintillaBase. - - Added SCI_GETIMEINTERACTION, SCI_SETIMEINTERACTION, SC_IME_WINDOWED and - SC_IME_INLINE to QsciScintillaBase. - - Added SC_MARK_BOOKMARK to QsciScintillaBase. - - Added INDIC_COMPOSITIONTHIN, INDIC_FULLBOX, INDIC_TEXTFORE, INDIC_IME, - INDIC_IME_MAX, SC_INDICVALUEBIT, SC_INDICVALUEMASK, - SC_INDICFLAG_VALUEBEFORE, SCI_INDICSETHOVERSTYLE, SCI_INDICGETHOVERSTYLE, - SCI_INDICSETHOVERFORE, SCI_INDICGETHOVERFORE, SCI_INDICSETFLAGS and - SCI_INDICGETFLAGS to QsciScintillaBase. - - Added SCI_SETTARGETRANGE and SCI_GETTARGETRANGE to QsciScintillaBase. - - Added SCFIND_CXX11REGEX to QsciScintillaBase. - - Added SCI_CALLTIPSETPOSSTART to QsciScintillaBase. - - Added SC_FOLDFLAG_LINESTATE to QsciScintillaBase. - - Added SC_WRAP_WHITESPACE to QsciScintillaBase. - - Added SC_PHASES_ONE, SC_PHASES_TWO, SC_PHASES_MULTIPLE, SCI_GETPHASESDRAW - and SCI_SETPHASESDRAW to QsciScintillaBase. - - Added SC_STATUS_OK, SC_STATUS_FAILURE, SC_STATUS_BADALLOC, - SC_STATUS_WARN_START and SC_STATUS_WARNREGEX to QsciScintillaBase. - - Added SC_MULTIAUTOC_ONCE, SC_MULTIAUTOC_EACH, SCI_AUTOCSETMULTI and - SCI_AUTOCGETMULTI to QsciScintillaBase. - - Added ANNOTATION_INDENTED to QsciScintillaBase. - - Added SCI_DROPSELECTIONN to QsciScintillaBase. - - Added SC_TECHNOLOGY_DIRECTWRITERETAIN and SC_TECHNOLOGY_DIRECTWRITEDC to - QsciScintillaBase. - - Added SC_LINE_END_TYPE_DEFAULT, SC_LINE_END_TYPE_UNICODE, - SCI_GETLINEENDTYPESSUPPORTED, SCI_SETLINEENDTYPESALLOWED, - SCI_GETLINEENDTYPESALLOWED and SCI_GETLINEENDTYPESACTIVE to - QsciScintillaBase. - - Added SCI_ALLOCATESUBSTYLES, SCI_GETSUBSTYLESSTART, SCI_GETSUBSTYLESLENGTH, - SCI_GETSTYLEFROMSUBSTYLE, SCI_GETPRIMARYSTYLEFROMSTYLE, SCI_FREESUBSTYLES, - SCI_SETIDENTIFIERS, SCI_DISTANCETOSECONDARYSTYLES and SCI_GETSUBSTYLEBASES - to QsciScintillaBase. - - Added SC_MOD_INSERTCHECK and SC_MOD_CHANGETABSTOPS to QsciScintillaBase. - - Qt v3 and PyQt v3 are no longer supported. - -v2.8.4 11th September 2014 - - Added setHotspotForegroundColor(), resetHotspotForegroundColor(), - setHotspotBackgroundColor(), resetHotspotBackgroundColor(), - setHotspotUnderline() and setHotspotWrap() to QsciScintilla. - - Added SCI_SETHOTSPOTSINGLELINE to QsciScintillaBase. - - Bug fixes. - -v2.8.3 3rd July 2014 - - Added the QsciLexerCoffeeScript class. - - Font sizes are now handled as floating point values rather than integers. - - Bug fixes. - -v2.8.2 26th May 2014 - - Added the QsciLexerAVS class. - - Added the QsciLexerPO class. - - Added the --sysroot, --no-sip-files and --no-qsci-api options to the Python - bindings' configure.py. - - Cross-compilation (specifically to iOS and Android) is now supported. - - configure.py has been refactored and relicensed so that it can be used as a - template for wrapping other bindings. - - Bug fixes. - -v2.8.1 14th March 2014 - - Added support for iOS and Android. - - Added support for retina displays. - - A qscintilla2.prf file is installed so that application .pro files only - need to add CONFIG += qscintilla2. - - Updated the keywords recognised by the Octave lexer. - - Bug fixes. - -v2.8 9th November 2013 - - Based on Scintilla v3.3.6. - - Added the SCN_FOCUSIN() and SCN_FOCUSOUT() signals to QsciScintillaBase. - - Added PreProcessorCommentLineDoc and InactivePreProcessorCommentLineDoc to - QsciLexerCPP. - - Added SCLEX_LITERATEHASKELL, SCLEX_KVIRC, SCLEX_RUST and SCLEX_STTXT to - QsciScintillaBase. - - Added ThickCompositionIndicator to QsciScintilla::IndicatorStyle. - - Added INDIC_COMPOSITIONTHICK to QsciScintillaBase. - - Added SC_FOLDACTION_CONTRACT, SC_FOLDACTION_EXPAND and SC_FOLDACTION_TOGGLE - to QsciScintillaBase. - - Added SCI_FOLDLINE, SCI_FOLDCHILDREN, SCI_EXPANDCHILDREN and SCI_FOLDALL to - QsciScintillaBase. - - Added SC_AUTOMATICFOLD_SHOW, SC_AUTOMATICFOLD_CLICK and - SC_AUTOMATICFOLD_CHANGE to QsciScintillaBase. - - Added SCI_SETAUTOMATICFOLD and SCI_GETAUTOMATICFOLD to QsciScintillaBase. - - Added SC_ORDER_PRESORTED, SC_ORDER_PERFORMSORT and SC_ORDER_CUSTOM to - QsciScintillaBase. - - Added SCI_AUTOCSETORDER and SCI_AUTOCGETORDER to QsciScintillaBase. - - Added SCI_POSITIONRELATIVE to QsciScintillaBase. - - Added SCI_RELEASEALLEXTENDEDSTYLES and SCI_ALLOCATEEXTENDEDSTYLES to - QsciScintillaBase. - - Added SCI_SCROLLRANGE to QsciScintillaBase. - - Added SCI_SETCARETLINEVISIBLEALWAYS and SCI_GETCARETLINEVISIBLEALWAYS to - QsciScintillaBase. - - Added SCI_SETMOUSESELECTIONRECTANGULARSWITCH and - SCI_GETMOUSESELECTIONRECTANGULARSWITCH to QsciScintillaBase. - - Added SCI_SETREPRESENTATION, SCI_GETREPRESENTATION and - SCI_CLEARREPRESENTATION to QsciScintillaBase. - - Input methods are now properly supported. - -v2.7.2 16th June 2013 - - The build script for the Python bindings now has a --pyqt argument for - specifying PyQt4 or PyQt5. - - The default EOL mode on OS/X is now EolUnix. - - Bug fixes. - -v2.7.1 1st March 2013 - - Added support for the final release of Qt v5. - - The build script for the Python bindings should now work with SIP v5. - - Bug fixes. - -v2.7 8th December 2012 - - Based on Scintilla v3.2.3. - - Added support for Qt v5-rc1. - - Added HashQuotedString, InactiveHashQuotedString, PreProcessorComment, - InactivePreProcessorComment, setHighlightHashQuotedStrings() and - highlightHashQuotedStrings() to QsciLexerCpp. - - Added Variable, setHSSLanguage(), HSSLanguage(), setLessLanguage(), - LessLanguage(), setSCCSLanguage() and SCCSLanguage() to QsciLexerCSS. - - Added setOverwriteMode() and overwriteMode() to QsciScintilla. - - Added wordAtLineIndex() to QsciScintilla. - - Added findFirstInSelection() to QsciScintilla. - - Added CallTipsPosition, callTipsPosition() and setCallTipsPosition() to - QsciScintilla. - - Added WrapFlagInMargin to QsciScintilla::WrapVisualFlag. - - Added SquigglePixmapIndicator to QsciScintilla::IndicatorStyle. - - The weight of a font (rather than whether it is just bold or not) is now - respected. - - Added SCLEX_AVS, SCLEX_COFFEESCRIPT, SCLEX_ECL, SCLEX_OSCRIPT, - SCLEX_TCMD and SCLEX_VISUALPROLOG to QsciScintillaBase. - - Added SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE and - SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE to QsciScintillaBase. - - Added SC_FONT_SIZE_MULTIPLIER to QsciScintillaBase. - - Added SC_WEIGHT_NORMAL, SC_WEIGHT_SEMIBOLD and SC_WEIGHT_BOLD to - QsciScintillaBase. - - Added SC_WRAPVISUALFLAG_MARGIN to QsciScintillaBase. - - Added INDIC_SQUIGGLEPIXMAP to QsciScintillaBase. - - Added SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR, - SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR, SCI_CALLTIPSETPOSITION, - SCI_COUNTCHARACTERS, SCI_CREATELOADER, SCI_DELETERANGE, - SCI_FINDINDICATORFLASH, SCI_FINDINDICATORHIDE, SCI_FINDINDICATORSHOW, - SCI_GETALLLINESVISIBLE, SCI_GETGAPPOSITION, SCI_GETPUNCTUATIONCHARS, - SCI_GETRANGEPOINTER, SCI_GETSELECTIONEMPTY, SCI_GETTECHNOLOGY, - SCI_GETWHITESPACECHARS, SCI_GETWORDCHARS, SCI_RGBAIMAGESETSCALE, - SCI_SETPUNCTUATIONCHARS, SCI_SETTECHNOLOGY, SCI_STYLESETSIZEFRACTIONAL, - SCI_STYLEGETSIZEFRACTIONAL, SCI_STYLESETWEIGHT and SCI_STYLEGETWEIGHT to - QsciScintillaBase. - - Removed SCI_GETUSEPALETTE and SCI_SETUSEPALETTE from QsciScintillaBase. - - Bug fixes. - -v2.6.2 20th June 2012 - - Added support for Qt v5-alpha. - - QsciLexer::wordCharacters() is now part of the public API. - - Bug fixes. - -v2.6.1 10th February 2012 - - Support SCI_NAMESPACE to enable all internal Scintilla classes to be put - into the Scintilla namespace. - - APIs now allow for spaces between the end of a word and the opening - parenthesis. - - Building against Qt v3 is fixed. - -v2.6 11th November 2011 - - Based on Scintilla v2.29. - - Added Command, command() and execute() to QsciCommand. - - Added boundTo() and find() to QsciCommandSet. - - Added createStandardContextMenu() to QsciScintilla. - - Added StraightBoxIndicator, DashesIndicator, DotsIndicator, - SquiggleLowIndicator and DotBoxIndicator to QsciScintilla::IndicatorStyle. - - Added markerDefine() to QsciScintilla. - - Added MoNone, MoSublineSelect, marginOptions() and setMarginOptions() to - QsciScintilla. - - Added registerImage() to QsciScintilla. - - Added setIndicatorOutlineColor() to QsciScintilla. - - Added setMatchedBraceIndicator(), resetMatchedBraceIndicator(), - setUnmatchedBraceIndicator() and resetUnmatchedBraceIndicator() to - QsciScintilla. - - Added highlightTripleQuotedStrings() and setHighlightTripleQuotedStrings() - to QsciLexerCpp. - - Added Label to QsciLexerLua. - - Added DoubleQuotedStringVar, Translation, RegexVar, SubstitutionVar, - BackticksVar, DoubleQuotedHereDocumentVar, BacktickHereDocumentVar, - QuotedStringQQVar, QuotedStringQXVar, QuotedStringQRVar, setFoldAtElse() - and foldAtElse() to QsciLexerPerl. - - Added highlightSubidentifiers() and setHighlightSubidentifiers() to - QsciLexerPython. - - Added INDIC_STRAIGHTBOX, INDIC_DASH, INDIC_DOTS, INDIC_SQUIGGLELOW and - INDIC_DOTBOX to QsciScintillaBase. - - Added SC_MARGINOPTION_NONE and SC_MARGINOPTION_SUBLINESELECT to - QsciScintillaBase. - - Added SC_MARK_RGBAIMAGE to QsciScintillaBase. - - Added SCI_BRACEBADLIGHTINDICATOR, SCI_BRACEHIGHLIGHTINDICATOR, - SCI_GETIDENTIFIER, SCI_GETMARGINOPTIONS, SCI_INDICGETOUTLINEALPHA, - SCI_INDICSETOUTLINEALPHA, SCI_MARKERDEFINERGBAIMAGE, - SCI_MARKERENABLEHIGHLIGHT, SCI_MARKERSETBACKSELECTED, - SCI_MOVESELECTEDLINESDOWN, SCI_MOVESELECTEDLINESUP, SCI_REGISTERRGBAIMAGE, - SCI_RGBAIMAGESETHEIGHT, SCI_RGBAIMAGESETWIDTH, SCI_SCROLLTOEND, - SCI_SCROLLTOSTART, SCI_SETEMPTYSELECTION, SCI_SETIDENTIFIER and - SCI_SETMARGINOPTIONS to QsciScintillaBase. - -v2.5.1 17th April 2011 - - Added QsciLexerMatlab and QsciLexerOctave. - -v2.5 29th March 2011 - - Based on Scintilla v2.25. - - Rectangular selections are now fully supported and compatible with SciTE. - - The signature of the fromMimeData() and toMimeData() methods of - QsciScintillaBase have changed incompatibly in order to support rectangular - selections. - - Added QsciScintilla::setAutoCompletionUseSingle() to replace the now - deprecated setAutoCompletionShowSingle(). - - Added QsciScintilla::autoCompletionUseSingle() to replace the now - deprecated autoCompletionShowSingle(). - - QsciScintilla::setAutoCompletionCaseSensitivity() is no longer ignored if a - lexer has been set. - - Added FullRectangle, LeftRectangle and Underline to the - QsciScintilla::MarkerSymbol enum. - - Added setExtraAscent(), extraAscent(), setExtraDescent() and extraDescent() - to QsciScintilla. - - Added setWhitespaceSize() and whitespaceSize() to QsciScintilla. - - Added replaceSelectedText() to QsciScintilla. - - Added setWhitespaceBackgroundColor() and setWhitespaceForegroundColor() to - QsciScintilla. - - Added setWrapIndentMode() and wrapIndentMode() to QsciScintilla. - - Added setFirstVisibleLine() to QsciScintilla. - - Added setContractedFolds() and contractedFolds() to QsciScintilla. - - Added the SCN_HOTSPOTRELEASECLICK() signal to QsciScintillaBase. - - The signature of the QsciScintillaBase::SCN_UPDATEUI() signal has changed. - - Added the RawString and inactive styles to QsciLexerCPP. - - Added MediaRule to QsciLexerCSS. - - Added BackquoteString, RawString, KeywordSet5, KeywordSet6 and KeywordSet7 - to QsciLexerD. - - Added setDjangoTemplates(), djangoTemplates(), setMakoTemplates() and - makoTemplates() to QsciLexerHTML. - - Added KeywordSet5, KeywordSet6, KeywordSet7 and KeywordSet8 to - QsciLexerLua. - - Added setInitialSpaces() and initialSpaces() to QsciLexerProperties. - - Added setFoldCompact(), foldCompact(), setStringsOverNewlineAllowed() and - stringsOverNewlineAllowed() to QsciLexerPython. - - Added setFoldComments(), foldComments(), setFoldCompact() and foldCompact() - to QsciLexerRuby. - - Added setFoldComments() and foldComments(), and removed setFoldCompact() - and foldCompact() from QsciLexerTCL. - - Added setFoldComments(), foldComments(), setFoldCompact(), foldCompact(), - setProcessComments(), processComments(), setProcessIf(), and processIf() to - QsciLexerTeX. - - Added QuotedIdentifier, setDottedWords(), dottedWords(), setFoldAtElse(), - foldAtElse(), setFoldOnlyBegin(), foldOnlyBegin(), setHashComments(), - hashComments(), setQuotedIdentifiers() and quotedIdentifiers() to - QsciLexerSQL. - - The Python bindings now allow optional arguments to be specified as keyword - arguments. - - The Python bindings will now build using the protected-is-public hack if - possible. - -v2.4.6 23rd December 2010 - - Added support for indicators to the high-level API, i.e. added the - IndicatorStyle enum, the clearIndicatorRange(), fillIndicatorRange(), - indicatorDefine(), indicatorDrawUnder(), setIndicatorDrawUnder() and - setIndicatorForegroundColor methods, and the indicatorClicked() and - indicatorReleased() signals to QsciScintilla. - - Added support for the Key style in QsciLexerProperties. - - Added an API file for Python v2.7. - - Added the --no-timestamp command line option to the Python bindings' - configure.py. - -v2.4.5 31st August 2010 - - A bug fix release. - -v2.4.4 12th July 2010 - - Added the canInsertFromMimeData(), fromMimeData() and toMimeData() methods - to QsciScintillaBase. - - QsciScintilla::markerDefine() now allows existing markers to be redefined. - -v2.4.3 17th March 2010 - - Added clearFolds() to QsciScintilla. - -v2.4.2 20th January 2010 - - Updated Spanish translations from Jaime Seuma. - - Fixed compilation problems with Qt v3 and Qt v4 prior to v4.5. - -v2.4.1 14th January 2010 - - Added the QsciLexerSpice and QsciLexerVerilog classes. - - Significant performance improvements when handling long lines. - - The Python bindings include automatically generated docstrings by default. - - Added an API file for Python v3. - -v2.4 5th June 2009 - - Based on Scintilla v1.78. - - Added the QsciLexerCustom, QsciStyle and QsciStyledText classes. - - Added annotate(), annotation(), clearAnnotations(), setAnnotationDisplay() - and annotationDisplay() to QsciScintilla. - - Added setMarginText(), clearMarginText(), setMarginType() and marginType() - to QsciScintilla. - - Added QsciLexer::lexerId() so that container lexers can be implemented. - - Added editor() and styleBitsNeeded() to QsciLexer. - - Added setDollarsAllowed() and dollarsAllowed() to QsciLexerCPP. - - Added setFoldScriptComments(), foldScriptComments(), - setFoldScriptHeredocs() and foldScriptHeredocs() to QsciLexerHTML. - - Added setSmartHighlighting() and smartHighlighting() to QsciLexerPascal. - (Note that the Scintilla Pascal lexer has changed so that any saved colour - and font settings will not be properly restored.) - - Added setFoldPackages(), foldPackages(), setFoldPODBlocks() and - foldPODBlocks() to QsciLexerPerl. - - Added setV2UnicodeAllowed(), v2UnicodeAllowed(), setV3BinaryOctalAllowed(), - v3BinaryOctalAllowed(), setV3BytesAllowed and v3BytesAllowed() to - QsciLexerPython. - - Added setScriptsStyled() and scriptsStyled() to QsciLexerXML. - - Added Spanish translations from Jaime Seuma. - -v2.3.2 17th November 2008 - - A bug fix release. - -v2.3.1 6th November 2008 - - Based on Scintilla v1.77. - - Added the read() and write() methods to QsciScintilla to allow a file to be - read and written while minimising the conversions. - - Added the positionFromLineIndex() and lineIndexFromPosition() methods to - QsciScintilla to convert between a Scintilla character address and a - QScintilla character address. - - Added QsciScintilla::wordAtPoint() to return the word at the given screen - coordinates. - - QSciScintilla::setSelection() now allows the carat to be left at either the - start or the end of the selection. - - 'with' is now treated as a keyword by the Python lexer. - -v2.3 20th September 2008 - - Based on Scintilla v1.76. - - The new QsciAbstractAPIs class allows applications to replace the default - implementation of the language APIs used for auto-completion lists and call - tips. - - Added QsciScintilla::apiContext() to allow applications to determine the - context used for auto-completion and call tips. - - Added the QsciLexerFortran, QsciLexerFortran77, QsciLexerPascal, - QsciLexerPostScript, QsciLexerTCL, QsciLexerXML and QsciLexerYAML classes. - - QsciScintilla::setFolding() will now accept an optional margin number. - -v2.2 27th February 2008 - - Based on Scintilla v1.75. - - A lexer's default colour, paper and font are now written to and read from - the settings. - - Windows64 is now supported. - - The signature of the QsciScintillaBase::SCN_MACRORECORD() signal has - changed slightly. - - Changed the licensing to match the current Qt licenses, including GPL v3. - -v2.1 1st June 2007 - - A slightly revised API, incompatible with QScintilla v2.0. - - Lexers now remember their style settings. A lexer no longer has to be the - current lexer when changing a style's color, end-of-line fill, font or - paper. - - The color(), eolFill(), font() and paper() methods of QsciLexer now return - the current values for a style rather than the default values. - - The setDefaultColor(), setDefaultFont() and setDefaultPaper() methods of - QsciLexer are no longer slots and no longer virtual. - - The defaultColor(), defaultFont() and defaultPaper() methods of QsciLexer - are no longer virtual. - - The color(), eolFill(), font() and paper() methods of all QsciLexer derived - classes (except for QsciLexer itself) have been renamed defaultColor(), - defaultEolFill(), defaultFont() and defaultPaper() respectively. - -v2.0 26th May 2007 - - A revised API, incompatible with QScintilla v1. - - Hugely improved autocompletion and call tips support. - - Supports both Qt v3 and Qt v4. - - Includes Python bindings. diff --git a/libs/qscintilla/Qt4Qt5/CMakeLists.txt b/libs/qscintilla/Qt4Qt5/CMakeLists.txt deleted file mode 100644 index d46452247..000000000 --- a/libs/qscintilla/Qt4Qt5/CMakeLists.txt +++ /dev/null @@ -1,166 +0,0 @@ -cmake_minimum_required(VERSION 2.8.7) - -if(USE_QT5) - set(CMAKE_AUTOMOC ON) - set(CMAKE_INCLUDE_CURRENT_DIR ON) - find_package(Qt5Widgets REQUIRED) -else() - find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) - include("${QT_USE_FILE}") - add_definitions(${QT_DEFINITIONS}) -endif() - -if(APPLE AND USE_QT5) - find_package(Qt5MacExtras) -endif() - -add_definitions(-DSCINTILLA_QT) -add_definitions(-DSCI_LEXER) - -set(QSCINTILLA_SRC - qsciscintilla.cpp - qsciscintillabase.cpp - qsciabstractapis.cpp - qsciapis.cpp - qscicommand.cpp - qscicommandset.cpp - qscidocument.cpp - qscilexer.cpp - qscilexersql.cpp - qscimacro.cpp - qsciprinter.cpp - qscistyle.cpp - qscistyledtext.cpp - MacPasteboardMime.cpp - InputMethod.cpp - SciClasses.cpp - ListBoxQt.cpp - PlatQt.cpp - ScintillaQt.cpp - ../lexers/LexSQL.cpp - ../lexlib/Accessor.cpp - ../lexlib/CharacterCategory.cpp - ../lexlib/CharacterSet.cpp - ../lexlib/LexerBase.cpp - ../lexlib/LexerModule.cpp - ../lexlib/LexerNoExceptions.cpp - ../lexlib/LexerSimple.cpp - ../lexlib/PropSetSimple.cpp - ../lexlib/StyleContext.cpp - ../lexlib/WordList.cpp - ../src/AutoComplete.cpp - ../src/CallTip.cpp - ../src/CaseConvert.cpp - ../src/CaseFolder.cpp - ../src/Catalogue.cpp - ../src/CellBuffer.cpp - ../src/CharClassify.cpp - ../src/ContractionState.cpp - ../src/Decoration.cpp - ../src/Document.cpp - ../src/Editor.cpp - ../src/EditModel.cpp - ../src/EditView.cpp - ../src/ExternalLexer.cpp - ../src/Indicator.cpp - ../src/KeyMap.cpp - ../src/LineMarker.cpp - ../src/MarginView.cpp - ../src/PerLine.cpp - ../src/PositionCache.cpp - ../src/RESearch.cpp - ../src/RunStyles.cpp - ../src/ScintillaBase.cpp - ../src/Selection.cpp - ../src/Style.cpp - ../src/UniConversion.cpp - ../src/ViewStyle.cpp - ../src/XPM.cpp -) - -set(QSCINTILLA_HDR - ./Qsci/qsciglobal.h - ./Qsci/qscicommand.h - ./Qsci/qscicommandset.h - ./Qsci/qscidocument.h - ./Qsci/qsciprinter.h - ./Qsci/qscistyle.h - ./Qsci/qscistyledtext.h - ListBoxQt.h - SciNamespace.h - ../include/ILexer.h - ../include/Platform.h - ../include/SciLexer.h - ../include/Scintilla.h - ../include/ScintillaWidget.h - ../lexlib/Accessor.h - ../lexlib/CharacterCategory.h - ../lexlib/CharacterSet.h - ../lexlib/LexAccessor.h - ../lexlib/LexerBase.h - ../lexlib/LexerModule.h - ../lexlib/LexerNoExceptions.h - ../lexlib/LexerSimple.h - ../lexlib/OptionSet.h - ../lexlib/PropSetSimple.h - ../lexlib/StyleContext.h - ../lexlib/SubStyles.h - ../lexlib/WordList.h - ../src/AutoComplete.h - ../src/CallTip.h - ../src/CaseConvert.h - ../src/CaseFolder.h - ../src/Catalogue.h - ../src/CellBuffer.h - ../src/CharClassify.h - ../src/ContractionState.h - ../src/Decoration.h - ../src/Document.h - ../src/Editor.h - ../src/ExternalLexer.h - ../src/FontQuality.h - ../src/Indicator.h - ../src/KeyMap.h - ../src/LineMarker.h - ../src/Partitioning.h - ../src/PerLine.h - ../src/PositionCache.h - ../src/RESearch.h - ../src/RunStyles.h - ../src/ScintillaBase.h - ../src/Selection.h - ../src/SplitVector.h - ../src/Style.h - ../src/UnicodeFromUTF8.h - ../src/UniConversion.h - ../src/ViewStyle.h - ../src/XPM.h -) - -set(QSCINTILLA_MOC_HDR - ./Qsci/qsciscintilla.h - ./Qsci/qsciscintillabase.h - ./Qsci/qsciabstractapis.h - ./Qsci/qsciapis.h - ./Qsci/qscilexer.h - ./Qsci/qscilexersql.h - ./Qsci/qscimacro.h - SciClasses.h - ScintillaQt.h -) - -if(NOT USE_QT5) - QT4_WRAP_CPP(QSCINTILLA_MOC ${QSCINTILLA_MOC_HDR}) -endif() - -include_directories(. ../include ../lexlib ../src) - -add_library(qscintilla2 ${QSCINTILLA_SRC} ${QSCINTILLA_HDR} ${QSCINTILLA_MOC_HDR} ${QSCINTILLA_MOC}) - -if(USE_QT5) - if (APPLE) - qt5_use_modules(qscintilla2 Widgets PrintSupport MacExtras) - else() - qt5_use_modules(qscintilla2 Widgets PrintSupport) - endif() -endif() diff --git a/libs/qscintilla/Qt4Qt5/InputMethod.cpp b/libs/qscintilla/Qt4Qt5/InputMethod.cpp deleted file mode 100644 index c6da96737..000000000 --- a/libs/qscintilla/Qt4Qt5/InputMethod.cpp +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2015 Riverbank Computing Limited -// Copyright (c) 2011 Archaeopteryx Software, Inc. -// Copyright (c) 1990-2011, Scientific Toolworks, Inc. -// -// The License.txt file describes the conditions under which this software may -// be distributed. - - -#include - -#include "Qsci/qsciscintillabase.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ScintillaQt.h" - - -#define INDIC_INPUTMETHOD 24 - - -void QsciScintillaBase::inputMethodEvent(QInputMethodEvent *event) -{ - // Do nothing if it appears to be a non-event. This can sometimes happen - // (but why?) on losing focus. - if (event->commitString().isEmpty() && event->preeditString().isEmpty() && event->replacementLength() == 0) - return; - - ScintillaBytes bytes; - - // Clear the current selection. - sci->ClearSelection(); - if (preeditPos >= 0) - sci->SetSelection(preeditPos, preeditPos); - - // Insert the commit string. - if (!event->commitString().isEmpty() || event->replacementLength()) { - // Select the text to be removed. - int commitPos = SendScintilla(SCI_GETCURRENTPOS); - int start = commitPos + event->replacementStart(); - int end = start + event->replacementLength(); - sci->SetSelection(start, end); - - // Replace the selection with the commit string. - bytes = textAsBytes(event->commitString()); - sci->AddCharUTF(bytes.data(), bytes.length()); - } - - // Select the previous preedit string. - int pos = SendScintilla(SCI_GETCURRENTPOS); - sci->SetSelection(pos, pos + preeditNrBytes); - - // Replace the selection with the new preedit string. - bool recording = sci->recordingMacro; - sci->recordingMacro = false; - SendScintilla(SCI_SETUNDOCOLLECTION, false); - bytes = textAsBytes(event->preeditString()); - sci->AddCharUTF(bytes.data(), bytes.length()); - SendScintilla(SCI_SETUNDOCOLLECTION, true); - sci->recordingMacro = recording; - sci->SetSelection(pos, pos); - - // Store the state of the current preedit string. - preeditString = event->preeditString(); - preeditNrBytes = bytes.length(); - preeditPos = preeditNrBytes ? SendScintilla(SCI_GETCURRENTPOS) : -1; - - if (preeditNrBytes) { - // Apply attributes to the preedit string. - int indicNum = 0; - sci->ShowCaretAtCurrentPosition(); - foreach (QInputMethodEvent::Attribute a, event->attributes()) { - QString prefix = preeditString.left(a.start); - int prefixLength = textAsBytes(prefix).length(); - int caretPos = preeditPos + prefixLength; - - if (a.type == QInputMethodEvent::Cursor) { - sci->SetSelection(caretPos, caretPos); - if (!a.length) - sci->DropCaret(); - - } else if (a.type == QInputMethodEvent::TextFormat) { - Q_ASSERT(a.value.canConvert(QVariant::TextFormat)); - QTextFormat format = a.value.value(); - Q_ASSERT(format.isCharFormat()); - QTextCharFormat charFormat = format.toCharFormat(); - - if (charFormat.underlineStyle() != QTextCharFormat::NoUnderline) { - QString sub = preeditString.mid(a.start, a.length); - int subLength = textAsBytes(sub).length(); - - // Set temporary indicator for underline style. - QColor uc = charFormat.underlineColor(); - int style = INDIC_COMPOSITIONTHICK; - if (charFormat.underlineStyle() == QTextCharFormat::DashUnderline) - style = INDIC_DASH; - - SendScintilla(SCI_INDICSETSTYLE, INDIC_INPUTMETHOD + indicNum, style); - SendScintilla(SCI_INDICSETFORE, INDIC_INPUTMETHOD + indicNum, uc.rgb()); - SendScintilla(SCI_SETINDICATORCURRENT, INDIC_INPUTMETHOD + indicNum); - SendScintilla(SCI_INDICATORFILLRANGE, caretPos, subLength); - indicNum++; - } - } - } - } -} - -QVariant QsciScintillaBase::inputMethodQuery(Qt::InputMethodQuery query) const -{ - int pos = SendScintilla(SCI_GETCURRENTPOS); - int line = SendScintilla(SCI_LINEFROMPOSITION, pos); - - switch (query) { -#if QT_VERSION >= 0x050000 - case Qt::ImHints: - return QWidget::inputMethodQuery(query); -#endif - - case Qt::ImMicroFocus: - { - int startPos = (preeditPos >= 0) ? preeditPos : pos; - Point pt = sci->LocationFromPosition(startPos); - int width = SendScintilla(SCI_GETCARETWIDTH); - int height = SendScintilla(SCI_TEXTHEIGHT, line); - return QRect(pt.x, pt.y, width, height); - } - - case Qt::ImFont: - { - char fontName[64]; - int style = SendScintilla(SCI_GETSTYLEAT, pos); - int len = SendScintilla(SCI_STYLEGETFONT, style, (sptr_t)fontName); - int size = SendScintilla(SCI_STYLEGETSIZE, style); - bool italic = SendScintilla(SCI_STYLEGETITALIC, style); - int weight = SendScintilla(SCI_STYLEGETBOLD, style) ? QFont::Bold : -1; - return QFont(QString::fromUtf8(fontName, len), size, weight, italic); - } - - case Qt::ImCursorPosition: - { - int paraStart = sci->pdoc->ParaUp(pos); - return pos - paraStart; - } - - case Qt::ImSurroundingText: - { - int paraStart = sci->pdoc->ParaUp(pos); - int paraEnd = sci->pdoc->ParaDown(pos); - QVarLengthArray buffer(paraEnd - paraStart + 1); - - Sci_CharacterRange charRange; - charRange.cpMin = paraStart; - charRange.cpMax = paraEnd; - - Sci_TextRange textRange; - textRange.chrg = charRange; - textRange.lpstrText = buffer.data(); - - SendScintilla(SCI_GETTEXTRANGE, 0, (sptr_t)&textRange); - - return bytesAsText(buffer.constData()); - } - - case Qt::ImCurrentSelection: - { - QVarLengthArray buffer(SendScintilla(SCI_GETSELTEXT)); - SendScintilla(SCI_GETSELTEXT, 0, (sptr_t)buffer.data()); - - return bytesAsText(buffer.constData()); - } - - default: - return QVariant(); - } -} diff --git a/libs/qscintilla/Qt4Qt5/Qsci/qsciglobal.h b/libs/qscintilla/Qt4Qt5/Qsci/qsciglobal.h deleted file mode 100644 index 84cc8d3aa..000000000 --- a/libs/qscintilla/Qt4Qt5/Qsci/qsciglobal.h +++ /dev/null @@ -1,62 +0,0 @@ -// This module defines various things common to all of the Scintilla Qt port. -// -// Copyright (c) 2015 Riverbank Computing Limited -// -// This file is part of QScintilla. -// -// This file may be used under the terms of the GNU General Public License -// version 3.0 as published by the Free Software Foundation and appearing in -// the file LICENSE included in the packaging of this file. Please review the -// following information to ensure the GNU General Public License version 3.0 -// requirements will be met: http://www.gnu.org/copyleft/gpl.html. -// -// If you do not wish to use this file under the terms of the GPL version 3.0 -// then you may purchase a commercial license. For more information contact -// info@riverbankcomputing.com. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - - -#ifndef QSCIGLOBAL_H -#define QSCIGLOBAL_H - -#ifdef __APPLE__ -extern "C++" { -#endif - -#include - - -#define QSCINTILLA_VERSION 0x020900 -#define QSCINTILLA_VERSION_STR "2.9" - - -// Under Windows, define QSCINTILLA_MAKE_DLL to create a Scintilla DLL, or -// define QSCINTILLA_DLL to link against a Scintilla DLL, or define neither -// to either build or link against a static Scintilla library. -#if defined(Q_OS_WIN) - -#if defined(QSCINTILLA_DLL) -#define QSCINTILLA_EXPORT __declspec(dllimport) -#elif defined(QSCINTILLA_MAKE_DLL) -#define QSCINTILLA_EXPORT __declspec(dllexport) -#endif - -#endif - -#if !defined(QSCINTILLA_EXPORT) -#define QSCINTILLA_EXPORT -#endif - - -#if !defined(QT_BEGIN_NAMESPACE) -#define QT_BEGIN_NAMESPACE -#define QT_END_NAMESPACE -#endif - -#ifdef __APPLE__ -} -#endif - -#endif diff --git a/libs/qscintilla/Qt4Qt5/SciNamespace.h b/libs/qscintilla/Qt4Qt5/SciNamespace.h deleted file mode 100644 index 5c4e3a11c..000000000 --- a/libs/qscintilla/Qt4Qt5/SciNamespace.h +++ /dev/null @@ -1,35 +0,0 @@ -// Support for building the Scintilla code in the Scintilla namespace using the -// -DSCI_NAMESPACE compiler flag. -// -// Copyright (c) 2015 Riverbank Computing Limited -// -// This file is part of QScintilla. -// -// This file may be used under the terms of the GNU General Public License -// version 3.0 as published by the Free Software Foundation and appearing in -// the file LICENSE included in the packaging of this file. Please review the -// following information to ensure the GNU General Public License version 3.0 -// requirements will be met: http://www.gnu.org/copyleft/gpl.html. -// -// If you do not wish to use this file under the terms of the GPL version 3.0 -// then you may purchase a commercial license. For more information contact -// info@riverbankcomputing.com. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - - -#ifndef _SCINAMESPACE_H -#define _SCINAMESPACE_H - -#ifdef SCI_NAMESPACE -#define QSCI_SCI_NAMESPACE(name) Scintilla::name -#define QSCI_BEGIN_SCI_NAMESPACE namespace Scintilla { -#define QSCI_END_SCI_NAMESPACE }; -#else -#define QSCI_SCI_NAMESPACE(name) name -#define QSCI_BEGIN_SCI_NAMESPACE -#define QSCI_END_SCI_NAMESPACE -#endif - -#endif diff --git a/libs/qscintilla/Qt4Qt5/features/qscintilla2.prf b/libs/qscintilla/Qt4Qt5/features/qscintilla2.prf deleted file mode 100644 index e91e3beb5..000000000 --- a/libs/qscintilla/Qt4Qt5/features/qscintilla2.prf +++ /dev/null @@ -1,25 +0,0 @@ -greaterThan(QT_MAJOR_VERSION, 4) { - QT += widgets printsupport - - greaterThan(QT_MINOR_VERSION, 1) { - macx:QT += macextras - } -} - -INCLUDEPATH += $$[QT_INSTALL_HEADERS] - -LIBS += -L$$[QT_INSTALL_LIBS] - -CONFIG(debug, debug|release) { - mac: { - LIBS += -lqscintilla2_debug - } else { - win32: { - LIBS += -lqscintilla2d - } else { - LIBS += -lqscintilla2 - } - } -} else { - LIBS += -lqscintilla2 -} diff --git a/libs/qscintilla/Qt4Qt5/qscintilla.pro b/libs/qscintilla/Qt4Qt5/qscintilla.pro deleted file mode 100644 index d6951811a..000000000 --- a/libs/qscintilla/Qt4Qt5/qscintilla.pro +++ /dev/null @@ -1,224 +0,0 @@ -# The project file for the QScintilla library. -# -# Copyright (c) 2014 Riverbank Computing Limited -# -# This file is part of QScintilla. -# -# This file may be used under the terms of the GNU General Public -# License versions 2.0 or 3.0 as published by the Free Software -# Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 -# included in the packaging of this file. Alternatively you may (at -# your option) use any later version of the GNU General Public -# License if such license has been publicly approved by Riverbank -# Computing Limited (or its successors, if any) and the KDE Free Qt -# Foundation. In addition, as a special exception, Riverbank gives you -# certain additional rights. These rights are described in the Riverbank -# GPL Exception version 1.1, which can be found in the file -# GPL_EXCEPTION.txt in this package. -# -# If you are unsure which license is appropriate for your use, please -# contact the sales department at sales@riverbankcomputing.com. -# -# This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -# WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - - -# This must be kept in sync with Python/configure.py, Python/configure-old.py, -# example-Qt4Qt5/application.pro and designer-Qt4Qt5/designer.pro. -!win32:VERSION = 11.3.0 - -TEMPLATE = lib -TARGET = qscintilla2 -CONFIG += qt warn_off thread exceptions staticlib debug_and_release -INCLUDEPATH += . ../include ../lexlib ../src - -DEFINES += QSCINTILLA_MAKE_DLL SCINTILLA_QT SCI_LEXER -greaterThan(QT_MAJOR_VERSION, 3) { - CONFIG(staticlib) { - DEFINES -= QSCINTILLA_MAKE_DLL - } -} - -greaterThan(QT_MAJOR_VERSION, 4) { - # Qt5 requires widgets and printsupport defined - QT += widgets printsupport - - greaterThan(QT_MINOR_VERSION, 1) { - # Qt5 5.2 and above on OSX require macextras - macx:QT += macextras - } - - # Work around QTBUG-39300. - CONFIG -= android_install -} - -# Comment this in if you want the internal Scintilla classes to be placed in a -# Scintilla namespace rather than pollute the global namespace. -#DEFINES += SCI_NAMESPACE - -# Handle both Qt v4 and v3. -target.path = $$[QT_INSTALL_LIBS] -isEmpty(target.path) { - target.path = $(QTDIR)/lib -} - -header.path = $$[QT_INSTALL_HEADERS] -header.files = Qsci -isEmpty(header.path) { - header.path = $(QTDIR)/include/Qsci - header.files = Qsci/qsci*.h -} - -trans.path = $$[QT_INSTALL_TRANSLATIONS] -trans.files = qscintilla_*.qm -isEmpty(trans.path) { - trans.path = $(QTDIR)/translations -} - -qsci.path = $$[QT_INSTALL_DATA] -qsci.files = ../qsci -isEmpty(qsci.path) { - qsci.path = $(QTDIR) -} - -INSTALLS += header trans qsci target - -greaterThan(QT_MAJOR_VERSION, 3) { - features.path = $$[QT_INSTALL_DATA]/mkspecs/features - features.files = $$PWD/features/qscintilla2.prf - INSTALLS += features -} - -HEADERS = \ - ./Qsci/qsciglobal.h \ - ./Qsci/qsciscintilla.h \ - ./Qsci/qsciscintillabase.h \ - ./Qsci/qsciabstractapis.h \ - ./Qsci/qsciapis.h \ - ./Qsci/qscicommand.h \ - ./Qsci/qscicommandset.h \ - ./Qsci/qscidocument.h \ - ./Qsci/qscilexer.h \ - ./Qsci/qscilexersql.h \ - ./Qsci/qscimacro.h \ - ./Qsci/qsciprinter.h \ - ./Qsci/qscistyle.h \ - ./Qsci/qscistyledtext.h \ - ListBoxQt.h \ - SciClasses.h \ - SciNamespace.h \ - ScintillaQt.h \ - ../include/ILexer.h \ - ../include/Platform.h \ - ../include/SciLexer.h \ - ../include/Scintilla.h \ - ../include/ScintillaWidget.h \ - ../lexlib/Accessor.h \ - ../lexlib/CharacterCategory.h \ - ../lexlib/CharacterSet.h \ - ../lexlib/LexAccessor.h \ - ../lexlib/LexerBase.h \ - ../lexlib/LexerModule.h \ - ../lexlib/LexerNoExceptions.h \ - ../lexlib/LexerSimple.h \ - ../lexlib/OptionSet.h \ - ../lexlib/PropSetSimple.h \ - ../lexlib/StyleContext.h \ - ../lexlib/SubStyles.h \ - ../lexlib/WordList.h \ - ../src/AutoComplete.h \ - ../src/CallTip.h \ - ../src/CaseConvert.h \ - ../src/CaseFolder.h \ - ../src/Catalogue.h \ - ../src/CellBuffer.h \ - ../src/CharClassify.h \ - ../src/ContractionState.h \ - ../src/Decoration.h \ - ../src/Document.h \ - ../src/Editor.h \ - ../src/ExternalLexer.h \ - ../src/FontQuality.h \ - ../src/Indicator.h \ - ../src/KeyMap.h \ - ../src/LineMarker.h \ - ../src/Partitioning.h \ - ../src/PerLine.h \ - ../src/PositionCache.h \ - ../src/RESearch.h \ - ../src/RunStyles.h \ - ../src/ScintillaBase.h \ - ../src/Selection.h \ - ../src/SplitVector.h \ - ../src/Style.h \ - ../src/UnicodeFromUTF8.h \ - ../src/UniConversion.h \ - ../src/ViewStyle.h \ - ../src/XPM.h - -SOURCES = \ - qsciscintilla.cpp \ - qsciscintillabase.cpp \ - qsciabstractapis.cpp \ - qsciapis.cpp \ - qscicommand.cpp \ - qscicommandset.cpp \ - qscidocument.cpp \ - qscilexer.cpp \ - qscilexersql.cpp \ - qscimacro.cpp \ - qsciprinter.cpp \ - qscistyle.cpp \ - qscistyledtext.cpp \ - MacPasteboardMime.cpp \ - InputMethod.cpp \ - SciClasses.cpp \ - ListBoxQt.cpp \ - PlatQt.cpp \ - ScintillaQt.cpp \ - ../lexers/LexSQL.cpp \ - ../lexlib/Accessor.cpp \ - ../lexlib/CharacterCategory.cpp \ - ../lexlib/CharacterSet.cpp \ - ../lexlib/LexerBase.cpp \ - ../lexlib/LexerModule.cpp \ - ../lexlib/LexerNoExceptions.cpp \ - ../lexlib/LexerSimple.cpp \ - ../lexlib/PropSetSimple.cpp \ - ../lexlib/StyleContext.cpp \ - ../lexlib/WordList.cpp \ - ../src/AutoComplete.cpp \ - ../src/CallTip.cpp \ - ../src/CaseConvert.cpp \ - ../src/CaseFolder.cpp \ - ../src/Catalogue.cpp \ - ../src/CellBuffer.cpp \ - ../src/CharClassify.cpp \ - ../src/ContractionState.cpp \ - ../src/Decoration.cpp \ - ../src/Document.cpp \ - ../src/Editor.cpp \ - ../src/EditModel.cpp \ - ../src/EditView.cpp \ - ../src/ExternalLexer.cpp \ - ../src/Indicator.cpp \ - ../src/KeyMap.cpp \ - ../src/LineMarker.cpp \ - ../src/MarginView.cpp \ - ../src/PerLine.cpp \ - ../src/PositionCache.cpp \ - ../src/RESearch.cpp \ - ../src/RunStyles.cpp \ - ../src/ScintillaBase.cpp \ - ../src/Selection.cpp \ - ../src/Style.cpp \ - ../src/UniConversion.cpp \ - ../src/ViewStyle.cpp \ - ../src/XPM.cpp - -TRANSLATIONS = \ - qscintilla_cs.ts \ - qscintilla_de.ts \ - qscintilla_es.ts \ - qscintilla_fr.ts \ - qscintilla_pt_br.ts diff --git a/libs/qscintilla/Qt4Qt5/qscintilla_cs.qm b/libs/qscintilla/Qt4Qt5/qscintilla_cs.qm deleted file mode 100644 index 4a6ed6502..000000000 Binary files a/libs/qscintilla/Qt4Qt5/qscintilla_cs.qm and /dev/null differ diff --git a/libs/qscintilla/Qt4Qt5/qscintilla_de.qm b/libs/qscintilla/Qt4Qt5/qscintilla_de.qm deleted file mode 100644 index 78cfcf1bf..000000000 Binary files a/libs/qscintilla/Qt4Qt5/qscintilla_de.qm and /dev/null differ diff --git a/libs/qscintilla/Qt4Qt5/qscintilla_es.qm b/libs/qscintilla/Qt4Qt5/qscintilla_es.qm deleted file mode 100644 index cfa20f6e8..000000000 Binary files a/libs/qscintilla/Qt4Qt5/qscintilla_es.qm and /dev/null differ diff --git a/libs/qscintilla/Qt4Qt5/qscintilla_fr.qm b/libs/qscintilla/Qt4Qt5/qscintilla_fr.qm deleted file mode 100644 index 6f4d10493..000000000 Binary files a/libs/qscintilla/Qt4Qt5/qscintilla_fr.qm and /dev/null differ diff --git a/libs/qscintilla/Qt4Qt5/qscintilla_fr.ts b/libs/qscintilla/Qt4Qt5/qscintilla_fr.ts deleted file mode 100644 index 9b5fbb0ee..000000000 --- a/libs/qscintilla/Qt4Qt5/qscintilla_fr.ts +++ /dev/null @@ -1,3702 +0,0 @@ - - - - - QsciCommand - - - Move down one line - Déplacement d'une ligne vers le bas - - - - Extend selection down one line - Extension de la sélection d'une ligne vers le bas - - - - Scroll view down one line - Decendre la vue d'une ligne - - - - Extend rectangular selection down one line - Extension de la sélection rectangulaire d'une ligne vers le bas - - - - Move up one line - Déplacement d'une ligne vers le haut - - - - Extend selection up one line - Extension de la sélection d'une ligne vers le haut - - - - Scroll view up one line - Remonter la vue d'une ligne - - - - Extend rectangular selection up one line - Extension de la sélection rectangulaire d'une ligne vers le haut - - - - Move up one paragraph - Déplacement d'un paragraphe vers le haut - - - - Extend selection up one paragraph - Extension de la sélection d'un paragraphe vers le haut - - - - Move down one paragraph - Déplacement d'un paragraphe vers le bas - - - - Scroll to start of document - - - - - Scroll to end of document - - - - - Scroll vertically to centre current line - - - - - Extend selection down one paragraph - Extension de la sélection d'un paragraphe vers le bas - - - - Move left one character - Déplacement d'un caractère vers la gauche - - - - Extend selection left one character - Extension de la sélection d'un caractère vers la gauche - - - - Move left one word - Déplacement d'un mot vers la gauche - - - - Extend selection left one word - Extension de la sélection d'un mot vers la gauche - - - - Extend rectangular selection left one character - Extension de la sélection rectangulaire d'un caractère vers la gauche - - - - Move right one character - Déplacement d'un caractère vers la droite - - - - Extend selection right one character - Extension de la sélection d'un caractère vers la droite - - - - Move right one word - Déplacement d'un mot vers la droite - - - - Extend selection right one word - Extension de la sélection d'un mot vers la droite - - - - Extend rectangular selection right one character - Extension de la sélection rectangulaire d'un caractère vers la droite - - - - Move to end of previous word - - - - - Extend selection to end of previous word - - - - - Move to end of next word - - - - - Extend selection to end of next word - - - - - Move left one word part - Déplacement d'une part de mot vers la gauche - - - - Extend selection left one word part - Extension de la sélection d'une part de mot vers la gauche - - - - Move right one word part - Déplacement d'une part de mot vers la droite - - - - Extend selection right one word part - Extension de la sélection d'une part de mot vers la droite - - - - Move up one page - Déplacement d'une page vers le haut - - - - Extend selection up one page - Extension de la sélection d'une page vers le haut - - - - Extend rectangular selection up one page - Extension de la sélection rectangulaire d'une page vers le haut - - - - Move down one page - Déplacement d'une page vers le bas - - - - Extend selection down one page - Extension de la sélection d'une page vers le bas - - - - Extend rectangular selection down one page - Extension de la sélection rectangulaire d'une page vers le bas - - - - Delete current character - Effacement du caractère courant - - - - Cut selection - Couper la sélection - - - - Delete word to right - Suppression du mot de droite - - - - Move to start of document line - - - - - Extend selection to start of document line - - - - - Extend rectangular selection to start of document line - - - - - Move to start of display line - - - - - Extend selection to start of display line - - - - - Move to start of display or document line - - - - - Extend selection to start of display or document line - - - - - Move to first visible character in document line - - - - - Extend selection to first visible character in document line - - - - - Extend rectangular selection to first visible character in document line - - - - - Move to first visible character of display in document line - - - - - Extend selection to first visible character in display or document line - - - - - Move to end of document line - - - - - Extend selection to end of document line - - - - - Extend rectangular selection to end of document line - - - - - Move to end of display line - - - - - Extend selection to end of display line - - - - - Move to end of display or document line - - - - - Extend selection to end of display or document line - - - - - Move to start of document - - - - - Extend selection to start of document - - - - - Move to end of document - - - - - Extend selection to end of document - - - - - Stuttered move up one page - - - - - Stuttered extend selection up one page - - - - - Stuttered move down one page - - - - - Stuttered extend selection down one page - - - - - Delete previous character if not at start of line - - - - - Delete right to end of next word - - - - - Delete line to right - Suppression de la partie droite de la ligne - - - - Transpose current and previous lines - - - - - Duplicate the current line - - - - - Select all - Select document - - - - - Move selected lines up one line - - - - - Move selected lines down one line - - - - - Toggle insert/overtype - Basculement Insertion /Ecrasement - - - - Paste - Coller - - - - Copy selection - Copier la sélection - - - - Insert newline - - - - - De-indent one level - - - - - Cancel - Annuler - - - - Delete previous character - Suppression du dernier caractère - - - - Delete word to left - Suppression du mot de gauche - - - - Delete line to left - Effacer la partie gauche de la ligne - - - - Undo last command - - - - - Redo last command - Refaire la dernière commande - - - - Indent one level - Indentation d'un niveau - - - - Zoom in - Zoom avant - - - - Zoom out - Zoom arrière - - - - Formfeed - Chargement de la page - - - - Cut current line - Couper la ligne courante - - - - Delete current line - Suppression de la ligne courante - - - - Copy current line - Copier la ligne courante - - - - Convert selection to lower case - Conversion de la ligne courante en minuscules - - - - Convert selection to upper case - Conversion de la ligne courante en majuscules - - - - Duplicate selection - - - - - QsciLexerAVS - - - Default - Par défaut - - - - Block comment - - - - - Nested block comment - - - - - Line comment - Commentaire de ligne - - - - Number - Nombre - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - Double-quoted string - Chaine de caractères (guillemets doubles) - - - - Triple double-quoted string - Chaine de caractères HTML (guillemets simples) - - - - Keyword - Mot-clé - - - - Filter - - - - - Plugin - - - - - Function - - - - - Clip property - - - - - User defined - - - - - QsciLexerBash - - - Default - Par défaut - - - - Error - Erreur - - - - Comment - Commentaire - - - - Number - Nombre - - - - Keyword - Mot-clé - - - - Double-quoted string - Chaine de caractères (guillemets doubles) - - - - Single-quoted string - Chaine de caractères (guillemets simples) - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - Scalar - Scalaire - - - - Parameter expansion - Extension de paramètre - - - - Backticks - Quotes inverses - - - - Here document delimiter - Délimiteur de texte intégré (cat <<EOF....EOF) - - - - Single-quoted here document - Document intégré guillemets simples - - - - QsciLexerBatch - - - Default - Par défaut - - - - Comment - Commentaire - - - - Keyword - Mot-clé - - - - Label - Titre - - - - Hide command character - Cacher le caratère de commande - - - - External command - Commande externe - - - - Variable - Variable - - - - Operator - Opérateur - - - - QsciLexerCMake - - - Default - Par défaut - - - - Comment - Commentaire - - - - String - Chaîne de caractères - - - - Left quoted string - - - - - Right quoted string - - - - - Function - - - - - Variable - Variable - - - - Label - Titre - - - - User defined - - - - - WHILE block - - - - - FOREACH block - - - - - IF block - - - - - MACRO block - - - - - Variable within a string - - - - - Number - Nombre - - - - QsciLexerCPP - - - Default - Par défaut - - - - Inactive default - - - - - C comment - Commentaire C - - - - Inactive C comment - - - - - C++ comment - Commentaire C++ - - - - Inactive C++ comment - - - - - JavaDoc style C comment - Commentaire C de style JavaDoc - - - - Inactive JavaDoc style C comment - - - - - Number - Nombre - - - - Inactive number - - - - - Keyword - Mot-clé - - - - Inactive keyword - - - - - Double-quoted string - Chaine de caractères (guillemets doubles) - - - - Inactive double-quoted string - - - - - Single-quoted string - Chaine de caractères (guillemets simples) - - - - Inactive single-quoted string - - - - - IDL UUID - - - - - Inactive IDL UUID - - - - - Pre-processor block - Instructions de pré-processing - - - - Inactive pre-processor block - - - - - Operator - Opérateur - - - - Inactive operator - - - - - Identifier - Identificateur - - - - Inactive identifier - - - - - Unclosed string - Chaine de caractères non refermée - - - - Inactive unclosed string - - - - - C# verbatim string - - - - - Inactive C# verbatim string - - - - - JavaScript regular expression - Expression régulière JavaScript - - - - Inactive JavaScript regular expression - - - - - JavaDoc style C++ comment - Commentaire C++ de style JavaDoc - - - - Inactive JavaDoc style C++ comment - - - - - Secondary keywords and identifiers - Seconds mots-clés et identificateurs - - - - Inactive secondary keywords and identifiers - - - - - JavaDoc keyword - Mot-clé JavaDoc - - - - Inactive JavaDoc keyword - - - - - JavaDoc keyword error - Erreur de mot-clé JavaDoc - - - - Inactive JavaDoc keyword error - - - - - Global classes and typedefs - Classes globales et définitions de types - - - - Inactive global classes and typedefs - - - - - C++ raw string - - - - - Inactive C++ raw string - - - - - Vala triple-quoted verbatim string - - - - - Inactive Vala triple-quoted verbatim string - - - - - Pike hash-quoted string - - - - - Inactive Pike hash-quoted string - - - - - Pre-processor C comment - - - - - Inactive pre-processor C comment - - - - - JavaDoc style pre-processor comment - - - - - Inactive JavaDoc style pre-processor comment - - - - - User-defined literal - - - - - Inactive user-defined literal - - - - - Task marker - - - - - Inactive task marker - - - - - Escape sequence - - - - - Inactive escape sequence - - - - - QsciLexerCSS - - - Default - Par défaut - - - - Tag - Balise - - - - Class selector - Classe - - - - Pseudo-class - Pseudo-classe - - - - Unknown pseudo-class - Peudo-classe inconnue - - - - Operator - Opérateur - - - - CSS1 property - Propriété CSS1 - - - - Unknown property - Propriété inconnue - - - - Value - Valeur - - - - ID selector - ID - - - - Important - Important - - - - @-rule - règle-@ - - - - Double-quoted string - Chaine de caractères (guillemets doubles) - - - - Single-quoted string - Chaine de caractères (guillemets simples) - - - - CSS2 property - Propriété CSS2 - - - - Attribute - Attribut - - - - CSS3 property - Propriété CSS2 {3 ?} - - - - Pseudo-element - - - - - Extended CSS property - - - - - Extended pseudo-class - - - - - Extended pseudo-element - - - - - Media rule - - - - - Variable - Variable - - - - QsciLexerCSharp - - - Verbatim string - Chaine verbatim - - - - QsciLexerCoffeeScript - - - Default - Par défaut - - - - C-style comment - - - - - C++-style comment - - - - - JavaDoc C-style comment - - - - - Number - Nombre - - - - Keyword - Mot-clé - - - - Double-quoted string - Chaine de caractères (guillemets doubles) - - - - Single-quoted string - Chaine de caractères (guillemets simples) - - - - IDL UUID - - - - - Pre-processor block - Instructions de pré-processing - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - Unclosed string - Chaine de caractères non refermée - - - - C# verbatim string - - - - - Regular expression - Expression régulière - - - - JavaDoc C++-style comment - - - - - Secondary keywords and identifiers - Seconds mots-clés et identificateurs - - - - JavaDoc keyword - Mot-clé JavaDoc - - - - JavaDoc keyword error - Erreur de mot-clé JavaDoc - - - - Global classes - - - - - Block comment - - - - - Block regular expression - - - - - Block regular expression comment - - - - - QsciLexerD - - - Default - Par défaut - - - - Block comment - - - - - Line comment - Commentaire de ligne - - - - DDoc style block comment - - - - - Nesting comment - - - - - Number - Nombre - - - - Keyword - Mot-clé - - - - Secondary keyword - - - - - Documentation keyword - - - - - Type definition - - - - - String - Chaîne de caractères - - - - Unclosed string - Chaine de caractères non refermée - - - - Character - Caractère - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - DDoc style line comment - - - - - DDoc keyword - Mot-clé JavaDoc - - - - DDoc keyword error - Erreur de mot-clé JavaDoc - - - - Backquoted string - - - - - Raw string - - - - - User defined 1 - Définition utilisateur 1 - - - - User defined 2 - Définition utilisateur 2 - - - - User defined 3 - Définition utilisateur 3 - - - - QsciLexerDiff - - - Default - Par défaut - - - - Comment - Commentaire - - - - Command - Commande - - - - Header - En-tête - - - - Position - Position - - - - Removed line - Ligne supprimée - - - - Added line - Ligne ajoutée - - - - Changed line - - - - - QsciLexerFortran77 - - - Default - Par défaut - - - - Comment - Commentaire - - - - Number - Nombre - - - - Single-quoted string - Chaine de caractères (guillemets simples) - - - - Double-quoted string - Chaine de caractères (guillemets doubles) - - - - Unclosed string - Chaine de caractères non refermée - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - Keyword - Mot-clé - - - - Intrinsic function - - - - - Extended function - - - - - Pre-processor block - Instructions de pré-processing - - - - Dotted operator - - - - - Label - Titre - - - - Continuation - - - - - QsciLexerHTML - - - HTML default - HTML par défaut - - - - Tag - Balise - - - - Unknown tag - Balise inconnue - - - - Attribute - Attribut - - - - Unknown attribute - Attribut inconnu - - - - HTML number - Nombre HTML - - - - HTML double-quoted string - Chaine de caractères HTML (guillemets doubles) - - - - HTML single-quoted string - Chaine de caractères HTML (guillemets simples) - - - - Other text in a tag - Autre texte dans les balises - - - - HTML comment - Commentaire HTML - - - - Entity - Entité - - - - End of a tag - Balise fermante - - - - Start of an XML fragment - Début de block XML - - - - End of an XML fragment - Fin de block XML - - - - Script tag - Balise de script - - - - Start of an ASP fragment with @ - Début de block ASP avec @ - - - - Start of an ASP fragment - Début de block ASP - - - - CDATA - CDATA - - - - Start of a PHP fragment - Début de block PHP - - - - Unquoted HTML value - Valeur HTML sans guillemets - - - - ASP X-Code comment - Commentaire X-Code ASP - - - - SGML default - SGML par défaut - - - - SGML command - Commande SGML - - - - First parameter of an SGML command - Premier paramètre de commande SGML - - - - SGML double-quoted string - Chaine de caractères SGML (guillemets doubles) - - - - SGML single-quoted string - Chaine de caractères SGML (guillemets simples) - - - - SGML error - Erreur SGML - - - - SGML special entity - Entité SGML spéciale - - - - SGML comment - Commentaire SGML - - - - First parameter comment of an SGML command - Premier paramètre de commentaire de commande SGML - - - - SGML block default - Block SGML par défaut - - - - Start of a JavaScript fragment - Début de block JavaScript - - - - JavaScript default - JavaScript par défaut - - - - JavaScript comment - Commentaire JavaScript - - - - JavaScript line comment - Commentaire de ligne JavaScript - - - - JavaDoc style JavaScript comment - Commentaire JavaScript de style JavaDoc - - - - JavaScript number - Nombre JavaScript - - - - JavaScript word - Mot JavaScript - - - - JavaScript keyword - Mot-clé JavaScript - - - - JavaScript double-quoted string - Chaine de caractères JavaScript (guillemets doubles) - - - - JavaScript single-quoted string - Chaine de caractères JavaScript (guillemets simples) - - - - JavaScript symbol - Symbole JavaScript - - - - JavaScript unclosed string - Chaine de caractères JavaScript non refermée - - - - JavaScript regular expression - Expression régulière JavaScript - - - - Start of an ASP JavaScript fragment - Début de block JavaScript ASP - - - - ASP JavaScript default - JavaScript ASP par défaut - - - - ASP JavaScript comment - Commentaire JavaScript ASP - - - - ASP JavaScript line comment - Commentaire de ligne JavaScript ASP - - - - JavaDoc style ASP JavaScript comment - Commentaire JavaScript ASP de style JavaDoc - - - - ASP JavaScript number - Nombre JavaScript ASP - - - - ASP JavaScript word - Mot JavaScript ASP - - - - ASP JavaScript keyword - Mot-clé JavaScript ASP - - - - ASP JavaScript double-quoted string - Chaine de caractères JavaScript ASP (guillemets doubles) - - - - ASP JavaScript single-quoted string - Chaine de caractères JavaScript ASP (guillemets simples) - - - - ASP JavaScript symbol - Symbole JavaScript ASP - - - - ASP JavaScript unclosed string - Chaine de caractères JavaScript ASP non refermée - - - - ASP JavaScript regular expression - Expression régulière JavaScript ASP - - - - Start of a VBScript fragment - Début de block VBScript - - - - VBScript default - VBScript par défaut - - - - VBScript comment - Commentaire VBScript - - - - VBScript number - Nombre VBScript - - - - VBScript keyword - Mot-clé VBScript - - - - VBScript string - Chaine de caractères VBScript - - - - VBScript identifier - Identificateur VBScript - - - - VBScript unclosed string - Chaine de caractères VBScript non refermée - - - - Start of an ASP VBScript fragment - Début de block VBScript ASP - - - - ASP VBScript default - VBScript ASP par défaut - - - - ASP VBScript comment - Commentaire VBScript ASP - - - - ASP VBScript number - Nombre VBScript ASP - - - - ASP VBScript keyword - Mot-clé VBScript ASP - - - - ASP VBScript string - Chaine de caractères VBScript ASP - - - - ASP VBScript identifier - Identificateur VBScript ASP - - - - ASP VBScript unclosed string - Chaine de caractères VBScript ASP non refermée - - - - Start of a Python fragment - Début de block Python - - - - Python default - Python par défaut - - - - Python comment - Commentaire Python - - - - Python number - Nombre Python - - - - Python double-quoted string - Chaine de caractères Python (guillemets doubles) - - - - Python single-quoted string - Chaine de caractères Python (guillemets simples) - - - - Python keyword - Mot-clé Python - - - - Python triple double-quoted string - Chaine de caractères Python (triples guillemets doubles) - - - - Python triple single-quoted string - Chaine de caractères Python (triples guillemets simples) - - - - Python class name - Nom de classe Python - - - - Python function or method name - Méthode ou fonction Python - - - - Python operator - Opérateur Python - - - - Python identifier - Identificateur Python - - - - Start of an ASP Python fragment - Début de block Python ASP - - - - ASP Python default - Python ASP par défaut - - - - ASP Python comment - Commentaire Python ASP - - - - ASP Python number - Nombre Python ASP - - - - ASP Python double-quoted string - Chaine de caractères Python ASP (guillemets doubles) - - - - ASP Python single-quoted string - Chaine de caractères Python ASP (guillemets simples) - - - - ASP Python keyword - Mot-clé Python ASP - - - - ASP Python triple double-quoted string - Chaine de caractères Python ASP (triples guillemets doubles) - - - - ASP Python triple single-quoted string - Chaine de caractères Python ASP (triples guillemets simples) - - - - ASP Python class name - Nom de classe Python ASP - - - - ASP Python function or method name - Méthode ou fonction Python ASP - - - - ASP Python operator - Opérateur Python ASP - - - - ASP Python identifier - Identificateur Python ASP - - - - PHP default - PHP par défaut - - - - PHP double-quoted string - Chaine de caractères PHP (guillemets doubles) - - - - PHP single-quoted string - Chaine de caractères PHP (guillemets simples) - - - - PHP keyword - Mot-clé PHP - - - - PHP number - Nombre PHP - - - - PHP variable - Variable PHP - - - - PHP comment - Commentaire PHP - - - - PHP line comment - Commentaire de ligne PHP - - - - PHP double-quoted variable - Variable PHP (guillemets doubles) - - - - PHP operator - Opérateur PHP - - - - QsciLexerIDL - - - UUID - UUID - - - - QsciLexerJavaScript - - - Regular expression - Expression régulière - - - - QsciLexerLua - - - Default - Par défaut - - - - Comment - Commentaire - - - - Line comment - Commentaire de ligne - - - - Number - Nombre - - - - Keyword - Mot-clé - - - - String - Chaîne de caractères - - - - Character - Caractère - - - - Literal string - Chaîne littérale - - - - Preprocessor - Préprocessing - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - Unclosed string - Chaine de caractères non refermée - - - - Basic functions - Fonctions de base - - - - String, table and maths functions - Fonctions sur les chaines, tables et fonctions math - - - - Coroutines, i/o and system facilities - Coroutines, i/o et fonctions système - - - - User defined 1 - Définition utilisateur 1 - - - - User defined 2 - Définition utilisateur 2 - - - - User defined 3 - Définition utilisateur 3 - - - - User defined 4 - Définition utilisateur 4 - - - - Label - Titre - - - - QsciLexerMakefile - - - Default - Par défaut - - - - Comment - Commentaire - - - - Preprocessor - Préprocessing - - - - Variable - Variable - - - - Operator - Opérateur - - - - Target - Cible - - - - Error - Erreur - - - - QsciLexerMatlab - - - Default - Par défaut - - - - Comment - Commentaire - - - - Command - Commande - - - - Number - Nombre - - - - Keyword - Mot-clé - - - - Single-quoted string - Chaine de caractères (guillemets simples) - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - Double-quoted string - Chaine de caractères (guillemets doubles) - - - - QsciLexerPO - - - Default - Par défaut - - - - Comment - Commentaire - - - - Message identifier - - - - - Message identifier text - - - - - Message string - - - - - Message string text - - - - - Message context - - - - - Message context text - - - - - Fuzzy flag - - - - - Programmer comment - - - - - Reference - - - - - Flags - - - - - Message identifier text end-of-line - - - - - Message string text end-of-line - - - - - Message context text end-of-line - - - - - QsciLexerPOV - - - Default - Par défaut - - - - Comment - Commentaire - - - - Comment line - Ligne commentée - - - - Number - Nombre - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - String - Chaîne de caractères - - - - Unclosed string - Chaine de caractères non refermée - - - - Directive - Directive - - - - Bad directive - Mauvaise directive - - - - Objects, CSG and appearance - Objets, CSG et apparence - - - - Types, modifiers and items - Types, modifieurs et éléments - - - - Predefined identifiers - Identifiants prédéfinis - - - - Predefined functions - Fonctions prédéfinies - - - - User defined 1 - Définition utilisateur 1 - - - - User defined 2 - Définition utilisateur 2 - - - - User defined 3 - Définition utilisateur 3 - - - - QsciLexerPascal - - - Default - Par défaut - - - - Line comment - Commentaire de ligne - - - - Number - Nombre - - - - Keyword - Mot-clé - - - - Single-quoted string - Chaine de caractères (guillemets simples) - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - '{ ... }' style comment - - - - - '(* ... *)' style comment - - - - - '{$ ... }' style pre-processor block - - - - - '(*$ ... *)' style pre-processor block - - - - - Hexadecimal number - - - - - Unclosed string - Chaine de caractères non refermée - - - - Character - Caractère - - - - Inline asm - - - - - QsciLexerPerl - - - Default - Par défaut - - - - Error - Erreur - - - - Comment - Commentaire - - - - POD - POD - - - - Number - Nombre - - - - Keyword - Mot-clé - - - - Double-quoted string - Chaine de caractères (guillemets doubles) - - - - Single-quoted string - Chaine de caractères (guillemets simples) - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - Scalar - Scalaire - - - - Array - Tableau - - - - Hash - Hashage - - - - Symbol table - Table de symboles - - - - Regular expression - Expression régulière - - - - Substitution - Substitution - - - - Backticks - Quotes inverses - - - - Data section - Section de données - - - - Here document delimiter - Délimiteur de texte intégré (cat <<EOF....EOF) - - - - Single-quoted here document - Document intégré guillemets simples - - - - Double-quoted here document - Document intégré guillemets doubles - - - - Backtick here document - Document intégré quotes inverses - - - - Quoted string (q) - Chaine quotée (q) - - - - Quoted string (qq) - Chaine quotée (qq) - - - - Quoted string (qx) - Chaine quotée (qx) - - - - Quoted string (qr) - Chaine quotée (qr) - - - - Quoted string (qw) - Chaine quotée (qw) - - - - POD verbatim - POD verbatim - - - - Subroutine prototype - - - - - Format identifier - - - - - Format body - - - - - Double-quoted string (interpolated variable) - - - - - Translation - - - - - Regular expression (interpolated variable) - - - - - Substitution (interpolated variable) - - - - - Backticks (interpolated variable) - - - - - Double-quoted here document (interpolated variable) - - - - - Backtick here document (interpolated variable) - - - - - Quoted string (qq, interpolated variable) - - - - - Quoted string (qx, interpolated variable) - - - - - Quoted string (qr, interpolated variable) - - - - - QsciLexerPostScript - - - Default - Par défaut - - - - Comment - Commentaire - - - - DSC comment - - - - - DSC comment value - - - - - Number - Nombre - - - - Name - - - - - Keyword - Mot-clé - - - - Literal - - - - - Immediately evaluated literal - - - - - Array parenthesis - - - - - Dictionary parenthesis - - - - - Procedure parenthesis - - - - - Text - Texte - - - - Hexadecimal string - - - - - Base85 string - - - - - Bad string character - - - - - QsciLexerProperties - - - Default - Par défaut - - - - Comment - Commentaire - - - - Section - Section - - - - Assignment - Affectation - - - - Default value - Valeur par défaut - - - - Key - - - - - QsciLexerPython - - - Default - Par défaut - - - - Comment - Commentaire - - - - Number - Nombre - - - - Double-quoted string - Chaine de caractères (guillemets doubles) - - - - Single-quoted string - Chaine de caractères (guillemets simples) - - - - Keyword - Mot-clé - - - - Triple single-quoted string - Chaine de caractères HTML (guillemets simples) - - - - Triple double-quoted string - Chaine de caractères HTML (guillemets simples) - - - - Class name - Nom de classe - - - - Function or method name - Nom de méthode ou de fonction - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - Comment block - Block de commentaires - - - - Unclosed string - Chaine de caractères non refermée - - - - Highlighted identifier - - - - - Decorator - - - - - QsciLexerRuby - - - Default - Par défaut - - - - Comment - Commentaire - - - - Number - Nombre - - - - Double-quoted string - Chaine de caractères (guillemets doubles) - - - - Single-quoted string - Chaine de caractères (guillemets simples) - - - - Keyword - Mot-clé - - - - Class name - Nom de classe - - - - Function or method name - Nom de méthode ou de fonction - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - Error - Erreur - - - - POD - POD - - - - Regular expression - Expression régulière - - - - Global - - - - - Symbol - Symbole - - - - Module name - - - - - Instance variable - - - - - Class variable - - - - - Backticks - Quotes inverses - - - - Data section - Section de données - - - - Here document delimiter - Délimiteur de texte intégré (cat <<EOF....EOF) - - - - Here document - - - - - %q string - - - - - %Q string - - - - - %x string - - - - - %r string - - - - - %w string - - - - - Demoted keyword - - - - - stdin - - - - - stdout - - - - - stderr - - - - - QsciLexerSQL - - - Default - Par défaut - - - - Comment - Commentaire - - - - Number - Nombre - - - - Keyword - Mot-clé - - - - Single-quoted string - Chaine de caractères (guillemets simples) - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - Comment line - Ligne commentée - - - - JavaDoc style comment - Commentaire style JavaDoc - - - - Double-quoted string - Chaine de caractères (guillemets doubles) - - - - SQL*Plus keyword - Mot-clé SQL*Plus - - - - SQL*Plus prompt - Prompt SQL*Plus - - - - SQL*Plus comment - Commentaire SQL*Plus - - - - # comment line - # Ligne commentée - - - - JavaDoc keyword - Mot-clé JavaDoc - - - - JavaDoc keyword error - Erreur de mot-clé JavaDoc - - - - User defined 1 - Définition utilisateur 1 - - - - User defined 2 - Définition utilisateur 2 - - - - User defined 3 - Définition utilisateur 3 - - - - User defined 4 - Définition utilisateur 4 - - - - Quoted identifier - - - - - Quoted operator - - - - - QsciLexerSpice - - - Default - Par défaut - - - - Identifier - Identificateur - - - - Command - Commande - - - - Function - - - - - Parameter - - - - - Number - Nombre - - - - Delimiter - - - - - Value - Valeur - - - - Comment - Commentaire - - - - QsciLexerTCL - - - Default - Par défaut - - - - Comment - Commentaire - - - - Comment line - Ligne commentée - - - - Number - Nombre - - - - Quoted keyword - - - - - Quoted string - - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - Substitution - Substitution - - - - Brace substitution - - - - - Modifier - - - - - Expand keyword - - - - - TCL keyword - - - - - Tk keyword - - - - - iTCL keyword - - - - - Tk command - - - - - User defined 1 - Définition utilisateur 1 - - - - User defined 2 - Définition utilisateur 2 - - - - User defined 3 - Définition utilisateur 3 - - - - User defined 4 - Définition utilisateur 4 - - - - Comment box - - - - - Comment block - Block de commentaires - - - - QsciLexerTeX - - - Default - Par défaut - - - - Special - Spécial - - - - Group - Groupe - - - - Symbol - Symbole - - - - Command - Commande - - - - Text - Texte - - - - QsciLexerVHDL - - - Default - Par défaut - - - - Comment - Commentaire - - - - Comment line - Ligne commentée - - - - Number - Nombre - - - - String - Chaîne de caractères - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - Unclosed string - Chaine de caractères non refermée - - - - Keyword - Mot-clé - - - - Standard operator - - - - - Attribute - Attribut - - - - Standard function - - - - - Standard package - - - - - Standard type - - - - - User defined - - - - - Comment block - Block de commentaires - - - - QsciLexerVerilog - - - Default - Par défaut - - - - Comment - Commentaire - - - - Line comment - Commentaire de ligne - - - - Bang comment - - - - - Number - Nombre - - - - Primary keywords and identifiers - - - - - String - Chaîne de caractères - - - - Secondary keywords and identifiers - Seconds mots-clés et identificateurs - - - - System task - - - - - Preprocessor block - - - - - Operator - Opérateur - - - - Identifier - Identificateur - - - - Unclosed string - Chaine de caractères non refermée - - - - User defined tasks and identifiers - - - - - Keyword comment - - - - - Inactive keyword comment - - - - - Input port declaration - - - - - Inactive input port declaration - - - - - Output port declaration - - - - - Inactive output port declaration - - - - - Input/output port declaration - - - - - Inactive input/output port declaration - - - - - Port connection - - - - - Inactive port connection - - - - - QsciLexerYAML - - - Default - Par défaut - - - - Comment - Commentaire - - - - Identifier - Identificateur - - - - Keyword - Mot-clé - - - - Number - Nombre - - - - Reference - - - - - Document delimiter - - - - - Text block marker - - - - - Syntax error marker - - - - - Operator - Opérateur - - - - QsciScintilla - - - &Undo - - - - - &Redo - - - - - Cu&t - - - - - &Copy - - - - - &Paste - - - - - Delete - - - - - Select All - - - - diff --git a/libs/qscintilla/README b/libs/qscintilla/README deleted file mode 100644 index dc603f98e..000000000 --- a/libs/qscintilla/README +++ /dev/null @@ -1,2 +0,0 @@ -All the documentation for QScintilla for Qt v4 and Qt v5 (including -installation instructions) can be found in doc/html-Qt4Qt5/index.html. diff --git a/libs/qscintilla/include/ILexer.h b/libs/qscintilla/include/ILexer.h deleted file mode 100644 index b90092750..000000000 --- a/libs/qscintilla/include/ILexer.h +++ /dev/null @@ -1,98 +0,0 @@ -// Scintilla source code edit control -/** @file ILexer.h - ** Interface between Scintilla and lexers. - **/ -// Copyright 1998-2010 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef ILEXER_H -#define ILEXER_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -#ifdef _WIN32 - #define SCI_METHOD __stdcall -#else - #define SCI_METHOD -#endif - -enum { dvOriginal=0, dvLineEnd=1 }; - -class IDocument { -public: - virtual int SCI_METHOD Version() const = 0; - virtual void SCI_METHOD SetErrorStatus(int status) = 0; - virtual int SCI_METHOD Length() const = 0; - virtual void SCI_METHOD GetCharRange(char *buffer, int position, int lengthRetrieve) const = 0; - virtual char SCI_METHOD StyleAt(int position) const = 0; - virtual int SCI_METHOD LineFromPosition(int position) const = 0; - virtual int SCI_METHOD LineStart(int line) const = 0; - virtual int SCI_METHOD GetLevel(int line) const = 0; - virtual int SCI_METHOD SetLevel(int line, int level) = 0; - virtual int SCI_METHOD GetLineState(int line) const = 0; - virtual int SCI_METHOD SetLineState(int line, int state) = 0; - virtual void SCI_METHOD StartStyling(int position, char mask) = 0; - virtual bool SCI_METHOD SetStyleFor(int length, char style) = 0; - virtual bool SCI_METHOD SetStyles(int length, const char *styles) = 0; - virtual void SCI_METHOD DecorationSetCurrentIndicator(int indicator) = 0; - virtual void SCI_METHOD DecorationFillRange(int position, int value, int fillLength) = 0; - virtual void SCI_METHOD ChangeLexerState(int start, int end) = 0; - virtual int SCI_METHOD CodePage() const = 0; - virtual bool SCI_METHOD IsDBCSLeadByte(char ch) const = 0; - virtual const char * SCI_METHOD BufferPointer() = 0; - virtual int SCI_METHOD GetLineIndentation(int line) = 0; -}; - -class IDocumentWithLineEnd : public IDocument { -public: - virtual int SCI_METHOD LineEnd(int line) const = 0; - virtual int SCI_METHOD GetRelativePosition(int positionStart, int characterOffset) const = 0; - virtual int SCI_METHOD GetCharacterAndWidth(int position, int *pWidth) const = 0; -}; - -enum { lvOriginal=0, lvSubStyles=1 }; - -class ILexer { -public: - virtual int SCI_METHOD Version() const = 0; - virtual void SCI_METHOD Release() = 0; - virtual const char * SCI_METHOD PropertyNames() = 0; - virtual int SCI_METHOD PropertyType(const char *name) = 0; - virtual const char * SCI_METHOD DescribeProperty(const char *name) = 0; - virtual int SCI_METHOD PropertySet(const char *key, const char *val) = 0; - virtual const char * SCI_METHOD DescribeWordListSets() = 0; - virtual int SCI_METHOD WordListSet(int n, const char *wl) = 0; - virtual void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0; - virtual void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0; - virtual void * SCI_METHOD PrivateCall(int operation, void *pointer) = 0; -}; - -class ILexerWithSubStyles : public ILexer { -public: - virtual int SCI_METHOD LineEndTypesSupported() = 0; - virtual int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) = 0; - virtual int SCI_METHOD SubStylesStart(int styleBase) = 0; - virtual int SCI_METHOD SubStylesLength(int styleBase) = 0; - virtual int SCI_METHOD StyleFromSubStyle(int subStyle) = 0; - virtual int SCI_METHOD PrimaryStyleFromStyle(int style) = 0; - virtual void SCI_METHOD FreeSubStyles() = 0; - virtual void SCI_METHOD SetIdentifiers(int style, const char *identifiers) = 0; - virtual int SCI_METHOD DistanceToSecondaryStyles() = 0; - virtual const char * SCI_METHOD GetSubStyleBases() = 0; -}; - -class ILoader { -public: - virtual int SCI_METHOD Release() = 0; - // Returns a status code from SC_STATUS_* - virtual int SCI_METHOD AddData(char *data, int length) = 0; - virtual void * SCI_METHOD ConvertToDocument() = 0; -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/include/License.txt b/libs/qscintilla/include/License.txt deleted file mode 100644 index cbe25b2fc..000000000 --- a/libs/qscintilla/include/License.txt +++ /dev/null @@ -1,20 +0,0 @@ -License for Scintilla and SciTE - -Copyright 1998-2003 by Neil Hodgson - -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation. - -NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE -OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/libs/qscintilla/include/Platform.h b/libs/qscintilla/include/Platform.h deleted file mode 100644 index 839d7859f..000000000 --- a/libs/qscintilla/include/Platform.h +++ /dev/null @@ -1,555 +0,0 @@ -// Scintilla source code edit control -/** @file Platform.h - ** Interface to platform facilities. Also includes some basic utilities. - ** Implemented in PlatGTK.cxx for GTK+/Linux, PlatWin.cxx for Windows, and PlatWX.cxx for wxWindows. - **/ -// Copyright 1998-2009 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef PLATFORM_H -#define PLATFORM_H - -// PLAT_GTK = GTK+ on Linux or Win32 -// PLAT_GTK_WIN32 is defined additionally when running PLAT_GTK under Win32 -// PLAT_WIN = Win32 API on Win32 OS -// PLAT_WX is wxWindows on any supported platform -// PLAT_TK = Tcl/TK on Linux or Win32 - -#define PLAT_GTK 0 -#define PLAT_GTK_WIN32 0 -#define PLAT_GTK_MACOSX 0 -#define PLAT_MACOSX 0 -#define PLAT_WIN 0 -#define PLAT_WX 0 -#define PLAT_QT 0 -#define PLAT_FOX 0 -#define PLAT_CURSES 0 -#define PLAT_TK 0 - -#if defined(FOX) -#undef PLAT_FOX -#define PLAT_FOX 1 - -#elif defined(__WX__) -#undef PLAT_WX -#define PLAT_WX 1 - -#elif defined(CURSES) -#undef PLAT_CURSES -#define PLAT_CURSES 1 - -#elif defined(SCINTILLA_QT) -#undef PLAT_QT -#define PLAT_QT 1 - -#include -QT_BEGIN_NAMESPACE -class QPainter; -QT_END_NAMESPACE - -// This is needed to work around an HP-UX bug with Qt4. -#include - -#elif defined(TK) -#undef PLAT_TK -#define PLAT_TK 1 - -#elif defined(GTK) -#undef PLAT_GTK -#define PLAT_GTK 1 - -#if defined(__WIN32__) || defined(_MSC_VER) -#undef PLAT_GTK_WIN32 -#define PLAT_GTK_WIN32 1 -#endif - -#if defined(__APPLE__) -#undef PLAT_GTK_MACOSX -#define PLAT_GTK_MACOSX 1 -#endif - -#elif defined(__APPLE__) - -#undef PLAT_MACOSX -#define PLAT_MACOSX 1 - -#else -#undef PLAT_WIN -#define PLAT_WIN 1 - -#endif - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -typedef float XYPOSITION; -typedef double XYACCUMULATOR; -inline int RoundXYPosition(XYPOSITION xyPos) { - return int(xyPos + 0.5); -} - -// Underlying the implementation of the platform classes are platform specific types. -// Sometimes these need to be passed around by client code so they are defined here - -typedef void *FontID; -typedef void *SurfaceID; -typedef void *WindowID; -typedef void *MenuID; -typedef void *TickerID; -typedef void *Function; -typedef void *IdlerID; - -/** - * A geometric point class. - * Point is similar to the Win32 POINT and GTK+ GdkPoint types. - */ -class Point { -public: - XYPOSITION x; - XYPOSITION y; - - explicit Point(XYPOSITION x_=0, XYPOSITION y_=0) : x(x_), y(y_) { - } - - static Point FromInts(int x_, int y_) { - return Point(static_cast(x_), static_cast(y_)); - } - - // Other automatically defined methods (assignment, copy constructor, destructor) are fine - - static Point FromLong(long lpoint); -}; - -/** - * A geometric rectangle class. - * PRectangle is similar to the Win32 RECT. - * PRectangles contain their top and left sides, but not their right and bottom sides. - */ -class PRectangle { -public: - XYPOSITION left; - XYPOSITION top; - XYPOSITION right; - XYPOSITION bottom; - - explicit PRectangle(XYPOSITION left_=0, XYPOSITION top_=0, XYPOSITION right_=0, XYPOSITION bottom_ = 0) : - left(left_), top(top_), right(right_), bottom(bottom_) { - } - - static PRectangle FromInts(int left_, int top_, int right_, int bottom_) { - return PRectangle(static_cast(left_), static_cast(top_), - static_cast(right_), static_cast(bottom_)); - } - - // Other automatically defined methods (assignment, copy constructor, destructor) are fine - - bool operator==(PRectangle &rc) const { - return (rc.left == left) && (rc.right == right) && - (rc.top == top) && (rc.bottom == bottom); - } - bool Contains(Point pt) const { - return (pt.x >= left) && (pt.x <= right) && - (pt.y >= top) && (pt.y <= bottom); - } - bool ContainsWholePixel(Point pt) const { - // Does the rectangle contain all of the pixel to left/below the point - return (pt.x >= left) && ((pt.x+1) <= right) && - (pt.y >= top) && ((pt.y+1) <= bottom); - } - bool Contains(PRectangle rc) const { - return (rc.left >= left) && (rc.right <= right) && - (rc.top >= top) && (rc.bottom <= bottom); - } - bool Intersects(PRectangle other) const { - return (right > other.left) && (left < other.right) && - (bottom > other.top) && (top < other.bottom); - } - void Move(XYPOSITION xDelta, XYPOSITION yDelta) { - left += xDelta; - top += yDelta; - right += xDelta; - bottom += yDelta; - } - XYPOSITION Width() const { return right - left; } - XYPOSITION Height() const { return bottom - top; } - bool Empty() const { - return (Height() <= 0) || (Width() <= 0); - } -}; - -/** - * Holds a desired RGB colour. - */ -class ColourDesired { - long co; -public: - ColourDesired(long lcol=0) { - co = lcol; - } - - ColourDesired(unsigned int red, unsigned int green, unsigned int blue) { - Set(red, green, blue); - } - - bool operator==(const ColourDesired &other) const { - return co == other.co; - } - - void Set(long lcol) { - co = lcol; - } - - void Set(unsigned int red, unsigned int green, unsigned int blue) { - co = red | (green << 8) | (blue << 16); - } - - static inline unsigned int ValueOfHex(const char ch) { - if (ch >= '0' && ch <= '9') - return ch - '0'; - else if (ch >= 'A' && ch <= 'F') - return ch - 'A' + 10; - else if (ch >= 'a' && ch <= 'f') - return ch - 'a' + 10; - else - return 0; - } - - void Set(const char *val) { - if (*val == '#') { - val++; - } - unsigned int r = ValueOfHex(val[0]) * 16 + ValueOfHex(val[1]); - unsigned int g = ValueOfHex(val[2]) * 16 + ValueOfHex(val[3]); - unsigned int b = ValueOfHex(val[4]) * 16 + ValueOfHex(val[5]); - Set(r, g, b); - } - - long AsLong() const { - return co; - } - - unsigned int GetRed() const { - return co & 0xff; - } - - unsigned int GetGreen() const { - return (co >> 8) & 0xff; - } - - unsigned int GetBlue() const { - return (co >> 16) & 0xff; - } -}; - -/** - * Font management. - */ - -struct FontParameters { - const char *faceName; - float size; - int weight; - bool italic; - int extraFontFlag; - int technology; - int characterSet; - - FontParameters( - const char *faceName_, - float size_=10, - int weight_=400, - bool italic_=false, - int extraFontFlag_=0, - int technology_=0, - int characterSet_=0) : - - faceName(faceName_), - size(size_), - weight(weight_), - italic(italic_), - extraFontFlag(extraFontFlag_), - technology(technology_), - characterSet(characterSet_) - { - } - -}; - -class Font { -protected: - FontID fid; -#if PLAT_WX - int ascent; -#endif - // Private so Font objects can not be copied - Font(const Font &); - Font &operator=(const Font &); -public: - Font(); - virtual ~Font(); - - virtual void Create(const FontParameters &fp); - virtual void Release(); - - FontID GetID() { return fid; } - // Alias another font - caller guarantees not to Release - void SetID(FontID fid_) { fid = fid_; } -#if PLAT_WX - void SetAscent(int ascent_) { ascent = ascent_; } -#endif - friend class Surface; - friend class SurfaceImpl; -}; - -/** - * A surface abstracts a place to draw. - */ -#if defined(PLAT_QT) -class XPM; -#endif -class Surface { -private: - // Private so Surface objects can not be copied - Surface(const Surface &) {} - Surface &operator=(const Surface &) { return *this; } -public: - Surface() {} - virtual ~Surface() {} - static Surface *Allocate(int technology); - - virtual void Init(WindowID wid)=0; - virtual void Init(SurfaceID sid, WindowID wid)=0; - virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid)=0; - - virtual void Release()=0; - virtual bool Initialised()=0; - virtual void PenColour(ColourDesired fore)=0; - virtual int LogPixelsY()=0; - virtual int DeviceHeightFont(int points)=0; - virtual void MoveTo(int x_, int y_)=0; - virtual void LineTo(int x_, int y_)=0; - virtual void Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back)=0; - virtual void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back)=0; - virtual void FillRectangle(PRectangle rc, ColourDesired back)=0; - virtual void FillRectangle(PRectangle rc, Surface &surfacePattern)=0; - virtual void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back)=0; - virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill, - ColourDesired outline, int alphaOutline, int flags)=0; - virtual void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) = 0; - virtual void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back)=0; - virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0; - - virtual void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0; - virtual void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0; - virtual void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore)=0; - virtual void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions)=0; - virtual XYPOSITION WidthText(Font &font_, const char *s, int len)=0; - virtual XYPOSITION WidthChar(Font &font_, char ch)=0; - virtual XYPOSITION Ascent(Font &font_)=0; - virtual XYPOSITION Descent(Font &font_)=0; - virtual XYPOSITION InternalLeading(Font &font_)=0; - virtual XYPOSITION ExternalLeading(Font &font_)=0; - virtual XYPOSITION Height(Font &font_)=0; - virtual XYPOSITION AverageCharWidth(Font &font_)=0; - - virtual void SetClip(PRectangle rc)=0; - virtual void FlushCachedState()=0; - - virtual void SetUnicodeMode(bool unicodeMode_)=0; - virtual void SetDBCSMode(int codePage)=0; - -#if defined(PLAT_QT) - virtual void Init(QPainter *p)=0; - virtual void DrawXPM(PRectangle rc, const XPM *xpm)=0; -#endif -}; - -/** - * A simple callback action passing one piece of untyped user data. - */ -typedef void (*CallBackAction)(void*); - -/** - * Class to hide the details of window manipulation. - * Does not own the window which will normally have a longer life than this object. - */ -class Window { -protected: - WindowID wid; -public: - Window() : wid(0), cursorLast(cursorInvalid) { - } - Window(const Window &source) : wid(source.wid), cursorLast(cursorInvalid) { - } - virtual ~Window(); - Window &operator=(WindowID wid_) { - wid = wid_; - return *this; - } - WindowID GetID() const { return wid; } - bool Created() const { return wid != 0; } - void Destroy(); - bool HasFocus(); - PRectangle GetPosition(); - void SetPosition(PRectangle rc); - void SetPositionRelative(PRectangle rc, Window relativeTo); - PRectangle GetClientPosition(); - void Show(bool show=true); - void InvalidateAll(); - void InvalidateRectangle(PRectangle rc); - virtual void SetFont(Font &font); - enum Cursor { cursorInvalid, cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow, cursorHand }; - void SetCursor(Cursor curs); - void SetTitle(const char *s); - PRectangle GetMonitorRect(Point pt); -private: - Cursor cursorLast; -}; - -/** - * Listbox management. - */ - -class ListBox : public Window { -public: - ListBox(); - virtual ~ListBox(); - static ListBox *Allocate(); - - virtual void SetFont(Font &font)=0; - virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_, int technology_)=0; - virtual void SetAverageCharWidth(int width)=0; - virtual void SetVisibleRows(int rows)=0; - virtual int GetVisibleRows() const=0; - virtual PRectangle GetDesiredRect()=0; - virtual int CaretFromEdge()=0; - virtual void Clear()=0; - virtual void Append(char *s, int type = -1)=0; - virtual int Length()=0; - virtual void Select(int n)=0; - virtual int GetSelection()=0; - virtual int Find(const char *prefix)=0; - virtual void GetValue(int n, char *value, int len)=0; - virtual void RegisterImage(int type, const char *xpm_data)=0; - virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) = 0; - virtual void ClearRegisteredImages()=0; - virtual void SetDoubleClickAction(CallBackAction, void *)=0; - virtual void SetList(const char* list, char separator, char typesep)=0; -}; - -/** - * Menu management. - */ -class Menu { - MenuID mid; -public: - Menu(); - MenuID GetID() { return mid; } - void CreatePopUp(); - void Destroy(); - void Show(Point pt, Window &w); -}; - -class ElapsedTime { - long bigBit; - long littleBit; -public: - ElapsedTime(); - double Duration(bool reset=false); -}; - -/** - * Dynamic Library (DLL/SO/...) loading - */ -class DynamicLibrary { -public: - virtual ~DynamicLibrary() {} - - /// @return Pointer to function "name", or NULL on failure. - virtual Function FindFunction(const char *name) = 0; - - /// @return true if the library was loaded successfully. - virtual bool IsValid() = 0; - - /// @return An instance of a DynamicLibrary subclass with "modulePath" loaded. - static DynamicLibrary *Load(const char *modulePath); -}; - -#if defined(__clang__) -# if __has_feature(attribute_analyzer_noreturn) -# define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn)) -# else -# define CLANG_ANALYZER_NORETURN -# endif -#else -# define CLANG_ANALYZER_NORETURN -#endif - -/** - * Platform class used to retrieve system wide parameters such as double click speed - * and chrome colour. Not a creatable object, more of a module with several functions. - */ -class Platform { - // Private so Platform objects can not be copied - Platform(const Platform &) {} - Platform &operator=(const Platform &) { return *this; } -public: - // Should be private because no new Platforms are ever created - // but gcc warns about this - Platform() {} - ~Platform() {} - static ColourDesired Chrome(); - static ColourDesired ChromeHighlight(); - static const char *DefaultFont(); - static int DefaultFontSize(); - static unsigned int DoubleClickTime(); - static bool MouseButtonBounce(); - static void DebugDisplay(const char *s); - static bool IsKeyDown(int key); - static long SendScintilla( - WindowID w, unsigned int msg, unsigned long wParam=0, long lParam=0); - static long SendScintillaPointer( - WindowID w, unsigned int msg, unsigned long wParam=0, void *lParam=0); - static bool IsDBCSLeadByte(int codePage, char ch); - static int DBCSCharLength(int codePage, const char *s); - static int DBCSCharMaxLength(); - - // These are utility functions not really tied to a platform - static int Minimum(int a, int b); - static int Maximum(int a, int b); - // Next three assume 16 bit shorts and 32 bit longs - static long LongFromTwoShorts(short a,short b) { - return (a) | ((b) << 16); - } - static short HighShortFromLong(long x) { - return static_cast(x >> 16); - } - static short LowShortFromLong(long x) { - return static_cast(x & 0xffff); - } - static void DebugPrintf(const char *format, ...); - static bool ShowAssertionPopUps(bool assertionPopUps_); - static void Assert(const char *c, const char *file, int line) CLANG_ANALYZER_NORETURN; - static int Clamp(int val, int minVal, int maxVal); -}; - -#ifdef NDEBUG -#define PLATFORM_ASSERT(c) ((void)0) -#else -#ifdef SCI_NAMESPACE -#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Scintilla::Platform::Assert(#c, __FILE__, __LINE__)) -#else -#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Platform::Assert(#c, __FILE__, __LINE__)) -#endif -#endif - -#ifdef SCI_NAMESPACE -} -#endif - -#if defined(__GNUC__) && defined(SCINTILLA_QT) -#pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif - -#endif diff --git a/libs/qscintilla/include/ScintillaWidget.h b/libs/qscintilla/include/ScintillaWidget.h deleted file mode 100644 index f8cd212b0..000000000 --- a/libs/qscintilla/include/ScintillaWidget.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Scintilla source code edit control */ -/** @file ScintillaWidget.h - ** Definition of Scintilla widget for GTK+. - ** Only needed by GTK+ code but is harmless on other platforms. - **/ -/* Copyright 1998-2001 by Neil Hodgson - * The License.txt file describes the conditions under which this software may be distributed. */ - -#ifndef SCINTILLAWIDGET_H -#define SCINTILLAWIDGET_H - -#if defined(GTK) - -#ifdef __cplusplus -extern "C" { -#endif - -#define SCINTILLA(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, scintilla_get_type (), ScintillaObject) -#define SCINTILLA_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, scintilla_get_type (), ScintillaClass) -#define IS_SCINTILLA(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, scintilla_get_type ()) - -typedef struct _ScintillaObject ScintillaObject; -typedef struct _ScintillaClass ScintillaClass; - -struct _ScintillaObject { - GtkContainer cont; - void *pscin; -}; - -struct _ScintillaClass { - GtkContainerClass parent_class; - - void (* command) (ScintillaObject *ttt); - void (* notify) (ScintillaObject *ttt); -}; - -GType scintilla_get_type (void); -GtkWidget* scintilla_new (void); -void scintilla_set_id (ScintillaObject *sci, uptr_t id); -sptr_t scintilla_send_message (ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam); -void scintilla_release_resources(void); - -#define SCINTILLA_NOTIFY "sci-notify" - -#ifdef __cplusplus -} -#endif - -#endif - -#endif diff --git a/libs/qscintilla/lexers/License.txt b/libs/qscintilla/lexers/License.txt deleted file mode 100644 index cbe25b2fc..000000000 --- a/libs/qscintilla/lexers/License.txt +++ /dev/null @@ -1,20 +0,0 @@ -License for Scintilla and SciTE - -Copyright 1998-2003 by Neil Hodgson - -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation. - -NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE -OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/libs/qscintilla/lexlib/CharacterCategory.cpp b/libs/qscintilla/lexlib/CharacterCategory.cpp deleted file mode 100644 index 2be46c013..000000000 --- a/libs/qscintilla/lexlib/CharacterCategory.cpp +++ /dev/null @@ -1,3304 +0,0 @@ -// Scintilla source code edit control -/** @file CharacterCategory.cxx - ** Returns the Unicode general category of a character. - ** Table automatically regenerated by scripts/GenerateCharacterCategory.py - ** Should only be rarely regenerated for new versions of Unicode. - **/ -// Copyright 2013 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include - -#include "StringCopy.h" -#include "CharacterCategory.h" - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -namespace { - // Use an unnamed namespace to protect the declarations from name conflicts - -const int catRanges[] = { -//++Autogenerated -- start of section automatically generated -// Created with Python 3.3.0, Unicode 6.1.0 -25, -1046, -1073, -1171, -1201, -1293, -1326, -1361, -1394, -1425, -1452, -1489, -1544, -1873, -1938, -2033, -2080, -2925, -2961, -2990, -3028, -3051, -3092, -3105, -3949, -3986, -4014, -4050, -4089, -5142, -5169, -5203, -5333, -5361, -5396, -5429, -5444, -5487, -5522, -5562, -5589, -5620, -5653, -5682, -5706, -5780, -5793, -5841, -5908, -5930, -5956, -6000, -6026, -6129, -6144, -6898, -6912, -7137, -7922, -7937, -8192, -8225, -8256, -8289, -8320, -8353, -8384, -8417, -8448, -8481, -8512, -8545, -8576, -8609, -8640, -8673, -8704, -8737, -8768, -8801, -8832, -8865, -8896, -8929, -8960, -8993, -9024, -9057, -9088, -9121, -9152, -9185, -9216, -9249, -9280, -9313, -9344, -9377, -9408, -9441, -9472, -9505, -9536, -9569, -9600, -9633, -9664, -9697, -9728, -9761, -9792, -9825, -9856, -9889, -9920, -9953, -10016, -10049, -10080, -10113, -10144, -10177, -10208, -10241, -10272, -10305, -10336, -10369, -10400, -10433, -10464, -10497, -10560, -10593, -10624, -10657, -10688, -10721, -10752, -10785, -10816, -10849, -10880, -10913, -10944, -10977, -11008, -11041, -11072, -11105, -11136, -11169, -11200, -11233, -11264, -11297, -11328, -11361, -11392, -11425, -11456, -11489, -11520, -11553, -11584, -11617, -11648, -11681, -11712, -11745, -11776, -11809, -11840, -11873, -11904, -11937, -11968, -12001, -12032, -12097, -12128, -12161, -12192, -12225, -12320, -12385, -12416, -12449, -12480, -12545, -12576, -12673, -12736, -12865, -12896, -12961, -12992, -13089, -13184, -13249, -13280, -13345, -13376, -13409, -13440, -13473, -13504, -13569, -13600, -13633, -13696, -13729, -13760, -13825, -13856, -13953, -13984, -14017, -14048, -14113, -14180, -14208, -14241, -14340, -14464, -14498, -14529, -14560, -14594, -14625, -14656, -14690, -14721, -14752, -14785, -14816, -14849, -14880, -14913, -14944, -14977, -15008, -15041, -15072, -15105, -15136, -15169, -15200, -15233, -15296, -15329, -15360, -15393, -15424, -15457, -15488, -15521, -15552, -15585, -15616, -15649, -15680, -15713, -15744, -15777, -15808, -15841, -15904, -15938, -15969, -16000, -16033, -16064, -16161, -16192, -16225, -16256, -16289, -16320, -16353, -16384, -16417, -16448, -16481, -16512, -16545, -16576, -16609, -16640, -16673, -16704, -16737, -16768, -16801, -16832, -16865, -16896, -16929, -16960, -16993, -17024, -17057, -17088, -17121, -17152, -17185, -17216, -17249, -17280, -17313, -17344, -17377, -17408, -17441, -17472, -17505, -17536, -17569, -17600, -17633, -17664, -17697, -17728, -17761, -17792, -17825, -17856, -17889, -17920, -17953, -17984, -18017, -18240, -18305, -18336, -18401, -18464, -18497, -18528, -18657, -18688, -18721, -18752, -18785, -18816, -18849, -18880, -18913, -21124, -21153, -22019, -22612, -22723, -23124, -23555, -23732, -23939, -23988, -24003, -24052, -24581, -28160, -28193, -28224, -28257, -28291, -28340, -28352, -28385, -28445, -28483, -28513, -28625, -28669, -28820, -28864, -28913, -28928, -29053, -29056, -29117, -29120, -29185, -29216, -29789, -29792, -30081, -31200, -31233, -31296, -31393, -31488, -31521, -31552, -31585, -31616, -31649, -31680, -31713, -31744, -31777, -31808, -31841, -31872, -31905, -31936, -31969, -32000, -32033, -32064, -32097, -32128, -32161, -32192, -32225, -32384, -32417, -32466, -32480, -32513, -32544, -32609, -32672, -34305, -35840, -35873, -35904, -35937, -35968, -36001, -36032, -36065, -36096, -36129, -36160, -36193, -36224, -36257, -36288, -36321, -36352, -36385, -36416, -36449, -36480, -36513, -36544, -36577, -36608, -36641, -36672, -36705, -36736, -36769, -36800, -36833, -36864, -36897, -36949, -36965, -37127, -37184, -37217, -37248, -37281, -37312, -37345, -37376, -37409, -37440, -37473, -37504, -37537, -37568, -37601, -37632, -37665, -37696, -37729, -37760, -37793, -37824, -37857, -37888, -37921, -37952, -37985, -38016, -38049, -38080, -38113, -38144, -38177, -38208, -38241, -38272, -38305, -38336, -38369, -38400, -38433, -38464, -38497, -38528, -38561, -38592, -38625, -38656, -38689, -38720, -38753, -38784, -38817, -38848, -38881, -38912, -38977, -39008, -39041, -39072, -39105, -39136, -39169, -39200, -39233, -39264, -39297, -39328, -39361, -39424, -39457, -39488, -39521, -39552, -39585, -39616, -39649, -39680, -39713, -39744, -39777, -39808, -39841, -39872, -39905, -39936, -39969, -40000, -40033, -40064, -40097, -40128, -40161, -40192, -40225, -40256, -40289, -40320, -40353, -40384, -40417, -40448, -40481, -40512, -40545, -40576, -40609, -40640, -40673, -40704, -40737, -40768, -40801, -40832, -40865, -40896, -40929, -40960, -40993, -41024, -41057, -41088, -41121, -41152, -41185, -41216, -41249, -41280, -41313, -41344, -41377, -41408, -41441, -41472, -41505, -41536, -41569, -41600, -41633, -41664, -41697, -41728, -41761, -41792, -41825, -41856, -41889, -41920, -41953, -41984, -42017, -42048, -42081, -42112, -42145, -42176, -42209, -42269, -42528, -43773, -43811, -43857, -44061, -44065, -45341, -45361, -45388, -45437, -45555, -45597, -45605, -47052, -47077, -47121, -47141, -47217, -47237, -47313, -47333, -47389, -47620, -48509, -48644, -48753, -48829, -49178, -49341, -49362, -49457, -49523, -49553, -49621, -49669, -50033, -50077, -50129, -50180, -51203, -51236, -51557, -52232, -52561, -52676, -52741, -52772, -55953, -55972, -56005, -56250, -56277, -56293, -56483, -56549, -56629, -56645, -56772, -56840, -57156, -57269, -57316, -57361, -57821, -57850, -57860, -57893, -57924, -58885, -59773, -59812, -62661, -63012, -63069, -63496, -63812, -64869, -65155, -65237, -65265, -65347, -65405, -65540, -66245, -66371, -66405, -66691, -66725, -66819, -66853, -67037, -67089, -67581, -67588, -68389, -68509, -68561, -68605, -70660, -70717, -70724, -71101, -72837, -73725, -73733, -73830, -73860, -75589, -75622, -75653, -75684, -75718, -75813, -76070, -76197, -76230, -76292, -76325, -76548, -76869, -76945, -77000, -77329, -77347, -77380, -77597, -77604, -77853, -77861, -77894, -77981, -77988, -78269, -78308, -78397, -78436, -79165, -79172, -79421, -79428, -79485, -79556, -79709, -79749, -79780, -79814, -79909, -80061, -80102, -80189, -80230, -80293, -80324, -80381, -80614, -80669, -80772, -80861, -80868, -80965, -81053, -81096, -81412, -81491, -81546, -81749, -81779, -81821, -81957, -82022, -82077, -82084, -82301, -82404, -82493, -82532, -83261, -83268, -83517, -83524, -83613, -83620, -83709, -83716, -83805, -83845, -83901, -83910, -84005, -84093, -84197, -84285, -84325, -84445, -84517, -84573, -84772, -84925, -84932, -84989, -85192, -85509, -85572, -85669, -85725, -86053, -86118, -86173, -86180, -86493, -86500, -86621, -86628, -87357, -87364, -87613, -87620, -87709, -87716, -87901, -87941, -87972, -88006, -88101, -88285, -88293, -88358, -88413, -88422, -88485, -88541, -88580, -88637, -89092, -89157, -89245, -89288, -89617, -89651, -89693, -90149, -90182, -90269, -90276, -90557, -90596, -90685, -90724, -91453, -91460, -91709, -91716, -91805, -91812, -91997, -92037, -92068, -92102, -92133, -92166, -92197, -92349, -92390, -92477, -92518, -92581, -92637, -92869, -92902, -92957, -93060, -93149, -93156, -93253, -93341, -93384, -93717, -93732, -93770, -93981, -94277, -94308, -94365, -94372, -94589, -94660, -94781, -94788, -94941, -95012, -95101, -95108, -95165, -95172, -95261, -95332, -95421, -95492, -95613, -95684, -96093, -96198, -96261, -96294, -96381, -96454, -96573, -96582, -96677, -96733, -96772, -96829, -96998, -97053, -97480, -97802, -97909, -98099, -98133, -98173, -98342, -98461, -98468, -98749, -98756, -98877, -98884, -99645, -99652, -99997, -100004, -100189, -100260, -100293, -100390, -100541, -100549, -100669, -100677, -100829, -101029, -101117, -101124, -101213, -101380, -101445, -101533, -101576, -101917, -102154, -102389, -102429, -102470, -102557, -102564, -102845, -102852, -102973, -102980, -103741, -103748, -104093, -104100, -104285, -104325, -104356, -104390, -104421, -104454, -104637, -104645, -104678, -104765, -104774, -104837, -104925, -105126, -105213, -105412, -105469, -105476, -105541, -105629, -105672, -106013, -106020, -106109, -106566, -106653, -106660, -106941, -106948, -107069, -107076, -108413, -108452, -108486, -108581, -108733, -108742, -108861, -108870, -108965, -108996, -109053, -109286, -109341, -109572, -109637, -109725, -109768, -110090, -110301, -110389, -110404, -110621, -110662, -110749, -110756, -111357, -111428, -112221, -112228, -112541, -112548, -112605, -112644, -112893, -112965, -113021, -113126, -113221, -113341, -113349, -113405, -113414, -113693, -114246, -114321, -114365, -114724, -116261, -116292, -116357, -116605, -116723, -116740, -116931, -116965, -117233, -117256, -117585, -117661, -118820, -118909, -118916, -118973, -119012, -119101, -119108, -119165, -119204, -119261, -119428, -119581, -119588, -119837, -119844, -119965, -119972, -120029, -120036, -120093, -120132, -120221, -120228, -120357, -120388, -120453, -120669, -120677, -120740, -120797, -120836, -121021, -121027, -121085, -121093, -121309, -121352, -121693, -121732, -121885, -122884, -122933, -123025, -123509, -123537, -123573, -123653, -123733, -123912, -124234, -124565, -124581, -124629, -124645, -124693, -124709, -124749, -124782, -124813, -124846, -124870, -124932, -125213, -125220, -126397, -126501, -126950, -126981, -127153, -127173, -127236, -127397, -127773, -127781, -128957, -128981, -129221, -129269, -129469, -129493, -129553, -129717, -129841, -129917, -131076, -132454, -132517, -132646, -132677, -132870, -132901, -132966, -133029, -133092, -133128, -133457, -133636, -133830, -133893, -133956, -134085, -134180, -134214, -134308, -134374, -134596, -134693, -134820, -135237, -135270, -135333, -135398, -135589, -135620, -135654, -135688, -136006, -136101, -136149, -136192, -137437, -137440, -137501, -137632, -137693, -137732, -139121, -139139, -139172, -149821, -149828, -149981, -150020, -150269, -150276, -150333, -150340, -150493, -150532, -151869, -151876, -152029, -152068, -153149, -153156, -153309, -153348, -153597, -153604, -153661, -153668, -153821, -153860, -154365, -154372, -156221, -156228, -156381, -156420, -158589, -158629, -158737, -159018, -159677, -159748, -160277, -160605, -160772, -163517, -163852, -163876, -183729, -183780, -184342, -184356, -185197, -185230, -185277, -185348, -187761, -187849, -187965, -188420, -188861, -188868, -188997, -189117, -189444, -190021, -190129, -190205, -190468, -191045, -191133, -191492, -191933, -191940, -192061, -192069, -192157, -192516, -194181, -194246, -194277, -194502, -194757, -194790, -194853, -195217, -195299, -195345, -195443, -195460, -195493, -195549, -195592, -195933, -196106, -196445, -196625, -196812, -196849, -196965, -197078, -197117, -197128, -197469, -197636, -198755, -198788, -200477, -200708, -202021, -202052, -202109, -202244, -204509, -204804, -205757, -205829, -205926, -206053, -206118, -206237, -206342, -206405, -206438, -206629, -206749, -206869, -206909, -206993, -207048, -207364, -208349, -208388, -208573, -208900, -210333, -210438, -210980, -211206, -211293, -211464, -211786, -211837, -211925, -212996, -213733, -213798, -213917, -213969, -214020, -215718, -215749, -215782, -215813, -216061, -216069, -216102, -216133, -216166, -216229, -216486, -216677, -217021, -217061, -217096, -217437, -217608, -217949, -218129, -218339, -218385, -218589, -221189, -221318, -221348, -222853, -222886, -222917, -223078, -223109, -223142, -223301, -223334, -223396, -223645, -223752, -224081, -224309, -224613, -224917, -225213, -225285, -225350, -225380, -226342, -226373, -226502, -226565, -226630, -226661, -226694, -226756, -226824, -227140, -228549, -228582, -228613, -228678, -228773, -228806, -228837, -228934, -229021, -229265, -229380, -230534, -230789, -231046, -231109, -231197, -231281, -231432, -231773, -231844, -231944, -232260, -233219, -233425, -233501, -235537, -235805, -236037, -236145, -236165, -236582, -236613, -236836, -236965, -236996, -237126, -237189, -237220, -237309, -237569, -238979, -240993, -241411, -241441, -242531, -243717, -244989, -245637, -245760, -245793, -245824, -245857, -245888, -245921, -245952, -245985, -246016, -246049, -246080, -246113, -246144, -246177, -246208, -246241, -246272, -246305, -246336, -246369, -246400, -246433, -246464, -246497, -246528, -246561, -246592, -246625, -246656, -246689, -246720, -246753, -246784, -246817, -246848, -246881, -246912, -246945, -246976, -247009, -247040, -247073, -247104, -247137, -247168, -247201, -247232, -247265, -247296, -247329, -247360, -247393, -247424, -247457, -247488, -247521, -247552, -247585, -247616, -247649, -247680, -247713, -247744, -247777, -247808, -247841, -247872, -247905, -247936, -247969, -248000, -248033, -248064, -248097, -248128, -248161, -248192, -248225, -248256, -248289, -248320, -248353, -248384, -248417, -248448, -248481, -248512, -248545, -248576, -248609, -248640, -248673, -248704, -248737, -248768, -248801, -248832, -248865, -248896, -248929, -248960, -248993, -249024, -249057, -249088, -249121, -249152, -249185, -249216, -249249, -249280, -249313, -249344, -249377, -249408, -249441, -249472, -249505, -249536, -249569, -249600, -249633, -249664, -249697, -249728, -249761, -249792, -249825, -249856, -249889, -249920, -249953, -249984, -250017, -250048, -250081, -250112, -250145, -250176, -250209, -250240, -250273, -250304, -250337, -250368, -250401, -250432, -250465, -250496, -250529, -250816, -250849, -250880, -250913, -250944, -250977, -251008, -251041, -251072, -251105, -251136, -251169, -251200, -251233, -251264, -251297, -251328, -251361, -251392, -251425, -251456, -251489, -251520, -251553, -251584, -251617, -251648, -251681, -251712, -251745, -251776, -251809, -251840, -251873, -251904, -251937, -251968, -252001, -252032, -252065, -252096, -252129, -252160, -252193, -252224, -252257, -252288, -252321, -252352, -252385, -252416, -252449, -252480, -252513, -252544, -252577, -252608, -252641, -252672, -252705, -252736, -252769, -252800, -252833, -252864, -252897, -252928, -252961, -252992, -253025, -253056, -253089, -253120, -253153, -253184, -253217, -253248, -253281, -253312, -253345, -253376, -253409, -253440, -253473, -253504, -253537, -253568, -253601, -253632, -253665, -253696, -253729, -253760, -253793, -253824, -253857, -253888, -253921, -254208, -254465, -254685, -254720, -254941, -254977, -255232, -255489, -255744, -256001, -256221, -256256, -256477, -256513, -256797, -256800, -256861, -256864, -256925, -256928, -256989, -256992, -257025, -257280, -257537, -258013, -258049, -258306, -258561, -258818, -259073, -259330, -259585, -259773, -259777, -259840, -259970, -260020, -260033, -260084, -260161, -260285, -260289, -260352, -260482, -260532, -260609, -260765, -260801, -260864, -261021, -261044, -261121, -261376, -261556, -261661, -261697, -261821, -261825, -261888, -262018, -262068, -262141, -262166, -262522, -262668, -262865, -262927, -262960, -262989, -263023, -263088, -263117, -263151, -263185, -263447, -263480, -263514, -263670, -263697, -263983, -264016, -264049, -264171, -264241, -264338, -264365, -264398, -264433, -264786, -264817, -264843, -264881, -265206, -265242, -265405, -265562, -265738, -265763, -265821, -265866, -266066, -266157, -266190, -266211, -266250, -266578, -266669, -266702, -266749, -266755, -267197, -267283, -268125, -268805, -269223, -269349, -269383, -269477, -269885, -270357, -270400, -270453, -270560, -270613, -270657, -270688, -270785, -270848, -270945, -270997, -271008, -271061, -271122, -271136, -271317, -271488, -271541, -271552, -271605, -271616, -271669, -271680, -271829, -271841, -271872, -272001, -272036, -272161, -272213, -272257, -272320, -272402, -272544, -272577, -272725, -272754, -272789, -272833, -272885, -272906, -273417, -274528, -274561, -274601, -274730, -274781, -274962, -275125, -275282, -275349, -275474, -275509, -275570, -275605, -275666, -275701, -275922, -275957, -276946, -277013, -277074, -277109, -277138, -277173, -278162, -286741, -286994, -287125, -287762, -287829, -288045, -288078, -288117, -290706, -290741, -291698, -292501, -293778, -293973, -294557, -294933, -296189, -296981, -297341, -297994, -299925, -302410, -303125, -308978, -309013, -309298, -309333, -311058, -311317, -314866, -314901, -319517, -319541, -322829, -322862, -322893, -322926, -322957, -322990, -323021, -323054, -323085, -323118, -323149, -323182, -323213, -323246, -323274, -324245, -325650, -325805, -325838, -325874, -326861, -326894, -326925, -326958, -326989, -327022, -327053, -327086, -327117, -327150, -327186, -327701, -335890, -340077, -340110, -340141, -340174, -340205, -340238, -340269, -340302, -340333, -340366, -340397, -340430, -340461, -340494, -340525, -340558, -340589, -340622, -340653, -340686, -340717, -340750, -340786, -342797, -342830, -342861, -342894, -342930, -343949, -343982, -344018, -352277, -353810, -354485, -354546, -354749, -354837, -355165, -360448, -361981, -361985, -363517, -363520, -363553, -363584, -363681, -363744, -363777, -363808, -363841, -363872, -363905, -363936, -364065, -364096, -364129, -364192, -364225, -364419, -364480, -364577, -364608, -364641, -364672, -364705, -364736, -364769, -364800, -364833, -364864, -364897, -364928, -364961, -364992, -365025, -365056, -365089, -365120, -365153, -365184, -365217, -365248, -365281, -365312, -365345, -365376, -365409, -365440, -365473, -365504, -365537, -365568, -365601, -365632, -365665, -365696, -365729, -365760, -365793, -365824, -365857, -365888, -365921, -365952, -365985, -366016, -366049, -366080, -366113, -366144, -366177, -366208, -366241, -366272, -366305, -366336, -366369, -366400, -366433, -366464, -366497, -366528, -366561, -366592, -366625, -366656, -366689, -366720, -366753, -366784, -366817, -366848, -366881, -366912, -366945, -366976, -367009, -367040, -367073, -367104, -367137, -367168, -367201, -367232, -367265, -367296, -367329, -367360, -367393, -367424, -367457, -367488, -367521, -367552, -367585, -367616, -367649, -367680, -367713, -367797, -367968, -368001, -368032, -368065, -368101, -368192, -368225, -368285, -368433, -368554, -368593, -368641, -369885, -369889, -369949, -370081, -370141, -370180, -371997, -372195, -372241, -372285, -372709, -372740, -373501, -373764, -374013, -374020, -374269, -374276, -374525, -374532, -374781, -374788, -375037, -375044, -375293, -375300, -375549, -375556, -375805, -375813, -376849, -376911, -376944, -376975, -377008, -377041, -377135, -377168, -377201, -377231, -377264, -377297, -377580, -377617, -377676, -377713, -377743, -377776, -377809, -377871, -377904, -377933, -377966, -377997, -378030, -378061, -378094, -378125, -378158, -378193, -378339, -378385, -378700, -378781, -380949, -381789, -381813, -384669, -385045, -391901, -392725, -393117, -393238, -393265, -393365, -393379, -393412, -393449, -393485, -393518, -393549, -393582, -393613, -393646, -393677, -393710, -393741, -393774, -393813, -393869, -393902, -393933, -393966, -393997, -394030, -394061, -394094, -394124, -394157, -394190, -394261, -394281, -394565, -394694, -394764, -394787, -394965, -395017, -395107, -395140, -395185, -395221, -395293, -395300, -398077, -398117, -398196, -398243, -398308, -398348, -398372, -401265, -401283, -401380, -401437, -401572, -402909, -402980, -406013, -406037, -406090, -406229, -406532, -407421, -407573, -408733, -409092, -409621, -410621, -410634, -410965, -411914, -412181, -412202, -412693, -413706, -414037, -415274, -415765, -417789, -417813, -425988, -636637, -636949, -638980, -1309117, -1310724, -1311395, -1311428, -1348029, -1348117, -1349885, -1350148, -1351427, -1351633, -1351684, -1360259, -1360305, -1360388, -1360904, -1361220, -1361309, -1361920, -1361953, -1361984, -1362017, -1362048, -1362081, -1362112, -1362145, -1362176, -1362209, -1362240, -1362273, -1362304, -1362337, -1362368, -1362401, -1362432, -1362465, -1362496, -1362529, -1362560, -1362593, -1362624, -1362657, -1362688, -1362721, -1362752, -1362785, -1362816, -1362849, -1362880, -1362913, -1362944, -1362977, -1363008, -1363041, -1363072, -1363105, -1363136, -1363169, -1363200, -1363233, -1363264, -1363297, -1363328, -1363361, -1363396, -1363429, -1363463, -1363569, -1363589, -1363921, -1363939, -1363968, -1364001, -1364032, -1364065, -1364096, -1364129, -1364160, -1364193, -1364224, -1364257, -1364288, -1364321, -1364352, -1364385, -1364416, -1364449, -1364480, -1364513, -1364544, -1364577, -1364608, -1364641, -1364672, -1364705, -1364765, -1364965, -1364996, -1367241, -1367557, -1367633, -1367837, -1368084, -1368803, -1369108, -1369152, -1369185, -1369216, -1369249, -1369280, -1369313, -1369344, -1369377, -1369408, -1369441, -1369472, -1369505, -1369536, -1369569, -1369664, -1369697, -1369728, -1369761, -1369792, -1369825, -1369856, -1369889, -1369920, -1369953, -1369984, -1370017, -1370048, -1370081, -1370112, -1370145, -1370176, -1370209, -1370240, -1370273, -1370304, -1370337, -1370368, -1370401, -1370432, -1370465, -1370496, -1370529, -1370560, -1370593, -1370624, -1370657, -1370688, -1370721, -1370752, -1370785, -1370816, -1370849, -1370880, -1370913, -1370944, -1370977, -1371008, -1371041, -1371072, -1371105, -1371136, -1371169, -1371200, -1371233, -1371264, -1371297, -1371328, -1371361, -1371392, -1371425, -1371456, -1371489, -1371520, -1371553, -1371584, -1371617, -1371651, -1371681, -1371936, -1371969, -1372000, -1372033, -1372064, -1372129, -1372160, -1372193, -1372224, -1372257, -1372288, -1372321, -1372352, -1372385, -1372419, -1372468, -1372512, -1372545, -1372576, -1372609, -1372669, -1372672, -1372705, -1372736, -1372769, -1372829, -1373184, -1373217, -1373248, -1373281, -1373312, -1373345, -1373376, -1373409, -1373440, -1373473, -1373504, -1373565, -1376003, -1376065, -1376100, -1376325, -1376356, -1376453, -1376484, -1376613, -1376644, -1377382, -1377445, -1377510, -1377557, -1377693, -1377802, -1378005, -1378067, -1378101, -1378141, -1378308, -1379985, -1380125, -1380358, -1380420, -1382022, -1382533, -1382589, -1382865, -1382920, -1383261, -1383429, -1384004, -1384209, -1384292, -1384349, -1384456, -1384772, -1385669, -1385937, -1385988, -1386725, -1387078, -1387165, -1387505, -1387524, -1388477, -1388549, -1388646, -1388676, -1390181, -1390214, -1390277, -1390406, -1390469, -1390502, -1390641, -1391069, -1391075, -1391112, -1391453, -1391569, -1391645, -1392644, -1393957, -1394150, -1394213, -1394278, -1394341, -1394429, -1394692, -1394789, -1394820, -1395077, -1395110, -1395165, -1395208, -1395549, -1395601, -1395716, -1396227, -1396260, -1396469, -1396548, -1396582, -1396637, -1396740, -1398277, -1398308, -1398341, -1398436, -1398501, -1398564, -1398725, -1398788, -1398821, -1398852, -1398909, -1399652, -1399715, -1399761, -1399812, -1400166, -1400197, -1400262, -1400337, -1400388, -1400419, -1400486, -1400517, -1400573, -1400868, -1401085, -1401124, -1401341, -1401380, -1401597, -1401860, -1402109, -1402116, -1402365, -1406980, -1408102, -1408165, -1408198, -1408261, -1408294, -1408369, -1408390, -1408421, -1408477, -1408520, -1408861, -1409028, -1766557, -1766916, -1767677, -1767780, -1769373, -1769499, -1835036, -2039812, -2051549, -2051588, -2055005, -2056193, -2056445, -2056801, -2056989, -2057124, -2057157, -2057188, -2057522, -2057540, -2057981, -2057988, -2058173, -2058180, -2058237, -2058244, -2058333, -2058340, -2058429, -2058436, -2061908, -2062429, -2062948, -2074573, -2074606, -2074653, -2075140, -2077213, -2077252, -2079005, -2080260, -2080659, -2080693, -2080733, -2080773, -2081297, -2081517, -2081550, -2081585, -2081629, -2081797, -2082045, -2082321, -2082348, -2082411, -2082477, -2082510, -2082541, -2082574, -2082605, -2082638, -2082669, -2082702, -2082733, -2082766, -2082797, -2082830, -2082861, -2082894, -2082925, -2082958, -2082993, -2083053, -2083086, -2083121, -2083243, -2083345, -2083453, -2083473, -2083596, -2083629, -2083662, -2083693, -2083726, -2083757, -2083790, -2083825, -2083922, -2083948, -2083986, -2084093, -2084113, -2084147, -2084177, -2084253, -2084356, -2084541, -2084548, -2088893, -2088954, -2088989, -2089009, -2089107, -2089137, -2089229, -2089262, -2089297, -2089330, -2089361, -2089388, -2089425, -2089480, -2089809, -2089874, -2089969, -2090016, -2090861, -2090897, -2090926, -2090964, -2090987, -2091028, -2091041, -2091885, -2091922, -2091950, -2091986, -2092013, -2092046, -2092081, -2092109, -2092142, -2092177, -2092228, -2092547, -2092580, -2094019, -2094084, -2095101, -2095172, -2095389, -2095428, -2095645, -2095684, -2095901, -2095940, -2096061, -2096147, -2096210, -2096244, -2096277, -2096307, -2096381, -2096405, -2096434, -2096565, -2096637, -2096954, -2097045, -2097117, -2097156, -2097565, -2097572, -2098429, -2098436, -2099069, -2099076, -2099165, -2099172, -2099677, -2099716, -2100189, -2101252, -2105213, -2105361, -2105469, -2105578, -2107037, -2107125, -2107401, -2109098, -2109237, -2109770, -2109821, -2109973, -2110365, -2112021, -2113445, -2113501, -2117636, -2118589, -2118660, -2120253, -2121732, -2122749, -2122762, -2122909, -2123268, -2123817, -2123844, -2124105, -2124157, -2125828, -2126813, -2126833, -2126852, -2128029, -2128132, -2128401, -2128425, -2128605, -2129920, -2131201, -2132484, -2135005, -2135048, -2135389, -2162692, -2162909, -2162948, -2163005, -2163012, -2164445, -2164452, -2164541, -2164612, -2164669, -2164708, -2165469, -2165489, -2165514, -2165789, -2170884, -2171594, -2171805, -2171889, -2171908, -2172765, -2172913, -2172957, -2174980, -2176797, -2176964, -2177053, -2179076, -2179109, -2179229, -2179237, -2179325, -2179461, -2179588, -2179741, -2179748, -2179869, -2179876, -2180765, -2180869, -2180989, -2181093, -2181130, -2181405, -2181649, -2181949, -2182148, -2183082, -2183153, -2183197, -2187268, -2189021, -2189105, -2189316, -2190045, -2190090, -2190340, -2190973, -2191114, -2191389, -2195460, -2197821, -2214922, -2215933, -2228230, -2228261, -2228294, -2228324, -2230021, -2230513, -2230749, -2230858, -2231496, -2231837, -2232325, -2232390, -2232420, -2233862, -2233957, -2234086, -2234149, -2234225, -2234298, -2234321, -2234461, -2234884, -2235709, -2235912, -2236253, -2236421, -2236516, -2237669, -2237830, -2237861, -2238141, -2238152, -2238481, -2238621, -2240517, -2240582, -2240612, -2242150, -2242245, -2242534, -2242596, -2242737, -2242877, -2243080, -2243421, -2281476, -2282853, -2282886, -2282917, -2282950, -2283013, -2283206, -2283237, -2283293, -2283528, -2283869, -2359300, -2387453, -2392073, -2395261, -2395665, -2395805, -2490372, -2524669, -2949124, -2967357, -3006468, -3008701, -3009028, -3009062, -3010557, -3011045, -3011171, -3011613, -3538948, -3539037, -3801109, -3808989, -3809301, -3810557, -3810613, -3812518, -3812581, -3812693, -3812774, -3812986, -3813221, -3813493, -3813541, -3813781, -3814725, -3814869, -3816413, -3817493, -3819589, -3819701, -3819741, -3825685, -3828477, -3828746, -3829341, -3833856, -3834689, -3835520, -3836353, -3836605, -3836609, -3837184, -3838017, -3838848, -3838909, -3838912, -3839005, -3839040, -3839101, -3839136, -3839229, -3839264, -3839421, -3839424, -3839681, -3839837, -3839841, -3839901, -3839905, -3840157, -3840161, -3840512, -3841345, -3842176, -3842269, -3842272, -3842429, -3842464, -3842749, -3842752, -3843005, -3843009, -3843840, -3843933, -3843936, -3844093, -3844096, -3844285, -3844288, -3844349, -3844416, -3844669, -3844673, -3845504, -3846337, -3847168, -3848001, -3848832, -3849665, -3850496, -3851329, -3852160, -3852993, -3853824, -3854657, -3855581, -3855616, -3856434, -3856449, -3857266, -3857281, -3857472, -3858290, -3858305, -3859122, -3859137, -3859328, -3860146, -3860161, -3860978, -3860993, -3861184, -3862002, -3862017, -3862834, -3862849, -3863040, -3863858, -3863873, -3864690, -3864705, -3864896, -3864929, -3864989, -3865032, -3866653, -4046852, -4047005, -4047012, -4047901, -4047908, -4047997, -4048004, -4048061, -4048100, -4048157, -4048164, -4048509, -4048516, -4048669, -4048676, -4048733, -4048740, -4048797, -4048964, -4049021, -4049124, -4049181, -4049188, -4049245, -4049252, -4049309, -4049316, -4049437, -4049444, -4049533, -4049540, -4049597, -4049636, -4049693, -4049700, -4049757, -4049764, -4049821, -4049828, -4049885, -4049892, -4049949, -4049956, -4050045, -4050052, -4050109, -4050148, -4050301, -4050308, -4050557, -4050564, -4050717, -4050724, -4050877, -4050884, -4050941, -4050948, -4051293, -4051300, -4051869, -4052004, -4052125, -4052132, -4052317, -4052324, -4052893, -4054546, -4054621, -4063253, -4064669, -4064789, -4067997, -4068373, -4068861, -4068917, -4069373, -4069429, -4069917, -4069941, -4070429, -4071434, -4071805, -4071957, -4072957, -4072981, -4074909, -4075029, -4076413, -4078805, -4079741, -4080149, -4081533, -4081685, -4081981, -4082197, -4082269, -4087829, -4088893, -4089365, -4089565, -4089589, -4091837, -4091925, -4092573, -4092949, -4094141, -4094165, -4094333, -4094997, -4095549, -4096021, -4098045, -4098069, -4098109, -4098133, -4103965, -4103989, -4104125, -4104213, -4106205, -4106261, -4106397, -4106773, -4107549, -4112245, -4114493, -4114613, -4114973, -4116501, -4118749, -4120597, -4124317, -4194308, -5561085, -5562372, -5695165, -5695492, -5702621, -6225924, -6243293, -29360186, -29360221, -29361178, -29364253, -29368325, -29376029, -31457308, -33554397, -33554460, -35651549, -//--Autogenerated -- end of section automatically generated -}; - -const int maxUnicode = 0x10ffff; -const int maskCategory = 0x1F; -const int nRanges = ELEMENTS(catRanges); - -} - -// Each element in catRanges is the start of a range of Unicode characters in -// one general category. -// The value is comprised of a 21-bit character value shifted 5 bits and a 5 bit -// category matching the CharacterCategory enumeration. -// Initial version has 3249 entries and adds about 13K to the executable. -// The array is in ascending order so can be searched using binary search. -// Therefore the average call takes log2(3249) = 12 comparisons. -// For speed, it may be useful to make a linear table for the common values, -// possibly for 0..0xff for most Western European text or 0..0xfff for most -// alphabetic languages. - -CharacterCategory CategoriseCharacter(int character) { - if (character < 0 || character > maxUnicode) - return ccCn; - const int baseValue = character * (maskCategory+1) + maskCategory; - const int *placeAfter = std::lower_bound(catRanges, catRanges+nRanges, baseValue); - return static_cast(*(placeAfter-1) & maskCategory); -} - -#ifdef SCI_NAMESPACE -} -#endif diff --git a/libs/qscintilla/lexlib/CharacterSet.cpp b/libs/qscintilla/lexlib/CharacterSet.cpp deleted file mode 100644 index 0ab2cc0cc..000000000 --- a/libs/qscintilla/lexlib/CharacterSet.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Scintilla source code edit control -/** @file CharacterSet.cxx - ** Simple case functions for ASCII. - ** Lexer infrastructure. - **/ -// Copyright 1998-2010 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include "CharacterSet.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -int CompareCaseInsensitive(const char *a, const char *b) { - while (*a && *b) { - if (*a != *b) { - char upperA = MakeUpperCase(*a); - char upperB = MakeUpperCase(*b); - if (upperA != upperB) - return upperA - upperB; - } - a++; - b++; - } - // Either *a or *b is nul - return *a - *b; -} - -int CompareNCaseInsensitive(const char *a, const char *b, size_t len) { - while (*a && *b && len) { - if (*a != *b) { - char upperA = MakeUpperCase(*a); - char upperB = MakeUpperCase(*b); - if (upperA != upperB) - return upperA - upperB; - } - a++; - b++; - len--; - } - if (len == 0) - return 0; - else - // Either *a or *b is nul - return *a - *b; -} - -#ifdef SCI_NAMESPACE -} -#endif diff --git a/libs/qscintilla/lexlib/LexAccessor.h b/libs/qscintilla/lexlib/LexAccessor.h deleted file mode 100644 index 8e3455d0c..000000000 --- a/libs/qscintilla/lexlib/LexAccessor.h +++ /dev/null @@ -1,204 +0,0 @@ -// Scintilla source code edit control -/** @file LexAccessor.h - ** Interfaces between Scintilla and lexers. - **/ -// Copyright 1998-2010 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef LEXACCESSOR_H -#define LEXACCESSOR_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -enum EncodingType { enc8bit, encUnicode, encDBCS }; - -class LexAccessor { -private: - IDocument *pAccess; - enum {extremePosition=0x7FFFFFFF}; - /** @a bufferSize is a trade off between time taken to copy the characters - * and retrieval overhead. - * @a slopSize positions the buffer before the desired position - * in case there is some backtracking. */ - enum {bufferSize=4000, slopSize=bufferSize/8}; - char buf[bufferSize+1]; - int startPos; - int endPos; - int codePage; - enum EncodingType encodingType; - int lenDoc; - char styleBuf[bufferSize]; - int validLen; - unsigned int startSeg; - int startPosStyling; - int documentVersion; - - void Fill(int position) { - startPos = position - slopSize; - if (startPos + bufferSize > lenDoc) - startPos = lenDoc - bufferSize; - if (startPos < 0) - startPos = 0; - endPos = startPos + bufferSize; - if (endPos > lenDoc) - endPos = lenDoc; - - pAccess->GetCharRange(buf, startPos, endPos-startPos); - buf[endPos-startPos] = '\0'; - } - -public: - explicit LexAccessor(IDocument *pAccess_) : - pAccess(pAccess_), startPos(extremePosition), endPos(0), - codePage(pAccess->CodePage()), - encodingType(enc8bit), - lenDoc(pAccess->Length()), - validLen(0), - startSeg(0), startPosStyling(0), - documentVersion(pAccess->Version()) { - // Prevent warnings by static analyzers about uninitialized buf and styleBuf. - buf[0] = 0; - styleBuf[0] = 0; - switch (codePage) { - case 65001: - encodingType = encUnicode; - break; - case 932: - case 936: - case 949: - case 950: - case 1361: - encodingType = encDBCS; - } - } - char operator[](int position) { - if (position < startPos || position >= endPos) { - Fill(position); - } - return buf[position - startPos]; - } - IDocumentWithLineEnd *MultiByteAccess() const { - if (documentVersion >= dvLineEnd) { - return static_cast(pAccess); - } - return 0; - } - /** Safe version of operator[], returning a defined value for invalid position. */ - char SafeGetCharAt(int position, char chDefault=' ') { - if (position < startPos || position >= endPos) { - Fill(position); - if (position < startPos || position >= endPos) { - // Position is outside range of document - return chDefault; - } - } - return buf[position - startPos]; - } - bool IsLeadByte(char ch) const { - return pAccess->IsDBCSLeadByte(ch); - } - EncodingType Encoding() const { - return encodingType; - } - bool Match(int pos, const char *s) { - for (int i=0; *s; i++) { - if (*s != SafeGetCharAt(pos+i)) - return false; - s++; - } - return true; - } - char StyleAt(int position) const { - return static_cast(pAccess->StyleAt(position)); - } - int GetLine(int position) const { - return pAccess->LineFromPosition(position); - } - int LineStart(int line) const { - return pAccess->LineStart(line); - } - int LineEnd(int line) { - if (documentVersion >= dvLineEnd) { - return (static_cast(pAccess))->LineEnd(line); - } else { - // Old interface means only '\r', '\n' and '\r\n' line ends. - int startNext = pAccess->LineStart(line+1); - char chLineEnd = SafeGetCharAt(startNext-1); - if (chLineEnd == '\n' && (SafeGetCharAt(startNext-2) == '\r')) - return startNext - 2; - else - return startNext - 1; - } - } - int LevelAt(int line) const { - return pAccess->GetLevel(line); - } - int Length() const { - return lenDoc; - } - void Flush() { - if (validLen > 0) { - pAccess->SetStyles(validLen, styleBuf); - startPosStyling += validLen; - validLen = 0; - } - } - int GetLineState(int line) const { - return pAccess->GetLineState(line); - } - int SetLineState(int line, int state) { - return pAccess->SetLineState(line, state); - } - // Style setting - void StartAt(unsigned int start) { - pAccess->StartStyling(start, '\377'); - startPosStyling = start; - } - unsigned int GetStartSegment() const { - return startSeg; - } - void StartSegment(unsigned int pos) { - startSeg = pos; - } - void ColourTo(unsigned int pos, int chAttr) { - // Only perform styling if non empty range - if (pos != startSeg - 1) { - assert(pos >= startSeg); - if (pos < startSeg) { - return; - } - - if (validLen + (pos - startSeg + 1) >= bufferSize) - Flush(); - if (validLen + (pos - startSeg + 1) >= bufferSize) { - // Too big for buffer so send directly - pAccess->SetStyleFor(pos - startSeg + 1, static_cast(chAttr)); - } else { - for (unsigned int i = startSeg; i <= pos; i++) { - assert((startPosStyling + validLen) < Length()); - styleBuf[validLen++] = static_cast(chAttr); - } - } - } - startSeg = pos+1; - } - void SetLevel(int line, int level) { - pAccess->SetLevel(line, level); - } - void IndicatorFill(int start, int end, int indicator, int value) { - pAccess->DecorationSetCurrentIndicator(indicator); - pAccess->DecorationFillRange(start, value, end - start); - } - - void ChangeLexerState(int start, int end) { - pAccess->ChangeLexerState(start, end); - } -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/lexlib/LexerBase.cpp b/libs/qscintilla/lexlib/LexerBase.cpp deleted file mode 100644 index bbef3f159..000000000 --- a/libs/qscintilla/lexlib/LexerBase.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// Scintilla source code edit control -/** @file LexerBase.cxx - ** A simple lexer with no state. - **/ -// Copyright 1998-2010 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "PropSetSimple.h" -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "LexerModule.h" -#include "LexerBase.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -LexerBase::LexerBase() { - for (int wl = 0; wl < numWordLists; wl++) - keyWordLists[wl] = new WordList; - keyWordLists[numWordLists] = 0; -} - -LexerBase::~LexerBase() { - for (int wl = 0; wl < numWordLists; wl++) { - delete keyWordLists[wl]; - keyWordLists[wl] = 0; - } - keyWordLists[numWordLists] = 0; -} - -void SCI_METHOD LexerBase::Release() { - delete this; -} - -int SCI_METHOD LexerBase::Version() const { - return lvOriginal; -} - -const char * SCI_METHOD LexerBase::PropertyNames() { - return ""; -} - -int SCI_METHOD LexerBase::PropertyType(const char *) { - return SC_TYPE_BOOLEAN; -} - -const char * SCI_METHOD LexerBase::DescribeProperty(const char *) { - return ""; -} - -int SCI_METHOD LexerBase::PropertySet(const char *key, const char *val) { - const char *valOld = props.Get(key); - if (strcmp(val, valOld) != 0) { - props.Set(key, val); - return 0; - } else { - return -1; - } -} - -const char * SCI_METHOD LexerBase::DescribeWordListSets() { - return ""; -} - -int SCI_METHOD LexerBase::WordListSet(int n, const char *wl) { - if (n < numWordLists) { - WordList wlNew; - wlNew.Set(wl); - if (*keyWordLists[n] != wlNew) { - keyWordLists[n]->Set(wl); - return 0; - } - } - return -1; -} - -void * SCI_METHOD LexerBase::PrivateCall(int, void *) { - return 0; -} diff --git a/libs/qscintilla/lexlib/LexerBase.h b/libs/qscintilla/lexlib/LexerBase.h deleted file mode 100644 index 2998d2449..000000000 --- a/libs/qscintilla/lexlib/LexerBase.h +++ /dev/null @@ -1,41 +0,0 @@ -// Scintilla source code edit control -/** @file LexerBase.h - ** A simple lexer with no state. - **/ -// Copyright 1998-2010 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef LEXERBASE_H -#define LEXERBASE_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -// A simple lexer with no state -class LexerBase : public ILexer { -protected: - PropSetSimple props; - enum {numWordLists=KEYWORDSET_MAX+1}; - WordList *keyWordLists[numWordLists+1]; -public: - LexerBase(); - virtual ~LexerBase(); - void SCI_METHOD Release(); - int SCI_METHOD Version() const; - const char * SCI_METHOD PropertyNames(); - int SCI_METHOD PropertyType(const char *name); - const char * SCI_METHOD DescribeProperty(const char *name); - int SCI_METHOD PropertySet(const char *key, const char *val); - const char * SCI_METHOD DescribeWordListSets(); - int SCI_METHOD WordListSet(int n, const char *wl); - void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0; - void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0; - void * SCI_METHOD PrivateCall(int operation, void *pointer); -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/lexlib/LexerModule.cpp b/libs/qscintilla/lexlib/LexerModule.cpp deleted file mode 100644 index 6cefbee77..000000000 --- a/libs/qscintilla/lexlib/LexerModule.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// Scintilla source code edit control -/** @file LexerModule.cxx - ** Colourise for particular languages. - **/ -// Copyright 1998-2010 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "PropSetSimple.h" -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "LexerModule.h" -#include "LexerBase.h" -#include "LexerSimple.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -LexerModule::LexerModule(int language_, - LexerFunction fnLexer_, - const char *languageName_, - LexerFunction fnFolder_, - const char *const wordListDescriptions_[]) : - language(language_), - fnLexer(fnLexer_), - fnFolder(fnFolder_), - fnFactory(0), - wordListDescriptions(wordListDescriptions_), - languageName(languageName_) { -} - -LexerModule::LexerModule(int language_, - LexerFactoryFunction fnFactory_, - const char *languageName_, - const char * const wordListDescriptions_[]) : - language(language_), - fnLexer(0), - fnFolder(0), - fnFactory(fnFactory_), - wordListDescriptions(wordListDescriptions_), - languageName(languageName_) { -} - -int LexerModule::GetNumWordLists() const { - if (wordListDescriptions == NULL) { - return -1; - } else { - int numWordLists = 0; - - while (wordListDescriptions[numWordLists]) { - ++numWordLists; - } - - return numWordLists; - } -} - -const char *LexerModule::GetWordListDescription(int index) const { - assert(index < GetNumWordLists()); - if (!wordListDescriptions || (index >= GetNumWordLists())) { - return ""; - } else { - return wordListDescriptions[index]; - } -} - -ILexer *LexerModule::Create() const { - if (fnFactory) - return fnFactory(); - else - return new LexerSimple(this); -} - -void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler) const { - if (fnLexer) - fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler); -} - -void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler) const { - if (fnFolder) { - int lineCurrent = styler.GetLine(startPos); - // Move back one line in case deletion wrecked current line fold state - if (lineCurrent > 0) { - lineCurrent--; - int newStartPos = styler.LineStart(lineCurrent); - lengthDoc += startPos - newStartPos; - startPos = newStartPos; - initStyle = 0; - if (startPos > 0) { - initStyle = styler.StyleAt(startPos - 1); - } - } - fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler); - } -} diff --git a/libs/qscintilla/lexlib/LexerModule.h b/libs/qscintilla/lexlib/LexerModule.h deleted file mode 100644 index 5993c0fe9..000000000 --- a/libs/qscintilla/lexlib/LexerModule.h +++ /dev/null @@ -1,82 +0,0 @@ -// Scintilla source code edit control -/** @file LexerModule.h - ** Colourise for particular languages. - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef LEXERMODULE_H -#define LEXERMODULE_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -class Accessor; -class WordList; - -typedef void (*LexerFunction)(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler); -typedef ILexer *(*LexerFactoryFunction)(); - -/** - * A LexerModule is responsible for lexing and folding a particular language. - * The class maintains a list of LexerModules which can be searched to find a - * module appropriate to a particular language. - */ -class LexerModule { -protected: - int language; - LexerFunction fnLexer; - LexerFunction fnFolder; - LexerFactoryFunction fnFactory; - const char * const * wordListDescriptions; - -public: - const char *languageName; - LexerModule(int language_, - LexerFunction fnLexer_, - const char *languageName_=0, - LexerFunction fnFolder_=0, - const char * const wordListDescriptions_[] = NULL); - LexerModule(int language_, - LexerFactoryFunction fnFactory_, - const char *languageName_, - const char * const wordListDescriptions_[] = NULL); - virtual ~LexerModule() { - } - int GetLanguage() const { return language; } - - // -1 is returned if no WordList information is available - int GetNumWordLists() const; - const char *GetWordListDescription(int index) const; - - ILexer *Create() const; - - virtual void Lex(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) const; - virtual void Fold(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) const; - - friend class Catalogue; -}; - -inline int Maximum(int a, int b) { - return (a > b) ? a : b; -} - -// Shut up annoying Visual C++ warnings: -#ifdef _MSC_VER -#pragma warning(disable: 4244 4309 4456 4457) -#endif - -// Turn off shadow warnings for lexers as may be maintained by others -#if defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wshadow" -#endif - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/lexlib/LexerNoExceptions.cpp b/libs/qscintilla/lexlib/LexerNoExceptions.cpp deleted file mode 100644 index 9ebae2af0..000000000 --- a/libs/qscintilla/lexlib/LexerNoExceptions.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// Scintilla source code edit control -/** @file LexerNoExceptions.cxx - ** A simple lexer with no state which does not throw exceptions so can be used in an external lexer. - **/ -// Copyright 1998-2010 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "PropSetSimple.h" -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "LexerModule.h" -#include "LexerBase.h" -#include "LexerNoExceptions.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -int SCI_METHOD LexerNoExceptions::PropertySet(const char *key, const char *val) { - try { - return LexerBase::PropertySet(key, val); - } catch (...) { - // Should not throw into caller as may be compiled with different compiler or options - } - return -1; -} - -int SCI_METHOD LexerNoExceptions::WordListSet(int n, const char *wl) { - try { - return LexerBase::WordListSet(n, wl); - } catch (...) { - // Should not throw into caller as may be compiled with different compiler or options - } - return -1; -} - -void SCI_METHOD LexerNoExceptions::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { - try { - Accessor astyler(pAccess, &props); - Lexer(startPos, length, initStyle, pAccess, astyler); - astyler.Flush(); - } catch (...) { - // Should not throw into caller as may be compiled with different compiler or options - pAccess->SetErrorStatus(SC_STATUS_FAILURE); - } -} -void SCI_METHOD LexerNoExceptions::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { - try { - Accessor astyler(pAccess, &props); - Folder(startPos, length, initStyle, pAccess, astyler); - astyler.Flush(); - } catch (...) { - // Should not throw into caller as may be compiled with different compiler or options - pAccess->SetErrorStatus(SC_STATUS_FAILURE); - } -} diff --git a/libs/qscintilla/lexlib/LexerNoExceptions.h b/libs/qscintilla/lexlib/LexerNoExceptions.h deleted file mode 100644 index 70ff3c138..000000000 --- a/libs/qscintilla/lexlib/LexerNoExceptions.h +++ /dev/null @@ -1,32 +0,0 @@ -// Scintilla source code edit control -/** @file LexerNoExceptions.h - ** A simple lexer with no state. - **/ -// Copyright 1998-2010 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef LEXERNOEXCEPTIONS_H -#define LEXERNOEXCEPTIONS_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -// A simple lexer with no state -class LexerNoExceptions : public LexerBase { -public: - // TODO Also need to prevent exceptions in constructor and destructor - int SCI_METHOD PropertySet(const char *key, const char *val); - int SCI_METHOD WordListSet(int n, const char *wl); - void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); - void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *); - - virtual void Lexer(unsigned int startPos, int length, int initStyle, IDocument *pAccess, Accessor &styler) = 0; - virtual void Folder(unsigned int startPos, int length, int initStyle, IDocument *pAccess, Accessor &styler) = 0; -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/lexlib/LexerSimple.cpp b/libs/qscintilla/lexlib/LexerSimple.cpp deleted file mode 100644 index 4d0e178ca..000000000 --- a/libs/qscintilla/lexlib/LexerSimple.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Scintilla source code edit control -/** @file LexerSimple.cxx - ** A simple lexer with no state. - **/ -// Copyright 1998-2010 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "PropSetSimple.h" -#include "WordList.h" -#include "LexAccessor.h" -#include "Accessor.h" -#include "LexerModule.h" -#include "LexerBase.h" -#include "LexerSimple.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -LexerSimple::LexerSimple(const LexerModule *module_) : module(module_) { - for (int wl = 0; wl < module->GetNumWordLists(); wl++) { - if (!wordLists.empty()) - wordLists += "\n"; - wordLists += module->GetWordListDescription(wl); - } -} - -const char * SCI_METHOD LexerSimple::DescribeWordListSets() { - return wordLists.c_str(); -} - -void SCI_METHOD LexerSimple::Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) { - Accessor astyler(pAccess, &props); - module->Lex(startPos, lengthDoc, initStyle, keyWordLists, astyler); - astyler.Flush(); -} - -void SCI_METHOD LexerSimple::Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) { - if (props.GetInt("fold")) { - Accessor astyler(pAccess, &props); - module->Fold(startPos, lengthDoc, initStyle, keyWordLists, astyler); - astyler.Flush(); - } -} diff --git a/libs/qscintilla/lexlib/LexerSimple.h b/libs/qscintilla/lexlib/LexerSimple.h deleted file mode 100644 index e9fa9003f..000000000 --- a/libs/qscintilla/lexlib/LexerSimple.h +++ /dev/null @@ -1,30 +0,0 @@ -// Scintilla source code edit control -/** @file LexerSimple.h - ** A simple lexer with no state. - **/ -// Copyright 1998-2010 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef LEXERSIMPLE_H -#define LEXERSIMPLE_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -// A simple lexer with no state -class LexerSimple : public LexerBase { - const LexerModule *module; - std::string wordLists; -public: - explicit LexerSimple(const LexerModule *module_); - const char * SCI_METHOD DescribeWordListSets(); - void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); - void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/lexlib/License.txt b/libs/qscintilla/lexlib/License.txt deleted file mode 100644 index cbe25b2fc..000000000 --- a/libs/qscintilla/lexlib/License.txt +++ /dev/null @@ -1,20 +0,0 @@ -License for Scintilla and SciTE - -Copyright 1998-2003 by Neil Hodgson - -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation. - -NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE -OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/libs/qscintilla/lexlib/StyleContext.cpp b/libs/qscintilla/lexlib/StyleContext.cpp deleted file mode 100644 index 9429c5ba8..000000000 --- a/libs/qscintilla/lexlib/StyleContext.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// Scintilla source code edit control -/** @file StyleContext.cxx - ** Lexer infrastructure. - **/ -// Copyright 1998-2004 by Neil Hodgson -// This file is in the public domain. - -#include -#include -#include -#include -#include - -#include "ILexer.h" - -#include "LexAccessor.h" -#include "Accessor.h" -#include "StyleContext.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static void getRange(unsigned int start, - unsigned int end, - LexAccessor &styler, - char *s, - unsigned int len) { - unsigned int i = 0; - while ((i < end - start + 1) && (i < len-1)) { - s[i] = styler[start + i]; - i++; - } - s[i] = '\0'; -} - -void StyleContext::GetCurrent(char *s, unsigned int len) { - getRange(styler.GetStartSegment(), currentPos - 1, styler, s, len); -} - -static void getRangeLowered(unsigned int start, - unsigned int end, - LexAccessor &styler, - char *s, - unsigned int len) { - unsigned int i = 0; - while ((i < end - start + 1) && (i < len-1)) { - s[i] = static_cast(tolower(styler[start + i])); - i++; - } - s[i] = '\0'; -} - -void StyleContext::GetCurrentLowered(char *s, unsigned int len) { - getRangeLowered(styler.GetStartSegment(), currentPos - 1, styler, s, len); -} diff --git a/libs/qscintilla/lexlib/StyleContext.h b/libs/qscintilla/lexlib/StyleContext.h deleted file mode 100644 index 837386cef..000000000 --- a/libs/qscintilla/lexlib/StyleContext.h +++ /dev/null @@ -1,231 +0,0 @@ -// Scintilla source code edit control -/** @file StyleContext.h - ** Lexer infrastructure. - **/ -// Copyright 1998-2004 by Neil Hodgson -// This file is in the public domain. - -#ifndef STYLECONTEXT_H -#define STYLECONTEXT_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -static inline int MakeLowerCase(int ch) { - if (ch < 'A' || ch > 'Z') - return ch; - else - return ch - 'A' + 'a'; -} - -// All languages handled so far can treat all characters >= 0x80 as one class -// which just continues the current token or starts an identifier if in default. -// DBCS treated specially as the second character can be < 0x80 and hence -// syntactically significant. UTF-8 avoids this as all trail bytes are >= 0x80 -class StyleContext { - LexAccessor &styler; - IDocumentWithLineEnd *multiByteAccess; - unsigned int endPos; - unsigned int lengthDocument; - - // Used for optimizing GetRelativeCharacter - unsigned int posRelative; - unsigned int currentPosLastRelative; - int offsetRelative; - - StyleContext &operator=(const StyleContext &); - - void GetNextChar() { - if (multiByteAccess) { - chNext = multiByteAccess->GetCharacterAndWidth(currentPos+width, &widthNext); - } else { - chNext = static_cast(styler.SafeGetCharAt(currentPos+width, 0)); - widthNext = 1; - } - // End of line determined from line end position, allowing CR, LF, - // CRLF and Unicode line ends as set by document. - if (currentLine < lineDocEnd) - atLineEnd = static_cast(currentPos) >= (lineStartNext-1); - else // Last line - atLineEnd = static_cast(currentPos) >= lineStartNext; - } - -public: - unsigned int currentPos; - int currentLine; - int lineDocEnd; - int lineStartNext; - bool atLineStart; - bool atLineEnd; - int state; - int chPrev; - int ch; - int width; - int chNext; - int widthNext; - - StyleContext(unsigned int startPos, unsigned int length, - int initStyle, LexAccessor &styler_, char chMask='\377') : - styler(styler_), - multiByteAccess(0), - endPos(startPos + length), - posRelative(0), - currentPosLastRelative(0x7FFFFFFF), - offsetRelative(0), - currentPos(startPos), - currentLine(-1), - lineStartNext(-1), - atLineEnd(false), - state(initStyle & chMask), // Mask off all bits which aren't in the chMask. - chPrev(0), - ch(0), - width(0), - chNext(0), - widthNext(1) { - if (styler.Encoding() != enc8bit) { - multiByteAccess = styler.MultiByteAccess(); - } - styler.StartAt(startPos /*, chMask*/); - styler.StartSegment(startPos); - currentLine = styler.GetLine(startPos); - lineStartNext = styler.LineStart(currentLine+1); - lengthDocument = static_cast(styler.Length()); - if (endPos == lengthDocument) - endPos++; - lineDocEnd = styler.GetLine(lengthDocument); - atLineStart = static_cast(styler.LineStart(currentLine)) == startPos; - - // Variable width is now 0 so GetNextChar gets the char at currentPos into chNext/widthNext - width = 0; - GetNextChar(); - ch = chNext; - width = widthNext; - - GetNextChar(); - } - void Complete() { - styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state); - styler.Flush(); - } - bool More() const { - return currentPos < endPos; - } - void Forward() { - if (currentPos < endPos) { - atLineStart = atLineEnd; - if (atLineStart) { - currentLine++; - lineStartNext = styler.LineStart(currentLine+1); - } - chPrev = ch; - currentPos += width; - ch = chNext; - width = widthNext; - GetNextChar(); - } else { - atLineStart = false; - chPrev = ' '; - ch = ' '; - chNext = ' '; - atLineEnd = true; - } - } - void Forward(int nb) { - for (int i = 0; i < nb; i++) { - Forward(); - } - } - void ForwardBytes(int nb) { - size_t forwardPos = currentPos + nb; - while (forwardPos > currentPos) { - Forward(); - } - } - void ChangeState(int state_) { - state = state_; - } - void SetState(int state_) { - styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state); - state = state_; - } - void ForwardSetState(int state_) { - Forward(); - styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state); - state = state_; - } - int LengthCurrent() const { - return currentPos - styler.GetStartSegment(); - } - int GetRelative(int n) { - return static_cast(styler.SafeGetCharAt(currentPos+n, 0)); - } - int GetRelativeCharacter(int n) { - if (n == 0) - return ch; - if (multiByteAccess) { - if ((currentPosLastRelative != currentPos) || - ((n > 0) && ((offsetRelative < 0) || (n < offsetRelative))) || - ((n < 0) && ((offsetRelative > 0) || (n > offsetRelative)))) { - posRelative = currentPos; - offsetRelative = 0; - } - int diffRelative = n - offsetRelative; - int posNew = multiByteAccess->GetRelativePosition(posRelative, diffRelative); - int chReturn = multiByteAccess->GetCharacterAndWidth(posNew, 0); - posRelative = posNew; - currentPosLastRelative = currentPos; - offsetRelative = n; - return chReturn; - } else { - // fast version for single byte encodings - return static_cast(styler.SafeGetCharAt(currentPos + n, 0)); - } - } - bool Match(char ch0) const { - return ch == static_cast(ch0); - } - bool Match(char ch0, char ch1) const { - return (ch == static_cast(ch0)) && (chNext == static_cast(ch1)); - } - bool Match(const char *s) { - if (ch != static_cast(*s)) - return false; - s++; - if (!*s) - return true; - if (chNext != static_cast(*s)) - return false; - s++; - for (int n=2; *s; n++) { - if (*s != styler.SafeGetCharAt(currentPos+n, 0)) - return false; - s++; - } - return true; - } - bool MatchIgnoreCase(const char *s) { - if (MakeLowerCase(ch) != static_cast(*s)) - return false; - s++; - if (MakeLowerCase(chNext) != static_cast(*s)) - return false; - s++; - for (int n=2; *s; n++) { - if (static_cast(*s) != - MakeLowerCase(static_cast(styler.SafeGetCharAt(currentPos+n, 0)))) - return false; - s++; - } - return true; - } - // Non-inline - void GetCurrent(char *s, unsigned int len); - void GetCurrentLowered(char *s, unsigned int len); -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/lexlib/WordList.cpp b/libs/qscintilla/lexlib/WordList.cpp deleted file mode 100644 index be7fda505..000000000 --- a/libs/qscintilla/lexlib/WordList.cpp +++ /dev/null @@ -1,242 +0,0 @@ -// Scintilla source code edit control -/** @file KeyWords.cxx - ** Colourise for particular languages. - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include - -#include "StringCopy.h" -#include "WordList.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/** - * Creates an array that points into each word in the string and puts \0 terminators - * after each word. - */ -static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = false) { - int prev = '\n'; - int words = 0; - // For rapid determination of whether a character is a separator, build - // a look up table. - bool wordSeparator[256]; - for (int i=0; i<256; i++) { - wordSeparator[i] = false; - } - wordSeparator[static_cast('\r')] = true; - wordSeparator[static_cast('\n')] = true; - if (!onlyLineEnds) { - wordSeparator[static_cast(' ')] = true; - wordSeparator[static_cast('\t')] = true; - } - for (int j = 0; wordlist[j]; j++) { - int curr = static_cast(wordlist[j]); - if (!wordSeparator[curr] && wordSeparator[prev]) - words++; - prev = curr; - } - char **keywords = new char *[words + 1]; - int wordsStore = 0; - const size_t slen = strlen(wordlist); - if (words) { - prev = '\0'; - for (size_t k = 0; k < slen; k++) { - if (!wordSeparator[static_cast(wordlist[k])]) { - if (!prev) { - keywords[wordsStore] = &wordlist[k]; - wordsStore++; - } - } else { - wordlist[k] = '\0'; - } - prev = wordlist[k]; - } - } - keywords[wordsStore] = &wordlist[slen]; - *len = wordsStore; - return keywords; -} - -WordList::WordList(bool onlyLineEnds_) : - words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) { - // Prevent warnings by static analyzers about uninitialized starts. - starts[0] = -1; -} - -WordList::~WordList() { - Clear(); -} - -WordList::operator bool() const { - return len ? true : false; -} - -bool WordList::operator!=(const WordList &other) const { - if (len != other.len) - return true; - for (int i=0; i(a), *static_cast(b)); -} - -static void SortWordList(char **words, unsigned int len) { - qsort(reinterpret_cast(words), len, sizeof(*words), cmpWords); -} - -#endif - -void WordList::Set(const char *s) { - Clear(); - const size_t lenS = strlen(s) + 1; - list = new char[lenS]; - memcpy(list, s, lenS); - words = ArrayFromWordList(list, &len, onlyLineEnds); -#ifdef _MSC_VER - std::sort(words, words + len, cmpWords); -#else - SortWordList(words, len); -#endif - for (unsigned int k = 0; k < ELEMENTS(starts); k++) - starts[k] = -1; - for (int l = len - 1; l >= 0; l--) { - unsigned char indexChar = words[l][0]; - starts[indexChar] = l; - } -} - -/** Check whether a string is in the list. - * List elements are either exact matches or prefixes. - * Prefix elements start with '^' and match all strings that start with the rest of the element - * so '^GTK_' matches 'GTK_X', 'GTK_MAJOR_VERSION', and 'GTK_'. - */ -bool WordList::InList(const char *s) const { - if (0 == words) - return false; - unsigned char firstChar = s[0]; - int j = starts[firstChar]; - if (j >= 0) { - while (static_cast(words[j][0]) == firstChar) { - if (s[1] == words[j][1]) { - const char *a = words[j] + 1; - const char *b = s + 1; - while (*a && *a == *b) { - a++; - b++; - } - if (!*a && !*b) - return true; - } - j++; - } - } - j = starts[static_cast('^')]; - if (j >= 0) { - while (words[j][0] == '^') { - const char *a = words[j] + 1; - const char *b = s; - while (*a && *a == *b) { - a++; - b++; - } - if (!*a) - return true; - j++; - } - } - return false; -} - -/** similar to InList, but word s can be a substring of keyword. - * eg. the keyword define is defined as def~ine. This means the word must start - * with def to be a keyword, but also defi, defin and define are valid. - * The marker is ~ in this case. - */ -bool WordList::InListAbbreviated(const char *s, const char marker) const { - if (0 == words) - return false; - unsigned char firstChar = s[0]; - int j = starts[firstChar]; - if (j >= 0) { - while (static_cast(words[j][0]) == firstChar) { - bool isSubword = false; - int start = 1; - if (words[j][1] == marker) { - isSubword = true; - start++; - } - if (s[1] == words[j][start]) { - const char *a = words[j] + start; - const char *b = s + 1; - while (*a && *a == *b) { - a++; - if (*a == marker) { - isSubword = true; - a++; - } - b++; - } - if ((!*a || isSubword) && !*b) - return true; - } - j++; - } - } - j = starts[static_cast('^')]; - if (j >= 0) { - while (words[j][0] == '^') { - const char *a = words[j] + 1; - const char *b = s; - while (*a && *a == *b) { - a++; - b++; - } - if (!*a) - return true; - j++; - } - } - return false; -} - -const char *WordList::WordAt(int n) const { - return words[n]; -} - diff --git a/libs/qscintilla/src/CaseConvert.cpp b/libs/qscintilla/src/CaseConvert.cpp deleted file mode 100644 index e8f533d5c..000000000 --- a/libs/qscintilla/src/CaseConvert.cpp +++ /dev/null @@ -1,634 +0,0 @@ -// Scintilla source code edit control -// Encoding: UTF-8 -/** @file CaseConvert.cxx - ** Case fold characters and convert them to upper or lower case. - ** Tables automatically regenerated by scripts/GenerateCaseConvert.py - ** Should only be rarely regenerated for new versions of Unicode. - **/ -// Copyright 2013 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include - -#include -#include - -#include "StringCopy.h" -#include "CaseConvert.h" -#include "UniConversion.h" -#include "UnicodeFromUTF8.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -namespace { - // Use an unnamed namespace to protect the declarations from name conflicts - -// Unicode code points are ordered by groups and follow patterns. -// Most characters (pitch==1) are in ranges for a particular alphabet and their -// upper case forms are a fixed distance away. -// Another pattern (pitch==2) is where each lower case letter is preceded by -// the upper case form. These are also grouped into ranges. - -int symmetricCaseConversionRanges[] = { -//lower, upper, range length, range pitch -//++Autogenerated -- start of section automatically generated -//**\(\*\n\) -97,65,26,1, -224,192,23,1, -248,216,7,1, -257,256,24,2, -314,313,8,2, -331,330,23,2, -462,461,8,2, -479,478,9,2, -505,504,20,2, -547,546,9,2, -583,582,5,2, -945,913,17,1, -963,931,9,1, -985,984,12,2, -1072,1040,32,1, -1104,1024,16,1, -1121,1120,17,2, -1163,1162,27,2, -1218,1217,7,2, -1233,1232,44,2, -1377,1329,38,1, -7681,7680,75,2, -7841,7840,48,2, -7936,7944,8,1, -7952,7960,6,1, -7968,7976,8,1, -7984,7992,8,1, -8000,8008,6,1, -8032,8040,8,1, -8560,8544,16,1, -9424,9398,26,1, -11312,11264,47,1, -11393,11392,50,2, -11520,4256,38,1, -42561,42560,23,2, -42625,42624,12,2, -42787,42786,7,2, -42803,42802,31,2, -42879,42878,5,2, -42913,42912,5,2, -65345,65313,26,1, -66600,66560,40,1, - -//--Autogenerated -- end of section automatically generated -}; - -// Code points that are symmetric but don't fit into a range of similar characters -// are listed here. - -int symmetricCaseConversions[] = { -//lower, upper -//++Autogenerated -- start of section automatically generated -//**1 \(\*\n\) -255,376, -307,306, -309,308, -311,310, -378,377, -380,379, -382,381, -384,579, -387,386, -389,388, -392,391, -396,395, -402,401, -405,502, -409,408, -410,573, -414,544, -417,416, -419,418, -421,420, -424,423, -429,428, -432,431, -436,435, -438,437, -441,440, -445,444, -447,503, -454,452, -457,455, -460,458, -477,398, -499,497, -501,500, -572,571, -575,11390, -576,11391, -578,577, -592,11375, -593,11373, -594,11376, -595,385, -596,390, -598,393, -599,394, -601,399, -603,400, -608,403, -611,404, -613,42893, -614,42922, -616,407, -617,406, -619,11362, -623,412, -625,11374, -626,413, -629,415, -637,11364, -640,422, -643,425, -648,430, -649,580, -650,433, -651,434, -652,581, -658,439, -881,880, -883,882, -887,886, -891,1021, -892,1022, -893,1023, -940,902, -941,904, -942,905, -943,906, -972,908, -973,910, -974,911, -983,975, -1010,1017, -1016,1015, -1019,1018, -1231,1216, -7545,42877, -7549,11363, -8017,8025, -8019,8027, -8021,8029, -8023,8031, -8048,8122, -8049,8123, -8050,8136, -8051,8137, -8052,8138, -8053,8139, -8054,8154, -8055,8155, -8056,8184, -8057,8185, -8058,8170, -8059,8171, -8060,8186, -8061,8187, -8112,8120, -8113,8121, -8144,8152, -8145,8153, -8160,8168, -8161,8169, -8165,8172, -8526,8498, -8580,8579, -11361,11360, -11365,570, -11366,574, -11368,11367, -11370,11369, -11372,11371, -11379,11378, -11382,11381, -11500,11499, -11502,11501, -11507,11506, -11559,4295, -11565,4301, -42874,42873, -42876,42875, -42892,42891, -42897,42896, -42899,42898, - -//--Autogenerated -- end of section automatically generated -}; - -// Characters that have complex case conversions are listed here. -// This includes cases where more than one character is needed for a conversion, -// folding is different to lowering, or (as appropriate) upper(lower(x)) != x or -// lower(upper(x)) != x. - -const char *complexCaseConversions = -// Original | Folded | Upper | Lower | -//++Autogenerated -- start of section automatically generated -//**2 \(\*\n\) -"\xc2\xb5|\xce\xbc|\xce\x9c||" -"\xc3\x9f|ss|SS||" -"\xc4\xb0|i\xcc\x87||i\xcc\x87|" -"\xc4\xb1||I||" -"\xc5\x89|\xca\xbcn|\xca\xbcN||" -"\xc5\xbf|s|S||" -"\xc7\x85|\xc7\x86|\xc7\x84|\xc7\x86|" -"\xc7\x88|\xc7\x89|\xc7\x87|\xc7\x89|" -"\xc7\x8b|\xc7\x8c|\xc7\x8a|\xc7\x8c|" -"\xc7\xb0|j\xcc\x8c|J\xcc\x8c||" -"\xc7\xb2|\xc7\xb3|\xc7\xb1|\xc7\xb3|" -"\xcd\x85|\xce\xb9|\xce\x99||" -"\xce\x90|\xce\xb9\xcc\x88\xcc\x81|\xce\x99\xcc\x88\xcc\x81||" -"\xce\xb0|\xcf\x85\xcc\x88\xcc\x81|\xce\xa5\xcc\x88\xcc\x81||" -"\xcf\x82|\xcf\x83|\xce\xa3||" -"\xcf\x90|\xce\xb2|\xce\x92||" -"\xcf\x91|\xce\xb8|\xce\x98||" -"\xcf\x95|\xcf\x86|\xce\xa6||" -"\xcf\x96|\xcf\x80|\xce\xa0||" -"\xcf\xb0|\xce\xba|\xce\x9a||" -"\xcf\xb1|\xcf\x81|\xce\xa1||" -"\xcf\xb4|\xce\xb8||\xce\xb8|" -"\xcf\xb5|\xce\xb5|\xce\x95||" -"\xd6\x87|\xd5\xa5\xd6\x82|\xd4\xb5\xd5\x92||" -"\xe1\xba\x96|h\xcc\xb1|H\xcc\xb1||" -"\xe1\xba\x97|t\xcc\x88|T\xcc\x88||" -"\xe1\xba\x98|w\xcc\x8a|W\xcc\x8a||" -"\xe1\xba\x99|y\xcc\x8a|Y\xcc\x8a||" -"\xe1\xba\x9a|a\xca\xbe|A\xca\xbe||" -"\xe1\xba\x9b|\xe1\xb9\xa1|\xe1\xb9\xa0||" -"\xe1\xba\x9e|ss||\xc3\x9f|" -"\xe1\xbd\x90|\xcf\x85\xcc\x93|\xce\xa5\xcc\x93||" -"\xe1\xbd\x92|\xcf\x85\xcc\x93\xcc\x80|\xce\xa5\xcc\x93\xcc\x80||" -"\xe1\xbd\x94|\xcf\x85\xcc\x93\xcc\x81|\xce\xa5\xcc\x93\xcc\x81||" -"\xe1\xbd\x96|\xcf\x85\xcc\x93\xcd\x82|\xce\xa5\xcc\x93\xcd\x82||" -"\xe1\xbe\x80|\xe1\xbc\x80\xce\xb9|\xe1\xbc\x88\xce\x99||" -"\xe1\xbe\x81|\xe1\xbc\x81\xce\xb9|\xe1\xbc\x89\xce\x99||" -"\xe1\xbe\x82|\xe1\xbc\x82\xce\xb9|\xe1\xbc\x8a\xce\x99||" -"\xe1\xbe\x83|\xe1\xbc\x83\xce\xb9|\xe1\xbc\x8b\xce\x99||" -"\xe1\xbe\x84|\xe1\xbc\x84\xce\xb9|\xe1\xbc\x8c\xce\x99||" -"\xe1\xbe\x85|\xe1\xbc\x85\xce\xb9|\xe1\xbc\x8d\xce\x99||" -"\xe1\xbe\x86|\xe1\xbc\x86\xce\xb9|\xe1\xbc\x8e\xce\x99||" -"\xe1\xbe\x87|\xe1\xbc\x87\xce\xb9|\xe1\xbc\x8f\xce\x99||" -"\xe1\xbe\x88|\xe1\xbc\x80\xce\xb9|\xe1\xbc\x88\xce\x99|\xe1\xbe\x80|" -"\xe1\xbe\x89|\xe1\xbc\x81\xce\xb9|\xe1\xbc\x89\xce\x99|\xe1\xbe\x81|" -"\xe1\xbe\x8a|\xe1\xbc\x82\xce\xb9|\xe1\xbc\x8a\xce\x99|\xe1\xbe\x82|" -"\xe1\xbe\x8b|\xe1\xbc\x83\xce\xb9|\xe1\xbc\x8b\xce\x99|\xe1\xbe\x83|" -"\xe1\xbe\x8c|\xe1\xbc\x84\xce\xb9|\xe1\xbc\x8c\xce\x99|\xe1\xbe\x84|" -"\xe1\xbe\x8d|\xe1\xbc\x85\xce\xb9|\xe1\xbc\x8d\xce\x99|\xe1\xbe\x85|" -"\xe1\xbe\x8e|\xe1\xbc\x86\xce\xb9|\xe1\xbc\x8e\xce\x99|\xe1\xbe\x86|" -"\xe1\xbe\x8f|\xe1\xbc\x87\xce\xb9|\xe1\xbc\x8f\xce\x99|\xe1\xbe\x87|" -"\xe1\xbe\x90|\xe1\xbc\xa0\xce\xb9|\xe1\xbc\xa8\xce\x99||" -"\xe1\xbe\x91|\xe1\xbc\xa1\xce\xb9|\xe1\xbc\xa9\xce\x99||" -"\xe1\xbe\x92|\xe1\xbc\xa2\xce\xb9|\xe1\xbc\xaa\xce\x99||" -"\xe1\xbe\x93|\xe1\xbc\xa3\xce\xb9|\xe1\xbc\xab\xce\x99||" -"\xe1\xbe\x94|\xe1\xbc\xa4\xce\xb9|\xe1\xbc\xac\xce\x99||" -"\xe1\xbe\x95|\xe1\xbc\xa5\xce\xb9|\xe1\xbc\xad\xce\x99||" -"\xe1\xbe\x96|\xe1\xbc\xa6\xce\xb9|\xe1\xbc\xae\xce\x99||" -"\xe1\xbe\x97|\xe1\xbc\xa7\xce\xb9|\xe1\xbc\xaf\xce\x99||" -"\xe1\xbe\x98|\xe1\xbc\xa0\xce\xb9|\xe1\xbc\xa8\xce\x99|\xe1\xbe\x90|" -"\xe1\xbe\x99|\xe1\xbc\xa1\xce\xb9|\xe1\xbc\xa9\xce\x99|\xe1\xbe\x91|" -"\xe1\xbe\x9a|\xe1\xbc\xa2\xce\xb9|\xe1\xbc\xaa\xce\x99|\xe1\xbe\x92|" -"\xe1\xbe\x9b|\xe1\xbc\xa3\xce\xb9|\xe1\xbc\xab\xce\x99|\xe1\xbe\x93|" -"\xe1\xbe\x9c|\xe1\xbc\xa4\xce\xb9|\xe1\xbc\xac\xce\x99|\xe1\xbe\x94|" -"\xe1\xbe\x9d|\xe1\xbc\xa5\xce\xb9|\xe1\xbc\xad\xce\x99|\xe1\xbe\x95|" -"\xe1\xbe\x9e|\xe1\xbc\xa6\xce\xb9|\xe1\xbc\xae\xce\x99|\xe1\xbe\x96|" -"\xe1\xbe\x9f|\xe1\xbc\xa7\xce\xb9|\xe1\xbc\xaf\xce\x99|\xe1\xbe\x97|" -"\xe1\xbe\xa0|\xe1\xbd\xa0\xce\xb9|\xe1\xbd\xa8\xce\x99||" -"\xe1\xbe\xa1|\xe1\xbd\xa1\xce\xb9|\xe1\xbd\xa9\xce\x99||" -"\xe1\xbe\xa2|\xe1\xbd\xa2\xce\xb9|\xe1\xbd\xaa\xce\x99||" -"\xe1\xbe\xa3|\xe1\xbd\xa3\xce\xb9|\xe1\xbd\xab\xce\x99||" -"\xe1\xbe\xa4|\xe1\xbd\xa4\xce\xb9|\xe1\xbd\xac\xce\x99||" -"\xe1\xbe\xa5|\xe1\xbd\xa5\xce\xb9|\xe1\xbd\xad\xce\x99||" -"\xe1\xbe\xa6|\xe1\xbd\xa6\xce\xb9|\xe1\xbd\xae\xce\x99||" -"\xe1\xbe\xa7|\xe1\xbd\xa7\xce\xb9|\xe1\xbd\xaf\xce\x99||" -"\xe1\xbe\xa8|\xe1\xbd\xa0\xce\xb9|\xe1\xbd\xa8\xce\x99|\xe1\xbe\xa0|" -"\xe1\xbe\xa9|\xe1\xbd\xa1\xce\xb9|\xe1\xbd\xa9\xce\x99|\xe1\xbe\xa1|" -"\xe1\xbe\xaa|\xe1\xbd\xa2\xce\xb9|\xe1\xbd\xaa\xce\x99|\xe1\xbe\xa2|" -"\xe1\xbe\xab|\xe1\xbd\xa3\xce\xb9|\xe1\xbd\xab\xce\x99|\xe1\xbe\xa3|" -"\xe1\xbe\xac|\xe1\xbd\xa4\xce\xb9|\xe1\xbd\xac\xce\x99|\xe1\xbe\xa4|" -"\xe1\xbe\xad|\xe1\xbd\xa5\xce\xb9|\xe1\xbd\xad\xce\x99|\xe1\xbe\xa5|" -"\xe1\xbe\xae|\xe1\xbd\xa6\xce\xb9|\xe1\xbd\xae\xce\x99|\xe1\xbe\xa6|" -"\xe1\xbe\xaf|\xe1\xbd\xa7\xce\xb9|\xe1\xbd\xaf\xce\x99|\xe1\xbe\xa7|" -"\xe1\xbe\xb2|\xe1\xbd\xb0\xce\xb9|\xe1\xbe\xba\xce\x99||" -"\xe1\xbe\xb3|\xce\xb1\xce\xb9|\xce\x91\xce\x99||" -"\xe1\xbe\xb4|\xce\xac\xce\xb9|\xce\x86\xce\x99||" -"\xe1\xbe\xb6|\xce\xb1\xcd\x82|\xce\x91\xcd\x82||" -"\xe1\xbe\xb7|\xce\xb1\xcd\x82\xce\xb9|\xce\x91\xcd\x82\xce\x99||" -"\xe1\xbe\xbc|\xce\xb1\xce\xb9|\xce\x91\xce\x99|\xe1\xbe\xb3|" -"\xe1\xbe\xbe|\xce\xb9|\xce\x99||" -"\xe1\xbf\x82|\xe1\xbd\xb4\xce\xb9|\xe1\xbf\x8a\xce\x99||" -"\xe1\xbf\x83|\xce\xb7\xce\xb9|\xce\x97\xce\x99||" -"\xe1\xbf\x84|\xce\xae\xce\xb9|\xce\x89\xce\x99||" -"\xe1\xbf\x86|\xce\xb7\xcd\x82|\xce\x97\xcd\x82||" -"\xe1\xbf\x87|\xce\xb7\xcd\x82\xce\xb9|\xce\x97\xcd\x82\xce\x99||" -"\xe1\xbf\x8c|\xce\xb7\xce\xb9|\xce\x97\xce\x99|\xe1\xbf\x83|" -"\xe1\xbf\x92|\xce\xb9\xcc\x88\xcc\x80|\xce\x99\xcc\x88\xcc\x80||" -"\xe1\xbf\x93|\xce\xb9\xcc\x88\xcc\x81|\xce\x99\xcc\x88\xcc\x81||" -"\xe1\xbf\x96|\xce\xb9\xcd\x82|\xce\x99\xcd\x82||" -"\xe1\xbf\x97|\xce\xb9\xcc\x88\xcd\x82|\xce\x99\xcc\x88\xcd\x82||" -"\xe1\xbf\xa2|\xcf\x85\xcc\x88\xcc\x80|\xce\xa5\xcc\x88\xcc\x80||" -"\xe1\xbf\xa3|\xcf\x85\xcc\x88\xcc\x81|\xce\xa5\xcc\x88\xcc\x81||" -"\xe1\xbf\xa4|\xcf\x81\xcc\x93|\xce\xa1\xcc\x93||" -"\xe1\xbf\xa6|\xcf\x85\xcd\x82|\xce\xa5\xcd\x82||" -"\xe1\xbf\xa7|\xcf\x85\xcc\x88\xcd\x82|\xce\xa5\xcc\x88\xcd\x82||" -"\xe1\xbf\xb2|\xe1\xbd\xbc\xce\xb9|\xe1\xbf\xba\xce\x99||" -"\xe1\xbf\xb3|\xcf\x89\xce\xb9|\xce\xa9\xce\x99||" -"\xe1\xbf\xb4|\xcf\x8e\xce\xb9|\xce\x8f\xce\x99||" -"\xe1\xbf\xb6|\xcf\x89\xcd\x82|\xce\xa9\xcd\x82||" -"\xe1\xbf\xb7|\xcf\x89\xcd\x82\xce\xb9|\xce\xa9\xcd\x82\xce\x99||" -"\xe1\xbf\xbc|\xcf\x89\xce\xb9|\xce\xa9\xce\x99|\xe1\xbf\xb3|" -"\xe2\x84\xa6|\xcf\x89||\xcf\x89|" -"\xe2\x84\xaa|k||k|" -"\xe2\x84\xab|\xc3\xa5||\xc3\xa5|" -"\xef\xac\x80|ff|FF||" -"\xef\xac\x81|fi|FI||" -"\xef\xac\x82|fl|FL||" -"\xef\xac\x83|ffi|FFI||" -"\xef\xac\x84|ffl|FFL||" -"\xef\xac\x85|st|ST||" -"\xef\xac\x86|st|ST||" -"\xef\xac\x93|\xd5\xb4\xd5\xb6|\xd5\x84\xd5\x86||" -"\xef\xac\x94|\xd5\xb4\xd5\xa5|\xd5\x84\xd4\xb5||" -"\xef\xac\x95|\xd5\xb4\xd5\xab|\xd5\x84\xd4\xbb||" -"\xef\xac\x96|\xd5\xbe\xd5\xb6|\xd5\x8e\xd5\x86||" -"\xef\xac\x97|\xd5\xb4\xd5\xad|\xd5\x84\xd4\xbd||" - -//--Autogenerated -- end of section automatically generated -; - -class CaseConverter : public ICaseConverter { - // Maximum length of a case conversion result is 6 bytes in UTF-8 - enum { maxConversionLength=6 }; - struct ConversionString { - char conversion[maxConversionLength+1]; - ConversionString() { - conversion[0] = '\0'; - } - }; - // Conversions are initially store in a vector of structs but then decomposed into - // parallel arrays as that is about 10% faster to search. - struct CharacterConversion { - int character; - ConversionString conversion; - CharacterConversion(int character_=0, const char *conversion_="") : character(character_) { - StringCopy(conversion.conversion, conversion_); - } - bool operator<(const CharacterConversion &other) const { - return character < other.character; - } - }; - typedef std::vector CharacterToConversion; - CharacterToConversion characterToConversion; - // The parallel arrays - std::vector characters; - std::vector conversions; - -public: - CaseConverter() { - } - bool Initialised() const { - return characters.size() > 0; - } - void Add(int character, const char *conversion) { - characterToConversion.push_back(CharacterConversion(character, conversion)); - } - const char *Find(int character) { - const std::vector::iterator it = std::lower_bound(characters.begin(), characters.end(), character); - if (it == characters.end()) - return 0; - else if (*it == character) - return conversions[it - characters.begin()].conversion; - else - return 0; - } - size_t CaseConvertString(char *converted, size_t sizeConverted, const char *mixed, size_t lenMixed) { - size_t lenConverted = 0; - size_t mixedPos = 0; - unsigned char bytes[UTF8MaxBytes + 1]; - while (mixedPos < lenMixed) { - const unsigned char leadByte = static_cast(mixed[mixedPos]); - const char *caseConverted = 0; - size_t lenMixedChar = 1; - if (UTF8IsAscii(leadByte)) { - caseConverted = Find(leadByte); - } else { - bytes[0] = leadByte; - const int widthCharBytes = UTF8BytesOfLead[leadByte]; - for (int b=1; b= sizeConverted) - return 0; - } - } else { - // Character has no conversion so copy the input to output - for (size_t i=0; i= sizeConverted) - return 0; - } - } - mixedPos += lenMixedChar; - } - return lenConverted; - } - void FinishedAdding() { - std::sort(characterToConversion.begin(), characterToConversion.end()); - characters.reserve(characterToConversion.size()); - conversions.reserve(characterToConversion.size()); - for (CharacterToConversion::iterator it = characterToConversion.begin(); it != characterToConversion.end(); ++it) { - characters.push_back(it->character); - conversions.push_back(it->conversion); - } - // Empty the original calculated data completely - CharacterToConversion().swap(characterToConversion); - } -}; - -CaseConverter caseConvFold; -CaseConverter caseConvUp; -CaseConverter caseConvLow; - -void UTF8FromUTF32Character(int uch, char *putf) { - size_t k = 0; - if (uch < 0x80) { - putf[k++] = static_cast(uch); - } else if (uch < 0x800) { - putf[k++] = static_cast(0xC0 | (uch >> 6)); - putf[k++] = static_cast(0x80 | (uch & 0x3f)); - } else if (uch < 0x10000) { - putf[k++] = static_cast(0xE0 | (uch >> 12)); - putf[k++] = static_cast(0x80 | ((uch >> 6) & 0x3f)); - putf[k++] = static_cast(0x80 | (uch & 0x3f)); - } else { - putf[k++] = static_cast(0xF0 | (uch >> 18)); - putf[k++] = static_cast(0x80 | ((uch >> 12) & 0x3f)); - putf[k++] = static_cast(0x80 | ((uch >> 6) & 0x3f)); - putf[k++] = static_cast(0x80 | (uch & 0x3f)); - } - putf[k] = 0; -} - -void AddSymmetric(enum CaseConversion conversion, int lower,int upper) { - char lowerUTF8[UTF8MaxBytes+1]; - UTF8FromUTF32Character(lower, lowerUTF8); - char upperUTF8[UTF8MaxBytes+1]; - UTF8FromUTF32Character(upper, upperUTF8); - - switch (conversion) { - case CaseConversionFold: - caseConvFold.Add(upper, lowerUTF8); - break; - case CaseConversionUpper: - caseConvUp.Add(lower, upperUTF8); - break; - case CaseConversionLower: - caseConvLow.Add(upper, lowerUTF8); - break; - } -} - -void SetupConversions(enum CaseConversion conversion) { - // First initialize for the symmetric ranges - for (size_t i=0; i(originUTF8)); - - if (conversion == CaseConversionFold && foldedUTF8[0]) { - caseConvFold.Add(character, foldedUTF8); - } - - if (conversion == CaseConversionUpper && upperUTF8[0]) { - caseConvUp.Add(character, upperUTF8); - } - - if (conversion == CaseConversionLower && lowerUTF8[0]) { - caseConvLow.Add(character, lowerUTF8); - } - } - - switch (conversion) { - case CaseConversionFold: - caseConvFold.FinishedAdding(); - break; - case CaseConversionUpper: - caseConvUp.FinishedAdding(); - break; - case CaseConversionLower: - caseConvLow.FinishedAdding(); - break; - } -} - -CaseConverter *ConverterForConversion(enum CaseConversion conversion) { - switch (conversion) { - case CaseConversionFold: - return &caseConvFold; - case CaseConversionUpper: - return &caseConvUp; - case CaseConversionLower: - return &caseConvLow; - } - return 0; -} - -} - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -ICaseConverter *ConverterFor(enum CaseConversion conversion) { - CaseConverter *pCaseConv = ConverterForConversion(conversion); - if (!pCaseConv->Initialised()) - SetupConversions(conversion); - return pCaseConv; -} - -const char *CaseConvert(int character, enum CaseConversion conversion) { - CaseConverter *pCaseConv = ConverterForConversion(conversion); - if (!pCaseConv->Initialised()) - SetupConversions(conversion); - return pCaseConv->Find(character); -} - -size_t CaseConvertString(char *converted, size_t sizeConverted, const char *mixed, size_t lenMixed, enum CaseConversion conversion) { - CaseConverter *pCaseConv = ConverterForConversion(conversion); - if (!pCaseConv->Initialised()) - SetupConversions(conversion); - return pCaseConv->CaseConvertString(converted, sizeConverted, mixed, lenMixed); -} - -#ifdef SCI_NAMESPACE -} -#endif diff --git a/libs/qscintilla/src/CaseFolder.h b/libs/qscintilla/src/CaseFolder.h deleted file mode 100644 index 2d754d4f3..000000000 --- a/libs/qscintilla/src/CaseFolder.h +++ /dev/null @@ -1,45 +0,0 @@ -// Scintilla source code edit control -/** @file CaseFolder.h - ** Classes for case folding. - **/ -// Copyright 1998-2013 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef CASEFOLDER_H -#define CASEFOLDER_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -class CaseFolder { -public: - virtual ~CaseFolder(); - virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) = 0; -}; - -class CaseFolderTable : public CaseFolder { -protected: - char mapping[256]; -public: - CaseFolderTable(); - virtual ~CaseFolderTable(); - virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed); - void SetTranslation(char ch, char chTranslation); - void StandardASCII(); -}; - -class ICaseConverter; - -class CaseFolderUnicode : public CaseFolderTable { - ICaseConverter *converter; -public: - CaseFolderUnicode(); - virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed); -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/Catalogue.cpp b/libs/qscintilla/src/Catalogue.cpp deleted file mode 100644 index c318d1874..000000000 --- a/libs/qscintilla/src/Catalogue.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// Scintilla source code edit control -/** @file Catalogue.cxx - ** Colourise for particular languages. - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "LexerModule.h" -#include "Catalogue.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static std::vector lexerCatalogue; -static int nextLanguage = SCLEX_AUTOMATIC+1; - -const LexerModule *Catalogue::Find(int language) { - Scintilla_LinkLexers(); - for (std::vector::iterator it=lexerCatalogue.begin(); - it != lexerCatalogue.end(); ++it) { - if ((*it)->GetLanguage() == language) { - return *it; - } - } - return 0; -} - -const LexerModule *Catalogue::Find(const char *languageName) { - Scintilla_LinkLexers(); - if (languageName) { - for (std::vector::iterator it=lexerCatalogue.begin(); - it != lexerCatalogue.end(); ++it) { - if ((*it)->languageName && (0 == strcmp((*it)->languageName, languageName))) { - return *it; - } - } - } - return 0; -} - -void Catalogue::AddLexerModule(LexerModule *plm) { - if (plm->GetLanguage() == SCLEX_AUTOMATIC) { - plm->language = nextLanguage; - nextLanguage++; - } - lexerCatalogue.push_back(plm); -} - -// To add or remove a lexer, add or remove its file and run LexGen.py. - -// Force a reference to all of the Scintilla lexers so that the linker will -// not remove the code of the lexers. -int Scintilla_LinkLexers() { - - static int initialised = 0; - if (initialised) - return 0; - initialised = 1; - -// Shorten the code that declares a lexer and ensures it is linked in by calling a method. -#define LINK_LEXER(lexer) extern LexerModule lexer; Catalogue::AddLexerModule(&lexer); - -//++Autogenerated -- run scripts/LexGen.py to regenerate -//**\(\tLINK_LEXER(\*);\n\) - LINK_LEXER(lmSQL); - -//--Autogenerated -- end of automatically generated section - - return 1; -} diff --git a/libs/qscintilla/src/CellBuffer.cpp b/libs/qscintilla/src/CellBuffer.cpp deleted file mode 100644 index dfa1350c0..000000000 --- a/libs/qscintilla/src/CellBuffer.cpp +++ /dev/null @@ -1,822 +0,0 @@ -// Scintilla source code edit control -/** @file CellBuffer.cxx - ** Manages a buffer of cells. - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include - -#include -#include - -#include "Platform.h" - -#include "Scintilla.h" -#include "SplitVector.h" -#include "Partitioning.h" -#include "CellBuffer.h" -#include "UniConversion.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -LineVector::LineVector() : starts(256), perLine(0) { - Init(); -} - -LineVector::~LineVector() { - starts.DeleteAll(); -} - -void LineVector::Init() { - starts.DeleteAll(); - if (perLine) { - perLine->Init(); - } -} - -void LineVector::SetPerLine(PerLine *pl) { - perLine = pl; -} - -void LineVector::InsertText(int line, int delta) { - starts.InsertText(line, delta); -} - -void LineVector::InsertLine(int line, int position, bool lineStart) { - starts.InsertPartition(line, position); - if (perLine) { - if ((line > 0) && lineStart) - line--; - perLine->InsertLine(line); - } -} - -void LineVector::SetLineStart(int line, int position) { - starts.SetPartitionStartPosition(line, position); -} - -void LineVector::RemoveLine(int line) { - starts.RemovePartition(line); - if (perLine) { - perLine->RemoveLine(line); - } -} - -int LineVector::LineFromPosition(int pos) const { - return starts.PartitionFromPosition(pos); -} - -Action::Action() { - at = startAction; - position = 0; - data = 0; - lenData = 0; - mayCoalesce = false; -} - -Action::~Action() { - Destroy(); -} - -void Action::Create(actionType at_, int position_, const char *data_, int lenData_, bool mayCoalesce_) { - delete []data; - data = NULL; - position = position_; - at = at_; - if (lenData_) { - data = new char[lenData_]; - memcpy(data, data_, lenData_); - } - lenData = lenData_; - mayCoalesce = mayCoalesce_; -} - -void Action::Destroy() { - delete []data; - data = 0; -} - -void Action::Grab(Action *source) { - delete []data; - - position = source->position; - at = source->at; - data = source->data; - lenData = source->lenData; - mayCoalesce = source->mayCoalesce; - - // Ownership of source data transferred to this - source->position = 0; - source->at = startAction; - source->data = 0; - source->lenData = 0; - source->mayCoalesce = true; -} - -// The undo history stores a sequence of user operations that represent the user's view of the -// commands executed on the text. -// Each user operation contains a sequence of text insertion and text deletion actions. -// All the user operations are stored in a list of individual actions with 'start' actions used -// as delimiters between user operations. -// Initially there is one start action in the history. -// As each action is performed, it is recorded in the history. The action may either become -// part of the current user operation or may start a new user operation. If it is to be part of the -// current operation, then it overwrites the current last action. If it is to be part of a new -// operation, it is appended after the current last action. -// After writing the new action, a new start action is appended at the end of the history. -// The decision of whether to start a new user operation is based upon two factors. If a -// compound operation has been explicitly started by calling BeginUndoAction and no matching -// EndUndoAction (these calls nest) has been called, then the action is coalesced into the current -// operation. If there is no outstanding BeginUndoAction call then a new operation is started -// unless it looks as if the new action is caused by the user typing or deleting a stream of text. -// Sequences that look like typing or deletion are coalesced into a single user operation. - -UndoHistory::UndoHistory() { - - lenActions = 100; - actions = new Action[lenActions]; - maxAction = 0; - currentAction = 0; - undoSequenceDepth = 0; - savePoint = 0; - tentativePoint = -1; - - actions[currentAction].Create(startAction); -} - -UndoHistory::~UndoHistory() { - delete []actions; - actions = 0; -} - -void UndoHistory::EnsureUndoRoom() { - // Have to test that there is room for 2 more actions in the array - // as two actions may be created by the calling function - if (currentAction >= (lenActions - 2)) { - // Run out of undo nodes so extend the array - int lenActionsNew = lenActions * 2; - Action *actionsNew = new Action[lenActionsNew]; - for (int act = 0; act <= currentAction; act++) - actionsNew[act].Grab(&actions[act]); - delete []actions; - lenActions = lenActionsNew; - actions = actionsNew; - } -} - -const char *UndoHistory::AppendAction(actionType at, int position, const char *data, int lengthData, - bool &startSequence, bool mayCoalesce) { - EnsureUndoRoom(); - //Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction); - //Platform::DebugPrintf("^ %d action %d %d\n", actions[currentAction - 1].at, - // actions[currentAction - 1].position, actions[currentAction - 1].lenData); - if (currentAction < savePoint) { - savePoint = -1; - } - int oldCurrentAction = currentAction; - if (currentAction >= 1) { - if (0 == undoSequenceDepth) { - // Top level actions may not always be coalesced - int targetAct = -1; - const Action *actPrevious = &(actions[currentAction + targetAct]); - // Container actions may forward the coalesce state of Scintilla Actions. - while ((actPrevious->at == containerAction) && actPrevious->mayCoalesce) { - targetAct--; - actPrevious = &(actions[currentAction + targetAct]); - } - // See if current action can be coalesced into previous action - // Will work if both are inserts or deletes and position is same -#if defined(_MSC_VER) && defined(_PREFAST_) - // Visual Studio 2013 Code Analysis wrongly believes actions can be NULL at its next reference - __analysis_assume(actions); -#endif - if ((currentAction == savePoint) || (currentAction == tentativePoint)) { - currentAction++; - } else if (!actions[currentAction].mayCoalesce) { - // Not allowed to coalesce if this set - currentAction++; - } else if (!mayCoalesce || !actPrevious->mayCoalesce) { - currentAction++; - } else if (at == containerAction || actions[currentAction].at == containerAction) { - ; // A coalescible containerAction - } else if ((at != actPrevious->at) && (actPrevious->at != startAction)) { - currentAction++; - } else if ((at == insertAction) && - (position != (actPrevious->position + actPrevious->lenData))) { - // Insertions must be immediately after to coalesce - currentAction++; - } else if (at == removeAction) { - if ((lengthData == 1) || (lengthData == 2)) { - if ((position + lengthData) == actPrevious->position) { - ; // Backspace -> OK - } else if (position == actPrevious->position) { - ; // Delete -> OK - } else { - // Removals must be at same position to coalesce - currentAction++; - } - } else { - // Removals must be of one character to coalesce - currentAction++; - } - } else { - // Action coalesced. - } - - } else { - // Actions not at top level are always coalesced unless this is after return to top level - if (!actions[currentAction].mayCoalesce) - currentAction++; - } - } else { - currentAction++; - } - startSequence = oldCurrentAction != currentAction; - int actionWithData = currentAction; - actions[currentAction].Create(at, position, data, lengthData, mayCoalesce); - currentAction++; - actions[currentAction].Create(startAction); - maxAction = currentAction; - return actions[actionWithData].data; -} - -void UndoHistory::BeginUndoAction() { - EnsureUndoRoom(); - if (undoSequenceDepth == 0) { - if (actions[currentAction].at != startAction) { - currentAction++; - actions[currentAction].Create(startAction); - maxAction = currentAction; - } - actions[currentAction].mayCoalesce = false; - } - undoSequenceDepth++; -} - -void UndoHistory::EndUndoAction() { - PLATFORM_ASSERT(undoSequenceDepth > 0); - EnsureUndoRoom(); - undoSequenceDepth--; - if (0 == undoSequenceDepth) { - if (actions[currentAction].at != startAction) { - currentAction++; - actions[currentAction].Create(startAction); - maxAction = currentAction; - } - actions[currentAction].mayCoalesce = false; - } -} - -void UndoHistory::DropUndoSequence() { - undoSequenceDepth = 0; -} - -void UndoHistory::DeleteUndoHistory() { - for (int i = 1; i < maxAction; i++) - actions[i].Destroy(); - maxAction = 0; - currentAction = 0; - actions[currentAction].Create(startAction); - savePoint = 0; - tentativePoint = -1; -} - -void UndoHistory::SetSavePoint() { - savePoint = currentAction; -} - -bool UndoHistory::IsSavePoint() const { - return savePoint == currentAction; -} - -void UndoHistory::TentativeStart() { - tentativePoint = currentAction; -} - -void UndoHistory::TentativeCommit() { - tentativePoint = -1; - // Truncate undo history - maxAction = currentAction; -} - -int UndoHistory::TentativeSteps() { - // Drop any trailing startAction - if (actions[currentAction].at == startAction && currentAction > 0) - currentAction--; - if (tentativePoint >= 0) - return currentAction - tentativePoint; - else - return -1; -} - -bool UndoHistory::CanUndo() const { - return (currentAction > 0) && (maxAction > 0); -} - -int UndoHistory::StartUndo() { - // Drop any trailing startAction - if (actions[currentAction].at == startAction && currentAction > 0) - currentAction--; - - // Count the steps in this action - int act = currentAction; - while (actions[act].at != startAction && act > 0) { - act--; - } - return currentAction - act; -} - -const Action &UndoHistory::GetUndoStep() const { - return actions[currentAction]; -} - -void UndoHistory::CompletedUndoStep() { - currentAction--; -} - -bool UndoHistory::CanRedo() const { - return maxAction > currentAction; -} - -int UndoHistory::StartRedo() { - // Drop any leading startAction - if (actions[currentAction].at == startAction && currentAction < maxAction) - currentAction++; - - // Count the steps in this action - int act = currentAction; - while (actions[act].at != startAction && act < maxAction) { - act++; - } - return act - currentAction; -} - -const Action &UndoHistory::GetRedoStep() const { - return actions[currentAction]; -} - -void UndoHistory::CompletedRedoStep() { - currentAction++; -} - -CellBuffer::CellBuffer() { - readOnly = false; - utf8LineEnds = 0; - collectingUndo = true; -} - -CellBuffer::~CellBuffer() { -} - -char CellBuffer::CharAt(int position) const { - return substance.ValueAt(position); -} - -void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) const { - if (lengthRetrieve <= 0) - return; - if (position < 0) - return; - if ((position + lengthRetrieve) > substance.Length()) { - Platform::DebugPrintf("Bad GetCharRange %d for %d of %d\n", position, - lengthRetrieve, substance.Length()); - return; - } - substance.GetRange(buffer, position, lengthRetrieve); -} - -char CellBuffer::StyleAt(int position) const { - return style.ValueAt(position); -} - -void CellBuffer::GetStyleRange(unsigned char *buffer, int position, int lengthRetrieve) const { - if (lengthRetrieve < 0) - return; - if (position < 0) - return; - if ((position + lengthRetrieve) > style.Length()) { - Platform::DebugPrintf("Bad GetStyleRange %d for %d of %d\n", position, - lengthRetrieve, style.Length()); - return; - } - style.GetRange(reinterpret_cast(buffer), position, lengthRetrieve); -} - -const char *CellBuffer::BufferPointer() { - return substance.BufferPointer(); -} - -const char *CellBuffer::RangePointer(int position, int rangeLength) { - return substance.RangePointer(position, rangeLength); -} - -int CellBuffer::GapPosition() const { - return substance.GapPosition(); -} - -// The char* returned is to an allocation owned by the undo history -const char *CellBuffer::InsertString(int position, const char *s, int insertLength, bool &startSequence) { - // InsertString and DeleteChars are the bottleneck though which all changes occur - const char *data = s; - if (!readOnly) { - if (collectingUndo) { - // Save into the undo/redo stack, but only the characters - not the formatting - // This takes up about half load time - data = uh.AppendAction(insertAction, position, s, insertLength, startSequence); - } - - BasicInsertString(position, s, insertLength); - } - return data; -} - -bool CellBuffer::SetStyleAt(int position, char styleValue) { - char curVal = style.ValueAt(position); - if (curVal != styleValue) { - style.SetValueAt(position, styleValue); - return true; - } else { - return false; - } -} - -bool CellBuffer::SetStyleFor(int position, int lengthStyle, char styleValue) { - bool changed = false; - PLATFORM_ASSERT(lengthStyle == 0 || - (lengthStyle > 0 && lengthStyle + position <= style.Length())); - while (lengthStyle--) { - char curVal = style.ValueAt(position); - if (curVal != styleValue) { - style.SetValueAt(position, styleValue); - changed = true; - } - position++; - } - return changed; -} - -// The char* returned is to an allocation owned by the undo history -const char *CellBuffer::DeleteChars(int position, int deleteLength, bool &startSequence) { - // InsertString and DeleteChars are the bottleneck though which all changes occur - PLATFORM_ASSERT(deleteLength > 0); - const char *data = 0; - if (!readOnly) { - if (collectingUndo) { - // Save into the undo/redo stack, but only the characters - not the formatting - // The gap would be moved to position anyway for the deletion so this doesn't cost extra - data = substance.RangePointer(position, deleteLength); - data = uh.AppendAction(removeAction, position, data, deleteLength, startSequence); - } - - BasicDeleteChars(position, deleteLength); - } - return data; -} - -int CellBuffer::Length() const { - return substance.Length(); -} - -void CellBuffer::Allocate(int newSize) { - substance.ReAllocate(newSize); - style.ReAllocate(newSize); -} - -void CellBuffer::SetLineEndTypes(int utf8LineEnds_) { - if (utf8LineEnds != utf8LineEnds_) { - utf8LineEnds = utf8LineEnds_; - ResetLineEnds(); - } -} - -void CellBuffer::SetPerLine(PerLine *pl) { - lv.SetPerLine(pl); -} - -int CellBuffer::Lines() const { - return lv.Lines(); -} - -int CellBuffer::LineStart(int line) const { - if (line < 0) - return 0; - else if (line >= Lines()) - return Length(); - else - return lv.LineStart(line); -} - -bool CellBuffer::IsReadOnly() const { - return readOnly; -} - -void CellBuffer::SetReadOnly(bool set) { - readOnly = set; -} - -void CellBuffer::SetSavePoint() { - uh.SetSavePoint(); -} - -bool CellBuffer::IsSavePoint() const { - return uh.IsSavePoint(); -} - -void CellBuffer::TentativeStart() { - uh.TentativeStart(); -} - -void CellBuffer::TentativeCommit() { - uh.TentativeCommit(); -} - -int CellBuffer::TentativeSteps() { - return uh.TentativeSteps(); -} - -bool CellBuffer::TentativeActive() const { - return uh.TentativeActive(); -} - -// Without undo - -void CellBuffer::InsertLine(int line, int position, bool lineStart) { - lv.InsertLine(line, position, lineStart); -} - -void CellBuffer::RemoveLine(int line) { - lv.RemoveLine(line); -} - -bool CellBuffer::UTF8LineEndOverlaps(int position) const { - unsigned char bytes[] = { - static_cast(substance.ValueAt(position-2)), - static_cast(substance.ValueAt(position-1)), - static_cast(substance.ValueAt(position)), - static_cast(substance.ValueAt(position+1)), - }; - return UTF8IsSeparator(bytes) || UTF8IsSeparator(bytes+1) || UTF8IsNEL(bytes+1); -} - -void CellBuffer::ResetLineEnds() { - // Reinitialize line data -- too much work to preserve - lv.Init(); - - int position = 0; - int length = Length(); - int lineInsert = 1; - bool atLineStart = true; - lv.InsertText(lineInsert-1, length); - unsigned char chBeforePrev = 0; - unsigned char chPrev = 0; - for (int i = 0; i < length; i++) { - unsigned char ch = substance.ValueAt(position + i); - if (ch == '\r') { - InsertLine(lineInsert, (position + i) + 1, atLineStart); - lineInsert++; - } else if (ch == '\n') { - if (chPrev == '\r') { - // Patch up what was end of line - lv.SetLineStart(lineInsert - 1, (position + i) + 1); - } else { - InsertLine(lineInsert, (position + i) + 1, atLineStart); - lineInsert++; - } - } else if (utf8LineEnds) { - unsigned char back3[3] = {chBeforePrev, chPrev, ch}; - if (UTF8IsSeparator(back3) || UTF8IsNEL(back3+1)) { - InsertLine(lineInsert, (position + i) + 1, atLineStart); - lineInsert++; - } - } - chBeforePrev = chPrev; - chPrev = ch; - } -} - -void CellBuffer::BasicInsertString(int position, const char *s, int insertLength) { - if (insertLength == 0) - return; - PLATFORM_ASSERT(insertLength > 0); - - unsigned char chAfter = substance.ValueAt(position); - bool breakingUTF8LineEnd = false; - if (utf8LineEnds && UTF8IsTrailByte(chAfter)) { - breakingUTF8LineEnd = UTF8LineEndOverlaps(position); - } - - substance.InsertFromArray(position, s, 0, insertLength); - style.InsertValue(position, insertLength, 0); - - int lineInsert = lv.LineFromPosition(position) + 1; - bool atLineStart = lv.LineStart(lineInsert-1) == position; - // Point all the lines after the insertion point further along in the buffer - lv.InsertText(lineInsert-1, insertLength); - unsigned char chBeforePrev = substance.ValueAt(position - 2); - unsigned char chPrev = substance.ValueAt(position - 1); - if (chPrev == '\r' && chAfter == '\n') { - // Splitting up a crlf pair at position - InsertLine(lineInsert, position, false); - lineInsert++; - } - if (breakingUTF8LineEnd) { - RemoveLine(lineInsert); - } - unsigned char ch = ' '; - for (int i = 0; i < insertLength; i++) { - ch = s[i]; - if (ch == '\r') { - InsertLine(lineInsert, (position + i) + 1, atLineStart); - lineInsert++; - } else if (ch == '\n') { - if (chPrev == '\r') { - // Patch up what was end of line - lv.SetLineStart(lineInsert - 1, (position + i) + 1); - } else { - InsertLine(lineInsert, (position + i) + 1, atLineStart); - lineInsert++; - } - } else if (utf8LineEnds) { - unsigned char back3[3] = {chBeforePrev, chPrev, ch}; - if (UTF8IsSeparator(back3) || UTF8IsNEL(back3+1)) { - InsertLine(lineInsert, (position + i) + 1, atLineStart); - lineInsert++; - } - } - chBeforePrev = chPrev; - chPrev = ch; - } - // Joining two lines where last insertion is cr and following substance starts with lf - if (chAfter == '\n') { - if (ch == '\r') { - // End of line already in buffer so drop the newly created one - RemoveLine(lineInsert - 1); - } - } else if (utf8LineEnds && !UTF8IsAscii(chAfter)) { - // May have end of UTF-8 line end in buffer and start in insertion - for (int j = 0; j < UTF8SeparatorLength-1; j++) { - unsigned char chAt = substance.ValueAt(position + insertLength + j); - unsigned char back3[3] = {chBeforePrev, chPrev, chAt}; - if (UTF8IsSeparator(back3)) { - InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart); - lineInsert++; - } - if ((j == 0) && UTF8IsNEL(back3+1)) { - InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart); - lineInsert++; - } - chBeforePrev = chPrev; - chPrev = chAt; - } - } -} - -void CellBuffer::BasicDeleteChars(int position, int deleteLength) { - if (deleteLength == 0) - return; - - if ((position == 0) && (deleteLength == substance.Length())) { - // If whole buffer is being deleted, faster to reinitialise lines data - // than to delete each line. - lv.Init(); - } else { - // Have to fix up line positions before doing deletion as looking at text in buffer - // to work out which lines have been removed - - int lineRemove = lv.LineFromPosition(position) + 1; - lv.InsertText(lineRemove-1, - (deleteLength)); - unsigned char chPrev = substance.ValueAt(position - 1); - unsigned char chBefore = chPrev; - unsigned char chNext = substance.ValueAt(position); - bool ignoreNL = false; - if (chPrev == '\r' && chNext == '\n') { - // Move back one - lv.SetLineStart(lineRemove, position); - lineRemove++; - ignoreNL = true; // First \n is not real deletion - } - if (utf8LineEnds && UTF8IsTrailByte(chNext)) { - if (UTF8LineEndOverlaps(position)) { - RemoveLine(lineRemove); - } - } - - unsigned char ch = chNext; - for (int i = 0; i < deleteLength; i++) { - chNext = substance.ValueAt(position + i + 1); - if (ch == '\r') { - if (chNext != '\n') { - RemoveLine(lineRemove); - } - } else if (ch == '\n') { - if (ignoreNL) { - ignoreNL = false; // Further \n are real deletions - } else { - RemoveLine(lineRemove); - } - } else if (utf8LineEnds) { - if (!UTF8IsAscii(ch)) { - unsigned char next3[3] = {ch, chNext, - static_cast(substance.ValueAt(position + i + 2))}; - if (UTF8IsSeparator(next3) || UTF8IsNEL(next3)) { - RemoveLine(lineRemove); - } - } - } - - ch = chNext; - } - // May have to fix up end if last deletion causes cr to be next to lf - // or removes one of a crlf pair - char chAfter = substance.ValueAt(position + deleteLength); - if (chBefore == '\r' && chAfter == '\n') { - // Using lineRemove-1 as cr ended line before start of deletion - RemoveLine(lineRemove - 1); - lv.SetLineStart(lineRemove - 1, position + 1); - } - } - substance.DeleteRange(position, deleteLength); - style.DeleteRange(position, deleteLength); -} - -bool CellBuffer::SetUndoCollection(bool collectUndo) { - collectingUndo = collectUndo; - uh.DropUndoSequence(); - return collectingUndo; -} - -bool CellBuffer::IsCollectingUndo() const { - return collectingUndo; -} - -void CellBuffer::BeginUndoAction() { - uh.BeginUndoAction(); -} - -void CellBuffer::EndUndoAction() { - uh.EndUndoAction(); -} - -void CellBuffer::AddUndoAction(int token, bool mayCoalesce) { - bool startSequence; - uh.AppendAction(containerAction, token, 0, 0, startSequence, mayCoalesce); -} - -void CellBuffer::DeleteUndoHistory() { - uh.DeleteUndoHistory(); -} - -bool CellBuffer::CanUndo() const { - return uh.CanUndo(); -} - -int CellBuffer::StartUndo() { - return uh.StartUndo(); -} - -const Action &CellBuffer::GetUndoStep() const { - return uh.GetUndoStep(); -} - -void CellBuffer::PerformUndoStep() { - const Action &actionStep = uh.GetUndoStep(); - if (actionStep.at == insertAction) { - if (substance.Length() < actionStep.lenData) { - throw std::runtime_error( - "CellBuffer::PerformUndoStep: deletion must be less than document length."); - } - BasicDeleteChars(actionStep.position, actionStep.lenData); - } else if (actionStep.at == removeAction) { - BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData); - } - uh.CompletedUndoStep(); -} - -bool CellBuffer::CanRedo() const { - return uh.CanRedo(); -} - -int CellBuffer::StartRedo() { - return uh.StartRedo(); -} - -const Action &CellBuffer::GetRedoStep() const { - return uh.GetRedoStep(); -} - -void CellBuffer::PerformRedoStep() { - const Action &actionStep = uh.GetRedoStep(); - if (actionStep.at == insertAction) { - BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData); - } else if (actionStep.at == removeAction) { - BasicDeleteChars(actionStep.position, actionStep.lenData); - } - uh.CompletedRedoStep(); -} - diff --git a/libs/qscintilla/src/CellBuffer.h b/libs/qscintilla/src/CellBuffer.h deleted file mode 100644 index 5e4fc7c8c..000000000 --- a/libs/qscintilla/src/CellBuffer.h +++ /dev/null @@ -1,231 +0,0 @@ -// Scintilla source code edit control -/** @file CellBuffer.h - ** Manages the text of the document. - **/ -// Copyright 1998-2004 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef CELLBUFFER_H -#define CELLBUFFER_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -// Interface to per-line data that wants to see each line insertion and deletion -class PerLine { -public: - virtual ~PerLine() {} - virtual void Init()=0; - virtual void InsertLine(int line)=0; - virtual void RemoveLine(int line)=0; -}; - -/** - * The line vector contains information about each of the lines in a cell buffer. - */ -class LineVector { - - Partitioning starts; - PerLine *perLine; - -public: - - LineVector(); - ~LineVector(); - void Init(); - void SetPerLine(PerLine *pl); - - void InsertText(int line, int delta); - void InsertLine(int line, int position, bool lineStart); - void SetLineStart(int line, int position); - void RemoveLine(int line); - int Lines() const { - return starts.Partitions(); - } - int LineFromPosition(int pos) const; - int LineStart(int line) const { - return starts.PositionFromPartition(line); - } - - int MarkValue(int line); - int AddMark(int line, int marker); - void MergeMarkers(int pos); - void DeleteMark(int line, int markerNum, bool all); - void DeleteMarkFromHandle(int markerHandle); - int LineFromHandle(int markerHandle); - - void ClearLevels(); - int SetLevel(int line, int level); - int GetLevel(int line); - - int SetLineState(int line, int state); - int GetLineState(int line); - int GetMaxLineState(); - -}; - -enum actionType { insertAction, removeAction, startAction, containerAction }; - -/** - * Actions are used to store all the information required to perform one undo/redo step. - */ -class Action { -public: - actionType at; - int position; - char *data; - int lenData; - bool mayCoalesce; - - Action(); - ~Action(); - void Create(actionType at_, int position_=0, const char *data_=0, int lenData_=0, bool mayCoalesce_=true); - void Destroy(); - void Grab(Action *source); -}; - -/** - * - */ -class UndoHistory { - Action *actions; - int lenActions; - int maxAction; - int currentAction; - int undoSequenceDepth; - int savePoint; - int tentativePoint; - - void EnsureUndoRoom(); - - // Private so UndoHistory objects can not be copied - UndoHistory(const UndoHistory &); - -public: - UndoHistory(); - ~UndoHistory(); - - const char *AppendAction(actionType at, int position, const char *data, int length, bool &startSequence, bool mayCoalesce=true); - - void BeginUndoAction(); - void EndUndoAction(); - void DropUndoSequence(); - void DeleteUndoHistory(); - - /// The save point is a marker in the undo stack where the container has stated that - /// the buffer was saved. Undo and redo can move over the save point. - void SetSavePoint(); - bool IsSavePoint() const; - - // Tentative actions are used for input composition so that it can be undone cleanly - void TentativeStart(); - void TentativeCommit(); - bool TentativeActive() const { return tentativePoint >= 0; } - int TentativeSteps(); - - /// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is - /// called that many times. Similarly for redo. - bool CanUndo() const; - int StartUndo(); - const Action &GetUndoStep() const; - void CompletedUndoStep(); - bool CanRedo() const; - int StartRedo(); - const Action &GetRedoStep() const; - void CompletedRedoStep(); -}; - -/** - * Holder for an expandable array of characters that supports undo and line markers. - * Based on article "Data Structures in a Bit-Mapped Text Editor" - * by Wilfred J. Hansen, Byte January 1987, page 183. - */ -class CellBuffer { -private: - SplitVector substance; - SplitVector style; - bool readOnly; - int utf8LineEnds; - - bool collectingUndo; - UndoHistory uh; - - LineVector lv; - - bool UTF8LineEndOverlaps(int position) const; - void ResetLineEnds(); - /// Actions without undo - void BasicInsertString(int position, const char *s, int insertLength); - void BasicDeleteChars(int position, int deleteLength); - -public: - - CellBuffer(); - ~CellBuffer(); - - /// Retrieving positions outside the range of the buffer works and returns 0 - char CharAt(int position) const; - void GetCharRange(char *buffer, int position, int lengthRetrieve) const; - char StyleAt(int position) const; - void GetStyleRange(unsigned char *buffer, int position, int lengthRetrieve) const; - const char *BufferPointer(); - const char *RangePointer(int position, int rangeLength); - int GapPosition() const; - - int Length() const; - void Allocate(int newSize); - int GetLineEndTypes() const { return utf8LineEnds; } - void SetLineEndTypes(int utf8LineEnds_); - void SetPerLine(PerLine *pl); - int Lines() const; - int LineStart(int line) const; - int LineFromPosition(int pos) const { return lv.LineFromPosition(pos); } - void InsertLine(int line, int position, bool lineStart); - void RemoveLine(int line); - const char *InsertString(int position, const char *s, int insertLength, bool &startSequence); - - /// Setting styles for positions outside the range of the buffer is safe and has no effect. - /// @return true if the style of a character is changed. - bool SetStyleAt(int position, char styleValue); - bool SetStyleFor(int position, int length, char styleValue); - - const char *DeleteChars(int position, int deleteLength, bool &startSequence); - - bool IsReadOnly() const; - void SetReadOnly(bool set); - - /// The save point is a marker in the undo stack where the container has stated that - /// the buffer was saved. Undo and redo can move over the save point. - void SetSavePoint(); - bool IsSavePoint() const; - - void TentativeStart(); - void TentativeCommit(); - bool TentativeActive() const; - int TentativeSteps(); - - bool SetUndoCollection(bool collectUndo); - bool IsCollectingUndo() const; - void BeginUndoAction(); - void EndUndoAction(); - void AddUndoAction(int token, bool mayCoalesce); - void DeleteUndoHistory(); - - /// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is - /// called that many times. Similarly for redo. - bool CanUndo() const; - int StartUndo(); - const Action &GetUndoStep() const; - void PerformUndoStep(); - bool CanRedo() const; - int StartRedo(); - const Action &GetRedoStep() const; - void PerformRedoStep(); -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/ContractionState.cpp b/libs/qscintilla/src/ContractionState.cpp deleted file mode 100644 index 7b7655420..000000000 --- a/libs/qscintilla/src/ContractionState.cpp +++ /dev/null @@ -1,284 +0,0 @@ -// Scintilla source code edit control -/** @file ContractionState.cxx - ** Manages visibility of lines for folding and wrapping. - **/ -// Copyright 1998-2007 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include - -#include - -#include "Platform.h" - -#include "SplitVector.h" -#include "Partitioning.h" -#include "RunStyles.h" -#include "ContractionState.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) { - //InsertLine(0); -} - -ContractionState::~ContractionState() { - Clear(); -} - -void ContractionState::EnsureData() { - if (OneToOne()) { - visible = new RunStyles(); - expanded = new RunStyles(); - heights = new RunStyles(); - displayLines = new Partitioning(4); - InsertLines(0, linesInDocument); - } -} - -void ContractionState::Clear() { - delete visible; - visible = 0; - delete expanded; - expanded = 0; - delete heights; - heights = 0; - delete displayLines; - displayLines = 0; - linesInDocument = 1; -} - -int ContractionState::LinesInDoc() const { - if (OneToOne()) { - return linesInDocument; - } else { - return displayLines->Partitions() - 1; - } -} - -int ContractionState::LinesDisplayed() const { - if (OneToOne()) { - return linesInDocument; - } else { - return displayLines->PositionFromPartition(LinesInDoc()); - } -} - -int ContractionState::DisplayFromDoc(int lineDoc) const { - if (OneToOne()) { - return (lineDoc <= linesInDocument) ? lineDoc : linesInDocument; - } else { - if (lineDoc > displayLines->Partitions()) - lineDoc = displayLines->Partitions(); - return displayLines->PositionFromPartition(lineDoc); - } -} - -int ContractionState::DisplayLastFromDoc(int lineDoc) const { - return DisplayFromDoc(lineDoc) + GetHeight(lineDoc) - 1; -} - -int ContractionState::DocFromDisplay(int lineDisplay) const { - if (OneToOne()) { - return lineDisplay; - } else { - if (lineDisplay <= 0) { - return 0; - } - if (lineDisplay > LinesDisplayed()) { - return displayLines->PartitionFromPosition(LinesDisplayed()); - } - int lineDoc = displayLines->PartitionFromPosition(lineDisplay); - PLATFORM_ASSERT(GetVisible(lineDoc)); - return lineDoc; - } -} - -void ContractionState::InsertLine(int lineDoc) { - if (OneToOne()) { - linesInDocument++; - } else { - visible->InsertSpace(lineDoc, 1); - visible->SetValueAt(lineDoc, 1); - expanded->InsertSpace(lineDoc, 1); - expanded->SetValueAt(lineDoc, 1); - heights->InsertSpace(lineDoc, 1); - heights->SetValueAt(lineDoc, 1); - int lineDisplay = DisplayFromDoc(lineDoc); - displayLines->InsertPartition(lineDoc, lineDisplay); - displayLines->InsertText(lineDoc, 1); - } -} - -void ContractionState::InsertLines(int lineDoc, int lineCount) { - for (int l = 0; l < lineCount; l++) { - InsertLine(lineDoc + l); - } - Check(); -} - -void ContractionState::DeleteLine(int lineDoc) { - if (OneToOne()) { - linesInDocument--; - } else { - if (GetVisible(lineDoc)) { - displayLines->InsertText(lineDoc, -heights->ValueAt(lineDoc)); - } - displayLines->RemovePartition(lineDoc); - visible->DeleteRange(lineDoc, 1); - expanded->DeleteRange(lineDoc, 1); - heights->DeleteRange(lineDoc, 1); - } -} - -void ContractionState::DeleteLines(int lineDoc, int lineCount) { - for (int l = 0; l < lineCount; l++) { - DeleteLine(lineDoc); - } - Check(); -} - -bool ContractionState::GetVisible(int lineDoc) const { - if (OneToOne()) { - return true; - } else { - if (lineDoc >= visible->Length()) - return true; - return visible->ValueAt(lineDoc) == 1; - } -} - -bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool isVisible) { - if (OneToOne() && isVisible) { - return false; - } else { - EnsureData(); - int delta = 0; - Check(); - if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) { - for (int line = lineDocStart; line <= lineDocEnd; line++) { - if (GetVisible(line) != isVisible) { - int difference = isVisible ? heights->ValueAt(line) : -heights->ValueAt(line); - visible->SetValueAt(line, isVisible ? 1 : 0); - displayLines->InsertText(line, difference); - delta += difference; - } - } - } else { - return false; - } - Check(); - return delta != 0; - } -} - -bool ContractionState::HiddenLines() const { - if (OneToOne()) { - return false; - } else { - return !visible->AllSameAs(1); - } -} - -bool ContractionState::GetExpanded(int lineDoc) const { - if (OneToOne()) { - return true; - } else { - Check(); - return expanded->ValueAt(lineDoc) == 1; - } -} - -bool ContractionState::SetExpanded(int lineDoc, bool isExpanded) { - if (OneToOne() && isExpanded) { - return false; - } else { - EnsureData(); - if (isExpanded != (expanded->ValueAt(lineDoc) == 1)) { - expanded->SetValueAt(lineDoc, isExpanded ? 1 : 0); - Check(); - return true; - } else { - Check(); - return false; - } - } -} - -int ContractionState::ContractedNext(int lineDocStart) const { - if (OneToOne()) { - return -1; - } else { - Check(); - if (!expanded->ValueAt(lineDocStart)) { - return lineDocStart; - } else { - int lineDocNextChange = expanded->EndRun(lineDocStart); - if (lineDocNextChange < LinesInDoc()) - return lineDocNextChange; - else - return -1; - } - } -} - -int ContractionState::GetHeight(int lineDoc) const { - if (OneToOne()) { - return 1; - } else { - return heights->ValueAt(lineDoc); - } -} - -// Set the number of display lines needed for this line. -// Return true if this is a change. -bool ContractionState::SetHeight(int lineDoc, int height) { - if (OneToOne() && (height == 1)) { - return false; - } else if (lineDoc < LinesInDoc()) { - EnsureData(); - if (GetHeight(lineDoc) != height) { - if (GetVisible(lineDoc)) { - displayLines->InsertText(lineDoc, height - GetHeight(lineDoc)); - } - heights->SetValueAt(lineDoc, height); - Check(); - return true; - } else { - Check(); - return false; - } - } else { - return false; - } -} - -void ContractionState::ShowAll() { - int lines = LinesInDoc(); - Clear(); - linesInDocument = lines; -} - -// Debugging checks - -void ContractionState::Check() const { -#ifdef CHECK_CORRECTNESS - for (int vline = 0; vline < LinesDisplayed(); vline++) { - const int lineDoc = DocFromDisplay(vline); - PLATFORM_ASSERT(GetVisible(lineDoc)); - } - for (int lineDoc = 0; lineDoc < LinesInDoc(); lineDoc++) { - const int displayThis = DisplayFromDoc(lineDoc); - const int displayNext = DisplayFromDoc(lineDoc + 1); - const int height = displayNext - displayThis; - PLATFORM_ASSERT(height >= 0); - if (GetVisible(lineDoc)) { - PLATFORM_ASSERT(GetHeight(lineDoc) == height); - } else { - PLATFORM_ASSERT(0 == height); - } - } -#endif -} diff --git a/libs/qscintilla/src/ContractionState.h b/libs/qscintilla/src/ContractionState.h deleted file mode 100644 index 96cbf0763..000000000 --- a/libs/qscintilla/src/ContractionState.h +++ /dev/null @@ -1,69 +0,0 @@ -// Scintilla source code edit control -/** @file ContractionState.h - ** Manages visibility of lines for folding and wrapping. - **/ -// Copyright 1998-2007 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef CONTRACTIONSTATE_H -#define CONTRACTIONSTATE_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -/** - */ -class ContractionState { - // These contain 1 element for every document line. - RunStyles *visible; - RunStyles *expanded; - RunStyles *heights; - Partitioning *displayLines; - int linesInDocument; - - void EnsureData(); - - bool OneToOne() const { - // True when each document line is exactly one display line so need for - // complex data structures. - return visible == 0; - } - -public: - ContractionState(); - virtual ~ContractionState(); - - void Clear(); - - int LinesInDoc() const; - int LinesDisplayed() const; - int DisplayFromDoc(int lineDoc) const; - int DisplayLastFromDoc(int lineDoc) const; - int DocFromDisplay(int lineDisplay) const; - - void InsertLine(int lineDoc); - void InsertLines(int lineDoc, int lineCount); - void DeleteLine(int lineDoc); - void DeleteLines(int lineDoc, int lineCount); - - bool GetVisible(int lineDoc) const; - bool SetVisible(int lineDocStart, int lineDocEnd, bool isVisible); - bool HiddenLines() const; - - bool GetExpanded(int lineDoc) const; - bool SetExpanded(int lineDoc, bool isExpanded); - int ContractedNext(int lineDocStart) const; - - int GetHeight(int lineDoc) const; - bool SetHeight(int lineDoc, int height); - - void ShowAll(); - void Check() const; -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/Decoration.cpp b/libs/qscintilla/src/Decoration.cpp deleted file mode 100644 index e7610e0b6..000000000 --- a/libs/qscintilla/src/Decoration.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/** @file Decoration.cxx - ** Visual elements added over text. - **/ -// Copyright 1998-2007 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include - -#include - -#include "Platform.h" - -#include "Scintilla.h" -#include "SplitVector.h" -#include "Partitioning.h" -#include "RunStyles.h" -#include "Decoration.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -Decoration::Decoration(int indicator_) : next(0), indicator(indicator_) { -} - -Decoration::~Decoration() { -} - -bool Decoration::Empty() const { - return (rs.Runs() == 1) && (rs.AllSameAs(0)); -} - -DecorationList::DecorationList() : currentIndicator(0), currentValue(1), current(0), - lengthDocument(0), root(0), clickNotified(false) { -} - -DecorationList::~DecorationList() { - Decoration *deco = root; - while (deco) { - Decoration *decoNext = deco->next; - delete deco; - deco = decoNext; - } - root = 0; - current = 0; -} - -Decoration *DecorationList::DecorationFromIndicator(int indicator) { - for (Decoration *deco=root; deco; deco = deco->next) { - if (deco->indicator == indicator) { - return deco; - } - } - return 0; -} - -Decoration *DecorationList::Create(int indicator, int length) { - currentIndicator = indicator; - Decoration *decoNew = new Decoration(indicator); - decoNew->rs.InsertSpace(0, length); - - Decoration *decoPrev = 0; - Decoration *deco = root; - - while (deco && (deco->indicator < indicator)) { - decoPrev = deco; - deco = deco->next; - } - if (decoPrev == 0) { - decoNew->next = root; - root = decoNew; - } else { - decoNew->next = deco; - decoPrev->next = decoNew; - } - return decoNew; -} - -void DecorationList::Delete(int indicator) { - Decoration *decoToDelete = 0; - if (root) { - if (root->indicator == indicator) { - decoToDelete = root; - root = root->next; - } else { - Decoration *deco=root; - while (deco->next && !decoToDelete) { - if (deco->next && deco->next->indicator == indicator) { - decoToDelete = deco->next; - deco->next = decoToDelete->next; - } else { - deco = deco->next; - } - } - } - } - if (decoToDelete) { - delete decoToDelete; - current = 0; - } -} - -void DecorationList::SetCurrentIndicator(int indicator) { - currentIndicator = indicator; - current = DecorationFromIndicator(indicator); - currentValue = 1; -} - -void DecorationList::SetCurrentValue(int value) { - currentValue = value ? value : 1; -} - -bool DecorationList::FillRange(int &position, int value, int &fillLength) { - if (!current) { - current = DecorationFromIndicator(currentIndicator); - if (!current) { - current = Create(currentIndicator, lengthDocument); - } - } - bool changed = current->rs.FillRange(position, value, fillLength); - if (current->Empty()) { - Delete(currentIndicator); - } - return changed; -} - -void DecorationList::InsertSpace(int position, int insertLength) { - const bool atEnd = position == lengthDocument; - lengthDocument += insertLength; - for (Decoration *deco=root; deco; deco = deco->next) { - deco->rs.InsertSpace(position, insertLength); - if (atEnd) { - deco->rs.FillRange(position, 0, insertLength); - } - } -} - -void DecorationList::DeleteRange(int position, int deleteLength) { - lengthDocument -= deleteLength; - Decoration *deco; - for (deco=root; deco; deco = deco->next) { - deco->rs.DeleteRange(position, deleteLength); - } - DeleteAnyEmpty(); -} - -void DecorationList::DeleteAnyEmpty() { - Decoration *deco = root; - while (deco) { - if ((lengthDocument == 0) || deco->Empty()) { - Delete(deco->indicator); - deco = root; - } else { - deco = deco->next; - } - } -} - -int DecorationList::AllOnFor(int position) const { - int mask = 0; - for (Decoration *deco=root; deco; deco = deco->next) { - if (deco->rs.ValueAt(position)) { - if (deco->indicator < INDIC_IME) { - mask |= 1 << deco->indicator; - } - } - } - return mask; -} - -int DecorationList::ValueAt(int indicator, int position) { - Decoration *deco = DecorationFromIndicator(indicator); - if (deco) { - return deco->rs.ValueAt(position); - } - return 0; -} - -int DecorationList::Start(int indicator, int position) { - Decoration *deco = DecorationFromIndicator(indicator); - if (deco) { - return deco->rs.StartRun(position); - } - return 0; -} - -int DecorationList::End(int indicator, int position) { - Decoration *deco = DecorationFromIndicator(indicator); - if (deco) { - return deco->rs.EndRun(position); - } - return 0; -} diff --git a/libs/qscintilla/src/Decoration.h b/libs/qscintilla/src/Decoration.h deleted file mode 100644 index a0c434af8..000000000 --- a/libs/qscintilla/src/Decoration.h +++ /dev/null @@ -1,64 +0,0 @@ -/** @file Decoration.h - ** Visual elements added over text. - **/ -// Copyright 1998-2007 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef DECORATION_H -#define DECORATION_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -class Decoration { -public: - Decoration *next; - RunStyles rs; - int indicator; - - explicit Decoration(int indicator_); - ~Decoration(); - - bool Empty() const; -}; - -class DecorationList { - int currentIndicator; - int currentValue; - Decoration *current; - int lengthDocument; - Decoration *DecorationFromIndicator(int indicator); - Decoration *Create(int indicator, int length); - void Delete(int indicator); - void DeleteAnyEmpty(); -public: - Decoration *root; - bool clickNotified; - - DecorationList(); - ~DecorationList(); - - void SetCurrentIndicator(int indicator); - int GetCurrentIndicator() const { return currentIndicator; } - - void SetCurrentValue(int value); - int GetCurrentValue() const { return currentValue; } - - // Returns true if some values may have changed - bool FillRange(int &position, int value, int &fillLength); - - void InsertSpace(int position, int insertLength); - void DeleteRange(int position, int deleteLength); - - int AllOnFor(int position) const; - int ValueAt(int indicator, int position); - int Start(int indicator, int position); - int End(int indicator, int position); -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/Document.cpp b/libs/qscintilla/src/Document.cpp deleted file mode 100644 index 7d34dace1..000000000 --- a/libs/qscintilla/src/Document.cpp +++ /dev/null @@ -1,2815 +0,0 @@ -// Scintilla source code edit control -/** @file Document.cxx - ** Text document that handles notifications, DBCS, styling, words and end of line. - **/ -// Copyright 1998-2011 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef CXX11_REGEX -#include -#endif - -#include "Platform.h" - -#include "ILexer.h" -#include "Scintilla.h" - -#include "CharacterSet.h" -#include "SplitVector.h" -#include "Partitioning.h" -#include "RunStyles.h" -#include "CellBuffer.h" -#include "PerLine.h" -#include "CharClassify.h" -#include "Decoration.h" -#include "CaseFolder.h" -#include "Document.h" -#include "RESearch.h" -#include "UniConversion.h" -#include "UnicodeFromUTF8.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsPunctuation(char ch) { - return IsASCII(ch) && ispunct(ch); -} - -void LexInterface::Colourise(int start, int end) { - if (pdoc && instance && !performingStyle) { - // Protect against reentrance, which may occur, for example, when - // fold points are discovered while performing styling and the folding - // code looks for child lines which may trigger styling. - performingStyle = true; - - int lengthDoc = pdoc->Length(); - if (end == -1) - end = lengthDoc; - int len = end - start; - - PLATFORM_ASSERT(len >= 0); - PLATFORM_ASSERT(start + len <= lengthDoc); - - int styleStart = 0; - if (start > 0) - styleStart = pdoc->StyleAt(start - 1); - - if (len > 0) { - instance->Lex(start, len, styleStart, pdoc); - instance->Fold(start, len, styleStart, pdoc); - } - - performingStyle = false; - } -} - -int LexInterface::LineEndTypesSupported() { - if (instance) { - int interfaceVersion = instance->Version(); - if (interfaceVersion >= lvSubStyles) { - ILexerWithSubStyles *ssinstance = static_cast(instance); - return ssinstance->LineEndTypesSupported(); - } - } - return 0; -} - -Document::Document() { - refCount = 0; - pcf = NULL; -#ifdef _WIN32 - eolMode = SC_EOL_CRLF; -#else - eolMode = SC_EOL_LF; -#endif - dbcsCodePage = 0; - lineEndBitSet = SC_LINE_END_TYPE_DEFAULT; - endStyled = 0; - styleClock = 0; - enteredModification = 0; - enteredStyling = 0; - enteredReadOnlyCount = 0; - insertionSet = false; - tabInChars = 8; - indentInChars = 0; - actualIndentInChars = 8; - useTabs = true; - tabIndents = true; - backspaceUnindents = false; - - matchesValid = false; - regex = 0; - - UTF8BytesOfLeadInitialise(); - - perLineData[ldMarkers] = new LineMarkers(); - perLineData[ldLevels] = new LineLevels(); - perLineData[ldState] = new LineState(); - perLineData[ldMargin] = new LineAnnotation(); - perLineData[ldAnnotation] = new LineAnnotation(); - - cb.SetPerLine(this); - - pli = 0; -} - -Document::~Document() { - for (std::vector::iterator it = watchers.begin(); it != watchers.end(); ++it) { - it->watcher->NotifyDeleted(this, it->userData); - } - for (int j=0; jInit(); - } -} - -int Document::LineEndTypesSupported() const { - if ((SC_CP_UTF8 == dbcsCodePage) && pli) - return pli->LineEndTypesSupported(); - else - return 0; -} - -bool Document::SetDBCSCodePage(int dbcsCodePage_) { - if (dbcsCodePage != dbcsCodePage_) { - dbcsCodePage = dbcsCodePage_; - SetCaseFolder(NULL); - cb.SetLineEndTypes(lineEndBitSet & LineEndTypesSupported()); - return true; - } else { - return false; - } -} - -bool Document::SetLineEndTypesAllowed(int lineEndBitSet_) { - if (lineEndBitSet != lineEndBitSet_) { - lineEndBitSet = lineEndBitSet_; - int lineEndBitSetActive = lineEndBitSet & LineEndTypesSupported(); - if (lineEndBitSetActive != cb.GetLineEndTypes()) { - ModifiedAt(0); - cb.SetLineEndTypes(lineEndBitSetActive); - return true; - } else { - return false; - } - } else { - return false; - } -} - -void Document::InsertLine(int line) { - for (int j=0; jInsertLine(line); - } -} - -void Document::RemoveLine(int line) { - for (int j=0; jRemoveLine(line); - } -} - -// Increase reference count and return its previous value. -int Document::AddRef() { - return refCount++; -} - -// Decrease reference count and return its previous value. -// Delete the document if reference count reaches zero. -int SCI_METHOD Document::Release() { - int curRefCount = --refCount; - if (curRefCount == 0) - delete this; - return curRefCount; -} - -void Document::SetSavePoint() { - cb.SetSavePoint(); - NotifySavePoint(true); -} - -void Document::TentativeUndo() { - CheckReadOnly(); - if (enteredModification == 0) { - enteredModification++; - if (!cb.IsReadOnly()) { - bool startSavePoint = cb.IsSavePoint(); - bool multiLine = false; - int steps = cb.TentativeSteps(); - //Platform::DebugPrintf("Steps=%d\n", steps); - for (int step = 0; step < steps; step++) { - const int prevLinesTotal = LinesTotal(); - const Action &action = cb.GetUndoStep(); - if (action.at == removeAction) { - NotifyModified(DocModification( - SC_MOD_BEFOREINSERT | SC_PERFORMED_UNDO, action)); - } else if (action.at == containerAction) { - DocModification dm(SC_MOD_CONTAINER | SC_PERFORMED_UNDO); - dm.token = action.position; - NotifyModified(dm); - } else { - NotifyModified(DocModification( - SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action)); - } - cb.PerformUndoStep(); - if (action.at != containerAction) { - ModifiedAt(action.position); - } - - int modFlags = SC_PERFORMED_UNDO; - // With undo, an insertion action becomes a deletion notification - if (action.at == removeAction) { - modFlags |= SC_MOD_INSERTTEXT; - } else if (action.at == insertAction) { - modFlags |= SC_MOD_DELETETEXT; - } - if (steps > 1) - modFlags |= SC_MULTISTEPUNDOREDO; - const int linesAdded = LinesTotal() - prevLinesTotal; - if (linesAdded != 0) - multiLine = true; - if (step == steps - 1) { - modFlags |= SC_LASTSTEPINUNDOREDO; - if (multiLine) - modFlags |= SC_MULTILINEUNDOREDO; - } - NotifyModified(DocModification(modFlags, action.position, action.lenData, - linesAdded, action.data)); - } - - bool endSavePoint = cb.IsSavePoint(); - if (startSavePoint != endSavePoint) - NotifySavePoint(endSavePoint); - - cb.TentativeCommit(); - } - enteredModification--; - } -} - -int Document::GetMark(int line) { - return static_cast(perLineData[ldMarkers])->MarkValue(line); -} - -int Document::MarkerNext(int lineStart, int mask) const { - return static_cast(perLineData[ldMarkers])->MarkerNext(lineStart, mask); -} - -int Document::AddMark(int line, int markerNum) { - if (line >= 0 && line <= LinesTotal()) { - int prev = static_cast(perLineData[ldMarkers])-> - AddMark(line, markerNum, LinesTotal()); - DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); - NotifyModified(mh); - return prev; - } else { - return 0; - } -} - -void Document::AddMarkSet(int line, int valueSet) { - if (line < 0 || line > LinesTotal()) { - return; - } - unsigned int m = valueSet; - for (int i = 0; m; i++, m >>= 1) - if (m & 1) - static_cast(perLineData[ldMarkers])-> - AddMark(line, i, LinesTotal()); - DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); - NotifyModified(mh); -} - -void Document::DeleteMark(int line, int markerNum) { - static_cast(perLineData[ldMarkers])->DeleteMark(line, markerNum, false); - DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); - NotifyModified(mh); -} - -void Document::DeleteMarkFromHandle(int markerHandle) { - static_cast(perLineData[ldMarkers])->DeleteMarkFromHandle(markerHandle); - DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0); - mh.line = -1; - NotifyModified(mh); -} - -void Document::DeleteAllMarks(int markerNum) { - bool someChanges = false; - for (int line = 0; line < LinesTotal(); line++) { - if (static_cast(perLineData[ldMarkers])->DeleteMark(line, markerNum, true)) - someChanges = true; - } - if (someChanges) { - DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0); - mh.line = -1; - NotifyModified(mh); - } -} - -int Document::LineFromHandle(int markerHandle) { - return static_cast(perLineData[ldMarkers])->LineFromHandle(markerHandle); -} - -int SCI_METHOD Document::LineStart(int line) const { - return cb.LineStart(line); -} - -bool Document::IsLineStartPosition(int position) const { - return LineStart(LineFromPosition(position)) == position; -} - -int SCI_METHOD Document::LineEnd(int line) const { - if (line >= LinesTotal() - 1) { - return LineStart(line + 1); - } else { - int position = LineStart(line + 1); - if (SC_CP_UTF8 == dbcsCodePage) { - unsigned char bytes[] = { - static_cast(cb.CharAt(position-3)), - static_cast(cb.CharAt(position-2)), - static_cast(cb.CharAt(position-1)), - }; - if (UTF8IsSeparator(bytes)) { - return position - UTF8SeparatorLength; - } - if (UTF8IsNEL(bytes+1)) { - return position - UTF8NELLength; - } - } - position--; // Back over CR or LF - // When line terminator is CR+LF, may need to go back one more - if ((position > LineStart(line)) && (cb.CharAt(position - 1) == '\r')) { - position--; - } - return position; - } -} - -void SCI_METHOD Document::SetErrorStatus(int status) { - // Tell the watchers an error has occurred. - for (std::vector::iterator it = watchers.begin(); it != watchers.end(); ++it) { - it->watcher->NotifyErrorOccurred(this, it->userData, status); - } -} - -int SCI_METHOD Document::LineFromPosition(int pos) const { - return cb.LineFromPosition(pos); -} - -int Document::LineEndPosition(int position) const { - return LineEnd(LineFromPosition(position)); -} - -bool Document::IsLineEndPosition(int position) const { - return LineEnd(LineFromPosition(position)) == position; -} - -bool Document::IsPositionInLineEnd(int position) const { - return position >= LineEnd(LineFromPosition(position)); -} - -int Document::VCHomePosition(int position) const { - int line = LineFromPosition(position); - int startPosition = LineStart(line); - int endLine = LineEnd(line); - int startText = startPosition; - while (startText < endLine && (cb.CharAt(startText) == ' ' || cb.CharAt(startText) == '\t')) - startText++; - if (position == startText) - return startPosition; - else - return startText; -} - -int SCI_METHOD Document::SetLevel(int line, int level) { - int prev = static_cast(perLineData[ldLevels])->SetLevel(line, level, LinesTotal()); - if (prev != level) { - DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER, - LineStart(line), 0, 0, 0, line); - mh.foldLevelNow = level; - mh.foldLevelPrev = prev; - NotifyModified(mh); - } - return prev; -} - -int SCI_METHOD Document::GetLevel(int line) const { - return static_cast(perLineData[ldLevels])->GetLevel(line); -} - -void Document::ClearLevels() { - static_cast(perLineData[ldLevels])->ClearLevels(); -} - -static bool IsSubordinate(int levelStart, int levelTry) { - if (levelTry & SC_FOLDLEVELWHITEFLAG) - return true; - else - return (levelStart & SC_FOLDLEVELNUMBERMASK) < (levelTry & SC_FOLDLEVELNUMBERMASK); -} - -int Document::GetLastChild(int lineParent, int level, int lastLine) { - if (level == -1) - level = GetLevel(lineParent) & SC_FOLDLEVELNUMBERMASK; - int maxLine = LinesTotal(); - int lookLastLine = (lastLine != -1) ? Platform::Minimum(LinesTotal() - 1, lastLine) : -1; - int lineMaxSubord = lineParent; - while (lineMaxSubord < maxLine - 1) { - EnsureStyledTo(LineStart(lineMaxSubord + 2)); - if (!IsSubordinate(level, GetLevel(lineMaxSubord + 1))) - break; - if ((lookLastLine != -1) && (lineMaxSubord >= lookLastLine) && !(GetLevel(lineMaxSubord) & SC_FOLDLEVELWHITEFLAG)) - break; - lineMaxSubord++; - } - if (lineMaxSubord > lineParent) { - if (level > (GetLevel(lineMaxSubord + 1) & SC_FOLDLEVELNUMBERMASK)) { - // Have chewed up some whitespace that belongs to a parent so seek back - if (GetLevel(lineMaxSubord) & SC_FOLDLEVELWHITEFLAG) { - lineMaxSubord--; - } - } - } - return lineMaxSubord; -} - -int Document::GetFoldParent(int line) const { - int level = GetLevel(line) & SC_FOLDLEVELNUMBERMASK; - int lineLook = line - 1; - while ((lineLook > 0) && ( - (!(GetLevel(lineLook) & SC_FOLDLEVELHEADERFLAG)) || - ((GetLevel(lineLook) & SC_FOLDLEVELNUMBERMASK) >= level)) - ) { - lineLook--; - } - if ((GetLevel(lineLook) & SC_FOLDLEVELHEADERFLAG) && - ((GetLevel(lineLook) & SC_FOLDLEVELNUMBERMASK) < level)) { - return lineLook; - } else { - return -1; - } -} - -void Document::GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, int line, int lastLine) { - int level = GetLevel(line); - int lookLastLine = Platform::Maximum(line, lastLine) + 1; - - int lookLine = line; - int lookLineLevel = level; - int lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; - while ((lookLine > 0) && ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) || - ((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum >= (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))))) { - lookLineLevel = GetLevel(--lookLine); - lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; - } - - int beginFoldBlock = (lookLineLevel & SC_FOLDLEVELHEADERFLAG) ? lookLine : GetFoldParent(lookLine); - if (beginFoldBlock == -1) { - highlightDelimiter.Clear(); - return; - } - - int endFoldBlock = GetLastChild(beginFoldBlock, -1, lookLastLine); - int firstChangeableLineBefore = -1; - if (endFoldBlock < line) { - lookLine = beginFoldBlock - 1; - lookLineLevel = GetLevel(lookLine); - lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; - while ((lookLine >= 0) && (lookLineLevelNum >= SC_FOLDLEVELBASE)) { - if (lookLineLevel & SC_FOLDLEVELHEADERFLAG) { - if (GetLastChild(lookLine, -1, lookLastLine) == line) { - beginFoldBlock = lookLine; - endFoldBlock = line; - firstChangeableLineBefore = line - 1; - } - } - if ((lookLine > 0) && (lookLineLevelNum == SC_FOLDLEVELBASE) && ((GetLevel(lookLine - 1) & SC_FOLDLEVELNUMBERMASK) > lookLineLevelNum)) - break; - lookLineLevel = GetLevel(--lookLine); - lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; - } - } - if (firstChangeableLineBefore == -1) { - for (lookLine = line - 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; - lookLine >= beginFoldBlock; - lookLineLevel = GetLevel(--lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) { - if ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) || (lookLineLevelNum > (level & SC_FOLDLEVELNUMBERMASK))) { - firstChangeableLineBefore = lookLine; - break; - } - } - } - if (firstChangeableLineBefore == -1) - firstChangeableLineBefore = beginFoldBlock - 1; - - int firstChangeableLineAfter = -1; - for (lookLine = line + 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; - lookLine <= endFoldBlock; - lookLineLevel = GetLevel(++lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) { - if ((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum < (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))) { - firstChangeableLineAfter = lookLine; - break; - } - } - if (firstChangeableLineAfter == -1) - firstChangeableLineAfter = endFoldBlock + 1; - - highlightDelimiter.beginFoldBlock = beginFoldBlock; - highlightDelimiter.endFoldBlock = endFoldBlock; - highlightDelimiter.firstChangeableLineBefore = firstChangeableLineBefore; - highlightDelimiter.firstChangeableLineAfter = firstChangeableLineAfter; -} - -int Document::ClampPositionIntoDocument(int pos) const { - return Platform::Clamp(pos, 0, Length()); -} - -bool Document::IsCrLf(int pos) const { - if (pos < 0) - return false; - if (pos >= (Length() - 1)) - return false; - return (cb.CharAt(pos) == '\r') && (cb.CharAt(pos + 1) == '\n'); -} - -int Document::LenChar(int pos) { - if (pos < 0) { - return 1; - } else if (IsCrLf(pos)) { - return 2; - } else if (SC_CP_UTF8 == dbcsCodePage) { - const unsigned char leadByte = static_cast(cb.CharAt(pos)); - const int widthCharBytes = UTF8BytesOfLead[leadByte]; - int lengthDoc = Length(); - if ((pos + widthCharBytes) > lengthDoc) - return lengthDoc - pos; - else - return widthCharBytes; - } else if (dbcsCodePage) { - return IsDBCSLeadByte(cb.CharAt(pos)) ? 2 : 1; - } else { - return 1; - } -} - -bool Document::InGoodUTF8(int pos, int &start, int &end) const { - int trail = pos; - while ((trail>0) && (pos-trail < UTF8MaxBytes) && UTF8IsTrailByte(static_cast(cb.CharAt(trail-1)))) - trail--; - start = (trail > 0) ? trail-1 : trail; - - const unsigned char leadByte = static_cast(cb.CharAt(start)); - const int widthCharBytes = UTF8BytesOfLead[leadByte]; - if (widthCharBytes == 1) { - return false; - } else { - int trailBytes = widthCharBytes - 1; - int len = pos - start; - if (len > trailBytes) - // pos too far from lead - return false; - char charBytes[UTF8MaxBytes] = {static_cast(leadByte),0,0,0}; - for (int b=1; b(start+b)); - int utf8status = UTF8Classify(reinterpret_cast(charBytes), widthCharBytes); - if (utf8status & UTF8MaskInvalid) - return false; - end = start + widthCharBytes; - return true; - } -} - -// Normalise a position so that it is not halfway through a two byte character. -// This can occur in two situations - -// When lines are terminated with \r\n pairs which should be treated as one character. -// When displaying DBCS text such as Japanese. -// If moving, move the position in the indicated direction. -int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) const { - //Platform::DebugPrintf("NoCRLF %d %d\n", pos, moveDir); - // If out of range, just return minimum/maximum value. - if (pos <= 0) - return 0; - if (pos >= Length()) - return Length(); - - // PLATFORM_ASSERT(pos > 0 && pos < Length()); - if (checkLineEnd && IsCrLf(pos - 1)) { - if (moveDir > 0) - return pos + 1; - else - return pos - 1; - } - - if (dbcsCodePage) { - if (SC_CP_UTF8 == dbcsCodePage) { - unsigned char ch = static_cast(cb.CharAt(pos)); - // If ch is not a trail byte then pos is valid intercharacter position - if (UTF8IsTrailByte(ch)) { - int startUTF = pos; - int endUTF = pos; - if (InGoodUTF8(pos, startUTF, endUTF)) { - // ch is a trail byte within a UTF-8 character - if (moveDir > 0) - pos = endUTF; - else - pos = startUTF; - } - // Else invalid UTF-8 so return position of isolated trail byte - } - } else { - // Anchor DBCS calculations at start of line because start of line can - // not be a DBCS trail byte. - int posStartLine = LineStart(LineFromPosition(pos)); - if (pos == posStartLine) - return pos; - - // Step back until a non-lead-byte is found. - int posCheck = pos; - while ((posCheck > posStartLine) && IsDBCSLeadByte(cb.CharAt(posCheck-1))) - posCheck--; - - // Check from known start of character. - while (posCheck < pos) { - int mbsize = IsDBCSLeadByte(cb.CharAt(posCheck)) ? 2 : 1; - if (posCheck + mbsize == pos) { - return pos; - } else if (posCheck + mbsize > pos) { - if (moveDir > 0) { - return posCheck + mbsize; - } else { - return posCheck; - } - } - posCheck += mbsize; - } - } - } - - return pos; -} - -// NextPosition moves between valid positions - it can not handle a position in the middle of a -// multi-byte character. It is used to iterate through text more efficiently than MovePositionOutsideChar. -// A \r\n pair is treated as two characters. -int Document::NextPosition(int pos, int moveDir) const { - // If out of range, just return minimum/maximum value. - int increment = (moveDir > 0) ? 1 : -1; - if (pos + increment <= 0) - return 0; - if (pos + increment >= Length()) - return Length(); - - if (dbcsCodePage) { - if (SC_CP_UTF8 == dbcsCodePage) { - if (increment == 1) { - // Simple forward movement case so can avoid some checks - const unsigned char leadByte = static_cast(cb.CharAt(pos)); - if (UTF8IsAscii(leadByte)) { - // Single byte character or invalid - pos++; - } else { - const int widthCharBytes = UTF8BytesOfLead[leadByte]; - char charBytes[UTF8MaxBytes] = {static_cast(leadByte),0,0,0}; - for (int b=1; b(pos+b)); - int utf8status = UTF8Classify(reinterpret_cast(charBytes), widthCharBytes); - if (utf8status & UTF8MaskInvalid) - pos++; - else - pos += utf8status & UTF8MaskWidth; - } - } else { - // Examine byte before position - pos--; - unsigned char ch = static_cast(cb.CharAt(pos)); - // If ch is not a trail byte then pos is valid intercharacter position - if (UTF8IsTrailByte(ch)) { - // If ch is a trail byte in a valid UTF-8 character then return start of character - int startUTF = pos; - int endUTF = pos; - if (InGoodUTF8(pos, startUTF, endUTF)) { - pos = startUTF; - } - // Else invalid UTF-8 so return position of isolated trail byte - } - } - } else { - if (moveDir > 0) { - int mbsize = IsDBCSLeadByte(cb.CharAt(pos)) ? 2 : 1; - pos += mbsize; - if (pos > Length()) - pos = Length(); - } else { - // Anchor DBCS calculations at start of line because start of line can - // not be a DBCS trail byte. - int posStartLine = LineStart(LineFromPosition(pos)); - // See http://msdn.microsoft.com/en-us/library/cc194792%28v=MSDN.10%29.aspx - // http://msdn.microsoft.com/en-us/library/cc194790.aspx - if ((pos - 1) <= posStartLine) { - return pos - 1; - } else if (IsDBCSLeadByte(cb.CharAt(pos - 1))) { - // Must actually be trail byte - return pos - 2; - } else { - // Otherwise, step back until a non-lead-byte is found. - int posTemp = pos - 1; - while (posStartLine <= --posTemp && IsDBCSLeadByte(cb.CharAt(posTemp))) - ; - // Now posTemp+1 must point to the beginning of a character, - // so figure out whether we went back an even or an odd - // number of bytes and go back 1 or 2 bytes, respectively. - return (pos - 1 - ((pos - posTemp) & 1)); - } - } - } - } else { - pos += increment; - } - - return pos; -} - -bool Document::NextCharacter(int &pos, int moveDir) const { - // Returns true if pos changed - int posNext = NextPosition(pos, moveDir); - if (posNext == pos) { - return false; - } else { - pos = posNext; - return true; - } -} - -// Return -1 on out-of-bounds -int SCI_METHOD Document::GetRelativePosition(int positionStart, int characterOffset) const { - int pos = positionStart; - if (dbcsCodePage) { - const int increment = (characterOffset > 0) ? 1 : -1; - while (characterOffset != 0) { - const int posNext = NextPosition(pos, increment); - if (posNext == pos) - return INVALID_POSITION; - pos = posNext; - characterOffset -= increment; - } - } else { - pos = positionStart + characterOffset; - if ((pos < 0) || (pos > Length())) - return INVALID_POSITION; - } - return pos; -} - -int Document::GetRelativePositionUTF16(int positionStart, int characterOffset) const { - int pos = positionStart; - if (dbcsCodePage) { - const int increment = (characterOffset > 0) ? 1 : -1; - while (characterOffset != 0) { - const int posNext = NextPosition(pos, increment); - if (posNext == pos) - return INVALID_POSITION; - if (abs(pos-posNext) > 3) // 4 byte character = 2*UTF16. - characterOffset -= increment; - pos = posNext; - characterOffset -= increment; - } - } else { - pos = positionStart + characterOffset; - if ((pos < 0) || (pos > Length())) - return INVALID_POSITION; - } - return pos; -} - -int SCI_METHOD Document::GetCharacterAndWidth(int position, int *pWidth) const { - int character; - int bytesInCharacter = 1; - if (dbcsCodePage) { - const unsigned char leadByte = static_cast(cb.CharAt(position)); - if (SC_CP_UTF8 == dbcsCodePage) { - if (UTF8IsAscii(leadByte)) { - // Single byte character or invalid - character = leadByte; - } else { - const int widthCharBytes = UTF8BytesOfLead[leadByte]; - unsigned char charBytes[UTF8MaxBytes] = {leadByte,0,0,0}; - for (int b=1; b(cb.CharAt(position+b)); - int utf8status = UTF8Classify(charBytes, widthCharBytes); - if (utf8status & UTF8MaskInvalid) { - // Report as singleton surrogate values which are invalid Unicode - character = 0xDC80 + leadByte; - } else { - bytesInCharacter = utf8status & UTF8MaskWidth; - character = UnicodeFromUTF8(charBytes); - } - } - } else { - if (IsDBCSLeadByte(leadByte)) { - bytesInCharacter = 2; - character = (leadByte << 8) | static_cast(cb.CharAt(position+1)); - } else { - character = leadByte; - } - } - } else { - character = cb.CharAt(position); - } - if (pWidth) { - *pWidth = bytesInCharacter; - } - return character; -} - -int SCI_METHOD Document::CodePage() const { - return dbcsCodePage; -} - -bool SCI_METHOD Document::IsDBCSLeadByte(char ch) const { - // Byte ranges found in Wikipedia articles with relevant search strings in each case - unsigned char uch = static_cast(ch); - switch (dbcsCodePage) { - case 932: - // Shift_jis - return ((uch >= 0x81) && (uch <= 0x9F)) || - ((uch >= 0xE0) && (uch <= 0xFC)); - // Lead bytes F0 to FC may be a Microsoft addition. - case 936: - // GBK - return (uch >= 0x81) && (uch <= 0xFE); - case 949: - // Korean Wansung KS C-5601-1987 - return (uch >= 0x81) && (uch <= 0xFE); - case 950: - // Big5 - return (uch >= 0x81) && (uch <= 0xFE); - case 1361: - // Korean Johab KS C-5601-1992 - return - ((uch >= 0x84) && (uch <= 0xD3)) || - ((uch >= 0xD8) && (uch <= 0xDE)) || - ((uch >= 0xE0) && (uch <= 0xF9)); - } - return false; -} - -static inline bool IsSpaceOrTab(int ch) { - return ch == ' ' || ch == '\t'; -} - -// Need to break text into segments near lengthSegment but taking into -// account the encoding to not break inside a UTF-8 or DBCS character -// and also trying to avoid breaking inside a pair of combining characters. -// The segment length must always be long enough (more than 4 bytes) -// so that there will be at least one whole character to make a segment. -// For UTF-8, text must consist only of valid whole characters. -// In preference order from best to worst: -// 1) Break after space -// 2) Break before punctuation -// 3) Break after whole character - -int Document::SafeSegment(const char *text, int length, int lengthSegment) const { - if (length <= lengthSegment) - return length; - int lastSpaceBreak = -1; - int lastPunctuationBreak = -1; - int lastEncodingAllowedBreak = 0; - for (int j=0; j < lengthSegment;) { - unsigned char ch = static_cast(text[j]); - if (j > 0) { - if (IsSpaceOrTab(text[j - 1]) && !IsSpaceOrTab(text[j])) { - lastSpaceBreak = j; - } - if (ch < 'A') { - lastPunctuationBreak = j; - } - } - lastEncodingAllowedBreak = j; - - if (dbcsCodePage == SC_CP_UTF8) { - j += UTF8BytesOfLead[ch]; - } else if (dbcsCodePage) { - j += IsDBCSLeadByte(ch) ? 2 : 1; - } else { - j++; - } - } - if (lastSpaceBreak >= 0) { - return lastSpaceBreak; - } else if (lastPunctuationBreak >= 0) { - return lastPunctuationBreak; - } - return lastEncodingAllowedBreak; -} - -EncodingFamily Document::CodePageFamily() const { - if (SC_CP_UTF8 == dbcsCodePage) - return efUnicode; - else if (dbcsCodePage) - return efDBCS; - else - return efEightBit; -} - -void Document::ModifiedAt(int pos) { - if (endStyled > pos) - endStyled = pos; -} - -void Document::CheckReadOnly() { - if (cb.IsReadOnly() && enteredReadOnlyCount == 0) { - enteredReadOnlyCount++; - NotifyModifyAttempt(); - enteredReadOnlyCount--; - } -} - -// Document only modified by gateways DeleteChars, InsertString, Undo, Redo, and SetStyleAt. -// SetStyleAt does not change the persistent state of a document - -bool Document::DeleteChars(int pos, int len) { - if (pos < 0) - return false; - if (len <= 0) - return false; - if ((pos + len) > Length()) - return false; - CheckReadOnly(); - if (enteredModification != 0) { - return false; - } else { - enteredModification++; - if (!cb.IsReadOnly()) { - NotifyModified( - DocModification( - SC_MOD_BEFOREDELETE | SC_PERFORMED_USER, - pos, len, - 0, 0)); - int prevLinesTotal = LinesTotal(); - bool startSavePoint = cb.IsSavePoint(); - bool startSequence = false; - const char *text = cb.DeleteChars(pos, len, startSequence); - if (startSavePoint && cb.IsCollectingUndo()) - NotifySavePoint(!startSavePoint); - if ((pos < Length()) || (pos == 0)) - ModifiedAt(pos); - else - ModifiedAt(pos-1); - NotifyModified( - DocModification( - SC_MOD_DELETETEXT | SC_PERFORMED_USER | (startSequence?SC_STARTACTION:0), - pos, len, - LinesTotal() - prevLinesTotal, text)); - } - enteredModification--; - } - return !cb.IsReadOnly(); -} - -/** - * Insert a string with a length. - */ -int Document::InsertString(int position, const char *s, int insertLength) { - if (insertLength <= 0) { - return 0; - } - CheckReadOnly(); // Application may change read only state here - if (cb.IsReadOnly()) { - return 0; - } - if (enteredModification != 0) { - return 0; - } - enteredModification++; - insertionSet = false; - insertion.clear(); - NotifyModified( - DocModification( - SC_MOD_INSERTCHECK, - position, insertLength, - 0, s)); - if (insertionSet) { - s = insertion.c_str(); - insertLength = static_cast(insertion.length()); - } - NotifyModified( - DocModification( - SC_MOD_BEFOREINSERT | SC_PERFORMED_USER, - position, insertLength, - 0, s)); - int prevLinesTotal = LinesTotal(); - bool startSavePoint = cb.IsSavePoint(); - bool startSequence = false; - const char *text = cb.InsertString(position, s, insertLength, startSequence); - if (startSavePoint && cb.IsCollectingUndo()) - NotifySavePoint(!startSavePoint); - ModifiedAt(position); - NotifyModified( - DocModification( - SC_MOD_INSERTTEXT | SC_PERFORMED_USER | (startSequence?SC_STARTACTION:0), - position, insertLength, - LinesTotal() - prevLinesTotal, text)); - if (insertionSet) { // Free memory as could be large - std::string().swap(insertion); - } - enteredModification--; - return insertLength; -} - -void Document::ChangeInsertion(const char *s, int length) { - insertionSet = true; - insertion.assign(s, length); -} - -int SCI_METHOD Document::AddData(char *data, int length) { - try { - int position = Length(); - InsertString(position, data, length); - } catch (std::bad_alloc &) { - return SC_STATUS_BADALLOC; - } catch (...) { - return SC_STATUS_FAILURE; - } - return 0; -} - -void * SCI_METHOD Document::ConvertToDocument() { - return this; -} - -int Document::Undo() { - int newPos = -1; - CheckReadOnly(); - if ((enteredModification == 0) && (cb.IsCollectingUndo())) { - enteredModification++; - if (!cb.IsReadOnly()) { - bool startSavePoint = cb.IsSavePoint(); - bool multiLine = false; - int steps = cb.StartUndo(); - //Platform::DebugPrintf("Steps=%d\n", steps); - int coalescedRemovePos = -1; - int coalescedRemoveLen = 0; - int prevRemoveActionPos = -1; - int prevRemoveActionLen = 0; - for (int step = 0; step < steps; step++) { - const int prevLinesTotal = LinesTotal(); - const Action &action = cb.GetUndoStep(); - if (action.at == removeAction) { - NotifyModified(DocModification( - SC_MOD_BEFOREINSERT | SC_PERFORMED_UNDO, action)); - } else if (action.at == containerAction) { - DocModification dm(SC_MOD_CONTAINER | SC_PERFORMED_UNDO); - dm.token = action.position; - NotifyModified(dm); - if (!action.mayCoalesce) { - coalescedRemovePos = -1; - coalescedRemoveLen = 0; - prevRemoveActionPos = -1; - prevRemoveActionLen = 0; - } - } else { - NotifyModified(DocModification( - SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action)); - } - cb.PerformUndoStep(); - if (action.at != containerAction) { - ModifiedAt(action.position); - newPos = action.position; - } - - int modFlags = SC_PERFORMED_UNDO; - // With undo, an insertion action becomes a deletion notification - if (action.at == removeAction) { - newPos += action.lenData; - modFlags |= SC_MOD_INSERTTEXT; - if ((coalescedRemoveLen > 0) && - (action.position == prevRemoveActionPos || action.position == (prevRemoveActionPos + prevRemoveActionLen))) { - coalescedRemoveLen += action.lenData; - newPos = coalescedRemovePos + coalescedRemoveLen; - } else { - coalescedRemovePos = action.position; - coalescedRemoveLen = action.lenData; - } - prevRemoveActionPos = action.position; - prevRemoveActionLen = action.lenData; - } else if (action.at == insertAction) { - modFlags |= SC_MOD_DELETETEXT; - coalescedRemovePos = -1; - coalescedRemoveLen = 0; - prevRemoveActionPos = -1; - prevRemoveActionLen = 0; - } - if (steps > 1) - modFlags |= SC_MULTISTEPUNDOREDO; - const int linesAdded = LinesTotal() - prevLinesTotal; - if (linesAdded != 0) - multiLine = true; - if (step == steps - 1) { - modFlags |= SC_LASTSTEPINUNDOREDO; - if (multiLine) - modFlags |= SC_MULTILINEUNDOREDO; - } - NotifyModified(DocModification(modFlags, action.position, action.lenData, - linesAdded, action.data)); - } - - bool endSavePoint = cb.IsSavePoint(); - if (startSavePoint != endSavePoint) - NotifySavePoint(endSavePoint); - } - enteredModification--; - } - return newPos; -} - -int Document::Redo() { - int newPos = -1; - CheckReadOnly(); - if ((enteredModification == 0) && (cb.IsCollectingUndo())) { - enteredModification++; - if (!cb.IsReadOnly()) { - bool startSavePoint = cb.IsSavePoint(); - bool multiLine = false; - int steps = cb.StartRedo(); - for (int step = 0; step < steps; step++) { - const int prevLinesTotal = LinesTotal(); - const Action &action = cb.GetRedoStep(); - if (action.at == insertAction) { - NotifyModified(DocModification( - SC_MOD_BEFOREINSERT | SC_PERFORMED_REDO, action)); - } else if (action.at == containerAction) { - DocModification dm(SC_MOD_CONTAINER | SC_PERFORMED_REDO); - dm.token = action.position; - NotifyModified(dm); - } else { - NotifyModified(DocModification( - SC_MOD_BEFOREDELETE | SC_PERFORMED_REDO, action)); - } - cb.PerformRedoStep(); - if (action.at != containerAction) { - ModifiedAt(action.position); - newPos = action.position; - } - - int modFlags = SC_PERFORMED_REDO; - if (action.at == insertAction) { - newPos += action.lenData; - modFlags |= SC_MOD_INSERTTEXT; - } else if (action.at == removeAction) { - modFlags |= SC_MOD_DELETETEXT; - } - if (steps > 1) - modFlags |= SC_MULTISTEPUNDOREDO; - const int linesAdded = LinesTotal() - prevLinesTotal; - if (linesAdded != 0) - multiLine = true; - if (step == steps - 1) { - modFlags |= SC_LASTSTEPINUNDOREDO; - if (multiLine) - modFlags |= SC_MULTILINEUNDOREDO; - } - NotifyModified( - DocModification(modFlags, action.position, action.lenData, - linesAdded, action.data)); - } - - bool endSavePoint = cb.IsSavePoint(); - if (startSavePoint != endSavePoint) - NotifySavePoint(endSavePoint); - } - enteredModification--; - } - return newPos; -} - -void Document::DelChar(int pos) { - DeleteChars(pos, LenChar(pos)); -} - -void Document::DelCharBack(int pos) { - if (pos <= 0) { - return; - } else if (IsCrLf(pos - 2)) { - DeleteChars(pos - 2, 2); - } else if (dbcsCodePage) { - int startChar = NextPosition(pos, -1); - DeleteChars(startChar, pos - startChar); - } else { - DeleteChars(pos - 1, 1); - } -} - -static int NextTab(int pos, int tabSize) { - return ((pos / tabSize) + 1) * tabSize; -} - -static std::string CreateIndentation(int indent, int tabSize, bool insertSpaces) { - std::string indentation; - if (!insertSpaces) { - while (indent >= tabSize) { - indentation += '\t'; - indent -= tabSize; - } - } - while (indent > 0) { - indentation += ' '; - indent--; - } - return indentation; -} - -int SCI_METHOD Document::GetLineIndentation(int line) { - int indent = 0; - if ((line >= 0) && (line < LinesTotal())) { - int lineStart = LineStart(line); - int length = Length(); - for (int i = lineStart; i < length; i++) { - char ch = cb.CharAt(i); - if (ch == ' ') - indent++; - else if (ch == '\t') - indent = NextTab(indent, tabInChars); - else - return indent; - } - } - return indent; -} - -int Document::SetLineIndentation(int line, int indent) { - int indentOfLine = GetLineIndentation(line); - if (indent < 0) - indent = 0; - if (indent != indentOfLine) { - std::string linebuf = CreateIndentation(indent, tabInChars, !useTabs); - int thisLineStart = LineStart(line); - int indentPos = GetLineIndentPosition(line); - UndoGroup ug(this); - DeleteChars(thisLineStart, indentPos - thisLineStart); - return thisLineStart + InsertString(thisLineStart, linebuf.c_str(), - static_cast(linebuf.length())); - } else { - return GetLineIndentPosition(line); - } -} - -int Document::GetLineIndentPosition(int line) const { - if (line < 0) - return 0; - int pos = LineStart(line); - int length = Length(); - while ((pos < length) && IsSpaceOrTab(cb.CharAt(pos))) { - pos++; - } - return pos; -} - -int Document::GetColumn(int pos) { - int column = 0; - int line = LineFromPosition(pos); - if ((line >= 0) && (line < LinesTotal())) { - for (int i = LineStart(line); i < pos;) { - char ch = cb.CharAt(i); - if (ch == '\t') { - column = NextTab(column, tabInChars); - i++; - } else if (ch == '\r') { - return column; - } else if (ch == '\n') { - return column; - } else if (i >= Length()) { - return column; - } else { - column++; - i = NextPosition(i, 1); - } - } - } - return column; -} - -int Document::CountCharacters(int startPos, int endPos) const { - startPos = MovePositionOutsideChar(startPos, 1, false); - endPos = MovePositionOutsideChar(endPos, -1, false); - int count = 0; - int i = startPos; - while (i < endPos) { - count++; - if (IsCrLf(i)) - i++; - i = NextPosition(i, 1); - } - return count; -} - -int Document::CountUTF16(int startPos, int endPos) const { - startPos = MovePositionOutsideChar(startPos, 1, false); - endPos = MovePositionOutsideChar(endPos, -1, false); - int count = 0; - int i = startPos; - while (i < endPos) { - count++; - const int next = NextPosition(i, 1); - if ((next - i) > 3) - count++; - i = next; - } - return count; -} - -int Document::FindColumn(int line, int column) { - int position = LineStart(line); - if ((line >= 0) && (line < LinesTotal())) { - int columnCurrent = 0; - while ((columnCurrent < column) && (position < Length())) { - char ch = cb.CharAt(position); - if (ch == '\t') { - columnCurrent = NextTab(columnCurrent, tabInChars); - if (columnCurrent > column) - return position; - position++; - } else if (ch == '\r') { - return position; - } else if (ch == '\n') { - return position; - } else { - columnCurrent++; - position = NextPosition(position, 1); - } - } - } - return position; -} - -void Document::Indent(bool forwards, int lineBottom, int lineTop) { - // Dedent - suck white space off the front of the line to dedent by equivalent of a tab - for (int line = lineBottom; line >= lineTop; line--) { - int indentOfLine = GetLineIndentation(line); - if (forwards) { - if (LineStart(line) < LineEnd(line)) { - SetLineIndentation(line, indentOfLine + IndentSize()); - } - } else { - SetLineIndentation(line, indentOfLine - IndentSize()); - } - } -} - -// Convert line endings for a piece of text to a particular mode. -// Stop at len or when a NUL is found. -std::string Document::TransformLineEnds(const char *s, size_t len, int eolModeWanted) { - std::string dest; - for (size_t i = 0; (i < len) && (s[i]); i++) { - if (s[i] == '\n' || s[i] == '\r') { - if (eolModeWanted == SC_EOL_CR) { - dest.push_back('\r'); - } else if (eolModeWanted == SC_EOL_LF) { - dest.push_back('\n'); - } else { // eolModeWanted == SC_EOL_CRLF - dest.push_back('\r'); - dest.push_back('\n'); - } - if ((s[i] == '\r') && (i+1 < len) && (s[i+1] == '\n')) { - i++; - } - } else { - dest.push_back(s[i]); - } - } - return dest; -} - -void Document::ConvertLineEnds(int eolModeSet) { - UndoGroup ug(this); - - for (int pos = 0; pos < Length(); pos++) { - if (cb.CharAt(pos) == '\r') { - if (cb.CharAt(pos + 1) == '\n') { - // CRLF - if (eolModeSet == SC_EOL_CR) { - DeleteChars(pos + 1, 1); // Delete the LF - } else if (eolModeSet == SC_EOL_LF) { - DeleteChars(pos, 1); // Delete the CR - } else { - pos++; - } - } else { - // CR - if (eolModeSet == SC_EOL_CRLF) { - pos += InsertString(pos + 1, "\n", 1); // Insert LF - } else if (eolModeSet == SC_EOL_LF) { - pos += InsertString(pos, "\n", 1); // Insert LF - DeleteChars(pos, 1); // Delete CR - pos--; - } - } - } else if (cb.CharAt(pos) == '\n') { - // LF - if (eolModeSet == SC_EOL_CRLF) { - pos += InsertString(pos, "\r", 1); // Insert CR - } else if (eolModeSet == SC_EOL_CR) { - pos += InsertString(pos, "\r", 1); // Insert CR - DeleteChars(pos, 1); // Delete LF - pos--; - } - } - } - -} - -bool Document::IsWhiteLine(int line) const { - int currentChar = LineStart(line); - int endLine = LineEnd(line); - while (currentChar < endLine) { - if (cb.CharAt(currentChar) != ' ' && cb.CharAt(currentChar) != '\t') { - return false; - } - ++currentChar; - } - return true; -} - -int Document::ParaUp(int pos) const { - int line = LineFromPosition(pos); - line--; - while (line >= 0 && IsWhiteLine(line)) { // skip empty lines - line--; - } - while (line >= 0 && !IsWhiteLine(line)) { // skip non-empty lines - line--; - } - line++; - return LineStart(line); -} - -int Document::ParaDown(int pos) const { - int line = LineFromPosition(pos); - while (line < LinesTotal() && !IsWhiteLine(line)) { // skip non-empty lines - line++; - } - while (line < LinesTotal() && IsWhiteLine(line)) { // skip empty lines - line++; - } - if (line < LinesTotal()) - return LineStart(line); - else // end of a document - return LineEnd(line-1); -} - -CharClassify::cc Document::WordCharClass(unsigned char ch) const { - if ((SC_CP_UTF8 == dbcsCodePage) && (!UTF8IsAscii(ch))) - return CharClassify::ccWord; - return charClass.GetClass(ch); -} - -/** - * Used by commmands that want to select whole words. - * Finds the start of word at pos when delta < 0 or the end of the word when delta >= 0. - */ -int Document::ExtendWordSelect(int pos, int delta, bool onlyWordCharacters) { - CharClassify::cc ccStart = CharClassify::ccWord; - if (delta < 0) { - if (!onlyWordCharacters) - ccStart = WordCharClass(cb.CharAt(pos-1)); - while (pos > 0 && (WordCharClass(cb.CharAt(pos - 1)) == ccStart)) - pos--; - } else { - if (!onlyWordCharacters && pos < Length()) - ccStart = WordCharClass(cb.CharAt(pos)); - while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == ccStart)) - pos++; - } - return MovePositionOutsideChar(pos, delta, true); -} - -/** - * Find the start of the next word in either a forward (delta >= 0) or backwards direction - * (delta < 0). - * This is looking for a transition between character classes although there is also some - * additional movement to transit white space. - * Used by cursor movement by word commands. - */ -int Document::NextWordStart(int pos, int delta) { - if (delta < 0) { - while (pos > 0 && (WordCharClass(cb.CharAt(pos - 1)) == CharClassify::ccSpace)) - pos--; - if (pos > 0) { - CharClassify::cc ccStart = WordCharClass(cb.CharAt(pos-1)); - while (pos > 0 && (WordCharClass(cb.CharAt(pos - 1)) == ccStart)) { - pos--; - } - } - } else { - CharClassify::cc ccStart = WordCharClass(cb.CharAt(pos)); - while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == ccStart)) - pos++; - while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == CharClassify::ccSpace)) - pos++; - } - return pos; -} - -/** - * Find the end of the next word in either a forward (delta >= 0) or backwards direction - * (delta < 0). - * This is looking for a transition between character classes although there is also some - * additional movement to transit white space. - * Used by cursor movement by word commands. - */ -int Document::NextWordEnd(int pos, int delta) { - if (delta < 0) { - if (pos > 0) { - CharClassify::cc ccStart = WordCharClass(cb.CharAt(pos-1)); - if (ccStart != CharClassify::ccSpace) { - while (pos > 0 && WordCharClass(cb.CharAt(pos - 1)) == ccStart) { - pos--; - } - } - while (pos > 0 && WordCharClass(cb.CharAt(pos - 1)) == CharClassify::ccSpace) { - pos--; - } - } - } else { - while (pos < Length() && WordCharClass(cb.CharAt(pos)) == CharClassify::ccSpace) { - pos++; - } - if (pos < Length()) { - CharClassify::cc ccStart = WordCharClass(cb.CharAt(pos)); - while (pos < Length() && WordCharClass(cb.CharAt(pos)) == ccStart) { - pos++; - } - } - } - return pos; -} - -/** - * Check that the character at the given position is a word or punctuation character and that - * the previous character is of a different character class. - */ -bool Document::IsWordStartAt(int pos) const { - if (pos > 0) { - CharClassify::cc ccPos = WordCharClass(CharAt(pos)); - return (ccPos == CharClassify::ccWord || ccPos == CharClassify::ccPunctuation) && - (ccPos != WordCharClass(CharAt(pos - 1))); - } - return true; -} - -/** - * Check that the character at the given position is a word or punctuation character and that - * the next character is of a different character class. - */ -bool Document::IsWordEndAt(int pos) const { - if (pos < Length()) { - CharClassify::cc ccPrev = WordCharClass(CharAt(pos-1)); - return (ccPrev == CharClassify::ccWord || ccPrev == CharClassify::ccPunctuation) && - (ccPrev != WordCharClass(CharAt(pos))); - } - return true; -} - -/** - * Check that the given range is has transitions between character classes at both - * ends and where the characters on the inside are word or punctuation characters. - */ -bool Document::IsWordAt(int start, int end) const { - return IsWordStartAt(start) && IsWordEndAt(end); -} - -bool Document::MatchesWordOptions(bool word, bool wordStart, int pos, int length) const { - return (!word && !wordStart) || - (word && IsWordAt(pos, pos + length)) || - (wordStart && IsWordStartAt(pos)); -} - -bool Document::HasCaseFolder(void) const { - return pcf != 0; -} - -void Document::SetCaseFolder(CaseFolder *pcf_) { - delete pcf; - pcf = pcf_; -} - -Document::CharacterExtracted Document::ExtractCharacter(int position) const { - const unsigned char leadByte = static_cast(cb.CharAt(position)); - if (UTF8IsAscii(leadByte)) { - // Common case: ASCII character - return CharacterExtracted(leadByte, 1); - } - const int widthCharBytes = UTF8BytesOfLead[leadByte]; - unsigned char charBytes[UTF8MaxBytes] = { leadByte, 0, 0, 0 }; - for (int b=1; b(cb.CharAt(position + b)); - int utf8status = UTF8Classify(charBytes, widthCharBytes); - if (utf8status & UTF8MaskInvalid) { - // Treat as invalid and use up just one byte - return CharacterExtracted(unicodeReplacementChar, 1); - } else { - return CharacterExtracted(UnicodeFromUTF8(charBytes), utf8status & UTF8MaskWidth); - } -} - -/** - * Find text in document, supporting both forward and backward - * searches (just pass minPos > maxPos to do a backward search) - * Has not been tested with backwards DBCS searches yet. - */ -long Document::FindText(int minPos, int maxPos, const char *search, - bool caseSensitive, bool word, bool wordStart, bool regExp, int flags, - int *length) { - if (*length <= 0) - return minPos; - if (regExp) { - if (!regex) - regex = CreateRegexSearch(&charClass); - return regex->FindText(this, minPos, maxPos, search, caseSensitive, word, wordStart, flags, length); - } else { - - const bool forward = minPos <= maxPos; - const int increment = forward ? 1 : -1; - - // Range endpoints should not be inside DBCS characters, but just in case, move them. - const int startPos = MovePositionOutsideChar(minPos, increment, false); - const int endPos = MovePositionOutsideChar(maxPos, increment, false); - - // Compute actual search ranges needed - const int lengthFind = *length; - - //Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind); - const int limitPos = Platform::Maximum(startPos, endPos); - int pos = startPos; - if (!forward) { - // Back all of a character - pos = NextPosition(pos, increment); - } - if (caseSensitive) { - const int endSearch = (startPos <= endPos) ? endPos - lengthFind + 1 : endPos; - const char charStartSearch = search[0]; - while (forward ? (pos < endSearch) : (pos >= endSearch)) { - if (CharAt(pos) == charStartSearch) { - bool found = (pos + lengthFind) <= limitPos; - for (int indexSearch = 1; (indexSearch < lengthFind) && found; indexSearch++) { - found = CharAt(pos + indexSearch) == search[indexSearch]; - } - if (found && MatchesWordOptions(word, wordStart, pos, lengthFind)) { - return pos; - } - } - if (!NextCharacter(pos, increment)) - break; - } - } else if (SC_CP_UTF8 == dbcsCodePage) { - const size_t maxFoldingExpansion = 4; - std::vector searchThing(lengthFind * UTF8MaxBytes * maxFoldingExpansion + 1); - const int lenSearch = static_cast( - pcf->Fold(&searchThing[0], searchThing.size(), search, lengthFind)); - char bytes[UTF8MaxBytes + 1]; - char folded[UTF8MaxBytes * maxFoldingExpansion + 1]; - while (forward ? (pos < endPos) : (pos >= endPos)) { - int widthFirstCharacter = 0; - int posIndexDocument = pos; - int indexSearch = 0; - bool characterMatches = true; - for (;;) { - const unsigned char leadByte = static_cast(cb.CharAt(posIndexDocument)); - bytes[0] = leadByte; - int widthChar = 1; - if (!UTF8IsAscii(leadByte)) { - const int widthCharBytes = UTF8BytesOfLead[leadByte]; - for (int b=1; b(bytes), widthCharBytes) & UTF8MaskWidth; - } - if (!widthFirstCharacter) - widthFirstCharacter = widthChar; - if ((posIndexDocument + widthChar) > limitPos) - break; - const int lenFlat = static_cast(pcf->Fold(folded, sizeof(folded), bytes, widthChar)); - folded[lenFlat] = 0; - // Does folded match the buffer - characterMatches = 0 == memcmp(folded, &searchThing[0] + indexSearch, lenFlat); - if (!characterMatches) - break; - posIndexDocument += widthChar; - indexSearch += lenFlat; - if (indexSearch >= lenSearch) - break; - } - if (characterMatches && (indexSearch == static_cast(lenSearch))) { - if (MatchesWordOptions(word, wordStart, pos, posIndexDocument - pos)) { - *length = posIndexDocument - pos; - return pos; - } - } - if (forward) { - pos += widthFirstCharacter; - } else { - if (!NextCharacter(pos, increment)) - break; - } - } - } else if (dbcsCodePage) { - const size_t maxBytesCharacter = 2; - const size_t maxFoldingExpansion = 4; - std::vector searchThing(lengthFind * maxBytesCharacter * maxFoldingExpansion + 1); - const int lenSearch = static_cast( - pcf->Fold(&searchThing[0], searchThing.size(), search, lengthFind)); - while (forward ? (pos < endPos) : (pos >= endPos)) { - int indexDocument = 0; - int indexSearch = 0; - bool characterMatches = true; - while (characterMatches && - ((pos + indexDocument) < limitPos) && - (indexSearch < lenSearch)) { - char bytes[maxBytesCharacter + 1]; - bytes[0] = cb.CharAt(pos + indexDocument); - const int widthChar = IsDBCSLeadByte(bytes[0]) ? 2 : 1; - if (widthChar == 2) - bytes[1] = cb.CharAt(pos + indexDocument + 1); - if ((pos + indexDocument + widthChar) > limitPos) - break; - char folded[maxBytesCharacter * maxFoldingExpansion + 1]; - const int lenFlat = static_cast(pcf->Fold(folded, sizeof(folded), bytes, widthChar)); - folded[lenFlat] = 0; - // Does folded match the buffer - characterMatches = 0 == memcmp(folded, &searchThing[0] + indexSearch, lenFlat); - indexDocument += widthChar; - indexSearch += lenFlat; - } - if (characterMatches && (indexSearch == static_cast(lenSearch))) { - if (MatchesWordOptions(word, wordStart, pos, indexDocument)) { - *length = indexDocument; - return pos; - } - } - if (!NextCharacter(pos, increment)) - break; - } - } else { - const int endSearch = (startPos <= endPos) ? endPos - lengthFind + 1 : endPos; - std::vector searchThing(lengthFind + 1); - pcf->Fold(&searchThing[0], searchThing.size(), search, lengthFind); - while (forward ? (pos < endSearch) : (pos >= endSearch)) { - bool found = (pos + lengthFind) <= limitPos; - for (int indexSearch = 0; (indexSearch < lengthFind) && found; indexSearch++) { - char ch = CharAt(pos + indexSearch); - char folded[2]; - pcf->Fold(folded, sizeof(folded), &ch, 1); - found = folded[0] == searchThing[indexSearch]; - } - if (found && MatchesWordOptions(word, wordStart, pos, lengthFind)) { - return pos; - } - if (!NextCharacter(pos, increment)) - break; - } - } - } - //Platform::DebugPrintf("Not found\n"); - return -1; -} - -const char *Document::SubstituteByPosition(const char *text, int *length) { - if (regex) - return regex->SubstituteByPosition(this, text, length); - else - return 0; -} - -int Document::LinesTotal() const { - return cb.Lines(); -} - -void Document::SetDefaultCharClasses(bool includeWordClass) { - charClass.SetDefaultCharClasses(includeWordClass); -} - -void Document::SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass) { - charClass.SetCharClasses(chars, newCharClass); -} - -int Document::GetCharsOfClass(CharClassify::cc characterClass, unsigned char *buffer) { - return charClass.GetCharsOfClass(characterClass, buffer); -} - -void SCI_METHOD Document::StartStyling(int position, char) { - endStyled = position; -} - -bool SCI_METHOD Document::SetStyleFor(int length, char style) { - if (enteredStyling != 0) { - return false; - } else { - enteredStyling++; - int prevEndStyled = endStyled; - if (cb.SetStyleFor(endStyled, length, style)) { - DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER, - prevEndStyled, length); - NotifyModified(mh); - } - endStyled += length; - enteredStyling--; - return true; - } -} - -bool SCI_METHOD Document::SetStyles(int length, const char *styles) { - if (enteredStyling != 0) { - return false; - } else { - enteredStyling++; - bool didChange = false; - int startMod = 0; - int endMod = 0; - for (int iPos = 0; iPos < length; iPos++, endStyled++) { - PLATFORM_ASSERT(endStyled < Length()); - if (cb.SetStyleAt(endStyled, styles[iPos])) { - if (!didChange) { - startMod = endStyled; - } - didChange = true; - endMod = endStyled; - } - } - if (didChange) { - DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER, - startMod, endMod - startMod + 1); - NotifyModified(mh); - } - enteredStyling--; - return true; - } -} - -void Document::EnsureStyledTo(int pos) { - if ((enteredStyling == 0) && (pos > GetEndStyled())) { - IncrementStyleClock(); - if (pli && !pli->UseContainerLexing()) { - int lineEndStyled = LineFromPosition(GetEndStyled()); - int endStyledTo = LineStart(lineEndStyled); - pli->Colourise(endStyledTo, pos); - } else { - // Ask the watchers to style, and stop as soon as one responds. - for (std::vector::iterator it = watchers.begin(); - (pos > GetEndStyled()) && (it != watchers.end()); ++it) { - it->watcher->NotifyStyleNeeded(this, it->userData, pos); - } - } - } -} - -void Document::LexerChanged() { - // Tell the watchers the lexer has changed. - for (std::vector::iterator it = watchers.begin(); it != watchers.end(); ++it) { - it->watcher->NotifyLexerChanged(this, it->userData); - } -} - -int SCI_METHOD Document::SetLineState(int line, int state) { - int statePrevious = static_cast(perLineData[ldState])->SetLineState(line, state); - if (state != statePrevious) { - DocModification mh(SC_MOD_CHANGELINESTATE, LineStart(line), 0, 0, 0, line); - NotifyModified(mh); - } - return statePrevious; -} - -int SCI_METHOD Document::GetLineState(int line) const { - return static_cast(perLineData[ldState])->GetLineState(line); -} - -int Document::GetMaxLineState() { - return static_cast(perLineData[ldState])->GetMaxLineState(); -} - -void SCI_METHOD Document::ChangeLexerState(int start, int end) { - DocModification mh(SC_MOD_LEXERSTATE, start, end-start, 0, 0, 0); - NotifyModified(mh); -} - -StyledText Document::MarginStyledText(int line) const { - LineAnnotation *pla = static_cast(perLineData[ldMargin]); - return StyledText(pla->Length(line), pla->Text(line), - pla->MultipleStyles(line), pla->Style(line), pla->Styles(line)); -} - -void Document::MarginSetText(int line, const char *text) { - static_cast(perLineData[ldMargin])->SetText(line, text); - DocModification mh(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line); - NotifyModified(mh); -} - -void Document::MarginSetStyle(int line, int style) { - static_cast(perLineData[ldMargin])->SetStyle(line, style); - NotifyModified(DocModification(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line)); -} - -void Document::MarginSetStyles(int line, const unsigned char *styles) { - static_cast(perLineData[ldMargin])->SetStyles(line, styles); - NotifyModified(DocModification(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line)); -} - -void Document::MarginClearAll() { - int maxEditorLine = LinesTotal(); - for (int l=0; l(perLineData[ldMargin])->ClearAll(); -} - -StyledText Document::AnnotationStyledText(int line) const { - LineAnnotation *pla = static_cast(perLineData[ldAnnotation]); - return StyledText(pla->Length(line), pla->Text(line), - pla->MultipleStyles(line), pla->Style(line), pla->Styles(line)); -} - -void Document::AnnotationSetText(int line, const char *text) { - if (line >= 0 && line < LinesTotal()) { - const int linesBefore = AnnotationLines(line); - static_cast(perLineData[ldAnnotation])->SetText(line, text); - const int linesAfter = AnnotationLines(line); - DocModification mh(SC_MOD_CHANGEANNOTATION, LineStart(line), 0, 0, 0, line); - mh.annotationLinesAdded = linesAfter - linesBefore; - NotifyModified(mh); - } -} - -void Document::AnnotationSetStyle(int line, int style) { - static_cast(perLineData[ldAnnotation])->SetStyle(line, style); - DocModification mh(SC_MOD_CHANGEANNOTATION, LineStart(line), 0, 0, 0, line); - NotifyModified(mh); -} - -void Document::AnnotationSetStyles(int line, const unsigned char *styles) { - if (line >= 0 && line < LinesTotal()) { - static_cast(perLineData[ldAnnotation])->SetStyles(line, styles); - } -} - -int Document::AnnotationLines(int line) const { - return static_cast(perLineData[ldAnnotation])->Lines(line); -} - -void Document::AnnotationClearAll() { - int maxEditorLine = LinesTotal(); - for (int l=0; l(perLineData[ldAnnotation])->ClearAll(); -} - -void Document::IncrementStyleClock() { - styleClock = (styleClock + 1) % 0x100000; -} - -void SCI_METHOD Document::DecorationFillRange(int position, int value, int fillLength) { - if (decorations.FillRange(position, value, fillLength)) { - DocModification mh(SC_MOD_CHANGEINDICATOR | SC_PERFORMED_USER, - position, fillLength); - NotifyModified(mh); - } -} - -bool Document::AddWatcher(DocWatcher *watcher, void *userData) { - WatcherWithUserData wwud(watcher, userData); - std::vector::iterator it = - std::find(watchers.begin(), watchers.end(), wwud); - if (it != watchers.end()) - return false; - watchers.push_back(wwud); - return true; -} - -bool Document::RemoveWatcher(DocWatcher *watcher, void *userData) { - std::vector::iterator it = - std::find(watchers.begin(), watchers.end(), WatcherWithUserData(watcher, userData)); - if (it != watchers.end()) { - watchers.erase(it); - return true; - } - return false; -} - -void Document::NotifyModifyAttempt() { - for (std::vector::iterator it = watchers.begin(); it != watchers.end(); ++it) { - it->watcher->NotifyModifyAttempt(this, it->userData); - } -} - -void Document::NotifySavePoint(bool atSavePoint) { - for (std::vector::iterator it = watchers.begin(); it != watchers.end(); ++it) { - it->watcher->NotifySavePoint(this, it->userData, atSavePoint); - } -} - -void Document::NotifyModified(DocModification mh) { - if (mh.modificationType & SC_MOD_INSERTTEXT) { - decorations.InsertSpace(mh.position, mh.length); - } else if (mh.modificationType & SC_MOD_DELETETEXT) { - decorations.DeleteRange(mh.position, mh.length); - } - for (std::vector::iterator it = watchers.begin(); it != watchers.end(); ++it) { - it->watcher->NotifyModified(this, mh, it->userData); - } -} - -bool Document::IsWordPartSeparator(char ch) const { - return (WordCharClass(ch) == CharClassify::ccWord) && IsPunctuation(ch); -} - -int Document::WordPartLeft(int pos) { - if (pos > 0) { - --pos; - char startChar = cb.CharAt(pos); - if (IsWordPartSeparator(startChar)) { - while (pos > 0 && IsWordPartSeparator(cb.CharAt(pos))) { - --pos; - } - } - if (pos > 0) { - startChar = cb.CharAt(pos); - --pos; - if (IsLowerCase(startChar)) { - while (pos > 0 && IsLowerCase(cb.CharAt(pos))) - --pos; - if (!IsUpperCase(cb.CharAt(pos)) && !IsLowerCase(cb.CharAt(pos))) - ++pos; - } else if (IsUpperCase(startChar)) { - while (pos > 0 && IsUpperCase(cb.CharAt(pos))) - --pos; - if (!IsUpperCase(cb.CharAt(pos))) - ++pos; - } else if (IsADigit(startChar)) { - while (pos > 0 && IsADigit(cb.CharAt(pos))) - --pos; - if (!IsADigit(cb.CharAt(pos))) - ++pos; - } else if (IsPunctuation(startChar)) { - while (pos > 0 && IsPunctuation(cb.CharAt(pos))) - --pos; - if (!IsPunctuation(cb.CharAt(pos))) - ++pos; - } else if (isspacechar(startChar)) { - while (pos > 0 && isspacechar(cb.CharAt(pos))) - --pos; - if (!isspacechar(cb.CharAt(pos))) - ++pos; - } else if (!IsASCII(startChar)) { - while (pos > 0 && !IsASCII(cb.CharAt(pos))) - --pos; - if (IsASCII(cb.CharAt(pos))) - ++pos; - } else { - ++pos; - } - } - } - return pos; -} - -int Document::WordPartRight(int pos) { - char startChar = cb.CharAt(pos); - int length = Length(); - if (IsWordPartSeparator(startChar)) { - while (pos < length && IsWordPartSeparator(cb.CharAt(pos))) - ++pos; - startChar = cb.CharAt(pos); - } - if (!IsASCII(startChar)) { - while (pos < length && !IsASCII(cb.CharAt(pos))) - ++pos; - } else if (IsLowerCase(startChar)) { - while (pos < length && IsLowerCase(cb.CharAt(pos))) - ++pos; - } else if (IsUpperCase(startChar)) { - if (IsLowerCase(cb.CharAt(pos + 1))) { - ++pos; - while (pos < length && IsLowerCase(cb.CharAt(pos))) - ++pos; - } else { - while (pos < length && IsUpperCase(cb.CharAt(pos))) - ++pos; - } - if (IsLowerCase(cb.CharAt(pos)) && IsUpperCase(cb.CharAt(pos - 1))) - --pos; - } else if (IsADigit(startChar)) { - while (pos < length && IsADigit(cb.CharAt(pos))) - ++pos; - } else if (IsPunctuation(startChar)) { - while (pos < length && IsPunctuation(cb.CharAt(pos))) - ++pos; - } else if (isspacechar(startChar)) { - while (pos < length && isspacechar(cb.CharAt(pos))) - ++pos; - } else { - ++pos; - } - return pos; -} - -bool IsLineEndChar(char c) { - return (c == '\n' || c == '\r'); -} - -int Document::ExtendStyleRange(int pos, int delta, bool singleLine) { - int sStart = cb.StyleAt(pos); - if (delta < 0) { - while (pos > 0 && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos)))) - pos--; - pos++; - } else { - while (pos < (Length()) && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos)))) - pos++; - } - return pos; -} - -static char BraceOpposite(char ch) { - switch (ch) { - case '(': - return ')'; - case ')': - return '('; - case '[': - return ']'; - case ']': - return '['; - case '{': - return '}'; - case '}': - return '{'; - case '<': - return '>'; - case '>': - return '<'; - default: - return '\0'; - } -} - -// TODO: should be able to extend styled region to find matching brace -int Document::BraceMatch(int position, int /*maxReStyle*/) { - char chBrace = CharAt(position); - char chSeek = BraceOpposite(chBrace); - if (chSeek == '\0') - return - 1; - char styBrace = static_cast(StyleAt(position)); - int direction = -1; - if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<') - direction = 1; - int depth = 1; - position = NextPosition(position, direction); - while ((position >= 0) && (position < Length())) { - char chAtPos = CharAt(position); - char styAtPos = static_cast(StyleAt(position)); - if ((position > GetEndStyled()) || (styAtPos == styBrace)) { - if (chAtPos == chBrace) - depth++; - if (chAtPos == chSeek) - depth--; - if (depth == 0) - return position; - } - int positionBeforeMove = position; - position = NextPosition(position, direction); - if (position == positionBeforeMove) - break; - } - return - 1; -} - -/** - * Implementation of RegexSearchBase for the default built-in regular expression engine - */ -class BuiltinRegex : public RegexSearchBase { -public: - explicit BuiltinRegex(CharClassify *charClassTable) : search(charClassTable) {} - - virtual ~BuiltinRegex() { - } - - virtual long FindText(Document *doc, int minPos, int maxPos, const char *s, - bool caseSensitive, bool word, bool wordStart, int flags, - int *length); - - virtual const char *SubstituteByPosition(Document *doc, const char *text, int *length); - -private: - RESearch search; - std::string substituted; -}; - -namespace { - -/** -* RESearchRange keeps track of search range. -*/ -class RESearchRange { -public: - const Document *doc; - int increment; - int startPos; - int endPos; - int lineRangeStart; - int lineRangeEnd; - int lineRangeBreak; - RESearchRange(const Document *doc_, int minPos, int maxPos) : doc(doc_) { - increment = (minPos <= maxPos) ? 1 : -1; - - // Range endpoints should not be inside DBCS characters, but just in case, move them. - startPos = doc->MovePositionOutsideChar(minPos, 1, false); - endPos = doc->MovePositionOutsideChar(maxPos, 1, false); - - lineRangeStart = doc->LineFromPosition(startPos); - lineRangeEnd = doc->LineFromPosition(endPos); - if ((increment == 1) && - (startPos >= doc->LineEnd(lineRangeStart)) && - (lineRangeStart < lineRangeEnd)) { - // the start position is at end of line or between line end characters. - lineRangeStart++; - startPos = doc->LineStart(lineRangeStart); - } else if ((increment == -1) && - (startPos <= doc->LineStart(lineRangeStart)) && - (lineRangeStart > lineRangeEnd)) { - // the start position is at beginning of line. - lineRangeStart--; - startPos = doc->LineEnd(lineRangeStart); - } - lineRangeBreak = lineRangeEnd + increment; - } - Range LineRange(int line) const { - Range range(doc->LineStart(line), doc->LineEnd(line)); - if (increment == 1) { - if (line == lineRangeStart) - range.start = startPos; - if (line == lineRangeEnd) - range.end = endPos; - } else { - if (line == lineRangeEnd) - range.start = endPos; - if (line == lineRangeStart) - range.end = startPos; - } - return range; - } -}; - -// Define a way for the Regular Expression code to access the document -class DocumentIndexer : public CharacterIndexer { - Document *pdoc; - int end; -public: - DocumentIndexer(Document *pdoc_, int end_) : - pdoc(pdoc_), end(end_) { - } - - virtual ~DocumentIndexer() { - } - - virtual char CharAt(int index) { - if (index < 0 || index >= end) - return 0; - else - return pdoc->CharAt(index); - } -}; - -#ifdef CXX11_REGEX - -class ByteIterator : public std::iterator { -public: - const Document *doc; - Position position; - ByteIterator(const Document *doc_ = 0, Position position_ = 0) : doc(doc_), position(position_) { - } - ByteIterator(const ByteIterator &other) { - doc = other.doc; - position = other.position; - } - ByteIterator &operator=(const ByteIterator &other) { - if (this != &other) { - doc = other.doc; - position = other.position; - } - return *this; - } - char operator*() const { - return doc->CharAt(position); - } - ByteIterator &operator++() { - position++; - return *this; - } - ByteIterator operator++(int) { - ByteIterator retVal(*this); - position++; - return retVal; - } - ByteIterator &operator--() { - position--; - return *this; - } - bool operator==(const ByteIterator &other) const { - return doc == other.doc && position == other.position; - } - bool operator!=(const ByteIterator &other) const { - return doc != other.doc || position != other.position; - } - int Pos() const { - return position; - } - int PosRoundUp() const { - return position; - } -}; - -// On Windows, wchar_t is 16 bits wide and on Unix it is 32 bits wide. -// Would be better to use sizeof(wchar_t) or similar to differentiate -// but easier for now to hard-code platforms. -// C++11 has char16_t and char32_t but neither Clang nor Visual C++ -// appear to allow specializing basic_regex over these. - -#ifdef _WIN32 -#define WCHAR_T_IS_16 1 -#else -#define WCHAR_T_IS_16 0 -#endif - -#if WCHAR_T_IS_16 - -// On Windows, report non-BMP characters as 2 separate surrogates as that -// matches wregex since it is based on wchar_t. -class UTF8Iterator : public std::iterator { - // These 3 fields determine the iterator position and are used for comparisons - const Document *doc; - Position position; - size_t characterIndex; - // Remaining fields are derived from the determining fields so are excluded in comparisons - unsigned int lenBytes; - size_t lenCharacters; - wchar_t buffered[2]; -public: - UTF8Iterator(const Document *doc_ = 0, Position position_ = 0) : - doc(doc_), position(position_), characterIndex(0), lenBytes(0), lenCharacters(0) { - buffered[0] = 0; - buffered[1] = 0; - if (doc) { - ReadCharacter(); - } - } - UTF8Iterator(const UTF8Iterator &other) { - doc = other.doc; - position = other.position; - characterIndex = other.characterIndex; - lenBytes = other.lenBytes; - lenCharacters = other.lenCharacters; - buffered[0] = other.buffered[0]; - buffered[1] = other.buffered[1]; - } - UTF8Iterator &operator=(const UTF8Iterator &other) { - if (this != &other) { - doc = other.doc; - position = other.position; - characterIndex = other.characterIndex; - lenBytes = other.lenBytes; - lenCharacters = other.lenCharacters; - buffered[0] = other.buffered[0]; - buffered[1] = other.buffered[1]; - } - return *this; - } - wchar_t operator*() const { - assert(lenCharacters != 0); - return buffered[characterIndex]; - } - UTF8Iterator &operator++() { - if ((characterIndex + 1) < (lenCharacters)) { - characterIndex++; - } else { - position += lenBytes; - ReadCharacter(); - characterIndex = 0; - } - return *this; - } - UTF8Iterator operator++(int) { - UTF8Iterator retVal(*this); - if ((characterIndex + 1) < (lenCharacters)) { - characterIndex++; - } else { - position += lenBytes; - ReadCharacter(); - characterIndex = 0; - } - return retVal; - } - UTF8Iterator &operator--() { - if (characterIndex) { - characterIndex--; - } else { - position = doc->NextPosition(position, -1); - ReadCharacter(); - characterIndex = lenCharacters - 1; - } - return *this; - } - bool operator==(const UTF8Iterator &other) const { - // Only test the determining fields, not the character widths and values derived from this - return doc == other.doc && - position == other.position && - characterIndex == other.characterIndex; - } - bool operator!=(const UTF8Iterator &other) const { - // Only test the determining fields, not the character widths and values derived from this - return doc != other.doc || - position != other.position || - characterIndex != other.characterIndex; - } - int Pos() const { - return position; - } - int PosRoundUp() const { - if (characterIndex) - return position + lenBytes; // Force to end of character - else - return position; - } -private: - void ReadCharacter() { - Document::CharacterExtracted charExtracted = doc->ExtractCharacter(position); - lenBytes = charExtracted.widthBytes; - if (charExtracted.character == unicodeReplacementChar) { - lenCharacters = 1; - buffered[0] = static_cast(charExtracted.character); - } else { - lenCharacters = UTF16FromUTF32Character(charExtracted.character, buffered); - } - } -}; - -#else - -// On Unix, report non-BMP characters as single characters - -class UTF8Iterator : public std::iterator { - const Document *doc; - Position position; -public: - UTF8Iterator(const Document *doc_=0, Position position_=0) : doc(doc_), position(position_) { - } - UTF8Iterator(const UTF8Iterator &other) { - doc = other.doc; - position = other.position; - } - UTF8Iterator &operator=(const UTF8Iterator &other) { - if (this != &other) { - doc = other.doc; - position = other.position; - } - return *this; - } - wchar_t operator*() const { - Document::CharacterExtracted charExtracted = doc->ExtractCharacter(position); - return charExtracted.character; - } - UTF8Iterator &operator++() { - position = doc->NextPosition(position, 1); - return *this; - } - UTF8Iterator operator++(int) { - UTF8Iterator retVal(*this); - position = doc->NextPosition(position, 1); - return retVal; - } - UTF8Iterator &operator--() { - position = doc->NextPosition(position, -1); - return *this; - } - bool operator==(const UTF8Iterator &other) const { - return doc == other.doc && position == other.position; - } - bool operator!=(const UTF8Iterator &other) const { - return doc != other.doc || position != other.position; - } - int Pos() const { - return position; - } - int PosRoundUp() const { - return position; - } -}; - -#endif - -std::regex_constants::match_flag_type MatchFlags(const Document *doc, int startPos, int endPos) { - std::regex_constants::match_flag_type flagsMatch = std::regex_constants::match_default; - if (!doc->IsLineStartPosition(startPos)) - flagsMatch |= std::regex_constants::match_not_bol; - if (!doc->IsLineEndPosition(endPos)) - flagsMatch |= std::regex_constants::match_not_eol; - return flagsMatch; -} - -template -bool MatchOnLines(const Document *doc, const Regex ®exp, const RESearchRange &resr, RESearch &search) { - bool matched = false; - std::match_results match; - - // MSVC and libc++ have problems with ^ and $ matching line ends inside a range - // If they didn't then the line by line iteration could be removed for the forwards - // case and replaced with the following 4 lines: - // Iterator uiStart(doc, startPos); - // Iterator uiEnd(doc, endPos); - // flagsMatch = MatchFlags(doc, startPos, endPos); - // matched = std::regex_search(uiStart, uiEnd, match, regexp, flagsMatch); - - // Line by line. - for (int line = resr.lineRangeStart; line != resr.lineRangeBreak; line += resr.increment) { - const Range lineRange = resr.LineRange(line); - Iterator itStart(doc, lineRange.start); - Iterator itEnd(doc, lineRange.end); - std::regex_constants::match_flag_type flagsMatch = MatchFlags(doc, lineRange.start, lineRange.end); - matched = std::regex_search(itStart, itEnd, match, regexp, flagsMatch); - // Check for the last match on this line. - if (matched) { - if (resr.increment == -1) { - while (matched) { - Iterator itNext(doc, match[0].second.PosRoundUp()); - flagsMatch = MatchFlags(doc, itNext.Pos(), lineRange.end); - std::match_results matchNext; - matched = std::regex_search(itNext, itEnd, matchNext, regexp, flagsMatch); - if (matched) { - if (match[0].first == match[0].second) { - // Empty match means failure so exit - return false; - } - match = matchNext; - } - } - matched = true; - } - break; - } - } - if (matched) { - for (size_t co = 0; co < match.size(); co++) { - search.bopat[co] = match[co].first.Pos(); - search.eopat[co] = match[co].second.PosRoundUp(); - size_t lenMatch = search.eopat[co] - search.bopat[co]; - search.pat[co].resize(lenMatch); - for (size_t iPos = 0; iPos < lenMatch; iPos++) { - search.pat[co][iPos] = doc->CharAt(iPos + search.bopat[co]); - } - } - } - return matched; -} - -long Cxx11RegexFindText(Document *doc, int minPos, int maxPos, const char *s, - bool caseSensitive, int *length, RESearch &search) { - const RESearchRange resr(doc, minPos, maxPos); - try { - //ElapsedTime et; - std::regex::flag_type flagsRe = std::regex::ECMAScript; - // Flags that apper to have no effect: - // | std::regex::collate | std::regex::extended; - if (!caseSensitive) - flagsRe = flagsRe | std::regex::icase; - - // Clear the RESearch so can fill in matches - search.Clear(); - - bool matched = false; - if (SC_CP_UTF8 == doc->dbcsCodePage) { - unsigned int lenS = static_cast(strlen(s)); - std::vector ws(lenS + 1); -#if WCHAR_T_IS_16 - size_t outLen = UTF16FromUTF8(s, lenS, &ws[0], lenS); -#else - size_t outLen = UTF32FromUTF8(s, lenS, reinterpret_cast(&ws[0]), lenS); -#endif - ws[outLen] = 0; - std::wregex regexp; -#if defined(__APPLE__) - // Using a UTF-8 locale doesn't change to Unicode over a byte buffer so '.' - // is one byte not one character. - // However, on OS X this makes wregex act as Unicode - std::locale localeU("en_US.UTF-8"); - regexp.imbue(localeU); -#endif - regexp.assign(&ws[0], flagsRe); - matched = MatchOnLines(doc, regexp, resr, search); - - } else { - std::regex regexp; - regexp.assign(s, flagsRe); - matched = MatchOnLines(doc, regexp, resr, search); - } - - int posMatch = -1; - if (matched) { - posMatch = search.bopat[0]; - *length = search.eopat[0] - search.bopat[0]; - } - // Example - search in doc/ScintillaHistory.html for - // [[:upper:]]eta[[:space:]] - // On MacBook, normally around 1 second but with locale imbued -> 14 seconds. - //double durSearch = et.Duration(true); - //Platform::DebugPrintf("Search:%9.6g \n", durSearch); - return posMatch; - } catch (std::regex_error &) { - // Failed to create regular expression - throw RegexError(); - } catch (...) { - // Failed in some other way - return -1; - } -} - -#endif - -} - -long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s, - bool caseSensitive, bool, bool, int flags, - int *length) { - -#ifdef CXX11_REGEX - if (flags & SCFIND_CXX11REGEX) { - return Cxx11RegexFindText(doc, minPos, maxPos, s, - caseSensitive, length, search); - } -#endif - - const RESearchRange resr(doc, minPos, maxPos); - - const bool posix = (flags & SCFIND_POSIX) != 0; - - const char *errmsg = search.Compile(s, *length, caseSensitive, posix); - if (errmsg) { - return -1; - } - // Find a variable in a property file: \$(\([A-Za-z0-9_.]+\)) - // Replace first '.' with '-' in each property file variable reference: - // Search: \$(\([A-Za-z0-9_-]+\)\.\([A-Za-z0-9_.]+\)) - // Replace: $(\1-\2) - int pos = -1; - int lenRet = 0; - const char searchEnd = s[*length - 1]; - const char searchEndPrev = (*length > 1) ? s[*length - 2] : '\0'; - for (int line = resr.lineRangeStart; line != resr.lineRangeBreak; line += resr.increment) { - int startOfLine = doc->LineStart(line); - int endOfLine = doc->LineEnd(line); - if (resr.increment == 1) { - if (line == resr.lineRangeStart) { - if ((resr.startPos != startOfLine) && (s[0] == '^')) - continue; // Can't match start of line if start position after start of line - startOfLine = resr.startPos; - } - if (line == resr.lineRangeEnd) { - if ((resr.endPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\')) - continue; // Can't match end of line if end position before end of line - endOfLine = resr.endPos; - } - } else { - if (line == resr.lineRangeEnd) { - if ((resr.endPos != startOfLine) && (s[0] == '^')) - continue; // Can't match start of line if end position after start of line - startOfLine = resr.endPos; - } - if (line == resr.lineRangeStart) { - if ((resr.startPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\')) - continue; // Can't match end of line if start position before end of line - endOfLine = resr.startPos; - } - } - - DocumentIndexer di(doc, endOfLine); - int success = search.Execute(di, startOfLine, endOfLine); - if (success) { - pos = search.bopat[0]; - // Ensure only whole characters selected - search.eopat[0] = doc->MovePositionOutsideChar(search.eopat[0], 1, false); - lenRet = search.eopat[0] - search.bopat[0]; - // There can be only one start of a line, so no need to look for last match in line - if ((resr.increment == -1) && (s[0] != '^')) { - // Check for the last match on this line. - int repetitions = 1000; // Break out of infinite loop - while (success && (search.eopat[0] <= endOfLine) && (repetitions--)) { - success = search.Execute(di, pos+1, endOfLine); - if (success) { - if (search.eopat[0] <= minPos) { - pos = search.bopat[0]; - lenRet = search.eopat[0] - search.bopat[0]; - } else { - success = 0; - } - } - } - } - break; - } - } - *length = lenRet; - return pos; -} - -const char *BuiltinRegex::SubstituteByPosition(Document *doc, const char *text, int *length) { - substituted.clear(); - DocumentIndexer di(doc, doc->Length()); - search.GrabMatches(di); - for (int j = 0; j < *length; j++) { - if (text[j] == '\\') { - if (text[j + 1] >= '0' && text[j + 1] <= '9') { - unsigned int patNum = text[j + 1] - '0'; - unsigned int len = search.eopat[patNum] - search.bopat[patNum]; - if (!search.pat[patNum].empty()) // Will be null if try for a match that did not occur - substituted.append(search.pat[patNum].c_str(), len); - j++; - } else { - j++; - switch (text[j]) { - case 'a': - substituted.push_back('\a'); - break; - case 'b': - substituted.push_back('\b'); - break; - case 'f': - substituted.push_back('\f'); - break; - case 'n': - substituted.push_back('\n'); - break; - case 'r': - substituted.push_back('\r'); - break; - case 't': - substituted.push_back('\t'); - break; - case 'v': - substituted.push_back('\v'); - break; - case '\\': - substituted.push_back('\\'); - break; - default: - substituted.push_back('\\'); - j--; - } - } - } else { - substituted.push_back(text[j]); - } - } - *length = static_cast(substituted.length()); - return substituted.c_str(); -} - -#ifndef SCI_OWNREGEX - -#ifdef SCI_NAMESPACE - -RegexSearchBase *Scintilla::CreateRegexSearch(CharClassify *charClassTable) { - return new BuiltinRegex(charClassTable); -} - -#else - -RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable) { - return new BuiltinRegex(charClassTable); -} - -#endif - -#endif diff --git a/libs/qscintilla/src/Document.h b/libs/qscintilla/src/Document.h deleted file mode 100644 index 5e66dc2b6..000000000 --- a/libs/qscintilla/src/Document.h +++ /dev/null @@ -1,536 +0,0 @@ -// Scintilla source code edit control -/** @file Document.h - ** Text document that handles notifications, DBCS, styling, words and end of line. - **/ -// Copyright 1998-2011 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef DOCUMENT_H -#define DOCUMENT_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -/** - * A Position is a position within a document between two characters or at the beginning or end. - * Sometimes used as a character index where it identifies the character after the position. - */ -typedef int Position; -const Position invalidPosition = -1; - -enum EncodingFamily { efEightBit, efUnicode, efDBCS }; - -/** - * The range class represents a range of text in a document. - * The two values are not sorted as one end may be more significant than the other - * as is the case for the selection where the end position is the position of the caret. - * If either position is invalidPosition then the range is invalid and most operations will fail. - */ -class Range { -public: - Position start; - Position end; - - explicit Range(Position pos=0) : - start(pos), end(pos) { - } - Range(Position start_, Position end_) : - start(start_), end(end_) { - } - - bool operator==(const Range &other) const { - return (start == other.start) && (end == other.end); - } - - bool Valid() const { - return (start != invalidPosition) && (end != invalidPosition); - } - - Position First() const { - return (start <= end) ? start : end; - } - - Position Last() const { - return (start > end) ? start : end; - } - - // Is the position within the range? - bool Contains(Position pos) const { - if (start < end) { - return (pos >= start && pos <= end); - } else { - return (pos <= start && pos >= end); - } - } - - // Is the character after pos within the range? - bool ContainsCharacter(Position pos) const { - if (start < end) { - return (pos >= start && pos < end); - } else { - return (pos < start && pos >= end); - } - } - - bool Contains(Range other) const { - return Contains(other.start) && Contains(other.end); - } - - bool Overlaps(Range other) const { - return - Contains(other.start) || - Contains(other.end) || - other.Contains(start) || - other.Contains(end); - } -}; - -class DocWatcher; -class DocModification; -class Document; - -/** - * Interface class for regular expression searching - */ -class RegexSearchBase { -public: - virtual ~RegexSearchBase() {} - - virtual long FindText(Document *doc, int minPos, int maxPos, const char *s, - bool caseSensitive, bool word, bool wordStart, int flags, int *length) = 0; - - ///@return String with the substitutions, must remain valid until the next call or destruction - virtual const char *SubstituteByPosition(Document *doc, const char *text, int *length) = 0; -}; - -/// Factory function for RegexSearchBase -extern RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable); - -struct StyledText { - size_t length; - const char *text; - bool multipleStyles; - size_t style; - const unsigned char *styles; - StyledText(size_t length_, const char *text_, bool multipleStyles_, int style_, const unsigned char *styles_) : - length(length_), text(text_), multipleStyles(multipleStyles_), style(style_), styles(styles_) { - } - // Return number of bytes from start to before '\n' or end of text. - // Return 1 when start is outside text - size_t LineLength(size_t start) const { - size_t cur = start; - while ((cur < length) && (text[cur] != '\n')) - cur++; - return cur-start; - } - size_t StyleAt(size_t i) const { - return multipleStyles ? styles[i] : style; - } -}; - -class HighlightDelimiter { -public: - HighlightDelimiter() : isEnabled(false) { - Clear(); - } - - void Clear() { - beginFoldBlock = -1; - endFoldBlock = -1; - firstChangeableLineBefore = -1; - firstChangeableLineAfter = -1; - } - - bool NeedsDrawing(int line) const { - return isEnabled && (line <= firstChangeableLineBefore || line >= firstChangeableLineAfter); - } - - bool IsFoldBlockHighlighted(int line) const { - return isEnabled && beginFoldBlock != -1 && beginFoldBlock <= line && line <= endFoldBlock; - } - - bool IsHeadOfFoldBlock(int line) const { - return beginFoldBlock == line && line < endFoldBlock; - } - - bool IsBodyOfFoldBlock(int line) const { - return beginFoldBlock != -1 && beginFoldBlock < line && line < endFoldBlock; - } - - bool IsTailOfFoldBlock(int line) const { - return beginFoldBlock != -1 && beginFoldBlock < line && line == endFoldBlock; - } - - int beginFoldBlock; // Begin of current fold block - int endFoldBlock; // End of current fold block - int firstChangeableLineBefore; // First line that triggers repaint before starting line that determined current fold block - int firstChangeableLineAfter; // First line that triggers repaint after starting line that determined current fold block - bool isEnabled; -}; - -class Document; - -class LexInterface { -protected: - Document *pdoc; - ILexer *instance; - bool performingStyle; ///< Prevent reentrance -public: - explicit LexInterface(Document *pdoc_) : pdoc(pdoc_), instance(0), performingStyle(false) { - } - virtual ~LexInterface() { - } - void Colourise(int start, int end); - int LineEndTypesSupported(); - bool UseContainerLexing() const { - return instance == 0; - } -}; - -struct RegexError : public std::runtime_error { - RegexError() : std::runtime_error("regex failure") {} -}; - -/** - */ -class Document : PerLine, public IDocumentWithLineEnd, public ILoader { - -public: - /** Used to pair watcher pointer with user data. */ - struct WatcherWithUserData { - DocWatcher *watcher; - void *userData; - WatcherWithUserData(DocWatcher *watcher_=0, void *userData_=0) : - watcher(watcher_), userData(userData_) { - } - bool operator==(const WatcherWithUserData &other) const { - return (watcher == other.watcher) && (userData == other.userData); - } - }; - -private: - int refCount; - CellBuffer cb; - CharClassify charClass; - CaseFolder *pcf; - int endStyled; - int styleClock; - int enteredModification; - int enteredStyling; - int enteredReadOnlyCount; - - bool insertionSet; - std::string insertion; - - std::vector watchers; - - // ldSize is not real data - it is for dimensions and loops - enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize }; - PerLine *perLineData[ldSize]; - - bool matchesValid; - RegexSearchBase *regex; - -public: - - LexInterface *pli; - - int eolMode; - /// Can also be SC_CP_UTF8 to enable UTF-8 mode - int dbcsCodePage; - int lineEndBitSet; - int tabInChars; - int indentInChars; - int actualIndentInChars; - bool useTabs; - bool tabIndents; - bool backspaceUnindents; - - DecorationList decorations; - - Document(); - virtual ~Document(); - - int AddRef(); - int SCI_METHOD Release(); - - virtual void Init(); - int LineEndTypesSupported() const; - bool SetDBCSCodePage(int dbcsCodePage_); - int GetLineEndTypesAllowed() const { return cb.GetLineEndTypes(); } - bool SetLineEndTypesAllowed(int lineEndBitSet_); - int GetLineEndTypesActive() const { return cb.GetLineEndTypes(); } - virtual void InsertLine(int line); - virtual void RemoveLine(int line); - - int SCI_METHOD Version() const { - return dvLineEnd; - } - - void SCI_METHOD SetErrorStatus(int status); - - int SCI_METHOD LineFromPosition(int pos) const; - int ClampPositionIntoDocument(int pos) const; - bool IsCrLf(int pos) const; - int LenChar(int pos); - bool InGoodUTF8(int pos, int &start, int &end) const; - int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true) const; - int NextPosition(int pos, int moveDir) const; - bool NextCharacter(int &pos, int moveDir) const; // Returns true if pos changed - int SCI_METHOD GetRelativePosition(int positionStart, int characterOffset) const; - int GetRelativePositionUTF16(int positionStart, int characterOffset) const; - int SCI_METHOD GetCharacterAndWidth(int position, int *pWidth) const; - int SCI_METHOD CodePage() const; - bool SCI_METHOD IsDBCSLeadByte(char ch) const; - int SafeSegment(const char *text, int length, int lengthSegment) const; - EncodingFamily CodePageFamily() const; - - // Gateways to modifying document - void ModifiedAt(int pos); - void CheckReadOnly(); - bool DeleteChars(int pos, int len); - int InsertString(int position, const char *s, int insertLength); - void ChangeInsertion(const char *s, int length); - int SCI_METHOD AddData(char *data, int length); - void * SCI_METHOD ConvertToDocument(); - int Undo(); - int Redo(); - bool CanUndo() const { return cb.CanUndo(); } - bool CanRedo() const { return cb.CanRedo(); } - void DeleteUndoHistory() { cb.DeleteUndoHistory(); } - bool SetUndoCollection(bool collectUndo) { - return cb.SetUndoCollection(collectUndo); - } - bool IsCollectingUndo() const { return cb.IsCollectingUndo(); } - void BeginUndoAction() { cb.BeginUndoAction(); } - void EndUndoAction() { cb.EndUndoAction(); } - void AddUndoAction(int token, bool mayCoalesce) { cb.AddUndoAction(token, mayCoalesce); } - void SetSavePoint(); - bool IsSavePoint() const { return cb.IsSavePoint(); } - - void TentativeStart() { cb.TentativeStart(); } - void TentativeCommit() { cb.TentativeCommit(); } - void TentativeUndo(); - bool TentativeActive() const { return cb.TentativeActive(); } - - const char * SCI_METHOD BufferPointer() { return cb.BufferPointer(); } - const char *RangePointer(int position, int rangeLength) { return cb.RangePointer(position, rangeLength); } - int GapPosition() const { return cb.GapPosition(); } - - int SCI_METHOD GetLineIndentation(int line); - int SetLineIndentation(int line, int indent); - int GetLineIndentPosition(int line) const; - int GetColumn(int position); - int CountCharacters(int startPos, int endPos) const; - int CountUTF16(int startPos, int endPos) const; - int FindColumn(int line, int column); - void Indent(bool forwards, int lineBottom, int lineTop); - static std::string TransformLineEnds(const char *s, size_t len, int eolModeWanted); - void ConvertLineEnds(int eolModeSet); - void SetReadOnly(bool set) { cb.SetReadOnly(set); } - bool IsReadOnly() const { return cb.IsReadOnly(); } - - void DelChar(int pos); - void DelCharBack(int pos); - - char CharAt(int position) const { return cb.CharAt(position); } - void SCI_METHOD GetCharRange(char *buffer, int position, int lengthRetrieve) const { - cb.GetCharRange(buffer, position, lengthRetrieve); - } - char SCI_METHOD StyleAt(int position) const { return cb.StyleAt(position); } - void GetStyleRange(unsigned char *buffer, int position, int lengthRetrieve) const { - cb.GetStyleRange(buffer, position, lengthRetrieve); - } - int GetMark(int line); - int MarkerNext(int lineStart, int mask) const; - int AddMark(int line, int markerNum); - void AddMarkSet(int line, int valueSet); - void DeleteMark(int line, int markerNum); - void DeleteMarkFromHandle(int markerHandle); - void DeleteAllMarks(int markerNum); - int LineFromHandle(int markerHandle); - int SCI_METHOD LineStart(int line) const; - bool IsLineStartPosition(int position) const; - int SCI_METHOD LineEnd(int line) const; - int LineEndPosition(int position) const; - bool IsLineEndPosition(int position) const; - bool IsPositionInLineEnd(int position) const; - int VCHomePosition(int position) const; - - int SCI_METHOD SetLevel(int line, int level); - int SCI_METHOD GetLevel(int line) const; - void ClearLevels(); - int GetLastChild(int lineParent, int level=-1, int lastLine=-1); - int GetFoldParent(int line) const; - void GetHighlightDelimiters(HighlightDelimiter &hDelimiter, int line, int lastLine); - - void Indent(bool forwards); - int ExtendWordSelect(int pos, int delta, bool onlyWordCharacters=false); - int NextWordStart(int pos, int delta); - int NextWordEnd(int pos, int delta); - int SCI_METHOD Length() const { return cb.Length(); } - void Allocate(int newSize) { cb.Allocate(newSize); } - - struct CharacterExtracted { - unsigned int character; - unsigned int widthBytes; - CharacterExtracted(unsigned int character_, unsigned int widthBytes_) : - character(character_), widthBytes(widthBytes_) { - } - }; - CharacterExtracted ExtractCharacter(int position) const; - - bool MatchesWordOptions(bool word, bool wordStart, int pos, int length) const; - bool HasCaseFolder(void) const; - void SetCaseFolder(CaseFolder *pcf_); - long FindText(int minPos, int maxPos, const char *search, bool caseSensitive, bool word, - bool wordStart, bool regExp, int flags, int *length); - const char *SubstituteByPosition(const char *text, int *length); - int LinesTotal() const; - - void SetDefaultCharClasses(bool includeWordClass); - void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass); - int GetCharsOfClass(CharClassify::cc characterClass, unsigned char *buffer); - void SCI_METHOD StartStyling(int position, char mask); - bool SCI_METHOD SetStyleFor(int length, char style); - bool SCI_METHOD SetStyles(int length, const char *styles); - int GetEndStyled() const { return endStyled; } - void EnsureStyledTo(int pos); - void LexerChanged(); - int GetStyleClock() const { return styleClock; } - void IncrementStyleClock(); - void SCI_METHOD DecorationSetCurrentIndicator(int indicator) { - decorations.SetCurrentIndicator(indicator); - } - void SCI_METHOD DecorationFillRange(int position, int value, int fillLength); - - int SCI_METHOD SetLineState(int line, int state); - int SCI_METHOD GetLineState(int line) const; - int GetMaxLineState(); - void SCI_METHOD ChangeLexerState(int start, int end); - - StyledText MarginStyledText(int line) const; - void MarginSetStyle(int line, int style); - void MarginSetStyles(int line, const unsigned char *styles); - void MarginSetText(int line, const char *text); - void MarginClearAll(); - - StyledText AnnotationStyledText(int line) const; - void AnnotationSetText(int line, const char *text); - void AnnotationSetStyle(int line, int style); - void AnnotationSetStyles(int line, const unsigned char *styles); - int AnnotationLines(int line) const; - void AnnotationClearAll(); - - bool AddWatcher(DocWatcher *watcher, void *userData); - bool RemoveWatcher(DocWatcher *watcher, void *userData); - - CharClassify::cc WordCharClass(unsigned char ch) const; - bool IsWordPartSeparator(char ch) const; - int WordPartLeft(int pos); - int WordPartRight(int pos); - int ExtendStyleRange(int pos, int delta, bool singleLine = false); - bool IsWhiteLine(int line) const; - int ParaUp(int pos) const; - int ParaDown(int pos) const; - int IndentSize() const { return actualIndentInChars; } - int BraceMatch(int position, int maxReStyle); - -private: - bool IsWordStartAt(int pos) const; - bool IsWordEndAt(int pos) const; - bool IsWordAt(int start, int end) const; - - void NotifyModifyAttempt(); - void NotifySavePoint(bool atSavePoint); - void NotifyModified(DocModification mh); -}; - -class UndoGroup { - Document *pdoc; - bool groupNeeded; -public: - UndoGroup(Document *pdoc_, bool groupNeeded_=true) : - pdoc(pdoc_), groupNeeded(groupNeeded_) { - if (groupNeeded) { - pdoc->BeginUndoAction(); - } - } - ~UndoGroup() { - if (groupNeeded) { - pdoc->EndUndoAction(); - } - } - bool Needed() const { - return groupNeeded; - } -}; - - -/** - * To optimise processing of document modifications by DocWatchers, a hint is passed indicating the - * scope of the change. - * If the DocWatcher is a document view then this can be used to optimise screen updating. - */ -class DocModification { -public: - int modificationType; - int position; - int length; - int linesAdded; /**< Negative if lines deleted. */ - const char *text; /**< Only valid for changes to text, not for changes to style. */ - int line; - int foldLevelNow; - int foldLevelPrev; - int annotationLinesAdded; - int token; - - DocModification(int modificationType_, int position_=0, int length_=0, - int linesAdded_=0, const char *text_=0, int line_=0) : - modificationType(modificationType_), - position(position_), - length(length_), - linesAdded(linesAdded_), - text(text_), - line(line_), - foldLevelNow(0), - foldLevelPrev(0), - annotationLinesAdded(0), - token(0) {} - - DocModification(int modificationType_, const Action &act, int linesAdded_=0) : - modificationType(modificationType_), - position(act.position), - length(act.lenData), - linesAdded(linesAdded_), - text(act.data), - line(0), - foldLevelNow(0), - foldLevelPrev(0), - annotationLinesAdded(0), - token(0) {} -}; - -/** - * A class that wants to receive notifications from a Document must be derived from DocWatcher - * and implement the notification methods. It can then be added to the watcher list with AddWatcher. - */ -class DocWatcher { -public: - virtual ~DocWatcher() {} - - virtual void NotifyModifyAttempt(Document *doc, void *userData) = 0; - virtual void NotifySavePoint(Document *doc, void *userData, bool atSavePoint) = 0; - virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0; - virtual void NotifyDeleted(Document *doc, void *userData) = 0; - virtual void NotifyStyleNeeded(Document *doc, void *userData, int endPos) = 0; - virtual void NotifyLexerChanged(Document *doc, void *userData) = 0; - virtual void NotifyErrorOccurred(Document *doc, void *userData, int status) = 0; -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/EditModel.cpp b/libs/qscintilla/src/EditModel.cpp deleted file mode 100644 index b50ade258..000000000 --- a/libs/qscintilla/src/EditModel.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Scintilla source code edit control -/** @file EditModel.cxx - ** Defines the editor state that must be visible to EditorView. - **/ -// Copyright 1998-2014 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "ILexer.h" -#include "Scintilla.h" - -#include "StringCopy.h" -#include "SplitVector.h" -#include "Partitioning.h" -#include "RunStyles.h" -#include "ContractionState.h" -#include "CellBuffer.h" -#include "KeyMap.h" -#include "Indicator.h" -#include "XPM.h" -#include "LineMarker.h" -#include "Style.h" -#include "ViewStyle.h" -#include "CharClassify.h" -#include "Decoration.h" -#include "CaseFolder.h" -#include "Document.h" -#include "UniConversion.h" -#include "Selection.h" -#include "PositionCache.h" -#include "EditModel.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -Caret::Caret() : - active(false), on(false), period(500) {} - -EditModel::EditModel() { - inOverstrike = false; - xOffset = 0; - trackLineWidth = false; - posDrag = SelectionPosition(invalidPosition); - braces[0] = invalidPosition; - braces[1] = invalidPosition; - bracesMatchStyle = STYLE_BRACEBAD; - highlightGuideColumn = 0; - primarySelection = true; - imeInteraction = imeWindowed; - foldFlags = 0; - hotspot = Range(invalidPosition); - hoverIndicatorPos = invalidPosition; - wrapWidth = LineLayout::wrapWidthInfinite; - pdoc = new Document(); - pdoc->AddRef(); -} - -EditModel::~EditModel() { - pdoc->Release(); - pdoc = 0; -} diff --git a/libs/qscintilla/src/EditModel.h b/libs/qscintilla/src/EditModel.h deleted file mode 100644 index fce26bd22..000000000 --- a/libs/qscintilla/src/EditModel.h +++ /dev/null @@ -1,70 +0,0 @@ -// Scintilla source code edit control -/** @file EditModel.h - ** Defines the editor state that must be visible to EditorView. - **/ -// Copyright 1998-2014 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef EDITMODEL_H -#define EDITMODEL_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -/** -*/ -class Caret { -public: - bool active; - bool on; - int period; - - Caret(); -}; - -class EditModel { - // Private so EditModel objects can not be copied - EditModel(const EditModel &); - EditModel &operator=(const EditModel &); - -public: - bool inOverstrike; - int xOffset; ///< Horizontal scrolled amount in pixels - bool trackLineWidth; - - SpecialRepresentations reprs; - Caret caret; - SelectionPosition posDrag; - Position braces[2]; - int bracesMatchStyle; - int highlightGuideColumn; - Selection sel; - bool primarySelection; - - enum IMEInteraction { imeWindowed, imeInline } imeInteraction; - - int foldFlags; - ContractionState cs; - // Hotspot support - Range hotspot; - int hoverIndicatorPos; - - // Wrapping support - int wrapWidth; - - Document *pdoc; - - EditModel(); - virtual ~EditModel(); - virtual int TopLineOfMain() const = 0; - virtual Point GetVisibleOriginInMain() const = 0; - virtual int LinesOnScreen() const = 0; - virtual Range GetHotSpotRange() const = 0; -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/EditView.cpp b/libs/qscintilla/src/EditView.cpp deleted file mode 100644 index 3893c4053..000000000 --- a/libs/qscintilla/src/EditView.cpp +++ /dev/null @@ -1,2116 +0,0 @@ -// Scintilla source code edit control -/** @file Editor.cxx - ** Defines the appearance of the main text area of the editor window. - **/ -// Copyright 1998-2014 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "ILexer.h" -#include "Scintilla.h" - -#include "StringCopy.h" -#include "SplitVector.h" -#include "Partitioning.h" -#include "RunStyles.h" -#include "ContractionState.h" -#include "CellBuffer.h" -#include "PerLine.h" -#include "KeyMap.h" -#include "Indicator.h" -#include "XPM.h" -#include "LineMarker.h" -#include "Style.h" -#include "ViewStyle.h" -#include "CharClassify.h" -#include "Decoration.h" -#include "CaseFolder.h" -#include "Document.h" -#include "UniConversion.h" -#include "Selection.h" -#include "PositionCache.h" -#include "EditModel.h" -#include "MarginView.h" -#include "EditView.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsControlCharacter(int ch) { - // iscntrl returns true for lots of chars > 127 which are displayable - return ch >= 0 && ch < ' '; -} - -PrintParameters::PrintParameters() { - magnification = 0; - colourMode = SC_PRINT_NORMAL; - wrapState = eWrapWord; -} - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st) { - if (st.multipleStyles) { - for (size_t iStyle = 0; iStyle(styles[endSegment + 1]) == style)) - endSegment++; - FontAlias fontText = vs.styles[style + styleOffset].font; - width += static_cast(surface->WidthText(fontText, text + start, - static_cast(endSegment - start + 1))); - start = endSegment + 1; - } - return width; -} - -int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st) { - int widthMax = 0; - size_t start = 0; - while (start < st.length) { - size_t lenLine = st.LineLength(start); - int widthSubLine; - if (st.multipleStyles) { - widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine); - } else { - FontAlias fontText = vs.styles[styleOffset + st.style].font; - widthSubLine = static_cast(surface->WidthText(fontText, - st.text + start, static_cast(lenLine))); - } - if (widthSubLine > widthMax) - widthMax = widthSubLine; - start += lenLine + 1; - } - return widthMax; -} - -void DrawTextNoClipPhase(Surface *surface, PRectangle rc, const Style &style, XYPOSITION ybase, - const char *s, int len, DrawPhase phase) { - FontAlias fontText = style.font; - if (phase & drawBack) { - if (phase & drawText) { - // Drawing both - surface->DrawTextNoClip(rc, fontText, ybase, s, len, - style.fore, style.back); - } else { - surface->FillRectangle(rc, style.back); - } - } else if (phase & drawText) { - surface->DrawTextTransparent(rc, fontText, ybase, s, len, style.fore); - } -} - -void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText, - const StyledText &st, size_t start, size_t length, DrawPhase phase) { - - if (st.multipleStyles) { - int x = static_cast(rcText.left); - size_t i = 0; - while (i < length) { - size_t end = i; - size_t style = st.styles[i + start]; - while (end < length - 1 && st.styles[start + end + 1] == style) - end++; - style += styleOffset; - FontAlias fontText = vs.styles[style].font; - const int width = static_cast(surface->WidthText(fontText, - st.text + start + i, static_cast(end - i + 1))); - PRectangle rcSegment = rcText; - rcSegment.left = static_cast(x); - rcSegment.right = static_cast(x + width + 1); - DrawTextNoClipPhase(surface, rcSegment, vs.styles[style], - rcText.top + vs.maxAscent, st.text + start + i, - static_cast(end - i + 1), phase); - x += width; - i = end + 1; - } - } else { - const size_t style = st.style + styleOffset; - DrawTextNoClipPhase(surface, rcText, vs.styles[style], - rcText.top + vs.maxAscent, st.text + start, - static_cast(length), phase); - } -} - -#ifdef SCI_NAMESPACE -} -#endif - -const XYPOSITION epsilon = 0.0001f; // A small nudge to avoid floating point precision issues - -EditView::EditView() { - ldTabstops = NULL; - hideSelection = false; - drawOverstrikeCaret = true; - bufferedDraw = false; - phasesDraw = phasesTwo; - lineWidthMaxSeen = 0; - additionalCaretsBlink = true; - additionalCaretsVisible = true; - imeCaretBlockOverride = false; - pixmapLine = 0; - pixmapIndentGuide = 0; - pixmapIndentGuideHighlight = 0; - llc.SetLevel(LineLayoutCache::llcCaret); - posCache.SetSize(0x400); - tabArrowHeight = 4; - customDrawTabArrow = NULL; - customDrawWrapMarker = NULL; -} - -EditView::~EditView() { - delete ldTabstops; - ldTabstops = NULL; -} - -bool EditView::SetTwoPhaseDraw(bool twoPhaseDraw) { - const PhasesDraw phasesDrawNew = twoPhaseDraw ? phasesTwo : phasesOne; - const bool redraw = phasesDraw != phasesDrawNew; - phasesDraw = phasesDrawNew; - return redraw; -} - -bool EditView::SetPhasesDraw(int phases) { - const PhasesDraw phasesDrawNew = static_cast(phases); - const bool redraw = phasesDraw != phasesDrawNew; - phasesDraw = phasesDrawNew; - return redraw; -} - -bool EditView::LinesOverlap() const { - return phasesDraw == phasesMultiple; -} - -void EditView::ClearAllTabstops() { - delete ldTabstops; - ldTabstops = 0; -} - -XYPOSITION EditView::NextTabstopPos(int line, XYPOSITION x, XYPOSITION tabWidth) const { - int next = GetNextTabstop(line, static_cast(x + 2)); - if (next > 0) - return static_cast(next); - return (static_cast((x + 2) / tabWidth) + 1) * tabWidth; -} - -bool EditView::ClearTabstops(int line) { - LineTabstops *lt = static_cast(ldTabstops); - return lt && lt->ClearTabstops(line); -} - -bool EditView::AddTabstop(int line, int x) { - if (!ldTabstops) { - ldTabstops = new LineTabstops(); - } - LineTabstops *lt = static_cast(ldTabstops); - return lt && lt->AddTabstop(line, x); -} - -int EditView::GetNextTabstop(int line, int x) const { - LineTabstops *lt = static_cast(ldTabstops); - if (lt) { - return lt->GetNextTabstop(line, x); - } else { - return 0; - } -} - -void EditView::LinesAddedOrRemoved(int lineOfPos, int linesAdded) { - if (ldTabstops) { - if (linesAdded > 0) { - for (int line = lineOfPos; line < lineOfPos + linesAdded; line++) { - ldTabstops->InsertLine(line); - } - } else { - for (int line = (lineOfPos + -linesAdded) - 1; line >= lineOfPos; line--) { - ldTabstops->RemoveLine(line); - } - } - } -} - -void EditView::DropGraphics(bool freeObjects) { - if (freeObjects) { - delete pixmapLine; - pixmapLine = 0; - delete pixmapIndentGuide; - pixmapIndentGuide = 0; - delete pixmapIndentGuideHighlight; - pixmapIndentGuideHighlight = 0; - } else { - if (pixmapLine) - pixmapLine->Release(); - if (pixmapIndentGuide) - pixmapIndentGuide->Release(); - if (pixmapIndentGuideHighlight) - pixmapIndentGuideHighlight->Release(); - } -} - -void EditView::AllocateGraphics(const ViewStyle &vsDraw) { - if (!pixmapLine) - pixmapLine = Surface::Allocate(vsDraw.technology); - if (!pixmapIndentGuide) - pixmapIndentGuide = Surface::Allocate(vsDraw.technology); - if (!pixmapIndentGuideHighlight) - pixmapIndentGuideHighlight = Surface::Allocate(vsDraw.technology); -} - -const char *ControlCharacterString(unsigned char ch) { - const char *reps[] = { - "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", - "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", - "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", - "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US" - }; - if (ch < ELEMENTS(reps)) { - return reps[ch]; - } else { - return "BAD"; - } -} - -void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) { - int ydiff = static_cast(rcTab.bottom - rcTab.top) / 2; - int xhead = static_cast(rcTab.right) - 1 - ydiff; - if (xhead <= rcTab.left) { - ydiff -= static_cast(rcTab.left) - xhead - 1; - xhead = static_cast(rcTab.left) - 1; - } - if ((rcTab.left + 2) < (rcTab.right - 1)) - surface->MoveTo(static_cast(rcTab.left) + 2, ymid); - else - surface->MoveTo(static_cast(rcTab.right) - 1, ymid); - surface->LineTo(static_cast(rcTab.right) - 1, ymid); - surface->LineTo(xhead, ymid - ydiff); - surface->MoveTo(static_cast(rcTab.right) - 1, ymid); - surface->LineTo(xhead, ymid + ydiff); -} - -void EditView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) { - if (!pixmapIndentGuide->Initialised()) { - // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line - pixmapIndentGuide->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid); - pixmapIndentGuideHighlight->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid); - PRectangle rcIG = PRectangle::FromInts(0, 0, 1, vsDraw.lineHeight); - pixmapIndentGuide->FillRectangle(rcIG, vsDraw.styles[STYLE_INDENTGUIDE].back); - pixmapIndentGuide->PenColour(vsDraw.styles[STYLE_INDENTGUIDE].fore); - pixmapIndentGuideHighlight->FillRectangle(rcIG, vsDraw.styles[STYLE_BRACELIGHT].back); - pixmapIndentGuideHighlight->PenColour(vsDraw.styles[STYLE_BRACELIGHT].fore); - for (int stripe = 1; stripe < vsDraw.lineHeight + 1; stripe += 2) { - PRectangle rcPixel = PRectangle::FromInts(0, stripe, 1, stripe + 1); - pixmapIndentGuide->FillRectangle(rcPixel, vsDraw.styles[STYLE_INDENTGUIDE].fore); - pixmapIndentGuideHighlight->FillRectangle(rcPixel, vsDraw.styles[STYLE_BRACELIGHT].fore); - } - } -} - -LineLayout *EditView::RetrieveLineLayout(int lineNumber, const EditModel &model) { - int posLineStart = model.pdoc->LineStart(lineNumber); - int posLineEnd = model.pdoc->LineStart(lineNumber + 1); - PLATFORM_ASSERT(posLineEnd >= posLineStart); - int lineCaret = model.pdoc->LineFromPosition(model.sel.MainCaret()); - return llc.Retrieve(lineNumber, lineCaret, - posLineEnd - posLineStart, model.pdoc->GetStyleClock(), - model.LinesOnScreen() + 1, model.pdoc->LinesTotal()); -} - -/** -* Fill in the LineLayout data for the given line. -* Copy the given @a line and its styles from the document into local arrays. -* Also determine the x position at which each character starts. -*/ -void EditView::LayoutLine(const EditModel &model, int line, Surface *surface, const ViewStyle &vstyle, LineLayout *ll, int width) { - if (!ll) - return; - - PLATFORM_ASSERT(line < model.pdoc->LinesTotal()); - PLATFORM_ASSERT(ll->chars != NULL); - int posLineStart = model.pdoc->LineStart(line); - int posLineEnd = model.pdoc->LineStart(line + 1); - // If the line is very long, limit the treatment to a length that should fit in the viewport - if (posLineEnd >(posLineStart + ll->maxLineLength)) { - posLineEnd = posLineStart + ll->maxLineLength; - } - if (ll->validity == LineLayout::llCheckTextAndStyle) { - int lineLength = posLineEnd - posLineStart; - if (!vstyle.viewEOL) { - lineLength = model.pdoc->LineEnd(line) - posLineStart; - } - if (lineLength == ll->numCharsInLine) { - // See if chars, styles, indicators, are all the same - bool allSame = true; - // Check base line layout - char styleByte = 0; - int numCharsInLine = 0; - while (numCharsInLine < lineLength) { - int charInDoc = numCharsInLine + posLineStart; - char chDoc = model.pdoc->CharAt(charInDoc); - styleByte = model.pdoc->StyleAt(charInDoc); - allSame = allSame && - (ll->styles[numCharsInLine] == static_cast(styleByte)); - if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed) - allSame = allSame && - (ll->chars[numCharsInLine] == chDoc); - else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower) - allSame = allSame && - (ll->chars[numCharsInLine] == static_cast(tolower(chDoc))); - else // Style::caseUpper - allSame = allSame && - (ll->chars[numCharsInLine] == static_cast(toupper(chDoc))); - numCharsInLine++; - } - allSame = allSame && (ll->styles[numCharsInLine] == styleByte); // For eolFilled - if (allSame) { - ll->validity = LineLayout::llPositions; - } else { - ll->validity = LineLayout::llInvalid; - } - } else { - ll->validity = LineLayout::llInvalid; - } - } - if (ll->validity == LineLayout::llInvalid) { - ll->widthLine = LineLayout::wrapWidthInfinite; - ll->lines = 1; - if (vstyle.edgeState == EDGE_BACKGROUND) { - ll->edgeColumn = model.pdoc->FindColumn(line, vstyle.theEdge); - if (ll->edgeColumn >= posLineStart) { - ll->edgeColumn -= posLineStart; - } - } else { - ll->edgeColumn = -1; - } - - // Fill base line layout - const int lineLength = posLineEnd - posLineStart; - model.pdoc->GetCharRange(ll->chars, posLineStart, lineLength); - model.pdoc->GetStyleRange(ll->styles, posLineStart, lineLength); - int numCharsBeforeEOL = model.pdoc->LineEnd(line) - posLineStart; - const int numCharsInLine = (vstyle.viewEOL) ? lineLength : numCharsBeforeEOL; - for (int styleInLine = 0; styleInLine < numCharsInLine; styleInLine++) { - const unsigned char styleByte = ll->styles[styleInLine]; - ll->styles[styleInLine] = styleByte; - } - const unsigned char styleByteLast = (lineLength > 0) ? ll->styles[lineLength - 1] : 0; - if (vstyle.someStylesForceCase) { - for (int charInLine = 0; charInLinechars[charInLine]; - if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseUpper) - ll->chars[charInLine] = static_cast(toupper(chDoc)); - else if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseLower) - ll->chars[charInLine] = static_cast(tolower(chDoc)); - } - } - ll->xHighlightGuide = 0; - // Extra element at the end of the line to hold end x position and act as - ll->chars[numCharsInLine] = 0; // Also triggers processing in the loops as this is a control character - ll->styles[numCharsInLine] = styleByteLast; // For eolFilled - - // Layout the line, determining the position of each character, - // with an extra element at the end for the end of the line. - ll->positions[0] = 0; - bool lastSegItalics = false; - - BreakFinder bfLayout(ll, NULL, Range(0, numCharsInLine), posLineStart, 0, false, model.pdoc, &model.reprs, NULL); - while (bfLayout.More()) { - - const TextSegment ts = bfLayout.Next(); - - std::fill(&ll->positions[ts.start + 1], &ll->positions[ts.end() + 1], 0.0f); - if (vstyle.styles[ll->styles[ts.start]].visible) { - if (ts.representation) { - XYPOSITION representationWidth = vstyle.controlCharWidth; - if (ll->chars[ts.start] == '\t') { - // Tab is a special case of representation, taking a variable amount of space - const XYPOSITION x = ll->positions[ts.start]; - representationWidth = NextTabstopPos(line, x, vstyle.tabWidth) - ll->positions[ts.start]; - } else { - if (representationWidth <= 0.0) { - XYPOSITION positionsRepr[256]; // Should expand when needed - posCache.MeasureWidths(surface, vstyle, STYLE_CONTROLCHAR, ts.representation->stringRep.c_str(), - static_cast(ts.representation->stringRep.length()), positionsRepr, model.pdoc); - representationWidth = positionsRepr[ts.representation->stringRep.length() - 1] + vstyle.ctrlCharPadding; - } - } - for (int ii = 0; ii < ts.length; ii++) - ll->positions[ts.start + 1 + ii] = representationWidth; - } else { - if ((ts.length == 1) && (' ' == ll->chars[ts.start])) { - // Over half the segments are single characters and of these about half are space characters. - ll->positions[ts.start + 1] = vstyle.styles[ll->styles[ts.start]].spaceWidth; - } else { - posCache.MeasureWidths(surface, vstyle, ll->styles[ts.start], ll->chars + ts.start, - ts.length, ll->positions + ts.start + 1, model.pdoc); - } - } - lastSegItalics = (!ts.representation) && ((ll->chars[ts.end() - 1] != ' ') && vstyle.styles[ll->styles[ts.start]].italic); - } - - for (int posToIncrease = ts.start + 1; posToIncrease <= ts.end(); posToIncrease++) { - ll->positions[posToIncrease] += ll->positions[ts.start]; - } - } - - // Small hack to make lines that end with italics not cut off the edge of the last character - if (lastSegItalics) { - ll->positions[numCharsInLine] += vstyle.lastSegItalicsOffset; - } - ll->numCharsInLine = numCharsInLine; - ll->numCharsBeforeEOL = numCharsBeforeEOL; - ll->validity = LineLayout::llPositions; - } - // Hard to cope when too narrow, so just assume there is space - if (width < 20) { - width = 20; - } - if ((ll->validity == LineLayout::llPositions) || (ll->widthLine != width)) { - ll->widthLine = width; - if (width == LineLayout::wrapWidthInfinite) { - ll->lines = 1; - } else if (width > ll->positions[ll->numCharsInLine]) { - // Simple common case where line does not need wrapping. - ll->lines = 1; - } else { - if (vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_END) { - width -= static_cast(vstyle.aveCharWidth); // take into account the space for end wrap mark - } - XYPOSITION wrapAddIndent = 0; // This will be added to initial indent of line - if (vstyle.wrapIndentMode == SC_WRAPINDENT_INDENT) { - wrapAddIndent = model.pdoc->IndentSize() * vstyle.spaceWidth; - } else if (vstyle.wrapIndentMode == SC_WRAPINDENT_FIXED) { - wrapAddIndent = vstyle.wrapVisualStartIndent * vstyle.aveCharWidth; - } - ll->wrapIndent = wrapAddIndent; - if (vstyle.wrapIndentMode != SC_WRAPINDENT_FIXED) - for (int i = 0; i < ll->numCharsInLine; i++) { - if (!IsSpaceOrTab(ll->chars[i])) { - ll->wrapIndent += ll->positions[i]; // Add line indent - break; - } - } - // Check for text width minimum - if (ll->wrapIndent > width - static_cast(vstyle.aveCharWidth) * 15) - ll->wrapIndent = wrapAddIndent; - // Check for wrapIndent minimum - if ((vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (ll->wrapIndent < vstyle.aveCharWidth)) - ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual - ll->lines = 0; - // Calculate line start positions based upon width. - int lastGoodBreak = 0; - int lastLineStart = 0; - XYACCUMULATOR startOffset = 0; - int p = 0; - while (p < ll->numCharsInLine) { - if ((ll->positions[p + 1] - startOffset) >= width) { - if (lastGoodBreak == lastLineStart) { - // Try moving to start of last character - if (p > 0) { - lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1) - - posLineStart; - } - if (lastGoodBreak == lastLineStart) { - // Ensure at least one character on line. - lastGoodBreak = model.pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1) - - posLineStart; - } - } - lastLineStart = lastGoodBreak; - ll->lines++; - ll->SetLineStart(ll->lines, lastGoodBreak); - startOffset = ll->positions[lastGoodBreak]; - // take into account the space for start wrap mark and indent - startOffset -= ll->wrapIndent; - p = lastGoodBreak + 1; - continue; - } - if (p > 0) { - if (vstyle.wrapState == eWrapChar) { - lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1) - - posLineStart; - p = model.pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart; - continue; - } else if ((vstyle.wrapState == eWrapWord) && (ll->styles[p] != ll->styles[p - 1])) { - lastGoodBreak = p; - } else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) { - lastGoodBreak = p; - } - } - p++; - } - ll->lines++; - } - ll->validity = LineLayout::llLines; - } -} - -Point EditView::LocationFromPosition(Surface *surface, const EditModel &model, SelectionPosition pos, int topLine, const ViewStyle &vs) { - Point pt; - if (pos.Position() == INVALID_POSITION) - return pt; - const int line = model.pdoc->LineFromPosition(pos.Position()); - const int lineVisible = model.cs.DisplayFromDoc(line); - //Platform::DebugPrintf("line=%d\n", line); - AutoLineLayout ll(llc, RetrieveLineLayout(line, model)); - if (surface && ll) { - const int posLineStart = model.pdoc->LineStart(line); - LayoutLine(model, line, surface, vs, ll, model.wrapWidth); - const int posInLine = pos.Position() - posLineStart; - pt = ll->PointFromPosition(posInLine, vs.lineHeight); - pt.y += (lineVisible - topLine) * vs.lineHeight; - pt.x += vs.textStart - model.xOffset; - } - pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth; - return pt; -} - -SelectionPosition EditView::SPositionFromLocation(Surface *surface, const EditModel &model, Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace, const ViewStyle &vs) { - pt.x = pt.x - vs.textStart; - int visibleLine = static_cast(floor(pt.y / vs.lineHeight)); - if (!canReturnInvalid && (visibleLine < 0)) - visibleLine = 0; - const int lineDoc = model.cs.DocFromDisplay(visibleLine); - if (canReturnInvalid && (lineDoc < 0)) - return SelectionPosition(INVALID_POSITION); - if (lineDoc >= model.pdoc->LinesTotal()) - return SelectionPosition(canReturnInvalid ? INVALID_POSITION : model.pdoc->Length()); - const int posLineStart = model.pdoc->LineStart(lineDoc); - AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model)); - if (surface && ll) { - LayoutLine(model, lineDoc, surface, vs, ll, model.wrapWidth); - const int lineStartSet = model.cs.DisplayFromDoc(lineDoc); - const int subLine = visibleLine - lineStartSet; - if (subLine < ll->lines) { - const Range rangeSubLine = ll->SubLineRange(subLine); - const XYPOSITION subLineStart = ll->positions[rangeSubLine.start]; - if (subLine > 0) // Wrapped - pt.x -= ll->wrapIndent; - const int positionInLine = ll->FindPositionFromX(pt.x + subLineStart, rangeSubLine, charPosition); - if (positionInLine < rangeSubLine.end) { - return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1)); - } - if (virtualSpace) { - const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; - const int spaceOffset = static_cast( - (pt.x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth); - return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset); - } else if (canReturnInvalid) { - if (pt.x < (ll->positions[rangeSubLine.end] - subLineStart)) { - return SelectionPosition(model.pdoc->MovePositionOutsideChar(rangeSubLine.end + posLineStart, 1)); - } - } else { - return SelectionPosition(rangeSubLine.end + posLineStart); - } - } - if (!canReturnInvalid) - return SelectionPosition(ll->numCharsInLine + posLineStart); - } - return SelectionPosition(canReturnInvalid ? INVALID_POSITION : posLineStart); -} - -/** -* Find the document position corresponding to an x coordinate on a particular document line. -* Ensure is between whole characters when document is in multi-byte or UTF-8 mode. -* This method is used for rectangular selections and does not work on wrapped lines. -*/ -SelectionPosition EditView::SPositionFromLineX(Surface *surface, const EditModel &model, int lineDoc, int x, const ViewStyle &vs) { - AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model)); - if (surface && ll) { - const int posLineStart = model.pdoc->LineStart(lineDoc); - LayoutLine(model, lineDoc, surface, vs, ll, model.wrapWidth); - const Range rangeSubLine = ll->SubLineRange(0); - const XYPOSITION subLineStart = ll->positions[rangeSubLine.start]; - const int positionInLine = ll->FindPositionFromX(x + subLineStart, rangeSubLine, false); - if (positionInLine < rangeSubLine.end) { - return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1)); - } - const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; - const int spaceOffset = static_cast( - (x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth); - return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset); - } - return SelectionPosition(0); -} - -int EditView::DisplayFromPosition(Surface *surface, const EditModel &model, int pos, const ViewStyle &vs) { - int lineDoc = model.pdoc->LineFromPosition(pos); - int lineDisplay = model.cs.DisplayFromDoc(lineDoc); - AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model)); - if (surface && ll) { - LayoutLine(model, lineDoc, surface, vs, ll, model.wrapWidth); - unsigned int posLineStart = model.pdoc->LineStart(lineDoc); - int posInLine = pos - posLineStart; - lineDisplay--; // To make up for first increment ahead. - for (int subLine = 0; subLine < ll->lines; subLine++) { - if (posInLine >= ll->LineStart(subLine)) { - lineDisplay++; - } - } - } - return lineDisplay; -} - -int EditView::StartEndDisplayLine(Surface *surface, const EditModel &model, int pos, bool start, const ViewStyle &vs) { - int line = model.pdoc->LineFromPosition(pos); - AutoLineLayout ll(llc, RetrieveLineLayout(line, model)); - int posRet = INVALID_POSITION; - if (surface && ll) { - unsigned int posLineStart = model.pdoc->LineStart(line); - LayoutLine(model, line, surface, vs, ll, model.wrapWidth); - int posInLine = pos - posLineStart; - if (posInLine <= ll->maxLineLength) { - for (int subLine = 0; subLine < ll->lines; subLine++) { - if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) { - if (start) { - posRet = ll->LineStart(subLine) + posLineStart; - } else { - if (subLine == ll->lines - 1) - posRet = ll->LineStart(subLine + 1) + posLineStart; - else - posRet = ll->LineStart(subLine + 1) + posLineStart - 1; - } - } - } - } - } - return posRet; -} - -static ColourDesired SelectionBackground(const ViewStyle &vsDraw, bool main, bool primarySelection) { - return main ? - (primarySelection ? vsDraw.selColours.back : vsDraw.selBackground2) : - vsDraw.selAdditionalBackground; -} - -static ColourDesired TextBackground(const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - ColourOptional background, int inSelection, bool inHotspot, int styleMain, int i) { - if (inSelection == 1) { - if (vsDraw.selColours.back.isSet && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) { - return SelectionBackground(vsDraw, true, model.primarySelection); - } - } else if (inSelection == 2) { - if (vsDraw.selColours.back.isSet && (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)) { - return SelectionBackground(vsDraw, false, model.primarySelection); - } - } else { - if ((vsDraw.edgeState == EDGE_BACKGROUND) && - (i >= ll->edgeColumn) && - (i < ll->numCharsBeforeEOL)) - return vsDraw.edgecolour; - if (inHotspot && vsDraw.hotspotColours.back.isSet) - return vsDraw.hotspotColours.back; - } - if (background.isSet && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) { - return background; - } else { - return vsDraw.styles[styleMain].back; - } -} - -void EditView::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) { - Point from = Point::FromInts(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0); - PRectangle rcCopyArea = PRectangle::FromInts(start + 1, static_cast(rcSegment.top), start + 2, static_cast(rcSegment.bottom)); - surface->Copy(rcCopyArea, from, - highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide); -} - -static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourDesired fill, int alpha) { - if (alpha != SC_ALPHA_NOALPHA) { - surface->AlphaRectangle(rc, 0, fill, alpha, fill, alpha, 0); - } -} - -static void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle rcSegment, - const char *s, ColourDesired textBack, ColourDesired textFore, bool fillBackground) { - if (fillBackground) { - surface->FillRectangle(rcSegment, textBack); - } - FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font; - int normalCharHeight = static_cast(surface->Ascent(ctrlCharsFont) - - surface->InternalLeading(ctrlCharsFont)); - PRectangle rcCChar = rcSegment; - rcCChar.left = rcCChar.left + 1; - rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight; - rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1; - PRectangle rcCentral = rcCChar; - rcCentral.top++; - rcCentral.bottom--; - surface->FillRectangle(rcCentral, textFore); - PRectangle rcChar = rcCChar; - rcChar.left++; - rcChar.right--; - surface->DrawTextClipped(rcChar, ctrlCharsFont, - rcSegment.top + vsDraw.maxAscent, s, static_cast(s ? strlen(s) : 0), - textBack, textFore); -} - -void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - PRectangle rcLine, int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart, - ColourOptional background) { - - const int posLineStart = model.pdoc->LineStart(line); - PRectangle rcSegment = rcLine; - - const bool lastSubLine = subLine == (ll->lines - 1); - XYPOSITION virtualSpace = 0; - if (lastSubLine) { - const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; - virtualSpace = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)) * spaceWidth; - } - XYPOSITION xEol = static_cast(ll->positions[lineEnd] - subLineStart); - - // Fill the virtual space and show selections within it - if (virtualSpace > 0.0f) { - rcSegment.left = xEol + xStart; - rcSegment.right = xEol + xStart + virtualSpace; - surface->FillRectangle(rcSegment, background.isSet ? background : vsDraw.styles[ll->styles[ll->numCharsInLine]].back); - if (!hideSelection && ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA))) { - SelectionSegment virtualSpaceRange(SelectionPosition(model.pdoc->LineEnd(line)), SelectionPosition(model.pdoc->LineEnd(line), model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)))); - for (size_t r = 0; rEndLineStyle()].spaceWidth; - rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - - static_cast(subLineStart)+portion.start.VirtualSpace() * spaceWidth; - rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - - static_cast(subLineStart)+portion.end.VirtualSpace() * spaceWidth; - rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; - rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; - surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection)); - } - } - } - } - } - - int eolInSelection = 0; - int alpha = SC_ALPHA_NOALPHA; - if (!hideSelection) { - int posAfterLineEnd = model.pdoc->LineStart(line + 1); - eolInSelection = (subLine == (ll->lines - 1)) ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0; - alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha; - } - - // Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on - XYPOSITION blobsWidth = 0; - if (lastSubLine) { - for (int eolPos = ll->numCharsBeforeEOL; eolPosnumCharsInLine; eolPos++) { - rcSegment.left = xStart + ll->positions[eolPos] - static_cast(subLineStart)+virtualSpace; - rcSegment.right = xStart + ll->positions[eolPos + 1] - static_cast(subLineStart)+virtualSpace; - blobsWidth += rcSegment.Width(); - char hexits[4]; - const char *ctrlChar; - unsigned char chEOL = ll->chars[eolPos]; - int styleMain = ll->styles[eolPos]; - ColourDesired textBack = TextBackground(model, vsDraw, ll, background, eolInSelection, false, styleMain, eolPos); - if (UTF8IsAscii(chEOL)) { - ctrlChar = ControlCharacterString(chEOL); - } else { - const Representation *repr = model.reprs.RepresentationFromCharacter(ll->chars + eolPos, ll->numCharsInLine - eolPos); - if (repr) { - ctrlChar = repr->stringRep.c_str(); - eolPos = ll->numCharsInLine; - } else { - sprintf(hexits, "x%2X", chEOL); - ctrlChar = hexits; - } - } - ColourDesired textFore = vsDraw.styles[styleMain].fore; - if (eolInSelection && vsDraw.selColours.fore.isSet) { - textFore = (eolInSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground; - } - if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1)) { - if (alpha == SC_ALPHA_NOALPHA) { - surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection)); - } else { - surface->FillRectangle(rcSegment, textBack); - } - } else { - surface->FillRectangle(rcSegment, textBack); - } - DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, phasesDraw == phasesOne); - if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); - } - } - } - - // Draw the eol-is-selected rectangle - rcSegment.left = xEol + xStart + virtualSpace + blobsWidth; - rcSegment.right = rcSegment.left + vsDraw.aveCharWidth; - - if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { - surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection)); - } else { - if (background.isSet) { - surface->FillRectangle(rcSegment, background); - } else if (line < model.pdoc->LinesTotal() - 1) { - surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back); - } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) { - surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back); - } else { - surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back); - } - if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); - } - } - - // Fill the remainder of the line - rcSegment.left = rcSegment.right; - if (rcSegment.left < rcLine.left) - rcSegment.left = rcLine.left; - rcSegment.right = rcLine.right; - - if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { - surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection)); - } else { - if (background.isSet) { - surface->FillRectangle(rcSegment, background); - } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) { - surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back); - } else { - surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back); - } - if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha); - } - } - - bool drawWrapMarkEnd = false; - - if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_END) { - if (subLine + 1 < ll->lines) { - drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0; - } - } - - if (drawWrapMarkEnd) { - PRectangle rcPlace = rcSegment; - - if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_END_BY_TEXT) { - rcPlace.left = xEol + xStart + virtualSpace; - rcPlace.right = rcPlace.left + vsDraw.aveCharWidth; - } else { - // rcLine is clipped to text area - rcPlace.right = rcLine.right; - rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; - } - if (customDrawWrapMarker == NULL) { - DrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour()); - } else { - customDrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour()); - } - } -} - -static void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, const ViewStyle &vsDraw, - const LineLayout *ll, int xStart, PRectangle rcLine, int subLine, Indicator::DrawState drawState, int value) { - const XYPOSITION subLineStart = ll->positions[ll->LineStart(subLine)]; - PRectangle rcIndic( - ll->positions[startPos] + xStart - subLineStart, - rcLine.top + vsDraw.maxAscent, - ll->positions[endPos] + xStart - subLineStart, - rcLine.top + vsDraw.maxAscent + 3); - vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine, drawState, value); -} - -static void DrawIndicators(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - int line, int xStart, PRectangle rcLine, int subLine, int lineEnd, bool under, int hoverIndicatorPos) { - // Draw decorators - const int posLineStart = model.pdoc->LineStart(line); - const int lineStart = ll->LineStart(subLine); - const int posLineEnd = posLineStart + lineEnd; - - for (Decoration *deco = model.pdoc->decorations.root; deco; deco = deco->next) { - if (under == vsDraw.indicators[deco->indicator].under) { - int startPos = posLineStart + lineStart; - if (!deco->rs.ValueAt(startPos)) { - startPos = deco->rs.EndRun(startPos); - } - while ((startPos < posLineEnd) && (deco->rs.ValueAt(startPos))) { - int endPos = deco->rs.EndRun(startPos); - if (endPos > posLineEnd) - endPos = posLineEnd; - const bool hover = vsDraw.indicators[deco->indicator].IsDynamic() && - ((hoverIndicatorPos >= startPos) && (hoverIndicatorPos <= endPos)); - const int value = deco->rs.ValueAt(startPos); - Indicator::DrawState drawState = hover ? Indicator::drawHover : Indicator::drawNormal; - DrawIndicator(deco->indicator, startPos - posLineStart, endPos - posLineStart, - surface, vsDraw, ll, xStart, rcLine, subLine, drawState, value); - startPos = endPos; - if (!deco->rs.ValueAt(startPos)) { - startPos = deco->rs.EndRun(startPos); - } - } - } - } - - // Use indicators to highlight matching braces - if ((vsDraw.braceHighlightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACELIGHT)) || - (vsDraw.braceBadLightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACEBAD))) { - int braceIndicator = (model.bracesMatchStyle == STYLE_BRACELIGHT) ? vsDraw.braceHighlightIndicator : vsDraw.braceBadLightIndicator; - if (under == vsDraw.indicators[braceIndicator].under) { - Range rangeLine(posLineStart + lineStart, posLineEnd); - if (rangeLine.ContainsCharacter(model.braces[0])) { - int braceOffset = model.braces[0] - posLineStart; - if (braceOffset < ll->numCharsInLine) { - DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, subLine, Indicator::drawNormal, 1); - } - } - if (rangeLine.ContainsCharacter(model.braces[1])) { - int braceOffset = model.braces[1] - posLineStart; - if (braceOffset < ll->numCharsInLine) { - DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, subLine, Indicator::drawNormal, 1); - } - } - } - } -} - -static bool AnnotationBoxedOrIndented(int annotationVisible) { - return annotationVisible == ANNOTATION_BOXED || annotationVisible == ANNOTATION_INDENTED; -} - -void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - int line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase) { - int indent = static_cast(model.pdoc->GetLineIndentation(line) * vsDraw.spaceWidth); - PRectangle rcSegment = rcLine; - int annotationLine = subLine - ll->lines; - const StyledText stAnnotation = model.pdoc->AnnotationStyledText(line); - if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) { - if (phase & drawBack) { - surface->FillRectangle(rcSegment, vsDraw.styles[0].back); - } - rcSegment.left = static_cast(xStart); - if (model.trackLineWidth || AnnotationBoxedOrIndented(vsDraw.annotationVisible)) { - // Only care about calculating width if tracking or need to draw indented box - int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation); - if (AnnotationBoxedOrIndented(vsDraw.annotationVisible)) { - widthAnnotation += static_cast(vsDraw.spaceWidth * 2); // Margins - rcSegment.left = static_cast(xStart + indent); - rcSegment.right = rcSegment.left + widthAnnotation; - } - if (widthAnnotation > lineWidthMaxSeen) - lineWidthMaxSeen = widthAnnotation; - } - const int annotationLines = model.pdoc->AnnotationLines(line); - size_t start = 0; - size_t lengthAnnotation = stAnnotation.LineLength(start); - int lineInAnnotation = 0; - while ((lineInAnnotation < annotationLine) && (start < stAnnotation.length)) { - start += lengthAnnotation + 1; - lengthAnnotation = stAnnotation.LineLength(start); - lineInAnnotation++; - } - PRectangle rcText = rcSegment; - if ((phase & drawBack) && AnnotationBoxedOrIndented(vsDraw.annotationVisible)) { - surface->FillRectangle(rcText, - vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back); - rcText.left += vsDraw.spaceWidth; - } - DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, - stAnnotation, start, lengthAnnotation, phase); - if ((phase & drawBack) && (vsDraw.annotationVisible == ANNOTATION_BOXED)) { - surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore); - surface->MoveTo(static_cast(rcSegment.left), static_cast(rcSegment.top)); - surface->LineTo(static_cast(rcSegment.left), static_cast(rcSegment.bottom)); - surface->MoveTo(static_cast(rcSegment.right), static_cast(rcSegment.top)); - surface->LineTo(static_cast(rcSegment.right), static_cast(rcSegment.bottom)); - if (subLine == ll->lines) { - surface->MoveTo(static_cast(rcSegment.left), static_cast(rcSegment.top)); - surface->LineTo(static_cast(rcSegment.right), static_cast(rcSegment.top)); - } - if (subLine == ll->lines + annotationLines - 1) { - surface->MoveTo(static_cast(rcSegment.left), static_cast(rcSegment.bottom - 1)); - surface->LineTo(static_cast(rcSegment.right), static_cast(rcSegment.bottom - 1)); - } - } - } -} - -static void DrawBlockCaret(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - int subLine, int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour) { - - int lineStart = ll->LineStart(subLine); - int posBefore = posCaret; - int posAfter = model.pdoc->MovePositionOutsideChar(posCaret + 1, 1); - int numCharsToDraw = posAfter - posCaret; - - // Work out where the starting and ending offsets are. We need to - // see if the previous character shares horizontal space, such as a - // glyph / combining character. If so we'll need to draw that too. - int offsetFirstChar = offset; - int offsetLastChar = offset + (posAfter - posCaret); - while ((posBefore > 0) && ((offsetLastChar - numCharsToDraw) >= lineStart)) { - if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - numCharsToDraw]) > 0) { - // The char does not share horizontal space - break; - } - // Char shares horizontal space, update the numChars to draw - // Update posBefore to point to the prev char - posBefore = model.pdoc->MovePositionOutsideChar(posBefore - 1, -1); - numCharsToDraw = posAfter - posBefore; - offsetFirstChar = offset - (posCaret - posBefore); - } - - // See if the next character shares horizontal space, if so we'll - // need to draw that too. - if (offsetFirstChar < 0) - offsetFirstChar = 0; - numCharsToDraw = offsetLastChar - offsetFirstChar; - while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) { - // Update posAfter to point to the 2nd next char, this is where - // the next character ends, and 2nd next begins. We'll need - // to compare these two - posBefore = posAfter; - posAfter = model.pdoc->MovePositionOutsideChar(posAfter + 1, 1); - offsetLastChar = offset + (posAfter - posCaret); - if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - (posAfter - posBefore)]) > 0) { - // The char does not share horizontal space - break; - } - // Char shares horizontal space, update the numChars to draw - numCharsToDraw = offsetLastChar - offsetFirstChar; - } - - // We now know what to draw, update the caret drawing rectangle - rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart; - rcCaret.right = ll->positions[offsetFirstChar + numCharsToDraw] - ll->positions[lineStart] + xStart; - - // Adjust caret position to take into account any word wrapping symbols. - if ((ll->wrapIndent != 0) && (lineStart != 0)) { - XYPOSITION wordWrapCharWidth = ll->wrapIndent; - rcCaret.left += wordWrapCharWidth; - rcCaret.right += wordWrapCharWidth; - } - - // This character is where the caret block is, we override the colours - // (inversed) for drawing the caret here. - int styleMain = ll->styles[offsetFirstChar]; - FontAlias fontText = vsDraw.styles[styleMain].font; - surface->DrawTextClipped(rcCaret, fontText, - rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar, - numCharsToDraw, vsDraw.styles[styleMain].back, - caretColour); -} - -void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - int lineDoc, int xStart, PRectangle rcLine, int subLine) const { - // When drag is active it is the only caret drawn - bool drawDrag = model.posDrag.IsValid(); - if (hideSelection && !drawDrag) - return; - const int posLineStart = model.pdoc->LineStart(lineDoc); - // For each selection draw - for (size_t r = 0; (rEndLineStyle()].spaceWidth; - const XYPOSITION virtualOffset = posCaret.VirtualSpace() * spaceWidth; - if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) { - XYPOSITION xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)]; - if (ll->wrapIndent != 0) { - int lineStart = ll->LineStart(subLine); - if (lineStart != 0) // Wrapped - xposCaret += ll->wrapIndent; - } - bool caretBlinkState = (model.caret.active && model.caret.on) || (!additionalCaretsBlink && !mainCaret); - bool caretVisibleState = additionalCaretsVisible || mainCaret; - if ((xposCaret >= 0) && (vsDraw.caretWidth > 0) && (vsDraw.caretStyle != CARETSTYLE_INVISIBLE) && - ((model.posDrag.IsValid()) || (caretBlinkState && caretVisibleState))) { - bool caretAtEOF = false; - bool caretAtEOL = false; - bool drawBlockCaret = false; - XYPOSITION widthOverstrikeCaret; - XYPOSITION caretWidthOffset = 0; - PRectangle rcCaret = rcLine; - - if (posCaret.Position() == model.pdoc->Length()) { // At end of document - caretAtEOF = true; - widthOverstrikeCaret = vsDraw.aveCharWidth; - } else if ((posCaret.Position() - posLineStart) >= ll->numCharsInLine) { // At end of line - caretAtEOL = true; - widthOverstrikeCaret = vsDraw.aveCharWidth; - } else { - const int widthChar = model.pdoc->LenChar(posCaret.Position()); - widthOverstrikeCaret = ll->positions[offset + widthChar] - ll->positions[offset]; - } - if (widthOverstrikeCaret < 3) // Make sure its visible - widthOverstrikeCaret = 3; - - if (xposCaret > 0) - caretWidthOffset = 0.51f; // Move back so overlaps both character cells. - xposCaret += xStart; - if (model.posDrag.IsValid()) { - /* Dragging text, use a line caret */ - rcCaret.left = static_cast(RoundXYPosition(xposCaret - caretWidthOffset)); - rcCaret.right = rcCaret.left + vsDraw.caretWidth; - } else if (model.inOverstrike && drawOverstrikeCaret) { - /* Overstrike (insert mode), use a modified bar caret */ - rcCaret.top = rcCaret.bottom - 2; - rcCaret.left = xposCaret + 1; - rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1; - } else if ((vsDraw.caretStyle == CARETSTYLE_BLOCK) || imeCaretBlockOverride) { - /* Block caret */ - rcCaret.left = xposCaret; - if (!caretAtEOL && !caretAtEOF && (ll->chars[offset] != '\t') && !(IsControlCharacter(ll->chars[offset]))) { - drawBlockCaret = true; - rcCaret.right = xposCaret + widthOverstrikeCaret; - } else { - rcCaret.right = xposCaret + vsDraw.aveCharWidth; - } - } else { - /* Line caret */ - rcCaret.left = static_cast(RoundXYPosition(xposCaret - caretWidthOffset)); - rcCaret.right = rcCaret.left + vsDraw.caretWidth; - } - ColourDesired caretColour = mainCaret ? vsDraw.caretcolour : vsDraw.additionalCaretColour; - if (drawBlockCaret) { - DrawBlockCaret(surface, model, vsDraw, ll, subLine, xStart, offset, posCaret.Position(), rcCaret, caretColour); - } else { - surface->FillRectangle(rcCaret, caretColour); - } - } - } - if (drawDrag) - break; - } -} - -static void DrawWrapIndentAndMarker(Surface *surface, const ViewStyle &vsDraw, const LineLayout *ll, - int xStart, PRectangle rcLine, ColourOptional background, DrawWrapMarkerFn customDrawWrapMarker) { - // default bgnd here.. - surface->FillRectangle(rcLine, background.isSet ? background : - vsDraw.styles[STYLE_DEFAULT].back); - - if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_START) { - - // draw continuation rect - PRectangle rcPlace = rcLine; - - rcPlace.left = static_cast(xStart); - rcPlace.right = rcPlace.left + ll->wrapIndent; - - if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_START_BY_TEXT) - rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; - else - rcPlace.right = rcPlace.left + vsDraw.aveCharWidth; - - if (customDrawWrapMarker == NULL) { - DrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour()); - } else { - customDrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour()); - } - } -} - -void EditView::DrawBackground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - PRectangle rcLine, Range lineRange, int posLineStart, int xStart, - int subLine, ColourOptional background) const { - - const bool selBackDrawn = vsDraw.SelectionBackgroundDrawn(); - bool inIndentation = subLine == 0; // Do not handle indentation except on first subline. - const XYACCUMULATOR subLineStart = ll->positions[lineRange.start]; - // Does not take margin into account but not significant - const int xStartVisible = static_cast(subLineStart)-xStart; - - BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, selBackDrawn, model.pdoc, &model.reprs, NULL); - - const bool drawWhitespaceBackground = vsDraw.WhitespaceBackgroundDrawn() && !background.isSet; - - // Background drawing loop - while (bfBack.More()) { - - const TextSegment ts = bfBack.Next(); - const int i = ts.end() - 1; - const int iDoc = i + posLineStart; - - PRectangle rcSegment = rcLine; - rcSegment.left = ll->positions[ts.start] + xStart - static_cast(subLineStart); - rcSegment.right = ll->positions[ts.end()] + xStart - static_cast(subLineStart); - // Only try to draw if really visible - enhances performance by not calling environment to - // draw strings that are completely past the right side of the window. - if (rcSegment.Intersects(rcLine)) { - // Clip to line rectangle, since may have a huge position which will not work with some platforms - if (rcSegment.left < rcLine.left) - rcSegment.left = rcLine.left; - if (rcSegment.right > rcLine.right) - rcSegment.right = rcLine.right; - - const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc); - const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc); - ColourDesired textBack = TextBackground(model, vsDraw, ll, background, inSelection, - inHotspot, ll->styles[i], i); - if (ts.representation) { - if (ll->chars[i] == '\t') { - // Tab display - if (drawWhitespaceBackground && - (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) - textBack = vsDraw.whitespaceColours.back; - } else { - // Blob display - inIndentation = false; - } - surface->FillRectangle(rcSegment, textBack); - } else { - // Normal text display - surface->FillRectangle(rcSegment, textBack); - if (vsDraw.viewWhitespace != wsInvisible || - (inIndentation && vsDraw.viewIndentationGuides == ivReal)) { - for (int cpos = 0; cpos <= i - ts.start; cpos++) { - if (ll->chars[cpos + ts.start] == ' ') { - if (drawWhitespaceBackground && - (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { - PRectangle rcSpace( - ll->positions[cpos + ts.start] + xStart - static_cast(subLineStart), - rcSegment.top, - ll->positions[cpos + ts.start + 1] + xStart - static_cast(subLineStart), - rcSegment.bottom); - surface->FillRectangle(rcSpace, vsDraw.whitespaceColours.back); - } - } else { - inIndentation = false; - } - } - } - } - } else if (rcSegment.left > rcLine.right) { - break; - } - } -} - -static void DrawEdgeLine(Surface *surface, const ViewStyle &vsDraw, const LineLayout *ll, PRectangle rcLine, - Range lineRange, int xStart) { - if (vsDraw.edgeState == EDGE_LINE) { - PRectangle rcSegment = rcLine; - int edgeX = static_cast(vsDraw.theEdge * vsDraw.spaceWidth); - rcSegment.left = static_cast(edgeX + xStart); - if ((ll->wrapIndent != 0) && (lineRange.start != 0)) - rcSegment.left -= ll->wrapIndent; - rcSegment.right = rcSegment.left + 1; - surface->FillRectangle(rcSegment, vsDraw.edgecolour); - } -} - -// Draw underline mark as part of background if not transparent -static void DrawMarkUnderline(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, - int line, PRectangle rcLine) { - int marks = model.pdoc->GetMark(line); - for (int markBit = 0; (markBit < 32) && marks; markBit++) { - if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE) && - (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) { - PRectangle rcUnderline = rcLine; - rcUnderline.top = rcUnderline.bottom - 2; - surface->FillRectangle(rcUnderline, vsDraw.markers[markBit].back); - } - marks >>= 1; - } -} -static void DrawTranslucentSelection(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - int line, PRectangle rcLine, int subLine, Range lineRange, int xStart) { - if ((vsDraw.selAlpha != SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha != SC_ALPHA_NOALPHA)) { - const int posLineStart = model.pdoc->LineStart(line); - const XYACCUMULATOR subLineStart = ll->positions[lineRange.start]; - // For each selection draw - int virtualSpaces = 0; - if (subLine == (ll->lines - 1)) { - virtualSpaces = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)); - } - SelectionPosition posStart(posLineStart + lineRange.start); - SelectionPosition posEnd(posLineStart + lineRange.end, virtualSpaces); - SelectionSegment virtualSpaceRange(posStart, posEnd); - for (size_t r = 0; r < model.sel.Count(); r++) { - int alpha = (r == model.sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha; - if (alpha != SC_ALPHA_NOALPHA) { - SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange); - if (!portion.Empty()) { - const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; - PRectangle rcSegment = rcLine; - rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - - static_cast(subLineStart)+portion.start.VirtualSpace() * spaceWidth; - rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - - static_cast(subLineStart)+portion.end.VirtualSpace() * spaceWidth; - if ((ll->wrapIndent != 0) && (lineRange.start != 0)) { - if ((portion.start.Position() - posLineStart) == lineRange.start && model.sel.Range(r).ContainsCharacter(portion.start.Position() - 1)) - rcSegment.left -= static_cast(ll->wrapIndent); // indentation added to xStart was truncated to int, so we do the same here - } - rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; - rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; - if (rcSegment.right > rcLine.left) - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection), alpha); - } - } - } - } -} - -// Draw any translucent whole line states -static void DrawTranslucentLineState(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - int line, PRectangle rcLine) { - if ((model.caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && ll->containsCaret) { - SimpleAlphaRectangle(surface, rcLine, vsDraw.caretLineBackground, vsDraw.caretLineAlpha); - } - int marks = model.pdoc->GetMark(line); - for (int markBit = 0; (markBit < 32) && marks; markBit++) { - if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND)) { - SimpleAlphaRectangle(surface, rcLine, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); - } else if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE)) { - PRectangle rcUnderline = rcLine; - rcUnderline.top = rcUnderline.bottom - 2; - SimpleAlphaRectangle(surface, rcUnderline, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); - } - marks >>= 1; - } - if (vsDraw.maskInLine) { - int marksMasked = model.pdoc->GetMark(line) & vsDraw.maskInLine; - if (marksMasked) { - for (int markBit = 0; (markBit < 32) && marksMasked; markBit++) { - if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY)) { - SimpleAlphaRectangle(surface, rcLine, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); - } - marksMasked >>= 1; - } - } - } -} - -void EditView::DrawForeground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - int lineVisible, PRectangle rcLine, Range lineRange, int posLineStart, int xStart, - int subLine, ColourOptional background) { - - const bool selBackDrawn = vsDraw.SelectionBackgroundDrawn(); - const bool drawWhitespaceBackground = vsDraw.WhitespaceBackgroundDrawn() && !background.isSet; - bool inIndentation = subLine == 0; // Do not handle indentation except on first subline. - - const XYACCUMULATOR subLineStart = ll->positions[lineRange.start]; - const XYPOSITION indentWidth = model.pdoc->IndentSize() * vsDraw.spaceWidth; - - // Does not take margin into account but not significant - const int xStartVisible = static_cast(subLineStart)-xStart; - - // Foreground drawing loop - BreakFinder bfFore(ll, &model.sel, lineRange, posLineStart, xStartVisible, - (((phasesDraw == phasesOne) && selBackDrawn) || vsDraw.selColours.fore.isSet), model.pdoc, &model.reprs, &vsDraw); - - while (bfFore.More()) { - - const TextSegment ts = bfFore.Next(); - const int i = ts.end() - 1; - const int iDoc = i + posLineStart; - - PRectangle rcSegment = rcLine; - rcSegment.left = ll->positions[ts.start] + xStart - static_cast(subLineStart); - rcSegment.right = ll->positions[ts.end()] + xStart - static_cast(subLineStart); - // Only try to draw if really visible - enhances performance by not calling environment to - // draw strings that are completely past the right side of the window. - if (rcSegment.Intersects(rcLine)) { - int styleMain = ll->styles[i]; - ColourDesired textFore = vsDraw.styles[styleMain].fore; - FontAlias textFont = vsDraw.styles[styleMain].font; - //hotspot foreground - const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc); - if (inHotspot) { - if (vsDraw.hotspotColours.fore.isSet) - textFore = vsDraw.hotspotColours.fore; - } - if (vsDraw.indicatorsSetFore > 0) { - // At least one indicator sets the text colour so see if it applies to this segment - for (Decoration *deco = model.pdoc->decorations.root; deco; deco = deco->next) { - const int indicatorValue = deco->rs.ValueAt(ts.start + posLineStart); - if (indicatorValue) { - const Indicator &indicator = vsDraw.indicators[deco->indicator]; - const bool hover = indicator.IsDynamic() && - ((model.hoverIndicatorPos >= ts.start + posLineStart) && - (model.hoverIndicatorPos <= ts.end() + posLineStart)); - if (hover) { - if (indicator.sacHover.style == INDIC_TEXTFORE) { - textFore = indicator.sacHover.fore; - } - } else { - if (indicator.sacNormal.style == INDIC_TEXTFORE) { - if (indicator.Flags() & SC_INDICFLAG_VALUEFORE) - textFore = indicatorValue & SC_INDICVALUEMASK; - else - textFore = indicator.sacNormal.fore; - } - } - } - } - } - const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc); - if (inSelection && (vsDraw.selColours.fore.isSet)) { - textFore = (inSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground; - } - ColourDesired textBack = TextBackground(model, vsDraw, ll, background, inSelection, inHotspot, styleMain, i); - if (ts.representation) { - if (ll->chars[i] == '\t') { - // Tab display - if (phasesDraw == phasesOne) { - if (drawWhitespaceBackground && - (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) - textBack = vsDraw.whitespaceColours.back; - surface->FillRectangle(rcSegment, textBack); - } - if (inIndentation && vsDraw.viewIndentationGuides == ivReal) { - for (int indentCount = static_cast((ll->positions[i] + epsilon) / indentWidth); - indentCount <= (ll->positions[i + 1] - epsilon) / indentWidth; - indentCount++) { - if (indentCount > 0) { - int xIndent = static_cast(indentCount * indentWidth); - DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment, - (ll->xHighlightGuide == xIndent)); - } - } - } - if (vsDraw.viewWhitespace != wsInvisible) { - if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { - if (vsDraw.whitespaceColours.fore.isSet) - textFore = vsDraw.whitespaceColours.fore; - surface->PenColour(textFore); - PRectangle rcTab(rcSegment.left + 1, rcSegment.top + tabArrowHeight, - rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent); - if (customDrawTabArrow == NULL) - DrawTabArrow(surface, rcTab, static_cast(rcSegment.top + vsDraw.lineHeight / 2)); - else - customDrawTabArrow(surface, rcTab, static_cast(rcSegment.top + vsDraw.lineHeight / 2)); - } - } - } else { - inIndentation = false; - if (vsDraw.controlCharSymbol >= 32) { - // Using one font for all control characters so it can be controlled independently to ensure - // the box goes around the characters tightly. Seems to be no way to work out what height - // is taken by an individual character - internal leading gives varying results. - FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font; - char cc[2] = { static_cast(vsDraw.controlCharSymbol), '\0' }; - surface->DrawTextNoClip(rcSegment, ctrlCharsFont, - rcSegment.top + vsDraw.maxAscent, - cc, 1, textBack, textFore); - } else { - DrawTextBlob(surface, vsDraw, rcSegment, ts.representation->stringRep.c_str(), - textBack, textFore, phasesDraw == phasesOne); - } - } - } else { - // Normal text display - if (vsDraw.styles[styleMain].visible) { - if (phasesDraw != phasesOne) { - surface->DrawTextTransparent(rcSegment, textFont, - rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start, - i - ts.start + 1, textFore); - } else { - surface->DrawTextNoClip(rcSegment, textFont, - rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start, - i - ts.start + 1, textFore, textBack); - } - } - if (vsDraw.viewWhitespace != wsInvisible || - (inIndentation && vsDraw.viewIndentationGuides != ivNone)) { - for (int cpos = 0; cpos <= i - ts.start; cpos++) { - if (ll->chars[cpos + ts.start] == ' ') { - if (vsDraw.viewWhitespace != wsInvisible) { - if (vsDraw.whitespaceColours.fore.isSet) - textFore = vsDraw.whitespaceColours.fore; - if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { - XYPOSITION xmid = (ll->positions[cpos + ts.start] + ll->positions[cpos + ts.start + 1]) / 2; - if ((phasesDraw == phasesOne) && drawWhitespaceBackground && - (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { - textBack = vsDraw.whitespaceColours.back; - PRectangle rcSpace( - ll->positions[cpos + ts.start] + xStart - static_cast(subLineStart), - rcSegment.top, - ll->positions[cpos + ts.start + 1] + xStart - static_cast(subLineStart), - rcSegment.bottom); - surface->FillRectangle(rcSpace, textBack); - } - PRectangle rcDot(xmid + xStart - static_cast(subLineStart), - rcSegment.top + vsDraw.lineHeight / 2, 0.0f, 0.0f); - rcDot.right = rcDot.left + vsDraw.whitespaceSize; - rcDot.bottom = rcDot.top + vsDraw.whitespaceSize; - surface->FillRectangle(rcDot, textFore); - } - } - if (inIndentation && vsDraw.viewIndentationGuides == ivReal) { - for (int indentCount = static_cast((ll->positions[cpos + ts.start] + epsilon) / indentWidth); - indentCount <= (ll->positions[cpos + ts.start + 1] - epsilon) / indentWidth; - indentCount++) { - if (indentCount > 0) { - int xIndent = static_cast(indentCount * indentWidth); - DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment, - (ll->xHighlightGuide == xIndent)); - } - } - } - } else { - inIndentation = false; - } - } - } - } - if (ll->hotspot.Valid() && vsDraw.hotspotUnderline && ll->hotspot.ContainsCharacter(iDoc)) { - PRectangle rcUL = rcSegment; - rcUL.top = rcUL.top + vsDraw.maxAscent + 1; - rcUL.bottom = rcUL.top + 1; - if (vsDraw.hotspotColours.fore.isSet) - surface->FillRectangle(rcUL, vsDraw.hotspotColours.fore); - else - surface->FillRectangle(rcUL, textFore); - } else if (vsDraw.styles[styleMain].underline) { - PRectangle rcUL = rcSegment; - rcUL.top = rcUL.top + vsDraw.maxAscent + 1; - rcUL.bottom = rcUL.top + 1; - surface->FillRectangle(rcUL, textFore); - } - } else if (rcSegment.left > rcLine.right) { - break; - } - } -} - -void EditView::DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - int line, int lineVisible, PRectangle rcLine, int xStart, int subLine) { - if ((vsDraw.viewIndentationGuides == ivLookForward || vsDraw.viewIndentationGuides == ivLookBoth) - && (subLine == 0)) { - const int posLineStart = model.pdoc->LineStart(line); - int indentSpace = model.pdoc->GetLineIndentation(line); - int xStartText = static_cast(ll->positions[model.pdoc->GetLineIndentPosition(line) - posLineStart]); - - // Find the most recent line with some text - - int lineLastWithText = line; - while (lineLastWithText > Platform::Maximum(line - 20, 0) && model.pdoc->IsWhiteLine(lineLastWithText)) { - lineLastWithText--; - } - if (lineLastWithText < line) { - xStartText = 100000; // Don't limit to visible indentation on empty line - // This line is empty, so use indentation of last line with text - int indentLastWithText = model.pdoc->GetLineIndentation(lineLastWithText); - int isFoldHeader = model.pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG; - if (isFoldHeader) { - // Level is one more level than parent - indentLastWithText += model.pdoc->IndentSize(); - } - if (vsDraw.viewIndentationGuides == ivLookForward) { - // In viLookForward mode, previous line only used if it is a fold header - if (isFoldHeader) { - indentSpace = Platform::Maximum(indentSpace, indentLastWithText); - } - } else { // viLookBoth - indentSpace = Platform::Maximum(indentSpace, indentLastWithText); - } - } - - int lineNextWithText = line; - while (lineNextWithText < Platform::Minimum(line + 20, model.pdoc->LinesTotal()) && model.pdoc->IsWhiteLine(lineNextWithText)) { - lineNextWithText++; - } - if (lineNextWithText > line) { - xStartText = 100000; // Don't limit to visible indentation on empty line - // This line is empty, so use indentation of first next line with text - indentSpace = Platform::Maximum(indentSpace, - model.pdoc->GetLineIndentation(lineNextWithText)); - } - - for (int indentPos = model.pdoc->IndentSize(); indentPos < indentSpace; indentPos += model.pdoc->IndentSize()) { - int xIndent = static_cast(indentPos * vsDraw.spaceWidth); - if (xIndent < xStartText) { - DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcLine, - (ll->xHighlightGuide == xIndent)); - } - } - } -} - -void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - int line, int lineVisible, int xStart, PRectangle rcLine, int subLine, DrawPhase phase) { - - if (subLine >= ll->lines) { - DrawAnnotation(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, phase); - return; // No further drawing - } - - // See if something overrides the line background color. - const ColourOptional background = vsDraw.Background(model.pdoc->GetMark(line), model.caret.active, ll->containsCaret); - - const int posLineStart = model.pdoc->LineStart(line); - - const Range lineRange = ll->SubLineRange(subLine); - const XYACCUMULATOR subLineStart = ll->positions[lineRange.start]; - - if ((ll->wrapIndent != 0) && (subLine > 0)) { - if (phase & drawBack) { - DrawWrapIndentAndMarker(surface, vsDraw, ll, xStart, rcLine, background, customDrawWrapMarker); - } - xStart += static_cast(ll->wrapIndent); - } - - if ((phasesDraw != phasesOne) && (phase & drawBack)) { - DrawBackground(surface, model, vsDraw, ll, rcLine, lineRange, posLineStart, xStart, - subLine, background); - DrawEOL(surface, model, vsDraw, ll, rcLine, line, lineRange.end, - xStart, subLine, subLineStart, background); - } - - if (phase & drawIndicatorsBack) { - DrawIndicators(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, lineRange.end, true, model.hoverIndicatorPos); - DrawEdgeLine(surface, vsDraw, ll, rcLine, lineRange, xStart); - DrawMarkUnderline(surface, model, vsDraw, line, rcLine); - } - - if (phase & drawText) { - DrawForeground(surface, model, vsDraw, ll, lineVisible, rcLine, lineRange, posLineStart, xStart, - subLine, background); - } - - if (phase & drawIndentationGuides) { - DrawIndentGuidesOverEmpty(surface, model, vsDraw, ll, line, lineVisible, rcLine, xStart, subLine); - } - - if (phase & drawIndicatorsFore) { - DrawIndicators(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, lineRange.end, false, model.hoverIndicatorPos); - } - - // End of the drawing of the current line - if (phasesDraw == phasesOne) { - DrawEOL(surface, model, vsDraw, ll, rcLine, line, lineRange.end, - xStart, subLine, subLineStart, background); - } - - if (!hideSelection && (phase & drawSelectionTranslucent)) { - DrawTranslucentSelection(surface, model, vsDraw, ll, line, rcLine, subLine, lineRange, xStart); - } - - if (phase & drawLineTranslucent) { - DrawTranslucentLineState(surface, model, vsDraw, ll, line, rcLine); - } -} - -static void DrawFoldLines(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, int line, PRectangle rcLine) { - bool expanded = model.cs.GetExpanded(line); - const int level = model.pdoc->GetLevel(line); - const int levelNext = model.pdoc->GetLevel(line + 1); - if ((level & SC_FOLDLEVELHEADERFLAG) && - ((level & SC_FOLDLEVELNUMBERMASK) < (levelNext & SC_FOLDLEVELNUMBERMASK))) { - // Paint the line above the fold - if ((expanded && (model.foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED)) - || - (!expanded && (model.foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) { - PRectangle rcFoldLine = rcLine; - rcFoldLine.bottom = rcFoldLine.top + 1; - surface->FillRectangle(rcFoldLine, vsDraw.styles[STYLE_DEFAULT].fore); - } - // Paint the line below the fold - if ((expanded && (model.foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED)) - || - (!expanded && (model.foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) { - PRectangle rcFoldLine = rcLine; - rcFoldLine.top = rcFoldLine.bottom - 1; - surface->FillRectangle(rcFoldLine, vsDraw.styles[STYLE_DEFAULT].fore); - } - } -} - -void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectangle rcArea, - PRectangle rcClient, const ViewStyle &vsDraw) { - // Allow text at start of line to overlap 1 pixel into the margin as this displays - // serifs and italic stems for aliased text. - const int leftTextOverlap = ((model.xOffset == 0) && (vsDraw.leftMarginWidth > 0)) ? 1 : 0; - - // Do the painting - if (rcArea.right > vsDraw.textStart - leftTextOverlap) { - - Surface *surface = surfaceWindow; - if (bufferedDraw) { - surface = pixmapLine; - PLATFORM_ASSERT(pixmapLine->Initialised()); - } - surface->SetUnicodeMode(SC_CP_UTF8 == model.pdoc->dbcsCodePage); - surface->SetDBCSMode(model.pdoc->dbcsCodePage); - - const Point ptOrigin = model.GetVisibleOriginInMain(); - - const int screenLinePaintFirst = static_cast(rcArea.top) / vsDraw.lineHeight; - const int xStart = vsDraw.textStart - model.xOffset + static_cast(ptOrigin.x); - - SelectionPosition posCaret = model.sel.RangeMain().caret; - if (model.posDrag.IsValid()) - posCaret = model.posDrag; - const int lineCaret = model.pdoc->LineFromPosition(posCaret.Position()); - - PRectangle rcTextArea = rcClient; - if (vsDraw.marginInside) { - rcTextArea.left += vsDraw.textStart; - rcTextArea.right -= vsDraw.rightMarginWidth; - } else { - rcTextArea = rcArea; - } - - // Remove selection margin from drawing area so text will not be drawn - // on it in unbuffered mode. - if (!bufferedDraw && vsDraw.marginInside) { - PRectangle rcClipText = rcTextArea; - rcClipText.left -= leftTextOverlap; - surfaceWindow->SetClip(rcClipText); - } - - // Loop on visible lines - //double durLayout = 0.0; - //double durPaint = 0.0; - //double durCopy = 0.0; - //ElapsedTime etWhole; - - const bool bracesIgnoreStyle = ((vsDraw.braceHighlightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACELIGHT)) || - (vsDraw.braceBadLightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACEBAD))); - - int lineDocPrevious = -1; // Used to avoid laying out one document line multiple times - AutoLineLayout ll(llc, 0); - std::vector phases; - if ((phasesDraw == phasesMultiple) && !bufferedDraw) { - for (DrawPhase phase = drawBack; phase <= drawCarets; phase = static_cast(phase * 2)) { - phases.push_back(phase); - } - } else { - phases.push_back(drawAll); - } - for (std::vector::iterator it = phases.begin(); it != phases.end(); ++it) { - int ypos = 0; - if (!bufferedDraw) - ypos += screenLinePaintFirst * vsDraw.lineHeight; - int yposScreen = screenLinePaintFirst * vsDraw.lineHeight; - int visibleLine = model.TopLineOfMain() + screenLinePaintFirst; - while (visibleLine < model.cs.LinesDisplayed() && yposScreen < rcArea.bottom) { - - const int lineDoc = model.cs.DocFromDisplay(visibleLine); - // Only visible lines should be handled by the code within the loop - PLATFORM_ASSERT(model.cs.GetVisible(lineDoc)); - const int lineStartSet = model.cs.DisplayFromDoc(lineDoc); - const int subLine = visibleLine - lineStartSet; - - // Copy this line and its styles from the document into local arrays - // and determine the x position at which each character starts. - //ElapsedTime et; - if (lineDoc != lineDocPrevious) { - ll.Set(0); - ll.Set(RetrieveLineLayout(lineDoc, model)); - LayoutLine(model, lineDoc, surface, vsDraw, ll, model.wrapWidth); - lineDocPrevious = lineDoc; - } - //durLayout += et.Duration(true); - - if (ll) { - ll->containsCaret = !hideSelection && (lineDoc == lineCaret); - ll->hotspot = model.GetHotSpotRange(); - - PRectangle rcLine = rcTextArea; - rcLine.top = static_cast(ypos); - rcLine.bottom = static_cast(ypos + vsDraw.lineHeight); - - Range rangeLine(model.pdoc->LineStart(lineDoc), model.pdoc->LineStart(lineDoc + 1)); - - // Highlight the current braces if any - ll->SetBracesHighlight(rangeLine, model.braces, static_cast(model.bracesMatchStyle), - static_cast(model.highlightGuideColumn * vsDraw.spaceWidth), bracesIgnoreStyle); - - if (leftTextOverlap && bufferedDraw) { - PRectangle rcSpacer = rcLine; - rcSpacer.right = rcSpacer.left; - rcSpacer.left -= 1; - surface->FillRectangle(rcSpacer, vsDraw.styles[STYLE_DEFAULT].back); - } - - DrawLine(surface, model, vsDraw, ll, lineDoc, visibleLine, xStart, rcLine, subLine, *it); - //durPaint += et.Duration(true); - - // Restore the previous styles for the brace highlights in case layout is in cache. - ll->RestoreBracesHighlight(rangeLine, model.braces, bracesIgnoreStyle); - - if (*it & drawFoldLines) { - DrawFoldLines(surface, model, vsDraw, lineDoc, rcLine); - } - - if (*it & drawCarets) { - DrawCarets(surface, model, vsDraw, ll, lineDoc, xStart, rcLine, subLine); - } - - if (bufferedDraw) { - Point from = Point::FromInts(vsDraw.textStart - leftTextOverlap, 0); - PRectangle rcCopyArea = PRectangle::FromInts(vsDraw.textStart - leftTextOverlap, yposScreen, - static_cast(rcClient.right - vsDraw.rightMarginWidth), - yposScreen + vsDraw.lineHeight); - surfaceWindow->Copy(rcCopyArea, from, *pixmapLine); - } - - lineWidthMaxSeen = Platform::Maximum( - lineWidthMaxSeen, static_cast(ll->positions[ll->numCharsInLine])); - //durCopy += et.Duration(true); - } - - if (!bufferedDraw) { - ypos += vsDraw.lineHeight; - } - - yposScreen += vsDraw.lineHeight; - visibleLine++; - } - } - ll.Set(0); - //if (durPaint < 0.00000001) - // durPaint = 0.00000001; - - // Right column limit indicator - PRectangle rcBeyondEOF = (vsDraw.marginInside) ? rcClient : rcArea; - rcBeyondEOF.left = static_cast(vsDraw.textStart); - rcBeyondEOF.right = rcBeyondEOF.right - ((vsDraw.marginInside) ? vsDraw.rightMarginWidth : 0); - rcBeyondEOF.top = static_cast((model.cs.LinesDisplayed() - model.TopLineOfMain()) * vsDraw.lineHeight); - if (rcBeyondEOF.top < rcBeyondEOF.bottom) { - surfaceWindow->FillRectangle(rcBeyondEOF, vsDraw.styles[STYLE_DEFAULT].back); - if (vsDraw.edgeState == EDGE_LINE) { - int edgeX = static_cast(vsDraw.theEdge * vsDraw.spaceWidth); - rcBeyondEOF.left = static_cast(edgeX + xStart); - rcBeyondEOF.right = rcBeyondEOF.left + 1; - surfaceWindow->FillRectangle(rcBeyondEOF, vsDraw.edgecolour); - } - } - //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset); - - //Platform::DebugPrintf( - //"Layout:%9.6g Paint:%9.6g Ratio:%9.6g Copy:%9.6g Total:%9.6g\n", - //durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration()); - } -} - -// Space (3 space characters) between line numbers and text when printing. -#define lineNumberPrintSpace " " - -ColourDesired InvertedLight(ColourDesired orig) { - unsigned int r = orig.GetRed(); - unsigned int g = orig.GetGreen(); - unsigned int b = orig.GetBlue(); - unsigned int l = (r + g + b) / 3; // There is a better calculation for this that matches human eye - unsigned int il = 0xff - l; - if (l == 0) - return ColourDesired(0xff, 0xff, 0xff); - r = r * il / l; - g = g * il / l; - b = b * il / l; - return ColourDesired(Platform::Minimum(r, 0xff), Platform::Minimum(g, 0xff), Platform::Minimum(b, 0xff)); -} - -long EditView::FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure, - const EditModel &model, const ViewStyle &vs) { - // Can't use measurements cached for screen - posCache.Clear(); - - ViewStyle vsPrint(vs); - vsPrint.technology = SC_TECHNOLOGY_DEFAULT; - - // Modify the view style for printing as do not normally want any of the transient features to be printed - // Printing supports only the line number margin. - int lineNumberIndex = -1; - for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) { - if ((vsPrint.ms[margin].style == SC_MARGIN_NUMBER) && (vsPrint.ms[margin].width > 0)) { - lineNumberIndex = margin; - } else { - vsPrint.ms[margin].width = 0; - } - } - vsPrint.fixedColumnWidth = 0; - vsPrint.zoomLevel = printParameters.magnification; - // Don't show indentation guides - // If this ever gets changed, cached pixmap would need to be recreated if technology != SC_TECHNOLOGY_DEFAULT - vsPrint.viewIndentationGuides = ivNone; - // Don't show the selection when printing - vsPrint.selColours.back.isSet = false; - vsPrint.selColours.fore.isSet = false; - vsPrint.selAlpha = SC_ALPHA_NOALPHA; - vsPrint.selAdditionalAlpha = SC_ALPHA_NOALPHA; - vsPrint.whitespaceColours.back.isSet = false; - vsPrint.whitespaceColours.fore.isSet = false; - vsPrint.showCaretLineBackground = false; - vsPrint.alwaysShowCaretLineBackground = false; - // Don't highlight matching braces using indicators - vsPrint.braceHighlightIndicatorSet = false; - vsPrint.braceBadLightIndicatorSet = false; - - // Set colours for printing according to users settings - for (size_t sty = 0; sty < vsPrint.styles.size(); sty++) { - if (printParameters.colourMode == SC_PRINT_INVERTLIGHT) { - vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore); - vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back); - } else if (printParameters.colourMode == SC_PRINT_BLACKONWHITE) { - vsPrint.styles[sty].fore = ColourDesired(0, 0, 0); - vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); - } else if (printParameters.colourMode == SC_PRINT_COLOURONWHITE) { - vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); - } else if (printParameters.colourMode == SC_PRINT_COLOURONWHITEDEFAULTBG) { - if (sty <= STYLE_DEFAULT) { - vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); - } - } - } - // White background for the line numbers - vsPrint.styles[STYLE_LINENUMBER].back = ColourDesired(0xff, 0xff, 0xff); - - // Printing uses different margins, so reset screen margins - vsPrint.leftMarginWidth = 0; - vsPrint.rightMarginWidth = 0; - - vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars); - // Determining width must happen after fonts have been realised in Refresh - int lineNumberWidth = 0; - if (lineNumberIndex >= 0) { - lineNumberWidth = static_cast(surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font, - "99999" lineNumberPrintSpace, 5 + static_cast(strlen(lineNumberPrintSpace)))); - vsPrint.ms[lineNumberIndex].width = lineNumberWidth; - vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars); // Recalculate fixedColumnWidth - } - - int linePrintStart = model.pdoc->LineFromPosition(static_cast(pfr->chrg.cpMin)); - int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1; - if (linePrintLast < linePrintStart) - linePrintLast = linePrintStart; - int linePrintMax = model.pdoc->LineFromPosition(static_cast(pfr->chrg.cpMax)); - if (linePrintLast > linePrintMax) - linePrintLast = linePrintMax; - //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n", - // linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight, - // surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font)); - int endPosPrint = model.pdoc->Length(); - if (linePrintLast < model.pdoc->LinesTotal()) - endPosPrint = model.pdoc->LineStart(linePrintLast + 1); - - // Ensure we are styled to where we are formatting. - model.pdoc->EnsureStyledTo(endPosPrint); - - int xStart = vsPrint.fixedColumnWidth + pfr->rc.left; - int ypos = pfr->rc.top; - - int lineDoc = linePrintStart; - - int nPrintPos = static_cast(pfr->chrg.cpMin); - int visibleLine = 0; - int widthPrint = pfr->rc.right - pfr->rc.left - vsPrint.fixedColumnWidth; - if (printParameters.wrapState == eWrapNone) - widthPrint = LineLayout::wrapWidthInfinite; - - while (lineDoc <= linePrintLast && ypos < pfr->rc.bottom) { - - // When printing, the hdc and hdcTarget may be the same, so - // changing the state of surfaceMeasure may change the underlying - // state of surface. Therefore, any cached state is discarded before - // using each surface. - surfaceMeasure->FlushCachedState(); - - // Copy this line and its styles from the document into local arrays - // and determine the x position at which each character starts. - LineLayout ll(model.pdoc->LineStart(lineDoc + 1) - model.pdoc->LineStart(lineDoc) + 1); - LayoutLine(model, lineDoc, surfaceMeasure, vsPrint, &ll, widthPrint); - - ll.containsCaret = false; - - PRectangle rcLine = PRectangle::FromInts( - pfr->rc.left, - ypos, - pfr->rc.right - 1, - ypos + vsPrint.lineHeight); - - // When document line is wrapped over multiple display lines, find where - // to start printing from to ensure a particular position is on the first - // line of the page. - if (visibleLine == 0) { - int startWithinLine = nPrintPos - model.pdoc->LineStart(lineDoc); - for (int iwl = 0; iwl < ll.lines - 1; iwl++) { - if (ll.LineStart(iwl) <= startWithinLine && ll.LineStart(iwl + 1) >= startWithinLine) { - visibleLine = -iwl; - } - } - - if (ll.lines > 1 && startWithinLine >= ll.LineStart(ll.lines - 1)) { - visibleLine = -(ll.lines - 1); - } - } - - if (draw && lineNumberWidth && - (ypos + vsPrint.lineHeight <= pfr->rc.bottom) && - (visibleLine >= 0)) { - char number[100]; - sprintf(number, "%d" lineNumberPrintSpace, lineDoc + 1); - PRectangle rcNumber = rcLine; - rcNumber.right = rcNumber.left + lineNumberWidth; - // Right justify - rcNumber.left = rcNumber.right - surfaceMeasure->WidthText( - vsPrint.styles[STYLE_LINENUMBER].font, number, static_cast(strlen(number))); - surface->FlushCachedState(); - surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font, - static_cast(ypos + vsPrint.maxAscent), number, static_cast(strlen(number)), - vsPrint.styles[STYLE_LINENUMBER].fore, - vsPrint.styles[STYLE_LINENUMBER].back); - } - - // Draw the line - surface->FlushCachedState(); - - for (int iwl = 0; iwl < ll.lines; iwl++) { - if (ypos + vsPrint.lineHeight <= pfr->rc.bottom) { - if (visibleLine >= 0) { - if (draw) { - rcLine.top = static_cast(ypos); - rcLine.bottom = static_cast(ypos + vsPrint.lineHeight); - DrawLine(surface, model, vsPrint, &ll, lineDoc, visibleLine, xStart, rcLine, iwl, drawAll); - } - ypos += vsPrint.lineHeight; - } - visibleLine++; - if (iwl == ll.lines - 1) - nPrintPos = model.pdoc->LineStart(lineDoc + 1); - else - nPrintPos += ll.LineStart(iwl + 1) - ll.LineStart(iwl); - } - } - - ++lineDoc; - } - - // Clear cache so measurements are not used for screen - posCache.Clear(); - - return nPrintPos; -} diff --git a/libs/qscintilla/src/EditView.h b/libs/qscintilla/src/EditView.h deleted file mode 100644 index 70af6b2bf..000000000 --- a/libs/qscintilla/src/EditView.h +++ /dev/null @@ -1,173 +0,0 @@ -// Scintilla source code edit control -/** @file EditView.h - ** Defines the appearance of the main text area of the editor window. - **/ -// Copyright 1998-2014 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef EDITVIEW_H -#define EDITVIEW_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -struct PrintParameters { - int magnification; - int colourMode; - WrapMode wrapState; - PrintParameters(); -}; - -/** -* The view may be drawn in separate phases. -*/ -enum DrawPhase { - drawBack = 0x1, - drawIndicatorsBack = 0x2, - drawText = 0x4, - drawIndentationGuides = 0x8, - drawIndicatorsFore = 0x10, - drawSelectionTranslucent = 0x20, - drawLineTranslucent = 0x40, - drawFoldLines = 0x80, - drawCarets = 0x100, - drawAll = 0x1FF -}; - -bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st); -int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st); -void DrawTextNoClipPhase(Surface *surface, PRectangle rc, const Style &style, XYPOSITION ybase, - const char *s, int len, DrawPhase phase); -void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText, - const StyledText &st, size_t start, size_t length, DrawPhase phase); - -typedef void (*DrawTabArrowFn)(Surface *surface, PRectangle rcTab, int ymid); - -/** -* EditView draws the main text area. -*/ -class EditView { -public: - PrintParameters printParameters; - PerLine *ldTabstops; - - bool hideSelection; - bool drawOverstrikeCaret; - - /** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to - * the screen. This avoids flashing but is about 30% slower. */ - bool bufferedDraw; - /** In phasesTwo mode, drawing is performed in two phases, first the background - * and then the foreground. This avoids chopping off characters that overlap the next run. - * In multiPhaseDraw mode, drawing is performed in multiple phases with each phase drawing - * one feature over the whole drawing area, instead of within one line. This allows text to - * overlap from one line to the next. */ - enum PhasesDraw { phasesOne, phasesTwo, phasesMultiple }; - PhasesDraw phasesDraw; - - int lineWidthMaxSeen; - - bool additionalCaretsBlink; - bool additionalCaretsVisible; - - bool imeCaretBlockOverride; - - Surface *pixmapLine; - Surface *pixmapIndentGuide; - Surface *pixmapIndentGuideHighlight; - - LineLayoutCache llc; - PositionCache posCache; - - int tabArrowHeight; // draw arrow heads this many pixels above/below line midpoint - /** Some platforms, notably PLAT_CURSES, do not support Scintilla's native - * DrawTabArrow function for drawing tab characters. Allow those platforms to - * override it instead of creating a new method in the Surface class that - * existing platforms must implement as empty. */ - DrawTabArrowFn customDrawTabArrow; - DrawWrapMarkerFn customDrawWrapMarker; - - EditView(); - virtual ~EditView(); - - bool SetTwoPhaseDraw(bool twoPhaseDraw); - bool SetPhasesDraw(int phases); - bool LinesOverlap() const; - - void ClearAllTabstops(); - XYPOSITION NextTabstopPos(int line, XYPOSITION x, XYPOSITION tabWidth) const; - bool ClearTabstops(int line); - bool AddTabstop(int line, int x); - int GetNextTabstop(int line, int x) const; - void LinesAddedOrRemoved(int lineOfPos, int linesAdded); - - void DropGraphics(bool freeObjects); - void AllocateGraphics(const ViewStyle &vsDraw); - void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw); - - LineLayout *RetrieveLineLayout(int lineNumber, const EditModel &model); - void LayoutLine(const EditModel &model, int line, Surface *surface, const ViewStyle &vstyle, - LineLayout *ll, int width = LineLayout::wrapWidthInfinite); - - Point LocationFromPosition(Surface *surface, const EditModel &model, SelectionPosition pos, int topLine, const ViewStyle &vs); - SelectionPosition SPositionFromLocation(Surface *surface, const EditModel &model, Point pt, bool canReturnInvalid, - bool charPosition, bool virtualSpace, const ViewStyle &vs); - SelectionPosition SPositionFromLineX(Surface *surface, const EditModel &model, int lineDoc, int x, const ViewStyle &vs); - int DisplayFromPosition(Surface *surface, const EditModel &model, int pos, const ViewStyle &vs); - int StartEndDisplayLine(Surface *surface, const EditModel &model, int pos, bool start, const ViewStyle &vs); - - void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight); - void DrawEOL(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, PRectangle rcLine, - int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart, - ColourOptional background); - void DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - int line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase); - void DrawCarets(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, int line, - int xStart, PRectangle rcLine, int subLine) const; - void DrawBackground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, PRectangle rcLine, - Range lineRange, int posLineStart, int xStart, - int subLine, ColourOptional background) const; - void DrawForeground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, int lineVisible, - PRectangle rcLine, Range lineRange, int posLineStart, int xStart, - int subLine, ColourOptional background); - void DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - int line, int lineVisible, PRectangle rcLine, int xStart, int subLine); - void DrawLine(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, int line, - int lineVisible, int xStart, PRectangle rcLine, int subLine, DrawPhase phase); - void PaintText(Surface *surfaceWindow, const EditModel &model, PRectangle rcArea, PRectangle rcClient, - const ViewStyle &vsDraw); - long FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure, - const EditModel &model, const ViewStyle &vs); -}; - -/** -* Convenience class to ensure LineLayout objects are always disposed. -*/ -class AutoLineLayout { - LineLayoutCache &llc; - LineLayout *ll; - AutoLineLayout &operator=(const AutoLineLayout &); -public: - AutoLineLayout(LineLayoutCache &llc_, LineLayout *ll_) : llc(llc_), ll(ll_) {} - ~AutoLineLayout() { - llc.Dispose(ll); - ll = 0; - } - LineLayout *operator->() const { - return ll; - } - operator LineLayout *() const { - return ll; - } - void Set(LineLayout *ll_) { - llc.Dispose(ll); - ll = ll_; - } -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/Editor.cpp b/libs/qscintilla/src/Editor.cpp deleted file mode 100644 index 585acb086..000000000 --- a/libs/qscintilla/src/Editor.cpp +++ /dev/null @@ -1,7679 +0,0 @@ -// Scintilla source code edit control -/** @file Editor.cxx - ** Main code for the edit control. - **/ -// Copyright 1998-2011 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "ILexer.h" -#include "Scintilla.h" - -#include "StringCopy.h" -#include "SplitVector.h" -#include "Partitioning.h" -#include "RunStyles.h" -#include "ContractionState.h" -#include "CellBuffer.h" -#include "PerLine.h" -#include "KeyMap.h" -#include "Indicator.h" -#include "XPM.h" -#include "LineMarker.h" -#include "Style.h" -#include "ViewStyle.h" -#include "CharClassify.h" -#include "Decoration.h" -#include "CaseFolder.h" -#include "Document.h" -#include "UniConversion.h" -#include "Selection.h" -#include "PositionCache.h" -#include "EditModel.h" -#include "MarginView.h" -#include "EditView.h" -#include "Editor.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/* - return whether this modification represents an operation that - may reasonably be deferred (not done now OR [possibly] at all) -*/ -static bool CanDeferToLastStep(const DocModification &mh) { - if (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) - return true; // CAN skip - if (!(mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO))) - return false; // MUST do - if (mh.modificationType & SC_MULTISTEPUNDOREDO) - return true; // CAN skip - return false; // PRESUMABLY must do -} - -static bool CanEliminate(const DocModification &mh) { - return - (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) != 0; -} - -/* - return whether this modification represents the FINAL step - in a [possibly lengthy] multi-step Undo/Redo sequence -*/ -static bool IsLastStep(const DocModification &mh) { - return - (mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)) != 0 - && (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0 - && (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0 - && (mh.modificationType & SC_MULTILINEUNDOREDO) != 0; -} - -Timer::Timer() : - ticking(false), ticksToWait(0), tickerID(0) {} - -Idler::Idler() : - state(false), idlerID(0) {} - -static inline bool IsAllSpacesOrTabs(const char *s, unsigned int len) { - for (unsigned int i = 0; i < len; i++) { - // This is safe because IsSpaceOrTab() will return false for null terminators - if (!IsSpaceOrTab(s[i])) - return false; - } - return true; -} - -Editor::Editor() { - ctrlID = 0; - - stylesValid = false; - technology = SC_TECHNOLOGY_DEFAULT; - scaleRGBAImage = 100.0f; - - cursorMode = SC_CURSORNORMAL; - - hasFocus = false; - errorStatus = 0; - mouseDownCaptures = true; - - lastClickTime = 0; - doubleClickCloseThreshold = Point(3, 3); - dwellDelay = SC_TIME_FOREVER; - ticksToDwell = SC_TIME_FOREVER; - dwelling = false; - ptMouseLast.x = 0; - ptMouseLast.y = 0; - inDragDrop = ddNone; - dropWentOutside = false; - posDrop = SelectionPosition(invalidPosition); - hotSpotClickPos = INVALID_POSITION; - selectionType = selChar; - - lastXChosen = 0; - lineAnchorPos = 0; - originalAnchorPos = 0; - wordSelectAnchorStartPos = 0; - wordSelectAnchorEndPos = 0; - wordSelectInitialCaretPos = -1; - - caretXPolicy = CARET_SLOP | CARET_EVEN; - caretXSlop = 50; - - caretYPolicy = CARET_EVEN; - caretYSlop = 0; - - visiblePolicy = 0; - visibleSlop = 0; - - searchAnchor = 0; - - xCaretMargin = 50; - horizontalScrollBarVisible = true; - scrollWidth = 2000; - verticalScrollBarVisible = true; - endAtLastLine = true; - caretSticky = SC_CARETSTICKY_OFF; - marginOptions = SC_MARGINOPTION_NONE; - mouseSelectionRectangularSwitch = false; - multipleSelection = false; - additionalSelectionTyping = false; - multiPasteMode = SC_MULTIPASTE_ONCE; - virtualSpaceOptions = SCVS_NONE; - - targetStart = 0; - targetEnd = 0; - searchFlags = 0; - - topLine = 0; - posTopLine = 0; - - lengthForEncode = -1; - - needUpdateUI = 0; - ContainerNeedsUpdate(SC_UPDATE_CONTENT); - - paintState = notPainting; - paintAbandonedByStyling = false; - paintingAllText = false; - willRedrawAll = false; - - modEventMask = SC_MODEVENTMASKALL; - - pdoc->AddWatcher(this, 0); - - recordingMacro = false; - foldAutomatic = 0; - - convertPastes = true; - - SetRepresentations(); -} - -Editor::~Editor() { - pdoc->RemoveWatcher(this, 0); - DropGraphics(true); -} - -void Editor::Finalise() { - SetIdle(false); - CancelModes(); -} - -void Editor::SetRepresentations() { - reprs.Clear(); - - // C0 control set - const char *reps[] = { - "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", - "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", - "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", - "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US" - }; - for (size_t j=0; j < ELEMENTS(reps); j++) { - char c[2] = { static_cast(j), 0 }; - reprs.SetRepresentation(c, reps[j]); - } - - // C1 control set - // As well as Unicode mode, ISO-8859-1 should use these - if (IsUnicodeMode()) { - const char *repsC1[] = { - "PAD", "HOP", "BPH", "NBH", "IND", "NEL", "SSA", "ESA", - "HTS", "HTJ", "VTS", "PLD", "PLU", "RI", "SS2", "SS3", - "DCS", "PU1", "PU2", "STS", "CCH", "MW", "SPA", "EPA", - "SOS", "SGCI", "SCI", "CSI", "ST", "OSC", "PM", "APC" - }; - for (size_t j=0; j < ELEMENTS(repsC1); j++) { - char c1[3] = { '\xc2', static_cast(0x80+j), 0 }; - reprs.SetRepresentation(c1, repsC1[j]); - } - reprs.SetRepresentation("\xe2\x80\xa8", "LS"); - reprs.SetRepresentation("\xe2\x80\xa9", "PS"); - } - - // UTF-8 invalid bytes - if (IsUnicodeMode()) { - for (int k=0x80; k < 0x100; k++) { - char hiByte[2] = { static_cast(k), 0 }; - char hexits[4]; - sprintf(hexits, "x%2X", k); - reprs.SetRepresentation(hiByte, hexits); - } - } -} - -void Editor::DropGraphics(bool freeObjects) { - marginView.DropGraphics(freeObjects); - view.DropGraphics(freeObjects); -} - -void Editor::AllocateGraphics() { - marginView.AllocateGraphics(vs); - view.AllocateGraphics(vs); -} - -void Editor::InvalidateStyleData() { - stylesValid = false; - vs.technology = technology; - DropGraphics(false); - AllocateGraphics(); - view.llc.Invalidate(LineLayout::llInvalid); - view.posCache.Clear(); -} - -void Editor::InvalidateStyleRedraw() { - NeedWrapping(); - InvalidateStyleData(); - Redraw(); -} - -void Editor::RefreshStyleData() { - if (!stylesValid) { - stylesValid = true; - AutoSurface surface(this); - if (surface) { - vs.Refresh(*surface, pdoc->tabInChars); - } - SetScrollBars(); - SetRectangularRange(); - } -} - -Point Editor::GetVisibleOriginInMain() const { - return Point(0,0); -} - -Point Editor::DocumentPointFromView(Point ptView) const { - Point ptDocument = ptView; - if (wMargin.GetID()) { - Point ptOrigin = GetVisibleOriginInMain(); - ptDocument.x += ptOrigin.x; - ptDocument.y += ptOrigin.y; - } else { - ptDocument.x += xOffset; - ptDocument.y += topLine * vs.lineHeight; - } - return ptDocument; -} - -int Editor::TopLineOfMain() const { - if (wMargin.GetID()) - return 0; - else - return topLine; -} - -PRectangle Editor::GetClientRectangle() const { - Window &win = const_cast(wMain); - return win.GetClientPosition(); -} - -PRectangle Editor::GetClientDrawingRectangle() { - return GetClientRectangle(); -} - -PRectangle Editor::GetTextRectangle() const { - PRectangle rc = GetClientRectangle(); - rc.left += vs.textStart; - rc.right -= vs.rightMarginWidth; - return rc; -} - -int Editor::LinesOnScreen() const { - PRectangle rcClient = GetClientRectangle(); - int htClient = static_cast(rcClient.bottom - rcClient.top); - //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1); - return htClient / vs.lineHeight; -} - -int Editor::LinesToScroll() const { - int retVal = LinesOnScreen() - 1; - if (retVal < 1) - return 1; - else - return retVal; -} - -int Editor::MaxScrollPos() const { - //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n", - //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1); - int retVal = cs.LinesDisplayed(); - if (endAtLastLine) { - retVal -= LinesOnScreen(); - } else { - retVal--; - } - if (retVal < 0) { - return 0; - } else { - return retVal; - } -} - -SelectionPosition Editor::ClampPositionIntoDocument(SelectionPosition sp) const { - if (sp.Position() < 0) { - return SelectionPosition(0); - } else if (sp.Position() > pdoc->Length()) { - return SelectionPosition(pdoc->Length()); - } else { - // If not at end of line then set offset to 0 - if (!pdoc->IsLineEndPosition(sp.Position())) - sp.SetVirtualSpace(0); - return sp; - } -} - -Point Editor::LocationFromPosition(SelectionPosition pos) { - RefreshStyleData(); - AutoSurface surface(this); - return view.LocationFromPosition(surface, *this, pos, topLine, vs); -} - -Point Editor::LocationFromPosition(int pos) { - return LocationFromPosition(SelectionPosition(pos)); -} - -int Editor::XFromPosition(int pos) { - Point pt = LocationFromPosition(pos); - return static_cast(pt.x) - vs.textStart + xOffset; -} - -int Editor::XFromPosition(SelectionPosition sp) { - Point pt = LocationFromPosition(sp); - return static_cast(pt.x) - vs.textStart + xOffset; -} - -SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace) { - RefreshStyleData(); - AutoSurface surface(this); - - if (canReturnInvalid) { - PRectangle rcClient = GetTextRectangle(); - // May be in scroll view coordinates so translate back to main view - Point ptOrigin = GetVisibleOriginInMain(); - rcClient.Move(-ptOrigin.x, -ptOrigin.y); - if (!rcClient.Contains(pt)) - return SelectionPosition(INVALID_POSITION); - if (pt.x < vs.textStart) - return SelectionPosition(INVALID_POSITION); - if (pt.y < 0) - return SelectionPosition(INVALID_POSITION); - } - pt = DocumentPointFromView(pt); - return view.SPositionFromLocation(surface, *this, pt, canReturnInvalid, charPosition, virtualSpace, vs); -} - -int Editor::PositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition) { - return SPositionFromLocation(pt, canReturnInvalid, charPosition, false).Position(); -} - -/** -* Find the document position corresponding to an x coordinate on a particular document line. -* Ensure is between whole characters when document is in multi-byte or UTF-8 mode. -* This method is used for rectangular selections and does not work on wrapped lines. -*/ -SelectionPosition Editor::SPositionFromLineX(int lineDoc, int x) { - RefreshStyleData(); - if (lineDoc >= pdoc->LinesTotal()) - return SelectionPosition(pdoc->Length()); - //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine); - AutoSurface surface(this); - return view.SPositionFromLineX(surface, *this, lineDoc, x, vs); -} - -int Editor::PositionFromLineX(int lineDoc, int x) { - return SPositionFromLineX(lineDoc, x).Position(); -} - -int Editor::LineFromLocation(Point pt) const { - return cs.DocFromDisplay(static_cast(pt.y) / vs.lineHeight + topLine); -} - -void Editor::SetTopLine(int topLineNew) { - if ((topLine != topLineNew) && (topLineNew >= 0)) { - topLine = topLineNew; - ContainerNeedsUpdate(SC_UPDATE_V_SCROLL); - } - posTopLine = pdoc->LineStart(cs.DocFromDisplay(topLine)); -} - -/** - * If painting then abandon the painting because a wider redraw is needed. - * @return true if calling code should stop drawing. - */ -bool Editor::AbandonPaint() { - if ((paintState == painting) && !paintingAllText) { - paintState = paintAbandoned; - } - return paintState == paintAbandoned; -} - -void Editor::RedrawRect(PRectangle rc) { - //Platform::DebugPrintf("Redraw %0d,%0d - %0d,%0d\n", rc.left, rc.top, rc.right, rc.bottom); - - // Clip the redraw rectangle into the client area - PRectangle rcClient = GetClientRectangle(); - if (rc.top < rcClient.top) - rc.top = rcClient.top; - if (rc.bottom > rcClient.bottom) - rc.bottom = rcClient.bottom; - if (rc.left < rcClient.left) - rc.left = rcClient.left; - if (rc.right > rcClient.right) - rc.right = rcClient.right; - - if ((rc.bottom > rc.top) && (rc.right > rc.left)) { - wMain.InvalidateRectangle(rc); - } -} - -void Editor::DiscardOverdraw() { - // Overridden on platforms that may draw outside visible area. -} - -void Editor::Redraw() { - //Platform::DebugPrintf("Redraw all\n"); - PRectangle rcClient = GetClientRectangle(); - wMain.InvalidateRectangle(rcClient); - if (wMargin.GetID()) - wMargin.InvalidateAll(); - //wMain.InvalidateAll(); -} - -void Editor::RedrawSelMargin(int line, bool allAfter) { - bool abandonDraw = false; - if (!wMargin.GetID()) // Margin in main window so may need to abandon and retry - abandonDraw = AbandonPaint(); - if (!abandonDraw) { - if (vs.maskInLine) { - Redraw(); - } else { - PRectangle rcSelMargin = GetClientRectangle(); - rcSelMargin.right = rcSelMargin.left + vs.fixedColumnWidth; - if (line != -1) { - PRectangle rcLine = RectangleFromRange(Range(pdoc->LineStart(line)), 0); - - // Inflate line rectangle if there are image markers with height larger than line height - if (vs.largestMarkerHeight > vs.lineHeight) { - int delta = (vs.largestMarkerHeight - vs.lineHeight + 1) / 2; - rcLine.top -= delta; - rcLine.bottom += delta; - if (rcLine.top < rcSelMargin.top) - rcLine.top = rcSelMargin.top; - if (rcLine.bottom > rcSelMargin.bottom) - rcLine.bottom = rcSelMargin.bottom; - } - - rcSelMargin.top = rcLine.top; - if (!allAfter) - rcSelMargin.bottom = rcLine.bottom; - if (rcSelMargin.Empty()) - return; - } - if (wMargin.GetID()) { - Point ptOrigin = GetVisibleOriginInMain(); - rcSelMargin.Move(-ptOrigin.x, -ptOrigin.y); - wMargin.InvalidateRectangle(rcSelMargin); - } else { - wMain.InvalidateRectangle(rcSelMargin); - } - } - } -} - -PRectangle Editor::RectangleFromRange(Range r, int overlap) { - const int minLine = cs.DisplayFromDoc(pdoc->LineFromPosition(r.First())); - const int maxLine = cs.DisplayLastFromDoc(pdoc->LineFromPosition(r.Last())); - const PRectangle rcClientDrawing = GetClientDrawingRectangle(); - PRectangle rc; - const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0; - rc.left = static_cast(vs.textStart - leftTextOverlap); - rc.top = static_cast((minLine - TopLineOfMain()) * vs.lineHeight - overlap); - if (rc.top < rcClientDrawing.top) - rc.top = rcClientDrawing.top; - // Extend to right of prepared area if any to prevent artifacts from caret line highlight - rc.right = rcClientDrawing.right; - rc.bottom = static_cast((maxLine - TopLineOfMain() + 1) * vs.lineHeight + overlap); - - return rc; -} - -void Editor::InvalidateRange(int start, int end) { - RedrawRect(RectangleFromRange(Range(start, end), view.LinesOverlap() ? vs.lineOverlap : 0)); -} - -int Editor::CurrentPosition() const { - return sel.MainCaret(); -} - -bool Editor::SelectionEmpty() const { - return sel.Empty(); -} - -SelectionPosition Editor::SelectionStart() { - return sel.RangeMain().Start(); -} - -SelectionPosition Editor::SelectionEnd() { - return sel.RangeMain().End(); -} - -void Editor::SetRectangularRange() { - if (sel.IsRectangular()) { - int xAnchor = XFromPosition(sel.Rectangular().anchor); - int xCaret = XFromPosition(sel.Rectangular().caret); - if (sel.selType == Selection::selThin) { - xCaret = xAnchor; - } - int lineAnchorRect = pdoc->LineFromPosition(sel.Rectangular().anchor.Position()); - int lineCaret = pdoc->LineFromPosition(sel.Rectangular().caret.Position()); - int increment = (lineCaret > lineAnchorRect) ? 1 : -1; - for (int line=lineAnchorRect; line != lineCaret+increment; line += increment) { - SelectionRange range(SPositionFromLineX(line, xCaret), SPositionFromLineX(line, xAnchor)); - if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) == 0) - range.ClearVirtualSpace(); - if (line == lineAnchorRect) - sel.SetSelection(range); - else - sel.AddSelectionWithoutTrim(range); - } - } -} - -void Editor::ThinRectangularRange() { - if (sel.IsRectangular()) { - sel.selType = Selection::selThin; - if (sel.Rectangular().caret < sel.Rectangular().anchor) { - sel.Rectangular() = SelectionRange(sel.Range(sel.Count()-1).caret, sel.Range(0).anchor); - } else { - sel.Rectangular() = SelectionRange(sel.Range(sel.Count()-1).anchor, sel.Range(0).caret); - } - SetRectangularRange(); - } -} - -void Editor::InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection) { - if (sel.Count() > 1 || !(sel.RangeMain().anchor == newMain.anchor) || sel.IsRectangular()) { - invalidateWholeSelection = true; - } - int firstAffected = Platform::Minimum(sel.RangeMain().Start().Position(), newMain.Start().Position()); - // +1 for lastAffected ensures caret repainted - int lastAffected = Platform::Maximum(newMain.caret.Position()+1, newMain.anchor.Position()); - lastAffected = Platform::Maximum(lastAffected, sel.RangeMain().End().Position()); - if (invalidateWholeSelection) { - for (size_t r=0; rLineFromPosition(currentPos_.Position()); - /* For Line selection - ensure the anchor and caret are always - at the beginning and end of the region lines. */ - if (sel.selType == Selection::selLines) { - if (currentPos_ > anchor_) { - anchor_ = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(anchor_.Position()))); - currentPos_ = SelectionPosition(pdoc->LineEnd(pdoc->LineFromPosition(currentPos_.Position()))); - } else { - currentPos_ = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(currentPos_.Position()))); - anchor_ = SelectionPosition(pdoc->LineEnd(pdoc->LineFromPosition(anchor_.Position()))); - } - } - SelectionRange rangeNew(currentPos_, anchor_); - if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) { - InvalidateSelection(rangeNew); - } - sel.RangeMain() = rangeNew; - SetRectangularRange(); - ClaimSelection(); - SetHoverIndicatorPosition(sel.MainCaret()); - - if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) { - RedrawSelMargin(); - } - QueueIdleWork(WorkNeeded::workUpdateUI); -} - -void Editor::SetSelection(int currentPos_, int anchor_) { - SetSelection(SelectionPosition(currentPos_), SelectionPosition(anchor_)); -} - -// Just move the caret on the main selection -void Editor::SetSelection(SelectionPosition currentPos_) { - currentPos_ = ClampPositionIntoDocument(currentPos_); - int currentLine = pdoc->LineFromPosition(currentPos_.Position()); - if (sel.Count() > 1 || !(sel.RangeMain().caret == currentPos_)) { - InvalidateSelection(SelectionRange(currentPos_)); - } - if (sel.IsRectangular()) { - sel.Rectangular() = - SelectionRange(SelectionPosition(currentPos_), sel.Rectangular().anchor); - SetRectangularRange(); - } else { - sel.RangeMain() = - SelectionRange(SelectionPosition(currentPos_), sel.RangeMain().anchor); - } - ClaimSelection(); - SetHoverIndicatorPosition(sel.MainCaret()); - - if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) { - RedrawSelMargin(); - } - QueueIdleWork(WorkNeeded::workUpdateUI); -} - -void Editor::SetSelection(int currentPos_) { - SetSelection(SelectionPosition(currentPos_)); -} - -void Editor::SetEmptySelection(SelectionPosition currentPos_) { - int currentLine = pdoc->LineFromPosition(currentPos_.Position()); - SelectionRange rangeNew(ClampPositionIntoDocument(currentPos_)); - if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) { - InvalidateSelection(rangeNew); - } - sel.Clear(); - sel.RangeMain() = rangeNew; - SetRectangularRange(); - ClaimSelection(); - SetHoverIndicatorPosition(sel.MainCaret()); - - if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) { - RedrawSelMargin(); - } - QueueIdleWork(WorkNeeded::workUpdateUI); -} - -void Editor::SetEmptySelection(int currentPos_) { - SetEmptySelection(SelectionPosition(currentPos_)); -} - -bool Editor::RangeContainsProtected(int start, int end) const { - if (vs.ProtectionActive()) { - if (start > end) { - int t = start; - start = end; - end = t; - } - for (int pos = start; pos < end; pos++) { - if (vs.styles[pdoc->StyleAt(pos)].IsProtected()) - return true; - } - } - return false; -} - -bool Editor::SelectionContainsProtected() { - for (size_t r=0; rMovePositionOutsideChar(pos.Position(), moveDir, checkLineEnd); - if (posMoved != pos.Position()) - pos.SetPosition(posMoved); - if (vs.ProtectionActive()) { - if (moveDir > 0) { - if ((pos.Position() > 0) && vs.styles[pdoc->StyleAt(pos.Position() - 1)].IsProtected()) { - while ((pos.Position() < pdoc->Length()) && - (vs.styles[pdoc->StyleAt(pos.Position())].IsProtected())) - pos.Add(1); - } - } else if (moveDir < 0) { - if (vs.styles[pdoc->StyleAt(pos.Position())].IsProtected()) { - while ((pos.Position() > 0) && - (vs.styles[pdoc->StyleAt(pos.Position() - 1)].IsProtected())) - pos.Add(-1); - } - } - } - return pos; -} - -int Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, bool ensureVisible) { - bool simpleCaret = (sel.Count() == 1) && sel.Empty(); - SelectionPosition spCaret = sel.Last(); - - int delta = newPos.Position() - sel.MainCaret(); - newPos = ClampPositionIntoDocument(newPos); - newPos = MovePositionOutsideChar(newPos, delta); - if (!multipleSelection && sel.IsRectangular() && (selt == Selection::selStream)) { - // Can't turn into multiple selection so clear additional selections - InvalidateSelection(SelectionRange(newPos), true); - SelectionRange rangeMain = sel.RangeMain(); - sel.SetSelection(rangeMain); - } - if (!sel.IsRectangular() && (selt == Selection::selRectangle)) { - // Switching to rectangular - InvalidateSelection(sel.RangeMain(), false); - SelectionRange rangeMain = sel.RangeMain(); - sel.Clear(); - sel.Rectangular() = rangeMain; - } - if (selt != Selection::noSel) { - sel.selType = selt; - } - if (selt != Selection::noSel || sel.MoveExtends()) { - SetSelection(newPos); - } else { - SetEmptySelection(newPos); - } - ShowCaretAtCurrentPosition(); - - int currentLine = pdoc->LineFromPosition(newPos.Position()); - if (ensureVisible) { - // In case in need of wrapping to ensure DisplayFromDoc works. - if (currentLine >= wrapPending.start) - WrapLines(wsAll); - XYScrollPosition newXY = XYScrollToMakeVisible( - SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret), xysDefault); - if (simpleCaret && (newXY.xOffset == xOffset)) { - // simple vertical scroll then invalidate - ScrollTo(newXY.topLine); - InvalidateSelection(SelectionRange(spCaret), true); - } else { - SetXYScroll(newXY); - } - } - - if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) { - RedrawSelMargin(); - } - return 0; -} - -int Editor::MovePositionTo(int newPos, Selection::selTypes selt, bool ensureVisible) { - return MovePositionTo(SelectionPosition(newPos), selt, ensureVisible); -} - -SelectionPosition Editor::MovePositionSoVisible(SelectionPosition pos, int moveDir) { - pos = ClampPositionIntoDocument(pos); - pos = MovePositionOutsideChar(pos, moveDir); - int lineDoc = pdoc->LineFromPosition(pos.Position()); - if (cs.GetVisible(lineDoc)) { - return pos; - } else { - int lineDisplay = cs.DisplayFromDoc(lineDoc); - if (moveDir > 0) { - // lineDisplay is already line before fold as lines in fold use display line of line after fold - lineDisplay = Platform::Clamp(lineDisplay, 0, cs.LinesDisplayed()); - return SelectionPosition(pdoc->LineStart(cs.DocFromDisplay(lineDisplay))); - } else { - lineDisplay = Platform::Clamp(lineDisplay - 1, 0, cs.LinesDisplayed()); - return SelectionPosition(pdoc->LineEnd(cs.DocFromDisplay(lineDisplay))); - } - } -} - -SelectionPosition Editor::MovePositionSoVisible(int pos, int moveDir) { - return MovePositionSoVisible(SelectionPosition(pos), moveDir); -} - -Point Editor::PointMainCaret() { - return LocationFromPosition(sel.Range(sel.Main()).caret); -} - -/** - * Choose the x position that the caret will try to stick to - * as it moves up and down. - */ -void Editor::SetLastXChosen() { - Point pt = PointMainCaret(); - lastXChosen = static_cast(pt.x) + xOffset; -} - -void Editor::ScrollTo(int line, bool moveThumb) { - int topLineNew = Platform::Clamp(line, 0, MaxScrollPos()); - if (topLineNew != topLine) { - // Try to optimise small scrolls -#ifndef UNDER_CE - int linesToMove = topLine - topLineNew; - bool performBlit = (abs(linesToMove) <= 10) && (paintState == notPainting); - willRedrawAll = !performBlit; -#endif - SetTopLine(topLineNew); - // Optimize by styling the view as this will invalidate any needed area - // which could abort the initial paint if discovered later. - StyleToPositionInView(PositionAfterArea(GetClientRectangle())); -#ifndef UNDER_CE - // Perform redraw rather than scroll if many lines would be redrawn anyway. - if (performBlit) { - ScrollText(linesToMove); - } else { - Redraw(); - } - willRedrawAll = false; -#else - Redraw(); -#endif - if (moveThumb) { - SetVerticalScrollPos(); - } - } -} - -void Editor::ScrollText(int /* linesToMove */) { - //Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove); - Redraw(); -} - -void Editor::HorizontalScrollTo(int xPos) { - //Platform::DebugPrintf("HorizontalScroll %d\n", xPos); - if (xPos < 0) - xPos = 0; - if (!Wrapping() && (xOffset != xPos)) { - xOffset = xPos; - ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); - SetHorizontalScrollPos(); - RedrawRect(GetClientRectangle()); - } -} - -void Editor::VerticalCentreCaret() { - int lineDoc = pdoc->LineFromPosition(sel.IsRectangular() ? sel.Rectangular().caret.Position() : sel.MainCaret()); - int lineDisplay = cs.DisplayFromDoc(lineDoc); - int newTop = lineDisplay - (LinesOnScreen() / 2); - if (topLine != newTop) { - SetTopLine(newTop > 0 ? newTop : 0); - RedrawRect(GetClientRectangle()); - } -} - -// Avoid 64 bit compiler warnings. -// Scintilla does not support text buffers larger than 2**31 -static int istrlen(const char *s) { - return static_cast(s ? strlen(s) : 0); -} - -void Editor::MoveSelectedLines(int lineDelta) { - - // if selection doesn't start at the beginning of the line, set the new start - int selectionStart = SelectionStart().Position(); - int startLine = pdoc->LineFromPosition(selectionStart); - int beginningOfStartLine = pdoc->LineStart(startLine); - selectionStart = beginningOfStartLine; - - // if selection doesn't end at the beginning of a line greater than that of the start, - // then set it at the beginning of the next one - int selectionEnd = SelectionEnd().Position(); - int endLine = pdoc->LineFromPosition(selectionEnd); - int beginningOfEndLine = pdoc->LineStart(endLine); - bool appendEol = false; - if (selectionEnd > beginningOfEndLine - || selectionStart == selectionEnd) { - selectionEnd = pdoc->LineStart(endLine + 1); - appendEol = (selectionEnd == pdoc->Length() && pdoc->LineFromPosition(selectionEnd) == endLine); - } - - // if there's nowhere for the selection to move - // (i.e. at the beginning going up or at the end going down), - // stop it right there! - if ((selectionStart == 0 && lineDelta < 0) - || (selectionEnd == pdoc->Length() && lineDelta > 0) - || selectionStart == selectionEnd) { - return; - } - - UndoGroup ug(pdoc); - - if (lineDelta > 0 && selectionEnd == pdoc->LineStart(pdoc->LinesTotal() - 1)) { - SetSelection(pdoc->MovePositionOutsideChar(selectionEnd - 1, -1), selectionEnd); - ClearSelection(); - selectionEnd = CurrentPosition(); - } - SetSelection(selectionStart, selectionEnd); - - SelectionText selectedText; - CopySelectionRange(&selectedText); - - int selectionLength = SelectionRange(selectionStart, selectionEnd).Length(); - Point currentLocation = LocationFromPosition(CurrentPosition()); - int currentLine = LineFromLocation(currentLocation); - - if (appendEol) - SetSelection(pdoc->MovePositionOutsideChar(selectionStart - 1, -1), selectionEnd); - ClearSelection(); - - const char *eol = StringFromEOLMode(pdoc->eolMode); - if (currentLine + lineDelta >= pdoc->LinesTotal()) - pdoc->InsertString(pdoc->Length(), eol, istrlen(eol)); - GoToLine(currentLine + lineDelta); - - selectionLength = pdoc->InsertString(CurrentPosition(), selectedText.Data(), selectionLength); - if (appendEol) { - const int lengthInserted = pdoc->InsertString(CurrentPosition() + selectionLength, eol, istrlen(eol)); - selectionLength += lengthInserted; - } - SetSelection(CurrentPosition(), CurrentPosition() + selectionLength); -} - -void Editor::MoveSelectedLinesUp() { - MoveSelectedLines(-1); -} - -void Editor::MoveSelectedLinesDown() { - MoveSelectedLines(1); -} - -void Editor::MoveCaretInsideView(bool ensureVisible) { - PRectangle rcClient = GetTextRectangle(); - Point pt = PointMainCaret(); - if (pt.y < rcClient.top) { - MovePositionTo(SPositionFromLocation( - Point::FromInts(lastXChosen - xOffset, static_cast(rcClient.top)), - false, false, UserVirtualSpace()), - Selection::noSel, ensureVisible); - } else if ((pt.y + vs.lineHeight - 1) > rcClient.bottom) { - int yOfLastLineFullyDisplayed = static_cast(rcClient.top) + (LinesOnScreen() - 1) * vs.lineHeight; - MovePositionTo(SPositionFromLocation( - Point::FromInts(lastXChosen - xOffset, static_cast(rcClient.top) + yOfLastLineFullyDisplayed), - false, false, UserVirtualSpace()), - Selection::noSel, ensureVisible); - } -} - -int Editor::DisplayFromPosition(int pos) { - AutoSurface surface(this); - return view.DisplayFromPosition(surface, *this, pos, vs); -} - -/** - * Ensure the caret is reasonably visible in context. - * -Caret policy in SciTE - -If slop is set, we can define a slop value. -This value defines an unwanted zone (UZ) where the caret is... unwanted. -This zone is defined as a number of pixels near the vertical margins, -and as a number of lines near the horizontal margins. -By keeping the caret away from the edges, it is seen within its context, -so it is likely that the identifier that the caret is on can be completely seen, -and that the current line is seen with some of the lines following it which are -often dependent on that line. - -If strict is set, the policy is enforced... strictly. -The caret is centred on the display if slop is not set, -and cannot go in the UZ if slop is set. - -If jumps is set, the display is moved more energetically -so the caret can move in the same direction longer before the policy is applied again. -'3UZ' notation is used to indicate three time the size of the UZ as a distance to the margin. - -If even is not set, instead of having symmetrical UZs, -the left and bottom UZs are extended up to right and top UZs respectively. -This way, we favour the displaying of useful information: the beginning of lines, -where most code reside, and the lines after the caret, eg. the body of a function. - - | | | | | -slop | strict | jumps | even | Caret can go to the margin | When reaching limit (caret going out of - | | | | | visibility or going into the UZ) display is... ------+--------+-------+------+--------------------------------------------+-------------------------------------------------------------- - 0 | 0 | 0 | 0 | Yes | moved to put caret on top/on right - 0 | 0 | 0 | 1 | Yes | moved by one position - 0 | 0 | 1 | 0 | Yes | moved to put caret on top/on right - 0 | 0 | 1 | 1 | Yes | centred on the caret - 0 | 1 | - | 0 | Caret is always on top/on right of display | - - 0 | 1 | - | 1 | No, caret is always centred | - - 1 | 0 | 0 | 0 | Yes | moved to put caret out of the asymmetrical UZ - 1 | 0 | 0 | 1 | Yes | moved to put caret out of the UZ - 1 | 0 | 1 | 0 | Yes | moved to put caret at 3UZ of the top or right margin - 1 | 0 | 1 | 1 | Yes | moved to put caret at 3UZ of the margin - 1 | 1 | - | 0 | Caret is always at UZ of top/right margin | - - 1 | 1 | 0 | 1 | No, kept out of UZ | moved by one position - 1 | 1 | 1 | 1 | No, kept out of UZ | moved to put caret at 3UZ of the margin -*/ - -Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange &range, const XYScrollOptions options) { - PRectangle rcClient = GetTextRectangle(); - Point pt = LocationFromPosition(range.caret); - Point ptAnchor = LocationFromPosition(range.anchor); - const Point ptOrigin = GetVisibleOriginInMain(); - pt.x += ptOrigin.x; - pt.y += ptOrigin.y; - ptAnchor.x += ptOrigin.x; - ptAnchor.y += ptOrigin.y; - const Point ptBottomCaret(pt.x, pt.y + vs.lineHeight - 1); - - XYScrollPosition newXY(xOffset, topLine); - if (rcClient.Empty()) { - return newXY; - } - - // Vertical positioning - if ((options & xysVertical) && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) { - const int lineCaret = DisplayFromPosition(range.caret.Position()); - const int linesOnScreen = LinesOnScreen(); - const int halfScreen = Platform::Maximum(linesOnScreen - 1, 2) / 2; - const bool bSlop = (caretYPolicy & CARET_SLOP) != 0; - const bool bStrict = (caretYPolicy & CARET_STRICT) != 0; - const bool bJump = (caretYPolicy & CARET_JUMPS) != 0; - const bool bEven = (caretYPolicy & CARET_EVEN) != 0; - - // It should be possible to scroll the window to show the caret, - // but this fails to remove the caret on GTK+ - if (bSlop) { // A margin is defined - int yMoveT, yMoveB; - if (bStrict) { - int yMarginT, yMarginB; - if (!(options & xysUseMargin)) { - // In drag mode, avoid moves - // otherwise, a double click will select several lines. - yMarginT = yMarginB = 0; - } else { - // yMarginT must equal to caretYSlop, with a minimum of 1 and - // a maximum of slightly less than half the heigth of the text area. - yMarginT = Platform::Clamp(caretYSlop, 1, halfScreen); - if (bEven) { - yMarginB = yMarginT; - } else { - yMarginB = linesOnScreen - yMarginT - 1; - } - } - yMoveT = yMarginT; - if (bEven) { - if (bJump) { - yMoveT = Platform::Clamp(caretYSlop * 3, 1, halfScreen); - } - yMoveB = yMoveT; - } else { - yMoveB = linesOnScreen - yMoveT - 1; - } - if (lineCaret < topLine + yMarginT) { - // Caret goes too high - newXY.topLine = lineCaret - yMoveT; - } else if (lineCaret > topLine + linesOnScreen - 1 - yMarginB) { - // Caret goes too low - newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB; - } - } else { // Not strict - yMoveT = bJump ? caretYSlop * 3 : caretYSlop; - yMoveT = Platform::Clamp(yMoveT, 1, halfScreen); - if (bEven) { - yMoveB = yMoveT; - } else { - yMoveB = linesOnScreen - yMoveT - 1; - } - if (lineCaret < topLine) { - // Caret goes too high - newXY.topLine = lineCaret - yMoveT; - } else if (lineCaret > topLine + linesOnScreen - 1) { - // Caret goes too low - newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB; - } - } - } else { // No slop - if (!bStrict && !bJump) { - // Minimal move - if (lineCaret < topLine) { - // Caret goes too high - newXY.topLine = lineCaret; - } else if (lineCaret > topLine + linesOnScreen - 1) { - // Caret goes too low - if (bEven) { - newXY.topLine = lineCaret - linesOnScreen + 1; - } else { - newXY.topLine = lineCaret; - } - } - } else { // Strict or going out of display - if (bEven) { - // Always center caret - newXY.topLine = lineCaret - halfScreen; - } else { - // Always put caret on top of display - newXY.topLine = lineCaret; - } - } - } - if (!(range.caret == range.anchor)) { - const int lineAnchor = DisplayFromPosition(range.anchor.Position()); - if (lineAnchor < lineCaret) { - // Shift up to show anchor or as much of range as possible - newXY.topLine = std::min(newXY.topLine, lineAnchor); - newXY.topLine = std::max(newXY.topLine, lineCaret - LinesOnScreen()); - } else { - // Shift down to show anchor or as much of range as possible - newXY.topLine = std::max(newXY.topLine, lineAnchor - LinesOnScreen()); - newXY.topLine = std::min(newXY.topLine, lineCaret); - } - } - newXY.topLine = Platform::Clamp(newXY.topLine, 0, MaxScrollPos()); - } - - // Horizontal positioning - if ((options & xysHorizontal) && !Wrapping()) { - const int halfScreen = Platform::Maximum(static_cast(rcClient.Width()) - 4, 4) / 2; - const bool bSlop = (caretXPolicy & CARET_SLOP) != 0; - const bool bStrict = (caretXPolicy & CARET_STRICT) != 0; - const bool bJump = (caretXPolicy & CARET_JUMPS) != 0; - const bool bEven = (caretXPolicy & CARET_EVEN) != 0; - - if (bSlop) { // A margin is defined - int xMoveL, xMoveR; - if (bStrict) { - int xMarginL, xMarginR; - if (!(options & xysUseMargin)) { - // In drag mode, avoid moves unless very near of the margin - // otherwise, a simple click will select text. - xMarginL = xMarginR = 2; - } else { - // xMargin must equal to caretXSlop, with a minimum of 2 and - // a maximum of slightly less than half the width of the text area. - xMarginR = Platform::Clamp(caretXSlop, 2, halfScreen); - if (bEven) { - xMarginL = xMarginR; - } else { - xMarginL = static_cast(rcClient.Width()) - xMarginR - 4; - } - } - if (bJump && bEven) { - // Jump is used only in even mode - xMoveL = xMoveR = Platform::Clamp(caretXSlop * 3, 1, halfScreen); - } else { - xMoveL = xMoveR = 0; // Not used, avoid a warning - } - if (pt.x < rcClient.left + xMarginL) { - // Caret is on the left of the display - if (bJump && bEven) { - newXY.xOffset -= xMoveL; - } else { - // Move just enough to allow to display the caret - newXY.xOffset -= static_cast((rcClient.left + xMarginL) - pt.x); - } - } else if (pt.x >= rcClient.right - xMarginR) { - // Caret is on the right of the display - if (bJump && bEven) { - newXY.xOffset += xMoveR; - } else { - // Move just enough to allow to display the caret - newXY.xOffset += static_cast(pt.x - (rcClient.right - xMarginR) + 1); - } - } - } else { // Not strict - xMoveR = bJump ? caretXSlop * 3 : caretXSlop; - xMoveR = Platform::Clamp(xMoveR, 1, halfScreen); - if (bEven) { - xMoveL = xMoveR; - } else { - xMoveL = static_cast(rcClient.Width()) - xMoveR - 4; - } - if (pt.x < rcClient.left) { - // Caret is on the left of the display - newXY.xOffset -= xMoveL; - } else if (pt.x >= rcClient.right) { - // Caret is on the right of the display - newXY.xOffset += xMoveR; - } - } - } else { // No slop - if (bStrict || - (bJump && (pt.x < rcClient.left || pt.x >= rcClient.right))) { - // Strict or going out of display - if (bEven) { - // Center caret - newXY.xOffset += static_cast(pt.x - rcClient.left - halfScreen); - } else { - // Put caret on right - newXY.xOffset += static_cast(pt.x - rcClient.right + 1); - } - } else { - // Move just enough to allow to display the caret - if (pt.x < rcClient.left) { - // Caret is on the left of the display - if (bEven) { - newXY.xOffset -= static_cast(rcClient.left - pt.x); - } else { - newXY.xOffset += static_cast(pt.x - rcClient.right) + 1; - } - } else if (pt.x >= rcClient.right) { - // Caret is on the right of the display - newXY.xOffset += static_cast(pt.x - rcClient.right) + 1; - } - } - } - // In case of a jump (find result) largely out of display, adjust the offset to display the caret - if (pt.x + xOffset < rcClient.left + newXY.xOffset) { - newXY.xOffset = static_cast(pt.x + xOffset - rcClient.left) - 2; - } else if (pt.x + xOffset >= rcClient.right + newXY.xOffset) { - newXY.xOffset = static_cast(pt.x + xOffset - rcClient.right) + 2; - if ((vs.caretStyle == CARETSTYLE_BLOCK) || view.imeCaretBlockOverride) { - // Ensure we can see a good portion of the block caret - newXY.xOffset += static_cast(vs.aveCharWidth); - } - } - if (!(range.caret == range.anchor)) { - if (ptAnchor.x < pt.x) { - // Shift to left to show anchor or as much of range as possible - int maxOffset = static_cast(ptAnchor.x + xOffset - rcClient.left) - 1; - int minOffset = static_cast(pt.x + xOffset - rcClient.right) + 1; - newXY.xOffset = std::min(newXY.xOffset, maxOffset); - newXY.xOffset = std::max(newXY.xOffset, minOffset); - } else { - // Shift to right to show anchor or as much of range as possible - int minOffset = static_cast(ptAnchor.x + xOffset - rcClient.right) + 1; - int maxOffset = static_cast(pt.x + xOffset - rcClient.left) - 1; - newXY.xOffset = std::max(newXY.xOffset, minOffset); - newXY.xOffset = std::min(newXY.xOffset, maxOffset); - } - } - if (newXY.xOffset < 0) { - newXY.xOffset = 0; - } - } - - return newXY; -} - -void Editor::SetXYScroll(XYScrollPosition newXY) { - if ((newXY.topLine != topLine) || (newXY.xOffset != xOffset)) { - if (newXY.topLine != topLine) { - SetTopLine(newXY.topLine); - SetVerticalScrollPos(); - } - if (newXY.xOffset != xOffset) { - xOffset = newXY.xOffset; - ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); - if (newXY.xOffset > 0) { - PRectangle rcText = GetTextRectangle(); - if (horizontalScrollBarVisible && - rcText.Width() + xOffset > scrollWidth) { - scrollWidth = xOffset + static_cast(rcText.Width()); - SetScrollBars(); - } - } - SetHorizontalScrollPos(); - } - Redraw(); - UpdateSystemCaret(); - } -} - -void Editor::ScrollRange(SelectionRange range) { - SetXYScroll(XYScrollToMakeVisible(range, xysDefault)); -} - -void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { - SetXYScroll(XYScrollToMakeVisible(SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret), - static_cast((useMargin?xysUseMargin:0)|(vert?xysVertical:0)|(horiz?xysHorizontal:0)))); -} - -void Editor::ShowCaretAtCurrentPosition() { - if (hasFocus) { - caret.active = true; - caret.on = true; - if (FineTickerAvailable()) { - FineTickerCancel(tickCaret); - if (caret.period > 0) - FineTickerStart(tickCaret, caret.period, caret.period/10); - } else { - SetTicking(true); - } - } else { - caret.active = false; - caret.on = false; - if (FineTickerAvailable()) { - FineTickerCancel(tickCaret); - } - } - InvalidateCaret(); -} - -void Editor::DropCaret() { - caret.active = false; - if (FineTickerAvailable()) { - FineTickerCancel(tickCaret); - } - InvalidateCaret(); -} - -void Editor::CaretSetPeriod(int period) { - if (caret.period != period) { - caret.period = period; - caret.on = true; - if (FineTickerAvailable()) { - FineTickerCancel(tickCaret); - if ((caret.active) && (caret.period > 0)) - FineTickerStart(tickCaret, caret.period, caret.period/10); - } - InvalidateCaret(); - } -} - -void Editor::InvalidateCaret() { - if (posDrag.IsValid()) { - InvalidateRange(posDrag.Position(), posDrag.Position() + 1); - } else { - for (size_t r=0; rlines; - } - return cs.SetHeight(lineToWrap, linesWrapped + - (vs.annotationVisible ? pdoc->AnnotationLines(lineToWrap) : 0)); -} - -// Perform wrapping for a subset of the lines needing wrapping. -// wsAll: wrap all lines which need wrapping in this single call -// wsVisible: wrap currently visible lines -// wsIdle: wrap one page + 100 lines -// Return true if wrapping occurred. -bool Editor::WrapLines(enum wrapScope ws) { - int goodTopLine = topLine; - bool wrapOccurred = false; - if (!Wrapping()) { - if (wrapWidth != LineLayout::wrapWidthInfinite) { - wrapWidth = LineLayout::wrapWidthInfinite; - for (int lineDoc = 0; lineDoc < pdoc->LinesTotal(); lineDoc++) { - cs.SetHeight(lineDoc, 1 + - (vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0)); - } - wrapOccurred = true; - } - wrapPending.Reset(); - - } else if (wrapPending.NeedsWrap()) { - wrapPending.start = std::min(wrapPending.start, pdoc->LinesTotal()); - if (!SetIdle(true)) { - // Idle processing not supported so full wrap required. - ws = wsAll; - } - // Decide where to start wrapping - int lineToWrap = wrapPending.start; - int lineToWrapEnd = std::min(wrapPending.end, pdoc->LinesTotal()); - const int lineDocTop = cs.DocFromDisplay(topLine); - const int subLineTop = topLine - cs.DisplayFromDoc(lineDocTop); - if (ws == wsVisible) { - lineToWrap = Platform::Clamp(lineDocTop-5, wrapPending.start, pdoc->LinesTotal()); - // Priority wrap to just after visible area. - // Since wrapping could reduce display lines, treat each - // as taking only one display line. - lineToWrapEnd = lineDocTop; - int lines = LinesOnScreen() + 1; - while ((lineToWrapEnd < cs.LinesInDoc()) && (lines>0)) { - if (cs.GetVisible(lineToWrapEnd)) - lines--; - lineToWrapEnd++; - } - // .. and if the paint window is outside pending wraps - if ((lineToWrap > wrapPending.end) || (lineToWrapEnd < wrapPending.start)) { - // Currently visible text does not need wrapping - return false; - } - } else if (ws == wsIdle) { - lineToWrapEnd = lineToWrap + LinesOnScreen() + 100; - } - const int lineEndNeedWrap = std::min(wrapPending.end, pdoc->LinesTotal()); - lineToWrapEnd = std::min(lineToWrapEnd, lineEndNeedWrap); - - // Ensure all lines being wrapped are styled. - pdoc->EnsureStyledTo(pdoc->LineStart(lineToWrapEnd)); - - if (lineToWrap < lineToWrapEnd) { - - PRectangle rcTextArea = GetClientRectangle(); - rcTextArea.left = static_cast(vs.textStart); - rcTextArea.right -= vs.rightMarginWidth; - wrapWidth = static_cast(rcTextArea.Width()); - RefreshStyleData(); - AutoSurface surface(this); - if (surface) { -//Platform::DebugPrintf("Wraplines: scope=%0d need=%0d..%0d perform=%0d..%0d\n", ws, wrapPending.start, wrapPending.end, lineToWrap, lineToWrapEnd); - - while (lineToWrap < lineToWrapEnd) { - if (WrapOneLine(surface, lineToWrap)) { - wrapOccurred = true; - } - wrapPending.Wrapped(lineToWrap); - lineToWrap++; - } - - goodTopLine = cs.DisplayFromDoc(lineDocTop) + std::min(subLineTop, cs.GetHeight(lineDocTop)-1); - } - } - - // If wrapping is done, bring it to resting position - if (wrapPending.start >= lineEndNeedWrap) { - wrapPending.Reset(); - } - } - - if (wrapOccurred) { - SetScrollBars(); - SetTopLine(Platform::Clamp(goodTopLine, 0, MaxScrollPos())); - SetVerticalScrollPos(); - } - - return wrapOccurred; -} - -void Editor::LinesJoin() { - if (!RangeContainsProtected(targetStart, targetEnd)) { - UndoGroup ug(pdoc); - bool prevNonWS = true; - for (int pos = targetStart; pos < targetEnd; pos++) { - if (pdoc->IsPositionInLineEnd(pos)) { - targetEnd -= pdoc->LenChar(pos); - pdoc->DelChar(pos); - if (prevNonWS) { - // Ensure at least one space separating previous lines - const int lengthInserted = pdoc->InsertString(pos, " ", 1); - targetEnd += lengthInserted; - } - } else { - prevNonWS = pdoc->CharAt(pos) != ' '; - } - } - } -} - -const char *Editor::StringFromEOLMode(int eolMode) { - if (eolMode == SC_EOL_CRLF) { - return "\r\n"; - } else if (eolMode == SC_EOL_CR) { - return "\r"; - } else { - return "\n"; - } -} - -void Editor::LinesSplit(int pixelWidth) { - if (!RangeContainsProtected(targetStart, targetEnd)) { - if (pixelWidth == 0) { - PRectangle rcText = GetTextRectangle(); - pixelWidth = static_cast(rcText.Width()); - } - int lineStart = pdoc->LineFromPosition(targetStart); - int lineEnd = pdoc->LineFromPosition(targetEnd); - const char *eol = StringFromEOLMode(pdoc->eolMode); - UndoGroup ug(pdoc); - for (int line = lineStart; line <= lineEnd; line++) { - AutoSurface surface(this); - AutoLineLayout ll(view.llc, view.RetrieveLineLayout(line, *this)); - if (surface && ll) { - unsigned int posLineStart = pdoc->LineStart(line); - view.LayoutLine(*this, line, surface, vs, ll, pixelWidth); - int lengthInsertedTotal = 0; - for (int subLine = 1; subLine < ll->lines; subLine++) { - const int lengthInserted = pdoc->InsertString( - static_cast(posLineStart + lengthInsertedTotal + - ll->LineStart(subLine)), - eol, istrlen(eol)); - targetEnd += lengthInserted; - lengthInsertedTotal += lengthInserted; - } - } - lineEnd = pdoc->LineFromPosition(targetEnd); - } - } -} - -void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { - if (vs.fixedColumnWidth == 0) - return; - - AllocateGraphics(); - RefreshStyleData(); - RefreshPixMaps(surfWindow); - - // On GTK+ with Ubuntu overlay scroll bars, the surface may have been finished - // at this point. The Initialised call checks for this case and sets the status - // to be bad which avoids crashes in following calls. - if (!surfWindow->Initialised()) { - return; - } - - PRectangle rcMargin = GetClientRectangle(); - Point ptOrigin = GetVisibleOriginInMain(); - rcMargin.Move(0, -ptOrigin.y); - rcMargin.left = 0; - rcMargin.right = static_cast(vs.fixedColumnWidth); - - if (!rc.Intersects(rcMargin)) - return; - - Surface *surface; - if (view.bufferedDraw) { - surface = marginView.pixmapSelMargin; - } else { - surface = surfWindow; - } - - // Clip vertically to paint area to avoid drawing line numbers - if (rcMargin.bottom > rc.bottom) - rcMargin.bottom = rc.bottom; - if (rcMargin.top < rc.top) - rcMargin.top = rc.top; - - marginView.PaintMargin(surface, topLine, rc, rcMargin, *this, vs); - - if (view.bufferedDraw) { - surfWindow->Copy(rcMargin, Point(rcMargin.left, rcMargin.top), *marginView.pixmapSelMargin); - } -} - -void Editor::RefreshPixMaps(Surface *surfaceWindow) { - view.RefreshPixMaps(surfaceWindow, wMain.GetID(), vs); - marginView.RefreshPixMaps(surfaceWindow, wMain.GetID(), vs); - if (view.bufferedDraw) { - PRectangle rcClient = GetClientRectangle(); - if (!view.pixmapLine->Initialised()) { - - view.pixmapLine->InitPixMap(static_cast(rcClient.Width()), vs.lineHeight, - surfaceWindow, wMain.GetID()); - } - if (!marginView.pixmapSelMargin->Initialised()) { - marginView.pixmapSelMargin->InitPixMap(vs.fixedColumnWidth, - static_cast(rcClient.Height()), surfaceWindow, wMain.GetID()); - } - } -} - -void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { - //Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n", - // paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom); - AllocateGraphics(); - - RefreshStyleData(); - if (paintState == paintAbandoned) - return; // Scroll bars may have changed so need redraw - RefreshPixMaps(surfaceWindow); - - paintAbandonedByStyling = false; - - StyleToPositionInView(PositionAfterArea(rcArea)); - - PRectangle rcClient = GetClientRectangle(); - //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d) %d\n", - // rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); - - if (NotifyUpdateUI()) { - RefreshStyleData(); - RefreshPixMaps(surfaceWindow); - } - - // Wrap the visible lines if needed. - if (WrapLines(wsVisible)) { - // The wrapping process has changed the height of some lines so - // abandon this paint for a complete repaint. - if (AbandonPaint()) { - return; - } - RefreshPixMaps(surfaceWindow); // In case pixmaps invalidated by scrollbar change - } - PLATFORM_ASSERT(marginView.pixmapSelPattern->Initialised()); - - if (!view.bufferedDraw) - surfaceWindow->SetClip(rcArea); - - if (paintState != paintAbandoned) { - if (vs.marginInside) { - PaintSelMargin(surfaceWindow, rcArea); - PRectangle rcRightMargin = rcClient; - rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth; - if (rcArea.Intersects(rcRightMargin)) { - surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back); - } - } else { // Else separate view so separate paint event but leftMargin included to allow overlap - PRectangle rcLeftMargin = rcArea; - rcLeftMargin.left = 0; - rcLeftMargin.right = rcLeftMargin.left + vs.leftMarginWidth; - if (rcArea.Intersects(rcLeftMargin)) { - surfaceWindow->FillRectangle(rcLeftMargin, vs.styles[STYLE_DEFAULT].back); - } - } - } - - if (paintState == paintAbandoned) { - // Either styling or NotifyUpdateUI noticed that painting is needed - // outside the current painting rectangle - //Platform::DebugPrintf("Abandoning paint\n"); - if (Wrapping()) { - if (paintAbandonedByStyling) { - // Styling has spilled over a line end, such as occurs by starting a multiline - // comment. The width of subsequent text may have changed, so rewrap. - NeedWrapping(cs.DocFromDisplay(topLine)); - } - } - return; - } - - view.PaintText(surfaceWindow, *this, rcArea, rcClient, vs); - - if (horizontalScrollBarVisible && trackLineWidth && (view.lineWidthMaxSeen > scrollWidth)) { - if (FineTickerAvailable()) { - scrollWidth = view.lineWidthMaxSeen; - if (!FineTickerRunning(tickWiden)) { - FineTickerStart(tickWiden, 50, 5); - } - } - } - - NotifyPainted(); -} - -// This is mostly copied from the Paint method but with some things omitted -// such as the margin markers, line numbers, selection and caret -// Should be merged back into a combined Draw method. -long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) { - if (!pfr) - return 0; - - AutoSurface surface(pfr->hdc, this, SC_TECHNOLOGY_DEFAULT); - if (!surface) - return 0; - AutoSurface surfaceMeasure(pfr->hdcTarget, this, SC_TECHNOLOGY_DEFAULT); - if (!surfaceMeasure) { - return 0; - } - return view.FormatRange(draw, pfr, surface, surfaceMeasure, *this, vs); -} - -int Editor::TextWidth(int style, const char *text) { - RefreshStyleData(); - AutoSurface surface(this); - if (surface) { - return static_cast(surface->WidthText(vs.styles[style].font, text, istrlen(text))); - } else { - return 1; - } -} - -// Empty method is overridden on GTK+ to show / hide scrollbars -void Editor::ReconfigureScrollBars() {} - -void Editor::SetScrollBars() { - RefreshStyleData(); - - int nMax = MaxScrollPos(); - int nPage = LinesOnScreen(); - bool modified = ModifyScrollBars(nMax + nPage - 1, nPage); - if (modified) { - DwellEnd(true); - } - - // TODO: ensure always showing as many lines as possible - // May not be, if, for example, window made larger - if (topLine > MaxScrollPos()) { - SetTopLine(Platform::Clamp(topLine, 0, MaxScrollPos())); - SetVerticalScrollPos(); - Redraw(); - } - if (modified) { - if (!AbandonPaint()) - Redraw(); - } - //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage); -} - -void Editor::ChangeSize() { - DropGraphics(false); - SetScrollBars(); - if (Wrapping()) { - PRectangle rcTextArea = GetClientRectangle(); - rcTextArea.left = static_cast(vs.textStart); - rcTextArea.right -= vs.rightMarginWidth; - if (wrapWidth != rcTextArea.Width()) { - NeedWrapping(); - Redraw(); - } - } -} - -int Editor::InsertSpace(int position, unsigned int spaces) { - if (spaces > 0) { - std::string spaceText(spaces, ' '); - const int lengthInserted = pdoc->InsertString(position, spaceText.c_str(), spaces); - position += lengthInserted; - } - return position; -} - -void Editor::AddChar(char ch) { - char s[2]; - s[0] = ch; - s[1] = '\0'; - AddCharUTF(s, 1); -} - -void Editor::FilterSelections() { - if (!additionalSelectionTyping && (sel.Count() > 1)) { - SelectionRange rangeOnly = sel.RangeMain(); - InvalidateSelection(rangeOnly, true); - sel.SetSelection(rangeOnly); - } -} - -static bool cmpSelPtrs(const SelectionRange *a, const SelectionRange *b) { - return *a < *b; -} - -// AddCharUTF inserts an array of bytes which may or may not be in UTF-8. -void Editor::AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS) { - FilterSelections(); - { - UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty() || inOverstrike); - - // Vector elements point into selection in order to change selection. - std::vector selPtrs; - for (size_t r = 0; r < sel.Count(); r++) { - selPtrs.push_back(&sel.Range(r)); - } - // Order selections by position in document. - std::sort(selPtrs.begin(), selPtrs.end(), cmpSelPtrs); - - // Loop in reverse to avoid disturbing positions of selections yet to be processed. - for (std::vector::reverse_iterator rit = selPtrs.rbegin(); - rit != selPtrs.rend(); ++rit) { - SelectionRange *currentSel = *rit; - if (!RangeContainsProtected(currentSel->Start().Position(), - currentSel->End().Position())) { - int positionInsert = currentSel->Start().Position(); - if (!currentSel->Empty()) { - if (currentSel->Length()) { - pdoc->DeleteChars(positionInsert, currentSel->Length()); - currentSel->ClearVirtualSpace(); - } else { - // Range is all virtual so collapse to start of virtual space - currentSel->MinimizeVirtualSpace(); - } - } else if (inOverstrike) { - if (positionInsert < pdoc->Length()) { - if (!pdoc->IsPositionInLineEnd(positionInsert)) { - pdoc->DelChar(positionInsert); - currentSel->ClearVirtualSpace(); - } - } - } - positionInsert = InsertSpace(positionInsert, currentSel->caret.VirtualSpace()); - const int lengthInserted = pdoc->InsertString(positionInsert, s, len); - if (lengthInserted > 0) { - currentSel->caret.SetPosition(positionInsert + lengthInserted); - currentSel->anchor.SetPosition(positionInsert + lengthInserted); - } - currentSel->ClearVirtualSpace(); - // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information - if (Wrapping()) { - AutoSurface surface(this); - if (surface) { - if (WrapOneLine(surface, pdoc->LineFromPosition(positionInsert))) { - SetScrollBars(); - SetVerticalScrollPos(); - Redraw(); - } - } - } - } - } - } - if (Wrapping()) { - SetScrollBars(); - } - ThinRectangularRange(); - // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information - EnsureCaretVisible(); - // Avoid blinking during rapid typing: - ShowCaretAtCurrentPosition(); - if ((caretSticky == SC_CARETSTICKY_OFF) || - ((caretSticky == SC_CARETSTICKY_WHITESPACE) && !IsAllSpacesOrTabs(s, len))) { - SetLastXChosen(); - } - - if (treatAsDBCS) { - NotifyChar((static_cast(s[0]) << 8) | - static_cast(s[1])); - } else if (len > 0) { - int byte = static_cast(s[0]); - if ((byte < 0xC0) || (1 == len)) { - // Handles UTF-8 characters between 0x01 and 0x7F and single byte - // characters when not in UTF-8 mode. - // Also treats \0 and naked trail bytes 0x80 to 0xBF as valid - // characters representing themselves. - } else { - unsigned int utf32[1] = { 0 }; - UTF32FromUTF8(s, len, utf32, ELEMENTS(utf32)); - byte = utf32[0]; - } - NotifyChar(byte); - } - - if (recordingMacro) { - NotifyMacroRecord(SCI_REPLACESEL, 0, reinterpret_cast(s)); - } -} - -void Editor::FillVirtualSpace() { - const bool tmpOverstrike = inOverstrike; - inOverstrike = false; // not allow to be deleted twice. - AddCharUTF("", 0); - inOverstrike = tmpOverstrike; -} - -void Editor::InsertPaste(const char *text, int len) { - if (multiPasteMode == SC_MULTIPASTE_ONCE) { - SelectionPosition selStart = sel.Start(); - selStart = SelectionPosition(InsertSpace(selStart.Position(), selStart.VirtualSpace())); - const int lengthInserted = pdoc->InsertString(selStart.Position(), text, len); - if (lengthInserted > 0) { - SetEmptySelection(selStart.Position() + lengthInserted); - } - } else { - // SC_MULTIPASTE_EACH - for (size_t r=0; rDeleteChars(positionInsert, sel.Range(r).Length()); - sel.Range(r).ClearVirtualSpace(); - } else { - // Range is all virtual so collapse to start of virtual space - sel.Range(r).MinimizeVirtualSpace(); - } - } - positionInsert = InsertSpace(positionInsert, sel.Range(r).caret.VirtualSpace()); - const int lengthInserted = pdoc->InsertString(positionInsert, text, len); - if (lengthInserted > 0) { - sel.Range(r).caret.SetPosition(positionInsert + lengthInserted); - sel.Range(r).anchor.SetPosition(positionInsert + lengthInserted); - } - sel.Range(r).ClearVirtualSpace(); - } - } - } -} - -void Editor::InsertPasteShape(const char *text, int len, PasteShape shape) { - std::string convertedText; - if (convertPastes) { - // Convert line endings of the paste into our local line-endings mode - convertedText = Document::TransformLineEnds(text, len, pdoc->eolMode); - len = static_cast(convertedText.length()); - text = convertedText.c_str(); - } - if (shape == pasteRectangular) { - PasteRectangular(sel.Start(), text, len); - } else { - if (shape == pasteLine) { - int insertPos = pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())); - int lengthInserted = pdoc->InsertString(insertPos, text, len); - // add the newline if necessary - if ((len > 0) && (text[len - 1] != '\n' && text[len - 1] != '\r')) { - const char *endline = StringFromEOLMode(pdoc->eolMode); - int length = static_cast(strlen(endline)); - lengthInserted += pdoc->InsertString(insertPos + lengthInserted, endline, length); - } - if (sel.MainCaret() == insertPos) { - SetEmptySelection(sel.MainCaret() + lengthInserted); - } - } else { - InsertPaste(text, len); - } - } -} - -void Editor::ClearSelection(bool retainMultipleSelections) { - if (!sel.IsRectangular() && !retainMultipleSelections) - FilterSelections(); - UndoGroup ug(pdoc); - for (size_t r=0; rDeleteChars(sel.Range(r).Start().Position(), - sel.Range(r).Length()); - sel.Range(r) = SelectionRange(sel.Range(r).Start()); - } - } - } - ThinRectangularRange(); - sel.RemoveDuplicates(); - ClaimSelection(); - SetHoverIndicatorPosition(sel.MainCaret()); -} - -void Editor::ClearAll() { - { - UndoGroup ug(pdoc); - if (0 != pdoc->Length()) { - pdoc->DeleteChars(0, pdoc->Length()); - } - if (!pdoc->IsReadOnly()) { - cs.Clear(); - pdoc->AnnotationClearAll(); - pdoc->MarginClearAll(); - } - } - - view.ClearAllTabstops(); - - sel.Clear(); - SetTopLine(0); - SetVerticalScrollPos(); - InvalidateStyleRedraw(); -} - -void Editor::ClearDocumentStyle() { - Decoration *deco = pdoc->decorations.root; - while (deco) { - // Save next in case deco deleted - Decoration *decoNext = deco->next; - if (deco->indicator < INDIC_CONTAINER) { - pdoc->decorations.SetCurrentIndicator(deco->indicator); - pdoc->DecorationFillRange(0, 0, pdoc->Length()); - } - deco = decoNext; - } - pdoc->StartStyling(0, '\377'); - pdoc->SetStyleFor(pdoc->Length(), 0); - cs.ShowAll(); - SetAnnotationHeights(0, pdoc->LinesTotal()); - pdoc->ClearLevels(); -} - -void Editor::CopyAllowLine() { - SelectionText selectedText; - CopySelectionRange(&selectedText, true); - CopyToClipboard(selectedText); -} - -void Editor::Cut() { - pdoc->CheckReadOnly(); - if (!pdoc->IsReadOnly() && !SelectionContainsProtected()) { - Copy(); - ClearSelection(); - } -} - -void Editor::PasteRectangular(SelectionPosition pos, const char *ptr, int len) { - if (pdoc->IsReadOnly() || SelectionContainsProtected()) { - return; - } - sel.Clear(); - sel.RangeMain() = SelectionRange(pos); - int line = pdoc->LineFromPosition(sel.MainCaret()); - UndoGroup ug(pdoc); - sel.RangeMain().caret = SelectionPosition( - InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace())); - int xInsert = XFromPosition(sel.RangeMain().caret); - bool prevCr = false; - while ((len > 0) && IsEOLChar(ptr[len-1])) - len--; - for (int i = 0; i < len; i++) { - if (IsEOLChar(ptr[i])) { - if ((ptr[i] == '\r') || (!prevCr)) - line++; - if (line >= pdoc->LinesTotal()) { - if (pdoc->eolMode != SC_EOL_LF) - pdoc->InsertString(pdoc->Length(), "\r", 1); - if (pdoc->eolMode != SC_EOL_CR) - pdoc->InsertString(pdoc->Length(), "\n", 1); - } - // Pad the end of lines with spaces if required - sel.RangeMain().caret.SetPosition(PositionFromLineX(line, xInsert)); - if ((XFromPosition(sel.MainCaret()) < xInsert) && (i + 1 < len)) { - while (XFromPosition(sel.MainCaret()) < xInsert) { - const int lengthInserted = pdoc->InsertString(sel.MainCaret(), " ", 1); - sel.RangeMain().caret.Add(lengthInserted); - } - } - prevCr = ptr[i] == '\r'; - } else { - const int lengthInserted = pdoc->InsertString(sel.MainCaret(), ptr + i, 1); - sel.RangeMain().caret.Add(lengthInserted); - prevCr = false; - } - } - SetEmptySelection(pos); -} - -bool Editor::CanPaste() { - return !pdoc->IsReadOnly() && !SelectionContainsProtected(); -} - -void Editor::Clear() { - // If multiple selections, don't delete EOLS - if (sel.Empty()) { - bool singleVirtual = false; - if ((sel.Count() == 1) && - !RangeContainsProtected(sel.MainCaret(), sel.MainCaret() + 1) && - sel.RangeMain().Start().VirtualSpace()) { - singleVirtual = true; - } - UndoGroup ug(pdoc, (sel.Count() > 1) || singleVirtual); - for (size_t r=0; rIsPositionInLineEnd(sel.Range(r).caret.Position())) { - pdoc->DelChar(sel.Range(r).caret.Position()); - sel.Range(r).ClearVirtualSpace(); - } // else multiple selection so don't eat line ends - } else { - sel.Range(r).ClearVirtualSpace(); - } - } - } else { - ClearSelection(); - } - sel.RemoveDuplicates(); - ShowCaretAtCurrentPosition(); // Avoid blinking -} - -void Editor::SelectAll() { - sel.Clear(); - SetSelection(0, pdoc->Length()); - Redraw(); -} - -void Editor::Undo() { - if (pdoc->CanUndo()) { - InvalidateCaret(); - int newPos = pdoc->Undo(); - if (newPos >= 0) - SetEmptySelection(newPos); - EnsureCaretVisible(); - } -} - -void Editor::Redo() { - if (pdoc->CanRedo()) { - int newPos = pdoc->Redo(); - if (newPos >= 0) - SetEmptySelection(newPos); - EnsureCaretVisible(); - } -} - -void Editor::DelCharBack(bool allowLineStartDeletion) { - RefreshStyleData(); - if (!sel.IsRectangular()) - FilterSelections(); - if (sel.IsRectangular()) - allowLineStartDeletion = false; - UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty()); - if (sel.Empty()) { - for (size_t r=0; rLineFromPosition(sel.Range(r).caret.Position()); - if (allowLineStartDeletion || (pdoc->LineStart(lineCurrentPos) != sel.Range(r).caret.Position())) { - if (pdoc->GetColumn(sel.Range(r).caret.Position()) <= pdoc->GetLineIndentation(lineCurrentPos) && - pdoc->GetColumn(sel.Range(r).caret.Position()) > 0 && pdoc->backspaceUnindents) { - UndoGroup ugInner(pdoc, !ug.Needed()); - int indentation = pdoc->GetLineIndentation(lineCurrentPos); - int indentationStep = pdoc->IndentSize(); - int indentationChange = indentation % indentationStep; - if (indentationChange == 0) - indentationChange = indentationStep; - const int posSelect = pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationChange); - // SetEmptySelection - sel.Range(r) = SelectionRange(posSelect); - } else { - pdoc->DelCharBack(sel.Range(r).caret.Position()); - } - } - } - } else { - sel.Range(r).ClearVirtualSpace(); - } - } - ThinRectangularRange(); - } else { - ClearSelection(); - } - sel.RemoveDuplicates(); - ContainerNeedsUpdate(SC_UPDATE_SELECTION); - // Avoid blinking during rapid typing: - ShowCaretAtCurrentPosition(); -} - -int Editor::ModifierFlags(bool shift, bool ctrl, bool alt, bool meta) { - return - (shift ? SCI_SHIFT : 0) | - (ctrl ? SCI_CTRL : 0) | - (alt ? SCI_ALT : 0) | - (meta ? SCI_META : 0); -} - -void Editor::NotifyFocus(bool focus) { - SCNotification scn = {}; - scn.nmhdr.code = focus ? SCN_FOCUSIN : SCN_FOCUSOUT; - NotifyParent(scn); -} - -void Editor::SetCtrlID(int identifier) { - ctrlID = identifier; -} - -void Editor::NotifyStyleToNeeded(int endStyleNeeded) { - SCNotification scn = {}; - scn.nmhdr.code = SCN_STYLENEEDED; - scn.position = endStyleNeeded; - NotifyParent(scn); -} - -void Editor::NotifyStyleNeeded(Document *, void *, int endStyleNeeded) { - NotifyStyleToNeeded(endStyleNeeded); -} - -void Editor::NotifyLexerChanged(Document *, void *) { -} - -void Editor::NotifyErrorOccurred(Document *, void *, int status) { - errorStatus = status; -} - -void Editor::NotifyChar(int ch) { - SCNotification scn = {}; - scn.nmhdr.code = SCN_CHARADDED; - scn.ch = ch; - NotifyParent(scn); -} - -void Editor::NotifySavePoint(bool isSavePoint) { - SCNotification scn = {}; - if (isSavePoint) { - scn.nmhdr.code = SCN_SAVEPOINTREACHED; - } else { - scn.nmhdr.code = SCN_SAVEPOINTLEFT; - } - NotifyParent(scn); -} - -void Editor::NotifyModifyAttempt() { - SCNotification scn = {}; - scn.nmhdr.code = SCN_MODIFYATTEMPTRO; - NotifyParent(scn); -} - -void Editor::NotifyDoubleClick(Point pt, int modifiers) { - SCNotification scn = {}; - scn.nmhdr.code = SCN_DOUBLECLICK; - scn.line = LineFromLocation(pt); - scn.position = PositionFromLocation(pt, true); - scn.modifiers = modifiers; - NotifyParent(scn); -} - -void Editor::NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt) { - NotifyDoubleClick(pt, ModifierFlags(shift, ctrl, alt)); -} - -void Editor::NotifyHotSpotDoubleClicked(int position, int modifiers) { - SCNotification scn = {}; - scn.nmhdr.code = SCN_HOTSPOTDOUBLECLICK; - scn.position = position; - scn.modifiers = modifiers; - NotifyParent(scn); -} - -void Editor::NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt) { - NotifyHotSpotDoubleClicked(position, ModifierFlags(shift, ctrl, alt)); -} - -void Editor::NotifyHotSpotClicked(int position, int modifiers) { - SCNotification scn = {}; - scn.nmhdr.code = SCN_HOTSPOTCLICK; - scn.position = position; - scn.modifiers = modifiers; - NotifyParent(scn); -} - -void Editor::NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt) { - NotifyHotSpotClicked(position, ModifierFlags(shift, ctrl, alt)); -} - -void Editor::NotifyHotSpotReleaseClick(int position, int modifiers) { - SCNotification scn = {}; - scn.nmhdr.code = SCN_HOTSPOTRELEASECLICK; - scn.position = position; - scn.modifiers = modifiers; - NotifyParent(scn); -} - -void Editor::NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool alt) { - NotifyHotSpotReleaseClick(position, ModifierFlags(shift, ctrl, alt)); -} - -bool Editor::NotifyUpdateUI() { - if (needUpdateUI) { - SCNotification scn = {}; - scn.nmhdr.code = SCN_UPDATEUI; - scn.updated = needUpdateUI; - NotifyParent(scn); - needUpdateUI = 0; - return true; - } - return false; -} - -void Editor::NotifyPainted() { - SCNotification scn = {}; - scn.nmhdr.code = SCN_PAINTED; - NotifyParent(scn); -} - -void Editor::NotifyIndicatorClick(bool click, int position, int modifiers) { - int mask = pdoc->decorations.AllOnFor(position); - if ((click && mask) || pdoc->decorations.clickNotified) { - SCNotification scn = {}; - pdoc->decorations.clickNotified = click; - scn.nmhdr.code = click ? SCN_INDICATORCLICK : SCN_INDICATORRELEASE; - scn.modifiers = modifiers; - scn.position = position; - NotifyParent(scn); - } -} - -void Editor::NotifyIndicatorClick(bool click, int position, bool shift, bool ctrl, bool alt) { - NotifyIndicatorClick(click, position, ModifierFlags(shift, ctrl, alt)); -} - -bool Editor::NotifyMarginClick(Point pt, int modifiers) { - int marginClicked = -1; - int x = vs.textStart - vs.fixedColumnWidth; - for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) { - if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width)) - marginClicked = margin; - x += vs.ms[margin].width; - } - if ((marginClicked >= 0) && vs.ms[marginClicked].sensitive) { - int position = pdoc->LineStart(LineFromLocation(pt)); - if ((vs.ms[marginClicked].mask & SC_MASK_FOLDERS) && (foldAutomatic & SC_AUTOMATICFOLD_CLICK)) { - const bool ctrl = (modifiers & SCI_CTRL) != 0; - const bool shift = (modifiers & SCI_SHIFT) != 0; - int lineClick = pdoc->LineFromPosition(position); - if (shift && ctrl) { - FoldAll(SC_FOLDACTION_TOGGLE); - } else { - int levelClick = pdoc->GetLevel(lineClick); - if (levelClick & SC_FOLDLEVELHEADERFLAG) { - if (shift) { - // Ensure all children visible - FoldExpand(lineClick, SC_FOLDACTION_EXPAND, levelClick); - } else if (ctrl) { - FoldExpand(lineClick, SC_FOLDACTION_TOGGLE, levelClick); - } else { - // Toggle this line - FoldLine(lineClick, SC_FOLDACTION_TOGGLE); - } - } - } - return true; - } - SCNotification scn = {}; - scn.nmhdr.code = SCN_MARGINCLICK; - scn.modifiers = modifiers; - scn.position = position; - scn.margin = marginClicked; - NotifyParent(scn); - return true; - } else { - return false; - } -} - -bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) { - return NotifyMarginClick(pt, ModifierFlags(shift, ctrl, alt)); -} - -void Editor::NotifyNeedShown(int pos, int len) { - SCNotification scn = {}; - scn.nmhdr.code = SCN_NEEDSHOWN; - scn.position = pos; - scn.length = len; - NotifyParent(scn); -} - -void Editor::NotifyDwelling(Point pt, bool state) { - SCNotification scn = {}; - scn.nmhdr.code = state ? SCN_DWELLSTART : SCN_DWELLEND; - scn.position = PositionFromLocation(pt, true); - scn.x = static_cast(pt.x + vs.ExternalMarginWidth()); - scn.y = static_cast(pt.y); - NotifyParent(scn); -} - -void Editor::NotifyZoom() { - SCNotification scn = {}; - scn.nmhdr.code = SCN_ZOOM; - NotifyParent(scn); -} - -// Notifications from document -void Editor::NotifyModifyAttempt(Document *, void *) { - //Platform::DebugPrintf("** Modify Attempt\n"); - NotifyModifyAttempt(); -} - -void Editor::NotifySavePoint(Document *, void *, bool atSavePoint) { - //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off"); - NotifySavePoint(atSavePoint); -} - -void Editor::CheckModificationForWrap(DocModification mh) { - if (mh.modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) { - view.llc.Invalidate(LineLayout::llCheckTextAndStyle); - int lineDoc = pdoc->LineFromPosition(mh.position); - int lines = Platform::Maximum(0, mh.linesAdded); - if (Wrapping()) { - NeedWrapping(lineDoc, lineDoc + lines + 1); - } - RefreshStyleData(); - // Fix up annotation heights - SetAnnotationHeights(lineDoc, lineDoc + lines + 2); - } -} - -// Move a position so it is still after the same character as before the insertion. -static inline int MovePositionForInsertion(int position, int startInsertion, int length) { - if (position > startInsertion) { - return position + length; - } - return position; -} - -// Move a position so it is still after the same character as before the deletion if that -// character is still present else after the previous surviving character. -static inline int MovePositionForDeletion(int position, int startDeletion, int length) { - if (position > startDeletion) { - int endDeletion = startDeletion + length; - if (position > endDeletion) { - return position - length; - } else { - return startDeletion; - } - } else { - return position; - } -} - -void Editor::NotifyModified(Document *, DocModification mh, void *) { - ContainerNeedsUpdate(SC_UPDATE_CONTENT); - if (paintState == painting) { - CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length)); - } - if (mh.modificationType & SC_MOD_CHANGELINESTATE) { - if (paintState == painting) { - CheckForChangeOutsidePaint( - Range(pdoc->LineStart(mh.line), pdoc->LineStart(mh.line + 1))); - } else { - // Could check that change is before last visible line. - Redraw(); - } - } - if (mh.modificationType & SC_MOD_CHANGETABSTOPS) { - Redraw(); - } - if (mh.modificationType & SC_MOD_LEXERSTATE) { - if (paintState == painting) { - CheckForChangeOutsidePaint( - Range(mh.position, mh.position + mh.length)); - } else { - Redraw(); - } - } - if (mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) { - if (mh.modificationType & SC_MOD_CHANGESTYLE) { - pdoc->IncrementStyleClock(); - } - if (paintState == notPainting) { - if (mh.position < pdoc->LineStart(topLine)) { - // Styling performed before this view - Redraw(); - } else { - InvalidateRange(mh.position, mh.position + mh.length); - } - } - if (mh.modificationType & SC_MOD_CHANGESTYLE) { - view.llc.Invalidate(LineLayout::llCheckTextAndStyle); - } - } else { - // Move selection and brace highlights - if (mh.modificationType & SC_MOD_INSERTTEXT) { - sel.MovePositions(true, mh.position, mh.length); - braces[0] = MovePositionForInsertion(braces[0], mh.position, mh.length); - braces[1] = MovePositionForInsertion(braces[1], mh.position, mh.length); - } else if (mh.modificationType & SC_MOD_DELETETEXT) { - sel.MovePositions(false, mh.position, mh.length); - braces[0] = MovePositionForDeletion(braces[0], mh.position, mh.length); - braces[1] = MovePositionForDeletion(braces[1], mh.position, mh.length); - } - if ((mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) && cs.HiddenLines()) { - // Some lines are hidden so may need shown. - // TODO: check if the modified area is hidden. - if (mh.modificationType & SC_MOD_BEFOREINSERT) { - int lineOfPos = pdoc->LineFromPosition(mh.position); - bool insertingNewLine = false; - for (int i=0; i < mh.length; i++) { - if ((mh.text[i] == '\n') || (mh.text[i] == '\r')) - insertingNewLine = true; - } - if (insertingNewLine && (mh.position != pdoc->LineStart(lineOfPos))) - NeedShown(mh.position, pdoc->LineStart(lineOfPos+1) - mh.position); - else - NeedShown(mh.position, 0); - } else if (mh.modificationType & SC_MOD_BEFOREDELETE) { - NeedShown(mh.position, mh.length); - } - } - if (mh.linesAdded != 0) { - // Update contraction state for inserted and removed lines - // lineOfPos should be calculated in context of state before modification, shouldn't it - int lineOfPos = pdoc->LineFromPosition(mh.position); - if (mh.position > pdoc->LineStart(lineOfPos)) - lineOfPos++; // Affecting subsequent lines - if (mh.linesAdded > 0) { - cs.InsertLines(lineOfPos, mh.linesAdded); - } else { - cs.DeleteLines(lineOfPos, -mh.linesAdded); - } - view.LinesAddedOrRemoved(lineOfPos, mh.linesAdded); - } - if (mh.modificationType & SC_MOD_CHANGEANNOTATION) { - int lineDoc = pdoc->LineFromPosition(mh.position); - if (vs.annotationVisible) { - cs.SetHeight(lineDoc, cs.GetHeight(lineDoc) + mh.annotationLinesAdded); - Redraw(); - } - } - CheckModificationForWrap(mh); - if (mh.linesAdded != 0) { - // Avoid scrolling of display if change before current display - if (mh.position < posTopLine && !CanDeferToLastStep(mh)) { - int newTop = Platform::Clamp(topLine + mh.linesAdded, 0, MaxScrollPos()); - if (newTop != topLine) { - SetTopLine(newTop); - SetVerticalScrollPos(); - } - } - - if (paintState == notPainting && !CanDeferToLastStep(mh)) { - QueueIdleWork(WorkNeeded::workStyle, pdoc->Length()); - Redraw(); - } - } else { - if (paintState == notPainting && mh.length && !CanEliminate(mh)) { - QueueIdleWork(WorkNeeded::workStyle, mh.position + mh.length); - InvalidateRange(mh.position, mh.position + mh.length); - } - } - } - - if (mh.linesAdded != 0 && !CanDeferToLastStep(mh)) { - SetScrollBars(); - } - - if ((mh.modificationType & SC_MOD_CHANGEMARKER) || (mh.modificationType & SC_MOD_CHANGEMARGIN)) { - if ((!willRedrawAll) && ((paintState == notPainting) || !PaintContainsMargin())) { - if (mh.modificationType & SC_MOD_CHANGEFOLD) { - // Fold changes can affect the drawing of following lines so redraw whole margin - RedrawSelMargin(marginView.highlightDelimiter.isEnabled ? -1 : mh.line - 1, true); - } else { - RedrawSelMargin(mh.line); - } - } - } - if ((mh.modificationType & SC_MOD_CHANGEFOLD) && (foldAutomatic & SC_AUTOMATICFOLD_CHANGE)) { - FoldChanged(mh.line, mh.foldLevelNow, mh.foldLevelPrev); - } - - // NOW pay the piper WRT "deferred" visual updates - if (IsLastStep(mh)) { - SetScrollBars(); - Redraw(); - } - - // If client wants to see this modification - if (mh.modificationType & modEventMask) { - if ((mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) == 0) { - // Real modification made to text of document. - NotifyChange(); // Send EN_CHANGE - } - - SCNotification scn = {}; - scn.nmhdr.code = SCN_MODIFIED; - scn.position = mh.position; - scn.modificationType = mh.modificationType; - scn.text = mh.text; - scn.length = mh.length; - scn.linesAdded = mh.linesAdded; - scn.line = mh.line; - scn.foldLevelNow = mh.foldLevelNow; - scn.foldLevelPrev = mh.foldLevelPrev; - scn.token = mh.token; - scn.annotationLinesAdded = mh.annotationLinesAdded; - NotifyParent(scn); - } -} - -void Editor::NotifyDeleted(Document *, void *) { - /* Do nothing */ -} - -void Editor::NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { - - // Enumerates all macroable messages - switch (iMessage) { - case SCI_CUT: - case SCI_COPY: - case SCI_PASTE: - case SCI_CLEAR: - case SCI_REPLACESEL: - case SCI_ADDTEXT: - case SCI_INSERTTEXT: - case SCI_APPENDTEXT: - case SCI_CLEARALL: - case SCI_SELECTALL: - case SCI_GOTOLINE: - case SCI_GOTOPOS: - case SCI_SEARCHANCHOR: - case SCI_SEARCHNEXT: - case SCI_SEARCHPREV: - case SCI_LINEDOWN: - case SCI_LINEDOWNEXTEND: - case SCI_PARADOWN: - case SCI_PARADOWNEXTEND: - case SCI_LINEUP: - case SCI_LINEUPEXTEND: - case SCI_PARAUP: - case SCI_PARAUPEXTEND: - case SCI_CHARLEFT: - case SCI_CHARLEFTEXTEND: - case SCI_CHARRIGHT: - case SCI_CHARRIGHTEXTEND: - case SCI_WORDLEFT: - case SCI_WORDLEFTEXTEND: - case SCI_WORDRIGHT: - case SCI_WORDRIGHTEXTEND: - case SCI_WORDPARTLEFT: - case SCI_WORDPARTLEFTEXTEND: - case SCI_WORDPARTRIGHT: - case SCI_WORDPARTRIGHTEXTEND: - case SCI_WORDLEFTEND: - case SCI_WORDLEFTENDEXTEND: - case SCI_WORDRIGHTEND: - case SCI_WORDRIGHTENDEXTEND: - case SCI_HOME: - case SCI_HOMEEXTEND: - case SCI_LINEEND: - case SCI_LINEENDEXTEND: - case SCI_HOMEWRAP: - case SCI_HOMEWRAPEXTEND: - case SCI_LINEENDWRAP: - case SCI_LINEENDWRAPEXTEND: - case SCI_DOCUMENTSTART: - case SCI_DOCUMENTSTARTEXTEND: - case SCI_DOCUMENTEND: - case SCI_DOCUMENTENDEXTEND: - case SCI_STUTTEREDPAGEUP: - case SCI_STUTTEREDPAGEUPEXTEND: - case SCI_STUTTEREDPAGEDOWN: - case SCI_STUTTEREDPAGEDOWNEXTEND: - case SCI_PAGEUP: - case SCI_PAGEUPEXTEND: - case SCI_PAGEDOWN: - case SCI_PAGEDOWNEXTEND: - case SCI_EDITTOGGLEOVERTYPE: - case SCI_CANCEL: - case SCI_DELETEBACK: - case SCI_TAB: - case SCI_BACKTAB: - case SCI_FORMFEED: - case SCI_VCHOME: - case SCI_VCHOMEEXTEND: - case SCI_VCHOMEWRAP: - case SCI_VCHOMEWRAPEXTEND: - case SCI_VCHOMEDISPLAY: - case SCI_VCHOMEDISPLAYEXTEND: - case SCI_DELWORDLEFT: - case SCI_DELWORDRIGHT: - case SCI_DELWORDRIGHTEND: - case SCI_DELLINELEFT: - case SCI_DELLINERIGHT: - case SCI_LINECOPY: - case SCI_LINECUT: - case SCI_LINEDELETE: - case SCI_LINETRANSPOSE: - case SCI_LINEDUPLICATE: - case SCI_LOWERCASE: - case SCI_UPPERCASE: - case SCI_LINESCROLLDOWN: - case SCI_LINESCROLLUP: - case SCI_DELETEBACKNOTLINE: - case SCI_HOMEDISPLAY: - case SCI_HOMEDISPLAYEXTEND: - case SCI_LINEENDDISPLAY: - case SCI_LINEENDDISPLAYEXTEND: - case SCI_SETSELECTIONMODE: - case SCI_LINEDOWNRECTEXTEND: - case SCI_LINEUPRECTEXTEND: - case SCI_CHARLEFTRECTEXTEND: - case SCI_CHARRIGHTRECTEXTEND: - case SCI_HOMERECTEXTEND: - case SCI_VCHOMERECTEXTEND: - case SCI_LINEENDRECTEXTEND: - case SCI_PAGEUPRECTEXTEND: - case SCI_PAGEDOWNRECTEXTEND: - case SCI_SELECTIONDUPLICATE: - case SCI_COPYALLOWLINE: - case SCI_VERTICALCENTRECARET: - case SCI_MOVESELECTEDLINESUP: - case SCI_MOVESELECTEDLINESDOWN: - case SCI_SCROLLTOSTART: - case SCI_SCROLLTOEND: - break; - - // Filter out all others like display changes. Also, newlines are redundant - // with char insert messages. - case SCI_NEWLINE: - default: - // printf("Filtered out %ld of macro recording\n", iMessage); - return; - } - - // Send notification - SCNotification scn = {}; - scn.nmhdr.code = SCN_MACRORECORD; - scn.message = iMessage; - scn.wParam = wParam; - scn.lParam = lParam; - NotifyParent(scn); -} - -// Something has changed that the container should know about -void Editor::ContainerNeedsUpdate(int flags) { - needUpdateUI |= flags; -} - -/** - * Force scroll and keep position relative to top of window. - * - * If stuttered = true and not already at first/last row, move to first/last row of window. - * If stuttered = true and already at first/last row, scroll as normal. - */ -void Editor::PageMove(int direction, Selection::selTypes selt, bool stuttered) { - int topLineNew; - SelectionPosition newPos; - - int currentLine = pdoc->LineFromPosition(sel.MainCaret()); - int topStutterLine = topLine + caretYSlop; - int bottomStutterLine = - pdoc->LineFromPosition(PositionFromLocation( - Point::FromInts(lastXChosen - xOffset, direction * vs.lineHeight * LinesToScroll()))) - - caretYSlop - 1; - - if (stuttered && (direction < 0 && currentLine > topStutterLine)) { - topLineNew = topLine; - newPos = SPositionFromLocation(Point::FromInts(lastXChosen - xOffset, vs.lineHeight * caretYSlop), - false, false, UserVirtualSpace()); - - } else if (stuttered && (direction > 0 && currentLine < bottomStutterLine)) { - topLineNew = topLine; - newPos = SPositionFromLocation(Point::FromInts(lastXChosen - xOffset, vs.lineHeight * (LinesToScroll() - caretYSlop)), - false, false, UserVirtualSpace()); - - } else { - Point pt = LocationFromPosition(sel.MainCaret()); - - topLineNew = Platform::Clamp( - topLine + direction * LinesToScroll(), 0, MaxScrollPos()); - newPos = SPositionFromLocation( - Point::FromInts(lastXChosen - xOffset, static_cast(pt.y) + direction * (vs.lineHeight * LinesToScroll())), - false, false, UserVirtualSpace()); - } - - if (topLineNew != topLine) { - SetTopLine(topLineNew); - MovePositionTo(newPos, selt); - Redraw(); - SetVerticalScrollPos(); - } else { - MovePositionTo(newPos, selt); - } -} - -void Editor::ChangeCaseOfSelection(int caseMapping) { - UndoGroup ug(pdoc); - for (size_t r=0; r 0) { - std::string sText = RangeText(currentNoVS.Start().Position(), currentNoVS.End().Position()); - - std::string sMapped = CaseMapString(sText, caseMapping); - - if (sMapped != sText) { - size_t firstDifference = 0; - while (sMapped[firstDifference] == sText[firstDifference]) - firstDifference++; - size_t lastDifferenceText = sText.size() - 1; - size_t lastDifferenceMapped = sMapped.size() - 1; - while (sMapped[lastDifferenceMapped] == sText[lastDifferenceText]) { - lastDifferenceText--; - lastDifferenceMapped--; - } - size_t endDifferenceText = sText.size() - 1 - lastDifferenceText; - pdoc->DeleteChars( - static_cast(currentNoVS.Start().Position() + firstDifference), - static_cast(rangeBytes - firstDifference - endDifferenceText)); - const int lengthChange = static_cast(lastDifferenceMapped - firstDifference + 1); - const int lengthInserted = pdoc->InsertString( - static_cast(currentNoVS.Start().Position() + firstDifference), - sMapped.c_str() + firstDifference, - lengthChange); - // Automatic movement changes selection so reset to exactly the same as it was. - int diffSizes = static_cast(sMapped.size() - sText.size()) + lengthInserted - lengthChange; - if (diffSizes != 0) { - if (current.anchor > current.caret) - current.anchor.Add(diffSizes); - else - current.caret.Add(diffSizes); - } - sel.Range(r) = current; - } - } - } -} - -void Editor::LineTranspose() { - int line = pdoc->LineFromPosition(sel.MainCaret()); - if (line > 0) { - UndoGroup ug(pdoc); - - const int startPrevious = pdoc->LineStart(line - 1); - const std::string linePrevious = RangeText(startPrevious, pdoc->LineEnd(line - 1)); - - int startCurrent = pdoc->LineStart(line); - const std::string lineCurrent = RangeText(startCurrent, pdoc->LineEnd(line)); - - pdoc->DeleteChars(startCurrent, static_cast(lineCurrent.length())); - pdoc->DeleteChars(startPrevious, static_cast(linePrevious.length())); - startCurrent -= static_cast(linePrevious.length()); - - startCurrent += pdoc->InsertString(startPrevious, lineCurrent.c_str(), - static_cast(lineCurrent.length())); - pdoc->InsertString(startCurrent, linePrevious.c_str(), - static_cast(linePrevious.length())); - // Move caret to start of current line - MovePositionTo(SelectionPosition(startCurrent)); - } -} - -void Editor::Duplicate(bool forLine) { - if (sel.Empty()) { - forLine = true; - } - UndoGroup ug(pdoc); - const char *eol = ""; - int eolLen = 0; - if (forLine) { - eol = StringFromEOLMode(pdoc->eolMode); - eolLen = istrlen(eol); - } - for (size_t r=0; rLineFromPosition(sel.Range(r).caret.Position()); - start = SelectionPosition(pdoc->LineStart(line)); - end = SelectionPosition(pdoc->LineEnd(line)); - } - std::string text = RangeText(start.Position(), end.Position()); - int lengthInserted = eolLen; - if (forLine) - lengthInserted = pdoc->InsertString(end.Position(), eol, eolLen); - pdoc->InsertString(end.Position() + lengthInserted, text.c_str(), static_cast(text.length())); - } - if (sel.Count() && sel.IsRectangular()) { - SelectionPosition last = sel.Last(); - if (forLine) { - int line = pdoc->LineFromPosition(last.Position()); - last = SelectionPosition(last.Position() + pdoc->LineStart(line+1) - pdoc->LineStart(line)); - } - if (sel.Rectangular().anchor > sel.Rectangular().caret) - sel.Rectangular().anchor = last; - else - sel.Rectangular().caret = last; - SetRectangularRange(); - } -} - -void Editor::CancelModes() { - sel.SetMoveExtends(false); -} - -void Editor::NewLine() { - // Remove non-main ranges - InvalidateSelection(sel.RangeMain(), true); - sel.SetSelection(sel.RangeMain()); - sel.RangeMain().ClearVirtualSpace(); - - // Clear main range and insert line end - bool needGroupUndo = !sel.Empty(); - if (needGroupUndo) - pdoc->BeginUndoAction(); - - if (!sel.Empty()) - ClearSelection(); - const char *eol = "\n"; - if (pdoc->eolMode == SC_EOL_CRLF) { - eol = "\r\n"; - } else if (pdoc->eolMode == SC_EOL_CR) { - eol = "\r"; - } // else SC_EOL_LF -> "\n" already set - const int insertLength = pdoc->InsertString(sel.MainCaret(), eol, istrlen(eol)); - // Want to end undo group before NotifyChar as applications often modify text here - if (needGroupUndo) - pdoc->EndUndoAction(); - if (insertLength > 0) { - SetEmptySelection(sel.MainCaret() + insertLength); - while (*eol) { - NotifyChar(*eol); - if (recordingMacro) { - char txt[2]; - txt[0] = *eol; - txt[1] = '\0'; - NotifyMacroRecord(SCI_REPLACESEL, 0, reinterpret_cast(txt)); - } - eol++; - } - } - SetLastXChosen(); - SetScrollBars(); - EnsureCaretVisible(); - // Avoid blinking during rapid typing: - ShowCaretAtCurrentPosition(); -} - -void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) { - SelectionPosition caretToUse = sel.Range(sel.Main()).caret; - if (sel.IsRectangular()) { - if (selt == Selection::noSel) { - caretToUse = (direction > 0) ? sel.Limits().end : sel.Limits().start; - } else { - caretToUse = sel.Rectangular().caret; - } - } - - Point pt = LocationFromPosition(caretToUse); - int skipLines = 0; - - if (vs.annotationVisible) { - int lineDoc = pdoc->LineFromPosition(caretToUse.Position()); - Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc)); - int subLine = static_cast(pt.y - ptStartLine.y) / vs.lineHeight; - - if (direction < 0 && subLine == 0) { - int lineDisplay = cs.DisplayFromDoc(lineDoc); - if (lineDisplay > 0) { - skipLines = pdoc->AnnotationLines(cs.DocFromDisplay(lineDisplay - 1)); - } - } else if (direction > 0 && subLine >= (cs.GetHeight(lineDoc) - 1 - pdoc->AnnotationLines(lineDoc))) { - skipLines = pdoc->AnnotationLines(lineDoc); - } - } - - int newY = static_cast(pt.y) + (1 + skipLines) * direction * vs.lineHeight; - SelectionPosition posNew = SPositionFromLocation( - Point::FromInts(lastXChosen - xOffset, newY), false, false, UserVirtualSpace()); - - if (direction < 0) { - // Line wrapping may lead to a location on the same line, so - // seek back if that is the case. - Point ptNew = LocationFromPosition(posNew.Position()); - while ((posNew.Position() > 0) && (pt.y == ptNew.y)) { - posNew.Add(-1); - posNew.SetVirtualSpace(0); - ptNew = LocationFromPosition(posNew.Position()); - } - } else if (direction > 0 && posNew.Position() != pdoc->Length()) { - // There is an equivalent case when moving down which skips - // over a line. - Point ptNew = LocationFromPosition(posNew.Position()); - while ((posNew.Position() > caretToUse.Position()) && (ptNew.y > newY)) { - posNew.Add(-1); - posNew.SetVirtualSpace(0); - ptNew = LocationFromPosition(posNew.Position()); - } - } - - MovePositionTo(MovePositionSoVisible(posNew, direction), selt); -} - -void Editor::ParaUpOrDown(int direction, Selection::selTypes selt) { - int lineDoc, savedPos = sel.MainCaret(); - do { - MovePositionTo(SelectionPosition(direction > 0 ? pdoc->ParaDown(sel.MainCaret()) : pdoc->ParaUp(sel.MainCaret())), selt); - lineDoc = pdoc->LineFromPosition(sel.MainCaret()); - if (direction > 0) { - if (sel.MainCaret() >= pdoc->Length() && !cs.GetVisible(lineDoc)) { - if (selt == Selection::noSel) { - MovePositionTo(SelectionPosition(pdoc->LineEndPosition(savedPos))); - } - break; - } - } - } while (!cs.GetVisible(lineDoc)); -} - -int Editor::StartEndDisplayLine(int pos, bool start) { - RefreshStyleData(); - AutoSurface surface(this); - int posRet = view.StartEndDisplayLine(surface, *this, pos, start, vs); - if (posRet == INVALID_POSITION) { - return pos; - } else { - return posRet; - } -} - -int Editor::KeyCommand(unsigned int iMessage) { - switch (iMessage) { - case SCI_LINEDOWN: - CursorUpOrDown(1); - break; - case SCI_LINEDOWNEXTEND: - CursorUpOrDown(1, Selection::selStream); - break; - case SCI_LINEDOWNRECTEXTEND: - CursorUpOrDown(1, Selection::selRectangle); - break; - case SCI_PARADOWN: - ParaUpOrDown(1); - break; - case SCI_PARADOWNEXTEND: - ParaUpOrDown(1, Selection::selStream); - break; - case SCI_LINESCROLLDOWN: - ScrollTo(topLine + 1); - MoveCaretInsideView(false); - break; - case SCI_LINEUP: - CursorUpOrDown(-1); - break; - case SCI_LINEUPEXTEND: - CursorUpOrDown(-1, Selection::selStream); - break; - case SCI_LINEUPRECTEXTEND: - CursorUpOrDown(-1, Selection::selRectangle); - break; - case SCI_PARAUP: - ParaUpOrDown(-1); - break; - case SCI_PARAUPEXTEND: - ParaUpOrDown(-1, Selection::selStream); - break; - case SCI_LINESCROLLUP: - ScrollTo(topLine - 1); - MoveCaretInsideView(false); - break; - case SCI_CHARLEFT: - if (SelectionEmpty() || sel.MoveExtends()) { - if ((sel.Count() == 1) && pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) { - SelectionPosition spCaret = sel.RangeMain().caret; - spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1); - MovePositionTo(spCaret); - } else if (sel.MoveExtends() && sel.selType == Selection::selStream) { - MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1)); - } else { - MovePositionTo(MovePositionSoVisible( - SelectionPosition((sel.LimitsForRectangularElseMain().start).Position() - 1), -1)); - } - } else { - MovePositionTo(sel.LimitsForRectangularElseMain().start); - } - SetLastXChosen(); - break; - case SCI_CHARLEFTEXTEND: - if (pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) { - SelectionPosition spCaret = sel.RangeMain().caret; - spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1); - MovePositionTo(spCaret, Selection::selStream); - } else { - MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1), Selection::selStream); - } - SetLastXChosen(); - break; - case SCI_CHARLEFTRECTEXTEND: - if (pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) { - SelectionPosition spCaret = sel.RangeMain().caret; - spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1); - MovePositionTo(spCaret, Selection::selRectangle); - } else { - MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1), Selection::selRectangle); - } - SetLastXChosen(); - break; - case SCI_CHARRIGHT: - if (SelectionEmpty() || sel.MoveExtends()) { - if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(sel.MainCaret())) { - SelectionPosition spCaret = sel.RangeMain().caret; - spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1); - MovePositionTo(spCaret); - } else if (sel.MoveExtends() && sel.selType == Selection::selStream) { - MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1)); - } else { - MovePositionTo(MovePositionSoVisible( - SelectionPosition((sel.LimitsForRectangularElseMain().end).Position() + 1), 1)); - } - } else { - MovePositionTo(sel.LimitsForRectangularElseMain().end); - } - SetLastXChosen(); - break; - case SCI_CHARRIGHTEXTEND: - if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(sel.MainCaret())) { - SelectionPosition spCaret = sel.RangeMain().caret; - spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1); - MovePositionTo(spCaret, Selection::selStream); - } else { - MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1), Selection::selStream); - } - SetLastXChosen(); - break; - case SCI_CHARRIGHTRECTEXTEND: - if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) && pdoc->IsLineEndPosition(sel.MainCaret())) { - SelectionPosition spCaret = sel.RangeMain().caret; - spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1); - MovePositionTo(spCaret, Selection::selRectangle); - } else { - MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1), Selection::selRectangle); - } - SetLastXChosen(); - break; - case SCI_WORDLEFT: - MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), -1), -1)); - SetLastXChosen(); - break; - case SCI_WORDLEFTEXTEND: - MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), -1), -1), Selection::selStream); - SetLastXChosen(); - break; - case SCI_WORDRIGHT: - MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), 1), 1)); - SetLastXChosen(); - break; - case SCI_WORDRIGHTEXTEND: - MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), 1), 1), Selection::selStream); - SetLastXChosen(); - break; - - case SCI_WORDLEFTEND: - MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), -1), -1)); - SetLastXChosen(); - break; - case SCI_WORDLEFTENDEXTEND: - MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), -1), -1), Selection::selStream); - SetLastXChosen(); - break; - case SCI_WORDRIGHTEND: - MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), 1), 1)); - SetLastXChosen(); - break; - case SCI_WORDRIGHTENDEXTEND: - MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), 1), 1), Selection::selStream); - SetLastXChosen(); - break; - - case SCI_HOME: - MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret()))); - SetLastXChosen(); - break; - case SCI_HOMEEXTEND: - MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())), Selection::selStream); - SetLastXChosen(); - break; - case SCI_HOMERECTEXTEND: - MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())), Selection::selRectangle); - SetLastXChosen(); - break; - case SCI_LINEEND: - MovePositionTo(pdoc->LineEndPosition(sel.MainCaret())); - SetLastXChosen(); - break; - case SCI_LINEENDEXTEND: - MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()), Selection::selStream); - SetLastXChosen(); - break; - case SCI_LINEENDRECTEXTEND: - MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()), Selection::selRectangle); - SetLastXChosen(); - break; - case SCI_HOMEWRAP: { - SelectionPosition homePos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1); - if (sel.RangeMain().caret <= homePos) - homePos = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret()))); - MovePositionTo(homePos); - SetLastXChosen(); - } - break; - case SCI_HOMEWRAPEXTEND: { - SelectionPosition homePos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1); - if (sel.RangeMain().caret <= homePos) - homePos = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret()))); - MovePositionTo(homePos, Selection::selStream); - SetLastXChosen(); - } - break; - case SCI_LINEENDWRAP: { - SelectionPosition endPos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), false), 1); - SelectionPosition realEndPos = SelectionPosition(pdoc->LineEndPosition(sel.MainCaret())); - if (endPos > realEndPos // if moved past visible EOLs - || sel.RangeMain().caret >= endPos) // if at end of display line already - endPos = realEndPos; - MovePositionTo(endPos); - SetLastXChosen(); - } - break; - case SCI_LINEENDWRAPEXTEND: { - SelectionPosition endPos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), false), 1); - SelectionPosition realEndPos = SelectionPosition(pdoc->LineEndPosition(sel.MainCaret())); - if (endPos > realEndPos // if moved past visible EOLs - || sel.RangeMain().caret >= endPos) // if at end of display line already - endPos = realEndPos; - MovePositionTo(endPos, Selection::selStream); - SetLastXChosen(); - } - break; - case SCI_DOCUMENTSTART: - MovePositionTo(0); - SetLastXChosen(); - break; - case SCI_DOCUMENTSTARTEXTEND: - MovePositionTo(0, Selection::selStream); - SetLastXChosen(); - break; - case SCI_DOCUMENTEND: - MovePositionTo(pdoc->Length()); - SetLastXChosen(); - break; - case SCI_DOCUMENTENDEXTEND: - MovePositionTo(pdoc->Length(), Selection::selStream); - SetLastXChosen(); - break; - case SCI_STUTTEREDPAGEUP: - PageMove(-1, Selection::noSel, true); - break; - case SCI_STUTTEREDPAGEUPEXTEND: - PageMove(-1, Selection::selStream, true); - break; - case SCI_STUTTEREDPAGEDOWN: - PageMove(1, Selection::noSel, true); - break; - case SCI_STUTTEREDPAGEDOWNEXTEND: - PageMove(1, Selection::selStream, true); - break; - case SCI_PAGEUP: - PageMove(-1); - break; - case SCI_PAGEUPEXTEND: - PageMove(-1, Selection::selStream); - break; - case SCI_PAGEUPRECTEXTEND: - PageMove(-1, Selection::selRectangle); - break; - case SCI_PAGEDOWN: - PageMove(1); - break; - case SCI_PAGEDOWNEXTEND: - PageMove(1, Selection::selStream); - break; - case SCI_PAGEDOWNRECTEXTEND: - PageMove(1, Selection::selRectangle); - break; - case SCI_EDITTOGGLEOVERTYPE: - inOverstrike = !inOverstrike; - ShowCaretAtCurrentPosition(); - ContainerNeedsUpdate(SC_UPDATE_CONTENT); - NotifyUpdateUI(); - break; - case SCI_CANCEL: // Cancel any modes - handled in subclass - // Also unselect text - CancelModes(); - break; - case SCI_DELETEBACK: - DelCharBack(true); - if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) { - SetLastXChosen(); - } - EnsureCaretVisible(); - break; - case SCI_DELETEBACKNOTLINE: - DelCharBack(false); - if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) { - SetLastXChosen(); - } - EnsureCaretVisible(); - break; - case SCI_TAB: - Indent(true); - if (caretSticky == SC_CARETSTICKY_OFF) { - SetLastXChosen(); - } - EnsureCaretVisible(); - ShowCaretAtCurrentPosition(); // Avoid blinking - break; - case SCI_BACKTAB: - Indent(false); - if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) { - SetLastXChosen(); - } - EnsureCaretVisible(); - ShowCaretAtCurrentPosition(); // Avoid blinking - break; - case SCI_NEWLINE: - NewLine(); - break; - case SCI_FORMFEED: - AddChar('\f'); - break; - case SCI_VCHOME: - MovePositionTo(pdoc->VCHomePosition(sel.MainCaret())); - SetLastXChosen(); - break; - case SCI_VCHOMEEXTEND: - MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()), Selection::selStream); - SetLastXChosen(); - break; - case SCI_VCHOMERECTEXTEND: - MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()), Selection::selRectangle); - SetLastXChosen(); - break; - case SCI_VCHOMEWRAP: { - SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret())); - SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1); - if ((viewLineStart < sel.RangeMain().caret) && (viewLineStart > homePos)) - homePos = viewLineStart; - - MovePositionTo(homePos); - SetLastXChosen(); - } - break; - case SCI_VCHOMEWRAPEXTEND: { - SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret())); - SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1); - if ((viewLineStart < sel.RangeMain().caret) && (viewLineStart > homePos)) - homePos = viewLineStart; - - MovePositionTo(homePos, Selection::selStream); - SetLastXChosen(); - } - break; - case SCI_ZOOMIN: - if (vs.zoomLevel < 20) { - vs.zoomLevel++; - InvalidateStyleRedraw(); - NotifyZoom(); - } - break; - case SCI_ZOOMOUT: - if (vs.zoomLevel > -10) { - vs.zoomLevel--; - InvalidateStyleRedraw(); - NotifyZoom(); - } - break; - case SCI_DELWORDLEFT: { - int startWord = pdoc->NextWordStart(sel.MainCaret(), -1); - pdoc->DeleteChars(startWord, sel.MainCaret() - startWord); - sel.RangeMain().ClearVirtualSpace(); - SetLastXChosen(); - } - break; - case SCI_DELWORDRIGHT: { - UndoGroup ug(pdoc); - InvalidateSelection(sel.RangeMain(), true); - sel.RangeMain().caret = SelectionPosition( - InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace())); - sel.RangeMain().anchor = sel.RangeMain().caret; - int endWord = pdoc->NextWordStart(sel.MainCaret(), 1); - pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret()); - } - break; - case SCI_DELWORDRIGHTEND: { - UndoGroup ug(pdoc); - InvalidateSelection(sel.RangeMain(), true); - sel.RangeMain().caret = SelectionPosition( - InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace())); - int endWord = pdoc->NextWordEnd(sel.MainCaret(), 1); - pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret()); - } - break; - case SCI_DELLINELEFT: { - int line = pdoc->LineFromPosition(sel.MainCaret()); - int start = pdoc->LineStart(line); - pdoc->DeleteChars(start, sel.MainCaret() - start); - sel.RangeMain().ClearVirtualSpace(); - SetLastXChosen(); - } - break; - case SCI_DELLINERIGHT: { - int line = pdoc->LineFromPosition(sel.MainCaret()); - int end = pdoc->LineEnd(line); - pdoc->DeleteChars(sel.MainCaret(), end - sel.MainCaret()); - } - break; - case SCI_LINECOPY: { - int lineStart = pdoc->LineFromPosition(SelectionStart().Position()); - int lineEnd = pdoc->LineFromPosition(SelectionEnd().Position()); - CopyRangeToClipboard(pdoc->LineStart(lineStart), - pdoc->LineStart(lineEnd + 1)); - } - break; - case SCI_LINECUT: { - int lineStart = pdoc->LineFromPosition(SelectionStart().Position()); - int lineEnd = pdoc->LineFromPosition(SelectionEnd().Position()); - int start = pdoc->LineStart(lineStart); - int end = pdoc->LineStart(lineEnd + 1); - SetSelection(start, end); - Cut(); - SetLastXChosen(); - } - break; - case SCI_LINEDELETE: { - int line = pdoc->LineFromPosition(sel.MainCaret()); - int start = pdoc->LineStart(line); - int end = pdoc->LineStart(line + 1); - pdoc->DeleteChars(start, end - start); - } - break; - case SCI_LINETRANSPOSE: - LineTranspose(); - break; - case SCI_LINEDUPLICATE: - Duplicate(true); - break; - case SCI_SELECTIONDUPLICATE: - Duplicate(false); - break; - case SCI_LOWERCASE: - ChangeCaseOfSelection(cmLower); - break; - case SCI_UPPERCASE: - ChangeCaseOfSelection(cmUpper); - break; - case SCI_WORDPARTLEFT: - MovePositionTo(MovePositionSoVisible(pdoc->WordPartLeft(sel.MainCaret()), -1)); - SetLastXChosen(); - break; - case SCI_WORDPARTLEFTEXTEND: - MovePositionTo(MovePositionSoVisible(pdoc->WordPartLeft(sel.MainCaret()), -1), Selection::selStream); - SetLastXChosen(); - break; - case SCI_WORDPARTRIGHT: - MovePositionTo(MovePositionSoVisible(pdoc->WordPartRight(sel.MainCaret()), 1)); - SetLastXChosen(); - break; - case SCI_WORDPARTRIGHTEXTEND: - MovePositionTo(MovePositionSoVisible(pdoc->WordPartRight(sel.MainCaret()), 1), Selection::selStream); - SetLastXChosen(); - break; - case SCI_HOMEDISPLAY: - MovePositionTo(MovePositionSoVisible( - StartEndDisplayLine(sel.MainCaret(), true), -1)); - SetLastXChosen(); - break; - case SCI_VCHOMEDISPLAY: { - SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret())); - SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1); - if (viewLineStart > homePos) - homePos = viewLineStart; - - MovePositionTo(homePos); - SetLastXChosen(); - } - break; - case SCI_HOMEDISPLAYEXTEND: - MovePositionTo(MovePositionSoVisible( - StartEndDisplayLine(sel.MainCaret(), true), -1), Selection::selStream); - SetLastXChosen(); - break; - case SCI_VCHOMEDISPLAYEXTEND: { - SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret())); - SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1); - if (viewLineStart > homePos) - homePos = viewLineStart; - - MovePositionTo(homePos, Selection::selStream); - SetLastXChosen(); - } - break; - case SCI_LINEENDDISPLAY: - MovePositionTo(MovePositionSoVisible( - StartEndDisplayLine(sel.MainCaret(), false), 1)); - SetLastXChosen(); - break; - case SCI_LINEENDDISPLAYEXTEND: - MovePositionTo(MovePositionSoVisible( - StartEndDisplayLine(sel.MainCaret(), false), 1), Selection::selStream); - SetLastXChosen(); - break; - case SCI_SCROLLTOSTART: - ScrollTo(0); - break; - case SCI_SCROLLTOEND: - ScrollTo(MaxScrollPos()); - break; - } - return 0; -} - -int Editor::KeyDefault(int, int) { - return 0; -} - -int Editor::KeyDownWithModifiers(int key, int modifiers, bool *consumed) { - DwellEnd(false); - int msg = kmap.Find(key, modifiers); - if (msg) { - if (consumed) - *consumed = true; - return static_cast(WndProc(msg, 0, 0)); - } else { - if (consumed) - *consumed = false; - return KeyDefault(key, modifiers); - } -} - -int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed) { - return KeyDownWithModifiers(key, ModifierFlags(shift, ctrl, alt), consumed); -} - -void Editor::Indent(bool forwards) { - UndoGroup ug(pdoc); - for (size_t r=0; rLineFromPosition(sel.Range(r).anchor.Position()); - int caretPosition = sel.Range(r).caret.Position(); - int lineCurrentPos = pdoc->LineFromPosition(caretPosition); - if (lineOfAnchor == lineCurrentPos) { - if (forwards) { - pdoc->DeleteChars(sel.Range(r).Start().Position(), sel.Range(r).Length()); - caretPosition = sel.Range(r).caret.Position(); - if (pdoc->GetColumn(caretPosition) <= pdoc->GetColumn(pdoc->GetLineIndentPosition(lineCurrentPos)) && - pdoc->tabIndents) { - int indentation = pdoc->GetLineIndentation(lineCurrentPos); - int indentationStep = pdoc->IndentSize(); - const int posSelect = pdoc->SetLineIndentation( - lineCurrentPos, indentation + indentationStep - indentation % indentationStep); - sel.Range(r) = SelectionRange(posSelect); - } else { - if (pdoc->useTabs) { - const int lengthInserted = pdoc->InsertString(caretPosition, "\t", 1); - sel.Range(r) = SelectionRange(caretPosition + lengthInserted); - } else { - int numSpaces = (pdoc->tabInChars) - - (pdoc->GetColumn(caretPosition) % (pdoc->tabInChars)); - if (numSpaces < 1) - numSpaces = pdoc->tabInChars; - const std::string spaceText(numSpaces, ' '); - const int lengthInserted = pdoc->InsertString(caretPosition, spaceText.c_str(), - static_cast(spaceText.length())); - sel.Range(r) = SelectionRange(caretPosition + lengthInserted); - } - } - } else { - if (pdoc->GetColumn(caretPosition) <= pdoc->GetLineIndentation(lineCurrentPos) && - pdoc->tabIndents) { - int indentation = pdoc->GetLineIndentation(lineCurrentPos); - int indentationStep = pdoc->IndentSize(); - const int posSelect = pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep); - sel.Range(r) = SelectionRange(posSelect); - } else { - int newColumn = ((pdoc->GetColumn(caretPosition) - 1) / pdoc->tabInChars) * - pdoc->tabInChars; - if (newColumn < 0) - newColumn = 0; - int newPos = caretPosition; - while (pdoc->GetColumn(newPos) > newColumn) - newPos--; - sel.Range(r) = SelectionRange(newPos); - } - } - } else { // Multiline - int anchorPosOnLine = sel.Range(r).anchor.Position() - pdoc->LineStart(lineOfAnchor); - int currentPosPosOnLine = caretPosition - pdoc->LineStart(lineCurrentPos); - // Multiple lines selected so indent / dedent - int lineTopSel = Platform::Minimum(lineOfAnchor, lineCurrentPos); - int lineBottomSel = Platform::Maximum(lineOfAnchor, lineCurrentPos); - if (pdoc->LineStart(lineBottomSel) == sel.Range(r).anchor.Position() || pdoc->LineStart(lineBottomSel) == caretPosition) - lineBottomSel--; // If not selecting any characters on a line, do not indent - pdoc->Indent(forwards, lineBottomSel, lineTopSel); - if (lineOfAnchor < lineCurrentPos) { - if (currentPosPosOnLine == 0) - sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor)); - else - sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos + 1), pdoc->LineStart(lineOfAnchor)); - } else { - if (anchorPosOnLine == 0) - sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor)); - else - sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor + 1)); - } - } - } - ContainerNeedsUpdate(SC_UPDATE_SELECTION); -} - -class CaseFolderASCII : public CaseFolderTable { -public: - CaseFolderASCII() { - StandardASCII(); - } - ~CaseFolderASCII() { - } -}; - - -CaseFolder *Editor::CaseFolderForEncoding() { - // Simple default that only maps ASCII upper case to lower case. - return new CaseFolderASCII(); -} - -/** - * Search of a text in the document, in the given range. - * @return The position of the found text, -1 if not found. - */ -long Editor::FindText( - uptr_t wParam, ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD, - ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX. - sptr_t lParam) { ///< @c TextToFind structure: The text to search for in the given range. - - Sci_TextToFind *ft = reinterpret_cast(lParam); - int lengthFound = istrlen(ft->lpstrText); - if (!pdoc->HasCaseFolder()) - pdoc->SetCaseFolder(CaseFolderForEncoding()); - try { - long pos = pdoc->FindText( - static_cast(ft->chrg.cpMin), - static_cast(ft->chrg.cpMax), - ft->lpstrText, - (wParam & SCFIND_MATCHCASE) != 0, - (wParam & SCFIND_WHOLEWORD) != 0, - (wParam & SCFIND_WORDSTART) != 0, - (wParam & SCFIND_REGEXP) != 0, - static_cast(wParam), - &lengthFound); - if (pos != -1) { - ft->chrgText.cpMin = pos; - ft->chrgText.cpMax = pos + lengthFound; - } - return static_cast(pos); - } catch (RegexError &) { - errorStatus = SC_STATUS_WARN_REGEX; - return -1; - } -} - -/** - * Relocatable search support : Searches relative to current selection - * point and sets the selection to the found text range with - * each search. - */ -/** - * Anchor following searches at current selection start: This allows - * multiple incremental interactive searches to be macro recorded - * while still setting the selection to found text so the find/select - * operation is self-contained. - */ -void Editor::SearchAnchor() { - searchAnchor = SelectionStart().Position(); -} - -/** - * Find text from current search anchor: Must call @c SearchAnchor first. - * Used for next text and previous text requests. - * @return The position of the found text, -1 if not found. - */ -long Editor::SearchText( - unsigned int iMessage, ///< Accepts both @c SCI_SEARCHNEXT and @c SCI_SEARCHPREV. - uptr_t wParam, ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD, - ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX. - sptr_t lParam) { ///< The text to search for. - - const char *txt = reinterpret_cast(lParam); - long pos; - int lengthFound = istrlen(txt); - if (!pdoc->HasCaseFolder()) - pdoc->SetCaseFolder(CaseFolderForEncoding()); - try { - if (iMessage == SCI_SEARCHNEXT) { - pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt, - (wParam & SCFIND_MATCHCASE) != 0, - (wParam & SCFIND_WHOLEWORD) != 0, - (wParam & SCFIND_WORDSTART) != 0, - (wParam & SCFIND_REGEXP) != 0, - static_cast(wParam), - &lengthFound); - } else { - pos = pdoc->FindText(searchAnchor, 0, txt, - (wParam & SCFIND_MATCHCASE) != 0, - (wParam & SCFIND_WHOLEWORD) != 0, - (wParam & SCFIND_WORDSTART) != 0, - (wParam & SCFIND_REGEXP) != 0, - static_cast(wParam), - &lengthFound); - } - } catch (RegexError &) { - errorStatus = SC_STATUS_WARN_REGEX; - return -1; - } - if (pos != -1) { - SetSelection(static_cast(pos), static_cast(pos + lengthFound)); - } - - return pos; -} - -std::string Editor::CaseMapString(const std::string &s, int caseMapping) { - std::string ret(s); - for (size_t i=0; i= 'a' && ret[i] <= 'z') - ret[i] = static_cast(ret[i] - 'a' + 'A'); - break; - case cmLower: - if (ret[i] >= 'A' && ret[i] <= 'Z') - ret[i] = static_cast(ret[i] - 'A' + 'a'); - break; - } - } - return ret; -} - -/** - * Search for text in the target range of the document. - * @return The position of the found text, -1 if not found. - */ -long Editor::SearchInTarget(const char *text, int length) { - int lengthFound = length; - - if (!pdoc->HasCaseFolder()) - pdoc->SetCaseFolder(CaseFolderForEncoding()); - try { - long pos = pdoc->FindText(targetStart, targetEnd, text, - (searchFlags & SCFIND_MATCHCASE) != 0, - (searchFlags & SCFIND_WHOLEWORD) != 0, - (searchFlags & SCFIND_WORDSTART) != 0, - (searchFlags & SCFIND_REGEXP) != 0, - searchFlags, - &lengthFound); - if (pos != -1) { - targetStart = static_cast(pos); - targetEnd = static_cast(pos + lengthFound); - } - return pos; - } catch (RegexError &) { - errorStatus = SC_STATUS_WARN_REGEX; - return -1; - } -} - -void Editor::GoToLine(int lineNo) { - if (lineNo > pdoc->LinesTotal()) - lineNo = pdoc->LinesTotal(); - if (lineNo < 0) - lineNo = 0; - SetEmptySelection(pdoc->LineStart(lineNo)); - ShowCaretAtCurrentPosition(); - EnsureCaretVisible(); -} - -static bool Close(Point pt1, Point pt2, Point threshold) { - if (std::abs(pt1.x - pt2.x) > threshold.x) - return false; - if (std::abs(pt1.y - pt2.y) > threshold.y) - return false; - return true; -} - -std::string Editor::RangeText(int start, int end) const { - if (start < end) { - int len = end - start; - std::string ret(len, '\0'); - for (int i = 0; i < len; i++) { - ret[i] = pdoc->CharAt(start + i); - } - return ret; - } - return std::string(); -} - -void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) { - if (sel.Empty()) { - if (allowLineCopy) { - int currentLine = pdoc->LineFromPosition(sel.MainCaret()); - int start = pdoc->LineStart(currentLine); - int end = pdoc->LineEnd(currentLine); - - std::string text = RangeText(start, end); - if (pdoc->eolMode != SC_EOL_LF) - text.push_back('\r'); - if (pdoc->eolMode != SC_EOL_CR) - text.push_back('\n'); - ss->Copy(text, pdoc->dbcsCodePage, - vs.styles[STYLE_DEFAULT].characterSet, false, true); - } - } else { - std::string text; - std::vector rangesInOrder = sel.RangesCopy(); - if (sel.selType == Selection::selRectangle) - std::sort(rangesInOrder.begin(), rangesInOrder.end()); - for (size_t r=0; reolMode != SC_EOL_LF) - text.push_back('\r'); - if (pdoc->eolMode != SC_EOL_CR) - text.push_back('\n'); - } - } - ss->Copy(text, pdoc->dbcsCodePage, - vs.styles[STYLE_DEFAULT].characterSet, sel.IsRectangular(), sel.selType == Selection::selLines); - } -} - -void Editor::CopyRangeToClipboard(int start, int end) { - start = pdoc->ClampPositionIntoDocument(start); - end = pdoc->ClampPositionIntoDocument(end); - SelectionText selectedText; - std::string text = RangeText(start, end); - selectedText.Copy(text, - pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false); - CopyToClipboard(selectedText); -} - -void Editor::CopyText(int length, const char *text) { - SelectionText selectedText; - selectedText.Copy(std::string(text, length), - pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false); - CopyToClipboard(selectedText); -} - -void Editor::SetDragPosition(SelectionPosition newPos) { - if (newPos.Position() >= 0) { - newPos = MovePositionOutsideChar(newPos, 1); - posDrop = newPos; - } - if (!(posDrag == newPos)) { - caret.on = true; - if (FineTickerAvailable()) { - FineTickerCancel(tickCaret); - if ((caret.active) && (caret.period > 0) && (newPos.Position() < 0)) - FineTickerStart(tickCaret, caret.period, caret.period/10); - } else { - SetTicking(true); - } - InvalidateCaret(); - posDrag = newPos; - InvalidateCaret(); - } -} - -void Editor::DisplayCursor(Window::Cursor c) { - if (cursorMode == SC_CURSORNORMAL) - wMain.SetCursor(c); - else - wMain.SetCursor(static_cast(cursorMode)); -} - -bool Editor::DragThreshold(Point ptStart, Point ptNow) { - int xMove = static_cast(ptStart.x - ptNow.x); - int yMove = static_cast(ptStart.y - ptNow.y); - int distanceSquared = xMove * xMove + yMove * yMove; - return distanceSquared > 16; -} - -void Editor::StartDrag() { - // Always handled by subclasses - //SetMouseCapture(true); - //DisplayCursor(Window::cursorArrow); -} - -void Editor::DropAt(SelectionPosition position, const char *value, size_t lengthValue, bool moving, bool rectangular) { - //Platform::DebugPrintf("DropAt %d %d\n", inDragDrop, position); - if (inDragDrop == ddDragging) - dropWentOutside = false; - - bool positionWasInSelection = PositionInSelection(position.Position()); - - bool positionOnEdgeOfSelection = - (position == SelectionStart()) || (position == SelectionEnd()); - - if ((inDragDrop != ddDragging) || !(positionWasInSelection) || - (positionOnEdgeOfSelection && !moving)) { - - SelectionPosition selStart = SelectionStart(); - SelectionPosition selEnd = SelectionEnd(); - - UndoGroup ug(pdoc); - - SelectionPosition positionAfterDeletion = position; - if ((inDragDrop == ddDragging) && moving) { - // Remove dragged out text - if (rectangular || sel.selType == Selection::selLines) { - for (size_t r=0; r= sel.Range(r).Start()) { - if (position > sel.Range(r).End()) { - positionAfterDeletion.Add(-sel.Range(r).Length()); - } else { - positionAfterDeletion.Add(-SelectionRange(position, sel.Range(r).Start()).Length()); - } - } - } - } else { - if (position > selStart) { - positionAfterDeletion.Add(-SelectionRange(selEnd, selStart).Length()); - } - } - ClearSelection(); - } - position = positionAfterDeletion; - - std::string convertedText = Document::TransformLineEnds(value, lengthValue, pdoc->eolMode); - - if (rectangular) { - PasteRectangular(position, convertedText.c_str(), static_cast(convertedText.length())); - // Should try to select new rectangle but it may not be a rectangle now so just select the drop position - SetEmptySelection(position); - } else { - position = MovePositionOutsideChar(position, sel.MainCaret() - position.Position()); - position = SelectionPosition(InsertSpace(position.Position(), position.VirtualSpace())); - const int lengthInserted = pdoc->InsertString( - position.Position(), convertedText.c_str(), static_cast(convertedText.length())); - if (lengthInserted > 0) { - SelectionPosition posAfterInsertion = position; - posAfterInsertion.Add(lengthInserted); - SetSelection(posAfterInsertion, position); - } - } - } else if (inDragDrop == ddDragging) { - SetEmptySelection(position); - } -} - -void Editor::DropAt(SelectionPosition position, const char *value, bool moving, bool rectangular) { - DropAt(position, value, strlen(value), moving, rectangular); -} - -/** - * @return true if given position is inside the selection, - */ -bool Editor::PositionInSelection(int pos) { - pos = MovePositionOutsideChar(pos, sel.MainCaret() - pos); - for (size_t r=0; r ptPos.x) { - hit = false; - } - } - if (hit) - return true; - } - } - return false; -} - -bool Editor::PointInSelMargin(Point pt) const { - // Really means: "Point in a margin" - if (vs.fixedColumnWidth > 0) { // There is a margin - PRectangle rcSelMargin = GetClientRectangle(); - rcSelMargin.right = static_cast(vs.textStart - vs.leftMarginWidth); - rcSelMargin.left = static_cast(vs.textStart - vs.fixedColumnWidth); - return rcSelMargin.ContainsWholePixel(pt); - } else { - return false; - } -} - -Window::Cursor Editor::GetMarginCursor(Point pt) const { - int x = 0; - for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) { - if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width)) - return static_cast(vs.ms[margin].cursor); - x += vs.ms[margin].width; - } - return Window::cursorReverseArrow; -} - -void Editor::TrimAndSetSelection(int currentPos_, int anchor_) { - sel.TrimSelection(SelectionRange(currentPos_, anchor_)); - SetSelection(currentPos_, anchor_); -} - -void Editor::LineSelection(int lineCurrentPos_, int lineAnchorPos_, bool wholeLine) { - int selCurrentPos, selAnchorPos; - if (wholeLine) { - int lineCurrent_ = pdoc->LineFromPosition(lineCurrentPos_); - int lineAnchor_ = pdoc->LineFromPosition(lineAnchorPos_); - if (lineAnchorPos_ < lineCurrentPos_) { - selCurrentPos = pdoc->LineStart(lineCurrent_ + 1); - selAnchorPos = pdoc->LineStart(lineAnchor_); - } else if (lineAnchorPos_ > lineCurrentPos_) { - selCurrentPos = pdoc->LineStart(lineCurrent_); - selAnchorPos = pdoc->LineStart(lineAnchor_ + 1); - } else { // Same line, select it - selCurrentPos = pdoc->LineStart(lineAnchor_ + 1); - selAnchorPos = pdoc->LineStart(lineAnchor_); - } - } else { - if (lineAnchorPos_ < lineCurrentPos_) { - selCurrentPos = StartEndDisplayLine(lineCurrentPos_, false) + 1; - selCurrentPos = pdoc->MovePositionOutsideChar(selCurrentPos, 1); - selAnchorPos = StartEndDisplayLine(lineAnchorPos_, true); - } else if (lineAnchorPos_ > lineCurrentPos_) { - selCurrentPos = StartEndDisplayLine(lineCurrentPos_, true); - selAnchorPos = StartEndDisplayLine(lineAnchorPos_, false) + 1; - selAnchorPos = pdoc->MovePositionOutsideChar(selAnchorPos, 1); - } else { // Same line, select it - selCurrentPos = StartEndDisplayLine(lineAnchorPos_, false) + 1; - selCurrentPos = pdoc->MovePositionOutsideChar(selCurrentPos, 1); - selAnchorPos = StartEndDisplayLine(lineAnchorPos_, true); - } - } - TrimAndSetSelection(selCurrentPos, selAnchorPos); -} - -void Editor::WordSelection(int pos) { - if (pos < wordSelectAnchorStartPos) { - // Extend backward to the word containing pos. - // Skip ExtendWordSelect if the line is empty or if pos is after the last character. - // This ensures that a series of empty lines isn't counted as a single "word". - if (!pdoc->IsLineEndPosition(pos)) - pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos + 1, 1), -1); - TrimAndSetSelection(pos, wordSelectAnchorEndPos); - } else if (pos > wordSelectAnchorEndPos) { - // Extend forward to the word containing the character to the left of pos. - // Skip ExtendWordSelect if the line is empty or if pos is the first position on the line. - // This ensures that a series of empty lines isn't counted as a single "word". - if (pos > pdoc->LineStart(pdoc->LineFromPosition(pos))) - pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos - 1, -1), 1); - TrimAndSetSelection(pos, wordSelectAnchorStartPos); - } else { - // Select only the anchored word - if (pos >= originalAnchorPos) - TrimAndSetSelection(wordSelectAnchorEndPos, wordSelectAnchorStartPos); - else - TrimAndSetSelection(wordSelectAnchorStartPos, wordSelectAnchorEndPos); - } -} - -void Editor::DwellEnd(bool mouseMoved) { - if (mouseMoved) - ticksToDwell = dwellDelay; - else - ticksToDwell = SC_TIME_FOREVER; - if (dwelling && (dwellDelay < SC_TIME_FOREVER)) { - dwelling = false; - NotifyDwelling(ptMouseLast, dwelling); - } - if (FineTickerAvailable()) { - FineTickerCancel(tickDwell); - if (mouseMoved && (dwellDelay < SC_TIME_FOREVER)) { - //FineTickerStart(tickDwell, dwellDelay, dwellDelay/10); - } - } -} - -void Editor::MouseLeave() { - SetHotSpotRange(NULL); - if (!HaveMouseCapture()) { - ptMouseLast = Point(-1,-1); - DwellEnd(true); - } -} - -static bool AllowVirtualSpace(int virtualSpaceOptions, bool rectangular) { - return (!rectangular && ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0)) - || (rectangular && ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) != 0)); -} - -void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers) { - SetHoverIndicatorPoint(pt); - //Platform::DebugPrintf("ButtonDown %d %d = %d alt=%d %d\n", curTime, lastClickTime, curTime - lastClickTime, alt, inDragDrop); - ptMouseLast = pt; - const bool ctrl = (modifiers & SCI_CTRL) != 0; - const bool shift = (modifiers & SCI_SHIFT) != 0; - const bool alt = (modifiers & SCI_ALT) != 0; - SelectionPosition newPos = SPositionFromLocation(pt, false, false, AllowVirtualSpace(virtualSpaceOptions, alt)); - newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position()); - SelectionPosition newCharPos = SPositionFromLocation(pt, false, true, false); - newCharPos = MovePositionOutsideChar(newCharPos, -1); - inDragDrop = ddNone; - sel.SetMoveExtends(false); - - if (NotifyMarginClick(pt, modifiers)) - return; - - NotifyIndicatorClick(true, newPos.Position(), modifiers); - - bool inSelMargin = PointInSelMargin(pt); - // In margin ctrl+(double)click should always select everything - if (ctrl && inSelMargin) { - SelectAll(); - lastClickTime = curTime; - lastClick = pt; - return; - } - if (shift && !inSelMargin) { - SetSelection(newPos); - } - if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick, doubleClickCloseThreshold)) { - //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime); - SetMouseCapture(true); - if (FineTickerAvailable()) { - FineTickerStart(tickScroll, 100, 10); - } - if (!ctrl || !multipleSelection || (selectionType != selChar && selectionType != selWord)) - SetEmptySelection(newPos.Position()); - bool doubleClick = false; - // Stop mouse button bounce changing selection type - if (!Platform::MouseButtonBounce() || curTime != lastClickTime) { - if (inSelMargin) { - // Inside margin selection type should be either selSubLine or selWholeLine. - if (selectionType == selSubLine) { - // If it is selSubLine, we're inside a *double* click and word wrap is enabled, - // so we switch to selWholeLine in order to select whole line. - selectionType = selWholeLine; - } else if (selectionType != selSubLine && selectionType != selWholeLine) { - // If it is neither, reset selection type to line selection. - selectionType = (Wrapping() && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine; - } - } else { - if (selectionType == selChar) { - selectionType = selWord; - doubleClick = true; - } else if (selectionType == selWord) { - // Since we ended up here, we're inside a *triple* click, which should always select - // whole line regardless of word wrap being enabled or not. - selectionType = selWholeLine; - } else { - selectionType = selChar; - originalAnchorPos = sel.MainCaret(); - } - } - } - - if (selectionType == selWord) { - int charPos = originalAnchorPos; - if (sel.MainCaret() == originalAnchorPos) { - charPos = PositionFromLocation(pt, false, true); - charPos = MovePositionOutsideChar(charPos, -1); - } - - int startWord, endWord; - if ((sel.MainCaret() >= originalAnchorPos) && !pdoc->IsLineEndPosition(charPos)) { - startWord = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(charPos + 1, 1), -1); - endWord = pdoc->ExtendWordSelect(charPos, 1); - } else { - // Selecting backwards, or anchor beyond last character on line. In these cases, - // we select the word containing the character to the *left* of the anchor. - if (charPos > pdoc->LineStart(pdoc->LineFromPosition(charPos))) { - startWord = pdoc->ExtendWordSelect(charPos, -1); - endWord = pdoc->ExtendWordSelect(startWord, 1); - } else { - // Anchor at start of line; select nothing to begin with. - startWord = charPos; - endWord = charPos; - } - } - - wordSelectAnchorStartPos = startWord; - wordSelectAnchorEndPos = endWord; - wordSelectInitialCaretPos = sel.MainCaret(); - WordSelection(wordSelectInitialCaretPos); - } else if (selectionType == selSubLine || selectionType == selWholeLine) { - lineAnchorPos = newPos.Position(); - LineSelection(lineAnchorPos, lineAnchorPos, selectionType == selWholeLine); - //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos); - } else { - SetEmptySelection(sel.MainCaret()); - } - //Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos); - if (doubleClick) { - NotifyDoubleClick(pt, modifiers); - if (PositionIsHotspot(newCharPos.Position())) - NotifyHotSpotDoubleClicked(newCharPos.Position(), modifiers); - } - } else { // Single click - if (inSelMargin) { - sel.selType = Selection::selStream; - if (!shift) { - // Single click in margin: select whole line or only subline if word wrap is enabled - lineAnchorPos = newPos.Position(); - selectionType = (Wrapping() && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine; - LineSelection(lineAnchorPos, lineAnchorPos, selectionType == selWholeLine); - } else { - // Single shift+click in margin: select from line anchor to clicked line - if (sel.MainAnchor() > sel.MainCaret()) - lineAnchorPos = sel.MainAnchor() - 1; - else - lineAnchorPos = sel.MainAnchor(); - // Reset selection type if there is an empty selection. - // This ensures that we don't end up stuck in previous selection mode, which is no longer valid. - // Otherwise, if there's a non empty selection, reset selection type only if it differs from selSubLine and selWholeLine. - // This ensures that we continue selecting in the same selection mode. - if (sel.Empty() || (selectionType != selSubLine && selectionType != selWholeLine)) - selectionType = (Wrapping() && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine; - LineSelection(newPos.Position(), lineAnchorPos, selectionType == selWholeLine); - } - - SetDragPosition(SelectionPosition(invalidPosition)); - SetMouseCapture(true); - if (FineTickerAvailable()) { - FineTickerStart(tickScroll, 100, 10); - } - } else { - if (PointIsHotspot(pt)) { - NotifyHotSpotClicked(newCharPos.Position(), modifiers); - hotSpotClickPos = newCharPos.Position(); - } - if (!shift) { - if (PointInSelection(pt) && !SelectionEmpty()) - inDragDrop = ddInitial; - else - inDragDrop = ddNone; - } - SetMouseCapture(true); - if (FineTickerAvailable()) { - FineTickerStart(tickScroll, 100, 10); - } - if (inDragDrop != ddInitial) { - SetDragPosition(SelectionPosition(invalidPosition)); - if (!shift) { - if (ctrl && multipleSelection) { - SelectionRange range(newPos); - sel.TentativeSelection(range); - InvalidateSelection(range, true); - } else { - InvalidateSelection(SelectionRange(newPos), true); - if (sel.Count() > 1) - Redraw(); - if ((sel.Count() > 1) || (sel.selType != Selection::selStream)) - sel.Clear(); - sel.selType = alt ? Selection::selRectangle : Selection::selStream; - SetSelection(newPos, newPos); - } - } - SelectionPosition anchorCurrent = newPos; - if (shift) - anchorCurrent = sel.IsRectangular() ? - sel.Rectangular().anchor : sel.RangeMain().anchor; - sel.selType = alt ? Selection::selRectangle : Selection::selStream; - selectionType = selChar; - originalAnchorPos = sel.MainCaret(); - sel.Rectangular() = SelectionRange(newPos, anchorCurrent); - SetRectangularRange(); - } - } - } - lastClickTime = curTime; - lastClick = pt; - lastXChosen = static_cast(pt.x) + xOffset; - ShowCaretAtCurrentPosition(); -} - -void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) { - return ButtonDownWithModifiers(pt, curTime, ModifierFlags(shift, ctrl, alt)); -} - -bool Editor::PositionIsHotspot(int position) const { - return vs.styles[static_cast(pdoc->StyleAt(position))].hotspot; -} - -bool Editor::PointIsHotspot(Point pt) { - int pos = PositionFromLocation(pt, true, true); - if (pos == INVALID_POSITION) - return false; - return PositionIsHotspot(pos); -} - -void Editor::SetHoverIndicatorPosition(int position) { - int hoverIndicatorPosPrev = hoverIndicatorPos; - hoverIndicatorPos = INVALID_POSITION; - if (vs.indicatorsDynamic == 0) - return; - if (position != INVALID_POSITION) { - for (Decoration *deco = pdoc->decorations.root; deco; deco = deco->next) { - if (vs.indicators[deco->indicator].IsDynamic()) { - if (pdoc->decorations.ValueAt(deco->indicator, position)) { - hoverIndicatorPos = position; - } - } - } - } - if (hoverIndicatorPosPrev != hoverIndicatorPos) { - if (hoverIndicatorPosPrev != INVALID_POSITION) - InvalidateRange(hoverIndicatorPosPrev, hoverIndicatorPosPrev + 1); - if (hoverIndicatorPos != INVALID_POSITION) - InvalidateRange(hoverIndicatorPos, hoverIndicatorPos + 1); - } -} - -void Editor::SetHoverIndicatorPoint(Point pt) { - if (vs.indicatorsDynamic == 0) { - SetHoverIndicatorPosition(INVALID_POSITION); - } else { - SetHoverIndicatorPosition(PositionFromLocation(pt, true, true)); - } -} - -void Editor::SetHotSpotRange(Point *pt) { - if (pt) { - int pos = PositionFromLocation(*pt, false, true); - - // If we don't limit this to word characters then the - // range can encompass more than the run range and then - // the underline will not be drawn properly. - Range hsNew; - hsNew.start = pdoc->ExtendStyleRange(pos, -1, vs.hotspotSingleLine); - hsNew.end = pdoc->ExtendStyleRange(pos, 1, vs.hotspotSingleLine); - - // Only invalidate the range if the hotspot range has changed... - if (!(hsNew == hotspot)) { - if (hotspot.Valid()) { - InvalidateRange(hotspot.start, hotspot.end); - } - hotspot = hsNew; - InvalidateRange(hotspot.start, hotspot.end); - } - } else { - if (hotspot.Valid()) { - InvalidateRange(hotspot.start, hotspot.end); - } - hotspot = Range(invalidPosition); - } -} - -Range Editor::GetHotSpotRange() const { - return hotspot; -} - -void Editor::ButtonMoveWithModifiers(Point pt, int modifiers) { - if ((ptMouseLast.x != pt.x) || (ptMouseLast.y != pt.y)) { - DwellEnd(true); - } - - SelectionPosition movePos = SPositionFromLocation(pt, false, false, - AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular())); - movePos = MovePositionOutsideChar(movePos, sel.MainCaret() - movePos.Position()); - - if (inDragDrop == ddInitial) { - if (DragThreshold(ptMouseLast, pt)) { - SetMouseCapture(false); - if (FineTickerAvailable()) { - FineTickerCancel(tickScroll); - } - SetDragPosition(movePos); - CopySelectionRange(&drag); - StartDrag(); - } - return; - } - - ptMouseLast = pt; - PRectangle rcClient = GetClientRectangle(); - Point ptOrigin = GetVisibleOriginInMain(); - rcClient.Move(0, -ptOrigin.y); - if (FineTickerAvailable() && (dwellDelay < SC_TIME_FOREVER) && rcClient.Contains(pt)) { - FineTickerStart(tickDwell, dwellDelay, dwellDelay/10); - } - //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y); - if (HaveMouseCapture()) { - - // Slow down autoscrolling/selection - autoScrollTimer.ticksToWait -= timer.tickSize; - if (autoScrollTimer.ticksToWait > 0) - return; - autoScrollTimer.ticksToWait = autoScrollDelay; - - // Adjust selection - if (posDrag.IsValid()) { - SetDragPosition(movePos); - } else { - if (selectionType == selChar) { - if (sel.selType == Selection::selStream && (modifiers & SCI_ALT) && mouseSelectionRectangularSwitch) { - sel.selType = Selection::selRectangle; - } - if (sel.IsRectangular()) { - sel.Rectangular() = SelectionRange(movePos, sel.Rectangular().anchor); - SetSelection(movePos, sel.RangeMain().anchor); - } else if (sel.Count() > 1) { - InvalidateSelection(sel.RangeMain(), false); - SelectionRange range(movePos, sel.RangeMain().anchor); - sel.TentativeSelection(range); - InvalidateSelection(range, true); - } else { - SetSelection(movePos, sel.RangeMain().anchor); - } - } else if (selectionType == selWord) { - // Continue selecting by word - if (movePos.Position() == wordSelectInitialCaretPos) { // Didn't move - // No need to do anything. Previously this case was lumped - // in with "Moved forward", but that can be harmful in this - // case: a handler for the NotifyDoubleClick re-adjusts - // the selection for a fancier definition of "word" (for - // example, in Perl it is useful to include the leading - // '$', '%' or '@' on variables for word selection). In this - // the ButtonMove() called via Tick() for auto-scrolling - // could result in the fancier word selection adjustment - // being unmade. - } else { - wordSelectInitialCaretPos = -1; - WordSelection(movePos.Position()); - } - } else { - // Continue selecting by line - LineSelection(movePos.Position(), lineAnchorPos, selectionType == selWholeLine); - } - } - - // Autoscroll - int lineMove = DisplayFromPosition(movePos.Position()); - if (pt.y > rcClient.bottom) { - ScrollTo(lineMove - LinesOnScreen() + 1); - Redraw(); - } else if (pt.y < rcClient.top) { - ScrollTo(lineMove); - Redraw(); - } - EnsureCaretVisible(false, false, true); - - if (hotspot.Valid() && !PointIsHotspot(pt)) - SetHotSpotRange(NULL); - - if (hotSpotClickPos != INVALID_POSITION && PositionFromLocation(pt,true,true) != hotSpotClickPos) { - if (inDragDrop == ddNone) { - DisplayCursor(Window::cursorText); - } - hotSpotClickPos = INVALID_POSITION; - } - - } else { - if (vs.fixedColumnWidth > 0) { // There is a margin - if (PointInSelMargin(pt)) { - DisplayCursor(GetMarginCursor(pt)); - SetHotSpotRange(NULL); - return; // No need to test for selection - } - } - // Display regular (drag) cursor over selection - if (PointInSelection(pt) && !SelectionEmpty()) { - DisplayCursor(Window::cursorArrow); - } else { - SetHoverIndicatorPoint(pt); - if (PointIsHotspot(pt)) { - DisplayCursor(Window::cursorHand); - SetHotSpotRange(&pt); - } else { - if (hoverIndicatorPos != invalidPosition) - DisplayCursor(Window::cursorHand); - else - DisplayCursor(Window::cursorText); - SetHotSpotRange(NULL); - } - } - } -} - -void Editor::ButtonMove(Point pt) { - ButtonMoveWithModifiers(pt, 0); -} - -void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { - //Platform::DebugPrintf("ButtonUp %d %d\n", HaveMouseCapture(), inDragDrop); - SelectionPosition newPos = SPositionFromLocation(pt, false, false, - AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular())); - if (hoverIndicatorPos != INVALID_POSITION) - InvalidateRange(newPos.Position(), newPos.Position() + 1); - newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position()); - if (inDragDrop == ddInitial) { - inDragDrop = ddNone; - SetEmptySelection(newPos); - selectionType = selChar; - originalAnchorPos = sel.MainCaret(); - } - if (hotSpotClickPos != INVALID_POSITION && PointIsHotspot(pt)) { - hotSpotClickPos = INVALID_POSITION; - SelectionPosition newCharPos = SPositionFromLocation(pt, false, true, false); - newCharPos = MovePositionOutsideChar(newCharPos, -1); - NotifyHotSpotReleaseClick(newCharPos.Position(), ctrl ? SCI_CTRL : 0); - } - if (HaveMouseCapture()) { - if (PointInSelMargin(pt)) { - DisplayCursor(GetMarginCursor(pt)); - } else { - DisplayCursor(Window::cursorText); - SetHotSpotRange(NULL); - } - ptMouseLast = pt; - SetMouseCapture(false); - if (FineTickerAvailable()) { - FineTickerCancel(tickScroll); - } - NotifyIndicatorClick(false, newPos.Position(), 0); - if (inDragDrop == ddDragging) { - SelectionPosition selStart = SelectionStart(); - SelectionPosition selEnd = SelectionEnd(); - if (selStart < selEnd) { - if (drag.Length()) { - const int length = static_cast(drag.Length()); - if (ctrl) { - const int lengthInserted = pdoc->InsertString( - newPos.Position(), drag.Data(), length); - if (lengthInserted > 0) { - SetSelection(newPos.Position(), newPos.Position() + lengthInserted); - } - } else if (newPos < selStart) { - pdoc->DeleteChars(selStart.Position(), static_cast(drag.Length())); - const int lengthInserted = pdoc->InsertString( - newPos.Position(), drag.Data(), length); - if (lengthInserted > 0) { - SetSelection(newPos.Position(), newPos.Position() + lengthInserted); - } - } else if (newPos > selEnd) { - pdoc->DeleteChars(selStart.Position(), static_cast(drag.Length())); - newPos.Add(-static_cast(drag.Length())); - const int lengthInserted = pdoc->InsertString( - newPos.Position(), drag.Data(), length); - if (lengthInserted > 0) { - SetSelection(newPos.Position(), newPos.Position() + lengthInserted); - } - } else { - SetEmptySelection(newPos.Position()); - } - drag.Clear(); - } - selectionType = selChar; - } - } else { - if (selectionType == selChar) { - if (sel.Count() > 1) { - sel.RangeMain() = - SelectionRange(newPos, sel.Range(sel.Count() - 1).anchor); - InvalidateSelection(sel.RangeMain(), true); - } else { - SetSelection(newPos, sel.RangeMain().anchor); - } - } - sel.CommitTentative(); - } - SetRectangularRange(); - lastClickTime = curTime; - lastClick = pt; - lastXChosen = static_cast(pt.x) + xOffset; - if (sel.selType == Selection::selStream) { - SetLastXChosen(); - } - inDragDrop = ddNone; - EnsureCaretVisible(false); - } -} - -// Called frequently to perform background UI including -// caret blinking and automatic scrolling. -void Editor::Tick() { - if (HaveMouseCapture()) { - // Auto scroll - ButtonMove(ptMouseLast); - } - if (caret.period > 0) { - timer.ticksToWait -= timer.tickSize; - if (timer.ticksToWait <= 0) { - caret.on = !caret.on; - timer.ticksToWait = caret.period; - if (caret.active) { - InvalidateCaret(); - } - } - } - if (horizontalScrollBarVisible && trackLineWidth && (view.lineWidthMaxSeen > scrollWidth)) { - scrollWidth = view.lineWidthMaxSeen; - SetScrollBars(); - } - if ((dwellDelay < SC_TIME_FOREVER) && - (ticksToDwell > 0) && - (!HaveMouseCapture()) && - (ptMouseLast.y >= 0)) { - ticksToDwell -= timer.tickSize; - if (ticksToDwell <= 0) { - dwelling = true; - NotifyDwelling(ptMouseLast, dwelling); - } - } -} - -bool Editor::Idle() { - - bool idleDone; - - bool wrappingDone = !Wrapping(); - - if (!wrappingDone) { - // Wrap lines during idle. - WrapLines(wsIdle); - // No more wrapping - if (!wrapPending.NeedsWrap()) - wrappingDone = true; - } - - // Add more idle things to do here, but make sure idleDone is - // set correctly before the function returns. returning - // false will stop calling this idle function until SetIdle() is - // called again. - - idleDone = wrappingDone; // && thatDone && theOtherThingDone... - - return !idleDone; -} - -void Editor::SetTicking(bool) { - // SetTicking is deprecated. In the past it was pure virtual and was overridden in each - // derived platform class but fine grained timers should now be implemented. - // Either way, execution should not arrive here so assert failure. - assert(false); -} - -void Editor::TickFor(TickReason reason) { - switch (reason) { - case tickCaret: - caret.on = !caret.on; - if (caret.active) { - InvalidateCaret(); - } - break; - case tickScroll: - // Auto scroll - ButtonMove(ptMouseLast); - break; - case tickWiden: - SetScrollBars(); - FineTickerCancel(tickWiden); - break; - case tickDwell: - if ((!HaveMouseCapture()) && - (ptMouseLast.y >= 0)) { - dwelling = true; - NotifyDwelling(ptMouseLast, dwelling); - } - FineTickerCancel(tickDwell); - break; - default: - // tickPlatform handled by subclass - break; - } -} - -bool Editor::FineTickerAvailable() { - return false; -} - -// FineTickerStart is be overridden by subclasses that support fine ticking so -// this method should never be called. -bool Editor::FineTickerRunning(TickReason) { - assert(false); - return false; -} - -// FineTickerStart is be overridden by subclasses that support fine ticking so -// this method should never be called. -void Editor::FineTickerStart(TickReason, int, int) { - assert(false); -} - -// FineTickerCancel is be overridden by subclasses that support fine ticking so -// this method should never be called. -void Editor::FineTickerCancel(TickReason) { - assert(false); -} - -void Editor::SetFocusState(bool focusState) { - hasFocus = focusState; - NotifyFocus(hasFocus); - if (!hasFocus) { - CancelModes(); - } - ShowCaretAtCurrentPosition(); -} - -int Editor::PositionAfterArea(PRectangle rcArea) const { - // The start of the document line after the display line after the area - // This often means that the line after a modification is restyled which helps - // detect multiline comment additions and heals single line comments - int lineAfter = TopLineOfMain() + static_cast(rcArea.bottom - 1) / vs.lineHeight + 1; - if (lineAfter < cs.LinesDisplayed()) - return pdoc->LineStart(cs.DocFromDisplay(lineAfter) + 1); - else - return pdoc->Length(); -} - -// Style to a position within the view. If this causes a change at end of last line then -// affects later lines so style all the viewed text. -void Editor::StyleToPositionInView(Position pos) { - int endWindow = PositionAfterArea(GetClientDrawingRectangle()); - if (pos > endWindow) - pos = endWindow; - int styleAtEnd = pdoc->StyleAt(pos-1); - pdoc->EnsureStyledTo(pos); - if ((endWindow > pos) && (styleAtEnd != pdoc->StyleAt(pos-1))) { - // Style at end of line changed so is multi-line change like starting a comment - // so require rest of window to be styled. - DiscardOverdraw(); // Prepared bitmaps may be invalid - // DiscardOverdraw may have truncated client drawing area so recalculate endWindow - endWindow = PositionAfterArea(GetClientDrawingRectangle()); - pdoc->EnsureStyledTo(endWindow); - } -} - -void Editor::IdleWork() { - // Style the line after the modification as this allows modifications that change just the - // line of the modification to heal instead of propagating to the rest of the window. - if (workNeeded.items & WorkNeeded::workStyle) - StyleToPositionInView(pdoc->LineStart(pdoc->LineFromPosition(workNeeded.upTo) + 2)); - - NotifyUpdateUI(); - workNeeded.Reset(); -} - -void Editor::QueueIdleWork(WorkNeeded::workItems items, int upTo) { - workNeeded.Need(items, upTo); -} - -bool Editor::PaintContains(PRectangle rc) { - if (rc.Empty()) { - return true; - } else { - return rcPaint.Contains(rc); - } -} - -bool Editor::PaintContainsMargin() { - if (wMargin.GetID()) { - // With separate margin view, paint of text view - // never contains margin. - return false; - } - PRectangle rcSelMargin = GetClientRectangle(); - rcSelMargin.right = static_cast(vs.textStart); - return PaintContains(rcSelMargin); -} - -void Editor::CheckForChangeOutsidePaint(Range r) { - if (paintState == painting && !paintingAllText) { - //Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end); - if (!r.Valid()) - return; - - PRectangle rcRange = RectangleFromRange(r, 0); - PRectangle rcText = GetTextRectangle(); - if (rcRange.top < rcText.top) { - rcRange.top = rcText.top; - } - if (rcRange.bottom > rcText.bottom) { - rcRange.bottom = rcText.bottom; - } - - if (!PaintContains(rcRange)) { - AbandonPaint(); - paintAbandonedByStyling = true; - } - } -} - -void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) { - if ((pos0 != braces[0]) || (pos1 != braces[1]) || (matchStyle != bracesMatchStyle)) { - if ((braces[0] != pos0) || (matchStyle != bracesMatchStyle)) { - CheckForChangeOutsidePaint(Range(braces[0])); - CheckForChangeOutsidePaint(Range(pos0)); - braces[0] = pos0; - } - if ((braces[1] != pos1) || (matchStyle != bracesMatchStyle)) { - CheckForChangeOutsidePaint(Range(braces[1])); - CheckForChangeOutsidePaint(Range(pos1)); - braces[1] = pos1; - } - bracesMatchStyle = matchStyle; - if (paintState == notPainting) { - Redraw(); - } - } -} - -void Editor::SetAnnotationHeights(int start, int end) { - if (vs.annotationVisible) { - RefreshStyleData(); - bool changedHeight = false; - for (int line=start; lineLinesTotal(); line++) { - int linesWrapped = 1; - if (Wrapping()) { - AutoSurface surface(this); - AutoLineLayout ll(view.llc, view.RetrieveLineLayout(line, *this)); - if (surface && ll) { - view.LayoutLine(*this, line, surface, vs, ll, wrapWidth); - linesWrapped = ll->lines; - } - } - if (cs.SetHeight(line, pdoc->AnnotationLines(line) + linesWrapped)) - changedHeight = true; - } - if (changedHeight) { - Redraw(); - } - } -} - -void Editor::SetDocPointer(Document *document) { - //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document); - pdoc->RemoveWatcher(this, 0); - pdoc->Release(); - if (document == NULL) { - pdoc = new Document(); - } else { - pdoc = document; - } - pdoc->AddRef(); - - // Ensure all positions within document - sel.Clear(); - targetStart = 0; - targetEnd = 0; - - braces[0] = invalidPosition; - braces[1] = invalidPosition; - - vs.ReleaseAllExtendedStyles(); - - SetRepresentations(); - - // Reset the contraction state to fully shown. - cs.Clear(); - cs.InsertLines(0, pdoc->LinesTotal() - 1); - SetAnnotationHeights(0, pdoc->LinesTotal()); - view.llc.Deallocate(); - NeedWrapping(); - - hotspot = Range(invalidPosition); - hoverIndicatorPos = invalidPosition; - - view.ClearAllTabstops(); - - pdoc->AddWatcher(this, 0); - SetScrollBars(); - Redraw(); -} - -void Editor::SetAnnotationVisible(int visible) { - if (vs.annotationVisible != visible) { - bool changedFromOrToHidden = ((vs.annotationVisible != 0) != (visible != 0)); - vs.annotationVisible = visible; - if (changedFromOrToHidden) { - int dir = vs.annotationVisible ? 1 : -1; - for (int line=0; lineLinesTotal(); line++) { - int annotationLines = pdoc->AnnotationLines(line); - if (annotationLines > 0) { - cs.SetHeight(line, cs.GetHeight(line) + annotationLines * dir); - } - } - } - Redraw(); - } -} - -/** - * Recursively expand a fold, making lines visible except where they have an unexpanded parent. - */ -int Editor::ExpandLine(int line) { - int lineMaxSubord = pdoc->GetLastChild(line); - line++; - while (line <= lineMaxSubord) { - cs.SetVisible(line, line, true); - int level = pdoc->GetLevel(line); - if (level & SC_FOLDLEVELHEADERFLAG) { - if (cs.GetExpanded(line)) { - line = ExpandLine(line); - } else { - line = pdoc->GetLastChild(line); - } - } - line++; - } - return lineMaxSubord; -} - -void Editor::SetFoldExpanded(int lineDoc, bool expanded) { - if (cs.SetExpanded(lineDoc, expanded)) { - RedrawSelMargin(); - } -} - -void Editor::FoldLine(int line, int action) { - if (line >= 0) { - if (action == SC_FOLDACTION_TOGGLE) { - if ((pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) == 0) { - line = pdoc->GetFoldParent(line); - if (line < 0) - return; - } - action = (cs.GetExpanded(line)) ? SC_FOLDACTION_CONTRACT : SC_FOLDACTION_EXPAND; - } - - if (action == SC_FOLDACTION_CONTRACT) { - int lineMaxSubord = pdoc->GetLastChild(line); - if (lineMaxSubord > line) { - cs.SetExpanded(line, 0); - cs.SetVisible(line + 1, lineMaxSubord, false); - - int lineCurrent = pdoc->LineFromPosition(sel.MainCaret()); - if (lineCurrent > line && lineCurrent <= lineMaxSubord) { - // This does not re-expand the fold - EnsureCaretVisible(); - } - } - - } else { - if (!(cs.GetVisible(line))) { - EnsureLineVisible(line, false); - GoToLine(line); - } - cs.SetExpanded(line, 1); - ExpandLine(line); - } - - SetScrollBars(); - Redraw(); - } -} - -void Editor::FoldExpand(int line, int action, int level) { - bool expanding = action == SC_FOLDACTION_EXPAND; - if (action == SC_FOLDACTION_TOGGLE) { - expanding = !cs.GetExpanded(line); - } - SetFoldExpanded(line, expanding); - if (expanding && (cs.HiddenLines() == 0)) - // Nothing to do - return; - int lineMaxSubord = pdoc->GetLastChild(line, level & SC_FOLDLEVELNUMBERMASK); - line++; - cs.SetVisible(line, lineMaxSubord, expanding); - while (line <= lineMaxSubord) { - int levelLine = pdoc->GetLevel(line); - if (levelLine & SC_FOLDLEVELHEADERFLAG) { - SetFoldExpanded(line, expanding); - } - line++; - } - SetScrollBars(); - Redraw(); -} - -int Editor::ContractedFoldNext(int lineStart) const { - for (int line = lineStart; lineLinesTotal();) { - if (!cs.GetExpanded(line) && (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG)) - return line; - line = cs.ContractedNext(line+1); - if (line < 0) - return -1; - } - - return -1; -} - -/** - * Recurse up from this line to find any folds that prevent this line from being visible - * and unfold them all. - */ -void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) { - - // In case in need of wrapping to ensure DisplayFromDoc works. - if (lineDoc >= wrapPending.start) - WrapLines(wsAll); - - if (!cs.GetVisible(lineDoc)) { - // Back up to find a non-blank line - int lookLine = lineDoc; - int lookLineLevel = pdoc->GetLevel(lookLine); - while ((lookLine > 0) && (lookLineLevel & SC_FOLDLEVELWHITEFLAG)) { - lookLineLevel = pdoc->GetLevel(--lookLine); - } - int lineParent = pdoc->GetFoldParent(lookLine); - if (lineParent < 0) { - // Backed up to a top level line, so try to find parent of initial line - lineParent = pdoc->GetFoldParent(lineDoc); - } - if (lineParent >= 0) { - if (lineDoc != lineParent) - EnsureLineVisible(lineParent, enforcePolicy); - if (!cs.GetExpanded(lineParent)) { - cs.SetExpanded(lineParent, 1); - ExpandLine(lineParent); - } - } - SetScrollBars(); - Redraw(); - } - if (enforcePolicy) { - int lineDisplay = cs.DisplayFromDoc(lineDoc); - if (visiblePolicy & VISIBLE_SLOP) { - if ((topLine > lineDisplay) || ((visiblePolicy & VISIBLE_STRICT) && (topLine + visibleSlop > lineDisplay))) { - SetTopLine(Platform::Clamp(lineDisplay - visibleSlop, 0, MaxScrollPos())); - SetVerticalScrollPos(); - Redraw(); - } else if ((lineDisplay > topLine + LinesOnScreen() - 1) || - ((visiblePolicy & VISIBLE_STRICT) && (lineDisplay > topLine + LinesOnScreen() - 1 - visibleSlop))) { - SetTopLine(Platform::Clamp(lineDisplay - LinesOnScreen() + 1 + visibleSlop, 0, MaxScrollPos())); - SetVerticalScrollPos(); - Redraw(); - } - } else { - if ((topLine > lineDisplay) || (lineDisplay > topLine + LinesOnScreen() - 1) || (visiblePolicy & VISIBLE_STRICT)) { - SetTopLine(Platform::Clamp(lineDisplay - LinesOnScreen() / 2 + 1, 0, MaxScrollPos())); - SetVerticalScrollPos(); - Redraw(); - } - } - } -} - -void Editor::FoldAll(int action) { - pdoc->EnsureStyledTo(pdoc->Length()); - int maxLine = pdoc->LinesTotal(); - bool expanding = action == SC_FOLDACTION_EXPAND; - if (action == SC_FOLDACTION_TOGGLE) { - // Discover current state - for (int lineSeek = 0; lineSeek < maxLine; lineSeek++) { - if (pdoc->GetLevel(lineSeek) & SC_FOLDLEVELHEADERFLAG) { - expanding = !cs.GetExpanded(lineSeek); - break; - } - } - } - if (expanding) { - cs.SetVisible(0, maxLine-1, true); - for (int line = 0; line < maxLine; line++) { - int levelLine = pdoc->GetLevel(line); - if (levelLine & SC_FOLDLEVELHEADERFLAG) { - SetFoldExpanded(line, true); - } - } - } else { - for (int line = 0; line < maxLine; line++) { - int level = pdoc->GetLevel(line); - if ((level & SC_FOLDLEVELHEADERFLAG) && - (SC_FOLDLEVELBASE == (level & SC_FOLDLEVELNUMBERMASK))) { - SetFoldExpanded(line, false); - int lineMaxSubord = pdoc->GetLastChild(line, -1); - if (lineMaxSubord > line) { - cs.SetVisible(line + 1, lineMaxSubord, false); - } - } - } - } - SetScrollBars(); - Redraw(); -} - -void Editor::FoldChanged(int line, int levelNow, int levelPrev) { - if (levelNow & SC_FOLDLEVELHEADERFLAG) { - if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) { - // Adding a fold point. - if (cs.SetExpanded(line, true)) { - RedrawSelMargin(); - } - FoldExpand(line, SC_FOLDACTION_EXPAND, levelPrev); - } - } else if (levelPrev & SC_FOLDLEVELHEADERFLAG) { - if (!cs.GetExpanded(line)) { - // Removing the fold from one that has been contracted so should expand - // otherwise lines are left invisible with no way to make them visible - if (cs.SetExpanded(line, true)) { - RedrawSelMargin(); - } - FoldExpand(line, SC_FOLDACTION_EXPAND, levelPrev); - } - } - if (!(levelNow & SC_FOLDLEVELWHITEFLAG) && - ((levelPrev & SC_FOLDLEVELNUMBERMASK) > (levelNow & SC_FOLDLEVELNUMBERMASK))) { - if (cs.HiddenLines()) { - // See if should still be hidden - int parentLine = pdoc->GetFoldParent(line); - if ((parentLine < 0) || (cs.GetExpanded(parentLine) && cs.GetVisible(parentLine))) { - cs.SetVisible(line, line, true); - SetScrollBars(); - Redraw(); - } - } - } -} - -void Editor::NeedShown(int pos, int len) { - if (foldAutomatic & SC_AUTOMATICFOLD_SHOW) { - int lineStart = pdoc->LineFromPosition(pos); - int lineEnd = pdoc->LineFromPosition(pos+len); - for (int line = lineStart; line <= lineEnd; line++) { - EnsureLineVisible(line, false); - } - } else { - NotifyNeedShown(pos, len); - } -} - -int Editor::GetTag(char *tagValue, int tagNumber) { - const char *text = 0; - int length = 0; - if ((tagNumber >= 1) && (tagNumber <= 9)) { - char name[3] = "\\?"; - name[1] = static_cast(tagNumber + '0'); - length = 2; - text = pdoc->SubstituteByPosition(name, &length); - } - if (tagValue) { - if (text) - memcpy(tagValue, text, length + 1); - else - *tagValue = '\0'; - } - return length; -} - -int Editor::ReplaceTarget(bool replacePatterns, const char *text, int length) { - UndoGroup ug(pdoc); - if (length == -1) - length = istrlen(text); - if (replacePatterns) { - text = pdoc->SubstituteByPosition(text, &length); - if (!text) { - return 0; - } - } - if (targetStart != targetEnd) - pdoc->DeleteChars(targetStart, targetEnd - targetStart); - targetEnd = targetStart; - const int lengthInserted = pdoc->InsertString(targetStart, text, length); - targetEnd = targetStart + lengthInserted; - return length; -} - -bool Editor::IsUnicodeMode() const { - return pdoc && (SC_CP_UTF8 == pdoc->dbcsCodePage); -} - -int Editor::CodePage() const { - if (pdoc) - return pdoc->dbcsCodePage; - else - return 0; -} - -int Editor::WrapCount(int line) { - AutoSurface surface(this); - AutoLineLayout ll(view.llc, view.RetrieveLineLayout(line, *this)); - - if (surface && ll) { - view.LayoutLine(*this, line, surface, vs, ll, wrapWidth); - return ll->lines; - } else { - return 1; - } -} - -void Editor::AddStyledText(char *buffer, int appendLength) { - // The buffer consists of alternating character bytes and style bytes - int textLength = appendLength / 2; - std::string text(textLength, '\0'); - int i; - for (i = 0; i < textLength; i++) { - text[i] = buffer[i*2]; - } - const int lengthInserted = pdoc->InsertString(CurrentPosition(), text.c_str(), textLength); - for (i = 0; i < textLength; i++) { - text[i] = buffer[i*2+1]; - } - pdoc->StartStyling(CurrentPosition(), static_cast(0xff)); - pdoc->SetStyles(textLength, text.c_str()); - SetEmptySelection(sel.MainCaret() + lengthInserted); -} - -static bool ValidMargin(uptr_t wParam) { - return wParam <= SC_MAX_MARGIN; -} - -static char *CharPtrFromSPtr(sptr_t lParam) { - return reinterpret_cast(lParam); -} - -void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { - vs.EnsureStyle(wParam); - switch (iMessage) { - case SCI_STYLESETFORE: - vs.styles[wParam].fore = ColourDesired(static_cast(lParam)); - break; - case SCI_STYLESETBACK: - vs.styles[wParam].back = ColourDesired(static_cast(lParam)); - break; - case SCI_STYLESETBOLD: - vs.styles[wParam].weight = lParam != 0 ? SC_WEIGHT_BOLD : SC_WEIGHT_NORMAL; - break; - case SCI_STYLESETWEIGHT: - vs.styles[wParam].weight = static_cast(lParam); - break; - case SCI_STYLESETITALIC: - vs.styles[wParam].italic = lParam != 0; - break; - case SCI_STYLESETEOLFILLED: - vs.styles[wParam].eolFilled = lParam != 0; - break; - case SCI_STYLESETSIZE: - vs.styles[wParam].size = static_cast(lParam * SC_FONT_SIZE_MULTIPLIER); - break; - case SCI_STYLESETSIZEFRACTIONAL: - vs.styles[wParam].size = static_cast(lParam); - break; - case SCI_STYLESETFONT: - if (lParam != 0) { - vs.SetStyleFontName(static_cast(wParam), CharPtrFromSPtr(lParam)); - } - break; - case SCI_STYLESETUNDERLINE: - vs.styles[wParam].underline = lParam != 0; - break; - case SCI_STYLESETCASE: - vs.styles[wParam].caseForce = static_cast(lParam); - break; - case SCI_STYLESETCHARACTERSET: - vs.styles[wParam].characterSet = static_cast(lParam); - pdoc->SetCaseFolder(NULL); - break; - case SCI_STYLESETVISIBLE: - vs.styles[wParam].visible = lParam != 0; - break; - case SCI_STYLESETCHANGEABLE: - vs.styles[wParam].changeable = lParam != 0; - break; - case SCI_STYLESETHOTSPOT: - vs.styles[wParam].hotspot = lParam != 0; - break; - } - InvalidateStyleRedraw(); -} - -sptr_t Editor::StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { - vs.EnsureStyle(wParam); - switch (iMessage) { - case SCI_STYLEGETFORE: - return vs.styles[wParam].fore.AsLong(); - case SCI_STYLEGETBACK: - return vs.styles[wParam].back.AsLong(); - case SCI_STYLEGETBOLD: - return vs.styles[wParam].weight > SC_WEIGHT_NORMAL; - case SCI_STYLEGETWEIGHT: - return vs.styles[wParam].weight; - case SCI_STYLEGETITALIC: - return vs.styles[wParam].italic ? 1 : 0; - case SCI_STYLEGETEOLFILLED: - return vs.styles[wParam].eolFilled ? 1 : 0; - case SCI_STYLEGETSIZE: - return vs.styles[wParam].size / SC_FONT_SIZE_MULTIPLIER; - case SCI_STYLEGETSIZEFRACTIONAL: - return vs.styles[wParam].size; - case SCI_STYLEGETFONT: - return StringResult(lParam, vs.styles[wParam].fontName); - case SCI_STYLEGETUNDERLINE: - return vs.styles[wParam].underline ? 1 : 0; - case SCI_STYLEGETCASE: - return static_cast(vs.styles[wParam].caseForce); - case SCI_STYLEGETCHARACTERSET: - return vs.styles[wParam].characterSet; - case SCI_STYLEGETVISIBLE: - return vs.styles[wParam].visible ? 1 : 0; - case SCI_STYLEGETCHANGEABLE: - return vs.styles[wParam].changeable ? 1 : 0; - case SCI_STYLEGETHOTSPOT: - return vs.styles[wParam].hotspot ? 1 : 0; - } - return 0; -} - -sptr_t Editor::StringResult(sptr_t lParam, const char *val) { - const size_t len = val ? strlen(val) : 0; - if (lParam) { - char *ptr = CharPtrFromSPtr(lParam); - if (val) - memcpy(ptr, val, len+1); - else - *ptr = 0; - } - return len; // Not including NUL -} - -sptr_t Editor::BytesResult(sptr_t lParam, const unsigned char *val, size_t len) { - // No NUL termination: len is number of valid/displayed bytes - if ((lParam) && (len > 0)) { - char *ptr = CharPtrFromSPtr(lParam); - if (val) - memcpy(ptr, val, len); - else - *ptr = 0; - } - return val ? len : 0; -} - -sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { - //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam); - - // Optional macro recording hook - if (recordingMacro) - NotifyMacroRecord(iMessage, wParam, lParam); - - switch (iMessage) { - - case SCI_GETTEXT: { - if (lParam == 0) - return pdoc->Length() + 1; - if (wParam == 0) - return 0; - char *ptr = CharPtrFromSPtr(lParam); - unsigned int iChar = 0; - for (; iChar < wParam - 1; iChar++) - ptr[iChar] = pdoc->CharAt(iChar); - ptr[iChar] = '\0'; - return iChar; - } - - case SCI_SETTEXT: { - if (lParam == 0) - return 0; - UndoGroup ug(pdoc); - pdoc->DeleteChars(0, pdoc->Length()); - SetEmptySelection(0); - const char *text = CharPtrFromSPtr(lParam); - pdoc->InsertString(0, text, istrlen(text)); - return 1; - } - - case SCI_GETTEXTLENGTH: - return pdoc->Length(); - - case SCI_CUT: - Cut(); - SetLastXChosen(); - break; - - case SCI_COPY: - Copy(); - break; - - case SCI_COPYALLOWLINE: - CopyAllowLine(); - break; - - case SCI_VERTICALCENTRECARET: - VerticalCentreCaret(); - break; - - case SCI_MOVESELECTEDLINESUP: - MoveSelectedLinesUp(); - break; - - case SCI_MOVESELECTEDLINESDOWN: - MoveSelectedLinesDown(); - break; - - case SCI_COPYRANGE: - CopyRangeToClipboard(static_cast(wParam), static_cast(lParam)); - break; - - case SCI_COPYTEXT: - CopyText(static_cast(wParam), CharPtrFromSPtr(lParam)); - break; - - case SCI_PASTE: - Paste(); - if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) { - SetLastXChosen(); - } - EnsureCaretVisible(); - break; - - case SCI_CLEAR: - Clear(); - SetLastXChosen(); - EnsureCaretVisible(); - break; - - case SCI_UNDO: - Undo(); - SetLastXChosen(); - break; - - case SCI_CANUNDO: - return (pdoc->CanUndo() && !pdoc->IsReadOnly()) ? 1 : 0; - - case SCI_EMPTYUNDOBUFFER: - pdoc->DeleteUndoHistory(); - return 0; - - case SCI_GETFIRSTVISIBLELINE: - return topLine; - - case SCI_SETFIRSTVISIBLELINE: - ScrollTo(static_cast(wParam)); - break; - - case SCI_GETLINE: { // Risk of overwriting the end of the buffer - int lineStart = pdoc->LineStart(static_cast(wParam)); - int lineEnd = pdoc->LineStart(static_cast(wParam + 1)); - if (lParam == 0) { - return lineEnd - lineStart; - } - char *ptr = CharPtrFromSPtr(lParam); - int iPlace = 0; - for (int iChar = lineStart; iChar < lineEnd; iChar++) { - ptr[iPlace++] = pdoc->CharAt(iChar); - } - return iPlace; - } - - case SCI_GETLINECOUNT: - if (pdoc->LinesTotal() == 0) - return 1; - else - return pdoc->LinesTotal(); - - case SCI_GETMODIFY: - return !pdoc->IsSavePoint(); - - case SCI_SETSEL: { - int nStart = static_cast(wParam); - int nEnd = static_cast(lParam); - if (nEnd < 0) - nEnd = pdoc->Length(); - if (nStart < 0) - nStart = nEnd; // Remove selection - InvalidateSelection(SelectionRange(nStart, nEnd)); - sel.Clear(); - sel.selType = Selection::selStream; - SetSelection(nEnd, nStart); - EnsureCaretVisible(); - } - break; - - case SCI_GETSELTEXT: { - SelectionText selectedText; - CopySelectionRange(&selectedText); - if (lParam == 0) { - return selectedText.LengthWithTerminator(); - } else { - char *ptr = CharPtrFromSPtr(lParam); - unsigned int iChar = 0; - if (selectedText.Length()) { - for (; iChar < selectedText.LengthWithTerminator(); iChar++) - ptr[iChar] = selectedText.Data()[iChar]; - } else { - ptr[0] = '\0'; - } - return iChar; - } - } - - case SCI_LINEFROMPOSITION: - if (static_cast(wParam) < 0) - return 0; - return pdoc->LineFromPosition(static_cast(wParam)); - - case SCI_POSITIONFROMLINE: - if (static_cast(wParam) < 0) - wParam = pdoc->LineFromPosition(SelectionStart().Position()); - if (wParam == 0) - return 0; // Even if there is no text, there is a first line that starts at 0 - if (static_cast(wParam) > pdoc->LinesTotal()) - return -1; - //if (wParam > pdoc->LineFromPosition(pdoc->Length())) // Useful test, anyway... - // return -1; - return pdoc->LineStart(static_cast(wParam)); - - // Replacement of the old Scintilla interpretation of EM_LINELENGTH - case SCI_LINELENGTH: - if ((static_cast(wParam) < 0) || - (static_cast(wParam) > pdoc->LineFromPosition(pdoc->Length()))) - return 0; - return pdoc->LineStart(static_cast(wParam) + 1) - pdoc->LineStart(static_cast(wParam)); - - case SCI_REPLACESEL: { - if (lParam == 0) - return 0; - UndoGroup ug(pdoc); - ClearSelection(); - char *replacement = CharPtrFromSPtr(lParam); - const int lengthInserted = pdoc->InsertString( - sel.MainCaret(), replacement, istrlen(replacement)); - SetEmptySelection(sel.MainCaret() + lengthInserted); - EnsureCaretVisible(); - } - break; - - case SCI_SETTARGETSTART: - targetStart = static_cast(wParam); - break; - - case SCI_GETTARGETSTART: - return targetStart; - - case SCI_SETTARGETEND: - targetEnd = static_cast(wParam); - break; - - case SCI_GETTARGETEND: - return targetEnd; - - case SCI_SETTARGETRANGE: - targetStart = static_cast(wParam); - targetEnd = static_cast(lParam); - break; - - case SCI_TARGETFROMSELECTION: - if (sel.MainCaret() < sel.MainAnchor()) { - targetStart = sel.MainCaret(); - targetEnd = sel.MainAnchor(); - } else { - targetStart = sel.MainAnchor(); - targetEnd = sel.MainCaret(); - } - break; - - case SCI_GETTARGETTEXT: { - std::string text = RangeText(targetStart, targetEnd); - return BytesResult(lParam, reinterpret_cast(text.c_str()), text.length()); - } - - case SCI_REPLACETARGET: - PLATFORM_ASSERT(lParam); - return ReplaceTarget(false, CharPtrFromSPtr(lParam), static_cast(wParam)); - - case SCI_REPLACETARGETRE: - PLATFORM_ASSERT(lParam); - return ReplaceTarget(true, CharPtrFromSPtr(lParam), static_cast(wParam)); - - case SCI_SEARCHINTARGET: - PLATFORM_ASSERT(lParam); - return SearchInTarget(CharPtrFromSPtr(lParam), static_cast(wParam)); - - case SCI_SETSEARCHFLAGS: - searchFlags = static_cast(wParam); - break; - - case SCI_GETSEARCHFLAGS: - return searchFlags; - - case SCI_GETTAG: - return GetTag(CharPtrFromSPtr(lParam), static_cast(wParam)); - - case SCI_POSITIONBEFORE: - return pdoc->MovePositionOutsideChar(static_cast(wParam) - 1, -1, true); - - case SCI_POSITIONAFTER: - return pdoc->MovePositionOutsideChar(static_cast(wParam) + 1, 1, true); - - case SCI_POSITIONRELATIVE: - return Platform::Clamp(pdoc->GetRelativePosition(static_cast(wParam), static_cast(lParam)), 0, pdoc->Length()); - - case SCI_LINESCROLL: - ScrollTo(topLine + static_cast(lParam)); - HorizontalScrollTo(xOffset + static_cast(wParam)* static_cast(vs.spaceWidth)); - return 1; - - case SCI_SETXOFFSET: - xOffset = static_cast(wParam); - ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); - SetHorizontalScrollPos(); - Redraw(); - break; - - case SCI_GETXOFFSET: - return xOffset; - - case SCI_CHOOSECARETX: - SetLastXChosen(); - break; - - case SCI_SCROLLCARET: - EnsureCaretVisible(); - break; - - case SCI_SETREADONLY: - pdoc->SetReadOnly(wParam != 0); - return 1; - - case SCI_GETREADONLY: - return pdoc->IsReadOnly(); - - case SCI_CANPASTE: - return CanPaste(); - - case SCI_POINTXFROMPOSITION: - if (lParam < 0) { - return 0; - } else { - Point pt = LocationFromPosition(static_cast(lParam)); - // Convert to view-relative - return static_cast(pt.x) - vs.textStart + vs.fixedColumnWidth; - } - - case SCI_POINTYFROMPOSITION: - if (lParam < 0) { - return 0; - } else { - Point pt = LocationFromPosition(static_cast(lParam)); - return static_cast(pt.y); - } - - case SCI_FINDTEXT: - return FindText(wParam, lParam); - - case SCI_GETTEXTRANGE: { - if (lParam == 0) - return 0; - Sci_TextRange *tr = reinterpret_cast(lParam); - int cpMax = static_cast(tr->chrg.cpMax); - if (cpMax == -1) - cpMax = pdoc->Length(); - PLATFORM_ASSERT(cpMax <= pdoc->Length()); - int len = static_cast(cpMax - tr->chrg.cpMin); // No -1 as cpMin and cpMax are referring to inter character positions - pdoc->GetCharRange(tr->lpstrText, static_cast(tr->chrg.cpMin), len); - // Spec says copied text is terminated with a NUL - tr->lpstrText[len] = '\0'; - return len; // Not including NUL - } - - case SCI_HIDESELECTION: - view.hideSelection = wParam != 0; - Redraw(); - break; - - case SCI_FORMATRANGE: - return FormatRange(wParam != 0, reinterpret_cast(lParam)); - - case SCI_GETMARGINLEFT: - return vs.leftMarginWidth; - - case SCI_GETMARGINRIGHT: - return vs.rightMarginWidth; - - case SCI_SETMARGINLEFT: - lastXChosen += static_cast(lParam) - vs.leftMarginWidth; - vs.leftMarginWidth = static_cast(lParam); - InvalidateStyleRedraw(); - break; - - case SCI_SETMARGINRIGHT: - vs.rightMarginWidth = static_cast(lParam); - InvalidateStyleRedraw(); - break; - - // Control specific mesages - - case SCI_ADDTEXT: { - if (lParam == 0) - return 0; - const int lengthInserted = pdoc->InsertString( - CurrentPosition(), CharPtrFromSPtr(lParam), static_cast(wParam)); - SetEmptySelection(sel.MainCaret() + lengthInserted); - return 0; - } - - case SCI_ADDSTYLEDTEXT: - if (lParam) - AddStyledText(CharPtrFromSPtr(lParam), static_cast(wParam)); - return 0; - - case SCI_INSERTTEXT: { - if (lParam == 0) - return 0; - int insertPos = static_cast(wParam); - if (static_cast(wParam) == -1) - insertPos = CurrentPosition(); - int newCurrent = CurrentPosition(); - char *sz = CharPtrFromSPtr(lParam); - const int lengthInserted = pdoc->InsertString(insertPos, sz, istrlen(sz)); - if (newCurrent > insertPos) - newCurrent += lengthInserted; - SetEmptySelection(newCurrent); - return 0; - } - - case SCI_CHANGEINSERTION: - PLATFORM_ASSERT(lParam); - pdoc->ChangeInsertion(CharPtrFromSPtr(lParam), static_cast(wParam)); - return 0; - - case SCI_APPENDTEXT: - pdoc->InsertString(pdoc->Length(), CharPtrFromSPtr(lParam), static_cast(wParam)); - return 0; - - case SCI_CLEARALL: - ClearAll(); - return 0; - - case SCI_DELETERANGE: - pdoc->DeleteChars(static_cast(wParam), static_cast(lParam)); - return 0; - - case SCI_CLEARDOCUMENTSTYLE: - ClearDocumentStyle(); - return 0; - - case SCI_SETUNDOCOLLECTION: - pdoc->SetUndoCollection(wParam != 0); - return 0; - - case SCI_GETUNDOCOLLECTION: - return pdoc->IsCollectingUndo(); - - case SCI_BEGINUNDOACTION: - pdoc->BeginUndoAction(); - return 0; - - case SCI_ENDUNDOACTION: - pdoc->EndUndoAction(); - return 0; - - case SCI_GETCARETPERIOD: - return caret.period; - - case SCI_SETCARETPERIOD: - CaretSetPeriod(static_cast(wParam)); - break; - - case SCI_GETWORDCHARS: - return pdoc->GetCharsOfClass(CharClassify::ccWord, reinterpret_cast(lParam)); - - case SCI_SETWORDCHARS: { - pdoc->SetDefaultCharClasses(false); - if (lParam == 0) - return 0; - pdoc->SetCharClasses(reinterpret_cast(lParam), CharClassify::ccWord); - } - break; - - case SCI_GETWHITESPACECHARS: - return pdoc->GetCharsOfClass(CharClassify::ccSpace, reinterpret_cast(lParam)); - - case SCI_SETWHITESPACECHARS: { - if (lParam == 0) - return 0; - pdoc->SetCharClasses(reinterpret_cast(lParam), CharClassify::ccSpace); - } - break; - - case SCI_GETPUNCTUATIONCHARS: - return pdoc->GetCharsOfClass(CharClassify::ccPunctuation, reinterpret_cast(lParam)); - - case SCI_SETPUNCTUATIONCHARS: { - if (lParam == 0) - return 0; - pdoc->SetCharClasses(reinterpret_cast(lParam), CharClassify::ccPunctuation); - } - break; - - case SCI_SETCHARSDEFAULT: - pdoc->SetDefaultCharClasses(true); - break; - - case SCI_GETLENGTH: - return pdoc->Length(); - - case SCI_ALLOCATE: - pdoc->Allocate(static_cast(wParam)); - break; - - case SCI_GETCHARAT: - return pdoc->CharAt(static_cast(wParam)); - - case SCI_SETCURRENTPOS: - if (sel.IsRectangular()) { - sel.Rectangular().caret.SetPosition(static_cast(wParam)); - SetRectangularRange(); - Redraw(); - } else { - SetSelection(static_cast(wParam), sel.MainAnchor()); - } - break; - - case SCI_GETCURRENTPOS: - return sel.IsRectangular() ? sel.Rectangular().caret.Position() : sel.MainCaret(); - - case SCI_SETANCHOR: - if (sel.IsRectangular()) { - sel.Rectangular().anchor.SetPosition(static_cast(wParam)); - SetRectangularRange(); - Redraw(); - } else { - SetSelection(sel.MainCaret(), static_cast(wParam)); - } - break; - - case SCI_GETANCHOR: - return sel.IsRectangular() ? sel.Rectangular().anchor.Position() : sel.MainAnchor(); - - case SCI_SETSELECTIONSTART: - SetSelection(Platform::Maximum(sel.MainCaret(), static_cast(wParam)), static_cast(wParam)); - break; - - case SCI_GETSELECTIONSTART: - return sel.LimitsForRectangularElseMain().start.Position(); - - case SCI_SETSELECTIONEND: - SetSelection(static_cast(wParam), Platform::Minimum(sel.MainAnchor(), static_cast(wParam))); - break; - - case SCI_GETSELECTIONEND: - return sel.LimitsForRectangularElseMain().end.Position(); - - case SCI_SETEMPTYSELECTION: - SetEmptySelection(static_cast(wParam)); - break; - - case SCI_SETPRINTMAGNIFICATION: - view.printParameters.magnification = static_cast(wParam); - break; - - case SCI_GETPRINTMAGNIFICATION: - return view.printParameters.magnification; - - case SCI_SETPRINTCOLOURMODE: - view.printParameters.colourMode = static_cast(wParam); - break; - - case SCI_GETPRINTCOLOURMODE: - return view.printParameters.colourMode; - - case SCI_SETPRINTWRAPMODE: - view.printParameters.wrapState = (wParam == SC_WRAP_WORD) ? eWrapWord : eWrapNone; - break; - - case SCI_GETPRINTWRAPMODE: - return view.printParameters.wrapState; - - case SCI_GETSTYLEAT: - if (static_cast(wParam) >= pdoc->Length()) - return 0; - else - return pdoc->StyleAt(static_cast(wParam)); - - case SCI_REDO: - Redo(); - break; - - case SCI_SELECTALL: - SelectAll(); - break; - - case SCI_SETSAVEPOINT: - pdoc->SetSavePoint(); - break; - - case SCI_GETSTYLEDTEXT: { - if (lParam == 0) - return 0; - Sci_TextRange *tr = reinterpret_cast(lParam); - int iPlace = 0; - for (long iChar = tr->chrg.cpMin; iChar < tr->chrg.cpMax; iChar++) { - tr->lpstrText[iPlace++] = pdoc->CharAt(static_cast(iChar)); - tr->lpstrText[iPlace++] = pdoc->StyleAt(static_cast(iChar)); - } - tr->lpstrText[iPlace] = '\0'; - tr->lpstrText[iPlace + 1] = '\0'; - return iPlace; - } - - case SCI_CANREDO: - return (pdoc->CanRedo() && !pdoc->IsReadOnly()) ? 1 : 0; - - case SCI_MARKERLINEFROMHANDLE: - return pdoc->LineFromHandle(static_cast(wParam)); - - case SCI_MARKERDELETEHANDLE: - pdoc->DeleteMarkFromHandle(static_cast(wParam)); - break; - - case SCI_GETVIEWWS: - return vs.viewWhitespace; - - case SCI_SETVIEWWS: - vs.viewWhitespace = static_cast(wParam); - Redraw(); - break; - - case SCI_GETWHITESPACESIZE: - return vs.whitespaceSize; - - case SCI_SETWHITESPACESIZE: - vs.whitespaceSize = static_cast(wParam); - Redraw(); - break; - - case SCI_POSITIONFROMPOINT: - return PositionFromLocation(Point::FromInts(static_cast(wParam) - vs.ExternalMarginWidth(), static_cast(lParam)), - false, false); - - case SCI_POSITIONFROMPOINTCLOSE: - return PositionFromLocation(Point::FromInts(static_cast(wParam) - vs.ExternalMarginWidth(), static_cast(lParam)), - true, false); - - case SCI_CHARPOSITIONFROMPOINT: - return PositionFromLocation(Point::FromInts(static_cast(wParam) - vs.ExternalMarginWidth(), static_cast(lParam)), - false, true); - - case SCI_CHARPOSITIONFROMPOINTCLOSE: - return PositionFromLocation(Point::FromInts(static_cast(wParam) - vs.ExternalMarginWidth(), static_cast(lParam)), - true, true); - - case SCI_GOTOLINE: - GoToLine(static_cast(wParam)); - break; - - case SCI_GOTOPOS: - SetEmptySelection(static_cast(wParam)); - EnsureCaretVisible(); - break; - - case SCI_GETCURLINE: { - int lineCurrentPos = pdoc->LineFromPosition(sel.MainCaret()); - int lineStart = pdoc->LineStart(lineCurrentPos); - unsigned int lineEnd = pdoc->LineStart(lineCurrentPos + 1); - if (lParam == 0) { - return 1 + lineEnd - lineStart; - } - PLATFORM_ASSERT(wParam > 0); - char *ptr = CharPtrFromSPtr(lParam); - unsigned int iPlace = 0; - for (unsigned int iChar = lineStart; iChar < lineEnd && iPlace < wParam - 1; iChar++) { - ptr[iPlace++] = pdoc->CharAt(iChar); - } - ptr[iPlace] = '\0'; - return sel.MainCaret() - lineStart; - } - - case SCI_GETENDSTYLED: - return pdoc->GetEndStyled(); - - case SCI_GETEOLMODE: - return pdoc->eolMode; - - case SCI_SETEOLMODE: - pdoc->eolMode = static_cast(wParam); - break; - - case SCI_SETLINEENDTYPESALLOWED: - if (pdoc->SetLineEndTypesAllowed(static_cast(wParam))) { - cs.Clear(); - cs.InsertLines(0, pdoc->LinesTotal() - 1); - SetAnnotationHeights(0, pdoc->LinesTotal()); - InvalidateStyleRedraw(); - } - break; - - case SCI_GETLINEENDTYPESALLOWED: - return pdoc->GetLineEndTypesAllowed(); - - case SCI_GETLINEENDTYPESACTIVE: - return pdoc->GetLineEndTypesActive(); - - case SCI_STARTSTYLING: - pdoc->StartStyling(static_cast(wParam), static_cast(lParam)); - break; - - case SCI_SETSTYLING: - pdoc->SetStyleFor(static_cast(wParam), static_cast(lParam)); - break; - - case SCI_SETSTYLINGEX: // Specify a complete styling buffer - if (lParam == 0) - return 0; - pdoc->SetStyles(static_cast(wParam), CharPtrFromSPtr(lParam)); - break; - - case SCI_SETBUFFEREDDRAW: - view.bufferedDraw = wParam != 0; - break; - - case SCI_GETBUFFEREDDRAW: - return view.bufferedDraw; - - case SCI_GETTWOPHASEDRAW: - return view.phasesDraw == EditView::phasesTwo; - - case SCI_SETTWOPHASEDRAW: - if (view.SetTwoPhaseDraw(wParam != 0)) - InvalidateStyleRedraw(); - break; - - case SCI_GETPHASESDRAW: - return view.phasesDraw; - - case SCI_SETPHASESDRAW: - if (view.SetPhasesDraw(static_cast(wParam))) - InvalidateStyleRedraw(); - break; - - case SCI_SETFONTQUALITY: - vs.extraFontFlag &= ~SC_EFF_QUALITY_MASK; - vs.extraFontFlag |= (wParam & SC_EFF_QUALITY_MASK); - InvalidateStyleRedraw(); - break; - - case SCI_GETFONTQUALITY: - return (vs.extraFontFlag & SC_EFF_QUALITY_MASK); - - case SCI_SETTABWIDTH: - if (wParam > 0) { - pdoc->tabInChars = static_cast(wParam); - if (pdoc->indentInChars == 0) - pdoc->actualIndentInChars = pdoc->tabInChars; - } - InvalidateStyleRedraw(); - break; - - case SCI_GETTABWIDTH: - return pdoc->tabInChars; - - case SCI_CLEARTABSTOPS: - if (view.ClearTabstops(static_cast(wParam))) { - DocModification mh(SC_MOD_CHANGETABSTOPS, 0, 0, 0, 0, static_cast(wParam)); - NotifyModified(pdoc, mh, NULL); - } - break; - - case SCI_ADDTABSTOP: - if (view.AddTabstop(static_cast(wParam), static_cast(lParam))) { - DocModification mh(SC_MOD_CHANGETABSTOPS, 0, 0, 0, 0, static_cast(wParam)); - NotifyModified(pdoc, mh, NULL); - } - break; - - case SCI_GETNEXTTABSTOP: - return view.GetNextTabstop(static_cast(wParam), static_cast(lParam)); - - case SCI_SETINDENT: - pdoc->indentInChars = static_cast(wParam); - if (pdoc->indentInChars != 0) - pdoc->actualIndentInChars = pdoc->indentInChars; - else - pdoc->actualIndentInChars = pdoc->tabInChars; - InvalidateStyleRedraw(); - break; - - case SCI_GETINDENT: - return pdoc->indentInChars; - - case SCI_SETUSETABS: - pdoc->useTabs = wParam != 0; - InvalidateStyleRedraw(); - break; - - case SCI_GETUSETABS: - return pdoc->useTabs; - - case SCI_SETLINEINDENTATION: - pdoc->SetLineIndentation(static_cast(wParam), static_cast(lParam)); - break; - - case SCI_GETLINEINDENTATION: - return pdoc->GetLineIndentation(static_cast(wParam)); - - case SCI_GETLINEINDENTPOSITION: - return pdoc->GetLineIndentPosition(static_cast(wParam)); - - case SCI_SETTABINDENTS: - pdoc->tabIndents = wParam != 0; - break; - - case SCI_GETTABINDENTS: - return pdoc->tabIndents; - - case SCI_SETBACKSPACEUNINDENTS: - pdoc->backspaceUnindents = wParam != 0; - break; - - case SCI_GETBACKSPACEUNINDENTS: - return pdoc->backspaceUnindents; - - case SCI_SETMOUSEDWELLTIME: - dwellDelay = static_cast(wParam); - ticksToDwell = dwellDelay; - break; - - case SCI_GETMOUSEDWELLTIME: - return dwellDelay; - - case SCI_WORDSTARTPOSITION: - return pdoc->ExtendWordSelect(static_cast(wParam), -1, lParam != 0); - - case SCI_WORDENDPOSITION: - return pdoc->ExtendWordSelect(static_cast(wParam), 1, lParam != 0); - - case SCI_SETWRAPMODE: - if (vs.SetWrapState(static_cast(wParam))) { - xOffset = 0; - ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); - InvalidateStyleRedraw(); - ReconfigureScrollBars(); - } - break; - - case SCI_GETWRAPMODE: - return vs.wrapState; - - case SCI_SETWRAPVISUALFLAGS: - if (vs.SetWrapVisualFlags(static_cast(wParam))) { - InvalidateStyleRedraw(); - ReconfigureScrollBars(); - } - break; - - case SCI_GETWRAPVISUALFLAGS: - return vs.wrapVisualFlags; - - case SCI_SETWRAPVISUALFLAGSLOCATION: - if (vs.SetWrapVisualFlagsLocation(static_cast(wParam))) { - InvalidateStyleRedraw(); - } - break; - - case SCI_GETWRAPVISUALFLAGSLOCATION: - return vs.wrapVisualFlagsLocation; - - case SCI_SETWRAPSTARTINDENT: - if (vs.SetWrapVisualStartIndent(static_cast(wParam))) { - InvalidateStyleRedraw(); - ReconfigureScrollBars(); - } - break; - - case SCI_GETWRAPSTARTINDENT: - return vs.wrapVisualStartIndent; - - case SCI_SETWRAPINDENTMODE: - if (vs.SetWrapIndentMode(static_cast(wParam))) { - InvalidateStyleRedraw(); - ReconfigureScrollBars(); - } - break; - - case SCI_GETWRAPINDENTMODE: - return vs.wrapIndentMode; - - case SCI_SETLAYOUTCACHE: - view.llc.SetLevel(static_cast(wParam)); - break; - - case SCI_GETLAYOUTCACHE: - return view.llc.GetLevel(); - - case SCI_SETPOSITIONCACHE: - view.posCache.SetSize(wParam); - break; - - case SCI_GETPOSITIONCACHE: - return view.posCache.GetSize(); - - case SCI_SETSCROLLWIDTH: - PLATFORM_ASSERT(wParam > 0); - if ((wParam > 0) && (wParam != static_cast(scrollWidth))) { - view.lineWidthMaxSeen = 0; - scrollWidth = static_cast(wParam); - SetScrollBars(); - } - break; - - case SCI_GETSCROLLWIDTH: - return scrollWidth; - - case SCI_SETSCROLLWIDTHTRACKING: - trackLineWidth = wParam != 0; - break; - - case SCI_GETSCROLLWIDTHTRACKING: - return trackLineWidth; - - case SCI_LINESJOIN: - LinesJoin(); - break; - - case SCI_LINESSPLIT: - LinesSplit(static_cast(wParam)); - break; - - case SCI_TEXTWIDTH: - PLATFORM_ASSERT(wParam < vs.styles.size()); - PLATFORM_ASSERT(lParam); - return TextWidth(static_cast(wParam), CharPtrFromSPtr(lParam)); - - case SCI_TEXTHEIGHT: - return vs.lineHeight; - - case SCI_SETENDATLASTLINE: - PLATFORM_ASSERT((wParam == 0) || (wParam == 1)); - if (endAtLastLine != (wParam != 0)) { - endAtLastLine = wParam != 0; - SetScrollBars(); - } - break; - - case SCI_GETENDATLASTLINE: - return endAtLastLine; - - case SCI_SETCARETSTICKY: - PLATFORM_ASSERT(wParam <= SC_CARETSTICKY_WHITESPACE); - if (wParam <= SC_CARETSTICKY_WHITESPACE) { - caretSticky = static_cast(wParam); - } - break; - - case SCI_GETCARETSTICKY: - return caretSticky; - - case SCI_TOGGLECARETSTICKY: - caretSticky = !caretSticky; - break; - - case SCI_GETCOLUMN: - return pdoc->GetColumn(static_cast(wParam)); - - case SCI_FINDCOLUMN: - return pdoc->FindColumn(static_cast(wParam), static_cast(lParam)); - - case SCI_SETHSCROLLBAR : - if (horizontalScrollBarVisible != (wParam != 0)) { - horizontalScrollBarVisible = wParam != 0; - SetScrollBars(); - ReconfigureScrollBars(); - } - break; - - case SCI_GETHSCROLLBAR: - return horizontalScrollBarVisible; - - case SCI_SETVSCROLLBAR: - if (verticalScrollBarVisible != (wParam != 0)) { - verticalScrollBarVisible = wParam != 0; - SetScrollBars(); - ReconfigureScrollBars(); - if (verticalScrollBarVisible) - SetVerticalScrollPos(); - } - break; - - case SCI_GETVSCROLLBAR: - return verticalScrollBarVisible; - - case SCI_SETINDENTATIONGUIDES: - vs.viewIndentationGuides = IndentView(wParam); - Redraw(); - break; - - case SCI_GETINDENTATIONGUIDES: - return vs.viewIndentationGuides; - - case SCI_SETHIGHLIGHTGUIDE: - if ((highlightGuideColumn != static_cast(wParam)) || (wParam > 0)) { - highlightGuideColumn = static_cast(wParam); - Redraw(); - } - break; - - case SCI_GETHIGHLIGHTGUIDE: - return highlightGuideColumn; - - case SCI_GETLINEENDPOSITION: - return pdoc->LineEnd(static_cast(wParam)); - - case SCI_SETCODEPAGE: - if (ValidCodePage(static_cast(wParam))) { - if (pdoc->SetDBCSCodePage(static_cast(wParam))) { - cs.Clear(); - cs.InsertLines(0, pdoc->LinesTotal() - 1); - SetAnnotationHeights(0, pdoc->LinesTotal()); - InvalidateStyleRedraw(); - SetRepresentations(); - } - } - break; - - case SCI_GETCODEPAGE: - return pdoc->dbcsCodePage; - - case SCI_SETIMEINTERACTION: - imeInteraction = static_cast(wParam); - break; - - case SCI_GETIMEINTERACTION: - return imeInteraction; - -#ifdef INCLUDE_DEPRECATED_FEATURES - case SCI_SETUSEPALETTE: - InvalidateStyleRedraw(); - break; - - case SCI_GETUSEPALETTE: - return 0; -#endif - - // Marker definition and setting - case SCI_MARKERDEFINE: - if (wParam <= MARKER_MAX) { - vs.markers[wParam].markType = static_cast(lParam); - vs.CalcLargestMarkerHeight(); - } - InvalidateStyleData(); - RedrawSelMargin(); - break; - - case SCI_MARKERSYMBOLDEFINED: - if (wParam <= MARKER_MAX) - return vs.markers[wParam].markType; - else - return 0; - - case SCI_MARKERSETFORE: - if (wParam <= MARKER_MAX) - vs.markers[wParam].fore = ColourDesired(static_cast(lParam)); - InvalidateStyleData(); - RedrawSelMargin(); - break; - case SCI_MARKERSETBACKSELECTED: - if (wParam <= MARKER_MAX) - vs.markers[wParam].backSelected = ColourDesired(static_cast(lParam)); - InvalidateStyleData(); - RedrawSelMargin(); - break; - case SCI_MARKERENABLEHIGHLIGHT: - marginView.highlightDelimiter.isEnabled = wParam == 1; - RedrawSelMargin(); - break; - case SCI_MARKERSETBACK: - if (wParam <= MARKER_MAX) - vs.markers[wParam].back = ColourDesired(static_cast(lParam)); - InvalidateStyleData(); - RedrawSelMargin(); - break; - case SCI_MARKERSETALPHA: - if (wParam <= MARKER_MAX) - vs.markers[wParam].alpha = static_cast(lParam); - InvalidateStyleRedraw(); - break; - case SCI_MARKERADD: { - int markerID = pdoc->AddMark(static_cast(wParam), static_cast(lParam)); - return markerID; - } - case SCI_MARKERADDSET: - if (lParam != 0) - pdoc->AddMarkSet(static_cast(wParam), static_cast(lParam)); - break; - - case SCI_MARKERDELETE: - pdoc->DeleteMark(static_cast(wParam), static_cast(lParam)); - break; - - case SCI_MARKERDELETEALL: - pdoc->DeleteAllMarks(static_cast(wParam)); - break; - - case SCI_MARKERGET: - return pdoc->GetMark(static_cast(wParam)); - - case SCI_MARKERNEXT: - return pdoc->MarkerNext(static_cast(wParam), static_cast(lParam)); - - case SCI_MARKERPREVIOUS: { - for (int iLine = static_cast(wParam); iLine >= 0; iLine--) { - if ((pdoc->GetMark(iLine) & lParam) != 0) - return iLine; - } - } - return -1; - - case SCI_MARKERDEFINEPIXMAP: - if (wParam <= MARKER_MAX) { - vs.markers[wParam].SetXPM(CharPtrFromSPtr(lParam)); - vs.CalcLargestMarkerHeight(); - } - InvalidateStyleData(); - RedrawSelMargin(); - break; - - case SCI_RGBAIMAGESETWIDTH: - sizeRGBAImage.x = static_cast(wParam); - break; - - case SCI_RGBAIMAGESETHEIGHT: - sizeRGBAImage.y = static_cast(wParam); - break; - - case SCI_RGBAIMAGESETSCALE: - scaleRGBAImage = static_cast(wParam); - break; - - case SCI_MARKERDEFINERGBAIMAGE: - if (wParam <= MARKER_MAX) { - vs.markers[wParam].SetRGBAImage(sizeRGBAImage, scaleRGBAImage / 100.0f, reinterpret_cast(lParam)); - vs.CalcLargestMarkerHeight(); - } - InvalidateStyleData(); - RedrawSelMargin(); - break; - - case SCI_SETMARGINTYPEN: - if (ValidMargin(wParam)) { - vs.ms[wParam].style = static_cast(lParam); - InvalidateStyleRedraw(); - } - break; - - case SCI_GETMARGINTYPEN: - if (ValidMargin(wParam)) - return vs.ms[wParam].style; - else - return 0; - - case SCI_SETMARGINWIDTHN: - if (ValidMargin(wParam)) { - // Short-circuit if the width is unchanged, to avoid unnecessary redraw. - if (vs.ms[wParam].width != lParam) { - lastXChosen += static_cast(lParam) - vs.ms[wParam].width; - vs.ms[wParam].width = static_cast(lParam); - InvalidateStyleRedraw(); - } - } - break; - - case SCI_GETMARGINWIDTHN: - if (ValidMargin(wParam)) - return vs.ms[wParam].width; - else - return 0; - - case SCI_SETMARGINMASKN: - if (ValidMargin(wParam)) { - vs.ms[wParam].mask = static_cast(lParam); - InvalidateStyleRedraw(); - } - break; - - case SCI_GETMARGINMASKN: - if (ValidMargin(wParam)) - return vs.ms[wParam].mask; - else - return 0; - - case SCI_SETMARGINSENSITIVEN: - if (ValidMargin(wParam)) { - vs.ms[wParam].sensitive = lParam != 0; - InvalidateStyleRedraw(); - } - break; - - case SCI_GETMARGINSENSITIVEN: - if (ValidMargin(wParam)) - return vs.ms[wParam].sensitive ? 1 : 0; - else - return 0; - - case SCI_SETMARGINCURSORN: - if (ValidMargin(wParam)) - vs.ms[wParam].cursor = static_cast(lParam); - break; - - case SCI_GETMARGINCURSORN: - if (ValidMargin(wParam)) - return vs.ms[wParam].cursor; - else - return 0; - - case SCI_STYLECLEARALL: - vs.ClearStyles(); - InvalidateStyleRedraw(); - break; - - case SCI_STYLESETFORE: - case SCI_STYLESETBACK: - case SCI_STYLESETBOLD: - case SCI_STYLESETWEIGHT: - case SCI_STYLESETITALIC: - case SCI_STYLESETEOLFILLED: - case SCI_STYLESETSIZE: - case SCI_STYLESETSIZEFRACTIONAL: - case SCI_STYLESETFONT: - case SCI_STYLESETUNDERLINE: - case SCI_STYLESETCASE: - case SCI_STYLESETCHARACTERSET: - case SCI_STYLESETVISIBLE: - case SCI_STYLESETCHANGEABLE: - case SCI_STYLESETHOTSPOT: - StyleSetMessage(iMessage, wParam, lParam); - break; - - case SCI_STYLEGETFORE: - case SCI_STYLEGETBACK: - case SCI_STYLEGETBOLD: - case SCI_STYLEGETWEIGHT: - case SCI_STYLEGETITALIC: - case SCI_STYLEGETEOLFILLED: - case SCI_STYLEGETSIZE: - case SCI_STYLEGETSIZEFRACTIONAL: - case SCI_STYLEGETFONT: - case SCI_STYLEGETUNDERLINE: - case SCI_STYLEGETCASE: - case SCI_STYLEGETCHARACTERSET: - case SCI_STYLEGETVISIBLE: - case SCI_STYLEGETCHANGEABLE: - case SCI_STYLEGETHOTSPOT: - return StyleGetMessage(iMessage, wParam, lParam); - - case SCI_STYLERESETDEFAULT: - vs.ResetDefaultStyle(); - InvalidateStyleRedraw(); - break; - case SCI_SETSTYLEBITS: - vs.EnsureStyle(0xff); - break; - - case SCI_GETSTYLEBITS: - return 8; - - case SCI_SETLINESTATE: - return pdoc->SetLineState(static_cast(wParam), static_cast(lParam)); - - case SCI_GETLINESTATE: - return pdoc->GetLineState(static_cast(wParam)); - - case SCI_GETMAXLINESTATE: - return pdoc->GetMaxLineState(); - - case SCI_GETCARETLINEVISIBLE: - return vs.showCaretLineBackground; - case SCI_SETCARETLINEVISIBLE: - vs.showCaretLineBackground = wParam != 0; - InvalidateStyleRedraw(); - break; - case SCI_GETCARETLINEVISIBLEALWAYS: - return vs.alwaysShowCaretLineBackground; - case SCI_SETCARETLINEVISIBLEALWAYS: - vs.alwaysShowCaretLineBackground = wParam != 0; - InvalidateStyleRedraw(); - break; - - case SCI_GETCARETLINEBACK: - return vs.caretLineBackground.AsLong(); - case SCI_SETCARETLINEBACK: - vs.caretLineBackground = static_cast(wParam); - InvalidateStyleRedraw(); - break; - case SCI_GETCARETLINEBACKALPHA: - return vs.caretLineAlpha; - case SCI_SETCARETLINEBACKALPHA: - vs.caretLineAlpha = static_cast(wParam); - InvalidateStyleRedraw(); - break; - - // Folding messages - - case SCI_VISIBLEFROMDOCLINE: - return cs.DisplayFromDoc(static_cast(wParam)); - - case SCI_DOCLINEFROMVISIBLE: - return cs.DocFromDisplay(static_cast(wParam)); - - case SCI_WRAPCOUNT: - return WrapCount(static_cast(wParam)); - - case SCI_SETFOLDLEVEL: { - int prev = pdoc->SetLevel(static_cast(wParam), static_cast(lParam)); - if (prev != static_cast(lParam)) - RedrawSelMargin(); - return prev; - } - - case SCI_GETFOLDLEVEL: - return pdoc->GetLevel(static_cast(wParam)); - - case SCI_GETLASTCHILD: - return pdoc->GetLastChild(static_cast(wParam), static_cast(lParam)); - - case SCI_GETFOLDPARENT: - return pdoc->GetFoldParent(static_cast(wParam)); - - case SCI_SHOWLINES: - cs.SetVisible(static_cast(wParam), static_cast(lParam), true); - SetScrollBars(); - Redraw(); - break; - - case SCI_HIDELINES: - if (wParam > 0) - cs.SetVisible(static_cast(wParam), static_cast(lParam), false); - SetScrollBars(); - Redraw(); - break; - - case SCI_GETLINEVISIBLE: - return cs.GetVisible(static_cast(wParam)); - - case SCI_GETALLLINESVISIBLE: - return cs.HiddenLines() ? 0 : 1; - - case SCI_SETFOLDEXPANDED: - SetFoldExpanded(static_cast(wParam), lParam != 0); - break; - - case SCI_GETFOLDEXPANDED: - return cs.GetExpanded(static_cast(wParam)); - - case SCI_SETAUTOMATICFOLD: - foldAutomatic = static_cast(wParam); - break; - - case SCI_GETAUTOMATICFOLD: - return foldAutomatic; - - case SCI_SETFOLDFLAGS: - foldFlags = static_cast(wParam); - Redraw(); - break; - - case SCI_TOGGLEFOLD: - FoldLine(static_cast(wParam), SC_FOLDACTION_TOGGLE); - break; - - case SCI_FOLDLINE: - FoldLine(static_cast(wParam), static_cast(lParam)); - break; - - case SCI_FOLDCHILDREN: - FoldExpand(static_cast(wParam), static_cast(lParam), pdoc->GetLevel(static_cast(wParam))); - break; - - case SCI_FOLDALL: - FoldAll(static_cast(wParam)); - break; - - case SCI_EXPANDCHILDREN: - FoldExpand(static_cast(wParam), SC_FOLDACTION_EXPAND, static_cast(lParam)); - break; - - case SCI_CONTRACTEDFOLDNEXT: - return ContractedFoldNext(static_cast(wParam)); - - case SCI_ENSUREVISIBLE: - EnsureLineVisible(static_cast(wParam), false); - break; - - case SCI_ENSUREVISIBLEENFORCEPOLICY: - EnsureLineVisible(static_cast(wParam), true); - break; - - case SCI_SCROLLRANGE: - ScrollRange(SelectionRange(static_cast(wParam), static_cast(lParam))); - break; - - case SCI_SEARCHANCHOR: - SearchAnchor(); - break; - - case SCI_SEARCHNEXT: - case SCI_SEARCHPREV: - return SearchText(iMessage, wParam, lParam); - - case SCI_SETXCARETPOLICY: - caretXPolicy = static_cast(wParam); - caretXSlop = static_cast(lParam); - break; - - case SCI_SETYCARETPOLICY: - caretYPolicy = static_cast(wParam); - caretYSlop = static_cast(lParam); - break; - - case SCI_SETVISIBLEPOLICY: - visiblePolicy = static_cast(wParam); - visibleSlop = static_cast(lParam); - break; - - case SCI_LINESONSCREEN: - return LinesOnScreen(); - - case SCI_SETSELFORE: - vs.selColours.fore = ColourOptional(wParam, lParam); - vs.selAdditionalForeground = ColourDesired(static_cast(lParam)); - InvalidateStyleRedraw(); - break; - - case SCI_SETSELBACK: - vs.selColours.back = ColourOptional(wParam, lParam); - vs.selAdditionalBackground = ColourDesired(static_cast(lParam)); - InvalidateStyleRedraw(); - break; - - case SCI_SETSELALPHA: - vs.selAlpha = static_cast(wParam); - vs.selAdditionalAlpha = static_cast(wParam); - InvalidateStyleRedraw(); - break; - - case SCI_GETSELALPHA: - return vs.selAlpha; - - case SCI_GETSELEOLFILLED: - return vs.selEOLFilled; - - case SCI_SETSELEOLFILLED: - vs.selEOLFilled = wParam != 0; - InvalidateStyleRedraw(); - break; - - case SCI_SETWHITESPACEFORE: - vs.whitespaceColours.fore = ColourOptional(wParam, lParam); - InvalidateStyleRedraw(); - break; - - case SCI_SETWHITESPACEBACK: - vs.whitespaceColours.back = ColourOptional(wParam, lParam); - InvalidateStyleRedraw(); - break; - - case SCI_SETCARETFORE: - vs.caretcolour = ColourDesired(static_cast(wParam)); - InvalidateStyleRedraw(); - break; - - case SCI_GETCARETFORE: - return vs.caretcolour.AsLong(); - - case SCI_SETCARETSTYLE: - if (wParam <= CARETSTYLE_BLOCK) - vs.caretStyle = static_cast(wParam); - else - /* Default to the line caret */ - vs.caretStyle = CARETSTYLE_LINE; - InvalidateStyleRedraw(); - break; - - case SCI_GETCARETSTYLE: - return vs.caretStyle; - - case SCI_SETCARETWIDTH: - if (static_cast(wParam) <= 0) - vs.caretWidth = 0; - else if (wParam >= 3) - vs.caretWidth = 3; - else - vs.caretWidth = static_cast(wParam); - InvalidateStyleRedraw(); - break; - - case SCI_GETCARETWIDTH: - return vs.caretWidth; - - case SCI_ASSIGNCMDKEY: - kmap.AssignCmdKey(Platform::LowShortFromLong(static_cast(wParam)), - Platform::HighShortFromLong(static_cast(wParam)), static_cast(lParam)); - break; - - case SCI_CLEARCMDKEY: - kmap.AssignCmdKey(Platform::LowShortFromLong(static_cast(wParam)), - Platform::HighShortFromLong(static_cast(wParam)), SCI_NULL); - break; - - case SCI_CLEARALLCMDKEYS: - kmap.Clear(); - break; - - case SCI_INDICSETSTYLE: - if (wParam <= INDIC_MAX) { - vs.indicators[wParam].sacNormal.style = static_cast(lParam); - vs.indicators[wParam].sacHover.style = static_cast(lParam); - InvalidateStyleRedraw(); - } - break; - - case SCI_INDICGETSTYLE: - return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacNormal.style : 0; - - case SCI_INDICSETFORE: - if (wParam <= INDIC_MAX) { - vs.indicators[wParam].sacNormal.fore = ColourDesired(static_cast(lParam)); - vs.indicators[wParam].sacHover.fore = ColourDesired(static_cast(lParam)); - InvalidateStyleRedraw(); - } - break; - - case SCI_INDICGETFORE: - return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacNormal.fore.AsLong() : 0; - - case SCI_INDICSETHOVERSTYLE: - if (wParam <= INDIC_MAX) { - vs.indicators[wParam].sacHover.style = static_cast(lParam); - InvalidateStyleRedraw(); - } - break; - - case SCI_INDICGETHOVERSTYLE: - return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacHover.style : 0; - - case SCI_INDICSETHOVERFORE: - if (wParam <= INDIC_MAX) { - vs.indicators[wParam].sacHover.fore = ColourDesired(static_cast(lParam)); - InvalidateStyleRedraw(); - } - break; - - case SCI_INDICGETHOVERFORE: - return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacHover.fore.AsLong() : 0; - - case SCI_INDICSETFLAGS: - if (wParam <= INDIC_MAX) { - vs.indicators[wParam].SetFlags(static_cast(lParam)); - InvalidateStyleRedraw(); - } - break; - - case SCI_INDICGETFLAGS: - return (wParam <= INDIC_MAX) ? vs.indicators[wParam].Flags() : 0; - - case SCI_INDICSETUNDER: - if (wParam <= INDIC_MAX) { - vs.indicators[wParam].under = lParam != 0; - InvalidateStyleRedraw(); - } - break; - - case SCI_INDICGETUNDER: - return (wParam <= INDIC_MAX) ? vs.indicators[wParam].under : 0; - - case SCI_INDICSETALPHA: - if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) { - vs.indicators[wParam].fillAlpha = static_cast(lParam); - InvalidateStyleRedraw(); - } - break; - - case SCI_INDICGETALPHA: - return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fillAlpha : 0; - - case SCI_INDICSETOUTLINEALPHA: - if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) { - vs.indicators[wParam].outlineAlpha = static_cast(lParam); - InvalidateStyleRedraw(); - } - break; - - case SCI_INDICGETOUTLINEALPHA: - return (wParam <= INDIC_MAX) ? vs.indicators[wParam].outlineAlpha : 0; - - case SCI_SETINDICATORCURRENT: - pdoc->decorations.SetCurrentIndicator(static_cast(wParam)); - break; - case SCI_GETINDICATORCURRENT: - return pdoc->decorations.GetCurrentIndicator(); - case SCI_SETINDICATORVALUE: - pdoc->decorations.SetCurrentValue(static_cast(wParam)); - break; - case SCI_GETINDICATORVALUE: - return pdoc->decorations.GetCurrentValue(); - - case SCI_INDICATORFILLRANGE: - pdoc->DecorationFillRange(static_cast(wParam), pdoc->decorations.GetCurrentValue(), static_cast(lParam)); - break; - - case SCI_INDICATORCLEARRANGE: - pdoc->DecorationFillRange(static_cast(wParam), 0, static_cast(lParam)); - break; - - case SCI_INDICATORALLONFOR: - return pdoc->decorations.AllOnFor(static_cast(wParam)); - - case SCI_INDICATORVALUEAT: - return pdoc->decorations.ValueAt(static_cast(wParam), static_cast(lParam)); - - case SCI_INDICATORSTART: - return pdoc->decorations.Start(static_cast(wParam), static_cast(lParam)); - - case SCI_INDICATOREND: - return pdoc->decorations.End(static_cast(wParam), static_cast(lParam)); - - case SCI_LINEDOWN: - case SCI_LINEDOWNEXTEND: - case SCI_PARADOWN: - case SCI_PARADOWNEXTEND: - case SCI_LINEUP: - case SCI_LINEUPEXTEND: - case SCI_PARAUP: - case SCI_PARAUPEXTEND: - case SCI_CHARLEFT: - case SCI_CHARLEFTEXTEND: - case SCI_CHARRIGHT: - case SCI_CHARRIGHTEXTEND: - case SCI_WORDLEFT: - case SCI_WORDLEFTEXTEND: - case SCI_WORDRIGHT: - case SCI_WORDRIGHTEXTEND: - case SCI_WORDLEFTEND: - case SCI_WORDLEFTENDEXTEND: - case SCI_WORDRIGHTEND: - case SCI_WORDRIGHTENDEXTEND: - case SCI_HOME: - case SCI_HOMEEXTEND: - case SCI_LINEEND: - case SCI_LINEENDEXTEND: - case SCI_HOMEWRAP: - case SCI_HOMEWRAPEXTEND: - case SCI_LINEENDWRAP: - case SCI_LINEENDWRAPEXTEND: - case SCI_DOCUMENTSTART: - case SCI_DOCUMENTSTARTEXTEND: - case SCI_DOCUMENTEND: - case SCI_DOCUMENTENDEXTEND: - case SCI_SCROLLTOSTART: - case SCI_SCROLLTOEND: - - case SCI_STUTTEREDPAGEUP: - case SCI_STUTTEREDPAGEUPEXTEND: - case SCI_STUTTEREDPAGEDOWN: - case SCI_STUTTEREDPAGEDOWNEXTEND: - - case SCI_PAGEUP: - case SCI_PAGEUPEXTEND: - case SCI_PAGEDOWN: - case SCI_PAGEDOWNEXTEND: - case SCI_EDITTOGGLEOVERTYPE: - case SCI_CANCEL: - case SCI_DELETEBACK: - case SCI_TAB: - case SCI_BACKTAB: - case SCI_NEWLINE: - case SCI_FORMFEED: - case SCI_VCHOME: - case SCI_VCHOMEEXTEND: - case SCI_VCHOMEWRAP: - case SCI_VCHOMEWRAPEXTEND: - case SCI_VCHOMEDISPLAY: - case SCI_VCHOMEDISPLAYEXTEND: - case SCI_ZOOMIN: - case SCI_ZOOMOUT: - case SCI_DELWORDLEFT: - case SCI_DELWORDRIGHT: - case SCI_DELWORDRIGHTEND: - case SCI_DELLINELEFT: - case SCI_DELLINERIGHT: - case SCI_LINECOPY: - case SCI_LINECUT: - case SCI_LINEDELETE: - case SCI_LINETRANSPOSE: - case SCI_LINEDUPLICATE: - case SCI_LOWERCASE: - case SCI_UPPERCASE: - case SCI_LINESCROLLDOWN: - case SCI_LINESCROLLUP: - case SCI_WORDPARTLEFT: - case SCI_WORDPARTLEFTEXTEND: - case SCI_WORDPARTRIGHT: - case SCI_WORDPARTRIGHTEXTEND: - case SCI_DELETEBACKNOTLINE: - case SCI_HOMEDISPLAY: - case SCI_HOMEDISPLAYEXTEND: - case SCI_LINEENDDISPLAY: - case SCI_LINEENDDISPLAYEXTEND: - case SCI_LINEDOWNRECTEXTEND: - case SCI_LINEUPRECTEXTEND: - case SCI_CHARLEFTRECTEXTEND: - case SCI_CHARRIGHTRECTEXTEND: - case SCI_HOMERECTEXTEND: - case SCI_VCHOMERECTEXTEND: - case SCI_LINEENDRECTEXTEND: - case SCI_PAGEUPRECTEXTEND: - case SCI_PAGEDOWNRECTEXTEND: - case SCI_SELECTIONDUPLICATE: - return KeyCommand(iMessage); - - case SCI_BRACEHIGHLIGHT: - SetBraceHighlight(static_cast(wParam), static_cast(lParam), STYLE_BRACELIGHT); - break; - - case SCI_BRACEHIGHLIGHTINDICATOR: - if (lParam >= 0 && lParam <= INDIC_MAX) { - vs.braceHighlightIndicatorSet = wParam != 0; - vs.braceHighlightIndicator = static_cast(lParam); - } - break; - - case SCI_BRACEBADLIGHT: - SetBraceHighlight(static_cast(wParam), -1, STYLE_BRACEBAD); - break; - - case SCI_BRACEBADLIGHTINDICATOR: - if (lParam >= 0 && lParam <= INDIC_MAX) { - vs.braceBadLightIndicatorSet = wParam != 0; - vs.braceBadLightIndicator = static_cast(lParam); - } - break; - - case SCI_BRACEMATCH: - // wParam is position of char to find brace for, - // lParam is maximum amount of text to restyle to find it - return pdoc->BraceMatch(static_cast(wParam), static_cast(lParam)); - - case SCI_GETVIEWEOL: - return vs.viewEOL; - - case SCI_SETVIEWEOL: - vs.viewEOL = wParam != 0; - InvalidateStyleRedraw(); - break; - - case SCI_SETZOOM: - vs.zoomLevel = static_cast(wParam); - InvalidateStyleRedraw(); - NotifyZoom(); - break; - - case SCI_GETZOOM: - return vs.zoomLevel; - - case SCI_GETEDGECOLUMN: - return vs.theEdge; - - case SCI_SETEDGECOLUMN: - vs.theEdge = static_cast(wParam); - InvalidateStyleRedraw(); - break; - - case SCI_GETEDGEMODE: - return vs.edgeState; - - case SCI_SETEDGEMODE: - vs.edgeState = static_cast(wParam); - InvalidateStyleRedraw(); - break; - - case SCI_GETEDGECOLOUR: - return vs.edgecolour.AsLong(); - - case SCI_SETEDGECOLOUR: - vs.edgecolour = ColourDesired(static_cast(wParam)); - InvalidateStyleRedraw(); - break; - - case SCI_GETDOCPOINTER: - return reinterpret_cast(pdoc); - - case SCI_SETDOCPOINTER: - CancelModes(); - SetDocPointer(reinterpret_cast(lParam)); - return 0; - - case SCI_CREATEDOCUMENT: { - Document *doc = new Document(); - doc->AddRef(); - return reinterpret_cast(doc); - } - - case SCI_ADDREFDOCUMENT: - (reinterpret_cast(lParam))->AddRef(); - break; - - case SCI_RELEASEDOCUMENT: - (reinterpret_cast(lParam))->Release(); - break; - - case SCI_CREATELOADER: { - Document *doc = new Document(); - doc->AddRef(); - doc->Allocate(static_cast(wParam)); - doc->SetUndoCollection(false); - return reinterpret_cast(static_cast(doc)); - } - - case SCI_SETMODEVENTMASK: - modEventMask = static_cast(wParam); - return 0; - - case SCI_GETMODEVENTMASK: - return modEventMask; - - case SCI_CONVERTEOLS: - pdoc->ConvertLineEnds(static_cast(wParam)); - SetSelection(sel.MainCaret(), sel.MainAnchor()); // Ensure selection inside document - return 0; - - case SCI_SETLENGTHFORENCODE: - lengthForEncode = static_cast(wParam); - return 0; - - case SCI_SELECTIONISRECTANGLE: - return sel.selType == Selection::selRectangle ? 1 : 0; - - case SCI_SETSELECTIONMODE: { - switch (wParam) { - case SC_SEL_STREAM: - sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream)); - sel.selType = Selection::selStream; - break; - case SC_SEL_RECTANGLE: - sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selRectangle)); - sel.selType = Selection::selRectangle; - break; - case SC_SEL_LINES: - sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selLines)); - sel.selType = Selection::selLines; - break; - case SC_SEL_THIN: - sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selThin)); - sel.selType = Selection::selThin; - break; - default: - sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream)); - sel.selType = Selection::selStream; - } - InvalidateSelection(sel.RangeMain(), true); - break; - } - case SCI_GETSELECTIONMODE: - switch (sel.selType) { - case Selection::selStream: - return SC_SEL_STREAM; - case Selection::selRectangle: - return SC_SEL_RECTANGLE; - case Selection::selLines: - return SC_SEL_LINES; - case Selection::selThin: - return SC_SEL_THIN; - default: // ?! - return SC_SEL_STREAM; - } - case SCI_GETLINESELSTARTPOSITION: - case SCI_GETLINESELENDPOSITION: { - SelectionSegment segmentLine(SelectionPosition(pdoc->LineStart(static_cast(wParam))), - SelectionPosition(pdoc->LineEnd(static_cast(wParam)))); - for (size_t r=0; r(wParam); - break; - - case SCI_GETSTATUS: - return errorStatus; - - case SCI_SETMOUSEDOWNCAPTURES: - mouseDownCaptures = wParam != 0; - break; - - case SCI_GETMOUSEDOWNCAPTURES: - return mouseDownCaptures; - - case SCI_SETCURSOR: - cursorMode = static_cast(wParam); - DisplayCursor(Window::cursorText); - break; - - case SCI_GETCURSOR: - return cursorMode; - - case SCI_SETCONTROLCHARSYMBOL: - vs.controlCharSymbol = static_cast(wParam); - InvalidateStyleRedraw(); - break; - - case SCI_GETCONTROLCHARSYMBOL: - return vs.controlCharSymbol; - - case SCI_SETREPRESENTATION: - reprs.SetRepresentation(reinterpret_cast(wParam), CharPtrFromSPtr(lParam)); - break; - - case SCI_GETREPRESENTATION: { - const Representation *repr = reprs.RepresentationFromCharacter( - reinterpret_cast(wParam), UTF8MaxBytes); - if (repr) { - return StringResult(lParam, repr->stringRep.c_str()); - } - return 0; - } - - case SCI_CLEARREPRESENTATION: - reprs.ClearRepresentation(reinterpret_cast(wParam)); - break; - - case SCI_STARTRECORD: - recordingMacro = true; - return 0; - - case SCI_STOPRECORD: - recordingMacro = false; - return 0; - - case SCI_MOVECARETINSIDEVIEW: - MoveCaretInsideView(); - break; - - case SCI_SETFOLDMARGINCOLOUR: - vs.foldmarginColour = ColourOptional(wParam, lParam); - InvalidateStyleRedraw(); - break; - - case SCI_SETFOLDMARGINHICOLOUR: - vs.foldmarginHighlightColour = ColourOptional(wParam, lParam); - InvalidateStyleRedraw(); - break; - - case SCI_SETHOTSPOTACTIVEFORE: - vs.hotspotColours.fore = ColourOptional(wParam, lParam); - InvalidateStyleRedraw(); - break; - - case SCI_GETHOTSPOTACTIVEFORE: - return vs.hotspotColours.fore.AsLong(); - - case SCI_SETHOTSPOTACTIVEBACK: - vs.hotspotColours.back = ColourOptional(wParam, lParam); - InvalidateStyleRedraw(); - break; - - case SCI_GETHOTSPOTACTIVEBACK: - return vs.hotspotColours.back.AsLong(); - - case SCI_SETHOTSPOTACTIVEUNDERLINE: - vs.hotspotUnderline = wParam != 0; - InvalidateStyleRedraw(); - break; - - case SCI_GETHOTSPOTACTIVEUNDERLINE: - return vs.hotspotUnderline ? 1 : 0; - - case SCI_SETHOTSPOTSINGLELINE: - vs.hotspotSingleLine = wParam != 0; - InvalidateStyleRedraw(); - break; - - case SCI_GETHOTSPOTSINGLELINE: - return vs.hotspotSingleLine ? 1 : 0; - - case SCI_SETPASTECONVERTENDINGS: - convertPastes = wParam != 0; - break; - - case SCI_GETPASTECONVERTENDINGS: - return convertPastes ? 1 : 0; - - case SCI_GETCHARACTERPOINTER: - return reinterpret_cast(pdoc->BufferPointer()); - - case SCI_GETRANGEPOINTER: - return reinterpret_cast(pdoc->RangePointer(static_cast(wParam), static_cast(lParam))); - - case SCI_GETGAPPOSITION: - return pdoc->GapPosition(); - - case SCI_SETEXTRAASCENT: - vs.extraAscent = static_cast(wParam); - InvalidateStyleRedraw(); - break; - - case SCI_GETEXTRAASCENT: - return vs.extraAscent; - - case SCI_SETEXTRADESCENT: - vs.extraDescent = static_cast(wParam); - InvalidateStyleRedraw(); - break; - - case SCI_GETEXTRADESCENT: - return vs.extraDescent; - - case SCI_MARGINSETSTYLEOFFSET: - vs.marginStyleOffset = static_cast(wParam); - InvalidateStyleRedraw(); - break; - - case SCI_MARGINGETSTYLEOFFSET: - return vs.marginStyleOffset; - - case SCI_SETMARGINOPTIONS: - marginOptions = static_cast(wParam); - break; - - case SCI_GETMARGINOPTIONS: - return marginOptions; - - case SCI_MARGINSETTEXT: - pdoc->MarginSetText(static_cast(wParam), CharPtrFromSPtr(lParam)); - break; - - case SCI_MARGINGETTEXT: { - const StyledText st = pdoc->MarginStyledText(static_cast(wParam)); - return BytesResult(lParam, reinterpret_cast(st.text), st.length); - } - - case SCI_MARGINSETSTYLE: - pdoc->MarginSetStyle(static_cast(wParam), static_cast(lParam)); - break; - - case SCI_MARGINGETSTYLE: { - const StyledText st = pdoc->MarginStyledText(static_cast(wParam)); - return st.style; - } - - case SCI_MARGINSETSTYLES: - pdoc->MarginSetStyles(static_cast(wParam), reinterpret_cast(lParam)); - break; - - case SCI_MARGINGETSTYLES: { - const StyledText st = pdoc->MarginStyledText(static_cast(wParam)); - return BytesResult(lParam, st.styles, st.length); - } - - case SCI_MARGINTEXTCLEARALL: - pdoc->MarginClearAll(); - break; - - case SCI_ANNOTATIONSETTEXT: - pdoc->AnnotationSetText(static_cast(wParam), CharPtrFromSPtr(lParam)); - break; - - case SCI_ANNOTATIONGETTEXT: { - const StyledText st = pdoc->AnnotationStyledText(static_cast(wParam)); - return BytesResult(lParam, reinterpret_cast(st.text), st.length); - } - - case SCI_ANNOTATIONGETSTYLE: { - const StyledText st = pdoc->AnnotationStyledText(static_cast(wParam)); - return st.style; - } - - case SCI_ANNOTATIONSETSTYLE: - pdoc->AnnotationSetStyle(static_cast(wParam), static_cast(lParam)); - break; - - case SCI_ANNOTATIONSETSTYLES: - pdoc->AnnotationSetStyles(static_cast(wParam), reinterpret_cast(lParam)); - break; - - case SCI_ANNOTATIONGETSTYLES: { - const StyledText st = pdoc->AnnotationStyledText(static_cast(wParam)); - return BytesResult(lParam, st.styles, st.length); - } - - case SCI_ANNOTATIONGETLINES: - return pdoc->AnnotationLines(static_cast(wParam)); - - case SCI_ANNOTATIONCLEARALL: - pdoc->AnnotationClearAll(); - break; - - case SCI_ANNOTATIONSETVISIBLE: - SetAnnotationVisible(static_cast(wParam)); - break; - - case SCI_ANNOTATIONGETVISIBLE: - return vs.annotationVisible; - - case SCI_ANNOTATIONSETSTYLEOFFSET: - vs.annotationStyleOffset = static_cast(wParam); - InvalidateStyleRedraw(); - break; - - case SCI_ANNOTATIONGETSTYLEOFFSET: - return vs.annotationStyleOffset; - - case SCI_RELEASEALLEXTENDEDSTYLES: - vs.ReleaseAllExtendedStyles(); - break; - - case SCI_ALLOCATEEXTENDEDSTYLES: - return vs.AllocateExtendedStyles(static_cast(wParam)); - - case SCI_ADDUNDOACTION: - pdoc->AddUndoAction(static_cast(wParam), lParam & UNDO_MAY_COALESCE); - break; - - case SCI_SETMOUSESELECTIONRECTANGULARSWITCH: - mouseSelectionRectangularSwitch = wParam != 0; - break; - - case SCI_GETMOUSESELECTIONRECTANGULARSWITCH: - return mouseSelectionRectangularSwitch; - - case SCI_SETMULTIPLESELECTION: - multipleSelection = wParam != 0; - InvalidateCaret(); - break; - - case SCI_GETMULTIPLESELECTION: - return multipleSelection; - - case SCI_SETADDITIONALSELECTIONTYPING: - additionalSelectionTyping = wParam != 0; - InvalidateCaret(); - break; - - case SCI_GETADDITIONALSELECTIONTYPING: - return additionalSelectionTyping; - - case SCI_SETMULTIPASTE: - multiPasteMode = static_cast(wParam); - break; - - case SCI_GETMULTIPASTE: - return multiPasteMode; - - case SCI_SETADDITIONALCARETSBLINK: - view.additionalCaretsBlink = wParam != 0; - InvalidateCaret(); - break; - - case SCI_GETADDITIONALCARETSBLINK: - return view.additionalCaretsBlink; - - case SCI_SETADDITIONALCARETSVISIBLE: - view.additionalCaretsVisible = wParam != 0; - InvalidateCaret(); - break; - - case SCI_GETADDITIONALCARETSVISIBLE: - return view.additionalCaretsVisible; - - case SCI_GETSELECTIONS: - return sel.Count(); - - case SCI_GETSELECTIONEMPTY: - return sel.Empty(); - - case SCI_CLEARSELECTIONS: - sel.Clear(); - Redraw(); - break; - - case SCI_SETSELECTION: - sel.SetSelection(SelectionRange(static_cast(wParam), static_cast(lParam))); - Redraw(); - break; - - case SCI_ADDSELECTION: - sel.AddSelection(SelectionRange(static_cast(wParam), static_cast(lParam))); - Redraw(); - break; - - case SCI_DROPSELECTIONN: - sel.DropSelection(static_cast(wParam)); - Redraw(); - break; - - case SCI_SETMAINSELECTION: - sel.SetMain(static_cast(wParam)); - Redraw(); - break; - - case SCI_GETMAINSELECTION: - return sel.Main(); - - case SCI_SETSELECTIONNCARET: - sel.Range(wParam).caret.SetPosition(static_cast(lParam)); - Redraw(); - break; - - case SCI_GETSELECTIONNCARET: - return sel.Range(wParam).caret.Position(); - - case SCI_SETSELECTIONNANCHOR: - sel.Range(wParam).anchor.SetPosition(static_cast(lParam)); - Redraw(); - break; - case SCI_GETSELECTIONNANCHOR: - return sel.Range(wParam).anchor.Position(); - - case SCI_SETSELECTIONNCARETVIRTUALSPACE: - sel.Range(wParam).caret.SetVirtualSpace(static_cast(lParam)); - Redraw(); - break; - - case SCI_GETSELECTIONNCARETVIRTUALSPACE: - return sel.Range(wParam).caret.VirtualSpace(); - - case SCI_SETSELECTIONNANCHORVIRTUALSPACE: - sel.Range(wParam).anchor.SetVirtualSpace(static_cast(lParam)); - Redraw(); - break; - - case SCI_GETSELECTIONNANCHORVIRTUALSPACE: - return sel.Range(wParam).anchor.VirtualSpace(); - - case SCI_SETSELECTIONNSTART: - sel.Range(wParam).anchor.SetPosition(static_cast(lParam)); - Redraw(); - break; - - case SCI_GETSELECTIONNSTART: - return sel.Range(wParam).Start().Position(); - - case SCI_SETSELECTIONNEND: - sel.Range(wParam).caret.SetPosition(static_cast(lParam)); - Redraw(); - break; - - case SCI_GETSELECTIONNEND: - return sel.Range(wParam).End().Position(); - - case SCI_SETRECTANGULARSELECTIONCARET: - if (!sel.IsRectangular()) - sel.Clear(); - sel.selType = Selection::selRectangle; - sel.Rectangular().caret.SetPosition(static_cast(wParam)); - SetRectangularRange(); - Redraw(); - break; - - case SCI_GETRECTANGULARSELECTIONCARET: - return sel.Rectangular().caret.Position(); - - case SCI_SETRECTANGULARSELECTIONANCHOR: - if (!sel.IsRectangular()) - sel.Clear(); - sel.selType = Selection::selRectangle; - sel.Rectangular().anchor.SetPosition(static_cast(wParam)); - SetRectangularRange(); - Redraw(); - break; - - case SCI_GETRECTANGULARSELECTIONANCHOR: - return sel.Rectangular().anchor.Position(); - - case SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE: - if (!sel.IsRectangular()) - sel.Clear(); - sel.selType = Selection::selRectangle; - sel.Rectangular().caret.SetVirtualSpace(static_cast(wParam)); - SetRectangularRange(); - Redraw(); - break; - - case SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE: - return sel.Rectangular().caret.VirtualSpace(); - - case SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE: - if (!sel.IsRectangular()) - sel.Clear(); - sel.selType = Selection::selRectangle; - sel.Rectangular().anchor.SetVirtualSpace(static_cast(wParam)); - SetRectangularRange(); - Redraw(); - break; - - case SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE: - return sel.Rectangular().anchor.VirtualSpace(); - - case SCI_SETVIRTUALSPACEOPTIONS: - virtualSpaceOptions = static_cast(wParam); - break; - - case SCI_GETVIRTUALSPACEOPTIONS: - return virtualSpaceOptions; - - case SCI_SETADDITIONALSELFORE: - vs.selAdditionalForeground = ColourDesired(static_cast(wParam)); - InvalidateStyleRedraw(); - break; - - case SCI_SETADDITIONALSELBACK: - vs.selAdditionalBackground = ColourDesired(static_cast(wParam)); - InvalidateStyleRedraw(); - break; - - case SCI_SETADDITIONALSELALPHA: - vs.selAdditionalAlpha = static_cast(wParam); - InvalidateStyleRedraw(); - break; - - case SCI_GETADDITIONALSELALPHA: - return vs.selAdditionalAlpha; - - case SCI_SETADDITIONALCARETFORE: - vs.additionalCaretColour = ColourDesired(static_cast(wParam)); - InvalidateStyleRedraw(); - break; - - case SCI_GETADDITIONALCARETFORE: - return vs.additionalCaretColour.AsLong(); - - case SCI_ROTATESELECTION: - sel.RotateMain(); - InvalidateSelection(sel.RangeMain(), true); - break; - - case SCI_SWAPMAINANCHORCARET: - InvalidateSelection(sel.RangeMain()); - sel.RangeMain() = SelectionRange(sel.RangeMain().anchor, sel.RangeMain().caret); - break; - - case SCI_CHANGELEXERSTATE: - pdoc->ChangeLexerState(static_cast(wParam), static_cast(lParam)); - break; - - case SCI_SETIDENTIFIER: - SetCtrlID(static_cast(wParam)); - break; - - case SCI_GETIDENTIFIER: - return GetCtrlID(); - - case SCI_SETTECHNOLOGY: - // No action by default - break; - - case SCI_GETTECHNOLOGY: - return technology; - - case SCI_COUNTCHARACTERS: - return pdoc->CountCharacters(static_cast(wParam), static_cast(lParam)); - - default: - return DefWndProc(iMessage, wParam, lParam); - } - //Platform::DebugPrintf("end wnd proc\n"); - return 0l; -} diff --git a/libs/qscintilla/src/Editor.h b/libs/qscintilla/src/Editor.h deleted file mode 100644 index 1fc907ac7..000000000 --- a/libs/qscintilla/src/Editor.h +++ /dev/null @@ -1,620 +0,0 @@ -// Scintilla source code edit control -/** @file Editor.h - ** Defines the main editor class. - **/ -// Copyright 1998-2011 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef EDITOR_H -#define EDITOR_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -/** - */ -class Timer { -public: - bool ticking; - int ticksToWait; - enum {tickSize = 100}; - TickerID tickerID; - - Timer(); -}; - -/** - */ -class Idler { -public: - bool state; - IdlerID idlerID; - - Idler(); -}; - -/** - * When platform has a way to generate an event before painting, - * accumulate needed styling range and other work items in - * WorkNeeded to avoid unnecessary work inside paint handler - */ -class WorkNeeded { -public: - enum workItems { - workNone=0, - workStyle=1, - workUpdateUI=2 - }; - bool active; - enum workItems items; - Position upTo; - - WorkNeeded() : active(false), items(workNone), upTo(0) {} - void Reset() { - active = false; - items = workNone; - upTo = 0; - } - void Need(workItems items_, Position pos) { - if ((items_ & workStyle) && (upTo < pos)) - upTo = pos; - items = static_cast(items | items_); - } -}; - -/** - * Hold a piece of text selected for copying or dragging, along with encoding and selection format information. - */ -class SelectionText { - std::string s; -public: - bool rectangular; - bool lineCopy; - int codePage; - int characterSet; - SelectionText() : rectangular(false), lineCopy(false), codePage(0), characterSet(0) {} - ~SelectionText() { - } - void Clear() { - s.clear(); - rectangular = false; - lineCopy = false; - codePage = 0; - characterSet = 0; - } - void Copy(const std::string &s_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) { - s = s_; - codePage = codePage_; - characterSet = characterSet_; - rectangular = rectangular_; - lineCopy = lineCopy_; - FixSelectionForClipboard(); - } - void Copy(const SelectionText &other) { - Copy(other.s, other.codePage, other.characterSet, other.rectangular, other.lineCopy); - } - const char *Data() const { - return s.c_str(); - } - size_t Length() const { - return s.length(); - } - size_t LengthWithTerminator() const { - return s.length() + 1; - } - bool Empty() const { - return s.empty(); - } -private: - void FixSelectionForClipboard() { - // To avoid truncating the contents of the clipboard when pasted where the - // clipboard contains NUL characters, replace NUL characters by spaces. - std::replace(s.begin(), s.end(), '\0', ' '); - } -}; - -struct WrapPending { - // The range of lines that need to be wrapped - enum { lineLarge = 0x7ffffff }; - int start; // When there are wraps pending, will be in document range - int end; // May be lineLarge to indicate all of document after start - WrapPending() { - start = lineLarge; - end = lineLarge; - } - void Reset() { - start = lineLarge; - end = lineLarge; - } - void Wrapped(int line) { - if (start == line) - start++; - } - bool NeedsWrap() const { - return start < end; - } - bool AddRange(int lineStart, int lineEnd) { - const bool neededWrap = NeedsWrap(); - bool changed = false; - if (start > lineStart) { - start = lineStart; - changed = true; - } - if ((end < lineEnd) || !neededWrap) { - end = lineEnd; - changed = true; - } - return changed; - } -}; - -/** - */ -class Editor : public EditModel, public DocWatcher { - // Private so Editor objects can not be copied - Editor(const Editor &); - Editor &operator=(const Editor &); - -protected: // ScintillaBase subclass needs access to much of Editor - - /** On GTK+, Scintilla is a container widget holding two scroll bars - * whereas on Windows there is just one window with both scroll bars turned on. */ - Window wMain; ///< The Scintilla parent window - Window wMargin; ///< May be separate when using a scroll view for wMain - - /** Style resources may be expensive to allocate so are cached between uses. - * When a style attribute is changed, this cache is flushed. */ - bool stylesValid; - ViewStyle vs; - int technology; - Point sizeRGBAImage; - float scaleRGBAImage; - - MarginView marginView; - EditView view; - - int cursorMode; - - bool hasFocus; - bool mouseDownCaptures; - - int xCaretMargin; ///< Ensure this many pixels visible on both sides of caret - bool horizontalScrollBarVisible; - int scrollWidth; - bool verticalScrollBarVisible; - bool endAtLastLine; - int caretSticky; - int marginOptions; - bool mouseSelectionRectangularSwitch; - bool multipleSelection; - bool additionalSelectionTyping; - int multiPasteMode; - - int virtualSpaceOptions; - - KeyMap kmap; - - Timer timer; - Timer autoScrollTimer; - enum { autoScrollDelay = 200 }; - - Idler idler; - - Point lastClick; - unsigned int lastClickTime; - Point doubleClickCloseThreshold; - int dwellDelay; - int ticksToDwell; - bool dwelling; - enum { selChar, selWord, selSubLine, selWholeLine } selectionType; - Point ptMouseLast; - enum { ddNone, ddInitial, ddDragging } inDragDrop; - bool dropWentOutside; - SelectionPosition posDrop; - int hotSpotClickPos; - int lastXChosen; - int lineAnchorPos; - int originalAnchorPos; - int wordSelectAnchorStartPos; - int wordSelectAnchorEndPos; - int wordSelectInitialCaretPos; - int targetStart; - int targetEnd; - int searchFlags; - int topLine; - int posTopLine; - int lengthForEncode; - - int needUpdateUI; - - enum { notPainting, painting, paintAbandoned } paintState; - bool paintAbandonedByStyling; - PRectangle rcPaint; - bool paintingAllText; - bool willRedrawAll; - WorkNeeded workNeeded; - - int modEventMask; - - SelectionText drag; - - int caretXPolicy; - int caretXSlop; ///< Ensure this many pixels visible on both sides of caret - - int caretYPolicy; - int caretYSlop; ///< Ensure this many lines visible on both sides of caret - - int visiblePolicy; - int visibleSlop; - - int searchAnchor; - - bool recordingMacro; - - int foldAutomatic; - - // Wrapping support - WrapPending wrapPending; - - bool convertPastes; - - Editor(); - virtual ~Editor(); - virtual void Initialise() = 0; - virtual void Finalise(); - - void InvalidateStyleData(); - void InvalidateStyleRedraw(); - void RefreshStyleData(); - void SetRepresentations(); - void DropGraphics(bool freeObjects); - void AllocateGraphics(); - - // The top left visible point in main window coordinates. Will be 0,0 except for - // scroll views where it will be equivalent to the current scroll position. - virtual Point GetVisibleOriginInMain() const; - Point DocumentPointFromView(Point ptView) const; // Convert a point from view space to document - int TopLineOfMain() const; // Return the line at Main's y coordinate 0 - virtual PRectangle GetClientRectangle() const; - virtual PRectangle GetClientDrawingRectangle(); - PRectangle GetTextRectangle() const; - - virtual int LinesOnScreen() const; - int LinesToScroll() const; - int MaxScrollPos() const; - SelectionPosition ClampPositionIntoDocument(SelectionPosition sp) const; - Point LocationFromPosition(SelectionPosition pos); - Point LocationFromPosition(int pos); - int XFromPosition(int pos); - int XFromPosition(SelectionPosition sp); - SelectionPosition SPositionFromLocation(Point pt, bool canReturnInvalid=false, bool charPosition=false, bool virtualSpace=true); - int PositionFromLocation(Point pt, bool canReturnInvalid = false, bool charPosition = false); - SelectionPosition SPositionFromLineX(int lineDoc, int x); - int PositionFromLineX(int line, int x); - int LineFromLocation(Point pt) const; - void SetTopLine(int topLineNew); - - virtual bool AbandonPaint(); - virtual void RedrawRect(PRectangle rc); - virtual void DiscardOverdraw(); - virtual void Redraw(); - void RedrawSelMargin(int line=-1, bool allAfter=false); - PRectangle RectangleFromRange(Range r, int overlap); - void InvalidateRange(int start, int end); - - bool UserVirtualSpace() const { - return ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0); - } - int CurrentPosition() const; - bool SelectionEmpty() const; - SelectionPosition SelectionStart(); - SelectionPosition SelectionEnd(); - void SetRectangularRange(); - void ThinRectangularRange(); - void InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection=false); - void SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_); - void SetSelection(int currentPos_, int anchor_); - void SetSelection(SelectionPosition currentPos_); - void SetSelection(int currentPos_); - void SetEmptySelection(SelectionPosition currentPos_); - void SetEmptySelection(int currentPos_); - bool RangeContainsProtected(int start, int end) const; - bool SelectionContainsProtected(); - int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true) const; - SelectionPosition MovePositionOutsideChar(SelectionPosition pos, int moveDir, bool checkLineEnd=true) const; - int MovePositionTo(SelectionPosition newPos, Selection::selTypes selt=Selection::noSel, bool ensureVisible=true); - int MovePositionTo(int newPos, Selection::selTypes selt=Selection::noSel, bool ensureVisible=true); - SelectionPosition MovePositionSoVisible(SelectionPosition pos, int moveDir); - SelectionPosition MovePositionSoVisible(int pos, int moveDir); - Point PointMainCaret(); - void SetLastXChosen(); - - void ScrollTo(int line, bool moveThumb=true); - virtual void ScrollText(int linesToMove); - void HorizontalScrollTo(int xPos); - void VerticalCentreCaret(); - void MoveSelectedLines(int lineDelta); - void MoveSelectedLinesUp(); - void MoveSelectedLinesDown(); - void MoveCaretInsideView(bool ensureVisible=true); - int DisplayFromPosition(int pos); - - struct XYScrollPosition { - int xOffset; - int topLine; - XYScrollPosition(int xOffset_, int topLine_) : xOffset(xOffset_), topLine(topLine_) {} - bool operator==(const XYScrollPosition &other) const { - return (xOffset == other.xOffset) && (topLine == other.topLine); - } - }; - enum XYScrollOptions { - xysUseMargin=0x1, - xysVertical=0x2, - xysHorizontal=0x4, - xysDefault=xysUseMargin|xysVertical|xysHorizontal}; - XYScrollPosition XYScrollToMakeVisible(const SelectionRange &range, const XYScrollOptions options); - void SetXYScroll(XYScrollPosition newXY); - void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true); - void ScrollRange(SelectionRange range); - void ShowCaretAtCurrentPosition(); - void DropCaret(); - void CaretSetPeriod(int period); - void InvalidateCaret(); - virtual void UpdateSystemCaret(); - - bool Wrapping() const; - void NeedWrapping(int docLineStart=0, int docLineEnd=WrapPending::lineLarge); - bool WrapOneLine(Surface *surface, int lineToWrap); - enum wrapScope {wsAll, wsVisible, wsIdle}; - bool WrapLines(enum wrapScope ws); - void LinesJoin(); - void LinesSplit(int pixelWidth); - - void PaintSelMargin(Surface *surface, PRectangle &rc); - void RefreshPixMaps(Surface *surfaceWindow); - void Paint(Surface *surfaceWindow, PRectangle rcArea); - long FormatRange(bool draw, Sci_RangeToFormat *pfr); - int TextWidth(int style, const char *text); - - virtual void SetVerticalScrollPos() = 0; - virtual void SetHorizontalScrollPos() = 0; - virtual bool ModifyScrollBars(int nMax, int nPage) = 0; - virtual void ReconfigureScrollBars(); - void SetScrollBars(); - void ChangeSize(); - - void FilterSelections(); - int InsertSpace(int position, unsigned int spaces); - void AddChar(char ch); - virtual void AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS=false); - void FillVirtualSpace(); - void InsertPaste(const char *text, int len); - enum PasteShape { pasteStream=0, pasteRectangular = 1, pasteLine = 2 }; - void InsertPasteShape(const char *text, int len, PasteShape shape); - void ClearSelection(bool retainMultipleSelections = false); - void ClearAll(); - void ClearDocumentStyle(); - void Cut(); - void PasteRectangular(SelectionPosition pos, const char *ptr, int len); - virtual void Copy() = 0; - virtual void CopyAllowLine(); - virtual bool CanPaste(); - virtual void Paste() = 0; - void Clear(); - void SelectAll(); - void Undo(); - void Redo(); - void DelCharBack(bool allowLineStartDeletion); - virtual void ClaimSelection() = 0; - - static int ModifierFlags(bool shift, bool ctrl, bool alt, bool meta=false); - virtual void NotifyChange() = 0; - virtual void NotifyFocus(bool focus); - virtual void SetCtrlID(int identifier); - virtual int GetCtrlID() { return ctrlID; } - virtual void NotifyParent(SCNotification scn) = 0; - virtual void NotifyStyleToNeeded(int endStyleNeeded); - void NotifyChar(int ch); - void NotifySavePoint(bool isSavePoint); - void NotifyModifyAttempt(); - virtual void NotifyDoubleClick(Point pt, int modifiers); - virtual void NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt); - void NotifyHotSpotClicked(int position, int modifiers); - void NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt); - void NotifyHotSpotDoubleClicked(int position, int modifiers); - void NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt); - void NotifyHotSpotReleaseClick(int position, int modifiers); - void NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool alt); - bool NotifyUpdateUI(); - void NotifyPainted(); - void NotifyIndicatorClick(bool click, int position, int modifiers); - void NotifyIndicatorClick(bool click, int position, bool shift, bool ctrl, bool alt); - bool NotifyMarginClick(Point pt, int modifiers); - bool NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt); - void NotifyNeedShown(int pos, int len); - void NotifyDwelling(Point pt, bool state); - void NotifyZoom(); - - void NotifyModifyAttempt(Document *document, void *userData); - void NotifySavePoint(Document *document, void *userData, bool atSavePoint); - void CheckModificationForWrap(DocModification mh); - void NotifyModified(Document *document, DocModification mh, void *userData); - void NotifyDeleted(Document *document, void *userData); - void NotifyStyleNeeded(Document *doc, void *userData, int endPos); - void NotifyLexerChanged(Document *doc, void *userData); - void NotifyErrorOccurred(Document *doc, void *userData, int status); - void NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam); - - void ContainerNeedsUpdate(int flags); - void PageMove(int direction, Selection::selTypes selt=Selection::noSel, bool stuttered = false); - enum { cmSame, cmUpper, cmLower }; - virtual std::string CaseMapString(const std::string &s, int caseMapping); - void ChangeCaseOfSelection(int caseMapping); - void LineTranspose(); - void Duplicate(bool forLine); - virtual void CancelModes(); - void NewLine(); - void CursorUpOrDown(int direction, Selection::selTypes selt=Selection::noSel); - void ParaUpOrDown(int direction, Selection::selTypes selt=Selection::noSel); - int StartEndDisplayLine(int pos, bool start); - virtual int KeyCommand(unsigned int iMessage); - virtual int KeyDefault(int /* key */, int /*modifiers*/); - int KeyDownWithModifiers(int key, int modifiers, bool *consumed); - int KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed=0); - - void Indent(bool forwards); - - virtual CaseFolder *CaseFolderForEncoding(); - long FindText(uptr_t wParam, sptr_t lParam); - void SearchAnchor(); - long SearchText(unsigned int iMessage, uptr_t wParam, sptr_t lParam); - long SearchInTarget(const char *text, int length); - void GoToLine(int lineNo); - - virtual void CopyToClipboard(const SelectionText &selectedText) = 0; - std::string RangeText(int start, int end) const; - void CopySelectionRange(SelectionText *ss, bool allowLineCopy=false); - void CopyRangeToClipboard(int start, int end); - void CopyText(int length, const char *text); - void SetDragPosition(SelectionPosition newPos); - virtual void DisplayCursor(Window::Cursor c); - virtual bool DragThreshold(Point ptStart, Point ptNow); - virtual void StartDrag(); - void DropAt(SelectionPosition position, const char *value, size_t lengthValue, bool moving, bool rectangular); - void DropAt(SelectionPosition position, const char *value, bool moving, bool rectangular); - /** PositionInSelection returns true if position in selection. */ - bool PositionInSelection(int pos); - bool PointInSelection(Point pt); - bool PointInSelMargin(Point pt) const; - Window::Cursor GetMarginCursor(Point pt) const; - void TrimAndSetSelection(int currentPos_, int anchor_); - void LineSelection(int lineCurrentPos_, int lineAnchorPos_, bool wholeLine); - void WordSelection(int pos); - void DwellEnd(bool mouseMoved); - void MouseLeave(); - virtual void ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers); - virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt); - void ButtonMoveWithModifiers(Point pt, int modifiers); - void ButtonMove(Point pt); - void ButtonUp(Point pt, unsigned int curTime, bool ctrl); - - void Tick(); - bool Idle(); - virtual void SetTicking(bool on); - enum TickReason { tickCaret, tickScroll, tickWiden, tickDwell, tickPlatform }; - virtual void TickFor(TickReason reason); - virtual bool FineTickerAvailable(); - virtual bool FineTickerRunning(TickReason reason); - virtual void FineTickerStart(TickReason reason, int millis, int tolerance); - virtual void FineTickerCancel(TickReason reason); - virtual bool SetIdle(bool) { return false; } - virtual void SetMouseCapture(bool on) = 0; - virtual bool HaveMouseCapture() = 0; - void SetFocusState(bool focusState); - - int PositionAfterArea(PRectangle rcArea) const; - void StyleToPositionInView(Position pos); - virtual void IdleWork(); - virtual void QueueIdleWork(WorkNeeded::workItems items, int upTo=0); - - virtual bool PaintContains(PRectangle rc); - bool PaintContainsMargin(); - void CheckForChangeOutsidePaint(Range r); - void SetBraceHighlight(Position pos0, Position pos1, int matchStyle); - - void SetAnnotationHeights(int start, int end); - virtual void SetDocPointer(Document *document); - - void SetAnnotationVisible(int visible); - - int ExpandLine(int line); - void SetFoldExpanded(int lineDoc, bool expanded); - void FoldLine(int line, int action); - void FoldExpand(int line, int action, int level); - int ContractedFoldNext(int lineStart) const; - void EnsureLineVisible(int lineDoc, bool enforcePolicy); - void FoldChanged(int line, int levelNow, int levelPrev); - void NeedShown(int pos, int len); - void FoldAll(int action); - - int GetTag(char *tagValue, int tagNumber); - int ReplaceTarget(bool replacePatterns, const char *text, int length=-1); - - bool PositionIsHotspot(int position) const; - bool PointIsHotspot(Point pt); - void SetHotSpotRange(Point *pt); - Range GetHotSpotRange() const; - void SetHoverIndicatorPosition(int position); - void SetHoverIndicatorPoint(Point pt); - - int CodePage() const; - virtual bool ValidCodePage(int /* codePage */) const { return true; } - int WrapCount(int line); - void AddStyledText(char *buffer, int appendLength); - - virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0; - void StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam); - sptr_t StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam); - - static const char *StringFromEOLMode(int eolMode); - - static sptr_t StringResult(sptr_t lParam, const char *val); - static sptr_t BytesResult(sptr_t lParam, const unsigned char *val, size_t len); - -public: - // Public so the COM thunks can access it. - bool IsUnicodeMode() const; - // Public so scintilla_send_message can use it. - virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); - // Public so scintilla_set_id can use it. - int ctrlID; - // Public so COM methods for drag and drop can set it. - int errorStatus; - friend class AutoSurface; - friend class SelectionLineIterator; -}; - -/** - * A smart pointer class to ensure Surfaces are set up and deleted correctly. - */ -class AutoSurface { -private: - Surface *surf; -public: - AutoSurface(Editor *ed, int technology = -1) : surf(0) { - if (ed->wMain.GetID()) { - surf = Surface::Allocate(technology != -1 ? technology : ed->technology); - if (surf) { - surf->Init(ed->wMain.GetID()); - surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage()); - surf->SetDBCSMode(ed->CodePage()); - } - } - } - AutoSurface(SurfaceID sid, Editor *ed, int technology = -1) : surf(0) { - if (ed->wMain.GetID()) { - surf = Surface::Allocate(technology != -1 ? technology : ed->technology); - if (surf) { - surf->Init(sid, ed->wMain.GetID()); - surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage()); - surf->SetDBCSMode(ed->CodePage()); - } - } - } - ~AutoSurface() { - delete surf; - } - Surface *operator->() const { - return surf; - } - operator Surface *() const { - return surf; - } -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/ExternalLexer.cpp b/libs/qscintilla/src/ExternalLexer.cpp deleted file mode 100644 index 25d83ceb8..000000000 --- a/libs/qscintilla/src/ExternalLexer.cpp +++ /dev/null @@ -1,191 +0,0 @@ -// Scintilla source code edit control -/** @file ExternalLexer.cxx - ** Support external lexers in DLLs. - **/ -// Copyright 2001 Simon Steele , portions copyright Neil Hodgson. -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include - -#include "Platform.h" - -#include "ILexer.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#include "LexerModule.h" -#include "Catalogue.h" -#include "ExternalLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -LexerManager *LexerManager::theInstance = NULL; - -//------------------------------------------ -// -// ExternalLexerModule -// -//------------------------------------------ - -void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) { - fneFactory = fFactory; - fnFactory = fFactory(index); -} - -//------------------------------------------ -// -// LexerLibrary -// -//------------------------------------------ - -LexerLibrary::LexerLibrary(const char *ModuleName) { - // Initialise some members... - first = NULL; - last = NULL; - - // Load the DLL - lib = DynamicLibrary::Load(ModuleName); - if (lib->IsValid()) { - m_sModuleName = ModuleName; - //Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects - GetLexerCountFn GetLexerCount = (GetLexerCountFn)(sptr_t)lib->FindFunction("GetLexerCount"); - - if (GetLexerCount) { - ExternalLexerModule *lex; - LexerMinder *lm; - - // Find functions in the DLL - GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName"); - GetLexerFactoryFunction fnFactory = (GetLexerFactoryFunction)(sptr_t)lib->FindFunction("GetLexerFactory"); - - int nl = GetLexerCount(); - - for (int i = 0; i < nl; i++) { - // Assign a buffer for the lexer name. - char lexname[100] = ""; - GetLexerName(i, lexname, sizeof(lexname)); - lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL); - Catalogue::AddLexerModule(lex); - - // Create a LexerMinder so we don't leak the ExternalLexerModule... - lm = new LexerMinder; - lm->self = lex; - lm->next = NULL; - if (first != NULL) { - last->next = lm; - last = lm; - } else { - first = lm; - last = lm; - } - - // The external lexer needs to know how to call into its DLL to - // do its lexing and folding, we tell it here. - lex->SetExternal(fnFactory, i); - } - } - } - next = NULL; -} - -LexerLibrary::~LexerLibrary() { - Release(); - delete lib; -} - -void LexerLibrary::Release() { - LexerMinder *lm; - LexerMinder *lmNext; - lm = first; - while (NULL != lm) { - lmNext = lm->next; - delete lm->self; - delete lm; - lm = lmNext; - } - - first = NULL; - last = NULL; -} - -//------------------------------------------ -// -// LexerManager -// -//------------------------------------------ - -/// Return the single LexerManager instance... -LexerManager *LexerManager::GetInstance() { - if (!theInstance) - theInstance = new LexerManager; - return theInstance; -} - -/// Delete any LexerManager instance... -void LexerManager::DeleteInstance() { - delete theInstance; - theInstance = NULL; -} - -/// protected constructor - this is a singleton... -LexerManager::LexerManager() { - first = NULL; - last = NULL; -} - -LexerManager::~LexerManager() { - Clear(); -} - -void LexerManager::Load(const char *path) { - LoadLexerLibrary(path); -} - -void LexerManager::LoadLexerLibrary(const char *module) { - for (LexerLibrary *ll = first; ll; ll= ll->next) { - if (strcmp(ll->m_sModuleName.c_str(), module) == 0) - return; - } - LexerLibrary *lib = new LexerLibrary(module); - if (NULL != first) { - last->next = lib; - last = lib; - } else { - first = lib; - last = lib; - } -} - -void LexerManager::Clear() { - if (NULL != first) { - LexerLibrary *cur = first; - LexerLibrary *next; - while (cur) { - next = cur->next; - delete cur; - cur = next; - } - first = NULL; - last = NULL; - } -} - -//------------------------------------------ -// -// LexerManager -// -//------------------------------------------ - -LMMinder::~LMMinder() { - LexerManager::DeleteInstance(); -} - -LMMinder minder; diff --git a/libs/qscintilla/src/ExternalLexer.h b/libs/qscintilla/src/ExternalLexer.h deleted file mode 100644 index 191f64976..000000000 --- a/libs/qscintilla/src/ExternalLexer.h +++ /dev/null @@ -1,99 +0,0 @@ -// Scintilla source code edit control -/** @file ExternalLexer.h - ** Support external lexers in DLLs. - **/ -// Copyright 2001 Simon Steele , portions copyright Neil Hodgson. -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef EXTERNALLEXER_H -#define EXTERNALLEXER_H - -#if PLAT_WIN -#define EXT_LEXER_DECL __stdcall -#elif PLAT_QT -#include -#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) -#define EXT_LEXER_DECL __stdcall -#else -#define EXT_LEXER_DECL -#endif -#else -#define EXT_LEXER_DECL -#endif - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -typedef void*(EXT_LEXER_DECL *GetLexerFunction)(unsigned int Index); -typedef int (EXT_LEXER_DECL *GetLexerCountFn)(); -typedef void (EXT_LEXER_DECL *GetLexerNameFn)(unsigned int Index, char *name, int buflength); -typedef LexerFactoryFunction(EXT_LEXER_DECL *GetLexerFactoryFunction)(unsigned int Index); - -/// Sub-class of LexerModule to use an external lexer. -class ExternalLexerModule : public LexerModule { -protected: - GetLexerFactoryFunction fneFactory; - std::string name; -public: - ExternalLexerModule(int language_, LexerFunction fnLexer_, - const char *languageName_=0, LexerFunction fnFolder_=0) : - LexerModule(language_, fnLexer_, 0, fnFolder_), - fneFactory(0), name(languageName_){ - languageName = name.c_str(); - } - virtual void SetExternal(GetLexerFactoryFunction fFactory, int index); -}; - -/// LexerMinder points to an ExternalLexerModule - so we don't leak them. -class LexerMinder { -public: - ExternalLexerModule *self; - LexerMinder *next; -}; - -/// LexerLibrary exists for every External Lexer DLL, contains LexerMinders. -class LexerLibrary { - DynamicLibrary *lib; - LexerMinder *first; - LexerMinder *last; - -public: - explicit LexerLibrary(const char *ModuleName); - ~LexerLibrary(); - void Release(); - - LexerLibrary *next; - std::string m_sModuleName; -}; - -/// LexerManager manages external lexers, contains LexerLibrarys. -class LexerManager { -public: - ~LexerManager(); - - static LexerManager *GetInstance(); - static void DeleteInstance(); - - void Load(const char *path); - void Clear(); - -private: - LexerManager(); - static LexerManager *theInstance; - - void LoadLexerLibrary(const char *module); - LexerLibrary *first; - LexerLibrary *last; -}; - -class LMMinder { -public: - ~LMMinder(); -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/Indicator.cpp b/libs/qscintilla/src/Indicator.cpp deleted file mode 100644 index 62df0b716..000000000 --- a/libs/qscintilla/src/Indicator.cpp +++ /dev/null @@ -1,180 +0,0 @@ -// Scintilla source code edit control -/** @file Indicator.cxx - ** Defines the style of indicators which are text decorations such as underlining. - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include - -#include "Platform.h" - -#include "Scintilla.h" -#include "Indicator.h" -#include "XPM.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static PRectangle PixelGridAlign(const PRectangle &rc) { - // Move left and right side to nearest pixel to avoid blurry visuals - return PRectangle::FromInts(int(rc.left + 0.5), int(rc.top), int(rc.right + 0.5), int(rc.bottom)); -} - -void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine, DrawState drawState, int value) const { - StyleAndColour sacDraw = sacNormal; - if (Flags() & SC_INDICFLAG_VALUEFORE) { - sacDraw.fore = value & SC_INDICVALUEMASK; - } - if (drawState == drawHover) { - sacDraw = sacHover; - } - surface->PenColour(sacDraw.fore); - int ymid = static_cast(rc.bottom + rc.top) / 2; - if (sacDraw.style == INDIC_SQUIGGLE) { - int x = int(rc.left+0.5); - int xLast = int(rc.right+0.5); - int y = 0; - surface->MoveTo(x, static_cast(rc.top) + y); - while (x < xLast) { - if ((x + 2) > xLast) { - if (xLast > x) - y = 1; - x = xLast; - } else { - x += 2; - y = 2 - y; - } - surface->LineTo(x, static_cast(rc.top) + y); - } - } else if (sacDraw.style == INDIC_SQUIGGLEPIXMAP) { - PRectangle rcSquiggle = PixelGridAlign(rc); - - int width = Platform::Minimum(4000, static_cast(rcSquiggle.Width())); - RGBAImage image(width, 3, 1.0, 0); - enum { alphaFull = 0xff, alphaSide = 0x2f, alphaSide2=0x5f }; - for (int x = 0; x < width; x++) { - if (x%2) { - // Two halfway columns have a full pixel in middle flanked by light pixels - image.SetPixel(x, 0, sacDraw.fore, alphaSide); - image.SetPixel(x, 1, sacDraw.fore, alphaFull); - image.SetPixel(x, 2, sacDraw.fore, alphaSide); - } else { - // Extreme columns have a full pixel at bottom or top and a mid-tone pixel in centre - image.SetPixel(x, (x % 4) ? 0 : 2, sacDraw.fore, alphaFull); - image.SetPixel(x, 1, sacDraw.fore, alphaSide2); - } - } - surface->DrawRGBAImage(rcSquiggle, image.GetWidth(), image.GetHeight(), image.Pixels()); - } else if (sacDraw.style == INDIC_SQUIGGLELOW) { - surface->MoveTo(static_cast(rc.left), static_cast(rc.top)); - int x = static_cast(rc.left) + 3; - int y = 0; - while (x < rc.right) { - surface->LineTo(x - 1, static_cast(rc.top) + y); - y = 1 - y; - surface->LineTo(x, static_cast(rc.top) + y); - x += 3; - } - surface->LineTo(static_cast(rc.right), static_cast(rc.top) + y); // Finish the line - } else if (sacDraw.style == INDIC_TT) { - surface->MoveTo(static_cast(rc.left), ymid); - int x = static_cast(rc.left) + 5; - while (x < rc.right) { - surface->LineTo(x, ymid); - surface->MoveTo(x-3, ymid); - surface->LineTo(x-3, ymid+2); - x++; - surface->MoveTo(x, ymid); - x += 5; - } - surface->LineTo(static_cast(rc.right), ymid); // Finish the line - if (x - 3 <= rc.right) { - surface->MoveTo(x-3, ymid); - surface->LineTo(x-3, ymid+2); - } - } else if (sacDraw.style == INDIC_DIAGONAL) { - int x = static_cast(rc.left); - while (x < rc.right) { - surface->MoveTo(x, static_cast(rc.top) + 2); - int endX = x+3; - int endY = static_cast(rc.top) - 1; - if (endX > rc.right) { - endY += endX - static_cast(rc.right); - endX = static_cast(rc.right); - } - surface->LineTo(endX, endY); - x += 4; - } - } else if (sacDraw.style == INDIC_STRIKE) { - surface->MoveTo(static_cast(rc.left), static_cast(rc.top) - 4); - surface->LineTo(static_cast(rc.right), static_cast(rc.top) - 4); - } else if ((sacDraw.style == INDIC_HIDDEN) || (sacDraw.style == INDIC_TEXTFORE)) { - // Draw nothing - } else if (sacDraw.style == INDIC_BOX) { - surface->MoveTo(static_cast(rc.left), ymid + 1); - surface->LineTo(static_cast(rc.right), ymid + 1); - surface->LineTo(static_cast(rc.right), static_cast(rcLine.top) + 1); - surface->LineTo(static_cast(rc.left), static_cast(rcLine.top) + 1); - surface->LineTo(static_cast(rc.left), ymid + 1); - } else if (sacDraw.style == INDIC_ROUNDBOX || - sacDraw.style == INDIC_STRAIGHTBOX || - sacDraw.style == INDIC_FULLBOX) { - PRectangle rcBox = rcLine; - if (sacDraw.style != INDIC_FULLBOX) - rcBox.top = rcLine.top + 1; - rcBox.left = rc.left; - rcBox.right = rc.right; - surface->AlphaRectangle(rcBox, (sacDraw.style == INDIC_ROUNDBOX) ? 1 : 0, - sacDraw.fore, fillAlpha, sacDraw.fore, outlineAlpha, 0); - } else if (sacDraw.style == INDIC_DOTBOX) { - PRectangle rcBox = PixelGridAlign(rc); - rcBox.top = rcLine.top + 1; - rcBox.bottom = rcLine.bottom; - // Cap width at 4000 to avoid large allocations when mistakes made - int width = Platform::Minimum(static_cast(rcBox.Width()), 4000); - RGBAImage image(width, static_cast(rcBox.Height()), 1.0, 0); - // Draw horizontal lines top and bottom - for (int x=0; x(rcBox.Height()); y += static_cast(rcBox.Height()) - 1) { - image.SetPixel(x, y, sacDraw.fore, ((x + y) % 2) ? outlineAlpha : fillAlpha); - } - } - // Draw vertical lines left and right - for (int y = 1; y(rcBox.Height()); y++) { - for (int x=0; xDrawRGBAImage(rcBox, image.GetWidth(), image.GetHeight(), image.Pixels()); - } else if (sacDraw.style == INDIC_DASH) { - int x = static_cast(rc.left); - while (x < rc.right) { - surface->MoveTo(x, ymid); - surface->LineTo(Platform::Minimum(x + 4, static_cast(rc.right)), ymid); - x += 7; - } - } else if (sacDraw.style == INDIC_DOTS) { - int x = static_cast(rc.left); - while (x < static_cast(rc.right)) { - PRectangle rcDot = PRectangle::FromInts(x, ymid, x + 1, ymid + 1); - surface->FillRectangle(rcDot, sacDraw.fore); - x += 2; - } - } else if (sacDraw.style == INDIC_COMPOSITIONTHICK) { - PRectangle rcComposition(rc.left+1, rcLine.bottom-2, rc.right-1, rcLine.bottom); - surface->FillRectangle(rcComposition, sacDraw.fore); - } else if (sacDraw.style == INDIC_COMPOSITIONTHIN) { - PRectangle rcComposition(rc.left+1, rcLine.bottom-2, rc.right-1, rcLine.bottom-1); - surface->FillRectangle(rcComposition, sacDraw.fore); - } else { // Either INDIC_PLAIN or unknown - surface->MoveTo(static_cast(rc.left), ymid); - surface->LineTo(static_cast(rc.right), ymid); - } -} - -void Indicator::SetFlags(int attributes_) { - attributes = attributes_; -} diff --git a/libs/qscintilla/src/License.txt b/libs/qscintilla/src/License.txt deleted file mode 100644 index cbe25b2fc..000000000 --- a/libs/qscintilla/src/License.txt +++ /dev/null @@ -1,20 +0,0 @@ -License for Scintilla and SciTE - -Copyright 1998-2003 by Neil Hodgson - -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation. - -NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE -OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/libs/qscintilla/src/LineMarker.cpp b/libs/qscintilla/src/LineMarker.cpp deleted file mode 100644 index 98e75ca52..000000000 --- a/libs/qscintilla/src/LineMarker.cpp +++ /dev/null @@ -1,398 +0,0 @@ -// Scintilla source code edit control -/** @file LineMarker.cxx - ** Defines the look of a line marker in the margin. - **/ -// Copyright 1998-2011 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include - -#include -#include - -#include "Platform.h" - -#include "Scintilla.h" - -#include "StringCopy.h" -#include "XPM.h" -#include "LineMarker.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -void LineMarker::SetXPM(const char *textForm) { - delete pxpm; - pxpm = new XPM(textForm); - markType = SC_MARK_PIXMAP; -} - -void LineMarker::SetXPM(const char *const *linesForm) { - delete pxpm; - pxpm = new XPM(linesForm); - markType = SC_MARK_PIXMAP; -} - -void LineMarker::SetRGBAImage(Point sizeRGBAImage, float scale, const unsigned char *pixelsRGBAImage) { - delete image; - image = new RGBAImage(static_cast(sizeRGBAImage.x), static_cast(sizeRGBAImage.y), scale, pixelsRGBAImage); - markType = SC_MARK_RGBAIMAGE; -} - -static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) { - PRectangle rc = PRectangle::FromInts( - centreX - armSize, - centreY - armSize, - centreX + armSize + 1, - centreY + armSize + 1); - surface->RectangleDraw(rc, back, fore); -} - -static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) { - PRectangle rcCircle = PRectangle::FromInts( - centreX - armSize, - centreY - armSize, - centreX + armSize + 1, - centreY + armSize + 1); - surface->Ellipse(rcCircle, back, fore); -} - -static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) { - PRectangle rcV = PRectangle::FromInts(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1); - surface->FillRectangle(rcV, fore); - PRectangle rcH = PRectangle::FromInts(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY + 1); - surface->FillRectangle(rcH, fore); -} - -static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) { - PRectangle rcH = PRectangle::FromInts(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY + 1); - surface->FillRectangle(rcH, fore); -} - -void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, typeOfFold tFold, int marginStyle) const { - if (customDraw != NULL) { - customDraw(surface, rcWhole, fontForCharacter, tFold, marginStyle, this); - return; - } - - ColourDesired colourHead = back; - ColourDesired colourBody = back; - ColourDesired colourTail = back; - - switch (tFold) { - case LineMarker::head : - case LineMarker::headWithTail : - colourHead = backSelected; - colourTail = backSelected; - break; - case LineMarker::body : - colourHead = backSelected; - colourBody = backSelected; - break; - case LineMarker::tail : - colourBody = backSelected; - colourTail = backSelected; - break; - default : - // LineMarker::undefined - break; - } - - if ((markType == SC_MARK_PIXMAP) && (pxpm)) { - pxpm->Draw(surface, rcWhole); - return; - } - if ((markType == SC_MARK_RGBAIMAGE) && (image)) { - // Make rectangle just large enough to fit image centred on centre of rcWhole - PRectangle rcImage; - rcImage.top = ((rcWhole.top + rcWhole.bottom) - image->GetScaledHeight()) / 2; - rcImage.bottom = rcImage.top + image->GetScaledHeight(); - rcImage.left = ((rcWhole.left + rcWhole.right) - image->GetScaledWidth()) / 2; - rcImage.right = rcImage.left + image->GetScaledWidth(); - surface->DrawRGBAImage(rcImage, image->GetWidth(), image->GetHeight(), image->Pixels()); - return; - } - // Restrict most shapes a bit - PRectangle rc = rcWhole; - rc.top++; - rc.bottom--; - int minDim = Platform::Minimum(static_cast(rc.Width()), static_cast(rc.Height())); - minDim--; // Ensure does not go beyond edge - int centreX = static_cast(floor((rc.right + rc.left) / 2.0)); - int centreY = static_cast(floor((rc.bottom + rc.top) / 2.0)); - int dimOn2 = minDim / 2; - int dimOn4 = minDim / 4; - int blobSize = dimOn2-1; - int armSize = dimOn2-2; - if (marginStyle == SC_MARGIN_NUMBER || marginStyle == SC_MARGIN_TEXT || marginStyle == SC_MARGIN_RTEXT) { - // On textual margins move marker to the left to try to avoid overlapping the text - centreX = static_cast(rc.left) + dimOn2 + 1; - } - if (markType == SC_MARK_ROUNDRECT) { - PRectangle rcRounded = rc; - rcRounded.left = rc.left + 1; - rcRounded.right = rc.right - 1; - surface->RoundedRectangle(rcRounded, fore, back); - } else if (markType == SC_MARK_CIRCLE) { - PRectangle rcCircle = PRectangle::FromInts( - centreX - dimOn2, - centreY - dimOn2, - centreX + dimOn2, - centreY + dimOn2); - surface->Ellipse(rcCircle, fore, back); - } else if (markType == SC_MARK_ARROW) { - Point pts[] = { - Point::FromInts(centreX - dimOn4, centreY - dimOn2), - Point::FromInts(centreX - dimOn4, centreY + dimOn2), - Point::FromInts(centreX + dimOn2 - dimOn4, centreY), - }; - surface->Polygon(pts, ELEMENTS(pts), fore, back); - - } else if (markType == SC_MARK_ARROWDOWN) { - Point pts[] = { - Point::FromInts(centreX - dimOn2, centreY - dimOn4), - Point::FromInts(centreX + dimOn2, centreY - dimOn4), - Point::FromInts(centreX, centreY + dimOn2 - dimOn4), - }; - surface->Polygon(pts, ELEMENTS(pts), fore, back); - - } else if (markType == SC_MARK_PLUS) { - Point pts[] = { - Point::FromInts(centreX - armSize, centreY - 1), - Point::FromInts(centreX - 1, centreY - 1), - Point::FromInts(centreX - 1, centreY - armSize), - Point::FromInts(centreX + 1, centreY - armSize), - Point::FromInts(centreX + 1, centreY - 1), - Point::FromInts(centreX + armSize, centreY -1), - Point::FromInts(centreX + armSize, centreY +1), - Point::FromInts(centreX + 1, centreY + 1), - Point::FromInts(centreX + 1, centreY + armSize), - Point::FromInts(centreX - 1, centreY + armSize), - Point::FromInts(centreX - 1, centreY + 1), - Point::FromInts(centreX - armSize, centreY + 1), - }; - surface->Polygon(pts, ELEMENTS(pts), fore, back); - - } else if (markType == SC_MARK_MINUS) { - Point pts[] = { - Point::FromInts(centreX - armSize, centreY - 1), - Point::FromInts(centreX + armSize, centreY -1), - Point::FromInts(centreX + armSize, centreY +1), - Point::FromInts(centreX - armSize, centreY + 1), - }; - surface->Polygon(pts, ELEMENTS(pts), fore, back); - - } else if (markType == SC_MARK_SMALLRECT) { - PRectangle rcSmall; - rcSmall.left = rc.left + 1; - rcSmall.top = rc.top + 2; - rcSmall.right = rc.right - 1; - rcSmall.bottom = rc.bottom - 2; - surface->RectangleDraw(rcSmall, fore, back); - - } else if (markType == SC_MARK_EMPTY || markType == SC_MARK_BACKGROUND || - markType == SC_MARK_UNDERLINE || markType == SC_MARK_AVAILABLE) { - // An invisible marker so don't draw anything - - } else if (markType == SC_MARK_VLINE) { - surface->PenColour(colourBody); - surface->MoveTo(centreX, static_cast(rcWhole.top)); - surface->LineTo(centreX, static_cast(rcWhole.bottom)); - - } else if (markType == SC_MARK_LCORNER) { - surface->PenColour(colourTail); - surface->MoveTo(centreX, static_cast(rcWhole.top)); - surface->LineTo(centreX, centreY); - surface->LineTo(static_cast(rc.right) - 1, centreY); - - } else if (markType == SC_MARK_TCORNER) { - surface->PenColour(colourTail); - surface->MoveTo(centreX, centreY); - surface->LineTo(static_cast(rc.right) - 1, centreY); - - surface->PenColour(colourBody); - surface->MoveTo(centreX, static_cast(rcWhole.top)); - surface->LineTo(centreX, centreY + 1); - - surface->PenColour(colourHead); - surface->LineTo(centreX, static_cast(rcWhole.bottom)); - - } else if (markType == SC_MARK_LCORNERCURVE) { - surface->PenColour(colourTail); - surface->MoveTo(centreX, static_cast(rcWhole.top)); - surface->LineTo(centreX, centreY-3); - surface->LineTo(centreX+3, centreY); - surface->LineTo(static_cast(rc.right) - 1, centreY); - - } else if (markType == SC_MARK_TCORNERCURVE) { - surface->PenColour(colourTail); - surface->MoveTo(centreX, centreY-3); - surface->LineTo(centreX+3, centreY); - surface->LineTo(static_cast(rc.right) - 1, centreY); - - surface->PenColour(colourBody); - surface->MoveTo(centreX, static_cast(rcWhole.top)); - surface->LineTo(centreX, centreY-2); - - surface->PenColour(colourHead); - surface->LineTo(centreX, static_cast(rcWhole.bottom)); - - } else if (markType == SC_MARK_BOXPLUS) { - DrawBox(surface, centreX, centreY, blobSize, fore, colourHead); - DrawPlus(surface, centreX, centreY, blobSize, colourTail); - - } else if (markType == SC_MARK_BOXPLUSCONNECTED) { - if (tFold == LineMarker::headWithTail) - surface->PenColour(colourTail); - else - surface->PenColour(colourBody); - surface->MoveTo(centreX, centreY + blobSize); - surface->LineTo(centreX, static_cast(rcWhole.bottom)); - - surface->PenColour(colourBody); - surface->MoveTo(centreX, static_cast(rcWhole.top)); - surface->LineTo(centreX, centreY - blobSize); - - DrawBox(surface, centreX, centreY, blobSize, fore, colourHead); - DrawPlus(surface, centreX, centreY, blobSize, colourTail); - - if (tFold == LineMarker::body) { - surface->PenColour(colourTail); - surface->MoveTo(centreX + 1, centreY + blobSize); - surface->LineTo(centreX + blobSize + 1, centreY + blobSize); - - surface->MoveTo(centreX + blobSize, centreY + blobSize); - surface->LineTo(centreX + blobSize, centreY - blobSize); - - surface->MoveTo(centreX + 1, centreY - blobSize); - surface->LineTo(centreX + blobSize + 1, centreY - blobSize); - } - } else if (markType == SC_MARK_BOXMINUS) { - DrawBox(surface, centreX, centreY, blobSize, fore, colourHead); - DrawMinus(surface, centreX, centreY, blobSize, colourTail); - - surface->PenColour(colourHead); - surface->MoveTo(centreX, centreY + blobSize); - surface->LineTo(centreX, static_cast(rcWhole.bottom)); - - } else if (markType == SC_MARK_BOXMINUSCONNECTED) { - DrawBox(surface, centreX, centreY, blobSize, fore, colourHead); - DrawMinus(surface, centreX, centreY, blobSize, colourTail); - - surface->PenColour(colourHead); - surface->MoveTo(centreX, centreY + blobSize); - surface->LineTo(centreX, static_cast(rcWhole.bottom)); - - surface->PenColour(colourBody); - surface->MoveTo(centreX, static_cast(rcWhole.top)); - surface->LineTo(centreX, centreY - blobSize); - - if (tFold == LineMarker::body) { - surface->PenColour(colourTail); - surface->MoveTo(centreX + 1, centreY + blobSize); - surface->LineTo(centreX + blobSize + 1, centreY + blobSize); - - surface->MoveTo(centreX + blobSize, centreY + blobSize); - surface->LineTo(centreX + blobSize, centreY - blobSize); - - surface->MoveTo(centreX + 1, centreY - blobSize); - surface->LineTo(centreX + blobSize + 1, centreY - blobSize); - } - } else if (markType == SC_MARK_CIRCLEPLUS) { - DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead); - DrawPlus(surface, centreX, centreY, blobSize, colourTail); - - } else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) { - if (tFold == LineMarker::headWithTail) - surface->PenColour(colourTail); - else - surface->PenColour(colourBody); - surface->MoveTo(centreX, centreY + blobSize); - surface->LineTo(centreX, static_cast(rcWhole.bottom)); - - surface->PenColour(colourBody); - surface->MoveTo(centreX, static_cast(rcWhole.top)); - surface->LineTo(centreX, centreY - blobSize); - - DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead); - DrawPlus(surface, centreX, centreY, blobSize, colourTail); - - } else if (markType == SC_MARK_CIRCLEMINUS) { - surface->PenColour(colourHead); - surface->MoveTo(centreX, centreY + blobSize); - surface->LineTo(centreX, static_cast(rcWhole.bottom)); - - DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead); - DrawMinus(surface, centreX, centreY, blobSize, colourTail); - - } else if (markType == SC_MARK_CIRCLEMINUSCONNECTED) { - surface->PenColour(colourHead); - surface->MoveTo(centreX, centreY + blobSize); - surface->LineTo(centreX, static_cast(rcWhole.bottom)); - - surface->PenColour(colourBody); - surface->MoveTo(centreX, static_cast(rcWhole.top)); - surface->LineTo(centreX, centreY - blobSize); - - DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead); - DrawMinus(surface, centreX, centreY, blobSize, colourTail); - - } else if (markType >= SC_MARK_CHARACTER) { - char character[1]; - character[0] = static_cast(markType - SC_MARK_CHARACTER); - XYPOSITION width = surface->WidthText(fontForCharacter, character, 1); - rc.left += (rc.Width() - width) / 2; - rc.right = rc.left + width; - surface->DrawTextClipped(rc, fontForCharacter, rc.bottom - 2, - character, 1, fore, back); - - } else if (markType == SC_MARK_DOTDOTDOT) { - XYPOSITION right = static_cast(centreX - 6); - for (int b=0; b<3; b++) { - PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom-2); - surface->FillRectangle(rcBlob, fore); - right += 5.0f; - } - } else if (markType == SC_MARK_ARROWS) { - surface->PenColour(fore); - int right = centreX - 2; - const int armLength = dimOn2 - 1; - for (int b = 0; b<3; b++) { - surface->MoveTo(right, centreY); - surface->LineTo(right - armLength, centreY - armLength); - surface->MoveTo(right, centreY); - surface->LineTo(right - armLength, centreY + armLength); - right += 4; - } - } else if (markType == SC_MARK_SHORTARROW) { - Point pts[] = { - Point::FromInts(centreX, centreY + dimOn2), - Point::FromInts(centreX + dimOn2, centreY), - Point::FromInts(centreX, centreY - dimOn2), - Point::FromInts(centreX, centreY - dimOn4), - Point::FromInts(centreX - dimOn4, centreY - dimOn4), - Point::FromInts(centreX - dimOn4, centreY + dimOn4), - Point::FromInts(centreX, centreY + dimOn4), - Point::FromInts(centreX, centreY + dimOn2), - }; - surface->Polygon(pts, ELEMENTS(pts), fore, back); - } else if (markType == SC_MARK_LEFTRECT) { - PRectangle rcLeft = rcWhole; - rcLeft.right = rcLeft.left + 4; - surface->FillRectangle(rcLeft, back); - } else if (markType == SC_MARK_BOOKMARK) { - int halfHeight = minDim / 3; - Point pts[] = { - Point::FromInts(static_cast(rc.left), centreY-halfHeight), - Point::FromInts(static_cast(rc.right) - 3, centreY - halfHeight), - Point::FromInts(static_cast(rc.right) - 3 - halfHeight, centreY), - Point::FromInts(static_cast(rc.right) - 3, centreY + halfHeight), - Point::FromInts(static_cast(rc.left), centreY + halfHeight), - }; - surface->Polygon(pts, ELEMENTS(pts), fore, back); - } else { // SC_MARK_FULLRECT - surface->FillRectangle(rcWhole, back); - } -} diff --git a/libs/qscintilla/src/LineMarker.h b/libs/qscintilla/src/LineMarker.h deleted file mode 100644 index 6a5fe7492..000000000 --- a/libs/qscintilla/src/LineMarker.h +++ /dev/null @@ -1,86 +0,0 @@ -// Scintilla source code edit control -/** @file LineMarker.h - ** Defines the look of a line marker in the margin . - **/ -// Copyright 1998-2011 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef LINEMARKER_H -#define LINEMARKER_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -typedef void (*DrawLineMarkerFn)(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, int tFold, int marginStyle, const void *lineMarker); - -/** - */ -class LineMarker { -public: - enum typeOfFold { undefined, head, body, tail, headWithTail }; - - int markType; - ColourDesired fore; - ColourDesired back; - ColourDesired backSelected; - int alpha; - XPM *pxpm; - RGBAImage *image; - /** Some platforms, notably PLAT_CURSES, do not support Scintilla's native - * Draw function for drawing line markers. Allow those platforms to override - * it instead of creating a new method(s) in the Surface class that existing - * platforms must implement as empty. */ - DrawLineMarkerFn customDraw; - LineMarker() { - markType = SC_MARK_CIRCLE; - fore = ColourDesired(0,0,0); - back = ColourDesired(0xff,0xff,0xff); - backSelected = ColourDesired(0xff,0x00,0x00); - alpha = SC_ALPHA_NOALPHA; - pxpm = NULL; - image = NULL; - customDraw = NULL; - } - LineMarker(const LineMarker &) { - // Defined to avoid pxpm being blindly copied, not as a complete copy constructor - markType = SC_MARK_CIRCLE; - fore = ColourDesired(0,0,0); - back = ColourDesired(0xff,0xff,0xff); - backSelected = ColourDesired(0xff,0x00,0x00); - alpha = SC_ALPHA_NOALPHA; - pxpm = NULL; - image = NULL; - customDraw = NULL; - } - ~LineMarker() { - delete pxpm; - delete image; - } - LineMarker &operator=(const LineMarker &other) { - // Defined to avoid pxpm being blindly copied, not as a complete assignment operator - if (this != &other) { - markType = SC_MARK_CIRCLE; - fore = ColourDesired(0,0,0); - back = ColourDesired(0xff,0xff,0xff); - backSelected = ColourDesired(0xff,0x00,0x00); - alpha = SC_ALPHA_NOALPHA; - delete pxpm; - pxpm = NULL; - delete image; - image = NULL; - customDraw = NULL; - } - return *this; - } - void SetXPM(const char *textForm); - void SetXPM(const char *const *linesForm); - void SetRGBAImage(Point sizeRGBAImage, float scale, const unsigned char *pixelsRGBAImage); - void Draw(Surface *surface, PRectangle &rc, Font &fontForCharacter, typeOfFold tFold, int marginStyle) const; -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/Partitioning.h b/libs/qscintilla/src/Partitioning.h deleted file mode 100644 index 688b38d7d..000000000 --- a/libs/qscintilla/src/Partitioning.h +++ /dev/null @@ -1,198 +0,0 @@ -// Scintilla source code edit control -/** @file Partitioning.h - ** Data structure used to partition an interval. Used for holding line start/end positions. - **/ -// Copyright 1998-2007 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef PARTITIONING_H -#define PARTITIONING_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -/// A split vector of integers with a method for adding a value to all elements -/// in a range. -/// Used by the Partitioning class. - -class SplitVectorWithRangeAdd : public SplitVector { -public: - explicit SplitVectorWithRangeAdd(int growSize_) { - SetGrowSize(growSize_); - ReAllocate(growSize_); - } - ~SplitVectorWithRangeAdd() { - } - void RangeAddDelta(int start, int end, int delta) { - // end is 1 past end, so end-start is number of elements to change - int i = 0; - int rangeLength = end - start; - int range1Length = rangeLength; - int part1Left = part1Length - start; - if (range1Length > part1Left) - range1Length = part1Left; - while (i < range1Length) { - body[start++] += delta; - i++; - } - start += gapLength; - while (i < rangeLength) { - body[start++] += delta; - i++; - } - } -}; - -/// Divide an interval into multiple partitions. -/// Useful for breaking a document down into sections such as lines. -/// A 0 length interval has a single 0 length partition, numbered 0 -/// If interval not 0 length then each partition non-zero length -/// When needed, positions after the interval are considered part of the last partition -/// but the end of the last partition can be found with PositionFromPartition(last+1). - -class Partitioning { -private: - // To avoid calculating all the partition positions whenever any text is inserted - // there may be a step somewhere in the list. - int stepPartition; - int stepLength; - SplitVectorWithRangeAdd *body; - - // Move step forward - void ApplyStep(int partitionUpTo) { - if (stepLength != 0) { - body->RangeAddDelta(stepPartition+1, partitionUpTo + 1, stepLength); - } - stepPartition = partitionUpTo; - if (stepPartition >= body->Length()-1) { - stepPartition = body->Length()-1; - stepLength = 0; - } - } - - // Move step backward - void BackStep(int partitionDownTo) { - if (stepLength != 0) { - body->RangeAddDelta(partitionDownTo+1, stepPartition+1, -stepLength); - } - stepPartition = partitionDownTo; - } - - void Allocate(int growSize) { - body = new SplitVectorWithRangeAdd(growSize); - stepPartition = 0; - stepLength = 0; - body->Insert(0, 0); // This value stays 0 for ever - body->Insert(1, 0); // This is the end of the first partition and will be the start of the second - } - -public: - explicit Partitioning(int growSize) { - Allocate(growSize); - } - - ~Partitioning() { - delete body; - body = 0; - } - - int Partitions() const { - return body->Length()-1; - } - - void InsertPartition(int partition, int pos) { - if (stepPartition < partition) { - ApplyStep(partition); - } - body->Insert(partition, pos); - stepPartition++; - } - - void SetPartitionStartPosition(int partition, int pos) { - ApplyStep(partition+1); - if ((partition < 0) || (partition > body->Length())) { - return; - } - body->SetValueAt(partition, pos); - } - - void InsertText(int partitionInsert, int delta) { - // Point all the partitions after the insertion point further along in the buffer - if (stepLength != 0) { - if (partitionInsert >= stepPartition) { - // Fill in up to the new insertion point - ApplyStep(partitionInsert); - stepLength += delta; - } else if (partitionInsert >= (stepPartition - body->Length() / 10)) { - // Close to step but before so move step back - BackStep(partitionInsert); - stepLength += delta; - } else { - ApplyStep(body->Length()-1); - stepPartition = partitionInsert; - stepLength = delta; - } - } else { - stepPartition = partitionInsert; - stepLength = delta; - } - } - - void RemovePartition(int partition) { - if (partition > stepPartition) { - ApplyStep(partition); - stepPartition--; - } else { - stepPartition--; - } - body->Delete(partition); - } - - int PositionFromPartition(int partition) const { - PLATFORM_ASSERT(partition >= 0); - PLATFORM_ASSERT(partition < body->Length()); - if ((partition < 0) || (partition >= body->Length())) { - return 0; - } - int pos = body->ValueAt(partition); - if (partition > stepPartition) - pos += stepLength; - return pos; - } - - /// Return value in range [0 .. Partitions() - 1] even for arguments outside interval - int PartitionFromPosition(int pos) const { - if (body->Length() <= 1) - return 0; - if (pos >= (PositionFromPartition(body->Length()-1))) - return body->Length() - 1 - 1; - int lower = 0; - int upper = body->Length()-1; - do { - int middle = (upper + lower + 1) / 2; // Round high - int posMiddle = body->ValueAt(middle); - if (middle > stepPartition) - posMiddle += stepLength; - if (pos < posMiddle) { - upper = middle - 1; - } else { - lower = middle; - } - } while (lower < upper); - return lower; - } - - void DeleteAll() { - int growSize = body->GetGrowSize(); - delete body; - Allocate(growSize); - } -}; - - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/PerLine.cpp b/libs/qscintilla/src/PerLine.cpp deleted file mode 100644 index 8fd96cbed..000000000 --- a/libs/qscintilla/src/PerLine.cpp +++ /dev/null @@ -1,556 +0,0 @@ -// Scintilla source code edit control -/** @file PerLine.cxx - ** Manages data associated with each line of the document - **/ -// Copyright 1998-2009 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include - -#include -#include - -#include "Platform.h" - -#include "Scintilla.h" -#include "SplitVector.h" -#include "Partitioning.h" -#include "CellBuffer.h" -#include "PerLine.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -MarkerHandleSet::MarkerHandleSet() { - root = 0; -} - -MarkerHandleSet::~MarkerHandleSet() { - MarkerHandleNumber *mhn = root; - while (mhn) { - MarkerHandleNumber *mhnToFree = mhn; - mhn = mhn->next; - delete mhnToFree; - } - root = 0; -} - -int MarkerHandleSet::Length() const { - int c = 0; - MarkerHandleNumber *mhn = root; - while (mhn) { - c++; - mhn = mhn->next; - } - return c; -} - -int MarkerHandleSet::MarkValue() const { - unsigned int m = 0; - MarkerHandleNumber *mhn = root; - while (mhn) { - m |= (1 << mhn->number); - mhn = mhn->next; - } - return m; -} - -bool MarkerHandleSet::Contains(int handle) const { - MarkerHandleNumber *mhn = root; - while (mhn) { - if (mhn->handle == handle) { - return true; - } - mhn = mhn->next; - } - return false; -} - -bool MarkerHandleSet::InsertHandle(int handle, int markerNum) { - MarkerHandleNumber *mhn = new MarkerHandleNumber; - mhn->handle = handle; - mhn->number = markerNum; - mhn->next = root; - root = mhn; - return true; -} - -void MarkerHandleSet::RemoveHandle(int handle) { - MarkerHandleNumber **pmhn = &root; - while (*pmhn) { - MarkerHandleNumber *mhn = *pmhn; - if (mhn->handle == handle) { - *pmhn = mhn->next; - delete mhn; - return; - } - pmhn = &((*pmhn)->next); - } -} - -bool MarkerHandleSet::RemoveNumber(int markerNum, bool all) { - bool performedDeletion = false; - MarkerHandleNumber **pmhn = &root; - while (*pmhn) { - MarkerHandleNumber *mhn = *pmhn; - if (mhn->number == markerNum) { - *pmhn = mhn->next; - delete mhn; - performedDeletion = true; - if (!all) - break; - } else { - pmhn = &((*pmhn)->next); - } - } - return performedDeletion; -} - -void MarkerHandleSet::CombineWith(MarkerHandleSet *other) { - MarkerHandleNumber **pmhn = &root; - while (*pmhn) { - pmhn = &((*pmhn)->next); - } - *pmhn = other->root; - other->root = 0; -} - -LineMarkers::~LineMarkers() { - Init(); -} - -void LineMarkers::Init() { - for (int line = 0; line < markers.Length(); line++) { - delete markers[line]; - markers[line] = 0; - } - markers.DeleteAll(); -} - -void LineMarkers::InsertLine(int line) { - if (markers.Length()) { - markers.Insert(line, 0); - } -} - -void LineMarkers::RemoveLine(int line) { - // Retain the markers from the deleted line by oring them into the previous line - if (markers.Length()) { - if (line > 0) { - MergeMarkers(line - 1); - } - markers.Delete(line); - } -} - -int LineMarkers::LineFromHandle(int markerHandle) { - if (markers.Length()) { - for (int line = 0; line < markers.Length(); line++) { - if (markers[line]) { - if (markers[line]->Contains(markerHandle)) { - return line; - } - } - } - } - return -1; -} - -void LineMarkers::MergeMarkers(int pos) { - if (markers[pos + 1] != NULL) { - if (markers[pos] == NULL) - markers[pos] = new MarkerHandleSet; - markers[pos]->CombineWith(markers[pos + 1]); - delete markers[pos + 1]; - markers[pos + 1] = NULL; - } -} - -int LineMarkers::MarkValue(int line) { - if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) - return markers[line]->MarkValue(); - else - return 0; -} - -int LineMarkers::MarkerNext(int lineStart, int mask) const { - if (lineStart < 0) - lineStart = 0; - int length = markers.Length(); - for (int iLine = lineStart; iLine < length; iLine++) { - MarkerHandleSet *onLine = markers[iLine]; - if (onLine && ((onLine->MarkValue() & mask) != 0)) - //if ((pdoc->GetMark(iLine) & lParam) != 0) - return iLine; - } - return -1; -} - -int LineMarkers::AddMark(int line, int markerNum, int lines) { - handleCurrent++; - if (!markers.Length()) { - // No existing markers so allocate one element per line - markers.InsertValue(0, lines, 0); - } - if (line >= markers.Length()) { - return -1; - } - if (!markers[line]) { - // Need new structure to hold marker handle - markers[line] = new MarkerHandleSet(); - } - markers[line]->InsertHandle(handleCurrent, markerNum); - - return handleCurrent; -} - -bool LineMarkers::DeleteMark(int line, int markerNum, bool all) { - bool someChanges = false; - if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) { - if (markerNum == -1) { - someChanges = true; - delete markers[line]; - markers[line] = NULL; - } else { - someChanges = markers[line]->RemoveNumber(markerNum, all); - if (markers[line]->Length() == 0) { - delete markers[line]; - markers[line] = NULL; - } - } - } - return someChanges; -} - -void LineMarkers::DeleteMarkFromHandle(int markerHandle) { - int line = LineFromHandle(markerHandle); - if (line >= 0) { - markers[line]->RemoveHandle(markerHandle); - if (markers[line]->Length() == 0) { - delete markers[line]; - markers[line] = NULL; - } - } -} - -LineLevels::~LineLevels() { -} - -void LineLevels::Init() { - levels.DeleteAll(); -} - -void LineLevels::InsertLine(int line) { - if (levels.Length()) { - int level = (line < levels.Length()) ? levels[line] : SC_FOLDLEVELBASE; - levels.InsertValue(line, 1, level); - } -} - -void LineLevels::RemoveLine(int line) { - if (levels.Length()) { - // Move up following lines but merge header flag from this line - // to line before to avoid a temporary disappearence causing expansion. - int firstHeader = levels[line] & SC_FOLDLEVELHEADERFLAG; - levels.Delete(line); - if (line == levels.Length()-1) // Last line loses the header flag - levels[line-1] &= ~SC_FOLDLEVELHEADERFLAG; - else if (line > 0) - levels[line-1] |= firstHeader; - } -} - -void LineLevels::ExpandLevels(int sizeNew) { - levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE); -} - -void LineLevels::ClearLevels() { - levels.DeleteAll(); -} - -int LineLevels::SetLevel(int line, int level, int lines) { - int prev = 0; - if ((line >= 0) && (line < lines)) { - if (!levels.Length()) { - ExpandLevels(lines + 1); - } - prev = levels[line]; - if (prev != level) { - levels[line] = level; - } - } - return prev; -} - -int LineLevels::GetLevel(int line) const { - if (levels.Length() && (line >= 0) && (line < levels.Length())) { - return levels[line]; - } else { - return SC_FOLDLEVELBASE; - } -} - -LineState::~LineState() { -} - -void LineState::Init() { - lineStates.DeleteAll(); -} - -void LineState::InsertLine(int line) { - if (lineStates.Length()) { - lineStates.EnsureLength(line); - int val = (line < lineStates.Length()) ? lineStates[line] : 0; - lineStates.Insert(line, val); - } -} - -void LineState::RemoveLine(int line) { - if (lineStates.Length() > line) { - lineStates.Delete(line); - } -} - -int LineState::SetLineState(int line, int state) { - lineStates.EnsureLength(line + 1); - int stateOld = lineStates[line]; - lineStates[line] = state; - return stateOld; -} - -int LineState::GetLineState(int line) { - if (line < 0) - return 0; - lineStates.EnsureLength(line + 1); - return lineStates[line]; -} - -int LineState::GetMaxLineState() const { - return lineStates.Length(); -} - -static int NumberLines(const char *text) { - if (text) { - int newLines = 0; - while (*text) { - if (*text == '\n') - newLines++; - text++; - } - return newLines+1; - } else { - return 0; - } -} - -// Each allocated LineAnnotation is a char array which starts with an AnnotationHeader -// and then has text and optional styles. - -static const int IndividualStyles = 0x100; - -struct AnnotationHeader { - short style; // Style IndividualStyles implies array of styles - short lines; - int length; -}; - -LineAnnotation::~LineAnnotation() { - ClearAll(); -} - -void LineAnnotation::Init() { - ClearAll(); -} - -void LineAnnotation::InsertLine(int line) { - if (annotations.Length()) { - annotations.EnsureLength(line); - annotations.Insert(line, 0); - } -} - -void LineAnnotation::RemoveLine(int line) { - if (annotations.Length() && (line > 0) && (line <= annotations.Length())) { - delete []annotations[line-1]; - annotations.Delete(line-1); - } -} - -bool LineAnnotation::MultipleStyles(int line) const { - if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) - return reinterpret_cast(annotations[line])->style == IndividualStyles; - else - return 0; -} - -int LineAnnotation::Style(int line) const { - if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) - return reinterpret_cast(annotations[line])->style; - else - return 0; -} - -const char *LineAnnotation::Text(int line) const { - if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) - return annotations[line]+sizeof(AnnotationHeader); - else - return 0; -} - -const unsigned char *LineAnnotation::Styles(int line) const { - if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line] && MultipleStyles(line)) - return reinterpret_cast(annotations[line] + sizeof(AnnotationHeader) + Length(line)); - else - return 0; -} - -static char *AllocateAnnotation(int length, int style) { - size_t len = sizeof(AnnotationHeader) + length + ((style == IndividualStyles) ? length : 0); - char *ret = new char[len]; - memset(ret, 0, len); - return ret; -} - -void LineAnnotation::SetText(int line, const char *text) { - if (text && (line >= 0)) { - annotations.EnsureLength(line+1); - int style = Style(line); - if (annotations[line]) { - delete []annotations[line]; - } - annotations[line] = AllocateAnnotation(static_cast(strlen(text)), style); - AnnotationHeader *pah = reinterpret_cast(annotations[line]); - pah->style = static_cast(style); - pah->length = static_cast(strlen(text)); - pah->lines = static_cast(NumberLines(text)); - memcpy(annotations[line]+sizeof(AnnotationHeader), text, pah->length); - } else { - if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) { - delete []annotations[line]; - annotations[line] = 0; - } - } -} - -void LineAnnotation::ClearAll() { - for (int line = 0; line < annotations.Length(); line++) { - delete []annotations[line]; - annotations[line] = 0; - } - annotations.DeleteAll(); -} - -void LineAnnotation::SetStyle(int line, int style) { - annotations.EnsureLength(line+1); - if (!annotations[line]) { - annotations[line] = AllocateAnnotation(0, style); - } - reinterpret_cast(annotations[line])->style = static_cast(style); -} - -void LineAnnotation::SetStyles(int line, const unsigned char *styles) { - if (line >= 0) { - annotations.EnsureLength(line+1); - if (!annotations[line]) { - annotations[line] = AllocateAnnotation(0, IndividualStyles); - } else { - AnnotationHeader *pahSource = reinterpret_cast(annotations[line]); - if (pahSource->style != IndividualStyles) { - char *allocation = AllocateAnnotation(pahSource->length, IndividualStyles); - AnnotationHeader *pahAlloc = reinterpret_cast(allocation); - pahAlloc->length = pahSource->length; - pahAlloc->lines = pahSource->lines; - memcpy(allocation + sizeof(AnnotationHeader), annotations[line] + sizeof(AnnotationHeader), pahSource->length); - delete []annotations[line]; - annotations[line] = allocation; - } - } - AnnotationHeader *pah = reinterpret_cast(annotations[line]); - pah->style = IndividualStyles; - memcpy(annotations[line] + sizeof(AnnotationHeader) + pah->length, styles, pah->length); - } -} - -int LineAnnotation::Length(int line) const { - if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) - return reinterpret_cast(annotations[line])->length; - else - return 0; -} - -int LineAnnotation::Lines(int line) const { - if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) - return reinterpret_cast(annotations[line])->lines; - else - return 0; -} - -LineTabstops::~LineTabstops() { - Init(); -} - -void LineTabstops::Init() { - for (int line = 0; line < tabstops.Length(); line++) { - delete tabstops[line]; - } - tabstops.DeleteAll(); -} - -void LineTabstops::InsertLine(int line) { - if (tabstops.Length()) { - tabstops.EnsureLength(line); - tabstops.Insert(line, 0); - } -} - -void LineTabstops::RemoveLine(int line) { - if (tabstops.Length() > line) { - delete tabstops[line]; - tabstops.Delete(line); - } -} - -bool LineTabstops::ClearTabstops(int line) { - if (line < tabstops.Length()) { - TabstopList *tl = tabstops[line]; - if (tl) { - tl->clear(); - return true; - } - } - return false; -} - -bool LineTabstops::AddTabstop(int line, int x) { - tabstops.EnsureLength(line + 1); - if (!tabstops[line]) { - tabstops[line] = new TabstopList(); - } - - TabstopList *tl = tabstops[line]; - if (tl) { - // tabstop positions are kept in order - insert in the right place - std::vector::iterator it = std::lower_bound(tl->begin(), tl->end(), x); - // don't insert duplicates - if (it == tl->end() || *it != x) { - tl->insert(it, x); - return true; - } - } - return false; -} - -int LineTabstops::GetNextTabstop(int line, int x) const { - if (line < tabstops.Length()) { - TabstopList *tl = tabstops[line]; - if (tl) { - for (size_t i = 0; i < tl->size(); i++) { - if ((*tl)[i] > x) { - return (*tl)[i]; - } - } - } - } - return 0; -} diff --git a/libs/qscintilla/src/PerLine.h b/libs/qscintilla/src/PerLine.h deleted file mode 100644 index 4bf1c88fd..000000000 --- a/libs/qscintilla/src/PerLine.h +++ /dev/null @@ -1,136 +0,0 @@ -// Scintilla source code edit control -/** @file PerLine.h - ** Manages data associated with each line of the document - **/ -// Copyright 1998-2009 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef PERLINE_H -#define PERLINE_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -/** - * This holds the marker identifier and the marker type to display. - * MarkerHandleNumbers are members of lists. - */ -struct MarkerHandleNumber { - int handle; - int number; - MarkerHandleNumber *next; -}; - -/** - * A marker handle set contains any number of MarkerHandleNumbers. - */ -class MarkerHandleSet { - MarkerHandleNumber *root; - -public: - MarkerHandleSet(); - ~MarkerHandleSet(); - int Length() const; - int MarkValue() const; ///< Bit set of marker numbers. - bool Contains(int handle) const; - bool InsertHandle(int handle, int markerNum); - void RemoveHandle(int handle); - bool RemoveNumber(int markerNum, bool all); - void CombineWith(MarkerHandleSet *other); -}; - -class LineMarkers : public PerLine { - SplitVector markers; - /// Handles are allocated sequentially and should never have to be reused as 32 bit ints are very big. - int handleCurrent; -public: - LineMarkers() : handleCurrent(0) { - } - virtual ~LineMarkers(); - virtual void Init(); - virtual void InsertLine(int line); - virtual void RemoveLine(int line); - - int MarkValue(int line); - int MarkerNext(int lineStart, int mask) const; - int AddMark(int line, int marker, int lines); - void MergeMarkers(int pos); - bool DeleteMark(int line, int markerNum, bool all); - void DeleteMarkFromHandle(int markerHandle); - int LineFromHandle(int markerHandle); -}; - -class LineLevels : public PerLine { - SplitVector levels; -public: - virtual ~LineLevels(); - virtual void Init(); - virtual void InsertLine(int line); - virtual void RemoveLine(int line); - - void ExpandLevels(int sizeNew=-1); - void ClearLevels(); - int SetLevel(int line, int level, int lines); - int GetLevel(int line) const; -}; - -class LineState : public PerLine { - SplitVector lineStates; -public: - LineState() { - } - virtual ~LineState(); - virtual void Init(); - virtual void InsertLine(int line); - virtual void RemoveLine(int line); - - int SetLineState(int line, int state); - int GetLineState(int line); - int GetMaxLineState() const; -}; - -class LineAnnotation : public PerLine { - SplitVector annotations; -public: - LineAnnotation() { - } - virtual ~LineAnnotation(); - virtual void Init(); - virtual void InsertLine(int line); - virtual void RemoveLine(int line); - - bool MultipleStyles(int line) const; - int Style(int line) const; - const char *Text(int line) const; - const unsigned char *Styles(int line) const; - void SetText(int line, const char *text); - void ClearAll(); - void SetStyle(int line, int style); - void SetStyles(int line, const unsigned char *styles); - int Length(int line) const; - int Lines(int line) const; -}; - -typedef std::vector TabstopList; - -class LineTabstops : public PerLine { - SplitVector tabstops; -public: - LineTabstops() { - } - virtual ~LineTabstops(); - virtual void Init(); - virtual void InsertLine(int line); - virtual void RemoveLine(int line); - - bool ClearTabstops(int line); - bool AddTabstop(int line, int x); - int GetNextTabstop(int line, int x) const; -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/PositionCache.cpp b/libs/qscintilla/src/PositionCache.cpp deleted file mode 100644 index 860a780d9..000000000 --- a/libs/qscintilla/src/PositionCache.cpp +++ /dev/null @@ -1,703 +0,0 @@ -// Scintilla source code edit control -/** @file PositionCache.cxx - ** Classes for caching layout information. - **/ -// Copyright 1998-2007 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "ILexer.h" -#include "Scintilla.h" - -#include "SplitVector.h" -#include "Partitioning.h" -#include "RunStyles.h" -#include "ContractionState.h" -#include "CellBuffer.h" -#include "KeyMap.h" -#include "Indicator.h" -#include "XPM.h" -#include "LineMarker.h" -#include "Style.h" -#include "ViewStyle.h" -#include "CharClassify.h" -#include "Decoration.h" -#include "CaseFolder.h" -#include "Document.h" -#include "UniConversion.h" -#include "Selection.h" -#include "PositionCache.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -LineLayout::LineLayout(int maxLineLength_) : - lineStarts(0), - lenLineStarts(0), - lineNumber(-1), - inCache(false), - maxLineLength(-1), - numCharsInLine(0), - numCharsBeforeEOL(0), - validity(llInvalid), - xHighlightGuide(0), - highlightColumn(0), - containsCaret(false), - edgeColumn(0), - chars(0), - styles(0), - positions(0), - hotspot(0,0), - widthLine(wrapWidthInfinite), - lines(1), - wrapIndent(0) { - bracePreviousStyles[0] = 0; - bracePreviousStyles[1] = 0; - Resize(maxLineLength_); -} - -LineLayout::~LineLayout() { - Free(); -} - -void LineLayout::Resize(int maxLineLength_) { - if (maxLineLength_ > maxLineLength) { - Free(); - chars = new char[maxLineLength_ + 1]; - styles = new unsigned char[maxLineLength_ + 1]; - // Extra position allocated as sometimes the Windows - // GetTextExtentExPoint API writes an extra element. - positions = new XYPOSITION[maxLineLength_ + 1 + 1]; - maxLineLength = maxLineLength_; - } -} - -void LineLayout::Free() { - delete []chars; - chars = 0; - delete []styles; - styles = 0; - delete []positions; - positions = 0; - delete []lineStarts; - lineStarts = 0; -} - -void LineLayout::Invalidate(validLevel validity_) { - if (validity > validity_) - validity = validity_; -} - -int LineLayout::LineStart(int line) const { - if (line <= 0) { - return 0; - } else if ((line >= lines) || !lineStarts) { - return numCharsInLine; - } else { - return lineStarts[line]; - } -} - -int LineLayout::LineLastVisible(int line) const { - if (line < 0) { - return 0; - } else if ((line >= lines-1) || !lineStarts) { - return numCharsBeforeEOL; - } else { - return lineStarts[line+1]; - } -} - -Range LineLayout::SubLineRange(int subLine) const { - return Range(LineStart(subLine), LineLastVisible(subLine)); -} - -bool LineLayout::InLine(int offset, int line) const { - return ((offset >= LineStart(line)) && (offset < LineStart(line + 1))) || - ((offset == numCharsInLine) && (line == (lines-1))); -} - -void LineLayout::SetLineStart(int line, int start) { - if ((line >= lenLineStarts) && (line != 0)) { - int newMaxLines = line + 20; - int *newLineStarts = new int[newMaxLines]; - for (int i = 0; i < newMaxLines; i++) { - if (i < lenLineStarts) - newLineStarts[i] = lineStarts[i]; - else - newLineStarts[i] = 0; - } - delete []lineStarts; - lineStarts = newLineStarts; - lenLineStarts = newMaxLines; - } - lineStarts[line] = start; -} - -void LineLayout::SetBracesHighlight(Range rangeLine, const Position braces[], - char bracesMatchStyle, int xHighlight, bool ignoreStyle) { - if (!ignoreStyle && rangeLine.ContainsCharacter(braces[0])) { - int braceOffset = braces[0] - rangeLine.start; - if (braceOffset < numCharsInLine) { - bracePreviousStyles[0] = styles[braceOffset]; - styles[braceOffset] = bracesMatchStyle; - } - } - if (!ignoreStyle && rangeLine.ContainsCharacter(braces[1])) { - int braceOffset = braces[1] - rangeLine.start; - if (braceOffset < numCharsInLine) { - bracePreviousStyles[1] = styles[braceOffset]; - styles[braceOffset] = bracesMatchStyle; - } - } - if ((braces[0] >= rangeLine.start && braces[1] <= rangeLine.end) || - (braces[1] >= rangeLine.start && braces[0] <= rangeLine.end)) { - xHighlightGuide = xHighlight; - } -} - -void LineLayout::RestoreBracesHighlight(Range rangeLine, const Position braces[], bool ignoreStyle) { - if (!ignoreStyle && rangeLine.ContainsCharacter(braces[0])) { - int braceOffset = braces[0] - rangeLine.start; - if (braceOffset < numCharsInLine) { - styles[braceOffset] = bracePreviousStyles[0]; - } - } - if (!ignoreStyle && rangeLine.ContainsCharacter(braces[1])) { - int braceOffset = braces[1] - rangeLine.start; - if (braceOffset < numCharsInLine) { - styles[braceOffset] = bracePreviousStyles[1]; - } - } - xHighlightGuide = 0; -} - -int LineLayout::FindBefore(XYPOSITION x, int lower, int upper) const { - do { - int middle = (upper + lower + 1) / 2; // Round high - XYPOSITION posMiddle = positions[middle]; - if (x < posMiddle) { - upper = middle - 1; - } else { - lower = middle; - } - } while (lower < upper); - return lower; -} - - -int LineLayout::FindPositionFromX(XYPOSITION x, Range range, bool charPosition) const { - int pos = FindBefore(x, range.start, range.end); - while (pos < range.end) { - if (charPosition) { - if (x < (positions[pos + 1])) { - return pos; - } - } else { - if (x < ((positions[pos] + positions[pos + 1]) / 2)) { - return pos; - } - } - pos++; - } - return range.end; -} - -Point LineLayout::PointFromPosition(int posInLine, int lineHeight) const { - Point pt; - // In case of very long line put x at arbitrary large position - if (posInLine > maxLineLength) { - pt.x = positions[maxLineLength] - positions[LineStart(lines)]; - } - - for (int subLine = 0; subLine < lines; subLine++) { - const Range rangeSubLine = SubLineRange(subLine); - if (posInLine >= rangeSubLine.start) { - pt.y = static_cast(subLine*lineHeight); - if (posInLine <= rangeSubLine.end) { - pt.x = positions[posInLine] - positions[rangeSubLine.start]; - if (rangeSubLine.start != 0) // Wrapped lines may be indented - pt.x += wrapIndent; - } - } else { - break; - } - } - return pt; -} - -int LineLayout::EndLineStyle() const { - return styles[numCharsBeforeEOL > 0 ? numCharsBeforeEOL-1 : 0]; -} - -LineLayoutCache::LineLayoutCache() : - level(0), - allInvalidated(false), styleClock(-1), useCount(0) { - Allocate(0); -} - -LineLayoutCache::~LineLayoutCache() { - Deallocate(); -} - -void LineLayoutCache::Allocate(size_t length_) { - PLATFORM_ASSERT(cache.empty()); - allInvalidated = false; - cache.resize(length_); -} - -void LineLayoutCache::AllocateForLevel(int linesOnScreen, int linesInDoc) { - PLATFORM_ASSERT(useCount == 0); - size_t lengthForLevel = 0; - if (level == llcCaret) { - lengthForLevel = 1; - } else if (level == llcPage) { - lengthForLevel = linesOnScreen + 1; - } else if (level == llcDocument) { - lengthForLevel = linesInDoc; - } - if (lengthForLevel > cache.size()) { - Deallocate(); - Allocate(lengthForLevel); - } else { - if (lengthForLevel < cache.size()) { - for (size_t i = lengthForLevel; i < cache.size(); i++) { - delete cache[i]; - cache[i] = 0; - } - } - cache.resize(lengthForLevel); - } - PLATFORM_ASSERT(cache.size() == lengthForLevel); -} - -void LineLayoutCache::Deallocate() { - PLATFORM_ASSERT(useCount == 0); - for (size_t i = 0; i < cache.size(); i++) - delete cache[i]; - cache.clear(); -} - -void LineLayoutCache::Invalidate(LineLayout::validLevel validity_) { - if (!cache.empty() && !allInvalidated) { - for (size_t i = 0; i < cache.size(); i++) { - if (cache[i]) { - cache[i]->Invalidate(validity_); - } - } - if (validity_ == LineLayout::llInvalid) { - allInvalidated = true; - } - } -} - -void LineLayoutCache::SetLevel(int level_) { - allInvalidated = false; - if ((level_ != -1) && (level != level_)) { - level = level_; - Deallocate(); - } -} - -LineLayout *LineLayoutCache::Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_, - int linesOnScreen, int linesInDoc) { - AllocateForLevel(linesOnScreen, linesInDoc); - if (styleClock != styleClock_) { - Invalidate(LineLayout::llCheckTextAndStyle); - styleClock = styleClock_; - } - allInvalidated = false; - int pos = -1; - LineLayout *ret = 0; - if (level == llcCaret) { - pos = 0; - } else if (level == llcPage) { - if (lineNumber == lineCaret) { - pos = 0; - } else if (cache.size() > 1) { - pos = 1 + (lineNumber % (cache.size() - 1)); - } - } else if (level == llcDocument) { - pos = lineNumber; - } - if (pos >= 0) { - PLATFORM_ASSERT(useCount == 0); - if (!cache.empty() && (pos < static_cast(cache.size()))) { - if (cache[pos]) { - if ((cache[pos]->lineNumber != lineNumber) || - (cache[pos]->maxLineLength < maxChars)) { - delete cache[pos]; - cache[pos] = 0; - } - } - if (!cache[pos]) { - cache[pos] = new LineLayout(maxChars); - } - cache[pos]->lineNumber = lineNumber; - cache[pos]->inCache = true; - ret = cache[pos]; - useCount++; - } - } - - if (!ret) { - ret = new LineLayout(maxChars); - ret->lineNumber = lineNumber; - } - - return ret; -} - -void LineLayoutCache::Dispose(LineLayout *ll) { - allInvalidated = false; - if (ll) { - if (!ll->inCache) { - delete ll; - } else { - useCount--; - } - } -} - -// Simply pack the (maximum 4) character bytes into an int -static inline int KeyFromString(const char *charBytes, size_t len) { - PLATFORM_ASSERT(len <= 4); - int k=0; - for (size_t i=0; i(charBytes[i]); - } - return k; -} - -SpecialRepresentations::SpecialRepresentations() { - std::fill(startByteHasReprs, startByteHasReprs+0x100, 0); -} - -void SpecialRepresentations::SetRepresentation(const char *charBytes, const char *value) { - MapRepresentation::iterator it = mapReprs.find(KeyFromString(charBytes, UTF8MaxBytes)); - if (it == mapReprs.end()) { - // New entry so increment for first byte - startByteHasReprs[static_cast(charBytes[0])]++; - } - mapReprs[KeyFromString(charBytes, UTF8MaxBytes)] = Representation(value); -} - -void SpecialRepresentations::ClearRepresentation(const char *charBytes) { - MapRepresentation::iterator it = mapReprs.find(KeyFromString(charBytes, UTF8MaxBytes)); - if (it != mapReprs.end()) { - mapReprs.erase(it); - startByteHasReprs[static_cast(charBytes[0])]--; - } -} - -const Representation *SpecialRepresentations::RepresentationFromCharacter(const char *charBytes, size_t len) const { - PLATFORM_ASSERT(len <= 4); - if (!startByteHasReprs[static_cast(charBytes[0])]) - return 0; - MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes, len)); - if (it != mapReprs.end()) { - return &(it->second); - } - return 0; -} - -bool SpecialRepresentations::Contains(const char *charBytes, size_t len) const { - PLATFORM_ASSERT(len <= 4); - if (!startByteHasReprs[static_cast(charBytes[0])]) - return false; - MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes, len)); - return it != mapReprs.end(); -} - -void SpecialRepresentations::Clear() { - mapReprs.clear(); - std::fill(startByteHasReprs, startByteHasReprs+0x100, 0); -} - -void BreakFinder::Insert(int val) { - if (val > nextBreak) { - const std::vector::iterator it = std::lower_bound(selAndEdge.begin(), selAndEdge.end(), val); - if (it == selAndEdge.end()) { - selAndEdge.push_back(val); - } else if (*it != val) { - selAndEdge.insert(it, 1, val); - } - } -} - -BreakFinder::BreakFinder(const LineLayout *ll_, const Selection *psel, Range lineRange_, int posLineStart_, - int xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw) : - ll(ll_), - lineRange(lineRange_), - posLineStart(posLineStart_), - nextBreak(lineRange_.start), - saeCurrentPos(0), - saeNext(0), - subBreak(-1), - pdoc(pdoc_), - encodingFamily(pdoc_->CodePageFamily()), - preprs(preprs_) { - - // Search for first visible break - // First find the first visible character - if (xStart > 0.0f) - nextBreak = ll->FindBefore(static_cast(xStart), lineRange.start, lineRange.end); - // Now back to a style break - while ((nextBreak > lineRange.start) && (ll->styles[nextBreak] == ll->styles[nextBreak - 1])) { - nextBreak--; - } - - if (breakForSelection) { - SelectionPosition posStart(posLineStart); - SelectionPosition posEnd(posLineStart + lineRange.end); - SelectionSegment segmentLine(posStart, posEnd); - for (size_t r=0; rCount(); r++) { - SelectionSegment portion = psel->Range(r).Intersect(segmentLine); - if (!(portion.start == portion.end)) { - if (portion.start.IsValid()) - Insert(portion.start.Position() - posLineStart); - if (portion.end.IsValid()) - Insert(portion.end.Position() - posLineStart); - } - } - } - if (pvsDraw && pvsDraw->indicatorsSetFore > 0) { - for (Decoration *deco = pdoc->decorations.root; deco; deco = deco->next) { - if (pvsDraw->indicators[deco->indicator].OverridesTextFore()) { - int startPos = deco->rs.EndRun(posLineStart); - while (startPos < (posLineStart + lineRange.end)) { - Insert(startPos - posLineStart); - startPos = deco->rs.EndRun(startPos); - } - } - } - } - Insert(ll->edgeColumn); - Insert(lineRange.end); - saeNext = (!selAndEdge.empty()) ? selAndEdge[0] : -1; -} - -BreakFinder::~BreakFinder() { -} - -TextSegment BreakFinder::Next() { - if (subBreak == -1) { - int prev = nextBreak; - while (nextBreak < lineRange.end) { - int charWidth = 1; - if (encodingFamily == efUnicode) - charWidth = UTF8DrawBytes(reinterpret_cast(ll->chars) + nextBreak, lineRange.end - nextBreak); - else if (encodingFamily == efDBCS) - charWidth = pdoc->IsDBCSLeadByte(ll->chars[nextBreak]) ? 2 : 1; - const Representation *repr = preprs->RepresentationFromCharacter(ll->chars + nextBreak, charWidth); - if (((nextBreak > 0) && (ll->styles[nextBreak] != ll->styles[nextBreak - 1])) || - repr || - (nextBreak == saeNext)) { - while ((nextBreak >= saeNext) && (saeNext < lineRange.end)) { - saeCurrentPos++; - saeNext = (saeCurrentPos < selAndEdge.size()) ? selAndEdge[saeCurrentPos] : lineRange.end; - } - if ((nextBreak > prev) || repr) { - // Have a segment to report - if (nextBreak == prev) { - nextBreak += charWidth; - } else { - repr = 0; // Optimize -> should remember repr - } - if ((nextBreak - prev) < lengthStartSubdivision) { - return TextSegment(prev, nextBreak - prev, repr); - } else { - break; - } - } - } - nextBreak += charWidth; - } - if ((nextBreak - prev) < lengthStartSubdivision) { - return TextSegment(prev, nextBreak - prev); - } - subBreak = prev; - } - // Splitting up a long run from prev to nextBreak in lots of approximately lengthEachSubdivision. - // For very long runs add extra breaks after spaces or if no spaces before low punctuation. - int startSegment = subBreak; - if ((nextBreak - subBreak) <= lengthEachSubdivision) { - subBreak = -1; - return TextSegment(startSegment, nextBreak - startSegment); - } else { - subBreak += pdoc->SafeSegment(ll->chars + subBreak, nextBreak-subBreak, lengthEachSubdivision); - if (subBreak >= nextBreak) { - subBreak = -1; - return TextSegment(startSegment, nextBreak - startSegment); - } else { - return TextSegment(startSegment, subBreak - startSegment); - } - } -} - -bool BreakFinder::More() const { - return (subBreak >= 0) || (nextBreak < lineRange.end); -} - -PositionCacheEntry::PositionCacheEntry() : - styleNumber(0), len(0), clock(0), positions(0) { -} - -void PositionCacheEntry::Set(unsigned int styleNumber_, const char *s_, - unsigned int len_, XYPOSITION *positions_, unsigned int clock_) { - Clear(); - styleNumber = styleNumber_; - len = len_; - clock = clock_; - if (s_ && positions_) { - positions = new XYPOSITION[len + (len / 4) + 1]; - for (unsigned int i=0; i(reinterpret_cast(positions + len)), s_, len); - } -} - -PositionCacheEntry::~PositionCacheEntry() { - Clear(); -} - -void PositionCacheEntry::Clear() { - delete []positions; - positions = 0; - styleNumber = 0; - len = 0; - clock = 0; -} - -bool PositionCacheEntry::Retrieve(unsigned int styleNumber_, const char *s_, - unsigned int len_, XYPOSITION *positions_) const { - if ((styleNumber == styleNumber_) && (len == len_) && - (memcmp(reinterpret_cast(reinterpret_cast(positions + len)), s_, len)== 0)) { - for (unsigned int i=0; i other.clock; -} - -void PositionCacheEntry::ResetClock() { - if (clock > 0) { - clock = 1; - } -} - -PositionCache::PositionCache() { - clock = 1; - pces.resize(0x400); - allClear = true; -} - -PositionCache::~PositionCache() { - Clear(); -} - -void PositionCache::Clear() { - if (!allClear) { - for (size_t i=0; i BreakFinder::lengthStartSubdivision) { - // Break up into segments - unsigned int startSegment = 0; - XYPOSITION xStartSegment = 0; - while (startSegment < len) { - unsigned int lenSegment = pdoc->SafeSegment(s + startSegment, len - startSegment, BreakFinder::lengthEachSubdivision); - FontAlias fontStyle = vstyle.styles[styleNumber].font; - surface->MeasureWidths(fontStyle, s + startSegment, lenSegment, positions + startSegment); - for (unsigned int inSeg = 0; inSeg < lenSegment; inSeg++) { - positions[startSegment + inSeg] += xStartSegment; - } - xStartSegment = positions[startSegment + lenSegment - 1]; - startSegment += lenSegment; - } - } else { - FontAlias fontStyle = vstyle.styles[styleNumber].font; - surface->MeasureWidths(fontStyle, s, len, positions); - } - if (probe < pces.size()) { - // Store into cache - clock++; - if (clock > 60000) { - // Since there are only 16 bits for the clock, wrap it round and - // reset all cache entries so none get stuck with a high clock. - for (size_t i=0; i -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef POSITIONCACHE_H -#define POSITIONCACHE_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -static inline bool IsEOLChar(char ch) { - return (ch == '\r') || (ch == '\n'); -} - -/** - */ -class LineLayout { -private: - friend class LineLayoutCache; - int *lineStarts; - int lenLineStarts; - /// Drawing is only performed for @a maxLineLength characters on each line. - int lineNumber; - bool inCache; -public: - enum { wrapWidthInfinite = 0x7ffffff }; - int maxLineLength; - int numCharsInLine; - int numCharsBeforeEOL; - enum validLevel { llInvalid, llCheckTextAndStyle, llPositions, llLines } validity; - int xHighlightGuide; - bool highlightColumn; - bool containsCaret; - int edgeColumn; - char *chars; - unsigned char *styles; - XYPOSITION *positions; - char bracePreviousStyles[2]; - - // Hotspot support - Range hotspot; - - // Wrapped line support - int widthLine; - int lines; - XYPOSITION wrapIndent; // In pixels - - explicit LineLayout(int maxLineLength_); - virtual ~LineLayout(); - void Resize(int maxLineLength_); - void Free(); - void Invalidate(validLevel validity_); - int LineStart(int line) const; - int LineLastVisible(int line) const; - Range SubLineRange(int line) const; - bool InLine(int offset, int line) const; - void SetLineStart(int line, int start); - void SetBracesHighlight(Range rangeLine, const Position braces[], - char bracesMatchStyle, int xHighlight, bool ignoreStyle); - void RestoreBracesHighlight(Range rangeLine, const Position braces[], bool ignoreStyle); - int FindBefore(XYPOSITION x, int lower, int upper) const; - int FindPositionFromX(XYPOSITION x, Range range, bool charPosition) const; - Point PointFromPosition(int posInLine, int lineHeight) const; - int EndLineStyle() const; -}; - -/** - */ -class LineLayoutCache { - int level; - std::vectorcache; - bool allInvalidated; - int styleClock; - int useCount; - void Allocate(size_t length_); - void AllocateForLevel(int linesOnScreen, int linesInDoc); -public: - LineLayoutCache(); - virtual ~LineLayoutCache(); - void Deallocate(); - enum { - llcNone=SC_CACHE_NONE, - llcCaret=SC_CACHE_CARET, - llcPage=SC_CACHE_PAGE, - llcDocument=SC_CACHE_DOCUMENT - }; - void Invalidate(LineLayout::validLevel validity_); - void SetLevel(int level_); - int GetLevel() const { return level; } - LineLayout *Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_, - int linesOnScreen, int linesInDoc); - void Dispose(LineLayout *ll); -}; - -class PositionCacheEntry { - unsigned int styleNumber:8; - unsigned int len:8; - unsigned int clock:16; - XYPOSITION *positions; -public: - PositionCacheEntry(); - ~PositionCacheEntry(); - void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_, unsigned int clock_); - void Clear(); - bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_) const; - static unsigned int Hash(unsigned int styleNumber_, const char *s, unsigned int len); - bool NewerThan(const PositionCacheEntry &other) const; - void ResetClock(); -}; - -class Representation { -public: - std::string stringRep; - explicit Representation(const char *value="") : stringRep(value) { - } -}; - -typedef std::map MapRepresentation; - -class SpecialRepresentations { - MapRepresentation mapReprs; - short startByteHasReprs[0x100]; -public: - SpecialRepresentations(); - void SetRepresentation(const char *charBytes, const char *value); - void ClearRepresentation(const char *charBytes); - const Representation *RepresentationFromCharacter(const char *charBytes, size_t len) const; - bool Contains(const char *charBytes, size_t len) const; - void Clear(); -}; - -struct TextSegment { - int start; - int length; - const Representation *representation; - TextSegment(int start_=0, int length_=0, const Representation *representation_=0) : - start(start_), length(length_), representation(representation_) { - } - int end() const { - return start + length; - } -}; - -// Class to break a line of text into shorter runs at sensible places. -class BreakFinder { - const LineLayout *ll; - Range lineRange; - int posLineStart; - int nextBreak; - std::vector selAndEdge; - unsigned int saeCurrentPos; - int saeNext; - int subBreak; - const Document *pdoc; - EncodingFamily encodingFamily; - const SpecialRepresentations *preprs; - void Insert(int val); - // Private so BreakFinder objects can not be copied - BreakFinder(const BreakFinder &); -public: - // If a whole run is longer than lengthStartSubdivision then subdivide - // into smaller runs at spaces or punctuation. - enum { lengthStartSubdivision = 300 }; - // Try to make each subdivided run lengthEachSubdivision or shorter. - enum { lengthEachSubdivision = 100 }; - BreakFinder(const LineLayout *ll_, const Selection *psel, Range rangeLine_, int posLineStart_, - int xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw); - ~BreakFinder(); - TextSegment Next(); - bool More() const; -}; - -class PositionCache { - std::vector pces; - unsigned int clock; - bool allClear; - // Private so PositionCache objects can not be copied - PositionCache(const PositionCache &); -public: - PositionCache(); - ~PositionCache(); - void Clear(); - void SetSize(size_t size_); - size_t GetSize() const { return pces.size(); } - void MeasureWidths(Surface *surface, const ViewStyle &vstyle, unsigned int styleNumber, - const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc); -}; - -inline bool IsSpaceOrTab(int ch) { - return ch == ' ' || ch == '\t'; -} - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/RESearch.h b/libs/qscintilla/src/RESearch.h deleted file mode 100644 index 3a7f0e4d6..000000000 --- a/libs/qscintilla/src/RESearch.h +++ /dev/null @@ -1,73 +0,0 @@ -// Scintilla source code edit control -/** @file RESearch.h - ** Interface to the regular expression search library. - **/ -// Written by Neil Hodgson -// Based on the work of Ozan S. Yigit. -// This file is in the public domain. - -#ifndef RESEARCH_H -#define RESEARCH_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -/* - * The following defines are not meant to be changeable. - * They are for readability only. - */ -#define MAXCHR 256 -#define CHRBIT 8 -#define BITBLK MAXCHR/CHRBIT - -class CharacterIndexer { -public: - virtual char CharAt(int index)=0; - virtual ~CharacterIndexer() { - } -}; - -class RESearch { - -public: - explicit RESearch(CharClassify *charClassTable); - ~RESearch(); - void Clear(); - void GrabMatches(CharacterIndexer &ci); - const char *Compile(const char *pattern, int length, bool caseSensitive, bool posix); - int Execute(CharacterIndexer &ci, int lp, int endp); - - enum { MAXTAG=10 }; - enum { MAXNFA=2048 }; - enum { NOTFOUND=-1 }; - - int bopat[MAXTAG]; - int eopat[MAXTAG]; - std::string pat[MAXTAG]; - -private: - void ChSet(unsigned char c); - void ChSetWithCase(unsigned char c, bool caseSensitive); - int GetBackslashExpression(const char *pattern, int &incr); - - int PMatch(CharacterIndexer &ci, int lp, int endp, char *ap); - - int bol; - int tagstk[MAXTAG]; /* subpat tag stack */ - char nfa[MAXNFA]; /* automaton */ - int sta; - unsigned char bittab[BITBLK]; /* bit table for CCL pre-set bits */ - int failure; - CharClassify *charClass; - bool iswordc(unsigned char x) const { - return charClass->IsWord(x); - } -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif - diff --git a/libs/qscintilla/src/RunStyles.cpp b/libs/qscintilla/src/RunStyles.cpp deleted file mode 100644 index ad8d977d6..000000000 --- a/libs/qscintilla/src/RunStyles.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/** @file RunStyles.cxx - ** Data structure used to store sparse styles. - **/ -// Copyright 1998-2007 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include - -#include -#include - -#include "Platform.h" - -#include "Scintilla.h" -#include "SplitVector.h" -#include "Partitioning.h" -#include "RunStyles.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -// Find the first run at a position -int RunStyles::RunFromPosition(int position) const { - int run = starts->PartitionFromPosition(position); - // Go to first element with this position - while ((run > 0) && (position == starts->PositionFromPartition(run-1))) { - run--; - } - return run; -} - -// If there is no run boundary at position, insert one continuing style. -int RunStyles::SplitRun(int position) { - int run = RunFromPosition(position); - int posRun = starts->PositionFromPartition(run); - if (posRun < position) { - int runStyle = ValueAt(position); - run++; - starts->InsertPartition(run, position); - styles->InsertValue(run, 1, runStyle); - } - return run; -} - -void RunStyles::RemoveRun(int run) { - starts->RemovePartition(run); - styles->DeleteRange(run, 1); -} - -void RunStyles::RemoveRunIfEmpty(int run) { - if ((run < starts->Partitions()) && (starts->Partitions() > 1)) { - if (starts->PositionFromPartition(run) == starts->PositionFromPartition(run+1)) { - RemoveRun(run); - } - } -} - -void RunStyles::RemoveRunIfSameAsPrevious(int run) { - if ((run > 0) && (run < starts->Partitions())) { - if (styles->ValueAt(run-1) == styles->ValueAt(run)) { - RemoveRun(run); - } - } -} - -RunStyles::RunStyles() { - starts = new Partitioning(8); - styles = new SplitVector(); - styles->InsertValue(0, 2, 0); -} - -RunStyles::~RunStyles() { - delete starts; - starts = NULL; - delete styles; - styles = NULL; -} - -int RunStyles::Length() const { - return starts->PositionFromPartition(starts->Partitions()); -} - -int RunStyles::ValueAt(int position) const { - return styles->ValueAt(starts->PartitionFromPosition(position)); -} - -int RunStyles::FindNextChange(int position, int end) const { - int run = starts->PartitionFromPosition(position); - if (run < starts->Partitions()) { - int runChange = starts->PositionFromPartition(run); - if (runChange > position) - return runChange; - int nextChange = starts->PositionFromPartition(run + 1); - if (nextChange > position) { - return nextChange; - } else if (position < end) { - return end; - } else { - return end + 1; - } - } else { - return end + 1; - } -} - -int RunStyles::StartRun(int position) const { - return starts->PositionFromPartition(starts->PartitionFromPosition(position)); -} - -int RunStyles::EndRun(int position) const { - return starts->PositionFromPartition(starts->PartitionFromPosition(position) + 1); -} - -bool RunStyles::FillRange(int &position, int value, int &fillLength) { - if (fillLength <= 0) { - return false; - } - int end = position + fillLength; - if (end > Length()) { - return false; - } - int runEnd = RunFromPosition(end); - if (styles->ValueAt(runEnd) == value) { - // End already has value so trim range. - end = starts->PositionFromPartition(runEnd); - if (position >= end) { - // Whole range is already same as value so no action - return false; - } - fillLength = end - position; - } else { - runEnd = SplitRun(end); - } - int runStart = RunFromPosition(position); - if (styles->ValueAt(runStart) == value) { - // Start is in expected value so trim range. - runStart++; - position = starts->PositionFromPartition(runStart); - fillLength = end - position; - } else { - if (starts->PositionFromPartition(runStart) < position) { - runStart = SplitRun(position); - runEnd++; - } - } - if (runStart < runEnd) { - styles->SetValueAt(runStart, value); - // Remove each old run over the range - for (int run=runStart+1; runPositionFromPartition(runStart) == position) { - int runStyle = ValueAt(position); - // Inserting at start of run so make previous longer - if (runStart == 0) { - // Inserting at start of document so ensure 0 - if (runStyle) { - styles->SetValueAt(0, 0); - starts->InsertPartition(1, 0); - styles->InsertValue(1, 1, runStyle); - starts->InsertText(0, insertLength); - } else { - starts->InsertText(runStart, insertLength); - } - } else { - if (runStyle) { - starts->InsertText(runStart-1, insertLength); - } else { - // Insert at end of run so do not extend style - starts->InsertText(runStart, insertLength); - } - } - } else { - starts->InsertText(runStart, insertLength); - } -} - -void RunStyles::DeleteAll() { - delete starts; - starts = NULL; - delete styles; - styles = NULL; - starts = new Partitioning(8); - styles = new SplitVector(); - styles->InsertValue(0, 2, 0); -} - -void RunStyles::DeleteRange(int position, int deleteLength) { - int end = position + deleteLength; - int runStart = RunFromPosition(position); - int runEnd = RunFromPosition(end); - if (runStart == runEnd) { - // Deleting from inside one run - starts->InsertText(runStart, -deleteLength); - RemoveRunIfEmpty(runStart); - } else { - runStart = SplitRun(position); - runEnd = SplitRun(end); - starts->InsertText(runStart, -deleteLength); - // Remove each old run over the range - for (int run=runStart; runPartitions(); -} - -bool RunStyles::AllSame() const { - for (int run = 1; run < starts->Partitions(); run++) { - if (styles->ValueAt(run) != styles->ValueAt(run - 1)) - return false; - } - return true; -} - -bool RunStyles::AllSameAs(int value) const { - return AllSame() && (styles->ValueAt(0) == value); -} - -int RunStyles::Find(int value, int start) const { - if (start < Length()) { - int run = start ? RunFromPosition(start) : 0; - if (styles->ValueAt(run) == value) - return start; - run++; - while (run < starts->Partitions()) { - if (styles->ValueAt(run) == value) - return starts->PositionFromPartition(run); - run++; - } - } - return -1; -} - -void RunStyles::Check() const { - if (Length() < 0) { - throw std::runtime_error("RunStyles: Length can not be negative."); - } - if (starts->Partitions() < 1) { - throw std::runtime_error("RunStyles: Must always have 1 or more partitions."); - } - if (starts->Partitions() != styles->Length()-1) { - throw std::runtime_error("RunStyles: Partitions and styles different lengths."); - } - int start=0; - while (start < Length()) { - int end = EndRun(start); - if (start >= end) { - throw std::runtime_error("RunStyles: Partition is 0 length."); - } - start = end; - } - if (styles->ValueAt(styles->Length()-1) != 0) { - throw std::runtime_error("RunStyles: Unused style at end changed."); - } - for (int j=1; jLength()-1; j++) { - if (styles->ValueAt(j) == styles->ValueAt(j-1)) { - throw std::runtime_error("RunStyles: Style of a partition same as previous."); - } - } -} diff --git a/libs/qscintilla/src/RunStyles.h b/libs/qscintilla/src/RunStyles.h deleted file mode 100644 index b096ad800..000000000 --- a/libs/qscintilla/src/RunStyles.h +++ /dev/null @@ -1,54 +0,0 @@ -/** @file RunStyles.h - ** Data structure used to store sparse styles. - **/ -// Copyright 1998-2007 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -/// Styling buffer using one element for each run rather than using -/// a filled buffer. - -#ifndef RUNSTYLES_H -#define RUNSTYLES_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -class RunStyles { -private: - Partitioning *starts; - SplitVector *styles; - int RunFromPosition(int position) const; - int SplitRun(int position); - void RemoveRun(int run); - void RemoveRunIfEmpty(int run); - void RemoveRunIfSameAsPrevious(int run); - // Private so RunStyles objects can not be copied - RunStyles(const RunStyles &); -public: - RunStyles(); - ~RunStyles(); - int Length() const; - int ValueAt(int position) const; - int FindNextChange(int position, int end) const; - int StartRun(int position) const; - int EndRun(int position) const; - // Returns true if some values may have changed - bool FillRange(int &position, int value, int &fillLength); - void SetValueAt(int position, int value); - void InsertSpace(int position, int insertLength); - void DeleteAll(); - void DeleteRange(int position, int deleteLength); - int Runs() const; - bool AllSame() const; - bool AllSameAs(int value) const; - int Find(int value, int start) const; - - void Check() const; -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/ScintillaBase.cpp b/libs/qscintilla/src/ScintillaBase.cpp deleted file mode 100644 index b52fb9a04..000000000 --- a/libs/qscintilla/src/ScintillaBase.cpp +++ /dev/null @@ -1,1070 +0,0 @@ -// Scintilla source code edit control -/** @file ScintillaBase.cxx - ** An enhanced subclass of Editor with calltips, autocomplete and context menu. - **/ -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "Platform.h" - -#include "ILexer.h" -#include "Scintilla.h" - -#ifdef SCI_LEXER -#include "SciLexer.h" -#endif - -#include "PropSetSimple.h" - -#ifdef SCI_LEXER -#include "LexerModule.h" -#include "Catalogue.h" -#endif - -#include "SplitVector.h" -#include "Partitioning.h" -#include "RunStyles.h" -#include "ContractionState.h" -#include "CellBuffer.h" -#include "CallTip.h" -#include "KeyMap.h" -#include "Indicator.h" -#include "XPM.h" -#include "LineMarker.h" -#include "Style.h" -#include "ViewStyle.h" -#include "CharClassify.h" -#include "Decoration.h" -#include "CaseFolder.h" -#include "Document.h" -#include "Selection.h" -#include "PositionCache.h" -#include "EditModel.h" -#include "MarginView.h" -#include "EditView.h" -#include "Editor.h" -#include "AutoComplete.h" -#include "ScintillaBase.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -ScintillaBase::ScintillaBase() { - displayPopupMenu = true; - listType = 0; - maxListWidth = 0; - multiAutoCMode = SC_MULTIAUTOC_ONCE; -} - -ScintillaBase::~ScintillaBase() { -} - -void ScintillaBase::Finalise() { - Editor::Finalise(); - popup.Destroy(); -} - -void ScintillaBase::AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS) { - bool isFillUp = ac.Active() && ac.IsFillUpChar(*s); - if (!isFillUp) { - Editor::AddCharUTF(s, len, treatAsDBCS); - } - if (ac.Active()) { - AutoCompleteCharacterAdded(s[0]); - // For fill ups add the character after the autocompletion has - // triggered so containers see the key so can display a calltip. - if (isFillUp) { - Editor::AddCharUTF(s, len, treatAsDBCS); - } - } -} - -void ScintillaBase::Command(int cmdId) { - - switch (cmdId) { - - case idAutoComplete: // Nothing to do - - break; - - case idCallTip: // Nothing to do - - break; - - case idcmdUndo: - WndProc(SCI_UNDO, 0, 0); - break; - - case idcmdRedo: - WndProc(SCI_REDO, 0, 0); - break; - - case idcmdCut: - WndProc(SCI_CUT, 0, 0); - break; - - case idcmdCopy: - WndProc(SCI_COPY, 0, 0); - break; - - case idcmdPaste: - WndProc(SCI_PASTE, 0, 0); - break; - - case idcmdDelete: - WndProc(SCI_CLEAR, 0, 0); - break; - - case idcmdSelectAll: - WndProc(SCI_SELECTALL, 0, 0); - break; - } -} - -int ScintillaBase::KeyCommand(unsigned int iMessage) { - // Most key commands cancel autocompletion mode - if (ac.Active()) { - switch (iMessage) { - // Except for these - case SCI_LINEDOWN: - AutoCompleteMove(1); - return 0; - case SCI_LINEUP: - AutoCompleteMove(-1); - return 0; - case SCI_PAGEDOWN: - AutoCompleteMove(ac.lb->GetVisibleRows()); - return 0; - case SCI_PAGEUP: - AutoCompleteMove(-ac.lb->GetVisibleRows()); - return 0; - case SCI_VCHOME: - AutoCompleteMove(-5000); - return 0; - case SCI_LINEEND: - AutoCompleteMove(5000); - return 0; - case SCI_DELETEBACK: - DelCharBack(true); - AutoCompleteCharacterDeleted(); - EnsureCaretVisible(); - return 0; - case SCI_DELETEBACKNOTLINE: - DelCharBack(false); - AutoCompleteCharacterDeleted(); - EnsureCaretVisible(); - return 0; - case SCI_TAB: - AutoCompleteCompleted(); - return 0; - case SCI_NEWLINE: - AutoCompleteCompleted(); - return 0; - - default: - AutoCompleteCancel(); - } - } - - if (ct.inCallTipMode) { - if ( - (iMessage != SCI_CHARLEFT) && - (iMessage != SCI_CHARLEFTEXTEND) && - (iMessage != SCI_CHARRIGHT) && - (iMessage != SCI_CHARRIGHTEXTEND) && - (iMessage != SCI_EDITTOGGLEOVERTYPE) && - (iMessage != SCI_DELETEBACK) && - (iMessage != SCI_DELETEBACKNOTLINE) - ) { - ct.CallTipCancel(); - } - if ((iMessage == SCI_DELETEBACK) || (iMessage == SCI_DELETEBACKNOTLINE)) { - if (sel.MainCaret() <= ct.posStartCallTip) { - ct.CallTipCancel(); - } - } - } - return Editor::KeyCommand(iMessage); -} - -void ScintillaBase::AutoCompleteDoubleClick(void *p) { - ScintillaBase *sci = reinterpret_cast(p); - sci->AutoCompleteCompleted(); -} - -void ScintillaBase::AutoCompleteInsert(Position startPos, int removeLen, const char *text, int textLen) { - UndoGroup ug(pdoc); - if (multiAutoCMode == SC_MULTIAUTOC_ONCE) { - pdoc->DeleteChars(startPos, removeLen); - const int lengthInserted = pdoc->InsertString(startPos, text, textLen); - SetEmptySelection(startPos + lengthInserted); - } else { - // SC_MULTIAUTOC_EACH - for (size_t r=0; r= 0) { - positionInsert -= removeLen; - pdoc->DeleteChars(positionInsert, removeLen); - } - const int lengthInserted = pdoc->InsertString(positionInsert, text, textLen); - if (lengthInserted > 0) { - sel.Range(r).caret.SetPosition(positionInsert + lengthInserted); - sel.Range(r).anchor.SetPosition(positionInsert + lengthInserted); - } - sel.Range(r).ClearVirtualSpace(); - } - } - } -} - -void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) { - //Platform::DebugPrintf("AutoComplete %s\n", list); - ct.CallTipCancel(); - - if (ac.chooseSingle && (listType == 0)) { - if (list && !strchr(list, ac.GetSeparator())) { - const char *typeSep = strchr(list, ac.GetTypesep()); - int lenInsert = typeSep ? - static_cast(typeSep-list) : static_cast(strlen(list)); - if (ac.ignoreCase) { - // May need to convert the case before invocation, so remove lenEntered characters - AutoCompleteInsert(sel.MainCaret() - lenEntered, lenEntered, list, lenInsert); - } else { - AutoCompleteInsert(sel.MainCaret(), 0, list + lenEntered, lenInsert - lenEntered); - } - ac.Cancel(); - return; - } - } - ac.Start(wMain, idAutoComplete, sel.MainCaret(), PointMainCaret(), - lenEntered, vs.lineHeight, IsUnicodeMode(), technology); - - PRectangle rcClient = GetClientRectangle(); - Point pt = LocationFromPosition(sel.MainCaret() - lenEntered); - PRectangle rcPopupBounds = wMain.GetMonitorRect(pt); - if (rcPopupBounds.Height() == 0) - rcPopupBounds = rcClient; - - int heightLB = ac.heightLBDefault; - int widthLB = ac.widthLBDefault; - if (pt.x >= rcClient.right - widthLB) { - HorizontalScrollTo(static_cast(xOffset + pt.x - rcClient.right + widthLB)); - Redraw(); - pt = PointMainCaret(); - } - if (wMargin.GetID()) { - Point ptOrigin = GetVisibleOriginInMain(); - pt.x += ptOrigin.x; - pt.y += ptOrigin.y; - } - PRectangle rcac; - rcac.left = pt.x - ac.lb->CaretFromEdge(); - if (pt.y >= rcPopupBounds.bottom - heightLB && // Wont fit below. - pt.y >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2) { // and there is more room above. - rcac.top = pt.y - heightLB; - if (rcac.top < rcPopupBounds.top) { - heightLB -= static_cast(rcPopupBounds.top - rcac.top); - rcac.top = rcPopupBounds.top; - } - } else { - rcac.top = pt.y + vs.lineHeight; - } - rcac.right = rcac.left + widthLB; - rcac.bottom = static_cast(Platform::Minimum(static_cast(rcac.top) + heightLB, static_cast(rcPopupBounds.bottom))); - ac.lb->SetPositionRelative(rcac, wMain); - ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font); - unsigned int aveCharWidth = static_cast(vs.styles[STYLE_DEFAULT].aveCharWidth); - ac.lb->SetAverageCharWidth(aveCharWidth); - ac.lb->SetDoubleClickAction(AutoCompleteDoubleClick, this); - - ac.SetList(list ? list : ""); - - // Fiddle the position of the list so it is right next to the target and wide enough for all its strings - PRectangle rcList = ac.lb->GetDesiredRect(); - int heightAlloced = static_cast(rcList.bottom - rcList.top); - widthLB = Platform::Maximum(widthLB, static_cast(rcList.right - rcList.left)); - if (maxListWidth != 0) - widthLB = Platform::Minimum(widthLB, aveCharWidth*maxListWidth); - // Make an allowance for large strings in list - rcList.left = pt.x - ac.lb->CaretFromEdge(); - rcList.right = rcList.left + widthLB; - if (((pt.y + vs.lineHeight) >= (rcPopupBounds.bottom - heightAlloced)) && // Wont fit below. - ((pt.y + vs.lineHeight / 2) >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2)) { // and there is more room above. - rcList.top = pt.y - heightAlloced; - } else { - rcList.top = pt.y + vs.lineHeight; - } - rcList.bottom = rcList.top + heightAlloced; - ac.lb->SetPositionRelative(rcList, wMain); - ac.Show(true); - if (lenEntered != 0) { - AutoCompleteMoveToCurrentWord(); - } -} - -void ScintillaBase::AutoCompleteCancel() { - if (ac.Active()) { - SCNotification scn = {}; - scn.nmhdr.code = SCN_AUTOCCANCELLED; - scn.wParam = 0; - scn.listType = 0; - NotifyParent(scn); - } - ac.Cancel(); -} - -void ScintillaBase::AutoCompleteMove(int delta) { - ac.Move(delta); -} - -void ScintillaBase::AutoCompleteMoveToCurrentWord() { - std::string wordCurrent = RangeText(ac.posStart - ac.startLen, sel.MainCaret()); - ac.Select(wordCurrent.c_str()); -} - -void ScintillaBase::AutoCompleteCharacterAdded(char ch) { - if (ac.IsFillUpChar(ch)) { - AutoCompleteCompleted(); - } else if (ac.IsStopChar(ch)) { - AutoCompleteCancel(); - } else { - AutoCompleteMoveToCurrentWord(); - } -} - -void ScintillaBase::AutoCompleteCharacterDeleted() { - if (sel.MainCaret() < ac.posStart - ac.startLen) { - AutoCompleteCancel(); - } else if (ac.cancelAtStartPos && (sel.MainCaret() <= ac.posStart)) { - AutoCompleteCancel(); - } else { - AutoCompleteMoveToCurrentWord(); - } - SCNotification scn = {}; - scn.nmhdr.code = SCN_AUTOCCHARDELETED; - scn.wParam = 0; - scn.listType = 0; - NotifyParent(scn); -} - -void ScintillaBase::AutoCompleteCompleted() { - int item = ac.GetSelection(); - if (item == -1) { - AutoCompleteCancel(); - return; - } - const std::string selected = ac.GetValue(item); - - ac.Show(false); - - SCNotification scn = {}; - scn.nmhdr.code = listType > 0 ? SCN_USERLISTSELECTION : SCN_AUTOCSELECTION; - scn.message = 0; - scn.wParam = listType; - scn.listType = listType; - Position firstPos = ac.posStart - ac.startLen; - scn.position = firstPos; - scn.lParam = firstPos; - scn.text = selected.c_str(); - NotifyParent(scn); - - if (!ac.Active()) - return; - ac.Cancel(); - - if (listType > 0) - return; - - Position endPos = sel.MainCaret(); - if (ac.dropRestOfWord) - endPos = pdoc->ExtendWordSelect(endPos, 1, true); - if (endPos < firstPos) - return; - AutoCompleteInsert(firstPos, endPos - firstPos, selected.c_str(), static_cast(selected.length())); - SetLastXChosen(); -} - -int ScintillaBase::AutoCompleteGetCurrent() const { - if (!ac.Active()) - return -1; - return ac.GetSelection(); -} - -int ScintillaBase::AutoCompleteGetCurrentText(char *buffer) const { - if (ac.Active()) { - int item = ac.GetSelection(); - if (item != -1) { - const std::string selected = ac.GetValue(item); - if (buffer != NULL) - memcpy(buffer, selected.c_str(), selected.length()+1); - return static_cast(selected.length()); - } - } - if (buffer != NULL) - *buffer = '\0'; - return 0; -} - -void ScintillaBase::CallTipShow(Point pt, const char *defn) { - ac.Cancel(); - // If container knows about STYLE_CALLTIP then use it in place of the - // STYLE_DEFAULT for the face name, size and character set. Also use it - // for the foreground and background colour. - int ctStyle = ct.UseStyleCallTip() ? STYLE_CALLTIP : STYLE_DEFAULT; - if (ct.UseStyleCallTip()) { - ct.SetForeBack(vs.styles[STYLE_CALLTIP].fore, vs.styles[STYLE_CALLTIP].back); - } - if (wMargin.GetID()) { - Point ptOrigin = GetVisibleOriginInMain(); - pt.x += ptOrigin.x; - pt.y += ptOrigin.y; - } - PRectangle rc = ct.CallTipStart(sel.MainCaret(), pt, - vs.lineHeight, - defn, - vs.styles[ctStyle].fontName, - vs.styles[ctStyle].sizeZoomed, - CodePage(), - vs.styles[ctStyle].characterSet, - vs.technology, - wMain); - // If the call-tip window would be out of the client - // space - PRectangle rcClient = GetClientRectangle(); - int offset = vs.lineHeight + static_cast(rc.Height()); - // adjust so it displays above the text. - if (rc.bottom > rcClient.bottom && rc.Height() < rcClient.Height()) { - rc.top -= offset; - rc.bottom -= offset; - } - // adjust so it displays below the text. - if (rc.top < rcClient.top && rc.Height() < rcClient.Height()) { - rc.top += offset; - rc.bottom += offset; - } - // Now display the window. - CreateCallTipWindow(rc); - ct.wCallTip.SetPositionRelative(rc, wMain); - ct.wCallTip.Show(); -} - -void ScintillaBase::CallTipClick() { - SCNotification scn = {}; - scn.nmhdr.code = SCN_CALLTIPCLICK; - scn.position = ct.clickPlace; - NotifyParent(scn); -} - -void ScintillaBase::ContextMenu(Point pt) { - if (displayPopupMenu) { - bool writable = !WndProc(SCI_GETREADONLY, 0, 0); - popup.CreatePopUp(); - AddToPopUp("Undo", idcmdUndo, writable && pdoc->CanUndo()); - AddToPopUp("Redo", idcmdRedo, writable && pdoc->CanRedo()); - AddToPopUp(""); - AddToPopUp("Cut", idcmdCut, writable && !sel.Empty()); - AddToPopUp("Copy", idcmdCopy, !sel.Empty()); - AddToPopUp("Paste", idcmdPaste, writable && WndProc(SCI_CANPASTE, 0, 0)); - AddToPopUp("Delete", idcmdDelete, writable && !sel.Empty()); - AddToPopUp(""); - AddToPopUp("Select All", idcmdSelectAll); - popup.Show(pt, wMain); - } -} - -void ScintillaBase::CancelModes() { - AutoCompleteCancel(); - ct.CallTipCancel(); - Editor::CancelModes(); -} - -void ScintillaBase::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers) { - CancelModes(); - Editor::ButtonDownWithModifiers(pt, curTime, modifiers); -} - -void ScintillaBase::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) { - ButtonDownWithModifiers(pt, curTime, ModifierFlags(shift, ctrl, alt)); -} - -#ifdef SCI_LEXER - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -class LexState : public LexInterface { - const LexerModule *lexCurrent; - void SetLexerModule(const LexerModule *lex); - PropSetSimple props; - int interfaceVersion; -public: - int lexLanguage; - - explicit LexState(Document *pdoc_); - virtual ~LexState(); - void SetLexer(uptr_t wParam); - void SetLexerLanguage(const char *languageName); - const char *DescribeWordListSets(); - void SetWordList(int n, const char *wl); - const char *GetName() const; - void *PrivateCall(int operation, void *pointer); - const char *PropertyNames(); - int PropertyType(const char *name); - const char *DescribeProperty(const char *name); - void PropSet(const char *key, const char *val); - const char *PropGet(const char *key) const; - int PropGetInt(const char *key, int defaultValue=0) const; - int PropGetExpanded(const char *key, char *result) const; - - int LineEndTypesSupported(); - int AllocateSubStyles(int styleBase, int numberStyles); - int SubStylesStart(int styleBase); - int SubStylesLength(int styleBase); - int StyleFromSubStyle(int subStyle); - int PrimaryStyleFromStyle(int style); - void FreeSubStyles(); - void SetIdentifiers(int style, const char *identifiers); - int DistanceToSecondaryStyles(); - const char *GetSubStyleBases(); -}; - -#ifdef SCI_NAMESPACE -} -#endif - -LexState::LexState(Document *pdoc_) : LexInterface(pdoc_) { - lexCurrent = 0; - performingStyle = false; - interfaceVersion = lvOriginal; - lexLanguage = SCLEX_CONTAINER; -} - -LexState::~LexState() { - if (instance) { - instance->Release(); - instance = 0; - } -} - -LexState *ScintillaBase::DocumentLexState() { - if (!pdoc->pli) { - pdoc->pli = new LexState(pdoc); - } - return static_cast(pdoc->pli); -} - -void LexState::SetLexerModule(const LexerModule *lex) { - if (lex != lexCurrent) { - if (instance) { - instance->Release(); - instance = 0; - } - interfaceVersion = lvOriginal; - lexCurrent = lex; - if (lexCurrent) { - instance = lexCurrent->Create(); - interfaceVersion = instance->Version(); - } - pdoc->LexerChanged(); - } -} - -void LexState::SetLexer(uptr_t wParam) { - lexLanguage = static_cast(wParam); - if (lexLanguage == SCLEX_CONTAINER) { - SetLexerModule(0); - } else { - const LexerModule *lex = Catalogue::Find(lexLanguage); - if (!lex) - lex = Catalogue::Find(SCLEX_NULL); - SetLexerModule(lex); - } -} - -void LexState::SetLexerLanguage(const char *languageName) { - const LexerModule *lex = Catalogue::Find(languageName); - if (!lex) - lex = Catalogue::Find(SCLEX_NULL); - if (lex) - lexLanguage = lex->GetLanguage(); - SetLexerModule(lex); -} - -const char *LexState::DescribeWordListSets() { - if (instance) { - return instance->DescribeWordListSets(); - } else { - return 0; - } -} - -void LexState::SetWordList(int n, const char *wl) { - if (instance) { - int firstModification = instance->WordListSet(n, wl); - if (firstModification >= 0) { - pdoc->ModifiedAt(firstModification); - } - } -} - -const char *LexState::GetName() const { - return lexCurrent ? lexCurrent->languageName : ""; -} - -void *LexState::PrivateCall(int operation, void *pointer) { - if (pdoc && instance) { - return instance->PrivateCall(operation, pointer); - } else { - return 0; - } -} - -const char *LexState::PropertyNames() { - if (instance) { - return instance->PropertyNames(); - } else { - return 0; - } -} - -int LexState::PropertyType(const char *name) { - if (instance) { - return instance->PropertyType(name); - } else { - return SC_TYPE_BOOLEAN; - } -} - -const char *LexState::DescribeProperty(const char *name) { - if (instance) { - return instance->DescribeProperty(name); - } else { - return 0; - } -} - -void LexState::PropSet(const char *key, const char *val) { - props.Set(key, val); - if (instance) { - int firstModification = instance->PropertySet(key, val); - if (firstModification >= 0) { - pdoc->ModifiedAt(firstModification); - } - } -} - -const char *LexState::PropGet(const char *key) const { - return props.Get(key); -} - -int LexState::PropGetInt(const char *key, int defaultValue) const { - return props.GetInt(key, defaultValue); -} - -int LexState::PropGetExpanded(const char *key, char *result) const { - return props.GetExpanded(key, result); -} - -int LexState::LineEndTypesSupported() { - if (instance && (interfaceVersion >= lvSubStyles)) { - return static_cast(instance)->LineEndTypesSupported(); - } - return 0; -} - -int LexState::AllocateSubStyles(int styleBase, int numberStyles) { - if (instance && (interfaceVersion >= lvSubStyles)) { - return static_cast(instance)->AllocateSubStyles(styleBase, numberStyles); - } - return -1; -} - -int LexState::SubStylesStart(int styleBase) { - if (instance && (interfaceVersion >= lvSubStyles)) { - return static_cast(instance)->SubStylesStart(styleBase); - } - return -1; -} - -int LexState::SubStylesLength(int styleBase) { - if (instance && (interfaceVersion >= lvSubStyles)) { - return static_cast(instance)->SubStylesLength(styleBase); - } - return 0; -} - -int LexState::StyleFromSubStyle(int subStyle) { - if (instance && (interfaceVersion >= lvSubStyles)) { - return static_cast(instance)->StyleFromSubStyle(subStyle); - } - return 0; -} - -int LexState::PrimaryStyleFromStyle(int style) { - if (instance && (interfaceVersion >= lvSubStyles)) { - return static_cast(instance)->PrimaryStyleFromStyle(style); - } - return 0; -} - -void LexState::FreeSubStyles() { - if (instance && (interfaceVersion >= lvSubStyles)) { - static_cast(instance)->FreeSubStyles(); - } -} - -void LexState::SetIdentifiers(int style, const char *identifiers) { - if (instance && (interfaceVersion >= lvSubStyles)) { - static_cast(instance)->SetIdentifiers(style, identifiers); - } -} - -int LexState::DistanceToSecondaryStyles() { - if (instance && (interfaceVersion >= lvSubStyles)) { - return static_cast(instance)->DistanceToSecondaryStyles(); - } - return 0; -} - -const char *LexState::GetSubStyleBases() { - if (instance && (interfaceVersion >= lvSubStyles)) { - return static_cast(instance)->GetSubStyleBases(); - } - return ""; -} - -#endif - -void ScintillaBase::NotifyStyleToNeeded(int endStyleNeeded) { -#ifdef SCI_LEXER - if (DocumentLexState()->lexLanguage != SCLEX_CONTAINER) { - int lineEndStyled = pdoc->LineFromPosition(pdoc->GetEndStyled()); - int endStyled = pdoc->LineStart(lineEndStyled); - DocumentLexState()->Colourise(endStyled, endStyleNeeded); - return; - } -#endif - Editor::NotifyStyleToNeeded(endStyleNeeded); -} - -void ScintillaBase::NotifyLexerChanged(Document *, void *) { -#ifdef SCI_LEXER - vs.EnsureStyle(0xff); -#endif -} - -sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { - switch (iMessage) { - case SCI_AUTOCSHOW: - listType = 0; - AutoCompleteStart(static_cast(wParam), reinterpret_cast(lParam)); - break; - - case SCI_AUTOCCANCEL: - ac.Cancel(); - break; - - case SCI_AUTOCACTIVE: - return ac.Active(); - - case SCI_AUTOCPOSSTART: - return ac.posStart; - - case SCI_AUTOCCOMPLETE: - AutoCompleteCompleted(); - break; - - case SCI_AUTOCSETSEPARATOR: - ac.SetSeparator(static_cast(wParam)); - break; - - case SCI_AUTOCGETSEPARATOR: - return ac.GetSeparator(); - - case SCI_AUTOCSTOPS: - ac.SetStopChars(reinterpret_cast(lParam)); - break; - - case SCI_AUTOCSELECT: - ac.Select(reinterpret_cast(lParam)); - break; - - case SCI_AUTOCGETCURRENT: - return AutoCompleteGetCurrent(); - - case SCI_AUTOCGETCURRENTTEXT: - return AutoCompleteGetCurrentText(reinterpret_cast(lParam)); - - case SCI_AUTOCSETCANCELATSTART: - ac.cancelAtStartPos = wParam != 0; - break; - - case SCI_AUTOCGETCANCELATSTART: - return ac.cancelAtStartPos; - - case SCI_AUTOCSETFILLUPS: - ac.SetFillUpChars(reinterpret_cast(lParam)); - break; - - case SCI_AUTOCSETCHOOSESINGLE: - ac.chooseSingle = wParam != 0; - break; - - case SCI_AUTOCGETCHOOSESINGLE: - return ac.chooseSingle; - - case SCI_AUTOCSETIGNORECASE: - ac.ignoreCase = wParam != 0; - break; - - case SCI_AUTOCGETIGNORECASE: - return ac.ignoreCase; - - case SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR: - ac.ignoreCaseBehaviour = static_cast(wParam); - break; - - case SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR: - return ac.ignoreCaseBehaviour; - - case SCI_AUTOCSETMULTI: - multiAutoCMode = static_cast(wParam); - break; - - case SCI_AUTOCGETMULTI: - return multiAutoCMode; - - case SCI_AUTOCSETORDER: - ac.autoSort = static_cast(wParam); - break; - - case SCI_AUTOCGETORDER: - return ac.autoSort; - - case SCI_USERLISTSHOW: - listType = static_cast(wParam); - AutoCompleteStart(0, reinterpret_cast(lParam)); - break; - - case SCI_AUTOCSETAUTOHIDE: - ac.autoHide = wParam != 0; - break; - - case SCI_AUTOCGETAUTOHIDE: - return ac.autoHide; - - case SCI_AUTOCSETDROPRESTOFWORD: - ac.dropRestOfWord = wParam != 0; - break; - - case SCI_AUTOCGETDROPRESTOFWORD: - return ac.dropRestOfWord; - - case SCI_AUTOCSETMAXHEIGHT: - ac.lb->SetVisibleRows(static_cast(wParam)); - break; - - case SCI_AUTOCGETMAXHEIGHT: - return ac.lb->GetVisibleRows(); - - case SCI_AUTOCSETMAXWIDTH: - maxListWidth = static_cast(wParam); - break; - - case SCI_AUTOCGETMAXWIDTH: - return maxListWidth; - - case SCI_REGISTERIMAGE: - ac.lb->RegisterImage(static_cast(wParam), reinterpret_cast(lParam)); - break; - - case SCI_REGISTERRGBAIMAGE: - ac.lb->RegisterRGBAImage(static_cast(wParam), static_cast(sizeRGBAImage.x), static_cast(sizeRGBAImage.y), - reinterpret_cast(lParam)); - break; - - case SCI_CLEARREGISTEREDIMAGES: - ac.lb->ClearRegisteredImages(); - break; - - case SCI_AUTOCSETTYPESEPARATOR: - ac.SetTypesep(static_cast(wParam)); - break; - - case SCI_AUTOCGETTYPESEPARATOR: - return ac.GetTypesep(); - - case SCI_CALLTIPSHOW: - CallTipShow(LocationFromPosition(static_cast(wParam)), - reinterpret_cast(lParam)); - break; - - case SCI_CALLTIPCANCEL: - ct.CallTipCancel(); - break; - - case SCI_CALLTIPACTIVE: - return ct.inCallTipMode; - - case SCI_CALLTIPPOSSTART: - return ct.posStartCallTip; - - case SCI_CALLTIPSETPOSSTART: - ct.posStartCallTip = static_cast(wParam); - break; - - case SCI_CALLTIPSETHLT: - ct.SetHighlight(static_cast(wParam), static_cast(lParam)); - break; - - case SCI_CALLTIPSETBACK: - ct.colourBG = ColourDesired(static_cast(wParam)); - vs.styles[STYLE_CALLTIP].back = ct.colourBG; - InvalidateStyleRedraw(); - break; - - case SCI_CALLTIPSETFORE: - ct.colourUnSel = ColourDesired(static_cast(wParam)); - vs.styles[STYLE_CALLTIP].fore = ct.colourUnSel; - InvalidateStyleRedraw(); - break; - - case SCI_CALLTIPSETFOREHLT: - ct.colourSel = ColourDesired(static_cast(wParam)); - InvalidateStyleRedraw(); - break; - - case SCI_CALLTIPUSESTYLE: - ct.SetTabSize(static_cast(wParam)); - InvalidateStyleRedraw(); - break; - - case SCI_CALLTIPSETPOSITION: - ct.SetPosition(wParam != 0); - InvalidateStyleRedraw(); - break; - - case SCI_USEPOPUP: - displayPopupMenu = wParam != 0; - break; - -#ifdef SCI_LEXER - case SCI_SETLEXER: - DocumentLexState()->SetLexer(static_cast(wParam)); - break; - - case SCI_GETLEXER: - return DocumentLexState()->lexLanguage; - - case SCI_COLOURISE: - if (DocumentLexState()->lexLanguage == SCLEX_CONTAINER) { - pdoc->ModifiedAt(static_cast(wParam)); - NotifyStyleToNeeded((lParam == -1) ? pdoc->Length() : static_cast(lParam)); - } else { - DocumentLexState()->Colourise(static_cast(wParam), static_cast(lParam)); - } - Redraw(); - break; - - case SCI_SETPROPERTY: - DocumentLexState()->PropSet(reinterpret_cast(wParam), - reinterpret_cast(lParam)); - break; - - case SCI_GETPROPERTY: - return StringResult(lParam, DocumentLexState()->PropGet(reinterpret_cast(wParam))); - - case SCI_GETPROPERTYEXPANDED: - return DocumentLexState()->PropGetExpanded(reinterpret_cast(wParam), - reinterpret_cast(lParam)); - - case SCI_GETPROPERTYINT: - return DocumentLexState()->PropGetInt(reinterpret_cast(wParam), static_cast(lParam)); - - case SCI_SETKEYWORDS: - DocumentLexState()->SetWordList(static_cast(wParam), reinterpret_cast(lParam)); - break; - - case SCI_SETLEXERLANGUAGE: - DocumentLexState()->SetLexerLanguage(reinterpret_cast(lParam)); - break; - - case SCI_GETLEXERLANGUAGE: - return StringResult(lParam, DocumentLexState()->GetName()); - - case SCI_PRIVATELEXERCALL: - return reinterpret_cast( - DocumentLexState()->PrivateCall(static_cast(wParam), reinterpret_cast(lParam))); - - case SCI_GETSTYLEBITSNEEDED: - return 8; - - case SCI_PROPERTYNAMES: - return StringResult(lParam, DocumentLexState()->PropertyNames()); - - case SCI_PROPERTYTYPE: - return DocumentLexState()->PropertyType(reinterpret_cast(wParam)); - - case SCI_DESCRIBEPROPERTY: - return StringResult(lParam, - DocumentLexState()->DescribeProperty(reinterpret_cast(wParam))); - - case SCI_DESCRIBEKEYWORDSETS: - return StringResult(lParam, DocumentLexState()->DescribeWordListSets()); - - case SCI_GETLINEENDTYPESSUPPORTED: - return DocumentLexState()->LineEndTypesSupported(); - - case SCI_ALLOCATESUBSTYLES: - return DocumentLexState()->AllocateSubStyles(static_cast(wParam), static_cast(lParam)); - - case SCI_GETSUBSTYLESSTART: - return DocumentLexState()->SubStylesStart(static_cast(wParam)); - - case SCI_GETSUBSTYLESLENGTH: - return DocumentLexState()->SubStylesLength(static_cast(wParam)); - - case SCI_GETSTYLEFROMSUBSTYLE: - return DocumentLexState()->StyleFromSubStyle(static_cast(wParam)); - - case SCI_GETPRIMARYSTYLEFROMSTYLE: - return DocumentLexState()->PrimaryStyleFromStyle(static_cast(wParam)); - - case SCI_FREESUBSTYLES: - DocumentLexState()->FreeSubStyles(); - break; - - case SCI_SETIDENTIFIERS: - DocumentLexState()->SetIdentifiers(static_cast(wParam), - reinterpret_cast(lParam)); - break; - - case SCI_DISTANCETOSECONDARYSTYLES: - return DocumentLexState()->DistanceToSecondaryStyles(); - - case SCI_GETSUBSTYLEBASES: - return StringResult(lParam, DocumentLexState()->GetSubStyleBases()); -#endif - - default: - return Editor::WndProc(iMessage, wParam, lParam); - } - return 0l; -} diff --git a/libs/qscintilla/src/ScintillaBase.h b/libs/qscintilla/src/ScintillaBase.h deleted file mode 100644 index 668abed3c..000000000 --- a/libs/qscintilla/src/ScintillaBase.h +++ /dev/null @@ -1,104 +0,0 @@ -// Scintilla source code edit control -/** @file ScintillaBase.h - ** Defines an enhanced subclass of Editor with calltips, autocomplete and context menu. - **/ -// Copyright 1998-2002 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef SCINTILLABASE_H -#define SCINTILLABASE_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -#ifdef SCI_LEXER -class LexState; -#endif - -/** - */ -class ScintillaBase : public Editor { - // Private so ScintillaBase objects can not be copied - ScintillaBase(const ScintillaBase &); - ScintillaBase &operator=(const ScintillaBase &); - -protected: - /** Enumeration of commands and child windows. */ - enum { - idCallTip=1, - idAutoComplete=2, - - idcmdUndo=10, - idcmdRedo=11, - idcmdCut=12, - idcmdCopy=13, - idcmdPaste=14, - idcmdDelete=15, - idcmdSelectAll=16 - }; - - enum { maxLenInputIME = 200 }; - - bool displayPopupMenu; - Menu popup; - AutoComplete ac; - - CallTip ct; - - int listType; ///< 0 is an autocomplete list - int maxListWidth; /// Maximum width of list, in average character widths - int multiAutoCMode; /// Mode for autocompleting when multiple selections are present - -#ifdef SCI_LEXER - LexState *DocumentLexState(); - void SetLexer(uptr_t wParam); - void SetLexerLanguage(const char *languageName); - void Colourise(int start, int end); -#endif - - ScintillaBase(); - virtual ~ScintillaBase(); - virtual void Initialise() = 0; - virtual void Finalise(); - - virtual void AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS=false); - void Command(int cmdId); - virtual void CancelModes(); - virtual int KeyCommand(unsigned int iMessage); - - void AutoCompleteInsert(Position startPos, int removeLen, const char *text, int textLen); - void AutoCompleteStart(int lenEntered, const char *list); - void AutoCompleteCancel(); - void AutoCompleteMove(int delta); - int AutoCompleteGetCurrent() const; - int AutoCompleteGetCurrentText(char *buffer) const; - void AutoCompleteCharacterAdded(char ch); - void AutoCompleteCharacterDeleted(); - void AutoCompleteCompleted(); - void AutoCompleteMoveToCurrentWord(); - static void AutoCompleteDoubleClick(void *p); - - void CallTipClick(); - void CallTipShow(Point pt, const char *defn); - virtual void CreateCallTipWindow(PRectangle rc) = 0; - - virtual void AddToPopUp(const char *label, int cmd=0, bool enabled=true) = 0; - void ContextMenu(Point pt); - - virtual void ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers); - virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt); - - void NotifyStyleToNeeded(int endStyleNeeded); - void NotifyLexerChanged(Document *doc, void *userData); - -public: - // Public so scintilla_send_message can use it - virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/Selection.h b/libs/qscintilla/src/Selection.h deleted file mode 100644 index 499f83771..000000000 --- a/libs/qscintilla/src/Selection.h +++ /dev/null @@ -1,193 +0,0 @@ -// Scintilla source code edit control -/** @file Selection.h - ** Classes maintaining the selection. - **/ -// Copyright 2009 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef SELECTION_H -#define SELECTION_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -class SelectionPosition { - int position; - int virtualSpace; -public: - explicit SelectionPosition(int position_=INVALID_POSITION, int virtualSpace_=0) : position(position_), virtualSpace(virtualSpace_) { - PLATFORM_ASSERT(virtualSpace < 800000); - if (virtualSpace < 0) - virtualSpace = 0; - } - void Reset() { - position = 0; - virtualSpace = 0; - } - void MoveForInsertDelete(bool insertion, int startChange, int length); - bool operator ==(const SelectionPosition &other) const { - return position == other.position && virtualSpace == other.virtualSpace; - } - bool operator <(const SelectionPosition &other) const; - bool operator >(const SelectionPosition &other) const; - bool operator <=(const SelectionPosition &other) const; - bool operator >=(const SelectionPosition &other) const; - int Position() const { - return position; - } - void SetPosition(int position_) { - position = position_; - virtualSpace = 0; - } - int VirtualSpace() const { - return virtualSpace; - } - void SetVirtualSpace(int virtualSpace_) { - PLATFORM_ASSERT(virtualSpace_ < 800000); - if (virtualSpace_ >= 0) - virtualSpace = virtualSpace_; - } - void Add(int increment) { - position = position + increment; - } - bool IsValid() const { - return position >= 0; - } -}; - -// Ordered range to make drawing simpler -struct SelectionSegment { - SelectionPosition start; - SelectionPosition end; - SelectionSegment() : start(), end() { - } - SelectionSegment(SelectionPosition a, SelectionPosition b) { - if (a < b) { - start = a; - end = b; - } else { - start = b; - end = a; - } - } - bool Empty() const { - return start == end; - } - void Extend(SelectionPosition p) { - if (start > p) - start = p; - if (end < p) - end = p; - } -}; - -struct SelectionRange { - SelectionPosition caret; - SelectionPosition anchor; - - SelectionRange() : caret(), anchor() { - } - explicit SelectionRange(SelectionPosition single) : caret(single), anchor(single) { - } - explicit SelectionRange(int single) : caret(single), anchor(single) { - } - SelectionRange(SelectionPosition caret_, SelectionPosition anchor_) : caret(caret_), anchor(anchor_) { - } - SelectionRange(int caret_, int anchor_) : caret(caret_), anchor(anchor_) { - } - bool Empty() const { - return anchor == caret; - } - int Length() const; - // int Width() const; // Like Length but takes virtual space into account - bool operator ==(const SelectionRange &other) const { - return caret == other.caret && anchor == other.anchor; - } - bool operator <(const SelectionRange &other) const { - return caret < other.caret || ((caret == other.caret) && (anchor < other.anchor)); - } - void Reset() { - anchor.Reset(); - caret.Reset(); - } - void ClearVirtualSpace() { - anchor.SetVirtualSpace(0); - caret.SetVirtualSpace(0); - } - void MoveForInsertDelete(bool insertion, int startChange, int length); - bool Contains(int pos) const; - bool Contains(SelectionPosition sp) const; - bool ContainsCharacter(int posCharacter) const; - SelectionSegment Intersect(SelectionSegment check) const; - SelectionPosition Start() const { - return (anchor < caret) ? anchor : caret; - } - SelectionPosition End() const { - return (anchor < caret) ? caret : anchor; - } - bool Trim(SelectionRange range); - // If range is all virtual collapse to start of virtual space - void MinimizeVirtualSpace(); -}; - -class Selection { - std::vector ranges; - std::vector rangesSaved; - SelectionRange rangeRectangular; - size_t mainRange; - bool moveExtends; - bool tentativeMain; -public: - enum selTypes { noSel, selStream, selRectangle, selLines, selThin }; - selTypes selType; - - Selection(); - ~Selection(); - bool IsRectangular() const; - int MainCaret() const; - int MainAnchor() const; - SelectionRange &Rectangular(); - SelectionSegment Limits() const; - // This is for when you want to move the caret in response to a - // user direction command - for rectangular selections, use the range - // that covers all selected text otherwise return the main selection. - SelectionSegment LimitsForRectangularElseMain() const; - size_t Count() const; - size_t Main() const; - void SetMain(size_t r); - SelectionRange &Range(size_t r); - const SelectionRange &Range(size_t r) const; - SelectionRange &RangeMain(); - const SelectionRange &RangeMain() const; - SelectionPosition Start() const; - bool MoveExtends() const; - void SetMoveExtends(bool moveExtends_); - bool Empty() const; - SelectionPosition Last() const; - int Length() const; - void MovePositions(bool insertion, int startChange, int length); - void TrimSelection(SelectionRange range); - void SetSelection(SelectionRange range); - void AddSelection(SelectionRange range); - void AddSelectionWithoutTrim(SelectionRange range); - void DropSelection(size_t r); - void TentativeSelection(SelectionRange range); - void CommitTentative(); - int CharacterInSelection(int posCharacter) const; - int InSelectionForEOL(int pos) const; - int VirtualSpaceFor(int pos) const; - void Clear(); - void RemoveDuplicates(); - void RotateMain(); - bool Tentative() const { return tentativeMain; } - std::vector RangesCopy() const { - return ranges; - } -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/SplitVector.h b/libs/qscintilla/src/SplitVector.h deleted file mode 100644 index 288c9e39f..000000000 --- a/libs/qscintilla/src/SplitVector.h +++ /dev/null @@ -1,291 +0,0 @@ -// Scintilla source code edit control -/** @file SplitVector.h - ** Main data structure for holding arrays that handle insertions - ** and deletions efficiently. - **/ -// Copyright 1998-2007 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef SPLITVECTOR_H -#define SPLITVECTOR_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -template -class SplitVector { -protected: - T *body; - int size; - int lengthBody; - int part1Length; - int gapLength; /// invariant: gapLength == size - lengthBody - int growSize; - - /// Move the gap to a particular position so that insertion and - /// deletion at that point will not require much copying and - /// hence be fast. - void GapTo(int position) { - if (position != part1Length) { - if (position < part1Length) { - memmove( - body + position + gapLength, - body + position, - sizeof(T) * (part1Length - position)); - } else { // position > part1Length - memmove( - body + part1Length, - body + part1Length + gapLength, - sizeof(T) * (position - part1Length)); - } - part1Length = position; - } - } - - /// Check that there is room in the buffer for an insertion, - /// reallocating if more space needed. - void RoomFor(int insertionLength) { - if (gapLength <= insertionLength) { - while (growSize < size / 6) - growSize *= 2; - ReAllocate(size + insertionLength + growSize); - } - } - - void Init() { - body = NULL; - growSize = 8; - size = 0; - lengthBody = 0; - part1Length = 0; - gapLength = 0; - } - -public: - /// Construct a split buffer. - SplitVector() { - Init(); - } - - ~SplitVector() { - delete []body; - body = 0; - } - - int GetGrowSize() const { - return growSize; - } - - void SetGrowSize(int growSize_) { - growSize = growSize_; - } - - /// Reallocate the storage for the buffer to be newSize and - /// copy exisiting contents to the new buffer. - /// Must not be used to decrease the size of the buffer. - void ReAllocate(int newSize) { - if (newSize > size) { - // Move the gap to the end - GapTo(lengthBody); - T *newBody = new T[newSize]; - if ((size != 0) && (body != 0)) { - memmove(newBody, body, sizeof(T) * lengthBody); - delete []body; - } - body = newBody; - gapLength += newSize - size; - size = newSize; - } - } - - /// Retrieve the character at a particular position. - /// Retrieving positions outside the range of the buffer returns 0. - /// The assertions here are disabled since calling code can be - /// simpler if out of range access works and returns 0. - T ValueAt(int position) const { - if (position < part1Length) { - //PLATFORM_ASSERT(position >= 0); - if (position < 0) { - return 0; - } else { - return body[position]; - } - } else { - //PLATFORM_ASSERT(position < lengthBody); - if (position >= lengthBody) { - return 0; - } else { - return body[gapLength + position]; - } - } - } - - void SetValueAt(int position, T v) { - if (position < part1Length) { - PLATFORM_ASSERT(position >= 0); - if (position < 0) { - ; - } else { - body[position] = v; - } - } else { - PLATFORM_ASSERT(position < lengthBody); - if (position >= lengthBody) { - ; - } else { - body[gapLength + position] = v; - } - } - } - - T &operator[](int position) const { - PLATFORM_ASSERT(position >= 0 && position < lengthBody); - if (position < part1Length) { - return body[position]; - } else { - return body[gapLength + position]; - } - } - - /// Retrieve the length of the buffer. - int Length() const { - return lengthBody; - } - - /// Insert a single value into the buffer. - /// Inserting at positions outside the current range fails. - void Insert(int position, T v) { - PLATFORM_ASSERT((position >= 0) && (position <= lengthBody)); - if ((position < 0) || (position > lengthBody)) { - return; - } - RoomFor(1); - GapTo(position); - body[part1Length] = v; - lengthBody++; - part1Length++; - gapLength--; - } - - /// Insert a number of elements into the buffer setting their value. - /// Inserting at positions outside the current range fails. - void InsertValue(int position, int insertLength, T v) { - PLATFORM_ASSERT((position >= 0) && (position <= lengthBody)); - if (insertLength > 0) { - if ((position < 0) || (position > lengthBody)) { - return; - } - RoomFor(insertLength); - GapTo(position); - std::fill(&body[part1Length], &body[part1Length + insertLength], v); - lengthBody += insertLength; - part1Length += insertLength; - gapLength -= insertLength; - } - } - - /// Ensure at least length elements allocated, - /// appending zero valued elements if needed. - void EnsureLength(int wantedLength) { - if (Length() < wantedLength) { - InsertValue(Length(), wantedLength - Length(), 0); - } - } - - /// Insert text into the buffer from an array. - void InsertFromArray(int positionToInsert, const T s[], int positionFrom, int insertLength) { - PLATFORM_ASSERT((positionToInsert >= 0) && (positionToInsert <= lengthBody)); - if (insertLength > 0) { - if ((positionToInsert < 0) || (positionToInsert > lengthBody)) { - return; - } - RoomFor(insertLength); - GapTo(positionToInsert); - memmove(body + part1Length, s + positionFrom, sizeof(T) * insertLength); - lengthBody += insertLength; - part1Length += insertLength; - gapLength -= insertLength; - } - } - - /// Delete one element from the buffer. - void Delete(int position) { - PLATFORM_ASSERT((position >= 0) && (position < lengthBody)); - if ((position < 0) || (position >= lengthBody)) { - return; - } - DeleteRange(position, 1); - } - - /// Delete a range from the buffer. - /// Deleting positions outside the current range fails. - void DeleteRange(int position, int deleteLength) { - PLATFORM_ASSERT((position >= 0) && (position + deleteLength <= lengthBody)); - if ((position < 0) || ((position + deleteLength) > lengthBody)) { - return; - } - if ((position == 0) && (deleteLength == lengthBody)) { - // Full deallocation returns storage and is faster - delete []body; - Init(); - } else if (deleteLength > 0) { - GapTo(position); - lengthBody -= deleteLength; - gapLength += deleteLength; - } - } - - /// Delete all the buffer contents. - void DeleteAll() { - DeleteRange(0, lengthBody); - } - - // Retrieve a range of elements into an array - void GetRange(T *buffer, int position, int retrieveLength) const { - // Split into up to 2 ranges, before and after the split then use memcpy on each. - int range1Length = 0; - if (position < part1Length) { - int part1AfterPosition = part1Length - position; - range1Length = retrieveLength; - if (range1Length > part1AfterPosition) - range1Length = part1AfterPosition; - } - memcpy(buffer, body + position, range1Length * sizeof(T)); - buffer += range1Length; - position = position + range1Length + gapLength; - int range2Length = retrieveLength - range1Length; - memcpy(buffer, body + position, range2Length * sizeof(T)); - } - - T *BufferPointer() { - RoomFor(1); - GapTo(lengthBody); - body[lengthBody] = 0; - return body; - } - - T *RangePointer(int position, int rangeLength) { - if (position < part1Length) { - if ((position + rangeLength) > part1Length) { - // Range overlaps gap, so move gap to start of range. - GapTo(position); - return body + position + gapLength; - } else { - return body + position; - } - } else { - return body + position + gapLength; - } - } - - int GapPosition() const { - return part1Length; - } -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/UniConversion.cpp b/libs/qscintilla/src/UniConversion.cpp deleted file mode 100644 index 04053b057..000000000 --- a/libs/qscintilla/src/UniConversion.cpp +++ /dev/null @@ -1,311 +0,0 @@ -// Scintilla source code edit control -/** @file UniConversion.cxx - ** Functions to handle UTF-8 and UTF-16 strings. - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include - -#include "UniConversion.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -enum { SURROGATE_TRAIL_FIRST = 0xDC00 }; -enum { SURROGATE_TRAIL_LAST = 0xDFFF }; -enum { SUPPLEMENTAL_PLANE_FIRST = 0x10000 }; - -unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen) { - unsigned int len = 0; - for (unsigned int i = 0; i < tlen && uptr[i];) { - unsigned int uch = uptr[i]; - if (uch < 0x80) { - len++; - } else if (uch < 0x800) { - len += 2; - } else if ((uch >= SURROGATE_LEAD_FIRST) && - (uch <= SURROGATE_TRAIL_LAST)) { - len += 4; - i++; - } else { - len += 3; - } - i++; - } - return len; -} - -void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len) { - unsigned int k = 0; - for (unsigned int i = 0; i < tlen && uptr[i];) { - unsigned int uch = uptr[i]; - if (uch < 0x80) { - putf[k++] = static_cast(uch); - } else if (uch < 0x800) { - putf[k++] = static_cast(0xC0 | (uch >> 6)); - putf[k++] = static_cast(0x80 | (uch & 0x3f)); - } else if ((uch >= SURROGATE_LEAD_FIRST) && - (uch <= SURROGATE_TRAIL_LAST)) { - // Half a surrogate pair - i++; - unsigned int xch = 0x10000 + ((uch & 0x3ff) << 10) + (uptr[i] & 0x3ff); - putf[k++] = static_cast(0xF0 | (xch >> 18)); - putf[k++] = static_cast(0x80 | ((xch >> 12) & 0x3f)); - putf[k++] = static_cast(0x80 | ((xch >> 6) & 0x3f)); - putf[k++] = static_cast(0x80 | (xch & 0x3f)); - } else { - putf[k++] = static_cast(0xE0 | (uch >> 12)); - putf[k++] = static_cast(0x80 | ((uch >> 6) & 0x3f)); - putf[k++] = static_cast(0x80 | (uch & 0x3f)); - } - i++; - } - if (k < len) - putf[k] = '\0'; -} - -unsigned int UTF8CharLength(unsigned char ch) { - if (ch < 0x80) { - return 1; - } else if (ch < 0x80 + 0x40 + 0x20) { - return 2; - } else if (ch < 0x80 + 0x40 + 0x20 + 0x10) { - return 3; - } else { - return 4; - } -} - -size_t UTF16Length(const char *s, size_t len) { - size_t ulen = 0; - size_t charLen; - for (size_t i = 0; i(s[i]); - if (ch < 0x80) { - charLen = 1; - } else if (ch < 0x80 + 0x40 + 0x20) { - charLen = 2; - } else if (ch < 0x80 + 0x40 + 0x20 + 0x10) { - charLen = 3; - } else { - charLen = 4; - ulen++; - } - i += charLen; - ulen++; - } - return ulen; -} - -size_t UTF16FromUTF8(const char *s, size_t len, wchar_t *tbuf, size_t tlen) { - size_t ui = 0; - const unsigned char *us = reinterpret_cast(s); - size_t i = 0; - while ((i((ch & 0x1F) << 6); - ch = us[i++]; - tbuf[ui] = static_cast(tbuf[ui] + (ch & 0x7F)); - } else if (ch < 0x80 + 0x40 + 0x20 + 0x10) { - tbuf[ui] = static_cast((ch & 0xF) << 12); - ch = us[i++]; - tbuf[ui] = static_cast(tbuf[ui] + ((ch & 0x7F) << 6)); - ch = us[i++]; - tbuf[ui] = static_cast(tbuf[ui] + (ch & 0x7F)); - } else { - // Outside the BMP so need two surrogates - int val = (ch & 0x7) << 18; - ch = us[i++]; - val += (ch & 0x3F) << 12; - ch = us[i++]; - val += (ch & 0x3F) << 6; - ch = us[i++]; - val += (ch & 0x3F); - tbuf[ui] = static_cast(((val - 0x10000) >> 10) + SURROGATE_LEAD_FIRST); - ui++; - tbuf[ui] = static_cast((val & 0x3ff) + SURROGATE_TRAIL_FIRST); - } - ui++; - } - return ui; -} - -unsigned int UTF32FromUTF8(const char *s, unsigned int len, unsigned int *tbuf, unsigned int tlen) { - unsigned int ui=0; - const unsigned char *us = reinterpret_cast(s); - unsigned int i=0; - while ((i= 1) && (ch < 0x80 + 0x40 + 0x20)) { - value = (ch & 0x1F) << 6; - ch = us[i++]; - value += ch & 0x7F; - } else if (((len-i) >= 2) && (ch < 0x80 + 0x40 + 0x20 + 0x10)) { - value = (ch & 0xF) << 12; - ch = us[i++]; - value += (ch & 0x7F) << 6; - ch = us[i++]; - value += ch & 0x7F; - } else if ((len-i) >= 3) { - value = (ch & 0x7) << 18; - ch = us[i++]; - value += (ch & 0x3F) << 12; - ch = us[i++]; - value += (ch & 0x3F) << 6; - ch = us[i++]; - value += ch & 0x3F; - } - tbuf[ui] = value; - ui++; - } - return ui; -} - -unsigned int UTF16FromUTF32Character(unsigned int val, wchar_t *tbuf) { - if (val < SUPPLEMENTAL_PLANE_FIRST) { - tbuf[0] = static_cast(val); - return 1; - } else { - tbuf[0] = static_cast(((val - SUPPLEMENTAL_PLANE_FIRST) >> 10) + SURROGATE_LEAD_FIRST); - tbuf[1] = static_cast((val & 0x3ff) + SURROGATE_TRAIL_FIRST); - return 2; - } -} - -int UTF8BytesOfLead[256]; -static bool initialisedBytesOfLead = false; - -static int BytesFromLead(int leadByte) { - if (leadByte < 0xC2) { - // Single byte or invalid - return 1; - } else if (leadByte < 0xE0) { - return 2; - } else if (leadByte < 0xF0) { - return 3; - } else if (leadByte < 0xF5) { - return 4; - } else { - // Characters longer than 4 bytes not possible in current UTF-8 - return 1; - } -} - -void UTF8BytesOfLeadInitialise() { - if (!initialisedBytesOfLead) { - for (int i=0; i<256; i++) { - UTF8BytesOfLead[i] = BytesFromLead(i); - } - initialisedBytesOfLead = true; - } -} - -// Return both the width of the first character in the string and a status -// saying whether it is valid or invalid. -// Most invalid sequences return a width of 1 so are treated as isolated bytes but -// the non-characters *FFFE, *FFFF and FDD0 .. FDEF return 3 or 4 as they can be -// reasonably treated as code points in some circumstances. They will, however, -// not have associated glyphs. -int UTF8Classify(const unsigned char *us, int len) { - // For the rules: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - if (*us < 0x80) { - // Single bytes easy - return 1; - } else if (*us > 0xf4) { - // Characters longer than 4 bytes not possible in current UTF-8 - return UTF8MaskInvalid | 1; - } else if (*us >= 0xf0) { - // 4 bytes - if (len < 4) - return UTF8MaskInvalid | 1; - if (UTF8IsTrailByte(us[1]) && UTF8IsTrailByte(us[2]) && UTF8IsTrailByte(us[3])) { - if (((us[1] & 0xf) == 0xf) && (us[2] == 0xbf) && ((us[3] == 0xbe) || (us[3] == 0xbf))) { - // *FFFE or *FFFF non-character - return UTF8MaskInvalid | 4; - } - if (*us == 0xf4) { - // Check if encoding a value beyond the last Unicode character 10FFFF - if (us[1] > 0x8f) { - return UTF8MaskInvalid | 1; - } else if (us[1] == 0x8f) { - if (us[2] > 0xbf) { - return UTF8MaskInvalid | 1; - } else if (us[2] == 0xbf) { - if (us[3] > 0xbf) { - return UTF8MaskInvalid | 1; - } - } - } - } else if ((*us == 0xf0) && ((us[1] & 0xf0) == 0x80)) { - // Overlong - return UTF8MaskInvalid | 1; - } - return 4; - } else { - return UTF8MaskInvalid | 1; - } - } else if (*us >= 0xe0) { - // 3 bytes - if (len < 3) - return UTF8MaskInvalid | 1; - if (UTF8IsTrailByte(us[1]) && UTF8IsTrailByte(us[2])) { - if ((*us == 0xe0) && ((us[1] & 0xe0) == 0x80)) { - // Overlong - return UTF8MaskInvalid | 1; - } - if ((*us == 0xed) && ((us[1] & 0xe0) == 0xa0)) { - // Surrogate - return UTF8MaskInvalid | 1; - } - if ((*us == 0xef) && (us[1] == 0xbf) && (us[2] == 0xbe)) { - // U+FFFE non-character - 3 bytes long - return UTF8MaskInvalid | 3; - } - if ((*us == 0xef) && (us[1] == 0xbf) && (us[2] == 0xbf)) { - // U+FFFF non-character - 3 bytes long - return UTF8MaskInvalid | 3; - } - if ((*us == 0xef) && (us[1] == 0xb7) && (((us[2] & 0xf0) == 0x90) || ((us[2] & 0xf0) == 0xa0))) { - // U+FDD0 .. U+FDEF - return UTF8MaskInvalid | 3; - } - return 3; - } else { - return UTF8MaskInvalid | 1; - } - } else if (*us >= 0xc2) { - // 2 bytes - if (len < 2) - return UTF8MaskInvalid | 1; - if (UTF8IsTrailByte(us[1])) { - return 2; - } else { - return UTF8MaskInvalid | 1; - } - } else { - // 0xc0 .. 0xc1 is overlong encoding - // 0x80 .. 0xbf is trail byte - return UTF8MaskInvalid | 1; - } -} - -int UTF8DrawBytes(const unsigned char *us, int len) { - int utf8StatusNext = UTF8Classify(us, len); - return (utf8StatusNext & UTF8MaskInvalid) ? 1 : (utf8StatusNext & UTF8MaskWidth); -} - -#ifdef SCI_NAMESPACE -} -#endif diff --git a/libs/qscintilla/src/UniConversion.h b/libs/qscintilla/src/UniConversion.h deleted file mode 100644 index 08898cac3..000000000 --- a/libs/qscintilla/src/UniConversion.h +++ /dev/null @@ -1,68 +0,0 @@ -// Scintilla source code edit control -/** @file UniConversion.h - ** Functions to handle UTF-8 and UTF-16 strings. - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef UNICONVERSION_H -#define UNICONVERSION_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -const int UTF8MaxBytes = 4; - -const int unicodeReplacementChar = 0xFFFD; - -unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen); -void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len); -unsigned int UTF8CharLength(unsigned char ch); -size_t UTF16Length(const char *s, size_t len); -size_t UTF16FromUTF8(const char *s, size_t len, wchar_t *tbuf, size_t tlen); -unsigned int UTF32FromUTF8(const char *s, unsigned int len, unsigned int *tbuf, unsigned int tlen); -unsigned int UTF16FromUTF32Character(unsigned int val, wchar_t *tbuf); - -extern int UTF8BytesOfLead[256]; -void UTF8BytesOfLeadInitialise(); - -inline bool UTF8IsTrailByte(int ch) { - return (ch >= 0x80) && (ch < 0xc0); -} - -inline bool UTF8IsAscii(int ch) { - return ch < 0x80; -} - -enum { UTF8MaskWidth=0x7, UTF8MaskInvalid=0x8 }; -int UTF8Classify(const unsigned char *us, int len); - -// Similar to UTF8Classify but returns a length of 1 for invalid bytes -// instead of setting the invalid flag -int UTF8DrawBytes(const unsigned char *us, int len); - -// Line separator is U+2028 \xe2\x80\xa8 -// Paragraph separator is U+2029 \xe2\x80\xa9 -const int UTF8SeparatorLength = 3; -inline bool UTF8IsSeparator(const unsigned char *us) { - return (us[0] == 0xe2) && (us[1] == 0x80) && ((us[2] == 0xa8) || (us[2] == 0xa9)); -} - -// NEL is U+0085 \xc2\x85 -const int UTF8NELLength = 2; -inline bool UTF8IsNEL(const unsigned char *us) { - return (us[0] == 0xc2) && (us[1] == 0x85); -} - -enum { SURROGATE_LEAD_FIRST = 0xD800 }; -enum { SURROGATE_LEAD_LAST = 0xDBFF }; -inline unsigned int UTF16CharLength(wchar_t uch) { - return ((uch >= SURROGATE_LEAD_FIRST) && (uch <= SURROGATE_LEAD_LAST)) ? 2 : 1; -} - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/UnicodeFromUTF8.h b/libs/qscintilla/src/UnicodeFromUTF8.h deleted file mode 100644 index ae66cb0a9..000000000 --- a/libs/qscintilla/src/UnicodeFromUTF8.h +++ /dev/null @@ -1,32 +0,0 @@ -// Scintilla source code edit control -/** @file UnicodeFromUTF8.h - ** Lexer infrastructure. - **/ -// Copyright 2013 by Neil Hodgson -// This file is in the public domain. - -#ifndef UNICODEFROMUTF8_H -#define UNICODEFROMUTF8_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -inline int UnicodeFromUTF8(const unsigned char *us) { - if (us[0] < 0xC2) { - return us[0]; - } else if (us[0] < 0xE0) { - return ((us[0] & 0x1F) << 6) + (us[1] & 0x3F); - } else if (us[0] < 0xF0) { - return ((us[0] & 0xF) << 12) + ((us[1] & 0x3F) << 6) + (us[2] & 0x3F); - } else if (us[0] < 0xF5) { - return ((us[0] & 0x7) << 18) + ((us[1] & 0x3F) << 12) + ((us[2] & 0x3F) << 6) + (us[3] & 0x3F); - } - return us[0]; -} - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/libs/qscintilla/src/ViewStyle.cpp b/libs/qscintilla/src/ViewStyle.cpp deleted file mode 100644 index e56c8f375..000000000 --- a/libs/qscintilla/src/ViewStyle.cpp +++ /dev/null @@ -1,589 +0,0 @@ -// Scintilla source code edit control -/** @file ViewStyle.cxx - ** Store information on how the document is to be viewed. - **/ -// Copyright 1998-2003 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#include -#include - -#include -#include - -#include "Platform.h" - -#include "Scintilla.h" -#include "SplitVector.h" -#include "Partitioning.h" -#include "RunStyles.h" -#include "Indicator.h" -#include "XPM.h" -#include "LineMarker.h" -#include "Style.h" -#include "ViewStyle.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -MarginStyle::MarginStyle() : - style(SC_MARGIN_SYMBOL), width(0), mask(0), sensitive(false), cursor(SC_CURSORREVERSEARROW) { -} - -// A list of the fontnames - avoids wasting space in each style -FontNames::FontNames() { -} - -FontNames::~FontNames() { - Clear(); -} - -void FontNames::Clear() { - for (std::vector::const_iterator it=names.begin(); it != names.end(); ++it) { - delete []*it; - } - names.clear(); -} - -const char *FontNames::Save(const char *name) { - if (!name) - return 0; - - for (std::vector::const_iterator it=names.begin(); it != names.end(); ++it) { - if (strcmp(*it, name) == 0) { - return *it; - } - } - const size_t lenName = strlen(name) + 1; - char *nameSave = new char[lenName]; - memcpy(nameSave, name, lenName); - names.push_back(nameSave); - return nameSave; -} - -FontRealised::FontRealised() { -} - -FontRealised::~FontRealised() { - font.Release(); -} - -void FontRealised::Realise(Surface &surface, int zoomLevel, int technology, const FontSpecification &fs) { - PLATFORM_ASSERT(fs.fontName); - sizeZoomed = fs.size + zoomLevel * SC_FONT_SIZE_MULTIPLIER; - if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1 - sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER; - - float deviceHeight = static_cast(surface.DeviceHeightFont(sizeZoomed)); - FontParameters fp(fs.fontName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, fs.weight, fs.italic, fs.extraFontFlag, technology, fs.characterSet); - font.Create(fp); - - ascent = static_cast(surface.Ascent(font)); - descent = static_cast(surface.Descent(font)); - aveCharWidth = surface.AverageCharWidth(font); - spaceWidth = surface.WidthChar(font, ' '); -} - -ViewStyle::ViewStyle() { - Init(); -} - -ViewStyle::ViewStyle(const ViewStyle &source) { - Init(source.styles.size()); - for (unsigned int sty=0; stysecond; - } - fonts.clear(); -} - -void ViewStyle::Init(size_t stylesSize_) { - AllocStyles(stylesSize_); - nextExtendedStyle = 256; - fontNames.Clear(); - ResetDefaultStyle(); - - // There are no image markers by default, so no need for calling CalcLargestMarkerHeight() - largestMarkerHeight = 0; - - indicators[0] = Indicator(INDIC_SQUIGGLE, ColourDesired(0, 0x7f, 0)); - indicators[1] = Indicator(INDIC_TT, ColourDesired(0, 0, 0xff)); - indicators[2] = Indicator(INDIC_PLAIN, ColourDesired(0xff, 0, 0)); - - technology = SC_TECHNOLOGY_DEFAULT; - indicatorsDynamic = 0; - indicatorsSetFore = 0; - lineHeight = 1; - lineOverlap = 0; - maxAscent = 1; - maxDescent = 1; - aveCharWidth = 8; - spaceWidth = 8; - tabWidth = spaceWidth * 8; - - selColours.fore = ColourOptional(ColourDesired(0xff, 0, 0)); - selColours.back = ColourOptional(ColourDesired(0xc0, 0xc0, 0xc0), true); - selAdditionalForeground = ColourDesired(0xff, 0, 0); - selAdditionalBackground = ColourDesired(0xd7, 0xd7, 0xd7); - selBackground2 = ColourDesired(0xb0, 0xb0, 0xb0); - selAlpha = SC_ALPHA_NOALPHA; - selAdditionalAlpha = SC_ALPHA_NOALPHA; - selEOLFilled = false; - - foldmarginColour = ColourOptional(ColourDesired(0xff, 0, 0)); - foldmarginHighlightColour = ColourOptional(ColourDesired(0xc0, 0xc0, 0xc0)); - - whitespaceColours.fore = ColourOptional(); - whitespaceColours.back = ColourOptional(ColourDesired(0xff, 0xff, 0xff)); - controlCharSymbol = 0; /* Draw the control characters */ - controlCharWidth = 0; - selbar = Platform::Chrome(); - selbarlight = Platform::ChromeHighlight(); - styles[STYLE_LINENUMBER].fore = ColourDesired(0, 0, 0); - styles[STYLE_LINENUMBER].back = Platform::Chrome(); - caretcolour = ColourDesired(0, 0, 0); - additionalCaretColour = ColourDesired(0x7f, 0x7f, 0x7f); - showCaretLineBackground = false; - alwaysShowCaretLineBackground = false; - caretLineBackground = ColourDesired(0xff, 0xff, 0); - caretLineAlpha = SC_ALPHA_NOALPHA; - edgecolour = ColourDesired(0xc0, 0xc0, 0xc0); - edgeState = EDGE_NONE; - caretStyle = CARETSTYLE_LINE; - caretWidth = 1; - someStylesProtected = false; - someStylesForceCase = false; - - hotspotColours.fore = ColourOptional(ColourDesired(0, 0, 0xff)); - hotspotColours.back = ColourOptional(ColourDesired(0xff, 0xff, 0xff)); - hotspotUnderline = true; - hotspotSingleLine = true; - - leftMarginWidth = 1; - rightMarginWidth = 1; - ms[0].style = SC_MARGIN_NUMBER; - ms[0].width = 0; - ms[0].mask = 0; - ms[1].style = SC_MARGIN_SYMBOL; - ms[1].width = 16; - ms[1].mask = ~SC_MASK_FOLDERS; - ms[2].style = SC_MARGIN_SYMBOL; - ms[2].width = 0; - ms[2].mask = 0; - marginInside = true; - fixedColumnWidth = marginInside ? leftMarginWidth : 0; - maskInLine = 0xffffffff; - for (int margin=0; margin <= SC_MAX_MARGIN; margin++) { - fixedColumnWidth += ms[margin].width; - if (ms[margin].width > 0) - maskInLine &= ~ms[margin].mask; - } - textStart = marginInside ? fixedColumnWidth : leftMarginWidth; - zoomLevel = 0; - viewWhitespace = wsInvisible; - whitespaceSize = 1; - viewIndentationGuides = ivNone; - viewEOL = false; - extraFontFlag = 0; - extraAscent = 0; - extraDescent = 0; - marginStyleOffset = 0; - annotationVisible = ANNOTATION_HIDDEN; - annotationStyleOffset = 0; - braceHighlightIndicatorSet = false; - braceHighlightIndicator = 0; - braceBadLightIndicatorSet = false; - braceBadLightIndicator = 0; - - theEdge = 0; - - marginNumberPadding = 3; - ctrlCharPadding = 3; // +3 For a blank on front and rounded edge each side - lastSegItalicsOffset = 2; - - wrapState = eWrapNone; - wrapVisualFlags = 0; - wrapVisualFlagsLocation = 0; - wrapVisualStartIndent = 0; - wrapIndentMode = SC_WRAPINDENT_FIXED; -} - -void ViewStyle::Refresh(Surface &surface, int tabInChars) { - for (FontMap::iterator it = fonts.begin(); it != fonts.end(); ++it) { - delete it->second; - } - fonts.clear(); - - selbar = Platform::Chrome(); - selbarlight = Platform::ChromeHighlight(); - - for (unsigned int i=0; isecond->Realise(surface, zoomLevel, technology, it->first); - } - - for (unsigned int k=0; kfont, *fr); - } - indicatorsDynamic = 0; - indicatorsSetFore = 0; - for (int ind = 0; ind <= INDIC_MAX; ind++) { - if (indicators[ind].IsDynamic()) - indicatorsDynamic++; - if (indicators[ind].OverridesTextFore()) - indicatorsSetFore++; - } - maxAscent = 1; - maxDescent = 1; - FindMaxAscentDescent(); - maxAscent += extraAscent; - maxDescent += extraDescent; - lineHeight = maxAscent + maxDescent; - lineOverlap = lineHeight / 10; - if (lineOverlap < 2) - lineOverlap = 2; - if (lineOverlap > lineHeight) - lineOverlap = lineHeight; - - someStylesProtected = false; - someStylesForceCase = false; - for (unsigned int l=0; l= 32) { - controlCharWidth = surface.WidthChar(styles[STYLE_CONTROLCHAR].font, static_cast(controlCharSymbol)); - } - - fixedColumnWidth = marginInside ? leftMarginWidth : 0; - maskInLine = 0xffffffff; - for (int margin=0; margin <= SC_MAX_MARGIN; margin++) { - fixedColumnWidth += ms[margin].width; - if (ms[margin].width > 0) - maskInLine &= ~ms[margin].mask; - } - textStart = marginInside ? fixedColumnWidth : leftMarginWidth; -} - -void ViewStyle::ReleaseAllExtendedStyles() { - nextExtendedStyle = 256; -} - -int ViewStyle::AllocateExtendedStyles(int numberStyles) { - int startRange = static_cast(nextExtendedStyle); - nextExtendedStyle += numberStyles; - EnsureStyle(nextExtendedStyle); - for (size_t i=startRange; i= styles.size()) { - AllocStyles(index+1); - } -} - -void ViewStyle::ResetDefaultStyle() { - styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0), - ColourDesired(0xff,0xff,0xff), - Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, fontNames.Save(Platform::DefaultFont()), - SC_CHARSET_DEFAULT, - SC_WEIGHT_NORMAL, false, false, false, Style::caseMixed, true, true, false); -} - -void ViewStyle::ClearStyles() { - // Reset all styles to be like the default style - for (unsigned int i=0; iGetHeight() > largestMarkerHeight) - largestMarkerHeight = markers[m].pxpm->GetHeight(); - break; - case SC_MARK_RGBAIMAGE: - if (markers[m].image && markers[m].image->GetHeight() > largestMarkerHeight) - largestMarkerHeight = markers[m].image->GetHeight(); - break; - } - } -} - -// See if something overrides the line background color: Either if caret is on the line -// and background color is set for that, or if a marker is defined that forces its background -// color onto the line, or if a marker is defined but has no selection margin in which to -// display itself (as long as it's not an SC_MARK_EMPTY marker). These are checked in order -// with the earlier taking precedence. When multiple markers cause background override, -// the color for the highest numbered one is used. -ColourOptional ViewStyle::Background(int marksOfLine, bool caretActive, bool lineContainsCaret) const { - ColourOptional background; - if ((caretActive || alwaysShowCaretLineBackground) && showCaretLineBackground && (caretLineAlpha == SC_ALPHA_NOALPHA) && lineContainsCaret) { - background = ColourOptional(caretLineBackground, true); - } - if (!background.isSet && marksOfLine) { - int marks = marksOfLine; - for (int markBit = 0; (markBit < 32) && marks; markBit++) { - if ((marks & 1) && (markers[markBit].markType == SC_MARK_BACKGROUND) && - (markers[markBit].alpha == SC_ALPHA_NOALPHA)) { - background = ColourOptional(markers[markBit].back, true); - } - marks >>= 1; - } - } - if (!background.isSet && maskInLine) { - int marksMasked = marksOfLine & maskInLine; - if (marksMasked) { - for (int markBit = 0; (markBit < 32) && marksMasked; markBit++) { - if ((marksMasked & 1) && (markers[markBit].markType != SC_MARK_EMPTY) && - (markers[markBit].alpha == SC_ALPHA_NOALPHA)) { - background = ColourOptional(markers[markBit].back, true); - } - marksMasked >>= 1; - } - } - } - return background; -} - -bool ViewStyle::SelectionBackgroundDrawn() const { - return selColours.back.isSet && - ((selAlpha == SC_ALPHA_NOALPHA) || (selAdditionalAlpha == SC_ALPHA_NOALPHA)); -} - -bool ViewStyle::WhitespaceBackgroundDrawn() const { - return (viewWhitespace != wsInvisible) && (whitespaceColours.back.isSet); -} - -ColourDesired ViewStyle::WrapColour() const { - if (whitespaceColours.fore.isSet) - return whitespaceColours.fore; - else - return styles[STYLE_DEFAULT].fore; -} - -bool ViewStyle::SetWrapState(int wrapState_) { - WrapMode wrapStateWanted; - switch (wrapState_) { - case SC_WRAP_WORD: - wrapStateWanted = eWrapWord; - break; - case SC_WRAP_CHAR: - wrapStateWanted = eWrapChar; - break; - case SC_WRAP_WHITESPACE: - wrapStateWanted = eWrapWhitespace; - break; - default: - wrapStateWanted = eWrapNone; - break; - } - bool changed = wrapState != wrapStateWanted; - wrapState = wrapStateWanted; - return changed; -} - -bool ViewStyle::SetWrapVisualFlags(int wrapVisualFlags_) { - bool changed = wrapVisualFlags != wrapVisualFlags_; - wrapVisualFlags = wrapVisualFlags_; - return changed; -} - -bool ViewStyle::SetWrapVisualFlagsLocation(int wrapVisualFlagsLocation_) { - bool changed = wrapVisualFlagsLocation != wrapVisualFlagsLocation_; - wrapVisualFlagsLocation = wrapVisualFlagsLocation_; - return changed; -} - -bool ViewStyle::SetWrapVisualStartIndent(int wrapVisualStartIndent_) { - bool changed = wrapVisualStartIndent != wrapVisualStartIndent_; - wrapVisualStartIndent = wrapVisualStartIndent_; - return changed; -} - -bool ViewStyle::SetWrapIndentMode(int wrapIndentMode_) { - bool changed = wrapIndentMode != wrapIndentMode_; - wrapIndentMode = wrapIndentMode_; - return changed; -} - -void ViewStyle::AllocStyles(size_t sizeNew) { - size_t i=styles.size(); - styles.resize(sizeNew); - if (styles.size() > STYLE_DEFAULT) { - for (; isecond; - FontMap::iterator it = fonts.find(fs); - if (it != fonts.end()) { - // Should always reach here since map was just set for all styles - return it->second; - } - return 0; -} - -void ViewStyle::FindMaxAscentDescent() { - for (FontMap::const_iterator it = fonts.begin(); it != fonts.end(); ++it) { - if (maxAscent < it->second->ascent) - maxAscent = it->second->ascent; - if (maxDescent < it->second->descent) - maxDescent = it->second->descent; - } -} diff --git a/libs/qscintilla/src/ViewStyle.h b/libs/qscintilla/src/ViewStyle.h deleted file mode 100644 index 930ad104c..000000000 --- a/libs/qscintilla/src/ViewStyle.h +++ /dev/null @@ -1,199 +0,0 @@ -// Scintilla source code edit control -/** @file ViewStyle.h - ** Store information on how the document is to be viewed. - **/ -// Copyright 1998-2001 by Neil Hodgson -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef VIEWSTYLE_H -#define VIEWSTYLE_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -/** - */ -class MarginStyle { -public: - int style; - int width; - int mask; - bool sensitive; - int cursor; - MarginStyle(); -}; - -/** - */ -class FontNames { -private: - std::vector names; - - // Private so FontNames objects can not be copied - FontNames(const FontNames &); -public: - FontNames(); - ~FontNames(); - void Clear(); - const char *Save(const char *name); -}; - -class FontRealised : public FontMeasurements { - // Private so FontRealised objects can not be copied - FontRealised(const FontRealised &); - FontRealised &operator=(const FontRealised &); -public: - Font font; - FontRealised(); - virtual ~FontRealised(); - void Realise(Surface &surface, int zoomLevel, int technology, const FontSpecification &fs); -}; - -enum IndentView {ivNone, ivReal, ivLookForward, ivLookBoth}; - -enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterIndent=2}; - -typedef std::map FontMap; - -enum WrapMode { eWrapNone, eWrapWord, eWrapChar, eWrapWhitespace }; - -class ColourOptional : public ColourDesired { -public: - bool isSet; - ColourOptional(ColourDesired colour_=ColourDesired(0,0,0), bool isSet_=false) : ColourDesired(colour_), isSet(isSet_) { - } - ColourOptional(uptr_t wParam, sptr_t lParam) : ColourDesired(static_cast(lParam)), isSet(wParam != 0) { - } -}; - -struct ForeBackColours { - ColourOptional fore; - ColourOptional back; -}; - -/** - */ -class ViewStyle { - FontNames fontNames; - FontMap fonts; -public: - std::vector" + ""); + + // Insert the columns in a set, since they could be non-contiguous. + std::set colsInIndexes, rowsInIndexes; + for(const QModelIndex & idx : qAsConst(indices)) { + colsInIndexes.insert(idx.column()); + rowsInIndexes.insert(idx.row()); } - else - { - // Have only one cell, so there is no line break at end - endOfLine = "\n"; + + const QString fieldSepText = "\t"; +#ifdef Q_OS_WIN + const QString rowSepText = "\r\n"; +#else + const QString rowSepText = "\n"; +#endif + + int firstColumn = *colsInIndexes.begin(); + QString sqlInsertStatement; + // Table headers + if (withHeaders || inSQL) { + if (inSQL) + sqlInsertStatement = QString("INSERT INTO %1 (").arg(QString::fromStdString(m->currentTableName().toString())); + else + htmlResult.append(""); + } } - // Unpack cliboard, assuming that it is rectangular - QList clipboardTable; - QStringList cr = clipboard.split(endOfLine); - foreach(const QString& r, cr) - { - // Usually last splited line is empty - if(!r.isEmpty()) - { - clipboardTable.push_back(r.split("\t")); + QProgressDialog progress(this); + progress.setWindowModality(Qt::ApplicationModal); + // Disable context help button on Windows + progress.setWindowFlags(progress.windowFlags() + & ~Qt::WindowContextHelpButtonHint); + progress.setRange(*rowsInIndexes.begin(), *rowsInIndexes.rbegin()); + progress.setMinimumDuration(2000); + + // Iterate over rows x cols checking if the index actually exists when needed, in order + // to support non-rectangular selections. + for(const int row : rowsInIndexes) { + + // Beginning of row + if (inSQL) + result.append(sqlInsertStatement); + else + htmlResult.append(""); + + for(const int column : colsInIndexes) { + + const QModelIndex index = indices.first().sibling(row, column); + const bool isContained = indices.contains(index); + + if (column != firstColumn) { + // Add text separators + if (inSQL) + result.append(", "); + else + result.append(fieldSepText); + } + + if(isContained) { + QFont font; + font.fromString(index.data(Qt::FontRole).toString()); + + const Qt::Alignment align(index.data(Qt::TextAlignmentRole).toInt()); + const QString textAlign(CondFormat::alignmentTexts().at(CondFormat::fromCombinedAlignment(align)).toLower()); + htmlResult.append(QString(""); + } + + // End of row + if (inSQL) + result.append(");"); + else + htmlResult.append(""); + result.append(rowSepText); + + progress.setValue(row); + // Abort the operation if the user pressed ESC key or Cancel button + if (progress.wasCanceled()) { + return false; } } - int clipboardRows = clipboardTable.size(); - int clipboardColumns = clipboardTable.front().size(); + if (!inSQL) { + htmlResult.append("
"); + + for(int col : colsInIndexes) { + QByteArray headerText = model()->headerData(col, Qt::Horizontal, Qt::EditRole).toByteArray(); + if (col != firstColumn) { + if (inSQL) + sqlInsertStatement.append(", "); + else { + result.append(fieldSepText); + htmlResult.append(""); + } + } + if (inSQL) + sqlInsertStatement.append(sqlb::escapeIdentifier(headerText)); + else { + result.append(headerText); + htmlResult.append(headerText); + } + } + if (inSQL) + sqlInsertStatement.append(") VALUES ("); + else { + result.append(rowSepText); + htmlResult.append("
").arg( + font.family().toHtmlEscaped(), // font-family + QString::number(font.pointSize()), // font-size + font.italic() ? "italic" : "normal", // font-style, + font.bold() ? "bold" : "normal", // font-weigth, + font.underline() ? " text-decoration: underline;" : "", // text-decoration, + index.data(Qt::BackgroundRole).toString(), // background-color + index.data(Qt::ForegroundRole).toString(), // color + textAlign)); + } else { + htmlResult.append(""); + } + QImage img; + const QVariant bArrdata = isContained ? index.data(Qt::EditRole) : QVariant(); + + if (bArrdata.isNull()) { + // NULL data: NULL in SQL, empty in HTML or text. + if (inSQL) result.append("NULL"); + } else if(!m->isBinary(index)) { + // Text data + QByteArray text = bArrdata.toByteArray(); + + if (inSQL) { + // Escape string only if it isn't a number. + switch(bArrdata.type()) { + case QVariant::Double: + case QVariant::Int: + case QVariant::LongLong: + case QVariant::UInt: + case QVariant::ULongLong: + result.append(text); + break; + default: + result.append(sqlb::escapeString(text)); + } + } else { + result.append(text); + // Table cell data: text + if (text.contains('\n') || text.contains('\t')) + htmlResult.append(QString("
%1
").arg(QString(text).toHtmlEscaped())); + else + htmlResult.append(QString(text).toHtmlEscaped()); + } + } else if (inSQL) { + // Table cell data: binary in SQL. Save as BLOB literal. + result.append(QString("X'%1'").arg(QString(bArrdata.toByteArray().toHex()))); + } else if (img.loadFromData(bArrdata.toByteArray())) { + // Table cell data: image. Store it as an embedded image in HTML + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + img.save(&buffer, "PNG"); + buffer.close(); + + htmlResult.append(QString("\"Image\"") + .arg(QString(ba.toBase64()))); + result.append(index.data(Qt::DisplayRole).toByteArray()); + } + + // End of column + // Add HTML cell terminator + htmlResult.append("
"); + mimeData->setHtml(htmlResult); + } + // Single cells should only contain the value, not an ending row separator. + if (indices.size() == 1) { + result.resize(result.size() - rowSepText.size()); + } + mimeData->setText(result); + return true; +} + +void ExtendedTableWidget::copy(const bool withHeaders, const bool inSQL ) +{ + QMimeData *mimeData = new QMimeData; + copyMimeData(selectionModel()->selectedIndexes(), mimeData, withHeaders, inSQL); + qApp->clipboard()->setMimeData(mimeData); +} + +void ExtendedTableWidget::paste() +{ + // Get list of selected items + QItemSelectionModel* selection = selectionModel(); + QModelIndexList indices = selection->selectedIndexes(); + + // Abort if there's nowhere to paste + if(indices.isEmpty()) + return; + + SqliteTableModel* m = qobject_cast(model()); + + // We're also checking for system clipboard data first. Only if the data in the system clipboard is not ours, we use the system + // clipboard, otherwise we prefer the internal buffer. That's because the data in the internal buffer is easier to parse and more + // accurate, too. However, if we always preferred the internal copy-paste buffer there would be no way to copy data from other + // applications in here once the internal buffer has been filled. + + // If clipboard contains an image and no text, just insert the image + const QMimeData* mimeClipboard = qApp->clipboard()->mimeData(); + if (mimeClipboard->hasImage() && !mimeClipboard->hasText()) { + QImage img = qApp->clipboard()->image(); + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + img.save(&buffer, "PNG"); // We're always converting the image format to PNG here. TODO: Is that correct? + buffer.close(); + + m->setTypedData(indices.first(), /* isBlob = */ !isTextOnly(ba), ba); + return; + } + + // Get the clipboard text + QString clipboard = qApp->clipboard()->text(); + + // If data in system clipboard is ours and the internal copy-paste buffer is filled, use the internal buffer; otherwise parse the + // system clipboard contents (case for data copied by other application). - // Sort the items by row, then by column - qSort(indices); + std::vector clipboardTable; + std::vector* source; + + if(mimeClipboard->hasHtml() && mimeClipboard->html().contains(m_generatorStamp) && !m_buffer.empty()) + { + source = &m_buffer; + } else { + clipboardTable = parseClipboard(clipboard); + source = &clipboardTable; + } + + // Stop here if there's nothing to paste + if(!source->size()) + return; // Starting from assumption that selection is rectangular, and then first index is upper-left corner and last is lower-right. + int rows = static_cast(source->size()); + int columns = static_cast(source->front().size()); + int firstRow = indices.front().row(); - int selectedRows = indices.back().row() - firstRow + 1; int firstColumn = indices.front().column(); + int selectedRows = indices.back().row() - firstRow + 1; int selectedColumns = indices.back().column() - firstColumn + 1; + // If last row and column are after table size, clamp it + int lastRow = qMin(firstRow + rows - 1, m->rowCount() - 1); + int lastColumn = qMin(firstColumn + columns - 1, m->columnCount() - 1); - // If not selected only one cell then check does selection match cliboard dimensions - if(selectedRows != 1 || selectedColumns != 1) + // Special case: if there is only one cell of data to be pasted, paste it into all selected fields + if(rows == 1 && columns == 1) { - if(selectedRows != clipboardRows || selectedColumns != clipboardColumns) + QByteArray bArrdata = source->front().front(); + for(int row=firstRow;rowsetTypedData(m->index(row, column), !isTextOnly(bArrdata), bArrdata); } + return; } - // Here we have positive answer even if cliboard is bigger than selection + // If more than one cell was selected, check if the selection matches the cliboard dimensions + if(selectedRows != rows || selectedColumns != columns) + { + // Ask user if they are sure about this + if(QMessageBox::question(this, QApplication::applicationName(), + tr("The content of the clipboard is bigger than the range selected.\nDo you want to insert it anyway?"), + QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) + { + // If the user doesn't want to paste the clipboard data anymore, stop now + return; + } + } - SqliteTableModel* m = qobject_cast(model()); - // If last row and column are after table size clamp it - int lastRow = qMin(firstRow + clipboardRows - 1, m->rowCount() - 1); - int lastColumn = qMin(firstColumn + clipboardColumns - 1, m->columnCount() - 1); + // If we get here, we can definitely start pasting: either the ranges match in their size or the user agreed to paste anyway + // Copy the data cell by cell and as-is from the source buffer to the table int row = firstRow; - foreach(const QStringList& clipboardRow, clipboardTable) + for(const auto& source_row : *source) { int column = firstColumn; - foreach(const QString& cell, clipboardRow) + for(const QByteArray& source_cell : source_row) { - if(cell.startsWith('"') && cell.endsWith('"')) - { - QString unquatedCell = cell.mid(1, cell.length()-2); - m->setData(m->index(row, column), unquatedCell); - } - else - { - m->setData(m->index(row, column), cell); - } + m->setData(m->index(row, column), source_cell); column++; - if(column> lastColumn) - { + if (column > lastColumn) break; - } } row++; - if(row > lastRow) - { + if (row > lastRow) break; + } +} + +void ExtendedTableWidget::cut() +{ + const QModelIndexList& indices = selectionModel()->selectedIndexes(); + SqliteTableModel* m = qobject_cast(model()); + sqlb::TablePtr currentTable = m->db().getTableByName(m->currentTableName()); + + copy(false, false); + + // Check if the column in the selection has a NOT NULL constraint, then update with an empty string, else with NULL + if(currentTable) { + for(const QModelIndex& index : indices) { + // Do not process rowid column + if(index.column() != 0) { + const size_t indexField = static_cast(index.column()-1); + const sqlb::Field& field = currentTable->fields.at(indexField); + const QVariant newValue = field.notnull() ? QVariant("") : QVariant(); + // Update aborting in case of any error (to avoid repetitive errors like "Database is locked") + if(!model()->setData(index, newValue)) + return; + } } } +} + +void ExtendedTableWidget::useAsFilter(const QString& filterOperator, bool binary, const QString& operatorSuffix) +{ + QModelIndex index = selectionModel()->currentIndex(); + SqliteTableModel* m = qobject_cast(model()); + + // Abort if there's nothing to filter + if (!index.isValid() || !selectionModel()->hasSelection() || m->isBinary(index)) + return; + QVariant bArrdata = model()->data(index, Qt::EditRole); + QString value; + if (bArrdata.isNull()) + value = "NULL"; + else if (bArrdata.toString().isEmpty()) + value = "''"; + else + value = bArrdata.toString(); + + // When Containing filter is requested (empty operator) and the value starts with + // an operator character, the character is escaped. + if (filterOperator.isEmpty()) + value.replace(QRegularExpression("^(<|>|=|/)"), Settings::getValue("databrowser", "filter_escape").toString() + QString("\\1")); + + // If binary operator, the cell data is used as first value and + // the second value must be added by the user. + size_t column = static_cast(index.column()); + if (binary) + m_tableHeader->setFilter(column, value + filterOperator); + else + m_tableHeader->setFilter(column, filterOperator + value + operatorSuffix); + m_tableHeader->setFocusColumn(column); +} + +void ExtendedTableWidget::duplicateUpperCell() +{ + const QModelIndex& currentIndex = selectionModel()->currentIndex(); + QModelIndex upperIndex = currentIndex.sibling(currentIndex.row() - 1, currentIndex.column()); + if (upperIndex.isValid()) { + SqliteTableModel* m = qobject_cast(model()); + // When the data is binary, just copy it, since it cannot be edited inline. + if (m->isBinary(upperIndex)) + m->setData(currentIndex, m->data(upperIndex, Qt::EditRole), Qt::EditRole); + else { + // Open the inline editor and set the value (this mimics the behaviour of LibreOffice Calc) + edit(currentIndex); + QLineEdit* editor = qobject_cast(indexWidget(currentIndex)); + editor->setText(upperIndex.data().toString()); + } + } } void ExtendedTableWidget::keyPressEvent(QKeyEvent* event) @@ -189,33 +964,68 @@ void ExtendedTableWidget::keyPressEvent(QKeyEvent* event) // Call a custom copy method when Ctrl-C is pressed if(event->matches(QKeySequence::Copy)) { - copy(); - // Call a custom paste method when Ctrl-P is pressed - } else if(event->matches(QKeySequence::Paste)) - { + copy(false, false); + return; + } else if(event->matches(QKeySequence::Cut)) { + // Call a custom cut method when Ctrl-X is pressed + cut(); + } else if(event->matches(QKeySequence::Paste)) { + // Call a custom paste method when Ctrl-V is pressed paste(); + } else if(event->matches(QKeySequence::Print)) { + openPrintDialog(); + } else if(event->modifiers().testFlag(Qt::ControlModifier) && event->modifiers().testFlag(Qt::ShiftModifier) && (event->key() == Qt::Key_C)) { + // Call copy with headers when Ctrl-Shift-C is pressed + copy(true, false); + } else if(event->modifiers().testFlag(Qt::ControlModifier) && event->modifiers().testFlag(Qt::AltModifier) && (event->key() == Qt::Key_C)) { + // Call copy in SQL format when Ctrl-Alt-C is pressed + copy(false, true); + } else if(event->modifiers().testFlag(Qt::ControlModifier) && (event->key() == Qt::Key_Apostrophe)) { + // Call duplicateUpperCell when Ctrl-' is pressed (this is used by spreadsheets for "Copy Formula from Cell Above") + duplicateUpperCell(); } else if(event->key() == Qt::Key_Tab && hasFocus() && selectedIndexes().count() == 1 && selectedIndexes().at(0).row() == model()->rowCount()-1 && selectedIndexes().at(0).column() == model()->columnCount()-1) { // If the Tab key was pressed while the focus was on the last cell of the last row insert a new row automatically model()->insertRow(model()->rowCount()); - } else if(event->key() == Qt::Key_Delete) { - if(event->modifiers().testFlag(Qt::AltModifier)) + } else if ((event->key() == Qt::Key_Delete) || (event->key() == Qt::Key_Backspace)) { + // Check if entire rows are selected. We call the selectedRows() method here not only for simplicity reasons but also because it distinguishes between + // "an entire row is selected" and "all cells of a row are selected", the former is e.g. the case when the row number is clicked, the latter when all cells + // are selected manually. This is an important distinction (especially when a table has only one column!) to match the users' expectations. Also never + // delete records when the backspace key was pressed. + if(event->key() == Qt::Key_Delete && selectionModel()->selectedRows().size()) { - // When pressing Alt+Delete set the value to NULL - foreach(const QModelIndex& index, selectedIndexes()) - model()->setData(index, QString()); + // At least on entire row is selected. Because we don't allow completely arbitrary selections (at least at the moment) but only block selections, + // this means that only entire entire rows are selected. If an entire row is (or multiple entire rows are) selected, we delete that record instead + // of deleting only the cell contents. + + emit selectedRowsToBeDeleted(); } else { - // When pressing Delete only set the value to empty string - foreach(const QModelIndex& index, selectedIndexes()) - model()->setData(index, ""); + // No entire row is selected. So just set the selected cells to null or empty string depending on the modifier keys + + if(event->modifiers().testFlag(Qt::AltModifier)) + { + // When pressing Alt+Delete set the value to NULL + setToNull(selectedIndexes()); + } else { + // When pressing Delete only set the value to empty string + for(const QModelIndex& index : selectedIndexes()) + { + if(!model()->setData(index, "")) + return; + } + } } - } else if(event->key() == Qt::Key_Return && selectedIndexes().count() == 1 && state() != QTableView::EditingState) { - // When hitting the return key simulate a double click. This way you can change the focus to the editor dock when pressing the - // return key for advanced editing, just like a double click would open the edit dialog - emit doubleClicked(selectedIndexes().at(0)); + } else if(event->modifiers().testFlag(Qt::ControlModifier) && (event->key() == Qt::Key_PageUp || event->key() == Qt::Key_PageDown)) { + // When pressing Ctrl + Page up/down send a signal indicating the user wants to change the current table + emit switchTable(event->key() == Qt::Key_PageDown); + return; } + // Discoverability of Ctrl+Shift+Click to follow foreign keys or URLs + if(event->modifiers().testFlag(Qt::ControlModifier) && event->modifiers().testFlag(Qt::ShiftModifier)) + QApplication::setOverrideCursor(Qt::PointingHandCursor); + // This prevents the current selection from being changed when pressing tab to move to the next filter. Note that this is in an 'if' condition, // not in an 'else if' because this way, when the tab key was pressed and the focus was on the last cell, a new row is inserted and then the tab // key press is processed a second time to move the cursor as well @@ -223,18 +1033,36 @@ void ExtendedTableWidget::keyPressEvent(QKeyEvent* event) QTableView::keyPressEvent(event); } +void ExtendedTableWidget::keyReleaseEvent(QKeyEvent* event) +{ + + // Restore the PointingHandCursor override + if(!event->modifiers().testFlag(Qt::ControlModifier) || !event->modifiers().testFlag(Qt::ShiftModifier)) + QApplication::restoreOverrideCursor(); + + QTableView::keyReleaseEvent(event); +} + void ExtendedTableWidget::updateGeometries() { // Call the parent implementation first - it does most of the actual logic QTableView::updateGeometries(); + // Update frozen columns view too + if(m_frozen_table_view) + m_frozen_table_view->updateGeometries(); + // Check if a model has already been set yet if(model()) { // If so and if it is a SqliteTableModel and if the parent implementation of this method decided that a scrollbar is needed, update its maximum value SqliteTableModel* m = qobject_cast(model()); if(m && verticalScrollBar()->maximum()) - verticalScrollBar()->setMaximum(m->totalRowCount() - numVisibleRows() + 1); + { + verticalScrollBar()->setMaximum(m->rowCount() - numVisibleRows() + 1); + if(m_frozen_table_view) + m_frozen_table_view->verticalScrollBar()->setMaximum(verticalScrollBar()->maximum()); + } } } @@ -245,38 +1073,77 @@ void ExtendedTableWidget::vscrollbarChanged(int value) return; // Fetch more data from the DB if necessary - if((value + numVisibleRows()) >= model()->rowCount() && model()->canFetchMore(QModelIndex())) - model()->fetchMore(QModelIndex()); + const auto nrows = model()->rowCount(); + if(nrows == 0) + return; + + if(auto * m = dynamic_cast(model())) + { + int row_begin = std::min(value, nrows - 1); + int row_end = std::min(value + numVisibleRows(), nrows); + m->triggerCacheLoad(row_begin, row_end); + } } -int ExtendedTableWidget::numVisibleRows() +int ExtendedTableWidget::numVisibleRows() const { + if(!isVisible() || !model() || !verticalHeader()) + return 0; + // Get the row numbers of the rows currently visible at the top and the bottom of the widget - int row_top = rowAt(0) == -1 ? 0 : rowAt(0); - int row_bottom = rowAt(height()) == -1 ? model()->rowCount() : rowAt(height()); + int row_top = rowAt(0) == -1 ? 0 : verticalHeader()->visualIndexAt(0) + 1; + // Adjust the height so we don't count rows visible only less than a half of the default height + int adjusted_height = viewport()->height() - (verticalHeader()->defaultSectionSize() / 2); + int row_bottom = verticalHeader()->visualIndexAt(adjusted_height) == -1 ? model()->rowCount() : (verticalHeader()->visualIndexAt(adjusted_height) + 1); // Calculate the number of visible rows - return row_bottom - row_top; + return row_bottom - row_top + 1; } -QSet ExtendedTableWidget::selectedCols() +std::unordered_set ExtendedTableWidget::selectedCols() const { - QSet selectedCols; - foreach(const QModelIndex & idx, selectedIndexes()) - selectedCols.insert(idx.column()); + std::unordered_set selectedCols; + for(const auto& idx : selectionModel()->selectedColumns()) + selectedCols.insert(static_cast(idx.column())); return selectedCols; } +std::unordered_set ExtendedTableWidget::colsInSelection() const +{ + std::unordered_set colsInSelection; + for(const QModelIndex & idx : selectedIndexes()) + colsInSelection.insert(static_cast(idx.column())); + return colsInSelection; +} + +std::set ExtendedTableWidget::rowsInSelection() const +{ + std::set rowsInSelection; + for(const QModelIndex & idx : selectedIndexes()) + rowsInSelection.insert(static_cast(idx.row())); + return rowsInSelection; +} + void ExtendedTableWidget::cellClicked(const QModelIndex& index) { - // If Alt key is pressed try to jump to the row referenced by the foreign key of the clicked cell + // If Ctrl-Shift is pressed try to jump to the row referenced by the foreign key of the clicked cell if(qApp->keyboardModifiers().testFlag(Qt::ControlModifier) && qApp->keyboardModifiers().testFlag(Qt::ShiftModifier) && model()) { SqliteTableModel* m = qobject_cast(model()); - sqlb::ForeignKeyClause fk = m->getForeignKeyClause(index.column()-1); + auto fk = m->getForeignKeyClause(static_cast(index.column()-1)); + + if(fk) + emit foreignKeyClicked(sqlb::ObjectIdentifier(m->currentTableName().schema(), fk->table()), + fk->columns().size() ? fk->columns().at(0) : "", + m->data(index, Qt::EditRole).toByteArray()); + else { + // If this column does not have a foreign-key, try to interpret it as a filename/URL and open it in external application. - if(fk.isSet()) - emit foreignKeyClicked(fk.table(), fk.columns().size() ? fk.columns().at(0) : "", m->data(index, Qt::EditRole).toByteArray()); + // TODO: Qt is doing a contiguous selection when Control+Click is pressed. It should be disabled, but at least moving the + // current index gives better result. + setCurrentIndex(index); + emit requestUrlOrFileOpen(model()->data(index, Qt::EditRole).toString()); + } } } @@ -293,6 +1160,283 @@ void ExtendedTableWidget::dragMoveEvent(QDragMoveEvent* event) void ExtendedTableWidget::dropEvent(QDropEvent* event) { QModelIndex index = indexAt(event->pos()); + + if (!index.isValid()) + { + if (event->mimeData()->hasUrls() && event->mimeData()->urls().first().isLocalFile()) + emit openFileFromDropEvent(event->mimeData()->urls().first().toLocalFile()); + return; + } + model()->dropMimeData(event->mimeData(), Qt::CopyAction, index.row(), index.column(), QModelIndex()); event->acceptProposedAction(); } + +void ExtendedTableWidget::selectTableLine(int lineToSelect) +{ + SqliteTableModel* m = qobject_cast(model()); + + // Are there even that many lines? + if(lineToSelect >= m->rowCount()) + return; + + QApplication::setOverrideCursor( Qt::WaitCursor ); + m->triggerCacheLoad(lineToSelect); + + // Select it + clearSelection(); + selectRow(lineToSelect); + scrollTo(currentIndex(), QAbstractItemView::PositionAtTop); + QApplication::restoreOverrideCursor(); +} + +void ExtendedTableWidget::selectTableLines(int firstLine, int count) +{ + SqliteTableModel* m = qobject_cast(model()); + + int lastLine = firstLine+count-1; + // Are there even that many lines? + if(lastLine >= m->rowCount()) + return; + + selectTableLine(firstLine); + + QModelIndex topLeft = m->index(firstLine, 0); + QModelIndex bottomRight = m->index(lastLine, m->columnCount()-1); + + selectionModel()->select(QItemSelection(topLeft, bottomRight), QItemSelectionModel::Select | QItemSelectionModel::Rows); +} + +void ExtendedTableWidget::selectAll() +{ + SqliteTableModel* m = qobject_cast(model()); + + // Fetch all the data if needed and user accepts, then call parent's selectAll() + + QMessageBox::StandardButton answer = QMessageBox::Yes; + + // If we can fetch more data, ask user if they are sure about it. + if (!m->isCacheComplete()) { + + answer = QMessageBox::question(this, QApplication::applicationName(), + tr("

Not all data has been loaded. Do you want to load all data before selecting all the rows?

" + "

Answering No means that no more data will be loaded and the selection will not be performed.
" + "Answering Yes might take some time while the data is loaded but the selection will be complete.

" + "Warning: Loading all the data might require a great amount of memory for big tables."), + QMessageBox::Yes | QMessageBox::No); + + if (answer == QMessageBox::Yes) + m->completeCache(); + } + if (answer == QMessageBox::Yes) + QTableView::selectAll(); +} + +void ExtendedTableWidget::openPrintDialog() +{ + QMimeData *mimeData = new QMimeData; + QModelIndexList indices; + + // Print the selection, if active, or the entire table otherwise. + // Given that simply clicking over a cell, selects it, one-cell selections are ignored. + if (selectionModel()->hasSelection() && selectionModel()->selectedIndexes().count() > 1) + indices = selectionModel()->selectedIndexes(); + else + for (int row=0; row < model()->rowCount(); row++) + for (int column=0; column < model()->columnCount(); column++) + indices << model()->index(row, column); + + // Copy the specified indices content to mimeData for getting the HTML representation of + // the table with headers. We can then print it using an HTML text document. + bool mimeReady = copyMimeData(indices, mimeData, true, false); + if (!mimeReady) + { + delete mimeData; + return; + } + + QPrinter printer; + QPrintPreviewDialog *dialog = new QPrintPreviewDialog(&printer); + + connect(dialog, &QPrintPreviewDialog::paintRequested, this, [mimeData](QPrinter *previewPrinter) { + QTextDocument document; + document.setHtml(mimeData->html()); + document.print(previewPrinter); + }); + + dialog->exec(); + + delete dialog; + delete mimeData; +} + +void ExtendedTableWidget::sortByColumns(const std::vector& columns) +{ + // Are there even any columns to sort by? + if(columns.size() == 0) + return; + + // We only support sorting for SqliteTableModels with support for multiple and named sort columns + SqliteTableModel* sqlite_model = dynamic_cast(model()); + if(sqlite_model) + sqlite_model->sort(columns); +} + +void ExtendedTableWidget::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + QTableView::currentChanged(current, previous); + emit currentIndexChanged(current, previous); +} + +void ExtendedTableWidget::setToNull(const QModelIndexList& indices) +{ + SqliteTableModel* m = qobject_cast(model()); + sqlb::TablePtr currentTable = m->db().getTableByName(m->currentTableName()); + + // Check if some column in the selection has a NOT NULL constraint, before trying to update the cells. + if(currentTable) { + for(const QModelIndex& index : indices) { + // Do not process rowid column + if(index.column() != 0) { + const size_t indexField = static_cast(index.column()-1); + const sqlb::Field& field = currentTable->fields.at(indexField); + if(field.notnull()) { + QMessageBox::warning(nullptr, qApp->applicationName(), + tr("Cannot set selection to NULL. Column %1 has a NOT NULL constraint."). + arg(QString::fromStdString(field.name()))); + return; + } + } + } + } + for(const QModelIndex& index : indices) { + // Update aborting in case of any error (to avoid repetitive errors like "Database is locked") + if(!model()->setData(index, QVariant())) + return; + } +} + +void ExtendedTableWidget::setFrozenColumns(size_t count) +{ + if(!m_frozen_table_view) + return; + + m_frozen_column_count = count; + + // Set up frozen table view widget + m_frozen_table_view->setModel(model()); + m_frozen_table_view->setSelectionModel(selectionModel()); + for(int i=0;icolumnCount();i++) + m_frozen_table_view->setItemDelegateForColumn(i, nullptr); + m_frozen_table_view->setItemDelegateForColumn(static_cast(m_frozen_column_count-1), m_item_border_delegate); + + // Only show frozen columns in extra table view and copy column widths + m_frozen_table_view->horizontalHeader()->blockSignals(true); // Signals need to be blocked because hiding a column would emit resizedSection + for(size_t col=0;col(model()->columnCount());++col) + m_frozen_table_view->setColumnHidden(static_cast(col), col >= count); + m_frozen_table_view->horizontalHeader()->blockSignals(false); + for(int col=0;col(count);++col) + m_frozen_table_view->setColumnWidth(col, columnWidth(col)); + + updateFrozenTableGeometry(); + + // Only show extra table view when there are frozen columns to see + if(count) + m_frozen_table_view->show(); + else + m_frozen_table_view->hide(); +} + +void ExtendedTableWidget::generateFilters(size_t number, bool show_rowid) +{ + m_tableHeader->generateFilters(number, m_frozen_column_count); + + if(m_frozen_table_view) + { + size_t frozen_columns = std::min(m_frozen_column_count, number); + m_frozen_table_view->m_tableHeader->generateFilters(frozen_columns, show_rowid ? 0 : 1); + } +} + +void ExtendedTableWidget::updateSectionWidth(int logicalIndex, int /* oldSize */, int newSize) +{ + if(!m_frozen_table_view) + return; + + if(logicalIndex < static_cast(m_frozen_column_count)) + { + m_frozen_table_view->setColumnWidth(logicalIndex, newSize); + setColumnWidth(logicalIndex, newSize); + updateFrozenTableGeometry(); + } +} + +void ExtendedTableWidget::updateSectionHeight(int logicalIndex, int /* oldSize */, int newSize) +{ + if(!m_frozen_table_view) + return; + + m_frozen_table_view->setRowHeight(logicalIndex, newSize); +} + +void ExtendedTableWidget::resizeEvent(QResizeEvent* event) +{ + QTableView::resizeEvent(event); + updateFrozenTableGeometry(); +} + +QModelIndex ExtendedTableWidget::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) +{ + QModelIndex current = QTableView::moveCursor(cursorAction, modifiers); + if(!m_frozen_table_view) + return current; + + int width = 0; + for(int i=0;i(m_frozen_column_count);i++) + width += m_frozen_table_view->columnWidth(i); + + if(cursorAction == MoveLeft && current.column() > 0 && visualRect(current).topLeft().x() < width) + { + const int newValue = horizontalScrollBar()->value() + visualRect(current).topLeft().x() - width; + horizontalScrollBar()->setValue(newValue); + } + return current; +} + +void ExtendedTableWidget::scrollTo(const QModelIndex& index, ScrollHint hint) +{ + if(index.column() >= static_cast(m_frozen_column_count)) + QTableView::scrollTo(index, hint); +} + +void ExtendedTableWidget::updateFrozenTableGeometry() +{ + if(!m_frozen_table_view) + return; + + int width = 0; + for(int i=0;i(m_frozen_column_count);i++) + { + if(!isColumnHidden(i)) + width += columnWidth(i); + } + + m_frozen_table_view->setGeometry(verticalHeader()->width() + frameWidth(), + frameWidth(), + width, + viewport()->height() + horizontalHeader()->height()); +} + +void ExtendedTableWidget::setEditTriggers(QAbstractItemView::EditTriggers editTriggers) +{ + QTableView::setEditTriggers(editTriggers); + if(m_frozen_table_view) + m_frozen_table_view->setEditTriggers(editTriggers); +} + +void ExtendedTableWidget::setFilter(size_t column, const QString& value) +{ + filterHeader()->setFilter(column, value); + if(m_frozen_table_view) + m_frozen_table_view->filterHeader()->setFilter(column, value); +} diff --git a/src/ExtendedTableWidget.h b/src/ExtendedTableWidget.h index 0734978be..9c4469e16 100644 --- a/src/ExtendedTableWidget.h +++ b/src/ExtendedTableWidget.h @@ -1,44 +1,173 @@ #ifndef EXTENDEDTABLEWIDGET_H #define EXTENDEDTABLEWIDGET_H +#include +#include +#include +#include #include -#include "FilterTableHeader.h" -#include -#include -#include +#include +#include +#include +#include + +#include "sql/Query.h" + +class QMenu; +class QMimeData; +class QDropEvent; +class QDragMoveEvent; + +class FilterTableHeader; +class ItemBorderDelegate; +namespace sqlb { class ObjectIdentifier; } + +// Filter proxy model that only accepts distinct non-empty values. +class UniqueFilterModel : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + explicit UniqueFilterModel(QObject* parent = nullptr); + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + private: + std::unordered_set m_uniqueValues; +}; + +// Handler for pressing the tab key when the autocomplete popup is open, closing the popup and moving the cursor to the next item. +class CompleterTabKeyPressedEventFilter : public QObject +{ + Q_OBJECT + +public: + CompleterTabKeyPressedEventFilter(QObject* parent = nullptr) : QObject(parent) {} + +protected: + bool eventFilter(QObject* obj, QEvent* event) override { + if (event->type() == QEvent::KeyPress) { + QKeyEvent* keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Tab) { + QCompleter* completer = qobject_cast(this->parent()); + if (completer) { + completer->popup()->hide(); + QWidget* editor = completer->widget(); + if (editor) { + QKeyEvent tabEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier); + QApplication::sendEvent(editor, &tabEvent); + } + } + return true; + } + } + return QObject::eventFilter(obj, event); + } +}; + +// We use this class to provide editor widgets for the ExtendedTableWidget. It's used for every cell in the table view. +class ExtendedTableWidgetEditorDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + explicit ExtendedTableWidgetEditorDelegate(QObject* parent = nullptr); + + QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + void setEditorData(QWidget* editor, const QModelIndex& index) const override; + void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override; + void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + +signals: + void dataAboutToBeEdited(QModelIndex index) const; +}; class ExtendedTableWidget : public QTableView { Q_OBJECT public: - explicit ExtendedTableWidget(QWidget* parent = 0); + explicit ExtendedTableWidget(QWidget* parent = nullptr); + ~ExtendedTableWidget() override; FilterTableHeader* filterHeader() { return m_tableHeader; } + void generateFilters(size_t number, bool show_rowid); public: - QSet selectedCols(); + // Get set of selected columns (all cells in column has to be selected) + std::unordered_set selectedCols() const; + // Get set of columns traversed by selection (only some cells in column have to be selected) + std::unordered_set colsInSelection() const; + // Get set of ordered rows traversed by selection (only some cells in row have to be selected) + std::set rowsInSelection() const; + + int numVisibleRows() const; + + void sortByColumns(const std::vector& columns); + + void setFrozenColumns(size_t count); + + void setModel(QAbstractItemModel* item_model) override; + + void setEditTriggers(QAbstractItemView::EditTriggers editTriggers); + +public slots: + void reloadSettings(); + void selectTableLine(int lineToSelect); + void selectTableLines(int firstLine, int count); + void selectAll() override; + void openPrintDialog(); + void setFilter(size_t column, const QString& value); signals: - void foreignKeyClicked(const QString& table, const QString& column, const QByteArray& value); + void foreignKeyClicked(const sqlb::ObjectIdentifier& table, const std::string& column, const QByteArray& value); + void switchTable(bool next); // 'next' parameter is set to true if next table should be selected and to false if previous table should be selected + void openFileFromDropEvent(QString); + void selectedRowsToBeDeleted(); + void editCondFormats(int column); + void currentIndexChanged(const QModelIndex ¤t, const QModelIndex &previous); + void dataAboutToBeEdited(const QModelIndex& index); + void requestUrlOrFileOpen(const QString& urlString); private: - void copy(); + bool copyMimeData(const QModelIndexList& fromIndices, QMimeData* mimeData, const bool withHeaders, const bool inSQL); + void copy(const bool withHeaders, const bool inSQL); void paste(); - int numVisibleRows(); + void cut(); + + void useAsFilter(const QString& filterOperator, bool binary = false, const QString& operatorSuffix = QString()); + void duplicateUpperCell(); + + void setToNull(const QModelIndexList& indices); + + static std::vector> m_buffer; + static QString m_generatorStamp; + + ExtendedTableWidget* m_frozen_table_view; + size_t m_frozen_column_count; + ItemBorderDelegate* m_item_border_delegate; + void updateFrozenTableGeometry(); private slots: void vscrollbarChanged(int value); void cellClicked(const QModelIndex& index); + void updateSectionWidth(int logicalIndex, int oldSize, int newSize); + void updateSectionHeight(int logicalIndex, int oldSize, int newSize); protected: - virtual void keyPressEvent(QKeyEvent* event); - virtual void updateGeometries(); - virtual void dragEnterEvent(QDragEnterEvent* event); - virtual void dragMoveEvent(QDragMoveEvent* event); - virtual void dropEvent(QDropEvent* event); + void keyPressEvent(QKeyEvent* event) override; + void keyReleaseEvent(QKeyEvent* event) override; + void updateGeometries() override; + void dragEnterEvent(QDragEnterEvent* event) override; + void dragMoveEvent(QDragMoveEvent* event) override; + void dropEvent(QDropEvent* event) override; + void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) override; + + void resizeEvent(QResizeEvent* event) override; + QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override; + void scrollTo(const QModelIndex& index, ScrollHint hint = EnsureVisible) override; FilterTableHeader* m_tableHeader; + QMenu* m_contextMenu; + ExtendedTableWidgetEditorDelegate* m_editorDelegate; }; #endif diff --git a/src/FileDialog.cpp b/src/FileDialog.cpp index 56aa8e3b1..ed22c202b 100644 --- a/src/FileDialog.cpp +++ b/src/FileDialog.cpp @@ -1,61 +1,83 @@ #include "FileDialog.h" -#include "PreferencesDialog.h" +#include "Settings.h" -QString FileDialog::getOpenFileName(QWidget* parent, const QString& caption, const QString &filter, QString *selectedFilter, Options options) +QString FileDialog::getOpenFileName(const FileDialogTypes dialogType, QWidget* parent, const QString& caption, const QString &filter, QString *selectedFilter, Options options) { - QString result = QFileDialog::getOpenFileName(parent, caption, getFileDialogPath(), filter, selectedFilter, options); + QString result = QFileDialog::getOpenFileName(parent, caption, getFileDialogPath(dialogType), filter, selectedFilter, options); if(!result.isEmpty()) - setFileDialogPath(result); + setFileDialogPath(dialogType, result); return result; } -QString FileDialog::getSaveFileName(QWidget* parent, const QString& caption, const QString& filter, const QString& defaultFileName, QString* selectedFilter, Options options) +QStringList FileDialog::getOpenFileNames(const FileDialogTypes dialogType, QWidget *parent, const QString &caption, const QString &filter, QString *selectedFilter, QFileDialog::Options options) { - QString dir = getFileDialogPath(); + QStringList result = QFileDialog::getOpenFileNames(parent, caption, getFileDialogPath(dialogType), filter, selectedFilter, options); + if(!result.isEmpty()) + { + QFileInfo path = QFileInfo(result.first()); + setFileDialogPath(dialogType, path.absoluteFilePath()); + } + return result; +} + +QString FileDialog::getSaveFileName(const FileDialogTypes dialogType, QWidget* parent, const QString& caption, const QString& filter, const QString& defaultFileName, QString* selectedFilter, Options options) +{ + QString dir = getFileDialogPath(dialogType); if(!defaultFileName.isEmpty()) dir += "/" + defaultFileName; - QString result = QFileDialog::getSaveFileName(parent, caption, defaultFileName, filter, selectedFilter, options); + QString result = QFileDialog::getSaveFileName(parent, caption, dir, filter, selectedFilter, options); if(!result.isEmpty()) - setFileDialogPath(result); + setFileDialogPath(dialogType, result); return result; } -QString FileDialog::getExistingDirectory(QWidget* parent, const QString& caption, Options options) +QString FileDialog::getExistingDirectory(const FileDialogTypes dialogType, QWidget* parent, const QString& caption, Options options) { - QString result = QFileDialog::getExistingDirectory(parent, caption, getFileDialogPath(), options); + QString result = QFileDialog::getExistingDirectory(parent, caption, getFileDialogPath(dialogType), options); if(!result.isEmpty()) - setFileDialogPath(result); + setFileDialogPath(dialogType, result); return result; } -QString FileDialog::getFileDialogPath() +QString FileDialog::getFileDialogPath(const FileDialogTypes dialogType) { - switch(PreferencesDialog::getSettingsValue("db", "savedefaultlocation").toInt()) + switch(Settings::getValue("db", "savedefaultlocation").toInt()) { case 0: // Remember last location - case 2: // Remember last location for current session only - return PreferencesDialog::getSettingsValue("db", "lastlocation").toString(); - case 1: // Always use this locations - return PreferencesDialog::getSettingsValue("db", "defaultlocation").toString(); + case 2: { // Remember last location for current session only + QHash lastLocations = Settings::getValue("db", "lastlocations").toHash(); + + return lastLocations[QString::number(static_cast(dialogType))].toString(); + } + case 1: // Always use this location + return Settings::getValue("db", "defaultlocation").toString(); default: - return ""; + return QString(); } } -void FileDialog::setFileDialogPath(const QString& new_path) +void FileDialog::setFileDialogPath(const FileDialogTypes dialogType, const QString& new_path) { QString dir = QFileInfo(new_path).absolutePath(); + QHash lastLocations = Settings::getValue("db", "lastlocations").toHash(); + + lastLocations[QString::number(static_cast(dialogType))] = dir; - switch(PreferencesDialog::getSettingsValue("db", "savedefaultlocation").toInt()) + switch(Settings::getValue("db", "savedefaultlocation").toInt()) { case 0: // Remember last location - PreferencesDialog::setSettingsValue("db", "lastlocation", dir); + Settings::setValue("db", "lastlocations", lastLocations); break; case 2: // Remember last location for current session only - PreferencesDialog::setSettingsValue("db", "lastlocation", dir, true); + Settings::setValue("db", "lastlocations", lastLocations, false); break; case 1: // Always use this locations break; // Do nothing } } + +QString FileDialog::getSqlDatabaseFileFilter() +{ + return Settings::getValue("General", "DBFileExtensions").toString() + ";;" + QObject::tr("All files (*)"); //Always add "All files (*)" to the available filters +} diff --git a/src/FileDialog.h b/src/FileDialog.h index 0e98ab637..3c678ec2b 100644 --- a/src/FileDialog.h +++ b/src/FileDialog.h @@ -3,26 +3,108 @@ #include +// +// File Extensions Filters +// - space separated list of file extensions in QString +// - used during import/export +// - passed to QFileDialog to filter files shown based on extension +// +// SQLite DB File Extensions +static const QString FILE_FILTER_SQLDB(QObject::tr("SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3)")); + +// SQLite DB Project File Extensions +static const QString FILE_FILTER_SQLPRJ(QObject::tr("DB Browser for SQLite Project Files (*.sqbpro)")); +static const QString FILE_EXT_SQLPRJ_DEFAULT(".sqbpro"); + +// SQL File Extensions Filter +static const QString FILE_FILTER_SQL(QObject::tr("SQL Files (*.sql)")); +static const QString FILE_EXT_SQL_DEFAULT(".sql"); + +// All Files Extensions Filter +static const QString FILE_FILTER_ALL(QObject::tr("All Files (*)")); + +// Text Files Extensions Filter +static const QString FILE_FILTER_TXT(QObject::tr("Text Files (*.txt)")); +static const QString FILE_EXT_TXT_DEFAULT(".txt"); + +// Comma,Tab,or Delimiter-Separated Values File Extensions Filter +static const QString FILE_FILTER_CSV(QObject::tr("Comma-Separated Values Files (*.csv)")); +static const QString FILE_EXT_CSV_DEFAULT(".csv"); +static const QString FILE_FILTER_TSV(QObject::tr("Tab-Separated Values Files (*.tsv)")); +static const QString FILE_FILTER_DSV(QObject::tr("Delimiter-Separated Values Files (*.dsv)")); +static const QString FILE_FILTER_DAT(QObject::tr("Concordance DAT files (*.dat)")); + +// JSON File Extensions Filter +static const QString FILE_FILTER_JSON(QObject::tr("JSON Files (*.json *.js)")); +static const QString FILE_EXT_JSON_DEFAULT(".json"); + +// XML File Extensions Filter +static const QString FILE_FILTER_XML(QObject::tr("XML Files (*.xml)")); +static const QString FILE_EXT_XML_DEFAULT(".xml"); + +// Binary File Extensions Filter +static const QString FILE_FILTER_BIN(QObject::tr("Binary Files (*.bin *.dat)")); +static const QString FILE_EXT_BIN_DEFAULT(".bin"); + +// Scalar Vector Graphics File Extensions Filter +static const QString FILE_FILTER_SVG(QObject::tr("SVG Files (*.svg)")); +static const QString FILE_EXT_SVG_DEFAULT(".svg"); + +// Hex-Dump File Extension Filter +static const QString FILE_FILTER_HEX(QObject::tr("Hex Dump Files (*.dat *.bin)")); + +// Dynamic/Shared Objects File Extension Filter +static const QString FILE_FILTER_DYN(QObject::tr("Extensions (*.so *.dylib *.dll)")); + +// Initialization File Extension Filter +static const QString FILE_FILTER_INI(QObject::tr("Initialization File (*.ini)")); + +enum FileDialogTypes { + NoSpecificType, + + CreateProjectFile, + OpenProjectFile, + + CreateDatabaseFile, + OpenDatabaseFile, + + CreateSQLFile, + OpenSQLFile, + + OpenCSVFile, + + CreateDataFile, + OpenDataFile, + + OpenExtensionFile, + OpenCertificateFile, + + CreateSettingsFile, + OpenSettingsFile +}; + class FileDialog : public QFileDialog { + Q_OBJECT + public: - static QString getOpenFileName(QWidget* parent = 0, const QString& caption = QString(), - const QString& filter = QString(), QString* selectedFilter = 0, - Options options = 0); - static QString getSaveFileName(QWidget* parent = 0, const QString& caption = QString(), - const QString& filter = QString(), const QString& defaultFileName = QString(), QString* selectedFilter = 0, - Options options = 0); - static QString getExistingDirectory(QWidget* parent = 0, const QString& caption = QString(), - Options options = 0); - - static QString getSqlDatabaseFileFilter() - { - return tr("SQLite database files (*.db *.sqlite *.sqlite3 *.db3);;All files (*)"); - } + static QString getOpenFileName(const FileDialogTypes dialogType, QWidget* parent = nullptr, const QString& caption = QString(), + const QString& filter = QString(), QString* selectedFilter = nullptr, + Options options = Options()); + static QStringList getOpenFileNames(const FileDialogTypes dialogType, QWidget* parent = nullptr, const QString& caption = QString(), + const QString& filter = QString(), QString* selectedFilter = nullptr, + Options options = Options()); + static QString getSaveFileName(const FileDialogTypes dialogType, QWidget* parent = nullptr, const QString& caption = QString(), + const QString& filter = QString(), const QString& defaultFileName = QString(), QString* selectedFilter = nullptr, + Options options = Options()); + static QString getExistingDirectory(const FileDialogTypes dialogType, QWidget* parent = nullptr, const QString& caption = QString(), + Options options = Options()); + + static QString getSqlDatabaseFileFilter(); private: - static QString getFileDialogPath(); - static void setFileDialogPath(const QString& new_path); + static QString getFileDialogPath(const FileDialogTypes dialogType); + static void setFileDialogPath(const FileDialogTypes dialogType, const QString& new_path); }; #endif diff --git a/src/FileExtensionManager.cpp b/src/FileExtensionManager.cpp new file mode 100644 index 000000000..71ce8ebae --- /dev/null +++ b/src/FileExtensionManager.cpp @@ -0,0 +1,104 @@ +#include "FileExtensionManager.h" +#include "ui_FileExtensionManager.h" + +#include + +FileExtensionManager::FileExtensionManager(QStringList init, QWidget *parent) : + QDialog(parent), + ui(new Ui::FileExtensionManager) +{ + ui->setupUi(this); + + int i = 0; + for(const QString& itemString : init) + { + QString description = itemString.left(itemString.indexOf('(')).trimmed(); + QString extension = itemString; + extension = extension.remove (0, itemString.indexOf('(')+1).remove(')').simplified().trimmed(); + + QTableWidgetItem *newItemDescription = new QTableWidgetItem(description); + QTableWidgetItem *newItemExtension = new QTableWidgetItem(extension); + ui->tableExtensions->insertRow(i); + ui->tableExtensions->setItem(i, 0, newItemDescription); + ui->tableExtensions->setItem(i, 1, newItemExtension); + i++; + } + + connect(ui->buttonAdd, SIGNAL(clicked(bool)), this, SLOT(addItem())); + connect(ui->buttonRemove, SIGNAL(clicked(bool)), this, SLOT(removeItem())); + + connect(ui->buttonDown, SIGNAL(clicked(bool)), this, SLOT(downItem())); + connect(ui->buttonUp, SIGNAL(clicked(bool)), this, SLOT(upItem())); +} + +FileExtensionManager::~FileExtensionManager() +{ + delete ui; +} + +void FileExtensionManager::addItem() +{ + int i = ui->tableExtensions->rowCount(); + ui->tableExtensions->insertRow(i); + QTableWidgetItem *newItemDescription = new QTableWidgetItem(tr("Description")); + QTableWidgetItem *newItemExtension = new QTableWidgetItem(tr("*.extension")); + ui->tableExtensions->setItem(i, 0, newItemDescription); + ui->tableExtensions->setItem(i, 1, newItemExtension); +} + +void FileExtensionManager::removeItem() +{ + std::set selectedRows; + for (const QTableWidgetItem* item : ui->tableExtensions->selectedItems()) + selectedRows.insert(item->row()); + + for(int row : selectedRows) + ui->tableExtensions->removeRow(row); +} + +void FileExtensionManager::upItem() +{ + if (ui->tableExtensions->selectedItems().isEmpty()) return; + + int selectedRow = ui->tableExtensions->selectedItems().first()->row(); + if(selectedRow == 0) + return; + + QTableWidgetItem *t1, *t2; + t1 = ui->tableExtensions->takeItem(selectedRow, 0); + t2 = ui->tableExtensions->takeItem(selectedRow, 1); + ui->tableExtensions->removeRow(selectedRow); + ui->tableExtensions->insertRow(selectedRow-1); + ui->tableExtensions->setItem(selectedRow-1, 0, t1); + ui->tableExtensions->setItem(selectedRow-1, 1, t2); + ui->tableExtensions->selectRow(selectedRow-1); +} + +void FileExtensionManager::downItem() +{ + if (ui->tableExtensions->selectedItems().isEmpty()) return; + + int selectedRow = ui->tableExtensions->selectedItems().first()->row(); + if(selectedRow == ui->tableExtensions->rowCount() - 1) + return; + + QTableWidgetItem *t1, *t2; + t1 = ui->tableExtensions->takeItem(selectedRow, 0); + t2 = ui->tableExtensions->takeItem(selectedRow, 1); + ui->tableExtensions->removeRow(selectedRow); + ui->tableExtensions->insertRow(selectedRow+1); + ui->tableExtensions->setItem(selectedRow+1, 0, t1); + ui->tableExtensions->setItem(selectedRow+1, 1, t2); + ui->tableExtensions->selectRow(selectedRow+1); +} + +QStringList FileExtensionManager::getDBFileExtensions() const +{ + QStringList result; + for (int i = 0; i < ui->tableExtensions->rowCount(); ++i) + { + result.append(QString("%1 (%2)").arg(ui->tableExtensions->item(i, 0)->text(), ui->tableExtensions->item(i, 1)->text())); + } + return result; +} + diff --git a/src/FileExtensionManager.h b/src/FileExtensionManager.h new file mode 100644 index 000000000..7e0156e32 --- /dev/null +++ b/src/FileExtensionManager.h @@ -0,0 +1,30 @@ +#ifndef FILEEXTENSIONMANAGER_H +#define FILEEXTENSIONMANAGER_H + +#include + +namespace Ui { +class FileExtensionManager; +} + +class FileExtensionManager : public QDialog +{ + Q_OBJECT + +public: + explicit FileExtensionManager(QStringList init, QWidget *parent = nullptr); + ~FileExtensionManager() override; + + QStringList getDBFileExtensions() const; + +private: + Ui::FileExtensionManager *ui; + +public slots: + void addItem(); + void removeItem(); + void upItem(); + void downItem(); +}; + +#endif // FILEEXTENSIONMANAGER_H diff --git a/src/FileExtensionManager.ui b/src/FileExtensionManager.ui new file mode 100644 index 000000000..691d5b5fd --- /dev/null +++ b/src/FileExtensionManager.ui @@ -0,0 +1,153 @@ + + + FileExtensionManager + + + + 0 + 0 + 578 + 463 + + + + File Extension Manager + + + + + + + + &Up + + + + :/icons/up:/icons/up + + + + + + + &Down + + + + :/icons/down:/icons/down + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + &Add + + + + :/icons/field_add:/icons/field_add + + + + + + + &Remove + + + + :/icons/field_delete:/icons/field_delete + + + + + + + + + QAbstractScrollArea::AdjustToContents + + + true + + + 100 + + + 100 + + + + Description + + + + + Extensions + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + FileExtensionManager + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + FileExtensionManager + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/FilterLineEdit.cpp b/src/FilterLineEdit.cpp index bfdc277fe..661570625 100644 --- a/src/FilterLineEdit.cpp +++ b/src/FilterLineEdit.cpp @@ -1,16 +1,22 @@ #include "FilterLineEdit.h" -#include "PreferencesDialog.h" +#include "Settings.h" #include #include +#include +#include +#include +#include -FilterLineEdit::FilterLineEdit(QWidget* parent, QList* filters, int columnnum) : QLineEdit(parent), filterList(filters), columnNumber(columnnum) +FilterLineEdit::FilterLineEdit(QWidget* parent, std::vector* filters, size_t columnnum) : + QLineEdit(parent), + filterList(filters), + columnNumber(columnnum), + conditional_format(true) { setPlaceholderText(tr("Filter")); -#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) setClearButtonEnabled(true); -#endif - setProperty("column", columnnum); // Store the column number for later use + setProperty("column", static_cast(columnnum)); // Store the column number for later use // Introduce a timer for delaying the signal triggered whenever the user changes the filter value. // The idea here is that the textChanged() event isn't connected to the update filter slot directly anymore @@ -18,13 +24,30 @@ FilterLineEdit::FilterLineEdit(QWidget* parent, QList* filters, // is (re)started. As soon as the user stops typing the timer has a chance to trigger and call the // delayedSignalTimerTriggered() method which then stops the timer and emits the delayed signal. delaySignalTimer = new QTimer(this); - delaySignalTimer->setInterval(PreferencesDialog::getSettingsValue("databrowser", "filter_delay").toInt()); // This is the milliseconds of not-typing we want to wait before triggering - connect(this, SIGNAL(textChanged(QString)), delaySignalTimer, SLOT(start())); - connect(delaySignalTimer, SIGNAL(timeout()), this, SLOT(delayedSignalTimerTriggered())); + delaySignalTimer->setInterval(Settings::getValue("databrowser", "filter_delay").toInt()); // This is the milliseconds of not-typing we want to wait before triggering + connect(this, &FilterLineEdit::textChanged, delaySignalTimer, static_cast(&QTimer::start)); + connect(delaySignalTimer, &QTimer::timeout, this, &FilterLineEdit::delayedSignalTimerTriggered); + + setWhatsThis(tr("These input fields allow you to perform quick filters in the currently selected table.\n" + "By default, the rows containing the input text are filtered out.\n" + "The following operators are also supported:\n" + "%\tWildcard\n" + ">\tGreater than\n" + "<\tLess than\n" + ">=\tEqual to or greater\n" + "<=\tEqual to or less\n" + "=\tEqual to: exact match\n" + "<>\tUnequal: exact inverse match\n" + "x~y\tRange: values between x and y\n" + "/regexp/\tValues matching the regular expression")); // Immediately emit the delayed filter value changed signal if the user presses the enter or the return key or // the line edit widget loses focus - connect(this, SIGNAL(editingFinished()), this, SLOT(delayedSignalTimerTriggered())); + connect(this, &FilterLineEdit::editingFinished, this, &FilterLineEdit::delayedSignalTimerTriggered); + + // Prepare for adding the What's This information and filter helper actions to the context menu + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, &FilterLineEdit::customContextMenuRequested, this, &FilterLineEdit::showContextMenu); } void FilterLineEdit::delayedSignalTimerTriggered() @@ -32,31 +55,55 @@ void FilterLineEdit::delayedSignalTimerTriggered() // Stop the timer first to avoid triggering in intervals delaySignalTimer->stop(); - // Emit the delayed signal using the current value - emit delayedTextChanged(text()); + // Only emit text changed signal if the text has actually changed in comparison to the last emitted signal. This is necessary + // because this method is also called whenever the line edit loses focus and not only when its text has definitely been changed. + if(text() != lastValue) + { + // Emit the delayed signal using the current value + emit delayedTextChanged(text()); + + // Remember this value for the next time + lastValue = text(); + } } void FilterLineEdit::keyReleaseEvent(QKeyEvent* event) { + bool actedUponKey = false; if(event->key() == Qt::Key_Tab) { - if(columnNumber < filterList->size() - 1) + if(filterList && columnNumber < filterList->size() - 1) { filterList->at(columnNumber + 1)->setFocus(); - event->accept(); + } else { + QWidget* grandParent = parentWidget()->parentWidget(); + // Pass focus to the table (grandparent). + // Parent would be the table header, which would cycle back to the first + // column (due to proxying). + if(grandParent) + grandParent->setFocus(); } + actedUponKey = true; } else if(event->key() == Qt::Key_Backtab) { - if(columnNumber > 0) + if(filterList && columnNumber > 0) { filterList->at(columnNumber - 1)->setFocus(); - event->accept(); + actedUponKey = true; } } + if(!actedUponKey) + QLineEdit::keyReleaseEvent(event); +} + +void FilterLineEdit::focusInEvent(QFocusEvent* event) +{ + QLineEdit::focusInEvent(event); + emit filterFocused(); } void FilterLineEdit::clear() { - // When programatically clearing the line edit's value make sure the effects are applied immediately, i.e. + // When programmatically clearing the line edit's value make sure the effects are applied immediately, i.e. // bypass the delayed signal timer QLineEdit::clear(); delayedSignalTimerTriggered(); @@ -64,8 +111,133 @@ void FilterLineEdit::clear() void FilterLineEdit::setText(const QString& text) { - // When programatically setting the line edit's value make sure the effects are applied immediately, i.e. + // When programmatically setting the line edit's value make sure the effects are applied immediately, i.e. // bypass the delayed signal timer QLineEdit::setText(text); delayedSignalTimerTriggered(); } + +void FilterLineEdit::setFilterHelper(const QString& filterOperator, const QString& operatorSuffix) +{ + setText(filterOperator + "?" + operatorSuffix); + // Select the value for easy editing of the expression + setSelection(filterOperator.length(), 1); +} + +void FilterLineEdit::showContextMenu(const QPoint &pos) +{ + + // This has to be created here, otherwise the set of enabled options would not update accordingly. + QMenu* editContextMenu = createStandardContextMenu(); + editContextMenu->addSeparator(); + + QMenu* filterMenu = editContextMenu->addMenu(tr("Set Filter Expression")); + + QAction* whatsThisAction = new QAction(QIcon(":/icons/whatis"), tr("What's This?"), editContextMenu); + connect(whatsThisAction, &QAction::triggered, this, [&]() { + QDesktopServices::openUrl(QUrl("https://github.com/sqlitebrowser/sqlitebrowser/wiki/Using-the-Filters")); + QWhatsThis::showText(pos, whatsThis(), this); + }); + + QAction* isNullAction = new QAction(tr("Is NULL"), editContextMenu); + connect(isNullAction, &QAction::triggered, this, [&]() { + setText("=NULL"); + }); + + QAction* isNotNullAction = new QAction(tr("Is not NULL"), editContextMenu); + connect(isNotNullAction, &QAction::triggered, this, [&]() { + setText("<>NULL"); + }); + + QAction* isEmptyAction = new QAction(tr("Is empty"), editContextMenu); + connect(isEmptyAction, &QAction::triggered, this, [&]() { + setText("=''"); + }); + + QAction* isNotEmptyAction = new QAction(tr("Is not empty"), editContextMenu); + connect(isNotEmptyAction, &QAction::triggered, this, [&]() { + setText("<>''"); + }); + // Simplify this if we ever support a NOT LIKE filter + QAction* notContainingAction = new QAction(tr("Not containing..."), editContextMenu); + connect(notContainingAction, &QAction::triggered, this, [&]() { + setFilterHelper(QString ("/^((?!"), QString(").)*$/")); + }); + QAction* equalToAction = new QAction(tr("Equal to..."), editContextMenu); + connect(equalToAction, &QAction::triggered, this, [&]() { + setFilterHelper(QString ("=")); + }); + QAction* notEqualToAction = new QAction(tr("Not equal to..."), editContextMenu); + connect(notEqualToAction, &QAction::triggered, this, [&]() { + setFilterHelper(QString ("<>")); + }); + QAction* greaterThanAction = new QAction(tr("Greater than..."), editContextMenu); + connect(greaterThanAction, &QAction::triggered, this, [&]() { + setFilterHelper(QString (">")); + }); + QAction* lessThanAction = new QAction(tr("Less than..."), editContextMenu); + connect(lessThanAction, &QAction::triggered, this, [&]() { + setFilterHelper(QString ("<")); + }); + QAction* greaterEqualAction = new QAction(tr("Greater or equal..."), editContextMenu); + connect(greaterEqualAction, &QAction::triggered, this, [&]() { + setFilterHelper(QString (">=")); + }); + QAction* lessEqualAction = new QAction(tr("Less or equal..."), editContextMenu); + connect(lessEqualAction, &QAction::triggered, this, [&]() { + setFilterHelper(QString ("<=")); + }); + QAction* inRangeAction = new QAction(tr("In range..."), editContextMenu); + connect(inRangeAction, &QAction::triggered, this, [&]() { + setFilterHelper(QString ("?~")); + }); + + QAction* regexpAction = new QAction(tr("Regular expression..."), editContextMenu); + connect(regexpAction, &QAction::triggered, this, [&]() { + setFilterHelper(QString ("/"), QString ("/")); + }); + + + if(conditional_format) + { + QAction* conditionalFormatAction; + if (text().isEmpty()) { + conditionalFormatAction = new QAction(QIcon(":/icons/clear_cond_formats"), tr("Clear All Conditional Formats"), editContextMenu); + connect(conditionalFormatAction, &QAction::triggered, this, [&]() { + emit clearAllCondFormats(); + }); + } else { + conditionalFormatAction = new QAction(QIcon(":/icons/add_cond_format"), tr("Use for Conditional Format"), editContextMenu); + connect(conditionalFormatAction, &QAction::triggered, this, [&]() { + emit addFilterAsCondFormat(text()); + }); + } + QAction* editCondFormatsAction = new QAction(QIcon(":/icons/edit_cond_formats"), tr("Edit Conditional Formats..."), editContextMenu); + connect(editCondFormatsAction, &QAction::triggered, this, [&]() { + emit editCondFormats(); + }); + editContextMenu->addSeparator(); + + editContextMenu->addAction(conditionalFormatAction); + editContextMenu->addAction(editCondFormatsAction); + } + + + filterMenu->addAction(whatsThisAction); + filterMenu->addSeparator(); + filterMenu->addAction(isNullAction); + filterMenu->addAction(isNotNullAction); + filterMenu->addAction(isEmptyAction); + filterMenu->addAction(isNotEmptyAction); + filterMenu->addSeparator(); + filterMenu->addAction(notContainingAction); + filterMenu->addAction(equalToAction); + filterMenu->addAction(notEqualToAction); + filterMenu->addAction(greaterThanAction); + filterMenu->addAction(lessThanAction); + filterMenu->addAction(greaterEqualAction); + filterMenu->addAction(lessEqualAction); + filterMenu->addAction(inRangeAction); + filterMenu->addAction(regexpAction); + editContextMenu->exec(mapToGlobal(pos)); +} diff --git a/src/FilterLineEdit.h b/src/FilterLineEdit.h index b1d9fe130..688b2ddd1 100644 --- a/src/FilterLineEdit.h +++ b/src/FilterLineEdit.h @@ -2,7 +2,7 @@ #define FILTERLINEEDIT_H #include -#include +#include class QTimer; class QKeyEvent; @@ -12,25 +12,38 @@ class FilterLineEdit : public QLineEdit Q_OBJECT public: - explicit FilterLineEdit(QWidget* parent, QList* filters, int columnnum); + explicit FilterLineEdit(QWidget* parent, std::vector* filters = nullptr, size_t columnnum = 0); - // Override methods for programatically changing the value of the line edit + // Override methods for programmatically changing the value of the line edit void clear(); void setText(const QString& text); + void setConditionFormatContextMenuEnabled(bool enable) { conditional_format = enable; } + private slots: void delayedSignalTimerTriggered(); signals: void delayedTextChanged(QString text); + void addFilterAsCondFormat(QString text); + void clearAllCondFormats(); + void editCondFormats(); + void filterFocused(); protected: - void keyReleaseEvent(QKeyEvent* event); + void keyReleaseEvent(QKeyEvent* event) override; + void focusInEvent(QFocusEvent* event) override; + void setFilterHelper(const QString& filterOperator, const QString& operatorSuffix = QString()); private: - QList* filterList; - int columnNumber; + std::vector* filterList; + size_t columnNumber; QTimer* delaySignalTimer; + QString lastValue; + bool conditional_format; + +private slots: + void showContextMenu(const QPoint &pos); }; #endif diff --git a/src/FilterTableHeader.cpp b/src/FilterTableHeader.cpp index bcbbcac02..3df301c9c 100644 --- a/src/FilterTableHeader.cpp +++ b/src/FilterTableHeader.cpp @@ -1,6 +1,7 @@ #include "FilterTableHeader.h" #include "FilterLineEdit.h" +#include #include #include @@ -8,44 +9,53 @@ FilterTableHeader::FilterTableHeader(QTableView* parent) : QHeaderView(Qt::Horizontal, parent) { // Activate the click signals to allow sorting -#if QT_VERSION >= 0x050000 setSectionsClickable(true); -#else - setClickable(true); -#endif - setSortIndicatorShown(true); + // But use our own indicators allowing multi-column sorting + setSortIndicatorShown(false); + + // Make sure to not automatically resize the columns according to the contents + setSectionResizeMode(QHeaderView::Interactive); + + // Highlight column headers of selected cells to emulate spreadsheet behaviour + setHighlightSections(true); // Do some connects: Basically just resize and reposition the input widgets whenever anything changes - connect(this, SIGNAL(sectionResized(int,int,int)), this, SLOT(adjustPositions())); - connect(parent->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjustPositions())); - connect(parent->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjustPositions())); + connect(this, &FilterTableHeader::sectionResized, this, &FilterTableHeader::adjustPositions); + connect(this, &FilterTableHeader::sectionClicked, this, &FilterTableHeader::adjustPositions); + connect(parent->horizontalScrollBar(), &QScrollBar::valueChanged, this, &FilterTableHeader::adjustPositions); + connect(parent->verticalScrollBar(), &QScrollBar::valueChanged, this, &FilterTableHeader::adjustPositions); // Set custom context menu handling setContextMenuPolicy(Qt::CustomContextMenu); } -void FilterTableHeader::generateFilters(int number, bool showFirst) +void FilterTableHeader::generateFilters(size_t number, size_t number_of_hidden_filters) { // Delete all the current filter widgets - for(int i=0;i < filterWidgets.size(); ++i) - delete filterWidgets.at(i); + qDeleteAll(filterWidgets); filterWidgets.clear(); // And generate a bunch of new ones - for(int i=0;i < number; ++i) + for(size_t i=0; i < number; ++i) { FilterLineEdit* l = new FilterLineEdit(this, &filterWidgets, i); - if(!showFirst && i == 0) // This hides the first input widget which belongs to the hidden rowid column - l->setVisible(false); - else - l->setVisible(true); - connect(l, SIGNAL(delayedTextChanged(QString)), this, SLOT(inputChanged(QString))); + l->setVisible(i >= number_of_hidden_filters); + + // Set as focus proxy the first non-row-id visible filter-line. + if(i!=0 && l->isVisible() && !focusProxy()) + setFocusProxy(l); + + connect(l, &FilterLineEdit::delayedTextChanged, this, &FilterTableHeader::inputChanged); + connect(l, &FilterLineEdit::filterFocused, this, [this](){emit filterFocused();}); + connect(l, &FilterLineEdit::addFilterAsCondFormat, this, &FilterTableHeader::addFilterAsCondFormat); + connect(l, &FilterLineEdit::clearAllCondFormats, this, &FilterTableHeader::clearAllCondFormats); + connect(l, &FilterLineEdit::editCondFormats, this, &FilterTableHeader::editCondFormats); filterWidgets.push_back(l); } // Position them correctly - adjustPositions(); + updateGeometries(); } QSize FilterTableHeader::sizeHint() const @@ -53,7 +63,7 @@ QSize FilterTableHeader::sizeHint() const // For the size hint just take the value of the standard implementation and add the height of a input widget to it if necessary QSize s = QHeaderView::sizeHint(); if(filterWidgets.size()) - s.setHeight(s.height() + filterWidgets.at(0)->sizeHint().height() + 5); // The 5 adds just adds some extra space + s.setHeight(s.height() + filterWidgets.at(0)->sizeHint().height() + 4); // The 4 adds just adds some extra space return s; } @@ -72,30 +82,65 @@ void FilterTableHeader::updateGeometries() void FilterTableHeader::adjustPositions() { + // The two adds some extra space between the header label and the input widget + const int y = QHeaderView::sizeHint().height() + 2; // Loop through all widgets - for(int i=0;i < filterWidgets.size(); ++i) + for(int i=0;i < static_cast(filterWidgets.size()); ++i) { // Get the current widget, move it and resize it - QWidget* w = filterWidgets.at(i); - w->move(sectionPosition(i) - offset(), filterWidgets.at(i)->sizeHint().height() + 2); // The two adds some extra space between the header label and the input widget - w->resize(sectionSize(i), filterWidgets.at(i)->sizeHint().height()); + QWidget* w = filterWidgets.at(static_cast(i)); + if (QApplication::layoutDirection() == Qt::RightToLeft) + w->move(width() - (sectionPosition(i) + sectionSize(i) - offset()), y); + else + w->move(sectionPosition(i) - offset(), y); + w->resize(sectionSize(i), w->sizeHint().height()); } } void FilterTableHeader::inputChanged(const QString& new_value) { + adjustPositions(); // Just get the column number and the new value and send them to anybody interested in filter changes - emit filterChanged(sender()->property("column").toInt(), new_value); + emit filterChanged(sender()->property("column").toUInt(), new_value); +} + +void FilterTableHeader::addFilterAsCondFormat(const QString& filter) +{ + // Just get the column number and the new value and send them to anybody interested in new conditional formatting + emit addCondFormat(sender()->property("column").toUInt(), filter); +} + +void FilterTableHeader::clearAllCondFormats() +{ + // Just get the column number and send it to anybody responsible or interested in clearing conditional formatting + emit allCondFormatsCleared(sender()->property("column").toUInt()); +} + +void FilterTableHeader::editCondFormats() +{ + // Just get the column number and the new value and send them to anybody interested in editing conditional formatting + emit condFormatsEdited(sender()->property("column").toUInt()); } void FilterTableHeader::clearFilters() { - foreach (FilterLineEdit* filterLineEdit, filterWidgets) + for(FilterLineEdit* filterLineEdit : filterWidgets) filterLineEdit->clear(); } -void FilterTableHeader::setFilter(int column, const QString& value) +void FilterTableHeader::setFilter(size_t column, const QString& value) { if(column < filterWidgets.size()) filterWidgets.at(column)->setText(value); } + +QString FilterTableHeader::filterValue(size_t column) const +{ + return filterWidgets[column]->text(); +} + +void FilterTableHeader::setFocusColumn(size_t column) +{ + if(column < filterWidgets.size()) + filterWidgets.at(column)->setFocus(); +} diff --git a/src/FilterTableHeader.h b/src/FilterTableHeader.h index 8e170ba39..dfaf2a6a5 100644 --- a/src/FilterTableHeader.h +++ b/src/FilterTableHeader.h @@ -2,9 +2,8 @@ #define FILTERTABLEHEADER_H #include -#include +#include -class QLineEdit; class QTableView; class FilterLineEdit; @@ -13,26 +12,36 @@ class FilterTableHeader : public QHeaderView Q_OBJECT public: - explicit FilterTableHeader(QTableView* parent = 0); - virtual QSize sizeHint() const; - + explicit FilterTableHeader(QTableView* parent = nullptr); + QSize sizeHint() const override; + bool hasFilters() const {return (filterWidgets.size() > 0);} + QString filterValue(size_t column) const; + void setFocusColumn(size_t column); + public slots: - void generateFilters(int number, bool showFirst = false); + void generateFilters(size_t number, size_t number_of_hidden_filters = 1); void adjustPositions(); void clearFilters(); - void setFilter(int column, const QString& value); + void setFilter(size_t column, const QString& value); signals: - void filterChanged(int column, QString value); + void filterChanged(size_t column, QString value); + void filterFocused(); + void addCondFormat(size_t column, QString filter); + void allCondFormatsCleared(size_t column); + void condFormatsEdited(size_t column); protected: - virtual void updateGeometries(); + void updateGeometries() override; private slots: void inputChanged(const QString& new_value); + void addFilterAsCondFormat(const QString& filter); + void clearAllCondFormats(); + void editCondFormats(); private: - QList filterWidgets; + std::vector filterWidgets; }; #endif diff --git a/src/FindReplaceDialog.cpp b/src/FindReplaceDialog.cpp new file mode 100644 index 000000000..4279b3f84 --- /dev/null +++ b/src/FindReplaceDialog.cpp @@ -0,0 +1,227 @@ +#include "FindReplaceDialog.h" +#include "ui_FindReplaceDialog.h" +#include "ExtendedScintilla.h" + +#include + +FindReplaceDialog::FindReplaceDialog(QWidget* parent) + : QDialog(parent), + ui(new Ui::FindReplaceDialog), + m_scintilla(nullptr), + foundIndicatorNumber(0), + findInProgress(false) +{ + // Create UI + ui->setupUi(this); +} + +FindReplaceDialog::~FindReplaceDialog() +{ + delete ui; +} + +void FindReplaceDialog::setExtendedScintilla(ExtendedScintilla* scintilla) +{ + m_scintilla = scintilla; + + // Create indicator for find-all and replace-all occurrences + foundIndicatorNumber = m_scintilla->indicatorDefine(QsciScintilla::StraightBoxIndicator); + m_scintilla->setIndicatorForegroundColor(Qt::magenta, foundIndicatorNumber); + m_scintilla->setIndicatorDrawUnder(true, foundIndicatorNumber); + + bool isWriteable = ! m_scintilla->isReadOnly(); + ui->replaceWithText->setEnabled(isWriteable); + ui->replaceButton->setEnabled(isWriteable); + ui->replaceAllButton->setEnabled(isWriteable); + + connect(m_scintilla, &ExtendedScintilla::destroyed, this, &FindReplaceDialog::hide); + connect(ui->findText, &QLineEdit::editingFinished, this, &FindReplaceDialog::cancelFind); + connect(ui->regexpCheckBox, &QCheckBox::toggled, this, &FindReplaceDialog::cancelFind); + connect(ui->caseCheckBox, &QCheckBox::toggled, this, &FindReplaceDialog::cancelFind); + connect(ui->wholeWordsCheckBox, &QCheckBox::toggled, this, &FindReplaceDialog::cancelFind); + connect(ui->wrapCheckBox, &QCheckBox::toggled, this, &FindReplaceDialog::cancelFind); + connect(ui->backwardsCheckBox, &QCheckBox::toggled, this, &FindReplaceDialog::cancelFind); + connect(ui->selectionCheckBox, &QCheckBox::toggled, this, &FindReplaceDialog::cancelFind); + connect(ui->selectionCheckBox, &QCheckBox::toggled, ui->wrapCheckBox, &QCheckBox::setDisabled); +} + +bool FindReplaceDialog::findFirst(bool wrap, bool forward) +{ + if (ui->selectionCheckBox->isChecked()) + return m_scintilla->findFirstInSelection + (ui->findText->text(), + ui->regexpCheckBox->isChecked(), + ui->caseCheckBox->isChecked(), + ui->wholeWordsCheckBox->isChecked(), + forward, + /* show */ true, + /* posix */ true, + /* cxx11 */ true); + else + return m_scintilla->findFirst + (ui->findText->text(), + ui->regexpCheckBox->isChecked(), + ui->caseCheckBox->isChecked(), + ui->wholeWordsCheckBox->isChecked(), + wrap, + forward, + /* line */ -1, + /* index */ -1, + /* show */ true, + /* posix */ true, + /* cxx11 */ true); +} + +bool FindReplaceDialog::findNext() +{ + clearIndicators(); + + if (findInProgress) + findInProgress = m_scintilla->findNext(); + else + findInProgress = findFirst(ui->wrapCheckBox->isChecked(), + !ui->backwardsCheckBox->isChecked()); + + if (!findInProgress) + ui->messageLabel->setText(tr("The searched text was not found")); + + return findInProgress; + +} + +void FindReplaceDialog::showFindReplaceDialog(bool hasReplace) +{ + ui->replaceWithText->setVisible(hasReplace); + ui->replaceButton->setVisible(hasReplace); + ui->replaceWithLabel->setVisible(hasReplace); + ui->replaceAllButton->setVisible(hasReplace); + show(); +} + +void FindReplaceDialog::show() +{ + ui->findText->setFocus(); + + // If there is multi-line selected text set automatically the selection + // check box. If it's only part of a line, use it as text to find. + if (m_scintilla->hasSelectedText()) + if (m_scintilla->selectedText().contains("\n")) + ui->selectionCheckBox->setChecked(true); + else { + ui->findText->setText(m_scintilla->selectedText()); + ui->selectionCheckBox->setChecked(false); + } + else + ui->selectionCheckBox->setChecked(false); + + ui->findText->selectAll(); + QDialog::show(); +} + +void FindReplaceDialog::replace() +{ + if (m_scintilla->hasSelectedText()) + m_scintilla->replace(ui->replaceWithText->text()); + findNext(); +} + +void FindReplaceDialog::indicateSelection() +{ + int fromRow, fromIndex, toRow, toIndex; + m_scintilla->getSelection(&fromRow, &fromIndex, &toRow, &toIndex); + m_scintilla->fillIndicatorRange(fromRow, fromIndex, toRow, toIndex, foundIndicatorNumber); +} + +void FindReplaceDialog::searchAll(bool replace) +{ + clearIndicators(); + if (!ui->selectionCheckBox->isChecked()) + m_scintilla->setCursorPosition(0, 0); + + bool found = findFirst(/* wrap */ false, /* fordward */ true); + + int occurrences = 0; + while (found) { + if (replace) + m_scintilla->replace(ui->replaceWithText->text()); + indicateSelection(); + ++occurrences; + found = m_scintilla->findNext(); + } + + if (!ui->selectionCheckBox->isChecked()) + m_scintilla->clearSelection(); + + QString message; + switch (occurrences) { + case 0: + message = tr("The searched text was not found."); + break; + case 1: + if (replace) + message = tr("The searched text was replaced one time."); + else + message = tr("The searched text was found one time."); + break; + default: + if (replace) + message = tr("The searched text was replaced %1 times.").arg(occurrences); + else + message = tr("The searched text was found %1 times.").arg(occurrences); + + break; + } + + ui->messageLabel->setText(message); +} + +void FindReplaceDialog::findAll() +{ + searchAll(/* replace */ false); +} + +void FindReplaceDialog::replaceAll() +{ + searchAll(/* replace */ true); +} + +void FindReplaceDialog::cancelFind() +{ + m_scintilla->findFirst(QString(), false, false, false, false); + clearIndicators(); + findInProgress = false; + ui->messageLabel->setText(""); +} +void FindReplaceDialog::help() +{ + QWhatsThis::enterWhatsThisMode(); +} + +void FindReplaceDialog::clearIndicators() +{ + m_scintilla->clearIndicatorRange(0, 0, m_scintilla->lines(), m_scintilla->lineLength(m_scintilla->lines()), foundIndicatorNumber); + ui->messageLabel->setText(""); +} + +void FindReplaceDialog::close() +{ + m_scintilla->clearSelection(); + // Reset any previous find so it does not interfere with the next time + // the dialog is open. + cancelFind(); + QDialog::close(); +} + +void FindReplaceDialog::buttonBox_clicked(QAbstractButton* button) +{ + if (button == ui->buttonBox->button(QDialogButtonBox::Help)) + help(); + else if (button == ui->buttonBox->button(QDialogButtonBox::Close)) + close(); + +} +void FindReplaceDialog::reject() +{ + close(); + QDialog::reject(); +} diff --git a/src/FindReplaceDialog.h b/src/FindReplaceDialog.h new file mode 100644 index 000000000..b4865d625 --- /dev/null +++ b/src/FindReplaceDialog.h @@ -0,0 +1,48 @@ +#ifndef FindReplaceDialog_H +#define FindReplaceDialog_H + +#include + +class QAbstractButton; + +class ExtendedScintilla; + +namespace Ui { +class FindReplaceDialog; +} + +class FindReplaceDialog : public QDialog +{ + Q_OBJECT + +public: + + explicit FindReplaceDialog(QWidget* parent = nullptr); + ~FindReplaceDialog() override; + void setExtendedScintilla(ExtendedScintilla* scintilla); + void show(); + void showFindReplaceDialog(bool hasReplace); + +private slots: + bool findNext(); + void replace(); + void findAll(); + void replaceAll(); + void cancelFind(); + void help(); + void close(); + void reject() override; + void buttonBox_clicked(QAbstractButton* button); + +private: + bool findFirst(bool wrap, bool forward); + void searchAll(bool replace); + void indicateSelection(); + void clearIndicators(); + Ui::FindReplaceDialog* ui; + ExtendedScintilla* m_scintilla; + int foundIndicatorNumber; + bool findInProgress; +}; + +#endif diff --git a/src/FindReplaceDialog.ui b/src/FindReplaceDialog.ui new file mode 100644 index 000000000..25a0a5134 --- /dev/null +++ b/src/FindReplaceDialog.ui @@ -0,0 +1,322 @@ + + + FindReplaceDialog + + + + 0 + 0 + 451 + 288 + + + + Find and Replace + + + + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFormLayout::ExpandingFieldsGrow + + + + + Fi&nd text: + + + findText + + + + + + + + + + Re&place with: + + + replaceWithText + + + + + + + + + + Match &exact case + + + false + + + + + + + Match &only whole words + + + + + + + When enabled, the search continues from the other end when it reaches one end of the page + + + &Wrap around + + + + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + + + Search &backwards + + + + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + + + &Selection only + + + + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + Use regular e&xpressions + + + + + + + + + 7 + + + QLayout::SetDefaultConstraint + + + 0 + + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + + + &Find Next + + + F3 + + + + + + + &Replace + + + + + + + Highlight all the occurrences of the text in the page + + + F&ind All + + + + + + + Replace all the occurrences of the text in the page + + + Replace &All + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + 75 + true + + + + + + + Qt::AlignCenter + + + + + + + QDialogButtonBox::Close|QDialogButtonBox::Help + + + + + + + findText + replaceWithText + caseCheckBox + wholeWordsCheckBox + wrapCheckBox + backwardsCheckBox + selectionCheckBox + regexpCheckBox + findNextButton + replaceButton + findAllButton + replaceAllButton + + + + + findNextButton + clicked() + FindReplaceDialog + findNext() + + + 225 + 242 + + + 225 + 132 + + + + + replaceButton + clicked() + FindReplaceDialog + replace() + + + 225 + 242 + + + 225 + 132 + + + + + findAllButton + clicked() + FindReplaceDialog + findAll() + + + 225 + 242 + + + 225 + 132 + + + + + replaceAllButton + clicked() + FindReplaceDialog + replaceAll() + + + 225 + 242 + + + 225 + 132 + + + + + buttonBox + clicked(QAbstractButton*) + FindReplaceDialog + buttonBox_clicked(QAbstractButton*) + + + 225 + 265 + + + 225 + 143 + + + + + + updatePreview() + checkInput() + updateSelection(bool) + matchSimilar() + + diff --git a/src/ForeignKeyEditorDelegate.cpp b/src/ForeignKeyEditorDelegate.cpp new file mode 100644 index 000000000..07afdedc2 --- /dev/null +++ b/src/ForeignKeyEditorDelegate.cpp @@ -0,0 +1,203 @@ +#include "sqlitedb.h" +#include "ForeignKeyEditorDelegate.h" + +#include +#include +#include +#include + +Q_DECLARE_METATYPE(sqlb::StringVector) + +class ForeignKeyEditor : public QWidget +{ + Q_OBJECT + +public: + explicit ForeignKeyEditor(QWidget* parent = nullptr) + : QWidget(parent) + , tablesComboBox(new QComboBox(this)) + , idsComboBox(new QComboBox(this)) + , clauseEdit(new QLineEdit(this)) + , m_btnReset(new QPushButton(tr("&Reset"), this)) + { + idsComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); + clauseEdit->setPlaceholderText(tr("Foreign key clauses (ON UPDATE, ON DELETE etc.)")); + + QHBoxLayout* layout = new QHBoxLayout(this); + layout->addWidget(tablesComboBox); + layout->addWidget(idsComboBox); + layout->addWidget(clauseEdit); + layout->addWidget(m_btnReset); + layout->setSpacing(0); + layout->setContentsMargins(0, 0, 0, 0); + setLayout(layout); + + connect(m_btnReset, &QPushButton::clicked, this, [&] + { + tablesComboBox->setCurrentIndex(-1); + idsComboBox->setCurrentIndex(-1); + clauseEdit->clear(); + }); + + connect(tablesComboBox, static_cast(&QComboBox::currentIndexChanged), this, + [=](int index) + { + // reset ids combo box + idsComboBox->setCurrentIndex(-1); + + // disable clauses editor if none of tables is selected + bool enableClausesEditor = (index!= -1); + clauseEdit->setEnabled(enableClausesEditor); + }); + } + + QString getSql() const + { + if (tablesComboBox->currentText().isEmpty()) + return QString(); + + const QString table = sqlb::escapeIdentifier(tablesComboBox->currentText()); + const QString clauses = clauseEdit->text(); + + QString id = idsComboBox->currentText(); + if (!id.isEmpty()) + id = QString("(%1)").arg(sqlb::escapeIdentifier(id)); + + return QString("%1%2 %3").arg( + table, + id, + clauses) + .trimmed(); + } + + QComboBox* tablesComboBox; + QComboBox* idsComboBox; + QLineEdit* clauseEdit; // for ON CASCADE and such + std::shared_ptr foreignKey; // This can be used for storing a pointer to the foreign key object currently edited + +private: + QPushButton* m_btnReset; +}; + +ForeignKeyEditorDelegate::ForeignKeyEditorDelegate(const DBBrowserDB& db, sqlb::Table& table, QObject* parent) + : QStyledItemDelegate(parent) + , m_db(db) + , m_table(table) +{ + for(const auto& it : m_db.schemata) + { + for(const auto& jt : it.second.tables) + { + // Don't insert the current table into the list. The name and fields of the current table are always taken from the m_table reference + if(jt.first != m_table.name()) + m_tablesIds.insert({jt.first, jt.second->fieldNames()}); + } + } +} + +QWidget* ForeignKeyEditorDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + Q_UNUSED(option) + Q_UNUSED(index) + + ForeignKeyEditor* editor = new ForeignKeyEditor(parent); + editor->setAutoFillBackground(true); + + connect(editor->tablesComboBox, static_cast(&QComboBox::currentIndexChanged), this, + [=](int idx) + { + QString tableName = editor->tablesComboBox->itemText(idx); + + QComboBox* box = editor->idsComboBox; + box->clear(); + box->addItem(QString()); // for those heroes who don't like to specify key explicitly + + // For recursive foreign keys get the field list from the m_table reference. For other foreign keys from the prepared field lists. + if(tableName.toStdString() == m_table.name()) + { + for(const auto& n : m_table.fieldNames()) + box->addItem(QString::fromStdString(n)); + } else { + for(const auto& n : m_tablesIds[tableName.toStdString()]) + box->addItem(QString::fromStdString(n)); + } + + + box->setCurrentIndex(0); + }); + + editor->tablesComboBox->clear(); + editor->tablesComboBox->addItem(QString::fromStdString(m_table.name())); // For recursive foreign keys + editor->tablesComboBox->insertSeparator(1); + for(const auto& i : m_tablesIds) + editor->tablesComboBox->addItem(QString::fromStdString(i.first)); + + return editor; +} + +void ForeignKeyEditorDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const +{ + ForeignKeyEditor* fkEditor = static_cast(editor); + + // First try to get the fields list by assuming this is called for a constraints table in which the first column contains a list of fields. + // If this fails, assume this is called for a fields table in which the first column contains the name of a single table field. + sqlb::StringVector fields = index.sibling(index.row(), 0).data(Qt::UserRole).value(); + if(fields.empty()) + fields.push_back(index.sibling(index.row(), 0).data().toString().toStdString()); + fkEditor->foreignKey = m_table.foreignKey(fields); + + if (fkEditor->foreignKey) { + fkEditor->tablesComboBox->setCurrentText(QString::fromStdString(fkEditor->foreignKey->table())); + fkEditor->clauseEdit->setText(QString::fromStdString(fkEditor->foreignKey->constraint())); + if (!fkEditor->foreignKey->columns().empty()) + fkEditor->idsComboBox->setCurrentText(QString::fromStdString(fkEditor->foreignKey->columns().front())); + } else { + fkEditor->tablesComboBox->setCurrentIndex(-1); + } +} + +void ForeignKeyEditorDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const +{ + ForeignKeyEditor* fkEditor = static_cast(editor); + QString sql = fkEditor->getSql(); + + // First try to get the fields list by assuming this is called for a constraints table in which the first column contains a list of fields. + // If this fails, assume this is called for a fields table in which the first column contains the name of a single table field. + sqlb::StringVector fields = index.sibling(index.row(), 0).data(Qt::UserRole).value(); + if(fields.empty()) + fields.push_back(index.sibling(index.row(), 0).data().toString().toStdString()); + + if (sql.isEmpty() && fkEditor->foreignKey) { + // Remove the foreign key + m_table.removeConstraint(fkEditor->foreignKey); + } else { + // Create a new foreign key object if required + if(!fkEditor->foreignKey) + { + fkEditor->foreignKey = std::make_shared(); + m_table.addConstraint(fields, fkEditor->foreignKey); + } + + // Set data + const auto table = fkEditor->tablesComboBox->currentText().toStdString(); + const auto id = fkEditor->idsComboBox->currentText().toStdString(); + const auto clause = fkEditor->clauseEdit->text().trimmed().toStdString(); + fkEditor->foreignKey->setTable(table); + if(id.empty()) + fkEditor->foreignKey->setColumns({}); + else + fkEditor->foreignKey->setColumns({id}); + fkEditor->foreignKey->setConstraint(clause); + } + + model->setData(index, sql); +} + +void ForeignKeyEditorDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + Q_UNUSED(index) + + editor->setGeometry(option.rect); +} + +#include "ForeignKeyEditorDelegate.moc" diff --git a/src/ForeignKeyEditorDelegate.h b/src/ForeignKeyEditorDelegate.h new file mode 100644 index 000000000..58a788975 --- /dev/null +++ b/src/ForeignKeyEditorDelegate.h @@ -0,0 +1,34 @@ +#ifndef FOREIGNKEYDELEGATE_H +#define FOREIGNKEYDELEGATE_H + +#include +#include +#include +#include + +class DBBrowserDB; + +namespace sqlb +{ +class Table; +} + +class ForeignKeyEditorDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + explicit ForeignKeyEditorDelegate(const DBBrowserDB& db, sqlb::Table& table, QObject* parent = nullptr); + + QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + void setEditorData(QWidget* editor, const QModelIndex& index) const override; + void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override; + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + +private: + const DBBrowserDB& m_db; + sqlb::Table& m_table; + mutable std::map> m_tablesIds; +}; + +#endif // FOREIGNKEYDELEGATE_H diff --git a/src/IconCache.cpp b/src/IconCache.cpp new file mode 100644 index 000000000..fcc219fb9 --- /dev/null +++ b/src/IconCache.cpp @@ -0,0 +1,22 @@ +#include "IconCache.h" + +QIcon IconCache::null_icon; +std::unordered_map IconCache::icons; + +const QIcon& IconCache::get(const std::string& name) +{ + // Check if we already have an icon object with that name in the cache. If so, just return that + auto it = icons.find(name); + if(it != icons.end()) + return it->second; + + // If now, try to load an icon with that name and insert it into the cache + QIcon icon(":/icons/" + QString::fromStdString(name)); + auto ins = icons.insert({name, icon}); + + // If the insertion was successful, return the inserted icon object. If it was not, return a null icon. + if(ins.second) + return ins.first->second; + else + return null_icon; +} diff --git a/src/IconCache.h b/src/IconCache.h new file mode 100644 index 000000000..73200f513 --- /dev/null +++ b/src/IconCache.h @@ -0,0 +1,21 @@ +#ifndef ICONCACHE_H +#define ICONCACHE_H + +#include + +#include +#include + +class IconCache +{ +public: + IconCache() = delete; + + static const QIcon& get(const std::string& name); + +private: + static QIcon null_icon; + static std::unordered_map icons; +}; + +#endif diff --git a/src/ImageViewer.cpp b/src/ImageViewer.cpp new file mode 100644 index 000000000..f70b08945 --- /dev/null +++ b/src/ImageViewer.cpp @@ -0,0 +1,181 @@ +#include "ImageViewer.h" +#include "ui_ImageViewer.h" + +#include +#include +#include +#include +#include +#include +#include + +ImageViewer::ImageViewer(QWidget* parent) : + QWidget(parent), + ui(new Ui::ImageViewer), + m_image_size(0, 0), + m_pan_mode{false} +{ + ui->setupUi(this); + ui->scrollArea->viewport()->installEventFilter(this); + connect(ui->buttonOriginalSize, &QToolButton::clicked, this, [this]{ scaleImage(100); }); + + ui->labelView->addAction(ui->actionPrintImage); +} + +ImageViewer::~ImageViewer() +{ + delete ui; +} + +void ImageViewer::resetImage() +{ + ui->labelView->setPixmap(QPixmap(0, 0)); +} + +void ImageViewer::setImage(const QImage& image) +{ + auto widget_size = ui->scrollArea->viewport()->size(); + m_image_size = image.size(); + ui->labelView->setMaximumSize(m_image_size.scaled(widget_size, Qt::KeepAspectRatio)); + + ui->labelView->setPixmap(QPixmap::fromImage(image)); + + // If the image is larger than the viewport scale it to fit the viewport. + // If the image is smaller than the viewport show it in its original size. + if(!isQSizeCovered(m_image_size)) + ui->buttonFitToWindow->setChecked(true); + else + scaleImage(100); +} + +bool ImageViewer::isQSizeCovered(QSize rect) +{ + auto widget_size = ui->scrollArea->viewport()->size(); + return widget_size.width() >= rect.width() && widget_size.height() >= rect.height(); +} + +bool ImageViewer::eventFilter(QObject* /*obj*/, QEvent* e) { + auto e_type = e->type(); + + if (e_type == QEvent::Wheel) { + auto *wheel_event = static_cast(e); + auto step = ui->sliderScale->pageStep(); + if (wheel_event->angleDelta().y() < 0) { + step = -step; + } + scaleImage(ui->sliderScale->value() + step); + e->accept(); + return true; + } + + if (ui->buttonFitToWindow->isChecked()) { + if (e_type == QEvent::Resize) + scaleToFitWindow(true); + } else if (e_type >= QEvent::MouseButtonPress && e_type <= QEvent::MouseMove) { + auto *mouse_event = static_cast(e); + if (e_type == QEvent::MouseButtonPress && mouse_event->button() == Qt::LeftButton && + !isQSizeCovered(ui->labelView->size())) { + m_mouse_down = mouse_event->globalPos(); + m_pan_mode = true; + ui->scrollArea->setCursor(Qt::ClosedHandCursor); + } else if (e_type == QEvent::MouseMove && m_pan_mode) { + auto dx = mouse_event->globalX() - m_mouse_down.x(); + auto dy = mouse_event->globalY() - m_mouse_down.y(); + m_mouse_down = mouse_event->globalPos(); + if (dx != 0) { + ui->scrollArea->horizontalScrollBar()->setValue(ui->scrollArea->horizontalScrollBar()->value() - dx); + } + + if (dy != 0) { + ui->scrollArea->verticalScrollBar()->setValue(ui->scrollArea->verticalScrollBar()->value() - dy); + } + } else if (e_type == QEvent::MouseButtonRelease && mouse_event->button() == Qt::LeftButton) { + m_pan_mode = false; + ui->scrollArea->setCursor(Qt::ArrowCursor); + } + } + return false; +} + +void ImageViewer::openPrintImageDialog() +{ + QPrinter printer; + QPrintPreviewDialog dialog(&printer); + + connect(&dialog, &QPrintPreviewDialog::paintRequested, &dialog, [&](QPrinter* previewPrinter) { + QPainter painter(previewPrinter); + QRect rect = painter.viewport(); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) + QPixmap pixmap = *ui->labelView->pixmap(); +#else + QPixmap pixmap = ui->labelView->pixmap(Qt::ReturnByValue); +#endif + + QSize size = pixmap.size(); + size.scale(rect.size(), Qt::KeepAspectRatio); + painter.setViewport(rect.x(), rect.y(), size.width(), size.height()); + painter.setWindow(pixmap.rect()); + painter.drawPixmap(0, 0, pixmap); + }); + + dialog.exec(); +} + +void ImageViewer::scaleToFitWindow(bool enabled) +{ + // Enable/disable the automatic resizing of the label inside the scrollbar + ui->scrollArea->setWidgetResizable(enabled); + + // When disabling the fit to window scaling, revert back to the original image size + if(!enabled) { + scaleImage(100); + } else { + ui->labelView->setMaximumSize(m_image_size.scaled(ui->scrollArea->viewport()->size(), Qt::KeepAspectRatio)); + setSliderValueWithoutSignal(static_cast(ui->labelView->maximumWidth() / static_cast(m_image_size.width()) * 100)); + } +} + +void ImageViewer::setNoFitWithoutSignal() +{ + if (ui->buttonFitToWindow->isChecked()) { + ui->buttonFitToWindow->blockSignals(true); + ui->scrollArea->setWidgetResizable(false); + ui->buttonFitToWindow->setChecked(false); + ui->buttonFitToWindow->blockSignals(false); + } +} + +void ImageViewer::setSliderValueWithoutSignal(int value) +{ + ui->sliderScale->blockSignals(true); + ui->sliderScale->setValue(value); + ui->sliderScale->blockSignals(false); +} + +void ImageViewer::scaleImage(int scale) +{ + // Clamp scale to the sliderScale min/max + scale = std::min(ui->sliderScale->maximum(), std::max(ui->sliderScale->minimum(), scale)); + + // Make sure the slider is updated when this is called programmatically + setSliderValueWithoutSignal(scale); + + // Uncheck the fit to window button + setNoFitWithoutSignal(); + + // Update our scale factor + auto scale_factor = scale / 100.0; + + // Resize the image + auto max_size_old = ui->labelView->maximumSize(); + ui->labelView->setMaximumSize(m_image_size * scale_factor); + ui->labelView->resize(ui->labelView->maximumSize()); + auto factor_change = ui->labelView->maximumWidth() / static_cast(max_size_old.width()); + + // Fix scroll bars to zoom into center of viewport instead of the upper left corner + const auto adjust_scrollbar = [](QScrollBar* scroll_bar, qreal factor) { + scroll_bar->setValue(static_cast(factor * scroll_bar->value() + ((factor - 1) * scroll_bar->pageStep() / 2))); + }; + adjust_scrollbar(ui->scrollArea->horizontalScrollBar(), factor_change); + adjust_scrollbar(ui->scrollArea->verticalScrollBar(), factor_change); +} diff --git a/src/ImageViewer.h b/src/ImageViewer.h new file mode 100644 index 000000000..79803c7e7 --- /dev/null +++ b/src/ImageViewer.h @@ -0,0 +1,40 @@ +#ifndef IMAGEVIEWER_H +#define IMAGEVIEWER_H + +#include + +namespace Ui { +class ImageViewer; +} + +class ImageViewer : public QWidget +{ + Q_OBJECT + +public: + explicit ImageViewer(QWidget* parent = nullptr); + ~ImageViewer() override; + + void resetImage(); + void setImage(const QImage& image); + +public slots: + void openPrintImageDialog(); + +private slots: + void scaleToFitWindow(bool enabled); + void scaleImage(int scale); + +private: + Ui::ImageViewer* ui; + QSize m_image_size; + bool m_pan_mode; + QPoint m_mouse_down; + + bool eventFilter(QObject *obj, QEvent *e) override; + bool isQSizeCovered(QSize rect); + void setNoFitWithoutSignal(); + void setSliderValueWithoutSignal(int value); +}; + +#endif diff --git a/src/ImageViewer.ui b/src/ImageViewer.ui new file mode 100644 index 000000000..64535c6ed --- /dev/null +++ b/src/ImageViewer.ui @@ -0,0 +1,193 @@ + + + ImageViewer + + + + 0 + 0 + 433 + 307 + + + + Image Viewer + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::AlignCenter + + + + + 0 + 0 + 431 + 280 + + + + + 0 + 0 + + + + Qt::ActionsContextMenu + + + true + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1 + + + 800 + + + 100 + + + Qt::Horizontal + + + + + + + Reset the scaling to match the original size of the image. + + + + :/icons/view:/icons/view + + + + + + + Set the scaling to match the size of the viewport. + + + + :/icons/monitor_link:/icons/monitor_link + + + true + + + + + + + + + + :/icons/print:/icons/print + + + Print... + + + Open preview dialog for printing displayed image + + + Ctrl+P + + + + + + + + + actionPrintImage + triggered() + ImageViewer + openPrintImageDialog() + + + -1 + -1 + + + 308 + 190 + + + + + sliderScale + valueChanged(int) + ImageViewer + scaleImage(int) + + + 280 + 294 + + + 216 + 153 + + + + + buttonFitToWindow + toggled(bool) + ImageViewer + scaleToFitWindow(bool) + + + 419 + 294 + + + 216 + 153 + + + + + + scaleImage(int) + scaleToFitWindow(bool) + + diff --git a/src/ImportCsvDialog.cpp b/src/ImportCsvDialog.cpp index 3caf326f3..9921bb9f1 100644 --- a/src/ImportCsvDialog.cpp +++ b/src/ImportCsvDialog.cpp @@ -3,6 +3,8 @@ #include "sqlitedb.h" #include "csvparser.h" #include "sqlite.h" +#include "Settings.h" +#include "Data.h" #include #include @@ -13,42 +15,97 @@ #include #include #include -#include -#include #include #include -ImportCsvDialog::ImportCsvDialog(const QString& filename, DBBrowserDB* db, QWidget* parent) +// Enable this line to show basic performance stats after each imported CSV file. Please keep in mind that while these +// numbers might help to estimate the performance of the algorithm, this is not a proper benchmark. +//#define CSV_BENCHMARK + +#ifdef CSV_BENCHMARK +#include +#endif + +QChar ImportCsvDialog::getSettingsChar(const std::string& group, const std::string& name) +{ + QVariant value = Settings::getValue(group, name); + // QVariant is not able to return the character as a QChar when QString is stored. + // We do it manually, since it is versatile, when the option is passed from the command line, + // for example. + if(value.userType() == QMetaType::QString) + return value.toString().at(0); + else + return value.toChar(); +} + +ImportCsvDialog::ImportCsvDialog(const std::vector& filenames, DBBrowserDB* db, QWidget* parent, const QString& table) : QDialog(parent), ui(new Ui::ImportCsvDialog), - csvFilename(filename), + csvFilenames(filenames), pdb(db) { ui->setupUi(this); - // Get the actual file name out of the provided path and use it as the default table name for import - QFileInfo file(filename); - ui->editName->setText(file.baseName()); + // Hide "Advanced" section of the settings + toggleAdvancedSection(false); + + if(!table.isEmpty()) { + ui->editName->setText(table); + } else { + // Get the actual file name out of the provided path and use it as the default table name for import + // For importing several files at once, the fields have to be the same so we can safely use the first + QFileInfo file(filenames.front()); + ui->editName->setText(file.baseName()); + } // Create a list of all available encodings and create an auto completion list from them - QStringList encodingList; - foreach(QString enc, QTextCodec::availableCodecs()) - encodingList.push_back(enc); - encodingCompleter = new QCompleter(encodingList, this); + encodingCompleter = new QCompleter(toStringList(QTextCodec::availableCodecs()), this); encodingCompleter->setCaseSensitivity(Qt::CaseInsensitive); ui->editCustomEncoding->setCompleter(encodingCompleter); // Load last used settings and apply them - QSettings settings(QApplication::organizationName(), QApplication::organizationName()); - ui->checkboxHeader->setChecked(settings.value("importcsv/firstrowheader", false).toBool()); - ui->checkBoxTrimFields->setChecked(settings.value("importcsv/trimfields", true).toBool()); - setSeparatorChar(QChar(settings.value("importcsv/separator", ',').toInt())); - setQuoteChar(QChar(settings.value("importcsv/quotecharacter", '"').toInt())); - setEncoding(settings.value("importcsv/encoding", "UTF-8").toString()); - - // Initialise user interface - checkInput(); + ui->checkboxHeader->blockSignals(true); + ui->checkBoxTrimFields->blockSignals(true); + ui->checkBoxSeparateTables->blockSignals(true); + ui->checkLocalConventions->blockSignals(true); + ui->comboSeparator->blockSignals(true); + ui->comboQuote->blockSignals(true); + ui->comboEncoding->blockSignals(true); + + ui->checkboxHeader->setChecked(Settings::getValue("importcsv", "firstrowheader").toBool()); + ui->checkBoxTrimFields->setChecked(Settings::getValue("importcsv", "trimfields").toBool()); + ui->checkBoxSeparateTables->setChecked(Settings::getValue("importcsv", "separatetables").toBool()); + ui->checkLocalConventions->setChecked(Settings::getValue("importcsv", "localconventions").toBool()); + setSeparatorChar(getSettingsChar("importcsv", "separator")); + setQuoteChar(getSettingsChar("importcsv", "quotecharacter")); + setEncoding(Settings::getValue("importcsv", "encoding").toString()); + + ui->checkboxHeader->blockSignals(false); + ui->checkBoxTrimFields->blockSignals(false); + ui->checkBoxSeparateTables->blockSignals(false); + ui->checkLocalConventions->blockSignals(false); + ui->comboSeparator->blockSignals(false); + ui->comboQuote->blockSignals(false); + ui->comboEncoding->blockSignals(false); + + // Prepare and show interface depending on how many files are selected + if (csvFilenames.size() > 1) + { + ui->separateTables->setVisible(true); + ui->checkBoxSeparateTables->setVisible(true); + ui->filePickerBlock->setVisible(true); + selectFiles(); + } + else if (csvFilenames.size() == 1) + { + ui->separateTables->setVisible(false); + ui->checkBoxSeparateTables->setVisible(false); + ui->filePickerBlock->setVisible(false); + } + + selectedFile = csvFilenames.front(); updatePreview(); + checkInput(); } ImportCsvDialog::~ImportCsvDialog() @@ -60,12 +117,15 @@ namespace { void rollback( ImportCsvDialog* dialog, DBBrowserDB* pdb, - QProgressDialog& progress, - const QString& savepointName, + DBBrowserDB::db_pointer_type* db_ptr, + const std::string& savepointName, size_t nRecord, const QString& message) { - progress.hide(); + // Release DB handle. This needs to be done before calling revertToSavepoint as that function needs to be able to acquire its own handle. + if(db_ptr) + *db_ptr = nullptr; + QApplication::restoreOverrideCursor(); // restore original cursor if(!message.isEmpty()) { @@ -82,259 +142,632 @@ void rollback( class CSVImportProgress : public CSVProgress { public: - explicit CSVImportProgress(size_t filesize) + explicit CSVImportProgress(int64_t filesize) + : m_pProgressDlg(new QProgressDialog( + QObject::tr("Importing CSV file..."), + QObject::tr("Cancel"), + 0, + 10000)), + totalFileSize(filesize) { - m_pProgressDlg = new QProgressDialog( - QObject::tr("Decoding CSV file..."), - QObject::tr("Cancel"), - 0, - filesize); m_pProgressDlg->setWindowModality(Qt::ApplicationModal); + // Disable context help button on Windows + m_pProgressDlg->setWindowFlags(m_pProgressDlg->windowFlags() + & ~Qt::WindowContextHelpButtonHint); } - ~CSVImportProgress() - { - delete m_pProgressDlg; - } + CSVImportProgress(const CSVImportProgress&) = delete; + bool operator=(const CSVImportProgress&) = delete; - void start() + void start() override { m_pProgressDlg->show(); } - bool update(size_t pos) + bool update(int64_t pos) override { - m_pProgressDlg->setValue(pos); + m_pProgressDlg->setValue(static_cast((static_cast(pos) / static_cast(totalFileSize)) * 10000.0f)); qApp->processEvents(); return !m_pProgressDlg->wasCanceled(); } - void end() + void end() override { m_pProgressDlg->hide(); } private: - QProgressDialog* m_pProgressDlg; + std::unique_ptr m_pProgressDlg; + + int64_t totalFileSize; }; void ImportCsvDialog::accept() { - // save settings - QSettings settings(QApplication::organizationName(), QApplication::organizationName()); - settings.beginGroup("importcsv"); - settings.setValue("firstrowheader", ui->checkboxHeader->isChecked()); - settings.setValue("separator", currentSeparatorChar()); - settings.setValue("quotecharacter", currentQuoteChar()); - settings.setValue("trimfields", ui->checkBoxTrimFields->isChecked()); - settings.setValue("encoding", currentEncoding()); - settings.endGroup(); + // Save settings + Settings::setValue("importcsv", "firstrowheader", ui->checkboxHeader->isChecked()); + Settings::setValue("importcsv", "separator", currentSeparatorChar()); + Settings::setValue("importcsv", "quotecharacter", currentQuoteChar()); + Settings::setValue("importcsv", "trimfields", ui->checkBoxTrimFields->isChecked()); + Settings::setValue("importcsv", "separatetables", ui->checkBoxSeparateTables->isChecked()); + Settings::setValue("importcsv", "localconventions", ui->checkLocalConventions->isChecked()); + Settings::setValue("importcsv", "encoding", currentEncoding()); + + // Get all the selected files and start the import + if (ui->filePickerBlock->isVisible()) + { + bool filesLeft = false; + + // Loop through all the rows in the file picker list + for (int i = 0; i < ui->filePicker->count(); i++) { + auto item = ui->filePicker->item(i); + int row = ui->filePicker->row(item); + + // Check for files that aren't hidden (=imported) yet but that are checked and thus marked for import + if (item->checkState() == Qt::Checked && !ui->filePicker->isRowHidden(row)) { + if(!importCsv(item->data(Qt::DisplayRole).toString(), item->data(Qt::UserRole).toString())) + { + // If we're supposed to cancel the import process, we always have at least one file left (the cancelled one). Also + // we stop looping through the rest of the CSV files. + filesLeft = true; + break; + } + + // Hide each row after it's done + ui->filePicker->setRowHidden(row, true); + } else if(!ui->filePicker->isRowHidden(row)) { + // Check for files that aren't hidden yet but that aren't checked either. These are files that are still left + // to be imported + filesLeft = true; + } + } + + // Don't close the window if there are still files left to be imported + if(filesLeft) + { + QApplication::restoreOverrideCursor(); // restore original cursor + return; + } + } else { + importCsv(csvFilenames.front()); + } + + QApplication::restoreOverrideCursor(); // restore original cursor + QDialog::accept(); +} + +void ImportCsvDialog::updatePreview() +{ + // Show/hide custom quote/separator input fields + ui->editCustomQuote->setVisible(ui->comboQuote->currentIndex() == ui->comboQuote->count() - OtherPrintable); + ui->editCustomSeparator->setVisible(ui->comboSeparator->currentIndex() == ui->comboSeparator->count() - OtherPrintable); + ui->spinBoxQuote->setVisible(ui->comboQuote->currentIndex() == ui->comboQuote->count() - OtherCode); + ui->spinBoxSeparator->setVisible(ui->comboSeparator->currentIndex() == ui->comboSeparator->count() - OtherCode); + ui->editCustomEncoding->setVisible(ui->comboEncoding->currentIndex() == ui->comboEncoding->count()-1); + + // Reset preview widget + ui->tablePreview->clear(); + ui->tablePreview->setColumnCount(0); + ui->tablePreview->setRowCount(0); + + // Analyse CSV file + sqlb::FieldVector fieldList = generateFieldList(selectedFile); + + // Reset preview widget + ui->tablePreview->clear(); + ui->tablePreview->setColumnCount(static_cast(fieldList.size())); + + // Exit if there are no lines to preview at all + if(fieldList.size() == 0) + return; + + // Set horizontal header data + QStringList horizontalHeader; + std::transform(fieldList.begin(), fieldList.end(), std::back_inserter(horizontalHeader), [](const auto& field) { return QString::fromStdString(field.name()); }); + ui->tablePreview->setHorizontalHeaderLabels(horizontalHeader); + + // Parse file + parseCSV(selectedFile, [this](size_t rowNum, const CSVRow& rowData) -> bool { + // Skip first row if it is to be used as header + if(rowNum == 0 && ui->checkboxHeader->isChecked()) + return true; + + // Decrease the row number by one if the header checkbox is checked to take into account that the first row was used for the table header labels + // and therefore all data rows move one row up. + if(ui->checkboxHeader->isChecked()) + rowNum--; + + // Fill data section + ui->tablePreview->setRowCount(ui->tablePreview->rowCount() + 1); + for(size_t i=0;itablePreview->setVerticalHeaderItem(static_cast(rowNum), new QTableWidgetItem(QString::number(rowNum + 1))); + + // Add table item. Limit data length to a maximum character count to avoid a sluggish UI. And it's very unlikely that this + // many characters are going to be needed anyway for a preview. + uint64_t data_length = rowData.fields[i].data_length; + if(data_length > 1024) + data_length = 1024; + ui->tablePreview->setItem( + static_cast(rowNum), + static_cast(i), + new QTableWidgetItem(QString::fromUtf8(rowData.fields[i].data, static_cast(data_length)))); + } + + return true; + }, 20); +} + +void ImportCsvDialog::checkInput() +{ + bool allowImporting = false; + if (ui->filePickerBlock->isVisible()) { + bool checkedItem = false; + for (int i = 0; i < ui->filePicker->count(); i++) { + if (ui->filePicker->item(i)->checkState() == Qt::Checked) checkedItem = true; + } + allowImporting = !ui->editName->text().isEmpty() && checkedItem; + } else { + allowImporting = !ui->editName->text().isEmpty(); + } + + if (ui->filePicker->currentItem() && ui->checkBoxSeparateTables->isChecked()) { + ui->filePicker->currentItem()->setData(Qt::UserRole, ui->editName->text()); + } + + ui->matchSimilar->setEnabled(ui->filePicker->currentItem() != nullptr); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(allowImporting); +} + +void ImportCsvDialog::selectFiles() +{ + for (const auto& fileName : csvFilenames) { + auto fInfo = QFileInfo(fileName); + auto item = new QListWidgetItem(); + item->setText(fileName); + item->setData(Qt::UserRole, fInfo.baseName()); + item->setCheckState(Qt::Checked); + ui->filePicker->addItem(item); + } + + connect(ui->filePicker, &QListWidget::itemSelectionChanged, this, &ImportCsvDialog::updateSelectedFilePreview); +} + +void ImportCsvDialog::updateSelectedFilePreview() +{ + auto selection = ui->filePicker->selectedItems(); + if(!selection.isEmpty()) + { + auto item = selection.first(); + selectedFile = item->data(Qt::DisplayRole).toString(); + ui->editName->setText(item->data(Qt::UserRole).toString()); + updatePreview(); + checkInput(); + } +} + +void ImportCsvDialog::updateSelection(bool selected) +{ + for (int i = 0; i < ui->filePicker->count(); i++) + ui->filePicker->item(i)->setCheckState(selected ? Qt::Checked : Qt::Unchecked); + ui->toggleSelected->setText(selected ? tr("Deselect All") : tr("Select All")); + checkInput(); +} + +void ImportCsvDialog::matchSimilar() +{ + auto selectedHeader = generateFieldList(ui->filePicker->currentItem()->data(Qt::DisplayRole).toString()); + + for (int i = 0; i < ui->filePicker->count(); i++) + { + auto item = ui->filePicker->item(i); + auto header = generateFieldList(item->data(Qt::DisplayRole).toString()); + + if (selectedHeader.size() == header.size()) + { + bool matchingHeader = std::equal(selectedHeader.begin(), selectedHeader.end(), header.begin(), + [](const sqlb::Field& item1, const sqlb::Field& item2) -> bool { + return (item1.name() == item2.name()); + }); + if (matchingHeader) { + item->setCheckState(Qt::Checked); + item->setBackground(Qt::green); + } + } + else + { + item->setCheckState(Qt::Unchecked); + item->setBackground(Qt::white); + } + } + + checkInput(); +} + +CSVParser::ParserResult ImportCsvDialog::parseCSV(const QString &fileName, std::function rowFunction, size_t count) const +{ // Parse all csv data - QFile file(csvFilename); + QFile file(fileName); file.open(QIODevice::ReadOnly); - CSVParser csv(ui->checkBoxTrimFields->isChecked(), currentSeparatorChar(), currentQuoteChar()); - csv.setCSVProgress(new CSVImportProgress(file.size())); + CSVParser csv(ui->checkBoxTrimFields->isChecked(), toUtf8(currentSeparatorChar()), toUtf8(currentQuoteChar())); + // Only show progress dialog if we parse all rows. The assumption here is that if a row count limit has been set, it won't be a very high one. + if(count == 0) + csv.setCSVProgress(new CSVImportProgress(file.size())); QTextStream tstream(&file); + // textstream.setCodec(QTextCodec::codecForName("UTF-8")); + // is no longer needed in Qt6 since QTextStream defaults to utf-8. +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) tstream.setCodec(currentEncoding().toUtf8()); - csv.parse(tstream); - file.close(); +#endif - if(csv.csv().size() == 0) - return; + return csv.parse(rowFunction, tstream, count); +} - // Generate field names. These are either taken from the first CSV row or are generated in the format of "fieldXY" depending on the user input - sqlb::FieldVector fieldList; - CSVParser::TCSVResult::const_iterator itBegin = csv.csv().begin(); - if(ui->checkboxHeader->isChecked()) - { - ++itBegin; - for(QStringList::const_iterator it = csv.csv().at(0).begin(); - it != csv.csv().at(0).end(); - ++it) +sqlb::FieldVector ImportCsvDialog::generateFieldList(const QString& filename) const +{ + sqlb::FieldVector fieldList; // List of fields in the file + + // Parse the first couple of records of the CSV file and only analyse them + parseCSV(filename, [this, &fieldList](size_t rowNum, const CSVRow& rowData) -> bool { + // Has this row more columns than the previous one? Then add more fields to the field list as necessary. + for(size_t i=fieldList.size();icheckboxHeader->isChecked()) + { + // Take field name from CSV + fieldname = std::string(rowData.fields[i].data, rowData.fields[i].data_length); + } + + // If we don't have a field name by now, generate one + if(fieldname.empty()) + fieldname = "field" + std::to_string(i + 1); + + // Add field to the column list. For now we set the data type to nothing but this might be overwritten later in the automatic + // type detection code. + fieldList.emplace_back(fieldname, ""); + } + + // Try to find out a data type for each column. Skip the header row if there is one. + if(!ui->checkNoTypeDetection->isChecked() && !(rowNum == 0 && ui->checkboxHeader->isChecked())) + { + for(size_t i=0;i(rowData.fields[i].data_length)); + const QLocale &locale = ui->checkLocalConventions->isChecked() ? QLocale::system() : QLocale::c(); + + // Check if the content can be converted to an integer or to real + bool convert_to_integer, convert_to_real; + locale.toLongLong(content, &convert_to_integer); + locale.toDouble(content, &convert_to_real); + + // Set new data type. If we don't find any better data type, we fall back to the TEXT data type + std::string new_type = "TEXT"; + if(old_type == "INTEGER" && !convert_to_integer && convert_to_real) // So far it's integer, but now it's only convertible to float + new_type = "REAL"; + else if(old_type.empty() && convert_to_integer) // No type yet, but this bit is convertible to integer + new_type = "INTEGER"; + else if(old_type.empty() && convert_to_real) // No type yet and only convertible to float (less 'difficult' than integer) + new_type = "REAL"; + else if(old_type == "REAL" && convert_to_real) // It was float so far and still is + new_type = "INTEGER"; + else if(old_type == "INTEGER" && convert_to_integer) // It was integer so far and still is + new_type = "INTEGER"; + + fieldList.at(i).setType(new_type); + } + } + } + + // All good + return true; + }, 20); + + return fieldList; +} + +bool ImportCsvDialog::importCsv(const QString& fileName, const QString& name) +{ + // This function returns a boolean to indicate whether to continue or abort the import process. It's worth keeping in mind that + // this doesn't correlate 100% to this import being a success or not. The general rule is that if there was some internal error + // when writing to the database, we stop the entire import process. Also, if the user has clicked Cancel during the import of one + // file, we stop the entire import process, i.e. also the import of the remaining files. Furthermore, if the user clicks the Cancel + // button in a message box we (obviously) cancel the import process, too. In all other cases we return true to indicate that the import + // should continue. + +#ifdef CSV_BENCHMARK + // If benchmark mode is enabled start measuring the performance now + qint64 timesRowFunction = 0; + QElapsedTimer timer; + timer.start(); +#endif + + QString tableName; + + if (csvFilenames.size() > 1 && ui->checkBoxSeparateTables->isChecked()) { + if (name.isEmpty()) { + QFileInfo fileInfo(fileName); + tableName = fileInfo.baseName(); + } else { + tableName = name; } } else { - for(size_t i=0; i < csv.columns(); ++i) - fieldList.push_back(sqlb::FieldPtr(new sqlb::Field(QString("field%1").arg(i+1), ""))); + tableName = ui->editName->text(); } - // Show progress dialog - QProgressDialog progress(tr("Inserting data..."), tr("Cancel"), 0, csv.csv().size()); - progress.setWindowModality(Qt::ApplicationModal); - progress.show(); + // Analyse CSV file + sqlb::FieldVector fieldList = generateFieldList(fileName); + if(fieldList.size() == 0) + return true; // Are we importing into an existing table? bool importToExistingTable = false; - objectMap objects = pdb->getBrowsableObjects(); - for(objectMap::ConstIterator i=objects.begin();i!=objects.end();++i) + const sqlb::TablePtr tbl = pdb->getTableByName(sqlb::ObjectIdentifier("main", tableName.toStdString())); + if(tbl) { - if(i.value().gettype() == "table" && i.value().getname() == ui->editName->text()) + if(tbl->fields.size() != fieldList.size()) { - if((size_t)i.value().table.fields().size() != csv.columns()) + QMessageBox::warning(this, QApplication::applicationName(), + tr("There is already a table named '%1' and an import into an existing table is only possible if the number of columns match.").arg(tableName)); + return true; + } else { + // Only ask whether to import into any table if the 'Yes to All' button has not been clicked (yet) (empty string is included). + // Only ask whether to import into the existing table if the 'Yes' button has not been clicked (yet) for that table. + if(!dontAskForExistingTableAgain.contains("") && !dontAskForExistingTableAgain.contains(tableName)) { - QMessageBox::warning(this, QApplication::applicationName(), - tr("There is already a table of that name and an import into an existing table is only possible if the number of columns match.")); - return; - } else { - if(QMessageBox::question(this, QApplication::applicationName(), tr("There is already a table of that name. Do you want to import the data into it?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) - { - importToExistingTable = true; + int answer = QMessageBox::question(this, QApplication::applicationName(), + tr("There is already a table named '%1'. Do you want to import the data into it?").arg(tableName), + QMessageBox::Yes | QMessageBox::No | QMessageBox::YesAll | QMessageBox::Cancel, QMessageBox::No); + + // Stop now if the No button has been clicked + switch (answer) { + case QMessageBox::No: + return true; + + // Stop now if the Cancel button has been clicked. But also indicate, that the entire import process should be stopped. + case QMessageBox::Cancel: + return false; + + // If the 'Yes' button has been clicked, save the answer for that table for later + case QMessageBox::Yes: + dontAskForExistingTableAgain.append(tableName); + break; + // If the 'Yes to All' button has been clicked, save the answer for any future table name. An empty string is used in that case. + case QMessageBox::YesAll: + dontAskForExistingTableAgain.append(""); break; - } else { - return; } } + + // If we reached this point, this means that either the 'Yes' or the 'Yes all' button has been clicked or that no message box was shown at all + // because the 'Yes all' button has been clicked for a previous file + importToExistingTable = true; } } // Create a savepoint, so we can rollback in case of any errors during importing // db needs to be saved or an error will occur - QString restorepointName = QString("CSVIMPORT_%1").arg(QDateTime::currentMSecsSinceEpoch()); + std::string restorepointName = pdb->generateSavepointName("csvimport"); if(!pdb->setSavepoint(restorepointName)) - return rollback(this, pdb, progress, restorepointName, 0, tr("Creating restore point failed: %1").arg(pdb->lastErrorMessage)); - - // Create table - if(!importToExistingTable) { - if(!pdb->createTable(ui->editName->text(), fieldList)) - return rollback(this, pdb, progress, restorepointName, 0, tr("Creating the table failed: %1").arg(pdb->lastErrorMessage)); + rollback(this, pdb, nullptr, restorepointName, 0, tr("Creating restore point failed: %1").arg(pdb->lastError())); + return false; } - // now lets import all data, one row at a time - for(CSVParser::TCSVResult::const_iterator it = itBegin; - it != csv.csv().end(); - ++it) + // Create table + std::vector nullValues; + std::vector failOnMissingFieldList; + bool ignoreDefaults = ui->checkIgnoreDefaults->isChecked(); + bool failOnMissing = ui->checkFailOnMissing->isChecked(); + if(!importToExistingTable) { - QString sql = QString("INSERT INTO %1 VALUES(").arg(sqlb::escapeIdentifier(ui->editName->text())); - - QStringList insertlist; - for(QStringList::const_iterator jt = it->begin(); jt != it->end(); ++jt) + if(!pdb->createTable(sqlb::ObjectIdentifier("main", tableName.toStdString()), fieldList)) { - // need to mprintf here - char* formSQL = sqlite3_mprintf("%Q", (const char*)jt->toUtf8()); - insertlist << formSQL; - if(formSQL) - sqlite3_free(formSQL); + rollback(this, pdb, nullptr, restorepointName, 0, tr("Creating the table failed: %1").arg(pdb->lastError())); + return false; } - // add missing fields with empty values - for(unsigned int i = insertlist.size(); i < csv.columns(); ++i) + // If we're creating the table in this import session, don't ask the user if it's okay to import more data into it. It seems + // safe to just assume that's what they want. + dontAskForExistingTableAgain.append(tableName); + } else { + // Importing into an existing table. So find out something about it's structure. + + // Prepare the values for each table column that are to be inserted if the field in the CSV file is empty. Depending on the data type + // and the constraints of a field, we need to handle this case differently. + if(tbl) { - qWarning() << "ImportCSV" << tr("Missing field for record %1").arg(std::distance(itBegin, it) + 1); - insertlist << "NULL"; - } + for(const sqlb::Field& f : tbl->fields) + { + // For determining the value for empty fields we follow a set of rules - sql.append(insertlist.join(QChar(','))); - sql.append(");"); + // Normally we don't have to fail the import when importing an empty field. This last value of the vector + // is changed to true later if we actually do want to fail the import for this field. + failOnMissingFieldList.push_back(false); - if(!pdb->executeSQL(sql, false, false)) - return rollback(this, pdb, progress, restorepointName, std::distance(itBegin, it) + 1, tr("Inserting row failed: %1").arg(pdb->lastErrorMessage)); + // If a field has a default value, that gets priority over everything else. + // Exception: if the user wants to ignore default values we never use them. + if(!ignoreDefaults && !f.defaultValue().empty()) + { + nullValues.push_back(f.defaultValue().c_str()); + } else { + // If it has no default value, check if the field is NOT NULL + if(f.notnull()) + { + // The field is NOT NULL + + // If this is an integer column insert 0. Otherwise insert an empty string. + if(f.isInteger()) + nullValues.push_back("0"); + else + nullValues.push_back(""); + + // If the user wants to fail the import, remember this field + if(failOnMissing) + failOnMissingFieldList.back() = true; + } else { + // The field is not NOT NULL (stupid double negation here! NULL values are allowed in this case) + + // Just insert a NULL value + nullValues.push_back(QByteArray()); + } + } + } + } + } - // Update progress bar and check if cancel button was clicked - unsigned int prog = std::distance(csv.csv().begin(), it); - if(prog % 100 == 0) - progress.setValue(prog); - if(progress.wasCanceled()) - return rollback(this, pdb, progress, restorepointName, std::distance(itBegin, it) + 1, ""); + // Prepare the INSERT statement. The prepared statement can then be reused for each row to insert + std::string sQuery = "INSERT " + currentOnConflictStrategy() + " INTO " + sqlb::escapeIdentifier(tableName.toStdString()) + " VALUES("; + for(size_t i=1;i<=fieldList.size();i++) + sQuery += "?" + std::to_string(i) + ","; + sQuery.pop_back(); // Remove last comma + sQuery.append(")"); + sqlite3_stmt* stmt; + auto pDb = pdb->get(tr("importing CSV")); + if(sqlite3_prepare_v2(pDb.get(), sQuery.c_str(), static_cast(sQuery.size()), &stmt, nullptr) != SQLITE_OK) + { + rollback(this, pdb, nullptr, restorepointName, 0, tr("Could not prepare INSERT statement: %1").arg(pdb->lastError())); + return false; } - QApplication::restoreOverrideCursor(); // restore original cursor - QDialog::accept(); -} + // Parse entire file + size_t lastRowNum = 0; + CSVParser::ParserResult result = parseCSV(fileName, [&](size_t rowNum, const CSVRow& rowData) -> bool { + // Process the parser results row by row -void ImportCsvDialog::updatePreview() -{ - // Show/hide custom quote/separator input fields - ui->editCustomQuote->setVisible(ui->comboQuote->currentIndex() == ui->comboQuote->count()-1); - ui->editCustomSeparator->setVisible(ui->comboSeparator->currentIndex() == ui->comboSeparator->count()-1); - ui->editCustomEncoding->setVisible(ui->comboEncoding->currentIndex() == ui->comboEncoding->count()-1); +#ifdef CSV_BENCHMARK + qint64 timeAtStartOfRowFunction = timer.elapsed(); +#endif - // Get preview data - QFile file(csvFilename); - file.open(QIODevice::ReadOnly); + // Save row num for later use. This is used in the case of an error to tell the user in which row the error occurred + lastRowNum = rowNum; - CSVParser csv(ui->checkBoxTrimFields->isChecked(), currentSeparatorChar(), currentQuoteChar()); + // If this is the first row and we want to use the first row as table header, skip it now because this is the data import, not the header parsing + if(rowNum == 0 && ui->checkboxHeader->isChecked()) + return true; - QTextStream tstream(&file); - tstream.setCodec(currentEncoding().toUtf8()); - csv.parse(tstream, 20); - file.close(); + // Bind all values + for(size_t i=0;i i) + { + // Do we want to fail when trying to import an empty value into this field? Then exit with an error. + if(failOnMissingFieldList.at(i)) + return false; + + // This is an empty value. We'll need to look up how to handle it depending on the field to be inserted into. + const QByteArray& val = nullValues.at(i); + if(!val.isNull()) // No need to bind NULL values here as that is the default bound value in SQLite + sqlite3_bind_text(stmt, static_cast(i)+1, val, val.size(), SQLITE_STATIC); + // When importing into a new table, use the missing values setting directly + } else if(!importToExistingTable && rowData.fields[i].data_length == 0) { + // No need to bind NULL values here as that is the default bound value in SQLite + } else { + // This is a non-empty value, or we want to insert the empty string. Just add it to the statement. + bool convert_ok = false; + if(ui->checkLocalConventions->isChecked()) { + // Find the correct data type taking into account the locale. + QString content = QString::fromUtf8(rowData.fields[i].data, static_cast(rowData.fields[i].data_length)); + sqlite_int64 int64_value = QLocale::system().toLongLong(content, &convert_ok); + if(convert_ok) { + sqlite3_bind_int64(stmt, static_cast(i)+1, int64_value); + } else { + double value = QLocale::system().toDouble(content, &convert_ok); + if(convert_ok) + sqlite3_bind_double(stmt, static_cast(i)+1, value); + } + } - // Reset preview widget - ui->tablePreview->clear(); - ui->tablePreview->setColumnCount(csv.columns()); + if(!convert_ok) { + // If we don't find any better data type or we want SQLite to apply the type affinity + // (impossible when using local conventions), we fall back to the TEXT data type. + sqlite3_bind_text(stmt, static_cast(i)+1, rowData.fields[i].data, static_cast(rowData.fields[i].data_length), SQLITE_STATIC); + } + } + } - // Exit if there are no lines to preview at all - if(csv.columns() == 0) - return; + // Insert row + if(sqlite3_step(stmt) != SQLITE_DONE) + return false; - // Use first row as header if necessary - CSVParser::TCSVResult::const_iterator itBegin = csv.csv().begin(); - if(ui->checkboxHeader->isChecked()) - { - ui->tablePreview->setHorizontalHeaderLabels(*itBegin); - ++itBegin; - } + // Reset statement for next use. Also reset all bindings to NULL. This is important, so we don't need to bind missing columns or empty values in NULL + // columns manually. + sqlite3_reset(stmt); + sqlite3_clear_bindings(stmt); + +#ifdef CSV_BENCHMARK + timesRowFunction += timer.elapsed() - timeAtStartOfRowFunction; +#endif - // Fill data section - ui->tablePreview->setRowCount(std::distance(itBegin, csv.csv().end())); + return true; + }); - for(CSVParser::TCSVResult::const_iterator ct = itBegin; - ct != csv.csv().end(); - ++ct) + // Success? + if(result != CSVParser::ParserResult::ParserResultSuccess) { - for(QStringList::const_iterator it = ct->begin(); it != ct->end(); ++it) + // Some error occurred or the user cancelled the action + + // Rollback the entire import. If the action was cancelled, don't show an error message. If it errored, show an error message. + QString message; + if(result == CSVParser::ParserResult::ParserResultError) { - int rowNum = std::distance(itBegin, ct); - if(it == ct->begin()) - { - ui->tablePreview->setVerticalHeaderItem( - rowNum, - new QTableWidgetItem(QString::number(rowNum + 1))); - } - ui->tablePreview->setItem( - rowNum, - std::distance(ct->begin(), it), - new QTableWidgetItem(*it)); + QString error(sqlite3_errmsg(pDb.get())); + message = tr("Inserting row failed: %1").arg(error); + } else if(result == CSVParser::ParserResult::ParserResultUnexpectedEOF) { + message = tr("Unexpected end of file. Please make sure that you have configured the correct quote characters and " + "the file is not malformed."); } + + sqlite3_finalize(stmt); + rollback(this, pdb, &pDb, restorepointName, lastRowNum, message); + return false; } -} -void ImportCsvDialog::checkInput() -{ - bool valid = true; - if(ui->editName->text().isEmpty()) - valid = false; + // Clean up prepared statement + sqlite3_finalize(stmt); + +#ifdef CSV_BENCHMARK + QMessageBox::information(this, qApp->applicationName(), + tr("Importing the file '%1' took %2ms. Of this %3ms were spent in the row function.") + .arg(fileName) + .arg(timer.elapsed()) + .arg(timesRowFunction)); +#endif - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid); + return true; } -void ImportCsvDialog::setQuoteChar(const QChar& c) +void ImportCsvDialog::setQuoteChar(QChar c) { QComboBox* combo = ui->comboQuote; - int index = combo->findText(c); + int index = combo->findText(QString(c)); + ui->spinBoxQuote->setValue(c.unicode()); if(index == -1) { - combo->setCurrentIndex(combo->count()); - ui->editCustomQuote->setText(c); + if(c.isPrint()) + { + combo->setCurrentIndex(combo->count() - OtherPrintable); + ui->editCustomQuote->setText(QString(c)); + } + else + { + combo->setCurrentIndex(combo->count() - OtherCode); + } } else { @@ -342,27 +775,38 @@ void ImportCsvDialog::setQuoteChar(const QChar& c) } } -char ImportCsvDialog::currentQuoteChar() const +QChar ImportCsvDialog::currentQuoteChar() const { - // The last item in the combobox is the 'Other' item; if it is selected return the text of the line edit field instead - if(ui->comboQuote->currentIndex() == ui->comboQuote->count()-1) - return ui->editCustomQuote->text().length() ? ui->editCustomQuote->text().at(0).toLatin1() : 0; + QString value; - if(ui->comboQuote->currentText().length()) - return ui->comboQuote->currentText().at(0).toLatin1(); - else - return 0; + // The last item in the combobox is the 'Other' item; if it is selected return the text of the line edit field instead + if(ui->comboQuote->currentIndex() == ui->comboQuote->count() - OtherPrintable) + value = ui->editCustomQuote->text().length() ? ui->editCustomQuote->text() : ""; + else if(ui->comboQuote->currentIndex() == ui->comboQuote->count() - OtherCode) + value = QString(QChar(ui->spinBoxQuote->value())); + else if(ui->comboQuote->currentText().length()) + value = ui->comboQuote->currentText(); + + return value.size() ? value.at(0) : QChar(); } -void ImportCsvDialog::setSeparatorChar(const QChar& c) +void ImportCsvDialog::setSeparatorChar(QChar c) { QComboBox* combo = ui->comboSeparator; QString sText = c == '\t' ? QString("Tab") : QString(c); int index = combo->findText(sText); + ui->spinBoxSeparator->setValue(c.unicode()); if(index == -1) { - combo->setCurrentIndex(combo->count()); - ui->editCustomSeparator->setText(c); + if(c.isPrint()) + { + combo->setCurrentIndex(combo->count() - OtherPrintable); + ui->editCustomSeparator->setText(QString(c)); + } + else + { + combo->setCurrentIndex(combo->count() - OtherCode); + } } else { @@ -370,13 +814,20 @@ void ImportCsvDialog::setSeparatorChar(const QChar& c) } } -char ImportCsvDialog::currentSeparatorChar() const +QChar ImportCsvDialog::currentSeparatorChar() const { - // The last item in the combobox is the 'Other' item; if it is selected return the text of the line edit field instead - if(ui->comboSeparator->currentIndex() == ui->comboSeparator->count()-1) - return ui->editCustomSeparator->text().length() ? ui->editCustomSeparator->text().at(0).toLatin1() : 0; + QString value; + + // The last options in the combobox are the 'Other (*)' items; + // if one of them is selected return the text or code of the corresponding field instead + if(ui->comboSeparator->currentIndex() == ui->comboSeparator->count() - OtherPrintable) + value = ui->editCustomSeparator->text().length() ? ui->editCustomSeparator->text() : ""; + else if(ui->comboSeparator->currentIndex() == ui->comboSeparator->count() - OtherCode) + value = QString(QChar(ui->spinBoxSeparator->value())); + else + value = ui->comboSeparator->currentText() == tr("Tab") ? "\t" : ui->comboSeparator->currentText(); - return ui->comboSeparator->currentText() == tr("Tab") ? '\t' : ui->comboSeparator->currentText().at(0).toLatin1(); + return value.size() ? value.at(0) : QChar(); } void ImportCsvDialog::setEncoding(const QString& sEnc) @@ -385,7 +836,7 @@ void ImportCsvDialog::setEncoding(const QString& sEnc) int index = combo->findText(sEnc); if(index == -1) { - combo->setCurrentIndex(combo->count()); + combo->setCurrentIndex(combo->count() - 1); ui->editCustomEncoding->setText(sEnc); } else @@ -402,3 +853,44 @@ QString ImportCsvDialog::currentEncoding() const else return ui->comboEncoding->currentText(); } + +std::string ImportCsvDialog::currentOnConflictStrategy() const +{ + switch(ui->comboOnConflictStrategy->currentIndex()) + { + case 1: + return "OR IGNORE"; + case 2: + return "OR REPLACE"; + default: + return {}; + } +} + +void ImportCsvDialog::toggleAdvancedSection(bool show) +{ + ui->labelNoTypeDetection->setVisible(show); + ui->checkNoTypeDetection->setVisible(show); + ui->labelLocalConventions->setVisible(show); + ui->checkLocalConventions->setVisible(show); + ui->labelFailOnMissing->setVisible(show); + ui->checkFailOnMissing->setVisible(show); + ui->labelIgnoreDefaults->setVisible(show); + ui->checkIgnoreDefaults->setVisible(show); + ui->labelOnConflictStrategy->setVisible(show); + ui->comboOnConflictStrategy->setVisible(show); +} + +char32_t ImportCsvDialog::toUtf8(const QString& s) const +{ + if(s.isEmpty()) + return 0; + + QByteArray ba = s.toUtf8(); + + char32_t result = 0; + for(QByteArray::size_type i=std::min(ba.size()-1,QByteArray::size_type(3));i>=0;i--) + result = (result << 8) + static_cast(ba.at(i)); + + return result; +} diff --git a/src/ImportCsvDialog.h b/src/ImportCsvDialog.h index a03eb7537..fcc21c555 100644 --- a/src/ImportCsvDialog.h +++ b/src/ImportCsvDialog.h @@ -1,7 +1,11 @@ #ifndef IMPORTCSVDIALOG_H #define IMPORTCSVDIALOG_H +#include "csvparser.h" +#include "sql/sqlitetypes.h" + #include +#include class DBBrowserDB; class QCompleter; @@ -15,28 +19,51 @@ class ImportCsvDialog : public QDialog Q_OBJECT public: - explicit ImportCsvDialog(const QString& filename, DBBrowserDB* db, QWidget* parent = 0); - ~ImportCsvDialog(); + explicit ImportCsvDialog(const std::vector& filenames, DBBrowserDB* db, QWidget* parent = nullptr, const QString& table = QString()); + ~ImportCsvDialog() override; private slots: - virtual void accept(); - virtual void updatePreview(); - virtual void checkInput(); + void accept() override; + void updatePreview(); + void checkInput(); + void selectFiles(); + void updateSelectedFilePreview(); + void updateSelection(bool); + void matchSimilar(); + void toggleAdvancedSection(bool show); private: + + // Positions for combos starting at the bottom + enum {OtherCode = 1, + OtherPrintable = 2}; + Ui::ImportCsvDialog* ui; - QString csvFilename; + std::vector csvFilenames; + QString selectedFile; DBBrowserDB* pdb; QCompleter* encodingCompleter; + QStringList dontAskForExistingTableAgain; + + CSVParser::ParserResult parseCSV(const QString& fileName, std::function rowFunction, size_t count = 0) const; + sqlb::FieldVector generateFieldList(const QString& filename) const; - void setQuoteChar(const QChar& c); - char currentQuoteChar() const; + bool importCsv(const QString& f, const QString& n = QString()); - void setSeparatorChar(const QChar& c); - char currentSeparatorChar() const; + void setQuoteChar(QChar c); + QChar currentQuoteChar() const; + + void setSeparatorChar(QChar c); + QChar currentSeparatorChar() const; void setEncoding(const QString& sEnc); QString currentEncoding() const; + + std::string currentOnConflictStrategy() const; + + char32_t toUtf8(const QString& s) const; + + static QChar getSettingsChar(const std::string& group, const std::string& name); }; #endif diff --git a/src/ImportCsvDialog.ui b/src/ImportCsvDialog.ui index 5fe84eb13..a711aa2a1 100644 --- a/src/ImportCsvDialog.ui +++ b/src/ImportCsvDialog.ui @@ -6,14 +6,14 @@ 0 0 - 738 - 490 + 788 + 717 Import CSV file - + @@ -22,7 +22,7 @@ - &Table name + Table na&me editName @@ -49,7 +49,7 @@ - + Field &separator @@ -59,7 +59,7 @@ - + @@ -85,7 +85,12 @@ - Other + Other (printable) + + + + + Other (code) @@ -97,6 +102,13 @@ + + + + 1114112 + + + @@ -112,7 +124,7 @@ - + &Quote character @@ -122,7 +134,7 @@ - + @@ -143,7 +155,12 @@ - Other + Other (printable) + + + + + Other (code) @@ -155,6 +172,13 @@ + + + + 1114112 + + + @@ -170,7 +194,7 @@ - + &Encoding @@ -180,7 +204,7 @@ - + @@ -224,14 +248,17 @@ - + Trim fields? + + checkBoxTrimFields + - + @@ -241,10 +268,220 @@ + + + + Separate tables + + + checkBoxSeparateTables + + + + + + + + + + + + + + Advanced + + + + :/icons/down:/icons/down + + + true + + + + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + + + + + + + Ignore default &values + + + checkIgnoreDefaults + + + + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + + + + + + + Fail on missing values + + + checkFailOnMissing + + + + + + + Disable data type detection + + + checkNoTypeDetection + + + + + + + Disable the automatic data type detection when creating a new table. + + + + + + + Use local number conventions + + + checkLocalConventions + + + + + + + Use decimal and thousands separators according to the system locale. + + + + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + + + + Abort import + + + + + Ignore row + + + + + Replace existing row + + + + + + + + Conflict strategy + + + comboOnConflictStrategy + + + - + + + Qt::Vertical + + + false + + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 7 + + + QLayout::SetDefaultConstraint + + + 0 + + + + + Deselect All + + + true + + + true + + + + + + + false + + + Match Similar + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + @@ -267,39 +504,132 @@ editCustomQuote comboEncoding editCustomEncoding + checkBoxTrimFields + checkBoxSeparateTables + buttonAdvanced + checkIgnoreDefaults + checkNoTypeDetection + checkLocalConventions + checkFailOnMissing + comboOnConflictStrategy + filePicker + toggleSelected + matchSimilar tablePreview - + + + - buttonBox - accepted() + comboSeparator + currentIndexChanged(int) ImportCsvDialog - accept() + updatePreview() - 261 - 480 + 245 + 92 - 157 - 274 + 445 + 64 - buttonBox - rejected() + editName + textChanged(QString) ImportCsvDialog - reject() + checkInput() - 329 - 480 + 609 + 13 - 286 - 274 + 631 + 45 + + + + + editCustomSeparator + textChanged(QString) + ImportCsvDialog + updatePreview() + + + 511 + 92 + + + 577 + 76 + + + + + editCustomQuote + textChanged(QString) + ImportCsvDialog + updatePreview() + + + 511 + 126 + + + 530 + 90 + + + + + editCustomEncoding + textChanged(QString) + ImportCsvDialog + updatePreview() + + + 524 + 160 + + + 540 + 133 + + + + + checkBoxTrimFields + toggled(bool) + ImportCsvDialog + updatePreview() + + + 192 + 182 + + + 368 + 244 + + + + + comboEncoding + currentIndexChanged(int) + ImportCsvDialog + updatePreview() + + + 271 + 160 + + + 572 + 121 @@ -310,8 +640,8 @@ updatePreview() - 187 - 46 + 192 + 56 354 @@ -320,18 +650,18 @@ - comboSeparator - currentIndexChanged(int) + toggleSelected + toggled(bool) ImportCsvDialog - updatePreview() + updateSelection(bool) - 216 - 71 + 777 + 385 - 445 - 64 + 368 + 244 @@ -342,8 +672,8 @@ updatePreview() - 224 - 100 + 245 + 126 350 @@ -352,98 +682,114 @@ - editName - textChanged(QString) + buttonBox + accepted() ImportCsvDialog - checkInput() + accept() - 609 - 13 + 281 + 707 - 631 - 45 + 157 + 274 - editCustomSeparator - textChanged(QString) + buttonBox + rejected() ImportCsvDialog - updatePreview() + reject() - 325 - 70 + 349 + 707 - 577 - 76 + 286 + 274 - editCustomQuote - textChanged(QString) + checkBoxSeparateTables + toggled(bool) ImportCsvDialog - updatePreview() + checkInput() - 467 - 101 + 192 + 206 - 530 - 90 + 368 + 244 - comboEncoding - currentIndexChanged(int) + matchSimilar + pressed() ImportCsvDialog - updatePreview() + matchSimilar() - 198 - 131 + 777 + 418 - 572 - 121 + 368 + 244 - editCustomEncoding - textChanged(QString) + buttonAdvanced + toggled(bool) + ImportCsvDialog + toggleAdvancedSection(bool) + + + 265 + 241 + + + 393 + 358 + + + + + spinBoxQuote + valueChanged(int) ImportCsvDialog updatePreview() - 378 - 132 + 529 + 111 - 540 - 133 + 393 + 358 - checkBoxTrimFields - toggled(bool) + spinBoxSeparator + valueChanged(int) ImportCsvDialog updatePreview() - 191 - 189 + 529 + 77 - 368 - 244 + 393 + 358 @@ -451,5 +797,8 @@ updatePreview() checkInput() + updateSelection(bool) + matchSimilar() + toggleAdvancedSection(bool) diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index e988ed401..39804554c 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -1,11 +1,15 @@ #include "MainWindow.h" +#include "sql/ObjectIdentifier.h" +#include "sql/sqlitetypes.h" #include "ui_MainWindow.h" -#include "CreateIndexDialog.h" +#include "Application.h" +#include "EditIndexDialog.h" #include "AboutDialog.h" #include "EditTableDialog.h" #include "ImportCsvDialog.h" -#include "ExportCsvDialog.h" +#include "ExportDataDialog.h" +#include "Settings.h" #include "PreferencesDialog.h" #include "EditDialog.h" #include "sqlitetablemodel.h" @@ -18,25 +22,24 @@ #include "ExportSqlDialog.h" #include "SqlUiLexer.h" #include "FileDialog.h" -#include "ColumnDisplayFormatDialog.h" - +#include "FindReplaceDialog.h" +#include "RunSql.h" +#include "ExtendedTableWidget.h" +#include "Data.h" +#include "RemoteNetwork.h" +#include "TableBrowser.h" +#include "TableBrowserDock.h" + +#include #include -#include +#include #include #include #include -#include -#include +#include #include #include -#include -#include -#include -#include -#include -#include #include -#include #include #include #include @@ -45,107 +48,258 @@ #include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_MACX //Needed only on macOS + #include +#endif + +#include + +int MainWindow::MaxRecentFiles; MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow), - m_browseTableModel(new SqliteTableModel(this, &db, PreferencesDialog::getSettingsValue("db", "prefetchsize").toInt())), - m_currentTabTableModel(m_browseTableModel), - editWin(new EditDialog(this)), - editDock(new EditDialog(this, true)), - gotoValidator(new QIntValidator(0, 0, this)) + db(), + m_currentTabTableModel(nullptr), + editDock(new EditDialog(this)), + plotDock(new PlotDock(this)), + currentTableBrowser(nullptr), + findReplaceDialog(new FindReplaceDialog(this)), + execute_sql_worker(nullptr), + isProjectModified(false) { ui->setupUi(this); init(); activateFields(false); updateRecentFileActions(); + + if (!Settings::getValue("tmp", "fileWillBeOpenedFromCLI").toBool() && + Settings::getValue("General", "autoLoadLastDBFileAtStartup").toBool()) { + recentFileActs[0]->trigger(); + } } MainWindow::~MainWindow() { - delete gotoValidator; + delete dbSelected; + delete dockDbSelected; delete ui; } void MainWindow::init() { - // Connect SQL logging and database state setting to main window - connect(&db, SIGNAL(dbChanged(bool)), this, SLOT(dbState(bool))); - connect(&db, SIGNAL(sqlExecuted(QString, int)), this, SLOT(logSql(QString,int))); + // Load window settings + tabifyDockWidget(ui->dockLog, ui->dockPlot); + tabifyDockWidget(ui->dockLog, ui->dockSchema); + +#ifdef Q_OS_MACX + // Add OpenGL Context for macOS + QOpenGLWidget *ogl = new QOpenGLWidget(this); + ui->verticalLayout->addWidget(ogl); + ogl->setHidden(true); +#endif + + // Automatic update check +#ifdef CHECKNEWVERSION + // Check for a new version if automatic update check aren't disabled in the settings dialog + if(Settings::getValue("checkversion", "enabled").toBool()) + checkNewVersion(true); +#endif - // Set the validator for the goto line edit - ui->editGoto->setValidator(gotoValidator); + // create facade objects to dbTreeWidgets + dbSelected = new DbStructureQItemViewFacade(*ui->dbTreeWidget); + dockDbSelected = new DbStructureQItemViewFacade(*ui->treeSchemaDock); - // Set up DB models - ui->dataTable->setModel(m_browseTableModel); + // Connect SQL logging and database state setting to main window + connect(&db, &DBBrowserDB::dbChanged, this, &MainWindow::dbState, Qt::QueuedConnection); + connect(&db, &DBBrowserDB::sqlExecuted, this, &MainWindow::logSql, Qt::QueuedConnection); + connect(&db, &DBBrowserDB::requestCollation, this, &MainWindow::requestCollation); // Set up DB structure tab - dbStructureModel = new DbStructureModel(ui->dbTreeWidget); + dbStructureModel = new DbStructureModel(db, this, + Settings::getValue("SchemaDock", "dropSelectQuery").toBool(), + Settings::getValue("SchemaDock", "dropInsert").toBool()); + connect(&db, &DBBrowserDB::structureUpdated, this, [this]() { + std::vector old_tables; + for(const auto& d : allTableBrowserDocks()) + old_tables.push_back(d->tableBrowser()->currentlyBrowsedTableName()); + + dbStructureModel->reloadData(); + + populateStructure(old_tables); + }); ui->dbTreeWidget->setModel(dbStructureModel); - ui->dbTreeWidget->setColumnHidden(1, true); - ui->dbTreeWidget->setColumnWidth(0, 300); + ui->dbTreeWidget->setColumnWidth(DbStructureModel::ColumnName, 300); + ui->dbTreeWidget->setColumnHidden(DbStructureModel::ColumnObjectType, true); + ui->dbTreeWidget->setColumnHidden(DbStructureModel::ColumnSchema, true); // Set up DB schema dock ui->treeSchemaDock->setModel(dbStructureModel); - ui->treeSchemaDock->setColumnHidden(1, true); - ui->treeSchemaDock->setColumnWidth(0, 300); + ui->treeSchemaDock->setColumnHidden(DbStructureModel::ColumnObjectType, true); + ui->treeSchemaDock->setColumnHidden(DbStructureModel::ColumnSchema, true); + + // Create initial table browser tab + ui->tabBrowsers->setWindowFlags(Qt::Widget); + ui->tabBrowsers->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); + newTableBrowserTab(); + + // Create docks + ui->dockEdit->setWidget(editDock); + ui->dockPlot->setWidget(plotDock); + + // Set up edit dock + editDock->setReadOnly(true); + + // Restore window geometry + restoreGeometry(Settings::getValue("MainWindow", "geometry").toByteArray()); - // Edit dock - ui->dockEditWindow->setWidget(editDock); - ui->dockEditWindow->hide(); // Hidden by default + // Save default and restore window state + defaultWindowState = saveState(); + restoreState(Settings::getValue("MainWindow", "windowState").toByteArray()); + + // Save default and restore open tab order if the openTabs setting is saved. + defaultOpenTabs = saveOpenTabs(); + restoreOpenTabs(Settings::getValue("MainWindow", "openTabs").toString()); + + // Restore dock state settings + ui->comboLogSubmittedBy->setCurrentIndex(ui->comboLogSubmittedBy->findText(Settings::getValue("SQLLogDock", "Log").toString())); // Add keyboard shortcuts - QList shortcuts = ui->actionExecuteSql->shortcuts(); - shortcuts.push_back(QKeySequence(tr("Ctrl+Return"))); - ui->actionExecuteSql->setShortcuts(shortcuts); + QShortcut* shortcutBrowseRefreshF5 = new QShortcut(QKeySequence("F5"), this); + connect(shortcutBrowseRefreshF5, &QShortcut::activated, this, &MainWindow::refresh); + QShortcut* shortcutBrowseRefreshCtrlR = new QShortcut(QKeySequence("Ctrl+R"), this); + connect(shortcutBrowseRefreshCtrlR, &QShortcut::activated, this, &MainWindow::refresh); + QShortcut* shortcutBrowseRefreshCtrlEnter = new QShortcut(QKeySequence("Ctrl+Enter"), this); + connect(shortcutBrowseRefreshCtrlEnter, &QShortcut::activated, this, &MainWindow::refresh); + + // Add print shortcut for the DB Structure tab (dbTreeWidget) with context to the widget, so other print shortcuts aren't eclipsed. + QShortcut* shortcutPrint = new QShortcut(QKeySequence(QKeySequence::Print), ui->dbTreeWidget, nullptr, nullptr, Qt::WidgetShortcut); + connect(shortcutPrint, &QShortcut::activated, this, &MainWindow::printDbStructure); + + QShortcut* closeTabShortcut = new QShortcut(tr("Ctrl+W"), ui->tabSqlAreas, nullptr, nullptr, Qt::WidgetWithChildrenShortcut); + connect(closeTabShortcut, &QShortcut::activated, this, [this]() { + if(ui->tabSqlAreas->currentIndex() >= 0) + closeSqlTab(ui->tabSqlAreas->currentIndex()); + }); + + // Shortcuts for advancing and going back in the SQL Execution area tabs, independently of the widget which has focus. + // This emulates the shortcuts provided by QTabWidget. + QShortcut* shortcutNextTab = new QShortcut(QKeySequence(tr("Ctrl+Tab")), ui->tabSqlAreas, nullptr, nullptr, Qt::WidgetWithChildrenShortcut); + connect(shortcutNextTab, &QShortcut::activated, this, [this]() { + if(ui->tabSqlAreas->currentIndex() == ui->tabSqlAreas->count() - 1) + ui->tabSqlAreas->setCurrentIndex(0); + else + ui->tabSqlAreas->setCurrentIndex(ui->tabSqlAreas->currentIndex() + 1); + focusSqlEditor(); + }); + + QShortcut* shortcutPreviousTab = new QShortcut(QKeySequence(tr("Ctrl+Shift+Tab")), ui->tabSqlAreas, nullptr, nullptr, Qt::WidgetWithChildrenShortcut); + connect(shortcutPreviousTab, &QShortcut::activated, this, [this]() { + if(ui->tabSqlAreas->currentIndex() == 0) + ui->tabSqlAreas->setCurrentIndex(ui->tabSqlAreas->count() - 1); + else + ui->tabSqlAreas->setCurrentIndex(ui->tabSqlAreas->currentIndex() - 1); + focusSqlEditor(); + }); - QShortcut* shortcutBrowseRefresh = new QShortcut(QKeySequence("Ctrl+R"), this); - connect(shortcutBrowseRefresh, SIGNAL(activated()), ui->buttonRefresh, SLOT(click())); + // Get MaxRecentFiles value from QSettings. + MaxRecentFiles = Settings::getValue("General", "maxRecentFiles").toInt(); + recentFileActs.resize(MaxRecentFiles); // Create the actions for the recently opened dbs list for(int i = 0; i < MaxRecentFiles; ++i) { recentFileActs[i] = new QAction(this); recentFileActs[i]->setVisible(false); - connect(recentFileActs[i], SIGNAL(triggered()), this, SLOT(openRecentFile())); + connect(recentFileActs[i], &QAction::triggered, this, &MainWindow::openRecentFile); } for(int i = 0; i < MaxRecentFiles; ++i) - ui->fileMenu->insertAction(ui->fileExitAction, recentFileActs[i]); - recentSeparatorAct = ui->fileMenu->insertSeparator(ui->fileExitAction); + ui->fileRecentFiles->insertAction(ui->fileExitAction, recentFileActs[i]); + + recentSeparatorAct = ui->fileRecentFiles->insertSeparator(ui->fileExitAction); + optionToAutoLoadLastDBFileAtStartup = ui->fileRecentFiles->addAction(tr("Automatically load the last opened DB file at startup")); + optionToAutoLoadLastDBFileAtStartup->setCheckable(true); + optionToAutoLoadLastDBFileAtStartup->setChecked(Settings::getValue("General", "autoLoadLastDBFileAtStartup").toBool()); + clearRecentFilesAction = ui->fileRecentFiles->addAction(tr("Clear List")); + ui->fileRecentFiles->insertAction(ui->fileExitAction, clearRecentFilesAction); + connect(optionToAutoLoadLastDBFileAtStartup, &QAction::triggered, this, &MainWindow::toggleAutoLoadLastDBFileAtStartupOption); + connect(clearRecentFilesAction, &QAction::triggered, this, &MainWindow::clearRecentFiles); // Create popup menus popupTableMenu = new QMenu(this); popupTableMenu->addAction(ui->actionEditBrowseTable); - popupTableMenu->addAction(ui->editModifyTableAction); + popupTableMenu->addAction(ui->editModifyObjectAction); popupTableMenu->addAction(ui->editDeleteObjectAction); + popupTableMenu->addAction(ui->fileDetachAction); popupTableMenu->addSeparator(); popupTableMenu->addAction(ui->actionEditCopyCreateStatement); popupTableMenu->addAction(ui->actionExportCsvPopup); + popupSchemaDockMenu = new QMenu(this); + popupSchemaDockMenu->addAction(ui->actionPopupSchemaDockBrowseTable); + popupSchemaDockMenu->addAction(ui->actionPopupSchemaDockDetachDatabase); + popupSchemaDockMenu->addSeparator(); + + auto dropSchemaDockMenu = new QMenu(popupSchemaDockMenu); + popupSchemaDockMenu->addMenu(dropSchemaDockMenu); + dropSchemaDockMenu->setTitle(tr("Clipboard/Drop Options")); + dropSchemaDockMenu->setStatusTip(tr("Options for Drag && Drop and Copy to Clipboard operations.")); + dropSchemaDockMenu->addAction(ui->actionDropSelectQueryCheck); + dropSchemaDockMenu->addAction(ui->actionDropInsertCheck); + dropSchemaDockMenu->addAction(ui->actionDropNamesCheck); + + QActionGroup* dropGroup = new QActionGroup(dropSchemaDockMenu); + dropGroup->addAction(ui->actionDropSelectQueryCheck); + dropGroup->addAction(ui->actionDropInsertCheck); + dropGroup->addAction(ui->actionDropNamesCheck); + + dropSchemaDockMenu->addSeparator(); + dropSchemaDockMenu->addAction(ui->actionDropQualifiedCheck); + dropSchemaDockMenu->addAction(ui->actionEnquoteNamesCheck); + + popupSchemaDockMenu->addAction(ui->actionCopyInSchema); + connect(ui->actionCopyInSchema, &QAction::triggered, this, [=]() { + dbStructureModel->copy(ui->treeSchemaDock->selectionModel()->selectedIndexes()); + }); + auto copyShortcut = new QShortcut(QKeySequence::Copy, ui->treeSchemaDock, nullptr, nullptr, Qt::WidgetShortcut); + connect(copyShortcut, &QShortcut::activated, this, [=]() { + dbStructureModel->copy(ui->treeSchemaDock->selectionModel()->selectedIndexes()); + }); + + popupOpenDbMenu = new QMenu(this); + popupOpenDbMenu->addAction(ui->fileOpenAction); + popupOpenDbMenu->addAction(ui->fileOpenReadOnlyAction); + ui->fileOpenActionPopup->setMenu(popupOpenDbMenu); + popupSaveSqlFileMenu = new QMenu(this); popupSaveSqlFileMenu->addAction(ui->actionSqlSaveFile); popupSaveSqlFileMenu->addAction(ui->actionSqlSaveFileAs); ui->actionSqlSaveFilePopup->setMenu(popupSaveSqlFileMenu); - popupBrowseDataHeaderMenu = new QMenu(this); - popupBrowseDataHeaderMenu->addAction(ui->actionShowRowidColumn); - popupBrowseDataHeaderMenu->addAction(ui->actionBrowseTableEditDisplayFormat); - popupBrowseDataHeaderMenu->addAction(ui->actionSetTableEncoding); - popupBrowseDataHeaderMenu->addSeparator(); - popupBrowseDataHeaderMenu->addAction(ui->actionSetAllTablesEncoding); + popupSaveSqlResultsMenu = new QMenu(this); + popupSaveSqlResultsMenu->addAction(ui->actionSqlResultsExportCsv); + popupSaveSqlResultsMenu->addAction(ui->actionSqlResultsExportJson); + popupSaveSqlResultsMenu->addAction(ui->actionSqlResultsSaveAsView); + ui->actionSqlResultsSave->setMenu(popupSaveSqlResultsMenu); + qobject_cast(ui->toolbarSql->widgetForAction(ui->actionSqlResultsSave))->setPopupMode(QToolButton::InstantPopup); // Add menu item for log dock ui->viewMenu->insertAction(ui->viewDBToolbarAction, ui->dockLog->toggleViewAction()); ui->viewMenu->actions().at(0)->setShortcut(QKeySequence(tr("Ctrl+L"))); ui->viewMenu->actions().at(0)->setIcon(QIcon(":/icons/log_dock")); - ui->viewDBToolbarAction->setChecked(!ui->toolbarDB->isHidden()); // Add menu item for plot dock ui->viewMenu->insertAction(ui->viewDBToolbarAction, ui->dockPlot->toggleViewAction()); - QList plotkeyseqlist; - plotkeyseqlist << QKeySequence(tr("Ctrl+P")) << QKeySequence(tr("Ctrl+D")); - ui->viewMenu->actions().at(1)->setShortcuts(plotkeyseqlist); + ui->viewMenu->actions().at(1)->setShortcut(QKeySequence(tr("Ctrl+D"))); ui->viewMenu->actions().at(1)->setIcon(QIcon(":/icons/log_dock")); // Add menu item for schema dock @@ -154,10 +308,94 @@ void MainWindow::init() ui->viewMenu->actions().at(2)->setIcon(QIcon(":/icons/log_dock")); // Add menu item for edit dock - ui->viewMenu->insertAction(ui->viewDBToolbarAction, ui->dockEditWindow->toggleViewAction()); + ui->viewMenu->insertAction(ui->viewDBToolbarAction, ui->dockEdit->toggleViewAction()); + ui->viewMenu->actions().at(3)->setShortcut(QKeySequence(tr("Ctrl+E"))); ui->viewMenu->actions().at(3)->setIcon(QIcon(":/icons/log_dock")); + // Set checked state if toolbar is visible + ui->viewDBToolbarAction->setChecked(!ui->toolbarDB->isHidden()); + ui->viewExtraDBToolbarAction->setChecked(!ui->toolbarExtraDB->isHidden()); + ui->viewProjectToolbarAction->setChecked(!ui->toolbarProject->isHidden()); + + // Add separator between docks and toolbars + ui->viewMenu->insertSeparator(ui->viewDBToolbarAction); + + // Connect the tabCloseRequested to the actual closeTab function. + // This must be done before the connections for checking the actions in the View menu so + // they are updated accordingly. + connect(ui->mainTab, &QTabWidget::tabCloseRequested, this, &MainWindow::closeTab); + + // Add entries for toggling the visibility of main tabs + for (QWidget* widget : {ui->structure, ui->browser, ui->pragmas, ui->query}) { + QAction* action = ui->viewMenu->addAction(QIcon(":/icons/open_sql"), widget->accessibleName()); + action->setObjectName(widget->accessibleName()); + action->setCheckable(true); + action->setChecked(ui->mainTab->indexOf(widget) != -1); + connect(action, &QAction::toggled, this, [=](bool show) { toggleTabVisible(widget, show); }); + // Connect tabCloseRequested for setting checked the appropriate menu entry. + // Note these are called after the actual tab is closed only because they are connected + // after connecting closeTab. + connect(ui->mainTab, &QTabWidget::tabCloseRequested, this, [=](int /*index*/) { + action->setChecked(ui->mainTab->indexOf(widget) != -1); + }); + } + + ui->viewMenu->addSeparator(); + + QMenu* layoutMenu = new QMenu(tr("Window Layout"), this); + ui->viewMenu->addMenu(layoutMenu); + + QAction* resetLayoutAction = layoutMenu->addAction(tr("Reset Window Layout")); + resetLayoutAction->setShortcut(QKeySequence(tr("Ctrl+0"))); + connect(resetLayoutAction, &QAction::triggered, this, [=]() { + restoreState(defaultWindowState); + restoreOpenTabs(defaultOpenTabs); + ui->viewDBToolbarAction->setChecked(!ui->toolbarDB->isHidden()); + ui->viewExtraDBToolbarAction->setChecked(!ui->toolbarExtraDB->isHidden()); + ui->viewProjectToolbarAction->setChecked(!ui->toolbarProject->isHidden()); + }); + QAction* simplifyLayoutAction = layoutMenu->addAction(tr("Simplify Window Layout")); + simplifyLayoutAction->setShortcut(QKeySequence(tr("Alt+Shift+0"))); + connect(simplifyLayoutAction, &QAction::triggered, this, [=]() { + ui->viewMenu->findChild(ui->pragmas->accessibleName())->activate(QAction::Trigger); + ui->dockLog->hide(); + ui->dockPlot->hide(); + ui->dockSchema->hide(); + ui->dockEdit->hide(); + }); + QAction* atBottomLayoutAction = layoutMenu->addAction(tr("Dock Windows at Bottom")); + connect(atBottomLayoutAction, &QAction::triggered, this, [=]() { + moveDocksTo(Qt::BottomDockWidgetArea); + }); + QAction* atLeftLayoutAction = layoutMenu->addAction(tr("Dock Windows at Left Side")); + connect(atLeftLayoutAction, &QAction::triggered, this, [=]() { + moveDocksTo(Qt::LeftDockWidgetArea); + }); + QAction* atTopLayoutAction = layoutMenu->addAction(tr("Dock Windows at Top")); + connect(atTopLayoutAction, &QAction::triggered, this, [=]() { + moveDocksTo(Qt::TopDockWidgetArea); + }); + + // If we're not compiling in SQLCipher, hide its FAQ link in the help menu +#ifndef ENABLE_SQLCIPHER + ui->actionSqlCipherFaq->setVisible(false); +#endif + // Set statusbar fields + statusBusyLabel = new QLabel(ui->statusbar); + statusBusyLabel->setEnabled(false); + statusBusyLabel->setVisible(false); + statusBusyLabel->setToolTip(tr("The database is currently busy.")); + ui->statusbar->addPermanentWidget(statusBusyLabel); + + statusStopButton = new QToolButton(ui->statusbar); + statusStopButton->setVisible(false); + statusStopButton->setIcon(QIcon(":icons/cancel")); + statusStopButton->setToolTip(tr("Click here to interrupt the currently running query.")); + statusStopButton->setMaximumSize(ui->statusbar->geometry().height() - 6, ui->statusbar->geometry().height() - 6); + statusStopButton->setAutoRaise(true); + ui->statusbar->addPermanentWidget(statusStopButton); + statusEncryptionLabel = new QLabel(ui->statusbar); statusEncryptionLabel->setEnabled(false); statusEncryptionLabel->setVisible(false); @@ -178,73 +416,113 @@ void MainWindow::init() statusEncodingLabel->setToolTip(tr("Database encoding")); ui->statusbar->addPermanentWidget(statusEncodingLabel); - // Connect some more signals and slots - connect(ui->dataTable->filterHeader(), SIGNAL(sectionClicked(int)), this, SLOT(browseTableHeaderClicked(int))); - connect(ui->dataTable->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setRecordsetLabel())); - connect(ui->dataTable->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(updateBrowseDataColumnWidth(int,int,int))); - connect(editWin, SIGNAL(goingAway()), this, SLOT(editWinAway())); - connect(editWin, SIGNAL(updateRecordText(int, int, bool, QByteArray)), this, SLOT(updateRecordText(int, int, bool, QByteArray))); - connect(editDock, SIGNAL(goingAway()), this, SLOT(editWinAway())); - connect(editDock, SIGNAL(updateRecordText(int, int, bool, QByteArray)), this, SLOT(updateRecordText(int, int, bool, QByteArray))); - connect(ui->dbTreeWidget->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(changeTreeSelection())); - connect(ui->dataTable->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showDataColumnPopupMenu(QPoint))); - - // Load window settings - tabifyDockWidget(ui->dockLog, ui->dockPlot); - tabifyDockWidget(ui->dockLog, ui->dockSchema); - restoreGeometry(PreferencesDialog::getSettingsValue("MainWindow", "geometry").toByteArray()); - restoreState(PreferencesDialog::getSettingsValue("MainWindow", "windowState").toByteArray()); - ui->comboLogSubmittedBy->setCurrentIndex(ui->comboLogSubmittedBy->findText(PreferencesDialog::getSettingsValue("SQLLogDock", "Log").toString())); - ui->splitterForPlot->restoreState(PreferencesDialog::getSettingsValue("PlotDock", "splitterSize").toByteArray()); - ui->comboLineType->setCurrentIndex(PreferencesDialog::getSettingsValue("PlotDock", "lineType").toInt()); - ui->comboPointShape->setCurrentIndex(PreferencesDialog::getSettingsValue("PlotDock", "pointShape").toInt()); + // When changing the text of the toolbar actions, also automatically change their icon text and their tooltip text + connect(ui->editModifyObjectAction, &QAction::changed, this, [=]() { + ui->editModifyObjectAction->setIconText(ui->editModifyObjectAction->text()); + ui->editModifyObjectAction->setToolTip(ui->editModifyObjectAction->text()); + }); + connect(ui->editDeleteObjectAction, &QAction::changed, this, [=]() { + ui->editDeleteObjectAction->setIconText(ui->editDeleteObjectAction->text()); + ui->editDeleteObjectAction->setToolTip(ui->editDeleteObjectAction->text()); + }); + + // When clicking the interrupt query button in the status bar, ask SQLite to interrupt the current query + connect(statusStopButton, &QToolButton::clicked, this, [this]() { + db.interruptQuery(); + }); - // plot widgets - ui->treePlotColumns->setSelectionMode(QAbstractItemView::NoSelection); + // Connect some more signals and slots + connect(editDock, &EditDialog::recordTextUpdated, this, &MainWindow::updateRecordText); + connect(editDock, &EditDialog::evaluateText, this, &MainWindow::evaluateText); + connect(editDock, &EditDialog::requestUrlOrFileOpen, this, &MainWindow::openUrlOrFile); + connect(ui->dbTreeWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWindow::changeObjectSelection); + connect(ui->dockEdit, &QDockWidget::visibilityChanged, this, &MainWindow::toggleEditDock); + connect(ui->actionDropSelectQueryCheck, &QAction::toggled, dbStructureModel, &DbStructureModel::setDropSelectQuery); + connect(ui->actionDropInsertCheck, &QAction::toggled, dbStructureModel, &DbStructureModel::setDropInsert); + connect(ui->actionDropNamesCheck, &QAction::toggled, dbStructureModel, + [this]() { + dbStructureModel->setDropSelectQuery(false); + dbStructureModel->setDropInsert(false); + }); + connect(ui->actionDropQualifiedCheck, &QAction::toggled, dbStructureModel, &DbStructureModel::setDropQualifiedNames); + connect(ui->actionEnquoteNamesCheck, &QAction::toggled, dbStructureModel, &DbStructureModel::setDropEnquotedNames); + connect(&db, &DBBrowserDB::databaseInUseChanged, this, &MainWindow::updateDatabaseBusyStatus); + + connect(ui->actionSqlStop, &QAction::triggered, this, [this]() { + if(execute_sql_worker && execute_sql_worker->isRunning()) + execute_sql_worker->stop(); + }); + + // Connect tool pragmas + connect(ui->actionIntegrityCheck, &QAction::triggered, this, [this]() { + runSqlNewTab("PRAGMA integrity_check;", ui->actionIntegrityCheck->text(), "https://www.sqlite.org/pragma.html#pragma_integrity_check"); + }); + connect(ui->actionQuickCheck, &QAction::triggered, this, [this]() { + runSqlNewTab("PRAGMA quick_check;", ui->actionQuickCheck->text(), "https://www.sqlite.org/pragma.html#pragma_quick_check"); + }); + connect(ui->actionForeignKeyCheck, &QAction::triggered, this, [this]() { + runSqlNewTab("PRAGMA foreign_key_check;", ui->actionForeignKeyCheck->text(), "https://www.sqlite.org/pragma.html#pragma_foreign_key_check"); + }); + connect(ui->actionOptimize, &QAction::triggered, this, [this]() { + runSqlNewTab("PRAGMA optimize;", ui->actionOptimize->text(), "https://www.sqlite.org/pragma.html#pragma_optimize"); + }); + + // Action for switching the table via the Database Structure tab + connect(ui->actionPopupSchemaDockBrowseTable, &QAction::triggered, this, [this]() { + switchToBrowseDataTab(dockDbSelected->object()); + refresh(); // Required in case the Browse Data tab already was the active main tab + }); // Set other window settings setAcceptDrops(true); setWindowTitle(QApplication::applicationName()); + // Add the documentation of shortcuts, which aren't otherwise visible in the user interface, to some buttons. + addShortcutsTooltip(ui->actionDbPrint); + addShortcutsTooltip(ui->actionSqlOpenTab); + addShortcutsTooltip(ui->actionSqlOpenFile); + addShortcutsTooltip(ui->actionSqlPrint); + addShortcutsTooltip(ui->actionExecuteSql, {shortcutBrowseRefreshF5->key(), shortcutBrowseRefreshCtrlR->key()}); + addShortcutsTooltip(ui->actionSqlExecuteLine); + addShortcutsTooltip(ui->actionSqlFind); + addShortcutsTooltip(ui->actionSqlFindReplace); + addShortcutsTooltip(ui->actionSqlToggleComment); + + // Since in some keyboards pressing F keys is cumbersome, add an alternate shortcut and document + // it in the toolbar. + ui->fileCloseAction->setShortcuts({QKeySequence(tr("Ctrl+F4")), QKeySequence(tr("Alt+Shift+W"))}); + ui->actionCloseProject->setShortcuts({QKeySequence(tr("Ctrl+Shift+W")), QKeySequence(tr("Ctrl+Shift+F4"))}); + addShortcutsTooltip(ui->fileCloseAction); + // Load all settings reloadSettings(); -#ifdef CHECKNEWVERSION - // Check for a new version if automatic update check aren't disabled in the settings dialog - if(PreferencesDialog::getSettingsValue("checkversion", "enabled").toBool()) - { - // Check for a new release version, usually only enabled on windows - m_NetworkManager = new QNetworkAccessManager(this); - connect(m_NetworkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(httpresponse(QNetworkReply*))); - - QUrl url("https://raw.githubusercontent.com/sqlitebrowser/sqlitebrowser/master/currentrelease"); - m_NetworkManager->get(QNetworkRequest(url)); - } -#endif - #ifndef ENABLE_SQLCIPHER // Only show encryption menu action when SQLCipher support is enabled ui->actionEncryption->setVisible(false); #endif -#ifdef Q_OS_WIN - // On Windows remove all the & signs from the dock titles. Windows (or Qt on Windows) doesn't seem - // to support them properly, so they end up being visible instead of creating a keyboard shortcut. - ui->dockEditWindow->setWindowTitle(ui->dockEditWindow->windowTitle().remove('&')); + /* Remove all the '&' signs from the dock titles. On at least Windows and + * OSX, Qt doesn't seem to support them properly, so they end up being + * visible instead of creating a keyboard shortcut + */ + ui->dockEdit->setWindowTitle(ui->dockEdit->windowTitle().remove('&')); ui->dockLog->setWindowTitle(ui->dockLog->windowTitle().remove('&')); ui->dockPlot->setWindowTitle(ui->dockPlot->windowTitle().remove('&')); ui->dockSchema->setWindowTitle(ui->dockSchema->windowTitle().remove('&')); -#endif } -bool MainWindow::fileOpen(const QString& fileName, bool dontAddToRecentFiles) +bool MainWindow::fileOpen(const QString& fileName, bool openFromProject, bool readOnly) { bool retval = false; QString wFile = fileName; - if (!QFile::exists(wFile)) + // QFile::exist will produce error message if passed empty string. + // Test string length before usage w/ QFile to silence warning + if (wFile.isEmpty() || !QFile::exists(wFile)) { wFile = FileDialog::getOpenFileName( + OpenDatabaseFile, this, tr("Choose a database file") #ifndef Q_OS_MAC // Filters on OS X are buggy @@ -252,49 +530,81 @@ bool MainWindow::fileOpen(const QString& fileName, bool dontAddToRecentFiles) #endif ); } - if(QFile::exists(wFile) ) + // catch situation where user has canceled file selection from dialog + if(!wFile.isEmpty() && QFile::exists(wFile) ) { - // Close the database. If the user didn't want to close it, though, stop here - if(!fileClose()) + // Try opening it as a project file first. If confirmed, this will include closing current + // database and project files. + switch (loadProject(wFile, readOnly)) { + case Success: + return true; + case Aborted: return false; - - // Try opening it as a project file first - if(loadProject(wFile)) - { - retval = true; + case NotValidFormat: + // It's not a project. Continue trying to open the file as CSV or DB. + break; + } + if(isTextOnlyFile(wFile)) { + // If it's a text file, cannot be an SQLite/SQLCipher database, + // so try to import it as CSV. + importCSVfiles({wFile}); } else { + // Close the database. If the user didn't want to close it, though, stop here + if (db.isOpen()) + if(!fileClose()) + return false; + // No project file; so it should be a database file - if(db.open(wFile)) + if(db.open(wFile, readOnly)) { + // Close all open but empty SQL tabs + for(int i=ui->tabSqlAreas->count()-1;i>=0;i--) + { + if(qobject_cast(ui->tabSqlAreas->widget(i))->getSql().trimmed().isEmpty()) + closeSqlTab(i, true); + } + statusEncodingLabel->setText(db.getPragma("encoding")); statusEncryptionLabel->setVisible(db.encrypted()); statusReadOnlyLabel->setVisible(db.readOnly()); setCurrentFile(wFile); - if(!dontAddToRecentFiles) - addToRecentFilesMenu(wFile); - openSqlTab(true); - loadExtensionsFromSettings(); - populateStructure(); - if(ui->mainTab->currentIndex() == 1) - resetBrowser(); - else if(ui->mainTab->currentIndex() == 2) + if(!openFromProject) { + addToRecentFilesMenu(wFile, readOnly); + // When a new DB file has been open while a project is open, set the project modified. + if(!currentProjectFilename.isEmpty()) + isProjectModified = true; + } else { + // loadProject will init the rest + return true; + } + if(ui->tabSqlAreas->count() == 0) // Create a new tab if there isn't one. + openSqlTab(true); + if(ui->mainTab->currentWidget() == ui->pragmas) loadPragmas(); + + refreshTableBrowsers(); + if (db.readOnly()) { + if (!fileSystemWatch.files().isEmpty()) + fileSystemWatch.removePaths(fileSystemWatch.files()); + fileSystemWatch.addPath(wFile); + } retval = true; } else { - QMessageBox::warning(this, qApp->applicationName(), tr("Invalid file format.")); - return false; + QMessageBox::warning(this, qApp->applicationName(), tr("Could not open database file.\nReason: %1").arg(db.lastError())); + retval = false; } } } - return retval; } void MainWindow::fileNew() { - QString fileName = FileDialog::getSaveFileName(this, - tr("Choose a filename to save under"), - FileDialog::getSqlDatabaseFileFilter()); + QString fileName = FileDialog::getSaveFileName( + CreateDatabaseFile, + this, + tr("Choose a filename to save under"), + FileDialog::getSqlDatabaseFileFilter()); if(!fileName.isEmpty()) { if(QFile::exists(fileName)) @@ -305,460 +615,443 @@ void MainWindow::fileNew() statusEncodingLabel->setText(db.getPragma("encoding")); statusEncryptionLabel->setVisible(false); statusReadOnlyLabel->setVisible(false); - loadExtensionsFromSettings(); - populateStructure(); - resetBrowser(); - openSqlTab(true); + refreshTableBrowsers(); + if(ui->tabSqlAreas->count() == 0) + openSqlTab(true); createTable(); } } -void MainWindow::populateStructure() +void MainWindow::fileNewInMemoryDatabase(bool open_create_dialog) +{ + // Open an in-memory database. We use open() instead of create() here because the extra work create() does is not needed + // when no files are stored on disk. + db.open(":memory:"); + + setCurrentFile(tr("In-Memory database")); + statusEncodingLabel->setText(db.getPragma("encoding")); + statusEncryptionLabel->setVisible(false); + statusReadOnlyLabel->setVisible(false); + refreshTableBrowsers(); + if(ui->tabSqlAreas->count() == 0) + openSqlTab(true); + if(open_create_dialog) + createTable(); +} + +void MainWindow::populateStructure(const std::vector& old_tables) { // Refresh the structure tab - db.updateSchema(); - dbStructureModel->reloadData(&db); + ui->dbTreeWidget->setRootIndex(dbStructureModel->index(1, 0)); // Show the 'All' part of the db structure ui->dbTreeWidget->expandToDepth(0); + ui->treeSchemaDock->setRootIndex(dbStructureModel->index(1, 0)); // Show the 'All' part of the db structure ui->treeSchemaDock->expandToDepth(0); + // Refresh the browse data tabs + const auto all_table_browsers = allTableBrowserDocks(); + for(int i=0;i(old_tables.size());i++) + all_table_browsers.at(i)->tableBrowser()->setStructure(dbStructureModel, old_tables.at(static_cast(i))); + + // Cancel here if no database is opened if(!db.isOpen()) return; // Update table and column names for syntax highlighting - objectMap tab = db.getBrowsableObjects(); - SqlUiLexer::TablesAndColumnsMap tablesToColumnsMap; - for(objectMap::ConstIterator it=tab.begin(); it!=tab.end(); ++it) + SqlUiLexer::QualifiedTablesMap qualifiedTablesMap; + for(const auto& it : db.schemata) { - // If it is a table or a view add the fields - if((*it).gettype() == "table" || (*it).gettype() == "view") + SqlUiLexer::TablesAndColumnsMap tablesToColumnsMap; + + for(const auto& jt : it.second.tables) { - QString objectname = it.value().getname(); + QString objectname = QString::fromStdString(jt.first); - for(int i=0; i < (*it).table.fields().size(); ++i) - { - QString fieldname = (*it).table.fields().at(i)->name(); - tablesToColumnsMap[objectname].append(fieldname); - } + for(const auto& f : jt.second->fields) + tablesToColumnsMap[objectname].push_back(QString::fromStdString(f.name())); } + + qualifiedTablesMap[QString::fromStdString(it.first)] = tablesToColumnsMap; } - SqlTextEdit::sqlLexer->setTableNames(tablesToColumnsMap); + SqlTextEdit::sqlLexer->setTableNames(qualifiedTablesMap); ui->editLogApplication->reloadKeywords(); ui->editLogUser->reloadKeywords(); for(int i=0;itabSqlAreas->count();i++) qobject_cast(ui->tabSqlAreas->widget(i))->getEditor()->reloadKeywords(); // Resize SQL column to fit contents - ui->dbTreeWidget->resizeColumnToContents(3); + ui->dbTreeWidget->resizeColumnToContents(DbStructureModel::ColumnSQL); + ui->treeSchemaDock->resizeColumnToContents(DbStructureModel::ColumnSQL); + + // Resize also the Name column in the Dock since it has usually + // short content and there is little space there. + ui->treeSchemaDock->resizeColumnToContents(DbStructureModel::ColumnName); } -void MainWindow::populateTable(QString tablename) +void MainWindow::refreshTableBrowsers(bool all) { - // Remove the model-view link if the table name is empty in order to remove any data from the view - if(ui->comboBrowseTable->model()->rowCount() == 0 && tablename.isEmpty()) - { - ui->dataTable->setModel(0); - if(qobject_cast(ui->dataTable->horizontalHeader())) - qobject_cast(ui->dataTable->horizontalHeader())->generateFilters(0); - return; - } - QApplication::setOverrideCursor(Qt::WaitCursor); - - // Update combo box - if(ui->comboBrowseTable->currentText() != tablename) + for(const auto& d : allTableBrowserDocks()) { - int pos = ui->comboBrowseTable->findText(tablename); - if(pos == -1) + // When in the Browse Data tab update all docks. Otherwise just update the floating ones because they might + // be visible even when another tab is active. + if(all || ui->mainTab->currentWidget() == ui->browser || d->isFloating()) { - ui->comboBrowseTable->setCurrentIndex(0); - tablename = ui->comboBrowseTable->currentText(); - } else { - ui->comboBrowseTable->setCurrentIndex(pos); + TableBrowser* t = d->tableBrowser(); + if(t) + t->refresh(); } } + QApplication::restoreOverrideCursor(); +} - // Set model - bool reconnectSelectionSignals = false; - if(ui->dataTable->model() == 0) - reconnectSelectionSignals = true; - ui->dataTable->setModel(m_browseTableModel); - if(reconnectSelectionSignals) - connect(ui->dataTable->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(dataTableSelectionChanged(QModelIndex))); +void MainWindow::refreshDb() { + refreshTableBrowsers(); +} - // Search stored table settings for this table - QMap::ConstIterator tableIt; - tableIt = browseTableSettings.constFind(tablename); - bool storedDataFound = tableIt != browseTableSettings.constEnd(); +bool MainWindow::fileSaveAs() { - // Set new table - if(!storedDataFound) - { - m_browseTableModel->setTable(tablename); - } else { - QVector v; - bool only_defaults = true; - for(int i=0;iname())); - } + QString fileName = FileDialog::getSaveFileName( + OpenDatabaseFile, + this, + tr("Choose a database file to save under"), + FileDialog::getSqlDatabaseFileFilter() + ); + // catch situation where user has canceled file selection from dialog + if(!fileName.isEmpty()) { + bool result = db.saveAs(fileName.toStdString()); + if(result) { + setCurrentFile(fileName); + addToRecentFilesMenu(fileName); + } else { + QMessageBox::warning(this, QApplication::applicationName(), + tr("Error while saving the database to the new file.")); } - if(only_defaults) - m_browseTableModel->setTable(tablename); - else - m_browseTableModel->setTable(tablename, v); - } - - // Restore table settings - if(storedDataFound) - { - // There is information stored for this table, so extract it and apply it - - // Show rowid column. Needs to be done before the column widths setting because of the workaround in there and before the filter setting - // because of the filter row generation. - showRowidColumn(tableIt.value().showRowid); - - // Column widths - for(QMap::ConstIterator widthIt=tableIt.value().columnWidths.constBegin();widthIt!=tableIt.value().columnWidths.constEnd();++widthIt) - ui->dataTable->setColumnWidth(widthIt.key(), widthIt.value()); - - // Sorting - m_browseTableModel->sort(tableIt.value().sortOrderIndex, tableIt.value().sortOrderMode); - ui->dataTable->filterHeader()->setSortIndicator(tableIt.value().sortOrderIndex, tableIt.value().sortOrderMode); - - // Filters - FilterTableHeader* filterHeader = qobject_cast(ui->dataTable->horizontalHeader()); - for(QMap::ConstIterator filterIt=tableIt.value().filterValues.constBegin();filterIt!=tableIt.value().filterValues.constEnd();++filterIt) - filterHeader->setFilter(filterIt.key(), filterIt.value()); - - // Encoding - m_browseTableModel->setEncoding(tableIt.value().encoding); + return result; } else { - // There aren't any information stored for this table yet, so use some default values - - // Hide rowid column. Needs to be done before the column widths setting because of the workaround in there - showRowidColumn(false); - - // Column widths - for(int i=1;icolumnCount();i++) - ui->dataTable->setColumnWidth(i, ui->dataTable->horizontalHeader()->defaultSectionSize()); - - // Sorting - m_browseTableModel->sort(0, Qt::AscendingOrder); - ui->dataTable->filterHeader()->setSortIndicator(0, Qt::AscendingOrder); - - // Encoding - m_browseTableModel->setEncoding(defaultBrowseTableEncoding); - - // The filters can be left empty as they are + return false; } - - // Activate the add and delete record buttons and editing only if a table has been selected - bool editable = db.getObjectByName(tablename).gettype() == "table" && !db.readOnly(); - ui->buttonNewRecord->setEnabled(editable); - ui->buttonDeleteRecord->setEnabled(editable); - ui->dataTable->setEditTriggers(editable ? QAbstractItemView::SelectedClicked | QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed : QAbstractItemView::NoEditTriggers); - - // Set the recordset label - setRecordsetLabel(); - - // Reset the edit dialog - editWin->reset(); - editDock->reset(); - - // update plot - updatePlot(m_browseTableModel); - - QApplication::restoreOverrideCursor(); } -void MainWindow::resetBrowser(bool reloadTable) +bool MainWindow::fileClose() { - const QString sCurrentTable = ui->comboBrowseTable->currentText(); - ui->comboBrowseTable->clear(); - const objectMap& tab = db.getBrowsableObjects(); - - // fill a objmap which is sorted by table/view names - QMap objmap; - for(objectMap::ConstIterator i=tab.begin();i!=tab.end();++i) + // Stop any running SQL statements before closing the database + if(execute_sql_worker && execute_sql_worker->isRunning()) { - objmap[i.value().getname()] = i.value(); - } + if(QMessageBox::warning(this, qApp->applicationName(), + tr("You are still executing SQL statements. Closing the database now will stop their execution, possibly " + "leaving the database in an inconsistent state. Are you sure you want to close the database?"), + QMessageBox::Yes, QMessageBox::Cancel | QMessageBox::Default | QMessageBox::Escape) == QMessageBox::Cancel) + return false; - // Finally fill the combobox in sorted order - for(QMap::ConstIterator it=objmap.constBegin(); - it!=objmap.constEnd(); - ++it) - { - ui->comboBrowseTable->addItem( - QIcon(QString(":icons/%1").arg((*it).gettype())), - (*it).getname()); + execute_sql_worker->stop(); + execute_sql_worker->wait(); } - setRecordsetLabel(); - if(reloadTable) - populateTable(sCurrentTable); -} - -bool MainWindow::fileClose() -{ // Close the database but stop the closing process here if the user pressed the cancel button in there if(!db.close()) return false; - setWindowTitle(QApplication::applicationName()); - resetBrowser(); - populateStructure(); + if (!fileSystemWatch.files().isEmpty()) + fileSystemWatch.removePaths(fileSystemWatch.files()); + TableBrowser::resetSharedSettings(); + setCurrentFile(QString()); loadPragmas(); statusEncryptionLabel->setVisible(false); statusReadOnlyLabel->setVisible(false); - // Delete the model for the Browse tab and create a new one - delete m_browseTableModel; - m_browseTableModel = new SqliteTableModel(this, &db, PreferencesDialog::getSettingsValue("db", "prefetchsize").toInt()); - connect(ui->dataTable->filterHeader(), SIGNAL(filterChanged(int,QString)), this, SLOT(updateFilter(int,QString))); - connect(m_browseTableModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector)), this, SLOT(dataTableSelectionChanged(QModelIndex))); - - // Reset the edit dialog/dock - editDock->reset(); - editWin->reset(); - - // Remove all stored table information browse data tab - browseTableSettings.clear(); - defaultBrowseTableEncoding = QString(); - - // Manually update the recordset label inside the Browse tab now - setRecordsetLabel(); - - // Reset the plot dock model - updatePlot(0); - - activateFields(false); - ui->buttonLogClear->click(); - for(int i=ui->tabSqlAreas->count()-1;i>=0;i--) - closeSqlTab(i, true); + // Reset the table browser of the Browse Data tab. + // We call delete here to avoid the closed() signal being emitted + // which would open a new dock. + for(auto d : allTableBrowserDocks()) + delete d; + newTableBrowserTab(); + allTableBrowserDocks().at(0)->tableBrowser()->setEnabled(false); + + // Clear edit dock + editDock->setCurrentIndex(QModelIndex()); + + // Clear the SQL Log + ui->editLogApplication->clear(); + ui->editLogUser->clear(); + ui->editLogErrorLog->clear(); + + // Remove completion and highlighting for identifiers + SqlTextEdit::sqlLexer->setTableNames(SqlUiLexer::QualifiedTablesMap()); + for(int i=0; i < ui->tabSqlAreas->count(); i++) + qobject_cast(ui->tabSqlAreas->widget(i))->getEditor()->reloadKeywords(); return true; } void MainWindow::closeEvent( QCloseEvent* event ) { - if(db.close()) + if(closeFiles()) { - PreferencesDialog::setSettingsValue("MainWindow", "geometry", saveGeometry()); - PreferencesDialog::setSettingsValue("MainWindow", "windowState", saveState()); - PreferencesDialog::setSettingsValue("SQLLogDock", "Log", ui->comboLogSubmittedBy->currentText()); - PreferencesDialog::setSettingsValue("PlotDock", "splitterSize", ui->splitterForPlot->saveState()); - PreferencesDialog::setSettingsValue("PlotDock", "lineType", ui->comboLineType->currentIndex()); - PreferencesDialog::setSettingsValue("PlotDock", "pointShape", ui->comboPointShape->currentIndex()); + Settings::setValue("MainWindow", "geometry", saveGeometry()); + Settings::setValue("MainWindow", "windowState", saveState()); + Settings::setValue("MainWindow", "openTabs", saveOpenTabs()); + + Settings::setValue("SQLLogDock", "Log", ui->comboLogSubmittedBy->currentText()); + Settings::setValue("SchemaDock", "dropSelectQuery", ui->actionDropSelectQueryCheck->isChecked()); + Settings::setValue("SchemaDock", "dropInsert", ui->actionDropInsertCheck->isChecked()); + Settings::setValue("SchemaDock", "dropQualifiedNames", ui->actionDropQualifiedCheck->isChecked()); + Settings::setValue("SchemaDock", "dropEnquotedNames", ui->actionEnquoteNamesCheck->isChecked()); + + SqlExecutionArea::saveState(); + + Settings::sync(); + QMainWindow::closeEvent(event); } else { event->ignore(); } } -void MainWindow::addRecord() +bool MainWindow::closeFiles() { - int row = m_browseTableModel->rowCount(); - if(m_browseTableModel->insertRow(row)) - { - selectTableLine(row); - } else { - QMessageBox::warning( this, QApplication::applicationName(), tr("Error adding record:\n") + db.lastErrorMessage); + bool ignoreUnattachedBuffers = false; + // Ask for saving all modified open SQL files in their files and all the unattached tabs in a project file. + for(int i=0; itabSqlAreas->count(); i++) { + // Ask for saving and comply with cancel answer. + if(!askSaveSqlTab(i, ignoreUnattachedBuffers)) + return false; } -} -void MainWindow::deleteRecord() -{ - if(ui->dataTable->selectionModel()->hasSelection()) - { - // If only filter header is selected - if(ui->dataTable->selectionModel()->selectedIndexes().isEmpty()) - return; + bool projectClosed = closeProject(); - int old_row = ui->dataTable->currentIndex().row(); - while(ui->dataTable->selectionModel()->hasSelection()) - { - if(!m_browseTableModel->removeRow(ui->dataTable->selectionModel()->selectedIndexes().first().row())) - { - QMessageBox::warning(this, QApplication::applicationName(), tr("Error deleting record:\n%1").arg(db.lastErrorMessage)); - break; - } - } - populateTable(ui->comboBrowseTable->currentText()); - if(old_row > m_browseTableModel->totalRowCount()) - old_row = m_browseTableModel->totalRowCount(); - selectTableLine(old_row); - } else { - QMessageBox::information( this, QApplication::applicationName(), tr("Please select a record first")); + if (projectClosed) { + // Now all tabs can be closed at once without asking user. + // Close tabs in reverse order (so indexes are not changed in the process). + for(int i=ui->tabSqlAreas->count()-1; i>=0; i--) + closeSqlTab(i, /* force */ true, /* askSaving */ false); } + return projectClosed; } -void MainWindow::selectTableLine(int lineToSelect) -{ - // Are there even that many lines? - if(lineToSelect >= m_browseTableModel->totalRowCount()) - return; - - QApplication::setOverrideCursor( Qt::WaitCursor ); - // Make sure this line has already been fetched - while(lineToSelect >= m_browseTableModel->rowCount() && m_browseTableModel->canFetchMore()) - m_browseTableModel->fetchMore(); - - // Select it - ui->dataTable->clearSelection(); - ui->dataTable->selectRow(lineToSelect); - ui->dataTable->scrollTo(ui->dataTable->currentIndex()); - QApplication::restoreOverrideCursor(); -} - -void MainWindow::navigatePrevious() +bool MainWindow::closeProject() { - int curRow = ui->dataTable->currentIndex().row(); - curRow -= 100; - if(curRow < 0) - curRow = 0; - selectTableLine(curRow); -} - - -void MainWindow::navigateNext() -{ - int curRow = ui->dataTable->currentIndex().row(); - curRow += 100; - if(curRow >= m_browseTableModel->totalRowCount()) - curRow = m_browseTableModel->totalRowCount() - 1; - selectTableLine(curRow); -} - -void MainWindow::navigateBegin() -{ - selectTableLine(0); -} - -void MainWindow::navigateEnd() -{ - selectTableLine(m_browseTableModel->totalRowCount()-1); -} - - -void MainWindow::navigateGoto() -{ - int row = ui->editGoto->text().toInt(); - if(row <= 0) - row = 1; - if(row > m_browseTableModel->totalRowCount()) - row = m_browseTableModel->totalRowCount(); - - selectTableLine(row - 1); - ui->editGoto->setText(QString::number(row)); + if(!currentProjectFilename.isEmpty() && isProjectModified) { + QMessageBox::StandardButton reply = QMessageBox::question + (nullptr, + QApplication::applicationName(), + tr("Do you want to save the changes made to the project file '%1'?"). + arg(QFileInfo(currentProjectFilename).fileName()), + QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + switch(reply) { + case QMessageBox::Save: + saveProject(); + break; + case QMessageBox::Cancel: + return false; + default: + break; + } + } + currentProjectFilename.clear(); + return fileClose(); } -void MainWindow::setRecordsetLabel() +void MainWindow::attachPlot(ExtendedTableWidget* tableWidget, SqliteTableModel* model, BrowseDataTableSettings* settings, bool keepOrResetSelection) { - // Get all the numbers, i.e. the number of the first row and the last row as well as the total number of rows - int from = ui->dataTable->verticalHeader()->visualIndexAt(0) + 1; - int to = ui->dataTable->verticalHeader()->visualIndexAt(ui->dataTable->height()) - 1; - int total = m_browseTableModel->totalRowCount(); - if(to == -2) - to = total; - - // Update the validator of the goto row field - gotoValidator->setRange(0, total); - - // Update the label showing the current position - ui->labelRecordset->setText(tr("%1 - %2 of %3").arg(from).arg(to).arg(total)); + plotDock->updatePlot(model, settings, true, keepOrResetSelection); + // Disconnect previous connection + disconnect(plotDock, &PlotDock::pointsSelected, nullptr, nullptr); + if(tableWidget) { + // Connect plot selection to the current table results widget. + connect(plotDock, &PlotDock::pointsSelected, tableWidget, &ExtendedTableWidget::selectTableLines); + connect(tableWidget, &ExtendedTableWidget::destroyed, plotDock, &PlotDock::resetPlot); + // Disconnect requestUrlOrFileOpen in order to make sure that there is only one connection. Otherwise we can open it several times. + disconnect(tableWidget, &ExtendedTableWidget::requestUrlOrFileOpen, this, &MainWindow::openUrlOrFile); + connect(tableWidget, &ExtendedTableWidget::requestUrlOrFileOpen, this, &MainWindow::openUrlOrFile); + } } -void MainWindow::browseRefresh() +void MainWindow::refresh() { - db.updateSchema(); - populateTable(ui->comboBrowseTable->currentText()); + // What the Refresh function does depends on the currently active tab. This way the keyboard shortcuts (F5 and Ctrl+R) + // always perform some meaningful task; they just happen to be context dependent in the function they trigger. + QWidget* currentTab = ui->mainTab->currentWidget(); + if (currentTab == ui->structure) { + // Refresh the schema + db.updateSchema(); + } else if (currentTab == ui->browser) { + // Refresh the schema and reload the current table + refreshTableBrowsers(); + } else if (currentTab == ui->pragmas) { + // Reload pragma values + loadPragmas(); + } else if (currentTab == ui->query) { + // (Re-)Run the current SQL query + executeQuery(); + } } void MainWindow::createTable() { - if (!db.isOpen()){ - QMessageBox::information( this, QApplication::applicationName(), tr("There is no database opened. Please open or create a new database file.")); - return; - } - - EditTableDialog dialog(&db, "", true, this); + EditTableDialog dialog(db, sqlb::ObjectIdentifier(), true, this); if(dialog.exec()) { - populateStructure(); - resetBrowser(); + refreshTableBrowsers(); } } void MainWindow::createIndex() { - if (!db.isOpen()){ - QMessageBox::information( this, QApplication::applicationName(), tr("There is no database opened. Please open or create a new database file.")); - return; - } - CreateIndexDialog dialog(&db, this); + EditIndexDialog dialog(db, sqlb::ObjectIdentifier(), true, this); if(dialog.exec()) - { - populateStructure(); - resetBrowser(); - } + refreshTableBrowsers(); } void MainWindow::compact() { VacuumDialog dialog(&db, this); - if(dialog.exec()) - { - populateStructure(); - resetBrowser(); - } + dialog.exec(); } void MainWindow::deleteObject() { // Get name and type of object to delete - QString table = ui->dbTreeWidget->model()->data(ui->dbTreeWidget->currentIndex().sibling(ui->dbTreeWidget->currentIndex().row(), 0)).toString(); - QString type = ui->dbTreeWidget->model()->data(ui->dbTreeWidget->currentIndex().sibling(ui->dbTreeWidget->currentIndex().row(), 1)).toString(); + sqlb::ObjectIdentifier obj; + QString type; + getSelectedObject(type, obj); + + // Due to different grammar in languages (e.g. gender or declension), each message must be given separately to translation. + QString message; + if (type == "table") + message = tr("Are you sure you want to delete the table '%1'?\nAll data associated with the table will be lost."); + else if (type == "view") + message = tr("Are you sure you want to delete the view '%1'?"); + else if (type == "trigger") + message = tr("Are you sure you want to delete the trigger '%1'?"); + else if (type == "index") + message = tr("Are you sure you want to delete the index '%1'?"); // Ask user if he really wants to delete that table - if(QMessageBox::warning(this, QApplication::applicationName(), tr("Are you sure you want to delete the %1 '%2'?\nAll data associated with the %1 will be lost.").arg(type).arg(table), - QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape) == QMessageBox::Yes) + if(QMessageBox::warning(this, QApplication::applicationName(), message.arg(QString::fromStdString(obj.name())), + QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) { // Delete the table - QString statement = QString("DROP %1 %2;").arg(type.toUpper()).arg(sqlb::escapeIdentifier(table)); - if(!db.executeSQL( statement)) + QString statement = QString("DROP %1 %2;").arg(type.toUpper(), QString::fromStdString(obj.toString())); + if(!db.executeSQL(statement.toStdString())) { - QString error = tr("Error: could not delete the %1. Message from database engine:\n%2").arg(type).arg(db.lastErrorMessage); - QMessageBox::warning(this, QApplication::applicationName(), error); + if (type == "table") + message = tr("Error: could not delete the table."); + else if (type == "view") + message = tr("Error: could not delete the view."); + else if (type == "trigger") + message = tr("Error: could not delete the trigger."); + else if (type == "index") + message = tr("Error: could not delete the index."); + + QString error = tr("Message from database engine:\n%1").arg(db.lastError()); + QMessageBox::warning(this, QApplication::applicationName(), message + " " + error); } else { - populateStructure(); - resetBrowser(); + refreshTableBrowsers(); + changeObjectSelection(); } } } -void MainWindow::editTable() -{ - if (!db.isOpen()){ - QMessageBox::information( this, QApplication::applicationName(), tr("There is no database opened.")); - return; - } - if(!ui->dbTreeWidget->selectionModel()->hasSelection()){ - return; +void MainWindow::getSelectedObject(QString &type, sqlb::ObjectIdentifier& obj) { + + type = ""; + obj = sqlb::ObjectIdentifier(); + + QWidget* currentTab = ui->mainTab->currentWidget(); + if (currentTab == ui->structure) { + + if(!dbSelected->hasSelection()) + return; + + // Get name and type of the object to edit + obj = dbSelected->object(); + type = dbSelected->objectType(); + + } else if (currentTab == ui->browser) { + // Get name of the current table from the Data Browser + obj = currentlyBrowsedTableName(); + + sqlb::TablePtr tablePtr = db.getTableByName(obj); + if (!tablePtr) { + return; + } else { + type = tablePtr->isView()? "view" : "table"; + } } - QString tableToEdit = ui->dbTreeWidget->model()->data(ui->dbTreeWidget->currentIndex().sibling(ui->dbTreeWidget->currentIndex().row(), 0)).toString(); +} - EditTableDialog dialog(&db, tableToEdit, false, this); - if(dialog.exec()) +void MainWindow::editObject() +{ + QString type; + sqlb::ObjectIdentifier obj; + // Get name and type of object to edit + getSelectedObject(type, obj); + + if(type == "table") { - populateStructure(); - resetBrowser(); + // For a safe and possibly complex table modification we must follow the steps documented in + // https://www.sqlite.org/lang_altertable.html + // Paragraph (first procedure): Making Other Kinds Of Table Schema Changes + + QString foreign_keys = db.getPragma("foreign_keys"); + if (foreign_keys == "1") { + if(db.getDirty() && QMessageBox::question(this, + QApplication::applicationName(), + tr("Editing the table requires to save all pending changes now.\nAre you sure you want to save the database?"), + QMessageBox::Save | QMessageBox::Default, + QMessageBox::Cancel | QMessageBox::Escape) != QMessageBox::Save) + return; + // Commit all changes so the foreign_keys can be effective. + fileSave(); + db.setPragma("foreign_keys", "0"); + } + + EditTableDialog dialog(db, obj, false, this); + bool ok = dialog.exec(); + + // If foreign_keys were enabled, we must commit or rollback the transaction so the foreign_keys pragma can be restored. + if (foreign_keys == "1") { + if (!db.querySingleValueFromDb("PRAGMA " + sqlb::escapeIdentifier(obj.schema()) + ".foreign_key_check").isNull()) { + // Raise warning for accepted modification. When rejected, warn user also since we know now that the table has problems, + // but it wasn't our fault. + if (ok) + QMessageBox::warning(this, QApplication::applicationName(), + tr("Error checking foreign keys after table modification. The changes will be reverted.")); + else + QMessageBox::warning(this, QApplication::applicationName(), + tr("This table did not pass a foreign-key check.
" + "You should run 'Tools | Foreign-Key Check' and fix the reported issues.")); + db.revertAll(); + } else { + // Commit all changes so the foreign_keys can be effective. + fileSave(); + } + db.setPragma("foreign_keys", foreign_keys); + } + if(ok) { + for(const auto& d : allTableBrowserDocks()) + { + if(d->tableBrowser()->currentlyBrowsedTableName() == obj) + d->tableBrowser()->clearFilters(); + } + refreshTableBrowsers(); + } + } else if(type == "index") { + EditIndexDialog dialog(db, obj, false, this); + if(dialog.exec()) + refreshTableBrowsers(); + } else if(type == "view") { + sqlb::TablePtr view = db.getTableByName(obj); + runSqlNewTab(QString("DROP VIEW IF EXISTS %1;\n%2").arg(QString::fromStdString(obj.toString()), QString::fromStdString(view->sql())), + tr("Edit View %1").arg(QString::fromStdString(obj.toDisplayString())), + "https://www.sqlite.org/lang_createview.html", + /* autoRun */ false); + } else if(type == "trigger") { + sqlb::TriggerPtr trigger = db.getTriggerByName(obj); + runSqlNewTab(QString("DROP TRIGGER %1;\n%2").arg(QString::fromStdString(obj.toString()), QString::fromStdString(trigger->sql())), + tr("Edit Trigger %1").arg(QString::fromStdString(obj.toDisplayString())), + "https://www.sqlite.org/lang_createtrigger.html", + /* autoRun */ false); } } @@ -773,64 +1066,76 @@ void MainWindow::helpAbout() dialog.exec(); } -void MainWindow::updateRecordText(int row, int col, bool isBlob, const QByteArray& newtext) +void MainWindow::updateRecordText(const QPersistentModelIndex& idx, const QByteArray& text, bool isBlob) { - m_currentTabTableModel->setTypedData(m_currentTabTableModel->index(row, col), isBlob, newtext); + m_currentTabTableModel->setTypedData(idx, isBlob, text); } -void MainWindow::editWinAway() +void MainWindow::evaluateText(const QPersistentModelIndex& idx, const std::string& text) { - // Get the sender - EditDialog* sendingEditDialog = qobject_cast(sender()); - - // Only hide the edit window, not the edit dock - editWin->hide(); + QByteArray value = db.querySingleValueFromDb("SELECT " + text, /* log */ true, DBBrowserDB::Wait); + m_currentTabTableModel->setTypedData(idx, !isTextOnly(value), value); +} - // Update main window - activateWindow(); - ui->dataTable->setFocus(); - ui->dataTable->setCurrentIndex(ui->dataTable->currentIndex().sibling(sendingEditDialog->getCurrentRow(), sendingEditDialog->getCurrentCol())); +void MainWindow::toggleEditDock(bool visible) +{ + if (!visible) { + // Update main window + ui->tabBrowsers->setFocus(); + } else { + // fill edit dock with actual data, when the current index has changed while the dock was invisible. + // (note that this signal is also emitted when the widget is docked or undocked, so we have to avoid + // reloading data when the user is editing and (un)docks the editor). + if (currentTableBrowser && editDock->currentIndex() != currentTableBrowser->currentIndex()) + editDock->setCurrentIndex(currentTableBrowser->currentIndex()); + } } void MainWindow::doubleClickTable(const QModelIndex& index) { // Cancel on invalid index - if(!index.isValid()) + if (!index.isValid()) { return; + } - // Don't allow editing of other objects than tables (on the browse table) + // * Don't allow editing of other objects than tables and editable views + bool isEditingAllowed = !db.readOnly() && currentTableBrowser && m_currentTabTableModel == currentTableBrowser->model() && currentTableBrowser->model()->isEditable(index); - bool allowEditing = (m_currentTabTableModel == m_browseTableModel) && (db.getObjectByName(ui->comboBrowseTable->currentText()).gettype() == "table"); + // Enable or disable the Apply, Null, & Import buttons in the Edit Cell + // dock depending on the value of the "isEditingAllowed" bool above + editDock->setReadOnly(!isEditingAllowed); - editDock->allowEditing(allowEditing); - editWin->allowEditing(allowEditing); + editDock->setCurrentIndex(index); - // Load the current value into both, edit window and edit dock - editWin->loadText(index.data(Qt::EditRole).toByteArray(), index.row(), index.column()); - editDock->loadText(index.data(Qt::EditRole).toByteArray(), index.row(), index.column()); + // Show the edit dock + ui->dockEdit->setVisible(true); - // If the edit dock is visible don't open the edit window. If it's invisible open the edit window. - // The edit dock obviously doesn't need to be opened when it's already visible but setting focus to it makes sense. - if(!ui->dockEditWindow->isVisible()) - editWin->show(); - else - editDock->setFocus(); + // Set focus on the edit dock + editDock->setFocus(); } void MainWindow::dataTableSelectionChanged(const QModelIndex& index) { // Cancel on invalid index - if(!index.isValid()) + if(!index.isValid()) { + editDock->setCurrentIndex(QModelIndex()); return; + } - bool edit = (m_currentTabTableModel == m_browseTableModel) && - (db.getObjectByName(ui->comboBrowseTable->currentText()).gettype() == "table"); + TableBrowserDock* dock = qobject_cast(index.model()->parent()->parent()); + if(dock) + changeTableBrowserTab(dock); - // Don't allow editing of other objects than tables - editDock->allowEditing(edit); + bool editingAllowed = !db.readOnly() && currentTableBrowser && m_currentTabTableModel == currentTableBrowser->model() && currentTableBrowser->model()->isEditable(index); - // Load the current value into the edit dock only - editDock->loadText(index.data(Qt::EditRole).toByteArray(), index.row(), index.column()); + // Don't allow editing of other objects than tables and editable views + editDock->setReadOnly(!editingAllowed); + + // If the Edit Cell dock is visible, load the new value into it + if (editDock->isVisible()) { + editDock->setCurrentIndex(index); + } + changeObjectSelection(); } /* @@ -838,163 +1143,269 @@ void MainWindow::dataTableSelectionChanged(const QModelIndex& index) * right now you only see the result of the last executed statement. * A better experience would be tabs on the bottom with query results * for all the executed statements. - * Or at least a some way the use could see results/status message - * per executed statement. */ void MainWindow::executeQuery() { - SqlExecutionArea* sqlWidget = qobject_cast(ui->tabSqlAreas->currentWidget()); + // Make sure a database is opened. This is necessary because we allow opened SQL editor tabs even if no database is loaded. Hitting F5 or similar + // then might call this function. + if(!db.isOpen()) + return; - // Get SQL code to execute. This depends on the button that's been pressed - QString query; - bool singleStep = false; - int execution_start_line = 0; - int execution_start_index = 0; - if(sender()->objectName() == "actionSqlExecuteLine") + // Check if other task is still running and stop it if necessary + if(execute_sql_worker && execute_sql_worker->isRunning()) { - int cursor_line, cursor_index; - sqlWidget->getEditor()->getCursorPosition(&cursor_line, &cursor_index); - execution_start_line = cursor_line; - while(cursor_line < sqlWidget->getEditor()->lines()) - query += sqlWidget->getEditor()->text(cursor_line++); - singleStep = true; - } else { - // if a part of the query is selected, we will only execute this part - query = sqlWidget->getSelectedSql(); - int dummy; - if(query.isEmpty()) - query = sqlWidget->getSql(); - else - sqlWidget->getEditor()->getSelection(&execution_start_line, &execution_start_index, &dummy, &dummy); + // Ask the user and do nothing if he/she doesn't want to interrupt the running query + if(QMessageBox::warning(this, qApp->applicationName(), + tr("You are already executing SQL statements. Do you want to stop them in order to execute the current " + "statements instead? Note that this might leave the database in an inconsistent state."), + QMessageBox::Yes, QMessageBox::Cancel | QMessageBox::Default | QMessageBox::Escape) == QMessageBox::Cancel) + return; + + // Stop the running query + execute_sql_worker->stop(); + execute_sql_worker->wait(); } - if (query.isEmpty()) - return; - //log the query - db.logSQL(query, kLogMsg_User); - sqlite3_stmt *vm; - QByteArray utf8Query = query.toUtf8(); - const char *tail = utf8Query.data(); - int sql3status = 0; - int tail_length = utf8Query.length(); - QString statusMessage; - bool modified = false; - bool wasdirty = db.getDirty(); - - // there is no choice, we have to start a transaction before - // we create the prepared statement, otherwise every executed - // statement will get committed after the prepared statement - // gets finalized, see http://www.sqlite.org/lang_transaction.html - db.setSavepoint(); + // Get current SQL tab and editor + SqlExecutionArea* sqlWidget = qobject_cast(ui->tabSqlAreas->currentWidget()); + SqlTextEdit* editor = sqlWidget->getEditor(); + auto* current_tab = ui->tabSqlAreas->currentWidget(); + const QString tabName = ui->tabSqlAreas->tabText(ui->tabSqlAreas->currentIndex()).remove('&').remove(QRegularExpression("\\*$")); // Remove any error indicators - sqlWidget->getEditor()->clearErrorIndicators(); + editor->clearErrorIndicators(); + sqlWidget->getStatusEdit()->clear(); + sqlWidget->getStatusEdit()->setStyleSheet(""); + + // Determine execution mode: execute all, execute selection or execute current line + enum executionMode + { + All, + Selection, + Line + } mode; + if(sender() && sender()->objectName() == "actionSqlExecuteLine") + mode = Line; + else if(!sqlWidget->getSelectedSql().isEmpty()) + mode = Selection; + else + mode = All; - //Accept multi-line queries, by looping until the tail is empty - QElapsedTimer timer; - timer.start(); - do + // Get SQL code to execute. This depends on the execution mode. + int execute_from_position = 0; // Where we want to start the execution in the query string + int execute_to_position = 0; // Where we roughly want to end the execution in the query string + + switch(mode) { - int tail_length_before = tail_length; - const char* qbegin = tail; - sql3status = sqlite3_prepare_v2(db._db,tail, tail_length, &vm, &tail); - QString queryPart = QString::fromUtf8(qbegin, tail - qbegin); - tail_length -= (tail - qbegin); - int execution_end_index = execution_start_index + tail_length_before - tail_length; - - if (sql3status == SQLITE_OK) + case Selection: + { + // Start and end positions are start and end positions from the selection + int execute_from_line, execute_from_index, execute_to_line, execute_to_index; + editor->getSelection(&execute_from_line, &execute_from_index, &execute_to_line, &execute_to_index); + execute_from_position = editor->positionFromLineIndex(execute_from_line, execute_from_index); + execute_to_position = editor->positionFromLineIndex(execute_to_line, execute_to_index); + + db.logSQL(tr("-- EXECUTING SELECTION IN '%1'\n--").arg(tabName), kLogMsg_User); + } break; + case Line: { - sql3status = sqlite3_step(vm); - sqlite3_finalize(vm); + // Start position is the first character of the current line, except for those cases where we're in the middle of a + // statement which started on one the previous line. In that case the start position is actually a bit earlier. For + // the end position we set the last character of the current line. If the statement(s) continue(s) into the next line, + // SQLite will execute it/them anyway and we'll stop afterwards. + int execute_from_line, dummy; + editor->getCursorPosition(&execute_from_line, &dummy); + execute_from_position = editor->positionFromLineIndex(execute_from_line, 0); + + // Need to set the end position here before adjusting the start line + int execute_to_line = execute_from_line; + int execute_to_index = editor->text(execute_to_line).remove('\n').remove('\r').length(); // This chops the line break at the end of the line + execute_to_position = editor->positionFromLineIndex(execute_to_line, execute_to_index); + + QByteArray firstPartEntireSQL = sqlWidget->getSql().toUtf8().left(execute_from_position); + if(firstPartEntireSQL.lastIndexOf(';') != -1) { + execute_from_position -= firstPartEntireSQL.length() - firstPartEntireSQL.lastIndexOf(';') - 1; + } else { + // No semicolon before the current line, execute from the first line. + execute_from_position = editor->positionFromLineIndex(0, 0); + } - // SQLite returns SQLITE_DONE when a valid SELECT statement was executed but returned no results. To run into the branch that updates - // the status message and the table view anyway manipulate the status value here. This is also done for PRAGMA statements as they (sometimes) - // return rows just like SELECT statements, too. - if((queryPart.trimmed().startsWith("SELECT", Qt::CaseInsensitive) || - queryPart.trimmed().startsWith("PRAGMA", Qt::CaseInsensitive)) && sql3status == SQLITE_DONE) - sql3status = SQLITE_ROW; + db.logSQL(tr("-- EXECUTING LINE IN '%1'\n--").arg(tabName), kLogMsg_User); + } break; + case All: + { + // Start position is the first byte, end position the last. + // Note that we use byte positions that might differ from character positions. + execute_to_position = editor->length(); + + db.logSQL(tr("-- EXECUTING ALL IN '%1'\n--").arg(tabName), kLogMsg_User); + } break; + } + + // Prepare a lambda function for logging the results of a query + auto logged_queries = std::make_shared(); + auto query_logger = [sqlWidget, editor, logged_queries](bool ok, const QString& status_message, int from_position, int to_position) { + int execute_from_line, execute_from_index; + editor->lineIndexFromPosition(from_position, &execute_from_line, &execute_from_index); + + // Special case: if the start position is at the end of a line, then move to the beginning of next line. + // Otherwise for the typical case, the line reference is one less than expected. + // Note that execute_from_index uses character positions and not byte positions, so at() can be used. + QChar char_at_index = editor->text(execute_from_line).at(execute_from_index); + if (char_at_index == '\r' || char_at_index == '\n') { + execute_from_line++; + // The next lines could be empty, so skip all of them too. + while(editor->text(execute_from_line).trimmed().isEmpty()) + execute_from_line++; + execute_from_index = 0; + } - switch(sql3status) - { - case SQLITE_ROW: - { - sqlWidget->getModel()->setQuery(queryPart); - if(sqlWidget->getModel()->valid()) - { - // The query takes the last placeholder as it may itself contain the sequence '%' + number - statusMessage = tr("%1 rows returned in %2ms from: %3").arg( - sqlWidget->getModel()->totalRowCount()).arg(timer.elapsed()).arg(queryPart.trimmed()); - sqlWidget->enableSaveButton(true); - sql3status = SQLITE_OK; - } - else - { - statusMessage = tr("Error executing query: %1").arg(queryPart); - sql3status = SQLITE_ERROR; - } - } - case SQLITE_DONE: - case SQLITE_OK: - { - if( !queryPart.trimmed().startsWith("SELECT", Qt::CaseInsensitive) ) - { - modified = true; + // If there was an error highlight the erroneous SQL statement + if(!ok) + { + int end_of_current_statement_line, end_of_current_statement_index; + editor->lineIndexFromPosition(to_position, &end_of_current_statement_line, &end_of_current_statement_index); + editor->setErrorIndicator(execute_from_line, execute_from_index, end_of_current_statement_line, end_of_current_statement_index); - QString stmtHasChangedDatabase; - if(queryPart.trimmed().startsWith("INSERT", Qt::CaseInsensitive) || - queryPart.trimmed().startsWith("UPDATE", Qt::CaseInsensitive) || - queryPart.trimmed().startsWith("DELETE", Qt::CaseInsensitive)) - { - stmtHasChangedDatabase = tr(", %1 rows affected").arg(sqlite3_changes(db._db)); - } + editor->setCursorPosition(execute_from_line, execute_from_index); + } - statusMessage = tr("Query executed successfully: %1 (took %2ms%3)").arg(queryPart.trimmed()).arg(timer.elapsed()).arg(stmtHasChangedDatabase); - } - break; - } - default: - statusMessage = QString::fromUtf8((const char*)sqlite3_errmsg(db._db)) + - ": " + queryPart; - break; + // Log the query and the result message. + // The query takes the last placeholder as it may itself contain the sequence '%' + number. + QString query = editor->text(from_position, to_position); + QString log_message = "-- " + tr("At line %1:").arg(execute_from_line+1) + "\n" + query.trimmed() + "\n-- " + tr("Result: %1").arg(status_message); + logged_queries->append(log_message + "\n"); + + // Update the execution area + log_message = tr("Result: %2").arg(status_message) + "\n" + tr("At line %1:").arg(execute_from_line+1) + "\n" + query.trimmed(); + sqlWidget->finishExecution(log_message, ok); + }; + + // Get the statement(s) to execute. When in selection mode crop the query string at exactly the end of the selection to make sure SQLite has + // no chance to execute any further. + QString sql = sqlWidget->getSql(); + if(mode == Selection) { + // We have to convert to a QByteArray here because QScintilla gives us the position in bytes, not in characters. + // We also have to replace the characters before execute_from_position by spaces, so that they count as bytes and not multibyte characters. + sql = sql.toUtf8().replace(0, execute_from_position, QString(" ").repeated(execute_from_position).toUtf8()).left(execute_to_position); + } + // Prepare the SQL worker to run the query. We set the context of each signal-slot connection to the current SQL execution area. + // This means that if the tab is closed all these signals are automatically disconnected so the lambdas won't be called for a not + // existing execution area. + execute_sql_worker.reset(new RunSql(db, sql, execute_from_position, execute_to_position, true)); + + connect(execute_sql_worker.get(), &RunSql::structureUpdated, sqlWidget, [this]() { + db.updateSchema(); + }, Qt::QueuedConnection); + connect(execute_sql_worker.get(), &RunSql::statementErrored, sqlWidget, [query_logger, this](const QString& status_message, int from_position, int to_position) { + ui->actionSqlResultsSave->setEnabled(false); + ui->actionSqlResultsSaveAsView->setEnabled(false); + + query_logger(false, status_message, from_position, to_position); + }, Qt::QueuedConnection); + connect(execute_sql_worker.get(), &RunSql::statementExecuted, sqlWidget, [query_logger, this](const QString& status_message, int from_position, int to_position) { + ui->actionSqlResultsSave->setEnabled(false); + ui->actionSqlResultsSaveAsView->setEnabled(false); + + query_logger(true, status_message, from_position, to_position); + execute_sql_worker->startNextStatement(); + }, Qt::QueuedConnection); + connect(execute_sql_worker.get(), &RunSql::statementReturnsRows, sqlWidget, [query_logger, this, sqlWidget](const QString& query, int from_position, int to_position, qint64 time_in_ms_so_far) { + auto time_start = std::chrono::high_resolution_clock::now(); + + ui->actionSqlResultsSave->setEnabled(true); + ui->actionSqlResultsSaveAsView->setEnabled(!db.readOnly()); + + auto * model = sqlWidget->getModel(); + model->setQuery(query); + + // Wait until the initial loading of data (= first chunk and row count) has been performed + auto conn = std::make_shared(); + *conn = connect(model, &SqliteTableModel::finishedFetch, this, [=](int begin, int end) { + // Skip callback if it's is a chunk load. + // Now query_logger displays the correct value for "rows returned", not "Prefetch block size" + if (begin == 0 && end > 0) { + return; } - timer.restart(); + disconnect(*conn); + + attachPlot(sqlWidget->getTableResult(), sqlWidget->getModel()); + + connect(sqlWidget->getTableResult()->selectionModel(), &QItemSelectionModel::currentChanged, this, &MainWindow::dataTableSelectionChanged); + connect(sqlWidget->getTableResult(), &QTableView::doubleClicked, this, &MainWindow::doubleClickTable); + + auto time_end = std::chrono::high_resolution_clock::now(); + auto time_in_ms = std::chrono::duration_cast(time_end-time_start); + query_logger(true, tr("%1 rows returned in %2ms").arg(model->rowCount()).arg(time_in_ms.count()+time_in_ms_so_far), from_position, to_position); + execute_sql_worker->startNextStatement(); + }); + }, Qt::QueuedConnection); + connect(execute_sql_worker.get(), &RunSql::confirmSaveBeforePragmaOrVacuum, sqlWidget, [this]() { + if(QMessageBox::question(nullptr, QApplication::applicationName(), + tr("Setting PRAGMA values or vacuuming will commit your current transaction.\nAre you sure?"), + QMessageBox::Yes | QMessageBox::Default, + QMessageBox::No | QMessageBox::Escape) == QMessageBox::No) + execute_sql_worker->stop(); + + }, Qt::BlockingQueuedConnection); + connect(execute_sql_worker.get(), &RunSql::finished, sqlWidget, [this, current_tab, sqlWidget, logged_queries]() { + // Update the SQL log + db.logSQL(*logged_queries, kLogMsg_User); + + // We work with a pointer to the current tab here instead of its index because the user might reorder the tabs in the meantime. + // We set different icons for general tabs, which are either new or loaded from the project file, and for tabs loaded from a file. + if(sqlWidget->fileName().isEmpty()) + ui->tabSqlAreas->setTabIcon(ui->tabSqlAreas->indexOf(current_tab), QIcon(":/icons/open_sql")); + else + ui->tabSqlAreas->setTabIcon(ui->tabSqlAreas->indexOf(current_tab), QIcon(":/icons/document_open")); - // Stop after the first full statement if we're in single step mode - if(singleStep) - break; - } else { - statusMessage = QString::fromUtf8((const char*)sqlite3_errmsg(db._db)) + - ": " + queryPart; - sqlWidget->getEditor()->setErrorIndicator(execution_start_line, execution_start_index, execution_start_line, execution_end_index); - } + // Set no-running-query state + ui->tabSqlAreas->tabBar()->setTabData(ui->tabSqlAreas->indexOf(current_tab), QVariant(false)); + + // We don't need to check for the current SQL tab here because two concurrently running queries are not allowed + ui->actionSqlExecuteLine->setEnabled(true); + ui->actionExecuteSql->setEnabled(true); + ui->actionSqlStop->setEnabled(false); + sqlWidget->getEditor()->setReadOnly(false); + + // Show Done message + if(sqlWidget->inErrorState()) + sqlWidget->getStatusEdit()->setPlainText(tr("Execution finished with errors.") + "\n" + sqlWidget->getStatusEdit()->toPlainText()); + else + sqlWidget->getStatusEdit()->setPlainText(tr("Execution finished without errors.") + "\n" + sqlWidget->getStatusEdit()->toPlainText()); + }); - execution_start_index = execution_end_index; - } while( tail && *tail != 0 && (sql3status == SQLITE_OK || sql3status == SQLITE_DONE)); - sqlWidget->finishExecution(statusMessage); - updatePlot(sqlWidget->getModel()); + // Add an hourglass icon to the current tab to indicate that there's a running execution in there. + ui->tabSqlAreas->setTabIcon(ui->tabSqlAreas->currentIndex(), QIcon(":icons/hourglass")); + // We use the tab data to check whether a specific SQL tab is currently running a query or not. + ui->tabSqlAreas->tabBar()->setTabData(ui->tabSqlAreas->currentIndex(), QVariant(true)); - connect(sqlWidget->getTableResult(), SIGNAL(clicked(QModelIndex)), this, SLOT(dataTableSelectionChanged(QModelIndex))); + // Deactivate the buttons to start a query and activate the button to stop the query + ui->actionSqlExecuteLine->setEnabled(false); + ui->actionExecuteSql->setEnabled(false); + ui->actionSqlStop->setEnabled(true); - connect(sqlWidget->getTableResult(), SIGNAL(doubleClicked(QModelIndex)), this, SLOT(doubleClickTable(QModelIndex))); + // Make the SQL editor widget read-only. We do this because the error indicators would be misplaced if the user changed the SQL text during execution + sqlWidget->getEditor()->setReadOnly(true); - if(!modified && !wasdirty) - db.revertToSavepoint(); // better rollback, if the logic is not enough we can tune it. + // Reset model and clear plot dock + sqlWidget->getModel()->reset(); + attachPlot(sqlWidget->getTableResult(), sqlWidget->getModel()); + + // Start the execution + execute_sql_worker->start(); } -void MainWindow::mainTabSelected(int tabindex) +void MainWindow::mainTabSelected(int /*tabindex*/) { - editDock->allowEditing(false); + editDock->setReadOnly(true); - if(tabindex == 0) + if(ui->mainTab->currentWidget() == ui->browser) { - populateStructure(); - } else if(tabindex == 1) { - m_currentTabTableModel = m_browseTableModel; - populateStructure(); - resetBrowser(); - } else if(tabindex == 2) { + refreshTableBrowsers(); + } else if(ui->mainTab->currentWidget() == ui->pragmas) { loadPragmas(); - } else if(tabindex == 3) { + } else if(ui->mainTab->currentWidget() == ui->query) { SqlExecutionArea* sqlWidget = qobject_cast(ui->tabSqlAreas->currentWidget()); if (sqlWidget) { @@ -1005,51 +1416,118 @@ void MainWindow::mainTabSelected(int tabindex) } } +void MainWindow::importCSVfiles(const std::vector& inputFiles, const QString& table) +{ + if (!inputFiles.empty()) + { + // Allow importing to a new in-memory database that can be saved later. + if(!db.isOpen()) + fileNewInMemoryDatabase(/* open_create_dialog */ false); + + ImportCsvDialog dialog(inputFiles, &db, this, table); + if (dialog.exec()) + refreshTableBrowsers(); + } +} + void MainWindow::importTableFromCSV() { - QString wFile = FileDialog::getOpenFileName( - this, - tr("Choose a text file"), - tr("Text files(*.csv *.txt);;All files(*)")); + std::vector validFiles; - if (QFile::exists(wFile) ) + // Are we importing from a file or from the clipboard? + if(sender() == ui->fileImportCSVAction) { - ImportCsvDialog dialog(wFile, &db, this); - if(dialog.exec()) - { - populateStructure(); - resetBrowser(); - QMessageBox::information(this, QApplication::applicationName(), tr("Import completed")); + // Ask user to specify file(s) + + QStringList file_filter; + file_filter << FILE_FILTER_CSV + << FILE_FILTER_TSV + << FILE_FILTER_DSV + << FILE_FILTER_TXT + << FILE_FILTER_DAT + << FILE_FILTER_ALL; + + const QStringList wFiles = FileDialog::getOpenFileNames( + OpenCSVFile, + this, + tr("Choose text files"), + file_filter.join(";;")); + + for(const auto& file : wFiles) { + if (QFile::exists(file)) + validFiles.push_back(file); } + importCSVfiles(validFiles); + + } else if(sender() == ui->actionFileImportCsvClipboard) { + // Save clipboard content to temporary file + + QTemporaryFile temp(QDir::tempPath() + QDir::separator() + "csv_clipboard"); + temp.open(); + QClipboard* clipboard = QGuiApplication::clipboard(); + temp.write(clipboard->text().toUtf8()); + temp.close(); + validFiles.push_back(temp.fileName()); + + // Note that the temporary file will be removed when the object is + // destroyed, so the reading must be done in the same scope. + importCSVfiles(validFiles); } + } void MainWindow::exportTableToCSV() { // Get the current table name if we are in the Browse Data tab - QString current_table; - if(ui->mainTab->currentIndex() == 0) - current_table = ui->dbTreeWidget->model()->data(ui->dbTreeWidget->currentIndex().sibling(ui->dbTreeWidget->currentIndex().row(), 0)).toString(); - else if(ui->mainTab->currentIndex() == 1) - current_table = ui->comboBrowseTable->currentText(); + sqlb::ObjectIdentifier current_table; - // Open dialog - ExportCsvDialog dialog(&db, this, "", current_table); - dialog.exec(); + QString type; + // Get name and type of object to export + getSelectedObject(type, current_table); + + if(type == "table" || type == "view") { + // Open dialog + ExportDataDialog dialog(db, ExportDataDialog::ExportFormatCsv, this, "", current_table); + dialog.exec(); + } +} + +void MainWindow::exportTableToJson() +{ + // Get the current table name if we are in the Browse Data tab + sqlb::ObjectIdentifier current_table; + + QString type; + // Get name and type of object to export + getSelectedObject(type, current_table); + + if(type == "table" || type == "view") { + // Open dialog + ExportDataDialog dialog(db, ExportDataDialog::ExportFormatJson, this, "", current_table); + dialog.exec(); + } } -void MainWindow::dbState( bool dirty ) +void MainWindow::dbState(bool dirty) { ui->fileSaveAction->setEnabled(dirty); ui->fileRevertAction->setEnabled(dirty); - ui->fileAttachAction->setEnabled(!dirty); - //ui->actionEncryption->setEnabled(!dirty); + ui->undoAction->setEnabled(dirty); + // Unfortunately, sqlite does not allow to backup the DB while there are pending savepoints, + // so we cannot "Save As" when the DB is dirty. + ui->fileSaveAsAction->setEnabled(!dirty); } void MainWindow::fileSave() { if(db.isOpen()) - db.releaseAllSavepoints(); + { + if(!db.releaseAllSavepoints()) + { + QMessageBox::warning(this, QApplication::applicationName(), tr("Error while saving the database file. This means that not all changes to the database were " + "saved. You need to resolve the following error first.\n\n%1").arg(db.lastError())); + } + } } void MainWindow::fileRevert() @@ -1059,17 +1537,24 @@ void MainWindow::fileRevert() if(QMessageBox::question(this, QApplication::applicationName(), msg, QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape) == QMessageBox::Yes) { db.revertAll(); - populateStructure(); - resetBrowser(); + refreshTableBrowsers(); } } } +void MainWindow::undo() +{ + if (db.isOpen()) { + db.revertToUndoSavepoint(); + refreshTableBrowsers(); + } +} + void MainWindow::exportDatabaseToSQL() { QString current_table; - if(ui->mainTab->currentIndex() == 1) - current_table = ui->comboBrowseTable->currentText(); + if(ui->mainTab->currentWidget() == ui->browser) + current_table = QString::fromStdString(currentlyBrowsedTableName().name()); ExportSqlDialog dialog(&db, this, current_table); dialog.exec(); @@ -1077,17 +1562,24 @@ void MainWindow::exportDatabaseToSQL() void MainWindow::importDatabaseFromSQL() { + QStringList file_filter; + file_filter << FILE_FILTER_SQL + << FILE_FILTER_TXT + << FILE_FILTER_ALL; + // Get file name to import QString fileName = FileDialog::getOpenFileName( + OpenSQLFile, this, tr("Choose a file to import"), - tr("Text files(*.sql *.txt);;All files(*)")); + file_filter.join(";;")); // Cancel when file doesn't exist if(!QFile::exists(fileName)) return; - // If there is already a database file opened ask the user whether to import into this one or a new one. If no DB is opened just ask for a DB name directly + // If there is already a database file opened ask the user whether to import into + // this one or a new one. If no DB is opened just ask for a DB name directly QString newDbFile; if((db.isOpen() && QMessageBox::question(this, QApplication::applicationName(), @@ -1096,6 +1588,7 @@ void MainWindow::importDatabaseFromSQL() QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) || !db.isOpen()) { newDbFile = FileDialog::getSaveFileName( + CreateDatabaseFile, this, tr("Choose a filename to save under"), FileDialog::getSqlDatabaseFileFilter()); @@ -1107,29 +1600,40 @@ void MainWindow::importDatabaseFromSQL() return; } + // Create the new file and open it in the browser db.create(newDbFile); - loadExtensionsFromSettings(); + db.close(); + fileOpen(newDbFile); } + // Defer foreign keys. Just deferring them instead of disabling them should work fine because in the import we only expect CREATE and INSERT + // statements which unlike in the Edit Table dialog shouldn't trigger any problems. + QString foreignKeysOldSettings = db.getPragma("defer_foreign_keys"); + db.setPragma("defer_foreign_keys", "1"); + // Open, read, execute and close file QApplication::setOverrideCursor(Qt::WaitCursor); QFile f(fileName); f.open(QIODevice::ReadOnly); - if(!db.executeMultiSQL(f.readAll(), newDbFile.size() == 0)) - QMessageBox::warning(this, QApplication::applicationName(), tr("Error importing data: %1").arg(db.lastErrorMessage)); + QByteArray filedata = f.readAll(); + removeBom(filedata); + bool ok = db.executeMultiSQL(filedata, newDbFile.size() == 0); + // Restore cursor before asking the user to accept the message + QApplication::restoreOverrideCursor(); + if(!ok) + QMessageBox::warning(this, QApplication::applicationName(), tr("Error importing data: %1").arg(db.lastError())); + else if(db.getPragma("foreign_keys") == "1" && !db.querySingleValueFromDb("PRAGMA foreign_key_check").isNull()) + QMessageBox::warning(this, QApplication::applicationName(), tr("Import completed. Some foreign key constraints are violated. Please fix them before saving.")); else QMessageBox::information(this, QApplication::applicationName(), tr("Import completed.")); f.close(); - QApplication::restoreOverrideCursor(); - // Refresh window when importing into an existing DB or - when creating a new file - just open it correctly - if(newDbFile.size()) - { - fileOpen(newDbFile); - } else { - populateStructure(); - resetBrowser(); - } + // Restore the former foreign key settings + db.setPragma("defer_foreign_keys", foreignKeysOldSettings); + + // Refresh views + db.updateSchema(); + refreshTableBrowsers(); } void MainWindow::openPreferences() @@ -1142,45 +1646,103 @@ void MainWindow::openPreferences() //** Db Tree Context Menu void MainWindow::createTreeContextMenu(const QPoint &qPoint) { - if(!ui->dbTreeWidget->selectionModel()->hasSelection()) + if(!dbSelected->hasSelection()) return; - QString type = ui->dbTreeWidget->model()->data(ui->dbTreeWidget->currentIndex().sibling(ui->dbTreeWidget->currentIndex().row(), 1)).toString(); - - if(type == "table" || type == "view" || type == "trigger" || type == "index") + QString type = dbSelected->objectType(); + if(type == "table" || type == "view" || type == "trigger" || type == "index" || type == "database") + { + // needed for first click on treeView as for first time change QItemSelectionModel::currentChanged doesn't fire + changeObjectSelection(); popupTableMenu->exec(ui->dbTreeWidget->mapToGlobal(qPoint)); + } } -//** Tree selection changed -void MainWindow::changeTreeSelection() + +//** DB Schema Dock Context Menu +void MainWindow::createSchemaDockContextMenu(const QPoint &qPoint) +{ + bool enable_browse_table = false; + bool enable_detach_file = false; + + if(dockDbSelected->hasSelection()) + { + QString type = dockDbSelected->objectType(); + if(type == "table" || type == "view") + enable_browse_table = true; + else if(type == "database" && dockDbSelected->schema() != "main" && dockDbSelected->schema() != "temp") + enable_detach_file = true; + } + ui->actionPopupSchemaDockBrowseTable->setEnabled(enable_browse_table); + ui->actionPopupSchemaDockDetachDatabase->setEnabled(enable_detach_file); + + popupSchemaDockMenu->exec(ui->treeSchemaDock->mapToGlobal(qPoint)); +} + +void MainWindow::changeObjectSelection() { // Just assume first that something's selected that can not be edited at all ui->editDeleteObjectAction->setEnabled(false); - ui->editModifyTableAction->setEnabled(false); + ui->editModifyObjectAction->setEnabled(false); ui->actionEditBrowseTable->setEnabled(false); + ui->actionExportCsvPopup->setEnabled(false); + ui->fileDetachAction->setEnabled(false); + ui->actionEditCopyCreateStatement->setEnabled(false); - if(!ui->dbTreeWidget->currentIndex().isValid()) + ui->fileDetachAction->setVisible(false); + + QString type; + sqlb::ObjectIdentifier obj; + getSelectedObject(type, obj); + if(obj.isEmpty()) return; - // Change the text of the actions - QString type = ui->dbTreeWidget->model()->data(ui->dbTreeWidget->currentIndex().sibling(ui->dbTreeWidget->currentIndex().row(), 1)).toString(); - ui->editDeleteObjectAction->setIcon(QIcon(QString(":icons/%1_delete").arg(type))); - if(type == "view") + // Change the text and tooltips of the actions + QString schema = QString::fromStdString(obj.schema()); + + if (type.isEmpty()) + { + ui->editDeleteObjectAction->setIcon(QIcon(":icons/table_delete")); + ui->editModifyObjectAction->setIcon(QIcon(":icons/table_modify")); + } else { + ui->editDeleteObjectAction->setIcon(QIcon(QString(":icons/%1_delete").arg(type))); + ui->editModifyObjectAction->setIcon(QIcon(QString(":icons/%1_modify").arg(type))); + } + + if (type == "view") { ui->editDeleteObjectAction->setText(tr("Delete View")); - else if(type == "trigger") + ui->editModifyObjectAction->setText(tr("Modify View")); + } else if(type == "trigger") { ui->editDeleteObjectAction->setText(tr("Delete Trigger")); - else if(type == "index") + ui->editModifyObjectAction->setText(tr("Modify Trigger")); + } else if(type == "index") { ui->editDeleteObjectAction->setText(tr("Delete Index")); - else + ui->editModifyObjectAction->setText(tr("Modify Index")); + } else if(type == "table") { ui->editDeleteObjectAction->setText(tr("Delete Table")); + ui->editModifyObjectAction->setText(tr("Modify Table")); + } else if(type == "database") { + ui->editDeleteObjectAction->setVisible(false); + ui->editModifyObjectAction->setVisible(false); + ui->fileDetachAction->setVisible(true); + ui->fileDetachAction->setEnabled(!(schema == "main" || schema == "temp")); + return; + } else { + // Nothing to do for other types. Set the buttons not visible and return. + ui->editDeleteObjectAction->setVisible(false); + ui->editModifyObjectAction->setVisible(false); + ui->fileDetachAction->setVisible(false); + ui->actionEditCopyCreateStatement->setEnabled(true); + return; + } + + ui->editDeleteObjectAction->setVisible(true); + ui->editModifyObjectAction->setVisible(true); + ui->actionEditCopyCreateStatement->setEnabled(true); // Activate actions - if(type == "table") - { - ui->editDeleteObjectAction->setEnabled(!db.readOnly()); - ui->editModifyTableAction->setEnabled(!db.readOnly()); - } else if(type == "view" || type == "trigger" || type == "index") { - ui->editDeleteObjectAction->setEnabled(!db.readOnly()); - } + ui->editDeleteObjectAction->setEnabled(!db.readOnly()); + ui->editModifyObjectAction->setEnabled(!db.readOnly()); + if(type == "table" || type == "view") { ui->actionEditBrowseTable->setEnabled(true); @@ -1192,19 +1754,43 @@ void MainWindow::openRecentFile() { QAction *action = qobject_cast(sender()); if (action) - fileOpen(action->data().toString()); + { + QString file = action->data().toString(); + bool read_only = false; + if(file.startsWith("[ro]")) // Check if file is in read-only + { + file = file.mid(4); + read_only = true; + } + + // Holding the Shift key while opening a recent file inverts the read only flag + if(Application::keyboardModifiers().testFlag(Qt::ShiftModifier)) + read_only = !read_only; + + if(fileOpen(file, false, read_only)) + { + if(read_only) + ui->statusbar->showMessage(tr("Opened '%1' in read-only mode from recent file list").arg(file)); + else + ui->statusbar->showMessage(tr("Opened '%1' from recent file list").arg(file)); + } + } } void MainWindow::updateRecentFileActions() { // Get recent files list from settings - QStringList files = PreferencesDialog::getSettingsValue("General", "recentFileList").toStringList(); + QStringList files = Settings::getValue("General", "recentFileList").toStringList(); - // Check if files still exist and remove any non-existant file + // Check if files still exist and remove any non-existent file for(int i=0;isetText(text); recentFileActs[i]->setData(files[i]); recentFileActs[i]->setVisible(true); @@ -1225,32 +1819,56 @@ void MainWindow::updateRecentFileActions() // Add shortcut for opening the file using the keyboard. However, if the application is configured to store // more than nine recently opened files don't set shortcuts for the later ones which wouldn't be single digit anymore. if(i < 9) - recentFileActs[i]->setShortcut(QKeySequence(Qt::CTRL + (Qt::Key_1+i))); + { + recentFileActs[i]->setShortcuts({ + QKeySequence(Qt::CTRL | (Qt::Key_1 + i)), + QKeySequence(Qt::CTRL | Qt::SHIFT | (Qt::Key_1 + i)) + }); + } } for (int j = numRecentFiles; j < MaxRecentFiles; ++j) recentFileActs[j]->setVisible(false); - - recentSeparatorAct->setVisible(numRecentFiles > 0); } void MainWindow::setCurrentFile(const QString &fileName) { setWindowFilePath(fileName); - setWindowTitle( QApplication::applicationName() +" - "+fileName); - activateFields(true); + if(currentProjectFilename.isEmpty() && fileName.isEmpty()) + setWindowTitle(QApplication::applicationName()); + else if(currentProjectFilename.isEmpty()) + setWindowTitle(QApplication::applicationName() + " - " + QDir::toNativeSeparators(fileName)); + else { + QFileInfo projectFileInfo(currentProjectFilename); + QFileInfo dbFileInfo(fileName); + QString dbFileName; + if(dbFileInfo.path() == projectFileInfo.path()) + dbFileName = dbFileInfo.fileName(); + else + dbFileName = QDir::toNativeSeparators(fileName); + setWindowTitle(QApplication::applicationName() + " - " + QDir::toNativeSeparators(currentProjectFilename) + " [" + dbFileName + "]"); + } + activateFields(!fileName.isEmpty()); + if(!fileName.isEmpty()) + dbState(db.getDirty()); } -void MainWindow::addToRecentFilesMenu(const QString& filename) +void MainWindow::addToRecentFilesMenu(const QString& filename, bool read_only) { - QStringList files = PreferencesDialog::getSettingsValue("General", "recentFileList").toStringList(); - files.removeAll(filename); - files.prepend(filename); + QFileInfo info(filename); + QString path = info.absoluteFilePath(); + if(read_only) + path = "[ro]" + path; + + QStringList files = Settings::getValue("General", "recentFileList").toStringList(); + + files.removeAll(path); + files.prepend(path); while (files.size() > MaxRecentFiles) files.removeLast(); - PreferencesDialog::setSettingsValue("General", "recentFileList", files); + Settings::setValue("General", "recentFileList", files); - foreach (QWidget *widget, QApplication::topLevelWidgets()) { + for(QWidget* widget : QApplication::topLevelWidgets()) { MainWindow *mainWin = qobject_cast(widget); if (mainWin) mainWin->updateRecentFileActions(); @@ -1260,78 +1878,107 @@ void MainWindow::addToRecentFilesMenu(const QString& filename) void MainWindow::dragEnterEvent(QDragEnterEvent *event) { if( event->mimeData()->hasFormat("text/uri-list") ) - event->acceptProposedAction(); + event->acceptProposedAction(); } void MainWindow::dropEvent(QDropEvent *event) { - QList urls = event->mimeData()->urls(); + const QList urls = event->mimeData()->urls(); if( urls.isEmpty() ) return; QString fileName = urls.first().toLocalFile(); - if(!fileName.isEmpty()) + if(!fileName.isEmpty()) { + + // If there is no open database, the only possible option is to open the file. + if (!db.isOpen()) { fileOpen(fileName); + return; + } + bool ok; + const QString open = tr("Open Database or Project"); + const QString attach = tr("Attach Database..."); + const QString import = tr("Import CSV file(s)..."); + QString action = QInputDialog::getItem(this, + qApp->applicationName(), + tr("Select the action to apply to the dropped file(s).
" + "Note: only 'Import' will process more than one file.", + "Note for translation: Although there is no %n in the original, " + "you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. " + "Including %n in the translation will also work.", + urls.count()), + {open, attach, import}, + 0, + false, + &ok); + if(ok) { + if (action == open) { + fileOpen(fileName); + } else if (action == attach) { + fileAttach(fileName); + } else if (action == import) { + + std::vector validFiles; + for(const auto& url : urls) { + if (QFile::exists(url.toLocalFile())) + validFiles.push_back(url.toLocalFile()); + } + ImportCsvDialog dialog(validFiles, &db, this); + if (dialog.exec()) + refreshTableBrowsers(); + } + } + } } void MainWindow::activateFields(bool enable) { bool write = !db.readOnly(); + bool tempDb = db.currentFile() == ":memory:"; ui->fileCloseAction->setEnabled(enable); + ui->fileSaveAsAction->setEnabled(enable); + ui->fileAttachAction->setEnabled(enable); ui->fileCompactAction->setEnabled(enable && write); + ui->fileExportJsonAction->setEnabled(enable); ui->fileExportCSVAction->setEnabled(enable); ui->fileExportSQLAction->setEnabled(enable); ui->fileImportCSVAction->setEnabled(enable && write); + ui->actionFileImportCsvClipboard->setEnabled(enable && write); ui->editCreateTableAction->setEnabled(enable && write); ui->editCreateIndexAction->setEnabled(enable && write); - ui->buttonNext->setEnabled(enable); - ui->buttonPrevious->setEnabled(enable); - ui->buttonBegin->setEnabled(enable); - ui->buttonEnd->setEnabled(enable); + ui->actionRefreshStructure->setEnabled(enable); + ui->actionDbPrint->setEnabled(enable); ui->scrollAreaWidgetContents->setEnabled(enable); ui->buttonBoxPragmas->setEnabled(enable && write); - ui->buttonGoto->setEnabled(enable); - ui->editGoto->setEnabled(enable); - ui->buttonRefresh->setEnabled(enable); - ui->buttonDeleteRecord->setEnabled(enable && write); - ui->buttonNewRecord->setEnabled(enable && write); ui->actionExecuteSql->setEnabled(enable); ui->actionLoadExtension->setEnabled(enable); ui->actionSqlExecuteLine->setEnabled(enable); - ui->actionSqlOpenFile->setEnabled(enable); - ui->actionSqlOpenTab->setEnabled(enable); - ui->actionSqlSaveFilePopup->setEnabled(enable); - ui->actionSqlSaveFileAs->setEnabled(enable); - ui->actionSqlSaveFile->setEnabled(enable); - ui->actionSaveProject->setEnabled(enable); - ui->actionEncryption->setEnabled(enable && write); - ui->buttonClearFilters->setEnabled(enable); - ui->dockEditWindow->setEnabled(enable && write); -} - -void MainWindow::browseTableHeaderClicked(int logicalindex) -{ - // Abort if there is more than one column selected because this tells us that the user pretty sure wants to do a range selection instead of sorting data - if(ui->dataTable->selectionModel()->selectedColumns().count() > 1) - return; + ui->actionSaveProject->setEnabled(enable && !tempDb); + ui->actionSaveProjectAs->setEnabled(enable && !tempDb); + ui->actionSaveAll->setEnabled(enable && !tempDb); + ui->actionEncryption->setEnabled(enable && write && !tempDb); + ui->actionIntegrityCheck->setEnabled(enable); + ui->actionQuickCheck->setEnabled(enable); + ui->actionForeignKeyCheck->setEnabled(enable); + ui->actionOptimize->setEnabled(enable); + ui->actionRowCounts->setEnabled(enable); + ui->dockEdit->setEnabled(enable); + ui->dockPlot->setEnabled(enable); - // instead of the column name we just use the column index, +2 because 'rowid, *' is the projection - BrowseDataTableSettings& settings = browseTableSettings[ui->comboBrowseTable->currentText()]; - settings.sortOrderIndex = logicalindex; - settings.sortOrderMode = settings.sortOrderMode == Qt::AscendingOrder ? Qt::DescendingOrder : Qt::AscendingOrder; - ui->dataTable->sortByColumn(settings.sortOrderIndex, settings.sortOrderMode); + if(!enable) + ui->actionSqlResultsSave->setEnabled(false); - // select the first item in the column so the header is bold - // we might try to select the last selected item - ui->dataTable->setCurrentIndex(ui->dataTable->currentIndex().sibling(0, logicalindex)); + for(const auto& d : allTableBrowserDocks()) + d->tableBrowser()->setEnabled(enable); } void MainWindow::resizeEvent(QResizeEvent*) { - setRecordsetLabel(); + for(const auto& d : allTableBrowserDocks()) + d->tableBrowser()->updateRecordsetLabel(); } void MainWindow::loadPragmas() @@ -1353,6 +2000,7 @@ void MainWindow::loadPragmas() pragmaValues.temp_store = db.getPragma("temp_store").toInt(); pragmaValues.user_version = db.getPragma("user_version").toInt(); pragmaValues.wal_autocheckpoint = db.getPragma("wal_autocheckpoint").toInt(); + pragmaValues.case_sensitive_like = db.getPragma("case_sensitive_like").toInt(); updatePragmaUi(); } @@ -1365,17 +2013,18 @@ void MainWindow::updatePragmaUi() ui->checkboxPragmaForeignKeys->setChecked(pragmaValues.foreign_keys); ui->checkboxPragmaFullFsync->setChecked(pragmaValues.fullfsync); ui->checkboxPragmaIgnoreCheckConstraints->setChecked(pragmaValues.ignore_check_constraints); - ui->comboboxPragmaJournalMode->setCurrentIndex(ui->comboboxPragmaJournalMode->findText(pragmaValues.journal_mode, Qt::MatchFixedString)); + ui->comboboxPragmaJournalMode->setCurrentIndex(DBBrowserDB::journalModeValues.indexOf(pragmaValues.journal_mode)); ui->spinPragmaJournalSizeLimit->setValue(pragmaValues.journal_size_limit); - ui->comboboxPragmaLockingMode->setCurrentIndex(ui->comboboxPragmaLockingMode->findText(pragmaValues.locking_mode, Qt::MatchFixedString)); + ui->comboboxPragmaLockingMode->setCurrentIndex(DBBrowserDB::lockingModeValues.indexOf(pragmaValues.locking_mode)); ui->spinPragmaMaxPageCount->setValue(pragmaValues.max_page_count); - ui->spinPragmaPageSize->setValue(pragmaValues.page_size); + ui->comboPragmaPageSize->setCurrentIndex(ui->comboPragmaPageSize->findText(QString::number(pragmaValues.page_size), Qt::MatchFixedString)); ui->checkboxPragmaRecursiveTriggers->setChecked(pragmaValues.recursive_triggers); ui->checkboxPragmaSecureDelete->setChecked(pragmaValues.secure_delete); ui->comboboxPragmaSynchronous->setCurrentIndex(pragmaValues.synchronous); ui->comboboxPragmaTempStore->setCurrentIndex(pragmaValues.temp_store); ui->spinPragmaUserVersion->setValue(pragmaValues.user_version); ui->spinPragmaWalAutoCheckpoint->setValue(pragmaValues.wal_autocheckpoint); + ui->checkboxPragmaCaseSensitiveLike->setChecked(pragmaValues.case_sensitive_like); } void MainWindow::savePragmas() @@ -1394,17 +2043,25 @@ void MainWindow::savePragmas() db.setPragma("foreign_keys", ui->checkboxPragmaForeignKeys->isChecked(), pragmaValues.foreign_keys); db.setPragma("fullfsync", ui->checkboxPragmaFullFsync->isChecked(), pragmaValues.fullfsync); db.setPragma("ignore_check_constraints", ui->checkboxPragmaIgnoreCheckConstraints->isChecked(), pragmaValues.ignore_check_constraints); - db.setPragma("journal_mode", ui->comboboxPragmaJournalMode->currentText().toUpper(), pragmaValues.journal_mode); + + // Since we allow translation of UI combobox text and journal_mode and locking_mode pragmas + // need text values, we get the text value according to index. + // For this to work, order in journalModeValues and combo-box have to follow the order + // determined by SQLite documentation. + db.setPragma("journal_mode", DBBrowserDB::journalModeValues.at(ui->comboboxPragmaJournalMode->currentIndex()), pragmaValues.journal_mode); db.setPragma("journal_size_limit", ui->spinPragmaJournalSizeLimit->value(), pragmaValues.journal_size_limit); - db.setPragma("locking_mode", ui->comboboxPragmaLockingMode->currentText().toUpper(), pragmaValues.locking_mode); + db.setPragma("locking_mode", DBBrowserDB::lockingModeValues.at(ui->comboboxPragmaLockingMode->currentIndex()), pragmaValues.locking_mode); + db.setPragma("max_page_count", ui->spinPragmaMaxPageCount->value(), pragmaValues.max_page_count); - db.setPragma("page_size", ui->spinPragmaPageSize->value(), pragmaValues.page_size); + db.setPragma("page_size", ui->comboPragmaPageSize->currentText().toInt(), pragmaValues.page_size); db.setPragma("recursive_triggers", ui->checkboxPragmaRecursiveTriggers->isChecked(), pragmaValues.recursive_triggers); db.setPragma("secure_delete", ui->checkboxPragmaSecureDelete->isChecked(), pragmaValues.secure_delete); db.setPragma("synchronous", ui->comboboxPragmaSynchronous->currentIndex(), pragmaValues.synchronous); db.setPragma("temp_store", ui->comboboxPragmaTempStore->currentIndex(), pragmaValues.temp_store); db.setPragma("user_version", ui->spinPragmaUserVersion->value(), pragmaValues.user_version); db.setPragma("wal_autocheckpoint", ui->spinPragmaWalAutoCheckpoint->value(), pragmaValues.wal_autocheckpoint); + db.setPragma("case_sensitive_like", ui->checkboxPragmaCaseSensitiveLike->isChecked(), pragmaValues.case_sensitive_like); + isProjectModified = true; updatePragmaUi(); } @@ -1415,107 +2072,282 @@ void MainWindow::logSql(const QString& sql, int msgtype) { ui->editLogUser->append(sql + "\n"); ui->editLogUser->verticalScrollBar()->setValue(ui->editLogUser->verticalScrollBar()->maximum()); - } else { + } else if(msgtype == kLogMsg_App) { ui->editLogApplication->append(sql + "\n"); ui->editLogApplication->verticalScrollBar()->setValue(ui->editLogApplication->verticalScrollBar()->maximum()); + } else if(msgtype == kLogMsg_ErrorLog) { + ui->editLogErrorLog->append(sql + "\n"); + ui->editLogErrorLog->verticalScrollBar()->setValue(ui->editLogErrorLog->verticalScrollBar()->maximum()); + } +} + +// Ask user to save the buffer in the specified tab index. +// ignoreUnattachedBuffers is used to store answer about buffers not linked to files, so user is only asked once about them. +// Return true unless user wants to cancel the invoking action. +bool MainWindow::askSaveSqlTab(int index, bool& ignoreUnattachedBuffers) +{ + SqlExecutionArea* sqlExecArea = qobject_cast(ui->tabSqlAreas->widget(index)); + const bool isPromptSQLTabsInNewProject = Settings::getValue("General", "promptsqltabsinnewproject").toBool(); + + if(sqlExecArea->getEditor()->isModified()) { + if(sqlExecArea->fileName().isEmpty() && !ignoreUnattachedBuffers && isPromptSQLTabsInNewProject) { + // Once the project is saved, remaining SQL tabs will not be modified, so this is only expected to be asked once. + QString message = currentProjectFilename.isEmpty() ? + tr("Do you want to save the changes made to SQL tabs in a new project file?") : + tr("Do you want to save the changes made to SQL tabs in the project file '%1'?"). + arg(QFileInfo(currentProjectFilename).fileName()); + QMessageBox::StandardButton reply = QMessageBox::question(nullptr, + QApplication::applicationName(), + message, + QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + switch(reply) { + case QMessageBox::Save: + saveProject(); + break; + case QMessageBox::Cancel: + return false; + default: + ignoreUnattachedBuffers = true; + break; + } + } else if(!sqlExecArea->fileName().isEmpty()) { + QMessageBox::StandardButton reply = + QMessageBox::question(nullptr, + QApplication::applicationName(), + tr("Do you want to save the changes made to the SQL file %1?"). + arg(QFileInfo(sqlExecArea->fileName()).fileName()), + QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + switch(reply) { + case QMessageBox::Save: + saveSqlFile(index); + break; + case QMessageBox::Cancel: + return false; + default: + break; + } + } } + return true; } -void MainWindow::closeSqlTab(int index, bool force) +void MainWindow::closeSqlTab(int index, bool force, bool askSaving) { - // Don't close last tab - if(ui->tabSqlAreas->count() == 1 && !force) - return; + // Check if we're still executing statements from this tab and stop them before proceeding + if(ui->tabSqlAreas->tabBar()->tabData(index).toBool()) + { + if(QMessageBox::warning(this, qApp->applicationName(), + tr("The statements in the tab '%1' are still executing. Closing the tab will stop the " + "execution. This might leave the database in an inconsistent state. Are you sure " + "you want to close the tab?").arg(ui->tabSqlAreas->tabBar()->tabText(index)), + QMessageBox::Yes, + QMessageBox::Cancel | QMessageBox::Default | QMessageBox::Escape) == QMessageBox::Cancel) + return; + execute_sql_worker->stop(); + execute_sql_worker->wait(); + } + // Ask for saving and comply with cancel answer. + bool ignoreUnattachedBuffers = false; + if (askSaving && !askSaveSqlTab(index, ignoreUnattachedBuffers)) + return; // Remove the tab and delete the widget QWidget* w = ui->tabSqlAreas->widget(index); ui->tabSqlAreas->removeTab(index); delete w; + + // Don't let an empty tab widget + if(ui->tabSqlAreas->count() == 0 && !force) + openSqlTab(true); + + // Set focus to the currently selected editor tab. + focusSqlEditor(); +} + +void MainWindow::markTabsModified() +{ + // Add (and remove) an asterisk next to the filename of modified file tabs. + for (int i = 0; i < ui->tabSqlAreas->count(); ++i) { + SqlExecutionArea* sqlWidget = qobject_cast(ui->tabSqlAreas->widget(i)); + QString currentText = ui->tabSqlAreas->tabText(i); + if (!currentText.endsWith("*")) { + if (sqlWidget->getEditor()->isModified()) { + ui->tabSqlAreas->setTabText(i, currentText + "*"); + } + } + else { + if (!sqlWidget->getEditor()->isModified()) { + currentText.chop(1); + ui->tabSqlAreas->setTabText(i, currentText); + } + } + } } -unsigned int MainWindow::openSqlTab(bool resetCounter) +int MainWindow::openSqlTab(bool resetCounter) { - static unsigned int tabNumber = 0; + static int tabNumber = 0; if(resetCounter) tabNumber = 0; // Create new tab, add it to the tab widget and select it - SqlExecutionArea* w = new SqlExecutionArea(this, &db); + SqlExecutionArea* w = new SqlExecutionArea(db, this); int index = ui->tabSqlAreas->addTab(w, QString("SQL %1").arg(++tabNumber)); ui->tabSqlAreas->setCurrentIndex(index); + w->setFindFrameVisibility(ui->actionSqlFind->isChecked()); + // Disable the find dialog in the SQL tabs, since the shortcut + // would interfere with the search bar and it'd be anyway redundant. + w->getEditor()->setEnabledFindDialog(false); w->getEditor()->setFocus(); + connect(w, &SqlExecutionArea::findFrameVisibilityChanged, ui->actionSqlFind, &QAction::setChecked); + connect(w->getEditor(), &SqlTextEdit::modificationChanged, this, &MainWindow::markTabsModified); + + // Connect now the find shortcut to the editor with widget context, so it isn't ambiguous with other Scintilla Widgets. + QShortcut* shortcutFind = new QShortcut(ui->actionSqlFind->shortcut(), w->getEditor(), nullptr, nullptr, Qt::WidgetShortcut); + connect(shortcutFind, &QShortcut::activated, ui->actionSqlFind, &QAction::toggle); + ui->tabSqlAreas->setTabIcon(index, QIcon(":icons/open_sql")); + // The new tab is not currently running a query + ui->tabSqlAreas->tabBar()->setTabData(index, false); return index; } +void MainWindow::changeSqlTab(int index) +{ + // Instead of figuring out if there are some execution results in the new tab and which statement was used to generate them, + // we just disable the export buttons in the toolbar. + ui->actionSqlResultsSave->setEnabled(false); + + // Check if the new tab is currently running a query or not + if(!ui->tabSqlAreas->tabBar()->tabData(index).toBool()) + { + // Not running a query + + ui->actionSqlExecuteLine->setEnabled(db.isOpen()); + ui->actionExecuteSql->setEnabled(db.isOpen()); + ui->actionSqlStop->setEnabled(false); + } else { + // Running a query + + ui->actionSqlExecuteLine->setEnabled(false); + ui->actionExecuteSql->setEnabled(false); + ui->actionSqlStop->setEnabled(true); + } + SqlExecutionArea* sqlWidget = qobject_cast(ui->tabSqlAreas->currentWidget()); + if (sqlWidget) { + m_currentTabTableModel = sqlWidget->getModel(); + + dataTableSelectionChanged(sqlWidget->getTableResult()->currentIndex()); + } +} + +void MainWindow::openSqlFile(int tabindex, QString filename) +{ + SqlExecutionArea* sqlarea = qobject_cast(ui->tabSqlAreas->widget(tabindex)); + sqlarea->openFile(filename); + QFileInfo fileinfo(filename); + ui->tabSqlAreas->setTabText(tabindex, fileinfo.fileName()); + ui->tabSqlAreas->setTabIcon(tabindex, QIcon(":/icons/document_open")); +} + void MainWindow::openSqlFile() { - QString file = FileDialog::getOpenFileName( + const QStringList wfiles = FileDialog::getOpenFileNames( + OpenSQLFile, this, tr("Select SQL file to open"), tr("Text files(*.sql *.txt);;All files(*)")); - if(QFile::exists(file)) + for(const QString& file: wfiles) { - QFile f(file); - f.open(QIODevice::ReadOnly); - - // Decide whether to open a new tab or take the current one - unsigned int index; - SqlExecutionArea* current_tab = qobject_cast(ui->tabSqlAreas->currentWidget()); - if(current_tab->getSql().isEmpty() && current_tab->getModel()->rowCount() == 0) - index = ui->tabSqlAreas->currentIndex(); - else - index = openSqlTab(); + if(QFile::exists(file)) + { + // Decide whether to open a new tab or take the current one + int index; + SqlExecutionArea* current_tab = qobject_cast(ui->tabSqlAreas->currentWidget()); + if(current_tab && current_tab->getSql().isEmpty() && current_tab->getModel()->rowCount() == 0) + index = ui->tabSqlAreas->currentIndex(); + else + index = openSqlTab(); - SqlExecutionArea* sqlarea = qobject_cast(ui->tabSqlAreas->widget(index)); - sqlarea->getEditor()->setText(f.readAll()); - sqlarea->setFileName(file); - QFileInfo fileinfo(file); - ui->tabSqlAreas->setTabText(index, fileinfo.fileName()); + openSqlFile(index, file); + } } } -void MainWindow::saveSqlFile() +void MainWindow::saveSqlFile(int tabIndex) { - SqlExecutionArea* sqlarea = qobject_cast(ui->tabSqlAreas->currentWidget()); + SqlExecutionArea* sqlarea = qobject_cast(ui->tabSqlAreas->widget(tabIndex)); + if(!sqlarea) + return; // If this SQL file hasn't been saved before open the Save As dialog. Otherwise just use the old file name for saving if(sqlarea->fileName().isEmpty()) { saveSqlFileAs(); } else { - QFile f(sqlarea->fileName()); - f.open(QIODevice::WriteOnly); - f.write(sqlarea->getSql().toUtf8()); - - QFileInfo fileinfo(sqlarea->fileName()); - ui->tabSqlAreas->setTabText(ui->tabSqlAreas->currentIndex(), fileinfo.fileName()); + sqlarea->saveFile(sqlarea->fileName()); } } +void MainWindow::saveSqlFile() +{ + saveSqlFile(ui->tabSqlAreas->currentIndex()); +} + void MainWindow::saveSqlFileAs() { + SqlExecutionArea* sqlarea = qobject_cast(ui->tabSqlAreas->currentWidget()); + if(!sqlarea) + return; + + QStringList file_filter; + file_filter << FILE_FILTER_SQL + << FILE_FILTER_TXT + << FILE_FILTER_ALL; QString file = FileDialog::getSaveFileName( + CreateSQLFile, this, tr("Select file name"), - tr("Text files(*.sql *.txt);;All files(*)")); + file_filter.join(";;")); if(!file.isEmpty()) { - // Just set the selected file name and call the standard save action which is going to use it - qobject_cast(ui->tabSqlAreas->currentWidget())->setFileName(file); - saveSqlFile(); + sqlarea->saveFile(file); + + QFileInfo fileinfo(file); + ui->tabSqlAreas->setTabText(ui->tabSqlAreas->currentIndex(), fileinfo.fileName()); + ui->tabSqlAreas->setTabIcon(ui->tabSqlAreas->currentIndex(), QIcon(":/icons/document_open")); } } +void MainWindow::saveSqlResultsAsCsv() +{ + qobject_cast(ui->tabSqlAreas->currentWidget())->saveAsCsv(); +} + +void MainWindow::saveSqlResultsAsJson() +{ + qobject_cast(ui->tabSqlAreas->currentWidget())->saveAsJson(); +} + +void MainWindow::saveSqlResultsAsView() +{ + saveAsView(qobject_cast(ui->tabSqlAreas->currentWidget())->getModel()->query()); +} + void MainWindow::loadExtension() { + QStringList file_filter; + file_filter << FILE_FILTER_DYN + << FILE_FILTER_ALL; + QString file = FileDialog::getOpenFileName( + OpenExtensionFile, this, tr("Select extension file"), - tr("Extensions(*.so *.dll);;All files(*)")); + file_filter.join(";;")); if(file.isEmpty()) return; @@ -1523,480 +2355,425 @@ void MainWindow::loadExtension() if(db.loadExtension(file)) QMessageBox::information(this, QApplication::applicationName(), tr("Extension successfully loaded.")); else - QMessageBox::warning(this, QApplication::applicationName(), tr("Error loading extension: %1").arg(db.lastErrorMessage)); + QMessageBox::warning(this, QApplication::applicationName(), tr("Error loading extension: %1").arg(db.lastError())); } -void MainWindow::loadExtensionsFromSettings() +void MainWindow::reloadSettings() { - if(!db.isOpen()) - return; + // Set default application font size + qobject_cast(qApp)->reloadSettings(); - QStringList list = PreferencesDialog::getSettingsValue("extensions", "list").toStringList(); - foreach(QString ext, list) - { - if(db.loadExtension(ext) == false) - QMessageBox::warning(this, QApplication::applicationName(), tr("Error loading extension: %1").arg(db.lastErrorMessage)); + // Set data browser font + for(const auto& d : allTableBrowserDocks()) + d->tableBrowser()->reloadSettings(); + + // Set max recent files + const int newMaxRecentFiles = Settings::getValue("General", "maxRecentFiles").toInt(); + + if(MaxRecentFiles < newMaxRecentFiles) { + // If user increase max recent files value. + ui->fileRecentFiles->removeAction(clearRecentFilesAction); + + recentFileActs.resize(newMaxRecentFiles); + for(int i = MaxRecentFiles; i < newMaxRecentFiles; ++i) { + recentFileActs[i] = new QAction(this); + recentFileActs[i]->setVisible(false); + connect(recentFileActs[i], &QAction::triggered, this, &MainWindow::openRecentFile); + } + + for(int i = 0; i < newMaxRecentFiles; ++i) + ui->fileRecentFiles->insertAction(ui->fileExitAction, recentFileActs[i]); + + ui->fileRecentFiles->insertSeparator(ui->fileExitAction); + ui->fileRecentFiles->insertAction(ui->fileExitAction, clearRecentFilesAction); + + MaxRecentFiles = newMaxRecentFiles; + updateRecentFileActions(); + } else if (MaxRecentFiles > newMaxRecentFiles) { + // If user decrease max recent files value. + for(int i = (MaxRecentFiles - 1); i >= newMaxRecentFiles; --i) { + ui->fileRecentFiles->removeAction(recentFileActs[i]); + delete recentFileActs[i]; + } + + recentFileActs.resize(newMaxRecentFiles); + MaxRecentFiles = newMaxRecentFiles; + updateRecentFileActions(); } -} -void MainWindow::reloadSettings() -{ - // Read settings - int prefetch_size = PreferencesDialog::getSettingsValue("db", "prefetchsize").toInt(); - int log_fontsize = PreferencesDialog::getSettingsValue("log", "fontsize").toInt(); + Settings::AppStyle style = static_cast(Settings::getValue("General", "appStyle").toInt()); - QFont logfont("Monospace"); - logfont.setStyleHint(QFont::TypeWriter); - logfont.setPointSize(log_fontsize); + switch (style) { + case Settings::FollowDesktopStyle : + qApp->setStyleSheet(""); - // Set data browser font - QFont dataBrowserFont(PreferencesDialog::getSettingsValue("databrowser", "font").toString()); - dataBrowserFont.setPointSize(PreferencesDialog::getSettingsValue("databrowser", "fontsize").toInt()); - ui->dataTable->setFont(dataBrowserFont); + break; + case Settings::DarkStyle : + case Settings::LightStyle : + QFile f(style == Settings::DarkStyle ? ":qdarkstyle/dark/darkstyle.qss" : ":qdarkstyle/light/lightstyle.qss"); + if (!f.exists()) { + QMessageBox::warning(this, qApp->applicationName(), + tr("Could not find resource file: %1").arg(f.fileName())); + } else { + f.open(QFile::ReadOnly | QFile::Text); + QTextStream ts(&f); + qApp->setStyleSheet(ts.readAll()); + } + break; + } + + ui->toolbarDB->setToolButtonStyle(static_cast(Settings::getValue("General", "toolbarStyle").toInt())); + ui->dbToolbar->setToolButtonStyle(static_cast(Settings::getValue("General", "toolbarStyleStructure").toInt())); + ui->toolbarSql->setToolButtonStyle(static_cast(Settings::getValue("General", "toolbarStyleSql").toInt())); + // Other toolbars will follow Main Window ToolBar Style + ui->toolbarExtraDB->setToolButtonStyle(static_cast(Settings::getValue("General", "toolbarStyle").toInt())); + ui->toolbarProject->setToolButtonStyle(static_cast(Settings::getValue("General", "toolbarStyle").toInt())); // Set prefetch sizes for lazy population of table models - m_browseTableModel->setChunkSize(prefetch_size); - for(int i=0; i < ui->tabSqlAreas->count(); ++i) - { - SqlExecutionArea* sqlArea = qobject_cast(ui->tabSqlAreas->widget(i)); - sqlArea->reloadSettings(); - sqlArea->getModel()->setChunkSize(prefetch_size); - sqlArea->getResultView()->setFont(logfont); - } + for(int i=0;itabSqlAreas->count();++i) + qobject_cast(ui->tabSqlAreas->widget(i))->reloadSettings(); + + // Prepare log font + QFont logfont("Monospace"); + logfont.setStyleHint(QFont::TypeWriter); + logfont.setPointSize(Settings::getValue("log", "fontsize").toInt()); - // Set font for SQL logs + // Set font for SQL logs and edit dialog ui->editLogApplication->reloadSettings(); ui->editLogUser->reloadSettings(); + ui->editLogErrorLog->reloadSettings(); ui->editLogApplication->setFont(logfont); ui->editLogUser->setFont(logfont); + ui->editLogErrorLog->setFont(logfont); + editDock->reloadSettings(); + + // Set font for database structure views + QFont structure_font = ui->dbTreeWidget->font(); + structure_font.setPointSize(Settings::getValue("db", "fontsize").toInt()); + ui->dbTreeWidget->setFont(structure_font); + ui->treeSchemaDock->setFont(structure_font); // Load extensions - loadExtensionsFromSettings(); + db.loadExtensionsFromSettings(); // Refresh view - populateStructure(); - resetBrowser(); + emit db.structureUpdated(); + refreshTableBrowsers(); + + sqlb::setIdentifierQuoting(static_cast(Settings::getValue("editor", "identifier_quotes").toInt())); + + ui->tabSqlAreas->setTabsClosable( + Settings::getValue("editor", "close_button_on_tabs").toBool()); + + ui->actionDropSelectQueryCheck->setChecked(Settings::getValue("SchemaDock", "dropSelectQuery").toBool()); + ui->actionDropInsertCheck->setChecked(Settings::getValue("SchemaDock", "dropInsert").toBool()); + ui->actionDropNamesCheck->setChecked(!ui->actionDropSelectQueryCheck->isChecked() && + !ui->actionDropInsertCheck->isChecked()); + + ui->actionDropQualifiedCheck->setChecked(Settings::getValue("SchemaDock", "dropQualifiedNames").toBool()); + ui->actionEnquoteNamesCheck->setChecked(Settings::getValue("SchemaDock", "dropEnquotedNames").toBool()); + + if (Settings::getValue("db", "watcher").toBool()) + connect(&fileSystemWatch, &QFileSystemWatcher::fileChanged, this, &MainWindow::refreshDb, Qt::UniqueConnection); + else { + disconnect(&fileSystemWatch, &QFileSystemWatcher::fileChanged, nullptr, nullptr); + if (!fileSystemWatch.files().isEmpty()) + fileSystemWatch.removePaths(fileSystemWatch.files()); + } } -void MainWindow::httpresponse(QNetworkReply *reply) +void MainWindow::checkNewVersion(const bool automatic) { - if(reply->error() == QNetworkReply::NoError) - { - // Check for redirect - QVariant possibleRedirectUrl = - reply->attribute(QNetworkRequest::RedirectionTargetAttribute); - - if(!possibleRedirectUrl.toUrl().isEmpty()) - { - if(reply->url() == possibleRedirectUrl.toUrl()) - return; // escape possible redirect loop - m_NetworkManager->get(QNetworkRequest(possibleRedirectUrl.toUrl())); - return; - } + RemoteNetwork::get().fetch(QUrl("https://download.sqlitebrowser.org/currentrelease"), RemoteNetwork::RequestTypeCustom, + [this, automatic](const QByteArray& reply) { + QList info = reply.split('\n'); + if(info.size() >= 2) + { + QString version = info.at(0).trimmed(); + QString url = info.at(1).trimmed(); + compareVersionAndShowDialog(version, url, automatic); - // first line of the currentrelease file contains a major.minor.patch version string - QString sversion(reply->readLine()); + } + }, false, true); +} - QStringList versiontokens = sversion.split("."); - if(versiontokens.size() < 3) - return; +void MainWindow::compareVersionAndShowDialog(const QString& versionstring, const QString& url, const bool automatic) +{ + // versionString contains a major.minor.patch version string + QStringList versiontokens = versionstring.split("."); + if(versiontokens.size() < 3) + return; - int major = versiontokens[0].toInt(); - int minor = versiontokens[1].toInt(); - int patch = versiontokens[2].toInt(); + int major = versiontokens[0].toInt(); + int minor = versiontokens[1].toInt(); + int patch = versiontokens[2].toInt(); - bool newversion = false; - if(major > MAJOR_VERSION) + bool newversion = false; + if(major > MAJOR_VERSION) + newversion = true; + else if(major == MAJOR_VERSION) + { + if(minor > MINOR_VERSION) newversion = true; - else if(major == MAJOR_VERSION) + else if(minor == MINOR_VERSION) { - if(minor > MINOR_VERSION) + if(patch > PATCH_VERSION) newversion = true; - else if(minor == MINOR_VERSION) - { - if(patch > PATCH_VERSION) - newversion = true; - } } + } - if(newversion) - { - QSettings settings(QApplication::organizationName(), QApplication::organizationName()); - int ignmajor = settings.value("checkversion/ignmajor", 999).toInt(); - int ignminor = settings.value("checkversion/ignminor", 0).toInt(); - int ignpatch = settings.value("checkversion/ignpatch", 0).toInt(); + if(newversion) + { + int ignmajor = (automatic) ? Settings::getValue("checkversion", "ignmajor").toInt() : 0; + int ignminor = (automatic) ? Settings::getValue("checkversion", "ignminor").toInt() : 0; + int ignpatch = (automatic) ? Settings::getValue("checkversion", "ignpatch").toInt() : 0; - // check if the user doesn't care about the current update - if(!(ignmajor == major && ignminor == minor && ignpatch == patch)) + // check if the user doesn't care about the current update + if(!(ignmajor == major && ignminor == minor && ignpatch == patch)) + { + QMessageBox msgBox; + // WARN: Please note that if the user attempts to manually check for updates, the value of this variable may be nullptr. + QPushButton *idontcarebutton = (automatic) ? msgBox.addButton(tr("Don't show again"), QMessageBox::ActionRole) : nullptr; + msgBox.addButton(QMessageBox::Ok); + msgBox.setTextFormat(Qt::RichText); + msgBox.setWindowTitle(tr("New version available.")); + msgBox.setText(tr("A new DB Browser for SQLite version is available (%1.%2.%3).

" + "Please download at %4.").arg(major).arg(minor).arg(patch). + arg(url)); + msgBox.exec(); + + if(msgBox.clickedButton() == idontcarebutton) { - QMessageBox msgBox; - QPushButton *idontcarebutton = msgBox.addButton(tr("Don't show again"), QMessageBox::ActionRole); - msgBox.addButton(QMessageBox::Ok); - msgBox.setTextFormat(Qt::RichText); - msgBox.setWindowTitle(tr("New version available.")); - msgBox.setText(tr("A new DB Browser for SQLite version is available (%1.%2.%3).

" - "Please download at %4.").arg(major).arg(minor).arg(patch). - arg(QString(reply->readLine()).trimmed())); - msgBox.exec(); - - if(msgBox.clickedButton() == idontcarebutton) - { - // save that the user don't want to get bothered about this update - settings.beginGroup("checkversion"); - settings.setValue("ignmajor", major); - settings.setValue("ignminor", minor); - settings.setValue("ignpatch", patch); - settings.endGroup(); - } + // save that the user don't want to get bothered about this update + Settings::setValue("checkversion", "ignmajor", major); + Settings::setValue("checkversion", "ignminor", minor); + Settings::setValue("checkversion", "ignpatch", patch); } } } - - reply->deleteLater(); -} - -namespace { -/*! - * \brief guessdatatype try to parse the first 10 rows and decide the datatype - * \param model model to check the data - * \param column index of the column to check - * \return the guessed datatype - */ -QVariant::Type guessdatatype(SqliteTableModel* model, int column) -{ - QVariant::Type type = QVariant::Invalid; - for(int i = 0; i < std::min(10, model->rowCount()) && type != QVariant::String; ++i) + else { - QVariant data = model->data(model->index(i, column), Qt::EditRole); - if(data.convert(QVariant::Double)) - { - type = QVariant::Double; - } - else - { - QString s = model->data(model->index(i, column)).toString(); - QDate d = QDate::fromString(s, Qt::ISODate); - if(d.isValid()) - type = QVariant::DateTime; - else - type = QVariant::String; - } - + if(!automatic) + QMessageBox::information(this, QApplication::applicationName(), tr("You are using the latest version.")); } - return type; -} } -void MainWindow::updatePlot(SqliteTableModel *model, bool update) +void MainWindow::openLinkWiki() const { - // add columns to x/y selection tree widget - if(update) - { - // disconnect treeplotcolumns item changed updates - disconnect(ui->treePlotColumns, SIGNAL(itemChanged(QTreeWidgetItem*,int)), - this,SLOT(on_treePlotColumns_itemChanged(QTreeWidgetItem*,int))); - - m_currentPlotModel = model; - - // save current selected columns, so we can restore them after the update - QString sItemX; // selected X column - QMap mapItemsY; // selected Y columns with color - for(int i = 0; i < ui->treePlotColumns->topLevelItemCount(); ++i) - { - QTreeWidgetItem* item = ui->treePlotColumns->topLevelItem(i); - if(item->checkState(PlotColumnX) == Qt::Checked) - sItemX = item->text(PlotColumnField); - - if(item->checkState(PlotColumnY) == Qt::Checked) - { - mapItemsY[item->text(PlotColumnField)] = item->backgroundColor(PlotColumnY); - } - } + QDesktopServices::openUrl(QUrl("https://github.com/sqlitebrowser/sqlitebrowser/wiki")); +} - ui->treePlotColumns->clear(); +// 'Help | Bug Report...' link will set an appropriate body, add the system information and set the label 'bug' automatically to the issue +void MainWindow::openLinkBugReport() const +{ + const QString version = Application::versionString(); + const QString os = QSysInfo::prettyProductName(); + const QString kernelType = QSysInfo::kernelType(); + const QString kernelVersion = QSysInfo::kernelVersion(); + const QString arch = QSysInfo::currentCpuArchitecture(); + const QString built_for = QSysInfo::buildAbi(); - if(model) - { - for(int i = 0; i < model->columnCount(); ++i) - { - QVariant::Type columntype = guessdatatype(model, i); - if(columntype != QVariant::String && columntype != QVariant::Invalid) - { - QTreeWidgetItem* columnitem = new QTreeWidgetItem(ui->treePlotColumns); - // maybe i make this more complicated than i should - // but store the model column index in the first 16 bit and the type - // in the other 16 bits - uint itemdata = 0; - itemdata = i << 16; - itemdata |= columntype; - columnitem->setData(PlotColumnField, Qt::UserRole, itemdata); - columnitem->setText(PlotColumnField, model->headerData(i, Qt::Horizontal).toString()); - - // restore previous check state - if(mapItemsY.contains(columnitem->text(PlotColumnField))) - { - columnitem->setCheckState(PlotColumnY, Qt::Checked); - columnitem->setBackgroundColor(PlotColumnY, mapItemsY[columnitem->text(PlotColumnField)]); - } - else - columnitem->setCheckState(PlotColumnY, Qt::Unchecked); - if(sItemX == columnitem->text(PlotColumnField)) - columnitem->setCheckState(PlotColumnX, Qt::Checked); - else - columnitem->setCheckState(PlotColumnX, Qt::Unchecked); + QString sqlite_version, sqlcipher_version; + DBBrowserDB::getSqliteVersion(sqlite_version, sqlcipher_version); + if(sqlcipher_version.isNull()) + sqlite_version = QString("SQLite Version ") + sqlite_version; + else + sqlite_version = QString("SQLCipher Version ") + sqlcipher_version + QString(" (based on SQLite %1)").arg(sqlite_version); - ui->treePlotColumns->addTopLevelItem(columnitem); - } - } - } + const QString body = + QString("Details for the issue\n" + "--------------------\n\n" + "#### What did you do?\n\n\n" + "#### What did you expect to see?\n\n\n" + "#### What did you see instead?\n\n\n" + "Useful extra information\n" + "-------------------------\n" + "> DB4S v%1 [built for %2] on %3 (%4/%5) [%6]\n" + "> using %7\n" + "> and Qt %8") + .arg(version, built_for, os, kernelType, kernelVersion, arch, sqlite_version, QT_VERSION_STR); - ui->plotWidget->yAxis->setLabel("Y"); - ui->plotWidget->xAxis->setLabel("X"); - connect(ui->treePlotColumns, SIGNAL(itemChanged(QTreeWidgetItem*,int)), - this,SLOT(on_treePlotColumns_itemChanged(QTreeWidgetItem*,int))); - } + QUrlQuery query; + query.addQueryItem("labels", "bug"); + query.addQueryItem("body", body); - // search for the x axis select - QTreeWidgetItem* xitem = 0; - for(int i = 0; i < ui->treePlotColumns->topLevelItemCount(); ++i) - { - xitem = ui->treePlotColumns->topLevelItem(i); - if(xitem->checkState(PlotColumnX) == Qt::Checked) - break; + QUrl url("https://github.com/sqlitebrowser/sqlitebrowser/issues/new"); + url.setQuery(query); + QDesktopServices::openUrl(url); +} - xitem = 0; - } +// 'Help | Feature Request...' link will set an appropriate body and add the label 'enhancement' automatically to the issue +void MainWindow::openLinkFeatureRequest() const +{ + QUrlQuery query; - QStringList yAxisLabels; + // Add the label enhancement and use the Feature request template that + // we have in GitHub. + query.addQueryItem("labels", "enhancement"); + query.addQueryItem("template", "Feature_request.md"); - ui->plotWidget->clearGraphs(); - if(xitem) - { - // regain the model column index and the datatype - // leading 16 bit are column index, the other 16 bit are the datatype - // right now datatype is only important for X axis (date, non date) - uint xitemdata = xitem->data(PlotColumnField, Qt::UserRole).toUInt(); - int x = xitemdata >> 16; - int xtype = xitemdata & (uint)0xFF; + QUrl url("https://github.com/sqlitebrowser/sqlitebrowser/issues/new"); + url.setQuery(query); + QDesktopServices::openUrl(url); +} +void MainWindow::openLinkSqlCipherFaq() const +{ + QDesktopServices::openUrl(QUrl("https://discuss.zetetic.net/c/sqlcipher/sqlcipher-faq")); +} - // check if we have a x axis with datetime data - if(xtype == QVariant::DateTime) - { - ui->plotWidget->xAxis->setTickLabelType(QCPAxis::ltDateTime); - ui->plotWidget->xAxis->setDateTimeFormat("yyyy-MM-dd"); - } - else - { - ui->plotWidget->xAxis->setTickLabelType(QCPAxis::ltNumber); - } +void MainWindow::openLinkWebsite() const +{ + QDesktopServices::openUrl(QUrl("https://sqlitebrowser.org")); +} - // add graph for each selected y axis - for(int i = 0; i < ui->treePlotColumns->topLevelItemCount(); ++i) - { - QTreeWidgetItem* item = ui->treePlotColumns->topLevelItem(i); - if(item->checkState((PlotColumnY)) == Qt::Checked) - { - // regain the model column index and the datatype - // leading 16 bit are column index - uint itemdata = item->data(0, Qt::UserRole).toUInt(); - int column = itemdata >> 16; - QCPGraph* graph = ui->plotWidget->addGraph(); +void MainWindow::openLinkDonatePatreon() const +{ + QDesktopServices::openUrl(QUrl("https://www.patreon.com/bePatron?u=11578749")); +} - int y = column; +static void loadCondFormatMap(BrowseDataTableSettings::CondFormatMap& condFormats, QXmlStreamReader& xml, const QString& encoding) +{ + // using auto solves Qt 5/6 difference, QStringRef vs QStringView + const auto name = xml.name(); - graph->setPen(QPen(item->backgroundColor(PlotColumnY))); + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != name) { + if (xml.name() == QT_UNICODE_LITERAL("column")) { + size_t index = xml.attributes().value("index").toUInt(); + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("column")) { + if(xml.name() == QT_UNICODE_LITERAL("format")) { + QFont font; + if (xml.attributes().hasAttribute("font")) + font.fromString(xml.attributes().value("font").toString()); + else + Settings::getValue("databrowser", "font").toString(); - // prepare the data vectors for qcustomplot - // possible improvement might be a QVector subclass that directly - // access the model data, to save memory, we are copying here - QVector xdata(model->rowCount()), ydata(model->rowCount()); - for(int i = 0; i < model->rowCount(); ++i) - { - // convert x type axis if it's datetime - if(xtype == QVariant::DateTime) - { - QString s = model->data(model->index(i, x)).toString(); - QDateTime d = QDateTime::fromString(s, Qt::ISODate); - xdata[i] = d.toTime_t(); - } + CondFormat::Alignment align; + if (xml.attributes().hasAttribute("align")) + align = static_cast(xml.attributes().value("align").toInt()); else - { - xdata[i] = model->data(model->index(i, x)).toDouble(); - } + align = CondFormat::AlignLeft; - ydata[i] = model->data(model->index(i, y)).toDouble(); + condFormats[index].emplace_back(xml.attributes().value("condition").toString(), + QColor(xml.attributes().value("foreground").toString()), + QColor(xml.attributes().value("background").toString()), + font, align, encoding); + xml.skipCurrentElement(); } - - // set some graph styles - graph->setData(xdata, ydata); - graph->setLineStyle((QCPGraph::LineStyle) ui->comboLineType->currentIndex()); - // WARN: ssDot is removed - int shapeIdx = ui->comboPointShape->currentIndex(); - if (shapeIdx > 0) shapeIdx += 1; - graph->setScatterStyle(QCPScatterStyle((QCPScatterStyle::ScatterShape)shapeIdx, 5)); - - // gather Y label column names - yAxisLabels << model->headerData(y, Qt::Horizontal).toString(); } } - - ui->plotWidget->rescaleAxes(true); - - // set axis labels - ui->plotWidget->xAxis->setLabel(model->headerData(x, Qt::Horizontal).toString()); - ui->plotWidget->yAxis->setLabel(yAxisLabels.join("|")); } - ui->plotWidget->replot(); } -void MainWindow::on_treePlotColumns_itemChanged(QTreeWidgetItem *changeitem, int column) +static void loadBrowseDataTableSettings(BrowseDataTableSettings& settings, sqlb::TablePtr obj, QXmlStreamReader& xml) { - // disable change updates, or we get unwanted redrawing and weird behavior - disconnect(ui->treePlotColumns, SIGNAL(itemChanged(QTreeWidgetItem*,int)), - this,SLOT(on_treePlotColumns_itemChanged(QTreeWidgetItem*,int))); + settings.showRowid = xml.attributes().value("show_row_id").toInt(); + settings.encoding = xml.attributes().value("encoding").toString(); + settings.plotXAxis = xml.attributes().value("plot_x_axis").toString(); + settings.unlockViewPk = xml.attributes().value("unlock_view_pk").toString(); + if(xml.attributes().hasAttribute("freeze_columns")) + settings.frozenColumns = xml.attributes().value("freeze_columns").toUInt(); - // make sure only 1 X axis is selected - if(column == PlotColumnX) - { - for(int i = 0; i < ui->treePlotColumns->topLevelItemCount(); ++i) + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("table")) { + if(xml.name() == QT_UNICODE_LITERAL("sort")) { - QTreeWidgetItem* item = ui->treePlotColumns->topLevelItem(i); - if(item->checkState(column) == Qt::Checked && item != changeitem) + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("sort")) { - item->setCheckState(column, Qt::Unchecked); + if(xml.name() == QT_UNICODE_LITERAL("column")) + { + int index = xml.attributes().value("index").toInt(); + int mode = xml.attributes().value("mode").toInt(); + if(static_cast(index) < obj->fields.size()) + settings.sortColumns.emplace_back(obj->fields.at(static_cast(index)).name(), mode == Qt::AscendingOrder ? sqlb::OrderBy::Ascending : sqlb::OrderBy::Descending); + xml.skipCurrentElement(); + } } - } - } - else if(column == PlotColumnY) - { - if(changeitem->checkState(column) == Qt::Checked) - { - // get a default color - QColor curbkcolor = changeitem->backgroundColor(column); - QColor color = !curbkcolor.isValid() ? (Qt::GlobalColor)(qrand() % 13 + 5) : curbkcolor; - if(color.isValid()) - { - changeitem->setBackgroundColor(column, color); + } else if(xml.name() == QT_UNICODE_LITERAL("column_widths")) { + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("column_widths")) { + if (xml.name() == QT_UNICODE_LITERAL("column")) { + int index = xml.attributes().value("index").toInt(); + settings.columnWidths[index] = xml.attributes().value("value").toInt(); + xml.skipCurrentElement(); + } } - else + } else if(xml.name() == QT_UNICODE_LITERAL("filter_values")) { + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("filter_values")) { + if (xml.name() == QT_UNICODE_LITERAL("column")) { + size_t index = xml.attributes().value("index").toUInt(); + QString value = xml.attributes().value("value").toString(); + if(!value.isEmpty()) + settings.filterValues[obj->fields.at(index).name()] = value; + xml.skipCurrentElement(); + } + } + } else if(xml.name() == QT_UNICODE_LITERAL("conditional_formats")) { + loadCondFormatMap(settings.condFormats, xml, settings.encoding); + } else if(xml.name() == QT_UNICODE_LITERAL("row_id_formats")) { + loadCondFormatMap(settings.rowIdFormats, xml, settings.encoding); + } else if(xml.name() == QT_UNICODE_LITERAL("display_formats")) { + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("display_formats")) { + if (xml.name() == QT_UNICODE_LITERAL("column")) { + size_t index = xml.attributes().value("index").toUInt(); + settings.displayFormats[index] = xml.attributes().value("value").toString(); + xml.skipCurrentElement(); + } + } + } else if(xml.name() == QT_UNICODE_LITERAL("hidden_columns")) { + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("hidden_columns")) { + if (xml.name() == QT_UNICODE_LITERAL("column")) { + int index = xml.attributes().value("index").toInt(); + settings.hiddenColumns[index] = xml.attributes().value("value").toInt(); + xml.skipCurrentElement(); + } + } + } else if(xml.name() == QT_UNICODE_LITERAL("plot_y_axes")) { + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("plot_y_axes")) { + QString y1AxisName; + QString y2AxisName; + PlotDock::PlotSettings y1AxisSettings; + PlotDock::PlotSettings y2AxisSettings; + if (xml.name() == QT_UNICODE_LITERAL("y_axis")) { + y1AxisName = xml.attributes().value("name").toString(); + y1AxisSettings.lineStyle = xml.attributes().value("line_style").toInt(); + y1AxisSettings.pointShape = xml.attributes().value("point_shape").toInt(); + y1AxisSettings.colour = QColor (xml.attributes().value("colour").toString()); + y1AxisSettings.active = xml.attributes().value("active").toInt(); + xml.skipCurrentElement(); + } + settings.plotYAxes[0][y1AxisName] = y1AxisSettings; + if (xml.name() == QT_UNICODE_LITERAL("y2_axis")) { + y2AxisName = xml.attributes().value("name").toString(); + y2AxisSettings.lineStyle = xml.attributes().value("line_style").toInt(); + y2AxisSettings.pointShape = xml.attributes().value("point_shape").toInt(); + y2AxisSettings.colour = QColor (xml.attributes().value("colour").toString()); + y2AxisSettings.active = xml.attributes().value("active").toInt(); + xml.skipCurrentElement(); + } + settings.plotYAxes[1][y2AxisName] = y2AxisSettings; + } + } else if(xml.name() == QT_UNICODE_LITERAL("global_filter")) { + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("global_filter")) { - changeitem->setCheckState(column, Qt::Unchecked); + if(xml.name() == QT_UNICODE_LITERAL("filter")) + { + QString value = xml.attributes().value("value").toString(); + settings.globalFilters.push_back(value); + xml.skipCurrentElement(); + } } } } - - connect(ui->treePlotColumns, SIGNAL(itemChanged(QTreeWidgetItem*,int)), - this,SLOT(on_treePlotColumns_itemChanged(QTreeWidgetItem*,int))); - - updatePlot(m_currentPlotModel, false); -} - -void MainWindow::on_treePlotColumns_itemDoubleClicked(QTreeWidgetItem *item, int column) -{ - // disable change updates, or we get unwanted redrawing and weird behavior - disconnect(ui->treePlotColumns, SIGNAL(itemChanged(QTreeWidgetItem*,int)), - this,SLOT(on_treePlotColumns_itemChanged(QTreeWidgetItem*,int))); - - if(column == PlotColumnY) - { - // On double click open the colordialog - QColorDialog colordialog(this); - QColor curbkcolor = item->backgroundColor(column); - QColor precolor = !curbkcolor.isValid() ? (Qt::GlobalColor)(qrand() % 13 + 5) : curbkcolor; - QColor color = colordialog.getColor(precolor, this, tr("Choose a axis color")); - if(color.isValid()) - { - item->setCheckState(column, Qt::Checked); - item->setBackgroundColor(column, color); - } - else - { - item->setCheckState(column, Qt::Unchecked); - } - } - - connect(ui->treePlotColumns, SIGNAL(itemChanged(QTreeWidgetItem*,int)), - this,SLOT(on_treePlotColumns_itemChanged(QTreeWidgetItem*,int))); - - updatePlot(m_currentPlotModel, false); } - -void MainWindow::on_butSavePlot_clicked() -{ - QString fileName = FileDialog::getSaveFileName(this, - tr("Choose a filename to save under"), - tr("PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*)") - ); - if(!fileName.isEmpty()) - { - if(fileName.endsWith(".png", Qt::CaseInsensitive)) - { - ui->plotWidget->savePng(fileName); - } - else if(fileName.endsWith(".jpg", Qt::CaseInsensitive)) - { - ui->plotWidget->saveJpg(fileName); - } - else if(fileName.endsWith(".pdf", Qt::CaseInsensitive)) - { - ui->plotWidget->savePdf(fileName); - } - else if(fileName.endsWith(".bmp", Qt::CaseInsensitive)) - { - ui->plotWidget->saveBmp(fileName); - } - else - { - fileName += ".png"; - ui->plotWidget->savePng(fileName); - } - } -} - -void MainWindow::on_actionWiki_triggered() -{ - QDesktopServices::openUrl(QUrl("https://github.com/sqlitebrowser/sqlitebrowser/wiki")); -} - -void MainWindow::on_actionBug_report_triggered() -{ - QDesktopServices::openUrl(QUrl("https://github.com/sqlitebrowser/sqlitebrowser/issues/new")); -} - -void MainWindow::on_actionWebsite_triggered() -{ - QDesktopServices::openUrl(QUrl("http://sqlitebrowser.org")); -} - -void MainWindow::updateBrowseDataColumnWidth(int section, int /*old_size*/, int new_size) -{ - QSet selectedCols(ui->dataTable->selectedCols()); - QString tableName(ui->comboBrowseTable->currentText()); - if (!selectedCols.contains(section)) - { - browseTableSettings[tableName].columnWidths[section] = new_size; - } - else - { - ui->dataTable->blockSignals(true); - foreach (int col, selectedCols) - { - ui->dataTable->setColumnWidth(col, new_size); - browseTableSettings[tableName].columnWidths[col] = new_size; - } - ui->dataTable->blockSignals(false); - } -} - -bool MainWindow::loadProject(QString filename) +MainWindow::LoadAttempResult MainWindow::loadProject(QString filename, bool readOnly) { // Show the open file dialog when no filename was passed as parameter if(filename.isEmpty()) { - filename = FileDialog::getOpenFileName(this, - tr("Choose a file to open"), - tr("DB Browser for SQLite project file (*.sqbpro)")); + filename = FileDialog::getOpenFileName( + OpenProjectFile, + this, + tr("Choose a project file to open"), + tr("DB Browser for SQLite project file (*.sqbpro)")); } if(!filename.isEmpty()) @@ -2007,11 +2784,19 @@ bool MainWindow::loadProject(QString filename) QXmlStreamReader xml(&file); xml.readNext(); // token == QXmlStreamReader::StartDocument xml.readNext(); // name == sqlb_project - if(xml.name() != "sqlb_project") - return false; + if(xml.name() != QT_UNICODE_LITERAL("sqlb_project")) + return NotValidFormat; - addToRecentFilesMenu(filename); + // We are going to open a new project, so close the possible current one before opening another. + // Stop the opening process here if the user pressed the cancel button in there. + if(!closeFiles()) + return Aborted; + addToRecentFilesMenu(filename, readOnly); + currentProjectFilename = filename; + + int projectRestoreIdx = -1; + QString projectRestoreTabs; while(!xml.atEnd() && !xml.hasError()) { // Read next token @@ -2020,33 +2805,71 @@ bool MainWindow::loadProject(QString filename) // Handle element start if(token == QXmlStreamReader::StartElement) { - if(xml.name() == "db") + if(xml.name() == QT_UNICODE_LITERAL("db")) { + // Read only? + if(xml.attributes().hasAttribute("readonly") && xml.attributes().value("readonly").toInt()) + readOnly = true; + // DB file QString dbfilename = xml.attributes().value("path").toString(); - if(!QFile::exists(dbfilename)) + if(!QFile::exists(dbfilename)) { dbfilename = QFileInfo(filename).absolutePath() + QDir::separator() + dbfilename; - fileOpen(dbfilename, true); + // New DB filename is pending to be saved + isProjectModified = true; + } + if(!fileOpen(dbfilename, true, readOnly)) { + qWarning() << tr("DB file '%1' could not be opened").arg(dbfilename); + } ui->dbTreeWidget->collapseAll(); - } else if(xml.name() == "window") { + + // PRAGMAs + if(xml.attributes().hasAttribute("foreign_keys")) + db.setPragma("foreign_keys", xml.attributes().value("foreign_keys").toString()); + if(xml.attributes().hasAttribute("case_sensitive_like")) + db.setPragma("case_sensitive_like", xml.attributes().value("case_sensitive_like").toString()); + if(xml.attributes().hasAttribute("temp_store")) + db.setPragma("temp_store", xml.attributes().value("temp_store").toString()); + if(xml.attributes().hasAttribute("wal_autocheckpoint")) + db.setPragma("wal_autocheckpoint", xml.attributes().value("wal_autocheckpoint").toString()); + if(xml.attributes().hasAttribute("synchronous")) + db.setPragma("synchronous", xml.attributes().value("synchronous").toString()); + loadPragmas(); + } else if(xml.name() == QT_UNICODE_LITERAL("attached")) { + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("attached")) + { + if(xml.name() == QT_UNICODE_LITERAL("db")) + { + db.attach(xml.attributes().value("path").toString(), xml.attributes().value("schema").toString()); + xml.skipCurrentElement(); + } + } + } else if(xml.name() == QT_UNICODE_LITERAL("window")) { // Window settings - while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != "window") + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("window")) { - // Currently selected tab - if(xml.name() == "current_tab") - ui->mainTab->setCurrentIndex(xml.attributes().value("id").toString().toInt()); + if(xml.name() == QT_UNICODE_LITERAL("main_tabs")) { + projectRestoreTabs = xml.attributes().value("open").toString(); + projectRestoreIdx = xml.attributes().value("current").toString().toInt(); + xml.skipCurrentElement(); + } else if(xml.name() == QT_UNICODE_LITERAL("current_tab")) { + // Currently selected tab (3.11 or older format, first restore default open tabs) + projectRestoreTabs = defaultOpenTabs; + projectRestoreIdx = xml.attributes().value("id").toString().toInt(); + xml.skipCurrentElement(); + } } - } else if(xml.name() == "tab_structure") { + } else if(xml.name() == QT_UNICODE_LITERAL("tab_structure")) { // Database Structure tab settings - while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != "tab_structure") + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("tab_structure")) { - if(xml.name() == "column_width") + if(xml.name() == QT_UNICODE_LITERAL("column_width")) { // Tree view column widths ui->dbTreeWidget->setColumnWidth(xml.attributes().value("id").toString().toInt(), xml.attributes().value("width").toString().toInt()); xml.skipCurrentElement(); - } else if(xml.name() == "expanded_item") { + } else if(xml.name() == QT_UNICODE_LITERAL("expanded_item")) { // Tree view expanded items int parent = xml.attributes().value("parent").toString().toInt(); QModelIndex idx; @@ -2058,47 +2881,136 @@ bool MainWindow::loadProject(QString filename) xml.skipCurrentElement(); } } - } else if(xml.name() == "tab_browse") { + } else if(xml.name() == QT_UNICODE_LITERAL("tab_browse")) { + // Close all open tabs first. We call delete here to avoid the + // closed() signal being emitted which would open a new dock. + for(auto d : allTableBrowserDocks()) + delete d; + // Browse Data tab settings - while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != "tab_browse") + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("tab_browse")) { - if(xml.name() == "current_table") + if(xml.name() == QT_UNICODE_LITERAL("current_table")) { + // TODO This attribute was only created until version 3.12.0 which means we can remove support for this + // in the future. + // Currently selected table - ui->comboBrowseTable->setCurrentIndex(ui->comboBrowseTable->findText(xml.attributes().value("name").toString())); + QString table_name = xml.attributes().value("name").toString(); + sqlb::ObjectIdentifier currentTable; + if(!currentTable.fromSerialised(table_name.toStdString())) + { + // This is an old project file format which doesn't yet contain serialised table identifiers. This means + // we have to try our best to unserialise this one manually. The only problem is when the name of an + // attached database or of a table contains a dot character. In that case the name becomes ambigious and + // we just try to split it at the first dot. I don't think it affects many (if any) project files. But if + // it turn out to be wrong, we can always add a loop here which checks for any possible combination of schema + // and table name whether an object with that combination exists. + // TODO: Delete this code in the future when we don't expect there to be any project files in the old format anymore. + if(table_name.contains('.')) + { + currentTable.setSchema(table_name.left(table_name.indexOf('.')).toStdString()); + currentTable.setName(table_name.mid(table_name.indexOf('.')+1).toStdString()); + } else { + currentTable.setName(table_name.toStdString()); + } + } + + if (!currentTable.isEmpty()) + newTableBrowserTab(currentTable); + + xml.skipCurrentElement(); + } else if(xml.name() == QT_UNICODE_LITERAL("table")) { + // New browser tab + sqlb::ObjectIdentifier table; + table.fromSerialised(xml.attributes().value("table").toString().toStdString()); + QDockWidget* dock = newTableBrowserTab(table); + dock->setWindowTitle(xml.attributes().value("title").toString()); + + unsigned int dock_id = xml.attributes().value("dock_id").toUInt(); + if(dock_id) + dock->setObjectName("dockBrowse" + QString::number(dock_id)); + + if(xml.attributes().value("custom_title").toString() == "1") + dock->setProperty("custom_title", true); + + xml.skipCurrentElement(); + } else if(xml.name() == QT_UNICODE_LITERAL("dock_state")) { + // Dock state + ui->tabBrowsers->restoreState(QByteArray::fromHex(xml.attributes().value("state").toString().toUtf8())); + xml.skipCurrentElement(); - } else if(xml.name() == "default_encoding") { + } else if(xml.name() == QT_UNICODE_LITERAL("default_encoding")) { // Default text encoding - defaultBrowseTableEncoding = xml.attributes().value("codec").toString(); + TableBrowser::setDefaultEncoding(xml.attributes().value("codec").toString()); + xml.skipCurrentElement(); + } else if(xml.name() == QT_UNICODE_LITERAL("browsetable_info")) { + // This tag is only found in old project files. In newer versions (>= 3.11) it is replaced by a new implementation. + // 3.12 is the last version to support loading this file format, so just show a warning here. + if(!Settings::getValue("idontcare", "projectBrowseTable").toBool()) + { + QMessageBox msgBox; + QPushButton* idontcarebutton = msgBox.addButton(tr("Don't show again"), QMessageBox::ActionRole); + msgBox.addButton(QMessageBox::Ok); + msgBox.setTextFormat(Qt::RichText); + msgBox.setWindowTitle(qApp->applicationName()); + msgBox.setText(tr("This project file is using an old file format because it was created using DB Browser for SQLite " + "version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load " + "it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format.")); + msgBox.exec(); + if(msgBox.clickedButton() == idontcarebutton) + Settings::setValue("idontcare", "projectBrowseTable", false); + } + xml.skipCurrentElement(); - } else if(xml.name() == "browsetable_info") { - QString attrData = xml.attributes().value("data").toString(); - QByteArray temp = QByteArray::fromBase64(attrData.toUtf8()); - QDataStream stream(temp); - stream >> browseTableSettings; - populateTable(ui->comboBrowseTable->currentText()); // Refresh view - ui->dataTable->sortByColumn(browseTableSettings[ui->comboBrowseTable->currentText()].sortOrderIndex, - browseTableSettings[ui->comboBrowseTable->currentText()].sortOrderMode); - showRowidColumn(browseTableSettings[ui->comboBrowseTable->currentText()].showRowid); + } else if(xml.name() == QT_UNICODE_LITERAL("browse_table_settings")) { + + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("browse_table_settings")) { + if (xml.name() == QT_UNICODE_LITERAL("table")) { + + sqlb::ObjectIdentifier tableIdentifier = + sqlb::ObjectIdentifier (xml.attributes().value("schema").toString().toStdString(), + xml.attributes().value("name").toString().toStdString()); + sqlb::TablePtr table = db.getTableByName(tableIdentifier); + if(table == nullptr) { + qWarning() << tr("Table '%1' not found; settings ignored") + .arg(QString::fromStdString(tableIdentifier.toString())); + } else { + BrowseDataTableSettings settings; + loadBrowseDataTableSettings(settings, table, xml); + TableBrowser::setSettings(tableIdentifier, settings); + } + } + } + } else { xml.skipCurrentElement(); } } - } else if(xml.name() == "tab_sql") { - // Close existing tab - QWidget* w = ui->tabSqlAreas->widget(0); - ui->tabSqlAreas->removeTab(0); - delete w; + } else if(xml.name() == QT_UNICODE_LITERAL("tab_sql")) { + // Close all open tabs first + for(int i=ui->tabSqlAreas->count()-1;i>=0;i--) + closeSqlTab(i, true); // Execute SQL tab data - while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != "tab_sql") + while(xml.readNext() != QXmlStreamReader::EndElement && xml.name() != QT_UNICODE_LITERAL("tab_sql")) { - if(xml.name() == "sql") + if(xml.name() == QT_UNICODE_LITERAL("sql")) { // SQL editor tab - unsigned int index = openSqlTab(); - ui->tabSqlAreas->setTabText(index, xml.attributes().value("name").toString()); - qobject_cast(ui->tabSqlAreas->widget(index))->getEditor()->setText(xml.readElementText()); - } else if(xml.name() == "current_tab") { + int index = openSqlTab(); + + // if it has the filename attribute, it's a linked file, otherwise it's + // a free SQL buffer saved in the project. + if(xml.attributes().hasAttribute("filename")) { + openSqlFile(index, xml.attributes().value("filename").toString()); + xml.skipCurrentElement(); + } else { + ui->tabSqlAreas->setTabText(index, xml.attributes().value("name").toString()); + SqlTextEdit* sqlEditor = qobject_cast(ui->tabSqlAreas->widget(index))->getEditor(); + sqlEditor->setText(xml.readElementText()); + sqlEditor->setModified(false); + } + } else if(xml.name() == QT_UNICODE_LITERAL("current_tab")) { // Currently selected tab ui->tabSqlAreas->setCurrentIndex(xml.attributes().value("id").toString().toInt()); xml.skipCurrentElement(); @@ -2109,10 +3021,25 @@ bool MainWindow::loadProject(QString filename) } file.close(); - return !xml.hasError(); + + if (projectRestoreIdx != -1 && !projectRestoreTabs.isEmpty()) { + ui->mainTab->blockSignals(true); + restoreOpenTabs(projectRestoreTabs); + ui->mainTab->blockSignals(false); + ui->mainTab->setCurrentIndex(projectRestoreIdx); + } + + // This is done because on consecutive reloads, + // we have events in queue which will activate + // &TableBrowser::projectModified, + // append ourselves after those events + QMetaObject::invokeMethod(this, [this] { + isProjectModified = false; + }, Qt::QueuedConnection); + return !xml.hasError()? Success : Aborted; } else { // No project was opened - return false; + return Aborted; } } @@ -2132,33 +3059,187 @@ static void saveDbTreeState(const QTreeView* tree, QXmlStreamWriter& xml, QModel } } -void MainWindow::saveProject() +static void saveCondFormatMap(const QString& elementName, const BrowseDataTableSettings::CondFormatMap& condFormats, QXmlStreamWriter& xml) { - QString filename = FileDialog::getSaveFileName(this, - tr("Choose a filename to save under"), - tr("DB Browser for SQLite project file (*.sqbpro)"), - db.currentFile()); + xml.writeStartElement(elementName); + for(auto iter=condFormats.cbegin(); iter!=condFormats.cend(); ++iter) { + xml.writeStartElement("column"); + xml.writeAttribute("index", QString::number(iter->first)); + for(const auto& format : iter->second) { + xml.writeStartElement("format"); + xml.writeAttribute("condition", format.filter()); + xml.writeAttribute("background", format.backgroundColor().name()); + xml.writeAttribute("foreground", format.foregroundColor().name()); + xml.writeAttribute("font", format.font().toString()); + xml.writeAttribute("align", QString().setNum(format.alignment())); + xml.writeEndElement(); + } + xml.writeEndElement(); + } + xml.writeEndElement(); +} + +static void saveBrowseDataTableSettings(const BrowseDataTableSettings& object, sqlb::TablePtr obj, QXmlStreamWriter& xml) +{ + xml.writeAttribute("show_row_id", QString::number(object.showRowid)); + xml.writeAttribute("encoding", object.encoding); + xml.writeAttribute("plot_x_axis", object.plotXAxis); + xml.writeAttribute("unlock_view_pk", object.unlockViewPk); + xml.writeAttribute("freeze_columns", QString::number(object.frozenColumns)); + + xml.writeStartElement("sort"); + for(const auto& column : object.sortColumns) + { + xml.writeStartElement("column"); + xml.writeAttribute("index", QString::number(sqlb::getFieldNumber(obj, column.expr))); + xml.writeAttribute("mode", QString::number(column.direction)); + xml.writeEndElement(); + } + xml.writeEndElement(); + + xml.writeStartElement("column_widths"); + for(auto iter=object.columnWidths.cbegin(); iter!=object.columnWidths.cend(); ++iter) { + xml.writeStartElement("column"); + xml.writeAttribute("index", QString::number(iter->first)); + xml.writeAttribute("value", QString::number(iter->second)); + xml.writeEndElement(); + } + xml.writeEndElement(); + xml.writeStartElement("filter_values"); + for(auto iter=object.filterValues.cbegin(); iter!=object.filterValues.cend(); ++iter) { + xml.writeStartElement("column"); + xml.writeAttribute("index", QString::number(sqlb::getFieldNumber(obj, iter->first))); + xml.writeAttribute("value", iter->second); + xml.writeEndElement(); + } + xml.writeEndElement(); + saveCondFormatMap("conditional_formats", object.condFormats, xml); + saveCondFormatMap("row_id_formats", object.rowIdFormats, xml); + xml.writeStartElement("display_formats"); + for(auto iter=object.displayFormats.cbegin(); iter!=object.displayFormats.cend(); ++iter) { + xml.writeStartElement("column"); + xml.writeAttribute("index", QString::number(iter->first)); + xml.writeAttribute("value", iter->second); + xml.writeEndElement(); + } + xml.writeEndElement(); + xml.writeStartElement("hidden_columns"); + for(auto iter=object.hiddenColumns.cbegin(); iter!=object.hiddenColumns.cend(); ++iter) { + xml.writeStartElement("column"); + xml.writeAttribute("index", QString::number(iter->first)); + xml.writeAttribute("value", QString::number(iter->second)); + xml.writeEndElement(); + } + xml.writeEndElement(); + xml.writeStartElement("plot_y_axes"); + for(auto iter=object.plotYAxes[0].cbegin(); iter!=object.plotYAxes[0].cend(); ++iter) { + PlotDock::PlotSettings plotSettings = iter->second; + xml.writeStartElement("y_axis"); + xml.writeAttribute("name", iter->first); + xml.writeAttribute("line_style", QString::number(plotSettings.lineStyle)); + xml.writeAttribute("point_shape", QString::number(plotSettings.pointShape)); + xml.writeAttribute("colour", plotSettings.colour.name()); + xml.writeAttribute("active", QString::number(plotSettings.active)); + xml.writeEndElement(); + } + for(auto iter=object.plotYAxes[1].cbegin(); iter!=object.plotYAxes[1].cend(); ++iter) { + PlotDock::PlotSettings plotSettings = iter->second; + xml.writeStartElement("y2_axis"); + xml.writeAttribute("name", iter->first); + xml.writeAttribute("line_style", QString::number(plotSettings.lineStyle)); + xml.writeAttribute("point_shape", QString::number(plotSettings.pointShape)); + xml.writeAttribute("colour", plotSettings.colour.name()); + xml.writeAttribute("active", QString::number(plotSettings.active)); + xml.writeEndElement(); + } + xml.writeEndElement(); + xml.writeStartElement("global_filter"); + for(const auto& v : object.globalFilters) + { + xml.writeStartElement("filter"); + xml.writeAttribute("value", v); + xml.writeEndElement(); + } + xml.writeEndElement(); +} + +void MainWindow::saveProject(const QString& currentFilename) +{ + QString filename; + if(currentFilename.isEmpty()) { + QString basePathName = db.currentFile(); + // Remove database suffix + basePathName.chop(QFileInfo(basePathName).suffix().size()+1); + filename = FileDialog::getSaveFileName( + CreateProjectFile, + this, + tr("Choose a filename to save under"), + FILE_FILTER_SQLPRJ, + basePathName); + } else + filename = currentFilename; + if(!filename.isEmpty()) { // Make sure the file has got a .sqbpro ending - if(!filename.endsWith(".sqbpro", Qt::CaseInsensitive)) - filename.append(".sqbpro"); + if(!filename.endsWith(FILE_EXT_SQLPRJ_DEFAULT, Qt::CaseInsensitive)) + filename.append(FILE_EXT_SQLPRJ_DEFAULT); + + QSaveFile file(filename); + bool opened = file.open(QFile::WriteOnly | QFile::Text); + if(!opened) { + QMessageBox::warning(this, qApp->applicationName(), + tr("Could not open project file for writing.\nReason: %1").arg(file.errorString())); + currentProjectFilename.clear(); + return; + } + currentProjectFilename = filename; + QApplication::setOverrideCursor(Qt::WaitCursor); - QFile file(filename); - file.open(QFile::WriteOnly | QFile::Text); QXmlStreamWriter xml(&file); xml.writeStartDocument(); xml.writeStartElement("sqlb_project"); // Database file name xml.writeStartElement("db"); - xml.writeAttribute("path", db.currentFile()); + QFileInfo dbFileInfo (db.currentFile()); + QFileInfo projectFileInfo (filename); + + // Store a relative filename if the path to project and to DB is the same. + if(dbFileInfo.absolutePath() == projectFileInfo.absolutePath()) + xml.writeAttribute("path", dbFileInfo.fileName()); + else + xml.writeAttribute("path", db.currentFile()); + + xml.writeAttribute("readonly", QString::number(db.readOnly())); + xml.writeAttribute("foreign_keys", db.getPragma("foreign_keys")); + xml.writeAttribute("case_sensitive_like", db.getPragma("case_sensitive_like")); + xml.writeAttribute("temp_store", db.getPragma("temp_store")); + xml.writeAttribute("wal_autocheckpoint", db.getPragma("wal_autocheckpoint")); + xml.writeAttribute("synchronous", db.getPragma("synchronous")); + xml.writeEndElement(); + + // Attached databases + xml.writeStartElement("attached"); + db.executeSQL("PRAGMA database_list;", false, true, [&xml](int, std::vector values, std::vector) -> bool { + auto schema = values.at(1); + if(schema != "main" && schema != "temp") + { + auto path = values.at(2); + xml.writeStartElement("db"); + xml.writeAttribute("schema", schema); + xml.writeAttribute("path", path); + xml.writeEndElement(); + } + return false; + }); xml.writeEndElement(); // Window settings xml.writeStartElement("window"); - xml.writeStartElement("current_tab"); // Currently selected tab - xml.writeAttribute("id", QString::number(ui->mainTab->currentIndex())); + xml.writeStartElement("main_tabs"); // Currently open tabs + xml.writeAttribute("open", saveOpenTabs()); + xml.writeAttribute("current", QString::number(ui->mainTab->currentIndex())); xml.writeEndElement(); xml.writeEndElement(); @@ -2176,29 +3257,58 @@ void MainWindow::saveProject() // Browse Data tab settings xml.writeStartElement("tab_browse"); - xml.writeStartElement("current_table"); // Currently selected table - xml.writeAttribute("name", ui->comboBrowseTable->currentText()); + + for(const auto d : allTableBrowserDocks()) + { + xml.writeStartElement("table"); + xml.writeAttribute("title", d->windowTitle()); + xml.writeAttribute("custom_title", d->property("custom_title").toBool() ? "1" : "0"); + xml.writeAttribute("dock_id", d->objectName().mid(10)); // 10 is the length of "dockBrowse" + xml.writeAttribute("table", QString::fromStdString(d->tableBrowser()->currentlyBrowsedTableName().toSerialised())); + xml.writeEndElement(); + } + + xml.writeStartElement("dock_state"); + xml.writeAttribute("state", ui->tabBrowsers->saveState().toHex()); xml.writeEndElement(); + xml.writeStartElement("default_encoding"); // Default encoding for text stored in tables - xml.writeAttribute("codec", defaultBrowseTableEncoding); + xml.writeAttribute("codec", TableBrowser::defaultEncoding()); xml.writeEndElement(); - { // Table browser information - QByteArray temp; - QDataStream stream(&temp, QIODevice::WriteOnly); - stream << browseTableSettings; - xml.writeStartElement("browsetable_info"); - xml.writeAttribute("data", temp.toBase64()); + + xml.writeStartElement("browse_table_settings"); + const auto settings = TableBrowser::allSettings(); + for(auto tableIt=settings.cbegin(); tableIt!=settings.cend(); ++tableIt) { + + xml.writeStartElement("table"); + xml.writeAttribute("schema", QString::fromStdString(tableIt->first.schema())); + xml.writeAttribute("name", QString::fromStdString(tableIt->first.name())); + + auto obj = db.getTableByName(tableIt->first); + saveBrowseDataTableSettings(tableIt->second, obj, xml); xml.writeEndElement(); } + // + xml.writeEndElement(); + // xml.writeEndElement(); // Execute SQL tab data xml.writeStartElement("tab_sql"); for(int i=0;itabSqlAreas->count();i++) // All SQL tabs content { + SqlExecutionArea* sqlArea = qobject_cast(ui->tabSqlAreas->widget(i)); + QString sqlFilename = sqlArea->fileName(); xml.writeStartElement("sql"); - xml.writeAttribute("name", ui->tabSqlAreas->tabText(i)); - xml.writeCharacters(qobject_cast(ui->tabSqlAreas->widget(i))->getSql()); + xml.writeAttribute("name", ui->tabSqlAreas->tabText(i).remove(QRegularExpression("\\*$"))); + if(sqlFilename.isEmpty()) { + xml.writeCharacters(sqlArea->getSql()); + sqlArea->getEditor()->setModified(false); + } else { + xml.writeAttribute("filename", sqlFilename); + // Backwards compatibility, so older versions do not break. + xml.writeCharacters(tr("-- Reference to file \"%1\" (not supported by this version) --").arg(sqlFilename)); + } xml.writeEndElement(); } xml.writeStartElement("current_tab"); // Currently selected tab @@ -2208,42 +3318,61 @@ void MainWindow::saveProject() xml.writeEndElement(); xml.writeEndDocument(); - file.close(); + file.commit(); + addToRecentFilesMenu(filename); + setCurrentFile(db.currentFile()); + isProjectModified = false; + showStatusMessage5s(tr("Project saved to file '%1'").arg(currentProjectFilename)); + QApplication::restoreOverrideCursor(); } } -void MainWindow::fileAttach() +void MainWindow::saveProject() { - // Get file name of database to attach - QString file = FileDialog::getOpenFileName( - this, - tr("Choose a database file"), - FileDialog::getSqlDatabaseFileFilter()); + saveProject(currentProjectFilename); +} + +void MainWindow::saveProjectAs() +{ + saveProject(QString()); +} + +void MainWindow::fileAttach(const QString& fileName) +{ + QString file; + if (fileName.isEmpty()) { + + // Get file name of database to attach + file = FileDialog::getOpenFileName( + OpenDatabaseFile, + this, + tr("Choose a database file"), + FileDialog::getSqlDatabaseFileFilter()); + } else + file = fileName; + if(!QFile::exists(file)) return; // Attach it db.attach(file); -} - -void MainWindow::updateFilter(int column, const QString& value) -{ - m_browseTableModel->updateFilter(column, value); - browseTableSettings[ui->comboBrowseTable->currentText()].filterValues[column] = value; - setRecordsetLabel(); + isProjectModified = true; } void MainWindow::editEncryption() { #ifdef ENABLE_SQLCIPHER - CipherDialog dialog(this, true); - if(dialog.exec()) + CipherDialog cipherDialog(this, true); + if(cipherDialog.exec()) { // Show progress dialog even though we can't provide any detailed progress information but this // process might take some time. QProgressDialog progress(this); - progress.setCancelButton(0); + progress.setCancelButton(nullptr); + // Disable context help button on Windows + progress.setWindowFlags(progress.windowFlags() + & ~Qt::WindowContextHelpButtonHint); progress.setWindowModality(Qt::ApplicationModal); progress.show(); qApp->processEvents(); @@ -2252,257 +3381,690 @@ void MainWindow::editEncryption() bool ok = db.releaseAllSavepoints(); qApp->processEvents(); + const QString temporalFile = db.currentFile() + ".enctemp"; + // Create the new file first or it won't work if(ok) { - QFile file(db.currentFile() + ".enctemp"); + QFile file(temporalFile); file.open(QFile::WriteOnly); file.close(); } + CipherSettings cipherSettings = cipherDialog.getCipherSettings(); + // Attach a new database using the new settings qApp->processEvents(); if(ok) - ok = db.executeSQL(QString("ATTACH DATABASE '%1' AS sqlitebrowser_edit_encryption KEY '%2';").arg(db.currentFile() + ".enctemp").arg(dialog.password()), + ok = db.executeSQL("ATTACH DATABASE '" + temporalFile.toStdString() + "' AS sqlitebrowser_edit_encryption KEY " + cipherSettings.getPassword() + ";", false, false); qApp->processEvents(); if(ok) - ok = db.executeSQL(QString("PRAGMA sqlitebrowser_edit_encryption.cipher_page_size = %1").arg(dialog.pageSize()), false, false); + ok = db.executeSQL("PRAGMA sqlitebrowser_edit_encryption.cipher_page_size = " + std::to_string(cipherSettings.getPageSize()), false, false); + if(ok) + ok = db.executeSQL("PRAGMA sqlitebrowser_edit_encryption.cipher_hmac_algorithm = " + cipherSettings.getHmacAlgorithm(), false, false); + if(ok) + ok = db.executeSQL("PRAGMA sqlitebrowser_edit_encryption.cipher_kdf_algorithm = " + cipherSettings.getKdfAlgorithm(), false, false); + if(ok) + ok = db.executeSQL("PRAGMA sqlitebrowser_edit_encryption.kdf_iter = " + std::to_string(cipherSettings.getKdfIterations()), false, false); + if (ok) + ok = db.executeSQL("PRAGMA sqlitebrowser_edit_encryption.cipher_plaintext_header_size = " + std::to_string(cipherSettings.getPlaintextHeaderSize()), false, false); // Export the current database to the new one qApp->processEvents(); if(ok) ok = db.executeSQL("SELECT sqlcipher_export('sqlitebrowser_edit_encryption');", false, false); + // Set user version of the new database + qApp->processEvents(); + if (ok) + ok = db.executeSQL("PRAGMA sqlitebrowser_edit_encryption.user_version = " + std::to_string(db.getPragma("user_version").toInt()) + ";", false, false); + + // We need to detach the database before proceeding + qApp->processEvents(); + if (ok) + ok = db.executeSQL("DETACH sqlitebrowser_edit_encryption;", false, false); + // Check for errors qApp->processEvents(); if(ok) { // No errors: Then close the current database, switch names, open the new one and if that succeeded delete the old one + const QString currentFile = db.currentFile(); fileClose(); - QFile::rename(db.currentFile(), db.currentFile() + ".enctempold"); - QFile::rename(db.currentFile() + ".enctemp", db.currentFile()); - if(fileOpen(db.currentFile())) - QFile::remove(db.currentFile() + ".enctempold"); + QFile::rename(currentFile, temporalFile + "old"); + QFile::rename(temporalFile, currentFile); + if(fileOpen(currentFile)) + QFile::remove(temporalFile + "old"); } else { - QMessageBox::warning(this, qApp->applicationName(), db.lastErrorMessage); + QMessageBox::warning(this, qApp->applicationName(), db.lastError()); } } #endif } -void MainWindow::switchToBrowseDataTab(QString tableToBrowse) +void MainWindow::switchToBrowseDataTab(sqlb::ObjectIdentifier tableToBrowse) { // If no table name was provided get the currently selected table fromt he structure tab if(tableToBrowse.isEmpty()) { // Cancel here if there is no selection - if(!ui->dbTreeWidget->selectionModel()->hasSelection()) + if(!dbSelected->hasSelection()) return; - tableToBrowse = ui->dbTreeWidget->model()->data(ui->dbTreeWidget->currentIndex().sibling(ui->dbTreeWidget->currentIndex().row(), 0)).toString(); + tableToBrowse.setSchema(dbSelected->schema().toStdString()); + tableToBrowse.setName(dbSelected->name().toStdString()); } - resetBrowser(false); - ui->comboBrowseTable->setCurrentIndex(ui->comboBrowseTable->findText(tableToBrowse)); - ui->mainTab->setCurrentIndex(1); + TableBrowserDock* d = newTableBrowserTab(tableToBrowse); + + if (ui->mainTab->indexOf(ui->browser) == -1) + ui->mainTab->addTab(ui->browser, ui->browser->accessibleName()); + + // Don't emit a main tab changed signal here because all it would do is refreshing the just loaded table view + ui->mainTab->blockSignals(true); + ui->mainTab->setCurrentWidget(ui->browser); + ui->mainTab->blockSignals(false); + + // Bring new tab to foreground + Application::processEvents(); // For some reason this is required for raise() to work here. + d->raise(); +} + +void MainWindow::fileDetachDbTree() +{ + fileDetachTreeViewSelected(ui->dbTreeWidget); } -void MainWindow::on_buttonClearFilters_clicked() +void MainWindow::fileDetachTreeSchemaDock() { - ui->dataTable->filterHeader()->clearFilters(); + fileDetachTreeViewSelected(ui->treeSchemaDock); +} + +void MainWindow::fileDetachTreeViewSelected(QTreeView* treeView) +{ + // Cancel here if there is no selection + if (!treeView || !treeView->selectionModel()->hasSelection()) + { + return; + } + + // get the currently selected attached database from treeView parameter + std::string attached_as = treeView->model()->data(treeView->currentIndex().sibling(treeView->currentIndex().row(), DbStructureModel::ColumnSchema), Qt::EditRole).toString().toStdString(); + if (db.detach(attached_as)) + { + db.updateSchema(); + refreshTableBrowsers(/* all */ true); + isProjectModified = true; + } } void MainWindow::copyCurrentCreateStatement() { // Cancel if no field is currently selected - if(!ui->dbTreeWidget->selectionModel()->hasSelection()) + if(!dbSelected->hasSelection()) return; - // Get the CREATE statement from the Schema column - QString stmt = ui->dbTreeWidget->model()->data(ui->dbTreeWidget->currentIndex().sibling(ui->dbTreeWidget->currentIndex().row(), 3)).toString(); + // Get the CREATE statement from the SQL column + QString stmt = dbSelected->sql(); // Copy the statement to the global application clipboard QApplication::clipboard()->setText(stmt); } -void MainWindow::on_comboLineType_currentIndexChanged(int index) +void MainWindow::fileOpenReadOnly() +{ + // Redirect to 'standard' fileOpen(), with the read only flag set + fileOpen(QString(), false, true); +} + +void MainWindow::requestCollation(const QString& name, int eTextRep) { - Q_ASSERT(index >= QCPGraph::lsNone && - index <= QCPGraph::lsImpulse); - QCPGraph::LineStyle lineStyle = (QCPGraph::LineStyle) index; - for (int i = 0, ie = ui->plotWidget->graphCount(); i < ie; ++i) + // Show message box + if(!Settings::getValue("db", "dont_ask_collation").toBool()) { - QCPGraph * graph = ui->plotWidget->graph(i); - if (graph) - graph->setLineStyle(lineStyle); + QMessageBox msgbox; + QPushButton* button_dont_ask_again = msgbox.addButton(tr("Yes. Don't ask again"), QMessageBox::ActionRole); + msgbox.addButton(QMessageBox::Yes); + msgbox.addButton(QMessageBox::No); + msgbox.setTextFormat(Qt::RichText); + msgbox.setWindowTitle(tr("Collation needed! Proceed?")); + msgbox.setText(tr("A table in this database requires a special collation function '%1' " + "that this application can't provide without further knowledge.\n" + "If you choose to proceed, be aware bad things can happen to your database.\n" + "Create a backup!").arg(name)); + int reply = msgbox.exec(); + + // Remember Don't ask again setting and proceed if either that button or the Yes button was clicked. + // Cancel here if the No button was clicked + if(msgbox.clickedButton() == button_dont_ask_again) + { + Settings::setValue("db", "dont_ask_collation", false); + } else if(reply == QMessageBox::No) { + return; + } } - ui->plotWidget->replot(); + + // Add collation + auto pDb = db.get(tr("creating collation")); + sqlite3_create_collation(pDb.get(), name.toUtf8(), eTextRep, nullptr, collCompare); +} + +void MainWindow::renameSqlTab(int index) +{ + QString new_name = QInputDialog::getText(this, + qApp->applicationName(), + tr("Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut."), + QLineEdit::EchoMode::Normal, + ui->tabSqlAreas->tabText(index).remove(QRegularExpression("\\*$"))); + + + if(!new_name.isNull()) // Don't do anything if the Cancel button was clicked + ui->tabSqlAreas->setTabText(index, new_name); + markTabsModified(); } -void MainWindow::on_comboPointShape_currentIndexChanged(int index) +void MainWindow::setFindFrameVisibility(bool show) { - // WARN: because ssDot point shape is removed - if (index > 0) index += 1; - Q_ASSERT(index >= QCPScatterStyle::ssNone && - index < QCPScatterStyle::ssPixmap); - QCPScatterStyle::ScatterShape shape = (QCPScatterStyle::ScatterShape) index; - for (int i = 0, ie = ui->plotWidget->graphCount(); i < ie; ++i) + // Set the find frame visibility for all tabs, but leave the + // current as the last, to retain there the focus. + for(int i=0;itabSqlAreas->count();i++) + if (i != ui->tabSqlAreas->currentIndex()) + qobject_cast(ui->tabSqlAreas->widget(i))->setFindFrameVisibility(show); + if (ui->tabSqlAreas->count()>0) + qobject_cast(ui->tabSqlAreas->currentWidget())->setFindFrameVisibility(show); +} + +void MainWindow::openFindReplaceDialog() +{ + // The slot for the shortcut must discover which sqltexedit widget has the focus and then open its dialog. + SqlExecutionArea* sqlWidget = qobject_cast(ui->tabSqlAreas->currentWidget()); + + if (sqlWidget) + sqlWidget->getEditor()->openFindReplaceDialog(); +} + +void MainWindow::toggleSqlBlockComment() +{ + // The slot for the shortcut must discover which sqltexedit widget has the focus + SqlExecutionArea* sqlWidget = qobject_cast(ui->tabSqlAreas->currentWidget()); + + if (sqlWidget) + sqlWidget->getEditor()->toggleBlockComment(); +} + +void MainWindow::openSqlPrintDialog() +{ + // The slot for the shortcut must discover which sqltexedit widget has the focus and then open its dialog. + SqlExecutionArea* sqlWidget = qobject_cast(ui->tabSqlAreas->currentWidget()); + + if (sqlWidget) + sqlWidget->getEditor()->openPrintDialog(); +} + +void MainWindow::saveAsView(const std::string& query) +{ + // Let the user select a name for the new view and make sure it doesn't already exist + QString name; + while(true) { - QCPGraph * graph = ui->plotWidget->graph(i); - if (graph) - graph->setScatterStyle(QCPScatterStyle(shape, 5)); + name = QInputDialog::getText(this, qApp->applicationName(), tr("Please specify the view name")).trimmed(); + if(name.isNull()) + return; + if(db.getTableByName(sqlb::ObjectIdentifier("main", name.toStdString()))) + QMessageBox::warning(this, qApp->applicationName(), tr("There is already an object with that name. Please choose a different name.")); + else + break; } - ui->plotWidget->replot(); + + // Create the view + if(db.executeSQL("CREATE VIEW " + sqlb::escapeIdentifier(name.toStdString()) + " AS " + query + ";")) + QMessageBox::information(this, qApp->applicationName(), tr("View successfully created.")); + else + QMessageBox::warning(this, qApp->applicationName(), tr("Error creating view: %1").arg(db.lastError())); } -void MainWindow::jumpToRow(const QString& table, QString column, const QByteArray& value) +void MainWindow::runSqlNewTab(const QString& query, const QString& title, const QString& helpUrl, const bool autoRun) { - // First check if table exists - DBBrowserObject obj = db.getObjectByName(table); - if(obj.getname().size() == 0) + QString message; + + if(autoRun) + message = tr("This action will open a new SQL tab for running:"); + else + message = tr("This action will open a new SQL tab with the following statements for you to edit and run:"); + + message += QString("
%1
").arg(query.size() > 1000 ? query.left(1000) + "\n[...]" : query); + if(!helpUrl.isEmpty()) + message += tr("Press Help for opening the corresponding SQLite reference page."); + + QString windowTitle = title; + windowTitle.remove('&'); + auto result = QMessageBox::information(this, + windowTitle, + message, + QMessageBox::Ok | QMessageBox::Default, + QMessageBox::Cancel | QMessageBox::Escape, + helpUrl.isEmpty() ? 0 : QMessageBox::Help); + + switch (result) + { + case QMessageBox::Ok: { + if (ui->mainTab->indexOf(ui->query) == -1) + ui->mainTab->addTab(ui->query, ui->query->accessibleName()); + ui->mainTab->setCurrentWidget(ui->query); + int index = openSqlTab(); + ui->tabSqlAreas->setTabText(index, title); + qobject_cast(ui->tabSqlAreas->widget(index))->getEditor()->setText(query); + if(autoRun) + executeQuery(); + break; + } + case QMessageBox::Help: { + QDesktopServices::openUrl(QUrl(helpUrl)); + break; + } + default: return; + } +} - // If no column name is set, assume the primary key is meant - if(!column.size()) - column = obj.table.fields().at(obj.table.findPk())->name(); +void MainWindow::printDbStructure () +{ + const QTreeView* treeView = ui->dbTreeWidget; + const QAbstractItemModel* model = treeView->model(); - // If column doesn't exist don't do anything - int column_index = obj.table.findField(column); - if(column_index == -1) - return; + const int rowCount = model->rowCount(treeView->rootIndex()); + const int columnCount = model->columnCount(treeView->rootIndex()); + + QString strStream; + QTextStream out(&strStream); + + out << "" + << QString("%1").arg(treeView->windowTitle()) + << ""; + + for (int row = 0; row < rowCount; row++) { + + QModelIndex headerIndex = model->index(row, 0, treeView->rootIndex()); + QString strData = model->data(headerIndex).toString().toHtmlEscaped(); + out << QString("

%1

").arg(strData); + + // Open a new table for each group of objects + out << ""; + + for (int column = 0; column < columnCount; column++) { + // Headers + if (!treeView->isColumnHidden(column)) + out << QString("").arg(model->headerData(column, Qt::Horizontal).toString().toHtmlEscaped()); + } + out << ""; + + for (int column = 0; column < columnCount; column++) { + QModelIndex groupIndex = model->index(row, column, treeView->rootIndex()); + + // A row for the object name + for (int rowChild = 0; rowChild < model->rowCount(groupIndex); rowChild++) { + QModelIndex objectIndex = model->index(rowChild, column, groupIndex); + out << ""; + for (int column2 = 0; column2 < columnCount; column2++) { + if (!treeView->isColumnHidden(column2)) { + QModelIndex cellIndex = model->index(rowChild, column2, groupIndex); + QString header_data = model->data(cellIndex).toString().toHtmlEscaped(); + if (column2 != DbStructureModel::ColumnSQL) + out << QString("").arg((!header_data.isEmpty()) ? header_data : QString(" ")); + else + out << QString("").arg((!header_data.isEmpty()) ? header_data : QString(" ")); + } + } + out << ""; + + // One row for each object's fields + for (int rowChild2 = 0; rowChild2 < model->rowCount(objectIndex); rowChild2++) { + out << ""; + for (int column2 = 0; column2 < columnCount; column2++) { + if (!treeView->isColumnHidden(column2)) { + QModelIndex fieldIndex = model->index(rowChild2, column2, objectIndex); + QString field_data = model->data(fieldIndex).toString().toHtmlEscaped(); + out << QString("").arg((!field_data.isEmpty()) ? field_data : QString(" ")); + } + } + out << ""; + } + } + } + out << "
%1

%1

%1
%1
"; + } + out << ""; + + QPrinter printer; + printer.setDocName(treeView->windowTitle()); - // Jump to table - populateTable(table); + QPrintPreviewDialog *dialog = new QPrintPreviewDialog(&printer); + connect(dialog, &QPrintPreviewDialog::paintRequested, this, [strStream](QPrinter *previewPrinter) { + QTextDocument document; + document.setHtml(strStream); + document.print(previewPrinter); + }); + + dialog->exec(); + delete dialog; - // Set filter - ui->dataTable->filterHeader()->setFilter(column_index+1, value); } -void MainWindow::showDataColumnPopupMenu(const QPoint& pos) +void MainWindow::updateDatabaseBusyStatus(bool busy, const QString& user) { - // Get the index of the column which the user has clicked on and store it in the action. This is sort of hack-ish and it might be the heat in my room - // but I haven't come up with a better solution so far - int logical_index = ui->dataTable->horizontalHeader()->logicalIndexAt(pos); - if(logical_index == -1) // Don't open the popup menu if the user hasn't clicked on a column header - return; - ui->actionBrowseTableEditDisplayFormat->setProperty("clicked_column", logical_index); + statusBusyLabel->setText(tr("Busy (%1)").arg(user)); + statusBusyLabel->setVisible(busy); + statusStopButton->setVisible(busy); +} - // Calculate the proper position for the context menu and display it - popupBrowseDataHeaderMenu->exec(ui->dataTable->horizontalHeader()->mapToGlobal(pos)); +void MainWindow::closeTab(int index) +{ + ui->mainTab->removeTab(index); } -void MainWindow::editDataColumnDisplayFormat() +void MainWindow::toggleTabVisible(QWidget* tabWidget, bool show) { - // Get the current table name and fetch its table object, then retrieve the fields of that table and look up the index of the clicked table header - // section using it as the table field array index. Subtract one from the header index to get the column index because in the the first (though hidden) - // column is always the rowid column. Ultimately, get the column name from the column object - QString current_table = ui->comboBrowseTable->currentText(); - int field_number = sender()->property("clicked_column").toInt(); - QString field_name = db.getObjectByName(current_table).table.fields().at(field_number-1)->name(); + if (show) + ui->mainTab->addTab(tabWidget, tabWidget->accessibleName()); + else + ui->mainTab->removeTab(ui->mainTab->indexOf(tabWidget)); +} - // Get the current display format of the field - QString current_displayformat = browseTableSettings[current_table].displayFormats[field_number]; +void MainWindow::restoreOpenTabs(QString tabs) +{ + // Split the tab list, skipping the empty parts so the empty string turns to an empty list + // and not a list of one empty string. +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + const QStringList tabList = tabs.split(' ', QString::SkipEmptyParts); +#else + const QStringList tabList = tabs.split(' ', Qt::SkipEmptyParts); +#endif - // Open the dialog - ColumnDisplayFormatDialog dialog(field_name, current_displayformat, this); - if(dialog.exec()) - { - // Set the newly selected display format - QString new_format = dialog.selectedDisplayFormat(); - if(new_format.size()) - browseTableSettings[current_table].displayFormats[field_number] = new_format; - else - browseTableSettings[current_table].displayFormats.remove(field_number); + // Clear the tabs and then add them in the order specified by the setting. + // Use the accessibleName attribute for restoring the tab label. + if (!tabList.isEmpty()) { + // Avoid flickering while clearing and adding tabs. + ui->mainTab->setUpdatesEnabled(false); + ui->mainTab->clear(); + for (const auto& objectName : tabList) { + for (QWidget* widget : {ui->structure, ui->browser, ui->pragmas, ui->query}) + if (widget->objectName() == objectName) { + ui->mainTab->addTab(widget, widget->accessibleName()); + break; + } + } + ui->mainTab->setUpdatesEnabled(true); + // Force the update of the View menu toggable entries + // (it doesn't seem to be a better way) + emit ui->mainTab->tabCloseRequested(-1); + } +} + +QString MainWindow::saveOpenTabs() +{ + QString openTabs; + for (int i=0; i < ui->mainTab->count(); i++) + openTabs.append(ui->mainTab->widget(i)->objectName() + ' '); + openTabs.chop(1); + return openTabs; +} + +void MainWindow::showStatusMessage5s(QString message) +{ + ui->statusbar->showMessage(message, 5000); +} - // Refresh view - populateTable(current_table); +void MainWindow::saveAll() +{ + for(int i=0; itabSqlAreas->count(); i++) { + SqlExecutionArea* sqlExecArea = qobject_cast(ui->tabSqlAreas->widget(i)); + if(sqlExecArea->getEditor()->isModified() && !sqlExecArea->fileName().isEmpty()) + saveSqlFile(i); } + if(!currentProjectFilename.isEmpty()) + saveProject(); + fileSave(); + } -void MainWindow::showRowidColumn(bool show) +void MainWindow::showContextMenuSqlTabBar(const QPoint& pos) { - // Block all signals from the horizontal header. Otherwise the QHeaderView::sectionResized signal causes us trouble - ui->dataTable->horizontalHeader()->blockSignals(true); + // Don't show context menu if the mouse click was outside of all the tabs + int tab = ui->tabSqlAreas->tabBar()->tabAt(pos); + if(tab == -1) + return; - // Show/hide rowid column - ui->dataTable->setColumnHidden(0, !show); + // Prepare all menu actions + QAction* actionRename = new QAction(this); + actionRename->setText(tr("Rename Tab")); + connect(actionRename, &QAction::triggered, this, [this, tab]() { + renameSqlTab(tab); + }); + + QAction* actionDuplicate = new QAction(this); + actionDuplicate->setText(tr("Duplicate Tab")); + connect(actionDuplicate, &QAction::triggered, this, [this, tab]() { + QString tab_name = ui->tabSqlAreas->tabText(tab).remove("&").remove(QRegularExpression("\\*$")).remove(QRegularExpression(" \\(\\d+\\)$")); + QString new_tab_name; + for(int i=1;;i++) + { + new_tab_name = tab_name + QString(" (%1)").arg(i); + bool name_already_exists = false; + for(int j=0;jtabSqlAreas->count();j++) + { + if(ui->tabSqlAreas->tabText(j).remove("&").remove(QRegularExpression("\\*$")) == new_tab_name) + { + name_already_exists = true; + break; + } + } + + if(!name_already_exists) + break; + } - // Update checked status of the popup menu action - ui->actionShowRowidColumn->setChecked(show); + int new_tab = openSqlTab(); + ui->tabSqlAreas->setTabText(new_tab, new_tab_name); - // Save settings for this table - QString current_table = ui->comboBrowseTable->currentText(); - browseTableSettings[current_table].showRowid = show; + SqlExecutionArea* old_area = qobject_cast(ui->tabSqlAreas->widget(tab)); + SqlExecutionArea* new_area = qobject_cast(ui->tabSqlAreas->widget(new_tab)); + new_area->setSql(old_area->getSql()); + }); - // Update the filter row - qobject_cast(ui->dataTable->horizontalHeader())->generateFilters(m_browseTableModel->columnCount(), show); + QAction* actionClose = new QAction(this); + actionClose->setText(tr("Close Tab")); + actionClose->setShortcut(tr("Ctrl+W")); + connect(actionClose, &QAction::triggered, this, [this, tab]() { + closeSqlTab(tab); + }); - // Re-enable signals - ui->dataTable->horizontalHeader()->blockSignals(false); + // Show menu + QMenu* menuTabs = new QMenu(this); + menuTabs->addAction(actionRename); + menuTabs->addAction(actionDuplicate); + menuTabs->addAction(actionClose); + menuTabs->exec(ui->tabSqlAreas->mapToGlobal(pos)); } -void MainWindow::browseDataSetTableEncoding(bool forAllTables) +void MainWindow::openUrlOrFile(const QString& urlString) { - // Get the old encoding - QString encoding = m_browseTableModel->encoding(); + QUrl url = QUrl::fromUserInput(urlString, QFileInfo(db.currentFile()).path(), QUrl::AssumeLocalFile); + if(url.isValid()) { + if(QDesktopServices::openUrl(url)) + showStatusMessage5s(tr("Opening '%1'...").arg(url.toDisplayString())); + else + showStatusMessage5s(tr("There was an error opening '%1'...").arg(url.toDisplayString())); + + } else + showStatusMessage5s(tr("Value is not a valid URL or filename: %1").arg(url.errorString())); +} + +void MainWindow::focusSqlEditor() +{ + SqlExecutionArea* sqlArea = qobject_cast(ui->tabSqlAreas->currentWidget()); + if(sqlArea) + sqlArea->getEditor()->setFocus(); +} + +void MainWindow::moveDocksTo(Qt::DockWidgetArea area) +{ + addDockWidget(area, ui->dockEdit); + addDockWidget(area, ui->dockLog); + tabifyDockWidget(ui->dockLog, ui->dockPlot); + tabifyDockWidget(ui->dockLog, ui->dockSchema); +} + +void MainWindow::clearRecentFiles() +{ + Settings::clearValue("General", "recentFileList"); + + for(int i=0; i < MaxRecentFiles; ++i) + recentFileActs[i]->setVisible(false); +} - // Ask the user for a new encoding - bool ok; - QString question; - if(forAllTables) - question = tr("Please choose a new encoding for this table."); +sqlb::ObjectIdentifier MainWindow::currentlyBrowsedTableName() const +{ + if(currentTableBrowser) + return currentTableBrowser->currentlyBrowsedTableName(); else - question = tr("Please choose a new encoding for all tables."); - encoding = QInputDialog::getText(this, - tr("Set encoding"), - tr("%1\nLeave the field empty for using the database encoding.").arg(question), - QLineEdit::Normal, - encoding, - &ok); - - // Only set the new encoding if the user clicked the OK button - if(ok) + return sqlb::ObjectIdentifier{}; +} + +void MainWindow::tableBrowserTabClosed() +{ + // The closed() signal is emitted before the dock is destroyed. Since we + // always want to have at least one dock open we need to check if this is + // the last dock which is closed instead of if there is no dock remaining. + if(allTableBrowserDocks().size() == 1) { - // Check if encoding is valid - if(!QTextCodec::codecForName(encoding.toUtf8())) + newTableBrowserTab({}, /* forceHideTitlebar */ true); + } else { + // If only one dock will be left, make sure its titlebar is hidden, + // unless it's floating, so it can be closed or restored. + if(allTableBrowserDocks().size() == 2) { + for(auto dock : allTableBrowserDocks()) + if(!dock->isFloating()) + dock->setTitleBarWidget(new QWidget(dock)); + } + // If the currently active tab is closed activate another tab + if(currentTableBrowser && sender() == currentTableBrowser->parent()) { - QMessageBox::warning(this, qApp->applicationName(), tr("This encoding is either not valid or not supported.")); - return; + auto all_docks = allTableBrowserDocks(); + all_docks.front()->activateWindow(); + changeTableBrowserTab(all_docks.front()); } + } +} - // Set encoding for current table - m_browseTableModel->setEncoding(encoding); +TableBrowserDock* MainWindow::newTableBrowserTab(const sqlb::ObjectIdentifier& tableToBrowse, bool forceHideTitleBar) +{ + // Prepare new dock + TableBrowserDock* d = new TableBrowserDock(ui->tabBrowsers, this); + connect(d, &TableBrowserDock::closed, this, &MainWindow::tableBrowserTabClosed); + + // Initialise widget + d->tableBrowser()->setStructure(dbStructureModel, tableToBrowse); + d->tableBrowser()->setEnabled(ui->fileCloseAction->isEnabled()); + + // Connect signals and slots + connect(d, &TableBrowserDock::newDockRequested, this, [this]() { + newTableBrowserTab(); + }); + connect(d->tableBrowser(), &TableBrowser::projectModified, this, [this]() { + isProjectModified = true; + }); + connect(d->tableBrowser()->model(), &SqliteTableModel::dataChanged, this, &MainWindow::dataTableSelectionChanged); + connect(d->tableBrowser(), &TableBrowser::dataAboutToBeEdited, this, &MainWindow::dataTableSelectionChanged); + connect(d->tableBrowser(), &TableBrowser::selectionChanged, this, &MainWindow::dataTableSelectionChanged); + connect(d->tableBrowser(), &TableBrowser::selectionChangedByDoubleClick, this, &MainWindow::doubleClickTable); + connect(d->tableBrowser(), &TableBrowser::updatePlot, this, &MainWindow::attachPlot); + connect(d->tableBrowser(), &TableBrowser::createView, this, &MainWindow::saveAsView); + connect(d->tableBrowser(), &TableBrowser::requestFileOpen, this, [this](const QString& file) { + fileOpen(file); + }); + connect(d->tableBrowser(), &TableBrowser::statusMessageRequested, ui->statusbar, [this](const QString& message) { + ui->statusbar->showMessage(message); + }); + connect(d->tableBrowser(), &TableBrowser::foreignKeyClicked, this, [this](const sqlb::ObjectIdentifier& table, const std::string& column, const QByteArray& value) { + TableBrowserDock* foreign_key_dock = newTableBrowserTab(table); + foreign_key_dock->tableBrowser()->jumpToRow(table, column, value); + Application::processEvents(); // For some reason this is required for raise() to work here. + foreign_key_dock->raise(); + }); + connect(d->tableBrowser()->model(), &SqliteTableModel::finishedFetch, this, [this, d](){ + auto& settings = d->tableBrowser()->settings(d->tableBrowser()->currentlyBrowsedTableName()); + plotDock->updatePlot(d->tableBrowser()->model(), &settings, true, false); + }); + connect(d->tableBrowser(), &TableBrowser::prepareForFilter, editDock, &EditDialog::promptSaveData, Qt::QueuedConnection); + + // Restore titlebar for any other widget + for(auto dock : allTableBrowserDocks()) + dock->setTitleBarWidget(nullptr); + + // Hide titlebar if it is the only one dock + if(allTableBrowserDocks().size() == 1 || forceHideTitleBar) + d->setTitleBarWidget(new QWidget(d)); + + // Set up dock and add it to the tab + ui->tabBrowsers->addDockWidget(Qt::TopDockWidgetArea, d); + if(allTableBrowserDocks().size() > 1) +#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) + ui->tabBrowsers->tabifyDockWidget(allTableBrowserDocks().front(), d); +#else + ui->tabBrowsers->tabifyDockWidget(allTableBrowserDocks().constFirst(), d); +#endif - // Save encoding for this table - browseTableSettings[ui->comboBrowseTable->currentText()].encoding = encoding; + // Set current model and browser + d->activateWindow(); + changeTableBrowserTab(d); - // Set default encoding if requested to and change all stored table encodings - if(forAllTables) - { - defaultBrowseTableEncoding = encoding; + d->tableBrowser()->refresh(); - for(QMap::Iterator it=browseTableSettings.begin();it!=browseTableSettings.end();++it) - it.value().encoding = encoding; - } + return d; +} + +void MainWindow::changeTableBrowserTab(TableBrowserDock* dock) +{ + currentTableBrowser = dock->tableBrowser(); + + if(dock->tableBrowser() && dock->tableBrowser()->model() != m_currentTabTableModel) + { + // Make sure only the title of the active dock is highlighted + for(auto d : allTableBrowserDocks()) + d->setFocusStyle(false); + dock->setFocusStyle(true); + + m_currentTabTableModel = dock->tableBrowser()->model(); + const auto current_table_name = dock->tableBrowser()->currentlyBrowsedTableName(); + if(!current_table_name.isEmpty()) + plotDock->updatePlot(m_currentTabTableModel, &dock->tableBrowser()->settings(current_table_name), true, false); } } -void MainWindow::browseDataSetDefaultTableEncoding() +QList MainWindow::allTableBrowserDocks() const { - browseDataSetTableEncoding(true); + return ui->tabBrowsers->findChildren(); } -void MainWindow::browseDataFetchAllData() +void MainWindow::newRowCountsTab() { - if(m_browseTableModel) + QString sql; + for(const auto& it : db.schemata["main"].tables) { - // Make sure all data is loaded - while(m_browseTableModel->canFetchMore()) - m_browseTableModel->fetchMore(); - - // Update plot - updatePlot(m_browseTableModel); + sql += QString("SELECT %1 AS \"name\", '%2' AS \"type\", COUNT(*) AS \"rows\" FROM %3\nUNION ").arg( + QString::fromStdString(sqlb::escapeString(it.first)), + QString::fromStdString(it.second->isView() ? "view" : "table"), + QString::fromStdString(sqlb::escapeIdentifier(it.first))); } + sql.chop(7); // Remove the last "\nUNION " at the end + + runSqlNewTab(sql, ui->actionRowCounts->text()); +} + +void MainWindow::toggleAutoLoadLastDBFileAtStartupOption() +{ + optionToAutoLoadLastDBFileAtStartup->isChecked() ? Settings::setValue("General", "autoLoadLastDBFileAtStartup", true) + : Settings::setValue("General", "autoLoadLastDBFileAtStartup", false); } diff --git a/src/MainWindow.h b/src/MainWindow.h index 42cff2a2c..75d5e16c6 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -1,22 +1,31 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H -#include "sqltextedit.h" +#include "dbstructureqitemviewfacade.h" #include "sqlitedb.h" +#include +#include + #include -#include +#include -class QDragEnterEvent; +struct BrowseDataTableSettings; +class DbStructureModel; class EditDialog; -class QIntValidator; -class QLabel; -class QModelIndex; +class ExtendedTableWidget; +class FindReplaceDialog; +class PlotDock; +class RunSql; class SqliteTableModel; -class DbStructureModel; -class QNetworkReply; -class QNetworkAccessManager; -class QTreeWidgetItem; +class TableBrowser; +class TableBrowserDock; + +class QDragEnterEvent; +class QModelIndex; +class QLabel; +class QPersistentModelIndex; +class QToolButton; namespace Ui { class MainWindow; @@ -26,51 +35,22 @@ class MainWindow : public QMainWindow { Q_OBJECT +friend TableBrowserDock; + public: - explicit MainWindow(QWidget* parent = 0); - ~MainWindow(); + explicit MainWindow(QWidget* parent = nullptr); + ~MainWindow() override; - DBBrowserDB* getDb() { return &db; } + DBBrowserDB& getDb() { return db; } - struct BrowseDataTableSettings +private: + enum LoadAttempResult { - int sortOrderIndex; - Qt::SortOrder sortOrderMode; - QMap columnWidths; - QMap filterValues; - QMap displayFormats; - bool showRowid; - QString encoding; - - friend QDataStream& operator<<(QDataStream& stream, const MainWindow::BrowseDataTableSettings& object) - { - stream << object.sortOrderIndex; - stream << static_cast(object.sortOrderMode); - stream << object.columnWidths; - stream << object.filterValues; - stream << object.displayFormats; - stream << object.showRowid; - stream << object.encoding; - - return stream; - } - friend QDataStream& operator>>(QDataStream& stream, MainWindow::BrowseDataTableSettings& object) - { - stream >> object.sortOrderIndex; - int sortordermode; - stream >> sortordermode; - object.sortOrderMode = static_cast(sortordermode); - stream >> object.columnWidths; - stream >> object.filterValues; - stream >> object.displayFormats; - stream >> object.showRowid; - stream >> object.encoding; - - return stream; - } + Success, + NotValidFormat, + Aborted }; -private: struct PragmaValues { int autovacuum; @@ -90,143 +70,194 @@ class MainWindow : public QMainWindow int temp_store; int user_version; int wal_autocheckpoint; + int case_sensitive_like; } pragmaValues; - enum PlotColumns - { - PlotColumnField = 0, - PlotColumnX = 1, - PlotColumnY = 2, - PlotColumnDummy = 3 - }; - Ui::MainWindow* ui; - SqliteTableModel* m_browseTableModel; + DBBrowserDB db; + SqliteTableModel* m_currentTabTableModel; - SqliteTableModel* m_currentPlotModel; - QMenu *popupTableMenu; - QMenu *recentFilesMenu; - QMenu *popupSaveSqlFileMenu; - QMenu* popupBrowseDataHeaderMenu; + + QMenu* popupTableMenu; + QMenu* popupSchemaDockMenu; + QMenu* recentFilesMenu; + QMenu* popupOpenDbMenu; + QMenu* popupSaveSqlFileMenu; + QMenu* popupSaveSqlResultsMenu; QLabel* statusEncodingLabel; QLabel* statusEncryptionLabel; QLabel* statusReadOnlyLabel; + QToolButton* statusStopButton; + QLabel* statusBusyLabel; DbStructureModel* dbStructureModel; - enum { MaxRecentFiles = 5 }; - QAction *recentFileActs[MaxRecentFiles]; - QAction *recentSeparatorAct; + static int MaxRecentFiles; + QVector recentFileActs; + QAction* clearRecentFilesAction; + QAction* optionToAutoLoadLastDBFileAtStartup; + QAction* recentSeparatorAct; + + /** + * @brief dbSelected provides a simple read only interface to the actual selected node of ui->dbTreeWidget + */ + DbStructureQItemViewFacade *dbSelected; - QMap browseTableSettings; + /** + * @brief dockDbSelected provides a simple read only interface to the actual selected node of ui->treeSchemaDock + */ + DbStructureQItemViewFacade *dockDbSelected; - EditDialog* editWin; EditDialog* editDock; - QIntValidator* gotoValidator; + PlotDock* plotDock; + TableBrowser* currentTableBrowser; + FindReplaceDialog* findReplaceDialog; - DBBrowserDB db; - QString defaultBrowseTableEncoding; + std::unique_ptr execute_sql_worker; + + QString defaultOpenTabs; + QByteArray defaultWindowState; - QNetworkAccessManager* m_NetworkManager; + QString currentProjectFilename; + bool isProjectModified; + + QFileSystemWatcher fileSystemWatch; void init(); void clearCompleterModelsFields(); void updateRecentFileActions(); + void clearRecentFiles(); + void toggleAutoLoadLastDBFileAtStartupOption(); void setCurrentFile(const QString& fileName); - void addToRecentFilesMenu(const QString& filename); + void addToRecentFilesMenu(const QString& filename, bool read_only = false); void activateFields(bool enable = true); - void loadExtensionsFromSettings(); + void saveAsView(const std::string& query); + void attachPlot(ExtendedTableWidget* tableWidget, SqliteTableModel* model, BrowseDataTableSettings* settings = nullptr, bool keepOrResetSelection = true); + + void toggleTabVisible(QWidget* tabWidget, bool show); + void restoreOpenTabs(QString tabs); + QString saveOpenTabs(); + void saveProject(const QString& currentFilename); + bool closeProject(); + bool askSaveSqlTab(int index, bool& ignoreUnattachedBuffers); + void focusSqlEditor(); + void moveDocksTo(Qt::DockWidgetArea area); + + // Identifier of the currently browsed table in the current data browser tab + sqlb::ObjectIdentifier currentlyBrowsedTableName() const; + + QList allTableBrowserDocks() const; + void getSelectedObject(QString &type, sqlb::ObjectIdentifier& obj); protected: - void closeEvent(QCloseEvent *); - void dragEnterEvent(QDragEnterEvent *event); - void dropEvent(QDropEvent *event); - void resizeEvent(QResizeEvent *event); + void closeEvent(QCloseEvent *) override; + void dragEnterEvent(QDragEnterEvent *event) override; + void dropEvent(QDropEvent *event) override; + void resizeEvent(QResizeEvent *event) override; public slots: - bool fileOpen(const QString& fileName = QString(), bool dontAddToRecentFiles = false); + bool fileOpen(const QString& fileName = QString(), bool openFromProject = false, bool readOnly = false); void logSql(const QString &sql, int msgtype); void dbState(bool dirty); - void browseRefresh(); - void jumpToRow(const QString& table, QString column, const QByteArray& value); - void switchToBrowseDataTab(QString tableToBrowse = QString()); + void refresh(); + void switchToBrowseDataTab(sqlb::ObjectIdentifier tableToBrowse = sqlb::ObjectIdentifier()); + void populateStructure(const std::vector& old_tables = {}); + void fileDetachDbTree(); + void fileDetachTreeSchemaDock(); + void fileDetachTreeViewSelected(QTreeView* treeView); + void reloadSettings(); + bool closeFiles(); + void importCSVfiles(const std::vector& inputFiles, const QString& table = QString()); private slots: void createTreeContextMenu(const QPoint & qPoint); - void changeTreeSelection(); + void createSchemaDockContextMenu(const QPoint & qPoint); + void changeObjectSelection(); void fileNew(); - void populateStructure(); - void populateTable(QString tablename); - void resetBrowser(bool reloadTable = true); + void fileNewInMemoryDatabase(bool open_create_dialog = true); + // Refresh visible table browsers. When all is true, refresh all browsers. + void refreshTableBrowsers(bool all = false); + void refreshDb(); bool fileClose(); - void addRecord(); - void deleteRecord(); - void selectTableLine( int lineToSelect ); - void navigatePrevious(); - void navigateNext(); - void navigateBegin(); - void navigateEnd(); - void navigateGoto(); - void setRecordsetLabel(); + bool fileSaveAs(); void createTable(); void createIndex(); void compact(); void deleteObject(); - void editTable(); + void editObject(); void helpWhatsThis(); void helpAbout(); - void updateRecordText(int row, int col, bool type, const QByteArray& newtext); - void editWinAway(); + void updateRecordText(const QPersistentModelIndex& idx, const QByteArray& text, bool isBlob); + void evaluateText(const QPersistentModelIndex& idx, const std::string& text); + void toggleEditDock(bool visible); void dataTableSelectionChanged(const QModelIndex& index); void doubleClickTable(const QModelIndex& index); void executeQuery(); void importTableFromCSV(); void exportTableToCSV(); + void exportTableToJson(); void fileSave(); void fileRevert(); + void undo(); void exportDatabaseToSQL(); void importDatabaseFromSQL(); - void openPreferences(); void openRecentFile(); void loadPragmas(); void updatePragmaUi(); void savePragmas(); void mainTabSelected( int tabindex ); - void browseTableHeaderClicked(int logicalindex); - unsigned int openSqlTab(bool resetCounter = false); - void closeSqlTab(int index, bool force = false); + void openSqlFile(int tabindex, QString filename); void openSqlFile(); void saveSqlFile(); void saveSqlFileAs(); + void saveSqlResultsAsCsv(); + void saveSqlResultsAsJson(); + void saveSqlResultsAsView(); void loadExtension(); - void reloadSettings(); - void httpresponse(QNetworkReply* reply); - void updatePlot(SqliteTableModel* model, bool update = true); - void on_treePlotColumns_itemChanged(QTreeWidgetItem *item, int column); - void on_treePlotColumns_itemDoubleClicked(QTreeWidgetItem *item, int column); - void on_butSavePlot_clicked(); - void on_actionWiki_triggered(); - void on_actionBug_report_triggered(); - void on_actionWebsite_triggered(); - void updateBrowseDataColumnWidth(int section, int /*old_size*/, int new_size); - bool loadProject(QString filename = QString()); + void checkNewVersion(const bool automatic); + void compareVersionAndShowDialog(const QString& versionstring, const QString& url, const bool automatic); + void openLinkWiki() const; + void openLinkBugReport() const; + void openLinkFeatureRequest() const; + void openLinkSqlCipherFaq() const; + void openLinkWebsite() const; + void openLinkDonatePatreon() const; + LoadAttempResult loadProject(QString filename = QString(), bool readOnly = false); void saveProject(); - void fileAttach(); - void updateFilter(int column, const QString& value); + void saveProjectAs(); + void fileAttach(const QString& fileName = QString()); void editEncryption(); - void on_buttonClearFilters_clicked(); void copyCurrentCreateStatement(); - void on_comboLineType_currentIndexChanged(int index); - void on_comboPointShape_currentIndexChanged(int index); - void showDataColumnPopupMenu(const QPoint& pos); - void editDataColumnDisplayFormat(); - void showRowidColumn(bool show); - void browseDataSetTableEncoding(bool forAllTables = false); - void browseDataSetDefaultTableEncoding(); - void browseDataFetchAllData(); + void fileOpenReadOnly(); + void requestCollation(const QString& name, int eTextRep); + void setFindFrameVisibility(bool show); + void openFindReplaceDialog(); + void toggleSqlBlockComment(); + void openSqlPrintDialog(); + void runSqlNewTab(const QString& query, const QString& title, const QString& helpUrl = QString(), const bool autoRun = true); + void printDbStructure(); + void updateDatabaseBusyStatus(bool busy, const QString& user); + void openPreferences(); + void closeTab(int index); + void showStatusMessage5s(QString message); + void saveSqlFile(int tabIndex); + void saveAll(); + void openUrlOrFile(const QString& urlString); + void newRowCountsTab(); + + void markTabsModified(); + int openSqlTab(bool resetCounter = false); + void closeSqlTab(int index, bool force = false, bool askSaving = true); + void changeSqlTab(int index); + void renameSqlTab(int index); + void showContextMenuSqlTabBar(const QPoint& pos); + + TableBrowserDock* newTableBrowserTab(const sqlb::ObjectIdentifier& tableToBrowse = {}, bool forceHideTitleBar = false); + void tableBrowserTabClosed(); + void changeTableBrowserTab(TableBrowserDock* dock); }; #endif diff --git a/src/MainWindow.ui b/src/MainWindow.ui index a5a99b0e0..e3cc4b506 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -19,27 +19,71 @@ + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + 0 + + true + + + true + + + &Database Structure + - Database &Structure + &Database Structure + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + - toolBar1 + toolBar1 Qt::ToolButtonTextBesideIcon - + + + + + + @@ -47,6 +91,11 @@ Qt::CustomContextMenu + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + true @@ -67,339 +116,125 @@ + + &Browse Data + &Browse Data + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - - - - - Table: - - - comboBrowseTable - - - - - - - - 1 - 0 - - - - - 150 - 0 - - - - Select a table to browse data - - - Use this list to select a table to be displayed in the database view - - - - - - - Refresh the data in the selected table. - - - This button refreshes the data in the currently selected table. - - - - - - - :/icons/refresh:/icons/refresh - - - F5 - - - - - - - Clear all filters - - - - - - - :/icons/clear_filters:/icons/clear_filters - - - - - - - Qt::Horizontal - - - - 200 - 20 - - - - - - - - Insert a new record in the current table - - - This button creates a new, empty record in the database - - - New Record - - - - - - - Delete the current record - - - This button deletes the record currently selected in the database - - - Delete Record - - - - - - - - - true - - - This is the database view. You can double-click any record to edit its contents in the cell editor window. - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::DragDrop + + + Qt::CustomContextMenu - - Qt::CopyAction + + QMainWindow::AllowNestedDocks|QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks - - true - - - - - - - false - - - <html><head/><body><p>Scroll to the beginning</p></body></html> - - - <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> - - - |< - - - - - - - false - - - Scroll 100 records upwards - - - <html><head/><body><p>Clicking this button navigates 100 records upwards in the table view above.</p></body></html> - - - < - - - - - - - 0 - 0 of 0 - - - - - - - false - - - <html><head/><body><p>Scroll 100 records downwards</p></body></html> - - - <html><head/><body><p>Clicking this button navigates 100 records downwards in the table view above.</p></body></html> - - - > - - - - - - - false - - - Scroll to the end - - - <html><head/><body><p>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Clicking this button navigates up to the end in the table view above.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html> - - - >| - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - <html><head/><body><p>Click here to jump to the specified record</p></body></html> - - - <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> - - - Go to: - - - - - - - Enter record number to browse - - - Type a record number in this area and click the Go to: button to display the record in the database view - - - 1 - - - - - + + Edit P&ragmas + - Edit &Pragmas + Edit P&ragmas + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + - - true - - - - 0 - 0 - 468 - 558 - + + + 0 + 0 + - - - QFormLayout::ExpandingFieldsGrow + + + QLayout::SetMinAndMaxSize - - - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> - - - true + + + + PRAGMA wal_autocheckpoint - - Qt::LinksAccessibleByMouse + + WAL Auto Checkpoint - comboboxPragmaAutoVacuum + spinPragmaWalAutoCheckpoint - - - - - None - - - - - Full - - - - - Incremental - - - - - - - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> + + + + PRAGMA recursive_triggers - - true + + Recursive Triggers - checkboxPragmaAutomaticIndex + checkboxPragmaRecursiveTriggers - - + + + + PRAGMA auto_vacuum + - + Auto Vacuum + + + comboboxPragmaAutoVacuum - - + + + + https://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter true @@ -409,267 +244,320 @@ - - + + - - + + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></a></p></body></html> + - - true + + + + + + PRAGMA max_page_count + + + Max Page Count - checkboxPragmaForeignKeys + spinPragmaMaxPageCount - - + + + + https://www.sqlite.org/pragma.html#pragma_user_version + - + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_user_version"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter + + + true + + + spinPragmaUserVersion - - + + + + https://www.sqlite.org/pragma.html#pragma_journal_mode + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_journal_mode"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter true - checkboxPragmaFullFsync + comboboxPragmaJournalMode - - + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + - - + + + + https://www.sqlite.org/pragma.html#pragma_synchronous + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_synchronous"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter true - checkboxPragmaIgnoreCheckConstraints + comboboxPragmaSynchronous - - + + + + 10000 + + + + + + + PRAGMA locking_mode + - + Locking Mode + + + comboboxPragmaLockingMode - - + + + + https://www.sqlite.org/pragma.html#pragma_case_sensitive_like + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_case_sensitive_like"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter true - comboboxPragmaJournalMode + checkboxPragmaCaseSensitiveLike - - - - - Delete - - - - - Truncate - - - - - Persist - - + + - Memory + None - WAL + Full - Off + Incremental - - + + + + https://www.sqlite.org/pragma.html#pragma_auto_vacuum + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_auto_vacuum"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter true + + Qt::LinksAccessibleByMouse + - spinPragmaJournalSizeLimit + comboboxPragmaAutoVacuum - - - - -1 - - - 100000 + + + + https://www.sqlite.org/pragma.html#pragma_ignore_check_constraints - - - - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a></p></body></html> + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><img src=":/icons/whatis"/></a></p></body></html> - - true - - - comboboxPragmaLockingMode - - - - - - - - Normal - - - - - Exclusive - - - - - - - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> + + Qt::AlignCenter true - spinPragmaMaxPageCount + checkboxPragmaIgnoreCheckConstraints - - + + - 2000000000 + 2147483647 - - - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> + + + + PRAGMA synchronous - - true + + Synchronous - spinPragmaPageSize + comboboxPragmaSynchronous - - - - 512 - + + - 65536 + 2000000000 - - - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> + + + + PRAGMA checkpoint_fullfsync - - true + + Checkpoint Full FSYNC - checkboxPragmaRecursiveTriggers + checkboxPragmaCheckpointFullFsync - - + + - - + + + + https://www.sqlite.org/pragma.html#pragma_fullfsync + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_fullfsync"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter true - checkboxPragmaSecureDelete + checkboxPragmaFullFsync - - + + + + + Delete + + + + + Truncate + + + + + Persist + + + + + Memory + + + + + WAL + + + + + Off + + + + + + - - - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> + + + + PRAGMA case_sensitive_like - - true + + Case Sensitive Like - comboboxPragmaSynchronous + checkboxPragmaCaseSensitiveLike - + @@ -688,10 +576,119 @@ - + + + + + + + + + + + + 512 + + + + + 1024 + + + + + 2048 + + + + + 4096 + + + + + 8192 + + + + + 16384 + + + + + 32768 + + + + + 65536 + + + + + + + PRAGMA temp_store + + + Temp Store + + + comboboxPragmaTempStore + + + + + + + PRAGMA user_version + + + User Version + + + spinPragmaUserVersion + + + + + + + PRAGMA secure_delete + + + Secure Delete + + + checkboxPragmaSecureDelete + + + + + + + PRAGMA foreign_keys + + + Foreign Keys + + + checkboxPragmaForeignKeys + + + + + + + https://www.sqlite.org/pragma.html#pragma_temp_store + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_temp_store"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter true @@ -701,7 +698,7 @@ - + @@ -720,88 +717,394 @@ - - + + + + + 0 + 0 + + + + https://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter true - spinPragmaUserVersion + spinPragmaWalAutoCheckpoint - - - - 2147483647 + + + + PRAGMA page_size + + + Page Size + + + comboPragmaPageSize - - + + + + + + + + + + + https://www.sqlite.org/pragma.html#pragma_automatic_index + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_automatic_index"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter true - spinPragmaWalAutoCheckpoint + checkboxPragmaAutomaticIndex - - - - 10000 + + + + - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Save - - - false - - - - - - - - E&xecute SQL - - - - - - toolBar1 - - - - - - + + + + https://www.sqlite.org/pragma.html#pragma_max_page_count + + + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_max_page_count"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter + + + true + + + spinPragmaMaxPageCount + + + + + + + + Normal + + + + + Exclusive + + + + + + + + https://www.sqlite.org/pragma.html#pragma_foreign_keys + + + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_foreign_keys"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter + + + true + + + checkboxPragmaForeignKeys + + + + + + + PRAGMA fullfsync + + + Full FSYNC + + + checkboxPragmaFullFsync + + + + + + + https://www.sqlite.org/pragma.html#pragma_page_size + + + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_page_size"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter + + + true + + + comboPragmaPageSize + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + https://www.sqlite.org/pragma.html#pragma_secure_delete + + + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_secure_delete"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter + + + true + + + checkboxPragmaSecureDelete + + + + + + + PRAGMA ignore_check_constraints + + + Ignore Check Constraints + + + checkboxPragmaIgnoreCheckConstraints + + + + + + + PRAGMA journal_mode + + + Journal Mode + + + comboboxPragmaJournalMode + + + + + + + https://www.sqlite.org/pragma.html#pragma_locking_mode + + + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_locking_mode"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter + + + true + + + comboboxPragmaLockingMode + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + https://www.sqlite.org/pragma.html#pragma_recursive_triggers + + + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_recursive_triggers"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter + + + true + + + checkboxPragmaRecursiveTriggers + + + + + + + PRAGMA automatic_index + + + Automatic Index + + + checkboxPragmaAutomaticIndex + + + + + + + PRAGMA journal_size_limit + + + Journal Size Limit + + + spinPragmaJournalSizeLimit + + + + + + + https://www.sqlite.org/pragma.html#pragma_journal_size_limit + + + <html><head/><body><p><a href="https://www.sqlite.org/pragma.html#pragma_journal_size_limit"><img src=":/icons/whatis"/></a></p></body></html> + + + Qt::AlignCenter + + + true + + + spinPragmaJournalSizeLimit + + + + + + + -1 + + + 100000 + + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Save + + + false + + + + + + + + E&xecute SQL + + + E&xecute SQL + + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + toolBar1 + + + + + + + + + + + + + + + + + Qt::CustomContextMenu + -1 - - true - true @@ -819,7 +1122,7 @@ 0 0 1037 - 29 + 22 @@ -832,6 +1135,7 @@ + @@ -839,23 +1143,35 @@ + + + + + &Recent Files + + + + + - - - + + + + + @@ -864,32 +1180,58 @@ &Edit - + + + &View + + - &Help + + + + + + + + + + + Too&ls + + + + + + + + + + + +
@@ -907,15 +1249,22 @@ false - + + - - - QDockWidget::AllDockWidgetFeatures + + + Edit Database &Cell + + 2 + + + + SQL &Log @@ -924,10 +1273,28 @@ + + 2 + + + 0 + + + 2 + + + 0 + + + + 0 + 30 + + Show S&QL submitted by @@ -938,6 +1305,12 @@ + + + 0 + 30 + + User @@ -948,6 +1321,11 @@ Application + + + Error Log + + @@ -964,8 +1342,17 @@ - - + + + + 0 + 30 + + + + This button clears the contents of the SQL logs + + &Clear @@ -974,6 +1361,9 @@ + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + 0 @@ -984,11 +1374,22 @@ 8 - + true + + + Monospace + 8 + + + + true + + + Monospace @@ -1005,9 +1406,6 @@ - - QDockWidget::AllDockWidgetFeatures - &Plot @@ -1015,261 +1413,7 @@ 2 - - - - - Qt::Vertical - - - - - 0 - 2 - - - - 4 - - - 100 - - - - Columns - - - - - X - - - - - Y - - - - - _ - - - - - - - 0 - 8 - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Line type: - - - - - - - 1 - - - - None - - - - - Line - - - - - StepLeft - - - - - StepRight - - - - - StepCenter - - - - - Impulse - - - - - - - - Point shape: - - - - - - - 0 - - - - None - - - - - Cross - - - - - Plus - - - - - Circle - - - - - Disc - - - - - Square - - - - - Diamond - - - - - Star - - - - - Triangle - - - - - TriangleInverted - - - - - CrossSquare - - - - - PlusSquare - - - - - CrossCircle - - - - - PlusCircle - - - - - Peace - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> - - - Save current plot... - - - - - - - :/icons/save_table:/icons/save_table - - - false - - - false - - - false - - - false - - - - - - - Load all data. This has only an effect if not all data has been fetched from the table yet due to the partial fetch mechanism. - - - - :/icons/keyword:/icons/keyword - - - - - - - + @@ -1281,11 +1425,50 @@ + + 2 + + + 0 + + + 2 + + + 0 + + + Qt::CustomContextMenu + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + + + QFrame::NoFrame + + + QFrame::Plain + + + true + + + QAbstractItemView::DragDrop + true + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::SelectItems + QAbstractItemView::ScrollPerPixel @@ -1297,14 +1480,43 @@ - + - Edit &cell + Project Toolbar - - 8 + + Qt::ToolButtonTextBesideIcon + + + TopToolBarArea - + + false + + + + + + + true + + + Extra DB toolbar + + + Close the current database file + + + Qt::ToolButtonTextBesideIcon + + + TopToolBarArea + + + false + + + @@ -1314,6 +1526,9 @@ &New Database... + + &New Database + Create a new database file @@ -1326,6 +1541,9 @@ Ctrl+N + + QAction::NoRole + @@ -1347,16 +1565,35 @@ Ctrl+O + + QAction::NoRole + false + + + :/icons/close:/icons/close + &Close Database + + Close the current database file + + + Close the current database file + + + This button closes the connection to the currently open database file + - Ctrl+W + Ctrl+F4 + + + QAction::NoRole @@ -1373,9 +1610,39 @@ Revert database to last saved state + + Revert database to last saved state + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + + QAction::NoRole + + + + + false + + + + :/icons/undo.svg:/icons/undo.svg + + + &Undo + + + Undo last change to the database + + + Undo last change to the database + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + + + QAction::NoRole + @@ -1391,19 +1658,25 @@ Write changes to the database file + + Write changes to the database file + This option is used to save changes to the database file. Ctrl+S + + QAction::NoRole + false - Compact &Database + Compact &Database... Compact the database file, removing space wasted by deleted records @@ -1414,6 +1687,9 @@ Compact the database file, removing space wasted by deleted records. + + QAction::NoRole + @@ -1436,6 +1712,9 @@ This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + + QAction::NoRole + @@ -1447,6 +1726,9 @@ Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + + QAction::NoRole + @@ -1458,6 +1740,9 @@ This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + + QAction::NoRole + @@ -1469,6 +1754,9 @@ Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + + QAction::NoRole + @@ -1484,6 +1772,9 @@ Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + + QAction::NoRole + @@ -1502,8 +1793,11 @@ Open the Delete Table wizard, where you can select a database table to be dropped. + + QAction::NoRole + - + false @@ -1515,7 +1809,10 @@ &Modify Table... - Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields form a table, as well as modify field names and types. + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + + + QAction::NoRole @@ -1532,6 +1829,9 @@ Open the Create Index wizard, where it is possible to define a new index on an existing database table. + + QAction::NoRole + @@ -1555,12 +1855,19 @@ true + + + :/icons/toolbar:/icons/toolbar + &DB Toolbar Shows or hides the Database toolbar. + + QAction::NoRole + @@ -1573,10 +1880,13 @@ Shift+F1 + + QAction::NoRole + - &About... + &About QAction::AboutRole @@ -1590,10 +1900,13 @@ - :/icons/open_tab:/icons/open_tab + :/icons/new_tab:/icons/new_tab - Open &tab + New &tab + + + This button opens a new tab for the SQL editor Ctrl+T @@ -1608,10 +1921,13 @@ &Execute SQL - Execute SQL [F5, Ctrl+Return] + Execute all/selected SQL + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. - F5 + Ctrl+Return @@ -1620,7 +1936,13 @@ :/icons/document_open:/icons/document_open - Open SQL file + Open SQL file(s) + + + This button opens files containing SQL statements and loads them in new editor tabs + + + Ctrl+Shift+T @@ -1641,7 +1963,10 @@ :/icons/load_extension:/icons/load_extension - &Load extension + &Load Extension... + + + QAction::NoRole @@ -1652,11 +1977,17 @@ Execute current line + + Execute line + - Execute current line [Ctrl+E] + Execute current line + + + This button executes the SQL statement present in the current editor line - Ctrl+E + Shift+F5 @@ -1676,7 +2007,13 @@ :/icons/browser_open:/icons/browser_open - &Wiki... + &Wiki + + + F1 + + + QAction::NoRole @@ -1685,32 +2022,71 @@ :/icons/browser_open:/icons/browser_open - Bug &report... + Bug &Report... + + + QAction::NoRole - + :/icons/browser_open:/icons/browser_open - Web&site... + Feature Re&quest... + + + QAction::NoRole - + - :/icons/project_save:/icons/project_save + :/icons/browser_open:/icons/browser_open - Sa&ve Project + Web&site - - Save the current session to a file + + QAction::NoRole + + + + + + :/icons/browser_open:/icons/browser_open + + + &Donate on Patreon... + + + QAction::NoRole + + + + + + :/icons/project_save:/icons/project_save + + + Sa&ve Project + + + &Save Project + + + Save the current session to a file Save the current session to a file + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + + + QAction::NoRole + @@ -1718,6 +2094,9 @@ :/icons/project_open:/icons/project_open + Open &Project... + + Open &Project @@ -1726,13 +2105,35 @@ Load a working session from a file + + This button lets you open a DB Browser for SQLite project file + + + QAction::NoRole + false + + + :/icons/db_attach:/icons/db_attach + - &Attach Database + &Attach Database... + + + Add another database file to the current database connection + + + Add another database file to the current database connection + + + This button lets you add another database file to the current database connection + + + QAction::NoRole @@ -1741,7 +2142,10 @@ :/icons/encryption:/icons/encryption - &Set Encryption + &Set Encryption... + + + QAction::NoRole @@ -1767,6 +2171,9 @@ Save SQL file + + This button saves the content of the current SQL editor tab to a file + @@ -1789,115 +2196,1136 @@ Copy the CREATE statement of the item to the clipboard - + + + + :/icons/browser_open:/icons/browser_open + + + SQLCipher &FAQ + + + Opens the SQLCipher FAQ in a browser window + + + + + Table(&s) to JSON... + + + Export one or more table(s) to a JSON file + + + QAction::NoRole + + + + + + :/icons/db_open:/icons/db_open + + + Open Data&base Read Only... + + + Open an existing database file in read only mode + + + Open an existing database file + + + This option is used to open an existing database file. + + + Ctrl+Shift+O + + + QAction::NoRole + + + + + + :/icons/save_table:/icons/save_table + - Edit display format + Save results - Edit the display format of the data in this column + Save the results view + + + This button lets you save the results of the last executed query - + true + + + :/icons/find:/icons/find + - Show rowid column + Find text in SQL editor + + + Find - Toggle the visibility of the rowid column + Find text in SQL editor + + + This button opens the search bar of the editor + + + Ctrl+F + + + Qt::WidgetShortcut - + + + false + + + + :/icons/text_replace:/icons/text_replace + - Set encoding + Find or replace text in SQL editor + + + Find or replace - Change the encoding of the text in the table cells + Find or replace text in SQL editor + + + This button opens the find/replace dialog for the current editor tab + + + Ctrl+H + + + Qt::WidgetShortcut + + + + + Export to &CSV + + + + + Export to &JSON - + - Set encoding for all tables + Save as &view - Change the default encoding assumed for all tables in the database + Save as view - - - - ExtendedTableWidget - QTableWidget -
ExtendedTableWidget.h
- - foreignKeyClicked(QString,QString,QByteArray) - -
- - SqlTextEdit - QTextEdit -
sqltextedit.h
-
- - QCustomPlot - QWidget -
qcustomplot.h
- 1 -
-
- - dbTreeWidget - comboBrowseTable - buttonRefresh - buttonClearFilters - buttonNewRecord - buttonDeleteRecord - dataTable - buttonPrevious - buttonNext - buttonGoto - editGoto - scrollareaPragmas - comboboxPragmaAutoVacuum - checkboxPragmaAutomaticIndex - checkboxPragmaCheckpointFullFsync - checkboxPragmaForeignKeys - checkboxPragmaFullFsync - checkboxPragmaIgnoreCheckConstraints - comboboxPragmaJournalMode - spinPragmaJournalSizeLimit - comboboxPragmaLockingMode - spinPragmaMaxPageCount - spinPragmaPageSize - checkboxPragmaRecursiveTriggers - checkboxPragmaSecureDelete - comboboxPragmaSynchronous - comboboxPragmaTempStore - spinPragmaUserVersion - spinPragmaWalAutoCheckpoint - comboLogSubmittedBy - buttonLogClear - mainTab - buttonBegin - buttonEnd - tabSqlAreas - treePlotColumns - comboLineType - comboPointShape - butSavePlot - buttonLoadAllData - treeSchemaDock - - - - - + + + true + + + false + + + + :/icons/toolbar:/icons/toolbar + + + Project Toolbar + + + Shows or hides the Project toolbar. + + + QAction::NoRole + + + + + true + + + + :/icons/toolbar:/icons/toolbar + + + Extra DB Toolbar + + + + + + :/icons/db_open:/icons/db_open + + + &Open Database... + + + &Open Database + + + Open an existing database file + + + Open an existing database file + + + This option is used to open an existing database file. + + + QAction::TextHeuristicRole + + + + + New In-&Memory Database + + + + + true + + + SELECT Statement + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + + + + + true + + + INSERT Statement + + + When dragging fields from the same table or a single table, drop an INSERT statement into the editor + + + When dragging fields from the same table or a single table, drop an INSERT statement into the editor + + + + + true + + + Just Names + + + When dragging fields or tables, drop just the names into the editor + + + When dragging fields or tables, drop just the names into the editor + + + + + true + + + Qualified Names + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + + + + + true + + + Enquoted Names + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + + + + + Copy + + + + :/icons/copy:/icons/copy + + + Ctrl+C + + + Copies to the clipboard the selection according to the chosen Drag & Drop/Clipboard options. + + + Copies to the clipboard the selection according to the chosen Drag & Drop/Clipboard options. + + + + + &Integrity Check + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + + + + + &Foreign-Key Check + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + + + + + &Quick Integrity Check + + + Run a quick integrity check over the open DB + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + + + + + &Optimize + + + Attempt to optimize the database + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + + + + + + :/icons/print:/icons/print + + + Print + + + Print text from current SQL editor tab + + + + + + Open a dialog for printing the text in the current SQL editor tab + + + Ctrl+P + + + Qt::WidgetShortcut + + + + + false + + + + :/icons/print:/icons/print + + + Print + + + Print the structure of the opened database + + + + + + Open a dialog for printing the structure of the opened database + + + Ctrl+P + + + Qt::WidgetShortcut + + + + + + :/icons/comment_block:/icons/comment_block + + + Un/comment block of SQL code + + + Un/comment block + + + Comment or uncomment current line or selected block of code + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + + + Ctrl+/ + + + Qt::WidgetShortcut + + + + + + :/icons/cancel:/icons/cancel + + + Stop SQL execution + + + Stop execution + + + Stop the currently running SQL script + + + + + + :/icons/project_save_as:/icons/project_save_as + + + &Save Project As... + + + Save the project in a file selected in a dialog + + + Save the project in a file selected in a dialog + + + Save the project in a file selected in a dialog + + + + + + :/icons/save_all:/icons/save_all + + + Save A&ll + + + Save DB file, project file and opened SQL files + + + Save DB file, project file and opened SQL files + + + Save DB file, project file and opened SQL files + + + Ctrl+Shift+S + + + + + + :/icons/table:/icons/table + + + Browse Table + + + + + Close Pro&ject + + + Close project and database files and return to the initial state + + + Close project and database files and return to the initial state + + + Ctrl+Shift+W + + + + + + :/icons/db_detach:/icons/db_detach + + + Detach Database + + + Detach database file attached to the current database connection + + + + + + :/icons/db_detach:/icons/db_detach + + + Detach Database + + + Detach database file attached to the current database connection + + + + + Table from CSV data in Clipboard... + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + + + + + Show &Row Counts + + + This shows the number of rows for each table and view in the database. + + + + + false + + + + :/icons/db_save:/icons/db_save + + + Save Database &As... + + + Save the current database as a different file + + + + + + :/icons/refresh:/icons/refresh + + + Refresh + + + Reload the database structure + + + + + Check for Updates... + + +
+ + + SqlTextEdit + QWidget +
sqltextedit.h
+ 1 +
+ + ExtendedScintilla + QTextEdit +
ExtendedScintilla.h
+ 1 +
+
+ + mainTab + dbTreeWidget + comboLogSubmittedBy + buttonLogClear + treeSchemaDock + comboboxPragmaAutoVacuum + checkboxPragmaAutomaticIndex + checkboxPragmaCaseSensitiveLike + checkboxPragmaCheckpointFullFsync + checkboxPragmaForeignKeys + checkboxPragmaFullFsync + checkboxPragmaIgnoreCheckConstraints + comboboxPragmaJournalMode + tabSqlAreas + + + + + + + fileExitAction + triggered() + MainWindow + close() + + + -1 + -1 + + + 399 + 299 + + + + + fileOpenAction + triggered() + MainWindow + fileOpen() + + + -1 + -1 + + + 399 + 299 + + + + + fileNewAction + triggered() + MainWindow + fileNew() + + + -1 + -1 + + + 399 + 299 + + + + + fileCloseAction + triggered() + MainWindow + fileClose() + + + -1 + -1 + + + 399 + 299 + + + + + fileSaveAsAction + triggered() + MainWindow + fileSaveAs() + + + -1 + -1 + + + 399 + 299 + + + + + fileCompactAction + triggered() + MainWindow + compact() + + + -1 + -1 + + + 399 + 299 + + + + + helpWhatsThisAction + triggered() + MainWindow + helpWhatsThis() + + + -1 + -1 + + + 399 + 299 + + + + + helpAboutAction + triggered() + MainWindow + helpAbout() + + + -1 + -1 + + + 399 + 299 + + + + + mainTab + currentChanged(int) + MainWindow + mainTabSelected(int) + + + 399 + 315 + + + 399 + 299 + + + + + fileImportCSVAction + triggered() + MainWindow + importTableFromCSV() + + + -1 + -1 + + + 399 + 299 + + + + + fileExportCSVAction + triggered() + MainWindow + exportTableToCSV() + + + -1 + -1 + + + 399 + 299 + + + + + fileRevertAction + triggered() + MainWindow + fileRevert() + + + -1 + -1 + + + 399 + 299 + + + + + undoAction + triggered() + MainWindow + undo() + + + -1 + -1 + + + 399 + 299 + + + + + fileSaveAction + triggered() + MainWindow + fileSave() + + + -1 + -1 + + + 399 + 299 + + + + + editCreateIndexAction + triggered() + MainWindow + createIndex() + + + -1 + -1 + + + 399 + 299 + + + + + editDeleteObjectAction + triggered() + MainWindow + deleteObject() + + + -1 + -1 + + + 399 + 299 + + + + + editModifyObjectAction + triggered() + MainWindow + editObject() + + + -1 + -1 + + + 399 + 299 + + + + + fileExportSQLAction + triggered() + MainWindow + exportDatabaseToSQL() + + + -1 + -1 + + + 399 + 299 + + + + + fileImportSQLAction + triggered() + MainWindow + importDatabaseFromSQL() + + + -1 + -1 + + + 399 + 299 + + + + + viewPreferencesAction + triggered() + MainWindow + openPreferences() + + + -1 + -1 + + + 399 + 299 + + + + + dbTreeWidget + customContextMenuRequested(QPoint) + MainWindow + createTreeContextMenu(QPoint) + + + 111 + 261 + + + 399 + 299 + + + + + treeSchemaDock + customContextMenuRequested(QPoint) + MainWindow + createSchemaDockContextMenu(QPoint) + + + 111 + 261 + + + 399 + 299 + + + + + viewDBToolbarAction + toggled(bool) + toolbarDB + setVisible(bool) + + + -1 + -1 + + + 399 + 34 + + + + + actionSqlFind + toggled(bool) + MainWindow + setFindFrameVisibility(bool) + + + -1 + -1 + + + 399 + 34 + + + + + actionSqlFindReplace + triggered() + MainWindow + openFindReplaceDialog() + + + -1 + -1 + + + 399 + 34 + + + + + editCreateTableAction + triggered() + MainWindow + createTable() + + + -1 + -1 + + + 399 + 299 + + + + + buttonBoxPragmas + rejected() + MainWindow + loadPragmas() + + + 111 + 540 + + + -1 + 470 + + + + + buttonBoxPragmas + accepted() + MainWindow + savePragmas() + + + 111 + 540 + + + 802 + 522 + + + + + buttonLogClear + clicked() + editLogApplication + clear() + + + 989 + 126 + + + 632 + 173 + + + + + buttonLogClear + clicked() + editLogUser + clear() + + + 989 + 126 + + + 1028 + 230 + + + + + buttonLogClear + clicked() + editLogErrorLog + clear() + + + 989 + 126 + + + 632 + 173 + + + + + comboLogSubmittedBy + currentIndexChanged(int) + stackLog + setCurrentIndex(int) + + + 772 + 135 + + + 1028 + 230 + + + - fileExitAction + tabSqlAreas + tabCloseRequested(int) + MainWindow + closeSqlTab(int) + + + 91 + 259 + + + -1 + 51 + + + + + tabSqlAreas + currentChanged(int) + MainWindow + changeSqlTab(int) + + + 91 + 259 + + + -1 + 51 + + + + + actionExecuteSql triggered() MainWindow - close() + executeQuery() -1 @@ -1910,10 +3338,10 @@ - fileOpenAction + actionSqlOpenTab triggered() MainWindow - fileOpen() + openSqlTab() -1 @@ -1926,10 +3354,10 @@ - fileNewAction + actionSqlOpenFile triggered() MainWindow - fileNew() + openSqlFile() -1 @@ -1942,10 +3370,10 @@ - fileCloseAction + actionSqlSaveFile triggered() MainWindow - fileClose() + saveSqlFile() -1 @@ -1958,14 +3386,14 @@ - comboBrowseTable - activated(QString) + actionLoadExtension + triggered() MainWindow - populateTable(QString) + loadExtension() - 118 - 141 + -1 + -1 399 @@ -1974,14 +3402,14 @@ - buttonNewRecord - clicked() + actionSqlExecuteLine + triggered() MainWindow - addRecord() + executeQuery() - 402 - 143 + -1 + -1 399 @@ -1990,14 +3418,14 @@ - buttonDeleteRecord - clicked() + actionExportCsvPopup + triggered() MainWindow - deleteRecord() + exportTableToCSV() - 506 - 143 + -1 + -1 399 @@ -2006,14 +3434,14 @@ - buttonPrevious - clicked() + actionOpenProject + triggered() MainWindow - navigatePrevious() + loadProject() - 86 - 539 + -1 + -1 399 @@ -2022,14 +3450,14 @@ - buttonNext - clicked() + actionSaveProject + triggered() MainWindow - navigateNext() + saveProject() - 183 - 539 + -1 + -1 399 @@ -2038,778 +3466,874 @@ - buttonGoto - clicked() + fileAttachAction + triggered() MainWindow - navigateGoto() + fileAttach() - 365 - 539 + -1 + -1 - 399 - 299 + 499 + 314 - editGoto - returnPressed() + fileDetachAction + triggered() MainWindow - navigateGoto() + fileDetachDbTree() - 506 - 538 + -1 + -1 - 399 - 299 + 499 + 314 - buttonRefresh - clicked() + actionEncryption + triggered() MainWindow - browseRefresh() + editEncryption() - 245 - 139 + -1 + -1 - 399 - 299 + 499 + 314 - fileCompactAction + actionSqlSaveFilePopup triggered() MainWindow - compact() + saveSqlFile() -1 -1 - 399 - 299 + 499 + 314 - helpWhatsThisAction + actionSqlSaveFileAs triggered() MainWindow - helpWhatsThis() + saveSqlFileAs() -1 -1 - 399 - 299 + 499 + 314 - helpAboutAction + actionEditBrowseTable triggered() MainWindow - helpAbout() + switchToBrowseDataTab() -1 -1 - 399 - 299 + 499 + 314 - mainTab - currentChanged(int) + actionEditCopyCreateStatement + triggered() MainWindow - mainTabSelected(int) + copyCurrentCreateStatement() - 399 - 315 + -1 + -1 - 399 - 299 + 499 + 314 - fileImportCSVAction + fileExportJsonAction triggered() MainWindow - importTableFromCSV() + exportTableToJson() -1 -1 - 399 - 299 + 518 + 314 - fileExportCSVAction + fileOpenReadOnlyAction triggered() MainWindow - exportTableToCSV() + fileOpenReadOnly() -1 -1 - 399 - 299 + 518 + 314 - fileRevertAction + actionSqlResultsExportCsv triggered() MainWindow - fileRevert() + saveSqlResultsAsCsv() -1 -1 - 399 - 299 + 518 + 314 - fileSaveAction + actionSqlResultsExportJson triggered() MainWindow - fileSave() + saveSqlResultsAsJson() -1 -1 - 399 - 299 + 518 + 314 - editCreateIndexAction + actionSqlResultsSaveAsView triggered() MainWindow - createIndex() + saveSqlResultsAsView() -1 -1 - 399 - 299 + 518 + 314 - editDeleteObjectAction + tabSqlAreas + tabBarDoubleClicked(int) + MainWindow + renameSqlTab(int) + + + 330 + 372 + + + 518 + 314 + + + + + viewProjectToolbarAction + toggled(bool) + toolbarProject + setVisible(bool) + + + -1 + -1 + + + 887 + 44 + + + + + viewExtraDBToolbarAction + toggled(bool) + toolbarExtraDB + setVisible(bool) + + + -1 + -1 + + + 737 + 44 + + + + + MainWindow + toolButtonStyleChanged(Qt::ToolButtonStyle) + toolbarDB + setToolButtonStyle(Qt::ToolButtonStyle) + + + 518 + 314 + + + 296 + 44 + + + + + MainWindow + toolButtonStyleChanged(Qt::ToolButtonStyle) + toolbarExtraDB + setToolButtonStyle(Qt::ToolButtonStyle) + + + 518 + 314 + + + 737 + 44 + + + + + MainWindow + toolButtonStyleChanged(Qt::ToolButtonStyle) + toolbarProject + setToolButtonStyle(Qt::ToolButtonStyle) + + + 518 + 314 + + + 959 + 44 + + + + + fileOpenActionPopup triggered() MainWindow - deleteObject() + fileOpen() -1 -1 - 399 - 299 + 518 + 314 - editModifyTableAction + fileNewInMemoryDatabaseAction triggered() MainWindow - editTable() + fileNewInMemoryDatabase() -1 -1 - 399 - 299 + 20 + 20 - fileExportSQLAction + actionSqlPrint triggered() MainWindow - exportDatabaseToSQL() + openSqlPrintDialog() -1 -1 - 399 - 299 + 518 + 314 - fileImportSQLAction + actionDbPrint triggered() MainWindow - importDatabaseFromSQL() + printDbStructure() -1 -1 - 399 - 299 + 518 + 314 - viewPreferencesAction + actionSqlToggleComment triggered() MainWindow - openPreferences() + toggleSqlBlockComment() -1 -1 - 399 - 299 + 518 + 314 - dbTreeWidget - customContextMenuRequested(QPoint) + labelPragmaAutomaticIndex + linkHovered(QString) MainWindow - createTreeContextMenu(QPoint) + showStatusMessage5s(QString) - 111 - 261 + 85 + 133 - 399 - 299 + 518 + 314 - viewDBToolbarAction - toggled(bool) - toolbarDB - setVisible(bool) + labelPragmaCaseSensitiveLike + linkHovered(QString) + MainWindow + showStatusMessage5s(QString) - -1 - -1 + 85 + 133 - 399 - 34 + 518 + 314 - editCreateTableAction - triggered() + labelPragmaCheckpointFullFsync + linkHovered(QString) MainWindow - createTable() + showStatusMessage5s(QString) - -1 - -1 + 85 + 133 - 399 - 299 + 518 + 314 - buttonBoxPragmas - rejected() + labelPragmaForeignKeys + linkHovered(QString) MainWindow - loadPragmas() + showStatusMessage5s(QString) - 111 - 540 + 85 + 133 - -1 - 470 + 518 + 314 - buttonBoxPragmas - accepted() + labelPragmaFullFsync + linkHovered(QString) MainWindow - savePragmas() + showStatusMessage5s(QString) - 111 - 540 + 85 + 133 - 802 - 522 + 518 + 314 - buttonLogClear - clicked() - editLogApplication - clear() + labelPragmaIgnoreCheckConstraints + linkHovered(QString) + MainWindow + showStatusMessage5s(QString) - 989 - 126 + 85 + 133 - 632 - 173 + 518 + 314 - buttonLogClear - clicked() - editLogUser - clear() + labelPragmaJournalMode + linkHovered(QString) + MainWindow + showStatusMessage5s(QString) - 989 - 126 + 85 + 133 - 1028 - 230 + 518 + 314 - comboLogSubmittedBy - currentIndexChanged(int) - stackLog - setCurrentIndex(int) + labelPragmaLockingMode + linkHovered(QString) + MainWindow + showStatusMessage5s(QString) - 772 - 135 + 85 + 133 - 1028 - 230 + 518 + 314 - dataTable - doubleClicked(QModelIndex) + labelPragmaMaxPageCount + linkHovered(QString) MainWindow - doubleClickTable(QModelIndex) + showStatusMessage5s(QString) - 399 - 211 + 85 + 133 - 399 - 299 + 518 + 314 - tabSqlAreas - tabCloseRequested(int) + labelPragmaPageSize + linkHovered(QString) MainWindow - closeSqlTab(int) + showStatusMessage5s(QString) - 91 - 259 + 85 + 133 - -1 - 51 + 518 + 314 - actionExecuteSql - triggered() + labelPragmaRecursiveTriggers + linkHovered(QString) MainWindow - executeQuery() + showStatusMessage5s(QString) - -1 - -1 + 85 + 133 - 399 - 299 + 518 + 314 - actionSqlOpenTab - triggered() + labelPragmaSecureDelete + linkHovered(QString) MainWindow - openSqlTab() + showStatusMessage5s(QString) - -1 - -1 + 85 + 133 - 399 - 299 + 518 + 314 - actionSqlOpenFile - triggered() + labelPragmaSynchronous + linkHovered(QString) MainWindow - openSqlFile() + showStatusMessage5s(QString) - -1 - -1 + 85 + 133 - 399 - 299 + 518 + 314 - actionSqlSaveFile - triggered() + labelPragmaTempStore + linkHovered(QString) MainWindow - saveSqlFile() + showStatusMessage5s(QString) - -1 - -1 + 85 + 133 - 399 - 299 + 518 + 314 - actionLoadExtension - triggered() + labelPragmaUserVersion + linkHovered(QString) MainWindow - loadExtension() + showStatusMessage5s(QString) - -1 - -1 + 85 + 133 - 399 - 299 + 518 + 314 - actionSqlExecuteLine - triggered() + labelPragmaWalAutoCheckpoint + linkHovered(QString) MainWindow - executeQuery() + showStatusMessage5s(QString) - -1 - -1 + 85 + 133 - 399 - 299 + 518 + 314 - actionExportCsvPopup - triggered() + labelPragmaAutoVacuum + linkHovered(QString) MainWindow - exportTableToCSV() + showStatusMessage5s(QString) - -1 - -1 + 85 + 133 - 399 - 299 + 518 + 314 - actionOpenProject - triggered() + labelPragmaAutoVacuum + linkHovered(QString) MainWindow - loadProject() + showStatusMessage5s(QString) - -1 - -1 + 85 + 133 - 399 - 299 + 518 + 314 - actionSaveProject - triggered() + labelJournalSizeLimit + linkHovered(QString) MainWindow - saveProject() + showStatusMessage5s(QString) - -1 - -1 + 99 + 345 - 399 - 299 + 518 + 314 - fileAttachAction + actionSaveProjectAs triggered() MainWindow - fileAttach() + saveProjectAs() -1 -1 - 499 + 518 314 - actionEncryption + actionSaveAll triggered() MainWindow - editEncryption() + saveAll() -1 -1 - 499 + 518 314 - actionSqlSaveFilePopup - triggered() + tabSqlAreas + customContextMenuRequested(QPoint) MainWindow - saveSqlFile() + showContextMenuSqlTabBar(QPoint) -1 -1 - 499 - 314 + 20 + 20 - actionSqlSaveFileAs + actionCloseProject triggered() MainWindow - saveSqlFileAs() + closeFiles() -1 -1 - 499 + 518 314 - buttonEnd - clicked() + actionFileImportCsvClipboard + triggered() MainWindow - navigateEnd() + importTableFromCSV() - 223 - 539 + -1 + -1 - 499 + 518 314 - buttonBegin - clicked() + actionRowCounts + triggered() MainWindow - navigateBegin() + newRowCountsTab() - 50 - 539 + -1 + -1 - 499 + 518 314 - actionEditBrowseTable + actionWiki triggered() MainWindow - switchToBrowseDataTab() + openLinkWiki() -1 -1 - 499 - 314 + -1 + -1 - actionEditCopyCreateStatement + actionBug_report triggered() MainWindow - copyCurrentCreateStatement() + openLinkBugReport() -1 -1 - 499 - 314 + -1 + -1 - dataTable - foreignKeyClicked(QString,QString,QByteArray) + actionFeature_Request + triggered() MainWindow - jumpToRow(QString,QString,QByteArray) + openLinkFeatureRequest() - 70 - 242 + -1 + -1 - 518 - 314 + -1 + -1 - actionBrowseTableEditDisplayFormat + actionSqlCipherFaq triggered() MainWindow - editDataColumnDisplayFormat() + openLinkSqlCipherFaq() -1 -1 - 518 - 314 + -1 + -1 - actionShowRowidColumn - triggered(bool) + actionWebsite + triggered() MainWindow - showRowidColumn(bool) + openLinkWebsite() -1 -1 - 518 - 314 + -1 + -1 - actionSetTableEncoding + actionDonatePatreon triggered() MainWindow - browseDataSetTableEncoding() + openLinkDonatePatreon() -1 -1 - 518 - 314 + -1 + -1 - actionSetAllTablesEncoding + actionRefreshStructure triggered() MainWindow - browseDataSetDefaultTableEncoding() + refresh() -1 @@ -2822,18 +4346,18 @@ - buttonLoadAllData - clicked() + actionCheck_for_Updates + triggered(bool) MainWindow - browseDataFetchAllData() + checkNewVersion(bool) - 1003 - 389 + -1 + -1 - 1005 - 412 + 518 + 314 @@ -2841,31 +4365,22 @@ fileOpen() fileClose() - populateTable(QString) - addRecord() - deleteRecord() - navigatePrevious() - navigateNext() - navigateBegin() - navigateEnd() - navigateGoto() browseFind(bool) - browseRefresh() + refresh() compact() helpWhatsThis() - doubleClickTable(QModelIndex) - browseTableHeaderClicked(int) mainTabSelected(int) executeQuery() importTableFromCSV() exportTableToCSV() fileRevert() + undo() fileSave() deleteIndex() createIndex() createTable() deleteObject() - editTable() + editObject() editTablePopup() addField() editField() @@ -2888,15 +4403,33 @@ loadProject() saveProject() fileAttach() + fileDetachDbTree() + fileDetachTreeSchemaDock() editEncryption() saveSqlFileAs() switchToBrowseDataTab() copyCurrentCreateStatement() - jumpToRow(QString,QString,QByteArray) - editDataColumnDisplayFormat() - showRowidColumn(bool) - browseDataSetTableEncoding() - browseDataSetDefaultTableEncoding() browseDataFetchAllData() + exportTableToJson() + fileOpenReadOnly() + saveSqlResultsAsCsv() + saveSqlResultsAsView() + changeSqlTab(int) + renameSqlTab(int) + fileNewInMemoryDatabase() + showContextMenuSqlTabBar(QPoint) + closeTableBrowserTab(int) + openTableBrowserTab() + changeTableBrowserTab(int) + renameTableBrowserTab(int) + showContextMenuTableBrowserTabBar(QPoint) + newRowCountsTab() + openLinkWiki() + openLinkBugReport() + openLinkFeatureRequest() + openLinkSqlCipherFaq() + openLinkWebsite() + openLinkDonatePatreon() + checkNewVersion(bool) diff --git a/src/Palette.cpp b/src/Palette.cpp new file mode 100644 index 000000000..61e838984 --- /dev/null +++ b/src/Palette.cpp @@ -0,0 +1,94 @@ +#include "Palette.h" + +#include + +Palette::Palette() + : m_lastColourIndex(0) +{ +} + +QColor Palette::nextSerialColor(bool dark) +{ + if (dark) { + switch(m_lastColourIndex++) + { + case 0: + return QColor(0, 69, 134); + case 1: + return QColor(255, 66, 14); + case 2: + return QColor(255, 211, 32); + case 3: + return QColor(87, 157, 28); + case 4: + return QColor(126, 0, 33); + case 5: + return QColor(131, 202, 255); + case 6: + return QColor(49, 64, 4); + case 7: + return QColor(174, 207, 0); + case 8: + return QColor(75, 31, 111); + case 9: + return QColor(255, 149, 14); + case 10: + return QColor(197, 00, 11); + case 11: + + // Since this is the last colour in our table, reset the counter back + // to the first colour + m_lastColourIndex = 0; + + return QColor(0, 132, 209); + default: + // NOTE: This shouldn't happen! + m_lastColourIndex = 0; + return QColor(0, 0, 0); + } + } else { + // TODO: review the bright colours + switch(m_lastColourIndex++) + { + case 0: + return QColor(Qt::yellow); + case 1: + return QColor(Qt::cyan); + case 2: + return QColor(Qt::green); + case 3: + return QColor(Qt::magenta); + case 4: + return QColor(Qt::lightGray); + case 5: + return QColor("beige"); + case 6: + return QColor("lightblue"); + case 7: + return QColor("turquoise"); + case 8: + return QColor("mediumspringgreen"); + case 9: + return QColor("lightskyblue"); + case 10: + return QColor("moccasin"); + case 11: + + // Since this is the last colour in our table, reset the counter back + // to the first colour + m_lastColourIndex = 0; + + return QColor("pink"); + default: + // NOTE: This shouldn't happen! + return QColor(0, 0, 0); + } + } +} + +bool Palette::appHasDarkTheme() +{ + QColor backgroundColour = QPalette().color(QPalette::Active, QPalette::Base); + QColor foregroundColour = QPalette().color(QPalette::Active, QPalette::Text); + return backgroundColour.value() < foregroundColour.value(); +} diff --git a/src/Palette.h b/src/Palette.h new file mode 100644 index 000000000..1106b30e0 --- /dev/null +++ b/src/Palette.h @@ -0,0 +1,21 @@ +#ifndef PALETTE_H +#define PALETTE_H + +#include + +// Class providing series of colours in a given dark or light side of +// the spectrum. +class Palette +{ +public: + Palette(); + + QColor nextSerialColor(bool dark = true); + + static bool appHasDarkTheme(); + +private: + int m_lastColourIndex; +}; + +#endif diff --git a/src/PlotDock.cpp b/src/PlotDock.cpp new file mode 100644 index 000000000..f1bb50737 --- /dev/null +++ b/src/PlotDock.cpp @@ -0,0 +1,1088 @@ +#define QT_NO_FLOAT16_OPERATORS // This works around https://bugreports.qt.io/browse/QTBUG-72073 which makes the build fail on MSVC 2017 and Qt 5.12 + +#include "PlotDock.h" +#include "ui_PlotDock.h" +#include "Settings.h" +#include "sqlitetablemodel.h" +#include "FileDialog.h" +#include "TableBrowser.h" // Just for BrowseDataTableSettings, not for the actual table browser class + +#include +#include +#include +#include +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) +#include +#endif + +// Enable this line to show the most basic performance stats after pressing the fetch-all-data button. Please keep in mind that while these +// numbers might help to estimate the performance of the data loading procedure, this is not a proper benchmark. +//#define LOAD_DATA_BENCHMARK + +#ifdef LOAD_DATA_BENCHMARK +#include +#endif + +#include +#include + +static int random_number(int from, int to) +{ +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) + return QRandomGenerator::global()->bounded(from, to); +#else + return qrand() % to + from; +#endif +} + +PlotDock::PlotDock(QWidget* parent) + : QDialog(parent), + ui(new Ui::PlotDock), + m_currentPlotModel(nullptr), + m_currentTableSettings(nullptr), + m_showLegend(false), + m_stackedBars(false), + m_fixedFormat(false), + m_xtype(QVariant::Invalid) +{ + ui->setupUi(this); + + // Init widgets + ui->treePlotColumns->setSelectionMode(QAbstractItemView::NoSelection); + + // Restore state + ui->splitterForPlot->restoreState(Settings::getValue("PlotDock", "splitterSize").toByteArray()); + ui->comboLineType->setCurrentIndex(Settings::getValue("PlotDock", "lineType").toInt()); + ui->comboPointShape->setCurrentIndex(Settings::getValue("PlotDock", "pointShape").toInt()); + + // Connect signals + connect(ui->plotWidget, &QCustomPlot::selectionChangedByUser, this, &PlotDock::selectionChanged); + + // connect slots that takes care that when an axis is selected, only that direction can be dragged and zoomed: + connect(ui->plotWidget, &QCustomPlot::mousePress, this, &PlotDock::mousePress); + connect(ui->plotWidget, &QCustomPlot::mouseWheel, this, &PlotDock::mouseWheel); + connect(ui->plotWidget, &QCustomPlot::mouseMove, this, &PlotDock::mouseMove); + + // Enable: click on items to select them, Ctrl+Click for multi-selection, mouse-wheel for zooming and mouse drag for + // changing the visible range. + // Select one axis for zoom and drag applying only to that orientation. + ui->plotWidget->setInteractions(QCP::iSelectPlottables | QCP::iMultiSelect | QCP::iRangeZoom | QCP::iRangeDrag | QCP::iSelectAxes); + ui->plotWidget->setSelectionRectMode(QCP::srmNone); + + QShortcut* shortcutCopy = new QShortcut(QKeySequence::Copy, ui->plotWidget, nullptr, nullptr, Qt::WidgetShortcut); + connect(shortcutCopy, &QShortcut::activated, this, &PlotDock::copy); + + QShortcut* shortcutPrint = new QShortcut(QKeySequence::Print, ui->plotWidget, nullptr, nullptr, Qt::WidgetShortcut); + connect(shortcutPrint, &QShortcut::activated, this, &PlotDock::openPrintDialog); + + ui->plotWidget->setContextMenuPolicy(Qt::CustomContextMenu); + + // Set up context menu + m_contextMenu = new QMenu(this); + + QAction* copyAction = new QAction(QIcon(":/icons/copy"), tr("Copy"), m_contextMenu); + copyAction->setShortcut(shortcutCopy->key()); + m_contextMenu->addAction(copyAction); + connect(copyAction, &QAction::triggered, this, [&]() { + copy(); + }); + + QAction* printAction = new QAction(QIcon(":/icons/print"), tr("Print..."), m_contextMenu); + printAction->setShortcut(shortcutPrint->key()); + m_contextMenu->addAction(printAction); + connect(printAction, &QAction::triggered, this, [&]() { + openPrintDialog(); + }); + + QAction* helpAction = new QAction(QIcon(":/icons/whatis"), tr("Help"), m_contextMenu); + m_contextMenu->addAction(helpAction); + connect(helpAction, &QAction::triggered, this, [&]() { + QDesktopServices::openUrl(QUrl("https://github.com/sqlitebrowser/sqlitebrowser/wiki/Plot-Dock")); + }); + + QAction* showLegendAction = new QAction(tr("Show legend"), m_contextMenu); + showLegendAction->setCheckable(true); + m_contextMenu->addAction(showLegendAction); + + connect(showLegendAction, &QAction::toggled, this, &PlotDock::toggleLegendVisible); + + QAction* stackedBarsAction = new QAction(tr("Stacked bars"), m_contextMenu); + stackedBarsAction->setCheckable(true); + m_contextMenu->addAction(stackedBarsAction); + + connect(stackedBarsAction, &QAction::toggled, this, &PlotDock::toggleStackedBars); + + QAction* fixedFormatsAction = new QAction(tr("Fixed number format"), m_contextMenu); + fixedFormatsAction->setCheckable(true); + m_contextMenu->addAction(fixedFormatsAction); + + connect(fixedFormatsAction, &QAction::toggled, this, + [=](bool fixed) { + m_fixedFormat = fixed; + adjustAxisFormat(); + ui->plotWidget->replot(); + }); + + connect(ui->plotWidget, &QTableView::customContextMenuRequested, this, + [=](const QPoint& pos) { + // Show menu + m_contextMenu->popup(ui->plotWidget->mapToGlobal(pos)); + }); + + // Initialise the y axes and plotcolumn indices for y axes + yAxes = {ui->plotWidget->yAxis, ui->plotWidget->yAxis2}; + PlotColumnY = {PlotColumnY1, PlotColumnY2}; +} + +PlotDock::~PlotDock() +{ + // Save state + Settings::setValue("PlotDock", "splitterSize", ui->splitterForPlot->saveState()); + Settings::setValue("PlotDock", "lineType", ui->comboLineType->currentIndex()); + Settings::setValue("PlotDock", "pointShape", ui->comboPointShape->currentIndex()); + + // Finally, delete all widgets + delete ui; +} + +void PlotDock::updatePlot(SqliteTableModel* model, BrowseDataTableSettings* settings, bool update, bool keepOrResetSelection) +{ + // Each column has an id that we use internally, starting from 0. However, at the beginning of the columns list we want to add + // the virtual 'Row #' column which needs a separate unique id for internal use. This id is defined here as -1. + const int RowNumId = -1; + + // add columns to x/y selection tree widget + if(update) + { + // Store pointer to the current browse table settings in the main window + m_currentTableSettings = settings; + + // disable tree plot columns item changed updates + ui->treePlotColumns->blockSignals(true); + + m_currentPlotModel = model; + + // save current selected columns, so we can restore them after the update + QString sItemX; // selected X column + std::vector> mapItemsY = {std::map(), std::map()}; + + if(keepOrResetSelection) + { + // Store the currently selected plot columns to restore them later + for(int i = 0; i < ui->treePlotColumns->topLevelItemCount(); ++i) + { + QTreeWidgetItem* item = ui->treePlotColumns->topLevelItem(i); + if(item->checkState(PlotColumnX) == Qt::Checked) + sItemX = item->text(PlotColumnField); + + for(size_t y_ind = 0; y_ind < 2; y_ind++) + if(item->checkState(PlotColumnY[y_ind]) == Qt::Checked) + mapItemsY[y_ind][item->text(PlotColumnField)] = PlotSettings( + 0, 0, + item->background(PlotColumnY[y_ind]).color(), + item->checkState(PlotColumnY[y_ind]) == Qt::Checked); + } + } else { + // Get the plot columns to select from the stored browse table information + sItemX = m_currentTableSettings->plotXAxis; + mapItemsY[0] = m_currentTableSettings->plotYAxes[0]; + mapItemsY[1] = m_currentTableSettings->plotYAxes[1]; + } + + ui->treePlotColumns->clear(); + + if(model) + { + // Add each column with a supported data type to the column selection view + for(int i=0;icolumnCount();++i) + { + QVariant::Type columntype = guessDataType(model, i); + if(columntype != QVariant::Invalid) + { + QTreeWidgetItem* columnitem = new QTreeWidgetItem(ui->treePlotColumns); + + switch (columntype) { + case QVariant::DateTime: + columnitem->setText(PlotColumnType, tr("Date/Time")); + break; + case QVariant::Date: + columnitem->setText(PlotColumnType, tr("Date")); + break; + case QVariant::Time: + columnitem->setText(PlotColumnType, tr("Time")); + break; + case QVariant::Double: + columnitem->setText(PlotColumnType, tr("Numeric")); + break; + case QVariant::String: + columnitem->setText(PlotColumnType, tr("Label")); + break; + default: + // This is not actually expected + columnitem->setText(PlotColumnType, tr("Invalid")); + } + + // Store the model column index in the PlotColumnField and the type + // in the PlotColumnType, both using the User Role. + columnitem->setData(PlotColumnField, Qt::UserRole, i); + columnitem->setData(PlotColumnType, Qt::UserRole, static_cast(columntype)); + columnitem->setText(PlotColumnField, model->headerData(i, Qt::Horizontal, Qt::EditRole).toString()); + + // restore previous check state + for(size_t y_ind = 0; y_ind < 2; y_ind++) + { + if(contains(mapItemsY[y_ind], columnitem->text(PlotColumnField))) + { + columnitem->setCheckState(PlotColumnY[y_ind], mapItemsY[y_ind][columnitem->text(PlotColumnField)].active ? Qt::Checked : Qt::Unchecked); + columnitem->setBackground(PlotColumnY[y_ind], mapItemsY[y_ind][columnitem->text(PlotColumnField)].colour); + } else { + if (columntype == QVariant::Double) + columnitem->setCheckState(PlotColumnY[y_ind], Qt::Unchecked); + } + } + + if(sItemX == columnitem->text(PlotColumnField)) + columnitem->setCheckState(PlotColumnX, Qt::Checked); + else + columnitem->setCheckState(PlotColumnX, Qt::Unchecked); + } + } + + ui->treePlotColumns->resizeColumnToContents(PlotColumnField); + + // Add a row number column at the beginning of the column list, but only when there were (other) columns added + if(ui->treePlotColumns->topLevelItemCount()) + { + QTreeWidgetItem* columnitem = new QTreeWidgetItem(ui->treePlotColumns); + + // Just set RowNumId in the user role information field here to somehow indicate what column this is + columnitem->setData(PlotColumnField, Qt::UserRole, RowNumId); + columnitem->setText(PlotColumnField, tr("Row #")); + columnitem->setData(PlotColumnType, Qt::UserRole, static_cast(QVariant::Double)); + columnitem->setText(PlotColumnType, tr("Numeric")); + + // restore previous check state + for(size_t y_ind = 0; y_ind < 2; y_ind++) + { + if(contains(mapItemsY[y_ind], columnitem->text(PlotColumnField))) + { + columnitem->setCheckState(PlotColumnY[y_ind], mapItemsY[y_ind][columnitem->text(PlotColumnField)].active ? Qt::Checked : Qt::Unchecked); + columnitem->setBackground(PlotColumnY[y_ind], mapItemsY[y_ind][columnitem->text(PlotColumnField)].colour); + } else { + columnitem->setCheckState(PlotColumnY[y_ind], Qt::Unchecked); + } + } + + if(sItemX == columnitem->text(PlotColumnField)) + columnitem->setCheckState(PlotColumnX, Qt::Checked); + else + columnitem->setCheckState(PlotColumnX, Qt::Unchecked); + + ui->treePlotColumns->takeTopLevelItem(ui->treePlotColumns->indexOfTopLevelItem(columnitem)); + ui->treePlotColumns->insertTopLevelItem(0, columnitem); + } + } + + yAxes[0]->setLabel("Y1"); + yAxes[1]->setLabel("Y2"); + ui->plotWidget->xAxis->setLabel("X"); + ui->treePlotColumns->blockSignals(false); + } + + // search for the x axis select + QTreeWidgetItem* xitem = nullptr; + for(int i = 0; i < ui->treePlotColumns->topLevelItemCount(); ++i) + { + xitem = ui->treePlotColumns->topLevelItem(i); + if(xitem->checkState(PlotColumnX) == Qt::Checked) + break; + + xitem = nullptr; + } + + std::vector yAxisLabels = {QStringList(), QStringList()}; + + // Clear graphs and axis labels + ui->plotWidget->clearPlottables(); + ui->plotWidget->xAxis->setLabel(QString()); + yAxes[0]->setLabel(QString()); + yAxes[1]->setLabel(QString()); + + if(xitem) + { + // regain the model column index and the datatype + // right now datatype is only important for X axis (Y is always numeric) + int x = xitem->data(PlotColumnField, Qt::UserRole).toInt(); + m_xtype = xitem->data(PlotColumnType, Qt::UserRole).toUInt(); + + ui->plotWidget->xAxis->setTickLabelRotation(0); + + // check if we have a x axis with datetime data + switch (m_xtype) { + case QVariant::Date: { + QSharedPointer ticker(new QCPAxisTickerDateTime); + ticker->setDateTimeFormat("yyyy-MM-dd"); + ui->plotWidget->xAxis->setTicker(ticker); + break; + } + case QVariant::DateTime: { + QSharedPointer ticker(new QCPAxisTickerDateTime); + ticker->setDateTimeFormat("yyyy-MM-dd\nhh:mm:ss"); + ui->plotWidget->xAxis->setTicker(ticker); + break; + } + case QVariant::Time: { + QSharedPointer ticker(new QCPAxisTickerDateTime); + ticker->setDateTimeFormat("hh:mm:ss"); + ticker->setDateTimeSpec(Qt::UTC); + ui->plotWidget->xAxis->setTicker(ticker); + break; + } + case QVariant::String: { + // Ticker is set when we have got the labels + ui->plotWidget->xAxis->setTickLabelRotation(60); + break; + } + default: { + QSharedPointer ticker(new QCPAxisTickerFixed); + ticker->setTickStepStrategy(QCPAxisTicker::tssReadability); + ticker->setScaleStrategy(QCPAxisTickerFixed::ssMultiples); + ui->plotWidget->xAxis->setTicker(ticker); + } + } + + // Boolean to decide whether secondary y axis should be displayed + bool displayY2Axis = false; + + // add graph for each selected y axis + for(int i = 0; i < ui->treePlotColumns->topLevelItemCount(); ++i) + { + QTreeWidgetItem* item = ui->treePlotColumns->topLevelItem(i); + std::vector yItemBool = {false, false}; + + if(item->checkState((PlotColumnY[0])) == Qt::Checked || item->checkState((PlotColumnY[1])) == Qt::Checked) + { + for(size_t y_ind = 0; y_ind < 2; y_ind++) + if(item->checkState((PlotColumnY[y_ind])) == Qt::Checked) + yItemBool[y_ind] = true; + + if(yItemBool[1]) + displayY2Axis = true; + // regain the model column index + int column = item->data(PlotColumnField, Qt::UserRole).toInt(); + + bool isSorted = true; + + // prepare the data vectors for qcustomplot + // possible improvement might be a QVector subclass that directly + // access the model data, to save memory, we are copying here + + auto nrows = model->rowCount(); + + std::vector> ydata{QVector(nrows), QVector(nrows)}; + + QVector xdata(nrows), tdata(nrows); + QVector labels; + + for(int j = 0; j < nrows; ++j) + { + tdata[j] = j; + + if(x != RowNumId && model->data(model->index(j, x), Qt::EditRole).isNull()) { + // NULL values produce gaps in the linear graphs. We use NaN values in + // that case as required by QCustomPlot. + // Bar plots will display the configured string for NULL values. + if(m_xtype == QVariant::String) { + xdata[j] = j+1; + labels << model->data(model->index(j, x), Qt::DisplayRole).toString(); + } else + xdata[j] = qQNaN(); + } else { + + // convert x type axis if it's datetime + switch (m_xtype) { + case QVariant::DateTime: + case QVariant::Date: { + QString s = model->data(model->index(j, x)).toString(); + QDateTime d = QDateTime::fromString(s, Qt::ISODate); + xdata[j] = static_cast(d.toMSecsSinceEpoch()) / 1000.0; + break; + } + case QVariant::Time: { + QString s = model->data(model->index(j, x)).toString(); + QTime t = QTime::fromString(s); + xdata[j] = t.msecsSinceStartOfDay() / 1000.0; + break; + } + case QVariant::String: { + xdata[j] = j+1; + labels << model->data(model->index(j, x)).toString(); + break; + } + default: { + // Get the x value for this point. If the selected column is -1, i.e. the row number, just use the current row number from the loop + // instead of retrieving some value from the model. + if(x == RowNumId) + xdata[j] = j+1; + else + xdata[j] = model->data(model->index(j, x)).toDouble(); + } + } + } + if (j != 0) + isSorted &= (xdata[j-1] <= xdata[j]); + + // Get the y value for this point. If the selected column is -1, i.e. the row number, just use the current row number from the loop + // instead of retrieving some value from the model. + QVariant pointdata; + if(column == RowNumId) + pointdata = j+1; + else + pointdata = model->data(model->index(j, column), Qt::EditRole); + + for(size_t y_ind = 0; y_ind < 2; y_ind++) + { + if(pointdata.isNull()){ + if(yItemBool[y_ind]) + ydata[y_ind][j] = qQNaN(); + } + else{ + if(yItemBool[y_ind]) + ydata[y_ind][j] = pointdata.toDouble(); + } + } + } + + // Line type and point shape are not supported by the String X type (Bars) + ui->comboLineType->setEnabled(m_xtype != QVariant::String); + ui->comboPointShape->setEnabled(m_xtype != QVariant::String); + + // WARN: ssDot is removed + int shapeIdx = ui->comboPointShape->currentIndex(); + if (shapeIdx > 0) shapeIdx += 1; + QCPScatterStyle scatterStyle = QCPScatterStyle(static_cast(shapeIdx), 5); + + QCPAbstractPlottable* plottable = nullptr; + // When the X type is String, we draw a bar chart. + // When it is already sorted by x, we draw a graph. + // When it is not sorted by x, we draw a curve, so the order selected by the user in the table or in the query is + // respected. In this case the line will have loops and only None and Line is supported as line style. + // TODO: how to make the user aware of this without disturbing. + if (m_xtype == QVariant::String) { + + for(size_t y_ind = 0; y_ind < 2; y_ind++) + { + if(yItemBool[y_ind]) + { + QCPBars* bars = new QCPBars(ui->plotWidget->xAxis, yAxes[y_ind]); + plottable = bars; + bars->setData(xdata, ydata[y_ind]); + // Set ticker once + if (ui->plotWidget->plottableCount() == 1) { + QSharedPointer ticker(new QCPAxisTickerText); + ticker->addTicks(xdata, labels); + ui->plotWidget->xAxis->setTicker(ticker); + } + QColor color = item->background(PlotColumnY[y_ind]).color(); + bars->setBrush(color); + plottable->setPen(QPen(color.darker(150))); + } + } + } else { + if (isSorted) { + for(size_t y_ind = 0; y_ind < 2; y_ind++) + { + if(yItemBool[y_ind]) + { + QCPGraph* graph = ui->plotWidget->addGraph(ui->plotWidget->xAxis, yAxes[y_ind]); + plottable = graph; + graph->setData(xdata, ydata[y_ind], /*alreadySorted*/ true); + // set some graph styles not supported by the abstract plottable + graph->setLineStyle(static_cast(ui->comboLineType->currentIndex())); + graph->setScatterStyle(scatterStyle); + plottable->setPen(QPen(item->background(PlotColumnY[y_ind]).color())); + } + } + } else { + for(size_t y_ind = 0; y_ind < 2; y_ind++) + { + if(yItemBool[y_ind]) + { + QCPCurve* curve = new QCPCurve(ui->plotWidget->xAxis, yAxes[y_ind]); + plottable = curve; + curve->setData(tdata, xdata, ydata[y_ind], /*alreadySorted*/ true); + // set some curve styles not supported by the abstract plottable + if (ui->comboLineType->currentIndex() == QCPCurve::lsNone) + curve->setLineStyle(QCPCurve::lsNone); + else + curve->setLineStyle(QCPCurve::lsLine); + curve->setScatterStyle(scatterStyle); + plottable->setPen(QPen(item->background(PlotColumnY[y_ind]).color())); + } + } + } + } + + if(plottable) + { + plottable->setSelectable(QCP::stDataRange); + plottable->setName(item->text(PlotColumnField)); + } + + for(size_t y_ind = 0; y_ind < 2; y_ind++) + { + if(yItemBool[y_ind]) + { + // gather Y label column names + if(column == RowNumId) + yAxisLabels[y_ind] << tr("Row #"); + else + yAxisLabels[y_ind] << model->headerData(column, Qt::Horizontal, Qt::EditRole).toString(); + } + } + } + } + + ui->plotWidget->rescaleAxes(true); + ui->plotWidget->legend->setVisible(m_showLegend); + // Legend with slightly transparent background brush: + ui->plotWidget->legend->setBrush(QColor(255, 255, 255, 150)); + + // set axis labels + if(x == RowNumId) + ui->plotWidget->xAxis->setLabel(tr("Row #")); + else + ui->plotWidget->xAxis->setLabel(model->headerData(x, Qt::Horizontal, Qt::EditRole).toString()); + for(size_t y_ind = 0; y_ind < 2; y_ind++) + yAxes[y_ind]->setLabel(yAxisLabels[y_ind].join("|")); + + if(displayY2Axis){ + yAxes[1]->setVisible(true); + yAxes[1]->setTickLabels(true); + }else{ + yAxes[1]->setVisible(false); + yAxes[1]->setTickLabels(false); + } + } + + adjustBars(); + adjustAxisFormat(); + ui->plotWidget->replot(); + + // Warn user if not all data has been fetched and hint about the button for loading all the data + if (model && (model->rowCountAvailable() != SqliteTableModel::RowCount::Complete || !model->isCacheComplete())) { + ui->buttonLoadAllData->setEnabled(true); + ui->buttonLoadAllData->setStyleSheet("QToolButton {color: white; background-color: rgb(255, 102, 102)}"); + ui->buttonLoadAllData->setToolTip(tr("Load all data and redraw plot.\n" + "Warning: not all data has been fetched from the table yet due to the partial fetch mechanism.")); + } else { + ui->buttonLoadAllData->setEnabled(false); + ui->buttonLoadAllData->setStyleSheet(""); + ui->buttonLoadAllData->setToolTip(tr("Load all data and redraw plot")); + } +} + +void PlotDock::resetPlot() +{ + updatePlot(nullptr); +} + +void PlotDock::columnItemChanged(QTreeWidgetItem* changeitem, int column) +{ + // disable change updates, or we get unwanted redrawing and weird behavior + ui->treePlotColumns->blockSignals(true); + + // make sure only 1 X axis is selected + if(column == PlotColumnX) + { + for(int i = 0; i < ui->treePlotColumns->topLevelItemCount(); ++i) + { + QTreeWidgetItem* item = ui->treePlotColumns->topLevelItem(i); + if(item->checkState(column) == Qt::Checked && item != changeitem) + { + item->setCheckState(column, Qt::Unchecked); + } + } + + // Save settings for this table + if(m_currentTableSettings) + { + if(changeitem->checkState(column) == Qt::Checked) + m_currentTableSettings->plotXAxis = changeitem->text(PlotColumnField); + else + m_currentTableSettings->plotXAxis = QString(); + } + } else if(column == PlotColumnY[0] || column == PlotColumnY[1]) { + // Save check state of this column + for(size_t y_ind = 0; y_ind < 2; y_ind++) + { + if(column == PlotColumnY[y_ind]) + { + if(m_currentTableSettings) + { + PlotSettings& plot_settings = m_currentTableSettings->plotYAxes[y_ind][changeitem->text(PlotColumnField)]; + plot_settings.active = (changeitem->checkState(column) == Qt::Checked); + } + + if(changeitem->checkState(column) == Qt::Checked) + { + // Generate a default colour if none is set yet + QColor colour = changeitem->background(column).color(); + if(!colour.isValid() || colour == changeitem->background(PlotColumnField).color()) + colour = m_graphPalette.nextSerialColor(true); + + // Set colour to cell background + changeitem->setBackground(column, colour); + + // Save settings for this table + if(m_currentTableSettings) + { + PlotSettings& plot_settings = m_currentTableSettings->plotYAxes[y_ind][changeitem->text(PlotColumnField)]; + plot_settings.colour = colour; + plot_settings.lineStyle = ui->comboLineType->currentIndex(); + plot_settings.pointShape = (ui->comboPointShape->currentIndex() > 0 ? (ui->comboPointShape->currentIndex()+1) : ui->comboPointShape->currentIndex()); + } + } + } + } + + } + + ui->treePlotColumns->blockSignals(false); + + updatePlot(m_currentPlotModel, m_currentTableSettings, false); +} + +void PlotDock::columnItemDoubleClicked(QTreeWidgetItem* item, int column) +{ + // disable change updates, or we get unwanted redrawing and weird behavior + ui->treePlotColumns->blockSignals(true); + + unsigned int type = item->data(PlotColumnType, Qt::UserRole).toUInt(); + + for(size_t y_ind = 0; y_ind < 2; y_ind++) + { + if(column == PlotColumnY[y_ind] && type == QVariant::Double) + { + // On double click open the colordialog + QColorDialog colordialog(this); + QColor curbkcolor = item->background(column).color(); + QColor precolor = !curbkcolor.isValid() ? static_cast(random_number(5, 13)) : curbkcolor; + QColor color = colordialog.getColor(precolor, this, tr("Choose an axis color")); + if(color.isValid()) + { + item->setCheckState(column, Qt::Checked); + item->setBackground(column, color); + + // Save settings for this table + if(m_currentTableSettings) + { + PlotSettings& plot_settings = m_currentTableSettings->plotYAxes[y_ind][item->text(PlotColumnField)]; + plot_settings.active = (item->checkState(column) == Qt::Checked); + plot_settings.colour = color; + plot_settings.lineStyle = ui->comboLineType->currentIndex(); + plot_settings.pointShape = (ui->comboPointShape->currentIndex() > 0 ? (ui->comboPointShape->currentIndex()+1) : ui->comboPointShape->currentIndex()); + } + } else { + item->setCheckState(column, Qt::Unchecked); + + // Save settings for this table + if(m_currentTableSettings) + m_currentTableSettings->plotYAxes[y_ind].erase(item->text(PlotColumnField)); + } + } + } + + ui->treePlotColumns->blockSignals(false); + + updatePlot(m_currentPlotModel, m_currentTableSettings, false); +} + +void PlotDock::savePlot() +{ + QString fileName = FileDialog::getSaveFileName( + CreateDataFile, + this, + tr("Choose a filename to save under"), + tr("PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*)")); + if(!fileName.isEmpty()) + { + if(fileName.endsWith(".png", Qt::CaseInsensitive)) + { + ui->plotWidget->savePng(fileName); + } + else if(fileName.endsWith(".jpg", Qt::CaseInsensitive)) + { + ui->plotWidget->saveJpg(fileName); + } + else if(fileName.endsWith(".pdf", Qt::CaseInsensitive)) + { + ui->plotWidget->savePdf(fileName); + } + else if(fileName.endsWith(".bmp", Qt::CaseInsensitive)) + { + ui->plotWidget->saveBmp(fileName); + } + else + { + fileName += ".png"; + ui->plotWidget->savePng(fileName); + } + } +} + +void PlotDock::lineTypeChanged(int index) +{ + Q_ASSERT(index >= QCPGraph::lsNone && + index <= QCPGraph::lsImpulse); + + bool hasCurves = (ui->plotWidget->plottableCount() > ui->plotWidget->graphCount()); + QCPGraph::LineStyle lineStyle = static_cast(index); + if (lineStyle > QCPGraph::lsLine && hasCurves) { + QMessageBox::warning(this, qApp->applicationName(), + tr("There are curves in this plot and the selected line style can only be applied to graphs sorted by X. " + "Either sort the table or query by X to remove curves or select one of the styles supported by curves: " + "None or Line.")); + return; + } + for (int i = 0, ie = ui->plotWidget->graphCount(); i < ie; ++i) + { + QCPGraph * graph = ui->plotWidget->graph(i); + if (graph) + graph->setLineStyle(lineStyle); + } + // We have changed the style only for graphs, but not for curves. + // If there are any in the plot, we have to update it completely in order to apply the new style + if (hasCurves) + updatePlot(m_currentPlotModel, m_currentTableSettings, false); + else + ui->plotWidget->replot(); + + // Save settings for this table + if(m_currentTableSettings) + { + for(size_t y_ind = 0; y_ind < 2; y_ind++) + { + std::map& graphs = m_currentTableSettings->plotYAxes[y_ind]; + auto it = graphs.begin(); + while(it != graphs.end()) + { + it->second.lineStyle = lineStyle; + ++it; + } + } + } +} + +void PlotDock::pointShapeChanged(int index) +{ + // WARN: because ssDot point shape is removed + if (index > 0) index += 1; + Q_ASSERT(index >= QCPScatterStyle::ssNone && + index < QCPScatterStyle::ssPixmap); + + bool hasCurves = (ui->plotWidget->plottableCount() > ui->plotWidget->graphCount()); + QCPScatterStyle::ScatterShape shape = static_cast(index); + for (int i = 0, ie = ui->plotWidget->graphCount(); i < ie; ++i) + { + QCPGraph * graph = ui->plotWidget->graph(i); + if (graph) + graph->setScatterStyle(QCPScatterStyle(shape, 5)); + } + // We have changed the style only for graphs, but not for curves. + // If there are any in the plot, we have to update it completely in order to apply the new style + if (hasCurves) + updatePlot(m_currentPlotModel, m_currentTableSettings, false); + else + ui->plotWidget->replot(); + + // Save settings for this table + if(m_currentTableSettings) + { + for(size_t y_ind = 0; y_ind < 2; y_ind++) + { + std::map& graphs = m_currentTableSettings->plotYAxes[y_ind]; + auto it = graphs.begin(); + while(it != graphs.end()) + { + it->second.pointShape = shape; + ++it; + } + } + } +} + +QVariant::Type PlotDock::guessDataType(SqliteTableModel* model, int column) const +{ + QVariant::Type type = QVariant::Invalid; + for(int i = 0; i < std::min(10, model->rowCount()) && type != QVariant::String; ++i) + { + QVariant varData = model->data(model->index(i, column), Qt::EditRole); + if(varData.isNull() || varData.convert(QVariant::Double)) + { + type = QVariant::Double; + } else { + QString s = model->data(model->index(i, column)).toString(); + QDateTime dt = QDateTime::fromString(s, Qt::ISODate); + QTime t = QTime::fromString(s); + if (dt.isValid()) + // Since the way to discriminate dates with times and pure dates is that the time part is 0, we must take into account + // that some DateTimes could have "00:00:00" as time part and still the entire column has time information, so a single + // final Date should not set the type to Date if it has already been guessed as DateTime. + if (type != QVariant::DateTime && dt.time().msecsSinceStartOfDay() == 0) + type = QVariant::Date; + else + type = QVariant::DateTime; + else if (t.isValid()) + type = QVariant::Time; + else + type = QVariant::String; + } + } + + return type; +} + +void PlotDock::fetchAllData() +{ + if(m_currentPlotModel) + { +#ifdef LOAD_DATA_BENCHMARK + // If benchmark mode is enabled start measuring the performance now + QElapsedTimer timer; + timer.start(); +#endif + + // Make sure all data is loaded + m_currentPlotModel->completeCache(); + +#ifdef LOAD_DATA_BENCHMARK + QMessageBox::information(this, qApp->applicationName(), + tr("Loading all remaining data for this table took %1ms.") + .arg(timer.elapsed())); +#endif + + // Update plot + updatePlot(m_currentPlotModel, m_currentTableSettings); + } +} + +void PlotDock::selectionChanged() +{ + + for (const QCPAbstractPlottable* plottable : ui->plotWidget->selectedPlottables()) { + + for (const QCPDataRange& dataRange : plottable->selection().dataRanges()) { + + int index = dataRange.begin(); + if (dataRange.length() != 0) { + emit pointsSelected(index, dataRange.length()); + break; + } + + } + } + +} +void PlotDock::mousePress() +{ + // Allow user to reset the plot + ui->buttonLoadAllData->setEnabled(true); + + // if an axis (or axis labels) is selected, only allow the direction of that axis to be dragged + // if no axis (or axis labels) is selected, all three axes may be dragged + if (ui->plotWidget->xAxis->selectedParts().testFlag(QCPAxis::spAxis) || + ui->plotWidget->xAxis->selectedParts().testFlag(QCPAxis::spTickLabels) || + ui->plotWidget->xAxis->selectedParts().testFlag(QCPAxis::spAxisLabel)) + { + QList< QCPAxis *> axList = {ui->plotWidget->xAxis}; + ui->plotWidget->axisRect()->setRangeDragAxes(axList); + } + else if (yAxes[0]->selectedParts().testFlag(QCPAxis::spAxis) || + yAxes[0]->selectedParts().testFlag(QCPAxis::spTickLabels) || + yAxes[0]->selectedParts().testFlag(QCPAxis::spAxisLabel)) + { + QList< QCPAxis *> axList = {yAxes[0]}; + ui->plotWidget->axisRect()->setRangeDragAxes(axList); + } + else if (yAxes[1]->selectedParts().testFlag(QCPAxis::spAxis) || + yAxes[1]->selectedParts().testFlag(QCPAxis::spTickLabels) || + yAxes[1]->selectedParts().testFlag(QCPAxis::spAxisLabel)) + { + QList< QCPAxis *> axList = {yAxes[1]}; + ui->plotWidget->axisRect()->setRangeDragAxes(axList); + } + else{ + QList< QCPAxis *> axList = {ui->plotWidget->xAxis,yAxes[0], yAxes[1]}; + ui->plotWidget->axisRect()->setRangeDragAxes(axList); + } +} + +void PlotDock::mouseMove(QMouseEvent* event) +{ + double x = ui->plotWidget->xAxis->pixelToCoord(event->pos().x()); + double y = ui->plotWidget->yAxis->pixelToCoord(event->pos().y()); + + QString xLabel; + + switch (m_xtype) { + case QVariant::Date: + xLabel = QDateTime::fromMSecsSinceEpoch(static_cast(x*1000.0)).toString("yyyy-MM-dd, "); + break; + case QVariant::Time: + xLabel = QDateTime::fromMSecsSinceEpoch(static_cast(x*1000.0), Qt::UTC).toString("hh:mm:ss, "); + break; + case QVariant::DateTime: + xLabel = QDateTime::fromMSecsSinceEpoch(static_cast(x*1000.0)).toString("yyyy-MM-dd hh:mm:ss, "); + break; + case QVariant::String: + // In this case, only the y value is displayed + xLabel = QString("y="); + break; + default: + xLabel = QLocale().toString(x) + ", "; + } + + ui->plotWidget->setToolTip(xLabel + QLocale().toString(y)); +} + +void PlotDock::mouseWheel() +{ + // Allow user to reset the plot + ui->buttonLoadAllData->setEnabled(true); + + // if an axis (or axis labels) is selected, only allow the direction of that axis to be zoomed + // if no axis (or axis labels) is selected, all three axes may be zoomed + if (ui->plotWidget->xAxis->selectedParts().testFlag(QCPAxis::spAxis) || + ui->plotWidget->xAxis->selectedParts().testFlag(QCPAxis::spTickLabels) || + ui->plotWidget->xAxis->selectedParts().testFlag(QCPAxis::spAxisLabel)) + { + QList< QCPAxis *> axList = {ui->plotWidget->xAxis}; + ui->plotWidget->axisRect()->setRangeZoomAxes(axList); + } + else if (yAxes[0]->selectedParts().testFlag(QCPAxis::spAxis) || + yAxes[0]->selectedParts().testFlag(QCPAxis::spTickLabels) || + yAxes[0]->selectedParts().testFlag(QCPAxis::spAxisLabel)) + { + QList< QCPAxis *> axList = {yAxes[0]}; + ui->plotWidget->axisRect()->setRangeZoomAxes(axList); + } + else if (yAxes[1]->selectedParts().testFlag(QCPAxis::spAxis) || + yAxes[1]->selectedParts().testFlag(QCPAxis::spTickLabels) || + yAxes[1]->selectedParts().testFlag(QCPAxis::spAxisLabel)) + { + QList< QCPAxis *> axList = {yAxes[1]}; + ui->plotWidget->axisRect()->setRangeZoomAxes(axList); + } + + else{ + QList< QCPAxis *> axList = {ui->plotWidget->xAxis,yAxes[0], yAxes[1]}; + ui->plotWidget->axisRect()->setRangeZoomAxes(axList); + } +} + +void PlotDock::copy() +{ + QApplication::clipboard()->setPixmap(ui->plotWidget->toPixmap()); +} + +void PlotDock::toggleLegendVisible(bool visible) +{ + m_showLegend = visible; + ui->plotWidget->legend->setVisible(m_showLegend); + ui->plotWidget->replot(); +} + +// Stack or group bars and set the appropriate bar width (since it is not automatically done by QCustomPlot). +void PlotDock::adjustBars() +{ + const double padding = 0.15; + int plottableCount = ui->plotWidget->plottableCount(); + + if (plottableCount == 0) + return; + + const double groupedWidth = 1.0 / plottableCount; + QCPBars* previousBar = nullptr; + QCPBarsGroup* barsGroup = m_stackedBars ? nullptr : new QCPBarsGroup(ui->plotWidget); + for (int i = 0, ie = plottableCount; i < ie; ++i) + { + QCPBars* bar = qobject_cast(ui->plotWidget->plottable(i)); + if (bar) { + if (m_stackedBars) { + // Ungroup if grouped + bar->setBarsGroup(nullptr); + if (previousBar) + bar->moveAbove(previousBar); + // Set width to ocuppy the full coordinate space, less padding + bar->setWidth(1.0 - padding); + } else { + // Unstack if stacked + bar->moveAbove(nullptr); + bar->setBarsGroup(barsGroup); + // Set width to a plot coordinate width, less padding + bar->setWidth(groupedWidth - padding); + } + previousBar = bar; + } + } +} + +namespace { + void adjustOneAxisFormat (QCPAxis* axis, bool fixedFormat) { + const QString format = fixedFormat? "f" : "gb"; + axis->setNumberFormat(format); + int precision; + // Different values for big numbers and small numbers. + if (axis->range().center() > 999 && axis->range().size() > 10) + precision = fixedFormat? 0 : 2; + else + precision = fixedFormat? 2 : 6; + axis->setNumberPrecision(precision); + } +} + +void PlotDock::adjustAxisFormat() +{ + adjustOneAxisFormat(ui->plotWidget->xAxis, m_fixedFormat); + adjustOneAxisFormat(ui->plotWidget->yAxis, m_fixedFormat); + adjustOneAxisFormat(ui->plotWidget->yAxis2, m_fixedFormat); +} + +void PlotDock::toggleStackedBars(bool stacked) +{ + m_stackedBars = stacked; + adjustBars(); + ui->plotWidget->replot(); +} + +void PlotDock::reject() +{ + // We override this, to ensure the Escape key doesn't make this dialog + // dock go away + return; +} + +void PlotDock::openPrintDialog() +{ + QPrinter printer; + QPrintPreviewDialog previewDialog(&printer, this); + connect(&previewDialog, &QPrintPreviewDialog::paintRequested, this, &PlotDock::renderPlot); + previewDialog.exec(); +} + +void PlotDock::renderPlot(QPrinter* printer) +{ + QCPPainter painter(printer); + QRectF pageRect = printer->pageRect(QPrinter::DevicePixel); + + int plotWidth = ui->plotWidget->viewport().width(); + int plotHeight = ui->plotWidget->viewport().height(); + double scale = pageRect.width()/static_cast(plotWidth); + + painter.setMode(QCPPainter::pmVectorized); + painter.setMode(QCPPainter::pmNoCaching); + + painter.scale(scale, scale); + ui->plotWidget->toPainter(&painter, plotWidth, plotHeight); +} diff --git a/src/PlotDock.h b/src/PlotDock.h new file mode 100644 index 000000000..6440b3e3c --- /dev/null +++ b/src/PlotDock.h @@ -0,0 +1,133 @@ +#ifndef PLOTDOCK_H +#define PLOTDOCK_H + +#include "Palette.h" + +#include +#include + +#include + +class QMenu; +class QPrinter; +class QTreeWidgetItem; +class QCPAxis; +class QMouseEvent; + +class SqliteTableModel; +struct BrowseDataTableSettings; + +namespace Ui { +class PlotDock; +} + +class PlotDock : public QDialog +{ + Q_OBJECT + +public: + explicit PlotDock(QWidget* parent = nullptr); + ~PlotDock() override; + + struct PlotSettings + { + int lineStyle; + int pointShape; + QColor colour; + bool active; + + PlotSettings() : + lineStyle(0), + pointShape(0), + active(false) + {} + + PlotSettings(int _lineStyle, int _pointShape, QColor _colour, bool _active) : + lineStyle(_lineStyle), + pointShape(_pointShape), + colour(_colour), + active(_active) + {} + + friend QDataStream& operator<<(QDataStream& stream, const PlotDock::PlotSettings& object) + { + stream << object.lineStyle; + stream << object.pointShape; + stream << object.colour; + stream << object.active; + + return stream; + } + friend QDataStream& operator>>(QDataStream& stream, PlotDock::PlotSettings& object) + { + stream >> object.lineStyle; + stream >> object.pointShape; + stream >> object.colour; + + if(!stream.atEnd()) + stream >> object.active; + + return stream; + } + }; + +public slots: + void updatePlot(SqliteTableModel* model, BrowseDataTableSettings* settings = nullptr, bool update = true, bool keepOrResetSelection = true); + void fetchAllData(); + void resetPlot(); + void reject() override; + +signals: + void pointsSelected(int firstIndex, int count); + +private: + enum PlotColumns + { + PlotColumnField = 0, + PlotColumnX = 1, + PlotColumnY1 = 2, + PlotColumnY2 = 3, + PlotColumnType = 4, + }; + + Ui::PlotDock* ui; + + SqliteTableModel* m_currentPlotModel; + BrowseDataTableSettings* m_currentTableSettings; + QMenu* m_contextMenu; + bool m_showLegend; + bool m_stackedBars; + bool m_fixedFormat; + Palette m_graphPalette; + std::vector yAxes; + std::vector PlotColumnY; + unsigned int m_xtype; + + /*! + * \brief guessdatatype try to parse the first 10 rows and decide the datatype + * \param model model to check the data + * \param column index of the column to check + * \return the guessed datatype + */ + QVariant::Type guessDataType(SqliteTableModel* model, int column) const; + void adjustBars(); + void adjustAxisFormat(); + +private slots: + void columnItemChanged(QTreeWidgetItem* item, int column); + void columnItemDoubleClicked(QTreeWidgetItem* item, int column); + void savePlot(); + void lineTypeChanged(int index); + void pointShapeChanged(int index); + void selectionChanged(); + void mousePress(); + void mouseWheel(); + void mouseMove(QMouseEvent* event); + void copy(); + void toggleLegendVisible(bool visible); + void toggleStackedBars(bool stacked); + void openPrintDialog(); + void renderPlot(QPrinter* printer); +}; + +#endif diff --git a/src/PlotDock.ui b/src/PlotDock.ui new file mode 100644 index 000000000..993103258 --- /dev/null +++ b/src/PlotDock.ui @@ -0,0 +1,458 @@ + + + PlotDock + + + + 0 + 0 + 515 + 553 + + + + Plot + + + + 2 + + + 0 + + + 2 + + + 0 + + + + + Qt::Vertical + + + + + 0 + 2 + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + + + true + + + 5 + + + 100 + + + false + + + + Columns + + + + + X + + + + + Y1 + + + + + Y2 + + + + + Axis Type + + + + + + + 0 + 8 + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + + + + + + + + + + Line type: + + + comboLineType + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 50 + 0 + + + + 1 + + + + None + + + + + Line + + + + + StepLeft + + + + + StepRight + + + + + StepCenter + + + + + Impulse + + + + + + + + Point shape: + + + comboPointShape + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + 0 + + + + None + + + + + Cross + + + + + Plus + + + + + Circle + + + + + Disc + + + + + Square + + + + + Diamond + + + + + Star + + + + + Triangle + + + + + TriangleInverted + + + + + CrossSquare + + + + + PlusSquare + + + + + CrossCircle + + + + + PlusCircle + + + + + Peace + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + + + Save current plot... + + + + + + + :/icons/image_save:/icons/image_save + + + false + + + false + + + false + + + false + + + + + + + Load all data and redraw plot + + + + :/icons/refresh:/icons/refresh + + + + + + + + + + + + + QCustomPlot + QWidget +
qcustomplot.h
+ 1 +
+
+ + + + + + buttonLoadAllData + clicked() + PlotDock + fetchAllData() + + + 463 + 526 + + + 477 + 495 + + + + + treePlotColumns + itemChanged(QTreeWidgetItem*,int) + PlotDock + columnItemChanged(QTreeWidgetItem*,int) + + + -1 + -1 + + + -1 + -1 + + + + + treePlotColumns + itemDoubleClicked(QTreeWidgetItem*,int) + PlotDock + columnItemDoubleClicked(QTreeWidgetItem*,int) + + + -1 + -1 + + + -1 + -1 + + + + + butSavePlot + clicked() + PlotDock + savePlot() + + + -1 + -1 + + + -1 + -1 + + + + + comboLineType + currentIndexChanged(int) + PlotDock + lineTypeChanged(int) + + + -1 + -1 + + + -1 + -1 + + + + + comboPointShape + currentIndexChanged(int) + PlotDock + pointShapeChanged(int) + + + -1 + -1 + + + -1 + -1 + + + + + + fetchAllData() + columnItemChanged(QTreeWidgetItem*,int) + columnItemDoubleClicked(QTreeWidgetItem*,int) + savePlot() + lineTypeChanged(int) + pointShapeChanged(int) + +
diff --git a/src/PreferencesDialog.cpp b/src/PreferencesDialog.cpp index 622302507..7c98f9905 100644 --- a/src/PreferencesDialog.cpp +++ b/src/PreferencesDialog.cpp @@ -1,24 +1,27 @@ #include "PreferencesDialog.h" #include "ui_PreferencesDialog.h" -#include "sqlitedb.h" #include "FileDialog.h" +#include "Settings.h" +#include "MainWindow.h" +#include "FileExtensionManager.h" +#include "ProxyDialog.h" #include -#include #include #include #include +#include +#include +#include -QHash PreferencesDialog::m_hCache; - -PreferencesDialog::PreferencesDialog(QWidget* parent) +PreferencesDialog::PreferencesDialog(QWidget* parent, Tabs tab) : QDialog(parent), - ui(new Ui::PreferencesDialog) + ui(new Ui::PreferencesDialog), + m_proxyDialog(new ProxyDialog(this)), + m_dbFileExtensions(Settings::getValue("General", "DBFileExtensions").toString().split(";;")) { ui->setupUi(this); ui->treeSyntaxHighlighting->setColumnHidden(0, true); - ui->labelDatabaseDefaultSqlText->setVisible(false); - ui->editDatabaseDefaultSqlText->setVisible(false); ui->fr_bin_bg->installEventFilter(this); ui->fr_bin_fg->installEventFilter(this); @@ -26,13 +29,32 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) ui->fr_reg_fg->installEventFilter(this); ui->fr_null_bg->installEventFilter(this); ui->fr_null_fg->installEventFilter(this); + ui->fr_formatted_bg->installEventFilter(this); + ui->fr_formatted_fg->installEventFilter(this); + + connect(ui->comboDataBrowserFont, static_cast(&QFontComboBox::currentIndexChanged), this, &PreferencesDialog::updatePreviewFont); + connect(ui->spinDataBrowserFontSize, static_cast(&QSpinBox::valueChanged), this, &PreferencesDialog::updatePreviewFont); #ifndef CHECKNEWVERSION ui->labelUpdates->setVisible(false); ui->checkUpdates->setVisible(false); #endif + createBuiltinExtensionList(); + loadSettings(); + + connect(ui->appStyleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(adjustColorsToStyle(int))); + + // Avoid different heights due to having check boxes or not + ui->treeSyntaxHighlighting->setUniformRowHeights(true); + + // Set current tab + ui->tabWidget->setCurrentIndex(tab); + + // Connect 'Export Settings' and 'Import Settings' buttons + connect(ui->buttonExportSettings, &QPushButton::clicked, this, &PreferencesDialog::exportSettings); + connect(ui->buttonImportSettings, &QPushButton::clicked, this, &PreferencesDialog::importSettings); } /* @@ -46,6 +68,7 @@ PreferencesDialog::~PreferencesDialog() void PreferencesDialog::chooseLocation() { QString s = FileDialog::getExistingDirectory( + NoSpecificType, this, tr("Choose a directory"), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); @@ -56,329 +79,218 @@ void PreferencesDialog::chooseLocation() void PreferencesDialog::loadSettings() { - ui->encodingComboBox->setCurrentIndex(ui->encodingComboBox->findText(getSettingsValue("db", "defaultencoding").toString(), Qt::MatchFixedString)); - ui->comboDefaultLocation->setCurrentIndex(getSettingsValue("db", "savedefaultlocation").toInt()); - ui->locationEdit->setText(getSettingsValue("db", "defaultlocation").toString()); - ui->checkUpdates->setChecked(getSettingsValue("checkversion", "enabled").toBool()); - ui->checkHideSchemaLinebreaks->setChecked(getSettingsValue("db", "hideschemalinebreaks").toBool()); - ui->foreignKeysCheckBox->setChecked(getSettingsValue("db", "foreignkeys").toBool()); - ui->spinPrefetchSize->setValue(getSettingsValue("db", "prefetchsize").toInt()); - ui->editDatabaseDefaultSqlText->setText(getSettingsValue("db", "defaultsqltext").toString()); - - ui->comboDataBrowserFont->setCurrentIndex(ui->comboEditorFont->findText(getSettingsValue("databrowser", "font").toString())); - ui->spinDataBrowserFontSize->setValue(getSettingsValue("databrowser", "fontsize").toInt()); + ui->encodingComboBox->setCurrentIndex(ui->encodingComboBox->findText(Settings::getValue("db", "defaultencoding").toString(), Qt::MatchFixedString)); + ui->comboDefaultLocation->setCurrentIndex(Settings::getValue("db", "savedefaultlocation").toInt()); + ui->locationEdit->setText(QDir::toNativeSeparators(Settings::getValue("db", "defaultlocation").toString())); + ui->checkPromptSQLTabsInNewProject->setChecked(Settings::getValue("General", "promptsqltabsinnewproject").toBool()); + ui->checkUpdates->setChecked(Settings::getValue("checkversion", "enabled").toBool()); + + ui->checkHideSchemaLinebreaks->setChecked(Settings::getValue("db", "hideschemalinebreaks").toBool()); + ui->foreignKeysCheckBox->setChecked(Settings::getValue("db", "foreignkeys").toBool()); + ui->spinPrefetchSize->setValue(Settings::getValue("db", "prefetchsize").toInt()); + ui->editDatabaseDefaultSqlText->setText(Settings::getValue("db", "defaultsqltext").toString()); + + ui->defaultFieldTypeComboBox->addItems(DBBrowserDB::Datatypes); + + int defaultFieldTypeIndex = Settings::getValue("db", "defaultfieldtype").toInt(); + if (defaultFieldTypeIndex < DBBrowserDB::Datatypes.count()) + { + ui->defaultFieldTypeComboBox->setCurrentIndex(defaultFieldTypeIndex); + } + + ui->spinStructureFontSize->setValue(Settings::getValue("db", "fontsize").toInt()); + ui->watcherCheckBox->setChecked(Settings::getValue("db", "watcher").toBool()); + + // Gracefully handle the preferred Data Browser font not being available + int matchingFont = ui->comboDataBrowserFont->findText(Settings::getValue("databrowser", "font").toString(), Qt::MatchExactly); + if (matchingFont == -1) + matchingFont = ui->comboDataBrowserFont->findText(Settings::getDefaultValue("databrowser", "font").toString()); + ui->comboDataBrowserFont->setCurrentIndex(matchingFont); + + ui->spinDataBrowserFontSize->setValue(Settings::getValue("databrowser", "fontsize").toInt()); loadColorSetting(ui->fr_null_fg, "null_fg"); loadColorSetting(ui->fr_null_bg, "null_bg"); - loadColorSetting(ui->fr_reg_fg, "reg_fg"); - loadColorSetting(ui->fr_reg_bg, "reg_bg"); loadColorSetting(ui->fr_bin_fg, "bin_fg"); loadColorSetting(ui->fr_bin_bg, "bin_bg"); + loadColorSetting(ui->fr_reg_fg, "reg_fg"); + loadColorSetting(ui->fr_reg_bg, "reg_bg"); + loadColorSetting(ui->fr_formatted_fg, "formatted_fg"); + loadColorSetting(ui->fr_formatted_bg, "formatted_bg"); + + ui->spinSymbolLimit->setValue(Settings::getValue("databrowser", "symbol_limit").toInt()); + ui->spinCompleteThreshold->setValue(Settings::getValue("databrowser", "complete_threshold").toInt()); + ui->checkShowImagesInline->setChecked(Settings::getValue("databrowser", "image_preview").toBool()); + ui->checkCellWordWrap->setChecked(Settings::getValue("databrowser", "cell_word_wrap").toBool()); + ui->txtNull->setText(Settings::getValue("databrowser", "null_text").toString()); + ui->txtBlob->setText(Settings::getValue("databrowser", "blob_text").toString()); + ui->editFilterEscape->setText(Settings::getValue("databrowser", "filter_escape").toString()); + ui->spinFilterDelay->setValue(Settings::getValue("databrowser", "filter_delay").toInt()); - ui->txtNull->setText(getSettingsValue("databrowser", "null_text").toString()); - ui->editFilterEscape->setText(getSettingsValue("databrowser", "filter_escape").toString()); - ui->spinFilterDelay->setValue(getSettingsValue("databrowser", "filter_delay").toInt()); + ui->treeSyntaxHighlighting->resizeColumnToContents(1); for(int i=0; i < ui->treeSyntaxHighlighting->topLevelItemCount(); ++i) { - QString name = ui->treeSyntaxHighlighting->topLevelItem(i)->text(0); - QString colorname = getSettingsValue("syntaxhighlighter", name + "_colour").toString(); + std::string name = ui->treeSyntaxHighlighting->topLevelItem(i)->text(0).toStdString(); + QString colorname = Settings::getValue("syntaxhighlighter", name + "_colour").toString(); QColor color = QColor(colorname); - ui->treeSyntaxHighlighting->topLevelItem(i)->setTextColor(2, color); - ui->treeSyntaxHighlighting->topLevelItem(i)->setBackgroundColor(2, color); + ui->treeSyntaxHighlighting->topLevelItem(i)->setForeground(2, color); + ui->treeSyntaxHighlighting->topLevelItem(i)->setBackground(2, color); ui->treeSyntaxHighlighting->topLevelItem(i)->setText(2, colorname); - if (name != "null") { - ui->treeSyntaxHighlighting->topLevelItem(i)->setCheckState(3, getSettingsValue("syntaxhighlighter", name + "_bold").toBool() ? Qt::Checked : Qt::Unchecked); - ui->treeSyntaxHighlighting->topLevelItem(i)->setCheckState(4, getSettingsValue("syntaxhighlighter", name + "_italic").toBool() ? Qt::Checked : Qt::Unchecked); - ui->treeSyntaxHighlighting->topLevelItem(i)->setCheckState(5, getSettingsValue("syntaxhighlighter", name + "_underline").toBool() ? Qt::Checked : Qt::Unchecked); + + // Add font properties except for colour-only entries + if (name != "null" && name != "currentline" && + name != "background" && name != "foreground" && name != "highlight" && + name != "selected_fg" && name != "selected_bg") { + ui->treeSyntaxHighlighting->topLevelItem(i)->setCheckState(3, Settings::getValue("syntaxhighlighter", name + "_bold").toBool() ? Qt::Checked : Qt::Unchecked); + ui->treeSyntaxHighlighting->topLevelItem(i)->setCheckState(4, Settings::getValue("syntaxhighlighter", name + "_italic").toBool() ? Qt::Checked : Qt::Unchecked); + ui->treeSyntaxHighlighting->topLevelItem(i)->setCheckState(5, Settings::getValue("syntaxhighlighter", name + "_underline").toBool() ? Qt::Checked : Qt::Unchecked); } } - ui->comboEditorFont->setCurrentIndex(ui->comboEditorFont->findText(getSettingsValue("editor", "font").toString())); - ui->spinEditorFontSize->setValue(getSettingsValue("editor", "fontsize").toInt()); - ui->spinTabSize->setValue(getSettingsValue("editor", "tabsize").toInt()); - ui->spinLogFontSize->setValue(getSettingsValue("log", "fontsize").toInt()); - ui->checkAutoCompletion->setChecked(getSettingsValue("editor", "auto_completion").toBool()); - ui->checkErrorIndicators->setChecked(getSettingsValue("editor", "error_indicators").toBool()); - ui->checkHorizontalTiling->setChecked(getSettingsValue("editor", "horizontal_tiling").toBool()); - - ui->listExtensions->addItems(getSettingsValue("extensions", "list").toStringList()); - ui->checkRegexDisabled->setChecked(getSettingsValue("extensions", "disableregex").toBool()); + + // Gracefully handle the preferred Editor font not being available + matchingFont = ui->comboEditorFont->findText(Settings::getValue("editor", "font").toString(), Qt::MatchExactly); + if (matchingFont == -1) + matchingFont = ui->comboDataBrowserFont->findText(Settings::getDefaultValue("editor", "font").toString()); + ui->comboEditorFont->setCurrentIndex(matchingFont); + + ui->spinEditorFontSize->setValue(Settings::getValue("editor", "fontsize").toInt()); + ui->spinTabSize->setValue(Settings::getValue("editor", "tabsize").toInt()); + ui->checkIndentationUseTabs->setChecked(Settings::getValue("editor", "indentation_use_tabs").toBool()); + ui->spinLogFontSize->setValue(Settings::getValue("log", "fontsize").toInt()); + ui->wrapComboBox->setCurrentIndex(Settings::getValue("editor", "wrap_lines").toInt()); + ui->quoteComboBox->setCurrentIndex(Settings::getValue("editor", "identifier_quotes").toInt()); + ui->checkAutoCompletion->setChecked(Settings::getValue("editor", "auto_completion").toBool()); + ui->checkCompleteUpper->setEnabled(Settings::getValue("editor", "auto_completion").toBool()); + ui->checkCompleteUpper->setChecked(Settings::getValue("editor", "upper_keywords").toBool()); + ui->checkErrorIndicators->setChecked(Settings::getValue("editor", "error_indicators").toBool()); + ui->checkHorizontalTiling->setChecked(Settings::getValue("editor", "horizontal_tiling").toBool()); + ui->checkCloseButtonOnTabs->setChecked(Settings::getValue("editor", "close_button_on_tabs").toBool()); + + ui->listExtensions->addItems(Settings::getValue("extensions", "list").toStringList()); + for (int i=0;ilistBuiltinExtensions->count();++i) + { + QListWidgetItem* item = ui->listBuiltinExtensions->item(i); + item->setCheckState(Settings::getValue("extensions", "builtin").toMap().value(item->text()).toBool() ? Qt::Checked : Qt::Unchecked); + } + ui->checkRegexDisabled->setChecked(Settings::getValue("extensions", "disableregex").toBool()); + ui->checkAllowLoadExtension->setChecked(Settings::getValue("extensions", "enable_load_extension").toBool()); fillLanguageBox(); + ui->appStyleCombo->setCurrentIndex(Settings::getValue("General", "appStyle").toInt()); + ui->toolbarStyleComboMain->setCurrentIndex(Settings::getValue("General", "toolbarStyle").toInt()); + ui->toolbarStyleComboStructure->setCurrentIndex(Settings::getValue("General", "toolbarStyleStructure").toInt()); + ui->toolbarStyleComboBrowse->setCurrentIndex(Settings::getValue("General", "toolbarStyleBrowse").toInt()); + ui->toolbarStyleComboSql->setCurrentIndex(Settings::getValue("General", "toolbarStyleSql").toInt()); + ui->toolbarStyleComboEditCell->setCurrentIndex(Settings::getValue("General", "toolbarStyleEditCell").toInt()); + ui->spinGeneralFontSize->setValue(Settings::getValue("General", "fontsize").toInt()); + ui->spinMaxRecentFiles->setValue(Settings::getValue("General", "maxRecentFiles").toInt()); } -void PreferencesDialog::saveSettings() +void PreferencesDialog::saveSettings(bool accept) { - setSettingsValue("db", "defaultencoding", ui->encodingComboBox->currentText()); - setSettingsValue("db", "defaultlocation", ui->locationEdit->text()); - setSettingsValue("db", "savedefaultlocation", ui->comboDefaultLocation->currentIndex()); - setSettingsValue("db", "hideschemalinebreaks", ui->checkHideSchemaLinebreaks->isChecked()); - setSettingsValue("db", "foreignkeys", ui->foreignKeysCheckBox->isChecked()); - setSettingsValue("db", "prefetchsize", ui->spinPrefetchSize->value()); - setSettingsValue("db", "defaultsqltext", ui->editDatabaseDefaultSqlText->text()); - - setSettingsValue("checkversion", "enabled", ui->checkUpdates->isChecked()); - - setSettingsValue("databrowser", "font", ui->comboDataBrowserFont->currentText()); - setSettingsValue("databrowser", "fontsize", ui->spinDataBrowserFontSize->value()); + QApplication::setOverrideCursor(Qt::WaitCursor); + + Settings::setValue("db", "defaultencoding", ui->encodingComboBox->currentText()); + Settings::setValue("db", "defaultlocation", ui->locationEdit->text()); + Settings::setValue("db", "savedefaultlocation", ui->comboDefaultLocation->currentIndex()); + Settings::setValue("db", "hideschemalinebreaks", ui->checkHideSchemaLinebreaks->isChecked()); + Settings::setValue("db", "foreignkeys", ui->foreignKeysCheckBox->isChecked()); + Settings::setValue("db", "prefetchsize", ui->spinPrefetchSize->value()); + Settings::setValue("db", "defaultsqltext", ui->editDatabaseDefaultSqlText->text()); + Settings::setValue("db", "defaultfieldtype", ui->defaultFieldTypeComboBox->currentIndex()); + Settings::setValue("db", "fontsize", ui->spinStructureFontSize->value()); + Settings::setValue("db", "watcher", ui->watcherCheckBox->isChecked()); + + Settings::setValue("checkversion", "enabled", ui->checkUpdates->isChecked()); + + Settings::setValue("databrowser", "font", ui->comboDataBrowserFont->currentText()); + Settings::setValue("databrowser", "fontsize", ui->spinDataBrowserFontSize->value()); + Settings::setValue("databrowser", "image_preview", ui->checkShowImagesInline->isChecked()); + Settings::setValue("databrowser", "cell_word_wrap", ui->checkCellWordWrap->isChecked()); saveColorSetting(ui->fr_null_fg, "null_fg"); saveColorSetting(ui->fr_null_bg, "null_bg"); saveColorSetting(ui->fr_reg_fg, "reg_fg"); saveColorSetting(ui->fr_reg_bg, "reg_bg"); + saveColorSetting(ui->fr_formatted_fg, "formatted_fg"); + saveColorSetting(ui->fr_formatted_bg, "formatted_bg"); saveColorSetting(ui->fr_bin_fg, "bin_fg"); saveColorSetting(ui->fr_bin_bg, "bin_bg"); - setSettingsValue("databrowser", "null_text", ui->txtNull->text()); - setSettingsValue("databrowser", "filter_escape", ui->editFilterEscape->text()); - setSettingsValue("databrowser", "filter_delay", ui->spinFilterDelay->value()); + Settings::setValue("databrowser", "symbol_limit", ui->spinSymbolLimit->value()); + Settings::setValue("databrowser", "complete_threshold", ui->spinCompleteThreshold->value()); + Settings::setValue("databrowser", "null_text", ui->txtNull->text()); + Settings::setValue("databrowser", "blob_text", ui->txtBlob->text()); + Settings::setValue("databrowser", "filter_escape", ui->editFilterEscape->text()); + Settings::setValue("databrowser", "filter_delay", ui->spinFilterDelay->value()); for(int i=0; i < ui->treeSyntaxHighlighting->topLevelItemCount(); ++i) { - QString name = ui->treeSyntaxHighlighting->topLevelItem(i)->text(0); - setSettingsValue("syntaxhighlighter", name + "_colour", ui->treeSyntaxHighlighting->topLevelItem(i)->text(2)); - setSettingsValue("syntaxhighlighter", name + "_bold", ui->treeSyntaxHighlighting->topLevelItem(i)->checkState(3) == Qt::Checked); - setSettingsValue("syntaxhighlighter", name + "_italic", ui->treeSyntaxHighlighting->topLevelItem(i)->checkState(4) == Qt::Checked); - setSettingsValue("syntaxhighlighter", name + "_underline", ui->treeSyntaxHighlighting->topLevelItem(i)->checkState(5) == Qt::Checked); + std::string name = ui->treeSyntaxHighlighting->topLevelItem(i)->text(0).toStdString(); + Settings::setValue("syntaxhighlighter", name + "_colour", ui->treeSyntaxHighlighting->topLevelItem(i)->text(2)); + Settings::setValue("syntaxhighlighter", name + "_bold", ui->treeSyntaxHighlighting->topLevelItem(i)->checkState(3) == Qt::Checked); + Settings::setValue("syntaxhighlighter", name + "_italic", ui->treeSyntaxHighlighting->topLevelItem(i)->checkState(4) == Qt::Checked); + Settings::setValue("syntaxhighlighter", name + "_underline", ui->treeSyntaxHighlighting->topLevelItem(i)->checkState(5) == Qt::Checked); } - setSettingsValue("editor", "font", ui->comboEditorFont->currentText()); - setSettingsValue("editor", "fontsize", ui->spinEditorFontSize->value()); - setSettingsValue("editor", "tabsize", ui->spinTabSize->value()); - setSettingsValue("log", "fontsize", ui->spinLogFontSize->value()); - setSettingsValue("editor", "auto_completion", ui->checkAutoCompletion->isChecked()); - setSettingsValue("editor", "error_indicators", ui->checkErrorIndicators->isChecked()); - setSettingsValue("editor", "horizontal_tiling", ui->checkHorizontalTiling->isChecked()); + Settings::setValue("editor", "font", ui->comboEditorFont->currentText()); + Settings::setValue("editor", "fontsize", ui->spinEditorFontSize->value()); + Settings::setValue("editor", "tabsize", ui->spinTabSize->value()); + Settings::setValue("editor", "indentation_use_tabs", ui->checkIndentationUseTabs->isChecked()); + Settings::setValue("log", "fontsize", ui->spinLogFontSize->value()); + Settings::setValue("editor", "wrap_lines", ui->wrapComboBox->currentIndex()); + Settings::setValue("editor", "identifier_quotes", ui->quoteComboBox->currentIndex()); + Settings::setValue("editor", "auto_completion", ui->checkAutoCompletion->isChecked()); + Settings::setValue("editor", "upper_keywords", ui->checkCompleteUpper->isChecked()); + Settings::setValue("editor", "error_indicators", ui->checkErrorIndicators->isChecked()); + Settings::setValue("editor", "horizontal_tiling", ui->checkHorizontalTiling->isChecked()); + Settings::setValue("editor", "close_button_on_tabs", ui->checkCloseButtonOnTabs->isChecked()); QStringList extList; - foreach(QListWidgetItem* item, ui->listExtensions->findItems(QString("*"), Qt::MatchWrap | Qt::MatchWildcard)) - extList.append(item->text()); - setSettingsValue("extensions", "list", extList); - setSettingsValue("extensions", "disableregex", ui->checkRegexDisabled->isChecked()); + for(int i=0;ilistExtensions->count();++i) + extList.append(ui->listExtensions->item(i)->text()); + Settings::setValue("extensions", "list", extList); + Settings::setValue("extensions", "disableregex", ui->checkRegexDisabled->isChecked()); + Settings::setValue("extensions", "enable_load_extension", ui->checkAllowLoadExtension->isChecked()); + + QVariantMap builtinExtList; + for (int i=0;ilistBuiltinExtensions->count();++i) + builtinExtList.insert(ui->listBuiltinExtensions->item(i)->text(), ui->listBuiltinExtensions->item(i)->checkState()); + Settings::setValue("extensions", "builtin", QVariant::fromValue(builtinExtList)); // Warn about restarting to change language QVariant newLanguage = ui->languageComboBox->itemData(ui->languageComboBox->currentIndex()); - if (newLanguage != getSettingsValue("General", "language")) + if (newLanguage != Settings::getValue("General", "language")) QMessageBox::information(this, QApplication::applicationName(), tr("The language will change after you restart the application.")); - setSettingsValue("General", "language", newLanguage); - - accept(); -} + Settings::setValue("General", "language", newLanguage); + Settings::setValue("General", "appStyle", ui->appStyleCombo->currentIndex()); + Settings::setValue("General", "toolbarStyle", ui->toolbarStyleComboMain->currentIndex()); + Settings::setValue("General", "toolbarStyleStructure", ui->toolbarStyleComboStructure->currentIndex()); + Settings::setValue("General", "toolbarStyleBrowse", ui->toolbarStyleComboBrowse->currentIndex()); + Settings::setValue("General", "toolbarStyleSql", ui->toolbarStyleComboSql->currentIndex()); + Settings::setValue("General", "toolbarStyleEditCell", ui->toolbarStyleComboEditCell->currentIndex()); + Settings::setValue("General", "DBFileExtensions", m_dbFileExtensions.join(";;") ); + Settings::setValue("General", "fontsize", ui->spinGeneralFontSize->value()); + Settings::setValue("General", "maxRecentFiles", ui->spinMaxRecentFiles->value()); + Settings::setValue("General", "promptsqltabsinnewproject", ui->checkPromptSQLTabsInNewProject->isChecked()); -QVariant PreferencesDialog::getSettingsValue(const QString& group, const QString& name) -{ - // Have a look in the cache first - QHash::iterator cacheIndex = m_hCache.find(group + name); - if(cacheIndex != m_hCache.end()) - { - return cacheIndex.value(); - } else { - // Nothing found in the cache, so get the value from the settings file or get the default value if there is no value set yet - QSettings settings(QApplication::organizationName(), QApplication::organizationName()); - QVariant value = settings.value(group + "/" + name, getSettingsDefaultValue(group, name)); - - // Store this value in the cache for further usage and return it afterwards - m_hCache.insert(group + name, value); - return value; - } -} + m_proxyDialog->saveSettings(); -void PreferencesDialog::setSettingsValue(const QString& group, const QString& name, const QVariant& value, bool dont_save_to_disk) -{ - // Sometime the value has to be saved for the current session only but get discarded when the application exits. - // In order to achieve this this flag can be set which disables the save to disk mechanism and only leaves the save to cache part active. - if(dont_save_to_disk == false) - { - // Set the group and save the given value - QSettings settings(QApplication::organizationName(), QApplication::organizationName()); - settings.beginGroup(group); - settings.setValue(name, value); - settings.endGroup(); - } + if(accept) + PreferencesDialog::accept(); - // Also change it in the cache - m_hCache[group + name] = value; -} - -QVariant PreferencesDialog::getSettingsDefaultValue(const QString& group, const QString& name) -{ - // db/defaultencoding? - if(group == "db" && name == "defaultencoding") - return "UTF-8"; - - // db/savedefaultlocation? - if(group == "db" && name == "savedefaultlocation") - return 2; - - // db/defaultlocation? - if(group == "db" && name == "defaultlocation") - return QDir::homePath(); - - // db/lastlocation? - if(group == "db" && name == "lastlocation") - return getSettingsValue("db", "defaultlocation"); - - // db/hideschemalinebreaks? - if(group == "db" && name == "hideschemalinebreaks") - return false; - - // db/foreignkeys? - if(group == "db" && name == "foreignkeys") - return true; - - // db/prefetchsize? - if(group == "db" && name == "prefetchsize") - return 50000; - - // db/defaultsqltext? - if(group == "db" && name == "defaultsqltext") - return ""; - - // MainWindow/geometry? - if(group == "MainWindow" && name == "geometry") - return ""; - - // MainWindow/windowState? - if(group == "MainWindow" && name == "windowState") - return ""; - - // SQLLogDock/Log? - if(group == "SQLLogDock" && name == "Log") - return "Application"; - - // General/recentFileList? - if(group == "General" && name == "recentFileList") - return QStringList(); - - // General/language? - if(group == "General" && name == "language") - return QLocale::system().name(); - - // checkversion/enabled - if(group == "checkversion" && name == "enabled") - return true; - - // Data Browser/NULL Fields - if(group == "databrowser") - { - if(name == "font") - return "Sans Serif"; - if(name == "fontsize") - return 10; - if(name == "null_text") - return "NULL"; - if(name == "filter_escape") - return "\\"; - if(name == "filter_delay") - return 200; - if(name == "null_fg_colour") - return QColor(Qt::lightGray).name(); - if(name == "null_bg_colour") - return QColor(Qt::white).name(); - if(name == "reg_fg_colour") - return QColor(Qt::black).name(); - if(name == "reg_bg_colour") - return QColor(Qt::white).name(); - if(name == "bin_fg_colour") - return QColor(Qt::lightGray).name(); - if(name == "bin_bg_colour") - return QColor(Qt::white).name(); - } - - // syntaxhighlighter? - if(group == "syntaxhighlighter") - { - // Bold? Only tables, functions and keywords are bold by default - if(name.right(4) == "bold") - return name == "keyword_bold" || name == "table_bold" || name == "function_bold"; - - // Italic? Nothing by default - if(name.right(6) == "italic") - return false; - - // Underline? Nothing by default - if(name.right(9) == "underline") - return false; - - // Colour? - if(name.right(6) == "colour") - { - if(name == "keyword_colour") - return QColor(Qt::darkBlue).name(); - else if(name == "function_colour") - return QColor(Qt::blue).name(); - else if(name == "table_colour") - return QColor(Qt::darkCyan).name(); - else if(name == "comment_colour") - return QColor(Qt::darkGreen).name(); - else if(name == "identifier_colour") - return QColor(Qt::darkMagenta).name(); - else if(name == "string_colour") - return QColor(Qt::red).name(); - else if(name == "currentline_colour") - return QColor(236, 236, 245).name(); - } - } - - // editor/font? - if(group == "editor" && name == "font") - return "Monospace"; - - // editor/fontsize or log/fontsize? - if((group == "editor" || group == "log") && name == "fontsize") - return 9; - - if(group == "editor") - { - if(name == "tabsize") - { - return 4; - } - } - - // editor/auto_completion? - if(group == "editor" && name == "auto_completion") - return true; - - // editor/error_indicators? - if(group == "editor" && name == "error_indicators") - return true; - - // editor/horizontal_tiling? - if(group == "editor" && name == "horizontal_tiling") - return false; - - // extensions/list? - if(group == "extensions" && name == "list") - return QStringList(); - - // extensions/disableregex? - if(group == "extension" && name == "disableregex") - return false; - - // PlotDock/lineType or pointShape? - if(group == "PlotDock") - { - // QCPGraph::lsLine - if(name == "lineType") - return 1; - - // QCPScatterStyle::ssDisk - if(name == "pointShape") - return 4; - } - - // Unknown combination of group and name? Return an invalid QVariant! - return QVariant(); + QApplication::restoreOverrideCursor(); } void PreferencesDialog::showColourDialog(QTreeWidgetItem* item, int column) { - if(item->text(column).left(1) != "#") + QString text = item->text(column); + if(!text.size() || text.at(0) != '#') return; - QColor colour = QColorDialog::getColor(QColor(item->text(column)), this); + QColor colour = QColorDialog::getColor(text, this); if(colour.isValid()) { - item->setTextColor(column, colour); - item->setBackgroundColor(column, colour); + item->setForeground(column, colour); + item->setBackground(column, colour); item->setText(column, colour.name()); } } @@ -388,6 +300,7 @@ bool PreferencesDialog::eventFilter(QObject *obj, QEvent *event) // Use mouse click and enter press on the frames to pop up a colour dialog if (obj == ui->fr_bin_bg || obj == ui->fr_bin_fg || obj == ui->fr_reg_bg || obj == ui->fr_reg_fg || + obj == ui->fr_formatted_bg || obj == ui->fr_formatted_fg || obj == ui->fr_null_bg || obj == ui->fr_null_fg) { if (event->type() == QEvent::KeyPress) @@ -411,9 +324,7 @@ bool PreferencesDialog::eventFilter(QObject *obj, QEvent *event) if (colour.isValid()) { - QPalette palette = frame->palette(); - palette.setColor(frame->backgroundRole(), colour); - frame->setPalette(palette); + setColorSetting(frame, colour); } // Consume return true; @@ -426,9 +337,10 @@ bool PreferencesDialog::eventFilter(QObject *obj, QEvent *event) void PreferencesDialog::addExtension() { QString file = FileDialog::getOpenFileName( + OpenExtensionFile, this, tr("Select extension file"), - tr("Extensions(*.so *.dll);;All files(*)")); + tr("Extensions(*.so *.dylib *.dll);;All files(*)")); if(QFile::exists(file)) ui->listExtensions->addItem(file); @@ -440,6 +352,62 @@ void PreferencesDialog::removeExtension() ui->listExtensions->takeItem(ui->listExtensions->currentIndex().row()); } +void PreferencesDialog::createBuiltinExtensionList() +{ + QDir dir; + QStringList files; + + // If we upgrade Qt framework version to 6.x at some point, use 'macos' instead of 'osx.' + // For further information, see the https://doc.qt.io/qt-6/qsysinfo.html + if (QSysInfo::productType() == "osx") { + dir.setPath(qApp->applicationDirPath() + "/../Extensions/"); + files = dir.entryList(QStringList() << "*.dylib", QDir::Files); + } + else if (QSysInfo::productType() == "windows") { + dir.setPath(qApp->applicationDirPath() + "/extensions/"); + files = dir.entryList(QStringList() << "*.dll", QDir::Files); + } + else { + const QString productType (QSysInfo::productType()); + const QString cpuArchitecture (QSysInfo::currentCpuArchitecture()); + if (productType == "fedora" || productType == "redhat") { + if (cpuArchitecture.contains("64")) + dir.setPath("/usr/lib64/"); + else + dir.setPath("/usr/lib/"); + } else { + if (cpuArchitecture == "arm") { + dir.setPath("/usr/lib/aarch-linux-gnu/"); + } else if (cpuArchitecture == "arm64") { + dir.setPath("/usr/lib/aarch64-linux-gnu/"); + } else if (cpuArchitecture == "i386") { + dir.setPath("/usr/lib/i386-linux-gnu/"); + } else if (cpuArchitecture == "x86_64") { + dir.setPath("/usr/lib/x86_64-linux-gnu/"); + } else { + dir.setPath("/usr/lib/"); + } + } + // There is no single naming convention for SQLite extension libraries, + // but this gives good results, at least on Debian based systems. + // The patterns have to exclude "libsqlite3.so", which is the SQLite3 + // library, not an extension. + files = dir.entryList(QStringList() + << "libsqlite3[!.]*.so" + << "mod_*.so" + << "lib?*sqlite*.so", QDir::Files); + } + + for (const QString& file: files) { + QString absoluteFilePath = dir.absoluteFilePath(file); + QListWidgetItem* item = new QListWidgetItem(absoluteFilePath, ui->listBuiltinExtensions); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + // The check state is redetermined after the 'loadSettings()' function call. + item->setCheckState(Qt::Unchecked); + ui->listBuiltinExtensions->addItem(item); + } +} + void PreferencesDialog::fillLanguageBox() { QDir translationsDir(QCoreApplication::applicationDirPath() + "/translations", @@ -464,7 +432,7 @@ void PreferencesDialog::fillLanguageBox() // Get available *.qm files from translation dir near executable as well as from resources QFileInfoList file_infos = translationsDir.entryInfoList(); file_infos += QDir(":/translations").entryInfoList(); - foreach(const QFileInfo &file, file_infos) + for(const QFileInfo& file : qAsConst(file_infos)) { QLocale locale(file.baseName().remove("sqlb_")); @@ -488,7 +456,7 @@ void PreferencesDialog::fillLanguageBox() ui->languageComboBox->model()->sort(0); // Try to select the language for the stored locale - int index = ui->languageComboBox->findData(getSettingsValue("General", "language"), + int index = ui->languageComboBox->findData(Settings::getValue("General", "language"), Qt::UserRole, Qt::MatchExactly); // If there's no translation for the current locale, default to English @@ -503,18 +471,167 @@ void PreferencesDialog::fillLanguageBox() ui->languageComboBox->removeItem(index); ui->languageComboBox->insertItem(0, chosenIcon, chosenLanguage, chosenLocale); ui->languageComboBox->setCurrentIndex(0); + + // This is a workaround needed for QDarkStyleSheet. + // See https://github.com/ColinDuquesnoy/QDarkStyleSheet/issues/169 + QStyledItemDelegate* styledItemDelegate = new QStyledItemDelegate(ui->languageComboBox); + ui->languageComboBox->setItemDelegate(styledItemDelegate); + } -void PreferencesDialog::loadColorSetting(QFrame *frame, const QString & settingName) +void PreferencesDialog::loadColorSetting(QFrame *frame, const std::string& settingName) { + QColor color = QColor(Settings::getValue("databrowser", settingName + "_colour").toString()); + setColorSetting(frame, color); +} + +void PreferencesDialog::setColorSetting(QFrame *frame, const QColor &color) +{ + QPalette::ColorRole role; + QLineEdit *line; + + if (frame == ui->fr_bin_bg) { + line = ui->txtBlob; + role = line->backgroundRole(); + } else if (frame == ui->fr_bin_fg) { + line = ui->txtBlob; + role = line->foregroundRole(); + } else if (frame == ui->fr_reg_bg) { + line = ui->txtRegular; + role = line->backgroundRole(); + } else if (frame == ui->fr_reg_fg) { + line = ui->txtRegular; + role = line->foregroundRole(); + } else if (frame == ui->fr_formatted_bg) { + line = ui->txtFormatted; + role = line->backgroundRole(); + } else if (frame == ui->fr_formatted_fg) { + line = ui->txtFormatted; + role = line->foregroundRole(); + } else if (frame == ui->fr_null_bg) { + line = ui->txtNull; + role = line->backgroundRole(); + } else if (frame == ui->fr_null_fg) { + line = ui->txtNull; + role = line->foregroundRole(); + } else + return; + QPalette palette = frame->palette(); - palette.setColor(frame->backgroundRole(), - QColor(getSettingsValue("databrowser", settingName + "_colour").toString())); + palette.setColor(frame->backgroundRole(), color); frame->setPalette(palette); + + frame->setStyleSheet(QString(".QFrame {background-color: %2}").arg(color.name())); + + palette = line->palette(); + palette.setColor(role, color); + line->setPalette(palette); + + line->setStyleSheet(QString(".QLineEdit {color: %1; background-color: %2}").arg(palette.color(line->foregroundRole()).name(), + palette.color(line->backgroundRole()).name())); } -void PreferencesDialog::saveColorSetting(QFrame *frame, const QString & settingName) +void PreferencesDialog::saveColorSetting(QFrame* frame, const std::string& settingName) { - setSettingsValue("databrowser", settingName + "_colour", + Settings::setValue("databrowser", settingName + "_colour", frame->palette().color(frame->backgroundRole())); } + +void PreferencesDialog::adjustColorsToStyle(int style) +{ + Settings::AppStyle appStyle = static_cast(style); + setColorSetting(ui->fr_null_fg, Settings::getDefaultColorValue("databrowser", "null_fg_colour", appStyle)); + setColorSetting(ui->fr_null_bg, Settings::getDefaultColorValue("databrowser", "null_bg_colour", appStyle)); + setColorSetting(ui->fr_bin_fg, Settings::getDefaultColorValue("databrowser", "bin_fg_colour", appStyle)); + setColorSetting(ui->fr_bin_bg, Settings::getDefaultColorValue("databrowser", "bin_bg_colour", appStyle)); + setColorSetting(ui->fr_reg_fg, Settings::getDefaultColorValue("databrowser", "reg_fg_colour", appStyle)); + setColorSetting(ui->fr_reg_bg, Settings::getDefaultColorValue("databrowser", "reg_bg_colour", appStyle)); + setColorSetting(ui->fr_formatted_fg, Settings::getDefaultColorValue("databrowser", "formatted_fg_colour", appStyle)); + setColorSetting(ui->fr_formatted_bg, Settings::getDefaultColorValue("databrowser", "formatted_bg_colour", appStyle)); + + for(int i=0; i < ui->treeSyntaxHighlighting->topLevelItemCount(); ++i) + { + std::string name = ui->treeSyntaxHighlighting->topLevelItem(i)->text(0).toStdString(); + QColor color = Settings::getDefaultColorValue("syntaxhighlighter", name + "_colour", appStyle); + ui->treeSyntaxHighlighting->topLevelItem(i)->setForeground(2, color); + ui->treeSyntaxHighlighting->topLevelItem(i)->setBackground(2, color); + ui->treeSyntaxHighlighting->topLevelItem(i)->setText(2, color.name()); + } +} + +void PreferencesDialog::updatePreviewFont() +{ + if (ui->spinDataBrowserFontSize->value() != 0) { + QFont textFont(ui->comboDataBrowserFont->currentText()); + textFont.setPointSize(ui->spinDataBrowserFontSize->value()); + ui->txtRegular->setFont(textFont); + ui->txtFormatted->setFont(textFont); + textFont.setItalic(true); + ui->txtNull->setFont(textFont); + ui->txtBlob->setFont(textFont); + } +} + +void PreferencesDialog::showFileExtensionManager() +{ + FileExtensionManager *manager = new FileExtensionManager(m_dbFileExtensions, this); + + if(manager->exec() == QDialog::Accepted) + { + m_dbFileExtensions = manager->getDBFileExtensions(); + } +} + +void PreferencesDialog::buttonBoxClicked(QAbstractButton* button) +{ + if (button == ui->buttonBox->button(QDialogButtonBox::Cancel)) + reject(); + else if (button == ui->buttonBox->button(QDialogButtonBox::Save)) + saveSettings(); + else if (button == ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)) { + if (QMessageBox::warning(this, QApplication::applicationName(), tr("Are you sure you want to clear all the saved settings?\nAll your preferences will be lost and default values will be used."), + QMessageBox::RestoreDefaults | QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::RestoreDefaults) + { + Settings::restoreDefaults(); + accept(); + } + } +} + +void PreferencesDialog::configureProxy() +{ + m_proxyDialog->show(); +} + +void PreferencesDialog::exportSettings() +{ + saveSettings(false); + + const QString fileName = FileDialog::getSaveFileName(CreateSettingsFile, this, tr("Save Settings File"), tr("Initialization File (*.ini)")); + if(!fileName.isEmpty()) + { + Settings::exportSettings(fileName); + QMessageBox::information(this, QApplication::applicationName(), (tr("The settings file has been saved in location :\n") + fileName)); + } +} + +void PreferencesDialog::importSettings() +{ + const QString fileName = FileDialog::getOpenFileName(OpenSettingsFile, this, tr("Open Settings File"), tr("Initialization File (*.ini)")); + const QVariant existingLanguage = Settings::getValue("General", "language"); + + if(!fileName.isEmpty()) + { + if(Settings::importSettings(fileName)) + { + QMessageBox::information(this, QApplication::applicationName(), tr("The settings file was loaded properly.")); + if (existingLanguage != Settings::getValue("General", "language")) + QMessageBox::information(this, QApplication::applicationName(), + tr("The language will change after you restart the application.")); + + accept(); + } else { + QMessageBox::critical(this, QApplication::applicationName(), tr("The selected settings file is not a normal settings file.\nPlease check again.")); + } + } +} diff --git a/src/PreferencesDialog.h b/src/PreferencesDialog.h index 87eccf906..fae1e5bc9 100644 --- a/src/PreferencesDialog.h +++ b/src/PreferencesDialog.h @@ -2,11 +2,12 @@ #define PREFERENCESDIALOG_H #include -#include -#include class QTreeWidgetItem; class QFrame; +class QAbstractButton; + +class ProxyDialog; namespace Ui { class PreferencesDialog; @@ -17,37 +18,50 @@ class PreferencesDialog : public QDialog Q_OBJECT public: - explicit PreferencesDialog(QWidget* parent = 0); - ~PreferencesDialog(); + enum Tabs + { + TabGeneral, + TabDatabase, + TabDataBrowser, + TabSql, + TabExtensions + }; - // Use these methods to access the application settings. - static QVariant getSettingsValue(const QString& group, const QString& name); - static void setSettingsValue(const QString& group, const QString& name, const QVariant& value, bool dont_save_to_disk = false); + explicit PreferencesDialog(QWidget* parent = nullptr, Tabs tab = TabGeneral); + ~PreferencesDialog() override; private slots: - virtual void loadSettings(); - virtual void saveSettings(); + void loadSettings(); + void saveSettings(bool accept=true); + + void chooseLocation(); + void showColourDialog(QTreeWidgetItem* item, int column); + void addExtension(); + void createBuiltinExtensionList(); + void removeExtension(); + void updatePreviewFont(); + void adjustColorsToStyle(int style); + void configureProxy(); - virtual void chooseLocation(); - virtual void showColourDialog(QTreeWidgetItem* item, int column); - virtual void addExtension(); - virtual void removeExtension(); + void showFileExtensionManager(); + void buttonBoxClicked(QAbstractButton* button); private: - Ui::PreferencesDialog *ui; + Ui::PreferencesDialog* ui; - // This works similar to getSettingsValue but returns the default value instead of the value set by the user - static QVariant getSettingsDefaultValue(const QString& group, const QString& name); + ProxyDialog* m_proxyDialog; - // Cache for storing the settings to avoid repeatedly reading the settings file all the time - static QHash m_hCache; + QStringList m_dbFileExtensions; void fillLanguageBox(); - void loadColorSetting(QFrame *frame, const QString &name); - void saveColorSetting(QFrame *frame, const QString &name); + void loadColorSetting(QFrame *frame, const std::string& name); + void setColorSetting(QFrame* frame, const QColor &color); + void saveColorSetting(QFrame* frame, const std::string& name); + void exportSettings(); + void importSettings(); protected: - bool eventFilter(QObject *obj, QEvent *event); + bool eventFilter(QObject *obj, QEvent *event) override; }; #endif diff --git a/src/PreferencesDialog.ui b/src/PreferencesDialog.ui index 35c471a3f..2419f68e2 100644 --- a/src/PreferencesDialog.ui +++ b/src/PreferencesDialog.ui @@ -6,8 +6,8 @@ 0 0 - 590 - 532 + 756 + 625 @@ -27,7 +27,17 @@ &General - + + + + Default &location + + + locationEdit + + + + @@ -81,33 +91,61 @@ - + - Default &location + Lan&guage - locationEdit + languageComboBox + + + + + + + + 0 + 0 + + + + QComboBox::AdjustToContents + + + 35 + + + + 20 + 15 + - + - Lan&guage + Application style - languageComboBox + toolbarStyleComboStructure - + 0 0 + + When this value is changed, all the other color preferences are also set to matching colors. + + + 0 + QComboBox::AdjustToContents @@ -120,170 +158,641 @@ 15
+ + + Follow the desktop style + + + + + Dark style + + + + + Light style + + - + + + This sets the font size for all UI elements which do not have their own font size option. + - Automatic &updates + Font size - checkUpdates + spinGeneralFontSize - + + + + - enabled + Max Recent Files + + + spinMaxRecentFiles - - - - - &Database - - - - QFormLayout::FieldsStayAtSizeHint - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::AlignHCenter|Qt::AlignTop - - - + + + + QAbstractSpinBox::CorrectToNearestValue + + + 1 + + + 40 + + + + + - Database &encoding + Toolbar style - encodingComboBox + toolbarStyleComboMain - - + + + + Main Window + + + 20 + + + toolbarStyleComboMain + + + + + + + + 0 + 0 + + + + 2 + + + QComboBox::AdjustToContents + + + 35 + + + + 20 + 15 + + + + + Only display the icon + + + + + Only display the text + + + + + The text appears beside the icon + + - UTF-8 + The text appears under the icon - UTF-16 + Follow the style - - - - Open databases with foreign keys enabled. - + + - &Foreign keys + Database Structure + + + 20 - foreignKeysCheckBox + toolbarStyleComboStructure - - - - enabled + + + + + 0 + 0 + + + 2 + + + QComboBox::AdjustToContents + + + 35 + + + + 20 + 15 + + + + + Only display the icon + + + + + Only display the text + + + + + The text appears beside the icon + + + + + The text appears under the icon + + + + + Follow the style + + - - + + - Remove line breaks in schema &view + Browse Data + + + 20 - checkHideSchemaLinebreaks + toolbarStyleComboBrowse - - + + + + + 0 + 0 + + + + 0 + + + QComboBox::AdjustToContents + + + 35 + + + + 20 + 15 + + + + + Only display the icon + + + + + Only display the text + + + + + The text appears beside the icon + + + + + The text appears under the icon + + + + + Follow the style + + + - - + + - Prefetch block si&ze + Execute SQL + + + 20 - spinPrefetchSize + toolbarStyleComboSql - - - - 255 + + + + + 0 + 0 + - - 1000000 + + 0 + + + QComboBox::AdjustToContents + + + 35 + + + + 20 + 15 + + + + Only display the icon + + + + + Only display the text + + + + + The text appears beside the icon + + + + + The text appears under the icon + + + + + Follow the style + + - - + + - Advanced + Edit Database Cell - - - :/icons/down:/icons/down + + 20 - - true + + toolbarStyleComboEditCell - - - + + + + + 0 + 0 + + + + 0 + + + QComboBox::AdjustToContents + + + 35 + + 20 - 0 + 15 - - - 16777215 - 200 - + + + Only display the icon + + + + + Only display the text + + + + + The text appears beside the icon + + + + + The text appears under the icon + + + + + Follow the style + + + + + + + + Prompt to save SQL tabs +in new project file + + + checkPromptSQLTabsInNewProject + + + + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + + + enabled + + + true + + + + + + + Automatic &updates + + + checkUpdates + + + + + + + enabled + + + + + + + DB file extensions + + + buttonManageFileExtension - - + + + + Manage + + + + + + + Proxy + + + buttonProxy + + + + + + + Configure + + + + + + + + &Database + + + + + + QFormLayout::FieldsStayAtSizeHint + + + + + Database &encoding + + + encodingComboBox + + + + + + + Open databases with foreign keys enabled. + + + &Foreign keys + + + foreignKeysCheckBox + + + + + + + Remove line breaks in schema &view + + + checkHideSchemaLinebreaks + + + + + + + Prefetch block si&ze + + + spinPrefetchSize + + + + + + + Default field type + + + defaultFieldTypeComboBox + + + + + + + + + + QAbstractSpinBox::CorrectToNearestValue + + + 255 + + + 1000000 + + + + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + + + enabled + + + + + + + enabled + + + + + + + + UTF-8 + + + + + UTF-16 + + + + + + + + Database structure font size + + + spinStructureFontSize + + + + + + + + + + When the database is open in readonly mode, watch the database file and refresh when it is updated. + + + &When readonly, refresh on changed file + + + watcherCheckBox + + + + + - SQL to execute after opening database + enabled - - editDatabaseDefaultSqlText + + true - - - - Qt::Horizontal - - - - 180 - 20 - - - + + + + + + + + SQ&L to execute after opening database + + + editDatabaseDefaultSqlText + + + + + + + + 20 + 0 + + + + + 16777215 + 16777215 + + + + + @@ -296,80 +805,86 @@ + + + 0 + 0 + + Font - - + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + &Font + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + comboDataBrowserFont - - + + + + + 0 + 0 + + + - + - Font si&ze: + Font si&ze + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter spinDataBrowserFontSize - + - + - NULL fields + Field display - - - - - - - - 15 - - - Qt::AlignCenter - - - - + + + + + 0 + 0 + + - &Text + Displayed &text - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignCenter txtNull - - - - - - - Field colors - - @@ -380,28 +895,44 @@ + + + + Binary + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + - + - Regular + Formatted Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - + + - + Regular + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - + Qt::StrongFocus + + Click to set this color + true @@ -413,23 +944,38 @@ - - - - Text + + + + Qt::StrongFocus - - Qt::AlignCenter + + Click to set this color + + + true + + + QFrame::StyledPanel + + + QFrame::Raised - - + + + + + 0 + 0 + + - Binary + Text color - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignCenter @@ -438,6 +984,9 @@ Qt::StrongFocus + + Click to set this color + true @@ -451,8 +1000,14 @@ + + + 0 + 0 + + - Background + Background color Qt::AlignCenter @@ -464,6 +1019,9 @@ Qt::StrongFocus + + Click to set this color + true @@ -480,6 +1038,9 @@ Qt::StrongFocus + + Click to set this color + true @@ -496,6 +1057,9 @@ Qt::StrongFocus + + Click to set this color + true @@ -508,10 +1072,32 @@ + + + Qt::StrongFocus + + + Click to set this color + + + true + + + QFrame::StyledPanel + + + QFrame::Raised + + + + Qt::StrongFocus + + Click to set this color + true @@ -523,32 +1109,210 @@ + + + + + 0 + 0 + + + + + true + + + + NULL + + + + + + + + 0 + 0 + + + + + false + + + + Preview only (N/A) + + + true + + + + + + + + 0 + 0 + + + + + false + + + + Preview only (N/A) + + + true + + + + + + + + 0 + 0 + + + + + true + + + + BLOB + + + false + + + - + + + + 0 + 0 + + - Filters + Content - - - - - 1 + + + + + Symbol limit in cell + + + spinSymbolLimit - + - Escape character + Threshold for completion and calculation on selection - editFilterEscape + spinCompleteThreshold + + + + + + + Show images in cell + + + checkShowImagesInline + + + + + + + Enable word wrap in cell + + + checkCellWordWrap + + + + + + + QAbstractSpinBox::CorrectToNearestValue + + + 1 + + + 20000 + + + + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + + + QAbstractSpinBox::CorrectToNearestValue + + + 0 + + + 100000000 + + + + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + + + + + + + Enable this option to turn on word wrap in the cells. + + + + + + + + 0 + 0 + + + + Filters + + + + QLayout::SetDefaultConstraint + @@ -559,13 +1323,30 @@ - - - - Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. - - - 5000 + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + + + 5000 + + + + + + + Escape character + + + editFilterEscape + + + + + + + 1 @@ -591,7 +1372,7 @@ - Settings name + Settings name @@ -641,7 +1422,7 @@ - function + function Function @@ -729,51 +1510,117 @@ - currentline + currentline Current line + + + background + + + Background + + + + + foreground + + + Foreground + + + + + selected_bg + + + Selection background + + + + + selected_fg + + + Selection foreground + + + + + highlight + + + Highlight + + - - + + - SQL &editor font size + SQL editor &font - spinEditorFontSize + comboEditorFont - - - - 1 - - + + + + + + + + + SQL &editor font size + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + spinEditorFontSize + + + + + + + QAbstractSpinBox::CorrectToNearestValue + + + 1 + + + + - + - SQL &log font size + SQL &results font size spinLogFontSize - + + + QAbstractSpinBox::CorrectToNearestValue + 1 - + Tab size @@ -783,8 +1630,11 @@ - + + + QAbstractSpinBox::CorrectToNearestValue + 1 @@ -796,20 +1646,133 @@ - - + + - SQL editor &font + Use tabs for indentation - comboEditorFont + checkAutoCompletion - - + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + + + enabled + + + + + + + &Wrap lines + + + wrapComboBox + + + + + + + + Never + + + + + At word boundaries + + + + + At character boundaries + + + + + At whitespace boundaries + + + + + + &Quotes for identifiers + + + quoteComboBox + + + + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + + + + + + + "Double quotes" - Standard SQL (recommended) + + + + + `Grave accents` - Traditional MySQL quotes + + + + + [Square brackets] - Traditional MS SQL Server quotes + + + + + + + + Code co&mpletion + + + checkAutoCompletion + + + + + + + enabled + + + + + + + Keywords in &UPPER CASE + + + checkCompleteUpper + + + + + + + When set, the SQL keywords are completed in UPPER CASE letters. + + + enabled + + + + Error indicators @@ -819,17 +1782,17 @@ - + - Enabling error indicators highlights the SQL code lines that caused errors during the last execution + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background enabled - + Hori&zontal tiling @@ -839,7 +1802,7 @@ - + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. @@ -849,18 +1812,21 @@ - - + + - Code co&mpletion + Close button on tabs - checkAutoCompletion + checkCloseButtonOnTabs - - + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + enabled @@ -880,6 +1846,9 @@ Select extensions to load for every database: + + listExtensions + @@ -935,6 +1904,20 @@ + + + + Select built-in extensions to load for every database: + + + + + + + true + + + @@ -945,26 +1928,54 @@ + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + + + Allow loading extensions from SQL code + + + - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - + + + + + Export Settings + + + + + + + Import Settings + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::RestoreDefaults|QDialogButtonBox::Save + + + + SqlTextEdit - QTextEdit + QWidget
sqltextedit.h
1
@@ -975,22 +1986,42 @@ locationEdit setLocationButton languageComboBox + appStyleCombo + spinGeneralFontSize + spinMaxRecentFiles + toolbarStyleComboMain + toolbarStyleComboStructure + toolbarStyleComboBrowse + toolbarStyleComboSql + toolbarStyleComboEditCell + checkPromptSQLTabsInNewProject checkUpdates + buttonProxy + buttonManageFileExtension encodingComboBox foreignKeysCheckBox checkHideSchemaLinebreaks spinPrefetchSize - buttonDatabaseAdvanced - editDatabaseDefaultSqlText + defaultFieldTypeComboBox + spinStructureFontSize comboDataBrowserFont spinDataBrowserFontSize - txtNull fr_null_fg fr_null_bg + txtNull fr_bin_fg fr_bin_bg + txtBlob + fr_formatted_fg + fr_formatted_bg + txtFormatted fr_reg_fg fr_reg_bg + txtRegular + spinSymbolLimit + spinCompleteThreshold + checkShowImagesInline + checkCellWordWrap spinFilterDelay editFilterEscape treeSyntaxHighlighting @@ -998,50 +2029,27 @@ spinEditorFontSize spinLogFontSize spinTabSize + checkIndentationUseTabs + wrapComboBox + quoteComboBox checkAutoCompletion + checkCompleteUpper checkErrorIndicators checkHorizontalTiling + checkCloseButtonOnTabs listExtensions buttonAddExtension buttonRemoveExtension + listBuiltinExtensions checkRegexDisabled + checkAllowLoadExtension + buttonExportSettings + buttonImportSettings - - buttonBox - accepted() - PreferencesDialog - saveSettings() - - - 281 - 525 - - - 155 - 143 - - - - - buttonBox - rejected() - PreferencesDialog - reject() - - - 349 - 525 - - - 286 - 144 - - - buttonAddExtension clicked() @@ -1049,8 +2057,8 @@ addExtension() - 571 - 99 + 733 + 94 245 @@ -1065,8 +2073,8 @@ removeExtension() - 571 - 137 + 733 + 123 245 @@ -1097,8 +2105,8 @@ chooseLocation() - 567 - 100 + 733 + 103 294 @@ -1107,34 +2115,66 @@ - buttonDatabaseAdvanced + checkAutoCompletion toggled(bool) - labelDatabaseDefaultSqlText - setVisible(bool) + checkCompleteUpper + setEnabled(bool) - 375 - 202 + 733 + 444 - 64 - 243 + 733 + 474 - buttonDatabaseAdvanced - toggled(bool) - editDatabaseDefaultSqlText - setVisible(bool) + buttonBox + clicked(QAbstractButton*) + PreferencesDialog + buttonBoxClicked(QAbstractButton*) - 375 - 202 + 644 + 614 + + + 385 + 306 + + + + + buttonManageFileExtension + clicked() + PreferencesDialog + showFileExtensionManager() + + + -1 + -1 + + + -1 + -1 + + + + + buttonProxy + clicked() + PreferencesDialog + configureProxy() + + + 247 + 538 - 375 - 251 + 385 + 306 @@ -1145,5 +2185,8 @@ showColourDialog(QTreeWidgetItem*,int) addExtension() removeExtension() + configureProxy() + buttonBoxClicked() + showFileExtensionManager() diff --git a/src/ProxyDialog.cpp b/src/ProxyDialog.cpp new file mode 100644 index 000000000..2da7aa506 --- /dev/null +++ b/src/ProxyDialog.cpp @@ -0,0 +1,57 @@ +#include "ProxyDialog.h" +#include "ui_ProxyDialog.h" +#include "Settings.h" + +ProxyDialog::ProxyDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::ProxyDialog) +{ + ui->setupUi(this); + + // Add different proxy types. We use user data strings for addressing them later + ui->comboType->addItem(tr("None"), "none"); + ui->comboType->addItem(tr("System settings"), "system"); + ui->comboType->addItem(tr("HTTP"), "http"); + ui->comboType->addItem(tr("SOCKS5"), "socks5"); + + // Load current settings + ui->comboType->setCurrentIndex(ui->comboType->findData(Settings::getValue("proxy", "type").toString())); + ui->editHost->setText(Settings::getValue("proxy", "host").toString()); + ui->spinPort->setValue(Settings::getValue("proxy", "port").toInt()); + ui->checkAuthentication->setChecked(Settings::getValue("proxy", "authentication").toBool()); + ui->editUser->setText(Settings::getValue("proxy", "user").toString()); + ui->editPassword->setText(Settings::getValue("proxy", "password").toString()); +} + +ProxyDialog::~ProxyDialog() +{ + delete ui; +} + +void ProxyDialog::proxyTypeChanged(int /*new_index*/) +{ + // When selecting the "None" or "System settings" proxy types, disable all the other input fields + bool proxy_configuration = (ui->comboType->currentData() != "none" && ui->comboType->currentData() != "system"); + + ui->editHost->setEnabled(proxy_configuration); + ui->spinPort->setEnabled(proxy_configuration); + ui->checkAuthentication->setEnabled(proxy_configuration); + ui->editUser->setEnabled(ui->checkAuthentication->isChecked() && proxy_configuration); // Enable user name and password only if the... + ui->editPassword->setEnabled(ui->checkAuthentication->isChecked() && proxy_configuration); // ... Authentication Required checkbox is checked +} + +void ProxyDialog::authenticationRequiredChanged(bool required) +{ + ui->editUser->setEnabled(required); + ui->editPassword->setEnabled(required); +} + +void ProxyDialog::saveSettings() const +{ + Settings::setValue("proxy", "type", ui->comboType->currentData()); + Settings::setValue("proxy", "host", ui->editHost->text()); + Settings::setValue("proxy", "port", ui->spinPort->value()); + Settings::setValue("proxy", "authentication", ui->checkAuthentication->isChecked()); + Settings::setValue("proxy", "user", ui->editUser->text()); + Settings::setValue("proxy", "password", ui->editPassword->text()); +} diff --git a/src/ProxyDialog.h b/src/ProxyDialog.h new file mode 100644 index 000000000..9fbae9902 --- /dev/null +++ b/src/ProxyDialog.h @@ -0,0 +1,28 @@ +#ifndef PROXYDIALOG_H +#define PROXYDIALOG_H + +#include + +namespace Ui { +class ProxyDialog; +} + +class ProxyDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ProxyDialog(QWidget* parent = nullptr); + ~ProxyDialog() override; + + void saveSettings() const; + +private slots: + void proxyTypeChanged(int new_index); + void authenticationRequiredChanged(bool required); + +private: + Ui::ProxyDialog* ui; +}; + +#endif diff --git a/src/ProxyDialog.ui b/src/ProxyDialog.ui new file mode 100644 index 000000000..2437e604e --- /dev/null +++ b/src/ProxyDialog.ui @@ -0,0 +1,201 @@ + + + ProxyDialog + + + + 0 + 0 + 535 + 231 + + + + Proxy Configuration + + + + + + + + Pro&xy Type + + + comboType + + + + + + + + + + Host Na&me + + + editHost + + + + + + + + + + Port + + + spinPort + + + + + + + 1 + + + 65536 + + + + + + + Authentication Re&quired + + + checkAuthentication + + + + + + + + + + &User Name + + + editUser + + + + + + + + + + Password + + + editPassword + + + + + + + QLineEdit::Password + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + comboType + editHost + spinPort + checkAuthentication + editUser + editPassword + + + + + buttonBox + accepted() + ProxyDialog + accept() + + + 227 + 210 + + + 157 + 230 + + + + + buttonBox + rejected() + ProxyDialog + reject() + + + 295 + 216 + + + 286 + 230 + + + + + comboType + currentIndexChanged(int) + ProxyDialog + proxyTypeChanged(int) + + + 343 + 22 + + + 267 + 115 + + + + + checkAuthentication + toggled(bool) + ProxyDialog + authenticationRequiredChanged(bool) + + + 343 + 114 + + + 267 + 115 + + + + + + proxyTypeChanged(int) + authenticationRequiredChanged(bool) + + diff --git a/src/RemoteNetwork.cpp b/src/RemoteNetwork.cpp new file mode 100644 index 000000000..01aa5eb3e --- /dev/null +++ b/src/RemoteNetwork.cpp @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include + +#include "RemoteNetwork.h" +#include "Settings.h" +#include "version.h" + +RemoteNetwork::RemoteNetwork() : + m_manager(new QNetworkAccessManager) +{ + // Load settings and set up some more stuff while doing so + reloadSettings(); + + // Set up signals + connect(m_manager, &QNetworkAccessManager::sslErrors, this, &RemoteNetwork::gotError); +} + +RemoteNetwork::~RemoteNetwork() +{ + delete m_manager; +} + +void RemoteNetwork::reloadSettings() +{ + // Configure proxy to use + { + QString type = Settings::getValue("proxy", "type").toString(); + + QNetworkProxy proxy; + if(type == "system") + { + // For system settings we have to get the system-wide proxy and use that + + // Get list of proxies for accessing sqlitebrowser.org via HTTPS and use the first one + auto list = QNetworkProxyFactory::systemProxyForQuery(QNetworkProxyQuery(QUrl("https://sqlitebrowser.org/"))); + proxy = list.front(); + } else { + // For any other type we have to set up our own proxy configuration + + // Retrieve the required settings + QString host = Settings::getValue("proxy", "host").toString(); + unsigned short port = static_cast(Settings::getValue("proxy", "port").toUInt()); + bool authentication = Settings::getValue("proxy", "authentication").toBool(); + + if(type == "http") + proxy.setType(QNetworkProxy::HttpProxy); + else if(type == "socks5") + proxy.setType(QNetworkProxy::Socks5Proxy); + else + proxy.setType(QNetworkProxy::NoProxy); + + proxy.setHostName(host); + proxy.setPort(port); + + // Only set authentication details when authentication is required + if(authentication) + { + QString user = Settings::getValue("proxy", "user").toString(); + QString password = Settings::getValue("proxy", "password").toString(); + + proxy.setUser(user); + proxy.setPassword(password); + } + } + + // Start using the new proxy configuration + QNetworkProxy::setApplicationProxy(proxy); + } +} + +void RemoteNetwork::gotReply(QNetworkReply* reply) +{ + // What type of data is this? + RequestType type = static_cast(reply->property("type").toInt()); + + // Handle the reply data + switch(type) + { + case RequestTypeCustom: + break; + } + + // Delete reply later, i.e. after returning from this slot function + reply->deleteLater(); +} + +void RemoteNetwork::fetch(const QUrl& url, RequestType type, std::function when_finished, bool synchronous, bool ignore_errors) +{ + // Build network request + QNetworkRequest request; + request.setUrl(url); + request.setRawHeader("User-Agent", QString("%1 %2").arg(qApp->organizationName(), APP_VERSION).toUtf8()); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); +#elif QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) + request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); +#endif + + // Fetch database and prepare pending reply for future processing + QNetworkReply* reply = m_manager->get(request); + reply->setProperty("type", type); + reply->setProperty("ignore_errors", ignore_errors); + + // Hook up custom handler when there is one and global handler otherwise + if(when_finished) + { + connect(reply, &QNetworkReply::finished, reply, [this, when_finished, reply]() { + if(handleReply(reply)) + when_finished(reply->readAll()); + }); + } else { + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + if(handleReply(reply)) + gotReply(reply); + }); + } + + // When the synchrounous flag is set we wait for the request to finish before continuing + if(synchronous) + { + QEventLoop loop; + connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + loop.exec(); + } +} + +void RemoteNetwork::gotError(QNetworkReply* reply, const QList& errors) +{ + // Are there any errors in here that aren't about self-signed certificates and non-matching hostnames? + bool serious_errors = std::any_of(errors.begin(), errors.end(), [](const QSslError& error) { return error.error() != QSslError::SelfSignedCertificate; }); + + // Just stop the error checking here and accept the reply if there were no 'serious' errors + if(!serious_errors) + { + reply->ignoreSslErrors(errors); + return; + } + + // Build an error message and show it to the user + QString message = tr("Error opening remote file at %1.\n%2").arg(reply->url().toString(), errors.at(0).errorString()); + QMessageBox::warning(nullptr, qApp->applicationName(), message); + + // Delete reply later, i.e. after returning from this slot function + reply->deleteLater(); +} + +bool RemoteNetwork::handleReply(QNetworkReply* reply) +{ + // Check if request was successful + if(reply->error() != QNetworkReply::NoError) + { + // Do not show error message when operation was cancelled on purpose + if(reply->error() != QNetworkReply::OperationCanceledError && !reply->property("ignore_errors").toBool()) + { + QMessageBox::warning(nullptr, qApp->applicationName(), + reply->errorString() + "\n" + reply->readAll()); + } + + reply->deleteLater(); + return false; + } + + return true; +} diff --git a/src/RemoteNetwork.h b/src/RemoteNetwork.h new file mode 100644 index 000000000..28dd654e4 --- /dev/null +++ b/src/RemoteNetwork.h @@ -0,0 +1,44 @@ +#ifndef REMOTENETWORK_H +#define REMOTENETWORK_H + +#include +#include + +class QNetworkAccessManager; +class QNetworkReply; + +class RemoteNetwork : public QObject +{ + Q_OBJECT + +public: + static RemoteNetwork& get() + { + static RemoteNetwork instance; + return instance; + } + + void reloadSettings(); + + enum RequestType + { + RequestTypeCustom, + }; + + void fetch(const QUrl& url, RequestType type, std::function when_finished = {}, bool synchronous = false, bool ignore_errors = false); + +private: + RemoteNetwork(); + ~RemoteNetwork() override; + + void gotReply(QNetworkReply* reply); + void gotError(QNetworkReply* reply, const QList& errors); + + // This function is called for all network replies we get whether they are handled globally or individually. + // It mainly does some error checking and returns true if the actual handler should be called. + bool handleReply(QNetworkReply* reply); + + QNetworkAccessManager* m_manager; +}; + +#endif diff --git a/src/RowCache.h b/src/RowCache.h new file mode 100644 index 000000000..182c9865d --- /dev/null +++ b/src/RowCache.h @@ -0,0 +1,264 @@ +#ifndef ROW_CACHE_H +#define ROW_CACHE_H + +#include +#include +#include +#include + +/** + + cache structure adapted to the existing access patterns in + SqliteTableModel. handles many large segments with gaps in between + well. + + logical structure resembling a std::vector>, but + implementation avoids actually allocating space for the non-empty + optionals, and supports (hopefully) more efficient insertion / + deletion. + + actually, this is not even a "cache" - once set, elements are never + thrown away to make space for new elements. + + TODO introduce maximum segment size? + +**/ +template +class RowCache +{ +public: + using value_type = T; + + /// constructs an empty cache + explicit RowCache (); + + /// \returns number of cached rows + size_t numSet () const; + + /// \returns number of segments + size_t numSegments () const; + + /// \returns 1 if specified row is loaded, 0 otherwise + size_t count (size_t pos) const; + + /// \returns specified row. \throws if not available + const T & at (size_t pos) const; + T & at (size_t pos); + + /// assigns value to specified row; may increase numSet() by one + void set (size_t pos, T && value); + + /// insert new element; increases numSet() by one + void insert (size_t pos, T && value); + + /// delete element; decreases numSet() by one + void erase (size_t pos); + + /// reset to state after construction + void clear (); + + /// given a range of rows (end is exclusive), narrow it in order + /// to remove already-loaded rows from both ends. + void smallestNonAvailableRange (size_t & row_begin, size_t & row_end) const; + +private: + /// a single segment containing contiguous entries + struct Segment + { + size_t pos_begin; + std::vector entries; + + /// returns past-the-end position of this segment + size_t pos_end () const { return pos_begin + entries.size(); } + }; + + /// collection of non-overlapping segments, in order of increasing + /// position + using Segments = std::vector; + Segments segments; + + // ------------------------------------------------------------------------------ + + /// \returns first segment that definitely cannot contain 'pos', + /// because it starts at some later position. + typename Segments::const_iterator getSegmentBeyond (size_t pos) const { + // first segment whose pos_begin > pos (so can't contain pos itself): + return std::upper_bound(segments.begin(), segments.end(), pos, pred); + } + + typename Segments::iterator getSegmentBeyond (size_t pos) { + return std::upper_bound(segments.begin(), segments.end(), pos, pred); + } + + static bool pred (size_t pos, const Segment & s) { return pos < s.pos_begin; } + + // ------------------------------------------------------------------------------ + + /// \returns segment containing 'pos' + typename Segments::const_iterator getSegmentContaining (size_t pos) const + { + auto it = getSegmentBeyond(pos); + + if(it != segments.begin()) { + auto prev_it = it - 1; + if(pos < prev_it->pos_end()) + return prev_it; + } + + return segments.end(); + } + +}; + +template +RowCache::RowCache () +{ +} + +template +size_t RowCache::numSet () const +{ + return std::accumulate(segments.begin(), segments.end(), size_t(0), + [](size_t r, const Segment & s) { return r + s.entries.size(); }); +} + +template +size_t RowCache::numSegments () const +{ + return segments.size(); +} + +template +size_t RowCache::count (size_t pos) const +{ + return getSegmentContaining(pos) != segments.end(); +} + +template +const T & RowCache::at (size_t pos) const +{ + auto it = getSegmentContaining(pos); + + if(it != segments.end()) + return it->entries[pos - it->pos_begin]; + + throw std::out_of_range("no matching segment found"); +} + +template +T & RowCache::at (size_t pos) +{ + return const_cast(static_cast(*this).at(pos)); +} + +template +void RowCache::set (size_t pos, T && value) +{ + auto it = getSegmentBeyond(pos); + + if(it != segments.begin()) + { + auto prev_it = it - 1; + auto d = pos - prev_it->pos_begin; // distance from segment start (>=0) + + if(d < prev_it->entries.size()) + { + // replace value + prev_it->entries[d] = std::move(value); + return; + } + + if(d == prev_it->entries.size()) + { + // extend existing segment + prev_it->entries.insert(prev_it->entries.end(), std::move(value)); + return; + } + } + + // make new segment + segments.insert(it, { pos, { std::move(value) } }); +} + +template +void RowCache::insert (size_t pos, T && value) +{ + auto it = getSegmentBeyond(pos); + + if(it != segments.begin()) + { + auto prev_it = it - 1; + auto d = pos - prev_it->pos_begin; // distance from segment start (>=0) + + if(d <= prev_it->entries.size()) + { + // can extend existing segment + prev_it->entries.insert(prev_it->entries.begin() + d, std::move(value)); + goto push; + } + } + + // make new segment + it = segments.insert(it, { pos, { std::move(value) } }) + 1; + +push: + // push back all later segments + std::for_each(it, segments.end(), [](Segment &s){ s.pos_begin++; }); +} + +template +void RowCache::erase (size_t pos) +{ + auto it = getSegmentBeyond(pos); + + // if previous segment actually contains pos, shorten it + if(it != segments.begin()) + { + auto prev_it = it - 1; + auto d = pos - prev_it->pos_begin; // distance from segment start (>=0) + + if(d < prev_it->entries.size()) + { + prev_it->entries.erase(prev_it->entries.begin() + d); + if(prev_it->entries.empty()) + { + it = segments.erase(prev_it); + } + } + } + + // pull forward all later segments + std::for_each(it, segments.end(), [](Segment &s){ s.pos_begin--; }); +} + +template +void RowCache::clear () +{ + segments.clear(); +} + +template +void RowCache::smallestNonAvailableRange (size_t & row_begin, size_t & row_end) const +{ + if(row_end < row_begin) + throw std::invalid_argument("end must be >= begin"); + + while(row_begin < row_end) { + auto it = getSegmentContaining(row_begin); + if(it == segments.end()) + break; + row_begin = it->pos_end(); + } + + while(row_end > row_begin) { + auto it = getSegmentContaining(row_end - 1); + if(it == segments.end()) + break; + row_end = it->pos_begin; + } + + if(row_end < row_begin) + row_end = row_begin; +} + +#endif // SEGMENTING_CACHE_H diff --git a/src/RowLoader.cpp b/src/RowLoader.cpp new file mode 100644 index 000000000..2fa5c7213 --- /dev/null +++ b/src/RowLoader.cpp @@ -0,0 +1,277 @@ +#include +#include + +#include "RowLoader.h" +#include "sqlite.h" + +namespace { + + QString rtrimChar(const QString& s, QChar c) + { + QString r = s.trimmed(); + while(r.endsWith(c)) + r.chop(1); + return r; + } + +} // anon ns + + +RowLoader::RowLoader (std::function(void)> db_getter_, + std::function statement_logger_, + std::vector & headers_, + std::mutex & cache_mutex_, + Cache & cache_data_ + ) + : db_getter(db_getter_), statement_logger(statement_logger_) + , headers(headers_) + , cache_mutex(cache_mutex_), cache_data(cache_data_) + , query() + , countQuery() + , first_chunk_loaded(false) + , num_tasks(0) + , pDb(nullptr) + , stop_requested(false) + , current_task(nullptr) + , next_task(nullptr) +{ +} + +void RowLoader::setQuery (const QString& new_query, const QString& newCountQuery) +{ + std::lock_guard lk(m); + query = new_query; + first_chunk_loaded = false; + if (newCountQuery.isEmpty()) + // If it is a normal query - hopefully starting with SELECT - just do a COUNT on it and return the results + countQuery = QString("SELECT COUNT(*) FROM (%1);").arg(rtrimChar(query, ';')); + else + countQuery = newCountQuery; +} + +void RowLoader::triggerRowCountDetermination(int token) +{ + std::unique_lock lk(m); + + num_tasks++; + nosync_ensureDbAccess(); + + // do a count query to get the full row count in a fast manner + row_counter = std::async(std::launch::async, [this, token]() { + auto nrows = countRows(); + if(nrows >= 0) + emit rowCountComplete(token, nrows); + + std::lock_guard lk2(m); + nosync_taskDone(); + }); +} + +void RowLoader::nosync_ensureDbAccess () +{ + if(!pDb) + pDb = db_getter(); +} + +std::shared_ptr RowLoader::getDb () const +{ + std::lock_guard lk(m); + return pDb; +} + +int RowLoader::countRows() const +{ + int retval = -1; + + // Use a different approach of determining the row count when a EXPLAIN or a PRAGMA statement is used because a COUNT fails on these queries + if(query.startsWith("EXPLAIN", Qt::CaseInsensitive) || query.startsWith("PRAGMA", Qt::CaseInsensitive)) + { + // So just execute the statement as it is and fetch all results counting the rows + sqlite3_stmt* stmt; + QByteArray utf8Query = query.toUtf8(); + if(sqlite3_prepare_v2(pDb.get(), utf8Query, utf8Query.size(), &stmt, nullptr) == SQLITE_OK) + { + retval = 0; + while(sqlite3_step(stmt) == SQLITE_ROW) + retval++; + sqlite3_finalize(stmt); + return retval; + } + } else { + statement_logger(countQuery); + QByteArray utf8Query = countQuery.toUtf8(); + + sqlite3_stmt* stmt; + if(sqlite3_prepare_v2(pDb.get(), utf8Query, utf8Query.size(), &stmt, nullptr) == SQLITE_OK) + { + if(sqlite3_step(stmt) == SQLITE_ROW) + retval = sqlite3_column_int(stmt, 0); + sqlite3_finalize(stmt); + } else { + qWarning() << "Count query failed: " << countQuery; + } + } + + return retval; +} + +void RowLoader::triggerFetch (int token, size_t row_begin, size_t row_end) +{ + std::unique_lock lk(m); + + if(pDb) { + if(!row_counter.valid() || row_counter.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { + // only if row count is complete, we can safely interrupt SQLite to speed up cancellation + sqlite3_interrupt(pDb.get()); + } + } + + if(current_task) + current_task->cancel = true; + + nosync_ensureDbAccess(); + + // (forget a possibly already existing "next task") + next_task.reset(new Task{ *this, token, row_begin, row_end }); + + lk.unlock(); + cv.notify_all(); +} + +void RowLoader::nosync_taskDone() +{ + if(--num_tasks == 0) { + pDb = nullptr; + } +} + +void RowLoader::cancel () +{ + std::unique_lock lk(m); + + if(pDb) + sqlite3_interrupt(pDb.get()); + + if(current_task) + current_task->cancel = true; + + next_task = nullptr; + cv.notify_all(); +} + +void RowLoader::stop () +{ + cancel(); + std::unique_lock lk(m); + stop_requested = true; + cv.notify_all(); +} + +bool RowLoader::readingData () const +{ + std::unique_lock lk(m); + return pDb != nullptr; +} + +void RowLoader::waitUntilIdle () const +{ + if(row_counter.valid()) + row_counter.wait(); + std::unique_lock lk(m); + cv.wait(lk, [this](){ return stop_requested || (!current_task && !next_task); }); +} + +void RowLoader::run () +{ + for(;;) + { + std::unique_lock lk(m); + current_task = nullptr; + cv.notify_all(); + + cv.wait(lk, [this](){ return stop_requested || next_task; }); + + if(stop_requested) + return; + + current_task = std::move(next_task); + lk.unlock(); + + process(*current_task); + } +} + +void RowLoader::process (Task & t) +{ + QString sLimitQuery; + if(query.startsWith("PRAGMA", Qt::CaseInsensitive) || query.startsWith("EXPLAIN", Qt::CaseInsensitive) || + // With RETURNING keyword DELETE,INSERT,UPDATE can return rows + // https://www.sqlite.org/lang_returning.html + query.startsWith("DELETE", Qt::CaseInsensitive) || query.startsWith("INSERT", Qt::CaseInsensitive) || + query.startsWith("UPDATE", Qt::CaseInsensitive)) + { + sLimitQuery = query; + } else { + // Remove trailing trailing semicolon + QString queryTemp = rtrimChar(query, ';'); + + // If the query ends with a LIMIT statement or contains a compound operator take it as it is, + // if not append our own LIMIT part for lazy population. The compound operator test is a very + // weak check and does not detect whether the keyword is in a string or similar. This means + // that lazy population is disabled for more queries than necessary. We should fix this once + // we have a parser for SELECT statements but until then it is better to disable lazy population + // for more statements than required instead of failing to run some statements entirely. + + if(queryTemp.contains(QRegularExpression("LIMIT\\s+.+\\s*((,|\\b(OFFSET)\\b)\\s*.+\\s*)?$", QRegularExpression::CaseInsensitiveOption)) || + queryTemp.contains(QRegularExpression("\\s(UNION)|(INTERSECT)|(EXCEPT)\\s", QRegularExpression::CaseInsensitiveOption))) + sLimitQuery = queryTemp; + else + sLimitQuery = queryTemp + QString(" LIMIT %1 OFFSET %2;").arg(t.row_end-t.row_begin).arg(t.row_begin); + } + statement_logger(sLimitQuery); + + QByteArray utf8Query = sLimitQuery.toUtf8(); + sqlite3_stmt *stmt; + auto row = t.row_begin; + if(sqlite3_prepare_v2(pDb.get(), utf8Query, utf8Query.size(), &stmt, nullptr) == SQLITE_OK) + { + while(!t.cancel && sqlite3_step(stmt) == SQLITE_ROW) + { + size_t num_columns = static_cast(sqlite3_data_count(stmt)); + + // Construct a new row object with the right number of columns + Cache::value_type rowdata(num_columns); + for(size_t i=0;i(i)) != SQLITE_NULL) + { + int bytes = sqlite3_column_bytes(stmt, static_cast(i)); + if(bytes) + rowdata[i] = QByteArray(static_cast(sqlite3_column_blob(stmt, static_cast(i))), bytes); + else + rowdata[i] = ""; + } + } + std::lock_guard lk(cache_mutex); + cache_data.set(row++, std::move(rowdata)); + } + + sqlite3_finalize(stmt); + + // Query the total row count if and only if: + // - this is the first batch of data we load for this query + // - we got exactly the number of rows back we queried (which indicates there might be more rows) + // If there is no need to query the row count this means the number of rows we just got is the total row count. + if(!first_chunk_loaded) + { + first_chunk_loaded = true; + if(row == t.row_end) + triggerRowCountDetermination(t.token); + else + emit rowCountComplete(t.token, static_cast(row-t.row_begin)); + } + } + + emit fetched(t.token, t.row_begin, row); +} diff --git a/src/RowLoader.h b/src/RowLoader.h new file mode 100644 index 000000000..b3224bcf1 --- /dev/null +++ b/src/RowLoader.h @@ -0,0 +1,124 @@ +#ifndef ROW_LOADER_H +#define ROW_LOADER_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "RowCache.h" + +struct sqlite3; + +class RowLoader : public QThread +{ + Q_OBJECT + + void run() override; + +public: + using Cache = RowCache>; + + /// set up worker thread to handle row loading + explicit RowLoader ( + std::function(void)> db_getter, + std::function statement_logger, + std::vector & headers, + std::mutex & cache_mutex, + Cache & cache_data + ); + + void setQuery (const QString& new_query, const QString& newCountQuery = QString()); + + void triggerRowCountDetermination (int token); + + /// trigger asynchronous reading of specified row range, + /// cancelling previous tasks; 'row_end' is exclusive; \param + /// token is eventually returned through the 'fetched' + /// signal. depending on how and when tasks are cancelled, not + /// every triggerFetch() will result in a 'fetched' signal, or the + /// 'fetched' signal may be for a narrower row range. + void triggerFetch (int token, size_t row_begin, size_t row_end); + + /// cancel everything + void cancel (); + + /// cancel everything and terminate worker thread + void stop (); + + /// currently reading any data, or anything in "queue"? + bool readingData () const; + + /// wait until not reading any data + void waitUntilIdle () const; + + /// get current database - note that the worker thread might be + /// working on it, too... \returns current db, or nullptr. + std::shared_ptr getDb () const; + +signals: + void fetched(int token, size_t row_begin, size_t row_end); + void rowCountComplete(int token, int num_rows); + +private: + const std::function()> db_getter; + const std::function statement_logger; + std::vector & headers; + std::mutex & cache_mutex; + Cache & cache_data; + + mutable std::mutex m; + mutable std::condition_variable cv; + + QString query; + QString countQuery; + + mutable std::future row_counter; + + bool first_chunk_loaded; + + size_t num_tasks; + std::shared_ptr pDb; //< exclusive access while held... + + bool stop_requested; + + struct Task + { + RowLoader & row_loader; + int token; + size_t row_begin; + size_t row_end; //< exclusive + std::atomic cancel; + + Task(RowLoader & row_loader_, int t, size_t a, size_t b) + : row_loader(row_loader_), token(t), row_begin(a), row_end(b), cancel(false) + { + row_loader.num_tasks++; + } + + ~Task() + { + // (... mutex being held ...) + row_loader.nosync_taskDone(); + } + }; + + std::unique_ptr current_task; + std::unique_ptr next_task; + + int countRows () const; + + void process (Task &); + + void nosync_ensureDbAccess (); + void nosync_taskDone (); + +}; + +#endif // ROW_LOADER_H diff --git a/src/RunSql.cpp b/src/RunSql.cpp new file mode 100644 index 000000000..537c5e202 --- /dev/null +++ b/src/RunSql.cpp @@ -0,0 +1,336 @@ +#include "RunSql.h" +#include "sqlite.h" +#include "sqlitedb.h" +#include "Data.h" + +#include +#include +#include +#include + +RunSql::RunSql(DBBrowserDB& _db, QString query, int execute_from_position, int _execute_to_position, bool _interrupt_after_statements) : + db(_db), + may_continue_with_execution(true), + interrupt_after_statements(_interrupt_after_statements), + execute_current_position(execute_from_position), + execute_to_position(_execute_to_position), + structure_updated(false), + savepoint_created(false), + was_dirty(db.getDirty()), + modified(false) +{ + // Get lock to set up everything + std::unique_lock lk(m); + + // Cancel if there is nothing to execute + if(query.trimmed().isEmpty() || query.trimmed() == ";" || execute_from_position == execute_to_position || + query.mid(execute_from_position, execute_to_position-execute_from_position).trimmed().isEmpty() || + query.mid(execute_from_position, execute_to_position-execute_from_position).trimmed() == ";") + return; + + // All replacements in the query should be made by the same amount of characters, so the positions in the file + // for error indicators and line and column logs are not displaced. + // Whitespace and comments are discarded by SQLite, so it is better to just let it ignore them. + query = query.replace(QRegularExpression("^(\\s*)BEGIN TRANSACTION;", QRegularExpression::CaseInsensitiveOption), "\\1 "); + query = query.replace(QRegularExpression("COMMIT;(\\s*)$", QRegularExpression::CaseInsensitiveOption), " \\1"); + + // Convert query to byte array which we will use from now on, starting from the determined start position and + // until the end of the SQL code. By doing so we go further than the determined end position because in Line + // mode the last statement might go beyond that point. + queries_left_to_execute = query.toUtf8().mid(execute_from_position); +} + +void RunSql::run() +{ + // Execute statement by statement + for(;;) + { + if(!executeNextStatement()) + break; + } + + // Execution finished + + // If the DB structure was changed by some command in this SQL script, send a signal + if(structure_updated) + emit structureUpdated(); +} + +void RunSql::startNextStatement() +{ + std::unique_lock lk(m); + may_continue_with_execution = true; + cv.notify_one(); +} + +void RunSql::stop() +{ + std::unique_lock lk(m); + + stopExecution(); + if(pDb) + sqlite3_interrupt(pDb.get()); + may_continue_with_execution = true; + cv.notify_all(); +} + +bool RunSql::executeNextStatement() +{ + std::unique_lock lk(m); + + // Is there anything left to do? + if(queries_left_to_execute.isEmpty()) + return false; + + // Start execution timer + auto time_start = std::chrono::high_resolution_clock::now(); + + // Prepare next statement + const char* tail = queries_left_to_execute.data(); + int tail_length = queries_left_to_execute.length(); + const char* qbegin = tail; + acquireDbAccess(); + sqlite3_stmt* vm; + int sql3status = sqlite3_prepare_v2(pDb.get(), tail, tail_length, &vm, &tail); + QString executed_query = QString::fromUtf8(qbegin, static_cast(tail - qbegin)).trimmed(); + int tail_length_before = tail_length; + tail_length -= static_cast(tail - qbegin); + int end_of_current_statement_position = execute_current_position + tail_length_before - tail_length; + queries_left_to_execute = QByteArray(tail); // Save remaining statements + lk.unlock(); + + // Measure time up until here. We do that to not include the time spent on opening any message boxes or creating savepoints + // because both are not part of the actual query execution. + auto time_end_prepare = std::chrono::high_resolution_clock::now(); + auto time_for_prepare_in_ms = std::chrono::duration_cast(time_end_prepare - time_start); + + // Execute prepared statement + QString error; + if (sql3status == SQLITE_OK) + { + // What type of query was this? + StatementType query_type = getQueryType(executed_query); + + // Check whether the DB structure will be changed by actually running this statement + if(!structure_updated && (query_type == AlterStatement || + query_type == CreateStatement || + query_type == DropStatement || + query_type == RollbackStatement || + query_type == AttachStatement || + query_type == DetachStatement || + query_type == AnalyzeStatement)) + structure_updated = true; + + // Check whether this is trying to set a pragma or to vacuum the database + if((query_type == PragmaStatement && executed_query.contains('=') && !executed_query.contains("defer_foreign_keys", Qt::CaseInsensitive)) || query_type == VacuumStatement) + { + // We're trying to set a pragma. If the database has been modified it needs to be committed first. We'll need to ask the + // user about that + if(db.getDirty()) + { + // Ask user, then check if we should abort execution or continue with it. We depend on a BlockingQueueConnection here which makes sure to + // block this worker thread until the slot function in the main thread is completed and could tell us about its decision. + emit confirmSaveBeforePragmaOrVacuum(); + // We know user's answer because stopExecution will set execution_to_position to 0 + if(execute_to_position > 0) + { + releaseDbAccess(); + // Commit all changes + db.releaseAllSavepoints(); + acquireDbAccess(); + savepoint_created = false; + } else { + // Abort + emit statementErrored(tr("Execution aborted by user"), execute_current_position, execute_current_position + (query_type == PragmaStatement ? 5 : 6)); + releaseDbAccess(); + return false; + } + } + } else { + // We're not trying to set a pragma or to vacuum the database. In this case make sure a savepoint has been created in order to avoid committing + // all changes to the database immediately. Don't set more than one savepoint. + + if(!savepoint_created && !db.readOnly()) + { + // We have to start a transaction before we create the prepared statement otherwise every executed + // statement will get committed after the prepared statement gets finalized + releaseDbAccess(); + // Allow later undoing of this single execution with a non-unique savepoint. + db.setUndoSavepoint(); + // And set the unique savepoint (if not already set) for the full current transaction. + db.setSavepoint(); + acquireDbAccess(); + savepoint_created = true; + } + } + + // Start measuring time from here again + time_start = std::chrono::high_resolution_clock::now(); + + // Check if this statement returned any data. We skip this check if this is an ALTER TABLE statement which, for some reason, are reported to return one column. + if(query_type != AlterStatement && sqlite3_column_count(vm)) + { + // It did. So it is definitely some SELECT statement or similar and we don't need to actually execute it here + sql3status = SQLITE_ROW; + } else { + // It did not. So it's probably some modifying SQL statement and we want to execute it here. If for some reason + // it turns out to return data after all, we just change the status + sql3status = sqlite3_step(vm); + + // SQLite returns SQLITE_DONE when a valid SELECT statement was executed but returned no results. To run into the branch that updates + // the status message and the table view anyway manipulate the status value here. This is also done for PRAGMA statements as they (sometimes) + // return rows just like SELECT statements, too. + if((query_type == SelectStatement || query_type == PragmaStatement) && sql3status == SQLITE_DONE) + sql3status = SQLITE_ROW; + } + + // Destroy statement + sqlite3_finalize(vm); + + switch(sql3status) + { + case SQLITE_ROW: + { + // If we get here, the SQL statement returns some sort of data. So hand it over to the model for display. Don't set the modified flag + // because statements that display data don't change data as well, except if the statement are one of INSERT/UPDATE/DELETE that could + // return data with the RETURNING keyword. + + releaseDbAccess(); + + lk.lock(); + + // Set the modified flag to true if the statement was one of INSERT/UPDATE/DELETE triggered by a possible RETURNING keyword. + if (query_type == InsertStatement || query_type == UpdateStatement || query_type == DeleteStatement) + modified = true; + + may_continue_with_execution = false; + + auto time_end = std::chrono::high_resolution_clock::now(); + auto time_in_ms = std::chrono::duration_cast(time_end - time_start) + time_for_prepare_in_ms; + emit statementReturnsRows(executed_query, execute_current_position, end_of_current_statement_position, time_in_ms.count()); + + // Make sure the next statement isn't executed until we're told to do so + if(interrupt_after_statements) + cv.wait(lk, [this](){ return may_continue_with_execution; }); + lk.unlock(); + break; + } + case SQLITE_DONE: + case SQLITE_OK: + { + // If we get here, the SQL statement doesn't return data and just executes. Don't run it again because it has already been executed. + // But do set the modified flag because statements that don't return data, often modify the database. + + QString stmtHasChangedDatabase; + if(query_type == InsertStatement || query_type == UpdateStatement || query_type == DeleteStatement) + stmtHasChangedDatabase = tr(", %1 rows affected").arg(sqlite3_changes(pDb.get())); + + releaseDbAccess(); + + lk.lock(); + + // Attach/Detach statements don't modify the original database + if(query_type != StatementType::AttachStatement && query_type != StatementType::DetachStatement) + modified = true; + + may_continue_with_execution = false; + + auto time_end = std::chrono::high_resolution_clock::now(); + auto time_in_ms = std::chrono::duration_cast(time_end - time_start) + time_for_prepare_in_ms; + emit statementExecuted(tr("query executed successfully. Took %1ms%2").arg(time_in_ms.count()).arg(stmtHasChangedDatabase), + execute_current_position, end_of_current_statement_position); + + // Make sure the next statement isn't executed until we're told to do so + if(interrupt_after_statements) + cv.wait(lk, [this](){ return may_continue_with_execution; }); + lk.unlock(); + break; + } + case SQLITE_MISUSE: + break; + default: + error = QString::fromUtf8(sqlite3_errmsg(pDb.get())); + } + } else { + error = QString::fromUtf8(sqlite3_errmsg(pDb.get())); + } + + // Release the database + lk.lock(); + releaseDbAccess(); + + // Release savepoints now if they weren't needed. We need to do this here because there are some rare cases where the next statement might + // be affected by what is only a temporary and unnecessary savepoint. For example in this case: + // ATTACH 'xxx' AS 'db2' + // SELECT * FROM db2.xy; -- Savepoint created here + // DETACH db2; -- Savepoint makes this statement fail + // + // Note that a revert would also work for most cases, but we have to take into account that there are SELECT queries running functions + // which might have side effects. In those cases, it is better to err in the safe side by releasing the savepoint and immediately + // saving that side effect, than preventing the user to use those functions in our application. + // Examples of those queries can be found in the Spatialite extension: + // SELECT InitSpatialMetaData() + // SELECT RenameTable('main','Table1','Table2') + if(!modified && !was_dirty && savepoint_created) + { + db.releaseSavepoint(); + db.releaseUndoSavepoint(); + savepoint_created = false; + } + + if(!error.isEmpty()) + { + emit statementErrored(error, execute_current_position, end_of_current_statement_position); + stopExecution(); + return false; + } + // Update the start position for the next statement and check if we are at + // the end of the part we want to execute. If so, stop the execution now. + execute_current_position = end_of_current_statement_position; + if(execute_current_position >= execute_to_position) + { + stopExecution(); + return false; + } + + return true; +} + +void RunSql::stopExecution() +{ + execute_current_position = 0; + execute_to_position = 0; + may_continue_with_execution = false; + queries_left_to_execute.clear(); +} + +RunSql::StatementType RunSql::getQueryType(const QString& query) +{ + // Helper function for getting the type of a given query + + if(query.startsWith("SELECT", Qt::CaseInsensitive)) return SelectStatement; + if(query.startsWith("ALTER", Qt::CaseInsensitive)) return AlterStatement; + if(query.startsWith("DROP", Qt::CaseInsensitive)) return DropStatement; + if(query.startsWith("ROLLBACK", Qt::CaseInsensitive)) return RollbackStatement; + if(query.startsWith("PRAGMA", Qt::CaseInsensitive)) return PragmaStatement; + if(query.startsWith("VACUUM", Qt::CaseInsensitive)) return VacuumStatement; + if(query.startsWith("INSERT", Qt::CaseInsensitive)) return InsertStatement; + if(query.startsWith("UPDATE", Qt::CaseInsensitive)) return UpdateStatement; + if(query.startsWith("DELETE", Qt::CaseInsensitive)) return DeleteStatement; + if(query.startsWith("CREATE", Qt::CaseInsensitive)) return CreateStatement; + if(query.startsWith("ATTACH", Qt::CaseInsensitive)) return AttachStatement; + if(query.startsWith("DETACH", Qt::CaseInsensitive)) return DetachStatement; + if(query.startsWith("ANALYZE", Qt::CaseInsensitive)) return AnalyzeStatement; + + return OtherStatement; +} + +void RunSql::acquireDbAccess() +{ + pDb = db.get(tr("executing query"), true); +} + +void RunSql::releaseDbAccess() +{ + pDb = nullptr; +} diff --git a/src/RunSql.h b/src/RunSql.h new file mode 100644 index 000000000..6a9f13c2b --- /dev/null +++ b/src/RunSql.h @@ -0,0 +1,90 @@ +#ifndef RUNSQL_H +#define RUNSQL_H + +#include +#include +#include +#include + +class DBBrowserDB; +struct sqlite3; + +class RunSql : public QThread +{ + Q_OBJECT + + void run() override; + +public: + /** + * @param db Reference to the database connection to execute the statements with + * @param query The query to execute + * @param execute_from_position The index of the first character to execute in the query parameter + * @param execute_to_position The index of the last character to execute in the query parameter (see exact_execute_to_position) + * @param interrupt_after_statements Set to true to stop execution after each statement until startNextStatement() is called. Set to false to execute all statements + * in one go. + */ + RunSql(DBBrowserDB& db, QString query, int execute_from_position, int execute_to_position, bool interrupt_after_statements = false); + ~RunSql() override = default; + + enum StatementType + { + SelectStatement, + AlterStatement, + DropStatement, + RollbackStatement, + PragmaStatement, + VacuumStatement, + InsertStatement, + UpdateStatement, + DeleteStatement, + CreateStatement, + AttachStatement, + DetachStatement, + AnalyzeStatement, + OtherStatement, + }; + + static StatementType getQueryType(const QString& query); + + void startNextStatement(); + + void stop(); + +signals: + void statementErrored(QString message, int from_position, int to_position); + void statementExecuted(QString message, int from_position, int to_position); + void statementReturnsRows(QString query, int from_position, int to_position, qint64 time_in_ms); + void structureUpdated(); + + /** + * This signal must be connected with a Qt::BlockingQueuedConnection in order to work as expected! + */ + void confirmSaveBeforePragmaOrVacuum(); + +private: + DBBrowserDB& db; + std::shared_ptr pDb; + + mutable std::mutex m; + mutable std::condition_variable cv; + bool may_continue_with_execution; + + bool interrupt_after_statements; + + QByteArray queries_left_to_execute; + int execute_current_position; + int execute_to_position; + bool structure_updated; + bool savepoint_created; + bool was_dirty; + bool modified; + + void stopExecution(); + bool executeNextStatement(); + + void acquireDbAccess(); + void releaseDbAccess(); +}; + +#endif diff --git a/src/SelectItemsPopup.cpp b/src/SelectItemsPopup.cpp new file mode 100644 index 000000000..6d054f11e --- /dev/null +++ b/src/SelectItemsPopup.cpp @@ -0,0 +1,136 @@ +#include "SelectItemsPopup.h" +#include "ui_SelectItemsPopup.h" + +#include + +SelectItemsPopup::SelectItemsPopup(const std::vector& available, const std::vector& selected, QWidget* parent) : + QDialog(parent), + ui(new Ui::SelectItemsPopup) +{ + ui->setupUi(this); + setWindowFlags(Qt::Popup); + + // Load initial items + for(const auto& s : available) + { + if(std::find(selected.begin(), selected.end(), s) == selected.end()) + new QListWidgetItem(QString::fromStdString(s), ui->listAvailable); + } + for(const auto& s : selected) + new QListWidgetItem(QString::fromStdString(s), ui->listSelected); +} + +SelectItemsPopup::~SelectItemsPopup() +{ + delete ui; +} + +std::vector SelectItemsPopup::selectedItems() const +{ + std::vector result; + for(int i=0;ilistSelected->count();i++) + result.push_back(ui->listSelected->item(i)->text().toStdString()); + return result; +} + +void SelectItemsPopup::selectItem(const QModelIndex& idx) +{ + // Get currently selected iitem if none was provided + QListWidgetItem* item; + if(idx.isValid()) + item = ui->listAvailable->item(idx.row()); + else + item = ui->listAvailable->currentItem(); + + if(!item) + return; + + // Add it to the selected items list + new QListWidgetItem(item->text(), ui->listSelected); + + // Remove it from available items list + delete item; +} + +void SelectItemsPopup::unselectItem(const QModelIndex& idx) +{ + // Get currently selected iitem if none was provided + QListWidgetItem* item; + if(idx.isValid()) + item = ui->listSelected->item(idx.row()); + else + item = ui->listSelected->currentItem(); + + if(!item) + return; + + // Add it to the available items list + new QListWidgetItem(item->text(), ui->listAvailable); + + // Remove it from selected items list + delete item; +} + +void SelectItemsPopup::resizeEvent(QResizeEvent*) +{ + // We modify the shape of the dialog to add an arrow shaped edge. See the ascii art image below for details. The edges + // are numbered, their order is the same as in the polygon definition. + + /* + /3\ + / \ + 1---2 4--------5 + | | + | | + 7------------------6 + */ + + const int arrow_height = ui->spacer->geometry().height(); + const int arrow_width = arrow_height * 3; + const int arrow_position_div = 5; + + QPolygon poly; + poly << QPoint(rect().x(), rect().y() + arrow_height) + << QPoint(rect().x() + rect().width() / arrow_position_div - arrow_width / 2, rect().y() + arrow_height) + << QPoint(rect().x() + rect().width() / arrow_position_div, rect().y()) + << QPoint(rect().x() + rect().width() / arrow_position_div + arrow_width / 2, rect().y() + arrow_height) + << QPoint(rect().x() + rect().width(), rect().y() + arrow_height) + << QPoint(rect().x() + rect().width(), rect().y() + rect().height()) + << QPoint(rect().x(), rect().y() + rect().height()); + setMask(QRegion(poly)); +} + +void SelectItemsPopup::buttonBoxClicked(QAbstractButton* button) +{ + if(button == ui->buttonBox->button(QDialogButtonBox::Apply)) + accept(); +} + +void SelectItemsPopup::moveItemUp() +{ + moveCurrentItem(false); +} + +void SelectItemsPopup::moveItemDown() +{ + moveCurrentItem(true); +} + +void SelectItemsPopup::moveCurrentItem(bool down) +{ + // Get current row number and calculate row number after the movement. Check the values + int currentRow = ui->listSelected->currentRow(); + if(currentRow == -1) + return; + int newRow = currentRow + (down ? 1 : -1); + if(newRow < 0) + return; + if(newRow >= ui->listSelected->count()) + return; + + // Swap items + ui->listSelected->insertItem(newRow, ui->listSelected->takeItem(currentRow)); + + // Select old item at new position + ui->listSelected->setCurrentRow(newRow); +} diff --git a/src/SelectItemsPopup.h b/src/SelectItemsPopup.h new file mode 100644 index 000000000..f4436e8dc --- /dev/null +++ b/src/SelectItemsPopup.h @@ -0,0 +1,44 @@ +#ifndef SELECTITEMS_H +#define SELECTITEMS_H + +#include +#include + +#include +#include + +class QAbstractButton; + +namespace Ui { +class SelectItemsPopup; +} + +class SelectItemsPopup : public QDialog +{ + Q_OBJECT + +public: + explicit SelectItemsPopup(const std::vector& available, const std::vector& selected = {}, QWidget* parent = nullptr); + ~SelectItemsPopup() override; + + std::vector selectedItems() const; + +private slots: + void buttonBoxClicked(QAbstractButton* button); + + void selectItem(const QModelIndex& idx = QModelIndex()); + void unselectItem(const QModelIndex& idx = QModelIndex()); + + void moveItemUp(); + void moveItemDown(); + +protected: + void resizeEvent(QResizeEvent* ev) override; + +private: + Ui::SelectItemsPopup* ui; + + void moveCurrentItem(bool down); +}; + +#endif diff --git a/src/SelectItemsPopup.ui b/src/SelectItemsPopup.ui new file mode 100644 index 000000000..89b0d4eff --- /dev/null +++ b/src/SelectItemsPopup.ui @@ -0,0 +1,331 @@ + + + SelectItemsPopup + + + + 0 + 0 + 537 + 290 + + + + + + + Qt::Vertical + + + + 0 + 15 + + + + + + + + + + + + A&vailable + + + listAvailable + + + + + + + QAbstractItemView::NoEditTriggers + + + false + + + true + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::RightArrow + + + + + + + Qt::LeftArrow + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Sele&cted + + + listSelected + + + + + + + QAbstractItemView::NoEditTriggers + + + false + + + QAbstractItemView::InternalMove + + + true + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::UpArrow + + + + + + + Qt::DownArrow + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel + + + + + + + listAvailable + listSelected + buttonSelect + buttonUnselect + + + + + buttonSelect + clicked() + SelectItemsPopup + selectItem() + + + 263 + 115 + + + 2 + 203 + + + + + buttonUnselect + clicked() + SelectItemsPopup + unselectItem() + + + 257 + 159 + + + 515 + 186 + + + + + listAvailable + doubleClicked(QModelIndex) + SelectItemsPopup + selectItem(QModelIndex) + + + 124 + 45 + + + 115 + 0 + + + + + listSelected + doubleClicked(QModelIndex) + SelectItemsPopup + unselectItem(QModelIndex) + + + 377 + 96 + + + 383 + 4 + + + + + buttonBox + rejected() + SelectItemsPopup + reject() + + + 262 + 258 + + + 262 + 140 + + + + + buttonBox + clicked(QAbstractButton*) + SelectItemsPopup + buttonBoxClicked(QAbstractButton*) + + + 262 + 258 + + + 262 + 140 + + + + + buttonDown + clicked() + SelectItemsPopup + moveItemDown() + + + 513 + 153 + + + 268 + 144 + + + + + buttonUp + clicked() + SelectItemsPopup + moveItemUp() + + + 513 + 124 + + + 268 + 144 + + + + + + selectItem(QModelIndex) + unselectItem(QModelIndex) + selectItem() + unselectItem() + buttonBoxClicked(QAbstractButton*) + moveItemUp() + moveItemDown() + + diff --git a/src/Settings.cpp b/src/Settings.cpp new file mode 100644 index 000000000..6fe1b5d7f --- /dev/null +++ b/src/Settings.cpp @@ -0,0 +1,665 @@ +#include "Settings.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QString Settings::userSettingsFile; +QSettings* Settings::settings; +std::unordered_map Settings::m_hCache; +int Settings::m_defaultFontSize; + +static bool ends_with(const std::string& str, const std::string& with) +{ + return str.rfind(with) == str.size() - with.size(); +} + +void Settings::setUserSettingsFile(const QString& userSettingsFileArg) +{ + userSettingsFile = userSettingsFileArg; +} + +bool Settings::isVaildSettingsFile(const QString& userSettingsFile) +{ + /* + Variable that stores whether or not the settings file requested by the user is a normal settings file + If the file does not exist and is newly created, the if statement below is not executed, so the default value is set to true + */ + + bool isNormalUserSettingsFile = true; + + // Code that verifies that the settings file requested by the user is a normal settings file + if(userSettingsFile != nullptr) + { + QFile *file = new QFile; + file->setFileName(userSettingsFile); + + if(file->open(QIODevice::ReadOnly | QIODevice::Text)) + { + if(file->exists() && + QString::compare(QString("[%General]\n"), file->readLine(), Qt::CaseInsensitive) != 0) + isNormalUserSettingsFile = false; + } + + file->close(); + } + + return isNormalUserSettingsFile; +} + +void Settings::setSettingsObject() +{ + // If an object has already been created, it is terminated to reduce overhead + if(settings) + return; + + const bool isNormalUserSettingsFile = isVaildSettingsFile(userSettingsFile); + + if(userSettingsFile == nullptr) + { + settings = new QSettings(QCoreApplication::organizationName(), QCoreApplication::organizationName()); + } else { + if(isNormalUserSettingsFile) + { + settings = new QSettings(userSettingsFile, QSettings::IniFormat); + + // Code to verify that the user does not have access to the requested settings file + if(settings->status() == QSettings::AccessError) { + qWarning() << qPrintable("The given settings file can NOT access. Please check the permission for the file."); + qWarning() << qPrintable("So, the -S/--settings option is ignored."); + + // Since you do not have permission to the file, delete the existing assignment and assign the standard + delete settings; + settings = new QSettings(QCoreApplication::organizationName(), QCoreApplication::organizationName()); + } + } else { + qWarning() << qPrintable("The given settings file is not a normal settings file. Please check again."); + qWarning() << qPrintable("So, the -S/--settings option is ignored."); + settings = new QSettings(QCoreApplication::organizationName(), QCoreApplication::organizationName()); + } + } +} + +QVariant Settings::getValue(const std::string& group, const std::string& name) +{ + // Have a look in the cache first + auto cacheIndex = m_hCache.find(group + name); + if(cacheIndex != m_hCache.end()) + { + return cacheIndex->second; + } else { + // Nothing found in the cache, so get the value from the settings file or get the default value if there is no value set yet + setSettingsObject(); + QVariant value = settings->value(QString::fromStdString(group + "/" + name), getDefaultValue(group, name)); + + // Store this value in the cache for further usage and return it afterwards + m_hCache.insert({group + name, value}); + return value; + } +} + +void Settings::setValue(const std::string& group, const std::string& name, const QVariant& value, bool save_to_disk) +{ + // Sometime the value has to be saved for the current session only but get discarded when the application exits. + // In order to achieve this this flag can be set which disables the save to disk mechanism and only leaves the save to cache part active. + if(save_to_disk) + { + setSettingsObject(); + // Set the group and save the given value + settings->beginGroup(QString::fromStdString(group)); + settings->setValue(QString::fromStdString(name), value); + settings->endGroup(); + } + + // Also change it in the cache + m_hCache[group + name] = value; +} + +QVariant Settings::getDefaultValue(const std::string& group, const std::string& name) +{ + // db/defaultencoding? + if(group == "db" && name == "defaultencoding") + return "UTF-8"; + + // db/savedefaultlocation? + if(group == "db" && name == "savedefaultlocation") + return 2; + + // db/defaultlocation? + if(group == "db" && name == "defaultlocation") + return QDir::homePath(); + + // db/lastlocation? + if(group == "db" && name == "lastlocation") + return getValue("db", "defaultlocation"); + + // db/hideschemalinebreaks? + if(group == "db" && name == "hideschemalinebreaks") + return true; + + // db/foreignkeys? + if(group == "db" && name == "foreignkeys") + return true; + + // db/prefetchsize? + if(group == "db" && name == "prefetchsize") + return 50000U; + + // db/defaultsqltext? + if(group == "db" && name == "defaultsqltext") + return QString(); + + // db/fontsize? + if(group == "db" && name == "fontsize") + return 10; + + // db/watcher? + if(group == "db" && name == "watcher") + return false; + + // exportcsv/firstrowheader? + if(group == "exportcsv" && name == "firstrowheader") + return true; + + // exportcsv/separator? + if(group == "exportcsv" && name == "separator") + return ','; + + // exportcsv/quotecharacter? + if(group == "exportcsv" && name == "quotecharacter") + return '"'; + + // importcsv group? + if(group == "importcsv") + { + if(name == "firstrowheader") + return false; + if(name == "trimfields") + return true; + if(name == "separatetables") + return false; + if(name == "separator") + return ','; + if(name == "quotecharacter") + return '"'; + if(name == "encoding") + return "UTF-8"; + if(name == "localconventions") + return false; + } + + // exportsql group? + if(group == "exportsql") + { + if(name == "insertcolnames" || name == "insertmultiple" || name == "keeporiginal") + return false; + if(name == "oldschema") + return 0; + } + + // newline character + if (group == "exportcsv" && name == "newlinecharacters") +#ifdef Q_OS_WIN + return "\r\n"; +#else + return "\n"; +#endif + + // exportjson/prettyprint? + if(group == "exportjson" && name == "prettyprint") + return true; + + // MainWindow/geometry? + if(group == "MainWindow" && name == "geometry") + return QString(); + + // MainWindow/windowState? + if(group == "MainWindow" && name == "windowState") + return QString(); + + // MainWindow/openTabs? + if(group == "MainWindow" && name == "openTabs") + return QString(); + + // SQLLogDock/Log? + if(group == "SQLLogDock" && name == "Log") + return "Application"; + + // General/recentFileList? + if(group == "General" && name == "recentFileList") + return QStringList(); + + // General/maxRecentFiles? + if(group == "General" && name == "maxRecentFiles") + return 5; + + // General/language? + if(group == "General" && name == "language") + return QLocale::system().name(); + + // General/appStyle + if(group == "General" && name == "appStyle") + return static_cast(FollowDesktopStyle); + + // General/toolbarStyle + if(group == "General" && name == "toolbarStyle") + return static_cast(Qt::ToolButtonTextBesideIcon); + + // General/toolbarStyleStructure + if(group == "General" && name == "toolbarStyleStructure") + return static_cast(Qt::ToolButtonTextBesideIcon); + + // General/toolbarStyleBrowse + if(group == "General" && name == "toolbarStyleBrowse") + return static_cast(Qt::ToolButtonIconOnly); + + // General/toolbarStyleSql + if(group == "General" && name == "toolbarStyleSql") + return static_cast(Qt::ToolButtonIconOnly); + + // General/toolbarStyleEditCell + if(group == "General" && name == "toolbarStyleEditCell") + return static_cast(Qt::ToolButtonIconOnly); + + if(group == "General" && name == "DBFileExtensions") + return QObject::tr("SQLite database files (*.db *.sqlite *.sqlite3 *.db3)"); + + // General/fontsize + if(group == "General" && name == "fontsize") + return m_defaultFontSize; + + // General/promptsqltabsinnewproject + if(group == "General" && name == "promptsqltabsinnewproject") + return true; + + // checkversion group? + if(group == "checkversion") + { + if(name == "enabled") + return true; + if(name == "ignmajor") + return 999; + if(name == "ignminor" || name == "ignpatch") + return 0; + } + + // Data Browser/NULL Fields + if(group == "databrowser") + { + if(name == "font") { + QFont font("Monospace"); + font.setStyleHint(QFont::TypeWriter); + return QFontInfo(font).family(); + } + if(name == "fontsize") + return 10; + if(name == "symbol_limit") + return 5000; + if (name == "rows_limit") + return 10'000'000; + if(name == "complete_threshold") + return 1000; + if(name == "image_preview") + return false; + if(name == "cell_word_wrap") + return true; + if(name == "indent_compact") + return false; + if (name == "sort_keys") + return true; + if(name == "auto_switch_mode") + return true; + if(name == "editor_word_wrap") + return true; + if(name == "null_text") + return "NULL"; + if(name == "blob_text") + return "BLOB"; + if(name == "filter_escape") + return "\\"; + if(name == "filter_delay") + return 200; + if(ends_with(name, "colour")) + return getDefaultColorValue(group, name, FollowDesktopStyle); + } + + // syntaxhighlighter? + if(group == "syntaxhighlighter") + { + // Bold? Only tables, functions and keywords are bold by default + if(ends_with(name, "bold")) + return name == "keyword_bold" || name == "table_bold" || name == "function_bold"; + + // Italic? Nothing by default + if(ends_with(name, "italic")) + return false; + + // Underline? Nothing by default + if(ends_with(name, "underline")) + return false; + + // Colour? + if(ends_with(name, "colour")) + return getDefaultColorValue(group, name, FollowDesktopStyle); + } + + // editor/font? + if(group == "editor" && name == "font") + { + QFont font("Monospace"); + font.setStyleHint(QFont::TypeWriter); + return QFontInfo(font).family(); + } + + // editor/fontsize or log/fontsize? + if((group == "editor" || group == "log") && name == "fontsize") +#ifdef Q_OS_MAC + // Use 12 pt size as the default on macOS + return 12; +#else + return 9; +#endif + + if(group == "editor") + { + if(name == "tabsize") + return 4; + if(name == "indentation_use_tabs") + return true; + } + + // editor/wrap_lines + if(group == "editor" && name == "wrap_lines") + return 0; // QsciScintilla::WrapNone + + // editor/identifier_quotes + if(group == "editor" && name == "identifier_quotes") + return 0; // sqlb::DoubleQuotes + + // editor/auto_completion? + if(group == "editor" && name == "auto_completion") + return true; + + // editor/upper_keywords? + if(group == "editor" && name == "upper_keywords") + return true; + + // editor/error_indicators? + if(group == "editor" && name == "error_indicators") + return true; + + // editor/horizontal_tiling? + if(group == "editor" && name == "horizontal_tiling") + return false; + + // editor/splitter1_sizes? + if(group == "editor" && name == "splitter1_sizes") + return QVariant(); + + // editor/splitter2_sizes? + if(group == "editor" && name == "splitter2_sizes") + return QVariant(); + + // editor/close_button_on_tabs? + if(group == "editor" && name == "close_button_on_tabs") + return true; + + // extensions/list? + if(group == "extensions" && name == "list") + return QStringList(); + + // extensions/disableregex? + if(group == "extension" && name == "disableregex") + return false; + + // extensions/enable_load_extension? + if(group == "extension" && name == "enable_load_extension") + return false; + + // PlotDock/lineType or pointShape? + if(group == "PlotDock") + { + // QCPGraph::lsLine + if(name == "lineType") + return 1; + + // QCPScatterStyle::ssDisk + if(name == "pointShape") + return 4; + } + + + // SchemaDock Drag & drop settings + if(group == "SchemaDock") + { + if(name == "dropSelectQuery") + return true; + + if(name == "dropInsert") + return false; + + if(name == "dropQualifiedNames") + return false; + + if(name == "dropEnquotedNames") + return true; + } + + // Proxy settings + if(group == "proxy") + { + // Use system settings by default + if(name == "type") + return "system"; + } + + // Unknown combination of group and name? Return an invalid QVariant! + return QVariant(); +} + +QColor Settings::getDefaultColorValue(const std::string& group, const std::string& name, AppStyle style) +{ + // Data Browser/NULL & Binary Fields + if(group == "databrowser") + { + // The switch on style can be removed if the following issue is fixed: + // https://github.com/ColinDuquesnoy/QDarkStyleSheet/issues/171 + switch (style) { + case FollowDesktopStyle : + if(name == "null_fg_colour") + return QColor(Qt::lightGray).name(); + if(name == "null_bg_colour") + return QPalette().color(QPalette::Active, QPalette::Base).name(); + if(name == "reg_fg_colour") + return QPalette().color(QPalette::Active, QPalette::Text).name(); + if(name == "reg_bg_colour") + return QPalette().color(QPalette::Active, QPalette::Base).name(); + if(name == "formatted_fg_colour") + return QPalette().color(QPalette::Active, QPalette::Text).name(); + if(name == "formatted_bg_colour") + return QPalette().color(QPalette::Active, QPalette::AlternateBase).name(); + if(name == "bin_fg_colour") + return QColor(Qt::lightGray).name(); + if(name == "bin_bg_colour") + return QPalette().color(QPalette::Active, QPalette::Base).name(); + break; + case DarkStyle : + if(name == "null_fg_colour") + return QColor(0x78, 0x78, 0x78); + if(name == "null_bg_colour") + return QColor(0x19, 0x23, 0x2D); + if(name == "reg_fg_colour") + return QColor(0xF0, 0xF0, 0xF0); + if(name == "reg_bg_colour") + return QColor(0x19, 0x23, 0x2D); + if(name == "formatted_fg_colour") + return QColor(0xF0, 0xF0, 0xF0); + if(name == "formatted_bg_colour") + return QColor(0x19, 0x23, 0x2D); + if(name == "bin_fg_colour") + return QColor(0x78, 0x78, 0x78); + if(name == "bin_bg_colour") + return QColor(0x19, 0x23, 0x2D); + break; + case LightStyle : + if(name == "null_fg_colour" || name == "bin_fg_colour") + return QColor(0xA5, 0xA9, 0xAC); + if(name == "null_bg_colour" || name == "bin_bg_colour") + return QColor(0xFA, 0xFA, 0xFA); + if(name == "reg_fg_colour") + return QColor(0x00, 0x00, 0x00); + if(name == "reg_bg_colour") + return QColor(0xFA, 0xFA, 0xFA); + if(name == "formatted_fg_colour") + return QColor(0x00, 0x00, 0x00); + if(name == "formatted_bg_colour") + return QColor(0xFA, 0xFA, 0xFA); + break; + } + } + + // syntaxhighlighter? + if(group == "syntaxhighlighter") + { + // Colour? + if(ends_with(name, "colour")) + { + QColor backgroundColour; + QColor foregroundColour; + + switch (style) { + case FollowDesktopStyle : + backgroundColour = QPalette().color(QPalette::Active, QPalette::Base); + foregroundColour = QPalette().color(QPalette::Active, QPalette::Text); + break; + case DarkStyle : + foregroundColour = QColor(0xF0, 0xF0, 0xF0); + backgroundColour = QColor(0x19, 0x23, 0x2D); + break; + case LightStyle : + foregroundColour = QColor(0x00, 0x00, 0x00); + backgroundColour = QColor(0xFA, 0xFA, 0xFA); + break; + } + if(name == "foreground_colour") + return foregroundColour; + else if(name == "background_colour") + return backgroundColour; + else if(name == "selected_fg_colour") + return QPalette().color(QPalette::Active, QPalette::HighlightedText); + else if(name == "selected_bg_colour") + return QPalette().color(QPalette::Active, QPalette::Highlight); + + // Detect and provide sensible defaults for dark themes + if (backgroundColour.value() < foregroundColour.value()) { + if(name == "keyword_colour") + return QColor(82, 148, 226); + else if(name == "function_colour") + return QColor(Qt::yellow); + else if(name == "table_colour") + return QColor(Qt::cyan); + else if(name == "comment_colour") + return QColor(Qt::green); + else if(name == "identifier_colour") + return QColor(221, 160, 221); + else if(name == "string_colour") + return QColor(Qt::lightGray); + else if(name == "currentline_colour") + return backgroundColour.lighter(150); + else if(name == "highlight_colour") + return QColor(79, 148, 205); + } else { + if(name == "keyword_colour") + return QColor(Qt::darkBlue); + else if(name == "function_colour") + return QColor(Qt::blue); + else if(name == "table_colour") + return QColor(Qt::darkCyan); + else if(name == "comment_colour") + return QColor(Qt::darkGreen); + else if(name == "identifier_colour") + return QColor(Qt::darkMagenta); + else if(name == "string_colour") + return QColor(Qt::red); + else if(name == "currentline_colour") + return QColor(236, 236, 245); + else if(name == "highlight_colour") + return QColor(Qt::cyan); + } + } + } + + // Unknown combination of group and name? Return an invalid QColor! + return QColor(); +} + +void Settings::clearValue(const std::string& group, const std::string& name) +{ + setSettingsObject(); + settings->beginGroup(QString::fromStdString(group)); + settings->remove(QString::fromStdString(name)); + settings->endGroup(); + m_hCache.clear(); +} + +void Settings::restoreDefaults () +{ + setSettingsObject(); + settings->clear(); + m_hCache.clear(); +} + +void Settings::exportSettings(const QString& fileName) +{ + QSettings exportSettings(fileName, QSettings::IniFormat); + + const QStringList groups = settings->childGroups(); + for(const QString& currentGroup : groups) + { + settings->beginGroup(currentGroup); + const QStringList keys = settings->childKeys(); + for(const QString& currentKey : keys) + { + exportSettings.beginGroup(currentGroup); + exportSettings.setValue(currentKey, getValue((currentGroup.toStdString()), (currentKey.toStdString()))); + exportSettings.endGroup(); + } + settings->endGroup(); + } +} + +bool Settings::importSettings(const QString& fileName) +{ + if(!isVaildSettingsFile(fileName)) + return false; + + QSettings importSettings(fileName, QSettings::IniFormat); + + const QStringList groups = importSettings.childGroups(); + for(const QString& currentGroup : groups) + { + importSettings.beginGroup(currentGroup); + const QStringList keys = importSettings.childKeys(); + for(const QString& currentKey : keys) + { + settings->beginGroup(currentGroup); + settings->setValue(currentKey, importSettings.value(currentKey)); + settings->endGroup(); + } + importSettings.endGroup(); + } + + m_hCache.clear(); + return true; +} + +void Settings::sync() +{ + settings->sync(); +} diff --git a/src/Settings.h b/src/Settings.h new file mode 100644 index 000000000..5fca0a613 --- /dev/null +++ b/src/Settings.h @@ -0,0 +1,59 @@ +#ifndef SETTINGS_H +#define SETTINGS_H + +#include +#include +#include + +class Settings +{ + friend class PreferencesDialog; + +public: + enum AppStyle { + FollowDesktopStyle, + DarkStyle, + LightStyle + }; + + static void setUserSettingsFile(const QString& userSettingsFileArg); + static QVariant getValue(const std::string& group, const std::string& name); + static void setValue(const std::string& group, const std::string& name, const QVariant& value, bool save_to_disk = true); + static void clearValue(const std::string& group, const std::string& name); + static void restoreDefaults(); + + static void rememberDefaultFontSize(int size) { m_defaultFontSize = size; } + static void exportSettings(const QString& fileName); + static bool importSettings(const QString& fileName); + static void sync(); + +private: + Settings() = delete; // class is fully static + + // This works similar to getValue but returns the default value instead of the value set by the user + static QVariant getDefaultValue(const std::string& group, const std::string& name); + + // This works similar to getDefaultValue but returns the default color value based on the passed application style + // instead of the current palette. + static QColor getDefaultColorValue(const std::string& group, const std::string& name, AppStyle style); + + // User settings file path + static QString userSettingsFile; + + // QSettings object + static QSettings* settings; + + // This works verify that the settings file provided by the user is a normal settings file + static bool isVaildSettingsFile(const QString& userSettingsFile); + + // This works initialize QSettings object + static void setSettingsObject(); + + // Cache for storing the settings to avoid repeatedly reading the settings file all the time + static std::unordered_map m_hCache; + + // Default UI font size + static int m_defaultFontSize; +}; + +#endif diff --git a/src/SqlExecutionArea.cpp b/src/SqlExecutionArea.cpp index 1000f7c58..3e3ceafc2 100644 --- a/src/SqlExecutionArea.cpp +++ b/src/SqlExecutionArea.cpp @@ -1,33 +1,67 @@ #include "SqlExecutionArea.h" #include "ui_SqlExecutionArea.h" #include "sqltextedit.h" -#include "ExtendedTableWidget.h" #include "sqlitetablemodel.h" #include "sqlitedb.h" -#include "PreferencesDialog.h" -#include "ExportCsvDialog.h" +#include "Settings.h" +#include "ExportDataDialog.h" +#include "FilterTableHeader.h" -#include #include #include +#include +#include -SqlExecutionArea::SqlExecutionArea(QWidget* parent, DBBrowserDB* _db) : +SqlExecutionArea::SqlExecutionArea(DBBrowserDB& _db, QWidget* parent) : QWidget(parent), db(_db), - ui(new Ui::SqlExecutionArea) + ui(new Ui::SqlExecutionArea), + m_columnsResized(false), + error_state(false), + follow_mode(false) { // Create UI ui->setupUi(this); // Create model - model = new SqliteTableModel(this, db, PreferencesDialog::getSettingsValue("db", "prefetchsize").toInt()); + model = new SqliteTableModel(db, this); ui->tableResult->setModel(model); + connect(model, &SqliteTableModel::finishedFetch, this, &SqlExecutionArea::fetchedData); + connect(ui->tableResult->filterHeader(), &FilterTableHeader::sectionPressed, ui->tableResult, &QTableView::selectColumn); - // Create popup menu for save button - menuPopupSave = new QMenu(this); - menuPopupSave->addAction(ui->actionExportCsv); - menuPopupSave->addAction(ui->actionSaveAsView); - ui->buttonSave->setMenu(menuPopupSave); + ui->findFrame->hide(); + + QShortcut* shortcutHideFind = new QShortcut(QKeySequence("ESC"), ui->findLineEdit); + connect(shortcutHideFind, &QShortcut::activated, this, &SqlExecutionArea::hideFindFrame); + + QShortcut* shortcutFocusEditor = new QShortcut(QKeySequence(tr("Ctrl+PgUp")), this, nullptr, nullptr, Qt::WidgetWithChildrenShortcut); + connect(shortcutFocusEditor, &QShortcut::activated, this, [this]() { + ui->editEditor->setFocus(); + }); + + QShortcut* shortcutFocusResults = new QShortcut(QKeySequence(tr("Ctrl+PgDown")), this, nullptr, nullptr, Qt::WidgetWithChildrenShortcut); + connect(shortcutFocusResults, &QShortcut::activated, this, [this]() { + ui->tableResult->setFocus(); + }); + + connect(ui->findLineEdit, &QLineEdit::textChanged, this, &SqlExecutionArea::findLineEdit_textChanged); + connect(ui->previousToolButton, &QToolButton::clicked, this, &SqlExecutionArea::findPrevious); + connect(ui->nextToolButton, &QToolButton::clicked, this, &SqlExecutionArea::findNext); + connect(ui->findLineEdit, &QLineEdit::returnPressed, this, &SqlExecutionArea::findNext); + connect(ui->hideFindButton, &QToolButton::clicked, this, &SqlExecutionArea::hideFindFrame); + + connect(&fileSystemWatch, &QFileSystemWatcher::fileChanged, this, &SqlExecutionArea::fileChanged); + + // Save to settings when sppliter is moved, but only to memory. + connect(ui->splitter, &QSplitter::splitterMoved, this, [this]() { + Settings::setValue("editor", "splitter1_sizes", ui->splitter->saveState(), /* save_to_disk */ false); + }); + connect(ui->splitter_2, &QSplitter::splitterMoved, this, [this]() { + Settings::setValue("editor", "splitter2_sizes", ui->splitter_2->saveState(), /* save_to_disk */ false); + }); + + // Set collapsible the editErrors panel + ui->splitter_2->setCollapsible(1, true); // Load settings reloadSettings(); @@ -48,13 +82,38 @@ QString SqlExecutionArea::getSelectedSql() const return ui->editEditor->selectedText().trimmed().replace(QChar(0x2029), '\n'); } -void SqlExecutionArea::finishExecution(const QString& result) +void SqlExecutionArea::setSql(const QString& sql) { - ui->editErrors->setText(result); + ui->editEditor->setText(sql); +} + +void SqlExecutionArea::finishExecution(const QString& result, const bool ok) +{ + error_state = !ok; + m_columnsResized = false; + ui->editErrors->setPlainText(result); + // Set reddish background when not ok + if (showErrorIndicators) + { + if (ok) + ui->editErrors->setStyleSheet(""); + else + ui->editErrors->setStyleSheet("QTextEdit {color: white; background-color: rgb(255, 102, 102)}"); + } + +} + +void SqlExecutionArea::fetchedData() +{ + // Don't resize the columns more than once to fit their contents. This is necessary because the finishedFetch signal of the model + // is emitted for each loaded prefetch block and we want to avoid resizes while scrolling down. + if(m_columnsResized) + return; + m_columnsResized = true; // Set column widths according to their contents but make sure they don't exceed a certain size ui->tableResult->resizeColumnsToContents(); - for(int i=0;icolumnCount();i++) + for(int i = 0; i < model->columnCount(); i++) { if(ui->tableResult->columnWidth(i) > 300) ui->tableResult->setColumnWidth(i, 300); @@ -71,61 +130,240 @@ ExtendedTableWidget *SqlExecutionArea::getTableResult() return ui->tableResult; } - -QTextEdit* SqlExecutionArea::getResultView() +QTextEdit* SqlExecutionArea::getStatusEdit() { return ui->editErrors; } -void SqlExecutionArea::enableSaveButton(bool enable) -{ - ui->buttonSave->setEnabled(enable); -} - void SqlExecutionArea::saveAsCsv() { - ExportCsvDialog dialog(db, this, model->query()); + ExportDataDialog dialog(db, ExportDataDialog::ExportFormatCsv, this, model->query()); dialog.exec(); } -void SqlExecutionArea::saveAsView() +void SqlExecutionArea::saveAsJson() { - // Let the user select a name for the new view and make sure it doesn't already exist - QString name; - while(true) - { - name = QInputDialog::getText(this, qApp->applicationName(), tr("Please specify the view name")).trimmed(); - if(name.isEmpty()) - break; - if(!db->getObjectByName(name).getname().isEmpty()) - QMessageBox::warning(this, qApp->applicationName(), tr("There is already an object with that name. Please choose a different name.")); - else - break; - } - if(name.isEmpty()) - return; - - // Create the view - if(db->executeSQL(QString("CREATE VIEW %1 AS %2;").arg(sqlb::escapeIdentifier(name)).arg(model->query()))) - QMessageBox::information(this, qApp->applicationName(), tr("View successfully created.")); - else - QMessageBox::warning(this, qApp->applicationName(), tr("Error creating view: %1").arg(db->lastErrorMessage)); + ExportDataDialog dialog(db, ExportDataDialog::ExportFormatJson, this, model->query()); + dialog.exec(); } void SqlExecutionArea::reloadSettings() { - // Reload editor settings + // Reload editor and table settings ui->editEditor->reloadSettings(); + ui->tableResult->reloadSettings(); // Set font - QFont logfont(PreferencesDialog::getSettingsValue("editor", "font").toString()); + QFont logfont(Settings::getValue("editor", "font").toString()); logfont.setStyleHint(QFont::TypeWriter); - logfont.setPointSize(PreferencesDialog::getSettingsValue("log", "fontsize").toInt()); + logfont.setPointSize(Settings::getValue("log", "fontsize").toInt()); ui->editErrors->setFont(logfont); // Apply horizontal/vertical tiling option - if(PreferencesDialog::getSettingsValue("editor", "horizontal_tiling").toBool()) + if(Settings::getValue("editor", "horizontal_tiling").toBool()) ui->splitter->setOrientation(Qt::Horizontal); else ui->splitter->setOrientation(Qt::Vertical); + + ui->splitter->restoreState(Settings::getValue("editor", "splitter1_sizes").toByteArray()); + ui->splitter_2->restoreState(Settings::getValue("editor", "splitter2_sizes").toByteArray()); + + // Reload model settings + model->reloadSettings(); + + // Check if error indicators are enabled for the not-ok background clue + showErrorIndicators = Settings::getValue("editor", "error_indicators").toBool(); + if (!showErrorIndicators) + ui->editErrors->setStyleSheet(""); + +} + +void SqlExecutionArea::find(QString expr, bool forward) +{ + + bool found = ui->editEditor->findText + (expr, + ui->regexpCheckBox->isChecked(), + ui->caseCheckBox->isChecked(), + ui->wholeWordsCheckBox->isChecked(), + /* wrap */ true, + forward); + + // Set reddish background when not found + if (found || expr.isEmpty()) + ui->findLineEdit->setStyleSheet(""); + else + ui->findLineEdit->setStyleSheet("QLineEdit {color: white; background-color: rgb(255, 102, 102)}"); + +} + +void SqlExecutionArea::findPrevious() +{ + find(ui->findLineEdit->text(), false); +} + +void SqlExecutionArea::findNext() +{ + find(ui->findLineEdit->text(), true); +} + +void SqlExecutionArea::findLineEdit_textChanged(const QString &) +{ + // When the text changes, perform an incremental search from cursor + // position, or from begin of the selection position. + + // For incremental search while typing we need to start from the + // beginning of the current selection, otherwise we'd jump to the + // next occurrence + if (ui->editEditor->hasSelectedText()) { + int lineFrom; + int indexFrom; + int lineTo; + int indexTo; + ui->editEditor->getSelection(&lineFrom, &indexFrom, &lineTo, &indexTo); + ui->editEditor->setCursorPosition(lineFrom, indexFrom); + } + + find(ui->findLineEdit->text(), true); +} + +void SqlExecutionArea::hideFindFrame() +{ + ui->editEditor->setFocus(); + ui->findFrame->hide(); + emit findFrameVisibilityChanged(false); +} + +void SqlExecutionArea::setFindFrameVisibility(bool show) +{ + if (show) { + ui->findFrame->show(); + ui->findLineEdit->setFocus(); + ui->findLineEdit->selectAll(); + emit findFrameVisibilityChanged(true); + } else { + hideFindFrame(); + } +} + +void SqlExecutionArea::openFile(const QString& filename) +{ + // Open file for reading + QFile f(filename); + f.open(QIODevice::ReadOnly); + if(!f.isOpen()) + { + QMessageBox::warning(this, qApp->applicationName(), tr("Couldn't read file \"%1\": %2.").arg(filename, f.errorString())); + return; + } + + // Read in the entire file + ui->editEditor->setText(f.readAll()); + + // No modifications yet + ui->editEditor->setModified(false); + + // Remember file name + sqlFileName = filename; + + // Start watching this file for changes and unwatch the previously watched file, if any + if(!fileSystemWatch.files().empty()) + fileSystemWatch.removePaths(fileSystemWatch.files()); + fileSystemWatch.addPath(filename); +} + +void SqlExecutionArea::saveFile(const QString& filename) +{ + // Unwatch all files now. By unwatching them before the actual saving, we are not notified of our own changes + if(!fileSystemWatch.files().empty()) + fileSystemWatch.removePaths(fileSystemWatch.files()); + + // Open file for writing + QFile f(filename); + f.open(QIODevice::WriteOnly); + if(!f.isOpen()) + { + QMessageBox::warning(this, qApp->applicationName(), tr("Couldn't save file: %1.").arg(f.errorString())); + return; + } + + // Write to the file + if(f.write(getSql().toUtf8()) != -1) + { + // Close file now. If we let the destructor close it, we can get change notifications. + f.close(); + // Set modified to false so we can get control of unsaved changes when closing. + ui->editEditor->setModified(false); + + // Remember file name + sqlFileName = filename; + + // Start watching this file + fileSystemWatch.addPath(filename); + } else { + QMessageBox::warning(this, qApp->applicationName(), tr("Couldn't save file: %1.").arg(f.errorString())); + return; + } +} + +void SqlExecutionArea::fileChanged(const QString& filename) +{ + // Ignore the signal if the file is already removed from the watcher. + if(!fileSystemWatch.files().contains(filename)) + return; + + // When in follow_mode and the file is not modified, reload without prompt. + if(follow_mode && !ui->editEditor->isModified()) { + openFile(filename); + return; + } + + // Stop watching the file while the dialog is open. + fileSystemWatch.removePath(filename); + + // Check if there are unsaved changes in the file + QString changes; + if(ui->editEditor->isModified()) + changes = QString(" ") + tr("Your changes will be lost when reloading it!") + QString(""); + + // Ask user whether to reload the modified file + QMessageBox::StandardButton reply = QMessageBox::question( + this, + qApp->applicationName(), + tr("The file \"%1\" was modified by another program. Do you want to reload it?%2").arg(filename, changes) + + QString("
  • ") + + tr("Answer \"Yes to All\" to reload the file on any external update without further prompting.") + + QString("
  • ") + + tr("Answer \"No to All\" to ignore any external update without further prompting.") + + QString("
") + + tr("Modifying and saving the file will restore prompting."), + QMessageBox::Yes | QMessageBox::No | QMessageBox::YesToAll | QMessageBox::NoToAll); + + switch (reply) { + case QMessageBox::Yes: + case QMessageBox::YesToAll: + // Read in the file. This will restore the watcher. + openFile(filename); + break; + case QMessageBox::No: + // The file does not match the file on the disk anymore. So set the modified flag. + ui->editEditor->setModified(true); + // Start watching the file again for further prompting. + fileSystemWatch.addPath(filename); + break; + case QMessageBox::NoToAll: + // Set the modified flag and the watch is not restored until the file is saved again to disk. + ui->editEditor->setModified(true); + break; + default: + break; + } + follow_mode = reply == QMessageBox::YesToAll; +} + +void SqlExecutionArea::saveState() { + + // Save to disk last stored splitter sizes + Settings::setValue("editor", "splitter1_sizes", Settings::getValue("editor", "splitter1_sizes")); + Settings::setValue("editor", "splitter2_sizes", Settings::getValue("editor", "splitter2_sizes")); } diff --git a/src/SqlExecutionArea.h b/src/SqlExecutionArea.h index f38ed7418..da4f4f8f0 100644 --- a/src/SqlExecutionArea.h +++ b/src/SqlExecutionArea.h @@ -1,16 +1,14 @@ -#ifndef SQLEXECUTIONAREA_H +#ifndef SQLEXECUTIONAREA_H #define SQLEXECUTIONAREA_H -#include "sqltextedit.h" - #include - -#include "ExtendedTableWidget.h" +#include class SqlTextEdit; class SqliteTableModel; class DBBrowserDB; -class QMenu; +class ExtendedTableWidget; + class QTextEdit; namespace Ui { @@ -22,33 +20,59 @@ class SqlExecutionArea : public QWidget Q_OBJECT public: - explicit SqlExecutionArea(QWidget* parent, DBBrowserDB* _db); - ~SqlExecutionArea(); + explicit SqlExecutionArea(DBBrowserDB& _db, QWidget* parent = nullptr); + ~SqlExecutionArea() override; QString getSql() const; QString getSelectedSql() const; + void setSql(const QString& sql); + + void openFile(const QString& filename); + void saveFile(const QString& filename); QString fileName() const { return sqlFileName; } void setFileName(const QString& filename) { sqlFileName = filename; } SqliteTableModel* getModel() { return model; } - QTextEdit* getResultView(); SqlTextEdit* getEditor(); ExtendedTableWidget *getTableResult(); - + QTextEdit* getStatusEdit(); + + bool inErrorState() const { return error_state; } + + // Save window state to settings + static void saveState(); + public slots: - virtual void finishExecution(const QString& result); - virtual void enableSaveButton(bool enable); - virtual void saveAsCsv(); - virtual void saveAsView(); - virtual void reloadSettings(); + void finishExecution(const QString& result, const bool ok); + void saveAsCsv(); + void saveAsJson(); + void reloadSettings(); + void fetchedData(); + void setFindFrameVisibility(bool show); + +private slots: + void findPrevious(); + void findNext(); + void findLineEdit_textChanged(const QString& text); + void hideFindFrame(); + + void fileChanged(const QString& filename); + +signals: + void findFrameVisibilityChanged(bool visible); private: - DBBrowserDB* db; + void find(QString expr, bool forward); + DBBrowserDB& db; SqliteTableModel* model; - QMenu* menuPopupSave; QString sqlFileName; + QFileSystemWatcher fileSystemWatch; Ui::SqlExecutionArea* ui; + bool m_columnsResized; // This is set to true if the columns of the table view were already adjusted to fit their contents + bool showErrorIndicators; + bool error_state; + bool follow_mode; }; #endif diff --git a/src/SqlExecutionArea.ui b/src/SqlExecutionArea.ui index 2ac64ad25..a6df85829 100644 --- a/src/SqlExecutionArea.ui +++ b/src/SqlExecutionArea.ui @@ -6,163 +6,292 @@ 0 0 - 365 + 579 482 Form - + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + Qt::Vertical - - + + false + + + + 0 + - - - QAbstractItemView::NoEditTriggers - - + - - - - - - 16777215 - 80 - - - - - Monospace - 8 - - - - false - - - Results of the last executed statements - - - This field shows the results and status codes of the last executed statements. - - - QFrame::StyledPanel - - - QFrame::Sunken - - - true - - - false - - - true - - - - - - - false - - - - :/icons/save_table:/icons/save_table - - - QToolButton::InstantPopup - - - - + + + + 16777215 + 31 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 1 + + + 1 + + + 1 + + + 1 + + + 3 + + + + + Find previous match [Shift+F3] + + + Find previous match with wrapping + + + + :/icons/up:/icons/up + + + Shift+F3 + + + + + + + Qt::Horizontal + + + + + + + The found pattern must be a whole word + + + Whole Words + + + + + + + Qt::DefaultContextMenu + + + Text pattern to find considering the checks in this frame + + + Find in editor + + + true + + + + + + + The found pattern must match in letter case + + + Case Sensitive + + + + + + + Find next match [Enter, F3] + + + Find next match with wrapping + + + + :/icons/down:/icons/down + + + F3 + + + + + + + Interpret search pattern as a regular expression + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + Regular Expression + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Close Find Bar + + + Close Find Bar + + + + :/icons/close:/icons/close + + + true + + + + + + + + Qt::Vertical + + + false + + + + QAbstractItemView::NoEditTriggers + + + + + + 0 + 120 + + + + + Monospace + 8 + + + + false + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + + + This field shows the results and status codes of the last executed statements. + + + QFrame::StyledPanel + + + QFrame::Sunken + + + true + + + false + + + true + + + Results of the last executed statements + + + - - - Export to &CSV - - - - - Save as &view - - - Save as view - - - - ExtendedTableWidget - QTableWidget -
ExtendedTableWidget.h
-
SqlTextEdit QTextEdit
sqltextedit.h
1
+ + ExtendedTableWidget + QTableWidget +
ExtendedTableWidget.h
+ + foreignKeyClicked(QString,QString,QByteArray) + foreignKeyClicked(sqlb::ObjectIdentifier,QString,QByteArray) + +
+ editEditor + findLineEdit tableResult editErrors - buttonSave + previousToolButton + nextToolButton + caseCheckBox + wholeWordsCheckBox - - - actionExportCsv - triggered() - SqlExecutionArea - saveAsCsv() - - - -1 - -1 - - - 183 - 215 - - - - - actionSaveAsView - triggered() - SqlExecutionArea - saveAsView() - - - -1 - -1 - - - 183 - 215 - - - - + saveAsCsv() + saveAsJson() saveAsView() diff --git a/src/SqlUiLexer.cpp b/src/SqlUiLexer.cpp index 4cf145aff..face12259 100644 --- a/src/SqlUiLexer.cpp +++ b/src/SqlUiLexer.cpp @@ -1,5 +1,54 @@ +#include + #include "SqlUiLexer.h" #include "Qsci/qsciapis.h" +#include "Settings.h" +#include "sqlitedb.h" +#include "sqlite3.h" + +namespace +{ + const int SQLITE_VER_NUMBER_3_35 = 3035000; + + bool enabledMathFunctions() + { + bool enabled = (sqlite3_libversion_number() >= SQLITE_VER_NUMBER_3_35) && + ((sqlite3_compileoption_used("SQLITE_OMIT_COMPILEOPTION_DIAGS") == 1) || + (sqlite3_compileoption_used("SQLITE_ENABLE_MATH_FUNCTIONS") == 1 ) ); + return enabled; + } +} + +const QStringList SqlUiLexer::keywordPatterns = QStringList({ + // Keywords + "ABORT", "ACTION", "ADD", "AFTER", "ALL", + "ALTER", "ALWAYS", "ANALYZE", "AND", "ANY", "AS", "ASC", + "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", + "BY", "CASCADE", "CASE", "CAST", "CHECK", + "COLLATE", "COLUMN", "COMMIT", "CONFLICT", "CONSTRAINT", + "CREATE", "CROSS", "CURRENT", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", + "DATABASE", "DEFAULT", "DEFERRABLE", "DEFERRED", "DELETE", + "DESC", "DETACH", "DISTINCT", "DO", "DROP", "EACH", + "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", + "EXISTS", "EXPLAIN", "FAIL", "FILTER", "FOLLOWING", "FOR", "FOREIGN", + "FROM", "FULL", "GENERATED", "GLOB", "GROUP", "HAVING", + "IF", "IGNORE", "IMMEDIATE", "IN", "INDEX", + "INDEXED", "INITIALLY", "INNER", "INSERT", "INSTEAD", + "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", + "KEY", "LEFT", "LIKE", "LIMIT", "MATCH", + "NATURAL", "NO", "NOT", "NOTHING", "NOTNULL", "NULL", + "OF", "OFFSET", "ON", "OR", "ORDER", + "OUTER", "OVER", "PARTITION", "PLAN", "PRAGMA", "PRECEDING", "PRIMARY", "QUERY", + "RAISE", "RANGE", "RECURSIVE", "REFERENCES", "REGEXP", "REINDEX", "RELEASE", + "RENAME", "REPLACE", "RESTRICT", "RETURNING", "RIGHT", "ROLLBACK", + "ROWID", "ROW", "ROWS", "SAVEPOINT", "SELECT", "SET", "STORED", "STRICT", "TABLE", + "TEMP", "TEMPORARY", "THEN", "TO", "TRANSACTION", + "TRIGGER", "UNBOUNDED", "UNION", "UNIQUE", "UPDATE", "USING", + "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", + "WHERE", "WINDOW", "WITH", "WITHOUT", + // Data types + "INT", "INTEGER", "REAL", "TEXT", "BLOB", "NUMERIC", "CHAR" +}); SqlUiLexer::SqlUiLexer(QObject* parent) : QsciLexerSQL(parent) @@ -7,7 +56,6 @@ SqlUiLexer::SqlUiLexer(QObject* parent) : // Setup auto completion autocompleteApi = new QsciAPIs(this); setupAutoCompletion(); - autocompleteApi->prepare(); // Setup folding setFoldComments(true); @@ -16,144 +64,197 @@ SqlUiLexer::SqlUiLexer(QObject* parent) : void SqlUiLexer::setupAutoCompletion() { - // Set keywords - QStringList keywordPatterns; - keywordPatterns - // Keywords - << "ABORT" << "ACTION" << "ADD" << "AFTER" << "ALL" - << "ALTER" << "ANALYZE" << "AND" << "AS" << "ASC" - << "ATTACH" << "AUTOINCREMENT" << "BEFORE" << "BEGIN" << "BETWEEN" - << "BY" << "CASCADE" << "CASE" << "CAST" << "CHECK" - << "COLLATE" << "COLUMN" << "COMMIT" << "CONFLICT" << "CONSTRAINT" - << "CREATE" << "CROSS" << "CURRENT_DATE" << "CURRENT_TIME" << "CURRENT_TIMESTAMP" - << "DATABASE" << "DEFAULT" << "DEFERRABLE" << "DEFERRED" << "DELETE" - << "DESC" << "DETACH" << "DISTINCT" << "DROP" << "EACH" - << "ELSE" << "END" << "ESCAPE" << "EXCEPT" << "EXCLUSIVE" - << "EXISTS" << "EXPLAIN" << "FAIL" << "FOR" << "FOREIGN" - << "FROM" << "FULL" << "GLOB" << "GROUP" << "HAVING" - << "IF" << "IGNORE" << "IMMEDIATE" << "IN" << "INDEX" - << "INDEXED" << "INITIALLY" << "INNER" << "INSERT" << "INSTEAD" - << "INTERSECT" << "INTO" << "IS" << "ISNULL" << "JOIN" - << "KEY" << "LEFT" << "LIKE" << "LIMIT" << "MATCH" - << "NATURAL" << "NO" << "NOT" << "NOTNULL" << "NULL" - << "OF" << "OFFSET" << "ON" << "OR" << "ORDER" - << "OUTER" << "PLAN" << "PRAGMA" << "PRIMARY" << "QUERY" - << "RAISE" << "RECURSIVE" << "REFERENCES" << "REGEXP" << "REINDEX" << "RELEASE" - << "RENAME" << "REPLACE" << "RESTRICT" << "RIGHT" << "ROLLBACK" - << "ROW" << "SAVEPOINT" << "SELECT" << "SET" << "TABLE" - << "TEMP" << "TEMPORARY" << "THEN" << "TO" << "TRANSACTION" - << "TRIGGER" << "UNION" << "UNIQUE" << "UPDATE" << "USING" - << "VACUUM" << "VALUES" << "VIEW" << "VIRTUAL" << "WHEN" - << "WHERE" << "WITH" << "WITHOUT" - // Data types - << "INT" << "INTEGER" << "REAL" << "TEXT" << "BLOB" << "NUMERIC" << "CHAR"; - foreach(const QString& keyword, keywordPatterns) + bool upperKeywords = Settings::getValue("editor", "upper_keywords").toBool(); + for(const QString& keyword : qAsConst(keywordPatterns)) { - autocompleteApi->add(keyword + "?" + QString::number(ApiCompleterIconIdKeyword)); - autocompleteApi->add(keyword.toLower() + "?" + QString::number(ApiCompleterIconIdKeyword)); + if (upperKeywords) + autocompleteApi->add(keyword + "?" + QString::number(ApiCompleterIconIdKeyword)); + else + autocompleteApi->add(keyword.toLower() + "?" + QString::number(ApiCompleterIconIdKeyword)); } // Functions - QStringList functionPatterns; - functionPatterns + std::vector> functionPatterns = { // Core functions - << "abs" + tr("(X) The abs(X) function returns the absolute value of the numeric argument X.") - << "changes" + tr("() The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement.") - << "char" + tr("(X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. ") - << "coalesce" + tr("(X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL") - << "glob" + tr("(X,Y) The glob(X,Y) function is equivalent to the expression \"Y GLOB X\".") - << "ifnull" + tr("(X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL.") - << "instr" + tr("(X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X.") - << "hex" + tr("(X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob.") - << "last_insert_rowid" + tr("() The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function.") - << "length" + tr("(X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character.") - << "like" + tr("(X,Y) The like() function is used to implement the \"Y LIKE X\" expression.") - << "like" + tr("(X,Y,Z) The like() function is used to implement the \"Y LIKE X ESCAPE Z\" expression.") - << "load_extension" + tr("(X) The load_extension(X) function loads SQLite extensions out of the shared library file named X.") - << "load_extension" + tr("(X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y.") - << "lower" + tr("(X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case.") - << "ltrim" + tr("(X) ltrim(X) removes spaces from the left side of X.") - << "ltrim" + tr("(X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X.") - << "max" + tr("(X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL.") - << "min" + tr("(X,Y,...) The multi-argument min() function returns the argument with the minimum value.") - << "nullif" + tr("(X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same.") - << "printf" + tr("(FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library.") - << "quote" + tr("(X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement.") - << "random" + tr("() The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807.") - << "randomblob" + tr("(N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes.") - << "replace" + tr("(X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X.") - << "round" + tr("(X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point.") - << "round" + tr("(X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point.") - << "rtrim" + tr("(X) rtrim(X) removes spaces from the right side of X.") - << "rtrim" + tr("(X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X.") - << "soundex" + tr("(X) The soundex(X) function returns a string that is the soundex encoding of the string X.") - << "substr" + tr("(X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th.") - << "substr" + tr("(X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long.") - << "total_changes" + tr("() The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened.") - << "trim" + tr("(X) trim(X) removes spaces from both ends of X.") - << "trim" + tr("(X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X.") - << "typeof" + tr("(X) The typeof(X) function returns a string that indicates the datatype of the expression X.") - << "unicode" + tr("(X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X.") - << "upper" + tr("(X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent.") - << "zeroblob" + tr("(N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00.") + {"abs", tr("(X) The abs(X) function returns the absolute value of the numeric argument X.")}, + {"changes", tr("() The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement.")}, + {"char", tr("(X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. ")}, + {"coalesce", tr("(X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL")}, + {"concat", tr("(X,...) The concat(...) function returns a string which is the concatenation of the string representation of all of its non-NULL arguments. If all arguments are NULL, then concat() returns an empty string.")}, + {"concat_ws", tr("(SEP,X,...) The concat_ws(SEP,...) function returns a string that is the concatenation of all non-null arguments beyond the first argument, using the text value of the first argument as a separator.")}, + {"format", tr("(FORMAT,...) The format(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library.")}, + {"glob", tr("(X,Y) The glob(X,Y) function is equivalent to the expression \"Y GLOB X\".")}, + {"ifnull", tr("(X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL.")}, + {"instr", tr("(X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X.")}, + {"hex", tr("(X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob.")}, + {"iif", tr("(X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise.")}, + {"last_insert_rowid", tr("() The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function.")}, + {"length", tr("(X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character.")}, + {"like", tr("(X,Y) The like() function is used to implement the \"Y LIKE X\" expression.")}, + {"like", tr("(X,Y,Z) The like() function is used to implement the \"Y LIKE X ESCAPE Z\" expression.")}, + {"likelihood", tr("(X,Y) The purpose of the likelihood(X,Y) function is to provide a hint to the query planner that the argument X is a boolean that is true with a probability of approximately Y.")}, + {"likely", tr("(X) The purpose of the likely(X) function is to provide a hint to the query planner that the argument X is a boolean value that is usually true.")}, + {"load_extension", tr("(X) The load_extension(X) function loads SQLite extensions out of the shared library file named X.\nUse of this function must be authorized from Preferences.")}, + {"load_extension", tr("(X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y.\nUse of this function must be authorized from Preferences.")}, + {"lower", tr("(X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case.")}, + {"ltrim", tr("(X) ltrim(X) removes spaces from the left side of X.")}, + {"ltrim", tr("(X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X.")}, + {"max", tr("(X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL.")}, + {"min", tr("(X,Y,...) The multi-argument min() function returns the argument with the minimum value.")}, + {"nullif", tr("(X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same.")}, + {"octet_length", tr("(X) The octet_length(X) function returns the number of bytes in the encoding of X.")}, + {"printf", tr("(FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library.")}, + {"quote", tr("(X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement.")}, + {"random", tr("() The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807.")}, + {"randomblob", tr("(N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes.")}, + {"replace", tr("(X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X.")}, + {"round", tr("(X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point.")}, + {"round", tr("(X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point.")}, + {"rtrim", tr("(X) rtrim(X) removes spaces from the right side of X.")}, + {"rtrim", tr("(X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X.")}, + {"soundex", tr("(X) The soundex(X) function returns a string that is the soundex encoding of the string X.")}, + {"substr", tr("(X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th.")}, + {"substr", tr("(X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long.")}, + {"total_changes", tr("() The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened.")}, + {"trim", tr("(X) trim(X) removes spaces from both ends of X.")}, + {"trim", tr("(X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X.")}, + {"typeof", tr("(X) The typeof(X) function returns a string that indicates the datatype of the expression X.")}, + {"unhex", tr("(X) The unhex(X) function returns a BLOB value which is the decoding of the hexadecimal string X. X must be a pure hexadecimal string.")}, + {"unhex", tr("(X,Y) The unhex(X,Y) function returns a BLOB value which is the decoding of the hexadecimal string X. If X contains any characters that are not hexadecimal digits and which are not in Y, then unhex(X,Y) returns NULL.")}, + {"unicode", tr("(X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X.")}, + {"unlikely", tr("(X) The purpose of the unlikely(X) function is to provide a hint to the query planner that the argument X is a boolean value that is usually not true.")}, + {"upper", tr("(X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent.")}, + {"zeroblob", tr("(N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00.")}, // Date and time functions - << "date" + tr("(timestring,modifier,modifier,...)") - << "time" + tr("(timestring,modifier,modifier,...)") - << "datetime" + tr("(timestring,modifier,modifier,...)") - << "julianday" + tr("(timestring,modifier,modifier,...)") - << "strftime" + tr("(format,timestring,modifier,modifier,...)") + {"date", tr("(timestring,modifier,modifier,...)")}, + {"time", tr("(timestring,modifier,modifier,...)")}, + {"datetime", tr("(timestring,modifier,modifier,...)")}, + {"julianday", tr("(timestring,modifier,modifier,...)")}, + {"strftime", tr("(format,timestring,modifier,modifier,...)")}, // Aggregate functions - << "avg" + tr("(X) The avg() function returns the average value of all non-NULL X within a group.") - << "count" + tr("(X) The count(X) function returns a count of the number of times that X is not NULL in a group.") - << "group_concat" + tr("(X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X.") - << "group_concat" + tr("(X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X.") - << "max" + tr("(X) The max() aggregate function returns the maximum value of all values in the group.") - << "min" + tr("(X) The min() aggregate function returns the minimum non-NULL value of all values in the group.") - << "sum" + tr("(X) The sum() and total() aggregate functions return sum of all non-NULL values in the group.") - << "total" + tr("(X) The sum() and total() aggregate functions return sum of all non-NULL values in the group."); + {"avg", tr("(X) The avg() function returns the average value of all non-NULL X within a group.")}, + {"count", tr("(X) The count(X) function returns a count of the number of times that X is not NULL in a group.")}, + {"group_concat", tr("(X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X.")}, + {"group_concat", tr("(X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X.")}, + {"string_agg", tr("(X,Y) string_agg(X,Y) function is an alias for group_concat(X,Y). String_agg() is compatible with PostgreSQL and SQL-Server and group_concat() is compatible with MySQL.")}, + {"max", tr("(X) The max() aggregate function returns the maximum value of all values in the group.")}, + {"min", tr("(X) The min() aggregate function returns the minimum non-NULL value of all values in the group.")}, + {"sum", tr("(X) The sum() and total() aggregate functions return sum of all non-NULL values in the group.")}, + {"total", tr("(X) The sum() and total() aggregate functions return sum of all non-NULL values in the group.")}, + // Window functions + {"row_number", tr("() The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise.")}, + {"rank", tr("() The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1.")}, + {"dense_rank", tr("() The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. ")}, + {"percent_rank", tr("() Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. ")}, + {"cume_dist", tr("() The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition.")}, + {"ntile", tr("(N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of.")}, + {"lag", tr("(expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL.")}, + {"lag", tr("(expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned.")}, + {"lag", tr("(expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist.")}, + {"lead", tr("(expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL.")}, + {"lead", tr("(expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned.")}, + {"lead", tr("(expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist.")}, + {"first_value", tr("(expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row.")}, + {"last_value", tr("(expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row.")}, + {"nth_value", tr("(expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned.")} + }; + + if (enabledMathFunctions()) { + functionPatterns.insert(functionPatterns.end(), { + // Math functions introduced from SQLite 3.35 + {"acos", tr("(X) Return the arccosine of X. The result is in radians.")}, + {"acosh", tr("(X) Return the hyperbolic arccosine of X.")}, + {"asin", tr("(X) Return the arcsine of X. The result is in radians.")}, + {"asinh", tr("(X) Return the hyperbolic arcsine of X.")}, + {"atan", tr("(X) Return the arctangent of X. The result is in radians.")}, + {"atan2", tr("(X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y.")}, + {"atanh", tr("(X) Return the hyperbolic arctangent of X.")}, + {"ceil", tr("(X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero.")}, + {"ceiling", tr("(X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero.")}, + {"cos", tr("(X) Return the cosine of X. X is in radians.")}, + {"cosh", tr("(X) Return the hyperbolic cosine of X.")}, + {"degrees", tr("(X) Convert value X from radians into degrees.")}, + {"exp", tr("(X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X.")}, + {"floor", tr("(X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero.")}, + {"ln", tr("(X) Return the natural logarithm of X.")}, + {"log", tr("(B,X) Return the base-B logarithm of X.")}, + {"log", tr("(X) Return the base-10 logarithm for X.")}, + {"log10", tr("(X) Return the base-10 logarithm for X.")}, + {"log2", tr("(X) Return the logarithm base-2 for the number X.")}, + {"mod", tr("(X,Y) Return the remainder after dividing X by Y.")}, + {"pi", tr("() Return an approximation for Ï€.")}, + {"pow", tr("(X,Y) Compute X raised to the power Y.")}, + {"power", tr("(X,Y) Compute X raised to the power Y.")}, + {"radians", tr("(X) Convert X from degrees into radians.")}, + {"sin", tr("(X) Return the sine of X. X is in radians.")}, + {"sinh", tr("(X) Return the hyperbolic sine of X.")}, + {"sqrt", tr("(X) Return the square root of X. NULL is returned if X is negative.")}, + {"tan", tr("(X) Return the tangent of X. X is in radians.")}, + {"tanh", tr("(X) Return the hyperbolic tangent of X.")}, + {"trunc", tr("(X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero.")} + }); + } listFunctions.clear(); - foreach(const QString& keyword, functionPatterns) + for(const auto& keyword : functionPatterns) { - QString fn = keyword.left(keyword.indexOf('(')); - QString descr = keyword.mid(keyword.indexOf('(')); - - autocompleteApi->add(fn + "?" + QString::number(ApiCompleterIconIdFunction) + descr); - autocompleteApi->add(fn.toUpper() + "?" + QString::number(ApiCompleterIconIdFunction) + descr); + autocompleteApi->add(keyword.first + "?" + QString::number(ApiCompleterIconIdFunction) + keyword.second); + autocompleteApi->add(keyword.first.toUpper() + "?" + QString::number(ApiCompleterIconIdFunction) + keyword.second); // Store all function names in order to highlight them in a different colour - listFunctions.append(fn); + listFunctions.append(keyword.first); } + + // Push the QsciAPIs::prepare method call to the + // execution queue, callers should receive + // callbacks in order. + QMetaObject::invokeMethod(this, [this] { + autocompleteApi->prepare(); + }, Qt::QueuedConnection); } -void SqlUiLexer::setTableNames(const TablesAndColumnsMap& tables) +void SqlUiLexer::setTableNames(const QualifiedTablesMap& tables) { // Update list for auto completion autocompleteApi->clear(); listTables.clear(); - setupAutoCompletion(); - for(TablesAndColumnsMap::ConstIterator it=tables.constBegin();it!=tables.constEnd();++it) + for(const auto& itSchemas : tables) { - foreach(const QString& field, it.value()) - autocompleteApi->add(it.key() + "?" + QString::number(SqlUiLexer::ApiCompleterIconIdTable) + "." + - field + "?" + QString::number(SqlUiLexer::ApiCompleterIconIdColumn)); + for(const auto& itTables : itSchemas.second) + { + // Completion for schema.table + autocompleteApi->add(itSchemas.first + "?" + QString::number(SqlUiLexer::ApiCompleterIconIdSchema) + "." + + itTables.first + "?" + QString::number(SqlUiLexer::ApiCompleterIconIdTable)); + + for(const QString& field : itTables.second) { + // Completion for table.field + autocompleteApi->add(itTables.first + "?" + QString::number(SqlUiLexer::ApiCompleterIconIdTable) + "." + + field + "?" + QString::number(SqlUiLexer::ApiCompleterIconIdColumn)); - // Store the table name list in order to highlight them in a different colour - listTables.append(it.key()); + // Completion for isolated field + autocompleteApi->add(field + "?" + QString::number(SqlUiLexer::ApiCompleterIconIdColumn)); + } + // Store the table name list in order to highlight them in a different colour + listTables.append(itTables.first); + } } - autocompleteApi->prepare(); + + setupAutoCompletion(); } const char* SqlUiLexer::keywords(int set) const { // Function and table names are generated automatically but need to be returned to the calling functions. // In order to not have them deleted after this function ends they are stored as static variables. Because - // the functions list doesn't change after the first call it's initialised here whereas the tables list, which - // can change, is updated for each call + // the keywords and functions lists don't change after the first call it's initialised here whereas the tables + // list, which can change, is updated for each call + static std::string sqliteKeywords = keywordPatterns.join(" ").toLower().toUtf8().constData(); static std::string functions = listFunctions.join(" ").toUtf8().constData(); static std::string tables; - if(set == 6) // This corresponds to the QsciLexerSQL::KeywordSet6 style in SqlTextEdit + if(set == 1) { // This corresponds to the QsciLexerSQL::Keyword style in SqlTextEdit + return sqliteKeywords.c_str(); + } else if(set == 6) // This corresponds to the QsciLexerSQL::KeywordSet6 style in SqlTextEdit { tables = listTables.join(" ").toLower().toUtf8().constData(); return tables.c_str(); @@ -169,8 +270,19 @@ QStringList SqlUiLexer::autoCompletionWordSeparators() const { // The only word separator for auto completion in SQL is "." as in "tablename.columnname". // Because this isn't implemented in the default QScintilla SQL lexer for some reason we add it here. - + // We also need to consider quoted identifiers as in "tablename"."columnname" with whatever quote character + // is configured. QStringList wl; - wl << "."; + + QString escapeSeparator = sqlb::escapeIdentifier(QString(".")); + // Case for non symmetric quotes, e.g. "[.]" to "].[" + std::reverse(escapeSeparator.begin(), escapeSeparator.end()); + + wl << "." << escapeSeparator; return wl; } + +bool SqlUiLexer::caseSensitive() const +{ + return false; +} diff --git a/src/SqlUiLexer.h b/src/SqlUiLexer.h index e87dbf72f..b8717e605 100644 --- a/src/SqlUiLexer.h +++ b/src/SqlUiLexer.h @@ -3,7 +3,7 @@ #include "Qsci/qscilexersql.h" -#include +#include class QsciAPIs; @@ -12,7 +12,7 @@ class SqlUiLexer : public QsciLexerSQL Q_OBJECT public: - explicit SqlUiLexer(QObject *parent = 0); + explicit SqlUiLexer(QObject *parent = nullptr); enum ApiCompleterIconId { @@ -20,14 +20,19 @@ class SqlUiLexer : public QsciLexerSQL ApiCompleterIconIdFunction, ApiCompleterIconIdTable, ApiCompleterIconIdColumn, + ApiCompleterIconIdSchema, }; - typedef QMap > TablesAndColumnsMap; - void setTableNames(const TablesAndColumnsMap& tables); + using TablesAndColumnsMap = std::map>; + using QualifiedTablesMap = std::map; - virtual const char* keywords(int set) const; + void setTableNames(const QualifiedTablesMap& tables); - virtual QStringList autoCompletionWordSeparators() const; + const char* keywords(int set) const override; + + QStringList autoCompletionWordSeparators() const override; + + bool caseSensitive() const override; private: QsciAPIs* autocompleteApi; @@ -36,6 +41,7 @@ class SqlUiLexer : public QsciLexerSQL QStringList listTables; QStringList listFunctions; + static const QStringList keywordPatterns; }; #endif diff --git a/src/TableBrowser.cpp b/src/TableBrowser.cpp new file mode 100644 index 000000000..6dc3e8f2e --- /dev/null +++ b/src/TableBrowser.cpp @@ -0,0 +1,1736 @@ +#include "AddRecordDialog.h" +#include "Application.h" +#include "ColumnDisplayFormatDialog.h" +#include "CondFormatManager.h" +#include "Data.h" +#include "DbStructureModel.h" +#include "ExportDataDialog.h" +#include "FilterTableHeader.h" +#include "TableBrowser.h" +#include "Settings.h" +#include "sqlitedb.h" +#include "sqlitetablemodel.h" +#include "ui_TableBrowser.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +std::map TableBrowser::m_settings; +QString TableBrowser::m_defaultEncoding; + +TableBrowser::TableBrowser(DBBrowserDB* _db, QWidget* parent) : + QWidget(parent), + ui(new Ui::TableBrowser), + gotoValidator(new QIntValidator(0, 0, this)), + db(_db), + dbStructureModel(nullptr), + m_model(nullptr), + m_adjustRows(false), + m_columnsResized(false) +{ + ui->setupUi(this); + + // Set the validator for the goto line edit + ui->editGoto->setValidator(gotoValidator); + + // Set custom placeholder text for global filter field and disable conditional formats + ui->editGlobalFilter->setPlaceholderText(tr("Filter in any column")); + ui->editGlobalFilter->setConditionFormatContextMenuEnabled(false); + + // Set up popup menus + popupNewRecordMenu = new QMenu(this); + popupNewRecordMenu->addAction(ui->newRecordAction); + popupNewRecordMenu->addAction(ui->insertValuesAction); + ui->actionNewRecord->setMenu(popupNewRecordMenu); + + popupSaveFilterAsMenu = new QMenu(this); + popupSaveFilterAsMenu->addAction(ui->actionFilteredTableExportCsv); + popupSaveFilterAsMenu->addAction(ui->actionFilteredTableExportJson); + popupSaveFilterAsMenu->addAction(ui->actionFilterSaveAsView); + ui->actionSaveFilterAsPopup->setMenu(popupSaveFilterAsMenu); + qobject_cast(ui->browseToolbar->widgetForAction(ui->actionSaveFilterAsPopup))->setPopupMode(QToolButton::InstantPopup); + + popupHeaderMenu = new QMenu(this); + popupHeaderMenu->addAction(ui->actionShowRowidColumn); + popupHeaderMenu->addAction(ui->actionFreezeColumns); + popupHeaderMenu->addAction(ui->actionHideColumns); + popupHeaderMenu->addAction(ui->actionShowAllColumns); + popupHeaderMenu->addAction(ui->actionSelectColumn); + popupHeaderMenu->addSeparator(); + popupHeaderMenu->addAction(ui->actionUnlockViewEditing); + popupHeaderMenu->addAction(ui->actionBrowseTableEditDisplayFormat); + popupHeaderMenu->addSeparator(); + popupHeaderMenu->addAction(ui->actionSetTableEncoding); + popupHeaderMenu->addAction(ui->actionSetAllTablesEncoding); + popupHeaderMenu->addSeparator(); + popupHeaderMenu->addAction(ui->actionCopyColumnName); + + connect(ui->actionSelectColumn, &QAction::triggered, this, [this]() { + ui->dataTable->selectColumn(ui->actionBrowseTableEditDisplayFormat->property("clicked_column").toInt()); + }); + connect(ui->actionFreezeColumns, &QAction::triggered, this, [this](bool checked) { + if(checked) + freezeColumns(ui->actionBrowseTableEditDisplayFormat->property("clicked_column").toUInt() + 1); + else + freezeColumns(0); + }); + + // Set up shortcuts + QShortcut* dittoRecordShortcut = new QShortcut(QKeySequence("Ctrl+\""), this); + connect(dittoRecordShortcut, &QShortcut::activated, this, [this]() { + int currentRow = ui->dataTable->currentIndex().row(); + duplicateRecord(currentRow); + }); + + // Lambda function for keyboard shortcuts for selecting next/previous table in Browse Data tab + connect(ui->dataTable, &ExtendedTableWidget::switchTable, this, [this](bool next) { + int index = ui->comboBrowseTable->currentIndex(); + int num_items = ui->comboBrowseTable->count(); + if(next) + { + if(++index >= num_items) + index = 0; + } else { + if(--index < 0) + index = num_items - 1; + } + ui->comboBrowseTable->setCurrentIndex(index); + refresh(); + }); + + // This is a workaround needed for QDarkStyleSheet. + // See https://github.com/ColinDuquesnoy/QDarkStyleSheet/issues/169 + QStyledItemDelegate* styledItemDelegate = new QStyledItemDelegate(ui->comboBrowseTable); + ui->comboBrowseTable->setItemDelegate(styledItemDelegate); + + // Add the documentation of shortcuts, which aren't otherwise visible in the user interface, to some buttons. + addShortcutsTooltip(ui->actionRefresh, {QKeySequence(tr("Ctrl+R"))}); + addShortcutsTooltip(ui->actionPrintTable); + + // Set up filters + connect(ui->dataTable->filterHeader(), &FilterTableHeader::filterChanged, this, &TableBrowser::updateFilter); + connect(ui->dataTable->filterHeader(), &FilterTableHeader::filterFocused, this, [this]() { + emit prepareForFilter(); + }); + connect(ui->dataTable->filterHeader(), &FilterTableHeader::addCondFormat, this, &TableBrowser::addCondFormatFromFilter); + connect(ui->dataTable->filterHeader(), &FilterTableHeader::allCondFormatsCleared, this, &TableBrowser::clearAllCondFormats); + connect(ui->dataTable->filterHeader(), &FilterTableHeader::condFormatsEdited, this, &TableBrowser::editCondFormats); + connect(ui->dataTable, &ExtendedTableWidget::editCondFormats, this, &TableBrowser::editCondFormats); + connect(ui->dataTable, &ExtendedTableWidget::dataAboutToBeEdited, this, &TableBrowser::dataAboutToBeEdited); + + // Set up global filter + connect(ui->editGlobalFilter, &FilterLineEdit::filterFocused, this, [this]() { + emit prepareForFilter(); + }); + connect(ui->editGlobalFilter, &FilterLineEdit::delayedTextChanged, this, [this](const QString& value) { + // Split up filter values +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + QStringList values = value.trimmed().split(" ", QString::SkipEmptyParts); +#else + QStringList values = value.trimmed().split(" ", Qt::SkipEmptyParts); +#endif + std::vector filters; + std::copy(values.begin(), values.end(), std::back_inserter(filters)); + + ui->actionClearFilters->setEnabled(m_model->filterCount() > 0 || !ui->editGlobalFilter->text().isEmpty()); + + // Have they changed? + BrowseDataTableSettings& settings = m_settings[currentlyBrowsedTableName()]; + if(filters != settings.globalFilters) + { + // Set global filters + m_model->updateGlobalFilter(filters); + updateRecordsetLabel(); + + // Save them + settings.globalFilters = filters; + emit projectModified(); + } + }); + + connect(ui->dataTable, &ExtendedTableWidget::doubleClicked, this, &TableBrowser::selectionChangedByDoubleClick); + connect(ui->dataTable->filterHeader(), &FilterTableHeader::sectionClicked, this, &TableBrowser::headerClicked); + connect(ui->dataTable->filterHeader(), &QHeaderView::sectionDoubleClicked, ui->dataTable, &QTableView::selectColumn); + connect(ui->dataTable->verticalScrollBar(), &QScrollBar::valueChanged, this, &TableBrowser::updateRecordsetLabel); + connect(ui->dataTable->horizontalHeader(), &QHeaderView::sectionResized, this, &TableBrowser::updateRecordsetLabel); + connect(ui->dataTable->verticalHeader(), &QHeaderView::sectionResized, this, &TableBrowser::updateRecordsetLabel); + connect(ui->dataTable->horizontalHeader(), &QHeaderView::sectionResized, this, &TableBrowser::updateColumnWidth); + connect(ui->dataTable->horizontalHeader(), &QHeaderView::customContextMenuRequested, this, &TableBrowser::showDataColumnPopupMenu); + connect(ui->dataTable->verticalHeader(), &QHeaderView::customContextMenuRequested, this, &TableBrowser::showRecordPopupMenu); + connect(ui->dataTable, &ExtendedTableWidget::openFileFromDropEvent, this, &TableBrowser::requestFileOpen); + connect(ui->dataTable, &ExtendedTableWidget::selectedRowsToBeDeleted, this, &TableBrowser::deleteRecord); + + connect(ui->dataTable, &ExtendedTableWidget::foreignKeyClicked, this, [this](const sqlb::ObjectIdentifier& table, const std::string& column, const QByteArray& value) { + // Just select the column that was just clicked instead of selecting an entire range which + // happens because of the Ctrl and Shift keys. + ui->dataTable->selectionModel()->select(ui->dataTable->currentIndex(), QItemSelectionModel::ClearAndSelect); + + // Emit the foreign key clicked signal + emit foreignKeyClicked(table, column, value); + }); + + connect(ui->actionAddDock, &QAction::triggered, this, [this]() { + emit newDockRequested(); + }); + connect(ui->actionRefresh, &QAction::triggered, this, [this]() { + db->updateSchema(); + refresh(); + }); + connect(ui->fontComboBox, &QFontComboBox::currentFontChanged, this, [this](const QFont &font) { + modifyFormat([font](CondFormat& format) { format.setFontFamily(font.family()); }); + }); + connect(ui->fontSizeBox, static_cast(&QSpinBox::valueChanged), this, + [this](int pointSize) { + modifyFormat([pointSize](CondFormat& format) { format.setFontPointSize(pointSize); }); + }); + + connect(ui->actionFontColor, &QAction::triggered, this, [this]() { + QColor color = QColorDialog::getColor(QColor(m_model->data(currentIndex(), Qt::ForegroundRole).toString())); + if(color.isValid()) + modifyFormat([color](CondFormat& format) { format.setForegroundColor(color); }); + }); + connect(ui->actionBackgroundColor, &QAction::triggered, this, [this]() { + QColor color = QColorDialog::getColor(QColor(m_model->data(currentIndex(), Qt::BackgroundRole).toString())); + if(color.isValid()) + modifyFormat([color](CondFormat& format) { format.setBackgroundColor(color); }); + }); + + connect(ui->actionBold, &QAction::toggled, this, [this](bool checked) { + modifyFormat([checked](CondFormat& format) { format.setBold(checked); }); + }); + connect(ui->actionItalic, &QAction::toggled, this, [this](bool checked) { + modifyFormat([checked](CondFormat& format) { format.setItalic(checked); }); + }); + connect(ui->actionUnderline, &QAction::toggled, this, [this](bool checked) { + modifyFormat([checked](CondFormat& format) { format.setUnderline(checked); }); + }); + + connect(ui->actionLeftAlign, &QAction::triggered, this, [this]() { + ui->actionLeftAlign->setChecked(true); + ui->actionRightAlign->setChecked(false); + ui->actionCenter->setChecked(false); + ui->actionJustify->setChecked(false); + modifyFormat([](CondFormat& format) { format.setAlignment(CondFormat::AlignLeft); }); + }); + connect(ui->actionRightAlign, &QAction::triggered, this, [this]() { + ui->actionLeftAlign->setChecked(false); + ui->actionRightAlign->setChecked(true); + ui->actionCenter->setChecked(false); + ui->actionJustify->setChecked(false); + modifyFormat([](CondFormat& format) { format.setAlignment(CondFormat::AlignRight); }); + }); + connect(ui->actionCenter, &QAction::triggered, this, [this]() { + ui->actionLeftAlign->setChecked(false); + ui->actionRightAlign->setChecked(false); + ui->actionCenter->setChecked(true); + ui->actionJustify->setChecked(false); + modifyFormat([](CondFormat& format) { format.setAlignment(CondFormat::AlignCenter); }); + }); + connect(ui->actionJustify, &QAction::triggered, this, [this]() { + ui->actionLeftAlign->setChecked(false); + ui->actionRightAlign->setChecked(false); + ui->actionCenter->setChecked(false); + ui->actionJustify->setChecked(true); + modifyFormat([](CondFormat& format) { format.setAlignment(CondFormat::AlignJustify); }); + }); + + connect(ui->actionEditCondFormats, &QAction::triggered, this, [this]() { editCondFormats(static_cast(currentIndex().column())); }); + connect(ui->actionClearFormat, &QAction::triggered, this, [this]() { + for (const size_t column : ui->dataTable->selectedCols()) + clearAllCondFormats(column); + for (const QModelIndex& index : ui->dataTable->selectionModel()->selectedIndexes()) + clearRowIdFormats(index); + + }); + + connect(ui->dataTable, &ExtendedTableWidget::currentIndexChanged, this, [this](const QModelIndex ¤t, const QModelIndex &) { + // Get cell current format for updating the format toolbar values. Block signals, so the format change is not reapplied. + QString font_string = m_model->data(current, Qt::FontRole).toString(); + QFont font; + if(!font_string.isEmpty()) + font.fromString(font_string); + + ui->fontComboBox->blockSignals(true); + ui->fontComboBox->setCurrentFont(font); + ui->fontComboBox->blockSignals(false); + + ui->fontSizeBox->blockSignals(true); + ui->fontSizeBox->setValue(font.pointSize()); + ui->fontSizeBox->blockSignals(false); + + ui->actionBold->blockSignals(true); + ui->actionBold->setChecked(font.bold()); + ui->actionBold->blockSignals(false); + + ui->actionItalic->blockSignals(true); + ui->actionItalic->setChecked(font.italic()); + ui->actionItalic->blockSignals(false); + + ui->actionUnderline->blockSignals(true); + ui->actionUnderline->setChecked(font.underline()); + ui->actionUnderline->blockSignals(false); + + Qt::Alignment align = Qt::Alignment(m_model->data(current, Qt::TextAlignmentRole).toInt()); + ui->actionLeftAlign->blockSignals(true); + ui->actionLeftAlign->setChecked(align.testFlag(Qt::AlignLeft)); + ui->actionLeftAlign->blockSignals(false); + + ui->actionRightAlign->blockSignals(true); + ui->actionRightAlign->setChecked(align.testFlag(Qt::AlignRight)); + ui->actionRightAlign->blockSignals(false); + + ui->actionCenter->blockSignals(true); + ui->actionCenter->setChecked(align.testFlag(Qt::AlignCenter)); + ui->actionCenter->blockSignals(false); + + ui->actionJustify->blockSignals(true); + ui->actionJustify->setChecked(align.testFlag(Qt::AlignJustify)); + ui->actionJustify->blockSignals(false); + }); + + connect(ui->actionToggleFormatToolbar, &QAction::toggled, ui->formatFrame, &QFrame::setVisible); + ui->actionToggleFormatToolbar->setChecked(false); + ui->formatFrame->setVisible(false); + + // Set up find frame + ui->frameFind->hide(); + + QShortcut* shortcutHideFindFrame = new QShortcut(QKeySequence("ESC"), ui->editFindExpression); + connect(shortcutHideFindFrame, &QShortcut::activated, ui->buttonFindClose, &QToolButton::click); + + QShortcut* shortcutActionFind = new QShortcut(QKeySequence("Ctrl+F"), this, nullptr, nullptr, Qt::WidgetWithChildrenShortcut); + connect(shortcutActionFind, &QShortcut::activated, ui->actionFind, &QAction::trigger); + connect(ui->actionFind, &QAction::triggered, this, [this](bool checked) { + if(checked) + { + ui->widgetReplace->hide(); + ui->frameFind->show(); + ui->editFindExpression->setFocus(); + ui->actionReplace->setChecked(false); + } else { + ui->buttonFindClose->click(); + } + }); + + QShortcut* shortcutActionReplace = new QShortcut(QKeySequence("Ctrl+H"), this, nullptr, nullptr, Qt::WidgetWithChildrenShortcut); + connect(shortcutActionReplace, &QShortcut::activated, ui->actionReplace, &QAction::trigger); + connect(ui->actionReplace, &QAction::triggered, this, [this](bool checked) { + if(checked) + { + ui->widgetReplace->show(); + ui->frameFind->show(); + ui->editFindExpression->setFocus(); + ui->actionFind->setChecked(false); + } else { + ui->buttonFindClose->click(); + } + }); + + connect(ui->editFindExpression, &QLineEdit::returnPressed, ui->buttonFindNext, &QToolButton::click); + connect(ui->editFindExpression, &QLineEdit::textChanged, this, [this]() { + // When the text has changed but neither Return nor F3 or similar nor any buttons were pressed, we want to include the current + // cell in the search as well. This makes sure the selected cell does not jump around every time the text is changed but only + // when the current cell does not match the search expression anymore. + find(ui->editFindExpression->text(), true, true); + }); + connect(ui->buttonFindClose, &QToolButton::clicked, this, [this](){ + ui->dataTable->setFocus(); + ui->frameFind->hide(); + ui->actionFind->setChecked(false); + ui->actionReplace->setChecked(false); + }); + connect(ui->buttonFindPrevious, &QToolButton::clicked, this, [this](){ + find(ui->editFindExpression->text(), false); + }); + connect(ui->buttonFindNext, &QToolButton::clicked, this, [this](){ + find(ui->editFindExpression->text(), true); + }); + connect(ui->buttonReplaceNext, &QToolButton::clicked, this, [this](){ + find(ui->editFindExpression->text(), true, true, ReplaceMode::ReplaceNext); + }); + connect(ui->buttonReplaceAll, &QToolButton::clicked, this, [this](){ + find(ui->editFindExpression->text(), true, true, ReplaceMode::ReplaceAll); + }); + + QShortcut* shortcutActionFilter = new QShortcut(QKeySequence("Ctrl+Shift+F"), this, nullptr, nullptr, Qt::WidgetWithChildrenShortcut); + connect(shortcutActionFilter, &QShortcut::activated, this, [this](){ + // Restore cursor because in the ExtendedTableWidget it is changed to a hand when Ctrl+Shift + // is pressed. + QApplication::restoreOverrideCursor(); + FilterTableHeader* header = qobject_cast(ui->dataTable->horizontalHeader()); + // Set the focus to the current column if valid, otherwise, set focus to the first visible + // column. + if(!header) { + ui->dataTable->horizontalHeader()->setFocus(); + } else if(currentIndex().isValid()) { + header->setFocusColumn(static_cast(currentIndex().column())); + } else { + for(int col = 0; col < ui->dataTable->model()->columnCount(); col++) + { + if(!ui->dataTable->isColumnHidden(col)) { + header->setFocusColumn(static_cast(col)); + break; + } + } + } + }); + + QShortcut* shortcutActionGlobalFilter = new QShortcut(QKeySequence("F3"), this, nullptr, nullptr, Qt::WidgetWithChildrenShortcut); + connect(shortcutActionGlobalFilter, &QShortcut::activated, this, [this](){ + ui->editGlobalFilter->setFocus(); + }); + + // Recreate the model + if(m_model) + delete m_model; + m_model = new SqliteTableModel(*db, this, QString(), true); + + // Connect slots + connect(m_model, &SqliteTableModel::finishedFetch, this, &TableBrowser::fetchedData); + + // Load initial settings + reloadSettings(); +} + +TableBrowser::~TableBrowser() +{ + delete gotoValidator; + delete ui; +} + +void TableBrowser::reset() +{ + // Reset the model + m_model->reset(); + + // Reset the recordset label inside the Browse tab now + updateRecordsetLabel(); + + // Clear filters + clearFilters(); + + // Reset the plot dock model and connection + emit updatePlot(nullptr, nullptr, nullptr, true); +} + +void TableBrowser::resetSharedSettings() +{ + // Remove all stored table information browse data tab + m_settings.clear(); + m_defaultEncoding = QString(); +} + +sqlb::ObjectIdentifier TableBrowser::currentlyBrowsedTableName() const +{ + return sqlb::ObjectIdentifier(dbStructureModel->index(ui->comboBrowseTable->currentIndex(), + DbStructureModel::ColumnSchema, + ui->comboBrowseTable->rootModelIndex()).data().toString().toStdString(), + ui->comboBrowseTable->currentData(Qt::EditRole).toString().toStdString()); // Use the edit role here to make sure we actually get the + // table name without the schema bit in front of it. +} + +BrowseDataTableSettings& TableBrowser::settings(const sqlb::ObjectIdentifier& object) +{ + return m_settings[object]; +} + +void TableBrowser::setSettings(const sqlb::ObjectIdentifier& table, const BrowseDataTableSettings& table_settings) +{ + m_settings[table] = table_settings; +} + +void TableBrowser::setStructure(QAbstractItemModel* model, const sqlb::ObjectIdentifier& old_table) +{ + dbStructureModel = model; + + ui->comboBrowseTable->blockSignals(true); + ui->comboBrowseTable->setModel(model); + ui->comboBrowseTable->setRootModelIndex(dbStructureModel->index(0, 0)); // Show the 'browsable' section of the db structure tree + ui->comboBrowseTable->blockSignals(false); + + int old_table_index = ui->comboBrowseTable->findText(QString::fromStdString(old_table.toDisplayString())); + if(old_table_index == -1 && ui->comboBrowseTable->count()) // If the old table couldn't be found anymore but there is another table, select that + ui->comboBrowseTable->setCurrentIndex(0); + else if(old_table_index == -1) // If there aren't any tables to be selected anymore, clear the table view + clear(); + else // Under normal circumstances just select the old table again + ui->comboBrowseTable->setCurrentIndex(old_table_index); + + emit currentTableChanged(currentlyBrowsedTableName()); +} + +QModelIndex TableBrowser::currentIndex() const +{ + return ui->dataTable->currentIndex(); +} + +void TableBrowser::setEnabled(bool enable) +{ + ui->browseToolbar->setEnabled(enable); + ui->editGlobalFilter->setEnabled(enable); + ui->formatFrame->setEnabled(enable); + ui->frameFind->setEnabled(enable); + + ui->buttonNext->setEnabled(enable); + ui->buttonPrevious->setEnabled(enable); + ui->buttonBegin->setEnabled(enable); + ui->buttonEnd->setEnabled(enable); + ui->buttonGoto->setEnabled(enable); + ui->editGoto->setEnabled(enable); + + updateInsertDeleteRecordButton(); +} + +void TableBrowser::refresh() +{ + // If the list of table names is empty, i.e. there are no tables to browse, clear the view + // to make sure any left over data is removed and do not add any new information. + if(ui->comboBrowseTable->model()->rowCount(ui->comboBrowseTable->rootModelIndex()) == 0) + { + clear(); + return; + } + + // Reset the minimum width of the vertical header which could have been modified in updateFilter + // or in headerClicked. + ui->dataTable->verticalHeader()->setMinimumWidth(0); + + // Reset the model if it was cleared before + // Because setting a new model creates a new selection mode, reconnect the slots to its signals. + if(ui->dataTable->model() == nullptr) + { + ui->dataTable->setModel(m_model); + connect(ui->dataTable->selectionModel(), &QItemSelectionModel::currentChanged, this, &TableBrowser::selectionChanged); + connect(ui->dataTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this](const QItemSelection&, const QItemSelection&) { + updateInsertDeleteRecordButton(); + + const QModelIndexList& sel = ui->dataTable->selectionModel()->selectedIndexes(); + QString statusMessage; + if (sel.count() > 1) { + int rows = static_cast(ui->dataTable->rowsInSelection().size()); + statusMessage = tr("%n row(s)", "", rows); + int columns = static_cast(ui->dataTable->colsInSelection().size()); + statusMessage += tr(", %n column(s)", "", columns); + + if (sel.count() < Settings::getValue("databrowser", "complete_threshold").toInt()) { + double sum = 0; + double first = m_model->data(sel.first(), Qt::EditRole).toDouble(); + double min = first; + double max = first; + for (const QModelIndex& index : sel) { + double dblData = m_model->data(index, Qt::EditRole).toDouble(); + sum += dblData; + min = std::min(min, dblData); + max = std::max(max, dblData); + } + statusMessage += tr(". Sum: %1; Average: %2; Min: %3; Max: %4").arg(sum).arg(sum/sel.count()).arg(min).arg(max); + } + } + emit statusMessageRequested(statusMessage); + }); + } + + // Delete settings of no-longer existent tables + for (auto it = m_settings.cbegin(); it != m_settings.cend(); ) { + if (!db->getTableByName(it->first)) { + it = m_settings.erase(it); + } else { + ++it; + } + } + + // Retrieve the stored data for this table if there is any. If there are no settings for this table, + // this will insert and return a settings object with default values. + const sqlb::ObjectIdentifier tablename = currentlyBrowsedTableName(); + const BrowseDataTableSettings& storedData = m_settings[tablename]; + + // Set column widths to match contents when no column widths were provided in the stored settings. + // This needs to be done before setting the query because the data is returned asynchronously and + // so this information can be needed any time. + if(storedData.columnWidths.empty()) + m_columnsResized = false; + + // Current table changed + emit currentTableChanged(tablename); + + // Build query and apply settings + applyModelSettings(storedData, buildQuery(storedData, tablename)); + applyViewportSettings(storedData, tablename); + emit updatePlot(ui->dataTable, m_model, &m_settings[tablename], true); +} + +void TableBrowser::clearFilters() +{ + ui->dataTable->filterHeader()->clearFilters(); + ui->editGlobalFilter->clear(); +} + +void TableBrowser::reloadSettings() +{ + ui->dataTable->reloadSettings(); + + ui->browseToolbar->setToolButtonStyle(static_cast(Settings::getValue("General", "toolbarStyleBrowse").toInt())); + m_model->reloadSettings(); +} + +void TableBrowser::setCurrentTable(const sqlb::ObjectIdentifier& name) +{ + int index = ui->comboBrowseTable->findText(QString::fromStdString(name.toDisplayString())); + if(index != -1) + ui->comboBrowseTable->setCurrentIndex(index); +} + +void TableBrowser::clear() +{ + // This function unset the model in the data view. So if no model is set at the moment, + // this indicates that this function has already been called and does not need to + // executed another time. + if (!ui->dataTable->model()) + return; + + // Unset the model + ui->dataTable->setModel(nullptr); + + // Remove any filters, not just the values but the fields too + if(qobject_cast(ui->dataTable->horizontalHeader())) + qobject_cast(ui->dataTable->horizontalHeader())->generateFilters(0); + ui->editGlobalFilter->clear(); +} + +void TableBrowser::updateFilter(size_t column, const QString& value) +{ + // Set minimum width to the vertical header in order to avoid flickering while a filter is being updated. + ui->dataTable->verticalHeader()->setMinimumWidth(ui->dataTable->verticalHeader()->width()); + + // Update the filter in the model and its query + const std::string column_name = model()->headerData(static_cast(column), Qt::Horizontal, Qt::EditRole).toString().toStdString(); + m_model->updateFilter(column_name, value); + + ui->actionClearFilters->setEnabled(m_model->filterCount() > 0 || !ui->editGlobalFilter->text().isEmpty()); + + // Save the new filter settings + BrowseDataTableSettings& settings = m_settings[currentlyBrowsedTableName()]; + if(value.isEmpty()) + { + if(settings.filterValues.erase(column_name) > 0) + emit projectModified(); + } else { + if (settings.filterValues[column_name] != value) { + settings.filterValues[column_name] = value; + emit projectModified(); + } + } +} + +void TableBrowser::addCondFormatFromFilter(size_t column, const QString& value) +{ + QFont font = QFont(Settings::getValue("databrowser", "font").toString()); + font.setPointSize(Settings::getValue("databrowser", "fontsize").toInt()); + + // Create automatically a new conditional format with the next serial background color according to the theme and the regular foreground + // color and font in the settings. + CondFormat newCondFormat(value, QColor(Settings::getValue("databrowser", "reg_fg_colour").toString()), + m_condFormatPalette.nextSerialColor(Palette::appHasDarkTheme()), + font, + CondFormat::AlignLeft, + m_model->encoding()); + addCondFormat(false, column, newCondFormat); +} + +void TableBrowser::addCondFormat(bool isRowIdFormat, size_t column, const CondFormat& newCondFormat) +{ + BrowseDataTableSettings& settings = m_settings[currentlyBrowsedTableName()]; + std::vector& formats = isRowIdFormat ? settings.rowIdFormats[column] : settings.condFormats[column]; + m_model->addCondFormat(isRowIdFormat, column, newCondFormat); + + // Conditionless formats are pushed back and others inserted at the beginning, so they aren't eclipsed. + if (newCondFormat.filter().isEmpty()) + formats.push_back(newCondFormat); + else + formats.insert(formats.begin(), newCondFormat); + + emit projectModified(); +} + +void TableBrowser::clearAllCondFormats(size_t column) +{ + m_model->setCondFormats(false, column, {}); + m_settings[currentlyBrowsedTableName()].condFormats[column].clear(); + emit projectModified(); +} + +void TableBrowser::clearRowIdFormats(const QModelIndex index) +{ + std::vector& rowIdFormats = m_settings[currentlyBrowsedTableName()].rowIdFormats[static_cast(index.column())]; + rowIdFormats.erase(std::remove_if(rowIdFormats.begin(), rowIdFormats.end(), [&](const CondFormat& format) { + return format.filter() == QString("=%1").arg(m_model->data(index.sibling(index.row(), 0)).toString()); + }), rowIdFormats.end()); + m_model->setCondFormats(true, static_cast(index.column()), rowIdFormats); + + emit projectModified(); +} + +void TableBrowser::editCondFormats(size_t column) +{ + CondFormatManager condFormatDialog(m_settings[currentlyBrowsedTableName()].condFormats[column], + m_model->encoding(), this); + condFormatDialog.setWindowTitle(tr("Conditional formats for \"%1\""). + arg(m_model->headerData(static_cast(column), Qt::Horizontal, Qt::EditRole).toString())); + if (condFormatDialog.exec()) { + std::vector condFormatVector = condFormatDialog.getCondFormats(); + m_model->setCondFormats(false, column, condFormatVector); + m_settings[currentlyBrowsedTableName()].condFormats[column] = condFormatVector; + emit projectModified(); + } +} +void TableBrowser::modifySingleFormat(const bool isRowIdFormat, const QString& filter, const QModelIndex refIndex, std::function changeFunction) +{ + const size_t column = static_cast(refIndex.column()); + BrowseDataTableSettings& settings = m_settings[currentlyBrowsedTableName()]; + std::vector& formats = isRowIdFormat ? settings.rowIdFormats[column] : settings.condFormats[column]; + auto it = std::find_if(formats.begin(), formats.end(), [&filter](const CondFormat& format) { + return format.filter() == filter; + }); + if(it != formats.end()) { + changeFunction(*it); + m_model->addCondFormat(isRowIdFormat, column, *it); + } else { + // Create a new conditional format based on the current reference index and then modify it as requested using the passed function. + CondFormat newCondFormat(filter, m_model, refIndex, m_model->encoding()); + changeFunction(newCondFormat); + addCondFormat(isRowIdFormat, column, newCondFormat); + } +} + +void TableBrowser::modifyFormat(std::function changeFunction) +{ + // Modify the conditional formats from entirely selected columns having the current filter value, + // or modify the row-id formats of selected cells, when the selection does not cover entire columns. + const std::unordered_set& columns = ui->dataTable->selectedCols(); + if (columns.size() > 0) { + for (size_t column : columns) { + QString filter; + const std::string column_name = model()->headerData(static_cast(column), Qt::Horizontal, Qt::EditRole).toString().toStdString(); + if (m_settings[currentlyBrowsedTableName()].filterValues.count(column_name) > 0) + filter = m_settings[currentlyBrowsedTableName()].filterValues.at(column_name); + modifySingleFormat(false, filter, currentIndex().sibling(currentIndex().row(), static_cast(column)), changeFunction); + } + } else { + for(const QModelIndex& index : ui->dataTable->selectionModel()->selectedIndexes()) { + const QString filter = QString("=%1").arg(m_model->data(index.sibling(index.row(), 0)).toString()); + modifySingleFormat(true, filter, index, changeFunction); + } + } + emit projectModified(); +} + +void TableBrowser::updateRecordsetLabel() +{ + // Get all the numbers, i.e. the number of the first row and the last row as well as the total number of rows + // Internal row numbers start at 0, but we want to show them starting at 1. + int from = ui->dataTable->verticalHeader()->visualIndexAt(0) + 1; + int total = m_model->rowCount(); + int real_total = m_model->realRowCount(); + int to = from + ui->dataTable->numVisibleRows() - 1; + if(to < 0) + to = 0; + + // Adjust visible rows to contents if necessary, and then take the new visible rows, which might have changed. + if(m_adjustRows) { + for(int i=from-1; i<=to-1; i++) + ui->dataTable->resizeRowToContents(i); + from = ui->dataTable->verticalHeader()->visualIndexAt(0) + 1; + to = from + ui->dataTable->numVisibleRows() - 1; + } + + // Update the validator of the goto row field + gotoValidator->setRange(0, total); + + // When there is no query for this table (i.e. no table is selected), there is no row count query either which in turn means + // that the row count query will never finish. And because of this the row count will be forever unknown. To avoid always showing + // a misleading "determining row count" text in the UI we set the row count status to complete here for empty queries. + auto row_count_available = m_model->rowCountAvailable(); + if(m_model->query().empty()) + row_count_available = SqliteTableModel::RowCount::Complete; + + // Update the label showing the current position + QString txt; + switch(row_count_available) + { + case SqliteTableModel::RowCount::Unknown: + txt = tr("determining row count..."); + break; + case SqliteTableModel::RowCount::Partial: + txt = tr("%L1 - %L2 of >= %L3").arg(from).arg(to).arg(total); + break; + case SqliteTableModel::RowCount::Complete: + txt = tr("%L1 - %L2 of %L3").arg(from).arg(to).arg(real_total); + if (real_total != total) { + txt.append(tr(" (clipped at %L1 rows)").arg(total)); + } + break; + } + ui->labelRecordset->setText(txt); + + // Enable editing only for tables or views with editing unlocked for which the row count is already available + bool is_table_or_unlocked_view = false; + sqlb::ObjectIdentifier current_table = currentlyBrowsedTableName(); + if(!current_table.isEmpty() && !m_model->query().empty()) + { + auto obj = db->getTableByName(current_table); + is_table_or_unlocked_view = obj && ( + (obj->isView() && m_model->hasPseudoPk()) || + (!obj->isView())); + } + enableEditing(m_model->rowCountAvailable() != SqliteTableModel::RowCount::Unknown && is_table_or_unlocked_view); + + // Show filters unless the table is empty + const bool needs_filters = total > 0 || m_model->filterCount() > 0; + FilterTableHeader* header = qobject_cast(ui->dataTable->horizontalHeader()); + if(header) { + if(needs_filters && !header->hasFilters()) { + generateFilters(); + ui->dataTable->adjustSize(); + } else if(!needs_filters && header->hasFilters()) { + ui->dataTable->generateFilters(0, false); + } + } +} + +sqlb::Query TableBrowser::buildQuery(const BrowseDataTableSettings& storedData, const sqlb::ObjectIdentifier& tablename) const +{ + const auto table = db->getTableByName(tablename); + + sqlb::Query query(tablename, table && table->isView()); + + // Construct a query from the retrieved settings + + // Sorting + query.setOrderBy(storedData.sortColumns); + ui->actionClearSorting->setEnabled(storedData.sortColumns.size() > 0); + + // Filters + for(auto it=storedData.filterValues.cbegin();it!=storedData.filterValues.cend();++it) + query.where().insert({it->first, CondFormat::filterToSqlCondition(it->second, m_model->encoding())}); + + // Global filter + for(const auto& f : storedData.globalFilters) + query.globalWhere().push_back(CondFormat::filterToSqlCondition(f, m_model->encoding())); + + // Display formats + bool only_defaults = true; + if(table) + { + // When there is at least one custom display format, we have to set all columns for the query explicitly here + for(size_t i=0; ifields.size(); ++i) + { + QString format = contains(storedData.displayFormats, i+1) ? storedData.displayFormats.at(i+1) : QString(); + if(format.size()) + { + query.selectedColumns().emplace_back(table->fields.at(i).name(), format.toStdString()); + only_defaults = false; + } else { + query.selectedColumns().emplace_back(table->fields.at(i).name(), table->fields.at(i).name()); + } + } + } + if(only_defaults) + query.selectedColumns().clear(); + + // Unlock view editing + query.setRowIdColumn(storedData.unlockViewPk.toStdString()); + + return query; +} + +void TableBrowser::applyModelSettings(const BrowseDataTableSettings& storedData, const sqlb::Query& query) +{ + // Set query which also resets the model + m_model->setQuery(query); + + // Regular conditional formats + for(auto formatIt=storedData.condFormats.cbegin(); formatIt!=storedData.condFormats.cend(); ++formatIt) + m_model->setCondFormats(false, formatIt->first, formatIt->second); + + // Row Id formats + for(auto formatIt=storedData.rowIdFormats.cbegin(); formatIt!=storedData.rowIdFormats.cend(); ++formatIt) + m_model->setCondFormats(true, formatIt->first, formatIt->second); + + // Encoding + m_model->setEncoding(storedData.encoding); +} + +void TableBrowser::applyViewportSettings(const BrowseDataTableSettings& storedData, const sqlb::ObjectIdentifier& tablename) +{ + // Show rowid column. This also takes care of the filters. + showRowidColumn(storedData.showRowid); + + // Enable editing in general and (un)lock view editing depending on the settings + unlockViewEditing(!storedData.unlockViewPk.isEmpty() && storedData.unlockViewPk != "_rowid_", storedData.unlockViewPk); + + // Column hidden status + showAllColumns(); + for(auto hiddenIt=storedData.hiddenColumns.cbegin();hiddenIt!=storedData.hiddenColumns.cend();++hiddenIt) + hideColumns(hiddenIt->first, hiddenIt->second); + + // Column widths + std::map w = storedData.columnWidths; // We're working with a copy here because the map can get modified in the process + for(auto widthIt=w.cbegin();widthIt!=w.cend();++widthIt) + { + if(widthIt->first < ui->dataTable->model()->columnCount()) + ui->dataTable->setColumnWidth(widthIt->first, widthIt->second); + } + m_columnsResized = !w.empty(); + + // Global filters + QString text; + for(const auto& f : storedData.globalFilters) + text += f + " "; + text.chop(1); + ui->editGlobalFilter->setText(text); + + // Show/hide some menu options depending on whether this is a table or a view + const auto table = db->getTableByName(tablename); + if(!table->isView()) + { + // Table + ui->actionUnlockViewEditing->setVisible(false); + ui->actionShowRowidColumn->setVisible(!table->withoutRowidTable()); + } else { + // View + ui->actionUnlockViewEditing->setVisible(true); + ui->actionShowRowidColumn->setVisible(false); + } + + // Frozen columns + freezeColumns(storedData.frozenColumns); +} + +void TableBrowser::enableEditing(bool enable_edit) +{ + // Don't enable anything if this is a read only database + bool edit = enable_edit && !db->readOnly(); + + // Apply settings + ui->dataTable->setEditTriggers(edit ? QAbstractItemView::SelectedClicked | QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed : QAbstractItemView::NoEditTriggers); + updateInsertDeleteRecordButton(); +} + +void TableBrowser::showRowidColumn(bool show) +{ + // Disconnect the resized signal from the horizontal header. Otherwise it's resetting the automatic column widths + disconnect(ui->dataTable->horizontalHeader(), &QHeaderView::sectionResized, this, &TableBrowser::updateColumnWidth); + + // WORKAROUND + // Set the opposite hidden/visible status of what we actually want for the rowid column. This is to work around a Qt bug which + // is present in at least version 5.7.1. The problem is this: when you browse a table/view with n columns, then switch to a table/view + // with less than n columns, you'll be able to resize the first (hidden!) column by resizing the section to the left of the first visible + // column. By doing so the table view gets messed up. But even when not resizing the first hidden column, tab-ing through the fields + // will stop at the not-so-much-hidden rowid column, too. All this can be fixed by this line. I haven't managed to find another workaround + // or way to fix this yet. + ui->dataTable->setColumnHidden(0, show); + + // Show/hide rowid column + ui->dataTable->setColumnHidden(0, !show); + if(show) + ui->dataTable->setColumnWidth(0, ui->dataTable->horizontalHeader()->defaultSectionSize()); + + // Update checked status of the popup menu action + ui->actionShowRowidColumn->setChecked(show); + + // Save settings for this table + sqlb::ObjectIdentifier current_table = currentlyBrowsedTableName(); + if (m_settings[current_table].showRowid != show) { + emit projectModified(); + m_settings[current_table].showRowid = show; + } + + // Update the filter row + generateFilters(); + + // Re-enable signal + connect(ui->dataTable->horizontalHeader(), &QHeaderView::sectionResized, this, &TableBrowser::updateColumnWidth); + + ui->dataTable->update(); +} + +void TableBrowser::freezeColumns(size_t columns) +{ + // Update checked status of the popup menu action + ui->actionFreezeColumns->setChecked(columns != 0); + + // Save settings for this table + sqlb::ObjectIdentifier current_table = currentlyBrowsedTableName(); + if (m_settings[current_table].frozenColumns != columns) { + emit projectModified(); + m_settings[current_table].frozenColumns = columns; + } + + // Apply settings + ui->dataTable->horizontalHeader()->blockSignals(true); + ui->dataTable->setFrozenColumns(columns); + generateFilters(); + ui->dataTable->horizontalHeader()->blockSignals(false); +} + +void TableBrowser::generateFilters() +{ + // Generate a new row of filter line edits + const auto& settings = m_settings[currentlyBrowsedTableName()]; + ui->dataTable->generateFilters(static_cast(m_model->columnCount()), settings.showRowid); + + // Apply the stored filter strings to the new row of line edits + // Set filters blocking signals for this since the filter is already applied to the browse table model + FilterTableHeader* filterHeader = qobject_cast(ui->dataTable->horizontalHeader()); + bool oldState = filterHeader->blockSignals(true); + auto obj = db->getTableByName(currentlyBrowsedTableName()); + for(auto filterIt=settings.filterValues.cbegin();filterIt!=settings.filterValues.cend();++filterIt) + ui->dataTable->setFilter(sqlb::getFieldNumber(obj, filterIt->first) + 1, filterIt->second); + filterHeader->blockSignals(oldState); + + ui->actionClearFilters->setEnabled(m_model->filterCount() > 0 || !ui->editGlobalFilter->text().isEmpty()); +} + +void TableBrowser::unlockViewEditing(bool unlock, QString pk) +{ + sqlb::ObjectIdentifier currentTable = currentlyBrowsedTableName(); + sqlb::TablePtr view = db->getTableByName(currentTable); + + // If this isn't a view just unlock editing and return + if(!view) + { + m_model->setPseudoPk(m_model->pseudoPk()); + enableEditing(true); + return; + } + + // If the view gets unlocked for editing and we don't have a 'primary key' for this view yet, then ask for one + if(unlock && pk.isEmpty()) + { + while(true) + { + bool ok; + + QStringList options; + for(const auto& n : view->fieldNames()) + options.push_back(QString::fromStdString(n)); + + // Ask for a PK + pk = QInputDialog::getItem(this, + qApp->applicationName(), + tr("Please enter a pseudo-primary key in order to enable editing on this view. " + "This should be the name of a unique column in the view."), + options, + 0, + false, + &ok); + + // Cancelled? + if(!ok || pk.isEmpty()) { + ui->actionUnlockViewEditing->setChecked(false); + return; + } + + // Do some basic testing of the input and if the input appears to be good, go on + if(db->executeSQL("SELECT " + sqlb::escapeIdentifier(pk.toStdString()) + " FROM " + currentTable.toString() + " LIMIT 1;", false, true)) + break; + } + } else if(!unlock) { + // Locking the view is done by unsetting the pseudo-primary key + pk = "_rowid_"; + } + + // (De)activate editing + enableEditing(unlock); + m_model->setPseudoPk({pk.toStdString()}); + + // Update checked status of the popup menu action + ui->actionUnlockViewEditing->blockSignals(true); + ui->actionUnlockViewEditing->setChecked(unlock); + ui->actionUnlockViewEditing->blockSignals(false); + + // If the settings didn't change, do not try to reapply them. + // This avoids an infinite mutual recursion. + BrowseDataTableSettings& settings = m_settings[currentTable]; + + if(settings.unlockViewPk != pk) { + // Save settings for this table + settings.unlockViewPk = pk; + + // The filter row might move up one row when we change the query, so we need to regenerate it here + generateFilters(); + + emit projectModified(); + } +} + +void TableBrowser::hideColumns(int column, bool hide) +{ + sqlb::ObjectIdentifier tableName = currentlyBrowsedTableName(); + + // Select columns to (un)hide + std::unordered_set columns; + if(column == -1) + { + if(ui->dataTable->selectedCols().size() == 0) + columns.insert(ui->actionBrowseTableEditDisplayFormat->property("clicked_column").toInt()); + else { + auto cols = ui->dataTable->selectedCols(); + columns.insert(cols.begin(), cols.end()); + } + } else { + columns.insert(column); + } + + // (Un)hide requested column(s) + for(int col : columns) + { + if(col >= ui->dataTable->model()->columnCount()) + continue; + + ui->dataTable->setColumnHidden(col, hide); + if(!hide) + ui->dataTable->setColumnWidth(col, ui->dataTable->horizontalHeader()->defaultSectionSize()); + m_settings[tableName].hiddenColumns[col] = hide; + } + + // check to see if all the columns are hidden + bool allHidden = true; + for(int col = 1; col < ui->dataTable->model()->columnCount(); col++) + { + if(!ui->dataTable->isColumnHidden(col)) + { + allHidden = false; + break; + } + } + + if(allHidden && ui->dataTable->model()->columnCount() > 1) + hideColumns(1, false); + emit projectModified(); +} + +void TableBrowser::showAllColumns() +{ + for(int col = 1; col < ui->dataTable->model()->columnCount(); col++) + { + if(ui->dataTable->isColumnHidden(col)) + hideColumns(col, false); + } +} + +void TableBrowser::updateInsertDeleteRecordButton() +{ + // Update the delete record button to reflect number of selected records + + int rows = 0; + + // If there is no model yet (because e.g. no database file is opened) there is no selection model either. So we need to check for that here + // in order to avoid null pointer dereferences. If no selection model exists we will just continue as if no row is selected because without a + // model you could argue there actually is no row to be selected. + if(ui->dataTable->selectionModel()) + { + const auto & sel = ui->dataTable->selectionModel()->selectedIndexes(); + if(sel.count()) + rows = sel.last().row() - sel.first().row() + 1; + } + + // Enable the insert and delete buttons only if the currently browsed table or view is editable. For the delete button we additionally require + // at least one row to be selected. For the insert button there is an extra rule to disable it when we are browsing a view because inserting + // into a view isn't supported yet. + bool isEditable = m_model->isEditable() && !db->readOnly(); + ui->actionNewRecord->setEnabled(isEditable); + ui->actionDeleteRecord->setEnabled(isEditable && rows != 0); + + if(rows > 1) + ui->actionDeleteRecord->setText(tr("Delete Records")); + else + ui->actionDeleteRecord->setText(tr("Delete Record")); +} + +void TableBrowser::duplicateRecord(int currentRow) +{ + auto row = m_model->dittoRecord(currentRow); + if (row.isValid()) + ui->dataTable->setCurrentIndex(row); + else + QMessageBox::warning(this, qApp->applicationName(), db->lastError()); +} + +void TableBrowser::headerClicked(int logicalindex) +{ + BrowseDataTableSettings& settings = m_settings[currentlyBrowsedTableName()]; + + // Set minimum width to the vertical header in order to avoid flickering when sorting. + ui->dataTable->verticalHeader()->setMinimumWidth(ui->dataTable->verticalHeader()->width()); + + // Get the current list of sort columns + auto& columns = settings.sortColumns; + + // Get the name of the column the user clicked on + std::string column = model()->headerData(logicalindex, Qt::Horizontal, Qt::EditRole).toString().toStdString(); + + // Before sorting, first check if the Control key is pressed. If it is, we want to append this column to the list of sort columns. If it is not, + // we want to sort only by the new column. + if(QApplication::keyboardModifiers().testFlag(Qt::ControlModifier)) + { + // Multi column sorting + + // If the column was control+clicked again, change its sort order. + // If not already in the sort order, add the column as a new sort column to the list. + bool present = false; + for(sqlb::OrderBy& sortedCol : columns) { + if(sortedCol.expr == column) { + sortedCol.direction = (sortedCol.direction == sqlb::OrderBy::Ascending ? sqlb::OrderBy::Descending : sqlb::OrderBy::Ascending); + present = true; + break; + } + } + if(!present) + columns.emplace_back(column, sqlb::OrderBy::Ascending); + } else { + // Single column sorting + + // If we have exactly one sort column and it is the column which was just clicked, change its sort order. + // If not, clear the list of sorting columns and replace it by a single new sort column. + if(columns.size() == 1 && columns.front().expr == column) + { + columns.front().direction = (columns.front().direction == sqlb::OrderBy::Ascending ? sqlb::OrderBy::Descending : sqlb::OrderBy::Ascending); + } else { + columns.clear(); + columns.emplace_back(column, sqlb::OrderBy::Ascending); + } + } + + // Do the actual sorting + ui->dataTable->sortByColumns(columns); + + ui->actionClearSorting->setEnabled(columns.size() > 0); + + // select the first item in the column so the header is bold + // we might try to select the last selected item + ui->dataTable->setCurrentIndex(ui->dataTable->currentIndex().sibling(0, logicalindex)); + + emit updatePlot(ui->dataTable, m_model, &m_settings[currentlyBrowsedTableName()], true); + + emit projectModified(); +} + +void TableBrowser::updateColumnWidth(int section, int /*old_size*/, int new_size) +{ + std::unordered_set selectedCols = ui->dataTable->selectedCols(); + sqlb::ObjectIdentifier tableName = currentlyBrowsedTableName(); + + if (selectedCols.find(static_cast(section)) == selectedCols.end()) + { + if (m_settings[tableName].columnWidths[section] != new_size) { + emit projectModified(); + m_settings[tableName].columnWidths[section] = new_size; + } + } + else + { + ui->dataTable->blockSignals(true); + for(size_t col : selectedCols) + { + ui->dataTable->setColumnWidth(static_cast(col), new_size); + if (m_settings[tableName].columnWidths[static_cast(col)] != new_size) { + emit projectModified(); + m_settings[tableName].columnWidths[static_cast(col)] = new_size; + } + } + ui->dataTable->blockSignals(false); + } +} + +void TableBrowser::showDataColumnPopupMenu(const QPoint& pos) +{ + // Get the index of the column which the user has clicked on and store it in the action. This is sort of hack-ish and it might be the heat in my room + // but I haven't come up with a better solution so far + int logical_index = ui->dataTable->horizontalHeader()->logicalIndexAt(pos); + if(logical_index == -1) // Don't open the popup menu if the user hasn't clicked on a column header + return; + ui->actionBrowseTableEditDisplayFormat->setProperty("clicked_column", logical_index); + + // Calculate the proper position for the context menu and display it + popupHeaderMenu->exec(ui->dataTable->horizontalHeader()->mapToGlobal(pos)); +} + +void TableBrowser::showRecordPopupMenu(const QPoint& pos) +{ + int row = ui->dataTable->verticalHeader()->logicalIndexAt(pos); + if (row == -1) + return; + + QMenu popupRecordMenu(this); + + // "Delete and duplicate records" can only be done on writable objects + if(db->getTableByName(currentlyBrowsedTableName()) && !db->readOnly()) { + + // Select the row if it is not already in the selection. + QModelIndexList rowList = ui->dataTable->selectionModel()->selectedRows(); + bool found = false; + for (const QModelIndex& index : qAsConst(rowList)) { + if (row == index.row()) { + found = true; + break; + } + } + if (!found) + ui->dataTable->selectRow(row); + + rowList = ui->dataTable->selectionModel()->selectedRows(); + + QString duplicateText = rowList.count() > 1 ? tr("Duplicate records") : tr("Duplicate record"); + + QAction* action = new QAction(duplicateText, &popupRecordMenu); + // Set shortcut for documentation purposes (the actual functional shortcut is not set here) + action->setShortcut(QKeySequence(tr("Ctrl+\""))); + popupRecordMenu.addAction(action); + + connect(action, &QAction::triggered, this, [rowList, this]() { + for (const QModelIndex& index : rowList) + duplicateRecord(index.row()); + }); + + QAction* deleteRecordAction = new QAction(QIcon(":icons/delete_record"), ui->actionDeleteRecord->text(), &popupRecordMenu); + popupRecordMenu.addAction(deleteRecordAction); + + connect(deleteRecordAction, &QAction::triggered, this, [&]() { + deleteRecord(); + }); + + popupRecordMenu.addSeparator(); + } + + // "Adjust rows" can be done on any object + QAction* adjustRowHeightAction = new QAction(tr("Adjust rows to contents"), &popupRecordMenu); + adjustRowHeightAction->setCheckable(true); + adjustRowHeightAction->setChecked(m_adjustRows); + popupRecordMenu.addAction(adjustRowHeightAction); + + connect(adjustRowHeightAction, &QAction::toggled, this, [&](bool checked) { + m_adjustRows = checked; + refresh(); + }); + + popupRecordMenu.exec(ui->dataTable->verticalHeader()->mapToGlobal(pos)); +} + +void TableBrowser::addRecord() +{ + int row = m_model->rowCount(); + + // If table has pseudo_pk, then it must be an editable view. Jump straight to inserting by pop-up dialog. + if(!m_model->hasPseudoPk() && m_model->insertRow(row)) + { + selectTableLine(row); + } else { + // Error inserting empty row. + // User has to provide values accomplishing the constraints. Open Add Record Dialog. + insertValues(); + } + updateRecordsetLabel(); +} + +void TableBrowser::insertValues() +{ + std::vector pseudo_pk = m_model->hasPseudoPk() ? m_model->pseudoPk() : std::vector(); + AddRecordDialog dialog(*db, currentlyBrowsedTableName(), this, pseudo_pk); + if (dialog.exec()) + refresh(); +} + +void TableBrowser::deleteRecord() +{ + if(ui->dataTable->selectionModel()->hasSelection()) + { + // If only filter header is selected + if(ui->dataTable->selectionModel()->selectedIndexes().isEmpty()) + return; + + while(ui->dataTable->selectionModel()->hasSelection()) + { + std::set row_set = ui->dataTable->rowsInSelection(); + int first_selected_row = static_cast(*row_set.begin()); + int rows_to_remove = 0; + int previous_row = first_selected_row - 1; + + // Non-contiguous selection: remove only the contiguous + // rows in the selection in each cycle until the entire + // selection has been removed. + for(size_t row : row_set) { + if(previous_row == static_cast(row - 1)) + rows_to_remove++; + else + break; + } + + if(!m_model->removeRows(first_selected_row, rows_to_remove)) + { + QMessageBox::warning(this, QApplication::applicationName(), tr("Error deleting record:\n%1").arg(db->lastError())); + break; + } + } + } else { + QMessageBox::information( this, QApplication::applicationName(), tr("Please select a record first")); + } + updateRecordsetLabel(); +} + +void TableBrowser::navigatePrevious() +{ + int curRow = ui->dataTable->currentIndex().row(); + curRow -= ui->dataTable->numVisibleRows() - 1; + if(curRow < 0) + curRow = 0; + selectTableLine(curRow); +} + +void TableBrowser::navigateNext() +{ + int curRow = ui->dataTable->currentIndex().row(); + curRow += ui->dataTable->numVisibleRows() - 1; + if(curRow >= m_model->rowCount()) + curRow = m_model->rowCount() - 1; + selectTableLine(curRow); +} + +void TableBrowser::navigateBegin() +{ + selectTableLine(0); +} + +void TableBrowser::navigateEnd() +{ + selectTableLine(m_model->rowCount()-1); +} + +void TableBrowser::navigateGoto() +{ + int row = ui->editGoto->text().toInt(); + if(row <= 0) + row = 1; + if(row > m_model->rowCount()) + row = m_model->rowCount(); + + selectTableLine(row - 1); + ui->editGoto->setText(QString::number(row)); +} + +void TableBrowser::selectTableLine(int lineToSelect) +{ + ui->dataTable->selectTableLine(lineToSelect); +} + +void TableBrowser::clearSorting() +{ + // Get the current list of sort columns + auto& columns = m_settings[currentlyBrowsedTableName()].sortColumns; + columns.clear(); + // Set cleared vector of sort-by columns + m_model->sort(columns); + + ui->actionClearSorting->setEnabled(false); +} + +void TableBrowser::editDisplayFormat() +{ + // Get the current table name and fetch its table object, then retrieve the fields of that table and look up the index of the clicked table header + // section using it as the table field array index. Subtract one from the header index to get the column index because in the the first (though hidden) + // column is always the rowid column. Ultimately, get the column name from the column object + sqlb::ObjectIdentifier current_table = currentlyBrowsedTableName(); + size_t field_number = sender()->property("clicked_column").toUInt(); + QString field_name = QString::fromStdString(db->getTableByName(current_table)->fields.at(field_number-1).name()); + + // Get the current display format of the field + QString current_displayformat = m_settings[current_table].displayFormats[field_number]; + + // Open the dialog + ColumnDisplayFormatDialog dialog(*db, current_table, field_name, current_displayformat, this); + if(dialog.exec()) + { + // Set the newly selected display format + QString new_format = dialog.selectedDisplayFormat(); + if(new_format.size()) + m_settings[current_table].displayFormats[field_number] = new_format; + else + m_settings[current_table].displayFormats.erase(field_number); + emit projectModified(); + + // Refresh view + refresh(); + } +} + +void TableBrowser::exportCsvFilteredTable() +{ + ExportDataDialog dialog(*db, ExportDataDialog::ExportFormatCsv, this, m_model->customQuery(false)); + dialog.exec(); +} + +void TableBrowser::exportJsonFilteredTable() +{ + ExportDataDialog dialog(*db, ExportDataDialog::ExportFormatJson, this, m_model->customQuery(false)); + dialog.exec(); +} + +void TableBrowser::saveFilterAsView() +{ + // Save as view a custom query without rowid + emit createView(m_model->customQuery(false)); +} + +void TableBrowser::setTableEncoding(bool forAllTables) +{ + // Get the old encoding + QString encoding = m_model->encoding(); + + // Ask the user for a new encoding + bool ok; + QString question; + QStringList availableCodecs = toStringList(QTextCodec::availableCodecs()); + availableCodecs.removeDuplicates(); + int currentItem = availableCodecs.indexOf(encoding); + + if(forAllTables) + question = tr("Please choose a new encoding for all tables."); + else + question = tr("Please choose a new encoding for this table."); + encoding = QInputDialog::getItem(this, + tr("Set encoding"), + tr("%1\nLeave the field empty for using the database encoding.").arg(question), + availableCodecs, + currentItem, + true, // editable + &ok); + + // Only set the new encoding if the user clicked the OK button + if(ok) + { + // Check if encoding is valid + if(!encoding.isEmpty() && !QTextCodec::codecForName(encoding.toUtf8())) + { + QMessageBox::warning(this, qApp->applicationName(), tr("This encoding is either not valid or not supported.")); + return; + } + + // Set encoding for current table + m_model->setEncoding(encoding); + + // Save encoding for this table + m_settings[currentlyBrowsedTableName()].encoding = encoding; + + // Set default encoding if requested to and change all stored table encodings + if(forAllTables) + { + m_defaultEncoding = encoding; + + for(auto it=m_settings.begin();it!=m_settings.end();++it) + it->second.encoding = encoding; + } + + emit projectModified(); + } +} + +void TableBrowser::setDefaultTableEncoding() +{ + setTableEncoding(true); +} + +void TableBrowser::copyColumnName(){ + sqlb::ObjectIdentifier current_table = currentlyBrowsedTableName(); + int col_index = ui->actionBrowseTableEditDisplayFormat->property("clicked_column").toInt(); + QString field_name = QString::fromStdString(db->getTableByName(current_table)->fields.at(col_index - 1).name()); + + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(field_name); +} + +void TableBrowser::jumpToRow(const sqlb::ObjectIdentifier& table, std::string column, const QByteArray& value) +{ + // First check if table exists + sqlb::TablePtr obj = db->getTableByName(table); + if(!obj) + return; + + // If no column name is set, assume the primary key is meant + if(!column.size()) + column = obj->primaryKeyColumns().front().name(); + + // If column doesn't exist don't do anything + auto column_it = sqlb::findField(obj, column); + if(column_it == obj->fields.end()) + return; + + // Jump to table + setCurrentTable(table); + + // Set filter + m_settings[table].filterValues[column_it->name()] = value; + refresh(); +} + +static QString replaceInValue(QString value, const QString& find, const QString& replace, Qt::MatchFlags flags) +{ + // Helper function which replaces a string in another string by a third string. It uses regular expressions if told so. +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) + auto match_flag = Qt::MatchRegExp; +#else + auto match_flag = Qt::MatchRegularExpression; +#endif + if(flags.testFlag(match_flag)) + { + QRegularExpression reg_exp(find, (flags.testFlag(Qt::MatchCaseSensitive) ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption)); + if(!flags.testFlag(Qt::MatchContains)) + { +#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0) + reg_exp.setPattern("\\A(" + reg_exp.pattern() + ")\\Z"); +#else + reg_exp.setPattern(QRegularExpression::anchoredPattern(reg_exp.pattern())); +#endif + } + + return value.replace(reg_exp, replace); + } else { + return value.replace(find, replace, flags.testFlag(Qt::MatchCaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive); + } +} + +void TableBrowser::find(const QString& expr, bool forward, bool include_first, ReplaceMode replace) +{ + // Reset the colour of the line edit, assuming there is no error. + ui->editFindExpression->setStyleSheet(""); + + // You are not allowed to search for an empty string + if(expr.isEmpty()) + return; + + // Get the cell from which the search should be started. If there is a selected cell, use that. If there is no selected cell, start at the first cell. + QModelIndex start; + if(ui->dataTable->selectionModel()->hasSelection()) + start = ui->dataTable->selectionModel()->selectedIndexes().front(); + else + start = m_model->index(0, 0); + + // Prepare the match flags with all the search settings + Qt::MatchFlags flags = Qt::MatchWrap; + + if(ui->checkFindCaseSensitive->isChecked()) + flags |= Qt::MatchCaseSensitive; + + if(ui->checkFindWholeCell->isChecked()) + flags |= Qt::MatchFixedString; + else + flags |= Qt::MatchContains; + +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) + auto match_flag = Qt::MatchRegExp; +#else + auto match_flag = Qt::MatchRegularExpression; +#endif + if(ui->checkFindRegEx->isChecked()) + flags |= match_flag; + + // Prepare list of columns to search in. We only search in non-hidden rows + std::vector column_list; + sqlb::ObjectIdentifier tableName = currentlyBrowsedTableName(); + if(m_settings[tableName].showRowid) + column_list.push_back(0); + for(int i=1;icolumnCount();i++) + { + if(contains(m_settings[tableName].hiddenColumns, i) == false) + column_list.push_back(i); + else if(m_settings[tableName].hiddenColumns[i] == false) + column_list.push_back(i); + } + + // Are we only searching for text or are we supposed to replace text? + switch(replace) + { + case ReplaceMode::NoReplace: { + // Perform the actual search using the model class + const auto match = m_model->nextMatch(start, column_list, expr, flags, !forward, include_first); + + // Select the next match if we found one + if(match.isValid()) + ui->dataTable->setCurrentIndex(match); + + // Make the expression control red if no results were found + if(!match.isValid()) + ui->editFindExpression->setStyleSheet("QLineEdit {color: white; background-color: rgb(255, 102, 102)}"); + } break; + case ReplaceMode::ReplaceNext: { + // Find the next match + const auto match = m_model->nextMatch(start, column_list, expr, flags, !forward, include_first); + + // If there was a match, perform the replacement on the cell and select it + if(match.isValid()) + { + m_model->setData(match, replaceInValue(match.data(Qt::EditRole).toString(), expr, ui->editReplaceExpression->text(), flags)); + ui->dataTable->setCurrentIndex(match); + } + + // Make the expression control red if no results were found + if(!match.isValid()) + ui->editFindExpression->setStyleSheet("QLineEdit {color: white; background-color: rgb(255, 102, 102)}"); + } break; + case ReplaceMode::ReplaceAll: { + // Find all matches + std::set all_matches; + while(true) + { + // Find the next match + const auto match = m_model->nextMatch(start, column_list, expr, flags, !forward, include_first); + + // If there was a match, perform the replacement and continue from that position. If there was no match, stop looking for other matches. + // Additionally, keep track of all the matches so far in order to avoid running over them again indefinitely, e.g. when replacing "1" by "10". + if(match.isValid() && all_matches.find(match) == all_matches.end()) + { + all_matches.insert(match); + m_model->setData(match, replaceInValue(match.data(Qt::EditRole).toString(), expr, ui->editReplaceExpression->text(), flags)); + + // Start searching from the last match onwards in order to not search through the same cells over and over again. + start = match; + include_first = false; + } else { + break; + } + } + + // Make the expression control red if no results were found + if(!all_matches.empty()) + QMessageBox::information(this, qApp->applicationName(), tr("%1 replacement(s) made.").arg(all_matches.size())); + else + ui->editFindExpression->setStyleSheet("QLineEdit {color: white; background-color: rgb(255, 102, 102)}"); + } break; + } +} + +void TableBrowser::fetchedData() +{ + updateRecordsetLabel(); + + // Don't resize the columns more than once to fit their contents. This is necessary because the finishedFetch signal of the model + // is emitted for each loaded prefetch block and we want to avoid column resizes while scrolling down. + if(m_columnsResized) + return; + m_columnsResized = true; + + if (m_settings[currentlyBrowsedTableName()].columnWidths.empty()) { + // Set column widths according to their contents but make sure they don't exceed a certain size + ui->dataTable->resizeColumnsToContents(); + for(int i = 0; i < m_model->columnCount(); i++) + { + if(ui->dataTable->columnWidth(i) > 300) + ui->dataTable->setColumnWidth(i, 300); + } + } +} diff --git a/src/TableBrowser.h b/src/TableBrowser.h new file mode 100644 index 000000000..2d8aad3c4 --- /dev/null +++ b/src/TableBrowser.h @@ -0,0 +1,183 @@ +#ifndef TABLEBROWSER_H +#define TABLEBROWSER_H + +#include "CondFormat.h" +#include "PlotDock.h" +#include "sql/Query.h" + +#include +#include + +#include +#include +#include +#include + +class DBBrowserDB; +class ExtendedTableWidget; +class SqliteTableModel; + +class QAbstractItemModel; +class QIntValidator; + +namespace Ui { +class TableBrowser; +} + +struct BrowseDataTableSettings +{ + using CondFormatMap = std::map>; + std::vector sortColumns; + std::map columnWidths; + std::map filterValues; + CondFormatMap condFormats; + CondFormatMap rowIdFormats; + std::map displayFormats; + bool showRowid; + QString encoding; + QString plotXAxis; + std::vector> plotYAxes; + QString unlockViewPk; + std::map hiddenColumns; + std::vector globalFilters; + size_t frozenColumns; + + BrowseDataTableSettings() : + showRowid(false), + plotYAxes({std::map(), std::map()}), + unlockViewPk("_rowid_"), + frozenColumns(0) + { + } +}; + +class TableBrowser : public QWidget +{ + Q_OBJECT + +public: + explicit TableBrowser(DBBrowserDB* _db, QWidget* parent = nullptr); + ~TableBrowser() override; + + void reset(); + static void resetSharedSettings(); + + sqlb::ObjectIdentifier currentlyBrowsedTableName() const; + + static std::map allSettings() { return m_settings; } + static BrowseDataTableSettings& settings(const sqlb::ObjectIdentifier& object); + static void setSettings(const sqlb::ObjectIdentifier& table, const BrowseDataTableSettings& table_settings); + + void setStructure(QAbstractItemModel* model, const sqlb::ObjectIdentifier& old_table = sqlb::ObjectIdentifier{}); + + SqliteTableModel* model() { return m_model; } + + QModelIndex currentIndex() const; + + static void setDefaultEncoding(const QString& encoding) { m_defaultEncoding = encoding; } + static QString defaultEncoding() { return m_defaultEncoding; } + +public slots: + void setEnabled(bool enable); + void refresh(); + void clearFilters(); + void reloadSettings(); + void setCurrentTable(const sqlb::ObjectIdentifier& name); + void updateRecordsetLabel(); + void jumpToRow(const sqlb::ObjectIdentifier& table, std::string column, const QByteArray& value); + +signals: + void projectModified(); + void selectionChanged(QModelIndex index); + void selectionChangedByDoubleClick(QModelIndex index); + void statusMessageRequested(QString message); + void updatePlot(ExtendedTableWidget* tableWidget, SqliteTableModel* model, BrowseDataTableSettings* settings, bool keepOrResetSelection); + void createView(std::string sql); + void requestFileOpen(QString file); + void currentTableChanged(sqlb::ObjectIdentifier table); + void foreignKeyClicked(sqlb::ObjectIdentifier table, std::string column, QByteArray value); + void dataAboutToBeEdited(const QModelIndex& index); + void prepareForFilter(); + void newDockRequested(); + +private slots: + void clear(); + void updateFilter(size_t column, const QString& value); + void addCondFormatFromFilter(size_t column, const QString& value); + void addCondFormat(bool isRowIdFormat, size_t column, const CondFormat& newCondFormat); + void clearAllCondFormats(size_t column); + void clearRowIdFormats(const QModelIndex index); + void editCondFormats(size_t column); + void enableEditing(bool enable_edit); + void showRowidColumn(bool show); + void freezeColumns(size_t columns); + void unlockViewEditing(bool unlock, QString pk = QString()); + void hideColumns(int column = -1, bool hide = true); + void showAllColumns(); + void updateInsertDeleteRecordButton(); + void duplicateRecord(int currentRow); + void headerClicked(int logicalindex); + void updateColumnWidth(int section, int /*old_size*/, int new_size); + void showDataColumnPopupMenu(const QPoint& pos); + void showRecordPopupMenu(const QPoint& pos); + void addRecord(); + void insertValues(); + void deleteRecord(); + void navigatePrevious(); + void navigateNext(); + void navigateBegin(); + void navigateEnd(); + void navigateGoto(); + void selectTableLine(int lineToSelect); + void clearSorting(); + void editDisplayFormat(); + void exportCsvFilteredTable(); + void exportJsonFilteredTable(); + void saveFilterAsView(); + void setTableEncoding(bool forAllTables = false); + void setDefaultTableEncoding(); + void copyColumnName(); + void fetchedData(); + +private: + enum class ReplaceMode + { + NoReplace, + ReplaceNext, + ReplaceAll, + }; + void find(const QString& expr, bool forward, bool include_first = false, ReplaceMode replace = ReplaceMode::NoReplace); + +private: + Ui::TableBrowser* ui; + QIntValidator* gotoValidator; + QMenu* popupNewRecordMenu; + QMenu* popupSaveFilterAsMenu; + QMenu* popupHeaderMenu; + + DBBrowserDB* db; + + QAbstractItemModel* dbStructureModel; + + /// the table model used in the "Browse Data" page (re-used and + /// re-initialized when switching to another table) + SqliteTableModel* m_model; + + static std::map m_settings; // This is static, so settings are shared between instances + static QString m_defaultEncoding; + + Palette m_condFormatPalette; + bool m_adjustRows; + bool m_columnsResized; + + void modifySingleFormat(const bool isRowIdFormat, const QString& filter, const QModelIndex refIndex, + std::function changeFunction); + void modifyFormat(std::function changeFunction); + + sqlb::Query buildQuery(const BrowseDataTableSettings& storedData, const sqlb::ObjectIdentifier& tablename) const; + void applyModelSettings(const BrowseDataTableSettings& storedData, const sqlb::Query& query); + void applyViewportSettings(const BrowseDataTableSettings& storedData, const sqlb::ObjectIdentifier& tablename); + void generateFilters(); +}; + +#endif diff --git a/src/TableBrowser.ui b/src/TableBrowser.ui new file mode 100644 index 000000000..0d7e5dfee --- /dev/null +++ b/src/TableBrowser.ui @@ -0,0 +1,1565 @@ + + + TableBrowser + + + + 0 + 0 + 695 + 400 + + + + Browse Data + + + + 1 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 2 + + + 2 + + + + + &Table: + + + comboBrowseTable + + + + + + + + 150 + 0 + + + + Select a table to browse data + + + Use this list to select a table to be displayed in the database view + + + 30 + + + QComboBox::AdjustToContents + + + + + + + Qt::ToolButtonIconOnly + + + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::MinimumExpanding + + + + 0 + 20 + + + + + + + + + + + 5 + + + 2 + + + 0 + + + 2 + + + 0 + + + + + + + + + 50 + 16777215 + + + + 1 + + + + + + + Qt::ToolButtonIconOnly + + + + + + + + + + + + + + + + + + + + + + + + true + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::DragDrop + + + Qt::CopyAction + + + QAbstractItemView::ExtendedSelection + + + + + + + + 16777215 + 62 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + + + + 3 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::DefaultContextMenu + + + Text pattern to find considering the checks in this frame + + + Find in table + + + true + + + + + + + Find previous match [Shift+F3] + + + Find previous match with wrapping + + + + :/icons/up:/icons/up + + + Shift+F3 + + + + + + + Find next match [Enter, F3] + + + Find next match with wrapping + + + + :/icons/down:/icons/down + + + F3 + + + + + + + The found pattern must match in letter case + + + Case Sensitive + + + + + + + The found pattern must be a whole word + + + Whole Cell + + + + + + + Interpret search pattern as a regular expression + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + Regular Expression + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Close Find Bar + + + Close Find Bar + + + + :/icons/close:/icons/close + + + true + + + + + + + + + + + 3 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::DefaultContextMenu + + + Text to replace with + + + Replace with + + + true + + + + + + + Replace next match + + + Replace + + + + + + + Replace all matches + + + Replace all + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + 2 + + + 2 + + + 2 + + + 2 + + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + + + |< + + + + :/icons/resultset_first:/icons/resultset_first + + + + + + + Scroll one page upwards + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + + + < + + + + :/icons/resultset_previous:/icons/resultset_previous + + + + + + + 0 - 0 of 0 + + + + + + + Scroll one page downwards + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + + + > + + + + :/icons/run:/icons/run + + + + + + + Scroll to the end + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + + + >| + + + + :/icons/run_line:/icons/run_line + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + + + Go to: + + + + + + + Enter record number to browse + + + Type a record number in this area and click the Go to: button to display the record in the database view + + + 1 + + + + + + + + + true + + + Show rowid column + + + Toggle the visibility of the rowid column + + + + + true + + + Unlock view editing + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + + + + + Edit display format + + + Edit the display format of the data in this column + + + + + + :/icons/add_record:/icons/add_record + + + New Record + + + Insert a new record in the current table + + + Insert a new record in the current table + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + + + + + + :/icons/delete_record:/icons/delete_record + + + Delete Record + + + Delete the current record + + + This button deletes the record or records currently selected in the table + + + This button deletes the record or records currently selected in the table + + + + + + :/icons/add_record:/icons/add_record + + + New Record + + + Insert new record using default values in browsed table + + + Insert new record using default values in browsed table + + + + + Insert Values... + + + Open a dialog for inserting values in a new record + + + Open a dialog for inserting values in a new record + + + + + Export to &CSV + + + Export the filtered data to CSV + + + Export the filtered data to CSV + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + + + + + Export to &JSON + + + Export the filtered data to JSON + + + Export the filtered data to JSON + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + + + + + Save as &view + + + Save the current filter, sort column and display formats as a view + + + Save the current filter, sort column and display formats as a view + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + + + + + + :/icons/save_table:/icons/save_table + + + Save Table As... + + + Save the table as currently displayed + + + Save the table as currently displayed + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + + + + + Hide column(s) + + + Hide selected column(s) + + + + + Show all columns + + + Show all columns that were hidden + + + + + Set encoding + + + Change the encoding of the text in the table cells + + + + + Set encoding for all tables + + + Change the default encoding assumed for all tables in the database + + + + + Copy column name + + + Copy the database table column name to your clipboard + + + + + + :/icons/clear_filters:/icons/clear_filters + + + Clear Filters + + + Clear all filters + + + This button clears all the filters set in the header input fields for the currently browsed table. + + + This button clears all the filters set in the header input fields for the currently browsed table. + + + + + + :/icons/clear_sorting:/icons/clear_sorting + + + Clear Sorting + + + Reset the order of rows to the default + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + + + + + + :/icons/print:/icons/print + + + Print + + + Print currently browsed table data + + + + + + Print currently browsed table data. Print selection if more than one cell is selected. + + + Ctrl+P + + + Qt::WidgetShortcut + + + + + + :/icons/new_tab:/icons/new_tab + + + New Data Browser + + + Add a new docked Data Browser + + + Add a new docked Data Browser + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + + + + + + :/icons/refresh:/icons/refresh + + + Refresh + + + Refresh the data in the selected table + + + This button refreshes the data in the currently selected table. + + + F5 + + + Qt::WidgetShortcut + + + + + true + + + + :/icons/find:/icons/find + + + Find in cells + + + Open the find tool bar which allows you to search for values in the table view below. + + + + + true + + + + :/icons/text_bold:/icons/text_bold + + + Bold + + + Bold + + + Ctrl+B + + + + + true + + + + :/icons/text_italic:/icons/text_italic + + + Italic + + + Italic + + + + + true + + + + :/icons/text_underline:/icons/text_underline + + + Underline + + + Underline + + + Ctrl+U + + + + + true + + + + :/icons/text_align_right:/icons/text_align_right + + + Align Right + + + Align Right + + + + + true + + + + :/icons/text_align_left:/icons/text_align_left + + + Align Left + + + Align Left + + + + + true + + + + :/icons/text_align_center:/icons/text_align_center + + + Center Horizontally + + + Center Horizontally + + + + + true + + + + :/icons/text_align_justify:/icons/text_align_justify + + + Justify + + + Justify + + + + + + :/icons/edit_cond_formats:/icons/edit_cond_formats + + + Edit Conditional Formats... + + + Edit Conditional Formats... + + + Edit conditional formats for the current column + + + + + + :/icons/clear_cond_formats:/icons/clear_cond_formats + + + Clear Format + + + Clear All Formats + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + + + + + + :/icons/foreground_color:/icons/foreground_color + + + Font Color + + + Font Color + + + + + + :/icons/background_color:/icons/background_color + + + Background Color + + + Background Color + + + + + true + + + + :/icons/cond_formats:/icons/cond_formats + + + Toggle Format Toolbar + + + Show/hide format toolbar + + + This button shows or hides the formatting toolbar of the Data Browser + + + This button shows or hides the formatting toolbar of the Data Browser + + + + + Select column + + + Ctrl+Space + + + + + true + + + + :/icons/text_replace:/icons/text_replace + + + Replace + + + Replace text in cells + + + + + true + + + Freeze columns + + + Make all columns from the first column up to this column not move when scrolling horizontally + + + + + + ExtendedTableWidget + QTableWidget +
ExtendedTableWidget.h
+ + foreignKeyClicked(sqlb::ObjectIdentifier,QString,QByteArray) + +
+ + FilterLineEdit + QLineEdit +
FilterLineEdit.h
+
+
+ + comboBrowseTable + editGlobalFilter + fontComboBox + fontSizeBox + dataTable + editFindExpression + editReplaceExpression + buttonFindPrevious + buttonFindNext + checkFindCaseSensitive + checkFindWholeCell + checkFindRegEx + buttonFindClose + buttonReplaceNext + buttonReplaceAll + buttonBegin + buttonPrevious + buttonNext + buttonEnd + buttonGoto + editGoto + + + + + + + comboBrowseTable + activated(int) + TableBrowser + refresh() + + + 159 + 31 + + + 399 + 299 + + + + + buttonPrevious + clicked() + TableBrowser + navigatePrevious() + + + 55 + 395 + + + 399 + 299 + + + + + buttonNext + clicked() + TableBrowser + navigateNext() + + + 140 + 395 + + + 399 + 299 + + + + + buttonGoto + clicked() + TableBrowser + navigateGoto() + + + 452 + 397 + + + 399 + 299 + + + + + editGoto + returnPressed() + TableBrowser + navigateGoto() + + + 648 + 397 + + + 399 + 299 + + + + + buttonEnd + clicked() + TableBrowser + navigateEnd() + + + 170 + 395 + + + 499 + 314 + + + + + buttonBegin + clicked() + TableBrowser + navigateBegin() + + + 25 + 395 + + + 499 + 314 + + + + + actionShowRowidColumn + triggered(bool) + TableBrowser + showRowidColumn(bool) + + + -1 + -1 + + + 518 + 314 + + + + + actionUnlockViewEditing + toggled(bool) + TableBrowser + unlockViewEditing(bool) + + + -1 + -1 + + + 518 + 314 + + + + + actionBrowseTableEditDisplayFormat + triggered() + TableBrowser + editDisplayFormat() + + + -1 + -1 + + + 518 + 314 + + + + + actionNewRecord + triggered() + TableBrowser + addRecord() + + + -1 + -1 + + + 518 + 314 + + + + + actionDeleteRecord + triggered() + TableBrowser + deleteRecord() + + + -1 + -1 + + + 399 + 299 + + + + + newRecordAction + triggered() + TableBrowser + addRecord() + + + -1 + -1 + + + 518 + 314 + + + + + insertValuesAction + triggered() + TableBrowser + insertValues() + + + -1 + -1 + + + 20 + 20 + + + + + actionFilteredTableExportCsv + triggered() + TableBrowser + exportCsvFilteredTable() + + + -1 + -1 + + + 518 + 314 + + + + + actionFilteredTableExportJson + triggered() + TableBrowser + exportJsonFilteredTable() + + + -1 + -1 + + + 518 + 314 + + + + + actionFilterSaveAsView + triggered() + TableBrowser + saveFilterAsView() + + + -1 + -1 + + + 518 + 314 + + + + + actionSetTableEncoding + triggered() + TableBrowser + setTableEncoding() + + + -1 + -1 + + + 518 + 314 + + + + + actionCopyColumnName + triggered() + TableBrowser + copyColumnName() + + + -1 + -1 + + + 518 + 314 + + + + + actionSetAllTablesEncoding + triggered() + TableBrowser + setDefaultTableEncoding() + + + -1 + -1 + + + 518 + 314 + + + + + actionHideColumns + triggered() + TableBrowser + hideColumns() + + + -1 + -1 + + + 518 + 314 + + + + + actionPrintTable + triggered() + dataTable + openPrintDialog() + + + -1 + -1 + + + 326 + 291 + + + + + actionClearFilters + triggered() + TableBrowser + clearFilters() + + + -1 + -1 + + + -1 + -1 + + + + + actionClearSorting + triggered() + TableBrowser + clearSorting() + + + -1 + -1 + + + -1 + -1 + + + + + actionShowAllColumns + triggered() + TableBrowser + showAllColumns() + + + -1 + -1 + + + -1 + -1 + + + + + + refresh() + selectionChanged(QModelIndex) + navigatePrevious() + navigateNext() + navigateBegin() + navigateEnd() + navigateGoto() + showRowidColumn(bool) + unlockViewEditing(bool) + editDisplayFormat() + addRecord() + deleteRecord() + insertValues() + exportCsvFilteredTable + exportJsonFilteredTable + saveFilterAsView + setDefaultTableEncoding() + hideColumns() + setTableEncoding() + clearFilters() + clearSorting() + showAllColumns() + +
diff --git a/src/TableBrowserDock.cpp b/src/TableBrowserDock.cpp new file mode 100644 index 000000000..0ea947200 --- /dev/null +++ b/src/TableBrowserDock.cpp @@ -0,0 +1,108 @@ +#include +#include +#include +#include + +#include "TableBrowser.h" +#include "TableBrowserDock.h" +#include "MainWindow.h" + +TableBrowserDock::TableBrowserDock(QWidget* parent, MainWindow* mainWindow) + : QDockWidget(parent), + main_window(mainWindow), + browser(new TableBrowser(&mainWindow->db, this)) +{ + // Set context menu + setContextMenuPolicy(Qt::CustomContextMenu); + + // Normally dock widgets are not deleted when they are closed. Make sure to delete these + // because they can consume a lot of memory and we would need to figure out if they are + // visible whenever we loop over them. + setAttribute(Qt::WA_DeleteOnClose, true); + + // Set object name + static unsigned int counter = 0; + setObjectName("dockBrowse" + QString::number(++counter)); + + // Connect dock signals + connect(this, &TableBrowserDock::customContextMenuRequested, this, &TableBrowserDock::showContextMenuTableBrowserTabBar); + + // Connect browser signals + connect(browser, &TableBrowser::currentTableChanged, this, [this](const sqlb::ObjectIdentifier& table) { + // Only update dock name when no custom name was set + if(!property("custom_title").toBool()) + setWindowTitle(QString::fromStdString(table.toDisplayString())); + }); + + connect(browser, &TableBrowser::newDockRequested, this, &TableBrowserDock::newDockRequested); + + // Update view + browser->refresh(); + + // Set browser widget + setWidget(browser); +} + +void TableBrowserDock::closeEvent(QCloseEvent*) +{ + emit closed(); +} + +void TableBrowserDock::setFocusStyle(bool on) +{ + // Highlight title bar when dock widget is active + if(on) + setStyleSheet(QStringLiteral( + "QDockWidget::title {" + "background:palette(AlternateBase);" + "text-align: center;" + "border-bottom: 2px solid palette(highlight);" + "}")); + else + setStyleSheet(QStringLiteral( + "QDockWidget::title {" + "text-align: center;" + "}")); +} + +void TableBrowserDock::showContextMenuTableBrowserTabBar(const QPoint& pos) +{ + // Prepare all menu actions + QAction* actionNewDock = new QAction(this); + actionNewDock->setText(tr("New Data Browser")); + connect(actionNewDock, &QAction::triggered, this, &TableBrowserDock::newDockRequested); + + QAction* actionRename = new QAction(this); + actionRename->setText(tr("Rename Data Browser")); + connect(actionRename, &QAction::triggered, this, [this]() { + renameTableBrowserTab(); + }); + + QAction* actionClose = new QAction(this); + actionClose->setText(tr("Close Data Browser")); + connect(actionClose, &QAction::triggered, this, [this]() { + deleteLater(); + }); + + // Show menu + QMenu* menuTabs = new QMenu(this); + menuTabs->addAction(actionNewDock); + menuTabs->addAction(actionRename); + menuTabs->addAction(actionClose); + menuTabs->exec(mapToGlobal(pos)); +} + +void TableBrowserDock::renameTableBrowserTab() +{ + QString new_name = QInputDialog::getText(this, + qApp->applicationName(), + tr("Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut."), + QLineEdit::EchoMode::Normal, + windowTitle()); + + if(!new_name.isNull()) // Don't do anything if the Cancel button was clicked + { + setWindowTitle(new_name); + setProperty("custom_title", true); + } +} diff --git a/src/TableBrowserDock.h b/src/TableBrowserDock.h new file mode 100644 index 000000000..c6bb1d70e --- /dev/null +++ b/src/TableBrowserDock.h @@ -0,0 +1,34 @@ +#ifndef TABLEBROWSERDOCK_H +#define TABLEBROWSERDOCK_H + +#include + +class MainWindow; +class TableBrowser; + +class TableBrowserDock : public QDockWidget +{ + Q_OBJECT + +public: + explicit TableBrowserDock(QWidget* parent, MainWindow* mainWindow); + void setFocusStyle(bool on); + + TableBrowser* tableBrowser() { return browser; } + +signals: + void closed(); + void newDockRequested(); + +protected: + void closeEvent(QCloseEvent* event) override; + +private: + MainWindow* main_window; + TableBrowser* browser; + + void showContextMenuTableBrowserTabBar(const QPoint& pos); + void renameTableBrowserTab(); +}; + +#endif diff --git a/src/VacuumDialog.cpp b/src/VacuumDialog.cpp index 766bea3d0..d7785a74a 100644 --- a/src/VacuumDialog.cpp +++ b/src/VacuumDialog.cpp @@ -15,20 +15,17 @@ VacuumDialog::VacuumDialog(DBBrowserDB* _db, QWidget* parent) : // Show warning if DB is dirty ui->labelSavepointWarning->setVisible(db->getDirty()); - // Populate list of objects to compact - QList objects = db->objMap.values("table"); - objects.append(db->objMap.values("index")); - for(QList::const_iterator i=objects.constBegin();i!=objects.constEnd();++i) + // Populate list of objects to compact. We just support vacuuming the different schemas here. + for(const auto& it : db->schemata) { - QTreeWidgetItem* item = new QTreeWidgetItem(ui->treeSelectedObjects); - item->setText(0, (*i).getname()); - item->setIcon(0, QIcon(QString(":icons/%1").arg((*i).gettype()))); - ui->treeSelectedObjects->addTopLevelItem(item); + QTreeWidgetItem* item = new QTreeWidgetItem(ui->treeDatabases); + item->setText(0, QString::fromStdString(it.first)); + item->setIcon(0, QIcon(QString(":icons/database"))); + ui->treeDatabases->addTopLevelItem(item); } - // Sort objects and select them all - ui->treeSelectedObjects->sortByColumn(0, Qt::AscendingOrder); - ui->treeSelectedObjects->selectAll(); + // Select the first item which should always be the main schema + ui->treeDatabases->setCurrentItem(ui->treeDatabases->topLevelItem(0)); } VacuumDialog::~VacuumDialog() @@ -38,7 +35,7 @@ VacuumDialog::~VacuumDialog() void VacuumDialog::accept() { - if(ui->treeSelectedObjects->selectedItems().count() == 0) + if(ui->treeDatabases->selectedItems().count() == 0) return QDialog::reject(); QApplication::setOverrideCursor(Qt::WaitCursor); @@ -46,17 +43,10 @@ void VacuumDialog::accept() // Commit all changes first db->releaseAllSavepoints(); - // All items selected? - if(ui->treeSelectedObjects->selectedItems().count() == ui->treeSelectedObjects->topLevelItemCount()) - { - // Yes, so just execute a simple vacuum command for all objects - db->executeSQL("VACUUM;", false); - } else { - // No, so execute a vacuum command for each selected object individually - QList selection = ui->treeSelectedObjects->selectedItems(); - foreach(QTreeWidgetItem* item, selection) - db->executeSQL(QString("VACUUM %1;").arg(sqlb::escapeIdentifier(item->text(0))), false); - } + // Loop through all selected databases and vacuum them individually + const QList selection = ui->treeDatabases->selectedItems(); + for(const QTreeWidgetItem* item : selection) + db->executeSQL("VACUUM " + sqlb::escapeIdentifier(item->text(0).toStdString()), false); QApplication::restoreOverrideCursor(); QDialog::accept(); diff --git a/src/VacuumDialog.h b/src/VacuumDialog.h index 7ba8cba73..324838813 100644 --- a/src/VacuumDialog.h +++ b/src/VacuumDialog.h @@ -14,15 +14,15 @@ class VacuumDialog : public QDialog Q_OBJECT public: - explicit VacuumDialog(DBBrowserDB* _db, QWidget* parent = 0); - ~VacuumDialog(); + explicit VacuumDialog(DBBrowserDB* _db, QWidget* parent = nullptr); + ~VacuumDialog() override; private: Ui::VacuumDialog* ui; DBBrowserDB* db; protected slots: - virtual void accept(); + void accept() override; }; #endif diff --git a/src/VacuumDialog.ui b/src/VacuumDialog.ui index 81f63b95a..e1bf21546 100644 --- a/src/VacuumDialog.ui +++ b/src/VacuumDialog.ui @@ -23,7 +23,7 @@
- Warning: Compacting the database will commit all changes you made. + Warning: Compacting the database will commit all of your changes. true @@ -36,15 +36,15 @@ - Please select the objects to compact: + Please select the databases to co&mpact: - treeSelectedObjects + treeDatabases - + QAbstractItemView::NoEditTriggers @@ -86,7 +86,7 @@ - treeSelectedObjects + treeDatabases buttonBox diff --git a/src/app.plist b/src/app.plist index d4f66e7ef..e8a024297 100644 --- a/src/app.plist +++ b/src/app.plist @@ -10,6 +10,9 @@ CFBundleTypeExtensions db + db3 + sqlite + sqlite3 CFBundleTypeName Database Document @@ -52,7 +55,7 @@ CFBundleExecutable @EXECUTABLE@ CFBundleGetInfoString - DB Browser for SQLite + 3.13.99 CFBundleIconFile @ICON@ CFBundleIdentifier @@ -64,14 +67,16 @@ CFBundlePackageType APPL CFBundleShortVersionString - 3.8.99 + 3.13.99 CFBundleSignature SqLB CFBundleVersion - 3.8.99 + 3.13.99 NSPrincipalClass NSApplication NSHighResolutionCapable + NSSupportsAutomaticGraphicsSwitching + diff --git a/src/csvparser.cpp b/src/csvparser.cpp index 414da0abe..e2433ad08 100644 --- a/src/csvparser.cpp +++ b/src/csvparser.cpp @@ -1,16 +1,25 @@ #include "csvparser.h" +#include #include -#include -CSVParser::CSVParser(bool trimfields, const QChar& fieldseparator, const QChar& quotechar) +CSVParser::CSVParser(bool trimfields, char32_t fieldseparator, char32_t quotechar) : m_bTrimFields(trimfields) - , m_cFieldSeparator(fieldseparator) - , m_cQuoteChar(quotechar) - , m_pCSVProgress(0) - , m_nColumns(0) + , m_iNumExtraBytesFieldSeparator(0) + , m_iNumExtraBytesQuoteChar(0) + , m_pCSVProgress(nullptr) , m_nBufferSize(4096) { + for(int i=0;i<4;i++) + { + m_cFieldSeparator[i] = static_cast((fieldseparator >> i*8) & 0xFF); + m_cQuoteChar[i] = static_cast((quotechar >> i*8) & 0xFF); + + if(i && m_cFieldSeparator[i]) + m_iNumExtraBytesFieldSeparator = i; + if(i && m_cQuoteChar[i]) + m_iNumExtraBytesQuoteChar = i; + } } CSVParser::~CSVParser() @@ -19,144 +28,298 @@ CSVParser::~CSVParser() } namespace { -inline void addColumn(QStringList& r, QString& field, bool trim) +// This function adds a character to an existing field structure. If necessary, it extends the buffer size. +inline void addChar(CSVField* field, char c) +{ + // Increase buffer size if it is too small + if(field->buffer_length >= field->buffer_max_length) + { + field->buffer_max_length += 64; + field->buffer = static_cast(realloc(field->buffer, field->buffer_max_length)); + } + + // Add char to the end of the buffer and increase length by one + field->buffer[field->buffer_length++] = c; +} + +// This function increases the size of the field list of an existing row. However, it only does so if the field list is currently full. +inline void increaseRowSize(CSVRow& r) +{ + // Check if field list is full + if(r.num_fields >= r.max_num_fields) + { + // Increase field list size + r.max_num_fields += 5; + r.fields = static_cast(realloc(r.fields, r.max_num_fields*sizeof(CSVField))); + + // Initialise the newly created field structures + for(size_t i=r.num_fields;idata = field->buffer; + field->data_length = field->buffer_length; + + // If we have to trim the field, do this by manipulating the data start and data length variables if(trim) - r << field.trimmed(); - else - r << field; - field.clear(); + { + // Check for trailing spaces and omit them + while(field->data_length && isspace(*field->data)) + { + field->data++; + field->data_length--; + } + + // Check for pending spaces and omit them + while(field->data_length && isspace(field->data[field->data_length-1])) + field->data_length--; + } + + // We assume here that the field object has been constructed in-place. So all we need to do for adding it to the row structure + // is increasing the field count by one to make sure the newly constructed field object is used. + r.num_fields++; + + // Clear field buffer for next use + field->buffer_length = 0; + + // Increase field list size if it is too small + increaseRowSize(r); + + // Return pointer to the next field + return &r.fields[r.num_fields]; +} + +// This function takes a parsed CSV row and hands it back to the caller of the CSV parser. It returns a null pointer if the parsing should be +// aborted, otherwise it returns a pointer to a new field object that can be used for storing the contents of the first field of the next row. +inline CSVField* addRow(CSVParser::csvRowFunction f, CSVRow& r, size_t& rowCount) +{ + // Call row function + if(!f(rowCount, r)) + return nullptr; + + // Reset the field list by setting the field count to 0. No need to deconstruct anything else. + r.num_fields = 0; + + // Increase row count by one, as we're now starting to parse the next row + rowCount++; + + // Return a pointer to the first field in the row object because we're starting with the first field of the next row now + return r.fields; } } -bool CSVParser::parse(QTextStream& stream, qint64 nMaxRecords) +CSVParser::ParserResult CSVParser::parse(csvRowFunction insertFunction, QTextStream& stream, size_t nMaxRecords) { - m_vCSVData.clear(); - m_nColumns = 0; - ParseStates state = StateNormal; - QString fieldbuf; - QStringList record; + ParseStates state = StateNormal; // State of the parser + QByteArray sBuffer; // Buffer for reading the file + CSVRow record; // Buffer for parsing the current row + size_t parsedRows = 0; // Number of rows parsed so far + CSVField* field; // Buffer for parsing the current field if(m_pCSVProgress) m_pCSVProgress->start(); + // Initialise row buffer and get pointer to the first field + record = { nullptr, 0, 0 }; + increaseRowSize(record); + field = record.fields; + + // Make sure all buffers are freed when we're done here + class FieldBufferDealloc + { + public: + explicit FieldBufferDealloc(CSVRow& row) : m_row(row) {} + ~FieldBufferDealloc() + { + for(size_t i=0;i= nMaxRecords) - return true; + if(nMaxRecords > 0 && parsedRows >= nMaxRecords) + return ParserResult::ParserResultSuccess; } - if(m_pCSVProgress && m_vCSVData.size() % 100 == 0) + if(m_pCSVProgress && parsedRows % 100 == 0) { - if(!m_pCSVProgress->update(stream.pos())) - return false; + if(!m_pCSVProgress->update(bufferPos)) + return ParserResult::ParserResultCancelled; } } - if(!record.isEmpty()) + if(record.num_fields || record.fields->buffer_length) { - addColumn(record, fieldbuf, m_bTrimFields); + addColumn(record, field, m_bTrimFields); - addRow(record); + if(!addRow(insertFunction, record, parsedRows)) + return ParserResult::ParserResultError; } if(m_pCSVProgress) m_pCSVProgress->end(); - return state == StateNormal; + // Check if we are in StateNormal or StateEndQuote state. The first is what we should be in for unquoted data and all files which + // end with a line break. The latter is what we are in for quoted data with no final line break. + return (state == StateNormal || state == StateEndQuote) ? ParserResult::ParserResultSuccess : ParserResult::ParserResultUnexpectedEOF; +} + +bool CSVParser::look_ahead(QTextStream& stream, QByteArray& sBuffer, const char** it, const char** sBufferEnd, char expected) +{ + // look ahead for next byte + auto nit = *it + 1; + + // In order to check what the next byte is we must make sure that that byte is already loaded. Assume we're at an m_nBufferSize + // boundary but not at the end of the file when we hit a \r character. Now we're going to be at the end of the sBuffer string + // because of the m_nBufferSize boundary. But this means that the following check won't work properly because we can't check the + // next byte when we really should be able to do so because there's more data coming. To fix this we'll check for this particular + // case and, if this is what's happening, we'll just load an extra byte. + if(nit == *sBufferEnd && !stream.atEnd()) + { + // Load one more byte + sBuffer.append(stream.read(1).toUtf8()); + *sBufferEnd = sBuffer.constEnd(); + + // Restore both iterators. sBufferEnd points to the imagined char after the last one in the string. So the extra byte we've + // just loaded is the one before that, i.e. the actual last one, and the original last char is the one before that. + *it = *sBufferEnd - 2; + nit = *sBufferEnd - 1; + } + + // Check whether there actually is one more byte and it is the expected one + return nit != *sBufferEnd && *nit == expected; } diff --git a/src/csvparser.h b/src/csvparser.h index d886ae239..e78239007 100644 --- a/src/csvparser.h +++ b/src/csvparser.h @@ -1,10 +1,11 @@ #ifndef CSVPARSER_H #define CSVPARSER_H -#include -#include -#include +#include +#include +#include +class QByteArray; class QTextStream; /*! @@ -15,40 +16,63 @@ class QTextStream; class CSVProgress { public: - virtual ~CSVProgress() { } + virtual ~CSVProgress() = default; virtual void start() = 0; - virtual bool update(size_t pos) = 0; + virtual bool update(int64_t pos) = 0; virtual void end() = 0; }; +/* + * This structure represents one parsed column in a CSV row + */ +struct CSVField +{ + // These variables are used internally by the parser. Usually there should be no need to access them from outside the parser + char* buffer; // Start of the field buffer + uint64_t buffer_length; // Current length of the buffer content. The content is NOT null-terminated + uint64_t buffer_max_length; // Size of the entire buffer + + // These variables point to the parsed contents of the field and can be directly passed to SQLite functions + char* data; // Pointer to the start of the field contents + uint64_t data_length; // Length of the field contents +}; + +/* + * This structure holds all columns of a single parsed CSV row + */ +struct CSVRow +{ + CSVField* fields; // Pointer to the field list/the first element in the list + size_t num_fields; // Number of fields in the row + size_t max_num_fields; // Size of the field list. Used internally by the parser only +}; + class CSVParser { public: - typedef QVector TCSVResult; + using csvRowFunction = std::function; - CSVParser(bool trimfields = true, const QChar& fieldseparator = ',', const QChar& quotechar = '"'); + explicit CSVParser(bool trimfields = true, char32_t fieldseparator = ',', char32_t quotechar = '"'); ~CSVParser(); + enum ParserResult + { + ParserResultSuccess, + ParserResultCancelled, + ParserResultError, + ParserResultUnexpectedEOF + }; + /*! * \brief parse the given stream + * @param insertFunction A function pointer that is called for each parsed row. It is passed two parameters, the row number and a list of all parsed columns + * in the row. The called function may return false if an error occurred to stop the import process. Otherwise it should return true. * \param stream Stream with the CSV parser - * \param nMaxRecords Max records too read, -1 if unlimited - * \return True if parsing worked. + * \param nMaxRecords Max records too read, 0 if unlimited + * \return ParserResult value that indicated whether action finished normally, was cancelled or errored. */ - bool parse(QTextStream& stream, qint64 nMaxRecords = -1); - - /*! - * \brief csv - * \return The parse result - */ - const TCSVResult& csv() const { return m_vCSVData; } - - /*! - * \brief columns - * \return Number of columns parsed - */ - size_t columns() const { return m_nColumns; } + ParserResult parse(csvRowFunction insertFunction, QTextStream& stream, size_t nMaxRecords = 0); void setCSVProgress(CSVProgress* csvp) { m_pCSVProgress = csvp; } @@ -60,23 +84,17 @@ class CSVParser StateEndQuote }; - inline void addRow(QStringList& r) - { - m_vCSVData.append(r); - m_nColumns = std::max(r.size(), m_nColumns); - r.clear(); - } - private: bool m_bTrimFields; - QChar m_cFieldSeparator; - QChar m_cQuoteChar; + char m_cFieldSeparator[4]; + char m_cQuoteChar[4]; + int m_iNumExtraBytesFieldSeparator; + int m_iNumExtraBytesQuoteChar; CSVProgress* m_pCSVProgress; - TCSVResult m_vCSVData; - size_t m_nColumns; + int64_t m_nBufferSize; //! internal buffer read size - size_t m_nBufferSize; //! internal buffer read size + bool look_ahead(QTextStream& stream, QByteArray& sBuffer, const char** it, const char** sBufferEnd, char expected); }; -#endif // CSVPARSER_H +#endif diff --git a/src/dbstructureqitemviewfacade.cpp b/src/dbstructureqitemviewfacade.cpp new file mode 100644 index 000000000..3d6dac276 --- /dev/null +++ b/src/dbstructureqitemviewfacade.cpp @@ -0,0 +1,59 @@ +#include "DbStructureModel.h" +#include "dbstructureqitemviewfacade.h" + +DbStructureQItemViewFacade::DbStructureQItemViewFacade(QAbstractItemView& aitemView) + : QObject(&aitemView), + m_itemView(aitemView) +{ + +} + +const QAbstractItemView& DbStructureQItemViewFacade::itemView() const +{ + return m_itemView; +} + +bool DbStructureQItemViewFacade::hasSelection() const +{ + return m_itemView.selectionModel()->hasSelection(); +} + +QString DbStructureQItemViewFacade::displayName() const +{ + QAbstractItemModel *model = m_itemView.model(); + QModelIndex index = m_itemView.currentIndex(); + return model->data(index.sibling(index.row(), DbStructureModel::ColumnName), Qt::DisplayRole).toString(); +} + +QString DbStructureQItemViewFacade::name() const +{ + QAbstractItemModel *model = m_itemView.model(); + QModelIndex index = m_itemView.currentIndex(); + return model->data(index.sibling(index.row(), DbStructureModel::ColumnName), Qt::EditRole).toString(); +} + +QString DbStructureQItemViewFacade::objectType() const +{ + QAbstractItemModel *model = m_itemView.model(); + QModelIndex index = m_itemView.currentIndex(); + return model->data(index.sibling(index.row(), DbStructureModel::ColumnObjectType), Qt::EditRole).toString(); +} + +QString DbStructureQItemViewFacade::schema() const +{ + QAbstractItemModel *model = m_itemView.model(); + QModelIndex index = m_itemView.currentIndex(); + return model->data(index.sibling(index.row(), DbStructureModel::ColumnSchema), Qt::EditRole).toString(); +} + +QString DbStructureQItemViewFacade::sql() const +{ + QAbstractItemModel *model = m_itemView.model(); + QModelIndex index = m_itemView.currentIndex(); + return model->data(index.sibling(index.row(), DbStructureModel::ColumnSQL), Qt::EditRole).toString(); +} + +sqlb::ObjectIdentifier DbStructureQItemViewFacade::object() const +{ + return sqlb::ObjectIdentifier(schema().toStdString(), name().toStdString()); +} diff --git a/src/dbstructureqitemviewfacade.h b/src/dbstructureqitemviewfacade.h new file mode 100644 index 000000000..efdddfbd8 --- /dev/null +++ b/src/dbstructureqitemviewfacade.h @@ -0,0 +1,107 @@ +#ifndef DBSTRUCTUREQITEMVIEWFACADE_H +#define DBSTRUCTUREQITEMVIEWFACADE_H + +#include +#include +#include +#include +#include + +#include + + +/** + * @brief The DbStructureQItemViewFacade class + * Provides a simple read only interface to a QAbstractItemView (e.g. QTreeView) that holds a model() of type DBStructureModel. + * + * It is designed to simplify the access to the actual selected node. + * + * The Class follows the facade design pattern. + * But it doesn't control the lifecycle of the itemView it is connected to. + * + */ +class DbStructureQItemViewFacade : public QObject +{ + Q_OBJECT +public: + explicit DbStructureQItemViewFacade(QAbstractItemView& aitemView); + + /** + * @brief itemView returns the itemView that is hiding behind the facade. + * ItemView is connected on construction, the facadeObject has to be destroyed before the itemView. + * + * @return connected itemView + */ + const QAbstractItemView& itemView() const; + + /** + * @brief hasSelection returns true, if the itemView() has a selected Item. + * itemView().selectionModel().hasSelection() + * + * @return true, if the itemView() has a selected Item. + ***/ + bool hasSelection() const; + + /** + * @brief displayName returns the displayName of the itemViews selectedItem. + * + * It is taken from the model().data() with column=ColumnName and role=Qt::DisplayRole + * + * For the display role and the browsable branch of the tree we want to show the column name including the schema name if necessary (i.e. + * for schemata != "main"). For the normal structure branch of the tree we don't want to add the schema name because it's already obvious from + * the position of the item in the tree. + * + * @return displayName of selectedItem + */ + QString displayName() const; + + /** + * @brief returns the name of the itemViews selectedItem without decorations. + * It is taken from the model().data() with column=ColumnName and role=Qt::EditRole + * + * @return name of selectedItem + */ + QString name() const; + + /** + * @brief objectType returns the objectType of the itemViews selectedItem. + * + * It is taken from the model().data() with column=ColumnObjectType and role=Qt::EditRole + * + * @return + */ + QString objectType() const; + + + /** + * @brief schema returns the schema of the itemViews selectedItem. + * + * It is taken from the model().data() with column=ColumnSchema and role=Qt::EditRole + * + * @return + */ + QString schema() const; + + /** + * @brief sql returns the sql statement of the itemViews selectedItem. + * + * It is taken from the model().data() with column=ColumnSQL and role=Qt::EditRole + * + * @return + */ + QString sql() const; + + /** + * @brief Object returns a sqlb::ObjectIdentifier to the selected itemView item. + * Object identifier consisting of schema name and object name. + * + * @return sqlb::ObjectIdentifier to selected item + */ + sqlb::ObjectIdentifier object() const; + +private: + QAbstractItemView& m_itemView; + +}; + +#endif diff --git a/src/docktextedit.cpp b/src/docktextedit.cpp new file mode 100644 index 000000000..8c4ade71a --- /dev/null +++ b/src/docktextedit.cpp @@ -0,0 +1,121 @@ +#include "docktextedit.h" +#include "Settings.h" +#include "SqlUiLexer.h" + +#include +#include +#include + +QsciLexerJSON* DockTextEdit::jsonLexer = nullptr; +QsciLexerXML* DockTextEdit::xmlLexer = nullptr; + +DockTextEdit::DockTextEdit(QWidget* parent) : + SqlTextEdit(parent) +{ + // Create lexer objects if not done yet + if(jsonLexer == nullptr) + jsonLexer = new QsciLexerJSON(this); + if(xmlLexer == nullptr) + xmlLexer = new QsciLexerXML(this); + + // Set plain text as default + setLanguage(PlainText); + + jsonLexer->setFoldCompact(false); + jsonLexer->setHighlightComments(true); + + // Do rest of initialisation + reloadSettings(); +} + +void DockTextEdit::reloadSettings() +{ + // Set the parent settings for all lexers + SqlTextEdit::reloadSettings(); + reloadLexerSettings(jsonLexer); + reloadLexerSettings(xmlLexer); + + // Set the databrowser font for the plain text editor. + plainTextFont = QFont(Settings::getValue("databrowser", "font").toString()); + plainTextFont.setPointSize(Settings::getValue("databrowser", "fontsize").toInt()); + setFont(plainTextFont); + + setupSyntaxHighlightingFormat(jsonLexer, "comment", QsciLexerJSON::CommentLine); + setupSyntaxHighlightingFormat(jsonLexer, "comment", QsciLexerJSON::CommentBlock); + setupSyntaxHighlightingFormat(jsonLexer, "keyword", QsciLexerJSON::Keyword); + setupSyntaxHighlightingFormat(jsonLexer, "keyword", QsciLexerJSON::KeywordLD); + setupSyntaxHighlightingFormat(jsonLexer, "function", QsciLexerJSON::Operator); + setupSyntaxHighlightingFormat(jsonLexer, "string", QsciLexerJSON::String); + setupSyntaxHighlightingFormat(jsonLexer, "table", QsciLexerJSON::Number); + setupSyntaxHighlightingFormat(jsonLexer, "identifier", QsciLexerJSON::Property); + + // The default style for invalid JSON or unclosed strings uses red + // background and white foreground, but the current line has + // precedence, so it is by default white over gray. We change the + // default to something more readable for the current line at + // invalid JSON. + QColor stringColor = QColor(Settings::getValue("syntaxhighlighter", "string_colour").toString()); + jsonLexer->setColor(stringColor, QsciLexerJSON::Error); + jsonLexer->setColor(stringColor, QsciLexerJSON::UnclosedString); + QFont errorFont(Settings::getValue("editor", "font").toString()); + errorFont.setPointSize(Settings::getValue("editor", "fontsize").toInt()); + errorFont.setItalic(true); + jsonLexer->setFont(errorFont, QsciLexerJSON::Error); + jsonLexer->setFont(errorFont, QsciLexerJSON::UnclosedString); + jsonLexer->setPaper(jsonLexer->defaultPaper(QsciLexerJSON::String), QsciLexerJSON::Error); + jsonLexer->setPaper(jsonLexer->defaultPaper(QsciLexerJSON::String), QsciLexerJSON::UnclosedString); + + xmlLexer->setColor(QColor(Settings::getValue("syntaxhighlighter", "foreground_colour").toString())); + setupSyntaxHighlightingFormat(xmlLexer, "comment", QsciLexerHTML::HTMLComment); + setupSyntaxHighlightingFormat(xmlLexer, "keyword", QsciLexerHTML::Tag); + setupSyntaxHighlightingFormat(xmlLexer, "keyword", QsciLexerHTML::XMLTagEnd); + setupSyntaxHighlightingFormat(xmlLexer, "keyword", QsciLexerHTML::XMLStart); + setupSyntaxHighlightingFormat(xmlLexer, "keyword", QsciLexerHTML::XMLEnd); + setupSyntaxHighlightingFormat(xmlLexer, "string", QsciLexerHTML::HTMLDoubleQuotedString); + setupSyntaxHighlightingFormat(xmlLexer, "string", QsciLexerHTML::HTMLSingleQuotedString); + setupSyntaxHighlightingFormat(xmlLexer, "table", QsciLexerHTML::HTMLNumber); + setupSyntaxHighlightingFormat(xmlLexer, "identifier", QsciLexerHTML::Attribute); +} + +void DockTextEdit::setLanguage(Language lang) +{ + m_language = lang; + switch (lang) { + case PlainText: { + setLexer(nullptr); + setFolding(QsciScintilla::NoFoldStyle); + // This appears to be reset by setLexer + setFont(plainTextFont); + break; + } + case JSON: + setLexer(jsonLexer); + setFolding(QsciScintilla::BoxedTreeFoldStyle); + break; + case XML: + setLexer(xmlLexer); + setFolding(QsciScintilla::BoxedTreeFoldStyle); + break; + case SQL: + setLexer(sqlLexer); + setFolding(QsciScintilla::BoxedTreeFoldStyle); + break; + } +} + +void DockTextEdit::setTextInMargin(const QString& text) +{ + clearMarginText(); + setMarginType(0, QsciScintilla::TextMargin); + setMarginText(0, text, QsciStyle(QsciScintillaBase::STYLE_LINENUMBER)); + setMarginWidth(0, text); + reloadCommonSettings(); +} + +void DockTextEdit::clearTextInMargin() +{ + clearMarginText(); + setMarginLineNumbers(0, true); + reloadCommonSettings(); + emit linesChanged(); +} diff --git a/src/docktextedit.h b/src/docktextedit.h new file mode 100644 index 000000000..00c1bf25b --- /dev/null +++ b/src/docktextedit.h @@ -0,0 +1,51 @@ +#ifndef DOCKTEXTEDIT_H +#define DOCKTEXTEDIT_H + +#include "sqltextedit.h" + +class QsciLexerJSON; +class QsciLexerXML; +class SqlUiLexer; + +/** + * @brief The DockTextEdit class + * This class extends our QScintilla SQL Text Edit adding XML, JSON and plain text modes. + */ +class DockTextEdit : public SqlTextEdit +{ + Q_OBJECT + +public: + explicit DockTextEdit(QWidget *parent = nullptr); + + // Enumeration of supported languages + enum Language + { + PlainText, + JSON, + XML, + SQL + }; + + void setLanguage(Language lang); + Language language() const { return m_language; } + + // Disables the line-number margin and sets this text in the first line. + void setTextInMargin(const QString& text); + + // Resets margin to their original line-number mode + void clearTextInMargin(); + +public slots: + void reloadSettings(); + +protected: + static QsciLexerJSON* jsonLexer; + static QsciLexerXML* xmlLexer; + +private: + Language m_language; + QFont plainTextFont; +}; + +#endif diff --git a/src/extensions/extension-formats.c b/src/extensions/extension-formats.c new file mode 100644 index 000000000..3a7bddbfe --- /dev/null +++ b/src/extensions/extension-formats.c @@ -0,0 +1,1724 @@ +/*** Extension-formats + * + * This file adds the following file format support to SQLite. + * + * Plist - An XML like encoding + * Base64 - Standard binary to text conversion + * + * Compile using: + * + * gcc -g -fPIC -shared extension-formats.c -o libsqlite-formats.so + */ + +#include +#include +#include +#include +#include +#include +#include + +#define COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE 1 +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 + +#define INDENT_INCREMENT 4 + +#define ERROR_NONE 0 +#define ERROR_INSUFFICIENT_MEMORY 1 +#define ERROR_INVALID_HEADER 2 +#define ERROR_INVALID_TRAILER 3 +#define ERROR_INVALID_OFFSET 4 +#define ERROR_INVALID_OBJECT_LENGTH 5 +#define ERROR_INVALID_REFERENCE 6 +#define ERROR_INVALID_CHARACTER 7 + +typedef struct KEY { + struct OBJECT *key; + struct OBJECT *value; +} KEY; + +typedef struct OBJECT { + int type; + int length; + union { + time_t date; + double real; + long integer; + unsigned long uid; + unsigned char binary[1]; + char text[1]; + short int utf16[1]; + int refs[1]; + KEY keys[1]; + struct OBJECT *objects[1]; + } data; +} OBJECT; + +typedef struct CONFIG { + int bytesPerOffset; + int bytesPerReference; + int objectCount; + int rootObjectReference; + int offsetTableOffset; + size_t bufferLength; + size_t outputBufferLength; + size_t outputBufferIn; + long *offsetTable; + unsigned char *buffer; + unsigned char *outputBuffer; +} CONFIG; + +int createObject(int type, int length, size_t extra, OBJECT **ptr2); +int readObject(CONFIG *cfg, long offset, OBJECT **ptr2); + +static int indent = 2; + +int outputText(CONFIG *cfg, const char *text) +{ + size_t textLength = strlen(text); + size_t availableSpace = cfg->outputBufferLength - cfg->outputBufferIn; + while (textLength >= availableSpace) { + unsigned char *tmp = cfg->outputBuffer; + cfg->outputBufferLength += textLength + 1024; + cfg->outputBuffer = (unsigned char *)realloc(cfg->outputBuffer, cfg->outputBufferLength); + if (cfg->outputBuffer == NULL) { + if (tmp != NULL) + free(tmp); + return ERROR_INSUFFICIENT_MEMORY; + } + availableSpace = cfg->outputBufferLength - cfg->outputBufferIn; + } + strcpy((char *)(cfg->outputBuffer+cfg->outputBufferIn), text); + cfg->outputBufferIn += textLength; + return ERROR_NONE; +} + +int printWithIndent(CONFIG *cfg, const char *text, int newline) +{ + int err = ERROR_NONE; + char spaces[9] = " "; + int n = indent; + while ((n > 8) && (err == ERROR_NONE)) { + err = outputText(cfg, spaces); + n -= 8; + } + if ((n > 0) && (err == ERROR_NONE)) + err = outputText(cfg, spaces + 8 - n); + if (err == ERROR_NONE) + err = outputText(cfg, text); + if (newline && (err == ERROR_NONE)) + err = outputText(cfg, "\n"); + return err; +} + +int readHeader(CONFIG *cfg) +{ + if ((cfg->bufferLength < 40) || + (strncmp((const char *)(cfg->buffer), "bplist0", 7) != 0) || + ((cfg->buffer[7] != '0') && (cfg->buffer[7] != '1'))) + return ERROR_INVALID_HEADER; + return ERROR_NONE; +} + +int readTrailer(CONFIG *cfg) +{ + int i, j; + int objectCount = 0; + int rootObjectReference = 0; + int offsetTableOffset = 0; + unsigned char *ptr; + unsigned char *buffer = cfg->buffer + cfg->bufferLength - 32; + + // Extract the relevant fields + for (i=12; i < 16; i++) + objectCount = (objectCount << 8) + buffer[i]; + for (i=20; i < 24; i++) + rootObjectReference = (rootObjectReference << 8) + buffer[i]; + for (i=28; i < 32; i++) + offsetTableOffset = (offsetTableOffset << 8) + buffer[i]; + + // Populate the configurartion structure + cfg->bytesPerOffset = buffer[6]; + cfg->bytesPerReference = buffer[7]; + cfg->objectCount = objectCount; + cfg->rootObjectReference = rootObjectReference; + cfg->offsetTableOffset = offsetTableOffset; + cfg->offsetTable = (long *)malloc((size_t)objectCount * sizeof(long)); + if (cfg->offsetTable == NULL) + return ERROR_INSUFFICIENT_MEMORY; + ptr = cfg->buffer + offsetTableOffset; + for (i=0; i < objectCount; i++) { + long n = 0; + for (j=0; j < cfg->bytesPerOffset; j++) + n = (n << 8) | *(ptr++); + cfg->offsetTable[i] = n; + } + return ERROR_NONE; +} + +int createObject(int type, int length, size_t extra, OBJECT **ptr2) { + OBJECT *ptr; + size_t totalSize; + + // Calculate proper extra size based on type + size_t actualExtra; + switch (type) { + case 0x06: // UTF16 string + actualExtra = 2 * (length + 1); // 2 bytes per char + null terminator + break; + case 0x05: // Regular string + actualExtra = length + 1; // bytes + null terminator + break; + case 0x0A: // Array + actualExtra = length * sizeof(OBJECT*); + break; + case 0x0D: // Dictionary + actualExtra = (length - 1) * sizeof(KEY); + break; + default: + actualExtra = extra; + break; + } + + totalSize = sizeof(OBJECT) + actualExtra; + + ptr = malloc(totalSize); + if (ptr == NULL) + return ERROR_INSUFFICIENT_MEMORY; + + ptr->type = type; + ptr->length = length; + *ptr2 = ptr; + return ERROR_NONE; +} + +long readInteger(unsigned char *ptr, int desc) +{ + long value = 0L; + int n = 1 << (desc & 0x03); + while (n--) + value = (value << 8) | (long)(*(ptr++)); + return value; +} + +unsigned long readUid(unsigned char *ptr, int desc) +{ + unsigned long value = 0L; + int n = 1 << (desc & 0x03); + while (n--) + value = (value << 8) | (unsigned long)(*(ptr++)); + return value; +} + +double readDouble(unsigned char *ptr, int desc) +{ + union { + double v; + float f[2]; + unsigned char b[8]; + } value; + int n = 1 << (desc & 0x03); + for (int i=0; i < n; i++) + value.b[7-i] = *(ptr++); + if (n == 4) + value.v = (double)(value.f[1]); + return value.v; +} + +int readArray(CONFIG *cfg, unsigned char *ptr, int type, int length, OBJECT **array2) +{ + int i; + long offset; + OBJECT *array; + int err = createObject(type, length, ((length-1) * (int)sizeof(OBJECT)), &array); + *array2 = NULL; + for (i=0; (i < length) && (err == ERROR_NONE); i++) { + offset = 0L; + for (int j=0; j < cfg->bytesPerReference; j++) + offset = (offset << 8) | (long)(*(ptr++)); + if (offset >= cfg->objectCount) + return ERROR_INVALID_REFERENCE; + offset = cfg->offsetTable[offset]; + err = readObject(cfg, offset, &(array->data.objects[i])); + } + if (err == ERROR_NONE) + *array2 = array; + return err; +} + +int readDictionary(CONFIG *cfg, unsigned char *ptr, int type, int length, OBJECT **dict2) +{ + int i; + long offset; + OBJECT *dict; + int err = createObject(type, length, ((length-1) * (int)sizeof(KEY)), &dict); + *dict2 = NULL; + if (err != ERROR_NONE) + return err; + for (i=0; (i < length) && (err == ERROR_NONE); i++) { + offset = 0L; + for (int j=0; j < cfg->bytesPerReference; j++) + offset = (offset << 8) | (long)(*(ptr++)); + if (offset >= cfg->objectCount) + return ERROR_INVALID_REFERENCE; + offset = cfg->offsetTable[offset]; + err = readObject(cfg, offset, &(dict->data.keys[i].key)); + } + for (i=0; (i < length) && (err == ERROR_NONE); i++) { + offset = 0L; + for (int j=0; j < cfg->bytesPerReference; j++) + offset = (offset << 8) | (long)(*(ptr++)); + if (offset >= cfg->objectCount) + return ERROR_INVALID_REFERENCE; + offset = cfg->offsetTable[offset]; + err = readObject(cfg, offset, &(dict->data.keys[i].value)); + } + if (err == ERROR_NONE) + *dict2 = dict; + return err; +} + +int readObject(CONFIG *cfg, long offset, OBJECT **ptr2) +{ + int i; + int length; + int type; + int err = ERROR_NONE; + OBJECT *obj; + unsigned char *ptr; + + *ptr2 = NULL; + if ((size_t)offset >= cfg->bufferLength) + return ERROR_INVALID_OFFSET; + ptr = cfg->buffer + offset; + type = *(ptr++); + length = (type & 0x0F); + type >>= 4; + if ((type != 0) && (length == 0x0F)) { + length = *(ptr++); + if ((length >> 4) != 0x01) + return ERROR_INVALID_OBJECT_LENGTH; + i = (int)readInteger(ptr, length); + ptr += (1 << (length & 0x03)); + length = i; + } + switch (type) { + case 0x00: // Singleton + err = createObject(type, length, 5, &obj); + if (err != ERROR_NONE) + return err; + switch(length) { + case 0: // NULL + strcpy(obj->data.text, ""); + break; + case 8: // False + strcpy(obj->data.text, ""); + break; + case 9: // True + strcpy(obj->data.text, ""); + break; + case 15: // Fill + strcpy(obj->data.text, ""); + break; + default: // Illegal + strcpy(obj->data.text, "***Error***"); + break; + } + break; + case 0x01: // Integer + err = createObject(type, length, 0, &obj); + if (err != ERROR_NONE) + return err; + obj->data.integer = readInteger(ptr, length); + break; + case 0x02: // Float + err = createObject(type, length, 0, &obj); + if (err != ERROR_NONE) + return err; + obj->data.real = readDouble(ptr, length); + break; + case 0x03: // Date in Elapsed seconds + err = createObject(type, length, 0, &obj); + if (err != ERROR_NONE) + return err; + obj->data.date = (time_t)readDouble(ptr, length); + break; + case 0x04: // binary data + err = createObject(type, length, length, &obj); + if (err != ERROR_NONE) + return err; + for (i=0; i < length; i++) + obj->data.binary[i] = *(ptr++); + break; + case 0x05: // ASCII string + err = createObject(type, length, length, &obj); + if (err != ERROR_NONE) + return err; + for (i=0; i < length; i++) + obj->data.text[i] = (char)*(ptr++); + obj->data.text[length] = '\0'; + break; + case 0x06: // UTF16 string + { + size_t bytesNeeded = 2 * ((size_t)length + 1); + err = createObject(type, length, bytesNeeded, &obj); + if (err != ERROR_NONE) + return err; + + memset(obj->data.utf16, 0, bytesNeeded); + + for (i = 0; i < length; i++) { + unsigned char byte1 = *(ptr++); + unsigned char byte2 = *(ptr++); + obj->data.utf16[i] = (byte1 << 8) | byte2; + } + + obj->data.utf16[length] = 0; + } + break; + case 0x08: // UID + err = createObject(type, length, 0, &obj); + if (err != ERROR_NONE) + return err; + obj->data.uid = readUid(ptr, length); + break; + case 0x0A: // Array + err = readArray(cfg, ptr, type, length, &obj); + break; + case 0x0D: // Dictionary + err = readDictionary(cfg, ptr, type, length, &obj); + break; + default: + fprintf(stderr, "Unknown object type: %d\n", type); + err = createObject(type, length, 0, &obj); + break; + } + if (err == ERROR_NONE) + *ptr2 = obj; + return err; +} + +void displayHex(CONFIG *cfg, int data) +{ + static int in = 0; + static char buffer[76]; + static long offset = 0L; + static char hex[] = "0123456789ABCDEF"; + char *tmp; + + // If -ve then flush buffer + if (data < 0) { + if (in > 0) { + tmp = buffer + in * 3 + 8 + 2 * (in / 8); + while (tmp < buffer+59) + *(tmp++) = ' '; + buffer[in+59] = '\0'; + printWithIndent(cfg, buffer, 1); + } + offset = 0L; + in = 0; + return; + } + + // If start of line add offset + if (in == 0) { + sprintf((char *)buffer, "%06lX ", offset); + offset += 16; + buffer[8] = '\0'; + } + + // Add Byte in hex + tmp = buffer + in * 3 + 8 + 2 * (in / 8); + *(tmp++) = hex[(data >> 4) & 0x0F]; + *(tmp++) = hex[data & 0x0F]; + *(tmp++) = ' '; + + // Add to character buffer + buffer[in+59] = (char)data; + + // Check if midpoint of buffer + if (++in == 8) { + *(tmp++) = '-'; + *(tmp++) = ' '; + } + + // Check if buffer full + if (in == 16) { + buffer[75] = '\0'; + printWithIndent(cfg, buffer, 1); + in = 0; + } + return; +} + +int displayObject(CONFIG *cfg, OBJECT *obj, int raw) +{ + char text[32]; + switch (obj->type) { + case 0x00: // Singleton + printWithIndent(cfg, obj->data.text, 1); + break; + case 0x01: // Integer + if (raw == 0) + printWithIndent(cfg, "", 0); + sprintf(text, "%ld", obj->data.integer); + outputText(cfg, text); + if (raw == 0) + outputText(cfg, "\n"); + break; + case 0x02: // Float + if (raw == 0) + printWithIndent(cfg, "", 0); + sprintf(text, "%f", obj->data.real); + outputText(cfg, text); + if (raw == 0) + outputText(cfg, "\n"); + break; + case 0x03: // Date + if (raw == 0) + printWithIndent(cfg, "", 0); + outputText(cfg, ctime(&(obj->data.date))); + if (raw == 0) + outputText(cfg, "\n"); + break; + case 0x04: // Binary data + if (raw == 0) + printWithIndent(cfg, "", 1); + indent += INDENT_INCREMENT; + for (int i=0; i < obj->length; i++) + displayHex(cfg, obj->data.binary[i]); + displayHex(cfg, -1); + indent -= INDENT_INCREMENT; + if (raw == 0) + printWithIndent(cfg, "", 1); + break; + case 0x05: // String + if (raw == 0) + printWithIndent(cfg, "", 0); + outputText(cfg, (obj->data.text)); + if (raw == 0) + outputText(cfg, "\n"); + break; + case 0x06: // UTF16 string + if (raw == 0) + printWithIndent(cfg, "", 1); + indent += INDENT_INCREMENT; + for (int i=0; i < obj->length; i++) + displayHex(cfg, obj->data.binary[i]); + displayHex(cfg, -1); + indent -= INDENT_INCREMENT; + if (raw == 0) + printWithIndent(cfg, "", 1); + break; + case 0x08: // UID + if (raw == 0) + printWithIndent(cfg, "", 0); + sprintf(text, "%lu", obj->data.uid); + outputText(cfg, text); + if (raw == 0) + outputText(cfg, "\n"); + break; + case 0x0A: // Array + printWithIndent(cfg, "", 1); + indent += INDENT_INCREMENT; + for (int i=0; i < obj->length; i++) + displayObject(cfg, obj->data.objects[i], 0); + indent -= INDENT_INCREMENT; + printWithIndent(cfg, "", 1); + break; + case 0x0D: // Dictionary + printWithIndent(cfg, "", 1); + indent += INDENT_INCREMENT; + for (int i=0; i < obj->length; i++) { + printWithIndent(cfg, "", 0); + displayObject(cfg, obj->data.keys[i].key, 1); + outputText(cfg, "\n"); + displayObject(cfg, obj->data.keys[i].value, 0); + } + indent -= INDENT_INCREMENT; + printWithIndent(cfg, "", 1); + break; + default: + sprintf(text, "Cannot display type: %d\n", obj->type); + outputText(cfg, text); + break; + } + return ERROR_NONE; +} + +int releaseObject(OBJECT *obj) +{ + if (!obj) return ERROR_NONE; // Guard against NULL + + int i; + switch (obj->type) { + case 0x00: // Singleton + case 0x01: // Int + case 0x02: // Float + case 0x03: // Date + case 0x04: // Binary + case 0x05: // ASCII + case 0x06: // UTF16 + case 0x08: // UID + break; + case 0x0A: // Array + for (i=0; i < obj->length; i++) { + if (obj->data.objects[i]) { + releaseObject(obj->data.objects[i]); + obj->data.objects[i] = NULL; + } + } + break; + case 0x0D: // Dictionary + for (i=0; i < obj->length; i++) { + if (obj->data.keys[i].key) { + releaseObject(obj->data.keys[i].key); + obj->data.keys[i].key = NULL; + } + if (obj->data.keys[i].value) { + releaseObject(obj->data.keys[i].value); + obj->data.keys[i].value = NULL; + } + } + break; + default: + break; + } + + free(obj); + return ERROR_NONE; +} + +int parsePlist(char **result, const char *data, int dataLength) +{ + CONFIG cfg; + char *ptr; + OBJECT *obj; + int err = ERROR_NONE; + int version; + long offset; + long length; + char text[32]; + + // Determine the file size and save + cfg.buffer = (unsigned char *)data; + cfg.bufferLength = dataLength; + + // Preset the output buffer + cfg.outputBufferLength = 0; + cfg.outputBufferIn = 0; + cfg.outputBuffer = NULL; + + // Read the header + err = readHeader(&cfg); + if (err != ERROR_NONE) + return err; + version = (int)(cfg.buffer[7] - '0'); + + // Read the trailer + err = readTrailer(&cfg); + if (err != ERROR_NONE) + return err; // ERROR_INVALID_TRAILER; + + // Locate and read the root object + offset = cfg.offsetTable[cfg.rootObjectReference]; + err = readObject(&cfg, offset, &obj); + + // If no error display the root object and hence the whole object tree + if (err != ERROR_NONE) + return err; + + sprintf(text, "\n", version); + outputText(&cfg, text); + displayObject(&cfg, obj, 0); + outputText(&cfg, "\n"); + + // Create return data + length = strlen((const char *)(cfg.outputBuffer)); + ptr = malloc(length + 1); + *result = ptr; + if (ptr != NULL) { + for (int i=0; i < length; i++) + *(ptr++) = cfg.outputBuffer[i]; + *ptr = '\0'; + } + else + err = ERROR_INSUFFICIENT_MEMORY; + + // Release assigned memory + releaseObject(obj); + free(cfg.offsetTable); + free(cfg.outputBuffer); + return err; +} + +static char map[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/** Encode Base64 + * + */ + +int encodeBase64(char **result, const unsigned char *data, int dataLength) +{ + unsigned char d; + int b; + int bitsLeft = 0; + int in = 0; + int out = 0; + int encodedLength = dataLength * 4 / 3 + 4; + char *encoded = malloc(encodedLength); + *result = encoded; + if (encoded == NULL) + return ERROR_INSUFFICIENT_MEMORY; + + while (out < dataLength) { + d = data[out++]; + switch (bitsLeft) { + case 0: + encoded[in++] = map[d >> 2]; + b = d & 0x03; + bitsLeft = 2; + break; + case 2: + b = (b << 8) | d; + encoded[in++] = map[b >> 4]; + b &= 0x0F; + bitsLeft = 4; + break; + case 4: + b = (b << 8) | d; + encoded[in++] = map[b >> 6]; + encoded[in++] = map[b & 0x03F]; + bitsLeft = 0; + break; + } + } + + /* Flush remaining bits */ + switch (bitsLeft) { + case 2: + encoded[in++] = map[b << 4]; + encoded[in++] = '='; + encoded[in++] = '='; + break; + case 4: + encoded[in++] = map[b << 2]; + encoded[in++] = '='; + break; + default: + break; + } + + /* Terminate as string */ + encoded[in] = '\0'; + return ERROR_NONE; +} + +static unsigned char unmap[256] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 00 - 07 + 0x81, 0x80, 0x81, 0x80, 0x80, 0x81, 0x80, 0x80, // 08 - 0F + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 10 - 17 + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 18 - 1F + 0x80, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 20 - 27 + 0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, 0x80, 0x3F, // 28 - 2F + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, // 30 - 37 + 0x3C, 0x3D, 0x80, 0x80, 0x80, 0x40, 0x80, 0x80, // 38 - 3F + 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // 40 - 47 + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, // 48 - 4F + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // 50 - 57 + 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80, // 58 - 5F + 0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // 60 - 67 + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // 68 - 6F + 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, // 70 - 77 + 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, // 78 - 7F + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 80 - 87 + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 88 - 8F + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 90 - 97 + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 98 - 9F + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // A0 - A7 + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // A8 - AF + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // B0 - B7 + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // B8 - BF + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // C0 - C7 + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // C8 - CF + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // D0 - D7 + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // D8 - DF + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // E0 - E7 + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // E8 - EF + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // F0 - F7 + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // F8 - FF +}; + +/*** decodeBase64 + * + * Returns decoded data and length. + */ + +int decodeBase64(unsigned char **result, int *resultLength, const char *data, int dataLength) +{ + int bitsLeft = 8; + int in = 0; + unsigned char b; + unsigned char d; + unsigned char *decoded = malloc(dataLength * 3 / 4 + 3); + *result = decoded; + *resultLength = 0; + if (decoded == NULL) + return ERROR_INSUFFICIENT_MEMORY; + + while (*data != '\0') { + // Get character and check valid + d = unmap[*(data++)]; + if (d > 0x3F) { + if (d == 0x80) { + free(decoded); + return ERROR_INVALID_CHARACTER; + } + break; // padding space + } + + switch (bitsLeft) { + case 8: + decoded[in] = d; + bitsLeft = 2; + break; + case 2: + decoded[in] = (decoded[in] << 2) | (d >> 4); + decoded[++in] = d & 0x0F; + bitsLeft = 4; + break; + case 4: + decoded[in] = (decoded[in] << 4) | (d >> 2); + decoded[++in] = d & 0x03; + bitsLeft = 6; + break; + case 6: + decoded[in] = (decoded[in] << 6) | d; + in++; + bitsLeft = 8; + break; + } + } + *resultLength = in; + return ERROR_NONE; +} + +/** Wrapper functions + * + */ + +void freeResult(void *ptr) +{ + if (ptr != NULL) + free(ptr); + return; +} + +static void plistFunc(sqlite3_context *context, int argc, sqlite3_value **argv) { + int errorCode = 0; + char *result = NULL; + assert(argc==1); + + if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { + sqlite3_result_null(context); + return; + } + + const unsigned char *rawData = sqlite3_value_blob(argv[0]); + const int dataLength = sqlite3_value_bytes(argv[0]); + + // Check for valid plist header + if (!rawData || dataLength < 8 || memcmp(rawData, "bplist00", 8) != 0) { + // Not a plist, return original value + if (sqlite3_value_type(argv[0]) == SQLITE_TEXT) { + sqlite3_result_text(context, (const char *)rawData, dataLength, NULL); + } else { + sqlite3_result_blob(context, rawData, dataLength, NULL); + } + return; + } + + errorCode = parsePlist(&result, (const char *)rawData, dataLength); + if (errorCode == ERROR_NONE) { + int resultLength = strlen(result); + sqlite3_result_text(context, result, resultLength, &freeResult); + } else { + // On error, return original value + if (sqlite3_value_type(argv[0]) == SQLITE_TEXT) { + sqlite3_result_text(context, (const char *)rawData, dataLength, NULL); + } else { + sqlite3_result_blob(context, rawData, dataLength, NULL); + } + } +} + +static void encodeBase64Func(sqlite3_context *context, int argc, sqlite3_value **argv) { + int resultLength; + int errorCode = 0; + int dataLength; + const unsigned char *rawData; + char *result = NULL; + assert(argc==1); + switch(sqlite3_value_type(argv[0])) { + case SQLITE_BLOB: + rawData = sqlite3_value_blob(argv[0]); + dataLength = sqlite3_value_bytes(argv[0]); + errorCode = encodeBase64(&result, rawData, dataLength); + if (errorCode == ERROR_NONE) { + resultLength = strlen(result); + sqlite3_result_text(context, result, resultLength, &freeResult); + } else { + sqlite3_result_blob(context, rawData, dataLength, NULL); + } + break; + case SQLITE_TEXT: { + rawData = sqlite3_value_text(argv[0]); + dataLength = sqlite3_value_bytes(argv[0]); + sqlite3_result_text(context, (const char *)rawData, dataLength, NULL); + errorCode = encodeBase64(&result, rawData, dataLength); + if (errorCode == ERROR_NONE) { + resultLength = strlen(result); + sqlite3_result_text(context, result, resultLength, &freeResult); + } else { + sqlite3_result_text(context, (const char *)rawData, dataLength, NULL); + } + break; + } + default: { + sqlite3_result_null(context); + break; + } + } +} + + +/*** isText + * + * Returns zero if supplied data is entirely + * ASCII printable characters or white space. + */ + +int isText(unsigned char *data, int dataLength) +{ + static unsigned char map[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 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, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + int result = 0; + for (int i=0; i < dataLength; i++) + result |= map[*(data++)]; + return result; +} + +/** isUTF8 + * + * Returns one if the characters conform to UTF8 format in so + * far as all the byte lengths are consistent. It does not + * check for overlong encodings or invalid characters. A zero + * is returned if the format is not consistent. + * Note that a file of all zeros will be returned as UTF8. + */ + +int isUTF8(unsigned char *data, int length) +{ + int count = 0; + while (length-- > 0) { + unsigned char d = *(data++); + switch (count) { + case 0: /* First character */ + if ((d & 0x80) == 0) + continue; /* 7 bit ASCII */ + if ((d & 0xE0) == 0xC0) { + count = 1; /* 2 byte code */ + break; + } + if ((d & 0xF0) == 0xE0) { + count = 2; /* 3 byte code */ + break; + } + if ((d & 0xF8) == 0xF0) { + count = 3; /* 4 byte code */ + break; + } + return 0; + default: + count--; + if ((d & 0xC0) != 0x80) + return 0; + break; + } + } + return (count == 0) ? 1 : 0; +} + +static void decodeBase64Func(sqlite3_context *context, int argc, sqlite3_value **argv){ + int resultLength; + int errorCode = 0; + unsigned char *result = NULL; + assert( argc==1 ); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_BLOB: + case SQLITE_TEXT: { + const char *data = (const char *)sqlite3_value_text(argv[0]); + int dataLength = sqlite3_value_bytes(argv[0]); + errorCode = decodeBase64(&result, &resultLength, data, dataLength); + if (errorCode == ERROR_NONE) { + if (isUTF8(result, resultLength)) + sqlite3_result_text(context, (const char *)result, resultLength, &freeResult); + else + sqlite3_result_blob(context, result, resultLength, &freeResult); + } else { + if (sqlite3_value_type(argv[0]) == SQLITE_TEXT) + sqlite3_result_text(context, (const char *)data, dataLength, NULL); + else + sqlite3_result_blob(context, data, dataLength, NULL); + } + break; + } + default: { + sqlite3_result_null(context); + break; + } + } +} + +int isJsonString(const char *text) { + if (!text) return 0; + int len = strlen(text); + if (len < 2) return 0; + + // Check if it starts with [ or { or " + return (text[0] == '[' || text[0] == '{' || (text[0] == '"' && text[1] != '{')); +} + +int outputJsonEscapedText(CONFIG *cfg, const char *text) { + int err = ERROR_NONE; + + // Check if text is a JSON string that starts with { + if (text && (text[0] == '{' || (text[0] == '"' && text[1] != '{'))) { + // Try to unescape the JSON string + char *unescaped = malloc(strlen(text) + 1); + if (!unescaped) return ERROR_INSUFFICIENT_MEMORY; + + const char *src = text; + char *dst = unescaped; + + while (*src) { + if (*src == '\\' && *(src + 1) == '"') { + *dst++ = '"'; + src += 2; + } else { + *dst++ = *src++; + } + } + *dst = '\0'; + + // Output the unescaped JSON directly + err = outputText(cfg, unescaped); + free(unescaped); + return err; + } + + // Original escaping logic for regular strings + while (*text && err == ERROR_NONE) { + switch (*text) { + case '"': + err = outputText(cfg, "\\\""); + break; + case '\\': + err = outputText(cfg, "\\\\"); + break; + case '\b': + err = outputText(cfg, "\\b"); + break; + case '\f': + err = outputText(cfg, "\\f"); + break; + case '\n': + err = outputText(cfg, "\\n"); + break; + case '\r': + err = outputText(cfg, "\\r"); + break; + case '\t': + err = outputText(cfg, "\\t"); + break; + default: + if ((unsigned char)*text < 32) { + char escaped[8]; + sprintf(escaped, "\\u%04x", (unsigned char)*text); + err = outputText(cfg, escaped); + } else { + char c[2] = {*text, 0}; + err = outputText(cfg, c); + } + } + text++; + } + return err; +} + +char* utf16_to_utf8(const short int* utf16, int length) { + char* utf8 = malloc(length * 3 + 1); // Max 3 bytes per char + null terminator + if (!utf8) return NULL; + + int j = 0; + for (int i = 0; i < length; i++) { + unsigned short uc = utf16[i]; + + if (uc < 0x80) { + utf8[j++] = (char)uc; + } else if (uc < 0x800) { + utf8[j++] = (char)(0xC0 | (uc >> 6)); + utf8[j++] = (char)(0x80 | (uc & 0x3F)); + } else { + utf8[j++] = (char)(0xE0 | (uc >> 12)); + utf8[j++] = (char)(0x80 | ((uc >> 6) & 0x3F)); + utf8[j++] = (char)(0x80 | (uc & 0x3F)); + } + } + + utf8[j] = '\0'; + return utf8; +} + +// Add new display function for JSON format +int displayObjectAsJson(CONFIG *cfg, OBJECT *obj, int raw) { + char text[32]; + switch (obj->type) { + case 0x00: // Singleton + if (strcmp(obj->data.text, "") == 0) + outputText(cfg, "true"); + else if (strcmp(obj->data.text, "") == 0) + outputText(cfg, "false"); + else if (strcmp(obj->data.text, "") == 0) + outputText(cfg, "null"); + else + outputText(cfg, "null"); + break; + case 0x01: // Integer + sprintf(text, "%ld", obj->data.integer); + outputText(cfg, text); + break; + case 0x02: // Float + sprintf(text, "%f", obj->data.real); + outputText(cfg, text); + break; + case 0x03: // Date + outputText(cfg, "\""); + outputText(cfg, ctime(&(obj->data.date))); + if (cfg->outputBuffer[cfg->outputBufferIn-1] == '\n') + cfg->outputBufferIn--; // Remove trailing newline + outputText(cfg, "\""); + break; + case 0x04: // Binary data + outputText(cfg, "\"\""); + break; + case 0x05: // String + if (isJsonString(obj->data.text)) { + // If it's already JSON, output it directly + outputText(cfg, obj->data.text); + } else { + // Otherwise treat as regular string + outputText(cfg, "\""); + outputJsonEscapedText(cfg, obj->data.text); + outputText(cfg, "\""); + } + break; + case 0x06: // UTF16 string + { + char* utf8 = utf16_to_utf8(obj->data.utf16, obj->length); + if (utf8) { + if (isJsonString(utf8)) { + // If it's already JSON, output directly + outputText(cfg, utf8); + } else { + // Otherwise wrap in quotes and escape + outputText(cfg, "\""); + outputJsonEscapedText(cfg, utf8); + outputText(cfg, "\""); + } + free(utf8); + } else { + outputText(cfg, "\"\""); + } + } + break; + case 0x08: // UID + sprintf(text, "%lu", obj->data.uid); + outputText(cfg, text); + break; + case 0x0A: // Array + outputText(cfg, "["); + for (int i=0; i < obj->length; i++) { + displayObjectAsJson(cfg, obj->data.objects[i], 0); + if (i < obj->length - 1) + outputText(cfg, ","); + } + outputText(cfg, "]"); + break; + case 0x0D: // Dictionary + outputText(cfg, "{"); + for (int i=0; i < obj->length; i++) { + // Check if key is already JSON + if (!isJsonString(obj->data.keys[i].key->data.text)) { + outputText(cfg, "\""); + displayObject(cfg, obj->data.keys[i].key, 1); + outputText(cfg, "\""); + } else { + displayObject(cfg, obj->data.keys[i].key, 1); + } + outputText(cfg, ":"); + displayObjectAsJson(cfg, obj->data.keys[i].value, 0); + if (i < obj->length - 1) + outputText(cfg, ","); + } + outputText(cfg, "}"); + break; + default: + sprintf(text, "\"\"", obj->type); + outputText(cfg, text); + break; + } + return ERROR_NONE; +} + +// Add new function to parse plist to JSON +int parsePlistToJson(char **result, const char *data, int dataLength) { + CONFIG cfg; + char *ptr; + OBJECT *obj; + int err = ERROR_NONE; + long length; + + // Determine the file size and save + cfg.buffer = (unsigned char *)data; + cfg.bufferLength = dataLength; + + // Preset the output buffer + cfg.outputBufferLength = 0; + cfg.outputBufferIn = 0; + cfg.outputBuffer = NULL; + + // Read the header + err = readHeader(&cfg); + if (err != ERROR_NONE) + return err; + + // Read the trailer + err = readTrailer(&cfg); + if (err != ERROR_NONE) + return err; + + // Locate and read the root object + long offset = cfg.offsetTable[cfg.rootObjectReference]; + err = readObject(&cfg, offset, &obj); + + // If no error display the root object and hence the whole object tree + if (err != ERROR_NONE) + return err; + + displayObjectAsJson(&cfg, obj, 0); + + // Create return data + length = strlen((const char *)(cfg.outputBuffer)); + ptr = malloc(length + 1); + *result = ptr; + if (ptr != NULL) { + for (int i=0; i < length; i++) + *(ptr++) = cfg.outputBuffer[i]; + *ptr = '\0'; + } + else + err = ERROR_INSUFFICIENT_MEMORY; + + // Release assigned memory + releaseObject(obj); + free(cfg.offsetTable); + free(cfg.outputBuffer); + return err; +} + +// Add the new function to SQLite +static void plistToJsonFunc(sqlite3_context *context, int argc, sqlite3_value **argv) { + int errorCode = 0; + char *result = NULL; + assert(argc==1); + + if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { + sqlite3_result_null(context); + return; + } + + const unsigned char *rawData = sqlite3_value_blob(argv[0]); + const int dataLength = sqlite3_value_bytes(argv[0]); + + // Check for valid plist header + if (!rawData || dataLength < 8 || memcmp(rawData, "bplist00", 8) != 0) { + // Not a plist, return original value + if (sqlite3_value_type(argv[0]) == SQLITE_TEXT) { + sqlite3_result_text(context, (const char *)rawData, dataLength, NULL); + } else { + sqlite3_result_blob(context, rawData, dataLength, NULL); + } + return; + } + + errorCode = parsePlistToJson(&result, (const char *)rawData, dataLength); + if (errorCode == ERROR_NONE) { + int resultLength = strlen(result); + sqlite3_result_text(context, result, resultLength, &freeResult); + } else { + // On error, return original value + if (sqlite3_value_type(argv[0]) == SQLITE_TEXT) { + sqlite3_result_text(context, (const char *)rawData, dataLength, NULL); + } else { + sqlite3_result_blob(context, rawData, dataLength, NULL); + } + } +} + +// Add these helper functions for NSKeyedArchiver deserialization +int isNSKeyedArchiver(OBJECT *obj) { + if (obj->type != 0x0D) return 0; + + for (int i = 0; i < obj->length; i++) { + OBJECT *key = obj->data.keys[i].key; + if (key->type == 0x05 && strcmp(key->data.text, "$archiver") == 0) { + OBJECT *value = obj->data.keys[i].value; + if (value->type == 0x05 && strcmp(value->data.text, "NSKeyedArchiver") == 0) { + return 1; + } + } + } + return 0; +} + +OBJECT* findObjectByUID(CONFIG *cfg, int uid) { + if (uid >= cfg->objectCount) + return NULL; + long offset = cfg->offsetTable[uid]; + OBJECT *obj; + if (readObject(cfg, offset, &obj) != ERROR_NONE) + return NULL; + return obj; +} + +// Add this helper function to get actual object from reference +OBJECT* resolveReference(CONFIG *cfg, OBJECT *objects, OBJECT *ref) { + if (!ref || !objects) return NULL; + + if (ref->type == 0x01) { // Direct integer reference + int index = ref->data.integer; + if (index >= 0 && index < objects->length) { + return objects->data.objects[index]; + } + } + return ref; // Return original if not a reference +} + +// Add this helper function to get the actual value from an index +OBJECT* getObjectAtIndex(OBJECT *objects, int index) { + if (!objects || objects->type != 0x0A || index < 0 || index >= objects->length) { + return NULL; + } + return objects->data.objects[index]; +} + +// Helper function to get object from $objects array by index +OBJECT* getObjectByIndex(OBJECT *objects, int index) { + if (!objects || objects->type != 0x0A || index < 0 || index >= objects->length) { + return NULL; + } + return objects->data.objects[index]; +} + +// Helper function to get value from dictionary by key +OBJECT* getDictValue(OBJECT *dict, const char *key) { + if (!dict || dict->type != 0x0D || !key) return NULL; + + for (int i = 0; i < dict->length; i++) { + OBJECT *k = dict->data.keys[i].key; + if (k && k->type == 0x05 && strcmp(k->data.text, key) == 0) { + return dict->data.keys[i].value; + } + } + return NULL; +} + +// Helper function to get integer value from object +int getIntegerValue(OBJECT *obj) { + if (!obj) return -1; + + switch (obj->type) { + case 0x01: // Integer + return obj->data.integer; + case 0x08: // UID + return (int)obj->data.uid; + default: + return -1; + } +} + +OBJECT* resolveObject(OBJECT *objects, int index) { + if (!objects || index < 0 || index >= objects->length) { + return NULL; + } + + OBJECT *obj = getObjectByIndex(objects, index); + if (!obj) return NULL; + + // If it's a dictionary with NS.keys and NS.objects, resolve it + if (obj->type == 0x0D) { + OBJECT *nsKeys = getDictValue(obj, "NS.keys"); + OBJECT *nsObjects = getDictValue(obj, "NS.objects"); + + if (nsKeys && nsObjects && + nsKeys->type == 0x0A && nsObjects->type == 0x0A && + nsKeys->length == nsObjects->length && + nsKeys->length > 0) { + + OBJECT *result; + int err = createObject(0x0D, nsKeys->length, (nsKeys->length - 1) * sizeof(KEY), &result); + if (err != ERROR_NONE || !result) { + return NULL; + } + + for (int i = 0; i < nsKeys->length; i++) { + int keyIndex = getIntegerValue(nsKeys->data.objects[i]); + int valueIndex = getIntegerValue(nsObjects->data.objects[i]); + + if (keyIndex >= 0 && keyIndex < objects->length && + valueIndex >= 0 && valueIndex < objects->length) { + + OBJECT *key = getObjectByIndex(objects, keyIndex); + if (key) { + size_t extraSize = 0; + switch (key->type) { + case 0x06: // UTF16 string + extraSize = key->length * 2; // 2 bytes per character + break; + case 0x05: // Regular string + extraSize = key->length + 1; // Include null terminator + break; + case 0x0A: // Array + extraSize = key->length * sizeof(OBJECT*); + break; + case 0x0D: // Dictionary + extraSize = key->length * sizeof(KEY); + break; + default: + extraSize = key->length; + break; + } + + err = createObject(key->type, key->length, extraSize, &result->data.keys[i].key); + if (err == ERROR_NONE && result->data.keys[i].key) { + if (key->type == 0x06) { + memcpy(result->data.keys[i].key->data.utf16, key->data.utf16, key->length * 2); + } else { + memcpy(&result->data.keys[i].key->data, &key->data, extraSize); + } + } + + result->data.keys[i].value = resolveObject(objects, valueIndex); + } + } + } + return result; + } + } + + OBJECT *copy; + size_t extraSize = 0; + + switch (obj->type) { + case 0x06: // UTF16 string + extraSize = obj->length * 2; // 2 bytes per character + break; + case 0x05: // Regular string + extraSize = obj->length + 1; // Include null terminator + break; + case 0x0A: // Array + extraSize = obj->length * sizeof(OBJECT*); + break; + case 0x0D: // Dictionary + extraSize = obj->length * sizeof(KEY); + break; + default: + extraSize = obj->length; + break; + } + + int err = createObject(obj->type, obj->length, extraSize, ©); + if (err == ERROR_NONE && copy) { + if (obj->type == 0x06) { + memcpy(copy->data.utf16, obj->data.utf16, obj->length * 2); + } else { + memcpy(©->data, &obj->data, extraSize); + } + } + return copy; +} + +OBJECT* convertNSKeyedArchiver(OBJECT *archiver) { + if (!archiver || archiver->type != 0x0D) { + return NULL; + } + + // Get $objects array + OBJECT *objects = getDictValue(archiver, "$objects"); + if (!objects || objects->type != 0x0A || objects->length == 0) { + return NULL; + } + + // Get root object reference from $top + OBJECT *top = getDictValue(archiver, "$top"); + if (!top || top->type != 0x0D) { + return NULL; + } + + OBJECT *rootRef = getDictValue(top, "root"); + if (!rootRef) { + return NULL; + } + + int rootIndex = getIntegerValue(rootRef); + if (rootIndex < 0 || rootIndex >= objects->length) { + return NULL; + } + + // Get actual root object + OBJECT *root = getObjectByIndex(objects, rootIndex); + if (!root) { + return NULL; + } + + // If root is a dictionary with NS.keys and NS.objects, create new dict + if (root->type == 0x0D) { + OBJECT *nsKeys = getDictValue(root, "NS.keys"); + OBJECT *nsObjects = getDictValue(root, "NS.objects"); + + if (nsKeys && nsObjects && + nsKeys->type == 0x0A && nsObjects->type == 0x0A && + nsKeys->length == nsObjects->length && + nsKeys->length > 0) { + + OBJECT *result; + int err = createObject(0x0D, nsKeys->length, (nsKeys->length - 1) * sizeof(KEY), &result); + if (err != ERROR_NONE || !result) { + return NULL; + } + + for (int i = 0; i < nsKeys->length; i++) { + int keyIndex = getIntegerValue(nsKeys->data.objects[i]); + int valueIndex = getIntegerValue(nsObjects->data.objects[i]); + + if (keyIndex >= 0 && keyIndex < objects->length && + valueIndex >= 0 && valueIndex < objects->length) { + + OBJECT *key = getObjectByIndex(objects, keyIndex); + if (key) { + size_t extraSize = 0; + switch (key->type) { + case 0x06: // UTF16 string + extraSize = key->length * 2; // 2 bytes per character + break; + case 0x05: // Regular string + extraSize = key->length + 1; // Include null terminator + break; + case 0x0A: // Array + extraSize = key->length * sizeof(OBJECT*); + break; + case 0x0D: // Dictionary + extraSize = key->length * sizeof(KEY); + break; + default: + extraSize = key->length; + break; + } + + err = createObject(key->type, key->length, extraSize, &result->data.keys[i].key); + if (err == ERROR_NONE && result->data.keys[i].key) { + if (key->type == 0x06) { + memcpy(result->data.keys[i].key->data.utf16, key->data.utf16, key->length * 2); + } else { + memcpy(&result->data.keys[i].key->data, &key->data, extraSize); + } + } + + result->data.keys[i].value = resolveObject(objects, valueIndex); + } + } + } + return result; + } + } + + return resolveObject(objects, rootIndex); +} + +// Add new function for deserialized JSON conversion +int parsePlistDeserializedToJson(char **result, const char *data, int dataLength) { + CONFIG cfg; + char *ptr; + OBJECT *obj; + int err = ERROR_NONE; + long length; + + // Determine the file size and save + cfg.buffer = (unsigned char *)data; + cfg.bufferLength = dataLength; + + // Preset the output buffer + cfg.outputBufferLength = 0; + cfg.outputBufferIn = 0; + cfg.outputBuffer = NULL; + + // Read the header + err = readHeader(&cfg); + if (err != ERROR_NONE) + return err; + + // Read the trailer + err = readTrailer(&cfg); + if (err != ERROR_NONE) + return err; + + // Locate and read the root object + long offset = cfg.offsetTable[cfg.rootObjectReference]; + err = readObject(&cfg, offset, &obj); + + // If no error display the root object and hence the whole object tree + if (err != ERROR_NONE) + return err; + + // Check if this is an NSKeyedArchiver plist + if (isNSKeyedArchiver(obj)) { + OBJECT *deserializedObj = convertNSKeyedArchiver(obj); + if (deserializedObj) { + // Free original object and use deserialized version + releaseObject(obj); + obj = deserializedObj; + } + } + + displayObjectAsJson(&cfg, obj, 0); + + // Create return data + length = strlen((const char *)(cfg.outputBuffer)); + ptr = malloc(length + 1); + *result = ptr; + if (ptr != NULL) { + for (int i=0; i < length; i++) + *(ptr++) = cfg.outputBuffer[i]; + *ptr = '\0'; + } + else + err = ERROR_INSUFFICIENT_MEMORY; + + // Release assigned memory + releaseObject(obj); + free(cfg.offsetTable); + free(cfg.outputBuffer); + return err; +} + +// Add the new function to SQLite +static void plistDeserializedToJsonFunc(sqlite3_context *context, int argc, sqlite3_value **argv) { + int errorCode = 0; + char *result = NULL; + assert(argc==1); + + if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { + sqlite3_result_null(context); + return; + } + + const unsigned char *rawData = sqlite3_value_blob(argv[0]); + const int dataLength = sqlite3_value_bytes(argv[0]); + + // Check for valid plist header + if (!rawData || dataLength < 8 || memcmp(rawData, "bplist00", 8) != 0) { + // Not a plist, return original value + if (sqlite3_value_type(argv[0]) == SQLITE_TEXT) { + sqlite3_result_text(context, (const char *)rawData, dataLength, NULL); + } else { + sqlite3_result_blob(context, rawData, dataLength, NULL); + } + return; + } + + errorCode = parsePlistDeserializedToJson(&result, (const char *)rawData, dataLength); + if (errorCode == ERROR_NONE) { + int resultLength = strlen(result); + sqlite3_result_text(context, result, resultLength, &freeResult); + } else { + // On error, return original value + if (sqlite3_value_type(argv[0]) == SQLITE_TEXT) { + sqlite3_result_text(context, (const char *)rawData, dataLength, NULL); + } else { + sqlite3_result_blob(context, rawData, dataLength, NULL); + } + } +} + +static void load_formats_builtin(sqlite3_context *context, int argc, sqlite3_value **argv) { + // Return format: "Display Name|internal_name|function_name" + const char *result = "Plist as JSON|plistjson|plistToJson\n" + "Plist as JSON (Deserialized)|plistdesjson|plistDeserializedToJson\n" + "Plist as XML|plistxml|plist\n" + "Base64 Decode|base64|unBase64\n" + "Base64 Encode|base64|toBase64"; + sqlite3_result_text(context, result, -1, SQLITE_TRANSIENT); +} + +/** RegisterExtensionFormats + * + * Register the parsing functions with sqlite + */ + +int RegisterExtensionFormats(sqlite3 *db) { + sqlite3_create_function(db, "plist", 1, 0, db, plistFunc, 0, 0); + sqlite3_create_function(db, "plistToJson", 1, 0, db, plistToJsonFunc, 0, 0); + sqlite3_create_function(db, "plistDeserializedToJson", 1, 0, db, plistDeserializedToJsonFunc, 0, 0); + sqlite3_create_function(db, "unBase64", 1, 0, db, decodeBase64Func, 0, 0); + sqlite3_create_function(db, "toBase64", 1, 0, db, encodeBase64Func, 0, 0); + + // Register the display format + sqlite3_create_function(db, "load_formats_builtin", 0, SQLITE_UTF8, NULL, load_formats_builtin, NULL, NULL); + + return ERROR_NONE; +} + +#ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE + +#ifdef _WIN32 +__declspec(dllexport) +#endif + +int sqlite3_extension_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi) +{ + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); + RegisterExtensionFormats(db); + return rc; +} + +#endif + + diff --git a/src/extensions/extension-formats.def b/src/extensions/extension-formats.def new file mode 100644 index 000000000..2bfb84fb2 --- /dev/null +++ b/src/extensions/extension-formats.def @@ -0,0 +1,5 @@ +EXPORTS + RegisterExtensionFormats + sqlite3_api + sqlite3_extension_init + freeResult diff --git a/src/extensions/extension-functions.c b/src/extensions/extension-functions.c new file mode 100644 index 000000000..cb43fbbbd --- /dev/null +++ b/src/extensions/extension-functions.c @@ -0,0 +1,1947 @@ +/* +This library will provide common mathematical and string functions in +SQL queries using the operating system libraries or provided +definitions. It includes the following functions: + +Math: acos, asin, atan, atn2, atan2, acosh, asinh, atanh, difference, +degrees, radians, cos, sin, tan, cot, cosh, sinh, tanh, coth, exp, +log, log10, power, sign, sqrt, square, ceil, floor, pi. + +String: replicate, charindex, leftstr, rightstr, ltrim, rtrim, trim, +replace, reverse, proper, padl, padr, padc, strfilter. + +Aggregate: stdev, variance, mode, median, lower_quartile, +upper_quartile. + +The string functions ltrim, rtrim, trim, replace are included in +recent versions of SQLite and so by default do not build. + +Compilation instructions: + Compile this C source file into a dynamic library as follows: + * Linux: + gcc -fPIC -lm -shared extension-functions.c -o libsqlitefunctions.so + * macOS: + gcc -fno-common -dynamiclib extension-functions.c -o libsqlitefunctions.dylib + (You may need to add flags + -I /opt/local/include/ -L/opt/local/lib -lsqlite3 + if your sqlite3 is installed from Mac ports, or + -I /sw/include/ -L/sw/lib -lsqlite3 + if installed with Fink.) + * Windows: + 1. Install MinGW (http://www.mingw.org/) and you will get the gcc + (gnu compiler collection) + 2. add the path to your path variable (isn't done during the + installation!) + 3. compile: + gcc -shared -I "path" -o libsqlitefunctions.so extension-functions.c + (path = path of sqlite3ext.h; i.e. C:\programs\sqlite) + +Usage instructions for applications calling the sqlite3 API functions: + In your application, call sqlite3_enable_load_extension(db,1) to + allow loading external libraries. Then load the library libsqlitefunctions + using sqlite3_load_extension; the third argument should be 0. + See http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions. + Select statements may now use these functions, as in + SELECT cos(radians(inclination)) FROM satsum WHERE satnum = 25544; + +Usage instructions for the sqlite3 program: + If the program is built so that loading extensions is permitted, + the following will work: + sqlite> SELECT load_extension('./libsqlitefunctions.so'); + sqlite> select cos(radians(45)); + 0.707106781186548 + Note: Loading extensions is by default prohibited as a + security measure; see "Security Considerations" in + http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions. + If the sqlite3 program and library are built this + way, you cannot use these functions from the program, you + must write your own program using the sqlite3 API, and call + sqlite3_enable_load_extension as described above, or else + rebuilt the sqlite3 program to allow loadable extensions. + +Alterations: +The instructions are for Linux, Mac OS X, and Windows; users of other +OSes may need to modify this procedure. In particular, if your math +library lacks one or more of the needed trig or log functions, comment +out the appropriate HAVE_ #define at the top of file. If you do not +wish to make a loadable module, comment out the define for +COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE. If you are using a +version of SQLite without the trim functions and replace, comment out +the HAVE_TRIM #define. + +Liam Healy + +History: +2010-01-06 Correct check for argc in squareFunc, and add Windows +compilation instructions. +2009-06-24 Correct check for argc in properFunc. +2008-09-14 Add check that memory was actually allocated after +sqlite3_malloc or sqlite3StrDup, call sqlite3_result_error_nomem if +not. Thanks to Robert Simpson. +2008-06-13 Change to instructions to indicate use of the math library +and that program might work. +2007-10-01 Minor clarification to instructions. +2007-09-29 Compilation as loadable module is optional with +COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE. +2007-09-28 Use sqlite3_extension_init and macros +SQLITE_EXTENSION_INIT1, SQLITE_EXTENSION_INIT2, so that it works with +sqlite3_load_extension. Thanks to Eric Higashino and Joe Wilson. +New instructions for Mac compilation. +2007-09-17 With help from Joe Wilson and Nuno Luca, made use of +external interfaces so that compilation is no longer dependent on +SQLite source code. Merged source, header, and README into a single +file. Added casts so that Mac will compile without warnings (unsigned +and signed char). +2007-09-05 Included some definitions from sqlite 3.3.13 so that this +will continue to work in newer versions of sqlite. Completed +description of functions available. +2007-03-27 Revised description. +2007-03-23 Small cleanup and a bug fix on the code. This was mainly +letting errno flag errors encountered in the math library and checking +the result, rather than pre-checking. This fixes a bug in power that +would cause an error if any non-positive number was raised to any +power. +2007-02-07 posted by Mikey C to sqlite mailing list. +Original code 2006 June 05 by relicoder. + +*/ + +//#include "config.h" + +#define COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE 1 +#define HAVE_ACOSH 1 +#define HAVE_ASINH 1 +#define HAVE_ATANH 1 +#define HAVE_SINH 1 +#define HAVE_COSH 1 +#define HAVE_TANH 1 +#define HAVE_LOG10 1 +#define HAVE_ISBLANK 1 +#define SQLITE_SOUNDEX 1 +#define HAVE_TRIM 1 /* LMH 2007-03-25 if sqlite has trim functions */ + +#ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 +#else +#include "sqlite3.h" +#endif + +#include +/* relicoder */ +#include +#include +#include +#include /* LMH 2007-03-25 */ + +#include +#include + +#ifndef _MAP_H_ +#define _MAP_H_ + +#include + +/* +** Simple binary tree implementation to use in median, mode and quartile calculations +** Tree is not necessarily balanced. That would require something like red&black trees of AVL +*/ + +typedef int(*cmp_func)(const void *, const void *); +typedef void(*map_iterator)(void*, int64_t, void*); + +typedef struct node{ + struct node *l; + struct node *r; + void* data; + int64_t count; +} node; + +typedef struct map{ + node *base; + cmp_func cmp; + short free; +} map; + +/* +** creates a map given a comparison function +*/ +map map_make(cmp_func cmp); + +/* +** inserts the element e into map m +*/ +void map_insert(map *m, void *e); + +/* +** executes function iter over all elements in the map, in key increasing order +*/ +void map_iterate(map *m, map_iterator iter, void* p); + +/* +** frees all memory used by a map +*/ +void map_destroy(map *m); + +/* +** compares 2 integers +** to use with map_make +*/ +int int_cmp(const void *a, const void *b); + +/* +** compares 2 doubles +** to use with map_make +*/ +int double_cmp(const void *a, const void *b); + +#endif /* _MAP_H_ */ + +typedef uint8_t u8; +typedef uint16_t u16; +typedef int64_t i64; + +static char *sqlite3StrDup( const char *z ) { + char *res = sqlite3_malloc( strlen(z)+1 ); + return strcpy( res, z ); +} + +/* +** These are copied verbatim from fun.c so as to not have the names exported +*/ + +/* LMH from sqlite3 3.3.13 */ +/* +** This table maps from the first byte of a UTF-8 character to the number +** of trailing bytes expected. A value '4' indicates that the table key +** is not a legal first byte for a UTF-8 character. +*/ +static const u8 xtra_utf8_bytes[256] = { +/* 0xxxxxxx */ +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, + +/* 10wwwwww */ +4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + +/* 110yyyyy */ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + +/* 1110zzzz */ +2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + +/* 11110yyy */ +3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, +}; + + +/* +** This table maps from the number of trailing bytes in a UTF-8 character +** to an integer constant that is effectively calculated for each character +** read by a naive implementation of a UTF-8 character reader. The code +** in the READ_UTF8 macro explains things best. +*/ +static const int xtra_utf8_bits[] = { + 0, + 12416, /* (0xC0 << 6) + (0x80) */ + 925824, /* (0xE0 << 12) + (0x80 << 6) + (0x80) */ + 63447168 /* (0xF0 << 18) + (0x80 << 12) + (0x80 << 6) + 0x80 */ +}; + +/* +** If a UTF-8 character contains N bytes extra bytes (N bytes follow +** the initial byte so that the total character length is N+1) then +** masking the character with utf8_mask[N] must produce a non-zero +** result. Otherwise, we have an (illegal) overlong encoding. +*/ +static const int utf_mask[] = { + 0x00000000, + 0xffffff80, + 0xfffff800, + 0xffff0000, +}; + +/* LMH salvaged from sqlite3 3.3.13 source code src/utf.c */ +#define READ_UTF8(zIn, c) { \ + int xtra; \ + c = *(zIn)++; \ + xtra = xtra_utf8_bytes[c]; \ + switch( xtra ){ \ + case 4: c = (int)0xFFFD; break; \ + case 3: c = (c<<6) + *(zIn)++; \ + case 2: c = (c<<6) + *(zIn)++; \ + case 1: c = (c<<6) + *(zIn)++; \ + c -= xtra_utf8_bits[xtra]; \ + if( (utf_mask[xtra]&c)==0 \ + || (c&0xFFFFF800)==0xD800 \ + || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ + } \ +} + +static int sqlite3ReadUtf8(const unsigned char *z){ + int c; + READ_UTF8(z, c); + return c; +} + +#define SKIP_UTF8(zIn) { \ + zIn += (xtra_utf8_bytes[*(u8 *)zIn] + 1); \ +} + +/* +** pZ is a UTF-8 encoded unicode string. If nByte is less than zero, +** return the number of unicode characters in pZ up to (but not including) +** the first 0x00 byte. If nByte is not less than zero, return the +** number of unicode characters in the first nByte of pZ (or up to +** the first 0x00, whichever comes first). +*/ +static int sqlite3Utf8CharLen(const char *z, int nByte){ + int r = 0; + const char *zTerm; + if( nByte>=0 ){ + zTerm = &z[nByte]; + }else{ + zTerm = (const char *)(-1); + } + assert( z<=zTerm ); + while( *z!=0 && z 0) ? 1: ( iVal < 0 ) ? -1: 0; + sqlite3_result_int64(context, iVal); + break; + } + case SQLITE_NULL: { + sqlite3_result_null(context); + break; + } + default: { + /* 2nd change below. Line for abs was: if( rVal<0 ) rVal = rVal * -1.0; */ + + rVal = sqlite3_value_double(argv[0]); + rVal = ( rVal > 0) ? 1: ( rVal < 0 ) ? -1: 0; + sqlite3_result_double(context, rVal); + break; + } + } +} + + +/* +** smallest integer value not less than argument +*/ +static void ceilFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + double rVal=0.0; + i64 iVal=0; + assert( argc==1 ); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_INTEGER: { + i64 iVal = sqlite3_value_int64(argv[0]); + sqlite3_result_int64(context, iVal); + break; + } + case SQLITE_NULL: { + sqlite3_result_null(context); + break; + } + default: { + rVal = sqlite3_value_double(argv[0]); + sqlite3_result_int64(context, (i64) ceil(rVal)); + break; + } + } +} + +/* +** largest integer value not greater than argument +*/ +static void floorFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + double rVal=0.0; + i64 iVal=0; + assert( argc==1 ); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_INTEGER: { + i64 iVal = sqlite3_value_int64(argv[0]); + sqlite3_result_int64(context, iVal); + break; + } + case SQLITE_NULL: { + sqlite3_result_null(context); + break; + } + default: { + rVal = sqlite3_value_double(argv[0]); + sqlite3_result_int64(context, (i64) floor(rVal)); + break; + } + } +} + +/* +** Given a string (s) in the first argument and an integer (n) in the second returns the +** string that constains s contatenated n times +*/ +static void replicateFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + unsigned char *z; /* input string */ + unsigned char *zo; /* result string */ + i64 iCount; /* times to repeat */ + i64 nLen; /* length of the input string (no multibyte considerations) */ + i64 nTLen; /* length of the result string (no multibyte considerations) */ + i64 i=0; + + if( argc!=2 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) + return; + + iCount = sqlite3_value_int64(argv[1]); + + if( iCount<0 ){ + sqlite3_result_error(context, "domain error", -1); + }else{ + + nLen = sqlite3_value_bytes(argv[0]); + nTLen = nLen*iCount; + z=sqlite3_malloc(nTLen+1); + zo=sqlite3_malloc(nLen+1); + if (!z || !zo){ + sqlite3_result_error_nomem(context); + if (z) sqlite3_free(z); + if (zo) sqlite3_free(zo); + return; + } + strcpy((char*)zo, (char*)sqlite3_value_text(argv[0])); + + for(i=0; i=n it's a NOP +** padl(NULL) = NULL +*/ +static void padlFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + i64 ilen; /* length to pad to */ + i64 zl; /* length of the input string (UTF-8 chars) */ + int i = 0; + const char *zi; /* input string */ + char *zo; /* output string */ + char *zt; + + assert( argc==2 ); + + if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ + sqlite3_result_null(context); + }else{ + zi = (char *)sqlite3_value_text(argv[0]); + ilen = sqlite3_value_int64(argv[1]); + /* check domain */ + if(ilen<0){ + sqlite3_result_error(context, "domain error", -1); + return; + } + zl = sqlite3Utf8CharLen(zi, -1); + if( zl>=ilen ){ + /* string is longer than the requested pad length, return the same string (dup it) */ + zo = sqlite3StrDup(zi); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + }else{ + zo = sqlite3_malloc(strlen(zi)+ilen-zl+1); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + zt = zo; + for(i=1; i+zl<=ilen; ++i){ + *(zt++)=' '; + } + /* no need to take UTF-8 into consideration here */ + strcpy(zt,zi); + } + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + sqlite3_free(zo); + } +} + +/* +** given an input string (s) and an integer (n) appends spaces at the end of s +** until it has a length of n characters. +** When s has a length >=n it's a NOP +** padl(NULL) = NULL +*/ +static void padrFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + i64 ilen; /* length to pad to */ + i64 zl; /* length of the input string (UTF-8 chars) */ + i64 zll; /* length of the input string (bytes) */ + int i = 0; + const char *zi; /* input string */ + char *zo; /* output string */ + char *zt; + + assert( argc==2 ); + + if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ + sqlite3_result_null(context); + }else{ + zi = (char *)sqlite3_value_text(argv[0]); + ilen = sqlite3_value_int64(argv[1]); + /* check domain */ + if(ilen<0){ + sqlite3_result_error(context, "domain error", -1); + return; + } + zl = sqlite3Utf8CharLen(zi, -1); + if( zl>=ilen ){ + /* string is longer than the requested pad length, return the same string (dup it) */ + zo = sqlite3StrDup(zi); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + }else{ + zll = strlen(zi); + zo = sqlite3_malloc(zll+ilen-zl+1); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + zt = strcpy(zo,zi)+zll; + for(i=1; i+zl<=ilen; ++i){ + *(zt++) = ' '; + } + *zt = '\0'; + } + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + sqlite3_free(zo); + } +} + +/* +** given an input string (s) and an integer (n) appends spaces at the end of s +** and adds spaces at the beginning of s until it has a length of n characters. +** Tries to add has many characters at the left as at the right. +** When s has a length >=n it's a NOP +** padl(NULL) = NULL +*/ +static void padcFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + i64 ilen; /* length to pad to */ + i64 zl; /* length of the input string (UTF-8 chars) */ + i64 zll; /* length of the input string (bytes) */ + int i = 0; + const char *zi; /* input string */ + char *zo; /* output string */ + char *zt; + + assert( argc==2 ); + + if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ + sqlite3_result_null(context); + }else{ + zi = (char *)sqlite3_value_text(argv[0]); + ilen = sqlite3_value_int64(argv[1]); + /* check domain */ + if(ilen<0){ + sqlite3_result_error(context, "domain error", -1); + return; + } + zl = sqlite3Utf8CharLen(zi, -1); + if( zl>=ilen ){ + /* string is longer than the requested pad length, return the same string (dup it) */ + zo = sqlite3StrDup(zi); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + }else{ + zll = strlen(zi); + zo = sqlite3_malloc(zll+ilen-zl+1); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + zt = zo; + for(i=1; 2*i+zl<=ilen; ++i){ + *(zt++) = ' '; + } + strcpy(zt, zi); + zt+=zll; + for(; i+zl<=ilen; ++i){ + *(zt++) = ' '; + } + *zt = '\0'; + } + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + sqlite3_free(zo); + } +} + +/* +** given 2 string (s1,s2) returns the string s1 with the characters NOT in s2 removed +** assumes strings are UTF-8 encoded +*/ +static void strfilterFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *zi1; /* first parameter string (searched string) */ + const char *zi2; /* second parameter string (vcontains valid characters) */ + const char *z1; + const char *z21; + const char *z22; + char *zo; /* output string */ + char *zot; + int c1 = 0; + int c2 = 0; + + assert( argc==2 ); + + if( sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL ){ + sqlite3_result_null(context); + }else{ + zi1 = (char *)sqlite3_value_text(argv[0]); + zi2 = (char *)sqlite3_value_text(argv[1]); + /* + ** maybe I could allocate less, but that would imply 2 passes, rather waste + ** (possibly) some memory + */ + zo = sqlite3_malloc(strlen(zi1)+1); + if (!zo){ + sqlite3_result_error_nomem(context); + return; + } + zot = zo; + z1 = zi1; + while( (c1=sqliteCharVal((unsigned char *)z1))!=0 ){ + z21=zi2; + while( (c2=sqliteCharVal((unsigned char *)z21))!=0 && c2!=c1 ){ + sqliteNextChar(z21); + } + if( c2!=0){ + z22=z21; + sqliteNextChar(z22); + strncpy(zot, z21, z22-z21); + zot+=z22-z21; + } + sqliteNextChar(z1); + } + *zot = '\0'; + + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + sqlite3_free(zo); + } +} + +/* +** Given a string z1, retutns the (0 based) index of it's first occurence +** in z2 after the first s characters. +** Returns -1 when there isn't a match. +** updates p to point to the character where the match occured. +** This is an auxiliary function. +*/ +static int _substr(const char* z1, const char* z2, int s, const char** p){ + int c = 0; + int rVal=-1; + const char* zt1; + const char* zt2; + int c1,c2; + + if( '\0'==*z1 ){ + return -1; + } + + while( (sqliteCharVal((unsigned char *)z2) != 0) && (c++)=0 ? rVal+s : rVal; +} + +/* +** given 2 input strings (s1,s2) and an integer (n) searches from the nth character +** for the string s1. Returns the position where the match occured. +** Characters are counted from 1. +** 0 is returned when no match occurs. +*/ + +static void charindexFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const u8 *z1; /* s1 string */ + u8 *z2; /* s2 string */ + int s=0; + int rVal=0; + + assert( argc==3 ||argc==2); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) || SQLITE_NULL==sqlite3_value_type(argv[1])){ + sqlite3_result_null(context); + return; + } + + z1 = sqlite3_value_text(argv[0]); + if( z1==0 ) return; + z2 = (u8*) sqlite3_value_text(argv[1]); + if(argc==3){ + s = sqlite3_value_int(argv[2])-1; + if(s<0){ + s=0; + } + }else{ + s = 0; + } + + rVal = _substr((char *)z1,(char *)z2,s,NULL); + sqlite3_result_int(context, rVal+1); +} + +/* +** given a string (s) and an integer (n) returns the n leftmost (UTF-8) characters +** if the string has a length<=n or is NULL this function is NOP +*/ +static void leftFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + int c=0; + int cc=0; + int l=0; + const unsigned char *z; /* input string */ + const unsigned char *zt; + unsigned char *rz; /* output string */ + + assert( argc==2); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) || SQLITE_NULL==sqlite3_value_type(argv[1])){ + sqlite3_result_null(context); + return; + } + + z = sqlite3_value_text(argv[0]); + l = sqlite3_value_int(argv[1]); + zt = z; + + while( sqliteCharVal(zt) && c++ 0 ){ + sqliteNextChar(zt); + } + + rz = sqlite3_malloc(ze-zt+1); + if (!rz){ + sqlite3_result_error_nomem(context); + return; + } + strcpy((char*) rz, (char*) (zt)); + sqlite3_result_text(context, (char*)rz, -1, SQLITE_TRANSIENT); + sqlite3_free(rz); +} + +#ifndef HAVE_TRIM +/* +** removes the whitespaces at the beginning of a string. +*/ +const char* ltrim(const char* s){ + while( *s==' ' ) + ++s; + return s; +} + +/* +** removes the whitespaces at the end of a string. +** !mutates the input string! +*/ +void rtrim(char* s){ + char* ss = s+strlen(s)-1; + while( ss>=s && *ss==' ' ) + --ss; + *(ss+1)='\0'; +} + +/* +** Removes the whitespace at the beginning of a string +*/ +static void ltrimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *z; + + assert( argc==1); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ + sqlite3_result_null(context); + return; + } + z = sqlite3_value_text(argv[0]); + sqlite3_result_text(context, ltrim(z), -1, SQLITE_TRANSIENT); +} + +/* +** Removes the whitespace at the end of a string +*/ +static void rtrimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *z; + char *rz; + /* try not to change data in argv */ + + assert( argc==1); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ + sqlite3_result_null(context); + return; + } + z = sqlite3_value_text(argv[0]); + rz = sqlite3StrDup(z); + rtrim(rz); + sqlite3_result_text(context, rz, -1, SQLITE_TRANSIENT); + sqlite3_free(rz); +} + +/* +** Removes the whitespace at the beginning and end of a string +*/ +static void trimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *z; + char *rz; + /* try not to change data in argv */ + + assert( argc==1); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ + sqlite3_result_null(context); + return; + } + z = sqlite3_value_text(argv[0]); + rz = sqlite3StrDup(z); + rtrim(rz); + sqlite3_result_text(context, ltrim(rz), -1, SQLITE_TRANSIENT); + sqlite3_free(rz); +} +#endif + +/* +** given a pointer to a string s1, the length of that string (l1), a new string (s2) +** and it's length (l2) appends s2 to s1. +** All lengths in bytes. +** This is just an auxiliary function +*/ +// static void _append(char **s1, int l1, const char *s2, int l2){ +// *s1 = realloc(*s1, (l1+l2+1)*sizeof(char)); +// strncpy((*s1)+l1, s2, l2); +// *(*(s1)+l1+l2) = '\0'; +// } + +#ifndef HAVE_TRIM + +/* +** given strings s, s1 and s2 replaces occurrences of s1 in s by s2 +*/ +static void replaceFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *z1; /* string s (first parameter) */ + const char *z2; /* string s1 (second parameter) string to look for */ + const char *z3; /* string s2 (third parameter) string to replace occurrences of s1 with */ + int lz1; + int lz2; + int lz3; + int lzo=0; + char *zo=0; + int ret=0; + const char *zt1; + const char *zt2; + + assert( 3==argc ); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ + sqlite3_result_null(context); + return; + } + + z1 = sqlite3_value_text(argv[0]); + z2 = sqlite3_value_text(argv[1]); + z3 = sqlite3_value_text(argv[2]); + /* handle possible null values */ + if( 0==z2 ){ + z2=""; + } + if( 0==z3 ){ + z3=""; + } + + lz1 = strlen(z1); + lz2 = strlen(z2); + lz3 = strlen(z3); + +#if 0 + /* special case when z2 is empty (or null) nothing will be changed */ + if( 0==lz2 ){ + sqlite3_result_text(context, z1, -1, SQLITE_TRANSIENT); + return; + } +#endif + + zt1=z1; + zt2=z1; + + while(1){ + ret=_substr(z2,zt1 , 0, &zt2); + + if( ret<0 ) + break; + + _append(&zo, lzo, zt1, zt2-zt1); + lzo+=zt2-zt1; + _append(&zo, lzo, z3, lz3); + lzo+=lz3; + + zt1=zt2+lz2; + } + _append(&zo, lzo, zt1, lz1-(zt1-z1)); + sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); + sqlite3_free(zo); +} +#endif + +/* +** given a string returns the same string but with the characters in reverse order +*/ +static void reverseFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *z; + const char *zt; + char *rz; + char *rzt; + int l = 0; + int i = 0; + + assert( 1==argc ); + + if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ + sqlite3_result_null(context); + return; + } + z = (char *)sqlite3_value_text(argv[0]); + l = strlen(z); + rz = sqlite3_malloc(l+1); + if (!rz){ + sqlite3_result_error_nomem(context); + return; + } + rzt = rz+l; + *(rzt--) = '\0'; + + zt=z; + while( sqliteCharVal((unsigned char *)zt)!=0 ){ + z=zt; + sqliteNextChar(zt); + for(i=1; zt-i>=z; ++i){ + *(rzt--)=*(zt-i); + } + } + + sqlite3_result_text(context, rz, -1, SQLITE_TRANSIENT); + sqlite3_free(rz); +} + +/* +** An instance of the following structure holds the context of a +** stdev() or variance() aggregate computation. +** implementaion of http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Algorithm_II +** less prone to rounding errors +*/ +typedef struct StdevCtx StdevCtx; +struct StdevCtx { + double rM; + double rS; + i64 cnt; /* number of elements */ +}; + +/* +** An instance of the following structure holds the context of a +** mode() or median() aggregate computation. +** Depends on structures defined in map.c (see map & map) +** These aggregate functions only work for integers and floats although +** they could be made to work for strings. This is usually considered meaningless. +** Only usuall order (for median), no use of collation functions (would this even make sense?) +*/ +typedef struct ModeCtx ModeCtx; +struct ModeCtx { + i64 riM; /* integer value found so far */ + double rdM; /* double value found so far */ + i64 cnt; /* number of elements so far */ + double pcnt; /* number of elements smaller than a percentile */ + i64 mcnt; /* maximum number of occurrences (for mode) */ + i64 mn; /* number of occurrences (for mode and percentiles) */ + i64 is_double; /* whether the computation is being done for doubles (>0) or integers (=0) */ + map* m; /* map structure used for the computation */ + int done; /* whether the answer has been found */ +}; + +/* +** called for each value received during a calculation of stdev or variance +*/ +static void varianceStep(sqlite3_context *context, int argc, sqlite3_value **argv){ + StdevCtx *p; + + double delta; + double x; + + assert( argc==1 ); + p = sqlite3_aggregate_context(context, sizeof(*p)); + /* only consider non-null values */ + if( SQLITE_NULL != sqlite3_value_numeric_type(argv[0]) ){ + p->cnt++; + x = sqlite3_value_double(argv[0]); + delta = (x-p->rM); + p->rM += delta/p->cnt; + p->rS += delta*(x-p->rM); + } +} + +/* +** called for each value received during a calculation of mode of median +*/ +static void modeStep(sqlite3_context *context, int argc, sqlite3_value **argv){ + ModeCtx *p; + i64 xi=0; + double xd=0.0; + i64 *iptr; + double *dptr; + int type; + + assert( argc==1 ); + type = sqlite3_value_numeric_type(argv[0]); + + if( type == SQLITE_NULL) + return; + + p = sqlite3_aggregate_context(context, sizeof(*p)); + + if( 0==(p->m) ){ + p->m = calloc(1, sizeof(map)); + if( type==SQLITE_INTEGER ){ + /* map will be used for integers */ + *(p->m) = map_make(int_cmp); + p->is_double = 0; + }else{ + p->is_double = 1; + /* map will be used for doubles */ + *(p->m) = map_make(double_cmp); + } + } + + ++(p->cnt); + + if( 0==p->is_double ){ + xi = sqlite3_value_int64(argv[0]); + iptr = (i64*)calloc(1,sizeof(i64)); + *iptr = xi; + map_insert(p->m, iptr); + }else{ + xd = sqlite3_value_double(argv[0]); + dptr = (double*)calloc(1,sizeof(double)); + *dptr = xd; + map_insert(p->m, dptr); + } +} + +/* +** Auxiliary function that iterates all elements in a map and finds the mode +** (most frequent value) +*/ +static void modeIterate(void* e, i64 c, void* pp){ + i64 ei; + double ed; + ModeCtx *p = (ModeCtx*)pp; + + if( 0==p->is_double ){ + ei = *(int*)(e); + + if( p->mcnt==c ){ + ++p->mn; + }else if( p->mcntriM = ei; + p->mcnt = c; + p->mn=1; + } + }else{ + ed = *(double*)(e); + + if( p->mcnt==c ){ + ++p->mn; + }else if(p->mcntrdM = ed; + p->mcnt = c; + p->mn=1; + } + } +} + +/* +** Auxiliary function that iterates all elements in a map and finds the median +** (the value such that the number of elements smaller is equal the the number of +** elements larger) +*/ +static void medianIterate(void* e, i64 c, void* pp){ + i64 ei; + double ed; + double iL; + double iR; + int il; + int ir; + ModeCtx *p = (ModeCtx*)pp; + + if(p->done>0) + return; + + iL = p->pcnt; + iR = p->cnt - p->pcnt; + il = p->mcnt + c; + ir = p->cnt - p->mcnt; + + if( il >= iL ){ + if( ir >= iR ){ + ++p->mn; + if( 0==p->is_double ){ + ei = *(int*)(e); + p->riM += ei; + }else{ + ed = *(double*)(e); + p->rdM += ed; + } + }else{ + p->done=1; + } + } + p->mcnt+=c; +} + +/* +** Returns the mode value +*/ +static void modeFinalize(sqlite3_context *context){ + ModeCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->m ){ + map_iterate(p->m, modeIterate, p); + map_destroy(p->m); + free(p->m); + + if( 1==p->mn ){ + if( 0==p->is_double ) + sqlite3_result_int64(context, p->riM); + else + sqlite3_result_double(context, p->rdM); + } + } +} + +/* +** auxiliary function for percentiles +*/ +static void _medianFinalize(sqlite3_context *context){ + ModeCtx *p; + p = (ModeCtx*) sqlite3_aggregate_context(context, 0); + if( p && p->m ){ + p->done=0; + map_iterate(p->m, medianIterate, p); + map_destroy(p->m); + free(p->m); + + if( 0==p->is_double ) + if( 1==p->mn ) + sqlite3_result_int64(context, p->riM); + else + sqlite3_result_double(context, p->riM*1.0/p->mn); + else + sqlite3_result_double(context, p->rdM/p->mn); + } +} + +/* +** Returns the median value +*/ +static void medianFinalize(sqlite3_context *context){ + ModeCtx *p; + p = (ModeCtx*) sqlite3_aggregate_context(context, 0); + if( p!=0 ){ + p->pcnt = (p->cnt)/2.0; + _medianFinalize(context); + } +} + +/* +** Returns the lower_quartile value +*/ +static void lower_quartileFinalize(sqlite3_context *context){ + ModeCtx *p; + p = (ModeCtx*) sqlite3_aggregate_context(context, 0); + if( p!=0 ){ + p->pcnt = (p->cnt)/4.0; + _medianFinalize(context); + } +} + +/* +** Returns the upper_quartile value +*/ +static void upper_quartileFinalize(sqlite3_context *context){ + ModeCtx *p; + p = (ModeCtx*) sqlite3_aggregate_context(context, 0); + if( p!=0 ){ + p->pcnt = (p->cnt)*3/4.0; + _medianFinalize(context); + } +} + +/* +** Returns the stdev value +*/ +static void stdevFinalize(sqlite3_context *context){ + StdevCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->cnt>1 ){ + sqlite3_result_double(context, sqrt(p->rS/(p->cnt-1))); + }else{ + sqlite3_result_double(context, 0.0); + } +} + +/* +** Returns the variance value +*/ +static void varianceFinalize(sqlite3_context *context){ + StdevCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->cnt>1 ){ + sqlite3_result_double(context, p->rS/(p->cnt-1)); + }else{ + sqlite3_result_double(context, 0.0); + } +} + +#ifdef SQLITE_SOUNDEX + +/* relicoder factored code */ +/* +** Calculates the soundex value of a string +*/ + +static void soundex(const u8 *zIn, char *zResult){ + int i, j; + static const unsigned char iCode[] = { + 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, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, + 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, + 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, + }; + + for(i=0; zIn[i] && !isalpha(zIn[i]); i++){} + if( zIn[i] ){ + zResult[0] = toupper(zIn[i]); + for(j=1; j<4 && zIn[i]; i++){ + int code = iCode[zIn[i]&0x7f]; + if( code>0 ){ + zResult[j++] = code + '0'; + } + } + while( j<4 ){ + zResult[j++] = '0'; + } + zResult[j] = 0; + }else{ + strcpy(zResult, "?000"); + } +} + +/* +** computes the number of different characters between the soundex value fo 2 strings +*/ +static void differenceFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + char zResult1[8]; + char zResult2[8]; + char *zR1 = zResult1; + char *zR2 = zResult2; + int rVal = 0; + int i = 0; + const u8 *zIn1; + const u8 *zIn2; + + assert( argc==2 ); + + if( sqlite3_value_type(argv[0])==SQLITE_NULL || sqlite3_value_type(argv[1])==SQLITE_NULL ){ + sqlite3_result_null(context); + return; + } + + zIn1 = (u8*)sqlite3_value_text(argv[0]); + zIn2 = (u8*)sqlite3_value_text(argv[1]); + + soundex(zIn1, zR1); + soundex(zIn2, zR2); + + for(i=0; i<4; ++i){ + if( sqliteCharVal((unsigned char *)zR1)==sqliteCharVal((unsigned char *)zR2) ) + ++rVal; + sqliteNextChar(zR1); + sqliteNextChar(zR2); + } + sqlite3_result_int(context, rVal); +} +#endif + +/* +** This function registered all of the above C functions as SQL +** functions. This should be the only routine in this file with +** external linkage. +*/ +int RegisterExtensionFunctions(sqlite3 *db){ + static const struct FuncDef { + char *zName; + signed char nArg; + u8 argType; /* 0: none. 1: db 2: (-1) */ + u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */ + u8 needCollSeq; + void (*xFunc)(sqlite3_context*,int,sqlite3_value **); + } aFuncs[] = { + /* math.h */ + { "acos", 1, 0, SQLITE_UTF8, 0, acosFunc }, + { "asin", 1, 0, SQLITE_UTF8, 0, asinFunc }, + { "atan", 1, 0, SQLITE_UTF8, 0, atanFunc }, + { "atn2", 2, 0, SQLITE_UTF8, 0, atn2Func }, + /* XXX alias */ + { "atan2", 2, 0, SQLITE_UTF8, 0, atn2Func }, + { "acosh", 1, 0, SQLITE_UTF8, 0, acoshFunc }, + { "asinh", 1, 0, SQLITE_UTF8, 0, asinhFunc }, + { "atanh", 1, 0, SQLITE_UTF8, 0, atanhFunc }, + + { "difference", 2, 0, SQLITE_UTF8, 0, differenceFunc}, + { "degrees", 1, 0, SQLITE_UTF8, 0, rad2degFunc }, + { "radians", 1, 0, SQLITE_UTF8, 0, deg2radFunc }, + + { "cos", 1, 0, SQLITE_UTF8, 0, cosFunc }, + { "sin", 1, 0, SQLITE_UTF8, 0, sinFunc }, + { "tan", 1, 0, SQLITE_UTF8, 0, tanFunc }, + { "cot", 1, 0, SQLITE_UTF8, 0, cotFunc }, + { "cosh", 1, 0, SQLITE_UTF8, 0, coshFunc }, + { "sinh", 1, 0, SQLITE_UTF8, 0, sinhFunc }, + { "tanh", 1, 0, SQLITE_UTF8, 0, tanhFunc }, + { "coth", 1, 0, SQLITE_UTF8, 0, cothFunc }, + + { "exp", 1, 0, SQLITE_UTF8, 0, expFunc }, + { "log", 1, 0, SQLITE_UTF8, 0, logFunc }, + { "log10", 1, 0, SQLITE_UTF8, 0, log10Func }, + { "power", 2, 0, SQLITE_UTF8, 0, powerFunc }, + { "sign", 1, 0, SQLITE_UTF8, 0, signFunc }, + { "sqrt", 1, 0, SQLITE_UTF8, 0, sqrtFunc }, + { "square", 1, 0, SQLITE_UTF8, 0, squareFunc }, + + { "ceil", 1, 0, SQLITE_UTF8, 0, ceilFunc }, + { "floor", 1, 0, SQLITE_UTF8, 0, floorFunc }, + + { "pi", 0, 0, SQLITE_UTF8, 1, piFunc }, + + + /* string */ + { "replicate", 2, 0, SQLITE_UTF8, 0, replicateFunc }, + { "charindex", 2, 0, SQLITE_UTF8, 0, charindexFunc }, + { "charindex", 3, 0, SQLITE_UTF8, 0, charindexFunc }, + { "leftstr", 2, 0, SQLITE_UTF8, 0, leftFunc }, + { "rightstr", 2, 0, SQLITE_UTF8, 0, rightFunc }, +#ifndef HAVE_TRIM + { "ltrim", 1, 0, SQLITE_UTF8, 0, ltrimFunc }, + { "rtrim", 1, 0, SQLITE_UTF8, 0, rtrimFunc }, + { "trim", 1, 0, SQLITE_UTF8, 0, trimFunc }, + { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc }, +#endif + { "reverse", 1, 0, SQLITE_UTF8, 0, reverseFunc }, + { "proper", 1, 0, SQLITE_UTF8, 0, properFunc }, + { "padl", 2, 0, SQLITE_UTF8, 0, padlFunc }, + { "padr", 2, 0, SQLITE_UTF8, 0, padrFunc }, + { "padc", 2, 0, SQLITE_UTF8, 0, padcFunc }, + { "strfilter", 2, 0, SQLITE_UTF8, 0, strfilterFunc }, + + }; + /* Aggregate functions */ + static const struct FuncDefAgg { + char *zName; + signed char nArg; + u8 argType; + u8 needCollSeq; + void (*xStep)(sqlite3_context*,int,sqlite3_value**); + void (*xFinalize)(sqlite3_context*); + } aAggs[] = { + { "stdev", 1, 0, 0, varianceStep, stdevFinalize }, + { "variance", 1, 0, 0, varianceStep, varianceFinalize }, + { "mode", 1, 0, 0, modeStep, modeFinalize }, + { "median", 1, 0, 0, modeStep, medianFinalize }, + { "lower_quartile", 1, 0, 0, modeStep, lower_quartileFinalize }, + { "upper_quartile", 1, 0, 0, modeStep, upper_quartileFinalize }, + }; + int i; + + for(i=0; ineedCollSeq = 1; + } + } +#endif + } + + for(i=0; ineedCollSeq = 1; + } + } +#endif + } + return 0; +} + +#ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE +int sqlite3_extension_init( + sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi){ + SQLITE_EXTENSION_INIT2(pApi); + RegisterExtensionFunctions(db); + return 0; +} +#endif /* COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE */ + +map map_make(cmp_func cmp){ + map r; + r.cmp=cmp; + r.base = 0; + + return r; +} + +void* xcalloc(size_t nmemb, size_t size, char* s){ + void* ret = calloc(nmemb, size); + return ret; +} + +void xfree(void* p){ + free(p); +} + +void node_insert(node** n, cmp_func cmp, void *e){ + int c; + node* nn; + if(*n==0){ + nn = (node*)xcalloc(1,sizeof(node), "for node"); + nn->data = e; + nn->count = 1; + *n=nn; + }else{ + c=cmp((*n)->data,e); + if(0==c){ + ++((*n)->count); + xfree(e); + }else if(c>0){ + /* put it right here */ + node_insert(&((*n)->l), cmp, e); + }else{ + node_insert(&((*n)->r), cmp, e); + } + } +} + +void map_insert(map *m, void *e){ + node_insert(&(m->base), m->cmp, e); +} + +void node_iterate(node *n, map_iterator iter, void* p){ + if(n){ + if(n->l) + node_iterate(n->l, iter, p); + iter(n->data, n->count, p); + if(n->r) + node_iterate(n->r, iter, p); + } +} + +void map_iterate(map *m, map_iterator iter, void* p){ + node_iterate(m->base, iter, p); +} + +void node_destroy(node *n){ + if(0!=n){ + xfree(n->data); + if(n->l) + node_destroy(n->l); + if(n->r) + node_destroy(n->r); + + xfree(n); + } +} + +void map_destroy(map *m){ + node_destroy(m->base); +} + +int int_cmp(const void *a, const void *b){ + int64_t aa = *(int64_t *)(a); + int64_t bb = *(int64_t *)(b); + /* printf("cmp %d <=> %d\n",aa,bb); */ + if(aa==bb) + return 0; + else if(aa %d\n",aa,bb); */ + if(aa==bb) + return 0; + else if(aa %lld\n", ee,c); +} + diff --git a/src/extensions/extension-functions.def b/src/extensions/extension-functions.def new file mode 100644 index 000000000..df979a4ad --- /dev/null +++ b/src/extensions/extension-functions.def @@ -0,0 +1,16 @@ +EXPORTS + RegisterExtensionFunctions + double_cmp + int_cmp + map_destroy + map_insert + map_iterate + map_make + node_destroy + node_insert + node_iterate + print_elem + sqlite3_api + sqlite3_extension_init + xcalloc + xfree diff --git a/src/grammar/README b/src/grammar/README deleted file mode 100644 index 42fec62be..000000000 --- a/src/grammar/README +++ /dev/null @@ -1,6 +0,0 @@ -To generate c++ code from the grammar(sqlit3.g) you need -antlr 2.7.7. Download it from www.antlr2.org. - -Either put the antlr.jar into your system classpath or -start it like this: -java -cp .:/pathto/antlr.jar antlr.Tool sqlite3.g diff --git a/src/grammar/Sqlite3Lexer.cpp b/src/grammar/Sqlite3Lexer.cpp deleted file mode 100644 index a52cd1261..000000000 --- a/src/grammar/Sqlite3Lexer.cpp +++ /dev/null @@ -1,1221 +0,0 @@ -/* $ANTLR 2.7.7 (20141010): "sqlite3.g" -> "Sqlite3Lexer.cpp"$ */ -#include "Sqlite3Lexer.hpp" -#include -#include -#include -#include -#include -#include -#include - -Sqlite3Lexer::Sqlite3Lexer(ANTLR_USE_NAMESPACE(std)istream& in) - : ANTLR_USE_NAMESPACE(antlr)CharScanner(new ANTLR_USE_NAMESPACE(antlr)CharBuffer(in),false) -{ - initLiterals(); -} - -Sqlite3Lexer::Sqlite3Lexer(ANTLR_USE_NAMESPACE(antlr)InputBuffer& ib) - : ANTLR_USE_NAMESPACE(antlr)CharScanner(ib,false) -{ - initLiterals(); -} - -Sqlite3Lexer::Sqlite3Lexer(const ANTLR_USE_NAMESPACE(antlr)LexerSharedInputState& state) - : ANTLR_USE_NAMESPACE(antlr)CharScanner(state,false) -{ - initLiterals(); -} - -void Sqlite3Lexer::initLiterals() -{ - literals["CONSTRAINT"] = 19; - literals["CREATE"] = 16; - literals["CASE"] = 13; - literals["END"] = 29; - literals["CASCADE"] = 12; - literals["TEMPORARY"] = 59; - literals["DEFERRABLE"] = 24; - literals["IMMEDIATE"] = 42; - literals["AUTOINCREMENT"] = 6; - literals["ROWID"] = 57; - literals["EXISTS"] = 48; - literals["NO"] = 44; - literals["THEN"] = 61; - literals["AND"] = 9; - literals["CURRENT_DATE"] = 21; - literals["NOT"] = 45; - literals["KEY"] = 34; - literals["COLLATE"] = 17; - literals["NULL"] = 46; - literals["TEMP"] = 60; - literals["INITIALLY"] = 40; - literals["RESTRICT"] = 55; - literals["LIKE"] = 35; - literals["WHEN"] = 64; - literals["FOREIGN"] = 32; - literals["SET"] = 58; - literals["IS"] = 43; - literals["OR"] = 10; - literals["PRIMARY"] = 50; - literals["DEFERRED"] = 25; - literals["UPDATE"] = 63; - literals["IF"] = 37; - literals["UNIQUE"] = 62; - literals["AS"] = 7; - literals["TABLE"] = 36; - literals["DEFAULT"] = 23; - literals["ACTION"] = 5; - literals["DELETE"] = 26; - literals["GLOB"] = 33; - literals["IGNORE"] = 38; - literals["INSERT"] = 41; - literals["CURRENT_TIMESTAMP"] = 22; - literals["CONFLICT"] = 18; - literals["REPLACE"] = 54; - literals["ASC"] = 8; - literals["FAIL"] = 31; - literals["REGEXP"] = 53; - literals["REFERENCES"] = 52; - literals["ON"] = 49; - literals["DESC"] = 27; - literals["IN"] = 39; - literals["CAST"] = 14; - literals["ESCAPE"] = 30; - literals["ELSE"] = 28; - literals["WITHOUT"] = 65; - literals["MATCH"] = 47; - literals["RAISE"] = 51; - literals["ABORT"] = 4; - literals["BETWEEN"] = 11; - literals["CHECK"] = 15; - literals["ROLLBACK"] = 56; - literals["CURRENT_TIME"] = 20; -} - -ANTLR_USE_NAMESPACE(antlr)RefToken Sqlite3Lexer::nextToken() -{ - ANTLR_USE_NAMESPACE(antlr)RefToken theRetToken; - for (;;) { - ANTLR_USE_NAMESPACE(antlr)RefToken theRetToken; - int _ttype = ANTLR_USE_NAMESPACE(antlr)Token::INVALID_TYPE; - resetText(); - try { // for lexical and char stream error handling - switch ( LA(1)) { - case 0x5f /* '_' */ : - case 0x61 /* 'a' */ : - case 0x62 /* 'b' */ : - case 0x63 /* 'c' */ : - case 0x64 /* 'd' */ : - case 0x65 /* 'e' */ : - case 0x66 /* 'f' */ : - case 0x67 /* 'g' */ : - case 0x68 /* 'h' */ : - case 0x69 /* 'i' */ : - case 0x6a /* 'j' */ : - case 0x6b /* 'k' */ : - case 0x6c /* 'l' */ : - case 0x6d /* 'm' */ : - case 0x6e /* 'n' */ : - case 0x6f /* 'o' */ : - case 0x70 /* 'p' */ : - case 0x71 /* 'q' */ : - case 0x72 /* 'r' */ : - case 0x73 /* 's' */ : - case 0x74 /* 't' */ : - case 0x75 /* 'u' */ : - case 0x76 /* 'v' */ : - case 0x77 /* 'w' */ : - case 0x78 /* 'x' */ : - case 0x79 /* 'y' */ : - case 0x7a /* 'z' */ : - { - mID(true); - theRetToken=_returnToken; - break; - } - case 0x5b /* '[' */ : - case 0x60 /* '`' */ : - { - mQUOTEDID(true); - theRetToken=_returnToken; - break; - } - case 0x22 /* '\"' */ : - { - mQUOTEDLITERAL(true); - theRetToken=_returnToken; - break; - } - case 0x2e /* '.' */ : - case 0x30 /* '0' */ : - case 0x31 /* '1' */ : - case 0x32 /* '2' */ : - case 0x33 /* '3' */ : - case 0x34 /* '4' */ : - case 0x35 /* '5' */ : - case 0x36 /* '6' */ : - case 0x37 /* '7' */ : - case 0x38 /* '8' */ : - case 0x39 /* '9' */ : - { - mNUMERIC(true); - theRetToken=_returnToken; - break; - } - case 0x2b /* '+' */ : - { - mPLUS(true); - theRetToken=_returnToken; - break; - } - case 0x9 /* '\t' */ : - case 0xa /* '\n' */ : - case 0xc /* '\14' */ : - case 0xd /* '\r' */ : - case 0x20 /* ' ' */ : - { - mWS(true); - theRetToken=_returnToken; - break; - } - case 0x27 /* '\'' */ : - { - mSTRINGLITERAL(true); - theRetToken=_returnToken; - break; - } - case 0x28 /* '(' */ : - { - mLPAREN(true); - theRetToken=_returnToken; - break; - } - case 0x29 /* ')' */ : - { - mRPAREN(true); - theRetToken=_returnToken; - break; - } - case 0x2c /* ',' */ : - { - mCOMMA(true); - theRetToken=_returnToken; - break; - } - case 0x3b /* ';' */ : - { - mSEMI(true); - theRetToken=_returnToken; - break; - } - case 0x2a /* '*' */ : - { - mSTAR(true); - theRetToken=_returnToken; - break; - } - case 0x7e /* '~' */ : - { - mTILDE(true); - theRetToken=_returnToken; - break; - } - case 0x26 /* '&' */ : - { - mAMPERSAND(true); - theRetToken=_returnToken; - break; - } - case 0x21 /* '!' */ : - { - mUNEQUAL(true); - theRetToken=_returnToken; - break; - } - default: - if ((LA(1) == 0x2d /* '-' */ || LA(1) == 0x2f /* '/' */ ) && (LA(2) == 0x2a /* '*' */ || LA(2) == 0x2d /* '-' */ )) { - mCOMMENT(true); - theRetToken=_returnToken; - } - else if ((LA(1) == 0x7c /* '|' */ ) && (LA(2) == 0x7c /* '|' */ )) { - mOROP(true); - theRetToken=_returnToken; - } - else if ((LA(1) == 0x3d /* '=' */ ) && (LA(2) == 0x3d /* '=' */ )) { - mEQUAL2(true); - theRetToken=_returnToken; - } - else if ((LA(1) == 0x3e /* '>' */ ) && (LA(2) == 0x3d /* '=' */ )) { - mGREATEREQUAL(true); - theRetToken=_returnToken; - } - else if ((LA(1) == 0x3c /* '<' */ ) && (LA(2) == 0x3d /* '=' */ )) { - mLOWEREQUAL(true); - theRetToken=_returnToken; - } - else if ((LA(1) == 0x3c /* '<' */ ) && (LA(2) == 0x3e /* '>' */ )) { - mUNEQUAL2(true); - theRetToken=_returnToken; - } - else if ((LA(1) == 0x3c /* '<' */ ) && (LA(2) == 0x3c /* '<' */ )) { - mBITWISELEFT(true); - theRetToken=_returnToken; - } - else if ((LA(1) == 0x3e /* '>' */ ) && (LA(2) == 0x3e /* '>' */ )) { - mBITWISERIGHT(true); - theRetToken=_returnToken; - } - else if ((LA(1) == 0x2d /* '-' */ ) && (true)) { - mMINUS(true); - theRetToken=_returnToken; - } - else if ((LA(1) == 0x7c /* '|' */ ) && (true)) { - mBITOR(true); - theRetToken=_returnToken; - } - else if ((LA(1) == 0x3d /* '=' */ ) && (true)) { - mEQUAL(true); - theRetToken=_returnToken; - } - else if ((LA(1) == 0x3e /* '>' */ ) && (true)) { - mGREATER(true); - theRetToken=_returnToken; - } - else if ((LA(1) == 0x3c /* '<' */ ) && (true)) { - mLOWER(true); - theRetToken=_returnToken; - } - else { - if (LA(1)==EOF_CHAR) - { - uponEOF(); - _returnToken = makeToken(ANTLR_USE_NAMESPACE(antlr)Token::EOF_TYPE); - } - else {throw ANTLR_USE_NAMESPACE(antlr)NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} - } - } - if ( !_returnToken ) - goto tryAgain; // found SKIP token - - _ttype = _returnToken->getType(); - _ttype = testLiteralsTable(_ttype); - _returnToken->setType(_ttype); - return _returnToken; - } - catch (ANTLR_USE_NAMESPACE(antlr)RecognitionException& e) { - throw ANTLR_USE_NAMESPACE(antlr)TokenStreamRecognitionException(e); - } - catch (ANTLR_USE_NAMESPACE(antlr)CharStreamIOException& csie) { - throw ANTLR_USE_NAMESPACE(antlr)TokenStreamIOException(csie.io); - } - catch (ANTLR_USE_NAMESPACE(antlr)CharStreamException& cse) { - throw ANTLR_USE_NAMESPACE(antlr)TokenStreamException(cse.getMessage()); - } -tryAgain:; - } -} - -void Sqlite3Lexer::mDIGIT(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = DIGIT; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - matchRange(L'0',L'9'); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mDOT(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = DOT; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mID(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = ID; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - { - switch ( LA(1)) { - case 0x61 /* 'a' */ : - case 0x62 /* 'b' */ : - case 0x63 /* 'c' */ : - case 0x64 /* 'd' */ : - case 0x65 /* 'e' */ : - case 0x66 /* 'f' */ : - case 0x67 /* 'g' */ : - case 0x68 /* 'h' */ : - case 0x69 /* 'i' */ : - case 0x6a /* 'j' */ : - case 0x6b /* 'k' */ : - case 0x6c /* 'l' */ : - case 0x6d /* 'm' */ : - case 0x6e /* 'n' */ : - case 0x6f /* 'o' */ : - case 0x70 /* 'p' */ : - case 0x71 /* 'q' */ : - case 0x72 /* 'r' */ : - case 0x73 /* 's' */ : - case 0x74 /* 't' */ : - case 0x75 /* 'u' */ : - case 0x76 /* 'v' */ : - case 0x77 /* 'w' */ : - case 0x78 /* 'x' */ : - case 0x79 /* 'y' */ : - case 0x7a /* 'z' */ : - { - matchRange(L'a',L'z'); - break; - } - case 0x5f /* '_' */ : - { - match(L'_' /* charlit */ ); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); - } - } - } - { // ( ... )* - for (;;) { - switch ( LA(1)) { - case 0x61 /* 'a' */ : - case 0x62 /* 'b' */ : - case 0x63 /* 'c' */ : - case 0x64 /* 'd' */ : - case 0x65 /* 'e' */ : - case 0x66 /* 'f' */ : - case 0x67 /* 'g' */ : - case 0x68 /* 'h' */ : - case 0x69 /* 'i' */ : - case 0x6a /* 'j' */ : - case 0x6b /* 'k' */ : - case 0x6c /* 'l' */ : - case 0x6d /* 'm' */ : - case 0x6e /* 'n' */ : - case 0x6f /* 'o' */ : - case 0x70 /* 'p' */ : - case 0x71 /* 'q' */ : - case 0x72 /* 'r' */ : - case 0x73 /* 's' */ : - case 0x74 /* 't' */ : - case 0x75 /* 'u' */ : - case 0x76 /* 'v' */ : - case 0x77 /* 'w' */ : - case 0x78 /* 'x' */ : - case 0x79 /* 'y' */ : - case 0x7a /* 'z' */ : - { - matchRange(L'a',L'z'); - break; - } - case 0x30 /* '0' */ : - case 0x31 /* '1' */ : - case 0x32 /* '2' */ : - case 0x33 /* '3' */ : - case 0x34 /* '4' */ : - case 0x35 /* '5' */ : - case 0x36 /* '6' */ : - case 0x37 /* '7' */ : - case 0x38 /* '8' */ : - case 0x39 /* '9' */ : - { - matchRange(L'0',L'9'); - break; - } - case 0x5f /* '_' */ : - { - match(L'_' /* charlit */ ); - break; - } - default: - if (((LA(1) >= 0x80 && LA(1) <= 0x2b8))) { - matchRange(L'\200',L'\u02b8'); - } - else { - goto _loop6; - } - } - } - _loop6:; - } // ( ... )* - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mQUOTEDID(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = QUOTEDID; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - switch ( LA(1)) { - case 0x60 /* '`' */ : - { - match(L'`' /* charlit */ ); - { // ( ... )* - for (;;) { - if ((LA(1) == 0x60 /* '`' */ ) && (LA(2) == 0x60 /* '`' */ )) { - { - match(L'`' /* charlit */ ); - match(L'`' /* charlit */ ); - } - } - else if ((_tokenSet_0.member(LA(1)))) { - { - match(_tokenSet_0); - } - } - else { - goto _loop11; - } - - } - _loop11:; - } // ( ... )* - match(L'`' /* charlit */ ); - break; - } - case 0x5b /* '[' */ : - { - match(L'[' /* charlit */ ); - { // ( ... )* - for (;;) { - if ((_tokenSet_1.member(LA(1)))) { - { - match(_tokenSet_1); - } - } - else { - goto _loop14; - } - - } - _loop14:; - } // ( ... )* - match(L']' /* charlit */ ); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); - } - } - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mQUOTEDLITERAL(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = QUOTEDLITERAL; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L'\"' /* charlit */ ); - { // ( ... )* - for (;;) { - if ((LA(1) == 0x22 /* '\"' */ ) && (LA(2) == 0x22 /* '\"' */ )) { - { - match(L'\"' /* charlit */ ); - match(L'\"' /* charlit */ ); - } - } - else if ((_tokenSet_2.member(LA(1)))) { - matchNot(L'\"' /* charlit */ ); - } - else { - goto _loop18; - } - - } - _loop18:; - } // ( ... )* - match(L'\"' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mNUMERIC(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = NUMERIC; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - { - switch ( LA(1)) { - case 0x30 /* '0' */ : - case 0x31 /* '1' */ : - case 0x32 /* '2' */ : - case 0x33 /* '3' */ : - case 0x34 /* '4' */ : - case 0x35 /* '5' */ : - case 0x36 /* '6' */ : - case 0x37 /* '7' */ : - case 0x38 /* '8' */ : - case 0x39 /* '9' */ : - { - { // ( ... )+ - int _cnt22=0; - for (;;) { - if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { - mDIGIT(false); - } - else { - if ( _cnt22>=1 ) { goto _loop22; } else {throw ANTLR_USE_NAMESPACE(antlr)NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} - } - - _cnt22++; - } - _loop22:; - } // ( ... )+ - { - if ((LA(1) == 0x2e /* '.' */ )) { - match(L'.' /* charlit */ ); - { // ( ... )* - for (;;) { - if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { - mDIGIT(false); - } - else { - goto _loop25; - } - - } - _loop25:; - } // ( ... )* - } - else { - } - - } - break; - } - case 0x2e /* '.' */ : - { - match(L'.' /* charlit */ ); - _ttype=DOT; - { // ( ... )+ - int _cnt27=0; - for (;;) { - if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { - mDIGIT(false); - } - else { - if ( _cnt27>=1 ) { goto _loop27; } else {throw ANTLR_USE_NAMESPACE(antlr)NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} - } - - _cnt27++; - } - _loop27:; - } // ( ... )+ - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); - } - } - } - { - if ((LA(1) == 0x65 /* 'e' */ )) { - match(L'e' /* charlit */ ); - { - switch ( LA(1)) { - case 0x2b /* '+' */ : - { - mPLUS(false); - break; - } - case 0x2d /* '-' */ : - { - mMINUS(false); - break; - } - case 0x30 /* '0' */ : - case 0x31 /* '1' */ : - case 0x32 /* '2' */ : - case 0x33 /* '3' */ : - case 0x34 /* '4' */ : - case 0x35 /* '5' */ : - case 0x36 /* '6' */ : - case 0x37 /* '7' */ : - case 0x38 /* '8' */ : - case 0x39 /* '9' */ : - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); - } - } - } - { // ( ... )+ - int _cnt31=0; - for (;;) { - if (((LA(1) >= 0x30 /* '0' */ && LA(1) <= 0x39 /* '9' */ ))) { - mDIGIT(false); - } - else { - if ( _cnt31>=1 ) { goto _loop31; } else {throw ANTLR_USE_NAMESPACE(antlr)NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());} - } - - _cnt31++; - } - _loop31:; - } // ( ... )+ - } - else { - } - - } - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mPLUS(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = PLUS; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L'+' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mMINUS(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = MINUS; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L'-' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mNL(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = NL; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - { - switch ( LA(1)) { - case 0xd /* '\r' */ : - { - match(L'\r' /* charlit */ ); - break; - } - case 0xa /* '\n' */ : - { - match(L'\n' /* charlit */ ); - newline(); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); - } - } - } - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mCOMMENT(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = COMMENT; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - { - switch ( LA(1)) { - case 0x2d /* '-' */ : - { - match(L'-' /* charlit */ ); - match(L'-' /* charlit */ ); - { // ( ... )* - for (;;) { - if ((_tokenSet_3.member(LA(1)))) { - { - match(_tokenSet_3); - } - } - else { - goto _loop38; - } - - } - _loop38:; - } // ( ... )* - mNL(false); - newline(); - break; - } - case 0x2f /* '/' */ : - { - match(L'/' /* charlit */ ); - match(L'*' /* charlit */ ); - { // ( ... )* - for (;;) { - // nongreedy exit test - if ((LA(1) == 0x2a /* '*' */ ) && (LA(2) == 0x2f /* '/' */ )) goto _loop41; - if ((_tokenSet_3.member(LA(1))) && ((LA(2) >= 0x0 /* '\0' */ && LA(2) <= 0xfffe))) { - { - match(_tokenSet_3); - } - } - else if ((LA(1) == 0xa /* '\n' */ || LA(1) == 0xd /* '\r' */ )) { - mNL(false); - newline(); - } - else { - goto _loop41; - } - - } - _loop41:; - } // ( ... )* - match(L'*' /* charlit */ ); - match(L'/' /* charlit */ ); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); - } - } - } - _ttype = ANTLR_USE_NAMESPACE(antlr)Token::SKIP; - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mWS(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = WS; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - { - switch ( LA(1)) { - case 0x20 /* ' ' */ : - { - match(L' ' /* charlit */ ); - break; - } - case 0x9 /* '\t' */ : - { - match(L'\t' /* charlit */ ); - break; - } - case 0xc /* '\14' */ : - { - match(L'\14' /* charlit */ ); - break; - } - case 0xa /* '\n' */ : - case 0xd /* '\r' */ : - { - mNL(false); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn()); - } - } - } - _ttype = ANTLR_USE_NAMESPACE(antlr)Token::SKIP; - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mSTRINGLITERAL(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = STRINGLITERAL; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L'\'' /* charlit */ ); - { // ( ... )* - for (;;) { - if ((LA(1) == 0x27 /* '\'' */ ) && (LA(2) == 0x27 /* '\'' */ )) { - { - match(L'\'' /* charlit */ ); - match(L'\'' /* charlit */ ); - } - } - else if ((_tokenSet_4.member(LA(1)))) { - matchNot(L'\'' /* charlit */ ); - } - else { - goto _loop47; - } - - } - _loop47:; - } // ( ... )* - match(L'\'' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mLPAREN(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = LPAREN; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L'(' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mRPAREN(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = RPAREN; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L')' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mCOMMA(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = COMMA; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L',' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mSEMI(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = SEMI; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L';' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mSTAR(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = STAR; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L'*' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mTILDE(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = TILDE; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L'~' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mAMPERSAND(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = AMPERSAND; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L'&' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mBITOR(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = BITOR; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L'|' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mOROP(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = OROP; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - mBITOR(false); - mBITOR(false); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mEQUAL(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = EQUAL; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L'=' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mEQUAL2(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = EQUAL2; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - mEQUAL(false); - mEQUAL(false); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mGREATER(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = GREATER; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L'>' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mGREATEREQUAL(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = GREATEREQUAL; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - mGREATER(false); - mEQUAL(false); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mLOWER(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = LOWER; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L'<' /* charlit */ ); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mLOWEREQUAL(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = LOWEREQUAL; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - mLOWER(false); - mEQUAL(false); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mUNEQUAL(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = UNEQUAL; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - match(L'!' /* charlit */ ); - mEQUAL(false); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mUNEQUAL2(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = UNEQUAL2; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - mLOWER(false); - mGREATER(false); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mBITWISELEFT(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = BITWISELEFT; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - mLOWER(false); - mLOWER(false); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - -void Sqlite3Lexer::mBITWISERIGHT(bool _createToken) { - int _ttype; ANTLR_USE_NAMESPACE(antlr)RefToken _token; ANTLR_USE_NAMESPACE(std)string::size_type _begin = text.length(); - _ttype = BITWISERIGHT; - ANTLR_USE_NAMESPACE(std)string::size_type _saveIndex; - - mGREATER(false); - mGREATER(false); - if ( _createToken && _token==ANTLR_USE_NAMESPACE(antlr)nullToken && _ttype!=ANTLR_USE_NAMESPACE(antlr)Token::SKIP ) { - _token = makeToken(_ttype); - _token->setText(text.substr(_begin, text.length()-_begin)); - } - _returnToken = _token; - _saveIndex=0; -} - - -const unsigned long Sqlite3Lexer::_tokenSet_0_data_[] = { 4294967295UL, 4294967295UL, 4294967295UL, 4294967294UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 2147483647UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 -// 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e -// 0x1f ! \" # $ % & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > -// ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ 0x5c ] ^ _ -// a b c d e f g h i j -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Lexer::_tokenSet_0(_tokenSet_0_data_,4096); -const unsigned long Sqlite3Lexer::_tokenSet_1_data_[] = { 4294967295UL, 4294967295UL, 3758096383UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 2147483647UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 -// 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e -// 0x1f ! \" # $ % & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > -// ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ 0x5c ^ _ ` -// a b c d e f g h i j -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Lexer::_tokenSet_1(_tokenSet_1_data_,4096); -const unsigned long Sqlite3Lexer::_tokenSet_2_data_[] = { 4294967295UL, 4294967291UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 2147483647UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 -// 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e -// 0x1f ! # $ % & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? -// @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ 0x5c ] ^ _ ` -// a b c d e f g h i j -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Lexer::_tokenSet_2(_tokenSet_2_data_,4096); -const unsigned long Sqlite3Lexer::_tokenSet_3_data_[] = { 4294958079UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 2147483647UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xb 0xc 0xe 0xf 0x10 0x11 0x12 -// 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f ! -// \" # $ % & \' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B -// C D E F G H I J K L M N O P Q R S T U V W X Y Z [ 0x5c ] ^ _ ` a b c -// d e f g h i j -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Lexer::_tokenSet_3(_tokenSet_3_data_,4096); -const unsigned long Sqlite3Lexer::_tokenSet_4_data_[] = { 4294967295UL, 4294967167UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 4294967295UL, 2147483647UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf 0x10 -// 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e -// 0x1f ! \" # $ % & ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? -// @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ 0x5c ] ^ _ ` -// a b c d e f g h i j -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Lexer::_tokenSet_4(_tokenSet_4_data_,4096); - diff --git a/src/grammar/Sqlite3Lexer.hpp b/src/grammar/Sqlite3Lexer.hpp deleted file mode 100644 index fa6cdf277..000000000 --- a/src/grammar/Sqlite3Lexer.hpp +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef INC_Sqlite3Lexer_hpp_ -#define INC_Sqlite3Lexer_hpp_ - -#include -/* $ANTLR 2.7.7 (20141010): "sqlite3.g" -> "Sqlite3Lexer.hpp"$ */ -#include -#include -#include -#include "sqlite3TokenTypes.hpp" -#include -class CUSTOM_API Sqlite3Lexer : public ANTLR_USE_NAMESPACE(antlr)CharScanner, public sqlite3TokenTypes -{ -private: - void initLiterals(); -public: - bool getCaseSensitiveLiterals() const - { - return false; - } -public: - Sqlite3Lexer(ANTLR_USE_NAMESPACE(std)istream& in); - Sqlite3Lexer(ANTLR_USE_NAMESPACE(antlr)InputBuffer& ib); - Sqlite3Lexer(const ANTLR_USE_NAMESPACE(antlr)LexerSharedInputState& state); - ANTLR_USE_NAMESPACE(antlr)RefToken nextToken(); - protected: void mDIGIT(bool _createToken); - protected: void mDOT(bool _createToken); - public: void mID(bool _createToken); - public: void mQUOTEDID(bool _createToken); - public: void mQUOTEDLITERAL(bool _createToken); - public: void mNUMERIC(bool _createToken); - public: void mPLUS(bool _createToken); - public: void mMINUS(bool _createToken); - protected: void mNL(bool _createToken); - public: void mCOMMENT(bool _createToken); - public: void mWS(bool _createToken); - public: void mSTRINGLITERAL(bool _createToken); - public: void mLPAREN(bool _createToken); - public: void mRPAREN(bool _createToken); - public: void mCOMMA(bool _createToken); - public: void mSEMI(bool _createToken); - public: void mSTAR(bool _createToken); - public: void mTILDE(bool _createToken); - public: void mAMPERSAND(bool _createToken); - public: void mBITOR(bool _createToken); - public: void mOROP(bool _createToken); - public: void mEQUAL(bool _createToken); - public: void mEQUAL2(bool _createToken); - public: void mGREATER(bool _createToken); - public: void mGREATEREQUAL(bool _createToken); - public: void mLOWER(bool _createToken); - public: void mLOWEREQUAL(bool _createToken); - public: void mUNEQUAL(bool _createToken); - public: void mUNEQUAL2(bool _createToken); - public: void mBITWISELEFT(bool _createToken); - public: void mBITWISERIGHT(bool _createToken); -private: - - static const unsigned long _tokenSet_0_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_0; - static const unsigned long _tokenSet_1_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_1; - static const unsigned long _tokenSet_2_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_2; - static const unsigned long _tokenSet_3_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_3; - static const unsigned long _tokenSet_4_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_4; -}; - -#endif /*INC_Sqlite3Lexer_hpp_*/ diff --git a/src/grammar/Sqlite3Parser.cpp b/src/grammar/Sqlite3Parser.cpp deleted file mode 100644 index 923e092d0..000000000 --- a/src/grammar/Sqlite3Parser.cpp +++ /dev/null @@ -1,4876 +0,0 @@ -/* $ANTLR 2.7.7 (20141010): "sqlite3.g" -> "Sqlite3Parser.cpp"$ */ -#include "Sqlite3Parser.hpp" -#include -#include -#include -Sqlite3Parser::Sqlite3Parser(ANTLR_USE_NAMESPACE(antlr)TokenBuffer& tokenBuf, int k) -: ANTLR_USE_NAMESPACE(antlr)LLkParser(tokenBuf,k) -{ -} - -Sqlite3Parser::Sqlite3Parser(ANTLR_USE_NAMESPACE(antlr)TokenBuffer& tokenBuf) -: ANTLR_USE_NAMESPACE(antlr)LLkParser(tokenBuf,2) -{ -} - -Sqlite3Parser::Sqlite3Parser(ANTLR_USE_NAMESPACE(antlr)TokenStream& lexer, int k) -: ANTLR_USE_NAMESPACE(antlr)LLkParser(lexer,k) -{ -} - -Sqlite3Parser::Sqlite3Parser(ANTLR_USE_NAMESPACE(antlr)TokenStream& lexer) -: ANTLR_USE_NAMESPACE(antlr)LLkParser(lexer,2) -{ -} - -Sqlite3Parser::Sqlite3Parser(const ANTLR_USE_NAMESPACE(antlr)ParserSharedInputState& state) -: ANTLR_USE_NAMESPACE(antlr)LLkParser(state,2) -{ -} - -void Sqlite3Parser::id() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST id_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - switch ( LA(1)) { - case ID: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp1_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp1_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp1_AST); - } - match(ID); - id_AST = currentAST.root; - break; - } - case QUOTEDID: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp2_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp2_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp2_AST); - } - match(QUOTEDID); - id_AST = currentAST.root; - break; - } - case QUOTEDLITERAL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp3_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp3_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp3_AST); - } - match(QUOTEDLITERAL); - id_AST = currentAST.root; - break; - } - case STRINGLITERAL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp4_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp4_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp4_AST); - } - match(STRINGLITERAL); - id_AST = currentAST.root; - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - returnAST = id_AST; -} - -void Sqlite3Parser::databasename() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST databasename_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - id(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - databasename_AST = currentAST.root; - returnAST = databasename_AST; -} - -void Sqlite3Parser::tablename() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST tablename_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - id(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - tablename_AST = currentAST.root; - returnAST = tablename_AST; -} - -void Sqlite3Parser::nonkeyword_columnname() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST nonkeyword_columnname_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - id(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - nonkeyword_columnname_AST = currentAST.root; - returnAST = nonkeyword_columnname_AST; -} - -void Sqlite3Parser::identifier() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST identifier_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - { - if ((_tokenSet_0.member(LA(1))) && (_tokenSet_0.member(LA(2)))) { - { - switch ( LA(1)) { - case ID: - case QUOTEDID: - case QUOTEDLITERAL: - case STRINGLITERAL: - { - databasename(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case DOT: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp5_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp5_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp5_AST); - } - match(DOT); - } - else if ((_tokenSet_1.member(LA(1))) && (LA(2) == ANTLR_USE_NAMESPACE(antlr)Token::EOF_TYPE)) { - } - else { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - - } - tablename(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - identifier_AST = currentAST.root; - returnAST = identifier_AST; -} - -void Sqlite3Parser::collationname() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST collationname_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - ANTLR_USE_NAMESPACE(antlr)RefAST tmp6_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp6_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp6_AST); - } - match(ID); - collationname_AST = currentAST.root; - returnAST = collationname_AST; -} - -void Sqlite3Parser::signednumber() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST signednumber_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - { - switch ( LA(1)) { - case PLUS: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp7_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp7_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp7_AST); - } - match(PLUS); - break; - } - case MINUS: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp8_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp8_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp8_AST); - } - match(MINUS); - break; - } - case NUMERIC: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp9_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp9_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp9_AST); - } - match(NUMERIC); - signednumber_AST = currentAST.root; - returnAST = signednumber_AST; -} - -void Sqlite3Parser::statementlist() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST statementlist_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - { - switch ( LA(1)) { - case CREATE: - { - statement(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case ANTLR_USE_NAMESPACE(antlr)Token::EOF_TYPE: - case SEMI: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { // ( ... )* - for (;;) { - if ((LA(1) == SEMI)) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp10_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp10_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp10_AST); - } - match(SEMI); - statement(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - goto _loop82; - } - - } - _loop82:; - } // ( ... )* - statementlist_AST = currentAST.root; - returnAST = statementlist_AST; -} - -void Sqlite3Parser::statement() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST statement_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - createtable(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - statement_AST = currentAST.root; - returnAST = statement_AST; -} - -void Sqlite3Parser::createtable() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST createtable_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - ANTLR_USE_NAMESPACE(antlr)RefAST tmp11_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp11_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp11_AST); - } - match(CREATE); - { - switch ( LA(1)) { - case TEMP: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp12_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp12_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp12_AST); - } - match(TEMP); - break; - } - case TEMPORARY: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp13_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp13_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp13_AST); - } - match(TEMPORARY); - break; - } - case TABLE: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp14_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp14_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp14_AST); - } - match(TABLE); - { - switch ( LA(1)) { - case IF_T: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp15_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp15_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp15_AST); - } - match(IF_T); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp16_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp16_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp16_AST); - } - match(NOT); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp17_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp17_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp17_AST); - } - match(EXISTS); - break; - } - case ABORT: - case ACTION: - case ASC: - case CASCADE: - case CAST: - case CONFLICT: - case CURRENT_TIME: - case CURRENT_DATE: - case CURRENT_TIMESTAMP: - case DEFERRED: - case DESC: - case END: - case FAIL: - case GLOB: - case KEY: - case LIKE: - case IGNORE: - case INITIALLY: - case IMMEDIATE: - case MATCH: - case RAISE: - case REGEXP: - case REPLACE: - case RESTRICT: - case ROLLBACK: - case TEMPORARY: - case TEMP: - case ID: - case QUOTEDID: - case QUOTEDLITERAL: - case STRINGLITERAL: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { - switch ( LA(1)) { - case ID: - case QUOTEDID: - case QUOTEDLITERAL: - case STRINGLITERAL: - { - tablename(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case ABORT: - case ACTION: - case ASC: - case CASCADE: - case CAST: - case CONFLICT: - case CURRENT_TIME: - case CURRENT_DATE: - case CURRENT_TIMESTAMP: - case DEFERRED: - case DESC: - case END: - case FAIL: - case GLOB: - case KEY: - case LIKE: - case IGNORE: - case INITIALLY: - case IMMEDIATE: - case MATCH: - case RAISE: - case REGEXP: - case REPLACE: - case RESTRICT: - case ROLLBACK: - case TEMPORARY: - case TEMP: - { - keywordastablename(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { - switch ( LA(1)) { - case LPAREN: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp18_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp18_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp18_AST); - } - match(LPAREN); - columndef(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { // ( ... )* - for (;;) { - if ((LA(1) == COMMA) && (_tokenSet_2.member(LA(2)))) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp19_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp19_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp19_AST); - } - match(COMMA); - columndef(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - goto _loop93; - } - - } - _loop93:; - } // ( ... )* - { // ( ... )* - for (;;) { - if ((_tokenSet_3.member(LA(1)))) { - { - switch ( LA(1)) { - case COMMA: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp20_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp20_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp20_AST); - } - match(COMMA); - break; - } - case CHECK: - case CONSTRAINT: - case FOREIGN: - case PRIMARY: - case UNIQUE: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - tableconstraint(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - goto _loop96; - } - - } - _loop96:; - } // ( ... )* - ANTLR_USE_NAMESPACE(antlr)RefAST tmp21_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp21_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp21_AST); - } - match(RPAREN); - { - switch ( LA(1)) { - case WITHOUT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp22_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp22_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp22_AST); - } - match(WITHOUT); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp23_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp23_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp23_AST); - } - match(ROWID); - break; - } - case ANTLR_USE_NAMESPACE(antlr)Token::EOF_TYPE: - case SEMI: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - break; - } - case AS: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp24_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp24_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp24_AST); - } - match(AS); - selectstmt(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - if ( inputState->guessing==0 ) { - createtable_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(currentAST.root); - createtable_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(astFactory->make((new ANTLR_USE_NAMESPACE(antlr)ASTArray(2))->add(astFactory->create(CREATETABLE,"CREATETABLE"))->add(createtable_AST))); - currentAST.root = createtable_AST; - if ( createtable_AST!=ANTLR_USE_NAMESPACE(antlr)nullAST && - createtable_AST->getFirstChild() != ANTLR_USE_NAMESPACE(antlr)nullAST ) - currentAST.child = createtable_AST->getFirstChild(); - else - currentAST.child = createtable_AST; - currentAST.advanceChildToEnd(); - } - createtable_AST = currentAST.root; - returnAST = createtable_AST; -} - -void Sqlite3Parser::create_statements() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST create_statements_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - createtable(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - create_statements_AST = currentAST.root; - returnAST = create_statements_AST; -} - -void Sqlite3Parser::keywordastablename() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST keywordastablename_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - { - switch ( LA(1)) { - case ABORT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp25_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp25_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp25_AST); - } - match(ABORT); - break; - } - case ACTION: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp26_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp26_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp26_AST); - } - match(ACTION); - break; - } - case ASC: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp27_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp27_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp27_AST); - } - match(ASC); - break; - } - case CASCADE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp28_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp28_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp28_AST); - } - match(CASCADE); - break; - } - case CAST: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp29_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp29_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp29_AST); - } - match(CAST); - break; - } - case CONFLICT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp30_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp30_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp30_AST); - } - match(CONFLICT); - break; - } - case CURRENT_TIME: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp31_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp31_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp31_AST); - } - match(CURRENT_TIME); - break; - } - case CURRENT_DATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp32_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp32_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp32_AST); - } - match(CURRENT_DATE); - break; - } - case CURRENT_TIMESTAMP: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp33_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp33_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp33_AST); - } - match(CURRENT_TIMESTAMP); - break; - } - case DEFERRED: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp34_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp34_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp34_AST); - } - match(DEFERRED); - break; - } - case DESC: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp35_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp35_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp35_AST); - } - match(DESC); - break; - } - case END: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp36_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp36_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp36_AST); - } - match(END); - break; - } - case FAIL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp37_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp37_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp37_AST); - } - match(FAIL); - break; - } - case GLOB: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp38_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp38_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp38_AST); - } - match(GLOB); - break; - } - case KEY: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp39_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp39_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp39_AST); - } - match(KEY); - break; - } - case LIKE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp40_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp40_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp40_AST); - } - match(LIKE); - break; - } - case IGNORE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp41_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp41_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp41_AST); - } - match(IGNORE); - break; - } - case INITIALLY: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp42_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp42_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp42_AST); - } - match(INITIALLY); - break; - } - case IMMEDIATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp43_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp43_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp43_AST); - } - match(IMMEDIATE); - break; - } - case MATCH: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp44_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp44_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp44_AST); - } - match(MATCH); - break; - } - case RAISE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp45_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp45_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp45_AST); - } - match(RAISE); - break; - } - case REGEXP: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp46_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp46_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp46_AST); - } - match(REGEXP); - break; - } - case REPLACE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp47_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp47_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp47_AST); - } - match(REPLACE); - break; - } - case RESTRICT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp48_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp48_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp48_AST); - } - match(RESTRICT); - break; - } - case ROLLBACK: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp49_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp49_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp49_AST); - } - match(ROLLBACK); - break; - } - case TEMPORARY: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp50_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp50_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp50_AST); - } - match(TEMPORARY); - break; - } - case TEMP: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp51_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp51_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp51_AST); - } - match(TEMP); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - if ( inputState->guessing==0 ) { - keywordastablename_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(currentAST.root); - keywordastablename_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(astFactory->make((new ANTLR_USE_NAMESPACE(antlr)ASTArray(2))->add(astFactory->create(KEYWORDASTABLENAME,"KEYWORDASTABLENAME"))->add(keywordastablename_AST))); - currentAST.root = keywordastablename_AST; - if ( keywordastablename_AST!=ANTLR_USE_NAMESPACE(antlr)nullAST && - keywordastablename_AST->getFirstChild() != ANTLR_USE_NAMESPACE(antlr)nullAST ) - currentAST.child = keywordastablename_AST->getFirstChild(); - else - currentAST.child = keywordastablename_AST; - currentAST.advanceChildToEnd(); - } - keywordastablename_AST = currentAST.root; - returnAST = keywordastablename_AST; -} - -void Sqlite3Parser::columndef() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST columndef_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - columnname(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { - switch ( LA(1)) { - case ID: - case QUOTEDID: - case QUOTEDLITERAL: - case STRINGLITERAL: - { - type_name(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case CHECK: - case COLLATE: - case CONSTRAINT: - case DEFAULT: - case FOREIGN: - case NOT: - case NULL_T: - case PRIMARY: - case REFERENCES: - case UNIQUE: - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { // ( ... )* - for (;;) { - if ((_tokenSet_4.member(LA(1))) && (_tokenSet_5.member(LA(2)))) { - columnconstraint(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - goto _loop105; - } - - } - _loop105:; - } // ( ... )* - if ( inputState->guessing==0 ) { - columndef_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(currentAST.root); - columndef_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(astFactory->make((new ANTLR_USE_NAMESPACE(antlr)ASTArray(2))->add(astFactory->create(COLUMNDEF,"COLUMNDEF"))->add(columndef_AST))); - currentAST.root = columndef_AST; - if ( columndef_AST!=ANTLR_USE_NAMESPACE(antlr)nullAST && - columndef_AST->getFirstChild() != ANTLR_USE_NAMESPACE(antlr)nullAST ) - currentAST.child = columndef_AST->getFirstChild(); - else - currentAST.child = columndef_AST; - currentAST.advanceChildToEnd(); - } - columndef_AST = currentAST.root; - returnAST = columndef_AST; -} - -void Sqlite3Parser::tableconstraint() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST tableconstraint_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - { - switch ( LA(1)) { - case CONSTRAINT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp52_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp52_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp52_AST); - } - match(CONSTRAINT); - name(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case CHECK: - case FOREIGN: - case PRIMARY: - case UNIQUE: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { - switch ( LA(1)) { - case PRIMARY: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp53_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp53_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp53_AST); - } - match(PRIMARY); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp54_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp54_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp54_AST); - } - match(KEY); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp55_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp55_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp55_AST); - } - match(LPAREN); - indexedcolumn(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { // ( ... )* - for (;;) { - if ((LA(1) == COMMA)) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp56_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp56_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp56_AST); - } - match(COMMA); - indexedcolumn(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - goto _loop126; - } - - } - _loop126:; - } // ( ... )* - ANTLR_USE_NAMESPACE(antlr)RefAST tmp57_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp57_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp57_AST); - } - match(RPAREN); - { - switch ( LA(1)) { - case ON: - { - conflictclause(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case CHECK: - case CONSTRAINT: - case FOREIGN: - case PRIMARY: - case UNIQUE: - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - break; - } - case UNIQUE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp58_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp58_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp58_AST); - } - match(UNIQUE); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp59_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp59_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp59_AST); - } - match(LPAREN); - indexedcolumn(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { // ( ... )* - for (;;) { - if ((LA(1) == COMMA)) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp60_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp60_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp60_AST); - } - match(COMMA); - indexedcolumn(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - goto _loop129; - } - - } - _loop129:; - } // ( ... )* - ANTLR_USE_NAMESPACE(antlr)RefAST tmp61_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp61_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp61_AST); - } - match(RPAREN); - { - switch ( LA(1)) { - case ON: - { - conflictclause(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case CHECK: - case CONSTRAINT: - case FOREIGN: - case PRIMARY: - case UNIQUE: - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - break; - } - case CHECK: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp62_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp62_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp62_AST); - } - match(CHECK); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp63_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp63_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp63_AST); - } - match(LPAREN); - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp64_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp64_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp64_AST); - } - match(RPAREN); - break; - } - case FOREIGN: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp65_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp65_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp65_AST); - } - match(FOREIGN); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp66_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp66_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp66_AST); - } - match(KEY); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp67_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp67_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp67_AST); - } - match(LPAREN); - columnname(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { // ( ... )* - for (;;) { - if ((LA(1) == COMMA)) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp68_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp68_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp68_AST); - } - match(COMMA); - columnname(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - goto _loop132; - } - - } - _loop132:; - } // ( ... )* - ANTLR_USE_NAMESPACE(antlr)RefAST tmp69_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp69_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp69_AST); - } - match(RPAREN); - foreignkeyclause(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - if ( inputState->guessing==0 ) { - tableconstraint_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(currentAST.root); - tableconstraint_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(astFactory->make((new ANTLR_USE_NAMESPACE(antlr)ASTArray(2))->add(astFactory->create(TABLECONSTRAINT,"TABLECONSTRAINT"))->add(tableconstraint_AST))); - currentAST.root = tableconstraint_AST; - if ( tableconstraint_AST!=ANTLR_USE_NAMESPACE(antlr)nullAST && - tableconstraint_AST->getFirstChild() != ANTLR_USE_NAMESPACE(antlr)nullAST ) - currentAST.child = tableconstraint_AST->getFirstChild(); - else - currentAST.child = tableconstraint_AST; - currentAST.advanceChildToEnd(); - } - tableconstraint_AST = currentAST.root; - returnAST = tableconstraint_AST; -} - -void Sqlite3Parser::selectstmt() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST selectstmt_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - ANTLR_USE_NAMESPACE(antlr)RefAST tmp70_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp70_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp70_AST); - } - match(SELECT); - selectstmt_AST = currentAST.root; - returnAST = selectstmt_AST; -} - -void Sqlite3Parser::keywordascolumnname() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST keywordascolumnname_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - { - switch ( LA(1)) { - case ABORT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp71_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp71_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp71_AST); - } - match(ABORT); - break; - } - case ACTION: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp72_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp72_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp72_AST); - } - match(ACTION); - break; - } - case AUTOINCREMENT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp73_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp73_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp73_AST); - } - match(AUTOINCREMENT); - break; - } - case AS: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp74_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp74_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp74_AST); - } - match(AS); - break; - } - case ASC: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp75_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp75_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp75_AST); - } - match(ASC); - break; - } - case AND: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp76_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp76_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp76_AST); - } - match(AND); - break; - } - case OR: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp77_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp77_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp77_AST); - } - match(OR); - break; - } - case CASCADE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp78_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp78_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp78_AST); - } - match(CASCADE); - break; - } - case CASE_T: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp79_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp79_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp79_AST); - } - match(CASE_T); - break; - } - case CAST: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp80_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp80_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp80_AST); - } - match(CAST); - break; - } - case CREATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp81_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp81_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp81_AST); - } - match(CREATE); - break; - } - case COLLATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp82_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp82_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp82_AST); - } - match(COLLATE); - break; - } - case CONFLICT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp83_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp83_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp83_AST); - } - match(CONFLICT); - break; - } - case CURRENT_TIME: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp84_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp84_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp84_AST); - } - match(CURRENT_TIME); - break; - } - case CURRENT_DATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp85_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp85_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp85_AST); - } - match(CURRENT_DATE); - break; - } - case CURRENT_TIMESTAMP: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp86_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp86_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp86_AST); - } - match(CURRENT_TIMESTAMP); - break; - } - case DEFAULT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp87_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp87_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp87_AST); - } - match(DEFAULT); - break; - } - case DEFERRABLE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp88_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp88_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp88_AST); - } - match(DEFERRABLE); - break; - } - case DEFERRED: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp89_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp89_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp89_AST); - } - match(DEFERRED); - break; - } - case DELETE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp90_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp90_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp90_AST); - } - match(DELETE); - break; - } - case DESC: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp91_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp91_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp91_AST); - } - match(DESC); - break; - } - case ELSE_T: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp92_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp92_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp92_AST); - } - match(ELSE_T); - break; - } - case END: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp93_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp93_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp93_AST); - } - match(END); - break; - } - case ESCAPE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp94_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp94_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp94_AST); - } - match(ESCAPE); - break; - } - case FAIL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp95_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp95_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp95_AST); - } - match(FAIL); - break; - } - case GLOB: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp96_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp96_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp96_AST); - } - match(GLOB); - break; - } - case KEY: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp97_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp97_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp97_AST); - } - match(KEY); - break; - } - case LIKE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp98_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp98_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp98_AST); - } - match(LIKE); - break; - } - case TABLE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp99_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp99_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp99_AST); - } - match(TABLE); - break; - } - case IF_T: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp100_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp100_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp100_AST); - } - match(IF_T); - break; - } - case IGNORE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp101_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp101_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp101_AST); - } - match(IGNORE); - break; - } - case INITIALLY: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp102_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp102_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp102_AST); - } - match(INITIALLY); - break; - } - case IMMEDIATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp103_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp103_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp103_AST); - } - match(IMMEDIATE); - break; - } - case IS: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp104_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp104_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp104_AST); - } - match(IS); - break; - } - case NULL_T: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp105_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp105_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp105_AST); - } - match(NULL_T); - break; - } - case MATCH: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp106_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp106_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp106_AST); - } - match(MATCH); - break; - } - case EXISTS: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp107_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp107_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp107_AST); - } - match(EXISTS); - break; - } - case ON: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp108_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp108_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp108_AST); - } - match(ON); - break; - } - case RAISE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp109_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp109_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp109_AST); - } - match(RAISE); - break; - } - case REFERENCES: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp110_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp110_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp110_AST); - } - match(REFERENCES); - break; - } - case REGEXP: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp111_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp111_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp111_AST); - } - match(REGEXP); - break; - } - case REPLACE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp112_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp112_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp112_AST); - } - match(REPLACE); - break; - } - case RESTRICT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp113_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp113_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp113_AST); - } - match(RESTRICT); - break; - } - case ROLLBACK: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp114_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp114_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp114_AST); - } - match(ROLLBACK); - break; - } - case ROWID: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp115_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp115_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp115_AST); - } - match(ROWID); - break; - } - case SET: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp116_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp116_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp116_AST); - } - match(SET); - break; - } - case TEMPORARY: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp117_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp117_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp117_AST); - } - match(TEMPORARY); - break; - } - case TEMP: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp118_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp118_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp118_AST); - } - match(TEMP); - break; - } - case THEN: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp119_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp119_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp119_AST); - } - match(THEN); - break; - } - case UPDATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp120_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp120_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp120_AST); - } - match(UPDATE); - break; - } - case WHEN: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp121_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp121_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp121_AST); - } - match(WHEN); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - if ( inputState->guessing==0 ) { - keywordascolumnname_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(currentAST.root); - keywordascolumnname_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(astFactory->make((new ANTLR_USE_NAMESPACE(antlr)ASTArray(2))->add(astFactory->create(KEYWORDASCOLUMNNAME,"KEYWORDASCOLUMNNAME"))->add(keywordascolumnname_AST))); - currentAST.root = keywordascolumnname_AST; - if ( keywordascolumnname_AST!=ANTLR_USE_NAMESPACE(antlr)nullAST && - keywordascolumnname_AST->getFirstChild() != ANTLR_USE_NAMESPACE(antlr)nullAST ) - currentAST.child = keywordascolumnname_AST->getFirstChild(); - else - currentAST.child = keywordascolumnname_AST; - currentAST.advanceChildToEnd(); - } - keywordascolumnname_AST = currentAST.root; - returnAST = keywordascolumnname_AST; -} - -void Sqlite3Parser::columnname() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST columnname_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - { - switch ( LA(1)) { - case ID: - case QUOTEDID: - case QUOTEDLITERAL: - case STRINGLITERAL: - { - nonkeyword_columnname(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case ABORT: - case ACTION: - case AUTOINCREMENT: - case AS: - case ASC: - case AND: - case OR: - case CASCADE: - case CASE_T: - case CAST: - case CREATE: - case COLLATE: - case CONFLICT: - case CURRENT_TIME: - case CURRENT_DATE: - case CURRENT_TIMESTAMP: - case DEFAULT: - case DEFERRABLE: - case DEFERRED: - case DELETE: - case DESC: - case ELSE_T: - case END: - case ESCAPE: - case FAIL: - case GLOB: - case KEY: - case LIKE: - case TABLE: - case IF_T: - case IGNORE: - case INITIALLY: - case IMMEDIATE: - case IS: - case NULL_T: - case MATCH: - case EXISTS: - case ON: - case RAISE: - case REFERENCES: - case REGEXP: - case REPLACE: - case RESTRICT: - case ROLLBACK: - case ROWID: - case SET: - case TEMPORARY: - case TEMP: - case THEN: - case UPDATE: - case WHEN: - { - keywordascolumnname(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - if ( inputState->guessing==0 ) { - } - columnname_AST = currentAST.root; - returnAST = columnname_AST; -} - -void Sqlite3Parser::type_name() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST type_name_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - { // ( ... )+ - int _cnt109=0; - for (;;) { - if ((_tokenSet_1.member(LA(1)))) { - name(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - if ( _cnt109>=1 ) { goto _loop109; } else {throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename());} - } - - _cnt109++; - } - _loop109:; - } // ( ... )+ - { - switch ( LA(1)) { - case LPAREN: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp122_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp122_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp122_AST); - } - match(LPAREN); - signednumber(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { - switch ( LA(1)) { - case COMMA: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp123_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp123_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp123_AST); - } - match(COMMA); - signednumber(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case RPAREN: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp124_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp124_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp124_AST); - } - match(RPAREN); - break; - } - case CHECK: - case COLLATE: - case CONSTRAINT: - case DEFAULT: - case FOREIGN: - case NOT: - case NULL_T: - case PRIMARY: - case REFERENCES: - case UNIQUE: - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - if ( inputState->guessing==0 ) { - type_name_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(currentAST.root); - type_name_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(astFactory->make((new ANTLR_USE_NAMESPACE(antlr)ASTArray(2))->add(astFactory->create(TYPE_NAME,"TYPE_NAME"))->add(type_name_AST))); - currentAST.root = type_name_AST; - if ( type_name_AST!=ANTLR_USE_NAMESPACE(antlr)nullAST && - type_name_AST->getFirstChild() != ANTLR_USE_NAMESPACE(antlr)nullAST ) - currentAST.child = type_name_AST->getFirstChild(); - else - currentAST.child = type_name_AST; - currentAST.advanceChildToEnd(); - } - type_name_AST = currentAST.root; - returnAST = type_name_AST; -} - -void Sqlite3Parser::columnconstraint() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST columnconstraint_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - { - switch ( LA(1)) { - case CONSTRAINT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp125_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp125_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp125_AST); - } - match(CONSTRAINT); - name(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case CHECK: - case COLLATE: - case DEFAULT: - case NOT: - case NULL_T: - case PRIMARY: - case REFERENCES: - case UNIQUE: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { - switch ( LA(1)) { - case PRIMARY: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp126_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp126_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp126_AST); - } - match(PRIMARY); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp127_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp127_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp127_AST); - } - match(KEY); - { - switch ( LA(1)) { - case ASC: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp128_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp128_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp128_AST); - } - match(ASC); - break; - } - case DESC: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp129_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp129_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp129_AST); - } - match(DESC); - break; - } - case AUTOINCREMENT: - case CHECK: - case COLLATE: - case CONSTRAINT: - case DEFAULT: - case FOREIGN: - case NOT: - case NULL_T: - case ON: - case PRIMARY: - case REFERENCES: - case UNIQUE: - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { - switch ( LA(1)) { - case ON: - { - conflictclause(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case AUTOINCREMENT: - case CHECK: - case COLLATE: - case CONSTRAINT: - case DEFAULT: - case FOREIGN: - case NOT: - case NULL_T: - case PRIMARY: - case REFERENCES: - case UNIQUE: - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { - switch ( LA(1)) { - case AUTOINCREMENT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp130_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp130_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp130_AST); - } - match(AUTOINCREMENT); - break; - } - case CHECK: - case COLLATE: - case CONSTRAINT: - case DEFAULT: - case FOREIGN: - case NOT: - case NULL_T: - case PRIMARY: - case REFERENCES: - case UNIQUE: - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - break; - } - case NOT: - case NULL_T: - { - { - switch ( LA(1)) { - case NOT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp131_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp131_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp131_AST); - } - match(NOT); - break; - } - case NULL_T: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp132_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp132_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp132_AST); - } - match(NULL_T); - { - switch ( LA(1)) { - case ON: - { - conflictclause(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case CHECK: - case COLLATE: - case CONSTRAINT: - case DEFAULT: - case FOREIGN: - case NOT: - case NULL_T: - case PRIMARY: - case REFERENCES: - case UNIQUE: - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - break; - } - case UNIQUE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp133_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp133_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp133_AST); - } - match(UNIQUE); - { - switch ( LA(1)) { - case ON: - { - conflictclause(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case CHECK: - case COLLATE: - case CONSTRAINT: - case DEFAULT: - case FOREIGN: - case NOT: - case NULL_T: - case PRIMARY: - case REFERENCES: - case UNIQUE: - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - break; - } - case CHECK: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp134_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp134_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp134_AST); - } - match(CHECK); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp135_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp135_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp135_AST); - } - match(LPAREN); - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp136_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp136_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp136_AST); - } - match(RPAREN); - break; - } - case DEFAULT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp137_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp137_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp137_AST); - } - match(DEFAULT); - { - switch ( LA(1)) { - case QUOTEDLITERAL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp138_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp138_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp138_AST); - } - match(QUOTEDLITERAL); - break; - } - case LPAREN: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp139_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp139_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp139_AST); - } - match(LPAREN); - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp140_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp140_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp140_AST); - } - match(RPAREN); - break; - } - case ID: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp141_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp141_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp141_AST); - } - match(ID); - break; - } - default: - if ((LA(1) == NUMERIC || LA(1) == PLUS || LA(1) == MINUS) && (_tokenSet_6.member(LA(2)))) { - signednumber(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else if ((LA(1) == STRINGLITERAL) && (_tokenSet_7.member(LA(2)))) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp142_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp142_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp142_AST); - } - match(STRINGLITERAL); - } - else if ((_tokenSet_8.member(LA(1))) && (_tokenSet_7.member(LA(2)))) { - literalvalue(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - break; - } - case COLLATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp143_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp143_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp143_AST); - } - match(COLLATE); - collationname(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case REFERENCES: - { - foreignkeyclause(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - if ( inputState->guessing==0 ) { - columnconstraint_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(currentAST.root); - columnconstraint_AST = ANTLR_USE_NAMESPACE(antlr)RefAST(astFactory->make((new ANTLR_USE_NAMESPACE(antlr)ASTArray(2))->add(astFactory->create(COLUMNCONSTRAINT,"COLUMNCONSTRAINT"))->add(columnconstraint_AST))); - currentAST.root = columnconstraint_AST; - if ( columnconstraint_AST!=ANTLR_USE_NAMESPACE(antlr)nullAST && - columnconstraint_AST->getFirstChild() != ANTLR_USE_NAMESPACE(antlr)nullAST ) - currentAST.child = columnconstraint_AST->getFirstChild(); - else - currentAST.child = columnconstraint_AST; - currentAST.advanceChildToEnd(); - } - columnconstraint_AST = currentAST.root; - returnAST = columnconstraint_AST; -} - -void Sqlite3Parser::name() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST name_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - switch ( LA(1)) { - case ID: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp144_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp144_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp144_AST); - } - match(ID); - name_AST = currentAST.root; - break; - } - case QUOTEDID: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp145_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp145_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp145_AST); - } - match(QUOTEDID); - name_AST = currentAST.root; - break; - } - case QUOTEDLITERAL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp146_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp146_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp146_AST); - } - match(QUOTEDLITERAL); - name_AST = currentAST.root; - break; - } - case STRINGLITERAL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp147_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp147_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp147_AST); - } - match(STRINGLITERAL); - name_AST = currentAST.root; - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - returnAST = name_AST; -} - -void Sqlite3Parser::conflictclause() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST conflictclause_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - ANTLR_USE_NAMESPACE(antlr)RefAST tmp148_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp148_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp148_AST); - } - match(ON); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp149_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp149_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp149_AST); - } - match(CONFLICT); - { - switch ( LA(1)) { - case ROLLBACK: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp150_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp150_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp150_AST); - } - match(ROLLBACK); - break; - } - case ABORT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp151_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp151_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp151_AST); - } - match(ABORT); - break; - } - case FAIL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp152_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp152_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp152_AST); - } - match(FAIL); - break; - } - case IGNORE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp153_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp153_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp153_AST); - } - match(IGNORE); - break; - } - case REPLACE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp154_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp154_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp154_AST); - } - match(REPLACE); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - conflictclause_AST = currentAST.root; - returnAST = conflictclause_AST; -} - -void Sqlite3Parser::expr() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST expr_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - subexpr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { // ( ... )* - for (;;) { - if ((_tokenSet_9.member(LA(1))) && (_tokenSet_10.member(LA(2)))) { - { - switch ( LA(1)) { - case GLOB: - case LIKE: - case IS: - case MATCH: - case REGEXP: - case PLUS: - case MINUS: - case STAR: - case AMPERSAND: - case BITOR: - case OROP: - case EQUAL: - case EQUAL2: - case GREATER: - case GREATEREQUAL: - case LOWER: - case LOWEREQUAL: - case UNEQUAL: - case UNEQUAL2: - case BITWISELEFT: - case BITWISERIGHT: - case SLASH: - case PERCENT: - { - binaryoperator(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case AND: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp155_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp155_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp155_AST); - } - match(AND); - break; - } - case OR: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp156_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp156_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp156_AST); - } - match(OR); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - subexpr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - goto _loop160; - } - - } - _loop160:; - } // ( ... )* - expr_AST = currentAST.root; - returnAST = expr_AST; -} - -void Sqlite3Parser::literalvalue() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST literalvalue_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - switch ( LA(1)) { - case NUMERIC: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp157_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp157_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp157_AST); - } - match(NUMERIC); - literalvalue_AST = currentAST.root; - break; - } - case STRINGLITERAL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp158_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp158_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp158_AST); - } - match(STRINGLITERAL); - literalvalue_AST = currentAST.root; - break; - } - case NULL_T: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp159_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp159_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp159_AST); - } - match(NULL_T); - literalvalue_AST = currentAST.root; - break; - } - case CURRENT_TIME: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp160_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp160_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp160_AST); - } - match(CURRENT_TIME); - literalvalue_AST = currentAST.root; - break; - } - case CURRENT_DATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp161_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp161_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp161_AST); - } - match(CURRENT_DATE); - literalvalue_AST = currentAST.root; - break; - } - case CURRENT_TIMESTAMP: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp162_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp162_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp162_AST); - } - match(CURRENT_TIMESTAMP); - literalvalue_AST = currentAST.root; - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - returnAST = literalvalue_AST; -} - -void Sqlite3Parser::foreignkeyclause() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST foreignkeyclause_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - ANTLR_USE_NAMESPACE(antlr)RefAST tmp163_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp163_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp163_AST); - } - match(REFERENCES); - tablename(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { - switch ( LA(1)) { - case LPAREN: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp164_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp164_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp164_AST); - } - match(LPAREN); - columnname(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { // ( ... )* - for (;;) { - if ((LA(1) == COMMA)) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp165_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp165_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp165_AST); - } - match(COMMA); - columnname(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - goto _loop142; - } - - } - _loop142:; - } // ( ... )* - ANTLR_USE_NAMESPACE(antlr)RefAST tmp166_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp166_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp166_AST); - } - match(RPAREN); - break; - } - case CHECK: - case COLLATE: - case CONSTRAINT: - case DEFAULT: - case DEFERRABLE: - case FOREIGN: - case NOT: - case NULL_T: - case MATCH: - case ON: - case PRIMARY: - case REFERENCES: - case UNIQUE: - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { // ( ... )* - for (;;) { - switch ( LA(1)) { - case ON: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp167_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp167_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp167_AST); - } - match(ON); - { - switch ( LA(1)) { - case DELETE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp168_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp168_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp168_AST); - } - match(DELETE); - break; - } - case UPDATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp169_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp169_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp169_AST); - } - match(UPDATE); - break; - } - case INSERT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp170_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp170_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp170_AST); - } - match(INSERT); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { - switch ( LA(1)) { - case SET: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp171_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp171_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp171_AST); - } - match(SET); - { - switch ( LA(1)) { - case NULL_T: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp172_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp172_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp172_AST); - } - match(NULL_T); - break; - } - case DEFAULT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp173_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp173_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp173_AST); - } - match(DEFAULT); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - break; - } - case CASCADE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp174_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp174_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp174_AST); - } - match(CASCADE); - break; - } - case RESTRICT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp175_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp175_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp175_AST); - } - match(RESTRICT); - break; - } - case NO: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp176_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp176_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp176_AST); - } - match(NO); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp177_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp177_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp177_AST); - } - match(ACTION); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - break; - } - case MATCH: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp178_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp178_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp178_AST); - } - match(MATCH); - name(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - default: - { - goto _loop147; - } - } - } - _loop147:; - } // ( ... )* - { - bool synPredMatched150 = false; - if (((LA(1) == NOT) && (LA(2) == DEFERRABLE))) { - int _m150 = mark(); - synPredMatched150 = true; - inputState->guessing++; - try { - { - match(NOT); - match(DEFERRABLE); - } - } - catch (ANTLR_USE_NAMESPACE(antlr)RecognitionException& pe) { - synPredMatched150 = false; - } - rewind(_m150); - inputState->guessing--; - } - if ( synPredMatched150 ) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp179_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp179_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp179_AST); - } - match(NOT); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp180_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp180_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp180_AST); - } - match(DEFERRABLE); - { - switch ( LA(1)) { - case INITIALLY: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp181_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp181_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp181_AST); - } - match(INITIALLY); - { - switch ( LA(1)) { - case DEFERRED: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp182_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp182_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp182_AST); - } - match(DEFERRED); - break; - } - case IMMEDIATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp183_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp183_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp183_AST); - } - match(IMMEDIATE); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - break; - } - case CHECK: - case COLLATE: - case CONSTRAINT: - case DEFAULT: - case FOREIGN: - case NOT: - case NULL_T: - case PRIMARY: - case REFERENCES: - case UNIQUE: - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - } - else if ((LA(1) == DEFERRABLE)) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp184_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp184_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp184_AST); - } - match(DEFERRABLE); - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp185_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp185_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp185_AST); - } - match(INITIALLY); - { - switch ( LA(1)) { - case DEFERRED: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp186_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp186_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp186_AST); - } - match(DEFERRED); - break; - } - case IMMEDIATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp187_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp187_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp187_AST); - } - match(IMMEDIATE); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - } - } - else if ((_tokenSet_7.member(LA(1))) && (_tokenSet_11.member(LA(2)))) { - } - else { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - - } - foreignkeyclause_AST = currentAST.root; - returnAST = foreignkeyclause_AST; -} - -void Sqlite3Parser::indexedcolumn() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST indexedcolumn_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - columnname(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { - switch ( LA(1)) { - case COLLATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp188_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp188_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp188_AST); - } - match(COLLATE); - collationname(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case AUTOINCREMENT: - case ASC: - case DESC: - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { - switch ( LA(1)) { - case ASC: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp189_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp189_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp189_AST); - } - match(ASC); - break; - } - case DESC: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp190_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp190_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp190_AST); - } - match(DESC); - break; - } - case AUTOINCREMENT: - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { - switch ( LA(1)) { - case AUTOINCREMENT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp191_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp191_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp191_AST); - } - match(AUTOINCREMENT); - break; - } - case RPAREN: - case COMMA: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - indexedcolumn_AST = currentAST.root; - returnAST = indexedcolumn_AST; -} - -void Sqlite3Parser::functionname() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST functionname_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - id(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - functionname_AST = currentAST.root; - returnAST = functionname_AST; -} - -void Sqlite3Parser::subexpr() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST subexpr_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - { - switch ( LA(1)) { - case MINUS: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp192_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp192_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp192_AST); - } - match(MINUS); - break; - } - case PLUS: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp193_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp193_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp193_AST); - } - match(PLUS); - break; - } - case TILDE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp194_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp194_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp194_AST); - } - match(TILDE); - break; - } - case NOT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp195_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp195_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp195_AST); - } - match(NOT); - break; - } - case ABORT: - case ACTION: - case AUTOINCREMENT: - case AS: - case ASC: - case AND: - case OR: - case CASCADE: - case CASE_T: - case CAST: - case CREATE: - case COLLATE: - case CONFLICT: - case CURRENT_TIME: - case CURRENT_DATE: - case CURRENT_TIMESTAMP: - case DEFAULT: - case DEFERRABLE: - case DEFERRED: - case DELETE: - case DESC: - case ELSE_T: - case END: - case ESCAPE: - case FAIL: - case GLOB: - case KEY: - case LIKE: - case TABLE: - case IF_T: - case IGNORE: - case INITIALLY: - case IMMEDIATE: - case IS: - case NULL_T: - case MATCH: - case EXISTS: - case ON: - case RAISE: - case REFERENCES: - case REGEXP: - case REPLACE: - case RESTRICT: - case ROLLBACK: - case ROWID: - case SET: - case TEMPORARY: - case TEMP: - case THEN: - case UPDATE: - case WHEN: - case ID: - case QUOTEDID: - case QUOTEDLITERAL: - case NUMERIC: - case STRINGLITERAL: - case LPAREN: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { - if ((_tokenSet_8.member(LA(1))) && (_tokenSet_12.member(LA(2)))) { - literalvalue(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else if ((_tokenSet_2.member(LA(1))) && (_tokenSet_13.member(LA(2)))) { - { - if ((_tokenSet_1.member(LA(1))) && (LA(2) == DOT)) { - { - if ((_tokenSet_1.member(LA(1))) && (LA(2) == DOT)) { - databasename(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp196_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp196_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp196_AST); - } - match(DOT); - } - else if ((_tokenSet_1.member(LA(1))) && (LA(2) == DOT)) { - } - else { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - - } - tablename(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp197_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp197_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp197_AST); - } - match(DOT); - } - else if ((_tokenSet_2.member(LA(1))) && (_tokenSet_12.member(LA(2)))) { - } - else { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - - } - columnname(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else if ((_tokenSet_1.member(LA(1))) && (LA(2) == LPAREN)) { - functionname(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp198_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp198_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp198_AST); - } - match(LPAREN); - { - switch ( LA(1)) { - case ABORT: - case ACTION: - case AUTOINCREMENT: - case AS: - case ASC: - case AND: - case OR: - case CASCADE: - case CASE_T: - case CAST: - case CREATE: - case COLLATE: - case CONFLICT: - case CURRENT_TIME: - case CURRENT_DATE: - case CURRENT_TIMESTAMP: - case DEFAULT: - case DEFERRABLE: - case DEFERRED: - case DELETE: - case DESC: - case ELSE_T: - case END: - case ESCAPE: - case FAIL: - case GLOB: - case KEY: - case LIKE: - case TABLE: - case IF_T: - case IGNORE: - case INITIALLY: - case IMMEDIATE: - case IS: - case NOT: - case NULL_T: - case MATCH: - case EXISTS: - case ON: - case RAISE: - case REFERENCES: - case REGEXP: - case REPLACE: - case RESTRICT: - case ROLLBACK: - case ROWID: - case SET: - case TEMPORARY: - case TEMP: - case THEN: - case UPDATE: - case WHEN: - case ID: - case QUOTEDID: - case QUOTEDLITERAL: - case NUMERIC: - case STRINGLITERAL: - case LPAREN: - case PLUS: - case MINUS: - case TILDE: - { - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { // ( ... )* - for (;;) { - if ((LA(1) == COMMA)) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp199_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp199_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp199_AST); - } - match(COMMA); - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - goto _loop168; - } - - } - _loop168:; - } // ( ... )* - break; - } - case RPAREN: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp200_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp200_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp200_AST); - } - match(RPAREN); - } - else if ((LA(1) == CAST) && (LA(2) == LPAREN)) { - castexpr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else if ((LA(1) == EXISTS || LA(1) == LPAREN) && (_tokenSet_14.member(LA(2)))) { - { - switch ( LA(1)) { - case EXISTS: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp201_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp201_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp201_AST); - } - match(EXISTS); - break; - } - case LPAREN: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp202_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp202_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp202_AST); - } - match(LPAREN); - { - switch ( LA(1)) { - case ABORT: - case ACTION: - case AUTOINCREMENT: - case AS: - case ASC: - case AND: - case OR: - case CASCADE: - case CASE_T: - case CAST: - case CREATE: - case COLLATE: - case CONFLICT: - case CURRENT_TIME: - case CURRENT_DATE: - case CURRENT_TIMESTAMP: - case DEFAULT: - case DEFERRABLE: - case DEFERRED: - case DELETE: - case DESC: - case ELSE_T: - case END: - case ESCAPE: - case FAIL: - case GLOB: - case KEY: - case LIKE: - case TABLE: - case IF_T: - case IGNORE: - case INITIALLY: - case IMMEDIATE: - case IS: - case NOT: - case NULL_T: - case MATCH: - case EXISTS: - case ON: - case RAISE: - case REFERENCES: - case REGEXP: - case REPLACE: - case RESTRICT: - case ROLLBACK: - case ROWID: - case SET: - case TEMPORARY: - case TEMP: - case THEN: - case UPDATE: - case WHEN: - case ID: - case QUOTEDID: - case QUOTEDLITERAL: - case NUMERIC: - case STRINGLITERAL: - case LPAREN: - case PLUS: - case MINUS: - case TILDE: - { - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case SELECT: - { - selectstmt(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp203_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp203_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp203_AST); - } - match(RPAREN); - } - else if ((LA(1) == CASE_T) && (_tokenSet_10.member(LA(2)))) { - caseexpr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else if ((LA(1) == RAISE) && (LA(2) == LPAREN)) { - raisefunction(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - - } - { - if ((_tokenSet_15.member(LA(1))) && (_tokenSet_16.member(LA(2)))) { - suffixexpr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else if ((_tokenSet_17.member(LA(1))) && (_tokenSet_18.member(LA(2)))) { - } - else { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - - } - subexpr_AST = currentAST.root; - returnAST = subexpr_AST; -} - -void Sqlite3Parser::binaryoperator() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST binaryoperator_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - switch ( LA(1)) { - case OROP: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp204_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp204_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp204_AST); - } - match(OROP); - binaryoperator_AST = currentAST.root; - break; - } - case STAR: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp205_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp205_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp205_AST); - } - match(STAR); - binaryoperator_AST = currentAST.root; - break; - } - case SLASH: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp206_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp206_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp206_AST); - } - match(SLASH); - binaryoperator_AST = currentAST.root; - break; - } - case PERCENT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp207_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp207_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp207_AST); - } - match(PERCENT); - binaryoperator_AST = currentAST.root; - break; - } - case PLUS: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp208_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp208_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp208_AST); - } - match(PLUS); - binaryoperator_AST = currentAST.root; - break; - } - case MINUS: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp209_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp209_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp209_AST); - } - match(MINUS); - binaryoperator_AST = currentAST.root; - break; - } - case BITWISELEFT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp210_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp210_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp210_AST); - } - match(BITWISELEFT); - binaryoperator_AST = currentAST.root; - break; - } - case BITWISERIGHT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp211_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp211_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp211_AST); - } - match(BITWISERIGHT); - binaryoperator_AST = currentAST.root; - break; - } - case AMPERSAND: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp212_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp212_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp212_AST); - } - match(AMPERSAND); - binaryoperator_AST = currentAST.root; - break; - } - case BITOR: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp213_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp213_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp213_AST); - } - match(BITOR); - binaryoperator_AST = currentAST.root; - break; - } - case LOWER: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp214_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp214_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp214_AST); - } - match(LOWER); - binaryoperator_AST = currentAST.root; - break; - } - case LOWEREQUAL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp215_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp215_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp215_AST); - } - match(LOWEREQUAL); - binaryoperator_AST = currentAST.root; - break; - } - case GREATER: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp216_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp216_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp216_AST); - } - match(GREATER); - binaryoperator_AST = currentAST.root; - break; - } - case GREATEREQUAL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp217_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp217_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp217_AST); - } - match(GREATEREQUAL); - binaryoperator_AST = currentAST.root; - break; - } - case EQUAL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp218_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp218_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp218_AST); - } - match(EQUAL); - binaryoperator_AST = currentAST.root; - break; - } - case EQUAL2: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp219_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp219_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp219_AST); - } - match(EQUAL2); - binaryoperator_AST = currentAST.root; - break; - } - case UNEQUAL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp220_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp220_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp220_AST); - } - match(UNEQUAL); - binaryoperator_AST = currentAST.root; - break; - } - case UNEQUAL2: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp221_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp221_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp221_AST); - } - match(UNEQUAL2); - binaryoperator_AST = currentAST.root; - break; - } - case IS: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp222_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp222_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp222_AST); - } - match(IS); - binaryoperator_AST = currentAST.root; - break; - } - case GLOB: - case LIKE: - case MATCH: - case REGEXP: - { - like_operator(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - binaryoperator_AST = currentAST.root; - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - returnAST = binaryoperator_AST; -} - -void Sqlite3Parser::castexpr() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST castexpr_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - ANTLR_USE_NAMESPACE(antlr)RefAST tmp223_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp223_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp223_AST); - } - match(CAST); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp224_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp224_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp224_AST); - } - match(LPAREN); - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp225_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp225_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp225_AST); - } - match(AS); - type_name(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp226_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp226_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp226_AST); - } - match(RPAREN); - castexpr_AST = currentAST.root; - returnAST = castexpr_AST; -} - -void Sqlite3Parser::caseexpr() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST caseexpr_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - ANTLR_USE_NAMESPACE(antlr)RefAST tmp227_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp227_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp227_AST); - } - match(CASE_T); - { - if ((_tokenSet_10.member(LA(1))) && (_tokenSet_19.member(LA(2)))) { - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else if ((LA(1) == WHEN) && (_tokenSet_10.member(LA(2)))) { - } - else { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - - } - { // ( ... )+ - int _cnt176=0; - for (;;) { - if ((LA(1) == WHEN)) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp228_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp228_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp228_AST); - } - match(WHEN); - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp229_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp229_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp229_AST); - } - match(THEN); - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - if ( _cnt176>=1 ) { goto _loop176; } else {throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename());} - } - - _cnt176++; - } - _loop176:; - } // ( ... )+ - { - switch ( LA(1)) { - case ELSE_T: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp230_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp230_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp230_AST); - } - match(ELSE_T); - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case END: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp231_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp231_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp231_AST); - } - match(END); - caseexpr_AST = currentAST.root; - returnAST = caseexpr_AST; -} - -void Sqlite3Parser::raisefunction() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST raisefunction_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - ANTLR_USE_NAMESPACE(antlr)RefAST tmp232_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp232_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp232_AST); - } - match(RAISE); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp233_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp233_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp233_AST); - } - match(LPAREN); - { - switch ( LA(1)) { - case IGNORE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp234_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp234_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp234_AST); - } - match(IGNORE); - break; - } - case ABORT: - case FAIL: - case ROLLBACK: - { - { - switch ( LA(1)) { - case ROLLBACK: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp235_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp235_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp235_AST); - } - match(ROLLBACK); - break; - } - case ABORT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp236_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp236_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp236_AST); - } - match(ABORT); - break; - } - case FAIL: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp237_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp237_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp237_AST); - } - match(FAIL); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp238_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp238_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp238_AST); - } - match(COMMA); - ANTLR_USE_NAMESPACE(antlr)RefAST tmp239_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp239_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp239_AST); - } - match(STRINGLITERAL); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp240_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp240_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp240_AST); - } - match(RPAREN); - raisefunction_AST = currentAST.root; - returnAST = raisefunction_AST; -} - -void Sqlite3Parser::suffixexpr() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST suffixexpr_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - switch ( LA(1)) { - case COLLATE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp241_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp241_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp241_AST); - } - match(COLLATE); - collationname(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - suffixexpr_AST = currentAST.root; - break; - } - case BETWEEN: - case GLOB: - case LIKE: - case IN: - case NOT: - case MATCH: - case REGEXP: - { - { - switch ( LA(1)) { - case NOT: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp242_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp242_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp242_AST); - } - match(NOT); - break; - } - case BETWEEN: - case GLOB: - case LIKE: - case IN: - case MATCH: - case REGEXP: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - { - switch ( LA(1)) { - case BETWEEN: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp243_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp243_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp243_AST); - } - match(BETWEEN); - subexpr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { // ( ... )* - for (;;) { - if ((_tokenSet_20.member(LA(1)))) { - { - switch ( LA(1)) { - case GLOB: - case LIKE: - case IS: - case MATCH: - case REGEXP: - case PLUS: - case MINUS: - case STAR: - case AMPERSAND: - case BITOR: - case OROP: - case EQUAL: - case EQUAL2: - case GREATER: - case GREATEREQUAL: - case LOWER: - case LOWEREQUAL: - case UNEQUAL: - case UNEQUAL2: - case BITWISELEFT: - case BITWISERIGHT: - case SLASH: - case PERCENT: - { - binaryoperator(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case OR: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp244_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp244_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp244_AST); - } - match(OR); - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - subexpr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - goto _loop187; - } - - } - _loop187:; - } // ( ... )* - ANTLR_USE_NAMESPACE(antlr)RefAST tmp245_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp245_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp245_AST); - } - match(AND); - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case IN: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp246_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp246_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp246_AST); - } - match(IN); - { - switch ( LA(1)) { - case LPAREN: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp247_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp247_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp247_AST); - } - match(LPAREN); - { - switch ( LA(1)) { - case SELECT: - { - selectstmt(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - case ABORT: - case ACTION: - case AUTOINCREMENT: - case AS: - case ASC: - case AND: - case OR: - case CASCADE: - case CASE_T: - case CAST: - case CREATE: - case COLLATE: - case CONFLICT: - case CURRENT_TIME: - case CURRENT_DATE: - case CURRENT_TIMESTAMP: - case DEFAULT: - case DEFERRABLE: - case DEFERRED: - case DELETE: - case DESC: - case ELSE_T: - case END: - case ESCAPE: - case FAIL: - case GLOB: - case KEY: - case LIKE: - case TABLE: - case IF_T: - case IGNORE: - case INITIALLY: - case IMMEDIATE: - case IS: - case NOT: - case NULL_T: - case MATCH: - case EXISTS: - case ON: - case RAISE: - case REFERENCES: - case REGEXP: - case REPLACE: - case RESTRICT: - case ROLLBACK: - case ROWID: - case SET: - case TEMPORARY: - case TEMP: - case THEN: - case UPDATE: - case WHEN: - case ID: - case QUOTEDID: - case QUOTEDLITERAL: - case NUMERIC: - case STRINGLITERAL: - case LPAREN: - case PLUS: - case MINUS: - case TILDE: - { - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { // ( ... )* - for (;;) { - if ((LA(1) == COMMA)) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp248_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp248_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp248_AST); - } - match(COMMA); - expr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - goto _loop191; - } - - } - _loop191:; - } // ( ... )* - break; - } - case RPAREN: - { - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - ANTLR_USE_NAMESPACE(antlr)RefAST tmp249_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp249_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp249_AST); - } - match(RPAREN); - break; - } - case ID: - case QUOTEDID: - case QUOTEDLITERAL: - case STRINGLITERAL: - { - tablename(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - break; - } - case GLOB: - case LIKE: - case MATCH: - case REGEXP: - { - like_operator(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - subexpr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { - if ((LA(1) == ESCAPE) && (_tokenSet_10.member(LA(2)))) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp250_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp250_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp250_AST); - } - match(ESCAPE); - subexpr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else if ((_tokenSet_17.member(LA(1))) && (_tokenSet_18.member(LA(2)))) { - } - else { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - - } - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - } - suffixexpr_AST = currentAST.root; - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - returnAST = suffixexpr_AST; -} - -void Sqlite3Parser::like_operator() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST like_operator_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - switch ( LA(1)) { - case LIKE: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp251_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp251_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp251_AST); - } - match(LIKE); - like_operator_AST = currentAST.root; - break; - } - case GLOB: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp252_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp252_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp252_AST); - } - match(GLOB); - like_operator_AST = currentAST.root; - break; - } - case REGEXP: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp253_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp253_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp253_AST); - } - match(REGEXP); - like_operator_AST = currentAST.root; - break; - } - case MATCH: - { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp254_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp254_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp254_AST); - } - match(MATCH); - like_operator_AST = currentAST.root; - break; - } - default: - { - throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename()); - } - } - returnAST = like_operator_AST; -} - -void Sqlite3Parser::between_subexpr() { - returnAST = ANTLR_USE_NAMESPACE(antlr)nullAST; - ANTLR_USE_NAMESPACE(antlr)ASTPair currentAST; - ANTLR_USE_NAMESPACE(antlr)RefAST between_subexpr_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - - subexpr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - { // ( ... )+ - int _cnt181=0; - for (;;) { - if ((LA(1) == AND)) { - ANTLR_USE_NAMESPACE(antlr)RefAST tmp255_AST = ANTLR_USE_NAMESPACE(antlr)nullAST; - if ( inputState->guessing == 0 ) { - tmp255_AST = astFactory->create(LT(1)); - astFactory->addASTChild(currentAST, tmp255_AST); - } - match(AND); - subexpr(); - if (inputState->guessing==0) { - astFactory->addASTChild( currentAST, returnAST ); - } - } - else { - if ( _cnt181>=1 ) { goto _loop181; } else {throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename());} - } - - _cnt181++; - } - _loop181:; - } // ( ... )+ - between_subexpr_AST = currentAST.root; - returnAST = between_subexpr_AST; -} - -void Sqlite3Parser::initializeASTFactory( ANTLR_USE_NAMESPACE(antlr)ASTFactory& factory ) -{ - factory.setMaxNodeType(106); -} -const char* Sqlite3Parser::tokenNames[] = { - "<0>", - "EOF", - "<2>", - "NULL_TREE_LOOKAHEAD", - "\"ABORT\"", - "\"ACTION\"", - "\"AUTOINCREMENT\"", - "\"AS\"", - "\"ASC\"", - "\"AND\"", - "\"OR\"", - "\"BETWEEN\"", - "\"CASCADE\"", - "\"CASE\"", - "\"CAST\"", - "\"CHECK\"", - "\"CREATE\"", - "\"COLLATE\"", - "\"CONFLICT\"", - "\"CONSTRAINT\"", - "\"CURRENT_TIME\"", - "\"CURRENT_DATE\"", - "\"CURRENT_TIMESTAMP\"", - "\"DEFAULT\"", - "\"DEFERRABLE\"", - "\"DEFERRED\"", - "\"DELETE\"", - "\"DESC\"", - "\"ELSE\"", - "\"END\"", - "\"ESCAPE\"", - "\"FAIL\"", - "\"FOREIGN\"", - "\"GLOB\"", - "\"KEY\"", - "\"LIKE\"", - "\"TABLE\"", - "\"IF\"", - "\"IGNORE\"", - "\"IN\"", - "\"INITIALLY\"", - "\"INSERT\"", - "\"IMMEDIATE\"", - "\"IS\"", - "\"NO\"", - "\"NOT\"", - "\"NULL\"", - "\"MATCH\"", - "\"EXISTS\"", - "\"ON\"", - "\"PRIMARY\"", - "\"RAISE\"", - "\"REFERENCES\"", - "\"REGEXP\"", - "\"REPLACE\"", - "\"RESTRICT\"", - "\"ROLLBACK\"", - "\"ROWID\"", - "\"SET\"", - "\"TEMPORARY\"", - "\"TEMP\"", - "\"THEN\"", - "\"UNIQUE\"", - "\"UPDATE\"", - "\"WHEN\"", - "\"WITHOUT\"", - "TYPE_NAME", - "COLUMNDEF", - "COLUMNCONSTRAINT", - "TABLECONSTRAINT", - "CREATETABLE", - "KEYWORDASTABLENAME", - "KEYWORDASCOLUMNNAME", - "DIGIT", - "DOT", - "ID", - "QUOTEDID", - "QUOTEDLITERAL", - "NUMERIC", - "NL", - "COMMENT", - "WS", - "STRINGLITERAL", - "LPAREN", - "RPAREN", - "COMMA", - "SEMI", - "PLUS", - "MINUS", - "STAR", - "TILDE", - "AMPERSAND", - "BITOR", - "OROP", - "EQUAL", - "EQUAL2", - "GREATER", - "GREATEREQUAL", - "LOWER", - "LOWEREQUAL", - "UNEQUAL", - "UNEQUAL2", - "BITWISELEFT", - "BITWISERIGHT", - "SELECT", - "SLASH", - "PERCENT", - 0 -}; - -const unsigned long Sqlite3Parser::_tokenSet_0_data_[] = { 0UL, 0UL, 277504UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// DOT ID QUOTEDID QUOTEDLITERAL STRINGLITERAL -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_0(_tokenSet_0_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_1_data_[] = { 0UL, 0UL, 276480UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// ID QUOTEDID QUOTEDLITERAL STRINGLITERAL -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_1(_tokenSet_1_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_2_data_[] = { 4294408176UL, 3220950398UL, 276481UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// "ABORT" "ACTION" "AUTOINCREMENT" "AS" "ASC" "AND" "OR" "CASCADE" "CASE" -// "CAST" "CREATE" "COLLATE" "CONFLICT" "CURRENT_TIME" "CURRENT_DATE" "CURRENT_TIMESTAMP" -// "DEFAULT" "DEFERRABLE" "DEFERRED" "DELETE" "DESC" "ELSE" "END" "ESCAPE" -// "FAIL" "GLOB" "KEY" "LIKE" "TABLE" "IF" "IGNORE" "INITIALLY" "IMMEDIATE" -// "IS" "NULL" "MATCH" "EXISTS" "ON" "RAISE" "REFERENCES" "REGEXP" "REPLACE" -// "RESTRICT" "ROLLBACK" "ROWID" "SET" "TEMPORARY" "TEMP" "THEN" "UPDATE" -// "WHEN" ID QUOTEDID QUOTEDLITERAL STRINGLITERAL -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_2(_tokenSet_2_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_3_data_[] = { 557056UL, 1074003969UL, 2097152UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// "CHECK" "CONSTRAINT" "FOREIGN" "PRIMARY" "UNIQUE" COMMA -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_3(_tokenSet_3_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_4_data_[] = { 9076736UL, 1075077120UL, 0UL, 0UL }; -// "CHECK" "COLLATE" "CONSTRAINT" "DEFAULT" "NOT" "NULL" "PRIMARY" "REFERENCES" -// "UNIQUE" -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_4(_tokenSet_4_data_,4); -const unsigned long Sqlite3Parser::_tokenSet_5_data_[] = { 16416768UL, 1075208197UL, 29128704UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// "CHECK" "COLLATE" "CONSTRAINT" "CURRENT_TIME" "CURRENT_DATE" "CURRENT_TIMESTAMP" -// "DEFAULT" "FOREIGN" "KEY" "NOT" "NULL" "ON" "PRIMARY" "REFERENCES" "UNIQUE" -// ID QUOTEDID QUOTEDLITERAL NUMERIC STRINGLITERAL LPAREN RPAREN COMMA -// PLUS MINUS -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_5(_tokenSet_5_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_6_data_[] = { 9076736UL, 1075077121UL, 3162112UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// "CHECK" "COLLATE" "CONSTRAINT" "DEFAULT" "FOREIGN" "NOT" "NULL" "PRIMARY" -// "REFERENCES" "UNIQUE" NUMERIC RPAREN COMMA -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_6(_tokenSet_6_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_7_data_[] = { 9076736UL, 1075077121UL, 3145728UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// "CHECK" "COLLATE" "CONSTRAINT" "DEFAULT" "FOREIGN" "NOT" "NULL" "PRIMARY" -// "REFERENCES" "UNIQUE" RPAREN COMMA -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_7(_tokenSet_7_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_8_data_[] = { 7340032UL, 16384UL, 278528UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// "CURRENT_TIME" "CURRENT_DATE" "CURRENT_TIMESTAMP" "NULL" NUMERIC STRINGLITERAL -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_8(_tokenSet_8_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_9_data_[] = { 1536UL, 2131978UL, 4219469824UL, 1791UL, 0UL, 0UL, 0UL, 0UL }; -// "AND" "OR" "GLOB" "LIKE" "IS" "MATCH" "REGEXP" PLUS MINUS STAR AMPERSAND -// BITOR OROP EQUAL EQUAL2 GREATER GREATEREQUAL LOWER LOWEREQUAL UNEQUAL -// UNEQUAL2 BITWISELEFT BITWISERIGHT SLASH PERCENT -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_9(_tokenSet_9_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_10_data_[] = { 4294408176UL, 3220958590UL, 93091841UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// "ABORT" "ACTION" "AUTOINCREMENT" "AS" "ASC" "AND" "OR" "CASCADE" "CASE" -// "CAST" "CREATE" "COLLATE" "CONFLICT" "CURRENT_TIME" "CURRENT_DATE" "CURRENT_TIMESTAMP" -// "DEFAULT" "DEFERRABLE" "DEFERRED" "DELETE" "DESC" "ELSE" "END" "ESCAPE" -// "FAIL" "GLOB" "KEY" "LIKE" "TABLE" "IF" "IGNORE" "INITIALLY" "IMMEDIATE" -// "IS" "NOT" "NULL" "MATCH" "EXISTS" "ON" "RAISE" "REFERENCES" "REGEXP" -// "REPLACE" "RESTRICT" "ROLLBACK" "ROWID" "SET" "TEMPORARY" "TEMP" "THEN" -// "UPDATE" "WHEN" ID QUOTEDID QUOTEDLITERAL NUMERIC STRINGLITERAL LPAREN -// PLUS MINUS TILDE -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_10(_tokenSet_10_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_11_data_[] = { 4294965234UL, 4294962559UL, 33323011UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// EOF "ABORT" "ACTION" "AUTOINCREMENT" "AS" "ASC" "AND" "OR" "CASCADE" -// "CASE" "CAST" "CHECK" "CREATE" "COLLATE" "CONFLICT" "CONSTRAINT" "CURRENT_TIME" -// "CURRENT_DATE" "CURRENT_TIMESTAMP" "DEFAULT" "DEFERRABLE" "DEFERRED" -// "DELETE" "DESC" "ELSE" "END" "ESCAPE" "FAIL" "FOREIGN" "GLOB" "KEY" -// "LIKE" "TABLE" "IF" "IGNORE" "INITIALLY" "IMMEDIATE" "IS" "NOT" "NULL" -// "MATCH" "EXISTS" "ON" "PRIMARY" "RAISE" "REFERENCES" "REGEXP" "REPLACE" -// "RESTRICT" "ROLLBACK" "ROWID" "SET" "TEMPORARY" "TEMP" "THEN" "UNIQUE" -// "UPDATE" "WHEN" "WITHOUT" ID QUOTEDID QUOTEDLITERAL NUMERIC STRINGLITERAL -// LPAREN RPAREN COMMA SEMI PLUS MINUS -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_11(_tokenSet_11_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_12_data_[] = { 1879182978UL, 539011210UL, 4222615553UL, 1791UL, 0UL, 0UL, 0UL, 0UL }; -// EOF "AS" "AND" "OR" "BETWEEN" "COLLATE" "ELSE" "END" "ESCAPE" "GLOB" -// "LIKE" "IN" "IS" "NOT" "MATCH" "REGEXP" "THEN" "WHEN" RPAREN COMMA PLUS -// MINUS STAR AMPERSAND BITOR OROP EQUAL EQUAL2 GREATER GREATEREQUAL LOWER -// LOWEREQUAL UNEQUAL UNEQUAL2 BITWISELEFT BITWISERIGHT SLASH PERCENT -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_12(_tokenSet_12_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_13_data_[] = { 1879182978UL, 539011210UL, 4222616577UL, 1791UL, 0UL, 0UL, 0UL, 0UL }; -// EOF "AS" "AND" "OR" "BETWEEN" "COLLATE" "ELSE" "END" "ESCAPE" "GLOB" -// "LIKE" "IN" "IS" "NOT" "MATCH" "REGEXP" "THEN" "WHEN" DOT RPAREN COMMA -// PLUS MINUS STAR AMPERSAND BITOR OROP EQUAL EQUAL2 GREATER GREATEREQUAL -// LOWER LOWEREQUAL UNEQUAL UNEQUAL2 BITWISELEFT BITWISERIGHT SLASH PERCENT -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_13(_tokenSet_13_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_14_data_[] = { 4294408176UL, 3220958590UL, 93091841UL, 256UL, 0UL, 0UL, 0UL, 0UL }; -// "ABORT" "ACTION" "AUTOINCREMENT" "AS" "ASC" "AND" "OR" "CASCADE" "CASE" -// "CAST" "CREATE" "COLLATE" "CONFLICT" "CURRENT_TIME" "CURRENT_DATE" "CURRENT_TIMESTAMP" -// "DEFAULT" "DEFERRABLE" "DEFERRED" "DELETE" "DESC" "ELSE" "END" "ESCAPE" -// "FAIL" "GLOB" "KEY" "LIKE" "TABLE" "IF" "IGNORE" "INITIALLY" "IMMEDIATE" -// "IS" "NOT" "NULL" "MATCH" "EXISTS" "ON" "RAISE" "REFERENCES" "REGEXP" -// "REPLACE" "RESTRICT" "ROLLBACK" "ROWID" "SET" "TEMPORARY" "TEMP" "THEN" -// "UPDATE" "WHEN" ID QUOTEDID QUOTEDLITERAL NUMERIC STRINGLITERAL LPAREN -// PLUS MINUS TILDE SELECT -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_14(_tokenSet_14_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_15_data_[] = { 133120UL, 2138250UL, 0UL, 0UL }; -// "BETWEEN" "COLLATE" "GLOB" "LIKE" "IN" "NOT" "MATCH" "REGEXP" -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_15(_tokenSet_15_data_,4); -const unsigned long Sqlite3Parser::_tokenSet_16_data_[] = { 4294410224UL, 3220958718UL, 93091841UL, 0UL, 0UL, 0UL, 0UL, 0UL }; -// "ABORT" "ACTION" "AUTOINCREMENT" "AS" "ASC" "AND" "OR" "BETWEEN" "CASCADE" -// "CASE" "CAST" "CREATE" "COLLATE" "CONFLICT" "CURRENT_TIME" "CURRENT_DATE" -// "CURRENT_TIMESTAMP" "DEFAULT" "DEFERRABLE" "DEFERRED" "DELETE" "DESC" -// "ELSE" "END" "ESCAPE" "FAIL" "GLOB" "KEY" "LIKE" "TABLE" "IF" "IGNORE" -// "IN" "INITIALLY" "IMMEDIATE" "IS" "NOT" "NULL" "MATCH" "EXISTS" "ON" -// "RAISE" "REFERENCES" "REGEXP" "REPLACE" "RESTRICT" "ROLLBACK" "ROWID" -// "SET" "TEMPORARY" "TEMP" "THEN" "UPDATE" "WHEN" ID QUOTEDID QUOTEDLITERAL -// NUMERIC STRINGLITERAL LPAREN PLUS MINUS TILDE -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_16(_tokenSet_16_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_17_data_[] = { 1879049858UL, 539002890UL, 4222615553UL, 1791UL, 0UL, 0UL, 0UL, 0UL }; -// EOF "AS" "AND" "OR" "ELSE" "END" "ESCAPE" "GLOB" "LIKE" "IS" "MATCH" -// "REGEXP" "THEN" "WHEN" RPAREN COMMA PLUS MINUS STAR AMPERSAND BITOR -// OROP EQUAL EQUAL2 GREATER GREATEREQUAL LOWER LOWEREQUAL UNEQUAL UNEQUAL2 -// BITWISELEFT BITWISERIGHT SLASH PERCENT -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_17(_tokenSet_17_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_18_data_[] = { 4294967282UL, 4294962687UL, 4290541569UL, 1791UL, 0UL, 0UL, 0UL, 0UL }; -// EOF "ABORT" "ACTION" "AUTOINCREMENT" "AS" "ASC" "AND" "OR" "BETWEEN" -// "CASCADE" "CASE" "CAST" "CHECK" "CREATE" "COLLATE" "CONFLICT" "CONSTRAINT" -// "CURRENT_TIME" "CURRENT_DATE" "CURRENT_TIMESTAMP" "DEFAULT" "DEFERRABLE" -// "DEFERRED" "DELETE" "DESC" "ELSE" "END" "ESCAPE" "FAIL" "FOREIGN" "GLOB" -// "KEY" "LIKE" "TABLE" "IF" "IGNORE" "IN" "INITIALLY" "IMMEDIATE" "IS" -// "NOT" "NULL" "MATCH" "EXISTS" "ON" "PRIMARY" "RAISE" "REFERENCES" "REGEXP" -// "REPLACE" "RESTRICT" "ROLLBACK" "ROWID" "SET" "TEMPORARY" "TEMP" "THEN" -// "UNIQUE" "UPDATE" "WHEN" ID QUOTEDID QUOTEDLITERAL NUMERIC STRINGLITERAL -// LPAREN RPAREN COMMA PLUS MINUS STAR TILDE AMPERSAND BITOR OROP EQUAL -// EQUAL2 GREATER GREATEREQUAL LOWER LOWEREQUAL UNEQUAL UNEQUAL2 BITWISELEFT -// BITWISERIGHT SLASH PERCENT -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_18(_tokenSet_18_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_19_data_[] = { 4294410224UL, 3220958718UL, 4287396865UL, 2047UL, 0UL, 0UL, 0UL, 0UL }; -// "ABORT" "ACTION" "AUTOINCREMENT" "AS" "ASC" "AND" "OR" "BETWEEN" "CASCADE" -// "CASE" "CAST" "CREATE" "COLLATE" "CONFLICT" "CURRENT_TIME" "CURRENT_DATE" -// "CURRENT_TIMESTAMP" "DEFAULT" "DEFERRABLE" "DEFERRED" "DELETE" "DESC" -// "ELSE" "END" "ESCAPE" "FAIL" "GLOB" "KEY" "LIKE" "TABLE" "IF" "IGNORE" -// "IN" "INITIALLY" "IMMEDIATE" "IS" "NOT" "NULL" "MATCH" "EXISTS" "ON" -// "RAISE" "REFERENCES" "REGEXP" "REPLACE" "RESTRICT" "ROLLBACK" "ROWID" -// "SET" "TEMPORARY" "TEMP" "THEN" "UPDATE" "WHEN" DOT ID QUOTEDID QUOTEDLITERAL -// NUMERIC STRINGLITERAL LPAREN PLUS MINUS STAR TILDE AMPERSAND BITOR OROP -// EQUAL EQUAL2 GREATER GREATEREQUAL LOWER LOWEREQUAL UNEQUAL UNEQUAL2 -// BITWISELEFT BITWISERIGHT SELECT SLASH PERCENT -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_19(_tokenSet_19_data_,8); -const unsigned long Sqlite3Parser::_tokenSet_20_data_[] = { 1024UL, 2131978UL, 4219469824UL, 1791UL, 0UL, 0UL, 0UL, 0UL }; -// "OR" "GLOB" "LIKE" "IS" "MATCH" "REGEXP" PLUS MINUS STAR AMPERSAND BITOR -// OROP EQUAL EQUAL2 GREATER GREATEREQUAL LOWER LOWEREQUAL UNEQUAL UNEQUAL2 -// BITWISELEFT BITWISERIGHT SLASH PERCENT -const ANTLR_USE_NAMESPACE(antlr)BitSet Sqlite3Parser::_tokenSet_20(_tokenSet_20_data_,8); - - diff --git a/src/grammar/Sqlite3Parser.hpp b/src/grammar/Sqlite3Parser.hpp deleted file mode 100644 index f7522c98a..000000000 --- a/src/grammar/Sqlite3Parser.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef INC_Sqlite3Parser_hpp_ -#define INC_Sqlite3Parser_hpp_ - -#include -/* $ANTLR 2.7.7 (20141010): "sqlite3.g" -> "Sqlite3Parser.hpp"$ */ -#include -#include -#include "sqlite3TokenTypes.hpp" -#include - -class CUSTOM_API Sqlite3Parser : public ANTLR_USE_NAMESPACE(antlr)LLkParser, public sqlite3TokenTypes -{ -public: - void initializeASTFactory( ANTLR_USE_NAMESPACE(antlr)ASTFactory& factory ); -protected: - Sqlite3Parser(ANTLR_USE_NAMESPACE(antlr)TokenBuffer& tokenBuf, int k); -public: - Sqlite3Parser(ANTLR_USE_NAMESPACE(antlr)TokenBuffer& tokenBuf); -protected: - Sqlite3Parser(ANTLR_USE_NAMESPACE(antlr)TokenStream& lexer, int k); -public: - Sqlite3Parser(ANTLR_USE_NAMESPACE(antlr)TokenStream& lexer); - Sqlite3Parser(const ANTLR_USE_NAMESPACE(antlr)ParserSharedInputState& state); - int getNumTokens() const - { - return Sqlite3Parser::NUM_TOKENS; - } - const char* getTokenName( int type ) const - { - if( type > getNumTokens() ) return 0; - return Sqlite3Parser::tokenNames[type]; - } - const char* const* getTokenNames() const - { - return Sqlite3Parser::tokenNames; - } - public: void id(); - public: void databasename(); - public: void tablename(); - public: void nonkeyword_columnname(); - public: void identifier(); - public: void collationname(); - public: void signednumber(); - public: void statementlist(); - public: void statement(); - public: void createtable(); - public: void create_statements(); - public: void keywordastablename(); - public: void columndef(); - public: void tableconstraint(); - public: void selectstmt(); - public: void keywordascolumnname(); - public: void columnname(); - public: void type_name(); - public: void columnconstraint(); - public: void name(); - public: void conflictclause(); - public: void expr(); - public: void literalvalue(); - public: void foreignkeyclause(); - public: void indexedcolumn(); - public: void functionname(); - public: void subexpr(); - public: void binaryoperator(); - public: void castexpr(); - public: void caseexpr(); - public: void raisefunction(); - public: void suffixexpr(); - public: void like_operator(); - public: void between_subexpr(); -public: - ANTLR_USE_NAMESPACE(antlr)RefAST getAST() - { - return returnAST; - } - -protected: - ANTLR_USE_NAMESPACE(antlr)RefAST returnAST; -private: - static const char* tokenNames[]; -#ifndef NO_STATIC_CONSTS - static const int NUM_TOKENS = 107; -#else - enum { - NUM_TOKENS = 107 - }; -#endif - - static const unsigned long _tokenSet_0_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_0; - static const unsigned long _tokenSet_1_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_1; - static const unsigned long _tokenSet_2_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_2; - static const unsigned long _tokenSet_3_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_3; - static const unsigned long _tokenSet_4_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_4; - static const unsigned long _tokenSet_5_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_5; - static const unsigned long _tokenSet_6_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_6; - static const unsigned long _tokenSet_7_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_7; - static const unsigned long _tokenSet_8_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_8; - static const unsigned long _tokenSet_9_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_9; - static const unsigned long _tokenSet_10_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_10; - static const unsigned long _tokenSet_11_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_11; - static const unsigned long _tokenSet_12_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_12; - static const unsigned long _tokenSet_13_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_13; - static const unsigned long _tokenSet_14_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_14; - static const unsigned long _tokenSet_15_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_15; - static const unsigned long _tokenSet_16_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_16; - static const unsigned long _tokenSet_17_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_17; - static const unsigned long _tokenSet_18_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_18; - static const unsigned long _tokenSet_19_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_19; - static const unsigned long _tokenSet_20_data_[]; - static const ANTLR_USE_NAMESPACE(antlr)BitSet _tokenSet_20; -}; - -#endif /*INC_Sqlite3Parser_hpp_*/ diff --git a/src/grammar/sqlite3.g b/src/grammar/sqlite3.g deleted file mode 100644 index 8f27c86ec..000000000 --- a/src/grammar/sqlite3.g +++ /dev/null @@ -1,486 +0,0 @@ -options { - language="Cpp"; - genHashLines=false; -} - -class Sqlite3Lexer extends Lexer; -options { - k=2; - exportVocab=sqlite3; - caseSensitive=false; - caseSensitiveLiterals=false; - charVocabulary='\u0000'..'\uFFFE'; -} - -tokens { - ABORT="ABORT"; - ACTION="ACTION"; - AUTOINCREMENT="AUTOINCREMENT"; - AS="AS"; - ASC="ASC"; - AND="AND"; - OR="OR"; - BETWEEN="BETWEEN"; - CASCADE="CASCADE"; - CASE_T="CASE"; - CAST="CAST"; - CHECK="CHECK"; - CREATE="CREATE"; - COLLATE="COLLATE"; - CONFLICT="CONFLICT"; - CONSTRAINT="CONSTRAINT"; - CURRENT_TIME="CURRENT_TIME"; - CURRENT_DATE="CURRENT_DATE"; - CURRENT_TIMESTAMP="CURRENT_TIMESTAMP"; - DEFAULT="DEFAULT"; - DEFERRABLE="DEFERRABLE"; - DEFERRED="DEFERRED"; - DELETE="DELETE"; - DESC="DESC"; - ELSE_T="ELSE"; - END="END"; - ESCAPE="ESCAPE"; - FAIL="FAIL"; - FOREIGN="FOREIGN"; - GLOB="GLOB"; - KEY="KEY"; - LIKE="LIKE"; - TABLE="TABLE"; - IF_T="IF"; - IGNORE="IGNORE"; - IN="IN"; - INITIALLY="INITIALLY"; - INSERT="INSERT"; - IMMEDIATE="IMMEDIATE"; - IS="IS"; - NO="NO"; - NOT="NOT"; - NULL_T="NULL"; - MATCH="MATCH"; - EXISTS="EXISTS"; - ON="ON"; - PRIMARY="PRIMARY"; - RAISE="RAISE"; - REFERENCES="REFERENCES"; - REGEXP="REGEXP"; - REPLACE="REPLACE"; - RESTRICT="RESTRICT"; - ROLLBACK="ROLLBACK"; - ROWID="ROWID"; - SET="SET"; - TEMPORARY="TEMPORARY"; - TEMP="TEMP"; - THEN="THEN"; - UNIQUE="UNIQUE"; - UPDATE="UPDATE"; - WHEN="WHEN"; - WITHOUT="WITHOUT"; - -//ast - - TYPE_NAME; - COLUMNDEF; - COLUMNCONSTRAINT; - TABLECONSTRAINT; - CREATETABLE; - KEYWORDASTABLENAME; - KEYWORDASCOLUMNNAME; -} - -protected -DIGIT : '0'..'9' ; - -protected DOT:; - -ID - : - // 00C0 - 02B8 load of good looking unicode chars - // there might be more allowed characters - ('a'..'z'|'_') ('a'..'z'|'0'..'9'|'_'|'\u0080'..'\u02B8')* - ; - -QUOTEDID - : '`' ( ~('`') | ('`' '`') )* '`' - | '[' ( ~(']') )* ']' - ; - -QUOTEDLITERAL - : '"' ( ~'"' | ('"' '"' ) )* '"' - ; - -NUMERIC - : ( (DIGIT)+ ( '.' (DIGIT)* )? - | '.' { _ttype=DOT; } (DIGIT)+) - ( 'e' (PLUS|MINUS)? (DIGIT)+ )? - ; - -protected -NL : - ( '\r' - | '\n' {newline();} - ); - -COMMENT : - ( '-''-' (~('\n'|'\r'))* NL {newline();} // single line comment - | '/''*' ( options{greedy=false;} : NL {newline();} | ~('\n'|'\r') )* '*''/' // multi-line comment - ) { $setType(ANTLR_USE_NAMESPACE(antlr)Token::SKIP); }; - -WS : - ( ' ' - | '\t' - | '\f' - | NL - ) { $setType(ANTLR_USE_NAMESPACE(antlr)Token::SKIP); }; - -STRINGLITERAL - : -// '"' ( ESC_SEQ | ~('\\'|'"') )* '"' - '\'' ( ~'\'' | ('\'' '\'') )* '\'' - ; - -//protected -//ESC_SEQ -// : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\') -// ; - -LPAREN : '('; -RPAREN : ')'; -COMMA : ','; -SEMI : ';'; -PLUS : '+'; -MINUS : '-'; -STAR : '*'; -TILDE : '~'; -AMPERSAND: '&'; -BITOR: '|'; -OROP: BITOR BITOR; -EQUAL: '='; -EQUAL2: EQUAL EQUAL; -GREATER: '>'; -GREATEREQUAL: GREATER EQUAL; -LOWER: '<'; -LOWEREQUAL: LOWER EQUAL; -UNEQUAL: '!' EQUAL; -UNEQUAL2: LOWER GREATER; -BITWISELEFT: LOWER LOWER; -BITWISERIGHT: GREATER GREATER; - -// parser - -class Sqlite3Parser extends Parser; -options { - k=2; - buildAST = true; - defaultErrorHandler=false; -} - -id : ID | QUOTEDID | QUOTEDLITERAL | STRINGLITERAL ; - -databasename - : - id - ; - -tablename - : - id - ; - -nonkeyword_columnname - : - id - ; - -identifier - : - ((databasename)? DOT)? tablename - ; - -collationname - : - ID - ; - -signednumber - : (PLUS | MINUS)? NUMERIC -// {#signednumber = #([SIGNEDNUMBER, "SIGNEDNUMBER"], #signednumber);} - ; - -// parser part -statementlist - : - (statement)? - (SEMI statement)* - ; - -statement - : - createtable - ; - -create_statements - : - createtable - ; - -keywordastablename - : - ( ABORT - | ACTION - | ASC - | CASCADE - | CAST - | CONFLICT - | CURRENT_TIME - | CURRENT_DATE - | CURRENT_TIMESTAMP - | DEFERRED - | DESC - | END - | FAIL - | GLOB - | KEY - | LIKE - | IGNORE - | INITIALLY - | IMMEDIATE - | MATCH - | RAISE - | REGEXP - | REPLACE - | RESTRICT - | ROLLBACK - | TEMPORARY - | TEMP - ) - {#keywordastablename = #([KEYWORDASTABLENAME, "KEYWORDASTABLENAME"], #keywordastablename);} - ; - -createtable - : - CREATE (TEMP|TEMPORARY)? TABLE (IF_T NOT EXISTS)? (tablename | keywordastablename) - ( LPAREN columndef (COMMA columndef)* ((COMMA)? tableconstraint)* RPAREN (WITHOUT ROWID)? - | AS selectstmt - ) - {#createtable = #([CREATETABLE, "CREATETABLE"], #createtable);} - ; - -keywordascolumnname - : - ( ABORT - | ACTION - | AUTOINCREMENT - | AS - | ASC - | AND - | OR - | CASCADE - | CASE_T - | CAST - | CREATE - | COLLATE - | CONFLICT - | CURRENT_TIME - | CURRENT_DATE - | CURRENT_TIMESTAMP - | DEFAULT - | DEFERRABLE - | DEFERRED - | DELETE - | DESC - | ELSE_T - | END - | ESCAPE - | FAIL - | GLOB - | KEY - | LIKE - | TABLE - | IF_T - | IGNORE - | INITIALLY - | IMMEDIATE - | IS - | NULL_T - | MATCH - | EXISTS - | ON - | RAISE - | REFERENCES - | REGEXP - | REPLACE - | RESTRICT - | ROLLBACK - | ROWID - | SET - | TEMPORARY - | TEMP - | THEN - | UPDATE - | WHEN - ) - {#keywordascolumnname = #([KEYWORDASCOLUMNNAME, "KEYWORDASCOLUMNNAME"], #keywordascolumnname);} - ; - -columnname - : - ( nonkeyword_columnname - | keywordascolumnname - ) - {} - ; - -columndef - : - columnname (type_name)? (columnconstraint)* - {#columndef = #([COLUMNDEF, "COLUMNDEF"], #columndef);} - ; - -name : ID | QUOTEDID | QUOTEDLITERAL | STRINGLITERAL; - -type_name - : - (name)+ - (LPAREN signednumber (COMMA signednumber)? RPAREN)? - {#type_name = #([TYPE_NAME, "TYPE_NAME"], #type_name);} - ; - -columnconstraint - : - (CONSTRAINT name)? - ( PRIMARY KEY (ASC|DESC)? (conflictclause)? (AUTOINCREMENT)? - | (NOT)? NULL_T (conflictclause)? - | UNIQUE (conflictclause)? - | CHECK LPAREN expr RPAREN - | DEFAULT (signednumber | QUOTEDLITERAL | STRINGLITERAL | LPAREN expr RPAREN | literalvalue | ID) - | COLLATE collationname - | foreignkeyclause) - {#columnconstraint = #([COLUMNCONSTRAINT, "COLUMNCONSTRAINT"], #columnconstraint);} - ; - -tableconstraint - : - (CONSTRAINT name)? - ( PRIMARY KEY LPAREN indexedcolumn (COMMA indexedcolumn)* RPAREN (conflictclause)? - | UNIQUE LPAREN indexedcolumn (COMMA indexedcolumn)* RPAREN (conflictclause)? - | CHECK LPAREN expr RPAREN - | FOREIGN KEY LPAREN columnname (COMMA columnname)* RPAREN foreignkeyclause - ) - {#tableconstraint = #([TABLECONSTRAINT, "TABLECONSTRAINT"], #tableconstraint);} - ; - -indexedcolumn - : - columnname (COLLATE collationname)? (ASC|DESC)? (AUTOINCREMENT)? - ; - -conflictclause - : - ON CONFLICT - ( ROLLBACK - | ABORT - | FAIL - | IGNORE - | REPLACE - ) - ; - -foreignkeyclause - : - REFERENCES tablename (LPAREN columnname (COMMA columnname)* RPAREN)? - ( ON (DELETE | UPDATE | INSERT) - ( SET (NULL_T | DEFAULT) - | CASCADE - | RESTRICT - | NO ACTION - ) - | MATCH name - )* - ( (NOT DEFERRABLE) => NOT DEFERRABLE (INITIALLY (DEFERRED | IMMEDIATE))? - | DEFERRABLE (INITIALLY (DEFERRED | IMMEDIATE) ) )? - ; - -selectstmt - : SELECT - ; - -functionname - : id ; - -expr - : - subexpr ((binaryoperator | AND | OR) subexpr )* - ; - -subexpr - : - ( MINUS | PLUS | TILDE | NOT)? - ( literalvalue -// | bindparameter TODO - | ((databasename DOT)? tablename DOT)? columnname - | functionname LPAREN (expr (COMMA expr)* )? RPAREN //TODO - | castexpr - | (EXISTS)? LPAREN (expr | selectstmt) RPAREN - | caseexpr - | raisefunction - ) - (suffixexpr)? - ; - -castexpr - : - CAST LPAREN expr AS type_name RPAREN - ; - -caseexpr - : - CASE_T (expr)? (WHEN expr THEN expr)+ (ELSE_T expr)? END - ; - -like_operator - : - LIKE - | GLOB - | REGEXP - | MATCH - ; - -between_subexpr - : - subexpr (AND subexpr)+ - ; - -suffixexpr - : - COLLATE collationname - | (NOT)? - ( BETWEEN subexpr ((binaryoperator | OR) subexpr )* AND expr - | IN ( LPAREN (selectstmt | expr (COMMA expr)* )? RPAREN | tablename) - | like_operator subexpr (ESCAPE subexpr)? - ) - ; - -literalvalue - : - NUMERIC - | STRINGLITERAL -// | blob-literal - | NULL_T - | CURRENT_TIME - | CURRENT_DATE - | CURRENT_TIMESTAMP - ; - -raisefunction - : RAISE LPAREN ( IGNORE | (ROLLBACK | ABORT | FAIL) COMMA STRINGLITERAL ) RPAREN ; - -binaryoperator - : - OROP - | STAR | SLASH | PERCENT - | PLUS | MINUS - | BITWISELEFT | BITWISERIGHT | AMPERSAND | BITOR - | LOWER | LOWEREQUAL | GREATER | GREATEREQUAL - | EQUAL | EQUAL2 | UNEQUAL | UNEQUAL2 - | IS | like_operator - ; diff --git a/src/grammar/sqlite3TokenTypes.hpp b/src/grammar/sqlite3TokenTypes.hpp deleted file mode 100644 index 88bc25733..000000000 --- a/src/grammar/sqlite3TokenTypes.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef INC_sqlite3TokenTypes_hpp_ -#define INC_sqlite3TokenTypes_hpp_ - -/* $ANTLR 2.7.7 (20141010): "sqlite3.g" -> "sqlite3TokenTypes.hpp"$ */ - -#ifndef CUSTOM_API -# define CUSTOM_API -#endif - -#ifdef __cplusplus -struct CUSTOM_API sqlite3TokenTypes { -#endif - enum { - EOF_ = 1, - ABORT = 4, - ACTION = 5, - AUTOINCREMENT = 6, - AS = 7, - ASC = 8, - AND = 9, - OR = 10, - BETWEEN = 11, - CASCADE = 12, - CASE_T = 13, - CAST = 14, - CHECK = 15, - CREATE = 16, - COLLATE = 17, - CONFLICT = 18, - CONSTRAINT = 19, - CURRENT_TIME = 20, - CURRENT_DATE = 21, - CURRENT_TIMESTAMP = 22, - DEFAULT = 23, - DEFERRABLE = 24, - DEFERRED = 25, - DELETE = 26, - DESC = 27, - ELSE_T = 28, - END = 29, - ESCAPE = 30, - FAIL = 31, - FOREIGN = 32, - GLOB = 33, - KEY = 34, - LIKE = 35, - TABLE = 36, - IF_T = 37, - IGNORE = 38, - IN = 39, - INITIALLY = 40, - INSERT = 41, - IMMEDIATE = 42, - IS = 43, - NO = 44, - NOT = 45, - NULL_T = 46, - MATCH = 47, - EXISTS = 48, - ON = 49, - PRIMARY = 50, - RAISE = 51, - REFERENCES = 52, - REGEXP = 53, - REPLACE = 54, - RESTRICT = 55, - ROLLBACK = 56, - ROWID = 57, - SET = 58, - TEMPORARY = 59, - TEMP = 60, - THEN = 61, - UNIQUE = 62, - UPDATE = 63, - WHEN = 64, - WITHOUT = 65, - TYPE_NAME = 66, - COLUMNDEF = 67, - COLUMNCONSTRAINT = 68, - TABLECONSTRAINT = 69, - CREATETABLE = 70, - KEYWORDASTABLENAME = 71, - KEYWORDASCOLUMNNAME = 72, - DIGIT = 73, - DOT = 74, - ID = 75, - QUOTEDID = 76, - QUOTEDLITERAL = 77, - NUMERIC = 78, - NL = 79, - COMMENT = 80, - WS = 81, - STRINGLITERAL = 82, - LPAREN = 83, - RPAREN = 84, - COMMA = 85, - SEMI = 86, - PLUS = 87, - MINUS = 88, - STAR = 89, - TILDE = 90, - AMPERSAND = 91, - BITOR = 92, - OROP = 93, - EQUAL = 94, - EQUAL2 = 95, - GREATER = 96, - GREATEREQUAL = 97, - LOWER = 98, - LOWEREQUAL = 99, - UNEQUAL = 100, - UNEQUAL2 = 101, - BITWISELEFT = 102, - BITWISERIGHT = 103, - SELECT = 104, - SLASH = 105, - PERCENT = 106, - NULL_TREE_LOOKAHEAD = 3 - }; -#ifdef __cplusplus -}; -#endif -#endif /*INC_sqlite3TokenTypes_hpp_*/ diff --git a/src/i18n.pri b/src/i18n.pri deleted file mode 100644 index 5f201e5fb..000000000 --- a/src/i18n.pri +++ /dev/null @@ -1,48 +0,0 @@ -# This file is taken from the project https://gitorious.org/qop/qop/. -# For autocompiling qm-files. - -#rules to generate ts -isEmpty(QMAKE_LUPDATE) { - win32: QMAKE_LUPDATE = $$[QT_INSTALL_BINS]/lupdate.exe - unix { - QMAKE_LUPDATE = $$[QT_INSTALL_BINS]/lupdate - !exists($$QMAKE_LUPDATE) { QMAKE_LUPDATE = lupdate-qt4 } - } else { - !exists($$QMAKE_LUPDATE) { QMAKE_LUPDATE = lupdate } - } -} -#limitation: only on ts can be generated -updatets.name = Creating or updating ts-files... -updatets.input = _PRO_FILE_ -updatets.output = $$TRANSLATIONS -updatets.commands = $$QMAKE_LUPDATE ${QMAKE_FILE_IN} -updatets.CONFIG += no_link no_clean -QMAKE_EXTRA_COMPILERS += updatets - -#rules for ts->qm -isEmpty(QMAKE_LRELEASE) { -#a qm generated by lrelease-qt3 can be used for qt2, qt3, qt4! - win32: QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease.exe - unix { - QMAKE_LRELEASE = lrelease-qt3 - !exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease } - !exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease } - !exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease-qt4 } - } else { - !exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease } - } -} -updatets.name = Compiling qm-files... -updateqm.input = TRANSLATIONS -updateqm.output = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.qm -updateqm.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} -qm ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.qm -updateqm.CONFIG += no_link no_clean target_predeps -updateqm.variable_out = copytranslations.files -QMAKE_EXTRA_COMPILERS += updateqm - -# Copy translations into the bundle when one is created -mac:contains(CONFIG, "app_bundle") { - copytranslations.path = Contents/MacOS/translations - copytranslations.depends = updateqm - QMAKE_BUNDLE_DATA += copytranslations -} diff --git a/src/icons/application_go.svg b/src/icons/application_go.svg new file mode 100644 index 000000000..3ef61c6ac --- /dev/null +++ b/src/icons/application_go.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/application_link.svg b/src/icons/application_link.svg new file mode 100644 index 000000000..238c5ce31 --- /dev/null +++ b/src/icons/application_link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/application_side_list.svg b/src/icons/application_side_list.svg new file mode 100644 index 000000000..cb12b33b5 --- /dev/null +++ b/src/icons/application_side_list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/arrow_refresh_small.svg b/src/icons/arrow_refresh_small.svg new file mode 100644 index 000000000..96d0e8ed1 --- /dev/null +++ b/src/icons/arrow_refresh_small.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/bullet_arrow_bottom.svg b/src/icons/bullet_arrow_bottom.svg new file mode 100644 index 000000000..a66320c42 --- /dev/null +++ b/src/icons/bullet_arrow_bottom.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/bullet_arrow_down.png b/src/icons/bullet_arrow_down.png deleted file mode 100644 index 9b23c06d7..000000000 Binary files a/src/icons/bullet_arrow_down.png and /dev/null differ diff --git a/src/icons/bullet_arrow_down.svg b/src/icons/bullet_arrow_down.svg new file mode 100644 index 000000000..dbf419eea --- /dev/null +++ b/src/icons/bullet_arrow_down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/bullet_arrow_top.svg b/src/icons/bullet_arrow_top.svg new file mode 100644 index 000000000..8f920e083 --- /dev/null +++ b/src/icons/bullet_arrow_top.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/bullet_arrow_up.png b/src/icons/bullet_arrow_up.png deleted file mode 100644 index 24df0f421..000000000 Binary files a/src/icons/bullet_arrow_up.png and /dev/null differ diff --git a/src/icons/bullet_arrow_up.svg b/src/icons/bullet_arrow_up.svg new file mode 100644 index 000000000..554e0742a --- /dev/null +++ b/src/icons/bullet_arrow_up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/cancel.svg b/src/icons/cancel.svg new file mode 100644 index 000000000..9647fab8d --- /dev/null +++ b/src/icons/cancel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/chart_curve.png b/src/icons/chart_curve.png deleted file mode 100644 index 01e933a61..000000000 Binary files a/src/icons/chart_curve.png and /dev/null differ diff --git a/src/icons/chart_curve.svg b/src/icons/chart_curve.svg new file mode 100644 index 000000000..ebd50f656 --- /dev/null +++ b/src/icons/chart_curve.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/clear_filters.png b/src/icons/clear_filters.png deleted file mode 100644 index 39593e409..000000000 Binary files a/src/icons/clear_filters.png and /dev/null differ diff --git a/src/icons/clear_sorting.svg b/src/icons/clear_sorting.svg new file mode 100644 index 000000000..161052c2a --- /dev/null +++ b/src/icons/clear_sorting.svg @@ -0,0 +1,297 @@ + + + + + + image/svg+xml + + Arrow Up + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Arrow Up + Arrow Up Top + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/icons/cog.png b/src/icons/cog.png deleted file mode 100644 index 67de2c6cc..000000000 Binary files a/src/icons/cog.png and /dev/null differ diff --git a/src/icons/cog.svg b/src/icons/cog.svg new file mode 100644 index 000000000..ea843f8ec --- /dev/null +++ b/src/icons/cog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/cog_go.svg b/src/icons/cog_go.svg new file mode 100644 index 000000000..3053112c1 --- /dev/null +++ b/src/icons/cog_go.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/color_swatch.svg b/src/icons/color_swatch.svg new file mode 100644 index 000000000..124ec3ee6 --- /dev/null +++ b/src/icons/color_swatch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/color_wheel.svg b/src/icons/color_wheel.svg new file mode 100644 index 000000000..67e621775 --- /dev/null +++ b/src/icons/color_wheel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/cross.svg b/src/icons/cross.svg new file mode 100644 index 000000000..9a0d2ff14 --- /dev/null +++ b/src/icons/cross.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/database.svg b/src/icons/database.svg new file mode 100644 index 000000000..25dcd7176 --- /dev/null +++ b/src/icons/database.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/database_add.png b/src/icons/database_add.png deleted file mode 100755 index 802bd6cde..000000000 Binary files a/src/icons/database_add.png and /dev/null differ diff --git a/src/icons/database_add.svg b/src/icons/database_add.svg new file mode 100644 index 000000000..1ad18926d --- /dev/null +++ b/src/icons/database_add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/database_go.png b/src/icons/database_go.png deleted file mode 100755 index 61a8556c4..000000000 Binary files a/src/icons/database_go.png and /dev/null differ diff --git a/src/icons/database_go.svg b/src/icons/database_go.svg new file mode 100644 index 000000000..15b6451b2 --- /dev/null +++ b/src/icons/database_go.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/database_link.svg b/src/icons/database_link.svg new file mode 100644 index 000000000..f48b0464b --- /dev/null +++ b/src/icons/database_link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/database_refresh.png b/src/icons/database_refresh.png deleted file mode 100755 index ff803be12..000000000 Binary files a/src/icons/database_refresh.png and /dev/null differ diff --git a/src/icons/database_refresh.svg b/src/icons/database_refresh.svg new file mode 100644 index 000000000..ada718914 --- /dev/null +++ b/src/icons/database_refresh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/database_save.png b/src/icons/database_save.png deleted file mode 100755 index 44c06dddf..000000000 Binary files a/src/icons/database_save.png and /dev/null differ diff --git a/src/icons/database_save.svg b/src/icons/database_save.svg new file mode 100644 index 000000000..ee26191ed --- /dev/null +++ b/src/icons/database_save.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/document-open.png b/src/icons/document-open.png deleted file mode 100755 index ab940462f..000000000 Binary files a/src/icons/document-open.png and /dev/null differ diff --git a/src/icons/edit_cut.svg b/src/icons/edit_cut.svg new file mode 100644 index 000000000..3abc76739 --- /dev/null +++ b/src/icons/edit_cut.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/icons/find_edit.svg b/src/icons/find_edit.svg new file mode 100644 index 000000000..17db094c0 --- /dev/null +++ b/src/icons/find_edit.svg @@ -0,0 +1,478 @@ + + + + + + image/svg+xml + + Find Edit + + + + + Find Edit + Find Edit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/icons/folder.svg b/src/icons/folder.svg new file mode 100644 index 000000000..9c2ce8ac6 --- /dev/null +++ b/src/icons/folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/folder_page.svg b/src/icons/folder_page.svg new file mode 100644 index 000000000..fc87c537d --- /dev/null +++ b/src/icons/folder_page.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/folder_user.svg b/src/icons/folder_user.svg new file mode 100644 index 000000000..7bcfe0f6f --- /dev/null +++ b/src/icons/folder_user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/font.svg b/src/icons/font.svg new file mode 100644 index 000000000..c149d1e22 --- /dev/null +++ b/src/icons/font.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/font_add.svg b/src/icons/font_add.svg new file mode 100644 index 000000000..f1e98cc5e --- /dev/null +++ b/src/icons/font_add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/font_delete.svg b/src/icons/font_delete.svg new file mode 100644 index 000000000..d389e6257 --- /dev/null +++ b/src/icons/font_delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/font_edit.svg b/src/icons/font_edit.svg new file mode 100644 index 000000000..0a187ea60 --- /dev/null +++ b/src/icons/font_edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/funnel.svg b/src/icons/funnel.svg new file mode 100644 index 000000000..7f77114b4 --- /dev/null +++ b/src/icons/funnel.svg @@ -0,0 +1,32 @@ + + + + Funnel + Funnel + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/icons/funnel_delete.svg b/src/icons/funnel_delete.svg new file mode 100644 index 000000000..ae28e4e39 --- /dev/null +++ b/src/icons/funnel_delete.svg @@ -0,0 +1,49 @@ + + + + Funnel Delete + Funnel Delete + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/icons/help.png b/src/icons/help.png deleted file mode 100644 index 5c870176d..000000000 Binary files a/src/icons/help.png and /dev/null differ diff --git a/src/icons/help.svg b/src/icons/help.svg new file mode 100644 index 000000000..5dc92b7c0 --- /dev/null +++ b/src/icons/help.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/hourglass.svg b/src/icons/hourglass.svg new file mode 100644 index 000000000..18c6ba96d --- /dev/null +++ b/src/icons/hourglass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/icons.qrc b/src/icons/icons.qrc index 5a051d989..222f6d38e 100644 --- a/src/icons/icons.qrc +++ b/src/icons/icons.qrc @@ -1,50 +1,110 @@ - database_add.png - database_go.png - database_refresh.png - database_save.png - table_add.png - table_delete.png - table_edit.png - tag_blue_add.png - tag_blue_delete.png - page_edit.png - page_delete.png - page_add.png - page_green.png - table.png - tag_blue.png - view-refresh.png - picture_delete.png - picture.png - picture_add.png - script.png - script_add.png - script_delete.png - wrench.png - help.png - tab_add.png - resultset_next.png - page_save.png - page_white_database.png - plugin_add.png - plugin_delete.png - table_save.png - resultset_last.png - layout_sidebar.png - bullet_arrow_down.png - bullet_arrow_up.png + application_go.svg + application_link.svg + application_side_list.svg + arrow_refresh_small.svg + bullet_arrow_bottom.svg + bullet_arrow_down.svg + bullet_arrow_top.svg + bullet_arrow_up.svg + cancel.svg + chart_curve.svg + funnel_delete.svg + clear_sorting.svg + cog.svg + cog_go.svg + color_swatch.svg + cross.svg + edit_cut.svg + database.svg + database_add.svg + database_go.svg + database_link.svg + database_refresh.svg + database_save.svg + database_save.svg + funnel.svg + folder.svg + folder_page.svg + folder_user.svg + font.svg + font_add.svg + font_delete.svg + font_edit.svg + help.svg + hourglass.svg + key.svg + layout_sidebar.svg + link_break.svg + monitor_link.svg + package.svg + package_go.svg + package_rename.svg + package_save.svg + page_add.svg + page_copy.svg + script_copy.svg + page_delete.svg + page_edit.svg + page_find.svg + page_green.svg + page_key.svg + world_link.svg + page_white_color.svg + page_paste.svg + page_save.svg + page_white_copy.svg + page_white_database.svg + page_white_text.svg + picture.svg + picture_add.svg + picture_delete.svg + picture_edit.svg + picture_save.svg + plugin_add.svg + plugin_delete.svg + printer.svg + resultset_first.svg + resultset_last.svg + resultset_next.svg + resultset_previous.svg + script.svg + script_add.svg + script_delete.svg + script_edit.svg + script_link.svg + server_add.svg + server_go.svg sqlitebrowser.png - internet-web-browser.png - package.png - package_go.png - page_key.png - key.png - document-open.png - chart_curve.png - cog.png - clear_filters.png - page_copy.png + tab.svg + tab_add.svg + table.svg + table_add.svg + table_delete.svg + table_edit.svg + table_key.svg + table_row_delete.svg + table_row_insert.svg + table_save.svg + tag_blue.svg + tag_blue_add.svg + tag_blue_delete.svg + tag_blue_edit.svg + text_align_center.svg + text_align_justify.svg + text_align_left.svg + text_align_right.svg + text_bold.svg + text_italic.svg + text_padding_left.svg + text_sort_ascending.svg + text_padding_top.svg + color_wheel.svg + find_edit.svg + text_underlined.svg + textfield_delete.svg + wrench.svg + undo.svg diff --git a/src/icons/internet-web-browser.png b/src/icons/internet-web-browser.png deleted file mode 100644 index ac5957ad6..000000000 Binary files a/src/icons/internet-web-browser.png and /dev/null differ diff --git a/src/icons/key.png b/src/icons/key.png deleted file mode 100644 index 4ec1a9281..000000000 Binary files a/src/icons/key.png and /dev/null differ diff --git a/src/icons/key.svg b/src/icons/key.svg new file mode 100644 index 000000000..96100c2d7 --- /dev/null +++ b/src/icons/key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/layout_sidebar.png b/src/icons/layout_sidebar.png deleted file mode 100644 index 3be27bb9b..000000000 Binary files a/src/icons/layout_sidebar.png and /dev/null differ diff --git a/src/icons/layout_sidebar.svg b/src/icons/layout_sidebar.svg new file mode 100644 index 000000000..936bb8def --- /dev/null +++ b/src/icons/layout_sidebar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/link_break.svg b/src/icons/link_break.svg new file mode 100644 index 000000000..a05a23ba5 --- /dev/null +++ b/src/icons/link_break.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/monitor_link.svg b/src/icons/monitor_link.svg new file mode 100644 index 000000000..70738ecc2 --- /dev/null +++ b/src/icons/monitor_link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/package.png b/src/icons/package.png deleted file mode 100644 index da3c2a2d7..000000000 Binary files a/src/icons/package.png and /dev/null differ diff --git a/src/icons/package.svg b/src/icons/package.svg new file mode 100644 index 000000000..cca19521e --- /dev/null +++ b/src/icons/package.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/package_go.png b/src/icons/package_go.png deleted file mode 100644 index aace63ad6..000000000 Binary files a/src/icons/package_go.png and /dev/null differ diff --git a/src/icons/package_go.svg b/src/icons/package_go.svg new file mode 100644 index 000000000..c68be1917 --- /dev/null +++ b/src/icons/package_go.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/package_rename.svg b/src/icons/package_rename.svg new file mode 100644 index 000000000..b9afe334f --- /dev/null +++ b/src/icons/package_rename.svg @@ -0,0 +1,357 @@ + + + + + + image/svg+xml + + Package + + + + + + + + + + + + + + + + + + Package + Package Software + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/icons/package_save.svg b/src/icons/package_save.svg new file mode 100644 index 000000000..9978fdaed --- /dev/null +++ b/src/icons/package_save.svg @@ -0,0 +1,603 @@ + + + + + + image/svg+xml + + Package + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Package + Package Software + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/icons/package_world.svg b/src/icons/package_world.svg new file mode 100644 index 000000000..e42fd3e37 --- /dev/null +++ b/src/icons/package_world.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/page_add.png b/src/icons/page_add.png deleted file mode 100755 index d5bfa0719..000000000 Binary files a/src/icons/page_add.png and /dev/null differ diff --git a/src/icons/page_add.svg b/src/icons/page_add.svg new file mode 100644 index 000000000..5074d0c64 --- /dev/null +++ b/src/icons/page_add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/page_copy.png b/src/icons/page_copy.png deleted file mode 100644 index 195dc6d6c..000000000 Binary files a/src/icons/page_copy.png and /dev/null differ diff --git a/src/icons/page_copy.svg b/src/icons/page_copy.svg new file mode 100644 index 000000000..c58143387 --- /dev/null +++ b/src/icons/page_copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/page_delete.png b/src/icons/page_delete.png deleted file mode 100755 index 3141467c6..000000000 Binary files a/src/icons/page_delete.png and /dev/null differ diff --git a/src/icons/page_delete.svg b/src/icons/page_delete.svg new file mode 100644 index 000000000..73900ae0c --- /dev/null +++ b/src/icons/page_delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/page_edit.png b/src/icons/page_edit.png deleted file mode 100755 index 046811ed7..000000000 Binary files a/src/icons/page_edit.png and /dev/null differ diff --git a/src/icons/page_edit.svg b/src/icons/page_edit.svg new file mode 100644 index 000000000..26c4b76f8 --- /dev/null +++ b/src/icons/page_edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/page_find.svg b/src/icons/page_find.svg new file mode 100644 index 000000000..b0eccb65c --- /dev/null +++ b/src/icons/page_find.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/page_green.png b/src/icons/page_green.png deleted file mode 100755 index de8e003f9..000000000 Binary files a/src/icons/page_green.png and /dev/null differ diff --git a/src/icons/page_green.svg b/src/icons/page_green.svg new file mode 100644 index 000000000..f56563b11 --- /dev/null +++ b/src/icons/page_green.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/page_key.png b/src/icons/page_key.png deleted file mode 100644 index d6626cb09..000000000 Binary files a/src/icons/page_key.png and /dev/null differ diff --git a/src/icons/page_key.svg b/src/icons/page_key.svg new file mode 100644 index 000000000..82ac955e1 --- /dev/null +++ b/src/icons/page_key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/page_link.svg b/src/icons/page_link.svg new file mode 100644 index 000000000..fc4eea23b --- /dev/null +++ b/src/icons/page_link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/page_paste.svg b/src/icons/page_paste.svg new file mode 100644 index 000000000..9d44b1b16 --- /dev/null +++ b/src/icons/page_paste.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/page_save.png b/src/icons/page_save.png deleted file mode 100644 index caea546af..000000000 Binary files a/src/icons/page_save.png and /dev/null differ diff --git a/src/icons/page_save.svg b/src/icons/page_save.svg new file mode 100644 index 000000000..42f7a12bf --- /dev/null +++ b/src/icons/page_save.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/page_white_color.svg b/src/icons/page_white_color.svg new file mode 100644 index 000000000..e0afd410b --- /dev/null +++ b/src/icons/page_white_color.svg @@ -0,0 +1,80 @@ + + + + White Page Color + White Page Color + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/icons/page_white_copy.svg b/src/icons/page_white_copy.svg new file mode 100644 index 000000000..f49900b06 --- /dev/null +++ b/src/icons/page_white_copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/page_white_database.png b/src/icons/page_white_database.png deleted file mode 100644 index bddba1f98..000000000 Binary files a/src/icons/page_white_database.png and /dev/null differ diff --git a/src/icons/page_white_database.svg b/src/icons/page_white_database.svg new file mode 100644 index 000000000..632cc2ad9 --- /dev/null +++ b/src/icons/page_white_database.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/page_white_text.svg b/src/icons/page_white_text.svg new file mode 100644 index 000000000..ca5950b3b --- /dev/null +++ b/src/icons/page_white_text.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/picture.png b/src/icons/picture.png deleted file mode 100644 index 4a158fef7..000000000 Binary files a/src/icons/picture.png and /dev/null differ diff --git a/src/icons/picture.svg b/src/icons/picture.svg new file mode 100644 index 000000000..608ab8412 --- /dev/null +++ b/src/icons/picture.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/picture_add.png b/src/icons/picture_add.png deleted file mode 100644 index d6d3f8564..000000000 Binary files a/src/icons/picture_add.png and /dev/null differ diff --git a/src/icons/picture_add.svg b/src/icons/picture_add.svg new file mode 100644 index 000000000..98c1c4cda --- /dev/null +++ b/src/icons/picture_add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/picture_delete.png b/src/icons/picture_delete.png deleted file mode 100644 index cca9f535d..000000000 Binary files a/src/icons/picture_delete.png and /dev/null differ diff --git a/src/icons/picture_delete.svg b/src/icons/picture_delete.svg new file mode 100644 index 000000000..f8a239fb8 --- /dev/null +++ b/src/icons/picture_delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/picture_edit.svg b/src/icons/picture_edit.svg new file mode 100644 index 000000000..c87ce242b --- /dev/null +++ b/src/icons/picture_edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/picture_save.svg b/src/icons/picture_save.svg new file mode 100644 index 000000000..af8f848e5 --- /dev/null +++ b/src/icons/picture_save.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/plugin_add.png b/src/icons/plugin_add.png deleted file mode 100644 index ae43690ec..000000000 Binary files a/src/icons/plugin_add.png and /dev/null differ diff --git a/src/icons/plugin_add.svg b/src/icons/plugin_add.svg new file mode 100644 index 000000000..b416e14ce --- /dev/null +++ b/src/icons/plugin_add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/plugin_delete.png b/src/icons/plugin_delete.png deleted file mode 100644 index d9c3376d4..000000000 Binary files a/src/icons/plugin_delete.png and /dev/null differ diff --git a/src/icons/plugin_delete.svg b/src/icons/plugin_delete.svg new file mode 100644 index 000000000..a2e2d8ac2 --- /dev/null +++ b/src/icons/plugin_delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/printer.svg b/src/icons/printer.svg new file mode 100644 index 000000000..56b5787b4 --- /dev/null +++ b/src/icons/printer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/resultset_first.svg b/src/icons/resultset_first.svg new file mode 100644 index 000000000..2aaef03de --- /dev/null +++ b/src/icons/resultset_first.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/resultset_last.png b/src/icons/resultset_last.png deleted file mode 100644 index 8ec894784..000000000 Binary files a/src/icons/resultset_last.png and /dev/null differ diff --git a/src/icons/resultset_last.svg b/src/icons/resultset_last.svg new file mode 100644 index 000000000..129e02a8a --- /dev/null +++ b/src/icons/resultset_last.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/resultset_next.png b/src/icons/resultset_next.png deleted file mode 100644 index e252606d3..000000000 Binary files a/src/icons/resultset_next.png and /dev/null differ diff --git a/src/icons/resultset_next.svg b/src/icons/resultset_next.svg new file mode 100644 index 000000000..901b7562d --- /dev/null +++ b/src/icons/resultset_next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/resultset_previous.svg b/src/icons/resultset_previous.svg new file mode 100644 index 000000000..f5be28d4b --- /dev/null +++ b/src/icons/resultset_previous.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/script.png b/src/icons/script.png deleted file mode 100644 index 0f9ed4d48..000000000 Binary files a/src/icons/script.png and /dev/null differ diff --git a/src/icons/script.svg b/src/icons/script.svg new file mode 100644 index 000000000..aaf5e38c0 --- /dev/null +++ b/src/icons/script.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/script_add.png b/src/icons/script_add.png deleted file mode 100644 index d650552d9..000000000 Binary files a/src/icons/script_add.png and /dev/null differ diff --git a/src/icons/script_add.svg b/src/icons/script_add.svg new file mode 100644 index 000000000..5e92d6d06 --- /dev/null +++ b/src/icons/script_add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/script_copy.svg b/src/icons/script_copy.svg new file mode 100644 index 000000000..a8438014e --- /dev/null +++ b/src/icons/script_copy.svg @@ -0,0 +1,180 @@ + + + + + + image/svg+xml + + Script + + + + + + + + + + + + + + + Script + Script + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/icons/script_delete.png b/src/icons/script_delete.png deleted file mode 100644 index e6500ced7..000000000 Binary files a/src/icons/script_delete.png and /dev/null differ diff --git a/src/icons/script_delete.svg b/src/icons/script_delete.svg new file mode 100644 index 000000000..2b8ac16cc --- /dev/null +++ b/src/icons/script_delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/script_edit.svg b/src/icons/script_edit.svg new file mode 100644 index 000000000..8f938a304 --- /dev/null +++ b/src/icons/script_edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/script_link.svg b/src/icons/script_link.svg new file mode 100644 index 000000000..ef3fb8541 --- /dev/null +++ b/src/icons/script_link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/server_add.svg b/src/icons/server_add.svg new file mode 100644 index 000000000..595fff31b --- /dev/null +++ b/src/icons/server_add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/server_go.svg b/src/icons/server_go.svg new file mode 100644 index 000000000..4609516a6 --- /dev/null +++ b/src/icons/server_go.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/sqlitebrowser.png b/src/icons/sqlitebrowser.png index 9dcc89bac..7897a11e5 100644 Binary files a/src/icons/sqlitebrowser.png and b/src/icons/sqlitebrowser.png differ diff --git a/src/icons/tab.svg b/src/icons/tab.svg new file mode 100644 index 000000000..dd926f92c --- /dev/null +++ b/src/icons/tab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/tab_add.png b/src/icons/tab_add.png deleted file mode 100644 index d3b99364a..000000000 Binary files a/src/icons/tab_add.png and /dev/null differ diff --git a/src/icons/tab_add.svg b/src/icons/tab_add.svg new file mode 100644 index 000000000..b76986388 --- /dev/null +++ b/src/icons/tab_add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/table.png b/src/icons/table.png deleted file mode 100755 index abcd93689..000000000 Binary files a/src/icons/table.png and /dev/null differ diff --git a/src/icons/table.svg b/src/icons/table.svg new file mode 100644 index 000000000..0ff696d2c --- /dev/null +++ b/src/icons/table.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/table_add.png b/src/icons/table_add.png deleted file mode 100755 index 2a3e5c4df..000000000 Binary files a/src/icons/table_add.png and /dev/null differ diff --git a/src/icons/table_add.svg b/src/icons/table_add.svg new file mode 100644 index 000000000..5a246ee5d --- /dev/null +++ b/src/icons/table_add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/table_delete.png b/src/icons/table_delete.png deleted file mode 100755 index b85916d92..000000000 Binary files a/src/icons/table_delete.png and /dev/null differ diff --git a/src/icons/table_delete.svg b/src/icons/table_delete.svg new file mode 100644 index 000000000..27c3663fb --- /dev/null +++ b/src/icons/table_delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/table_edit.png b/src/icons/table_edit.png deleted file mode 100755 index bfcb0249a..000000000 Binary files a/src/icons/table_edit.png and /dev/null differ diff --git a/src/icons/table_edit.svg b/src/icons/table_edit.svg new file mode 100644 index 000000000..bc95ba8ba --- /dev/null +++ b/src/icons/table_edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/table_key.svg b/src/icons/table_key.svg new file mode 100644 index 000000000..fa36a245b --- /dev/null +++ b/src/icons/table_key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/table_row_delete.svg b/src/icons/table_row_delete.svg new file mode 100644 index 000000000..28c28c06a --- /dev/null +++ b/src/icons/table_row_delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/table_row_insert.svg b/src/icons/table_row_insert.svg new file mode 100644 index 000000000..a8911fade --- /dev/null +++ b/src/icons/table_row_insert.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/table_save.png b/src/icons/table_save.png deleted file mode 100644 index 25b74d18f..000000000 Binary files a/src/icons/table_save.png and /dev/null differ diff --git a/src/icons/table_save.svg b/src/icons/table_save.svg new file mode 100644 index 000000000..65a8afbb6 --- /dev/null +++ b/src/icons/table_save.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/tag_blue.png b/src/icons/tag_blue.png deleted file mode 100755 index 9757fc6ed..000000000 Binary files a/src/icons/tag_blue.png and /dev/null differ diff --git a/src/icons/tag_blue.svg b/src/icons/tag_blue.svg new file mode 100644 index 000000000..bf9bcc000 --- /dev/null +++ b/src/icons/tag_blue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/tag_blue_add.png b/src/icons/tag_blue_add.png deleted file mode 100755 index f135248f8..000000000 Binary files a/src/icons/tag_blue_add.png and /dev/null differ diff --git a/src/icons/tag_blue_add.svg b/src/icons/tag_blue_add.svg new file mode 100644 index 000000000..11d195a27 --- /dev/null +++ b/src/icons/tag_blue_add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/tag_blue_delete.png b/src/icons/tag_blue_delete.png deleted file mode 100755 index 9fbae6725..000000000 Binary files a/src/icons/tag_blue_delete.png and /dev/null differ diff --git a/src/icons/tag_blue_delete.svg b/src/icons/tag_blue_delete.svg new file mode 100644 index 000000000..8a400633d --- /dev/null +++ b/src/icons/tag_blue_delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/tag_blue_edit.svg b/src/icons/tag_blue_edit.svg new file mode 100644 index 000000000..1cbcf72a0 --- /dev/null +++ b/src/icons/tag_blue_edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/text_align_center.svg b/src/icons/text_align_center.svg new file mode 100644 index 000000000..f19046123 --- /dev/null +++ b/src/icons/text_align_center.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/text_align_justify.svg b/src/icons/text_align_justify.svg new file mode 100644 index 000000000..f5e0d738f --- /dev/null +++ b/src/icons/text_align_justify.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/text_align_left.svg b/src/icons/text_align_left.svg new file mode 100644 index 000000000..6bb6b2ffd --- /dev/null +++ b/src/icons/text_align_left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/text_align_right.svg b/src/icons/text_align_right.svg new file mode 100644 index 000000000..320945361 --- /dev/null +++ b/src/icons/text_align_right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/text_bold.svg b/src/icons/text_bold.svg new file mode 100644 index 000000000..e75c7fe2a --- /dev/null +++ b/src/icons/text_bold.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/text_italic.svg b/src/icons/text_italic.svg new file mode 100644 index 000000000..caa4f3eb1 --- /dev/null +++ b/src/icons/text_italic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/text_padding_left.svg b/src/icons/text_padding_left.svg new file mode 100644 index 000000000..7546633cb --- /dev/null +++ b/src/icons/text_padding_left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/text_padding_top.svg b/src/icons/text_padding_top.svg new file mode 100644 index 000000000..37dc74939 --- /dev/null +++ b/src/icons/text_padding_top.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/text_sort_ascending.svg b/src/icons/text_sort_ascending.svg new file mode 100644 index 000000000..347fda561 --- /dev/null +++ b/src/icons/text_sort_ascending.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + Layer 1 + + + + + + + + + + \ No newline at end of file diff --git a/src/icons/text_underlined.svg b/src/icons/text_underlined.svg new file mode 100644 index 000000000..df2c8f047 --- /dev/null +++ b/src/icons/text_underlined.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/textfield_delete.svg b/src/icons/textfield_delete.svg new file mode 100644 index 000000000..56494b9c0 --- /dev/null +++ b/src/icons/textfield_delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icons/undo.svg b/src/icons/undo.svg new file mode 100644 index 000000000..cae4034b8 --- /dev/null +++ b/src/icons/undo.svg @@ -0,0 +1,29 @@ + + + + Undo + Undo + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/icons/view-refresh.png b/src/icons/view-refresh.png deleted file mode 100644 index 3fd71d6e5..000000000 Binary files a/src/icons/view-refresh.png and /dev/null differ diff --git a/src/icons/world_link.svg b/src/icons/world_link.svg new file mode 100644 index 000000000..253629896 --- /dev/null +++ b/src/icons/world_link.svg @@ -0,0 +1,95 @@ + + + + World Link + World Globe Link + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/icons/wrench.png b/src/icons/wrench.png deleted file mode 100644 index 5c8213fef..000000000 Binary files a/src/icons/wrench.png and /dev/null differ diff --git a/src/icons/wrench.svg b/src/icons/wrench.svg new file mode 100644 index 000000000..449acdc97 --- /dev/null +++ b/src/icons/wrench.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/iconwin.ico b/src/iconwin.ico index 41fab2b7f..fa32e44db 100644 Binary files a/src/iconwin.ico and b/src/iconwin.ico differ diff --git a/src/macapp.icns b/src/macapp.icns index 2d54c099c..33cfe25c5 100644 Binary files a/src/macapp.icns and b/src/macapp.icns differ diff --git a/src/main.cpp b/src/main.cpp index 4bab99d58..dc91e197c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,14 +1,66 @@ + #include "Application.h" +#include "sqlite.h" +#include + +static QString message = QString(); + +void db4sMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + QByteArray localMsg = msg.toLocal8Bit(); + + // Emulate the default Qt treatment. This might not work in some OS, like Windows. + fprintf(stderr, "%s\n", localMsg.constData()); + + const char *file = context.file ? context.file : ""; + const char *function = context.function ? context.function : ""; + localMsg = QString("%1 (%2, %3:%4)\n").arg(msg, function, file).arg(context.line).toLocal8Bit(); + + // Log using the SQLite log mechanism, so it gets the same treatment than messages + // reported by SQLite itself. This will allow these messages to be seen in our Log window. + // Error code will be the type + sqlite3_log(static_cast(type), localMsg.constData()); +} + +void boxMessageOutput(QtMsgType, const QMessageLogContext &, const QString &msg) +{ + message += msg + "\n"; +} int main( int argc, char ** argv ) { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); +#endif +#endif + QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); +#endif +#ifdef Q_OS_WIN + // In Windows, there is no output to terminal for a graphical application, so we install + // the output to message box, until the main window is shown or the application exits. + qInstallMessageHandler(boxMessageOutput); +#endif + // Create application object. All the initialisation stuff happens in there Application a(argc, argv); + // If there has been invocations to the message handler, show it to user in a message box. + if(!message.isEmpty()) { + QMessageBox messageBox; + messageBox.setTextFormat(Qt::RichText); + messageBox.setText("
" + message.toHtmlEscaped() + "
"); + messageBox.exec(); + } + // Quit application now if user doesn't want to see the UI - if(a.dontShowMainWindow()) + if(!a.showMainWindow()) return 0; + qInstallMessageHandler(db4sMessageOutput); + // Run application return a.exec(); } diff --git a/src/qdarkstyle/LICENSE.rst b/src/qdarkstyle/LICENSE.rst new file mode 100644 index 000000000..e22b68735 --- /dev/null +++ b/src/qdarkstyle/LICENSE.rst @@ -0,0 +1,405 @@ +License +======= + +The MIT License (MIT) - Code +---------------------------- + +Copyright (c) 2013-2019 Colin Duquesnoy + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +Creative Commons Attribution International 4.0 - Images +------------------------------------------------------- + +QDarkStyle (c) 2013-2019 Colin Duquesnoy +QDarkStyle (c) 2019-2019 Daniel Cosmo Pizetta + +Creative Commons Corporation (“Creative Commonsâ€) is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an “as-is†basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright and +certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + +- **Considerations for licensors:** Our public licenses are intended + for use by those authorized to give the public permission to use + material in ways otherwise restricted by copyright and certain other + rights. Our licenses are irrevocable. Licensors should read and + understand the terms and conditions of the license they choose before + applying it. Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the material as + expected. Licensors should clearly mark any material not subject to + the license. This includes other CC-licensed material, or material + used under an exception or limitation to copyright. `More + considerations for + licensors `__. + +- **Considerations for the public:** By using one of our public + licenses, a licensor grants the public permission to use the licensed + material under specified terms and conditions. If the licensor’s + permission is not necessary for any reason–for example, because of + any applicable exception or limitation to copyright–then that use is + not regulated by the license. Our licenses grant only permissions + under copyright and certain other rights that a licensor has + authority to grant. Use of the licensed material may still be + restricted for other reasons, including because others have copyright + or other rights in the material. A licensor may make special + requests, such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to respect + those requests where reasonable. `More considerations for the + public `__. + + +Creative Commons Attribution 4.0 International Public License +------------------------------------------------------------- + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution 4.0 International Public License ("Public License"). To the +extent this Public License may be interpreted as a contract, You are +granted the Licensed Rights in consideration of Your acceptance of these +terms and conditions, and the Licensor grants You such rights in +consideration of benefits the Licensor receives from making the Licensed +Material available under these terms and conditions. + +Section 1 – Definitions +~~~~~~~~~~~~~~~~~~~~~~~ + +a. **Adapted Material** means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material and + in which the Licensed Material is translated, altered, arranged, + transformed, or otherwise modified in a manner requiring permission + under the Copyright and Similar Rights held by the Licensor. For + purposes of this Public License, where the Licensed Material is a + musical work, performance, or sound recording, Adapted Material is + always produced where the Licensed Material is synched in timed + relation with a moving image. + +b. **Adapter's License** means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + +c. **Copyright and Similar Rights** means copyright and/or similar + rights closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or categorized. + For purposes of this Public License, the rights specified in Section + 2(b)(1)-(2) are not Copyright and Similar Rights. + +d. **Effective Technological Measures** means those measures that, in + the absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright Treaty + adopted on December 20, 1996, and/or similar international + agreements. + +e. **Exceptions and Limitations** means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + +f. **Licensed Material** means the artistic or literary work, database, + or other material to which the Licensor applied this Public License. + +g. **Licensed Rights** means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to all + Copyright and Similar Rights that apply to Your use of the Licensed + Material and that the Licensor has authority to license. + +h. **Licensor** means the individual(s) or entity(ies) granting rights + under this Public License. + +i. **Share** means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such as + reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the public + may access the material from a place and at a time individually + chosen by them. + +j. **Sui Generis Database Rights** means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, as + amended and/or succeeded, as well as other essentially equivalent + rights anywhere in the world. + +k. **You** means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + +Section 2 – Scope +~~~~~~~~~~~~~~~~~ + +a. **License grant.** + +1. Subject to the terms and conditions of this Public License, the + Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to exercise the + Licensed Rights in the Licensed Material to: + + A. reproduce and Share the Licensed Material, in whole or in part; + and + + B. produce, reproduce, and Share Adapted Material. + +2. **Exceptions and Limitations.** For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public License + does not apply, and You do not need to comply with its terms and + conditions. + +3. **Term.** The term of this Public License is specified in Section + 6(a). + +4. **Media and formats; technical modifications allowed.** The Licensor + authorizes You to exercise the Licensed Rights in all media and + formats whether now known or hereafter created, and to make technical + modifications necessary to do so. The Licensor waives and/or agrees + not to assert any right or authority to forbid You from making + technical modifications necessary to exercise the Licensed Rights, + including technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, simply + making modifications authorized by this Section 2(a)(4) never + produces Adapted Material. + +5. **Downstream recipients.** + + A. **Offer from the Licensor – Licensed Material.** Every recipient + of the Licensed Material automatically receives an offer from the + Licensor to exercise the Licensed Rights under the terms and + conditions of this Public License. + + B. **No downstream restrictions.** You may not offer or impose any + additional or different terms or conditions on, or apply any + Effective Technological Measures to, the Licensed Material if doing + so restricts exercise of the Licensed Rights by any recipient of the + Licensed Material. + +6. **No endorsement.** Nothing in this Public License constitutes or may + be construed as permission to assert or imply that You are, or that + Your use of the Licensed Material is, connected with, or sponsored, + endorsed, or granted official status by, the Licensor or others + designated to receive attribution as provided in Section + 3(a)(1)(A)(i). + +b. **Other rights.** + +1. Moral rights, such as the right of integrity, are not licensed under + this Public License, nor are publicity, privacy, and/or other similar + personality rights; however, to the extent possible, the Licensor + waives and/or agrees not to assert any such rights held by the + Licensor to the limited extent necessary to allow You to exercise the + Licensed Rights, but not otherwise. + +2. Patent and trademark rights are not licensed under this Public + License. + +3. To the extent possible, the Licensor waives any right to collect + royalties from You for the exercise of the Licensed Rights, whether + directly or through a collecting society under any voluntary or + waivable statutory or compulsory licensing scheme. In all other cases + the Licensor expressly reserves any right to collect such royalties. + +Section 3 – License Conditions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + +a. **Attribution.** + +1. If You Share the Licensed Material (including in modified form), You + must: + + A. retain the following if it is supplied by the Licensor with the + Licensed Material: + + i. identification of the creator(s) of the Licensed Material and any + others designated to receive attribution, in any reasonable manner + requested by the Licensor (including by pseudonym if designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of warranties; + + v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; + + B. indicate if You modified the Licensed Material and retain an + indication of any previous modifications; and + + C. indicate the Licensed Material is licensed under this Public + License, and include the text of, or the URI or hyperlink to, this + Public License. + +2. You may satisfy the conditions in Section 3(a)(1) in any reasonable + manner based on the medium, means, and context in which You Share the + Licensed Material. For example, it may be reasonable to satisfy the + conditions by providing a URI or hyperlink to a resource that + includes the required information. + +3. If requested by the Licensor, You must remove any of the information + required by Section 3(a)(1)(A) to the extent reasonably practicable. + +4. If You Share Adapted Material You produce, the Adapter's License You + apply must not prevent recipients of the Adapted Material from + complying with this Public License. + +Section 4 – Sui Generis Database Rights +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Where the Licensed Rights include Sui Generis Database Rights that apply +to Your use of the Licensed Material: + +a. for the avoidance of doubt, Section 2(a)(1) grants You the right to + extract, reuse, reproduce, and Share all or a substantial portion of + the contents of the database; + +b. if You include all or a substantial portion of the database contents + in a database in which You have Sui Generis Database Rights, then the + database in which You have Sui Generis Database Rights (but not its + individual contents) is Adapted Material; and + +c. You must comply with the conditions in Section 3(a) if You Share all + or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + +Section 5 – Disclaimer of Warranties and Limitation of Liability +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +a. Unless otherwise separately undertaken by the Licensor, to the + extent possible, the Licensor offers the Licensed Material as-is and + as-available, and makes no representations or warranties of any kind + concerning the Licensed Material, whether express, implied, + statutory, or other. This includes, without limitation, warranties of + title, merchantability, fitness for a particular purpose, + non-infringement, absence of latent or other defects, accuracy, or + the presence or absence of errors, whether or not known or + discoverable. Where disclaimers of warranties are not allowed in full + or in part, this disclaimer may not apply to You. + +b. To the extent possible, in no event will the Licensor be liable to + You on any legal theory (including, without limitation, negligence) + or otherwise for any direct, special, indirect, incidental, + consequential, punitive, exemplary, or other losses, costs, expenses, + or damages arising out of this Public License or use of the Licensed + Material, even if the Licensor has been advised of the possibility of + such losses, costs, expenses, or damages. Where a limitation of + liability is not allowed in full or in part, this limitation may not + apply to You. + +c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent possible, + most closely approximates an absolute disclaimer and waiver of all + liability. + +Section 6 – Term and Termination +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +a. This Public License applies for the term of the Copyright and Similar + Rights licensed here. However, if You fail to comply with this Public + License, then Your rights under this Public License terminate + automatically. + +b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + +1. automatically as of the date the violation is cured, provided it is + cured within 30 days of Your discovery of the violation; or + +2. upon express reinstatement by the Licensor. + +For the avoidance of doubt, this Section 6(b) does not affect any right +the Licensor may have to seek remedies for Your violations of this +Public License. + +c. For the avoidance of doubt, the Licensor may also offer the Licensed + Material under separate terms or conditions or stop distributing the + Licensed Material at any time; however, doing so will not terminate + this Public License. + +d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + +Section 7 – Other Terms and Conditions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +a. The Licensor shall not be bound by any additional or different terms + or conditions communicated by You unless expressly agreed. + +b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and independent + of the terms and conditions of this Public License. + +Section 8 – Interpretation +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +a. For the avoidance of doubt, this Public License does not, and shall + not be interpreted to, reduce, limit, restrict, or impose conditions + on any use of the Licensed Material that could lawfully be made + without permission under this Public License. + +b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + +c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + +d. Nothing in this Public License constitutes or may be interpreted as a + limitation upon, or waiver of, any privileges and immunities that + apply to the Licensor or You, including from the legal processes of + any jurisdiction or authority. + + Creative Commons is not a party to its public licenses. + Notwithstanding, Creative Commons may elect to apply one of its + public licenses to material it publishes and in those instances will + be considered the “Licensor.†Except for the limited purpose of + indicating that material is shared under a Creative Commons public + license or as otherwise permitted by the Creative Commons policies + published at + `creativecommons.org/policies `__, + Creative Commons does not authorize the use of the trademark + “Creative Commons†or any other trademark or logo of Creative + Commons without its prior written consent including, without + limitation, in connection with any unauthorized modifications to any + of its public licenses or any other arrangements, understandings, or + agreements concerning use of licensed material. For the avoidance of + doubt, this paragraph does not form part of the public licenses. + + Creative Commons may be contacted at creativecommons.org diff --git a/src/qdarkstyle/dark/_variables.scss b/src/qdarkstyle/dark/_variables.scss new file mode 100644 index 000000000..d8f1bbedc --- /dev/null +++ b/src/qdarkstyle/dark/_variables.scss @@ -0,0 +1,33 @@ +// --------------------------------------------------------------------------- +// +// WARNING! File created programmatically. All changes made in this file will be lost! +// +// Created by the qtsass compiler v0.3.0 +// +// The definitions are in the "qdarkstyle.palette" module +// +//---------------------------------------------------------------------------- +$ID: 'dark'; +$COLOR_BACKGROUND_6: #60798B; +$COLOR_BACKGROUND_5: #54687A; +$COLOR_BACKGROUND_4: #455364; +$COLOR_BACKGROUND_2: #293544; +$COLOR_BACKGROUND_3: #37414F; +$COLOR_BACKGROUND_1: #19232D; +$COLOR_TEXT_1: #E0E1E3; +$COLOR_TEXT_2: #C9CDD0; +$COLOR_TEXT_3: #ACB1B6; +$COLOR_TEXT_4: #9DA9B5; +$COLOR_ACCENT_1: #26486B; +$COLOR_ACCENT_2: #346792; +$COLOR_ACCENT_3: #1A72BB; +$COLOR_ACCENT_4: #259AE9; +$OPACITY_TOOLTIP: 230; +$SIZE_BORDER_RADIUS: 4px; +$BORDER_1: 1px solid $COLOR_BACKGROUND_1; +$BORDER_2: 1px solid $COLOR_BACKGROUND_4; +$BORDER_3: 1px solid $COLOR_BACKGROUND_6; +$BORDER_SELECTION_3: 1px solid $COLOR_ACCENT_3; +$BORDER_SELECTION_2: 1px solid $COLOR_ACCENT_2; +$BORDER_SELECTION_1: 1px solid $COLOR_ACCENT_1; +$PATH_RESOURCES: ':/qss_icons'; diff --git a/src/qdarkstyle/dark/darkstyle.qrc b/src/qdarkstyle/dark/darkstyle.qrc new file mode 100644 index 000000000..ce0d85be6 --- /dev/null +++ b/src/qdarkstyle/dark/darkstyle.qrc @@ -0,0 +1,216 @@ + + + + rc/arrow_down.png + rc/arrow_down@2x.png + rc/arrow_down_disabled.png + rc/arrow_down_disabled@2x.png + rc/arrow_down_focus.png + rc/arrow_down_focus@2x.png + rc/arrow_down_pressed.png + rc/arrow_down_pressed@2x.png + rc/arrow_left.png + rc/arrow_left@2x.png + rc/arrow_left_disabled.png + rc/arrow_left_disabled@2x.png + rc/arrow_left_focus.png + rc/arrow_left_focus@2x.png + rc/arrow_left_pressed.png + rc/arrow_left_pressed@2x.png + rc/arrow_right.png + rc/arrow_right@2x.png + rc/arrow_right_disabled.png + rc/arrow_right_disabled@2x.png + rc/arrow_right_focus.png + rc/arrow_right_focus@2x.png + rc/arrow_right_pressed.png + rc/arrow_right_pressed@2x.png + rc/arrow_up.png + rc/arrow_up@2x.png + rc/arrow_up_disabled.png + rc/arrow_up_disabled@2x.png + rc/arrow_up_focus.png + rc/arrow_up_focus@2x.png + rc/arrow_up_pressed.png + rc/arrow_up_pressed@2x.png + rc/base_icon.png + rc/base_icon@2x.png + rc/base_icon_disabled.png + rc/base_icon_disabled@2x.png + rc/base_icon_focus.png + rc/base_icon_focus@2x.png + rc/base_icon_pressed.png + rc/base_icon_pressed@2x.png + rc/branch_closed.png + rc/branch_closed@2x.png + rc/branch_closed_disabled.png + rc/branch_closed_disabled@2x.png + rc/branch_closed_focus.png + rc/branch_closed_focus@2x.png + rc/branch_closed_pressed.png + rc/branch_closed_pressed@2x.png + rc/branch_end.png + rc/branch_end@2x.png + rc/branch_end_disabled.png + rc/branch_end_disabled@2x.png + rc/branch_end_focus.png + rc/branch_end_focus@2x.png + rc/branch_end_pressed.png + rc/branch_end_pressed@2x.png + rc/branch_line.png + rc/branch_line@2x.png + rc/branch_line_disabled.png + rc/branch_line_disabled@2x.png + rc/branch_line_focus.png + rc/branch_line_focus@2x.png + rc/branch_line_pressed.png + rc/branch_line_pressed@2x.png + rc/branch_more.png + rc/branch_more@2x.png + rc/branch_more_disabled.png + rc/branch_more_disabled@2x.png + rc/branch_more_focus.png + rc/branch_more_focus@2x.png + rc/branch_more_pressed.png + rc/branch_more_pressed@2x.png + rc/branch_open.png + rc/branch_open@2x.png + rc/branch_open_disabled.png + rc/branch_open_disabled@2x.png + rc/branch_open_focus.png + rc/branch_open_focus@2x.png + rc/branch_open_pressed.png + rc/branch_open_pressed@2x.png + rc/checkbox_checked.png + rc/checkbox_checked@2x.png + rc/checkbox_checked_disabled.png + rc/checkbox_checked_disabled@2x.png + rc/checkbox_checked_focus.png + rc/checkbox_checked_focus@2x.png + rc/checkbox_checked_pressed.png + rc/checkbox_checked_pressed@2x.png + rc/checkbox_indeterminate.png + rc/checkbox_indeterminate@2x.png + rc/checkbox_indeterminate_disabled.png + rc/checkbox_indeterminate_disabled@2x.png + rc/checkbox_indeterminate_focus.png + rc/checkbox_indeterminate_focus@2x.png + rc/checkbox_indeterminate_pressed.png + rc/checkbox_indeterminate_pressed@2x.png + rc/checkbox_unchecked.png + rc/checkbox_unchecked@2x.png + rc/checkbox_unchecked_disabled.png + rc/checkbox_unchecked_disabled@2x.png + rc/checkbox_unchecked_focus.png + rc/checkbox_unchecked_focus@2x.png + rc/checkbox_unchecked_pressed.png + rc/checkbox_unchecked_pressed@2x.png + rc/line_horizontal.png + rc/line_horizontal@2x.png + rc/line_horizontal_disabled.png + rc/line_horizontal_disabled@2x.png + rc/line_horizontal_focus.png + rc/line_horizontal_focus@2x.png + rc/line_horizontal_pressed.png + rc/line_horizontal_pressed@2x.png + rc/line_vertical.png + rc/line_vertical@2x.png + rc/line_vertical_disabled.png + rc/line_vertical_disabled@2x.png + rc/line_vertical_focus.png + rc/line_vertical_focus@2x.png + rc/line_vertical_pressed.png + rc/line_vertical_pressed@2x.png + rc/radio_checked.png + rc/radio_checked@2x.png + rc/radio_checked_disabled.png + rc/radio_checked_disabled@2x.png + rc/radio_checked_focus.png + rc/radio_checked_focus@2x.png + rc/radio_checked_pressed.png + rc/radio_checked_pressed@2x.png + rc/radio_unchecked.png + rc/radio_unchecked@2x.png + rc/radio_unchecked_disabled.png + rc/radio_unchecked_disabled@2x.png + rc/radio_unchecked_focus.png + rc/radio_unchecked_focus@2x.png + rc/radio_unchecked_pressed.png + rc/radio_unchecked_pressed@2x.png + rc/toolbar_move_horizontal.png + rc/toolbar_move_horizontal@2x.png + rc/toolbar_move_horizontal_disabled.png + rc/toolbar_move_horizontal_disabled@2x.png + rc/toolbar_move_horizontal_focus.png + rc/toolbar_move_horizontal_focus@2x.png + rc/toolbar_move_horizontal_pressed.png + rc/toolbar_move_horizontal_pressed@2x.png + rc/toolbar_move_vertical.png + rc/toolbar_move_vertical@2x.png + rc/toolbar_move_vertical_disabled.png + rc/toolbar_move_vertical_disabled@2x.png + rc/toolbar_move_vertical_focus.png + rc/toolbar_move_vertical_focus@2x.png + rc/toolbar_move_vertical_pressed.png + rc/toolbar_move_vertical_pressed@2x.png + rc/toolbar_separator_horizontal.png + rc/toolbar_separator_horizontal@2x.png + rc/toolbar_separator_horizontal_disabled.png + rc/toolbar_separator_horizontal_disabled@2x.png + rc/toolbar_separator_horizontal_focus.png + rc/toolbar_separator_horizontal_focus@2x.png + rc/toolbar_separator_horizontal_pressed.png + rc/toolbar_separator_horizontal_pressed@2x.png + rc/toolbar_separator_vertical.png + rc/toolbar_separator_vertical@2x.png + rc/toolbar_separator_vertical_disabled.png + rc/toolbar_separator_vertical_disabled@2x.png + rc/toolbar_separator_vertical_focus.png + rc/toolbar_separator_vertical_focus@2x.png + rc/toolbar_separator_vertical_pressed.png + rc/toolbar_separator_vertical_pressed@2x.png + rc/transparent.png + rc/transparent@2x.png + rc/transparent_disabled.png + rc/transparent_disabled@2x.png + rc/transparent_focus.png + rc/transparent_focus@2x.png + rc/transparent_pressed.png + rc/transparent_pressed@2x.png + rc/window_close.png + rc/window_close@2x.png + rc/window_close_disabled.png + rc/window_close_disabled@2x.png + rc/window_close_focus.png + rc/window_close_focus@2x.png + rc/window_close_pressed.png + rc/window_close_pressed@2x.png + rc/window_grip.png + rc/window_grip@2x.png + rc/window_grip_disabled.png + rc/window_grip_disabled@2x.png + rc/window_grip_focus.png + rc/window_grip_focus@2x.png + rc/window_grip_pressed.png + rc/window_grip_pressed@2x.png + rc/window_minimize.png + rc/window_minimize@2x.png + rc/window_minimize_disabled.png + rc/window_minimize_disabled@2x.png + rc/window_minimize_focus.png + rc/window_minimize_focus@2x.png + rc/window_minimize_pressed.png + rc/window_minimize_pressed@2x.png + rc/window_undock.png + rc/window_undock@2x.png + rc/window_undock_disabled.png + rc/window_undock_disabled@2x.png + rc/window_undock_focus.png + rc/window_undock_focus@2x.png + rc/window_undock_pressed.png + rc/window_undock_pressed@2x.png + + + darkstyle.qss + + diff --git a/src/qdarkstyle/dark/darkstyle.qss b/src/qdarkstyle/dark/darkstyle.qss new file mode 100644 index 000000000..bc04b911c --- /dev/null +++ b/src/qdarkstyle/dark/darkstyle.qss @@ -0,0 +1,2216 @@ +/* --------------------------------------------------------------------------- + + WARNING! File created programmatically. All changes made in this file will be lost! + + Created by the qtsass compiler v0.4.0 + + The definitions are in the "qdarkstyle.qss._styles.scss" module + +--------------------------------------------------------------------------- */ +/* Light Style - QDarkStyleSheet ------------------------------------------ */ +/* + +See Qt documentation: + + - https://doc.qt.io/qt-5/stylesheet.html + - https://doc.qt.io/qt-5/stylesheet-reference.html + - https://doc.qt.io/qt-5/stylesheet-examples.html + +--------------------------------------------------------------------------- */ +/* Reset elements ------------------------------------------------------------ + +Resetting everything helps to unify styles across different operating systems + +--------------------------------------------------------------------------- */ +* { + padding: 0px; + margin: 0px; + border: 0px; + border-style: none; + border-image: none; + outline: 0; +} + +/* specific reset for elements inside QToolBar */ +QToolBar * { + margin: 0px; + padding: 0px; +} + +/* QWidget ---------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QWidget { + background-color: #19232D; + border: 0px solid #455364; + padding: 0px; + color: #DFE1E2; + selection-background-color: #346792; + selection-color: #DFE1E2; +} + +QWidget:disabled { + background-color: #19232D; + color: #788D9C; + selection-background-color: #26486B; + selection-color: #788D9C; +} + +QWidget::item:selected { + background-color: #346792; +} + +QWidget::item:hover:!selected { + background-color: #1A72BB; +} + +/* QMainWindow ------------------------------------------------------------ + +This adjusts the splitter in the dock widget, not qsplitter +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmainwindow + +--------------------------------------------------------------------------- */ +QMainWindow::separator { + background-color: #455364; + border: 0px solid #19232D; + spacing: 0px; + padding: 2px; +} + +QMainWindow::separator:hover { + background-color: #60798B; + border: 0px solid #1A72BB; +} + +QMainWindow::separator:horizontal { + width: 5px; + margin-top: 2px; + margin-bottom: 2px; + image: url(":/qss_icons/dark/rc/toolbar_separator_vertical.png"); +} + +QMainWindow::separator:vertical { + height: 5px; + margin-left: 2px; + margin-right: 2px; + image: url(":/qss_icons/dark/rc/toolbar_separator_horizontal.png"); +} + +/* QToolTip --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtooltip + +--------------------------------------------------------------------------- */ +QToolTip { + background-color: #346792; + color: #DFE1E2; + /* If you remove the border property, background stops working on Windows */ + border: none; + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + /* Remove opacity, fix #174 - may need to use RGBA */ +} + +/* QStatusBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar + +--------------------------------------------------------------------------- */ +QStatusBar { + border: 1px solid #455364; + /* Fixes Spyder #9120, #9121 */ + background: #455364; + /* Fixes #205, white vertical borders separating items */ +} + +QStatusBar::item { + border: none; +} + +QStatusBar QToolTip { + background-color: #1A72BB; + border: 1px solid #19232D; + color: #19232D; + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + /* Reducing transparency to read better */ + opacity: 230; +} + +QStatusBar QLabel { + /* Fixes Spyder #9120, #9121 */ + background: transparent; +} + +/* QCheckBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcheckbox + +--------------------------------------------------------------------------- */ +QCheckBox { + background-color: #19232D; + color: #DFE1E2; + spacing: 4px; + outline: none; + padding-top: 4px; + padding-bottom: 4px; +} + +QCheckBox:focus { + border: none; +} + +QCheckBox QWidget:disabled { + background-color: #19232D; + color: #788D9C; +} + +QCheckBox::indicator { + margin-left: 2px; + height: 14px; + width: 14px; +} + +QCheckBox::indicator:unchecked { + image: url(":/qss_icons/dark/rc/checkbox_unchecked.png"); +} + +QCheckBox::indicator:unchecked:hover, QCheckBox::indicator:unchecked:focus, QCheckBox::indicator:unchecked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_unchecked_focus.png"); +} + +QCheckBox::indicator:unchecked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_unchecked_disabled.png"); +} + +QCheckBox::indicator:checked { + image: url(":/qss_icons/dark/rc/checkbox_checked.png"); +} + +QCheckBox::indicator:checked:hover, QCheckBox::indicator:checked:focus, QCheckBox::indicator:checked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_checked_focus.png"); +} + +QCheckBox::indicator:checked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_checked_disabled.png"); +} + +QCheckBox::indicator:indeterminate { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate.png"); +} + +QCheckBox::indicator:indeterminate:disabled { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_disabled.png"); +} + +QCheckBox::indicator:indeterminate:focus, QCheckBox::indicator:indeterminate:hover, QCheckBox::indicator:indeterminate:pressed { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_focus.png"); +} + +/* QGroupBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox + +--------------------------------------------------------------------------- */ +QGroupBox { + font-weight: bold; + border: 1px solid #455364; + border-radius: 4px; + padding: 2px; + margin-top: 6px; + margin-bottom: 4px; +} + +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + left: 4px; + padding-left: 2px; + padding-right: 4px; + padding-top: -4px; +} + +QGroupBox::indicator { + margin-left: 2px; + margin-top: 2px; + padding: 0; + height: 14px; + width: 14px; +} + +QGroupBox::indicator:unchecked { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_unchecked.png"); +} + +QGroupBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:focus, QGroupBox::indicator:unchecked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_unchecked_focus.png"); +} + +QGroupBox::indicator:unchecked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_unchecked_disabled.png"); +} + +QGroupBox::indicator:checked { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_checked.png"); +} + +QGroupBox::indicator:checked:hover, QGroupBox::indicator:checked:focus, QGroupBox::indicator:checked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_checked_focus.png"); +} + +QGroupBox::indicator:checked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_checked_disabled.png"); +} + +/* QRadioButton ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qradiobutton + +--------------------------------------------------------------------------- */ +QRadioButton { + background-color: #19232D; + color: #DFE1E2; + spacing: 4px; + padding-top: 4px; + padding-bottom: 4px; + border: none; + outline: none; +} + +QRadioButton:focus { + border: none; +} + +QRadioButton:disabled { + background-color: #19232D; + color: #788D9C; + border: none; + outline: none; +} + +QRadioButton QWidget { + background-color: #19232D; + color: #DFE1E2; + spacing: 0px; + padding: 0px; + outline: none; + border: none; +} + +QRadioButton::indicator { + border: none; + outline: none; + margin-left: 2px; + height: 14px; + width: 14px; +} + +QRadioButton::indicator:unchecked { + image: url(":/qss_icons/dark/rc/radio_unchecked.png"); +} + +QRadioButton::indicator:unchecked:hover, QRadioButton::indicator:unchecked:focus, QRadioButton::indicator:unchecked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_unchecked_focus.png"); +} + +QRadioButton::indicator:unchecked:disabled { + image: url(":/qss_icons/dark/rc/radio_unchecked_disabled.png"); +} + +QRadioButton::indicator:checked { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked.png"); +} + +QRadioButton::indicator:checked:hover, QRadioButton::indicator:checked:focus, QRadioButton::indicator:checked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked_focus.png"); +} + +QRadioButton::indicator:checked:disabled { + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked_disabled.png"); +} + +/* QMenuBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar + +--------------------------------------------------------------------------- */ +QMenuBar { + background-color: #455364; + padding: 2px; + border: 1px solid #19232D; + color: #DFE1E2; + selection-background-color: #1A72BB; +} + +QMenuBar:focus { + border: 1px solid #346792; +} + +QMenuBar::item { + background: transparent; + padding: 4px; +} + +QMenuBar::item:selected { + padding: 4px; + background: transparent; + border: 0px solid #455364; + background-color: #1A72BB; +} + +QMenuBar::item:pressed { + padding: 4px; + border: 0px solid #455364; + background-color: #1A72BB; + color: #DFE1E2; + margin-bottom: 0px; + padding-bottom: 0px; +} + +/* QMenu ------------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu + +--------------------------------------------------------------------------- */ +QMenu { + border: 0px solid #455364; + color: #DFE1E2; + margin: 0px; + background-color: #37414F; + selection-background-color: #1A72BB; +} + +QMenu::separator { + height: 1px; + background-color: #60798B; + color: #DFE1E2; +} + +QMenu::item { + background-color: #37414F; + padding: 4px 24px 4px 28px; + /* Reserve space for selection border */ + border: 1px transparent #455364; +} + +QMenu::item:selected { + color: #DFE1E2; + background-color: #1A72BB; +} + +QMenu::item:pressed { + background-color: #1A72BB; +} + +QMenu::icon { + padding-left: 10px; + width: 14px; + height: 14px; +} + +QMenu::indicator { + padding-left: 8px; + width: 12px; + height: 12px; + /* non-exclusive indicator = check box style indicator (see QActionGroup::setExclusive) */ + /* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */ +} + +QMenu::indicator:non-exclusive:unchecked { + image: url(":/qss_icons/dark/rc/checkbox_unchecked.png"); +} + +QMenu::indicator:non-exclusive:unchecked:hover, QMenu::indicator:non-exclusive:unchecked:focus, QMenu::indicator:non-exclusive:unchecked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_unchecked_focus.png"); +} + +QMenu::indicator:non-exclusive:unchecked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_unchecked_disabled.png"); +} + +QMenu::indicator:non-exclusive:checked { + image: url(":/qss_icons/dark/rc/checkbox_checked.png"); +} + +QMenu::indicator:non-exclusive:checked:hover, QMenu::indicator:non-exclusive:checked:focus, QMenu::indicator:non-exclusive:checked:pressed { + border: none; + image: url(":/qss_icons/dark/rc/checkbox_checked_focus.png"); +} + +QMenu::indicator:non-exclusive:checked:disabled { + image: url(":/qss_icons/dark/rc/checkbox_checked_disabled.png"); +} + +QMenu::indicator:non-exclusive:indeterminate { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate.png"); +} + +QMenu::indicator:non-exclusive:indeterminate:disabled { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_disabled.png"); +} + +QMenu::indicator:non-exclusive:indeterminate:focus, QMenu::indicator:non-exclusive:indeterminate:hover, QMenu::indicator:non-exclusive:indeterminate:pressed { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_focus.png"); +} + +QMenu::indicator:exclusive:unchecked { + image: url(":/qss_icons/dark/rc/radio_unchecked.png"); +} + +QMenu::indicator:exclusive:unchecked:hover, QMenu::indicator:exclusive:unchecked:focus, QMenu::indicator:exclusive:unchecked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_unchecked_focus.png"); +} + +QMenu::indicator:exclusive:unchecked:disabled { + image: url(":/qss_icons/dark/rc/radio_unchecked_disabled.png"); +} + +QMenu::indicator:exclusive:checked { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked.png"); +} + +QMenu::indicator:exclusive:checked:hover, QMenu::indicator:exclusive:checked:focus, QMenu::indicator:exclusive:checked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked_focus.png"); +} + +QMenu::indicator:exclusive:checked:disabled { + outline: none; + image: url(":/qss_icons/dark/rc/radio_checked_disabled.png"); +} + +QMenu::right-arrow { + margin: 5px; + padding-left: 12px; + image: url(":/qss_icons/dark/rc/arrow_right.png"); + height: 12px; + width: 12px; +} + +/* QAbstractItemView ------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QAbstractItemView { + alternate-background-color: #19232D; + color: #DFE1E2; + border: 1px solid #455364; + border-radius: 4px; +} + +QAbstractItemView QLineEdit { + padding: 2px; +} + +/* QAbstractScrollArea ---------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QAbstractScrollArea { + background-color: #19232D; + border: 1px solid #455364; + border-radius: 4px; + /* fix #159 */ + padding: 2px; + /* remove min-height to fix #244 */ + color: #DFE1E2; +} + +QAbstractScrollArea:disabled { + color: #788D9C; +} + +/* QScrollArea ------------------------------------------------------------ + +--------------------------------------------------------------------------- */ +QScrollArea QWidget QWidget:disabled { + background-color: #19232D; +} + +/* QScrollBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qscrollbar + +--------------------------------------------------------------------------- */ +QScrollBar:horizontal { + height: 16px; + margin: 2px 16px 2px 16px; + border: 1px solid #455364; + border-radius: 4px; + background-color: #19232D; +} + +QScrollBar:vertical { + background-color: #19232D; + width: 16px; + margin: 16px 2px 16px 2px; + border: 1px solid #455364; + border-radius: 4px; +} + +QScrollBar::handle:horizontal { + background-color: #60798B; + border: 1px solid #455364; + border-radius: 4px; + min-width: 8px; +} + +QScrollBar::handle:horizontal:hover { + background-color: #346792; + border: #346792; + border-radius: 4px; + min-width: 8px; +} + +QScrollBar::handle:horizontal:focus { + border: 1px solid #1A72BB; +} + +QScrollBar::handle:vertical { + background-color: #60798B; + border: 1px solid #455364; + min-height: 8px; + border-radius: 4px; +} + +QScrollBar::handle:vertical:hover { + background-color: #346792; + border: #346792; + border-radius: 4px; + min-height: 8px; +} + +QScrollBar::handle:vertical:focus { + border: 1px solid #1A72BB; +} + +QScrollBar::add-line:horizontal { + margin: 0px 0px 0px 0px; + border-image: url(":/qss_icons/dark/rc/arrow_right_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::add-line:horizontal:hover, QScrollBar::add-line:horizontal:on { + border-image: url(":/qss_icons/dark/rc/arrow_right.png"); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::add-line:vertical { + margin: 3px 0px 3px 0px; + border-image: url(":/qss_icons/dark/rc/arrow_down_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on { + border-image: url(":/qss_icons/dark/rc/arrow_down.png"); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal { + margin: 0px 3px 0px 3px; + border-image: url(":/qss_icons/dark/rc/arrow_left_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on { + border-image: url(":/qss_icons/dark/rc/arrow_left.png"); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:vertical { + margin: 3px 0px 3px 0px; + border-image: url(":/qss_icons/dark/rc/arrow_up_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:vertical:hover, QScrollBar::sub-line:vertical:on { + border-image: url(":/qss_icons/dark/rc/arrow_up.png"); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal { + background: none; +} + +QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { + background: none; +} + +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + background: none; +} + +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + background: none; +} + +/* QTextEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-specific-widgets + +--------------------------------------------------------------------------- */ +QTextEdit { + background-color: #19232D; + color: #DFE1E2; + border-radius: 4px; + border: 1px solid #455364; +} + +QTextEdit:focus { + border: 1px solid #1A72BB; +} + +QTextEdit:selected { + background: #346792; + color: #455364; +} + +/* QPlainTextEdit --------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QPlainTextEdit { + background-color: #19232D; + color: #DFE1E2; + border-radius: 4px; + border: 1px solid #455364; +} + +QPlainTextEdit:focus { + border: 1px solid #1A72BB; +} + +QPlainTextEdit:selected { + background: #346792; + color: #455364; +} + +/* QSizeGrip -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsizegrip + +--------------------------------------------------------------------------- */ +QSizeGrip { + background: transparent; + width: 12px; + height: 12px; + image: url(":/qss_icons/dark/rc/window_grip.png"); +} + +/* QStackedWidget --------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QStackedWidget { + padding: 2px; + border: 1px solid #455364; + border: 1px solid #19232D; +} + +/* QToolBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbar + +--------------------------------------------------------------------------- */ +QToolBar { + background-color: #455364; + border-bottom: 1px solid #19232D; + padding: 1px; + font-weight: bold; + spacing: 2px; +} + +QToolBar:disabled { + /* Fixes #272 */ + background-color: #455364; +} + +QToolBar::handle:horizontal { + width: 16px; + image: url(":/qss_icons/dark/rc/toolbar_move_horizontal.png"); +} + +QToolBar::handle:vertical { + height: 16px; + image: url(":/qss_icons/dark/rc/toolbar_move_vertical.png"); +} + +QToolBar::separator:horizontal { + width: 16px; + image: url(":/qss_icons/dark/rc/toolbar_separator_horizontal.png"); +} + +QToolBar::separator:vertical { + height: 16px; + image: url(":/qss_icons/dark/rc/toolbar_separator_vertical.png"); +} + +QToolButton#qt_toolbar_ext_button { + background: #455364; + border: 0px; + color: #DFE1E2; + image: url(":/qss_icons/dark/rc/arrow_right.png"); +} + +/* QAbstractSpinBox ------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractSpinBox { + background-color: #19232D; + border: 1px solid #455364; + color: #DFE1E2; + /* This fixes 103, 111 */ + padding-top: 2px; + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + border-radius: 4px; + /* min-width: 5px; removed to fix 109 */ +} + +QAbstractSpinBox:up-button { + background-color: transparent #19232D; + subcontrol-origin: border; + subcontrol-position: top right; + border-left: 1px solid #455364; + border-bottom: 1px solid #455364; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-bottom: -1px; +} + +QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off { + image: url(":/qss_icons/dark/rc/arrow_up_disabled.png"); + height: 8px; + width: 8px; +} + +QAbstractSpinBox::up-arrow:hover { + image: url(":/qss_icons/dark/rc/arrow_up.png"); +} + +QAbstractSpinBox:down-button { + background-color: transparent #19232D; + subcontrol-origin: border; + subcontrol-position: bottom right; + border-left: 1px solid #455364; + border-top: 1px solid #455364; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-top: -1px; +} + +QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off { + image: url(":/qss_icons/dark/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QAbstractSpinBox::down-arrow:hover { + image: url(":/qss_icons/dark/rc/arrow_down.png"); +} + +QAbstractSpinBox:hover { + border: 1px solid #346792; + color: #DFE1E2; +} + +QAbstractSpinBox:focus { + border: 1px solid #1A72BB; +} + +QAbstractSpinBox:selected { + background: #346792; + color: #455364; +} + +/* ------------------------------------------------------------------------ */ +/* DISPLAYS --------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QLabel ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe + +--------------------------------------------------------------------------- */ +QLabel { + background-color: #19232D; + border: 0px solid #455364; + padding: 2px; + margin: 0px; + color: #DFE1E2; +} + +QLabel:disabled { + background-color: #19232D; + border: 0px solid #455364; + color: #788D9C; +} + +/* QTextBrowser ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QTextBrowser { + background-color: #19232D; + border: 1px solid #455364; + color: #DFE1E2; + border-radius: 4px; +} + +QTextBrowser:disabled { + background-color: #19232D; + border: 1px solid #455364; + color: #788D9C; + border-radius: 4px; +} + +QTextBrowser:hover, QTextBrowser:!hover, QTextBrowser:selected, QTextBrowser:pressed { + border: 1px solid #455364; +} + +/* QGraphicsView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QGraphicsView { + background-color: #19232D; + border: 1px solid #455364; + color: #DFE1E2; + border-radius: 4px; +} + +QGraphicsView:disabled { + background-color: #19232D; + border: 1px solid #455364; + color: #788D9C; + border-radius: 4px; +} + +QGraphicsView:hover, QGraphicsView:!hover, QGraphicsView:selected, QGraphicsView:pressed { + border: 1px solid #455364; +} + +/* QCalendarWidget -------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCalendarWidget { + border: 1px solid #455364; + border-radius: 4px; +} + +QCalendarWidget:disabled { + background-color: #19232D; + color: #788D9C; +} + +/* QLCDNumber ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QLCDNumber { + background-color: #19232D; + color: #DFE1E2; +} + +QLCDNumber:disabled { + background-color: #19232D; + color: #788D9C; +} + +/* QProgressBar ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qprogressbar + +--------------------------------------------------------------------------- */ +QProgressBar { + background-color: #19232D; + border: 1px solid #455364; + color: #DFE1E2; + border-radius: 4px; + text-align: center; +} + +QProgressBar:disabled { + background-color: #19232D; + border: 1px solid #455364; + color: #788D9C; + border-radius: 4px; + text-align: center; +} + +QProgressBar::chunk { + background-color: #346792; + color: #19232D; + border-radius: 4px; +} + +QProgressBar::chunk:disabled { + background-color: #26486B; + color: #788D9C; + border-radius: 4px; +} + +/* ------------------------------------------------------------------------ */ +/* BUTTONS ---------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QPushButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qpushbutton + +--------------------------------------------------------------------------- */ +QPushButton { + background-color: #455364; + color: #DFE1E2; + border-radius: 4px; + padding: 2px; + outline: none; + border: none; +} + +QPushButton:disabled { + background-color: #455364; + color: #788D9C; + border-radius: 4px; + padding: 2px; +} + +QPushButton:checked { + background-color: #60798B; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QPushButton:checked:disabled { + background-color: #60798B; + color: #788D9C; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QPushButton:checked:selected { + background: #60798B; +} + +QPushButton:hover { + background-color: #54687A; + color: #DFE1E2; +} + +QPushButton:pressed { + background-color: #60798B; +} + +QPushButton:selected { + background: #60798B; + color: #DFE1E2; +} + +QPushButton::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: bottom right; + bottom: 4px; +} + +QDialogButtonBox QPushButton { + /* Issue #194 #248 - Special case of QPushButton inside dialogs, for better UI */ + min-width: 80px; +} + +/* QToolButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbutton + +--------------------------------------------------------------------------- */ +QToolButton { + background-color: #455364; + color: #DFE1E2; + border-radius: 4px; + padding: 2px; + outline: none; + border: none; + /* The subcontrols below are used only in the DelayedPopup mode */ + /* The subcontrols below are used only in the MenuButtonPopup mode */ + /* The subcontrol below is used only in the InstantPopup or DelayedPopup mode */ +} + +QToolButton:disabled { + background-color: #455364; + color: #788D9C; + border-radius: 4px; + padding: 2px; +} + +QToolButton:checked { + background-color: #60798B; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QToolButton:checked:disabled { + background-color: #60798B; + color: #788D9C; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QToolButton:checked:hover { + background-color: #54687A; + color: #DFE1E2; +} + +QToolButton:checked:pressed { + background-color: #60798B; +} + +QToolButton:checked:selected { + background: #60798B; + color: #DFE1E2; +} + +QToolButton:hover { + background-color: #54687A; + color: #DFE1E2; +} + +QToolButton:pressed { + background-color: #60798B; +} + +QToolButton:selected { + background: #60798B; + color: #DFE1E2; +} + +QToolButton[popupMode="0"] { + /* Only for DelayedPopup */ + padding-right: 2px; +} + +QToolButton[popupMode="1"] { + /* Only for MenuButtonPopup */ + padding-right: 20px; +} + +QToolButton[popupMode="1"]::menu-button { + border: none; +} + +QToolButton[popupMode="1"]::menu-button:hover { + border: none; + border-left: 1px solid #455364; + border-radius: 0; +} + +QToolButton[popupMode="2"] { + /* Only for InstantPopup */ + padding-right: 2px; +} + +QToolButton::menu-button { + padding: 2px; + border-radius: 4px; + width: 12px; + border: none; + outline: none; +} + +QToolButton::menu-button:hover { + border: 1px solid #346792; +} + +QToolButton::menu-button:checked:hover { + border: 1px solid #346792; +} + +QToolButton::menu-indicator { + image: url(":/qss_icons/dark/rc/arrow_down.png"); + height: 8px; + width: 8px; + top: 0; + /* Exclude a shift for better image */ + left: -2px; + /* Shift it a bit */ +} + +QToolButton::menu-arrow { + image: url(":/qss_icons/dark/rc/arrow_down.png"); + height: 8px; + width: 8px; +} + +QToolButton::menu-arrow:hover { + image: url(":/qss_icons/dark/rc/arrow_down_focus.png"); +} + +/* QCommandLinkButton ----------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCommandLinkButton { + background-color: transparent; + border: 1px solid #455364; + color: #DFE1E2; + border-radius: 4px; + padding: 0px; + margin: 0px; +} + +QCommandLinkButton:disabled { + background-color: transparent; + color: #788D9C; +} + +/* ------------------------------------------------------------------------ */ +/* INPUTS - NO FIELDS ----------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QComboBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QComboBox { + border: 1px solid #455364; + border-radius: 4px; + selection-background-color: #346792; + padding-left: 4px; + padding-right: 4px; + /* padding-right = 36; 4 + 16*2 See scrollbar size */ + /* changed to 4px to fix #239 */ + /* Fixes #103, #111 */ + min-height: 1.5em; + /* padding-top: 2px; removed to fix #132 */ + /* padding-bottom: 2px; removed to fix #132 */ + /* min-width: 75px; removed to fix #109 */ + /* Needed to remove indicator - fix #132 */ +} + +QComboBox QAbstractItemView { + border: 1px solid #455364; + border-radius: 0; + background-color: #19232D; + selection-background-color: #346792; +} + +QComboBox QAbstractItemView:hover { + background-color: #19232D; + color: #DFE1E2; +} + +QComboBox QAbstractItemView:selected { + background: #346792; + color: #455364; +} + +QComboBox QAbstractItemView:alternate { + background: #19232D; +} + +QComboBox:disabled { + background-color: #19232D; + color: #788D9C; +} + +QComboBox:hover { + border: 1px solid #346792; +} + +QComboBox:focus { + border: 1px solid #1A72BB; +} + +QComboBox:on { + selection-background-color: #346792; +} + +QComboBox::indicator { + border: none; + border-radius: 0; + background-color: transparent; + selection-background-color: transparent; + color: transparent; + selection-color: transparent; + /* Needed to remove indicator - fix #132 */ +} + +QComboBox::indicator:alternate { + background: #19232D; +} + +QComboBox::item { + /* Remove to fix #282, #285 and MR #288*/ + /*&:checked { + font-weight: bold; + } + + &:selected { + border: 0px solid transparent; + } + */ +} + +QComboBox::item:alternate { + background: #19232D; +} + +QComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid #455364; +} + +QComboBox::down-arrow { + image: url(":/qss_icons/dark/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QComboBox::down-arrow:on, QComboBox::down-arrow:hover, QComboBox::down-arrow:focus { + image: url(":/qss_icons/dark/rc/arrow_down.png"); +} + +/* QSlider ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qslider + +--------------------------------------------------------------------------- */ +QSlider:disabled { + background: #19232D; +} + +QSlider:focus { + border: none; +} + +QSlider::groove:horizontal { + background: #455364; + border: 1px solid #455364; + height: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::groove:vertical { + background: #455364; + border: 1px solid #455364; + width: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::add-page:vertical { + background: #346792; + border: 1px solid #455364; + width: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::add-page:vertical :disabled { + background: #26486B; +} + +QSlider::sub-page:horizontal { + background: #346792; + border: 1px solid #455364; + height: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::sub-page:horizontal:disabled { + background: #26486B; +} + +QSlider::handle:horizontal { + background: #9DA9B5; + border: 1px solid #455364; + width: 8px; + height: 8px; + margin: -8px 0px; + border-radius: 4px; +} + +QSlider::handle:horizontal:hover { + background: #346792; + border: 1px solid #346792; +} + +QSlider::handle:horizontal:focus { + border: 1px solid #1A72BB; +} + +QSlider::handle:vertical { + background: #9DA9B5; + border: 1px solid #455364; + width: 8px; + height: 8px; + margin: 0 -8px; + border-radius: 4px; +} + +QSlider::handle:vertical:hover { + background: #346792; + border: 1px solid #346792; +} + +QSlider::handle:vertical:focus { + border: 1px solid #1A72BB; +} + +/* QLineEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlineedit + +--------------------------------------------------------------------------- */ +QLineEdit { + background-color: #19232D; + padding-top: 2px; + /* This QLineEdit fix 103, 111 */ + padding-bottom: 2px; + /* This QLineEdit fix 103, 111 */ + padding-left: 4px; + padding-right: 4px; + border-style: solid; + border: 1px solid #455364; + border-radius: 4px; + color: #DFE1E2; +} + +QLineEdit:disabled { + background-color: #19232D; + color: #788D9C; +} + +QLineEdit:hover { + border: 1px solid #346792; + color: #DFE1E2; +} + +QLineEdit:focus { + border: 1px solid #1A72BB; +} + +QLineEdit:selected { + background-color: #346792; + color: #455364; +} + +/* QTabWiget -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabWidget { + padding: 2px; + selection-background-color: #455364; +} + +QTabWidget QWidget { + /* Fixes #189 */ + border-radius: 4px; +} + +QTabWidget::pane { + border: 1px solid #455364; + border-radius: 4px; + margin: 0px; + /* Fixes double border inside pane with pyqt5 */ + padding: 0px; +} + +QTabWidget::pane:selected { + background-color: #455364; + border: 1px solid #346792; +} + +/* QTabBar ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabBar, QDockWidget QTabBar { + qproperty-drawBase: 0; + border-radius: 4px; + margin: 0px; + padding: 2px; + border: 0; + /* left: 5px; move to the right by 5px - removed for fix */ +} + +QTabBar::close-button, QDockWidget QTabBar::close-button { + border: 0; + margin: 0; + padding: 4px; + image: url(":/qss_icons/dark/rc/window_close.png"); +} + +QTabBar::close-button:hover, QDockWidget QTabBar::close-button:hover { + image: url(":/qss_icons/dark/rc/window_close_focus.png"); +} + +QTabBar::close-button:pressed, QDockWidget QTabBar::close-button:pressed { + image: url(":/qss_icons/dark/rc/window_close_pressed.png"); +} + +QTabBar::tab, QDockWidget QTabBar::tab { + /* !selected and disabled ----------------------------------------- */ + /* selected ------------------------------------------------------- */ +} + +QTabBar::tab:top:selected:disabled, QDockWidget QTabBar::tab:top:selected:disabled { + border-bottom: 3px solid #26486B; + color: #788D9C; + background-color: #455364; +} + +QTabBar::tab:bottom:selected:disabled, QDockWidget QTabBar::tab:bottom:selected:disabled { + border-top: 3px solid #26486B; + color: #788D9C; + background-color: #455364; +} + +QTabBar::tab:left:selected:disabled, QDockWidget QTabBar::tab:left:selected:disabled { + border-right: 3px solid #26486B; + color: #788D9C; + background-color: #455364; +} + +QTabBar::tab:right:selected:disabled, QDockWidget QTabBar::tab:right:selected:disabled { + border-left: 3px solid #26486B; + color: #788D9C; + background-color: #455364; +} + +QTabBar::tab:top:!selected:disabled, QDockWidget QTabBar::tab:top:!selected:disabled { + border-bottom: 3px solid #19232D; + color: #788D9C; + background-color: #19232D; +} + +QTabBar::tab:bottom:!selected:disabled, QDockWidget QTabBar::tab:bottom:!selected:disabled { + border-top: 3px solid #19232D; + color: #788D9C; + background-color: #19232D; +} + +QTabBar::tab:left:!selected:disabled, QDockWidget QTabBar::tab:left:!selected:disabled { + border-right: 3px solid #19232D; + color: #788D9C; + background-color: #19232D; +} + +QTabBar::tab:right:!selected:disabled, QDockWidget QTabBar::tab:right:!selected:disabled { + border-left: 3px solid #19232D; + color: #788D9C; + background-color: #19232D; +} + +QTabBar::tab:top:!selected, QDockWidget QTabBar::tab:top:!selected { + border-bottom: 2px solid #19232D; + margin-top: 2px; +} + +QTabBar::tab:bottom:!selected, QDockWidget QTabBar::tab:bottom:!selected { + border-top: 2px solid #19232D; + margin-bottom: 2px; +} + +QTabBar::tab:left:!selected, QDockWidget QTabBar::tab:left:!selected { + border-left: 2px solid #19232D; + margin-right: 2px; +} + +QTabBar::tab:right:!selected, QDockWidget QTabBar::tab:right:!selected { + border-right: 2px solid #19232D; + margin-left: 2px; +} + +QTabBar::tab:top, QDockWidget QTabBar::tab:top { + background-color: #455364; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + min-width: 5px; + border-bottom: 3px solid #455364; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QTabBar::tab:top:selected, QDockWidget QTabBar::tab:top:selected { + background-color: #54687A; + border-bottom: 3px solid #259AE9; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QTabBar::tab:top:!selected:hover, QDockWidget QTabBar::tab:top:!selected:hover { + border: 1px solid #1A72BB; + border-bottom: 3px solid #1A72BB; + /* Fixes spyder-ide/spyder#9766 and #243 */ + padding-left: 3px; + padding-right: 3px; +} + +QTabBar::tab:bottom, QDockWidget QTabBar::tab:bottom { + border-top: 3px solid #455364; + background-color: #455364; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + min-width: 5px; +} + +QTabBar::tab:bottom:selected, QDockWidget QTabBar::tab:bottom:selected { + background-color: #54687A; + border-top: 3px solid #259AE9; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +QTabBar::tab:bottom:!selected:hover, QDockWidget QTabBar::tab:bottom:!selected:hover { + border: 1px solid #1A72BB; + border-top: 3px solid #1A72BB; + /* Fixes spyder-ide/spyder#9766 and #243 */ + padding-left: 3px; + padding-right: 3px; +} + +QTabBar::tab:left, QDockWidget QTabBar::tab:left { + background-color: #455364; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + min-height: 5px; +} + +QTabBar::tab:left:selected, QDockWidget QTabBar::tab:left:selected { + background-color: #54687A; + border-right: 3px solid #259AE9; +} + +QTabBar::tab:left:!selected:hover, QDockWidget QTabBar::tab:left:!selected:hover { + border: 1px solid #1A72BB; + border-right: 3px solid #1A72BB; + /* Fixes different behavior #271 */ + margin-right: 0px; + padding-right: -1px; +} + +QTabBar::tab:right, QDockWidget QTabBar::tab:right { + background-color: #455364; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + min-height: 5px; +} + +QTabBar::tab:right:selected, QDockWidget QTabBar::tab:right:selected { + background-color: #54687A; + border-left: 3px solid #259AE9; +} + +QTabBar::tab:right:!selected:hover, QDockWidget QTabBar::tab:right:!selected:hover { + border: 1px solid #1A72BB; + border-left: 3px solid #1A72BB; + /* Fixes different behavior #271 */ + margin-left: 0px; + padding-left: 0px; +} + +QTabBar QToolButton, QDockWidget QTabBar QToolButton { + /* Fixes #136 */ + background-color: #455364; + height: 12px; + width: 12px; +} + +QTabBar QToolButton:pressed, QDockWidget QTabBar QToolButton:pressed { + background-color: #455364; +} + +QTabBar QToolButton:pressed:hover, QDockWidget QTabBar QToolButton:pressed:hover { + border: 1px solid #346792; +} + +QTabBar QToolButton::left-arrow:enabled, QDockWidget QTabBar QToolButton::left-arrow:enabled { + image: url(":/qss_icons/dark/rc/arrow_left.png"); +} + +QTabBar QToolButton::left-arrow:disabled, QDockWidget QTabBar QToolButton::left-arrow:disabled { + image: url(":/qss_icons/dark/rc/arrow_left_disabled.png"); +} + +QTabBar QToolButton::right-arrow:enabled, QDockWidget QTabBar QToolButton::right-arrow:enabled { + image: url(":/qss_icons/dark/rc/arrow_right.png"); +} + +QTabBar QToolButton::right-arrow:disabled, QDockWidget QTabBar QToolButton::right-arrow:disabled { + image: url(":/qss_icons/dark/rc/arrow_right_disabled.png"); +} + +/* QDockWiget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QDockWidget { + outline: 1px solid #455364; + background-color: #19232D; + border: 1px solid #455364; + border-radius: 4px; + titlebar-close-icon: url(":/qss_icons/dark/rc/transparent.png"); + titlebar-normal-icon: url(":/qss_icons/dark/rc/transparent.png"); +} + +QDockWidget::title { + /* Better size for title bar */ + padding: 3px; + spacing: 4px; + border: none; + background-color: #455364; +} + +QDockWidget::close-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + border: 0; + margin: 0; + padding: 0; + image: url(":/qss_icons/dark/rc/window_close.png"); +} + +QDockWidget::close-button:hover { + image: url(":/qss_icons/dark/rc/window_close_focus.png"); +} + +QDockWidget::close-button:pressed { + image: url(":/qss_icons/dark/rc/window_close_pressed.png"); +} + +QDockWidget::float-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + border: 0; + margin: 0; + padding: 0; + image: url(":/qss_icons/dark/rc/window_undock.png"); +} + +QDockWidget::float-button:hover { + image: url(":/qss_icons/dark/rc/window_undock_focus.png"); +} + +QDockWidget::float-button:pressed { + image: url(":/qss_icons/dark/rc/window_undock_pressed.png"); +} + +/* QTreeView QListView QTableView ----------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtreeview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview + +--------------------------------------------------------------------------- */ +QTreeView:branch:selected, QTreeView:branch:hover { + background: url(":/qss_icons/dark/rc/transparent.png"); +} + +QTreeView:branch:has-siblings:!adjoins-item { + border-image: url(":/qss_icons/dark/rc/branch_line.png") 0; +} + +QTreeView:branch:has-siblings:adjoins-item { + border-image: url(":/qss_icons/dark/rc/branch_more.png") 0; +} + +QTreeView:branch:!has-children:!has-siblings:adjoins-item { + border-image: url(":/qss_icons/dark/rc/branch_end.png") 0; +} + +QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings { + border-image: none; + image: url(":/qss_icons/dark/rc/branch_closed.png"); +} + +QTreeView:branch:open:has-children:!has-siblings, QTreeView:branch:open:has-children:has-siblings { + border-image: none; + image: url(":/qss_icons/dark/rc/branch_open.png"); +} + +QTreeView:branch:has-children:!has-siblings:closed:hover, QTreeView:branch:closed:has-children:has-siblings:hover { + image: url(":/qss_icons/dark/rc/branch_closed_focus.png"); +} + +QTreeView:branch:open:has-children:!has-siblings:hover, QTreeView:branch:open:has-children:has-siblings:hover { + image: url(":/qss_icons/dark/rc/branch_open_focus.png"); +} + +QTreeView::indicator:checked, +QListView::indicator:checked, +QTableView::indicator:checked, +QColumnView::indicator:checked { + image: url(":/qss_icons/dark/rc/checkbox_checked.png"); +} + +QTreeView::indicator:checked:hover, QTreeView::indicator:checked:focus, QTreeView::indicator:checked:pressed, +QListView::indicator:checked:hover, +QListView::indicator:checked:focus, +QListView::indicator:checked:pressed, +QTableView::indicator:checked:hover, +QTableView::indicator:checked:focus, +QTableView::indicator:checked:pressed, +QColumnView::indicator:checked:hover, +QColumnView::indicator:checked:focus, +QColumnView::indicator:checked:pressed { + image: url(":/qss_icons/dark/rc/checkbox_checked_focus.png"); +} + +QTreeView::indicator:unchecked, +QListView::indicator:unchecked, +QTableView::indicator:unchecked, +QColumnView::indicator:unchecked { + image: url(":/qss_icons/dark/rc/checkbox_unchecked.png"); +} + +QTreeView::indicator:unchecked:hover, QTreeView::indicator:unchecked:focus, QTreeView::indicator:unchecked:pressed, +QListView::indicator:unchecked:hover, +QListView::indicator:unchecked:focus, +QListView::indicator:unchecked:pressed, +QTableView::indicator:unchecked:hover, +QTableView::indicator:unchecked:focus, +QTableView::indicator:unchecked:pressed, +QColumnView::indicator:unchecked:hover, +QColumnView::indicator:unchecked:focus, +QColumnView::indicator:unchecked:pressed { + image: url(":/qss_icons/dark/rc/checkbox_unchecked_focus.png"); +} + +QTreeView::indicator:indeterminate, +QListView::indicator:indeterminate, +QTableView::indicator:indeterminate, +QColumnView::indicator:indeterminate { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate.png"); +} + +QTreeView::indicator:indeterminate:hover, QTreeView::indicator:indeterminate:focus, QTreeView::indicator:indeterminate:pressed, +QListView::indicator:indeterminate:hover, +QListView::indicator:indeterminate:focus, +QListView::indicator:indeterminate:pressed, +QTableView::indicator:indeterminate:hover, +QTableView::indicator:indeterminate:focus, +QTableView::indicator:indeterminate:pressed, +QColumnView::indicator:indeterminate:hover, +QColumnView::indicator:indeterminate:focus, +QColumnView::indicator:indeterminate:pressed { + image: url(":/qss_icons/dark/rc/checkbox_indeterminate_focus.png"); +} + +QTreeView, +QListView, +QTableView, +QColumnView { + background-color: #19232D; + border: 1px solid #455364; + color: #DFE1E2; + gridline-color: #455364; + border-radius: 4px; +} + +QTreeView:disabled, +QListView:disabled, +QTableView:disabled, +QColumnView:disabled { + background-color: #19232D; + color: #788D9C; +} + +QTreeView:selected, +QListView:selected, +QTableView:selected, +QColumnView:selected { + background-color: #346792; + color: #455364; +} + +QTreeView:focus, +QListView:focus, +QTableView:focus, +QColumnView:focus { + border: 1px solid #1A72BB; +} + +QTreeView::item:pressed, +QListView::item:pressed, +QTableView::item:pressed, +QColumnView::item:pressed { + background-color: #346792; +} + +QTreeView::item:selected:active, +QListView::item:selected:active, +QTableView::item:selected:active, +QColumnView::item:selected:active { + background-color: #346792; +} + +QTreeView::item:selected:!active, +QListView::item:selected:!active, +QTableView::item:selected:!active, +QColumnView::item:selected:!active { + color: #DFE1E2; + background-color: #37414F; +} + +QTreeView::item:!selected:hover, +QListView::item:!selected:hover, +QTableView::item:!selected:hover, +QColumnView::item:!selected:hover { + outline: 0; + color: #DFE1E2; + background-color: #37414F; +} + +QTableCornerButton::section { + background-color: #19232D; + border: 1px transparent #455364; + border-radius: 0px; +} + +/* QHeaderView ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview + +--------------------------------------------------------------------------- */ +QHeaderView { + background-color: #455364; + border: 0px transparent #455364; + padding: 0; + margin: 0; + border-radius: 0; +} + +QHeaderView:disabled { + background-color: #455364; + border: 1px transparent #455364; +} + +QHeaderView::section { + background-color: #455364; + color: #DFE1E2; + border-radius: 0; + text-align: left; + font-size: 13px; +} + +QHeaderView::section::horizontal { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-left: 1px solid #19232D; +} + +QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one { + border-left: 1px solid #455364; +} + +QHeaderView::section::horizontal:disabled { + color: #788D9C; +} + +QHeaderView::section::vertical { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-top: 1px solid #19232D; +} + +QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one { + border-top: 1px solid #455364; +} + +QHeaderView::section::vertical:disabled { + color: #788D9C; +} + +QHeaderView::down-arrow { + /* Those settings (border/width/height/background-color) solve bug */ + /* transparent arrow background and size */ + background-color: #455364; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url(":/qss_icons/dark/rc/arrow_down.png"); +} + +QHeaderView::up-arrow { + background-color: #455364; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url(":/qss_icons/dark/rc/arrow_up.png"); +} + +/* QToolBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbox + +--------------------------------------------------------------------------- */ +QToolBox { + padding: 0px; + border: 0px; + border: 1px solid #455364; +} + +QToolBox:selected { + padding: 0px; + border: 2px solid #346792; +} + +QToolBox::tab { + background-color: #19232D; + border: 1px solid #455364; + color: #DFE1E2; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QToolBox::tab:disabled { + color: #788D9C; +} + +QToolBox::tab:selected { + background-color: #60798B; + border-bottom: 2px solid #346792; +} + +QToolBox::tab:selected:disabled { + background-color: #455364; + border-bottom: 2px solid #26486B; +} + +QToolBox::tab:!selected { + background-color: #455364; + border-bottom: 2px solid #455364; +} + +QToolBox::tab:!selected:disabled { + background-color: #19232D; +} + +QToolBox::tab:hover { + border-color: #1A72BB; + border-bottom: 2px solid #1A72BB; +} + +QToolBox QScrollArea { + padding: 0px; + border: 0px; + background-color: #19232D; +} + +/* QFrame ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe +https://doc.qt.io/qt-5/qframe.html#-prop +https://doc.qt.io/qt-5/qframe.html#details +https://stackoverflow.com/questions/14581498/qt-stylesheet-for-hline-vline-color + +--------------------------------------------------------------------------- */ +/* (dot) .QFrame fix #141, #126, #123 */ +.QFrame { + border-radius: 4px; + border: 1px solid #455364; + /* No frame */ + /* HLine */ + /* HLine */ +} + +.QFrame[frameShape="0"] { + border-radius: 4px; + border: 1px transparent #455364; +} + +.QFrame[frameShape="4"] { + max-height: 2px; + border: none; + background-color: #455364; +} + +.QFrame[frameShape="5"] { + max-width: 2px; + border: none; + background-color: #455364; +} + +/* QSplitter -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsplitter + +--------------------------------------------------------------------------- */ +QSplitter { + background-color: #455364; + spacing: 0px; + padding: 0px; + margin: 0px; +} + +QSplitter::handle { + background-color: #455364; + border: 0px solid #19232D; + spacing: 0px; + padding: 1px; + margin: 0px; +} + +QSplitter::handle:hover { + background-color: #9DA9B5; +} + +QSplitter::handle:horizontal { + width: 5px; + image: url(":/qss_icons/dark/rc/line_vertical.png"); +} + +QSplitter::handle:vertical { + height: 5px; + image: url(":/qss_icons/dark/rc/line_horizontal.png"); +} + +/* QDateEdit, QDateTimeEdit ----------------------------------------------- + +--------------------------------------------------------------------------- */ +QDateEdit, QDateTimeEdit { + selection-background-color: #346792; + border-style: solid; + border: 1px solid #455364; + border-radius: 4px; + /* This fixes 103, 111 */ + padding-top: 2px; + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + min-width: 10px; +} + +QDateEdit:on, QDateTimeEdit:on { + selection-background-color: #346792; +} + +QDateEdit::drop-down, QDateTimeEdit::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid #455364; +} + +QDateEdit::down-arrow, QDateTimeEdit::down-arrow { + image: url(":/qss_icons/dark/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QDateEdit::down-arrow:on, QDateEdit::down-arrow:hover, QDateEdit::down-arrow:focus, QDateTimeEdit::down-arrow:on, QDateTimeEdit::down-arrow:hover, QDateTimeEdit::down-arrow:focus { + image: url(":/qss_icons/dark/rc/arrow_down.png"); +} + +QDateEdit QAbstractItemView, QDateTimeEdit QAbstractItemView { + background-color: #19232D; + border-radius: 4px; + border: 1px solid #455364; + selection-background-color: #346792; +} + +/* QAbstractView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractView:hover { + border: 1px solid #346792; + color: #DFE1E2; +} + +QAbstractView:selected { + background: #346792; + color: #455364; +} + +/* PlotWidget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +PlotWidget { + /* Fix cut labels in plots #134 */ + padding: 0px; +} diff --git a/src/qdarkstyle/dark/main.scss b/src/qdarkstyle/dark/main.scss new file mode 100644 index 000000000..dc40bc521 --- /dev/null +++ b/src/qdarkstyle/dark/main.scss @@ -0,0 +1,4 @@ +/* Light Style - QDarkStyleSheet ------------------------------------------ */ + +@import '_variables'; +@import '../qss/_styles'; diff --git a/src/qdarkstyle/dark/rc/.keep b/src/qdarkstyle/dark/rc/.keep new file mode 100644 index 000000000..8d1c8b69c --- /dev/null +++ b/src/qdarkstyle/dark/rc/.keep @@ -0,0 +1 @@ + diff --git a/src/qdarkstyle/dark/rc/arrow_down.png b/src/qdarkstyle/dark/rc/arrow_down.png new file mode 100644 index 000000000..412b76e6f Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_down.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_down@2x.png b/src/qdarkstyle/dark/rc/arrow_down@2x.png new file mode 100644 index 000000000..74d0099ec Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_down@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_down_disabled.png b/src/qdarkstyle/dark/rc/arrow_down_disabled.png new file mode 100644 index 000000000..972df9cd1 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_down_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_down_disabled@2x.png b/src/qdarkstyle/dark/rc/arrow_down_disabled@2x.png new file mode 100644 index 000000000..b0fb4ad11 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_down_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_down_focus.png b/src/qdarkstyle/dark/rc/arrow_down_focus.png new file mode 100644 index 000000000..22df2c525 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_down_focus.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_down_focus@2x.png b/src/qdarkstyle/dark/rc/arrow_down_focus@2x.png new file mode 100644 index 000000000..06b80be4b Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_down_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_down_pressed.png b/src/qdarkstyle/dark/rc/arrow_down_pressed.png new file mode 100644 index 000000000..50f41cc6f Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_down_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_down_pressed@2x.png b/src/qdarkstyle/dark/rc/arrow_down_pressed@2x.png new file mode 100644 index 000000000..ef20f2cb0 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_down_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_left.png b/src/qdarkstyle/dark/rc/arrow_left.png new file mode 100644 index 000000000..b7aeac5f8 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_left.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_left@2x.png b/src/qdarkstyle/dark/rc/arrow_left@2x.png new file mode 100644 index 000000000..fef91a8c8 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_left@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_left_disabled.png b/src/qdarkstyle/dark/rc/arrow_left_disabled.png new file mode 100644 index 000000000..79b1f0565 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_left_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_left_disabled@2x.png b/src/qdarkstyle/dark/rc/arrow_left_disabled@2x.png new file mode 100644 index 000000000..144fdb5f8 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_left_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_left_focus.png b/src/qdarkstyle/dark/rc/arrow_left_focus.png new file mode 100644 index 000000000..ef0284994 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_left_focus.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_left_focus@2x.png b/src/qdarkstyle/dark/rc/arrow_left_focus@2x.png new file mode 100644 index 000000000..ca821dcac Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_left_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_left_pressed.png b/src/qdarkstyle/dark/rc/arrow_left_pressed.png new file mode 100644 index 000000000..c723d3bff Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_left_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_left_pressed@2x.png b/src/qdarkstyle/dark/rc/arrow_left_pressed@2x.png new file mode 100644 index 000000000..f0bcb5229 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_left_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_right.png b/src/qdarkstyle/dark/rc/arrow_right.png new file mode 100644 index 000000000..78d67f2db Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_right.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_right@2x.png b/src/qdarkstyle/dark/rc/arrow_right@2x.png new file mode 100644 index 000000000..ce0a8faeb Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_right@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_right_disabled.png b/src/qdarkstyle/dark/rc/arrow_right_disabled.png new file mode 100644 index 000000000..88da1f980 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_right_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_right_disabled@2x.png b/src/qdarkstyle/dark/rc/arrow_right_disabled@2x.png new file mode 100644 index 000000000..5351587e3 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_right_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_right_focus.png b/src/qdarkstyle/dark/rc/arrow_right_focus.png new file mode 100644 index 000000000..92271a8ed Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_right_focus.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_right_focus@2x.png b/src/qdarkstyle/dark/rc/arrow_right_focus@2x.png new file mode 100644 index 000000000..d6c31bdda Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_right_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_right_pressed.png b/src/qdarkstyle/dark/rc/arrow_right_pressed.png new file mode 100644 index 000000000..22902cf4f Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_right_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_right_pressed@2x.png b/src/qdarkstyle/dark/rc/arrow_right_pressed@2x.png new file mode 100644 index 000000000..f6181eb64 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_right_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_up.png b/src/qdarkstyle/dark/rc/arrow_up.png new file mode 100644 index 000000000..50321f29b Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_up.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_up@2x.png b/src/qdarkstyle/dark/rc/arrow_up@2x.png new file mode 100644 index 000000000..8c73c3be3 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_up@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_up_disabled.png b/src/qdarkstyle/dark/rc/arrow_up_disabled.png new file mode 100644 index 000000000..48054a8ae Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_up_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_up_disabled@2x.png b/src/qdarkstyle/dark/rc/arrow_up_disabled@2x.png new file mode 100644 index 000000000..e99960594 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_up_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_up_focus.png b/src/qdarkstyle/dark/rc/arrow_up_focus.png new file mode 100644 index 000000000..567ec8bdf Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_up_focus.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_up_focus@2x.png b/src/qdarkstyle/dark/rc/arrow_up_focus@2x.png new file mode 100644 index 000000000..f6998104b Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_up_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_up_pressed.png b/src/qdarkstyle/dark/rc/arrow_up_pressed.png new file mode 100644 index 000000000..223320106 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_up_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/arrow_up_pressed@2x.png b/src/qdarkstyle/dark/rc/arrow_up_pressed@2x.png new file mode 100644 index 000000000..9954cf519 Binary files /dev/null and b/src/qdarkstyle/dark/rc/arrow_up_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/base_icon.png b/src/qdarkstyle/dark/rc/base_icon.png new file mode 100644 index 000000000..bb00857a4 Binary files /dev/null and b/src/qdarkstyle/dark/rc/base_icon.png differ diff --git a/src/qdarkstyle/dark/rc/base_icon@2x.png b/src/qdarkstyle/dark/rc/base_icon@2x.png new file mode 100644 index 000000000..bc4ab78a2 Binary files /dev/null and b/src/qdarkstyle/dark/rc/base_icon@2x.png differ diff --git a/src/qdarkstyle/dark/rc/base_icon_disabled.png b/src/qdarkstyle/dark/rc/base_icon_disabled.png new file mode 100644 index 000000000..bb00857a4 Binary files /dev/null and b/src/qdarkstyle/dark/rc/base_icon_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/base_icon_disabled@2x.png b/src/qdarkstyle/dark/rc/base_icon_disabled@2x.png new file mode 100644 index 000000000..bc4ab78a2 Binary files /dev/null and b/src/qdarkstyle/dark/rc/base_icon_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/base_icon_focus.png b/src/qdarkstyle/dark/rc/base_icon_focus.png new file mode 100644 index 000000000..bb00857a4 Binary files /dev/null and b/src/qdarkstyle/dark/rc/base_icon_focus.png differ diff --git a/src/qdarkstyle/dark/rc/base_icon_focus@2x.png b/src/qdarkstyle/dark/rc/base_icon_focus@2x.png new file mode 100644 index 000000000..bc4ab78a2 Binary files /dev/null and b/src/qdarkstyle/dark/rc/base_icon_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/base_icon_pressed.png b/src/qdarkstyle/dark/rc/base_icon_pressed.png new file mode 100644 index 000000000..bb00857a4 Binary files /dev/null and b/src/qdarkstyle/dark/rc/base_icon_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/base_icon_pressed@2x.png b/src/qdarkstyle/dark/rc/base_icon_pressed@2x.png new file mode 100644 index 000000000..bc4ab78a2 Binary files /dev/null and b/src/qdarkstyle/dark/rc/base_icon_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_closed.png b/src/qdarkstyle/dark/rc/branch_closed.png new file mode 100644 index 000000000..4c152b795 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_closed.png differ diff --git a/src/qdarkstyle/dark/rc/branch_closed@2x.png b/src/qdarkstyle/dark/rc/branch_closed@2x.png new file mode 100644 index 000000000..a641a550b Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_closed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_closed_disabled.png b/src/qdarkstyle/dark/rc/branch_closed_disabled.png new file mode 100644 index 000000000..165fae29b Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_closed_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/branch_closed_disabled@2x.png b/src/qdarkstyle/dark/rc/branch_closed_disabled@2x.png new file mode 100644 index 000000000..421e8e094 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_closed_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_closed_focus.png b/src/qdarkstyle/dark/rc/branch_closed_focus.png new file mode 100644 index 000000000..ccc249a59 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_closed_focus.png differ diff --git a/src/qdarkstyle/dark/rc/branch_closed_focus@2x.png b/src/qdarkstyle/dark/rc/branch_closed_focus@2x.png new file mode 100644 index 000000000..88dd0a62b Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_closed_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_closed_pressed.png b/src/qdarkstyle/dark/rc/branch_closed_pressed.png new file mode 100644 index 000000000..2aae68a0a Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_closed_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/branch_closed_pressed@2x.png b/src/qdarkstyle/dark/rc/branch_closed_pressed@2x.png new file mode 100644 index 000000000..3849a7ff0 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_closed_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_end.png b/src/qdarkstyle/dark/rc/branch_end.png new file mode 100644 index 000000000..f92994650 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_end.png differ diff --git a/src/qdarkstyle/dark/rc/branch_end@2x.png b/src/qdarkstyle/dark/rc/branch_end@2x.png new file mode 100644 index 000000000..582832220 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_end@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_end_disabled.png b/src/qdarkstyle/dark/rc/branch_end_disabled.png new file mode 100644 index 000000000..bb4344c78 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_end_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/branch_end_disabled@2x.png b/src/qdarkstyle/dark/rc/branch_end_disabled@2x.png new file mode 100644 index 000000000..8feb46d46 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_end_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_end_focus.png b/src/qdarkstyle/dark/rc/branch_end_focus.png new file mode 100644 index 000000000..ff713cf5f Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_end_focus.png differ diff --git a/src/qdarkstyle/dark/rc/branch_end_focus@2x.png b/src/qdarkstyle/dark/rc/branch_end_focus@2x.png new file mode 100644 index 000000000..0bd0e4ba3 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_end_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_end_pressed.png b/src/qdarkstyle/dark/rc/branch_end_pressed.png new file mode 100644 index 000000000..2020162f2 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_end_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/branch_end_pressed@2x.png b/src/qdarkstyle/dark/rc/branch_end_pressed@2x.png new file mode 100644 index 000000000..2a5c4fabf Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_end_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_line.png b/src/qdarkstyle/dark/rc/branch_line.png new file mode 100644 index 000000000..2e8c72ab6 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_line.png differ diff --git a/src/qdarkstyle/dark/rc/branch_line@2x.png b/src/qdarkstyle/dark/rc/branch_line@2x.png new file mode 100644 index 000000000..c8f07af31 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_line@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_line_disabled.png b/src/qdarkstyle/dark/rc/branch_line_disabled.png new file mode 100644 index 000000000..9c8c47b3d Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_line_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/branch_line_disabled@2x.png b/src/qdarkstyle/dark/rc/branch_line_disabled@2x.png new file mode 100644 index 000000000..9b868f2a5 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_line_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_line_focus.png b/src/qdarkstyle/dark/rc/branch_line_focus.png new file mode 100644 index 000000000..c2ab3e19e Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_line_focus.png differ diff --git a/src/qdarkstyle/dark/rc/branch_line_focus@2x.png b/src/qdarkstyle/dark/rc/branch_line_focus@2x.png new file mode 100644 index 000000000..512ee13a2 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_line_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_line_pressed.png b/src/qdarkstyle/dark/rc/branch_line_pressed.png new file mode 100644 index 000000000..3ca15c5d0 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_line_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/branch_line_pressed@2x.png b/src/qdarkstyle/dark/rc/branch_line_pressed@2x.png new file mode 100644 index 000000000..368553102 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_line_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_more.png b/src/qdarkstyle/dark/rc/branch_more.png new file mode 100644 index 000000000..976354bc4 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_more.png differ diff --git a/src/qdarkstyle/dark/rc/branch_more@2x.png b/src/qdarkstyle/dark/rc/branch_more@2x.png new file mode 100644 index 000000000..9c1ab07d0 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_more@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_more_disabled.png b/src/qdarkstyle/dark/rc/branch_more_disabled.png new file mode 100644 index 000000000..29d99a63e Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_more_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/branch_more_disabled@2x.png b/src/qdarkstyle/dark/rc/branch_more_disabled@2x.png new file mode 100644 index 000000000..aba830362 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_more_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_more_focus.png b/src/qdarkstyle/dark/rc/branch_more_focus.png new file mode 100644 index 000000000..20a6f27b8 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_more_focus.png differ diff --git a/src/qdarkstyle/dark/rc/branch_more_focus@2x.png b/src/qdarkstyle/dark/rc/branch_more_focus@2x.png new file mode 100644 index 000000000..6f42eea84 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_more_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_more_pressed.png b/src/qdarkstyle/dark/rc/branch_more_pressed.png new file mode 100644 index 000000000..4f4d9fb91 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_more_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/branch_more_pressed@2x.png b/src/qdarkstyle/dark/rc/branch_more_pressed@2x.png new file mode 100644 index 000000000..5f18f8341 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_more_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_open.png b/src/qdarkstyle/dark/rc/branch_open.png new file mode 100644 index 000000000..fdf0f8b43 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_open.png differ diff --git a/src/qdarkstyle/dark/rc/branch_open@2x.png b/src/qdarkstyle/dark/rc/branch_open@2x.png new file mode 100644 index 000000000..703cd6af3 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_open@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_open_disabled.png b/src/qdarkstyle/dark/rc/branch_open_disabled.png new file mode 100644 index 000000000..8328e84d7 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_open_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/branch_open_disabled@2x.png b/src/qdarkstyle/dark/rc/branch_open_disabled@2x.png new file mode 100644 index 000000000..d8d0faecb Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_open_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_open_focus.png b/src/qdarkstyle/dark/rc/branch_open_focus.png new file mode 100644 index 000000000..711ce0979 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_open_focus.png differ diff --git a/src/qdarkstyle/dark/rc/branch_open_focus@2x.png b/src/qdarkstyle/dark/rc/branch_open_focus@2x.png new file mode 100644 index 000000000..b38e17a33 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_open_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/branch_open_pressed.png b/src/qdarkstyle/dark/rc/branch_open_pressed.png new file mode 100644 index 000000000..441c27344 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_open_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/branch_open_pressed@2x.png b/src/qdarkstyle/dark/rc/branch_open_pressed@2x.png new file mode 100644 index 000000000..0e43e8b73 Binary files /dev/null and b/src/qdarkstyle/dark/rc/branch_open_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_checked.png b/src/qdarkstyle/dark/rc/checkbox_checked.png new file mode 100644 index 000000000..3687e56c0 Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_checked.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_checked@2x.png b/src/qdarkstyle/dark/rc/checkbox_checked@2x.png new file mode 100644 index 000000000..e7a6b1afe Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_checked@2x.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_checked_disabled.png b/src/qdarkstyle/dark/rc/checkbox_checked_disabled.png new file mode 100644 index 000000000..e3cb2f127 Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_checked_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_checked_disabled@2x.png b/src/qdarkstyle/dark/rc/checkbox_checked_disabled@2x.png new file mode 100644 index 000000000..0c8c28a24 Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_checked_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_checked_focus.png b/src/qdarkstyle/dark/rc/checkbox_checked_focus.png new file mode 100644 index 000000000..58982ce87 Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_checked_focus.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_checked_focus@2x.png b/src/qdarkstyle/dark/rc/checkbox_checked_focus@2x.png new file mode 100644 index 000000000..ba33ba4fb Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_checked_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_checked_pressed.png b/src/qdarkstyle/dark/rc/checkbox_checked_pressed.png new file mode 100644 index 000000000..f104bb240 Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_checked_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_checked_pressed@2x.png b/src/qdarkstyle/dark/rc/checkbox_checked_pressed@2x.png new file mode 100644 index 000000000..bb972d68f Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_checked_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_indeterminate.png b/src/qdarkstyle/dark/rc/checkbox_indeterminate.png new file mode 100644 index 000000000..8159551de Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_indeterminate.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_indeterminate@2x.png b/src/qdarkstyle/dark/rc/checkbox_indeterminate@2x.png new file mode 100644 index 000000000..75864b46d Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_indeterminate@2x.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_indeterminate_disabled.png b/src/qdarkstyle/dark/rc/checkbox_indeterminate_disabled.png new file mode 100644 index 000000000..181625a00 Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_indeterminate_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_indeterminate_disabled@2x.png b/src/qdarkstyle/dark/rc/checkbox_indeterminate_disabled@2x.png new file mode 100644 index 000000000..0d32c78f3 Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_indeterminate_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_indeterminate_focus.png b/src/qdarkstyle/dark/rc/checkbox_indeterminate_focus.png new file mode 100644 index 000000000..d7b19f61a Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_indeterminate_focus.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_indeterminate_focus@2x.png b/src/qdarkstyle/dark/rc/checkbox_indeterminate_focus@2x.png new file mode 100644 index 000000000..d6403ca42 Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_indeterminate_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_indeterminate_pressed.png b/src/qdarkstyle/dark/rc/checkbox_indeterminate_pressed.png new file mode 100644 index 000000000..37f46ca3d Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_indeterminate_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_indeterminate_pressed@2x.png b/src/qdarkstyle/dark/rc/checkbox_indeterminate_pressed@2x.png new file mode 100644 index 000000000..aa7493edc Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_indeterminate_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_unchecked.png b/src/qdarkstyle/dark/rc/checkbox_unchecked.png new file mode 100644 index 000000000..e363ed620 Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_unchecked.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_unchecked@2x.png b/src/qdarkstyle/dark/rc/checkbox_unchecked@2x.png new file mode 100644 index 000000000..520f5e2a2 Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_unchecked@2x.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_unchecked_disabled.png b/src/qdarkstyle/dark/rc/checkbox_unchecked_disabled.png new file mode 100644 index 000000000..066185ee7 Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_unchecked_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_unchecked_disabled@2x.png b/src/qdarkstyle/dark/rc/checkbox_unchecked_disabled@2x.png new file mode 100644 index 000000000..9c80ad75a Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_unchecked_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_unchecked_focus.png b/src/qdarkstyle/dark/rc/checkbox_unchecked_focus.png new file mode 100644 index 000000000..366b868de Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_unchecked_focus.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_unchecked_focus@2x.png b/src/qdarkstyle/dark/rc/checkbox_unchecked_focus@2x.png new file mode 100644 index 000000000..4ab217356 Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_unchecked_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_unchecked_pressed.png b/src/qdarkstyle/dark/rc/checkbox_unchecked_pressed.png new file mode 100644 index 000000000..d9a0bf71c Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_unchecked_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/checkbox_unchecked_pressed@2x.png b/src/qdarkstyle/dark/rc/checkbox_unchecked_pressed@2x.png new file mode 100644 index 000000000..9e2b0515e Binary files /dev/null and b/src/qdarkstyle/dark/rc/checkbox_unchecked_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/line_horizontal.png b/src/qdarkstyle/dark/rc/line_horizontal.png new file mode 100644 index 000000000..4f88ddf7b Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_horizontal.png differ diff --git a/src/qdarkstyle/dark/rc/line_horizontal@2x.png b/src/qdarkstyle/dark/rc/line_horizontal@2x.png new file mode 100644 index 000000000..63be00c16 Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_horizontal@2x.png differ diff --git a/src/qdarkstyle/dark/rc/line_horizontal_disabled.png b/src/qdarkstyle/dark/rc/line_horizontal_disabled.png new file mode 100644 index 000000000..941f14a38 Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_horizontal_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/line_horizontal_disabled@2x.png b/src/qdarkstyle/dark/rc/line_horizontal_disabled@2x.png new file mode 100644 index 000000000..972fa0800 Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_horizontal_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/line_horizontal_focus.png b/src/qdarkstyle/dark/rc/line_horizontal_focus.png new file mode 100644 index 000000000..221fd4607 Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_horizontal_focus.png differ diff --git a/src/qdarkstyle/dark/rc/line_horizontal_focus@2x.png b/src/qdarkstyle/dark/rc/line_horizontal_focus@2x.png new file mode 100644 index 000000000..7e6505cae Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_horizontal_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/line_horizontal_pressed.png b/src/qdarkstyle/dark/rc/line_horizontal_pressed.png new file mode 100644 index 000000000..9f9113323 Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_horizontal_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/line_horizontal_pressed@2x.png b/src/qdarkstyle/dark/rc/line_horizontal_pressed@2x.png new file mode 100644 index 000000000..465680c3b Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_horizontal_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/line_vertical.png b/src/qdarkstyle/dark/rc/line_vertical.png new file mode 100644 index 000000000..6ee62c156 Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_vertical.png differ diff --git a/src/qdarkstyle/dark/rc/line_vertical@2x.png b/src/qdarkstyle/dark/rc/line_vertical@2x.png new file mode 100644 index 000000000..d65e74c62 Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_vertical@2x.png differ diff --git a/src/qdarkstyle/dark/rc/line_vertical_disabled.png b/src/qdarkstyle/dark/rc/line_vertical_disabled.png new file mode 100644 index 000000000..c7c4c8959 Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_vertical_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/line_vertical_disabled@2x.png b/src/qdarkstyle/dark/rc/line_vertical_disabled@2x.png new file mode 100644 index 000000000..b052de522 Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_vertical_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/line_vertical_focus.png b/src/qdarkstyle/dark/rc/line_vertical_focus.png new file mode 100644 index 000000000..36baa0936 Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_vertical_focus.png differ diff --git a/src/qdarkstyle/dark/rc/line_vertical_focus@2x.png b/src/qdarkstyle/dark/rc/line_vertical_focus@2x.png new file mode 100644 index 000000000..24a2b771c Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_vertical_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/line_vertical_pressed.png b/src/qdarkstyle/dark/rc/line_vertical_pressed.png new file mode 100644 index 000000000..60e357446 Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_vertical_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/line_vertical_pressed@2x.png b/src/qdarkstyle/dark/rc/line_vertical_pressed@2x.png new file mode 100644 index 000000000..c9494051c Binary files /dev/null and b/src/qdarkstyle/dark/rc/line_vertical_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/radio_checked.png b/src/qdarkstyle/dark/rc/radio_checked.png new file mode 100644 index 000000000..acb890155 Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_checked.png differ diff --git a/src/qdarkstyle/dark/rc/radio_checked@2x.png b/src/qdarkstyle/dark/rc/radio_checked@2x.png new file mode 100644 index 000000000..e19047621 Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_checked@2x.png differ diff --git a/src/qdarkstyle/dark/rc/radio_checked_disabled.png b/src/qdarkstyle/dark/rc/radio_checked_disabled.png new file mode 100644 index 000000000..49df43922 Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_checked_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/radio_checked_disabled@2x.png b/src/qdarkstyle/dark/rc/radio_checked_disabled@2x.png new file mode 100644 index 000000000..a9ffd40ce Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_checked_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/radio_checked_focus.png b/src/qdarkstyle/dark/rc/radio_checked_focus.png new file mode 100644 index 000000000..4bd472e16 Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_checked_focus.png differ diff --git a/src/qdarkstyle/dark/rc/radio_checked_focus@2x.png b/src/qdarkstyle/dark/rc/radio_checked_focus@2x.png new file mode 100644 index 000000000..aed5e0c94 Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_checked_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/radio_checked_pressed.png b/src/qdarkstyle/dark/rc/radio_checked_pressed.png new file mode 100644 index 000000000..ebb323b8c Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_checked_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/radio_checked_pressed@2x.png b/src/qdarkstyle/dark/rc/radio_checked_pressed@2x.png new file mode 100644 index 000000000..ffe0fd851 Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_checked_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/radio_unchecked.png b/src/qdarkstyle/dark/rc/radio_unchecked.png new file mode 100644 index 000000000..9ffddc4a0 Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_unchecked.png differ diff --git a/src/qdarkstyle/dark/rc/radio_unchecked@2x.png b/src/qdarkstyle/dark/rc/radio_unchecked@2x.png new file mode 100644 index 000000000..2160a32ed Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_unchecked@2x.png differ diff --git a/src/qdarkstyle/dark/rc/radio_unchecked_disabled.png b/src/qdarkstyle/dark/rc/radio_unchecked_disabled.png new file mode 100644 index 000000000..7ddff642d Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_unchecked_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/radio_unchecked_disabled@2x.png b/src/qdarkstyle/dark/rc/radio_unchecked_disabled@2x.png new file mode 100644 index 000000000..4de5d0d2d Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_unchecked_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/radio_unchecked_focus.png b/src/qdarkstyle/dark/rc/radio_unchecked_focus.png new file mode 100644 index 000000000..e62b996b1 Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_unchecked_focus.png differ diff --git a/src/qdarkstyle/dark/rc/radio_unchecked_focus@2x.png b/src/qdarkstyle/dark/rc/radio_unchecked_focus@2x.png new file mode 100644 index 000000000..eaf7bc26b Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_unchecked_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/radio_unchecked_pressed.png b/src/qdarkstyle/dark/rc/radio_unchecked_pressed.png new file mode 100644 index 000000000..8aaa343e8 Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_unchecked_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/radio_unchecked_pressed@2x.png b/src/qdarkstyle/dark/rc/radio_unchecked_pressed@2x.png new file mode 100644 index 000000000..ba4f83b91 Binary files /dev/null and b/src/qdarkstyle/dark/rc/radio_unchecked_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_horizontal.png b/src/qdarkstyle/dark/rc/toolbar_move_horizontal.png new file mode 100644 index 000000000..fa449d6ee Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_horizontal.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_horizontal@2x.png b/src/qdarkstyle/dark/rc/toolbar_move_horizontal@2x.png new file mode 100644 index 000000000..682575ee2 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_horizontal@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled.png b/src/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled.png new file mode 100644 index 000000000..568b0fbe1 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled@2x.png b/src/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled@2x.png new file mode 100644 index 000000000..4d15f1478 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_horizontal_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_horizontal_focus.png b/src/qdarkstyle/dark/rc/toolbar_move_horizontal_focus.png new file mode 100644 index 000000000..cdb96bfb9 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_horizontal_focus.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_horizontal_focus@2x.png b/src/qdarkstyle/dark/rc/toolbar_move_horizontal_focus@2x.png new file mode 100644 index 000000000..23e06a015 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_horizontal_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed.png b/src/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed.png new file mode 100644 index 000000000..9ce6f8d89 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed@2x.png b/src/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed@2x.png new file mode 100644 index 000000000..4d8e53e8e Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_horizontal_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_vertical.png b/src/qdarkstyle/dark/rc/toolbar_move_vertical.png new file mode 100644 index 000000000..bbc8abb1f Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_vertical.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_vertical@2x.png b/src/qdarkstyle/dark/rc/toolbar_move_vertical@2x.png new file mode 100644 index 000000000..136ebae2c Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_vertical@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_vertical_disabled.png b/src/qdarkstyle/dark/rc/toolbar_move_vertical_disabled.png new file mode 100644 index 000000000..37453ac25 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_vertical_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_vertical_disabled@2x.png b/src/qdarkstyle/dark/rc/toolbar_move_vertical_disabled@2x.png new file mode 100644 index 000000000..cca8f6d96 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_vertical_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_vertical_focus.png b/src/qdarkstyle/dark/rc/toolbar_move_vertical_focus.png new file mode 100644 index 000000000..b54877181 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_vertical_focus.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_vertical_focus@2x.png b/src/qdarkstyle/dark/rc/toolbar_move_vertical_focus@2x.png new file mode 100644 index 000000000..d4dd49dec Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_vertical_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_vertical_pressed.png b/src/qdarkstyle/dark/rc/toolbar_move_vertical_pressed.png new file mode 100644 index 000000000..768ebaf4c Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_vertical_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_move_vertical_pressed@2x.png b/src/qdarkstyle/dark/rc/toolbar_move_vertical_pressed@2x.png new file mode 100644 index 000000000..2f170ffd8 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_move_vertical_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_horizontal.png b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal.png new file mode 100644 index 000000000..01e350132 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_horizontal@2x.png b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal@2x.png new file mode 100644 index 000000000..68d768e5e Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled.png b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled.png new file mode 100644 index 000000000..f8796f9e6 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled@2x.png b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled@2x.png new file mode 100644 index 000000000..1d9f20421 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus.png b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus.png new file mode 100644 index 000000000..b592e61c1 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus@2x.png b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus@2x.png new file mode 100644 index 000000000..a593a7e76 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed.png b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed.png new file mode 100644 index 000000000..a806257e0 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed@2x.png b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed@2x.png new file mode 100644 index 000000000..e1e8e3c14 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_horizontal_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_vertical.png b/src/qdarkstyle/dark/rc/toolbar_separator_vertical.png new file mode 100644 index 000000000..2a14f5cbd Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_vertical.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_vertical@2x.png b/src/qdarkstyle/dark/rc/toolbar_separator_vertical@2x.png new file mode 100644 index 000000000..35371feea Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_vertical@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled.png b/src/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled.png new file mode 100644 index 000000000..48b2657f5 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled@2x.png b/src/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled@2x.png new file mode 100644 index 000000000..a2173c5ee Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_vertical_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_vertical_focus.png b/src/qdarkstyle/dark/rc/toolbar_separator_vertical_focus.png new file mode 100644 index 000000000..e31c694b0 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_vertical_focus.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_vertical_focus@2x.png b/src/qdarkstyle/dark/rc/toolbar_separator_vertical_focus@2x.png new file mode 100644 index 000000000..ce743cc86 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_vertical_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed.png b/src/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed.png new file mode 100644 index 000000000..4ee7aaaab Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed@2x.png b/src/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed@2x.png new file mode 100644 index 000000000..d8bf93bf6 Binary files /dev/null and b/src/qdarkstyle/dark/rc/toolbar_separator_vertical_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/transparent.png b/src/qdarkstyle/dark/rc/transparent.png new file mode 100644 index 000000000..67753617f Binary files /dev/null and b/src/qdarkstyle/dark/rc/transparent.png differ diff --git a/src/qdarkstyle/dark/rc/transparent@2x.png b/src/qdarkstyle/dark/rc/transparent@2x.png new file mode 100644 index 000000000..4012944b5 Binary files /dev/null and b/src/qdarkstyle/dark/rc/transparent@2x.png differ diff --git a/src/qdarkstyle/dark/rc/transparent_disabled.png b/src/qdarkstyle/dark/rc/transparent_disabled.png new file mode 100644 index 000000000..67753617f Binary files /dev/null and b/src/qdarkstyle/dark/rc/transparent_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/transparent_disabled@2x.png b/src/qdarkstyle/dark/rc/transparent_disabled@2x.png new file mode 100644 index 000000000..4012944b5 Binary files /dev/null and b/src/qdarkstyle/dark/rc/transparent_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/transparent_focus.png b/src/qdarkstyle/dark/rc/transparent_focus.png new file mode 100644 index 000000000..67753617f Binary files /dev/null and b/src/qdarkstyle/dark/rc/transparent_focus.png differ diff --git a/src/qdarkstyle/dark/rc/transparent_focus@2x.png b/src/qdarkstyle/dark/rc/transparent_focus@2x.png new file mode 100644 index 000000000..4012944b5 Binary files /dev/null and b/src/qdarkstyle/dark/rc/transparent_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/transparent_pressed.png b/src/qdarkstyle/dark/rc/transparent_pressed.png new file mode 100644 index 000000000..67753617f Binary files /dev/null and b/src/qdarkstyle/dark/rc/transparent_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/transparent_pressed@2x.png b/src/qdarkstyle/dark/rc/transparent_pressed@2x.png new file mode 100644 index 000000000..4012944b5 Binary files /dev/null and b/src/qdarkstyle/dark/rc/transparent_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_close.png b/src/qdarkstyle/dark/rc/window_close.png new file mode 100644 index 000000000..0b67d3bcc Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_close.png differ diff --git a/src/qdarkstyle/dark/rc/window_close@2x.png b/src/qdarkstyle/dark/rc/window_close@2x.png new file mode 100644 index 000000000..bb8ac7da5 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_close@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_close_disabled.png b/src/qdarkstyle/dark/rc/window_close_disabled.png new file mode 100644 index 000000000..46de804b8 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_close_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/window_close_disabled@2x.png b/src/qdarkstyle/dark/rc/window_close_disabled@2x.png new file mode 100644 index 000000000..8e4cd15d8 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_close_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_close_focus.png b/src/qdarkstyle/dark/rc/window_close_focus.png new file mode 100644 index 000000000..bb7d8c511 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_close_focus.png differ diff --git a/src/qdarkstyle/dark/rc/window_close_focus@2x.png b/src/qdarkstyle/dark/rc/window_close_focus@2x.png new file mode 100644 index 000000000..692ce24f2 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_close_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_close_pressed.png b/src/qdarkstyle/dark/rc/window_close_pressed.png new file mode 100644 index 000000000..53ae7f38e Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_close_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/window_close_pressed@2x.png b/src/qdarkstyle/dark/rc/window_close_pressed@2x.png new file mode 100644 index 000000000..e02b12292 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_close_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_grip.png b/src/qdarkstyle/dark/rc/window_grip.png new file mode 100644 index 000000000..db9ccb877 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_grip.png differ diff --git a/src/qdarkstyle/dark/rc/window_grip@2x.png b/src/qdarkstyle/dark/rc/window_grip@2x.png new file mode 100644 index 000000000..30b0639f4 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_grip@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_grip_disabled.png b/src/qdarkstyle/dark/rc/window_grip_disabled.png new file mode 100644 index 000000000..97c0e0f90 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_grip_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/window_grip_disabled@2x.png b/src/qdarkstyle/dark/rc/window_grip_disabled@2x.png new file mode 100644 index 000000000..7a3d8de6d Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_grip_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_grip_focus.png b/src/qdarkstyle/dark/rc/window_grip_focus.png new file mode 100644 index 000000000..99b27c9ce Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_grip_focus.png differ diff --git a/src/qdarkstyle/dark/rc/window_grip_focus@2x.png b/src/qdarkstyle/dark/rc/window_grip_focus@2x.png new file mode 100644 index 000000000..833cb90a9 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_grip_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_grip_pressed.png b/src/qdarkstyle/dark/rc/window_grip_pressed.png new file mode 100644 index 000000000..afea9749e Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_grip_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/window_grip_pressed@2x.png b/src/qdarkstyle/dark/rc/window_grip_pressed@2x.png new file mode 100644 index 000000000..c1c1a0e4b Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_grip_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_minimize.png b/src/qdarkstyle/dark/rc/window_minimize.png new file mode 100644 index 000000000..d8c54ebf2 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_minimize.png differ diff --git a/src/qdarkstyle/dark/rc/window_minimize@2x.png b/src/qdarkstyle/dark/rc/window_minimize@2x.png new file mode 100644 index 000000000..5421a3690 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_minimize@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_minimize_disabled.png b/src/qdarkstyle/dark/rc/window_minimize_disabled.png new file mode 100644 index 000000000..cc51ed0ee Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_minimize_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/window_minimize_disabled@2x.png b/src/qdarkstyle/dark/rc/window_minimize_disabled@2x.png new file mode 100644 index 000000000..c1676469f Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_minimize_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_minimize_focus.png b/src/qdarkstyle/dark/rc/window_minimize_focus.png new file mode 100644 index 000000000..1dcd083c0 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_minimize_focus.png differ diff --git a/src/qdarkstyle/dark/rc/window_minimize_focus@2x.png b/src/qdarkstyle/dark/rc/window_minimize_focus@2x.png new file mode 100644 index 000000000..2a4c868e0 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_minimize_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_minimize_pressed.png b/src/qdarkstyle/dark/rc/window_minimize_pressed.png new file mode 100644 index 000000000..0bb532126 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_minimize_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/window_minimize_pressed@2x.png b/src/qdarkstyle/dark/rc/window_minimize_pressed@2x.png new file mode 100644 index 000000000..5a515c806 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_minimize_pressed@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_undock.png b/src/qdarkstyle/dark/rc/window_undock.png new file mode 100644 index 000000000..d1f454259 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_undock.png differ diff --git a/src/qdarkstyle/dark/rc/window_undock@2x.png b/src/qdarkstyle/dark/rc/window_undock@2x.png new file mode 100644 index 000000000..f0efa3429 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_undock@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_undock_disabled.png b/src/qdarkstyle/dark/rc/window_undock_disabled.png new file mode 100644 index 000000000..6a609492b Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_undock_disabled.png differ diff --git a/src/qdarkstyle/dark/rc/window_undock_disabled@2x.png b/src/qdarkstyle/dark/rc/window_undock_disabled@2x.png new file mode 100644 index 000000000..c2e1b8fa7 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_undock_disabled@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_undock_focus.png b/src/qdarkstyle/dark/rc/window_undock_focus.png new file mode 100644 index 000000000..d6eebbdc2 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_undock_focus.png differ diff --git a/src/qdarkstyle/dark/rc/window_undock_focus@2x.png b/src/qdarkstyle/dark/rc/window_undock_focus@2x.png new file mode 100644 index 000000000..1aef06053 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_undock_focus@2x.png differ diff --git a/src/qdarkstyle/dark/rc/window_undock_pressed.png b/src/qdarkstyle/dark/rc/window_undock_pressed.png new file mode 100644 index 000000000..8b6beb19e Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_undock_pressed.png differ diff --git a/src/qdarkstyle/dark/rc/window_undock_pressed@2x.png b/src/qdarkstyle/dark/rc/window_undock_pressed@2x.png new file mode 100644 index 000000000..677ded425 Binary files /dev/null and b/src/qdarkstyle/dark/rc/window_undock_pressed@2x.png differ diff --git a/src/qdarkstyle/light/_variables.scss b/src/qdarkstyle/light/_variables.scss new file mode 100644 index 000000000..a341ec5e3 --- /dev/null +++ b/src/qdarkstyle/light/_variables.scss @@ -0,0 +1,33 @@ +// --------------------------------------------------------------------------- +// +// WARNING! File created programmatically. All changes made in this file will be lost! +// +// Created by the qtsass compiler v0.3.0 +// +// The definitions are in the "qdarkstyle.palette" module +// +//---------------------------------------------------------------------------- +$ID: 'light'; +$COLOR_BACKGROUND_6: #ACB1B6; +$COLOR_BACKGROUND_5: #B9BDC1; +$COLOR_BACKGROUND_4: #C9CDD0; +$COLOR_BACKGROUND_2: #E0E1E3; +$COLOR_BACKGROUND_3: #CED1D4; +$COLOR_BACKGROUND_1: #FAFAFA; +$COLOR_TEXT_1: #19232D; +$COLOR_TEXT_2: #293544; +$COLOR_TEXT_3: #54687A; +$COLOR_TEXT_4: #788D9C; +$COLOR_ACCENT_1: #DAEDFF; +$COLOR_ACCENT_2: #9FCBFF; +$COLOR_ACCENT_3: #73C7FF; +$COLOR_ACCENT_4: #37AEFE; +$OPACITY_TOOLTIP: 230; +$SIZE_BORDER_RADIUS: 4px; +$BORDER_1: 1px solid $COLOR_BACKGROUND_1; +$BORDER_2: 1px solid $COLOR_BACKGROUND_4; +$BORDER_3: 1px solid $COLOR_BACKGROUND_6; +$BORDER_SELECTION_3: 1px solid $COLOR_ACCENT_3; +$BORDER_SELECTION_2: 1px solid $COLOR_ACCENT_2; +$BORDER_SELECTION_1: 1px solid $COLOR_ACCENT_1; +$PATH_RESOURCES: ':/qss_icons'; diff --git a/src/qdarkstyle/light/lightstyle.qrc b/src/qdarkstyle/light/lightstyle.qrc new file mode 100644 index 000000000..04e9b5d89 --- /dev/null +++ b/src/qdarkstyle/light/lightstyle.qrc @@ -0,0 +1,216 @@ + + + + rc/arrow_down.png + rc/arrow_down@2x.png + rc/arrow_down_disabled.png + rc/arrow_down_disabled@2x.png + rc/arrow_down_focus.png + rc/arrow_down_focus@2x.png + rc/arrow_down_pressed.png + rc/arrow_down_pressed@2x.png + rc/arrow_left.png + rc/arrow_left@2x.png + rc/arrow_left_disabled.png + rc/arrow_left_disabled@2x.png + rc/arrow_left_focus.png + rc/arrow_left_focus@2x.png + rc/arrow_left_pressed.png + rc/arrow_left_pressed@2x.png + rc/arrow_right.png + rc/arrow_right@2x.png + rc/arrow_right_disabled.png + rc/arrow_right_disabled@2x.png + rc/arrow_right_focus.png + rc/arrow_right_focus@2x.png + rc/arrow_right_pressed.png + rc/arrow_right_pressed@2x.png + rc/arrow_up.png + rc/arrow_up@2x.png + rc/arrow_up_disabled.png + rc/arrow_up_disabled@2x.png + rc/arrow_up_focus.png + rc/arrow_up_focus@2x.png + rc/arrow_up_pressed.png + rc/arrow_up_pressed@2x.png + rc/base_icon.png + rc/base_icon@2x.png + rc/base_icon_disabled.png + rc/base_icon_disabled@2x.png + rc/base_icon_focus.png + rc/base_icon_focus@2x.png + rc/base_icon_pressed.png + rc/base_icon_pressed@2x.png + rc/branch_closed.png + rc/branch_closed@2x.png + rc/branch_closed_disabled.png + rc/branch_closed_disabled@2x.png + rc/branch_closed_focus.png + rc/branch_closed_focus@2x.png + rc/branch_closed_pressed.png + rc/branch_closed_pressed@2x.png + rc/branch_end.png + rc/branch_end@2x.png + rc/branch_end_disabled.png + rc/branch_end_disabled@2x.png + rc/branch_end_focus.png + rc/branch_end_focus@2x.png + rc/branch_end_pressed.png + rc/branch_end_pressed@2x.png + rc/branch_line.png + rc/branch_line@2x.png + rc/branch_line_disabled.png + rc/branch_line_disabled@2x.png + rc/branch_line_focus.png + rc/branch_line_focus@2x.png + rc/branch_line_pressed.png + rc/branch_line_pressed@2x.png + rc/branch_more.png + rc/branch_more@2x.png + rc/branch_more_disabled.png + rc/branch_more_disabled@2x.png + rc/branch_more_focus.png + rc/branch_more_focus@2x.png + rc/branch_more_pressed.png + rc/branch_more_pressed@2x.png + rc/branch_open.png + rc/branch_open@2x.png + rc/branch_open_disabled.png + rc/branch_open_disabled@2x.png + rc/branch_open_focus.png + rc/branch_open_focus@2x.png + rc/branch_open_pressed.png + rc/branch_open_pressed@2x.png + rc/checkbox_checked.png + rc/checkbox_checked@2x.png + rc/checkbox_checked_disabled.png + rc/checkbox_checked_disabled@2x.png + rc/checkbox_checked_focus.png + rc/checkbox_checked_focus@2x.png + rc/checkbox_checked_pressed.png + rc/checkbox_checked_pressed@2x.png + rc/checkbox_indeterminate.png + rc/checkbox_indeterminate@2x.png + rc/checkbox_indeterminate_disabled.png + rc/checkbox_indeterminate_disabled@2x.png + rc/checkbox_indeterminate_focus.png + rc/checkbox_indeterminate_focus@2x.png + rc/checkbox_indeterminate_pressed.png + rc/checkbox_indeterminate_pressed@2x.png + rc/checkbox_unchecked.png + rc/checkbox_unchecked@2x.png + rc/checkbox_unchecked_disabled.png + rc/checkbox_unchecked_disabled@2x.png + rc/checkbox_unchecked_focus.png + rc/checkbox_unchecked_focus@2x.png + rc/checkbox_unchecked_pressed.png + rc/checkbox_unchecked_pressed@2x.png + rc/line_horizontal.png + rc/line_horizontal@2x.png + rc/line_horizontal_disabled.png + rc/line_horizontal_disabled@2x.png + rc/line_horizontal_focus.png + rc/line_horizontal_focus@2x.png + rc/line_horizontal_pressed.png + rc/line_horizontal_pressed@2x.png + rc/line_vertical.png + rc/line_vertical@2x.png + rc/line_vertical_disabled.png + rc/line_vertical_disabled@2x.png + rc/line_vertical_focus.png + rc/line_vertical_focus@2x.png + rc/line_vertical_pressed.png + rc/line_vertical_pressed@2x.png + rc/radio_checked.png + rc/radio_checked@2x.png + rc/radio_checked_disabled.png + rc/radio_checked_disabled@2x.png + rc/radio_checked_focus.png + rc/radio_checked_focus@2x.png + rc/radio_checked_pressed.png + rc/radio_checked_pressed@2x.png + rc/radio_unchecked.png + rc/radio_unchecked@2x.png + rc/radio_unchecked_disabled.png + rc/radio_unchecked_disabled@2x.png + rc/radio_unchecked_focus.png + rc/radio_unchecked_focus@2x.png + rc/radio_unchecked_pressed.png + rc/radio_unchecked_pressed@2x.png + rc/toolbar_move_horizontal.png + rc/toolbar_move_horizontal@2x.png + rc/toolbar_move_horizontal_disabled.png + rc/toolbar_move_horizontal_disabled@2x.png + rc/toolbar_move_horizontal_focus.png + rc/toolbar_move_horizontal_focus@2x.png + rc/toolbar_move_horizontal_pressed.png + rc/toolbar_move_horizontal_pressed@2x.png + rc/toolbar_move_vertical.png + rc/toolbar_move_vertical@2x.png + rc/toolbar_move_vertical_disabled.png + rc/toolbar_move_vertical_disabled@2x.png + rc/toolbar_move_vertical_focus.png + rc/toolbar_move_vertical_focus@2x.png + rc/toolbar_move_vertical_pressed.png + rc/toolbar_move_vertical_pressed@2x.png + rc/toolbar_separator_horizontal.png + rc/toolbar_separator_horizontal@2x.png + rc/toolbar_separator_horizontal_disabled.png + rc/toolbar_separator_horizontal_disabled@2x.png + rc/toolbar_separator_horizontal_focus.png + rc/toolbar_separator_horizontal_focus@2x.png + rc/toolbar_separator_horizontal_pressed.png + rc/toolbar_separator_horizontal_pressed@2x.png + rc/toolbar_separator_vertical.png + rc/toolbar_separator_vertical@2x.png + rc/toolbar_separator_vertical_disabled.png + rc/toolbar_separator_vertical_disabled@2x.png + rc/toolbar_separator_vertical_focus.png + rc/toolbar_separator_vertical_focus@2x.png + rc/toolbar_separator_vertical_pressed.png + rc/toolbar_separator_vertical_pressed@2x.png + rc/transparent.png + rc/transparent@2x.png + rc/transparent_disabled.png + rc/transparent_disabled@2x.png + rc/transparent_focus.png + rc/transparent_focus@2x.png + rc/transparent_pressed.png + rc/transparent_pressed@2x.png + rc/window_close.png + rc/window_close@2x.png + rc/window_close_disabled.png + rc/window_close_disabled@2x.png + rc/window_close_focus.png + rc/window_close_focus@2x.png + rc/window_close_pressed.png + rc/window_close_pressed@2x.png + rc/window_grip.png + rc/window_grip@2x.png + rc/window_grip_disabled.png + rc/window_grip_disabled@2x.png + rc/window_grip_focus.png + rc/window_grip_focus@2x.png + rc/window_grip_pressed.png + rc/window_grip_pressed@2x.png + rc/window_minimize.png + rc/window_minimize@2x.png + rc/window_minimize_disabled.png + rc/window_minimize_disabled@2x.png + rc/window_minimize_focus.png + rc/window_minimize_focus@2x.png + rc/window_minimize_pressed.png + rc/window_minimize_pressed@2x.png + rc/window_undock.png + rc/window_undock@2x.png + rc/window_undock_disabled.png + rc/window_undock_disabled@2x.png + rc/window_undock_focus.png + rc/window_undock_focus@2x.png + rc/window_undock_pressed.png + rc/window_undock_pressed@2x.png + + + lightstyle.qss + + diff --git a/src/qdarkstyle/light/lightstyle.qss b/src/qdarkstyle/light/lightstyle.qss new file mode 100644 index 000000000..e83d3f234 --- /dev/null +++ b/src/qdarkstyle/light/lightstyle.qss @@ -0,0 +1,2216 @@ +/* --------------------------------------------------------------------------- + + WARNING! File created programmatically. All changes made in this file will be lost! + + Created by the qtsass compiler v0.4.0 + + The definitions are in the "qdarkstyle.qss._styles.scss" module + +--------------------------------------------------------------------------- */ +/* Dark Style - QDarkStyleSheet ------------------------------------------ */ +/* + +See Qt documentation: + + - https://doc.qt.io/qt-5/stylesheet.html + - https://doc.qt.io/qt-5/stylesheet-reference.html + - https://doc.qt.io/qt-5/stylesheet-examples.html + +--------------------------------------------------------------------------- */ +/* Reset elements ------------------------------------------------------------ + +Resetting everything helps to unify styles across different operating systems + +--------------------------------------------------------------------------- */ +* { + padding: 0px; + margin: 0px; + border: 0px; + border-style: none; + border-image: none; + outline: 0; +} + +/* specific reset for elements inside QToolBar */ +QToolBar * { + margin: 0px; + padding: 0px; +} + +/* QWidget ---------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QWidget { + background-color: #FAFAFA; + border: 0px solid #C0C4C8; + padding: 0px; + color: #19232D; + selection-background-color: #9FCBFF; + selection-color: #19232D; +} + +QWidget:disabled { + background-color: #FAFAFA; + color: #9DA9B5; + selection-background-color: #DAEDFF; + selection-color: #9DA9B5; +} + +QWidget::item:selected { + background-color: #9FCBFF; +} + +QWidget::item:hover:!selected { + background-color: #73C7FF; +} + +/* QMainWindow ------------------------------------------------------------ + +This adjusts the splitter in the dock widget, not qsplitter +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmainwindow + +--------------------------------------------------------------------------- */ +QMainWindow::separator { + background-color: #C0C4C8; + border: 0px solid #FAFAFA; + spacing: 0px; + padding: 2px; +} + +QMainWindow::separator:hover { + background-color: #ACB1B6; + border: 0px solid #73C7FF; +} + +QMainWindow::separator:horizontal { + width: 5px; + margin-top: 2px; + margin-bottom: 2px; + image: url(":/qss_icons/light/rc/toolbar_separator_vertical.png"); +} + +QMainWindow::separator:vertical { + height: 5px; + margin-left: 2px; + margin-right: 2px; + image: url(":/qss_icons/light/rc/toolbar_separator_horizontal.png"); +} + +/* QToolTip --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtooltip + +--------------------------------------------------------------------------- */ +QToolTip { + background-color: #9FCBFF; + color: #19232D; + /* If you remove the border property, background stops working on Windows */ + border: none; + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + /* Remove opacity, fix #174 - may need to use RGBA */ +} + +/* QStatusBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar + +--------------------------------------------------------------------------- */ +QStatusBar { + border: 1px solid #C0C4C8; + /* Fixes Spyder #9120, #9121 */ + background: #C0C4C8; + /* Fixes #205, white vertical borders separating items */ +} + +QStatusBar::item { + border: none; +} + +QStatusBar QToolTip { + background-color: #73C7FF; + border: 1px solid #FAFAFA; + color: #FAFAFA; + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + /* Reducing transparency to read better */ + opacity: 230; +} + +QStatusBar QLabel { + /* Fixes Spyder #9120, #9121 */ + background: transparent; +} + +/* QCheckBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcheckbox + +--------------------------------------------------------------------------- */ +QCheckBox { + background-color: #FAFAFA; + color: #19232D; + spacing: 4px; + outline: none; + padding-top: 4px; + padding-bottom: 4px; +} + +QCheckBox:focus { + border: none; +} + +QCheckBox QWidget:disabled { + background-color: #FAFAFA; + color: #9DA9B5; +} + +QCheckBox::indicator { + margin-left: 2px; + height: 14px; + width: 14px; +} + +QCheckBox::indicator:unchecked { + image: url(":/qss_icons/light/rc/checkbox_unchecked.png"); +} + +QCheckBox::indicator:unchecked:hover, QCheckBox::indicator:unchecked:focus, QCheckBox::indicator:unchecked:pressed { + border: none; + image: url(":/qss_icons/light/rc/checkbox_unchecked_focus.png"); +} + +QCheckBox::indicator:unchecked:disabled { + image: url(":/qss_icons/light/rc/checkbox_unchecked_disabled.png"); +} + +QCheckBox::indicator:checked { + image: url(":/qss_icons/light/rc/checkbox_checked.png"); +} + +QCheckBox::indicator:checked:hover, QCheckBox::indicator:checked:focus, QCheckBox::indicator:checked:pressed { + border: none; + image: url(":/qss_icons/light/rc/checkbox_checked_focus.png"); +} + +QCheckBox::indicator:checked:disabled { + image: url(":/qss_icons/light/rc/checkbox_checked_disabled.png"); +} + +QCheckBox::indicator:indeterminate { + image: url(":/qss_icons/light/rc/checkbox_indeterminate.png"); +} + +QCheckBox::indicator:indeterminate:disabled { + image: url(":/qss_icons/light/rc/checkbox_indeterminate_disabled.png"); +} + +QCheckBox::indicator:indeterminate:focus, QCheckBox::indicator:indeterminate:hover, QCheckBox::indicator:indeterminate:pressed { + image: url(":/qss_icons/light/rc/checkbox_indeterminate_focus.png"); +} + +/* QGroupBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox + +--------------------------------------------------------------------------- */ +QGroupBox { + font-weight: bold; + border: 1px solid #C0C4C8; + border-radius: 4px; + padding: 2px; + margin-top: 6px; + margin-bottom: 4px; +} + +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + left: 4px; + padding-left: 2px; + padding-right: 4px; + padding-top: -4px; +} + +QGroupBox::indicator { + margin-left: 2px; + margin-top: 2px; + padding: 0; + height: 14px; + width: 14px; +} + +QGroupBox::indicator:unchecked { + border: none; + image: url(":/qss_icons/light/rc/checkbox_unchecked.png"); +} + +QGroupBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:focus, QGroupBox::indicator:unchecked:pressed { + border: none; + image: url(":/qss_icons/light/rc/checkbox_unchecked_focus.png"); +} + +QGroupBox::indicator:unchecked:disabled { + image: url(":/qss_icons/light/rc/checkbox_unchecked_disabled.png"); +} + +QGroupBox::indicator:checked { + border: none; + image: url(":/qss_icons/light/rc/checkbox_checked.png"); +} + +QGroupBox::indicator:checked:hover, QGroupBox::indicator:checked:focus, QGroupBox::indicator:checked:pressed { + border: none; + image: url(":/qss_icons/light/rc/checkbox_checked_focus.png"); +} + +QGroupBox::indicator:checked:disabled { + image: url(":/qss_icons/light/rc/checkbox_checked_disabled.png"); +} + +/* QRadioButton ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qradiobutton + +--------------------------------------------------------------------------- */ +QRadioButton { + background-color: #FAFAFA; + color: #19232D; + spacing: 4px; + padding-top: 4px; + padding-bottom: 4px; + border: none; + outline: none; +} + +QRadioButton:focus { + border: none; +} + +QRadioButton:disabled { + background-color: #FAFAFA; + color: #9DA9B5; + border: none; + outline: none; +} + +QRadioButton QWidget { + background-color: #FAFAFA; + color: #19232D; + spacing: 0px; + padding: 0px; + outline: none; + border: none; +} + +QRadioButton::indicator { + border: none; + outline: none; + margin-left: 2px; + height: 14px; + width: 14px; +} + +QRadioButton::indicator:unchecked { + image: url(":/qss_icons/light/rc/radio_unchecked.png"); +} + +QRadioButton::indicator:unchecked:hover, QRadioButton::indicator:unchecked:focus, QRadioButton::indicator:unchecked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/light/rc/radio_unchecked_focus.png"); +} + +QRadioButton::indicator:unchecked:disabled { + image: url(":/qss_icons/light/rc/radio_unchecked_disabled.png"); +} + +QRadioButton::indicator:checked { + border: none; + outline: none; + image: url(":/qss_icons/light/rc/radio_checked.png"); +} + +QRadioButton::indicator:checked:hover, QRadioButton::indicator:checked:focus, QRadioButton::indicator:checked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/light/rc/radio_checked_focus.png"); +} + +QRadioButton::indicator:checked:disabled { + outline: none; + image: url(":/qss_icons/light/rc/radio_checked_disabled.png"); +} + +/* QMenuBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar + +--------------------------------------------------------------------------- */ +QMenuBar { + background-color: #C0C4C8; + padding: 2px; + border: 1px solid #FAFAFA; + color: #19232D; + selection-background-color: #73C7FF; +} + +QMenuBar:focus { + border: 1px solid #9FCBFF; +} + +QMenuBar::item { + background: transparent; + padding: 4px; +} + +QMenuBar::item:selected { + padding: 4px; + background: transparent; + border: 0px solid #C0C4C8; + background-color: #73C7FF; +} + +QMenuBar::item:pressed { + padding: 4px; + border: 0px solid #C0C4C8; + background-color: #73C7FF; + color: #19232D; + margin-bottom: 0px; + padding-bottom: 0px; +} + +/* QMenu ------------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu + +--------------------------------------------------------------------------- */ +QMenu { + border: 0px solid #C0C4C8; + color: #19232D; + margin: 0px; + background-color: #D2D5D8; + selection-background-color: #73C7FF; +} + +QMenu::separator { + height: 1px; + background-color: #ACB1B6; + color: #19232D; +} + +QMenu::item { + background-color: #D2D5D8; + padding: 4px 24px 4px 28px; + /* Reserve space for selection border */ + border: 1px transparent #C0C4C8; +} + +QMenu::item:selected { + color: #19232D; + background-color: #73C7FF; +} + +QMenu::item:pressed { + background-color: #73C7FF; +} + +QMenu::icon { + padding-left: 10px; + width: 14px; + height: 14px; +} + +QMenu::indicator { + padding-left: 8px; + width: 12px; + height: 12px; + /* non-exclusive indicator = check box style indicator (see QActionGroup::setExclusive) */ + /* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */ +} + +QMenu::indicator:non-exclusive:unchecked { + image: url(":/qss_icons/light/rc/checkbox_unchecked.png"); +} + +QMenu::indicator:non-exclusive:unchecked:hover, QMenu::indicator:non-exclusive:unchecked:focus, QMenu::indicator:non-exclusive:unchecked:pressed { + border: none; + image: url(":/qss_icons/light/rc/checkbox_unchecked_focus.png"); +} + +QMenu::indicator:non-exclusive:unchecked:disabled { + image: url(":/qss_icons/light/rc/checkbox_unchecked_disabled.png"); +} + +QMenu::indicator:non-exclusive:checked { + image: url(":/qss_icons/light/rc/checkbox_checked.png"); +} + +QMenu::indicator:non-exclusive:checked:hover, QMenu::indicator:non-exclusive:checked:focus, QMenu::indicator:non-exclusive:checked:pressed { + border: none; + image: url(":/qss_icons/light/rc/checkbox_checked_focus.png"); +} + +QMenu::indicator:non-exclusive:checked:disabled { + image: url(":/qss_icons/light/rc/checkbox_checked_disabled.png"); +} + +QMenu::indicator:non-exclusive:indeterminate { + image: url(":/qss_icons/light/rc/checkbox_indeterminate.png"); +} + +QMenu::indicator:non-exclusive:indeterminate:disabled { + image: url(":/qss_icons/light/rc/checkbox_indeterminate_disabled.png"); +} + +QMenu::indicator:non-exclusive:indeterminate:focus, QMenu::indicator:non-exclusive:indeterminate:hover, QMenu::indicator:non-exclusive:indeterminate:pressed { + image: url(":/qss_icons/light/rc/checkbox_indeterminate_focus.png"); +} + +QMenu::indicator:exclusive:unchecked { + image: url(":/qss_icons/light/rc/radio_unchecked.png"); +} + +QMenu::indicator:exclusive:unchecked:hover, QMenu::indicator:exclusive:unchecked:focus, QMenu::indicator:exclusive:unchecked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/light/rc/radio_unchecked_focus.png"); +} + +QMenu::indicator:exclusive:unchecked:disabled { + image: url(":/qss_icons/light/rc/radio_unchecked_disabled.png"); +} + +QMenu::indicator:exclusive:checked { + border: none; + outline: none; + image: url(":/qss_icons/light/rc/radio_checked.png"); +} + +QMenu::indicator:exclusive:checked:hover, QMenu::indicator:exclusive:checked:focus, QMenu::indicator:exclusive:checked:pressed { + border: none; + outline: none; + image: url(":/qss_icons/light/rc/radio_checked_focus.png"); +} + +QMenu::indicator:exclusive:checked:disabled { + outline: none; + image: url(":/qss_icons/light/rc/radio_checked_disabled.png"); +} + +QMenu::right-arrow { + margin: 5px; + padding-left: 12px; + image: url(":/qss_icons/light/rc/arrow_right.png"); + height: 12px; + width: 12px; +} + +/* QAbstractItemView ------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QAbstractItemView { + alternate-background-color: #FAFAFA; + color: #19232D; + border: 1px solid #C0C4C8; + border-radius: 4px; +} + +QAbstractItemView QLineEdit { + padding: 2px; +} + +/* QAbstractScrollArea ---------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QAbstractScrollArea { + background-color: #FAFAFA; + border: 1px solid #C0C4C8; + border-radius: 4px; + /* fix #159 */ + padding: 2px; + /* remove min-height to fix #244 */ + color: #19232D; +} + +QAbstractScrollArea:disabled { + color: #9DA9B5; +} + +/* QScrollArea ------------------------------------------------------------ + +--------------------------------------------------------------------------- */ +QScrollArea QWidget QWidget:disabled { + background-color: #FAFAFA; +} + +/* QScrollBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qscrollbar + +--------------------------------------------------------------------------- */ +QScrollBar:horizontal { + height: 16px; + margin: 2px 16px 2px 16px; + border: 1px solid #C0C4C8; + border-radius: 4px; + background-color: #FAFAFA; +} + +QScrollBar:vertical { + background-color: #FAFAFA; + width: 16px; + margin: 16px 2px 16px 2px; + border: 1px solid #C0C4C8; + border-radius: 4px; +} + +QScrollBar::handle:horizontal { + background-color: #ACB1B6; + border: 1px solid #C0C4C8; + border-radius: 4px; + min-width: 8px; +} + +QScrollBar::handle:horizontal:hover { + background-color: #9FCBFF; + border: #9FCBFF; + border-radius: 4px; + min-width: 8px; +} + +QScrollBar::handle:horizontal:focus { + border: 1px solid #73C7FF; +} + +QScrollBar::handle:vertical { + background-color: #ACB1B6; + border: 1px solid #C0C4C8; + min-height: 8px; + border-radius: 4px; +} + +QScrollBar::handle:vertical:hover { + background-color: #9FCBFF; + border: #9FCBFF; + border-radius: 4px; + min-height: 8px; +} + +QScrollBar::handle:vertical:focus { + border: 1px solid #73C7FF; +} + +QScrollBar::add-line:horizontal { + margin: 0px 0px 0px 0px; + border-image: url(":/qss_icons/light/rc/arrow_right_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::add-line:horizontal:hover, QScrollBar::add-line:horizontal:on { + border-image: url(":/qss_icons/light/rc/arrow_right.png"); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::add-line:vertical { + margin: 3px 0px 3px 0px; + border-image: url(":/qss_icons/light/rc/arrow_down_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on { + border-image: url(":/qss_icons/light/rc/arrow_down.png"); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal { + margin: 0px 3px 0px 3px; + border-image: url(":/qss_icons/light/rc/arrow_left_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on { + border-image: url(":/qss_icons/light/rc/arrow_left.png"); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:vertical { + margin: 3px 0px 3px 0px; + border-image: url(":/qss_icons/light/rc/arrow_up_disabled.png"); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::sub-line:vertical:hover, QScrollBar::sub-line:vertical:on { + border-image: url(":/qss_icons/light/rc/arrow_up.png"); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal { + background: none; +} + +QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { + background: none; +} + +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + background: none; +} + +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + background: none; +} + +/* QTextEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-specific-widgets + +--------------------------------------------------------------------------- */ +QTextEdit { + background-color: #FAFAFA; + color: #19232D; + border-radius: 4px; + border: 1px solid #C0C4C8; +} + +QTextEdit:focus { + border: 1px solid #73C7FF; +} + +QTextEdit:selected { + background: #9FCBFF; + color: #C0C4C8; +} + +/* QPlainTextEdit --------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QPlainTextEdit { + background-color: #FAFAFA; + color: #19232D; + border-radius: 4px; + border: 1px solid #C0C4C8; +} + +QPlainTextEdit:focus { + border: 1px solid #73C7FF; +} + +QPlainTextEdit:selected { + background: #9FCBFF; + color: #C0C4C8; +} + +/* QSizeGrip -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsizegrip + +--------------------------------------------------------------------------- */ +QSizeGrip { + background: transparent; + width: 12px; + height: 12px; + image: url(":/qss_icons/light/rc/window_grip.png"); +} + +/* QStackedWidget --------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QStackedWidget { + padding: 2px; + border: 1px solid #C0C4C8; + border: 1px solid #FAFAFA; +} + +/* QToolBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbar + +--------------------------------------------------------------------------- */ +QToolBar { + background-color: #C0C4C8; + border-bottom: 1px solid #FAFAFA; + padding: 1px; + font-weight: bold; + spacing: 2px; +} + +QToolBar:disabled { + /* Fixes #272 */ + background-color: #C0C4C8; +} + +QToolBar::handle:horizontal { + width: 16px; + image: url(":/qss_icons/light/rc/toolbar_move_horizontal.png"); +} + +QToolBar::handle:vertical { + height: 16px; + image: url(":/qss_icons/light/rc/toolbar_move_vertical.png"); +} + +QToolBar::separator:horizontal { + width: 16px; + image: url(":/qss_icons/light/rc/toolbar_separator_horizontal.png"); +} + +QToolBar::separator:vertical { + height: 16px; + image: url(":/qss_icons/light/rc/toolbar_separator_vertical.png"); +} + +QToolButton#qt_toolbar_ext_button { + background: #C0C4C8; + border: 0px; + color: #19232D; + image: url(":/qss_icons/light/rc/arrow_right.png"); +} + +/* QAbstractSpinBox ------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractSpinBox { + background-color: #FAFAFA; + border: 1px solid #C0C4C8; + color: #19232D; + /* This fixes 103, 111 */ + padding-top: 2px; + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + border-radius: 4px; + /* min-width: 5px; removed to fix 109 */ +} + +QAbstractSpinBox:up-button { + background-color: transparent #FAFAFA; + subcontrol-origin: border; + subcontrol-position: top right; + border-left: 1px solid #C0C4C8; + border-bottom: 1px solid #C0C4C8; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-bottom: -1px; +} + +QAbstractSpinBox::up-arrow, QAbstractSpinBox::up-arrow:disabled, QAbstractSpinBox::up-arrow:off { + image: url(":/qss_icons/light/rc/arrow_up_disabled.png"); + height: 8px; + width: 8px; +} + +QAbstractSpinBox::up-arrow:hover { + image: url(":/qss_icons/light/rc/arrow_up.png"); +} + +QAbstractSpinBox:down-button { + background-color: transparent #FAFAFA; + subcontrol-origin: border; + subcontrol-position: bottom right; + border-left: 1px solid #C0C4C8; + border-top: 1px solid #C0C4C8; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-top: -1px; +} + +QAbstractSpinBox::down-arrow, QAbstractSpinBox::down-arrow:disabled, QAbstractSpinBox::down-arrow:off { + image: url(":/qss_icons/light/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QAbstractSpinBox::down-arrow:hover { + image: url(":/qss_icons/light/rc/arrow_down.png"); +} + +QAbstractSpinBox:hover { + border: 1px solid #9FCBFF; + color: #19232D; +} + +QAbstractSpinBox:focus { + border: 1px solid #73C7FF; +} + +QAbstractSpinBox:selected { + background: #9FCBFF; + color: #C0C4C8; +} + +/* ------------------------------------------------------------------------ */ +/* DISPLAYS --------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QLabel ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe + +--------------------------------------------------------------------------- */ +QLabel { + background-color: #FAFAFA; + border: 0px solid #C0C4C8; + padding: 2px; + margin: 0px; + color: #19232D; +} + +QLabel:disabled { + background-color: #FAFAFA; + border: 0px solid #C0C4C8; + color: #9DA9B5; +} + +/* QTextBrowser ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QTextBrowser { + background-color: #FAFAFA; + border: 1px solid #C0C4C8; + color: #19232D; + border-radius: 4px; +} + +QTextBrowser:disabled { + background-color: #FAFAFA; + border: 1px solid #C0C4C8; + color: #9DA9B5; + border-radius: 4px; +} + +QTextBrowser:hover, QTextBrowser:!hover, QTextBrowser:selected, QTextBrowser:pressed { + border: 1px solid #C0C4C8; +} + +/* QGraphicsView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QGraphicsView { + background-color: #FAFAFA; + border: 1px solid #C0C4C8; + color: #19232D; + border-radius: 4px; +} + +QGraphicsView:disabled { + background-color: #FAFAFA; + border: 1px solid #C0C4C8; + color: #9DA9B5; + border-radius: 4px; +} + +QGraphicsView:hover, QGraphicsView:!hover, QGraphicsView:selected, QGraphicsView:pressed { + border: 1px solid #C0C4C8; +} + +/* QCalendarWidget -------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCalendarWidget { + border: 1px solid #C0C4C8; + border-radius: 4px; +} + +QCalendarWidget:disabled { + background-color: #FAFAFA; + color: #9DA9B5; +} + +/* QLCDNumber ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QLCDNumber { + background-color: #FAFAFA; + color: #19232D; +} + +QLCDNumber:disabled { + background-color: #FAFAFA; + color: #9DA9B5; +} + +/* QProgressBar ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qprogressbar + +--------------------------------------------------------------------------- */ +QProgressBar { + background-color: #FAFAFA; + border: 1px solid #C0C4C8; + color: #19232D; + border-radius: 4px; + text-align: center; +} + +QProgressBar:disabled { + background-color: #FAFAFA; + border: 1px solid #C0C4C8; + color: #9DA9B5; + border-radius: 4px; + text-align: center; +} + +QProgressBar::chunk { + background-color: #9FCBFF; + color: #FAFAFA; + border-radius: 4px; +} + +QProgressBar::chunk:disabled { + background-color: #DAEDFF; + color: #9DA9B5; + border-radius: 4px; +} + +/* ------------------------------------------------------------------------ */ +/* BUTTONS ---------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QPushButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qpushbutton + +--------------------------------------------------------------------------- */ +QPushButton { + background-color: #C0C4C8; + color: #19232D; + border-radius: 4px; + padding: 2px; + outline: none; + border: none; +} + +QPushButton:disabled { + background-color: #C0C4C8; + color: #9DA9B5; + border-radius: 4px; + padding: 2px; +} + +QPushButton:checked { + background-color: #ACB1B6; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QPushButton:checked:disabled { + background-color: #ACB1B6; + color: #9DA9B5; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QPushButton:checked:selected { + background: #ACB1B6; +} + +QPushButton:hover { + background-color: #B4B8BC; + color: #19232D; +} + +QPushButton:pressed { + background-color: #ACB1B6; +} + +QPushButton:selected { + background: #ACB1B6; + color: #19232D; +} + +QPushButton::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: bottom right; + bottom: 4px; +} + +QDialogButtonBox QPushButton { + /* Issue #194 #248 - Special case of QPushButton inside dialogs, for better UI */ + min-width: 80px; +} + +/* QToolButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbutton + +--------------------------------------------------------------------------- */ +QToolButton { + background-color: #C0C4C8; + color: #19232D; + border-radius: 4px; + padding: 2px; + outline: none; + border: none; + /* The subcontrols below are used only in the DelayedPopup mode */ + /* The subcontrols below are used only in the MenuButtonPopup mode */ + /* The subcontrol below is used only in the InstantPopup or DelayedPopup mode */ +} + +QToolButton:disabled { + background-color: #C0C4C8; + color: #9DA9B5; + border-radius: 4px; + padding: 2px; +} + +QToolButton:checked { + background-color: #ACB1B6; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QToolButton:checked:disabled { + background-color: #ACB1B6; + color: #9DA9B5; + border-radius: 4px; + padding: 2px; + outline: none; +} + +QToolButton:checked:hover { + background-color: #B4B8BC; + color: #19232D; +} + +QToolButton:checked:pressed { + background-color: #ACB1B6; +} + +QToolButton:checked:selected { + background: #ACB1B6; + color: #19232D; +} + +QToolButton:hover { + background-color: #B4B8BC; + color: #19232D; +} + +QToolButton:pressed { + background-color: #ACB1B6; +} + +QToolButton:selected { + background: #ACB1B6; + color: #19232D; +} + +QToolButton[popupMode="0"] { + /* Only for DelayedPopup */ + padding-right: 2px; +} + +QToolButton[popupMode="1"] { + /* Only for MenuButtonPopup */ + padding-right: 20px; +} + +QToolButton[popupMode="1"]::menu-button { + border: none; +} + +QToolButton[popupMode="1"]::menu-button:hover { + border: none; + border-left: 1px solid #C0C4C8; + border-radius: 0; +} + +QToolButton[popupMode="2"] { + /* Only for InstantPopup */ + padding-right: 2px; +} + +QToolButton::menu-button { + padding: 2px; + border-radius: 4px; + width: 12px; + border: none; + outline: none; +} + +QToolButton::menu-button:hover { + border: 1px solid #9FCBFF; +} + +QToolButton::menu-button:checked:hover { + border: 1px solid #9FCBFF; +} + +QToolButton::menu-indicator { + image: url(":/qss_icons/light/rc/arrow_down.png"); + height: 8px; + width: 8px; + top: 0; + /* Exclude a shift for better image */ + left: -2px; + /* Shift it a bit */ +} + +QToolButton::menu-arrow { + image: url(":/qss_icons/light/rc/arrow_down.png"); + height: 8px; + width: 8px; +} + +QToolButton::menu-arrow:hover { + image: url(":/qss_icons/light/rc/arrow_down_focus.png"); +} + +/* QCommandLinkButton ----------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCommandLinkButton { + background-color: transparent; + border: 1px solid #C0C4C8; + color: #19232D; + border-radius: 4px; + padding: 0px; + margin: 0px; +} + +QCommandLinkButton:disabled { + background-color: transparent; + color: #9DA9B5; +} + +/* ------------------------------------------------------------------------ */ +/* INPUTS - NO FIELDS ----------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ +/* QComboBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QComboBox { + border: 1px solid #C0C4C8; + border-radius: 4px; + selection-background-color: #9FCBFF; + padding-left: 4px; + padding-right: 4px; + /* padding-right = 36; 4 + 16*2 See scrollbar size */ + /* changed to 4px to fix #239 */ + /* Fixes #103, #111 */ + min-height: 1.5em; + /* padding-top: 2px; removed to fix #132 */ + /* padding-bottom: 2px; removed to fix #132 */ + /* min-width: 75px; removed to fix #109 */ + /* Needed to remove indicator - fix #132 */ +} + +QComboBox QAbstractItemView { + border: 1px solid #C0C4C8; + border-radius: 0; + background-color: #FAFAFA; + selection-background-color: #9FCBFF; +} + +QComboBox QAbstractItemView:hover { + background-color: #FAFAFA; + color: #19232D; +} + +QComboBox QAbstractItemView:selected { + background: #9FCBFF; + color: #C0C4C8; +} + +QComboBox QAbstractItemView:alternate { + background: #FAFAFA; +} + +QComboBox:disabled { + background-color: #FAFAFA; + color: #9DA9B5; +} + +QComboBox:hover { + border: 1px solid #9FCBFF; +} + +QComboBox:focus { + border: 1px solid #73C7FF; +} + +QComboBox:on { + selection-background-color: #9FCBFF; +} + +QComboBox::indicator { + border: none; + border-radius: 0; + background-color: transparent; + selection-background-color: transparent; + color: transparent; + selection-color: transparent; + /* Needed to remove indicator - fix #132 */ +} + +QComboBox::indicator:alternate { + background: #FAFAFA; +} + +QComboBox::item { + /* Remove to fix #282, #285 and MR #288*/ + /*&:checked { + font-weight: bold; + } + + &:selected { + border: 0px solid transparent; + } + */ +} + +QComboBox::item:alternate { + background: #FAFAFA; +} + +QComboBox::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid #C0C4C8; +} + +QComboBox::down-arrow { + image: url(":/qss_icons/light/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QComboBox::down-arrow:on, QComboBox::down-arrow:hover, QComboBox::down-arrow:focus { + image: url(":/qss_icons/light/rc/arrow_down.png"); +} + +/* QSlider ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qslider + +--------------------------------------------------------------------------- */ +QSlider:disabled { + background: #FAFAFA; +} + +QSlider:focus { + border: none; +} + +QSlider::groove:horizontal { + background: #C0C4C8; + border: 1px solid #C0C4C8; + height: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::groove:vertical { + background: #C0C4C8; + border: 1px solid #C0C4C8; + width: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::add-page:vertical { + background: #9FCBFF; + border: 1px solid #C0C4C8; + width: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::add-page:vertical :disabled { + background: #DAEDFF; +} + +QSlider::sub-page:horizontal { + background: #9FCBFF; + border: 1px solid #C0C4C8; + height: 4px; + margin: 0px; + border-radius: 4px; +} + +QSlider::sub-page:horizontal:disabled { + background: #DAEDFF; +} + +QSlider::handle:horizontal { + background: #788D9C; + border: 1px solid #C0C4C8; + width: 8px; + height: 8px; + margin: -8px 0px; + border-radius: 4px; +} + +QSlider::handle:horizontal:hover { + background: #9FCBFF; + border: 1px solid #9FCBFF; +} + +QSlider::handle:horizontal:focus { + border: 1px solid #73C7FF; +} + +QSlider::handle:vertical { + background: #788D9C; + border: 1px solid #C0C4C8; + width: 8px; + height: 8px; + margin: 0 -8px; + border-radius: 4px; +} + +QSlider::handle:vertical:hover { + background: #9FCBFF; + border: 1px solid #9FCBFF; +} + +QSlider::handle:vertical:focus { + border: 1px solid #73C7FF; +} + +/* QLineEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlineedit + +--------------------------------------------------------------------------- */ +QLineEdit { + background-color: #FAFAFA; + padding-top: 2px; + /* This QLineEdit fix 103, 111 */ + padding-bottom: 2px; + /* This QLineEdit fix 103, 111 */ + padding-left: 4px; + padding-right: 4px; + border-style: solid; + border: 1px solid #C0C4C8; + border-radius: 4px; + color: #19232D; +} + +QLineEdit:disabled { + background-color: #FAFAFA; + color: #9DA9B5; +} + +QLineEdit:hover { + border: 1px solid #9FCBFF; + color: #19232D; +} + +QLineEdit:focus { + border: 1px solid #73C7FF; +} + +QLineEdit:selected { + background-color: #9FCBFF; + color: #C0C4C8; +} + +/* QTabWiget -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabWidget { + padding: 2px; + selection-background-color: #C0C4C8; +} + +QTabWidget QWidget { + /* Fixes #189 */ + border-radius: 4px; +} + +QTabWidget::pane { + border: 1px solid #C0C4C8; + border-radius: 4px; + margin: 0px; + /* Fixes double border inside pane with pyqt5 */ + padding: 0px; +} + +QTabWidget::pane:selected { + background-color: #C0C4C8; + border: 1px solid #9FCBFF; +} + +/* QTabBar ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabBar, QDockWidget QTabBar { + qproperty-drawBase: 0; + border-radius: 4px; + margin: 0px; + padding: 2px; + border: 0; + /* left: 5px; move to the right by 5px - removed for fix */ +} + +QTabBar::close-button, QDockWidget QTabBar::close-button { + border: 0; + margin: 0; + padding: 4px; + image: url(":/qss_icons/light/rc/window_close.png"); +} + +QTabBar::close-button:hover, QDockWidget QTabBar::close-button:hover { + image: url(":/qss_icons/light/rc/window_close_focus.png"); +} + +QTabBar::close-button:pressed, QDockWidget QTabBar::close-button:pressed { + image: url(":/qss_icons/light/rc/window_close_pressed.png"); +} + +QTabBar::tab, QDockWidget QTabBar::tab { + /* !selected and disabled ----------------------------------------- */ + /* selected ------------------------------------------------------- */ +} + +QTabBar::tab:top:selected:disabled, QDockWidget QTabBar::tab:top:selected:disabled { + border-bottom: 3px solid #DAEDFF; + color: #9DA9B5; + background-color: #C0C4C8; +} + +QTabBar::tab:bottom:selected:disabled, QDockWidget QTabBar::tab:bottom:selected:disabled { + border-top: 3px solid #DAEDFF; + color: #9DA9B5; + background-color: #C0C4C8; +} + +QTabBar::tab:left:selected:disabled, QDockWidget QTabBar::tab:left:selected:disabled { + border-right: 3px solid #DAEDFF; + color: #9DA9B5; + background-color: #C0C4C8; +} + +QTabBar::tab:right:selected:disabled, QDockWidget QTabBar::tab:right:selected:disabled { + border-left: 3px solid #DAEDFF; + color: #9DA9B5; + background-color: #C0C4C8; +} + +QTabBar::tab:top:!selected:disabled, QDockWidget QTabBar::tab:top:!selected:disabled { + border-bottom: 3px solid #FAFAFA; + color: #9DA9B5; + background-color: #FAFAFA; +} + +QTabBar::tab:bottom:!selected:disabled, QDockWidget QTabBar::tab:bottom:!selected:disabled { + border-top: 3px solid #FAFAFA; + color: #9DA9B5; + background-color: #FAFAFA; +} + +QTabBar::tab:left:!selected:disabled, QDockWidget QTabBar::tab:left:!selected:disabled { + border-right: 3px solid #FAFAFA; + color: #9DA9B5; + background-color: #FAFAFA; +} + +QTabBar::tab:right:!selected:disabled, QDockWidget QTabBar::tab:right:!selected:disabled { + border-left: 3px solid #FAFAFA; + color: #9DA9B5; + background-color: #FAFAFA; +} + +QTabBar::tab:top:!selected, QDockWidget QTabBar::tab:top:!selected { + border-bottom: 2px solid #FAFAFA; + margin-top: 2px; +} + +QTabBar::tab:bottom:!selected, QDockWidget QTabBar::tab:bottom:!selected { + border-top: 2px solid #FAFAFA; + margin-bottom: 2px; +} + +QTabBar::tab:left:!selected, QDockWidget QTabBar::tab:left:!selected { + border-left: 2px solid #FAFAFA; + margin-right: 2px; +} + +QTabBar::tab:right:!selected, QDockWidget QTabBar::tab:right:!selected { + border-right: 2px solid #FAFAFA; + margin-left: 2px; +} + +QTabBar::tab:top, QDockWidget QTabBar::tab:top { + background-color: #C0C4C8; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + min-width: 5px; + border-bottom: 3px solid #C0C4C8; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QTabBar::tab:top:selected, QDockWidget QTabBar::tab:top:selected { + background-color: #B4B8BC; + border-bottom: 3px solid #37AEFE; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QTabBar::tab:top:!selected:hover, QDockWidget QTabBar::tab:top:!selected:hover { + border: 1px solid #73C7FF; + border-bottom: 3px solid #73C7FF; + /* Fixes spyder-ide/spyder#9766 and #243 */ + padding-left: 3px; + padding-right: 3px; +} + +QTabBar::tab:bottom, QDockWidget QTabBar::tab:bottom { + border-top: 3px solid #C0C4C8; + background-color: #C0C4C8; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + min-width: 5px; +} + +QTabBar::tab:bottom:selected, QDockWidget QTabBar::tab:bottom:selected { + background-color: #B4B8BC; + border-top: 3px solid #37AEFE; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +QTabBar::tab:bottom:!selected:hover, QDockWidget QTabBar::tab:bottom:!selected:hover { + border: 1px solid #73C7FF; + border-top: 3px solid #73C7FF; + /* Fixes spyder-ide/spyder#9766 and #243 */ + padding-left: 3px; + padding-right: 3px; +} + +QTabBar::tab:left, QDockWidget QTabBar::tab:left { + background-color: #C0C4C8; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + min-height: 5px; +} + +QTabBar::tab:left:selected, QDockWidget QTabBar::tab:left:selected { + background-color: #B4B8BC; + border-right: 3px solid #37AEFE; +} + +QTabBar::tab:left:!selected:hover, QDockWidget QTabBar::tab:left:!selected:hover { + border: 1px solid #73C7FF; + border-right: 3px solid #73C7FF; + /* Fixes different behavior #271 */ + margin-right: 0px; + padding-right: -1px; +} + +QTabBar::tab:right, QDockWidget QTabBar::tab:right { + background-color: #C0C4C8; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + min-height: 5px; +} + +QTabBar::tab:right:selected, QDockWidget QTabBar::tab:right:selected { + background-color: #B4B8BC; + border-left: 3px solid #37AEFE; +} + +QTabBar::tab:right:!selected:hover, QDockWidget QTabBar::tab:right:!selected:hover { + border: 1px solid #73C7FF; + border-left: 3px solid #73C7FF; + /* Fixes different behavior #271 */ + margin-left: 0px; + padding-left: 0px; +} + +QTabBar QToolButton, QDockWidget QTabBar QToolButton { + /* Fixes #136 */ + background-color: #C0C4C8; + height: 12px; + width: 12px; +} + +QTabBar QToolButton:pressed, QDockWidget QTabBar QToolButton:pressed { + background-color: #C0C4C8; +} + +QTabBar QToolButton:pressed:hover, QDockWidget QTabBar QToolButton:pressed:hover { + border: 1px solid #9FCBFF; +} + +QTabBar QToolButton::left-arrow:enabled, QDockWidget QTabBar QToolButton::left-arrow:enabled { + image: url(":/qss_icons/light/rc/arrow_left.png"); +} + +QTabBar QToolButton::left-arrow:disabled, QDockWidget QTabBar QToolButton::left-arrow:disabled { + image: url(":/qss_icons/light/rc/arrow_left_disabled.png"); +} + +QTabBar QToolButton::right-arrow:enabled, QDockWidget QTabBar QToolButton::right-arrow:enabled { + image: url(":/qss_icons/light/rc/arrow_right.png"); +} + +QTabBar QToolButton::right-arrow:disabled, QDockWidget QTabBar QToolButton::right-arrow:disabled { + image: url(":/qss_icons/light/rc/arrow_right_disabled.png"); +} + +/* QDockWiget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QDockWidget { + outline: 1px solid #C0C4C8; + background-color: #FAFAFA; + border: 1px solid #C0C4C8; + border-radius: 4px; + titlebar-close-icon: url(":/qss_icons/light/rc/transparent.png"); + titlebar-normal-icon: url(":/qss_icons/light/rc/transparent.png"); +} + +QDockWidget::title { + /* Better size for title bar */ + padding: 3px; + spacing: 4px; + border: none; + background-color: #C0C4C8; +} + +QDockWidget::close-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + border: 0; + margin: 0; + padding: 0; + image: url(":/qss_icons/light/rc/window_close.png"); +} + +QDockWidget::close-button:hover { + image: url(":/qss_icons/light/rc/window_close_focus.png"); +} + +QDockWidget::close-button:pressed { + image: url(":/qss_icons/light/rc/window_close_pressed.png"); +} + +QDockWidget::float-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + border: 0; + margin: 0; + padding: 0; + image: url(":/qss_icons/light/rc/window_undock.png"); +} + +QDockWidget::float-button:hover { + image: url(":/qss_icons/light/rc/window_undock_focus.png"); +} + +QDockWidget::float-button:pressed { + image: url(":/qss_icons/light/rc/window_undock_pressed.png"); +} + +/* QTreeView QListView QTableView ----------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtreeview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview + +--------------------------------------------------------------------------- */ +QTreeView:branch:selected, QTreeView:branch:hover { + background: url(":/qss_icons/light/rc/transparent.png"); +} + +QTreeView:branch:has-siblings:!adjoins-item { + border-image: url(":/qss_icons/light/rc/branch_line.png") 0; +} + +QTreeView:branch:has-siblings:adjoins-item { + border-image: url(":/qss_icons/light/rc/branch_more.png") 0; +} + +QTreeView:branch:!has-children:!has-siblings:adjoins-item { + border-image: url(":/qss_icons/light/rc/branch_end.png") 0; +} + +QTreeView:branch:has-children:!has-siblings:closed, QTreeView:branch:closed:has-children:has-siblings { + border-image: none; + image: url(":/qss_icons/light/rc/branch_closed.png"); +} + +QTreeView:branch:open:has-children:!has-siblings, QTreeView:branch:open:has-children:has-siblings { + border-image: none; + image: url(":/qss_icons/light/rc/branch_open.png"); +} + +QTreeView:branch:has-children:!has-siblings:closed:hover, QTreeView:branch:closed:has-children:has-siblings:hover { + image: url(":/qss_icons/light/rc/branch_closed_focus.png"); +} + +QTreeView:branch:open:has-children:!has-siblings:hover, QTreeView:branch:open:has-children:has-siblings:hover { + image: url(":/qss_icons/light/rc/branch_open_focus.png"); +} + +QTreeView::indicator:checked, +QListView::indicator:checked, +QTableView::indicator:checked, +QColumnView::indicator:checked { + image: url(":/qss_icons/light/rc/checkbox_checked.png"); +} + +QTreeView::indicator:checked:hover, QTreeView::indicator:checked:focus, QTreeView::indicator:checked:pressed, +QListView::indicator:checked:hover, +QListView::indicator:checked:focus, +QListView::indicator:checked:pressed, +QTableView::indicator:checked:hover, +QTableView::indicator:checked:focus, +QTableView::indicator:checked:pressed, +QColumnView::indicator:checked:hover, +QColumnView::indicator:checked:focus, +QColumnView::indicator:checked:pressed { + image: url(":/qss_icons/light/rc/checkbox_checked_focus.png"); +} + +QTreeView::indicator:unchecked, +QListView::indicator:unchecked, +QTableView::indicator:unchecked, +QColumnView::indicator:unchecked { + image: url(":/qss_icons/light/rc/checkbox_unchecked.png"); +} + +QTreeView::indicator:unchecked:hover, QTreeView::indicator:unchecked:focus, QTreeView::indicator:unchecked:pressed, +QListView::indicator:unchecked:hover, +QListView::indicator:unchecked:focus, +QListView::indicator:unchecked:pressed, +QTableView::indicator:unchecked:hover, +QTableView::indicator:unchecked:focus, +QTableView::indicator:unchecked:pressed, +QColumnView::indicator:unchecked:hover, +QColumnView::indicator:unchecked:focus, +QColumnView::indicator:unchecked:pressed { + image: url(":/qss_icons/light/rc/checkbox_unchecked_focus.png"); +} + +QTreeView::indicator:indeterminate, +QListView::indicator:indeterminate, +QTableView::indicator:indeterminate, +QColumnView::indicator:indeterminate { + image: url(":/qss_icons/light/rc/checkbox_indeterminate.png"); +} + +QTreeView::indicator:indeterminate:hover, QTreeView::indicator:indeterminate:focus, QTreeView::indicator:indeterminate:pressed, +QListView::indicator:indeterminate:hover, +QListView::indicator:indeterminate:focus, +QListView::indicator:indeterminate:pressed, +QTableView::indicator:indeterminate:hover, +QTableView::indicator:indeterminate:focus, +QTableView::indicator:indeterminate:pressed, +QColumnView::indicator:indeterminate:hover, +QColumnView::indicator:indeterminate:focus, +QColumnView::indicator:indeterminate:pressed { + image: url(":/qss_icons/light/rc/checkbox_indeterminate_focus.png"); +} + +QTreeView, +QListView, +QTableView, +QColumnView { + background-color: #FAFAFA; + border: 1px solid #C0C4C8; + color: #19232D; + gridline-color: #C0C4C8; + border-radius: 4px; +} + +QTreeView:disabled, +QListView:disabled, +QTableView:disabled, +QColumnView:disabled { + background-color: #FAFAFA; + color: #9DA9B5; +} + +QTreeView:selected, +QListView:selected, +QTableView:selected, +QColumnView:selected { + background-color: #9FCBFF; + color: #C0C4C8; +} + +QTreeView:focus, +QListView:focus, +QTableView:focus, +QColumnView:focus { + border: 1px solid #73C7FF; +} + +QTreeView::item:pressed, +QListView::item:pressed, +QTableView::item:pressed, +QColumnView::item:pressed { + background-color: #9FCBFF; +} + +QTreeView::item:selected:active, +QListView::item:selected:active, +QTableView::item:selected:active, +QColumnView::item:selected:active { + background-color: #9FCBFF; +} + +QTreeView::item:selected:!active, +QListView::item:selected:!active, +QTableView::item:selected:!active, +QColumnView::item:selected:!active { + color: #19232D; + background-color: #D2D5D8; +} + +QTreeView::item:!selected:hover, +QListView::item:!selected:hover, +QTableView::item:!selected:hover, +QColumnView::item:!selected:hover { + outline: 0; + color: #19232D; + background-color: #D2D5D8; +} + +QTableCornerButton::section { + background-color: #FAFAFA; + border: 1px transparent #C0C4C8; + border-radius: 0px; +} + +/* QHeaderView ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview + +--------------------------------------------------------------------------- */ +QHeaderView { + background-color: #C0C4C8; + border: 0px transparent #C0C4C8; + padding: 0; + margin: 0; + border-radius: 0; +} + +QHeaderView:disabled { + background-color: #C0C4C8; + border: 1px transparent #C0C4C8; +} + +QHeaderView::section { + background-color: #C0C4C8; + color: #19232D; + border-radius: 0; + text-align: left; + font-size: 13px; +} + +QHeaderView::section::horizontal { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-left: 1px solid #FAFAFA; +} + +QHeaderView::section::horizontal::first, QHeaderView::section::horizontal::only-one { + border-left: 1px solid #C0C4C8; +} + +QHeaderView::section::horizontal:disabled { + color: #9DA9B5; +} + +QHeaderView::section::vertical { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-top: 1px solid #FAFAFA; +} + +QHeaderView::section::vertical::first, QHeaderView::section::vertical::only-one { + border-top: 1px solid #C0C4C8; +} + +QHeaderView::section::vertical:disabled { + color: #9DA9B5; +} + +QHeaderView::down-arrow { + /* Those settings (border/width/height/background-color) solve bug */ + /* transparent arrow background and size */ + background-color: #C0C4C8; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url(":/qss_icons/light/rc/arrow_down.png"); +} + +QHeaderView::up-arrow { + background-color: #C0C4C8; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url(":/qss_icons/light/rc/arrow_up.png"); +} + +/* QToolBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbox + +--------------------------------------------------------------------------- */ +QToolBox { + padding: 0px; + border: 0px; + border: 1px solid #C0C4C8; +} + +QToolBox:selected { + padding: 0px; + border: 2px solid #9FCBFF; +} + +QToolBox::tab { + background-color: #FAFAFA; + border: 1px solid #C0C4C8; + color: #19232D; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QToolBox::tab:disabled { + color: #9DA9B5; +} + +QToolBox::tab:selected { + background-color: #ACB1B6; + border-bottom: 2px solid #9FCBFF; +} + +QToolBox::tab:selected:disabled { + background-color: #C0C4C8; + border-bottom: 2px solid #DAEDFF; +} + +QToolBox::tab:!selected { + background-color: #C0C4C8; + border-bottom: 2px solid #C0C4C8; +} + +QToolBox::tab:!selected:disabled { + background-color: #FAFAFA; +} + +QToolBox::tab:hover { + border-color: #73C7FF; + border-bottom: 2px solid #73C7FF; +} + +QToolBox QScrollArea { + padding: 0px; + border: 0px; + background-color: #FAFAFA; +} + +/* QFrame ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe +https://doc.qt.io/qt-5/qframe.html#-prop +https://doc.qt.io/qt-5/qframe.html#details +https://stackoverflow.com/questions/14581498/qt-stylesheet-for-hline-vline-color + +--------------------------------------------------------------------------- */ +/* (dot) .QFrame fix #141, #126, #123 */ +.QFrame { + border-radius: 4px; + border: 1px solid #C0C4C8; + /* No frame */ + /* HLine */ + /* HLine */ +} + +.QFrame[frameShape="0"] { + border-radius: 4px; + border: 1px transparent #C0C4C8; +} + +.QFrame[frameShape="4"] { + max-height: 2px; + border: none; + background-color: #C0C4C8; +} + +.QFrame[frameShape="5"] { + max-width: 2px; + border: none; + background-color: #C0C4C8; +} + +/* QSplitter -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsplitter + +--------------------------------------------------------------------------- */ +QSplitter { + background-color: #C0C4C8; + spacing: 0px; + padding: 0px; + margin: 0px; +} + +QSplitter::handle { + background-color: #C0C4C8; + border: 0px solid #FAFAFA; + spacing: 0px; + padding: 1px; + margin: 0px; +} + +QSplitter::handle:hover { + background-color: #788D9C; +} + +QSplitter::handle:horizontal { + width: 5px; + image: url(":/qss_icons/light/rc/line_vertical.png"); +} + +QSplitter::handle:vertical { + height: 5px; + image: url(":/qss_icons/light/rc/line_horizontal.png"); +} + +/* QDateEdit, QDateTimeEdit ----------------------------------------------- + +--------------------------------------------------------------------------- */ +QDateEdit, QDateTimeEdit { + selection-background-color: #9FCBFF; + border-style: solid; + border: 1px solid #C0C4C8; + border-radius: 4px; + /* This fixes 103, 111 */ + padding-top: 2px; + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + min-width: 10px; +} + +QDateEdit:on, QDateTimeEdit:on { + selection-background-color: #9FCBFF; +} + +QDateEdit::drop-down, QDateTimeEdit::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid #C0C4C8; +} + +QDateEdit::down-arrow, QDateTimeEdit::down-arrow { + image: url(":/qss_icons/light/rc/arrow_down_disabled.png"); + height: 8px; + width: 8px; +} + +QDateEdit::down-arrow:on, QDateEdit::down-arrow:hover, QDateEdit::down-arrow:focus, QDateTimeEdit::down-arrow:on, QDateTimeEdit::down-arrow:hover, QDateTimeEdit::down-arrow:focus { + image: url(":/qss_icons/light/rc/arrow_down.png"); +} + +QDateEdit QAbstractItemView, QDateTimeEdit QAbstractItemView { + background-color: #FAFAFA; + border-radius: 4px; + border: 1px solid #C0C4C8; + selection-background-color: #9FCBFF; +} + +/* QAbstractView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractView:hover { + border: 1px solid #9FCBFF; + color: #19232D; +} + +QAbstractView:selected { + background: #9FCBFF; + color: #C0C4C8; +} + +/* PlotWidget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +PlotWidget { + /* Fix cut labels in plots #134 */ + padding: 0px; +} diff --git a/src/qdarkstyle/light/main.scss b/src/qdarkstyle/light/main.scss new file mode 100644 index 000000000..5082a46ec --- /dev/null +++ b/src/qdarkstyle/light/main.scss @@ -0,0 +1,4 @@ +/* Dark Style - QDarkStyleSheet ------------------------------------------ */ + +@import '_variables'; +@import '../qss/_styles'; diff --git a/src/qdarkstyle/light/rc/.keep b/src/qdarkstyle/light/rc/.keep new file mode 100644 index 000000000..8d1c8b69c --- /dev/null +++ b/src/qdarkstyle/light/rc/.keep @@ -0,0 +1 @@ + diff --git a/src/qdarkstyle/light/rc/arrow_down.png b/src/qdarkstyle/light/rc/arrow_down.png new file mode 100644 index 000000000..8b8f1f255 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_down.png differ diff --git a/src/qdarkstyle/light/rc/arrow_down@2x.png b/src/qdarkstyle/light/rc/arrow_down@2x.png new file mode 100644 index 000000000..5e364fc78 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_down@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_down_disabled.png b/src/qdarkstyle/light/rc/arrow_down_disabled.png new file mode 100644 index 000000000..22295904e Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_down_disabled.png differ diff --git a/src/qdarkstyle/light/rc/arrow_down_disabled@2x.png b/src/qdarkstyle/light/rc/arrow_down_disabled@2x.png new file mode 100644 index 000000000..62991053e Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_down_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_down_focus.png b/src/qdarkstyle/light/rc/arrow_down_focus.png new file mode 100644 index 000000000..1747e0167 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_down_focus.png differ diff --git a/src/qdarkstyle/light/rc/arrow_down_focus@2x.png b/src/qdarkstyle/light/rc/arrow_down_focus@2x.png new file mode 100644 index 000000000..98672c91b Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_down_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_down_pressed.png b/src/qdarkstyle/light/rc/arrow_down_pressed.png new file mode 100644 index 000000000..384904399 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_down_pressed.png differ diff --git a/src/qdarkstyle/light/rc/arrow_down_pressed@2x.png b/src/qdarkstyle/light/rc/arrow_down_pressed@2x.png new file mode 100644 index 000000000..d17a9b5e6 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_down_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_left.png b/src/qdarkstyle/light/rc/arrow_left.png new file mode 100644 index 000000000..7d64295e3 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_left.png differ diff --git a/src/qdarkstyle/light/rc/arrow_left@2x.png b/src/qdarkstyle/light/rc/arrow_left@2x.png new file mode 100644 index 000000000..5582f64c6 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_left@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_left_disabled.png b/src/qdarkstyle/light/rc/arrow_left_disabled.png new file mode 100644 index 000000000..c9de6a70b Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_left_disabled.png differ diff --git a/src/qdarkstyle/light/rc/arrow_left_disabled@2x.png b/src/qdarkstyle/light/rc/arrow_left_disabled@2x.png new file mode 100644 index 000000000..34b9335e9 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_left_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_left_focus.png b/src/qdarkstyle/light/rc/arrow_left_focus.png new file mode 100644 index 000000000..aca7f7066 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_left_focus.png differ diff --git a/src/qdarkstyle/light/rc/arrow_left_focus@2x.png b/src/qdarkstyle/light/rc/arrow_left_focus@2x.png new file mode 100644 index 000000000..7da0ddf69 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_left_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_left_pressed.png b/src/qdarkstyle/light/rc/arrow_left_pressed.png new file mode 100644 index 000000000..1850c7448 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_left_pressed.png differ diff --git a/src/qdarkstyle/light/rc/arrow_left_pressed@2x.png b/src/qdarkstyle/light/rc/arrow_left_pressed@2x.png new file mode 100644 index 000000000..b718d7a01 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_left_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_right.png b/src/qdarkstyle/light/rc/arrow_right.png new file mode 100644 index 000000000..b802620be Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_right.png differ diff --git a/src/qdarkstyle/light/rc/arrow_right@2x.png b/src/qdarkstyle/light/rc/arrow_right@2x.png new file mode 100644 index 000000000..78212102c Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_right@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_right_disabled.png b/src/qdarkstyle/light/rc/arrow_right_disabled.png new file mode 100644 index 000000000..49fb80bf3 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_right_disabled.png differ diff --git a/src/qdarkstyle/light/rc/arrow_right_disabled@2x.png b/src/qdarkstyle/light/rc/arrow_right_disabled@2x.png new file mode 100644 index 000000000..988efd736 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_right_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_right_focus.png b/src/qdarkstyle/light/rc/arrow_right_focus.png new file mode 100644 index 000000000..cf10a6c78 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_right_focus.png differ diff --git a/src/qdarkstyle/light/rc/arrow_right_focus@2x.png b/src/qdarkstyle/light/rc/arrow_right_focus@2x.png new file mode 100644 index 000000000..7b294ee79 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_right_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_right_pressed.png b/src/qdarkstyle/light/rc/arrow_right_pressed.png new file mode 100644 index 000000000..a97f9dd82 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_right_pressed.png differ diff --git a/src/qdarkstyle/light/rc/arrow_right_pressed@2x.png b/src/qdarkstyle/light/rc/arrow_right_pressed@2x.png new file mode 100644 index 000000000..8d92cf25c Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_right_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_up.png b/src/qdarkstyle/light/rc/arrow_up.png new file mode 100644 index 000000000..cddf4edc6 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_up.png differ diff --git a/src/qdarkstyle/light/rc/arrow_up@2x.png b/src/qdarkstyle/light/rc/arrow_up@2x.png new file mode 100644 index 000000000..aacbe6583 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_up@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_up_disabled.png b/src/qdarkstyle/light/rc/arrow_up_disabled.png new file mode 100644 index 000000000..837da81e4 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_up_disabled.png differ diff --git a/src/qdarkstyle/light/rc/arrow_up_disabled@2x.png b/src/qdarkstyle/light/rc/arrow_up_disabled@2x.png new file mode 100644 index 000000000..baad7104d Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_up_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_up_focus.png b/src/qdarkstyle/light/rc/arrow_up_focus.png new file mode 100644 index 000000000..f00dd871f Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_up_focus.png differ diff --git a/src/qdarkstyle/light/rc/arrow_up_focus@2x.png b/src/qdarkstyle/light/rc/arrow_up_focus@2x.png new file mode 100644 index 000000000..ae9383e5f Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_up_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/arrow_up_pressed.png b/src/qdarkstyle/light/rc/arrow_up_pressed.png new file mode 100644 index 000000000..3d25e335c Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_up_pressed.png differ diff --git a/src/qdarkstyle/light/rc/arrow_up_pressed@2x.png b/src/qdarkstyle/light/rc/arrow_up_pressed@2x.png new file mode 100644 index 000000000..62230b8f0 Binary files /dev/null and b/src/qdarkstyle/light/rc/arrow_up_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/base_icon.png b/src/qdarkstyle/light/rc/base_icon.png new file mode 100644 index 000000000..bb00857a4 Binary files /dev/null and b/src/qdarkstyle/light/rc/base_icon.png differ diff --git a/src/qdarkstyle/light/rc/base_icon@2x.png b/src/qdarkstyle/light/rc/base_icon@2x.png new file mode 100644 index 000000000..bc4ab78a2 Binary files /dev/null and b/src/qdarkstyle/light/rc/base_icon@2x.png differ diff --git a/src/qdarkstyle/light/rc/base_icon_disabled.png b/src/qdarkstyle/light/rc/base_icon_disabled.png new file mode 100644 index 000000000..bb00857a4 Binary files /dev/null and b/src/qdarkstyle/light/rc/base_icon_disabled.png differ diff --git a/src/qdarkstyle/light/rc/base_icon_disabled@2x.png b/src/qdarkstyle/light/rc/base_icon_disabled@2x.png new file mode 100644 index 000000000..bc4ab78a2 Binary files /dev/null and b/src/qdarkstyle/light/rc/base_icon_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/base_icon_focus.png b/src/qdarkstyle/light/rc/base_icon_focus.png new file mode 100644 index 000000000..bb00857a4 Binary files /dev/null and b/src/qdarkstyle/light/rc/base_icon_focus.png differ diff --git a/src/qdarkstyle/light/rc/base_icon_focus@2x.png b/src/qdarkstyle/light/rc/base_icon_focus@2x.png new file mode 100644 index 000000000..bc4ab78a2 Binary files /dev/null and b/src/qdarkstyle/light/rc/base_icon_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/base_icon_pressed.png b/src/qdarkstyle/light/rc/base_icon_pressed.png new file mode 100644 index 000000000..bb00857a4 Binary files /dev/null and b/src/qdarkstyle/light/rc/base_icon_pressed.png differ diff --git a/src/qdarkstyle/light/rc/base_icon_pressed@2x.png b/src/qdarkstyle/light/rc/base_icon_pressed@2x.png new file mode 100644 index 000000000..bc4ab78a2 Binary files /dev/null and b/src/qdarkstyle/light/rc/base_icon_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_closed.png b/src/qdarkstyle/light/rc/branch_closed.png new file mode 100644 index 000000000..756c161fb Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_closed.png differ diff --git a/src/qdarkstyle/light/rc/branch_closed@2x.png b/src/qdarkstyle/light/rc/branch_closed@2x.png new file mode 100644 index 000000000..16617f5c9 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_closed@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_closed_disabled.png b/src/qdarkstyle/light/rc/branch_closed_disabled.png new file mode 100644 index 000000000..0fd49ba6d Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_closed_disabled.png differ diff --git a/src/qdarkstyle/light/rc/branch_closed_disabled@2x.png b/src/qdarkstyle/light/rc/branch_closed_disabled@2x.png new file mode 100644 index 000000000..e5d25314b Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_closed_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_closed_focus.png b/src/qdarkstyle/light/rc/branch_closed_focus.png new file mode 100644 index 000000000..d3e1453de Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_closed_focus.png differ diff --git a/src/qdarkstyle/light/rc/branch_closed_focus@2x.png b/src/qdarkstyle/light/rc/branch_closed_focus@2x.png new file mode 100644 index 000000000..c8a5ce119 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_closed_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_closed_pressed.png b/src/qdarkstyle/light/rc/branch_closed_pressed.png new file mode 100644 index 000000000..88756c8a6 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_closed_pressed.png differ diff --git a/src/qdarkstyle/light/rc/branch_closed_pressed@2x.png b/src/qdarkstyle/light/rc/branch_closed_pressed@2x.png new file mode 100644 index 000000000..9c80d487c Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_closed_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_end.png b/src/qdarkstyle/light/rc/branch_end.png new file mode 100644 index 000000000..5b3ef0d24 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_end.png differ diff --git a/src/qdarkstyle/light/rc/branch_end@2x.png b/src/qdarkstyle/light/rc/branch_end@2x.png new file mode 100644 index 000000000..b0c3ad8a2 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_end@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_end_disabled.png b/src/qdarkstyle/light/rc/branch_end_disabled.png new file mode 100644 index 000000000..2540b49f1 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_end_disabled.png differ diff --git a/src/qdarkstyle/light/rc/branch_end_disabled@2x.png b/src/qdarkstyle/light/rc/branch_end_disabled@2x.png new file mode 100644 index 000000000..68671d4c7 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_end_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_end_focus.png b/src/qdarkstyle/light/rc/branch_end_focus.png new file mode 100644 index 000000000..4c6ecc9d5 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_end_focus.png differ diff --git a/src/qdarkstyle/light/rc/branch_end_focus@2x.png b/src/qdarkstyle/light/rc/branch_end_focus@2x.png new file mode 100644 index 000000000..32491c6ae Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_end_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_end_pressed.png b/src/qdarkstyle/light/rc/branch_end_pressed.png new file mode 100644 index 000000000..33a1adf62 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_end_pressed.png differ diff --git a/src/qdarkstyle/light/rc/branch_end_pressed@2x.png b/src/qdarkstyle/light/rc/branch_end_pressed@2x.png new file mode 100644 index 000000000..4f8d2c8e0 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_end_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_line.png b/src/qdarkstyle/light/rc/branch_line.png new file mode 100644 index 000000000..f94928a48 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_line.png differ diff --git a/src/qdarkstyle/light/rc/branch_line@2x.png b/src/qdarkstyle/light/rc/branch_line@2x.png new file mode 100644 index 000000000..b956af189 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_line@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_line_disabled.png b/src/qdarkstyle/light/rc/branch_line_disabled.png new file mode 100644 index 000000000..7617849c3 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_line_disabled.png differ diff --git a/src/qdarkstyle/light/rc/branch_line_disabled@2x.png b/src/qdarkstyle/light/rc/branch_line_disabled@2x.png new file mode 100644 index 000000000..970ed0614 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_line_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_line_focus.png b/src/qdarkstyle/light/rc/branch_line_focus.png new file mode 100644 index 000000000..8a1a8a722 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_line_focus.png differ diff --git a/src/qdarkstyle/light/rc/branch_line_focus@2x.png b/src/qdarkstyle/light/rc/branch_line_focus@2x.png new file mode 100644 index 000000000..4b1e3e267 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_line_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_line_pressed.png b/src/qdarkstyle/light/rc/branch_line_pressed.png new file mode 100644 index 000000000..f73928880 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_line_pressed.png differ diff --git a/src/qdarkstyle/light/rc/branch_line_pressed@2x.png b/src/qdarkstyle/light/rc/branch_line_pressed@2x.png new file mode 100644 index 000000000..6861baf55 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_line_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_more.png b/src/qdarkstyle/light/rc/branch_more.png new file mode 100644 index 000000000..150b7d069 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_more.png differ diff --git a/src/qdarkstyle/light/rc/branch_more@2x.png b/src/qdarkstyle/light/rc/branch_more@2x.png new file mode 100644 index 000000000..0135f10a6 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_more@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_more_disabled.png b/src/qdarkstyle/light/rc/branch_more_disabled.png new file mode 100644 index 000000000..25b797451 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_more_disabled.png differ diff --git a/src/qdarkstyle/light/rc/branch_more_disabled@2x.png b/src/qdarkstyle/light/rc/branch_more_disabled@2x.png new file mode 100644 index 000000000..dd21fce5b Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_more_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_more_focus.png b/src/qdarkstyle/light/rc/branch_more_focus.png new file mode 100644 index 000000000..20e3d236f Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_more_focus.png differ diff --git a/src/qdarkstyle/light/rc/branch_more_focus@2x.png b/src/qdarkstyle/light/rc/branch_more_focus@2x.png new file mode 100644 index 000000000..af6c5db82 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_more_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_more_pressed.png b/src/qdarkstyle/light/rc/branch_more_pressed.png new file mode 100644 index 000000000..26aaca5a1 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_more_pressed.png differ diff --git a/src/qdarkstyle/light/rc/branch_more_pressed@2x.png b/src/qdarkstyle/light/rc/branch_more_pressed@2x.png new file mode 100644 index 000000000..e2c6627bd Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_more_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_open.png b/src/qdarkstyle/light/rc/branch_open.png new file mode 100644 index 000000000..1c35b8c6f Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_open.png differ diff --git a/src/qdarkstyle/light/rc/branch_open@2x.png b/src/qdarkstyle/light/rc/branch_open@2x.png new file mode 100644 index 000000000..3854f1cbd Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_open@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_open_disabled.png b/src/qdarkstyle/light/rc/branch_open_disabled.png new file mode 100644 index 000000000..8fd4936a9 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_open_disabled.png differ diff --git a/src/qdarkstyle/light/rc/branch_open_disabled@2x.png b/src/qdarkstyle/light/rc/branch_open_disabled@2x.png new file mode 100644 index 000000000..70ac2ecda Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_open_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_open_focus.png b/src/qdarkstyle/light/rc/branch_open_focus.png new file mode 100644 index 000000000..6d604b5f4 Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_open_focus.png differ diff --git a/src/qdarkstyle/light/rc/branch_open_focus@2x.png b/src/qdarkstyle/light/rc/branch_open_focus@2x.png new file mode 100644 index 000000000..96337aa6e Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_open_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/branch_open_pressed.png b/src/qdarkstyle/light/rc/branch_open_pressed.png new file mode 100644 index 000000000..178f1bcbe Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_open_pressed.png differ diff --git a/src/qdarkstyle/light/rc/branch_open_pressed@2x.png b/src/qdarkstyle/light/rc/branch_open_pressed@2x.png new file mode 100644 index 000000000..7ff7b8aba Binary files /dev/null and b/src/qdarkstyle/light/rc/branch_open_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_checked.png b/src/qdarkstyle/light/rc/checkbox_checked.png new file mode 100644 index 000000000..fd1d4a4a7 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_checked.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_checked@2x.png b/src/qdarkstyle/light/rc/checkbox_checked@2x.png new file mode 100644 index 000000000..bbcc43507 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_checked@2x.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_checked_disabled.png b/src/qdarkstyle/light/rc/checkbox_checked_disabled.png new file mode 100644 index 000000000..34492ed42 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_checked_disabled.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_checked_disabled@2x.png b/src/qdarkstyle/light/rc/checkbox_checked_disabled@2x.png new file mode 100644 index 000000000..e4b77e452 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_checked_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_checked_focus.png b/src/qdarkstyle/light/rc/checkbox_checked_focus.png new file mode 100644 index 000000000..31e2111b9 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_checked_focus.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_checked_focus@2x.png b/src/qdarkstyle/light/rc/checkbox_checked_focus@2x.png new file mode 100644 index 000000000..a651ca563 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_checked_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_checked_pressed.png b/src/qdarkstyle/light/rc/checkbox_checked_pressed.png new file mode 100644 index 000000000..0863079ae Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_checked_pressed.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_checked_pressed@2x.png b/src/qdarkstyle/light/rc/checkbox_checked_pressed@2x.png new file mode 100644 index 000000000..38874b2b6 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_checked_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_indeterminate.png b/src/qdarkstyle/light/rc/checkbox_indeterminate.png new file mode 100644 index 000000000..37d03be03 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_indeterminate.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_indeterminate@2x.png b/src/qdarkstyle/light/rc/checkbox_indeterminate@2x.png new file mode 100644 index 000000000..df49db526 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_indeterminate@2x.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_indeterminate_disabled.png b/src/qdarkstyle/light/rc/checkbox_indeterminate_disabled.png new file mode 100644 index 000000000..dd53a1e95 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_indeterminate_disabled.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_indeterminate_disabled@2x.png b/src/qdarkstyle/light/rc/checkbox_indeterminate_disabled@2x.png new file mode 100644 index 000000000..8cd127c84 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_indeterminate_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_indeterminate_focus.png b/src/qdarkstyle/light/rc/checkbox_indeterminate_focus.png new file mode 100644 index 000000000..25afd03ba Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_indeterminate_focus.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_indeterminate_focus@2x.png b/src/qdarkstyle/light/rc/checkbox_indeterminate_focus@2x.png new file mode 100644 index 000000000..fe3685824 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_indeterminate_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_indeterminate_pressed.png b/src/qdarkstyle/light/rc/checkbox_indeterminate_pressed.png new file mode 100644 index 000000000..e290fb82f Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_indeterminate_pressed.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_indeterminate_pressed@2x.png b/src/qdarkstyle/light/rc/checkbox_indeterminate_pressed@2x.png new file mode 100644 index 000000000..97efff28d Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_indeterminate_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_unchecked.png b/src/qdarkstyle/light/rc/checkbox_unchecked.png new file mode 100644 index 000000000..8e845d327 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_unchecked.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_unchecked@2x.png b/src/qdarkstyle/light/rc/checkbox_unchecked@2x.png new file mode 100644 index 000000000..d4b9b6ff9 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_unchecked@2x.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_unchecked_disabled.png b/src/qdarkstyle/light/rc/checkbox_unchecked_disabled.png new file mode 100644 index 000000000..07b60303d Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_unchecked_disabled.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_unchecked_disabled@2x.png b/src/qdarkstyle/light/rc/checkbox_unchecked_disabled@2x.png new file mode 100644 index 000000000..84ac5e704 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_unchecked_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_unchecked_focus.png b/src/qdarkstyle/light/rc/checkbox_unchecked_focus.png new file mode 100644 index 000000000..257f6dd4f Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_unchecked_focus.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_unchecked_focus@2x.png b/src/qdarkstyle/light/rc/checkbox_unchecked_focus@2x.png new file mode 100644 index 000000000..275d3b934 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_unchecked_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_unchecked_pressed.png b/src/qdarkstyle/light/rc/checkbox_unchecked_pressed.png new file mode 100644 index 000000000..2d2a134e9 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_unchecked_pressed.png differ diff --git a/src/qdarkstyle/light/rc/checkbox_unchecked_pressed@2x.png b/src/qdarkstyle/light/rc/checkbox_unchecked_pressed@2x.png new file mode 100644 index 000000000..46750f484 Binary files /dev/null and b/src/qdarkstyle/light/rc/checkbox_unchecked_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/line_horizontal.png b/src/qdarkstyle/light/rc/line_horizontal.png new file mode 100644 index 000000000..f633b1163 Binary files /dev/null and b/src/qdarkstyle/light/rc/line_horizontal.png differ diff --git a/src/qdarkstyle/light/rc/line_horizontal@2x.png b/src/qdarkstyle/light/rc/line_horizontal@2x.png new file mode 100644 index 000000000..b20b0863e Binary files /dev/null and b/src/qdarkstyle/light/rc/line_horizontal@2x.png differ diff --git a/src/qdarkstyle/light/rc/line_horizontal_disabled.png b/src/qdarkstyle/light/rc/line_horizontal_disabled.png new file mode 100644 index 000000000..4f82c8542 Binary files /dev/null and b/src/qdarkstyle/light/rc/line_horizontal_disabled.png differ diff --git a/src/qdarkstyle/light/rc/line_horizontal_disabled@2x.png b/src/qdarkstyle/light/rc/line_horizontal_disabled@2x.png new file mode 100644 index 000000000..c5e1798aa Binary files /dev/null and b/src/qdarkstyle/light/rc/line_horizontal_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/line_horizontal_focus.png b/src/qdarkstyle/light/rc/line_horizontal_focus.png new file mode 100644 index 000000000..bd87c6842 Binary files /dev/null and b/src/qdarkstyle/light/rc/line_horizontal_focus.png differ diff --git a/src/qdarkstyle/light/rc/line_horizontal_focus@2x.png b/src/qdarkstyle/light/rc/line_horizontal_focus@2x.png new file mode 100644 index 000000000..f3fc5321c Binary files /dev/null and b/src/qdarkstyle/light/rc/line_horizontal_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/line_horizontal_pressed.png b/src/qdarkstyle/light/rc/line_horizontal_pressed.png new file mode 100644 index 000000000..5dd8eb284 Binary files /dev/null and b/src/qdarkstyle/light/rc/line_horizontal_pressed.png differ diff --git a/src/qdarkstyle/light/rc/line_horizontal_pressed@2x.png b/src/qdarkstyle/light/rc/line_horizontal_pressed@2x.png new file mode 100644 index 000000000..a79bb70b5 Binary files /dev/null and b/src/qdarkstyle/light/rc/line_horizontal_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/line_vertical.png b/src/qdarkstyle/light/rc/line_vertical.png new file mode 100644 index 000000000..a1ce50905 Binary files /dev/null and b/src/qdarkstyle/light/rc/line_vertical.png differ diff --git a/src/qdarkstyle/light/rc/line_vertical@2x.png b/src/qdarkstyle/light/rc/line_vertical@2x.png new file mode 100644 index 000000000..4763755b5 Binary files /dev/null and b/src/qdarkstyle/light/rc/line_vertical@2x.png differ diff --git a/src/qdarkstyle/light/rc/line_vertical_disabled.png b/src/qdarkstyle/light/rc/line_vertical_disabled.png new file mode 100644 index 000000000..efc3f49d2 Binary files /dev/null and b/src/qdarkstyle/light/rc/line_vertical_disabled.png differ diff --git a/src/qdarkstyle/light/rc/line_vertical_disabled@2x.png b/src/qdarkstyle/light/rc/line_vertical_disabled@2x.png new file mode 100644 index 000000000..3a711cf52 Binary files /dev/null and b/src/qdarkstyle/light/rc/line_vertical_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/line_vertical_focus.png b/src/qdarkstyle/light/rc/line_vertical_focus.png new file mode 100644 index 000000000..43fcb1f3d Binary files /dev/null and b/src/qdarkstyle/light/rc/line_vertical_focus.png differ diff --git a/src/qdarkstyle/light/rc/line_vertical_focus@2x.png b/src/qdarkstyle/light/rc/line_vertical_focus@2x.png new file mode 100644 index 000000000..2b55586fb Binary files /dev/null and b/src/qdarkstyle/light/rc/line_vertical_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/line_vertical_pressed.png b/src/qdarkstyle/light/rc/line_vertical_pressed.png new file mode 100644 index 000000000..b5bcd9e08 Binary files /dev/null and b/src/qdarkstyle/light/rc/line_vertical_pressed.png differ diff --git a/src/qdarkstyle/light/rc/line_vertical_pressed@2x.png b/src/qdarkstyle/light/rc/line_vertical_pressed@2x.png new file mode 100644 index 000000000..69c9857dc Binary files /dev/null and b/src/qdarkstyle/light/rc/line_vertical_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/radio_checked.png b/src/qdarkstyle/light/rc/radio_checked.png new file mode 100644 index 000000000..f72a6e84f Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_checked.png differ diff --git a/src/qdarkstyle/light/rc/radio_checked@2x.png b/src/qdarkstyle/light/rc/radio_checked@2x.png new file mode 100644 index 000000000..dcb4e444d Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_checked@2x.png differ diff --git a/src/qdarkstyle/light/rc/radio_checked_disabled.png b/src/qdarkstyle/light/rc/radio_checked_disabled.png new file mode 100644 index 000000000..4009f74fa Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_checked_disabled.png differ diff --git a/src/qdarkstyle/light/rc/radio_checked_disabled@2x.png b/src/qdarkstyle/light/rc/radio_checked_disabled@2x.png new file mode 100644 index 000000000..060164b4c Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_checked_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/radio_checked_focus.png b/src/qdarkstyle/light/rc/radio_checked_focus.png new file mode 100644 index 000000000..4e0da9b14 Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_checked_focus.png differ diff --git a/src/qdarkstyle/light/rc/radio_checked_focus@2x.png b/src/qdarkstyle/light/rc/radio_checked_focus@2x.png new file mode 100644 index 000000000..2d659f13c Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_checked_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/radio_checked_pressed.png b/src/qdarkstyle/light/rc/radio_checked_pressed.png new file mode 100644 index 000000000..91f45ba32 Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_checked_pressed.png differ diff --git a/src/qdarkstyle/light/rc/radio_checked_pressed@2x.png b/src/qdarkstyle/light/rc/radio_checked_pressed@2x.png new file mode 100644 index 000000000..cb24b03b3 Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_checked_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/radio_unchecked.png b/src/qdarkstyle/light/rc/radio_unchecked.png new file mode 100644 index 000000000..8fac5d4f8 Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_unchecked.png differ diff --git a/src/qdarkstyle/light/rc/radio_unchecked@2x.png b/src/qdarkstyle/light/rc/radio_unchecked@2x.png new file mode 100644 index 000000000..87831756b Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_unchecked@2x.png differ diff --git a/src/qdarkstyle/light/rc/radio_unchecked_disabled.png b/src/qdarkstyle/light/rc/radio_unchecked_disabled.png new file mode 100644 index 000000000..d6de6b0b4 Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_unchecked_disabled.png differ diff --git a/src/qdarkstyle/light/rc/radio_unchecked_disabled@2x.png b/src/qdarkstyle/light/rc/radio_unchecked_disabled@2x.png new file mode 100644 index 000000000..93c558939 Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_unchecked_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/radio_unchecked_focus.png b/src/qdarkstyle/light/rc/radio_unchecked_focus.png new file mode 100644 index 000000000..6ae76c481 Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_unchecked_focus.png differ diff --git a/src/qdarkstyle/light/rc/radio_unchecked_focus@2x.png b/src/qdarkstyle/light/rc/radio_unchecked_focus@2x.png new file mode 100644 index 000000000..8888b5274 Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_unchecked_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/radio_unchecked_pressed.png b/src/qdarkstyle/light/rc/radio_unchecked_pressed.png new file mode 100644 index 000000000..e660846f5 Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_unchecked_pressed.png differ diff --git a/src/qdarkstyle/light/rc/radio_unchecked_pressed@2x.png b/src/qdarkstyle/light/rc/radio_unchecked_pressed@2x.png new file mode 100644 index 000000000..c133f6b12 Binary files /dev/null and b/src/qdarkstyle/light/rc/radio_unchecked_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_horizontal.png b/src/qdarkstyle/light/rc/toolbar_move_horizontal.png new file mode 100644 index 000000000..2edb67684 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_horizontal.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_horizontal@2x.png b/src/qdarkstyle/light/rc/toolbar_move_horizontal@2x.png new file mode 100644 index 000000000..f8390608d Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_horizontal@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_horizontal_disabled.png b/src/qdarkstyle/light/rc/toolbar_move_horizontal_disabled.png new file mode 100644 index 000000000..5961fc350 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_horizontal_disabled.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_horizontal_disabled@2x.png b/src/qdarkstyle/light/rc/toolbar_move_horizontal_disabled@2x.png new file mode 100644 index 000000000..b3ca0d9b5 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_horizontal_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_horizontal_focus.png b/src/qdarkstyle/light/rc/toolbar_move_horizontal_focus.png new file mode 100644 index 000000000..a2b9a7b81 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_horizontal_focus.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_horizontal_focus@2x.png b/src/qdarkstyle/light/rc/toolbar_move_horizontal_focus@2x.png new file mode 100644 index 000000000..73bd2d994 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_horizontal_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_horizontal_pressed.png b/src/qdarkstyle/light/rc/toolbar_move_horizontal_pressed.png new file mode 100644 index 000000000..c18f66d56 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_horizontal_pressed.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_horizontal_pressed@2x.png b/src/qdarkstyle/light/rc/toolbar_move_horizontal_pressed@2x.png new file mode 100644 index 000000000..fcbad73f5 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_horizontal_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_vertical.png b/src/qdarkstyle/light/rc/toolbar_move_vertical.png new file mode 100644 index 000000000..2e881ef48 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_vertical.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_vertical@2x.png b/src/qdarkstyle/light/rc/toolbar_move_vertical@2x.png new file mode 100644 index 000000000..3e37185a4 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_vertical@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_vertical_disabled.png b/src/qdarkstyle/light/rc/toolbar_move_vertical_disabled.png new file mode 100644 index 000000000..14d3f923d Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_vertical_disabled.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_vertical_disabled@2x.png b/src/qdarkstyle/light/rc/toolbar_move_vertical_disabled@2x.png new file mode 100644 index 000000000..22646afc0 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_vertical_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_vertical_focus.png b/src/qdarkstyle/light/rc/toolbar_move_vertical_focus.png new file mode 100644 index 000000000..c27874889 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_vertical_focus.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_vertical_focus@2x.png b/src/qdarkstyle/light/rc/toolbar_move_vertical_focus@2x.png new file mode 100644 index 000000000..9978da3b3 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_vertical_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_vertical_pressed.png b/src/qdarkstyle/light/rc/toolbar_move_vertical_pressed.png new file mode 100644 index 000000000..9c3996492 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_vertical_pressed.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_move_vertical_pressed@2x.png b/src/qdarkstyle/light/rc/toolbar_move_vertical_pressed@2x.png new file mode 100644 index 000000000..763751dca Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_move_vertical_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_horizontal.png b/src/qdarkstyle/light/rc/toolbar_separator_horizontal.png new file mode 100644 index 000000000..0d599e5ca Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_horizontal.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_horizontal@2x.png b/src/qdarkstyle/light/rc/toolbar_separator_horizontal@2x.png new file mode 100644 index 000000000..3e4666ad7 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_horizontal@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_horizontal_disabled.png b/src/qdarkstyle/light/rc/toolbar_separator_horizontal_disabled.png new file mode 100644 index 000000000..591f4dff5 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_horizontal_disabled.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_horizontal_disabled@2x.png b/src/qdarkstyle/light/rc/toolbar_separator_horizontal_disabled@2x.png new file mode 100644 index 000000000..bccdaf3c3 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_horizontal_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_horizontal_focus.png b/src/qdarkstyle/light/rc/toolbar_separator_horizontal_focus.png new file mode 100644 index 000000000..4674965ff Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_horizontal_focus.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_horizontal_focus@2x.png b/src/qdarkstyle/light/rc/toolbar_separator_horizontal_focus@2x.png new file mode 100644 index 000000000..89a876026 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_horizontal_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_horizontal_pressed.png b/src/qdarkstyle/light/rc/toolbar_separator_horizontal_pressed.png new file mode 100644 index 000000000..8f1f98911 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_horizontal_pressed.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_horizontal_pressed@2x.png b/src/qdarkstyle/light/rc/toolbar_separator_horizontal_pressed@2x.png new file mode 100644 index 000000000..7ef52e27b Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_horizontal_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_vertical.png b/src/qdarkstyle/light/rc/toolbar_separator_vertical.png new file mode 100644 index 000000000..06acdaab6 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_vertical.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_vertical@2x.png b/src/qdarkstyle/light/rc/toolbar_separator_vertical@2x.png new file mode 100644 index 000000000..28925a0a4 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_vertical@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_vertical_disabled.png b/src/qdarkstyle/light/rc/toolbar_separator_vertical_disabled.png new file mode 100644 index 000000000..bf79d6cd7 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_vertical_disabled.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_vertical_disabled@2x.png b/src/qdarkstyle/light/rc/toolbar_separator_vertical_disabled@2x.png new file mode 100644 index 000000000..f3a633cad Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_vertical_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_vertical_focus.png b/src/qdarkstyle/light/rc/toolbar_separator_vertical_focus.png new file mode 100644 index 000000000..c0d940e0f Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_vertical_focus.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_vertical_focus@2x.png b/src/qdarkstyle/light/rc/toolbar_separator_vertical_focus@2x.png new file mode 100644 index 000000000..a4ca04996 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_vertical_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_vertical_pressed.png b/src/qdarkstyle/light/rc/toolbar_separator_vertical_pressed.png new file mode 100644 index 000000000..cf16a05d1 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_vertical_pressed.png differ diff --git a/src/qdarkstyle/light/rc/toolbar_separator_vertical_pressed@2x.png b/src/qdarkstyle/light/rc/toolbar_separator_vertical_pressed@2x.png new file mode 100644 index 000000000..184855710 Binary files /dev/null and b/src/qdarkstyle/light/rc/toolbar_separator_vertical_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/transparent.png b/src/qdarkstyle/light/rc/transparent.png new file mode 100644 index 000000000..67753617f Binary files /dev/null and b/src/qdarkstyle/light/rc/transparent.png differ diff --git a/src/qdarkstyle/light/rc/transparent@2x.png b/src/qdarkstyle/light/rc/transparent@2x.png new file mode 100644 index 000000000..4012944b5 Binary files /dev/null and b/src/qdarkstyle/light/rc/transparent@2x.png differ diff --git a/src/qdarkstyle/light/rc/transparent_disabled.png b/src/qdarkstyle/light/rc/transparent_disabled.png new file mode 100644 index 000000000..67753617f Binary files /dev/null and b/src/qdarkstyle/light/rc/transparent_disabled.png differ diff --git a/src/qdarkstyle/light/rc/transparent_disabled@2x.png b/src/qdarkstyle/light/rc/transparent_disabled@2x.png new file mode 100644 index 000000000..4012944b5 Binary files /dev/null and b/src/qdarkstyle/light/rc/transparent_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/transparent_focus.png b/src/qdarkstyle/light/rc/transparent_focus.png new file mode 100644 index 000000000..67753617f Binary files /dev/null and b/src/qdarkstyle/light/rc/transparent_focus.png differ diff --git a/src/qdarkstyle/light/rc/transparent_focus@2x.png b/src/qdarkstyle/light/rc/transparent_focus@2x.png new file mode 100644 index 000000000..4012944b5 Binary files /dev/null and b/src/qdarkstyle/light/rc/transparent_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/transparent_pressed.png b/src/qdarkstyle/light/rc/transparent_pressed.png new file mode 100644 index 000000000..67753617f Binary files /dev/null and b/src/qdarkstyle/light/rc/transparent_pressed.png differ diff --git a/src/qdarkstyle/light/rc/transparent_pressed@2x.png b/src/qdarkstyle/light/rc/transparent_pressed@2x.png new file mode 100644 index 000000000..4012944b5 Binary files /dev/null and b/src/qdarkstyle/light/rc/transparent_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_close.png b/src/qdarkstyle/light/rc/window_close.png new file mode 100644 index 000000000..79f16fe47 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_close.png differ diff --git a/src/qdarkstyle/light/rc/window_close@2x.png b/src/qdarkstyle/light/rc/window_close@2x.png new file mode 100644 index 000000000..7152832aa Binary files /dev/null and b/src/qdarkstyle/light/rc/window_close@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_close_disabled.png b/src/qdarkstyle/light/rc/window_close_disabled.png new file mode 100644 index 000000000..6fafd3a40 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_close_disabled.png differ diff --git a/src/qdarkstyle/light/rc/window_close_disabled@2x.png b/src/qdarkstyle/light/rc/window_close_disabled@2x.png new file mode 100644 index 000000000..0a852da6b Binary files /dev/null and b/src/qdarkstyle/light/rc/window_close_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_close_focus.png b/src/qdarkstyle/light/rc/window_close_focus.png new file mode 100644 index 000000000..5745d2a51 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_close_focus.png differ diff --git a/src/qdarkstyle/light/rc/window_close_focus@2x.png b/src/qdarkstyle/light/rc/window_close_focus@2x.png new file mode 100644 index 000000000..f5bc16826 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_close_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_close_pressed.png b/src/qdarkstyle/light/rc/window_close_pressed.png new file mode 100644 index 000000000..c8dca67b6 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_close_pressed.png differ diff --git a/src/qdarkstyle/light/rc/window_close_pressed@2x.png b/src/qdarkstyle/light/rc/window_close_pressed@2x.png new file mode 100644 index 000000000..d0ec9a573 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_close_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_grip.png b/src/qdarkstyle/light/rc/window_grip.png new file mode 100644 index 000000000..dbde6c0a1 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_grip.png differ diff --git a/src/qdarkstyle/light/rc/window_grip@2x.png b/src/qdarkstyle/light/rc/window_grip@2x.png new file mode 100644 index 000000000..35072484a Binary files /dev/null and b/src/qdarkstyle/light/rc/window_grip@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_grip_disabled.png b/src/qdarkstyle/light/rc/window_grip_disabled.png new file mode 100644 index 000000000..4b5efea45 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_grip_disabled.png differ diff --git a/src/qdarkstyle/light/rc/window_grip_disabled@2x.png b/src/qdarkstyle/light/rc/window_grip_disabled@2x.png new file mode 100644 index 000000000..cb23cbdca Binary files /dev/null and b/src/qdarkstyle/light/rc/window_grip_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_grip_focus.png b/src/qdarkstyle/light/rc/window_grip_focus.png new file mode 100644 index 000000000..083b6653f Binary files /dev/null and b/src/qdarkstyle/light/rc/window_grip_focus.png differ diff --git a/src/qdarkstyle/light/rc/window_grip_focus@2x.png b/src/qdarkstyle/light/rc/window_grip_focus@2x.png new file mode 100644 index 000000000..0e6bf6400 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_grip_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_grip_pressed.png b/src/qdarkstyle/light/rc/window_grip_pressed.png new file mode 100644 index 000000000..3f35d2a55 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_grip_pressed.png differ diff --git a/src/qdarkstyle/light/rc/window_grip_pressed@2x.png b/src/qdarkstyle/light/rc/window_grip_pressed@2x.png new file mode 100644 index 000000000..5cc52ee4d Binary files /dev/null and b/src/qdarkstyle/light/rc/window_grip_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_minimize.png b/src/qdarkstyle/light/rc/window_minimize.png new file mode 100644 index 000000000..8441cab89 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_minimize.png differ diff --git a/src/qdarkstyle/light/rc/window_minimize@2x.png b/src/qdarkstyle/light/rc/window_minimize@2x.png new file mode 100644 index 000000000..407007fb9 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_minimize@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_minimize_disabled.png b/src/qdarkstyle/light/rc/window_minimize_disabled.png new file mode 100644 index 000000000..a29a8c2ba Binary files /dev/null and b/src/qdarkstyle/light/rc/window_minimize_disabled.png differ diff --git a/src/qdarkstyle/light/rc/window_minimize_disabled@2x.png b/src/qdarkstyle/light/rc/window_minimize_disabled@2x.png new file mode 100644 index 000000000..bc76829b6 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_minimize_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_minimize_focus.png b/src/qdarkstyle/light/rc/window_minimize_focus.png new file mode 100644 index 000000000..2db1960e4 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_minimize_focus.png differ diff --git a/src/qdarkstyle/light/rc/window_minimize_focus@2x.png b/src/qdarkstyle/light/rc/window_minimize_focus@2x.png new file mode 100644 index 000000000..b05fd312d Binary files /dev/null and b/src/qdarkstyle/light/rc/window_minimize_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_minimize_pressed.png b/src/qdarkstyle/light/rc/window_minimize_pressed.png new file mode 100644 index 000000000..baeecc093 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_minimize_pressed.png differ diff --git a/src/qdarkstyle/light/rc/window_minimize_pressed@2x.png b/src/qdarkstyle/light/rc/window_minimize_pressed@2x.png new file mode 100644 index 000000000..de3c819fd Binary files /dev/null and b/src/qdarkstyle/light/rc/window_minimize_pressed@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_undock.png b/src/qdarkstyle/light/rc/window_undock.png new file mode 100644 index 000000000..2f937bee6 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_undock.png differ diff --git a/src/qdarkstyle/light/rc/window_undock@2x.png b/src/qdarkstyle/light/rc/window_undock@2x.png new file mode 100644 index 000000000..62fb1c1c5 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_undock@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_undock_disabled.png b/src/qdarkstyle/light/rc/window_undock_disabled.png new file mode 100644 index 000000000..8255701f7 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_undock_disabled.png differ diff --git a/src/qdarkstyle/light/rc/window_undock_disabled@2x.png b/src/qdarkstyle/light/rc/window_undock_disabled@2x.png new file mode 100644 index 000000000..6016912e5 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_undock_disabled@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_undock_focus.png b/src/qdarkstyle/light/rc/window_undock_focus.png new file mode 100644 index 000000000..9ce07ab34 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_undock_focus.png differ diff --git a/src/qdarkstyle/light/rc/window_undock_focus@2x.png b/src/qdarkstyle/light/rc/window_undock_focus@2x.png new file mode 100644 index 000000000..b91963e8a Binary files /dev/null and b/src/qdarkstyle/light/rc/window_undock_focus@2x.png differ diff --git a/src/qdarkstyle/light/rc/window_undock_pressed.png b/src/qdarkstyle/light/rc/window_undock_pressed.png new file mode 100644 index 000000000..4302b637b Binary files /dev/null and b/src/qdarkstyle/light/rc/window_undock_pressed.png differ diff --git a/src/qdarkstyle/light/rc/window_undock_pressed@2x.png b/src/qdarkstyle/light/rc/window_undock_pressed@2x.png new file mode 100644 index 000000000..e47401292 Binary files /dev/null and b/src/qdarkstyle/light/rc/window_undock_pressed@2x.png differ diff --git a/src/qdarkstyle/qss/_styles.scss b/src/qdarkstyle/qss/_styles.scss new file mode 100644 index 000000000..107a62564 --- /dev/null +++ b/src/qdarkstyle/qss/_styles.scss @@ -0,0 +1,2352 @@ +/* + +See Qt documentation: + + - https://doc.qt.io/qt-5/stylesheet.html + - https://doc.qt.io/qt-5/stylesheet-reference.html + - https://doc.qt.io/qt-5/stylesheet-examples.html + +--------------------------------------------------------------------------- */ + + + +/* Reset elements ------------------------------------------------------------ + +Resetting everything helps to unify styles across different operating systems + +--------------------------------------------------------------------------- */ +* { + padding: 0px; + margin: 0px; + border: 0px; + border-style: none; + border-image: none; + outline: 0; +} + +/* specific reset for elements inside QToolBar */ +QToolBar * { + margin: 0px; + padding: 0px; + } + + + + +/* QWidget ---------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QWidget { + background-color: $COLOR_BACKGROUND_1; + border: 0px solid $COLOR_BACKGROUND_4; + padding: 0px; + color: $COLOR_TEXT_1; + selection-background-color: $COLOR_ACCENT_2; + selection-color: $COLOR_TEXT_1; + + &:disabled { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_4; + selection-background-color: $COLOR_ACCENT_1; + selection-color: $COLOR_TEXT_4; + } + + &::item { + + &:selected { + background-color: $COLOR_ACCENT_2; + } + + &:hover:!selected { + background-color: $COLOR_ACCENT_3; + } + } +} + +/* QMainWindow ------------------------------------------------------------ + +This adjusts the splitter in the dock widget, not qsplitter +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmainwindow + +--------------------------------------------------------------------------- */ +QMainWindow { + + &::separator { + background-color: $COLOR_BACKGROUND_4; + border: 0px solid $COLOR_BACKGROUND_1; + spacing: 0px; + padding: 2px; + + &:hover { + background-color: $COLOR_BACKGROUND_6; + border: 0px solid $COLOR_ACCENT_3; + } + + &:horizontal { + width: 5px; + margin-top: 2px; + margin-bottom: 2px; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/toolbar_separator_vertical.png'); + } + + &:vertical { + height: 5px; + margin-left: 2px; + margin-right: 2px; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/toolbar_separator_horizontal.png'); + } + } +} + +/* QToolTip --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtooltip + +--------------------------------------------------------------------------- */ +QToolTip { + background-color: $COLOR_ACCENT_2; + color: $COLOR_TEXT_1; + /* If you remove the border property, background stops working on Windows */ + border: none; + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + + /* Remove opacity, fix #174 - may need to use RGBA */ +} + +/* QStatusBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qstatusbar + +--------------------------------------------------------------------------- */ +QStatusBar { + border: $BORDER_2; + + /* Fixes Spyder #9120, #9121 */ + background: $COLOR_BACKGROUND_4; + + /* Fixes #205, white vertical borders separating items */ + &::item { + border: none; + } + + QToolTip { + background-color: $COLOR_ACCENT_3; + border: $BORDER_1; + color: $COLOR_BACKGROUND_1; + + /* Remove padding, for fix combo box tooltip */ + padding: 0px; + + /* Reducing transparency to read better */ + opacity: $OPACITY_TOOLTIP; + } + + QLabel { + /* Fixes Spyder #9120, #9121 */ + background: transparent; + } +} + +/* QCheckBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcheckbox + +--------------------------------------------------------------------------- */ +QCheckBox { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_1; + spacing: 4px; + outline: none; + padding-top: 4px; + padding-bottom: 4px; + + &:focus { + border: none; + } + + QWidget:disabled { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_4; + } + + &::indicator { + margin-left: 2px; + height: 14px; + width: 14px; + + &:unchecked { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_unchecked.png'); + + &:hover, + &:focus, + &:pressed { + border: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_unchecked_focus.png'); + } + + &:disabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_unchecked_disabled.png'); + } + } + + &:checked { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_checked.png'); + + &:hover, + &:focus, + &:pressed { + border: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_checked_focus.png'); + } + + &:disabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_checked_disabled.png'); + } + } + + &:indeterminate { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_indeterminate.png'); + + &:disabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_indeterminate_disabled.png'); + } + + &:focus, + &:hover, + &:pressed { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_indeterminate_focus.png'); + } + } + } +} + +/* QGroupBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qgroupbox + +--------------------------------------------------------------------------- */ +QGroupBox { + font-weight: bold; + border: $BORDER_2; + border-radius: $SIZE_BORDER_RADIUS; + padding: 2px; + margin-top: 6px; + margin-bottom: 4px; + + &::title { + subcontrol-origin: margin; + subcontrol-position: top left; + left: 4px; + padding-left: 2px; + padding-right: 4px; + padding-top: -4px; + } + + &::indicator { + margin-left: 2px; + margin-top: 2px; + padding: 0; + height: 14px; + width: 14px; + + &:unchecked { + border: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_unchecked.png'); + + &:hover, + &:focus, + &:pressed { + border: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_unchecked_focus.png'); + } + + &:disabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_unchecked_disabled.png'); + } + } + + &:checked { + border: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_checked.png'); + + + &:hover, + &:focus, + &:pressed { + border: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_checked_focus.png'); + } + + &:disabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_checked_disabled.png'); + } + } + } +} + +/* QRadioButton ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qradiobutton + +--------------------------------------------------------------------------- */ +QRadioButton { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_1; + spacing: 4px; + padding-top: 4px; + padding-bottom: 4px; + border: none; + outline: none; + + &:focus { + border: none; + } + + &:disabled { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_4; + border: none; + outline: none; + } + + QWidget { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_1; + spacing: 0px; + padding: 0px; + outline: none; + border: none; + } + + &::indicator { + border: none; + outline: none; + margin-left: 2px; + height: 14px; + width: 14px; + + &:unchecked { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/radio_unchecked.png'); + + &:hover, + &:focus, + &:pressed { + border: none; + outline: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/radio_unchecked_focus.png'); + } + + &:disabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/radio_unchecked_disabled.png'); + } + } + + &:checked { + border: none; + outline: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/radio_checked.png'); + + &:hover, + &:focus, + &:pressed { + border: none; + outline: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/radio_checked_focus.png'); + } + + &:disabled { + outline: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/radio_checked_disabled.png'); + } + } + } +} + +/* QMenuBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenubar + +--------------------------------------------------------------------------- */ +QMenuBar { + background-color: $COLOR_BACKGROUND_4; + padding: 2px; + border: $BORDER_1; + color: $COLOR_TEXT_1; + selection-background-color: $COLOR_ACCENT_3; + &:focus { + border: $BORDER_SELECTION_2; + } + + &::item { + background: transparent; + padding: 4px; + + &:selected { + padding: 4px; + background: transparent; + border: 0px solid $COLOR_BACKGROUND_4; + background-color: $COLOR_ACCENT_3; + } + + &:pressed { + padding: 4px; + border: 0px solid $COLOR_BACKGROUND_4; + background-color: $COLOR_ACCENT_3; + color: $COLOR_TEXT_1; + margin-bottom: 0px; + padding-bottom: 0px; + } + } +} + +/* QMenu ------------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qmenu + +--------------------------------------------------------------------------- */ +QMenu { + border: 0px solid $COLOR_BACKGROUND_4; + color: $COLOR_TEXT_1; + margin: 0px; + background-color: $COLOR_BACKGROUND_3; + selection-background-color: $COLOR_ACCENT_3; + + &::separator { + height: 1px; + background-color: $COLOR_BACKGROUND_6; + color: $COLOR_TEXT_1; + } + + &::icon { + margin: 0px; + padding-left: 8px; + } + + &::item { + background-color: $COLOR_BACKGROUND_3; + padding: 4px 24px 4px 8px; + /* Reserve space for selection border */ + border: 1px transparent $COLOR_BACKGROUND_4; + + &:selected { + color: $COLOR_TEXT_1; + background-color: $COLOR_ACCENT_3; + } + &:pressed { + background-color: $COLOR_ACCENT_3; + } + } + + &::indicator { + width: 14px; + height: 14px; + padding-left: 6px; + + /* non-exclusive indicator = check box style indicator (see QActionGroup::setExclusive) */ + &:non-exclusive { + + &:unchecked { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_unchecked.png'); + + &:hover, + &:focus, + &:pressed { + border: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_unchecked_focus.png'); + } + + &:disabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_unchecked_disabled.png'); + } + } + + &:checked { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_checked.png'); + + &:hover, + &:focus, + &:pressed { + border: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_checked_focus.png'); + } + + &:disabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_checked_disabled.png'); + } + } + + &:indeterminate { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_indeterminate.png'); + + &:disabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_indeterminate_disabled.png'); + } + + &:focus, + &:hover, + &:pressed { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_indeterminate_focus.png'); + } + } + } + + /* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */ + &:exclusive { + + &:unchecked { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/radio_unchecked.png'); + + &:hover, + &:focus, + &:pressed { + border: none; + outline: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/radio_unchecked_focus.png'); + } + + &:disabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/radio_unchecked_disabled.png'); + } + } + + &:checked { + border: none; + outline: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/radio_checked.png'); + + &:hover, + &:focus, + &:pressed { + border: none; + outline: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/radio_checked_focus.png'); + } + + &:disabled { + outline: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/radio_checked_disabled.png'); + } + } + } + } + + &::right-arrow { + margin: 5px; + padding-left:12px; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_right.png'); + height: 12px; + width: 12px; + } +} + +/* QAbstractItemView ------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QAbstractItemView { + alternate-background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_1; + border: $BORDER_2; + border-radius: $SIZE_BORDER_RADIUS; + + QLineEdit { + padding: 2px; + } +} + +/* QAbstractScrollArea ---------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QAbstractScrollArea { + background-color: $COLOR_BACKGROUND_1; + border: $BORDER_2; + border-radius: $SIZE_BORDER_RADIUS; + /* fix #159 */ + padding: 2px; + /* remove min-height to fix #244 */ + color: $COLOR_TEXT_1; + + &:disabled { + color: $COLOR_TEXT_4; + } +} + +/* QScrollArea ------------------------------------------------------------ + +--------------------------------------------------------------------------- */ +QScrollArea QWidget QWidget:disabled { + background-color: $COLOR_BACKGROUND_1; +} + +/* QScrollBar ------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qscrollbar + +--------------------------------------------------------------------------- */ +QScrollBar { + + &:horizontal { + height: 16px; + margin: 2px 16px 2px 16px; + border: $BORDER_2; + border-radius: $SIZE_BORDER_RADIUS; + background-color: $COLOR_BACKGROUND_1; + } + + &:vertical { + background-color: $COLOR_BACKGROUND_1; + width: 16px; + margin: 16px 2px 16px 2px; + border: $BORDER_2; + border-radius: $SIZE_BORDER_RADIUS; + } + + &::handle { + + &:horizontal { + background-color: $COLOR_BACKGROUND_6; + border: $BORDER_2; + border-radius: $SIZE_BORDER_RADIUS; + min-width: 8px; + + &:hover { + background-color: $COLOR_ACCENT_2; + border: $COLOR_ACCENT_2; + border-radius: $SIZE_BORDER_RADIUS; + min-width: 8px; + } + + &:focus { + border: $BORDER_SELECTION_3; + } + } + + &:vertical { + background-color: $COLOR_BACKGROUND_6; + border: $BORDER_2; + min-height: 8px; + border-radius: $SIZE_BORDER_RADIUS; + + &:hover { + background-color: $COLOR_ACCENT_2; + border: $COLOR_ACCENT_2; + border-radius: $SIZE_BORDER_RADIUS; + min-height: 8px; + } + + &:focus { + border: $BORDER_SELECTION_3; + } + } + } + + &::add-line { + + &:horizontal { + margin: 0px 0px 0px 0px; + border-image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_right_disabled.png'); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; + + &:hover, + &:on { + border-image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_right.png'); + height: 12px; + width: 12px; + subcontrol-position: right; + subcontrol-origin: margin; + } + } + + &:vertical { + margin: 3px 0px 3px 0px; + border-image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_down_disabled.png'); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; + + &:hover, + &:on { + border-image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_down.png'); + height: 12px; + width: 12px; + subcontrol-position: bottom; + subcontrol-origin: margin; + } + } + } + + &::sub-line { + &:horizontal { + margin: 0px 3px 0px 3px; + border-image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_left_disabled.png'); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; + + &:hover, + &:on { + border-image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_left.png'); + height: 12px; + width: 12px; + subcontrol-position: left; + subcontrol-origin: margin; + } + } + + &:vertical { + margin: 3px 0px 3px 0px; + border-image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_up_disabled.png'); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; + + &:hover, + &:on { + border-image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_up.png'); + height: 12px; + width: 12px; + subcontrol-position: top; + subcontrol-origin: margin; + } + } + } + + &::up-arrow:horizontal, + &::down-arrow:horizontal { + background: none; + } + + &::up-arrow:vertical, + &::down-arrow:vertical { + background: none; + } + + &::add-page:horizontal, + &::sub-page:horizontal { + background: none; + } + + &::add-page:vertical, + &::sub-page:vertical { + background: none; + } +} + +/* QTextEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-specific-widgets + +--------------------------------------------------------------------------- */ +QTextEdit { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_1; + border-radius: $SIZE_BORDER_RADIUS; + border: $BORDER_2; + + &:focus { + border: $BORDER_SELECTION_3; + } + + &:selected { + background: $COLOR_ACCENT_2; + color: $COLOR_BACKGROUND_4; + } +} + +/* QPlainTextEdit --------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QPlainTextEdit { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_1; + border-radius: $SIZE_BORDER_RADIUS; + border: $BORDER_2; + + &:focus { + border: $BORDER_SELECTION_3; + } + + &:selected { + background: $COLOR_ACCENT_2; + color: $COLOR_BACKGROUND_4; + } +} + +/* QSizeGrip -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsizegrip + +--------------------------------------------------------------------------- */ +QSizeGrip { + background: transparent; + width: 12px; + height: 12px; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/window_grip.png'); +} + +/* QStackedWidget --------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QStackedWidget { + padding: 2px; + border: $BORDER_2; + border: $BORDER_1; +} + +/* QToolBar --------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbar + +--------------------------------------------------------------------------- */ +QToolBar { + background-color: $COLOR_BACKGROUND_4; + border-bottom: $BORDER_1; + padding: 1px; + font-weight: bold; + spacing: 2px; + + QToolButton { + background-color: $COLOR_BACKGROUND_4; + border: $BORDER_2; + + &:hover { + background-color: $COLOR_BACKGROUND_5; + border: $COLOR_BACKGROUND_5; + } + + &:checked { + border: $COLOR_BACKGROUND_6; + background-color: $COLOR_BACKGROUND_6; + + &:hover { + background-color: $COLOR_BACKGROUND_6; + border: $COLOR_BACKGROUND_6; + } + } + + &:pressed { + border: $COLOR_BACKGROUND_6; + background-color: $COLOR_BACKGROUND_6; + + &:hover { + background-color: $COLOR_BACKGROUND_6; + border: $COLOR_BACKGROUND_6; + } + } + + /* This fixes 202 */ + &:disabled { + border: $COLOR_BACKGROUND_4; + background-color: $COLOR_BACKGROUND_4; + + } + } + + &::handle { + + &:horizontal { + width: 16px; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/toolbar_move_horizontal.png'); + } + + &:vertical { + height: 16px; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/toolbar_move_vertical.png'); + } + } + + &::separator { + + &:horizontal { + width: 16px; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/toolbar_separator_horizontal.png'); + } + + &:vertical { + height: 16px; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/toolbar_separator_vertical.png'); + } + } +} + +QToolButton#qt_toolbar_ext_button { + background: $COLOR_BACKGROUND_4; + border: 0px; + color: $COLOR_TEXT_1; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_right.png'); +} + +/* QAbstractSpinBox ------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractSpinBox { + background-color: $COLOR_BACKGROUND_1; + border: $BORDER_2; + color: $COLOR_TEXT_1; + + /* This fixes 103, 111 */ + padding-top: 2px; + + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + border-radius: $SIZE_BORDER_RADIUS; + /* min-width: 5px; removed to fix 109 */ + + &:up-button { + background-color: transparent $COLOR_BACKGROUND_1; + subcontrol-origin: border; + subcontrol-position: top right; + border-left: $BORDER_2; + border-bottom: $BORDER_2; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-bottom: -1px; + } + + &::up-arrow, + &::up-arrow:disabled, + &::up-arrow:off { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_up_disabled.png'); + height: 8px; + width: 8px; + } + + &::up-arrow:hover { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_up.png'); + } + + &:down-button { + background-color: transparent $COLOR_BACKGROUND_1; + subcontrol-origin: border; + subcontrol-position: bottom right; + border-left: $BORDER_2; + border-top: $BORDER_2; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + margin: 1px; + width: 12px; + margin-top: -1px; + } + + &::down-arrow, + &::down-arrow:disabled, + &::down-arrow:off { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_down_disabled.png'); + height: 8px; + width: 8px; + } + + &::down-arrow:hover { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_down.png'); + } + + &:hover { + border: $BORDER_SELECTION_2; + color: $COLOR_TEXT_1; + } + + &:focus { + border: $BORDER_SELECTION_3; + } + + &:selected { + background: $COLOR_ACCENT_2; + color: $COLOR_BACKGROUND_4; + } +} + +/* ------------------------------------------------------------------------ */ +/* DISPLAYS --------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ + +/* QLabel ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe + +--------------------------------------------------------------------------- */ +QLabel { + background-color: $COLOR_BACKGROUND_1; + border: 0px solid $COLOR_BACKGROUND_4; + padding: 2px; + margin: 0px; + color: $COLOR_TEXT_1; + + &:disabled { + background-color: $COLOR_BACKGROUND_1; + border: 0px solid $COLOR_BACKGROUND_4; + color: $COLOR_TEXT_4; + } +} + +/* QTextBrowser ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea + +--------------------------------------------------------------------------- */ +QTextBrowser { + background-color: $COLOR_BACKGROUND_1; + border: $BORDER_2; + color: $COLOR_TEXT_1; + border-radius: $SIZE_BORDER_RADIUS; + + &:disabled { + background-color: $COLOR_BACKGROUND_1; + border: $BORDER_2; + color: $COLOR_TEXT_4; + border-radius: $SIZE_BORDER_RADIUS; + } + + &:hover, + &:!hover, + &:selected, + &:pressed { + border: $BORDER_2; + } +} + +/* QGraphicsView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QGraphicsView { + background-color: $COLOR_BACKGROUND_1; + border: $BORDER_2; + color: $COLOR_TEXT_1; + border-radius: $SIZE_BORDER_RADIUS; + + &:disabled { + background-color: $COLOR_BACKGROUND_1; + border: $BORDER_2; + color: $COLOR_TEXT_4; + border-radius: $SIZE_BORDER_RADIUS; + } + + &:hover, + &:!hover, + &:selected, + &:pressed { + border: $BORDER_2; + } +} + +/* QCalendarWidget -------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCalendarWidget { + border: $BORDER_2; + border-radius: $SIZE_BORDER_RADIUS; + + &:disabled { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_4; + } +} + +/* QLCDNumber ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QLCDNumber { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_1; + + &:disabled { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_4; + } +} + +/* QProgressBar ----------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qprogressbar + +--------------------------------------------------------------------------- */ +QProgressBar { + background-color: $COLOR_BACKGROUND_1; + border: $BORDER_2; + color: $COLOR_TEXT_1; + border-radius: $SIZE_BORDER_RADIUS; + text-align: center; + + &:disabled { + background-color: $COLOR_BACKGROUND_1; + border: $BORDER_2; + color: $COLOR_TEXT_4; + border-radius: $SIZE_BORDER_RADIUS; + text-align: center; + } + + &::chunk { + background-color: $COLOR_ACCENT_2; + color: $COLOR_BACKGROUND_1; + border-radius: $SIZE_BORDER_RADIUS; + + &:disabled { + background-color: $COLOR_ACCENT_1; + color: $COLOR_TEXT_4; + border-radius: $SIZE_BORDER_RADIUS; + } + } +} + +/* ------------------------------------------------------------------------ */ +/* BUTTONS ---------------------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ + +/* QPushButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qpushbutton + +--------------------------------------------------------------------------- */ +QPushButton { + background-color: $COLOR_BACKGROUND_4; + border: $BORDER_2; + color: $COLOR_TEXT_1; + border-radius: $SIZE_BORDER_RADIUS; + padding: 3px; + outline: none; + + &:disabled { + background-color: $COLOR_BACKGROUND_4; + border: $BORDER_2; + color: $COLOR_TEXT_4; + border-radius: $SIZE_BORDER_RADIUS; + padding: 3px; + } + + &:checked { + background-color: $COLOR_BACKGROUND_6; + border: $COLOR_BACKGROUND_6; + border-radius: $SIZE_BORDER_RADIUS; + padding: 3px; + outline: none; + + &:disabled { + background-color: $COLOR_BACKGROUND_6; + border: $COLOR_BACKGROUND_6; + color: $COLOR_TEXT_4; + border-radius: $SIZE_BORDER_RADIUS; + padding: 3px; + outline: none; + } + + &:selected { + background: $COLOR_BACKGROUND_6; + } + + } + + &::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: bottom right; + bottom: 4px; + } + + &:hover { + background-color: $COLOR_BACKGROUND_5; + border: $COLOR_BACKGROUND_5; + color: $COLOR_TEXT_1; + } + + &:pressed { + background-color: $COLOR_BACKGROUND_6; + border: $COLOR_BACKGROUND_6; + } + + &:selected { + background: $COLOR_BACKGROUND_6; + color: $COLOR_TEXT_1; + } + +} + +QDialogButtonBox QPushButton { + /* Issue #194 #248 - Special case of QPushButton inside dialogs, for better UI */ + min-width: 80px; +} +/* QToolButton ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbutton + +--------------------------------------------------------------------------- */ +QToolButton { + background-color: transparent; + border: 1px solid transparent; + border-radius: $SIZE_BORDER_RADIUS; + margin: 0px; + padding: 2px; + + &:checked { + background-color: $COLOR_BACKGROUND_3; + border: $COLOR_BACKGROUND_3; + + &:disabled { + background-color: $COLOR_BACKGROUND_4; + border: $COLOR_BACKGROUND_4; + } + &:hover { + background-color: $COLOR_BACKGROUND_3; + border: $COLOR_BACKGROUND_3; + } + } + + &:pressed { + margin: 1px; + background-color: $COLOR_BACKGROUND_3; + border: $COLOR_BACKGROUND_3; + &:hover { + background-color: $COLOR_BACKGROUND_3; + border: $COLOR_BACKGROUND_3; + } + } + + &:disabled { + border: none; + + } + + &:hover { + background-color: $COLOR_BACKGROUND_2; + border: $COLOR_BACKGROUND_2; + + } + + /* The subcontrols below are used only in the DelayedPopup mode */ + &[popupMode="0"] { + /* Only for DelayedPopup */ + padding-right: 2px; + } + + /* The subcontrols below are used only in the MenuButtonPopup mode */ + &[popupMode="1"] { + /* Only for MenuButtonPopup */ + padding-right: 20px; + + &::menu-button { + border: none; + + &:hover { + border: none; + border-left: 1px solid $COLOR_ACCENT_3; + border-radius: 0; + } + } + } + + /* The subcontrol below is used only in the InstantPopup or DelayedPopup mode */ + &[popupMode="2"] { + /* Only for InstantPopup */ + padding-right: 2px; + } + + &::menu-button { + padding: 2px; + border-radius: $SIZE_BORDER_RADIUS; + border: $BORDER_2; + width: 12px; + outline: none; + + &:hover { + border: $BORDER_SELECTION_2; + } + + &:checked { + &:hover { + border: $BORDER_SELECTION_2; + } + } + } + + &::menu-indicator { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_down.png'); + height: 8px; + width: 8px; + top: 0; + /* Exclude a shift for better image */ + left: -2px; + /* Shift it a bit */ + } + + &::menu-arrow { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_down.png'); + height: 8px; + width: 8px; + + &:hover { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_down_focus.png'); + } + } +} + +/* QCommandLinkButton ----------------------------------------------------- + +--------------------------------------------------------------------------- */ +QCommandLinkButton { + background-color: transparent; + border: $BORDER_2; + color: $COLOR_TEXT_1; + border-radius: $SIZE_BORDER_RADIUS; + padding: 0px; + margin: 0px; + + &:disabled { + background-color: transparent; + color: $COLOR_TEXT_4; + } +} + +/* ------------------------------------------------------------------------ */ +/* INPUTS - NO FIELDS ----------------------------------------------------- */ +/* ------------------------------------------------------------------------ */ + +/* QComboBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qcombobox + +--------------------------------------------------------------------------- */ +QComboBox { + border: $BORDER_2; + border-radius: $SIZE_BORDER_RADIUS; + selection-background-color: $COLOR_ACCENT_2; + padding-left: 4px; + padding-right: 4px; + /* padding-right = 36; 4 + 16*2 See scrollbar size */ + /* changed to 4px to fix #239 */ + + /* Fixes #103, #111 */ + min-height: 1.5em; + + /* padding-top: 2px; removed to fix #132 */ + /* padding-bottom: 2px; removed to fix #132 */ + /* min-width: 75px; removed to fix #109 */ + + QAbstractItemView { + border: $BORDER_2; + border-radius: 0; + background-color: $COLOR_BACKGROUND_1; + selection-background-color: $COLOR_ACCENT_2; + + &:hover { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_1; + } + + &:selected { + background: $COLOR_ACCENT_2; + color: $COLOR_BACKGROUND_4; + } + + &:alternate { + background: $COLOR_BACKGROUND_1; + } + + } + + &:disabled { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_4; + } + + &:hover { + border: $BORDER_SELECTION_2; + } + + &:focus { + border: $BORDER_SELECTION_3; + } + + &:on { + selection-background-color: $COLOR_ACCENT_2; + } + + /* Needed to remove indicator - fix #132 */ + &::indicator { + border: none; + border-radius: 0; + background-color: transparent; + selection-background-color: transparent; + color: transparent; + selection-color: transparent; + + /* Needed to remove indicator - fix #132 */ + &:alternate { + background: $COLOR_BACKGROUND_1; + } + } + + &::item { + + &:alternate { + background: $COLOR_BACKGROUND_1; + } + + &:checked { + font-weight: bold; + } + + &:selected { + border: 0px solid transparent; + } + } + + &::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid $COLOR_BACKGROUND_4; + } + + &::down-arrow { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_down_disabled.png'); + height: 8px; + width: 8px; + + &:on, + &:hover, + &:focus { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_down.png'); + } + } +} + +/* QSlider ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qslider + +--------------------------------------------------------------------------- */ +QSlider { + + &:disabled { + background: $COLOR_BACKGROUND_1; + } + + &:focus { + border: none; + } + + &::groove { + &:horizontal { + background: $COLOR_BACKGROUND_4; + border: $BORDER_2; + height: 4px; + margin: 0px; + border-radius: $SIZE_BORDER_RADIUS; + } + + &:vertical { + background: $COLOR_BACKGROUND_4; + border: $BORDER_2; + width: 4px; + margin: 0px; + border-radius: $SIZE_BORDER_RADIUS; + } + } + + &::add-page { + + &:vertical { + background: $COLOR_ACCENT_2; + border: $BORDER_2; + width: 4px; + margin: 0px; + border-radius: $SIZE_BORDER_RADIUS; + + :disabled { + background: $COLOR_ACCENT_1; + } + } + } + + &::sub-page { + + &:horizontal { + background: $COLOR_ACCENT_2; + border: $BORDER_2; + height: 4px; + margin: 0px; + border-radius: $SIZE_BORDER_RADIUS; + + &:disabled { + background: $COLOR_ACCENT_1; + } + } + } + + &::handle { + + &:horizontal { + background: $COLOR_TEXT_4; + border: $BORDER_2; + width: 8px; + height: 8px; + margin: -8px 0px; + border-radius: $SIZE_BORDER_RADIUS; + + &:hover { + background: $COLOR_ACCENT_2; + border: $BORDER_SELECTION_2; + } + + &:focus { + border: $BORDER_SELECTION_3; + } + } + + &:vertical { + background: $COLOR_TEXT_4; + border: $BORDER_2; + width: 8px; + height: 8px; + margin: 0 -8px; + border-radius: $SIZE_BORDER_RADIUS; + + &:hover { + background: $COLOR_ACCENT_2; + border: $BORDER_SELECTION_2; + } + + &:focus { + border: $BORDER_SELECTION_3; + } + } + } +} + +/* QLineEdit -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlineedit + +--------------------------------------------------------------------------- */ +QLineEdit { + background-color: $COLOR_BACKGROUND_1; + padding-top: 2px; + /* This QLineEdit fix 103, 111 */ + padding-bottom: 2px; + /* This QLineEdit fix 103, 111 */ + padding-left: 4px; + padding-right: 4px; + border-style: solid; + border: $BORDER_2; + border-radius: $SIZE_BORDER_RADIUS; + color: $COLOR_TEXT_1; + + &:disabled { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_4; + } + + &:hover { + border: $BORDER_SELECTION_2; + color: $COLOR_TEXT_1; + } + + &:focus { + border: $BORDER_SELECTION_3; + } + + &:selected { + background-color: $COLOR_ACCENT_2; + color: $COLOR_BACKGROUND_4; + } +} + +/* QTabWiget -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabWidget { + padding: 2px; + selection-background-color: $COLOR_BACKGROUND_4; + + QWidget { + /* Fixes #189 */ + border-radius: $SIZE_BORDER_RADIUS; + } + + &::pane { + border: $BORDER_2; + border-radius: $SIZE_BORDER_RADIUS; + margin: 0px; + /* Fixes double border inside pane with pyqt5 */ + padding: 0px; + + &:selected { + background-color: $COLOR_BACKGROUND_4; + border: 1px solid $COLOR_ACCENT_2; + } + } +} + +/* QTabBar ---------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtabwidget-and-qtabbar + +--------------------------------------------------------------------------- */ +QTabBar { + qproperty-drawBase: 0; + border-radius: $SIZE_BORDER_RADIUS; + margin: 0px; + padding: 2px; + border: 0; + /* left: 5px; move to the right by 5px - removed for fix */ + + &::close-button { + border: 0; + margin: 0; + padding: 4px; + + image: url($PATH_RESOURCES + '/' + $ID + '/rc/window_close.png'); + + &:hover { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/window_close_focus.png'); + } + + &:pressed { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/window_close_pressed.png'); + } + } + + &::tab { + + &:top:selected:disabled { + border-bottom: 3px solid $COLOR_ACCENT_1; + color: $COLOR_TEXT_4; + background-color: $COLOR_BACKGROUND_4; + } + + &:bottom:selected:disabled { + border-top: 3px solid $COLOR_ACCENT_1; + color: $COLOR_TEXT_4; + background-color: $COLOR_BACKGROUND_4; + } + + &:left:selected:disabled { + border-right: 3px solid $COLOR_ACCENT_1; + color: $COLOR_TEXT_4; + background-color: $COLOR_BACKGROUND_4; + } + + &:right:selected:disabled { + border-left: 3px solid $COLOR_ACCENT_1; + color: $COLOR_TEXT_4; + background-color: $COLOR_BACKGROUND_4; + } + + /* !selected and disabled ----------------------------------------- */ + &:top:!selected:disabled { + border-bottom: 3px solid $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_4; + background-color: $COLOR_BACKGROUND_1; + } + + &:bottom:!selected:disabled { + border-top: 3px solid $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_4; + background-color: $COLOR_BACKGROUND_1; + } + + &:left:!selected:disabled { + border-right: 3px solid $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_4; + background-color: $COLOR_BACKGROUND_1; + } + + &:right:!selected:disabled { + border-left: 3px solid $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_4; + background-color: $COLOR_BACKGROUND_1; + } + + /* selected ------------------------------------------------------- */ + &:top:!selected { + border-bottom: 2px solid $COLOR_BACKGROUND_1; + margin-top: 2px; + } + + &:bottom:!selected { + border-top: 2px solid $COLOR_BACKGROUND_1; + margin-bottom: 3px; + } + + &:left:!selected { + border-left: 2px solid $COLOR_BACKGROUND_1; + margin-right: 2px; + } + + &:right:!selected { + border-right: 2px solid $COLOR_BACKGROUND_1; + margin-left: 2px; + } + + &:top { + background-color: $COLOR_BACKGROUND_4; + color: $COLOR_TEXT_1; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + min-width: 5px; + border-bottom: 3px solid $COLOR_BACKGROUND_4; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + + &:selected { + background-color: $COLOR_BACKGROUND_5; + color: $COLOR_TEXT_1; + border-bottom: 3px solid $COLOR_ACCENT_4; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + } + + &:!selected:hover { + border: $BORDER_SELECTION_3; + border-bottom: 3px solid $COLOR_ACCENT_3; + + /* Fixes spyder-ide/spyder#9766 */ + padding-left: 4px; + padding-right: 4px; + } + } + + &:bottom { + color: $COLOR_TEXT_1; + border-top: 3px solid $COLOR_BACKGROUND_4; + background-color: $COLOR_BACKGROUND_4; + margin-left: 2px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + min-width: 5px; + + &:selected { + color: $COLOR_TEXT_1; + background-color: $COLOR_BACKGROUND_5; + border-top: 3px solid $COLOR_ACCENT_4; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + } + + &:!selected:hover { + border: $BORDER_SELECTION_3; + border-top: 3px solid $COLOR_ACCENT_3; + + /* Fixes spyder-ide/spyder#9766 */ + padding-left: 4px; + padding-right: 4px; + } + + } + + &:left { + color: $COLOR_TEXT_1; + background-color: $COLOR_BACKGROUND_4; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; + min-height: 5px; + + &:selected { + color: $COLOR_TEXT_1; + background-color: $COLOR_BACKGROUND_5; + border-right: 3px solid $COLOR_ACCENT_4; + } + + &:!selected:hover { + border: $BORDER_SELECTION_3; + border-right: 3px solid $COLOR_ACCENT_3; + padding: 0px; + } + } + + &:right { + color: $COLOR_TEXT_1; + background-color: $COLOR_BACKGROUND_4; + margin-top: 2px; + padding-left: 2px; + padding-right: 2px; + padding-top: 4px; + padding-bottom: 4px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + min-height: 5px; + + &:selected { + color: $COLOR_TEXT_1; + background-color: $COLOR_BACKGROUND_5; + border-left: 3px solid $COLOR_ACCENT_4; + + } + + &:!selected:hover { + border: $BORDER_SELECTION_3; + border-left: 3px solid $COLOR_ACCENT_3; + padding: 0px; + } + } + } + + QToolButton { + /* Fixes #136 */ + background-color: $COLOR_BACKGROUND_4; + height: 12px; + width: 12px; + + &:pressed { + background-color: $COLOR_BACKGROUND_4; + + &:hover { + border: $BORDER_SELECTION_2; + } + } + + &::left-arrow { + &:enabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_left.png'); + } + + &:disabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_left_disabled.png'); + } + } + + &::right-arrow { + &:enabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_right.png'); + } + + &:disabled { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_right_disabled.png'); + } + } + } +} + +/* QDockWiget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QDockWidget { + outline: $BORDER_2; + background-color: $COLOR_BACKGROUND_1; + border: $BORDER_2; + border-radius: $SIZE_BORDER_RADIUS; + // See discussion here: https://stackoverflow.com/questions/32145080/qdockwidget-float-close-button-hover-images + titlebar-close-icon: url($PATH_RESOURCES + '/' + $ID + '/rc/transparent.png'); + titlebar-normal-icon: url($PATH_RESOURCES + '/' + $ID + '/rc/transparent.png'); + + &::title { + /* Better size for title bar */ + padding: 3px; + spacing: 4px; + border: none; + background-color: $COLOR_BACKGROUND_4; + } + + &::close-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + border: 0; + margin: 0; + padding: 0; + + image: url($PATH_RESOURCES + '/' + $ID + '/rc/window_close.png'); + + &:hover { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/window_close_focus.png'); + } + + &:pressed { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/window_close_pressed.png'); + } + } + + &::float-button { + icon-size: 12px; + border: none; + background: transparent; + background-image: transparent; + // float button has an issue that if you change any of those + // parameters bellow there will be a duplication in the icon + // actually it seems that they are always there (duplication) + border: 0; + margin: 0; + padding: 0; + + image: url($PATH_RESOURCES + '/' + $ID + '/rc/window_undock.png'); + + &:hover { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/window_undock_focus.png'); + } + + &:pressed { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/window_undock_pressed.png'); + } + } +} + +/* QTreeView QListView QTableView ----------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtreeview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtableview + +--------------------------------------------------------------------------- */ +QTreeView { + + &:branch { + + &:selected, + &:hover { + background: url($PATH_RESOURCES + '/' + $ID + '/rc/transparent.png'); + } + + &:has-siblings:!adjoins-item { + border-image: url($PATH_RESOURCES + '/' + $ID + '/rc/branch_line.png') 0; + } + + &:has-siblings:adjoins-item { + border-image: url($PATH_RESOURCES + '/' + $ID + '/rc/branch_more.png') 0; + } + + &:!has-children:!has-siblings:adjoins-item { + border-image: url($PATH_RESOURCES + '/' + $ID + '/rc/branch_end.png') 0; + } + + &:has-children:!has-siblings:closed, + &:closed:has-children:has-siblings { + border-image: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/branch_closed.png'); + } + + &:open:has-children:!has-siblings, + &:open:has-children:has-siblings { + border-image: none; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/branch_open.png'); + } + + &:has-children:!has-siblings:closed:hover, + &:closed:has-children:has-siblings:hover { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/branch_closed_focus.png'); + } + + &:open:has-children:!has-siblings:hover, + &:open:has-children:has-siblings:hover { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/branch_open_focus.png'); + } + } +} + +QTreeView, +QListView, +QTableView, +QColumnView { + + &::indicator { + + &:checked { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_checked.png'); + + &:hover, + &:focus, + &:pressed { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_checked_focus.png'); + } + } + + &:unchecked { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_unchecked.png'); + + &:hover, + &:focus, + &:pressed { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_unchecked_focus.png'); + } + } + + &:indeterminate { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_indeterminate.png'); + + &:hover, + &:focus, + &:pressed { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/checkbox_indeterminate_focus.png'); + } + } + } +} + +QTreeView, +QListView, +QTableView, +QColumnView { + background-color: $COLOR_BACKGROUND_1; + border: $BORDER_2; + color: $COLOR_TEXT_1; + gridline-color: $COLOR_BACKGROUND_4; + border-radius: $SIZE_BORDER_RADIUS; + + &:disabled { + background-color: $COLOR_BACKGROUND_1; + color: $COLOR_TEXT_4; + } + + &:selected { + background-color: $COLOR_ACCENT_2; + color: $COLOR_BACKGROUND_4; + } + + &:focus { + border: $BORDER_SELECTION_3; + } + + &::item { + + &:pressed { + background-color: $COLOR_ACCENT_2; + } + + &:selected { + + &:active { + background-color: $COLOR_ACCENT_2; + } + } + + &:!selected { + + &:hover { + outline: 0; + color: $COLOR_TEXT_1; + background-color: $COLOR_BACKGROUND_3; + } + } + } +} + +QTableCornerButton { + &::section { + background-color: $COLOR_BACKGROUND_1; + border: 1px transparent $COLOR_BACKGROUND_4; + border-radius: 0px; + } +} + +/* QHeaderView ------------------------------------------------------------ + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qheaderview + +--------------------------------------------------------------------------- */ +QHeaderView { + background-color: $COLOR_BACKGROUND_4; + border: 0px transparent $COLOR_BACKGROUND_4; + padding: 0; + margin: 0; + border-radius: 0; + + &:disabled { + background-color: $COLOR_BACKGROUND_4; + border: 1px transparent $COLOR_BACKGROUND_4; + } + + &::section { + background-color: $COLOR_BACKGROUND_4; + color: $COLOR_TEXT_1; + border-radius: 0; + text-align: left; + font-size: 13px; + + &:checked { + color: $COLOR_TEXT_1; + background-color: $COLOR_ACCENT_2; + + &:disabled { + color: $COLOR_TEXT_4; + background-color: $COLOR_ACCENT_1; + } + } + + &::horizontal { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-left: $BORDER_1; + + &::first, + &::only-one { + border-left: $BORDER_2; + } + + &:disabled { + color: $COLOR_TEXT_4; + } + } + + &::vertical { + padding-top: 0; + padding-bottom: 0; + padding-left: 4px; + padding-right: 4px; + border-top: $BORDER_1; + + &::first, + &::only-one { + border-top: $BORDER_2; + } + + &:disabled { + color: $COLOR_TEXT_4; + } + } + } + + &::down-arrow { + /* Those settings (border/width/height/background-color) solve bug */ + /* transparent arrow background and size */ + background-color: $COLOR_BACKGROUND_4; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_down.png'); + } + + &::up-arrow { + background-color: $COLOR_BACKGROUND_4; + border: none; + height: 12px; + width: 12px; + padding-left: 2px; + padding-right: 2px; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_up.png'); + } +} + +/* QToolBox -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtoolbox + +--------------------------------------------------------------------------- */ +QToolBox { + padding: 0px; + border: 0px; + border: $BORDER_2; + + &:selected { + padding: 0px; + border: 2px solid $COLOR_ACCENT_2; + } + + &::tab { + background-color: $COLOR_BACKGROUND_1; + border: $BORDER_2; + color: $COLOR_TEXT_1; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + + &:disabled { + color: $COLOR_TEXT_4; + } + + &:selected { + background-color: $COLOR_BACKGROUND_6; + border-bottom: 2px solid $COLOR_ACCENT_2; + + &:disabled { + background-color: $COLOR_BACKGROUND_4; + border-bottom: 2px solid $COLOR_ACCENT_1; + } + } + + &:!selected { + background-color: $COLOR_BACKGROUND_4; + border-bottom: 2px solid $COLOR_BACKGROUND_4; + + &:disabled { + background-color: $COLOR_BACKGROUND_1; + } + + } + + &:hover { + border-color: $COLOR_ACCENT_3; + border-bottom: 2px solid $COLOR_ACCENT_3; + } + } + + QScrollArea QWidget QWidget { + padding: 0px; + border: 0px; + background-color: $COLOR_BACKGROUND_1; + } +} + +/* QFrame ----------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qframe +https://doc.qt.io/qt-5/qframe.html#-prop +https://doc.qt.io/qt-5/qframe.html#details +https://stackoverflow.com/questions/14581498/qt-stylesheet-for-hline-vline-color + +--------------------------------------------------------------------------- */ + +/* (dot) .QFrame fix #141, #126, #123 */ + +.QFrame { + border-radius: $SIZE_BORDER_RADIUS; + border: $BORDER_2; + + /* No frame */ + &[frameShape="0"] { + border-radius: $SIZE_BORDER_RADIUS; + border: 1px transparent $COLOR_BACKGROUND_4; + } + + /* HLine */ + &[frameShape="4"] { + max-height: 2px; + border: none; + background-color: $COLOR_BACKGROUND_4; + } + + /* HLine */ + &[frameShape="5"] { + max-width: 2px; + border: none; + background-color: $COLOR_BACKGROUND_4; + } + +} + +/* QSplitter -------------------------------------------------------------- + +https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qsplitter + +--------------------------------------------------------------------------- */ +QSplitter { + background-color: $COLOR_BACKGROUND_4; + spacing: 0px; + padding: 0px; + margin: 0px; + + &::handle { + background-color: $COLOR_BACKGROUND_4; + border: 0px solid $COLOR_BACKGROUND_1; + spacing: 0px; + padding: 1px; + margin: 0px; + + &:hover { + background-color: $COLOR_TEXT_4; + } + + &:horizontal { + width: 5px; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/line_vertical.png'); + } + + &:vertical { + height: 5px; + image: url($PATH_RESOURCES + '/' + $ID + '/rc/line_horizontal.png'); + } + } +} + +/* QDateEdit, QDateTimeEdit ----------------------------------------------- + +--------------------------------------------------------------------------- */ +QDateEdit, QDateTimeEdit { + selection-background-color: $COLOR_ACCENT_2; + border-style: solid; + border: $BORDER_2; + border-radius: $SIZE_BORDER_RADIUS; + + /* This fixes 103, 111 */ + padding-top: 2px; + + /* This fixes 103, 111 */ + padding-bottom: 2px; + padding-left: 4px; + padding-right: 4px; + min-width: 10px; + + &:on { + selection-background-color: $COLOR_ACCENT_2; + } + + &::drop-down { + subcontrol-origin: padding; + subcontrol-position: top right; + width: 12px; + border-left: 1px solid $COLOR_BACKGROUND_4; + } + + &::down-arrow { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_down_disabled.png'); + height: 8px; + width: 8px; + + &:on, + &:hover, + &:focus { + image: url($PATH_RESOURCES + '/' + $ID + '/rc/arrow_down.png'); + } + + } + + QAbstractItemView { + background-color: $COLOR_BACKGROUND_1; + border-radius: $SIZE_BORDER_RADIUS; + border: $BORDER_2; + selection-background-color: $COLOR_ACCENT_2; + } +} + + +/* QAbstractView ---------------------------------------------------------- + +--------------------------------------------------------------------------- */ +QAbstractView { + + &:hover { + border: $BORDER_SELECTION_2; + color: $COLOR_TEXT_1; + } + + &:selected { + background: $COLOR_ACCENT_2; + color: $COLOR_BACKGROUND_4; + } +} + + +/* PlotWidget ------------------------------------------------------------- + +--------------------------------------------------------------------------- */ +PlotWidget { + /* Fix cut labels in plots #134 */ + padding: 0px; +} diff --git a/src/sql/ObjectIdentifier.cpp b/src/sql/ObjectIdentifier.cpp new file mode 100644 index 000000000..f76619634 --- /dev/null +++ b/src/sql/ObjectIdentifier.cpp @@ -0,0 +1,79 @@ +#include "ObjectIdentifier.h" + +static std::string duplicate_char(std::string str, char to_replace) +{ + size_t pos = 0; + while((pos = str.find(to_replace, pos)) != std::string::npos) + { + str.insert(pos, 1, to_replace); + pos += 2; // Advance by two characters in order to avoid escaping a character multiple times + } + return str; +} + +namespace sqlb { + +static escapeQuoting customQuoting = DoubleQuotes; + +void setIdentifierQuoting(escapeQuoting toQuoting) +{ + customQuoting = toQuoting; +} + +char getIdentifierQuoteChar() +{ + switch(customQuoting) { + case GraveAccents: + return '`'; + case SquareBrackets: + return '['; + case DoubleQuotes: + return '"'; + } + + return '"'; +} + +std::string escapeIdentifier(const std::string& id) +{ + switch(customQuoting) { + case GraveAccents: + return '`' + duplicate_char(id, '`') + '`'; + case SquareBrackets: + // There aren't any escaping possibilities for square brackets inside the identifier, + // so we rely on the user to not enter these characters when this kind of quoting is + // selected. + return '[' + id + ']'; + case DoubleQuotes: + // This may produce a 'control reaches end of non-void function' warning if the + // default branch is removed, even though we have covered all possibilities in the + // switch statement. + return '"' + duplicate_char(id, '"') + '"'; + } +} + +std::string escapeString(const std::string& literal) +{ + return '\'' + duplicate_char(literal, '\'') + '\''; +} + +bool ObjectIdentifier::fromSerialised(const std::string& serialised) +{ + auto pos_comma = serialised.find(","); + auto pos_colon = serialised.find(":"); + if(pos_comma == serialised.npos || pos_colon == serialised.npos) + return false; + + size_t size_schema, size_name; + size_schema = std::stoul(serialised.substr(0, pos_comma)); + size_name = std::stoul(serialised.substr(pos_comma+1, pos_colon-pos_comma)); + if(pos_colon + size_schema + size_name + 1 != serialised.size()) + return false; + + m_schema = serialised.substr(pos_colon + 1, size_schema); + m_name = serialised.substr(pos_colon + size_schema + 1, size_name); + + return true; +} + +} diff --git a/src/sql/ObjectIdentifier.h b/src/sql/ObjectIdentifier.h new file mode 100644 index 000000000..8d2f52829 --- /dev/null +++ b/src/sql/ObjectIdentifier.h @@ -0,0 +1,104 @@ +#ifndef OBJECTIDENTIFIER_H +#define OBJECTIDENTIFIER_H + +#include + +namespace sqlb { + +enum escapeQuoting { + DoubleQuotes, + GraveAccents, + SquareBrackets +}; + +// Set quoting style for escapeIdentifier +void setIdentifierQuoting(escapeQuoting toQuoting); + +// Get currently configured quote char +char getIdentifierQuoteChar(); + +// Add quotes to an identifier +std::string escapeIdentifier(const std::string& id); + +// Add SQL quotes to a string literal and escape any single quote character +std::string escapeString(const std::string& literal); + +// Object identifier consisting of schema name and object name +class ObjectIdentifier +{ +public: + ObjectIdentifier(const std::string& schema, const std::string& name) + : m_schema(schema), + m_name(name) + { + } + + ObjectIdentifier() + : m_schema("main") + { + } + + explicit ObjectIdentifier(const std::string& variant) + { + // Try to unserialise the parameter first. If that does not work, just assume it's an object name for the main schema + clear(); + if(!fromSerialised(variant)) + m_name = variant; + } + + bool operator==(const ObjectIdentifier& rhs) const + { + return (rhs.m_schema == m_schema && rhs.m_name == m_name); + } + + bool operator<(const ObjectIdentifier& rhs) const + { + return toDisplayString() < rhs.toDisplayString(); + } + + const std::string& schema() const { return m_schema; } + const std::string& name() const { return m_name; } + void setSchema(const std::string& schema) { m_schema = schema; } + void setName(const std::string& name) { m_name = name; } + + void clear() + { + m_schema = "main"; + m_name.clear(); + } + + bool isEmpty() const { return m_name.empty(); } + + // This returns a string which can be used in SQL statements + std::string toString(bool shortName = false) const + { + if(shortName && m_schema == "main") + return sqlb::escapeIdentifier(m_name); + else + return sqlb::escapeIdentifier(m_schema) + "." + sqlb::escapeIdentifier(m_name); + } + + // This returns a string which can be used in the user interface + std::string toDisplayString() const + { + if(m_schema == "main") + return m_name; + else + return m_schema + "." + m_name; + } + + std::string toSerialised() const + { + return std::to_string(m_schema.size()) + "," + std::to_string(m_name.size()) + ":" + m_schema + m_name; + } + + bool fromSerialised(const std::string& serialised); + +private: + std::string m_schema; + std::string m_name; +}; + +} + +#endif diff --git a/src/sql/Query.cpp b/src/sql/Query.cpp new file mode 100644 index 000000000..27db9bb60 --- /dev/null +++ b/src/sql/Query.cpp @@ -0,0 +1,150 @@ +#include "Query.h" + +#include + +namespace sqlb +{ + +void Query::clear() +{ + m_table.clear(); + m_rowid_columns = {"_rowid_"}; + m_selected_columns.clear(); + m_where.clear(); + m_sort.clear(); +} + +std::string Query::buildWherePart() const +{ + if(m_where.empty() && m_global_where.empty()) + return std::string(); + + std::string where = "WHERE "; + + if(m_where.size()) + { + for(auto i=m_where.cbegin();i!=m_where.cend();++i) + { + const auto it = findSelectedColumnByName(i->first); + std::string column = sqlb::escapeIdentifier(i->first); + if(it != m_selected_columns.cend() && it->selector != i->first) + column = it->selector; + where += column + " " + i->second + " AND "; + } + + // Remove last ' AND ' + where.erase(where.size() - 5); + } + + if(m_global_where.size()) + { + // Connect to previous conditions if there are any + if(m_where.size()) + where += " AND "; + + // For each condition + for(const auto& w : m_global_where) + { + where += "("; + + // For each selected column + for(const auto& c : m_column_names) + { + const auto it = findSelectedColumnByName(c); + std::string column = sqlb::escapeIdentifier(c); + if(it != m_selected_columns.cend() && it->selector != column) + column = it->selector; + + where += column + " " + w + " OR "; + } + + // Remove last ' OR ' + where.erase(where.size() - 4); + + where += ") AND "; + } + + // Remove last ' AND ' + where.erase(where.size() - 5); + } + + return where; +} + +std::string Query::buildQuery(bool withRowid) const +{ + // Selector and display formats + std::string selector; + if (withRowid) + { + // We select the rowid data into a JSON array in case there are multiple rowid columns in order to have all values at hand. + // If there is only one rowid column, we leave it as is. + if(m_rowid_columns.size() == 1) + { + // As of SQLite 3.36 when selecting rowid from a view SQLite does not return NULL anymore but instead returns "rowid" and throws + // an error. To avoid that error (we don't actually care for the value of this column, so the value is not the issue here) we + // explicitly select NULL (without any quotes) here. + if(m_is_view && !hasCustomRowIdColumn()) + selector = "NULL,"; + else + selector = sqlb::escapeIdentifier(m_rowid_columns.at(0)) + ","; + } else { + selector += "sqlb_make_single_value("; + for(size_t i=0;i::iterator Query::findSelectedColumnByName(const std::string& name) +{ + return std::find_if(m_selected_columns.begin(), m_selected_columns.end(), [name](const SelectedColumn& c) { + return name == c.original_column; + }); +} + +std::vector::const_iterator Query::findSelectedColumnByName(const std::string& name) const +{ + return std::find_if(m_selected_columns.cbegin(), m_selected_columns.cend(), [name](const SelectedColumn& c) { + return name == c.original_column; + }); +} + +} diff --git a/src/sql/Query.h b/src/sql/Query.h new file mode 100644 index 000000000..9ddc202e8 --- /dev/null +++ b/src/sql/Query.h @@ -0,0 +1,114 @@ +#ifndef QUERY_H +#define QUERY_H + +#include "ObjectIdentifier.h" + +#include +#include +#include + +namespace sqlb +{ + +struct OrderBy +{ + enum SortDirection + { + Ascending, + Descending + }; + + OrderBy(const std::string& expr_, SortDirection direction_) : + expr(expr_), + is_expression(false), + direction(direction_) + {} + + bool operator==(const OrderBy& rhs) const + { + return direction == rhs.direction && is_expression == rhs.is_expression && expr == rhs.expr; + } + + std::string toSql() const + { + if(is_expression) + return expr + (direction == Ascending ? " ASC" : " DESC"); + else + return sqlb::escapeIdentifier(expr) + (direction == Ascending ? " ASC" : " DESC"); + } + + std::string expr; + bool is_expression; + SortDirection direction; +}; + +struct SelectedColumn +{ + SelectedColumn(const std::string& original_column_, const std::string& selector_) : + original_column(original_column_), + selector(selector_) + {} + + std::string original_column; + std::string selector; +}; + +class Query +{ +public: + Query() : + m_is_view(false) + {} + + explicit Query(const sqlb::ObjectIdentifier& table, bool is_view = false) : + m_table(table), + m_is_view(is_view) + {} + + void clear(); + std::string buildQuery(bool withRowid) const; + std::string buildCountQuery() const; + + void setColumnNames(const std::vector& column_names) { m_column_names = column_names; } + std::vector columnNames() const { return m_column_names; } + + void setTable(const sqlb::ObjectIdentifier& table) { m_table = table; } + sqlb::ObjectIdentifier table() const { return m_table; } + + void setRowIdColumns(const std::vector& rowids) { m_rowid_columns = rowids; } + std::vector rowIdColumns() const { return m_rowid_columns; } + void setRowIdColumn(const std::string& rowid) { m_rowid_columns = {rowid}; } + bool hasCustomRowIdColumn() const { return m_rowid_columns.size() != 1 || (m_rowid_columns.at(0) != "rowid" && m_rowid_columns.at(0) != "_rowid_"); } + + const std::vector& selectedColumns() const { return m_selected_columns; } + std::vector& selectedColumns() { return m_selected_columns; } + + const std::unordered_map& where() const { return m_where; } + std::unordered_map& where() { return m_where; } + + const std::vector& globalWhere() const { return m_global_where; } + std::vector& globalWhere() { return m_global_where; } + void setGlobalWhere(const std::vector& w) { m_global_where = w; } + + const std::vector& orderBy() const { return m_sort; } + std::vector& orderBy() { return m_sort; } + void setOrderBy(const std::vector& columns) { m_sort = columns; } + +private: + std::vector m_column_names; + sqlb::ObjectIdentifier m_table; + std::vector m_rowid_columns; + std::vector m_selected_columns; + std::unordered_map m_where; // TODO The two where variables should be merged into a single variable which ... + std::vector m_global_where; // ... holds some sort of general tree structure for all sorts of where conditions. + std::vector m_sort; + bool m_is_view; + + std::vector::iterator findSelectedColumnByName(const std::string& name); + std::vector::const_iterator findSelectedColumnByName(const std::string& name) const; + std::string buildWherePart() const; +}; + +} + +#endif diff --git a/src/sql/parser/ParserDriver.cpp b/src/sql/parser/ParserDriver.cpp new file mode 100644 index 000000000..d2dae0f5c --- /dev/null +++ b/src/sql/parser/ParserDriver.cpp @@ -0,0 +1,31 @@ +#include "ParserDriver.h" + +namespace sqlb +{ +namespace parser +{ + +ParserDriver::ParserDriver() : + result(nullptr), + trace_scanner(false), + trace_parser(false), + scanner(nullptr), + buffer(nullptr) +{ +} + +int ParserDriver::parse(const std::string& s) +{ + source = s; + begin_scan(); + + sqlb::parser::parser parse(scanner, *this); + parse.set_debug_level(trace_parser); + int res = parse(); + + end_scan(); + return res; +} + +} +} diff --git a/src/sql/parser/ParserDriver.h b/src/sql/parser/ParserDriver.h new file mode 100644 index 000000000..ba3b781df --- /dev/null +++ b/src/sql/parser/ParserDriver.h @@ -0,0 +1,65 @@ +#ifndef PARSER_DRIVER_H +#define PARSER_DRIVER_H + +#include +#include "sqlite3_parser.hpp" +#include "../sqlitetypes.h" + +// Give Flex the prototype of yylex we want and declare it for the parser +typedef void* yyscan_t; +namespace sqlb { namespace parser { class ParserDriver; } } +#define YY_DECL sqlb::parser::parser::symbol_type yylex(yyscan_t yyscanner, sqlb::parser::ParserDriver& drv) +YY_DECL; + +namespace sqlb +{ +namespace parser +{ + +class ParserDriver +{ + friend parser; + +public: + ParserDriver(); + + void setScannerDebug(bool on) { trace_scanner = on; } + void setParserDebug(bool on) { trace_parser = on; } + + // Run the parser on string s. Returns 0 on success + int parse(const std::string& s); + + // Result returned by the parsing process + sqlb::ObjectPtr result; + + // The token's location used by the scanner + sqlb::parser::location location; + +private: + // The string to be parsed + std::string source; + + // Handling the scanner + void begin_scan(); + void end_scan(); + + // Debug flags for both scanner and parser + bool trace_scanner; + bool trace_parser; + + // Scanner state + yyscan_t scanner; + + // Scanner buffer + typedef struct yy_buffer_state* YY_BUFFER_STATE; + YY_BUFFER_STATE buffer; + + // This is a purely internal variable used for parsing CREATE TABLE statements. It stores a pointer to the table column which + // is currently being parsed. This allows us to modify the column and add additional constraints when we see them. + std::shared_ptr last_table_column; +}; + +} +} + +#endif diff --git a/src/sql/parser/README b/src/sql/parser/README new file mode 100644 index 000000000..71adf65bc --- /dev/null +++ b/src/sql/parser/README @@ -0,0 +1,9 @@ +This directory contains the SQLite lexer and parser files. + +For convenience and to not have extra dependencies in the build process, +the generated C++ files are included here. Please don't edit them by hand. +To modify the lexer or parser, edit the sqlite3_lexer.ll or sqlite3_parser.yy +files and rerun flex or bison like this: + +flex sqlite3_lexer.ll +bison sqlite3_parser.yy diff --git a/src/sql/parser/sqlite3_lexer.cpp b/src/sql/parser/sqlite3_lexer.cpp new file mode 100644 index 000000000..559173362 --- /dev/null +++ b/src/sql/parser/sqlite3_lexer.cpp @@ -0,0 +1,3647 @@ +#line 2 "sqlite3_lexer.cpp" + +#line 4 "sqlite3_lexer.cpp" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +/* %not-for-header */ +/* %if-c-only */ +/* %if-not-reentrant */ +/* %endif */ +/* %endif */ +/* %ok-for-header */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* %if-c++-only */ +/* %endif */ + +/* %if-c-only */ + +/* %endif */ + +/* %if-c-only */ + +/* %endif */ + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +/* %if-c-only */ +#include +#include +#include +#include +/* %endif */ + +/* %if-tables-serialization */ +/* %endif */ +/* end standard C headers. */ + +/* %if-c-or-c++ */ +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* %endif */ + +/* begin standard C++ headers. */ +/* %if-c++-only */ +/* %endif */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* %not-for-header */ +/* Returned upon end-of-file. */ +#define YY_NULL 0 +/* %ok-for-header */ + +/* %not-for-header */ +/* Promotes a possibly negative, possibly signed char to an + * integer in range [0..255] for use as an array index. + */ +#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) +/* %ok-for-header */ + +/* %if-reentrant */ + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* %endif */ + +/* %if-not-reentrant */ +/* %endif */ + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin , yyscanner ) +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +/* %if-not-reentrant */ +/* %endif */ + +/* %if-c-only */ +/* %if-not-reentrant */ +/* %endif */ +/* %endif */ + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { +/* %if-c-only */ + FILE *yy_input_file; +/* %endif */ + +/* %if-c++-only */ +/* %endif */ + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* %if-c-only Standard (non-C++) definition */ +/* %not-for-header */ +/* %if-not-reentrant */ +/* %endif */ +/* %ok-for-header */ + +/* %endif */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ + ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ + : NULL) +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +/* %if-c-only Standard (non-C++) definition */ + +/* %if-not-reentrant */ +/* %not-for-header */ +/* %ok-for-header */ + +/* %endif */ + +void yyrestart ( FILE *input_file , yyscan_t yyscanner ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); +void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +void yypop_buffer_state ( yyscan_t yyscanner ); + +static void yyensure_buffer_stack ( yyscan_t yyscanner ); +static void yy_load_buffer_state ( yyscan_t yyscanner ); +static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner ); +#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner) + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); + +/* %endif */ + +void *yyalloc ( yy_size_t , yyscan_t yyscanner ); +void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); +void yyfree ( void * , yyscan_t yyscanner ); + +#define yy_new_buffer yy_create_buffer +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */ +/* Begin user sect3 */ + +#define yywrap(yyscanner) (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP + +#define FLEX_DEBUG +typedef flex_uint8_t YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +/* %% [1.5] DFA */ + +/* %if-c-only Standard (non-C++) definition */ + +static yy_state_type yy_get_previous_state ( yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner); +static int yy_get_next_buffer ( yyscan_t yyscanner ); +static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); + +/* %endif */ + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ +/* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\ + yyleng = (int) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ +/* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\ + yyg->yy_c_buf_p = yy_cp; +/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ +#define YY_NUM_RULES 126 +#define YY_END_OF_BUFFER 127 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static const flex_int16_t yy_accept[481] = + { 0, + 0, 0, 0, 0, 127, 125, 1, 2, 2, 125, + 125, 112, 111, 125, 101, 102, 108, 106, 104, 107, + 103, 109, 97, 97, 125, 105, 119, 115, 117, 99, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 125, 125, 113, 110, 125, 125, 125, 92, + 1, 2, 121, 0, 95, 0, 96, 3, 97, 4, + 97, 97, 0, 0, 100, 123, 120, 122, 116, 118, + 124, 99, 92, 92, 92, 92, 92, 11, 92, 0, + 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, + + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 43, 92, 92, 46, 50, 92, 92, 92, 55, 92, + 59, 60, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 0, 0, 94, 0, 93, 114, 92, 0, 0, 92, + 97, 0, 97, 97, 99, 92, 92, 92, 6, 12, + 92, 0, 0, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 32, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 52, 92, 92, 56, 92, 92, 92, 92, + + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 76, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 98, 0, 0, 5, 92, + 92, 92, 92, 0, 92, 92, 15, 16, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 29, 92, 31, + 92, 92, 35, 92, 92, 92, 92, 40, 92, 42, + 92, 92, 92, 92, 92, 92, 53, 92, 92, 58, + 61, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 74, 92, 92, 92, 92, 80, 82, + 83, 92, 92, 92, 92, 92, 89, 92, 92, 8, + + 92, 92, 92, 92, 92, 17, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 36, 92, 92, + 92, 92, 92, 92, 47, 92, 92, 92, 54, 92, + 92, 92, 92, 65, 66, 92, 92, 92, 92, 92, + 92, 73, 92, 92, 92, 79, 92, 92, 92, 92, + 87, 92, 90, 92, 9, 10, 92, 92, 92, 92, + 92, 92, 21, 92, 92, 92, 28, 92, 33, 34, + 37, 92, 92, 92, 44, 92, 92, 49, 51, 92, + 92, 92, 92, 92, 68, 92, 92, 92, 92, 75, + 77, 78, 92, 92, 85, 86, 92, 92, 92, 7, + + 14, 18, 92, 92, 92, 25, 92, 92, 92, 92, + 39, 92, 92, 92, 57, 92, 92, 64, 92, 69, + 92, 92, 92, 92, 92, 88, 91, 92, 19, 92, + 92, 92, 27, 30, 92, 92, 92, 92, 92, 92, + 92, 70, 92, 72, 92, 92, 92, 92, 92, 92, + 92, 38, 41, 45, 48, 62, 63, 92, 71, 81, + 84, 92, 20, 92, 92, 26, 67, 92, 92, 92, + 92, 22, 23, 13, 92, 92, 92, 92, 24, 0 + } ; + +static const YY_CHAR yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 2, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 5, 6, 1, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 21, 22, 23, + 24, 25, 26, 21, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 36, + 52, 1, 53, 1, 54, 55, 56, 57, 58, 59, + + 60, 61, 62, 63, 64, 36, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 36, 1, 80, 1, 81, 1, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 1, 1, 83, 83, 83, 83, 83, 83, 83, + + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, + 85, 85, 85, 85, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static const YY_CHAR yy_meta[86] = + { 0, + 1, 1, 2, 1, 1, 1, 3, 1, 1, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, + 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, + 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 1, 1, 3, 1, 6, 6, 6, 6, 6, + 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, + 1, 1, 3, 3, 3 + } ; + +static const flex_int16_t yy_base[489] = + { 0, + 0, 0, 59, 60, 299, 2446, 293, 85, 87, 270, + 285, 2446, 2446, 278, 2446, 2446, 2446, 2446, 2446, 271, + 73, 270, 77, 81, 0, 2446, 79, 255, 81, 244, + 128, 64, 187, 76, 124, 154, 191, 34, 245, 68, + 94, 87, 183, 225, 161, 255, 271, 315, 280, 99, + 298, 157, 210, 206, 156, 2446, 153, 150, 145, 373, + 223, 106, 2446, 214, 210, 205, 196, 2446, 229, 2446, + 261, 349, 106, 0, 0, 2446, 2446, 2446, 2446, 2446, + 2446, 111, 61, 310, 252, 170, 344, 331, 338, 122, + 111, 109, 350, 359, 366, 370, 406, 396, 427, 400, + + 419, 437, 440, 322, 470, 433, 463, 378, 447, 473, + 220, 493, 498, 515, 501, 487, 307, 506, 518, 521, + 391, 443, 536, 550, 576, 573, 630, 600, 604, 610, + 540, 613, 584, 624, 677, 643, 646, 667, 659, 671, + 177, 127, 2446, 121, 110, 2446, 533, 72, 68, 688, + 357, 113, 119, 0, 180, 681, 685, 711, 543, 546, + 694, 60, 53, 697, 754, 746, 749, 774, 757, 714, + 761, 789, 778, 781, 792, 562, 795, 798, 818, 815, + 821, 830, 856, 850, 859, 863, 853, 866, 892, 847, + 896, 878, 638, 914, 899, 918, 921, 924, 939, 931, + + 927, 945, 955, 960, 988, 983, 979, 994, 999, 1012, + 1015, 706, 1008, 741, 1004, 1032, 1041, 1059, 1045, 1051, + 1076, 1065, 1072, 1097, 1089, 2446, 113, 39, 718, 1092, + 1110, 975, 1104, 31, 1123, 1135, 725, 824, 1127, 1140, + 1120, 1152, 1155, 1168, 1174, 1158, 1171, 827, 1149, 886, + 1180, 1198, 948, 1215, 1229, 1207, 1232, 951, 1222, 1023, + 1225, 1243, 1251, 1239, 1260, 1255, 1027, 1284, 1273, 1131, + 1194, 1290, 1299, 1304, 1310, 1318, 1307, 1321, 1325, 1328, + 1342, 1379, 1385, 1201, 1388, 1391, 1394, 1397, 1355, 1278, + 1281, 1408, 1411, 1414, 1423, 1437, 1335, 1430, 1418, 1346, + + 1449, 1455, 1469, 1485, 1488, 1349, 1477, 1491, 1505, 1496, + 1510, 1519, 1514, 1499, 1523, 1536, 1542, 1358, 1556, 1552, + 1572, 1582, 1585, 1578, 1364, 1590, 1597, 1593, 1382, 1606, + 1612, 1620, 1616, 1458, 1481, 1623, 1642, 1635, 1650, 1647, + 1665, 1527, 1670, 1679, 1682, 1539, 1685, 1703, 1691, 1721, + 1564, 1733, 1568, 1725, 1656, 1662, 1744, 1739, 1730, 1751, + 1754, 1764, 1709, 1757, 1779, 1799, 1712, 1792, 1760, 1773, + 1782, 1816, 1806, 1786, 1802, 1825, 1830, 1809, 1819, 1840, + 1853, 1862, 1856, 1865, 1835, 1891, 1869, 1894, 1899, 1847, + 1859, 1876, 1907, 1926, 1881, 1884, 1932, 1940, 1936, 1888, + + 1904, 1910, 1953, 1962, 1946, 1918, 1976, 1982, 1988, 1967, + 1959, 1997, 1994, 2010, 1970, 2015, 2018, 2004, 2034, 2021, + 2037, 2029, 2059, 2063, 2077, 2042, 2045, 2085, 2048, 2070, + 2093, 2098, 2066, 2073, 2101, 2129, 2134, 2120, 2139, 2147, + 2142, 2106, 2154, 2112, 2150, 2162, 2169, 2174, 2184, 2180, + 2210, 2166, 2177, 2188, 2191, 2194, 2197, 2238, 2201, 2204, + 2207, 2265, 2214, 2254, 2262, 2219, 2222, 2268, 2281, 2284, + 2287, 2233, 2290, 2247, 2308, 2300, 2275, 2320, 2293, 2446, + 2405, 2412, 2414, 2419, 2426, 2433, 2436, 2439 + } ; + +static const flex_int16_t yy_def[489] = + { 0, + 480, 1, 1, 1, 480, 480, 480, 480, 480, 480, + 481, 480, 480, 482, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 483, 480, 480, 480, 480, 480, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 485, 486, 480, 480, 480, 480, 480, 484, + 480, 480, 480, 481, 480, 482, 480, 480, 480, 480, + 480, 480, 480, 487, 483, 480, 480, 480, 480, 480, + 480, 480, 484, 484, 484, 484, 484, 484, 484, 480, + 480, 480, 484, 484, 484, 484, 484, 484, 484, 484, + + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 488, 485, 480, 486, 480, 480, 484, 480, 480, 484, + 480, 480, 480, 487, 480, 484, 484, 484, 484, 484, + 484, 480, 480, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 480, 488, 480, 484, 484, + 484, 484, 484, 480, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, + 484, 484, 484, 484, 484, 484, 484, 484, 484, 0, + 480, 480, 480, 480, 480, 480, 480, 480 + } ; + +static const flex_int16_t yy_nxt[2532] = + { 0, + 6, 7, 8, 9, 10, 11, 6, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 38, 40, 41, 42, 43, + 44, 45, 38, 46, 47, 48, 49, 50, 51, 52, + 38, 53, 6, 38, 54, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 38, 46, 47, 48, 49, 50, 51, 52, 38, 55, + 56, 6, 57, 58, 59, 60, 60, 62, 62, 62, + 62, 69, 69, 71, 93, 72, 72, 71, 116, 72, + + 72, 76, 77, 78, 80, 81, 99, 73, 62, 62, + 100, 73, 83, 118, 60, 60, 90, 91, 92, 152, + 147, 152, 226, 93, 153, 153, 74, 116, 117, 155, + 155, 153, 153, 138, 234, 99, 73, 153, 153, 100, + 73, 83, 118, 90, 91, 92, 90, 91, 92, 228, + 90, 91, 92, 147, 74, 84, 85, 117, 90, 91, + 92, 101, 138, 102, 144, 86, 141, 87, 103, 90, + 91, 92, 88, 104, 89, 145, 90, 91, 92, 143, + 105, 90, 91, 92, 84, 85, 226, 124, 106, 101, + 163, 102, 162, 86, 107, 87, 103, 108, 155, 155, + + 88, 104, 89, 83, 125, 66, 90, 91, 92, 105, + 90, 91, 92, 94, 67, 64, 124, 106, 158, 65, + 95, 109, 107, 119, 61, 108, 149, 96, 110, 120, + 97, 148, 125, 98, 147, 146, 90, 91, 92, 90, + 91, 92, 94, 90, 91, 92, 158, 69, 69, 95, + 109, 119, 90, 91, 92, 96, 110, 120, 97, 73, + 145, 98, 143, 82, 121, 90, 91, 92, 122, 90, + 91, 92, 123, 90, 91, 92, 111, 112, 79, 151, + 151, 126, 70, 113, 114, 127, 68, 67, 73, 115, + 65, 73, 121, 63, 61, 128, 122, 157, 480, 480, + + 123, 129, 90, 91, 92, 111, 112, 90, 91, 92, + 126, 113, 114, 480, 127, 480, 130, 115, 480, 135, + 73, 136, 480, 128, 137, 157, 480, 90, 91, 92, + 129, 139, 140, 480, 90, 91, 92, 90, 91, 92, + 480, 131, 480, 194, 130, 132, 480, 135, 133, 136, + 156, 480, 137, 90, 91, 92, 178, 480, 134, 160, + 139, 140, 90, 91, 92, 71, 480, 72, 72, 480, + 131, 194, 480, 159, 132, 151, 151, 133, 156, 73, + 90, 91, 92, 161, 480, 178, 134, 73, 160, 90, + 91, 92, 90, 91, 92, 164, 166, 90, 91, 92, + + 84, 85, 159, 165, 90, 91, 92, 167, 73, 168, + 86, 161, 150, 90, 91, 92, 73, 88, 184, 89, + 90, 91, 92, 164, 480, 166, 90, 91, 92, 84, + 85, 165, 90, 91, 92, 167, 169, 168, 86, 170, + 150, 90, 91, 92, 174, 88, 184, 89, 90, 91, + 92, 480, 90, 91, 92, 90, 91, 92, 171, 480, + 90, 91, 92, 175, 172, 169, 176, 170, 177, 480, + 181, 173, 174, 90, 91, 92, 480, 480, 90, 91, + 92, 480, 90, 91, 92, 480, 185, 171, 90, 91, + 92, 175, 172, 480, 480, 176, 480, 177, 181, 173, + + 182, 90, 91, 92, 179, 480, 183, 180, 480, 90, + 91, 92, 480, 186, 185, 90, 91, 92, 480, 90, + 91, 92, 90, 91, 92, 90, 91, 92, 182, 90, + 91, 92, 187, 179, 183, 180, 188, 193, 480, 480, + 192, 186, 480, 480, 189, 90, 91, 92, 480, 190, + 480, 195, 90, 91, 92, 90, 91, 92, 197, 191, + 187, 480, 480, 196, 188, 193, 198, 215, 192, 90, + 91, 92, 480, 189, 480, 90, 91, 92, 190, 195, + 90, 91, 92, 90, 91, 92, 197, 191, 90, 91, + 92, 196, 480, 199, 480, 198, 215, 90, 91, 92, + + 90, 91, 92, 90, 91, 92, 200, 202, 480, 480, + 201, 480, 203, 480, 217, 90, 91, 92, 90, 91, + 92, 199, 90, 91, 92, 90, 91, 92, 90, 91, + 92, 480, 90, 91, 92, 200, 202, 209, 480, 201, + 203, 211, 480, 217, 90, 91, 92, 480, 210, 212, + 213, 216, 480, 214, 480, 90, 91, 92, 90, 91, + 92, 204, 205, 480, 480, 209, 90, 91, 92, 211, + 218, 206, 221, 480, 207, 208, 210, 212, 213, 216, + 222, 214, 90, 91, 92, 480, 90, 91, 92, 224, + 204, 205, 90, 91, 92, 90, 91, 92, 218, 206, + + 480, 221, 207, 208, 219, 480, 90, 91, 92, 222, + 223, 220, 90, 91, 92, 480, 225, 229, 224, 231, + 90, 91, 92, 480, 230, 90, 91, 92, 90, 91, + 92, 480, 480, 219, 233, 480, 480, 232, 223, 480, + 220, 90, 91, 92, 225, 235, 229, 480, 231, 90, + 91, 92, 230, 90, 91, 92, 480, 244, 480, 90, + 91, 92, 233, 90, 91, 92, 232, 90, 91, 92, + 90, 91, 92, 235, 239, 287, 90, 91, 92, 90, + 91, 92, 236, 243, 237, 244, 240, 245, 90, 91, + 92, 246, 480, 90, 91, 92, 90, 91, 92, 238, + + 90, 91, 92, 239, 287, 241, 248, 90, 91, 92, + 480, 236, 243, 237, 240, 480, 245, 480, 242, 247, + 246, 251, 250, 90, 91, 92, 249, 238, 90, 91, + 92, 90, 91, 92, 241, 248, 90, 91, 92, 90, + 91, 92, 252, 90, 91, 92, 242, 480, 247, 480, + 251, 250, 480, 480, 249, 253, 90, 91, 92, 254, + 90, 91, 92, 90, 91, 92, 255, 256, 480, 480, + 252, 90, 91, 92, 90, 91, 92, 90, 91, 92, + 90, 91, 92, 253, 480, 480, 257, 254, 258, 259, + 260, 480, 264, 261, 255, 256, 262, 90, 91, 92, + + 90, 91, 92, 90, 91, 92, 90, 91, 92, 90, + 91, 92, 90, 91, 92, 257, 258, 480, 259, 260, + 264, 261, 263, 480, 266, 262, 265, 268, 480, 90, + 91, 92, 90, 91, 92, 90, 91, 92, 90, 91, + 92, 90, 91, 92, 267, 90, 91, 92, 90, 91, + 92, 263, 266, 480, 480, 265, 268, 269, 270, 273, + 90, 91, 92, 480, 480, 274, 480, 271, 90, 91, + 92, 480, 480, 267, 90, 91, 92, 480, 90, 91, + 92, 90, 91, 92, 272, 269, 270, 276, 273, 275, + 277, 480, 480, 274, 480, 271, 90, 91, 92, 480, + + 90, 91, 92, 90, 91, 92, 90, 91, 92, 90, + 91, 92, 272, 90, 91, 92, 276, 275, 278, 277, + 279, 90, 91, 92, 280, 302, 480, 90, 91, 92, + 90, 91, 92, 90, 91, 92, 282, 90, 91, 92, + 281, 288, 90, 91, 92, 285, 283, 278, 279, 480, + 480, 286, 280, 302, 480, 480, 284, 90, 91, 92, + 480, 90, 91, 92, 282, 90, 91, 92, 281, 288, + 90, 91, 92, 289, 285, 283, 90, 91, 92, 286, + 290, 90, 91, 92, 284, 292, 90, 91, 92, 291, + 90, 91, 92, 293, 90, 91, 92, 90, 91, 92, + + 480, 289, 294, 480, 295, 90, 91, 92, 290, 90, + 91, 92, 480, 292, 90, 91, 92, 296, 291, 480, + 480, 293, 299, 90, 91, 92, 480, 90, 91, 92, + 480, 294, 295, 90, 91, 92, 297, 300, 303, 480, + 298, 90, 91, 92, 480, 296, 480, 90, 91, 92, + 301, 299, 480, 304, 90, 91, 92, 308, 90, 91, + 92, 305, 480, 306, 297, 300, 307, 303, 298, 480, + 480, 90, 91, 92, 90, 91, 92, 480, 301, 90, + 91, 92, 304, 315, 480, 308, 90, 91, 92, 480, + 305, 306, 90, 91, 92, 307, 480, 309, 311, 480, + + 310, 313, 90, 91, 92, 90, 91, 92, 480, 90, + 91, 92, 315, 90, 91, 92, 314, 90, 91, 92, + 312, 316, 90, 91, 92, 309, 480, 311, 310, 313, + 480, 90, 91, 92, 90, 91, 92, 90, 91, 92, + 90, 91, 92, 317, 314, 318, 480, 320, 312, 316, + 90, 91, 92, 90, 91, 92, 90, 91, 92, 319, + 480, 480, 90, 91, 92, 322, 321, 480, 323, 480, + 480, 317, 324, 326, 318, 320, 90, 91, 92, 480, + 90, 91, 92, 90, 91, 92, 480, 480, 319, 90, + 91, 92, 328, 322, 480, 321, 323, 90, 91, 92, + + 325, 324, 326, 327, 90, 91, 92, 90, 91, 92, + 480, 90, 91, 92, 90, 91, 92, 329, 480, 330, + 328, 90, 91, 92, 331, 90, 91, 92, 325, 332, + 333, 327, 480, 90, 91, 92, 480, 90, 91, 92, + 334, 480, 90, 91, 92, 480, 329, 330, 335, 480, + 336, 338, 480, 331, 480, 90, 91, 92, 332, 333, + 90, 91, 92, 90, 91, 92, 90, 91, 92, 334, + 337, 339, 90, 91, 92, 480, 480, 335, 336, 480, + 338, 90, 91, 92, 480, 340, 90, 91, 92, 90, + 91, 92, 90, 91, 92, 347, 480, 480, 337, 339, + + 90, 91, 92, 90, 91, 92, 341, 90, 91, 92, + 90, 91, 92, 340, 342, 480, 343, 90, 91, 92, + 480, 344, 345, 347, 90, 91, 92, 346, 90, 91, + 92, 90, 91, 92, 480, 341, 480, 90, 91, 92, + 90, 91, 92, 342, 480, 343, 90, 91, 92, 480, + 344, 345, 480, 480, 348, 351, 346, 349, 354, 350, + 353, 90, 91, 92, 90, 91, 92, 90, 91, 92, + 90, 91, 92, 90, 91, 92, 90, 91, 92, 90, + 91, 92, 348, 352, 351, 349, 354, 350, 355, 353, + 90, 91, 92, 90, 91, 92, 90, 91, 92, 356, + + 90, 91, 92, 480, 480, 90, 91, 92, 357, 480, + 480, 352, 90, 91, 92, 358, 355, 359, 480, 90, + 91, 92, 360, 480, 480, 361, 363, 356, 480, 367, + 480, 90, 91, 92, 480, 480, 357, 90, 91, 92, + 90, 91, 92, 480, 358, 480, 359, 480, 362, 364, + 360, 90, 91, 92, 361, 363, 365, 366, 367, 90, + 91, 92, 368, 90, 91, 92, 369, 90, 91, 92, + 90, 91, 92, 90, 91, 92, 362, 364, 90, 91, + 92, 90, 91, 92, 365, 366, 370, 90, 91, 92, + 368, 480, 90, 91, 92, 369, 90, 91, 92, 371, + + 372, 90, 91, 92, 373, 90, 91, 92, 374, 90, + 91, 92, 376, 480, 370, 375, 377, 480, 90, 91, + 92, 90, 91, 92, 90, 91, 92, 371, 372, 480, + 379, 480, 480, 373, 90, 91, 92, 374, 90, 91, + 92, 376, 378, 380, 375, 377, 90, 91, 92, 382, + 90, 91, 92, 384, 90, 91, 92, 381, 379, 383, + 90, 91, 92, 386, 90, 91, 92, 90, 91, 92, + 378, 380, 90, 91, 92, 90, 91, 92, 382, 90, + 91, 92, 384, 385, 387, 381, 388, 383, 90, 91, + 92, 389, 386, 480, 90, 91, 92, 480, 90, 91, + + 92, 480, 90, 91, 92, 90, 91, 92, 391, 480, + 480, 385, 480, 387, 388, 390, 480, 90, 91, 92, + 389, 395, 480, 480, 90, 91, 92, 392, 393, 90, + 91, 92, 90, 91, 92, 480, 480, 391, 90, 91, + 92, 480, 394, 390, 90, 91, 92, 90, 91, 92, + 395, 396, 90, 91, 92, 392, 393, 480, 480, 397, + 401, 90, 91, 92, 90, 91, 92, 90, 91, 92, + 394, 398, 399, 90, 91, 92, 480, 480, 400, 480, + 396, 402, 403, 480, 480, 90, 91, 92, 397, 401, + 404, 90, 91, 92, 90, 91, 92, 480, 480, 398, + + 480, 399, 405, 90, 91, 92, 400, 90, 91, 92, + 402, 403, 90, 91, 92, 90, 91, 92, 480, 404, + 409, 90, 91, 92, 406, 407, 90, 91, 92, 408, + 405, 412, 480, 90, 91, 92, 90, 91, 92, 90, + 91, 92, 90, 91, 92, 411, 90, 91, 92, 409, + 410, 413, 406, 480, 407, 90, 91, 92, 408, 412, + 480, 90, 91, 92, 90, 91, 92, 414, 90, 91, + 92, 480, 480, 411, 90, 91, 92, 415, 480, 410, + 413, 90, 91, 92, 90, 91, 92, 416, 90, 91, + 92, 90, 91, 92, 480, 414, 417, 421, 90, 91, + + 92, 90, 91, 92, 419, 415, 418, 90, 91, 92, + 480, 480, 90, 91, 92, 480, 416, 90, 91, 92, + 480, 420, 90, 91, 92, 417, 421, 423, 422, 90, + 91, 92, 419, 424, 418, 90, 91, 92, 90, 91, + 92, 90, 91, 92, 90, 91, 92, 90, 91, 92, + 420, 90, 91, 92, 480, 425, 423, 422, 90, 91, + 92, 480, 424, 90, 91, 92, 90, 91, 92, 426, + 90, 91, 92, 90, 91, 92, 90, 91, 92, 428, + 480, 90, 91, 92, 425, 427, 90, 91, 92, 90, + 91, 92, 90, 91, 92, 480, 430, 426, 429, 431, + + 90, 91, 92, 432, 480, 480, 435, 428, 90, 91, + 92, 433, 480, 427, 90, 91, 92, 480, 90, 91, + 92, 480, 90, 91, 92, 430, 429, 436, 90, 91, + 92, 480, 432, 434, 435, 90, 91, 92, 480, 437, + 433, 90, 91, 92, 90, 91, 92, 438, 480, 90, + 91, 92, 90, 91, 92, 439, 436, 440, 90, 91, + 92, 434, 441, 480, 90, 91, 92, 437, 443, 480, + 90, 91, 92, 480, 480, 438, 90, 91, 92, 90, + 91, 92, 442, 439, 480, 440, 90, 91, 92, 480, + 480, 441, 90, 91, 92, 444, 443, 90, 91, 92, + + 90, 91, 92, 90, 91, 92, 445, 446, 480, 448, + 442, 90, 91, 92, 480, 447, 90, 91, 92, 90, + 91, 92, 449, 444, 90, 91, 92, 90, 91, 92, + 90, 91, 92, 452, 445, 451, 446, 448, 450, 480, + 480, 90, 91, 92, 447, 90, 91, 92, 90, 91, + 92, 449, 90, 91, 92, 90, 91, 92, 453, 90, + 91, 92, 452, 451, 454, 480, 450, 90, 91, 92, + 455, 480, 458, 480, 480, 90, 91, 92, 456, 457, + 90, 91, 92, 90, 91, 92, 459, 453, 90, 91, + 92, 461, 480, 454, 90, 91, 92, 480, 455, 480, + + 460, 458, 90, 91, 92, 480, 456, 462, 457, 480, + 464, 90, 91, 92, 465, 459, 90, 91, 92, 463, + 461, 90, 91, 92, 90, 91, 92, 480, 460, 90, + 91, 92, 90, 91, 92, 462, 90, 91, 92, 464, + 466, 480, 480, 465, 90, 91, 92, 463, 90, 91, + 92, 90, 91, 92, 480, 480, 90, 91, 92, 90, + 91, 92, 90, 91, 92, 480, 90, 91, 92, 466, + 90, 91, 92, 90, 91, 92, 90, 91, 92, 90, + 91, 92, 467, 90, 91, 92, 90, 91, 92, 90, + 91, 92, 90, 91, 92, 468, 90, 91, 92, 469, + + 470, 90, 91, 92, 90, 91, 92, 471, 480, 480, + 467, 472, 480, 478, 473, 90, 91, 92, 480, 480, + 90, 91, 92, 480, 468, 480, 477, 469, 470, 90, + 91, 92, 474, 480, 475, 471, 90, 91, 92, 480, + 472, 478, 480, 473, 90, 91, 92, 90, 91, 92, + 90, 91, 92, 476, 480, 477, 480, 90, 91, 92, + 474, 479, 475, 90, 91, 92, 90, 91, 92, 90, + 91, 92, 90, 91, 92, 90, 91, 92, 480, 480, + 480, 476, 90, 91, 92, 480, 480, 480, 480, 479, + 90, 91, 92, 480, 480, 480, 480, 480, 480, 480, + + 480, 480, 90, 91, 92, 64, 480, 64, 64, 64, + 64, 64, 66, 480, 66, 66, 66, 66, 66, 75, + 75, 83, 480, 83, 83, 83, 142, 480, 142, 142, + 142, 142, 142, 144, 480, 144, 144, 144, 144, 144, + 154, 154, 227, 227, 227, 5, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480 + } ; + +static const flex_int16_t yy_chk[2532] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 4, 8, 8, 9, + 9, 21, 21, 23, 32, 23, 23, 24, 40, 24, + + 24, 27, 27, 27, 29, 29, 34, 23, 62, 62, + 34, 24, 234, 42, 3, 4, 38, 38, 38, 73, + 228, 73, 227, 32, 73, 73, 23, 40, 41, 82, + 82, 152, 152, 50, 163, 34, 23, 153, 153, 34, + 24, 162, 42, 83, 83, 83, 32, 32, 32, 149, + 40, 40, 40, 148, 23, 31, 31, 41, 34, 34, + 34, 35, 50, 35, 145, 31, 52, 31, 35, 42, + 42, 42, 31, 35, 31, 144, 41, 41, 41, 142, + 36, 50, 50, 50, 31, 31, 141, 45, 36, 35, + 92, 35, 91, 31, 36, 31, 35, 36, 155, 155, + + 31, 35, 31, 90, 45, 67, 35, 35, 35, 36, + 31, 31, 31, 33, 66, 65, 45, 36, 86, 64, + 33, 37, 36, 43, 61, 36, 59, 33, 37, 43, + 33, 58, 45, 33, 57, 55, 36, 36, 36, 52, + 52, 52, 33, 45, 45, 45, 86, 69, 69, 33, + 37, 43, 86, 86, 86, 33, 37, 43, 33, 69, + 54, 33, 53, 30, 44, 43, 43, 43, 44, 33, + 33, 33, 44, 37, 37, 37, 39, 39, 28, 71, + 71, 46, 22, 39, 39, 46, 20, 14, 69, 39, + 11, 71, 44, 10, 7, 46, 44, 85, 5, 0, + + 44, 47, 111, 111, 111, 39, 39, 44, 44, 44, + 46, 39, 39, 0, 46, 0, 47, 39, 0, 49, + 71, 49, 0, 46, 49, 85, 0, 39, 39, 39, + 47, 51, 51, 0, 85, 85, 85, 46, 46, 46, + 0, 48, 0, 117, 47, 48, 0, 49, 48, 49, + 84, 0, 49, 47, 47, 47, 104, 0, 48, 88, + 51, 51, 49, 49, 49, 72, 0, 72, 72, 0, + 48, 117, 0, 87, 48, 151, 151, 48, 84, 72, + 51, 51, 51, 89, 0, 104, 48, 151, 88, 117, + 117, 117, 84, 84, 84, 93, 95, 48, 48, 48, + + 60, 60, 87, 94, 104, 104, 104, 96, 72, 96, + 60, 89, 60, 88, 88, 88, 151, 60, 108, 60, + 89, 89, 89, 93, 0, 95, 87, 87, 87, 60, + 60, 94, 93, 93, 93, 96, 97, 96, 60, 98, + 60, 94, 94, 94, 100, 60, 108, 60, 95, 95, + 95, 0, 96, 96, 96, 60, 60, 60, 99, 0, + 108, 108, 108, 101, 99, 97, 102, 98, 103, 0, + 106, 99, 100, 121, 121, 121, 0, 0, 98, 98, + 98, 0, 100, 100, 100, 0, 109, 99, 97, 97, + 97, 101, 99, 0, 0, 102, 0, 103, 106, 99, + + 107, 101, 101, 101, 105, 0, 107, 105, 0, 99, + 99, 99, 0, 110, 109, 106, 106, 106, 0, 102, + 102, 102, 103, 103, 103, 122, 122, 122, 107, 109, + 109, 109, 112, 105, 107, 105, 113, 116, 0, 0, + 115, 110, 0, 0, 114, 107, 107, 107, 0, 114, + 0, 118, 105, 105, 105, 110, 110, 110, 120, 114, + 112, 0, 0, 119, 113, 116, 123, 131, 115, 116, + 116, 116, 0, 114, 0, 112, 112, 112, 114, 118, + 113, 113, 113, 115, 115, 115, 120, 114, 118, 118, + 118, 119, 0, 124, 0, 123, 131, 114, 114, 114, + + 119, 119, 119, 120, 120, 120, 125, 126, 0, 0, + 125, 0, 126, 0, 133, 147, 147, 147, 123, 123, + 123, 124, 131, 131, 131, 159, 159, 159, 160, 160, + 160, 0, 124, 124, 124, 125, 126, 128, 0, 125, + 126, 129, 0, 133, 176, 176, 176, 0, 128, 129, + 130, 132, 0, 130, 0, 126, 126, 126, 125, 125, + 125, 127, 127, 0, 0, 128, 133, 133, 133, 129, + 134, 127, 136, 0, 127, 127, 128, 129, 130, 132, + 137, 130, 128, 128, 128, 0, 129, 129, 129, 139, + 127, 127, 130, 130, 130, 132, 132, 132, 134, 127, + + 0, 136, 127, 127, 135, 0, 134, 134, 134, 137, + 138, 135, 127, 127, 127, 0, 140, 150, 139, 157, + 193, 193, 193, 0, 156, 136, 136, 136, 137, 137, + 137, 0, 0, 135, 161, 0, 0, 158, 138, 0, + 135, 139, 139, 139, 140, 164, 150, 0, 157, 138, + 138, 138, 156, 140, 140, 140, 0, 170, 0, 135, + 135, 135, 161, 156, 156, 156, 158, 157, 157, 157, + 150, 150, 150, 164, 166, 214, 161, 161, 161, 164, + 164, 164, 165, 169, 165, 170, 167, 171, 212, 212, + 212, 171, 0, 158, 158, 158, 170, 170, 170, 165, + + 229, 229, 229, 166, 214, 168, 173, 237, 237, 237, + 0, 165, 169, 165, 167, 0, 171, 0, 168, 172, + 171, 177, 175, 214, 214, 214, 174, 165, 166, 166, + 166, 167, 167, 167, 168, 173, 165, 165, 165, 169, + 169, 169, 178, 171, 171, 171, 168, 0, 172, 0, + 177, 175, 0, 0, 174, 179, 168, 168, 168, 180, + 173, 173, 173, 174, 174, 174, 181, 182, 0, 0, + 178, 172, 172, 172, 175, 175, 175, 177, 177, 177, + 178, 178, 178, 179, 0, 0, 183, 180, 184, 185, + 186, 0, 190, 187, 181, 182, 188, 180, 180, 180, + + 179, 179, 179, 181, 181, 181, 238, 238, 238, 248, + 248, 248, 182, 182, 182, 183, 184, 0, 185, 186, + 190, 187, 189, 0, 192, 188, 191, 195, 0, 190, + 190, 190, 184, 184, 184, 187, 187, 187, 183, 183, + 183, 185, 185, 185, 194, 186, 186, 186, 188, 188, + 188, 189, 192, 0, 0, 191, 195, 196, 197, 200, + 192, 192, 192, 0, 0, 201, 0, 198, 250, 250, + 250, 0, 0, 194, 189, 189, 189, 0, 191, 191, + 191, 195, 195, 195, 199, 196, 197, 203, 200, 202, + 204, 0, 0, 201, 0, 198, 194, 194, 194, 0, + + 196, 196, 196, 197, 197, 197, 198, 198, 198, 201, + 201, 201, 199, 200, 200, 200, 203, 202, 205, 204, + 206, 199, 199, 199, 207, 232, 0, 202, 202, 202, + 253, 253, 253, 258, 258, 258, 209, 203, 203, 203, + 208, 215, 204, 204, 204, 211, 210, 205, 206, 0, + 0, 213, 207, 232, 0, 0, 210, 232, 232, 232, + 0, 207, 207, 207, 209, 206, 206, 206, 208, 215, + 205, 205, 205, 216, 211, 210, 208, 208, 208, 213, + 217, 209, 209, 209, 210, 219, 215, 215, 215, 218, + 213, 213, 213, 220, 210, 210, 210, 211, 211, 211, + + 0, 216, 221, 0, 222, 260, 260, 260, 217, 267, + 267, 267, 0, 219, 216, 216, 216, 223, 218, 0, + 0, 220, 225, 217, 217, 217, 0, 219, 219, 219, + 0, 221, 222, 220, 220, 220, 224, 230, 233, 0, + 224, 218, 218, 218, 0, 223, 0, 222, 222, 222, + 231, 225, 0, 235, 223, 223, 223, 241, 221, 221, + 221, 236, 0, 239, 224, 230, 240, 233, 224, 0, + 0, 225, 225, 225, 230, 230, 230, 0, 231, 224, + 224, 224, 235, 249, 0, 241, 233, 233, 233, 0, + 236, 239, 231, 231, 231, 240, 0, 242, 244, 0, + + 243, 246, 241, 241, 241, 235, 235, 235, 0, 239, + 239, 239, 249, 270, 270, 270, 247, 236, 236, 236, + 245, 251, 240, 240, 240, 242, 0, 244, 243, 246, + 0, 249, 249, 249, 242, 242, 242, 243, 243, 243, + 246, 246, 246, 252, 247, 254, 0, 256, 245, 251, + 244, 244, 244, 247, 247, 247, 245, 245, 245, 255, + 0, 0, 251, 251, 251, 259, 257, 0, 261, 0, + 0, 252, 262, 264, 254, 256, 271, 271, 271, 0, + 252, 252, 252, 284, 284, 284, 0, 0, 255, 256, + 256, 256, 266, 259, 0, 257, 261, 254, 254, 254, + + 263, 262, 264, 265, 259, 259, 259, 261, 261, 261, + 0, 255, 255, 255, 257, 257, 257, 268, 0, 269, + 266, 264, 264, 264, 272, 262, 262, 262, 263, 273, + 274, 265, 0, 263, 263, 263, 0, 266, 266, 266, + 275, 0, 265, 265, 265, 0, 268, 269, 276, 0, + 277, 279, 0, 272, 0, 269, 269, 269, 273, 274, + 290, 290, 290, 291, 291, 291, 268, 268, 268, 275, + 278, 280, 272, 272, 272, 0, 0, 276, 277, 0, + 279, 273, 273, 273, 0, 281, 274, 274, 274, 277, + 277, 277, 275, 275, 275, 289, 0, 0, 278, 280, + + 276, 276, 276, 278, 278, 278, 282, 279, 279, 279, + 280, 280, 280, 281, 283, 0, 285, 297, 297, 297, + 0, 286, 287, 289, 281, 281, 281, 288, 300, 300, + 300, 306, 306, 306, 0, 282, 0, 289, 289, 289, + 318, 318, 318, 283, 0, 285, 325, 325, 325, 0, + 286, 287, 0, 0, 292, 295, 288, 293, 299, 294, + 298, 282, 282, 282, 329, 329, 329, 283, 283, 283, + 285, 285, 285, 286, 286, 286, 287, 287, 287, 288, + 288, 288, 292, 296, 295, 293, 299, 294, 301, 298, + 292, 292, 292, 293, 293, 293, 294, 294, 294, 302, + + 299, 299, 299, 0, 0, 295, 295, 295, 303, 0, + 0, 296, 298, 298, 298, 304, 301, 305, 0, 296, + 296, 296, 307, 0, 0, 308, 310, 302, 0, 314, + 0, 301, 301, 301, 0, 0, 303, 302, 302, 302, + 334, 334, 334, 0, 304, 0, 305, 0, 309, 311, + 307, 303, 303, 303, 308, 310, 312, 313, 314, 307, + 307, 307, 315, 335, 335, 335, 316, 304, 304, 304, + 305, 305, 305, 308, 308, 308, 309, 311, 310, 310, + 310, 314, 314, 314, 312, 313, 317, 309, 309, 309, + 315, 0, 311, 311, 311, 316, 313, 313, 313, 319, + + 320, 312, 312, 312, 321, 315, 315, 315, 322, 342, + 342, 342, 324, 0, 317, 323, 326, 0, 316, 316, + 316, 346, 346, 346, 317, 317, 317, 319, 320, 0, + 328, 0, 0, 321, 320, 320, 320, 322, 319, 319, + 319, 324, 327, 330, 323, 326, 351, 351, 351, 332, + 353, 353, 353, 336, 321, 321, 321, 331, 328, 333, + 324, 324, 324, 338, 322, 322, 322, 323, 323, 323, + 327, 330, 326, 326, 326, 328, 328, 328, 332, 327, + 327, 327, 336, 337, 339, 331, 340, 333, 330, 330, + 330, 341, 338, 0, 331, 331, 331, 0, 333, 333, + + 333, 0, 332, 332, 332, 336, 336, 336, 344, 0, + 0, 337, 0, 339, 340, 343, 0, 338, 338, 338, + 341, 349, 0, 0, 337, 337, 337, 345, 347, 340, + 340, 340, 339, 339, 339, 0, 0, 344, 355, 355, + 355, 0, 348, 343, 356, 356, 356, 341, 341, 341, + 349, 350, 343, 343, 343, 345, 347, 0, 0, 352, + 359, 344, 344, 344, 345, 345, 345, 347, 347, 347, + 348, 354, 357, 349, 349, 349, 0, 0, 358, 0, + 350, 360, 361, 0, 0, 348, 348, 348, 352, 359, + 362, 363, 363, 363, 367, 367, 367, 0, 0, 354, + + 0, 357, 364, 350, 350, 350, 358, 354, 354, 354, + 360, 361, 359, 359, 359, 352, 352, 352, 0, 362, + 368, 358, 358, 358, 365, 366, 357, 357, 357, 366, + 364, 374, 0, 360, 360, 360, 361, 361, 361, 364, + 364, 364, 369, 369, 369, 373, 362, 362, 362, 368, + 372, 376, 365, 0, 366, 370, 370, 370, 366, 374, + 0, 365, 365, 365, 371, 371, 371, 377, 374, 374, + 374, 0, 0, 373, 368, 368, 368, 380, 0, 372, + 376, 366, 366, 366, 375, 375, 375, 381, 373, 373, + 373, 378, 378, 378, 0, 377, 382, 387, 372, 372, + + 372, 379, 379, 379, 384, 380, 383, 376, 376, 376, + 0, 0, 377, 377, 377, 0, 381, 385, 385, 385, + 0, 386, 380, 380, 380, 382, 387, 389, 388, 390, + 390, 390, 384, 393, 383, 381, 381, 381, 383, 383, + 383, 391, 391, 391, 382, 382, 382, 384, 384, 384, + 386, 387, 387, 387, 0, 394, 389, 388, 392, 392, + 392, 0, 393, 395, 395, 395, 396, 396, 396, 397, + 400, 400, 400, 386, 386, 386, 388, 388, 388, 399, + 0, 389, 389, 389, 394, 398, 401, 401, 401, 393, + 393, 393, 402, 402, 402, 0, 404, 397, 403, 405, + + 406, 406, 406, 407, 0, 0, 410, 399, 394, 394, + 394, 408, 0, 398, 397, 397, 397, 0, 399, 399, + 399, 0, 398, 398, 398, 404, 403, 412, 405, 405, + 405, 0, 407, 409, 410, 403, 403, 403, 0, 413, + 408, 411, 411, 411, 404, 404, 404, 414, 0, 410, + 410, 410, 415, 415, 415, 416, 412, 417, 407, 407, + 407, 409, 419, 0, 408, 408, 408, 413, 422, 0, + 409, 409, 409, 0, 0, 414, 413, 413, 413, 412, + 412, 412, 421, 416, 0, 417, 418, 418, 418, 0, + 0, 419, 414, 414, 414, 423, 422, 416, 416, 416, + + 417, 417, 417, 420, 420, 420, 424, 425, 0, 430, + 421, 422, 422, 422, 0, 428, 419, 419, 419, 421, + 421, 421, 431, 423, 426, 426, 426, 427, 427, 427, + 429, 429, 429, 435, 424, 432, 425, 430, 431, 0, + 0, 423, 423, 423, 428, 424, 424, 424, 433, 433, + 433, 431, 430, 430, 430, 434, 434, 434, 436, 425, + 425, 425, 435, 432, 437, 0, 431, 428, 428, 428, + 438, 0, 441, 0, 0, 431, 431, 431, 439, 440, + 432, 432, 432, 435, 435, 435, 443, 436, 442, 442, + 442, 446, 0, 437, 444, 444, 444, 0, 438, 0, + + 445, 441, 438, 438, 438, 0, 439, 447, 440, 0, + 449, 436, 436, 436, 450, 443, 437, 437, 437, 448, + 446, 439, 439, 439, 441, 441, 441, 0, 445, 440, + 440, 440, 445, 445, 445, 447, 443, 443, 443, 449, + 451, 0, 0, 450, 446, 446, 446, 448, 452, 452, + 452, 447, 447, 447, 0, 0, 448, 448, 448, 453, + 453, 453, 450, 450, 450, 0, 449, 449, 449, 451, + 454, 454, 454, 455, 455, 455, 456, 456, 456, 457, + 457, 457, 458, 459, 459, 459, 460, 460, 460, 461, + 461, 461, 451, 451, 451, 462, 463, 463, 463, 464, + + 465, 466, 466, 466, 467, 467, 467, 468, 0, 0, + 458, 469, 0, 477, 470, 472, 472, 472, 0, 0, + 458, 458, 458, 0, 462, 0, 476, 464, 465, 474, + 474, 474, 471, 0, 473, 468, 464, 464, 464, 0, + 469, 477, 0, 470, 465, 465, 465, 462, 462, 462, + 468, 468, 468, 475, 0, 476, 0, 477, 477, 477, + 471, 478, 473, 469, 469, 469, 470, 470, 470, 471, + 471, 471, 473, 473, 473, 479, 479, 479, 0, 0, + 0, 475, 476, 476, 476, 0, 0, 0, 0, 478, + 475, 475, 475, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 478, 478, 478, 481, 0, 481, 481, 481, + 481, 481, 482, 0, 482, 482, 482, 482, 482, 483, + 483, 484, 0, 484, 484, 484, 485, 0, 485, 485, + 485, 485, 485, 486, 0, 486, 486, 486, 486, 486, + 487, 487, 488, 488, 488, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, + 480 + } ; + +static const flex_int16_t yy_rule_linenum[126] = + { 0, + 80, 81, 83, 89, 113, 114, 115, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 202, 203, 204, 205, 206, 207, 208, 209, 210, + + 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 235, 237 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "sqlite3_lexer.ll" +#line 2 "sqlite3_lexer.ll" +#include +#include "ParserDriver.h" +#include "sqlite3_parser.hpp" +#line 1244 "sqlite3_lexer.cpp" +#define YY_NO_UNISTD_H 1 +#line 12 "sqlite3_lexer.ll" + #define TOKEN(n) sqlb::parser::parser::symbol_type(sqlb::parser::parser::token::TOK_##n, yytext, loc) + + std::string unquote_string(std::string s, char quote_char) + { + if(s.size() < 2) + return s; + + if(quote_char == '[') + { + if(s.front() == '[' && s.back() == ']') + s = s.substr(1, s.size()-2); + } else { + if(s.front() == quote_char && s.back() == quote_char) + { + s = s.substr(1, s.size()-2); + auto pos = s.npos; + while((pos = s.find(std::string(2, quote_char))) != s.npos) + s = s.replace(pos, 2, std::string(1, quote_char)); + } + } + + return s; + } +#line 1270 "sqlite3_lexer.cpp" +#line 55 "sqlite3_lexer.ll" + /* TODO Add $ bind parameters */ + // Code run each time a pattern is matched. + #define YY_USER_ACTION loc.columns(yyleng); +#line 1275 "sqlite3_lexer.cpp" + +#line 1277 "sqlite3_lexer.cpp" + +#define INITIAL 0 +#define BETWEEN_MODE 1 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +/* %if-c-only */ +#include +/* %endif */ +/* %if-c++-only */ +/* %endif */ +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* %if-c-only Reentrant structure and macros (non-C++). */ +/* %if-reentrant */ + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t + { + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + int yy_n_chars; + int yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + }; /* end struct yyguts_t */ + +/* %if-c-only */ + +static int yy_init_globals ( yyscan_t yyscanner ); + +/* %endif */ + +/* %if-reentrant */ + +int yylex_init (yyscan_t* scanner); + +int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); + +/* %endif */ + +/* %endif End reentrant structures and macros. */ + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( yyscan_t yyscanner ); + +int yyget_debug ( yyscan_t yyscanner ); + +void yyset_debug ( int debug_flag , yyscan_t yyscanner ); + +YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); + +FILE *yyget_in ( yyscan_t yyscanner ); + +void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); + +FILE *yyget_out ( yyscan_t yyscanner ); + +void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); + + int yyget_leng ( yyscan_t yyscanner ); + +char *yyget_text ( yyscan_t yyscanner ); + +int yyget_lineno ( yyscan_t yyscanner ); + +void yyset_lineno ( int _line_number , yyscan_t yyscanner ); + +int yyget_column ( yyscan_t yyscanner ); + +void yyset_column ( int _column_no , yyscan_t yyscanner ); + +/* %if-bison-bridge */ +/* %endif */ + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( yyscan_t yyscanner ); +#else +extern int yywrap ( yyscan_t yyscanner ); +#endif +#endif + +/* %not-for-header */ +#ifndef YY_NO_UNPUT + +#endif +/* %ok-for-header */ + +/* %endif */ + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * , yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT +/* %if-c-only Standard (non-C++) definition */ +/* %not-for-header */ +#ifdef __cplusplus +static int yyinput ( yyscan_t yyscanner ); +#else +static int input ( yyscan_t yyscanner ); +#endif +/* %ok-for-header */ + +/* %endif */ +#endif + +/* %if-c-only */ + +/* %endif */ + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* %if-c-only Standard (non-C++) definition */ +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) +/* %endif */ +/* %if-c++-only C++ definition */ +/* %endif */ +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ +/* %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ */\ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + int n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ +/* %if-c++-only C++ definition \ */\ +/* %endif */ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +/* %if-c-only */ +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +#endif + +/* %if-tables-serialization structures and prototypes */ +/* %not-for-header */ +/* %ok-for-header */ + +/* %not-for-header */ +/* %tables-yydmap generated elements */ +/* %endif */ +/* end tables serialization structures and prototypes */ + +/* %ok-for-header */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 +/* %if-c-only Standard (non-C++) definition */ + +extern int yylex (yyscan_t yyscanner); + +#define YY_DECL int yylex (yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only C++ definition */ +/* %endif */ +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +/* %% [6.0] YY_RULE_SETUP definition goes here */ +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/* %not-for-header */ +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( !yyg->yy_init ) + { + yyg->yy_init = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yyg->yy_start ) + yyg->yy_start = 1; /* first start state */ + + if ( ! yyin ) +/* %if-c-only */ + yyin = stdin; +/* %endif */ +/* %if-c++-only */ +/* %endif */ + + if ( ! yyout ) +/* %if-c-only */ + yyout = stdout; +/* %endif */ +/* %if-c++-only */ +/* %endif */ + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); + } + + yy_load_buffer_state( yyscanner ); + } + + { +/* %% [7.0] user's declarations go here */ +#line 69 "sqlite3_lexer.ll" + + + +#line 73 "sqlite3_lexer.ll" + // Shortcut to the location held by the driver + sqlb::parser::location& loc = drv.location; + + // Code run each time yylex is called. + loc.step(); + + +#line 1615 "sqlite3_lexer.cpp" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { +/* %% [8.0] yymore()-related code goes here */ + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + +/* %% [9.0] code to set up and find next match goes here */ + yy_current_state = yyg->yy_start; +yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 481 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + ++yy_cp; + } + while ( yy_current_state != 480 ); + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + +yy_find_action: +/* %% [10.0] code to find the action number goes here */ + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +/* %% [11.0] code for yylineno update goes here */ + +do_action: /* This label is used only to access EOF actions. */ + +/* %% [12.0] debug code goes here */ + if ( yy_flex_debug ) + { + if ( yy_act == 0 ) + fprintf( stderr, "--scanner backing up\n" ); + else if ( yy_act < 126 ) + fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", + (long)yy_rule_linenum[yy_act], yytext ); + else if ( yy_act == 126 ) + fprintf( stderr, "--accepting default rule (\"%s\")\n", + yytext ); + else if ( yy_act == 127 ) + fprintf( stderr, "--(end of buffer or a NUL)\n" ); + else + fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); + } + + switch ( yy_act ) + { /* beginning of action switch */ +/* %% [13.0] actions go here */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 80 "sqlite3_lexer.ll" +loc.step(); + YY_BREAK +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +#line 81 "sqlite3_lexer.ll" +loc.lines(yyleng); loc.step(); + YY_BREAK +case 3: +YY_RULE_SETUP +#line 83 "sqlite3_lexer.ll" +{ + int c; + while((c = yyinput(yyscanner)) != '\n' && c != EOF) + ; /* eat up text of comment */ + } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 89 "sqlite3_lexer.ll" +{ + int c; + + for(;;) + { + while((c = yyinput(yyscanner)) != '*' && c != EOF) + ; /* eat up text of comment */ + + if(c == '*') + { + while((c = yyinput(yyscanner)) == '*') + ; + if(c == '/') + break; /* found the end */ + } + + if(c == EOF) + throw sqlb::parser::parser::syntax_error(loc, "EOF in comment"); + } + } + YY_BREAK +/* For lack of a better idea, we need this hack to avoid reduce/reduce conflicts in the rules for parsing BETWEEN expressions. + * What we do here is distinguish two types of AND operators: the regular one and the special case when the AND follows a BETWEEN keyword. + */ +case 5: +YY_RULE_SETUP +#line 113 "sqlite3_lexer.ll" +{ BEGIN INITIAL; return TOKEN(AND_BETWEEN); } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 114 "sqlite3_lexer.ll" +return TOKEN(AND); + YY_BREAK +case 7: +YY_RULE_SETUP +#line 115 "sqlite3_lexer.ll" +{ BEGIN BETWEEN_MODE; return TOKEN(BETWEEN); } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 117 "sqlite3_lexer.ll" +return TOKEN(ABORT); + YY_BREAK +case 9: +YY_RULE_SETUP +#line 118 "sqlite3_lexer.ll" +return TOKEN(ACTION); + YY_BREAK +case 10: +YY_RULE_SETUP +#line 119 "sqlite3_lexer.ll" +return TOKEN(ALWAYS); + YY_BREAK +case 11: +YY_RULE_SETUP +#line 120 "sqlite3_lexer.ll" +return TOKEN(AS); + YY_BREAK +case 12: +YY_RULE_SETUP +#line 121 "sqlite3_lexer.ll" +return TOKEN(ASC); + YY_BREAK +case 13: +YY_RULE_SETUP +#line 122 "sqlite3_lexer.ll" +return TOKEN(AUTOINCREMENT); + YY_BREAK +case 14: +YY_RULE_SETUP +#line 123 "sqlite3_lexer.ll" +return TOKEN(CASCADE); + YY_BREAK +case 15: +YY_RULE_SETUP +#line 124 "sqlite3_lexer.ll" +return TOKEN(CASE); + YY_BREAK +case 16: +YY_RULE_SETUP +#line 125 "sqlite3_lexer.ll" +return TOKEN(CAST); + YY_BREAK +case 17: +YY_RULE_SETUP +#line 126 "sqlite3_lexer.ll" +return TOKEN(CHECK); + YY_BREAK +case 18: +YY_RULE_SETUP +#line 127 "sqlite3_lexer.ll" +return TOKEN(COLLATE); + YY_BREAK +case 19: +YY_RULE_SETUP +#line 128 "sqlite3_lexer.ll" +return TOKEN(CONFLICT); + YY_BREAK +case 20: +YY_RULE_SETUP +#line 129 "sqlite3_lexer.ll" +return TOKEN(CONSTRAINT); + YY_BREAK +case 21: +YY_RULE_SETUP +#line 130 "sqlite3_lexer.ll" +return TOKEN(CREATE); + YY_BREAK +case 22: +YY_RULE_SETUP +#line 131 "sqlite3_lexer.ll" +return TOKEN(CURRENT_DATE); + YY_BREAK +case 23: +YY_RULE_SETUP +#line 132 "sqlite3_lexer.ll" +return TOKEN(CURRENT_TIME); + YY_BREAK +case 24: +YY_RULE_SETUP +#line 133 "sqlite3_lexer.ll" +return TOKEN(CURRENT_TIMESTAMP); + YY_BREAK +case 25: +YY_RULE_SETUP +#line 134 "sqlite3_lexer.ll" +return TOKEN(DEFAULT); + YY_BREAK +case 26: +YY_RULE_SETUP +#line 135 "sqlite3_lexer.ll" +return TOKEN(DEFERRABLE); + YY_BREAK +case 27: +YY_RULE_SETUP +#line 136 "sqlite3_lexer.ll" +return TOKEN(DEFERRED); + YY_BREAK +case 28: +YY_RULE_SETUP +#line 137 "sqlite3_lexer.ll" +return TOKEN(DELETE); + YY_BREAK +case 29: +YY_RULE_SETUP +#line 138 "sqlite3_lexer.ll" +return TOKEN(DESC); + YY_BREAK +case 30: +YY_RULE_SETUP +#line 139 "sqlite3_lexer.ll" +return TOKEN(DISTINCT); + YY_BREAK +case 31: +YY_RULE_SETUP +#line 140 "sqlite3_lexer.ll" +return TOKEN(ELSE); + YY_BREAK +case 32: +YY_RULE_SETUP +#line 141 "sqlite3_lexer.ll" +return TOKEN(END); + YY_BREAK +case 33: +YY_RULE_SETUP +#line 142 "sqlite3_lexer.ll" +return TOKEN(ESCAPE); + YY_BREAK +case 34: +YY_RULE_SETUP +#line 143 "sqlite3_lexer.ll" +return TOKEN(EXISTS); + YY_BREAK +case 35: +YY_RULE_SETUP +#line 144 "sqlite3_lexer.ll" +return TOKEN(FAIL); + YY_BREAK +case 36: +YY_RULE_SETUP +#line 145 "sqlite3_lexer.ll" +return TOKEN(FALSE); + YY_BREAK +case 37: +YY_RULE_SETUP +#line 146 "sqlite3_lexer.ll" +return TOKEN(FILTER); + YY_BREAK +case 38: +YY_RULE_SETUP +#line 147 "sqlite3_lexer.ll" +return TOKEN(FOLLOWING); + YY_BREAK +case 39: +YY_RULE_SETUP +#line 148 "sqlite3_lexer.ll" +return TOKEN(FOREIGN); + YY_BREAK +case 40: +YY_RULE_SETUP +#line 149 "sqlite3_lexer.ll" +return TOKEN(FROM); + YY_BREAK +case 41: +YY_RULE_SETUP +#line 150 "sqlite3_lexer.ll" +return TOKEN(GENERATED); + YY_BREAK +case 42: +YY_RULE_SETUP +#line 151 "sqlite3_lexer.ll" +return TOKEN(GLOB); + YY_BREAK +case 43: +YY_RULE_SETUP +#line 152 "sqlite3_lexer.ll" +return TOKEN(IF); + YY_BREAK +case 44: +YY_RULE_SETUP +#line 153 "sqlite3_lexer.ll" +return TOKEN(IGNORE); + YY_BREAK +case 45: +YY_RULE_SETUP +#line 154 "sqlite3_lexer.ll" +return TOKEN(IMMEDIATE); + YY_BREAK +case 46: +YY_RULE_SETUP +#line 155 "sqlite3_lexer.ll" +return TOKEN(IN); + YY_BREAK +case 47: +YY_RULE_SETUP +#line 156 "sqlite3_lexer.ll" +return TOKEN(INDEX); + YY_BREAK +case 48: +YY_RULE_SETUP +#line 157 "sqlite3_lexer.ll" +return TOKEN(INITIALLY); + YY_BREAK +case 49: +YY_RULE_SETUP +#line 158 "sqlite3_lexer.ll" +return TOKEN(INSERT); + YY_BREAK +case 50: +YY_RULE_SETUP +#line 159 "sqlite3_lexer.ll" +return TOKEN(IS); + YY_BREAK +case 51: +YY_RULE_SETUP +#line 160 "sqlite3_lexer.ll" +return TOKEN(ISNULL); + YY_BREAK +case 52: +YY_RULE_SETUP +#line 161 "sqlite3_lexer.ll" +return TOKEN(KEY); + YY_BREAK +case 53: +YY_RULE_SETUP +#line 162 "sqlite3_lexer.ll" +return TOKEN(LIKE); + YY_BREAK +case 54: +YY_RULE_SETUP +#line 163 "sqlite3_lexer.ll" +return TOKEN(MATCH); + YY_BREAK +case 55: +YY_RULE_SETUP +#line 164 "sqlite3_lexer.ll" +return TOKEN(NO); + YY_BREAK +case 56: +YY_RULE_SETUP +#line 165 "sqlite3_lexer.ll" +return TOKEN(NOT); + YY_BREAK +case 57: +YY_RULE_SETUP +#line 166 "sqlite3_lexer.ll" +return TOKEN(NOTNULL); + YY_BREAK +case 58: +YY_RULE_SETUP +#line 167 "sqlite3_lexer.ll" +return TOKEN(NULL); + YY_BREAK +case 59: +YY_RULE_SETUP +#line 168 "sqlite3_lexer.ll" +return TOKEN(ON); + YY_BREAK +case 60: +YY_RULE_SETUP +#line 169 "sqlite3_lexer.ll" +return TOKEN(OR); + YY_BREAK +case 61: +YY_RULE_SETUP +#line 170 "sqlite3_lexer.ll" +return TOKEN(OVER); + YY_BREAK +case 62: +YY_RULE_SETUP +#line 171 "sqlite3_lexer.ll" +return TOKEN(PARTITION); + YY_BREAK +case 63: +YY_RULE_SETUP +#line 172 "sqlite3_lexer.ll" +return TOKEN(PRECEDING); + YY_BREAK +case 64: +YY_RULE_SETUP +#line 173 "sqlite3_lexer.ll" +return TOKEN(PRIMARY); + YY_BREAK +case 65: +YY_RULE_SETUP +#line 174 "sqlite3_lexer.ll" +return TOKEN(RAISE); + YY_BREAK +case 66: +YY_RULE_SETUP +#line 175 "sqlite3_lexer.ll" +return TOKEN(RANGE); + YY_BREAK +case 67: +YY_RULE_SETUP +#line 176 "sqlite3_lexer.ll" +return TOKEN(REFERENCES); + YY_BREAK +case 68: +YY_RULE_SETUP +#line 177 "sqlite3_lexer.ll" +return TOKEN(REGEXP); + YY_BREAK +case 69: +YY_RULE_SETUP +#line 178 "sqlite3_lexer.ll" +return TOKEN(REPLACE); + YY_BREAK +case 70: +YY_RULE_SETUP +#line 179 "sqlite3_lexer.ll" +return TOKEN(RESTRICT); + YY_BREAK +case 71: +YY_RULE_SETUP +#line 180 "sqlite3_lexer.ll" +return TOKEN(RETURNING); + YY_BREAK +case 72: +YY_RULE_SETUP +#line 181 "sqlite3_lexer.ll" +return TOKEN(ROLLBACK); + YY_BREAK +case 73: +YY_RULE_SETUP +#line 182 "sqlite3_lexer.ll" +return TOKEN(ROWID); + YY_BREAK +case 74: +YY_RULE_SETUP +#line 183 "sqlite3_lexer.ll" +return TOKEN(ROWS); + YY_BREAK +case 75: +YY_RULE_SETUP +#line 184 "sqlite3_lexer.ll" +return TOKEN(SELECT); + YY_BREAK +case 76: +YY_RULE_SETUP +#line 185 "sqlite3_lexer.ll" +return TOKEN(SET); + YY_BREAK +case 77: +YY_RULE_SETUP +#line 186 "sqlite3_lexer.ll" +return TOKEN(STORED); + YY_BREAK +case 78: +YY_RULE_SETUP +#line 187 "sqlite3_lexer.ll" +return TOKEN(STRICT); + YY_BREAK +case 79: +YY_RULE_SETUP +#line 188 "sqlite3_lexer.ll" +return TOKEN(TABLE); + YY_BREAK +case 80: +YY_RULE_SETUP +#line 189 "sqlite3_lexer.ll" +return TOKEN(TEMP); + YY_BREAK +case 81: +YY_RULE_SETUP +#line 190 "sqlite3_lexer.ll" +return TOKEN(TEMPORARY); + YY_BREAK +case 82: +YY_RULE_SETUP +#line 191 "sqlite3_lexer.ll" +return TOKEN(THEN); + YY_BREAK +case 83: +YY_RULE_SETUP +#line 192 "sqlite3_lexer.ll" +return TOKEN(TRUE); + YY_BREAK +case 84: +YY_RULE_SETUP +#line 193 "sqlite3_lexer.ll" +return TOKEN(UNBOUNDED); + YY_BREAK +case 85: +YY_RULE_SETUP +#line 194 "sqlite3_lexer.ll" +return TOKEN(UNIQUE); + YY_BREAK +case 86: +YY_RULE_SETUP +#line 195 "sqlite3_lexer.ll" +return TOKEN(UPDATE); + YY_BREAK +case 87: +YY_RULE_SETUP +#line 196 "sqlite3_lexer.ll" +return TOKEN(USING); + YY_BREAK +case 88: +YY_RULE_SETUP +#line 197 "sqlite3_lexer.ll" +return TOKEN(VIRTUAL); + YY_BREAK +case 89: +YY_RULE_SETUP +#line 198 "sqlite3_lexer.ll" +return TOKEN(WHEN); + YY_BREAK +case 90: +YY_RULE_SETUP +#line 199 "sqlite3_lexer.ll" +return TOKEN(WHERE); + YY_BREAK +case 91: +YY_RULE_SETUP +#line 200 "sqlite3_lexer.ll" +return TOKEN(WITHOUT); + YY_BREAK +case 92: +YY_RULE_SETUP +#line 202 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_IDENTIFIER(yytext, loc); + YY_BREAK +case 93: +YY_RULE_SETUP +#line 203 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_IDENTIFIER(unquote_string(yytext, '`'), loc); + YY_BREAK +case 94: +YY_RULE_SETUP +#line 204 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_IDENTIFIER(unquote_string(yytext, '['), loc); + YY_BREAK +case 95: +YY_RULE_SETUP +#line 205 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_QUOTEDLITERAL(unquote_string(yytext, '"'), loc); + YY_BREAK +case 96: +YY_RULE_SETUP +#line 206 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_STRINGLITERAL(yytext, loc); + YY_BREAK +case 97: +YY_RULE_SETUP +#line 207 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_NUMERIC(yytext, loc); + YY_BREAK +case 98: +YY_RULE_SETUP +#line 208 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_BLOBLITERAL(yytext, loc); + YY_BREAK +case 99: +YY_RULE_SETUP +#line 209 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_BINDPARAMETER(yytext, loc); + YY_BREAK +case 100: +YY_RULE_SETUP +#line 210 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_BINDPARAMETER(yytext, loc); + YY_BREAK +case 101: +YY_RULE_SETUP +#line 212 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_LPAREN(loc); + YY_BREAK +case 102: +YY_RULE_SETUP +#line 213 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_RPAREN(loc); + YY_BREAK +case 103: +YY_RULE_SETUP +#line 214 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_DOT(loc); + YY_BREAK +case 104: +YY_RULE_SETUP +#line 215 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_COMMA(loc); + YY_BREAK +case 105: +YY_RULE_SETUP +#line 216 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_SEMI(loc); + YY_BREAK +case 106: +YY_RULE_SETUP +#line 217 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_PLUS(loc); + YY_BREAK +case 107: +YY_RULE_SETUP +#line 218 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_MINUS(loc); + YY_BREAK +case 108: +YY_RULE_SETUP +#line 219 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_STAR(loc); + YY_BREAK +case 109: +YY_RULE_SETUP +#line 220 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_SLASH(loc); + YY_BREAK +case 110: +YY_RULE_SETUP +#line 221 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_TILDE(loc); + YY_BREAK +case 111: +YY_RULE_SETUP +#line 222 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_AMPERSAND(loc); + YY_BREAK +case 112: +YY_RULE_SETUP +#line 223 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_PERCENT(loc); + YY_BREAK +case 113: +YY_RULE_SETUP +#line 224 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_BITOR(loc); + YY_BREAK +case 114: +YY_RULE_SETUP +#line 225 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_OROP(loc); + YY_BREAK +case 115: +YY_RULE_SETUP +#line 226 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_EQUAL(loc); + YY_BREAK +case 116: +YY_RULE_SETUP +#line 227 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_EQUAL2(loc); + YY_BREAK +case 117: +YY_RULE_SETUP +#line 228 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_GREATER(loc); + YY_BREAK +case 118: +YY_RULE_SETUP +#line 229 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_GREATEREQUAL(loc); + YY_BREAK +case 119: +YY_RULE_SETUP +#line 230 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_LOWER(loc); + YY_BREAK +case 120: +YY_RULE_SETUP +#line 231 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_LOWEREQUAL(loc); + YY_BREAK +case 121: +YY_RULE_SETUP +#line 232 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_UNEQUAL(loc); + YY_BREAK +case 122: +YY_RULE_SETUP +#line 233 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_UNEQUAL2(loc); + YY_BREAK +case 123: +YY_RULE_SETUP +#line 234 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_BITWISELEFT(loc); + YY_BREAK +case 124: +YY_RULE_SETUP +#line 235 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_BITWISERIGHT(loc); + YY_BREAK +case 125: +YY_RULE_SETUP +#line 237 "sqlite3_lexer.ll" +throw sqlb::parser::parser::syntax_error(loc, "Invalid character: " + std::string(yytext)); + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(BETWEEN_MODE): +#line 239 "sqlite3_lexer.ll" +return sqlb::parser::parser::make_EOF(loc); + YY_BREAK +case 126: +YY_RULE_SETUP +#line 241 "sqlite3_lexer.ll" +YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK +#line 2353 "sqlite3_lexer.cpp" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; +/* %if-c-only */ + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; +/* %endif */ +/* %if-c++-only */ +/* %endif */ + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { +/* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */ + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_END_OF_FILE: + { + yyg->yy_did_buffer_switch_on_eof = 0; + + if ( yywrap( yyscanner ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = + yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ +/* %ok-for-header */ + +/* %if-c++-only */ +/* %not-for-header */ +/* %ok-for-header */ + +/* %endif */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +/* %if-c-only */ +static int yy_get_next_buffer (yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = yyg->yytext_ptr; + int number_to_move, i; + int ret_val; + + if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1); + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc( (void *) b->yy_ch_buf, + (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = NULL; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + yyg->yy_n_chars, num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if ( yyg->yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin , yyscanner); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( + (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + /* "- 2" to take care of EOB's */ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); + } + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +/* %if-c-only */ +/* %not-for-header */ + static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + yy_state_type yy_current_state; + char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +/* %% [15.0] code to get the start state into yy_current_state goes here */ + yy_current_state = yyg->yy_start; + + for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) + { +/* %% [16.0] code to find the next state goes here */ + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 481 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ +/* %if-c-only */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ +/* %% [17.0] code to find the next state, and perhaps do backing up, goes here */ + char *yy_cp = yyg->yy_c_buf_p; + + YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 481 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + yy_is_jam = (yy_current_state == 480); + + (void)yyg; + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT +/* %if-c-only */ + +/* %endif */ +#endif + +/* %if-c-only */ +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (yyscan_t yyscanner) +#else + static int input (yyscan_t yyscanner) +#endif + +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + int c; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr); + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin , yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( yyscanner ) ) + return 0; + + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(yyscanner); +#else + return input(yyscanner); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + +/* %% [19.0] update BOL and yylineno */ + + return c; +} +/* %if-c-only */ +#endif /* ifndef YY_NO_INPUT */ +/* %endif */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ +/* %if-c-only */ + void yyrestart (FILE * input_file , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); + } + + yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner); + yy_load_buffer_state( yyscanner ); +} + +/* %if-c++-only */ +/* %endif */ + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ +/* %if-c-only */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (yyscanner); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( yyscanner ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/* %if-c-only */ +static void yy_load_buffer_state (yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; +/* %if-c-only */ + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; +/* %endif */ +/* %if-c++-only */ +/* %endif */ + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ +/* %if-c-only */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file , yyscanner); + + return b; +} + +/* %if-c++-only */ +/* %endif */ + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * @param yyscanner The scanner object. + */ +/* %if-c-only */ + void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree( (void *) b->yy_ch_buf , yyscanner ); + + yyfree( (void *) b , yyscanner ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ +/* %if-c-only */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ + +{ + int oerrno = errno; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_flush_buffer( b , yyscanner); + +/* %if-c-only */ + b->yy_input_file = file; +/* %endif */ +/* %if-c++-only */ +/* %endif */ + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + +/* %if-c-only */ + + b->yy_is_interactive = 0; + +/* %endif */ +/* %if-c++-only */ +/* %endif */ + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ +/* %if-c-only */ + void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( yyscanner ); +} + +/* %if-c-or-c++ */ +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +/* %if-c-only */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(yyscanner); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; +} +/* %endif */ + +/* %if-c-or-c++ */ +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +/* %if-c-only */ +void yypop_buffer_state (yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} +/* %endif */ + +/* %if-c-or-c++ */ +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +/* %if-c-only */ +static void yyensure_buffer_stack (yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + yy_size_t num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc + (yyg->yy_buffer_stack, + num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return NULL; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = NULL; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b , yyscanner ); + + return b; +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner) +{ + + return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner); +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = (yy_size_t) (_yybytes_len + 2); + buf = (char *) yyalloc( n , yyscanner ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n , yyscanner); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} +/* %endif */ + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +/* %if-c-only */ +static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} +/* %endif */ +/* %if-c++-only */ +/* %endif */ + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/* %if-c-only */ +/* %if-reentrant */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyextra; +} + +/* %endif */ + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int yyget_lineno (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int yyget_column (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_in (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_out (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +int yyget_leng (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *yyget_text (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yytext; +} + +/* %if-reentrant */ + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyextra = user_defined ; +} + +/* %endif */ + +/** Set the current line number. + * @param _line_number line number + * @param yyscanner The scanner object. + */ +void yyset_lineno (int _line_number , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + YY_FATAL_ERROR( "yyset_lineno called with no buffer" ); + + yylineno = _line_number; +} + +/** Set the current column. + * @param _column_no column number + * @param yyscanner The scanner object. + */ +void yyset_column (int _column_no , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + YY_FATAL_ERROR( "yyset_column called with no buffer" ); + + yycolumn = _column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * @param yyscanner The scanner object. + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * _in_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyin = _in_str ; +} + +void yyset_out (FILE * _out_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyout = _out_str ; +} + +int yyget_debug (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yy_flex_debug; +} + +void yyset_debug (int _bdebug , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yy_flex_debug = _bdebug ; +} + +/* %endif */ + +/* %if-reentrant */ +/* Accessor methods for yylval and yylloc */ + +/* %if-bison-bridge */ +/* %endif */ + +/* User-visible API */ + +/* yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ +int yylex_init(yyscan_t* ptr_yy_globals) +{ + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* yylex_init_extra has the same functionality as yylex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to yyalloc in + * the yyextra field. + */ +int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals ) +{ + struct yyguts_t dummy_yyguts; + + yyset_extra (yy_user_defined, &dummy_yyguts); + + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in + yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + yyset_extra (yy_user_defined, *ptr_yy_globals); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* %endif if-c-only */ + +/* %if-c-only */ +static int yy_init_globals (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + yyg->yy_buffer_stack = NULL; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = NULL; + yyg->yy_init = 0; + yyg->yy_start = 0; + + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = NULL; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = NULL; + yyout = NULL; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} +/* %endif */ + +/* %if-c-only SNIP! this currently causes conflicts with the c++ scanner */ +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + yyfree(yyg->yy_buffer_stack , yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + yyfree( yyg->yy_start_stack , yyscanner ); + yyg->yy_start_stack = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( yyscanner); + +/* %if-reentrant */ + /* Destroy the main struct (reentrant only). */ + yyfree ( yyscanner , yyscanner ); + yyscanner = NULL; +/* %endif */ + return 0; +} +/* %endif */ + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + + int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (const char * s , yyscan_t yyscanner) +{ + int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + return malloc(size); +} + +void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return realloc(ptr, size); +} + +void yyfree (void * ptr , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +/* %if-tables-serialization definitions */ +/* %define-yytables The name for this specific scanner's tables. */ +#define YYTABLES_NAME "yytables" +/* %endif */ + +/* %ok-for-header */ + +#line 241 "sqlite3_lexer.ll" + + +namespace sqlb +{ +namespace parser +{ + +void ParserDriver::begin_scan() +{ + yylex_init(&scanner); + location.initialize(); + yyset_debug(trace_scanner, scanner); + buffer = yy_scan_string(source.c_str(), scanner); +} + +void ParserDriver::end_scan() +{ + yy_delete_buffer(buffer, scanner); + yylex_destroy(scanner); +} + +} +} + diff --git a/src/sql/parser/sqlite3_lexer.h b/src/sql/parser/sqlite3_lexer.h new file mode 100644 index 000000000..2f26b4247 --- /dev/null +++ b/src/sql/parser/sqlite3_lexer.h @@ -0,0 +1,610 @@ +#ifndef yyHEADER_H +#define yyHEADER_H 1 +#define yyIN_HEADER 1 + +#line 6 "sqlite3_lexer.h" + +#line 8 "sqlite3_lexer.h" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +/* %not-for-header */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* %if-c++-only */ +/* %endif */ + +/* %if-c-only */ + +/* %endif */ + +/* %if-c-only */ + +/* %endif */ + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +/* %if-c-only */ +#include +#include +#include +#include +/* %endif */ + +/* %if-tables-serialization */ +/* %endif */ +/* end standard C headers. */ + +/* %if-c-or-c++ */ +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* %endif */ + +/* begin standard C++ headers. */ +/* %if-c++-only */ +/* %endif */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* %not-for-header */ + +/* %not-for-header */ + +/* %if-reentrant */ + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* %endif */ + +/* %if-not-reentrant */ +/* %endif */ + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +/* %if-not-reentrant */ +/* %endif */ + +/* %if-c-only */ +/* %if-not-reentrant */ +/* %endif */ +/* %endif */ + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { +/* %if-c-only */ + FILE *yy_input_file; +/* %endif */ + +/* %if-c++-only */ +/* %endif */ + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* %if-c-only Standard (non-C++) definition */ +/* %not-for-header */ + +/* %endif */ + +/* %if-c-only Standard (non-C++) definition */ + +/* %if-not-reentrant */ +/* %not-for-header */ + +/* %endif */ + +void yyrestart ( FILE *input_file , yyscan_t yyscanner ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); +void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +void yypop_buffer_state ( yyscan_t yyscanner ); + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner ); + +/* %endif */ + +void *yyalloc ( yy_size_t , yyscan_t yyscanner ); +void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); +void yyfree ( void * , yyscan_t yyscanner ); + +/* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */ +/* Begin user sect3 */ + +#define yywrap(yyscanner) (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP + +#define FLEX_DEBUG + +#define yytext_ptr yytext_r + +/* %if-c-only Standard (non-C++) definition */ + +/* %endif */ + +#ifdef YY_HEADER_EXPORT_START_CONDITIONS +#define INITIAL 0 +#define BETWEEN_MODE 1 + +#endif + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +/* %if-c-only */ +#include +/* %endif */ +/* %if-c++-only */ +/* %endif */ +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* %if-c-only Reentrant structure and macros (non-C++). */ +/* %if-reentrant */ + +/* %if-c-only */ + +/* %endif */ + +/* %if-reentrant */ + +int yylex_init (yyscan_t* scanner); + +int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); + +/* %endif */ + +/* %endif End reentrant structures and macros. */ + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( yyscan_t yyscanner ); + +int yyget_debug ( yyscan_t yyscanner ); + +void yyset_debug ( int debug_flag , yyscan_t yyscanner ); + +YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); + +FILE *yyget_in ( yyscan_t yyscanner ); + +void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); + +FILE *yyget_out ( yyscan_t yyscanner ); + +void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); + + int yyget_leng ( yyscan_t yyscanner ); + +char *yyget_text ( yyscan_t yyscanner ); + +int yyget_lineno ( yyscan_t yyscanner ); + +void yyset_lineno ( int _line_number , yyscan_t yyscanner ); + +int yyget_column ( yyscan_t yyscanner ); + +void yyset_column ( int _column_no , yyscan_t yyscanner ); + +/* %if-bison-bridge */ +/* %endif */ + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( yyscan_t yyscanner ); +#else +extern int yywrap ( yyscan_t yyscanner ); +#endif +#endif + +/* %not-for-header */ + +/* %endif */ + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * , yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT +/* %if-c-only Standard (non-C++) definition */ +/* %not-for-header */ + +/* %endif */ +#endif + +/* %if-c-only */ + +/* %endif */ + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* %if-tables-serialization structures and prototypes */ +/* %not-for-header */ + +/* %not-for-header */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 +/* %if-c-only Standard (non-C++) definition */ + +extern int yylex (yyscan_t yyscanner); + +#define YY_DECL int yylex (yyscan_t yyscanner) +/* %endif */ +/* %if-c++-only C++ definition */ +/* %endif */ +#endif /* !YY_DECL */ + +/* %not-for-header */ + +/* %if-c++-only */ +/* %not-for-header */ + +/* %endif */ + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +/* %if-c-only */ +/* %not-for-header */ + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif + +#ifndef yy_create_buffer_ALREADY_DEFINED +#undef yy_create_buffer +#endif +#ifndef yy_delete_buffer_ALREADY_DEFINED +#undef yy_delete_buffer +#endif +#ifndef yy_scan_buffer_ALREADY_DEFINED +#undef yy_scan_buffer +#endif +#ifndef yy_scan_string_ALREADY_DEFINED +#undef yy_scan_string +#endif +#ifndef yy_scan_bytes_ALREADY_DEFINED +#undef yy_scan_bytes +#endif +#ifndef yy_init_buffer_ALREADY_DEFINED +#undef yy_init_buffer +#endif +#ifndef yy_flush_buffer_ALREADY_DEFINED +#undef yy_flush_buffer +#endif +#ifndef yy_load_buffer_state_ALREADY_DEFINED +#undef yy_load_buffer_state +#endif +#ifndef yy_switch_to_buffer_ALREADY_DEFINED +#undef yy_switch_to_buffer +#endif +#ifndef yypush_buffer_state_ALREADY_DEFINED +#undef yypush_buffer_state +#endif +#ifndef yypop_buffer_state_ALREADY_DEFINED +#undef yypop_buffer_state +#endif +#ifndef yyensure_buffer_stack_ALREADY_DEFINED +#undef yyensure_buffer_stack +#endif +#ifndef yylex_ALREADY_DEFINED +#undef yylex +#endif +#ifndef yyrestart_ALREADY_DEFINED +#undef yyrestart +#endif +#ifndef yylex_init_ALREADY_DEFINED +#undef yylex_init +#endif +#ifndef yylex_init_extra_ALREADY_DEFINED +#undef yylex_init_extra +#endif +#ifndef yylex_destroy_ALREADY_DEFINED +#undef yylex_destroy +#endif +#ifndef yyget_debug_ALREADY_DEFINED +#undef yyget_debug +#endif +#ifndef yyset_debug_ALREADY_DEFINED +#undef yyset_debug +#endif +#ifndef yyget_extra_ALREADY_DEFINED +#undef yyget_extra +#endif +#ifndef yyset_extra_ALREADY_DEFINED +#undef yyset_extra +#endif +#ifndef yyget_in_ALREADY_DEFINED +#undef yyget_in +#endif +#ifndef yyset_in_ALREADY_DEFINED +#undef yyset_in +#endif +#ifndef yyget_out_ALREADY_DEFINED +#undef yyget_out +#endif +#ifndef yyset_out_ALREADY_DEFINED +#undef yyset_out +#endif +#ifndef yyget_leng_ALREADY_DEFINED +#undef yyget_leng +#endif +#ifndef yyget_text_ALREADY_DEFINED +#undef yyget_text +#endif +#ifndef yyget_lineno_ALREADY_DEFINED +#undef yyget_lineno +#endif +#ifndef yyset_lineno_ALREADY_DEFINED +#undef yyset_lineno +#endif +#ifndef yyget_column_ALREADY_DEFINED +#undef yyget_column +#endif +#ifndef yyset_column_ALREADY_DEFINED +#undef yyset_column +#endif +#ifndef yywrap_ALREADY_DEFINED +#undef yywrap +#endif +#ifndef yyget_lval_ALREADY_DEFINED +#undef yyget_lval +#endif +#ifndef yyset_lval_ALREADY_DEFINED +#undef yyset_lval +#endif +#ifndef yyget_lloc_ALREADY_DEFINED +#undef yyget_lloc +#endif +#ifndef yyset_lloc_ALREADY_DEFINED +#undef yyset_lloc +#endif +#ifndef yyalloc_ALREADY_DEFINED +#undef yyalloc +#endif +#ifndef yyrealloc_ALREADY_DEFINED +#undef yyrealloc +#endif +#ifndef yyfree_ALREADY_DEFINED +#undef yyfree +#endif +#ifndef yytext_ALREADY_DEFINED +#undef yytext +#endif +#ifndef yyleng_ALREADY_DEFINED +#undef yyleng +#endif +#ifndef yyin_ALREADY_DEFINED +#undef yyin +#endif +#ifndef yyout_ALREADY_DEFINED +#undef yyout +#endif +#ifndef yy_flex_debug_ALREADY_DEFINED +#undef yy_flex_debug +#endif +#ifndef yylineno_ALREADY_DEFINED +#undef yylineno +#endif +#ifndef yytables_fload_ALREADY_DEFINED +#undef yytables_fload +#endif +#ifndef yytables_destroy_ALREADY_DEFINED +#undef yytables_destroy +#endif +#ifndef yyTABLES_NAME_ALREADY_DEFINED +#undef yyTABLES_NAME +#endif + +#line 241 "sqlite3_lexer.ll" + + +#line 609 "sqlite3_lexer.h" +#undef yyIN_HEADER +#endif /* yyHEADER_H */ diff --git a/src/sql/parser/sqlite3_lexer.ll b/src/sql/parser/sqlite3_lexer.ll new file mode 100644 index 000000000..39d6ce003 --- /dev/null +++ b/src/sql/parser/sqlite3_lexer.ll @@ -0,0 +1,262 @@ +%{ +#include +#include "ParserDriver.h" +#include "sqlite3_parser.hpp" +%} + +%option noyywrap nounput batch debug case-insensitive 8bit never-interactive nodefault nounistd reentrant warn +%option header-file="sqlite3_lexer.h" +%option outfile="sqlite3_lexer.cpp" + +%{ + #define TOKEN(n) sqlb::parser::parser::symbol_type(sqlb::parser::parser::token::TOK_##n, yytext, loc) + + std::string unquote_string(std::string s, char quote_char) + { + if(s.size() < 2) + return s; + + if(quote_char == '[') + { + if(s.front() == '[' && s.back() == ']') + s = s.substr(1, s.size()-2); + } else { + if(s.front() == quote_char && s.back() == quote_char) + { + s = s.substr(1, s.size()-2); + auto pos = s.npos; + while((pos = s.find(std::string(2, quote_char))) != s.npos) + s = s.replace(pos, 2, std::string(1, quote_char)); + } + } + + return s; + } +%} + +U [\x80-\xbf] +U2 [\xc2-\xdf] +U3 [\xe0-\xef] +U4 [\xf0-\xf4] +UNICODE {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U} + +ID ([a-z_]|{UNICODE})([a-z0-9_$]|{UNICODE})* + +GRAVEQUOTEDID `([^\n`]|(``))*` +SQUAREBRACKETID \[([^\n\]])*\] + +QUOTEDLITERAL \"([^\n\"]|(\"\"))*\" +STRINGLITERAL \'([^\n\']|(\'\'))*\' +BLOBLITERAL X\'[0-9a-f]*\' + +BINDPARAMETER_NUM \?([1-9]{DIGIT}*)? +BINDPARAMETER_STR [:@][a-z]+ + /* TODO Add $ bind parameters */ + +DIGIT [0-9] +NUMERIC (({DIGIT}+(\.{DIGIT}*)?|(\.{DIGIT}+))(e[\+\-]?{DIGIT}+)?)|(0x[0-9a-f]+) + +NL [\r\n] +WS [ \t\f] + +%{ + // Code run each time a pattern is matched. + #define YY_USER_ACTION loc.columns(yyleng); +%} + +%s BETWEEN_MODE + +%% + +%{ + // Shortcut to the location held by the driver + sqlb::parser::location& loc = drv.location; + + // Code run each time yylex is called. + loc.step(); +%} + +{WS}+ loc.step(); +{NL}+ loc.lines(yyleng); loc.step(); + +"--" { + int c; + while((c = yyinput(yyscanner)) != '\n' && c != EOF) + ; /* eat up text of comment */ + } + +"/*" { + int c; + + for(;;) + { + while((c = yyinput(yyscanner)) != '*' && c != EOF) + ; /* eat up text of comment */ + + if(c == '*') + { + while((c = yyinput(yyscanner)) == '*') + ; + if(c == '/') + break; /* found the end */ + } + + if(c == EOF) + throw sqlb::parser::parser::syntax_error(loc, "EOF in comment"); + } + } + + /* For lack of a better idea, we need this hack to avoid reduce/reduce conflicts in the rules for parsing BETWEEN expressions. + * What we do here is distinguish two types of AND operators: the regular one and the special case when the AND follows a BETWEEN keyword. + */ +"AND" { BEGIN INITIAL; return TOKEN(AND_BETWEEN); } +"AND" return TOKEN(AND); +"BETWEEN" { BEGIN BETWEEN_MODE; return TOKEN(BETWEEN); } + +"ABORT" return TOKEN(ABORT); +"ACTION" return TOKEN(ACTION); +"ALWAYS" return TOKEN(ALWAYS); +"AS" return TOKEN(AS); +"ASC" return TOKEN(ASC); +"AUTOINCREMENT" return TOKEN(AUTOINCREMENT); +"CASCADE" return TOKEN(CASCADE); +"CASE" return TOKEN(CASE); +"CAST" return TOKEN(CAST); +"CHECK" return TOKEN(CHECK); +"COLLATE" return TOKEN(COLLATE); +"CONFLICT" return TOKEN(CONFLICT); +"CONSTRAINT" return TOKEN(CONSTRAINT); +"CREATE" return TOKEN(CREATE); +"CURRENT_DATE" return TOKEN(CURRENT_DATE); +"CURRENT_TIME" return TOKEN(CURRENT_TIME); +"CURRENT_TIMESTAMP" return TOKEN(CURRENT_TIMESTAMP); +"DEFAULT" return TOKEN(DEFAULT); +"DEFERRABLE" return TOKEN(DEFERRABLE); +"DEFERRED" return TOKEN(DEFERRED); +"DELETE" return TOKEN(DELETE); +"DESC" return TOKEN(DESC); +"DISTINCT" return TOKEN(DISTINCT); +"ELSE" return TOKEN(ELSE); +"END" return TOKEN(END); +"ESCAPE" return TOKEN(ESCAPE); +"EXISTS" return TOKEN(EXISTS); +"FAIL" return TOKEN(FAIL); +"FALSE" return TOKEN(FALSE); +"FILTER" return TOKEN(FILTER); +"FOLLOWING" return TOKEN(FOLLOWING); +"FOREIGN" return TOKEN(FOREIGN); +"FROM" return TOKEN(FROM); +"GENERATED" return TOKEN(GENERATED); +"GLOB" return TOKEN(GLOB); +"IF" return TOKEN(IF); +"IGNORE" return TOKEN(IGNORE); +"IMMEDIATE" return TOKEN(IMMEDIATE); +"IN" return TOKEN(IN); +"INDEX" return TOKEN(INDEX); +"INITIALLY" return TOKEN(INITIALLY); +"INSERT" return TOKEN(INSERT); +"IS" return TOKEN(IS); +"ISNULL" return TOKEN(ISNULL); +"KEY" return TOKEN(KEY); +"LIKE" return TOKEN(LIKE); +"MATCH" return TOKEN(MATCH); +"NO" return TOKEN(NO); +"NOT" return TOKEN(NOT); +"NOTNULL" return TOKEN(NOTNULL); +"NULL" return TOKEN(NULL); +"ON" return TOKEN(ON); +"OR" return TOKEN(OR); +"OVER" return TOKEN(OVER); +"PARTITION" return TOKEN(PARTITION); +"PRECEDING" return TOKEN(PRECEDING); +"PRIMARY" return TOKEN(PRIMARY); +"RAISE" return TOKEN(RAISE); +"RANGE" return TOKEN(RANGE); +"REFERENCES" return TOKEN(REFERENCES); +"REGEXP" return TOKEN(REGEXP); +"REPLACE" return TOKEN(REPLACE); +"RESTRICT" return TOKEN(RESTRICT); +"RETURNING" return TOKEN(RETURNING); +"ROLLBACK" return TOKEN(ROLLBACK); +"ROWID" return TOKEN(ROWID); +"ROWS" return TOKEN(ROWS); +"SELECT" return TOKEN(SELECT); +"SET" return TOKEN(SET); +"STORED" return TOKEN(STORED); +"STRICT" return TOKEN(STRICT); +"TABLE" return TOKEN(TABLE); +"TEMP" return TOKEN(TEMP); +"TEMPORARY" return TOKEN(TEMPORARY); +"THEN" return TOKEN(THEN); +"TRUE" return TOKEN(TRUE); +"UNBOUNDED" return TOKEN(UNBOUNDED); +"UNIQUE" return TOKEN(UNIQUE); +"UPDATE" return TOKEN(UPDATE); +"USING" return TOKEN(USING); +"VIRTUAL" return TOKEN(VIRTUAL); +"WHEN" return TOKEN(WHEN); +"WHERE" return TOKEN(WHERE); +"WITHOUT" return TOKEN(WITHOUT); + +{ID} return sqlb::parser::parser::make_IDENTIFIER(yytext, loc); +{GRAVEQUOTEDID} return sqlb::parser::parser::make_IDENTIFIER(unquote_string(yytext, '`'), loc); +{SQUAREBRACKETID} return sqlb::parser::parser::make_IDENTIFIER(unquote_string(yytext, '['), loc); +{QUOTEDLITERAL} return sqlb::parser::parser::make_QUOTEDLITERAL(unquote_string(yytext, '"'), loc); +{STRINGLITERAL} return sqlb::parser::parser::make_STRINGLITERAL(yytext, loc); +{NUMERIC} return sqlb::parser::parser::make_NUMERIC(yytext, loc); +{BLOBLITERAL} return sqlb::parser::parser::make_BLOBLITERAL(yytext, loc); +{BINDPARAMETER_NUM} return sqlb::parser::parser::make_BINDPARAMETER(yytext, loc); +{BINDPARAMETER_STR} return sqlb::parser::parser::make_BINDPARAMETER(yytext, loc); + +"(" return sqlb::parser::parser::make_LPAREN(loc); +")" return sqlb::parser::parser::make_RPAREN(loc); +"." return sqlb::parser::parser::make_DOT(loc); +"," return sqlb::parser::parser::make_COMMA(loc); +";" return sqlb::parser::parser::make_SEMI(loc); +"+" return sqlb::parser::parser::make_PLUS(loc); +"-" return sqlb::parser::parser::make_MINUS(loc); +"*" return sqlb::parser::parser::make_STAR(loc); +"/" return sqlb::parser::parser::make_SLASH(loc); +"~" return sqlb::parser::parser::make_TILDE(loc); +"&" return sqlb::parser::parser::make_AMPERSAND(loc); +"%" return sqlb::parser::parser::make_PERCENT(loc); +"|" return sqlb::parser::parser::make_BITOR(loc); +"||" return sqlb::parser::parser::make_OROP(loc); +"=" return sqlb::parser::parser::make_EQUAL(loc); +"==" return sqlb::parser::parser::make_EQUAL2(loc); +">" return sqlb::parser::parser::make_GREATER(loc); +">=" return sqlb::parser::parser::make_GREATEREQUAL(loc); +"<" return sqlb::parser::parser::make_LOWER(loc); +"<=" return sqlb::parser::parser::make_LOWEREQUAL(loc); +"!=" return sqlb::parser::parser::make_UNEQUAL(loc); +"<>" return sqlb::parser::parser::make_UNEQUAL2(loc); +"<<" return sqlb::parser::parser::make_BITWISELEFT(loc); +">>" return sqlb::parser::parser::make_BITWISERIGHT(loc); + +. throw sqlb::parser::parser::syntax_error(loc, "Invalid character: " + std::string(yytext)); + +<> return sqlb::parser::parser::make_EOF(loc); + +%% + +namespace sqlb +{ +namespace parser +{ + +void ParserDriver::begin_scan() +{ + yylex_init(&scanner); + location.initialize(); + yyset_debug(trace_scanner, scanner); + buffer = yy_scan_string(source.c_str(), scanner); +} + +void ParserDriver::end_scan() +{ + yy_delete_buffer(buffer, scanner); + yylex_destroy(scanner); +} + +} +} diff --git a/src/sql/parser/sqlite3_location.h b/src/sql/parser/sqlite3_location.h new file mode 100644 index 000000000..0b6b1c35a --- /dev/null +++ b/src/sql/parser/sqlite3_location.h @@ -0,0 +1,306 @@ +// A Bison parser, made by GNU Bison 3.8.2. + +// Locations for Bison parsers in C++ + +// Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// As a special exception, you may create a larger work that contains +// part or all of the Bison parser skeleton and distribute that work +// under terms of your choice, so long as that work isn't itself a +// parser generator using the skeleton or a modified version thereof +// as a parser skeleton. Alternatively, if you modify or redistribute +// the parser skeleton itself, you may (at your option) remove this +// special exception, which will cause the skeleton and the resulting +// Bison output files to be licensed under the GNU General Public +// License without this special exception. + +// This special exception was added by the Free Software Foundation in +// version 2.2 of Bison. + +/** + ** \file sqlite3_location.h + ** Define the sqlb::parser ::location class. + */ + +#ifndef YY_YY_SQLITE3_LOCATION_H_INCLUDED +# define YY_YY_SQLITE3_LOCATION_H_INCLUDED + +# include +# include + +# ifndef YY_NULLPTR +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# else +# define YY_NULLPTR ((void*)0) +# endif +# endif + +#line 10 "sqlite3_parser.yy" +namespace sqlb { namespace parser { +#line 59 "sqlite3_location.h" + + /// A point in a source file. + class position + { + public: + /// Type for file name. + typedef const std::string filename_type; + /// Type for line and column numbers. + typedef int counter_type; + + /// Construct a position. + explicit position (filename_type* f = YY_NULLPTR, + counter_type l = 1, + counter_type c = 1) + : filename (f) + , line (l) + , column (c) + {} + + + /// Initialization. + void initialize (filename_type* fn = YY_NULLPTR, + counter_type l = 1, + counter_type c = 1) + { + filename = fn; + line = l; + column = c; + } + + /** \name Line and Column related manipulators + ** \{ */ + /// (line related) Advance to the COUNT next lines. + void lines (counter_type count = 1) + { + if (count) + { + column = 1; + line = add_ (line, count, 1); + } + } + + /// (column related) Advance to the COUNT next columns. + void columns (counter_type count = 1) + { + column = add_ (column, count, 1); + } + /** \} */ + + /// File name to which this position refers. + filename_type* filename; + /// Current line number. + counter_type line; + /// Current column number. + counter_type column; + + private: + /// Compute max (min, lhs+rhs). + static counter_type add_ (counter_type lhs, counter_type rhs, counter_type min) + { + return lhs + rhs < min ? min : lhs + rhs; + } + }; + + /// Add \a width columns, in place. + inline position& + operator+= (position& res, position::counter_type width) + { + res.columns (width); + return res; + } + + /// Add \a width columns. + inline position + operator+ (position res, position::counter_type width) + { + return res += width; + } + + /// Subtract \a width columns, in place. + inline position& + operator-= (position& res, position::counter_type width) + { + return res += -width; + } + + /// Subtract \a width columns. + inline position + operator- (position res, position::counter_type width) + { + return res -= width; + } + + /** \brief Intercept output stream redirection. + ** \param ostr the destination output stream + ** \param pos a reference to the position to redirect + */ + template + std::basic_ostream& + operator<< (std::basic_ostream& ostr, const position& pos) + { + if (pos.filename) + ostr << *pos.filename << ':'; + return ostr << pos.line << '.' << pos.column; + } + + /// Two points in a source file. + class location + { + public: + /// Type for file name. + typedef position::filename_type filename_type; + /// Type for line and column numbers. + typedef position::counter_type counter_type; + + /// Construct a location from \a b to \a e. + location (const position& b, const position& e) + : begin (b) + , end (e) + {} + + /// Construct a 0-width location in \a p. + explicit location (const position& p = position ()) + : begin (p) + , end (p) + {} + + /// Construct a 0-width location in \a f, \a l, \a c. + explicit location (filename_type* f, + counter_type l = 1, + counter_type c = 1) + : begin (f, l, c) + , end (f, l, c) + {} + + + /// Initialization. + void initialize (filename_type* f = YY_NULLPTR, + counter_type l = 1, + counter_type c = 1) + { + begin.initialize (f, l, c); + end = begin; + } + + /** \name Line and Column related manipulators + ** \{ */ + public: + /// Reset initial location to final location. + void step () + { + begin = end; + } + + /// Extend the current location to the COUNT next columns. + void columns (counter_type count = 1) + { + end += count; + } + + /// Extend the current location to the COUNT next lines. + void lines (counter_type count = 1) + { + end.lines (count); + } + /** \} */ + + + public: + /// Beginning of the located region. + position begin; + /// End of the located region. + position end; + }; + + /// Join two locations, in place. + inline location& + operator+= (location& res, const location& end) + { + res.end = end.end; + return res; + } + + /// Join two locations. + inline location + operator+ (location res, const location& end) + { + return res += end; + } + + /// Add \a width columns to the end position, in place. + inline location& + operator+= (location& res, location::counter_type width) + { + res.columns (width); + return res; + } + + /// Add \a width columns to the end position. + inline location + operator+ (location res, location::counter_type width) + { + return res += width; + } + + /// Subtract \a width columns to the end position, in place. + inline location& + operator-= (location& res, location::counter_type width) + { + return res += -width; + } + + /// Subtract \a width columns to the end position. + inline location + operator- (location res, location::counter_type width) + { + return res -= width; + } + + /** \brief Intercept output stream redirection. + ** \param ostr the destination output stream + ** \param loc a reference to the location to redirect + ** + ** Avoid duplicate information. + */ + template + std::basic_ostream& + operator<< (std::basic_ostream& ostr, const location& loc) + { + location::counter_type end_col + = 0 < loc.end.column ? loc.end.column - 1 : 0; + ostr << loc.begin; + if (loc.end.filename + && (!loc.begin.filename + || *loc.begin.filename != *loc.end.filename)) + ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col; + else if (loc.begin.line < loc.end.line) + ostr << '-' << loc.end.line << '.' << end_col; + else if (loc.begin.column < end_col) + ostr << '-' << end_col; + return ostr; + } + +#line 10 "sqlite3_parser.yy" +} } // sqlb::parser +#line 305 "sqlite3_location.h" + +#endif // !YY_YY_SQLITE3_LOCATION_H_INCLUDED diff --git a/src/sql/parser/sqlite3_parser.cpp b/src/sql/parser/sqlite3_parser.cpp new file mode 100644 index 000000000..afa7c6502 --- /dev/null +++ b/src/sql/parser/sqlite3_parser.cpp @@ -0,0 +1,4875 @@ +// A Bison parser, made by GNU Bison 3.8.2. + +// Skeleton implementation for Bison LALR(1) parsers in C++ + +// Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// As a special exception, you may create a larger work that contains +// part or all of the Bison parser skeleton and distribute that work +// under terms of your choice, so long as that work isn't itself a +// parser generator using the skeleton or a modified version thereof +// as a parser skeleton. Alternatively, if you modify or redistribute +// the parser skeleton itself, you may (at your option) remove this +// special exception, which will cause the skeleton and the resulting +// Bison output files to be licensed under the GNU General Public +// License without this special exception. + +// This special exception was added by the Free Software Foundation in +// version 2.2 of Bison. + +// DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, +// especially those whose name start with YY_ or yy_. They are +// private implementation details that can be changed or removed. + + + + + +#include "sqlite3_parser.hpp" + + +// Unqualified %code blocks. +#line 39 "sqlite3_parser.yy" + + #include "ParserDriver.h" + + static std::string unquote_text(std::string str, char quote_char) + { + if(quote_char != '[') + { + if(str.front() != quote_char || str.back() != quote_char) + return str; + + str = str.substr(1, str.size()-2); + + std::string quote(2, quote_char); + + size_t pos = 0; + while((pos = str.find(quote, pos)) != std::string::npos) + { + str.erase(pos, 1); + pos += 1; // Don't remove the other quote char too + } + return str; + } else { + if(str.front() != '[' || str.back() != ']') + return str; + + return str.substr(1, str.size()-2); + } + } + +#line 76 "sqlite3_parser.cpp" + + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include // FIXME: INFRINGES ON USER NAME SPACE. +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + + +// Whether we are compiled with exception support. +#ifndef YY_EXCEPTIONS +# if defined __GNUC__ && !defined __EXCEPTIONS +# define YY_EXCEPTIONS 0 +# else +# define YY_EXCEPTIONS 1 +# endif +#endif + +#define YYRHSLOC(Rhs, K) ((Rhs)[K].location) +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +# ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) \ + { \ + (Current).begin = YYRHSLOC (Rhs, 1).begin; \ + (Current).end = YYRHSLOC (Rhs, N).end; \ + } \ + else \ + { \ + (Current).begin = (Current).end = YYRHSLOC (Rhs, 0).end; \ + } \ + while (false) +# endif + + +// Enable debugging if requested. +#if YYDEBUG + +// A pseudo ostream that takes yydebug_ into account. +# define YYCDEBUG if (yydebug_) (*yycdebug_) + +# define YY_SYMBOL_PRINT(Title, Symbol) \ + do { \ + if (yydebug_) \ + { \ + *yycdebug_ << Title << ' '; \ + yy_print_ (*yycdebug_, Symbol); \ + *yycdebug_ << '\n'; \ + } \ + } while (false) + +# define YY_REDUCE_PRINT(Rule) \ + do { \ + if (yydebug_) \ + yy_reduce_print_ (Rule); \ + } while (false) + +# define YY_STACK_PRINT() \ + do { \ + if (yydebug_) \ + yy_stack_print_ (); \ + } while (false) + +#else // !YYDEBUG + +# define YYCDEBUG if (false) std::cerr +# define YY_SYMBOL_PRINT(Title, Symbol) YY_USE (Symbol) +# define YY_REDUCE_PRINT(Rule) static_cast (0) +# define YY_STACK_PRINT() static_cast (0) + +#endif // !YYDEBUG + +#define yyerrok (yyerrstatus_ = 0) +#define yyclearin (yyla.clear ()) + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab +#define YYRECOVERING() (!!yyerrstatus_) + +#line 10 "sqlite3_parser.yy" +namespace sqlb { namespace parser { +#line 169 "sqlite3_parser.cpp" + + /// Build a parser object. + parser::parser (yyscan_t yyscanner_yyarg, ParserDriver& drv_yyarg) +#if YYDEBUG + : yydebug_ (false), + yycdebug_ (&std::cerr), +#else + : +#endif + yyscanner (yyscanner_yyarg), + drv (drv_yyarg) + {} + + parser::~parser () + {} + + parser::syntax_error::~syntax_error () YY_NOEXCEPT YY_NOTHROW + {} + + /*---------. + | symbol. | + `---------*/ + + + + // by_state. + parser::by_state::by_state () YY_NOEXCEPT + : state (empty_state) + {} + + parser::by_state::by_state (const by_state& that) YY_NOEXCEPT + : state (that.state) + {} + + void + parser::by_state::clear () YY_NOEXCEPT + { + state = empty_state; + } + + void + parser::by_state::move (by_state& that) + { + state = that.state; + that.clear (); + } + + parser::by_state::by_state (state_type s) YY_NOEXCEPT + : state (s) + {} + + parser::symbol_kind_type + parser::by_state::kind () const YY_NOEXCEPT + { + if (state == empty_state) + return symbol_kind::S_YYEMPTY; + else + return YY_CAST (symbol_kind_type, yystos_[+state]); + } + + parser::stack_symbol_type::stack_symbol_type () + {} + + parser::stack_symbol_type::stack_symbol_type (YY_RVREF (stack_symbol_type) that) + : super_type (YY_MOVE (that.state), YY_MOVE (that.location)) + { + switch (that.kind ()) + { + case symbol_kind::S_columndef_list: // columndef_list + value.YY_MOVE_OR_COPY< ColumnList > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_columnconstraint_list: // columnconstraint_list + case symbol_kind::S_tableconstraint: // tableconstraint + case symbol_kind::S_tableconstraint_list: // tableconstraint_list + case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list + value.YY_MOVE_OR_COPY< TableConstraints > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_optional_if_not_exists: // optional_if_not_exists + case symbol_kind::S_optional_unique: // optional_unique + case symbol_kind::S_optional_temporary: // optional_temporary + case symbol_kind::S_optional_always_generated: // optional_always_generated + value.YY_MOVE_OR_COPY< bool > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_createindex_stmt: // createindex_stmt + value.YY_MOVE_OR_COPY< sqlb::IndexPtr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_indexed_column: // indexed_column + value.YY_MOVE_OR_COPY< sqlb::IndexedColumn > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_indexed_column_list: // indexed_column_list + value.YY_MOVE_OR_COPY< sqlb::IndexedColumnVector > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_columnid_list: // columnid_list + case symbol_kind::S_optional_columnid_with_paren_list: // optional_columnid_with_paren_list + value.YY_MOVE_OR_COPY< sqlb::StringVector > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_createvirtualtable_stmt: // createvirtualtable_stmt + case symbol_kind::S_createtable_stmt: // createtable_stmt + value.YY_MOVE_OR_COPY< sqlb::TablePtr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_tableoption: // tableoption + case symbol_kind::S_tableoptions_list: // tableoptions_list + case symbol_kind::S_optional_tableoptions_list: // optional_tableoptions_list + value.YY_MOVE_OR_COPY< std::bitset > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_columnconstraint: // columnconstraint + value.YY_MOVE_OR_COPY< std::pair, std::shared_ptr> > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_columndef: // columndef + value.YY_MOVE_OR_COPY< std::shared_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_ABORT: // "ABORT" + case symbol_kind::S_ACTION: // "ACTION" + case symbol_kind::S_ALWAYS: // "ALWAYS" + case symbol_kind::S_AND: // "AND" + case symbol_kind::S_AND_BETWEEN: // "AND BETWEEN" + case symbol_kind::S_AS: // "AS" + case symbol_kind::S_ASC: // "ASC" + case symbol_kind::S_AUTOINCREMENT: // "AUTOINCREMENT" + case symbol_kind::S_BETWEEN: // "BETWEEN" + case symbol_kind::S_CASCADE: // "CASCADE" + case symbol_kind::S_CASE: // "CASE" + case symbol_kind::S_CAST: // "CAST" + case symbol_kind::S_CHECK: // "CHECK" + case symbol_kind::S_COLLATE: // "COLLATE" + case symbol_kind::S_CONFLICT: // "CONFLICT" + case symbol_kind::S_CONSTRAINT: // "CONSTRAINT" + case symbol_kind::S_CREATE: // "CREATE" + case symbol_kind::S_CURRENT_DATE: // "CURRENT_DATE" + case symbol_kind::S_CURRENT_TIME: // "CURRENT_TIME" + case symbol_kind::S_CURRENT_TIMESTAMP: // "CURRENT_TIMESTAMP" + case symbol_kind::S_DEFAULT: // "DEFAULT" + case symbol_kind::S_DEFERRABLE: // "DEFERRABLE" + case symbol_kind::S_DEFERRED: // "DEFERRED" + case symbol_kind::S_DELETE: // "DELETE" + case symbol_kind::S_DESC: // "DESC" + case symbol_kind::S_DISTINCT: // "DISTINCT" + case symbol_kind::S_ELSE: // "ELSE" + case symbol_kind::S_END: // "END" + case symbol_kind::S_ESCAPE: // "ESCAPE" + case symbol_kind::S_EXISTS: // "EXISTS" + case symbol_kind::S_FAIL: // "FAIL" + case symbol_kind::S_FALSE: // "FALSE" + case symbol_kind::S_FILTER: // "FILTER" + case symbol_kind::S_FOLLOWING: // "FOLLOWING" + case symbol_kind::S_FOREIGN: // "FOREIGN" + case symbol_kind::S_FROM: // "FROM" + case symbol_kind::S_GENERATED: // "GENERATED" + case symbol_kind::S_GLOB: // "GLOB" + case symbol_kind::S_IF: // "IF" + case symbol_kind::S_IGNORE: // "IGNORE" + case symbol_kind::S_IMMEDIATE: // "IMMEDIATE" + case symbol_kind::S_IN: // "IN" + case symbol_kind::S_INDEX: // "INDEX" + case symbol_kind::S_INITIALLY: // "INITIALLY" + case symbol_kind::S_INSERT: // "INSERT" + case symbol_kind::S_IS: // "IS" + case symbol_kind::S_ISNULL: // "ISNULL" + case symbol_kind::S_KEY: // "KEY" + case symbol_kind::S_LIKE: // "LIKE" + case symbol_kind::S_MATCH: // "MATCH" + case symbol_kind::S_NO: // "NO" + case symbol_kind::S_NOT: // "NOT" + case symbol_kind::S_NOTNULL: // "NOTNULL" + case symbol_kind::S_NULL: // "NULL" + case symbol_kind::S_ON: // "ON" + case symbol_kind::S_OR: // "OR" + case symbol_kind::S_OVER: // "OVER" + case symbol_kind::S_PARTITION: // "PARTITION" + case symbol_kind::S_PRECEDING: // "PRECEDING" + case symbol_kind::S_PRIMARY: // "PRIMARY" + case symbol_kind::S_RAISE: // "RAISE" + case symbol_kind::S_RANGE: // "RANGE" + case symbol_kind::S_REFERENCES: // "REFERENCES" + case symbol_kind::S_REGEXP: // "REGEXP" + case symbol_kind::S_REPLACE: // "REPLACE" + case symbol_kind::S_RESTRICT: // "RESTRICT" + case symbol_kind::S_RETURNING: // "RETURNING" + case symbol_kind::S_ROLLBACK: // "ROLLBACK" + case symbol_kind::S_ROWID: // "ROWID" + case symbol_kind::S_ROWS: // "ROWS" + case symbol_kind::S_SELECT: // "SELECT" + case symbol_kind::S_SET: // "SET" + case symbol_kind::S_STORED: // "STORED" + case symbol_kind::S_STRICT: // "STRICT" + case symbol_kind::S_TABLE: // "TABLE" + case symbol_kind::S_TEMP: // "TEMP" + case symbol_kind::S_TEMPORARY: // "TEMPORARY" + case symbol_kind::S_THEN: // "THEN" + case symbol_kind::S_TRUE: // "TRUE" + case symbol_kind::S_UNBOUNDED: // "UNBOUNDED" + case symbol_kind::S_UNIQUE: // "UNIQUE" + case symbol_kind::S_UPDATE: // "UPDATE" + case symbol_kind::S_USING: // "USING" + case symbol_kind::S_VIRTUAL: // "VIRTUAL" + case symbol_kind::S_WHEN: // "WHEN" + case symbol_kind::S_WHERE: // "WHERE" + case symbol_kind::S_WITHOUT: // "WITHOUT" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_NUMERIC: // "numeric" + case symbol_kind::S_STRINGLITERAL: // "string literal" + case symbol_kind::S_QUOTEDLITERAL: // "quoted literal" + case symbol_kind::S_BLOBLITERAL: // "blob literal" + case symbol_kind::S_BINDPARAMETER: // "bind parameter" + case symbol_kind::S_literalvalue: // literalvalue + case symbol_kind::S_id: // id + case symbol_kind::S_allowed_keywords_as_identifier: // allowed_keywords_as_identifier + case symbol_kind::S_tableid: // tableid + case symbol_kind::S_columnid: // columnid + case symbol_kind::S_signednumber: // signednumber + case symbol_kind::S_signednumber_or_numeric: // signednumber_or_numeric + case symbol_kind::S_typename_namelist: // typename_namelist + case symbol_kind::S_type_name: // type_name + case symbol_kind::S_unary_expr: // unary_expr + case symbol_kind::S_binary_expr: // binary_expr + case symbol_kind::S_like_expr: // like_expr + case symbol_kind::S_exprlist_expr: // exprlist_expr + case symbol_kind::S_function_expr: // function_expr + case symbol_kind::S_isnull_expr: // isnull_expr + case symbol_kind::S_between_expr: // between_expr + case symbol_kind::S_in_expr: // in_expr + case symbol_kind::S_whenthenlist_expr: // whenthenlist_expr + case symbol_kind::S_case_expr: // case_expr + case symbol_kind::S_raise_expr: // raise_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_select_stmt: // select_stmt + case symbol_kind::S_optional_sort_order: // optional_sort_order + case symbol_kind::S_optional_where: // optional_where + case symbol_kind::S_tableid_with_uninteresting_schema: // tableid_with_uninteresting_schema + case symbol_kind::S_optional_exprlist_with_paren: // optional_exprlist_with_paren + case symbol_kind::S_optional_conflictclause: // optional_conflictclause + case symbol_kind::S_optional_typename: // optional_typename + case symbol_kind::S_optional_storage_identifier: // optional_storage_identifier + case symbol_kind::S_optional_constraintname: // optional_constraintname + case symbol_kind::S_fk_clause_part: // fk_clause_part + case symbol_kind::S_fk_clause_part_list: // fk_clause_part_list + case symbol_kind::S_optional_fk_clause: // optional_fk_clause + value.YY_MOVE_OR_COPY< std::string > (YY_MOVE (that.value)); + break; + + default: + break; + } + +#if 201103L <= YY_CPLUSPLUS + // that is emptied. + that.state = empty_state; +#endif + } + + parser::stack_symbol_type::stack_symbol_type (state_type s, YY_MOVE_REF (symbol_type) that) + : super_type (s, YY_MOVE (that.location)) + { + switch (that.kind ()) + { + case symbol_kind::S_columndef_list: // columndef_list + value.move< ColumnList > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_columnconstraint_list: // columnconstraint_list + case symbol_kind::S_tableconstraint: // tableconstraint + case symbol_kind::S_tableconstraint_list: // tableconstraint_list + case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list + value.move< TableConstraints > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_optional_if_not_exists: // optional_if_not_exists + case symbol_kind::S_optional_unique: // optional_unique + case symbol_kind::S_optional_temporary: // optional_temporary + case symbol_kind::S_optional_always_generated: // optional_always_generated + value.move< bool > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_createindex_stmt: // createindex_stmt + value.move< sqlb::IndexPtr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_indexed_column: // indexed_column + value.move< sqlb::IndexedColumn > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_indexed_column_list: // indexed_column_list + value.move< sqlb::IndexedColumnVector > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_columnid_list: // columnid_list + case symbol_kind::S_optional_columnid_with_paren_list: // optional_columnid_with_paren_list + value.move< sqlb::StringVector > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_createvirtualtable_stmt: // createvirtualtable_stmt + case symbol_kind::S_createtable_stmt: // createtable_stmt + value.move< sqlb::TablePtr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_tableoption: // tableoption + case symbol_kind::S_tableoptions_list: // tableoptions_list + case symbol_kind::S_optional_tableoptions_list: // optional_tableoptions_list + value.move< std::bitset > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_columnconstraint: // columnconstraint + value.move< std::pair, std::shared_ptr> > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_columndef: // columndef + value.move< std::shared_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_ABORT: // "ABORT" + case symbol_kind::S_ACTION: // "ACTION" + case symbol_kind::S_ALWAYS: // "ALWAYS" + case symbol_kind::S_AND: // "AND" + case symbol_kind::S_AND_BETWEEN: // "AND BETWEEN" + case symbol_kind::S_AS: // "AS" + case symbol_kind::S_ASC: // "ASC" + case symbol_kind::S_AUTOINCREMENT: // "AUTOINCREMENT" + case symbol_kind::S_BETWEEN: // "BETWEEN" + case symbol_kind::S_CASCADE: // "CASCADE" + case symbol_kind::S_CASE: // "CASE" + case symbol_kind::S_CAST: // "CAST" + case symbol_kind::S_CHECK: // "CHECK" + case symbol_kind::S_COLLATE: // "COLLATE" + case symbol_kind::S_CONFLICT: // "CONFLICT" + case symbol_kind::S_CONSTRAINT: // "CONSTRAINT" + case symbol_kind::S_CREATE: // "CREATE" + case symbol_kind::S_CURRENT_DATE: // "CURRENT_DATE" + case symbol_kind::S_CURRENT_TIME: // "CURRENT_TIME" + case symbol_kind::S_CURRENT_TIMESTAMP: // "CURRENT_TIMESTAMP" + case symbol_kind::S_DEFAULT: // "DEFAULT" + case symbol_kind::S_DEFERRABLE: // "DEFERRABLE" + case symbol_kind::S_DEFERRED: // "DEFERRED" + case symbol_kind::S_DELETE: // "DELETE" + case symbol_kind::S_DESC: // "DESC" + case symbol_kind::S_DISTINCT: // "DISTINCT" + case symbol_kind::S_ELSE: // "ELSE" + case symbol_kind::S_END: // "END" + case symbol_kind::S_ESCAPE: // "ESCAPE" + case symbol_kind::S_EXISTS: // "EXISTS" + case symbol_kind::S_FAIL: // "FAIL" + case symbol_kind::S_FALSE: // "FALSE" + case symbol_kind::S_FILTER: // "FILTER" + case symbol_kind::S_FOLLOWING: // "FOLLOWING" + case symbol_kind::S_FOREIGN: // "FOREIGN" + case symbol_kind::S_FROM: // "FROM" + case symbol_kind::S_GENERATED: // "GENERATED" + case symbol_kind::S_GLOB: // "GLOB" + case symbol_kind::S_IF: // "IF" + case symbol_kind::S_IGNORE: // "IGNORE" + case symbol_kind::S_IMMEDIATE: // "IMMEDIATE" + case symbol_kind::S_IN: // "IN" + case symbol_kind::S_INDEX: // "INDEX" + case symbol_kind::S_INITIALLY: // "INITIALLY" + case symbol_kind::S_INSERT: // "INSERT" + case symbol_kind::S_IS: // "IS" + case symbol_kind::S_ISNULL: // "ISNULL" + case symbol_kind::S_KEY: // "KEY" + case symbol_kind::S_LIKE: // "LIKE" + case symbol_kind::S_MATCH: // "MATCH" + case symbol_kind::S_NO: // "NO" + case symbol_kind::S_NOT: // "NOT" + case symbol_kind::S_NOTNULL: // "NOTNULL" + case symbol_kind::S_NULL: // "NULL" + case symbol_kind::S_ON: // "ON" + case symbol_kind::S_OR: // "OR" + case symbol_kind::S_OVER: // "OVER" + case symbol_kind::S_PARTITION: // "PARTITION" + case symbol_kind::S_PRECEDING: // "PRECEDING" + case symbol_kind::S_PRIMARY: // "PRIMARY" + case symbol_kind::S_RAISE: // "RAISE" + case symbol_kind::S_RANGE: // "RANGE" + case symbol_kind::S_REFERENCES: // "REFERENCES" + case symbol_kind::S_REGEXP: // "REGEXP" + case symbol_kind::S_REPLACE: // "REPLACE" + case symbol_kind::S_RESTRICT: // "RESTRICT" + case symbol_kind::S_RETURNING: // "RETURNING" + case symbol_kind::S_ROLLBACK: // "ROLLBACK" + case symbol_kind::S_ROWID: // "ROWID" + case symbol_kind::S_ROWS: // "ROWS" + case symbol_kind::S_SELECT: // "SELECT" + case symbol_kind::S_SET: // "SET" + case symbol_kind::S_STORED: // "STORED" + case symbol_kind::S_STRICT: // "STRICT" + case symbol_kind::S_TABLE: // "TABLE" + case symbol_kind::S_TEMP: // "TEMP" + case symbol_kind::S_TEMPORARY: // "TEMPORARY" + case symbol_kind::S_THEN: // "THEN" + case symbol_kind::S_TRUE: // "TRUE" + case symbol_kind::S_UNBOUNDED: // "UNBOUNDED" + case symbol_kind::S_UNIQUE: // "UNIQUE" + case symbol_kind::S_UPDATE: // "UPDATE" + case symbol_kind::S_USING: // "USING" + case symbol_kind::S_VIRTUAL: // "VIRTUAL" + case symbol_kind::S_WHEN: // "WHEN" + case symbol_kind::S_WHERE: // "WHERE" + case symbol_kind::S_WITHOUT: // "WITHOUT" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_NUMERIC: // "numeric" + case symbol_kind::S_STRINGLITERAL: // "string literal" + case symbol_kind::S_QUOTEDLITERAL: // "quoted literal" + case symbol_kind::S_BLOBLITERAL: // "blob literal" + case symbol_kind::S_BINDPARAMETER: // "bind parameter" + case symbol_kind::S_literalvalue: // literalvalue + case symbol_kind::S_id: // id + case symbol_kind::S_allowed_keywords_as_identifier: // allowed_keywords_as_identifier + case symbol_kind::S_tableid: // tableid + case symbol_kind::S_columnid: // columnid + case symbol_kind::S_signednumber: // signednumber + case symbol_kind::S_signednumber_or_numeric: // signednumber_or_numeric + case symbol_kind::S_typename_namelist: // typename_namelist + case symbol_kind::S_type_name: // type_name + case symbol_kind::S_unary_expr: // unary_expr + case symbol_kind::S_binary_expr: // binary_expr + case symbol_kind::S_like_expr: // like_expr + case symbol_kind::S_exprlist_expr: // exprlist_expr + case symbol_kind::S_function_expr: // function_expr + case symbol_kind::S_isnull_expr: // isnull_expr + case symbol_kind::S_between_expr: // between_expr + case symbol_kind::S_in_expr: // in_expr + case symbol_kind::S_whenthenlist_expr: // whenthenlist_expr + case symbol_kind::S_case_expr: // case_expr + case symbol_kind::S_raise_expr: // raise_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_select_stmt: // select_stmt + case symbol_kind::S_optional_sort_order: // optional_sort_order + case symbol_kind::S_optional_where: // optional_where + case symbol_kind::S_tableid_with_uninteresting_schema: // tableid_with_uninteresting_schema + case symbol_kind::S_optional_exprlist_with_paren: // optional_exprlist_with_paren + case symbol_kind::S_optional_conflictclause: // optional_conflictclause + case symbol_kind::S_optional_typename: // optional_typename + case symbol_kind::S_optional_storage_identifier: // optional_storage_identifier + case symbol_kind::S_optional_constraintname: // optional_constraintname + case symbol_kind::S_fk_clause_part: // fk_clause_part + case symbol_kind::S_fk_clause_part_list: // fk_clause_part_list + case symbol_kind::S_optional_fk_clause: // optional_fk_clause + value.move< std::string > (YY_MOVE (that.value)); + break; + + default: + break; + } + + // that is emptied. + that.kind_ = symbol_kind::S_YYEMPTY; + } + +#if YY_CPLUSPLUS < 201103L + parser::stack_symbol_type& + parser::stack_symbol_type::operator= (const stack_symbol_type& that) + { + state = that.state; + switch (that.kind ()) + { + case symbol_kind::S_columndef_list: // columndef_list + value.copy< ColumnList > (that.value); + break; + + case symbol_kind::S_columnconstraint_list: // columnconstraint_list + case symbol_kind::S_tableconstraint: // tableconstraint + case symbol_kind::S_tableconstraint_list: // tableconstraint_list + case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list + value.copy< TableConstraints > (that.value); + break; + + case symbol_kind::S_optional_if_not_exists: // optional_if_not_exists + case symbol_kind::S_optional_unique: // optional_unique + case symbol_kind::S_optional_temporary: // optional_temporary + case symbol_kind::S_optional_always_generated: // optional_always_generated + value.copy< bool > (that.value); + break; + + case symbol_kind::S_createindex_stmt: // createindex_stmt + value.copy< sqlb::IndexPtr > (that.value); + break; + + case symbol_kind::S_indexed_column: // indexed_column + value.copy< sqlb::IndexedColumn > (that.value); + break; + + case symbol_kind::S_indexed_column_list: // indexed_column_list + value.copy< sqlb::IndexedColumnVector > (that.value); + break; + + case symbol_kind::S_columnid_list: // columnid_list + case symbol_kind::S_optional_columnid_with_paren_list: // optional_columnid_with_paren_list + value.copy< sqlb::StringVector > (that.value); + break; + + case symbol_kind::S_createvirtualtable_stmt: // createvirtualtable_stmt + case symbol_kind::S_createtable_stmt: // createtable_stmt + value.copy< sqlb::TablePtr > (that.value); + break; + + case symbol_kind::S_tableoption: // tableoption + case symbol_kind::S_tableoptions_list: // tableoptions_list + case symbol_kind::S_optional_tableoptions_list: // optional_tableoptions_list + value.copy< std::bitset > (that.value); + break; + + case symbol_kind::S_columnconstraint: // columnconstraint + value.copy< std::pair, std::shared_ptr> > (that.value); + break; + + case symbol_kind::S_columndef: // columndef + value.copy< std::shared_ptr > (that.value); + break; + + case symbol_kind::S_ABORT: // "ABORT" + case symbol_kind::S_ACTION: // "ACTION" + case symbol_kind::S_ALWAYS: // "ALWAYS" + case symbol_kind::S_AND: // "AND" + case symbol_kind::S_AND_BETWEEN: // "AND BETWEEN" + case symbol_kind::S_AS: // "AS" + case symbol_kind::S_ASC: // "ASC" + case symbol_kind::S_AUTOINCREMENT: // "AUTOINCREMENT" + case symbol_kind::S_BETWEEN: // "BETWEEN" + case symbol_kind::S_CASCADE: // "CASCADE" + case symbol_kind::S_CASE: // "CASE" + case symbol_kind::S_CAST: // "CAST" + case symbol_kind::S_CHECK: // "CHECK" + case symbol_kind::S_COLLATE: // "COLLATE" + case symbol_kind::S_CONFLICT: // "CONFLICT" + case symbol_kind::S_CONSTRAINT: // "CONSTRAINT" + case symbol_kind::S_CREATE: // "CREATE" + case symbol_kind::S_CURRENT_DATE: // "CURRENT_DATE" + case symbol_kind::S_CURRENT_TIME: // "CURRENT_TIME" + case symbol_kind::S_CURRENT_TIMESTAMP: // "CURRENT_TIMESTAMP" + case symbol_kind::S_DEFAULT: // "DEFAULT" + case symbol_kind::S_DEFERRABLE: // "DEFERRABLE" + case symbol_kind::S_DEFERRED: // "DEFERRED" + case symbol_kind::S_DELETE: // "DELETE" + case symbol_kind::S_DESC: // "DESC" + case symbol_kind::S_DISTINCT: // "DISTINCT" + case symbol_kind::S_ELSE: // "ELSE" + case symbol_kind::S_END: // "END" + case symbol_kind::S_ESCAPE: // "ESCAPE" + case symbol_kind::S_EXISTS: // "EXISTS" + case symbol_kind::S_FAIL: // "FAIL" + case symbol_kind::S_FALSE: // "FALSE" + case symbol_kind::S_FILTER: // "FILTER" + case symbol_kind::S_FOLLOWING: // "FOLLOWING" + case symbol_kind::S_FOREIGN: // "FOREIGN" + case symbol_kind::S_FROM: // "FROM" + case symbol_kind::S_GENERATED: // "GENERATED" + case symbol_kind::S_GLOB: // "GLOB" + case symbol_kind::S_IF: // "IF" + case symbol_kind::S_IGNORE: // "IGNORE" + case symbol_kind::S_IMMEDIATE: // "IMMEDIATE" + case symbol_kind::S_IN: // "IN" + case symbol_kind::S_INDEX: // "INDEX" + case symbol_kind::S_INITIALLY: // "INITIALLY" + case symbol_kind::S_INSERT: // "INSERT" + case symbol_kind::S_IS: // "IS" + case symbol_kind::S_ISNULL: // "ISNULL" + case symbol_kind::S_KEY: // "KEY" + case symbol_kind::S_LIKE: // "LIKE" + case symbol_kind::S_MATCH: // "MATCH" + case symbol_kind::S_NO: // "NO" + case symbol_kind::S_NOT: // "NOT" + case symbol_kind::S_NOTNULL: // "NOTNULL" + case symbol_kind::S_NULL: // "NULL" + case symbol_kind::S_ON: // "ON" + case symbol_kind::S_OR: // "OR" + case symbol_kind::S_OVER: // "OVER" + case symbol_kind::S_PARTITION: // "PARTITION" + case symbol_kind::S_PRECEDING: // "PRECEDING" + case symbol_kind::S_PRIMARY: // "PRIMARY" + case symbol_kind::S_RAISE: // "RAISE" + case symbol_kind::S_RANGE: // "RANGE" + case symbol_kind::S_REFERENCES: // "REFERENCES" + case symbol_kind::S_REGEXP: // "REGEXP" + case symbol_kind::S_REPLACE: // "REPLACE" + case symbol_kind::S_RESTRICT: // "RESTRICT" + case symbol_kind::S_RETURNING: // "RETURNING" + case symbol_kind::S_ROLLBACK: // "ROLLBACK" + case symbol_kind::S_ROWID: // "ROWID" + case symbol_kind::S_ROWS: // "ROWS" + case symbol_kind::S_SELECT: // "SELECT" + case symbol_kind::S_SET: // "SET" + case symbol_kind::S_STORED: // "STORED" + case symbol_kind::S_STRICT: // "STRICT" + case symbol_kind::S_TABLE: // "TABLE" + case symbol_kind::S_TEMP: // "TEMP" + case symbol_kind::S_TEMPORARY: // "TEMPORARY" + case symbol_kind::S_THEN: // "THEN" + case symbol_kind::S_TRUE: // "TRUE" + case symbol_kind::S_UNBOUNDED: // "UNBOUNDED" + case symbol_kind::S_UNIQUE: // "UNIQUE" + case symbol_kind::S_UPDATE: // "UPDATE" + case symbol_kind::S_USING: // "USING" + case symbol_kind::S_VIRTUAL: // "VIRTUAL" + case symbol_kind::S_WHEN: // "WHEN" + case symbol_kind::S_WHERE: // "WHERE" + case symbol_kind::S_WITHOUT: // "WITHOUT" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_NUMERIC: // "numeric" + case symbol_kind::S_STRINGLITERAL: // "string literal" + case symbol_kind::S_QUOTEDLITERAL: // "quoted literal" + case symbol_kind::S_BLOBLITERAL: // "blob literal" + case symbol_kind::S_BINDPARAMETER: // "bind parameter" + case symbol_kind::S_literalvalue: // literalvalue + case symbol_kind::S_id: // id + case symbol_kind::S_allowed_keywords_as_identifier: // allowed_keywords_as_identifier + case symbol_kind::S_tableid: // tableid + case symbol_kind::S_columnid: // columnid + case symbol_kind::S_signednumber: // signednumber + case symbol_kind::S_signednumber_or_numeric: // signednumber_or_numeric + case symbol_kind::S_typename_namelist: // typename_namelist + case symbol_kind::S_type_name: // type_name + case symbol_kind::S_unary_expr: // unary_expr + case symbol_kind::S_binary_expr: // binary_expr + case symbol_kind::S_like_expr: // like_expr + case symbol_kind::S_exprlist_expr: // exprlist_expr + case symbol_kind::S_function_expr: // function_expr + case symbol_kind::S_isnull_expr: // isnull_expr + case symbol_kind::S_between_expr: // between_expr + case symbol_kind::S_in_expr: // in_expr + case symbol_kind::S_whenthenlist_expr: // whenthenlist_expr + case symbol_kind::S_case_expr: // case_expr + case symbol_kind::S_raise_expr: // raise_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_select_stmt: // select_stmt + case symbol_kind::S_optional_sort_order: // optional_sort_order + case symbol_kind::S_optional_where: // optional_where + case symbol_kind::S_tableid_with_uninteresting_schema: // tableid_with_uninteresting_schema + case symbol_kind::S_optional_exprlist_with_paren: // optional_exprlist_with_paren + case symbol_kind::S_optional_conflictclause: // optional_conflictclause + case symbol_kind::S_optional_typename: // optional_typename + case symbol_kind::S_optional_storage_identifier: // optional_storage_identifier + case symbol_kind::S_optional_constraintname: // optional_constraintname + case symbol_kind::S_fk_clause_part: // fk_clause_part + case symbol_kind::S_fk_clause_part_list: // fk_clause_part_list + case symbol_kind::S_optional_fk_clause: // optional_fk_clause + value.copy< std::string > (that.value); + break; + + default: + break; + } + + location = that.location; + return *this; + } + + parser::stack_symbol_type& + parser::stack_symbol_type::operator= (stack_symbol_type& that) + { + state = that.state; + switch (that.kind ()) + { + case symbol_kind::S_columndef_list: // columndef_list + value.move< ColumnList > (that.value); + break; + + case symbol_kind::S_columnconstraint_list: // columnconstraint_list + case symbol_kind::S_tableconstraint: // tableconstraint + case symbol_kind::S_tableconstraint_list: // tableconstraint_list + case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list + value.move< TableConstraints > (that.value); + break; + + case symbol_kind::S_optional_if_not_exists: // optional_if_not_exists + case symbol_kind::S_optional_unique: // optional_unique + case symbol_kind::S_optional_temporary: // optional_temporary + case symbol_kind::S_optional_always_generated: // optional_always_generated + value.move< bool > (that.value); + break; + + case symbol_kind::S_createindex_stmt: // createindex_stmt + value.move< sqlb::IndexPtr > (that.value); + break; + + case symbol_kind::S_indexed_column: // indexed_column + value.move< sqlb::IndexedColumn > (that.value); + break; + + case symbol_kind::S_indexed_column_list: // indexed_column_list + value.move< sqlb::IndexedColumnVector > (that.value); + break; + + case symbol_kind::S_columnid_list: // columnid_list + case symbol_kind::S_optional_columnid_with_paren_list: // optional_columnid_with_paren_list + value.move< sqlb::StringVector > (that.value); + break; + + case symbol_kind::S_createvirtualtable_stmt: // createvirtualtable_stmt + case symbol_kind::S_createtable_stmt: // createtable_stmt + value.move< sqlb::TablePtr > (that.value); + break; + + case symbol_kind::S_tableoption: // tableoption + case symbol_kind::S_tableoptions_list: // tableoptions_list + case symbol_kind::S_optional_tableoptions_list: // optional_tableoptions_list + value.move< std::bitset > (that.value); + break; + + case symbol_kind::S_columnconstraint: // columnconstraint + value.move< std::pair, std::shared_ptr> > (that.value); + break; + + case symbol_kind::S_columndef: // columndef + value.move< std::shared_ptr > (that.value); + break; + + case symbol_kind::S_ABORT: // "ABORT" + case symbol_kind::S_ACTION: // "ACTION" + case symbol_kind::S_ALWAYS: // "ALWAYS" + case symbol_kind::S_AND: // "AND" + case symbol_kind::S_AND_BETWEEN: // "AND BETWEEN" + case symbol_kind::S_AS: // "AS" + case symbol_kind::S_ASC: // "ASC" + case symbol_kind::S_AUTOINCREMENT: // "AUTOINCREMENT" + case symbol_kind::S_BETWEEN: // "BETWEEN" + case symbol_kind::S_CASCADE: // "CASCADE" + case symbol_kind::S_CASE: // "CASE" + case symbol_kind::S_CAST: // "CAST" + case symbol_kind::S_CHECK: // "CHECK" + case symbol_kind::S_COLLATE: // "COLLATE" + case symbol_kind::S_CONFLICT: // "CONFLICT" + case symbol_kind::S_CONSTRAINT: // "CONSTRAINT" + case symbol_kind::S_CREATE: // "CREATE" + case symbol_kind::S_CURRENT_DATE: // "CURRENT_DATE" + case symbol_kind::S_CURRENT_TIME: // "CURRENT_TIME" + case symbol_kind::S_CURRENT_TIMESTAMP: // "CURRENT_TIMESTAMP" + case symbol_kind::S_DEFAULT: // "DEFAULT" + case symbol_kind::S_DEFERRABLE: // "DEFERRABLE" + case symbol_kind::S_DEFERRED: // "DEFERRED" + case symbol_kind::S_DELETE: // "DELETE" + case symbol_kind::S_DESC: // "DESC" + case symbol_kind::S_DISTINCT: // "DISTINCT" + case symbol_kind::S_ELSE: // "ELSE" + case symbol_kind::S_END: // "END" + case symbol_kind::S_ESCAPE: // "ESCAPE" + case symbol_kind::S_EXISTS: // "EXISTS" + case symbol_kind::S_FAIL: // "FAIL" + case symbol_kind::S_FALSE: // "FALSE" + case symbol_kind::S_FILTER: // "FILTER" + case symbol_kind::S_FOLLOWING: // "FOLLOWING" + case symbol_kind::S_FOREIGN: // "FOREIGN" + case symbol_kind::S_FROM: // "FROM" + case symbol_kind::S_GENERATED: // "GENERATED" + case symbol_kind::S_GLOB: // "GLOB" + case symbol_kind::S_IF: // "IF" + case symbol_kind::S_IGNORE: // "IGNORE" + case symbol_kind::S_IMMEDIATE: // "IMMEDIATE" + case symbol_kind::S_IN: // "IN" + case symbol_kind::S_INDEX: // "INDEX" + case symbol_kind::S_INITIALLY: // "INITIALLY" + case symbol_kind::S_INSERT: // "INSERT" + case symbol_kind::S_IS: // "IS" + case symbol_kind::S_ISNULL: // "ISNULL" + case symbol_kind::S_KEY: // "KEY" + case symbol_kind::S_LIKE: // "LIKE" + case symbol_kind::S_MATCH: // "MATCH" + case symbol_kind::S_NO: // "NO" + case symbol_kind::S_NOT: // "NOT" + case symbol_kind::S_NOTNULL: // "NOTNULL" + case symbol_kind::S_NULL: // "NULL" + case symbol_kind::S_ON: // "ON" + case symbol_kind::S_OR: // "OR" + case symbol_kind::S_OVER: // "OVER" + case symbol_kind::S_PARTITION: // "PARTITION" + case symbol_kind::S_PRECEDING: // "PRECEDING" + case symbol_kind::S_PRIMARY: // "PRIMARY" + case symbol_kind::S_RAISE: // "RAISE" + case symbol_kind::S_RANGE: // "RANGE" + case symbol_kind::S_REFERENCES: // "REFERENCES" + case symbol_kind::S_REGEXP: // "REGEXP" + case symbol_kind::S_REPLACE: // "REPLACE" + case symbol_kind::S_RESTRICT: // "RESTRICT" + case symbol_kind::S_RETURNING: // "RETURNING" + case symbol_kind::S_ROLLBACK: // "ROLLBACK" + case symbol_kind::S_ROWID: // "ROWID" + case symbol_kind::S_ROWS: // "ROWS" + case symbol_kind::S_SELECT: // "SELECT" + case symbol_kind::S_SET: // "SET" + case symbol_kind::S_STORED: // "STORED" + case symbol_kind::S_STRICT: // "STRICT" + case symbol_kind::S_TABLE: // "TABLE" + case symbol_kind::S_TEMP: // "TEMP" + case symbol_kind::S_TEMPORARY: // "TEMPORARY" + case symbol_kind::S_THEN: // "THEN" + case symbol_kind::S_TRUE: // "TRUE" + case symbol_kind::S_UNBOUNDED: // "UNBOUNDED" + case symbol_kind::S_UNIQUE: // "UNIQUE" + case symbol_kind::S_UPDATE: // "UPDATE" + case symbol_kind::S_USING: // "USING" + case symbol_kind::S_VIRTUAL: // "VIRTUAL" + case symbol_kind::S_WHEN: // "WHEN" + case symbol_kind::S_WHERE: // "WHERE" + case symbol_kind::S_WITHOUT: // "WITHOUT" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_NUMERIC: // "numeric" + case symbol_kind::S_STRINGLITERAL: // "string literal" + case symbol_kind::S_QUOTEDLITERAL: // "quoted literal" + case symbol_kind::S_BLOBLITERAL: // "blob literal" + case symbol_kind::S_BINDPARAMETER: // "bind parameter" + case symbol_kind::S_literalvalue: // literalvalue + case symbol_kind::S_id: // id + case symbol_kind::S_allowed_keywords_as_identifier: // allowed_keywords_as_identifier + case symbol_kind::S_tableid: // tableid + case symbol_kind::S_columnid: // columnid + case symbol_kind::S_signednumber: // signednumber + case symbol_kind::S_signednumber_or_numeric: // signednumber_or_numeric + case symbol_kind::S_typename_namelist: // typename_namelist + case symbol_kind::S_type_name: // type_name + case symbol_kind::S_unary_expr: // unary_expr + case symbol_kind::S_binary_expr: // binary_expr + case symbol_kind::S_like_expr: // like_expr + case symbol_kind::S_exprlist_expr: // exprlist_expr + case symbol_kind::S_function_expr: // function_expr + case symbol_kind::S_isnull_expr: // isnull_expr + case symbol_kind::S_between_expr: // between_expr + case symbol_kind::S_in_expr: // in_expr + case symbol_kind::S_whenthenlist_expr: // whenthenlist_expr + case symbol_kind::S_case_expr: // case_expr + case symbol_kind::S_raise_expr: // raise_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_select_stmt: // select_stmt + case symbol_kind::S_optional_sort_order: // optional_sort_order + case symbol_kind::S_optional_where: // optional_where + case symbol_kind::S_tableid_with_uninteresting_schema: // tableid_with_uninteresting_schema + case symbol_kind::S_optional_exprlist_with_paren: // optional_exprlist_with_paren + case symbol_kind::S_optional_conflictclause: // optional_conflictclause + case symbol_kind::S_optional_typename: // optional_typename + case symbol_kind::S_optional_storage_identifier: // optional_storage_identifier + case symbol_kind::S_optional_constraintname: // optional_constraintname + case symbol_kind::S_fk_clause_part: // fk_clause_part + case symbol_kind::S_fk_clause_part_list: // fk_clause_part_list + case symbol_kind::S_optional_fk_clause: // optional_fk_clause + value.move< std::string > (that.value); + break; + + default: + break; + } + + location = that.location; + // that is emptied. + that.state = empty_state; + return *this; + } +#endif + + template + void + parser::yy_destroy_ (const char* yymsg, basic_symbol& yysym) const + { + if (yymsg) + YY_SYMBOL_PRINT (yymsg, yysym); + } + +#if YYDEBUG + template + void + parser::yy_print_ (std::ostream& yyo, const basic_symbol& yysym) const + { + std::ostream& yyoutput = yyo; + YY_USE (yyoutput); + if (yysym.empty ()) + yyo << "empty symbol"; + else + { + symbol_kind_type yykind = yysym.kind (); + yyo << (yykind < YYNTOKENS ? "token" : "nterm") + << ' ' << yysym.name () << " (" + << yysym.location << ": "; + YY_USE (yykind); + yyo << ')'; + } + } +#endif + + void + parser::yypush_ (const char* m, YY_MOVE_REF (stack_symbol_type) sym) + { + if (m) + YY_SYMBOL_PRINT (m, sym); + yystack_.push (YY_MOVE (sym)); + } + + void + parser::yypush_ (const char* m, state_type s, YY_MOVE_REF (symbol_type) sym) + { +#if 201103L <= YY_CPLUSPLUS + yypush_ (m, stack_symbol_type (s, std::move (sym))); +#else + stack_symbol_type ss (s, sym); + yypush_ (m, ss); +#endif + } + + void + parser::yypop_ (int n) YY_NOEXCEPT + { + yystack_.pop (n); + } + +#if YYDEBUG + std::ostream& + parser::debug_stream () const + { + return *yycdebug_; + } + + void + parser::set_debug_stream (std::ostream& o) + { + yycdebug_ = &o; + } + + + parser::debug_level_type + parser::debug_level () const + { + return yydebug_; + } + + void + parser::set_debug_level (debug_level_type l) + { + yydebug_ = l; + } +#endif // YYDEBUG + + parser::state_type + parser::yy_lr_goto_state_ (state_type yystate, int yysym) + { + int yyr = yypgoto_[yysym - YYNTOKENS] + yystate; + if (0 <= yyr && yyr <= yylast_ && yycheck_[yyr] == yystate) + return yytable_[yyr]; + else + return yydefgoto_[yysym - YYNTOKENS]; + } + + bool + parser::yy_pact_value_is_default_ (int yyvalue) YY_NOEXCEPT + { + return yyvalue == yypact_ninf_; + } + + bool + parser::yy_table_value_is_error_ (int yyvalue) YY_NOEXCEPT + { + return yyvalue == yytable_ninf_; + } + + int + parser::operator() () + { + return parse (); + } + + int + parser::parse () + { + int yyn; + /// Length of the RHS of the rule being reduced. + int yylen = 0; + + // Error handling. + int yynerrs_ = 0; + int yyerrstatus_ = 0; + + /// The lookahead symbol. + symbol_type yyla; + + /// The locations where the error started and ended. + stack_symbol_type yyerror_range[3]; + + /// The return value of parse (). + int yyresult; + +#if YY_EXCEPTIONS + try +#endif // YY_EXCEPTIONS + { + YYCDEBUG << "Starting parse\n"; + + + /* Initialize the stack. The initial state will be set in + yynewstate, since the latter expects the semantical and the + location values to have been already stored, initialize these + stacks with a primary value. */ + yystack_.clear (); + yypush_ (YY_NULLPTR, 0, YY_MOVE (yyla)); + + /*-----------------------------------------------. + | yynewstate -- push a new symbol on the stack. | + `-----------------------------------------------*/ + yynewstate: + YYCDEBUG << "Entering state " << int (yystack_[0].state) << '\n'; + YY_STACK_PRINT (); + + // Accept? + if (yystack_[0].state == yyfinal_) + YYACCEPT; + + goto yybackup; + + + /*-----------. + | yybackup. | + `-----------*/ + yybackup: + // Try to take a decision without lookahead. + yyn = yypact_[+yystack_[0].state]; + if (yy_pact_value_is_default_ (yyn)) + goto yydefault; + + // Read a lookahead token. + if (yyla.empty ()) + { + YYCDEBUG << "Reading a token\n"; +#if YY_EXCEPTIONS + try +#endif // YY_EXCEPTIONS + { + symbol_type yylookahead (yylex (yyscanner, drv)); + yyla.move (yylookahead); + } +#if YY_EXCEPTIONS + catch (const syntax_error& yyexc) + { + YYCDEBUG << "Caught exception: " << yyexc.what() << '\n'; + error (yyexc); + goto yyerrlab1; + } +#endif // YY_EXCEPTIONS + } + YY_SYMBOL_PRINT ("Next token is", yyla); + + if (yyla.kind () == symbol_kind::S_YYerror) + { + // The scanner already issued an error message, process directly + // to error recovery. But do not keep the error token as + // lookahead, it is too special and may lead us to an endless + // loop in error recovery. */ + yyla.kind_ = symbol_kind::S_YYUNDEF; + goto yyerrlab1; + } + + /* If the proper action on seeing token YYLA.TYPE is to reduce or + to detect an error, take that action. */ + yyn += yyla.kind (); + if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yyla.kind ()) + { + goto yydefault; + } + + // Reduce or error. + yyn = yytable_[yyn]; + if (yyn <= 0) + { + if (yy_table_value_is_error_ (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + // Count tokens shifted since error; after three, turn off error status. + if (yyerrstatus_) + --yyerrstatus_; + + // Shift the lookahead token. + yypush_ ("Shifting", state_type (yyn), YY_MOVE (yyla)); + goto yynewstate; + + + /*-----------------------------------------------------------. + | yydefault -- do the default action for the current state. | + `-----------------------------------------------------------*/ + yydefault: + yyn = yydefact_[+yystack_[0].state]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + + /*-----------------------------. + | yyreduce -- do a reduction. | + `-----------------------------*/ + yyreduce: + yylen = yyr2_[yyn]; + { + stack_symbol_type yylhs; + yylhs.state = yy_lr_goto_state_ (yystack_[yylen].state, yyr1_[yyn]); + /* Variants are always initialized to an empty instance of the + correct type. The default '$$ = $1' action is NOT applied + when using variants. */ + switch (yyr1_[yyn]) + { + case symbol_kind::S_columndef_list: // columndef_list + yylhs.value.emplace< ColumnList > (); + break; + + case symbol_kind::S_columnconstraint_list: // columnconstraint_list + case symbol_kind::S_tableconstraint: // tableconstraint + case symbol_kind::S_tableconstraint_list: // tableconstraint_list + case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list + yylhs.value.emplace< TableConstraints > (); + break; + + case symbol_kind::S_optional_if_not_exists: // optional_if_not_exists + case symbol_kind::S_optional_unique: // optional_unique + case symbol_kind::S_optional_temporary: // optional_temporary + case symbol_kind::S_optional_always_generated: // optional_always_generated + yylhs.value.emplace< bool > (); + break; + + case symbol_kind::S_createindex_stmt: // createindex_stmt + yylhs.value.emplace< sqlb::IndexPtr > (); + break; + + case symbol_kind::S_indexed_column: // indexed_column + yylhs.value.emplace< sqlb::IndexedColumn > (); + break; + + case symbol_kind::S_indexed_column_list: // indexed_column_list + yylhs.value.emplace< sqlb::IndexedColumnVector > (); + break; + + case symbol_kind::S_columnid_list: // columnid_list + case symbol_kind::S_optional_columnid_with_paren_list: // optional_columnid_with_paren_list + yylhs.value.emplace< sqlb::StringVector > (); + break; + + case symbol_kind::S_createvirtualtable_stmt: // createvirtualtable_stmt + case symbol_kind::S_createtable_stmt: // createtable_stmt + yylhs.value.emplace< sqlb::TablePtr > (); + break; + + case symbol_kind::S_tableoption: // tableoption + case symbol_kind::S_tableoptions_list: // tableoptions_list + case symbol_kind::S_optional_tableoptions_list: // optional_tableoptions_list + yylhs.value.emplace< std::bitset > (); + break; + + case symbol_kind::S_columnconstraint: // columnconstraint + yylhs.value.emplace< std::pair, std::shared_ptr> > (); + break; + + case symbol_kind::S_columndef: // columndef + yylhs.value.emplace< std::shared_ptr > (); + break; + + case symbol_kind::S_ABORT: // "ABORT" + case symbol_kind::S_ACTION: // "ACTION" + case symbol_kind::S_ALWAYS: // "ALWAYS" + case symbol_kind::S_AND: // "AND" + case symbol_kind::S_AND_BETWEEN: // "AND BETWEEN" + case symbol_kind::S_AS: // "AS" + case symbol_kind::S_ASC: // "ASC" + case symbol_kind::S_AUTOINCREMENT: // "AUTOINCREMENT" + case symbol_kind::S_BETWEEN: // "BETWEEN" + case symbol_kind::S_CASCADE: // "CASCADE" + case symbol_kind::S_CASE: // "CASE" + case symbol_kind::S_CAST: // "CAST" + case symbol_kind::S_CHECK: // "CHECK" + case symbol_kind::S_COLLATE: // "COLLATE" + case symbol_kind::S_CONFLICT: // "CONFLICT" + case symbol_kind::S_CONSTRAINT: // "CONSTRAINT" + case symbol_kind::S_CREATE: // "CREATE" + case symbol_kind::S_CURRENT_DATE: // "CURRENT_DATE" + case symbol_kind::S_CURRENT_TIME: // "CURRENT_TIME" + case symbol_kind::S_CURRENT_TIMESTAMP: // "CURRENT_TIMESTAMP" + case symbol_kind::S_DEFAULT: // "DEFAULT" + case symbol_kind::S_DEFERRABLE: // "DEFERRABLE" + case symbol_kind::S_DEFERRED: // "DEFERRED" + case symbol_kind::S_DELETE: // "DELETE" + case symbol_kind::S_DESC: // "DESC" + case symbol_kind::S_DISTINCT: // "DISTINCT" + case symbol_kind::S_ELSE: // "ELSE" + case symbol_kind::S_END: // "END" + case symbol_kind::S_ESCAPE: // "ESCAPE" + case symbol_kind::S_EXISTS: // "EXISTS" + case symbol_kind::S_FAIL: // "FAIL" + case symbol_kind::S_FALSE: // "FALSE" + case symbol_kind::S_FILTER: // "FILTER" + case symbol_kind::S_FOLLOWING: // "FOLLOWING" + case symbol_kind::S_FOREIGN: // "FOREIGN" + case symbol_kind::S_FROM: // "FROM" + case symbol_kind::S_GENERATED: // "GENERATED" + case symbol_kind::S_GLOB: // "GLOB" + case symbol_kind::S_IF: // "IF" + case symbol_kind::S_IGNORE: // "IGNORE" + case symbol_kind::S_IMMEDIATE: // "IMMEDIATE" + case symbol_kind::S_IN: // "IN" + case symbol_kind::S_INDEX: // "INDEX" + case symbol_kind::S_INITIALLY: // "INITIALLY" + case symbol_kind::S_INSERT: // "INSERT" + case symbol_kind::S_IS: // "IS" + case symbol_kind::S_ISNULL: // "ISNULL" + case symbol_kind::S_KEY: // "KEY" + case symbol_kind::S_LIKE: // "LIKE" + case symbol_kind::S_MATCH: // "MATCH" + case symbol_kind::S_NO: // "NO" + case symbol_kind::S_NOT: // "NOT" + case symbol_kind::S_NOTNULL: // "NOTNULL" + case symbol_kind::S_NULL: // "NULL" + case symbol_kind::S_ON: // "ON" + case symbol_kind::S_OR: // "OR" + case symbol_kind::S_OVER: // "OVER" + case symbol_kind::S_PARTITION: // "PARTITION" + case symbol_kind::S_PRECEDING: // "PRECEDING" + case symbol_kind::S_PRIMARY: // "PRIMARY" + case symbol_kind::S_RAISE: // "RAISE" + case symbol_kind::S_RANGE: // "RANGE" + case symbol_kind::S_REFERENCES: // "REFERENCES" + case symbol_kind::S_REGEXP: // "REGEXP" + case symbol_kind::S_REPLACE: // "REPLACE" + case symbol_kind::S_RESTRICT: // "RESTRICT" + case symbol_kind::S_RETURNING: // "RETURNING" + case symbol_kind::S_ROLLBACK: // "ROLLBACK" + case symbol_kind::S_ROWID: // "ROWID" + case symbol_kind::S_ROWS: // "ROWS" + case symbol_kind::S_SELECT: // "SELECT" + case symbol_kind::S_SET: // "SET" + case symbol_kind::S_STORED: // "STORED" + case symbol_kind::S_STRICT: // "STRICT" + case symbol_kind::S_TABLE: // "TABLE" + case symbol_kind::S_TEMP: // "TEMP" + case symbol_kind::S_TEMPORARY: // "TEMPORARY" + case symbol_kind::S_THEN: // "THEN" + case symbol_kind::S_TRUE: // "TRUE" + case symbol_kind::S_UNBOUNDED: // "UNBOUNDED" + case symbol_kind::S_UNIQUE: // "UNIQUE" + case symbol_kind::S_UPDATE: // "UPDATE" + case symbol_kind::S_USING: // "USING" + case symbol_kind::S_VIRTUAL: // "VIRTUAL" + case symbol_kind::S_WHEN: // "WHEN" + case symbol_kind::S_WHERE: // "WHERE" + case symbol_kind::S_WITHOUT: // "WITHOUT" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_NUMERIC: // "numeric" + case symbol_kind::S_STRINGLITERAL: // "string literal" + case symbol_kind::S_QUOTEDLITERAL: // "quoted literal" + case symbol_kind::S_BLOBLITERAL: // "blob literal" + case symbol_kind::S_BINDPARAMETER: // "bind parameter" + case symbol_kind::S_literalvalue: // literalvalue + case symbol_kind::S_id: // id + case symbol_kind::S_allowed_keywords_as_identifier: // allowed_keywords_as_identifier + case symbol_kind::S_tableid: // tableid + case symbol_kind::S_columnid: // columnid + case symbol_kind::S_signednumber: // signednumber + case symbol_kind::S_signednumber_or_numeric: // signednumber_or_numeric + case symbol_kind::S_typename_namelist: // typename_namelist + case symbol_kind::S_type_name: // type_name + case symbol_kind::S_unary_expr: // unary_expr + case symbol_kind::S_binary_expr: // binary_expr + case symbol_kind::S_like_expr: // like_expr + case symbol_kind::S_exprlist_expr: // exprlist_expr + case symbol_kind::S_function_expr: // function_expr + case symbol_kind::S_isnull_expr: // isnull_expr + case symbol_kind::S_between_expr: // between_expr + case symbol_kind::S_in_expr: // in_expr + case symbol_kind::S_whenthenlist_expr: // whenthenlist_expr + case symbol_kind::S_case_expr: // case_expr + case symbol_kind::S_raise_expr: // raise_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_select_stmt: // select_stmt + case symbol_kind::S_optional_sort_order: // optional_sort_order + case symbol_kind::S_optional_where: // optional_where + case symbol_kind::S_tableid_with_uninteresting_schema: // tableid_with_uninteresting_schema + case symbol_kind::S_optional_exprlist_with_paren: // optional_exprlist_with_paren + case symbol_kind::S_optional_conflictclause: // optional_conflictclause + case symbol_kind::S_optional_typename: // optional_typename + case symbol_kind::S_optional_storage_identifier: // optional_storage_identifier + case symbol_kind::S_optional_constraintname: // optional_constraintname + case symbol_kind::S_fk_clause_part: // fk_clause_part + case symbol_kind::S_fk_clause_part_list: // fk_clause_part_list + case symbol_kind::S_optional_fk_clause: // optional_fk_clause + yylhs.value.emplace< std::string > (); + break; + + default: + break; + } + + + // Default location. + { + stack_type::slice range (yystack_, yylen); + YYLLOC_DEFAULT (yylhs.location, range, yylen); + yyerror_range[1].location = yylhs.location; + } + + // Perform the reduction. + YY_REDUCE_PRINT (yyn); +#if YY_EXCEPTIONS + try +#endif // YY_EXCEPTIONS + { + switch (yyn) + { + case 4: // statement: createindex_stmt +#line 278 "sqlite3_parser.yy" + { drv.result = yystack_[0].value.as < sqlb::IndexPtr > (); } +#line 1479 "sqlite3_parser.cpp" + break; + + case 5: // statement: createvirtualtable_stmt +#line 279 "sqlite3_parser.yy" + { drv.result = yystack_[0].value.as < sqlb::TablePtr > (); } +#line 1485 "sqlite3_parser.cpp" + break; + + case 6: // statement: createtable_stmt +#line 280 "sqlite3_parser.yy" + { drv.result = yystack_[0].value.as < sqlb::TablePtr > (); } +#line 1491 "sqlite3_parser.cpp" + break; + + case 7: // literalvalue: "numeric" +#line 288 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1497 "sqlite3_parser.cpp" + break; + + case 8: // literalvalue: "string literal" +#line 289 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1503 "sqlite3_parser.cpp" + break; + + case 9: // literalvalue: "blob literal" +#line 290 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1509 "sqlite3_parser.cpp" + break; + + case 10: // literalvalue: "NULL" +#line 291 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1515 "sqlite3_parser.cpp" + break; + + case 11: // literalvalue: "TRUE" +#line 292 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1521 "sqlite3_parser.cpp" + break; + + case 12: // literalvalue: "FALSE" +#line 293 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1527 "sqlite3_parser.cpp" + break; + + case 13: // literalvalue: "CURRENT_TIME" +#line 294 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1533 "sqlite3_parser.cpp" + break; + + case 14: // literalvalue: "CURRENT_DATE" +#line 295 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1539 "sqlite3_parser.cpp" + break; + + case 15: // literalvalue: "CURRENT_TIMESTAMP" +#line 296 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1545 "sqlite3_parser.cpp" + break; + + case 16: // id: "identifier" +#line 300 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1551 "sqlite3_parser.cpp" + break; + + case 17: // id: "quoted literal" +#line 301 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1557 "sqlite3_parser.cpp" + break; + + case 18: // allowed_keywords_as_identifier: "ABORT" +#line 306 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1563 "sqlite3_parser.cpp" + break; + + case 19: // allowed_keywords_as_identifier: "ACTION" +#line 307 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1569 "sqlite3_parser.cpp" + break; + + case 20: // allowed_keywords_as_identifier: "ALWAYS" +#line 308 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1575 "sqlite3_parser.cpp" + break; + + case 21: // allowed_keywords_as_identifier: "ASC" +#line 309 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1581 "sqlite3_parser.cpp" + break; + + case 22: // allowed_keywords_as_identifier: "CASCADE" +#line 310 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1587 "sqlite3_parser.cpp" + break; + + case 23: // allowed_keywords_as_identifier: "CAST" +#line 311 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1593 "sqlite3_parser.cpp" + break; + + case 24: // allowed_keywords_as_identifier: "CONFLICT" +#line 312 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1599 "sqlite3_parser.cpp" + break; + + case 25: // allowed_keywords_as_identifier: "DEFERRED" +#line 313 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1605 "sqlite3_parser.cpp" + break; + + case 26: // allowed_keywords_as_identifier: "DESC" +#line 314 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1611 "sqlite3_parser.cpp" + break; + + case 27: // allowed_keywords_as_identifier: "END" +#line 315 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1617 "sqlite3_parser.cpp" + break; + + case 28: // allowed_keywords_as_identifier: "FAIL" +#line 316 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1623 "sqlite3_parser.cpp" + break; + + case 29: // allowed_keywords_as_identifier: "FILTER" +#line 317 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1629 "sqlite3_parser.cpp" + break; + + case 30: // allowed_keywords_as_identifier: "FOLLOWING" +#line 318 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1635 "sqlite3_parser.cpp" + break; + + case 31: // allowed_keywords_as_identifier: "GENERATED" +#line 319 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1641 "sqlite3_parser.cpp" + break; + + case 32: // allowed_keywords_as_identifier: "GLOB" +#line 320 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1647 "sqlite3_parser.cpp" + break; + + case 33: // allowed_keywords_as_identifier: "KEY" +#line 321 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1653 "sqlite3_parser.cpp" + break; + + case 34: // allowed_keywords_as_identifier: "LIKE" +#line 322 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1659 "sqlite3_parser.cpp" + break; + + case 35: // allowed_keywords_as_identifier: "IGNORE" +#line 323 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1665 "sqlite3_parser.cpp" + break; + + case 36: // allowed_keywords_as_identifier: "INITIALLY" +#line 324 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1671 "sqlite3_parser.cpp" + break; + + case 37: // allowed_keywords_as_identifier: "IMMEDIATE" +#line 325 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1677 "sqlite3_parser.cpp" + break; + + case 38: // allowed_keywords_as_identifier: "MATCH" +#line 326 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1683 "sqlite3_parser.cpp" + break; + + case 39: // allowed_keywords_as_identifier: "NO" +#line 327 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1689 "sqlite3_parser.cpp" + break; + + case 40: // allowed_keywords_as_identifier: "OVER" +#line 328 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1695 "sqlite3_parser.cpp" + break; + + case 41: // allowed_keywords_as_identifier: "PARTITION" +#line 329 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1701 "sqlite3_parser.cpp" + break; + + case 42: // allowed_keywords_as_identifier: "PRECEDING" +#line 330 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1707 "sqlite3_parser.cpp" + break; + + case 43: // allowed_keywords_as_identifier: "RAISE" +#line 331 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1713 "sqlite3_parser.cpp" + break; + + case 44: // allowed_keywords_as_identifier: "RANGE" +#line 332 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1719 "sqlite3_parser.cpp" + break; + + case 45: // allowed_keywords_as_identifier: "REGEXP" +#line 333 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1725 "sqlite3_parser.cpp" + break; + + case 46: // allowed_keywords_as_identifier: "REPLACE" +#line 334 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1731 "sqlite3_parser.cpp" + break; + + case 47: // allowed_keywords_as_identifier: "RESTRICT" +#line 335 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1737 "sqlite3_parser.cpp" + break; + + case 48: // allowed_keywords_as_identifier: "RETURNING" +#line 336 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1743 "sqlite3_parser.cpp" + break; + + case 49: // allowed_keywords_as_identifier: "ROLLBACK" +#line 337 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1749 "sqlite3_parser.cpp" + break; + + case 50: // allowed_keywords_as_identifier: "ROWID" +#line 338 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1755 "sqlite3_parser.cpp" + break; + + case 51: // allowed_keywords_as_identifier: "ROWS" +#line 339 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1761 "sqlite3_parser.cpp" + break; + + case 52: // allowed_keywords_as_identifier: "STORED" +#line 340 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1767 "sqlite3_parser.cpp" + break; + + case 53: // allowed_keywords_as_identifier: "STRICT" +#line 341 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1773 "sqlite3_parser.cpp" + break; + + case 54: // allowed_keywords_as_identifier: "TEMPORARY" +#line 342 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1779 "sqlite3_parser.cpp" + break; + + case 55: // allowed_keywords_as_identifier: "TEMP" +#line 343 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1785 "sqlite3_parser.cpp" + break; + + case 56: // allowed_keywords_as_identifier: "UNBOUNDED" +#line 344 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1791 "sqlite3_parser.cpp" + break; + + case 57: // allowed_keywords_as_identifier: "VIRTUAL" +#line 345 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1797 "sqlite3_parser.cpp" + break; + + case 58: // allowed_keywords_as_identifier: "WITHOUT" +#line 346 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1803 "sqlite3_parser.cpp" + break; + + case 59: // tableid: allowed_keywords_as_identifier +#line 350 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1809 "sqlite3_parser.cpp" + break; + + case 60: // tableid: "CURRENT_TIME" +#line 351 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1815 "sqlite3_parser.cpp" + break; + + case 61: // tableid: "CURRENT_DATE" +#line 352 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1821 "sqlite3_parser.cpp" + break; + + case 62: // tableid: "CURRENT_TIMESTAMP" +#line 353 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1827 "sqlite3_parser.cpp" + break; + + case 63: // tableid: id +#line 354 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1833 "sqlite3_parser.cpp" + break; + + case 64: // tableid: "string literal" +#line 355 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = unquote_text(yystack_[0].value.as < std::string > (), '\''); } +#line 1839 "sqlite3_parser.cpp" + break; + + case 65: // columnid: allowed_keywords_as_identifier +#line 359 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1845 "sqlite3_parser.cpp" + break; + + case 66: // columnid: "CURRENT_TIME" +#line 360 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1851 "sqlite3_parser.cpp" + break; + + case 67: // columnid: "CURRENT_DATE" +#line 361 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1857 "sqlite3_parser.cpp" + break; + + case 68: // columnid: "CURRENT_TIMESTAMP" +#line 362 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1863 "sqlite3_parser.cpp" + break; + + case 69: // columnid: "IF" +#line 363 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1869 "sqlite3_parser.cpp" + break; + + case 70: // columnid: id +#line 364 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1875 "sqlite3_parser.cpp" + break; + + case 71: // columnid: "string literal" +#line 365 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = unquote_text(yystack_[0].value.as < std::string > (), '\''); } +#line 1881 "sqlite3_parser.cpp" + break; + + case 72: // signednumber: "+" "numeric" +#line 369 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "+" + yystack_[0].value.as < std::string > (); } +#line 1887 "sqlite3_parser.cpp" + break; + + case 73: // signednumber: "-" "numeric" +#line 370 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "-" + yystack_[0].value.as < std::string > (); } +#line 1893 "sqlite3_parser.cpp" + break; + + case 74: // signednumber_or_numeric: signednumber +#line 374 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1899 "sqlite3_parser.cpp" + break; + + case 75: // signednumber_or_numeric: "numeric" +#line 375 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1905 "sqlite3_parser.cpp" + break; + + case 76: // typename_namelist: tableid +#line 379 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1911 "sqlite3_parser.cpp" + break; + + case 77: // typename_namelist: typename_namelist tableid +#line 380 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 1917 "sqlite3_parser.cpp" + break; + + case 78: // type_name: typename_namelist +#line 384 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 1923 "sqlite3_parser.cpp" + break; + + case 79: // type_name: typename_namelist "(" signednumber_or_numeric ")" +#line 385 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + "(" + yystack_[1].value.as < std::string > () + ")"; } +#line 1929 "sqlite3_parser.cpp" + break; + + case 80: // type_name: typename_namelist "(" signednumber_or_numeric "," signednumber_or_numeric ")" +#line 386 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[5].value.as < std::string > () + "(" + yystack_[3].value.as < std::string > () + ", " + yystack_[1].value.as < std::string > () + ")"; } +#line 1935 "sqlite3_parser.cpp" + break; + + case 81: // unary_expr: "-" expr +#line 390 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "-" + yystack_[0].value.as < std::string > (); } +#line 1941 "sqlite3_parser.cpp" + break; + + case 82: // unary_expr: "+" expr +#line 391 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "+" + yystack_[0].value.as < std::string > (); } +#line 1947 "sqlite3_parser.cpp" + break; + + case 83: // unary_expr: "~" expr +#line 392 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "~" + yystack_[0].value.as < std::string > (); } +#line 1953 "sqlite3_parser.cpp" + break; + + case 84: // unary_expr: "NOT" expr +#line 393 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "NOT " + yystack_[0].value.as < std::string > (); } +#line 1959 "sqlite3_parser.cpp" + break; + + case 85: // binary_expr: expr "||" expr +#line 397 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " || " + yystack_[0].value.as < std::string > (); } +#line 1965 "sqlite3_parser.cpp" + break; + + case 86: // binary_expr: expr "*" expr +#line 398 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " * " + yystack_[0].value.as < std::string > (); } +#line 1971 "sqlite3_parser.cpp" + break; + + case 87: // binary_expr: expr "/" expr +#line 399 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " / " + yystack_[0].value.as < std::string > (); } +#line 1977 "sqlite3_parser.cpp" + break; + + case 88: // binary_expr: expr "%" expr +#line 400 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " % " + yystack_[0].value.as < std::string > (); } +#line 1983 "sqlite3_parser.cpp" + break; + + case 89: // binary_expr: expr "+" expr +#line 401 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " + " + yystack_[0].value.as < std::string > (); } +#line 1989 "sqlite3_parser.cpp" + break; + + case 90: // binary_expr: expr "-" expr +#line 402 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " - " + yystack_[0].value.as < std::string > (); } +#line 1995 "sqlite3_parser.cpp" + break; + + case 91: // binary_expr: expr "<<" expr +#line 403 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " << " + yystack_[0].value.as < std::string > (); } +#line 2001 "sqlite3_parser.cpp" + break; + + case 92: // binary_expr: expr ">>" expr +#line 404 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " >> " + yystack_[0].value.as < std::string > (); } +#line 2007 "sqlite3_parser.cpp" + break; + + case 93: // binary_expr: expr "&" expr +#line 405 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " & " + yystack_[0].value.as < std::string > (); } +#line 2013 "sqlite3_parser.cpp" + break; + + case 94: // binary_expr: expr "|" expr +#line 406 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " | " + yystack_[0].value.as < std::string > (); } +#line 2019 "sqlite3_parser.cpp" + break; + + case 95: // binary_expr: expr "<" expr +#line 407 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " < " + yystack_[0].value.as < std::string > (); } +#line 2025 "sqlite3_parser.cpp" + break; + + case 96: // binary_expr: expr "<=" expr +#line 408 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " <= " + yystack_[0].value.as < std::string > (); } +#line 2031 "sqlite3_parser.cpp" + break; + + case 97: // binary_expr: expr ">" expr +#line 409 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " > " + yystack_[0].value.as < std::string > (); } +#line 2037 "sqlite3_parser.cpp" + break; + + case 98: // binary_expr: expr ">=" expr +#line 410 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " >= " + yystack_[0].value.as < std::string > (); } +#line 2043 "sqlite3_parser.cpp" + break; + + case 99: // binary_expr: expr "=" expr +#line 411 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " = " + yystack_[0].value.as < std::string > (); } +#line 2049 "sqlite3_parser.cpp" + break; + + case 100: // binary_expr: expr "==" expr +#line 412 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " == " + yystack_[0].value.as < std::string > (); } +#line 2055 "sqlite3_parser.cpp" + break; + + case 101: // binary_expr: expr "!=" expr +#line 413 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " != " + yystack_[0].value.as < std::string > (); } +#line 2061 "sqlite3_parser.cpp" + break; + + case 102: // binary_expr: expr "<>" expr +#line 414 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " <> " + yystack_[0].value.as < std::string > (); } +#line 2067 "sqlite3_parser.cpp" + break; + + case 103: // binary_expr: expr "IS" expr +#line 415 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " IS " + yystack_[0].value.as < std::string > (); } +#line 2073 "sqlite3_parser.cpp" + break; + + case 104: // binary_expr: expr "IS" "DISTINCT" "FROM" expr +#line 416 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + " IS DISTINCT FROM " + yystack_[0].value.as < std::string > (); } +#line 2079 "sqlite3_parser.cpp" + break; + + case 105: // binary_expr: expr "IS" "NOT" "DISTINCT" "FROM" expr +#line 417 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[5].value.as < std::string > () + " IS NOT DISTINCT FROM " + yystack_[0].value.as < std::string > (); } +#line 2085 "sqlite3_parser.cpp" + break; + + case 106: // binary_expr: expr "AND" expr +#line 418 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " AND " + yystack_[0].value.as < std::string > (); } +#line 2091 "sqlite3_parser.cpp" + break; + + case 107: // binary_expr: expr "OR" expr +#line 419 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " OR " + yystack_[0].value.as < std::string > (); } +#line 2097 "sqlite3_parser.cpp" + break; + + case 108: // like_expr: expr "LIKE" expr +#line 423 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " LIKE " + yystack_[0].value.as < std::string > (); } +#line 2103 "sqlite3_parser.cpp" + break; + + case 109: // like_expr: expr "GLOB" expr +#line 424 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " GLOB " + yystack_[0].value.as < std::string > (); } +#line 2109 "sqlite3_parser.cpp" + break; + + case 110: // like_expr: expr "MATCH" expr +#line 425 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " MATCH " + yystack_[0].value.as < std::string > (); } +#line 2115 "sqlite3_parser.cpp" + break; + + case 111: // like_expr: expr "REGEXP" expr +#line 426 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " REGEXP " + yystack_[0].value.as < std::string > (); } +#line 2121 "sqlite3_parser.cpp" + break; + + case 112: // like_expr: expr "NOT" "LIKE" expr +#line 427 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " NOT LIKE " + yystack_[0].value.as < std::string > (); } +#line 2127 "sqlite3_parser.cpp" + break; + + case 113: // like_expr: expr "NOT" "GLOB" expr +#line 428 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " NOT GLOB " + yystack_[0].value.as < std::string > (); } +#line 2133 "sqlite3_parser.cpp" + break; + + case 114: // like_expr: expr "NOT" "MATCH" expr +#line 429 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " NOT MATCH " + yystack_[0].value.as < std::string > (); } +#line 2139 "sqlite3_parser.cpp" + break; + + case 115: // like_expr: expr "NOT" "REGEXP" expr +#line 430 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " NOT REGEXP " + yystack_[0].value.as < std::string > (); } +#line 2145 "sqlite3_parser.cpp" + break; + + case 116: // like_expr: expr "LIKE" expr "ESCAPE" expr +#line 431 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + " LIKE " + yystack_[2].value.as < std::string > () + " ESCAPE " + yystack_[0].value.as < std::string > (); } +#line 2151 "sqlite3_parser.cpp" + break; + + case 117: // like_expr: expr "GLOB" expr "ESCAPE" expr +#line 432 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + " GLOB " + yystack_[2].value.as < std::string > () + " ESCAPE " + yystack_[0].value.as < std::string > (); } +#line 2157 "sqlite3_parser.cpp" + break; + + case 118: // like_expr: expr "MATCH" expr "ESCAPE" expr +#line 433 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + " MATCH " + yystack_[2].value.as < std::string > () + " ESCAPE " + yystack_[0].value.as < std::string > (); } +#line 2163 "sqlite3_parser.cpp" + break; + + case 119: // like_expr: expr "REGEXP" expr "ESCAPE" expr +#line 434 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + " REGEXP " + yystack_[2].value.as < std::string > () + " ESCAPE " + yystack_[0].value.as < std::string > (); } +#line 2169 "sqlite3_parser.cpp" + break; + + case 120: // like_expr: expr "NOT" "LIKE" expr "ESCAPE" expr +#line 435 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[5].value.as < std::string > () + " NOT LIKE " + yystack_[3].value.as < std::string > () + " ESCAPE " + yystack_[0].value.as < std::string > (); } +#line 2175 "sqlite3_parser.cpp" + break; + + case 121: // like_expr: expr "NOT" "GLOB" expr "ESCAPE" expr +#line 436 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[5].value.as < std::string > () + " NOT GLOB " + yystack_[3].value.as < std::string > () + " ESCAPE " + yystack_[0].value.as < std::string > (); } +#line 2181 "sqlite3_parser.cpp" + break; + + case 122: // like_expr: expr "NOT" "MATCH" expr "ESCAPE" expr +#line 437 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[5].value.as < std::string > () + " NOT MATCH " + yystack_[3].value.as < std::string > () + " ESCAPE " + yystack_[0].value.as < std::string > (); } +#line 2187 "sqlite3_parser.cpp" + break; + + case 123: // like_expr: expr "NOT" "REGEXP" expr "ESCAPE" expr +#line 438 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[5].value.as < std::string > () + " NOT REGEXP " + yystack_[3].value.as < std::string > () + " ESCAPE " + yystack_[0].value.as < std::string > (); } +#line 2193 "sqlite3_parser.cpp" + break; + + case 124: // exprlist_expr: expr +#line 442 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2199 "sqlite3_parser.cpp" + break; + + case 125: // exprlist_expr: exprlist_expr "," expr +#line 443 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + ", " + yystack_[0].value.as < std::string > (); } +#line 2205 "sqlite3_parser.cpp" + break; + + case 126: // function_expr: id "(" exprlist_expr ")" +#line 447 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + "(" + yystack_[1].value.as < std::string > () + ")"; } +#line 2211 "sqlite3_parser.cpp" + break; + + case 127: // function_expr: id "(" "DISTINCT" exprlist_expr ")" +#line 448 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + "(DISTINCT " + yystack_[1].value.as < std::string > () + ")"; } +#line 2217 "sqlite3_parser.cpp" + break; + + case 128: // function_expr: id "(" ")" +#line 449 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + "()"; } +#line 2223 "sqlite3_parser.cpp" + break; + + case 129: // function_expr: id "(" "*" ")" +#line 450 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + "(*)"; } +#line 2229 "sqlite3_parser.cpp" + break; + + case 130: // isnull_expr: expr "ISNULL" +#line 454 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[1].value.as < std::string > () + " ISNULL"; } +#line 2235 "sqlite3_parser.cpp" + break; + + case 131: // isnull_expr: expr "NOTNULL" +#line 455 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[1].value.as < std::string > () + " NOTNULL"; } +#line 2241 "sqlite3_parser.cpp" + break; + + case 132: // isnull_expr: expr "NOT" "NULL" +#line 456 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " NOT NULL"; } +#line 2247 "sqlite3_parser.cpp" + break; + + case 133: // between_expr: expr "BETWEEN" expr "AND BETWEEN" expr +#line 460 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + " BETWEEN " + yystack_[2].value.as < std::string > () + " AND " + yystack_[0].value.as < std::string > (); } +#line 2253 "sqlite3_parser.cpp" + break; + + case 134: // between_expr: expr "NOT" "BETWEEN" expr "AND BETWEEN" expr +#line 461 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[5].value.as < std::string > () + " NOT BETWEEN " + yystack_[2].value.as < std::string > () + " AND " + yystack_[0].value.as < std::string > (); } +#line 2259 "sqlite3_parser.cpp" + break; + + case 135: // in_expr: expr "IN" "(" ")" +#line 465 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " IN ()"; } +#line 2265 "sqlite3_parser.cpp" + break; + + case 136: // in_expr: expr "IN" "(" select_stmt ")" +#line 466 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + " IN (" + yystack_[1].value.as < std::string > () + ")"; } +#line 2271 "sqlite3_parser.cpp" + break; + + case 137: // in_expr: expr "IN" "(" exprlist_expr ")" +#line 467 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + " IN (" + yystack_[1].value.as < std::string > () + ")"; } +#line 2277 "sqlite3_parser.cpp" + break; + + case 138: // in_expr: expr "IN" id "." tableid +#line 468 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + " IN " + sqlb::escapeIdentifier(yystack_[2].value.as < std::string > ()) + "." + sqlb::escapeIdentifier(yystack_[0].value.as < std::string > ()); } +#line 2283 "sqlite3_parser.cpp" + break; + + case 139: // in_expr: expr "IN" tableid +#line 469 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " IN " + sqlb::escapeIdentifier(yystack_[0].value.as < std::string > ()); } +#line 2289 "sqlite3_parser.cpp" + break; + + case 140: // in_expr: expr "IN" id "." id "(" ")" +#line 470 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[6].value.as < std::string > () + " IN " + sqlb::escapeIdentifier(yystack_[4].value.as < std::string > ()) + "." + yystack_[2].value.as < std::string > () + "()"; } +#line 2295 "sqlite3_parser.cpp" + break; + + case 141: // in_expr: expr "IN" id "." id "(" exprlist_expr ")" +#line 471 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[7].value.as < std::string > () + " IN " + sqlb::escapeIdentifier(yystack_[5].value.as < std::string > ()) + "." + yystack_[3].value.as < std::string > () + "(" + yystack_[1].value.as < std::string > () + ")"; } +#line 2301 "sqlite3_parser.cpp" + break; + + case 142: // in_expr: expr "IN" id "(" exprlist_expr ")" +#line 472 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[5].value.as < std::string > () + " IN " + yystack_[3].value.as < std::string > () + "(" + yystack_[1].value.as < std::string > () + ")"; } +#line 2307 "sqlite3_parser.cpp" + break; + + case 143: // in_expr: expr "NOT" "IN" "(" ")" +#line 473 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + " NOT IN ()"; } +#line 2313 "sqlite3_parser.cpp" + break; + + case 144: // in_expr: expr "NOT" "IN" "(" select_stmt ")" +#line 474 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[5].value.as < std::string > () + " NOT IN (" + yystack_[1].value.as < std::string > () + ")"; } +#line 2319 "sqlite3_parser.cpp" + break; + + case 145: // in_expr: expr "NOT" "IN" "(" exprlist_expr ")" +#line 475 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[5].value.as < std::string > () + " NOT IN (" + yystack_[1].value.as < std::string > () + ")"; } +#line 2325 "sqlite3_parser.cpp" + break; + + case 146: // in_expr: expr "NOT" "IN" id "." tableid +#line 476 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[5].value.as < std::string > () + " NOT IN " + sqlb::escapeIdentifier(yystack_[2].value.as < std::string > ()) + "." + sqlb::escapeIdentifier(yystack_[0].value.as < std::string > ()); } +#line 2331 "sqlite3_parser.cpp" + break; + + case 147: // in_expr: expr "NOT" "IN" tableid +#line 477 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " NOT IN " + sqlb::escapeIdentifier(yystack_[0].value.as < std::string > ()); } +#line 2337 "sqlite3_parser.cpp" + break; + + case 148: // in_expr: expr "NOT" "IN" id "." id "(" ")" +#line 478 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[7].value.as < std::string > () + " NOT IN " + sqlb::escapeIdentifier(yystack_[4].value.as < std::string > ()) + "." + yystack_[2].value.as < std::string > () + "()"; } +#line 2343 "sqlite3_parser.cpp" + break; + + case 149: // in_expr: expr "NOT" "IN" id "." id "(" exprlist_expr ")" +#line 479 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[8].value.as < std::string > () + " NOT IN " + sqlb::escapeIdentifier(yystack_[5].value.as < std::string > ()) + "." + yystack_[3].value.as < std::string > () + "(" + yystack_[1].value.as < std::string > () + ")"; } +#line 2349 "sqlite3_parser.cpp" + break; + + case 150: // in_expr: expr "NOT" "IN" id "(" exprlist_expr ")" +#line 480 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[6].value.as < std::string > () + " NOT IN " + yystack_[3].value.as < std::string > () + "(" + yystack_[1].value.as < std::string > () + ")"; } +#line 2355 "sqlite3_parser.cpp" + break; + + case 151: // whenthenlist_expr: "WHEN" expr "THEN" expr +#line 484 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "WHEN " + yystack_[2].value.as < std::string > () + " THEN " + yystack_[0].value.as < std::string > (); } +#line 2361 "sqlite3_parser.cpp" + break; + + case 152: // whenthenlist_expr: whenthenlist_expr "WHEN" expr "THEN" expr +#line 485 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + " WHEN" + yystack_[2].value.as < std::string > () + " THEN " + yystack_[0].value.as < std::string > (); } +#line 2367 "sqlite3_parser.cpp" + break; + + case 153: // case_expr: "CASE" expr whenthenlist_expr "ELSE" expr "END" +#line 489 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "CASE " + yystack_[4].value.as < std::string > () + " " + yystack_[3].value.as < std::string > () + " ELSE " + yystack_[1].value.as < std::string > () + " END"; } +#line 2373 "sqlite3_parser.cpp" + break; + + case 154: // case_expr: "CASE" expr whenthenlist_expr "END" +#line 490 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "CASE " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " END"; } +#line 2379 "sqlite3_parser.cpp" + break; + + case 155: // case_expr: "CASE" whenthenlist_expr "ELSE" expr "END" +#line 491 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "CASE " + yystack_[3].value.as < std::string > () + " ELSE " + yystack_[1].value.as < std::string > () + " END"; } +#line 2385 "sqlite3_parser.cpp" + break; + + case 156: // case_expr: "CASE" whenthenlist_expr "END" +#line 492 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "CASE " + yystack_[1].value.as < std::string > () + " END"; } +#line 2391 "sqlite3_parser.cpp" + break; + + case 157: // raise_expr: "RAISE" "(" "IGNORE" ")" +#line 496 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "RAISE(IGNORE)"; } +#line 2397 "sqlite3_parser.cpp" + break; + + case 158: // raise_expr: "RAISE" "(" "ROLLBACK" "," "string literal" ")" +#line 497 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "RAISE(ROLLBACK, " + yystack_[1].value.as < std::string > () + ")"; } +#line 2403 "sqlite3_parser.cpp" + break; + + case 159: // raise_expr: "RAISE" "(" "ABORT" "," "string literal" ")" +#line 498 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "RAISE(ABORT, " + yystack_[1].value.as < std::string > () + ")"; } +#line 2409 "sqlite3_parser.cpp" + break; + + case 160: // raise_expr: "RAISE" "(" "FAIL" "," "string literal" ")" +#line 499 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "RAISE(FAIL, " + yystack_[1].value.as < std::string > () + ")"; } +#line 2415 "sqlite3_parser.cpp" + break; + + case 161: // expr: literalvalue +#line 503 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2421 "sqlite3_parser.cpp" + break; + + case 162: // expr: allowed_keywords_as_identifier +#line 504 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = sqlb::escapeIdentifier(yystack_[0].value.as < std::string > ()); } +#line 2427 "sqlite3_parser.cpp" + break; + + case 163: // expr: "bind parameter" +#line 505 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2433 "sqlite3_parser.cpp" + break; + + case 164: // expr: id "." id "." id +#line 506 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = sqlb::escapeIdentifier(yystack_[4].value.as < std::string > ()) + "." + sqlb::escapeIdentifier(yystack_[2].value.as < std::string > ()) + "." + sqlb::escapeIdentifier(yystack_[0].value.as < std::string > ()); } +#line 2439 "sqlite3_parser.cpp" + break; + + case 165: // expr: id "." id +#line 507 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = sqlb::escapeIdentifier(yystack_[2].value.as < std::string > ()) + "." + sqlb::escapeIdentifier(yystack_[0].value.as < std::string > ()); } +#line 2445 "sqlite3_parser.cpp" + break; + + case 166: // expr: id +#line 508 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = sqlb::escapeIdentifier(yystack_[0].value.as < std::string > ()); } +#line 2451 "sqlite3_parser.cpp" + break; + + case 167: // expr: unary_expr +#line 509 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2457 "sqlite3_parser.cpp" + break; + + case 168: // expr: binary_expr +#line 510 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2463 "sqlite3_parser.cpp" + break; + + case 169: // expr: function_expr +#line 511 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2469 "sqlite3_parser.cpp" + break; + + case 170: // expr: "(" exprlist_expr ")" +#line 512 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "(" + yystack_[1].value.as < std::string > () + ")"; } +#line 2475 "sqlite3_parser.cpp" + break; + + case 171: // expr: "CAST" "(" expr "AS" type_name ")" +#line 513 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "CAST(" + yystack_[3].value.as < std::string > () + " AS " + yystack_[1].value.as < std::string > () + ")"; } +#line 2481 "sqlite3_parser.cpp" + break; + + case 172: // expr: expr "COLLATE" id +#line 514 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " COLLATE " + yystack_[0].value.as < std::string > (); } +#line 2487 "sqlite3_parser.cpp" + break; + + case 173: // expr: like_expr +#line 515 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2493 "sqlite3_parser.cpp" + break; + + case 174: // expr: isnull_expr +#line 516 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2499 "sqlite3_parser.cpp" + break; + + case 175: // expr: between_expr +#line 517 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2505 "sqlite3_parser.cpp" + break; + + case 176: // expr: in_expr +#line 518 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2511 "sqlite3_parser.cpp" + break; + + case 177: // expr: case_expr +#line 519 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2517 "sqlite3_parser.cpp" + break; + + case 178: // expr: raise_expr +#line 520 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2523 "sqlite3_parser.cpp" + break; + + case 179: // select_stmt: "SELECT" +#line 529 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "SELECT"; } +#line 2529 "sqlite3_parser.cpp" + break; + + case 180: // optional_if_not_exists: %empty +#line 537 "sqlite3_parser.yy" + { yylhs.value.as < bool > () = false; } +#line 2535 "sqlite3_parser.cpp" + break; + + case 181: // optional_if_not_exists: "IF" "NOT" "EXISTS" +#line 538 "sqlite3_parser.yy" + { yylhs.value.as < bool > () = true; } +#line 2541 "sqlite3_parser.cpp" + break; + + case 182: // optional_sort_order: %empty +#line 542 "sqlite3_parser.yy" + { } +#line 2547 "sqlite3_parser.cpp" + break; + + case 183: // optional_sort_order: "ASC" +#line 543 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "ASC"; } +#line 2553 "sqlite3_parser.cpp" + break; + + case 184: // optional_sort_order: "DESC" +#line 544 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "DESC"; } +#line 2559 "sqlite3_parser.cpp" + break; + + case 185: // optional_unique: %empty +#line 552 "sqlite3_parser.yy" + { yylhs.value.as < bool > () = false; } +#line 2565 "sqlite3_parser.cpp" + break; + + case 186: // optional_unique: "UNIQUE" +#line 553 "sqlite3_parser.yy" + { yylhs.value.as < bool > () = true; } +#line 2571 "sqlite3_parser.cpp" + break; + + case 187: // optional_where: %empty +#line 557 "sqlite3_parser.yy" + { } +#line 2577 "sqlite3_parser.cpp" + break; + + case 188: // optional_where: "WHERE" expr +#line 558 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2583 "sqlite3_parser.cpp" + break; + + case 189: // tableid_with_uninteresting_schema: id "." tableid +#line 562 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2589 "sqlite3_parser.cpp" + break; + + case 190: // tableid_with_uninteresting_schema: "TEMP" "." tableid +#line 563 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2595 "sqlite3_parser.cpp" + break; + + case 191: // tableid_with_uninteresting_schema: tableid +#line 564 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2601 "sqlite3_parser.cpp" + break; + + case 192: // indexed_column: expr optional_sort_order +#line 568 "sqlite3_parser.yy" + { + // If the expression is only one column name and nothing else, treat it as a column name; otherwise as an expression. + char quote = getIdentifierQuoteChar(); + if((quote == '[' && std::count(yystack_[1].value.as < std::string > ().begin(), yystack_[1].value.as < std::string > ().end(), quote) == 1 && yystack_[1].value.as < std::string > ().front() == '[' && yystack_[1].value.as < std::string > ().back() == ']') || + (quote != '[' && std::count(yystack_[1].value.as < std::string > ().begin(), yystack_[1].value.as < std::string > ().end(), quote) == 2 && yystack_[1].value.as < std::string > ().front() == quote && yystack_[1].value.as < std::string > ().back() == quote)) + { + yylhs.value.as < sqlb::IndexedColumn > () = sqlb::IndexedColumn(unquote_text(yystack_[1].value.as < std::string > (), quote), false, yystack_[0].value.as < std::string > ()); + } else if(std::count(yystack_[1].value.as < std::string > ().begin(), yystack_[1].value.as < std::string > ().end(), '\'') == 2 && yystack_[1].value.as < std::string > ().front() == '\'' && yystack_[1].value.as < std::string > ().back() == '\'') { + // Also remove single quotes when this actually is a string literal but looks like a columnid + yylhs.value.as < sqlb::IndexedColumn > () = sqlb::IndexedColumn(unquote_text(yystack_[1].value.as < std::string > (), '\''), false, yystack_[0].value.as < std::string > ()); + } else { + yylhs.value.as < sqlb::IndexedColumn > () = sqlb::IndexedColumn(yystack_[1].value.as < std::string > (), true, yystack_[0].value.as < std::string > ()); + } + } +#line 2620 "sqlite3_parser.cpp" + break; + + case 193: // indexed_column_list: indexed_column +#line 585 "sqlite3_parser.yy" + { yylhs.value.as < sqlb::IndexedColumnVector > () = sqlb::IndexedColumnVector(1, yystack_[0].value.as < sqlb::IndexedColumn > ()); } +#line 2626 "sqlite3_parser.cpp" + break; + + case 194: // indexed_column_list: indexed_column_list "," indexed_column +#line 586 "sqlite3_parser.yy" + { yylhs.value.as < sqlb::IndexedColumnVector > () = yystack_[2].value.as < sqlb::IndexedColumnVector > (); yylhs.value.as < sqlb::IndexedColumnVector > ().push_back(yystack_[0].value.as < sqlb::IndexedColumn > ()); } +#line 2632 "sqlite3_parser.cpp" + break; + + case 195: // createindex_stmt: "CREATE" optional_unique "INDEX" optional_if_not_exists tableid_with_uninteresting_schema "ON" tableid "(" indexed_column_list ")" optional_where +#line 590 "sqlite3_parser.yy" + { + yylhs.value.as < sqlb::IndexPtr > () = std::make_shared(yystack_[6].value.as < std::string > ()); + yylhs.value.as < sqlb::IndexPtr > ()->setTable(yystack_[4].value.as < std::string > ()); + yylhs.value.as < sqlb::IndexPtr > ()->setUnique(yystack_[9].value.as < bool > ()); + yylhs.value.as < sqlb::IndexPtr > ()->setWhereExpr(yystack_[0].value.as < std::string > ()); + yylhs.value.as < sqlb::IndexPtr > ()->fields = yystack_[2].value.as < sqlb::IndexedColumnVector > (); + yylhs.value.as < sqlb::IndexPtr > ()->setFullyParsed(true); + } +#line 2645 "sqlite3_parser.cpp" + break; + + case 196: // optional_exprlist_with_paren: %empty +#line 605 "sqlite3_parser.yy" + { } +#line 2651 "sqlite3_parser.cpp" + break; + + case 197: // optional_exprlist_with_paren: "(" ")" +#line 606 "sqlite3_parser.yy" + { } +#line 2657 "sqlite3_parser.cpp" + break; + + case 198: // optional_exprlist_with_paren: "(" exprlist_expr ")" +#line 607 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[1].value.as < std::string > (); } +#line 2663 "sqlite3_parser.cpp" + break; + + case 199: // createvirtualtable_stmt: "CREATE" "VIRTUAL" "TABLE" optional_if_not_exists tableid_with_uninteresting_schema "USING" id optional_exprlist_with_paren +#line 611 "sqlite3_parser.yy" + { + yylhs.value.as < sqlb::TablePtr > () = std::make_shared(yystack_[3].value.as < std::string > ()); + yylhs.value.as < sqlb::TablePtr > ()->setVirtualUsing(yystack_[1].value.as < std::string > ()); + yylhs.value.as < sqlb::TablePtr > ()->setFullyParsed(false); + } +#line 2673 "sqlite3_parser.cpp" + break; + + case 200: // optional_temporary: %empty +#line 623 "sqlite3_parser.yy" + { yylhs.value.as < bool > () = false; } +#line 2679 "sqlite3_parser.cpp" + break; + + case 201: // optional_temporary: "TEMP" +#line 624 "sqlite3_parser.yy" + { yylhs.value.as < bool > () = true; } +#line 2685 "sqlite3_parser.cpp" + break; + + case 202: // optional_temporary: "TEMPORARY" +#line 625 "sqlite3_parser.yy" + { yylhs.value.as < bool > () = true; } +#line 2691 "sqlite3_parser.cpp" + break; + + case 203: // tableoption: "WITHOUT" "ROWID" +#line 629 "sqlite3_parser.yy" + { yylhs.value.as < std::bitset > ().set(sqlb::Table::WithoutRowid, true); } +#line 2697 "sqlite3_parser.cpp" + break; + + case 204: // tableoption: "STRICT" +#line 630 "sqlite3_parser.yy" + { yylhs.value.as < std::bitset > ().set(sqlb::Table::Strict, true); } +#line 2703 "sqlite3_parser.cpp" + break; + + case 205: // tableoptions_list: tableoption +#line 634 "sqlite3_parser.yy" + { yylhs.value.as < std::bitset > () = yystack_[0].value.as < std::bitset > (); } +#line 2709 "sqlite3_parser.cpp" + break; + + case 206: // tableoptions_list: tableoptions_list "," tableoption +#line 635 "sqlite3_parser.yy" + { yylhs.value.as < std::bitset > () = yystack_[2].value.as < std::bitset > () | yystack_[0].value.as < std::bitset > (); } +#line 2715 "sqlite3_parser.cpp" + break; + + case 207: // tableoptions_list: tableoptions_list tableoption +#line 636 "sqlite3_parser.yy" + { yylhs.value.as < std::bitset > () = yystack_[1].value.as < std::bitset > () | yystack_[0].value.as < std::bitset > (); } +#line 2721 "sqlite3_parser.cpp" + break; + + case 208: // optional_tableoptions_list: %empty +#line 640 "sqlite3_parser.yy" + { } +#line 2727 "sqlite3_parser.cpp" + break; + + case 209: // optional_tableoptions_list: tableoptions_list +#line 641 "sqlite3_parser.yy" + { yylhs.value.as < std::bitset > () = yystack_[0].value.as < std::bitset > (); } +#line 2733 "sqlite3_parser.cpp" + break; + + case 210: // optional_conflictclause: %empty +#line 645 "sqlite3_parser.yy" + { } +#line 2739 "sqlite3_parser.cpp" + break; + + case 211: // optional_conflictclause: "ON" "CONFLICT" "ROLLBACK" +#line 646 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2745 "sqlite3_parser.cpp" + break; + + case 212: // optional_conflictclause: "ON" "CONFLICT" "ABORT" +#line 647 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2751 "sqlite3_parser.cpp" + break; + + case 213: // optional_conflictclause: "ON" "CONFLICT" "FAIL" +#line 648 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2757 "sqlite3_parser.cpp" + break; + + case 214: // optional_conflictclause: "ON" "CONFLICT" "IGNORE" +#line 649 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2763 "sqlite3_parser.cpp" + break; + + case 215: // optional_conflictclause: "ON" "CONFLICT" "REPLACE" +#line 650 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2769 "sqlite3_parser.cpp" + break; + + case 216: // optional_typename: %empty +#line 654 "sqlite3_parser.yy" + { } +#line 2775 "sqlite3_parser.cpp" + break; + + case 217: // optional_typename: type_name +#line 655 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 2781 "sqlite3_parser.cpp" + break; + + case 218: // optional_storage_identifier: %empty +#line 659 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "VIRTUAL"; } +#line 2787 "sqlite3_parser.cpp" + break; + + case 219: // optional_storage_identifier: "STORED" +#line 660 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "STORED"; } +#line 2793 "sqlite3_parser.cpp" + break; + + case 220: // optional_storage_identifier: "VIRTUAL" +#line 661 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = "VIRTUAL"; } +#line 2799 "sqlite3_parser.cpp" + break; + + case 221: // optional_always_generated: %empty +#line 665 "sqlite3_parser.yy" + { yylhs.value.as < bool > () = false; } +#line 2805 "sqlite3_parser.cpp" + break; + + case 222: // optional_always_generated: "GENERATED" "ALWAYS" +#line 666 "sqlite3_parser.yy" + { yylhs.value.as < bool > () = true; } +#line 2811 "sqlite3_parser.cpp" + break; + + case 223: // columnconstraint: optional_constraintname "PRIMARY" "KEY" optional_sort_order optional_conflictclause +#line 670 "sqlite3_parser.yy" + { + auto pk = std::make_shared(); + pk->setName(yystack_[4].value.as < std::string > ()); + pk->setConflictAction(yystack_[0].value.as < std::string > ()); + yylhs.value.as < std::pair, std::shared_ptr> > ().first = pk; + } +#line 2822 "sqlite3_parser.cpp" + break; + + case 224: // columnconstraint: optional_constraintname "PRIMARY" "KEY" optional_sort_order optional_conflictclause "AUTOINCREMENT" +#line 676 "sqlite3_parser.yy" + { + auto pk = std::make_shared(); + pk->setName(yystack_[5].value.as < std::string > ()); + pk->setConflictAction(yystack_[1].value.as < std::string > ()); + pk->setAutoIncrement(true); + yylhs.value.as < std::pair, std::shared_ptr> > ().first = pk; + } +#line 2834 "sqlite3_parser.cpp" + break; + + case 225: // columnconstraint: optional_constraintname "NOT" "NULL" optional_conflictclause +#line 683 "sqlite3_parser.yy" + { + auto nn = std::make_shared(); + nn->setName(yystack_[3].value.as < std::string > ()); + nn->setConflictAction(yystack_[0].value.as < std::string > ()); + drv.last_table_column->setNotNull(nn); + } +#line 2845 "sqlite3_parser.cpp" + break; + + case 226: // columnconstraint: optional_constraintname "NULL" +#line 689 "sqlite3_parser.yy" + { + } +#line 2852 "sqlite3_parser.cpp" + break; + + case 227: // columnconstraint: optional_constraintname "UNIQUE" optional_conflictclause +#line 691 "sqlite3_parser.yy" + { + auto u = std::make_shared(); + u->setName(yystack_[2].value.as < std::string > ()); + u->setConflictAction(yystack_[0].value.as < std::string > ()); + drv.last_table_column->setUnique(u); + } +#line 2863 "sqlite3_parser.cpp" + break; + + case 228: // columnconstraint: optional_constraintname "CHECK" "(" expr ")" +#line 697 "sqlite3_parser.yy" + { + auto c = std::make_shared(yystack_[1].value.as < std::string > ()); + c->setName(yystack_[4].value.as < std::string > ()); + drv.last_table_column->setCheck(c); + } +#line 2873 "sqlite3_parser.cpp" + break; + + case 229: // columnconstraint: optional_constraintname "DEFAULT" signednumber +#line 702 "sqlite3_parser.yy" + { + auto d = std::make_shared(yystack_[0].value.as < std::string > ()); + d->setName(yystack_[2].value.as < std::string > ()); + drv.last_table_column->setDefaultValue(d); + } +#line 2883 "sqlite3_parser.cpp" + break; + + case 230: // columnconstraint: optional_constraintname "DEFAULT" literalvalue +#line 707 "sqlite3_parser.yy" + { + auto d = std::make_shared(yystack_[0].value.as < std::string > ()); + d->setName(yystack_[2].value.as < std::string > ()); + drv.last_table_column->setDefaultValue(d); + } +#line 2893 "sqlite3_parser.cpp" + break; + + case 231: // columnconstraint: optional_constraintname "DEFAULT" id +#line 712 "sqlite3_parser.yy" + { + auto d = std::make_shared(yystack_[0].value.as < std::string > ()); + d->setName(yystack_[2].value.as < std::string > ()); + drv.last_table_column->setDefaultValue(d); + } +#line 2903 "sqlite3_parser.cpp" + break; + + case 232: // columnconstraint: optional_constraintname "DEFAULT" allowed_keywords_as_identifier +#line 717 "sqlite3_parser.yy" + { // We must allow the same keywords as unquoted default values as in the columnid context. + // But we do not use columnid here in order to avoid reduce/reduce conflicts. + auto d = std::make_shared(yystack_[0].value.as < std::string > ()); + d->setName(yystack_[2].value.as < std::string > ()); + drv.last_table_column->setDefaultValue(d); + } +#line 2914 "sqlite3_parser.cpp" + break; + + case 233: // columnconstraint: optional_constraintname "DEFAULT" "IF" +#line 723 "sqlite3_parser.yy" + { // Same as above. + auto d = std::make_shared(yystack_[0].value.as < std::string > ()); + d->setName(yystack_[2].value.as < std::string > ()); + drv.last_table_column->setDefaultValue(d); + } +#line 2924 "sqlite3_parser.cpp" + break; + + case 234: // columnconstraint: optional_constraintname "DEFAULT" "(" expr ")" +#line 728 "sqlite3_parser.yy" + { + auto d = std::make_shared("(" + yystack_[1].value.as < std::string > () + ")"); + d->setName(yystack_[4].value.as < std::string > ()); + drv.last_table_column->setDefaultValue(d); + } +#line 2934 "sqlite3_parser.cpp" + break; + + case 235: // columnconstraint: optional_constraintname "COLLATE" id +#line 733 "sqlite3_parser.yy" + { + auto c = std::make_shared(yystack_[0].value.as < std::string > ()); + c->setName(yystack_[2].value.as < std::string > ()); + drv.last_table_column->setCollation(c); + } +#line 2944 "sqlite3_parser.cpp" + break; + + case 236: // columnconstraint: optional_constraintname "REFERENCES" tableid optional_columnid_with_paren_list optional_fk_clause +#line 738 "sqlite3_parser.yy" + { // TODO Solve shift/reduce conflict. It is not super important though as shifting seems to be right here. + auto fk = std::make_shared(); + fk->setName(yystack_[4].value.as < std::string > ()); + fk->setTable(yystack_[2].value.as < std::string > ()); + fk->setColumns(yystack_[1].value.as < sqlb::StringVector > ()); + fk->setConstraint(yystack_[0].value.as < std::string > ()); + yylhs.value.as < std::pair, std::shared_ptr> > ().second = fk; + } +#line 2957 "sqlite3_parser.cpp" + break; + + case 237: // columnconstraint: optional_constraintname optional_always_generated "AS" "(" expr ")" optional_storage_identifier +#line 746 "sqlite3_parser.yy" + { // TODO Solve shift/reduce conflict. + auto g = std::make_shared(yystack_[2].value.as < std::string > (), yystack_[0].value.as < std::string > ()); + g->setName(yystack_[6].value.as < std::string > ()); + + drv.last_table_column->setGenerated(g); + + // This is a hack which removes any "GENERATED ALWAYS" from the end of the type name. + // As of now these are shifted to the type instead of reducing the type when seeing the GENERATED identifier. + // TODO Remove this once the grammar is conflict free + const std::string generated_always = "GENERATED ALWAYS"; + if(drv.last_table_column->type().size() >= generated_always.size() && drv.last_table_column->type().compare(drv.last_table_column->type().size() - generated_always.size(), generated_always.size(), generated_always) == 0) + { + std::string type = drv.last_table_column->type().substr(0, drv.last_table_column->type().size()-generated_always.size()); + if(type.back() == ' ') + type.pop_back(); + drv.last_table_column->setType(type); + } + } +#line 2980 "sqlite3_parser.cpp" + break; + + case 238: // columnconstraint_list: %empty +#line 767 "sqlite3_parser.yy" + { } +#line 2986 "sqlite3_parser.cpp" + break; + + case 239: // columnconstraint_list: columnconstraint_list columnconstraint +#line 768 "sqlite3_parser.yy" + { + yylhs.value.as < TableConstraints > () = yystack_[1].value.as < TableConstraints > (); + + // Primary key and foreign key constraints are converted to table constraints + // because we cannot store them as column constraints at the moment. + if(yystack_[0].value.as < std::pair, std::shared_ptr> > ().first) + yylhs.value.as < TableConstraints > ().index.insert(std::make_pair(sqlb::IndexedColumnVector{sqlb::IndexedColumn(drv.last_table_column->name(), false)}, yystack_[0].value.as < std::pair, std::shared_ptr> > ().first)); + if(yystack_[0].value.as < std::pair, std::shared_ptr> > ().second) + yylhs.value.as < TableConstraints > ().fk.insert(std::make_pair(sqlb::StringVector{drv.last_table_column->name()}, yystack_[0].value.as < std::pair, std::shared_ptr> > ().second)); + } +#line 3001 "sqlite3_parser.cpp" + break; + + case 240: // columndef: columnid optional_typename +#line 781 "sqlite3_parser.yy" + { yylhs.value.as < std::shared_ptr > () = std::make_shared(yystack_[1].value.as < std::string > (), yystack_[0].value.as < std::string > ()); drv.last_table_column = yylhs.value.as < std::shared_ptr > (); } +#line 3007 "sqlite3_parser.cpp" + break; + + case 241: // columndef_list: columndef columnconstraint_list +#line 785 "sqlite3_parser.yy" + { yylhs.value.as < ColumnList > ().first.push_back(yystack_[1].value.as < std::shared_ptr > ()); yylhs.value.as < ColumnList > ().second = yystack_[0].value.as < TableConstraints > (); } +#line 3013 "sqlite3_parser.cpp" + break; + + case 242: // columndef_list: columndef_list "," columndef columnconstraint_list +#line 786 "sqlite3_parser.yy" + { yylhs.value.as < ColumnList > () = yystack_[3].value.as < ColumnList > (); yylhs.value.as < ColumnList > ().first.push_back(yystack_[1].value.as < std::shared_ptr > ()); yylhs.value.as < ColumnList > ().second.index.insert(yystack_[0].value.as < TableConstraints > ().index.begin(), yystack_[0].value.as < TableConstraints > ().index.end()); yylhs.value.as < ColumnList > ().second.fk.insert(yystack_[0].value.as < TableConstraints > ().fk.begin(), yystack_[0].value.as < TableConstraints > ().fk.end()); } +#line 3019 "sqlite3_parser.cpp" + break; + + case 243: // optional_constraintname: %empty +#line 790 "sqlite3_parser.yy" + { } +#line 3025 "sqlite3_parser.cpp" + break; + + case 244: // optional_constraintname: "CONSTRAINT" id +#line 791 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 3031 "sqlite3_parser.cpp" + break; + + case 245: // optional_constraintname: "CONSTRAINT" "string literal" +#line 792 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 3037 "sqlite3_parser.cpp" + break; + + case 246: // columnid_list: columnid +#line 796 "sqlite3_parser.yy" + { yylhs.value.as < sqlb::StringVector > () = sqlb::StringVector(1, yystack_[0].value.as < std::string > ()); } +#line 3043 "sqlite3_parser.cpp" + break; + + case 247: // columnid_list: columnid_list "," columnid +#line 797 "sqlite3_parser.yy" + { yylhs.value.as < sqlb::StringVector > () = yystack_[2].value.as < sqlb::StringVector > (); yylhs.value.as < sqlb::StringVector > ().push_back(yystack_[0].value.as < std::string > ()); } +#line 3049 "sqlite3_parser.cpp" + break; + + case 248: // optional_columnid_with_paren_list: %empty +#line 801 "sqlite3_parser.yy" + { } +#line 3055 "sqlite3_parser.cpp" + break; + + case 249: // optional_columnid_with_paren_list: "(" columnid_list ")" +#line 802 "sqlite3_parser.yy" + { yylhs.value.as < sqlb::StringVector > () = yystack_[1].value.as < sqlb::StringVector > (); } +#line 3061 "sqlite3_parser.cpp" + break; + + case 250: // fk_clause_part: "ON" "DELETE" "SET" "NULL" +#line 806 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3067 "sqlite3_parser.cpp" + break; + + case 251: // fk_clause_part: "ON" "DELETE" "SET" "DEFAULT" +#line 807 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3073 "sqlite3_parser.cpp" + break; + + case 252: // fk_clause_part: "ON" "DELETE" "CASCADE" +#line 808 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3079 "sqlite3_parser.cpp" + break; + + case 253: // fk_clause_part: "ON" "DELETE" "RESTRICT" +#line 809 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3085 "sqlite3_parser.cpp" + break; + + case 254: // fk_clause_part: "ON" "DELETE" "NO" "ACTION" +#line 810 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3091 "sqlite3_parser.cpp" + break; + + case 255: // fk_clause_part: "ON" "UPDATE" "SET" "NULL" +#line 811 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3097 "sqlite3_parser.cpp" + break; + + case 256: // fk_clause_part: "ON" "UPDATE" "SET" "DEFAULT" +#line 812 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3103 "sqlite3_parser.cpp" + break; + + case 257: // fk_clause_part: "ON" "UPDATE" "CASCADE" +#line 813 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3109 "sqlite3_parser.cpp" + break; + + case 258: // fk_clause_part: "ON" "UPDATE" "RESTRICT" +#line 814 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3115 "sqlite3_parser.cpp" + break; + + case 259: // fk_clause_part: "ON" "UPDATE" "NO" "ACTION" +#line 815 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3121 "sqlite3_parser.cpp" + break; + + case 260: // fk_clause_part: "ON" "INSERT" "SET" "NULL" +#line 816 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3127 "sqlite3_parser.cpp" + break; + + case 261: // fk_clause_part: "ON" "INSERT" "SET" "DEFAULT" +#line 817 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3133 "sqlite3_parser.cpp" + break; + + case 262: // fk_clause_part: "ON" "INSERT" "CASCADE" +#line 818 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3139 "sqlite3_parser.cpp" + break; + + case 263: // fk_clause_part: "ON" "INSERT" "RESTRICT" +#line 819 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3145 "sqlite3_parser.cpp" + break; + + case 264: // fk_clause_part: "ON" "INSERT" "NO" "ACTION" +#line 820 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3151 "sqlite3_parser.cpp" + break; + + case 265: // fk_clause_part: "MATCH" id +#line 821 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3157 "sqlite3_parser.cpp" + break; + + case 266: // fk_clause_part_list: fk_clause_part +#line 825 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 3163 "sqlite3_parser.cpp" + break; + + case 267: // fk_clause_part_list: fk_clause_part_list fk_clause_part +#line 826 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3169 "sqlite3_parser.cpp" + break; + + case 268: // optional_fk_clause: %empty +#line 830 "sqlite3_parser.yy" + { } +#line 3175 "sqlite3_parser.cpp" + break; + + case 269: // optional_fk_clause: fk_clause_part_list +#line 831 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 3181 "sqlite3_parser.cpp" + break; + + case 270: // optional_fk_clause: fk_clause_part_list "DEFERRABLE" "INITIALLY" "DEFERRED" +#line 832 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3187 "sqlite3_parser.cpp" + break; + + case 271: // optional_fk_clause: fk_clause_part_list "DEFERRABLE" "INITIALLY" "IMMEDIATE" +#line 833 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3193 "sqlite3_parser.cpp" + break; + + case 272: // optional_fk_clause: fk_clause_part_list "DEFERRABLE" +#line 834 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3199 "sqlite3_parser.cpp" + break; + + case 273: // optional_fk_clause: fk_clause_part_list "NOT" "DEFERRABLE" "INITIALLY" "DEFERRED" +#line 835 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + " " + yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3205 "sqlite3_parser.cpp" + break; + + case 274: // optional_fk_clause: fk_clause_part_list "NOT" "DEFERRABLE" "INITIALLY" "IMMEDIATE" +#line 836 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[4].value.as < std::string > () + " " + yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3211 "sqlite3_parser.cpp" + break; + + case 275: // optional_fk_clause: fk_clause_part_list "NOT" "DEFERRABLE" +#line 837 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3217 "sqlite3_parser.cpp" + break; + + case 276: // optional_fk_clause: "DEFERRABLE" "INITIALLY" "DEFERRED" +#line 838 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3223 "sqlite3_parser.cpp" + break; + + case 277: // optional_fk_clause: "DEFERRABLE" "INITIALLY" "IMMEDIATE" +#line 839 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3229 "sqlite3_parser.cpp" + break; + + case 278: // optional_fk_clause: "DEFERRABLE" +#line 840 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[0].value.as < std::string > (); } +#line 3235 "sqlite3_parser.cpp" + break; + + case 279: // optional_fk_clause: "NOT" "DEFERRABLE" "INITIALLY" "DEFERRED" +#line 841 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3241 "sqlite3_parser.cpp" + break; + + case 280: // optional_fk_clause: "NOT" "DEFERRABLE" "INITIALLY" "IMMEDIATE" +#line 842 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[3].value.as < std::string > () + " " + yystack_[2].value.as < std::string > () + " " + yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3247 "sqlite3_parser.cpp" + break; + + case 281: // optional_fk_clause: "NOT" "DEFERRABLE" +#line 843 "sqlite3_parser.yy" + { yylhs.value.as < std::string > () = yystack_[1].value.as < std::string > () + " " + yystack_[0].value.as < std::string > (); } +#line 3253 "sqlite3_parser.cpp" + break; + + case 282: // tableconstraint: optional_constraintname "PRIMARY" "KEY" "(" indexed_column_list ")" optional_conflictclause +#line 847 "sqlite3_parser.yy" + { + auto pk = std::make_shared(); + pk->setName(yystack_[6].value.as < std::string > ()); + pk->setConflictAction(yystack_[0].value.as < std::string > ()); + yylhs.value.as < TableConstraints > ().index.insert(std::make_pair(yystack_[2].value.as < sqlb::IndexedColumnVector > (), pk)); + } +#line 3264 "sqlite3_parser.cpp" + break; + + case 283: // tableconstraint: optional_constraintname "PRIMARY" "KEY" "(" indexed_column_list "AUTOINCREMENT" ")" optional_conflictclause +#line 853 "sqlite3_parser.yy" + { + auto pk = std::make_shared(); + pk->setName(yystack_[7].value.as < std::string > ()); + pk->setConflictAction(yystack_[0].value.as < std::string > ()); + pk->setAutoIncrement(true); + yylhs.value.as < TableConstraints > ().index.insert(std::make_pair(yystack_[3].value.as < sqlb::IndexedColumnVector > (), pk)); + } +#line 3276 "sqlite3_parser.cpp" + break; + + case 284: // tableconstraint: optional_constraintname "UNIQUE" "(" indexed_column_list ")" optional_conflictclause +#line 860 "sqlite3_parser.yy" + { + auto u = std::make_shared(); + u->setName(yystack_[5].value.as < std::string > ()); + u->setConflictAction(yystack_[0].value.as < std::string > ()); + sqlb::StringVector columns; + yylhs.value.as < TableConstraints > ().index.insert(std::make_pair(yystack_[2].value.as < sqlb::IndexedColumnVector > (), u)); + } +#line 3288 "sqlite3_parser.cpp" + break; + + case 285: // tableconstraint: optional_constraintname "CHECK" "(" expr ")" +#line 867 "sqlite3_parser.yy" + { + auto c = std::make_shared(yystack_[1].value.as < std::string > ()); + c->setName(yystack_[4].value.as < std::string > ()); + yylhs.value.as < TableConstraints > ().check.push_back(c); + } +#line 3298 "sqlite3_parser.cpp" + break; + + case 286: // tableconstraint: optional_constraintname "FOREIGN" "KEY" "(" columnid_list ")" "REFERENCES" tableid optional_columnid_with_paren_list optional_fk_clause +#line 872 "sqlite3_parser.yy" + { + auto f = std::make_shared(yystack_[2].value.as < std::string > (), yystack_[1].value.as < sqlb::StringVector > (), yystack_[0].value.as < std::string > ()); + f->setName(yystack_[9].value.as < std::string > ()); + yylhs.value.as < TableConstraints > ().fk.insert(std::make_pair(yystack_[5].value.as < sqlb::StringVector > (), f)); + } +#line 3308 "sqlite3_parser.cpp" + break; + + case 287: // tableconstraint_list: tableconstraint +#line 880 "sqlite3_parser.yy" + { yylhs.value.as < TableConstraints > () = yystack_[0].value.as < TableConstraints > (); } +#line 3314 "sqlite3_parser.cpp" + break; + + case 288: // tableconstraint_list: tableconstraint_list "," tableconstraint +#line 881 "sqlite3_parser.yy" + { yylhs.value.as < TableConstraints > () = yystack_[2].value.as < TableConstraints > (); yylhs.value.as < TableConstraints > ().index.insert(yystack_[0].value.as < TableConstraints > ().index.begin(), yystack_[0].value.as < TableConstraints > ().index.end()); yylhs.value.as < TableConstraints > ().fk.insert(yystack_[0].value.as < TableConstraints > ().fk.begin(), yystack_[0].value.as < TableConstraints > ().fk.end()); std::copy(yystack_[0].value.as < TableConstraints > ().check.begin(), yystack_[0].value.as < TableConstraints > ().check.end(), std::back_inserter(yylhs.value.as < TableConstraints > ().check)); } +#line 3320 "sqlite3_parser.cpp" + break; + + case 289: // tableconstraint_list: tableconstraint_list tableconstraint +#line 882 "sqlite3_parser.yy" + { yylhs.value.as < TableConstraints > () = yystack_[1].value.as < TableConstraints > (); yylhs.value.as < TableConstraints > ().index.insert(yystack_[0].value.as < TableConstraints > ().index.begin(), yystack_[0].value.as < TableConstraints > ().index.end()); yylhs.value.as < TableConstraints > ().fk.insert(yystack_[0].value.as < TableConstraints > ().fk.begin(), yystack_[0].value.as < TableConstraints > ().fk.end()); std::copy(yystack_[0].value.as < TableConstraints > ().check.begin(), yystack_[0].value.as < TableConstraints > ().check.end(), std::back_inserter(yylhs.value.as < TableConstraints > ().check)); } +#line 3326 "sqlite3_parser.cpp" + break; + + case 290: // optional_tableconstraint_list: %empty +#line 886 "sqlite3_parser.yy" + { } +#line 3332 "sqlite3_parser.cpp" + break; + + case 291: // optional_tableconstraint_list: "," tableconstraint_list +#line 887 "sqlite3_parser.yy" + { yylhs.value.as < TableConstraints > () = yystack_[0].value.as < TableConstraints > (); } +#line 3338 "sqlite3_parser.cpp" + break; + + case 292: // createtable_stmt: "CREATE" optional_temporary "TABLE" optional_if_not_exists tableid_with_uninteresting_schema "AS" select_stmt +#line 891 "sqlite3_parser.yy" + { + yylhs.value.as < sqlb::TablePtr > () = std::make_shared(yystack_[2].value.as < std::string > ()); + yylhs.value.as < sqlb::TablePtr > ()->setFullyParsed(false); + } +#line 3347 "sqlite3_parser.cpp" + break; + + case 293: // createtable_stmt: "CREATE" optional_temporary "TABLE" optional_if_not_exists tableid_with_uninteresting_schema "(" columndef_list optional_tableconstraint_list ")" optional_tableoptions_list +#line 895 "sqlite3_parser.yy" + { + yylhs.value.as < sqlb::TablePtr > () = std::make_shared(yystack_[5].value.as < std::string > ()); + yylhs.value.as < sqlb::TablePtr > ()->setWithoutRowidTable(yystack_[0].value.as < std::bitset > ().test(sqlb::Table::WithoutRowid)); + yylhs.value.as < sqlb::TablePtr > ()->setStrict(yystack_[0].value.as < std::bitset > ().test(sqlb::Table::Strict)); + for(const auto& i : yystack_[2].value.as < TableConstraints > ().index) + yylhs.value.as < sqlb::TablePtr > ()->addConstraint(i.first, i.second); + for(const auto& i : yystack_[2].value.as < TableConstraints > ().fk) + yylhs.value.as < sqlb::TablePtr > ()->addConstraint(i.first, i.second); + for(const auto& i : yystack_[2].value.as < TableConstraints > ().check) + yylhs.value.as < sqlb::TablePtr > ()->addConstraint(i); + yylhs.value.as < sqlb::TablePtr > ()->setFullyParsed(true); + + for(const auto& f : yystack_[3].value.as < ColumnList > ().first) + yylhs.value.as < sqlb::TablePtr > ()->fields.push_back(*f); + for(const auto& pk : yystack_[3].value.as < ColumnList > ().second.index) + yylhs.value.as < sqlb::TablePtr > ()->addConstraint(pk.first, pk.second); + for(const auto& fk : yystack_[3].value.as < ColumnList > ().second.fk) + yylhs.value.as < sqlb::TablePtr > ()->addConstraint(fk.first, fk.second); + } +#line 3371 "sqlite3_parser.cpp" + break; + + +#line 3375 "sqlite3_parser.cpp" + + default: + break; + } + } +#if YY_EXCEPTIONS + catch (const syntax_error& yyexc) + { + YYCDEBUG << "Caught exception: " << yyexc.what() << '\n'; + error (yyexc); + YYERROR; + } +#endif // YY_EXCEPTIONS + YY_SYMBOL_PRINT ("-> $$ =", yylhs); + yypop_ (yylen); + yylen = 0; + + // Shift the result of the reduction. + yypush_ (YY_NULLPTR, YY_MOVE (yylhs)); + } + goto yynewstate; + + + /*--------------------------------------. + | yyerrlab -- here on detecting error. | + `--------------------------------------*/ + yyerrlab: + // If not already recovering from an error, report this error. + if (!yyerrstatus_) + { + ++yynerrs_; + context yyctx (*this, yyla); + std::string msg = yysyntax_error_ (yyctx); + error (yyla.location, YY_MOVE (msg)); + } + + + yyerror_range[1].location = yyla.location; + if (yyerrstatus_ == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + // Return failure if at end of input. + if (yyla.kind () == symbol_kind::S_YYEOF) + YYABORT; + else if (!yyla.empty ()) + { + yy_destroy_ ("Error: discarding", yyla); + yyla.clear (); + } + } + + // Else will try to reuse lookahead token after shifting the error token. + goto yyerrlab1; + + + /*---------------------------------------------------. + | yyerrorlab -- error raised explicitly by YYERROR. | + `---------------------------------------------------*/ + yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and + the label yyerrorlab therefore never appears in user code. */ + if (false) + YYERROR; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + yypop_ (yylen); + yylen = 0; + YY_STACK_PRINT (); + goto yyerrlab1; + + + /*-------------------------------------------------------------. + | yyerrlab1 -- common code for both syntax error and YYERROR. | + `-------------------------------------------------------------*/ + yyerrlab1: + yyerrstatus_ = 3; // Each real token shifted decrements this. + // Pop stack until we find a state that shifts the error token. + for (;;) + { + yyn = yypact_[+yystack_[0].state]; + if (!yy_pact_value_is_default_ (yyn)) + { + yyn += symbol_kind::S_YYerror; + if (0 <= yyn && yyn <= yylast_ + && yycheck_[yyn] == symbol_kind::S_YYerror) + { + yyn = yytable_[yyn]; + if (0 < yyn) + break; + } + } + + // Pop the current state because it cannot handle the error token. + if (yystack_.size () == 1) + YYABORT; + + yyerror_range[1].location = yystack_[0].location; + yy_destroy_ ("Error: popping", yystack_[0]); + yypop_ (); + YY_STACK_PRINT (); + } + { + stack_symbol_type error_token; + + yyerror_range[2].location = yyla.location; + YYLLOC_DEFAULT (error_token.location, yyerror_range, 2); + + // Shift the error token. + error_token.state = state_type (yyn); + yypush_ ("Shifting", YY_MOVE (error_token)); + } + goto yynewstate; + + + /*-------------------------------------. + | yyacceptlab -- YYACCEPT comes here. | + `-------------------------------------*/ + yyacceptlab: + yyresult = 0; + goto yyreturn; + + + /*-----------------------------------. + | yyabortlab -- YYABORT comes here. | + `-----------------------------------*/ + yyabortlab: + yyresult = 1; + goto yyreturn; + + + /*-----------------------------------------------------. + | yyreturn -- parsing is finished, return the result. | + `-----------------------------------------------------*/ + yyreturn: + if (!yyla.empty ()) + yy_destroy_ ("Cleanup: discarding lookahead", yyla); + + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + yypop_ (yylen); + YY_STACK_PRINT (); + while (1 < yystack_.size ()) + { + yy_destroy_ ("Cleanup: popping", yystack_[0]); + yypop_ (); + } + + return yyresult; + } +#if YY_EXCEPTIONS + catch (...) + { + YYCDEBUG << "Exception caught: cleaning lookahead and stack\n"; + // Do not try to display the values of the reclaimed symbols, + // as their printers might throw an exception. + if (!yyla.empty ()) + yy_destroy_ (YY_NULLPTR, yyla); + + while (1 < yystack_.size ()) + { + yy_destroy_ (YY_NULLPTR, yystack_[0]); + yypop_ (); + } + throw; + } +#endif // YY_EXCEPTIONS + } + + void + parser::error (const syntax_error& yyexc) + { + error (yyexc.location, yyexc.what ()); + } + + /* Return YYSTR after stripping away unnecessary quotes and + backslashes, so that it's suitable for yyerror. The heuristic is + that double-quoting is unnecessary unless the string contains an + apostrophe, a comma, or backslash (other than backslash-backslash). + YYSTR is taken from yytname. */ + std::string + parser::yytnamerr_ (const char *yystr) + { + if (*yystr == '"') + { + std::string yyr; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + else + goto append; + + append: + default: + yyr += *yyp; + break; + + case '"': + return yyr; + } + do_not_strip_quotes: ; + } + + return yystr; + } + + std::string + parser::symbol_name (symbol_kind_type yysymbol) + { + return yytnamerr_ (yytname_[yysymbol]); + } + + + + // parser::context. + parser::context::context (const parser& yyparser, const symbol_type& yyla) + : yyparser_ (yyparser) + , yyla_ (yyla) + {} + + int + parser::context::expected_tokens (symbol_kind_type yyarg[], int yyargn) const + { + // Actual number of expected tokens + int yycount = 0; + + const int yyn = yypact_[+yyparser_.yystack_[0].state]; + if (!yy_pact_value_is_default_ (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + const int yyxbegin = yyn < 0 ? -yyn : 0; + // Stay within bounds of both yycheck and yytname. + const int yychecklim = yylast_ - yyn + 1; + const int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + for (int yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck_[yyx + yyn] == yyx && yyx != symbol_kind::S_YYerror + && !yy_table_value_is_error_ (yytable_[yyx + yyn])) + { + if (!yyarg) + ++yycount; + else if (yycount == yyargn) + return 0; + else + yyarg[yycount++] = YY_CAST (symbol_kind_type, yyx); + } + } + + if (yyarg && yycount == 0 && 0 < yyargn) + yyarg[0] = symbol_kind::S_YYEMPTY; + return yycount; + } + + + + + + + int + parser::yy_syntax_error_arguments_ (const context& yyctx, + symbol_kind_type yyarg[], int yyargn) const + { + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yyla) is + if this state is a consistent state with a default action. + Thus, detecting the absence of a lookahead is sufficient to + determine that there is no unexpected or expected token to + report. In that case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is + a consistent state with a default action. There might have + been a previous inconsistent state, consistent state with a + non-default action, or user semantic action that manipulated + yyla. (However, yyla is currently not documented for users.) + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + + if (!yyctx.lookahead ().empty ()) + { + if (yyarg) + yyarg[0] = yyctx.token (); + int yyn = yyctx.expected_tokens (yyarg ? yyarg + 1 : yyarg, yyargn - 1); + return yyn + 1; + } + return 0; + } + + // Generate an error message. + std::string + parser::yysyntax_error_ (const context& yyctx) const + { + // Its maximum. + enum { YYARGS_MAX = 5 }; + // Arguments of yyformat. + symbol_kind_type yyarg[YYARGS_MAX]; + int yycount = yy_syntax_error_arguments_ (yyctx, yyarg, YYARGS_MAX); + + char const* yyformat = YY_NULLPTR; + switch (yycount) + { +#define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + default: // Avoid compiler warnings. + YYCASE_ (0, YY_("syntax error")); + YYCASE_ (1, YY_("syntax error, unexpected %s")); + YYCASE_ (2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_ (3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_ (4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_ (5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +#undef YYCASE_ + } + + std::string yyres; + // Argument number. + std::ptrdiff_t yyi = 0; + for (char const* yyp = yyformat; *yyp; ++yyp) + if (yyp[0] == '%' && yyp[1] == 's' && yyi < yycount) + { + yyres += symbol_name (yyarg[yyi++]); + ++yyp; + } + else + yyres += *yyp; + return yyres; + } + + + const short parser::yypact_ninf_ = -349; + + const short parser::yytable_ninf_ = -292; + + const short + parser::yypact_[] = + { + 11, 145, 123, 106, -349, -349, -349, -349, -349, -349, + 51, 67, 58, -349, -349, 117, 117, 117, 86, 2483, + 2483, 2483, 130, -349, -349, -349, -349, -349, -349, -349, + -349, -349, -349, -349, -349, -349, -349, -349, -349, -349, + -349, -349, -349, -349, -349, -349, -349, -349, -349, -349, + -349, -349, -349, -349, -349, -349, -349, -349, -349, -349, + -349, -349, 168, -349, -349, -349, -349, -349, -349, -349, + 173, -349, -349, 97, 160, 99, -349, 2574, 2574, -8, + 2574, 2392, 129, -349, -349, -349, -349, 242, 247, -349, + -349, -349, -349, -349, -349, -349, 2574, -349, 251, -349, + -349, 1034, -349, 1736, -349, 1947, -349, -349, 28, 2301, + 249, 1736, -349, 1736, 1736, 1736, 1151, 257, -349, -349, + -349, -349, 1736, -349, 258, -349, -349, -349, -349, -349, + -349, 102, -349, -349, -349, -349, 113, -349, -349, -349, + -349, -349, -349, 3480, 3012, -349, 122, 7, -349, -71, + -349, 61, -349, -14, -349, 34, -74, 165, -349, -349, + -349, 1736, -32, 214, 1736, 3592, 9, 683, -8, -349, + 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, + 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, + 1736, -8, 1736, 2041, 1268, -349, 1736, 1736, 80, -349, + 1736, 1736, -349, -349, -349, 164, 1736, 169, 170, -349, + -349, 175, -349, -349, 285, -8, 1853, 262, 222, -349, + 232, 2574, 236, 286, 38, 316, 246, 248, 318, 282, + -349, -349, 231, -349, -2, -349, -349, 542, 1736, -349, + 1736, -30, 3090, 321, 322, 327, 326, -349, 329, 1736, + 203, 332, 3480, 151, 151, 126, 126, 202, 126, 202, + 296, 179, 179, 254, 254, 254, 254, 179, 179, 202, + 202, 3592, 3168, -349, 331, 800, 180, -349, 276, 1385, + 179, 387, 514, 1736, 1736, 2135, 1736, 1736, -349, 1736, + 3558, 2285, 1736, -349, -349, -349, -349, -349, 7, 1736, + -349, 1736, -349, -349, -349, -349, -349, -349, 236, 2, + 352, 293, -349, 355, 1736, 356, 357, 1736, -349, -349, + -74, -349, 1736, 3246, 2245, 1736, -349, 2574, 245, 250, + -349, 253, -349, 252, -349, -8, 1736, 1736, -349, 267, + 358, 1736, 2574, 1736, 302, 1736, 1736, 3324, 2719, 917, + 272, -349, 2802, 2885, 3664, 1736, 3480, 359, 2685, 2768, + -349, 236, 2392, 56, -9, 1736, 2851, 2392, 1736, 277, + -349, 3480, -349, 1736, 3402, 361, 364, 366, 368, -349, + -349, 179, 179, -349, -349, 291, 370, -349, -349, 1736, + 179, 179, 1736, 1736, -349, 294, 371, 1736, 2574, 1736, + 1736, 1736, 179, -349, -349, -349, 340, -349, 297, 307, + -8, 328, -21, -349, 62, -349, -349, -349, -349, -349, + -349, 2934, -349, 301, 112, 236, 3480, -349, -349, -349, + -349, -349, -349, 1502, -349, 179, 179, -349, -349, 305, + 375, -349, 179, 179, 179, -349, -349, 2392, -18, -349, + 310, -3, 35, 37, 311, 334, -349, -58, 295, 236, + 379, -349, -349, 306, -349, 1619, -349, -349, -349, 96, + -349, 360, -349, -17, -349, 362, -349, 4, -349, 365, + -349, 8, 108, 317, -349, -349, -349, 2574, -349, 236, + -349, -349, 309, -349, -349, -349, -349, -349, -349, -349, + -349, -349, -349, -349, -349, -349, 109, 352, -349, -349, + -349, -349, 56, -349 + }; + + const short + parser::yydefact_[] = + { + 0, 185, 0, 2, 4, 5, 6, 201, 202, 186, + 0, 0, 0, 1, 3, 180, 180, 180, 0, 0, + 0, 0, 0, 18, 19, 20, 21, 22, 23, 24, + 61, 60, 62, 25, 26, 27, 28, 29, 30, 31, + 32, 35, 37, 36, 33, 34, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 55, 54, 56, 57, 58, 16, 64, 17, + 63, 59, 191, 0, 0, 0, 181, 0, 0, 0, + 0, 0, 0, 55, 63, 190, 189, 196, 0, 67, + 66, 68, 69, 71, 70, 65, 216, 238, 290, 179, + 292, 0, 199, 0, 76, 78, 217, 240, 243, 243, + 0, 0, 197, 0, 0, 0, 0, 23, 14, 13, + 15, 12, 0, 10, 43, 11, 7, 8, 9, 163, + 161, 166, 162, 167, 168, 173, 0, 169, 174, 175, + 176, 177, 178, 124, 182, 193, 0, 0, 77, 0, + 239, 221, 238, 0, 287, 243, 208, 0, 82, 81, + 83, 0, 0, 0, 0, 84, 0, 0, 0, 198, + 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, 130, 0, 0, 0, 131, + 0, 0, 183, 184, 192, 187, 0, 0, 0, 75, + 74, 0, 245, 244, 0, 0, 0, 0, 0, 226, + 0, 0, 210, 0, 243, 0, 0, 0, 0, 243, + 289, 204, 0, 205, 209, 293, 170, 0, 0, 156, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, + 0, 165, 125, 89, 90, 86, 87, 93, 88, 94, + 85, 99, 100, 97, 98, 95, 96, 101, 102, 91, + 92, 106, 0, 172, 109, 0, 63, 139, 0, 0, + 103, 108, 110, 0, 0, 0, 0, 0, 132, 0, + 107, 111, 0, 195, 194, 72, 73, 79, 0, 0, + 235, 0, 233, 230, 231, 232, 229, 222, 210, 182, + 248, 0, 227, 0, 0, 0, 0, 0, 288, 203, + 0, 207, 0, 0, 0, 0, 154, 0, 0, 0, + 157, 0, 129, 0, 126, 0, 0, 0, 135, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 113, 0, + 63, 147, 112, 114, 115, 0, 188, 0, 0, 0, + 225, 210, 0, 268, 0, 0, 0, 0, 0, 0, + 206, 151, 155, 0, 0, 0, 0, 0, 0, 127, + 164, 133, 117, 137, 136, 0, 63, 138, 104, 0, + 116, 118, 0, 0, 143, 0, 0, 0, 0, 0, + 0, 0, 119, 80, 228, 234, 223, 246, 0, 278, + 0, 0, 0, 266, 269, 236, 212, 213, 214, 215, + 211, 0, 285, 0, 0, 210, 152, 153, 171, 159, + 160, 158, 142, 0, 105, 134, 121, 145, 144, 0, + 63, 146, 120, 122, 123, 224, 249, 0, 0, 265, + 281, 0, 0, 0, 272, 0, 267, 218, 0, 210, + 0, 284, 140, 0, 150, 0, 247, 276, 277, 0, + 252, 0, 253, 0, 262, 0, 263, 0, 257, 0, + 258, 0, 0, 275, 219, 220, 237, 0, 282, 210, + 141, 148, 0, 279, 280, 254, 251, 250, 264, 261, + 260, 259, 256, 255, 270, 271, 0, 248, 283, 149, + 273, 274, 268, 286 + }; + + const short + parser::yypgoto_[] = + { + -349, -349, -349, 176, -19, -13, -68, -348, 178, 91, + -349, 72, -349, -349, -349, -98, -349, -349, -349, -349, + 241, -349, -349, 308, -258, 198, 101, -349, -349, 200, + 199, -290, -349, -349, -349, -349, -223, -349, -349, -305, + -349, -349, -349, -349, 263, 320, -349, -103, 47, -91, + 3, -349, -94, -135, -349, -349, -349 + }; + + const short + parser::yydefgoto_[] = + { + 0, 2, 3, 130, 131, 132, 72, 96, 210, 211, + 105, 106, 133, 134, 135, 136, 137, 138, 139, 140, + 162, 141, 142, 143, 100, 19, 204, 11, 293, 73, + 145, 146, 4, 102, 5, 12, 233, 234, 235, 312, + 107, 486, 223, 150, 108, 97, 98, 153, 408, 363, + 413, 414, 415, 154, 155, 110, 6 + }; + + const short + parser::yytable_[] = + { + 70, 70, 70, 360, 320, 151, 71, 71, 71, 85, + 86, 321, 88, 157, 407, 207, 208, 340, 416, 407, + 230, 238, 239, 325, 326, 225, 231, 369, 104, 451, + 496, 467, -241, 470, -241, 202, 243, 148, -291, 232, + 229, 484, -242, 67, -242, 212, 69, 226, 417, 468, + 452, 499, 485, 203, 1, 502, 406, 418, 84, 84, + 87, 84, 94, 497, 71, 71, 244, 71, 95, 250, + 149, 474, 227, 478, 471, 245, 149, 84, 424, 240, + 149, 240, 419, 71, 500, 420, 84, 453, 503, 472, + 94, 396, 71, 228, 318, 473, 95, 370, 231, 466, + 214, 215, 81, 246, 409, 167, 67, 168, 216, 69, + 454, 232, 475, 14, 479, 283, 459, 169, 206, 170, + 461, 151, 209, 13, 217, 277, 205, 476, 206, 480, + 213, 82, 410, 477, 411, 481, 16, 412, 410, 218, + 455, 219, 178, 412, 284, 493, 460, 220, 285, 251, + 221, 333, 15, 310, 488, 286, 287, 504, 510, 17, + 288, 173, 174, 494, 22, 176, 191, 178, 222, 236, + 289, 170, 273, 77, 276, 505, 511, 339, 78, 297, + 71, 298, 18, 341, 508, 342, 76, 171, 172, 173, + 174, 191, 175, 176, 177, 178, 300, 304, 181, 182, + 183, 184, 84, 305, 187, 188, 79, 334, 71, 170, + 171, 172, 173, 174, 20, 21, 176, 351, 178, 191, + 74, 75, 171, 172, 173, 174, 99, 175, 176, 177, + 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 80, 191, 385, 189, 101, -200, 7, 8, 190, + 103, 395, 9, 156, 191, 10, 379, 109, 170, 104, + 164, 166, 171, 172, 173, 174, 350, 175, 176, 177, + 178, 383, 71, 170, 387, 397, 292, 398, 192, 187, + 188, 425, 193, 206, 295, 296, 194, 195, 299, 196, + 197, 307, 198, 199, 191, 432, 200, 170, 437, 439, + 170, 446, 308, 447, 201, 458, 309, 447, 84, 464, + 490, 170, 170, 509, 71, 170, 380, 311, 313, 314, + 315, 317, 316, 386, 149, 161, 319, 328, 329, 71, + 441, 330, 331, 332, 364, 463, 191, 335, 343, 171, + 172, 173, 174, 94, 175, 176, 177, 178, 94, 95, + 181, 182, 183, 184, 95, 362, 187, 188, 365, 367, + 368, 376, 384, 403, 389, 428, 377, 492, 429, 378, + 430, 191, 431, 433, 445, 438, 450, 448, 465, 440, + 469, 482, 483, 489, 487, 71, 337, 506, 495, 357, + 498, 449, 303, 501, 306, 171, 172, 173, 174, 375, + 175, 176, 177, 178, 241, 294, 181, 182, 183, 184, + 361, 144, 187, 188, 423, 224, 512, 456, 513, 507, + 0, 158, 159, 160, 163, 0, 0, 191, 94, 152, + 165, 0, 0, 0, 95, 0, 0, 0, 0, 0, + 0, 0, 345, 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, 84, 237, + 0, 0, 242, 0, 71, 0, 0, 0, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, 0, + 274, 0, 280, 0, 281, 282, 0, 0, 290, 291, + 0, 0, 0, 0, 144, 0, 0, 0, 0, 0, + 0, 0, 171, 172, 173, 174, 0, 175, 176, 177, + 178, 0, 0, 181, 182, 183, 184, 0, 0, 187, + 188, 0, 0, 0, 0, 0, 323, 0, 324, 0, + 171, 172, 173, 174, 191, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 346, + 0, 0, 189, 0, 0, 0, 0, 190, 0, 0, + 0, 0, 191, 0, 0, 0, 0, 165, 0, 0, + 0, 347, 348, 0, 352, 353, 0, 354, 0, 0, + 356, 0, 0, 0, 0, 0, 192, 358, 0, 359, + 193, 0, 0, 0, 194, 195, 0, 196, 197, 0, + 198, 199, 366, 0, 200, 144, 0, 0, 0, 0, + 371, 0, 201, 374, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 381, 382, 322, 0, 0, 0, + 0, 388, 0, 390, 391, 0, 0, 0, 0, 0, + 0, 0, 0, 402, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 421, 0, 0, 144, 0, 0, 0, + 0, 426, 0, 0, 0, 0, 111, 247, 0, 0, + 0, 113, 114, 248, 0, 115, 0, 434, 0, 0, + 435, 436, 0, 0, 0, 0, 0, 442, 443, 444, + 23, 24, 25, 0, 0, 0, 26, 0, 0, 27, + 116, 117, 0, 0, 29, 0, 0, 118, 119, 120, + 0, 0, 33, 0, 34, 249, 0, 35, 0, 0, + 36, 121, 37, 38, 0, 0, 39, 40, 0, 41, + 42, 0, 0, 43, 0, 0, 0, 44, 45, 46, + 47, 122, 0, 123, 0, 0, 48, 49, 50, 0, + 124, 52, 0, 53, 54, 55, 56, 57, 58, 59, + 0, 0, 60, 61, 0, 83, 63, 0, 125, 64, + 0, 0, 0, 65, 0, 0, 66, 67, 126, 127, + 69, 128, 129, 111, 338, 0, 0, 0, 113, 114, + 0, 0, 115, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 23, 24, 25, + 0, 0, 0, 26, 0, 0, 27, 116, 117, 0, + 0, 29, 0, 0, 118, 119, 120, 0, 0, 33, + 0, 34, 0, 0, 35, 0, 0, 36, 121, 37, + 38, 0, 0, 39, 40, 0, 41, 42, 0, 0, + 43, 0, 0, 0, 44, 45, 46, 47, 122, 0, + 123, 0, 0, 48, 49, 50, 0, 124, 52, 0, + 53, 54, 55, 56, 57, 58, 59, 99, 0, 60, + 61, 0, 83, 63, 0, 125, 64, 0, 0, 0, + 65, 0, 0, 66, 67, 126, 127, 69, 128, 129, + 111, 394, 0, 0, 0, 113, 114, 0, 0, 115, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 23, 24, 25, 0, 0, 0, + 26, 0, 0, 27, 116, 117, 0, 0, 29, 0, + 0, 118, 119, 120, 0, 0, 33, 0, 34, 0, + 0, 35, 0, 0, 36, 121, 37, 38, 0, 0, + 39, 40, 0, 41, 42, 0, 0, 43, 0, 0, + 0, 44, 45, 46, 47, 122, 0, 123, 0, 0, + 48, 49, 50, 0, 124, 52, 0, 53, 54, 55, + 56, 57, 58, 59, 99, 0, 60, 61, 0, 83, + 63, 0, 125, 64, 0, 0, 0, 65, 0, 0, + 66, 67, 126, 127, 69, 128, 129, 111, 112, 0, + 0, 0, 113, 114, 0, 0, 115, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 23, 24, 25, 0, 0, 0, 26, 0, 0, + 27, 116, 117, 0, 0, 29, 0, 0, 118, 119, + 120, 0, 0, 33, 0, 34, 0, 0, 35, 0, + 0, 36, 121, 37, 38, 0, 0, 39, 40, 0, + 41, 42, 0, 0, 43, 0, 0, 0, 44, 45, + 46, 47, 122, 0, 123, 0, 0, 48, 49, 50, + 0, 124, 52, 0, 53, 54, 55, 56, 57, 58, + 59, 0, 0, 60, 61, 0, 83, 63, 0, 125, + 64, 0, 0, 0, 65, 0, 0, 66, 67, 126, + 127, 69, 128, 129, 111, 0, 0, 0, 0, 113, + 114, 0, 0, 115, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, + 25, 0, 0, 0, 26, 0, 0, 27, 116, 117, + 0, 0, 29, 0, 0, 118, 119, 120, 0, 0, + 33, 0, 34, 0, 0, 35, 0, 0, 36, 121, + 37, 38, 0, 0, 39, 40, 0, 41, 42, 0, + 0, 43, 0, 0, 0, 44, 45, 46, 47, 122, + 0, 123, 0, 0, 48, 49, 50, 0, 124, 52, + 0, 53, 54, 55, 56, 57, 58, 59, 0, 0, + 60, 61, 0, 83, 63, 0, 125, 64, 0, 0, + 0, 65, 161, 0, 66, 67, 126, 127, 69, 128, + 129, 111, 0, 0, 0, 0, 113, 114, 0, 0, + 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 23, 24, 25, 0, 0, + 0, 26, 0, 0, 27, 116, 117, 0, 0, 29, + 0, 0, 118, 119, 120, 0, 0, 33, 0, 34, + 278, 0, 35, 0, 0, 36, 121, 37, 38, 0, + 0, 39, 40, 0, 41, 42, 0, 0, 43, 0, + 0, 0, 44, 45, 46, 47, 279, 0, 123, 0, + 0, 48, 49, 50, 0, 124, 52, 0, 53, 54, + 55, 56, 57, 58, 59, 0, 0, 60, 61, 0, + 83, 63, 0, 125, 64, 0, 0, 0, 65, 0, + 0, 66, 67, 126, 127, 69, 128, 129, 111, 0, + 0, 0, 0, 113, 114, 0, 0, 115, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 23, 24, 25, 0, 0, 0, 26, 0, + 0, 27, 116, 117, 0, 0, 29, 0, 0, 118, + 119, 120, 0, 0, 33, 0, 34, 344, 0, 35, + 0, 0, 36, 121, 37, 38, 0, 0, 39, 40, + 0, 41, 42, 0, 0, 43, 0, 0, 0, 44, + 45, 46, 47, 122, 0, 123, 0, 0, 48, 49, + 50, 0, 124, 52, 0, 53, 54, 55, 56, 57, + 58, 59, 0, 0, 60, 61, 0, 83, 63, 0, + 125, 64, 0, 0, 0, 65, 0, 0, 66, 67, + 126, 127, 69, 128, 129, 111, 462, 0, 0, 0, + 113, 114, 0, 0, 115, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, + 24, 25, 0, 0, 0, 26, 0, 0, 27, 116, + 117, 0, 0, 29, 0, 0, 118, 119, 120, 0, + 0, 33, 0, 34, 0, 0, 35, 0, 0, 36, + 121, 37, 38, 0, 0, 39, 40, 0, 41, 42, + 0, 0, 43, 0, 0, 0, 44, 45, 46, 47, + 122, 0, 123, 0, 0, 48, 49, 50, 0, 124, + 52, 0, 53, 54, 55, 56, 57, 58, 59, 0, + 0, 60, 61, 0, 83, 63, 0, 125, 64, 0, + 0, 0, 65, 0, 0, 66, 67, 126, 127, 69, + 128, 129, 111, 491, 0, 0, 0, 113, 114, 0, + 0, 115, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 23, 24, 25, 0, + 0, 0, 26, 0, 0, 27, 116, 117, 0, 0, + 29, 0, 0, 118, 119, 120, 0, 0, 33, 0, + 34, 0, 0, 35, 0, 0, 36, 121, 37, 38, + 0, 0, 39, 40, 0, 41, 42, 0, 0, 43, + 0, 0, 0, 44, 45, 46, 47, 122, 0, 123, + 0, 0, 48, 49, 50, 0, 124, 52, 0, 53, + 54, 55, 56, 57, 58, 59, 0, 0, 60, 61, + 0, 83, 63, 0, 125, 64, 0, 0, 0, 65, + 0, 0, 66, 67, 126, 127, 69, 128, 129, 111, + 0, 0, 0, 0, 113, 114, 0, 0, 115, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 23, 24, 25, 0, 0, 0, 26, + 0, 0, 27, 116, 117, 0, 0, 29, 0, 0, + 118, 119, 120, 0, 0, 33, 0, 34, 0, 0, + 35, 0, 0, 36, 121, 37, 38, 0, 0, 39, + 40, 0, 41, 42, 0, 0, 43, 0, 0, 0, + 44, 45, 46, 47, 122, 0, 123, 0, 0, 48, + 49, 50, 0, 124, 52, 0, 53, 54, 55, 56, + 57, 58, 59, 0, 0, 60, 61, 0, 83, 63, + 0, 125, 64, 0, 0, 0, 65, 0, 0, 66, + 67, 126, 127, 69, 128, 129, 301, 0, 0, 0, + 0, 207, 208, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 23, 24, 25, 0, 0, 0, 26, 0, 0, 27, + 0, 28, 0, 0, 29, 0, 0, 118, 119, 120, + 0, 0, 33, 0, 34, 0, 0, 35, 0, 0, + 36, 121, 37, 38, 0, 0, 39, 40, 302, 41, + 42, 0, 0, 43, 0, 0, 0, 44, 45, 46, + 47, 0, 0, 123, 0, 0, 48, 49, 50, 0, + 51, 52, 0, 53, 54, 55, 56, 57, 58, 59, + 147, 0, 60, 61, 0, 83, 63, 0, 125, 64, + 0, 0, 0, 65, 0, 0, 66, 67, 126, 127, + 69, 128, 0, 0, 23, 24, 25, 0, 0, 0, + 26, 0, 0, 27, 0, 28, 0, 0, 29, 0, + 0, 30, 31, 32, 0, 0, 33, 0, 34, 0, + 0, 35, 0, 0, 36, 0, 37, 38, 0, 0, + 39, 40, 0, 41, 42, 0, 0, 43, 0, 0, + 0, 44, 45, 46, 47, 0, 0, 0, 0, 0, + 48, 49, 50, 0, 51, 52, 0, 53, 54, 55, + 56, 57, 58, 59, 275, 0, 60, 61, 0, 83, + 63, 0, 0, 64, 0, 0, 0, 65, 0, 0, + 66, 67, 0, 68, 69, 0, 0, 0, 23, 24, + 25, 0, 0, 0, 26, 0, 0, 27, 0, 28, + 0, 0, 29, 0, 0, 30, 31, 32, 0, 0, + 33, 0, 34, 0, 0, 35, 0, 0, 36, 0, + 37, 38, 0, 0, 39, 40, 0, 41, 42, 0, + 0, 43, 0, 0, 0, 44, 45, 46, 47, 0, + 0, 0, 0, 0, 48, 49, 50, 0, 51, 52, + 0, 53, 54, 55, 56, 57, 58, 59, 349, 0, + 60, 61, 0, 83, 63, 0, 0, 64, 0, 0, + 0, 65, 0, 0, 66, 67, 0, 68, 69, 0, + 0, 0, 23, 24, 25, 0, 0, 0, 26, 0, + 0, 27, 0, 28, 0, 0, 29, 0, 0, 30, + 31, 32, 0, 0, 33, 0, 34, 0, 0, 35, + 0, 0, 36, 0, 37, 38, 0, 0, 39, 40, + 0, 41, 42, 0, 0, 43, 0, 0, 0, 44, + 45, 46, 47, 0, 0, 0, 0, 0, 48, 49, + 50, 0, 51, 52, 0, 53, 54, 55, 56, 57, + 58, 59, 0, 0, 60, 61, 0, 83, 63, 0, + 0, 64, 0, 0, 0, 65, 0, 0, 66, 67, + 0, 68, 69, 171, 172, 173, 174, 0, 175, 176, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 0, 0, 0, 189, 0, 0, 0, 0, + 190, 0, 0, 0, 0, 191, 0, 0, 0, 0, + 0, 0, 0, 171, 172, 173, 174, 0, 175, 176, + 177, 178, 0, 0, 181, 182, 183, 184, 0, 192, + 187, 188, 0, 193, 0, 0, 0, 194, 195, 0, + 196, 197, 0, 198, 199, 191, 0, 200, 23, 24, + 25, 0, 0, 0, 26, 201, 0, 27, 0, 28, + 355, 0, 29, 149, 0, 89, 90, 91, 0, 373, + 33, 0, 34, 0, 0, 35, 0, 0, 36, 0, + 37, 38, 0, 0, 39, 40, 92, 41, 42, 0, + 0, 43, 0, 0, 0, 44, 45, 46, 47, 0, + 0, 0, 0, 0, 48, 49, 50, 0, 51, 52, + 0, 53, 54, 55, 56, 57, 58, 59, 0, 0, + 60, 61, 0, 83, 63, 0, 0, 64, 0, 0, + 0, 65, 0, 0, 66, 67, 0, 93, 69, 23, + 24, 25, 0, 0, 0, 26, 0, 0, 27, 0, + 28, 0, 0, 29, 0, 0, 89, 90, 91, 0, + 0, 33, 0, 34, 0, 0, 35, 0, 0, 36, + 0, 37, 38, 0, 0, 39, 40, 92, 41, 42, + 0, 0, 43, 0, 0, 0, 44, 45, 46, 47, + 0, 0, 0, 0, 0, 48, 49, 50, 0, 51, + 52, 0, 53, 54, 55, 56, 57, 58, 59, 0, + 0, 60, 61, 0, 83, 63, 0, 0, 64, 0, + 0, 0, 65, 0, 0, 66, 67, 0, 93, 69, + 23, 24, 25, 0, 0, 0, 26, 0, 0, 27, + 0, 28, 0, 0, 29, 0, 0, 30, 31, 32, + 0, 0, 33, 0, 34, 0, 0, 35, 0, 0, + 36, 0, 37, 38, 0, 0, 39, 40, 0, 41, + 42, 0, 0, 43, 0, 0, 0, 44, 45, 46, + 47, 0, 0, 0, 0, 0, 48, 49, 50, 0, + 51, 52, 0, 53, 54, 55, 56, 57, 58, 59, + 0, 0, 60, 61, 0, 62, 63, 0, 0, 64, + 0, 0, 0, 65, 0, 0, 66, 67, 0, 68, + 69, 23, 24, 25, 0, 0, 0, 26, 0, 0, + 27, 0, 28, 0, 0, 29, 0, 0, 30, 31, + 32, 0, 0, 33, 0, 34, 0, 0, 35, 0, + 0, 36, 0, 37, 38, 0, 0, 39, 40, 0, + 41, 42, 0, 0, 43, 0, 0, 0, 44, 45, + 46, 47, 0, 0, 0, 0, 0, 48, 49, 50, + 0, 51, 52, 0, 53, 54, 55, 56, 57, 58, + 59, 0, 0, 60, 61, 0, 83, 63, 0, 0, + 64, 0, 0, 0, 65, 0, 0, 66, 67, 404, + 68, 69, 0, 171, 172, 173, 174, 0, 175, 176, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 0, 0, 0, 189, 0, 0, 0, 0, + 190, 0, 0, 0, 0, 191, 0, 171, 172, 173, + 174, 0, 175, 176, 177, 178, 0, 0, 181, 182, + 183, 184, 0, 0, 187, 188, 0, 0, 0, 192, + 0, 0, 0, 193, 0, 0, 0, 194, 195, 191, + 196, 197, 0, 198, 199, 0, 0, 200, 0, 0, + 0, 0, 405, 0, 393, 201, 171, 172, 173, 174, + 0, 175, 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 0, 0, 0, 189, 0, + 0, 0, 0, 190, 0, 0, 0, 0, 191, 0, + 171, 172, 173, 174, 0, 175, 176, 177, 178, 0, + 0, 181, 182, 183, 184, 0, 0, 187, 188, 0, + 0, 0, 192, 0, 0, 0, 193, 0, 0, 0, + 194, 195, 191, 196, 197, 0, 198, 199, 0, 0, + 200, 0, 0, 0, 0, 422, 0, 399, 201, 171, + 172, 173, 174, 0, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 0, 0, + 0, 189, 0, 0, 0, 0, 190, 0, 0, 0, + 0, 191, 0, 171, 172, 173, 174, 0, 175, 176, + 177, 178, 0, 0, 181, 182, 183, 184, 0, 0, + 187, 188, 0, 0, 0, 192, 0, 0, 0, 193, + 0, 0, 0, 194, 195, 191, 196, 197, 0, 198, + 199, 0, 0, 200, 0, 0, 0, 0, 457, 0, + 400, 201, 171, 172, 173, 174, 0, 175, 176, 177, + 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 0, 0, 0, 189, 0, 0, 0, 0, 190, + 0, 0, 0, 0, 191, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, + 0, 0, 193, 0, 0, 0, 194, 195, 0, 196, + 197, 0, 198, 199, 0, 0, 200, 0, 0, 0, + 171, 172, 173, 174, 201, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 0, + 0, 0, 189, 0, 0, 202, 0, 190, 0, 0, + 0, 0, 191, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, + 193, 0, 0, 0, 194, 195, 0, 196, 197, 0, + 198, 199, 0, 0, 200, 0, 0, 0, 171, 172, + 173, 174, 201, 175, 176, 177, 178, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 0, 0, 0, + 189, 0, 327, 0, 0, 190, 0, 0, 0, 0, + 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 192, 0, 0, 0, 193, 0, + 0, 0, 194, 195, 0, 196, 197, 0, 198, 199, + 0, 0, 200, 0, 0, 0, 171, 172, 173, 174, + 201, 175, 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 0, 0, 0, 189, 336, + 0, 0, 0, 190, 0, 0, 0, 0, 191, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 192, 0, 0, 0, 193, 0, 0, 0, + 194, 195, 0, 196, 197, 0, 198, 199, 0, 0, + 200, 0, 0, 0, 171, 172, 173, 174, 201, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 0, 0, 0, 189, 0, 0, 0, + 0, 190, 0, 0, 0, 0, 191, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 372, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 192, 0, 0, 0, 193, 0, 0, 0, 194, 195, + 0, 196, 197, 0, 198, 199, 0, 0, 200, 0, + 0, 0, 171, 172, 173, 174, 201, 175, 176, 177, + 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 0, 0, 0, 189, 392, 0, 0, 0, 190, + 0, 0, 0, 0, 191, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, + 0, 0, 193, 0, 0, 0, 194, 195, 0, 196, + 197, 0, 198, 199, 0, 0, 200, 0, 0, 0, + 171, 172, 173, 174, 201, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 0, + 0, 0, 189, 0, 0, 0, 0, 190, 0, 0, + 0, 0, 191, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 427, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, + 193, 0, 0, 0, 194, 195, 0, 196, 197, 0, + 198, 199, 0, 0, 200, 0, 0, 0, 171, 172, + 173, 174, 201, 175, 176, 177, 178, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 0, 0, 0, + 189, 0, 0, 0, 0, 190, 0, 0, 0, 0, + 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 192, 0, 0, 0, 193, 0, + 0, 0, 194, 195, 0, 196, 197, 0, 198, 199, + 0, 0, 200, 0, 0, 0, 171, 172, 173, 174, + 201, 175, 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 0, 0, 0, 189, 0, + 0, 0, 0, 190, 0, 0, 0, 0, 191, 0, + 171, 172, 173, 174, 0, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 0, + 0, 0, 192, 0, 0, 0, 193, 190, 0, 0, + 194, 195, 191, 196, 197, 0, 198, 199, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 201, 0, + 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, + 193, 0, 0, 0, 194, 195, 0, 196, 197, 0, + 198, 199, 171, 172, 173, 174, 0, 175, 176, 177, + 178, 0, 201, 181, 182, 183, 184, 0, 0, 187, + 188, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 191, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 401 + }; + + const short + parser::yycheck_[] = + { + 19, 20, 21, 308, 6, 108, 19, 20, 21, 77, + 78, 234, 80, 111, 362, 8, 9, 275, 27, 367, + 155, 53, 54, 53, 54, 39, 100, 317, 96, 50, + 47, 49, 4, 36, 6, 33, 27, 105, 4, 113, + 6, 99, 4, 114, 6, 116, 117, 61, 57, 67, + 71, 47, 110, 51, 43, 47, 361, 66, 77, 78, + 79, 80, 81, 80, 77, 78, 57, 80, 81, 167, + 42, 36, 86, 36, 77, 66, 42, 96, 368, 111, + 42, 111, 91, 96, 80, 94, 105, 108, 80, 92, + 109, 349, 105, 107, 229, 98, 109, 320, 100, 447, + 39, 40, 3, 94, 48, 3, 114, 5, 47, 117, + 48, 113, 77, 7, 77, 35, 4, 4, 6, 6, + 425, 224, 115, 0, 63, 193, 4, 92, 6, 92, + 149, 32, 76, 98, 78, 98, 69, 81, 76, 78, + 78, 80, 16, 81, 64, 49, 34, 86, 68, 168, + 89, 249, 101, 221, 459, 75, 76, 49, 49, 101, + 80, 10, 11, 67, 78, 14, 40, 16, 107, 4, + 90, 6, 191, 5, 193, 67, 67, 275, 5, 4, + 193, 6, 65, 3, 489, 5, 56, 8, 9, 10, + 11, 40, 13, 14, 15, 16, 215, 216, 19, 20, + 21, 22, 221, 216, 25, 26, 109, 4, 221, 6, + 8, 9, 10, 11, 16, 17, 14, 285, 16, 40, + 20, 21, 8, 9, 10, 11, 97, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 81, 40, 341, 30, 3, 101, 102, 103, 35, + 3, 349, 107, 4, 40, 110, 4, 6, 6, 327, + 3, 3, 8, 9, 10, 11, 285, 13, 14, 15, + 16, 4, 285, 6, 342, 3, 112, 5, 64, 25, + 26, 4, 68, 6, 115, 115, 72, 73, 3, 75, + 76, 29, 78, 79, 40, 4, 82, 6, 4, 397, + 6, 4, 80, 6, 90, 4, 74, 6, 327, 4, + 4, 6, 6, 4, 327, 6, 335, 81, 32, 3, + 74, 3, 74, 342, 42, 111, 95, 6, 6, 342, + 398, 4, 6, 4, 41, 433, 40, 5, 62, 8, + 9, 10, 11, 362, 13, 14, 15, 16, 367, 362, + 19, 20, 21, 22, 367, 3, 25, 26, 3, 3, + 3, 116, 4, 4, 62, 4, 116, 465, 4, 116, + 4, 40, 4, 3, 34, 4, 48, 70, 3, 398, + 70, 70, 48, 4, 89, 398, 55, 70, 28, 298, + 28, 410, 216, 28, 216, 8, 9, 10, 11, 327, + 13, 14, 15, 16, 163, 206, 19, 20, 21, 22, + 309, 103, 25, 26, 367, 152, 507, 414, 512, 487, + -1, 113, 114, 115, 116, -1, -1, 40, 447, 109, + 122, -1, -1, -1, 447, -1, -1, -1, -1, -1, + -1, -1, 55, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 487, 161, + -1, -1, 164, -1, 487, -1, -1, -1, 170, 171, + 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, -1, + 192, -1, 194, -1, 196, 197, -1, -1, 200, 201, + -1, -1, -1, -1, 206, -1, -1, -1, -1, -1, + -1, -1, 8, 9, 10, 11, -1, 13, 14, 15, + 16, -1, -1, 19, 20, 21, 22, -1, -1, 25, + 26, -1, -1, -1, -1, -1, 238, -1, 240, -1, + 8, 9, 10, 11, 40, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 55, + -1, -1, 30, -1, -1, -1, -1, 35, -1, -1, + -1, -1, 40, -1, -1, -1, -1, 279, -1, -1, + -1, 283, 284, -1, 286, 287, -1, 289, -1, -1, + 292, -1, -1, -1, -1, -1, 64, 299, -1, 301, + 68, -1, -1, -1, 72, 73, -1, 75, 76, -1, + 78, 79, 314, -1, 82, 317, -1, -1, -1, -1, + 322, -1, 90, 325, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 336, 337, 104, -1, -1, -1, + -1, 343, -1, 345, 346, -1, -1, -1, -1, -1, + -1, -1, -1, 355, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 365, -1, -1, 368, -1, -1, -1, + -1, 373, -1, -1, -1, -1, 3, 4, -1, -1, + -1, 8, 9, 10, -1, 12, -1, 389, -1, -1, + 392, 393, -1, -1, -1, -1, -1, 399, 400, 401, + 27, 28, 29, -1, -1, -1, 33, -1, -1, 36, + 37, 38, -1, -1, 41, -1, -1, 44, 45, 46, + -1, -1, 49, -1, 51, 52, -1, 54, -1, -1, + 57, 58, 59, 60, -1, -1, 63, 64, -1, 66, + 67, -1, -1, 70, -1, -1, -1, 74, 75, 76, + 77, 78, -1, 80, -1, -1, 83, 84, 85, -1, + 87, 88, -1, 90, 91, 92, 93, 94, 95, 96, + -1, -1, 99, 100, -1, 102, 103, -1, 105, 106, + -1, -1, -1, 110, -1, -1, 113, 114, 115, 116, + 117, 118, 119, 3, 4, -1, -1, -1, 8, 9, + -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 27, 28, 29, + -1, -1, -1, 33, -1, -1, 36, 37, 38, -1, + -1, 41, -1, -1, 44, 45, 46, -1, -1, 49, + -1, 51, -1, -1, 54, -1, -1, 57, 58, 59, + 60, -1, -1, 63, 64, -1, 66, 67, -1, -1, + 70, -1, -1, -1, 74, 75, 76, 77, 78, -1, + 80, -1, -1, 83, 84, 85, -1, 87, 88, -1, + 90, 91, 92, 93, 94, 95, 96, 97, -1, 99, + 100, -1, 102, 103, -1, 105, 106, -1, -1, -1, + 110, -1, -1, 113, 114, 115, 116, 117, 118, 119, + 3, 4, -1, -1, -1, 8, 9, -1, -1, 12, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 27, 28, 29, -1, -1, -1, + 33, -1, -1, 36, 37, 38, -1, -1, 41, -1, + -1, 44, 45, 46, -1, -1, 49, -1, 51, -1, + -1, 54, -1, -1, 57, 58, 59, 60, -1, -1, + 63, 64, -1, 66, 67, -1, -1, 70, -1, -1, + -1, 74, 75, 76, 77, 78, -1, 80, -1, -1, + 83, 84, 85, -1, 87, 88, -1, 90, 91, 92, + 93, 94, 95, 96, 97, -1, 99, 100, -1, 102, + 103, -1, 105, 106, -1, -1, -1, 110, -1, -1, + 113, 114, 115, 116, 117, 118, 119, 3, 4, -1, + -1, -1, 8, 9, -1, -1, 12, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 27, 28, 29, -1, -1, -1, 33, -1, -1, + 36, 37, 38, -1, -1, 41, -1, -1, 44, 45, + 46, -1, -1, 49, -1, 51, -1, -1, 54, -1, + -1, 57, 58, 59, 60, -1, -1, 63, 64, -1, + 66, 67, -1, -1, 70, -1, -1, -1, 74, 75, + 76, 77, 78, -1, 80, -1, -1, 83, 84, 85, + -1, 87, 88, -1, 90, 91, 92, 93, 94, 95, + 96, -1, -1, 99, 100, -1, 102, 103, -1, 105, + 106, -1, -1, -1, 110, -1, -1, 113, 114, 115, + 116, 117, 118, 119, 3, -1, -1, -1, -1, 8, + 9, -1, -1, 12, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 27, 28, + 29, -1, -1, -1, 33, -1, -1, 36, 37, 38, + -1, -1, 41, -1, -1, 44, 45, 46, -1, -1, + 49, -1, 51, -1, -1, 54, -1, -1, 57, 58, + 59, 60, -1, -1, 63, 64, -1, 66, 67, -1, + -1, 70, -1, -1, -1, 74, 75, 76, 77, 78, + -1, 80, -1, -1, 83, 84, 85, -1, 87, 88, + -1, 90, 91, 92, 93, 94, 95, 96, -1, -1, + 99, 100, -1, 102, 103, -1, 105, 106, -1, -1, + -1, 110, 111, -1, 113, 114, 115, 116, 117, 118, + 119, 3, -1, -1, -1, -1, 8, 9, -1, -1, + 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 27, 28, 29, -1, -1, + -1, 33, -1, -1, 36, 37, 38, -1, -1, 41, + -1, -1, 44, 45, 46, -1, -1, 49, -1, 51, + 52, -1, 54, -1, -1, 57, 58, 59, 60, -1, + -1, 63, 64, -1, 66, 67, -1, -1, 70, -1, + -1, -1, 74, 75, 76, 77, 78, -1, 80, -1, + -1, 83, 84, 85, -1, 87, 88, -1, 90, 91, + 92, 93, 94, 95, 96, -1, -1, 99, 100, -1, + 102, 103, -1, 105, 106, -1, -1, -1, 110, -1, + -1, 113, 114, 115, 116, 117, 118, 119, 3, -1, + -1, -1, -1, 8, 9, -1, -1, 12, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 27, 28, 29, -1, -1, -1, 33, -1, + -1, 36, 37, 38, -1, -1, 41, -1, -1, 44, + 45, 46, -1, -1, 49, -1, 51, 52, -1, 54, + -1, -1, 57, 58, 59, 60, -1, -1, 63, 64, + -1, 66, 67, -1, -1, 70, -1, -1, -1, 74, + 75, 76, 77, 78, -1, 80, -1, -1, 83, 84, + 85, -1, 87, 88, -1, 90, 91, 92, 93, 94, + 95, 96, -1, -1, 99, 100, -1, 102, 103, -1, + 105, 106, -1, -1, -1, 110, -1, -1, 113, 114, + 115, 116, 117, 118, 119, 3, 4, -1, -1, -1, + 8, 9, -1, -1, 12, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, + 28, 29, -1, -1, -1, 33, -1, -1, 36, 37, + 38, -1, -1, 41, -1, -1, 44, 45, 46, -1, + -1, 49, -1, 51, -1, -1, 54, -1, -1, 57, + 58, 59, 60, -1, -1, 63, 64, -1, 66, 67, + -1, -1, 70, -1, -1, -1, 74, 75, 76, 77, + 78, -1, 80, -1, -1, 83, 84, 85, -1, 87, + 88, -1, 90, 91, 92, 93, 94, 95, 96, -1, + -1, 99, 100, -1, 102, 103, -1, 105, 106, -1, + -1, -1, 110, -1, -1, 113, 114, 115, 116, 117, + 118, 119, 3, 4, -1, -1, -1, 8, 9, -1, + -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 27, 28, 29, -1, + -1, -1, 33, -1, -1, 36, 37, 38, -1, -1, + 41, -1, -1, 44, 45, 46, -1, -1, 49, -1, + 51, -1, -1, 54, -1, -1, 57, 58, 59, 60, + -1, -1, 63, 64, -1, 66, 67, -1, -1, 70, + -1, -1, -1, 74, 75, 76, 77, 78, -1, 80, + -1, -1, 83, 84, 85, -1, 87, 88, -1, 90, + 91, 92, 93, 94, 95, 96, -1, -1, 99, 100, + -1, 102, 103, -1, 105, 106, -1, -1, -1, 110, + -1, -1, 113, 114, 115, 116, 117, 118, 119, 3, + -1, -1, -1, -1, 8, 9, -1, -1, 12, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 27, 28, 29, -1, -1, -1, 33, + -1, -1, 36, 37, 38, -1, -1, 41, -1, -1, + 44, 45, 46, -1, -1, 49, -1, 51, -1, -1, + 54, -1, -1, 57, 58, 59, 60, -1, -1, 63, + 64, -1, 66, 67, -1, -1, 70, -1, -1, -1, + 74, 75, 76, 77, 78, -1, 80, -1, -1, 83, + 84, 85, -1, 87, 88, -1, 90, 91, 92, 93, + 94, 95, 96, -1, -1, 99, 100, -1, 102, 103, + -1, 105, 106, -1, -1, -1, 110, -1, -1, 113, + 114, 115, 116, 117, 118, 119, 3, -1, -1, -1, + -1, 8, 9, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 27, 28, 29, -1, -1, -1, 33, -1, -1, 36, + -1, 38, -1, -1, 41, -1, -1, 44, 45, 46, + -1, -1, 49, -1, 51, -1, -1, 54, -1, -1, + 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, + 67, -1, -1, 70, -1, -1, -1, 74, 75, 76, + 77, -1, -1, 80, -1, -1, 83, 84, 85, -1, + 87, 88, -1, 90, 91, 92, 93, 94, 95, 96, + 3, -1, 99, 100, -1, 102, 103, -1, 105, 106, + -1, -1, -1, 110, -1, -1, 113, 114, 115, 116, + 117, 118, -1, -1, 27, 28, 29, -1, -1, -1, + 33, -1, -1, 36, -1, 38, -1, -1, 41, -1, + -1, 44, 45, 46, -1, -1, 49, -1, 51, -1, + -1, 54, -1, -1, 57, -1, 59, 60, -1, -1, + 63, 64, -1, 66, 67, -1, -1, 70, -1, -1, + -1, 74, 75, 76, 77, -1, -1, -1, -1, -1, + 83, 84, 85, -1, 87, 88, -1, 90, 91, 92, + 93, 94, 95, 96, 3, -1, 99, 100, -1, 102, + 103, -1, -1, 106, -1, -1, -1, 110, -1, -1, + 113, 114, -1, 116, 117, -1, -1, -1, 27, 28, + 29, -1, -1, -1, 33, -1, -1, 36, -1, 38, + -1, -1, 41, -1, -1, 44, 45, 46, -1, -1, + 49, -1, 51, -1, -1, 54, -1, -1, 57, -1, + 59, 60, -1, -1, 63, 64, -1, 66, 67, -1, + -1, 70, -1, -1, -1, 74, 75, 76, 77, -1, + -1, -1, -1, -1, 83, 84, 85, -1, 87, 88, + -1, 90, 91, 92, 93, 94, 95, 96, 3, -1, + 99, 100, -1, 102, 103, -1, -1, 106, -1, -1, + -1, 110, -1, -1, 113, 114, -1, 116, 117, -1, + -1, -1, 27, 28, 29, -1, -1, -1, 33, -1, + -1, 36, -1, 38, -1, -1, 41, -1, -1, 44, + 45, 46, -1, -1, 49, -1, 51, -1, -1, 54, + -1, -1, 57, -1, 59, 60, -1, -1, 63, 64, + -1, 66, 67, -1, -1, 70, -1, -1, -1, 74, + 75, 76, 77, -1, -1, -1, -1, -1, 83, 84, + 85, -1, 87, 88, -1, 90, 91, 92, 93, 94, + 95, 96, -1, -1, 99, 100, -1, 102, 103, -1, + -1, 106, -1, -1, -1, 110, -1, -1, 113, 114, + -1, 116, 117, 8, 9, 10, 11, -1, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, -1, -1, -1, 30, -1, -1, -1, -1, + 35, -1, -1, -1, -1, 40, -1, -1, -1, -1, + -1, -1, -1, 8, 9, 10, 11, -1, 13, 14, + 15, 16, -1, -1, 19, 20, 21, 22, -1, 64, + 25, 26, -1, 68, -1, -1, -1, 72, 73, -1, + 75, 76, -1, 78, 79, 40, -1, 82, 27, 28, + 29, -1, -1, -1, 33, 90, -1, 36, -1, 38, + 55, -1, 41, 42, -1, 44, 45, 46, -1, 104, + 49, -1, 51, -1, -1, 54, -1, -1, 57, -1, + 59, 60, -1, -1, 63, 64, 65, 66, 67, -1, + -1, 70, -1, -1, -1, 74, 75, 76, 77, -1, + -1, -1, -1, -1, 83, 84, 85, -1, 87, 88, + -1, 90, 91, 92, 93, 94, 95, 96, -1, -1, + 99, 100, -1, 102, 103, -1, -1, 106, -1, -1, + -1, 110, -1, -1, 113, 114, -1, 116, 117, 27, + 28, 29, -1, -1, -1, 33, -1, -1, 36, -1, + 38, -1, -1, 41, -1, -1, 44, 45, 46, -1, + -1, 49, -1, 51, -1, -1, 54, -1, -1, 57, + -1, 59, 60, -1, -1, 63, 64, 65, 66, 67, + -1, -1, 70, -1, -1, -1, 74, 75, 76, 77, + -1, -1, -1, -1, -1, 83, 84, 85, -1, 87, + 88, -1, 90, 91, 92, 93, 94, 95, 96, -1, + -1, 99, 100, -1, 102, 103, -1, -1, 106, -1, + -1, -1, 110, -1, -1, 113, 114, -1, 116, 117, + 27, 28, 29, -1, -1, -1, 33, -1, -1, 36, + -1, 38, -1, -1, 41, -1, -1, 44, 45, 46, + -1, -1, 49, -1, 51, -1, -1, 54, -1, -1, + 57, -1, 59, 60, -1, -1, 63, 64, -1, 66, + 67, -1, -1, 70, -1, -1, -1, 74, 75, 76, + 77, -1, -1, -1, -1, -1, 83, 84, 85, -1, + 87, 88, -1, 90, 91, 92, 93, 94, 95, 96, + -1, -1, 99, 100, -1, 102, 103, -1, -1, 106, + -1, -1, -1, 110, -1, -1, 113, 114, -1, 116, + 117, 27, 28, 29, -1, -1, -1, 33, -1, -1, + 36, -1, 38, -1, -1, 41, -1, -1, 44, 45, + 46, -1, -1, 49, -1, 51, -1, -1, 54, -1, + -1, 57, -1, 59, 60, -1, -1, 63, 64, -1, + 66, 67, -1, -1, 70, -1, -1, -1, 74, 75, + 76, 77, -1, -1, -1, -1, -1, 83, 84, 85, + -1, 87, 88, -1, 90, 91, 92, 93, 94, 95, + 96, -1, -1, 99, 100, -1, 102, 103, -1, -1, + 106, -1, -1, -1, 110, -1, -1, 113, 114, 4, + 116, 117, -1, 8, 9, 10, 11, -1, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, -1, -1, -1, 30, -1, -1, -1, -1, + 35, -1, -1, -1, -1, 40, -1, 8, 9, 10, + 11, -1, 13, 14, 15, 16, -1, -1, 19, 20, + 21, 22, -1, -1, 25, 26, -1, -1, -1, 64, + -1, -1, -1, 68, -1, -1, -1, 72, 73, 40, + 75, 76, -1, 78, 79, -1, -1, 82, -1, -1, + -1, -1, 4, -1, 55, 90, 8, 9, 10, 11, + -1, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, -1, -1, -1, 30, -1, + -1, -1, -1, 35, -1, -1, -1, -1, 40, -1, + 8, 9, 10, 11, -1, 13, 14, 15, 16, -1, + -1, 19, 20, 21, 22, -1, -1, 25, 26, -1, + -1, -1, 64, -1, -1, -1, 68, -1, -1, -1, + 72, 73, 40, 75, 76, -1, 78, 79, -1, -1, + 82, -1, -1, -1, -1, 4, -1, 55, 90, 8, + 9, 10, 11, -1, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, -1, -1, + -1, 30, -1, -1, -1, -1, 35, -1, -1, -1, + -1, 40, -1, 8, 9, 10, 11, -1, 13, 14, + 15, 16, -1, -1, 19, 20, 21, 22, -1, -1, + 25, 26, -1, -1, -1, 64, -1, -1, -1, 68, + -1, -1, -1, 72, 73, 40, 75, 76, -1, 78, + 79, -1, -1, 82, -1, -1, -1, -1, 4, -1, + 55, 90, 8, 9, 10, 11, -1, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, -1, -1, -1, 30, -1, -1, -1, -1, 35, + -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 64, -1, + -1, -1, 68, -1, -1, -1, 72, 73, -1, 75, + 76, -1, 78, 79, -1, -1, 82, -1, -1, -1, + 8, 9, 10, 11, 90, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, -1, + -1, -1, 30, -1, -1, 33, -1, 35, -1, -1, + -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 51, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 64, -1, -1, -1, + 68, -1, -1, -1, 72, 73, -1, 75, 76, -1, + 78, 79, -1, -1, 82, -1, -1, -1, 8, 9, + 10, 11, 90, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, -1, -1, -1, + 30, -1, 32, -1, -1, 35, -1, -1, -1, -1, + 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 64, -1, -1, -1, 68, -1, + -1, -1, 72, 73, -1, 75, 76, -1, 78, 79, + -1, -1, 82, -1, -1, -1, 8, 9, 10, 11, + 90, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, -1, -1, -1, 30, 31, + -1, -1, -1, 35, -1, -1, -1, -1, 40, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 64, -1, -1, -1, 68, -1, -1, -1, + 72, 73, -1, 75, 76, -1, 78, 79, -1, -1, + 82, -1, -1, -1, 8, 9, 10, 11, 90, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, -1, -1, -1, 30, -1, -1, -1, + -1, 35, -1, -1, -1, -1, 40, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 54, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 64, -1, -1, -1, 68, -1, -1, -1, 72, 73, + -1, 75, 76, -1, 78, 79, -1, -1, 82, -1, + -1, -1, 8, 9, 10, 11, 90, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, -1, -1, -1, 30, 31, -1, -1, -1, 35, + -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 64, -1, + -1, -1, 68, -1, -1, -1, 72, 73, -1, 75, + 76, -1, 78, 79, -1, -1, 82, -1, -1, -1, + 8, 9, 10, 11, 90, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, -1, + -1, -1, 30, -1, -1, -1, -1, 35, -1, -1, + -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 54, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 64, -1, -1, -1, + 68, -1, -1, -1, 72, 73, -1, 75, 76, -1, + 78, 79, -1, -1, 82, -1, -1, -1, 8, 9, + 10, 11, 90, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, -1, -1, -1, + 30, -1, -1, -1, -1, 35, -1, -1, -1, -1, + 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 64, -1, -1, -1, 68, -1, + -1, -1, 72, 73, -1, 75, 76, -1, 78, 79, + -1, -1, 82, -1, -1, -1, 8, 9, 10, 11, + 90, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, -1, -1, -1, 30, -1, + -1, -1, -1, 35, -1, -1, -1, -1, 40, -1, + 8, 9, 10, 11, -1, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, -1, + -1, -1, 64, -1, -1, -1, 68, 35, -1, -1, + 72, 73, 40, 75, 76, -1, 78, 79, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 90, -1, + -1, -1, -1, -1, -1, -1, 64, -1, -1, -1, + 68, -1, -1, -1, 72, 73, -1, 75, 76, -1, + 78, 79, 8, 9, 10, 11, -1, 13, 14, 15, + 16, -1, 90, 19, 20, 21, 22, -1, -1, 25, + 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 55 + }; + + const unsigned char + parser::yystos_[] = + { + 0, 43, 121, 122, 152, 154, 176, 102, 103, 107, + 110, 147, 155, 0, 7, 101, 69, 101, 65, 145, + 145, 145, 78, 27, 28, 29, 33, 36, 38, 41, + 44, 45, 46, 49, 51, 54, 57, 59, 60, 63, + 64, 66, 67, 70, 74, 75, 76, 77, 83, 84, + 85, 87, 88, 90, 91, 92, 93, 94, 95, 96, + 99, 100, 102, 103, 106, 110, 113, 114, 116, 117, + 124, 125, 126, 149, 149, 149, 56, 5, 5, 109, + 81, 3, 32, 102, 124, 126, 126, 124, 126, 44, + 45, 46, 65, 116, 124, 125, 127, 165, 166, 97, + 144, 3, 153, 3, 126, 130, 131, 160, 164, 6, + 175, 3, 4, 8, 9, 12, 37, 38, 44, 45, + 46, 58, 78, 80, 87, 105, 115, 116, 118, 119, + 123, 124, 125, 132, 133, 134, 135, 136, 137, 138, + 139, 141, 142, 143, 143, 150, 151, 3, 126, 42, + 163, 167, 165, 167, 173, 174, 4, 135, 143, 143, + 143, 111, 140, 143, 3, 143, 3, 3, 5, 4, + 6, 8, 9, 10, 11, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 30, + 35, 40, 64, 68, 72, 73, 75, 76, 78, 79, + 82, 90, 33, 51, 146, 4, 6, 8, 9, 115, + 128, 129, 116, 124, 39, 40, 47, 63, 78, 80, + 86, 89, 107, 162, 164, 39, 61, 86, 107, 6, + 173, 100, 113, 156, 157, 158, 4, 143, 53, 54, + 111, 140, 143, 27, 57, 66, 94, 4, 10, 52, + 135, 124, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 124, 143, 3, 124, 126, 52, 78, + 143, 143, 143, 35, 64, 68, 75, 76, 80, 90, + 143, 143, 112, 148, 150, 115, 115, 4, 6, 3, + 124, 3, 65, 123, 124, 125, 128, 29, 80, 74, + 126, 81, 159, 32, 3, 74, 74, 3, 173, 95, + 6, 156, 104, 143, 143, 53, 54, 32, 6, 6, + 4, 6, 4, 135, 4, 5, 31, 55, 4, 135, + 144, 3, 5, 62, 52, 55, 55, 143, 143, 3, + 124, 126, 143, 143, 143, 55, 143, 129, 143, 143, + 159, 146, 3, 169, 41, 3, 143, 3, 3, 151, + 156, 143, 54, 104, 143, 131, 116, 116, 116, 4, + 124, 143, 143, 4, 4, 135, 124, 126, 143, 62, + 143, 143, 31, 55, 4, 135, 144, 3, 5, 55, + 55, 55, 143, 4, 4, 4, 159, 127, 168, 48, + 76, 78, 81, 170, 171, 172, 27, 57, 66, 91, + 94, 143, 4, 168, 151, 4, 143, 54, 4, 4, + 4, 4, 4, 3, 143, 143, 143, 4, 4, 135, + 124, 126, 143, 143, 143, 34, 4, 6, 70, 124, + 48, 50, 71, 108, 48, 78, 170, 4, 4, 4, + 34, 159, 4, 135, 4, 3, 127, 49, 67, 70, + 36, 77, 92, 98, 36, 77, 92, 98, 36, 77, + 92, 98, 70, 48, 99, 110, 161, 89, 159, 4, + 4, 4, 135, 49, 67, 28, 47, 80, 28, 47, + 80, 28, 47, 80, 49, 67, 70, 126, 159, 4, + 49, 67, 169, 172 + }; + + const unsigned char + parser::yyr1_[] = + { + 0, 120, 121, 121, 122, 122, 122, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 124, 124, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 125, 126, + 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, + 127, 127, 128, 128, 129, 129, 130, 130, 131, 131, + 131, 132, 132, 132, 132, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 135, 135, 136, 136, 136, 136, + 137, 137, 137, 138, 138, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 140, 140, 141, 141, 141, 141, 142, 142, 142, + 142, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 144, + 145, 145, 146, 146, 146, 147, 147, 148, 148, 149, + 149, 149, 150, 151, 151, 152, 153, 153, 153, 154, + 155, 155, 155, 156, 156, 157, 157, 157, 158, 158, + 159, 159, 159, 159, 159, 159, 160, 160, 161, 161, + 161, 162, 162, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 163, 163, 163, 163, 164, 164, + 165, 166, 166, 167, 167, 167, 168, 168, 169, 169, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 171, 171, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 173, 173, 173, 173, 173, 174, 174, 174, + 175, 175, 176, 176 + }; + + const signed char + parser::yyr2_[] = + { + 0, 2, 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 1, 1, 1, 2, 1, 4, + 6, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 5, 6, 3, 3, 3, 3, + 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, + 6, 6, 6, 6, 1, 3, 4, 5, 3, 4, + 2, 2, 3, 5, 6, 4, 5, 5, 5, 3, + 7, 8, 6, 5, 6, 6, 6, 4, 8, 9, + 7, 4, 5, 6, 4, 5, 3, 4, 6, 6, + 6, 1, 1, 1, 5, 3, 1, 1, 1, 1, + 3, 6, 3, 1, 1, 1, 1, 1, 1, 1, + 0, 3, 0, 1, 1, 0, 1, 0, 2, 3, + 3, 1, 2, 1, 3, 11, 0, 2, 3, 8, + 0, 1, 1, 2, 1, 1, 3, 2, 0, 1, + 0, 3, 3, 3, 3, 3, 0, 1, 0, 1, + 1, 0, 2, 5, 6, 4, 2, 3, 5, 3, + 3, 3, 3, 3, 5, 3, 5, 7, 0, 2, + 2, 2, 4, 0, 2, 2, 1, 3, 0, 3, + 4, 4, 3, 3, 4, 4, 4, 3, 3, 4, + 4, 4, 3, 3, 4, 2, 1, 2, 0, 1, + 4, 4, 2, 5, 5, 3, 3, 3, 1, 4, + 4, 2, 7, 8, 6, 5, 10, 1, 3, 2, + 0, 2, 7, 10 + }; + + +#if YYDEBUG || 1 + // YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + // First, the terminals, then, starting at \a YYNTOKENS, nonterminals. + const char* + const parser::yytname_[] = + { + "\"end of file\"", "error", "\"invalid token\"", "\"(\"", "\")\"", + "\".\"", "\",\"", "\";\"", "\"+\"", "\"-\"", "\"*\"", "\"/\"", "\"~\"", + "\"&\"", "\"%\"", "\"|\"", "\"||\"", "\"=\"", "\"==\"", "\">\"", + "\">=\"", "\"<\"", "\"<=\"", "\"!=\"", "\"<>\"", "\"<<\"", "\">>\"", + "\"ABORT\"", "\"ACTION\"", "\"ALWAYS\"", "\"AND\"", "\"AND BETWEEN\"", + "\"AS\"", "\"ASC\"", "\"AUTOINCREMENT\"", "\"BETWEEN\"", "\"CASCADE\"", + "\"CASE\"", "\"CAST\"", "\"CHECK\"", "\"COLLATE\"", "\"CONFLICT\"", + "\"CONSTRAINT\"", "\"CREATE\"", "\"CURRENT_DATE\"", "\"CURRENT_TIME\"", + "\"CURRENT_TIMESTAMP\"", "\"DEFAULT\"", "\"DEFERRABLE\"", "\"DEFERRED\"", + "\"DELETE\"", "\"DESC\"", "\"DISTINCT\"", "\"ELSE\"", "\"END\"", + "\"ESCAPE\"", "\"EXISTS\"", "\"FAIL\"", "\"FALSE\"", "\"FILTER\"", + "\"FOLLOWING\"", "\"FOREIGN\"", "\"FROM\"", "\"GENERATED\"", "\"GLOB\"", + "\"IF\"", "\"IGNORE\"", "\"IMMEDIATE\"", "\"IN\"", "\"INDEX\"", + "\"INITIALLY\"", "\"INSERT\"", "\"IS\"", "\"ISNULL\"", "\"KEY\"", + "\"LIKE\"", "\"MATCH\"", "\"NO\"", "\"NOT\"", "\"NOTNULL\"", "\"NULL\"", + "\"ON\"", "\"OR\"", "\"OVER\"", "\"PARTITION\"", "\"PRECEDING\"", + "\"PRIMARY\"", "\"RAISE\"", "\"RANGE\"", "\"REFERENCES\"", "\"REGEXP\"", + "\"REPLACE\"", "\"RESTRICT\"", "\"RETURNING\"", "\"ROLLBACK\"", + "\"ROWID\"", "\"ROWS\"", "\"SELECT\"", "\"SET\"", "\"STORED\"", + "\"STRICT\"", "\"TABLE\"", "\"TEMP\"", "\"TEMPORARY\"", "\"THEN\"", + "\"TRUE\"", "\"UNBOUNDED\"", "\"UNIQUE\"", "\"UPDATE\"", "\"USING\"", + "\"VIRTUAL\"", "\"WHEN\"", "\"WHERE\"", "\"WITHOUT\"", "\"identifier\"", + "\"numeric\"", "\"string literal\"", "\"quoted literal\"", + "\"blob literal\"", "\"bind parameter\"", "$accept", "sql", "statement", + "literalvalue", "id", "allowed_keywords_as_identifier", "tableid", + "columnid", "signednumber", "signednumber_or_numeric", + "typename_namelist", "type_name", "unary_expr", "binary_expr", + "like_expr", "exprlist_expr", "function_expr", "isnull_expr", + "between_expr", "in_expr", "whenthenlist_expr", "case_expr", + "raise_expr", "expr", "select_stmt", "optional_if_not_exists", + "optional_sort_order", "optional_unique", "optional_where", + "tableid_with_uninteresting_schema", "indexed_column", + "indexed_column_list", "createindex_stmt", + "optional_exprlist_with_paren", "createvirtualtable_stmt", + "optional_temporary", "tableoption", "tableoptions_list", + "optional_tableoptions_list", "optional_conflictclause", + "optional_typename", "optional_storage_identifier", + "optional_always_generated", "columnconstraint", "columnconstraint_list", + "columndef", "columndef_list", "optional_constraintname", + "columnid_list", "optional_columnid_with_paren_list", "fk_clause_part", + "fk_clause_part_list", "optional_fk_clause", "tableconstraint", + "tableconstraint_list", "optional_tableconstraint_list", + "createtable_stmt", YY_NULLPTR + }; +#endif + + +#if YYDEBUG + const short + parser::yyrline_[] = + { + 0, 273, 273, 274, 278, 279, 280, 288, 289, 290, + 291, 292, 293, 294, 295, 296, 300, 301, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, 350, + 351, 352, 353, 354, 355, 359, 360, 361, 362, 363, + 364, 365, 369, 370, 374, 375, 379, 380, 384, 385, + 386, 390, 391, 392, 393, 397, 398, 399, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 416, 417, 418, 419, 423, 424, + 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, + 435, 436, 437, 438, 442, 443, 447, 448, 449, 450, + 454, 455, 456, 460, 461, 465, 466, 467, 468, 469, + 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, + 480, 484, 485, 489, 490, 491, 492, 496, 497, 498, + 499, 503, 504, 505, 506, 507, 508, 509, 510, 511, + 512, 513, 514, 515, 516, 517, 518, 519, 520, 529, + 537, 538, 542, 543, 544, 552, 553, 557, 558, 562, + 563, 564, 568, 585, 586, 590, 605, 606, 607, 611, + 623, 624, 625, 629, 630, 634, 635, 636, 640, 641, + 645, 646, 647, 648, 649, 650, 654, 655, 659, 660, + 661, 665, 666, 670, 676, 683, 689, 691, 697, 702, + 707, 712, 717, 723, 728, 733, 738, 746, 767, 768, + 781, 785, 786, 790, 791, 792, 796, 797, 801, 802, + 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, + 816, 817, 818, 819, 820, 821, 825, 826, 830, 831, + 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, + 842, 843, 847, 853, 860, 867, 872, 880, 881, 882, + 886, 887, 891, 895 + }; + + void + parser::yy_stack_print_ () const + { + *yycdebug_ << "Stack now"; + for (stack_type::const_iterator + i = yystack_.begin (), + i_end = yystack_.end (); + i != i_end; ++i) + *yycdebug_ << ' ' << int (i->state); + *yycdebug_ << '\n'; + } + + void + parser::yy_reduce_print_ (int yyrule) const + { + int yylno = yyrline_[yyrule]; + int yynrhs = yyr2_[yyrule]; + // Print the symbols being reduced, and their result. + *yycdebug_ << "Reducing stack by rule " << yyrule - 1 + << " (line " << yylno << "):\n"; + // The symbols being reduced. + for (int yyi = 0; yyi < yynrhs; yyi++) + YY_SYMBOL_PRINT (" $" << yyi + 1 << " =", + yystack_[(yynrhs) - (yyi + 1)]); + } +#endif // YYDEBUG + + +#line 10 "sqlite3_parser.yy" +} } // sqlb::parser +#line 4868 "sqlite3_parser.cpp" + +#line 916 "sqlite3_parser.yy" + + +void sqlb::parser::parser::error(const location_type& l, const std::string& m) +{ + std::cerr << l << ": " << m << std::endl; +} diff --git a/src/sql/parser/sqlite3_parser.hpp b/src/sql/parser/sqlite3_parser.hpp new file mode 100644 index 000000000..52aea06a8 --- /dev/null +++ b/src/sql/parser/sqlite3_parser.hpp @@ -0,0 +1,4418 @@ +// A Bison parser, made by GNU Bison 3.8.2. + +// Skeleton interface for Bison LALR(1) parsers in C++ + +// Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// As a special exception, you may create a larger work that contains +// part or all of the Bison parser skeleton and distribute that work +// under terms of your choice, so long as that work isn't itself a +// parser generator using the skeleton or a modified version thereof +// as a parser skeleton. Alternatively, if you modify or redistribute +// the parser skeleton itself, you may (at your option) remove this +// special exception, which will cause the skeleton and the resulting +// Bison output files to be licensed under the GNU General Public +// License without this special exception. + +// This special exception was added by the Free Software Foundation in +// version 2.2 of Bison. + + +/** + ** \file sqlite3_parser.hpp + ** Define the sqlb::parser ::parser class. + */ + +// C++ LALR(1) parser skeleton written by Akim Demaille. + +// DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, +// especially those whose name start with YY_ or yy_. They are +// private implementation details that can be changed or removed. + +#ifndef YY_YY_SQLITE3_PARSER_HPP_INCLUDED +# define YY_YY_SQLITE3_PARSER_HPP_INCLUDED +// "%code requires" blocks. +#line 12 "sqlite3_parser.yy" + + #include + #include + #include "../sqlitetypes.h" + #include "../ObjectIdentifier.h" + namespace sqlb { namespace parser { class ParserDriver; } } + typedef void* yyscan_t; + + struct TableConstraints + { + std::multimap> index; + std::multimap> fk; + std::vector> check; + }; + + using ColumnList = std::pair>, TableConstraints>; + +#line 67 "sqlite3_parser.hpp" + +# include +# include // std::abort +# include +# include +# include +# include + +#if defined __cplusplus +# define YY_CPLUSPLUS __cplusplus +#else +# define YY_CPLUSPLUS 199711L +#endif + +// Support move semantics when possible. +#if 201103L <= YY_CPLUSPLUS +# define YY_MOVE std::move +# define YY_MOVE_OR_COPY move +# define YY_MOVE_REF(Type) Type&& +# define YY_RVREF(Type) Type&& +# define YY_COPY(Type) Type +#else +# define YY_MOVE +# define YY_MOVE_OR_COPY copy +# define YY_MOVE_REF(Type) Type& +# define YY_RVREF(Type) const Type& +# define YY_COPY(Type) const Type& +#endif + +// Support noexcept when possible. +#if 201103L <= YY_CPLUSPLUS +# define YY_NOEXCEPT noexcept +# define YY_NOTHROW +#else +# define YY_NOEXCEPT +# define YY_NOTHROW throw () +#endif + +// Support constexpr when possible. +#if 201703 <= YY_CPLUSPLUS +# define YY_CONSTEXPR constexpr +#else +# define YY_CONSTEXPR +#endif +# include "sqlite3_location.h" +#include +#ifndef YY_ASSERT +# include +# define YY_ASSERT assert +#endif + + +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define YY_ATTRIBUTE_PURE +# endif +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +# else +# define YY_ATTRIBUTE_UNUSED +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YY_USE(E) ((void) (E)) +#else +# define YY_USE(E) /* empty */ +#endif + +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") +# else +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# endif +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END \ + _Pragma ("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END +#endif + +# ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast (Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) +# else +# define YY_CAST(Type, Val) ((Type) (Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +# endif +# endif +# ifndef YY_NULLPTR +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# else +# define YY_NULLPTR ((void*)0) +# endif +# endif + +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif + +#line 10 "sqlite3_parser.yy" +namespace sqlb { namespace parser { +#line 208 "sqlite3_parser.hpp" + + + + + /// A Bison parser. + class parser + { + public: +#ifdef YYSTYPE +# ifdef __GNUC__ +# pragma GCC message "bison: do not #define YYSTYPE in C++, use %define api.value.type" +# endif + typedef YYSTYPE value_type; +#else + /// A buffer to store and retrieve objects. + /// + /// Sort of a variant, but does not keep track of the nature + /// of the stored data, since that knowledge is available + /// via the current parser state. + class value_type + { + public: + /// Type of *this. + typedef value_type self_type; + + /// Empty construction. + value_type () YY_NOEXCEPT + : yyraw_ () + , yytypeid_ (YY_NULLPTR) + {} + + /// Construct and fill. + template + value_type (YY_RVREF (T) t) + : yytypeid_ (&typeid (T)) + { + YY_ASSERT (sizeof (T) <= size); + new (yyas_ ()) T (YY_MOVE (t)); + } + +#if 201103L <= YY_CPLUSPLUS + /// Non copyable. + value_type (const self_type&) = delete; + /// Non copyable. + self_type& operator= (const self_type&) = delete; +#endif + + /// Destruction, allowed only if empty. + ~value_type () YY_NOEXCEPT + { + YY_ASSERT (!yytypeid_); + } + +# if 201103L <= YY_CPLUSPLUS + /// Instantiate a \a T in here from \a t. + template + T& + emplace (U&&... u) + { + YY_ASSERT (!yytypeid_); + YY_ASSERT (sizeof (T) <= size); + yytypeid_ = & typeid (T); + return *new (yyas_ ()) T (std::forward (u)...); + } +# else + /// Instantiate an empty \a T in here. + template + T& + emplace () + { + YY_ASSERT (!yytypeid_); + YY_ASSERT (sizeof (T) <= size); + yytypeid_ = & typeid (T); + return *new (yyas_ ()) T (); + } + + /// Instantiate a \a T in here from \a t. + template + T& + emplace (const T& t) + { + YY_ASSERT (!yytypeid_); + YY_ASSERT (sizeof (T) <= size); + yytypeid_ = & typeid (T); + return *new (yyas_ ()) T (t); + } +# endif + + /// Instantiate an empty \a T in here. + /// Obsolete, use emplace. + template + T& + build () + { + return emplace (); + } + + /// Instantiate a \a T in here from \a t. + /// Obsolete, use emplace. + template + T& + build (const T& t) + { + return emplace (t); + } + + /// Accessor to a built \a T. + template + T& + as () YY_NOEXCEPT + { + YY_ASSERT (yytypeid_); + YY_ASSERT (*yytypeid_ == typeid (T)); + YY_ASSERT (sizeof (T) <= size); + return *yyas_ (); + } + + /// Const accessor to a built \a T (for %printer). + template + const T& + as () const YY_NOEXCEPT + { + YY_ASSERT (yytypeid_); + YY_ASSERT (*yytypeid_ == typeid (T)); + YY_ASSERT (sizeof (T) <= size); + return *yyas_ (); + } + + /// Swap the content with \a that, of same type. + /// + /// Both variants must be built beforehand, because swapping the actual + /// data requires reading it (with as()), and this is not possible on + /// unconstructed variants: it would require some dynamic testing, which + /// should not be the variant's responsibility. + /// Swapping between built and (possibly) non-built is done with + /// self_type::move (). + template + void + swap (self_type& that) YY_NOEXCEPT + { + YY_ASSERT (yytypeid_); + YY_ASSERT (*yytypeid_ == *that.yytypeid_); + std::swap (as (), that.as ()); + } + + /// Move the content of \a that to this. + /// + /// Destroys \a that. + template + void + move (self_type& that) + { +# if 201103L <= YY_CPLUSPLUS + emplace (std::move (that.as ())); +# else + emplace (); + swap (that); +# endif + that.destroy (); + } + +# if 201103L <= YY_CPLUSPLUS + /// Move the content of \a that to this. + template + void + move (self_type&& that) + { + emplace (std::move (that.as ())); + that.destroy (); + } +#endif + + /// Copy the content of \a that to this. + template + void + copy (const self_type& that) + { + emplace (that.as ()); + } + + /// Destroy the stored \a T. + template + void + destroy () + { + as ().~T (); + yytypeid_ = YY_NULLPTR; + } + + private: +#if YY_CPLUSPLUS < 201103L + /// Non copyable. + value_type (const self_type&); + /// Non copyable. + self_type& operator= (const self_type&); +#endif + + /// Accessor to raw memory as \a T. + template + T* + yyas_ () YY_NOEXCEPT + { + void *yyp = yyraw_; + return static_cast (yyp); + } + + /// Const accessor to raw memory as \a T. + template + const T* + yyas_ () const YY_NOEXCEPT + { + const void *yyp = yyraw_; + return static_cast (yyp); + } + + /// An auxiliary type to compute the largest semantic type. + union union_type + { + // columndef_list + char dummy1[sizeof (ColumnList)]; + + // columnconstraint_list + // tableconstraint + // tableconstraint_list + // optional_tableconstraint_list + char dummy2[sizeof (TableConstraints)]; + + // optional_if_not_exists + // optional_unique + // optional_temporary + // optional_always_generated + char dummy3[sizeof (bool)]; + + // createindex_stmt + char dummy4[sizeof (sqlb::IndexPtr)]; + + // indexed_column + char dummy5[sizeof (sqlb::IndexedColumn)]; + + // indexed_column_list + char dummy6[sizeof (sqlb::IndexedColumnVector)]; + + // columnid_list + // optional_columnid_with_paren_list + char dummy7[sizeof (sqlb::StringVector)]; + + // createvirtualtable_stmt + // createtable_stmt + char dummy8[sizeof (sqlb::TablePtr)]; + + // tableoption + // tableoptions_list + // optional_tableoptions_list + char dummy9[sizeof (std::bitset)]; + + // columnconstraint + char dummy10[sizeof (std::pair, std::shared_ptr>)]; + + // columndef + char dummy11[sizeof (std::shared_ptr)]; + + // "ABORT" + // "ACTION" + // "ALWAYS" + // "AND" + // "AND BETWEEN" + // "AS" + // "ASC" + // "AUTOINCREMENT" + // "BETWEEN" + // "CASCADE" + // "CASE" + // "CAST" + // "CHECK" + // "COLLATE" + // "CONFLICT" + // "CONSTRAINT" + // "CREATE" + // "CURRENT_DATE" + // "CURRENT_TIME" + // "CURRENT_TIMESTAMP" + // "DEFAULT" + // "DEFERRABLE" + // "DEFERRED" + // "DELETE" + // "DESC" + // "DISTINCT" + // "ELSE" + // "END" + // "ESCAPE" + // "EXISTS" + // "FAIL" + // "FALSE" + // "FILTER" + // "FOLLOWING" + // "FOREIGN" + // "FROM" + // "GENERATED" + // "GLOB" + // "IF" + // "IGNORE" + // "IMMEDIATE" + // "IN" + // "INDEX" + // "INITIALLY" + // "INSERT" + // "IS" + // "ISNULL" + // "KEY" + // "LIKE" + // "MATCH" + // "NO" + // "NOT" + // "NOTNULL" + // "NULL" + // "ON" + // "OR" + // "OVER" + // "PARTITION" + // "PRECEDING" + // "PRIMARY" + // "RAISE" + // "RANGE" + // "REFERENCES" + // "REGEXP" + // "REPLACE" + // "RESTRICT" + // "RETURNING" + // "ROLLBACK" + // "ROWID" + // "ROWS" + // "SELECT" + // "SET" + // "STORED" + // "STRICT" + // "TABLE" + // "TEMP" + // "TEMPORARY" + // "THEN" + // "TRUE" + // "UNBOUNDED" + // "UNIQUE" + // "UPDATE" + // "USING" + // "VIRTUAL" + // "WHEN" + // "WHERE" + // "WITHOUT" + // "identifier" + // "numeric" + // "string literal" + // "quoted literal" + // "blob literal" + // "bind parameter" + // literalvalue + // id + // allowed_keywords_as_identifier + // tableid + // columnid + // signednumber + // signednumber_or_numeric + // typename_namelist + // type_name + // unary_expr + // binary_expr + // like_expr + // exprlist_expr + // function_expr + // isnull_expr + // between_expr + // in_expr + // whenthenlist_expr + // case_expr + // raise_expr + // expr + // select_stmt + // optional_sort_order + // optional_where + // tableid_with_uninteresting_schema + // optional_exprlist_with_paren + // optional_conflictclause + // optional_typename + // optional_storage_identifier + // optional_constraintname + // fk_clause_part + // fk_clause_part_list + // optional_fk_clause + char dummy12[sizeof (std::string)]; + }; + + /// The size of the largest semantic type. + enum { size = sizeof (union_type) }; + + /// A buffer to store semantic values. + union + { + /// Strongest alignment constraints. + long double yyalign_me_; + /// A buffer large enough to store any of the semantic values. + char yyraw_[size]; + }; + + /// Whether the content is built: if defined, the name of the stored type. + const std::type_info *yytypeid_; + }; + +#endif + /// Backward compatibility (Bison 3.8). + typedef value_type semantic_type; + + /// Symbol locations. + typedef location location_type; + + /// Syntax errors thrown from user actions. + struct syntax_error : std::runtime_error + { + syntax_error (const location_type& l, const std::string& m) + : std::runtime_error (m) + , location (l) + {} + + syntax_error (const syntax_error& s) + : std::runtime_error (s.what ()) + , location (s.location) + {} + + ~syntax_error () YY_NOEXCEPT YY_NOTHROW; + + location_type location; + }; + + /// Token kinds. + struct token + { + enum token_kind_type + { + TOK_YYEMPTY = -2, + TOK_EOF = 0, // "end of file" + TOK_YYerror = 256, // error + TOK_YYUNDEF = 257, // "invalid token" + TOK_LPAREN = 258, // "(" + TOK_RPAREN = 259, // ")" + TOK_DOT = 260, // "." + TOK_COMMA = 261, // "," + TOK_SEMI = 262, // ";" + TOK_PLUS = 263, // "+" + TOK_MINUS = 264, // "-" + TOK_STAR = 265, // "*" + TOK_SLASH = 266, // "/" + TOK_TILDE = 267, // "~" + TOK_AMPERSAND = 268, // "&" + TOK_PERCENT = 269, // "%" + TOK_BITOR = 270, // "|" + TOK_OROP = 271, // "||" + TOK_EQUAL = 272, // "=" + TOK_EQUAL2 = 273, // "==" + TOK_GREATER = 274, // ">" + TOK_GREATEREQUAL = 275, // ">=" + TOK_LOWER = 276, // "<" + TOK_LOWEREQUAL = 277, // "<=" + TOK_UNEQUAL = 278, // "!=" + TOK_UNEQUAL2 = 279, // "<>" + TOK_BITWISELEFT = 280, // "<<" + TOK_BITWISERIGHT = 281, // ">>" + TOK_ABORT = 282, // "ABORT" + TOK_ACTION = 283, // "ACTION" + TOK_ALWAYS = 284, // "ALWAYS" + TOK_AND = 285, // "AND" + TOK_AND_BETWEEN = 286, // "AND BETWEEN" + TOK_AS = 287, // "AS" + TOK_ASC = 288, // "ASC" + TOK_AUTOINCREMENT = 289, // "AUTOINCREMENT" + TOK_BETWEEN = 290, // "BETWEEN" + TOK_CASCADE = 291, // "CASCADE" + TOK_CASE = 292, // "CASE" + TOK_CAST = 293, // "CAST" + TOK_CHECK = 294, // "CHECK" + TOK_COLLATE = 295, // "COLLATE" + TOK_CONFLICT = 296, // "CONFLICT" + TOK_CONSTRAINT = 297, // "CONSTRAINT" + TOK_CREATE = 298, // "CREATE" + TOK_CURRENT_DATE = 299, // "CURRENT_DATE" + TOK_CURRENT_TIME = 300, // "CURRENT_TIME" + TOK_CURRENT_TIMESTAMP = 301, // "CURRENT_TIMESTAMP" + TOK_DEFAULT = 302, // "DEFAULT" + TOK_DEFERRABLE = 303, // "DEFERRABLE" + TOK_DEFERRED = 304, // "DEFERRED" + TOK_DELETE = 305, // "DELETE" + TOK_DESC = 306, // "DESC" + TOK_DISTINCT = 307, // "DISTINCT" + TOK_ELSE = 308, // "ELSE" + TOK_END = 309, // "END" + TOK_ESCAPE = 310, // "ESCAPE" + TOK_EXISTS = 311, // "EXISTS" + TOK_FAIL = 312, // "FAIL" + TOK_FALSE = 313, // "FALSE" + TOK_FILTER = 314, // "FILTER" + TOK_FOLLOWING = 315, // "FOLLOWING" + TOK_FOREIGN = 316, // "FOREIGN" + TOK_FROM = 317, // "FROM" + TOK_GENERATED = 318, // "GENERATED" + TOK_GLOB = 319, // "GLOB" + TOK_IF = 320, // "IF" + TOK_IGNORE = 321, // "IGNORE" + TOK_IMMEDIATE = 322, // "IMMEDIATE" + TOK_IN = 323, // "IN" + TOK_INDEX = 324, // "INDEX" + TOK_INITIALLY = 325, // "INITIALLY" + TOK_INSERT = 326, // "INSERT" + TOK_IS = 327, // "IS" + TOK_ISNULL = 328, // "ISNULL" + TOK_KEY = 329, // "KEY" + TOK_LIKE = 330, // "LIKE" + TOK_MATCH = 331, // "MATCH" + TOK_NO = 332, // "NO" + TOK_NOT = 333, // "NOT" + TOK_NOTNULL = 334, // "NOTNULL" + TOK_NULL = 335, // "NULL" + TOK_ON = 336, // "ON" + TOK_OR = 337, // "OR" + TOK_OVER = 338, // "OVER" + TOK_PARTITION = 339, // "PARTITION" + TOK_PRECEDING = 340, // "PRECEDING" + TOK_PRIMARY = 341, // "PRIMARY" + TOK_RAISE = 342, // "RAISE" + TOK_RANGE = 343, // "RANGE" + TOK_REFERENCES = 344, // "REFERENCES" + TOK_REGEXP = 345, // "REGEXP" + TOK_REPLACE = 346, // "REPLACE" + TOK_RESTRICT = 347, // "RESTRICT" + TOK_RETURNING = 348, // "RETURNING" + TOK_ROLLBACK = 349, // "ROLLBACK" + TOK_ROWID = 350, // "ROWID" + TOK_ROWS = 351, // "ROWS" + TOK_SELECT = 352, // "SELECT" + TOK_SET = 353, // "SET" + TOK_STORED = 354, // "STORED" + TOK_STRICT = 355, // "STRICT" + TOK_TABLE = 356, // "TABLE" + TOK_TEMP = 357, // "TEMP" + TOK_TEMPORARY = 358, // "TEMPORARY" + TOK_THEN = 359, // "THEN" + TOK_TRUE = 360, // "TRUE" + TOK_UNBOUNDED = 361, // "UNBOUNDED" + TOK_UNIQUE = 362, // "UNIQUE" + TOK_UPDATE = 363, // "UPDATE" + TOK_USING = 364, // "USING" + TOK_VIRTUAL = 365, // "VIRTUAL" + TOK_WHEN = 366, // "WHEN" + TOK_WHERE = 367, // "WHERE" + TOK_WITHOUT = 368, // "WITHOUT" + TOK_IDENTIFIER = 369, // "identifier" + TOK_NUMERIC = 370, // "numeric" + TOK_STRINGLITERAL = 371, // "string literal" + TOK_QUOTEDLITERAL = 372, // "quoted literal" + TOK_BLOBLITERAL = 373, // "blob literal" + TOK_BINDPARAMETER = 374 // "bind parameter" + }; + /// Backward compatibility alias (Bison 3.6). + typedef token_kind_type yytokentype; + }; + + /// Token kind, as returned by yylex. + typedef token::token_kind_type token_kind_type; + + /// Backward compatibility alias (Bison 3.6). + typedef token_kind_type token_type; + + /// Symbol kinds. + struct symbol_kind + { + enum symbol_kind_type + { + YYNTOKENS = 120, ///< Number of tokens. + S_YYEMPTY = -2, + S_YYEOF = 0, // "end of file" + S_YYerror = 1, // error + S_YYUNDEF = 2, // "invalid token" + S_LPAREN = 3, // "(" + S_RPAREN = 4, // ")" + S_DOT = 5, // "." + S_COMMA = 6, // "," + S_SEMI = 7, // ";" + S_PLUS = 8, // "+" + S_MINUS = 9, // "-" + S_STAR = 10, // "*" + S_SLASH = 11, // "/" + S_TILDE = 12, // "~" + S_AMPERSAND = 13, // "&" + S_PERCENT = 14, // "%" + S_BITOR = 15, // "|" + S_OROP = 16, // "||" + S_EQUAL = 17, // "=" + S_EQUAL2 = 18, // "==" + S_GREATER = 19, // ">" + S_GREATEREQUAL = 20, // ">=" + S_LOWER = 21, // "<" + S_LOWEREQUAL = 22, // "<=" + S_UNEQUAL = 23, // "!=" + S_UNEQUAL2 = 24, // "<>" + S_BITWISELEFT = 25, // "<<" + S_BITWISERIGHT = 26, // ">>" + S_ABORT = 27, // "ABORT" + S_ACTION = 28, // "ACTION" + S_ALWAYS = 29, // "ALWAYS" + S_AND = 30, // "AND" + S_AND_BETWEEN = 31, // "AND BETWEEN" + S_AS = 32, // "AS" + S_ASC = 33, // "ASC" + S_AUTOINCREMENT = 34, // "AUTOINCREMENT" + S_BETWEEN = 35, // "BETWEEN" + S_CASCADE = 36, // "CASCADE" + S_CASE = 37, // "CASE" + S_CAST = 38, // "CAST" + S_CHECK = 39, // "CHECK" + S_COLLATE = 40, // "COLLATE" + S_CONFLICT = 41, // "CONFLICT" + S_CONSTRAINT = 42, // "CONSTRAINT" + S_CREATE = 43, // "CREATE" + S_CURRENT_DATE = 44, // "CURRENT_DATE" + S_CURRENT_TIME = 45, // "CURRENT_TIME" + S_CURRENT_TIMESTAMP = 46, // "CURRENT_TIMESTAMP" + S_DEFAULT = 47, // "DEFAULT" + S_DEFERRABLE = 48, // "DEFERRABLE" + S_DEFERRED = 49, // "DEFERRED" + S_DELETE = 50, // "DELETE" + S_DESC = 51, // "DESC" + S_DISTINCT = 52, // "DISTINCT" + S_ELSE = 53, // "ELSE" + S_END = 54, // "END" + S_ESCAPE = 55, // "ESCAPE" + S_EXISTS = 56, // "EXISTS" + S_FAIL = 57, // "FAIL" + S_FALSE = 58, // "FALSE" + S_FILTER = 59, // "FILTER" + S_FOLLOWING = 60, // "FOLLOWING" + S_FOREIGN = 61, // "FOREIGN" + S_FROM = 62, // "FROM" + S_GENERATED = 63, // "GENERATED" + S_GLOB = 64, // "GLOB" + S_IF = 65, // "IF" + S_IGNORE = 66, // "IGNORE" + S_IMMEDIATE = 67, // "IMMEDIATE" + S_IN = 68, // "IN" + S_INDEX = 69, // "INDEX" + S_INITIALLY = 70, // "INITIALLY" + S_INSERT = 71, // "INSERT" + S_IS = 72, // "IS" + S_ISNULL = 73, // "ISNULL" + S_KEY = 74, // "KEY" + S_LIKE = 75, // "LIKE" + S_MATCH = 76, // "MATCH" + S_NO = 77, // "NO" + S_NOT = 78, // "NOT" + S_NOTNULL = 79, // "NOTNULL" + S_NULL = 80, // "NULL" + S_ON = 81, // "ON" + S_OR = 82, // "OR" + S_OVER = 83, // "OVER" + S_PARTITION = 84, // "PARTITION" + S_PRECEDING = 85, // "PRECEDING" + S_PRIMARY = 86, // "PRIMARY" + S_RAISE = 87, // "RAISE" + S_RANGE = 88, // "RANGE" + S_REFERENCES = 89, // "REFERENCES" + S_REGEXP = 90, // "REGEXP" + S_REPLACE = 91, // "REPLACE" + S_RESTRICT = 92, // "RESTRICT" + S_RETURNING = 93, // "RETURNING" + S_ROLLBACK = 94, // "ROLLBACK" + S_ROWID = 95, // "ROWID" + S_ROWS = 96, // "ROWS" + S_SELECT = 97, // "SELECT" + S_SET = 98, // "SET" + S_STORED = 99, // "STORED" + S_STRICT = 100, // "STRICT" + S_TABLE = 101, // "TABLE" + S_TEMP = 102, // "TEMP" + S_TEMPORARY = 103, // "TEMPORARY" + S_THEN = 104, // "THEN" + S_TRUE = 105, // "TRUE" + S_UNBOUNDED = 106, // "UNBOUNDED" + S_UNIQUE = 107, // "UNIQUE" + S_UPDATE = 108, // "UPDATE" + S_USING = 109, // "USING" + S_VIRTUAL = 110, // "VIRTUAL" + S_WHEN = 111, // "WHEN" + S_WHERE = 112, // "WHERE" + S_WITHOUT = 113, // "WITHOUT" + S_IDENTIFIER = 114, // "identifier" + S_NUMERIC = 115, // "numeric" + S_STRINGLITERAL = 116, // "string literal" + S_QUOTEDLITERAL = 117, // "quoted literal" + S_BLOBLITERAL = 118, // "blob literal" + S_BINDPARAMETER = 119, // "bind parameter" + S_YYACCEPT = 120, // $accept + S_sql = 121, // sql + S_statement = 122, // statement + S_literalvalue = 123, // literalvalue + S_id = 124, // id + S_allowed_keywords_as_identifier = 125, // allowed_keywords_as_identifier + S_tableid = 126, // tableid + S_columnid = 127, // columnid + S_signednumber = 128, // signednumber + S_signednumber_or_numeric = 129, // signednumber_or_numeric + S_typename_namelist = 130, // typename_namelist + S_type_name = 131, // type_name + S_unary_expr = 132, // unary_expr + S_binary_expr = 133, // binary_expr + S_like_expr = 134, // like_expr + S_exprlist_expr = 135, // exprlist_expr + S_function_expr = 136, // function_expr + S_isnull_expr = 137, // isnull_expr + S_between_expr = 138, // between_expr + S_in_expr = 139, // in_expr + S_whenthenlist_expr = 140, // whenthenlist_expr + S_case_expr = 141, // case_expr + S_raise_expr = 142, // raise_expr + S_expr = 143, // expr + S_select_stmt = 144, // select_stmt + S_optional_if_not_exists = 145, // optional_if_not_exists + S_optional_sort_order = 146, // optional_sort_order + S_optional_unique = 147, // optional_unique + S_optional_where = 148, // optional_where + S_tableid_with_uninteresting_schema = 149, // tableid_with_uninteresting_schema + S_indexed_column = 150, // indexed_column + S_indexed_column_list = 151, // indexed_column_list + S_createindex_stmt = 152, // createindex_stmt + S_optional_exprlist_with_paren = 153, // optional_exprlist_with_paren + S_createvirtualtable_stmt = 154, // createvirtualtable_stmt + S_optional_temporary = 155, // optional_temporary + S_tableoption = 156, // tableoption + S_tableoptions_list = 157, // tableoptions_list + S_optional_tableoptions_list = 158, // optional_tableoptions_list + S_optional_conflictclause = 159, // optional_conflictclause + S_optional_typename = 160, // optional_typename + S_optional_storage_identifier = 161, // optional_storage_identifier + S_optional_always_generated = 162, // optional_always_generated + S_columnconstraint = 163, // columnconstraint + S_columnconstraint_list = 164, // columnconstraint_list + S_columndef = 165, // columndef + S_columndef_list = 166, // columndef_list + S_optional_constraintname = 167, // optional_constraintname + S_columnid_list = 168, // columnid_list + S_optional_columnid_with_paren_list = 169, // optional_columnid_with_paren_list + S_fk_clause_part = 170, // fk_clause_part + S_fk_clause_part_list = 171, // fk_clause_part_list + S_optional_fk_clause = 172, // optional_fk_clause + S_tableconstraint = 173, // tableconstraint + S_tableconstraint_list = 174, // tableconstraint_list + S_optional_tableconstraint_list = 175, // optional_tableconstraint_list + S_createtable_stmt = 176 // createtable_stmt + }; + }; + + /// (Internal) symbol kind. + typedef symbol_kind::symbol_kind_type symbol_kind_type; + + /// The number of tokens. + static const symbol_kind_type YYNTOKENS = symbol_kind::YYNTOKENS; + + /// A complete symbol. + /// + /// Expects its Base type to provide access to the symbol kind + /// via kind (). + /// + /// Provide access to semantic value and location. + template + struct basic_symbol : Base + { + /// Alias to Base. + typedef Base super_type; + + /// Default constructor. + basic_symbol () YY_NOEXCEPT + : value () + , location () + {} + +#if 201103L <= YY_CPLUSPLUS + /// Move constructor. + basic_symbol (basic_symbol&& that) + : Base (std::move (that)) + , value () + , location (std::move (that.location)) + { + switch (this->kind ()) + { + case symbol_kind::S_columndef_list: // columndef_list + value.move< ColumnList > (std::move (that.value)); + break; + + case symbol_kind::S_columnconstraint_list: // columnconstraint_list + case symbol_kind::S_tableconstraint: // tableconstraint + case symbol_kind::S_tableconstraint_list: // tableconstraint_list + case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list + value.move< TableConstraints > (std::move (that.value)); + break; + + case symbol_kind::S_optional_if_not_exists: // optional_if_not_exists + case symbol_kind::S_optional_unique: // optional_unique + case symbol_kind::S_optional_temporary: // optional_temporary + case symbol_kind::S_optional_always_generated: // optional_always_generated + value.move< bool > (std::move (that.value)); + break; + + case symbol_kind::S_createindex_stmt: // createindex_stmt + value.move< sqlb::IndexPtr > (std::move (that.value)); + break; + + case symbol_kind::S_indexed_column: // indexed_column + value.move< sqlb::IndexedColumn > (std::move (that.value)); + break; + + case symbol_kind::S_indexed_column_list: // indexed_column_list + value.move< sqlb::IndexedColumnVector > (std::move (that.value)); + break; + + case symbol_kind::S_columnid_list: // columnid_list + case symbol_kind::S_optional_columnid_with_paren_list: // optional_columnid_with_paren_list + value.move< sqlb::StringVector > (std::move (that.value)); + break; + + case symbol_kind::S_createvirtualtable_stmt: // createvirtualtable_stmt + case symbol_kind::S_createtable_stmt: // createtable_stmt + value.move< sqlb::TablePtr > (std::move (that.value)); + break; + + case symbol_kind::S_tableoption: // tableoption + case symbol_kind::S_tableoptions_list: // tableoptions_list + case symbol_kind::S_optional_tableoptions_list: // optional_tableoptions_list + value.move< std::bitset > (std::move (that.value)); + break; + + case symbol_kind::S_columnconstraint: // columnconstraint + value.move< std::pair, std::shared_ptr> > (std::move (that.value)); + break; + + case symbol_kind::S_columndef: // columndef + value.move< std::shared_ptr > (std::move (that.value)); + break; + + case symbol_kind::S_ABORT: // "ABORT" + case symbol_kind::S_ACTION: // "ACTION" + case symbol_kind::S_ALWAYS: // "ALWAYS" + case symbol_kind::S_AND: // "AND" + case symbol_kind::S_AND_BETWEEN: // "AND BETWEEN" + case symbol_kind::S_AS: // "AS" + case symbol_kind::S_ASC: // "ASC" + case symbol_kind::S_AUTOINCREMENT: // "AUTOINCREMENT" + case symbol_kind::S_BETWEEN: // "BETWEEN" + case symbol_kind::S_CASCADE: // "CASCADE" + case symbol_kind::S_CASE: // "CASE" + case symbol_kind::S_CAST: // "CAST" + case symbol_kind::S_CHECK: // "CHECK" + case symbol_kind::S_COLLATE: // "COLLATE" + case symbol_kind::S_CONFLICT: // "CONFLICT" + case symbol_kind::S_CONSTRAINT: // "CONSTRAINT" + case symbol_kind::S_CREATE: // "CREATE" + case symbol_kind::S_CURRENT_DATE: // "CURRENT_DATE" + case symbol_kind::S_CURRENT_TIME: // "CURRENT_TIME" + case symbol_kind::S_CURRENT_TIMESTAMP: // "CURRENT_TIMESTAMP" + case symbol_kind::S_DEFAULT: // "DEFAULT" + case symbol_kind::S_DEFERRABLE: // "DEFERRABLE" + case symbol_kind::S_DEFERRED: // "DEFERRED" + case symbol_kind::S_DELETE: // "DELETE" + case symbol_kind::S_DESC: // "DESC" + case symbol_kind::S_DISTINCT: // "DISTINCT" + case symbol_kind::S_ELSE: // "ELSE" + case symbol_kind::S_END: // "END" + case symbol_kind::S_ESCAPE: // "ESCAPE" + case symbol_kind::S_EXISTS: // "EXISTS" + case symbol_kind::S_FAIL: // "FAIL" + case symbol_kind::S_FALSE: // "FALSE" + case symbol_kind::S_FILTER: // "FILTER" + case symbol_kind::S_FOLLOWING: // "FOLLOWING" + case symbol_kind::S_FOREIGN: // "FOREIGN" + case symbol_kind::S_FROM: // "FROM" + case symbol_kind::S_GENERATED: // "GENERATED" + case symbol_kind::S_GLOB: // "GLOB" + case symbol_kind::S_IF: // "IF" + case symbol_kind::S_IGNORE: // "IGNORE" + case symbol_kind::S_IMMEDIATE: // "IMMEDIATE" + case symbol_kind::S_IN: // "IN" + case symbol_kind::S_INDEX: // "INDEX" + case symbol_kind::S_INITIALLY: // "INITIALLY" + case symbol_kind::S_INSERT: // "INSERT" + case symbol_kind::S_IS: // "IS" + case symbol_kind::S_ISNULL: // "ISNULL" + case symbol_kind::S_KEY: // "KEY" + case symbol_kind::S_LIKE: // "LIKE" + case symbol_kind::S_MATCH: // "MATCH" + case symbol_kind::S_NO: // "NO" + case symbol_kind::S_NOT: // "NOT" + case symbol_kind::S_NOTNULL: // "NOTNULL" + case symbol_kind::S_NULL: // "NULL" + case symbol_kind::S_ON: // "ON" + case symbol_kind::S_OR: // "OR" + case symbol_kind::S_OVER: // "OVER" + case symbol_kind::S_PARTITION: // "PARTITION" + case symbol_kind::S_PRECEDING: // "PRECEDING" + case symbol_kind::S_PRIMARY: // "PRIMARY" + case symbol_kind::S_RAISE: // "RAISE" + case symbol_kind::S_RANGE: // "RANGE" + case symbol_kind::S_REFERENCES: // "REFERENCES" + case symbol_kind::S_REGEXP: // "REGEXP" + case symbol_kind::S_REPLACE: // "REPLACE" + case symbol_kind::S_RESTRICT: // "RESTRICT" + case symbol_kind::S_RETURNING: // "RETURNING" + case symbol_kind::S_ROLLBACK: // "ROLLBACK" + case symbol_kind::S_ROWID: // "ROWID" + case symbol_kind::S_ROWS: // "ROWS" + case symbol_kind::S_SELECT: // "SELECT" + case symbol_kind::S_SET: // "SET" + case symbol_kind::S_STORED: // "STORED" + case symbol_kind::S_STRICT: // "STRICT" + case symbol_kind::S_TABLE: // "TABLE" + case symbol_kind::S_TEMP: // "TEMP" + case symbol_kind::S_TEMPORARY: // "TEMPORARY" + case symbol_kind::S_THEN: // "THEN" + case symbol_kind::S_TRUE: // "TRUE" + case symbol_kind::S_UNBOUNDED: // "UNBOUNDED" + case symbol_kind::S_UNIQUE: // "UNIQUE" + case symbol_kind::S_UPDATE: // "UPDATE" + case symbol_kind::S_USING: // "USING" + case symbol_kind::S_VIRTUAL: // "VIRTUAL" + case symbol_kind::S_WHEN: // "WHEN" + case symbol_kind::S_WHERE: // "WHERE" + case symbol_kind::S_WITHOUT: // "WITHOUT" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_NUMERIC: // "numeric" + case symbol_kind::S_STRINGLITERAL: // "string literal" + case symbol_kind::S_QUOTEDLITERAL: // "quoted literal" + case symbol_kind::S_BLOBLITERAL: // "blob literal" + case symbol_kind::S_BINDPARAMETER: // "bind parameter" + case symbol_kind::S_literalvalue: // literalvalue + case symbol_kind::S_id: // id + case symbol_kind::S_allowed_keywords_as_identifier: // allowed_keywords_as_identifier + case symbol_kind::S_tableid: // tableid + case symbol_kind::S_columnid: // columnid + case symbol_kind::S_signednumber: // signednumber + case symbol_kind::S_signednumber_or_numeric: // signednumber_or_numeric + case symbol_kind::S_typename_namelist: // typename_namelist + case symbol_kind::S_type_name: // type_name + case symbol_kind::S_unary_expr: // unary_expr + case symbol_kind::S_binary_expr: // binary_expr + case symbol_kind::S_like_expr: // like_expr + case symbol_kind::S_exprlist_expr: // exprlist_expr + case symbol_kind::S_function_expr: // function_expr + case symbol_kind::S_isnull_expr: // isnull_expr + case symbol_kind::S_between_expr: // between_expr + case symbol_kind::S_in_expr: // in_expr + case symbol_kind::S_whenthenlist_expr: // whenthenlist_expr + case symbol_kind::S_case_expr: // case_expr + case symbol_kind::S_raise_expr: // raise_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_select_stmt: // select_stmt + case symbol_kind::S_optional_sort_order: // optional_sort_order + case symbol_kind::S_optional_where: // optional_where + case symbol_kind::S_tableid_with_uninteresting_schema: // tableid_with_uninteresting_schema + case symbol_kind::S_optional_exprlist_with_paren: // optional_exprlist_with_paren + case symbol_kind::S_optional_conflictclause: // optional_conflictclause + case symbol_kind::S_optional_typename: // optional_typename + case symbol_kind::S_optional_storage_identifier: // optional_storage_identifier + case symbol_kind::S_optional_constraintname: // optional_constraintname + case symbol_kind::S_fk_clause_part: // fk_clause_part + case symbol_kind::S_fk_clause_part_list: // fk_clause_part_list + case symbol_kind::S_optional_fk_clause: // optional_fk_clause + value.move< std::string > (std::move (that.value)); + break; + + default: + break; + } + + } +#endif + + /// Copy constructor. + basic_symbol (const basic_symbol& that); + + /// Constructors for typed symbols. +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, location_type&& l) + : Base (t) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const location_type& l) + : Base (t) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, ColumnList&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const ColumnList& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, TableConstraints&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const TableConstraints& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, bool&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const bool& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, sqlb::IndexPtr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const sqlb::IndexPtr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, sqlb::IndexedColumn&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const sqlb::IndexedColumn& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, sqlb::IndexedColumnVector&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const sqlb::IndexedColumnVector& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, sqlb::StringVector&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const sqlb::StringVector& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, sqlb::TablePtr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const sqlb::TablePtr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, std::bitset&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const std::bitset& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, std::pair, std::shared_ptr>&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const std::pair, std::shared_ptr>& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, std::shared_ptr&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const std::shared_ptr& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + +#if 201103L <= YY_CPLUSPLUS + basic_symbol (typename Base::kind_type t, std::string&& v, location_type&& l) + : Base (t) + , value (std::move (v)) + , location (std::move (l)) + {} +#else + basic_symbol (typename Base::kind_type t, const std::string& v, const location_type& l) + : Base (t) + , value (v) + , location (l) + {} +#endif + + /// Destroy the symbol. + ~basic_symbol () + { + clear (); + } + + + + /// Destroy contents, and record that is empty. + void clear () YY_NOEXCEPT + { + // User destructor. + symbol_kind_type yykind = this->kind (); + basic_symbol& yysym = *this; + (void) yysym; + switch (yykind) + { + default: + break; + } + + // Value type destructor. +switch (yykind) + { + case symbol_kind::S_columndef_list: // columndef_list + value.template destroy< ColumnList > (); + break; + + case symbol_kind::S_columnconstraint_list: // columnconstraint_list + case symbol_kind::S_tableconstraint: // tableconstraint + case symbol_kind::S_tableconstraint_list: // tableconstraint_list + case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list + value.template destroy< TableConstraints > (); + break; + + case symbol_kind::S_optional_if_not_exists: // optional_if_not_exists + case symbol_kind::S_optional_unique: // optional_unique + case symbol_kind::S_optional_temporary: // optional_temporary + case symbol_kind::S_optional_always_generated: // optional_always_generated + value.template destroy< bool > (); + break; + + case symbol_kind::S_createindex_stmt: // createindex_stmt + value.template destroy< sqlb::IndexPtr > (); + break; + + case symbol_kind::S_indexed_column: // indexed_column + value.template destroy< sqlb::IndexedColumn > (); + break; + + case symbol_kind::S_indexed_column_list: // indexed_column_list + value.template destroy< sqlb::IndexedColumnVector > (); + break; + + case symbol_kind::S_columnid_list: // columnid_list + case symbol_kind::S_optional_columnid_with_paren_list: // optional_columnid_with_paren_list + value.template destroy< sqlb::StringVector > (); + break; + + case symbol_kind::S_createvirtualtable_stmt: // createvirtualtable_stmt + case symbol_kind::S_createtable_stmt: // createtable_stmt + value.template destroy< sqlb::TablePtr > (); + break; + + case symbol_kind::S_tableoption: // tableoption + case symbol_kind::S_tableoptions_list: // tableoptions_list + case symbol_kind::S_optional_tableoptions_list: // optional_tableoptions_list + value.template destroy< std::bitset > (); + break; + + case symbol_kind::S_columnconstraint: // columnconstraint + value.template destroy< std::pair, std::shared_ptr> > (); + break; + + case symbol_kind::S_columndef: // columndef + value.template destroy< std::shared_ptr > (); + break; + + case symbol_kind::S_ABORT: // "ABORT" + case symbol_kind::S_ACTION: // "ACTION" + case symbol_kind::S_ALWAYS: // "ALWAYS" + case symbol_kind::S_AND: // "AND" + case symbol_kind::S_AND_BETWEEN: // "AND BETWEEN" + case symbol_kind::S_AS: // "AS" + case symbol_kind::S_ASC: // "ASC" + case symbol_kind::S_AUTOINCREMENT: // "AUTOINCREMENT" + case symbol_kind::S_BETWEEN: // "BETWEEN" + case symbol_kind::S_CASCADE: // "CASCADE" + case symbol_kind::S_CASE: // "CASE" + case symbol_kind::S_CAST: // "CAST" + case symbol_kind::S_CHECK: // "CHECK" + case symbol_kind::S_COLLATE: // "COLLATE" + case symbol_kind::S_CONFLICT: // "CONFLICT" + case symbol_kind::S_CONSTRAINT: // "CONSTRAINT" + case symbol_kind::S_CREATE: // "CREATE" + case symbol_kind::S_CURRENT_DATE: // "CURRENT_DATE" + case symbol_kind::S_CURRENT_TIME: // "CURRENT_TIME" + case symbol_kind::S_CURRENT_TIMESTAMP: // "CURRENT_TIMESTAMP" + case symbol_kind::S_DEFAULT: // "DEFAULT" + case symbol_kind::S_DEFERRABLE: // "DEFERRABLE" + case symbol_kind::S_DEFERRED: // "DEFERRED" + case symbol_kind::S_DELETE: // "DELETE" + case symbol_kind::S_DESC: // "DESC" + case symbol_kind::S_DISTINCT: // "DISTINCT" + case symbol_kind::S_ELSE: // "ELSE" + case symbol_kind::S_END: // "END" + case symbol_kind::S_ESCAPE: // "ESCAPE" + case symbol_kind::S_EXISTS: // "EXISTS" + case symbol_kind::S_FAIL: // "FAIL" + case symbol_kind::S_FALSE: // "FALSE" + case symbol_kind::S_FILTER: // "FILTER" + case symbol_kind::S_FOLLOWING: // "FOLLOWING" + case symbol_kind::S_FOREIGN: // "FOREIGN" + case symbol_kind::S_FROM: // "FROM" + case symbol_kind::S_GENERATED: // "GENERATED" + case symbol_kind::S_GLOB: // "GLOB" + case symbol_kind::S_IF: // "IF" + case symbol_kind::S_IGNORE: // "IGNORE" + case symbol_kind::S_IMMEDIATE: // "IMMEDIATE" + case symbol_kind::S_IN: // "IN" + case symbol_kind::S_INDEX: // "INDEX" + case symbol_kind::S_INITIALLY: // "INITIALLY" + case symbol_kind::S_INSERT: // "INSERT" + case symbol_kind::S_IS: // "IS" + case symbol_kind::S_ISNULL: // "ISNULL" + case symbol_kind::S_KEY: // "KEY" + case symbol_kind::S_LIKE: // "LIKE" + case symbol_kind::S_MATCH: // "MATCH" + case symbol_kind::S_NO: // "NO" + case symbol_kind::S_NOT: // "NOT" + case symbol_kind::S_NOTNULL: // "NOTNULL" + case symbol_kind::S_NULL: // "NULL" + case symbol_kind::S_ON: // "ON" + case symbol_kind::S_OR: // "OR" + case symbol_kind::S_OVER: // "OVER" + case symbol_kind::S_PARTITION: // "PARTITION" + case symbol_kind::S_PRECEDING: // "PRECEDING" + case symbol_kind::S_PRIMARY: // "PRIMARY" + case symbol_kind::S_RAISE: // "RAISE" + case symbol_kind::S_RANGE: // "RANGE" + case symbol_kind::S_REFERENCES: // "REFERENCES" + case symbol_kind::S_REGEXP: // "REGEXP" + case symbol_kind::S_REPLACE: // "REPLACE" + case symbol_kind::S_RESTRICT: // "RESTRICT" + case symbol_kind::S_RETURNING: // "RETURNING" + case symbol_kind::S_ROLLBACK: // "ROLLBACK" + case symbol_kind::S_ROWID: // "ROWID" + case symbol_kind::S_ROWS: // "ROWS" + case symbol_kind::S_SELECT: // "SELECT" + case symbol_kind::S_SET: // "SET" + case symbol_kind::S_STORED: // "STORED" + case symbol_kind::S_STRICT: // "STRICT" + case symbol_kind::S_TABLE: // "TABLE" + case symbol_kind::S_TEMP: // "TEMP" + case symbol_kind::S_TEMPORARY: // "TEMPORARY" + case symbol_kind::S_THEN: // "THEN" + case symbol_kind::S_TRUE: // "TRUE" + case symbol_kind::S_UNBOUNDED: // "UNBOUNDED" + case symbol_kind::S_UNIQUE: // "UNIQUE" + case symbol_kind::S_UPDATE: // "UPDATE" + case symbol_kind::S_USING: // "USING" + case symbol_kind::S_VIRTUAL: // "VIRTUAL" + case symbol_kind::S_WHEN: // "WHEN" + case symbol_kind::S_WHERE: // "WHERE" + case symbol_kind::S_WITHOUT: // "WITHOUT" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_NUMERIC: // "numeric" + case symbol_kind::S_STRINGLITERAL: // "string literal" + case symbol_kind::S_QUOTEDLITERAL: // "quoted literal" + case symbol_kind::S_BLOBLITERAL: // "blob literal" + case symbol_kind::S_BINDPARAMETER: // "bind parameter" + case symbol_kind::S_literalvalue: // literalvalue + case symbol_kind::S_id: // id + case symbol_kind::S_allowed_keywords_as_identifier: // allowed_keywords_as_identifier + case symbol_kind::S_tableid: // tableid + case symbol_kind::S_columnid: // columnid + case symbol_kind::S_signednumber: // signednumber + case symbol_kind::S_signednumber_or_numeric: // signednumber_or_numeric + case symbol_kind::S_typename_namelist: // typename_namelist + case symbol_kind::S_type_name: // type_name + case symbol_kind::S_unary_expr: // unary_expr + case symbol_kind::S_binary_expr: // binary_expr + case symbol_kind::S_like_expr: // like_expr + case symbol_kind::S_exprlist_expr: // exprlist_expr + case symbol_kind::S_function_expr: // function_expr + case symbol_kind::S_isnull_expr: // isnull_expr + case symbol_kind::S_between_expr: // between_expr + case symbol_kind::S_in_expr: // in_expr + case symbol_kind::S_whenthenlist_expr: // whenthenlist_expr + case symbol_kind::S_case_expr: // case_expr + case symbol_kind::S_raise_expr: // raise_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_select_stmt: // select_stmt + case symbol_kind::S_optional_sort_order: // optional_sort_order + case symbol_kind::S_optional_where: // optional_where + case symbol_kind::S_tableid_with_uninteresting_schema: // tableid_with_uninteresting_schema + case symbol_kind::S_optional_exprlist_with_paren: // optional_exprlist_with_paren + case symbol_kind::S_optional_conflictclause: // optional_conflictclause + case symbol_kind::S_optional_typename: // optional_typename + case symbol_kind::S_optional_storage_identifier: // optional_storage_identifier + case symbol_kind::S_optional_constraintname: // optional_constraintname + case symbol_kind::S_fk_clause_part: // fk_clause_part + case symbol_kind::S_fk_clause_part_list: // fk_clause_part_list + case symbol_kind::S_optional_fk_clause: // optional_fk_clause + value.template destroy< std::string > (); + break; + + default: + break; + } + + Base::clear (); + } + + /// The user-facing name of this symbol. + std::string name () const YY_NOEXCEPT + { + return parser::symbol_name (this->kind ()); + } + + /// Backward compatibility (Bison 3.6). + symbol_kind_type type_get () const YY_NOEXCEPT; + + /// Whether empty. + bool empty () const YY_NOEXCEPT; + + /// Destructive move, \a s is emptied into this. + void move (basic_symbol& s); + + /// The semantic value. + value_type value; + + /// The location. + location_type location; + + private: +#if YY_CPLUSPLUS < 201103L + /// Assignment operator. + basic_symbol& operator= (const basic_symbol& that); +#endif + }; + + /// Type access provider for token (enum) based symbols. + struct by_kind + { + /// The symbol kind as needed by the constructor. + typedef token_kind_type kind_type; + + /// Default constructor. + by_kind () YY_NOEXCEPT; + +#if 201103L <= YY_CPLUSPLUS + /// Move constructor. + by_kind (by_kind&& that) YY_NOEXCEPT; +#endif + + /// Copy constructor. + by_kind (const by_kind& that) YY_NOEXCEPT; + + /// Constructor from (external) token numbers. + by_kind (kind_type t) YY_NOEXCEPT; + + + + /// Record that this symbol is empty. + void clear () YY_NOEXCEPT; + + /// Steal the symbol kind from \a that. + void move (by_kind& that); + + /// The (internal) type number (corresponding to \a type). + /// \a empty when empty. + symbol_kind_type kind () const YY_NOEXCEPT; + + /// Backward compatibility (Bison 3.6). + symbol_kind_type type_get () const YY_NOEXCEPT; + + /// The symbol kind. + /// \a S_YYEMPTY when empty. + symbol_kind_type kind_; + }; + + /// Backward compatibility for a private implementation detail (Bison 3.6). + typedef by_kind by_type; + + /// "External" symbols: returned by the scanner. + struct symbol_type : basic_symbol + { + /// Superclass. + typedef basic_symbol super_type; + + /// Empty symbol. + symbol_type () YY_NOEXCEPT {} + + /// Constructor for valueless symbols, and symbols from each type. +#if 201103L <= YY_CPLUSPLUS + symbol_type (int tok, location_type l) + : super_type (token_kind_type (tok), std::move (l)) +#else + symbol_type (int tok, const location_type& l) + : super_type (token_kind_type (tok), l) +#endif + { +#if !defined _MSC_VER || defined __clang__ + YY_ASSERT (tok == token::TOK_EOF + || (token::TOK_YYerror <= tok && tok <= token::TOK_BITWISERIGHT)); +#endif + } +#if 201103L <= YY_CPLUSPLUS + symbol_type (int tok, std::string v, location_type l) + : super_type (token_kind_type (tok), std::move (v), std::move (l)) +#else + symbol_type (int tok, const std::string& v, const location_type& l) + : super_type (token_kind_type (tok), v, l) +#endif + { +#if !defined _MSC_VER || defined __clang__ + YY_ASSERT ((token::TOK_ABORT <= tok && tok <= token::TOK_BINDPARAMETER)); +#endif + } + }; + + /// Build a parser object. + parser (yyscan_t yyscanner_yyarg, ParserDriver& drv_yyarg); + virtual ~parser (); + +#if 201103L <= YY_CPLUSPLUS + /// Non copyable. + parser (const parser&) = delete; + /// Non copyable. + parser& operator= (const parser&) = delete; +#endif + + /// Parse. An alias for parse (). + /// \returns 0 iff parsing succeeded. + int operator() (); + + /// Parse. + /// \returns 0 iff parsing succeeded. + virtual int parse (); + +#if YYDEBUG + /// The current debugging stream. + std::ostream& debug_stream () const YY_ATTRIBUTE_PURE; + /// Set the current debugging stream. + void set_debug_stream (std::ostream &); + + /// Type for debugging levels. + typedef int debug_level_type; + /// The current debugging level. + debug_level_type debug_level () const YY_ATTRIBUTE_PURE; + /// Set the current debugging level. + void set_debug_level (debug_level_type l); +#endif + + /// Report a syntax error. + /// \param loc where the syntax error is found. + /// \param msg a description of the syntax error. + virtual void error (const location_type& loc, const std::string& msg); + + /// Report a syntax error. + void error (const syntax_error& err); + + /// The user-facing name of the symbol whose (internal) number is + /// YYSYMBOL. No bounds checking. + static std::string symbol_name (symbol_kind_type yysymbol); + + // Implementation of make_symbol for each token kind. +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_EOF (location_type l) + { + return symbol_type (token::TOK_EOF, std::move (l)); + } +#else + static + symbol_type + make_EOF (const location_type& l) + { + return symbol_type (token::TOK_EOF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_YYerror (location_type l) + { + return symbol_type (token::TOK_YYerror, std::move (l)); + } +#else + static + symbol_type + make_YYerror (const location_type& l) + { + return symbol_type (token::TOK_YYerror, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_YYUNDEF (location_type l) + { + return symbol_type (token::TOK_YYUNDEF, std::move (l)); + } +#else + static + symbol_type + make_YYUNDEF (const location_type& l) + { + return symbol_type (token::TOK_YYUNDEF, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_LPAREN (location_type l) + { + return symbol_type (token::TOK_LPAREN, std::move (l)); + } +#else + static + symbol_type + make_LPAREN (const location_type& l) + { + return symbol_type (token::TOK_LPAREN, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_RPAREN (location_type l) + { + return symbol_type (token::TOK_RPAREN, std::move (l)); + } +#else + static + symbol_type + make_RPAREN (const location_type& l) + { + return symbol_type (token::TOK_RPAREN, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DOT (location_type l) + { + return symbol_type (token::TOK_DOT, std::move (l)); + } +#else + static + symbol_type + make_DOT (const location_type& l) + { + return symbol_type (token::TOK_DOT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_COMMA (location_type l) + { + return symbol_type (token::TOK_COMMA, std::move (l)); + } +#else + static + symbol_type + make_COMMA (const location_type& l) + { + return symbol_type (token::TOK_COMMA, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SEMI (location_type l) + { + return symbol_type (token::TOK_SEMI, std::move (l)); + } +#else + static + symbol_type + make_SEMI (const location_type& l) + { + return symbol_type (token::TOK_SEMI, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_PLUS (location_type l) + { + return symbol_type (token::TOK_PLUS, std::move (l)); + } +#else + static + symbol_type + make_PLUS (const location_type& l) + { + return symbol_type (token::TOK_PLUS, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_MINUS (location_type l) + { + return symbol_type (token::TOK_MINUS, std::move (l)); + } +#else + static + symbol_type + make_MINUS (const location_type& l) + { + return symbol_type (token::TOK_MINUS, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_STAR (location_type l) + { + return symbol_type (token::TOK_STAR, std::move (l)); + } +#else + static + symbol_type + make_STAR (const location_type& l) + { + return symbol_type (token::TOK_STAR, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SLASH (location_type l) + { + return symbol_type (token::TOK_SLASH, std::move (l)); + } +#else + static + symbol_type + make_SLASH (const location_type& l) + { + return symbol_type (token::TOK_SLASH, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_TILDE (location_type l) + { + return symbol_type (token::TOK_TILDE, std::move (l)); + } +#else + static + symbol_type + make_TILDE (const location_type& l) + { + return symbol_type (token::TOK_TILDE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_AMPERSAND (location_type l) + { + return symbol_type (token::TOK_AMPERSAND, std::move (l)); + } +#else + static + symbol_type + make_AMPERSAND (const location_type& l) + { + return symbol_type (token::TOK_AMPERSAND, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_PERCENT (location_type l) + { + return symbol_type (token::TOK_PERCENT, std::move (l)); + } +#else + static + symbol_type + make_PERCENT (const location_type& l) + { + return symbol_type (token::TOK_PERCENT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_BITOR (location_type l) + { + return symbol_type (token::TOK_BITOR, std::move (l)); + } +#else + static + symbol_type + make_BITOR (const location_type& l) + { + return symbol_type (token::TOK_BITOR, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_OROP (location_type l) + { + return symbol_type (token::TOK_OROP, std::move (l)); + } +#else + static + symbol_type + make_OROP (const location_type& l) + { + return symbol_type (token::TOK_OROP, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_EQUAL (location_type l) + { + return symbol_type (token::TOK_EQUAL, std::move (l)); + } +#else + static + symbol_type + make_EQUAL (const location_type& l) + { + return symbol_type (token::TOK_EQUAL, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_EQUAL2 (location_type l) + { + return symbol_type (token::TOK_EQUAL2, std::move (l)); + } +#else + static + symbol_type + make_EQUAL2 (const location_type& l) + { + return symbol_type (token::TOK_EQUAL2, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_GREATER (location_type l) + { + return symbol_type (token::TOK_GREATER, std::move (l)); + } +#else + static + symbol_type + make_GREATER (const location_type& l) + { + return symbol_type (token::TOK_GREATER, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_GREATEREQUAL (location_type l) + { + return symbol_type (token::TOK_GREATEREQUAL, std::move (l)); + } +#else + static + symbol_type + make_GREATEREQUAL (const location_type& l) + { + return symbol_type (token::TOK_GREATEREQUAL, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_LOWER (location_type l) + { + return symbol_type (token::TOK_LOWER, std::move (l)); + } +#else + static + symbol_type + make_LOWER (const location_type& l) + { + return symbol_type (token::TOK_LOWER, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_LOWEREQUAL (location_type l) + { + return symbol_type (token::TOK_LOWEREQUAL, std::move (l)); + } +#else + static + symbol_type + make_LOWEREQUAL (const location_type& l) + { + return symbol_type (token::TOK_LOWEREQUAL, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_UNEQUAL (location_type l) + { + return symbol_type (token::TOK_UNEQUAL, std::move (l)); + } +#else + static + symbol_type + make_UNEQUAL (const location_type& l) + { + return symbol_type (token::TOK_UNEQUAL, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_UNEQUAL2 (location_type l) + { + return symbol_type (token::TOK_UNEQUAL2, std::move (l)); + } +#else + static + symbol_type + make_UNEQUAL2 (const location_type& l) + { + return symbol_type (token::TOK_UNEQUAL2, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_BITWISELEFT (location_type l) + { + return symbol_type (token::TOK_BITWISELEFT, std::move (l)); + } +#else + static + symbol_type + make_BITWISELEFT (const location_type& l) + { + return symbol_type (token::TOK_BITWISELEFT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_BITWISERIGHT (location_type l) + { + return symbol_type (token::TOK_BITWISERIGHT, std::move (l)); + } +#else + static + symbol_type + make_BITWISERIGHT (const location_type& l) + { + return symbol_type (token::TOK_BITWISERIGHT, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ABORT (std::string v, location_type l) + { + return symbol_type (token::TOK_ABORT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_ABORT (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_ABORT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ACTION (std::string v, location_type l) + { + return symbol_type (token::TOK_ACTION, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_ACTION (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_ACTION, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ALWAYS (std::string v, location_type l) + { + return symbol_type (token::TOK_ALWAYS, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_ALWAYS (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_ALWAYS, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_AND (std::string v, location_type l) + { + return symbol_type (token::TOK_AND, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_AND (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_AND, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_AND_BETWEEN (std::string v, location_type l) + { + return symbol_type (token::TOK_AND_BETWEEN, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_AND_BETWEEN (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_AND_BETWEEN, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_AS (std::string v, location_type l) + { + return symbol_type (token::TOK_AS, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_AS (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_AS, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ASC (std::string v, location_type l) + { + return symbol_type (token::TOK_ASC, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_ASC (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_ASC, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_AUTOINCREMENT (std::string v, location_type l) + { + return symbol_type (token::TOK_AUTOINCREMENT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_AUTOINCREMENT (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_AUTOINCREMENT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_BETWEEN (std::string v, location_type l) + { + return symbol_type (token::TOK_BETWEEN, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_BETWEEN (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_BETWEEN, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CASCADE (std::string v, location_type l) + { + return symbol_type (token::TOK_CASCADE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_CASCADE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_CASCADE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CASE (std::string v, location_type l) + { + return symbol_type (token::TOK_CASE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_CASE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_CASE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CAST (std::string v, location_type l) + { + return symbol_type (token::TOK_CAST, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_CAST (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_CAST, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CHECK (std::string v, location_type l) + { + return symbol_type (token::TOK_CHECK, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_CHECK (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_CHECK, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_COLLATE (std::string v, location_type l) + { + return symbol_type (token::TOK_COLLATE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_COLLATE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_COLLATE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CONFLICT (std::string v, location_type l) + { + return symbol_type (token::TOK_CONFLICT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_CONFLICT (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_CONFLICT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CONSTRAINT (std::string v, location_type l) + { + return symbol_type (token::TOK_CONSTRAINT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_CONSTRAINT (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_CONSTRAINT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CREATE (std::string v, location_type l) + { + return symbol_type (token::TOK_CREATE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_CREATE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_CREATE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CURRENT_DATE (std::string v, location_type l) + { + return symbol_type (token::TOK_CURRENT_DATE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_CURRENT_DATE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_CURRENT_DATE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CURRENT_TIME (std::string v, location_type l) + { + return symbol_type (token::TOK_CURRENT_TIME, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_CURRENT_TIME (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_CURRENT_TIME, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_CURRENT_TIMESTAMP (std::string v, location_type l) + { + return symbol_type (token::TOK_CURRENT_TIMESTAMP, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_CURRENT_TIMESTAMP (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_CURRENT_TIMESTAMP, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DEFAULT (std::string v, location_type l) + { + return symbol_type (token::TOK_DEFAULT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_DEFAULT (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_DEFAULT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DEFERRABLE (std::string v, location_type l) + { + return symbol_type (token::TOK_DEFERRABLE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_DEFERRABLE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_DEFERRABLE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DEFERRED (std::string v, location_type l) + { + return symbol_type (token::TOK_DEFERRED, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_DEFERRED (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_DEFERRED, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DELETE (std::string v, location_type l) + { + return symbol_type (token::TOK_DELETE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_DELETE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_DELETE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DESC (std::string v, location_type l) + { + return symbol_type (token::TOK_DESC, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_DESC (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_DESC, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_DISTINCT (std::string v, location_type l) + { + return symbol_type (token::TOK_DISTINCT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_DISTINCT (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_DISTINCT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ELSE (std::string v, location_type l) + { + return symbol_type (token::TOK_ELSE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_ELSE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_ELSE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_END (std::string v, location_type l) + { + return symbol_type (token::TOK_END, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_END (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_END, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ESCAPE (std::string v, location_type l) + { + return symbol_type (token::TOK_ESCAPE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_ESCAPE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_ESCAPE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_EXISTS (std::string v, location_type l) + { + return symbol_type (token::TOK_EXISTS, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_EXISTS (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_EXISTS, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_FAIL (std::string v, location_type l) + { + return symbol_type (token::TOK_FAIL, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_FAIL (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_FAIL, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_FALSE (std::string v, location_type l) + { + return symbol_type (token::TOK_FALSE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_FALSE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_FALSE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_FILTER (std::string v, location_type l) + { + return symbol_type (token::TOK_FILTER, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_FILTER (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_FILTER, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_FOLLOWING (std::string v, location_type l) + { + return symbol_type (token::TOK_FOLLOWING, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_FOLLOWING (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_FOLLOWING, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_FOREIGN (std::string v, location_type l) + { + return symbol_type (token::TOK_FOREIGN, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_FOREIGN (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_FOREIGN, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_FROM (std::string v, location_type l) + { + return symbol_type (token::TOK_FROM, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_FROM (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_FROM, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_GENERATED (std::string v, location_type l) + { + return symbol_type (token::TOK_GENERATED, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_GENERATED (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_GENERATED, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_GLOB (std::string v, location_type l) + { + return symbol_type (token::TOK_GLOB, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_GLOB (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_GLOB, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_IF (std::string v, location_type l) + { + return symbol_type (token::TOK_IF, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_IF (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_IF, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_IGNORE (std::string v, location_type l) + { + return symbol_type (token::TOK_IGNORE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_IGNORE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_IGNORE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_IMMEDIATE (std::string v, location_type l) + { + return symbol_type (token::TOK_IMMEDIATE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_IMMEDIATE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_IMMEDIATE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_IN (std::string v, location_type l) + { + return symbol_type (token::TOK_IN, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_IN (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_IN, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_INDEX (std::string v, location_type l) + { + return symbol_type (token::TOK_INDEX, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_INDEX (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_INDEX, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_INITIALLY (std::string v, location_type l) + { + return symbol_type (token::TOK_INITIALLY, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_INITIALLY (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_INITIALLY, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_INSERT (std::string v, location_type l) + { + return symbol_type (token::TOK_INSERT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_INSERT (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_INSERT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_IS (std::string v, location_type l) + { + return symbol_type (token::TOK_IS, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_IS (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_IS, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ISNULL (std::string v, location_type l) + { + return symbol_type (token::TOK_ISNULL, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_ISNULL (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_ISNULL, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_KEY (std::string v, location_type l) + { + return symbol_type (token::TOK_KEY, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_KEY (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_KEY, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_LIKE (std::string v, location_type l) + { + return symbol_type (token::TOK_LIKE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_LIKE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_LIKE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_MATCH (std::string v, location_type l) + { + return symbol_type (token::TOK_MATCH, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_MATCH (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_MATCH, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_NO (std::string v, location_type l) + { + return symbol_type (token::TOK_NO, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_NO (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_NO, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_NOT (std::string v, location_type l) + { + return symbol_type (token::TOK_NOT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_NOT (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_NOT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_NOTNULL (std::string v, location_type l) + { + return symbol_type (token::TOK_NOTNULL, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_NOTNULL (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_NOTNULL, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_NULL (std::string v, location_type l) + { + return symbol_type (token::TOK_NULL, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_NULL (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_NULL, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ON (std::string v, location_type l) + { + return symbol_type (token::TOK_ON, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_ON (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_ON, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_OR (std::string v, location_type l) + { + return symbol_type (token::TOK_OR, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_OR (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_OR, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_OVER (std::string v, location_type l) + { + return symbol_type (token::TOK_OVER, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_OVER (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_OVER, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_PARTITION (std::string v, location_type l) + { + return symbol_type (token::TOK_PARTITION, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_PARTITION (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_PARTITION, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_PRECEDING (std::string v, location_type l) + { + return symbol_type (token::TOK_PRECEDING, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_PRECEDING (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_PRECEDING, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_PRIMARY (std::string v, location_type l) + { + return symbol_type (token::TOK_PRIMARY, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_PRIMARY (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_PRIMARY, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_RAISE (std::string v, location_type l) + { + return symbol_type (token::TOK_RAISE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_RAISE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_RAISE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_RANGE (std::string v, location_type l) + { + return symbol_type (token::TOK_RANGE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_RANGE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_RANGE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_REFERENCES (std::string v, location_type l) + { + return symbol_type (token::TOK_REFERENCES, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_REFERENCES (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_REFERENCES, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_REGEXP (std::string v, location_type l) + { + return symbol_type (token::TOK_REGEXP, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_REGEXP (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_REGEXP, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_REPLACE (std::string v, location_type l) + { + return symbol_type (token::TOK_REPLACE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_REPLACE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_REPLACE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_RESTRICT (std::string v, location_type l) + { + return symbol_type (token::TOK_RESTRICT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_RESTRICT (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_RESTRICT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_RETURNING (std::string v, location_type l) + { + return symbol_type (token::TOK_RETURNING, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_RETURNING (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_RETURNING, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ROLLBACK (std::string v, location_type l) + { + return symbol_type (token::TOK_ROLLBACK, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_ROLLBACK (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_ROLLBACK, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ROWID (std::string v, location_type l) + { + return symbol_type (token::TOK_ROWID, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_ROWID (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_ROWID, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_ROWS (std::string v, location_type l) + { + return symbol_type (token::TOK_ROWS, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_ROWS (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_ROWS, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SELECT (std::string v, location_type l) + { + return symbol_type (token::TOK_SELECT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_SELECT (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_SELECT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SET (std::string v, location_type l) + { + return symbol_type (token::TOK_SET, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_SET (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_SET, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_STORED (std::string v, location_type l) + { + return symbol_type (token::TOK_STORED, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_STORED (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_STORED, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_STRICT (std::string v, location_type l) + { + return symbol_type (token::TOK_STRICT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_STRICT (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_STRICT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_TABLE (std::string v, location_type l) + { + return symbol_type (token::TOK_TABLE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_TABLE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_TABLE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_TEMP (std::string v, location_type l) + { + return symbol_type (token::TOK_TEMP, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_TEMP (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_TEMP, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_TEMPORARY (std::string v, location_type l) + { + return symbol_type (token::TOK_TEMPORARY, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_TEMPORARY (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_TEMPORARY, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_THEN (std::string v, location_type l) + { + return symbol_type (token::TOK_THEN, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_THEN (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_THEN, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_TRUE (std::string v, location_type l) + { + return symbol_type (token::TOK_TRUE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_TRUE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_TRUE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_UNBOUNDED (std::string v, location_type l) + { + return symbol_type (token::TOK_UNBOUNDED, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_UNBOUNDED (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_UNBOUNDED, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_UNIQUE (std::string v, location_type l) + { + return symbol_type (token::TOK_UNIQUE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_UNIQUE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_UNIQUE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_UPDATE (std::string v, location_type l) + { + return symbol_type (token::TOK_UPDATE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_UPDATE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_UPDATE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_USING (std::string v, location_type l) + { + return symbol_type (token::TOK_USING, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_USING (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_USING, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_VIRTUAL (std::string v, location_type l) + { + return symbol_type (token::TOK_VIRTUAL, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_VIRTUAL (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_VIRTUAL, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_WHEN (std::string v, location_type l) + { + return symbol_type (token::TOK_WHEN, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_WHEN (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_WHEN, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_WHERE (std::string v, location_type l) + { + return symbol_type (token::TOK_WHERE, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_WHERE (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_WHERE, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_WITHOUT (std::string v, location_type l) + { + return symbol_type (token::TOK_WITHOUT, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_WITHOUT (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_WITHOUT, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_IDENTIFIER (std::string v, location_type l) + { + return symbol_type (token::TOK_IDENTIFIER, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_IDENTIFIER (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_IDENTIFIER, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_NUMERIC (std::string v, location_type l) + { + return symbol_type (token::TOK_NUMERIC, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_NUMERIC (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_NUMERIC, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_STRINGLITERAL (std::string v, location_type l) + { + return symbol_type (token::TOK_STRINGLITERAL, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_STRINGLITERAL (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_STRINGLITERAL, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_QUOTEDLITERAL (std::string v, location_type l) + { + return symbol_type (token::TOK_QUOTEDLITERAL, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_QUOTEDLITERAL (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_QUOTEDLITERAL, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_BLOBLITERAL (std::string v, location_type l) + { + return symbol_type (token::TOK_BLOBLITERAL, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_BLOBLITERAL (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_BLOBLITERAL, v, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_BINDPARAMETER (std::string v, location_type l) + { + return symbol_type (token::TOK_BINDPARAMETER, std::move (v), std::move (l)); + } +#else + static + symbol_type + make_BINDPARAMETER (const std::string& v, const location_type& l) + { + return symbol_type (token::TOK_BINDPARAMETER, v, l); + } +#endif + + + class context + { + public: + context (const parser& yyparser, const symbol_type& yyla); + const symbol_type& lookahead () const YY_NOEXCEPT { return yyla_; } + symbol_kind_type token () const YY_NOEXCEPT { return yyla_.kind (); } + const location_type& location () const YY_NOEXCEPT { return yyla_.location; } + + /// Put in YYARG at most YYARGN of the expected tokens, and return the + /// number of tokens stored in YYARG. If YYARG is null, return the + /// number of expected tokens (guaranteed to be less than YYNTOKENS). + int expected_tokens (symbol_kind_type yyarg[], int yyargn) const; + + private: + const parser& yyparser_; + const symbol_type& yyla_; + }; + + private: +#if YY_CPLUSPLUS < 201103L + /// Non copyable. + parser (const parser&); + /// Non copyable. + parser& operator= (const parser&); +#endif + + + /// Stored state numbers (used for stacks). + typedef short state_type; + + /// The arguments of the error message. + int yy_syntax_error_arguments_ (const context& yyctx, + symbol_kind_type yyarg[], int yyargn) const; + + /// Generate an error message. + /// \param yyctx the context in which the error occurred. + virtual std::string yysyntax_error_ (const context& yyctx) const; + /// Compute post-reduction state. + /// \param yystate the current state + /// \param yysym the nonterminal to push on the stack + static state_type yy_lr_goto_state_ (state_type yystate, int yysym); + + /// Whether the given \c yypact_ value indicates a defaulted state. + /// \param yyvalue the value to check + static bool yy_pact_value_is_default_ (int yyvalue) YY_NOEXCEPT; + + /// Whether the given \c yytable_ value indicates a syntax error. + /// \param yyvalue the value to check + static bool yy_table_value_is_error_ (int yyvalue) YY_NOEXCEPT; + + static const short yypact_ninf_; + static const short yytable_ninf_; + + /// Convert a scanner token kind \a t to a symbol kind. + /// In theory \a t should be a token_kind_type, but character literals + /// are valid, yet not members of the token_kind_type enum. + static symbol_kind_type yytranslate_ (int t) YY_NOEXCEPT; + + /// Convert the symbol name \a n to a form suitable for a diagnostic. + static std::string yytnamerr_ (const char *yystr); + + /// For a symbol, its name in clear. + static const char* const yytname_[]; + + + // Tables. + // YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + // STATE-NUM. + static const short yypact_[]; + + // YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + // Performed when YYTABLE does not specify something else to do. Zero + // means the default is an error. + static const short yydefact_[]; + + // YYPGOTO[NTERM-NUM]. + static const short yypgoto_[]; + + // YYDEFGOTO[NTERM-NUM]. + static const short yydefgoto_[]; + + // YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + // positive, shift that token. If negative, reduce the rule whose + // number is the opposite. If YYTABLE_NINF, syntax error. + static const short yytable_[]; + + static const short yycheck_[]; + + // YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of + // state STATE-NUM. + static const unsigned char yystos_[]; + + // YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. + static const unsigned char yyr1_[]; + + // YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. + static const signed char yyr2_[]; + + +#if YYDEBUG + // YYRLINE[YYN] -- Source line where rule number YYN was defined. + static const short yyrline_[]; + /// Report on the debug stream that the rule \a r is going to be reduced. + virtual void yy_reduce_print_ (int r) const; + /// Print the state stack on the debug stream. + virtual void yy_stack_print_ () const; + + /// Debugging level. + int yydebug_; + /// Debug stream. + std::ostream* yycdebug_; + + /// \brief Display a symbol kind, value and location. + /// \param yyo The output stream. + /// \param yysym The symbol. + template + void yy_print_ (std::ostream& yyo, const basic_symbol& yysym) const; +#endif + + /// \brief Reclaim the memory associated to a symbol. + /// \param yymsg Why this token is reclaimed. + /// If null, print nothing. + /// \param yysym The symbol. + template + void yy_destroy_ (const char* yymsg, basic_symbol& yysym) const; + + private: + /// Type access provider for state based symbols. + struct by_state + { + /// Default constructor. + by_state () YY_NOEXCEPT; + + /// The symbol kind as needed by the constructor. + typedef state_type kind_type; + + /// Constructor. + by_state (kind_type s) YY_NOEXCEPT; + + /// Copy constructor. + by_state (const by_state& that) YY_NOEXCEPT; + + /// Record that this symbol is empty. + void clear () YY_NOEXCEPT; + + /// Steal the symbol kind from \a that. + void move (by_state& that); + + /// The symbol kind (corresponding to \a state). + /// \a symbol_kind::S_YYEMPTY when empty. + symbol_kind_type kind () const YY_NOEXCEPT; + + /// The state number used to denote an empty symbol. + /// We use the initial state, as it does not have a value. + enum { empty_state = 0 }; + + /// The state. + /// \a empty when empty. + state_type state; + }; + + /// "Internal" symbol: element of the stack. + struct stack_symbol_type : basic_symbol + { + /// Superclass. + typedef basic_symbol super_type; + /// Construct an empty symbol. + stack_symbol_type (); + /// Move or copy construction. + stack_symbol_type (YY_RVREF (stack_symbol_type) that); + /// Steal the contents from \a sym to build this. + stack_symbol_type (state_type s, YY_MOVE_REF (symbol_type) sym); +#if YY_CPLUSPLUS < 201103L + /// Assignment, needed by push_back by some old implementations. + /// Moves the contents of that. + stack_symbol_type& operator= (stack_symbol_type& that); + + /// Assignment, needed by push_back by other implementations. + /// Needed by some other old implementations. + stack_symbol_type& operator= (const stack_symbol_type& that); +#endif + }; + + /// A stack with random access from its top. + template > + class stack + { + public: + // Hide our reversed order. + typedef typename S::iterator iterator; + typedef typename S::const_iterator const_iterator; + typedef typename S::size_type size_type; + typedef typename std::ptrdiff_t index_type; + + stack (size_type n = 200) YY_NOEXCEPT + : seq_ (n) + {} + +#if 201103L <= YY_CPLUSPLUS + /// Non copyable. + stack (const stack&) = delete; + /// Non copyable. + stack& operator= (const stack&) = delete; +#endif + + /// Random access. + /// + /// Index 0 returns the topmost element. + const T& + operator[] (index_type i) const + { + return seq_[size_type (size () - 1 - i)]; + } + + /// Random access. + /// + /// Index 0 returns the topmost element. + T& + operator[] (index_type i) + { + return seq_[size_type (size () - 1 - i)]; + } + + /// Steal the contents of \a t. + /// + /// Close to move-semantics. + void + push (YY_MOVE_REF (T) t) + { + seq_.push_back (T ()); + operator[] (0).move (t); + } + + /// Pop elements from the stack. + void + pop (std::ptrdiff_t n = 1) YY_NOEXCEPT + { + for (; 0 < n; --n) + seq_.pop_back (); + } + + /// Pop all elements from the stack. + void + clear () YY_NOEXCEPT + { + seq_.clear (); + } + + /// Number of elements on the stack. + index_type + size () const YY_NOEXCEPT + { + return index_type (seq_.size ()); + } + + /// Iterator on top of the stack (going downwards). + const_iterator + begin () const YY_NOEXCEPT + { + return seq_.begin (); + } + + /// Bottom of the stack. + const_iterator + end () const YY_NOEXCEPT + { + return seq_.end (); + } + + /// Present a slice of the top of a stack. + class slice + { + public: + slice (const stack& stack, index_type range) YY_NOEXCEPT + : stack_ (stack) + , range_ (range) + {} + + const T& + operator[] (index_type i) const + { + return stack_[range_ - i]; + } + + private: + const stack& stack_; + index_type range_; + }; + + private: +#if YY_CPLUSPLUS < 201103L + /// Non copyable. + stack (const stack&); + /// Non copyable. + stack& operator= (const stack&); +#endif + /// The wrapped container. + S seq_; + }; + + + /// Stack type. + typedef stack stack_type; + + /// The stack. + stack_type yystack_; + + /// Push a new state on the stack. + /// \param m a debug message to display + /// if null, no trace is output. + /// \param sym the symbol + /// \warning the contents of \a s.value is stolen. + void yypush_ (const char* m, YY_MOVE_REF (stack_symbol_type) sym); + + /// Push a new look ahead token on the state on the stack. + /// \param m a debug message to display + /// if null, no trace is output. + /// \param s the state + /// \param sym the symbol (for its value and location). + /// \warning the contents of \a sym.value is stolen. + void yypush_ (const char* m, state_type s, YY_MOVE_REF (symbol_type) sym); + + /// Pop \a n symbols from the stack. + void yypop_ (int n = 1) YY_NOEXCEPT; + + /// Constants. + enum + { + yylast_ = 3719, ///< Last index in yytable_. + yynnts_ = 57, ///< Number of nonterminal symbols. + yyfinal_ = 13 ///< Termination state number. + }; + + + // User arguments. + yyscan_t yyscanner; + ParserDriver& drv; + + }; + + inline + parser::symbol_kind_type + parser::yytranslate_ (int t) YY_NOEXCEPT + { + // YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to + // TOKEN-NUM as returned by yylex. + static + const signed char + translate_table[] = + { + 0, 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, 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, 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, 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, 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, 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, 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, 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119 + }; + // Last valid token kind. + const int code_max = 374; + + if (t <= 0) + return symbol_kind::S_YYEOF; + else if (t <= code_max) + return static_cast (translate_table[t]); + else + return symbol_kind::S_YYUNDEF; + } + + // basic_symbol. + template + parser::basic_symbol::basic_symbol (const basic_symbol& that) + : Base (that) + , value () + , location (that.location) + { + switch (this->kind ()) + { + case symbol_kind::S_columndef_list: // columndef_list + value.copy< ColumnList > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_columnconstraint_list: // columnconstraint_list + case symbol_kind::S_tableconstraint: // tableconstraint + case symbol_kind::S_tableconstraint_list: // tableconstraint_list + case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list + value.copy< TableConstraints > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_optional_if_not_exists: // optional_if_not_exists + case symbol_kind::S_optional_unique: // optional_unique + case symbol_kind::S_optional_temporary: // optional_temporary + case symbol_kind::S_optional_always_generated: // optional_always_generated + value.copy< bool > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_createindex_stmt: // createindex_stmt + value.copy< sqlb::IndexPtr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_indexed_column: // indexed_column + value.copy< sqlb::IndexedColumn > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_indexed_column_list: // indexed_column_list + value.copy< sqlb::IndexedColumnVector > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_columnid_list: // columnid_list + case symbol_kind::S_optional_columnid_with_paren_list: // optional_columnid_with_paren_list + value.copy< sqlb::StringVector > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_createvirtualtable_stmt: // createvirtualtable_stmt + case symbol_kind::S_createtable_stmt: // createtable_stmt + value.copy< sqlb::TablePtr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_tableoption: // tableoption + case symbol_kind::S_tableoptions_list: // tableoptions_list + case symbol_kind::S_optional_tableoptions_list: // optional_tableoptions_list + value.copy< std::bitset > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_columnconstraint: // columnconstraint + value.copy< std::pair, std::shared_ptr> > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_columndef: // columndef + value.copy< std::shared_ptr > (YY_MOVE (that.value)); + break; + + case symbol_kind::S_ABORT: // "ABORT" + case symbol_kind::S_ACTION: // "ACTION" + case symbol_kind::S_ALWAYS: // "ALWAYS" + case symbol_kind::S_AND: // "AND" + case symbol_kind::S_AND_BETWEEN: // "AND BETWEEN" + case symbol_kind::S_AS: // "AS" + case symbol_kind::S_ASC: // "ASC" + case symbol_kind::S_AUTOINCREMENT: // "AUTOINCREMENT" + case symbol_kind::S_BETWEEN: // "BETWEEN" + case symbol_kind::S_CASCADE: // "CASCADE" + case symbol_kind::S_CASE: // "CASE" + case symbol_kind::S_CAST: // "CAST" + case symbol_kind::S_CHECK: // "CHECK" + case symbol_kind::S_COLLATE: // "COLLATE" + case symbol_kind::S_CONFLICT: // "CONFLICT" + case symbol_kind::S_CONSTRAINT: // "CONSTRAINT" + case symbol_kind::S_CREATE: // "CREATE" + case symbol_kind::S_CURRENT_DATE: // "CURRENT_DATE" + case symbol_kind::S_CURRENT_TIME: // "CURRENT_TIME" + case symbol_kind::S_CURRENT_TIMESTAMP: // "CURRENT_TIMESTAMP" + case symbol_kind::S_DEFAULT: // "DEFAULT" + case symbol_kind::S_DEFERRABLE: // "DEFERRABLE" + case symbol_kind::S_DEFERRED: // "DEFERRED" + case symbol_kind::S_DELETE: // "DELETE" + case symbol_kind::S_DESC: // "DESC" + case symbol_kind::S_DISTINCT: // "DISTINCT" + case symbol_kind::S_ELSE: // "ELSE" + case symbol_kind::S_END: // "END" + case symbol_kind::S_ESCAPE: // "ESCAPE" + case symbol_kind::S_EXISTS: // "EXISTS" + case symbol_kind::S_FAIL: // "FAIL" + case symbol_kind::S_FALSE: // "FALSE" + case symbol_kind::S_FILTER: // "FILTER" + case symbol_kind::S_FOLLOWING: // "FOLLOWING" + case symbol_kind::S_FOREIGN: // "FOREIGN" + case symbol_kind::S_FROM: // "FROM" + case symbol_kind::S_GENERATED: // "GENERATED" + case symbol_kind::S_GLOB: // "GLOB" + case symbol_kind::S_IF: // "IF" + case symbol_kind::S_IGNORE: // "IGNORE" + case symbol_kind::S_IMMEDIATE: // "IMMEDIATE" + case symbol_kind::S_IN: // "IN" + case symbol_kind::S_INDEX: // "INDEX" + case symbol_kind::S_INITIALLY: // "INITIALLY" + case symbol_kind::S_INSERT: // "INSERT" + case symbol_kind::S_IS: // "IS" + case symbol_kind::S_ISNULL: // "ISNULL" + case symbol_kind::S_KEY: // "KEY" + case symbol_kind::S_LIKE: // "LIKE" + case symbol_kind::S_MATCH: // "MATCH" + case symbol_kind::S_NO: // "NO" + case symbol_kind::S_NOT: // "NOT" + case symbol_kind::S_NOTNULL: // "NOTNULL" + case symbol_kind::S_NULL: // "NULL" + case symbol_kind::S_ON: // "ON" + case symbol_kind::S_OR: // "OR" + case symbol_kind::S_OVER: // "OVER" + case symbol_kind::S_PARTITION: // "PARTITION" + case symbol_kind::S_PRECEDING: // "PRECEDING" + case symbol_kind::S_PRIMARY: // "PRIMARY" + case symbol_kind::S_RAISE: // "RAISE" + case symbol_kind::S_RANGE: // "RANGE" + case symbol_kind::S_REFERENCES: // "REFERENCES" + case symbol_kind::S_REGEXP: // "REGEXP" + case symbol_kind::S_REPLACE: // "REPLACE" + case symbol_kind::S_RESTRICT: // "RESTRICT" + case symbol_kind::S_RETURNING: // "RETURNING" + case symbol_kind::S_ROLLBACK: // "ROLLBACK" + case symbol_kind::S_ROWID: // "ROWID" + case symbol_kind::S_ROWS: // "ROWS" + case symbol_kind::S_SELECT: // "SELECT" + case symbol_kind::S_SET: // "SET" + case symbol_kind::S_STORED: // "STORED" + case symbol_kind::S_STRICT: // "STRICT" + case symbol_kind::S_TABLE: // "TABLE" + case symbol_kind::S_TEMP: // "TEMP" + case symbol_kind::S_TEMPORARY: // "TEMPORARY" + case symbol_kind::S_THEN: // "THEN" + case symbol_kind::S_TRUE: // "TRUE" + case symbol_kind::S_UNBOUNDED: // "UNBOUNDED" + case symbol_kind::S_UNIQUE: // "UNIQUE" + case symbol_kind::S_UPDATE: // "UPDATE" + case symbol_kind::S_USING: // "USING" + case symbol_kind::S_VIRTUAL: // "VIRTUAL" + case symbol_kind::S_WHEN: // "WHEN" + case symbol_kind::S_WHERE: // "WHERE" + case symbol_kind::S_WITHOUT: // "WITHOUT" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_NUMERIC: // "numeric" + case symbol_kind::S_STRINGLITERAL: // "string literal" + case symbol_kind::S_QUOTEDLITERAL: // "quoted literal" + case symbol_kind::S_BLOBLITERAL: // "blob literal" + case symbol_kind::S_BINDPARAMETER: // "bind parameter" + case symbol_kind::S_literalvalue: // literalvalue + case symbol_kind::S_id: // id + case symbol_kind::S_allowed_keywords_as_identifier: // allowed_keywords_as_identifier + case symbol_kind::S_tableid: // tableid + case symbol_kind::S_columnid: // columnid + case symbol_kind::S_signednumber: // signednumber + case symbol_kind::S_signednumber_or_numeric: // signednumber_or_numeric + case symbol_kind::S_typename_namelist: // typename_namelist + case symbol_kind::S_type_name: // type_name + case symbol_kind::S_unary_expr: // unary_expr + case symbol_kind::S_binary_expr: // binary_expr + case symbol_kind::S_like_expr: // like_expr + case symbol_kind::S_exprlist_expr: // exprlist_expr + case symbol_kind::S_function_expr: // function_expr + case symbol_kind::S_isnull_expr: // isnull_expr + case symbol_kind::S_between_expr: // between_expr + case symbol_kind::S_in_expr: // in_expr + case symbol_kind::S_whenthenlist_expr: // whenthenlist_expr + case symbol_kind::S_case_expr: // case_expr + case symbol_kind::S_raise_expr: // raise_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_select_stmt: // select_stmt + case symbol_kind::S_optional_sort_order: // optional_sort_order + case symbol_kind::S_optional_where: // optional_where + case symbol_kind::S_tableid_with_uninteresting_schema: // tableid_with_uninteresting_schema + case symbol_kind::S_optional_exprlist_with_paren: // optional_exprlist_with_paren + case symbol_kind::S_optional_conflictclause: // optional_conflictclause + case symbol_kind::S_optional_typename: // optional_typename + case symbol_kind::S_optional_storage_identifier: // optional_storage_identifier + case symbol_kind::S_optional_constraintname: // optional_constraintname + case symbol_kind::S_fk_clause_part: // fk_clause_part + case symbol_kind::S_fk_clause_part_list: // fk_clause_part_list + case symbol_kind::S_optional_fk_clause: // optional_fk_clause + value.copy< std::string > (YY_MOVE (that.value)); + break; + + default: + break; + } + + } + + + + + template + parser::symbol_kind_type + parser::basic_symbol::type_get () const YY_NOEXCEPT + { + return this->kind (); + } + + + template + bool + parser::basic_symbol::empty () const YY_NOEXCEPT + { + return this->kind () == symbol_kind::S_YYEMPTY; + } + + template + void + parser::basic_symbol::move (basic_symbol& s) + { + super_type::move (s); + switch (this->kind ()) + { + case symbol_kind::S_columndef_list: // columndef_list + value.move< ColumnList > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_columnconstraint_list: // columnconstraint_list + case symbol_kind::S_tableconstraint: // tableconstraint + case symbol_kind::S_tableconstraint_list: // tableconstraint_list + case symbol_kind::S_optional_tableconstraint_list: // optional_tableconstraint_list + value.move< TableConstraints > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_optional_if_not_exists: // optional_if_not_exists + case symbol_kind::S_optional_unique: // optional_unique + case symbol_kind::S_optional_temporary: // optional_temporary + case symbol_kind::S_optional_always_generated: // optional_always_generated + value.move< bool > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_createindex_stmt: // createindex_stmt + value.move< sqlb::IndexPtr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_indexed_column: // indexed_column + value.move< sqlb::IndexedColumn > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_indexed_column_list: // indexed_column_list + value.move< sqlb::IndexedColumnVector > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_columnid_list: // columnid_list + case symbol_kind::S_optional_columnid_with_paren_list: // optional_columnid_with_paren_list + value.move< sqlb::StringVector > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_createvirtualtable_stmt: // createvirtualtable_stmt + case symbol_kind::S_createtable_stmt: // createtable_stmt + value.move< sqlb::TablePtr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_tableoption: // tableoption + case symbol_kind::S_tableoptions_list: // tableoptions_list + case symbol_kind::S_optional_tableoptions_list: // optional_tableoptions_list + value.move< std::bitset > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_columnconstraint: // columnconstraint + value.move< std::pair, std::shared_ptr> > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_columndef: // columndef + value.move< std::shared_ptr > (YY_MOVE (s.value)); + break; + + case symbol_kind::S_ABORT: // "ABORT" + case symbol_kind::S_ACTION: // "ACTION" + case symbol_kind::S_ALWAYS: // "ALWAYS" + case symbol_kind::S_AND: // "AND" + case symbol_kind::S_AND_BETWEEN: // "AND BETWEEN" + case symbol_kind::S_AS: // "AS" + case symbol_kind::S_ASC: // "ASC" + case symbol_kind::S_AUTOINCREMENT: // "AUTOINCREMENT" + case symbol_kind::S_BETWEEN: // "BETWEEN" + case symbol_kind::S_CASCADE: // "CASCADE" + case symbol_kind::S_CASE: // "CASE" + case symbol_kind::S_CAST: // "CAST" + case symbol_kind::S_CHECK: // "CHECK" + case symbol_kind::S_COLLATE: // "COLLATE" + case symbol_kind::S_CONFLICT: // "CONFLICT" + case symbol_kind::S_CONSTRAINT: // "CONSTRAINT" + case symbol_kind::S_CREATE: // "CREATE" + case symbol_kind::S_CURRENT_DATE: // "CURRENT_DATE" + case symbol_kind::S_CURRENT_TIME: // "CURRENT_TIME" + case symbol_kind::S_CURRENT_TIMESTAMP: // "CURRENT_TIMESTAMP" + case symbol_kind::S_DEFAULT: // "DEFAULT" + case symbol_kind::S_DEFERRABLE: // "DEFERRABLE" + case symbol_kind::S_DEFERRED: // "DEFERRED" + case symbol_kind::S_DELETE: // "DELETE" + case symbol_kind::S_DESC: // "DESC" + case symbol_kind::S_DISTINCT: // "DISTINCT" + case symbol_kind::S_ELSE: // "ELSE" + case symbol_kind::S_END: // "END" + case symbol_kind::S_ESCAPE: // "ESCAPE" + case symbol_kind::S_EXISTS: // "EXISTS" + case symbol_kind::S_FAIL: // "FAIL" + case symbol_kind::S_FALSE: // "FALSE" + case symbol_kind::S_FILTER: // "FILTER" + case symbol_kind::S_FOLLOWING: // "FOLLOWING" + case symbol_kind::S_FOREIGN: // "FOREIGN" + case symbol_kind::S_FROM: // "FROM" + case symbol_kind::S_GENERATED: // "GENERATED" + case symbol_kind::S_GLOB: // "GLOB" + case symbol_kind::S_IF: // "IF" + case symbol_kind::S_IGNORE: // "IGNORE" + case symbol_kind::S_IMMEDIATE: // "IMMEDIATE" + case symbol_kind::S_IN: // "IN" + case symbol_kind::S_INDEX: // "INDEX" + case symbol_kind::S_INITIALLY: // "INITIALLY" + case symbol_kind::S_INSERT: // "INSERT" + case symbol_kind::S_IS: // "IS" + case symbol_kind::S_ISNULL: // "ISNULL" + case symbol_kind::S_KEY: // "KEY" + case symbol_kind::S_LIKE: // "LIKE" + case symbol_kind::S_MATCH: // "MATCH" + case symbol_kind::S_NO: // "NO" + case symbol_kind::S_NOT: // "NOT" + case symbol_kind::S_NOTNULL: // "NOTNULL" + case symbol_kind::S_NULL: // "NULL" + case symbol_kind::S_ON: // "ON" + case symbol_kind::S_OR: // "OR" + case symbol_kind::S_OVER: // "OVER" + case symbol_kind::S_PARTITION: // "PARTITION" + case symbol_kind::S_PRECEDING: // "PRECEDING" + case symbol_kind::S_PRIMARY: // "PRIMARY" + case symbol_kind::S_RAISE: // "RAISE" + case symbol_kind::S_RANGE: // "RANGE" + case symbol_kind::S_REFERENCES: // "REFERENCES" + case symbol_kind::S_REGEXP: // "REGEXP" + case symbol_kind::S_REPLACE: // "REPLACE" + case symbol_kind::S_RESTRICT: // "RESTRICT" + case symbol_kind::S_RETURNING: // "RETURNING" + case symbol_kind::S_ROLLBACK: // "ROLLBACK" + case symbol_kind::S_ROWID: // "ROWID" + case symbol_kind::S_ROWS: // "ROWS" + case symbol_kind::S_SELECT: // "SELECT" + case symbol_kind::S_SET: // "SET" + case symbol_kind::S_STORED: // "STORED" + case symbol_kind::S_STRICT: // "STRICT" + case symbol_kind::S_TABLE: // "TABLE" + case symbol_kind::S_TEMP: // "TEMP" + case symbol_kind::S_TEMPORARY: // "TEMPORARY" + case symbol_kind::S_THEN: // "THEN" + case symbol_kind::S_TRUE: // "TRUE" + case symbol_kind::S_UNBOUNDED: // "UNBOUNDED" + case symbol_kind::S_UNIQUE: // "UNIQUE" + case symbol_kind::S_UPDATE: // "UPDATE" + case symbol_kind::S_USING: // "USING" + case symbol_kind::S_VIRTUAL: // "VIRTUAL" + case symbol_kind::S_WHEN: // "WHEN" + case symbol_kind::S_WHERE: // "WHERE" + case symbol_kind::S_WITHOUT: // "WITHOUT" + case symbol_kind::S_IDENTIFIER: // "identifier" + case symbol_kind::S_NUMERIC: // "numeric" + case symbol_kind::S_STRINGLITERAL: // "string literal" + case symbol_kind::S_QUOTEDLITERAL: // "quoted literal" + case symbol_kind::S_BLOBLITERAL: // "blob literal" + case symbol_kind::S_BINDPARAMETER: // "bind parameter" + case symbol_kind::S_literalvalue: // literalvalue + case symbol_kind::S_id: // id + case symbol_kind::S_allowed_keywords_as_identifier: // allowed_keywords_as_identifier + case symbol_kind::S_tableid: // tableid + case symbol_kind::S_columnid: // columnid + case symbol_kind::S_signednumber: // signednumber + case symbol_kind::S_signednumber_or_numeric: // signednumber_or_numeric + case symbol_kind::S_typename_namelist: // typename_namelist + case symbol_kind::S_type_name: // type_name + case symbol_kind::S_unary_expr: // unary_expr + case symbol_kind::S_binary_expr: // binary_expr + case symbol_kind::S_like_expr: // like_expr + case symbol_kind::S_exprlist_expr: // exprlist_expr + case symbol_kind::S_function_expr: // function_expr + case symbol_kind::S_isnull_expr: // isnull_expr + case symbol_kind::S_between_expr: // between_expr + case symbol_kind::S_in_expr: // in_expr + case symbol_kind::S_whenthenlist_expr: // whenthenlist_expr + case symbol_kind::S_case_expr: // case_expr + case symbol_kind::S_raise_expr: // raise_expr + case symbol_kind::S_expr: // expr + case symbol_kind::S_select_stmt: // select_stmt + case symbol_kind::S_optional_sort_order: // optional_sort_order + case symbol_kind::S_optional_where: // optional_where + case symbol_kind::S_tableid_with_uninteresting_schema: // tableid_with_uninteresting_schema + case symbol_kind::S_optional_exprlist_with_paren: // optional_exprlist_with_paren + case symbol_kind::S_optional_conflictclause: // optional_conflictclause + case symbol_kind::S_optional_typename: // optional_typename + case symbol_kind::S_optional_storage_identifier: // optional_storage_identifier + case symbol_kind::S_optional_constraintname: // optional_constraintname + case symbol_kind::S_fk_clause_part: // fk_clause_part + case symbol_kind::S_fk_clause_part_list: // fk_clause_part_list + case symbol_kind::S_optional_fk_clause: // optional_fk_clause + value.move< std::string > (YY_MOVE (s.value)); + break; + + default: + break; + } + + location = YY_MOVE (s.location); + } + + // by_kind. + inline + parser::by_kind::by_kind () YY_NOEXCEPT + : kind_ (symbol_kind::S_YYEMPTY) + {} + +#if 201103L <= YY_CPLUSPLUS + inline + parser::by_kind::by_kind (by_kind&& that) YY_NOEXCEPT + : kind_ (that.kind_) + { + that.clear (); + } +#endif + + inline + parser::by_kind::by_kind (const by_kind& that) YY_NOEXCEPT + : kind_ (that.kind_) + {} + + inline + parser::by_kind::by_kind (token_kind_type t) YY_NOEXCEPT + : kind_ (yytranslate_ (t)) + {} + + + + inline + void + parser::by_kind::clear () YY_NOEXCEPT + { + kind_ = symbol_kind::S_YYEMPTY; + } + + inline + void + parser::by_kind::move (by_kind& that) + { + kind_ = that.kind_; + that.clear (); + } + + inline + parser::symbol_kind_type + parser::by_kind::kind () const YY_NOEXCEPT + { + return kind_; + } + + + inline + parser::symbol_kind_type + parser::by_kind::type_get () const YY_NOEXCEPT + { + return this->kind (); + } + + +#line 10 "sqlite3_parser.yy" +} } // sqlb::parser +#line 4414 "sqlite3_parser.hpp" + + + + +#endif // !YY_YY_SQLITE3_PARSER_HPP_INCLUDED diff --git a/src/sql/parser/sqlite3_parser.yy b/src/sql/parser/sqlite3_parser.yy new file mode 100644 index 000000000..fb08f4cf3 --- /dev/null +++ b/src/sql/parser/sqlite3_parser.yy @@ -0,0 +1,921 @@ +%skeleton "lalr1.cc" +%require "3.4.1" +%defines + +%define api.token.constructor +%define api.value.type variant +%define parse.assert +%output "sqlite3_parser.cpp" +%define api.location.file "sqlite3_location.h" +%define api.namespace { sqlb::parser } + +%code requires { + #include + #include + #include "../sqlitetypes.h" + #include "../ObjectIdentifier.h" + namespace sqlb { namespace parser { class ParserDriver; } } + typedef void* yyscan_t; + + struct TableConstraints + { + std::multimap> index; + std::multimap> fk; + std::vector> check; + }; + + using ColumnList = std::pair>, TableConstraints>; +} + +// The parsing context +%param { yyscan_t yyscanner } +%param { ParserDriver& drv } + +%locations + +%define parse.trace +%define parse.error verbose + +%code { + #include "ParserDriver.h" + + static std::string unquote_text(std::string str, char quote_char) + { + if(quote_char != '[') + { + if(str.front() != quote_char || str.back() != quote_char) + return str; + + str = str.substr(1, str.size()-2); + + std::string quote(2, quote_char); + + size_t pos = 0; + while((pos = str.find(quote, pos)) != std::string::npos) + { + str.erase(pos, 1); + pos += 1; // Don't remove the other quote char too + } + return str; + } else { + if(str.front() != '[' || str.back() != ']') + return str; + + return str.substr(1, str.size()-2); + } + } +} + +%define api.token.prefix {TOK_} +%token + EOF 0 "end of file" + LPAREN "(" + RPAREN ")" + DOT "." + COMMA "," + SEMI ";" + PLUS "+" + MINUS "-" + STAR "*" + SLASH "/" + TILDE "~" + AMPERSAND "&" + PERCENT "%" + BITOR "|" + OROP "||" + EQUAL "=" + EQUAL2 "==" + GREATER ">" + GREATEREQUAL ">=" + LOWER "<" + LOWEREQUAL "<=" + UNEQUAL "!=" + UNEQUAL2 "<>" + BITWISELEFT "<<" + BITWISERIGHT ">>" +; + +%token ABORT "ABORT" +%token ACTION "ACTION" +%token ALWAYS "ALWAYS" +%token AND "AND" +%token AND_BETWEEN "AND BETWEEN" +%token AS "AS" +%token ASC "ASC" +%token AUTOINCREMENT "AUTOINCREMENT" +%token BETWEEN "BETWEEN" +%token CASCADE "CASCADE" +%token CASE "CASE" +%token CAST "CAST" +%token CHECK "CHECK" +%token COLLATE "COLLATE" +%token CONFLICT "CONFLICT" +%token CONSTRAINT "CONSTRAINT" +%token CREATE "CREATE" +%token CURRENT_DATE "CURRENT_DATE" +%token CURRENT_TIME "CURRENT_TIME" +%token CURRENT_TIMESTAMP "CURRENT_TIMESTAMP" +%token DEFAULT "DEFAULT" +%token DEFERRABLE "DEFERRABLE" +%token DEFERRED "DEFERRED" +%token DELETE "DELETE" +%token DESC "DESC" +%token DISTINCT "DISTINCT" +%token ELSE "ELSE" +%token END "END" +%token ESCAPE "ESCAPE" +%token EXISTS "EXISTS" +%token FAIL "FAIL" +%token FALSE "FALSE" +%token FILTER "FILTER" +%token FOLLOWING "FOLLOWING" +%token FOREIGN "FOREIGN" +%token FROM "FROM" +%token GENERATED "GENERATED" +%token GLOB "GLOB" +%token IF "IF" +%token IGNORE "IGNORE" +%token IMMEDIATE "IMMEDIATE" +%token IN "IN" +%token INDEX "INDEX" +%token INITIALLY "INITIALLY" +%token INSERT "INSERT" +%token IS "IS" +%token ISNULL "ISNULL" +%token KEY "KEY" +%token LIKE "LIKE" +%token MATCH "MATCH" +%token NO "NO" +%token NOT "NOT" +%token NOTNULL "NOTNULL" +%token NULL "NULL" +%token ON "ON" +%token OR "OR" +%token OVER "OVER" +%token PARTITION "PARTITION" +%token PRECEDING "PRECEDING" +%token PRIMARY "PRIMARY" +%token RAISE "RAISE" +%token RANGE "RANGE" +%token REFERENCES "REFERENCES" +%token REGEXP "REGEXP" +%token REPLACE "REPLACE" +%token RESTRICT "RESTRICT" +%token RETURNING "RETURNING" +%token ROLLBACK "ROLLBACK" +%token ROWID "ROWID" +%token ROWS "ROWS" +%token SELECT "SELECT" +%token SET "SET" +%token STORED "STORED" +%token STRICT "STRICT" +%token TABLE "TABLE" +%token TEMP "TEMP" +%token TEMPORARY "TEMPORARY" +%token THEN "THEN" +%token TRUE "TRUE" +%token UNBOUNDED "UNBOUNDED" +%token UNIQUE "UNIQUE" +%token UPDATE "UPDATE" +%token USING "USING" +%token VIRTUAL "VIRTUAL" +%token WHEN "WHEN" +%token WHERE "WHERE" +%token WITHOUT "WITHOUT" + +%token IDENTIFIER "identifier" +%token NUMERIC "numeric" +%token STRINGLITERAL "string literal" +%token QUOTEDLITERAL "quoted literal" +%token BLOBLITERAL "blob literal" +%token BINDPARAMETER "bind parameter" + +%type literalvalue +%type signednumber +%type signednumber_or_numeric +%type id +%type allowed_keywords_as_identifier +%type tableid +%type columnid +%type typename_namelist +%type type_name +%type unary_expr +%type binary_expr +%type like_expr +%type exprlist_expr +%type function_expr +%type isnull_expr +%type between_expr +%type in_expr +%type whenthenlist_expr +%type case_expr +%type raise_expr +%type expr +%type optional_if_not_exists +%type optional_unique +%type optional_temporary +%type optional_sort_order +%type optional_where +%type optional_constraintname +%type optional_conflictclause +%type tableid_with_uninteresting_schema +%type optional_exprlist_with_paren +%type select_stmt + +%type indexed_column +%type indexed_column_list +%type createindex_stmt +%type createvirtualtable_stmt + +%type optional_typename +%type optional_storage_identifier +%type optional_always_generated +%type columnconstraint_list +%type , std::shared_ptr>> columnconstraint +%type > columndef +%type columndef_list +%type columnid_list +%type optional_columnid_with_paren_list +%type fk_clause_part +%type fk_clause_part_list +%type optional_fk_clause +%type tableconstraint +%type tableconstraint_list +%type optional_tableconstraint_list +%type > tableoption +%type > tableoptions_list +%type > optional_tableoptions_list +%type createtable_stmt + +%% + +%left OR; +%left AND; +%right NOT; +%left IS MATCH LIKE BETWEEN IN UNEQUAL UNEQUAL2 EQUAL EQUAL2 GLOB REGEXP ISNULL NOTNULL; +%left GREATER LOWEREQUAL LOWER GREATEREQUAL; +%right ESCAPE; +%left AMPERSAND BITOR BITWISELEFT BITWISERIGHT; +%left PLUS MINUS; +%left STAR SLASH PERCENT; +%left OROP; +%left COLLATE; +%right TILDE; +%nonassoc ON; + +/* + * Statements + */ + +%start sql; + +sql: + statement + | statement ";" + ; + +statement: + createindex_stmt { drv.result = $1; } + | createvirtualtable_stmt { drv.result = $1; } + | createtable_stmt { drv.result = $1; } + ; + +/* + * Expressions + */ + +literalvalue: + NUMERIC + | STRINGLITERAL + | BLOBLITERAL + | NULL + | TRUE + | FALSE + | CURRENT_TIME + | CURRENT_DATE + | CURRENT_TIMESTAMP + ; + +id: + IDENTIFIER + | QUOTEDLITERAL + //| STRINGLITERAL + ; + +allowed_keywords_as_identifier: + ABORT + | ACTION + | ALWAYS + | ASC + | CASCADE + | CAST + | CONFLICT + | DEFERRED + | DESC + | END + | FAIL + | FILTER + | FOLLOWING + | GENERATED + | GLOB + | KEY + | LIKE + | IGNORE + | INITIALLY + | IMMEDIATE + | MATCH + | NO + | OVER + | PARTITION + | PRECEDING + | RAISE + | RANGE + | REGEXP + | REPLACE + | RESTRICT + | RETURNING + | ROLLBACK + | ROWID + | ROWS + | STORED + | STRICT + | TEMPORARY + | TEMP + | UNBOUNDED + | VIRTUAL + | WITHOUT + ; + +tableid: + allowed_keywords_as_identifier + | CURRENT_TIME + | CURRENT_DATE + | CURRENT_TIMESTAMP + | id + | STRINGLITERAL { $$ = unquote_text($1, '\''); } + ; + +columnid: + allowed_keywords_as_identifier + | CURRENT_TIME + | CURRENT_DATE + | CURRENT_TIMESTAMP + | IF + | id + | STRINGLITERAL { $$ = unquote_text($1, '\''); } + ; + +signednumber: + "+" NUMERIC { $$ = "+" + $2; } // No NUMERIC without "+" or "-" here because that is just a literalvalue + | "-" NUMERIC { $$ = "-" + $2; } + ; + +signednumber_or_numeric: + signednumber + | NUMERIC + ; + +typename_namelist: + tableid { $$ = $1; } + | typename_namelist tableid { $$ = $1 + " " + $2; } + ; + +type_name: + typename_namelist { $$ = $1; } + | typename_namelist "(" signednumber_or_numeric ")" { $$ = $1 + "(" + $3 + ")"; } + | typename_namelist "(" signednumber_or_numeric "," signednumber_or_numeric ")" { $$ = $1 + "(" + $3 + ", " + $5 + ")"; } + ; + +unary_expr: + "-" expr %prec TILDE { $$ = "-" + $2; } + | "+" expr %prec TILDE { $$ = "+" + $2; } + | "~" expr { $$ = "~" + $2; } + | NOT expr { $$ = "NOT " + $2; } + ; + +binary_expr: + expr "||" expr { $$ = $1 + " || " + $3; } + | expr "*" expr { $$ = $1 + " * " + $3; } + | expr "/" expr { $$ = $1 + " / " + $3; } + | expr "%" expr { $$ = $1 + " % " + $3; } + | expr "+" expr { $$ = $1 + " + " + $3; } + | expr "-" expr { $$ = $1 + " - " + $3; } + | expr "<<" expr { $$ = $1 + " << " + $3; } + | expr ">>" expr { $$ = $1 + " >> " + $3; } + | expr "&" expr { $$ = $1 + " & " + $3; } + | expr "|" expr { $$ = $1 + " | " + $3; } + | expr "<" expr { $$ = $1 + " < " + $3; } + | expr "<=" expr { $$ = $1 + " <= " + $3; } + | expr ">" expr { $$ = $1 + " > " + $3; } + | expr ">=" expr { $$ = $1 + " >= " + $3; } + | expr "=" expr { $$ = $1 + " = " + $3; } + | expr "==" expr { $$ = $1 + " == " + $3; } + | expr "!=" expr { $$ = $1 + " != " + $3; } + | expr "<>" expr { $$ = $1 + " <> " + $3; } + | expr IS expr { $$ = $1 + " IS " + $3; } + | expr IS DISTINCT FROM expr %prec TILDE { $$ = $1 + " IS DISTINCT FROM " + $5; } + | expr IS NOT DISTINCT FROM expr %prec TILDE { $$ = $1 + " IS NOT DISTINCT FROM " + $6; } + | expr AND expr { $$ = $1 + " AND " + $3; } + | expr OR expr { $$ = $1 + " OR " + $3; } + ; + +like_expr: + expr LIKE expr { $$ = $1 + " LIKE " + $3; } + | expr GLOB expr { $$ = $1 + " GLOB " + $3; } + | expr MATCH expr { $$ = $1 + " MATCH " + $3; } + | expr REGEXP expr { $$ = $1 + " REGEXP " + $3; } + | expr NOT LIKE expr { $$ = $1 + " NOT LIKE " + $4; } + | expr NOT GLOB expr { $$ = $1 + " NOT GLOB " + $4; } + | expr NOT MATCH expr { $$ = $1 + " NOT MATCH " + $4; } + | expr NOT REGEXP expr { $$ = $1 + " NOT REGEXP " + $4; } + | expr LIKE expr ESCAPE expr %prec LIKE { $$ = $1 + " LIKE " + $3 + " ESCAPE " + $5; } + | expr GLOB expr ESCAPE expr %prec GLOB { $$ = $1 + " GLOB " + $3 + " ESCAPE " + $5; } + | expr MATCH expr ESCAPE expr %prec MATCH { $$ = $1 + " MATCH " + $3 + " ESCAPE " + $5; } + | expr REGEXP expr ESCAPE expr %prec REGEXP { $$ = $1 + " REGEXP " + $3 + " ESCAPE " + $5; } + | expr NOT LIKE expr ESCAPE expr %prec LIKE { $$ = $1 + " NOT LIKE " + $3 + " ESCAPE " + $6; } + | expr NOT GLOB expr ESCAPE expr %prec GLOB { $$ = $1 + " NOT GLOB " + $3 + " ESCAPE " + $6; } + | expr NOT MATCH expr ESCAPE expr %prec MATCH { $$ = $1 + " NOT MATCH " + $3 + " ESCAPE " + $6; } + | expr NOT REGEXP expr ESCAPE expr %prec REGEXP { $$ = $1 + " NOT REGEXP " + $3 + " ESCAPE " + $6; } + ; + +exprlist_expr: + expr { $$ = $1; } + | exprlist_expr "," expr { $$ = $1 + ", " + $3; } + ; + +function_expr: + id "(" exprlist_expr ")" { $$ = $1 + "(" + $3 + ")"; } + | id "(" DISTINCT exprlist_expr ")" { $$ = $1 + "(DISTINCT " + $4 + ")"; } + | id "(" ")" { $$ = $1 + "()"; } + | id "(" "*" ")" { $$ = $1 + "(*)"; } + ; + +isnull_expr: + expr ISNULL { $$ = $1 + " ISNULL"; } + | expr NOTNULL { $$ = $1 + " NOTNULL"; } + | expr NOT NULL %prec NOTNULL { $$ = $1 + " NOT NULL"; } + ; + +between_expr: + expr BETWEEN expr AND_BETWEEN expr %prec BETWEEN { $$ = $1 + " BETWEEN " + $3 + " AND " + $5; } + | expr NOT BETWEEN expr AND_BETWEEN expr %prec BETWEEN { $$ = $1 + " NOT BETWEEN " + $4 + " AND " + $6; } + ; + +in_expr: + expr IN "(" ")" { $$ = $1 + " IN ()"; } + | expr IN "(" select_stmt ")" { $$ = $1 + " IN (" + $4 + ")"; } + | expr IN "(" exprlist_expr ")" { $$ = $1 + " IN (" + $4 + ")"; } + | expr IN id "." tableid { $$ = $1 + " IN " + sqlb::escapeIdentifier($3) + "." + sqlb::escapeIdentifier($5); } + | expr IN tableid { $$ = $1 + " IN " + sqlb::escapeIdentifier($3); } + | expr IN id "." id "(" ")" { $$ = $1 + " IN " + sqlb::escapeIdentifier($3) + "." + $5 + "()"; } + | expr IN id "." id "(" exprlist_expr ")" { $$ = $1 + " IN " + sqlb::escapeIdentifier($3) + "." + $5 + "(" + $7 + ")"; } + | expr IN id "(" exprlist_expr ")" { $$ = $1 + " IN " + $3 + "(" + $5 + ")"; } + | expr NOT IN "(" ")" { $$ = $1 + " NOT IN ()"; } + | expr NOT IN "(" select_stmt ")" { $$ = $1 + " NOT IN (" + $5 + ")"; } + | expr NOT IN "(" exprlist_expr ")" { $$ = $1 + " NOT IN (" + $5 + ")"; } + | expr NOT IN id "." tableid { $$ = $1 + " NOT IN " + sqlb::escapeIdentifier($4) + "." + sqlb::escapeIdentifier($6); } + | expr NOT IN tableid { $$ = $1 + " NOT IN " + sqlb::escapeIdentifier($4); } + | expr NOT IN id "." id "(" ")" { $$ = $1 + " NOT IN " + sqlb::escapeIdentifier($4) + "." + $6 + "()"; } + | expr NOT IN id "." id "(" exprlist_expr ")" { $$ = $1 + " NOT IN " + sqlb::escapeIdentifier($4) + "." + $6 + "(" + $8 + ")"; } + | expr NOT IN id "(" exprlist_expr ")" { $$ = $1 + " NOT IN " + $4 + "(" + $6 + ")"; } + ; + +whenthenlist_expr: + WHEN expr THEN expr { $$ = "WHEN " + $2 + " THEN " + $4; } + | whenthenlist_expr WHEN expr THEN expr { $$ = $1 + " WHEN" + $3 + " THEN " + $5; } + ; + +case_expr: + CASE expr whenthenlist_expr ELSE expr END { $$ = "CASE " + $2 + " " + $3 + " ELSE " + $5 + " END"; } + | CASE expr whenthenlist_expr END { $$ = "CASE " + $2 + " " + $3 + " END"; } + | CASE whenthenlist_expr ELSE expr END { $$ = "CASE " + $2 + " ELSE " + $4 + " END"; } + | CASE whenthenlist_expr END { $$ = "CASE " + $2 + " END"; } + ; + +raise_expr: + RAISE "(" IGNORE ")" { $$ = "RAISE(IGNORE)"; } + | RAISE "(" ROLLBACK "," STRINGLITERAL ")" { $$ = "RAISE(ROLLBACK, " + $5 + ")"; } + | RAISE "(" ABORT "," STRINGLITERAL ")" { $$ = "RAISE(ABORT, " + $5 + ")"; } + | RAISE "(" FAIL "," STRINGLITERAL ")" { $$ = "RAISE(FAIL, " + $5 + ")"; } + ; + +expr: + literalvalue + | allowed_keywords_as_identifier { $$ = sqlb::escapeIdentifier($1); } + | BINDPARAMETER + | id "." id "." id { $$ = sqlb::escapeIdentifier($1) + "." + sqlb::escapeIdentifier($3) + "." + sqlb::escapeIdentifier($5); } + | id "." id { $$ = sqlb::escapeIdentifier($1) + "." + sqlb::escapeIdentifier($3); } + | id { $$ = sqlb::escapeIdentifier($1); } + | unary_expr + | binary_expr + | function_expr + | "(" exprlist_expr ")" { $$ = "(" + $2 + ")"; } + | CAST "(" expr AS type_name ")" { $$ = "CAST(" + $3 + " AS " + $5 + ")"; } + | expr COLLATE id { $$ = $1 + " COLLATE " + $3; } + | like_expr + | isnull_expr + | between_expr + | in_expr + | case_expr + | raise_expr + // TODO Window functions + ; + +/* + * SELECT + */ + +select_stmt: + SELECT { $$ = "SELECT"; } // TODO + ; + +/* + * Helper rules for CREATE statements + */ + +optional_if_not_exists: + %empty { $$ = false; } + | IF NOT EXISTS { $$ = true; } + ; + +optional_sort_order: + %empty { } + | ASC { $$ = "ASC"; } + | DESC { $$ = "DESC"; } + ; + +/* + * CREATE INDEX + */ + +optional_unique: + %empty { $$ = false; } + | UNIQUE { $$ = true; } + ; + +optional_where: + %empty { } + | WHERE expr { $$ = $2; } + ; + +tableid_with_uninteresting_schema: + id "." tableid { $$ = $3; } + | TEMP "." tableid { $$ = $3; } + | tableid { $$ = $1; } + ; + +indexed_column: + expr optional_sort_order { + // If the expression is only one column name and nothing else, treat it as a column name; otherwise as an expression. + char quote = getIdentifierQuoteChar(); + if((quote == '[' && std::count($1.begin(), $1.end(), quote) == 1 && $1.front() == '[' && $1.back() == ']') || + (quote != '[' && std::count($1.begin(), $1.end(), quote) == 2 && $1.front() == quote && $1.back() == quote)) + { + $$ = sqlb::IndexedColumn(unquote_text($1, quote), false, $2); + } else if(std::count($1.begin(), $1.end(), '\'') == 2 && $1.front() == '\'' && $1.back() == '\'') { + // Also remove single quotes when this actually is a string literal but looks like a columnid + $$ = sqlb::IndexedColumn(unquote_text($1, '\''), false, $2); + } else { + $$ = sqlb::IndexedColumn($1, true, $2); + } + } + ; + +indexed_column_list: + indexed_column { $$ = sqlb::IndexedColumnVector(1, $1); } + | indexed_column_list "," indexed_column { $$ = $1; $$.push_back($3); } + ; + +createindex_stmt: + CREATE optional_unique INDEX optional_if_not_exists tableid_with_uninteresting_schema ON tableid "(" indexed_column_list ")" optional_where { + $$ = std::make_shared($5); + $$->setTable($7); + $$->setUnique($2); + $$->setWhereExpr($11); + $$->fields = $9; + $$->setFullyParsed(true); + } + ; + +/* + * CREATE VIRTUAL TABLE + */ + +optional_exprlist_with_paren: + %empty { } + | "(" ")" { } + | "(" exprlist_expr ")" { $$ = $2; } + ; + +createvirtualtable_stmt: + CREATE VIRTUAL TABLE optional_if_not_exists tableid_with_uninteresting_schema USING id optional_exprlist_with_paren { + $$ = std::make_shared($5); + $$->setVirtualUsing($7); + $$->setFullyParsed(false); + } + ; + +/* + * CREATE TABLE + */ + +optional_temporary: + %empty { $$ = false; } + | TEMP { $$ = true; } + | TEMPORARY { $$ = true; } + ; + +tableoption: + WITHOUT ROWID { $$.set(sqlb::Table::WithoutRowid, true); } + | STRICT { $$.set(sqlb::Table::Strict, true); } + ; + +tableoptions_list: + tableoption { $$ = $1; } + | tableoptions_list "," tableoption { $$ = $1 | $3; } + | tableoptions_list tableoption { $$ = $1 | $2; } + ; + +optional_tableoptions_list: + %empty { } + | tableoptions_list { $$ = $1; } + ; + +optional_conflictclause: + %empty { } + | ON CONFLICT ROLLBACK { $$ = $3; } + | ON CONFLICT ABORT { $$ = $3; } + | ON CONFLICT FAIL { $$ = $3; } + | ON CONFLICT IGNORE { $$ = $3; } + | ON CONFLICT REPLACE { $$ = $3; } + ; + +optional_typename: + %empty { } + | type_name { $$ = $1; } + ; + +optional_storage_identifier: + %empty { $$ = "VIRTUAL"; } + | STORED { $$ = "STORED"; } + | VIRTUAL { $$ = "VIRTUAL"; } + ; + +optional_always_generated: + %empty { $$ = false; } + | GENERATED ALWAYS { $$ = true; } + ; + +columnconstraint: + optional_constraintname PRIMARY KEY optional_sort_order optional_conflictclause { + auto pk = std::make_shared(); + pk->setName($1); + pk->setConflictAction($5); + $$.first = pk; + } + | optional_constraintname PRIMARY KEY optional_sort_order optional_conflictclause AUTOINCREMENT { + auto pk = std::make_shared(); + pk->setName($1); + pk->setConflictAction($5); + pk->setAutoIncrement(true); + $$.first = pk; + } + | optional_constraintname NOT NULL optional_conflictclause { + auto nn = std::make_shared(); + nn->setName($1); + nn->setConflictAction($4); + drv.last_table_column->setNotNull(nn); + } + | optional_constraintname NULL { + } + | optional_constraintname UNIQUE optional_conflictclause { + auto u = std::make_shared(); + u->setName($1); + u->setConflictAction($3); + drv.last_table_column->setUnique(u); + } + | optional_constraintname CHECK "(" expr ")" { + auto c = std::make_shared($4); + c->setName($1); + drv.last_table_column->setCheck(c); + } + | optional_constraintname DEFAULT signednumber { + auto d = std::make_shared($3); + d->setName($1); + drv.last_table_column->setDefaultValue(d); + } + | optional_constraintname DEFAULT literalvalue { + auto d = std::make_shared($3); + d->setName($1); + drv.last_table_column->setDefaultValue(d); + } + | optional_constraintname DEFAULT id { + auto d = std::make_shared($3); + d->setName($1); + drv.last_table_column->setDefaultValue(d); + } + | optional_constraintname DEFAULT allowed_keywords_as_identifier { // We must allow the same keywords as unquoted default values as in the columnid context. + // But we do not use columnid here in order to avoid reduce/reduce conflicts. + auto d = std::make_shared($3); + d->setName($1); + drv.last_table_column->setDefaultValue(d); + } + | optional_constraintname DEFAULT IF { // Same as above. + auto d = std::make_shared($3); + d->setName($1); + drv.last_table_column->setDefaultValue(d); + } + | optional_constraintname DEFAULT "(" expr ")" { + auto d = std::make_shared("(" + $4 + ")"); + d->setName($1); + drv.last_table_column->setDefaultValue(d); + } + | optional_constraintname COLLATE id { + auto c = std::make_shared($3); + c->setName($1); + drv.last_table_column->setCollation(c); + } + | optional_constraintname REFERENCES tableid optional_columnid_with_paren_list optional_fk_clause { // TODO Solve shift/reduce conflict. It is not super important though as shifting seems to be right here. + auto fk = std::make_shared(); + fk->setName($1); + fk->setTable($3); + fk->setColumns($4); + fk->setConstraint($5); + $$.second = fk; + } + | optional_constraintname optional_always_generated AS "(" expr ")" optional_storage_identifier { // TODO Solve shift/reduce conflict. + auto g = std::make_shared($5, $7); + g->setName($1); + + drv.last_table_column->setGenerated(g); + + // This is a hack which removes any "GENERATED ALWAYS" from the end of the type name. + // As of now these are shifted to the type instead of reducing the type when seeing the GENERATED identifier. + // TODO Remove this once the grammar is conflict free + const std::string generated_always = "GENERATED ALWAYS"; + if(drv.last_table_column->type().size() >= generated_always.size() && drv.last_table_column->type().compare(drv.last_table_column->type().size() - generated_always.size(), generated_always.size(), generated_always) == 0) + { + std::string type = drv.last_table_column->type().substr(0, drv.last_table_column->type().size()-generated_always.size()); + if(type.back() == ' ') + type.pop_back(); + drv.last_table_column->setType(type); + } + } + ; + +columnconstraint_list: + %empty { } + | columnconstraint_list columnconstraint { + $$ = $1; + + // Primary key and foreign key constraints are converted to table constraints + // because we cannot store them as column constraints at the moment. + if($2.first) + $$.index.insert(std::make_pair(sqlb::IndexedColumnVector{sqlb::IndexedColumn(drv.last_table_column->name(), false)}, $2.first)); + if($2.second) + $$.fk.insert(std::make_pair(sqlb::StringVector{drv.last_table_column->name()}, $2.second)); + } + ; + +columndef: + columnid optional_typename { $$ = std::make_shared($1, $2); drv.last_table_column = $$; } + ; + +columndef_list: + columndef columnconstraint_list { $$.first.push_back($1); $$.second = $2; } + | columndef_list "," columndef columnconstraint_list { $$ = $1; $$.first.push_back($3); $$.second.index.insert($4.index.begin(), $4.index.end()); $$.second.fk.insert($4.fk.begin(), $4.fk.end()); } + ; + +optional_constraintname: + %empty { } + | CONSTRAINT id { $$ = $2; } + | CONSTRAINT STRINGLITERAL { $$ = $2; } + ; + +columnid_list: + columnid { $$ = sqlb::StringVector(1, $1); } + | columnid_list "," columnid { $$ = $1; $$.push_back($3); } + ; + +optional_columnid_with_paren_list: + %empty { } + | "(" columnid_list ")" { $$ = $2; } + ; + +fk_clause_part: + ON DELETE SET NULL { $$ = $1 + " " + $2 + " " + $3 + " " + $4; } + | ON DELETE SET DEFAULT { $$ = $1 + " " + $2 + " " + $3 + " " + $4; } + | ON DELETE CASCADE { $$ = $1 + " " + $2 + " " + $3; } + | ON DELETE RESTRICT { $$ = $1 + " " + $2 + " " + $3; } + | ON DELETE NO ACTION { $$ = $1 + " " + $2 + " " + $3 + " " + $4; } + | ON UPDATE SET NULL { $$ = $1 + " " + $2 + " " + $3 + " " + $4; } + | ON UPDATE SET DEFAULT { $$ = $1 + " " + $2 + " " + $3 + " " + $4; } + | ON UPDATE CASCADE { $$ = $1 + " " + $2 + " " + $3; } + | ON UPDATE RESTRICT { $$ = $1 + " " + $2 + " " + $3; } + | ON UPDATE NO ACTION { $$ = $1 + " " + $2 + " " + $3 + " " + $4; } + | ON INSERT SET NULL { $$ = $1 + " " + $2 + " " + $3 + " " + $4; } + | ON INSERT SET DEFAULT { $$ = $1 + " " + $2 + " " + $3 + " " + $4; } + | ON INSERT CASCADE { $$ = $1 + " " + $2 + " " + $3; } + | ON INSERT RESTRICT { $$ = $1 + " " + $2 + " " + $3; } + | ON INSERT NO ACTION { $$ = $1 + " " + $2 + " " + $3 + " " + $4; } + | MATCH id { $$ = $1 + " " + $2; } + ; + +fk_clause_part_list: + fk_clause_part { $$ = $1; } + | fk_clause_part_list fk_clause_part { $$ = $1 + " " + $2; } + ; + +optional_fk_clause: + %empty { } + | fk_clause_part_list { $$ = $1; } + | fk_clause_part_list DEFERRABLE INITIALLY DEFERRED { $$ = $1 + " " + $2 + " " + $3 + " " + $4; } + | fk_clause_part_list DEFERRABLE INITIALLY IMMEDIATE { $$ = $1 + " " + $2 + " " + $3 + " " + $4; } + | fk_clause_part_list DEFERRABLE { $$ = $1 + " " + $2; } + | fk_clause_part_list NOT DEFERRABLE INITIALLY DEFERRED { $$ = $1 + " " + $2 + " " + $3 + " " + $4 + " " + $5; } + | fk_clause_part_list NOT DEFERRABLE INITIALLY IMMEDIATE { $$ = $1 + " " + $2 + " " + $3 + " " + $4 + " " + $5; } + | fk_clause_part_list NOT DEFERRABLE { $$ = $1 + " " + $2 + " " + $3; } + | DEFERRABLE INITIALLY DEFERRED { $$ = $1 + " " + $2 + " " + $3; } + | DEFERRABLE INITIALLY IMMEDIATE { $$ = $1 + " " + $2 + " " + $3; } + | DEFERRABLE { $$ = $1; } + | NOT DEFERRABLE INITIALLY DEFERRED { $$ = $1 + " " + $2 + " " + $3 + " " + $4; } + | NOT DEFERRABLE INITIALLY IMMEDIATE { $$ = $1 + " " + $2 + " " + $3 + " " + $4; } + | NOT DEFERRABLE { $$ = $1 + " " + $2; } + ; + +tableconstraint: + optional_constraintname PRIMARY KEY "(" indexed_column_list ")" optional_conflictclause { + auto pk = std::make_shared(); + pk->setName($1); + pk->setConflictAction($7); + $$.index.insert(std::make_pair($5, pk)); + } + | optional_constraintname PRIMARY KEY "(" indexed_column_list AUTOINCREMENT ")" optional_conflictclause { + auto pk = std::make_shared(); + pk->setName($1); + pk->setConflictAction($8); + pk->setAutoIncrement(true); + $$.index.insert(std::make_pair($5, pk)); + } + | optional_constraintname UNIQUE "(" indexed_column_list ")" optional_conflictclause { + auto u = std::make_shared(); + u->setName($1); + u->setConflictAction($6); + sqlb::StringVector columns; + $$.index.insert(std::make_pair($4, u)); + } + | optional_constraintname CHECK "(" expr ")" { + auto c = std::make_shared($4); + c->setName($1); + $$.check.push_back(c); + } + | optional_constraintname FOREIGN KEY "(" columnid_list ")" REFERENCES tableid optional_columnid_with_paren_list optional_fk_clause { + auto f = std::make_shared($8, $9, $10); + f->setName($1); + $$.fk.insert(std::make_pair($5, f)); + } + ; + +tableconstraint_list: + tableconstraint { $$ = $1; } + | tableconstraint_list "," tableconstraint { $$ = $1; $$.index.insert($3.index.begin(), $3.index.end()); $$.fk.insert($3.fk.begin(), $3.fk.end()); std::copy($3.check.begin(), $3.check.end(), std::back_inserter($$.check)); } + | tableconstraint_list tableconstraint { $$ = $1; $$.index.insert($2.index.begin(), $2.index.end()); $$.fk.insert($2.fk.begin(), $2.fk.end()); std::copy($2.check.begin(), $2.check.end(), std::back_inserter($$.check)); } + ; + +optional_tableconstraint_list: + %empty { } + | "," tableconstraint_list { $$ = $2; } + ; + +createtable_stmt: + CREATE optional_temporary TABLE optional_if_not_exists tableid_with_uninteresting_schema AS select_stmt { + $$ = std::make_shared($5); + $$->setFullyParsed(false); + } + | CREATE optional_temporary TABLE optional_if_not_exists tableid_with_uninteresting_schema "(" columndef_list optional_tableconstraint_list ")" optional_tableoptions_list { + $$ = std::make_shared($5); + $$->setWithoutRowidTable($10.test(sqlb::Table::WithoutRowid)); + $$->setStrict($10.test(sqlb::Table::Strict)); + for(const auto& i : $8.index) + $$->addConstraint(i.first, i.second); + for(const auto& i : $8.fk) + $$->addConstraint(i.first, i.second); + for(const auto& i : $8.check) + $$->addConstraint(i); + $$->setFullyParsed(true); + + for(const auto& f : $7.first) + $$->fields.push_back(*f); + for(const auto& pk : $7.second.index) + $$->addConstraint(pk.first, pk.second); + for(const auto& fk : $7.second.fk) + $$->addConstraint(fk.first, fk.second); + } + ; + +%% + +void sqlb::parser::parser::error(const location_type& l, const std::string& m) +{ + std::cerr << l << ": " << m << std::endl; +} diff --git a/src/sql/sqlitetypes.cpp b/src/sql/sqlitetypes.cpp new file mode 100644 index 000000000..aa00f5875 --- /dev/null +++ b/src/sql/sqlitetypes.cpp @@ -0,0 +1,697 @@ +#include "sqlitetypes.h" +#include "ObjectIdentifier.h" +#include "parser/ParserDriver.h" + +#include +#include +#include + +namespace sqlb { + +StringVector escapeIdentifier(StringVector ids) +{ + std::transform(ids.begin(), ids.end(), ids.begin(), [](const std::string& id) { + return escapeIdentifier(id); + }); + return ids; +} + +std::string joinStringVector(const StringVector& vec, const std::string& delim) +{ + return std::accumulate(vec.begin(), vec.end(), std::string(), [delim](const std::string& so_far, const std::string& s) { + return so_far.empty() ? s : so_far + delim + s; + }); +} + +std::string joinStringVector(const IndexedColumnVector& vec, const std::string& delim) +{ + return std::accumulate(vec.begin(), vec.end(), std::string(), [delim](const std::string& so_far, const IndexedColumn& c) { + return so_far.empty() ? c.toString("", " ") : so_far + delim + c.toString("", ""); + }); +} + +bool Object::operator==(const Object& rhs) const +{ + if(m_name != rhs.m_name) + return false; + if(m_fullyParsed != rhs.m_fullyParsed) // We check for the fully parsed flag to make sure not to lose anything in some corner cases + return false; + + // We don't care about the original SQL text + + return true; +} + +std::string ForeignKeyClause::toString() const +{ + std::string result = escapeIdentifier(m_table); + + if(m_columns.size()) + result += "(" + joinStringVector(escapeIdentifier(m_columns), ",") + ")"; + + if(m_constraint.size()) + result += " " + m_constraint; + + return result; +} + +std::string ForeignKeyClause::toSql(const StringVector& columns) const +{ + std::string result; + if(!m_name.empty()) + result = "CONSTRAINT " + escapeIdentifier(m_name) + " "; + result += "FOREIGN KEY(" + joinStringVector(escapeIdentifier(columns), ",") + ") REFERENCES " + this->toString(); + + return result; +} + +std::string UniqueConstraint::toSql(const IndexedColumnVector& columns) const +{ + std::string result; + if(!m_name.empty()) + result = "CONSTRAINT " + escapeIdentifier(m_name) + " "; + + result += "UNIQUE"; + + if(columns.size()) + result += "(" + joinStringVector(columns, ",") + ")"; + + if(!m_conflictAction.empty()) + result += " ON CONFLICT " + m_conflictAction; + + return result; +} + +std::string NotNullConstraint::toSql() const +{ + std::string result; + if(!m_name.empty()) + result = "CONSTRAINT " + escapeIdentifier(m_name) + " "; + + result += "NOT NULL"; + + if(!m_conflictAction.empty()) + result += " ON CONFLICT " + m_conflictAction; + + return result; +} + +std::string PrimaryKeyConstraint::toSql(const IndexedColumnVector& columns) const +{ + std::string result; + if(!m_name.empty()) + result = "CONSTRAINT " + escapeIdentifier(m_name) + " "; + + result += "PRIMARY KEY(" + joinStringVector(columns, ",") + (m_auto_increment ? " AUTOINCREMENT" : "") + ")"; + + if(!m_conflictAction.empty()) + result += " ON CONFLICT " + m_conflictAction; + + return result; +} + +std::string CheckConstraint::toSql() const +{ + std::string result; + if(!m_name.empty()) + result = "CONSTRAINT " + escapeIdentifier(m_name) + " "; + result += "CHECK(" + m_expression + ")"; + + return result; +} + +std::string DefaultConstraint::toSql() const +{ + std::string result; + if(!m_name.empty()) + result = "CONSTRAINT " + escapeIdentifier(m_name) + " "; + result += "DEFAULT " + m_value; + + return result; +} + +std::string CollateConstraint::toSql() const +{ + std::string result; + if(!m_name.empty()) + result = "CONSTRAINT " + escapeIdentifier(m_name) + " "; + result += "COLLATE " + m_collation; + + return result; +} + +std::string GeneratedColumnConstraint::toSql() const +{ + std::string result; + if(!m_name.empty()) + result = "CONSTRAINT " + escapeIdentifier(m_name) + " "; + result += "GENERATED ALWAYS AS (" + m_expression + ")" + " " + storage(); + + return result; +} + +bool Field::operator==(const Field& rhs) const +{ + if(m_name != rhs.m_name) + return false; + if(m_type != rhs.m_type) + return false; + if(m_notnull != rhs.m_notnull) + return false; + if(m_check != rhs.m_check) + return false; + if(m_defaultvalue != rhs.m_defaultvalue) + return false; + if(m_unique != rhs.m_unique) + return false; + if(m_collation != rhs.m_collation) + return false; + + return true; +} + +std::string Field::toString(const std::string& indent, const std::string& sep) const +{ + std::string str = indent + escapeIdentifier(m_name) + sep + m_type; + if(m_notnull) + str += " " + m_notnull->toSql(); + if(m_defaultvalue) + str += " " + m_defaultvalue->toSql(); + if(m_check) + str += " " + m_check->toSql(); + if(m_unique) + str += " " + m_unique->toSql({}); + if(m_collation) + str += " " + m_collation->toSql(); + if(m_generated) + str += " " + m_generated->toSql(); + return str; +} + +bool Field::isText() const +{ + if(starts_with_ci(m_type, "character")) return true; + if(starts_with_ci(m_type, "varchar")) return true; + if(starts_with_ci(m_type, "varying character")) return true; + if(starts_with_ci(m_type, "nchar")) return true; + if(starts_with_ci(m_type, "native character")) return true; + if(starts_with_ci(m_type, "nvarchar")) return true; + if(compare_ci(m_type, "text")) return true; + if(compare_ci(m_type, "clob")) return true; + return false; +} + +bool Field::isInteger() const +{ + if(compare_ci(m_type, "int")) return true; + if(compare_ci(m_type, "integer")) return true; + if(compare_ci(m_type, "tinyint")) return true; + if(compare_ci(m_type, "smallint")) return true; + if(compare_ci(m_type, "mediumint")) return true; + if(compare_ci(m_type, "bigint")) return true; + if(compare_ci(m_type, "unsigned big int")) return true; + if(compare_ci(m_type, "int2")) return true; + if(compare_ci(m_type, "int8")) return true; + return false; +} + +bool Field::isReal() const +{ + if(compare_ci(m_type, "real")) return true; + if(compare_ci(m_type, "double")) return true; + if(compare_ci(m_type, "double precision")) return true; + if(compare_ci(m_type, "float")) return true; + return false; +} + +bool Field::isNumeric() const +{ + if(starts_with_ci(m_type, "decimal")) return true; + if(compare_ci(m_type, "numeric")) return true; + if(compare_ci(m_type, "boolean")) return true; + if(compare_ci(m_type, "date")) return true; + if(compare_ci(m_type, "datetime")) return true; + return false; +} + +bool Field::isBlob() const +{ + if(m_type.empty()) return true; + if(compare_ci(m_type, "blob")) return true; + return false; +} + +Field::Affinity Field::affinity() const +{ + if (isInteger()) return IntegerAffinity; + + if (isText()) return TextAffinity; + + if (isBlob()) return BlobAffinity; + + if (isReal() || isNumeric()) return FloatAffinity; + + return BlobAffinity; +} + +Table::Table(const Table& table) + : Object(table.name()) +{ + *this = table; +} + +Table& Table::operator=(const Table& rhs) +{ + // Base class + Object::operator=(rhs); + + // Just assign the simple values + m_options = rhs.m_options; + m_virtual = rhs.m_virtual; + + // Clear the fields and the constraints first in order to avoid duplicates and/or old data in the next step + fields.clear(); + m_indexConstraints.clear(); + m_foreignKeys.clear(); + m_checkConstraints.clear(); + + // Make copies of the fields and the constraints. This is necessary in order to avoid any unwanted changes to the application's main database + // schema representation just by modifying a reference to the fields or constraints and thinking it operates on a copy. + std::copy(rhs.fields.begin(), rhs.fields.end(), std::back_inserter(fields)); + for(const auto& e : rhs.m_indexConstraints) + { + if(e.second->isPrimaryKey()) + m_indexConstraints.insert(std::make_pair(e.first, std::make_shared(*std::dynamic_pointer_cast(e.second)))); + else + m_indexConstraints.insert(std::make_pair(e.first, std::make_shared(*e.second))); + } + for(const auto& e : rhs.m_foreignKeys) + m_foreignKeys.insert(std::make_pair(e.first, std::make_shared(*e.second))); + std::transform(rhs.m_checkConstraints.begin(), rhs.m_checkConstraints.end(), std::back_inserter(m_checkConstraints), [](const auto& e) { return std::make_shared(*e); }); + + return *this; +} + +bool Table::operator==(const Table& rhs) const +{ + if(!Object::operator==(rhs)) + return false; + + if(m_options != rhs.m_options) + return false; + if(m_virtual != rhs.m_virtual) + return false; + if(fields != rhs.fields) + return false; + if(m_indexConstraints != rhs.m_indexConstraints) + return false; + if(m_foreignKeys != rhs.m_foreignKeys) + return false; + if(m_checkConstraints != rhs.m_checkConstraints) + return false; + + return true; +} + +StringVector Table::fieldList() const +{ + StringVector sl; + std::transform(fields.begin(), fields.end(), std::back_inserter(sl), [](const auto& f) { return f.toString(); }); + return sl; +} + +StringVector Table::fieldNames() const +{ + StringVector sl; + std::transform(fields.begin(), fields.end(), std::back_inserter(sl), [](const auto& f) { return f.name(); }); + return sl; +} + +StringVector Table::rowidColumns() const +{ + // For WITHOUT ROWID tables this function returns the names of the primary key column. For ordinary tables with a rowid column, it returns "_rowid_" + if(withoutRowidTable()) + { + auto columns = primaryKeyColumns(); + StringVector result; + std::transform(columns.begin(), columns.end(), std::back_inserter(result), [](const auto& e) { return e.name(); }); + return result; + } else + return {"_rowid_"}; +} + +TablePtr Table::parseSQL(const std::string& sSQL) +{ + parser::ParserDriver drv; + if(!drv.parse(sSQL)) + { + TablePtr t = std::dynamic_pointer_cast(drv.result); + t->setOriginalSql(sSQL); + return t; + } else { + std::cerr << "Sqlite parse error: " << sSQL << std::endl; + TablePtr t = std::make_shared
(""); + t->setOriginalSql(sSQL); + return t; + } +} + +std::string Table::sql(const std::string& schema, bool ifNotExists) const +{ + // Special handling for virtual tables: just build an easy create statement and copy the using part in there + if(isVirtual()) + return "CREATE VIRTUAL TABLE " + ObjectIdentifier(schema, m_name).toString(true) + " USING " + m_virtual + ";"; + + // This is a normal table, not a virtual one + std::string sql = "CREATE TABLE "; + if(ifNotExists) + sql += "IF NOT EXISTS "; + sql += ObjectIdentifier(schema, m_name).toString(true); + sql += " (\n"; + + sql += joinStringVector(fieldList(), ",\n"); + + // Constraints + for(const auto& it : m_indexConstraints) + sql += ",\n\t" + it.second->toSql(it.first); + for(const auto& it : m_foreignKeys) + sql += ",\n\t" + it.second->toSql(it.first); + for(const auto& it : m_checkConstraints) + sql += ",\n\t" + it->toSql(); + + sql += "\n)"; + + // Table options + bool first_option = true; + for(size_t i=0;i constraint) +{ + IndexedColumnVector c; + std::transform(columns.begin(), columns.end(), std::back_inserter(c), [](const auto& e) { return IndexedColumn(e, false); }); + m_indexConstraints.insert(std::make_pair(c, constraint)); +} + +void Table::addConstraint(const StringVector& columns, std::shared_ptr constraint) +{ + IndexedColumnVector c; + std::transform(columns.begin(), columns.end(), std::back_inserter(c), [](const auto& e) { return IndexedColumn(e, false); }); + m_indexConstraints.insert(std::make_pair(c, constraint)); +} + +void Table::addConstraint(const IndexedColumnVector& columns, std::shared_ptr constraint) +{ + StringVector c; + std::transform(columns.begin(), columns.end(), std::back_inserter(c), [](const auto& e) { return e.name(); }); + m_foreignKeys.insert(std::make_pair(c, constraint)); +} + +void Table::removeConstraint(std::shared_ptr constraint) +{ + auto c = std::find_if(m_indexConstraints.begin(), m_indexConstraints.end(), [constraint](const auto& e) { return e.second == constraint; }); + if(c != m_indexConstraints.end()) + m_indexConstraints.erase(c); +} + +void Table::removeConstraint(std::shared_ptr constraint) +{ + auto c = std::find_if(m_foreignKeys.begin(), m_foreignKeys.end(), [constraint](const auto& e) { return e.second == constraint; }); + if(c != m_foreignKeys.end()) + m_foreignKeys.erase(c); +} + +void Table::removeConstraint(std::shared_ptr constraint) +{ + m_checkConstraints.erase(std::remove_if(m_checkConstraints.begin(), m_checkConstraints.end(), [constraint](const auto& e) { return e == constraint; })); +} + +void Table::addKeyToConstraint(std::shared_ptr constraint, const std::string& key) +{ + // Search for matching constraint + for(auto it=m_indexConstraints.begin();it!=m_indexConstraints.end();) + { + if(it->second == constraint) + { + // Add key to the column list + auto new_columns = it->first; + new_columns.emplace_back(key, false); + + m_indexConstraints.insert(std::make_pair(new_columns, it->second)); + it = m_indexConstraints.erase(it); + } + else + { + ++it; + } + } +} + +void Table::removeKeyFromConstraint(std::shared_ptr constraint, const std::string& key) +{ + for(auto it=m_indexConstraints.begin();it!=m_indexConstraints.end();) + { + if(it->second == constraint) + { + // Remove key from the column list + std::remove_const_tfirst)> new_columns; + std::copy_if(it->first.begin(), it->first.end(), std::back_inserter(new_columns), [key](const auto& c) { return c != key; }); + + // If the column list is empty now, remove the entire constraint. Otherwise save the updated column list + if(new_columns.empty()) + { + it = m_indexConstraints.erase(it); + } else { + m_indexConstraints.insert(std::make_pair(new_columns, it->second)); + it = m_indexConstraints.erase(it); + } + } else { + ++it; + } + } +} + +void Table::removeKeyFromAllConstraints(const std::string& key) +{ + auto match_and_remove = [key](auto& container, auto& it) { + // Check if they contain the old key name + if(contains(it->first, key)) + { + // If so, remove it from the column list + std::remove_const_tfirst)> new_columns; + std::copy_if(it->first.begin(), it->first.end(), std::back_inserter(new_columns), [key](const auto& c) { return c != key; }); + + // If the column list is empty now, remove the entire constraint. Otherwise save the updated column list + if(new_columns.empty()) + { + it = container.erase(it); + } else { + container.insert(std::make_pair(new_columns, it->second)); + it = container.erase(it); + } + } else { + ++it; + } + }; + + for(auto it=m_indexConstraints.begin();it!=m_indexConstraints.end();) + match_and_remove(m_indexConstraints, it); + + for(auto it=m_foreignKeys.begin();it!=m_foreignKeys.end();) + match_and_remove(m_foreignKeys, it); +} + +void Table::renameKeyInAllConstraints(const std::string& key, const std::string& to) +{ + // Do nothing if the key hasn't really changed + if(key == to) + return; + + const auto match_and_rename = [key, to](auto& container, auto& it, const auto& rename) { + // Check if they contain the old key name + if(contains(it->first, key)) + { + // If so, update it in the column list + std::remove_const_tfirst)> new_columns; + std::transform(it->first.begin(), it->first.end(), std::back_inserter(new_columns), [rename](auto c) { + return rename(c); + }); + + container.insert(std::make_pair(new_columns, it->second)); + it = container.erase(it); + } + else + { + ++it; + } + }; + + // Update all constraints + for(auto it=m_indexConstraints.begin();it!=m_indexConstraints.end();) + { + match_and_rename(m_indexConstraints, it, [key, to](IndexedColumn c) { + if(c == key) + c.setName(to); + return c; + }); + } + + for(auto it=m_foreignKeys.begin();it!=m_foreignKeys.end();++it) + match_and_rename(m_foreignKeys, it, [key, to](const std::string& c) { return c == key ? to : c; }); +} + +std::shared_ptr Table::primaryKey() const +{ + const auto it = std::find_if(m_indexConstraints.begin(), m_indexConstraints.end(), [](const auto& e) { return e.second->isPrimaryKey(); }); + if(it != m_indexConstraints.end()) + return std::dynamic_pointer_cast(it->second); + return nullptr; +} + +IndexedColumnVector Table::primaryKeyColumns() const +{ + const auto it = std::find_if(m_indexConstraints.begin(), m_indexConstraints.end(), [](const auto& e) { return e.second->isPrimaryKey(); }); + if(it != m_indexConstraints.end()) + return it->first; + return {}; +} + +std::shared_ptr Table::foreignKey(const StringVector& columns) const +{ + const auto it = std::find_if(m_foreignKeys.begin(), m_foreignKeys.end(), [columns](const auto& e) { return e.first == columns; }); + if(it != m_foreignKeys.end()) + return it->second; + return nullptr; +} + + +std::string IndexedColumn::toString(const std::string& indent, const std::string& sep) const +{ + std::string name = m_isExpression ? m_name : escapeIdentifier(m_name); + std::string order = (m_order.empty() ? "" : (sep + m_order)); + return indent + name + order; +} + +Index& Index::operator=(const Index& rhs) +{ + // Base class + Object::operator=(rhs); + + // Just assign the easy stuff + m_unique = rhs.m_unique; + m_table = rhs.m_table; + m_whereExpr = rhs.m_whereExpr; + + // Make copies of the column + std::copy(rhs.fields.begin(), rhs.fields.end(), std::back_inserter(fields)); + + return *this; +} + +StringVector Index::columnSqlList() const +{ + StringVector sl; + std::transform(fields.begin(), fields.end(), std::back_inserter(sl), [](const auto& c) { return c.toString(); }); + return sl; +} + +std::string Index::sql(const std::string& schema, bool ifNotExists) const +{ + // Start CREATE (UNIQUE) INDEX statement + std::string sql; + if(m_unique) + sql = "CREATE UNIQUE INDEX "; + else + sql = "CREATE INDEX "; + if(ifNotExists) + sql += "IF NOT EXISTS "; + sql += ObjectIdentifier(schema, m_name).toString(true); + sql += " ON "; + sql += sqlb::escapeIdentifier(m_table); + sql += " (\n"; + + // Add column list + sql += joinStringVector(columnSqlList(), ",\n"); + + // Add partial index bit + sql += "\n)"; + if(!m_whereExpr.empty()) + sql += " WHERE " + m_whereExpr; + + return sql + ";"; +} + +IndexPtr Index::parseSQL(const std::string& sSQL) +{ + parser::ParserDriver drv; + if(!drv.parse(sSQL)) + { + IndexPtr i = std::dynamic_pointer_cast(drv.result); + i->setOriginalSql(sSQL); + return i; + } else { + std::cerr << "Sqlite parse error: " << sSQL << std::endl; + IndexPtr i = std::make_shared(""); + i->setOriginalSql(sSQL); + return i; + } +} + +template<> +std::string getBaseTable(IndexPtr object) +{ + return object->table(); +} + + + +ViewPtr View::parseSQL(const std::string& sSQL) +{ + // TODO + + auto v = std::make_shared(""); + v->setOriginalSql(sSQL); + return v; +} + + +TriggerPtr Trigger::parseSQL(const std::string& sSQL) +{ + // TODO + + auto t = std::make_shared(""); + t->setOriginalSql(sSQL); + return t; +} + +template<> +std::string getBaseTable(TriggerPtr object) +{ + return object->table(); +} + +} //namespace sqlb diff --git a/src/sql/sqlitetypes.h b/src/sql/sqlitetypes.h new file mode 100644 index 000000000..4835f89d4 --- /dev/null +++ b/src/sql/sqlitetypes.h @@ -0,0 +1,636 @@ +#pragma once +#ifndef SQLITETYPES_H +#define SQLITETYPES_H + +#include +#include +#include +#include +#include +#include +#include +#include + +template +bool contains(const C& container, E element) +{ + return std::find(container.begin(), container.end(), element) != container.end(); +} + +template +bool contains(const std::map& container, E element) +{ + return container.find(element) != container.end(); +} + +template +bool compare_ci(const T& a, const T& b) +{ + // Note: This function does not have to be (actually it must not be) fully UTF-8 aware because SQLite itself is not either. + + return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](unsigned char c1, unsigned char c2) { + return std::tolower(c1) == std::tolower(c2); + }); +} + +template +bool compare_ci(const T& a, const char* b) +{ + return compare_ci(a, std::string(b)); +} + +inline bool starts_with_ci(const std::string& str, const std::string& with) +{ + if(str.size() < with.size()) + return false; + else + return compare_ci(str.substr(0, with.size()), with); +} + +namespace sqlb { + +using StringVector = std::vector; + +class Object; +class Table; +class Index; +class View; +class Trigger; +class Field; +class Constraint; +class IndexedColumn; +using ObjectPtr = std::shared_ptr; +using TablePtr = std::shared_ptr
; +using IndexPtr = std::shared_ptr; +using ViewPtr = std::shared_ptr; +using TriggerPtr = std::shared_ptr; +using FieldVector = std::vector; +using IndexedColumnVector = std::vector; + +StringVector escapeIdentifier(StringVector ids); +std::string joinStringVector(const StringVector& vec, const std::string& delim); +std::string joinStringVector(const IndexedColumnVector& vec, const std::string& delim); + +class Object +{ +public: + explicit Object(const std::string& name): m_name(name), m_fullyParsed(false) {} + virtual ~Object() = default; + + bool operator==(const Object& rhs) const; + + void setName(const std::string& name) { m_name = name; } + const std::string& name() const { return m_name; } + + void setOriginalSql(const std::string& original_sql) { m_originalSql = original_sql; } + std::string originalSql() const { return m_originalSql; } + + void setFullyParsed(bool fully_parsed) { m_fullyParsed = fully_parsed; } + bool fullyParsed() const { return m_fullyParsed; } + + /** + * @brief Returns the CREATE statement for this object + * @param schema The schema name of the object + * @param ifNotExists If set to true the "IF NOT EXISTS" qualifier will be added to the create statement + * @return A std::string with the CREATE statement. + */ + virtual std::string sql(const std::string& schema = std::string("main"), bool ifNotExists = false) const = 0; + +protected: + std::string m_name; + std::string m_originalSql; + bool m_fullyParsed; +}; + +class Constraint +{ +public: + void setName(const std::string& name) { m_name = name; } + const std::string& name() const { return m_name; } + +protected: + std::string m_name; +}; + +class ForeignKeyClause : public Constraint +{ +public: + explicit ForeignKeyClause(const std::string& table = std::string(), const StringVector& columns = {}, const std::string& constraint = std::string()) + : m_table(table), + m_columns(columns), + m_constraint(constraint) + { + } + + std::string toString() const; + + void setTable(const std::string& table) { m_table = table; } + const std::string& table() const { return m_table; } + + void setColumns(const StringVector& columns) { m_columns = columns; } + const StringVector& columns() const { return m_columns; } + + void setConstraint(const std::string& constraint) { m_constraint = constraint; } + const std::string& constraint() const { return m_constraint; } + + std::string toSql(const StringVector& columns) const; + +private: + std::string m_table; + StringVector m_columns; + std::string m_constraint; +}; + +class UniqueConstraint : public Constraint +{ +public: + virtual ~UniqueConstraint() = default; + + void setConflictAction(const std::string& conflict) { m_conflictAction = conflict; } + const std::string& conflictAction() const { return m_conflictAction; } + + virtual std::string toSql(const IndexedColumnVector& columns) const; + + virtual bool isPrimaryKey() const { return false; } + +protected: + std::string m_conflictAction; +}; + + +class NotNullConstraint : public Constraint +{ +public: + void setConflictAction(const std::string& conflict) { m_conflictAction = conflict; } + const std::string& conflictAction() const { return m_conflictAction; } + + std::string toSql() const; + +protected: + std::string m_conflictAction; +}; + + +class PrimaryKeyConstraint : public UniqueConstraint +{ + // Primary keys are a sort of unique constraint for us. This matches quite nicely as both can have a conflict action + // and both need to maintain a copy of the column list with sort order information etc. + +public: + PrimaryKeyConstraint() + : m_auto_increment(false) + {} + + void setAutoIncrement(bool ai) { m_auto_increment = ai; } + bool autoIncrement() const { return m_auto_increment; } + + bool isPrimaryKey() const override { return true; } + std::string toSql(const IndexedColumnVector& columns) const override; + +private: + bool m_auto_increment; +}; + +class CheckConstraint : public Constraint +{ +public: + explicit CheckConstraint(const std::string& expr = std::string()) + : m_expression(expr) + { + } + + void setExpression(const std::string& expr) { m_expression = expr; } + const std::string& expression() const { return m_expression; } + + std::string toSql() const; + +private: + std::string m_expression; +}; + +class DefaultConstraint : public Constraint +{ +public: + explicit DefaultConstraint(const std::string& value = std::string()) + : m_value(value) + { + } + + void setValue(const std::string& value) { m_value = value; } + const std::string& value() const { return m_value; } + + std::string toSql() const; + +private: + std::string m_value; +}; + +class CollateConstraint : public Constraint +{ +public: + explicit CollateConstraint(const std::string& collation) + : m_collation(collation) + { + } + + void setCollation(const std::string& collation) { m_collation = collation; } + const std::string& collation() const { return m_collation; } + + std::string toSql() const; + +private: + std::string m_collation; +}; + +class GeneratedColumnConstraint : public Constraint +{ +public: + explicit GeneratedColumnConstraint(const std::string& expr = std::string(), const std::string& storage = "VIRTUAL") + : m_expression(expr), + m_storage(storage) + { + } + + void setExpression(const std::string& expr) { m_expression = expr; } + const std::string& expression() const { return m_expression; } + + void setStorage(const std::string& storage) { m_storage = storage; } + std::string storage() const { return m_storage.empty() ? "VIRTUAL" : m_storage; } + + std::string toSql() const; + +private: + std::string m_expression; + std::string m_storage; +}; + +class Field +{ +public: + Field() + {} + + Field(const std::string& name, + const std::string& type, + bool notnull = false, + const std::string& defaultvalue = std::string(), + const std::string& check = std::string(), + bool unique = false, + const std::string& collation = std::string()) + : m_name(name) + , m_type(type) + , m_notnull(notnull ? std::make_shared() : nullptr) + , m_check(check.empty() ? nullptr : std::make_shared(check)) + , m_defaultvalue(defaultvalue.empty() ? nullptr : std::make_shared(defaultvalue)) + , m_unique(unique ? std::make_shared() : nullptr) + , m_collation(collation.empty() ? nullptr : std::make_shared(collation)) + {} + + bool operator==(const Field& rhs) const; + + std::string toString(const std::string& indent = "\t", const std::string& sep = "\t") const; + + void setName(const std::string& name) { m_name = name; } + void setType(const std::string& type) { m_type = type; } + void setNotNull(std::shared_ptr notnull) { m_notnull = notnull; } + void setNotNull(bool notnull = true) { if(notnull) m_notnull = std::make_shared(); else m_notnull.reset(); } + void setCheck(std::shared_ptr check) { m_check = check; } + void setCheck(const std::string& check) { if(!check.empty()) m_check = std::make_shared(check); else m_check.reset(); } + void setDefaultValue(std::shared_ptr defaultvalue) { m_defaultvalue = defaultvalue; } + void setDefaultValue(const std::string& value) { if(!value.empty()) m_defaultvalue = std::make_shared(value); else m_defaultvalue.reset(); } + void setUnique(std::shared_ptr u) { m_unique = u; } + void setUnique(bool u) { if(u) m_unique = std::make_shared(); else m_unique.reset(); } + void setCollation(std::shared_ptr c) { m_collation = c; } + void setCollation(const std::string& collation) { if(!collation.empty()) m_collation = std::make_shared(collation); else m_collation.reset(); } + + bool isText() const; + bool isInteger() const; + bool isBlob() const; + bool isReal() const; + bool isNumeric() const; + + // Type affinity of the column according to SQLite3 rules. + // The Affinity enum values match the SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_BLOB, and SQLITE_TEXT constants + enum Affinity + { + IntegerAffinity = 1, + FloatAffinity = 2, + TextAffinity = 3, + BlobAffinity = 4, + }; + Affinity affinity() const; + + const std::string& name() const { return m_name; } + const std::string& type() const { return m_type; } + bool notnull() const { return m_notnull ? true : false; } + std::string check() const { return m_check ? m_check->expression() : std::string{}; } + std::string defaultValue() const { return m_defaultvalue ? m_defaultvalue->value() : std::string{}; } + bool unique() const { return m_unique ? true : false; } + std::string collation() const { return m_collation ? m_collation->collation() : std::string{}; } + + const std::shared_ptr generated() const { return m_generated; } + std::shared_ptr generated() { return m_generated; } + void setGenerated(std::shared_ptr gen) { m_generated = gen; } + +private: + std::string m_name; + std::string m_type; + std::shared_ptr m_notnull; + std::shared_ptr m_check; + std::shared_ptr m_defaultvalue; + std::shared_ptr m_unique; + std::shared_ptr m_collation; + std::shared_ptr m_generated; +}; + +class Table : public Object +{ +public: + explicit Table(const std::string& name): Object(name) {} + explicit Table(const Table& table); + Table& operator=(const Table& rhs); + + bool operator==(const Table& rhs) const; + + virtual bool isView() const { return false; } + + FieldVector fields; + using field_type = Field; + using field_iterator = FieldVector::iterator; + + enum Options + { + WithoutRowid, + Strict, + + NumOptions + }; + + /** + * @brief Returns the CREATE TABLE statement for this table object + * @return A std::string with the CREATE TABLE object. + */ + std::string sql(const std::string& schema = "main", bool ifNotExists = false) const override; + + StringVector fieldNames() const; + + StringVector rowidColumns() const; + void setWithoutRowidTable(bool without_rowid) { m_options.set(WithoutRowid, without_rowid); } + bool withoutRowidTable() const { return m_options.test(WithoutRowid); } + + void setStrict(bool strict) { m_options.set(Strict, strict); } + bool isStrict() const { return m_options.test(Strict); } + + void setVirtualUsing(const std::string& virt_using) { m_virtual = virt_using; } + const std::string& virtualUsing() const { return m_virtual; } + bool isVirtual() const { return !m_virtual.empty(); } + + void addConstraint(const IndexedColumnVector& columns, std::shared_ptr constraint) { m_indexConstraints.insert(std::make_pair(columns, constraint)); } + void addConstraint(const IndexedColumnVector& columns, std::shared_ptr constraint) { m_indexConstraints.insert(std::make_pair(columns, constraint)); } + void addConstraint(const StringVector& columns, std::shared_ptr constraint) { m_foreignKeys.insert(std::make_pair(columns, constraint)); } + void addConstraint(std::shared_ptr constraint) { m_checkConstraints.push_back(constraint); } + void removeConstraint(std::shared_ptr constraint); + void removeConstraint(std::shared_ptr constraint); + void removeConstraint(std::shared_ptr constraint); + void addKeyToConstraint(std::shared_ptr constraint, const std::string& key); + void removeKeyFromConstraint(std::shared_ptr constraint, const std::string& key); + void removeKeyFromAllConstraints(const std::string& key); + void renameKeyInAllConstraints(const std::string& key, const std::string& to); + + // These three functions are helper functions which we need for some templated code. As soon as we + // switch to C++17 we should be able to rewrite that code so we can get rid of these. + void addConstraint(const StringVector& columns, std::shared_ptr constraint); + void addConstraint(const StringVector& columns, std::shared_ptr constraint); + void addConstraint(const IndexedColumnVector& columns, std::shared_ptr constraint); + + std::shared_ptr primaryKey() const; + IndexedColumnVector primaryKeyColumns() const; + std::multimap> indexConstraints() const { return m_indexConstraints; } + std::multimap> foreignKeys() const { return m_foreignKeys; } + std::shared_ptr foreignKey(const StringVector& columns) const; //! Only returns the first foreign key, if any + std::vector> checkConstraints() const { return m_checkConstraints; } + + /** + * @brief parseSQL Parses the create Table statement in sSQL. + * @param sSQL The create table statement. + * @return The table object. The table object may be empty if parsing failed. + */ + static TablePtr parseSQL(const std::string& sSQL); + +private: + StringVector fieldList() const; + +private: + std::multimap> m_indexConstraints; // This stores both UNIQUE and PRIMARY KEY constraints + std::multimap> m_foreignKeys; + std::vector> m_checkConstraints; + std::string m_virtual; + std::bitset m_options; +}; + +class IndexedColumn +{ +public: + IndexedColumn() + : m_isExpression(false) + { + } + + IndexedColumn(const std::string& name, bool expr, const std::string& order = std::string()) + : m_name(name), + m_isExpression(expr), + m_order(order) + { + } + + bool operator==(const std::string& name) const { return !m_isExpression && m_name == name; } + bool operator!=(const std::string& name) const { return !m_isExpression && m_name != name; } + bool operator==(const IndexedColumn& other) const { return m_name == other.m_name && m_isExpression == other.m_isExpression && m_order == other.m_order; } + bool operator<(const IndexedColumn& other) const { return m_name < other.m_name; } + + void setName(const std::string& name) { m_name = name; } + const std::string& name() const { return m_name; } + + void setExpression(bool expr) { m_isExpression = expr; } + bool expression() const { return m_isExpression; } + + void setOrder(const std::string& order) { m_order = order; } + std::string order() const { return m_order; } + + std::string toString(const std::string& indent = "\t", const std::string& sep = "\t") const; + +private: + std::string m_name; + bool m_isExpression; + std::string m_order; +}; + +class Index : public Object +{ +public: + explicit Index(const std::string& name): Object(name), m_unique(false) {} + Index& operator=(const Index& rhs); + + IndexedColumnVector fields; + using field_type = IndexedColumn; + using field_iterator = IndexedColumnVector::iterator; + + void setUnique(bool unique) { m_unique = unique; } + bool unique() const { return m_unique; } + + void setTable(const std::string& table) { m_table = table; } + const std::string& table() const { return m_table; } + + void setWhereExpr(const std::string& expr) { m_whereExpr = expr; } + const std::string& whereExpr() const { return m_whereExpr; } + + /** + * @brief Returns the CREATE INDEX statement for this index object + * @return A std::string with the CREATE INDEX object. + */ + std::string sql(const std::string& schema = "main", bool ifNotExists = false) const override; + + /** + * @brief parseSQL Parses the CREATE INDEX statement in sSQL. + * @param sSQL The create index statement. + * @return The index object. The index object may be empty if the parsing failed. + */ + static IndexPtr parseSQL(const std::string& sSQL); + +private: + StringVector columnSqlList() const; + + bool m_unique; + std::string m_table; + std::string m_whereExpr; +}; + +class View : public Table +{ +public: + explicit View(const std::string& name): Table(name) {} + + virtual bool isView() const override { return true; } + + std::string sql(const std::string& /*schema*/ = "main", bool /*ifNotExists*/ = false) const override + { /* TODO */ return m_originalSql; } + + static ViewPtr parseSQL(const std::string& sSQL); +}; + +class Trigger : public Object +{ +public: + explicit Trigger(const std::string& name): Object(name) {} + + std::string sql(const std::string& /*schema*/ = "main", bool /*ifNotExists*/ = false) const override + { /* TODO */ return m_originalSql; } + + static TriggerPtr parseSQL(const std::string& sSQL); + + void setTable(const std::string& table) { m_table = table; } + std::string table() const { return m_table; } + +private: + std::string m_table; +}; + +/** + * @brief Return the name of the base table of the given object. For indices and triggers that is the table which the object is related to. + */ + +template +std::string getBaseTable(std::shared_ptr /*object*/) +{ + return std::string{}; +} + +template<> +std::string getBaseTable(IndexPtr object); + +template<> +std::string getBaseTable(TriggerPtr object); + +/** + * @brief findField Finds a field in the database object and returns an iterator to it. + * @param object + * @param name + * @return The iterator pointing to the field in the field container of the object if the field was found. + * object.fields.end() if the field couldn't be found. + */ +template +typename T::field_iterator findField(T* object, const std::string& name) +{ + return std::find_if(object->fields.begin(), object->fields.end(), [&name](const typename T::field_type& f) { + return compare_ci(name, f.name()); + }); +} +template +typename T::field_iterator findField(const T* object, const std::string& name) +{ + return findField(const_cast(object), name); +} +template +typename std::remove_reference::type::field_iterator findField(std::shared_ptr object, const std::string& name) +{ + return findField(object.get(), name); +} +template +typename std::remove_reference::type::field_iterator findField(T& object, const std::string& name) +{ + return findField(&object, name); +} + +template struct is_shared_ptr : std::false_type {}; +template struct is_shared_ptr> : std::true_type {}; + +/** + * @brief removeField Finds and removes a field in the database object + * @param object + * @param name + * @return true if sucessful, otherwise false + */ +template +bool removeField(T* object, const std::string& name) +{ + auto index = findField(object, name); + if(index != object->fields.end()) + { + object->fields.erase(index); + return true; + } + return false; +} +template::value>::type> +bool removeField(T object, const std::string& name) +{ + return removeField(object.get(), name); +} +template::value>::type> +bool removeField(T& object, const std::string& name) +{ + return removeField(&object, name); +} + +/** + * @brief getFieldNumber returns the number of the field with the given name in an object. This is supposed to be a temporary helper function only. + * @param object + * @param name + * @return number of the field + * + * TODO Remove this function. Whereever it is used we make the assumption that the queried columns are exactly equal to the columns of the table or view. + * For more complex queries this is not true and in fact it already is a dubious assumption because we also select the rowid column. + */ +inline size_t getFieldNumber(TablePtr object, const std::string& name) +{ + for(size_t i=0;ifields.size();i++) + { + if(object->fields[i].name() == name) + return i; + } + return 0; +} + +} //namespace sqlb + +#endif diff --git a/src/sqlite.h b/src/sqlite.h index 4f7b02096..f6a9b3b99 100644 --- a/src/sqlite.h +++ b/src/sqlite.h @@ -3,10 +3,23 @@ #ifdef ENABLE_SQLCIPHER #define SQLITE_TEMP_STORE 2 - #define SQLITE_HAS_CODEC - #include + #ifndef SQLITE_HAS_CODEC + #define SQLITE_HAS_CODEC + #endif + #ifdef Q_OS_WIN32 + #include + #else + #include + #endif #else #include #endif +// For older versions of the SQLite library which do not have the SQLITE_DETERMINISTIC flag +// yet (which introduced in this commit: https://www.sqlite.org/src/info/5716fc2341ddd8cf), we +// define it here with a value of 0. Because it is ORed with other constants a value of 0 is a no-op. +#ifndef SQLITE_DETERMINISTIC + #define SQLITE_DETERMINISTIC 0 +#endif + #endif diff --git a/src/sqlitedb.cpp b/src/sqlitedb.cpp index 53d421d40..3a26e6199 100644 --- a/src/sqlitedb.cpp +++ b/src/sqlitedb.cpp @@ -2,80 +2,207 @@ #include "sqlite.h" #include "sqlitetablemodel.h" #include "CipherDialog.h" +#include "CipherSettings.h" +#include "Settings.h" +#include "Data.h" #include #include #include #include -#include -#include #include #include #include +#include +#include +#include -// collation callbacks -int collCompare(void* /*pArg*/, int /*eTextRepA*/, const void* sA, int /*eTextRepB*/, const void* sB) +#include +#include +#include +#include +#include +#include +#include + +namespace { + +bool equalsIgnoreCase(const std::string& lhs, const std::string& rhs) +{ + if(lhs.size() != rhs.size()) + return false; + + return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), [](unsigned char a, unsigned char b) { + return std::tolower(a) == std::tolower(b); + }); +} + +template +typename MapType::const_iterator findCaseInsensitive(const MapType& map, const std::string& key) +{ + auto it = map.find(key); + if(it != map.end()) + return it; + + return std::find_if(map.begin(), map.end(), [&key](const auto& entry) { + return equalsIgnoreCase(entry.first, key); + }); +} + +} + +const QStringList DBBrowserDB::journalModeValues = {"DELETE", "TRUNCATE", "PERSIST", "MEMORY", "WAL", "OFF"}; +const QStringList DBBrowserDB::lockingModeValues = {"NORMAL", "EXCLUSIVE"}; + +QStringList DBBrowserDB::Datatypes = {"INTEGER", "TEXT", "BLOB", "REAL", "NUMERIC"}; +QStringList DBBrowserDB::DatatypesStrict = {"INT", "INTEGER", "TEXT", "BLOB", "REAL", "ANY"}; + +// Helper template to allow turning member functions into a C-style function pointer +// See https://stackoverflow.com/questions/19808054/convert-c-function-pointer-to-c-function-pointer/19809787 +template +struct Callback; +template +struct Callback { + template + static Ret callback(Args... args) { return func(args...); } + static std::function func; +}; +template +std::function Callback::func; + +namespace sqlb { +QString escapeIdentifier(const QString& id) { - size_t sizeA = strlen((const char*)sA); - size_t sizeB = strlen((const char*)sB); + return QString::fromStdString(escapeIdentifier(id.toStdString())); +} +QString escapeString(const QString& literal) +{ + return QString::fromStdString(escapeString(literal.toStdString())); +} +QString escapeByteArray(const QByteArray& literal) +{ + if(isTextOnly(literal)) + return sqlb::escapeString(literal); + else + return QString("X'%1'").arg(QString(literal.toHex())); +}} +// collation callbacks +int collCompare(void* /*pArg*/, int sizeA, const void* sA, int sizeB, const void* sB) +{ if(sizeA == sizeB) - return memcmp(sA, sB, sizeA); + return memcmp(sA, sB, static_cast(sizeA)); return sizeA - sizeB; } static int sqlite_compare_utf16( void* /*arg*/,int size1, const void *str1, int size2, const void* str2) { - const QString string1 = QString::fromRawData(reinterpret_cast(str1), size1 / sizeof(QChar)); - const QString string2 = QString::fromRawData(reinterpret_cast(str2), size2 / sizeof(QChar)); + const QString string1 = QString::fromRawData(reinterpret_cast(str1), static_cast(static_cast(size1) / sizeof(QChar))); + const QString string2 = QString::fromRawData(reinterpret_cast(str2), static_cast(static_cast(size2) / sizeof(QChar))); return QString::compare(string1, string2, Qt::CaseSensitive); } static int sqlite_compare_utf16ci( void* /*arg*/,int size1, const void *str1, int size2, const void* str2) { - const QString string1 = QString::fromRawData(reinterpret_cast(str1), size1 / sizeof(QChar)); - const QString string2 = QString::fromRawData(reinterpret_cast(str2), size2 / sizeof(QChar)); + const QString string1 = QString::fromRawData(reinterpret_cast(str1), static_cast(static_cast(size1) / sizeof(QChar))); + const QString string2 = QString::fromRawData(reinterpret_cast(str2), static_cast(static_cast(size2) / sizeof(QChar))); return QString::compare(string1, string2, Qt::CaseInsensitive); } -void collation_needed(void* /*pData*/, sqlite3* db, int eTextRep, const char* sCollationName) +static void sqlite_make_single_value(sqlite3_context* ctx, int num_arguments, sqlite3_value* arguments[]) +{ + QByteArray output; + for(int i=0;i(sqlite3_value_text(arguments[i])); + + char* output_str = new char[static_cast(output.size()) + 1]; + std::strcpy(output_str, output); + + sqlite3_result_text(ctx, output_str, output.size(), [](void* ptr) { + char* cptr = static_cast(ptr); + delete cptr; + }); +} + +DBBrowserDB::DBBrowserDB() : + _db(nullptr), + db_used(false), + isEncrypted(false), + isReadOnly(false), + disableStructureUpdateChecks(false) +{ + // Register error log callback. This needs to be done before SQLite is first used + Callback::func = std::bind(&DBBrowserDB::errorLogCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + void (*log_callback)(void*, int, const char*) = static_cast(Callback::callback); + sqlite3_config(SQLITE_CONFIG_LOG, log_callback, nullptr); + + // Enable URI filenames + sqlite3_config(SQLITE_CONFIG_URI, 1); +} + +void DBBrowserDB::collationNeeded(void* /*pData*/, sqlite3* /*db*/, int eTextRep, const char* sCollationName) { - QMessageBox::StandardButton reply = QMessageBox::question( - 0, - QObject::tr("Collation needed! Proceed?"), - QObject::tr("A table in this database requires a special collation function '%1' " - "that this application can't provide without further knowledge.\n" - "If you choose to proceed, be aware bad things can happen to your database.\n" - "Create a backup!").arg(sCollationName), QMessageBox::Yes | QMessageBox::No); - if(reply == QMessageBox::Yes) - sqlite3_create_collation(db, sCollationName, eTextRep, NULL, collCompare); + QString name(sCollationName); + + // Don't request built-in collations. SQLite requests these collations even though they are built into + // the library. Since we have no need for overriding them, we just silently ignore these requests. + if(name.compare("BINARY", Qt::CaseInsensitive) && + name.compare("NOCASE", Qt::CaseInsensitive) && + name.compare("RTRIM", Qt::CaseInsensitive)) + { + emit requestCollation(name, eTextRep); + } } +void DBBrowserDB::errorLogCallback(void* /*user_data*/, int error_code, const char* message) +{ + QString msg = QString("(%1) %2").arg(error_code).arg(message); + + logSQL(msg, kLogMsg_ErrorLog); +} static void regexp(sqlite3_context* ctx, int /*argc*/, sqlite3_value* argv[]) { + // This is a cache for the last 50 regular expressions. Compiling them takes some time, so we want to cache the compiled + // regular expressions for performance purposes. + static std::array, 50> regex_cache; + + // Check if pattern is in cache + QString pattern{reinterpret_cast(sqlite3_value_text(argv[0]))}; + QRegularExpression regex; + const auto it = std::find_if(regex_cache.begin(), regex_cache.end(), [pattern](const std::pair& val) { + return val.first == pattern; + }); + if(it == regex_cache.end()) + { + // Pattern is not in cache. Create a new regular expressions object, compile it, and insert it into the cache + regex.setPattern(pattern); + regex.setPatternOptions(QRegularExpression::UseUnicodePropertiesOption); + if(!regex.isValid()) + return sqlite3_result_error(ctx, "invalid operand", -1); + regex.optimize(); + + static size_t regex_cache_size; + regex_cache_size = (regex_cache_size + 1) % regex_cache.size(); + regex_cache[regex_cache_size] = {pattern, regex}; + } else { + // Pattern is in the cache. Just retrieve it + regex = it->second; + } + // Get arguments and check their values - QRegExp arg1((const char*)sqlite3_value_text(argv[0])); - QString arg2((const char*)sqlite3_value_text(argv[1])); - if(!arg1.isValid()) - return sqlite3_result_error(ctx, "invalid operand", -1); - - // Set the pattern matching syntax to a Perl-like one. This is the default in Qt 4.x but Qt 5 - // changes this to a greedy one (QRegExp::RegExp2). To make sure the behaviour of our application - // doesn't change depending on the build environment, we make sure to always set the same pattern - // matching syntax. - arg1.setPatternSyntax(QRegExp::RegExp); - - // Perform the actual matching and return the result. Note that Qt's QRegExp returns -1 if the regex - // doesn't match and the position in the string otherwise; SQLite expects a 0 for not found and a 1 for found. - sqlite3_result_int(ctx, arg1.indexIn(arg2) >= 0); + QString arg2{reinterpret_cast(sqlite3_value_text(argv[1]))}; + + // Perform the actual matching and return the result. + // SQLite expects a 0 for not found and a 1 for found. + sqlite3_result_int(ctx, regex.match(arg2).hasMatch()); } bool DBBrowserDB::isOpen ( ) const { - return _db!=0; + return _db != nullptr; } bool DBBrowserDB::getDirty() const @@ -83,224 +210,438 @@ bool DBBrowserDB::getDirty() const return !savepointList.empty(); } -bool DBBrowserDB::open(const QString& db) +bool DBBrowserDB::open(const QString& db, bool readOnly) { if (isOpen()) close(); isEncrypted = false; + disableStructureUpdateChecks = false; // Get encryption settings for database file - CipherDialog* cipher = 0; - if(tryEncryptionSettings(db, &isEncrypted, cipher) == false) - { - lastErrorMessage = QString::fromUtf8((const char*)sqlite3_errmsg(_db)); + CipherSettings cipherSettings; + if(tryEncryptionSettings(db, &isEncrypted, &cipherSettings) == false) return false; - } // Open database file - if(sqlite3_open_v2(db.toUtf8(), &_db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) + if(sqlite3_open_v2(db.toUtf8(), &_db, readOnly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE, nullptr) != SQLITE_OK) { - lastErrorMessage = QString::fromUtf8((const char*)sqlite3_errmsg(_db)); + lastErrorMessage = QString::fromUtf8(sqlite3_errmsg(_db)); return false; } // Set encryption details if database is encrypted #ifdef ENABLE_SQLCIPHER - if(isEncrypted && cipher) + if(isEncrypted) { - sqlite3_key(_db, cipher->password().toUtf8(), cipher->password().toUtf8().length()); - if(cipher->pageSize() != 1024) - executeSQL(QString("PRAGMA cipher_page_size = %1;").arg(cipher->pageSize()), false, false); + executeSQL("PRAGMA key = " + cipherSettings.getPassword(), false, false); + executeSQL("PRAGMA cipher_page_size = " + std::to_string(cipherSettings.getPageSize()), false, false); + executeSQL("PRAGMA kdf_iter = " + std::to_string(cipherSettings.getKdfIterations()), false, false); + executeSQL("PRAGMA cipher_hmac_algorithm = " + cipherSettings.getHmacAlgorithm(), false, false); + executeSQL("PRAGMA cipher_kdf_algorithm = " + cipherSettings.getKdfAlgorithm(), false, false); + executeSQL("PRAGMA cipher_plaintext_header_size = " + std::to_string(cipherSettings.getPlaintextHeaderSize()), false, false); } #endif - delete cipher; if (_db) { // add UTF16 collation (comparison is performed by QString functions) - sqlite3_create_collation(_db, "UTF16", SQLITE_UTF16, 0, sqlite_compare_utf16); + sqlite3_create_collation(_db, "UTF16", SQLITE_UTF16, nullptr, sqlite_compare_utf16); // add UTF16CI (case insensitive) collation (comparison is performed by QString functions) - sqlite3_create_collation(_db, "UTF16CI", SQLITE_UTF16, 0, sqlite_compare_utf16ci); - + sqlite3_create_collation(_db, "UTF16CI", SQLITE_UTF16, nullptr, sqlite_compare_utf16ci); + // register collation callback - sqlite3_collation_needed(_db, NULL, collation_needed); + Callback::func = std::bind(&DBBrowserDB::collationNeeded, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); + void (*c_callback)(void*, sqlite3*, int, const char*) = static_cast(Callback::callback); + sqlite3_collation_needed(_db, nullptr, c_callback); - // set preference defaults - QSettings settings(QApplication::organizationName(), QApplication::organizationName()); - settings.sync(); - bool foreignkeys = settings.value( "/db/foreignkeys", false ).toBool(); + // Set foreign key settings as requested in the preferences + bool foreignkeys = Settings::getValue("db", "foreignkeys").toBool(); setPragma("foreign_keys", foreignkeys ? "1" : "0"); - // Enable extension loading - sqlite3_enable_load_extension(_db, 1); - // Register REGEXP function - if(settings.value("/extensions/disableregex", false) == false) - sqlite3_create_function(_db, "REGEXP", 2, SQLITE_UTF8, NULL, regexp, NULL, NULL); + if(Settings::getValue("extensions", "disableregex").toBool() == false) + sqlite3_create_function(_db, "REGEXP", 2, SQLITE_UTF8, nullptr, regexp, nullptr, nullptr); + + // Register our internal helper function for putting multiple values into a single column + sqlite3_create_function_v2( + _db, + "sqlb_make_single_value", + -1, + SQLITE_UTF8 | SQLITE_DETERMINISTIC, + nullptr, + sqlite_make_single_value, + nullptr, + nullptr, + nullptr + ); + + // Check if file is read only. In-memory databases are never read only + if(db == ":memory:") + { + isReadOnly = false; + } else { + QFileInfo fi(db); + QFileInfo fid(fi.absoluteDir().absolutePath()); + isReadOnly = readOnly || !fi.isWritable() || !fid.isWritable(); + } - // Check if file is read only - QFileInfo fi(db); - QFileInfo fid(fi.absoluteDir().absolutePath()); - isReadOnly = !fi.isWritable() || !fid.isWritable(); + // Load extensions + loadExtensionsFromSettings(); // Execute default SQL if(!isReadOnly) { - QString default_sql = settings.value( "/db/defaultsqltext", "").toString(); + QByteArray default_sql = Settings::getValue("db", "defaultsqltext").toByteArray(); if(!default_sql.isEmpty()) executeMultiSQL(default_sql, false, true); } curDBFilename = db; + + updateSchema(); + return true; } else { return false; } } -bool DBBrowserDB::attach(const QString& filename, QString attach_as) +/** + detaches a previously attached database identified with its alias-name +**/ +bool DBBrowserDB::detach(const std::string& attached_as) +{ + if(!_db) + { + return false; + } + + waitForDbRelease(); + + // detach database + if(!executeSQL("DETACH " + sqlb::escapeIdentifier(attached_as) + ";", false)) + { + QMessageBox::warning(nullptr, qApp->applicationName(), lastErrorMessage); + return false; + } + + + // Update schema to load database schema of the newly attached database + updateSchema(); + + return true; +} + + +bool DBBrowserDB::attach(const QString& filePath, QString attach_as) { + if(!_db) + return false; + + waitForDbRelease(); + + // In shared cache mode, attempting to attach the same database file more than once results in an error. + // So no need for a check if this file has already been attached and abort if this is the case + // Ask for name to be given to the attached database if none was provided if(attach_as.isEmpty()) - attach_as = QInputDialog::getText(0, + { + attach_as = QInputDialog::getText(nullptr, qApp->applicationName(), - tr("Please specify the database name under which you want to access the attached database") + tr("Please specify the database name under which you want to access the attached database"), + QLineEdit::Normal, + QFileInfo(filePath).baseName() ).trimmed(); - if(attach_as.isEmpty()) + } + if(attach_as.isNull()) return false; #ifdef ENABLE_SQLCIPHER // Try encryption settings - CipherDialog* cipher = 0; + CipherSettings cipherSettings; bool is_encrypted; - if(tryEncryptionSettings(filename, &is_encrypted, cipher) == false) + if(tryEncryptionSettings(filePath, &is_encrypted, &cipherSettings) == false) return false; // Attach database - QString key; - if(cipher) key = cipher->password(); - if(!executeSQL(QString("ATTACH '%1' AS %2 KEY '%3'").arg(filename).arg(sqlb::escapeIdentifier(attach_as)).arg(key), false)) - { - QMessageBox::warning(0, qApp->applicationName(), lastErrorMessage); - return false; - } - if(cipher && cipher->pageSize() != 1024) + std::string key; + if(is_encrypted) + key = "KEY " + cipherSettings.getPassword(); + else + key = "KEY ''"; + + // Only apply cipher settings if the database is encrypted + if(is_encrypted) { - if(!executeSQL(QString("PRAGMA %1.cipher_page_size = %2").arg(sqlb::escapeIdentifier(attach_as)).arg(cipher->pageSize()), false)) + if(!executeSQL("PRAGMA cipher_default_page_size = " + std::to_string(cipherSettings.getPageSize()), false)) + { + QMessageBox::warning(nullptr, qApp->applicationName(), lastErrorMessage); + return false; + } + if(!executeSQL("PRAGMA cipher_default_kdf_iter = " + std::to_string(cipherSettings.getKdfIterations()), false)) + { + QMessageBox::warning(nullptr, qApp->applicationName(), lastErrorMessage); + return false; + } + if(!executeSQL("PRAGMA cipher_hmac_algorithm = " + cipherSettings.getHmacAlgorithm(), false)) { - QMessageBox::warning(0, qApp->applicationName(), lastErrorMessage); + QMessageBox::warning(nullptr, qApp->applicationName(), lastErrorMessage); return false; } + if(!executeSQL("PRAGMA cipher_kdf_algorithm = " + cipherSettings.getKdfAlgorithm(), false)) + { + QMessageBox::warning(nullptr, qApp->applicationName(), lastErrorMessage); + return false; + } + if(!executeSQL("PRAGMA cipher_plaintext_header_size = " + std::to_string(cipherSettings.getPlaintextHeaderSize()), false)) + { + QMessageBox::warning(nullptr, qApp->applicationName(), lastErrorMessage); + return false; + } + } + + if(!executeSQL("ATTACH " + sqlb::escapeString(filePath.toStdString()) + " AS " + sqlb::escapeIdentifier(attach_as.toStdString()) + " " + key, false)) + { + QMessageBox::warning(nullptr, qApp->applicationName(), lastErrorMessage); + return false; } + + // Clean up cipher settings #else // Attach database - if(!executeSQL(QString("ATTACH '%1' AS %2").arg(filename).arg(sqlb::escapeIdentifier(attach_as)), false)) + if(!executeSQL("ATTACH " + sqlb::escapeString(filePath.toStdString()) + " AS " + sqlb::escapeIdentifier(attach_as.toStdString()), false)) { - QMessageBox::warning(0, qApp->applicationName(), lastErrorMessage); + QMessageBox::warning(nullptr, qApp->applicationName(), lastErrorMessage); return false; } #endif + // Update schema to load database schema of the newly attached database + updateSchema(); + return true; } -bool DBBrowserDB::tryEncryptionSettings(const QString& filename, bool* encrypted, CipherDialog*& cipherSettings) +bool DBBrowserDB::tryEncryptionSettings(const QString& filePath, bool* encrypted, CipherSettings* cipherSettings) const { + lastErrorMessage = tr("Invalid file format"); + // Open database file sqlite3* dbHandle; - if(sqlite3_open_v2(filename.toUtf8(), &dbHandle, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) + if(sqlite3_open_v2(filePath.toUtf8(), &dbHandle, SQLITE_OPEN_READONLY, nullptr) != SQLITE_OK) return false; // Try reading from database + +#ifdef ENABLE_SQLCIPHER + bool isDotenvChecked = false; + + // Determine default encryption settings depending on the SQLCipher version we use + QString sqlite_version, sqlcipher_version; + getSqliteVersion(sqlite_version, sqlcipher_version); + int enc_default_page_size, enc_default_kdf_iter; + int enc_default_plaintext_header_size = 0; + std::string enc_default_hmac_algorithm, enc_default_kdf_algorithm; + if(sqlcipher_version.startsWith('4')) + { + enc_default_page_size = 4096; + enc_default_kdf_iter = 256000; + enc_default_hmac_algorithm = "SHA512"; + enc_default_kdf_algorithm = "SHA512"; + } else { + enc_default_page_size = 1024; + enc_default_kdf_iter = 64000; + enc_default_hmac_algorithm = "SHA1"; + enc_default_kdf_algorithm = "SHA1"; + } +#endif + *encrypted = false; - cipherSettings = 0; while(true) { - QString statement = "SELECT COUNT(*) FROM sqlite_master;"; - QByteArray utf8Statement = statement.toUtf8(); + const std::string statement = "SELECT COUNT(*) FROM sqlite_master;"; sqlite3_stmt* vm; const char* tail; - sqlite3_prepare_v2(dbHandle, utf8Statement, utf8Statement.length(), &vm, &tail); + int err = sqlite3_prepare_v2(dbHandle, statement.c_str(), static_cast(statement.size()), &vm, &tail); + if(err == SQLITE_BUSY || err == SQLITE_PERM || err == SQLITE_NOMEM || err == SQLITE_IOERR || err == SQLITE_CORRUPT || err == SQLITE_CANTOPEN) + { + lastErrorMessage = QString::fromUtf8(sqlite3_errmsg(dbHandle)); + sqlite3_close_v2(dbHandle); + return false; + } + if(sqlite3_step(vm) != SQLITE_ROW) { sqlite3_finalize(vm); #ifdef ENABLE_SQLCIPHER - delete cipherSettings; - cipherSettings = new CipherDialog(0, false); - if(cipherSettings->exec()) - { - // Close and reopen database first to be in a clean state after the failed read attempt from above - sqlite3_close(dbHandle); - if(sqlite3_open_v2(filename.toUtf8(), &dbHandle, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) + bool foundDotenvPassword = false; + + // Being in a while loop, we don't want to check the same file multiple times + if (!isDotenvChecked) { + QFile databaseFile(filePath); + QFileInfo databaseFileInfo(databaseFile); + + QString databaseDirectoryPath = databaseFileInfo.dir().path(); + QString databaseFileName(databaseFileInfo.fileName()); + + QString dotenvFilePath = databaseDirectoryPath + "/.env"; + QSettings dotenv(dotenvFilePath, QSettings::IniFormat); + + QVariant passwordValue = dotenv.value(databaseFileName); + + foundDotenvPassword = !passwordValue.isNull(); + isDotenvChecked = true; + + if (foundDotenvPassword) { - delete cipherSettings; - cipherSettings = 0; - return false; + std::string password = passwordValue.toString().toStdString(); + + QVariant keyFormatValue = dotenv.value(databaseFileName + "_keyFormat", QVariant(CipherSettings::KeyFormats::Passphrase)); + CipherSettings::KeyFormats keyFormat = CipherSettings::getKeyFormat(keyFormatValue.toInt()); + + int pageSize = dotenv.value(databaseFileName + "_pageSize", enc_default_page_size).toInt(); + int kdfIterations = dotenv.value(databaseFileName + "_kdfIter", enc_default_kdf_iter).toInt(); + int plaintextHeaderSize = dotenv.value(databaseFileName + "_plaintextHeaderSize", enc_default_plaintext_header_size).toInt(); + std::string hmacAlgorithm = dotenv.value(databaseFileName + "_hmacAlgorithm", QString::fromStdString(enc_default_hmac_algorithm)).toString().toStdString(); + std::string kdfAlgorithm = dotenv.value(databaseFileName + "_kdfAlgorithm", QString::fromStdString(enc_default_kdf_algorithm)).toString().toStdString(); + + cipherSettings->setKeyFormat(keyFormat); + cipherSettings->setPassword(password); + cipherSettings->setPageSize(pageSize); + cipherSettings->setKdfIterations(kdfIterations); + cipherSettings->setHmacAlgorithm("HMAC_" + hmacAlgorithm); + cipherSettings->setKdfAlgorithm("PBKDF2_HMAC_" + kdfAlgorithm); + cipherSettings->setPlaintextHeaderSize(plaintextHeaderSize); } + } - // Set key and, if it differs from the default value, the page size - sqlite3_key(dbHandle, cipherSettings->password().toUtf8(), cipherSettings->password().toUtf8().length()); - if(cipherSettings->pageSize() != 1024) - sqlite3_exec(dbHandle, QString("PRAGMA cipher_page_size = %1;").arg(cipherSettings->pageSize()).toUtf8(), NULL, NULL, NULL); - - *encrypted = true; + if(foundDotenvPassword) + { + // Skip the CipherDialog prompt for now to test if the dotenv settings are correct } else { - sqlite3_close(dbHandle); - *encrypted = false; - delete cipherSettings; - cipherSettings = 0; + CipherDialog *cipherDialog = new CipherDialog(nullptr, false); + if(cipherDialog->exec()) + { + *cipherSettings = cipherDialog->getCipherSettings(); + } else { + sqlite3_close_v2(dbHandle); + *encrypted = false; + return false; + } + } + + // Close and reopen database first to be in a clean state after the failed read attempt from above + sqlite3_close_v2(dbHandle); + if(sqlite3_open_v2(filePath.toUtf8(), &dbHandle, SQLITE_OPEN_READONLY, nullptr) != SQLITE_OK) return false; - } + + // Set the key + sqlite3_exec(dbHandle, ("PRAGMA key = " + cipherSettings->getPassword()).c_str(), nullptr, nullptr, nullptr); + + // Set the settings if they differ from the default values + if(cipherSettings->getPageSize() != enc_default_page_size) + sqlite3_exec(dbHandle, ("PRAGMA cipher_page_size = " + std::to_string(cipherSettings->getPageSize())).c_str(), nullptr, nullptr, nullptr); + if(cipherSettings->getKdfIterations() != enc_default_kdf_iter) + sqlite3_exec(dbHandle, ("PRAGMA kdf_iter = " + std::to_string(cipherSettings->getKdfIterations())).c_str(), nullptr, nullptr, nullptr); + if(cipherSettings->getHmacAlgorithm() != enc_default_hmac_algorithm) + sqlite3_exec(dbHandle, ("PRAGMA cipher_hmac_algorithm = " + cipherSettings->getHmacAlgorithm()).c_str(), nullptr, nullptr, nullptr); + if(cipherSettings->getKdfAlgorithm() != enc_default_kdf_algorithm) + sqlite3_exec(dbHandle, ("PRAGMA cipher_kdf_algorithm = " + cipherSettings->getKdfAlgorithm()).c_str(), nullptr, nullptr, nullptr); + if(cipherSettings->getPlaintextHeaderSize() != enc_default_plaintext_header_size) + sqlite3_exec(dbHandle, ("PRAGMA cipher_plaintext_header_size = " + std::to_string(cipherSettings->getPlaintextHeaderSize())).c_str(), nullptr, nullptr, nullptr); + + *encrypted = true; #else - sqlite3_close(dbHandle); + lastErrorMessage = QString::fromUtf8(sqlite3_errmsg(dbHandle)); + sqlite3_close_v2(dbHandle); return false; #endif } else { sqlite3_finalize(vm); - sqlite3_close(dbHandle); + sqlite3_close_v2(dbHandle); return true; } } } -bool DBBrowserDB::setSavepoint(const QString& pointname) +void DBBrowserDB::getSqliteVersion(QString& sqlite, QString& sqlcipher) +{ + sqlite = QString(SQLITE_VERSION); + + // The SQLCipher version must be queried via a pragma and for a pragma we need a database connection. + // Because we want to be able to query the SQLCipher version without opening a database file first, we + // open a separate connection to an in-memory database here. + sqlcipher = QString(); +#ifdef ENABLE_SQLCIPHER + sqlite3* dummy; + if(sqlite3_open(":memory:", &dummy) == SQLITE_OK) + { + sqlite3_stmt* stmt; + if(sqlite3_prepare_v2(dummy, "PRAGMA cipher_version", -1, &stmt, nullptr) == SQLITE_OK) + { + if(sqlite3_step(stmt) == SQLITE_ROW) + sqlcipher = QByteArray(static_cast(sqlite3_column_blob(stmt, 0)), sqlite3_column_bytes(stmt, 0)); + + sqlite3_finalize(stmt); + } + + sqlite3_close_v2(dummy); + } +#endif +} + +bool DBBrowserDB::setSavepoint(const std::string& pointname, bool unique) { if(!isOpen()) return false; - if(savepointList.contains(pointname)) + if(isReadOnly) { + qWarning() << "setSavepoint: not done. DB is read-only"; + return false; + } + if(unique && contains(savepointList, pointname)) return true; - QString query = QString("SAVEPOINT %1;").arg(pointname); - executeSQL(query, false, false); - savepointList.append(pointname); + executeSQL("SAVEPOINT " + sqlb::escapeIdentifier(pointname) + ";", false, true); + savepointList.push_back(pointname); emit dbChanged(getDirty()); return true; } -bool DBBrowserDB::releaseSavepoint(const QString& pointname) +bool DBBrowserDB::releaseSavepoint(const std::string& pointname) { - if(!isOpen() || savepointList.contains(pointname) == false) + if(!isOpen()) return false; + if(contains(savepointList, pointname) == false) + // If there is no such savepoint in the list, + // we have already released it, so in this case + // the operation should be successfull + return true; - QString query = QString("RELEASE %1;").arg(pointname); - executeSQL(query, false, false); - savepointList.removeAll(pointname); + if(!executeSQL("RELEASE " + sqlb::escapeIdentifier(pointname) + ";", false, true)) + return false; + // SQLite releases all savepoints that were created between + // creation of given savepoint and releasing of it, + // so we should too + auto it = std::find(savepointList.rbegin(), savepointList.rend(), pointname).base() - 1; + savepointList.erase(it, savepointList.end()); emit dbChanged(getDirty()); return true; } -bool DBBrowserDB::revertToSavepoint(const QString& pointname) +bool DBBrowserDB::revertToSavepoint(const std::string& pointname) { - if(!isOpen() || savepointList.contains(pointname) == false) + if(!isOpen() || contains(savepointList, pointname) == false) return false; - QString query = QString("ROLLBACK TO SAVEPOINT %1;").arg(pointname); - executeSQL(query, false, false); - query = QString("RELEASE %1;").arg(pointname); - executeSQL(query, false, false); - savepointList.removeAll(pointname); + executeSQL("ROLLBACK TO SAVEPOINT " + sqlb::escapeIdentifier(pointname) + ";", false, true); + executeSQL("RELEASE " + sqlb::escapeIdentifier(pointname) + ";", false, true); + // SQLite releases all savepoints that were created between + // creation of given savepoint and releasing of it, + // so we should too + auto it = std::find(savepointList.rbegin(), savepointList.rend(), pointname).base() - 1; + savepointList.erase(it, savepointList.end()); emit dbChanged(getDirty()); return true; @@ -308,24 +649,29 @@ bool DBBrowserDB::revertToSavepoint(const QString& pointname) bool DBBrowserDB::releaseAllSavepoints() { - foreach(const QString& point, savepointList) + if(!_db) + return false; + + waitForDbRelease(); + + while(!savepointList.empty()) { - if(!releaseSavepoint(point)) + if(!releaseSavepoint(savepointList.front())) return false; } // When still in a transaction, commit that too if(sqlite3_get_autocommit(_db) == 0) - executeSQL("COMMIT;", false, false); + executeSQL("COMMIT;", false, true); return true; } bool DBBrowserDB::revertAll() { - foreach(const QString& point, savepointList) + while(!savepointList.empty()) { - if(!revertToSavepoint(point)) + if(!revertToSavepoint(savepointList.front())) return false; } return true; @@ -333,12 +679,11 @@ bool DBBrowserDB::revertAll() bool DBBrowserDB::create ( const QString & db) { - if (isOpen()) close(); + if (isOpen()) + close(); - // read encoding from settings and open with sqlite3_open for utf8 - // and sqlite3_open16 for utf16 - QSettings settings(QApplication::organizationName(), QApplication::organizationName()); - QString sEncoding = settings.value("/db/defaultencoding", "UTF-8").toString(); + // read encoding from settings and open with sqlite3_open for utf8 and sqlite3_open16 for utf16 + QString sEncoding = Settings::getValue("db", "defaultencoding").toString(); int openresult = SQLITE_OK; @@ -348,112 +693,227 @@ bool DBBrowserDB::create ( const QString & db) openresult = sqlite3_open16(db.utf16(), &_db); if( openresult != SQLITE_OK ){ - lastErrorMessage = QString::fromUtf8((const char*)sqlite3_errmsg(_db)); - sqlite3_close(_db); - _db = 0; + lastErrorMessage = QString::fromUtf8(sqlite3_errmsg(_db)); + sqlite3_close_v2(_db); + _db = nullptr; return false; } if (_db) { - // set preference defaults - QSettings settings(QApplication::organizationName(), QApplication::organizationName()); - settings.sync(); - bool foreignkeys = settings.value( "/db/foreignkeys", false ).toBool(); - setPragma("foreign_keys", foreignkeys ? "1" : "0"); - - // Enable extension loading - sqlite3_enable_load_extension(_db, 1); - // force sqlite3 do write proper file header // if we don't create and drop the table we might end up // with a 0 byte file, if the user cancels the create table dialog - executeSQL("CREATE TABLE notempty (id integer primary key);", false, false); - executeSQL("DROP TABLE notempty;", false, false); - executeSQL("COMMIT;", false, false); - - // Execute default SQL - QString default_sql = settings.value( "/db/defaultsqltext", "").toString(); - if(!default_sql.isEmpty()) - executeMultiSQL(default_sql, false, true); + { + NoStructureUpdateChecks nup(*this); + executeSQL("CREATE TABLE notempty (id integer primary key);", false, false); + executeSQL("DROP TABLE notempty;", false, false); + } - curDBFilename = db; - isEncrypted = false; - isReadOnly = false; - return true; + // Close database and open it through the code for opening existing database files. This is slightly less efficient but saves us some duplicate + // code. + sqlite3_close_v2(_db); + return open(db); } else { return false; } } - bool DBBrowserDB::close() { - if(_db) + // Do nothing if no file is opened + if(!_db) + return true; + + waitForDbRelease(); + + if (getDirty()) { - if (getDirty()) + // In-memory databases can't be saved to disk. So the need another text than regular databases. + // Note that the QMessageBox::Yes option in the :memory: case and the QMessageBox::No option in the regular case are + // doing the same job: proceeding but not saving anything. + QMessageBox::StandardButton reply; + if(curDBFilename == ":memory:") { - QMessageBox::StandardButton reply = QMessageBox::question(0, - QApplication::applicationName(), - tr("Do you want to save the changes " - "made to the database file %1?").arg(curDBFilename), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - - // If the user clicked the cancel button stop here and return false - if(reply == QMessageBox::Cancel) - return false; - - // If he didn't it was either yes or no - if(reply == QMessageBox::Yes) - releaseAllSavepoints(); - else - revertAll(); //not really necessary, I think... but will not hurt. + reply = QMessageBox::question(nullptr, + QApplication::applicationName(), + tr("Do you really want to close this temporary database? All data will be lost."), + QMessageBox::Yes | QMessageBox::Cancel); + } else { + reply = QMessageBox::question(nullptr, + QApplication::applicationName(), + tr("Do you want to save the changes made to the database file %1?").arg(curDBFilename), + QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); } - sqlite3_close(_db); + + // If the user clicked the cancel button stop here and return false + if(reply == QMessageBox::Cancel) + return false; + + // If he didn't it was either yes or no + if(reply == QMessageBox::Save) + releaseAllSavepoints(); + else + revertAll(); //not really necessary, I think... but will not hurt. } - _db = 0; - objMap.clear(); + + if(sqlite3_close_v2(_db) != SQLITE_OK) + qWarning() << tr("Database didn't close correctly, probably still busy"); + + _db = nullptr; + curDBFilename.clear(); + schemata.clear(); savepointList.clear(); + emit dbChanged(getDirty()); + emit structureUpdated(); // Return true to tell the calling function that the closing wasn't cancelled by the user return true; } -bool DBBrowserDB::dump(const QString& filename, - const QStringList & tablesToDump, +bool DBBrowserDB::saveAs(const std::string& filename) { + if(!_db) + return false; + + waitForDbRelease(); + + // Open the database file identified by filename. Exit early if this fails + // for any reason. + sqlite3* pTo; + int rc = sqlite3_open(filename.c_str(), &pTo); + if(rc!=SQLITE_OK) { + qWarning() << tr("Cannot open destination file: '%1'").arg(filename.c_str()); + return false; + } else { + // Set up the backup procedure to copy from the "main" database of + // connection _db to the main database of connection pTo. + // If something goes wrong, pBackup will be set to nullptr and an error + // code and message left in connection pTo. + // + // If the backup object is successfully created, call backup_step() + // to copy data from _db to pTo. Then call backup_finish() + // to release resources associated with the pBackup object. If an + // error occurred, then an error code and message will be left in + // connection pTo. If no error occurred, then the error code belonging + // to pTo is set to SQLITE_OK. + // + sqlite3_backup* pBackup = sqlite3_backup_init(pTo, "main", _db, "main"); + if(pBackup == nullptr) { + qWarning() << tr("Cannot backup to file: '%1'. Message: %2").arg(filename.c_str(), sqlite3_errmsg(pTo)); + sqlite3_close_v2(pTo); + return false; + } else { + sqlite3_backup_step(pBackup, -1); + sqlite3_backup_finish(pBackup); + } + rc = sqlite3_errcode(pTo); + } + + if(rc == SQLITE_OK) { + // Close current database and set backup as current + sqlite3_close_v2(_db); + _db = pTo; + curDBFilename = QString::fromStdString(filename); + + return true; + } else { + qWarning() << tr("Cannot backup to file: '%1'. Message: %2").arg(filename.c_str(), sqlite3_errmsg(pTo)); + // Close failed database connection. + sqlite3_close_v2(pTo); + return false; + } +} + +DBBrowserDB::db_pointer_type DBBrowserDB::get(const QString& user, bool force_wait) +{ + if(!_db) + return nullptr; + + waitForDbRelease(force_wait ? Wait : Ask); + + db_user = user; + db_used = true; + emit databaseInUseChanged(true, user); + + return db_pointer_type(_db, DatabaseReleaser(this)); +} + +void DBBrowserDB::waitForDbRelease(ChoiceOnUse choice) const +{ + if(!_db) + return; + + // We can't show a message box from another thread than the main thread. So instead of crashing we + // just decide that we don't interrupt any running query in this case. + if(choice == Ask && QThread::currentThread() != QApplication::instance()->thread()) + choice = Wait; + + std::unique_lock lk(m); + while(db_used) { + // notify user, give him the opportunity to cancel that + auto str = db_user; + lk.unlock(); + + bool cancel = choice == CancelOther; + if(choice == Ask) { + QMessageBox msgBox; + msgBox.setText(tr("The database is currently busy: ") + str); + msgBox.setInformativeText(tr("Do you want to abort that other operation?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + int ret = msgBox.exec(); + + cancel = ret == QMessageBox::Yes; + } + if(cancel) + sqlite3_interrupt(_db); + + lk.lock(); + cv.wait(lk, [this](){ return !db_used; }); + } +} + +bool DBBrowserDB::dump(const QString& filePath, + const std::vector& tablesToDump, bool insertColNames, bool insertNewSyntx, + bool keepOriginal, bool exportSchema, - bool exportData) + bool exportData, + bool keepOldSchema) const { + waitForDbRelease(); + // Open file - QFile file(filename); - if(file.open(QIODevice::WriteOnly)) + QFile file(filePath); + if(file.open(QIODevice::WriteOnly|QIODevice::Text)) { QApplication::setOverrideCursor(Qt::WaitCursor); - size_t numRecordsTotal = 0, numRecordsCurrent = 0; - QList tables = objMap.values("table"); - QMutableListIterator it(tables); - while(it.hasNext()) + // Count the total number of all records in all tables for the progress dialog + size_t numRecordsTotal = 0; + objectMap objMap = schemata.at("main"); // We only always export the main database, not the attached databases + std::vector tables; + for(const auto& it : objMap.tables) { - it.next(); - - // Remove the sqlite_stat1 table if there is one - if(it.value().getname() == "sqlite_stat1" || it.value().getname() == "sqlite_sequence") + QString tableName = QString::fromStdString(it.first); + // Never export the sqlite internal tables. Also only export any tables which are selected for export. + if(!it.second->isView() + && !tableName.startsWith("sqlite_", Qt::CaseInsensitive) + && contains(tablesToDump, it.first)) { - it.remove(); - } else { - // Otherwise get the number of records in this table - SqliteTableModel tableModel(0, this); - tableModel.setTable(it.value().getname()); - numRecordsTotal += tableModel.totalRowCount(); + // Get the number of records in this table and remember to export it + tables.push_back(it.second); + numRecordsTotal += querySingleValueFromDb("SELECT COUNT(*) FROM " + sqlb::ObjectIdentifier("main", it.first).toString()).toUInt(); } } QProgressDialog progress(tr("Exporting database to SQL file..."), - tr("Cancel"), 0, numRecordsTotal); + tr("Cancel"), 0, static_cast(numRecordsTotal)); + // Disable context help button on Windows + progress.setWindowFlags(progress.windowFlags() + & ~Qt::WindowContextHelpButtonHint); progress.setWindowModality(Qt::ApplicationModal); progress.show(); qApp->processEvents(); @@ -464,119 +924,156 @@ bool DBBrowserDB::dump(const QString& filename, // Put the SQL commands in a transaction block stream << "BEGIN TRANSACTION;\n"; - // Loop through all tables first as they are required to generate views, indices etc. later - for(QList::ConstIterator it=tables.begin();it!=tables.end();++it) + // First export the schema of all selected tables. We need to export the schema of all tables before we export the first INSERT statement to + // make sure foreign keys are working properly. + if(exportSchema) { - if (tablesToDump.indexOf(it->getTableName()) == -1) - continue; - - // Write the SQL string used to create this table to the output file - if(exportSchema) - stream << it->getsql() << ";\n"; - - // If the user doesn't want the data to be exported skip the rest of the loop block here - if(!exportData) - continue; - - // get columns - QStringList cols(it->table.fieldNames()); - - QString sQuery = QString("SELECT * FROM %1;").arg(sqlb::escapeIdentifier(it->getTableName())); - QByteArray utf8Query = sQuery.toUtf8(); - sqlite3_stmt *stmt; - QString lineSep(QString(")%1\n").arg(insertNewSyntx?',':';')); + for(const auto& it : tables) + { + // Write the SQL string used to create this table to the output file + if(!keepOldSchema) + stream << QString("DROP TABLE IF EXISTS %1;\n").arg(QString::fromStdString(sqlb::escapeIdentifier(it->name()))); + + if(it->fullyParsed() && !keepOriginal) + stream << QString::fromStdString(it->sql("main", keepOldSchema)) << "\n"; + else { + QString statement = QString::fromStdString(it->originalSql()); + if(keepOldSchema) { + if (statement.startsWith("CREATE VIRTUAL TABLE", Qt::CaseInsensitive)) { + const int createTableLength = 20; + statement.replace(0, createTableLength, "CREATE VIRTUAL TABLE IF NOT EXISTS"); + } else { + // The statement is guaranteed by SQLite to start with "CREATE TABLE" + const int createTableLength = 12; + statement.replace(0, createTableLength, "CREATE TABLE IF NOT EXISTS"); + } + } + stream << statement << ";\n"; + } + } + } - int status = sqlite3_prepare_v2(this->_db, utf8Query.data(), utf8Query.size(), &stmt, NULL); - if(SQLITE_OK == status) + // Now export the data as well + if(exportData) + { + for(const auto& it : tables) { - int columns = sqlite3_column_count(stmt); - size_t counter = 0; - qApp->processEvents(); - while(sqlite3_step(stmt) == SQLITE_ROW) - { - if (counter) stream << lineSep; + // get columns + sqlb::StringVector cols = it->fieldNames(); - if (!insertNewSyntx || !counter) - { - stream << "INSERT INTO " << sqlb::escapeIdentifier(it->getTableName()); - if (insertColNames) - stream << " (" << cols.join(",") << ")"; - stream << " VALUES ("; - } - else - { - stream << " ("; - } + std::string sQuery = "SELECT * FROM " + sqlb::escapeIdentifier(it->name()); + sqlite3_stmt *stmt; + QString lineSep(QString(")%1\n").arg(insertNewSyntx?',':';')); - for (int i = 0; i < columns; ++i) + int status = sqlite3_prepare_v2(_db, sQuery.c_str(), static_cast(sQuery.size()), &stmt, nullptr); + if(SQLITE_OK == status) + { + int columns = sqlite3_column_count(stmt); + size_t counter = 0; + size_t numRecordsCurrent = 0; + qApp->processEvents(); + while(sqlite3_step(stmt) == SQLITE_ROW) { - int fieldsize = sqlite3_column_bytes(stmt, i); - int fieldtype = sqlite3_column_type(stmt, i); - QByteArray bcontent( - (const char*)sqlite3_column_blob(stmt, i), - fieldsize); + if (counter) stream << lineSep; - if(bcontent.left(2048).contains('\0')) // binary check + if (!insertNewSyntx || !counter) { - stream << QString("X'%1'").arg(QString(bcontent.toHex())); + stream << "INSERT INTO " << QString::fromStdString(sqlb::escapeIdentifier(it->name())); + if (insertColNames) + stream << " (" << QString::fromStdString(sqlb::joinStringVector(sqlb::escapeIdentifier(cols), ",")) << ")"; + stream << " VALUES ("; } else { + stream << " ("; + } + + for (int i = 0; i < columns; ++i) + { + int fieldsize = sqlite3_column_bytes(stmt, i); + int fieldtype = sqlite3_column_type(stmt, i); + QByteArray bcontent( + reinterpret_cast(sqlite3_column_blob(stmt, i)), + fieldsize); + switch(fieldtype) { - case SQLITE_TEXT: case SQLITE_BLOB: - stream << "'" << bcontent.replace("'", "''") << "'"; - break; + stream << QString("X'%1'").arg(QString(bcontent.toHex())); + break; + case SQLITE_TEXT: + stream << sqlb::escapeByteArray(bcontent); + break; case SQLITE_NULL: stream << "NULL"; - break; + break; case SQLITE_FLOAT: if(bcontent.indexOf("Inf") != -1) stream << "'" << bcontent << "'"; else stream << bcontent; - break; + break; default: stream << bcontent; } + if(i != columns - 1) + stream << ','; } - if(i != columns - 1) - stream << ','; - } - progress.setValue(++numRecordsCurrent); - if(counter % 5000 == 0) - qApp->processEvents(); - counter++; + progress.setValue(static_cast(++numRecordsCurrent)); + if(counter % 5000 == 0) + qApp->processEvents(); + counter++; - if(progress.wasCanceled()) - { - sqlite3_finalize(stmt); - file.close(); - file.remove(); - QApplication::restoreOverrideCursor(); - return false; + if(progress.wasCanceled()) + { + sqlite3_finalize(stmt); + file.close(); + file.remove(); + QApplication::restoreOverrideCursor(); + return false; + } } + if (counter > 0) stream << ");\n"; } - if (counter > 0) stream << ");\n"; + sqlite3_finalize(stmt); } - sqlite3_finalize(stmt); } - // Now dump all the other objects (but only if we are exporting the schema) + // Finally export all objects other than tables if(exportSchema) { - for(objectMap::ConstIterator it=objMap.begin();it!=objMap.end();++it) - { - // Make sure it's not a table again - if(it.value().gettype() == "table") - continue; + auto writeSchema = [&stream, &tablesToDump, keepOldSchema, keepOriginal](const QString& type, auto objects) { + for(const auto& obj : objects) + { + const auto& it = obj.second; - // Write the SQL string used to create this object to the output file - if(!it->getsql().isEmpty()) - stream << it->getsql() << ";\n"; - } + // If this object is based on a table (e.g. is an index for that table) it depends on the existence of this table. + // So if we didn't export the base table this depends on, don't export this object either. + if(!sqlb::getBaseTable(it).empty() && !contains(tablesToDump, sqlb::getBaseTable(it))) + continue; + + // Write the SQL string used to create this object to the output file + if(!it->originalSql().empty()) + { + if(!keepOldSchema) + stream << QString("DROP %1 IF EXISTS %2;\n").arg( + type.toUpper(), + QString::fromStdString(sqlb::escapeIdentifier(it->name()))); + + if(it->fullyParsed() && !keepOriginal) + stream << QString::fromStdString(it->sql("main", keepOldSchema)) << "\n"; + else + stream << QString::fromStdString(it->originalSql()) << ";\n"; + } + } + }; + + std::map views; + std::copy_if(objMap.tables.begin(), objMap.tables.end(), std::inserter(views, views.end()), [](const auto& t) { return t.second->isView(); }); + writeSchema("view", views); + writeSchema("index", objMap.indices); + writeSchema("trigger", objMap.triggers); } // Done @@ -585,111 +1082,266 @@ bool DBBrowserDB::dump(const QString& filename, QApplication::restoreOverrideCursor(); qApp->processEvents(); - return true; + return stream.status() == QTextStream::Ok && file.error() == QFileDevice::NoError; } return false; } -bool DBBrowserDB::executeSQL ( const QString & statement, bool dirtyDB, bool logsql) +// Callback for sqlite3_exec. It receives the user callback in the first parameter. Converts parameters +// to C++ classes and calls user callback. +int DBBrowserDB::callbackWrapper (void* callback, int numberColumns, char** values, char** columnNames) { - char *errmsg; + std::vector valuesList; + std::vector namesList; - if (!isOpen()) - return false; + for (int i=0; i(callback)); + return userCallback(numberColumns, valuesList, namesList); +} - if (SQLITE_OK == sqlite3_exec(_db, statement.toUtf8(), NULL, NULL, &errmsg)) +bool DBBrowserDB::executeSQL(const std::string& statement, bool dirtyDB, bool logsql, execCallback callback) +{ + waitForDbRelease(); + if(!_db) { - return true; - } else { - lastErrorMessage = QString("%1 (%2)").arg(QString::fromUtf8(errmsg)).arg(statement); - qWarning() << "executeSQL: " << statement << "->" << errmsg; + lastErrorMessage = tr("No database file opened"); + return false; + } + + if (dirtyDB) setSavepoint(); + if (logsql) logSQL(QString::fromStdString(statement), kLogMsg_App); + + char* errmsg; + if (SQLITE_OK == sqlite3_exec(_db, statement.c_str(), callback ? callbackWrapper : nullptr, &callback, &errmsg)) + { + // Update DB structure after executing an SQL statement. But try to avoid doing unnecessary updates. + if(!disableStructureUpdateChecks && (starts_with_ci(statement, "ALTER") || + starts_with_ci(statement, "CREATE") || + starts_with_ci(statement, "DROP") || + starts_with_ci(statement, "ROLLBACK"))) + updateSchema(); + + return true; + } else { + lastErrorMessage = QString("%1 (%2)").arg(QString::fromUtf8(errmsg), QString::fromStdString(statement)); + qWarning() << "executeSQL: " << lastErrorMessage; + sqlite3_free(errmsg); + return false; } } -bool DBBrowserDB::executeMultiSQL(const QString& statement, bool dirty, bool log) +bool DBBrowserDB::executeMultiSQL(QByteArray query, bool dirty, bool log) { - // First check if a DB is opened - if(!isOpen()) + waitForDbRelease(); + if(!_db) + { + lastErrorMessage = tr("No database file opened"); return false; + } // Log the statement if needed if(log) - logSQL(statement, kLogMsg_App); - - // Set DB to dirty/create restore point if necessary - if(dirty) - setSavepoint(); + logSQL(query, kLogMsg_App); // Show progress dialog - int statement_size = statement.size(); QProgressDialog progress(tr("Executing SQL..."), - tr("Cancel"), 0, statement_size); + tr("Cancel"), 0, 100); progress.setWindowModality(Qt::ApplicationModal); + // Disable context help button on Windows + progress.setWindowFlags(progress.windowFlags() + & ~Qt::WindowContextHelpButtonHint); progress.show(); // Execute the statement by looping until SQLite stops giving back a tail string sqlite3_stmt* vm; - QByteArray utf8Query = statement.toUtf8(); - const char *tail = utf8Query.data(); - int res = 0; + const char *tail = query.constData(); + const char * const tail_start = tail; + const char * const tail_end = tail + query.size() + 1; + size_t total_tail_length = static_cast(tail_end - tail_start); unsigned int line = 0; - do + bool structure_updated = false; + int last_progress_value = -1; + std::string savepoint_name; + while(tail && *tail != 0) { line++; - size_t tail_length = strlen(tail); - // Update progress dialog, keep UI responsive - progress.setValue(statement_size - tail_length); - qApp->processEvents(); - if(progress.wasCanceled()) + // Update progress dialog, keep UI responsive. Make sure to not spend too much time updating the progress dialog in case there are many small statements. + int progress_value = static_cast(static_cast(tail - tail_start) / static_cast(total_tail_length) * 100.0f); + if(progress_value > last_progress_value) { - lastErrorMessage = tr("Action cancelled."); - return false; + progress.setValue(progress_value); + qApp->processEvents(); + if(progress.wasCanceled()) + { + lastErrorMessage = tr("Action cancelled."); + return false; + } + last_progress_value = progress_value; + } + + // Check next statement + { + // Ignore all whitespace at the start of the current tail + const char* tail_ptr = tail; + while(std::isspace(*tail_ptr)) + tail_ptr++; + + // Convert the first couple of bytes of the tail to a C++ string for easier handling. We only need the first 8 bytes (in cae it's a ROLLBACK + // statement), so no need to convert the entire tail. If the tail is less than 8 bytes long, make sure not to read past its end. + size_t length = std::min(static_cast(tail_end - tail + 1), static_cast(8)); + std::string next_statement(tail_ptr, length); + std::transform(next_statement.begin(), next_statement.end(), next_statement.begin(), ::toupper); + + // Check for transaction statements and skip until the next semicolon + if(next_statement.compare(0, 6, "COMMIT") == 0 || + next_statement.compare(0, 4, "END ") == 0 || + next_statement.compare(0, 6, "BEGIN ") == 0) + { + while(tail != tail_end) + { + if(*tail++ == ';') + break; + } + + // Set DB to dirty and create a restore point if we haven't done that yet + if(savepoint_name.empty()) + { + savepoint_name = generateSavepointName("execmultisql"); + setSavepoint(savepoint_name); + dirty = true; + } + + // Don't just execute next statement. Start next statement with the same checks + continue; + } + + // Check whether the DB structure is changed by this statement + if(!disableStructureUpdateChecks && !structure_updated) + { + // Check if it's a modifying statement + if(next_statement.compare(0, 5, "ALTER") == 0 || + next_statement.compare(0, 6, "CREATE") == 0 || + next_statement.compare(0, 4, "DROP") == 0 || + next_statement.compare(0, 8, "ROLLBACK") == 0) + structure_updated = true; + } } // Execute next statement - res = sqlite3_prepare_v2(_db, tail, tail_length, &vm, &tail); - if(res == SQLITE_OK) + if(sqlite3_prepare_v2(_db, tail, static_cast(tail_end - tail + 1), &vm, &tail) == SQLITE_OK) { - if(sqlite3_step(vm) == SQLITE_ERROR) + switch(sqlite3_step(vm)) { + case SQLITE_OK: + case SQLITE_ROW: + case SQLITE_DONE: + case SQLITE_MISUSE: // This is a workaround around problematic user scripts. If they lead to empty commands, + // SQLite will return a misuse error which we hereby ignore. sqlite3_finalize(vm); - lastErrorMessage = tr("Error in statement #%1: %2.\n" - "Aborting execution.").arg(line).arg(sqlite3_errmsg(_db)); + break; + default: + // In case of *any* error abort the execution and roll back the transaction + + // Make sure to save the error message first before any other function can mess around with it + lastErrorMessage = tr("Error in statement #%1: %2.\nAborting execution%3.").arg( + QString::number(line), + sqlite3_errmsg(_db), + dirty ? tr(" and rolling back") : ""); qWarning() << lastErrorMessage; - return false; - } else { + + // Clean up sqlite3_finalize(vm); + if(dirty) + revertToSavepoint(savepoint_name); + return false; } } else { - lastErrorMessage = tr("Error in statement #%1: %2.\n" - "Aborting execution.").arg(line).arg(sqlite3_errmsg(_db)); + lastErrorMessage = tr("Error in statement #%1: %2.\nAborting execution%3.").arg( + QString::number(line), + sqlite3_errmsg(_db), + dirty ? tr(" and rolling back") : ""); qWarning() << lastErrorMessage; + if(dirty) + revertToSavepoint(savepoint_name); return false; } - } while(tail && *tail != 0 && (res == SQLITE_OK || res == SQLITE_DONE)); + } + + // If the DB structure was changed by some command in this SQL script, update our schema representations + if(structure_updated) + updateSchema(); // Exit return true; } -bool DBBrowserDB::getRow(const QString& sTableName, const QString& rowid, QList& rowdata) +QByteArray DBBrowserDB::querySingleValueFromDb(const std::string& sql, bool log, ChoiceOnUse choice) const { - QString sQuery = QString("SELECT * FROM %1 WHERE %2='%3';") - .arg(sqlb::escapeIdentifier(sTableName)) - .arg(sqlb::escapeIdentifier(getObjectByName(sTableName).table.rowidColumn())) - .arg(rowid); + waitForDbRelease(choice); + if(!_db) + return QByteArray(); + + if(log) + logSQL(QString::fromStdString(sql), kLogMsg_App); + + QByteArray retval; + + sqlite3_stmt* stmt; + if(sqlite3_prepare_v2(_db, sql.c_str(), static_cast(sql.size()), &stmt, nullptr) == SQLITE_OK) + { + // Execute the statement. We distinguish three types of results: + // SQLITE_ROW in case some data was returned from the database. This data is then used as a return value. + // SQLITE_DONE in case the statement executed successfully but did not return any data. We do nothing in this case, leaving the return value empty. + // Any other case is an error, so we need to prepare an error message. + int result = sqlite3_step(stmt); + if(result == SQLITE_ROW) + { + if(sqlite3_column_count(stmt) > 0 && sqlite3_column_type(stmt, 0) != SQLITE_NULL) + { + int bytes = sqlite3_column_bytes(stmt, 0); + if(bytes) + retval = QByteArray(static_cast(sqlite3_column_blob(stmt, 0)), bytes); + else + retval = ""; + } + } else if(result != SQLITE_DONE) { + lastErrorMessage = tr("didn't receive any output from %1").arg(QString::fromStdString(sql)); + qWarning() << lastErrorMessage; + } + + sqlite3_finalize(stmt); + } else { + lastErrorMessage = tr("could not execute command: %1").arg(sqlite3_errmsg(_db)); + qWarning() << lastErrorMessage; + } + + return retval; +} + +bool DBBrowserDB::getRow(const sqlb::ObjectIdentifier& table, const QString& rowid, std::vector& rowdata) const +{ + waitForDbRelease(); + if(!_db) + return false; + + std::string query = "SELECT * FROM " + table.toString() + " WHERE "; + + // For a single rowid column we can use a simple WHERE condition, for multiple rowid columns we have to use sqlb_make_single_value to decode the composed rowid values. + sqlb::StringVector pks = getTableByName(table)->rowidColumns(); + if(pks.size() == 1) + query += sqlb::escapeIdentifier(pks.front()) + "='" + rowid.toStdString() + "'"; + else + query += "sqlb_make_single_value(" + sqlb::joinStringVector(sqlb::escapeIdentifier(pks), ",") + ")=" + sqlb::escapeString(rowid.toStdString()); - QByteArray utf8Query = sQuery.toUtf8(); sqlite3_stmt *stmt; bool ret = false; - - int status = sqlite3_prepare_v2(_db, utf8Query, utf8Query.size(), &stmt, NULL); - if(SQLITE_OK == status) + if(sqlite3_prepare_v2(_db, query.c_str(), static_cast(query.size()), &stmt, nullptr) == SQLITE_OK) { // even this is a while loop, the statement should always only return 1 row while(sqlite3_step(stmt) == SQLITE_ROW) @@ -698,13 +1350,13 @@ bool DBBrowserDB::getRow(const QString& sTableName, const QString& rowid, QList< { if(sqlite3_column_type(stmt, i) == SQLITE_NULL) { - rowdata.append(QByteArray()); + rowdata.emplace_back(); } else { int bytes = sqlite3_column_bytes(stmt, i); if(bytes) - rowdata.append(QByteArray(static_cast(sqlite3_column_blob(stmt, i)), bytes)); + rowdata.emplace_back(static_cast(sqlite3_column_blob(stmt, i)), bytes); else - rowdata.append(QByteArray("")); + rowdata.emplace_back(""); } } ret = true; @@ -715,68 +1367,72 @@ bool DBBrowserDB::getRow(const QString& sTableName, const QString& rowid, QList< return ret; } -QString DBBrowserDB::max(const sqlb::Table& t, sqlb::FieldPtr field) const +unsigned long DBBrowserDB::max(const sqlb::ObjectIdentifier& tableName, const std::string& field) const { - QString sQuery = QString("SELECT MAX(CAST(%2 AS INTEGER)) FROM %1;").arg(sqlb::escapeIdentifier(t.name())).arg(sqlb::escapeIdentifier(field->name())); - QByteArray utf8Query = sQuery.toUtf8(); - sqlite3_stmt *stmt; - QString ret = "0"; + // This query returns the maximum value of the given table and column + std::string query = "SELECT MAX(CAST(" + sqlb::escapeIdentifier(field) + " AS INTEGER)) FROM " + tableName.toString(); - int status = sqlite3_prepare_v2(_db, utf8Query, utf8Query.size(), &stmt, NULL); - if(SQLITE_OK == status) + // If, however, there is a sequence table in this database and the given column is the primary key of the table, we try to look up a value in the sequence table + if(schemata.at(tableName.schema()).tables.count("sqlite_sequence")) { - // even this is a while loop, the statement should always only return 1 row - while(sqlite3_step(stmt) == SQLITE_ROW) + auto pk = getTableByName(tableName)->primaryKeyColumns(); + if(pk.size() == 1 && pk.front().name() == field) { - if(sqlite3_column_count(stmt) == 1) - { - ret = QString::fromUtf8(reinterpret_cast(sqlite3_column_text(stmt, 0))); - } - } + // This SQL statement tries to do two things in one statement: get the current sequence number for this table from the sqlite_sequence table or, if there is no record for the table, return the highest integer value in the given column. + // This works by querying the sqlite_sequence table and using an aggregate function (SUM in this case) to make sure to always get exactly one result row, no matter if there is a sequence record or not. We then let COALESCE decide + // whether to return that sequence value if there is one or fall back to the SELECT MAX statement from avove if there is no sequence value. + query = "SELECT COALESCE(SUM(seq), (" + query + ")) FROM sqlite_sequence WHERE name=" + sqlb::escapeString(tableName.name()); + } } - sqlite3_finalize(stmt); - return ret; + return querySingleValueFromDb(query).toULong(); } -QString DBBrowserDB::emptyInsertStmt(const sqlb::Table& t, const QString& pk_value) const +std::string DBBrowserDB::emptyInsertStmt(const std::string& schemaName, const sqlb::Table& t, const QString& pk_value) const { - QString stmt = QString("INSERT INTO %1").arg(sqlb::escapeIdentifier(t.name())); + std::string stmt = "INSERT INTO " + sqlb::escapeIdentifier(schemaName) + "." + sqlb::escapeIdentifier(t.name()); + + const auto pk = t.primaryKeyColumns(); - QStringList vals; - QStringList fields; - foreach(sqlb::FieldPtr f, t.fields()) { - if(f->primaryKey()) { - fields << f->name(); + sqlb::StringVector vals; + sqlb::StringVector fields; + for(const sqlb::Field& f : t.fields) + { + // Never insert into a generated column + if(f.generated()) + continue; + + if(pk.size() == 1 && pk.at(0) == f.name()) + { + fields.push_back(f.name()); if(!pk_value.isNull()) { - vals << pk_value; + vals.push_back(f.isText()? "'" + pk_value.toStdString() + "'" : pk_value.toStdString()); } else { - if(f->notnull()) - { - QString maxval = this->max(t, f); - vals << QString::number(maxval.toLongLong() + 1); - } - else + if(f.notnull()) { - vals << "NULL"; + unsigned long maxval = this->max(sqlb::ObjectIdentifier(schemaName, t.name()), f.name()); + std::string newval = std::to_string(maxval + 1); + vals.push_back(f.isText()? "'" + newval + "'" : newval); + } else { + vals.push_back("NULL"); } } - } else if(f->notnull() && f->defaultValue().length() == 0) { - fields << f->name(); + } else if(f.notnull() && f.defaultValue().length() == 0) { + fields.push_back(f.name()); - if(f->isInteger()) - vals << "0"; + if(f.isInteger()) + vals.push_back("0"); else - vals << "''"; + vals.push_back("''"); } else { // don't insert into fields with a default value // or we will never see it. - if(f->defaultValue().length() == 0) + if(f.defaultValue().length() == 0) { - fields << f->name(); - vals << "NULL"; + fields.push_back(f.name()); + vals.push_back("NULL"); } } } @@ -786,33 +1442,37 @@ QString DBBrowserDB::emptyInsertStmt(const sqlb::Table& t, const QString& pk_val stmt.append(" DEFAULT VALUES;"); } else { stmt.append("("); - foreach(const QString& f, fields) - stmt.append(sqlb::escapeIdentifier(f) + ","); - stmt.chop(1); + stmt.append(sqlb::joinStringVector(sqlb::escapeIdentifier(fields), ",")); stmt.append(") VALUES ("); - stmt.append(vals.join(",")); + stmt.append(sqlb::joinStringVector(vals, ",")); stmt.append(");"); } return stmt; } -QString DBBrowserDB::addRecord(const QString& sTableName) +QString DBBrowserDB::addRecord(const sqlb::ObjectIdentifier& tablename) { - if (!isOpen()) return QString(); + waitForDbRelease(); + if(!_db) + return QString(); - sqlb::Table table = getObjectByName(sTableName).table; + sqlb::TablePtr table = getTableByName(tablename); + if(!table) + return QString(); // For tables without rowid we have to set the primary key by ourselves. We do so by querying for the largest value in the PK column // and adding one to it. - QString sInsertstmt; + std::string sInsertstmt; QString pk_value; - if(table.isWithoutRowidTable()) + if(table->withoutRowidTable()) { - pk_value = QString::number(max(table, table.fields().at(table.findField(table.rowidColumn()))).toLongLong() + 1); - sInsertstmt = emptyInsertStmt(table, pk_value); + // For multiple rowid columns we just use the value of the last one and increase that one by one. If this doesn't yield a valid combination + // the insert record dialog should pop up automatically. + pk_value = QString::number(max(tablename, table->rowidColumns().back()) + 1); + sInsertstmt = emptyInsertStmt(tablename.schema(), *table, pk_value); } else { - sInsertstmt = emptyInsertStmt(table); + sInsertstmt = emptyInsertStmt(tablename.schema(), *table); } if(!executeSQL(sInsertstmt)) @@ -820,65 +1480,107 @@ QString DBBrowserDB::addRecord(const QString& sTableName) qWarning() << "addRecord: " << lastErrorMessage; return QString(); } else { - if(table.isWithoutRowidTable()) + if(table->withoutRowidTable()) return pk_value; else return QString::number(sqlite3_last_insert_rowid(_db)); } } -bool DBBrowserDB::deleteRecord(const QString& table, const QString& rowid) +bool DBBrowserDB::deleteRecords(const sqlb::ObjectIdentifier& table, const std::vector& rowids, const sqlb::StringVector& pseudo_pk) { if (!isOpen()) return false; - bool ok = false; - QString statement = QString("DELETE FROM %1 WHERE %2='%3';") - .arg(sqlb::escapeIdentifier(table)) - .arg(sqlb::escapeIdentifier(getObjectByName(table).table.rowidColumn())) - .arg(rowid); + // Get primary key of the object to edit. + sqlb::StringVector pks = primaryKeyForEditing(table, pseudo_pk); + if(pks.empty()) + { + lastErrorMessage = tr("Cannot delete this object"); + return false; + } + + // Quote all values in advance + std::vector quoted_rowids; + std::transform(rowids.begin(), rowids.end(), std::back_inserter(quoted_rowids), [](const auto& rowid) { return sqlb::escapeByteArray(rowid).toStdString(); }); + + // For a single rowid column we can use a SELECT ... IN(...) statement which is faster. + // For multiple rowid columns we have to use sqlb_make_single_value to decode the composed rowid values. + std::string statement; + if(pks.size() == 1) + { + statement = "DELETE FROM " + table.toString() + " WHERE " + pks.at(0) + " IN ("+ sqlb::joinStringVector(quoted_rowids, ", ") + ");"; + } else { + statement = "DELETE FROM " + table.toString() + " WHERE "; + + statement += "sqlb_make_single_value("; + for(const auto& pk : pks) + statement += sqlb::escapeIdentifier(pk) + ","; + statement.erase(statement.end()-1); + statement += ") IN (" + sqlb::joinStringVector(quoted_rowids, ", ") + ")"; + } + if(executeSQL(statement)) - ok = true; - else + { + return true; + } else { qWarning() << "deleteRecord: " << lastErrorMessage; - - return ok; + return false; + } } -bool DBBrowserDB::updateRecord(const QString& table, const QString& column, const QString& rowid, const QByteArray& value, bool itsBlob) +bool DBBrowserDB::updateRecord(const sqlb::ObjectIdentifier& table, const std::string& column, + const QByteArray& rowid, const QByteArray& value, int force_type, const sqlb::StringVector& pseudo_pk) { + waitForDbRelease(); if (!isOpen()) return false; - QString sql = QString("UPDATE %1 SET %2=? WHERE %3='%4';") - .arg(sqlb::escapeIdentifier(table)) - .arg(sqlb::escapeIdentifier(column)) - .arg(sqlb::escapeIdentifier(getObjectByName(table).table.rowidColumn())) - .arg(rowid); + // Get primary key of the object to edit. + sqlb::StringVector pks = primaryKeyForEditing(table, pseudo_pk); + if(pks.empty()) + { + lastErrorMessage = tr("Cannot set data on this object"); + return false; + } + + std::string sql = "UPDATE " + table.toString() + " SET " + sqlb::escapeIdentifier(column) + "=? WHERE "; + + // For a single rowid column we can use a simple WHERE condition, for multiple rowid columns we have to use sqlb_make_single_value to decode the composed rowid values. + if(pks.size() == 1) + sql += sqlb::escapeIdentifier(pks.front()) + "=" + sqlb::escapeByteArray(rowid).toStdString(); + else + sql += "sqlb_make_single_value(" + sqlb::joinStringVector(sqlb::escapeIdentifier(pks), ",") + ")=" + sqlb::escapeString(rowid.toStdString()); - logSQL(sql, kLogMsg_App); setSavepoint(); // If we get a NULL QByteArray we insert a NULL value, and for that // we can pass NULL to sqlite3_bind_text() so that it behaves like sqlite3_bind_null() - const char *rawValue = value.isNull() ? NULL : value.constData(); + const char *rawValue = value.isNull() ? nullptr : value.constData(); sqlite3_stmt* stmt; int success = 1; - if(sqlite3_prepare_v2(_db, sql.toUtf8(), -1, &stmt, 0) != SQLITE_OK) + if(sqlite3_prepare_v2(_db, sql.c_str(), static_cast(sql.size()), &stmt, nullptr) != SQLITE_OK) success = 0; if(success == 1) { - if(itsBlob) + if(force_type == SQLITE_BLOB) { if(sqlite3_bind_blob(stmt, 1, rawValue, value.length(), SQLITE_STATIC)) success = -1; - } - else - { + } else if(force_type == SQLITE_INTEGER) { + if(sqlite3_bind_int64(stmt, 1, value.toLongLong())) + success = -1; + } else if(force_type == SQLITE_FLOAT) { + if(sqlite3_bind_double(stmt, 1, value.toDouble())) + success = -1; + } else { if(sqlite3_bind_text(stmt, 1, rawValue, value.length(), SQLITE_STATIC)) success = -1; } } - if(success == 1 && sqlite3_step(stmt) != SQLITE_DONE) - success = -1; + if(success == 1) { + logSQL(QString::fromUtf8(sqlite3_expanded_sql(stmt)), kLogMsg_App); + if(sqlite3_step(stmt) != SQLITE_DONE) + success = -1; + } if(success != 0 && sqlite3_finalize(stmt) != SQLITE_OK) success = -1; @@ -892,168 +1594,373 @@ bool DBBrowserDB::updateRecord(const QString& table, const QString& column, cons } } -bool DBBrowserDB::createTable(const QString& name, const sqlb::FieldVector& structure) +sqlb::StringVector DBBrowserDB::primaryKeyForEditing(const sqlb::ObjectIdentifier& table, const sqlb::StringVector& pseudo_pk) const { - // Build SQL statement - sqlb::Table table(name); - for(int i=0;irowidColumns(); + } else { + return pseudo_pk; + } + + return sqlb::StringVector(); } -bool DBBrowserDB::addColumn(const QString& tablename, const sqlb::FieldPtr& field) +bool DBBrowserDB::createTable(const sqlb::ObjectIdentifier& name, const sqlb::FieldVector& structure) { - QString sql = QString("ALTER TABLE %1 ADD COLUMN %2").arg(sqlb::escapeIdentifier(tablename)).arg(field->toString()); + // Build SQL statement + sqlb::Table table(name.name()); + for(size_t i=0;iname()) + ','); - select_cols.chop(1); // remove last comma - } else { - // We want to modify it + changed_something = true; + } + + // Add columns if necessary + for(const auto& field : new_table.fields) + { + // We loop through all the fields of the new table schema and check for each of them if they are new. + // If so, we add that field. The reason for looping through the new table schema instead of the track_columns + // map is that this way we make sure to preserve their order which increases our chances that we are done after + // this step. + if(std::any_of(track_columns.begin(), track_columns.end(), [&field](const std::pair& p) { + return p.first.isNull() && p.second.toStdString() == field.name(); + })) + { + if(!addColumn(sqlb::ObjectIdentifier(tablename.schema(), new_table.name()), field)) + { + revertToSavepoint(savepointName); + return false; + } + } + + changed_something = true; + } + + // Newer versions of SQLite add a better ALTER TABLE support which we can use +#if SQLITE_VERSION_NUMBER >= 3025000 + // If the name of a field should be changed do that by using SQLite's ALTER TABLE feature. We build a new + // map for tracking column names here which uses the update column names as the old names too. This is to + // make sure we are using the new table layout for later updates. + AlterTableTrackColumns new_track_columns; + for(const auto& old_name_it : track_columns) + { + QString old_name = old_name_it.first; + + QString new_name = track_columns[old_name]; + if(!old_name.isNull() && !new_name.isNull() && new_name != old_name) + { + if(!executeSQL("ALTER TABLE " + sqlb::ObjectIdentifier(tablename.schema(), new_table.name()).toString() + " RENAME COLUMN " + + sqlb::escapeIdentifier(old_name.toStdString()) + " TO " + sqlb::escapeIdentifier(new_name.toStdString()))) + { + QString error(tr("Renaming the column failed. DB says:\n%1").arg(lastErrorMessage)); + revertToSavepoint(savepointName); + lastErrorMessage = error; + return false; + } + + changed_something = true; + new_track_columns.insert({new_name, new_name}); + } else { + new_track_columns.insert({old_name, new_name}); + } + } + track_columns.swap(new_track_columns); +#endif - // Move field - int index = newSchema.findField(name); - sqlb::FieldPtr temp = newSchema.fields().at(index); - newSchema.setField(index, newSchema.fields().at(index + move)); - newSchema.setField(index + move, temp); + // Update our schema representation to get the new table and all the changed triggers, views and indices + if(changed_something) + { + updateSchema(); + old_table = *getTableByName(sqlb::ObjectIdentifier(tablename.schema(), new_table.name())); + } - // Get names of fields to select from old table now - after the field has been moved and before it might be renamed - for(int i=0;iname()) + ','); - select_cols.chop(1); // remove last comma + // Check if there's still more work to be done or if we are finished now + if(tablename.schema() == newSchemaName && old_table == new_table) + { + // Release the savepoint - everything went fine + if(!releaseSavepoint(savepointName)) + { + lastErrorMessage = tr("Releasing savepoint failed. DB says: %1").arg(lastErrorMessage); + return false; + } - // Modify field - newSchema.setField(index + move, to); + // Success, update the DB schema before returning + updateSchema(); + return true; } - // Create the new table - if(!executeSQL(newSchema.sql())) + // + // P A R T 3 + // + + // Create a new table with the desired schema and a name that doesn't exist yet + std::string new_table_name = new_table.name(); + sqlb::Table new_table_with_random_name(new_table); + new_table_with_random_name.setName(generateTemporaryTableName(newSchemaName)); + if(!executeSQL(new_table_with_random_name.sql(newSchemaName), true, true)) { - QString error(tr("renameColumn: creating new table failed. DB says: %1").arg(lastErrorMessage)); - qWarning() << error; - revertToSavepoint("sqlitebrowser_rename_column"); + QString error(tr("Creating new table failed. DB says: %1").arg(lastErrorMessage)); + revertToSavepoint(savepointName); lastErrorMessage = error; return false; } + // Assemble list of column names to copy from in the old table and list of column names to into into in the new table + sqlb::StringVector copy_values_from; + sqlb::StringVector copy_values_to; + for(const auto& from_it : track_columns) + { + const auto& from = from_it.first; + + // Ignore new fields + if(from.isNull()) + continue; + + // Ignore deleted fields + QString to = track_columns[from]; + if(to.isNull()) + continue; + + // Ignore generated columns + auto it = sqlb::findField(new_table, to.toStdString()); + if(it->generated()) + continue; + + copy_values_from.push_back(from.toStdString()); + copy_values_to.push_back(to.toStdString()); + } + // Copy the data from the old table to the new one - if(!executeSQL(QString("INSERT INTO sqlitebrowser_rename_column_new_table SELECT %1 FROM %2;").arg(select_cols).arg(sqlb::escapeIdentifier(tablename)))) + if(!executeSQL("INSERT INTO " + sqlb::escapeIdentifier(newSchemaName) + "." + sqlb::escapeIdentifier(new_table_with_random_name.name()) + + " (" + sqlb::joinStringVector(sqlb::escapeIdentifier(copy_values_to), ",") + ") SELECT " + + sqlb::joinStringVector(sqlb::escapeIdentifier(copy_values_from), ",") + " FROM " + + sqlb::escapeIdentifier(tablename.schema()) + "." + sqlb::escapeIdentifier(old_table.name()))) { - QString error(tr("renameColumn: copying data to new table failed. DB says:\n%1").arg(lastErrorMessage)); - qWarning() << error; - revertToSavepoint("sqlitebrowser_rename_column"); + QString error(tr("Copying data to new table failed. DB says:\n%1").arg(lastErrorMessage)); + revertToSavepoint(savepointName); lastErrorMessage = error; return false; } // Save all indices, triggers and views associated with this table because SQLite deletes them when we drop the table in the next step - QString otherObjectsSql; - for(objectMap::ConstIterator it=objMap.begin();it!=objMap.end();++it) - { - // If this object references the table and it's not the table itself save it's SQL string - if((*it).getTableName() == tablename && (*it).gettype() != "table") - otherObjectsSql += (*it).getsql() + "\n"; - } + std::vector otherObjectsSql; + auto saveRelatedObjects = [old_table, track_columns, &otherObjectsSql, newSchemaName](const auto& objects) { + for(const auto& obj : objects) + { + const auto& it = obj.second; + + // If this object references the table save its SQL string + if(sqlb::getBaseTable(it) == old_table.name()) + { + // If this is an index, update the fields first. This highly increases the chance that the SQL statement won't throw an + // error later on when we try to recreate it. + if(std::is_same::value) + { + sqlb::IndexPtr idx = std::dynamic_pointer_cast(it); - // Store the current foreign key settings and then disable the foreign keys being enforced to make sure the table can be dropped without errors - QString foreignKeysOldSettings = getPragma("foreign_keys"); - setPragma("foreign_keys", "0"); + // Loop through all changes to the table schema. For indices only the column names are relevant, so it suffices to look at the + // list of tracked columns + for(const auto& from_it : track_columns) + { + const auto& from = from_it.first; + const auto& to = from_it.second; + + // Are we updating the field name or are we removing the field entirely? + if(!to.isNull()) + { + // We're updating the field name. So search for it in the index and replace it wherever it is found + for(size_t i=0;ifields.size();i++) + { + if(idx->fields[i].name() == from.toStdString()) + idx->fields[i].setName(to.toStdString()); + } + } else { + // We're removing a field. So remove it from any indices, too. + while(sqlb::removeField(idx, from.toStdString())) + ; + } + } + + // Only try to add the index later if it has any columns remaining. Also use the new schema name here, too, to basically move + // any index that references the table to the same new schema as the table. + if(idx->fields.size()) + otherObjectsSql.push_back(idx->sql(newSchemaName)); + } else { + // If it's a view or a trigger we don't have any chance to corrections yet. Just store the statement as is and + // hope for the best. + otherObjectsSql.push_back(it->originalSql() + ";"); + } + } + } + }; + saveRelatedObjects(schemata[tablename.schema()].tables); // We can safely pass the tables along with the views here since they never have a base table set + saveRelatedObjects(schemata[tablename.schema()].indices); + saveRelatedObjects(schemata[tablename.schema()].triggers); + + // We need to disable foreign keys here. The reason is that in the next step the entire table will be dropped and there might be foreign keys + // in other tables that reference this table. These foreign keys would then cause the drop command in the next step to fail. However, we can't + // simply disable foreign keys here since that is not allowed from inside a transaction and we definitely are inside a transaction at that point. + // So what we do instead is defer foreign key enforcement until the end of the transaction which effectively disables foreign keys for us here. + // But because we don't really want to defer foreign keys, the former value of that pragma is saved here in order to restore the old value later. + QString foreignKeysOldSettings = getPragma("defer_foreign_keys"); + setPragma("defer_foreign_keys", "1"); // Delete the old table - if(!executeSQL(QString("DROP TABLE %1;").arg(sqlb::escapeIdentifier(tablename)))) + if(!executeSQL("DROP TABLE " + sqlb::escapeIdentifier(tablename.schema()) + "." + sqlb::escapeIdentifier(old_table.name()), true, true)) { - QString error(tr("renameColumn: deleting old table failed. DB says: %1").arg(lastErrorMessage)); - qWarning() << error; - revertToSavepoint("sqlitebrowser_rename_column"); + QString error(tr("Deleting old table failed. DB says: %1").arg(lastErrorMessage)); + revertToSavepoint(savepointName); lastErrorMessage = error; return false; } // Rename the temporary table - if(!renameTable("sqlitebrowser_rename_column_new_table", tablename)) + if(!renameTable(newSchemaName, new_table_with_random_name.name(), new_table.name())) { - revertToSavepoint("sqlitebrowser_rename_column"); + revertToSavepoint(savepointName); return false; } // Restore the former foreign key settings - setPragma("foreign_keys", foreignKeysOldSettings); + setPragma("defer_foreign_keys", foreignKeysOldSettings); // Restore the saved triggers, views and indices - if(!executeMultiSQL(otherObjectsSql, true, true)) + std::string errored_sqls; + for(const std::string& sql : otherObjectsSql) { - QMessageBox::information(0, qApp->applicationName(), tr("Restoring some of the objects associated with this table failed. " - "This is most likely because some column names changed. " - "Here's the SQL statement which you might want to fix and execute manually:\n\n") - + otherObjectsSql); + if(!executeSQL(sql, true, true)) + errored_sqls += sql + "\n"; + } + if(!errored_sqls.empty()) + { + QMessageBox::information(nullptr, qApp->applicationName(), tr("Restoring some of the objects associated with this table failed. " + "This is most likely because some column names changed. " + "Here's the SQL statement which you might want to fix and execute manually:\n\n") + + QString::fromStdString(errored_sqls)); } // Release the savepoint - everything went fine - if(!releaseSavepoint("sqlitebrowser_rename_column")) + if(!releaseSavepoint(savepointName)) { - lastErrorMessage = tr("renameColumn: releasing savepoint failed. DB says: %1").arg(lastErrorMessage); - qWarning() << lastErrorMessage; + lastErrorMessage = tr("Releasing savepoint failed. DB says: %1").arg(lastErrorMessage); return false; } @@ -1062,179 +1969,174 @@ bool DBBrowserDB::renameColumn(const QString& tablename, const QString& name, sq return true; } -bool DBBrowserDB::renameTable(const QString& from_table, const QString& to_table) +bool DBBrowserDB::renameTable(const std::string& schema, const std::string& from_table, const std::string& to_table) { - QString sql = QString("ALTER TABLE %1 RENAME TO %2").arg(sqlb::escapeIdentifier(from_table)).arg(sqlb::escapeIdentifier(to_table)); + // Do nothing if table names are the same + if(from_table == to_table) + return true; + + // Check if table names only differ in case. If they do, we have to rename the table twice because SQLite can't rename 'table' to 'Table'. + // To solve this we rename 'table' to 'some temp name' and then 'some temp name' to 'Table'. + if(compare_ci(from_table, to_table)) + { + // Generate a temporary table name and rename the table via that by recusrively calling this function + std::string temp_name = generateTemporaryTableName(schema); + if(!renameTable(schema, from_table, temp_name)) + return false; + if(!renameTable(schema, temp_name, to_table)) + return false; + + // Exit here + return true; + } + + // The old and the new table names differ (and that not only in case) + + // Rename the table + std::string sql = "ALTER TABLE " + sqlb::escapeIdentifier(schema) + "." + sqlb::escapeIdentifier(from_table) + " RENAME TO " + sqlb::escapeIdentifier(to_table); if(!executeSQL(sql)) { - QString error = tr("Error renaming table '%1' to '%2'." - "Message from database engine:\n%3").arg(from_table).arg(to_table).arg(lastErrorMessage); + QString error = tr("Error renaming table '%1' to '%2'.\n" + "Message from database engine:\n%3").arg(QString::fromStdString(from_table), QString::fromStdString(to_table), lastErrorMessage); lastErrorMessage = error; qWarning() << lastErrorMessage; return false; } else { - updateSchema(); return true; } } -objectMap DBBrowserDB::getBrowsableObjects() const +void DBBrowserDB::logSQL(const QString& statement, LogMessageType msgtype) const { - objectMap::ConstIterator it; - objectMap res; - - for(it=objMap.begin();it!=objMap.end();++it) - { - if(it.key() == "table" || it.key() == "view") - res.insert(it.key(), it.value()); - } - - return res; + // Remove any leading and trailing spaces, tabs, or line breaks first + emit sqlExecuted(statement.trimmed(), msgtype); } -DBBrowserObject DBBrowserDB::getObjectByName(const QString& name) const +void DBBrowserDB::updateSchema() { - for (objectMap::ConstIterator it = objMap.begin(); it != objMap.end(); ++it ) - { - if((*it).getname() == name) - return *it; - } - return DBBrowserObject(); -} + waitForDbRelease(); -void DBBrowserDB::logSQL(QString statement, int msgtype) -{ - // Remove any leading and trailing spaces, tabs, or line breaks first - statement = statement.trimmed(); + schemata.clear(); - // Replace binary log messages by a placeholder text instead of printing gibberish - for(int i=0;i0?i-1:0); - statement.append(tr("... ...")); + // Exit here is no DB is opened + if(!isOpen()) + return; - // early exit if we detect a binary character, - // to prevent checking all characters in a potential big string - break; - } - } + // Get a list of all databases. This list always includes the main and the temp database but can include more items if there are attached databases + if(!executeSQL("PRAGMA database_list;", false, true, [this](int, std::vector db_values, std::vector) -> bool { + // Get the schema name which is in column 1 (counting starts with 0). 0 contains an ID and 2 the file path. + const std::string schema_name = db_values.at(1).toStdString(); - emit sqlExecuted(statement, msgtype); -} + // Always add the schema to the map. This makes sure it's even then added when there are no objects in the database + objectMap& object_map = schemata[schema_name]; -void DBBrowserDB::updateSchema( ) -{ - sqlite3_stmt *vm; - const char *tail; - int err=0; + // Get a list of all the tables for the current database schema. We need to do this differently for normal databases and the temporary schema + // because SQLite doesn't understand the "temp.sqlite_master" notation. + std::string statement; + if(schema_name == "temp") + statement = "SELECT type,name,sql,tbl_name FROM sqlite_temp_master;"; + else + statement = "SELECT type,name,sql,tbl_name FROM " + sqlb::escapeIdentifier(schema_name) + ".sqlite_master;"; - objMap.clear(); + if(!executeSQL(statement, false, true, [this, schema_name, &object_map](int, std::vector values, std::vector) -> bool { + const std::string val_type = values.at(0).toStdString(); + const std::string val_name = values.at(1).toStdString(); + std::string val_sql = values.at(2).toStdString(); + const std::string val_tblname = values.at(3).toStdString(); - // Exit here is no DB is opened - if(!isOpen()) - return; + if(!val_sql.empty()) + { + val_sql.erase(std::remove(val_sql.begin(), val_sql.end(), '\r'), val_sql.end()); - QString statement = "SELECT type,name,sql,tbl_name FROM sqlite_master UNION SELECT type,name,sql,tbl_name FROM sqlite_temp_master;"; - - QByteArray utf8Statement = statement.toUtf8(); - err=sqlite3_prepare_v2(_db, utf8Statement, utf8Statement.length(), - &vm, &tail); - if (err == SQLITE_OK){ - logSQL(statement, kLogMsg_App); - while ( sqlite3_step(vm) == SQLITE_ROW ){ - QString val1 = QString::fromUtf8((const char*)sqlite3_column_text(vm, 0)); - QString val2 = QString::fromUtf8((const char*)sqlite3_column_text(vm, 1)); - QString val3 = QString::fromUtf8((const char*)sqlite3_column_text(vm, 2)); - QString val4 = QString::fromUtf8((const char*)sqlite3_column_text(vm, 3)); - val3.replace("\r", ""); - - if(val1 == "table" || val1 == "index" || val1 == "view" || val1 == "trigger") - objMap.insert(val1, DBBrowserObject(val2, val3, val1, val4)); - else - qWarning() << tr("unknown object type %1").arg(val1); - } - sqlite3_finalize(vm); - }else{ - qWarning() << tr("could not get list of db objects: %1, %2").arg(err).arg(sqlite3_errmsg(_db)); - } + if(val_type == "table" || val_type == "view") + { + sqlb::TablePtr table; + if(val_type == "table") + table = sqlb::Table::parseSQL(val_sql); + else + table = sqlb::View::parseSQL(val_sql); - //now get the field list for each table - objectMap::Iterator it; - for ( it = objMap.begin(); it != objMap.end(); ++it ) - { - // Use our SQL parser to generate the field list for tables. For views we currently have to fall back to the - // pragma SQLite offers. - if((*it).gettype() == "table") - { - (*it).table = sqlb::Table::parseSQL((*it).getsql()).first; - } else if((*it).gettype() == "view") { - statement = QString("PRAGMA TABLE_INFO(%1);").arg(sqlb::escapeIdentifier((*it).getname())); - logSQL(statement, kLogMsg_App); - err=sqlite3_prepare_v2(_db,statement.toUtf8(),statement.length(), - &vm, &tail); - if (err == SQLITE_OK){ - while ( sqlite3_step(vm) == SQLITE_ROW ){ - if (sqlite3_column_count(vm)==6) + if(!table->fullyParsed()) + table->setName(val_name); + + // For virtual tables, views, and tables we could not parse at all, + // query the column list using the SQLite pragma to at least get + // some information on them when our parser does not. + if((!table->fullyParsed() && table->fields.empty()) || table->isVirtual()) { - QString val_name = QString::fromUtf8((const char *)sqlite3_column_text(vm, 1)); - QString val_type = QString::fromUtf8((const char *)sqlite3_column_text(vm, 2)); + const auto columns = queryColumnInformation(schema_name, val_name); - sqlb::FieldPtr f(new sqlb::Field(val_name, val_type)); - (*it).table.addField(f); + for(const auto& column : columns) + table->fields.emplace_back(column.first, column.second); } + + object_map.tables.insert({val_name, table}); + } else if(val_type == "index") { + sqlb::IndexPtr index = sqlb::Index::parseSQL(val_sql); + if(!index->fullyParsed()) + index->setName(val_name); + + object_map.indices.insert({val_name, index}); + } else if(val_type == "trigger") { + sqlb::TriggerPtr trigger = sqlb::Trigger::parseSQL(val_sql); + trigger->setName(val_name); + trigger->setOriginalSql(val_sql); + + // For triggers set the name of the table the trigger operates on here because we don't have a parser for trigger statements yet. + trigger->setTable(val_tblname); + + object_map.triggers.insert({val_name, trigger}); } - sqlite3_finalize(vm); - } else{ - lastErrorMessage = tr("could not get types"); } + + return false; + })) + { + qWarning() << tr("could not get list of db objects: %1").arg(sqlite3_errmsg(_db)); } + + return false; + })) + { + qWarning() << tr("could not get list of databases: %1").arg(sqlite3_errmsg(_db)); } + + emit structureUpdated(); } -QString DBBrowserDB::getPragma(const QString& pragma) +QString DBBrowserDB::getPragma(const std::string& pragma) const { - if(!isOpen()) - return ""; - - QString sql = QString("PRAGMA %1").arg(pragma); - sqlite3_stmt* vm; - const char* tail; - QString retval = ""; - - // Get value from DB - int err = sqlite3_prepare_v2(_db, sql.toUtf8(), sql.toUtf8().length(), &vm, &tail); - if(err == SQLITE_OK){ - logSQL(sql, kLogMsg_App); - if(sqlite3_step(vm) == SQLITE_ROW) - retval = QString::fromUtf8((const char *) sqlite3_column_text(vm, 0)); - else - qWarning() << tr("didn't receive any output from pragma %1").arg(pragma); - - sqlite3_finalize(vm); - } else { - qWarning() << tr("could not execute pragma command: %1, %2").arg(err).arg(sqlite3_errmsg(_db)); - } - - // Return it - return retval; + if (pragma=="case_sensitive_like") + return querySingleValueFromDb("SELECT 'x' NOT LIKE 'X';"); + else + return querySingleValueFromDb("PRAGMA " + pragma + ";"); } -bool DBBrowserDB::setPragma(const QString& pragma, const QString& value) +bool DBBrowserDB::setPragma(const std::string& pragma, const QString& value) { // Set the pragma value - QString sql = QString("PRAGMA %1 = \"%2\";").arg(pragma).arg(value); + std::string sql = "PRAGMA " + pragma + " = '" + value.toStdString() + "';"; + + // In general, we want to commit changes before running pragmas because most of them can't be rolled back and some of them + // even fail when run in a transaction. However, the defer_foreign_keys pragma has neither problem and we need it to be settable + // inside transactions (see the renameColumn() function where it is set and reset at some point and where we don't want the changes + // to be committed just because of this pragma). + if(pragma != "defer_foreign_keys") + releaseSavepoint(); - releaseSavepoint(); bool res = executeSQL(sql, false, true); // PRAGMA statements are usually not transaction bound, so we can't revert if( !res ) - qWarning() << tr("Error setting pragma %1 to %2: %3").arg(pragma).arg(value).arg(lastErrorMessage); + qWarning() << tr("Error setting pragma %1 to %2: %3").arg(QString::fromStdString(pragma), value, lastErrorMessage); + + // If this is the page_size or the auto_vacuum pragma being set, we need to execute the vacuum command right after the pragma statement or the new + // settings won't be saved. + if(res && (pragma == "page_size" || pragma == "auto_vacuum")) + res = executeSQL("VACUUM;", false, true); + return res; } -bool DBBrowserDB::setPragma(const QString& pragma, const QString& value, QString& originalvalue) +bool DBBrowserDB::setPragma(const std::string& pragma, const QString& value, QString& originalvalue) { if( originalvalue != value ) { @@ -1247,7 +2149,7 @@ bool DBBrowserDB::setPragma(const QString& pragma, const QString& value, QString return false; } -bool DBBrowserDB::setPragma(const QString& pragma, int value, int& originalvalue) +bool DBBrowserDB::setPragma(const std::string& pragma, int value, int& originalvalue) { if( originalvalue != value ) { @@ -1261,21 +2163,32 @@ bool DBBrowserDB::setPragma(const QString& pragma, int value, int& originalvalue return false; } -bool DBBrowserDB::loadExtension(const QString& filename) +bool DBBrowserDB::loadExtension(const QString& filePath) { - if(!isOpen()) + waitForDbRelease(); + if(!_db) return false; // Check if file exists - if(!QFile::exists(filename)) + if(!QFile::exists(filePath)) { lastErrorMessage = tr("File not found."); return false; } + // Enable extension loading + sqlite3_enable_load_extension(_db, 1); + // Try to load extension char* error; - if(sqlite3_load_extension(_db, filename.toUtf8(), 0, &error) == SQLITE_OK) + int result = sqlite3_load_extension(_db, filePath.toUtf8(), nullptr, &error); + + // Disable extension loading if so configured + // (we don't want to leave the possibility of calling load_extension() from SQL without user informed permission) + if (!Settings::getValue("extensions", "enable_load_extension").toBool()) + sqlite3_enable_load_extension(_db, 0); + + if (result == SQLITE_OK) { return true; } else { @@ -1284,3 +2197,145 @@ bool DBBrowserDB::loadExtension(const QString& filename) return false; } } + + +void DBBrowserDB::loadExtensionsFromSettings() +{ + if(!_db) + return; + + sqlite3_enable_load_extension(_db, Settings::getValue("extensions", "enable_load_extension").toBool()); + + const QStringList list = Settings::getValue("extensions", "list").toStringList(); + for(const QString& ext : list) + { + if(loadExtension(ext) == false) + QMessageBox::warning(nullptr, QApplication::applicationName(), tr("Error loading extension: %1").arg(lastError())); + } + + const QVariantMap builtinList = Settings::getValue("extensions", "builtin").toMap(); + for(const QString& ext : builtinList.keys()) + { + if(builtinList.value(ext).toBool()) + { + if(loadExtension(ext) == false) + QMessageBox::warning(nullptr, QApplication::applicationName(), tr("Error loading built-in extension: %1").arg(lastError())); + } + } +} + +std::vector> DBBrowserDB::queryColumnInformation(const std::string& schema_name, const std::string& object_name) const +{ + waitForDbRelease(); + + std::vector> result; + std::string statement = "PRAGMA " + sqlb::escapeIdentifier(schema_name) + ".TABLE_INFO(" + sqlb::escapeIdentifier(object_name) + ");"; + logSQL(QString::fromStdString(statement), kLogMsg_App); + + sqlite3_stmt* vm; + const char* tail; + if(sqlite3_prepare_v2(_db, statement.c_str(), static_cast(statement.size()), &vm, &tail) == SQLITE_OK) + { + while(sqlite3_step(vm) == SQLITE_ROW) + { + std::string name = reinterpret_cast(sqlite3_column_text(vm, 1)); + std::string type = reinterpret_cast(sqlite3_column_text(vm, 2)); + + result.push_back(std::make_pair(name, type)); + } + sqlite3_finalize(vm); + } else{ + lastErrorMessage = tr("could not get column information"); + } + + return result; +} + +const sqlb::TablePtr DBBrowserDB::getTableByName(const sqlb::ObjectIdentifier& name) const +{ + if(schemata.empty() || name.schema().empty() || name.name().empty()) + return sqlb::TablePtr{}; + + const auto schemaIt = findCaseInsensitive(schemata, name.schema()); + if(schemaIt == schemata.end()) + return sqlb::TablePtr{}; + + const auto& tables = schemaIt->second.tables; + if(tables.empty()) + return sqlb::TablePtr{}; + + const auto tableIt = findCaseInsensitive(tables, name.name()); + if(tableIt == tables.end()) + return sqlb::TablePtr{}; + + return tableIt->second; +} + +const sqlb::IndexPtr DBBrowserDB::getIndexByName(const sqlb::ObjectIdentifier& name) const +{ + if(schemata.empty() || name.schema().empty() || name.name().empty()) + return sqlb::IndexPtr{}; + + const auto schemaIt = findCaseInsensitive(schemata, name.schema()); + if(schemaIt == schemata.end()) + return sqlb::IndexPtr{}; + + const auto& indices = schemaIt->second.indices; + if(indices.empty()) + return sqlb::IndexPtr{}; + + const auto indexIt = findCaseInsensitive(indices, name.name()); + if(indexIt == indices.end()) + return sqlb::IndexPtr{}; + + return indexIt->second; +} + +const sqlb::TriggerPtr DBBrowserDB::getTriggerByName(const sqlb::ObjectIdentifier& name) const +{ + if(schemata.empty() || name.schema().empty() || name.name().empty()) + return sqlb::TriggerPtr{}; + + const auto schemaIt = findCaseInsensitive(schemata, name.schema()); + if(schemaIt == schemata.end()) + return sqlb::TriggerPtr{}; + + const auto& triggers = schemaIt->second.triggers; + if(triggers.empty()) + return sqlb::TriggerPtr{}; + + const auto triggerIt = findCaseInsensitive(triggers, name.name()); + if(triggerIt == triggers.end()) + return sqlb::TriggerPtr{}; + + return triggerIt->second; +} + +std::string DBBrowserDB::generateSavepointName(const std::string& identifier) const +{ + // Generate some sort of unique name for a savepoint for internal use. + return "db4s_" + identifier + "_" + std::to_string(std::chrono::system_clock::now().time_since_epoch().count()); +} + +std::string DBBrowserDB::generateTemporaryTableName(const std::string& schema) const +{ + // We're using a static variable as a counter here instead of checking from the beginning onwards every time. This has + // two reasons: 1) It makes the function thread-safe, and 2) it saves us some time because in case older temporary tables + // are still in use. Both reasons don't matter too much for now, but just in case... + static std::atomic_uint counter; + + while(true) + { + std::string table_name = "sqlb_temp_table_" + std::to_string(++counter); + if(!getTableByName(sqlb::ObjectIdentifier(schema, table_name))) + return table_name; + } +} + +void DBBrowserDB::interruptQuery() +{ + if(!_db) + return; + + sqlite3_interrupt(_db); +} diff --git a/src/sqlitedb.h b/src/sqlitedb.h index d4b640408..284ce3411 100644 --- a/src/sqlitedb.h +++ b/src/sqlitedb.h @@ -1,142 +1,324 @@ #ifndef SQLITEDB_H #define SQLITEDB_H -#include "sqlitetypes.h" +#include "sql/ObjectIdentifier.h" +#include "sql/sqlitetypes.h" -#include -#include +#include +#include +#include +#include +#include +#include + +#include #include +#include struct sqlite3; -class CipherDialog; +class CipherSettings; -enum +enum LogMessageType { kLogMsg_User, - kLogMsg_App + kLogMsg_App, + kLogMsg_ErrorLog }; -typedef QMultiMap objectMap; - -class DBBrowserObject +struct objectMap { -public: - DBBrowserObject() : table(""), name( "" ) { } - DBBrowserObject( const QString& wname,const QString& wsql, const QString& wtype, const QString& tbl_name ) - : table(wname), name( wname), sql( wsql ), type(wtype), table_name(tbl_name) - { } - - QString getname() const { return name; } - QString getsql() const { return sql; } - QString gettype() const { return type; } - QString getTableName() const { return table_name; } - sqlb::Table table; -private: - QString name; - QString sql; - QString type; - QString table_name; // The name of the table this object references, interesting for views, triggers and indices + // These map from object name to object pointer + std::map tables; // This stores tables AND views + std::map indices; + std::map triggers; + + bool empty() const + { + return tables.empty() && indices.empty() && triggers.empty(); + } }; +using schemaMap = std::map; // Maps from the schema name (main, temp, attached schemas) to the object map for that schema + +int collCompare(void* pArg, int sizeA, const void* sA, int sizeB, const void* sB); + +namespace sqlb +{ +QString escapeIdentifier(const QString& id); +QString escapeString(const QString& literal); +QString escapeByteArray(const QByteArray& literal); +} + +/// represents a single SQLite database. except when noted otherwise, +/// all member functions are to be called from the main UI thread +/// only. class DBBrowserDB : public QObject { Q_OBJECT +private: + /// custom unique_ptr deleter releases database for further use by others + struct DatabaseReleaser + { + explicit DatabaseReleaser(DBBrowserDB * pParent_ = nullptr) : pParent(pParent_) {} + + DBBrowserDB * pParent; + + void operator() (const sqlite3* db) const + { + if(!db || !pParent) + return; + + std::unique_lock lk(pParent->m); + pParent->db_used = false; + lk.unlock(); + emit pParent->databaseInUseChanged(false, QString()); + pParent->cv.notify_one(); + } + }; + public: - explicit DBBrowserDB () : _db(0), isEncrypted(false), isReadOnly(false) {} - virtual ~DBBrowserDB (){} - bool open ( const QString & db); - bool attach(const QString& filename, QString attach_as = ""); + + explicit DBBrowserDB(); + ~DBBrowserDB () override = default; + + bool open(const QString& db, bool readOnly = false); + bool attach(const QString& filename, QString attach_as = QString()); + + /** + detaches a previously attached database identified with its alias-name + + \param attached_as the alias-name as witch a additional database file has been attached to the connection + **/ + bool detach(const std::string& attached_as); bool create ( const QString & db); bool close(); - bool setSavepoint(const QString& pointname = "RESTOREPOINT"); - bool releaseSavepoint(const QString& pointname = "RESTOREPOINT"); - bool revertToSavepoint(const QString& pointname = "RESTOREPOINT"); + bool saveAs(const std::string& filename); + + // This returns the SQLite version as well as the SQLCipher if DB4S is compiled with encryption support + static void getSqliteVersion(QString& sqlite, QString& sqlcipher); + + using db_pointer_type = std::unique_ptr; + + /** + borrow exclusive address to the currently open database, until + releasing the returned unique_ptr. + + the intended use case is that the main UI thread can call this + any time, and then optionally pass the obtained pointer to a + background worker, or release it after doing work immediately. + + if database is currently used by somebody else, opens a dialog + box and gives user the opportunity to sqlite3_interrupt() the + operation of the current owner, then tries again. + + \param user a string that identifies the new user, and which + can be displayed in the dialog box. + + \param force_wait if set to true we won't ask the user to cancel + the running query but just wait until it is done. + + \returns a unique_ptr containing the SQLite database handle, or + nullptr in case no database is open. + **/ + db_pointer_type get (const QString& user, bool force_wait = false); + + bool setSavepoint(const std::string& pointname = "RESTOREPOINT", bool unique = true); + bool releaseSavepoint(const std::string& pointname = "RESTOREPOINT"); + bool revertToSavepoint(const std::string& pointname = "RESTOREPOINT"); bool releaseAllSavepoints(); bool revertAll(); - bool dump(const QString & filename, const QStringList &tablesToDump, bool insertColNames, bool insertNew, bool exportSchema, bool exportData); - bool executeSQL ( const QString & statement, bool dirtyDB=true, bool logsql=true); - bool executeMultiSQL(const QString& statement, bool dirty = true, bool log = false); + + // Set a non-unique savepoint for the general undoing mechanism (undoing only last write). + bool setUndoSavepoint() { return setSavepoint("UNDOPOINT", /* unique */ false); }; + bool revertToUndoSavepoint() { return revertToSavepoint("UNDOPOINT"); }; + bool releaseUndoSavepoint() { return releaseSavepoint("UNDOPOINT"); }; + + bool dump(const QString& filename, const std::vector& tablesToDump, + bool insertColNames, bool insertNew, bool keepOriginal, bool exportSchema, bool exportData, bool keepOldSchema) const; + + enum ChoiceOnUse + { + Ask, + Wait, + CancelOther + }; + // Callback to get results from executeSQL(). It is invoked for + // each result row coming out of the evaluated SQL statements. If + // a callback returns true (abort), the executeSQL() method + // returns false (error) without invoking the callback again and + // without running any subsequent SQL statements. The 1st argument + // is the number of columns in the result. The 2nd argument to the + // callback is the text representation of the values, one for each + // column. The 3rd argument is a list of strings where each entry + // represents the name of corresponding result column. + using execCallback = std::function, std::vector)>; + bool executeSQL(const std::string& statement, bool dirtyDB = true, bool logsql = true, execCallback callback = nullptr); + bool executeMultiSQL(QByteArray query, bool dirty = true, bool log = false); + QByteArray querySingleValueFromDb(const std::string& sql, bool log = true, ChoiceOnUse choice = Ask) const; + + const QString& lastError() const { return lastErrorMessage; } /** * @brief getRow Executes a sqlite statement to get the rowdata(columns) * for the given rowid. + * @param schemaName Name of the database schema. * @param sTableName Table to query. * @param rowid The rowid to fetch. * @param rowdata A list of QByteArray containing the row data. * @return true if statement execution was ok, else false. */ - bool getRow(const QString& sTableName, const QString& rowid, QList& rowdata); + bool getRow(const sqlb::ObjectIdentifier& table, const QString& rowid, std::vector& rowdata) const; + + /** + * @brief Interrupts the currently running statement as soon as possible. + */ + void interruptQuery(); +private: /** * @brief max Queries the table t for the max value of field. - * @param t Table to query - * @param field Field to get the max value + * @param tableName Table to query + * @param field Name of the field to get the max value * @return the max value of the field or 0 on error */ - QString max(const sqlb::Table& t, sqlb::FieldPtr field) const; + unsigned long max(const sqlb::ObjectIdentifier& tableName, const std::string& field) const; + + static int callbackWrapper (void* callback, int numberColumns, char** values, char** columnNames); - void updateSchema(); - QString addRecord(const QString& sTableName); +public: + void updateSchema(); // Please don't call this from threads other than the main thread. +private: /** * @brief Creates an empty insert statement. + * @param schemaName The name of the database schema in which to find the table * @param pk_value This optional parameter can be used to manually set a specific value for the primary key column * @return An sqlite conform INSERT INTO statement with empty values. (NULL,'',0) */ - QString emptyInsertStmt(const sqlb::Table& t, const QString& pk_value = QString()) const; - bool deleteRecord(const QString& table, const QString& rowid); - bool updateRecord(const QString& table, const QString& column, const QString& rowid, const QByteArray& value, bool itsBlob); + std::string emptyInsertStmt(const std::string& schemaName, const sqlb::Table& t, const QString& pk_value = QString()) const; + +public: + QString addRecord(const sqlb::ObjectIdentifier& tablename); + bool deleteRecords(const sqlb::ObjectIdentifier& table, const std::vector& rowids, const sqlb::StringVector& pseudo_pk = {}); + bool updateRecord(const sqlb::ObjectIdentifier& table, const std::string& column, const QByteArray& rowid, const QByteArray& value, int force_type = 0, const sqlb::StringVector& pseudo_pk = {}); - bool createTable(const QString& name, const sqlb::FieldVector& structure); - bool renameTable(const QString& from_table, const QString& to_table); - bool addColumn(const QString& table, const sqlb::FieldPtr& field); + bool createTable(const sqlb::ObjectIdentifier& name, const sqlb::FieldVector& structure); + bool renameTable(const std::string& schema, const std::string& from_table, const std::string& to_table); + bool addColumn(const sqlb::ObjectIdentifier& tablename, const sqlb::Field& field); /** - * @brief renameColumn Can be used to rename, modify or drop an existing column of a given table - * @param tablename Specifies the table name - * @param name Name of the column to edit - * @param to The new field definition with changed name, type or the like. If Null-Pointer is given the column is dropped. - * @param move Set this to a value != 0 to move the new column to a different position + * @brief This type maps from old column names to new column names. Given the old and the new table definition, this suffices to + * track fields between the two. + * USE CASES: + * 1) Don't specify a column at all or specify equal column names: Keep its name as-is. + * 2) Specify different column names: Rename the field. + * 3) Map from an existing column name to a Null string: Delete the column. + * 4) Map from a Null column name to a new column name: Add the column. + */ + using AlterTableTrackColumns = std::map; + + /** + * @brief alterTable Can be used to rename, modify or drop existing columns of a given table + * @param tablename Specifies the schema and name of the table to edit + * @param new_table Specifies the new table schema. This is exactly how the new table is going to look like. + * @param track_columns Maps old column names to new column names. This is used to copy the data from the old table to the new one. + * @param newSchema Set this to a non-empty string to move the table to a new schema * @return true if renaming was successful, false if not. In the latter case also lastErrorMessage is set */ - bool renameColumn(const QString& tablename, const QString& name, sqlb::FieldPtr to, int move = 0); + bool alterTable(const sqlb::ObjectIdentifier& tablename, const sqlb::Table& new_table, AlterTableTrackColumns track_columns, std::string newSchemaName = std::string()); + + // Given that sqlite3 does not allow case-differing identifiers, and in some + // situations the stored name in `schemata` may differ only in case from the name used in + // the stored SQL create statement (like issue #4110), the search of these get*Name + // functions is case-insensitive, if not found as is. + + const sqlb::TablePtr getTableByName(const sqlb::ObjectIdentifier& name) const; + const sqlb::IndexPtr getIndexByName(const sqlb::ObjectIdentifier& name) const; + const sqlb::TriggerPtr getTriggerByName(const sqlb::ObjectIdentifier& name) const; - objectMap getBrowsableObjects() const; - DBBrowserObject getObjectByName(const QString& name) const; bool isOpen() const; bool encrypted() const { return isEncrypted; } bool readOnly() const { return isReadOnly; } bool getDirty() const; QString currentFile() const { return curDBFilename; } - void logSQL(QString statement, int msgtype); - QString getPragma(const QString& pragma); - bool setPragma(const QString& pragma, const QString& value); - bool setPragma(const QString& pragma, const QString& value, QString& originalvalue); - bool setPragma(const QString& pragma, int value, int& originalvalue); + /// log an SQL statement [thread-safe] + void logSQL(const QString& statement, LogMessageType msgtype) const; + + QString getPragma(const std::string& pragma) const; + bool setPragma(const std::string& pragma, const QString& value); + bool setPragma(const std::string& pragma, const QString& value, QString& originalvalue); + bool setPragma(const std::string& pragma, int value, int& originalvalue); + + // These are the two pragmas in SQLite which require values passed as text. + // Values follow the order of the SQLite documentation. + // Use these values for setPragma(). + static const QStringList journalModeValues; + static const QStringList lockingModeValues; bool loadExtension(const QString& filename); + void loadExtensionsFromSettings(); - sqlite3 * _db; + static QStringList Datatypes; + static QStringList DatatypesStrict; + +private: + std::vector > queryColumnInformation(const std::string& schema_name, const std::string& object_name) const; + +public: + std::string generateSavepointName(const std::string& identifier = std::string()) const; - objectMap objMap; + // This function generates the name for a temporary table. It guarantees that there is no table with this name yet + std::string generateTemporaryTableName(const std::string& schema) const; - QString lastErrorMessage; + schemaMap schemata; signals: - void sqlExecuted(QString sql, int msgtype); + void sqlExecuted(QString sql, int msgtype) const; void dbChanged(bool dirty); + void structureUpdated(); + void requestCollation(QString name, int eTextRep); + void databaseInUseChanged(bool busy, QString user); private: - QString curDBFilename; + /// external code needs to go through get() to obtain access to the database + sqlite3 * _db; + mutable std::mutex m; + mutable std::condition_variable cv; + bool db_used; + QString db_user; - QStringList savepointList; + /// wait for release of the DB locked through a previous get(), + /// giving users the option to discard running task through a + /// message box. + void waitForDbRelease(ChoiceOnUse choice = Ask) const; + QString curDBFilename; + mutable QString lastErrorMessage; + std::vector savepointList; bool isEncrypted; bool isReadOnly; - bool tryEncryptionSettings(const QString& filename, bool* encrypted, CipherDialog*& cipherSettings); + sqlb::StringVector primaryKeyForEditing(const sqlb::ObjectIdentifier& table, const sqlb::StringVector& pseudo_pk) const; + + // SQLite Callbacks + void collationNeeded(void* pData, sqlite3* db, int eTextRep, const char* sCollationName); + void errorLogCallback(void* user_data, int error_code, const char* message); + + bool tryEncryptionSettings(const QString& filename, bool* encrypted, CipherSettings* cipherSettings) const; + + bool disableStructureUpdateChecks; + + class NoStructureUpdateChecks + { + public: + explicit NoStructureUpdateChecks(DBBrowserDB& db) : m_db(db) { m_db.disableStructureUpdateChecks = true; } + ~NoStructureUpdateChecks() { m_db.disableStructureUpdateChecks = false; } + + private: + DBBrowserDB& m_db; + }; }; #endif diff --git a/src/sqlitetablemodel.cpp b/src/sqlitetablemodel.cpp index cdba79ea0..1e01b2ca0 100644 --- a/src/sqlitetablemodel.cpp +++ b/src/sqlitetablemodel.cpp @@ -1,240 +1,329 @@ -#include "sqlitetablemodel.h" +#include "sqlitetablemodel.h" #include "sqlitedb.h" #include "sqlite.h" +#include "Settings.h" +#include "Data.h" +#include "CondFormat.h" +#include "RowLoader.h" -#include "PreferencesDialog.h" -#include #include #include #include #include #include #include +#include +#include +#include +#include -SqliteTableModel::SqliteTableModel(QObject* parent, DBBrowserDB* db, size_t chunkSize, const QString& encoding) +#include + +SqliteTableModel::SqliteTableModel(DBBrowserDB& db, QObject* parent, const QString& encoding, bool force_wait) : QAbstractTableModel(parent) , m_db(db) - , m_rowCount(0) - , m_chunkSize(chunkSize) - , m_valid(false) + , m_lifeCounter(0) + , m_currentRowCount(0) + , m_realRowCount(0) , m_encoding(encoding) { + // Load initial settings first + reloadSettings(); + + worker = new RowLoader( + [this, force_wait](){ return m_db.get(tr("reading rows"), force_wait); }, + [this](QString stmt){ return m_db.logSQL(stmt, kLogMsg_App); }, + m_headers, m_mutexDataCache, m_cache + ); + + worker->start(); + + // any UI updates must be performed in the UI thread, not in the worker thread: + connect(worker, &RowLoader::fetched, this, &SqliteTableModel::handleFinishedFetch, Qt::QueuedConnection); + connect(worker, &RowLoader::rowCountComplete, this, &SqliteTableModel::handleRowCountComplete, Qt::QueuedConnection); + reset(); } -void SqliteTableModel::reset() +SqliteTableModel::~SqliteTableModel() { - m_iSortColumn = 0; - m_sSortOrder = "ASC"; - m_headers.clear(); - m_mWhere.clear(); - m_vDataTypes.clear(); - m_vDisplayFormat.clear(); + worker->stop(); + worker->wait(); + worker->disconnect(); + delete worker; } -void SqliteTableModel::setChunkSize(size_t chunksize) +SqliteTableModel::RowCount SqliteTableModel::rowCountAvailable () const { - m_chunkSize = chunksize; + return m_rowCountAvailable; } -void SqliteTableModel::setTable(const QString& table, const QVector& display_format) +void SqliteTableModel::handleFinishedFetch (int life_id, unsigned int fetched_row_begin, unsigned int fetched_row_end) { - reset(); + if(life_id < m_lifeCounter) + return; - m_sTable = table; - m_vDisplayFormat = display_format; + Q_ASSERT(fetched_row_end >= fetched_row_begin); - m_vDataTypes.push_back(SQLITE_INTEGER); + auto old_row_count = m_currentRowCount; + auto new_row_count = std::max(old_row_count, fetched_row_begin); + new_row_count = std::max(new_row_count, fetched_row_end); + Q_ASSERT(new_row_count >= old_row_count); - bool allOk = false; - if(m_db->getObjectByName(table).gettype() == "table") + if(new_row_count != old_row_count) { - sqlb::Table t = sqlb::Table::parseSQL(m_db->getObjectByName(table).getsql()).first; - if(t.fields().size()) // parsing was OK - { - m_headers.push_back(t.rowidColumn()); - m_headers.append(t.fieldNames()); - - // parse columns types - static QStringList dataTypes = QStringList() - << "INTEGER" - << "REAL" - << "TEXT" - << "BLOB"; - foreach(const sqlb::FieldPtr fld, t.fields()) - { - QString name(fld->type().toUpper()); - int colType = dataTypes.indexOf(name); - colType = (colType == -1) ? SQLITE_TEXT : colType + 1; - m_vDataTypes.push_back(colType); - } - allOk = true; - } + beginInsertRows(QModelIndex(), static_cast(old_row_count), static_cast(new_row_count - 1)); + m_currentRowCount = new_row_count; + endInsertRows(); } - if(!allOk) + if(fetched_row_end != fetched_row_begin) { - QString sColumnQuery = QString::fromUtf8("SELECT * FROM %1;").arg(sqlb::escapeIdentifier(table)); - m_headers.push_back("rowid"); - m_headers.append(getColumns(sColumnQuery, m_vDataTypes)); + // TODO optimize + size_t num_columns = m_headers.size(); + emit dataChanged(createIndex(static_cast(fetched_row_begin), 0), createIndex(static_cast(fetched_row_end) - 1, static_cast(num_columns) - 1)); } - buildQuery(); -} + if(m_rowCountAvailable != RowCount::Complete) + m_rowCountAvailable = RowCount::Partial; -namespace { -QString rtrimChar(const QString& s, QChar c) { - QString r = s.trimmed(); - while(r.endsWith(c)) - r.chop(1); - return r; + emit finishedFetch(static_cast(fetched_row_begin), static_cast(fetched_row_end)); } -QString removeComments(QString s) +void SqliteTableModel::handleRowCountComplete (int life_id, int num_rows) { - // Feel free to fix all the bugs this probably contains or just replace this function entirely by - // a 'simple' regular expression. I know there're better ways to do this... - - // This function removes any single line comments (starting with '--') from a given string. It does - // so by going through the string character by character and trying to keep track of whether we currently - // are in a string or identifier and only removing those parts starting with '--' which are in neither. - - QChar lastChar = 0; - QList stringChars; - for(int i=0; i < s.length(); ++i) - { - if(lastChar != '\\' && (s.at(i) == '\'' || s.at(i) == '"' || s.at(i) == '`')) - { - if(!stringChars.empty() && stringChars.last() == s.at(i)) - stringChars.removeLast(); - else if(!(!stringChars.empty() && (stringChars.last() != '\'' || stringChars.last() != '"')) || stringChars.empty()) - stringChars.push_back(s.at(i)); - } else if(stringChars.empty() && s.at(i) == '-' && lastChar == '-') { - int nextNL = s.indexOf('\n', i); - if(nextNL >= 0) - return removeComments(s.remove(i-1, nextNL - i + 2)); - else - return s.left(i-1); - } + if(life_id < m_lifeCounter) + return; - lastChar = s.at(i); + m_realRowCount = static_cast(num_rows); + if (num_rows > m_rowsLimit) { + num_rows = m_rowsLimit; } - return s; -} + m_rowCountAvailable = RowCount::Complete; + handleFinishedFetch(life_id, static_cast(num_rows), static_cast(num_rows)); + + emit finishedRowCount(); } -void SqliteTableModel::setQuery(const QString& sQuery, bool dontClearHeaders) +void SqliteTableModel::reset() { - // clear - if(!dontClearHeaders) - reset(); + beginResetModel(); - if(!m_db->isOpen()) - return; + clearCache(); + m_sQuery.clear(); + m_query.clear(); + m_table_of_query.reset(); + m_headers.clear(); + m_vDataTypes.clear(); + m_mCondFormats.clear(); + m_mRowIdFormats.clear(); + + endResetModel(); +} - m_sQuery = removeComments(sQuery).trimmed(); +void SqliteTableModel::setQuery(const sqlb::Query& query) +{ + // Unset all previous settings. When setting a table all information on the previously browsed data set is removed first. + reset(); - // do a count query to get the full row count in a fast manner - m_rowCount = getQueryRowCount(); - if(m_rowCount == -1) + // Save the query + m_query = query; + + // Set the row id columns + m_table_of_query = m_db.getTableByName(query.table()); + if(!m_table_of_query->isView()) { - m_valid = false; - return; + // It is a table + m_query.setRowIdColumns(m_table_of_query->rowidColumns()); + } else { + // It is a view + if(m_query.rowIdColumns().empty()) + m_query.setRowIdColumn("_rowid_"); } + m_vDataTypes.emplace_back(SQLITE_INTEGER); // TODO This is not necessarily true for tables without ROWID or with multiple PKs + m_headers.push_back(sqlb::joinStringVector(m_query.rowIdColumns(), ",")); - // headers - if(!dontClearHeaders) + // Store field names and affinity data types + for(const auto& fld : m_table_of_query->fields) { - m_headers.append(getColumns(sQuery, m_vDataTypes)); + m_headers.push_back(fld.name()); + m_vDataTypes.push_back(fld.affinity()); } - // now fetch the first entries - clearCache(); - fetchData(0, m_chunkSize); - m_valid = true; + // Tell the query object about the column names + m_query.setColumnNames(m_headers); - emit layoutChanged(); + // Apply new query and update view + updateAndRunQuery(); } -int SqliteTableModel::getQueryRowCount() +void SqliteTableModel::setQuery(const QString& sQuery) { - // Return -1 if there is an error - int retval = -1; + // Reset + reset(); - // Use a different approach of determining the row count when a EXPLAIN or a PRAGMA statement is used because a COUNT fails on these queries - if(m_sQuery.startsWith("EXPLAIN", Qt::CaseInsensitive) || m_sQuery.startsWith("PRAGMA", Qt::CaseInsensitive)) - { - // So just execute the statement as it is and fetch all results counting the rows - sqlite3_stmt* stmt; - QByteArray utf8Query = m_sQuery.toUtf8(); - if(sqlite3_prepare_v2(m_db->_db, utf8Query, utf8Query.size(), &stmt, NULL) == SQLITE_OK) - { - retval = 0; - while(sqlite3_step(stmt) == SQLITE_ROW) - retval++; - sqlite3_finalize(stmt); - - // Return the results but also set the chunk size the number of rows to prevent the lazy population mechanism to kick in as using LIMIT - // fails on this kind of queries as well - m_chunkSize = retval; - return retval; - } - } else { - // If it is a normal query - hopefully starting with SELECT - just do a COUNT on it and return the results - QString sCountQuery = QString("SELECT COUNT(*) FROM (%1);").arg(rtrimChar(m_sQuery, ';')); - m_db->logSQL(sCountQuery, kLogMsg_App); - QByteArray utf8Query = sCountQuery.toUtf8(); - - sqlite3_stmt* stmt; - int status = sqlite3_prepare_v2(m_db->_db, utf8Query, utf8Query.size(), &stmt, NULL); - if(status == SQLITE_OK) - { - status = sqlite3_step(stmt); - if(status == SQLITE_ROW) - { - QString sCount = QString::fromUtf8((const char*)sqlite3_column_text(stmt, 0)); - retval = sCount.toInt(); - } - sqlite3_finalize(stmt); - } else { - qWarning() << "Count query failed: " << sCountQuery; - } - } + m_sQuery = sQuery.trimmed(); + removeCommentsFromQuery(m_sQuery); - return retval; + getColumnNames(sQuery.toStdString()); + + worker->setQuery(m_sQuery, QString()); + + // now fetch the first entries + triggerCacheLoad(static_cast(m_chunkSize / 2) - 1); + + emit layoutChanged(); } int SqliteTableModel::rowCount(const QModelIndex&) const { - return m_data.size(); // current fetched row count + return static_cast(m_currentRowCount); } -int SqliteTableModel::totalRowCount() const +int SqliteTableModel::realRowCount() const { - return m_rowCount; + return static_cast(m_realRowCount); } int SqliteTableModel::columnCount(const QModelIndex&) const { - return m_headers.size(); + return static_cast(m_headers.size()); +} + +size_t SqliteTableModel::filterCount() const +{ + return m_query.where().size(); +} + +// Convert a number to string using the Unicode superscript characters +template +static QString toSuperScript(T number) +{ + QString superScript = QString::number(number); + superScript.replace("0", "â°"); + superScript.replace("1", "¹"); + superScript.replace("2", "²"); + superScript.replace("3", "³"); + superScript.replace("4", "â´"); + superScript.replace("5", "âµ"); + superScript.replace("6", "â¶"); + superScript.replace("7", "â·"); + superScript.replace("8", "â¸"); + superScript.replace("9", "â¹"); + return superScript; } QVariant SqliteTableModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (role != Qt::DisplayRole) + if (role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::FontRole) + return QVariant(); + + if (orientation == Qt::Vertical && role == Qt::FontRole) return QVariant(); if (orientation == Qt::Horizontal) { + size_t column = static_cast(section); // if we have a VIRTUAL table the model will not be valid, with no header data - if(section < m_headers.size()) - return m_headers.at(section); + if(column < m_headers.size()) { + const std::string plainHeader = m_headers.at(static_cast(section)); + // In the edit role, return a plain column name, but in the display role, add the sort indicator. + switch (role) { + case Qt::EditRole: + return QString::fromStdString(plainHeader); + case Qt::FontRole: { + bool is_pk = false; + bool is_fk = getForeignKeyClause(column-1) != nullptr; + + if (contains(m_query.rowIdColumns(), m_headers.at(column))) { + is_pk = true; + } else if (m_table_of_query) { + auto field = sqlb::findField(m_table_of_query, m_headers.at(column)); + const auto pk = m_table_of_query->primaryKeyColumns(); + is_pk = field != m_table_of_query->fields.end() && contains(pk, field->name()); + } - return QString("%1").arg(section + 1); + QFont font; + font.setUnderline(is_pk); + font.setItalic(is_fk); + return font; + } + default: + QString sortIndicator; + for(size_t i = 0; i < m_query.orderBy().size(); i++) { + const sqlb::OrderBy sortedColumn = m_query.orderBy()[i]; + // Append sort indicator with direction and ordinal number in superscript style + if (sortedColumn.expr == plainHeader) { + sortIndicator = sortedColumn.direction == sqlb::OrderBy::Ascending ? " â–´" : " â–¾"; + if(m_query.orderBy().size() > 1) + sortIndicator.append(toSuperScript(i+1)); + break; + } + } + return QString::fromStdString(plainHeader) + sortIndicator; + } + } + return QString::number(section + 1); } else - return QString("%1").arg(section + 1); + return QString::number(section + 1); +} + +QVariant SqliteTableModel::getMatchingCondFormat(const std::map>& mCondFormats, size_t column, const QString& value, int role) const +{ + if (!mCondFormats.count(column)) + return QVariant(); + + bool isNumber; + value.toDouble(&isNumber); + std::string sql; + + // For each conditional format for this column, + // if the condition matches the current data, return the associated format. + for (const CondFormat& eachCondFormat : mCondFormats.at(column)) { + if (isNumber && !contains(eachCondFormat.sqlCondition(), '\'')) + sql = "SELECT " + value.toStdString() + " " + eachCondFormat.sqlCondition(); + else + sql = "SELECT " + sqlb::escapeString(value.toStdString()) + " " + eachCondFormat.sqlCondition(); + + // Empty filter means: apply format to any row. + // Query the DB for the condition, waiting in case there is a loading in progress. + if (eachCondFormat.filter().isEmpty() || m_db.querySingleValueFromDb(sql, false, DBBrowserDB::Wait) == "1") + switch (role) { + case Qt::ForegroundRole: + return eachCondFormat.foregroundColor(); + case Qt::BackgroundRole: + return eachCondFormat.backgroundColor(); + case Qt::FontRole: + return eachCondFormat.font(); + case Qt::TextAlignmentRole: + return static_cast(eachCondFormat.alignmentFlag() | Qt::AlignVCenter); + } + } + return QVariant(); +} + +QVariant SqliteTableModel::getMatchingCondFormat(size_t row, size_t column, const QString& value, int role) const +{ + QVariant format; + // Check first for a row-id format and when there is none, for a conditional format. + if (m_mRowIdFormats.count(column)) + { + std::unique_lock lock(m_mutexDataCache); + const bool row_available = m_cache.count(row); + const QByteArray blank_data(""); + const QByteArray& row_id_data = row_available ? m_cache.at(row).at(0) : blank_data; + lock.unlock(); + + format = getMatchingCondFormat(m_mRowIdFormats, column, row_id_data, role); + if (format.isValid()) + return format; + } + if (m_mCondFormats.count(column)) + return getMatchingCondFormat(m_mCondFormats, column, value, role); + else + return QVariant(); } QVariant SqliteTableModel::data(const QModelIndex &index, int role) const @@ -242,60 +331,158 @@ QVariant SqliteTableModel::data(const QModelIndex &index, int role) const if (!index.isValid()) return QVariant(); - if (index.row() >= m_rowCount) + if (index.row() >= rowCount()) return QVariant(); - if(role == Qt::DisplayRole || role == Qt::EditRole) + std::unique_lock lock(m_mutexDataCache); + + const size_t row = static_cast(index.row()); + const size_t column = static_cast(index.column()); + + const bool row_available = m_cache.count(row); + const QByteArray blank_data(""); + const QByteArray& data = row_available ? m_cache.at(row).at(column) : blank_data; + + if(role == Qt::DisplayRole) { - // If this row is not in the cache yet get it first - while(index.row() >= m_data.size() && canFetchMore()) - const_cast(this)->fetchMore(); // Nothing evil to see here, move along - - if(role == Qt::DisplayRole && m_data.at(index.row()).at(index.column()).left(1024).contains('\0')) - return "BLOB"; - else if(role == Qt::DisplayRole && m_data.at(index.row()).at(index.column()).isNull()) - return PreferencesDialog::getSettingsValue("databrowser", "null_text").toString(); - else - return decode(m_data.at(index.row()).at(index.column())); + if(!row_available) + return tr("loading..."); + if(data.isNull()) + { + return m_nullText; + } else if(isBinary(data)) { + return m_blobText; + } else { + if (data.length() > m_symbolLimit) { + // Add "..." to the end of truncated strings + return decode(data.left(m_symbolLimit).append(" ...")); + } else { + return decode(data); + } + } + } else if(role == Qt::EditRole) { + if(!row_available || data.isNull()) + return QVariant(); + QVariant decodedData = decode(data); + QVariant convertedData = decodedData; + bool converted = false; + // For the edit role, return the data according to its column type if possible. + if(m_vDataTypes.at(column) == SQLITE_INTEGER && + decodedData.canConvert(QMetaType::LongLong)) { + converted = convertedData.convert(QMetaType::LongLong); + } else if(m_vDataTypes.at(column) == SQLITE_FLOAT && + decodedData.canConvert(QMetaType::Double)) { + converted = convertedData.convert(QMetaType::Double); + } + return converted? convertedData : decodedData; } else if(role == Qt::FontRole) { - QFont font; - if(m_data.at(index.row()).at(index.column()).isNull() || isBinary(index)) + QFont font = m_font; + if(!row_available || data.isNull() || isBinary(data)) font.setItalic(true); + else { + // Unlock before querying from DB + lock.unlock(); + QVariant condFormatFont = getMatchingCondFormat(row, column, data, role); + if (condFormatFont.isValid()) + return condFormatFont; + } return font; - } else if(role == Qt::TextColorRole) { - if(m_data.at(index.row()).at(index.column()).isNull()) - return QColor(PreferencesDialog::getSettingsValue("databrowser", "null_fg_colour").toString()); - else if (isBinary(index)) - return QColor(PreferencesDialog::getSettingsValue("databrowser", "bin_fg_colour").toString()); - return QColor(PreferencesDialog::getSettingsValue("databrowser", "reg_fg_colour").toString()); + } else if(role == Qt::ForegroundRole) { + if(!row_available) + return QColor(100, 100, 100); + if(data.isNull()) + return m_nullFgColour; + else if (isBinary(data)) + return m_binFgColour; + else { + // Unlock before querying from DB + lock.unlock(); + QVariant condFormatColor = getMatchingCondFormat(row, column, data, role); + if (condFormatColor.isValid()) + return condFormatColor; + if (hasDisplayFormat(index)) + return m_formattedFgColour; + } + // Regular case (not null, not binary, no matching conditional format and no display format) + return m_regFgColour; } else if (role == Qt::BackgroundRole) { - if(m_data.at(index.row()).at(index.column()).isNull()) - return QColor(PreferencesDialog::getSettingsValue("databrowser", "null_bg_colour").toString()); - else if (isBinary(index)) - return QColor(PreferencesDialog::getSettingsValue("databrowser", "bin_bg_colour").toString()); - return QColor(PreferencesDialog::getSettingsValue("databrowser", "reg_bg_colour").toString()); + if(!row_available) + return QColor(255, 200, 200); + if(data.isNull()) + return m_nullBgColour; + else if (isBinary(data)) + return m_binBgColour; + else { + // Unlock before querying from DB + lock.unlock(); + QVariant condFormatColor = getMatchingCondFormat(row, column, data, role); + if (condFormatColor.isValid()) + return condFormatColor; + if (hasDisplayFormat(index)) + return m_formattedBgColour; + } + // Regular case (not null, not binary, no matching conditional format and no display format) + return m_regBgColour; } else if(role == Qt::ToolTipRole) { - sqlb::ForeignKeyClause fk = getForeignKeyClause(index.column()-1); - if(fk.isSet()) - return tr("References %1(%2)\nHold Ctrl+Shift and click to jump there").arg(fk.table()).arg(fk.columns().join(",")); - else - return QString(); - } else { - return QVariant(); + auto fk = getForeignKeyClause(column-1); + if(fk) + return tr("References %1(%2)\nHold %3Shift and click to jump there").arg( + QString::fromStdString(fk->table()), + QString::fromStdString(sqlb::joinStringVector(fk->columns(), ",")), + QKeySequence(Qt::CTRL).toString(QKeySequence::NativeText)); + } else if (role == Qt::TextAlignmentRole) { + // Align horizontally according to conditional format or default (left for text and right for numbers) + // Align vertically to the center, which displays better. + lock.unlock(); + QVariant condFormat = getMatchingCondFormat(row, column, data, role); + if (condFormat.isValid()) + return condFormat; + bool isNumber = m_vDataTypes.at(column) == SQLITE_INTEGER || m_vDataTypes.at(column) == SQLITE_FLOAT; + return static_cast((isNumber ? Qt::AlignRight : Qt::AlignLeft) | Qt::AlignVCenter); + } else if(role == Qt::DecorationRole) { + if(!row_available) + return QVariant(); + + if(m_imagePreviewEnabled && !isImageData(data).isNull()) + { + QImage img; + if(img.loadFromData(data)) + return QPixmap::fromImage(img); + } } + + + return QVariant(); } -sqlb::ForeignKeyClause SqliteTableModel::getForeignKeyClause(int column) const +std::shared_ptr SqliteTableModel::getForeignKeyClause(size_t column) const { - DBBrowserObject obj = m_db->getObjectByName(m_sTable); - if(obj.getname().size()) - return obj.table.fields().at(column)->foreignKey(); - else - return sqlb::ForeignKeyClause(); + // No foreign keys when not browsing a table. This usually happens when executing custom SQL statements + // and browsing the result set instead of browsing an entire table. + if(m_query.table().isEmpty()) + return nullptr; + + // Check if database object is a table. If it isn't stop here and don't return a foreign key. + // This happens for views which don't have foreign keys (though we might want to think about + // how we can check for foreign keys in the underlying tables for some purposes like tool tips). + // If it is a table, heck if the column number is in the valid range. + if(m_table_of_query && m_table_of_query->name().size() && column < m_table_of_query->fields.size()) + { + // Note that the rowid column has number -1 here, it can safely be excluded since there will never be a + // foreign key on that column. + + return m_table_of_query->foreignKey({m_table_of_query->fields.at(column).name()}); + } + + return nullptr; } bool SqliteTableModel::setData(const QModelIndex& index, const QVariant& value, int role) { + // Don't even try setting any data if we're not browsing a table, i.e. the model data comes from a custom query + if(!isEditable(index)) + return false; + // This function is for in-place editing. // So, BLOB flag is false every times. return setTypedData(index, false, value, role); @@ -303,26 +490,95 @@ bool SqliteTableModel::setData(const QModelIndex& index, const QVariant& value, bool SqliteTableModel::setTypedData(const QModelIndex& index, bool isBlob, const QVariant& value, int role) { + if(readingData()) { + // can't insert rows while reading data in background + return false; + } + + m_db.setUndoSavepoint(); + if(index.isValid() && role == Qt::EditRole) { + std::unique_lock lock(m_mutexDataCache); + + auto & cached_row = m_cache.at(static_cast(index.row())); + const size_t column = static_cast(index.column()); + QByteArray newValue = encode(value.toByteArray()); - QByteArray oldValue = m_data.at(index.row()).at(index.column()); + QByteArray oldValue = cached_row.at(column); + + // Special handling for integer columns: instead of setting an integer column to an empty string, set it to '0' when it is also + // used in a primary key. Otherwise SQLite will always output an 'datatype mismatch' error. + if(newValue == "" && !newValue.isNull()) + { + if(m_table_of_query) + { + auto field = sqlb::findField(m_table_of_query, m_headers.at(column)); + const auto pk = m_table_of_query->primaryKeyColumns(); + if(contains(pk, field->name()) && field->isInteger()) + newValue = "0"; + } + } // Don't do anything if the data hasn't changed // To differentiate NULL and empty byte arrays, we also compare the NULL flag if(oldValue == newValue && oldValue.isNull() == newValue.isNull()) return true; - if(m_db->updateRecord(m_sTable, m_headers.at(index.column()), m_data[index.row()].at(0), newValue, isBlob)) + // Determine type. If the BLOB flag is set, it's always BLOB. If the affinity data type of the modified column is something numeric, + // we check if the new value is also numeric. In that case we can safely set the data type to INTEGER or FLOAT. In all other cases we + // default to TEXT. + int type = SQLITE_TEXT; + if(isBlob) { - // Only update the cache if this row has already been read, if not there's no need to do any changes to the cache - if(index.row() < m_data.size()) - m_data[index.row()].replace(index.column(), newValue); + type = SQLITE_BLOB; + } else if(m_vDataTypes.at(column) == SQLITE_INTEGER) { + bool ok; + newValue.toLongLong(&ok); + if(ok) + type = SQLITE_INTEGER; + } else if(m_vDataTypes.at(column) == SQLITE_FLOAT) { + bool ok; + newValue.toDouble(&ok); + if(ok) + type = SQLITE_FLOAT; + } - emit(dataChanged(index, index)); + if(m_db.updateRecord(m_query.table(), m_headers.at(column), cached_row.at(0), newValue, type, m_query.rowIdColumns())) + { + cached_row[column] = newValue; + + // After updating the value itself in the cache, we need to check if we need to update the rowid too. + if(contains(m_query.rowIdColumns(), m_headers.at(column))) + { + // When the cached rowid column needs to be updated as well, we need to distinguish between single-column and multi-column primary keys. + // For the former ones, we can just overwrite the existing value with the new value. + // For the latter ones, we need to make a new JSON object of the values of all primary key columns, not just the updated one. + if(m_query.rowIdColumns().size() == 1) + { + cached_row[0] = newValue; + } else { + assert(m_headers.size() == cached_row.size()); + QByteArray output; + for(size_t i=0;i(std::distance(m_headers.begin(), it))]; + output += QByteArray::number(v.size()) + ":" + v; + } + cached_row[0] = output; + } + const QModelIndex& rowidIndex = index.sibling(index.row(), 0); + lock.unlock(); + emit dataChanged(rowidIndex, rowidIndex); + } else { + lock.unlock(); + } + emit dataChanged(index, index); return true; } else { - QMessageBox::warning(0, qApp->applicationName(), tr("Error changing data:\n%1").arg(m_db->lastErrorMessage)); + lock.unlock(); + QMessageBox::warning(nullptr, qApp->applicationName(), tr("Error changing data:\n%1").arg(m_db.lastError())); return false; } } @@ -330,15 +586,16 @@ bool SqliteTableModel::setTypedData(const QModelIndex& index, bool isBlob, const return false; } -bool SqliteTableModel::canFetchMore(const QModelIndex&) const -{ - return m_data.size() < m_rowCount; -} - -void SqliteTableModel::fetchMore(const QModelIndex&) +// Custom display format set? +bool SqliteTableModel::hasDisplayFormat (const QModelIndex& index) const { - int row = m_data.size(); - fetchData(row, row + m_chunkSize); + bool custom_display_format = false; + if(m_query.selectedColumns().size()) + { + if(index.column() > 0) + custom_display_format = m_query.selectedColumns().at(static_cast(index.column())-1).selector != m_query.selectedColumns().at(static_cast(index.column())-1).original_column; + } + return custom_display_format; } Qt::ItemFlags SqliteTableModel::flags(const QModelIndex& index) const @@ -348,304 +605,293 @@ Qt::ItemFlags SqliteTableModel::flags(const QModelIndex& index) const Qt::ItemFlags ret = QAbstractTableModel::flags(index) | Qt::ItemIsDropEnabled; - // Custom display format set? - bool custom_display_format = false; - if(m_vDisplayFormat.size()) - { - // NOTE: This assumes that custom display formats never start and end with a backtick - if(index.column() > 0) - custom_display_format = !(m_vDisplayFormat.at(index.column()-1).startsWith("`") && m_vDisplayFormat.at(index.column()-1).endsWith("`")); - } - - if(!isBinary(index) && !custom_display_format) + if(!isBinary(index) && !hasDisplayFormat(index) && isEditable(index)) ret |= Qt::ItemIsEditable; return ret; } void SqliteTableModel::sort(int column, Qt::SortOrder order) +{ + // Construct a sort order list from this item and forward it to the function to sort by lists + std::vector list; + list.emplace_back(m_headers.at(static_cast(column)), order == Qt::AscendingOrder ? sqlb::OrderBy::Ascending : sqlb::OrderBy::Descending); + sort(list); +} + +void SqliteTableModel::sort(const std::vector& columns) { // Don't do anything when the sort order hasn't changed - if(m_iSortColumn == column && m_sSortOrder == (order == Qt::AscendingOrder ? "ASC" : "DESC")) + if(m_query.orderBy() == columns) return; // Save sort order - if (column >= 0 && column < m_headers.size()) - m_iSortColumn = column; - m_sSortOrder = (order == Qt::AscendingOrder ? "ASC" : "DESC"); + m_query.orderBy() = columns; // Set the new query (but only if a table has already been set - if(m_sTable != "") - buildQuery(); + if(!m_query.table().isEmpty()) + updateAndRunQuery(); +} + +SqliteTableModel::Row SqliteTableModel::makeDefaultCacheEntry () const +{ + Row blank_data; + + for(size_t i=0; i < m_headers.size(); ++i) + blank_data.emplace_back(""); + + return blank_data; +} + +bool SqliteTableModel::readingData() const +{ + return worker->readingData(); } bool SqliteTableModel::insertRows(int row, int count, const QModelIndex& parent) { - QByteArrayList blank_data; - for(int i=0; i < m_headers.size(); ++i) - blank_data.push_back(""); + if(!isEditable()) + return false; - DataType tempList; + if(readingData()) { + // can't insert rows while reading data in background + return false; + } + + const auto blank_data = makeDefaultCacheEntry(); + + std::vector tempList; for(int i=row; i < row + count; ++i) { - QString rowid = m_db->addRecord(m_sTable); + QString rowid = m_db.addRecord(m_query.table()); if(rowid.isNull()) { return false; } - m_rowCount++; - tempList.append(blank_data); - tempList[i - row].replace(0, rowid.toUtf8()); + tempList.emplace_back(blank_data); + tempList.back()[0] = rowid.toUtf8(); // update column with default values - QByteArrayList rowdata; - if( m_db->getRow(m_sTable, rowid, rowdata) ) + Row rowdata; + if(m_db.getRow(m_query.table(), rowid, rowdata)) { - for(int j=1; j < m_headers.size(); ++j) + for(size_t j=1; j < m_headers.size(); ++j) { - tempList[i - row].replace(j, rowdata[j - 1]); + tempList.back()[j] = rowdata[j - 1]; } } } beginInsertRows(parent, row, row + count - 1); - for(int i = 0; i < tempList.size(); ++i) + for(size_t i = 0; i < tempList.size(); ++i) { - m_data.insert(i + row, tempList.at(i)); + m_cache.insert(i + static_cast(row), std::move(tempList.at(i))); + m_currentRowCount++; + m_realRowCount++; } endInsertRows(); + return true; } bool SqliteTableModel::removeRows(int row, int count, const QModelIndex& parent) { - beginRemoveRows(parent, row, row + count - 1); + if(!isEditable()) + return false; + if(readingData()) { + // can't delete rows while reading data in background + return false; + } + + std::vector rowids; for(int i=count-1;i>=0;i--) { - m_db->deleteRecord(m_sTable, m_data.at(row + i).at(0)); - m_data.removeAt(row + i); + if(m_cache.count(static_cast(row+i))) { + rowids.push_back(m_cache.at(static_cast(row + i)).at(0)); + } } - m_rowCount -= count; + bool ok = m_db.deleteRecords(m_query.table(), rowids, m_query.rowIdColumns()); - endRemoveRows(); - return true; + if (ok) { + beginRemoveRows(parent, row, row + count - 1); + + for(int i=count-1;i>=0;i--) + { + m_cache.erase(static_cast(row + i)); + m_currentRowCount--; + m_realRowCount--; + } + + endRemoveRows(); + } + return ok; } -void SqliteTableModel::fetchData(unsigned int from, unsigned to) +QModelIndex SqliteTableModel::dittoRecord(int old_row) { - int currentsize = m_data.size(); + if(!isEditable()) + return QModelIndex(); - QString sLimitQuery; - if(m_sQuery.startsWith("PRAGMA", Qt::CaseInsensitive) || m_sQuery.startsWith("EXPLAIN", Qt::CaseInsensitive)) - { - sLimitQuery = m_sQuery; - } else { - // Remove trailing trailing semicolon - QString queryTemp = rtrimChar(m_sQuery, ';'); + if (!insertRow(rowCount())) + return QModelIndex(); - // If the query ends with a LIMIT statement take it as it is, if not append our own LIMIT part for lazy population - if(queryTemp.contains(QRegExp("LIMIT\\s+.+\\s*((,|\\b(OFFSET)\\b)\\s*.+\\s*)?$", Qt::CaseInsensitive))) - sLimitQuery = queryTemp; - else - sLimitQuery = queryTemp + QString(" LIMIT %1, %2;").arg(from).arg(to-from); - } - m_db->logSQL(sLimitQuery, kLogMsg_App); - QByteArray utf8Query = sLimitQuery.toUtf8(); - sqlite3_stmt *stmt; - int status = sqlite3_prepare_v2(m_db->_db, utf8Query, utf8Query.size(), &stmt, NULL); + size_t firstEditedColumn = 0; + int new_row = rowCount() - 1; - if(SQLITE_OK == status) - { - while(sqlite3_step(stmt) == SQLITE_ROW) - { - QByteArrayList rowdata; - for (int i = 0; i < m_headers.size(); ++i) - { - if(sqlite3_column_type(stmt, i) == SQLITE_NULL) - { - rowdata.append(QByteArray()); - } else { - int bytes = sqlite3_column_bytes(stmt, i); - if(bytes) - rowdata.append(QByteArray(static_cast(sqlite3_column_blob(stmt, i)), bytes)); - else - rowdata.append(QByteArray("")); - } - } - m_data.push_back(rowdata); + const auto pk = m_table_of_query->primaryKeyColumns(); + for (size_t col = 0; col < m_table_of_query->fields.size(); ++col) { + if(pk.empty() || !contains(pk, m_table_of_query->fields.at(col).name())) { + if (!firstEditedColumn) + firstEditedColumn = col + 1; + + QVariant value = data(index(old_row, static_cast(col + 1)), Qt::EditRole); + setData(index(new_row, static_cast(col + 1)), value); } } - sqlite3_finalize(stmt); - // Check if there was any new data - if(m_data.size() > currentsize) - { - beginInsertRows(QModelIndex(), currentsize, m_data.size()-1); - endInsertRows(); - } + return index(new_row, static_cast(firstEditedColumn)); } -void SqliteTableModel::buildQuery() +void SqliteTableModel::updateAndRunQuery() { - QString where; - - if(m_mWhere.size()) - { - where = "WHERE "; - - for(QMap::const_iterator i=m_mWhere.constBegin();i!=m_mWhere.constEnd();++i) - { - QString column; - if(m_vDisplayFormat.size()) - column = QString("col%1").arg(i.key()); - else - column = m_headers.at(i.key()); - where.append(QString("%1 %2 AND ").arg(sqlb::escapeIdentifier(column)).arg(i.value())); - } + clearCache(); - // Remove last 'AND ' - where.chop(4); - } + // Update the query + m_sQuery = QString::fromStdString(m_query.buildQuery(true)); + QString sCountQuery = QString::fromStdString(m_query.buildCountQuery()); + worker->setQuery(m_sQuery, sCountQuery); - QString selector; - if(m_vDisplayFormat.empty()) - { - selector = "*"; - } else { - for(int i=0;i(m_chunkSize / 2) - 1); - // Note: Building the SQL string is intentionally split into several parts here instead of arg()'ing it all together as one. - // The reason is that we're adding '%' characters automatically around search terms (and even if we didn't the user could add - // them manually) which means that e.g. searching for '1' results in another '%1' in the string which then totally confuses - // the QString::arg() function, resulting in an invalid SQL. - QString sql = QString("SELECT %1,%2 FROM %3 ") - .arg(sqlb::escapeIdentifier(m_headers.at(0))) - .arg(selector) - .arg(sqlb::escapeIdentifier(m_sTable)) - + where - + QString("ORDER BY %1 %2") - .arg(sqlb::escapeIdentifier(m_headers.at(m_iSortColumn))) - .arg(m_sSortOrder); - setQuery(sql, true); + emit layoutChanged(); } -QStringList SqliteTableModel::getColumns(const QString& sQuery, QVector& fieldsTypes) +void SqliteTableModel::getColumnNames(const std::string& sQuery) { + auto pDb = m_db.get(tr("retrieving list of columns")); + sqlite3_stmt* stmt; - QByteArray utf8Query = sQuery.toUtf8(); - int status = sqlite3_prepare_v2(m_db->_db, utf8Query, utf8Query.size(), &stmt, NULL); - QStringList listColumns; - if(SQLITE_OK == status) + if(sqlite3_prepare_v2(pDb.get(), sQuery.c_str(), static_cast(sQuery.size()), &stmt, nullptr) == SQLITE_OK) { - sqlite3_step(stmt); - int columns = sqlite3_data_count(stmt); + int columns = sqlite3_column_count(stmt); for(int i = 0; i < columns; ++i) { - listColumns.append(QString::fromUtf8((const char*)sqlite3_column_name(stmt, i))); - fieldsTypes.push_back(sqlite3_column_type(stmt, i)); + m_headers.push_back(sqlite3_column_name(stmt, i)); + m_vDataTypes.push_back(sqlite3_column_type(stmt, i)); } } sqlite3_finalize(stmt); +} - return listColumns; +static void addCondFormatToMap(std::map>& mCondFormats, size_t column, const CondFormat& condFormat) +{ + // If the condition is already present in the vector, update that entry and respect the order, since two entries with the same + // condition do not make sense. + auto it = std::find_if(mCondFormats[column].begin(), mCondFormats[column].end(), [condFormat](const CondFormat& format) { + return format.sqlCondition() == condFormat.sqlCondition(); + }); + // Replace cond-format if present. push it back if it's a conditionless format (apply to every cell in column) or insert + // as first element otherwise. + if(it != mCondFormats[column].end()) { + *it = condFormat; + } else if (condFormat.filter().isEmpty()) + mCondFormats[column].push_back(condFormat); + else + mCondFormats[column].insert(mCondFormats[column].begin(), condFormat); } -void SqliteTableModel::updateFilter(int column, const QString& value) +void SqliteTableModel::addCondFormat(const bool isRowIdFormat, size_t column, const CondFormat& condFormat) { - // Check for any special comparison operators at the beginning of the value string. If there are none default to LIKE. - QString op = "LIKE"; - QString val; - QString escape; - bool numeric = false; - if(value.left(2) == ">=" || value.left(2) == "<=" || value.left(2) == "<>") - { - bool ok; - value.mid(2).toFloat(&ok); - if(ok) - { - op = value.left(2); - val = value.mid(2); - numeric = true; - } - } else if(value.left(1) == ">" || value.left(1) == "<") { - bool ok; - value.mid(1).toFloat(&ok); - if(ok) - { - op = value.left(1); - val = value.mid(1); - numeric = true; - } - } else if(value.left(1) == "=") { - op = "="; - val = value.mid(1); - } else { - // Keep the default LIKE operator - - // Set the escape character if one has been specified in the settings dialog - QString escape_character = PreferencesDialog::getSettingsValue("databrowser", "filter_escape").toString(); - if(escape_character == "'") escape_character = "''"; - if(escape_character.length()) - escape = QString("ESCAPE '%1'").arg(escape_character); - - // Add % wildcards at the start and at the beginning of the filter query, but only if there weren't set any - // wildcards manually. The idea is to assume that a user who's just typing characters expects the wildcards to - // be added but a user who adds them herself knows what she's doing and doesn't want us to mess up her query. - if(!value.contains("%")) - { - val = value; - val.prepend('%'); - val.append('%'); - } - } - if(val.isEmpty()) - val = value; - if(!numeric) - val = QString("'%1'").arg(val.replace("'", "''")); + if(isRowIdFormat) + addCondFormatToMap(m_mRowIdFormats, column, condFormat); + else + addCondFormatToMap(m_mCondFormats, column, condFormat); + emit layoutChanged(); +} + +void SqliteTableModel::setCondFormats(const bool isRowIdFormat, size_t column, const std::vector& condFormats) +{ + if(isRowIdFormat) + m_mRowIdFormats[column] = condFormats; + else + m_mCondFormats[column] = condFormats; + emit layoutChanged(); +} + +void SqliteTableModel::updateFilter(const std::string& column, const QString& value) +{ + std::string whereClause = CondFormat::filterToSqlCondition(value, m_encoding); // If the value was set to an empty string remove any filter for this column. Otherwise insert a new filter rule or replace the old one if there is already one - if(val == "''" || val == "'%'" || val == "'%%'") - m_mWhere.remove(column); + if(whereClause.empty()) + m_query.where().erase(column); else - m_mWhere.insert(column, op + " " + QString(encode(val.toUtf8())) + " " + escape); + m_query.where()[column] = whereClause; + + // Build the new query + updateAndRunQuery(); +} + +void SqliteTableModel::updateGlobalFilter(const std::vector& values) +{ + std::vector filters; + for(auto& v : values) + filters.push_back(CondFormat::filterToSqlCondition(v, m_encoding)); + m_query.setGlobalWhere(filters); // Build the new query - buildQuery(); + updateAndRunQuery(); } void SqliteTableModel::clearCache() { - if(!m_data.empty()) - { - beginRemoveRows(QModelIndex(), 0, m_data.size() - 1); - m_data.clear(); - endRemoveRows(); - } + m_lifeCounter++; + + if(m_db.isOpen()) { + worker->cancel(); + worker->waitUntilIdle(); + } + + if(m_currentRowCount > 0) + { + beginRemoveRows(QModelIndex(), 0, static_cast(m_currentRowCount - 1)); + endRemoveRows(); + } + + m_cache.clear(); + + m_currentRowCount = 0; + m_realRowCount = 0; + m_rowCountAvailable = RowCount::Unknown; } bool SqliteTableModel::isBinary(const QModelIndex& index) const { - return m_vDataTypes.at(index.column()) == SQLITE_BLOB; + std::lock_guard lock(m_mutexDataCache); + + const size_t row = static_cast(index.row()); + if(!m_cache.count(row)) + return false; + + const auto & cached_row = m_cache.at(row); + return isBinary(cached_row.at(static_cast(index.column()))); +} + +bool SqliteTableModel::isBinary(const QByteArray& data) const +{ + return !isTextOnly(data, m_encoding, true); } QByteArray SqliteTableModel::encode(const QByteArray& str) const { - if(m_encoding.isEmpty()) - return str; - else - return QTextCodec::codecForName(m_encoding.toUtf8())->fromUnicode(str); + return encodeString(str, m_encoding); } QByteArray SqliteTableModel::decode(const QByteArray& str) const { - if(m_encoding.isEmpty()) - return str; - else - return QTextCodec::codecForName(m_encoding.toUtf8())->toUnicode(str).toUtf8(); + return decodeString(str, m_encoding); } Qt::DropActions SqliteTableModel::supportedDropActions() const @@ -673,3 +919,260 @@ bool SqliteTableModel::dropMimeData(const QMimeData* data, Qt::DropAction, int r return false; } + +void SqliteTableModel::setPseudoPk(std::vector pseudoPk) +{ + if(!m_table_of_query->isView()) + return; + + if(pseudoPk.empty()) + pseudoPk.emplace_back("_rowid_"); + + // Do nothing if the value didn't change + if(m_query.rowIdColumns() == pseudoPk) + return; + + m_query.setRowIdColumns(pseudoPk); + if(m_headers.size()) + m_headers[0] = sqlb::joinStringVector(pseudoPk, ","); + + updateAndRunQuery(); +} + +bool SqliteTableModel::hasPseudoPk() const +{ + return m_query.hasCustomRowIdColumn(); +} + +bool SqliteTableModel::isEditable(const QModelIndex& index) const +{ + if(m_query.table().isEmpty()) + return false; + if(!m_db.isOpen()) + return false; + if((!m_table_of_query || m_table_of_query->isView()) && !m_query.hasCustomRowIdColumn()) + return false; + + // Extra check when the index parameter is set and pointing to a generated column in a table + if(index.isValid() && m_table_of_query) + { + const auto field = sqlb::findField(m_table_of_query, m_headers.at(static_cast(index.column()))); + if(field != m_table_of_query->fields.cend() && field->generated()) + return false; + } + + return true; +} + +void SqliteTableModel::triggerCacheLoad (int row) const +{ + int halfChunk = static_cast( m_chunkSize / 2); + size_t row_begin = static_cast(std::max(0, row - halfChunk)); + size_t row_end = static_cast(row + halfChunk); + + if(rowCountAvailable() == RowCount::Complete) + { + row_end = std::min(row_end, static_cast(rowCount())); + } else { + // will be truncated by reader + } + + // avoid re-fetching data + std::lock_guard lk(m_mutexDataCache); + m_cache.smallestNonAvailableRange(row_begin, row_end); + + if(row_end != row_begin) + worker->triggerFetch(m_lifeCounter, row_begin, row_end); +} + +void SqliteTableModel::triggerCacheLoad (int row_begin, int row_end) const +{ + if(row_end == row_begin) + return; + + triggerCacheLoad((row_begin + row_end) / 2); +} + +bool SqliteTableModel::completeCache () const +{ + // Show progress dialog because fetching all data might take some time but only show + // cancel button if we allow cancellation here. This isn't + QProgressDialog progress(tr("Fetching data..."), + tr("Cancel"), 0, rowCount()); + + QPushButton* cancelButton = new QPushButton(tr("Cancel")); + // This is to prevent distracted cancellation of the fetching and avoid the + // Snap-To Windows optional feature. + cancelButton->setDefault(false); + cancelButton->setAutoDefault(false); + progress.setCancelButton(cancelButton); + + progress.setWindowModality(Qt::ApplicationModal); + // Disable context help button on Windows + progress.setWindowFlags(progress.windowFlags() + & ~Qt::WindowContextHelpButtonHint); + progress.show(); + + waitUntilIdle(); + + // This loop fetches all data by loading it block by block into the cache + for(int i = 0; i < (rowCount() + static_cast( m_chunkSize / 2)); i += static_cast(m_chunkSize)) + { + progress.setValue(i); + qApp->processEvents(); + if(progress.wasCanceled()) + return false; + + triggerCacheLoad(i); + worker->waitUntilIdle(); + } + + return true; +} + +bool SqliteTableModel::isCacheComplete () const +{ + if(readingData()) + return false; + std::lock_guard lock(m_mutexDataCache); + return m_cache.numSet() == m_currentRowCount; +} + +void SqliteTableModel::waitUntilIdle () const +{ + worker->waitUntilIdle(); +} + +QModelIndex SqliteTableModel::nextMatch(const QModelIndex& start, const std::vector& column_list, const QString& value, Qt::MatchFlags flags, bool reverse, bool dont_skip_to_next_field) const +{ + // Extract flags + bool whole_cell = !(flags & Qt::MatchContains); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) + auto match_flag = Qt::MatchRegExp; +#else + auto match_flag = Qt::MatchRegularExpression; +#endif + bool regex = flags & match_flag; + Qt::CaseSensitivity case_sensitive = ((flags & Qt::MatchCaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive); + bool wrap = flags & Qt::MatchWrap; + int increment = (reverse ? -1 : 1); + + // Prepare the regular expression for regex mode + QRegularExpression reg_exp; + if(regex) + { + reg_exp = QRegularExpression(value, (case_sensitive ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption)); + if(!reg_exp.isValid()) + return QModelIndex(); + + if(whole_cell) + { +#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0) + reg_exp.setPattern("\\A(" + reg_exp.pattern() + ")\\Z"); +#else + reg_exp.setPattern(QRegularExpression::anchoredPattern(reg_exp.pattern())); +#endif + } + } + + // Wait until the row count is there + waitUntilIdle(); + + // Stop right away if there is no data in the table + if(rowCount() == 0) + return QModelIndex(); + + // Make sure the start position starts in a column from the list of columns to search in + QModelIndex pos = start; + if(std::find(column_list.begin(), column_list.end(), pos.column()) == column_list.end()) + { + // If for some weird reason the start index is not in the column list, we simply use the first column of the column list instead + pos = pos.sibling(pos.row(), reverse ? column_list.back() : column_list.front()); + } + + // Get the last cell to search in. If wrapping is enabled, we search until we hit the start cell again. If wrapping is not enabled, we start at the last + // cell of the table. + QModelIndex end = (wrap ? pos : index(rowCount(), column_list.back())); + + // Loop through all cells for the search + while(true) + { + // Go to the next cell and skip all columns in between which we do not care about. This is done as the first step in order + // to skip the start index when matching the first cell is disabled. + if(dont_skip_to_next_field == false) + { + while(true) + { + // Next cell position + int next_row = pos.row(); + int next_column = pos.column() + increment; + + // Have we reached the end of the row? Then go to the next one + if(next_column < 0 || next_column >= static_cast(m_headers.size())) + { + next_row += increment; + next_column = (reverse ? column_list.back() : column_list.front()); + } + + // Have we reached the last row? Then wrap around to the first one + if(wrap && (next_row < 0 || next_row >= rowCount())) + next_row = (reverse ? rowCount()-1 : 0); + + // Set next index for search + pos = pos.sibling(next_row, next_column); + + // Have we hit the last column? We have not found anything then + if(pos == end) + return QModelIndex(); + + // Is this a column which we are supposed to search in? If so, stop looking for the next cell and start comparing + if(std::find(column_list.begin(), column_list.end(), next_column) != column_list.end()) + break; + } + } + + // Make sure the next time we hit the above check, we actuall move on to the next cell and do not skip the loop again. + dont_skip_to_next_field = false; + + // Get row from cache. If it is not in the cache, load the next chunk from the database + const size_t row = static_cast(pos.row()); + if(!m_cache.count(row)) + { + triggerCacheLoad(static_cast(row)); + waitUntilIdle(); + } + const Row* row_data = &m_cache.at(row); + + // Get cell data + const size_t column = static_cast(pos.column()); + QString data = row_data->at(column); + + // Perform comparison + if(whole_cell && !regex && data.compare(value, case_sensitive) == 0) + return pos; + else if(!whole_cell && !regex && data.contains(value, case_sensitive)) + return pos; + else if(regex && reg_exp.match(data).hasMatch()) + return pos; + } +} + +void SqliteTableModel::reloadSettings() +{ + m_nullText = Settings::getValue("databrowser", "null_text").toString(); + m_blobText = Settings::getValue("databrowser", "blob_text").toString(); + m_regFgColour = QColor(Settings::getValue("databrowser", "reg_fg_colour").toString()); + m_regBgColour = QColor(Settings::getValue("databrowser", "reg_bg_colour").toString()); + m_formattedFgColour = QColor(Settings::getValue("databrowser", "formatted_fg_colour").toString()); + m_formattedBgColour = QColor(Settings::getValue("databrowser", "formatted_bg_colour").toString()); + m_nullFgColour = QColor(Settings::getValue("databrowser", "null_fg_colour").toString()); + m_nullBgColour = QColor(Settings::getValue("databrowser", "null_bg_colour").toString()); + m_binFgColour = QColor(Settings::getValue("databrowser", "bin_fg_colour").toString()); + m_binBgColour = QColor(Settings::getValue("databrowser", "bin_bg_colour").toString()); + m_font = QFont(Settings::getValue("databrowser", "font").toString()); + m_font.setPointSize(Settings::getValue("databrowser", "fontsize").toInt()); + m_symbolLimit = Settings::getValue("databrowser", "symbol_limit").toInt(); + m_rowsLimit = Settings::getValue("databrowser", "rows_limit").toInt(); + m_imagePreviewEnabled = Settings::getValue("databrowser", "image_preview").toBool(); + m_chunkSize = static_cast(Settings::getValue("db", "prefetchsize").toUInt()); +} diff --git a/src/sqlitetablemodel.h b/src/sqlitetablemodel.h index c2ce5ce59..b24ca058d 100644 --- a/src/sqlitetablemodel.h +++ b/src/sqlitetablemodel.h @@ -2,83 +2,247 @@ #define SQLITETABLEMODEL_H #include -#include -#include +#include +#include +#include +#include +#include +#include + +#include "RowCache.h" +#include "sql/Query.h" +#include "sql/sqlitetypes.h" + +struct sqlite3; class DBBrowserDB; -namespace sqlb { class ForeignKeyClause; } +class CondFormat; class SqliteTableModel : public QAbstractTableModel { Q_OBJECT + +#ifdef REGEX_UNIT_TEST + friend class TestRegex; +#endif + public: - explicit SqliteTableModel(QObject *parent = 0, DBBrowserDB* db = 0, size_t chunkSize = 50000, const QString& encoding = QString()); + explicit SqliteTableModel(DBBrowserDB& db, QObject *parent = nullptr, const QString& encoding = QString(), bool force_wait = false); + ~SqliteTableModel() override; + + /// reset to state after construction void reset(); - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int totalRowCount() const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); + /// returns logical amount of rows, whether currently cached or not + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int realRowCount() const; + + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + size_t filterCount() const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; bool setTypedData(const QModelIndex& index, bool isBlob, const QVariant& value, int role = Qt::EditRole); - bool canFetchMore(const QModelIndex &parent = QModelIndex()) const; - void fetchMore(const QModelIndex &parent = QModelIndex()); - size_t queryMore(size_t offset); - bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()); - bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()); + enum class RowCount + { + Unknown, //< still finding out in background... + Partial, //< some chunk was read and at least a lower bound is thus known + Complete //< total row count of table known + }; + + /// what kind of information is available through rowCount()? + RowCount rowCountAvailable () const; + + /// trigger asynchronous loading of (at least) the specified row + /// into cache. + void triggerCacheLoad (int single_row) const; + + /// trigger asynchronous loading of (at least) the specified rows + /// into cache. \param row_end is exclusive. + void triggerCacheLoad (int row_begin, int row_end) const; + + /// wait until not reading any data (that does not mean data is + /// complete, just that the background reader is idle) + void waitUntilIdle () const; + + /// load all rows into cache, return when done. Returns true if all data was loaded, false if the loading was cancelled. + bool completeCache() const; + + /// returns true if all rows are currently available in cache + /// [NOTE: potentially unsafe in case we have a limited-size + /// cache, where entries can vanish again -- however we can't do + /// this for the current implementation of the PlotDock] + bool isCacheComplete () const; - void setQuery(const QString& sQuery, bool dontClearHeaders = false); - QString query() const { return m_sQuery; } - void setTable(const QString& table, const QVector &display_format = QVector()); - void setChunkSize(size_t chunksize); - void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); + bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; + bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; - Qt::ItemFlags flags(const QModelIndex& index) const; + QModelIndex dittoRecord(int old_row); - bool valid() const { return m_valid; } + /// configure for browsing results of specified query + void setQuery(const QString& sQuery); + + std::string query() const { return m_sQuery.toStdString(); } + std::string customQuery(bool withRowid) const { return m_query.buildQuery(withRowid); } + + /// configure for browsing specified table + void setQuery(const sqlb::Query& query); + + void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override; + void sort(const std::vector& columns); + sqlb::ObjectIdentifier currentTableName() const { return m_query.table(); } + + Qt::ItemFlags flags(const QModelIndex& index) const override; bool isBinary(const QModelIndex& index) const; - void setEncoding(QString encoding) { m_encoding = encoding; } + void setEncoding(const QString& encoding) { m_encoding = encoding; } QString encoding() const { return m_encoding; } - typedef QList QByteArrayList; + // The pseudo-primary key is exclusively for editing views + void setPseudoPk(std::vector pseudoPk); + bool hasPseudoPk() const; + std::vector pseudoPk() const { return m_query.rowIdColumns(); } + + std::shared_ptr getForeignKeyClause(size_t column) const; + + // This returns true if the model and, if set, the index can be edited. Not specifying the index parameter asks whether the model can + // be edited in general (i.e. inserting and deleting rows as well as updating some cells). Specifying the index parameter asks whether + // this specific index can be edited. + // The model is able to operate in more or less two different modes, table browsing and query browsing. We only support editing data + // in the table browsing mode but not for the query mode. This function returns true if the model is currently editable, i.e. it's + // running in the table mode and isn't browsing a view, unless this view is set up for editing by specifying a pseudo PK. + // When the index parameter is set, the same checks are performed but additionally the function checks whether this specific index + // can be edited. This makes a difference for generated columns which are in (editable) tables but cannot be modified anyway. + bool isEditable(const QModelIndex& index = QModelIndex()) const; - sqlb::ForeignKeyClause getForeignKeyClause(int column) const; + // Custom display format set? + bool hasDisplayFormat (const QModelIndex& index) const; + + // Conditional formats are of two kinds: regular conditional formats (including condition-free formats applying to any value in the + // column) and formats applying to a particular row-id and which have always precedence over the first kind and whose filter apply + // to the row-id column. + void addCondFormat(const bool isRowIdFormat, size_t column, const CondFormat& condFormat); + void setCondFormats(const bool isRowIdFormat, size_t column, const std::vector& condFormats); + + // Search for the specified expression in the given cells. This intended as a replacement for QAbstractItemModel::match() even though + // it does not override it, which - because of the different parameters - is not possible. + // start contains the index to start with, column_list contains the ordered list of the columns to look in, value is the value to search for, + // flags allows to modify the search process (Qt::MatchContains, Qt::MatchRegExp, Qt::MatchCaseSensitive, and Qt::MatchWrap are understood), + // reverse can be set to true to progress through the cells in backwards direction, and dont_skip_to_next_field can be set to true if the current + // cell can be matched as well. + QModelIndex nextMatch(const QModelIndex& start, + const std::vector& column_list, + const QString& value, + Qt::MatchFlags flags = Qt::MatchFlags(Qt::MatchContains), + bool reverse = false, + bool dont_skip_to_next_field = false) const; + + DBBrowserDB& db() { return m_db; } + + void reloadSettings(); public slots: - void updateFilter(int column, const QString& value); + void updateFilter(const std::string& column, const QString& value); + void updateGlobalFilter(const std::vector& values); + +signals: + void finishedFetch(int fetched_row_begin, int fetched_row_end); + void finishedRowCount(); protected: - virtual Qt::DropActions supportedDropActions() const; - virtual bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent); + Qt::DropActions supportedDropActions() const override; + bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; private: - void fetchData(unsigned int from, unsigned to); + friend class RowLoader; + class RowLoader * worker; + + /// clears the cache, resets row-count to unknown (but keeps table + /// & query info), increase life_counter void clearCache(); - void buildQuery(); - QStringList getColumns(const QString& sQuery, QVector& fieldsTypes); - int getQueryRowCount(); + void handleFinishedFetch(int life_id, unsigned int fetched_row_begin, unsigned int fetched_row_end); + void handleRowCountComplete(int life_id, int num_rows); + + void updateAndRunQuery(); + + void getColumnNames(const std::string& sQuery); QByteArray encode(const QByteArray& str) const; QByteArray decode(const QByteArray& str) const; - DBBrowserDB* m_db; - int m_rowCount; - QStringList m_headers; - typedef QList DataType; - DataType m_data; + // Return matching conditional format color/font or invalid value, otherwise. + // Only format roles are expected in role (Qt::ItemDataRole) + QVariant getMatchingCondFormat(size_t row, size_t column, const QString& value, int role) const; + QVariant getMatchingCondFormat(const std::map>& mCondFormats, size_t column, const QString& value, int role) const; + + DBBrowserDB& m_db; + + /// counts numbers of clearCache() since instantiation; using this + /// to avoid processing of queued signals originating in an era + /// before the most recent reset(). + int m_lifeCounter; + + /// note: the row count can be determined by the row-count query + /// (which yields the "final" row count"), or, if it is faster, by + /// the first chunk reading actual data (in which case the row + /// count will be set to that chunk's size and later updated to + /// the full row count, when the row-count query returns) + RowCount m_rowCountAvailable; + unsigned int m_currentRowCount; + unsigned int m_realRowCount; + + std::vector m_headers; + + /// reading something in background right now? (either counting + /// rows or actually loading data, doesn't matter) + bool readingData() const; + + using Row = std::vector; + mutable RowCache m_cache; + + Row makeDefaultCacheEntry () const; + + bool isBinary(const QByteArray& index) const; QString m_sQuery; - QString m_sTable; - int m_iSortColumn; - QString m_sSortOrder; - QMap m_mWhere; - QVector m_vDisplayFormat; - QVector m_vDataTypes; + std::vector m_vDataTypes; + std::map> m_mCondFormats; + std::map> m_mRowIdFormats; + + sqlb::Query m_query; + std::shared_ptr m_table_of_query; // This holds a pointer to the table object which is queried in the m_query object + + QString m_encoding; + + /** + * These are used for multi-threaded population of the table + */ + mutable std::mutex m_mutexDataCache; + +private: + /** + * Settings. These are stored here to avoid fetching and converting them every time we need them. Because this class + * uses a lot of settings and because some of its functions are called very often, this should speed things up noticeable. + * Call reloadSettings() to update these. + */ + + QString m_nullText; + QString m_blobText; + QColor m_regFgColour; + QColor m_regBgColour; + QColor m_formattedFgColour; + QColor m_formattedBgColour; + QColor m_nullFgColour; + QColor m_nullBgColour; + QColor m_binFgColour; + QColor m_binBgColour; + QFont m_font; + int m_symbolLimit; + int m_rowsLimit; + bool m_imagePreviewEnabled; /** * @brief m_chunkSize Size of the next chunk fetch more will try to fetch. @@ -89,10 +253,6 @@ public slots: * to that row count. */ size_t m_chunkSize; - - bool m_valid; //! tells if the current query is valid. - - QString m_encoding; }; -#endif // SQLITETABLEMODEL_H +#endif diff --git a/src/sqlitetypes.cpp b/src/sqlitetypes.cpp deleted file mode 100644 index 02725dffe..000000000 --- a/src/sqlitetypes.cpp +++ /dev/null @@ -1,605 +0,0 @@ -#include "sqlitetypes.h" -#include "grammar/Sqlite3Lexer.hpp" -#include "grammar/Sqlite3Parser.hpp" - -#include -#include - -namespace sqlb { - -QStringList Field::Datatypes = QStringList() << "INTEGER" << "TEXT" << "BLOB" << "REAL" << "NUMERIC"; - -QString escapeIdentifier(QString id) -{ - return '`' + id.replace('`', "``") + '`'; -} - -bool ForeignKeyClause::isSet() const -{ - return m_override.size() || m_table.size(); -} - -QString ForeignKeyClause::toString() const -{ - if(!isSet()) - return QString(); - - if(m_override.size()) - return m_override; - - QString result = escapeIdentifier(m_table); - - if(m_columns.size()) - { - result += "("; - foreach(const QString& column, m_columns) - result += escapeIdentifier(column) + ','; - result.chop(1); // Remove last comma - result += ")"; - } - - if(m_constraint.size()) - result += " " + m_constraint; - - return result; -} - -void ForeignKeyClause::setFromString(const QString& fk) -{ - m_override = fk; -} - -QString Field::toString(const QString& indent, const QString& sep) const -{ - QString str = indent + escapeIdentifier(m_name) + sep + m_type; - if(m_notnull) - str += " NOT NULL"; - if(!m_defaultvalue.isEmpty()) - str += QString(" DEFAULT %1").arg(m_defaultvalue); - if(!m_check.isEmpty()) - str += " CHECK(" + m_check + ")"; - if(m_autoincrement) - str += " PRIMARY KEY AUTOINCREMENT"; - if(m_unique) - str += " UNIQUE"; - return str; -} - -bool Field::isText() const -{ - QString norm = m_type.trimmed().toLower(); - - return norm.startsWith("character") - || norm.startsWith("varchar") - || norm.startsWith("varying character") - || norm.startsWith("nchar") - || norm.startsWith("native character") - || norm.startsWith("nvarchar") - || norm == "text" - || norm == "clob"; -} - -bool Field::isInteger() const -{ - QString norm = m_type.trimmed().toLower(); - - return norm == "int" - || norm == "integer" - || norm == "tinyint" - || norm == "smallint" - || norm == "mediumint" - || norm == "bigint" - || norm == "unsigned big int" - || norm == "int2" - || norm == "int8"; -} - -void Table::clear() -{ - m_fields.clear(); - m_rowidColumn = "_rowid_"; -} - -Table::~Table() -{ - clear(); -} - -void Table::addField(const FieldPtr& f) -{ - m_fields.append(FieldPtr(f)); -} - -bool Table::removeField(const QString& sFieldName) -{ - int index = findField(sFieldName); - if( index != -1) - { - m_fields.remove(index); - return true; - } - return false; -} - -void Table::setFields(const FieldVector &fields) -{ - clear(); - m_fields = fields; -} - -int Table::findField(const QString &sname) -{ - for(int i = 0; i < m_fields.count(); ++i) - { - if(m_fields.at(i)->name().compare(sname, Qt::CaseInsensitive) == 0) - return i; - } - return -1; -} - -int Table::findPk() const -{ - for(int i = 0; i < m_fields.count(); ++i) - { - if(m_fields.at(i)->primaryKey()) - return i; - } - return -1; -} - -QStringList Table::fieldList() const -{ - QStringList sl; - - foreach(const FieldPtr& f, m_fields) { - sl << f->toString(); - } - - return sl; -} - -QStringList Table::fieldNames() const -{ - QStringList sl; - - foreach(FieldPtr f, m_fields) - sl << f->name(); - - return sl; -} - -bool Table::hasAutoIncrement() const -{ - foreach(FieldPtr f, m_fields) { - if(f->autoIncrement()) - return true; - } - return false; -} - -QPair Table::parseSQL(const QString &sSQL) -{ - std::stringstream s; - s << sSQL.toStdString(); - Sqlite3Lexer lex(s); - - Sqlite3Parser parser(lex); - - antlr::ASTFactory ast_factory; - parser.initializeASTFactory(ast_factory); - parser.setASTFactory(&ast_factory); - - try - { - parser.createtable(); - CreateTableWalker ctw(parser.getAST()); - return qMakePair(ctw.table(), ctw.modifysupported()); - } - catch(antlr::ANTLRException& ex) - { - qCritical() << "Sqlite parse error: " << QString::fromStdString(ex.toString()) << "(" << sSQL << ")"; - } - catch(...) - { - qCritical() << "Sqlite parse error: " << sSQL; //TODO - } - - return qMakePair(Table(""), false); -} - -QString Table::sql() const -{ - QString sql = QString("CREATE TABLE %1 (\n").arg(escapeIdentifier(m_name)); - - sql += fieldList().join(",\n"); - - // primary key - if(!hasAutoIncrement()) - { - QString pk = ",\n\tPRIMARY KEY("; - bool pks_found = false; - foreach(FieldPtr f, m_fields) - { - if(f->primaryKey()) - { - pk += f->name() + ","; - pks_found = true; - } - } - pk.chop(1); - if(pks_found) - sql += pk + ")"; - } - - // foreign keys - foreach(FieldPtr f, m_fields) - { - if(f->foreignKey().isSet()) - sql += QString(",\n\tFOREIGN KEY(%1) REFERENCES %2").arg(escapeIdentifier(f->name())).arg(f->foreignKey().toString()); - } - - sql += "\n)"; - - // without rowid - if(isWithoutRowidTable()) - sql += " WITHOUT ROWID"; - - return sql + ";"; -} - -namespace -{ -QString identifier(antlr::RefAST ident) -{ - QString sident = ident->getText().c_str(); - if(ident->getType() == sqlite3TokenTypes::QUOTEDID || - ident->getType() == Sqlite3Lexer::QUOTEDLITERAL || - ident->getType() == sqlite3TokenTypes::STRINGLITERAL) - { - // Remember the way the identifier is quoted - QChar quoteChar = sident.at(0); - - // Remove first and final character, i.e. the quotes - sident.remove(0, 1); - sident.chop(1); - - // Replace all remaining occurences of two succeeding quote characters and replace them - // by a single instance. This is done because two quotes can be used as a means of escaping - // the quote character, thus only the visual representation has its two quotes, the actual - // name contains only one. - sident.replace(QString(quoteChar) + quoteChar, quoteChar); - } - - return sident; -} - -QString concatTextAST(antlr::RefAST t, bool withspace = false) -{ - QStringList stext; - while(t != antlr::nullAST) - { - stext.append(t->getText().c_str()); - t = t->getNextSibling(); - } - return stext.join(withspace ? " " : ""); -} -} - -namespace { -QString tablename(const antlr::RefAST& n) -{ - if(n->getType() == sqlite3TokenTypes::KEYWORDASTABLENAME) - return concatTextAST(n->getFirstChild()); - else - return identifier(n); -} -QString columnname(const antlr::RefAST& n) -{ - if(n->getType() == sqlite3TokenTypes::KEYWORDASCOLUMNNAME) - return concatTextAST(n->getFirstChild()); - else - return identifier(n); -} -} - -Table CreateTableWalker::table() -{ - Table tab(""); - - if( m_root ) //CREATE TABLE - { - antlr::RefAST s = m_root->getFirstChild(); - //skip to tablename - while(s->getType() != Sqlite3Lexer::ID && - s->getType() != Sqlite3Lexer::QUOTEDID && - s->getType() != Sqlite3Lexer::QUOTEDLITERAL && - s->getType() != Sqlite3Lexer::STRINGLITERAL && - s->getType() != sqlite3TokenTypes::KEYWORDASTABLENAME) - { - s = s->getNextSibling(); - } - - tab.setName(tablename(s)); - - s = s->getNextSibling(); // LPAREN - s = s->getNextSibling(); // first column name - antlr::RefAST column = s; - // loop columndefs - while(column != antlr::nullAST && column->getType() == sqlite3TokenTypes::COLUMNDEF) - { - FieldPtr f; - parsecolumn(f, column->getFirstChild()); - tab.addField(f); - column = column->getNextSibling(); //COMMA or RPAREN - column = column->getNextSibling(); //null or tableconstraint - } - - // now we are finished or it is a tableconstraint - while(s != antlr::nullAST) - { - // Is this a 'without rowid' definiton? - if(s->getType() != sqlite3TokenTypes::WITHOUT) - { - // It's not, so treat this as table constraints - - antlr::RefAST tc = s->getFirstChild(); - // skip constraint name, if there is any - if(tc->getType() == sqlite3TokenTypes::CONSTRAINT) - tc = tc->getNextSibling()->getNextSibling(); - - switch(tc->getType()) - { - case sqlite3TokenTypes::PRIMARY: - { - tc = tc->getNextSibling()->getNextSibling(); // skip primary and key - tc = tc->getNextSibling(); // skip LPAREN - do - { - QString col = columnname(tc); - int fieldindex = tab.findField(col); - if(fieldindex != -1) - tab.fields().at(fieldindex)->setPrimaryKey(true); - - tc = tc->getNextSibling(); - if(tc != antlr::nullAST - && (tc->getType() == sqlite3TokenTypes::ASC - || tc->getType() == sqlite3TokenTypes::DESC)) - { - // TODO save ASC / DESC information? - m_bModifySupported = false; - tc = tc->getNextSibling(); - } - - if(tc != antlr::nullAST && tc->getType() == sqlite3TokenTypes::AUTOINCREMENT) - { - tab.fields().at(fieldindex)->setAutoIncrement(true); - tc = tc->getNextSibling(); - } - while(tc != antlr::nullAST && tc->getType() == sqlite3TokenTypes::COMMA) - { - tc = tc->getNextSibling(); // skip ident and comma - } - } while(tc != antlr::nullAST && tc->getType() != sqlite3TokenTypes::RPAREN); - } - break; - case sqlite3TokenTypes::UNIQUE: - { - tc = tc->getNextSibling(); // skip UNIQUE - tc = tc->getNextSibling(); // skip LPAREN - QVector uniquefieldsindex; - do - { - QString col = columnname(tc); - int fieldindex = tab.findField(col); - if(fieldindex != -1) - uniquefieldsindex.append(fieldindex); - - tc = tc->getNextSibling(); - if(tc != antlr::nullAST - && (tc->getType() == sqlite3TokenTypes::ASC - || tc->getType() == sqlite3TokenTypes::DESC)) - { - // TODO save ASC / DESC information? - m_bModifySupported = false; - tc = tc->getNextSibling(); - } - - while(tc != antlr::nullAST && tc->getType() == sqlite3TokenTypes::COMMA) - { - tc = tc->getNextSibling(); // skip ident and comma - } - } while(tc != antlr::nullAST && tc->getType() != sqlite3TokenTypes::RPAREN); - - if(uniquefieldsindex.size() == 1) - { - tab.fields().at(uniquefieldsindex[0])->setUnique(true); - } - else - { - // else save on table a unique with more than one field - m_bModifySupported = false; - } - } - break; - case sqlite3TokenTypes::FOREIGN: - { - sqlb::ForeignKeyClause fk; - - tc = tc->getNextSibling(); // FOREIGN - tc = tc->getNextSibling(); // KEY - tc = tc->getNextSibling(); // LPAREN - QString column_name = columnname(tc); - tc = tc->getNextSibling(); // identifier - if(tc->getType() == sqlite3TokenTypes::COMMA) - { - // No support for composite foreign keys - m_bModifySupported = false; - break; - } - tc = tc->getNextSibling(); // RPAREN - tc = tc->getNextSibling(); // REFERENCES - - fk.setTable(identifier(tc)); - tc = tc->getNextSibling(); // identifier - - if(tc != antlr::nullAST && tc->getType() == sqlite3TokenTypes::LPAREN) - { - tc = tc->getNextSibling(); // LPAREN - - QStringList fk_cols; - while(tc != antlr::nullAST && tc->getType() != sqlite3TokenTypes::RPAREN) - { - if(tc->getType() != sqlite3TokenTypes::COMMA) - fk_cols.push_back(identifier(tc)); - tc = tc->getNextSibling(); - } - fk.setColumns(fk_cols); - - tc = tc->getNextSibling(); // RPAREN - } - - fk.setConstraint(concatTextAST(tc, true)); - - tab.fields().at(tab.findField(column_name))->setForeignKey(fk); - } - break; - default: - { - m_bModifySupported = false; - } - break; - } - - s = s->getNextSibling(); //COMMA or RPAREN - if(s->getType() == sqlite3TokenTypes::COMMA || s->getType() == sqlite3TokenTypes::RPAREN) - s = s->getNextSibling(); - } else { - // It is - - s = s->getNextSibling(); // WITHOUT - s = s->getNextSibling(); // ROWID - - tab.setRowidColumn(tab.fields().at(tab.findPk())->name()); - } - } - } - - return tab; -} - -void CreateTableWalker::parsecolumn(FieldPtr& f, antlr::RefAST c) -{ - QString colname; - QString type = "TEXT"; - bool autoincrement = false; - bool primarykey = false; - bool notnull = false; - bool unique = false; - QString defaultvalue; - QString check; - sqlb::ForeignKeyClause foreignKey; - - colname = columnname(c); - c = c->getNextSibling(); //type? - if(c != antlr::nullAST && c->getType() == sqlite3TokenTypes::TYPE_NAME) - { - type = concatTextAST(c->getFirstChild()); - c = c->getNextSibling(); - } - - // finished with type parsing - // now columnconstraints - while(c != antlr::nullAST) - { - antlr::RefAST con = c->getFirstChild(); - - // skip constraint name, if there is any - if(con->getType() == sqlite3TokenTypes::CONSTRAINT) - { - m_bModifySupported = false; - con = con->getNextSibling()->getNextSibling(); - } - - switch(con->getType()) - { - case sqlite3TokenTypes::PRIMARY: - { - primarykey = true; - con = con->getNextSibling()->getNextSibling(); // skip KEY - if(con != antlr::nullAST && (con->getType() == sqlite3TokenTypes::ASC - || con->getType() == sqlite3TokenTypes::DESC)) - { - m_bModifySupported = false; - con = con->getNextSibling(); //skip - } - if(con != antlr::nullAST && con->getType() == sqlite3TokenTypes::AUTOINCREMENT) - autoincrement = true; - } - break; - case sqlite3TokenTypes::NOT: - { - notnull = true; - } - break; - case sqlite3TokenTypes::CHECK: - { - con = con->getNextSibling(); //LPAREN - check = concatTextAST(con, true); - // remove parenthesis - check.remove(check.length()-1, 1); - check.remove(0,1); - check = check.trimmed(); - } - break; - case sqlite3TokenTypes::DEFAULT: - { - con = con->getNextSibling(); //SIGNEDNUMBER,STRING,LPAREN - defaultvalue = concatTextAST(con); - } - break; - case sqlite3TokenTypes::UNIQUE: - { - unique = true; - } - break; - case sqlite3TokenTypes::REFERENCES: - { - con = con->getNextSibling(); // REFERENCES - - foreignKey.setTable(identifier(con)); - con = con->getNextSibling(); // identifier - - if(con != antlr::nullAST && con->getType() == sqlite3TokenTypes::LPAREN) - { - con = con->getNextSibling(); // LPAREN - - QStringList fk_cols; - while(con != antlr::nullAST && con->getType() != sqlite3TokenTypes::RPAREN) - { - if(con->getType() != sqlite3TokenTypes::COMMA) - fk_cols.push_back(identifier(con)); - con = con->getNextSibling(); - } - foreignKey.setColumns(fk_cols); - - con = con->getNextSibling(); // RPAREN - } - - foreignKey.setConstraint(concatTextAST(con, true)); - } - break; - default: - { - m_bModifySupported = false; - } - break; - } - c = c->getNextSibling(); - } - - f = FieldPtr( new Field(colname, type, notnull, defaultvalue, check, primarykey, unique)); - f->setAutoIncrement(autoincrement); - f->setForeignKey(foreignKey); -} - -} //namespace sqlb diff --git a/src/sqlitetypes.h b/src/sqlitetypes.h deleted file mode 100644 index c65956da4..000000000 --- a/src/sqlitetypes.h +++ /dev/null @@ -1,190 +0,0 @@ -#pragma once -#ifndef SQLITETYPES_H -#define SQLITETYPES_H - -#include "antlr/ASTRefCount.hpp" - -#include -#include -#include -#include -#include - -namespace sqlb { - -QString escapeIdentifier(QString id); - -class ForeignKeyClause -{ -public: - ForeignKeyClause(const QString& table = QString(), const QStringList& columns = QStringList(), const QString& constraint = QString()) - : m_table(table), - m_columns(columns), - m_constraint(constraint), - m_override(QString()) - { - } - - bool isSet() const; - QString toString() const; - void setFromString(const QString& fk); - - void setTable(const QString& table) { m_override = QString(); m_table = table; } - const QString& table() const { return m_table; } - - void setColumns(const QStringList& columns) { m_columns = columns; } - const QStringList& columns() const { return m_columns; } - - void setConstraint(const QString& constraint) { m_constraint = constraint; } - const QString& constraint() const { return m_constraint; } - -private: - QString m_table; - QStringList m_columns; - QString m_constraint; - - QString m_override; -}; - -class Field -{ -public: - Field(const QString& name, - const QString& type, - bool notnull = false, - const QString& defaultvalue = "", - const QString& check = "", - bool pk = false, - bool unique = false) - : m_name(name) - , m_type(type) - , m_notnull(notnull) - , m_check(check) - , m_defaultvalue(defaultvalue) - , m_autoincrement(false) - , m_primaryKey(pk) - , m_unique(unique) - {} - - QString toString(const QString& indent = "\t", const QString& sep = "\t") const; - - void setName(const QString& name) { m_name = name; } - void setType(const QString& type) { m_type = type; } - void setNotNull(bool notnull = true) { m_notnull = notnull; } - void setCheck(const QString& check) { m_check = check; } - void setDefaultValue(const QString& defaultvalue) { m_defaultvalue = defaultvalue; } - void setAutoIncrement(bool autoinc) { m_autoincrement = autoinc; } - void setPrimaryKey(bool pk) { m_primaryKey = pk; } - void setUnique(bool u) { m_unique = u; } - void setForeignKey(const ForeignKeyClause& key) { m_foreignKey = key; } - - bool isText() const; - bool isInteger() const; - - const QString& name() const { return m_name; } - const QString& type() const { return m_type; } - bool notnull() const { return m_notnull; } - const QString& check() const { return m_check; } - const QString& defaultValue() const { return m_defaultvalue; } - bool autoIncrement() const { return m_autoincrement; } - bool primaryKey() const { return m_primaryKey; } - bool unique() const { return m_unique; } - const ForeignKeyClause& foreignKey() const { return m_foreignKey; } - - static QStringList Datatypes; -private: - QString m_name; - QString m_type; - bool m_notnull; - QString m_check; - QString m_defaultvalue; - ForeignKeyClause m_foreignKey; // Even though this information is a table constraint it's easier for accessing and processing to store it here - bool m_autoincrement; //! this is stored here for simplification - bool m_primaryKey; - bool m_unique; -}; - -typedef QSharedPointer FieldPtr; -typedef QVector< FieldPtr > FieldVector; -class Table -{ -public: - explicit Table(const QString& name): m_name(name), m_rowidColumn("_rowid_") {} - virtual ~Table(); - - void setName(const QString& name) { m_name = name; } - - const QString& name() const { return m_name; } - const FieldVector& fields() const { return m_fields; } - - /** - * @brief Returns the CREATE TABLE statement for this table object - * @return A QString with the CREATE TABLE object. - */ - QString sql() const; - - void addField(const FieldPtr& f); - bool removeField(const QString& sFieldName); - void setFields(const FieldVector& fields); - void setField(int index, FieldPtr f) { m_fields[index] = f; } - QStringList fieldNames() const; - void setRowidColumn(const QString& rowid) { m_rowidColumn = rowid; } - const QString& rowidColumn() const { return m_rowidColumn; } - bool isWithoutRowidTable() const { return m_rowidColumn != "_rowid_"; } - void clear(); - - /** - * @brief findField Finds a field and returns the index. - * @param sname - * @return The field index if the field was found. - * -1 if field couldn't be found. - */ - int findField(const QString& sname); - - int findPk() const; - - /** - * @brief parseSQL Parses the create Table statement in sSQL. - * @param sSQL The create table statement. - * @return A pair first is a table object, second is a bool indicating - * if our modify dialog supports the table. - * The table object may be a empty table if parsing failed. - */ - static QPair parseSQL(const QString& sSQL); -private: - QStringList fieldList() const; - bool hasAutoIncrement() const; - -private: - QString m_name; - FieldVector m_fields; - QString m_rowidColumn; -}; - -/** - * @brief The CreateTableWalker class - * Goes trough the createtable AST and returns - * Table object. - */ -class CreateTableWalker -{ -public: - explicit CreateTableWalker(antlr::RefAST r) - : m_root(r) - , m_bModifySupported(true) - {} - - Table table(); - bool modifysupported() const { return m_bModifySupported; } - -private: - void parsecolumn(FieldPtr& f, antlr::RefAST c); - -private: - antlr::RefAST m_root; - bool m_bModifySupported; -}; - -} //namespace sqlb - -#endif // SQLITETYPES_H diff --git a/src/sqltextedit.cpp b/src/sqltextedit.cpp index d2904283d..93f8efd2c 100644 --- a/src/sqltextedit.cpp +++ b/src/sqltextedit.cpp @@ -1,23 +1,24 @@ +#include "sql/ObjectIdentifier.h" #include "sqltextedit.h" -#include "PreferencesDialog.h" +#include "Settings.h" #include "SqlUiLexer.h" -#include -#include -#include -#include -#include +#include +#include -SqlUiLexer* SqlTextEdit::sqlLexer = 0; +#include +#include + +SqlUiLexer* SqlTextEdit::sqlLexer = nullptr; SqlTextEdit::SqlTextEdit(QWidget* parent) : - QsciScintilla(parent) + ExtendedScintilla(parent) { // Create lexer object if not done yet - if(sqlLexer == 0) + if(sqlLexer == nullptr) sqlLexer = new SqlUiLexer(this); - // Set the lexer + // Set the SQL lexer setLexer(sqlLexer); // Set icons for auto completion @@ -25,145 +26,127 @@ SqlTextEdit::SqlTextEdit(QWidget* parent) : registerImage(SqlUiLexer::ApiCompleterIconIdFunction, QImage(":/icons/function")); registerImage(SqlUiLexer::ApiCompleterIconIdTable, QImage(":/icons/table")); registerImage(SqlUiLexer::ApiCompleterIconIdColumn, QImage(":/icons/field")); + registerImage(SqlUiLexer::ApiCompleterIconIdSchema, QImage(":/icons/database")); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#define CAST_KEYS(k) QKeyCombination(k).toCombined() +#else +#define CAST_KEYS(k) k +#endif - // Enable UTF8 - setUtf8(true); + // Remove command bindings that would interfere with our shortcutToggleComment + QsciCommand * command = standardCommands()->boundTo(CAST_KEYS(Qt::ControlModifier | Qt::Key_Slash)); + command->setKey(0); + command = standardCommands()->boundTo(CAST_KEYS(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_Slash)); + command->setKey(0); - // Enable brace matching - setBraceMatching(QsciScintilla::SloppyBraceMatch); + // Change command binding for Ctrl+T so it doesn't interfere with "Open tab" + command = standardCommands()->boundTo(CAST_KEYS(Qt::ControlModifier | Qt::Key_T)); + command->setKey(CAST_KEYS(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_Up)); - // Enable auto indentation - setAutoIndent(true); + // Change command binding for Ctrl+Shift+T so it doesn't interfere with "Open SQL file" + command = standardCommands()->boundTo(CAST_KEYS(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_T)); + command->setKey(CAST_KEYS(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_Insert)); - // Enable folding - setFolding(QsciScintilla::BoxedTreeFoldStyle); +#undef CAST_KEYS - // Create error indicator - errorIndicatorNumber = indicatorDefine(QsciScintilla::SquiggleIndicator); - setIndicatorForegroundColor(Qt::red, errorIndicatorNumber); + QShortcut* shortcutToggleComment = new QShortcut(QKeySequence(tr("Ctrl+/")), this, nullptr, nullptr, Qt::WidgetShortcut); + connect(shortcutToggleComment, &QShortcut::activated, this, &SqlTextEdit::toggleBlockComment); // Do rest of initialisation reloadSettings(); - - // Connect signals - connect(this, SIGNAL(linesChanged()), this, SLOT(updateLineNumberAreaWidth())); -} - -SqlTextEdit::~SqlTextEdit() -{ -} - -void SqlTextEdit::updateLineNumberAreaWidth() -{ - // Calculate number of digits of the current number of lines - int digits = std::floor(std::log10(lines())) + 1; - - // Calculate the width of this number if it was all zeros (this is because a 1 might require less space than a 0 and this could - // cause some flickering depending on the font) and set the new margin width. - QFont font = lexer()->font(QsciLexerSQL::Default); - setMarginWidth(0, QFontMetrics(font).width(QString("0").repeated(digits)) + 5); -} - -void SqlTextEdit::dropEvent(QDropEvent* e) -{ - QList urls = e->mimeData()->urls(); - if(urls.isEmpty()) - return QsciScintilla::dropEvent(e); - - QString file = urls.first().toLocalFile(); - if(!QFile::exists(file)) - return; - - QFile f(file); - f.open(QIODevice::ReadOnly); - setText(f.readAll()); - f.close(); -} - -void SqlTextEdit::setupSyntaxHighlightingFormat(const QString& settings_name, int style) -{ - sqlLexer->setColor(QColor(PreferencesDialog::getSettingsValue("syntaxhighlighter", settings_name + "_colour").toString()), style); - - QFont font(PreferencesDialog::getSettingsValue("editor", "font").toString()); - font.setPointSize(PreferencesDialog::getSettingsValue("editor", "fontsize").toInt()); - font.setBold(PreferencesDialog::getSettingsValue("syntaxhighlighter", settings_name + "_bold").toBool()); - font.setItalic(PreferencesDialog::getSettingsValue("syntaxhighlighter", settings_name + "_italic").toBool()); - font.setUnderline(PreferencesDialog::getSettingsValue("syntaxhighlighter", settings_name + "_underline").toBool()); - sqlLexer->setFont(font, style); -} - -void SqlTextEdit::reloadKeywords() -{ - // Set lexer again to reload the updated keywords list - setLexer(lexer()); } void SqlTextEdit::reloadSettings() { // Enable auto completion if it hasn't been disabled - if(PreferencesDialog::getSettingsValue("editor", "auto_completion").toBool()) + if(Settings::getValue("editor", "auto_completion").toBool()) { setAutoCompletionThreshold(3); - setAutoCompletionCaseSensitivity(false); + setAutoCompletionCaseSensitivity(true); setAutoCompletionShowSingle(true); setAutoCompletionSource(QsciScintilla::AcsAPIs); } else { setAutoCompletionThreshold(0); } - - // Set syntax highlighting settings - QFont defaultfont(PreferencesDialog::getSettingsValue("editor", "font").toString()); - defaultfont.setStyleHint(QFont::TypeWriter); - defaultfont.setPointSize(PreferencesDialog::getSettingsValue("editor", "fontsize").toInt()); - sqlLexer->setColor(Qt::black, QsciLexerSQL::Default); - sqlLexer->setFont(defaultfont); - setupSyntaxHighlightingFormat("comment", QsciLexerSQL::Comment); - setupSyntaxHighlightingFormat("comment", QsciLexerSQL::CommentLine); - setupSyntaxHighlightingFormat("comment", QsciLexerSQL::CommentDoc); - setupSyntaxHighlightingFormat("keyword", QsciLexerSQL::Keyword); - setupSyntaxHighlightingFormat("table", QsciLexerSQL::KeywordSet6); - setupSyntaxHighlightingFormat("function", QsciLexerSQL::KeywordSet7); - setupSyntaxHighlightingFormat("string", QsciLexerSQL::DoubleQuotedString); - setupSyntaxHighlightingFormat("string", QsciLexerSQL::SingleQuotedString); - setupSyntaxHighlightingFormat("identifier", QsciLexerSQL::Identifier); - setupSyntaxHighlightingFormat("identifier", QsciLexerSQL::QuotedIdentifier); - - // Set font - QFont font(PreferencesDialog::getSettingsValue("editor", "font").toString()); - font.setStyleHint(QFont::TypeWriter); - font.setPointSize(PreferencesDialog::getSettingsValue("editor", "fontsize").toInt()); - setFont(font); - - // Show line numbers - QFont marginsfont(QFont(PreferencesDialog::getSettingsValue("editor", "font").toString())); - marginsfont.setPointSize(font.pointSize()); - setMarginsFont(marginsfont); - setMarginLineNumbers(0, true); - setMarginsBackgroundColor(Qt::lightGray); - updateLineNumberAreaWidth(); - - // Highlight current line - setCaretLineVisible(true); - setCaretLineBackgroundColor(QColor(PreferencesDialog::getSettingsValue("syntaxhighlighter", "currentline_colour").toString())); - - // Set tab width - setTabWidth(PreferencesDialog::getSettingsValue("editor", "tabsize").toInt()); - - // Check if error indicators are enabled and clear them if they just got disabled - showErrorIndicators = PreferencesDialog::getSettingsValue("editor", "error_indicators").toBool(); - if(!showErrorIndicators) - clearErrorIndicators(); + // Set wrap lines + setWrapMode(static_cast(Settings::getValue("editor", "wrap_lines").toInt())); + + ExtendedScintilla::reloadSettings(); + + setupSyntaxHighlightingFormat(sqlLexer, "comment", QsciLexerSQL::Comment); + setupSyntaxHighlightingFormat(sqlLexer, "comment", QsciLexerSQL::CommentLine); + setupSyntaxHighlightingFormat(sqlLexer, "comment", QsciLexerSQL::CommentDoc); + setupSyntaxHighlightingFormat(sqlLexer, "keyword", QsciLexerSQL::Keyword); + setupSyntaxHighlightingFormat(sqlLexer, "table", QsciLexerSQL::KeywordSet6); + setupSyntaxHighlightingFormat(sqlLexer, "function", QsciLexerSQL::KeywordSet7); + setupSyntaxHighlightingFormat(sqlLexer, "string", QsciLexerSQL::SingleQuotedString); + + // Highlight double quote strings as identifier or as literal string depending on user preference + switch(static_cast(Settings::getValue("editor", "identifier_quotes").toInt())) { + case sqlb::DoubleQuotes: + setupSyntaxHighlightingFormat(sqlLexer, "identifier", QsciLexerSQL::DoubleQuotedString); + sqlLexer->setQuotedIdentifiers(false); + break; + case sqlb::GraveAccents: + sqlLexer->setQuotedIdentifiers(true); + setupSyntaxHighlightingFormat(sqlLexer, "string", QsciLexerSQL::DoubleQuotedString); // treat quoted string as literal string + break; + case sqlb::SquareBrackets: + setupSyntaxHighlightingFormat(sqlLexer, "string", QsciLexerSQL::DoubleQuotedString); + break; + } + setupSyntaxHighlightingFormat(sqlLexer, "identifier", QsciLexerSQL::Identifier); + setupSyntaxHighlightingFormat(sqlLexer, "identifier", QsciLexerSQL::QuotedIdentifier); } -void SqlTextEdit::clearErrorIndicators() -{ - // Clear any error indicators from position (0,0) to the last column of the last line - clearIndicatorRange(0, 0, lines(), lineLength(lines()), errorIndicatorNumber); -} -void SqlTextEdit::setErrorIndicator(int fromRow, int fromIndex, int toRow, int toIndex) +void SqlTextEdit::toggleBlockComment() { - // Set error indicator for the specified range but only if they're enabled - if(showErrorIndicators) - fillIndicatorRange(fromRow, fromIndex, toRow, toIndex, errorIndicatorNumber); + int lineFrom, indexFrom, lineTo, indexTo; + + // If there is no selection, select the current line + if (!hasSelectedText()) { + getCursorPosition(&lineFrom, &indexFrom); + + indexTo = text(lineFrom).length(); + + // Windows lines requires an adjustment, otherwise the selection would + // end in the next line. + if (text(lineFrom).endsWith("\r\n")) + indexTo--; + + setSelection(lineFrom, 0, lineFrom, indexTo); + } + + getSelection(&lineFrom, &indexFrom, &lineTo, &indexTo); + + bool uncomment = text(lineFrom).contains(QRegularExpression("^[ \t]*--")); + + // If the selection ends before the first character of a line, don't + // take this line into account for un/commenting. + if (indexTo==0) + lineTo--; + + beginUndoAction(); + + // Iterate over the selected lines, get line text, make + // replacement depending on whether the first line was commented + // or uncommented, and replace the line text. All in a single undo action. + for (int line=lineFrom; line<=lineTo; line++) { + QString lineText = text(line); + + if (uncomment) + lineText.replace(QRegularExpression("^([ \t]*)-- ?"), "\\1"); + else + lineText.replace(QRegularExpression("^"), "-- "); + + indexTo = text(line).length(); + if (lineText.endsWith("\r\n")) + indexTo--; + + setSelection(line, 0, line, indexTo); + replaceSelectedText(lineText); + } + endUndoAction(); } diff --git a/src/sqltextedit.h b/src/sqltextedit.h index 4948b448e..ffcd6cf88 100644 --- a/src/sqltextedit.h +++ b/src/sqltextedit.h @@ -1,7 +1,7 @@ #ifndef SQLTEXTEDIT_H #define SQLTEXTEDIT_H -#include "Qsci/qsciscintilla.h" +#include "ExtendedScintilla.h" class SqlUiLexer; @@ -9,33 +9,19 @@ class SqlUiLexer; * @brief The SqlTextEdit class * This class is based on the QScintilla widget */ -class SqlTextEdit : public QsciScintilla +class SqlTextEdit : public ExtendedScintilla { Q_OBJECT public: - explicit SqlTextEdit(QWidget *parent = 0); - virtual ~SqlTextEdit(); + explicit SqlTextEdit(QWidget *parent = nullptr); static SqlUiLexer* sqlLexer; public slots: - void reloadKeywords(); void reloadSettings(); - void clearErrorIndicators(); - void setErrorIndicator(int fromRow, int fromIndex, int toRow, int toIndex); + void toggleBlockComment(); -protected: - void dropEvent(QDropEvent* e); - -private: - void setupSyntaxHighlightingFormat(const QString& settings_name, int style); - - int errorIndicatorNumber; - bool showErrorIndicators; - -private slots: - void updateLineNumberAreaWidth(); }; #endif diff --git a/src/src.pro b/src/src.pro deleted file mode 100644 index 4184f73e3..000000000 --- a/src/src.pro +++ /dev/null @@ -1,175 +0,0 @@ -TEMPLATE = app - -QT += core gui network -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport - -TARGET = sqlitebrowser - -CONFIG += debug_and_release -CONFIG += qt -CONFIG += warn_on - -# create a unittest option -CONFIG(unittest) { - greaterThan(QT_MAJOR_VERSION, 4) { - QT += testlib - } else { - CONFIG += qtestlib - } - - HEADERS += tests/testsqlobjects.h tests/TestImport.h - SOURCES += tests/testsqlobjects.cpp tests/TestImport.cpp tests/TestMain.cpp -} else { - SOURCES += main.cpp -} - -HEADERS += \ - sqlitedb.h \ - MainWindow.h \ - CreateIndexDialog.h \ - AboutDialog.h \ - EditTableDialog.h \ - PreferencesDialog.h \ - EditDialog.h \ - ExportCsvDialog.h \ - ImportCsvDialog.h \ - sqltextedit.h \ - sqlitetypes.h \ - csvparser.h \ - ExtendedTableWidget.h \ - grammar/Sqlite3Lexer.hpp \ - grammar/Sqlite3Parser.hpp \ - grammar/sqlite3TokenTypes.hpp \ - sqlitetablemodel.h \ - FilterTableHeader.h \ - version.h \ - SqlExecutionArea.h \ - VacuumDialog.h \ - DbStructureModel.h \ - Application.h \ - sqlite.h \ - CipherDialog.h \ - ExportSqlDialog.h \ - SqlUiLexer.h \ - FileDialog.h \ - ColumnDisplayFormatDialog.h \ - FilterLineEdit.h - -SOURCES += \ - sqlitedb.cpp \ - MainWindow.cpp \ - CreateIndexDialog.cpp \ - EditTableDialog.cpp \ - PreferencesDialog.cpp \ - AboutDialog.cpp \ - EditDialog.cpp \ - ExportCsvDialog.cpp \ - ImportCsvDialog.cpp \ - sqltextedit.cpp \ - sqlitetypes.cpp \ - csvparser.cpp \ - ExtendedTableWidget.cpp \ - grammar/Sqlite3Lexer.cpp \ - grammar/Sqlite3Parser.cpp \ - sqlitetablemodel.cpp \ - FilterTableHeader.cpp \ - SqlExecutionArea.cpp \ - VacuumDialog.cpp \ - DbStructureModel.cpp \ - Application.cpp \ - CipherDialog.cpp \ - ExportSqlDialog.cpp \ - SqlUiLexer.cpp \ - FileDialog.cpp \ - ColumnDisplayFormatDialog.cpp \ - FilterLineEdit.cpp - -RESOURCES += icons/icons.qrc \ - translations/flags/flags.qrc \ - translations/translations.qrc - -FORMS += \ - MainWindow.ui \ - CreateIndexDialog.ui \ - AboutDialog.ui \ - EditTableDialog.ui \ - PreferencesDialog.ui \ - EditDialog.ui \ - ExportCsvDialog.ui \ - ImportCsvDialog.ui \ - SqlExecutionArea.ui \ - VacuumDialog.ui \ - CipherDialog.ui \ - ExportSqlDialog.ui \ - ColumnDisplayFormatDialog.ui - -TRANSLATIONS += \ - translations/sqlb_zh.ts \ - translations/sqlb_zh_TW.ts \ - translations/sqlb_de.ts \ - translations/sqlb_es_ES.ts \ - translations/sqlb_fr.ts \ - translations/sqlb_ru.ts \ - translations/sqlb_pt_BR.ts \ - translations/sqlb_en_GB.ts \ - translations/sqlb_ko_KR.ts \ - translations/sqlb_tr.ts - -CONFIG(sqlcipher) { - QMAKE_CXXFLAGS += -DENABLE_SQLCIPHER - LIBS += -lsqlcipher -} else { - LIBS += -lsqlite3 -} - -LIBPATH_QHEXEDIT=$$OUT_PWD/../libs/qhexedit -LIBPATH_ANTLR=$$OUT_PWD/../libs/antlr-2.7.7 -LIBPATH_QCUSTOMPLOT=$$OUT_PWD/../libs/qcustomplot-source -LIBPATH_QSCINTILLA=$$OUT_PWD/../libs/qscintilla/Qt4Qt5 -unix { - LIBS += -ldl -} -os2 { - RC_FILE = os2app.rc -} -win32 { - RC_FILE = winapp.rc - INCLUDEPATH += $$PWD - CONFIG(debug,debug|release) { - LIBPATH_QHEXEDIT = $$LIBPATH_QHEXEDIT/debug - LIBPATH_ANTLR = $$LIBPATH_ANTLR/debug - LIBPATH_QCUSTOMPLOT = $$LIBPATH_QCUSTOMPLOT/debug - LIBPATH_QSCINTILLA = $$LIBPATH_QSCINTILLA/debug - } - CONFIG(release,debug|release) { - LIBPATH_QHEXEDIT = $$LIBPATH_QHEXEDIT/release - LIBPATH_ANTLR = $$LIBPATH_ANTLR/release - LIBPATH_QCUSTOMPLOT = $$LIBPATH_QCUSTOMPLOT/release - LIBPATH_QSCINTILLA = $$LIBPATH_QSCINTILLA/release - } - QMAKE_CXXFLAGS += -DCHECKNEWVERSION - - # Added SQLite installation path variables, matching our setup guide - LIBS += -L$$PWD/../../../dev/SQLite/ -lsqlite3 - INCLUDEPATH += $$PWD/../../../dev/SQLite - DEPENDPATH += $$PWD/../../../dev/SQLite -} -mac { - RC_FILE = macapp.icns - QT+= macextras - INCLUDEPATH += /usr/local/include \ - /usr/local/opt/sqlite/include - LIBS += -L/usr/local/lib \ - -L/usr/local/opt/sqlite/lib \ - -framework Carbon - QMAKE_INFO_PLIST = app.plist - QMAKE_CXXFLAGS += -DCHECKNEWVERSION -} - -UI_DIR = .ui -INCLUDEPATH += $$PWD/../libs/antlr-2.7.7 $$PWD/../libs/qhexedit $$PWD/../libs/qcustomplot-source $$PWD/../libs/qscintilla/Qt4Qt5 $$PWD/.. -LIBS += -L$$LIBPATH_QHEXEDIT -L$$LIBPATH_ANTLR -L$$LIBPATH_QCUSTOMPLOT -L$$LIBPATH_QSCINTILLA -lantlr -lqhexedit -lqcustomplot -lqscintilla2 -DEPENDPATH += $$PWD/../libs/antlr-2.7.7 $$PWD/../libs/qhexedit $$PWD/../libs/qcustomplot-source $$PWD/../libs/qscintilla/Qt4Qt5 - -# Rules for creating/updating {ts|qm}-files -include(i18n.pri) diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 2ff970750..2ec5837f5 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -1,105 +1,83 @@ -if(USE_QT5) -else() - find_package(Qt4 COMPONENTS QtTest REQUIRED) - include("${QT_USE_FILE}") - add_definitions(${QT_DEFINITIONS}) -endif() - include_directories("${CMAKE_CURRENT_BINARY_DIR}" ..) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +find_package(${QT_MAJOR} REQUIRED COMPONENTS Test Widgets) +if(QT_MAJOR STREQUAL "Qt6") + find_package(Qt6 REQUIRED COMPONENTS Core5Compat) + set(QT5_COMPAT Qt6::Core5Compat) +endif() + # test-sqlobjects set(TESTSQLOBJECTS_SRC - ../sqlitedb.cpp - ../sqlitetablemodel.cpp - ../sqlitetypes.cpp - ../csvparser.cpp - ../grammar/Sqlite3Lexer.cpp - ../grammar/Sqlite3Parser.cpp - ../PreferencesDialog.cpp - testsqlobjects.cpp - ../FileDialog.cpp - ../sqltextedit.cpp - ../SqlUiLexer.cpp + ../sql/sqlitetypes.cpp + ../sql/Query.cpp + ../sql/ObjectIdentifier.cpp + testsqlobjects.cpp + ../sql/parser/ParserDriver.cpp + ../sql/parser/sqlite3_lexer.cpp + ../sql/parser/sqlite3_parser.cpp ) set(TESTSQLOBJECTS_HDR - ../grammar/sqlite3TokenTypes.hpp - ../grammar/Sqlite3Lexer.hpp - ../grammar/Sqlite3Parser.hpp - ../sqlitetypes.h) - -set(TESTSQLOBJECTS_FORMS - ../PreferencesDialog.ui) - -set(TESTSQLOBJECTS_MOC_HDR - ../sqlitedb.h - ../sqlitetablemodel.h - ../PreferencesDialog.h - testsqlobjects.h - ../FileDialog.h - ../sqltextedit.h - ../SqlUiLexer.h + ../sql/sqlitetypes.h + ../sql/Query.h + ../sql/ObjectIdentifier.h + ../sql/parser/ParserDriver.h + ../sql/parser/sqlite3_lexer.h + ../sql/parser/sqlite3_location.h + ../sql/parser/sqlite3_parser.hpp + testsqlobjects.h ) -if(sqlcipher) - list(APPEND TESTSQLOBJECTS_SRC ../CipherDialog.cpp) - list(APPEND TESTSQLOBJECTS_FORMS ../CipherDialog.ui) - list(APPEND TESTSQLOBJECTS_MOC_HDR ../CipherDialog.h) -endif() - -if(USE_QT5) - QT5_WRAP_UI(TESTSQLOBJECTS_FORM_HDR ${TESTSQLOBJECTS_FORMS}) -else() - QT4_WRAP_CPP(TESTSQLOBJECTS_MOC ${TESTSQLOBJECTS_MOC_HDR}) - QT4_WRAP_UI(TESTSQLOBJECTS_FORM_HDR ${TESTSQLOBJECTS_FORMS}) -endif() - -add_executable(test-sqlobjects ${TESTSQLOBJECTS_MOC} ${TESTSQLOBJECTS_HDR} ${TESTSQLOBJECTS_SRC} ${TESTSQLOBJECTS_FORM_HDR}) - -if(USE_QT5) - qt5_use_modules(test-sqlobjects Test Widgets Gui) - set(QT_LIBRARIES "") -endif() - -if(ANTLR2_FOUND) -else() - add_dependencies(test-sqlobjects antlr) -endif() -target_link_libraries(test-sqlobjects ${QT_LIBRARIES} ${LIBSQLITE}) -if(ANTLR2_FOUND) - target_link_libraries(test-sqlobjects ${ANTLR2_LIBRARIES}) -else() - target_link_libraries(test-sqlobjects antlr) -endif() -link_directories("${CMAKE_CURRENT_BINARY_DIR}/${QSCINTILLA_DIR}") -add_dependencies(test-sqlobjects qscintilla2) -target_link_libraries(test-sqlobjects - qscintilla2) +add_executable(test-sqlobjects ${TESTSQLOBJECTS_HDR} ${TESTSQLOBJECTS_SRC}) +target_link_libraries(test-sqlobjects ${QT_MAJOR}::Test) add_test(test-sqlobjects test-sqlobjects) # test-import set(TESTIMPORT_SRC - ../csvparser.cpp - TestImport.cpp + ../csvparser.cpp + TestImport.cpp ) set(TESTIMPORT_MOC_HDR - TestImport.h + TestImport.h ) -if(USE_QT5) -else() - QT4_WRAP_CPP(TESTIMPORT_MOC ${TESTIMPORT_MOC_HDR}) -endif() +add_executable(test-import ${TESTIMPORT_MOC_HDR} ${TESTIMPORT_SRC}) +target_link_libraries(test-import ${QT_MAJOR}::Test) +add_test(test-import test-import) -add_executable(test-import ${TESTIMPORT_MOC} ${TESTIMPORT_SRC}) +# test regex -if(USE_QT5) - qt5_use_modules(test-import Test Core) - set(QT_LIBRARIES "") -endif() +set(TESTREGEX_SRC + TestRegex.cpp + ../Data.cpp +) -target_link_libraries(test-import ${QT_LIBRARIES}) -add_test(test-import test-import) +set(TESTREGEX_HDR + ../Data.h + TestRegex.h +) + +add_executable(test-regex ${TESTREGEX_HDR} ${TESTREGEX_SRC}) +target_link_libraries(test-regex ${QT_MAJOR}::Test ${QT_MAJOR}::Widgets ${QT5_COMPAT}) +add_test(test-regex test-regex) + +# test cache + +set(TESTCACHE_SRC + TestRowCache.cpp +) + +set(TESTCACHE_HDR + TestRowCache.h +) + +add_executable(test-cache ${TESTCACHE_HDR} ${TESTCACHE_SRC}) +target_link_libraries(test-cache ${QT_MAJOR}::Test) +add_test(test-cache test-cache) diff --git a/src/tests/TestImport.cpp b/src/tests/TestImport.cpp index 6e53bc195..6af0aefb1 100644 --- a/src/tests/TestImport.cpp +++ b/src/tests/TestImport.cpp @@ -4,14 +4,13 @@ #include #include #include +#include #include "csvparser.h" #include "TestImport.h" QTEST_MAIN(TestImport) -Q_DECLARE_METATYPE(CSVParser::TCSVResult) - TestImport::TestImport() { } @@ -28,27 +27,51 @@ void TestImport::csvImport() QFETCH(char, quote); QFETCH(QString, encoding); QFETCH(int, numfields); - QFETCH(QVector, result); + QFETCH(std::vector>, result); // Create temporary CSV file QTemporaryFile file; QVERIFY(file.open()); { - QTextStream out(&file); - out.setCodec(encoding.toUtf8()); - out << csv; + QTextStream out(&file); +// Qt6 QTextStream defaults to utf-8. +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + out.setCodec(encoding.toUtf8()); +#endif + out << csv; } file.flush(); CSVParser csvparser(true, separator, quote); file.seek(0); QTextStream tstream(&file); +// Qt6 QTextStream defaults to utf-8. +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) tstream.setCodec(encoding.toUtf8()); - csvparser.parse(tstream); +#endif + + std::vector> parsedCsv; + int parsedCsvColumns = 0; + csvparser.parse([&parsedCsv, &parsedCsvColumns](size_t /*rowNum*/, const CSVRow& data) -> bool { + std::vector row; + for(size_t i=0;i parsedCsvColumns) + parsedCsvColumns = row.size(); + return true; + }, tstream); // Check return values - QCOMPARE(csvparser.csv(), result); - QCOMPARE((int)csvparser.columns(), numfields); + QCOMPARE(parsedCsvColumns, numfields); + QCOMPARE(parsedCsv.size(), result.size()); + for(int i=0;i("quote"); QTest::addColumn("encoding"); QTest::addColumn("numfields"); - QTest::addColumn("result"); + QTest::addColumn>>("result"); - CSVParser::TCSVResult result; - result.append(QStringList() << "a" << "b" << "c"); - result.append(QStringList() << "d" << "e" << "f"); - result.append(QStringList() << "g" << "h" << "i"); + std::vector> result{ + {"a", "b", "c"}, + {"d", "e", "f"}, + {"g", "h", "i"} + }; QTest::newRow("commas_noquotes") << "a,b,c\nd,e,f\ng,h,i\n" << ',' - << (char)0 + << static_cast(0) << "UTF-8" << 3 << result; QTest::newRow("semicolons_noquotes") << "a;b;c\nd;e;f\ng;h;i\n" << ';' - << (char)0 + << static_cast(0) << "UTF-8" << 3 << result; @@ -90,42 +114,47 @@ void TestImport::csvImport_data() << result; QTest::newRow("windowslinebreaks") << "a,b,c\r\nd,e,f\r\ng,h,i\r\n" << ',' - << (char)0 + << static_cast(0) << "UTF-8" << 3 << result; QTest::newRow("oldmaclinebreaks") << "a,b,c\rd,e,f\rg,h,i\r" << ',' - << (char)0 + << static_cast(0) << "UTF-8" << 3 << result; result.clear(); - result.append(QStringList() << "a" << "b" << ""); - result.append(QStringList() << "c" << ""); - result.append(QStringList() << "d" << "" << "e"); - result.append(QStringList() << ""); - result.append(QStringList() << "" << "" << "f"); + result = { + {"a", "b", ""}, + {"c", ""}, + {"d", "", "e"}, + {""}, + {"", "", "f"} + }; QTest::newRow("emptyvalues") << "a,b,\nc,\nd,,e\n\n,,f" << ',' - << (char)0 + << static_cast(0) << "UTF-8" << 3 << result; result.clear(); - result.append(QStringList() << "a" << "b" << "c"); + result = {{"a", "b", "c"}}; QTest::newRow("oneline") << "a,b,c" << ',' - << (char)0 + << static_cast(0) << "UTF-8" << 3 << result; result.clear(); - result.append(QStringList() << "a,a\"" << "b" << "c"); - result.append(QStringList() << "d" << "e" << "\"\"f,f"); + result = { + {"a,a\"", "b", "c"}, + {"d", "e", "\"\"f,f"} + }; + QTest::newRow("manyquotes") << "\"a,a\"\"\",\"b\",\"c\"\n\"d\",\"e\",\"\"\"\"\"f,f\"\n" << ',' << '"' @@ -134,21 +163,21 @@ void TestImport::csvImport_data() << result; result.clear(); - result.append(QStringList() << QString::fromUtf8("\xC2\xAE") << QString::fromUtf8("\xC9\x85") << QString::fromUtf8("\xC6\x89")); + result = {{QByteArray("\xC2\xAE"), QByteArray("\xC9\x85"), QByteArray("\xC6\x89")}}; QString csv = QString::fromUtf8("\xC2\xAE") + "," + QString::fromUtf8("\xC9\x85") + "," + QString::fromUtf8("\xC6\x89") + "\n"; QTest::newRow("utf8chars") << csv << ',' - << (char)0 + << static_cast(0) << "UTF-8" << 3 << result; result.clear(); - result.append(QStringList() << QString::fromUtf8("\u4E18") << QString::fromUtf8("\u4E26") << QString::fromUtf8("\u4E4B")); + result = {{QByteArray("\u4E18"), QByteArray("\u4E26"), QByteArray("\u4E4B")}}; QString csv2 = QString::fromUtf8("\u4E18") + "," + QString::fromUtf8("\u4E26") + "," + QString::fromUtf8("\u4E4B") + "\n"; QTest::newRow("utf16chars") << csv2 << ',' - << (char)0 + << static_cast(0) << "UTF-16" << 3 << result; diff --git a/src/tests/TestRegex.cpp b/src/tests/TestRegex.cpp new file mode 100644 index 000000000..f7ef22a40 --- /dev/null +++ b/src/tests/TestRegex.cpp @@ -0,0 +1,81 @@ +#include "TestRegex.h" +#include "../Data.h" + +#include + +QTEST_APPLESS_MAIN(TestRegex) + +void TestRegex::sqlQueryComments_data() +{ + QTest::addColumn("dirtyQuery"); + QTest::addColumn("clearQuery"); + + QTest::newRow("test1") + << // dirtyQuery + "SELECT * -- asd ffdsf\n" + "-- saf ewf sf\n" + "-- dsaf fd\n" + "FROM \t-- sfsdf\n" + "qwfwqf -- asdasd" + << // clearQuery + "SELECT *\nFROM\nqwfwqf"; + + QTest::newRow("test2") + << // dirtyQuery + "SELECT *-- comment\n" + "FROM\n\n" + "-- something\n" + "qwfqwf" + << // cleanQuery + "SELECT *\nFROM\nqwfqwf"; + + QTest::newRow("test3") + << // dirtyQuery + "-- Comment before the query\n" + "SELECT * FROM test" + << // cleanQuery + "SELECT * FROM test"; + + QTest::newRow("test4") + << // dirtyQuery + "SELECT * FROM test\n" + "-- Comment after the query" + << // cleanQuery + "SELECT * FROM test"; + + QTest::newRow("test5") + << // dirtyQuery + "SELECT 40+2 -- get the answer\n" + "AS answer" + << // cleanQuery + "SELECT 40+2\n" + "AS answer"; + + QTest::newRow("test6") + << // dirtyQuery + "SELECT '-- comment inside quotes'" + << // cleanQuery + "SELECT '-- comment inside quotes'"; + + QTest::newRow("single_quote_comment") + << // dirtyQuery + "SELECT 'something--something' -- comment" + << // cleanQuery + "SELECT 'something--something'"; + + /* This still needs to be fixed in our code before activating the test + QTest::newRow("double_quote_comment") + << // dirtyQuery + "SELECT \"something--something\" -- comment" + << // cleanQuery + "SELECT \"something--something\"";*/ +} + +void TestRegex::sqlQueryComments() +{ + QFETCH(QString, dirtyQuery); + QFETCH(QString, clearQuery); + + removeCommentsFromQuery(dirtyQuery); + QCOMPARE(dirtyQuery, clearQuery); +} diff --git a/src/tests/TestRegex.h b/src/tests/TestRegex.h new file mode 100644 index 000000000..370a9be5c --- /dev/null +++ b/src/tests/TestRegex.h @@ -0,0 +1,17 @@ +#ifndef TESTREGEX_H +#define TESTREGEX_H + +#define REGEX_UNIT_TEST + +#include + +class TestRegex : public QObject +{ + Q_OBJECT + +private slots: + void sqlQueryComments(); + void sqlQueryComments_data(); +}; + +#endif diff --git a/src/tests/TestRowCache.cpp b/src/tests/TestRowCache.cpp new file mode 100644 index 000000000..610ba2cf3 --- /dev/null +++ b/src/tests/TestRowCache.cpp @@ -0,0 +1,189 @@ +#include + +#include "TestRowCache.h" +#include "../RowCache.h" + +QTEST_APPLESS_MAIN(TestRowCache) + +TestRowCache::TestRowCache() +{ +} + +TestRowCache::~TestRowCache() +{ +} + +using C = RowCache; + +void TestRowCache::construction() +{ + C c; + + QCOMPARE(c.numSet(), static_cast(0)); + + QVERIFY(c.count(0) == false); + QVERIFY(c.count(1) == false); + QVERIFY(c.count(2) == false); + + QVERIFY_EXCEPTION_THROWN(c.at(0), std::out_of_range); +} + +void TestRowCache::setGet() +{ + C c; + + c.set(1, 10); + c.set(5, 50); + c.set(0, 0); + c.set(6, 60); + c.set(100, 1000); + + QCOMPARE(c.numSet(), static_cast(5)); + QCOMPARE(c.numSegments(), static_cast(4)); // the '0' set after the '1' position does not merge currently + + int cnt = 0; + const C & cc = c; + for(size_t i = 0; i < 200; i++) { + if(c.count(i)) { + QCOMPARE(c.at(i), static_cast(10*i)); + QCOMPARE(cc.at(i), static_cast(10*i)); + cnt++; + } else { + QVERIFY_EXCEPTION_THROWN(c.at(i), std::out_of_range); + QVERIFY_EXCEPTION_THROWN(cc.at(i), std::out_of_range); + } + } + QCOMPARE(cnt, 5); +} + +void TestRowCache::insert() +{ + C c; + + c.insert(3, 30); + QCOMPARE(c.numSet(), static_cast(1)); + QCOMPARE(c.numSegments(), static_cast(1)); + QCOMPARE(c.at(3), 30); + + c.insert(3, 31); + QCOMPARE(c.numSet(), static_cast(2)); + QCOMPARE(c.numSegments(), static_cast(1)); + QCOMPARE(c.at(3), 31); + QCOMPARE(c.at(4), 30); + + c.insert(0, 0); + QCOMPARE(c.numSet(), static_cast(3)); + QCOMPARE(c.numSegments(), static_cast(2)); + QCOMPARE(c.at(0), 0); + QVERIFY_EXCEPTION_THROWN(c.at(3), std::out_of_range); + QCOMPARE(c.at(4), 31); + QCOMPARE(c.at(5), 30); + QVERIFY_EXCEPTION_THROWN(c.at(6), std::out_of_range); + + c.insert(1, 100); + QCOMPARE(c.numSet(), static_cast(4)); + QCOMPARE(c.numSegments(), static_cast(2)); + QCOMPARE(c.at(0), 0); + QCOMPARE(c.at(1), 100); + QCOMPARE(c.at(5), 31); + QCOMPARE(c.at(6), 30); + + c.insert(8, 1); + QCOMPARE(c.numSet(), static_cast(5)); + QCOMPARE(c.numSegments(), static_cast(3)); + QCOMPARE(c.at(0), 0); + QCOMPARE(c.at(1), 100); + QCOMPARE(c.at(5), 31); + QCOMPARE(c.at(6), 30); + QCOMPARE(c.at(8), 1); +} + +void TestRowCache::erase() +{ + C c; + c.insert(3, 30); + c.insert(3, 31); + c.insert(0, 0); + c.insert(8, 1); + QCOMPARE(c.numSet(), static_cast(4)); + QCOMPARE(c.numSegments(), static_cast(3)); + QCOMPARE(c.at(0), 0); + QCOMPARE(c.at(4), 31); + QCOMPARE(c.at(5), 30); + QCOMPARE(c.at(8), 1); + + // erase entire segment + c.erase(0); + QCOMPARE(c.numSet(), static_cast(3)); + QCOMPARE(c.numSegments(), static_cast(2)); + QCOMPARE(c.at(3), 31); + QCOMPARE(c.at(4), 30); + QCOMPARE(c.at(7), 1); + + // erase inside segment + c.erase(4); + QCOMPARE(c.numSet(), static_cast(2)); + QCOMPARE(c.numSegments(), static_cast(2)); + QCOMPARE(c.at(3), 31); + QCOMPARE(c.at(6), 1); + + // erase non-filled row + c.erase(5); + QCOMPARE(c.numSet(), static_cast(2)); + QCOMPARE(c.numSegments(), static_cast(2)); + QCOMPARE(c.at(3), 31); + QCOMPARE(c.at(5), 1); + + c.erase(5); + QCOMPARE(c.numSet(), static_cast(1)); + QCOMPARE(c.numSegments(), static_cast(1)); + QCOMPARE(c.at(3), 31); + + c.erase(3); + QCOMPARE(c.numSet(), static_cast(0)); + QCOMPARE(c.numSegments(), static_cast(0)); +} + +void TestRowCache::smallestNonAvailableRange() +{ + C c; + c.insert(3, 0); + c.insert(3, 0); + c.insert(0, 0); + c.insert(8, 0); + QCOMPARE(c.numSet(), static_cast(4)); + QVERIFY(c.count(0)); + QVERIFY(c.count(4)); + QVERIFY(c.count(5)); + QVERIFY(c.count(8)); + + using P = std::pair; + + auto test = [&](size_t begin, size_t end) { + P p{ begin, end }; + c.smallestNonAvailableRange(p.first, p.second); + return p; + }; + + QCOMPARE(test( 0, 0), P( 0, 0)); + QCOMPARE(test( 0, 1), P( 1, 1)); + QCOMPARE(test( 0, 2), P( 1, 2)); + QCOMPARE(test( 0, 3), P( 1, 3)); + QCOMPARE(test( 0, 4), P( 1, 4)); + QCOMPARE(test( 0, 5), P( 1, 4)); + QCOMPARE(test( 0, 6), P( 1, 4)); + QCOMPARE(test( 0, 7), P( 1, 7)); + QCOMPARE(test( 0, 8), P( 1, 8)); + QCOMPARE(test( 0, 9), P( 1, 8)); + QCOMPARE(test( 0,10), P( 1,10)); + QCOMPARE(test( 1,10), P( 1,10)); + QCOMPARE(test( 2,10), P( 2,10)); + QCOMPARE(test( 3,10), P( 3,10)); + QCOMPARE(test( 4,10), P( 6,10)); + QCOMPARE(test( 5,10), P( 6,10)); + QCOMPARE(test( 6,10), P( 6,10)); + QCOMPARE(test( 7,10), P( 7,10)); + QCOMPARE(test( 8,10), P( 9,10)); + QCOMPARE(test( 9,10), P( 9,10)); + QCOMPARE(test(10,10), P(10,10)); +} diff --git a/src/tests/TestRowCache.h b/src/tests/TestRowCache.h new file mode 100644 index 000000000..beeeee9c5 --- /dev/null +++ b/src/tests/TestRowCache.h @@ -0,0 +1,22 @@ +#ifndef TESTROWCACHE_H +#define TESTROWCACHE_H + +#include + +class TestRowCache : public QObject +{ + Q_OBJECT + +public: + TestRowCache(); + ~TestRowCache(); + +private slots: + void construction(); + void setGet(); + void insert(); + void erase(); + void smallestNonAvailableRange(); +}; + +#endif diff --git a/src/tests/testsqlobjects.cpp b/src/tests/testsqlobjects.cpp index 9d8287646..a50cc2f4f 100644 --- a/src/tests/testsqlobjects.cpp +++ b/src/tests/testsqlobjects.cpp @@ -1,304 +1,834 @@ #include "testsqlobjects.h" -#include "../sqlitetypes.h" +#include "../sql/ObjectIdentifier.h" +#include "../sql/sqlitetypes.h" #include QTEST_APPLESS_MAIN(TestTable) +Q_DECLARE_METATYPE(std::string) using namespace sqlb; +#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) +namespace QTest +{ +template +inline bool qCompare(const T1 &t1, const T2 &t2, const char *actual, const char *expected, + const char *file, int line) +{ + return compare_helper(t1 == t2, "Compared values are not the same", + toString(t1), toString(t2), actual, expected, file, line); +} +} +#endif + void TestTable::sqlOutput() { Table tt("testtable"); - FieldPtr f = FieldPtr(new Field("id", "integer")); - f->setPrimaryKey(true); - FieldPtr fkm = FieldPtr(new Field("km", "integer", false, "", "km > 1000")); - fkm->setPrimaryKey(true); - tt.addField(f); - tt.addField(FieldPtr(new Field("car", "text"))); - tt.addField(fkm); - - QCOMPARE(tt.sql(), QString("CREATE TABLE `testtable` (\n" - "\t`id`\tinteger,\n" - "\t`car`\ttext,\n" - "\t`km`\tinteger CHECK(km > 1000),\n" - "\tPRIMARY KEY(id,km)\n" - ");")); + Field f("id", "integer"); + Field fkm("km", "integer", false, "", "km > 1000"); + tt.fields.push_back(f); + tt.fields.emplace_back("car", "text"); + tt.fields.push_back(fkm); + tt.addConstraint({f.name(), fkm.name()}, std::make_shared()); + + QCOMPARE(tt.sql(), "CREATE TABLE \"testtable\" (\n" + "\t\"id\"\tinteger,\n" + "\t\"car\"\ttext,\n" + "\t\"km\"\tinteger CHECK(km > 1000),\n" + "\tPRIMARY KEY(\"id\",\"km\")\n" + ");"); } -void TestTable::autoincrement() +void TestTable::sqlGraveAccentOutput() { Table tt("testtable"); - FieldPtr f = FieldPtr(new Field("id", "integer")); - f->setPrimaryKey(true); - f->setAutoIncrement(true); - FieldPtr fkm = FieldPtr(new Field("km", "integer")); - tt.addField(f); - tt.addField(FieldPtr(new Field("car", "text"))); - tt.addField(fkm); + Field f("id", "integer"); + Field fkm("km", "integer", false, "", "km > 1000"); + tt.fields.push_back(f); + tt.fields.emplace_back("car", "text"); + tt.fields.push_back(fkm); + tt.addConstraint({f.name(), fkm.name()}, std::make_shared()); + sqlb::setIdentifierQuoting(sqlb::GraveAccents); + + QCOMPARE(tt.sql(), "CREATE TABLE `testtable` (\n" + "\t`id`\tinteger,\n" + "\t`car`\ttext,\n" + "\t`km`\tinteger CHECK(km > 1000),\n" + "\tPRIMARY KEY(`id`,`km`)\n" + ");"); + + sqlb::setIdentifierQuoting(sqlb::DoubleQuotes); +} + - QCOMPARE(tt.sql(), QString("CREATE TABLE `testtable` (\n" - "\t`id`\tinteger PRIMARY KEY AUTOINCREMENT,\n" - "\t`car`\ttext,\n" - "\t`km`\tinteger\n" - ");")); +void TestTable::sqlSquareBracketsOutput() +{ + Table tt("testtable"); + Field f("id", "integer"); + Field fkm("km", "integer", false, "", "km > 1000"); + tt.fields.push_back(f); + tt.fields.emplace_back("car", "text"); + tt.fields.push_back(fkm); + tt.addConstraint({f.name(), fkm.name()}, std::make_shared()); + sqlb::setIdentifierQuoting(sqlb::SquareBrackets); + + QCOMPARE(tt.sql(), "CREATE TABLE [testtable] (\n" + "\t[id]\tinteger,\n" + "\t[car]\ttext,\n" + "\t[km]\tinteger CHECK(km > 1000),\n" + "\tPRIMARY KEY([id],[km])\n" + ");"); + + sqlb::setIdentifierQuoting(sqlb::DoubleQuotes); } -void TestTable::notnull() +void TestTable::autoincrement() { Table tt("testtable"); - FieldPtr f = FieldPtr(new Field("id", "integer")); - f->setPrimaryKey(true); - f->setAutoIncrement(true); - FieldPtr fkm = FieldPtr(new Field("km", "integer")); - tt.addField(f); - tt.addField(FieldPtr(new Field("car", "text", true))); - tt.addField(fkm); + Field f("id", "integer"); + Field fkm("km", "integer"); + tt.fields.push_back(f); + tt.fields.emplace_back("car", "text"); + tt.fields.push_back(fkm); + PrimaryKeyConstraint pk; + pk.setAutoIncrement(true); + tt.addConstraint({f.name()}, std::make_shared(pk)); + + QCOMPARE(tt.sql(), "CREATE TABLE \"testtable\" (\n" + "\t\"id\"\tinteger,\n" + "\t\"car\"\ttext,\n" + "\t\"km\"\tinteger,\n" + "\tPRIMARY KEY(\"id\" AUTOINCREMENT)\n" + ");"); +} - QCOMPARE(tt.sql(), QString("CREATE TABLE `testtable` (\n" - "\t`id`\tinteger PRIMARY KEY AUTOINCREMENT,\n" - "\t`car`\ttext NOT NULL,\n" - "\t`km`\tinteger\n" - ");")); +void TestTable::notnull() +{ + Table tt("testtable"); + Field f("id", "integer"); + Field fkm("km", "integer"); + tt.fields.push_back(f); + tt.fields.emplace_back("car", "text", true); + tt.fields.push_back(fkm); + PrimaryKeyConstraint pk; + pk.setAutoIncrement(true); + tt.addConstraint({f.name()}, std::make_shared(pk)); + + QCOMPARE(tt.sql(), "CREATE TABLE \"testtable\" (\n" + "\t\"id\"\tinteger,\n" + "\t\"car\"\ttext NOT NULL,\n" + "\t\"km\"\tinteger,\n" + "\tPRIMARY KEY(\"id\" AUTOINCREMENT)\n" + ");"); } void TestTable::withoutRowid() { Table tt("testtable"); - FieldPtr f = FieldPtr(new Field("a", "integer")); - f->setPrimaryKey(true); - f->setAutoIncrement(true); - tt.addField(f); - tt.addField(FieldPtr(new Field("b", "integer"))); - tt.setRowidColumn("a"); + Field f("a", "integer"); + tt.fields.push_back(f); + tt.fields.emplace_back("b", "integer"); + tt.setWithoutRowidTable(true); + tt.addConstraint({f.name()}, std::make_shared()); + + QCOMPARE(tt.sql(), "CREATE TABLE \"testtable\" (\n" + "\t\"a\"\tinteger,\n" + "\t\"b\"\tinteger,\n" + "\tPRIMARY KEY(\"a\")\n" + ") WITHOUT ROWID;"); +} + +void TestTable::strict() +{ + Table tt("testtable"); + tt.fields.emplace_back("a", "integer"); + tt.fields.emplace_back("b", "integer"); + tt.setStrict(true); + + QCOMPARE(tt.sql(), "CREATE TABLE \"testtable\" (\n" + "\t\"a\"\tinteger,\n" + "\t\"b\"\tinteger\n" + ") STRICT;"); +} - QCOMPARE(tt.sql(), QString("CREATE TABLE `testtable` (\n" - "\t`a`\tinteger PRIMARY KEY AUTOINCREMENT,\n" - "\t`b`\tinteger\n" - ") WITHOUT ROWID;")); +void TestTable::strictAndWithoutRowid() +{ + Table tt("testtable"); + Field f("a", "integer"); + tt.fields.push_back(f); + tt.fields.emplace_back("b", "integer"); + tt.setStrict(true); + tt.setWithoutRowidTable(true); + tt.addConstraint({f.name()}, std::make_shared()); + + QCOMPARE(tt.sql(), "CREATE TABLE \"testtable\" (\n" + "\t\"a\"\tinteger,\n" + "\t\"b\"\tinteger,\n" + "\tPRIMARY KEY(\"a\")\n" + ") WITHOUT ROWID,STRICT;"); } void TestTable::foreignKeys() { Table tt("testtable"); - FieldPtr f = FieldPtr(new Field("a", "integer")); - f->setForeignKey(sqlb::ForeignKeyClause("b", QStringList("c"))); - tt.addField(f); + Field f("a", "integer"); + tt.fields.push_back(f); + auto fk = std::make_shared("b", sqlb::StringVector{"c"}); + tt.addConstraint({f.name()}, fk); + + QCOMPARE(tt.sql(), "CREATE TABLE \"testtable\" (\n" + "\t\"a\"\tinteger,\n" + "\tFOREIGN KEY(\"a\") REFERENCES \"b\"(\"c\")\n" + ");"); +} - QCOMPARE(tt.sql(), QString("CREATE TABLE `testtable` (\n" - "\t`a`\tinteger,\n" - "\tFOREIGN KEY(`a`) REFERENCES `b`(`c`)\n" - ");")); +void TestTable::uniqueConstraint() +{ + Table tt("testtable"); + Field f1("a", "integer"); + Field f2("b", "integer"); + Field f3("c", "integer"); + f1.setUnique(true); + tt.fields.push_back(f1); + tt.fields.push_back(f2); + tt.fields.push_back(f3); + tt.addConstraint({f2.name(), f3.name()}, std::make_shared()); + + QCOMPARE(tt.sql(), "CREATE TABLE \"testtable\" (\n" + "\t\"a\"\tinteger UNIQUE,\n" + "\t\"b\"\tinteger,\n" + "\t\"c\"\tinteger,\n" + "\tUNIQUE(\"b\",\"c\")\n" + ");"); } void TestTable::parseSQL() { - QString sSQL = "create TABLE hero (\n" - "\tid integer PRIMARY KEY AUTOINCREMENT,\n" - "\tname text NOT NULL DEFAULT 'xxxx',\n" - "\tinfo VARCHAR(255) CHECK (info == 'x')\n" - ");"; - - Table tab = Table::parseSQL(sSQL).first; - - QVERIFY(tab.name() == "hero"); - QVERIFY(tab.rowidColumn() == "_rowid_"); - QVERIFY(tab.fields().at(0)->name() == "id"); - QVERIFY(tab.fields().at(1)->name() == "name"); - QVERIFY(tab.fields().at(2)->name() == "info"); + std::string sSQL = "create TABLE hero (\n" + "\tid integer PRIMARY KEY AUTOINCREMENT,\n" + "\tname text NOT NULL DEFAULT 'xxxx',\n" + "\tinfo VARCHAR(255) CHECK (info == 'x')\n" + ");"; + + Table tab(*Table::parseSQL(sSQL)); + + QCOMPARE(tab.name(), "hero"); + QCOMPARE(tab.rowidColumns(), {"_rowid_"}); + QCOMPARE(tab.fields.at(0).name(), "id"); + QCOMPARE(tab.fields.at(1).name(), "name"); + QCOMPARE(tab.fields.at(2).name(), "info"); + + QCOMPARE(tab.fields.at(0).type(), "integer"); + QCOMPARE(tab.fields.at(1).type(), "text"); + QCOMPARE(tab.fields.at(2).type(), "VARCHAR(255)"); + + auto pk = tab.primaryKey(); + auto pkColumns = tab.primaryKeyColumns(); + QVERIFY(pk->autoIncrement()); + QCOMPARE(pkColumns.size(), 1); + QCOMPARE(pkColumns.at(0).name(), tab.fields.at(0).name()); + QVERIFY(tab.fields.at(1).notnull()); + QCOMPARE(tab.fields.at(1).defaultValue(), "'xxxx'"); + QCOMPARE(tab.fields.at(1).check(), ""); + QCOMPARE(tab.fields.at(2).check(), "\"info\" == 'x'"); +} - QVERIFY(tab.fields().at(0)->type() == "integer"); - QVERIFY(tab.fields().at(1)->type() == "text"); - QVERIFY(tab.fields().at(2)->type() == "VARCHAR(255)"); +void TestTable::parseSQLdefaultexpr() +{ + std::string sSQL = "CREATE TABLE chtest(\n" + "id integer primary key,\n" + "dumpytext text default('axa') CHECK(dumpytext == \"aa\"),\n" + "date datetime default CURRENT_TIMESTAMP," + "zoi integer)"; + + Table tab(*Table::parseSQL(sSQL)); + + QCOMPARE(tab.name(), "chtest"); + QCOMPARE(tab.fields.at(0).name(), "id"); + QCOMPARE(tab.fields.at(1).name(), "dumpytext"); + QCOMPARE(tab.fields.at(2).name(), "date"); + QCOMPARE(tab.fields.at(3).name(), "zoi"); + + QCOMPARE(tab.fields.at(0).type(), "integer"); + QCOMPARE(tab.fields.at(1).type(), "text"); + QCOMPARE(tab.fields.at(2).type(), "datetime"); + QCOMPARE(tab.fields.at(3).type(), "integer"); + + QCOMPARE(tab.fields.at(1).defaultValue(), "('axa')"); + QCOMPARE(tab.fields.at(1).check(), "\"dumpytext\" == \"aa\""); + QCOMPARE(tab.fields.at(2).defaultValue(), "CURRENT_TIMESTAMP"); + QCOMPARE(tab.fields.at(2).check(), ""); + QCOMPARE(tab.fields.at(3).defaultValue(), ""); + QCOMPARE(tab.fields.at(3).check(), ""); + + auto pk = tab.primaryKeyColumns(); + QCOMPARE(pk.size(), 1); + QCOMPARE(pk.at(0).name(), tab.fields.at(0).name()); +} - QVERIFY(tab.fields().at(0)->autoIncrement()); - QVERIFY(tab.fields().at(0)->primaryKey()); - QVERIFY(tab.fields().at(1)->notnull()); - QCOMPARE(tab.fields().at(1)->defaultValue(), QString("'xxxx'")); - QCOMPARE(tab.fields().at(1)->check(), QString("")); - QCOMPARE(tab.fields().at(2)->check(), QString("info == 'x'")); +void TestTable::parseSQLMultiPk() +{ + std::string sSQL = "CREATE TABLE hero (\n" + "\tid1 integer,\n" + "\tid2 integer,\n" + "\tnonpkfield blob,\n" + "PRIMARY KEY(\"id1\",\"id2\")\n" + ");"; + + Table tab(*Table::parseSQL(sSQL)); + + QCOMPARE(tab.name(), "hero"); + QCOMPARE(tab.fields.at(0).name(), "id1"); + QCOMPARE(tab.fields.at(1).name(), "id2"); + + QCOMPARE(tab.fields.at(0).type(), "integer"); + QCOMPARE(tab.fields.at(1).type(), "integer"); + + auto pk = tab.primaryKeyColumns(); + QCOMPARE(pk.size(), 2); + QCOMPARE(pk.at(0).name(), tab.fields.at(0).name()); + QCOMPARE(pk.at(1).name(), tab.fields.at(1).name()); } -void TestTable::parseSQLdefaultexpr() +void TestTable::parseSQLForeignKey() { - QString sSQL = "CREATE TABLE chtest(\n" - "id integer primary key,\n" - "dumpytext text default('axa') CHECK(dumpytext == \"aa\"),\n" - "date datetime default CURRENT_TIMESTAMP," - "zoi integer)"; + std::string sSQL = "CREATE TABLE grammar_test(id, test, FOREIGN KEY(test) REFERENCES other_table);"; - Table tab = Table::parseSQL(sSQL).first; + Table tab(*Table::parseSQL(sSQL)); - QCOMPARE(tab.name(), QString("chtest")); - QCOMPARE(tab.fields().at(0)->name(), QString("id")); - QCOMPARE(tab.fields().at(1)->name(), QString("dumpytext")); - QCOMPARE(tab.fields().at(2)->name(), QString("date")); - QCOMPARE(tab.fields().at(3)->name(), QString("zoi")); + QCOMPARE(tab.name(), "grammar_test"); + QCOMPARE(tab.fields.at(0).name(), "id"); + QCOMPARE(tab.fields.at(1).name(), "test"); +} - QCOMPARE(tab.fields().at(0)->type(), QString("integer")); - QCOMPARE(tab.fields().at(1)->type(), QString("text")); - QCOMPARE(tab.fields().at(2)->type(), QString("datetime")); - QCOMPARE(tab.fields().at(3)->type(), QString("integer")); +void TestTable::parseSQLSingleQuotes() +{ + std::string sSQL = "CREATE TABLE 'test'('id','test');"; - QCOMPARE(tab.fields().at(1)->defaultValue(), QString("('axa')")); - QCOMPARE(tab.fields().at(1)->check(), QString("dumpytext == \"aa\"")); - QCOMPARE(tab.fields().at(2)->defaultValue(), QString("CURRENT_TIMESTAMP")); - QCOMPARE(tab.fields().at(2)->check(), QString("")); - QCOMPARE(tab.fields().at(3)->defaultValue(), QString("")); - QCOMPARE(tab.fields().at(3)->check(), QString("")); + Table tab(*Table::parseSQL(sSQL)); - QVERIFY(tab.fields().at(0)->primaryKey()); + QCOMPARE(tab.name(), "test"); + QCOMPARE(tab.fields.at(0).name(), "id"); + QCOMPARE(tab.fields.at(1).name(), "test"); } -void TestTable::parseSQLMultiPk() +void TestTable::parseSQLSquareBrackets() { - QString sSQL = "CREATE TABLE hero (\n" - "\tid1 integer,\n" - "\tid2 integer,\n" - "\tnonpkfield blob,\n" - "PRIMARY KEY(id1,id2)\n" - ");"; + std::string sSQL = "CREATE TABLE [test]([id],[test]);"; + + Table tab(*Table::parseSQL(sSQL)); + + QCOMPARE(tab.name(), "test"); + QCOMPARE(tab.fields.at(0).name(), "id"); + QCOMPARE(tab.fields.at(1).name(), "test"); +} - Table tab = Table::parseSQL(sSQL).first; - QVERIFY(tab.name() == "hero"); - QVERIFY(tab.fields().at(0)->name() == "id1"); - QVERIFY(tab.fields().at(1)->name() == "id2"); +void TestTable::parseSQLKeywordInIdentifier() +{ + std::string sSQL = "CREATE TABLE deffered(key integer primary key, if text);"; - QVERIFY(tab.fields().at(0)->type() == "integer"); - QVERIFY(tab.fields().at(1)->type() == "integer"); + Table tab(*Table::parseSQL(sSQL)); - QVERIFY(tab.fields().at(0)->primaryKey()); - QVERIFY(tab.fields().at(1)->primaryKey()); + QCOMPARE(tab.name(), "deffered"); + QCOMPARE(tab.fields.at(0).name(), "key"); + QCOMPARE(tab.fields.at(1).name(), "if"); } -void TestTable::parseSQLForeignKey() + +void TestTable::parseSQLSomeKeywordsInIdentifier() { - QString sSQL = "CREATE TABLE grammar_test(id, test, FOREIGN KEY(test) REFERENCES other_table);"; + std::string sSQL = "CREATE TABLE \"Average Number of Volunteers by Area of Work\" (" + "`Area of Work` TEXT," + "`Average Number of Volunteers` INTEGER);"; - Table tab = Table::parseSQL(sSQL).first; + Table tab(*Table::parseSQL(sSQL)); - QVERIFY(tab.name() == "grammar_test"); - QVERIFY(tab.fields().at(0)->name() == "id"); - QVERIFY(tab.fields().at(1)->name() == "test"); + QCOMPARE(tab.name(), "Average Number of Volunteers by Area of Work"); + QCOMPARE(tab.fields.at(0).name(), "Area of Work"); + QCOMPARE(tab.fields.at(1).name(), "Average Number of Volunteers"); } -void TestTable::parseSQLSingleQuotes() +void TestTable::parseSQLWithoutRowid() { - QString sSQL = "CREATE TABLE 'test'('id','test');"; + std::string sSQL = "CREATE TABLE test(a integer primary key, b integer) WITHOUT ROWID;"; - Table tab = Table::parseSQL(sSQL).first; + Table tab(*Table::parseSQL(sSQL)); - QVERIFY(tab.name() == "test"); - QVERIFY(tab.fields().at(0)->name() == "id"); - QVERIFY(tab.fields().at(1)->name() == "test"); + QCOMPARE(tab.primaryKeyColumns().at(0).name(), "a"); + QCOMPARE(tab.rowidColumns(), {"a"}); + QCOMPARE(tab.withoutRowidTable(), true); + QCOMPARE(tab.isStrict(), false); } -void TestTable::parseSQLKeywordInIdentifier() +void TestTable::parseSQLStrictTable() { - QString sSQL = "CREATE TABLE deffered(key integer primary key, if text);"; + Table tab(*Table::parseSQL("CREATE TABLE test(a integer, b any) STRICT")); + + QCOMPARE(tab.name(), "test"); + QCOMPARE(tab.fields.at(0).name(), "a"); + QCOMPARE(tab.fields.at(1).name(), "b"); + QCOMPARE(tab.isStrict(), true); + QCOMPARE(tab.withoutRowidTable(), false); +} - Table tab = Table::parseSQL(sSQL).first; +void TestTable::parseSQLStrictAndWithoutRowidTable() +{ + Table tab(*Table::parseSQL("CREATE TABLE test(a integer, b any) STRICT, WITHOUT ROWID")); - QVERIFY(tab.name() == "deffered"); - QVERIFY(tab.fields().at(0)->name() == "key"); - QVERIFY(tab.fields().at(1)->name() == "if"); + QCOMPARE(tab.name(), "test"); + QCOMPARE(tab.fields.at(0).name(), "a"); + QCOMPARE(tab.fields.at(1).name(), "b"); + QCOMPARE(tab.isStrict(), true); + QCOMPARE(tab.withoutRowidTable(), true); } -void TestTable::parseSQLWithoutRowid() +void TestTable::parseNonASCIIChars() { - QString sSQL = "CREATE TABLE test(a integer primary key, b integer) WITHOUT ROWID;"; + std::string sSQL = "CREATE TABLE `lösung` (" + "`Fieldöäüß` INTEGER," + "PRIMARY KEY(`Fieldöäüß`)" + ");"; - Table tab = Table::parseSQL(sSQL).first; + Table tab(*Table::parseSQL(sSQL)); - QVERIFY(tab.fields().at(tab.findPk())->name() == "a"); - QVERIFY(tab.rowidColumn() == "a"); + QCOMPARE(tab.name(), "lösung"); + QCOMPARE(tab.fields.at(0).name(), "Fieldöäüß"); } -void TestTable::parseNonASCIIChars() +void TestTable::parseNonASCIICharsEs() { - QString sSQL = "CREATE TABLE `lösung` (" - "`Fieldöäüß` INTEGER," - "PRIMARY KEY(Fieldöäüß)" - ");"; + std::string sSQL = "CREATE TABLE \"Cigüeñas de Alcalá\" (" + "\"Field áéíóúÃÉÃÓÚñÑçÇ\" INTEGER," + "PRIMARY KEY(\"Field áéíóúÃÉÃÓÚñÑçÇ\")" + ");"; - Table tab = Table::parseSQL(sSQL).first; + Table tab(*Table::parseSQL(sSQL)); - QVERIFY(tab.name() == "lösung"); - QVERIFY(tab.fields().at(0)->name() == "Fieldöäüß"); + QCOMPARE(tab.name(), "Cigüeñas de Alcalá"); + QCOMPARE(tab.fields.at(0).name(), "Field áéíóúÃÉÃÓÚñÑçÇ"); } void TestTable::parseSQLEscapedQuotes() { - QString sSql = "CREATE TABLE double_quotes(a text default 'a''a');"; + std::string sSql = "CREATE TABLE double_quotes(a text default 'a''a');"; - Table tab = Table::parseSQL(sSql).first; + Table tab(*Table::parseSQL(sSql)); - QCOMPARE(tab.name(), QString("double_quotes")); - QCOMPARE(tab.fields().at(0)->name(), QString("a")); - QCOMPARE(tab.fields().at(0)->defaultValue(), QString("'a''a'")); + QCOMPARE(tab.name(), "double_quotes"); + QCOMPARE(tab.fields.at(0).name(), "a"); + QCOMPARE(tab.fields.at(0).defaultValue(), "'a''a'"); } void TestTable::parseSQLForeignKeys() { - QString sql = "CREATE TABLE foreign_key_test(a int, b int, foreign key (a) references x, foreign key (b) references w(y,z) on delete set null);"; + std::string sql = "CREATE TABLE foreign_key_test(a int, b int, foreign key (a) references x, foreign key (b) references w(y,z) on delete set null);"; - Table tab = Table::parseSQL(sql).first; + Table tab(*Table::parseSQL(sql)); - QCOMPARE(tab.name(), QString("foreign_key_test")); - QCOMPARE(tab.fields().at(0)->name(), QString("a")); - QCOMPARE(tab.fields().at(0)->type(), QString("int")); - QCOMPARE(tab.fields().at(0)->foreignKey().table(), QString("x")); - QCOMPARE(tab.fields().at(1)->name(), QString("b")); - QCOMPARE(tab.fields().at(1)->type(), QString("int")); - QCOMPARE(tab.fields().at(1)->foreignKey().toString(), QString("`w`(`y`,`z`) on delete set null")); + QCOMPARE(tab.name(), "foreign_key_test"); + QCOMPARE(tab.fields.at(0).name(), "a"); + QCOMPARE(tab.fields.at(0).type(), "int"); + QCOMPARE(tab.foreignKey({tab.fields.at(0).name()})->table(), "x"); + QCOMPARE(tab.fields.at(1).name(), "b"); + QCOMPARE(tab.fields.at(1).type(), "int"); + QCOMPARE(tab.foreignKey({tab.fields.at(1).name()})->toString(), "\"w\"(\"y\",\"z\") on delete set null"); } void TestTable::parseSQLCheckConstraint() { - QString sql = "CREATE TABLE a (`b` text CHECK(`b`='A' or `b`='B'));"; + std::string sql = "CREATE TABLE a (\"b\" text CHECK(\"b\"='A' or \"b\"='B'));"; + + Table tab(*Table::parseSQL(sql)); - Table tab = Table::parseSQL(sql).first; + QCOMPARE(tab.name(), "a"); + QCOMPARE(tab.fields.at(0).name(), "b"); + QCOMPARE(tab.fields.at(0).type(), "text"); + QCOMPARE(tab.fields.at(0).check(), "\"b\" = 'A' OR \"b\" = 'B'"); +} - QCOMPARE(tab.name(), QString("a")); - QCOMPARE(tab.fields().at(0)->name(), QString("b")); - QCOMPARE(tab.fields().at(0)->type(), QString("text")); - QCOMPARE(tab.fields().at(0)->check(), QString("`b` = 'A' or `b` = 'B'")); +void TestTable::parseDefaultValues() +{ + std::string sql = "CREATE TABLE test(a int DEFAULT 0, b int DEFAULT -1, c text DEFAULT 'hello', d text DEFAULT '0');"; + + Table tab(*Table::parseSQL(sql)); + + QCOMPARE(tab.name(), "test"); + QCOMPARE(tab.fields.at(0).name(), "a"); + QCOMPARE(tab.fields.at(0).type(), "int"); + QCOMPARE(tab.fields.at(0).defaultValue(), "0"); + QCOMPARE(tab.fields.at(1).name(), "b"); + QCOMPARE(tab.fields.at(1).type(), "int"); + QCOMPARE(tab.fields.at(1).defaultValue(), "-1"); + QCOMPARE(tab.fields.at(2).name(), "c"); + QCOMPARE(tab.fields.at(2).type(), "text"); + QCOMPARE(tab.fields.at(2).defaultValue(), "'hello'"); + QCOMPARE(tab.fields.at(3).name(), "d"); + QCOMPARE(tab.fields.at(3).type(), "text"); + QCOMPARE(tab.fields.at(3).defaultValue(), "'0'"); } void TestTable::createTableWithIn() { - QString sSQL = "CREATE TABLE not_working(" - "_id PRIMARY KEY NOT NULL," - "value NVARCHAR(5) CHECK (value IN ('a', 'b', 'c'))" - ");"; + std::string sSQL = "CREATE TABLE not_working(" + "_id PRIMARY KEY NOT NULL," + "value NVARCHAR(5) CHECK (value IN ('a', 'b', 'c'))" + ");"; - Table tab = Table::parseSQL(sSQL).first; - QVERIFY(tab.name() == "not_working"); + Table tab(*Table::parseSQL(sSQL)); + QCOMPARE(tab.name(), "not_working"); - QVERIFY(tab.fields().at(1)->check() == "value IN ( 'a' , 'b' , 'c' )"); + QCOMPARE(tab.fields.at(1).check(), "\"value\" IN ('a', 'b', 'c')"); } void TestTable::createTableWithNotLikeConstraint() { - QString sSQL = "CREATE TABLE hopefully_working(\n" - "value TEXT CONSTRAINT 'value' CHECK(value NOT LIKE 'prefix%'),\n" - "value2 TEXT CONSTRAINT 'value' CHECK(value2 NOT MATCH 'prefix%'),\n" - "value3 TEXT CONSTRAINT 'value' CHECK(value3 NOT REGEXP 'prefix%'),\n" - "value4 TEXT CONSTRAINT 'value' CHECK(value4 NOT GLOB 'prefix%'),\n" - "value5 INTEGER CONSTRAINT 'value' CHECK(value5 BETWEEN 1+4 AND 100 OR 200),\n" - "value6 INTEGER CONSTRAINT 'value' CHECK(value6 NOT BETWEEN 1 AND 100),\n" - "value7 INTEGER CONSTRAINT 'value' CHECK(NOT EXISTS (1))\n" - ");"; - - Table tab = Table::parseSQL(sSQL).first; - QVERIFY(tab.name() == "hopefully_working"); - - QVERIFY(tab.fields().at(0)->check() == "value NOT LIKE 'prefix%'"); - QVERIFY(tab.fields().at(1)->check() == "value2 NOT MATCH 'prefix%'"); - QVERIFY(tab.fields().at(2)->check() == "value3 NOT REGEXP 'prefix%'"); - QVERIFY(tab.fields().at(3)->check() == "value4 NOT GLOB 'prefix%'"); - QVERIFY(tab.fields().at(4)->check() == "value5 BETWEEN 1 + 4 AND 100 OR 200"); - QVERIFY(tab.fields().at(5)->check() == "value6 NOT BETWEEN 1 AND 100"); - QVERIFY(tab.fields().at(6)->check() == "NOT EXISTS ( 1 )"); + std::string sSQL = "CREATE TABLE hopefully_working(\n" + "value TEXT CHECK(value NOT LIKE 'prefix%'),\n" + "value2 TEXT CHECK(value2 NOT MATCH 'prefix%'),\n" + "value3 TEXT CHECK(value3 NOT REGEXP 'prefix%'),\n" + "value4 TEXT CHECK(value4 NOT GLOB 'prefix%'),\n" + "value5 INTEGER CHECK(value5 BETWEEN 1+4 AND 100 OR 200),\n" + "value6 INTEGER CHECK(value6 NOT BETWEEN 1 AND 100)\n" + ");"; + + Table tab(*Table::parseSQL(sSQL)); + QCOMPARE(tab.name(), "hopefully_working"); + + QCOMPARE(tab.fields.at(0).check(), "\"value\" NOT LIKE 'prefix%'"); + QCOMPARE(tab.fields.at(1).check(), "\"value2\" NOT MATCH 'prefix%'"); + QCOMPARE(tab.fields.at(2).check(), "\"value3\" NOT REGEXP 'prefix%'"); + QCOMPARE(tab.fields.at(3).check(), "\"value4\" NOT GLOB 'prefix%'"); + QCOMPARE(tab.fields.at(4).check(), "\"value5\" BETWEEN 1 + 4 AND 100 OR 200"); + QCOMPARE(tab.fields.at(5).check(), "\"value6\" NOT BETWEEN 1 AND 100"); +} + +void TestTable::rowValues() +{ + std::string sql = "CREATE TABLE test(\n" + "a INTEGER,\n" + "b INTEGER,\n" + "CHECK((a, b) = (1, 2))\n" + ");"; + + Table tab(*Table::parseSQL(sql)); + QCOMPARE(tab.name(), "test"); + + auto c = tab.checkConstraints(); + QCOMPARE(c.size(), 1); + QCOMPARE(c.at(0)->expression(), "(\"a\", \"b\") = (1, 2)"); +} + +void TestTable::complexExpressions() +{ + std::string sql = "CREATE TABLE test(\n" + "a INTEGER CHECK((a > 0)),\n" + "b INTEGER CHECK((b > 0 and b > 1)),\n" + "c INTEGER CHECK((c = -1) or (c > 0 and c > 1) or (c = 0)),\n" + "d INTEGER CHECK((((d > 0))))\n" + ");"; + + Table tab(*Table::parseSQL(sql)); + QCOMPARE(tab.name(), "test"); + + QCOMPARE(tab.fields.at(0).check(), "(\"a\" > 0)"); + QCOMPARE(tab.fields.at(1).check(), "(\"b\" > 0 AND \"b\" > 1)"); + QCOMPARE(tab.fields.at(2).check(), "(\"c\" = -1) OR (\"c\" > 0 AND \"c\" > 1) OR (\"c\" = 0)"); + QCOMPARE(tab.fields.at(3).check(), "(((\"d\" > 0)))"); +} + +void TestTable::datetimeExpression() +{ + std::string sql = "CREATE TABLE test(\n" + "entry INTEGER DEFAULT (DATETIME(CURRENT_TIMESTAMP, 'LOCALTIME'))\n" + ");"; + + Table tab(*Table::parseSQL(sql)); + QCOMPARE(tab.name(), "test"); + + QCOMPARE(tab.fields.at(0).name(), "entry"); + QCOMPARE(tab.fields.at(0).type(), "INTEGER"); + QCOMPARE(tab.fields.at(0).defaultValue(), "(DATETIME(CURRENT_TIMESTAMP, 'LOCALTIME'))"); +} + +void TestTable::extraParentheses() +{ + std::string sql = "CREATE TABLE test(\n" + "xy INTEGER DEFAULT (1 + (5) - 4)\n" + ");"; + + Table tab(*Table::parseSQL(sql)); + QCOMPARE(tab.name(), "test"); + + QCOMPARE(tab.fields.at(0).name(), "xy"); + QCOMPARE(tab.fields.at(0).type(), "INTEGER"); + QCOMPARE(tab.fields.at(0).defaultValue(), "(1 + (5) - 4)"); +} + +void TestTable::moduloOperator() +{ + std::string sql = "CREATE TABLE test(\n" + "xy INTEGER DEFAULT (7 % 2)\n" + ");"; + + Table tab(*Table::parseSQL(sql)); + QCOMPARE(tab.name(), "test"); + + QCOMPARE(tab.fields.at(0).name(), "xy"); + QCOMPARE(tab.fields.at(0).type(), "INTEGER"); + QCOMPARE(tab.fields.at(0).defaultValue(), "(7 % 2)"); +} + +void TestTable::complexExpression() +{ + std::string sql = "CREATE TABLE test(\n" + "uuid INTEGER DEFAULT (hex(randomblob(4))||'-'||hex(randomblob(2))||'-'||'4'||substr(hex(randomblob(2)),2)||'-'||substr('AB89',1+(abs(random())%4),1)||substr(hex(randomblob(2)),2)||'-'||hex(randomblob(6))),\n" + "a INTEGER,\n" + "b INTEGER,\n" + "CHECK((a = 'S' AND b IS NOT NULL) OR (a IN ('A', 'P')))" + ");"; + + Table tab(*Table::parseSQL(sql)); + QCOMPARE(tab.name(), "test"); + + QCOMPARE(tab.fields.at(0).name(), "uuid"); + QCOMPARE(tab.fields.at(0).type(), "INTEGER"); + QCOMPARE(tab.fields.at(0).defaultValue(), "(hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-' || '4' || substr(hex(randomblob(2)), 2) || '-' || substr('AB89', 1 + (abs(random()) % 4), 1) || substr(hex(randomblob(2)), 2) || '-' || hex(randomblob(6)))"); + + auto c = tab.checkConstraints(); + QCOMPARE(c.size(), 1); + QCOMPARE(c.at(0)->expression(), "(\"a\" = 'S' AND \"b\" IS NOT NULL) OR (\"a\" IN ('A', 'P'))"); +} + +void TestTable::parseIdentifierWithDollar() +{ + std::string sql = "CREATE TABLE te$st(te$st$ INTEGER);"; + + Table tab(*Table::parseSQL(sql)); + QCOMPARE(tab.name(), "te$st"); + + QCOMPARE(tab.fields.at(0).name(), "te$st$"); + QCOMPARE(tab.fields.at(0).type(), "INTEGER"); +} + +void TestTable::parseTest() +{ + QFETCH(std::string, sql); + + Table tab(*Table::parseSQL(sql)); + QVERIFY(tab.fullyParsed()); +} + +void TestTable::parseTest_data() +{ + // These are some rather unspecific queries but we include them here to test some basic parser features. They are + // extracted from this file: https://www.sqlite.org/cgi/src/artifact/1c602347e73ab80b + + QTest::addColumn("sql"); + + QTest::newRow("1") << std::string("CREATE TABLE t1(c1 one)"); + QTest::newRow("2") << std::string("CREATE TABLE t1(c1 one two)"); + QTest::newRow("3") << std::string("CREATE TABLE t1(c1 one two three)"); + QTest::newRow("4") << std::string("CREATE TABLE t1(c1 one two three four)"); + QTest::newRow("5") << std::string("CREATE TABLE t1(c1 one two three four(14))"); + QTest::newRow("6") << std::string("CREATE TABLE t1(c1 one two three four(14, 22))"); + QTest::newRow("7") << std::string("CREATE TABLE t1(c1 var(+14, -22.3))"); + QTest::newRow("8") << std::string("CREATE TABLE t1(c1 var(1.0e10))"); + QTest::newRow("9") << std::string("CREATE TABLE t1(c1 text PRIMARY KEY)"); + QTest::newRow("10") << std::string("CREATE TABLE t1(c1 text PRIMARY KEY ASC)"); + QTest::newRow("11") << std::string("CREATE TABLE t1(c1 text PRIMARY KEY DESC)"); + QTest::newRow("12") << std::string("CREATE TABLE t1(c1 text CONSTRAINT cons PRIMARY KEY DESC)"); + QTest::newRow("13") << std::string("CREATE TABLE t1(c1 text NOT NULL)"); + QTest::newRow("14") << std::string("CREATE TABLE t1(c1 text CONSTRAINT nm NOT NULL)"); + QTest::newRow("15") << std::string("CREATE TABLE t1(c1 text NULL)"); + QTest::newRow("16") << std::string("CREATE TABLE t1(c1 text CONSTRAINT nm NULL)"); + QTest::newRow("17") << std::string("CREATE TABLE t1(c1 text UNIQUE)"); + QTest::newRow("18") << std::string("CREATE TABLE t1(c1 text CONSTRAINT un UNIQUE)"); + QTest::newRow("19") << std::string("CREATE TABLE t1(c1 text CHECK(c1!=0))"); + QTest::newRow("20") << std::string("CREATE TABLE t1(c1 text CONSTRAINT chk CHECK(c1!=0))"); + QTest::newRow("21") << std::string("CREATE TABLE t1(c1 text DEFAULT 1)"); + QTest::newRow("22") << std::string("CREATE TABLE t1(c1 text DEFAULT -1)"); + QTest::newRow("23") << std::string("CREATE TABLE t1(c1 text DEFAULT +1)"); + QTest::newRow("24") << std::string("CREATE TABLE t1(c1 text DEFAULT -45.8e22)"); + QTest::newRow("25") << std::string("CREATE TABLE t1(c1 text DEFAULT (1+1))"); + QTest::newRow("26") << std::string("CREATE TABLE t1(c1 text CONSTRAINT \"1 2\" DEFAULT (1+1))"); + QTest::newRow("27") << std::string("CREATE TABLE t1(c1 text COLLATE nocase)"); + QTest::newRow("28") << std::string("CREATE TABLE t1(c1 text CONSTRAINT 'a x' COLLATE nocase)"); + QTest::newRow("29") << std::string("CREATE TABLE t1(c1 REFERENCES t2)"); + QTest::newRow("30") << std::string("CREATE TABLE t1(c1 CONSTRAINT abc REFERENCES t2)"); + QTest::newRow("31") << std::string("CREATE TABLE t1(c1 PRIMARY KEY NOT NULL UNIQUE CHECK(c1 IS 'ten') DEFAULT 123 REFERENCES t1);"); + QTest::newRow("32") << std::string("CREATE TABLE t1(c1 REFERENCES t1 DEFAULT 123 CHECK(c1 IS 'ten') UNIQUE NOT NULL PRIMARY KEY);"); + QTest::newRow("33") << std::string("CREATE TABLE t1(c1, c2, PRIMARY KEY(c1))"); + QTest::newRow("34") << std::string("CREATE TABLE t1(c1, c2, PRIMARY KEY(c1, c2))"); + QTest::newRow("35") << std::string("CREATE TABLE t1(c1, c2, PRIMARY KEY(c1, c2) ON CONFLICT IGNORE)"); + QTest::newRow("36") << std::string("CREATE TABLE t1(c1, c2, UNIQUE(c1))"); + QTest::newRow("37") << std::string("CREATE TABLE t1(c1, c2, UNIQUE(c1, c2))"); + QTest::newRow("38") << std::string("CREATE TABLE t1(c1, c2, UNIQUE(c1, c2) ON CONFLICT IGNORE)"); + QTest::newRow("39") << std::string("CREATE TABLE t1(c1, c2, CHECK(c1 IS NOT c2))"); + QTest::newRow("40") << std::string("CREATE TABLE t1(c1, c2, FOREIGN KEY(c1) REFERENCES t2)"); + QTest::newRow("41") << std::string("CREATE TABLE t1(col1, col2 TEXT, col3 INTEGER UNIQUE, col4 VARCHAR(10, 10) PRIMARY KEY, \"name with spaces\" REFERENCES t1);"); + QTest::newRow("42") << std::string("CREATE TABLE t1(a, b, c)"); + QTest::newRow("43") << std::string("CREATE TEMP TABLE t1(a, b, c)"); + QTest::newRow("44") << std::string("CREATE TEMPORARY TABLE t1(a, b, c)"); + QTest::newRow("45") << std::string("CREATE TABLE IF NOT EXISTS t1(a, b, c)"); + QTest::newRow("46") << std::string("CREATE TEMP TABLE IF NOT EXISTS t1(a, b, c)"); + QTest::newRow("47") << std::string("CREATE TEMPORARY TABLE IF NOT EXISTS t1(a, b, c)"); + QTest::newRow("48") << std::string("CREATE TABLE main.t1(a, b, c)"); + QTest::newRow("49") << std::string("CREATE TEMP TABLE temp.t1(a, b, c)"); + QTest::newRow("50") << std::string("CREATE TEMPORARY TABLE temp.t1(a, b, c)"); + QTest::newRow("51") << std::string("CREATE TABLE IF NOT EXISTS main.t1(a, b, c)"); + QTest::newRow("52") << std::string("CREATE TEMP TABLE IF NOT EXISTS temp.t1(a, b, c)"); + QTest::newRow("53") << std::string("CREATE TEMPORARY TABLE IF NOT EXISTS temp.t1(a, b, c)"); + QTest::newRow("54") << std::string("CREATE TABLE t1(a REFERENCES t2(x) MATCH FULL ON DELETE SET NULL ON UPDATE RESTRICT DEFERRABLE)"); + QTest::newRow("55") << std::string("CREATE TABLE t1(a REFERENCES t2(x) ON DELETE RESTRICT ON UPDATE SET NULL MATCH FULL NOT DEFERRABLE INITIALLY IMMEDIATE)"); + QTest::newRow("56") << std::string("CREATE TABLE t1(a REFERENCES t2(x) MATCH PARTIAL ON DELETE SET NULL ON UPDATE CASCADE DEFERRABLE INITIALLY IMMEDIATE)"); + QTest::newRow("57") << std::string("CREATE TABLE t1(a REFERENCES t2(x) MATCH PARTIAL ON DELETE RESTRICT ON UPDATE SET DEFAULT )"); + QTest::newRow("58") << std::string("CREATE TABLE t1(a REFERENCES t2(x) MATCH PARTIAL ON DELETE RESTRICT ON UPDATE RESTRICT DEFERRABLE)"); + QTest::newRow("59") << std::string("CREATE TABLE t1(a REFERENCES t2(x) MATCH PARTIAL ON DELETE NO ACTION ON UPDATE SET DEFAULT NOT DEFERRABLE INITIALLY IMMEDIATE)"); + QTest::newRow("60") << std::string("CREATE TABLE t1(a REFERENCES t2(x) MATCH SIMPLE ON DELETE SET NULL ON UPDATE CASCADE NOT DEFERRABLE)"); + QTest::newRow("61") << std::string("CREATE TABLE t1(a REFERENCES t2(x) MATCH SIMPLE ON DELETE SET DEFAULT ON UPDATE SET NULL DEFERRABLE)"); + QTest::newRow("62") << std::string("CREATE TABLE t1(a REFERENCES t2(x) MATCH SIMPLE ON DELETE SET DEFAULT NOT DEFERRABLE)"); + QTest::newRow("63") << std::string("CREATE TABLE t1(a REFERENCES t2(x) MATCH SIMPLE ON DELETE RESTRICT ON UPDATE SET DEFAULT NOT DEFERRABLE INITIALLY DEFERRED)"); + QTest::newRow("64") << std::string("CREATE TABLE t1(a REFERENCES t2(x) MATCH SIMPLE ON DELETE RESTRICT ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)"); + QTest::newRow("65") << std::string("CREATE TABLE t1(a REFERENCES t2(x) MATCH SIMPLE ON DELETE NO ACTION ON UPDATE SET DEFAULT NOT DEFERRABLE)"); + QTest::newRow("66") << std::string("CREATE TABLE t1(a REFERENCES t2(x) MATCH STICK ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE)"); + QTest::newRow("67") << std::string("CREATE TABLE t1(a REFERENCES t2(x) MATCH STICK ON UPDATE SET NULL NOT DEFERRABLE INITIALLY DEFERRED)"); + QTest::newRow("68") << std::string("CREATE TABLE t1(a REFERENCES t2(x) ON DELETE SET NULL ON UPDATE NO ACTION DEFERRABLE INITIALLY IMMEDIATE)"); + QTest::newRow("69") << std::string("CREATE TABLE t1(a REFERENCES t2(x) ON DELETE RESTRICT ON UPDATE NO ACTION NOT DEFERRABLE)"); + QTest::newRow("70") << std::string("CREATE TABLE t1(a REFERENCES t2(x) NOT DEFERRABLE INITIALLY DEFERRED)"); + QTest::newRow("71") << std::string("CREATE TABLE t1(a REFERENCES t2 MATCH FULL ON DELETE SET NULL ON UPDATE SET NULL DEFERRABLE INITIALLY IMMEDIATE)"); + QTest::newRow("72") << std::string("CREATE TABLE t1(a REFERENCES t2 MATCH FULL ON DELETE SET NULL ON UPDATE SET DEFAULT NOT DEFERRABLE)"); + QTest::newRow("73") << std::string("CREATE TABLE t1(a REFERENCES t2 MATCH FULL ON DELETE SET DEFAULT ON UPDATE SET NULL )"); + QTest::newRow("74") << std::string("CREATE TABLE t1(a REFERENCES t2 MATCH FULL ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)"); + QTest::newRow("75") << std::string("CREATE TABLE t1(a REFERENCES t2 MATCH PARTIAL ON DELETE SET NULL ON UPDATE RESTRICT NOT DEFERRABLE)"); + QTest::newRow("76") << std::string("CREATE TABLE t1(a REFERENCES t2 MATCH PARTIAL ON DELETE SET NULL ON UPDATE NO ACTION DEFERRABLE)"); + QTest::newRow("77") << std::string("CREATE TABLE t1(a REFERENCES t2 MATCH PARTIAL ON DELETE CASCADE ON UPDATE SET DEFAULT )"); + QTest::newRow("78") << std::string("CREATE TABLE t1(a REFERENCES t2 MATCH PARTIAL NOT DEFERRABLE)"); + QTest::newRow("79") << std::string("CREATE TABLE t1(a REFERENCES t2 MATCH SIMPLE ON DELETE SET DEFAULT ON UPDATE CASCADE DEFERRABLE)"); + QTest::newRow("80") << std::string("CREATE TABLE t1(a REFERENCES t2 MATCH STICK ON DELETE SET NULL ON UPDATE NO ACTION DEFERRABLE INITIALLY IMMEDIATE)"); + QTest::newRow("81") << std::string("CREATE TABLE t1(a REFERENCES t2 MATCH STICK ON DELETE NO ACTION ON UPDATE SET DEFAULT NOT DEFERRABLE INITIALLY IMMEDIATE)"); + QTest::newRow("82") << std::string("CREATE TABLE t1(a REFERENCES t2 MATCH STICK ON UPDATE SET DEFAULT DEFERRABLE INITIALLY IMMEDIATE)"); + QTest::newRow("83") << std::string("CREATE TABLE t1(a REFERENCES t2 ON DELETE RESTRICT ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED)"); + QTest::newRow("84") << std::string("CREATE TABLE sqlit_abc(a, b, c)"); + QTest::newRow("85") << std::string("CREATE TABLE temp.sqlitehelloworld(x)"); + QTest::newRow("86") << std::string("CREATE TABLE auxa.\"sqlite\"(x, y)"); + QTest::newRow("87") << std::string("CREATE TABLE auxb.\"sqlite-\"(z)"); + QTest::newRow("88") << std::string("CREATE TABLE \"SQLITE-TBL\"(z)"); + QTest::newRow("89") << std::string("CREATE TABLE main.abc(a, b, c)"); + QTest::newRow("90") << std::string("CREATE TABLE temp.helloworld(x)"); + QTest::newRow("91") << std::string("CREATE TABLE auxa.\"t 1\"(x, y)"); + QTest::newRow("92") << std::string("CREATE TABLE auxb.xyz(z)"); + QTest::newRow("93") << std::string("CREATE TABLE main.abc(a, b, c)"); + QTest::newRow("94") << std::string("CREATE TABLE main.t1(a, b, c)"); + QTest::newRow("95") << std::string("CREATE TABLE temp.tmp(a, b, c)"); + QTest::newRow("96") << std::string("CREATE TABLE auxb.tbl(x, y)"); + QTest::newRow("97") << std::string("CREATE TABLE auxb.t1(k, v)"); + QTest::newRow("98") << std::string("CREATE TABLE auxa.next(c, d)"); + QTest::newRow("99") << std::string("CREATE TEMP TABLE t1(a, b)"); + QTest::newRow("100") << std::string("CREATE TEMPORARY TABLE t2(a, b)"); + QTest::newRow("101") << std::string("CREATE TEMP TABLE temp.t1(a, b)"); + QTest::newRow("102") << std::string("CREATE TEMPORARY TABLE temp.t2(a, b)"); + QTest::newRow("103") << std::string("CREATE TEMP TABLE TEMP.t3(a, b)"); + QTest::newRow("104") << std::string("CREATE TEMPORARY TABLE TEMP.xxx(x)"); + QTest::newRow("105") << std::string("CREATE TABLE t1(a, b)"); + QTest::newRow("106") << std::string("CREATE TABLE t2(a, b)"); + QTest::newRow("107") << std::string("CREATE TABLE t3(a, b)"); + QTest::newRow("108") << std::string("CREATE TABLE xxx(x)"); + QTest::newRow("109") << std::string("CREATE TABLE auxa.t1(a, b)"); + QTest::newRow("110") << std::string("CREATE TABLE auxa.i1(a, b)"); + QTest::newRow("111") << std::string("CREATE TABLE auxa.v1(a, b)"); + QTest::newRow("112") << std::string("CREATE TABLE tbl1(a, b)"); + QTest::newRow("113") << std::string("CREATE TABLE idx1(a, b)"); + QTest::newRow("114") << std::string("CREATE TABLE view1(a, b)"); + QTest::newRow("115") << std::string("CREATE TABLE IF NOT EXISTS t1(a, b)"); + QTest::newRow("116") << std::string("CREATE TABLE IF NOT EXISTS auxa.tbl1(a, b)"); + QTest::newRow("117") << std::string("CREATE TABLE IF NOT EXISTS v1(a, b)"); + QTest::newRow("118") << std::string("CREATE TABLE IF NOT EXISTS auxa.view1(a, b)"); + QTest::newRow("119") << std::string("CREATE TABLE t1(a, b, c);"); + QTest::newRow("120") << std::string("CREATE TABLE t2(d, e, f);"); + QTest::newRow("121") << std::string("CREATE TABLE t3(g BIGINT, h VARCHAR(10));"); + QTest::newRow("122") << std::string("CREATE TABLE t4(i BLOB, j ANYOLDATA);"); + QTest::newRow("123") << std::string("CREATE TABLE t5(k FLOAT, l INTEGER);"); + QTest::newRow("124") << std::string("CREATE TABLE t6(m DEFAULT 10, n DEFAULT 5, PRIMARY KEY(m, n));"); + QTest::newRow("125") << std::string("CREATE TABLE t7(x INTEGER PRIMARY KEY);"); + QTest::newRow("126") << std::string("CREATE TABLE t8(o COLLATE nocase DEFAULT 'abc');"); + QTest::newRow("127") << std::string("CREATE TABLE t9(p NOT NULL, q DOUBLE CHECK (q!=0), r STRING UNIQUE);"); + QTest::newRow("128") << std::string("CREATE TABLE t1(x VARCHAR(10), y INTEGER, z DOUBLE);"); + QTest::newRow("129") << std::string("CREATE TABLE t2(a DATETIME, b STRING, c REAL);"); + QTest::newRow("130") << std::string("CREATE TABLE t3(o, t);"); + QTest::newRow("131") << std::string("CREATE TABLE t4(a DEFAULT NULL,b DEFAULT 'string constant',c DEFAULT X'424C4F42',d DEFAULT 1,e DEFAULT -1,f DEFAULT 3.14,g DEFAULT -3.14,h DEFAULT ( substr('abcd', 0, 2) || 'cd' ),i DEFAULT CURRENT_TIME,j DEFAULT CURRENT_DATE,k DEFAULT CURRENT_TIMESTAMP);"); + QTest::newRow("132") << std::string("CREATE TABLE t5(x DEFAULT ( 'abc' ))"); + QTest::newRow("133") << std::string("CREATE TABLE t5(x DEFAULT ( 1 IN (1, 2, 3) ))"); + QTest::newRow("134") << std::string("CREATE TABLE t5(a DEFAULT NULL, b DEFAULT 'text value', c DEFAULT X'424C4F42',d DEFAULT -45678.6,e DEFAULT 394507);"); + QTest::newRow("135") << std::string("CREATE TABLE t6(a DEFAULT ( nextint() ), b DEFAULT ( nextint() ));"); + QTest::newRow("136") << std::string("CREATE TABLE t7(a DEFAULT CURRENT_TIME, b DEFAULT CURRENT_DATE, c DEFAULT CURRENT_TIMESTAMP);"); + QTest::newRow("137") << std::string("CREATE TABLE t8(a COLLATE nocase, b COLLATE rtrim, c COLLATE binary, d);"); + QTest::newRow("138") << std::string("CREATE TABLE t1(a, b, c)"); + QTest::newRow("139") << std::string("CREATE TABLE t2(a PRIMARY KEY, b, c)"); + QTest::newRow("140") << std::string("CREATE TABLE t3(a, b, c, PRIMARY KEY(a))"); + QTest::newRow("141") << std::string("CREATE TABLE t4(a, b, c, PRIMARY KEY(c,b,a))"); + QTest::newRow("142") << std::string("CREATE TABLE t5(a, b INTEGER PRIMARY KEY, c)"); + QTest::newRow("143") << std::string("CREATE TABLE t5(a PRIMARY KEY, b, c)"); + QTest::newRow("144") << std::string("CREATE TABLE t5(a, b, c, PRIMARY KEY(a))"); + QTest::newRow("145") << std::string("CREATE TABLE t5(a, b, c, PRIMARY KEY(c,b,a))"); + QTest::newRow("146") << std::string("CREATE TABLE t5(a, b INTEGER PRIMARY KEY, c)"); + QTest::newRow("147") << std::string("CREATE TABLE t1(a UNIQUE, b UNIQUE)"); + QTest::newRow("148") << std::string("CREATE TABLE t2(a UNIQUE, b, c, UNIQUE(c, b))"); + QTest::newRow("149") << std::string("CREATE TABLE t3(a, b, c, UNIQUE(a), UNIQUE(b), UNIQUE(c))"); + QTest::newRow("150") << std::string("CREATE TABLE t4(a, b, c, UNIQUE(a, b, c))"); + QTest::newRow("151") << std::string("CREATE TABLE t1(a TEXT PRIMARY KEY, b)"); + QTest::newRow("152") << std::string("CREATE TABLE t1(a INTEGER PRIMARY KEY, b)"); + QTest::newRow("153") << std::string("CREATE TABLE t1(a TEXT UNIQUE, b)"); + QTest::newRow("154") << std::string("CREATE TABLE t1(a PRIMARY KEY, b TEXT UNIQUE)"); + QTest::newRow("155") << std::string("CREATE TABLE t1(a PRIMARY KEY, b, c, UNIQUE(c, b))"); + QTest::newRow("156") << std::string("CREATE TABLE t1(a, b PRIMARY KEY);"); + QTest::newRow("157") << std::string("CREATE TABLE t2(a, b, c, UNIQUE(b, c));"); + QTest::newRow("158") << std::string("CREATE TABLE x1(a TEXT, b INTEGER CHECK( b>0 ));"); + QTest::newRow("159") << std::string("CREATE TABLE t1(a TEXT, b INTEGER, CHECK( b>0 ));"); + QTest::newRow("160") << std::string("CREATE TABLE x2(a CHECK( a||b ), b);"); + QTest::newRow("161") << std::string("CREATE TABLE t2(a, b, CHECK( a||b ));"); + QTest::newRow("162") << std::string("CREATE TABLE t1(a NOT NULL, b)"); + QTest::newRow("163") << std::string("CREATE TABLE t2(a PRIMARY KEY NOT NULL, b)"); + QTest::newRow("164") << std::string("CREATE TABLE t3(a NOT NULL, b NOT NULL, c NOT NULL UNIQUE)"); + QTest::newRow("165") << std::string("CREATE TABLE t1_ab(a PRIMARY KEY ON CONFLICT ABORT, b);"); + QTest::newRow("166") << std::string("CREATE TABLE t1_ro(a PRIMARY KEY ON CONFLICT ROLLBACK, b);"); + QTest::newRow("167") << std::string("CREATE TABLE t1_ig(a PRIMARY KEY ON CONFLICT IGNORE, b);"); + QTest::newRow("168") << std::string("CREATE TABLE t1_fa(a PRIMARY KEY ON CONFLICT FAIL, b);"); + QTest::newRow("169") << std::string("CREATE TABLE t1_re(a PRIMARY KEY ON CONFLICT REPLACE, b);"); + QTest::newRow("170") << std::string("CREATE TABLE t1_xx(a PRIMARY KEY, b);"); + QTest::newRow("171") << std::string("CREATE TABLE t2_ab(a, b NOT NULL ON CONFLICT ABORT);"); + QTest::newRow("172") << std::string("CREATE TABLE t2_ro(a, b NOT NULL ON CONFLICT ROLLBACK);"); + QTest::newRow("173") << std::string("CREATE TABLE t2_ig(a, b NOT NULL ON CONFLICT IGNORE);"); + QTest::newRow("174") << std::string("CREATE TABLE t2_fa(a, b NOT NULL ON CONFLICT FAIL);"); + QTest::newRow("175") << std::string("CREATE TABLE t2_re(a, b NOT NULL ON CONFLICT REPLACE);"); + QTest::newRow("176") << std::string("CREATE TABLE t2_xx(a, b NOT NULL);"); + QTest::newRow("177") << std::string("CREATE TABLE t3_ab(a, b, UNIQUE(a, b) ON CONFLICT ABORT);"); + QTest::newRow("178") << std::string("CREATE TABLE t3_ro(a, b, UNIQUE(a, b) ON CONFLICT ROLLBACK);"); + QTest::newRow("179") << std::string("CREATE TABLE t3_ig(a, b, UNIQUE(a, b) ON CONFLICT IGNORE);"); + QTest::newRow("180") << std::string("CREATE TABLE t3_fa(a, b, UNIQUE(a, b) ON CONFLICT FAIL);"); + QTest::newRow("181") << std::string("CREATE TABLE t3_re(a, b, UNIQUE(a, b) ON CONFLICT REPLACE);"); + QTest::newRow("182") << std::string("CREATE TABLE t3_xx(a, b, UNIQUE(a, b));"); + QTest::newRow("183") << std::string("CREATE TABLE t4(a, b CHECK (b!=10));"); + QTest::newRow("184") << std::string("CREATE TABLE t2(oid, b);"); + QTest::newRow("185") << std::string("CREATE TABLE t3(a, _rowid_);"); + QTest::newRow("186") << std::string("CREATE TABLE t4(a, b, rowid);"); + QTest::newRow("187") << std::string("CREATE TABLE t5(pk integer primary key)"); + QTest::newRow("188") << std::string("CREATE TABLE t5(pk integer, primary key(pk))"); + QTest::newRow("189") << std::string("CREATE TABLE t5(pk integer, v integer, primary key(pk))"); + QTest::newRow("190") << std::string("CREATE TABLE t5(pk integer, v integer, primary key(pk, v))"); + QTest::newRow("191") << std::string("CREATE TABLE t5(pk int, v integer, primary key(pk, v))"); + QTest::newRow("192") << std::string("CREATE TABLE t5(pk int, v integer, primary key(pk))"); + QTest::newRow("193") << std::string("CREATE TABLE t5(pk int primary key, v integer)"); + QTest::newRow("194") << std::string("CREATE TABLE t5(pk inTEger primary key)"); + QTest::newRow("195") << std::string("CREATE TABLE t5(pk inteGEr, primary key(pk))"); + QTest::newRow("196") << std::string("CREATE TABLE t5(pk INTEGER, v integer, primary key(pk))"); + QTest::newRow("197") << std::string("CREATE TABLE t6(pk INT primary key);"); + QTest::newRow("198") << std::string("CREATE TABLE t7(pk BIGINT primary key);"); + QTest::newRow("199") << std::string("CREATE TABLE t8(pk SHORT INTEGER primary key);"); + QTest::newRow("200") << std::string("CREATE TABLE t9(pk UNSIGNED INTEGER primary key);"); + QTest::newRow("201") << std::string("CREATE TABLE t(x INTEGER PRIMARY KEY ASC, y, z)"); + QTest::newRow("202") << std::string("CREATE TABLE t(x INTEGER, y, z, PRIMARY KEY(x ASC))"); + QTest::newRow("203") << std::string("CREATE TABLE t(x INTEGER, y, z, PRIMARY KEY(x DESC))"); + QTest::newRow("204") << std::string("CREATE TABLE t(x INTEGER PRIMARY KEY DESC, y, z)"); } diff --git a/src/tests/testsqlobjects.h b/src/tests/testsqlobjects.h index c31569b2a..76a361c57 100644 --- a/src/tests/testsqlobjects.h +++ b/src/tests/testsqlobjects.h @@ -8,24 +8,45 @@ class TestTable: public QObject Q_OBJECT private slots: void sqlOutput(); + void sqlGraveAccentOutput(); + void sqlSquareBracketsOutput(); void autoincrement(); void notnull(); void withoutRowid(); + void strict(); + void strictAndWithoutRowid(); void foreignKeys(); + void uniqueConstraint(); void parseSQL(); + void parseSQLSquareBrackets(); void parseSQLdefaultexpr(); void parseSQLMultiPk(); void parseSQLForeignKey(); void parseSQLSingleQuotes(); void parseSQLKeywordInIdentifier(); + void parseSQLSomeKeywordsInIdentifier(); void parseSQLWithoutRowid(); + void parseSQLStrictTable(); + void parseSQLStrictAndWithoutRowidTable(); void parseNonASCIIChars(); + void parseNonASCIICharsEs(); void parseSQLEscapedQuotes(); void parseSQLForeignKeys(); void parseSQLCheckConstraint(); + void parseDefaultValues(); void createTableWithIn(); void createTableWithNotLikeConstraint(); + void rowValues(); + void complexExpressions(); + void datetimeExpression(); + void extraParentheses(); + void moduloOperator(); + void complexExpression(); + void parseIdentifierWithDollar(); + + void parseTest(); + void parseTest_data(); }; #endif diff --git a/src/tools/create_windows_icon.sh b/src/tools/create_windows_icon.sh index 879845c81..c46df6f8e 100755 --- a/src/tools/create_windows_icon.sh +++ b/src/tools/create_windows_icon.sh @@ -1,12 +1,19 @@ -#!/bin/sh +#!/usr/bin/env sh -# This script depends on imagemagick being installed +# This script depends on ImageMagick being installed +FILES=() # array accumulating names of converted images +# commands to give to convert for each iteration +MAGICK_CMDS="+antialias -units PixelsPerInch -alpha set -background transparent" +SRC_FILE="../../images/logo.svg" # conversion source +ICO_FILE="../iconwin.ico" # output icon file for imgsize in 16 32 64 128 do - convert ../icons/sqlitebrowser.png -resize "$imgsize"x"$imgsize" -background transparent icon"$imgsize".png - files="$files icon$imgsize.png" + RESIZE="${imgsize}x${imgsize}" + DEST_FILE="icon${imgsize}.png" + # NOTE: explicitly not using quotes - outpput raw contents to convert command + convert ${MAGICK_CMDS} ${SRC_FILE} -resize ${RESIZE} ${DEST_FILE} + FILES+=("${DEST_FILE}") done - -convert $files ../iconwin.ico -rm $files +convert "${FILES[@]}" "${ICO_FILE}" +rm "${FILES[@]}" diff --git a/src/translations/flags/ar.png b/src/translations/flags/ar.png new file mode 100644 index 000000000..ade5ca312 Binary files /dev/null and b/src/translations/flags/ar.png differ diff --git a/src/translations/flags/cn.png b/src/translations/flags/cn.png index 85434125d..c658f073a 100644 Binary files a/src/translations/flags/cn.png and b/src/translations/flags/cn.png differ diff --git a/src/translations/flags/cs.png b/src/translations/flags/cs.png new file mode 100644 index 000000000..f8f671a72 Binary files /dev/null and b/src/translations/flags/cs.png differ diff --git a/src/translations/flags/de.png b/src/translations/flags/de.png index e1e87e0ca..0b3b41f08 100644 Binary files a/src/translations/flags/de.png and b/src/translations/flags/de.png differ diff --git a/src/translations/flags/eg.png b/src/translations/flags/eg.png new file mode 100644 index 000000000..7d67af974 Binary files /dev/null and b/src/translations/flags/eg.png differ diff --git a/src/translations/flags/flags.qrc b/src/translations/flags/flags.qrc index 9fcb9381c..632cfe2a7 100644 --- a/src/translations/flags/flags.qrc +++ b/src/translations/flags/flags.qrc @@ -1,9 +1,12 @@ + ar.png + cs.png de.png es.png us.png fr.png + it.png ru.png cn.png br.png @@ -11,5 +14,13 @@ roc.png kr.png tr.png + ua.png + eg.png + pl.png + jp.png + nl.png + sv.png + id.png + ro.png diff --git a/src/translations/flags/fr.png b/src/translations/flags/fr.png index 7a815dd06..7fe158cee 100644 Binary files a/src/translations/flags/fr.png and b/src/translations/flags/fr.png differ diff --git a/src/translations/flags/id.png b/src/translations/flags/id.png new file mode 100644 index 000000000..c20e5c4ea Binary files /dev/null and b/src/translations/flags/id.png differ diff --git a/src/translations/flags/it.png b/src/translations/flags/it.png new file mode 100644 index 000000000..6bd49964c Binary files /dev/null and b/src/translations/flags/it.png differ diff --git a/src/translations/flags/jp.png b/src/translations/flags/jp.png new file mode 100644 index 000000000..325fbad3f Binary files /dev/null and b/src/translations/flags/jp.png differ diff --git a/src/translations/flags/nl.png b/src/translations/flags/nl.png new file mode 100644 index 000000000..99814aa9c Binary files /dev/null and b/src/translations/flags/nl.png differ diff --git a/src/translations/flags/pl.png b/src/translations/flags/pl.png new file mode 100644 index 000000000..d8ca17ce9 Binary files /dev/null and b/src/translations/flags/pl.png differ diff --git a/src/translations/flags/ro.png b/src/translations/flags/ro.png new file mode 100644 index 000000000..c577dfe7c Binary files /dev/null and b/src/translations/flags/ro.png differ diff --git a/src/translations/flags/ru.png b/src/translations/flags/ru.png index 744db41e6..e634822ec 100644 Binary files a/src/translations/flags/ru.png and b/src/translations/flags/ru.png differ diff --git a/src/translations/flags/sv.png b/src/translations/flags/sv.png new file mode 100644 index 000000000..f58768e1d Binary files /dev/null and b/src/translations/flags/sv.png differ diff --git a/src/translations/flags/ua.png b/src/translations/flags/ua.png new file mode 100644 index 000000000..cedf50226 Binary files /dev/null and b/src/translations/flags/ua.png differ diff --git a/src/translations/flags/us.png b/src/translations/flags/us.png index ddd6c6122..10db15e8f 100644 Binary files a/src/translations/flags/us.png and b/src/translations/flags/us.png differ diff --git a/src/translations/sqlb_ar_SA.ts b/src/translations/sqlb_ar_SA.ts new file mode 100644 index 000000000..792aef723 --- /dev/null +++ b/src/translations/sqlb_ar_SA.ts @@ -0,0 +1,8071 @@ + + + + + AboutDialog + + + About DB Browser for SQLite + عن «متصÙّح قواعد بيانات SQLite» + + + + Version + الإصدارة + + + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + + + + + AddRecordDialog + + + Add New Record + أضÙ٠سجلًا جديدًا + + + + Enter values for the new record considering constraints. Fields in bold are mandatory. + أدخÙÙ„ قيم السجلّ الجديد بأخذ القيود بعين الاعتبار. الحقول الثخينة ضرورية. + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + يمكنك تحديد قيمة الحقل المحدّد ÙÙŠ عمود â€Ø§Ù„اسم“ وذلك ÙÙŠ عمود â€Ø§Ù„قيمة“. ÙŠÙØ´ÙŠØ± عمود â€Ø§Ù„نوع“ إلى نوع الحقل. ØªÙØ¹Ø±Ø¶ القيم المبدئية Ø¨Ù†ÙØ³ نمط قيم NULL. + + + + Name + الاسم + + + + Type + النوع + + + + Value + القيمة + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + القيم التي Ø³ØªÙØ¯Ø±Ø¬. لو لم تتغيّر ÙØ³Ùتدرج آليًا القيم المبدئية المعبّأة مسبقًا. + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + عندما تحرّر القيم ÙÙŠ الإطار أعلاه، ستظهر هنا Ø¥ÙØ§Ø¯Ø© SQL لإدراج هذا السجلّ. يمكنك تحرير Ø§Ù„Ø¥ÙØ§Ø¯Ø© يدويًا قبل Ø§Ù„Ø­ÙØ¸. + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <p>Ø³ÙŠÙØ±Ø³Ù„ زر <span style=" font-weight:600;">Ø§Ø­ÙØ¸</span> Ø¥ÙØ§Ø¯Ø© SQL الظاهرة إلى قاعدة البيانات لإدراج السجلّ الجديد.</p><p>سيستعيد زر <span style=" font-weight:600;">استعد المبدئيات</span> القيمة الأولية ÙÙŠ عمود â€<span style=" font-weight:600;">القيمة</span>“.</p><p>Ø³ÙŠÙØºÙ„Ù‚ زر <span style=" font-weight:600;">ألغÙ</span> مربّع الحوار هذا دون تنÙيذ الاستعلام.</p> + + + + Auto-increment + + زيادة آليّة + + + + + Unique constraint + + قيد â€Ùريد“ + + + + + Check constraint: %1 + + قيد Ø§Ù„ÙØ­Øµ: %L1 + + + + + Foreign key: %1 + + Ø§Ù„Ù…ÙØªØ§Ø­ الأجنبي: %L1 + + + + + Default value: %1 + + القيمة المبدئية: %L1 + + + + + Error adding record. Message from database engine: + +%1 + خطأ أثناء Ø¥Ø¶Ø§ÙØ© السجلّ. الرسالة من محرّك قواعد البيانات: + +%L1 + + + + Are you sure you want to restore all the entered values to their defaults? + أمتأكّد من استعادة كلّ القيم Ø§Ù„Ù…ÙØ¯Ø®Ù„Ø© إلى مبدئياتها؟ + + + + Application + + + Possible command line arguments: + معطيات سطر الأوامر الممكنة: + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + يطلب الخياران ‎-o/--option Ùˆ ‎-O/--save-option معطًى بهذا النحو: group/setting=value + + + + The user settings file location is replaced with the argument value instead of the environment variable value. + + + + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + + + + + + The file %1 does not exist + المل٠%L1 غير موجود + + + + Usage + + + + + options + + + + + + database + + + + + + project + + + + + + csv-file + + + + + Show command line options + + + + + Exit application after running scripts + + + + + + file + + + + + Execute this SQL file after opening the DB + + + + + Import this CSV file into the passed DB or into a new DB + + + + + table + + + + + Browse this table, or use it as target of a data import + + + + + Open database in read-only mode + + + + + settings_file + + + + + Run application based on this settings file + + + + + + group + + + + + + settings + + + + + + value + + + + + Run application with this setting temporarily set to value + + + + + Run application saving this value for this setting + + + + + Display the current version + + + + + Open this SQLite database + + + + + Open this project file (*.sqbpro) + + + + + Import this CSV file into an in-memory database + + + + + + + The %1 option requires an argument + + + + + The -S/--settings option requires an argument. The option is ignored. + + + + + Invalid option/non-existent file: %1 + خيار غير صالح/مل٠غير موجود: %L1 + + + + SQLite Version + إصدارة SQLite: †+ + + + SQLCipher Version %1 (based on SQLite %2) + إصدارة SQLCipher:†%L1 (مبنيّة على SQLite %L2) + + + + DB Browser for SQLite Version %1. + «متصÙّح قواعد بيانات SQLite» الإصدارة %L1. + + + + Last commit hash when built: %1 + + + + + Built for %1, running on %2 + مبنيّة للمعماريّة %L1ØŒ وتعمل على المعماريّة %L2 + + + + Qt Version %1 + إصدارة كيوت: %L1 + + + + CipherDialog + + + SQLCipher encryption + تعمية SQLCipher + + + + &Password + &كلمة السر + + + + &Reenter password + Ø£&Ø¹ÙØ¯ إدخال كلمة السر + + + + Encr&yption settings + إعدادات التع&مية + + + + SQLCipher &3 defaults + مبدئيّات SQLCipher &3 + + + + SQLCipher &4 defaults + مبدئيّات SQLCipher &4 + + + + Custo&m + Ù…&خصّص + + + + Page si&ze + Ù…&قاس Ø§Ù„ØµÙØ­Ø© + + + + &KDF iterations + ت&كرارات KDF + + + + HMAC algorithm + خوارزميّة HMAC + + + + KDF algorithm + خوارزميّة KDF + + + + Plaintext Header Size + حجم ترويسة النص البائن + + + + Passphrase + عبارة سر + + + + Raw key + Ù…ÙØªØ§Ø­ خام + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + من ÙØ¶Ù„Ùƒ اضبط Ù…ÙØªØ§Ø­Ù‹Ø§ لتعمية قاعدة البيانات. +لو غيّرت أيًا من الإعدادات الأخرى (الاختيارية)ØŒ ÙØ³ÙŠÙƒÙˆÙ† عليك إعادة إدخالها أيضًا ÙÙŠ كلّ مرّة ØªÙØªØ­ Ùيها مل٠قاعدة البيانات. +اترك حقول كلمة السر ÙØ§Ø±ØºØ© لتعطيل التعمية. +قد تأخذ عملية التعمية وقتًا وعليك Ø§Ù„Ø§Ø­ØªÙØ§Ø¸ بنسخة من قاعدة البيانات احتياطًا! Ø³ØªÙØ·Ø¨Ù‘Ù‚ التعديلات غير المحÙوظة قبل تعديل التعمية. + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + من ÙØ¶Ù„Ùƒ أدخÙÙ„ Ø§Ù„Ù…ÙØªØ§Ø­ المستعمل لتعمية قاعدة البيانات. +إن كانت هناك إعدادات أخرى قد تغيّرت ÙÙŠ مل٠قاعدة البيانات هذا، ÙØ¹Ù„يك ذكر ذلك أيضًا. + + + + ColumnDisplayFormatDialog + + + Choose display format + اختر تنسيق العرض + + + + Display format + تنسيق العرض + + + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + اختر تنسيق عرض العمود â€%L1“ Ù„ÙŠÙØ·Ø¨Ù‘Ù‚ على كلّ قيمة قبل عرضها. + + + + Default + المبدئي + + + + Decimal number + عدد عشري + + + + Exponent notation + تدوين Ø£ÙØ³Ù‘ÙŠ + + + + Hex blob + â€BLOB ستّ‌عشري + + + + Hex number + عدد ستّ‌عشري + + + + Apple NSDate to date + â€ØªØ§Ø±ÙŠØ® آبل/Apple NSDate“ إلى تاريخ + + + + Java epoch (milliseconds) to date + عَصر جاڤا (ملّي‌ثانية) إلى تاريخ + + + + .NET DateTime.Ticks to date + â€DateTime.Ticks من ‎.NET إلى تاريح + + + + Julian day to date + يوم جولياني إلى تاريخ + + + + Unix epoch to local time + عَصر لينكس إلى الوقت المحلي + + + + WebKit / Chromium epoch to date + + + + + WebKit / Chromium epoch to local time + + + + + Date as dd/mm/yyyy + التاريخ بتنسيق dd/mm/yyyy + + + + Lower case + حالة الأحر٠صغيرة + + + + Binary GUID to text + + + + + SpatiaLite Geometry to SVG + + + + + Custom display format must contain a function call applied to %1 + على تنسيق العرض المخصّص أن يحتوي على نداء دالة مطبّق على %L1 + + + + Error in custom display format. Message from database engine: + +%1 + خطأ ÙÙŠ تنسيق العرض المخصّص. الرسالة من محرّك قواعد البيانات: +%L1 + + + + Custom display format must return only one column but it returned %1. + على تنسيق العرض المخصّص إعادة عمود واحد Ùقط، لكنّه أعاد %L1. + + + + Octal number + عدد ثماني + + + + Round number + عدد تقريبي + + + + Unix epoch to date + عَصر لينكس إلى تاريخ + + + + Upper case + حالة الأحر٠كبيرة + + + + Windows DATE to date + â€ØªØ§Ø±ÙŠØ® وندوز/Windows DATE“ إلى تاريخ + + + + Custom + مخصّص + + + + CondFormatManager + + + Conditional Format Manager + مدير التنسيقات الشرطيّة + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + ÙŠÙØªÙŠØ­ لك مربّع الحوار هذا إنشاء التنسيقات الشرطيّة وتحريرها. ستختار البرمجيّة كلّ نمط خلايا حسب أوّل شرط متواÙÙ‚ مع بيانات الخليّة. يمكنك نقل التنسيقات الشرطيّة إلى أعلى وأسÙÙ„ØŒ حيث تعبّر أعلاها أكثرها أولويّة، والعكس. صياغة الشروط هي Ù†ÙØ³Ù‡Ø§ صياغة المرشّحات، والشروط Ø§Ù„ÙØ§Ø±ØºØ© تنطبق على كلّ القيم. + + + + Add new conditional format + أضÙ٠تنسيقًا شرطيًا جديدًا + + + + &Add + Ø£&ضÙÙ + + + + Remove selected conditional format + أزÙÙ„ التنسيق الشرطيّ المحدّد + + + + &Remove + Ø£&زÙÙ„ + + + + Move selected conditional format up + انقل التنسيق الشرطيّ المحدّد لأعلى + + + + Move &up + انقل لأ&على + + + + Move selected conditional format down + انقل التنسيق الشرطيّ المحدّد لأسÙÙ„ + + + + Move &down + انقل لأ&سÙÙ„ + + + + Foreground + الأمامية + + + + Text color + لون النص + + + + Background + الخلÙية + + + + Background color + لون الخلÙية + + + + Font + الخط + + + + Size + الحجم + + + + Bold + ثخين + + + + Italic + مائل + + + + Underline + مسطّر + + + + Alignment + المحاذاة + + + + Condition + الشرط + + + + + Click to select color + انقر لاختيار لون + + + + Are you sure you want to clear all the conditional formats of this field? + أمتأكّد من مسح كلّ التنسيقات الشرطيّة لهذا الحقل؟ + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + من ÙØ¶Ù„Ùƒ اختر اسم قاعدة البيانات الذي تريد استعماله للوصول إلى قاعدة البيانات المرÙقة + + + + Invalid file format + تنسيق المل٠غير صالح + + + + Do you want to save the changes made to the database file %1? + أتريد Ø­ÙØ¸ التعديلات Ø§Ù„Ù…ÙØ¬Ø±Ø§Ø© على مل٠قاعدة البيانات %L1ØŸ + + + + Exporting database to SQL file... + يصدّر قاعدة البيانات إلى مل٠SQL... + + + + + Cancel + ألغ٠+ + + + Executing SQL... + ينÙّذ SQL... + + + + Action cancelled. + Ø£Ùلغي الإجراء. + + + + Do you really want to close this temporary database? All data will be lost. + أمتأكّد من إغلاق قاعدة البيانات المؤقّتة هذه؟ ستÙقد كلّ البيانات. + + + + Database didn't close correctly, probably still busy + لم ØªÙØºÙ„Ù‚ قاعدة البيانات كما ينبغي، ربّما هي مشغولة + + + + Cannot open destination file: '%1' + + + + + + Cannot backup to file: '%1'. Message: %2 + + + + + The database is currently busy: + قاعدة البيانات مشغولة حاليًا: + + + + Do you want to abort that other operation? + أتريد إجهاض العملية الأخرى؟ + + + + + No database file opened + لم ÙŠÙÙØªØ­ مل٠قاعدة بيانات + + + + + Error in statement #%1: %2. +Aborting execution%3. + خطأ ÙÙŠ Ø§Ù„Ø¥ÙØ§Ø¯Ø© رقم %L1:†%L2. +Ø³Ø£ÙØ¬Ù‡Ø¶ التنÙيذ%L3. + + + + + and rolling back + ÙˆØ£ÙØ±Ø¬Ø¹ ما كان موجودًا. + + + + didn't receive any output from %1 + لم أستلم أيّ ناتج من %L1 + + + + could not execute command: %1 + تعذّر تنÙيذ الأمر: %L1 + + + + Cannot delete this object + تعذّر حذ٠هذا الكائن + + + + Cannot set data on this object + تعذّر ضبط البيانات على هذا الكائن + + + + + A table with the name '%1' already exists in schema '%2'. + هناك جدول Ø¨Ù†ÙØ³ الاسم â€%L1“ Ø¨Ø§Ù„ÙØ¹Ù„ ÙÙŠ المخطّط â€%L2“. + + + + No table with name '%1' exists in schema '%2'. + ما من جدول له الاسم â€%L1“ ÙÙŠ المخطّط â€%L2“. + + + + + Cannot find column %1. + تعذّر العثور على العمود %L1 + + + + Creating savepoint failed. DB says: %1 + ÙØ´Ù„ إنشاء نقطة Ø§Ù„Ø­ÙØ¸. تقول قاعدة البيانات: %L1 + + + + Renaming the column failed. DB says: +%1 + ÙØ´Ù„ تغيير اسم العمود. تقول قاعدة البيانات: +%L1 + + + + + Releasing savepoint failed. DB says: %1 + ÙØ´Ù„ت استعداة نقطة Ø§Ù„Ø­ÙØ¸. تقول قاعدة البيانات: %L1 + + + + Creating new table failed. DB says: %1 + ÙØ´Ù„ إنشاء جدول جديد. تقول قاعدة البيانات: %L1 + + + + Copying data to new table failed. DB says: +%1 + ÙØ´Ù„ نسخ البيانات إلى جدول جديد. تقول قاعدة البيانات: +%L1 + + + + Deleting old table failed. DB says: %1 + ÙØ´Ù„ حذ٠الجدول القديم. تقول قاعدة البيانات: %L1 + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + خطأ ÙÙŠ تغيير اسم الجدول â€%L1“ إلى â€%L2“. +الرسالة من محرّك قواعد البيانات: +%L3 + + + + could not get list of db objects: %1 + تعذّر جلب قائمة كائنات قواعد البيانات: %L1 + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + ÙØ´Ù„ت استعادة بعض الكائنات المرتبطة بهذا الجدول. غالبًا ما يحدث هذا بسبب تغيّر اسم الأعمدة. هذه Ø¥ÙØ§Ø¯Ø© SQL التي قد ترغب بتنÙيذها لإصلاح ذلك يدويًا: + + + + + + could not get list of databases: %1 + تعذّر جلب قائمة قواعد البيانات: %L1 + + + + Error loading extension: %1 + خطأ أثناء تحميل الامتداد: %L1 + + + + Error loading built-in extension: %1 + + + + + could not get column information + تعذّر جلب معلومات العمود + + + + Error setting pragma %1 to %2: %3 + تعذّر ضبط pragma %L1 إلى %L2:†%L3 + + + + File not found. + تعذّر العثور على الملÙ. + + + + DbStructureModel + + + Name + الاسم + + + + Object + الكائن + + + + Type + النوع + + + + Schema + المخطّط + + + + Database + قاعدة البيانات + + + + Browsables + ما يمكنك تصÙّحه + + + + All + الكلّ + + + + Temporary + مؤقّتة + + + + Tables (%1) + الجداول (%L1) + + + + Indices (%1) + الÙهارس (%L1) + + + + Views (%1) + المناظير (%L1) + + + + Triggers (%1) + المحÙّزات (%L1) + + + + EditDialog + + + Edit database cell + تحرير خليّة قاعدة البيانات + + + + Mode: + الوضع: + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + هذه قائمة بالأوضاع المتوÙّرة ÙÙŠ محرّر الخلايا. اختر وضعًا لعرض أو تحرير البيانات ÙÙŠ الخليّة الحالية. + + + + Text + نصوص + + + + RTL Text + نصوص من اليمين إلى اليسار + + + + Binary + بيانات ثنائيّة + + + + + Image + صور + + + + JSON + JSON + + + + XML + XML + + + + Evaluation + + + + + + Automatically adjust the editor mode to the loaded data type + اضبط وضع المحرّر آليًا على نوع البيانات المحمّل + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + ÙŠÙÙØ¹Ù‘Ù„/ÙŠÙØ¹Ø·Ù‘Ù„ هذا الزر التبديل التلقائي لوضع المحرّر. متى حدّدت خليّة جديدة أو استوردت بيانات جديدة ويÙÙØ¹Ù‘Ù„ التبديل الآلي سترى بأنّ الوضع Ø³ÙŠÙØ¶Ø¨Ø· على نوع البيانات المكتشÙ. يمكنك بعدها تغيير وضع المحرّر يدويًا. لو أردت أن يكون التبديل يدويًا عند الانتقال بين الخلايا، ÙØ¹Ø·Ù‘Ù„ هذا الزر. + + + + Auto-switch + التبديل الآلي + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + ÙŠÙØ³ØªØ¹Ù…Ù„ محرّر «كيوت» هذا للغات المكتوبة من اليمين إلى اليسار (مثل العربيّة) إذ لا يدعمها محرّر النصوص المبدئي. لو كتبت حرو٠لغة تÙكتب من اليمين إلى اليسار، ÙØ³ØªÙƒØªØ´Ù البرمجيّة ذلك وتحدّد وضع الخليّة هذا تلقائيًا. + + + + Identification of the cell currently in the editor + + + + + Type and size of data currently in table + + + + + Open preview dialog for printing the data currently stored in the cell + Ø§ÙØªØ­ مربّع حوار معاينة طباعة البيانات المخزّنة ÙÙŠ الخليّة حاليًا + + + + Auto-format: pretty print on loading, compact on saving. + التنسيق الآلي: طباعة جميلة (pretty print) عند التحميل، رصّ عند Ø§Ù„Ø­ÙØ¸. + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + إن ÙØ¹Ù‘لت الخيار ÙØ³ØªÙنسّق ميزة التنسيق الآلي البياناتَ متى تحمّلت، ÙØªÙƒØ³Ø± النصوص إلى أسطر ÙˆØªÙØ²ÙŠØ­Ù‡Ø§ لزيادة مقروؤيتها. وعند Ø­ÙØ¸ البيانات ترصّ ميزة التنسيق الآلي البياناتَ بإزالة نهايات الأسطر ÙˆØ§Ù„Ù…Ø³Ø§ÙØ§Øª غير اللازمة. + + + + Word Wrap + Ù„ÙÙ‘ الأسطر + + + + Wrap lines on word boundaries + Ù„ÙÙÙ‘ الأسطر عند حدود الكلمات + + + + + Open in default application or browser + Ø§ÙØªØ­ ÙÙŠ التطبيق المبدئي أو المتصÙّح + + + + Open in application + Ø§ÙØªØ­ ÙÙŠ التطبيق + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + ØªÙØ­Ù„ّل البرمجيّة القيمة على أنّها مل٠أو مسار ÙˆØªÙØªØ­Ù‡ ÙÙŠ التطبيق المبدئي أو ÙÙŠ متصÙّح الوب. + + + + Save file reference... + Ø§Ø­ÙØ¸ إشارة إلى الملÙ... + + + + Save reference to file + Ø§Ø­ÙØ¸ إشارة إلى الملÙ... + + + + + Open in external application + Ø§ÙØªØ­ ÙÙŠ تطبيق خارجي + + + + Autoformat + التنسيق الآلي + + + + &Export... + &صدّر... + + + + + &Import... + ا&Ø³ØªÙˆØ±ÙØ¯... + + + + + Import from file + Ø§Ø³ØªÙˆØ±ÙØ¯ من مل٠+ + + + + Opens a file dialog used to import any kind of data to this database cell. + ÙŠÙØªØ­ مربّع حوار Ù…Ù„ÙØ§Øª ÙŠÙØ³ØªØ¹Ù…Ù„ لاستيراد أيّ نوع من البيانات ÙÙŠ خليّة قاعدة البيانات هذه. + + + + Export to file + صدّر إلى مل٠+ + + + Opens a file dialog used to export the contents of this database cell to a file. + ÙŠÙØªØ­ مربّع حوار Ù…Ù„ÙØ§Øª ÙŠÙØ³ØªØ¹Ù…Ù„ لتصدير محتويات خليّة قاعدة البيانات هذه إلى ملÙ. + + + + Print... + اطبع... + + + + Ctrl+P + Ctrl+P + + + + Open preview dialog for printing displayed text + ÙŠÙØªØ­ مربّع حوار المعاينة لطباعة النص المعروض + + + + Copy Hex and ASCII + انسخ Hex وآسكي + + + + Copy selected hexadecimal and ASCII columns to the clipboard + انسخ الأعمدة الستّ‌عشرية وآسكي المحدّدة إلى Ø§Ù„Ø­Ø§ÙØ¸Ø© + + + + Ctrl+Shift+C + Ctrl+Shift+C + + + + Erases the contents of the cell + يمسح محتويات هذه الخليّة + + + + Set as &NULL + ا&ضبط على NULL + + + + This area displays information about the data present in this database cell + تعرض هذه المنطقة معلومات عن البيانات الموجودة ÙÙŠ خليّة قاعدة البيانات هذه + + + + Apply data to cell + طبّق البيانات على الخليّة + + + + This button saves the changes performed in the cell editor to the database cell. + ÙŠØ­ÙØ¸ هذا الزر التغييرات Ø§Ù„Ù…ÙØ¬Ø±Ø§Ø© داخل محرّر الخلايا ÙÙŠ خليّة قاعدة البيانات. + + + + Apply + طبّق + + + + Choose a filename to export data + اختر اسمًا للمل٠لتصدير البيانات + + + + + Image data can't be viewed in this mode. + لا يمكن عرض بيانات الصور ÙÙŠ هذا الوضع. + + + + + Try switching to Image or Binary mode. + جرّب الانتقال إلى وضع â€ØµÙˆØ±â€œ أو â€Ø¨ÙŠØ§Ù†Ø§Øª ثنائيّة“. + + + + + Binary data can't be viewed in this mode. + لا يمكن عرض البيانات الثنائيّة ÙÙŠ هذا الوضع. + + + + + Try switching to Binary mode. + جربّ الانتقال إلى وضع â€Ø¨ÙŠØ§Ù†Ø§Øª ثنائيّة“. + + + + + Image files (%1) + Ù…Ù„ÙØ§Øª الصور (%L1) + + + + Binary files (*.bin) + Ø§Ù„Ù…Ù„ÙØ§Øª الثنائيّة (*.bin) + + + + Choose a file to import + اختر ملÙًا لاستيراده + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + + + + + Unsaved data in the cell editor + + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + + + + + Editing row=%1, column=%2 + + + + + No cell active. + + + + + %1 Image + صورة %L1 + + + + Invalid data for this mode + بيانات غير صالحة ÙÙŠ هذا الوضع + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + تحتوي الخليّة بيانات %L1 غير صالحة. السبب: %L2. أمتأكّد من تطبيقها على الخليّة؟ + + + + + Type: NULL; Size: 0 bytes + + + + + + Type: Text / Numeric; Size: %n character(s) + + + + + + + + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + + + + + Type: Valid JSON; Size: %n character(s) + + + + + + + + + + + + Type: Binary; Size: %n byte(s) + + + + + + + + + + + + Couldn't save file: %1. + تعذّر Ø­ÙØ¸ الملÙ: %L1. + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + + + + + EditIndexDialog + + + &Name + الا&سم + + + + Order + الترتيب + + + + &Table + الج&دول + + + + Edit Index Schema + تحرير مخطّط الÙهرس + + + + &Unique + &ÙØ±ÙŠØ¯ + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + إن أردت حصر الÙهرس على جزء من الجدول ÙØ­Ø³Ø¨ØŒ يمكنك هنا تحديد بند WHERE Ù„ÙŠÙØ­Ø¯Ù‘د جزء الجدول الذي يجب Ùهرسته + + + + Partial inde&x clause + بند Ù&هرس جزئي + + + + Colu&mns + الأ&عمدة + + + + Table column + عمود الجدول + + + + Type + النوع + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + أضÙ٠عمود تعبير جديد إلى الÙهرس. تحتوي أعمدة التعابير على تعابير SQL بدل أسماء الأعمدة. + + + + Index column + عمود الÙهرس + + + + Deleting the old index failed: +%1 + ÙØ´Ù„ حذ٠الÙهرس القديم: +%L1 + + + + Creating the index failed: +%1 + ÙØ´Ù„ إنشاء الÙهرس: +%L1 + + + + EditTableDialog + + + Edit table definition + تحرير تعري٠الجدول + + + + Table + الجدول + + + + Advanced + متقدّم + + + + Without Rowid + بلا معرّ٠للصÙÙˆÙ + + + + Fields + الحقول + + + + Database sche&ma + مخ&طّط قاعدة البيانات + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + + + + + On Conflict + + + + + Strict + + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + + + + + + + Add + أضÙÙ + + + + + + Remove + أزÙÙ„ + + + + Move to top + انقل للأعلى + + + + Move up + انقل لأعلى + + + + Move down + انقل لأسÙÙ„ + + + + Move to bottom + انقل للأسÙÙ„ + + + + + + + Name + الاسم + + + + + Type + النوع + + + + NN + NN + + + + Not null + ليس NULL + + + + PK + PK + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + + + + + AI + AI + + + + Autoincrement + زيادة آليّة Auto Increment + + + + U + U + + + + + + Unique + ÙØ±ÙŠØ¯ Unique + + + + Default + المبدئي + + + + Default value + القيمة المبدئية + + + + + Check + Ø§Ù„ÙØ­Øµ + + + + Check constraint + قيد Ø§Ù„ÙØ­Øµ Check constraint + + + + Collation + قواعد مقارنة المحار٠+ + + + Foreign Key + Ù…ÙØªØ§Ø­ أجنبي + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + + + + + Index Constraints + + + + + Add constraint + أضÙ٠قيدًا + + + + Remove constraint + أزÙÙ„ القيد + + + + + Columns + الأعمدة + + + + + + SQL + SQL + + + + Foreign Keys + + + + + References + + + + + Check Constraints + + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <span style=" font-weight:600; color:#ff0000;">تحذير: </span>ثمّة خطب بتعري٠هذا الجدول تعذّر على المحلّل Ùهمه تمامًا. يمكن أن يؤدّي تعديل ÙˆØ­ÙØ¸ هذا الجدول إلى بعض المشاكل. + + + + + Primary Key + Ù…ÙØªØ§Ø­ أساسي + + + + Add a primary key constraint + أضÙ٠قيد ÙØ±Ø¶ Ù…ÙØªØ§Ø­ أساسي + + + + Add a unique constraint + أضÙ٠قيد ÙØ±Ø¶ â€Ùريد“ + + + + Error creating table. Message from database engine: +%1 + خطأ أثناء إنشاء الجدول. الرسالة من محرّك قواعد البيانات: +%L1 + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + هناك حقل بهذا الاسم Ø¨Ø§Ù„ÙØ¹Ù„. من ÙØ¶Ù„Ùƒ غيّر اسمه أو اختر اسمًا مختلÙًا لهذا الحقل. + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + لكلّ جدول Ù…ÙØªØ§Ø­ أساسي واحد Ùقط. من ÙØ¶Ù„Ùƒ عدّل Ø§Ù„Ù…ÙØªØ§Ø­ الموجود بدل هذا الأمر. + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + هذا العمود مذكور ÙÙŠ Ù…ÙØªØ§Ø­ أجنبي ÙÙŠ الجدول %L1 ولا يمكن تغيير اسمه. + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + ثمّة صÙÙ‘ واحد على الأقل Ø¶ÙØ¨Ø· هذا الحقل Ùيه على NULL. لهذا السبب يستحيل ضبط هذه الراية. من ÙØ¶Ù„Ùƒ غيّر بيانات الجدول أوّلًا. + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + ثمّة صÙÙ‘ واحد على الأقل Ø¶ÙØ¨Ø· هذا الحقل Ùيه على قيمة ليست بنوع â€Ø¹Ø¯Ø¯ صحيح“. لهذا السبب يستحيل ضبط راية الزيادة الآليّة. من ÙØ¶Ù„Ùƒ غيّر بيانات الجدول أوّلًا. + + + + Column '%1' has duplicate data. + + ÙÙŠ العمود â€%L1“ بيانات متكرّرة. + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + يمنع هذا ØªÙØ¹ÙŠÙ„ راية â€Ùريد“. من ÙØ¶Ù„Ùƒ أزÙÙ„ البيانات المتكرّرة كي تقدر على ØªÙØ¹ÙŠÙ„ هذه الراية. + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + أمتأكّد من حذ٠الحقل â€%L1“؟ +ستÙقد كل البيانات المخزّنة Ùيه حاليًا. + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + من ÙØ¶Ù„Ùƒ أضÙ٠حقلًا ÙŠÙØ·Ø§Ø¨Ù‚ المعايير الآتية قبل ضبط راية â€Ø¨Ù„ا معرّ٠صÙÙˆÙ/rowid“: + - راية â€Ù…ÙØªØ§Ø­ أساسي“ مضبوطة + - الزيادة الآلية معطّلة + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + + + + + ExportDataDialog + + + Export data as CSV + تصدير البيانات بنسق CSV + + + + Tab&le(s) + الج&داول + + + + Colu&mn names in first line + أسماء الأ&عمدة ÙÙŠ أوّل سطر + + + + Fie&ld separator + ÙØ§ØµÙ„ الح&قول + + + + , + , + + + + ; + ; + + + + Tab + جدولات + + + + | + | + + + + + + Other + شيء آخر + + + + &Quote character + محر٠ال&تنصيص + + + + " + " + + + + ' + ' + + + + New line characters + محر٠الأسطر الجديدة + + + + Windows: CR+LF (\r\n) + وندوز: CR+LF â€(‎\r\n) + + + + Unix: LF (\n) + ÙŠÙنكس: LF â€(‎\n) + + + + Pretty print + طباعة جميلة + + + + + Could not open output file: %1 + تعذّر ÙØªØ­ مل٠الخرج: %L1 + + + + + Choose a filename to export data + اختر اسمًا للمل٠لتصدير البيانات + + + + Export data as JSON + تصدير البيانات بنسق JSON + + + + exporting CSV + يصدّر CSV + + + + + Error while writing the file '%1': %2 + + + + + exporting JSON + يصدّر JSON + + + + Please select at least 1 table. + من ÙØ¶Ù„Ùƒ حدّد جدولًا واحدًا على الأقل. + + + + Choose a directory + اختر دليلًا + + + + Export completed. + اكتمل التصدير. + + + + Export finished with errors. + + + + + ExportSqlDialog + + + Export SQL... + تصدير SQL... + + + + Tab&le(s) + الج&دول + + + + Select All + حدّد الكلّ + + + + Deselect All + ألغ٠تحديد الكلّ + + + + &Options + &خيارات + + + + Keep column names in INSERT INTO + أبق٠أسماء الأعمدة ÙÙŠ INSERT INTO + + + + Multiple rows (VALUES) per INSERT statement + أكثر من صÙÙ‘ واحد (VALUES) لكلّ Ø¥ÙØ§Ø¯Ø© INSERT + + + + Export everything + صدّر كل شيء + + + + Export schema only + صدّر المخطّط Ùقط + + + + Export data only + صدّر البيانات Ùقط + + + + Keep original CREATE statements + + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + أبق٠المخطّط القديم (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + اكتب على المخطّط القديم (DROP TABLEØŒ وبعدها CREATE TABLE) + + + + Please select at least one table. + من ÙØ¶Ù„Ùƒ حدّد جدولًا واحدًا على الأقل. + + + + Choose a filename to export + اختر اسمًا للمل٠لتصديره + + + + Export completed. + اكتمل التصدير. + + + + Export cancelled or failed. + إمّا أنّ التصدير Ø£Ùلغي أو أنّه ÙØ´Ù„. + + + + ExtendedScintilla + + + + Ctrl+H + Ctrl+H + + + + Ctrl+F + Ctrl+F + + + + + Ctrl+P + Ctrl+P + + + + Find... + ابحث... + + + + Find and Replace... + ابحث واستبدل... + + + + Print... + اطبع... + + + + ExtendedTableWidget + + + Use as Exact Filter + استعملها كمرشّح كما هي + + + + Containing + تحتوي على + + + + Not containing + لا تحتوي على + + + + Not equal to + لا تساوي + + + + Greater than + أكبر من + + + + Less than + أصغر من + + + + Greater or equal + أكبر من أو تساوي + + + + Less or equal + أصغر من أو تساوي + + + + Between this and... + بين هذه Ùˆ... + + + + Regular expression + تعبير نمطي + + + + Edit Conditional Formats... + حرّر التنسيقات الشرطيّة... + + + + Set to NULL + اضبطها على NULL + + + + Cut + + + + + Copy + انسخ + + + + Copy with Headers + انسخ مع الترويسات + + + + Copy as SQL + انسخ كَ†SQL + + + + Paste + ألصÙÙ‚ + + + + Print... + اطبع... + + + + Use in Filter Expression + استعملها ÙÙŠ تعبير الترشيح + + + + Alt+Del + Alt+Del + + + + Ctrl+Shift+C + Ctrl+Shift+C + + + + Ctrl+Alt+C + Ctrl+Alt+C + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + محتوى Ø§Ù„Ø­Ø§ÙØ¸Ø© أكبر من المدى المحدّد. +أتريد إدراجه رغم ذلك؟ + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>لم ØªÙØ­Ù…ّل كلّ البيانات. <b>أتريد تحميل كلّ البيانات قبل تحديد كلّ الصÙÙˆÙØŸ</b><p><p>لو اخترت <b>لا</b> Ùلن ØªÙØ­Ù…ّل أيّة بيانات أخرى ولن ÙŠÙØ¬Ø±Ù‰ هذا التحديد.<br/>لو اخترت <b>نعم</b> ÙØ¹Ù„يك الانتظار وقتًا حتّى ØªÙØ­Ù…ّل البيانات، ولكن التحديد هنا سيحدث</p>تحذير: قد يطلب تحميل كلّ البيانات ذاكرة كثيرة لو كانت الجداول ضخمة. + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + تعذّر ضبط التحديد على NULL. على العمود %L1 قيد â€Ù„يس NULL“. + + + + FileExtensionManager + + + File Extension Manager + مدير امتدادات Ø§Ù„Ù…Ù„ÙØ§Øª + + + + &Up + لأ&على + + + + &Down + لأ&سÙÙ„ + + + + &Add + Ø£&ضÙÙ + + + + &Remove + Ø£&زÙÙ„ + + + + + Description + الوص٠+ + + + Extensions + الامتدادات + + + + *.extension + يمكن للمستخدم تحرير هذه، ÙØ§Ù„Ø£ÙØ¶Ù„ أن تكون إنكليزية بدون محار٠يونيكود كي لا يتركها من غير قصد + *.extension + + + + FilterLineEdit + + + Filter + رشّح + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + تتيح لك مربّعات الإدخال هذه إجراء ترشيح سريع على الجدول المحدّد حاليًا. +مبدئيًا ØªÙØ±Ø´Ù‘Ø­ الصÙو٠التي تحتوي على نص الإدخال. +كما ويدعم البحث Ø§Ù„Ù…ÙØ¹Ø§Ù…لات الآتية: +% حر٠البدل +> أكبر من +< أصغر من +>= أكبر من أو يساوي +>= أصغر من أو يساوي += يساوي (Ù…ÙØ·Ø§Ø¨Ù‚Ø© تامّة) +<> لا يساوي (Ù…ÙØ·Ø§Ø¨Ù‚Ø© عكسية تامّة) +س~ص مدى: القيم بين â€Ø³â€œ Ùˆâ€Øµâ€œ +/ريجÙكس/ القيم التي ØªÙØ·Ø§Ø¨Ù‚ التعبير النمطي + + + + Clear All Conditional Formats + امسح كلّ التنسيقات الشرطيّة + + + + Use for Conditional Format + استعمله تنسيقًا شرطيًا + + + + Edit Conditional Formats... + حرّر التنسيقات الشرطيّة... + + + + Set Filter Expression + اضبط تعبير الترشيح + + + + What's This? + ما هذا؟ + + + + Is NULL + تساوي NULL + + + + Is not NULL + لا تساوي NULL + + + + Is empty + ÙØ§Ø±ØºØ© + + + + Is not empty + ليست ÙØ§Ø±ØºØ© + + + + Not containing... + لا تحتوي على... + + + + Equal to... + تساوي... + + + + Not equal to... + لا تساوي... + + + + Greater than... + أكبر من... + + + + Less than... + أصغر من... + + + + Greater or equal... + أكبر من أو تساوي... + + + + Less or equal... + أصغر من أو تساوي... + + + + In range... + ÙÙŠ المدى... + + + + Regular expression... + تعبير نمطي... + + + + FindReplaceDialog + + + Find and Replace + البحث والاستبدال + + + + Fi&nd text: + ابح&Ø« عن النص: + + + + Re&place with: + ا&ستبدله بÙâ€: + + + + Match &exact case + طابÙÙ‚ &حالة الأحر٠+ + + + Match &only whole words + طابÙÙ‚ الكلمات الكاملة &ÙØ­Ø³Ø¨ + + + + When enabled, the search continues from the other end when it reaches one end of the page + إن ÙØ¹Ù‘لته ÙØ³ÙŠÙواصل البحث من الطر٠التالي عندما يصل إلى نهاية Ø§Ù„ØµÙØ­Ø© + + + + &Wrap around + البحث يلت&ÙÙ‘ + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + إن ÙØ¹Ù‘لته ÙØ³ÙŠØ¬Ø±ÙŠ Ø§Ù„Ø¨Ø­Ø« إلى خل٠مكان المؤشّر، وإلّا ÙØ¥Ù„Ù‰ أمامه + + + + Search &backwards + ابحث لل&خل٠+ + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + إن ÙØ¹Ù‘لته Ùلن يجري البحث على النمط Ø§Ù„Ù…ÙØ±Ø§Ø¯ إلّا ÙÙŠ التحديد الحالي. + + + + &Selection only + الت&حديد Ùقط + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + إن ÙØ¹Ù‘لته ÙØ³ÙŠÙتعامل مع نمط البحث على أنّه تعبير يونكس نمطي. طالع <a href="https://en.wikibooks.org/wiki/Regular_Expressions">التعابير النمطية ÙÙŠ ويكي‌كتب (بالإنجليزية)</a>. + + + + Use regular e&xpressions + استعمل الت&عابير النمطية + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + ابحث عن الحدوث التالي من موقع المؤشّر حسب الاتجاه الذي حدّده â€Ø§Ù„بحث للخلÙ“ + + + + &Find Next + ابحث عن ال&تالي + + + + F3 + + + + + &Replace + ا&ستبدل + + + + Highlight all the occurrences of the text in the page + Ø£Ø¨Ø±ÙØ² كلّ الحدوثات ÙÙŠ نص Ø§Ù„ØµÙØ­Ø© + + + + F&ind All + ابحث عن ال&كلّ + + + + Replace all the occurrences of the text in the page + استبدل كلّ الحدوثات ÙÙŠ نص Ø§Ù„ØµÙØ­Ø© + + + + Replace &All + اس&تبدل الكلّ + + + + The searched text was not found + لم ÙŠÙØ¹Ø«Ø± على نص البحث + + + + The searched text was not found. + لم ÙŠÙØ¹Ø«Ø± على نص البحث. + + + + The searched text was found one time. + Ø¹ÙØ«Ø± على نص البحث مرّة واحدة. + + + + The searched text was found %1 times. + Ø¹ÙØ«Ø± على نص البحث %L1 من المرّات. + + + + The searched text was replaced one time. + Ø§Ø³ØªÙØ¨Ø¯Ù„ نص البحث مرّة واحدة. + + + + The searched text was replaced %1 times. + Ø§Ø³ØªÙØ¨Ø¯Ù„ نص البحث %L1 من المرّات. + + + + ForeignKeyEditor + + + &Reset + &صÙّر + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + بنود Ø§Ù„Ù…ÙØ§ØªÙŠØ­ الأجنبية (ON UPDATEØŒ أو ON DELETEØŒ إلخ.) + + + + ImageViewer + + + Image Viewer + + + + + Reset the scaling to match the original size of the image. + + + + + Set the scaling to match the size of the viewport. + + + + + Print... + اطبع... + + + + Open preview dialog for printing displayed image + ÙŠÙØªØ­ مربّع حوار المعاينة لطباعة الصورة المعروضة + + + + Ctrl+P + Ctrl+P + + + + ImportCsvDialog + + + Import CSV file + استيراد مل٠CSV + + + + Table na&me + ا&سم الجدول + + + + &Column names in first line + أسماء الأ&عمدة ÙÙŠ أوّل سطر + + + + Field &separator + &ÙØ§ØµÙ„ الحقول + + + + , + , + + + + ; + ; + + + + + Tab + جدولات + + + + | + | + + + + Other + شيء آخر + + + + &Quote character + محر٠الت&نصيص + + + + + Other (printable) + شيء آخر (مطبوع) + + + + + Other (code) + شيء آخر (كود) + + + + " + " + + + + ' + ' + + + + &Encoding + ال&ترميز + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Trim fields? + أأقلّم الحقول؟ + + + + Separate tables + Ø§ÙØµÙ„ الجداول + + + + Advanced + متقدّم + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + عند استيراد قيمة ÙØ§Ø±ØºØ© من مل٠CSV إلى جدول موجود يحمل قيمة مبدئية لهذا العمود، ØªÙØ¶Ø§Ù تلك القيمة المبدئية. ÙØ¹Ù‘Ù„ هذا الخيار لإدراج قيمة ÙØ§Ø±ØºØ© عوضًا عن ذلك. + + + + Ignore default &values + تجاهَل ال&قيم المبدئية + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + ÙØ¹Ù‘Ù„ هذا الخيار لإيقا٠الاستيراد عند محاولة استيراد قيمة ÙØ§Ø±ØºØ© ÙÙŠ عمود â€Ù„يس NULL“ ليس له قيمة مبدئية. + + + + Fail on missing values + ÙŠÙØ´Ù„ الاستيراد إن كانت القيم ناقصة + + + + Disable data type detection + عطّل اكتشا٠نوع البيانات + + + + Disable the automatic data type detection when creating a new table. + عطّل الاكتشا٠الآلي لنوع البيانات عند إنشاء جدول جديد. + + + + Use local number conventions + + + + + Use decimal and thousands separators according to the system locale. + + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + حين تستورد القيم إلى جدول موجود وله Ù…ÙØªØ§Ø­ أساسي أو قيود â€Ùريد“ أو Ùهرس â€Ùريد“، Ùهناك احتمال بحدوث تعارض. يتيح لك هذا الخيار تحديد الطريقة التي ستتّبعها البرمجيّة ÙÙŠ تلك الحالة. مبدئيًا تجهض البرمجيّة الاستيراد وترجع إلى ما كانت عليه قاعدة البيانات، ولكن يمكنك أيضًا تجاهل الصÙو٠المتعارضة وعدم استيرادها، أو حتّى استبدال الصÙÙ‘ الموجود ÙÙŠ الجدول كلّه. + + + + Abort import + Ø£Ø¬Ù‡ÙØ¶ الاستيراد + + + + Ignore row + تجاهَل الصÙÙ‘ + + + + Replace existing row + استبدل الصÙÙ‘ الموجود + + + + Conflict strategy + استراتيجيّة التعارضات + + + + + Deselect All + ألغ٠تحديد الكلّ + + + + Match Similar + طابÙÙ‚ المتشابهات + + + + Select All + حدّد الكلّ + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + هناك جدول Ø¨Ù†ÙØ³ الاسم â€%L1“ Ø¨Ø§Ù„ÙØ¹Ù„ ولا يمكن الاستيراد داخل أحد الجداول الموجودة إلّا إن تطابق عدد الأعمدة. + + + + There is already a table named '%1'. Do you want to import the data into it? + هناك جدول Ø¨Ù†ÙØ³ الاسم â€%L1“ Ø¨Ø§Ù„ÙØ¹Ù„. أتريد استيراد البيانات داخله؟ + + + + Creating restore point failed: %1 + ÙØ´Ù„ إنشاء نقطة استعادة: %L1 + + + + Creating the table failed: %1 + ÙØ´Ù„ إنشاء الجدول: %L1 + + + + importing CSV + يستورد CSV + + + + Could not prepare INSERT statement: %1 + + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + أخذ استيراد المل٠â€%L1“ â€%L2 م‌ث. منها %L3 م‌ث على دالة الصÙÙ‘. + + + + Inserting row failed: %1 + ÙØ´Ù„ إدراج الصÙÙ‘: %L1 + + + + MainWindow + + + DB Browser for SQLite + متصÙّح قواعد بيانات SQLite + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + هذه بنية قاعدة البيانات Ø§Ù„Ù…ÙØªÙˆØ­Ø©. +يمكنك سحب Ø¥ÙØ§Ø¯Ø§Øª SQL من صÙÙ‘ ÙÙŠ الكائن وإسقاطها ÙÙŠ التطبيقات الأخرى أو إلى سيرورة أخرى من â€Ù…تصÙّح قواعد بيانات SQLite“. + + + + Un/comment block of SQL code + اجعل/لا تجعل كتلة كود SQL تعليقًا + + + + Un/comment block + اجعل/لا تجعل الكتلة تعليقًا + + + + Comment or uncomment current line or selected block of code + حوّل السطر الحالي (أو كتلة الكود المحدّدة) إلى تعليق، أو ألغ٠التحويل + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + اجعل الأسطر المحدّدة (أو الحالي Ùقط لو لم يكن هناك تحديد) تعليقًا، أو ألغ٠ذلك. يتغيّر تحويل كتلة الكود كاملةً حسب أوّل سطر Ùيها. + + + + Ctrl+/ + Ctrl+/ + + + + Stop SQL execution + أوقÙ٠تنÙيذ SQL + + + + Stop execution + أوقÙ٠التنÙيذ + + + + Stop the currently running SQL script + أوقÙ٠تنÙيذ سكربت SQL الذي يعمل حاليًا + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + تحذير: لا يمكن قراءة pragma هذه، ولهذا استÙنتجت هذه القيمة. قد تؤدّي كتابة pragma على تعويض Ø¥ÙØ§Ø¯Ø© LIKE Ù…ÙØ¹Ø§Ø¯ تعريÙها ÙˆÙّرها امتداد SQLite. + + + + toolBar1 + شريط الأدوات1 + + + + Export one or more table(s) to a JSON file + صدّر جدولًا أو أكثر إلى مل٠JSON + + + + Edit Database &Cell + تحرير &خليّة قاعدة البيانات + + + + DB Sche&ma + Ù…&خطّط قاعدة البيانات + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + هذه بنية قاعدة البيانات Ø§Ù„Ù…ÙØªÙˆØ­Ø©. +يمكنك سحب عدد من أسماء الكائنات من عمود â€Ø§Ù„اسم“ وإسقاطها ÙÙŠ محرّر SQL ويمكنك ضبط خصائص تلك الأسماء Ø§Ù„Ù…ÙØ³Ù‚طة مستعملًا قائمة السياق. سيساعد هذا ÙÙŠ كتابة Ø¥ÙØ§Ø¯Ø§Øª SQL. +يمكنك سحب Ø¥ÙØ§Ø¯Ø§Øª SQL من عمود â€Ø§Ù„مخطّط“ وإسقاطها ÙÙŠ محرّر SQL أو ÙÙŠ أيّ تطبيق آخر. + + + + &Remote + الب&عيد + + + + + Execute current line + Ù†Ùّذ السطر الحالي + + + + This button executes the SQL statement present in the current editor line + ÙŠÙÙ†Ùّذ هذا الزر Ø¥ÙØ§Ø¯Ø© SQL الظاهرة ÙÙŠ سطر المحرّر الحالي + + + + Shift+F5 + Shift+F5 + + + + Open an existing database file in read only mode + Ø§ÙØªØ­ مل٠قاعدة بيانات موجود ÙÙŠ وضع القراءة Ùقط + + + + Opens the SQLCipher FAQ in a browser window + ÙŠÙØªØ­ الأسئلة الشائعة عن SQLCipher ÙÙŠ Ù†Ø§ÙØ°Ø© المتصÙّح + + + + &File + مل&Ù + + + + &Import + ا&Ø³ØªÙˆØ±ÙØ¯ + + + + &Export + &صدّر + + + + &Edit + ت&حرير + + + + &View + من&ظور + + + + &Help + Ù…&ساعدة + + + + Too&ls + Ø£&دوات + + + + DB Toolbar + شريط قاعدة البيانات + + + + SQL &Log + س&جلّ SQL + + + + Show S&QL submitted by + اعرض SQL الذي Ù†&Ùّذه + + + + User + المستخدم + + + + Application + التطبيق + + + + Error Log + سجلّ الأخطاء + + + + This button clears the contents of the SQL logs + يمسح هذا الزر محتويات سجلّات SQL + + + + &Clear + ا&مسح + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + تتيح لك هذه اللوحة ÙØ­Øµ كلّ أوامر SQL التي Ù†Ùّذها التطبيق أو المستخدم + + + + &Plot + الر&سم البياني + + + + &New Database... + قاعدة بيانات &جديدة... + + + + + Create a new database file + Ø£Ù†Ø´ÙØ¦ مل٠قاعدة بيانات جديد + + + + This option is used to create a new database file. + ÙŠÙØ³ØªØ®Ø¯Ù… هذا الخيار لإنشاء مل٠قاعدة بيانات جديد. + + + + Ctrl+N + Ctrl+N + + + + + &Open Database... + ا&ÙØªØ­ قاعدة بيانات... + + + + + + + + Open an existing database file + Ø§ÙØªØ­ مل٠قاعدة بيانات موجود + + + + + + This option is used to open an existing database file. + ÙŠÙØ³ØªØ®Ø¯Ù… هذا الخيار Ù„ÙØªØ­ مل٠قاعدة بيانات موجود. + + + + Ctrl+O + Ctrl+O + + + + &Close Database + Ø£&غلÙÙ‚ قاعدة البيانات + + + + This button closes the connection to the currently open database file + ÙŠÙØºÙ„Ù‚ هذا الزر الاتصال بمل٠قاعدة البيانات Ø§Ù„Ù…ÙØªÙˆØ­ حاليًا + + + + + Ctrl+W + Ctrl+W + + + + &Revert Changes + أرجÙ&ع التعديلات + + + + + Revert database to last saved state + Ø£Ø±Ø¬ÙØ¹ قاعدة البيانات إلى آخر حالة محÙوظة + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + ÙŠÙØ³ØªØ¹Ù…Ù„ هذا الخيار لإرجاع مل٠قاعدة البيانات إلى آخر حالة محÙوظة له. ستÙقد كلّ التعديلات عليه منذ آخر عملية Ø­ÙØ¸ أجريتها. + + + + &Write Changes + ا&كتب التعديلات + + + + + Write changes to the database file + اكتب التعديلات ÙÙŠ مل٠قاعدة البيانات + + + + This option is used to save changes to the database file. + ÙŠÙØ³ØªØ¹Ù…Ù„ هذا الخيار لكتابة التعديلات ÙÙŠ مل٠قاعدة البيانات. + + + + Ctrl+S + Ctrl+S + + + + Compact &Database... + Ø±ÙØµÙ‘ &قاعدة البيانات + + + + Compact the database file, removing space wasted by deleted records + Ø±ÙØµÙ‘ مل٠قاعدة البيانات، Ù…ÙØ²ÙŠÙ„ًا المساحة الضائعة بسبب حذ٠السجلّات + + + + + Compact the database file, removing space wasted by deleted records. + Ø±ÙØµÙ‘ مل٠قاعدة البيانات، Ù…ÙØ²ÙŠÙ„ًا المساحة الضائعة بسبب حذ٠السجلّات. + + + + E&xit + ا&خرج + + + + Ctrl+Q + Ctrl+Q + + + + &Database from SQL file... + &قاعدة بيانات من مل٠SQL... + + + + Import data from an .sql dump text file into a new or existing database. + Ø§Ø³ØªÙˆØ±ÙØ¯ بيانات من مل٠‎.sql نصي Ù…ÙØ±Ù‘غ إلى قاعدة بيانات جديدة أو موجودة. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + يتيح لك هذا الخيار استيراد البيانات من مل٠‎.sql نصي Ù…ÙØ±Ù‘غ إلى قاعدة بيانات جديدة أو موجودة. يمكن إنشاء Ù…Ù„ÙØ§Øª SQL Ø§Ù„Ù…ÙØ±Ù‘غة ÙÙŠ أغلب محرّكات قواعد البيانات، بما Ùيها MySQL ÙˆPostgreSQL. + + + + &Table from CSV file... + ج&دولًا من مل٠CSV... + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Ø§ÙØªØ­ مرشدًا يساعدك ÙÙŠ استيراد البيانات من مل٠نصي مقسوم بÙواصل إلى جدول قاعدة البيانات. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Ø§ÙØªØ­ مرشدًا يساعدك ÙÙŠ استيراد البيانات من مل٠نصي مقسوم بÙواصل إلى جدول قاعدة البيانات. يمكن إنشاء Ù…Ù„ÙØ§Øª CSV ÙÙŠ أغلب تطبيقات قواعد البيانات والجداول الممتدّة. + + + + &Database to SQL file... + &قاعدة بيانات إلى مل٠SQL... + + + + Export a database to a .sql dump text file. + صدّر قاعدة بيانات إلى مل٠‎.sql نصي Ù…ÙØ±Ù‘غ. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + يتيح لك هذا الخيار تصدير قاعدة بيانات إلى مل٠‎.sql نصي Ù…ÙØ±Ù‘غ. يمكن Ù„Ù…Ù„ÙØ§Øª SQL Ø§Ù„Ù…ÙØ±Ù‘غة احتواء كلّ البيانات الضرورية لإعادة إنشاء قاعدة البيانات ÙÙŠ أغلب محرّكات قواعد البيانات، Ùما Ùيها MySQL ÙˆPostgreSQL. + + + + &Table(s) as CSV file... + الج&داول كمل٠CSV... + + + + Export a database table as a comma separated text file. + صدّر جدول قاعدة بيانات كمل٠نصي مقسوم بÙواصل. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + صدّر جدول قاعدة بيانات كمل٠نصي مقسوم بÙواصل، جاهز Ù„ÙŠÙØ³ØªÙˆØ±Ø¯ إلى تطبيقات قواعد البيانات أو الجداول الممتدّة الأخرى. + + + + &Create Table... + Ø£&Ù†Ø´ÙØ¦ جدولًا... + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Ø§ÙØªØ­ مرشد إنشاء الجدول، حيث تستطيع تحديد اسم وحقول للجدول الجديد ÙÙŠ قاعدة البيانات + + + + &Delete Table... + ا&حذ٠الجدول... + + + + + Delete Table + احذ٠الجدول + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Ø§ÙØªØ­ مرشد حذ٠الجدول، حيث يمكنك تحديد جدول قاعدة البيانات الذي Ø³ÙŠÙØ­Ø°Ù. + + + + &Modify Table... + &عدّل الجدول... + + + + Create &Index... + Ø£Ù†Ø´ÙØ¦ &Ùهرسًا... + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + Ø§ÙØªØ­ جدول إنشاء الÙهارس، حيث يمكنك تحديد Ùهرس جديد ÙÙŠ جدول قاعدة بيانات موجود. + + + + &Preferences... + التÙ&ضيلات... + + + + + Open the preferences window. + Ø§ÙØªØ­ Ù†Ø§ÙØ°Ø© Ø§Ù„ØªÙØ¶ÙŠÙ„ات. + + + + &DB Toolbar + شريط &قاعدة البيانات + + + + Shows or hides the Database toolbar. + يعرض أو ÙŠÙØ®ÙÙŠ شريط قاعدة البيانات.. + + + + New &tab + + + + + Ctrl+T + Ctrl+T + + + + Open SQL file(s) + Ø§ÙØªØ­ Ù…Ù„ÙØ§Øª SQL + + + + This button opens files containing SQL statements and loads them in new editor tabs + ÙŠÙØªØ­ هذا الزر Ù…Ù„ÙØ§Øª تحتوي Ø¥ÙØ§Ø¯Ø§Øª SQL ويحمّلها ÙÙŠ ألسنة محرّر جديدة + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + يتيح لك هذا الزر Ø­ÙØ¸ كلّ الإعدادات المرتبطة بقاعدة البيانات Ø§Ù„Ù…ÙØªÙˆØ­Ø© ÙÙŠ مل٠مشروع «متصÙّح قواعد بيانات SQLite» + + + + This button lets you open a DB Browser for SQLite project file + يتيح لك هذا الزر ÙØªØ­ مل٠مشروع «متصÙّح قواعد بيانات SQLite» + + + + Browse Table + تصÙّح الجدول + + + + W&hat's This? + ما Ù‡&ذا؟ + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + + + + + Temp Store + + + + + Secure Delete + + + + + Case Sensitive Like + + + + + Journal Mode + + + + + Journal Size Limit + + + + + Recursive Triggers + + + + + Page Size + + + + + Foreign Keys + + + + + Auto Vacuum + + + + + Max Page Count + + + + + Checkpoint Full FSYNC + + + + + + Off + + + + + + Normal + + + + + + Full + + + + + Default + المبدئي + + + + File + المل٠+ + + + + Memory + + + + + Delete + + + + + Truncate + + + + + Persist + + + + + WAL + + + + + Exclusive + + + + + Automatic Index + + + + + Ignore Check Constraints + + + + + Full FSYNC + + + + + WAL Auto Checkpoint + + + + + User Version + + + + + Synchronous + + + + + None + + + + + Incremental + + + + + Locking Mode + + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + + + + + &Recent Files + + + + + &New Database + + + + + + Ctrl+F4 + Ctrl+F4 + + + + &Undo + + + + + + Undo last change to the database + + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + + + + + Shift+F1 + Shift+F1 + + + + Execute all/selected SQL + Ù†Ùّذ كلّ Ø¥ÙØ§Ø¯Ø§Øª SQL أو المحدّدة Ùقط + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + ÙŠÙÙ†Ùّذ هذا الزر Ø¥ÙØ§Ø¯Ø§Øª SQL المحدّدة حاليًا. إن لم تحدّد شيئًا ÙØ³ØªÙÙ†Ùّذ كلّ Ø¥ÙØ§Ø¯Ø§Øª SQL. + + + + Ctrl+Shift+T + + + + + &Load Extension... + &حمّل امتدادًا... + + + + Execute line + Ù†Ùّذ السطر + + + + &Wiki + الوي&كي + + + + F1 + + + + + Bug &Report... + Ø£Ø¨Ù„ÙØº عن علّ&Ø©... + + + + Feature Re&quest... + ا&طلب ميزة... + + + + Web&site + موقع الو&ب + + + + &Donate on Patreon... + تبرّع &عبر باتريون... + + + + &Save Project + + + + + Open &Project... + Ø§ÙØªØ­ Ù…&شروعًا... + + + + Open &Project + + + + + &Attach Database... + أر&ÙÙÙ‚ قاعدة بيانات... + + + + + Add another database file to the current database connection + أضÙ٠مل٠قاعدة بيانات آخر إلى اتصال قاعدة البيانات الحالي + + + + This button lets you add another database file to the current database connection + يتيح لك هذا الزر Ø¥Ø¶Ø§ÙØ© مل٠قاعدة بيانات آخر إلى اتصال قاعدة البيانات الحالي + + + + &Set Encryption... + ا&ضبط التعمية... + + + + SQLCipher &FAQ + Ø£&سئلة شائعة عن SQLCipher + + + + Table(&s) to JSON... + الج&دول/الجداول إلى JSON... + + + + Open Data&base Read Only... + Ø§ÙØªØ­ قاع&دة بيانات للقراءة Ùقط... + + + + Ctrl+Shift+O + Ctrl+Shift+O + + + + Save results + Ø§Ø­ÙØ¸ النتائج + + + + Save the results view + Ø§Ø­ÙØ¸ منظور النتائج + + + + This button lets you save the results of the last executed query + يتيح لك هذا الزر Ø­ÙØ¸ نتائج آخر استعلام Ù†ÙÙّذ + + + + + Find text in SQL editor + ابحث عن النصوص ÙÙŠ محرّر SQL + + + + Find + ابحث + + + + This button opens the search bar of the editor + ÙŠÙØªØ­ هذا الزر شريط البحث للمحرّر + + + + Ctrl+F + Ctrl+F + + + + + Find or replace text in SQL editor + ابحث أو استبدل النصوص ÙÙŠ محرّر SQL + + + + Find or replace + ابحث أو استبدل + + + + This button opens the find/replace dialog for the current editor tab + ÙŠÙØªØ­ هذا الزر مربّع حوار البحث والاستبدال للسان المحرّر الحالي + + + + Ctrl+H + Ctrl+H + + + + Export to &CSV + &صدّر بنسق CSV + + + + Export to &JSON + + + + + Save as &view + Ø§Ø­ÙØ¸ كمن&ظور + + + + Save as view + Ø§Ø­ÙØ¸ كمنظور + + + + Shows or hides the Project toolbar. + اعرض أو أخÙ٠شريط أدوات المشروع. + + + + Extra DB Toolbar + شريط أدوات قواعد البيانات الإضاÙÙŠ + + + + &Open Database + + + + + New In-&Memory Database + قاعدة بيانات جديدة ÙÙŠ ال&ذاكرة + + + + Drag && Drop SELECT Query + + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + + + + + Drag && Drop Qualified Names + اسحب ÙˆØ£Ø³Ù‚ÙØ· الأسماء المؤهّلة + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + استخدم الأسماء المؤهّلة (مثل ‎"Table"."Field"‎) عند سحب الكائنات وإسقاطها ÙÙŠ المحرّر. + + + + Drag && Drop Enquoted Names + اسحب ÙˆØ£Ø³Ù‚ÙØ· الأسماء مقتبسةً + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + استخدم Ø§Ù„Ù…ÙØ¹Ø±Ù‘ÙØ§Øª مهرّبة (مثلًا "Table1") عند سحب الكائنات وإسقاطها ÙÙŠ المحرّر + + + + &Integrity Check + ÙØ­Øµ ال&سلامة + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + ÙŠÙØ´ØºÙ‘Ù„ integrity_check pragma على قاعدة البيانات Ø§Ù„Ù…ÙØªÙˆØ­Ø© ÙˆÙŠÙØ¹ÙŠØ¯ النتائج ÙÙŠ لسان â€Ù†Ùّذ SQL“. ÙŠÙØ¬Ø±ÙŠ pragma ÙØ­Øµ سلامة على قاعدة البيانات كاملةً. + + + + &Foreign-Key Check + ÙØ­Øµ الم&ÙØªØ§Ø­ الأجنبي + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + ÙŠÙØ´ØºÙ‘Ù„ foreign_key_check pragma على قاعدة البيانات Ø§Ù„Ù…ÙØªÙˆØ­Ø© ÙˆÙŠÙØ¹ÙŠØ¯ النتائج ÙÙŠ لسان â€Ù†Ùّذ SQL“ + + + + &Quick Integrity Check + ÙØ­Øµ سلام&Ø© سريع + + + + Run a quick integrity check over the open DB + ÙŠÙØ´ØºÙ‘Ù„ ÙØ­Øµ سلامة سريع على قاعدة البيانات Ø§Ù„Ù…ÙØªÙˆØ­Ø© + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + ÙŠÙØ´ØºÙ‘Ù„ quick_check pragma على قاعدة البيانات Ø§Ù„Ù…ÙØªÙˆØ­Ø© ÙˆÙŠÙØ¹ÙŠØ¯ النتائج ÙÙŠ لسان â€Ù†Ùّذ SQL“. ÙŠÙØ¬Ø±ÙŠ Ù‡Ø°Ø§ الأمر أغلب ما ØªÙØ¬Ø±ÙŠÙ‡ PRAGMA integrity_check إلّا أنّه أسرع. + + + + &Optimize + Ø­&سّن + + + + Attempt to optimize the database + حاوÙÙ„ تحسين قاعدة البيانات + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + ÙŠÙØ´ØºÙ‘Ù„ optimize pragma على قاعدة البيانات Ø§Ù„Ù…ÙØªÙˆØ­Ø©. قد تؤدّي pragma إلى إجراء بعض التحسينات لها أن ØªÙØ­Ø³Ù‘Ù† من أداء الاستعلامات مستقبلًا. + + + + + Print + اطبع + + + + Print text from current SQL editor tab + اطبع النص من لسان محرّر SQL الحالي + + + + Open a dialog for printing the text in the current SQL editor tab + Ø§ÙØªØ­ مربّع حوار طباعة النص ÙÙŠ لسان محرّر SQL الحالي + + + + Print the structure of the opened database + اطبع بنية قاعدة البيانات Ø§Ù„Ù…ÙØªÙˆØ­Ø© + + + + Open a dialog for printing the structure of the opened database + Ø§ÙØªØ­ مربّع حوار طباعة بنية قاعدة البيانات Ø§Ù„Ù…ÙØªÙˆØ­Ø© + + + + &Save Project As... + احÙ&ظ المشروع ÙƒÙŽâ€... + + + + + + Save the project in a file selected in a dialog + Ø§Ø­ÙØ¸ المشروع ÙÙŠ مل٠تحدّده من مربّع حوار + + + + Save A&ll + Ø§Ø­ÙØ¸ ال&كلّ + + + + + + Save DB file, project file and opened SQL files + Ø§Ø­ÙØ¸ مل٠قاعدة البيانات ومل٠المشروع ÙˆÙ…Ù„ÙØ§Øª SQL Ø§Ù„Ù…ÙØªÙˆØ­Ø© + + + + Ctrl+Shift+S + Ctrl+Shift+S + + + + Close Pro&ject + + + + + + Close project and database files and return to the initial state + + + + + + Ctrl+Shift+W + + + + + Table from CSV data in Clipboard... + + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + + + + + Show &Row Counts + + + + + This shows the number of rows for each table and view in the database. + + + + + Save Database &As... + + + + + Save the current database as a different file + + + + + Refresh + Ø£Ù†Ø¹ÙØ´ + + + + Reload the database structure + + + + + Ctrl+Shift+F4 + + + + + + Detach Database + + + + + + Detach database file attached to the current database connection + + + + + &Recently opened + Ø§Ù„Ù…ÙØªÙˆØ­Ø© حدي&ثًا + + + + + Project Toolbar + شريط أدوات المشروع + + + + Extra DB toolbar + شريط أدوات قواعد البيانات الإضاÙÙŠ + + + + + + Close the current database file + أغلÙÙ‚ مل٠قاعدة البيانات الحالي + + + + &About + &عن + + + + This button opens a new tab for the SQL editor + ÙŠÙØªØ­ هذا الزر لسانًا جديدًا لمحرّر SQL + + + + &Execute SQL + Ù†&Ùّذ SQL + + + + + + Save SQL file + Ø§Ø­ÙØ¸ مل٠SQL + + + + Ctrl+E + Ctrl+E + + + + Export as CSV file + صدّر كمل٠بنسق CSV + + + + Export table as comma separated values file + صدّر الجدول كمل٠نصي مقسوم بÙواصل + + + + Sa&ve Project + احÙ&ظ المشروع + + + + + Save the current session to a file + Ø§Ø­ÙØ¸ الجلسة الحالية ÙÙŠ مل٠+ + + + + Load a working session from a file + حمّل جلسة عمل من مل٠+ + + + + Save SQL file as + Ø§Ø­ÙØ¸ مل٠SQL كَ†+ + + + This button saves the content of the current SQL editor tab to a file + ÙŠØ­ÙØ¸ هذا الزر محتويات لسان محرّر SQL الحالي ÙÙŠ مل٠+ + + + &Browse Table + ت&صÙّح الجدول + + + + Copy Create statement + انسخ Ø¥ÙØ§Ø¯Ø© الإنشاء + + + + Copy the CREATE statement of the item to the clipboard + انسخ Ø¥ÙØ§Ø¯Ø© CREATE للعنصر إلى Ø§Ù„Ø­Ø§ÙØ¸Ø© + + + + Ctrl+Return + Ctrl+Return + + + + Ctrl+L + Ctrl+L + + + + + Ctrl+P + Ctrl+P + + + + Ctrl+D + Ctrl+D + + + + Ctrl+I + Ctrl+I + + + + Encrypted + معمّاة + + + + Database is encrypted using SQLCipher + قاعدة البيانات معمّاة بامتداد SQLCipher + + + + Read only + للقراءة Ùقط + + + + Database file is read only. Editing the database is disabled. + مل٠قاعدة البيانات للقراءة Ùقط. تحرير قاعدة البيانات معطّل. + + + + Database encoding + ترميز قاعدة البيانات + + + + + Choose a database file + اختر مل٠قاعدة بيانات + + + + + + Choose a filename to save under + اختر اسمًا Ù„Ù„Ù…Ù„Ù Ù„Ø­ÙØ¸Ù‡ به + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + خطأ أثناء Ø­ÙØ¸ مل٠قاعدة البيانات. هذا يعني أنّه تعذّر Ø­ÙØ¸ كلّ التغييرات ÙÙŠ قاعدة البيانات. عليك حلّ الخطأ الآتي أوّلًا: + +%L1 + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + أمتأكّد من التراجع عن كلّ التعديلات التي أجريتها على مل٠قاعدة البيانات â€%L1“ منذ آخر Ø­ÙØ¸ØŸ + + + + Choose a file to import + اختر ملÙًا لاستيراده + + + + Text files(*.sql *.txt);;All files(*) + Ø§Ù„Ù…Ù„ÙØ§Øª النصية(*.sql *.txt);;كلّ Ø§Ù„Ù…Ù„ÙØ§Øª(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + أتريد إنشاء مل٠قاعدة بيانات جديد Ù„ÙŠØ­ØªÙØ¸ بالبيانات المستوردة؟ +إن كانت إجابتك â€Ù„ا“ ÙØ³Ù†Ø­Ø§ÙˆÙ„ استيراد البيانات من مل٠SQL إلى قاعدة البيانات الحالية. + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + ما زلت تنÙّذ Ø¥ÙØ§Ø¯Ø§Øª SQL. بإغلاق قاعدة البيانات الآن تكون Ø£ÙˆÙ‚ÙØª التنÙيذ وقد يترك ذلك قاعدة البيانات ÙÙŠ حال غير مستقرّة. أمتأكّد من إغلاق قاعدة البيانات؟ + + + + Do you want to save the changes made to the project file '%1'? + أتريد Ø­ÙØ¸ التعديلات التي أجريتها ÙÙŠ مل٠المشروع â€%L1“؟ + + + + File %1 already exists. Please choose a different name. + المل٠%L1 موجود Ø¨Ø§Ù„ÙØ¹Ù„. من ÙØ¶Ù„Ùƒ اختر اسمًا آخر. + + + + Error importing data: %1 + خطأ أثناء استيراد البيانات: %L1 + + + + Import completed. + اكتمل الاستيراد. + + + + Delete View + احذ٠المنظور + + + + Modify View + عدّل المنظور + + + + Delete Trigger + احذ٠المحÙّز + + + + Modify Trigger + عدّل المحÙّز + + + + Delete Index + احذ٠الÙهرس + + + + Modify Index + عدّل الÙهرس + + + + Modify Table + عدّل الجدول + + + + Do you want to save the changes made to SQL tabs in a new project file? + أتريد Ø­ÙØ¸ التعديلات التي أجريتها على ألسنة SQL ÙÙŠ مل٠مشروع جديد؟ + + + + Do you want to save the changes made to the SQL file %1? + أتريد Ø­ÙØ¸ التعديلات التي أجريتها على مل٠SQL بالاسم â€%L1“؟ + + + + Could not find resource file: %1 + تعذّر العثور على مل٠الموارد: %L1 + + + + Choose a project file to open + اختر مل٠مشروع Ù„ÙØªØ­Ù‡ + + + + Could not open project file for writing. +Reason: %1 + تعذّر ÙØªØ­ مل٠المشروع للكتابة. +السبب: %L1 + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + سيؤّدي ضبط قيم PRAGMA إلى إيداع المعاملة الحالية. +أمتأكّد؟ + + + + Ctrl+Tab + + + + + Ctrl+Shift+Tab + + + + + Clear List + + + + + Window Layout + تخطيط Ø§Ù„Ù†Ø§ÙØ°Ø© + + + + Reset Window Layout + صÙّر تخطيط Ø§Ù„Ù†Ø§ÙØ°Ø© + + + + Simplify Window Layout + بسّط تخطيط Ø§Ù„Ù†Ø§ÙØ°Ø© + + + + Alt+Shift+0 + Alt+Shift+0 + + + + Dock Windows at Bottom + Ø§Ø±ØµÙ Ø§Ù„Ù†ÙˆØ§ÙØ° بالأسÙÙ„ + + + + Dock Windows at Left Side + Ø§Ø±ØµÙ Ø§Ù„Ù†ÙˆØ§ÙØ° على اليسار + + + + Dock Windows at Top + Ø§Ø±ØµÙ Ø§Ù„Ù†ÙˆØ§ÙØ° بالأعلى + + + + The database is currently busy. + قاعدة البيانات مشغولة حاليًا. + + + + Click here to interrupt the currently running query. + انقر هنا لمقاطعة الاستعلام الذي يعمل حاليًا. + + + + Alt+Shift+W + + + + + Could not open database file. +Reason: %1 + تعذّر ÙØªØ­ مل٠قاعدة البيانات. +السبب: %L1 + + + + In-Memory database + قاعدة بيانات ÙÙŠ الذاكرة + + + + Choose a database file to save under + + + + + Error while saving the database to the new file. + + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + أمتأكّد من حذ٠الجدول â€%L1“؟ +ستÙقد كلّ البيانات المرتبطة بالجدول. + + + + Are you sure you want to delete the view '%1'? + أمتأكّد من حذ٠المنظور â€%L1“؟ + + + + Are you sure you want to delete the trigger '%1'? + أمتأكّد من حذ٠المحÙّز â€%L1“؟ + + + + Are you sure you want to delete the index '%1'? + أمتأكّد من حذ٠الÙهرس â€%L1“؟ + + + + Error: could not delete the table. + خطأ: تعذّر حذ٠الجدول. + + + + Error: could not delete the view. + خطأ: تعذّر حذ٠المنظور. + + + + Error: could not delete the trigger. + خطأ: تعذّر حذ٠المحÙّز. + + + + Error: could not delete the index. + خطأ: تعذّر حذ٠الÙهرس. + + + + Message from database engine: +%1 + الرسالة من محرّك قواعد البيانات: +%L1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + تحرير الجدول يطلب Ø­ÙØ¸ كلّ التغييرات المرجأة الآن. +أمتأكّد من Ø­ÙØ¸ قاعدة البيانات؟ + + + + Error checking foreign keys after table modification. The changes will be reverted. + خطأ أثناء ÙØ­Øµ Ø§Ù„Ù…ÙØ§ØªÙŠØ­ الأجنبية بعد تعديل الجدول. Ø³ØªÙØ±Ø¬ÙŽØ¹ التغييرات. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + لم يمرّ الجدول ÙØ­Øµ Ø§Ù„Ù…ÙØªØ§Ø­ الأجنبي.<br/>عليك تشغيل â€Ø£Ø¯ÙˆØ§Øª -> ÙØ­Øµ Ø§Ù„Ù…ÙØªØ§Ø­ الأجنبي“ وإصلاح المشاكل المذكورة. + + + + Edit View %1 + حرّر المنظور %L1 + + + + Edit Trigger %1 + حرّر المحÙّز %L1 + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + أنت تنÙّذ حقًا Ø¥ÙØ§Ø¯Ø§Øª SQL. أتريد إيقاÙها لتنÙيذ Ø§Ù„Ø¥ÙØ§Ø¯Ø§Øª الحالية بدلها؟ وقد يترك ذلك قاعدة البيانات ÙÙŠ حال غير مستقرّة. + + + + -- EXECUTING SELECTION IN '%1' +-- + -- ينÙّذ التحديد ÙÙŠ â€%L1“ +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- ينÙّذ السطر ÙÙŠ â€%L1“ +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- ينÙّذ الكلّ ÙÙŠ â€%L1“ +-- + + + + + At line %1: + عند السطر %L1: + + + + Result: %1 + النتيجة: %L1 + + + + Result: %2 + النتيجة: %L2 + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + سيؤّدي ضبط قيم PRAGMA أو التنظي٠إلى إيداع المعاملة الحالية. +أمتأكّد؟ + + + + Opened '%1' in read-only mode from recent file list + ÙÙØªØ­ â€%L1“ بوضع القراءة Ùقط من قائمة Ø§Ù„Ù…Ù„ÙØ§Øª Ø§Ù„Ù…ÙØªÙˆØ­Ø© حديثًا + + + + Opened '%1' from recent file list + ÙÙØªØ­ â€%L1“ من قائمة Ø§Ù„Ù…Ù„ÙØ§Øª Ø§Ù„Ù…ÙØªÙˆØ­Ø© حديثًا + + + + &%1 %2%3 + â€&%L1 â€â€Ž%L2‎â€%L3 + + + + (read only) + (للقراءة Ùقط) + + + + Open Database or Project + Ø§ÙØªØ­ قاعدة بيانات أو مشروع + + + + Attach Database... + أرÙÙÙ‚ قاعدة بيانات... + + + + Import CSV file(s)... + Ø§Ø³ØªÙˆØ±ÙØ¯ Ù…Ù„ÙØ§Øª CSV... + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + أتريد Ø­ÙØ¸ التعديلات التي أجريتها على ألسنة SQL ÙÙŠ مل٠المشروع â€%L1“؟ + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + + + + + DB file '%1' could not be opened + + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + + + + + Table '%1' not found; settings ignored + + + + + -- Reference to file "%1" (not supported by this version) -- + + + + + Project saved to file '%1' + Ø­ÙÙØ¸ المشروع ÙÙŠ المل٠â€%L1“ + + + + Yes. Don't ask again + + + + + This action will open a new SQL tab with the following statements for you to edit and run: + ÙŠÙØªØ­ هذا الإجراء لسان SQL جديد يحتوي Ø§Ù„Ø¥ÙØ§Ø¯Ø§Øª الآتية لتحرّرها وتنÙّذها: + + + + Busy (%1) + مشغولة (%L1) + + + + Rename Tab + غيّر اسم اللسان + + + + Duplicate Tab + كرّر اللسان + + + + Close Tab + أغلÙÙ‚ اللسان + + + + Opening '%1'... + ÙŠÙØªØ­ â€%L1“... + + + + There was an error opening '%1'... + خطأ أثناء ÙØªØ­ â€%L1“... + + + + Value is not a valid URL or filename: %1 + القيمة ليست عنوانًا ولا اسم مل٠صالح: %L1 + + + + %1 rows returned in %2ms + Ø£ÙØ¹ÙŠØ¯ من الصÙÙˆÙ %L1 خلال %L2 م‌ث + + + + Automatically load the last opened DB file at startup + + + + + Ctrl+0 + + + + + Choose text files + اختر Ù…Ù„ÙØ§Øª نصية + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + اكتمل الاستيراد. انتÙهكت بعض قيود Ø§Ù„Ù…ÙØªØ§Ø­ الأجنبي. من ÙØ¶Ù„Ùƒ Ø£ØµÙ„ÙØ­Ù‡Ø§ قبل Ø§Ù„Ø­ÙØ¸. + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + اختر الإجراء الذي تريد تطبيقه على Ø§Ù„Ù…Ù„ÙØ§Øª التي Ø£Ùلتّها. <br/>لاحظ أنّ خيار â€Ø§Ø³ØªÙˆØ±Ùد“ هو الوحيد الذي Ø³ÙŠÙØ¹Ø§Ù„ج Ø§Ù„Ù…Ù„ÙØ§Øª المتعدّدة. + اختر الإجراء الذي تريد تطبيقه على المل٠الذي Ø£Ùلتّه. <br/>لاحظ أنّ خيار â€Ø§Ø³ØªÙˆØ±Ùد“ هو الوحيد الذي Ø³ÙŠÙØ¹Ø§Ù„ج Ø§Ù„Ù…Ù„ÙØ§Øª المتعدّدة. + اختر الإجراء الذي تريد تطبيقه على الملÙين الذين Ø£Ùلتّهما. <br/>لاحظ أنّ خيار â€Ø§Ø³ØªÙˆØ±Ùد“ هو الوحيد الذي Ø³ÙŠÙØ¹Ø§Ù„ج Ø§Ù„Ù…Ù„ÙØ§Øª المتعدّدة. + اختر الإجراء الذي تريد تطبيقه على Ø§Ù„Ù…Ù„ÙØ§Øª التي Ø£Ùلتّها. <br/>لاحظ أنّ خيار â€Ø§Ø³ØªÙˆØ±Ùد“ هو الوحيد الذي Ø³ÙŠÙØ¹Ø§Ù„ج Ø§Ù„Ù…Ù„ÙØ§Øª المتعدّدة. + اختر الإجراء الذي تريد تطبيقه على Ø§Ù„Ù…Ù„ÙØ§Øª التي Ø£Ùلتّها. <br/>لاحظ أنّ خيار â€Ø§Ø³ØªÙˆØ±Ùد“ هو الوحيد الذي Ø³ÙŠÙØ¹Ø§Ù„ج Ø§Ù„Ù…Ù„ÙØ§Øª المتعدّدة. + اختر الإجراء الذي تريد تطبيقه على Ø§Ù„Ù…Ù„ÙØ§Øª التي Ø£Ùلتّها. <br/>لاحظ أنّ خيار â€Ø§Ø³ØªÙˆØ±Ùد“ هو الوحيد الذي Ø³ÙŠÙØ¹Ø§Ù„ج Ø§Ù„Ù…Ù„ÙØ§Øª المتعدّدة. + + + + + Select SQL file to open + اختر مل٠SQL Ù„ÙØªØ­Ù‡ + + + + Select file name + اختر اسم المل٠+ + + + Select extension file + اختر مل٠الامتداد + + + + Extension successfully loaded. + نجح تحميل الامتداد. + + + + Error loading extension: %1 + خطأ أثناء تحميل الامتداد: %L1 + + + + + Don't show again + لا تعرض ثانيةً + + + + New version available. + تتوÙّر إصدارة جديدة. + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + تتوÙّر إصدارة جديدة من «متصÙّح قواعد بيانات SQLite» â€(%L1Ù«â€%L2Ù«â€%L3).<br/><br/>من ÙØ¶Ù„Ùƒ نزّلها من <a href='%4'>%L4</a>. + + + + Collation needed! Proceed? + قواعد مقارنة المحار٠مطلوبة! أنتابع؟ + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + يحتاج أحد الجداول ÙÙŠ قاعدة البيانات هذه دالة قواعد مقارنة المحار٠Collation الخاصّة â€%L1“ والتي لا يستطيع البرنامج توÙيرها دون معلومات أخرى. +احذر إن اخترت المتابعة، Ùقد تحدث أمور غير حسنة لقاعدة البيانات. +Ø®ÙØ° نسخة احتياطيّة! + + + + creating collation + ÙŠÙنشئ قواعد مقارنة المحار٠+ + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + ضع اسمًا جديدًا للسان SQL. استخدم محر٠â€&&“ Ù„ÙŠÙØªØ§Ø­ استخدام المحر٠الذي يليه كاختصار لوحة Ù…ÙØ§ØªÙŠØ­. + + + + Please specify the view name + من ÙØ¶Ù„Ùƒ اختر اسم المنظور + + + + There is already an object with that name. Please choose a different name. + هناك كائن Ø¨Ù†ÙØ³ الاسم. من ÙØ¶Ù„Ùƒ اختر اسمًا آخر. + + + + View successfully created. + نجح إنشاء المنظور. + + + + Error creating view: %1 + خطأ أثناء إنشاء المنظور: %L1 + + + + This action will open a new SQL tab for running: + Ø³ÙŠÙØªØ­ هذا الإجراء لسان SQL جديد لتشغيل: + + + + Press Help for opening the corresponding SQLite reference page. + انقر â€Ù…ساعدة“ Ù„ÙØªØ­ ØµÙØ­Ø© SQLite المرجعية المناسبة. + + + + DB Browser for SQLite project file (*.sqbpro) + مل٠مشروع «متصÙّح قواعد بيانات SQLite» â€(*.sqbpro) + + + + Execution finished with errors. + اكتمل التنÙيذ وحدثت أخطاء. + + + + Execution finished without errors. + اكتمل التنÙيذ دون أخطاء. + + + + NullLineEdit + + + Set to NULL + اضبطه على NULL + + + + Alt+Del + Alt+Del + + + + PlotDock + + + Plot + رسم بياني + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + تعرض هذه اللوحة قائمة الأعمدة للمجدول الذي تتصÙّحه حاليًا أو للاستعلام الذي Ù†ÙÙّذ حديثًا. يمكنك تحديد الأعمدة التي تريد استخدامها كمحاور س أو ص للوحة الرسم البياني أدناه. يعرض الجدول نوع المحور المكتش٠والذي سيؤثّر على الرسم البياني الناتج. يمكنك تحديد الأعمدة العددية Ùقط لمحور ص، عكس محور س حيث يمكنك تحديد:<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">تاريخ/وقت</span>: السلاسل النصية التي لها التنسيق â€yyyy-MM-dd hh:mm:ss“ أو â€yyyy-MM-ddThh:mm:ss“</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">تاريخ</span>: السلاسل النصية التي لها التنسيق â€yyyy-MM-dd“</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">وقت</span>: السلاسل النصّية التي لها التنسيق â€hh:mm:ss“</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">لصيقة</span>: السلاسل النصية التي لها تنسيقات أخرى. تحديد هذا العمود كمحور x سيÙنتج رسم بياني بأشرطة حيث قيم الأعمدة ستكون لصيقات للأشرطة</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">عدد</span>: قيم عددية صحيحة أو حقيقية</li></ul>بنقر خلايا ص مزدوجًا يمكنك تغيير اللون المستخدم لذلك الرسم. + + + + Columns + الأعمدة + + + + X + س + + + + Y1 + ص1 + + + + Y2 + ص2 + + + + Axis Type + نوع المحور + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + هنا تجد الرسم البياني المرسوم عند تحديد قيم x Ùˆ y أعلاه. + +انقر النقاط لتحديدها ÙÙŠ الرسم البياني والجدول. انقر مع Ctrl لتحديد مدًى من النقاط. + +استخدم عجلة Ø§Ù„ÙØ£Ø±Ø© للتقريب والإبعاد، وحرّك Ø§Ù„ÙØ£Ø±Ø© لتغيير مدى المحور. + +اختر المحاور أو لصيقات المحاور لتحريكها أو قرّب/بعّد بذاك الاتجاه ÙØ­Ø³Ø¨. + + + + Line type: + نوع الخطوط: + + + + + None + بلا + + + + Line + خط + + + + StepLeft + عتبة يسرى + + + + StepRight + عتبة يمنى + + + + StepCenter + عتبة وسطى + + + + Impulse + نبض + + + + Point shape: + شكل النقط: + + + + Cross + علامة ضرب + + + + Plus + علامة جمع + + + + Circle + دائرة + + + + Disc + قرص + + + + Square + مربّع + + + + Diamond + معيّن + + + + Star + نجمة + + + + Triangle + مثلّث + + + + TriangleInverted + مثلّث مقلوب + + + + CrossSquare + علامة ضرب ÙÙŠ مربّع + + + + PlusSquare + علامة جمع ÙÙŠ مربّع + + + + CrossCircle + علامة ضرب ÙÙŠ دائرة + + + + PlusCircle + علامة جمع ÙÙŠ دائرة + + + + Peace + رمز السلام + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <p>Ø§Ø­ÙØ¸ الرسم البياني الحالي...</p><p>نسق المل٠يحدّده الامتداد (png Ùˆjpg Ùˆpdf Ùˆbmp)</p> + + + + Save current plot... + Ø§Ø­ÙØ¸ الرسم البياني الحالي... + + + + + Load all data and redraw plot + حمّل كلّ البيانات ÙˆØ£Ø¹ÙØ¯ رسم الرسم البياني + + + + + + Row # + رقم الص٠+ + + + Copy + انسخ + + + + Print... + اطبع... + + + + Help + + + + + Show legend + اعرض Ù…ÙØªØ§Ø­ الرسم + + + + Stacked bars + أشرطة مرصوصة + + + + Fixed number format + + + + + Date/Time + تاريخ/وقت + + + + Date + تاريخ + + + + Time + وقت + + + + + Numeric + عدد + + + + Label + لصيقة + + + + Invalid + غير صالح + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + حمّل كلّ البيانات ÙˆØ£Ø¹ÙØ¯ رسم الرسم البياني. +تحذير: لم ØªÙØ¬Ù„ب كلّ البيانات من الجدول بسبب استعمال آليّة جلب جزئية. + + + + Choose an axis color + اختر لونًا للمحور + + + + Choose a filename to save under + اختر اسمًا Ù„Ù„Ù…Ù„Ù Ù„Ø­ÙØ¸Ù‡ + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;كلّ Ø§Ù„Ù…Ù„ÙØ§Øª(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + توجد منحنيات ÙÙŠ هذا الرسم البياني ولا يمكن تطبيق نمط الخطوط المحدّد إلّا على الرسوم البيانية Ø§Ù„Ù…ÙØ±ÙˆØ²Ø© حسب س. إمّا أن ØªÙØ±Ø² الجدول أو الاستعلام حسب س لإزالة المنحنيات أو تحديد أحد الأنماط التي تدعمها المنحنيات: â€Ø¨Ù„ا“ أو â€Ø®Ø·â€œ. + + + + Loading all remaining data for this table took %1ms. + أخذ تحميل كلّ البيانات الباقية لهذا الجدول %L1 م‎ث. + + + + PreferencesDialog + + + Preferences + Ø§Ù„ØªÙØ¶ÙŠÙ„ات + + + + &General + &عام + + + + Remember last location + تذكّر آخر مكان + + + + Always use this location + استخدم هذا المكان دائمًا + + + + Remember last location for session only + تذكّر آخر مكان لهذه الجلسة Ùقط + + + + + + ... + ... + + + + Default &location + الم&كان المبدئي + + + + Lan&guage + الل&غة + + + + Automatic &updates + الت&حديثات الآلية + + + + + + + + + + + + + + enabled + Ù…ÙØ¹Ù‘لة + + + + Show remote options + اعرض خيارات البعيد + + + + &Database + &قاعدة البيانات + + + + Database &encoding + &ترميز قاعدة البيانات + + + + Open databases with foreign keys enabled. + Ø§ÙØªØ­ قواعد البيانات ÙˆØ§Ù„Ù…ÙØ§ØªÙŠØ­ الأجنبية Ù…ÙØ¹Ù‘لة. + + + + &Foreign keys + الم&ÙØ§ØªÙŠØ­ الأجنبية + + + + Remove line breaks in schema &view + أزÙÙ„ كاسرات الأسطر ÙÙŠ من&ظور المخطّط + + + + Prefetch block si&ze + &حجم الكتلة لجلبها مسبقًا + + + + SQ&L to execute after opening database + Ø¥&ÙØ§Ø¯Ø© SQL لتÙÙ†Ùّذ بعد ÙØªØ­ قاعدة البيانات + + + + Default field type + نوع الحقول المبدئي + + + + Data &Browser + مت&صÙّح البيانات + + + + Font + الخط + + + + &Font + ال&خط + + + + Content + المحتوى + + + + Symbol limit in cell + أقصى عدد من الرموز ÙÙŠ كلّ خليّة + + + + NULL + NULL + + + + Regular + العادية + + + + Binary + البيانات الثنائيّة + + + + Background + الخلÙية + + + + Filters + المرشّحات + + + + Threshold for completion and calculation on selection + عتبة إكمال النصوص والحساب + + + + Show images in cell + اعرض الصور ÙÙŠ الخلايا + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + ÙØ¹Ù‘Ù„ هذا الخيار لعرض معاينة كائنات BLOB التي Ùيها بيانات صور داخل الخلايا. ولكن يمكن أن يؤثّر هذا على أداء متصÙّح البيانات. + + + + Escape character + محر٠الهروب + + + + Delay time (&ms) + وقت التأخير (&م‌ث) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + اضبط وقت انتظار قبل تطبيق قيمة المرشّح الجديدة. يمكن ضبطه إلى القيمة صÙÙØ± لتعطيل الانتظار. + + + + &SQL + Ù…&حرّر SQL + + + + Context + السياق + + + + Colour + اللون + + + + Bold + ثخين + + + + Italic + مائل + + + + Underline + مسطّر + + + + Keyword + الكلمات Ø§Ù„Ù…ÙØªØ§Ø­ÙŠØ© + + + + Function + الدوال + + + + Table + الجداول + + + + Comment + التعليقات + + + + Identifier + Ø§Ù„Ù…Ø¹Ø±Ù‘ÙØ§Øª + + + + String + السلاسل النصية + + + + Current line + السطر الحالي + + + + SQL &editor font size + حجم الخط ÙÙŠ Ù…&حرّر SQL + + + + Tab size + حجم التبويبات + + + + SQL editor &font + &خط محرّر SQL + + + + Error indicators + مؤشّرات الأخطاء + + + + Hori&zontal tiling + التراتب Ø£Ù&قيًا + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + إن ÙØ¹Ù‘لته ÙØ³ØªØ±Ù‰ محرّر أكواد SQL ومنظور جدول النتائج جنبًا إلى جنب بدلًا من أن يكونان Ùوق بعض. + + + + Code co&mpletion + Ø¥&كمال الكود + + + + Toolbar style + نمط شريط الأدوات + + + + + + + + Only display the icon + اعرض الأيقونة ÙØ­Ø³Ø¨ + + + + + + + + Only display the text + اعرض النص ÙØ­Ø³Ø¨ + + + + + + + + The text appears beside the icon + يظهر النص بجانب الأيقونة + + + + + + + + The text appears under the icon + يظهر النص أسÙÙ„ الأيقونة + + + + + + + + Follow the style + اتبع النمط + + + + DB file extensions + امتدادات Ù…Ù„ÙØ§Øª قواعد البيانات + + + + Manage + Ø£Ø¯ÙØ± + + + + Main Window + Ø§Ù„Ù†Ø§ÙØ°Ø© الرئيسية + + + + Database Structure + بنية قاعدة البيانات + + + + Browse Data + تصÙّح البيانات + + + + Execute SQL + Ù†Ùّذ SQL + + + + Edit Database Cell + حرّر خليّة قاعدة البيانات + + + + When this value is changed, all the other color preferences are also set to matching colors. + ØªÙØ¶Ø¨Ø· كلّ ØªÙØ¶ÙŠÙ„ات الألوان الأخرى (متى تغيّر هذا الخيار) إلى الألوان Ø§Ù„Ù…ÙØ·Ø§Ø¨Ù‚Ø© للنمط. + + + + Follow the desktop style + اتبع نمط سطح المكتب + + + + Dark style + النمط الداكن + + + + Application style + نمط البرمجيّة + + + + This sets the font size for all UI elements which do not have their own font size option. + يضبط هذا حجم خط كلّ عناصر الواجهة التي لا تحدّد Ù„Ù†ÙØ³Ù‡Ø§ حجم خط. + + + + Font size + حجم الخط + + + + Max Recent Files + + + + + Prompt to save SQL tabs +in new project file + + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + إن ÙØ¹Ù‘لته ÙØ³ØªÙزال ÙƒØ§Ø³ÙØ±Ø§Øª الأسطر ÙÙŠ عمود â€Ø§Ù„مخطّط“ ÙÙŠ لسان â€Ø¨Ù†ÙŠØ© قاعدة البيانات“ كما والرصي٠والخرج المطبوع. + + + + Database structure font size + حجم خط بنية قاعدة البيانات + + + + Font si&ze + &حجم الخط + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + هذا أقصى عدد من العناصر المسموحة لإجراء مزايا الحساب الثقيلة من عدم ذلك. +أي أقصى عدد من الصÙÙˆÙ ÙÙŠ الجدول Ù„ØªÙØ¹ÙŠÙ„ إكمال القيم حسب القيم الموجودة ÙÙŠ العمود. +وأقصى عدد من الÙهارس ÙÙŠ التحديد لحساب المجموع والمتوسّط. +يمكنك ضبطه على صÙÙØ± لتعطيل الميزة. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + هذا أقصى عدد من الصÙÙˆÙ ÙÙŠ كلّ جدول Ù„ØªÙØ¹ÙŠÙ„ إكمال القيمة حسب البيانات الحالية ÙÙŠ العمود. +يمكن ضبطه على ØµÙØ± لتعطيل الإكمال. + + + + Field display + عرض الحقول + + + + Light style + + + + + Displayed &text + ال&نص المعروض + + + + Formatted + + + + + + + + + + + + Click to set this color + انقر لضبط هذا اللون + + + + Text color + لون النص + + + + Background color + لون الخلÙية + + + + + Preview only (N/A) + معاينة Ùقط (غير متوÙّر) + + + + Foreground + الأمامية + + + + Selection background + + + + + Selection foreground + + + + + Highlight + + + + + SQL &results font size + حجم خط Ù†&تائج SQL + + + + Use tabs for indentation + + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + + + + + &Wrap lines + Ù„Ù&ÙÙ‘ الأسطر + + + + Never + أبدًا + + + + At word boundaries + عند حدود الكلمات + + + + At character boundaries + عند حدود المحار٠+ + + + At whitespace boundaries + عند حدود Ø§Ù„Ù…Ø³Ø§ÙØ§Øª + + + + &Quotes for identifiers + &علامات التنصيص Ù„Ù„Ù…ÙØ¹Ø±Ù‘ÙØ§Øª + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + اختر آليّة التنصيص التي سيستخدمها التطبيق Ù„Ù„Ù…ÙØ¹Ø±Ù‘ÙØ§Øª ÙÙŠ كود SQL. + + + + "Double quotes" - Standard SQL (recommended) + "علامات تنصيص مزدوجة" - SQL القياسية (مستحسن) + + + + `Grave accents` - Traditional MySQL quotes + `نبر الإطالة` - علامات اقتباس MySQL التقليدية + + + + [Square brackets] - Traditional MS SQL Server quotes + [أقواس مربّعة] - علامات تنصيص خادوم SQL Ù„ÙÙ…Ø§ÙŠÙƒØ±ÙˆØ³ÙˆÙØª التقليدي + + + + Keywords in &UPPER CASE + الكلمات Ø§Ù„Ù…ÙØªØ§Ø­ÙŠØ© &كبيرة الحالة + + + + When set, the SQL keywords are completed in UPPER CASE letters. + إن ÙØ¹Ù‘لته ÙØ³ÙŠØ¬Ø±ÙŠ Ø¥ÙƒÙ…Ø§Ù„ كلمات SQL Ø§Ù„Ù…ÙØªØ§Ø­ÙŠÙ‘Ø© بالأحر٠وحالتها كبيرة. + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + إن ÙØ¹Ù‘لته ÙØ³ØªÙبرز الأسطر ÙÙŠ كود SQL التي تسبّبت بأخطاء أثناء آخر تنÙيذ ÙˆØ³ÙŠÙØ´ÙŠØ± إطار النتائج إلى الخطأ ÙÙŠ الخلÙية + + + + Close button on tabs + أزرار إغلاق على الألسنة + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + إن ÙØ¹Ù‘لته ÙØ³ØªØ¹Ø±Ø¶ ألسنة محرّر SQL زرّ إغلاق. وبغضّ النظر عن هذا الخيار، يمكنك استعمال قائمة السياق أو اختصار لوحة Ø§Ù„Ù…ÙØ§ØªÙŠØ­ لإغلاق تلك الألسنة. + + + + &Extensions + الامت&دادات + + + + Select extensions to load for every database: + حدّد الامتدادات Ù„ØªÙØ­Ù…ّل لكلّ قاعدة بيانات: + + + + Add extension + أضÙ٠امتدادًا + + + + Remove extension + أزÙÙ„ الامتداد + + + + Select built-in extensions to load for every database: + + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + مع أنّ معامل REGEX مدعوم، إلّا أنّ SQLITE ليس Ùيها أية خوارزمية تعابير نمطية Ù…Ùنجزة،<br/>بل تنادي التطبيق الجاري. ينÙّذ «متصÙّح قواعد بيانات SQLite» هذه الخوارزمية لك<br/>لتستعمل REGEXP دون عناء. مع ذلك، يختل٠تنÙيذ هذه الميزة ولربّما تحتاج استعمال<br/>واحدة أخرى، لذا ÙØ£Ù†Øª حرّ ÙÙŠ تعطيل طريقة التطبيق ÙÙŠ التنÙيذ وتحميل أيّ من تلك باستعمال<br/>إحدى الامتدادات. إعادة تشغيل التطبيق مطلوبة. + + + + Disable Regular Expression extension + عطّل ملحقة العبارات النمطية + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + توÙّر SQLite دالة SQL لتحميل الامتدادات من مل٠مكتبة مشتركة. ÙØ¹Ù‘Ù„ هذا إن أردت استعمال دالة <span style=" font-style:italic;">load_extension()‎</span> من كود SQL.</p><p>لأسباب أمنية، تحميل الامتداد معطّل مبدئيًا ويجب ØªÙØ¹ÙŠÙ„Ù‡ بهذا الإعداد. يمكنك دائمًا تحميل الامتدادات عبر الواجهة الرسومية، حتى لو كان هذا الخيار معطّلًا. + + + + Allow loading extensions from SQL code + اسمح بتحميل الامتدادات من كود SQL + + + + Remote + البعيد + + + + CA certificates + شهادات سلطة الشهادات + + + + Proxy + الوسيط + + + + Configure + اضبط + + + + Export Settings + + + + + Import Settings + + + + + + Subject CN + اش موضوع التعمية + + + + Common Name + الاسم الشائع + + + + Subject O + المنظّمة موضوع التعمية + + + + Organization + المنظّمة + + + + + Valid from + صالحة من + + + + + Valid to + صالحة حتى + + + + + Serial number + الرقم التسلسلي + + + + Your certificates + شهاداتك + + + + File + المل٠+ + + + Subject Common Name + الاسم الشائع لموضوع التعمية + + + + Issuer CN + اش Ø§Ù„Ù…ÙØµØ¯Ùر + + + + Issuer Common Name + الاسم الشائع Ù„Ù„Ù…ÙØµØ¯Ùر + + + + Clone databases into + استنسخ قواعد البيانات إلى + + + + + Choose a directory + اختر دليلًا + + + + + The language will change after you restart the application. + ستتغيّر اللغة بعد إعادة تشغيل التطبيق. + + + + Select extension file + اختر مل٠الامتداد + + + + Extensions(*.so *.dylib *.dll);;All files(*) + الامتدادات(*.so *.dylib *.dll);;كلّ Ø§Ù„Ù…Ù„ÙØ§Øª(*) + + + + Import certificate file + Ø§Ø³ØªÙˆØ±ÙØ¯ مل٠شهادة + + + + No certificates found in this file. + لم ØªÙØ¹Ø«Ø± على شهادات ÙÙŠ هذا الملÙ. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + أمتأكّد من إزالة هذه الشهادة؟ Ø³ØªÙØ­Ø°Ù كلّ بيانات الشهادة من إعدادات التطبيق! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + أمتأكّد من مسح كلّ الإعدادات المحÙوظة؟ +ستÙقد كلّ Ø§Ù„ØªÙØ¶ÙŠÙ„ات لديك ÙˆØ³ØªÙØ³ØªØ¹Ù…Ù„ القيم المبدئية. + + + + Save Settings File + + + + + + Initialization File (*.ini) + + + + + The settings file has been saved in location : + + + + + + Open Settings File + + + + + The settings file was loaded properly. + + + + + The selected settings file is not a normal settings file. +Please check again. + + + + + ProxyDialog + + + Proxy Configuration + ضبط الوسيط + + + + Pro&xy Type + &نوع الوسيط + + + + Host Na&me + ا&سم Ø§Ù„Ù…ÙØ¶ÙŠÙ + + + + Port + Ø§Ù„Ù…Ù†ÙØ° + + + + Authentication Re&quired + الاستيثاق Ù…&طلوب + + + + &User Name + اسم المست&خدم + + + + Password + كلمة السر + + + + None + بلا وسيط + + + + System settings + إعدادات النظام + + + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 + + + + QObject + + + Error importing data + خطأ ÙÙŠ استيراد البيانات + + + + from record number %1 + من السجلّ رقم %L1 + + + + . +%1 + . +%L1 + + + + Importing CSV file... + يستورد مل٠CSV... + + + + Cancel + ألغ٠+ + + + All files (*) + كلّ Ø§Ù„Ù…Ù„ÙØ§Øª (*) + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + Ù…Ù„ÙØ§Øª قواعد بيانات SQLite â€(*.db *.sqlite *.sqlite3 *.db3) + + + + Left + يسار + + + + Right + يمين + + + + Center + وسط + + + + Justify + ضبط + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + Ù…Ù„ÙØ§Øª قواعد بيانات SQLite â€(*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + Ù…Ù„ÙØ§Øª مشاريع «متصÙّح قواعد بيانات SQLite» â€(*.sqbpro) + + + + SQL Files (*.sql) + Ù…Ù„ÙØ§Øª SQL â€(*.sql) + + + + All Files (*) + كلّ Ø§Ù„Ù…Ù„ÙØ§Øª (*) + + + + Text Files (*.txt) + Ù…Ù„ÙØ§Øª النصوص (*.txt) + + + + Comma-Separated Values Files (*.csv) + Ù…Ù„ÙØ§Øª القيم المقسومة بÙواصل (*.csv) + + + + Tab-Separated Values Files (*.tsv) + Ù…Ù„ÙØ§Øª القيم المقسومة بجدولات (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + Ù…Ù„ÙØ§Øª القيم المقسومة Ø¨Ø­Ø±ÙˆÙ ÙØµÙ„ (*.dsv) + + + + Concordance DAT files (*.dat) + â€Concordance DAT files â€(*.dat) + + + + JSON Files (*.json *.js) + Ù…Ù„ÙØ§Øª JSON â€(*.json *.js) + + + + XML Files (*.xml) + Ù…Ù„ÙØ§Øª XML â€(*.xml) + + + + Binary Files (*.bin *.dat) + Ø§Ù„Ù…Ù„ÙØ§Øª الثنائيّة (*.bin *.dat) + + + + SVG Files (*.svg) + Ù…Ù„ÙØ§Øª SVG â€(*.svg) + + + + Hex Dump Files (*.dat *.bin) + Ù…Ù„ÙØ§Øª ستّ‌عشرية Ù…ÙØ±Ù‘غة (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + الامتدادات (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + + + + + QsciCommand + + Paste + ألصÙÙ‚ + + + Cancel + ألغ٠+ + + + QsciLexerCPP + + Default + المبدئي + + + Keyword + الكلمات Ø§Ù„Ù…ÙØªØ§Ø­ÙŠØ© + + + Identifier + Ø§Ù„Ù…Ø¹Ø±Ù‘ÙØ§Øª + + + + QsciLexerJSON + + Default + المبدئي + + + String + السلاسل النصية + + + + QsciLexerJavaScript + + Regular expression + تعبير نمطي + + + + QsciLexerPython + + Default + المبدئي + + + Comment + التعليقات + + + Keyword + الكلمات Ø§Ù„Ù…ÙØªØ§Ø­ÙŠØ© + + + Identifier + Ø§Ù„Ù…Ø¹Ø±Ù‘ÙØ§Øª + + + + QsciLexerSQL + + Default + المبدئي + + + Comment + التعليقات + + + Keyword + الكلمات Ø§Ù„Ù…ÙØªØ§Ø­ÙŠØ© + + + Identifier + Ø§Ù„Ù…Ø¹Ø±Ù‘ÙØ§Øª + + + + QsciScintilla + + Select All + حدّد الكلّ + + + + RemoteCommitsModel + + + Commit ID + معرّ٠الإيداع + + + + Message + الرسالة + + + + Date + التاريخ + + + + Author + المؤلّ٠+ + + + Size + الحجم + + + + Authored and committed by %1 + ألّÙÙ‡ وأودعه: %L1 + + + + Authored by %1, committed by %2 + ألّÙÙ‡ %L1ØŒ وأودعه %L2 + + + + RemoteDatabase + + + Error opening local databases list. +%1 + خطأ أثناء ÙØªØ­ قائمة قواعد البيانات المحليّة. +%L1 + + + + Error creating local databases list. +%1 + خطأ أثناء إنشاء قائمة قواعد البيانات المحليّة. +%L1 + + + + RemoteDock + + + Remote + البعيد + + + + Identity + الهويّة + + + + Push currently opened database to server + Ø§Ø¯ÙØ¹ قاعدة البيانات Ø§Ù„Ù…ÙØªÙˆØ­Ø© حاليًا إلى الخادوم + + + + Upload + + + + + DBHub.io + DBHub.io + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html dir="rtl"> +<p>يمكنك ÙÙŠ هذه اللوحة Ø¥Ø¶Ø§ÙØ© قواعد البيانات البعيدة من موقع dbhub.io إلى «متصÙّح قواعد بيانات SQLite». تحتاج أولًا إلى هويّة:</p> +<ol> +<li>Ù„ÙØ¬ إلى موقع dbhub.io (استعمل معلومات ولوج ØºÙØªâ€ŒÙ‡ÙŽØ¨ أو غيرها، كما ترغب)</li> +<li>انقر الزر â€Ù„توليد شهادة العميل“ (وهذه هي الهويّة). هكذا تحصل على مل٠شهادة ØªØ­ÙØ¸Ù‡ على القرص المحلي لديك.</li> +<li>انتقل إلى لسان â€Ø§Ù„بعيد“ ÙÙŠ ØªÙØ¶ÙŠÙ„ات «متصÙّح قواعد بيانات SQLite». انقر الزر Ù„Ø¥Ø¶Ø§ÙØ© شهادة جديدة إلى التطبيق واختر مل٠الشهادة الذي نزّلته للتو.</li> +</ol> +<p>سترى الآن ÙÙŠ لوحة â€Ø§Ù„بعيد“ هويّتك ويمكنك Ø¥Ø¶Ø§ÙØ© قواعد البيانات لتصير بعيدة.</p> +</html> + + + + Local + المحلي + + + + Current Database + قاعدة البيانات الحالية + + + + Clone + استنسخ + + + + Branch + Ø§Ù„ÙØ±Ø¹ + + + + Commits + الإيداعات + + + + Commits for + إيداعات Ø§Ù„ÙØ±Ø¹ + + + + Delete Database + احذ٠قاعدة البيانات + + + + Delete the local clone of this database + احذ٠النسخة المحلية من قاعدة البيانات هذه + + + + Open in Web Browser + Ø§ÙØªØ­ ÙÙŠ متصÙّح Ø§Ù„ÙˆÙØ¨ + + + + Open the web page for the current database in your browser + Ø§ÙØªØ­ ØµÙØ­Ø© Ø§Ù„ÙˆÙØ¨ لقاعدة البيانات الحالية ÙÙŠ المتصÙّح لديك + + + + Clone from Link + استنسخ من رابط + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + استعمل هذا لتنزيل قاعدة بيانات بعيدة للتعديل عليها محليًا باستعمال المسار الموجود ÙÙŠ ØµÙØ­Ø© Ø§Ù„ÙˆÙØ¨ لقاعدة البيانات تلك. + + + + Refresh + Ø£Ù†Ø¹ÙØ´ + + + + Reload all data and update the views + Ø£Ø¹ÙØ¯ تحميل كلّ البيانات وحدّث المناظير + + + + Clone Database + استنسخ قاعدة بيانات + + + + Open Database + Ø§ÙØªØ­ قاعدة بيانات + + + + Open the local copy of this database + Ø§ÙØªØ­ النسخة المحلية من قاعدة البيانات هذه + + + + Check out Commit + اسحب الإيداع (Check out) + + + + Download and open this specific commit + نزّل هذا الإيداع بعينه ÙˆØ§ÙØªØ­Ù‡ + + + + Check out Latest Commit + اسحب الإيداع الأخير (Check out) + + + + Check out the latest commit of the current branch + اسحب الإيداع الأخير (Check out) ÙÙŠ Ø§Ù„ÙØ±Ø¹ الحالي + + + + Save Revision to File + Ø§Ø­ÙØ¸ المراجعة ÙÙŠ مل٠+ + + + Saves the selected revision of the database to another file + ÙŠØ­ÙØ¸ المراجعة المحدّدة لقاعدة البيانات ÙÙŠ مل٠آخر + + + + Upload Database + Ø§Ø±ÙØ¹ قاعدة البيانات + + + + Upload this database as a new commit + ÙŠØ±ÙØ¹ قاعدة البيانات هذه كإيداع جديد + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + تستعمل حاليًا هويّة مضمّنة ÙÙŠ البرمجيّة وللقراءة Ùقط. لو أردت Ø±ÙØ¹ قاعدة البيانات ÙØ¹Ù„يك ضبط حسابك على DBHub.io واستعماله.<br/>أليس لديك واحد بعد؟ <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Ø£Ù†Ø´ÙØ¦Ù‡ الآن</span></a> ÙˆØ§Ø³ØªÙˆØ±ÙØ¯ الشهادة <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">هنا</span></a> Ù„ØªÙØ´Ø§Ø±Ùƒ قواعد بياناتك.<br/>Ø²ÙØ± <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">الموقع</span></a> للمساعدة ÙˆØ§Ù„ØªÙØ§ØµÙŠÙ„. + + + + &User + + + + + &Database + &قاعدة البيانات + + + + Back + Ø¹ÙØ¯ + + + + Select an identity to connect + اختر هويّة للاتصال + + + + Public + عامّة + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + بهذا تÙنزّل قاعدة بيانات من خادوم بعيد للتعديل عليها محليًا. +من ÙØ¶Ù„Ùƒ أدخÙÙ„ المسار الذي ستستنسخ القاعدة منه. +يمكنك توليده بنقر â€Ø§Ø³ØªÙ†Ø³Ø® قاعدة البيانات ÙÙŠ DB4S“ +ÙÙŠ ØµÙØ­Ø© Ø§Ù„ÙˆÙØ¨ لقاعدة البيانات التي تريد. + + + + Invalid URL: The host name does not match the host name of the current identity. + مسار غير صالح: لا يتطابق اسم المضي٠مع اسم مضي٠الهويّة الحالية. + + + + Invalid URL: No branch name specified. + مسار غير صالح: لم تحدّد اسم Ø§Ù„ÙØ±Ø¹. + + + + Invalid URL: No commit ID specified. + مسار غير صالح: لم تحدّد معرّ٠الإيداع. + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + عدّلت النسخة المحلية من قاعدة البيانات. بجلب الإيداع ÙØ£Ù†Øª تÙلغي هذه التعديلات المحلية. +أمتأكّد من المواصلة؟ + + + + The database has unsaved changes. Are you sure you want to push it before saving? + ÙÙŠ قاعدة البيانات تعديلات غير محÙوظة. أمتأكّد من Ø¯ÙØ¹ القاعدة قبل Ø­ÙØ¸ التعديلات؟ + + + + The database you are trying to delete is currently opened. Please close it before deleting. + قاعدة البيانات التي تحاول حذÙها Ù…ÙØªÙˆØ­Ø© حاليًا. من ÙØ¶Ù„Ùƒ أغلÙقها قبل حذÙها. + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + بهذا تحذ٠النسخة المحلية من قاعدة البيانات هذه مع كلّ التعديلات التي لم تودعها بعد. أمتأكّد من حذ٠قاعدة البيانات هذه؟ + + + + RemoteLocalFilesModel + + + Name + الاسم + + + + Branch + Ø§Ù„ÙØ±Ø¹ + + + + Last modified + آخر تعديل + + + + Size + الحجم + + + + Commit + الإيداع + + + + File + المل٠+ + + + RemoteModel + + + Name + الاسم + + + + Commit + الإيداع + + + + Last modified + آخر تعديل + + + + Size + الحجم + + + + Size: + الحجم: + + + + Last Modified: + آخر تعديل: + + + + Licence: + الرخصة: + + + + Default Branch: + Ø§Ù„ÙØ±Ø¹ المبدئي: + + + + RemoteNetwork + + + Choose a location to save the file + اختر مكانًا Ù„Ø­ÙØ¸ المل٠Ùيه + + + + Error opening remote file at %1. +%2 + خطأ أثناء ÙØªØ­ المل٠البعيد ÙÙŠ %L1. +%L2 + + + + Error: Invalid client certificate specified. + خطأ: Ø­ÙØ¯Ù‘دت شهادة عميل غير صالحة. + + + + Please enter the passphrase for this client certificate in order to authenticate. + من ÙØ¶Ù„Ùƒ أدخÙÙ„ عبارة السر لشهادة العميل لإجراء الاستيثاق. + + + + Cancel + ألغ٠+ + + + Uploading remote database to +%1 + ÙŠØ±ÙØ¹ قاعدة البيانات البعيدة إلى +%L1 + + + + Downloading remote database from +%1 + ينزّل قاعدة البيانات البعيدة من +%L1 + + + + Error: Cannot open the file for sending. + خطأ: تعذّر ÙØªØ­ المل٠لإرساله. + + + + RemotePushDialog + + + Push database + Ø¯ÙØ¹ قاعدة البيانات + + + + Database na&me to push to + ا&سم قاعدة البيانات الذي Ø³ÙŠÙØ¯Ùع إليها + + + + Commit message + رسالة الإيداع + + + + Database licence + رخصة قاعدة البيانات + + + + Public + عامّة + + + + Branch + Ø§Ù„ÙØ±Ø¹ + + + + Force push + Ø£Ø¬Ø¨ÙØ± Ø§Ù„Ø¯ÙØ¹ + + + + Username + اسم المستخدم + + + + Database will be public. Everyone has read access to it. + ستكون قاعدة البيانات عامّة. يملك الجميع تصريح القراءة منها. + + + + Database will be private. Only you have access to it. + ستكون قاعدة البيانات خاصّة. أنت من لديك حقّ الوصول إليها لا غير. + + + + Use with care. This can cause remote commits to be deleted. + استعمله بحذر. يمكن أن يتسبّب هذا بحذ٠الإيداعات البعيدة. + + + + RunSql + + + Execution aborted by user + أجهض المستخدم التنÙيذ + + + + , %1 rows affected + ØŒ عدد الصÙو٠المتأثّرة هو %L1 + + + + query executed successfully. Took %1ms%2 + Ù†ÙÙّذ الاستعلام بنجاح: أخذ %L1 م‌ث%L2 + + + + executing query + ينÙّذ الاستعلام + + + + SelectItemsPopup + + + A&vailable + ال&Ù…ÙØªØ§Ø­ + + + + Sele&cted + الم&حدّد + + + + SqlExecutionArea + + + Form + استمارة + + + + Find previous match [Shift+F3] + ابحث عن المطابقة السابقة [Shift+F3] + + + + Find previous match with wrapping + ابحث عن المطابقة السابقة مع Ø§Ù„Ø§Ù„ØªÙØ§Ù + + + + Shift+F3 + Shift+F3 + + + + The found pattern must be a whole word + يجب أن يكون النمط محور البحث كلمة كاملة + + + + Whole Words + الكلمات الكاملة + + + + Text pattern to find considering the checks in this frame + النمط محور البحث بأخذ Ø§Ù„ÙØ­ÙˆØµ ÙÙŠ هذا الإطار بعين الاعتبار + + + + Find in editor + ابحث ÙÙŠ المحرّر + + + + The found pattern must match in letter case + يجب أن يطابق النمط محور البحث حالة الأحر٠+ + + + Case Sensitive + حسّاس لحالة الأحر٠+ + + + Find next match [Enter, F3] + ابحث عن المطابقة التالية [Enter, F3] + + + + Find next match with wrapping + ابحث عن المطابقة التالية مع Ø§Ù„Ø§Ù„ØªÙØ§Ù + + + + F3 + + + + + Interpret search pattern as a regular expression + تعامَل مع نمط البحث كتعبير نمطي + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + إن ÙØ¹Ù‘لته ÙØ³ØªØªØ¹Ø§Ù…Ù„ البرمجيّة مع نمط البحث على أنّه تعبير يونكس نمطي. Ø·Ø§Ù„ÙØ¹ <a href="https://en.wikibooks.org/wiki/Regular_Expressions">التعابير النمطية ÙÙŠ ويكي‌كتب (بالإنجليزية)</a>. + + + + Regular Expression + تعبير نمطي + + + + + Close Find Bar + أغلÙÙ‚ شريط البحث + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + نتائج آخر Ø§Ù„Ø¥ÙØ§Ø¯Ø§Øª المنÙّذة.<br/>يمكنك طيّ هذه اللوحة واستعمال لوحة <span style=" font-style:italic;">سجلّ SQL</span> باختيار <span style=" font-style:italic;">المستخدم</span> بدل هذا. + + + + Results of the last executed statements + نتائج آخر Ø§Ù„Ø¥ÙØ§Ø¯Ø§Øª المنÙّذة + + + + This field shows the results and status codes of the last executed statements. + يعرض هذا الحقل نتائج ورموز حالة آخر Ø§Ù„Ø¥ÙØ§Ø¯Ø§Øª المنÙّذة. + + + + Ctrl+PgUp + + + + + Ctrl+PgDown + + + + + Couldn't read file "%1": %2. + + + + + + Couldn't save file: %1. + تعذّر Ø­ÙØ¸ الملÙ: %L1. + + + + Your changes will be lost when reloading it! + ستÙقد تغييراتك لو ÙØ¹Ù„ت! + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + عدّل برنامج آخر الملÙÙ‘ â€%L1“. أتريد إعادة تحميله؟%L2 + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + + + + + Answer "No to All" to ignore any external update without further prompting. + + + + + Modifying and saving the file will restore prompting. + + + + + SqlTextEdit + + + Ctrl+/ + Ctrl+/ + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) â€«ØªÙØ¹ÙŠØ¯ الدالة abs(X) القيمة Ø§Ù„Ù…ÙØ·Ù„قة للمعطى العددي X. + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + ‎() â€«ØªÙØ¹ÙŠØ¯ الدالة changes()‎ عدد الصÙÙˆÙ ÙÙŠ قاعدة البيانات التي تغيّرت أو Ø£ÙØ¯Ø±Ø¬Øª أو Ø­ÙØ°Ùت باستخدام أحدث Ø¥ÙØ§Ø¯Ø© INSERT أو DELETE أو UPDATE Ø£ÙØ¬Ø±ÙŠØª بنجاح. + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) â€«ØªÙØ¹ÙŠØ¯ الدالة char(X1,X2,...,XN) سلسلة نصية Ù…Ø¤Ù„Ù‘ÙØ© من محارÙÙŽ قيم٠نقاط رموزها اليونيكودية هي الأعداد الصحيحة بدءًا من X1 وحتّى XN بالترتيب. + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) â€«ØªÙØ¹ÙŠØ¯ الدالة coalesce()‎ نسخة من أوّل معطًى ليس NULØŒ أو NULL إن كانت كلّ المعطيات تساوي NULL. + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) ‫الدالة glob(X,Y) تعادل التعبير â€Y GLOB X“. + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) ØªÙØ¹ÙŠØ¯ الدالة‫ ifnull()‎ نسخة من أوّل معطًى ليس NULØŒ أو NULL إن كان ÙƒÙلا المعطيين يساويان NULL. + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) ‫تبحث الدالة instr(X,Y) عن أوّل حدوث للسلسلة النصية Y داخل السلسلة النصية X ÙˆØªÙØ¹ÙŠØ¯ عدد المحار٠قبلها زائدًا Ù¡ØŒ أو ØªÙØ¹ÙŠØ¯ القيمة صÙÙØ± إن لم توجد Y ÙÙŠ أيّ مكان ÙÙŠ X. + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) â€«ØªÙØ³Ù‘ر الدالة hex()‎ المطى على أنّه BLOB ÙˆØªÙØ¹ÙŠØ¯ سلسلة نصية تمثّل عرضًا ستّ‌عشري بحالة أحر٠كبيرة لمحتوى كائن BLOB ذاك. + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + ‎() â€«ØªÙØ¹ÙŠØ¯ الدالة last_insert_rowid()‎ معرّ٠الصÙ/ROWID لآخر عملية إدراج صÙÙ‘ من اتصال قاعدة البيانات والتي Ù†Ùّذت الدالة. + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) ‫باعتبار X سلسلة نصية، ØªÙØ¹ÙŠØ¯ الدالة length(X) عدد المحار٠(وليس البايتات) داخل X والموجودة قبل أوّل محر٠NUL Ùيها. + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) ØªÙØ³ØªØ¹Ù…Ù„ الدالة‫ like()‎ لتنÙيذ التعبير â€Y LIKE X“. + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) ØªÙØ³ØªØ¹Ù…Ù„ الدالة‫ like()‎ لتنÙيذ التعبير â€Y LIKE X ESCAPE Z“. + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) â€«ØªÙØ­Ù…ّل الدالة load_extension(X) امتدادات SQLite من مل٠مكتبة مشتركة اسمه X. +عليك السماح باستعمال هذه الدالة من Ø§Ù„ØªÙØ¶ÙŠÙ„ات. + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) â€«ØªÙØ­Ù…ّل الدالة load_extension(X) امتدادات SQLite من مل٠مكتبة مشتركة اسمه X باستخدام نقطة الإدخال Y. +عليك السماح باستعمال هذه الدالة من Ø§Ù„ØªÙØ¶ÙŠÙ„ات. + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) â€«ØªÙØ¹ÙŠØ¯ الدالة lower(X) نسخة من السلسلة النصية X حيث محار٠آسكي كلّها محوّلة إلى حالة الأحر٠الصغيرة. + + + + (X) ltrim(X) removes spaces from the left side of X. + (X) â€«ØªÙØ²ÙŠÙ„ ltrim(X) Ø§Ù„Ù…Ø³Ø§ÙØ§Øª من الجانب الأيسر للسلسلة النصية X. + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) â€«ØªÙØ¹ÙŠØ¯ الدالة ltrim(X,Y) سلسلة نصية بإزالة كلّ المحار٠التي قد تظهر ÙÙŠ Y من الجانب الأيسر للسلسلة X. + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) â€«ØªÙØ¹ÙŠØ¯ الدالة متعدّدة المعطيات max()‎ المعطى الذي له أكبر قيمة، أو NULL إن كان أحد المعطيات هو NULL. + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) â€«ØªÙØ¹ÙŠØ¯ الدالة متعدّدة المعطيات min()‎ المعطى الذي له أصغر قيمة. + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) â€«ØªÙØ¹ÙŠØ¯ الدالة nullif(X,Y) أوّل معطًى إن كانت المعطيات Ù…Ø®ØªÙ„ÙØ©ØŒ ÙˆØªÙØ¹ÙŠØ¯ NULL إن كانت المعطيات متطابقة. + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) ‫تعمل دالة SQL هذه printf(FORMAT,...) تمامًا مثل دالة لغة سي sqlite3_mprintf()‎ ودالة printf()‎ من مكتبة سي القياسية. + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) â€«ØªÙØ¹ÙŠØ¯ الدالة quote(X) نص SQL حرÙيّ تكون قيمة معامله مناسبة لتوضع ÙÙŠ عبارة SQL. + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + ‎() â€«ØªÙØ¹ÙŠØ¯ الدالة random()‎ عددًا صحيحًا عشوائيًا زائÙًا بين -٩٢٢٣٣٧٢٠٣٦٨٥٤٧٧٥٨٠٨ Ùˆ +٩٢٢٣٣٧٢٠٣٦٨٥٤٧٧٥٨٠٧. + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) â€«ØªÙØ¹ÙŠØ¯ الدالة randomblob(N) كائن BLOB بحجم N بايت يحتوي على بايتات عشوائية Ø²Ø§Ø¦ÙØ©. + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) â€«ØªÙØ¹ÙŠØ¯ الدالة replace(X,Y,Z) سلسلة نصية باستبدال كلّ ظهور للسلسة النصية Y ÙÙŠ السلسلة النصية X بالسلسلة النصية Z. + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) ØªÙØ¹ÙŠØ¯ الدالة‫ round(X) قيمة X عشرية عائمة Ù…Ùقرّبة إلى خانات الصÙÙØ± يمين Ø§Ù„ÙØ§ØµÙ„Ø© العشرية. + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) ØªÙØ¹ÙŠØ¯ الدالة‫ round(X,Y) قيمة X عشرية عائمة Ù…Ùقرّبة إلى خانات Y يمين Ø§Ù„ÙØ§ØµÙ„Ø© العشرية. + + + + (X) rtrim(X) removes spaces from the right side of X. + (X) â€«ØªÙØ²ÙŠÙ„ rtrim(X) Ø§Ù„Ù…Ø³Ø§ÙØ§Øª من الجانب الأيمن للسلسلة النصية X. + + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) â€«ØªÙØ¹ÙŠØ¯ الدالة rtrim(X,Y) سلسلة نصية بإزالة كلّ المحار٠التي قد تظهر ÙÙŠ Y من الجانب الأيمن للسلسلة X. + + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) â€«ØªÙØ¹ÙŠØ¯ الدالة soundex(X) سلسلة نصية بترميز Soundex من السلسلة النصية X. + + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) â€«ØªÙØ¹ÙŠØ¯ substr(X,Y) كلّ المحار٠حتّى نهاية السلسلة النصية X بدايةً من المحر٠رقم Y. + + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) â€«ØªÙØ¹ÙŠØ¯ الدالة substr(X,Y,Z) سلسلة نصية جزئية من السلسلة الدخل X والتي تبدأ بالمحر٠رقم Y وبطول Z من المحارÙ. + + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + ‎() â€«ØªÙØ¹ÙŠØ¯ الدالة total_changes()‎ عدد الصÙو٠المتأثّرة Ø¨Ø¥ÙØ§Ø¯Ø© INSERT أو UPDATE أو DELETE مذ ÙÙØªØ­ اتصال قاعدة البيانات الحالية. + + + + (X) trim(X) removes spaces from both ends of X. + (X) â€«ØªÙØ²ÙŠÙ„ trim(X) Ø§Ù„Ù…Ø³Ø§ÙØ§Øª من جانبي للسلسلة النصية X. + + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) â€«ØªÙØ¹ÙŠØ¯ الدالة trim(X,Y) سلسلة نصية بإزالة كلّ المحار٠التي قد تظهر ÙÙŠ Y من ÙƒÙلا جانبي X. + + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) â€«ØªÙØ¹ÙŠØ¯ الدالة typeof(X) سلسلة نصية توضّح نوع بيانات التعبير X. + + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) â€«ØªÙØ¹ÙŠØ¯ دالة unicode(X) النقطة الرمزية اليونيكودية العددية لأوّل محر٠من السلسلة النصية X. + + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) â€«ØªÙØ¹ÙŠØ¯ الدالة upper(X) نسخة من السلسلة النصية الدخل X حيث محار٠آسكي بحالة الأحر٠الكبيرة محوّلة كلّها إلى حالة الأحر٠الكبيرة. + + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) â€«ØªÙØ¹ÙŠØ¯ الدالة zeroblob(N) كائن BLOB يحتوي N بايت بالمحتوى 0x00. + + + + + + + (timestring,modifier,modifier,...) + (timestring,modifier,modifier,...) + + + + (format,timestring,modifier,modifier,...) + (format,timestring,modifier,modifier,...) + + + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) ØªÙØ¹ÙŠØ¯ الدالة‫ avg()‎ القيمة المتوسّطة لكلّ X لا تساوي NULL داخل مجموعة ما. + + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) â€«ØªÙØ¹ÙŠØ¯ الدالة count(X) عدد المرات التي لا يكون Ùيها X يساوي NULL ÙÙŠ مجموعة ما. + + + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) â€«ØªÙØ¹ÙŠØ¯ الدالة group_concat()‎ سلسلة نصية تجمع كلّ قيم X التي لا تساوي NULL. + + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) â€«ØªÙØ¹ÙŠØ¯ الدالة group_concat()‎ سلسلة نصية تجمع كلّ قيم X التي لا تساوي NULL. إن كان المعطى Y موجودًا، ÙØ³ÙŠÙستخدم ÙƒÙØ§ØµÙ„ بين سيرورات X. + + + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) â€«ØªÙØ¹ÙŠØ¯ الدالة الجامعة max()‎ أكبر قيمة لكلّ القيم ÙÙŠ المجموعة. + + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) â€«ØªÙØ¹ÙŠØ¯ الدالة الجامعة min()‎ أدنى قيمة لا تساوي NULL لكلّ القيم ÙÙŠ المجموعة. + + + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) â€«ØªÙØ¹ÙŠØ¯ الدالتان الجامعتان sum()‎ Ùˆ total()‎ مجموع كل القيم التي لا تساوي NULL ÙÙŠ المجموعة. + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + ‎() ‫رقم الصÙÙ‘ داخل القسم الحالي. ØªÙØ±Ù‚ّم الصÙو٠بدءًا من Ù¡ بالترتيب الذي حدّده بند ORDER BY ÙÙŠ ØªØ¹Ø±ÙŠÙ Ø§Ù„Ù†Ø§ÙØ°Ø©ØŒ أو بترتيب اعتباطي إن لم يكن كذلك.†+ + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + ‎() ‫ناتج row_number()‎ لأوّل ÙØ±Ø¯ ÙÙŠ كلّ مجموعة - رتبة الصÙÙ‘ الحالي مع Ø§Ù„ÙØ±Ø§ØºØ§Øª. إن لم يكن هناك بند ORDER BYØŒ ÙØ³ØªÙعتبر كلّ الصÙÙˆÙ Ø£ÙØ±Ø§Ø¯ ÙˆØ³ØªÙØ¹ÙŠØ¯ هذه الدالة Ù¡ دومًا. + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + ‎() ‫رقم مجموعة Ø§Ù„Ø£ÙØ±Ø§Ø¯ للصÙÙ‘ الحالي داخل القسم - رتبة الصÙÙ‘ الحالي مع Ø§Ù„ÙØ±Ø§ØºØ§Øª. ØªÙØ±Ù‚ّم الأقسام بدءًا من 1 الترتيب الذي حدّده بند ORDER BY ÙÙŠ ØªØ¹Ø±ÙŠÙ Ø§Ù„Ù†Ø§ÙØ°Ø©. إن لم يوجد بند ORDER BYØŒ ÙØ³ØªÙعتبر كلّ الصÙÙˆÙ Ø£ÙØ±Ø§Ø¯ ÙˆØ³ØªÙØ¹ÙŠØ¯ هذه الدالة Ù¡ دومًا. + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + ‎() ب‫غضّ النظر عن الاسم، ØªÙØ¹ÙŠØ¯ هذه الدالة دومًا قيمة بين ٠٫٠ و١٫٠ مساويةً لن(الرتبة - Ù¡)/(صÙو٠القسم - Ù¡)ØŒ حيث â€Ø§Ù„رتبة“ هي القيمة التي ØªÙØ¹ÙŠØ¯Ù‡Ø§ دالة Ø§Ù„Ù†Ø§ÙØ°Ø© المضمّنة rank()‎ Ùˆâ€ØµÙو٠القسم“ هو إجمال عدد الصÙÙˆÙ ÙÙŠ القسم. إن احتوى القسم صÙًا واحدًا ÙØ­Ø³Ø¨ØŒ ÙØ³ØªÙعيد هذه الدالة ٠٫٠. + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + ‎() التوزيع التصاعدي. ÙŠÙØ­Ø³Ø¨ بالمعادلة رقم الصÙ/صÙو٠القسم، حيث â€Ø±Ù‚Ù… الصÙ“ هي القيمة التي أرجعتها‫ row_number()‎ لآخر ÙØ±Ø¯ ÙÙŠ المجموعة، Ùˆâ€ØµÙو٠القسم“ هي عدد الصÙÙˆÙ ÙÙŠ القسم. + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) â€«ÙŠÙØªØ¹Ø§Ù…Ù„ مع المعطى N على أنّه عدد صحيح. تقسم هذه الدالة القسم إلى N مجموعة إلى حد الإمكان من المساواة، ÙˆØªÙØ³Ù†Ø¯ عددًا صحيحًا بين 1 ÙˆN لكل مجموعة، بالترتيب الذي حدّده بند ORDER BYØŒ أو بترتيب اعتباطي إن كان عكس ذلك. إن كان ضروريا، ÙØ³ØªØ­Ø¯Ø« المجموعات الأكبر أولا. ØªÙØ¹ÙŠØ¯ هذه الدالة قيمة العدد الصحيح Ø§Ù„Ù…ÙØ³Ù†Ø­Ø¯Ø© إلى المجموعة التي هي جزء من الص٠الحالي. + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) â€«ØªÙØ¹ÙŠØ¯ ناتج تقدير التعبير expr على الصÙÙ‘ السابق ÙÙŠ القسم. أو NULL إن لم يكن هناك صÙÙ‘ سابق (لأنّ الص٠الحالي هو الأوّل). + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr,offset) ‫لو ÙˆÙØ¬Ø¯ وسيط الإزاحة offset Ùيجب أن يكون عددًا صحيحًا غير سالب. ÙÙŠ هذه الحالة تكون القيمة Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ø© هي ناتج تقدير العبارة expr للصÙÙˆÙ Ø§Ù„Ù…ÙØ²Ø§Ø­Ø© حسب الإزاحة قبل الصÙÙ‘ الحالي ÙÙŠ القسم. لو كانت الإزاحة صÙÙØ±Ù‹Ø§ ÙØ³ÙŠÙقدّر التعبير حسب الص٠الحالي. لو لم تكن هناك صÙو٠بالإزاحة تلك قبل الصÙÙ‘ الحالي، ÙØ³ÙŠÙعاد NULL. + + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,offset,default) ‫وإن ÙˆÙØ¬Ø¯Øª قيمة default ÙØ³ØªÙعاد بدل NULL لو لم يوجد الصÙÙ‘ الذي حدّدته الإزاحة تلك. + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) â€«ØªÙØ¹ÙŠØ¯ ناتج تقدير التعبير حسب الصÙÙ‘ التالي ÙÙŠ القسم. أو NLL لو لم يكن هناك واحد (إذ الصÙÙ‘ الحالي هو آخر صÙÙ‘). + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,offset) ‫لو ÙˆÙØ¬Ø¯ وسيط الإزاحة offset Ùيجب أن يكون عددًا صحيحًا غير سالب. ÙÙŠ هذه الحالة تكون القيمة Ø§Ù„Ù…ÙØ¹Ø§Ø¯Ø© هي ناتج تقدير العبارة expr للصÙÙˆÙ Ø§Ù„Ù…ÙØ²Ø§Ø­Ø© حسب الإزاحة بعد الصÙÙ‘ الحالي ÙÙŠ القسم. لو كانت الإزاحة صÙÙØ±Ù‹Ø§ ÙØ³ÙŠÙقدّر التعبير حسب الص٠الحالي. لو لم تكن هناك صÙو٠بالإزاحة تلك بعد الصÙÙ‘ الحالي، ÙØ³ÙŠÙعاد NULL. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) ‫تحسب دالة Ø§Ù„Ù†ÙˆØ§ÙØ° (window) المضمّنة هذه إطار Ø§Ù„Ù†Ø§ÙØ°Ø© لكلّ ص٠كما تحسبها دوال الجامعة. ØªÙØ¹ÙŠØ¯ الدالة قيمة التعبير expr محسوبًا حسب الص٠الأوّل ÙÙŠ إطار Ø§Ù„Ù†Ø§ÙØ°Ø© لكلّ صÙ. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) ‫تحسب دالة Ø§Ù„Ù†ÙˆØ§ÙØ° (window) المضمّنة هذه إطار Ø§Ù„Ù†Ø§ÙØ°Ø© لكلّ ص٠كما تحسبها دوال الجامعة. ØªÙØ¹ÙŠØ¯ الدالة قيمة التعبير expr محسوبًا حسب الص٠الأخير ÙÙŠ إطار Ø§Ù„Ù†Ø§ÙØ°Ø© لكلّ صÙ. + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr, N) ‫تحسب دالة Ø§Ù„Ù†ÙˆØ§ÙØ° (window) المضمّنة هذه إطار Ø§Ù„Ù†Ø§ÙØ°Ø© لكلّ ص٠كما تحسبها دوال الجامعة. ØªÙØ¹ÙŠØ¯ الدالة قيمة التعبير expr محسوبًا حسب الص٠رقم N ÙÙŠ إطار Ø§Ù„Ù†Ø§ÙØ°Ø©. ØªÙØ±Ù‚ّم الصÙÙˆÙ ÙÙŠ إطارات Ø§Ù„Ù†ÙˆØ§ÙØ° بدءًا بالعدد Ù¡ حسب الترتيب الذي حدّده بند ORDER BY لو ÙˆÙØ¬Ø¯ØŒ أو بترتيب اعتباطي لو لم يوجد. ولو لم يكن هناك ص٠برقم N ÙÙŠ القسم ÙØ³ÙŠÙعاد NULL. + + + + (X) Return the arccosine of X. The result is in radians. + + + + + (X) Return the hyperbolic arccosine of X. + + + + + (X) Return the arcsine of X. The result is in radians. + + + + + (X) Return the hyperbolic arcsine of X. + + + + + (X) Return the arctangent of X. The result is in radians. + + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + + + + + (X) Return the hyperbolic arctangent of X. + + + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + + + + + (X) Return the cosine of X. X is in radians. + + + + + (X) Return the hyperbolic cosine of X. + + + + + (X) Convert value X from radians into degrees. + + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + + + + + (X) Return the natural logarithm of X. + + + + + (B,X) Return the base-B logarithm of X. + + + + + + (X) Return the base-10 logarithm for X. + + + + + (X) Return the logarithm base-2 for the number X. + + + + + (X,Y) Return the remainder after dividing X by Y. + + + + + () Return an approximation for Ï€. + + + + + + (X,Y) Compute X raised to the power Y. + + + + + (X) Convert X from degrees into radians. + + + + + (X) Return the sine of X. X is in radians. + + + + + (X) Return the hyperbolic sine of X. + + + + + (X) Return the square root of X. NULL is returned if X is negative. + + + + + (X) Return the tangent of X. X is in radians. + + + + + (X) Return the hyperbolic tangent of X. + + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + + + + + SqliteTableModel + + + reading rows + يقرأ الصÙÙˆÙ + + + + loading... + يحمّل... + + + + References %1(%2) +Hold %3Shift and click to jump there + Ø§Ù„ØªÙØ¶ÙŠÙ„ات %L1â€(%L2) +اضغط %L3Shift وانقر للانتقال إلى هناك + + + + Error changing data: +%1 + خطأ أثناء تغيير البيانات: +%L1 + + + + retrieving list of columns + يجلب قائمة الأعمدة + + + + Fetching data... + يجلب البيانات... + + + + + Cancel + ألغ٠+ + + + TableBrowser + + + Browse Data + تصÙّح البيانات + + + + &Table: + الج&دول: + + + + Select a table to browse data + اختر جدولًا لتصÙّح بياناته + + + + Use this list to select a table to be displayed in the database view + استعمل هذه القائمة لاختيار الجدول الذي Ø³ÙŠÙØ¹Ø±Ø¶ ÙÙŠ منظور قاعدة البيانات + + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + هذا هو منظور جدول قاعدة البيانات. يمكنك إجراء الآتي Ùيه: + - البدء بالكتابة لتحرير القيمة داخل الخط. + - النقر مزدوجًا على أيّ سجلّ لتحرير محتوياته ÙÙŠ Ù†Ø§ÙØ°Ø© محرّر الخلايا. + - ضغط Alt+Del لحذ٠محتوى الخليّة وضبطه على NULL. + - ضغط Ctrl+"‎ لتكرار السجلّ الحالي. + - ضغط Ctrl+'‎ لنسخ القيمة من الخلية أعلاه. + - التحديد العادي وعمليات النسخ واللصق. + + + + Text pattern to find considering the checks in this frame + النمط محور البحث بأخذ Ø§Ù„ÙØ­ÙˆØµ ÙÙŠ هذا الإطار بعين الاعتبار + + + + Find in table + ابحث ÙÙŠ الجدول + + + + Find previous match [Shift+F3] + ابحث عن المطابقة السابقة [Shift+F3] + + + + Find previous match with wrapping + ابحث عن المطابقة السابقة مع Ø§Ù„Ø§Ù„ØªÙØ§Ù + + + + Shift+F3 + Shift+F3 + + + + Find next match [Enter, F3] + ابحث عن المطابقة التالية [Enter, F3] + + + + Find next match with wrapping + ابحث عن المطابقة التالية مع Ø§Ù„Ø§Ù„ØªÙØ§Ù + + + + F3 + + + + + The found pattern must match in letter case + يجب أن يطابق النمط محور البحث حالة الأحر٠+ + + + Case Sensitive + حسّاس لحالة الأحر٠+ + + + The found pattern must be a whole word + يجب أن يكون النمط محور البحث كلمة كاملة + + + + Whole Cell + الخلية كاملة + + + + Interpret search pattern as a regular expression + تعامَل مع نمط البحث كتعبير نمطي + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + إن ÙØ¹Ù‘لته ÙØ³ÙŠÙتعامل مع نمط البحث على أنّه تعبير يونكس نمطي. طالع <a href="https://en.wikibooks.org/wiki/Regular_Expressions">التعابير النمطية ÙÙŠ ويكي‌كتب (بالإنجليزية)</a>. + + + + Regular Expression + تعبير نمطي + + + + + Close Find Bar + أغلÙÙ‚ شريط البحث + + + + Text to replace with + نص الاستبدال + + + + Replace with + استبدله بÙ†+ + + + Replace next match + استبدÙÙ„ المطابقة التالية + + + + + Replace + استبدل + + + + Replace all matches + استبدل كلّ المطابقات + + + + Replace all + استبدل الكلّ + + + + Export to &JSON + + + + + + Export the filtered data to JSON + + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + + + + + Copy column name + + + + + Copy the database table column name to your clipboard + + + + + New Data Browser + + + + + + Add a new docked Data Browser + + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + مرّر إلى البداية + + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + ينقلك هذا الزر إلى بداية منظور الجدول أعلاه. + + + + |< + |< + + + + Scroll one page upwards + مرّر ØµÙØ­Ø© واحدة للأمام + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + ينقلك هذا الزر ØµÙØ­Ø© واحدة من السجلّات لأعلى ÙÙŠ منظور الجدول أعلاه. + + + + < + < + + + + 0 - 0 of 0 + Ù  - Ù  من أصل Ù  + + + + Scroll one page downwards + مرّر ØµÙØ­Ø© واحدة للأسÙÙ„ + + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + ينقلك هذا الزر ØµÙØ­Ø© واحدة من السجلّات لأسÙÙ„ ÙÙŠ منظور الجدول أعلاه. + + + + > + > + + + + Scroll to the end + مرّر إلى النهاية + + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + ينقلك هذا الزر إلى نهاية منظور الجدول أعلاه. + + + + >| + >| + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + انقر هنا للانتقال إلى السجلّ المحدّد + + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + ÙŠÙØ³ØªØ¹Ù…Ù„ هذا الزر ÙÙŠ التنقّل إلى رقم السطر المحدّد ÙÙŠ منطقة â€Ø§Ù†ØªÙ‚Ù„ إلى“. + + + + Go to: + انتقل إلى: + + + + Enter record number to browse + أدخÙÙ„ رقم السجلّ لتصÙّحه + + + + Type a record number in this area and click the Go to: button to display the record in the database view + اكتب رقم السجلّ ÙÙŠ هذا المربّع وانقر زر â€Ø§Ù†ØªÙ‚Ù„ إلى:“ لعرض السجلّ ÙÙŠ منظور قاعدة البيانات + + + + 1 + Ù¡ + + + + Show rowid column + اعرض عمود معرّ٠الصÙÙˆÙ + + + + Toggle the visibility of the rowid column + بدّل ظهور عمود معرّ٠الصÙÙˆÙ/rowid + + + + Unlock view editing + اسمح بتحرير المنظور + + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + يتيح هذا تحرير المنظور الحالي. مع ذلك ستحتاج إلى المحÙّزات المناسبة لإجراء التحرير. + + + + Edit display format + حرّر تنسيق العرض + + + + Edit the display format of the data in this column + حرّر تنسيق عرض البيانات ÙÙŠ هذا العمود + + + + + New Record + سجلّ جديد + + + + + Insert a new record in the current table + Ø£Ø¯Ø±ÙØ¬ سجلًا جديدًا ÙÙŠ الجدول الحالي + + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + ÙŠÙنشئ هذا الزر سجلًا جديدًا ÙÙŠ قاعدة البيانات. أبق٠زر Ø§Ù„ÙØ£Ø±Ø© مضغوطًا Ù„ÙØªØ­ قائمة منبثقة Ùيها عدّة خيارات:<ul><li><span style=" font-weight:600;">سجلّ جديد</span>: لإدراج سجلّ جديد يحمل القيم المبدئية ÙÙŠ قاعدة البيانات.</li><li><span style=" font-weight:600;">Ø£Ø¯Ø±ÙØ¬ قيم...</span>: Ù„ÙØªØ­ مربّع حوار لإدخال القيم قبل إدراجها ÙÙŠ جدول البيانات. يتيح هذا إدخال القيم حسب القيود Ø§Ù„Ù…Ø®ØªÙ„ÙØ©. ÙŠÙÙØªØ­ مربّع الحوار هذا أيضًا إن ÙØ´Ù„ الخيار <span style=" font-weight:600;">سجلّ جديد</span> بسبب هذه القيود.</li></ul> + + + + + Delete Record + احذ٠السجلّ + + + + Delete the current record + احذ٠السجلّ الحالي + + + + + This button deletes the record or records currently selected in the table + يحذ٠هذا الزر السجلّ أو السجلّات المحدّدة حاليًا ÙÙŠ الجدول + + + + + Insert new record using default values in browsed table + Ø£Ø¯Ø±ÙØ¬ سجلًا جديدًا مستخدمًا القيم المبدئية ÙÙŠ الجدول الذي تتصÙّحه + + + + Insert Values... + Ø£Ø¯Ø±ÙØ¬ قيم... + + + + + Open a dialog for inserting values in a new record + Ø§ÙØªØ­ مربّع حوار لإدراج القيم ÙÙŠ سجلّ جديد + + + + Export to &CSV + &صدّر بنسق CSV + + + + + Export the filtered data to CSV + صدّر البيانات المرشّحة إلى CSV + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + ÙŠÙØµØ¯Ù‘ر هذا الزر بيانات الجدول الذي تتصÙّحه كما هي معروضة حاليًا (بعد المرشّحات وتنسيقات العرض وعمود Ø§Ù„ÙØ±Ø²) كمل٠CSV. + + + + Save as &view + Ø§Ø­ÙØ¸ كمن&ظور + + + + + Save the current filter, sort column and display formats as a view + Ø§Ø­ÙØ¸ المرشّح الحالي وعمود Ø§Ù„ÙØ±Ø² وتنسيقات العرض كمنظور + + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + ÙŠØ­ÙØ¸ هذا الزر الإعداد الحالي للجدول الذي تتصÙّحه (المرشّحات وتنسيقات العرض وعمود Ø§Ù„ÙØ±Ø²) ÙÙŠ منظور SQL يمكنك تصÙّحه لاحقًا أو استخدامه ÙÙŠ Ø¥ÙØ§Ø¯Ø§Øª SQL. + + + + Save Table As... + Ø§Ø­ÙØ¸ الجدول ÙƒÙŽâ€... + + + + + Save the table as currently displayed + Ø§Ø­ÙØ¸ الجدول كما هو معروض حاليًا + + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + توÙّر القائمة المنبثقة هذه الخيارات الآتية والتي تنطبق على الجدول الذي تتصÙّحه والمرشّح حاليًا:<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">صدّر بنسق CSV: ÙŠÙØµØ¯Ù‘ر هذا الخيار البيانات ÙÙŠ الجدول الذي تتصÙّحه كما هي معروضة حاليًا (بعد المرشّحات وتنسيقات العرض وعمود Ø§Ù„ÙØ±Ø²) إلى مل٠بنسق CSV.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ø§Ø­ÙØ¸ كمنظور: ÙŠØ­ÙØ¸ هذا الخيار الإعداد الحالي للجدول الذي تتصÙّحه (المرشّحات وتنسيقات العرض وعمود Ø§Ù„ÙØ±Ø²) ÙÙŠ منظور SQL يمكنك تصÙّحه لاحقًا أو استعماله ÙÙŠ Ø¥ÙØ§Ø¯Ø§Øª SQL.</li></ul> + + + + Hide column(s) + أخÙ٠العمود/الأعمدة + + + + Hide selected column(s) + أخÙ٠العمود/الأعمدة المحدّدة + + + + Show all columns + اعرض كلّ الأعمدة + + + + Show all columns that were hidden + اعرض كلّ الأعمدة التي Ø£ÙØ®Ùيت + + + + + Set encoding + اضبط الترميز + + + + Change the encoding of the text in the table cells + غيّر ترميز النصوص ÙÙŠ خلايا الجدول + + + + Set encoding for all tables + اضبط ترميز كلّ الجداول + + + + Change the default encoding assumed for all tables in the database + غيّر الترميز المبدئي Ø§Ù„Ù…ÙØªØ±Ø¶ ÙÙŠ كلّ جداول قاعدة البيانات + + + + Clear Filters + امسح المرشّحات + + + + Clear all filters + امسح كلّ المرشّحات + + + + + This button clears all the filters set in the header input fields for the currently browsed table. + يمسح هذا الزر كلّ المرشّحات المضبوطة ÙÙŠ حقول الدخل ÙÙŠ الترويسة للجدول الذي تتصÙّحه حاليًا. + + + + Clear Sorting + امسح Ø§Ù„ÙØ±Ø² + + + + Reset the order of rows to the default + صÙّر ترتيب الصÙو٠إلى المبدئيات + + + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + يمسح هذا الزر تريتب الأعمدة المحدّد للجدول الذي تتصÙّحه حاليًا ÙˆÙŠÙØ¹ÙŠØ¯Ù‡ إلى التريب المبدئي. + + + + Print + اطبع + + + + Print currently browsed table data + اطبع بيانات الجدول الذي تتصÙّحه حاليًا + + + + Print currently browsed table data. Print selection if more than one cell is selected. + اطبع بيانات الجدول الذي تتصÙّحه حاليًا. اطبع التحديد إن كانت هناك أكثر من خليّة واحدة محدّدة. + + + + Ctrl+P + Ctrl+P + + + + Refresh + Ø£Ù†Ø¹ÙØ´ + + + + Refresh the data in the selected table + Ø£Ù†Ø¹ÙØ´ البيانات ÙÙŠ الجدول المحدّد + + + + This button refreshes the data in the currently selected table. + ÙŠÙنعش هذا الزر البيانات ÙÙŠ الجدول المحدّد حاليًا. + + + + F5 + + + + + Find in cells + ابحث ÙÙŠ الخلايا + + + + Open the find tool bar which allows you to search for values in the table view below. + Ø§ÙØªØ­ شريط أدوات البحث لتبحث عن القيم التي تريد ÙÙŠ منظور الجدول أسÙله. + + + + Freeze columns + + + + + Make all columns from the first column up to this column not move when scrolling horizontally + + + + + + Bold + ثخين + + + + Ctrl+B + Ctrl+B + + + + + Italic + مائل + + + + + Underline + مسطّر + + + + Ctrl+U + Ctrl+U + + + + + Align Right + حاذ٠يمينًا + + + + + Align Left + حاذ٠يسارًا + + + + + Center Horizontally + الوسط الأÙقي + + + + + Justify + ضبط + + + + + Edit Conditional Formats... + حرّر التنسيقات الشرطيّة... + + + + Edit conditional formats for the current column + حرّر تنسيقات العمود الحالي الشرطيّة + + + + Clear Format + امسح التنسيق + + + + Clear All Formats + امسح كلّ التنسيقات + + + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + امسح كلّ تنسيق الخلايا ÙÙŠ الخلايا المحدّدة وكلّ التنسيقات الشرطيّة ÙÙŠ الأعمدة المحدّدة + + + + + Font Color + لون النص + + + + + Background Color + لون الخلÙية + + + + Toggle Format Toolbar + اعرض/أخÙ٠شريط أدوات التنسيق + + + + Show/hide format toolbar + اعرض/أخÙ٠شريط التنسيق + + + + + This button shows or hides the formatting toolbar of the Data Browser + يعرض هذا الزر (أو ÙŠÙØ®ÙÙŠ) شريط التنسيق لمتصÙّح البيانات + + + + Select column + اختر عمودًا + + + + Ctrl+Space + Ctrl+Space + + + + Replace text in cells + استبدل النصوص ÙÙŠ الخلايا + + + + Filter in any column + رشّح أيّ عمود + + + + Ctrl+R + Ctrl+R + + + + %n row(s) + + لا صÙÙˆÙ + صÙÙ‘ واحد + صÙّان اثنان + %Ln صÙÙˆÙ + %Ln صÙًا + %Ln صÙÙ‘ + + + + + , %n column(s) + + ولا أعمدة + وعمود واحد + وعمودين اثنين + Ùˆ%Ln أعمدة + Ùˆ%Ln عمودًا + Ùˆ%Ln عمود + + + + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . المجموع: %L1ØŒ المتوسّط: %L2ØŒ الأدنى: %L3ØŒ الأقصى: %L4 + + + + Conditional formats for "%1" + تنسيقات â€%L1“ الشرطيّة + + + + determining row count... + يحدّد عدد الصÙÙˆÙ... + + + + %L1 - %L2 of >= %L3 + + + + + %L1 - %L2 of %L3 + + + + + (clipped at %L1 rows) + + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + من ÙØ¶Ù„Ùƒ أدخÙÙ„ Ù…ÙØªØ§Ø­Ù‹Ø§ أساسيًا زائÙًا (pseudo) Ù„ØªÙØ¹ÙŠÙ„ التحرير ÙÙŠ هذا المنظور. يجب أن يكون Ø§Ù„Ù…ÙØªØ§Ø­ اسمًا لأحد الأعمدة Ø§Ù„ÙØ±ÙŠØ¯Ø© ÙÙŠ المنظور. + + + + Delete Records + احذ٠السجلّات + + + + Duplicate records + كرّر السجلّات + + + + Duplicate record + كرّر السجلّ + + + + Ctrl+" + Ctrl+" + + + + Adjust rows to contents + اضبط الصÙو٠إلى محتواها + + + + Error deleting record: +%1 + خطأ أثناء حذ٠السجلّ: +%L1 + + + + Please select a record first + من ÙØ¶Ù„Ùƒ اختر سجلًا أوّلًا + + + + Please choose a new encoding for all tables. + من ÙØ¶Ù„Ùƒ اختر ترميزًا جديدًا لكلّ الجداول. + + + + Please choose a new encoding for this table. + من ÙØ¶Ù„Ùƒ اختر ترميزًا جديدًا لهذا الجدول. + + + + %1 +Leave the field empty for using the database encoding. + %L1 +اترك الحقل ÙØ§Ø±ØºÙ‹Ø§ لاستعمال ترميز قاعدة البيانات. + + + + This encoding is either not valid or not supported. + إمّا أنّ هذا الترميز غير صالح أو أنّه غير مدعوم. + + + + %1 replacement(s) made. + عدد الاستبدالات Ø§Ù„Ù…ÙØ¬Ø±Ø§Ø©: %L1 + + + + TableBrowserDock + + + New Data Browser + + + + + Rename Data Browser + + + + + Close Data Browser + + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + + + + + VacuumDialog + + + Compact Database + رصّ قاعدة البيانات + + + + Warning: Compacting the database will commit all of your changes. + تحذير: برصّ قاعدة البيانات ستÙودع كلّ التعديلات التي أجريتها. + + + + Please select the databases to co&mpact: + من ÙØ¶Ù„Ùƒ اختر قواعد البيانات لر&صّها: + + + diff --git a/src/translations/sqlb_cs.ts b/src/translations/sqlb_cs.ts new file mode 100644 index 000000000..90d9ad759 --- /dev/null +++ b/src/translations/sqlb_cs.ts @@ -0,0 +1,7955 @@ + + + + + AboutDialog + + + About DB Browser for SQLite + O DB Browser pro SQLite + + + + Version + Verze + + + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + + + + + AddRecordDialog + + + Add New Record + + + + + Enter values for the new record considering constraints. Fields in bold are mandatory. + + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + + + + + Name + Název + + + + Type + Typ + + + + Value + + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + + + + + Auto-increment + + + + + + Unique constraint + + + + + + Check constraint: %1 + + + + + + Foreign key: %1 + + + + + + Default value: %1 + + + + + + Error adding record. Message from database engine: + +%1 + + + + + Are you sure you want to restore all the entered values to their defaults? + + + + + Application + + + Possible command line arguments: + Možné parametry pro příkazový řádek: + + + + The user settings file location is replaced with the argument value instead of the environment variable value. + + + + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + + + + + + The file %1 does not exist + Soubor %1 neexistuje + + + + Usage + + + + + options + + + + + + database + + + + + + project + + + + + + csv-file + + + + + Show command line options + + + + + Exit application after running scripts + + + + + + file + + + + + Execute this SQL file after opening the DB + + + + + Import this CSV file into the passed DB or into a new DB + + + + + table + + + + + Browse this table, or use it as target of a data import + + + + + Open database in read-only mode + + + + + settings_file + + + + + Run application based on this settings file + + + + + + group + + + + + + settings + + + + + + value + + + + + Run application with this setting temporarily set to value + + + + + Run application saving this value for this setting + + + + + Display the current version + + + + + Open this SQLite database + + + + + Open this project file (*.sqbpro) + + + + + Import this CSV file into an in-memory database + + + + + + + The %1 option requires an argument + + + + + The -S/--settings option requires an argument. The option is ignored. + + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + + + + + Invalid option/non-existent file: %1 + Neplatná volba/neexistující soubor: %1 + + + + SQLite Version + verze SQLite + + + + SQLCipher Version %1 (based on SQLite %2) + + + + + DB Browser for SQLite Version %1. + + + + + Last commit hash when built: %1 + + + + + Built for %1, running on %2 + + + + + Qt Version %1 + + + + + CipherDialog + + + SQLCipher encryption + Å¡ifrování SQLCipher + + + + &Password + &Heslo + + + + &Reenter password + &Zadejte heslo znovu + + + + Encr&yption settings + + + + + SQLCipher &3 defaults + + + + + SQLCipher &4 defaults + + + + + Custo&m + + + + + Page si&ze + Velikost strany + + + + &KDF iterations + + + + + HMAC algorithm + + + + + KDF algorithm + + + + + Plaintext Header Size + + + + + Passphrase + + + + + Raw key + + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + + + + + ColumnDisplayFormatDialog + + + Choose display format + Vyberte formát zobrazení + + + + Display format + Formát zobrazení + + + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + Vyberte formát zobrazení pro sloupec '%1' který je použit na každou hodnotu pÅ™ed zobrazením. + + + + Default + Výchozí + + + + Decimal number + Desetinné Äíslo + + + + Exponent notation + Notace exponentu + + + + Hex blob + Å estnáctkový blob + + + + Hex number + Å estnáctkové Äíslo + + + + Apple NSDate to date + Apple NSDate na datum + + + + Java epoch (milliseconds) to date + + + + + .NET DateTime.Ticks to date + + + + + Julian day to date + Juliánský den na datum + + + + Unix epoch to local time + + + + + WebKit / Chromium epoch to date + + + + + WebKit / Chromium epoch to local time + + + + + Date as dd/mm/yyyy + Datum jako dd/mm/yyyy + + + + Lower case + Malá písmena + + + + Binary GUID to text + + + + + SpatiaLite Geometry to SVG + + + + + Custom display format must contain a function call applied to %1 + + + + + Error in custom display format. Message from database engine: + +%1 + + + + + Custom display format must return only one column but it returned %1. + + + + + Octal number + OsmiÄkové Äíslo + + + + Round number + Zaokrouhlit Äíslo + + + + Unix epoch to date + Unix epoch na datum + + + + Upper case + Velká písmena + + + + Windows DATE to date + Windows DATE na datum + + + + Custom + Vlastní + + + + CondFormatManager + + + Conditional Format Manager + + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + + + + + Add new conditional format + + + + + &Add + PÅ™idat + + + + Remove selected conditional format + + + + + &Remove + Odstranit + + + + Move selected conditional format up + + + + + Move &up + + + + + Move selected conditional format down + + + + + Move &down + + + + + Foreground + PopÅ™edí + + + + Text color + Barva textu + + + + Background + Pozadí + + + + Background color + Barva pozadí + + + + Font + Font + + + + Size + Velikost + + + + Bold + TuÄný + + + + Italic + Kurzíva + + + + Underline + Podtržený + + + + Alignment + + + + + Condition + + + + + + Click to select color + + + + + Are you sure you want to clear all the conditional formats of this field? + + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + Prosím specifikujte jméno databáze, pod kterým chcete pÅ™istupovat k pÅ™ipojené databázi + + + + Invalid file format + Neplatný formát souboru + + + + Do you want to save the changes made to the database file %1? + Chcete uložit zmÄ›ny provedené do databázového souboru %1? + + + + Exporting database to SQL file... + Exportuji databázi do souboru SQL... + + + + + Cancel + ZruÅ¡it + + + + Executing SQL... + Provádím SQL... + + + + Action cancelled. + Akce zruÅ¡ena. + + + + Do you really want to close this temporary database? All data will be lost. + + + + + Database didn't close correctly, probably still busy + + + + + Cannot open destination file: '%1' + + + + + + Cannot backup to file: '%1'. Message: %2 + + + + + The database is currently busy: + Databáze je právÄ› zaneprázdnÄ›ná: + + + + Do you want to abort that other operation? + + + + + + No database file opened + + + + + + Error in statement #%1: %2. +Aborting execution%3. + + + + + + and rolling back + + + + + didn't receive any output from %1 + + + + + could not execute command: %1 + + + + + Cannot delete this object + Nemohu smazat tento objekt + + + + Cannot set data on this object + + + + + + A table with the name '%1' already exists in schema '%2'. + + + + + No table with name '%1' exists in schema '%2'. + + + + + + Cannot find column %1. + + + + + Creating savepoint failed. DB says: %1 + + + + + Renaming the column failed. DB says: +%1 + + + + + + Releasing savepoint failed. DB says: %1 + + + + + Creating new table failed. DB says: %1 + + + + + Copying data to new table failed. DB says: +%1 + + + + + Deleting old table failed. DB says: %1 + + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + + + + + could not get list of db objects: %1 + + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + + + + + could not get list of databases: %1 + + + + + Error loading extension: %1 + Chyba pÅ™i naÄítání přípony: %1 + + + + Error loading built-in extension: %1 + + + + + could not get column information + + + + + Error setting pragma %1 to %2: %3 + Chyba pÅ™i nastavování pragma %1 na %2: %3 + + + + File not found. + Soubor nebyl nalezen. + + + + DbStructureModel + + + Name + Název + + + + Object + Objekt + + + + Type + Typ + + + + Schema + Schéma + + + + Database + Databáze + + + + Browsables + + + + + All + VÅ¡echny + + + + Temporary + DoÄasný + + + + Tables (%1) + Tabulky (%1) + + + + Indices (%1) + Indexy (%1) + + + + Views (%1) + Pohledy (%1) + + + + Triggers (%1) + Triggery (%1) + + + + EditDialog + + + Edit database cell + Upravit buňku databáze + + + + Mode: + Mód: + + + + + Image + Obrázek + + + + Set as &NULL + Nastavit na &NULL + + + + Apply data to cell + + + + + This button saves the changes performed in the cell editor to the database cell. + + + + + Apply + Provést + + + + Text + Text + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + + + + + RTL Text + + + + + Binary + Binární + + + + JSON + + + + + XML + XML + + + + Evaluation + + + + + + Automatically adjust the editor mode to the loaded data type + + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + + + + + Auto-switch + + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + + + + + Identification of the cell currently in the editor + + + + + Type and size of data currently in table + + + + + Open preview dialog for printing the data currently stored in the cell + + + + + Auto-format: pretty print on loading, compact on saving. + + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + + + + + Word Wrap + + + + + Wrap lines on word boundaries + + + + + + Open in default application or browser + + + + + Open in application + + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + + + + + Save file reference... + + + + + Save reference to file + + + + + + Open in external application + + + + + Autoformat + + + + + &Export... + + + + + + &Import... + + + + + + Import from file + Importovat ze souboru + + + + + Opens a file dialog used to import any kind of data to this database cell. + + + + + Export to file + Exportovat do souboru + + + + Opens a file dialog used to export the contents of this database cell to a file. + + + + + Erases the contents of the cell + Vymazat obsah buňky + + + + This area displays information about the data present in this database cell + Tato oblast zobrazuje informace o aktuálních datech v této databázové buňce + + + + Print... + Tisk... + + + + Ctrl+P + + + + + Open preview dialog for printing displayed text + + + + + Copy Hex and ASCII + + + + + Copy selected hexadecimal and ASCII columns to the clipboard + + + + + Ctrl+Shift+C + + + + + Choose a filename to export data + Vyberte název souboru pro export dat + + + + + Image data can't be viewed in this mode. + + + + + + Try switching to Image or Binary mode. + + + + + + Binary data can't be viewed in this mode. + + + + + + Try switching to Binary mode. + Zkuste pÅ™epnout do binárního režimu. + + + + + Type: NULL; Size: 0 bytes + + + + + + Type: Text / Numeric; Size: %n character(s) + + + + + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + + + + + Type: Valid JSON; Size: %n character(s) + + + + + + + + + Type: Binary; Size: %n byte(s) + + + + + + + + + Couldn't save file: %1. + + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + + + + + + Image files (%1) + Soubory obrázků (%1) + + + + Binary files (*.bin) + Binární soubory (*.bin) + + + + Choose a file to import + Vyberte soubor pro import + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + + + + + Unsaved data in the cell editor + + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + + + + + Editing row=%1, column=%2 + + + + + No cell active. + + + + + %1 Image + %1 Obrázek + + + + Invalid data for this mode + Neplatná data pro tento režim + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + + + + + EditIndexDialog + + + &Name + Název + + + + Order + Řadit + + + + &Table + Tabulka + + + + Edit Index Schema + Upravit schéma indexů + + + + &Unique + Unikátní + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + + + + + Partial inde&x clause + + + + + Colu&mns + Sloupce + + + + Table column + Sloupec tabulky + + + + Type + Typ + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + + + + + Index column + Index sloupce + + + + Deleting the old index failed: +%1 + + + + + Creating the index failed: +%1 + Vytváření indexu se nezdaÅ™ilo: +%1 + + + + EditTableDialog + + + Edit table definition + Upravit definici tabulky + + + + Table + Tabulka + + + + Advanced + PokroÄilé + + + + Without Rowid + Bez id řádku + + + + Database sche&ma + + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + + + + + On Conflict + + + + + Strict + + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + + + + + Fields + Pole + + + + + + Add + + + + + + + Remove + + + + + Move to top + + + + + Move up + + + + + Move down + + + + + Move to bottom + + + + + + + + Name + Název + + + + + Type + Typ + + + + NN + NN + + + + Not null + Není null + + + + PK + PK + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + + + + + AI + AI + + + + Autoincrement + Autoincrement + + + + U + U + + + + + + Unique + Unikátní + + + + Default + Výchozí + + + + Default value + Výchozí hodnota + + + + + Check + Zkontrolovat + + + + Check constraint + Zkontrolovat omezení + + + + Collation + + + + + Foreign Key + Cizí klÃ­Ä + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + + + + + Index Constraints + + + + + Add constraint + + + + + Remove constraint + + + + + + Columns + Sloupce + + + + + + SQL + + + + + Foreign Keys + + + + + References + + + + + Check Constraints + + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + + + + + + Primary Key + + + + + Add a primary key constraint + + + + + Add a unique constraint + + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + + + + + Error creating table. Message from database engine: +%1 + Chyba pÅ™i vytváření tabulky. Zpráva z databáze: +%1 + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + Pole s tímto názvem již existuje. Nejdříve jej pÅ™ejmenujte, nebo vyberte pro toto pole jiný název, prosím. + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + Tento sloupec je použit jako cizí klÃ­Ä v tabulce %1 a jeho název nemůže být zmÄ›nÄ›n. + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + Existuje alespoň jeden řádek, který je nastaven na NULL. Z tohoto důvodu je nemožné nastavit tento flag. Nejprve změňte data v tabulce, prosím. + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + Existuje alespoň jeden řádek, který neobsahuje hodnotu typu integer. Z tohoto důvodu je nemožné nastavit AI flag. Nejprve změňte data v tabulce, prosím. + + + + Column '%1' has duplicate data. + + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + + + + + ExportDataDialog + + + Export data as CSV + Exportovat data do CSV + + + + Tab&le(s) + Tabulka/ky + + + + Colu&mn names in first line + Názvy sloupců v prvním řádku + + + + Fie&ld separator + OddÄ›lovaÄ pole + + + + , + , + + + + ; + ; + + + + Tab + Karta + + + + | + | + + + + + + Other + Ostatní + + + + &Quote character + &Uvozovka + + + + " + " + + + + ' + ' + + + + New line characters + Znaky nového řádku + + + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) + + + + Unix: LF (\n) + Unix: LF (\n) + + + + Pretty print + Pretty print + + + + + Could not open output file: %1 + Nemohu otevřít výstupní soubor: %1 + + + + + Choose a filename to export data + Vyberte název souboru pro export dat + + + + Export data as JSON + Exportovat data jako JSON + + + + exporting CSV + exportování CSV + + + + + Error while writing the file '%1': %2 + + + + + exporting JSON + exportování JSONu + + + + Please select at least 1 table. + Vyberte alespoň jednu tabulku, prosím. + + + + Choose a directory + Vybrat složku + + + + Export completed. + Export byl dokonÄen. + + + + Export finished with errors. + + + + + ExportSqlDialog + + + Export SQL... + Exportovat SQL... + + + + Tab&le(s) + Tabulka/ky + + + + Select All + Vybrat vÅ¡e + + + + Deselect All + ZruÅ¡it výbÄ›r + + + + &Options + Volby + + + + Keep column names in INSERT INTO + Zachovat názvy sloupců v INSERT INTO + + + + Multiple rows (VALUES) per INSERT statement + Více řádků (VALUES) pro příkaz INSERT + + + + Export everything + Exportovat vÅ¡e + + + + Export data only + Exportovat pouze data + + + + Keep original CREATE statements + + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + PÅ™epsat staré schéma (DROP TABLE, then CREATE TABLE) + + + + Export schema only + Exportovat pouze schéma + + + + Please select at least one table. + Vyberte prosím aspoň jednu tabulku. + + + + Choose a filename to export + Vyberte název souboru pro export + + + + Export completed. + Export dokonÄen. + + + + Export cancelled or failed. + Export byl zruÅ¡en nebo selhal. + + + + ExtendedScintilla + + + + Ctrl+H + + + + + Ctrl+F + + + + + + Ctrl+P + + + + + Find... + + + + + Find and Replace... + Najít a nahradit... + + + + Print... + Tisk... + + + + ExtendedTableWidget + + + Use as Exact Filter + + + + + Containing + + + + + Not containing + + + + + Not equal to + + + + + Greater than + VÄ›tší než + + + + Less than + Menší než + + + + Greater or equal + VÄ›tší nebo rovno + + + + Less or equal + Menší nebo rovno + + + + Between this and... + Mezi tímto a... + + + + Regular expression + + + + + Edit Conditional Formats... + + + + + Set to NULL + Nastavit na NULL + + + + Cut + + + + + Copy + Kopírovat + + + + Copy with Headers + Kopírovat s hlaviÄkami + + + + Copy as SQL + Kopírovat jako SQL + + + + Paste + Vložit + + + + Print... + Tisk... + + + + Use in Filter Expression + + + + + Alt+Del + + + + + Ctrl+Shift+C + + + + + Ctrl+Alt+C + + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + + + + + FileExtensionManager + + + File Extension Manager + + + + + &Up + Nahoru + + + + &Down + Dolů + + + + &Add + PÅ™idat + + + + &Remove + Odstranit + + + + + Description + Popis + + + + Extensions + Rozšíření + + + + *.extension + *.extension + + + + FilterLineEdit + + + Filter + Filtr + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + + + + + Clear All Conditional Formats + + + + + Use for Conditional Format + + + + + Edit Conditional Formats... + + + + + Set Filter Expression + + + + + What's This? + Co je toto? + + + + Is NULL + je NULL + + + + Is not NULL + Není NULL + + + + Is empty + Je prázdný + + + + Is not empty + Není prázdný + + + + Not containing... + + + + + Equal to... + Rovný k... + + + + Not equal to... + Není rovný k... + + + + Greater than... + VÄ›tší než... + + + + Less than... + Menší než... + + + + Greater or equal... + VÄ›tší nebo rovno... + + + + Less or equal... + Menší nebo rovno... + + + + In range... + V rozmezí... + + + + Regular expression... + + + + + FindReplaceDialog + + + Find and Replace + Najít a nahradit + + + + Fi&nd text: + Najít text + + + + Re&place with: + Nahradit s: + + + + Match &exact case + + + + + Match &only whole words + + + + + When enabled, the search continues from the other end when it reaches one end of the page + + + + + &Wrap around + + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + + + + + Search &backwards + + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + + + + + &Selection only + + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + + Use regular e&xpressions + + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + + + + + &Find Next + Najít další + + + + F3 + + + + + &Replace + Nahradit + + + + Highlight all the occurrences of the text in the page + + + + + F&ind All + Najít vÅ¡e + + + + Replace all the occurrences of the text in the page + + + + + Replace &All + Nahradit vÅ¡e + + + + The searched text was not found + Hledaný text nebyl nalezen + + + + The searched text was not found. + Hledaný text nebyl nalezen. + + + + The searched text was found one time. + Hledaný text byl nalezen jednou. + + + + The searched text was found %1 times. + Hledaný text byl nalezen %1 krát. + + + + The searched text was replaced one time. + Hledaný text byl nahrazen jednou. + + + + The searched text was replaced %1 times. + Hledaný text byl nahrazen %1 krát. + + + + ForeignKeyEditor + + + &Reset + + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + + + + + ImageViewer + + + Image Viewer + + + + + Reset the scaling to match the original size of the image. + + + + + Set the scaling to match the size of the viewport. + + + + + Print... + Tisk... + + + + Open preview dialog for printing displayed image + + + + + Ctrl+P + + + + + ImportCsvDialog + + + Import CSV file + Importovat soubor CSV + + + + Table na&me + Název tabulky + + + + &Column names in first line + &Názvy sloupců v prvním řádku + + + + Field &separator + OddÄ›lovaÄ pole + + + + , + , + + + + ; + ; + + + + + Tab + Karta + + + + | + | + + + + Other + Ostatní + + + + &Quote character + &Uvozovka + + + + + Other (printable) + + + + + + Other (code) + + + + + " + " + + + + ' + ' + + + + &Encoding + Kódování + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Trim fields? + OÅ™ezat pole? + + + + Separate tables + OddÄ›lit tabulky + + + + Advanced + PokroÄilé + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + + + + + Ignore default &values + Ignorovat výchozí hodnoty + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + + + + + Fail on missing values + + + + + Disable data type detection + + + + + Disable the automatic data type detection when creating a new table. + + + + + Use local number conventions + + + + + Use decimal and thousands separators according to the system locale. + + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + + + + + Abort import + + + + + Ignore row + + + + + Replace existing row + + + + + Conflict strategy + + + + + + Deselect All + ZruÅ¡it celý výbÄ›r + + + + Match Similar + + + + + Select All + Vybrat vÅ¡e + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + + + + + There is already a table named '%1'. Do you want to import the data into it? + + + + + Creating restore point failed: %1 + Vytváření bodu obnovy selhalo: %1 + + + + Creating the table failed: %1 + Vytváření tabulky selhalo: %1 + + + + importing CSV + importování CSV + + + + Could not prepare INSERT statement: %1 + + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + + + + + Inserting row failed: %1 + Vkládání řádku selhalo: %1 + + + + MainWindow + + + DB Browser for SQLite + DB Browser pro SQLite + + + + toolBar1 + toolBar1 + + + + Opens the SQLCipher FAQ in a browser window + OtevÅ™e SQLCipher FAQ v oknÄ› prohlížeÄe + + + + Export one or more table(s) to a JSON file + Export jedné nebo více tabulek do souboru JSON + + + + &File + &Soubor + + + + &Import + &Import + + + + &Export + &Export + + + + Open an existing database file in read only mode + + + + + &Edit + Upravit + + + + &View + Pohled + + + + &Help + Pomoc + + + + DB Toolbar + Panel nástrojů DB + + + + Edit Database &Cell + Upravit databázovou buňku + + + + DB Sche&ma + DB Schéma + + + + + Execute current line + Provést aktuální řádek + + + + This button executes the SQL statement present in the current editor line + + + + + Shift+F5 + + + + + Sa&ve Project + Ulo&žit Projekt + + + + User + Uživatel + + + + Application + Aplikace + + + + &Clear + &VyÄistit + + + + &New Database... + Nová databáze... + + + + + Create a new database file + VytvoÅ™it nový databázový soubor + + + + This option is used to create a new database file. + Tato volba slouží k vytvoÅ™ení nového souboru databáze. + + + + Ctrl+N + + + + + + &Open Database... + Otevřít databázi... + + + + + + + + Open an existing database file + Otevřít existující soubor databáze + + + + + + This option is used to open an existing database file. + Tato volba slouží k otevÅ™ení existujícího souboru databáze. + + + + Ctrl+O + + + + + &Close Database + &Zavřít databázi + + + + This button closes the connection to the currently open database file + + + + + + Ctrl+W + + + + + + Revert database to last saved state + Vrátit databázi do posledního uloženého stavu + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + + + + + + Write changes to the database file + Zapsat zmÄ›ny do souboru databáze + + + + This option is used to save changes to the database file. + Tato volba slouží k uložení provedených zmÄ›n do souboru databáze. + + + + Ctrl+S + + + + + Compact &Database... + + + + + Compact the database file, removing space wasted by deleted records + + + + + + Compact the database file, removing space wasted by deleted records. + + + + + E&xit + Exit + + + + Ctrl+Q + + + + + Import data from an .sql dump text file into a new or existing database. + Importovat data z textového souboru .sql do nové nebo již existující databáze. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + OtevÅ™e průzkumníka, kde můžete importovat data z textového souboru, kde jsou data oddÄ›lena Äárkami, do databázové tabulky. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + + + + + Export a database to a .sql dump text file. + Exportovat databázi do textového souboru .sql + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + + + + + Export a database table as a comma separated text file. + Exportovat databázovou tabulku jako textový soubor oddÄ›lený Äárkami. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + + + + + + Delete Table + Smazat Tabulku + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + + + + + &Preferences... + &Možnosti... + + + + + Open the preferences window. + Otevřít okno s možnostmi. + + + + &DB Toolbar + Panel nástrojů DB + + + + Shows or hides the Database toolbar. + Zobrazí nebo skryje liÅ¡tu Databáze. + + + + Shift+F1 + + + + + New &tab + + + + + Open SQL file(s) + + + + + This button opens files containing SQL statements and loads them in new editor tabs + + + + + Execute line + + + + + &Wiki + Wiki + + + + F1 + + + + + Bug &Report... + Nahlásit chybu... + + + + Feature Re&quest... + Požadavek na funkci... + + + + Web&site + Webová stránka + + + + &Donate on Patreon... + PÅ™ispÄ›t na Patreon... + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + + + + + This button lets you open a DB Browser for SQLite project file + + + + + Browse Table + + + + + Close Pro&ject + + + + + + Close project and database files and return to the initial state + + + + + Ctrl+Shift+F4 + + + + + + Detach Database + + + + + + Detach database file attached to the current database connection + + + + + &Attach Database... + PÅ™iložit databázi... + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + + + + + Temp Store + + + + + Secure Delete + + + + + Case Sensitive Like + + + + + Journal Mode + + + + + Journal Size Limit + + + + + Recursive Triggers + + + + + Page Size + + + + + Foreign Keys + + + + + Auto Vacuum + + + + + Max Page Count + + + + + Checkpoint Full FSYNC + + + + + + Off + + + + + + Normal + + + + + + Full + + + + + Default + Výchozí + + + + File + Soubor + + + + + Memory + + + + + Delete + + + + + Truncate + + + + + Persist + + + + + WAL + + + + + Exclusive + + + + + Automatic Index + + + + + Ignore Check Constraints + + + + + Full FSYNC + + + + + WAL Auto Checkpoint + + + + + User Version + + + + + Synchronous + + + + + None + Žádná + + + + Incremental + + + + + Locking Mode + + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + + + + + &Recent Files + + + + + &New Database + + + + + &Undo + + + + + + Undo last change to the database + + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + + + + + Ctrl+Shift+T + + + + + &Save Project + + + + + Open &Project + + + + + + Add another database file to the current database connection + + + + + This button lets you add another database file to the current database connection + + + + + &Set Encryption... + Nastavit Å¡ifrování... + + + + SQLCipher &FAQ + SQLCipher FAQ + + + + Table(&s) to JSON... + Tabulka(ky) do JSONu... + + + + Open Data&base Read Only... + + + + + Ctrl+Shift+O + + + + + Save results + Uložit výsledky + + + + Save the results view + + + + + This button lets you save the results of the last executed query + + + + + + Find text in SQL editor + Najít text v SQL editoru + + + + Find + + + + + This button opens the search bar of the editor + + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + Najít a nahradit text v SQL editoru + + + + Find or replace + + + + + This button opens the find/replace dialog for the current editor tab + + + + + Ctrl+H + + + + + Export to &CSV + Export do CSV + + + + Export to &JSON + + + + + Save as &view + Uložit jako pohled + + + + Save as view + Uložit jako pohled + + + + Shows or hides the Project toolbar. + Zobrazit nebo skrýt liÅ¡tu projektu + + + + Extra DB Toolbar + Extra DB Toolbar + + + + &Open Database + + + + + New In-&Memory Database + + + + + Drag && Drop SELECT Query + + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + + + + + Drag && Drop Qualified Names + + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + + + + + Drag && Drop Enquoted Names + + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + + + + + &Integrity Check + + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + + + + + &Foreign-Key Check + + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + + + + + &Quick Integrity Check + + + + + Run a quick integrity check over the open DB + + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + + + + + &Optimize + + + + + Attempt to optimize the database + + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + + + + + + Print + Tisk + + + + Print text from current SQL editor tab + + + + + Open a dialog for printing the text in the current SQL editor tab + + + + + Print the structure of the opened database + + + + + Open a dialog for printing the structure of the opened database + + + + + &Save Project As... + + + + + + + Save the project in a file selected in a dialog + + + + + Save A&ll + + + + + + + Save DB file, project file and opened SQL files + + + + + Ctrl+Shift+S + + + + + + Ctrl+Shift+W + + + + + Table from CSV data in Clipboard... + + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + + + + + Show &Row Counts + + + + + This shows the number of rows for each table and view in the database. + + + + + Save Database &As... + + + + + Save the current database as a different file + + + + + Refresh + Obnovit + + + + Reload the database structure + + + + + &Recently opened + &Nedávno otevÅ™ené + + + + Ctrl+T + + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + + + + + Un/comment block of SQL code + + + + + Un/comment block + + + + + Comment or uncomment current line or selected block of code + + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + + + + + Ctrl+/ + + + + + Stop SQL execution + + + + + Stop execution + + + + + Stop the currently running SQL script + + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + + + + + Too&ls + Nástroje + + + + SQL &Log + SQL &Log + + + + Show S&QL submitted by + + + + + Error Log + + + + + This button clears the contents of the SQL logs + + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + + + + + &Plot + + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + + + + + &Remote + Vzdálené + + + + + Project Toolbar + + + + + Extra DB toolbar + Extra DB toolbar + + + + + + Close the current database file + + + + + + Ctrl+F4 + + + + + &Revert Changes + Vrátit ZmÄ›ny + + + + &Write Changes + Zapsat ZmÄ›ny + + + + &Database from SQL file... + Databáze z SQL souboru... + + + + &Table from CSV file... + Tabulka ze souboru CSV... + + + + &Database to SQL file... + Databáze do souboru SQL... + + + + &Table(s) as CSV file... + Tabulka/ky jako soubor CSV... + + + + &Create Table... + VytvoÅ™it Tabulku... + + + + &Delete Table... + Smazat Tabulku... + + + + &Modify Table... + Upravit Tabulku... + + + + Create &Index... + VytvoÅ™it Index... + + + + W&hat's This? + Co je toto? + + + + &About + O + + + + This button opens a new tab for the SQL editor + + + + + &Execute SQL + &Provést příkaz SQL + + + + Execute all/selected SQL + Provést vÅ¡echny/vybrané SQL + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + + + + + + + Save SQL file + Uložit SQL soubor + + + + &Load Extension... + NaÄíst rozšíření... + + + + Ctrl+E + + + + + Export as CSV file + Exportovat jako soubor CSV + + + + Export table as comma separated values file + Exportovat tabulku do souboru jako hodnoty oddÄ›lené Äárkami + + + + + Save the current session to a file + Uložit aktuální session do souboru + + + + Open &Project... + Otevřít projekt... + + + + + Load a working session from a file + + + + + + Save SQL file as + Uložit soubor SQL jako + + + + This button saves the content of the current SQL editor tab to a file + + + + + &Browse Table + &Prohlížet Tabulku + + + + Copy Create statement + Kopírovat příkaz Create + + + + Copy the CREATE statement of the item to the clipboard + Zkopírovat do schránky příkaz CREATE + + + + Ctrl+Return + + + + + Ctrl+L + + + + + + Ctrl+P + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Encrypted + Å ifrováno + + + + Read only + Pouze pro Ätení + + + + Database file is read only. Editing the database is disabled. + Soubor databáze je urÄen pouze pro Ätení. Úprava databáze je zakázána. + + + + Database encoding + Kódování databáze + + + + Database is encrypted using SQLCipher + Databáze je Å¡ifrována pÅ™es SQLCipher + + + + + Choose a database file + Vyberte soubor databáze + + + + + + Choose a filename to save under + Vyberte název souboru pro uložení + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + Jste si jisti, že chcete vrátit zpÄ›t vÅ¡echny provedené zmÄ›ny v databázi '%1' od posledního uložení? + + + + Choose a file to import + Vyberte soubor pro import + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + + + + + Open Database or Project + + + + + Attach Database... + + + + + Import CSV file(s)... + + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + + + + + Text files(*.sql *.txt);;All files(*) + Textové soubory(*.sql *.txt);;VÅ¡echny soubory(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + + + + + Do you want to save the changes made to the project file '%1'? + + + + + File %1 already exists. Please choose a different name. + Soubor %1 již existuje. Vyberte jiný název, prosím. + + + + Error importing data: %1 + Chyba pÅ™i importu dat: %1 + + + + Import completed. + Import dokonÄen. + + + + Delete View + Smazat Pohled + + + + Modify View + + + + + Delete Trigger + Smazat Spoušť + + + + Modify Trigger + + + + + Delete Index + Smazat Index + + + + Modify Index + ZmÄ›nit Index + + + + Modify Table + ZmÄ›nit tabulku + + + + Do you want to save the changes made to SQL tabs in a new project file? + + + + + Do you want to save the changes made to the SQL file %1? + + + + + Could not find resource file: %1 + + + + + Choose a project file to open + Vybrat soubor projektu k otevÅ™ení + + + + Could not open project file for writing. +Reason: %1 + + + + + Busy (%1) + + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + + + + + Ctrl+Tab + + + + + Ctrl+Shift+Tab + + + + + Clear List + + + + + Window Layout + + + + + Reset Window Layout + + + + + Simplify Window Layout + + + + + Alt+Shift+0 + + + + + Dock Windows at Bottom + + + + + Dock Windows at Left Side + + + + + Dock Windows at Top + + + + + The database is currently busy. + + + + + Click here to interrupt the currently running query. + + + + + Alt+Shift+W + + + + + Could not open database file. +Reason: %1 + + + + + In-Memory database + + + + + Choose a database file to save under + + + + + Error while saving the database to the new file. + + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + + + + + Are you sure you want to delete the view '%1'? + + + + + Are you sure you want to delete the trigger '%1'? + + + + + Are you sure you want to delete the index '%1'? + + + + + Error: could not delete the table. + + + + + Error: could not delete the view. + + + + + Error: could not delete the trigger. + + + + + Error: could not delete the index. + + + + + Message from database engine: +%1 + + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + + + + + Edit View %1 + + + + + Edit Trigger %1 + + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + + + + + -- EXECUTING SELECTION IN '%1' +-- + + + + + -- EXECUTING LINE IN '%1' +-- + + + + + -- EXECUTING ALL IN '%1' +-- + + + + + + At line %1: + + + + + Result: %1 + + + + + Result: %2 + + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + + + + + Opened '%1' in read-only mode from recent file list + + + + + Opened '%1' from recent file list + + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + + + + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + + + + + DB file '%1' could not be opened + + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + + + + + Table '%1' not found; settings ignored + + + + + -- Reference to file "%1" (not supported by this version) -- + + + + + Yes. Don't ask again + + + + + This action will open a new SQL tab with the following statements for you to edit and run: + + + + + Rename Tab + + + + + Duplicate Tab + + + + + Close Tab + + + + + Opening '%1'... + + + + + There was an error opening '%1'... + + + + + Value is not a valid URL or filename: %1 + + + + + %1 rows returned in %2ms + + + + + Automatically load the last opened DB file at startup + + + + + Ctrl+0 + + + + + Choose text files + Vybrat textové soubory + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + + + + + Select SQL file to open + Vyberte soubor SQL k otevÅ™ení + + + + Select file name + Vyberte název souboru + + + + Select extension file + Vyberte soubor s rozšířením + + + + Extension successfully loaded. + Rozšíření bylo úspěšnÄ› naÄteno. + + + + Error loading extension: %1 + Chyba pÅ™i naÄítání přípony: %1 + + + + + Don't show again + Znovu nezobrazovat + + + + New version available. + Dostupná nová verze. + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + Nová verze DB Browseru pro SQLite je nyní dostupná (%1.%2.%3).<br/><br/>StáhnÄ›te ji prosím na <a href='%4'>%4</a>. + + + + Project saved to file '%1' + + + + + Collation needed! Proceed? + Je potÅ™eba provést collation! Potvrdit? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + + + + + creating collation + + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + + + + + Please specify the view name + Specifikujte název pohledu, prosím + + + + There is already an object with that name. Please choose a different name. + Objekt s tímto názvem již existuje. Vyberte jiný název, prosím. + + + + View successfully created. + Pohled byl úspěšnÄ› vytvoÅ™en. + + + + Error creating view: %1 + Chyba pÅ™i vytváření pohledu: %1 + + + + This action will open a new SQL tab for running: + + + + + Press Help for opening the corresponding SQLite reference page. + + + + + DB Browser for SQLite project file (*.sqbpro) + DB Browser pro SQLite project file (*.sqbpro) + + + + Error checking foreign keys after table modification. The changes will be reverted. + + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + + + + + Execution finished with errors. + + + + + Execution finished without errors. + + + + + NullLineEdit + + + Set to NULL + Nastavit na NULL + + + + Alt+Del + + + + + PlotDock + + + Plot + + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + + + + + Columns + Sloupce + + + + X + X + + + + Y1 + + + + + Y2 + + + + + Axis Type + + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + + + + + Line type: + Typ řádku: + + + + + None + Žádná + + + + Line + Řádek + + + + StepLeft + KrokVlevo + + + + StepRight + KrokVpravo + + + + StepCenter + KrokDoprostÅ™ed + + + + Impulse + Impuls + + + + Point shape: + + + + + Cross + Kříž + + + + Plus + Plus + + + + Circle + Kruh + + + + Disc + Disk + + + + Square + ÄŒtverec + + + + Diamond + Diamand + + + + Star + HvÄ›zda + + + + Triangle + Trojúhelník + + + + TriangleInverted + ObrácenýTrojúhelník + + + + CrossSquare + + + + + PlusSquare + PlusÄŒtverec + + + + CrossCircle + + + + + PlusCircle + + + + + Peace + + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + + + + + Save current plot... + + + + + + Load all data and redraw plot + + + + + + + Row # + Řádek # + + + + Copy + Kopírovat + + + + Print... + Tisk... + + + + Help + + + + + Show legend + Zobrazit legendu + + + + Stacked bars + + + + + Fixed number format + + + + + Date/Time + Datum/Äas + + + + Date + Datum + + + + Time + ÄŒas + + + + + Numeric + + + + + Label + Å títek + + + + Invalid + + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + + + + + Choose an axis color + Vyberte barvu osy + + + + Choose a filename to save under + Vyberte název souboru pro uložení + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;VÅ¡echny Soubory(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + + + + + Loading all remaining data for this table took %1ms. + + + + + PreferencesDialog + + + Preferences + Možnosti + + + + &General + &Obecné + + + + Remember last location + Zapamatovat poslední umístÄ›ní + + + + Always use this location + Vždy použít toto umístÄ›ní + + + + Remember last location for session only + Pamatovat poslední umístÄ›ní pouze po dobu trvání session + + + + + + ... + ... + + + + Default &location + Výchozí &umístÄ›ní + + + + Lan&guage + Jazyk + + + + Automatic &updates + Automatické &aktualizace + + + + + + + + + + + + + + enabled + povoleno + + + + Show remote options + Zobrazit vzdálené možnosti + + + + &Database + &Databáze + + + + Database &encoding + Kódování &databáze + + + + Open databases with foreign keys enabled. + OtevÅ™e databázi s povolenými cizími klíÄi. + + + + &Foreign keys + &Cizí klíÄe + + + + SQ&L to execute after opening database + SQ&L k vykonání po otevÅ™ení databáze + + + + Data &Browser + ProhlížeÄ Dat + + + + Remove line breaks in schema &view + + + + + Prefetch block si&ze + + + + + Default field type + Výchozí typ pole + + + + Font + Font + + + + &Font + &Font + + + + Content + Obsah + + + + Symbol limit in cell + Maximální poÄet znaků v buňce + + + + NULL + NULL + + + + Regular + Regulární + + + + Binary + Binární + + + + Background + Pozadí + + + + Filters + Filtry + + + + Threshold for completion and calculation on selection + + + + + Show images in cell + + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + + + + + Escape character + + + + + Delay time (&ms) + ZpoždÄ›ní (&ms) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + + + + + &SQL + &SQL + + + + Context + Kontext + + + + Colour + Barva + + + + Bold + TuÄný + + + + Italic + Kurzíva + + + + Underline + Podtržený + + + + Keyword + KlíÄové slovo + + + + Function + Funkce + + + + Table + Tabulka + + + + Comment + Komentář + + + + Identifier + Identifikátor + + + + String + String + + + + Current line + Aktuální řádek + + + + SQL &editor font size + velikost fontu SQL &editoru + + + + Tab size + + + + + SQL editor &font + &font SQL editoru + + + + Error indicators + + + + + Hori&zontal tiling + + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + + + + + Code co&mpletion + + + + + Toolbar style + + + + + + + + + Only display the icon + + + + + + + + + Only display the text + + + + + + + + + The text appears beside the icon + + + + + + + + + The text appears under the icon + + + + + + + + + Follow the style + + + + + DB file extensions + + + + + Manage + + + + + Main Window + + + + + Database Structure + Databázová Struktura + + + + Browse Data + Prohlížet data + + + + Execute SQL + ProveÄte SQL + + + + Edit Database Cell + + + + + When this value is changed, all the other color preferences are also set to matching colors. + + + + + Follow the desktop style + + + + + Dark style + + + + + Application style + + + + + This sets the font size for all UI elements which do not have their own font size option. + + + + + Font size + + + + + Max Recent Files + + + + + Prompt to save SQL tabs +in new project file + + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + + + + + Database structure font size + + + + + Font si&ze + Velikost písma + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + + + + + Field display + + + + + Light style + + + + + Displayed &text + + + + + Formatted + + + + + + + + + + + + Click to set this color + + + + + Text color + Barva textu + + + + Background color + Barva pozadí + + + + + Preview only (N/A) + + + + + Foreground + PopÅ™edí + + + + Selection background + + + + + Selection foreground + + + + + Highlight + + + + + SQL &results font size + + + + + Use tabs for indentation + + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + + + + + &Wrap lines + + + + + Never + Nikdy + + + + At word boundaries + + + + + At character boundaries + + + + + At whitespace boundaries + + + + + &Quotes for identifiers + + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + + + + + "Double quotes" - Standard SQL (recommended) + + + + + `Grave accents` - Traditional MySQL quotes + + + + + [Square brackets] - Traditional MS SQL Server quotes + + + + + Keywords in &UPPER CASE + + + + + When set, the SQL keywords are completed in UPPER CASE letters. + + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + + + + + Close button on tabs + + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + + + + + &Extensions + &Rozšíření + + + + Select extensions to load for every database: + Vyberte rozšíření k naÄtení pro každou databázi: + + + + Add extension + PÅ™idat rozšíření + + + + Remove extension + Odebrat rozšíření + + + + Select built-in extensions to load for every database: + + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + + + + + Disable Regular Expression extension + Zakázat rozšíření pro regulární výrazy + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + + + + + Allow loading extensions from SQL code + + + + + Remote + Vzdálený + + + + CA certificates + certifikáty CA + + + + Proxy + + + + + Configure + + + + + Export Settings + + + + + Import Settings + + + + + + Subject CN + pÅ™edmÄ›t CN + + + + Common Name + + + + + Subject O + pÅ™edmÄ›t O + + + + Organization + Organizace + + + + + Valid from + Platné od + + + + + Valid to + Platné do + + + + + Serial number + Sériové Äíslo + + + + Your certificates + VaÅ¡e certifikáty + + + + File + Soubor + + + + Subject Common Name + + + + + Issuer CN + + + + + Issuer Common Name + + + + + Clone databases into + + + + + + Choose a directory + Vyberte složku + + + + + The language will change after you restart the application. + Jazyk bude zmÄ›nÄ›n po restartu aplikace. + + + + Select extension file + Vybrat soubor rozšíření + + + + Extensions(*.so *.dylib *.dll);;All files(*) + + + + + Import certificate file + Importovat soubor certifikátu + + + + No certificates found in this file. + V tomto souboru nebyly nalezeny žádné certifikáty. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + Opravdu chcete smazat tento certifikát? VÅ¡echny data certifikátu budou smazány z nastavení aplikace! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + + + + + Save Settings File + + + + + + Initialization File (*.ini) + + + + + The settings file has been saved in location : + + + + + + Open Settings File + + + + + The settings file was loaded properly. + + + + + The selected settings file is not a normal settings file. +Please check again. + + + + + ProxyDialog + + + Proxy Configuration + + + + + Pro&xy Type + + + + + Host Na&me + + + + + Port + + + + + Authentication Re&quired + + + + + &User Name + + + + + Password + + + + + None + Žádná + + + + System settings + + + + + HTTP + + + + + SOCKS5 + + + + + QObject + + + Error importing data + Chyba pÅ™i importu dat + + + + from record number %1 + ze záznamu Äíslo %1 + + + + . +%1 + . +%1 + + + + Importing CSV file... + + + + + Cancel + ZruÅ¡it + + + + All files (*) + VÅ¡echny soubory (*) + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + + + + + Left + + + + + Right + + + + + Center + + + + + Justify + + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + + + + + DB Browser for SQLite Project Files (*.sqbpro) + + + + + SQL Files (*.sql) + + + + + All Files (*) + + + + + Text Files (*.txt) + + + + + Comma-Separated Values Files (*.csv) + + + + + Tab-Separated Values Files (*.tsv) + + + + + Delimiter-Separated Values Files (*.dsv) + + + + + Concordance DAT files (*.dat) + + + + + JSON Files (*.json *.js) + + + + + XML Files (*.xml) + + + + + Binary Files (*.bin *.dat) + + + + + SVG Files (*.svg) + + + + + Hex Dump Files (*.dat *.bin) + + + + + Extensions (*.so *.dylib *.dll) + + + + + Initialization File (*.ini) + + + + + QsciCommand + + Paste + Vložit + + + Cancel + ZruÅ¡it + + + + QsciLexerCPP + + Default + Výchozí + + + Keyword + KlíÄové slovo + + + Identifier + Identifikátor + + + + QsciLexerJSON + + Default + Výchozí + + + String + String + + + + QsciLexerPython + + Default + Výchozí + + + Comment + Komentář + + + Keyword + KlíÄové slovo + + + Identifier + Identifikátor + + + + QsciLexerSQL + + Default + Výchozí + + + Comment + Komentář + + + Keyword + KlíÄové slovo + + + Identifier + Identifikátor + + + + QsciScintilla + + Select All + Vybrat vÅ¡e + + + + RemoteCommitsModel + + + Commit ID + + + + + Message + + + + + Date + Datum + + + + Author + + + + + Size + Velikost + + + + Authored and committed by %1 + + + + + Authored by %1, committed by %2 + + + + + RemoteDatabase + + + Error opening local databases list. +%1 + + + + + Error creating local databases list. +%1 + + + + + RemoteDock + + + Remote + Vzdálený + + + + Identity + + + + + Push currently opened database to server + + + + + Upload + + + + + DBHub.io + + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + + + + + Local + + + + + Current Database + + + + + Clone + + + + + &User + + + + + &Database + &Databáze + + + + Branch + VÄ›tev + + + + Commits + + + + + Commits for + + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + + + + + Back + + + + + Delete Database + + + + + Delete the local clone of this database + + + + + Open in Web Browser + + + + + Open the web page for the current database in your browser + + + + + Clone from Link + + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + + + + + Refresh + Obnovit + + + + Reload all data and update the views + + + + + Clone Database + + + + + Open Database + + + + + Open the local copy of this database + + + + + Check out Commit + + + + + Download and open this specific commit + + + + + Check out Latest Commit + + + + + Check out the latest commit of the current branch + + + + + Save Revision to File + + + + + Saves the selected revision of the database to another file + + + + + Upload Database + + + + + Upload this database as a new commit + + + + + Select an identity to connect + + + + + Public + VeÅ™ejný + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + + + + + Invalid URL: The host name does not match the host name of the current identity. + + + + + Invalid URL: No branch name specified. + + + + + Invalid URL: No commit ID specified. + + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + + + + + The database has unsaved changes. Are you sure you want to push it before saving? + + + + + The database you are trying to delete is currently opened. Please close it before deleting. + + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + + + + + RemoteLocalFilesModel + + + Name + Název + + + + Branch + VÄ›tev + + + + Last modified + Poslední zmÄ›nÄ›né + + + + Size + Velikost + + + + Commit + + + + + File + Soubor + + + + RemoteModel + + + Name + Název + + + + Last modified + Poslední zmÄ›nÄ›né + + + + Size + Velikost + + + + Commit + + + + + Size: + + + + + Last Modified: + + + + + Licence: + + + + + Default Branch: + + + + + RemoteNetwork + + + Choose a location to save the file + + + + + Error opening remote file at %1. +%2 + + + + + Error: Invalid client certificate specified. + + + + + Please enter the passphrase for this client certificate in order to authenticate. + + + + + Cancel + ZruÅ¡it + + + + Uploading remote database to +%1 + Nahrávám vzdálenou databázi do +%1. {1?} + + + + Downloading remote database from +%1 + Stahuji vzdálenou databázi z +%1. {1?} + + + + Error: Cannot open the file for sending. + Chyba: Nemohu otevřít soubor k odeslání. + + + + RemotePushDialog + + + Push database + + + + + Database na&me to push to + + + + + Commit message + + + + + Database licence + + + + + Public + VeÅ™ejný + + + + Branch + VÄ›tev + + + + Force push + + + + + Username + + + + + Database will be public. Everyone has read access to it. + + + + + Database will be private. Only you have access to it. + + + + + Use with care. This can cause remote commits to be deleted. + + + + + RunSql + + + Execution aborted by user + + + + + , %1 rows affected + , %1 řádků bylo ovlivnÄ›no + + + + query executed successfully. Took %1ms%2 + + + + + executing query + + + + + SelectItemsPopup + + + A&vailable + + + + + Sele&cted + + + + + SqlExecutionArea + + + Form + Formulář + + + + Find previous match [Shift+F3] + + + + + Find previous match with wrapping + + + + + Shift+F3 + + + + + The found pattern must be a whole word + + + + + Whole Words + Celá slova + + + + Text pattern to find considering the checks in this frame + + + + + Find in editor + Najít v editoru + + + + The found pattern must match in letter case + + + + + Case Sensitive + + + + + Find next match [Enter, F3] + + + + + Find next match with wrapping + + + + + F3 + + + + + Interpret search pattern as a regular expression + + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + + Regular Expression + Regulární výraz + + + + + Close Find Bar + Zavřít liÅ¡tu pro hledání + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + + + + + Results of the last executed statements + Výsledky naposledy provedených příkazů + + + + This field shows the results and status codes of the last executed statements. + + + + + Ctrl+PgUp + + + + + Ctrl+PgDown + + + + + Couldn't read file "%1": %2. + + + + + + Couldn't save file: %1. + + + + + Your changes will be lost when reloading it! + + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + + + + + Answer "No to All" to ignore any external update without further prompting. + + + + + Modifying and saving the file will restore prompting. + + + + + SqlTextEdit + + + Ctrl+/ + + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + + + + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) odstraní mezery z levé strany X. + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) Funkce s více parametry min() vrací parametr s minimální hodnotou. + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) Funkce nullif(X,Y) vrací první parametr, pokud jsou parametry odliÅ¡né. NULL vrací, pokud jsou parametry stejné. + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () Funkce random() vrací pseudo-náhodný integer v rozmezí -9223372036854775808 a +9223372036854775807. + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + + + + + (X) rtrim(X) removes spaces from the right side of X. + + + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + + + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + + + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + + + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + + + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + + + + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) odstraní mezery z obou stran X. + + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + + + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + + + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + + + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + + + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + + + + + + + + (timestring,modifier,modifier,...) + + + + + (format,timestring,modifier,modifier,...) + + + + + (X) The avg() function returns the average value of all non-NULL X within a group. + + + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + + + + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + + + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + + + + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) AgregaÄní funkce max() vrací maximální hodnotu ze vÅ¡ech hodnot ve skupinÄ›. + + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) AgregaÄní funkce min() vrací minimální hodnotu ze vÅ¡ech hodnot ve skupinÄ›, která není NULL. + + + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) AgregaÄní funkce sum() a total() vrací souÄet vÅ¡ech hodnot ve skupinÄ›, které nejsou NULL. + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + + + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + + + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + + + + + (X) Return the arccosine of X. The result is in radians. + + + + + (X) Return the hyperbolic arccosine of X. + + + + + (X) Return the arcsine of X. The result is in radians. + + + + + (X) Return the hyperbolic arcsine of X. + + + + + (X) Return the arctangent of X. The result is in radians. + + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + + + + + (X) Return the hyperbolic arctangent of X. + + + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + + + + + (X) Return the cosine of X. X is in radians. + + + + + (X) Return the hyperbolic cosine of X. + + + + + (X) Convert value X from radians into degrees. + + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + + + + + (X) Return the natural logarithm of X. + + + + + (B,X) Return the base-B logarithm of X. + + + + + + (X) Return the base-10 logarithm for X. + + + + + (X) Return the logarithm base-2 for the number X. + + + + + (X,Y) Return the remainder after dividing X by Y. + + + + + () Return an approximation for Ï€. + + + + + + (X,Y) Compute X raised to the power Y. + + + + + (X) Convert X from degrees into radians. + + + + + (X) Return the sine of X. X is in radians. + + + + + (X) Return the hyperbolic sine of X. + + + + + (X) Return the square root of X. NULL is returned if X is negative. + + + + + (X) Return the tangent of X. X is in radians. + + + + + (X) Return the hyperbolic tangent of X. + + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + + + + + SqliteTableModel + + + reading rows + Ätení sloupců + + + + loading... + naÄítání... + + + + References %1(%2) +Hold %3Shift and click to jump there + + + + + Error changing data: +%1 + Chyba pÅ™i zmÄ›nÄ› dat: +%1 + + + + retrieving list of columns + + + + + Fetching data... + NaÄítám data... + + + + + Cancel + ZruÅ¡it + + + + TableBrowser + + + Browse Data + Prohlížet data + + + + &Table: + &Tabulka: + + + + Select a table to browse data + Vyberte tabulku pro prohlížení dat + + + + Use this list to select a table to be displayed in the database view + Pro zobrazení v databázovém pohledu použijte pro výbÄ›r tabulky tento seznam + + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + + + + + Text pattern to find considering the checks in this frame + + + + + Find in table + + + + + Find previous match [Shift+F3] + + + + + Find previous match with wrapping + + + + + Shift+F3 + + + + + Find next match [Enter, F3] + + + + + Find next match with wrapping + + + + + F3 + + + + + The found pattern must match in letter case + + + + + Case Sensitive + + + + + The found pattern must be a whole word + + + + + Whole Cell + + + + + Interpret search pattern as a regular expression + + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + + Regular Expression + Regulární výraz + + + + + Close Find Bar + Zavřít liÅ¡tu pro hledání + + + + Text to replace with + + + + + Replace with + + + + + Replace next match + + + + + + Replace + + + + + Replace all matches + + + + + Replace all + + + + + Export to &JSON + + + + + + Export the filtered data to JSON + + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + + + + + Copy column name + + + + + Copy the database table column name to your clipboard + + + + + New Data Browser + + + + + + Add a new docked Data Browser + + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>Posune na úplný zaÄátek</p></body></html> + + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>Kliknutím na toto tlaÄítko se pÅ™esunete na zaÄátek pohledu tabulky výše.</p></body></html> + + + + |< + |< + + + + Scroll one page upwards + + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + + + + + < + < + + + + 0 - 0 of 0 + 0 - 0 z 0 + + + + Scroll one page downwards + + + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + + + + + > + > + + + + Scroll to the end + Posunout na konec + + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + + + + + >| + >| + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>Kliknutím zde pÅ™eskoÄíte na urÄený záznam</p></body></html> + + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>Toto tlaÄítko je urÄeno k navigaci k záznamu, jehož Äíslo je nastaveno v poli Jít na.</p></body></html> + + + + Go to: + Jít na: + + + + Enter record number to browse + Vložte Äíslo záznamu pro jeho procházení + + + + Type a record number in this area and click the Go to: button to display the record in the database view + NapiÅ¡tÄ› Äíslo záznamu do tohoto pole a kliknÄ›te na Jít na: tlaÄítko k zobrazení záznamu v pohledu databáze + + + + 1 + 1 + + + + Show rowid column + Zobrazit rowid sloupce + + + + Toggle the visibility of the rowid column + PÅ™epnout viditelnost rowid sloupců + + + + Unlock view editing + + + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + + + + + Edit display format + Upravit formát zobrazení + + + + Edit the display format of the data in this column + Upravit formát zobrazení dat v tomto sloupci + + + + + New Record + Nový záznam + + + + + Insert a new record in the current table + Vložit nový záznam do souÄasné tabulky + + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + + + + + + Delete Record + Smazat záznam + + + + Delete the current record + Smazat aktuální záznam + + + + + This button deletes the record or records currently selected in the table + + + + + + Insert new record using default values in browsed table + + + + + Insert Values... + Vložit hodnoty... + + + + + Open a dialog for inserting values in a new record + + + + + Export to &CSV + Export do CSV + + + + + Export the filtered data to CSV + + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + + + + + Save as &view + Uložit jako pohled + + + + + Save the current filter, sort column and display formats as a view + + + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + + + + + Save Table As... + + + + + + Save the table as currently displayed + + + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + + + + + Hide column(s) + Skrýt sloupec(ce) + + + + Hide selected column(s) + Skrýt vybraný sloupec(ce) + + + + Show all columns + Zobrazit vÅ¡echny sloupce + + + + Show all columns that were hidden + + + + + + Set encoding + Nastavit kódování + + + + Change the encoding of the text in the table cells + ZmÄ›nit kódování textu v buňkách tabulky + + + + Set encoding for all tables + Nastavit kódování pro vÅ¡echny tabulky + + + + Change the default encoding assumed for all tables in the database + + + + + Clear Filters + + + + + Clear all filters + Vymazat vÅ¡echny filtry + + + + + This button clears all the filters set in the header input fields for the currently browsed table. + + + + + Clear Sorting + + + + + Reset the order of rows to the default + + + + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + + + + + Print + Tisk + + + + Print currently browsed table data + Tisk právÄ› prohlížených dat tabulky + + + + Print currently browsed table data. Print selection if more than one cell is selected. + + + + + Ctrl+P + + + + + Refresh + Obnovit + + + + Refresh the data in the selected table + + + + + This button refreshes the data in the currently selected table. + Toto tlaÄítko obnoví data v aktuálnÄ› vybrané tabulce. + + + + F5 + + + + + Find in cells + + + + + Open the find tool bar which allows you to search for values in the table view below. + + + + + Freeze columns + + + + + Make all columns from the first column up to this column not move when scrolling horizontally + + + + + + Bold + TuÄný + + + + Ctrl+B + + + + + + Italic + Kurzíva + + + + + Underline + Podtržený + + + + Ctrl+U + + + + + + Align Right + + + + + + Align Left + + + + + + Center Horizontally + + + + + + Justify + + + + + + Edit Conditional Formats... + + + + + Edit conditional formats for the current column + + + + + Clear Format + + + + + Clear All Formats + + + + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + + + + + + Font Color + + + + + + Background Color + + + + + Toggle Format Toolbar + + + + + Show/hide format toolbar + + + + + + This button shows or hides the formatting toolbar of the Data Browser + + + + + Select column + + + + + Ctrl+Space + + + + + Replace text in cells + + + + + Filter in any column + + + + + Ctrl+R + + + + + %n row(s) + + + + + + + + + , %n column(s) + + + + + + + + + . Sum: %1; Average: %2; Min: %3; Max: %4 + + + + + Conditional formats for "%1" + + + + + determining row count... + + + + + %L1 - %L2 of >= %L3 + + + + + %L1 - %L2 of %L3 + + + + + (clipped at %L1 rows) + + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + + + + + Delete Records + + + + + Duplicate records + + + + + Duplicate record + + + + + Ctrl+" + + + + + Adjust rows to contents + + + + + Error deleting record: +%1 + Chyba pÅ™i mazání záznamu: +%1 + + + + Please select a record first + Prosím vyberte záznam jako první + + + + Please choose a new encoding for all tables. + Vyberte nové kódování pro vÅ¡echny tabulky, prosím. + + + + Please choose a new encoding for this table. + Vyberte nové kódování pro tuto tabulku, prosím. + + + + %1 +Leave the field empty for using the database encoding. + %1 +Pro použití kódování databáze ponechte pole prázdné. + + + + This encoding is either not valid or not supported. + Toto kódování není buÄ platné, nebo podporováno. + + + + %1 replacement(s) made. + + + + + TableBrowserDock + + + New Data Browser + + + + + Rename Data Browser + + + + + Close Data Browser + + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + + + + + VacuumDialog + + + Compact Database + Compact Database + + + + Warning: Compacting the database will commit all of your changes. + Varování: Procesem 'compact the database' budou aplikovány vÅ¡echny vaÅ¡e provedené zmÄ›ny. + + + + Please select the databases to co&mpact: + Prosím vyberte databázi pro proces 'compact': + + + diff --git a/src/translations/sqlb_de.ts b/src/translations/sqlb_de.ts index 9bf92ae11..564ea9d87 100644 --- a/src/translations/sqlb_de.ts +++ b/src/translations/sqlb_de.ts @@ -1,2039 +1,8073 @@ - + AboutDialog About DB Browser for SQLite - Über DB-Browser für SQLite + Über DB-Browser für SQLite - + Version - Version + Version - - Qt Version - Qt-Version + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + <html><head/><body><p>DB-Browser für SQLite ist eine freie Open-Source-Anwendung mit GUI zum Erstellen, Entwerfen und Bearbeiten von SQLite-Datenbanken.</p><p>Die Anwendung ist sowohl unter der Mozilla Public License Version 2 als auch der GNU General Public License Version 3 or later verfügbar. Modifikationen oder Weitergabe sind unter Beachtung der Bedingungen dieser Lizenzen möglich.</p><p>Siehe <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> und <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> für Details.</p><p>Weitere Informationen über diese Anwendung gibt es auf unserer Webseite: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">Diese Software verwendet das Qt-Toolkit unter der GPL/LGPL Qt Toolkit, welches unter </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a> verfügbar ist. <span style=" font-size:small;"><br/>Zugehörige Lizenzbedingungen und Informationen gibt es unter </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"></span></p><p><span style=" font-size:8pt;">Wir verwenden die nalgeon/sqlean-Bibliothek für die Unterstützung von SQLite-Erweiterungen.<br/>Diese Bibliothek ist unter der MIT license verfügbar; mehr Informationen gibt es unter:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">Zudem wird das Pastel SVG Iconset von Michael Buckley verwendet, das unter der Creative Commons Attribution Share Alike 4.0 Lizenz steht.<br/>Siehe </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> für weitere Details.</span></p></body></html> + + + + AddRecordDialog + + + Add New Record + Neue Zeile hinzufügen + + + + Enter values for the new record considering constraints. Fields in bold are mandatory. + Geben Sie Werte für die neue Zeile unter Beachtung der Beschränkungen ein. Fette Felder sind Pflichtfelder. + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + In der Wertspalte können Sie den Wert für das durch die Namensspalte identifizierte Feld angeben. Die Typspalte zeigt den Feldtyp an. Standardwerte werden im Stil von NULL-Werten angezeigt. + + + + Name + Name + + + + Type + Typ + + + + Value + Wert + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + Einzufügende Werte. Vorausgefüllte Standardwerte werden automatisch eingefügt, sofern sie nicht geändert wurden. + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + Wenn Sie die Werte im oberen Teil ändern, wird hier die SQL-Abfrage für das Einfügen der neuen Zeile angezeigt. Sie können die Abfrage vor dem Speichern manuell bearbeiten. + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Speichern</span> wird die dargestellte SQL-Anweisung zum Einfügen des neuen Eintrags an die Datenbank übermitteln.</p><p><span style=" font-weight:600;">Voreinstellungen</span> wird die ursprünglichen Werte der Spalte <span style=" font-weight:600;">Wert</span> wiederherstellen.</p><p><span style=" font-weight:600;">Abbrechen</span> schließt diesen Dialog, ohne die Abfrage auszuführen.</p></body></html> + + + + Auto-increment + + Auto-Inkrement + + + + + Unique constraint + + Unique-Beschränkungen + + + + + Check constraint: %1 + + Prüfungsbeschränkung: %1 + + + + + Foreign key: %1 + + Fremdschlüssel: %1 + + + + + Default value: %1 + + Standardwert: %1 + + + + + Error adding record. Message from database engine: + +%1 + Fehler beim Hinzufügen der Zeile. Mitteilung der Datenbank-Engine: + +%1 + + + + Are you sure you want to restore all the entered values to their defaults? + Sind Sie sicher, dass Sie alle eingegebenen Werte auf ihre Standardwerte zurücksetzen möchten? + + + + Application + + + Possible command line arguments: + Mögliche Kommandozeilen-Argumente: + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + Die Optionen -o/--option und -O/--save-option benötigen ein Argument der Form Gruppe/Einstellung=Wert + + + + The user settings file location is replaced with the argument value instead of the environment variable value. + Der Dateipfad der Benutzereinstellungen wird mit dem übergebenen Argument statt der Umgebungsvariable ersetzt. + + + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + Wert der Umgebungsvariable (DB4S_SETTINGS_FILE) ignoriert: + + + + + The file %1 does not exist + Die Datei %1 existiert nicht + + + + Usage + Verwendung + + + + options + Optionen + + + + + database + Datenbank + + + + + project + Projekt + + + + + csv-file + CSV-Datei + + + + Show command line options + Terminaloptionen anzeigen + + + + Exit application after running scripts + Anwendung nach der Ausführung der Skripte beenden + + + + + file + Datei + + + + Execute this SQL file after opening the DB + Nach dem Öffnen der Datenbank diese SQL-Datei ausführen + + + + Import this CSV file into the passed DB or into a new DB + Diese CSV-Datei in die übergebene oder in eine neue Datenbank importieren + + + + table + Tabelle + + + + Browse this table, or use it as target of a data import + Diese Tabelle durchsuchen oder als Ziel für einen Datenimport verwenden + + + + Open database in read-only mode + Datenbank nur für den Lesezugriff öffnen + + + + settings_file + datei_mit_einstellungen + + + + Run application based on this settings file + Anwendung mit dieser Einstellungsdatei ausführen + + + + + group + Gruppe + + + + + settings + Einstellungen + + + + + value + Wert + + + + Run application with this setting temporarily set to value + Anwendung mit dem temporär angepassten Einstellungswert ausführen + + + + Run application saving this value for this setting + Anwendung mit dem angepassten Einstellungswert ausführen und die Einstellung dauerhaft speichern + + + + Display the current version + Die aktuelle Version anzeigen + + + + Open this SQLite database + Diese SQLite-Datenbank öffnen + + + + Open this project file (*.sqbpro) + Diese Projektdatei öffnen (*.sqbpro) + + + + Import this CSV file into an in-memory database + Diese CSV-Datei in eine In-Memory-Datenbank importieren + + + + + + The %1 option requires an argument + Die Option %1 benötigt ein Argument + + + + The -S/--settings option requires an argument. The option is ignored. + Die Option -S/--settings benötigt ein Argument. Diese Option wird ignoriert. + + + + SQLite Version + SQLite-Version + + + + SQLCipher Version %1 (based on SQLite %2) + SQLCipher Version %1 (basierend auf SQLite %2) + + + + DB Browser for SQLite Version %1. + DB-Browser für SQLite Version %1. + + + + Last commit hash when built: %1 + Letzter Commit-Hash des Builds: %1 + + + + Built for %1, running on %2 + Erstellt für %1, laufend unter %2 + + + + Qt Version %1 + Qt Version %1 + + + + Invalid option/non-existent file: %1 + Ungültige Option/nicht vorhandene Datei: %1 + + + + CipherDialog + + + SQLCipher encryption + SQLCipher-Verschlüsselung + + + + &Password + &Passwort + + + + &Reenter password + Passwort wiede&rholen + + + + Encr&yption settings + &Verschlüsselungs-Einstellungen + + + + SQLCipher &3 defaults + SQLCipher &3-Standardwerte + + + + SQLCipher &4 defaults + SQLCipher &4-Standardwerte + + + + Custo&m + &Benutzerdefiniert + + + + Page si&ze + Seiten&größe + + + + &KDF iterations + &KDF-Iterationen + + + + HMAC algorithm + HMAC-Algorithmus + + + + KDF algorithm + KDF-Algorithmus + + + + Plaintext Header Size + Reintext-Headergröße + + + + Passphrase + Passphrase + + + + Raw key + Originalschlüssel + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + Setzen Sie bitte einen Schlüssel zum Verschlüsseln der Datenbank. +Beachten Sie, dass bei Änderung der optionalen Einstellungen diese bei jedem Öffnen der Datenbankdatei eingegeben werden müssen. +Lassen Sie die Passwortfelder leer, um die Verschlüsselung zu deaktivieren. +Der Verschlüsselungsprozess benötigt unter Umständen ein bisschen Zeit und Sie sollten ein Backup-Kopie Ihrer Datenbank haben! Ungespeicherte Änderungen werden vor der Änderung der Verschlüsselung übernommen. + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + Geben Sie bitte den zur Verschlüsselung der Datenbank genutzten Schlüssel ein. +Wenn weitere Einstellungen für diese Datenbankdatei vorgenommen worden sind, müssen Sie diese Informationen zusätzlich angeben. + + + + ColumnDisplayFormatDialog + + + Choose display format + Anzeigeformat auswählen + + + + Display format + Anzeigeformat + + + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + Wählen Sie ein Anzeigeformat für die Spalte '%1', das bei der Anzeige eines jeden Wertes angewendet wird. + + + + Default + Voreinstellung + + + + Decimal number + Dezimalzahl + + + + Exponent notation + Exponentennotation + + + + Hex blob + Hex-Blob + + + + Hex number + Hexwert + + + + Apple NSDate to date + Apple NSDate zu Datum + + + + Java epoch (milliseconds) to date + Java-Epoche (Millisekunden) zu Datum + + + + .NET DateTime.Ticks to date + .NET DateTime.Ticks zu Datum + + + + Julian day to date + Julianischer Tag zu Datum + + + + Unix epoch to local time + Unix-Epoche zu lokaler Zeit + + + + WebKit / Chromium epoch to date + WebKit-/Chromium-Epoche zu Datum + + + + WebKit / Chromium epoch to local time + WebKit-/Chromium-Epoche zu lokaler Zeit + + + + Date as dd/mm/yyyy + Datum als dd/mm/yyyy + + + + Lower case + Kleinschreibung + + + + Binary GUID to text + Binäre GUID zu Text + + + + SpatiaLite Geometry to SVG + SpatiaLite-Geometrie zu SVG + + + + Custom display format must contain a function call applied to %1 + Benutzerdefinierte Darstellungsformate benötigen einen Funktionsaufruf, der auf %1 angewendet wird + + + + Error in custom display format. Message from database engine: + +%1 + Fehler im benutzerdefinierten Anzeigeformat. Meldung von Datenbank: + +%1 + + + + Custom display format must return only one column but it returned %1. + Das benutzerdefinierte Anzeigeformat darf nur eine Spalte zurückgeben, es wurde aber %1 zurückgegeben. + + + + Octal number + Oktalwert + + + + Round number + Gerundeter Wert + + + + Unix epoch to date + Unix-Epoche zu Datum + + + + Upper case + Großschreibung + + + + Windows DATE to date + Windows DATUM zu Datum + + + + Custom + Benutzerdefiniert + + + + CondFormatManager + + + Conditional Format Manager + Verwaltung für bedingte Formatierung + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + Dieser Dialog erlaubt das Erstellen und Bearbeiten bedingter Formatierungen. Jeder Zellenstil wird anhand der ersten erfüllten Bedingung für diese Zelldaten ausgewählt. Bedingte Formatierungen können nach oben und unten bewegt werden, wobei jene weiter oben Vorrang vor jenen weiter unten haben. Die Syntax für Bedingungen ist die gleiche wie bei Filtern und eine leere Bedingung trifft auf alle Werte zu. + + + + Add new conditional format + Neue bedingte Formatierung hinzufügen + + + + &Add + &Hinzufügen + + + + Remove selected conditional format + Ausgewählte bedingte Formatierung entfernen + + + + &Remove + &Entfernen + + + + Move selected conditional format up + Ausgewählte bedingte Formatierung nach oben bewegen + + + + Move &up + Nach &oben + + + + Move selected conditional format down + Ausgewählte bedingte Formatierung nach unten bewegen + + + + Move &down + Nach &unten + + + + Foreground + Vordergrund + + + + Text color + Textfarbe + + + + Background + Hintergrund + + + + Background color + Hintergrundfarbe + + + + Font + Schrift + + + + Size + Größe + + + + Bold + Fett + + + + Italic + Kursiv + + + + Underline + Unterstreichung + + + + Alignment + Ausrichtung + + + + Condition + Bedingung + + + + + Click to select color + Zur Auswahl der Farbe klicken + + + + Are you sure you want to clear all the conditional formats of this field? + Sollen wirklich alle bedingten Formatierungen dieses Felds gelöscht werden? + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + Geben Sie bitte einen Datenbanknamen an, mit dem Sie auf die anhängte Datenbank zugreifen möchten + + + + Invalid file format + Ungültiges Dateiformat + + + + Do you want to save the changes made to the database file %1? + Sollen die getätigten Änderungen an der Datenbankdatei %1 gespeichert werden? + + + + Exporting database to SQL file... + Datenbank in SQL-Datei exportieren... + + + + + Cancel + Abbrechen + + + + Executing SQL... + SQL ausführen... + + + + Action cancelled. + Vorgang abgebrochen. + + + + Do you really want to close this temporary database? All data will be lost. + Möchten Sie diese temporäre Datenbank wirklich schließen? Alle Daten gehen damit verloren. + + + + Database didn't close correctly, probably still busy + Datenbank wurde nicht richtig geschlossen, vermutlich noch in Bearbeitung + + + + Cannot open destination file: '%1' + Zieldatei kann nicht geöffnet werden: '%1' + + + + + Cannot backup to file: '%1'. Message: %2 + Erstellung des Backups in Datei '%1' nicht möglich. Mitteilung: %2 + + + + The database is currently busy: + Die Datenbank ist zur Zeit beschäftigt: + + + + Do you want to abort that other operation? + Möchten Sie die andere Operation abbrechen? + + + + + No database file opened + Keine Datenbankdatei geöffnet + + + + + Error in statement #%1: %2. +Aborting execution%3. + Fehler in der Anweisung #%1: %2. +Ausführung wird abgebrochen %3. + + + + + and rolling back + und der Zustand zurückgesetzt + + + + didn't receive any output from %1 + keine Ausgabe von %1 erhalten + + + + could not execute command: %1 + Befehl konnte nicht ausgeführt werden: %1 + + + + Cannot delete this object + Dieses Objekt kann nicht gelöscht werden + + + + Cannot set data on this object + Daten können für dieses Objekt nicht gesetzt werden + + + + + A table with the name '%1' already exists in schema '%2'. + Es existiert eine Tabelle mit dem Namen '%1' im Schema '%2'. + + + + No table with name '%1' exists in schema '%2'. + Im Schema '%2' existiert keine Tabelle mit dem Namen '%1'. + + + + + Cannot find column %1. + Spalte %1 kann nicht gefunden werden. + + + + Creating savepoint failed. DB says: %1 + Erstellung des Sicherungspunktes fehlgeschlagen. DB meldet: %1 + + + + Renaming the column failed. DB says: +%1 + Umbenennung der Spalte fehlgeschlagen. DB meldet: +%1 + + + + + Releasing savepoint failed. DB says: %1 + Entsperren des Sicherungspunktes fehlgeschlagen. DB meldet: %1 + + + + Creating new table failed. DB says: %1 + Erstellen der neuen Tabelle ist fehlgeschlagen. DB meldet: %1 + + + + Copying data to new table failed. DB says: +%1 + Kopieren der Daten zur neuen Tabelle ist fehlgeschlagen. DB meldet: +%1 + + + + Deleting old table failed. DB says: %1 + Löschen der alten Tabelle ist fehlgeschlagen. DB meldet: %1 + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + Fehler beim Umbenennen der Tabelle '%1' zu '%2'. +Meldung von Datenbank: +%3 + + + + could not get list of db objects: %1 + Liste der DB-Objekte konnte nicht abgefragt werden: %1 + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + Wiederherstellung einiger mit dieser Tabelle verbundener Objekte fehlgeschlagen. Dies passiert häufig durch geänderte Spaltennamen. SQL-Anweisung zum manuellen Reparieren und Ausführen: + + + + + + could not get list of databases: %1 + konnte keine Datenbankliste abrufen: %1 + + + + Error loading extension: %1 + Fehler beim Laden der Erweiterung: %1 + + + + Error loading built-in extension: %1 + Fehler beim Laden der eingebauten Erweiterung: %1 + + + + could not get column information + Spalteninformationen konnten nicht ermittelt werden + + + + Error setting pragma %1 to %2: %3 + Fehler beim Setzen des Pragmas %1 auf %2: %3 + + + + File not found. + Datei nicht gefunden. + + + + DbStructureModel + + + Name + Name + + + + Object + Objekt + + + + Type + Typ + + + + Schema + Schema + + + + Database + Datenbank + + + + Browsables + Durchsuchbar + + + + All + Alle + + + + Temporary + Temporär + + + + Tables (%1) + Tabellen (%1) + + + + Indices (%1) + Indizes (%1) + + + + Views (%1) + Ansichten (%1) + + + + Triggers (%1) + Trigger (%1) + + + + EditDialog + + + Edit database cell + Datenbankzelle bearbeiten + + + + Mode: + Modus: + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + Dies ist die Liste der unterstützten Modi des Zelleneditors. Wählen Sie einen Modus für die Anzeige oder Bearbeitung der Daten der aktuellen Zelle aus. + + + + RTL Text + RTL-Text + + + + + Image + Bild + + + + JSON + JSON + + + + XML + XML + + + + Evaluation + Auswertung + + + + + Automatically adjust the editor mode to the loaded data type + Den Editormodus automatisch dem geladenen Datentyp anpassen + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + Dieser Button aktiviert oder deaktiviert den automatischen Wechsel des Editormodus. Wenn eine neue Zelle ausgewählt wird oder neue Daten importiert werden und der automatische Wechsel aktiviert ist, passt sich der Modus dem erkannten Datentyp an. Sie können den Editormodus danach manuell ändern. Wenn Sie dies bei der Bewegung durch die Zellen im manuell eingestellten Modus behalten möchten, deaktivieren Sie den Button. + + + + Auto-switch + Auto-Wechsel + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + Dieser Qt-Editor wird für Rechts-nach-Links-Skripte verwendet, die vom Standard-Texteditor nicht unterstützt werden. Das Vorhandensein von Rechts-nach-Links-Zeichen wird erkannt und dieser Editormodus wird automatisch ausgewählt. + + + + Identification of the cell currently in the editor + Zuordnung der aktuell im Editor angezeigten Zelle + + + + Type and size of data currently in table + Typ und Größe der aktuellen Tabellendaten + + + + Open preview dialog for printing the data currently stored in the cell + Vorschau-Dialog öffnen, um die aktuell in der Zelle gespeicherten Daten auszugeben + + + + Auto-format: pretty print on loading, compact on saving. + Auto-Format: Druckoptimierung (Pretty Print) beim Laden, kompakt beim Speichern. + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + Wenn aktiviert, formatiert die Auto-Format-Funktion die Daten beim Laden, bricht den Text in Zeilen und rückt ihn für maximale Lesbarkeit ein. Beim Speichern der Daten verdichtet die Auto-Format-Funktion die Daten durch das Entfernen der Zeilenumbrüche und unnötigen Leerzeichen. + + + + Word Wrap + Wortumbrüche + + + + Wrap lines on word boundaries + Zeilen an Wortgrenzen umbrechen + + + + + Open in default application or browser + Mit der Standardanwendung oder dem Browser öffnen + + + + Open in application + Mit Anwendung öffnen + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + Der Wert wird als Datei oder URL interpretiert und mit der Standardanwendung oder dem Webbrowser geöffnet. + + + + Save file reference... + Dateireferenz speichern... + + + + Save reference to file + Referenz in Datei speichern + + + + + Open in external application + Mit externer Anwendung öffnen + + + + Autoformat + Auto-Format + + + + &Export... + &Exportieren... + + + + + &Import... + &Importieren... + + + + + Import from file + Aus Datei importieren + + + + + Opens a file dialog used to import any kind of data to this database cell. + Öffnet einen Dateidialog, um beliebige Daten in diese Datenbankzelle zu importieren. + + + + Export to file + In Datei exportieren + + + + Opens a file dialog used to export the contents of this database cell to a file. + Öffnet einen Dateidialog, um den Inhalt dieser Datenbankzelle in eine Datei zu exportieren. + + + + Print... + Drucken... + + + + Ctrl+P + + + + + Open preview dialog for printing displayed text + Vorschaudialog zum Drucken des angezeigten Textes öffnen + + + + Copy Hex and ASCII + Hex und ASCII kopieren + + + + Copy selected hexadecimal and ASCII columns to the clipboard + Ausgewählte hexadezimale und ASCII-Spalten in die Zwischenablage kopieren + + + + Ctrl+Shift+C + + + + + Set as &NULL + Auf &NULL setzen + + + + Apply data to cell + Daten auf Zelle anwenden + + + + This button saves the changes performed in the cell editor to the database cell. + Dieser Button speichert die im Zelleneditor für die Datenbankzelle durchgeführten Änderungen. + + + + Apply + Übernehmen + + + + Text + Text + + + + Binary + Binär + + + + Erases the contents of the cell + Löscht den Inhalt der Zelle + + + + This area displays information about the data present in this database cell + Dieser Bereich stellt Informationen über die Daten in dieser Datenbankzelle dar + + + + Choose a filename to export data + Dateinamen für den Datenexport wählen + + + + + Image data can't be viewed in this mode. + In diesem Modus können keine Bilddaten angezeigt werden. + + + + + Try switching to Image or Binary mode. + Versuchen Sie, in den Bild- oder Binärmodus zu wechseln. + + + + + Binary data can't be viewed in this mode. + Binärdaten können in diesem Modus nicht angezeigt werden. + + + + + Try switching to Binary mode. + Versuchen Sie, in den Binärmodus zu wechseln. + + + + + Type: NULL; Size: 0 bytes + Typ: NULL; Größe: 0 Bytes + + + + + Type: Text / Numeric; Size: %n character(s) + + Typ: Text / Numerisch; Größe: %n Zeichen + Typ: Text / Numerisch; Größe: %n Zeichen + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + Typ: %1-Bild; Größe: %2x%3 Pixel + + + + Type: Valid JSON; Size: %n character(s) + + Typ: Gültiges JSON; Größe: %n Zeichen + Typ: Gültiges JSON; Größe: %n Zeichen + + + + + Type: Binary; Size: %n byte(s) + + Typ: Binär; Größe: %n Byte + Typ: Binär: Größe: %n Bytes + + + + + Couldn't save file: %1. + Datei konnte nicht gespeichert werden: %1. + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + Die Daten wurden in einer temporären Datei gespeichert und mit der Standardanwendung geöffnet. Diese kann nun bearbeitet werden und am Ende entweder durch Speichern in die Zelle übernommen oder der Vorgang abgebrochen werden. + + + + + Image files (%1) + Bilddateien (%1) + + + + Binary files (*.bin) + Binärdateien (*.bin) + + + + Choose a file to import + Datei für Import auswählen + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + Die Texteditor-Modi erlauben das Bearbeiten von Reintext sowie JSON- und XML-Daten mit Syntaxhervorhebung, automatischer Formatierung und Validierung vor dem Speichern. + +Fehler werden mittels einer roten Wellenlinie markiert. + +Im Auswertungsmodus werden eingegebene SQLite-Ausdrücke ausgewertet und das Ergebnis auf die Zelle angewendet. + + + + Unsaved data in the cell editor + Ungespeicherte Änderungen im Zelleneditor + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + Der Zelleneditor enthält Daten, die noch nicht auf die Datenbank angewendet wurden. +Sollen die bearbeiteten Daten auf Zeile=%1, Spalte=%2 angewendet werden? + + + + Editing row=%1, column=%2 + Bearbeite Zeile=%1, Spalte=%2 + + + + No cell active. + Keine Zelle aktiv. + + + + %1 Image + %1 Bild + + + + Invalid data for this mode + Ungültige Daten für diesen Modus + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + Die Zelle enthält ungültige %1-Daten. Grund: %2. Möchten Sie diese wirklich auf die Zelle anwenden? + + + + EditIndexDialog + + + &Name + &Name + + + + Order + Sortierung + + + + &Table + &Tabelle + + + + Edit Index Schema + Index-Schema bearbeiten + + + + &Unique + Einde&utig + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + Zum Einschränken des Index auf einen Teil der Tabelle kann hier eine WHERE-Klausel angegeben werden, die den Teil der Tabelle auswählt, der indexiert werden soll + + + + Partial inde&x clause + Teilinde&x-Klausel + + + + Colu&mns + &Spalten + + + + Table column + Tabellenspalte + + + + Type + Typ + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + Fügt eine neue Ausdrucksspalte zum Index hinzu. Ausdrucksspalten enthalten SQL-Ausdrücke statt Spaltennamen. + + + + Index column + Indexspalte + + + + Deleting the old index failed: +%1 + Löschen des alten Index fehlgeschlagen: %1 + + + + Creating the index failed: +%1 + Erstellen des Index fehlgeschlagen: +%1 + + + + EditTableDialog + + + Edit table definition + Tabellen-Definition bearbeiten + + + + Table + Tabelle + + + + Advanced + Erweitert + + + + Without Rowid + Ohne Rowid + + + + Fields + Felder + + + + Database sche&ma + Datenbanksche&ma + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + Diese Tabelle zu "WITHOUT ROWID" umwandeln. Das Setzen dieses Flags erfordert die Angabe eines Primärschlüssels (welcher jeglichen Typ haben und auch zusammengesetzt sein darf), schließt aber das AUTOINCREMENT-Flag aus. + + + + On Conflict + ON CONFLICT + + + + Strict + Strikt + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + Wenn die Strikt-Option aktiviert ist, erzwingt SQLite den jeweiligen Datentyp der Spalte beim Aktualisieren oder Einfügen von Daten. + + + + + + Add + Hinzufügen + + + + + + Remove + Entfernen + + + + Move to top + Zum Beginn + + + + Move up + Nach oben + + + + Move down + Nach unten + + + + Move to bottom + Zum Ende + + + + + + + Name + Name + + + + + Type + Typ + + + + NN + NN + + + + Not null + Nicht Null + + + + PK + PK + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> Primärschlüssel</p></body></html> + + + + AI + AI + + + + Autoincrement + Autoinkrement + + + + U + + + + + + + Unique + Eindeutig + + + + Default + Voreinstellung + + + + Default value + Voreingestellter Wert + + + + + Check + Prüfen + + + + Check constraint + Beschränkung prüfen + + + + Collation + Kollation + + + + Foreign Key + Fremdschlüssel + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_fk"/> Fremdschlüssel</p></body></html> + + + + Index Constraints + Index-Beschränkungen + + + + Add constraint + Beschränkung hinzufügen + + + + Remove constraint + Beschränkung entfernen + + + + + Columns + Spalten + + + + + + SQL + SQL + + + + Foreign Keys + Fremdschlüssel + + + + References + Referenzen + + + + Check Constraints + CHECK-Beschränkungen + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html><head/><body><p><span style="font-weight:600; color:#ff0000;">Warnung: </span>Diese Tabellendefinition enthält Elemente, die unser Parser nicht vollständig versteht. Das Ändern und Speichern der Tabelle kann zu Problemen führen.</p></body></html> + + + + + Primary Key + Primärschlüssel + + + + Add a primary key constraint + Eine Beschränkung für den Primärschlüssel hinzufügen + + + + Add a unique constraint + Eine Unique-Beschränkung hinzufügen + + + + Error creating table. Message from database engine: +%1 + Fehler beim Erstellen der Tabelle. Meldung der Datenbank: +%1 + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + Es existiert bereits ein Feld mit diesem Namen. Bitte benennen Sie es zunächst um oder wählen Sie einen anderen Namen für dieses Feld. + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + Es kann nur einen Primärschlüssel für jede Tabelle geben. Bitte stattdessen den existierenden Primärschlüssel bearbeiten. + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + Diese Spalte wird in einem Fremdschlüssel in Tabelle %1 referenziert und kann aus diesem Grund nicht geändert werden. + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + Mindestens eine Reihe enthält ein Feld mit dem Wert NULL. Dies verhindert das Setzen dieser Markierung. Bitte zunächst die Tabellendaten ändern. + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + Mindestens eine Reihe enthält ein Feld mit einem nicht ganzzahligen Wert. Dies verhindert das Setzen der AI-Markierung. Bitte zunächst die Tabellendaten ändern. + + + + Column '%1' has duplicate data. + + Spalte '%1' hat doppelte Daten. + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + Dies macht das Aktivieren des Flags 'Unique' unmöglich. Bitte die doppelten Daten entfernen, damit das Flag 'Unique' dann aktiviert werden kann. + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + Soll das Feld '%1' wirklich gelöscht werden? +Alle aktuell in diesem Feld gespeicherten Daten gehen verloren. + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + Bitte fügen Sie vor dem Setzen des Flags "Without rowid" ein Feld hinzu, das folgenden Kriterien entspricht: + - Primärschlüssel-Flag gesetzt + - Autoinkrement deaktiviert + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + Bitte vor dem Setzen der Konfliktaktion ein Feld hinzufügen, das den folgenden Bedingungen genügt: + - Primärschlüssel ist aktiviert + + + + ExportDataDialog + + + Export data as CSV + Daten als CSV exportieren + + + + Tab&le(s) + Tabe&lle(n) + + + + Colu&mn names in first line + &Spaltennamen in der ersten Zeile + + + + Fie&ld separator + Fe&ld-Separator + + + + , + , + + + + ; + ; + + + + Tab + Tab + + + + | + | + + + + + + Other + Anderer + + + + &Quote character + &String-Zeichen + + + + " + " + + + + ' + ' + + + + New line characters + Zeilenumbruchs-Zeichen + + + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) + + + + Unix: LF (\n) + Unix: LF (\n) + + + + Pretty print + Pretty Print + + + + + Could not open output file: %1 + Ausgabedatei konnte nicht geöffnet werden: %1 + + + + + Choose a filename to export data + Dateinamen für den Datenexport wählen + + + + Export data as JSON + Daten als JSON exportieren + + + + exporting CSV + exportiere CSV + + + + + Error while writing the file '%1': %2 + Fehler beim Schreiben in Datei '%1': %2 + + + + exporting JSON + exportiere JSON + + + + Please select at least 1 table. + Bitte mindestens eine Tabelle auswählen. + + + + Choose a directory + Verzeichnis wählen + + + + Export completed. + Export abgeschlossen. + + + + Export finished with errors. + Export wurde mit Fehlern beendet. + + + + ExportSqlDialog + + + Export SQL... + SQL exportieren... + + + + Tab&le(s) + Tabe&lle(n) + + + + Select All + Alle auswählen + + + + Deselect All + Alle abwählen + + + + &Options + &Optionen + + + + Keep column names in INSERT INTO + Spaltennamen in INSERT INTO belassen + + + + Multiple rows (VALUES) per INSERT statement + Mehrere Reihen (VALUES) je INSERT-Anweisung + + + + Export everything + Alles exportieren + + + + Export schema only + Nur Schema exportieren + + + + Export data only + Nur Daten exportieren + + + + Keep original CREATE statements + Originale CREATE-Anweisungen behalten + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + Altes Schema behalten (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + Altes Schema überschreiben (DROP TABLE, dann CREATE TABLE) + + + + Please select at least one table. + Bitte wählen Sie mindestens eine Tabelle aus. + + + + Choose a filename to export + Dateinamen zum Export auswählen + + + + Export completed. + Export abgeschlossen. + + + + Export cancelled or failed. + Export abgebrochen oder fehlgeschlagen. + + + + ExtendedScintilla + + + + Ctrl+H + + + + + Ctrl+F + + + + + + Ctrl+P + + + + + Find... + Suchen... + + + + Find and Replace... + Suchen und ersetzen... + + + + Print... + Drucken... + + + + ExtendedTableWidget + + + Use as Exact Filter + Als exakten Filter verwenden + + + + Containing + Enthält + + + + Not containing + Enthält nicht + + + + Not equal to + Ungleich zu + + + + Greater than + Größer als + + + + Less than + Kleiner als + + + + Greater or equal + Größer oder gleich + + + + Less or equal + Kleiner oder gleich + + + + Between this and... + Zwischen diesem und... + + + + Regular expression + Regulärer Ausdruck + + + + Edit Conditional Formats... + Bedingte Formatierungen bearbeiten... + + + + Set to NULL + Auf NULL setzen + + + + Cut + Ausschneiden + + + + Copy + Kopieren + + + + Copy with Headers + Mit Headern kopieren + + + + Copy as SQL + Als SQL kopieren + + + + Paste + Einfügen + + + + Print... + Drucken... + + + + Use in Filter Expression + Im Filterausdruck verwenden + + + + Alt+Del + + + + + Ctrl+Shift+C + + + + + Ctrl+Alt+C + + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + Der Inhalt der Zwischenablage ist größer als der ausgewählte Bereich. Soll er dennoch eingefügt werden? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>Es wurden nicht alle Daten geladen. <b>Sollen vor dem Auswählen aller Zeilen alle Daten geladen werden?</b><p><p>Das Antworten von <b>Nein</b> wird keine weiteren Daten laden und die Auswahl nicht durchführen.</br>Das Antworten von <b>Ja</b> benötigt möglicherweise einige Zeit, während die Daten geladen werden, aber die Auswahl wird vollständig sein.</p>Warnung: Das Laden aller Daten benötigt bei großen Tabellen möglicherweise eine große Menge an Speicher. + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + Auswahl kann nicht auf NULL gesetzt. Die Spalte %1 hat eine NOT NULL Beschränkung. + + + + FileExtensionManager + + + File Extension Manager + Dateierweiterungs-Manager + + + + &Up + H&och + + + + &Down + &Runter + + + + &Add + &Hinzufügen + + + + &Remove + &Entfernen + + + + + Description + Beschreibung + + + + Extensions + Erweiterungen + + + + *.extension + *.erweiterung + + + + FilterLineEdit + + + Filter + Filtern + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + Diese Eingabefelder erlauben Ihnen das Anwenden von schnellen Filtern in der aktuell ausgewählten Tabelle. +Standardmäßig werden Zeilen, die den Eingabetext beinhalten, herausgefiltert. +Zudem werden die folgenden Operatoren unterstützt: +% Wildcard +> Größer als +< Kleiner als +>= Größer oder gleich +<= Kleiner oder gleich += Gleich: exakte Übereinstimmung +<> Ungleich:exakte inverse Übereinstimmung +x~y Bereich: Werte zwischen x und y +/regexp/ Werte, die dem regulären Ausdruck genügen + + + + Clear All Conditional Formats + Alle bedingten Formatierungen löschen + + + + Use for Conditional Format + Als bedingte Formatierung verwenden + + + + Edit Conditional Formats... + Bedingte Formatierungen bearbeiten... + + + + Set Filter Expression + Filterausdruck setzen + + + + What's This? + Was ist das? + + + + Is NULL + Ist NULL + + + + Is not NULL + Ist nicht NULL + + + + Is empty + Ist leer + + + + Is not empty + Ist nicht leer + + + + Not containing... + Enthält nicht... + + + + Equal to... + Gleich zu... + + + + Not equal to... + Ungleich zu... + + + + Greater than... + Größer als... + + + + Less than... + Kleiner als... + + + + Greater or equal... + Größer oder gleich... + + + + Less or equal... + Kleiner oder gleich... + + + + In range... + Im Bereich... + + + + Regular expression... + Regulärer Ausdruck... + + + + FindReplaceDialog + + + Find and Replace + Suchen und Ersetzen + + + + Fi&nd text: + Text fi&nden: + + + + Re&place with: + Er&setzen mit: + + + + Match &exact case + &Exakte Schreibung + + + + Match &only whole words + Nur &ganze Wörter + + + + When enabled, the search continues from the other end when it reaches one end of the page + Wenn aktiviert, fährt die Suche am anderen Ende fort, wenn sie das Ende der Seite erreicht hat + + + + &Wrap around + &Umbrechen + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + Wenn gesetzt, erfolgt die Suche rückwärts von der Cursorposition, anderenfalls erfolgt sie vorwärts + + + + Search &backwards + Rück&wärts suchen + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>Wenn ausgewählt, wird das gesuchte Muster nur in der aktuellen Auswahl gesucht.</p></body></html> + + + + &Selection only + Nur Au&swahl + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Wenn aktiviert, wird das Suchmuster als regulärer Ausdruck (UNIX-Stil) interpretiert. Siehe <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks (englisch)</a>.</p></body></html> + + + + Use regular e&xpressions + Reguläre A&usdrücke verwenden + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + Das nächste Auftreten ausgehend von der Cursorposition und in der durch "Rückwärts suchen" gesetzten Richtung finden + + + + &Find Next + Nächste &finden + + + + F3 + + + + + &Replace + &Ersetzen + + + + Highlight all the occurrences of the text in the page + Alle Auftreten des Textes auf der Seite hervorheben + + + + F&ind All + Alle f&inden + + + + Replace all the occurrences of the text in the page + Alle Auftreten des Textes auf der Seite ersetzen + + + + Replace &All + &Alle ersetzen + + + + The searched text was not found + Der gesuchte Text wurde nicht gefunden + + + + The searched text was not found. + Der gesuchte Text wurde nicht gefunden. + + + + The searched text was found one time. + Der gesuchte Text wurde ein Mal gefunden. + + + + The searched text was found %1 times. + Der gesuchte Text wurde %1-mal gefunden. + + + + The searched text was replaced one time. + Der gesuchte Text wurde ein Mal ersetzt. + + + + The searched text was replaced %1 times. + Der gesuchte Text wurde %1-mal ersetzt. + + + + ForeignKeyEditor + + + &Reset + Zu&rücksetzen + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + Fremdschlüssel-Klauseln (ON UPDATE, ON DELETE etc.) + + + + ImageViewer + + + Image Viewer + Bildanzeige + + + + Reset the scaling to match the original size of the image. + Skalierung auf Originalgröße des Bildes zurücksetzen. + + + + Set the scaling to match the size of the viewport. + Skalierung auf Fenstergröße setzen. + + + + Print... + Drucken... + + + + Open preview dialog for printing displayed image + Vorschaudialog zum Drucken des angezeigten Bildes öffnen + + + + Ctrl+P + + + + + ImportCsvDialog + + + Import CSV file + CSV-Datei importieren + + + + Table na&me + Tabellenna&me + + + + &Column names in first line + &Spaltennamen in erster Zeile + + + + Field &separator + Feld-&Separator + + + + , + , + + + + ; + ; + + + + + Tab + Tab + + + + | + | + + + + Other + Anderer + + + + &Quote character + &String-Zeichen + + + + + Other (printable) + Anderer (darstellbar) + + + + + Other (code) + Anderer (Code) + + + + " + " + + + + ' + ' + + + + &Encoding + &Codierung + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Trim fields? + Felder trimmen? + + + + Separate tables + Tabellen trennen + + + + Advanced + Erweitert + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + Beim Import eines leeren Wertes aus einer CSV-Datei in eine existierende Tabelle mit einem Standardwert für diese Spalte wird dieser Standardwert eingefügt. Aktivieren Sie diese Option, um stattdessen einen leeren Wert einzufügen. + + + + Ignore default &values + Standard&werte ignorieren + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + Aktivieren Sie diese Option, um den Import zu stoppen, wenn ein leerer Wert in eine NOT-NULL-Spalte ohne Standardwert importiert werden soll. + + + + Fail on missing values + Fehler bei fehlenden Werten + + + + Disable data type detection + Datentyp-Erkennung deaktivieren + + + + Disable the automatic data type detection when creating a new table. + Die automatische Datentyperkennung bei der Erstellung einer neuen Tabelle deaktivieren. + + + + Use local number conventions + Lokale Nummern-Konventionen verwenden + + + + Use decimal and thousands separators according to the system locale. + Dezimal- und Tausender-Trennzeichen entsprechend der Systemeinstellungen verwenden. + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + Beim Import von Daten in eine existierende Tabelle mit einem Primärschlüssel, Unique-Beschränkungen oder einem eindeutigen Index besteht die Möglichkeit von Konflikten. Diese Option erlaubt die Auswahl einer Strategie für diesen Fall: Standardmäßig wird der Import abgebrochen und zurückgerollt, aber es besteht auch die Option des Ignorierens und somit Nicht-Importierens in Konflikt stehender Zeilen oder des Ersetzens existierender Zeilen der Tabelle. + + + + Abort import + Import abbrechen + + + + Ignore row + Zeile ignorieren + + + + Replace existing row + Existierende Zeile ersetzen + + + + Conflict strategy + Konflikt-Strategie + + + + + Deselect All + Alle abwählen + + + + Match Similar + Ähnliche suchen + + + + Select All + Alle auswählen + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + Es gibt bereits eine Tabelle namens '%1' und ein Import in eine existierende Tabelle ist nur bei übereinstimmender Spaltenanzahl möglich. + + + + There is already a table named '%1'. Do you want to import the data into it? + Es gibt bereits eine Tabelle namens '%1'. Möchten Sie die Daten in diese importieren? + + + + Creating restore point failed: %1 + Erstellung des Wiederherstellungspunktes fehlgeschlagen: %1 + + + + Creating the table failed: %1 + Erstellung der Tabelle fehlgeschlagen: %1 + + + + importing CSV + importierte CSV + + + + Could not prepare INSERT statement: %1 + INSERT-Anweisung konnte nicht vorbereitet werden: %1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + Unerwartetes Dateiende. Bitte sicherstellen, dass die korrekten Anführungszeichen gesetzt sind und die Datei wohlgeformt ist. + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + Import der Datei '%1' benötigte %2 ms. Davon wurden %3 ms in der Zeilenfunktion verbracht. + + + + Inserting row failed: %1 + Einfügen der Zeile fehlgeschlagen: %1 + + + + MainWindow + + + toolBar1 + Werkzeugleiste1 + + + + Opens the SQLCipher FAQ in a browser window + Öffnet die SQLCipher-FAQ in einem Browserfenster + + + + Export one or more table(s) to a JSON file + Exportiert eine oder mehrere Tabelle(n) in eine JSON-Datei + + + + DB Browser for SQLite + DB-Browser für SQLite + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + Dies ist die Struktur der geöffneten Datenbank. +Sie können SQL-Anweisungen aus einer Objektzeile fassen und in anderen Anwendungen oder einer anderen 'DB-Browser für SQLite'-Instanz ablegen. + + + + + Un/comment block of SQL code + Kommentieren/Unkommentieren eines Block von SQL-Code + + + + Un/comment block + Block kommentieren/unkommentieren + + + + Comment or uncomment current line or selected block of code + Aktuelle Zeilen oder ausgewählten Codeblock kommentieren oder unkommentieren + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + Aktuelle Zeilen oder aktuelle Zeile kommentieren oder unkommentieren, wenn es keine Auswahl gibt. Der gesamte Block wird entsprechend der ersten Zeile invertiert. + + + + Ctrl+/ + + + + + Stop SQL execution + SQL-Ausführung abbrechen + + + + Stop execution + Ausführung abbrechen + + + + Stop the currently running SQL script + Das aktuelle laufende SQL-Skript stoppen + + + + Error Log + Fehlerprotokoll + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + &Datenbankstruktur + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + Daten d&urchsuchen + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + P&ragmas bearbeiten + + + + Temp Store + Temporärer Speicher + + + + Secure Delete + Sicheres Löschen + + + + Case Sensitive Like + Case-Sensitives LIKE + + + + Journal Mode + Journal-Modus + + + + Journal Size Limit + Begrenzung der Journalgröße + + + + Recursive Triggers + Rekursive Trigger + + + Delete + pragma + Löschen (DELETE) + + + Truncate + pragma + Kürzen (TRUNCATE) + + + Persist + pragma + Behalten (PERSIST) + + + Memory + pragma + RAM (MEMORY) + + + WAL + pragma + WAL + + + Off + pragma + Deaktiviert + + + + Page Size + Seitengröße + + + + Foreign Keys + Fremdschlüssel + + + + Auto Vacuum + Auto-Vakuum + + + + Max Page Count + Maximale Seitenzahl + + + Normal + pragma + Normal + + + Exclusive + pragma + Exklusiv + + + + Checkpoint Full FSYNC + Full FSYNC für Checkpoints + + + + + Off + Inaktiv + + + + + Normal + Normal + + + + + Full + Vollständig + + + + Default + Voreinstellung + + + + File + Datei + + + + + Memory + RAM + + + + Delete + Löschen (DELETE) + + + + Truncate + Kürzen (TRUNCATE) + + + + Persist + Behalten (PERSIST) + + + + WAL + WAL + + + + Exclusive + Exklusiv + + + + Automatic Index + Automatische Indizierung + + + + Ignore Check Constraints + CHECK-Beschränkungen ignorieren + + + + Full FSYNC + Full FSYNC + + + + WAL Auto Checkpoint + Automatische WAL-Checkpoints + + + + User Version + Benutzerspezifische Version + + + + Synchronous + Synchronität + + + + None + Inaktiv + + + + Incremental + Inkrementell + + + + Locking Mode + Sperrmodus + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + SQL aus&führen + + + + &Recent Files + &Kürzliche Dateien + + + + &New Database + &Neue Datenbank + + + + + Ctrl+F4 + + + + + &Undo + &Zurücksetzen + + + + + Undo last change to the database + Letzte Datenbankänderung rückgängig machen + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + Diese Aktion macht die letzte Änderung an der Datenbank aus "Daten durchsuchen" oder "SQL ausführen" rückgängig. Wiederherstellen ist nicht möglich. + + + + Compact &Database... + &Datenbank komprimieren... + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + Den Dialog zum Ändern der Tabelle öffnen, wo eine existierende Tabelle umbenannt werden kann. Zudem ist das Hinzufügen oder Löschen von Tabellenfeldern möglich, genauso wie das Ändern von Feldnamen und -typen. + + + + Execute all/selected SQL + Komplettes/ausgewähltes SQL ausführen + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + Dieser Button führt die aktuell ausgewählte SQL-Anweisung aus. Wenn kein Text ausgewählt ist, werden alle SQL-Anweisungen ausgeführt. + + + + Ctrl+Shift+T + + + + + &Load Extension... + Erweiterung &laden... + + + + Execute line + Zeile ausführen + + + + &Wiki + &Wiki + + + + F1 + + + + + Bug &Report... + Fehle&rmeldung... + + + + Feature Re&quest... + Funktions&anfrage... + + + + Web&site + Web&seite + + + + &Donate on Patreon... + Über &Patreon spenden... + + + + &Save Project + Projekt &speichern + + + + Open &Project... + &Projekt öffnen... + + + + Open &Project + &Projekt öffnen + + + + &Attach Database... + Datenbank &anhängen... + + + + + Add another database file to the current database connection + Eine andere Datenbankdatei zur aktuellen Datenbankverbindung hinzufügen + + + + This button lets you add another database file to the current database connection + Dieser Button erlaubt Ihnen das Hinzufügen einer anderen Datenbankdatei zur aktuellen Datenbankverbindung + + + + &Set Encryption... + Verschlüsselung &setzen... + + + + SQLCipher &FAQ + SQLCiper &FAQ + + + + Table(&s) to JSON... + Tabelle(&n) zu JSON... + + + + Open Data&base Read Only... + Daten&bank im Lesemodus öffnen... + + + + Ctrl+Shift+O + + + + + Save results + Ergebnisse speichern + + + + Save the results view + Ergebnisansicht speichern + + + + This button lets you save the results of the last executed query + Dieser Button erlaubt Ihnen das Speichern der Ergebnisse der zuletzt ausgeführten Abfrage + + + + + Find text in SQL editor + Text im SQL-Editor finden + + + + Find + Suchen + + + + This button opens the search bar of the editor + Dieser Button öffnet die Suchleiste des Editors + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + Text im SQL-Editor suchen oder ersetzen + + + + Find or replace + Suchen oder ersetzen + + + + This button opens the find/replace dialog for the current editor tab + Dieser Button öffnet den Suchen-/Ersetzen-Dialog für den aktuellen Editortab + + + + Ctrl+H + + + + + Export to &CSV + Nach &CSV exportieren + + + + Export to &JSON + Nach &JSON exportieren + + + + Save as &view + Als &View speichern + + + + Save as view + Als Ansicht speichern + + + + &Open Database + Datenbank &öffnen + + + + Drag && Drop SELECT Query + Drag-and-drop für SELECT-Abfrage + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + Wenn Felder aus der gleichen Tabelle oder einen einzelnen Tabelle ausgewählt und gezogen werden, soll eine SELECT-Abfrage in den Editor geschrieben werden + + + + Browse Table + Tabelle durchsuchen + + + + + Ctrl+Shift+W + + + + + Table from CSV data in Clipboard... + Tabelle aus CSV-Daten in der Zwischenablage... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + Dies behandelt den aktuellen Inhalt der Zwischenablage als CSV-Datei und öffnet den gleichen Import-Dialog wie für den Import von CSV-Daten aus einer Datei. + + + + Show &Row Counts + Zeilena&nzahl anzeigen + + + + This shows the number of rows for each table and view in the database. + Dies zeigt die Anzahl der Zeilen für jede Tabelle und Ansicht in der Datenbank. + + + + Save Database &As... + D&atenbank speichern unter... + + + + Save the current database as a different file + Die aktuelle Datenbank in einer anderen Datei speichern + + + + Refresh + Aktualisieren + + + + Reload the database structure + Die Datenbankstruktur neu laden + + + + Shows or hides the Project toolbar. + Zeigt oder versteckt die Projekt-Werkzeugleiste. + + + + Extra DB Toolbar + Extra DB-Werkzeugleiste + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + Dieser Button erlaubt Ihnen das Speichern aller mit der geöffneten DB verbundenen Einstellungen in einer DB-Browser für SQLite-Projektdatei + + + + This button lets you open a DB Browser for SQLite project file + Dieser Button erlaubt Ihnen das Öffnen einer DB-Browser für SQLite-Projektdatei + + + + New In-&Memory Database + Neue In-&Memory-Datenbank + + + + Drag && Drop Qualified Names + Drag-and-drop qualifizierter Namen + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + Qualifizierte Namen (z. B. "Tabelle."Feld") verwenden, wenn die Objekte gefasst und im Editor abgelegt werden + + + + Drag && Drop Enquoted Names + Drag-and-drop zitierter Namen + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + Geschützte Identifier (z. B. "Tabelle1") verwenden, wenn die Objekte gefasst und im Editor abgelegt werden + + + + &Integrity Check + &Integritätsprüfung + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + Führt das Pragma integrity_check auf der geöffneten Datenbank aus und gibt die Ergebnisse im SQL-Tab zurück. Dieses Pragma führt eine Integritätsprüfung der gesamten Datenbank durch. + + + + &Foreign-Key Check + &Fremdschlüssel-Prüfung + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + Führt das Pragma foreign_key_check auf der geöffneten Datenbank aus und gibt die Ergebnisse im SQL-Tab zurück + + + + &Quick Integrity Check + &Schnelle Integritätsprüfung + + + + Run a quick integrity check over the open DB + Führt eine schnelle Integritätsprüfung der geöffneten DB aus + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + Führt das Pragma quick_check auf der geöffneten Datenbank aus und gibt die Ergebnisse im SQL-Tab zurück. Dieser Befehl führt einen Großteil der Prüfung des Pragmas integrity_check aus, ist aber deutlich schneller. + + + + &Optimize + &Optimieren + + + + Attempt to optimize the database + Versuchen, die Datenbank zu optimieren + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + Führt das Pragma optimize auf der geöffneten Datenbank aus. Dieses Pragma führt möglicherweise Optimierungen durch, die die Performanz zukünftiger Queries verbessern. + + + + + Print + Drucken + + + + Print text from current SQL editor tab + Den Text aus dem aktuellen SQL-Editortab drucken + + + + Open a dialog for printing the text in the current SQL editor tab + Einen Dialog zum Drucken des Textes im aktuellen SQL-Editortab öffnen + + + + Print the structure of the opened database + Die Struktur der geöffneten Datenbank drucken + + + + Open a dialog for printing the structure of the opened database + Einen Dialog zum Drucken der Struktur der geöffneten Datenbank öffnen + + + + &Save Project As... + Projekt &speichern als... + + + + + + Save the project in a file selected in a dialog + Das Projekt in einer in einem Dialog ausgewählten Datei speichern + + + + Save A&ll + &Alle speichern + + + + + + Save DB file, project file and opened SQL files + DB-Datei, Projektdatei und geöffnete SQL-Dateien speichern + + + + Ctrl+Shift+S + + + + + Close Pro&ject + Pro&jekt schließen + + + + + Close project and database files and return to the initial state + Projekt und Datenbankdateien schließen und zum initialen Zustand zurückkehren + + + + Ctrl+Shift+F4 + + + + + + Detach Database + Datenbank ablösen + + + + + Detach database file attached to the current database connection + Die mit der aktuellen Datenbankverbindung verwendete Datenbankdatei ablösen + + + + Open an existing database file in read only mode + Eine existierende Datenbank schreibgeschützt öffnen + + + + &File + &Datei + + + + &Import + &Import + + + + &Export + &Export + + + + &Edit + &Bearbeiten + + + + &View + &Ansicht + + + + &Help + &Hilfe + + + + Edit Database &Cell + Datenbank&zelle bearbeiten + + + + This button clears the contents of the SQL logs + Dieser Button löscht den Inhalt der SQL-Protokolle + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + Dieses Panel erlaubt Ihnen das Betrachten eines Protokolls aller SQL-Kommandos, die von der Anwendung oder von Ihnen selbst ausgegangen sind + + + + DB Sche&ma + DB-Sche&ma + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + Dies ist die Struktur der geöffneten Datenbank. +Sie können mehrere Objektnamen aus der Namensspalte nehmen und in den SQL-Editor ziehen und Sie können die Eigenschaften der abgelegten Namen über das Kontextmenü anpassen. Dies kann Sie bei der Erstellung von SQL-Anweisungen unterstützen. +Sie können SQL-Anweisungen aus der Schemaspalte nehmen und in den SQL-Editor oder in anderen Anwendungen ablegen. + + + + + &Remote + Entfe&rnt + + + + Open SQL file(s) + SQL-Datei(en) öffnen + + + + This button opens files containing SQL statements and loads them in new editor tabs + Dieser Button öffnet Dateien mit SQL-Anweisungen und lädt diese in neue Editortabs + + + + + Execute current line + Aktuelle Zeile ausführen + + + + This button executes the SQL statement present in the current editor line + Dieser Button führt die SQL-Anweisung in der aktuellen Editorzeile aus + + + + Shift+F5 + + + + + Sa&ve Project + &Projekt speichern + + + + + Save SQL file as + SQL-Datei speichern als + + + + This button saves the content of the current SQL editor tab to a file + Dieser Button speichert den Inhalt des aktuellen SQL-Editortabs in einer Datei + + + + &Browse Table + Tabelle &durchsuchen + + + + Copy Create statement + CREATE-Anweisung kopieren + + + + Copy the CREATE statement of the item to the clipboard + CREATE-Anweisung des Elements in die Zwischenablage kopieren + + + + User + Benutzer + + + + Application + Anwendung + + + + &Clear + &Leeren + + + + &New Database... + &Neue Datenbank... + + + + + Create a new database file + Neue Datenbankdatei erstellen + + + + This option is used to create a new database file. + Diese Option wird zum Erstellen einer neuen Datenbankdatei verwendet. + + + + Ctrl+N + + + + + + &Open Database... + Datenbank &öffnen... + + + + + + + + Open an existing database file + Existierende Datenbankdatei öffnen + + + + + + This option is used to open an existing database file. + Diese Option wird zum Öffnen einer existierenden Datenbankdatei verwendet. + + + + Ctrl+O + + + + + &Close Database + Datenbank &schließen + + + + This button closes the connection to the currently open database file + Dieser Button schließt die Verbindung zu der aktuell geöffneten Datenbankdatei + + + + + Ctrl+W + + + + + + Revert database to last saved state + Datenbank auf zuletzt gespeicherten Zustand zurücksetzen + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + Diese Option wird zum Zurücksetzen der aktuellen Datenbankdatei auf den zuletzt gespeicherten Zustand verwendet. Alle getätigten Änderungen gehen verloren. + + + + + Write changes to the database file + Änderungen in Datenbankdatei schreiben + + + + This option is used to save changes to the database file. + Diese Option wird zum Speichern von Änderungen in der Datenbankdatei verwendet. + + + + Ctrl+S + + + + + Compact the database file, removing space wasted by deleted records + Datenbankdatei komprimieren, löscht Speicherplatz von gelöschten Zeilen + + + + + Compact the database file, removing space wasted by deleted records. + Datenbankdatei komprimieren, löscht Speicherplatz von gelöschten Zeilen. + + + + E&xit + &Beenden + + + + Ctrl+Q + + + + + Import data from an .sql dump text file into a new or existing database. + Daten von einer .sql-Dump-Textdatei in eine neue oder existierende Datenbank importieren. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + Diese Option wird zum Importieren von Daten von einer .sql-Dump-Textdatei in eine neue oder existierende Datenbank verwendet. SQL-Dumpdateien können von den meisten Datenbankanwendungen erstellt werden, inklusive MySQL und PostgreSQL. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Öffnet einen Assistenten zum Importieren von Daten aus einer kommaseparierten Textdatei in eine Datenbanktabelle. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Öffnet einen Assistenten zum Importieren von Daten aus einer kommaseparierten Textdatei in eine Datenbanktabelle. CSV-Dateien können von den meisten Datenbank- und Tabellenkalkulationsanwendungen erstellt werden. + + + + Export a database to a .sql dump text file. + Daten in eine .sql-Dump-Textdatei exportieren. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + Diese Option ermöglicht den Export einer Datenbank in eine .sql-Dump-Textdatei. SQL-Dumpdateien enthalten alle notwendigen Daten, um die Datenbank mit den meisten Datenbankanwendungen neu erstellen zu können, inklusive MySQL und PostgreSQL. + + + + Export a database table as a comma separated text file. + Datenbank als kommaseparierte Textdatei exportieren. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + Exportiert die Datenbank als kommaseparierte Textdatei, fertig zum Import in andere Datenbank- oder Tabellenkalkulationsanwendungen. + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Den Assistenten zum Erstellen einer Tabelle öffnen, wo der Name und die Felder für eine neue Tabelle in der Datenbank festgelegt werden können + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Den Assistenten zum Löschen einer Tabelle öffnen, wo eine zu entfernende Datenbanktabelle ausgewählt werden kann. + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + Den Assistenten zum Erstellen des Index öffnen, wo ein neuer Index für eine existierende Datenbanktabelle gewählt werden kann. + + + + &Preferences... + &Einstellungen... + + + + + Open the preferences window. + Das Einstellungsfenster öffnen. + + + + &DB Toolbar + &DB-Werkzeugleiste + + + + Shows or hides the Database toolbar. + Zeigt oder versteckt die Datenbank-Werkzeugleiste. + + + + Shift+F1 + + + + + &Recently opened + &Kürzlich geöffnet + + + + Ctrl+T + + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + Warnung: dieses Pragma ist nicht lesbar und dieser Wert wurde abgeleitet. Das Schreiben des Pragmas überschreibt möglicherweise ein geändertes LIKE, das von einer SQLite-Erweiterung zur Verfügung gestellt wird. + + + + Too&ls + &Werkzeuge + + + + DB Toolbar + DB-Werkzeugleiste + + + + SQL &Log + SQL-&Protokoll + + + + Show S&QL submitted by + Anzeige des übergebenen S&QL von + + + + &Plot + &Diagramm + + + + + Project Toolbar + Projekt-Werkzeugleiste + + + + Extra DB toolbar + Extra DB-Werkzeugleiste + + + + + + Close the current database file + Die aktuelle Datenbankdatei schließen + + + + &Revert Changes + Änderungen &rückgängig machen + + + + &Write Changes + Änderungen &schreiben + + + + &Database from SQL file... + &Datenbank aus SQL-Datei... + + + + &Table from CSV file... + &Tabelle aus CSV-Datei... + + + + &Database to SQL file... + &Datenbank als SQL-Datei... + + + + &Table(s) as CSV file... + &Tabelle(n) als CSV-Datei... + + + + &Create Table... + Tabelle &erstellen... + + + + &Delete Table... + Tabelle &löschen... + + + + &Modify Table... + Tabelle &ändern... + + + + Create &Index... + &Index erstellen... + + + + W&hat's This? + &Was ist das? + + + + &About + &Über + + + + New &tab + Neuer &Tab + + + + This button opens a new tab for the SQL editor + Dieser Button öffnet einen neuen Tab im SQL-Editor + + + + &Execute SQL + SQL &ausführen + + + + + Save the current session to a file + Aktuelle Sitzung in einer Datei speichern + + + + + Load a working session from a file + Sitzung aus einer Datei laden + + + + + + Save SQL file + SQL-Datei speichern + + + + Ctrl+E + + + + + Export as CSV file + Als CSV-Datei exportieren + + + + Export table as comma separated values file + Tabelle als kommaseparierte Wertedatei exportieren + + + + Ctrl+L + + + + + + Ctrl+P + + + + + Database encoding + Datenbank-Codierung + + + + + Choose a database file + Eine Datenbankdatei auswählen + + + + Ctrl+Return + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Reset Window Layout + Fensteranordnung zurücksetzen + + + + The database is currently busy. + Die Datenbank ist aktuell beschäftigt. + + + + Click here to interrupt the currently running query. + Hier klicken, um die aktuell laufende Abfrage zu unterbrechen. + + + + Encrypted + Verschlüsselt + + + + Database is encrypted using SQLCipher + Datenbank ist mittels SQLCipher verschlüsselt + + + + Read only + Nur lesen + + + + Database file is read only. Editing the database is disabled. + Zugriff auf Datenbank nur lesend. Bearbeiten der Datenbank ist deaktiviert. + + + + Could not open database file. +Reason: %1 + Datenbankdatei konnte nicht geöffnet werden. Grund: %1 + + + + + + Choose a filename to save under + Dateinamen zum Speichern auswählen + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + Fehler beim Speichern der Datenbankdatei. Dies bedeutet, dass nicht alle Änderungen an der Datenbank gespeichert wurden. Der folgende Fehler muss zuvor gelöst werden: + +%1 + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + Sollen die in den SQL-Tabs getätigten Änderungen in der Projektdatei '%1' gespeichert werden? + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + Eine neue Version des DB-Browsers für SQLite ist verfügbar (%1.%2.%3).<br/><br/>Bitte laden Sie diese von <a href='%4'>%4</a> herunter. + + + + DB Browser for SQLite project file (*.sqbpro) + DB-Browser für SQLite-Projektdatei (*.sqbpro) + + + + Error checking foreign keys after table modification. The changes will be reverted. + Fehler beim Prüfen von Fremdschlüsseln nach der Änderung an der Tabelle. Die Änderungen werden rückgängig gemacht. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + Diese Tabelle hat die Fremdschlüssel-Prüfung nicht bestanden.<br/>Sie sollten 'Werkzeuge | Fremdschlüssel-Prüfung' ausführen und die gemeldeten Probleme beheben. + + + + Execution finished with errors. + Ausführung wurde mit Fehlern beendet. + + + + Execution finished without errors. + Ausführung wurde ohne Fehler beendet. + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + Sollen wirklich alle Änderungen an der Datenbankdatei '%1' seit dem letzten Speichern rückgängig gemacht werden? + + + + Choose a file to import + Datei für Import auswählen + + + + Text files(*.sql *.txt);;All files(*) + Textdateien(*.sql *.txt);;Alle Dateien(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + Soll für die importierten Daten eine neue Datenbank erstellt werden? +Bei der Antwort NEIN werden die Daten in die SQL-Datei der aktuellen Datenbank importiert. + + + + Ctrl+Tab + + + + + Ctrl+Shift+Tab + + + + + Clear List + Liste leeren + + + + Window Layout + Fensterlayout + + + + Simplify Window Layout + Fensterlayout vereinfachen + + + + Alt+Shift+0 + + + + + Dock Windows at Bottom + Fenster unten anheften + + + + Dock Windows at Left Side + Fenster links anheften + + + + Dock Windows at Top + Fenster oben anheften + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + Es werden aktuell SQL-Anweisungen ausgeführt. Das Schließen der Datenbank wird deren Ausführung stoppen, was die Datenbank möglicherweise in einem inkonsistenten Zustand belässt. Soll die Datenbank wirklich geschlossen werden? + + + + Do you want to save the changes made to the project file '%1'? + Sollen die an der Projektdatei '%1' getätigten Änderungen gespeichert werden? + + + + File %1 already exists. Please choose a different name. + Datei %1 existiert bereits. Bitte einen anderen Namen auswählen. + + + + Error importing data: %1 + Fehler beim Datenimport: %1 + + + + Import completed. + Import abgeschlossen. + + + + Delete View + Ansicht löschen + + + + Delete Trigger + Trigger löschen + + + + Delete Index + Index löschen + + + + + Delete Table + Tabelle löschen + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + Das Setzen von PRAGMA-Werten übermittelt den aktuellen Vorgang. +Sind Sie sicher? + + + + In-Memory database + In-Memory-Datenbank + + + + Automatically load the last opened DB file at startup + Beim Starten automatisch die zuletzt geöffnete Datenbank öffnen + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + Möchten Sie die Tabelle '%1' wirklich löschen? +Alle mit dieser Tabelle verbundenen Daten gehen verloren. + + + + Are you sure you want to delete the view '%1'? + Möchten Sie die Ansicht '%1' wirklich löschen? + + + + Are you sure you want to delete the trigger '%1'? + Möchten Sie den Trigger '%1' wirklich löschen? + + + + Are you sure you want to delete the index '%1'? + Möchten Sie den Index '%1' wirklich löschen? + + + + Error: could not delete the table. + Fehler: Tabelle konnte nicht gelöscht werden. + + + + Error: could not delete the view. + Fehler: Ansicht konnte nicht gelöscht werden. + + + + Error: could not delete the trigger. + Fehler: Trigger konnte nicht gelöscht werden. + + + + Error: could not delete the index. + Fehler: Index konnte nicht gelöscht werden. + + + + Message from database engine: +%1 + Nachricht von Datenbank-Engine: +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + Das Bearbeiten der Tabelle setzt das Speichern aller ausstehenden Änderungen voraus. +Möchten Sie die Datenbank wirklich speichern? + + + + Edit View %1 + Ansicht %1 bearbeiten + + + + Edit Trigger %1 + Trigger %1 bearbeiten + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + Es werden bereits SQL-Anweisungen ausgeführt. Sollen diese gestoppt werden, um stattdessen die aktuellen Anweisungen auszuführen? Dies führt möglicherweise zu einem inkonsistenten Zustand der Datenbank. + + + + -- EXECUTING SELECTION IN '%1' +-- + -- FÜHRE AUSWAHL IN '%1' AUS +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- FÜHRE ZEILE IN '%1' AUS +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- FÜHRE ALLES IN '%1' AUS +-- + + + + + At line %1: + In Zeile %1: + + + + Result: %1 + Ergebnis: %1 + + + + Result: %2 + Ergebnis: %2 + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + Das Setzen von PRAGMA-Werten oder das Komprimieren wird Ihre aktuelle Transaktion übermitteln. +Sind Sie sich sicher? + + + + Opened '%1' in read-only mode from recent file list + '%1' aus der Liste zuletzt geöffneter Dateien im Lesemodus geöffnet + + + + Opened '%1' from recent file list + '%1' aus der Liste zuletzt geöffneter Dateien geöffnet + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + Auf die Datei anzuwendende Aktion auswählen. <br/>Hinweis: Nur 'Import' kann mehr als eine Datei verarbeiten. + Auf die Dateien anzuwendende Aktion auswählen. <br/>Hinweis: Nur 'Import' kann mehr als eine Datei verarbeiten. + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + Die Anweisungen im Tab '%1' werden noch ausgeführt. Das Schließen des Tabs stoppt die Ausführung. Dies hinterlässt die Datenbank möglicherweise in einem inkonsistenten Zustand. Soll der Tab wirklich geschlossen werden? + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + Diese Projektdatei verwendet ein altes Dateiformat, da es mit DB-Browser für SQLite Version 3.10 oder älter erstellt wurde. Das Laden dieser Dateien wird nicht mehr vollständig unterstützt. Um es komplett zu laden, bitte DB-Browser für SQLite Version 3.12 verwenden und in das neue Format konvertieren. + + + + Project saved to file '%1' + Projekt in Datei '%1' gespeichert + + + + Yes. Don't ask again + Ja. Nicht erneut fragen + + + + This action will open a new SQL tab with the following statements for you to edit and run: + Diese Aktion öffnet einen neuen SQL-Tab mit den folgenden Anweisungen zum Bearbeiten und Ausführen: + + + + Rename Tab + Tab umbenennen + + + + Duplicate Tab + Tab duplizieren + + + + Close Tab + Tab schließen + + + + Opening '%1'... + '%1' öffnen... + + + + There was an error opening '%1'... + Fehler beim Öffnen von '%1'... + + + + Value is not a valid URL or filename: %1 + Wert ist keine gültige URL bzw. kein gültiger Dateiname: %1 + + + + %1 rows returned in %2ms + %1 Zeilen in %2 ms zurückgegeben + + + + Ctrl+0 + + + + + Alt+Shift+W + + + + + Choose a database file to save under + Datenbankdatei zum Speichern auswählen + + + + Error while saving the database to the new file. + Fehler beim Speichern der Datenbank in einer neuen Datei. + + + + Choose text files + Textdateien auswählen + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + Import vollständig. Ein paar Fremdschlüssel-Beschränkungen wurden verletzt. Bitte beheben Sie diese vor dem Speichern. + + + + Modify View + Ansicht verändern + + + + Modify Trigger + Trigger verändern + + + + Modify Index + Index verändern + + + + Modify Table + Tabelle verändern + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (nur lesend) + + + + Open Database or Project + Datenbank oder Projekt öffnen + + + + Attach Database... + Datenbank anhängen... + + + + Import CSV file(s)... + CSV-Datei(en) importieren... + + + + Do you want to save the changes made to SQL tabs in a new project file? + Sollen die an den SQL-Tabs getätigten Änderungen in einer neuen Projektdatei gespeichert werden? + + + + Do you want to save the changes made to the SQL file %1? + Sollen die getätigten Änderungen in der SQL-Datei %1 gespeichert werden? + + + + Select SQL file to open + SQL-Datei zum Öffnen auswählen + + + + Select file name + Dateinamen auswählen + + + + Select extension file + Erweiterungsdatei auswählen + + + + Extension successfully loaded. + Erweiterung erfolgreich geladen. + + + + Error loading extension: %1 + Fehler beim Laden der Erweiterung: %1 + + + + Could not find resource file: %1 + Ressourcen-Datei konnte nicht gefunden werden: %1 + + + + + Don't show again + Nicht wieder anzeigen + + + + New version available. + Neue Version verfügbar. + + + + Choose a project file to open + Wählen Sie die zu öffnende Projektdatei + + + + DB file '%1' could not be opened + Datenbankdatei '%1' konnte nicht geöffnet werden + + + + Table '%1' not found; settings ignored + Tabelle '%1' nicht gefunden; Einstellungen werden ignoriert + + + + Could not open project file for writing. +Reason: %1 + Projekt-Datei konnte nicht schreibend geöffnet werden. +Grund: %1 + + + + -- Reference to file "%1" (not supported by this version) -- + -- Referenz zu Datei "%1" (von dieser Version nicht unterstützt) -- + + + + Collation needed! Proceed? + Kollation notwendig! Fortführen? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + Eine Tabelle in dieser Datenbank benötigt eine spezielle Kollationsfunktion '%1', die diese Anwendung ohne weitere Kenntnisse nicht bereitstellen kann. +Wenn Sie fortfahren, sollten Sie im Hinterkopf behalten, dass mit Ihrer Datenbank unerwartete Dinge geschehen können. +Erstellen Sie ein Backup! + + + + creating collation + erstelle Kollation + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + Vergeben Sie einen Namen für den SQL-Tab. Verwenden Sie das Zeichen '&&', um das folgende Zeichen als Tastaturkürzel zu verwenden. + + + + Please specify the view name + Geben Sie bitte einen Namen für Ansicht an + + + + There is already an object with that name. Please choose a different name. + Es gibt bereits ein Objekt mit diesem Namen. Bitte wählen Sie einen anderen aus. + + + + View successfully created. + Ansicht erfolgreich erstellt. + + + + Error creating view: %1 + Fehler beim Erstellen der Ansicht: %1 + + + + This action will open a new SQL tab for running: + Diese Aktion öffnet einen neuen SQL-Tab zur Ausführung: + + + + Press Help for opening the corresponding SQLite reference page. + Drücken Sie auf 'Hilfe', um die entsprechende SQLite-Referenzseite zu öffnen. + + + + Busy (%1) + Beschäftigt (%1) + + + + NullLineEdit + + + Set to NULL + Auf NULL setzen + + + + Alt+Del + + + + + PlotDock + + + Plot + Diagramm + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>Dieses Pane zeigt die Liste der Spalten der aktuell ausgewählten Tabelle oder der soeben ausgeführten Abfrage. Sie können die für die X- und Y-Achse gewünschten Spalten für das Plot-Pane unten auswählen. Die Tabelle zeigt den erkannten Achsentyp, der den entstehenden Plot beeinflusst. Für die Y-Achse sind nur numerische Spalten zulässig, während Sie für die X-Achse aus folgenden Optionen auswählen können:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Datum/Zeit</span>: Strings im Format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Datum</span>: Strings im Format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Zeit</span>: Strings im Format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Beschriftung</span>: andere Stringformate. Die Auswahl dieser Spalte als X-Achse erzeugt einen Balkendiagramm mit den Spaltenwerten als Beschriftung für die Balken.</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numerisch</span>: Integer- oder Real-Werte</li></ul><p>Ein Doppelklick auf die Y-Zellen ermöglicht Ihnen das Ändern der für den Graph verwendeten Farbe.</p></body></html> + + + + Columns + Spalten + + + + X + X + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + Achsentyp + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + Hier wird ein Plot angezeigt, wenn Sie oben die x- und y-Werte auswählen. + +Klicken Sie auf Punkte, um diese im Plot und in der Tabelle auszuwählen. Strg+Klick zur Auswahl eines Punktebereichs. + +Verwenden Sie das Mausrad zum Zoomen und ziehen Sie mit der Maus, um den Achsenbereich zu ändern. + +Wählen Sie die Achsen oder Achsenbeschriftungen aus, um nur in diese Richtung zu zoomen oder zu verschieben. + + + + Line type: + Linientyp: + + + + + None + Keine + + + + Line + Linie + + + + StepLeft + Linksschritt + + + + StepRight + Rechtsschritt + + + + StepCenter + Mittelschritt + + + + Impulse + Impuls + + + + Point shape: + Punktform: + + + + Cross + Kreuz + + + + Plus + Plus + + + + Circle + Kreis + + + + Disc + Scheibe + + + + Square + Quadrat + + + + Diamond + Diamant + + + + Star + Stern + + + + Triangle + Dreieck + + + + TriangleInverted + Invertiertes Dreieck + + + + CrossSquare + Quadrat mit Kreuz + + + + PlusSquare + Quadrat mit Plus + + + + CrossCircle + Kreis mit Kreuz + + + + PlusCircle + Kreis mit Plus + + + + Peace + Peace + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>Aktuelles Diagramm speichern...</p><p>Dateiformat durch Endung auswählen (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + Aktuelles Diagramm speichern... + + + + + Load all data and redraw plot + Alle Daten laden und Plot neu zeichnen + + + + + + Row # + Zeile # + + + + Copy + Kopieren + + + + Print... + Drucken... + + + + Help + + + + + Show legend + Legende anzeigen + + + + Stacked bars + Gestapelte Bars + + + + Fixed number format + Festes Zahlenformat + + + + Date/Time + Datum/Zeit + + + + Date + Datum + + + + Time + Zeit + + + + + Numeric + Numerisch + + + + Label + Beschriftung + + + + Invalid + Ungültig + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + Alle Daten laden und Plot neu zeichnen. +Warnung: es wurden aufgrund der partiellen Abrufmechanismus noch nicht alle Daten aus der Tabelle abgerufen. + + + + Choose an axis color + Eine Achsenfarbe wählen + + + + Choose a filename to save under + Dateinamen zum Speichern auswählen + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Alle Dateien(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + Dieser Plot enthält Kurven und der ausgewählte Linienstil kann nur auf nach X sortierte Graphen angewendet werden. Sortieren Sie entweder die Tabelle oder Abfrage nach X oder entfernen Sie die Kurven oder wählen Sie eine der Stile, die von Kurven unterstützt werden: Keiner oder Linie. + + + + Loading all remaining data for this table took %1ms. + Das Laden aller verbleibender Daten dieser Tabelle benötigte %1 ms. + + + + PreferencesDialog + + + Preferences + Einstellungen + + + + &General + All&gemeines + + + + Remember last location + Letztes Verzeichnis merken + + + + Always use this location + Immer dieses Verzeichnis verwenden + + + + Remember last location for session only + Letztes Verzeichnis nur innerhalb der Sitzung merken + + + + Lan&guage + &Sprache + + + + Show remote options + Fernzugriffs-Optionen anzeigen + + + + Automatic &updates + Automatische &Updates + + + + &Database + &Datenbank + + + + Database &encoding + Datenbank-&Codierung + + + + Open databases with foreign keys enabled. + Öffnen von Datenbanken mit Fremdschlüsseln aktiviert. + + + + &Foreign keys + &Fremdschlüssel + + + + + + + + + + + + + + enabled + aktiviert + + + + Default &location + Voreingestellter &Speicherort + + + + + + ... + ... + + + + Remove line breaks in schema &view + Zeilenumbrüche in der Schema&ansicht entfernen + + + + Prefetch block si&ze + Block&größe für Prefetch + + + + SQ&L to execute after opening database + Nach dem Öffnen einer Datenbank auszuführendes SQ&L + + + + Default field type + Voreingestellter Feldtyp + + + + Data &Browser + Daten&auswahl + + + + Font + Schrift + + + + &Font + Schri&ft + + + + Content + Inhalt + + + + Symbol limit in cell + Symbolbegrenzung in Zelle + + + + NULL + NULL + + + + Regular + Normal + + + + Binary + Binär + + + + Background + Hintergrund + + + + Filters + Filter + + + + Threshold for completion and calculation on selection + Schwellwert für die Vervollständigung und Berechnung bei Auswahl + + + + Show images in cell + Bilder in Zelle anzeigen + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + Diese Option aktivieren, um eine Vorschau von BLOBs mit Bilddaten in den Zellen anzuzeigen. Dies kann allerdings die Performanz der Anwendung beeinflussen. + + + + Escape character + Escape-Zeichen + + + + Delay time (&ms) + Verzögerung (&ms) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + Verzögerung vor der Anwendung eines neuen Filters setzen. Kann auf 0 gesetzt werden, um dies zu deaktivieren. + + + + &SQL + &SQL + + + + Context + Kontext + + + + Colour + Farbe + + + + Bold + Fett + + + + Italic + Kursiv + + + + Underline + Unterstreichung + + + + Keyword + Schlüsselwort + + + + Function + Funktion + + + + Table + Tabelle + + + + Comment + Kommentar + + + + Identifier + Bezeichner + + + + String + String + + + + Current line + Aktuelle Zeile + + + + SQL &editor font size + SQL-&Editor-Schriftgröße + + + + Tab size + Tab-Größe + + + + SQL editor &font + SQL-Editor-&Schrift + + + + Error indicators + Fehleranzeige + + + + Hori&zontal tiling + Hori&zontale Anordnung + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + Im aktivierten Zustand werden der SQL-Codeeditor und die Ergebnistabelle neben- statt untereinander angezeigt. + + + + Code co&mpletion + &Codevervollständigung + + + + Toolbar style + Werkzeugleisten-Stil + + + + + + + + Only display the icon + Nur das Symbol anzeigen + + + + + + + + Only display the text + Nur den Text anzeigen + + + + + + + + The text appears beside the icon + Der Text erscheint neben dem Symbol + + + + + + + + The text appears under the icon + Der Text erscheint unter dem Symbol + + + + + + + + Follow the style + Dem Stil folgen + + + + DB file extensions + DB-Dateierweiterungen + + + + Manage + Verwalten + + + + Main Window + Hauptfenster + + + + Database Structure + Datenbankstruktur + + + + Browse Data + Daten durchsuchen + + + + Execute SQL + SQL ausführen + + + + Edit Database Cell + Datenbankzelle bearbeiten + + + + When this value is changed, all the other color preferences are also set to matching colors. + Wenn dieser Wert geändert wird, werden alle anderen Farbeinstellungen auch auf die entsprechenden Farben gesetzt. + + + + Follow the desktop style + Dem Desktop-Stil folgen + + + + Dark style + Dunkler Stil + + + + Application style + Anwendungsstil + + + + This sets the font size for all UI elements which do not have their own font size option. + Dies setzt die Schriftgröße für alle GUI-Elemente, die keine eigene Einstellung für die Schriftgröße besitzen. + + + + Font size + Schriftgröße + + + + Max Recent Files + Maximale Anzahl zuletzt geöffneter Dateien + + + + Prompt to save SQL tabs +in new project file + Dialog zum Speichern von SQL-Tabs +in einer neuen Projektdatei + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + Wenn dies aktiviert ist, dann erzeugen Änderungen am SQL-Editor-Tab beim Schließen des Tabs einen Bestätigungsdialog zum Speichern als Projekt. + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + Wenn aktiviert, werden die Zeilenumbrüche in der Schemaspalte des DB-Strukturtabs, Docks und der gedruckten Ausgabe entfernt. + + + + Database structure font size + Schriftgröße in Datenbankstruktur + + + + Font si&ze + Schrift&größe + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + Dies ist die maximale Elementanzahl, die für die Aktivierung einiger rechenintensiver Funktionalitäten erlaubt ist: +Maximale Zeilenanzahl in einer Tabelle für die Wertvervollständigung basierend auf den aktuellen Werten in dieser Spalte. +Maximale Indexanzahl in einer Auswahl für die Berechnung von Summe und Durchschnitt. +Kann auf 0 gesetzt werden, um diese Funktionalitäten zu deaktivieren. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + Dies ist die maximale Anzahl an Zeilen in einer Tabelle, die zur Wertvervollständigung basierend auf aktuellen Werten in dieser Spalte erlaubt ist. +Kann auf 0 gesetzt werden, um die Vervollständigung zu deaktivieren. + + + + Field display + Feldanzeige + + + + Light style + Heller Stil + + + + Displayed &text + Angezeigter &Text + + + + Formatted + Formatiert + + + + + + + + + + + Click to set this color + Zur Auswahl der Farbe klicken + + + + Text color + Textfarbe + + + + Background color + Hintergrundfarbe + + + + + Preview only (N/A) + Nur Vorschau (N/A) + + + + Foreground + Vordergrund + + + + Selection background + Hintergrund einer Auswahl + + + + Selection foreground + Vordergrund einer Auswahl + + + + Highlight + Hervorhebung + + + + SQL &results font size + Schriftgröße der SQL-&Ergebnisse + + + + Use tabs for indentation + Tabulatoren zur Einrückung verwenden + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + Wenn aktiviert, dann wird die Tabulator-Taste Tabulatoren und Leerzeichen zur Einrückung einfügen. Ansonsten werden lediglich Leerzeichen verwendet. + + + + &Wrap lines + Zeilen &umbrechen + + + + Never + Nie + + + + At word boundaries + An Wortgrenzen + + + + At character boundaries + An Zeichengrenzen + + + + At whitespace boundaries + An Leerzeichengrenzen + + + + &Quotes for identifiers + &Anführungszeichen für Identifiers + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + Wählen Sie den Zitiermechanismus aus, der von der Anwendung für Identifier im SQL-Code verwendet wird. + + + + "Double quotes" - Standard SQL (recommended) + "Doppelte Anführungszeichen" - Standard-SQL (empfohlen) + + + + `Grave accents` - Traditional MySQL quotes + `Akzente` - Traditionelle MySQL-Anführungszeichen + + + + [Square brackets] - Traditional MS SQL Server quotes + [Eckige Klammern] - Traditionelle MS-SQL-Server-Anführungszeichen + + + + Keywords in &UPPER CASE + Schlüsselwörter in &GROẞSCHREIBUNG + + + + When set, the SQL keywords are completed in UPPER CASE letters. + Wenn gesetzt, werden die SQL-Schlüsselwörter in GROẞSCHREIBUNG vervollständigt. + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + Wenn gesetzt, werden die SQL-Codezeilen, die während der letzten Ausführung Fehler verursacht haben, hervorgehoben und das Ergebnisfenster zeigt den Fehler im Hintergrund an + + + + Close button on tabs + Schließen-Button für Tabs + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + Wenn aktiviert, werden die SQL-Editor-Tabs einen Schließen-Button haben. In jedem Fall können Sie zum Schließen auch das Kontextmenü oder die Tastenkombination verwenden. + + + + &Extensions + &Erweiterungen + + + + Select extensions to load for every database: + Bei jeder Datenbank zu ladende Erweiterungen auswählen: + + + + Add extension + Erweiterung hinzufügen + + + + Remove extension + Erweiterung entfernen + + + + Select built-in extensions to load for every database: + Bei jeder Datenbank zu ladende eingebaute Erweiterungen auswählen: + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>Auch wenn der REGEXP-Operator unterstützt wird, implementiert SQLite keinerlei Algorithmus für reguläre<br/>Ausdrücke, sondern leitet diese an die laufende Anwendung weiter. DB-Browser für SQLite implementierte diesen<br/>Algorithmus für Sie, um REGEXP ohne Zusätze verwenden zu können. Allerdings gibt es viele mögliche<br/>Implementierungen und Sie möchten unter Umständen eine andere wählen, dann können Sie die<br/>Implementierung der Anwendung deaktivieren und Ihre eigene durch Laden einer Erweiterung verwenden. Ein Neustart der Anwendung ist notwendig.</p></body></html> + + + + Disable Regular Expression extension + Erweiterung für reguläre Ausdrücke deaktivieren + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite bietet eine SQL-Funktion an, um Erweiterungen aus einer Shared-Library-Datei zu laden. Aktivieren Sie dies, wenn Sie die Funktion <span style=" font-style:italic;">load_extension()</span> aus SQL-Code heraus benutzen möchten.</p><p>Aus Sicherheitsgründen ist das Laden von Erweiterungen standardmäßig deaktiviert und muss durch diese Einstellung aktiviert werden. Sie können alternativ immer die gewünschten Erweiterungen über die GUI laden, auch wenn diese Option deaktiviert ist.</p></body></html> + + + + Allow loading extensions from SQL code + Laden von Erweiterungen aus SQL-Code erlauben + + + + Remote + Entfernt + + + + CA certificates + CA-Zertifikate + + + + Proxy + Proxy + + + + Configure + Konfigurieren + + + + Export Settings + Einstellungen exportieren + + + + Import Settings + Einstellungen importieren + + + + + Subject CN + Subject CN + + + + Common Name + Common Name + + + + Subject O + Subject O + + + + Organization + Organisation + + + + + Valid from + Gültig ab + + + + + Valid to + Gültig bis + + + + + Serial number + Seriennummer + + + + Your certificates + Ihre Zertifikate + + + + File + Datei + + + + Subject Common Name + Subject Common Name + + + + Issuer CN + CN des Ausstellers + + + + Issuer Common Name + Common Name des Ausstellers + + + + Clone databases into + Datenbank klonen nach + + + + + Choose a directory + Verzeichnis wählen + + + + + The language will change after you restart the application. + Die Sprache wird nach einem Neustart der Anwendung geändert. + + + + Select extension file + Erweiterungsdatei wählen + + + + Extensions(*.so *.dylib *.dll);;All files(*) + Erweiterungen(*.so *.dylib *.dll);;Alle Dateien(*) + + + + Import certificate file + Zertifikatsdatei importieren + + + + No certificates found in this file. + In dieser Datei wurden keine Zertifikate gefunden. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + Soll dieses Zertifikat wirklich entfernt werden? Alle Zertifikatsdaten werden aus den Anwendungseinstellungen gelöscht! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + Möchten Sie wirklich alle gespeicherten Einstellungen löschen? +Alle Ihre Einstellungen gehen dadurch verloren und die Standardwerte werden verwendet. + + + + Save Settings File + Einstellungsdatei speichern + + + + + Initialization File (*.ini) + Initialisierungsdatei (*.ini) + + + + The settings file has been saved in location : + + Die Einstellungsdatei wurde gespeichert unter: + + + + + Open Settings File + Einstellungsdatei öffnen + + + + The settings file was loaded properly. + Die Einstellungsdatei wurde korrekt geladen. + + + + The selected settings file is not a normal settings file. +Please check again. + Die ausgewählte Einstellungsdatei ist keine normale Einstellungsdatei. +Bitte erneut prüfen. + + + + ProxyDialog + + + Proxy Configuration + Proxy-Konfiguration + + + + Pro&xy Type + Pro&xy-Typ + + + + Host Na&me + Hostna&me + + + + Port + Port + + + + Authentication Re&quired + Anmeldung not&wendig + + + + &User Name + &Benutzername + + + + Password + Passwort + + + + None + Keiner - - SQLite Version - SQLite-Version + + System settings + Systemeinstellungen - - <html><head/><body><p>SQLite Database Browser is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:small;">It also uses the Silk icon set by Mark James licensed under a Creative Commons Attribution 2.5 and 3.0 license.<br/>See </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> - <html><head/><body><p>SQLite Database Browser ist ein grafisches, freies Open Source Tool zum Erstellen, Bearbeiten und Ändern von SQLite-Datenbankdateien.</p><p>Es steht unter zwei Lizenzen, der Mozilla Public License Version 2 und der GNU General Public License Version 3 oder aktueller. Sie können das Programm unter den Bedingungen dieser Lizenzen ändern und weitergeben.</p><p>Siehe <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> und <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> für Details.</p><p>Für mehr Informationen über dieses Programm besuchen Sie unsere Website unter: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">Diese Anwendung verwendet das GPL/LGPL Qt Toolkit von </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>Siehe </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> für Lizenzinformationenund weitere Informationen.</span></p><p><span style=" font-size:small;">Sie verwendet außerdem das Silk iconset von Mark James, das unter einer Creative Commons Attribution 2.5 und 3.0 Lizenz steht.<br/>Siehe </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> für Details.</span></p></body></html> + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 - Application + QObject - - Usage: %1 [options] [db] - - Verwendung: %1 [Optionen] [db] - + + Error importing data + Fehler beim Datenimport - - Possible command line arguments: - Mögliche Kommandozeilen-Argumente: + + from record number %1 + von Zeilennummer %1 - - -h, --help Show command line options - -h, --help Kommandozeilen-Optionen anzeigen + + . +%1 + . +%1 - - -s, --sql [file] Execute this SQL file after opening the DB - -s, --sql [Datei] Führe diese SQL-Datei nach dem Öffnen der DB aus + + Importing CSV file... + CSV-Datei importieren... - - -q, --quit Exit application after running scripts - -q, --quit Beende die Anwendung nach der Ausführung der Skripte + + Cancel + Abbrechen - - [file] Open this SQLite database - [Datei] Diese SQLite-Datenbank öffnen + + All files (*) + Alle Dateien (*) - - The -s/--sql option requires an argument - Die -s/--sql Option benötigt ein Argument + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + SQLite Datenbankdateien (*.db *.sqlite *.sqlite3 *.db3) - - The file %1 does not exist - Die Datei %1 existiert nicht + + Left + Links + + + + Right + Rechts + + + + Center + Zentriert + + + + Justify + Blocksatz + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + SQLite-Datenbankdateien (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + DB-Browser für SQLite-Projektdateien (*.sqbpro) + + + + SQL Files (*.sql) + SQL-Dateien (*.sql) + + + + All Files (*) + Alle Dateien (*) + + + + Text Files (*.txt) + Text-Dateien (*.txt) + + + + Comma-Separated Values Files (*.csv) + Kommaseparierte Datendateien (*.csv) + + + + Tab-Separated Values Files (*.tsv) + Tabulator-separierte Datendateien (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + Trennzeichen-separierte Datendateien (*.dsv) + + + + Concordance DAT files (*.dat) + Konkordanz DAT-Dateien (*.dat) + + + + JSON Files (*.json *.js) + JSON-Dateien (*.json *.js) + + + + XML Files (*.xml) + XML-Dateien (*.xml) + + + + Binary Files (*.bin *.dat) + Binärdateien (*.bin *.dat) + + + + SVG Files (*.svg) + SVG-Dateien (*.svg) + + + + Hex Dump Files (*.dat *.bin) + Hex-Dump-Dateien (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + Erweiterungen (*.so *.dylib *.dll) - - Invalid option/non-existant file: %1 - Ungültige Option/nicht existente Datei: %1 + + Initialization File (*.ini) + Initialisierungsdatei (*.ini) - CreateIndexDialog + QsciCommand - - Create New Index - Neuen Index erstellen + Paste + Einfügen - - &Name - &Name + Cancel + Abbrechen + + + + QsciLexerCPP + + Default + Voreinstellung - - &Columns - &Spalten + Keyword + Schlüsselwort - - Column - Spalte + Identifier + Bezeichner + + + QsciLexerJSON - - Use in Index - Im Index verwenden + Default + Voreinstellung - - Order - Sortierung + String + String + + + QsciLexerJavaScript - - &Table - &Tabelle + Regular expression + Regulärer Ausdruck + + + QsciLexerPython - - &Unique - &Eindeutig + Default + Voreinstellung - - Creating the index failed: -%1 - Erstellen des Index fehlgeschlagen: -%1 + Comment + Kommentar + + + Keyword + Schlüsselwort + + + Identifier + Bezeichner - DbStructureModel + QsciLexerSQL - - Name - Name + Default + Voreinstellung - - Object - Objekt + Comment + Kommentar - - Type - Typ + Keyword + Schlüsselwort - - Schema - Schema + Identifier + Bezeichner + + + QsciScintilla - - Tables (%1) - Tabellen (%1) + &Undo + &Zurücksetzen - - Indices (%1) - Indizes (%1) + Select All + Alle auswählen + + + + RemoteCommitsModel + + + Commit ID + Commit-ID - - Views (%1) - Aufrufe (%1) + + Message + Mitteilung - - Triggers (%1) - Trigger (%1) + + Date + Datum + + + + Author + Autor + + + + Size + Größe + + + + Authored and committed by %1 + Erstellt und übermittelt von %1 + + + + Authored by %1, committed by %2 + Erstellt von %1, übermittelt von %2 - EditDialog + RemoteDatabase - - Edit database cell - Datenbank-Zelle bearbeiten + + Error opening local databases list. +%1 + Fehler beim Öffnen der lokalen Datenbankliste. +%1 - - Import text - Text importieren + + Error creating local databases list. +%1 + Fehler beim Erstellen der lokalen Datenbankliste. +%1 + + + RemoteDock - - Opens a file dialog used to import text to this database cell. - Öffnet einen Dateiauswahldialog, um Text in diese Datenbank-Zelle zu importieren. + + Remote + Entfernt - - &Import - &Importieren + + Local + Lokal - - Export text - Text exportieren + + Identity + Identität - - Opens a file dialog used to export the contents of this database cell to a text file. - Öffnet einen Dateiauswahldialog, um den Inhalt dieser Datenbank-Zelle in eine Textdatei zu exportieren. + + Push currently opened database to server + Aktuell geöffnete Datenbank an den Server übertragen - - &Export - &Exportieren + + Upload + Hochladen - - Text - Text + + DBHub.io + DBHub.io - - Binary - Binär + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>In diesem Fensterbereich können entfernte Datenbanken von der Webseite dbhub.io zu DB-Browser für SQLite hinzugefügt werden. Zunächst benötigen Sie eine Identität:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Melden Sie sich auf der Webseite dbhub.io an (unter Verwendung Ihrer GitHub-Daten oder wie gewünscht)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Klicken Sie auf den Button &quot;Generate client certificate&quot;, um ein Zertifikat zu erstellen (das ist Ihre Identität). Speichern Sie die erzeugte Zertifikatsdatei auf ihrer lokalen Festplatte.</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Öffnen Sie den Entfernt-Tab in den DB-Browser für SQLite-Einstellungen. Klicken Sie auf den Button, um ein neues Zertifikat hinzuzufügen und wählen Sie die soeben heruntergeladene Zertifikatsdatei aus.</li></ol><p>Jetzt zeigt der Entfernt-Fensterbereich Ihre Identität und Sie können entfernte Datenbanken hinzufügen.</p></body></html> - - Clear cell data - Zelldaten löschen + + Current Database + Aktuelle Datenbank - - Erases the contents of the cell - Löscht den Inhalt der Zelle + + Clone + Klonen - - &Clear - &Leeren + + Branch + Branch - - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Warning: Editing binary content in text mode may result in corrupted data!</span></p></body></html> - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Warnung: Das Bearbeiten von Binärdaten im Textmodus produziert eventuell ungültige Daten!</span></p></body></html> + + Commits + Commits - - This area displays information about the data present in this database cell - Dieser Bereich stellt Informationen über die Daten in dieser Datenbank-Zelle dar + + Commits for + Commits für - - Type of data currently in cell - Art der Daten in dieser Zelle + + Delete Database + Datenbank löschen - - Size of data currently in table - Größe der Daten in dieser Tabelle + + Delete the local clone of this database + Den lokalen Klon der Datenbank löschen - - Choose a file - Datei auswählen + + Open in Web Browser + Im Webbrowser öffnen - - Text files(*.txt);;Image files(%1);;All files(*) - Text-Dateien(*.txt);;Bild-Dateien(%1);;Alle Dateien(*) + + Open the web page for the current database in your browser + Die Webseite der aktuellen Datenbank im Webbrowser öffnen - - Choose a filename to export data - Einen Dateinamen für den Datenexport auswählen + + Clone from Link + Über Link klonen - - Text files(*.txt);;All files(*) - Text-Dateien(*.txt);;Alle Dateien(*) + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + Diese Option verwenden, um eine entfernte Datenbank für die lokale Bearbeitung mittels einer URL herunterzuladen, wie sie auf der Webseite der Datenbank angegeben ist. - - Type of data currently in cell: Text / Numeric - Art der Daten in dieser Zelle: Text / Numerisch + + Refresh + Aktualisieren - - %n char(s) - %n Zeichen + + Reload all data and update the views + Alle Daten erneut laden und die Ansichten aktualisieren - - Type of data currently in cell: Image - Art der Daten in dieser Zelle: Bild + + Clone Database + Datenbank klonen - - %1x%2 pixel - %1x%2 Pixel + + Open Database + Datenbank öffnen - - Type of data currently in cell: Binary - Art der Daten in dieser Zelle: Binär + + Open the local copy of this database + Die lokale Kopie dieser Datenbank öffnen - - %n byte(s) - %n Byte(s) + + Check out Commit + Commit auschecken - - - EditTableDialog - - Edit table definition - Tabellen-Definition bearbeiten + + Download and open this specific commit + Diesen spezifischen Commit herunterladen und öffnen - - Table - Tabelle + + Check out Latest Commit + Letzten Commit auschecken - - Fields - Felder + + Check out the latest commit of the current branch + Den letzten Commit des aktuellen Branchs auschecken - - Add field - Feld hinzufügen + + Save Revision to File + Revision in Datei speichern - - Remove field - Feld entfernen + + Saves the selected revision of the database to another file + Speichert die ausgewählte Revision der Datenbank in einer anderen Datei - - Move field up - Feld nach oben verschieben + + Upload Database + Datenbank hochladen - - Move field down - Feld nach unten verschieben + + Upload this database as a new commit + Diese Datenbank als neuen Commit hochladen - - Name - Name + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>Aktuell wird eine eingebaute, nur lesend verwendbare Identität verwendet. Zum Hochladen einer Datenbank muss ein DBHub.io-Konto konfiguriert und verwendet werden.</p><p>Noch kein DBHub.io-Konto vorhanden? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Jetzt ein Konto erstellen</span></a> und das Zertifikat <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">hier</span></a> hochladen, um Datenbanken zu teilen.</p><p>Eine englische Online-Hilfe ist <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">hier</span></a> verfügbar.</p></body></html> - - Type - Typ + + &User + Ben&utzer - - - Not null - Nicht Null + + &Database + &Datenbank - - PK - PK + + Back + Zurück - - Primary key - Primärschlüssel + + Select an identity to connect + Eine Identität zum Verbinden auswählen - - AI - AI + + Public + Öffentlich - - Autoincrement - Autoinkrement + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + Dies lädt eine Datenbank zur lokalen Bearbeitung von einem entfernten Server herunter. +Bitte die URL zum Klonen eingeben. Die URL kann durch +Klicken des Buttons 'Clone Database in DB4S' auf der Webseite +der Datenbank generiert werden. - - Default - Voreinstellung + + Invalid URL: The host name does not match the host name of the current identity. + Ungültige URL: Der Hostname entspricht nicht dem Hostnamen der aktuellen Identität. - - Default value - Voreingestellter Wert + + Invalid URL: No branch name specified. + Ungültige URL: Kein Branch-Name gesetzt. - - Check - Prüfen + + Invalid URL: No commit ID specified. + Ungültige URL: Keine Commit-ID gesetzt. - - Check constraint - Beschränkung prüfen + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + Der lokale Klon der Datenbank enthält Änderungen. Das Holen dieses Commits überschreibt die lokalen Änderungen. +Soll wirklich fortgefahren werden? - - Error creating table. Message from database engine: -%1 - Fehler beim Erstellen der Tabelle. Meldung der Datenbank: -%1 + + The database has unsaved changes. Are you sure you want to push it before saving? + Die Datenbank besitzt ungespeicherte Änderungen. Soll diese wirklich vor dem Speicher hochgeladen werden? - - There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. - Mindestens eine Reihe enthält ein Feld mit dem Wert NULL. Dies verhindert das Setzen dieser Markierung. Bitte zuerst die Tabellen-Daten ändern. + + The database you are trying to delete is currently opened. Please close it before deleting. + Die zu löschende Datenbank ist aktuell geöffnet. Bitte vor dem Löschen schließen. - - There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. - Mindestens eine Reihe enthält ein Feld mit einem nicht ganzzahligen Wert. Dies verhindert das Setzen der AI-Markierung. Bitte zuerst die Tabellen-Daten ändern. + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + Dies löscht die lokale Version der Datenbank mit allen Änderungen, die noch nicht übermittelt wurden. Soll diese Datenbank wirklich gelöscht werden? + + + RemoteLocalFilesModel - - Are you sure you want to delete the field '%1'? -All data currently stored in this field will be lost. - Soll das Feld '%1' wirklich gelöscht werden? -Alle aktuell in diesem Feld gespeicherten Daten gehen verloren. + + Name + Name + + + + Branch + Branch + + + + Last modified + Letzte Änderung + + + + Size + Größe + + + + Commit + Commit + + + + File + Datei - ExportCsvDialog + RemoteModel - - Export data as CSV - Daten als CSV exportieren + + Name + Name - - &Table - &Tabelle + + Last modified + Letzte Änderung - - &Column names in first line - &Spaltennamen in erster Zeile + + Size + Größe - - Field &separator - Feld-Separator + + Commit + Commit - - , - , + + Size: + Größe: - - ; - ; + + Last Modified: + Letzte Änderung: - - - Tab - Tab + + Licence: + Lizenz: - - | - | + + Default Branch: + Standard-Branch: + + + RemoteNetwork - - - Other - Anderer + + Choose a location to save the file + Ort zum Speichern der Datei wählen - - &Quote character - &String-Zeichen + + Error opening remote file at %1. +%2 + Fehler beim Öffnen der entfernten Datei unter %1. +%2 - - " - " + + Error: Invalid client certificate specified. + Fehler: Ungültiges Benutzerzertifikat angegeben. - - ' - ' + + Please enter the passphrase for this client certificate in order to authenticate. + Bitte die Passphrase für dieses Benutzerzertifikat eingeben, um die Authentifizierung durchzuführen. - - Choose a filename to export data - Einen Dateinamen für den Datenexport wählen + + Cancel + Abbrechen - - Text files(*.csv *.txt) - Text-Dateien(*.csv *.txt) + + Uploading remote database to +%1 + Entfernte Datenbank wird hochgeladen zu +%1 - - Export completed. - Export abgeschlossen. + + Downloading remote database from +%1 + Entfernte Datenbank wird heruntergeladen von +%1 - - Could not open output file. - Ausgabedatei konnte nicht geöffnet werden. + + Error: Cannot open the file for sending. + Fehler: Öffnen der Datei zum Senden nicht möglich. - FilterTableHeader + RemotePushDialog - - Filter - Filtern + + Push database + Datenbank übertragen - - - ImportCsvDialog - - Import CSV file - CSV-Datei importieren + + Database na&me to push to + Datenbankna&me am Zielort - - &Table name - &Tabellen-Name + + Commit message + Commit-Nachricht - - &Column names in first line - &Spaltennamen in erster Zeile + + Database licence + Datenbanklizenz - - Field &separator - Feld-Separator + + Public + Öffentlich - - , - , + + Branch + Branch - - ; - ; + + Force push + Push erzwingen - - - Tab - Tab + + Username + Benutzername - - | - | + + Database will be public. Everyone has read access to it. + Datenbank wird öffentlich sein. Jeder hat Lesezugriff darauf. - - - Other - Anderer + + Database will be private. Only you have access to it. + Datenbank wird privat sein. Nur Sie haben Zugriff darauf. - - &Quote character - &String-Zeichen + + Use with care. This can cause remote commits to be deleted. + Verwenden Sie dies mit Vorsicht. Dadurch können entfernte Commits gelöscht werden. + + + RunSql - - " - " + + Execution aborted by user + Ausführung durch Benutzer abgebrochen - - ' - ' + + , %1 rows affected + , %1 Zeilen betroffen - - Inserting data... - Füge Daten ein... + + query executed successfully. Took %1ms%2 + Abfrage erfolgreich ausgeführt. Benötigte %1 ms %2 - - Cancel - Abbrechen + + executing query + führe Abfrage aus + + + SelectItemsPopup - - There is already a table of that name and an import into an existing table is only possible if the number of columns match. - Es gibt bereits eine Tabelle mit diesem Namen. Ein Import in eine existierende Tabelle ist nur bei übereinstimmender Spaltenanzahl möglich. + + A&vailable + &Verfügbar - - There is already a table of that name. Do you want to import the data into it? - Es gibt bereits eine Tabelle mit diesem Namen. Sollen die Daten in diese importiert werden? + + Sele&cted + &Ausgewählt - MainWindow + SqlExecutionArea - - SQLiteBrowser - SQLiteBrowser + + Form + Formular - - Database &Structure - Datenbank&struktur + + Find previous match [Shift+F3] + Vorherige Übereinstimmung finden [Umschalt+F3] - - - toolBar1 - Toolbar1 + + Find previous match with wrapping + Vorherige Übereinstimmung mit Mapping finden - - &Browse Data - &Daten durchsuchen + + Shift+F3 + - - Table: - Tabelle: + + The found pattern must be a whole word + Das Muster muss ein ganzes Wort sein - - Select a table to browse data - Anzuzeigende Tabelle auswählen + + Whole Words + Ganze Wörter - - Use this list to select a table to be displayed in the database view - Mit dieser Liste können Sie die in der Tabllenansicht anzuzeigende Tabelle auswählen + + Text pattern to find considering the checks in this frame + Zu findendes Textmuster unter Einbeziehung der Prüfungen in diesem Fenster - - Refresh the data in the selected table. - Aktualisiert die angezeigten Tabellendaten. + + Find in editor + Im Editor finden - - This button refreshes the data in the currently selected table. - Dieser Button aktualisiert die Daten der aktuellen Tabellenansicht. + + The found pattern must match in letter case + Das gefundene Muster muss in Groß-/Kleinschreibung übereinstimmen - - - F5 - F5 + + Case Sensitive + Schreibungsabhängig - - Insert a new record in the current table - Fügt eine neue Zeile zur aktuellen Tabelle hinzu + + Find next match [Enter, F3] + Nächste Übereinstimmung finden [Enter, F3] - - This button creates a new, empty record in the database - Dieser Button erzeugt eine neue, leere Zeile in der Tabelle + + Find next match with wrapping + Nächste Übereinstimmung mit Umbruch finden - - New Record - Neue Zeile + + F3 + - - Delete the current record - Aktuelle Zeile löschen + + Interpret search pattern as a regular expression + Suchmuster als regulären Ausdruck interpretieren + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Wenn aktiviert, wird das Suchmuster als regulärer Ausdruck (UNIX-Stil) interpretiert. Siehe <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks (englisch)</a>.</p></body></html> + + + + Regular Expression + Regulärer Ausdruck + + + + + Close Find Bar + Suchbar schließen + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>Ergebnisse der zuletzt ausgeführten Anweisungen.</p><p>Dieses Panel kann zusammengeklappt und stattdessen der Dock <span style=" font-style:italic;">SQL-Protokoll</span> mit der Auswahl <span style=" font-style:italic;">Benutzer</span> verwendet werden.</p></body></html> + + + + Results of the last executed statements + Ergebnisse der zuletzt ausgeführten Anweisungen - - This button deletes the record currently selected in the database - Dieser Button löscht die aktuell in der Tabellenansicht ausgewählte Zeile + + This field shows the results and status codes of the last executed statements. + Dieses Feld zeigt die Ergebnisse und Statuscodes der zuletzt ausgeführten Anweisungen. - - Delete Record - Zeile löschen + + Ctrl+PgUp + - - This is the database view. You can double-click any record to edit its contents in the cell editor window. - Dies ist die Tabellenansicht. Mit einem Doppelklick auf eine Zelle können Sie ihren Inhalt in einem Editorfenster bearbeiten. + + Ctrl+PgDown + - - < - < + + Couldn't read file "%1": %2. + Datei "%1" konnte nicht gelesen werden: %2. - - 0 - 0 of 0 - 0 - 0 von 0 + + + Couldn't save file: %1. + Datei konnte nicht gespeichert werden: %1. - - > - > + + Your changes will be lost when reloading it! + Beim Neuladen gehen die Änderungen verloren! - - Scroll 100 records upwards - 100 Zeilen nach oben scrollen + + The file "%1" was modified by another program. Do you want to reload it?%2 + Die Datei "%1" wurde durch ein anderes Programm geändert. Soll es neu geladen werden?%2 - - <html><head/><body><p>Clicking this button navigates 100 records upwards in the table view above.</p></body></html> - <html><head/><body><p>Ein Klick auf diesen Button wechselt die Tabellenansicht um 100 Einträge nach oben.</p></body></html> + + Answer "Yes to All" to reload the file on any external update without further prompting. + Mit "Ja für Alle" antworten, um die Datei für jedes externe Update ohne weiteren Dialog neu zu laden. - - <html><head/><body><p>Scroll 100 records downwards</p></body></html> - <html><head/><body><p>100 Zeilen nach unten scrollen</p></body></html> + + Answer "No to All" to ignore any external update without further prompting. + Mit "Nein für Alle" antworten, um alle externen Updates ohne weitere Dialoge zu ignorieren. - - <html><head/><body><p>Clicking this button navigates 100 records downwards in the table view above.</p></body></html> - <html><head/><body><p>Ein Klick auf diesen Button wechselt die Tabellenansicht um 100 Einträge nach unten.</p></body></html> + + Modifying and saving the file will restore prompting. + Das Ändern und Speichern der Datei wird die Dialoge reaktivieren. + + + SqlTextEdit - - <html><head/><body><p>Click here to jump to the specified record</p></body></html> - <html><body><p>Klicke hier, um zu einer bestimmten Zeile zu springen</p></body></html> + + Ctrl+/ + + + + SqlUiLexer - - <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> - <html><body><p>Dieser Button kann zum Navigieren zu einer im "Springe zu"-Bereich festgelegten Zeile verwendet werden.</p></body></html> + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) Die Funktion abs(X) gibt einen absoluten Wert des numerischen Arguments X zurück. - - Go to: - Springe zu: + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () Die Funktion changes() gibt die Anzahl der Datenbankzeilen zurück, die mit der zuletzt abgeschlossenen INSERT-, DELETE- oder UPDATE-Anweisung geändert, eingefügt oder gelöscht worden sind. - - Enter record number to browse - Zeilennummern zum Suchen auswählen + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) Die Funktion char(X1,X2,...,XN) gibt eine Zeichenkette zurück, die aus den Zeichen der Unicode-Werte der Ganzzahlen X1 bis XN zusammengesetzt ist. - - Type a record number in this area and click the Go to: button to display the record in the database view - Eine Zeilennummer in diesem Bereich eingeben und auf den "Springe zu:"-Button klicken, um die Zeile in der Datenbankansicht anzuzeigen + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) Die Funktion coalesce() gibt eine Kopie des ersten Nicht-NULL-Arguments zurück, oder NULL wenn alle Argumente NULL sind - - 1 - 1 + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) Die Funktion glob(X,Y) ist äquivalent zum Ausdruck "Y GLOB X". - - Edit &Pragmas - &Pragmas bearbeiten + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) Die Funktion ifnull() gibt eine Kopie des ersten Nicht-NULL-Arguments zurück, oder NULL, wenn beide Argumente NULL sind. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline, color:#0000ff;">Auto Vacuum</span></a></p></body></html> + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) Die Funktion instr(X,Y) sucht das erste Auftreten von Zeichenkette Y innerhalb der Zeichenkette X und gibt die Anzahl vorhergehender Charakter plus 1 zurück, oder 0, wenn Y in X nicht gefunden werden konnte. - - None - Nichts + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) Die Funktion hex() interpretiert ihr Argument als BLOB und gibt eine Zeichenkette zurück, die die Hexadezimaldarstellung des Blob-Inhaltes in Großbuchstaben enthält. - - - Full - Vollständig + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) Die Funktion iif(X,Y,Z) gibt den Wert Y zurück, wenn X true ist, ansonsten Z. - - Incremental - Inkrementell + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () Die Funktion last_insert_rowid() gibt die ROWID der letzte Zeile zurück, die von der Datenbankverbindung eingefügt wurde und die dann die Funktion aufrief. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) Für eine Zeichenkette X gibt die Funktion length(X) die Anzahl der Zeichen (nicht Bytes) von X zurück, die sich vor dem ersten NUL-Zeichen befinden. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) Die Funktion like() wird als Implementierung des Ausdrucks "Y LIKE X" verwendet. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_key"><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></p></body></html> + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) Die Funktion like() wird als Implementierung des Ausdrucks "Y LIKE X ESCAPE Z" verwendet. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) Die Funktion load_extension(X) lädt SQLite-Erweiterungen aus der Shared-Library-Datei namens X. +Die Verwendung dieser Funktion muss in den Einstellungen autorisiert werden. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) Die Funktion load_extension(X,Y) lädt SQLite-Erweiterungen aus der Shared-Library-Datei namens X unter Verwendung des Eintrittspunktes Y. +Die Verwendung dieser Funktion muss in den Einstellungen autorisiert werden. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Model</span></a></p></body></html> + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) Die Funktion lower(X) gibt eine Kopie der Zeichenkette X mit allen ASCII-Zeichen in Kleinschreibung zurück. - - Delete - Löschen + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) entfernt Leerzeichen aus der linken Seite von X. - - Truncate - Kürzen + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) Die Funktion ltrim(X,Y) gibt eine Zeichenkette zurück, die durch Entfernen aller Zeichen innerhalb von Y aus der linken Seite von X gebildet wird. - - Persist - Behalten + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) Die Funktion max() mit mehreren Argumenten gibt das Argument mit dem größten Wert zurück, oder NULL, wenn ein Argument NULL ist. - - - Memory - Speicher + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) Die Funktion max() mit mehreren Argumenten gibt das Argument mit dem kleinsten Wert zurück. - - WAL - WAL + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) Die Funktion nullif(X,Y) gibt ihr erstes Argument zurück, wenn die Argumente verschieden sind und NULL, wenn die Argumente gleich sind. - - - Off - Aus + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) Die printf(FORMAT,...) SQL-Funktion arbeitet wie die C-Funktion sqlite3_mprintf() und die Funktion printf() aus der C-Standardbibliothek. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> - <html><head/><body><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body><html> + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) Die Funktion quote(X) gibt den Text eines SQL-Literals zurück, wobei der Wert des Arguments zum Einfügen in eine SQL-Anweisung geeignet ist. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a><p></body></html> + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () Die Funktion random() gibt eine pseudozufällige Ganzzahl zwischen -9223372036854775808 und +9223372036854775807 zurück. - - - Normal - Normal + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) Die Funktion randomblob(N) gibt einen N-Byte Blob aus pseudozufälligen Bytes zurück. - - Exclusive - Exklusiv + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) Die Funktion replace(X,Y,Z) gibt einen String zurück, der durch Ersetzen der Zeichenkette Z bei jedem Auftreten von Zeichenkette Y in Zeichenkette X gebildet wird. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) Die Funktion round(X) gibt einen Gleitkommawert X auf null Nachkommastellen gerundet zurück. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) Die Funktion round(X,Y) gibt eine Gleitkommazahl X auf Y Nachkommastellen gerundet zurück. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X) entfernt Leerzeichen aus der rechten Seite von X. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) Die Funktion rtrim(X,Y) gibt eine Zeichenkette zurück, die durch Entfernen aller Zeichen innerhalb von Y aus der rechten Seite von X gebildet wird. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) Die Funktion soundex(X) gibt eine Zeichenkette zurück, die aus der Soundex-Codierung von Zeichenkette X besteht. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) substr(X,Y) gibt alle Zeichen bis zum Ende der Zeichenkette X zurück, beginnend mit dem Y-ten. - - Default - Voreinstellung + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) Die Funktion substr(X,Y) gibt einen Teil der Zeichenkette X zurück, die mit dem Y-ten Zeichen beginnt und Z Zeichen lang ist. - - File - Datei + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () Die Funktion changes() gibt die Anzahl der geänderten Datenbankzeilen zurück, die seit dem Öffnen der aktuellen Datenbankverbindung mit INSERT-, DELETE- oder UPDATE-Anweisung geändert, eingefügt oder gelöscht worden sind. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) entfernt Leerzeichen an beiden Enden von X. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) Die Funktion ltrim(X,Y) gibt eine Zeichenkette zurück, die durch Entfernen aller Zeichen innerhalb von Y aus der von beiden Seiten von X gebildet wird. - - E&xecute SQL - S&QL ausführen + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) Die Funktion typeof(X) gibt einen String zurück, der den Datentyp des Ausdrucks X angibt. - - &File - Da&tei + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) Die Funktion unicode(X) gibt einen numerischen Unicode-Wert zurück, der dem ersten Zeichen der Zeichenkette X entspricht. - - &Import - &Import + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) Die Funktion lower(X) gibt eine Kopie der Zeichenkette X mit allen ASCII-Zeichen in Großschreibung zurück. - - &Export - &Export + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) Die Funktion zeroblob(N) gibt einen BLOB aus N Bytes mit 0x00 zurück. - - &Edit - &Bearbeiten + + + + + (timestring,modifier,modifier,...) + (Zeitstring,Modifikation,Modifikation,...) - - &View - &Ansicht + + (format,timestring,modifier,modifier,...) + (Format,Zeitstring,Modifikation,Modifikation,...) - - &Help - &Hilfe + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) Die Funktion avg() gibt den Durchschnittswert alle Nicht-NULL-X in einer Gruppe zurück. - - toolBar - Toolbar + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) Die Funktion count(X) gibt die Anzahl der Nicht-NULL-Elemente von X in einer Gruppe zurück. - - SQL Log - SQL-Log + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) Die Funktion group_conact() gibt eine Zeichenkette zurück, die eine Verkettung aller Nicht-NULL-Werte von X ist. - - &Show SQL submitted by - Zeige SQL von + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) Die Funktion group_conact() gibt eine Zeichenkette zurück, die eine Verkettung aller Nicht-NULL-Werte von X ist. Wenn der Parameter Y aktiv ist, wird dieser als Trennzeichen zwischen Instanzen von X behandelt. - - User - Benutzer + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) Die Sammelfunktion max() gibt den Maximalwert aller Werte in der Gruppe zurück. - - Application - Anwendung + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) Die Sammelfunktion min() gibt den Minimalwert aller Nicht-NULL-Werte in der Gruppe zurück. - - &Clear - &Leeren + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) Die Sammelfunktionen sum() und total() geben die Summe aller Nicht-NULL-Werte in der Gruppe zurück. - - Plot - Anzeigen + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () Die Anzahl der Zeilen in der aktuellen Partition. Zeilen werden beginnend bei 1 in der durch den Befehl ORDER BY in der Fensterdefinition nummeriert, ansonsten in willkürlicher Reihenfolge. - - Columns - Spalten + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () Die row_number() des ersten Peer in jeder Gruppe - der Rang der aktuellen Zeile mit Lücken. Wenn es keinen Befehl ORDER BY gibt, dann werden alle Zeilen als Peers angesehen und diese Funktion gibt immer 1 zurück. - - X - X + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () Die Nummer der Peer-Gruppe der aktuellen Zeile in der Partition - der Rang der aktuellen Reihe ohne Lücken. Partitionen werden mit 1 startend nummeriert in der Reihenfolge, wie sie durch den Befehl ORDER BY in der Fensterdefinition festgelegt ist. Wenn es keinen Befehl ORDER BY gibt, werden alle Zeilen als Peers angesehen und diese Funktion gibt immer 1 zurück. - - Y - Y + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () Ungeachtet des Namens gibt diese Funktion immer einen Wert zwischen 0.0 und 1.0 identisch zu (Rang - 1)/(Partitionszeilen - 1) zurück, wobei Rang der Wert der eingebauten Fensterfunktion rank() und Partitionszeilen die Gesamtanzahl der Zeilen in der Partition ist. Wenn die Partition nur eine Zeile enthält, gibt diese Funktion 0.0 zurück. - - _ - _ + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () Die kumulative Verteilung. Berechnet als Zeilenanzahl/Partitionszeilen, wobei Zeilenanzahl der durch row_number() zurückgegebene Wert für den letzten Peer in der Gruppe ist und Partitionszeilen die Anzahl der Zeilen in der Partition. - - Save current plot... - Aktuelle Anzeige speichern... + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) Das Argument N wird als Integer behandelt. Diese Funktion teilt die Partition in N Gruppen so gleichmäßig wie möglich auf und weist jeder Gruppe einen Integer zwischen 1 und N zu, in der Reihenfolge, die durch den Befehl ORDER BY definiert ist, ansonsten in beliebiger Reihenfolge. Wenn notwendig, tauchen größere Gruppen als erstes auf. Diese Funktion gibt einen Integerwert zurück, der der Gruppe zugewiesen ist, zu der die aktuelle Zeile gehört. - - &New Database... - &Neue Datenbank... + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) Gibt das Ergebnis der Evaluation des Ausdrucks expr gegen die vorherige Zeile in der Partition zurück. Wenn es keine vorhergehende Zeile gibt (weil die aktuelle Zeile die erste ist), wird NULL zurückgegeben. - - - Create a new database file - Neue Datenbank-Datei erstellen + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr,offset) Wenn das Argument offset angegeben ist, dann muss dieses ein nichtnegativer Integerwert sein. In diesem Fall ist der Rückgabewert das Ergebnis der Evaluation von expr gegen die Zeile, die innerhalb der Partition offset Zeilen weiter oben liegt. Wenn offset 0 ist, wird expr gegen die aktuelle Zeile evaluiert. Wenn vor der aktuellen Zeile nicht genügend Zeilen vorhanden sind, wird NULL zurückgegeben. - - This option is used to create a new database file. - Diese Option wird zum Erstellen einer neuen Datenbank-Datei verwendet. + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,offset,default) Wenn auch default angegeben ist, dann wird dieser Wert anstatt NULL zurückgegeben, wenn die durch offset angegebene Zeile nicht existiert. - - Ctrl+N - Strg+N + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) Gibt das Ergebnis der Evaluation des Ausdrucks expr gegen die nächste Zeile in der Partition zurück. Wenn es keine nächste Zeile gibt (weil die aktuelle Zeile die letzte ist), wird NULL zurückgegeben. - - &Open Database... - &Datenbank öffnen... + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,offset) Wenn das Argument offset angegeben ist, dann muss dieses ein nichtnegativer Integerwert sein. In diesem Fall ist der Rückgabewert das Ergebnis der Evaluation von expr gegen die Zeile, die innerhalb der Partition offset Zeilen weiter unten liegt. Wenn offset 0 ist, wird expr gegen die aktuelle Zeile evaluiert. Wenn nach der aktuellen Zeile nicht genügend Zeilen vorhanden sind, wird NULL zurückgegeben. - - - Open an existing database file - Existierende Datenbank-Datei öffnen + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) Diese eingebaute Fensterfunktion berechnet den Fensterrahmen für jede Zeile auf die gleiche Art wie ein aggregierte Fensterfunktion. Sie gibt den Wert von expr evaluiert gegen die erste Zeile im Fensterrahmen für jede Zeile zurück. - - This option is used to open an existing database file. - Diese Option wird zum Öffnen einer existierenden Datenbank-Datei verwendet. + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) Diese eingebaute Fensterfunktion berechnet den Fensterrahmen für jede Zeile auf die gleiche Art wie ein aggregierte Fensterfunktion. Sie gibt den Wert von expr evaluiert gegen die letzte Zeile im Fensterrahmen für jede Zeile zurück. - - Ctrl+O - Strg+O + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr,N) Diese eingebaute Fensterfunktion berechnet den Fensterrahmen für jede Zeile auf die gleiche Art wie ein aggregierte Fensterfunktion. Sie gibt den Wert von expr evaluiert gegen die N-te Zeile im Fensterrahmen zurück. Die Zeilen werden beginnend bei 1 in der durch den Befehl ORDER BY definierten Reihenfolge nummeriert, falls dieser vorhanden ist, ansonsten in beliebiger Reihenfolge. Wenn es keine N-te Zeile in der Partition gibt, dann wird NULL zurückgegeben. - - &Close Database - &Datenbank schließen + + (X) Return the arccosine of X. The result is in radians. + (X) Gibt den Arkuskosinus von X zurück. Das Ergebnis ist im Bogenmaß. - - Ctrl+W - Strg+W + + (X) Return the hyperbolic arccosine of X. + (X) Gibt den Areakosinus hyperbolicus von X zurück. - - Revert Changes - Änderungen rückgängig machen + + (X) Return the arcsine of X. The result is in radians. + (X) Gibt den Arkussinus von X zurück. Das Ergebnis ist im Bogenmaß. - - Revert database to last saved state - Datenbank auf zuletzt gespeicherten Zustand zurücksetzen + + (X) Return the hyperbolic arcsine of X. + (X) Gibt den Areasinus hyperbolicus von X zurück. - - This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. - Diese Option wird zum Zurücksetzen der aktuellen Datenbank-Datei auf den zuletzt gespeicherten Zustand verwendet. Alle danach getätigten Änderungen gehen verloren. + + (X) Return the arctangent of X. The result is in radians. + (X) Gibt den Arkustangens von X zurück. Das Ergebnis ist im Bogenmaß. - - Write Changes - Änderungen schreiben + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + (X,Y) Den Arkustangens von Y/X ermitteln. Das Ergebnis ist im Bogenmaß. Das Ergebnis wird abhängig von den Vorzeichen von X und Y im korrekten Quadranten platziert. - - Write changes to the database file - Änderungen in Datenbank-Datei schreiben + + (X) Return the hyperbolic arctangent of X. + (X) Gibt den Areatangens hyperbolicus von X zurück. - - This option is used to save changes to the database file. - Diese Option wird zum Speichern von Änderungen in der Datenbank-Datei verwendet. + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + (X) Gibt die erste darstellbare Ganzzahl größer oder gleich X zurück. Für positive X-Werte wird immer von Null weg gerundet. Für negative X-Werte wird immer in Richtung Null gerundet. - - Ctrl+S - Strg+S + + (X) Return the cosine of X. X is in radians. + (X) Gibt den Kosinus von X zurück. X ist im Bogenmaß. - - Compact Database - Datenbank komprimieren + + (X) Return the hyperbolic cosine of X. + (X) Gibt den Kosinus hyperbolicus von X zurück. - - Compact the database file, removing space wasted by deleted records - Datenbank-Datei komprimieren, löscht Speicherplatz von gelöschten Zeilen + + (X) Convert value X from radians into degrees. + (X) Umwandlung des Wertes X von Bogenmaß in Grad. - - - Compact the database file, removing space wasted by deleted records. - Datenbank-Datei komprimieren, löscht Speicherplatz von gelöschten Zeilen. + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + (X) Ermittelt e (Eulersche Zahl, ungefähr 2.71828182845905) hoch X. - - E&xit - B&eenden + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + (X) Gibt die erste darstellbare Ganzzahl kleiner oder gleich X zurück. Für positive X-Werte wird immer in Richtung Null gerundet. Für negative X-Werte wird immer von Null weg gerundet. - - Ctrl+Q - Strg+Q + + (X) Return the natural logarithm of X. + (X) Gibt den natürlichen Logarithmus von X zurück. - - Database from SQL file... - Datenbank aus SQL-Datei... + + (B,X) Return the base-B logarithm of X. + (B,X) Den Logarithmus von X zur Basis B zurückgeben. - - Import data from an .sql dump text file into a new or existing database. - Daten von einer .sql-Dump-Textdatei in eine neue oder existierende Datenbank importieren. + + + (X) Return the base-10 logarithm for X. + (X) Gibt den Logarithmus von X zur Basis 10 zurück. - - This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. - Diese Option wird zum Importieren von Daten von einer .sql-Dump-Textdatei in eine neue oder existierende Datebank verwendet. SQL-Dumpdateien können von den meisten Datenbankanwendungen erstellt werden, inklusive MySQL und PostgreSQL. + + (X) Return the logarithm base-2 for the number X. + (X) Gibt den Logarithmus von X zur Basis 2 zurück. - - Table from CSV file... - Tabelle aus CSV-Datei... + + (X,Y) Return the remainder after dividing X by Y. + (X,Y) Den Rest der Division von X durch Y ermitteln. - - Open a wizard that lets you import data from a comma separated text file into a database table. - Öffnet einen Assistenten zum Importieren von Daten aus einer kommaseparierten Textdatei in eine Datenbanktabelle. + + () Return an approximation for Ï€. + () Eine Näherung von Ï€ zurückgeben. - - Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. - Öffnet einen Assistenten zum Importieren von Daten aus einer kommaseparierten Textdatei in eine Datenbanktabelle. CSV-Dateien können von den meisten Datenbank- und Tabellenkalkulations-Anwendungen erstellt werden. + + + (X,Y) Compute X raised to the power Y. + (X,Y) Berechnung von X hoch Y. - - Database to SQL file... - Datenbank zu SQL-Datei... + + (X) Convert X from degrees into radians. + (X) Umwandlung des Wertes X von Grad zu Bogenmaß. - - Export a database to a .sql dump text file. - Exportiert eine Datenbank in eine .sql-Dump-Textdatei. + + (X) Return the sine of X. X is in radians. + (X) Gibt den Sinus von X zurück. X ist im Bogenmaß. - - This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. - Diese Option ermöglicht den Export einer Datenbank in eine .sql-Dump-Textdatei. SQL-Dumpdateien enthalten alle notwendigen Daten, um die Datenbank mit den meisten Datenbankanwendungen neu erstellen zu können, inklusive MySQL und PostgreSQL. + + (X) Return the hyperbolic sine of X. + (X) Gibt den Sinus hyperbolicus von X zurück. - - Table as CSV file... - Tabelle als CSV-Datei... + + (X) Return the square root of X. NULL is returned if X is negative. + (X) Gibt die Quadratwurzel von X zurück. Wenn X negativ ist, wird NULL zurückgegeben. - - Export a database table as a comma separated text file. - Datenbank als kommaseparierte Textdatei exportieren. + + (X) Return the tangent of X. X is in radians. + (X) Gibt den Tangens von X zurück. X ist im Bogenmaß. - - Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. - Exportiert die Datenbank als kommaseparierte Textdatei, fertig zum Import in andere Datenbank- oder Tabellenkalkulations-Anwendungen. + + (X) Return the hyperbolic tangent of X. + (X) Gibt den Tangens hyperbolicus von X zurück. - - Create Table... - Tabelle erstellen... + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + (X) Gibt die darstellbare Ganzzahl zwischen X und 0 (inklusiv) zurück, die am weitesten von Null entfernt ist. Oder, anders formuliert, gibt den Ganzzahl-Teil von X bei Rundung gegen Null zurück. + + + SqliteTableModel - - Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database - Den Assistenten zum Erstellen einer Tabelle öffnen, wo der Name und die Felder für eine neue Tabelle in der Datenbank festgelegt werden können. + + reading rows + lese Zeilen - - Delete Table... - Tabelle löschen... + + loading... + laden... - - Open the Delete Table wizard, where you can select a database table to be dropped. - Den Assistenten zum Löschen einer Tabelle öffnen, wo eine zu entfernende Datenbanktabelle ausgewählt werden kann. + + References %1(%2) +Hold %3Shift and click to jump there + Referenzen %1(%2) +Halten Sie %3Umschalt und klicken Sie, um hierher zu springen - - Modify Table... - Tabelle ändern... + + Error changing data: +%1 + Fehler beim Ändern der Daten: +%1 - - Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields form a table, as well as modify field names and types. - Den Assistenten zum Ändern einer Tabelle öffnen, wo eine existierende Tabelle umbenannt werden kann. Ebenso können Felder hinzugefügt und gelöscht sowie Feldnamen und -typen geändert werden. + + retrieving list of columns + Liste der Spalten ermitteln - - Create Index... - Index erstellen... + + Fetching data... + Daten abrufen... - - Open the Create Index wizard, where it is possible to define a new index on an existing database table. - Den Assistenten zum Erstellen des Index öffnen, wo ein neuer Index für eine existierende Datenbanktabelle gewählt werden kann. + + + Cancel + Abbrechen + + + TableBrowser - - &Preferences... - &Einstellungen + + Browse Data + Daten durchsuchen - - - Open the preferences window. - Das Einstellungsfenster öffnen. + + &Table: + &Tabelle: - - &DB Toolbar - &DB Toolbar + + Select a table to browse data + Anzuzeigende Tabelle auswählen - - Shows or hides the Database toolbar. - Zeigt oder versteckt die Datenbank-Toolbar. + + Use this list to select a table to be displayed in the database view + Diese Liste zur Auswahl der in der Datenbankansicht anzuzeigenden Tabelle verwenden - - What's This? - Funktionen erläutern + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + Dies ist die Datenbanktabellen-Ansicht. Sie können die folgenden Aktionen durchführen: + - Mit dem Schreiben beginnen, um die Werte Inline zu bearbeiten. + - Doppelt auf einen Eintrag klicken, um dessen Inhalte im Zelleneditor-Fenster zu bearbeiten. + - Alt+Entf zum Löschen des Zellinhaltes zu NULL. + - Strg+" zur Duplizierung des aktuellen Eintrags. + - Strg+' zum Kopieren des Wertes der darüberliegenden Zelle. + - Standardmäßige Auswahl- und Kopieren/Einfügen-Operationen. - - Shift+F1 - Shift+F1 + + Text pattern to find considering the checks in this frame + Zu findendes Textmuster unter Einbeziehung der Prüfungen in diesem Fenster - - &About... - &Über... + + Find in table + In Tabelle suchen - - &Recently opened - &Kürzlich geöffnet + + Find previous match [Shift+F3] + Vorherige Übereinstimmung finden [Umschalt+F3] - - Open &tab - Tab &öffnen + + Find previous match with wrapping + Vorherige Übereinstimmung mit Umbruch finden - - Ctrl+T - Strg+T + + Shift+F3 + - - &Execute SQL - &SQL ausführen + + Find next match [Enter, F3] + Nächste Übereinstimmung finden [Enter, F3] - - Execute SQL [F5, Ctrl+Return] - SQL ausführen [F5, Strg+Return] + + Find next match with wrapping + Nächste Übereinstimmung mit Umbruch finden - - &Wiki... - &Wiki... + + F3 + - - Bug &report... - Fehler &melden... + + The found pattern must match in letter case + Das Suchmuster muss in Groß-/Kleinschreibung übereinstimmen - - Web&site... - Web&site... + + Case Sensitive + Schreibungsabhängig - - Save Project - Projekt speichern + + The found pattern must be a whole word + Das Muster muss ein ganzes Wort sein - - - Save the current session to a file - Aktuelle Sitzung in einer Datei speichern + + Whole Cell + Gesamte Zelle - - Open Project - Projekt öffnen + + Interpret search pattern as a regular expression + Suchmuster als regulären Ausdruck interpretieren - - - Load a working session from a file - Sitzung aus einer Datei laden + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Wenn aktiviert, wird das Suchmuster als regulärer Ausdruck (UNIX-Stil) interpretiert. Siehe <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks (englisch)</a>.</p></body></html> - - Open SQL file - SQL-Datei öffnen + + Regular Expression + Regulärer Ausdruck - - <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> - <html><head/><body><p>Aktuelle Ansicht speichern...</p><p>Dateiformat durch Endung auswählen (png, jpg, pdf, bmp)</p></body></html> + + + Close Find Bar + Suchbar schließen - - Save SQL file - SQL-Datei speichern + + Text to replace with + Ersetzungstext - - Load extension - Erweiterung laden + + Replace with + Ersetzen mit - - Execute current line - Aktuelle Zeile ausführen + + Replace next match + Nächste Übereinstimmung ersetzen - - Execute current line [Ctrl+E] - Aktuelle Zeile ausführen [Strg+E] + + + Replace + Ersetzen - - Ctrl+E - Strg+E + + Replace all matches + Alle Übereinstimmungen ersetzen - - Export as CSV file - Als CSV-Datei exportieren + + Replace all + Alle ersetzen - - Export table as comma separated values file - Tabelle als kommaseparierte Wertedatei exportieren + + Export to &JSON + Nach &JSON exportieren - - Ctrl+L - Strg+L + + + Export the filtered data to JSON + Die gefilterten Daten nach JSON exportieren - - Ctrl+P - Strg+P + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + Dieser Button exportiert die Daten der angezeigten Tabelle wie aktuell dargestellt (inklusive Filtern, Anzeigeformaten und Spaltenreihenfolge) als eine JSON-Datei. - - Database encoding - Datenbank-Kodierung + + Copy column name + Spaltenname kopieren - - Choose a database file - Eine Datenbankdatei auswählen + + Copy the database table column name to your clipboard + Den Spaltennamen in die Zwischenablage kopieren - - Ctrl+Return - Strg+Return + + New Data Browser + Neuer Datenbrowser - - - - - Choose a filename to save under - Dateinamen zum Speichern auswählen + + + Add a new docked Data Browser + Einen neuen angedockten Datenbrowser hinzufügen - - Error adding record: - - Fehler beim Hinzufügen der Zeile: - + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + Dieser Button fügt einen neuen angedockten Datenbrowser hinzu, der abgedockt und in verschiedenen Layouts angeordnet werden kann. - - Error deleting record: -%1 - Fehler beim Löschen der Zeile: -%1 + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>Zum Anfang scrollen</p></body></html> - - Please select a record first - Bitte zuerst eine Zeile auswählen + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>Ein Klick auf diesen Button navigiert zum Anfang der oben angezeigten Tabelle.</p></body></html> - - %1 - %2 of %3 - %1 - %2 von %3 + + |< + |< - - - There is no database opened. Please open or create a new database file. - Es ist keine Datenbank geöffnet. Bitte eine Datenbank-Datei öffnen oder eine neue erstellen. + + Scroll one page upwards + Eine Seite nach oben scrollen - - Are you sure you want to delete the %1 '%2'? -All data associated with the %1 will be lost. - Sollen %1 '%2' wirklich gelöscht werden? -Alle mit %1 verbundenen Daten gehen verloren. + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>Ein Klick auf diesen Button navigiert in den Einträgen der Tabellenansicht oben eine Seite nach oben.</p></body></html> - - Error: could not delete the %1. Message from database engine: -%2 - Fehler: %1 konnte nicht gelöscht werden. Meldung der Datenbank: -%2 + + < + < - - There is no database opened. - Keine Datenbank geöffnet. + + 0 - 0 of 0 + 0 - 0 von 0 - - %1 Rows returned from: %2 (took %3ms) - %1 Reihen zurückgegeben von: %2 (in %3ms) + + Scroll one page downwards + Eine Seite nach unten scrollen - - Error executing query: %1 - Fehler beim Ausführen der Anfrage: %1 + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>Ein Klick auf diesen Button navigiert in den Einträgen der Tabellenansicht oben eine Seite nach unten.</p></body></html> - - Query executed successfully: %1 (took %2ms) - Anfrage erfolgreich ausgeführt: %1 (in %2ms) + + > + > - - Choose a text file - Textdatei auswählen + + Scroll to the end + Zum Ende scrollen - - Text files(*.csv *.txt);;All files(*) - Textdateien(*.csv *.txt);;Alle Dateien(*) + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>Ein Klick auf diesen Button navigiert zum Ende der oben angezeigten Tabelle.</p></body></html> - - Import completed - Import vollständig + + >| + >| - - Are you sure you want to undo all changes made to the database file '%1' since the last save? - Sollen wirklich alle Änderungen an der Datenbankdatei '%1' seit dem letzten Speichern rückgängig gemacht werden? + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html></head><body><p>Klicken Sie hier, um zu einer bestimmten Zeile zu springen</p></body></html> - - Choose a filename to export - Dateinamen zum Export auswählen + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html></head><body><p>Dieser Button kann zum Navigieren zu einer im Bereich "Springe zu" festgelegten Zeile verwendet werden.</p></body></html> - - Text files(*.sql *.txt) - Textdateien(*.sql *.txt) + + Go to: + Springe zu: - - Export cancelled or failed. - Export abgebrochen oder fehlgeschlagen. + + Enter record number to browse + Zeilennummer zum Suchen auswählen - - Export completed. - Export abgeschlossen. + + Type a record number in this area and click the Go to: button to display the record in the database view + Geben Sie eine Zeilennummer in diesem Bereich ein und klicken Sie auf den Button "Springe zu:", um die Zeile in der Datenbankansicht anzuzeigen - - Choose a file to import - Datei für Import auswählen + + 1 + 1 - - - - Text files(*.sql *.txt);;All files(*) - Textdateien(*.sql *.txt);;Alle Dateien(*) + + Show rowid column + Rowid-Spalte anzeigen - - Do you want to create a new database file to hold the imported data? -If you answer no we will attempt to import the data in the SQL file to the current database. - Soll für die importierten Daten eine neue Datenbank erstellt werden? -Bei der Antwort NEIN werden die Daten in die SQL-Datei der aktuellen Datenbank importiert. + + Toggle the visibility of the rowid column + Sichtbarkeit der Rowid-Spalte umschalten - - File %1 already exists. Please choose a different name. - Datei %1 existiert bereits. Bitte einen anderen Namen auswählen. + + Unlock view editing + Ansicht zur Bearbeitung entsperren - - Error importing data: %1 - Fehler beim Datenimport: %1 + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + Dies entsperrt die aktuelle Ansicht zur Bearbeitung. Allerdings werden zur Bearbeitung passende Trigger benötigt. - - Import completed. - Import abgeschlossen. + + Edit display format + Anzeigeformat bearbeiten - - Delete View - Ansicht löschen + + Edit the display format of the data in this column + Anzeigeformat der Daten in dieser Spalte bearbeiten - - Delete Trigger - Trigger löschen + + + New Record + Neue Zeile - - Delete Index - Index löschen + + + Insert a new record in the current table + Fügt eine neue Zeile zur aktuellen Tabelle hinzu - - - Delete Table - Tabelle löschen + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>Dieser Button erstellt eine neue Zeile in der Datenbank. Halten sie die Maustaste gedrückt, um ein Popup-Menü mit verschiedenen Optionen zu öffnen:</p><ul><li><span style=" font-weight:600;">Neuer Eintrag</span>: eine neue Zeile mit Standardwerten in die Datenbank einfügen.</li><li><span style=" font-weight:600;">Werte einfügen...</span>: einen Dialog zur Eingabe von Werten öffnen, bevor diese in die Datenbank eingefügt werden. Dies erlaubt die Eingabe von Werten, die den Beschränkungen Genüge tun. Dieser Dialog wird auch geöffnet, wenn die Option <span style=" font-weight:600;">Neuer Eintrag</span> aufgrund dieser Beschränkungen fehlschlägt.</li></ul></body></html> - - &%1 %2 - &%1 %2 + + + Delete Record + Zeile löschen - - Setting PRAGMA values will commit your current transaction. -Are you sure? - Das Setzen von PRAGMA-Werten übermittelt den aktuellen Vorgang. -Sind Sie sicher? + + Delete the current record + Aktuelle Zeile löschen - - Select SQL file to open - SQL-Datei zum Öffnen auswählen + + + This button deletes the record or records currently selected in the table + Dieser Button löscht die Zeile oder Zeilen, die aktuell in der Tabelle ausgewählt sind - - Select file name - Dateinamen auswählen + + + Insert new record using default values in browsed table + Eine neue Zeile mit den Standardwerten in den ausgewählte Tabelle einfügen - - Select extension file - Erweiterungsdatei auswählen + + Insert Values... + Werte einfügen... - - Extensions(*.so *.dll);;All files(*) - Erweiterungen(*.so *.dll);;Alle Dateien(*) + + + Open a dialog for inserting values in a new record + Einen Dialog zum Einfügen von Werten in eine neue Zeile öffnen - - Extension successfully loaded. - Erweiterung erfolgreich geladen. + + Export to &CSV + Nach &CSV exportieren - - - Error loading extension: %1 - Fehler beim Laden der Erweiterung: %1 + + + Export the filtered data to CSV + Die gefilterten Daten als CSV exportieren - - Don't show again - Nicht wieder anzeigen + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + Dieser Button exportiert die Daten der ausgewählten Tabelle wie aktuell angezeigt (gefiltert, Anzeigeformate und Spaltenreihenfolge) als CSV-Datei. - - New version available. - Neue Version verfügbar. + + Save as &view + Als &View speichern - - A new sqlitebrowser version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. - Eine neue sqlitebrowser-Version ist verfügbar (%1.%2.%3).<br/><br/>Bitte von <a href='%4'>%4</a> herunterladen. + + + Save the current filter, sort column and display formats as a view + Den aktuellen Filter, die Spaltenreihenfolge und Anzeigeformate als Ansicht speichern - - Choose a axis color - Achsenfarbe auswählen + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + Dieser Button speichert die aktuellen Einstellungen der ausgewählten Tabelle (Filter, Anzeigeformate und Spaltenreihenfolge) als SQL-Ansicht, die Sie später durchsuchen oder in SQL-Anweisungen verwenden können. - - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Alle Dateien(*) + + Save Table As... + Tabelle speichern als... - - Choose a file to open - Datei zum Öffnen auswählen + + + Save the table as currently displayed + Tabelle wie aktuell angezeigt speichern - - - SQLiteBrowser project(*.sqbpro) - SQLiteBrowser-Projekt(*.sqbpro) + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>Dieses Popup-Menü bietet die folgenden Optionen zur Anwendung auf die aktuell ausgewählte und gefilterte Tabelle:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">CSV exportieren: diese Option exportiert die Daten der ausgewählten Tabelle wie aktuell angezeigt (gefiltert, Anzeigeformat und Spaltenreihenfolge) in eine CSV-Datei.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Als Ansicht speichern: diese Option speichert die aktuelle Einstellung der ausgewählten Tabelle (Filter, Anzeigeformat und Spaltenreihenfolge) als eine SQL-Ansicht, die Sie später durchsuchen oder in SQL-Anweisungen verwenden können.</li></ul></body></html> - - Invalid file format. - Ungültiges Dateiformat. + + Hide column(s) + Spalte(n) verbergen - - - PreferencesDialog - - Preferences - Einstellungen + + Hide selected column(s) + Ausgewählte Spalte(n) verbergen - - &Database - &Datenbank + + Show all columns + Alle Spalten anzeigen - - Database &encoding - Datenbank-&-Kodierung + + Show all columns that were hidden + Alle versteckten Spalten anzeigen - - Open databases with foreign keys enabled. - Öffnet von Datenbanken mit fremden Schlüsseln aktiviert. + + + Set encoding + Codierung setzen - - &Foreign keys - &Fremde Schlüssel + + Change the encoding of the text in the table cells + Codierung des Textes in den Tabellenzellen ändern - - enabled - aktiviert + + Set encoding for all tables + Codierung für alle Tabellen setzen - - Default &location - Voreingestellte &Speicherort + + Change the default encoding assumed for all tables in the database + Voreingestellte Codierung für alle Tabellen in der Datenbank ändern - - ... - ... + + Clear Filters + Filter löschen - - &Prefetch block size - &Prefetch Blockgröße + + Clear all filters + Alle Filter löschen - - &SQL - &SQL + + + This button clears all the filters set in the header input fields for the currently browsed table. + Dieser Button löscht alle gesetzten Filter in den Header-Eingabefeldern der aktuell angezeigten Tabelle. - - Settings name - Einstellungsname + + Clear Sorting + Sortierung löschen - - Context - Kontext + + Reset the order of rows to the default + Die Zeilenreihenfolge auf den Standardzustand zurücksetzen - - Colour - Farbe + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + Dieser Button setzt die angegebene Spaltensortierung für die aktuell angezeigte Tabelle zurück und verwendet die Standardreihenfolge. - - Bold - Fett + + Print + Drucken - - Italic - Kursiv + + Print currently browsed table data + Aktuell angezeigte Tabellendaten drucken - - Underline - Unterstreichung + + Print currently browsed table data. Print selection if more than one cell is selected. + Die aktuell angezeigten Tabellendaten drucken. Auswahl drucken, wenn mehr als eine Zelle ausgewählt ist. - - Keyword - Schlüsselwort + + Ctrl+P + - - function - Funktion + + Refresh + Aktualisieren - - Function - Funktion + + Refresh the data in the selected table + Die Daten in der ausgewählten Tabelle aktualisieren - - Table - Tabelle + + This button refreshes the data in the currently selected table. + Dieser Button aktualisiert die Daten der aktuellen Tabellenansicht. - - Comment - Kommentar + + F5 + - - Identifier - Bezeichner + + Find in cells + In Zellen suchen - - String - String + + Open the find tool bar which allows you to search for values in the table view below. + Die Such-Werkzeugleiste öffnen, die das Suchen nach Werten in der Tabellenansicht unten erlaubt. - - currentline - Aktuelle Zeile + + + Bold + Fett - - Current line - Aktuelle Zeile + + Ctrl+B + - - SQL &editor font size - SQL&-Editor Schriftgröße + + + Italic + Kursiv - - SQL &log font size - SQL&-Log Schriftgröße + + + Underline + Unterstreichung - - &Extensions - &Erweiterungen + + Ctrl+U + - - Select extensions to load for every database: - Bei jeder Datenbank zu ladende Erweiterungen auswählen: + + + Align Right + Rechts ausrichten - - Add extension - Erweiterung hinzufügen + + + Align Left + Links ausrichten - - Remove extension - Erweiterung entfernen + + + Center Horizontally + Horizontal zentrieren - - Choose a directory - Verzeichnis wählen + + + Justify + Blocksatz - - Select extension file - Erweiterungsdatei wählen + + + Edit Conditional Formats... + Bedingte Formatierungen bearbeiten... - - Extensions(*.so *.dll);;All files(*) - Erweiterungen(*.so *.dll);;Alle Dateien(*) + + Edit conditional formats for the current column + Bedingte Formatierungen der aktuellen Spalte bearbeiten - - - QObject - - Error importing data. Message from database engine: %1 - Fehler beim Datenimport. Meldung der Datenbank: %1 + + Clear Format + Formatierung löschen - - File is not a SQLite 3 database - Datei ist keine SQLite 3-Datenbank + + Clear All Formats + Alle Formatierungen löschen - - File could not be read - Datei konnte nicht gelesen werden + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + Alle Zellenformatierungen aus den ausgewählten Zellen und alle bedingten Formatierungen aus den ausgewählten Spalten löschen - - - - no error - kein Fehler + + + Font Color + Schriftfarbe - - Do you want to save the changes made to the database file %1? - Sollen die getätigten Änderungen an der Datenbank-Datei %1 gespeichert werden? + + + Background Color + Hintergrundfarbe - - Exporting database to SQL file... - Datenbank in SQL-Datei exportieren... + + Toggle Format Toolbar + Formatierungs-Werkzeugleiste umschalten - - - - Cancel - Abbrechen + + Show/hide format toolbar + Formatierungs-Werkzeugleiste anzeigen/verstecken - - Executing SQL... - SQL ausführen... + + + This button shows or hides the formatting toolbar of the Data Browser + Dieser Button zeigt oder versteckt die Formatierungs-Werkzeugleiste im Datenbrowser - - Action cancelled. - Vorgang abgebrochen. + + Select column + Spalte auswählen - - - Error in statement #%1: %2. -Aborting execution. - Fehler im Statement #%1: %2. -Ausführung wird abgebrochen. + + Ctrl+Space + - - renameColumn: cannot find table %1. - Spalte umbenennen: Tabelle %1 nicht gefunden. + + Replace text in cells + Text in Zellen ersetzen - - renameColumn: cannot find column %1. - Spalte umbennen: Spalte %1 nicht gefunden. + + Freeze columns + Spalten sperren - - renameColumn: creating savepoint failed. DB says: %1 - Spalte umbenennen: Anlegen von Speicherpunkt fehlgeschlagen. DB meldet: %1 + + Make all columns from the first column up to this column not move when scrolling horizontally + Blockiert die Bewegung aller Spalten von der ersten Spalte bis zu dieser Spalte beim horizontalen Scrollen - - renameColumn: creating new table failed. DB says: %1 - Spalte umbenennen: Erstellen neuer Tabelle fehlgeschlagen. DB meldet: %1 + + Filter in any column + In allen Spalten filtern - - renameColumn: copying data to new table failed. DB says: -%1 - Spalte umbenennen: Kopieren der Daten in neue Tabelle fehlgeschlagen. DB sagt: -%1 + + Ctrl+R + - - - renameColumn: deleting old table failed. DB says: %1 - Spalte umbenennen: Löschen der alten Tabelle fehlgeschlagen. DB meldet: %1 + + + %n row(s) + + %n Zeile + %n Zeilen + + + + + , %n column(s) + + , %n Spalte + , %n Spalten + - - Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: - - - Wiederherstellung einiger mit dieser Tabelle verbundener Objekte fehlgeschagen. Dies passiert häufig durch geänderte Spaltennamen. Hier das SQL-Statement zum manuellen Reparieren und Ausführen: - - + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . Summe: %1; Durchschnitt: %2; Minimum: %3; Maximum: %4 - - renameColumn: releasing savepoint failed. DB says: %1 - Spalte umbenennen: Freigeben des Speicherpunktes fehlgeschlagen. DB meldet: %1 + + Conditional formats for "%1" + Bedingte Formatierung für "%1" - - Error renaming table '%1' to '%2'.Message from database engine: -%3 - Fehler beim Umbenennen der Tabelle '%1' zu '%2'. Meldung von Datenbank: -%3 + + determining row count... + Zeilenanzahl bestimmen... - - ... <string can not be logged, contains binary data> ... - ... <String kann nicht geloggt werden, enthält binäre Daten> ... + + %L1 - %L2 of >= %L3 + %L1 - %L2 von >= %L3 - - unknown object type %1 - unbekannter Objekttyp %1 + + %L1 - %L2 of %L3 + %L1 - %L2 von %L3 - - could not get list of db objects: %1, %2 - Liste mit DB-Ojekten konnte nicht bezogen werden: %1, %2 + + (clipped at %L1 rows) + (abgeschnitten bei %L1 Zeilen) - - could not get types - Typen konnten nicht bezogen werden + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + Bitte einen Pseudo-Primärschlüssel eingeben, um die Bearbeitung dieser Ansicht zu ermöglichen. Dies sollte der Name der eindeutigen Spalte dieser Ansicht sein. - - Decoding CSV file... - CSV-Datei dekodieren... + + Delete Records + Einträge löschen - - didn't receive any output from pragma %1 - keine Ausgabe von Pragma %1 + + Duplicate records + Einträge duplizieren - - could not execute pragma command: %1, %2 - Pragma-Kommando konnte nicht ausgeführt werden: %1, %2 + + Duplicate record + Eintrag duplizieren - - Error setting pragma %1 to %2: %3 - Fehler beim Setzen des Pragmas %1 auf %2: %3 + + Ctrl+" + - - File not found. - Datei nicht gefunden. + + Adjust rows to contents + Zeilen an Inhalte anpassen - - - SqlExecutionArea - - Form - Form + + Error deleting record: +%1 + Fehler beim Löschen des Eintrags: +%1 - - Results of the last executed statements - Ergebnisse des zuletzt ausgeführten Statements + + Please select a record first + Bitte zuerst einen Eintrag auswählen - - This field shows the results and status codes of the last executed statements. - Dieses Feld zeigt die Ergebnisse und Statuscodes der zuletzt ausgeführten Statements. + + Please choose a new encoding for all tables. + Bitte wählen Sie eine neue Codierung für alle Tabellen. - - Export to &CSV - Nach &CSV exportieren + + Please choose a new encoding for this table. + Bitte wählen Sie eine neue Codierung für diese Tabelle. - - Save as &view - Ansicht &speichern + + %1 +Leave the field empty for using the database encoding. + %1 +Lassen Sie das Feld leer, um die Datenbank-Codierung zu verwenden. - - Save as view - Ansicht speichern + + This encoding is either not valid or not supported. + Diese Codierung ist entweder nicht gültig oder nicht unterstützt. - - Please specify the view name - Namen für Ansicht angeben + + %1 replacement(s) made. + %1 Ersetzung(en) durchgeführt. + + + TableBrowserDock - - There is already an object with that name. Please choose a different name. - Es gibt bereits ein Objekt mit diesem Namen. Bitte einen anderen auswählen. + + New Data Browser + Neuer Datenbrowser - - View successfully created. - Ansicht erfolgreich erstellt. + + Rename Data Browser + Datenbrowser umbenennen - - Error creating view: %1 - Fehler beim Erstellen der Ansicht: %1 + + Close Data Browser + Datenbrowser schließen - - - SqliteTableModel - - Error changing data: -%1 - Fehler beim Ändern der Daten: -%1 + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + Einen neuen Namen für den Datenbrowser setzen. Das Zeichen '&&' verwenden, um das folgende Zeichen als Shortcut zu verwenden. @@ -2041,17 +8075,17 @@ Ausführung wird abgebrochen. Compact Database - Datenbank komprimieren + Datenbank komprimieren - Warning: Compacting the database will commit all changes you made. - Warnung: Das Komprimieren der Datenbank wird alle getätigten Änderungen übernehmen. + Warning: Compacting the database will commit all of your changes. + Warnung: Das Verdichten der Datenbank wird alle Ihre Änderungen übermitteln. - Please select the objects to compact: - Bitte zu komprimierende Objekte auswählen: + Please select the databases to co&mpact: + Bitte wählen Sie die zu ver&dichtenden Datenbanken aus: diff --git a/src/translations/sqlb_en_GB.ts b/src/translations/sqlb_en_GB.ts index 62b6a1f20..e23589001 100644 --- a/src/translations/sqlb_en_GB.ts +++ b/src/translations/sqlb_en_GB.ts @@ -1,6 +1,6 @@ - + AboutDialog @@ -9,2793 +9,7851 @@ - + Version - - <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:small;">It also uses the Silk icon set by Mark James licensed under a Creative Commons Attribution 2.5 and 3.0 license.<br/>See </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> - + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + + + + AddRecordDialog - - Version - + + Add New Record + - - Qt Version - + + Enter values for the new record considering constraints. Fields in bold are mandatory. + - - SQLCipher Version - + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + - - SQLite Version - + + Name + - - - Application - - Usage: %1 [options] [db] - - + + Type + - - Possible command line arguments: - + + Value + - - -h, --help Show command line options - + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + - - -s, --sql [file] Execute this SQL file after opening the DB - + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + - - -q, --quit Exit application after running scripts - + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + - - [file] Open this SQLite database - + + Auto-increment + + - - The -s/--sql option requires an argument - + + Unique constraint + + - - The file %1 does not exist - + + Check constraint: %1 + + - - Invalid option/non-existant file: %1 - + + Foreign key: %1 + + - - - CipherDialog - - SQLCipher encryption - + + Default value: %1 + + - - &Password - + + Error adding record. Message from database engine: + +%1 + - - &Reenter password - + + Are you sure you want to restore all the entered values to their defaults? + + + + Application - - Page &size + + Possible command line arguments: - - Please set a key to encrypt the database. -Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. -Leave the password fields empty to disable the encryption. -The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. - + + The user settings file location is replaced with the argument value instead of the environment variable value. + - - Please enter the key used to encrypt the database. -If any of the other settings were altered for this database file you need to provide this information as well. - + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + - - - CreateIndexDialog - - Create New Index + + + The file %1 does not exist - - &Name - + + Usage + - - &Columns - + + options + - - Column - + + + database + - - Use in Index - + + + project + - - Order - + + + csv-file + - - &Table - + + Show command line options + - - &Unique - + + Exit application after running scripts + - - Creating the index failed: -%1 - + + + file + - - - DBBrowserDB - - - - - no error - + + Execute this SQL file after opening the DB + - - Please specify the database name under which you want to access the attached database - + + Import this CSV file into the passed DB or into a new DB + - - Do you want to save the changes made to the database file %1? - + + table + - - Exporting database to SQL file... - + + Browse this table, or use it as target of a data import + - - - Cancel - + + Open database in read-only mode + - - Executing SQL... - + + settings_file + - - Action cancelled. - + + Run application based on this settings file + - - - Error in statement #%1: %2. -Aborting execution. - + + + group + - - renameColumn: cannot find table %1. - + + + settings + - - renameColumn: cannot find column %1. - + + + value + - - renameColumn: creating savepoint failed. DB says: %1 - + + Run application with this setting temporarily set to value + - - renameColumn: creating new table failed. DB says: %1 - + + Run application saving this value for this setting + - - renameColumn: copying data to new table failed. DB says: -%1 - + + Display the current version + - - renameColumn: deleting old table failed. DB says: %1 - + + Open this SQLite database + - - Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: - - - + + Open this project file (*.sqbpro) + - - renameColumn: releasing savepoint failed. DB says: %1 - + + Import this CSV file into an in-memory database + - - Error renaming table '%1' to '%2'.Message from database engine: -%3 - + + + + The %1 option requires an argument + - - ... <string can not be logged, contains binary data> ... - + + The -S/--settings option requires an argument. The option is ignored. + - - unknown object type %1 - + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + - - could not get list of db objects: %1, %2 - + + Invalid option/non-existent file: %1 + - - could not get types - + + SQLite Version + - - didn't receive any output from pragma %1 - + + SQLCipher Version %1 (based on SQLite %2) + - - could not execute pragma command: %1, %2 - + + DB Browser for SQLite Version %1. + - - Error setting pragma %1 to %2: %3 - + + Last commit hash when built: %1 + - - File not found. - + + Built for %1, running on %2 + + + + + Qt Version %1 + - DbStructureModel + CipherDialog - - Name + + SQLCipher encryption - - Object + + &Password - - Type + + &Reenter password - - Schema - + + Encr&yption settings + - - Tables (%1) - + + SQLCipher &3 defaults + - - Indices (%1) - + + SQLCipher &4 defaults + - - Views (%1) - + + Custo&m + - - Triggers (%1) - + + Page si&ze + - - - EditDialog - - Edit database cell - + + &KDF iterations + - - Import text - + + HMAC algorithm + - - Opens a file dialog used to import text to this database cell. - + + KDF algorithm + - - &Import - + + Plaintext Header Size + - - Export text - + + Passphrase + - - Opens a file dialog used to export the contents of this database cell to a text file. - + + Raw key + - - &Export + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. - - Text + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + + + ColumnDisplayFormatDialog - - Binary - + + Choose display format + - - Clear cell data - + + Display format + - - Erases the contents of the cell - + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + - - &Clear - + + Default + - - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Warning: Editing binary content in text mode may result in corrupted data!</span></p></body></html> - + + Decimal number + - - This area displays information about the data present in this database cell - + + Exponent notation + - - Type of data currently in cell - + + Hex blob + - - Size of data currently in table - + + Hex number + - - Choose a file - + + Apple NSDate to date + - - Text files(*.txt);;Image files(%1);;All files(*) - + + Java epoch (milliseconds) to date + - - Choose a filename to export data - + + .NET DateTime.Ticks to date + - - Text files(*.txt);;All files(*) - + + Julian day to date + - - Type of data currently in cell: Null - + + Unix epoch to local time + - - Type of data currently in cell: Text / Numeric - + + WebKit / Chromium epoch to date + - - - %n char(s) - - - + + + WebKit / Chromium epoch to local time + - - Type of data currently in cell: Image - + + Date as dd/mm/yyyy + - - %1x%2 pixel - + + Lower case + - - Type of data currently in cell: Binary - + + Binary GUID to text + - - - %n byte(s) - - - + + + SpatiaLite Geometry to SVG + - - - EditTableDialog - - Edit table definition - + + Custom display format must contain a function call applied to %1 + - - Table - + + Error in custom display format. Message from database engine: + +%1 + - - Advanced - + + Custom display format must return only one column but it returned %1. + - - Make this a 'WITHOUT rowid' table. Setting this flag requires a field of type INTEGER with the primary key flag set and the auto increment flag unset. - + + Octal number + - - Without Rowid - + + Round number + - - Fields - + + Unix epoch to date + - - Add field - + + Upper case + - - Remove field - + + Windows DATE to date + - - Move field up - + + Custom + + + + CondFormatManager - - Move field down - + + Conditional Format Manager + - - Name - + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + - - Type - + + Add new conditional format + - - - Not null - + + &Add + - - PK - + + Remove selected conditional format + - - Primary key - + + &Remove + - - AI - + + Move selected conditional format up + - - Autoincrement - + + Move &up + - - U - + + Move selected conditional format down + - - Unique - + + Move &down + - - Default - + + Foreground + - - Default value - + + Text color + Text colour - - Check - + + Background + - - Check constraint - + + Background color + Background colour - - Foreign Key - + + Font + - - Error creating table. Message from database engine: -%1 - + + Size + - - There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. - + + Bold + - - There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. - + + Italic + - - Column `%1` has no unique data. - - + + Underline + - - This makes it impossible to set this flag. Please change the table data first. - + + Alignment + - - Are you sure you want to delete the field '%1'? -All data currently stored in this field will be lost. - + + Condition + - - Please add a field which meets the following criteria before setting the without rowid flag: - - Primary key flag set - - Auto increment disabled - + + + Click to select color + + + + + Are you sure you want to clear all the conditional formats of this field? + - ExportCsvDialog + DBBrowserDB - - Export data as CSV + + Please specify the database name under which you want to access the attached database - - &Table(s) - + + Invalid file format + - - &Column names in first line - + + Do you really want to close this temporary database? All data will be lost. + - - Field &separator + + Do you want to save the changes made to the database file %1? - - , - + + Database didn't close correctly, probably still busy + - - ; - + + Cannot open destination file: '%1' + - - - Tab - + + + Cannot backup to file: '%1'. Message: %2 + - - | - + + The database is currently busy: + - - - Other - + + Do you want to abort that other operation? + - - &Quote character + + Exporting database to SQL file... - - " + + + Cancel - - ' - + + + No database file opened + - - Could not open output file: %1 + + Executing SQL... - - - Choose a filename to export data + + Action cancelled. - - - Text files(*.csv *.txt) - + + + Error in statement #%1: %2. +Aborting execution%3. + - - Please select at least 1 table. - + + + and rolling back + - - Choose a directory - + + didn't receive any output from %1 + - - Export completed. - + + could not execute command: %1 + - - - ExportSqlDialog - - Export SQL... - + + Cannot delete this object + - - &Table(s) - + + Cannot set data on this object + - - &Options - + + + A table with the name '%1' already exists in schema '%2'. + - - Keep column names in INSERT INTO - + + No table with name '%1' exists in schema '%2'. + - - New INSERT INTO syntax (multiple rows in VALUES) - + + + Cannot find column %1. + - - Export schema only - + + Renaming the column failed. DB says: +%1 + - - Please select at least 1 table. - + + Creating new table failed. DB says: %1 + - - Choose a filename to export - + + Copying data to new table failed. DB says: +%1 + - - Text files(*.sql *.txt) - + + Deleting old table failed. DB says: %1 + - - Export completed. + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + - - Export cancelled or failed. - + + could not get list of databases: %1 + - - - FilterLineEdit - - Filter - + + Error loading extension: %1 + - - - ImportCsvDialog - - Import CSV file - + + Error loading built-in extension: %1 + - - &Table name - + + could not get column information + - - &Column names in first line - + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + - - Field &separator - + + Creating savepoint failed. DB says: %1 + - - , - + + + Releasing savepoint failed. DB says: %1 + - - ; - + + could not get list of db objects: %1 + - - - Tab + + Error setting pragma %1 to %2: %3 - - | + + File not found. + + + DbStructureModel - - - - Other + + Name - - &Quote character + + Object - - " + + Type - - ' + + Schema - - &Encoding - + + Database + - - UTF-8 - + + Browsables + - - UTF-16 - + + All + - - ISO-8859-1 - + + Temporary + - - Trim fields? + + Tables (%1) - - Inserting data... + + Indices (%1) - - Cancel + + Views (%1) - - There is already a table of that name and an import into an existing table is only possible if the number of columns match. + + Triggers (%1) + + + EditDialog - - There is already a table of that name. Do you want to import the data into it? + + Edit database cell - - Creating restore point failed: %1 - + + Mode: + - - Creating the table failed: %1 - + + + Image + - - Missing field for record %1 - + + Set as &NULL + - - Inserting row failed: %1 - + + Apply data to cell + - - - MainWindow - - DB Browser for SQLite - + + This button saves the changes performed in the cell editor to the database cell. + - - Database &Structure - + + Apply + - - - toolBar1 + + Text - - &Browse Data - + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + - - Table: - + + RTL Text + - - Select a table to browse data + + Binary - - Use this list to select a table to be displayed in the database view - + + JSON + - - Refresh the data in the selected table. - + + XML + - - This button refreshes the data in the currently selected table. - + + Evaluation + - - - F5 - + + + Automatically adjust the editor mode to the loaded data type + - - Clear all filters - + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + - - Insert a new record in the current table - + + Auto-switch + - - This button creates a new, empty record in the database - + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + - - New Record - + + Identification of the cell currently in the editor + - - Delete the current record - + + Type and size of data currently in table + - - This button deletes the record currently selected in the database - + + Open preview dialog for printing the data currently stored in the cell + - - Delete Record - + + Auto-format: pretty print on loading, compact on saving. + - - This is the database view. You can double-click any record to edit its contents in the cell editor window. - + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + - - <html><head/><body><p>Scroll to the beginning</p></body></html> - + + Word Wrap + - - <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> - + + Wrap lines on word boundaries + - - |< - + + + Open in default application or browser + - - Scroll 100 records upwards - + + Open in application + - - <html><head/><body><p>Clicking this button navigates 100 records upwards in the table view above.</p></body></html> - + + The value is interpreted as a file or URL and opened in the default application or web browser. + - - < - + + Save file reference... + - - 0 - 0 of 0 - + + Save reference to file + - - <html><head/><body><p>Scroll 100 records downwards</p></body></html> - + + + Open in external application + - - <html><head/><body><p>Clicking this button navigates 100 records downwards in the table view above.</p></body></html> - + + Autoformat + - - > - + + &Export... + - - Scroll to the end - + + + &Import... + - - <html><head/><body><p>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Clicking this button navigates up to the end in the table view above.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html> - + + + Import from file + - - >| - + + + Opens a file dialog used to import any kind of data to this database cell. + - - <html><head/><body><p>Click here to jump to the specified record</p></body></html> - + + Export to file + - - <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> - + + Opens a file dialog used to export the contents of this database cell to a file. + - - Go to: + + Erases the contents of the cell - - Enter record number to browse + + This area displays information about the data present in this database cell - - Type a record number in this area and click the Go to: button to display the record in the database view - + + Print... + - - 1 + + Ctrl+P - - Edit &Pragmas - + + Open preview dialog for printing displayed text + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> - + + Copy Hex and ASCII + - - - - None - + + Copy selected hexadecimal and ASCII columns to the clipboard + - - - Full + + Ctrl+Shift+C - - Incremental + + Choose a filename to export data - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> - + + + Image data can't be viewed in this mode. + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> - + + + Try switching to Image or Binary mode. + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></a></p></body></html> - + + + Binary data can't be viewed in this mode. + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> - + + + Try switching to Binary mode. + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> - + + + Image files (%1) + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> - + + Binary files (*.bin) + - - Delete - + + + Type: NULL; Size: 0 bytes + - - - Truncate - + + + + Type: Text / Numeric; Size: %n character(s) + + + + - - Persist - + + Type: %1 Image; Size: %2x%3 pixel(s) + - - - - Memory - + + + Type: Valid JSON; Size: %n character(s) + + + + + + + + Type: Binary; Size: %n byte(s) + + + + - - WAL - + + Couldn't save file: %1. + - - - Off - + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> - + + Choose a file to import + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a></p></body></html> - + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + - - - Normal - + + Unsaved data in the cell editor + - - Exclusive - + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> - + + Editing row=%1, column=%2 + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> - + + No cell active. + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> - + + %1 Image + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> - + + Invalid data for this mode + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> - + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + + + + EditIndexDialog - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> + + &Name - - Default + + Order - - File + + &Table - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> - + + Edit Index Schema + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> + + &Unique - - E&xecute SQL - + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + - - &File - + + Partial inde&x clause + - - &Import - + + Colu&mns + - - &Export - + + Table column + - - &Edit - + + Type + - - &View - + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + - - &Help - + + Index column + - - DB Toolbar - + + Deleting the old index failed: +%1 + - - SQL Log + + Creating the index failed: +%1 + + + EditTableDialog - - &Show SQL submitted by + + Edit table definition - - User + + Table - - Application + + Advanced - - &Clear + + Without Rowid - - Plot - + + Database sche&ma + - - Columns - + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + - - X - + + On Conflict + - - Y - + + Strict + - - _ - + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + - - Line type: + + Fields - - Line - + + + + Add + - - StepLeft - + + + + Remove + - - StepRight - + + Move to top + - - StepCenter - + + Move up + - - Impulse - + + Move down + - - Point shape: - + + Move to bottom + - - Cross + + + + + Name - - Plus + + + Type - - Circle - + + NN + - - Disc + + Not null - - Square + + PK - - Diamond - + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + - - Star + + AI - - Triangle + + Autoincrement - - TriangleInverted + + U - - CrossSquare + + + + Unique - - PlusSquare + + Default - - CrossCircle + + Default value - - PlusCircle + + + Check - - Peace + + Check constraint - - <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> - + + Collation + - - Save current plot... + + Foreign Key - - DB Schema - + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + - - &New Database... - + + Index Constraints + - - - Create a new database file - + + Add constraint + - - This option is used to create a new database file. - + + Remove constraint + - - Ctrl+N - + + + Columns + - - &Open Database... - + + + + SQL + - - - Open an existing database file - + + Foreign Keys + - - This option is used to open an existing database file. - + + References + - - Ctrl+O - + + Check Constraints + - - &Close Database - + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + - - Ctrl+W - + + + Primary Key + - - Revert Changes - + + Add a primary key constraint + - - Revert database to last saved state - + + Add a unique constraint + - - This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. - + + + There can only be one primary key for each table. Please modify the existing primary key instead. + - - Write Changes + + Error creating table. Message from database engine: +%1 - - Write changes to the database file - + + There already is a field with that name. Please rename it first or choose a different name for this field. + - - This option is used to save changes to the database file. - + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + - - Ctrl+S + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. - - Compact Database + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. - - Compact the database file, removing space wasted by deleted records - + + Column '%1' has duplicate data. + + - - - Compact the database file, removing space wasted by deleted records. - + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + - - E&xit + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. - - Ctrl+Q + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled - - Database from SQL file... - + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + + + + ExportDataDialog - - Import data from an .sql dump text file into a new or existing database. + + Export data as CSV - - This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. - + + Tab&le(s) + - - Table from CSV file... - + + Colu&mn names in first line + - - Open a wizard that lets you import data from a comma separated text file into a database table. - + + Fie&ld separator + - - Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + + , - - Database to SQL file... + + ; - - Export a database to a .sql dump text file. + + Tab - - This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + + | - - Table(s) as CSV file... + + + + Other - - Export a database table as a comma separated text file. + + &Quote character - - Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + + " - - Create Table... + + ' - - Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database - + + New line characters + - - Delete Table... - + + Windows: CR+LF (\r\n) + - - - Delete Table - + + Unix: LF (\n) + - - Open the Delete Table wizard, where you can select a database table to be dropped. - + + Pretty print + - - Modify Table... + + + Could not open output file: %1 - - Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields form a table, as well as modify field names and types. + + + Choose a filename to export data - - Create Index... - + + Export data as JSON + - - Open the Create Index wizard, where it is possible to define a new index on an existing database table. - + + exporting CSV + - - &Preferences... - + + + Error while writing the file '%1': %2 + - - - Open the preferences window. - + + exporting JSON + - - &DB Toolbar + + Please select at least 1 table. - - Shows or hides the Database toolbar. + + Choose a directory - - What's This? + + Export completed. - - Shift+F1 - + + Export finished with errors. + + + + ExportSqlDialog - - &About... + + Export SQL... - - &Recently opened - + + Tab&le(s) + - - Open &tab - + + Select All + - - Ctrl+T - + + Deselect All + - - &Execute SQL + + &Options - - Execute SQL [F5, Ctrl+Return] + + Keep column names in INSERT INTO - - Open SQL file - + + Multiple rows (VALUES) per INSERT statement + - - - - Save SQL file - + + Export everything + - - Load extension - + + Export data only + - - Execute current line - + + Keep original CREATE statements + - - Execute current line [Ctrl+E] - + + Keep old schema (CREATE TABLE IF NOT EXISTS) + - - Ctrl+E - + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + - - Export as CSV file + + Export schema only - - Export table as comma separated values file - + + Please select at least one table. + - - &Wiki... + + Choose a filename to export - - Bug &report... + + Export completed. - - Web&site... + + Export cancelled or failed. + + + ExtendedScintilla - - Save Project + + + Ctrl+H - - - Save the current session to a file + + Ctrl+F - - Open Project + + + Ctrl+P - - - Load a working session from a file - + + Find... + - - &Attach Database - + + Find and Replace... + - - Set Encryption - - - - - - Save SQL file as - + + Print... + + + + ExtendedTableWidget - - &Browse Table - + + Use as Exact Filter + - - Copy Create statement - + + Containing + - - Copy the CREATE statement of the item to the clipboard - + + Not containing + - - Ctrl+Return - + + Not equal to + - - Ctrl+L - + + Greater than + - - Ctrl+P - + + Less than + - - Ctrl+D - + + Greater or equal + - - Ctrl+I - + + Less or equal + - - Database encoding - + + Between this and... + - - Database is encrypted using SQLCipher - + + Regular expression + - - - Choose a database file - + + Edit Conditional Formats... + - - SQLite database files (*.db *.sqlite *.sqlite3 *.db3);;All files (*) - + + Set to NULL + - - Invalid file format. - + + Cut + - - - - - Choose a filename to save under - + + Copy + - - Error adding record: - - + + Copy with Headers + - - Error deleting record: -%1 - + + Copy as SQL + - - Please select a record first - + + Paste + - - %1 - %2 of %3 - + + Print... + - - - There is no database opened. Please open or create a new database file. - + + Use in Filter Expression + - - Are you sure you want to delete the %1 '%2'? -All data associated with the %1 will be lost. + + Alt+Del - - Error: could not delete the %1. Message from database engine: -%2 + + Ctrl+Shift+C - - There is no database opened. + + Ctrl+Alt+C - - %1 Rows returned from: %3 (took %2ms) - + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + - - Error executing query: %1 - + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + - - Query executed successfully: %1 (took %2ms) - + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + + + + FileExtensionManager - - Choose a text file - + + File Extension Manager + - - Text files(*.csv *.txt);;All files(*) - + + &Up + - - Import completed - + + &Down + - - Are you sure you want to undo all changes made to the database file '%1' since the last save? - + + &Add + - - Choose a file to import - + + &Remove + - - - - Text files(*.sql *.txt);;All files(*) - + + + Description + - - Do you want to create a new database file to hold the imported data? -If you answer no we will attempt to import the data in the SQL file to the current database. - + + Extensions + - - File %1 already exists. Please choose a different name. - + + *.extension + + + + FilterLineEdit - - Error importing data: %1 + + Filter - - Import completed. - + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + - - Delete View - + + Clear All Conditional Formats + - - Delete Trigger - + + Use for Conditional Format + - - Delete Index - + + Edit Conditional Formats... + - - &%1 %2 - + + Set Filter Expression + - - Setting PRAGMA values will commit your current transaction. -Are you sure? - + + What's This? + - - Select SQL file to open - + + Is NULL + - - Select file name - + + Is not NULL + - - Select extension file - + + Is empty + - - Extensions(*.so *.dll);;All files(*) - + + Is not empty + - - Extension successfully loaded. - + + Not containing... + - - - Error loading extension: %1 - + + Equal to... + - - Don't show again - + + Not equal to... + - - New version available. - + + Greater than... + - - A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. - + + Less than... + - - Choose a axis color - Choose an axis colour + + Greater or equal... + - - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) - + + Less or equal... + - - Choose a file to open - + + In range... + - - - DB Browser for SQLite project file (*.sqbpro) - + + Regular expression... + - PreferencesDialog + FindReplaceDialog - - Preferences - + + Find and Replace + - - &General - + + Fi&nd text: + - - Remember last location - + + Re&place with: + - - Always use this location - + + Match &exact case + - - Remember last location for session only - + + Match &only whole words + - - ... - + + When enabled, the search continues from the other end when it reaches one end of the page + - - Default &location - + + &Wrap around + - - Lan&guage - + + When set, the search goes backwards from cursor position, otherwise it goes forward + - - Automatic &updates - + + Search &backwards + - - - enabled - + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + - - &Database - + + &Selection only + - - Database &encoding - + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + - - Open databases with foreign keys enabled. - + + Use regular e&xpressions + - - &Foreign keys - + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + - - Remove line breaks in schema view - + + &Find Next + - - &Prefetch block size + + F3 - - Data &Browser - + + &Replace + - - NULL fields - + + Highlight all the occurrences of the text in the page + - - Text &colour - + + F&ind All + - - &Text - + + Replace all the occurrences of the text in the page + - - Bac&kground colour - + + Replace &All + - - &SQL - + + The searched text was not found + - - Settings name - + + The searched text was not found. + - - Context - + + The searched text was found one time. + - - Colour - + + The searched text was found %1 times. + - - Bold - + + The searched text was replaced one time. + - - Italic - + + The searched text was replaced %1 times. + + + + ForeignKeyEditor - - Underline - + + &Reset + - - Keyword - + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + + + + ImageViewer - - function - + + Image Viewer + - - Function - + + Reset the scaling to match the original size of the image. + - - Table - + + Set the scaling to match the size of the viewport. + - - Comment - + + Print... + - - Identifier - + + Open preview dialog for printing displayed image + - - String - + + Ctrl+P + + + + ImportCsvDialog - - currentline + + Import CSV file - - Current line - + + Table na&me + - - SQL &editor font size + + &Column names in first line - - SQL &log font size + + Field &separator - - Tab size: + + , - - SQL editor &font + + ; - - &Extensions + + + Tab - - Select extensions to load for every database: + + | - - Add extension + + Other - - Remove extension + + &Quote character - - <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> - + + + Other (printable) + - - Disable Regular Expression extension - + + + Other (code) + - - Choose a directory + + " - - The language will change after you restart the application. + + ' - - Select extension file + + &Encoding - - Extensions(*.so *.dll);;All files(*) + + UTF-8 - - - QObject - - Error importing data + + UTF-16 - - from record number %1 + + ISO-8859-1 - - . -%1 + + Trim fields? - - Decoding CSV file... - + + Separate tables + - - Cancel - + + Advanced + - - Collation needed! Proceed? - + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + - - A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. -If you choose to proceed, be aware bad things can happen to your database. -Create a backup! - + + Ignore default &values + - - - SqlExecutionArea - - Form - + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + - - Results of the last executed statements - + + Fail on missing values + - - This field shows the results and status codes of the last executed statements. - + + Disable data type detection + - - Export to &CSV - + + Disable the automatic data type detection when creating a new table. + - - Save as &view - + + Use local number conventions + - - Save as view - + + Use decimal and thousands separators according to the system locale. + - - Please specify the view name - + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + - - There is already an object with that name. Please choose a different name. + + Abort import + + + + + Ignore row + + + + + Replace existing row + + + + + Conflict strategy + + + + + + Deselect All + + + + + Match Similar + + + + + Select All + + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + + + + + There is already a table named '%1'. Do you want to import the data into it? + + + + + Creating restore point failed: %1 - - View successfully created. + + Creating the table failed: %1 - - Error creating view: %1 + + importing CSV + + + + + Could not prepare INSERT statement: %1 + + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + + + + + Inserting row failed: %1 - SqlUiLexer + MainWindow - - (X) The abs(X) function returns the absolute value of the numeric argument X. + + DB Browser for SQLite - - () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + + toolBar1 - - (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. - + + Opens the SQLCipher FAQ in a browser window + - - (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL - + + Export one or more table(s) to a JSON file + - - (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + + &File - - (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + + &Import - - (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + + &Export - - (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + + &Edit - - () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + + &View - - (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + + &Help - - (X,Y) The like() function is used to implement the "Y LIKE X" expression. + + DB Toolbar - - (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + + Edit Database &Cell + + + + + DB Sche&ma + + + + + &Remote + + + + + + Execute current line + + + + + This button executes the SQL statement present in the current editor line + + + + + Shift+F5 - - (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. + + Sa&ve Project + + + + + Open an existing database file in read only mode + + + + + User - - (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + + + + + Un/comment block of SQL code + + + + + Un/comment block + + + + + Comment or uncomment current line or selected block of code + + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + + + + + Ctrl+/ - - (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + + Stop SQL execution + + + + + Stop execution + + + + + Stop the currently running SQL script + + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + + + + + Too&ls + + + + + Application - - (X) ltrim(X) removes spaces from the left side of X. + + Error Log + + + + + This button clears the contents of the SQL logs + + + + + &Clear - - (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + + + + + + Project Toolbar + + + + + Extra DB toolbar + + + + + + + Close the current database file + + + + + &New Database... - - (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + + + Create a new database file - - (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + + This option is used to create a new database file. - - (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + + Ctrl+N - - (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + + + &Open Database... - - (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + + + + + + Open an existing database file - - () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + + + + This option is used to open an existing database file. - - (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + + Ctrl+O - - (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + + &Close Database - - (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + + This button closes the connection to the currently open database file + + + + + + Ctrl+W - - (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + + + Revert database to last saved state - - (X) rtrim(X) removes spaces from the right side of X. + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. - - (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + + + Write changes to the database file - - (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + + This option is used to save changes to the database file. - - (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + + Ctrl+S - - (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + + Compact &Database... + + + + + Compact the database file, removing space wasted by deleted records - - () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + + + Compact the database file, removing space wasted by deleted records. - - (X) trim(X) removes spaces from both ends of X. + + E&xit - - (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + + Ctrl+Q - - (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + + Import data from an .sql dump text file into a new or existing database. - - (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. - - (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + + Open a wizard that lets you import data from a comma separated text file into a database table. - - (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. - - - - - (timestring,modifier,modifier,...) + + Export a database to a .sql dump text file. - - (format,timestring,modifier,modifier,...) + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. - - (X) The avg() function returns the average value of all non-NULL X within a group. + + Export a database table as a comma separated text file. - - (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. - - (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database - - (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + + + Delete Table - - (X) The max() aggregate function returns the maximum value of all values in the group. + + Open the Delete Table wizard, where you can select a database table to be dropped. - - (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. - - - (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + + &Preferences... - - - SqliteTableModel - - Error changing data: -%1 + + + Open the preferences window. - - - VacuumDialog - - Compact Database + + &DB Toolbar - - Warning: Compacting the database will commit all changes you made. + + Shows or hides the Database toolbar. - - Please select the objects to compact: + + Shift+F1 + + + New &tab + + + + + Open SQL file(s) + + + + + This button opens files containing SQL statements and loads them in new editor tabs + + + + + Execute line + + + + + &Wiki + + + + + F1 + + + + + Bug &Report... + + + + + Feature Re&quest... + + + + + Web&site + + + + + &Donate on Patreon... + + + + + &Save Project + + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + + + + + Open &Project + + + + + This button lets you open a DB Browser for SQLite project file + + + + + Ctrl+Shift+O + + + + + &Save Project As... + + + + + + + Save the project in a file selected in a dialog + + + + + Save A&ll + + + + + + + Save DB file, project file and opened SQL files + + + + + Ctrl+Shift+S + + + + + Browse Table + + + + + Close Pro&ject + + + + + + Close project and database files and return to the initial state + + + + + Ctrl+Shift+F4 + + + + + + Detach Database + + + + + + Detach database file attached to the current database connection + + + + + &Attach Database... + + + + + Temp Store + + + + + Secure Delete + + + + + Case Sensitive Like + + + + + Journal Mode + + + + + Journal Size Limit + + + + + Recursive Triggers + + + + + Page Size + + + + + Foreign Keys + + + + + Auto Vacuum + + + + + Max Page Count + + + + + Checkpoint Full FSYNC + + + + + + Off + + + + + + Normal + + + + + + Full + + + + + Default + + + + + File + + + + + + Memory + + + + + Delete + + + + + Truncate + + + + + Persist + + + + + WAL + + + + + Exclusive + + + + + Automatic Index + + + + + Ignore Check Constraints + + + + + Full FSYNC + + + + + WAL Auto Checkpoint + + + + + User Version + + + + + Synchronous + + + + + None + + + + + Incremental + + + + + Locking Mode + + + + + + Add another database file to the current database connection + + + + + This button lets you add another database file to the current database connection + + + + + &Set Encryption... + + + + + SQLCipher &FAQ + + + + + Table(&s) to JSON... + + + + + Open Data&base Read Only... + + + + + Save results + + + + + Save the results view + + + + + This button lets you save the results of the last executed query + + + + + + Find text in SQL editor + + + + + Find + + + + + This button opens the search bar of the editor + + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + + + + + Find or replace + + + + + This button opens the find/replace dialog for the current editor tab + + + + + Ctrl+H + + + + + Export to &CSV + + + + + Export to &JSON + + + + + Save as &view + + + + + Save as view + + + + + Shows or hides the Project toolbar. + + + + + Extra DB Toolbar + + + + + &Open Database + + + + + New In-&Memory Database + + + + + Drag && Drop SELECT Query + + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + + + + + Drag && Drop Qualified Names + + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + + + + + Drag && Drop Enquoted Names + + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + + + + + &Integrity Check + + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + + + + + &Foreign-Key Check + + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + + + + + &Quick Integrity Check + + + + + Run a quick integrity check over the open DB + + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + + + + + &Optimize + + + + + Attempt to optimize the database + + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + + + + + + Print + + + + + Print text from current SQL editor tab + + + + + Open a dialog for printing the text in the current SQL editor tab + + + + + Print the structure of the opened database + + + + + Open a dialog for printing the structure of the opened database + + + + + + Ctrl+Shift+W + + + + + Table from CSV data in Clipboard... + + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + + + + + Show &Row Counts + + + + + This shows the number of rows for each table and view in the database. + + + + + Save Database &As... + + + + + Save the current database as a different file + + + + + Refresh + + + + + Reload the database structure + + + + + &Recently opened + + + + + Ctrl+T + + + + + SQL &Log + + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + + + + + &Recent Files + + + + + Show S&QL submitted by + + + + + &Plot + + + + + &New Database + + + + + + Ctrl+F4 + + + + + &Revert Changes + + + + + &Undo + + + + + + Undo last change to the database + + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + + + + + &Write Changes + + + + + &Database from SQL file... + + + + + &Table from CSV file... + + + + + &Database to SQL file... + + + + + &Table(s) as CSV file... + + + + + &Create Table... + + + + + &Delete Table... + + + + + &Modify Table... + + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + + + + + Create &Index... + + + + + W&hat's This? + + + + + &About + + + + + This button opens a new tab for the SQL editor + + + + + &Execute SQL + + + + + Execute all/selected SQL + + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + + + + + Ctrl+Shift+T + + + + + + + Save SQL file + + + + + &Load Extension... + + + + + Ctrl+E + + + + + Export as CSV file + + + + + Export table as comma separated values file + + + + + + Save the current session to a file + + + + + Open &Project... + + + + + + Load a working session from a file + + + + + + Save SQL file as + + + + + This button saves the content of the current SQL editor tab to a file + + + + + &Browse Table + + + + + Copy Create statement + + + + + Copy the CREATE statement of the item to the clipboard + + + + + Ctrl+Return + + + + + Ctrl+L + + + + + + Ctrl+P + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Encrypted + + + + + Read only + + + + + Database file is read only. Editing the database is disabled. + + + + + Database encoding + + + + + Database is encrypted using SQLCipher + + + + + + Choose a database file + + + + + + + Choose a filename to save under + + + + + Error checking foreign keys after table modification. The changes will be reverted. + + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + + + + + + At line %1: + + + + + Result: %2 + + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + + + + + Choose a file to import + + + + + Text files(*.sql *.txt);;All files(*) + + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + + + + + Automatically load the last opened DB file at startup + + + + + Alt+Shift+0 + + + + + The database is currently busy. + + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + + + + + Do you want to save the changes made to the project file '%1'? + + + + + File %1 already exists. Please choose a different name. + + + + + Error importing data: %1 + + + + + Import completed. + + + + + Delete View + + + + + Modify View + + + + + Delete Trigger + + + + + Modify Trigger + + + + + Delete Index + + + + + Modify Index + + + + + Modify Table + + + + + Do you want to save the changes made to SQL tabs in a new project file? + + + + + Do you want to save the changes made to the SQL file %1? + + + + + Could not find resource file: %1 + + + + + Choose a project file to open + + + + + Could not open project file for writing. +Reason: %1 + + + + + Busy (%1) + + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + + + + + Reset Window Layout + + + + + Click here to interrupt the currently running query. + + + + + Alt+Shift+W + + + + + Could not open database file. +Reason: %1 + + + + + In-Memory database + + + + + Choose a database file to save under + + + + + Error while saving the database to the new file. + + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + + + + + Are you sure you want to delete the view '%1'? + + + + + Are you sure you want to delete the trigger '%1'? + + + + + Are you sure you want to delete the index '%1'? + + + + + Error: could not delete the table. + + + + + Error: could not delete the view. + + + + + Error: could not delete the trigger. + + + + + Error: could not delete the index. + + + + + Message from database engine: +%1 + + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + + + + + Edit View %1 + + + + + Edit Trigger %1 + + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + + + + + -- EXECUTING SELECTION IN '%1' +-- + + + + + -- EXECUTING LINE IN '%1' +-- + + + + + -- EXECUTING ALL IN '%1' +-- + + + + + Result: %1 + + + + + %1 rows returned in %2ms + + + + + Choose text files + + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + + + + + Opened '%1' in read-only mode from recent file list + + + + + Opened '%1' from recent file list + + + + + &%1 %2%3 + + + + + (read only) + + + + + Open Database or Project + + + + + Attach Database... + + + + + Import CSV file(s)... + + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + + + + + Select SQL file to open + + + + + DB file '%1' could not be opened + + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + + + + + Table '%1' not found; settings ignored + + + + + -- Reference to file "%1" (not supported by this version) -- + + + + + Yes. Don't ask again + + + + + This action will open a new SQL tab with the following statements for you to edit and run: + + + + + Rename Tab + + + + + Duplicate Tab + + + + + Close Tab + + + + + Opening '%1'... + + + + + There was an error opening '%1'... + + + + + Value is not a valid URL or filename: %1 + + + + + Select file name + + + + + Ctrl+Tab + + + + + Ctrl+Shift+Tab + + + + + Clear List + + + + + Window Layout + + + + + Ctrl+0 + + + + + Simplify Window Layout + + + + + Dock Windows at Bottom + + + + + Dock Windows at Left Side + + + + + Dock Windows at Top + + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + + + + + + + Select extension file + + + + + Extension successfully loaded. + + + + + Error loading extension: %1 + + + + + + Don't show again + + + + + New version available. + + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + + + + + Project saved to file '%1' + + + + + Collation needed! Proceed? + + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + + + + + creating collation + + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + + + + + Please specify the view name + + + + + There is already an object with that name. Please choose a different name. + + + + + View successfully created. + + + + + Error creating view: %1 + + + + + This action will open a new SQL tab for running: + + + + + Press Help for opening the corresponding SQLite reference page. + + + + + DB Browser for SQLite project file (*.sqbpro) + + + + + Execution finished with errors. + + + + + Execution finished without errors. + + + + + NullLineEdit + + + Set to NULL + + + + + Alt+Del + + + + + PlotDock + + + Plot + + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used colour for that graph.</p></body></html> + + + + Columns + + + + + X + + + + + Y1 + + + + + Y2 + + + + + Axis Type + + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + + + + + Line type: + + + + + + None + + + + + Line + + + + + StepLeft + + + + + StepRight + + + + + StepCenter + + + + + Impulse + + + + + Point shape: + + + + + Cross + + + + + Plus + + + + + Circle + + + + + Disc + + + + + Square + + + + + Diamond + + + + + Star + + + + + Triangle + + + + + TriangleInverted + + + + + CrossSquare + + + + + PlusSquare + + + + + CrossCircle + + + + + PlusCircle + + + + + Peace + + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + + + + + Save current plot... + + + + + + Load all data and redraw plot + + + + + + + Row # + + + + + Copy + + + + + Print... + + + + + Help + + + + + Show legend + + + + + Stacked bars + + + + + Fixed number format + + + + + Date/Time + + + + + Date + + + + + Time + + + + + + Numeric + + + + + Label + + + + + Invalid + + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + + + + + Choose an axis color + Choose an axis colour + + + + Choose a filename to save under + + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + + + + + Loading all remaining data for this table took %1ms. + + + + + PreferencesDialog + + + Preferences + + + + + &General + + + + + Remember last location + + + + + Always use this location + + + + + Remember last location for session only + + + + + + + ... + + + + + Default &location + + + + + Lan&guage + + + + + Automatic &updates + + + + + + + + + + + + + + + enabled + + + + + Show remote options + + + + + &Database + + + + + Database &encoding + + + + + Open databases with foreign keys enabled. + + + + + &Foreign keys + + + + + SQ&L to execute after opening database + + + + + Data &Browser + + + + + Remove line breaks in schema &view + + + + + Prefetch block si&ze + + + + + Default field type + + + + + Font + + + + + &Font + + + + + Content + + + + + Symbol limit in cell + + + + + NULL + + + + + Regular + + + + + Binary + + + + + Background + + + + + Filters + + + + + Threshold for completion and calculation on selection + + + + + Escape character + + + + + Delay time (&ms) + + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + + + + + &SQL + + + + + Context + + + + + Colour + + + + + Bold + + + + + Italic + + + + + Underline + + + + + Keyword + + + + + Function + + + + + Table + + + + + Comment + + + + + Identifier + + + + + String + + + + + Current line + + + + + SQL &editor font size + + + + + Tab size + + + + + SQL editor &font + + + + + Error indicators + + + + + Hori&zontal tiling + + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + + + + + Code co&mpletion + + + + + Toolbar style + + + + + + + + + Only display the icon + + + + + + + + + Only display the text + + + + + + + + + The text appears beside the icon + + + + + + + + + The text appears under the icon + + + + + + + + + Follow the style + + + + + DB file extensions + + + + + Manage + + + + + Main Window + + + + + Database Structure + + + + + Browse Data + + + + + Execute SQL + + + + + Edit Database Cell + + + + + When this value is changed, all the other color preferences are also set to matching colors. + + + + + Follow the desktop style + + + + + Dark style + + + + + Application style + + + + + This sets the font size for all UI elements which do not have their own font size option. + + + + + Font size + + + + + Max Recent Files + + + + + Prompt to save SQL tabs +in new project file + + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + + + + + Database structure font size + + + + + Font si&ze + + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + + + + + Show images in cell + + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + + + + + Field display + + + + + Light style + + + + + Displayed &text + + + + + Formatted + + + + + + + + + + + + Click to set this color + + + + + Text color + Text colour + + + + Background color + Background colour + + + + + Preview only (N/A) + + + + + Foreground + + + + + Selection background + + + + + Selection foreground + + + + + Highlight + + + + + SQL &results font size + + + + + Use tabs for indentation + + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + + + + + &Wrap lines + + + + + Never + + + + + At word boundaries + + + + + At character boundaries + + + + + At whitespace boundaries + + + + + &Quotes for identifiers + + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + + + + + "Double quotes" - Standard SQL (recommended) + + + + + `Grave accents` - Traditional MySQL quotes + + + + + [Square brackets] - Traditional MS SQL Server quotes + + + + + Keywords in &UPPER CASE + + + + + When set, the SQL keywords are completed in UPPER CASE letters. + + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + + + + + Close button on tabs + + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + + + + + &Extensions + + + + + Select extensions to load for every database: + + + + + Add extension + + + + + Remove extension + + + + + Select built-in extensions to load for every database: + + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + + + + + Disable Regular Expression extension + + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + + + + + Allow loading extensions from SQL code + + + + + Remote + + + + + CA certificates + + + + + Proxy + + + + + Configure + + + + + Export Settings + + + + + Import Settings + + + + + + Subject CN + + + + + Common Name + + + + + Subject O + + + + + Organization + + + + + + Valid from + + + + + + Valid to + + + + + + Serial number + + + + + Your certificates + + + + + File + + + + + Subject Common Name + + + + + Issuer CN + + + + + Issuer Common Name + + + + + Clone databases into + + + + + + Choose a directory + + + + + + The language will change after you restart the application. + + + + + Select extension file + + + + + Extensions(*.so *.dylib *.dll);;All files(*) + + + + + Import certificate file + + + + + No certificates found in this file. + + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + + + + + Save Settings File + + + + + + Initialization File (*.ini) + + + + + The settings file has been saved in location : + + + + + + Open Settings File + + + + + The settings file was loaded properly. + + + + + The selected settings file is not a normal settings file. +Please check again. + + + + + ProxyDialog + + + Proxy Configuration + + + + + Pro&xy Type + + + + + Host Na&me + + + + + Port + + + + + Authentication Re&quired + + + + + &User Name + + + + + Password + + + + + None + + + + + System settings + + + + + HTTP + + + + + SOCKS5 + + + + + QObject + + + Error importing data + + + + + from record number %1 + + + + + . +%1 + + + + + Importing CSV file... + + + + + Cancel + + + + + All files (*) + + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + + + + + Left + + + + + Right + + + + + Center + + + + + Justify + + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + + + + + DB Browser for SQLite Project Files (*.sqbpro) + + + + + SQL Files (*.sql) + + + + + All Files (*) + + + + + Text Files (*.txt) + + + + + Comma-Separated Values Files (*.csv) + + + + + Tab-Separated Values Files (*.tsv) + + + + + Delimiter-Separated Values Files (*.dsv) + + + + + Concordance DAT files (*.dat) + + + + + JSON Files (*.json *.js) + + + + + XML Files (*.xml) + + + + + Binary Files (*.bin *.dat) + + + + + SVG Files (*.svg) + + + + + Hex Dump Files (*.dat *.bin) + + + + + Extensions (*.so *.dylib *.dll) + + + + + Initialization File (*.ini) + + + + + RemoteCommitsModel + + + Commit ID + + + + + Message + + + + + Date + + + + + Author + + + + + Size + + + + + Authored and committed by %1 + + + + + Authored by %1, committed by %2 + + + + + RemoteDatabase + + + Error opening local databases list. +%1 + + + + + Error creating local databases list. +%1 + + + + + RemoteDock + + + Remote + + + + + Identity + + + + + Push currently opened database to server + + + + + Upload + + + + + DBHub.io + + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + + + + + Local + + + + + Current Database + + + + + Clone + + + + + &User + + + + + &Database + + + + + Branch + + + + + Commits + + + + + Commits for + + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + + + + + Back + + + + + Delete Database + + + + + Delete the local clone of this database + + + + + Open in Web Browser + + + + + Open the web page for the current database in your browser + + + + + Clone from Link + + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + + + + + Refresh + + + + + Reload all data and update the views + + + + + Clone Database + + + + + Open Database + + + + + Open the local copy of this database + + + + + Check out Commit + + + + + Download and open this specific commit + + + + + Check out Latest Commit + + + + + Check out the latest commit of the current branch + + + + + Save Revision to File + + + + + Saves the selected revision of the database to another file + + + + + Upload Database + + + + + Upload this database as a new commit + + + + + Select an identity to connect + + + + + Public + + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + + + + + Invalid URL: The host name does not match the host name of the current identity. + + + + + Invalid URL: No branch name specified. + + + + + Invalid URL: No commit ID specified. + + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + + + + + The database has unsaved changes. Are you sure you want to push it before saving? + + + + + The database you are trying to delete is currently opened. Please close it before deleting. + + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + + + + + RemoteLocalFilesModel + + + Name + + + + + Branch + + + + + Last modified + + + + + Size + + + + + Commit + + + + + File + + + + + RemoteModel + + + Name + + + + + Commit + + + + + Last modified + + + + + Size + + + + + Size: + + + + + Last Modified: + + + + + Licence: + + + + + Default Branch: + + + + + RemoteNetwork + + + Choose a location to save the file + + + + + Error opening remote file at %1. +%2 + + + + + Error: Invalid client certificate specified. + + + + + Please enter the passphrase for this client certificate in order to authenticate. + + + + + Cancel + + + + + Uploading remote database to +%1 + + + + + Downloading remote database from +%1 + + + + + Error: Cannot open the file for sending. + + + + + RemotePushDialog + + + Push database + + + + + Database na&me to push to + + + + + Commit message + + + + + Database licence + + + + + Public + + + + + Branch + + + + + Force push + + + + + Username + + + + + Database will be public. Everyone has read access to it. + + + + + Database will be private. Only you have access to it. + + + + + Use with care. This can cause remote commits to be deleted. + + + + + RunSql + + + Execution aborted by user + + + + + , %1 rows affected + + + + + query executed successfully. Took %1ms%2 + + + + + executing query + + + + + SelectItemsPopup + + + A&vailable + + + + + Sele&cted + + + + + SqlExecutionArea + + + Form + + + + + Find previous match [Shift+F3] + + + + + Find previous match with wrapping + + + + + Shift+F3 + + + + + The found pattern must be a whole word + + + + + Whole Words + + + + + Text pattern to find considering the checks in this frame + + + + + Find in editor + + + + + The found pattern must match in letter case + + + + + Case Sensitive + + + + + Find next match [Enter, F3] + + + + + Find next match with wrapping + + + + + F3 + + + + + Interpret search pattern as a regular expression + + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + + Regular Expression + + + + + + Close Find Bar + + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + + + + + Results of the last executed statements + + + + + This field shows the results and status codes of the last executed statements. + + + + + Ctrl+PgUp + + + + + Ctrl+PgDown + + + + + Couldn't read file "%1": %2. + + + + + + Couldn't save file: %1. + + + + + Your changes will be lost when reloading it! + + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + + + + + Answer "No to All" to ignore any external update without further prompting. + + + + + Modifying and saving the file will restore prompting. + + + + + SqlTextEdit + + + Ctrl+/ + + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + + + + + (X) ltrim(X) removes spaces from the left side of X. + + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + + + + + (X) rtrim(X) removes spaces from the right side of X. + + + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + + + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + + + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + + + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + + + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + + + + + (X) trim(X) removes spaces from both ends of X. + + + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + + + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + + + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + + + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + + + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + + + + + + + + (timestring,modifier,modifier,...) + + + + + (format,timestring,modifier,modifier,...) + + + + + (X) The avg() function returns the average value of all non-NULL X within a group. + + + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + + + + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + + + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + + + + + (X) The max() aggregate function returns the maximum value of all values in the group. + + + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + + + + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + + + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + + + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + + + + + (X) Return the arccosine of X. The result is in radians. + + + + + (X) Return the hyperbolic arccosine of X. + + + + + (X) Return the arcsine of X. The result is in radians. + + + + + (X) Return the hyperbolic arcsine of X. + + + + + (X) Return the arctangent of X. The result is in radians. + + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + + + + + (X) Return the hyperbolic arctangent of X. + + + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + + + + + (X) Return the cosine of X. X is in radians. + + + + + (X) Return the hyperbolic cosine of X. + + + + + (X) Convert value X from radians into degrees. + + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + + + + + (X) Return the natural logarithm of X. + + + + + (B,X) Return the base-B logarithm of X. + + + + + + (X) Return the base-10 logarithm for X. + + + + + (X) Return the logarithm base-2 for the number X. + + + + + (X,Y) Return the remainder after dividing X by Y. + + + + + () Return an approximation for Ï€. + + + + + + (X,Y) Compute X raised to the power Y. + + + + + (X) Convert X from degrees into radians. + + + + + (X) Return the sine of X. X is in radians. + + + + + (X) Return the hyperbolic sine of X. + + + + + (X) Return the square root of X. NULL is returned if X is negative. + + + + + (X) Return the tangent of X. X is in radians. + + + + + (X) Return the hyperbolic tangent of X. + + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + + + + + SqliteTableModel + + + reading rows + + + + + loading... + + + + + References %1(%2) +Hold %3Shift and click to jump there + + + + + Error changing data: +%1 + + + + + retrieving list of columns + + + + + Fetching data... + + + + + + Cancel + + + + + TableBrowser + + + Browse Data + + + + + &Table: + + + + + Select a table to browse data + + + + + Use this list to select a table to be displayed in the database view + + + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + + + + + Text pattern to find considering the checks in this frame + + + + + Find in table + + + + + Find previous match [Shift+F3] + + + + + Find previous match with wrapping + + + + + Shift+F3 + + + + + Find next match [Enter, F3] + + + + + Find next match with wrapping + + + + + F3 + + + + + The found pattern must match in letter case + + + + + Case Sensitive + + + + + The found pattern must be a whole word + + + + + Whole Cell + + + + + Interpret search pattern as a regular expression + + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + + Regular Expression + + + + + + Close Find Bar + + + + + Text to replace with + + + + + Replace with + + + + + Replace next match + + + + + + Replace + + + + + Replace all matches + + + + + Replace all + + + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + + + + + Export to &JSON + + + + + + Export the filtered data to JSON + + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + + + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + + + + + Copy column name + + + + + Copy the database table column name to your clipboard + + + + + New Data Browser + + + + + + Add a new docked Data Browser + + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + + + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + + + + + |< + + + + + Scroll one page upwards + + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + + + + + < + + + + + 0 - 0 of 0 + + + + + Scroll one page downwards + + + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + + + + + > + + + + + Scroll to the end + + + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + + + + + >| + + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + + + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + + + + + Go to: + + + + + Enter record number to browse + + + + + Type a record number in this area and click the Go to: button to display the record in the database view + + + + + 1 + + + + + Show rowid column + + + + + Toggle the visibility of the rowid column + + + + + Unlock view editing + + + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + + + + + Edit display format + + + + + Edit the display format of the data in this column + + + + + + New Record + + + + + + Insert a new record in the current table + + + + + + Delete Record + + + + + Delete the current record + + + + + + This button deletes the record or records currently selected in the table + + + + + + Insert new record using default values in browsed table + + + + + Insert Values... + + + + + + Open a dialog for inserting values in a new record + + + + + Export to &CSV + + + + + + Export the filtered data to CSV + + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + + + + + Save as &view + + + + + + Save the current filter, sort column and display formats as a view + + + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + + + + + Save Table As... + + + + + + Save the table as currently displayed + + + + + Hide column(s) + + + + + Hide selected column(s) + + + + + Show all columns + + + + + Show all columns that were hidden + + + + + + Set encoding + + + + + Change the encoding of the text in the table cells + + + + + Set encoding for all tables + + + + + Change the default encoding assumed for all tables in the database + + + + + Clear Filters + + + + + Clear all filters + + + + + + This button clears all the filters set in the header input fields for the currently browsed table. + + + + + Clear Sorting + + + + + Reset the order of rows to the default + + + + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + + + + + Print + + + + + Print currently browsed table data + + + + + Print currently browsed table data. Print selection if more than one cell is selected. + + + + + Ctrl+P + + + + + Refresh + + + + + Refresh the data in the selected table + + + + + This button refreshes the data in the currently selected table. + + + + + F5 + + + + + Find in cells + + + + + Open the find tool bar which allows you to search for values in the table view below. + + + + + + Bold + + + + + Ctrl+B + + + + + + Italic + + + + + + Underline + + + + + Ctrl+U + + + + + + Align Right + + + + + + Align Left + + + + + + Center Horizontally + + + + + + Justify + + + + + + Edit Conditional Formats... + + + + + Edit conditional formats for the current column + + + + + Clear Format + + + + + Clear All Formats + + + + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + + + + + + Font Color + + + + + + Background Color + + + + + Toggle Format Toolbar + + + + + Show/hide format toolbar + + + + + + This button shows or hides the formatting toolbar of the Data Browser + + + + + Select column + + + + + Ctrl+Space + + + + + Replace text in cells + + + + + Freeze columns + + + + + Make all columns from the first column up to this column not move when scrolling horizontally + + + + + Filter in any column + + + + + Ctrl+R + + + + + %n row(s) + + %n row + %n rows + + + + + , %n column(s) + + , %n column + , %n columns + + + + + . Sum: %1; Average: %2; Min: %3; Max: %4 + + + + + Conditional formats for "%1" + + + + + determining row count... + + + + + %L1 - %L2 of >= %L3 + + + + + %L1 - %L2 of %L3 + + + + + (clipped at %L1 rows) + + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + + + + + Delete Records + + + + + Duplicate records + + + + + Duplicate record + + + + + Ctrl+" + + + + + Adjust rows to contents + + + + + Error deleting record: +%1 + + + + + Please select a record first + + + + + Please choose a new encoding for all tables. + + + + + Please choose a new encoding for this table. + + + + + %1 +Leave the field empty for using the database encoding. + + + + + This encoding is either not valid or not supported. + + + + + %1 replacement(s) made. + + + + + TableBrowserDock + + + New Data Browser + + + + + Rename Data Browser + + + + + Close Data Browser + + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + + + + + VacuumDialog + + + Compact Database + + + + + Warning: Compacting the database will commit all of your changes. + + + + + Please select the databases to co&mpact: + + diff --git a/src/translations/sqlb_es_ES.ts b/src/translations/sqlb_es_ES.ts index 01b699a6b..d206bd48b 100644 --- a/src/translations/sqlb_es_ES.ts +++ b/src/translations/sqlb_es_ES.ts @@ -1,2844 +1,8095 @@ - + - + AboutDialog About DB Browser for SQLite - Acerca de DB Browser para SQLite + Acerca de «DB Browser for SQLite» - + Version Versión - - <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:small;">It also uses the Silk icon set by Mark James licensed under a Creative Commons Attribution 2.5 and 3.0 license.<br/>See </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> - <html><head/><body> -<p>DB Browser para SQLite es una herramienta gratuita y de código abierto usada para crear, diseñar y editar archivos de bases de datos de SQLite.</p> -<p>Está doblemente licenciada con Mozilla Public License Version 2, y también con GNU General Public License Version 3 o posterior. Puede modificarla o redistribuirla bajo las condiciones de esas licencias.</p> -<p>Vea <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> y <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> para los detalles.</p> -<p>Para más información acerca de este programa por favor, visite nuestra página web en: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p> -<p><span style=" font-size:small;">Este software usa el GPL/LGPL Qt Toolkit de </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>Vea </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> para más información y las condiciones de la licencia.</span> -</p><p><span style=" font-size:small;">También usa el Silk icon set de Mark James licenciado bajo Creative Commons Attribution 2.5 y 3.0.<br/>Vea </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> para los detalles.</span></p></body></html> - + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + <html><head/><body><p><em>DB Browser for SQLite</em> es una herramienta visual gratuita y de código abierto que se utiliza para crear, diseñar y editar archivos de bases de datos SQLite.</p><p>Tiene licencia doble bajo la Licencia Pública de Mozilla versión 2, así como la Licencia Pública General de GNU versión 3 o posterior. Puede modificarlo o redistribuirlo bajo las condiciones de estas licencias.</p><p>Vea <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> y <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> para los detalles.</p><p>Para obtener más información sobre este programa, visite nuestra página en: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">Esta aplicación usa el Qt Toolkit GPL/LGPL de </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>Vea </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> para los detalles y los términos de licencia.</span></p><p><span style=" font-size:8pt;">Utilizamos la biblioteca nalgeon/sqlen para el soporte de extensiones SQLite.<br/>Esta biblioteca se distribuye bajo la licencia MIT, vea lo siguiente para más información:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">También utiliza el conjunto de iconos SVG de Michael Buckley bajo licencia Creative Commons Attribution Share Alike 4.0.<br/>Vea </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> para los detalles.</span></p></body></html> + + + AddRecordDialog - - Version - Versión + + Add New Record + Añadir nuevo registro - - Qt Version - Versión de Qt + + Enter values for the new record considering constraints. Fields in bold are mandatory. + Introduzca valores para el nuevo registro teniendo en cuenta las restricciones. Los campos en negrita son obligatorios. - - SQLCipher Version - Versión de SQLCipher + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + En la columna Valor puede especificar el valor del campo identificado en la columna Nombre. La columna Tipo indica el tipo de campo. Los valores por defecto se muestran en la misma tipografía que los valores NULL. - - SQLite Version - Versión de SQLite + + Name + Nombre - - - Application - - Usage: %1 [options] [db] - - Uso: %1 [opciones] [bd] - + + Type + Tipo - - Possible command line arguments: - Argumentos de línea de comandos disponibles: + + Value + Valor - - -h, --help Show command line options - -h, --help Muestra opciones de línea de comandos + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + Valores a insertar. Los valores mostrados por defecto son insertados automáticamente a menos que se cambien. - - -s, --sql [file] Execute this SQL file after opening the DB - -s, --sql [archivo] Ejecuta este archivo de SQL tras abrir la BB.DD. + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + Cuando se editan los valores en el cuadro superior, aquí se muestra la consulta SQL para insertar este nuevo registro. Puede editarla antes de guardar. - - -q, --quit Exit application after running scripts - -q, --quit Salir de la aplicación tras ejecutar los scripts + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Guardar</span> enviará a la base de datos la sentencia SQL mostrada para insertar el nuevo registro.</p><p><span style=" font-weight:600;">Restituir valores por Defecto</span> restituirá los valores iniciales en la columna <span style=" font-weight:600;">Valor</span></p><p><span style=" font-weight:600;">Cancelar</span> cierra este diálogo sin ejecutar la consulta.</p></body></html> - - [file] Open this SQLite database - [archivo] Abrir esta base de datos de SQLite + + Auto-increment + + Auto-incremento + - - The -s/--sql option requires an argument - La opción -s/--sql necesita un argumento + + Unique constraint + + Restricción UNIQUE + - - The file %1 does not exist - El archivo %1 no existe + + Check constraint: %1 + + Restricción CHECK: %1 + - - Invalid option/non-existant file: %1 - Opción inválida o archivo inexistente: %1 + + Foreign key: %1 + + Clave foránea: %1 + - - - CipherDialog - - SQLCipher encryption - Cifrado con SQLCipher + + Default value: %1 + + Valor por defecto: %1 + - - &Password - &Clave + + Error adding record. Message from database engine: + +%1 + Error añadiendo registro. Mensaje de la base de datos: + +%1 - - &Reenter password - &Reintroducir clave + + Are you sure you want to restore all the entered values to their defaults? + ¿Está seguro de que quiere restaurar todos los valores introducidos a sus valores por defecto? + + + Application - - Page &size - &Tamaño de página + + Possible command line arguments: + Argumentos de línea de comandos disponibles: - - Please set a key to encrypt the database. -Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. -Leave the password fields empty to disable the encryption. -The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. - Por favor, elija una clave para cifrar la base de datos. -Tenga en cuenta que si modifica cualquiera de los otros ajustes opcionales necesitará reintroducirlos también cada vez que abra la base de datos. -Deje los campos de clave vacíos para no usar cifrado. -El proceso de cifrado puede llevar algún tiempo y ¡debería hacer una copia de seguridad de la base de datos! Los cambios no guardados son aplicados antes de modificar el cifrado. + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + Las opciones -o/--option y -O/--save-option requieren un argumento de la forma grupo/ajuste=valor - - Please enter the key used to encrypt the database. -If any of the other settings were altered for this database file you need to provide this information as well. - Por favor, introduzca la clave a usar en el cifrardo de la base de datos. -Si se modificaron cualquiera de los otros ajustes para este archivo de base de datos, también tendrá que proporcionar esta información. + + The user settings file location is replaced with the argument value instead of the environment variable value. + La ubicación del archivo de ajustes de usuario es reemplazada por el valor del argumento, en vez del valor de la variable de entorno. - - - CreateIndexDialog - - Create New Index - Crear un Ãndice Nuevo + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + Valor ignorado de la variable de entorno (DB4S_SETTINGS_FILE): - - &Name - &Nombre + + + The file %1 does not exist + El archivo %1 no existe - - &Columns - &Columnas + + Usage + Uso - - Column - Columna + + options + opciones - - Use in Index - Usar como Ãndice + + + database + base-de-datos - - Order - Orden + + + project + proyecto - - &Table - &Tabla + + + csv-file + archivo-csv - - &Unique - &Único + + Show command line options + Mostrar opciones de línea de comandos - - Creating the index failed: -%1 - Creación de índice fallida: -%1 + + Exit application after running scripts + Salir de la aplicación tras ejecutar los scripts - - - DBBrowserDB - - - - - no error - Sin errores + + + file + archivo - - Please specify the database name under which you want to access the attached database - Por favor, especifique el nombre de la base de datos con el que acceder a la base de datos anexada + + Execute this SQL file after opening the DB + Ejecutar este archivo de SQL tras abrir la base de datos - - Do you want to save the changes made to the database file %1? - ¿Guardar los cambios hechos a la base de datos %1? + + Import this CSV file into the passed DB or into a new DB + Importar este archivo CSV a la base de datos pasada o en una nueva base de datos - - Exporting database to SQL file... - Exportando base de datos a un archivo SQL + + table + tabla - - - Cancel - Cancelar + + Browse this table, or use it as target of a data import + Mostrar esta tabla en la hoja de datos tras abrir la base de datos - - Executing SQL... - Ejecutando SQL... + + Open database in read-only mode + Abrir base de datos en modo de solo-lectura - - Action cancelled. - Acción cancelada. + + settings_file + The other command-line placeholders are using "-" so this is more consistent than the original. + archivo-ajustes - - - Error in statement #%1: %2. -Aborting execution. - Error en la consulta #%1: %2. -Abortando ejecución. + + Run application based on this settings file + Ejecutar la aplicación basándose en este archivo de ajustes - - renameColumn: cannot find table %1. - renameColumn: no se puede encontrar la tabla %1. + + + group + grupo - - renameColumn: cannot find column %1. - renameColumn: no se puede encontrar la columna %1. + + + settings + ajustes - - renameColumn: creating savepoint failed. DB says: %1 - renameColumn: creación del savepoint fallido. La BB.DD. dice: %1 + + + value + valor - - renameColumn: creating new table failed. DB says: %1 - renameColumn: creación de la nueva tabla fallida. La BB.DD. dice: %1 + + Run application with this setting temporarily set to value + Ejecutar la aplicación con este ajuste establecido temporalmente a este valor - - renameColumn: copying data to new table failed. DB says: -%1 - renameColumn: copia de datos a la nueva table fallida. La BB.DD. dice: -%1 + + Run application saving this value for this setting + Ejecutar la aplicación guardando este valor para este ajuste - - renameColumn: deleting old table failed. DB says: %1 - renameColumn: borrado de tabla fallido. La BB.DD. dice: %1 + + Display the current version + Mostrar la versión actual - - Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: - - - La restitución de algunos de los objetos asociados con esta tabla falló. Lo más probable es que esto suceda porque han cambiado los nombres de algunas columnas. Esta es la consulta SQL que puede que quiera corregir y ejecutar manualmente: - - + + Open this SQLite database + Abrir esta base de datos SQLite - - renameColumn: releasing savepoint failed. DB says: %1 - renameColumn: liberación del savepoint fallido. La BB.DD. dice: %1 + + Open this project file (*.sqbpro) + Abrir este archivo de proyecto (*.sqbpro) - - Error renaming table '%1' to '%2'.Message from database engine: -%3 - Error renombrando la tabla '%1' a '%2'. Mensaje de la base de datos: -%3 + + Import this CSV file into an in-memory database + Importar este archivo CSV a una base de datos en memoria + + + + + + The %1 option requires an argument + La opción %1 necesita un argumento - - ... <string can not be logged, contains binary data> ... - ... <la cadena no se puede 'logear'; contiene datos binarios> ... + + The -S/--settings option requires an argument. The option is ignored. + La opción -S/--settings necesita un argumento. La opción es ignorada. - - unknown object type %1 - tipo de objeto desconocido %1 + + SQLite Version + Versión de SQLite - - could not get list of db objects: %1, %2 - No se pudo obtener la lista de objetos de la base de datos: %1, %2 + + SQLCipher Version %1 (based on SQLite %2) + Versión de SQLCipher %1 (basado en SQLite %2) - - could not get types - No se pudieron obtener los tipos + + DB Browser for SQLite Version %1. + «DB Browser for SQLite» Versión %1. - - didn't receive any output from pragma %1 - No se obtuvo ninguna salida del pragma %1 + + Last commit hash when built: %1 + Último «commit hash» cuando fue compilado: %1 - - could not execute pragma command: %1, %2 - No se pudo ejecutar el comando pragma: %1, %2 + + Built for %1, running on %2 + Compilado para %1, ejecutándose en %2 - - Error setting pragma %1 to %2: %3 - Error definiendo pragma %1 como %2: %3 + + Qt Version %1 + Versión de Qt %1 - - File not found. - Archivo no encontrado. + + Invalid option/non-existent file: %1 + Opción inválida o archivo inexistente: %1 - DbStructureModel + CipherDialog - - Name - Nombre + + SQLCipher encryption + Cifrado con SQLCipher - - Object - Objeto + + &Password + &Clave - - Type - Tipo + + &Reenter password + &Reintroducir clave - - Schema - Esquema + + Encr&yption settings + Ajustes de &cifrado - - Tables (%1) - Tablas (%1) + + SQLCipher &3 defaults + Predeterminados de SQLCipher &3 - - Indices (%1) - Ãndices (%1) + + SQLCipher &4 defaults + Predeterminados de SQLCipher &4 - - Views (%1) - Vistas (%1) + + Custo&m + &Personalizado - - Triggers (%1) - Disparadores (%1) + + Page si&ze + &Tamaño de página - - - EditDialog - - Edit database cell - Editar celda de la base de datos + + &KDF iterations + Iteraciones &KDF - - Import text - Importar texto + + HMAC algorithm + Algoritmo HMAC - - Opens a file dialog used to import text to this database cell. - Abre una ventana para importar texto a esta celda de la base de datos + + KDF algorithm + Algoritmo KDF - - &Import - &Importar + + Plaintext Header Size + Tamaño de la cabecera del texto en claro - - Export text - Exportar texto + + Passphrase + Frase de contraseña - - Opens a file dialog used to export the contents of this database cell to a text file. - Abre una ventana para exportar el contenido de esta celda de la base de datos a un archivo de texto + + Raw key + Clave en bruto - - &Export - &Exportar + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + Por favor, elija una clave para cifrar la base de datos. +Tenga en cuenta que: +- Si modifica cualquiera de los otros ajustes opcionales necesitará + reintroducirlos también cada vez que abra la base de datos. +- Puede dejar los campos de clave en blanco para no usar cifrado. +- El proceso de cifrado puede llevar algún tiempo. +- ¡Debería hacer una copia de respaldo de la base de datos! +- Los cambios no guardados son aplicados antes de modificar el cifrado. - - Text - Texto + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + Por favor, introduzca la clave a usar en el cifrado de la base de datos. +Si se modificaron cualquiera de los otros ajustes para este archivo de base de datos, también tendrá que proporcionar esta información. + + + ColumnDisplayFormatDialog - - Binary - Binario + + Choose display format + Elija el formato de presentación - - Clear cell data - Borrar datos de la celda + + Display format + Formato de presentación - - Erases the contents of the cell - Borra el contenido de la celda + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + Elija el formato para la columna «%1» el cual se aplicará a cada valor antes de mostrarlo. - - &Clear - &Borrar + + Default + Por defecto - - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Warning: Editing binary content in text mode may result in corrupted data!</span></p></body></html> - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">¡Precaución: Editar contenido binario en modo texto puede dañar los datos!</span></p></body></html> + + Decimal number + Número decimal - - This area displays information about the data present in this database cell - Esta zona muestra información acerca de los datos presentes en esta celda de la base de datos + + Exponent notation + Notación exponencial - - Type of data currently in cell - Tipo de datos actualmente en la celda + + Hex blob + Secuencia hexadecimal - - Size of data currently in table - Tamaño de los datos actualmente en la tabla + + Hex number + Número hexadecimal - - Choose a file - Seleccione un archivo + + Apple NSDate to date + Fecha de Apple NSDate a fecha - - Text files(*.txt);;Image files(%1);;All files(*) - Archivos de texto(*.txt);;Archivos de imagen(%1);;Todos los archivos(*) + + Java epoch (milliseconds) to date + Tiempo Java (milisegundos) a fecha - - Choose a filename to export data - Seleccione un nombre de archivo para exportar los datos + + .NET DateTime.Ticks to date + DateTime.Ticks de .NET a fecha - - Text files(*.txt);;All files(*) - Archivos de texto(*.txt);;Todos los archivos(*) + + Julian day to date + Fecha juliana a fecha - - Type of data currently in cell: Null - Tipo de datos actualmente en la celda: Null + + Unix epoch to local time + Tiempo Unix a hora local - - Type of data currently in cell: Text / Numeric - Tipo de datos actualmente en la celda: Texto / Numérico + + WebKit / Chromium epoch to date + WebKit / Chromium epoch a fecha - - - %n char(s) - - %n carácter - %n caracteres - + + + WebKit / Chromium epoch to local time + WebKit / Chromium epoch a hora local - - Type of data currently in cell: Image - Tipo de datos actualmente en la celda: Imagen + + Date as dd/mm/yyyy + Fecha dd/mm/aaaa - - %1x%2 pixel - %1x%2 pixel + + Lower case + Minúsculas - - Type of data currently in cell: Binary - Tipo de datos actualmente en la celda: Binario + + Binary GUID to text + GUID binario a texto - - - %n byte(s) - - %n byte - %n bytes - + + + SpatiaLite Geometry to SVG + Geometría SpatiaLite a SVG - - - EditTableDialog - - Edit table definition - Editar la definición de la tabla + + Custom display format must contain a function call applied to %1 + El formato de presentación a medida tiene que contener una llamada de función aplicada a %1 - - Table - Tabla + + Error in custom display format. Message from database engine: + +%1 + Error en el formato de presentación a medida. Mensaje del motor de la base de datos: + +%1 - - Advanced - Avanzado + + Custom display format must return only one column but it returned %1. + El formato de presentación a medida debe devolver sólo una columna pero ha devuelto %1. - - Make this a 'WITHOUT rowid' table. Setting this flag requires a field of type INTEGER with the primary key flag set and the auto increment flag unset. - Hacer de esta una tabla 'SIN rowid'. Para activar este flag es necesario un campo de tipo ENTERO con la clave primaria activada y el flag de autoincremento desactivado. + + Octal number + Número octal - - Without Rowid - Sin Rowid + + Round number + Número redondeado - - Fields - Campos + + Unix epoch to date + Tiempo Unix a fecha + + + + Upper case + Mayúsculas - - Add field - Añadir campo + + Windows DATE to date + Fecha Windows a fecha - - Remove field - Eliminar campo + + Custom + A medida + + + CondFormatManager - - Move field up - Mover campo hacia arriba + + Conditional Format Manager + Gestor de Formato Condicional - - Move field down - Mover campo hacia abajo + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + Este diálogo permite crear y editar formatos condicionales. Cada estilo de celda será seleccionado por la primera condición que se cumpla para los datos de esa celda. Los formatos condicionales se pueden mover arriba y abajo, teniendo precedencia aquellos en líneas superiores sobre los inferiores. La sintaxis es la misma que para los filtros y se aplica una condición vacía a todos los valores. - - Name - Nombre + + Add new conditional format + Añadir un nuevo formato condicional - - Type - Tipo + + &Add + &Añadir - - - Not null - No nulo + + Remove selected conditional format + Elimina el formato condicional seleccionado - - PK - PK + + &Remove + &Eliminar - - Primary key - Clave primaria + + Move selected conditional format up + Mueve arriba el formato condicional seleccionado - - AI - AI + + Move &up + Mueve a&rriba - - Autoincrement - Autoincremento + + Move selected conditional format down + Mueve abajo el formato condicional seleccionado - - U - U + + Move &down + Mueve a&bajo - - Unique - Único + + Foreground + Texto - - Default - Default + + Text color + Color del texto - - Default value - Valor por defecto + + Background + Fondo - - Check - Check + + Background color + Color del fondo - - Check constraint - Comprobar restricción + + Font + Tipo de letra - - Foreign Key - Foreign Key + + Size + Tamaño - - Error creating table. Message from database engine: -%1 - Error creando la tabla. Mensaje de la base de datos: -%1 + + Bold + Negrita - - There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. - Hay al menos una línea con este campo NULO. Esto hace imposible activar este flag. Por favor, modifique antes los datos de la tabla. + + Italic + Cursiva - - There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. - Hay al menos una línea con un valor no entero en este campo. Esto hace imposible activar el flag AI. Por favor, modifique antes los datos de la tabla. + + Underline + Subrayado - - Column `%1` has no unique data. - - La columna '%1' no tiene datos únicos. - + + Alignment + Justificado - - This makes it impossible to set this flag. Please change the table data first. - Esto hace imposible activar este flag. Por favor, modifique antes los datos de la tabla. + + Condition + Condición - - Are you sure you want to delete the field '%1'? -All data currently stored in this field will be lost. - ¿Está seguro de que quiere borrar este campo '%1'? -Todos los datos actualmente almacenados en este campo se perderán. + + + Click to select color + Haga clic para seleccionar el color - - Please add a field which meets the following criteria before setting the without rowid flag: - - Primary key flag set - - Auto increment disabled - Por favor añada un campo que cumpla las siguientes condiciones antes de activar el flag 'sin rowid': - - Flag de clave primaria activado - - Flag de autoincremento desactivado + + Are you sure you want to clear all the conditional formats of this field? + ¿Está seguro de que quiere borrar todos los formatos condicionales de este campo? - ExportCsvDialog + DBBrowserDB - - Export data as CSV - Exportar datos como CSV + + Please specify the database name under which you want to access the attached database + Por favor, especifique el nombre con el que acceder a la base de datos anexada - - &Table(s) - &Tablas(s) + + Invalid file format + Formato de archivo inválido - - &Column names in first line - Nombres de las &columnas en la primera línea + + Do you want to save the changes made to the database file %1? + ¿Guardar los cambios hechos al archivo de base de datos «%1»? - - Field &separator - &Separador de campos + + Exporting database to SQL file... + Exportando base de datos a un archivo SQL... - - , - , + + + Cancel + Cancelar - - ; - ; + + Executing SQL... + Ejecutando SQL... - - - Tab - Tab + + Action cancelled. + Acción cancelada. - - | - | + + Do you really want to close this temporary database? All data will be lost. + ¿Está seguro de que quiere cerrar esta base de datos temporal? Todos los datos se perderán. - - - Other - Otro + + Database didn't close correctly, probably still busy + La base de datos no se ha cerrado correctamente, probablemente todavía está ocupada - - &Quote character - Entrecomillado + + Cannot open destination file: '%1' + No se puede abrir el archivo de destino: «%1» - - " - " + + + Cannot backup to file: '%1'. Message: %2 + No se puede guardar copia de seguridad en el archivo: «%1». Mensaje: %2 - - ' - ' + + The database is currently busy: + La base de datos está actualmente ocupada: - - Could not open output file: %1 - No se puede abrir el archivo de salida: %1 + + Do you want to abort that other operation? + ¿Desea abortar la otra operación? - - - Choose a filename to export data - Seleccione un nombre de archivo para exportar los datos + + + No database file opened + No hay una base de datos abierta - - - Text files(*.csv *.txt) - Archivos de texto(*.csv *.txt) + + + Error in statement #%1: %2. +Aborting execution%3. + Error en la sentencia #%1: %2. +Abortando ejecución%3. - - Please select at least 1 table. - Por favor, seleccione al menos 1 tabla. + + + and rolling back + y deshaciendo cambios - - Choose a directory - Seleccione una carpeta + + didn't receive any output from %1 + no se recibió ninguna salida de «%1» - - Export completed. - Exportación completada. + + could not execute command: %1 + no se pudo ejecutar el comando: «%1» - - - ExportSqlDialog - - Export SQL... - Exportar SQL... + + Cannot delete this object + No se puede borrar este objeto - - &Table(s) - &Tabla(s) + + Cannot set data on this object + No se pueden poner datos en este objeto - - &Options - &Opciones + + + A table with the name '%1' already exists in schema '%2'. + Una tabla con el nombre «%1» ya existe en el esquema «%2». - - Keep column names in INSERT INTO - Mantener el nombre de la columna en INSERT INTO + + No table with name '%1' exists in schema '%2'. + No existe una tabla con el nombre «%1» en el esquema «%2». - - New INSERT INTO syntax (multiple rows in VALUES) - Usa nueva sintáxis de INSERT INTO (múltiple 'rows' en VALUES) + + + Cannot find column %1. + No se puede encontrar la columna %1. - - Export schema only - Exportar sólo el esquema + + Creating savepoint failed. DB says: %1 + Creación del punto de guardado fallido. La base de datos dice: %1 - - Please select at least 1 table. - Por favor, seleccione al menos 1 tabla. + + Renaming the column failed. DB says: +%1 + Renombrado de la columna fallido. La base de datos dice: +%1 - - Choose a filename to export - Seleccione un nombre de archivo al que exportar + + + Releasing savepoint failed. DB says: %1 + Liberación del punto de guardado fallido. La base de datos dice: %1 - - Text files(*.sql *.txt) - Archivos de texto(*.sql *.txt) + + Creating new table failed. DB says: %1 + Creación de la nueva tabla fallida. La base de datos dice: %1 - - Export completed. - Exportación completada. + + Copying data to new table failed. DB says: +%1 + Copia de datos a la nueva tabla fallida. La base de datos dice: +%1 - - Export cancelled or failed. - Exportación cancelada o fallida. + + Deleting old table failed. DB says: %1 + Borrado de tabla fallido. La base de datos dice: %1 - - - FilterLineEdit - - Filter - Filtro + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + Error renombrando la tabla «%1» a «%2». +Mensaje de la base de datos: +%3 - - - ImportCsvDialog - - Import CSV file - Importar archivo CSV + + could not get list of db objects: %1 + No se pudo obtener la lista de objetos de la base de datos: %1 - - &Table name - Nombre de la &tabla + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + La restitución de algunos de los objetos asociados con esta tabla ha fallado. Lo más probable es que esto suceda porque los nombres de algunas columnas han cambiado. Esta es la sentencia SQL que puede que quiera corregir y ejecutar manualmente: + + - - &Column names in first line - Nombres de &columa en la primera línea + + could not get list of databases: %1 + no se pudo obtener lista de bases de datos: %1 - - Field &separator - &Separador de campos + + Error loading extension: %1 + Error cargando la extensión: %1 - - , - , + + Error loading built-in extension: %1 + Error cargando extensión incorporada: %1 - - ; - ; + + could not get column information + No se pudo obtener información de la columna - - - Tab - Tab + + Error setting pragma %1 to %2: %3 + Error definiendo pragma %1 como %2: %3 - - | - | + + File not found. + Archivo no encontrado. + + + DbStructureModel - - - - Other - Otro + + Name + Nombre - - &Quote character - &Entrecomillado + + Object + Objeto - - " - " + + Type + Tipo - - ' - ' + + Schema + Esquema - - &Encoding - &Codificado + + Database + Base de datos - - UTF-8 - UTF-8 + + Browsables + Navegables - - UTF-16 - UTF-16 + + All + Todos - - ISO-8859-1 - ISO-8859-1 + + Temporary + Temporal - - Trim fields? - ¿&Recortar campos? + + Tables (%1) + Tablas (%1) - - Inserting data... - Insertando datos... + + Indices (%1) + Ãndices (%1) - - Cancel - Cancelar + + Views (%1) + Vistas (%1) - - There is already a table of that name and an import into an existing table is only possible if the number of columns match. - Ya hay una tabla con ese nombre y la importación a una tabla existente sólo es posible si el número de columnas coincide. + + Triggers (%1) + Disparadores (%1) + + + EditDialog - - There is already a table of that name. Do you want to import the data into it? - Ya hay una tabla con ese nombre. ¿Quiere importar los datos en ella? + + Edit database cell + Editar celda de la base de datos - - Creating restore point failed: %1 - Creación del punto de restauración fallido: %1 + + Mode: + Modo: - - Creating the table failed: %1 - Creación de la tabla fallido: %1 + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + Esta es la lista de modos admitidos en el editor de celdas. Elija un modo para visualizar o editar los datos de la celda actual. - - Missing field for record %1 - Falta el campo para el registro %1 + + RTL Text + Texto RTL - - Inserting row failed: %1 - Inserción de línea fallido: %1 + + + Image + Imagen - - - MainWindow - - DB Browser for SQLite - DB Browser para SQLite + + JSON + JSON - - Database &Structure - E&structura de la Base de Datos + + XML + XML - - - toolBar1 - toolBar1 + + Evaluation + Evaluación - - &Browse Data - &Navegar Datos + + + Automatically adjust the editor mode to the loaded data type + Ajustar automáticamente el modo de edición al tipo de datos cargados - - Table: - Tabla: + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + Esta casilla activa o desactiva el cambio automático del modo de edición. Cuando se selecciona una nueva celda o se importan nuevos datos y la selección automática está activada, el modo de edición se ajusta al tipo de datos detectados. El modo de edición para la celda se puede cambiar manualmente. Si prefiere mantener el modo de edición seleccionado manualmente mientras se mueve por las celdas, desmarque la casilla. - - Select a table to browse data - Seleccione una tabla para navegar + + Auto-switch + Auto-selección - - Use this list to select a table to be displayed in the database view - Use esta lista para seleccionar la tabla a mostrar en la vista de la base de datos + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + Este editor Qt se usa para scripts de derecha-a-izquierda, que no están soportados por el editor de Texto por defecto. Al detectar la presencia de caracteres de derecha-a-izquierda este modo de edición se activa automáticamente. - - Refresh the data in the selected table. - Refresca los datos de la tabla seleccionada. + + Identification of the cell currently in the editor + Identificación de la celda actualmente en el editor - - This button refreshes the data in the currently selected table. - Este botón refresca los datos de la tabla actualmente seleccionada. + + Type and size of data currently in table + Tipo y tamaño de la celda actualmente en la tabla - - - F5 - F5 + + Open preview dialog for printing the data currently stored in the cell + Abrir diálogo de previsualización para imprimir los datos actualmente almacenados en la celda - - Clear all filters - Borrar todos los filtros + + Auto-format: pretty print on loading, compact on saving. + Auto-formato: dar formato al cargar, compactar al guardar. - - Insert a new record in the current table - Insertar un nuevo registro en la tabla actual + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + Si se habilita, la opción de auto-formato da formato a los datos al cargarlos, rompiendo y sangrando las líneas de texto para una legibilidad máxima. Al guardar los datos, esta opción los compacta, eliminando fines de línea y espacio en blanco innecesario. - - This button creates a new, empty record in the database - Este botón crea un nuevo registro vacío en la base de datos + + Word Wrap + Ajuste del Texto - - New Record - Nuevo registro + + Wrap lines on word boundaries + Ajustar las líneas en palabras completas - - Delete the current record - Borra el registro actual + + + Open in default application or browser + Abrir en la aplicacion por defecto o navegador - - This button deletes the record currently selected in the database - Este botón borra el registro actualmente seleccionado en la base de datos + + Open in application + Abrir en una aplicacion - - Delete Record - Borrar registro + + The value is interpreted as a file or URL and opened in the default application or web browser. + El valor es interpretado como un nombre de archivo o URL y abierto en la aplicación por defecto del sistema o el navegador de internet. - - This is the database view. You can double-click any record to edit its contents in the cell editor window. - Esta es la vista de la base de datos. Puede hacer doble-click sobre cualquier registro para editar su contenido en la ventana del editor de celdas. + + Save file reference... + Guardar referencia de archivo... - - <html><head/><body><p>Scroll to the beginning</p></body></html> - <html><head/><body><p>Desplazarse hasta el principio</p></body></html> + + Save reference to file + Guardar referencia a archivo - - <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> - <html><head/><body><p>Pulsando este botón se mueve hasta el principio en la vista de tabla de arriba.</p></body></html> + + + Open in external application + Abrir en una aplicación externa - - |< - |< + + Autoformat + Auto-formato - - Scroll 100 records upwards - Desplazarse 100 registros hacia arriba + + &Export... + &Exportar... - - <html><head/><body><p>Clicking this button navigates 100 records upwards in the table view above.</p></body></html> - <html><head/><body><p>Pulsando este botón se desplaza 100 registros hacia arriba en la vista de tabla de arriba.</p></body></html> + + + &Import... + &Importar... - - < - < + + + Import from file + Importar desde archivo - - 0 - 0 of 0 - 0 - 0 de 0 + + + Opens a file dialog used to import any kind of data to this database cell. + Abre un diálogo para elegir el archivo para importar cualquier tipo de datos a esta celda. - - <html><head/><body><p>Scroll 100 records downwards</p></body></html> - <html><head/><body><p>Desplazarse 100 registros hacia abajo</p></body></html> + + Export to file + Exportar a archivo - - <html><head/><body><p>Clicking this button navigates 100 records downwards in the table view above.</p></body></html> - <html><head/><body><p>Pulsando este botón se desplaza 100 registros hacia abajo en la vista de tabla de arriba.</p></body></html> + + Opens a file dialog used to export the contents of this database cell to a file. + Abre un diálogo para elegir el archivo al que exportar el contenido de esta celda de la base de datos. - - > - > + + Print... + Imprimir... - - Scroll to the end - Desplazarse hasta el final + + Ctrl+P + - - <html><head/><body><p>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Clicking this button navigates up to the end in the table view above.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html> - <html><head/><body><p>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Pulsando este botón se mueve hasta el final en la vista de tabla de arriba.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html> + + Open preview dialog for printing displayed text + Abre un diálogo de previsualización para imprimir el texto mostrado - - >| - >| + + Copy Hex and ASCII + Copiar hex. y ASCII - - <html><head/><body><p>Click here to jump to the specified record</p></body></html> - Pulse aquí para saltar al registro especificado + + Copy selected hexadecimal and ASCII columns to the clipboard + Copia las columnas seleccionadas en hexadecimal y ASCII al portapapeles - - <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> - <html><head/><body><p>Este botón se usa para moverse al número de registro especificado en la casilla Ir a.</p></body></html> + + Ctrl+Shift+C + - - Go to: - Ir a: + + Set as &NULL + Borrar a &NULL - - Enter record number to browse - Introduzca el número de registro para navegar + + Apply data to cell + Aplicar los datos a la celda - - Type a record number in this area and click the Go to: button to display the record in the database view - Escriba un número de registro en esta casilla y haga click en el botón Ir a: para mostrar el registro en la vista de la base de datos + + This button saves the changes performed in the cell editor to the database cell. + Este botón guarda los cambios realizados en el editor a la celda de la base de datos. - - 1 - 1 + + Apply + Aplicar - - Edit &Pragmas - Editar &Pragmas + + Text + Texto - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> - + + Binary + Binario - - - - None - Ninguno + + Erases the contents of the cell + Borra el contenido de la celda - - - Full - Completo + + This area displays information about the data present in this database cell + Esta zona muestra información acerca de los datos presentes en esta celda de la base de datos - - Incremental - Incremental + + Choose a filename to export data + Seleccione un nombre de archivo para exportar los datos - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Indexado Automático</span></a></p></body></html> + + + Image data can't be viewed in this mode. + Datos de imagen no se pueden visualizar en este modo. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> - + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + Los modos de edición de texto permiten editar texto plano, y también JSON o XML con resaltado de sintaxis, formato automático y validación previa a guardar. + +Los errores se indican con un subrayado ondulado en rojo. + +En el modo de Evaluación, las expresiones de SQLite se evalúan y el resultado se aplica a la celda. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></a></p></body></html> - + + Unsaved data in the cell editor + Datos sin guardar en el editor de celdas - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> - + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + El editor de celdas contiene datos aún no aplicados a la base de datos. +¿Desea aplicar los datos editados a la fila=%1, columna=%2? - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignorar Check Constraints</span></a></p></body></html> + + Editing row=%1, column=%2 + Editando fila=%1, columna=%2 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Modo Journal</span></a></p></body></html> + + No cell active. + No hay celda activa. - - Delete - Borrar + + + Try switching to Image or Binary mode. + Intente cambiando al modo «Imagen» o «Binario». - - Truncate - Truncar + + + Binary data can't be viewed in this mode. + Datos binarios no se pueden visualizar en este modo. - - Persist - Persistente + + + Try switching to Binary mode. + Intente cambiando al modo «Binario». - - - Memory - Memoria + + + Image files (%1) + Archivos de imagen (%1) - - WAL - WAL + + Binary files (*.bin) + Archivos binarios (*.bin) - - - Off - Apagado + + + Type: NULL; Size: 0 bytes + Tipo: NULL; Tamaño: 0 bytes - - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Límite de tamaño del Journal</span></a></p></body></html> + + + + Type: Text / Numeric; Size: %n character(s) + + Tipo: Texto / Numérico; Tamaño: %n carácter + Tipo: Texto / Numérico; Tamaño: %n caracteres + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Modo de Bloqueo</span></a></p></body></html> + + Type: %1 Image; Size: %2x%3 pixel(s) + Tipo: Imagen %1; Tamaño: %2×%3 píxeles - - - - Normal - Normal + + + Type: Valid JSON; Size: %n character(s) + + Tipo: JSON válido; Tamaño: %n carácter + Tipo: JSON válido; Tamaño: %n caracteres + + + + + Type: Binary; Size: %n byte(s) + + Tipo: Binario; Tamaño: %n byte + Tipo: Binario; Tamaño: %n bytes + - - Exclusive - Exclusivo + + Choose a file to import + Seleccione el archivo a importar - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">Máximo número de Páginas</span></a></p></body></html> + + %1 Image + Imagen %1 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Tamaño de Página</span></a></p></body></html> + + Invalid data for this mode + Datos inválidos para este modo - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Disparadores Recursivos</span></a></p></body></html> + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + La celda contiene datos de tipo %1 inválidos. Razón: «%2». ¿Realmente desea aplicarlos a la celda? - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Borrado Seguro</span></a></p></body></html> + + Couldn't save file: %1. + No se pudo guardar el archivo: «%1». - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Síncrono</span></a></p></body></html> + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + Los datos se han guardado en un archivo temporal y se han abierto con la aplicación predeterminada. Ahora puede editar el archivo y, cuando haya terminado, podrá aplicar los nuevos datos a la celda o cancelar los cambios. + + + EditIndexDialog - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Almacenamiento Temporal</span></a></p></body></html> + + &Name + &Nombre - - Default - + + Order + Orden - - File - Archivo + + &Table + &Tabla - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">Versión de Usuario</span></a></p></body></html> + + Edit Index Schema + Editar índice del esquema - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> - + + &Unique + Ú&nico - - E&xecute SQL - E&jecutar SQL + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + Para restringir el índice exclusivamente a una parte de la tabla hay que especificar aquí una cláusula WHERE que seleccione la parte de la tabla que será indexada - - &File - &Archivo + + Partial inde&x clause + Cláusula para inde&xado parcial - - &Import - &Importar + + Colu&mns + Colu&mnas - - &Export - E&xportar + + Table column + Columna de la tabla - - &Edit - &Editar + + Type + Tipo - - &View - &Ver + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + Añade una nueva columna computada al índice. Las columnas computadas contienen una expresión SQL en lugar de nombres de columna. - - &Help - Ay&uda + + Index column + Columna de índice - - DB Toolbar - DB Toolbar + + Deleting the old index failed: +%1 + Borrado del índice previo fallido: +%1 - - SQL Log - SQL Log + + Creating the index failed: +%1 + Creación de índice fallida: +%1 + + + EditTableDialog - - &Show SQL submitted by - &Mostrar SQL enviado por + + Edit table definition + Editar la definición de la tabla - - User - Usuario + + Table + Tabla - - Application - Aplicación + + Advanced + Avanzado - - &Clear - &Limpiar + + Without Rowid + Sin Rowid - - Plot - Dibujo + + Fields + Campos - - Columns - Columnas + + Database sche&ma + Esque&ma de la base de datos - - X - X + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + Establecer la propiedad «WITHOUT ROWID» a la tabla. Establecer esta opción requiere especificar una clave primaria (que puede ser de cualquier tipo y puede ser compuesta), y prohibe el uso de la propiedad AUTOINCREMENT. - - Y - Y + + On Conflict + En caso de conflicto - - _ - _ + + Strict + Opción STRICT - - Line type: - Tipo de línea: + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + Cuando la opción «STRICT» está habilitada, SQLite hace cumplir los tipos de datos de cada columna cuando se actualizan o insertan datos. - - Line - Línea + + + + Add + Añadir - - StepLeft - + + + + Remove + Eliminar - - StepRight - + + Move to top + Mover al principio - - StepCenter - + + Move up + Mover hacia arriba - - Impulse - Impulso + + Move down + Mover hacia abajo - - Point shape: - Forma del punto: + + Move to bottom + Mover al final - - Cross - Cruz + + + + + Name + Nombre - - Plus - Más + + + Type + Tipo - - Circle - Circunferencia + + NN + NN - - Disc - Disco + + Not null + No nulo - - Square - Cuadrado + + PK + PK - - Diamond - Diamante + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> Clave primaria</p></body></html> - - Star - Estrella + + AI + AI - - Triangle - Triángulo + + Autoincrement + Autoincremento - - TriangleInverted - TriánguloInvertido + + U + U - - CrossSquare - CruzCuadrado + + + + Unique + Único - - PlusSquare - MasCuadrado + + Default + Por defecto - - CrossCircle - CruzCircunferencia + + Default value + Valor por defecto - - PlusCircle - MásCircunferencia + + + Check + Check - - Peace - Paz + + Check constraint + Restricción de «check» - - <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> - <html><head/><body><p>Guradar dibujo actual...</p><p>El formato del archivo es elegido por la extensión (png, jpg, pdf, bmp)</p></body></html> + + Collation + Comparación - - Save current plot... - Guardar el dibujo actual... + + Foreign Key + Clave foránea - - DB Schema - Esquema de la base de datos + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> Clave foránea</p></body></html> - - &New Database... - &Nueva base de datos + + Index Constraints + Restricciones de índice - - - Create a new database file - Crea un nuevo archivo de base de datos + + Add constraint + Añadir restricción - - This option is used to create a new database file. - Esta opción se usa para crear un nuevo archivo de base de datos + + Remove constraint + Eliminar restricción - - Ctrl+N - Ctrl+N + + + Columns + Columnas - - &Open Database... - &Abrir base de datos + + + + SQL + SQL - - - Open an existing database file - Abrir un archivo de base de datos + + Foreign Keys + Claves foráneas - - This option is used to open an existing database file. - Esta opción se usa para abrir un archivo de base de datos. + + References + Referencias - - Ctrl+O - Ctrl+O + + Check Constraints + Restricciones «CHECK» - - &Close Database - &Cierra base de datos + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Aviso: </span>algo ocurre con la definición de esta tabla que nuestro intérprete no entiende completamente. Modificar y guardar esta tabla podría traer problemas.</p></body></html> - - Ctrl+W - Ctrl+W + + + Primary Key + Clave Primaria - - Revert Changes - Deshacer cambios + + Add a primary key constraint + Añadir una restricción de clave primaria - - Revert database to last saved state - Deshacer cambios al último estado guardado + + Add a unique constraint + Añadir una restricción de único" - - This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. - Esta opción se usa para deshacer los cambios en la base de datos actual al último estado guardado. Todos los cambios hechos desde la última vez que se guardó se perderán. + + Error creating table. Message from database engine: +%1 + Error creando la tabla. Mensaje de la base de datos: +%1 - - Write Changes - Escribir cambios + + There already is a field with that name. Please rename it first or choose a different name for this field. + Ya hay un campo con este nombre. Por favor, renómbrelo antes o elija un nombre diferente para este campo. - - Write changes to the database file - Escribir cambios al archivo de la base de datos + + + There can only be one primary key for each table. Please modify the existing primary key instead. + Sólo puede existir una clave primaria en cada tabla. Por favor, modifique la clave primaria existente. - - This option is used to save changes to the database file. - Esta opción se usa para guardar los cambios en el archivo de la base de datos. + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + Esta columna está referenciada en una clave foránea en la tabla %1 y por tanto no se le puede cambiar el nombre. - - Ctrl+S - Ctrl+S + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + Hay al menos una línea con este campo NULO. Esto hace imposible activar este flag. Por favor, modifique antes los datos de la tabla. - - Compact Database - Compactar base de datos + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + Hay al menos una línea con un valor no entero en este campo. Esto hace imposible activar el flag AI. Por favor, modifique antes los datos de la tabla. - - Compact the database file, removing space wasted by deleted records - Compacta el archivo de la base de datos eliminando el espacio malgastado por los registros borrados + + Column '%1' has duplicate data. + + La columna «%1» tiene datos duplicados. + - - - Compact the database file, removing space wasted by deleted records. - Compacta el archivo de la base de datos eliminando el espacio malgastado por los registros borrados + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + Como en otros textos, pasamos los términos estándar de SQL a mayúsculas para evitar traducirlos, lo que podría ser más confuso para el usuario experto y no tener beneficio para el inexperto. + Esto imposibilita la habilitación de la restricción UNIQUE. Por favor, elimine primero los datos duplicados, lo cual permitirá habilitar la restricción UNIQUE. - - E&xit - &Salir + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + ¿Está seguro de que quiere borrar este campo «%1»? +Todos los datos actualmente almacenados en este campo se perderán. - - Ctrl+Q - Ctrl+Q + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + Por favor añada un campo que cumpla las siguientes condiciones antes de activar el indicador «sin rowid»: + - Indicador de clave primaria activado + - Indicador de autoincremento desactivado - - Database from SQL file... - Base de datos en un archivo SQL... + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + Por favor añada un campo que cumpla las siguientes condiciones antes de activar la acción «ON CONFLICT»: + - Indicador de clave primaria activado + + + ExportDataDialog - - Import data from an .sql dump text file into a new or existing database. - Importa datos de un archivo de texto con un volcado .sql en una base de datos nueva o existente. + + Export data as CSV + Exportar datos como CSV - - This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. - Esta opción se usa para importar datos de un archivo de texto con un volcado .sql en una base de datos nueva o existente. Los archivos de volcado SQL se pueden crear en la mayoría de los motores de base de datos, incluyendo MySQL y PostgreSQL. + + Tab&le(s) + Tab&la(s) - - Table from CSV file... - Tabla de un archivo CSV... + + Colu&mn names in first line + Nombres de las &columnas en la primera línea - - Open a wizard that lets you import data from a comma separated text file into a database table. - Abre un asistente que le permite importar datos desde un archivo de texto con valores separado por comas a una tabla de una base de datos. + + Fie&ld separator + &Separador de campos - - Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. - Abre un asistente que le permite importar datos desde un archivo de texto con valores separado por comas a una tabla de una base de datos. Los archivos CSV se pueden crear en la mayoría de las aplicaciones de bases de datos y hojas de cálculo. + + , + , - - Database to SQL file... - Base de datos a archivo SQL... + + ; + ; - - Export a database to a .sql dump text file. - Exporta la base de datos como un volcado .sql a un archivo de texto. + + Tab + Tab - - This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. - Esta opción le permite exportar la base de datos como un volcado .sql a un archivo de texto. Los archivos de volcado SQL contienen todos los datos necesarios para recrear la base de datos en la mayoría de los motores de base de datos, incluyendo MySQL y PostgreSQL. + + | + | - - Table(s) as CSV file... - Tabla(s) como un archivo CSV... + + + + Other + Otro - - Export a database table as a comma separated text file. - Exporta la base de datos como un archivo de texto con valores separados por comas. + + &Quote character + &Entrecomillado - - Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. - Exporta la base de datos como un archivo de texto con valores separados por comas, listo para ser importado en otra base de datos o aplicaciones de hoja de cálculo. + + " + " - - Create Table... - Crea Tabla... + + ' + ' - - Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database - Abre el asistente para Crear una Tabla, donde se puede definir el nombre y los campos de una nueva tabla en la base de datos + + New line characters + Caracteres de nueva línea - - Delete Table... - Borra Tabla... + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) - - - Delete Table - Borra Tabla + + Unix: LF (\n) + Unix: LF (\n) - - Open the Delete Table wizard, where you can select a database table to be dropped. - Abre el asistente para Borrar una Tabla, donde se puede seleccionar una tabla de la base de datos para borrar. + + Pretty print + Impresión formateada - - Modify Table... - Modifica Tabla... + + + Could not open output file: %1 + No se puede abrir el archivo de salida: %1 - - Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields form a table, as well as modify field names and types. - Abre el asistente para Modificar una Tabla, donde se puede renombrar una tabla existente de la base de datos. También se pueden añadir o borrar campos de la tabla, así como modificar los nombres de los campos y sus tipos. + + + Choose a filename to export data + Seleccione un nombre de archivo para exportar los datos - - Create Index... - Crea Ãndice... + + Export data as JSON + Exportar datos como JSON - - Open the Create Index wizard, where it is possible to define a new index on an existing database table. - Abre el asistente para Crear un Ãndice, donde se puede definir un nuevo índice de una tabla existente de la base de datos. + + exporting CSV + exportando CSV - - &Preferences... - &Preferencias... + + + Error while writing the file '%1': %2 + Error al guardar el archivo «%1»: %2 - - - Open the preferences window. - Abrir la ventana de preferencias. + + exporting JSON + exportando JSON - - &DB Toolbar - Barra de herramientas de la base de datos + + Please select at least 1 table. + Por favor, seleccione al menos 1 tabla. - - Shows or hides the Database toolbar. - Muestra u oculta la barra de herramientas de la base de datos + + Choose a directory + Seleccione una carpeta - - What's This? - ¿Qué es esto? + + Export completed. + Exportación completada. - - Shift+F1 - Shift+F1 + + Export finished with errors. + Exportación terminada con errores. + + + ExportSqlDialog - - &About... - &Acerca de... + + Export SQL... + Exportar SQL... - - &Recently opened - Archivos &recientes + + Tab&le(s) + Tab&la(s) - - Open &tab - Abrir &pestaña + + Select All + Seleccionar Todo - - Ctrl+T - Ctrl+T + + Deselect All + Deseleccionar Todo - - &Execute SQL - &Ejecutar SQL + + &Options + &Opciones - - Execute SQL [F5, Ctrl+Return] - Ejecutar SQL [F5, Ctrl+Return] + + Keep column names in INSERT INTO + Mantener el nombre de la columna en INSERT INTO - - Open SQL file - Abrir archivo SQL + + Multiple rows (VALUES) per INSERT statement + Múltiples líneas (VALUES) en cada sentencia INSERT - - - - Save SQL file - Guardar archivo SQL + + Export everything + Exportar todo - - Load extension - Cargar extensión + + Export data only + Exportar solo los datos - - Execute current line - Ejecutar la línea actual + + Keep original CREATE statements + Mantener las sentencias «CREATE» originales - - Execute current line [Ctrl+E] - Ejecutar la línea actual [Ctrl+E] + + Keep old schema (CREATE TABLE IF NOT EXISTS) + Mantener esquema previo (CREATE TABLE IF NOT EXISTS) - - Ctrl+E - Ctrl+E + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + Sobrescribir esquema previo (DROP TABLE, después CREATE TABLE) - - Export as CSV file - Exportar como archivo CSV - - - - Export table as comma separated values file - Exportar tabla como archivo de valores separados por comas + + Export schema only + Exportar solo el esquema - - &Wiki... - &Wiki... + + Please select at least one table. + Por favor, seleccione al menos una tabla. - - Bug &report... - Informe de &fallos + + Choose a filename to export + Seleccione un nombre de archivo al que exportar - - Web&site... - Sitio &Web + + Export completed. + Exportación completada. - - Save Project - Guardar Proyecto + + Export cancelled or failed. + Exportación cancelada o fallida. + + + ExtendedScintilla - - - Save the current session to a file - Guardar la sesion actual en un archivo + + + Ctrl+H + - - Open Project - Abrir Proyecto + + Ctrl+F + - - - Load a working session from a file - Carga una sesion de trabajo de un archivo + + + Ctrl+P + - - &Attach Database - &Anexar la base de datos + + Find... + Buscar... - - Set Encryption - Definir Cifrado + + Find and Replace... + Buscar y reemplazar... - - - Save SQL file as - Guardar fichero SQL como + + Print... + Imprimir... + + + ExtendedTableWidget - - &Browse Table - &Navegar por la Tabla + + Use as Exact Filter + Usar como filtro exacto - - Copy Create statement - Copiar comando Create + + Containing + Conteniendo - - Copy the CREATE statement of the item to the clipboard - Copia el comando CREATE del item al portapapeles + + Not containing + Que no contenga - - Ctrl+Return - Ctrl+Return + + Not equal to + No igual a - - Ctrl+L - Ctrl+L + + Greater than + Mayor que - - Ctrl+P - Ctrl+P + + Less than + Menor que - - Ctrl+D - Ctrl+D + + Greater or equal + Mayor o igual - - Ctrl+I - Ctrl+I + + Less or equal + Menor o igual - - Database encoding - Codificación de la base de datos + + Between this and... + Entre esto y... - - Database is encrypted using SQLCipher - La base de datos está cifrada usando SQLCipher + + Regular expression + Expresión regular - - - Choose a database file - Seleccione un archivo de base de datos + + Edit Conditional Formats... + Editar formatos condicionales... - - SQLite database files (*.db *.sqlite *.sqlite3 *.db3);;All files (*) - Archivos de base de datos de SQLite (*.db *.sqlite *.sqlite3 *.db3);;Todos los archivos (*) + + Set to NULL + Poner a NULL - - Invalid file format. - Formato de archivo inválido. + + Cut + Cortar - - - - - Choose a filename to save under - Seleccione un nombre de archivo en el que guardar + + Copy + Copiar - - Error adding record: - - Error añadiendo registro: - + + Copy with Headers + Copiar con cabeceras - - Error deleting record: -%1 - Error borrando registro: -%1 + + Copy as SQL + Copiar como SQL - - Please select a record first - Por favor, antes seleccione un registro + + Paste + Pegar - - %1 - %2 of %3 - %1 - %2 de %3 + + Print... + Imprimir... - - - There is no database opened. Please open or create a new database file. - No hay una base de datos abierta. Por favor, abra o cree un nuevo archivo de base de datos. + + Use in Filter Expression + Usar en expresión de filtro - - Are you sure you want to delete the %1 '%2'? -All data associated with the %1 will be lost. - ¿Está seguro de que quiere borrar %1 '%2'? -Se perderán todos los datos asociados con %1. + + Alt+Del + - - Error: could not delete the %1. Message from database engine: -%2 - Error: no se pudo borrar el %1. Mensaje de la base de datos: -%2 + + Ctrl+Shift+C + - - There is no database opened. - No hay una base de datos abierta. + + Ctrl+Alt+C + - - %1 Rows returned from: %3 (took %2ms) - %1 líneas devueltas de: %3 (tardó %2ms) + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>No se han cargado todos los datos. <b>¿Quiere cargar todos los datos antes de seleccionar todas las filas?</b><p><p>Responder <b>No</b> significa que no se cargarán mas datos y la selección no se se realizará.<br/>Responder <b>Sí</b> puede tardar un tiempo mientras los datos se cargan pero la selección se realizará en su totalidad.</p>Precaución: Cargar todos los datos puede necesitar una gran cantidad de memoria para tablas grandes. - - Error executing query: %1 - Error ejecutando la consulta: %1 + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + No se puede ajustar la selección a NULL. La columna %1 tiene una restricción NOT NULL. - - Query executed successfully: %1 (took %2ms) - Consulta ejecutada con éxito: %1 (tardó %2ms) + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + El contenido del portapapeles es mayor que el rango seleccionado. +¿Quiere insertarlo de todos modos? + + + FileExtensionManager - - Choose a text file - Seleccione un archivo de texto + + File Extension Manager + Gestor de extensiones de archivos - - Text files(*.csv *.txt);;All files(*) - Archivos de texto(*.csv *.txt);;Todos los archivos(*) + + &Up + &Subir - - Import completed - Importación completada + + &Down + &Bajar - - Are you sure you want to undo all changes made to the database file '%1' since the last save? - ¿Está seguro de que quiere deshacer todos los cambios hechos al archivo de la base de datos '%1' desde la última vez que se guardó? + + &Add + &Añadir - - Choose a file to import - Seleccione el archivo a importar + + &Remove + &Eliminar - - - - Text files(*.sql *.txt);;All files(*) - Archivos de texto(*.sql *.txt);;Todos los archivos(*) + + + Description + Descripción - - Do you want to create a new database file to hold the imported data? -If you answer no we will attempt to import the data in the SQL file to the current database. - ¿Quiere crear un nuevo archivo de base de datos donde poner los datos importados? -Si responde no se intentarán importar los datos del archivo SQL en la base de datos actual. + + Extensions + Extensiones - - File %1 already exists. Please choose a different name. - El archivo %1 ya existe. Por favor elija un nombre diferente. + + *.extension + *.extensión + + + FilterLineEdit - - Error importing data: %1 - Error importando datos: %1 + + Filter + Filtro - - Import completed. - Importación completada. + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + Estos campos de texto permiten realizar filtros rápidos sobre la tabla actualmente seleccionada. +Por defecto, las filas que contengan el texto introducido se muestran. +Los siguientes operadores también se admiten: +% Comodín +> Mayor que +< Menor que +>= Igual o mayor que +<= Igual o menor que += Igual a: correspondencia exacta +<> Distinto: correspondencia inversa exacta +x~y Rango: valores entre x e y - - Delete View - Borrar vista + + Clear All Conditional Formats + Eliminar todos los formatos condicionales - - Delete Trigger - Borrar Disparador + + Use for Conditional Format + Usar para formato condicional - - Delete Index - Borrar Ãndice + + Edit Conditional Formats... + Editar formatos condicionales... - - &%1 %2 - &%1 %2 + + Set Filter Expression + Establecer expresión de filtro - - Setting PRAGMA values will commit your current transaction. -Are you sure? - Al definir los valores de PRAGMA se confirmará la transacción actual. -¿Está seguro? + + What's This? + ¿Qué es esto? - - Select SQL file to open - Seleccione el archivo SQL a abrir + + Is NULL + Es nulo - - Select file name - Seleccione el nombre del archivo + + Is not NULL + No es nulo - - Select extension file - Selecione el archivo de extensión + + Is empty + Es vacío - - Extensions(*.so *.dll);;All files(*) - Extensiones(*.so *.dll);;Todos los archivos(*) + + Is not empty + No es vacío - - Extension successfully loaded. - Extensiones cargadas con éxito. + + Not containing... + No contiene... - - - Error loading extension: %1 - Error cargando la extensión: %1 + + Equal to... + Igual a... - - Don't show again - No volver a mostrar + + Not equal to... + No igual a... - - New version available. - Hay una nueva versión disponible. + + Greater than... + Mayor que... - - A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. - Hay diponible una nueva version de DB Browser para SQLite (%1.%2.%3).<br/><br/>Por favor, descárguela de <a href='%4'>%4</a>. + + Less than... + Menor que... - - Choose a axis color - Seleccione un eje de color + + Greater or equal... + Mayor o igual... - - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Todos los Archivos(*) + + Less or equal... + Menor o igual... - - Choose a file to open - Seleccione un archivo para abrir + + In range... + En el rango... - - - DB Browser for SQLite project file (*.sqbpro) - Archivo de proyecto de DB Browser para SQLite (*.sqbpro) + + Regular expression... + Expresión regular... - PreferencesDialog + FindReplaceDialog - - Preferences - Preferencias + + Find and Replace + Buscar y reemplazar - - &General - &General + + Fi&nd text: + &Buscar texto: - - Remember last location - Recordar la última posición + + Re&place with: + &Reemplazar con: - - Always use this location - Usar siempre esta posición + + Match &exact case + Distinguir &mayús. y minús. - - Remember last location for session only - Recordar la última posición sólo para esta sesión + + Match &only whole words + &Solo palabras completas - - ... - ... + + When enabled, the search continues from the other end when it reaches one end of the page + Si se habilita, la búsqueda continua desde el otro extremo cuando llega a un extremo de la página - - Default &location - &Posición por defecto + + &Wrap around + &Dar la vuelta - - Lan&guage - &Idioma + + When set, the search goes backwards from cursor position, otherwise it goes forward + Si se marca, la búsqueda va hacia atrás desde la posición del cursor. De lo contrario va hacia adelante - - Automatic &updates - &Actualizaciones automáticas + + Search &backwards + Buscar hacia &atrás - - - enabled - activado + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>Si se marca, el patrón de búsqueda se limita a buscar sólo en la selección.</p></body></html> - - &Database - &Base de datos + + &Selection only + En la &selección - - Database &encoding - Co&dificación de la base de datos + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Si se marca, el patrón de búsqueda se interpreta como una expresión regular UNIX. Véase <a href="https://es.wikipedia.org/wiki/Expresi%C3%B3n_regular">«Expresión regular» en Wikipedia</a>.</p></body></html> - - Open databases with foreign keys enabled. - Abrir base de datos con 'claves foreign' activadas + + Use regular e&xpressions + Usar e&xpresiones regulares - - &Foreign keys - Foreign &keys + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + Encontrar la siguiente ocurrencia desde la posición del cursor y en la dirección definida por «Buscar hacia atrás» - - Remove line breaks in schema view - Eliminar los salos de línea en la vista del esquema + + &Find Next + Buscar &siguiente - - &Prefetch block size - Tamaño del bloque de &precarga + + F3 + - - Data &Browser - &Navegador de datos + + &Replace + R&eemplazar - - NULL fields - Campos NULOS + + Highlight all the occurrences of the text in the page + Resaltar todas las ocurrencias del texto en la página - - Text &colour - &Color del texto + + F&ind All + Encontrar &todo - - &Text - &Texto + + Replace all the occurrences of the text in the page + Reemplazar todas las ocurrencias del texto en la página - - Bac&kground colour - Color de &fondo + + Replace &All + Reem&plazar todo - - &SQL - &SQL + + The searched text was not found + El texto buscado no fue encontrado - - Settings name - Nombre de los ajustes + + The searched text was not found. + El texto buscado no fue encontrado. - - Context - Contexto + + The searched text was found one time. + El texto buscado fue encontrado una vez. - - Colour - Color + + The searched text was found %1 times. + El texto buscado fue encontrado %1 veces. - - Bold - Negrita + + The searched text was replaced one time. + El texto buscado fue reemplazado una vez. - - Italic - Cursiva + + The searched text was replaced %1 times. + El texto buscado fue reemplazado %1 veces. + + + ForeignKeyEditor - - Underline - Subrayado + + &Reset + &Reiniciar - - Keyword - palabra clave + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + Cláusulas de clave foránea (ON UPDATE, ON DELETE etc.) + + + ImageViewer - - function - función + + Image Viewer + Visor de imágenes - - Function - Función + + Reset the scaling to match the original size of the image. + Restablecer el escalado según el tamaño original de la imagen. - - Table - Tabla + + Set the scaling to match the size of the viewport. + Establecer el escalado según el tamaño del área de visualización. - - Comment - Comentario + + Print... + Imprimir... - - Identifier - Identificador + + Open preview dialog for printing displayed image + Abre un diálogo de previsualización para imprimir la imagen mostrada - - String - Cadena + + Ctrl+P + + + + ImportCsvDialog - - currentline - currentline + + Import CSV file + Importar archivo CSV - - Current line - Línea actual + + Table na&me + &Nombre de la tabla - - SQL &editor font size - Tamaño de fuentes del &editor SQL + + &Column names in first line + Nombres de &columna en la primera línea - - SQL &log font size - Tamaño de fuentes del &log de SQL + + Field &separator + &Separador de campos - - Tab size: - Tamaño del tabulador: + + , + , - - SQL editor &font - &Tipo de fuente del editor SQL + + ; + ; - - &Extensions - E&xtensiones + + + Tab + Tab - - Select extensions to load for every database: - Seleccione extensiones a cargar para cada base de datos: + + | + | - - Add extension - Añadir extensión + + Other + Otro - - Remove extension - Eliminar extensión + + &Quote character + &Entrecomillado - - <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> - -<html><head/><body><p> -Aunque SQLite admite el operador REGEXP, no implementa en sí ningún algoritmo de expresiones<br/> -regulares sino que llama a los de la aplicación en ejecución. DB Browser para SQLite implementa este<br/> -método para permitirle usar REGEXP de fábrica. Sin embargo, como hay múltiples posibles<br/> -implementaciones y puede querer usar otro, puede desactivar este método y cargar el suyo propio<br/> -usando una extensión. Necesitará reiniciar la aplicación.</p> -</body></html> + + + Other (printable) + Otro (imprimible) - - Disable Regular Expression extension - Desactivar extensión de Expresiones Regulares + + + Other (code) + Otro (código) - - Choose a directory - Seleccione una carpeta + + " + " - - The language will change after you restart the application. - El idioma cambiará al reiniciar la aplicación + + ' + ' - - Select extension file - Seleccione archivo de extensión + + &Encoding + &Codificación - - Extensions(*.so *.dll);;All files(*) - Extensiones(*.so *.dll);;Todos los archivos + + UTF-8 + UTF-8 - - - QObject - - Error importing data - Error importando datos + + UTF-16 + UTF-16 - - from record number %1 - del registro número %1 + + ISO-8859-1 + ISO-8859-1 - - . -%1 - . -%1 + + Trim fields? + ¿Recortar campos? - - Decoding CSV file... - Descodificando archivo CSV... + + Separate tables + Tablas separadas - - Cancel - Cancelar + + Advanced + Avanzado - - Collation needed! Proceed? - ¡Es necesaria una función de comparación! ¿Proceder? + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + Cuando se importe un valor vacío desde el archivo CSV a una tabla existente con un valor por defecto para la columna, ese valor por defecto es insertado. Active esta opción si, por el contrario, desea insertar un valor vacío para esta columna. - - A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. -If you choose to proceed, be aware bad things can happen to your database. + + Ignore default &values + Ignorar &valores por defecto + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + Active esta opción para para la importación cuando se intente importar un valor vacío a una columna NOT NULL sin un valor por defecto. + + + + Fail on missing values + Fallar cuando falten valores + + + + Disable data type detection + Deshabilitar detección de tipo + + + + Disable the automatic data type detection when creating a new table. + Deshabilitar la detección automática de tipo cuando se esté creando una nueva tabla. + + + + Use local number conventions + Usar convenios numéricos locales + + + + Use decimal and thousands separators according to the system locale. + Usar separadores de decimales y de miles según la configuración regional. + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + Cuando se importa a una tabla existente con una clave primaria, restricciones de único o un índice de único, existe la posibilidad de que se genere un conflicto. Esta opción le permite elegir la estrategia en esos casos: Por defecto la importación se aborta y se deshacen los cambios pero también puede elegir ignorar y no importar las filas conflictivas o reemplazar las filas existentes en la tabla. + + + + Abort import + Abortar importación + + + + Ignore row + Ignorar fila + + + + Replace existing row + Reemplazar la fila existente + + + + Conflict strategy + Estrategia para conflictos + + + + + Deselect All + Deseleccionar Todo + + + + Match Similar + Emparejar Similares + + + + Select All + Seleccionar Todo + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + Ya existe una tabla con nombre «%1» y una importación a una tabla existente solo es posible si el número de columnas coincide. + + + + There is already a table named '%1'. Do you want to import the data into it? + Ya existe una tabla con nombre «%1». ¿Desea importar los datos cargándolos en ella? + + + + Creating restore point failed: %1 + Creación del punto de restauración fallido: %1 + + + + Creating the table failed: %1 + Creación de la tabla fallido: %1 + + + + importing CSV + importando CSV + + + + Could not prepare INSERT statement: %1 + No se pudo preparar la sentencia «INSERT»: %1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + Fin de archivo inesperado. Por favor, asegúrese de haber configurado correctamente el entrecomillado y de que el archivo no esté mal formado. + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + Importar el archivo «%1» tardó %2ms. De ellos, %3ms se gastaron en la función fila. + + + + Inserting row failed: %1 + Inserción de línea fallido: %1 + + + + MainWindow + + + DB Browser for SQLite + DB Browser for SQLite + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + Estru&ctura + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + Hoja de &datos + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + Editar p&ragmas + + + + Temp Store + Almacenamiento temporal + + + + Secure Delete + Borrado seguro + + + + Case Sensitive Like + LIKE sensible a mayús/minus. + + + + Journal Mode + Modo de journal + + + + Journal Size Limit + Límite en tamaño de journal + + + + Recursive Triggers + Disparadores recursivos + + + Delete + pragma + Borrar + + + Truncate + pragma + Truncar + + + Persist + pragma + Persistir + + + Memory + pragma + Memoria + + + Off + pragma + Apagado + + + + Page Size + Tamaño de página + + + + Foreign Keys + Claves foráneas + + + + Auto Vacuum + Limpieza automática + + + + Max Page Count + Máx. número de páginas + + + Exclusive + pragma + Exclusivo + + + + Checkpoint Full FSYNC + Checkpoint FSYNC completo + + + + + Off + Apagado + + + + + Normal + + + + + + Full + Completa + + + + Default + Por defecto + + + + File + Archivo + + + + + Memory + Memoria + + + + Delete + Borrar + + + + Truncate + Truncar + + + + Persist + Persistir + + + + WAL + + + + + Exclusive + Exclusivo + + + + Automatic Index + Indexado automático + + + + Ignore Check Constraints + Ignorar restricciones CHECK + + + + Full FSYNC + FSYNC completo + + + + WAL Auto Checkpoint + Punto de comprobación WAL auto. + + + + User Version + Versión de usuario + + + + Synchronous + Síncrono + + + + None + Ninguna + + + + Incremental + + + + + Locking Mode + Modo de bloqueo + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + E&jecutar SQL + + + + toolBar1 + toolBar1 + + + + &Recent Files + Archivos &recientes + + + + This button clears the contents of the SQL logs + Este botón limpia el contenido del historial SQL + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + Este panel le permite examinar el histórico de todos los comandos SQL ordenados por la aplicación o por usted mismo + + + + + Project Toolbar + Barra de herramientas de proyectos + + + + Extra DB toolbar + Barra de herramientas extra + + + + + + Close the current database file + Cierra el archivo de base de datos actual + + + + &New Database + &Nueva base de datos + + + + This button closes the connection to the currently open database file + Este botón cierra la conexión con el archivo de base de datos actualmente abierto + + + + + Ctrl+F4 + + + + + &Undo + &Deshacer + + + + + Undo last change to the database + Deshace el último cambio realizado a la base de datos + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + Esta acción deshace el último cambio realizado a la base de datos en «Hoja de datos» «Ejecutar SQL». Volver a realizarlo no es posible. + + + + Compact &Database... + Compactar base de &datos... + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + Abre el asistente «Modificar tabla», donde se puede renombrar una tabla existente. También se pueden añadir o borrar campos de la tabla, así como modificar los nombres de los campos y sus tipos. + + + + &About + &Acerca de + + + + This button opens a new tab for the SQL editor + Este botón abre una nueva pestaña para el editor SQL + + + + Execute all/selected SQL + Ejecuta todo el SQL (o la selección) + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + Este botón ejecuta las sentencias SQL actualmente seleccionadas. Si no hay ningún texto seleccionado, se ejecutan todas las sentencias. + + + + Ctrl+Shift+T + + + + + &Load Extension... + &Cargar extensión... + + + + Execute line + Ejecutar línea + + + + This button executes the SQL statement present in the current editor line + Este botón ejecuta la sentencia SQL presente en la línea actual del editor + + + + &Wiki + &Wiki + + + + F1 + + + + + Bug &Report... + &Informar de fallos... + + + + Feature Re&quest... + Solicitud de &mejoras... + + + + Web&site + &Sitio web + + + + &Donate on Patreon... + &Donar en Patreon... + + + + &Save Project + &Guardar proyecto + + + + Open &Project... + Abrir &proyecto... + + + + Open &Project + Abrir &proyecto + + + + &Attach Database... + Ane&xar base de datos... + + + + + Add another database file to the current database connection + Añade un archivo de base de datos adicional a la conexión actual + + + + This button lets you add another database file to the current database connection + Este botón le permite añadir otro archivo de base de datos a la conexión de base de datos actual + + + + &Set Encryption... + &Establecer cifrado... + + + + This button saves the content of the current SQL editor tab to a file + Este botón guarda el contenido de la pestaña actual del editor SQL a un archivo + + + + SQLCipher &FAQ + SQLCipher &FAQ + + + + Find + Buscar + + + + Find or replace + Buscar o reemplazar + + + + Ctrl+H + + + + + + Ctrl+Shift+W + + + + + Table from CSV data in Clipboard... + Tabla desde CSV en el portapapeles... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + Esta opción interpreta el contenido del portapapeles como un archivo CSV y abre el mismo asistente usado para importar datos CSV desde un archivo. + + + + Show &Row Counts + &Contar filas + + + + This shows the number of rows for each table and view in the database. + Muestra el número de filas de cada una de las tablas y vistas de la base de datos. + + + + Save Database &As... + G&uardar base de datos como... + + + + Save the current database as a different file + Guardar la base de datos actual como un archivo diferente + + + + Refresh + Refrescar + + + + Reload the database structure + Recargar la estructura de la base de datos + + + + New &tab + Nueva pesta&ña + + + + Open SQL file(s) + Abrir archivo(s) SQL + + + + This button opens files containing SQL statements and loads them in new editor tabs + Este botón abre archivos que contengan sentencias SQL y los carga en pestañas nuevas del editor + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + Este botón le permite guardar todos los ajustes asociados a la base de datos abierta a un archivo de proyecto de «DB Browser for SQLite» + + + + This button lets you open a DB Browser for SQLite project file + Este botón le permite abrir un archivo de proyecto «DB Browser for SQLite» + + + + Export to &JSON + Exportar a &JSON + + + + &Open Database + &Abrir base de datos + + + + New In-&Memory Database + Nueva base de datos en &memoria + + + + Drag && Drop SELECT Query + Arrastrar y soltar consulta SELECT + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + Cuando se arrastran campos de la misma tabla o de una única tabla, pone una consulta SELECT en el editor + + + + Drag && Drop Qualified Names + Arrastrar y soltar nombres calificados + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + Usa nombres calificados (p.ej. "Tabla"."Campo") al arrastrar los objetos y soltarlos en el editor + + + + Drag && Drop Enquoted Names + Arrastrar y soltar nombres entrecomillados + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + Usa identificadores escapados (p.ej. "Tabla1") al arrastrar los objetos y soltarlos en el editor + + + + &Integrity Check + Comprobar &integridad + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + Ejecuta el pragma integrity_check en la base de datos abierta y devuelve los resultados en la pestaña Ejecutar SQL. Este pragma realiza una comprobación de integridad de toda la base de datos. + + + + &Foreign-Key Check + Comprobar clave &foránea + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + Ejecuta el pragma foreign_key_check con la base de datos abierta y devuelve los resultados en la pestaña Ejecutar SQL. + + + + &Quick Integrity Check + Comprobar integridad &rápido + + + + Run a quick integrity check over the open DB + Ejecuta una comprobación de integridad rápida en la base de datos abierta + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + Ejecuta el pragma quick_check en la base de datos abierta y devuelve los resultados en la pestaña Executar SQL. Este comando hace la mayoría de comprobaciones de PRAGMA integrity_check pero se ejecuta mucho más rápido. + + + + &Optimize + &Optimizar + + + + Attempt to optimize the database + Intenta optimizar la base de datos + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + Ejecuta el pragma optimize en la base de datos abierta. Este pragma realiza optimizaciones que pueden mejorar el rendimiento de consultas futuras. + + + + + Print + Imprimir + + + + Print text from current SQL editor tab + Imprime el texto de la pestaña actual del editor SQL + + + + Open a dialog for printing the text in the current SQL editor tab + Abre un diálogo para imprimir el texto de la pestaña actual del editor SQL + + + + Print the structure of the opened database + Imprime la estructura de la base de datos abierta + + + + Open a dialog for printing the structure of the opened database + Abre un diálogo para imprimir la estructura de la base de datos abierta + + + + Un/comment block of SQL code + Des/comentar bloque de código SQL + + + + Un/comment block + Des/comentar bloque de código + + + + Comment or uncomment current line or selected block of code + Comenta o descomenta la línea actual o el bloque de código seleccionado + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + Comenta o descomenta las líneas seleccionadas o la línea actual cuando no hay selección. El estado de todo el bloque es intercambiado en función de la primera línea. + + + + Ctrl+/ + + + + + Stop SQL execution + Detener ejecución de SQL + + + + Stop execution + Detener ejecución + + + + Stop the currently running SQL script + Detener el script SQL que está ejecutándose + + + + &Save Project As... + &Guardar proyecto como... + + + + + + Save the project in a file selected in a dialog + Guarda el proyecto en un archivo seleccionado en una ventana de diálogo + + + + Save A&ll + Guardar &todo + + + + + + Save DB file, project file and opened SQL files + Guarda los archivos de la base de datos, el proyecto y los archivos SQL abiertos + + + + Ctrl+Shift+S + + + + + Browse Table + Navegar Tabla + + + + Close Pro&ject + Cerrar pro&yecto + + + + + Close project and database files and return to the initial state + Cierra el proyecto y los archivos de la base de datos y vuelve al estado inicial + + + + Ctrl+Shift+F4 + + + + + + Detach Database + Desanclar base de datos + + + + + Detach database file attached to the current database connection + Desanclar el archivo de base de datos anclado a la conexión actual de la base de datos + + + + Shows or hides the Project toolbar. + Muestra u oculta la barra de herramientas de proyecto. + + + + Extra DB Toolbar + Barra de herramientas extra + + + + Export one or more table(s) to a JSON file + Exportar una o más tablas a un archivo JSON + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + Esta es la estructura de la base de datos abierta. +Puede arrastrar sentencias SQL desde una fila de objeto y soltarlas en otras aplicaciones o en otra instancia de «DB Browser for SQLite». + + + + + Table(&s) to JSON... + Tabla(&s) a JSON... + + + + Open Data&base Read Only... + Abrir &base de datos como solo lectura... + + + + Ctrl+Shift+O + + + + + Save results + Guardar resultados + + + + Save the results view + Guarda la vista de resultados + + + + This button lets you save the results of the last executed query + Este botón le permite guardar los resultados de la última consulta ejecutada + + + + + Find text in SQL editor + Buscar texto en el editor SQL + + + + This button opens the search bar of the editor + Este botón abre la barra de búsqueda del editor + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + Buscar o reemplazar texto en el editor SQL + + + + This button opens the find/replace dialog for the current editor tab + Este botón abre el diálogo de buscar/reemplazar para la pestaña actual del editor + + + + Export to &CSV + Exportar a &CSV + + + + Save as &view + Guardar como &vista + + + + Save as view + Guardar como vista + + + + Open an existing database file in read only mode + Abre una base de datos existente en modo de solo lectura + + + + &File + &Archivo + + + + &Import + &Importar + + + + &Export + E&xportar + + + + &Edit + &Editar + + + + &View + &Ver + + + + &Help + Ay&uda + + + + Too&ls + &Herramientas + + + + DB Toolbar + DB Toolbar + + + + Edit Database &Cell + Editar &celda + + + + Error Log + Registro de errores + + + + DB Sche&ma + Esque&ma + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + Esta es la estructura de la base de datos abierta. +Puede arrastrar múltiples objetos de la columna Nombre, soltarlos en el editor SQL y ajustar sus propiedades usando el menú contextual. Esto le ayudará a componer sentencias SQL. +Puede arrastrar sentencias SQL desde la columna Esquema y soltarlas en el editor SQL o en otras aplicaciones. + + + + + &Remote + &Remoto + + + + + Execute current line + Ejecuta la línea actual + + + + Shift+F5 + + + + + Sa&ve Project + &Guardar proyecto + + + + User + Usuario + + + + Application + Aplicación + + + + &Clear + &Limpiar + + + + &New Database... + &Nueva base de datos... + + + + + Create a new database file + Crea un nuevo archivo de base de datos + + + + This option is used to create a new database file. + Esta opción se usa para crear un nuevo archivo de base de datos. + + + + Ctrl+N + + + + + + &Open Database... + &Abrir base de datos... + + + + + + + + Open an existing database file + Abre un archivo de base de datos + + + + + + This option is used to open an existing database file. + Esta opción se usa para abrir un archivo de base de datos. + + + + Ctrl+O + + + + + &Close Database + &Cerrar base de datos + + + + + Ctrl+W + + + + + Opens the SQLCipher FAQ in a browser window + Abre la FAQ de SQLCipher en una ventana del navegador + + + + + Revert database to last saved state + Revierte el estado de la base de datos al último guardado + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + Esta opción se usa para revertir el estado de la base de datos actual al último guardado. Todos los cambios hechos desde la última vez que se guardó se perderán. + + + + + Write changes to the database file + Escribe los cambios al archivo de la base de datos + + + + This option is used to save changes to the database file. + Esta opción se usa para guardar los cambios en el archivo de la base de datos. + + + + Ctrl+S + + + + + Compact the database file, removing space wasted by deleted records + Compacta el archivo de la base de datos eliminando el espacio malgastado por los registros borrados + + + + + Compact the database file, removing space wasted by deleted records. + Compacta el archivo de la base de datos, eliminando el espacio malgastado por los registros borrados. + + + + E&xit + &Salir + + + + Ctrl+Q + + + + + Import data from an .sql dump text file into a new or existing database. + Importa datos de un archivo de texto con un volcado .sql en una base de datos nueva o existente. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + Esta opción se usa para importar datos de un archivo de texto con un volcado .sql en una base de datos nueva o existente. Los archivos de volcado SQL se pueden crear en la mayoría de los motores de base de datos, incluyendo MySQL y PostgreSQL. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Abre un asistente que le permite importar datos desde un archivo de texto con valores separado por comas a una tabla de una base de datos. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Abre un asistente que le permite importar datos desde un archivo de texto con valores separado por comas a una tabla de una base de datos. Los archivos CSV se pueden crear en la mayoría de las aplicaciones de bases de datos y hojas de cálculo. + + + + Export a database to a .sql dump text file. + Exporta la base de datos como un volcado .sql a un archivo de texto. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + Esta opción le permite exportar la base de datos como un volcado .sql a un archivo de texto. Los archivos de volcado SQL contienen todos los datos necesarios para recrear la base de datos en la mayoría de los motores de base de datos, incluyendo MySQL y PostgreSQL. + + + + Export a database table as a comma separated text file. + Exporta la base de datos como un archivo de texto con valores separados por comas. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + Exporta la base de datos como un archivo de texto con valores separados por comas, listo para ser importado en otra base de datos o aplicaciones de hoja de cálculo. + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Abre el asistente para Crear una Tabla, donde se puede definir el nombre y los campos de una nueva tabla en la base de datos + + + + + Delete Table + Borrar tabla + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Abre el asistente para «Borrar tabla», donde se puede seleccionar una tabla de la base de datos para borrar. + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + Abre el asistente «Crear índice», donde se puede definir un nuevo índice de una tabla existente de la base de datos. + + + + &Preferences... + &Preferencias... + + + + + Open the preferences window. + Abrir la ventana de preferencias. + + + + &DB Toolbar + &Barra de herramientas + + + + Shows or hides the Database toolbar. + Muestra u oculta la barra de herramientas de la base de datos. + + + + Shift+F1 + + + + + &Recently opened + Archivos &recientes + + + + Ctrl+T + + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + Aviso: este pragma no es legible y este valor se ha supuesto. Escribir el pragma puede sobreescribir un LIKE redefinido que proporcione una extensión de SQLite. + + + + SQL &Log + Historial de &SQL + + + + Show S&QL submitted by + Mostrar S&QL ejecutado por + + + + &Plot + &Gráfica + + + + &Revert Changes + &Revertir cambios + + + + &Write Changes + &Guardar cambios + + + + &Database from SQL file... + Base de datos de &archivo SQL... + + + + &Table from CSV file... + &Tabla de archivo CSV... + + + + &Database to SQL file... + &Base de datos a archivo SQL... + + + + &Table(s) as CSV file... + &Tabla(s) a archivo CSV... + + + + &Create Table... + &Crear tabla... + + + + &Delete Table... + &Borrar tabla... + + + + &Modify Table... + &Modificar tabla... + + + + Create &Index... + Crear í&ndice... + + + + W&hat's This? + ¿&Qué es esto? + + + + &Execute SQL + &Ejecutar SQL + + + + + + Save SQL file + Guardar archivo SQL + + + + Ctrl+E + + + + + Export as CSV file + Exportar como archivo CSV + + + + Export table as comma separated values file + Exportar tabla como archivo de valores separados por comas + + + + + Save the current session to a file + Guarda la sesión actual en un archivo + + + + + Load a working session from a file + Carga una sesión de trabajo de un archivo + + + + + Save SQL file as + Guardar archivo SQL como + + + + &Browse Table + &Mostrar datos + + + + Copy Create statement + Copiar sentencia CREATE + + + + Copy the CREATE statement of the item to the clipboard + Copia la sentencia CREATE del ítem al portapapeles + + + + Ctrl+Return + + + + + Ctrl+L + + + + + + Ctrl+P + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Encrypted + Cifrado + + + + Read only + Solo lectura + + + + Database file is read only. Editing the database is disabled. + El archivo de la base de datos es de solo lectura. La edición de la base de datos está desactivada. + + + + Database encoding + Codificación de la base de datos + + + + Database is encrypted using SQLCipher + La base de datos está cifrada usando SQLCipher + + + + + Choose a database file + Seleccione un archivo de base de datos + + + + + + Choose a filename to save under + Seleccione un nombre de archivo en el que guardar + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + Error mientras se guardaba el archivo de la base de datos. Esto significa que no todos lo cambios hechos a la base de datos se han guardado. Antes tiene que solucionar el siguiente error. +%1 + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + ¿Está seguro de que quiere deshacer todos los cambios hechos al archivo de la base de datos «%1» desde la última vez que se guardó? + + + + Choose a file to import + Seleccione el archivo a importar + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (sólo lectura) + + + + Open Database or Project + Abrir base de datos o proyecto + + + + Attach Database... + Anexar base de datos... + + + + Import CSV file(s)... + Importar archivo(s) CSV... + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + ¿Quiere guardar los cambios hechos a las pestañas SQL en el archivo de proyecto «%1»? + + + + Text files(*.sql *.txt);;All files(*) + Archivos de texto(*.sql *.txt);;Todos los archivos(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + ¿Quiere crear un nuevo archivo de base de datos donde poner los datos importados? +Si responde no se intentarán importar los datos del archivo SQL en la base de datos actual. + + + + Automatically load the last opened DB file at startup + Cargar automáticamente al inicio el último archivo abierto + + + + Ctrl+0 + + + + + Alt+Shift+W + + + + + Choose a database file to save under + Elija un archivo de base de datos en el que guardar + + + + Error while saving the database to the new file. + Error mientras se guardaba la base de datos en el nuevo archivo. + + + + Do you want to save the changes made to the project file '%1'? + ¿Quiere guardar los cambios hechos al archivo de proyecto «%1»? + + + + Edit View %1 + Editar vista %1 + + + + Edit Trigger %1 + Editar disparador %1 + + + + Result: %1 + Resultado: %1 + + + + File %1 already exists. Please choose a different name. + El archivo %1 ya existe. Por favor elija un nombre diferente. + + + + Error importing data: %1 + Error importando datos: %1 + + + + Import completed. + Importación completada. + + + + Delete View + Borrar vista + + + + Modify View + Modificar vista + + + + Delete Trigger + Borrar disparador + + + + Modify Trigger + Modificar disparador + + + + Delete Index + Borrar índice + + + + Modify Index + Modificar índice + + + + Modify Table + Modificar tabla + + + + Opened '%1' in read-only mode from recent file list + Se ha abierto «%1» en modo de sólo lectura desde la lista de archivos recientes + + + + Opened '%1' from recent file list + Se ha abierto «%1» desde la lista de archivos recientes + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + Seleccione la acción a aplicar al archivo. + Seleccione la acción a aplicar a los archivos <br/>Nota: sólo «Importar» procesará más de un archivo. + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + Las sentencias en la pestaña «%1»; todavía se están ejecutando. Al cerrar la pestaña se detendrá la ejecución. Esto puede dejar la base de datos en un estado inconsistente. ¿Está seguro de que quiere cerrar la pestaña? + + + + DB file '%1' could not be opened + El archivo de base de datos «%1»; no se pudo abrir + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + Este proyecto está usando un formato de archivo antiguo porque fue creado usando «DB Browser for SQLite» versión 3.10 o menor. La carga de este formato de archivo no está soportado en su totalidad. Si quiere cargarlo completamente, por favor, use «DB Browser for SQLite» versión 3.12 para convertirlo al nuevo formato. + + + + Table '%1' not found; settings ignored + No se ha encontrado la tabla «%1»;; ajustes ignorados + + + + -- Reference to file "%1" (not supported by this version) -- + -- Vínculo al archivo "%1" (no soportado en esta versión) -- + + + + Yes. Don't ask again + Sí. No pregunte otra vez + + + + This action will open a new SQL tab with the following statements for you to edit and run: + Esta acción abrirá una nueva pestaña SQL con las siguientes sentencias para que usted las pueda modificar y ejecutar: + + + + Rename Tab + Renombrar Pestaña + + + + Duplicate Tab + Duplicar Pestaña + + + + Close Tab + Cerrar Pestaña + + + + Opening '%1'... + Abriendo «%1»... + + + + There was an error opening '%1'... + Hubo un error abriendo «%1»... + + + + Value is not a valid URL or filename: %1 + Valor no es un nombre de archivo o URL válido: %1 + + + + Do you want to save the changes made to SQL tabs in a new project file? + ¿Quiere guardar los cambios hechos a las pestañas SQL en un nuevo archivo de proyecto? + + + + Do you want to save the changes made to the SQL file %1? + ¿Quiere guardar los cambios hechos al archivo SQL %1? + + + + Could not find resource file: %1 + No se pudo encontrar el archivo de recursos: %1 + + + + Choose a project file to open + Seleccione un archivo de proyecto para abrir + + + + Could not open project file for writing. +Reason: %1 + No se pudo abrir el archivo de proyecto para escritura. +Motivo: %1 + + + + Collation needed! Proceed? + ¡Es necesaria una función de comparación! ¿Proceder? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. Create a backup! - Una tabla en esta base de datos necesita una función de comparación especial '%1' que esta aplicacion no puede proporcionar sin más información. + Una tabla en esta base de datos necesita una función de comparación especial «%1» que esta aplicación no puede proporcionar sin más información. Si decide continuar, está avisado de que la base de datos se puede dañar. -¡Cree un backup! +¡Cree una copia de respaldo! + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + Al definir los valores de PRAGMA se consolidará la transacción actual. +¿Está seguro? + + + + Ctrl+Tab + + + + + Ctrl+Shift+Tab + + + + + Clear List + Limpiar lista + + + + Window Layout + Disposición de la ventana + + + + Reset Window Layout + Reiniciar disposición + + + + Simplify Window Layout + Simplificar disposición + + + + Alt+Shift+0 + + + + + Dock Windows at Bottom + Acoplar ventanas en la parte inferior + + + + Dock Windows at Left Side + Acoplar ventanas en la parte izquierda + + + + Dock Windows at Top + Acoplar ventanas en la parte superior + + + + The database is currently busy. + La base de datos está ocupada + + + + Click here to interrupt the currently running query. + Haga clic aquí para interrumpir la consulta que se está ejecutando + + + + Could not open database file. +Reason: %1 + No se pudo abrir el archivo de base de datos. +Razón: %1 + + + + In-Memory database + Base de datos en memoria + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + Todavía se están ejecutando sentencias SQL. Al cerrar la base de datos se detendrá la ejecución. Esto puede dejar la base de datos en un estado inconsistente. ¿Está seguro de que quiere cerrar la base de datos? + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + ¿Está seguro de que quiere borrar la tabla «%1»? +Se perderán todos los datos asociados con la tabla. + + + + Are you sure you want to delete the view '%1'? + ¿Está seguro de que quiere borrar la vista «%1»? + + + + Are you sure you want to delete the trigger '%1'? + ¿Está seguro de que quiere borrar el disparador «%1»? + + + + Are you sure you want to delete the index '%1'? + ¿Está seguro de que quiere borrar el índice «%1»? + + + + Error: could not delete the table. + Error: no se pudo borrar la tabla. + + + + Error: could not delete the view. + Error: no se pudo borrar la vista. + + + + Error: could not delete the trigger. + Error: no se pudo borrar el disparador. + + + + Error: could not delete the index. + Error: no se pudo borrar el índice. + + + + Message from database engine: +%1 + Mensaje de la base de datos: +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + Para editar la tabla es necesario guardar antes todos los cambios pendientes. +¿Está seguro de que quiere guardar la base de datos? + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + Ya se están ejecutando sentencias SQL. ¿Quiere detenerlas para en su lugar ejecutar las sentencias actuales?. Esto puede dejar la base de datos en un estado inconsistente. + + + + -- EXECUTING SELECTION IN '%1' +-- + -- EJECUTANDO SELECCIÓN DE «%1» +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- EJECUTANDO LÃNEA DE «%1» +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- EJECUTANDO TODO «%1» +-- + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + Establecer valores PRAGMA o realizar una limpieza consolidará la transacción actual. +¿Está seguro? + + + + Busy (%1) + Ocupado (%1) + + + + %1 rows returned in %2ms + %1 filas devueltas en %2ms + + + + Choose text files + Elija archivos de texto + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + Importación completada. Algunas restricciones de las claves foráneas se han infringido. Por favor arréglelas antes de guardar. + + + + Select SQL file to open + Seleccione el archivo SQL a abrir + + + + Select file name + Seleccione el nombre del archivo + + + + Select extension file + Seleccione el archivo de extensión + + + + Extension successfully loaded. + Extensiones cargadas con éxito. + + + + Error loading extension: %1 + Error cargando la extensión: %1 + + + + + Don't show again + No volver a mostrar + + + + New version available. + Hay una nueva versión disponible. + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + Hay disponible una nueva versión de «DB Browser for SQLite» (%1.%2.%3).<br/><br/>Por favor, descárguela de <a href='%4'>%4</a>. + + + + Project saved to file '%1' + Proyecto guardado en el archivo «%1» + + + + creating collation + creando comparación + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + Establezca el nuevo nombre para la pestaña SQL. Use el carácter «&&» para permitir usar el carácter siguiente como un atajo de teclado. + + + + Please specify the view name + Por favor, especifique el nombre de la vista + + + + There is already an object with that name. Please choose a different name. + Ya hay un objeto con ese nombre. Por favor, elija un nombre diferente. + + + + View successfully created. + Vista creada con éxito. + + + + Error creating view: %1 + Error creando la vista: %1 + + + + This action will open a new SQL tab for running: + Esta acción abrirá una nueva pestaña SQL para ejecutar: + + + + Press Help for opening the corresponding SQLite reference page. + Pulse Ayuda para abrir la página correspondiente de la referencia de SQLite. + + + + DB Browser for SQLite project file (*.sqbpro) + Archivo de proyecto de «DB Browser for SQLite» (*.sqbpro) + + + + Error checking foreign keys after table modification. The changes will be reverted. + Error comprobando las claves foráneas tras la modificación de la tabla. Los cambios se desharán. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + Esta tabla no ha pasado la comprobación de claves foráneas.<br/>Debería ejecutar 'Herramientas | Comprobar Claves foráneas' y arreglar los problemas mostrados. + + + + + At line %1: + En la línea %1: + + + + Result: %2 + Resultado: %2 + + + + Execution finished with errors. + Ejecución terminada con errores. + + + + Execution finished without errors. + Ejecución terminada sin errores. + + + + NullLineEdit + + + Set to NULL + Poner a NULL + + + + Alt+Del + + + + + PlotDock + + + Plot + Gráfica + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>Esta tabla muestra la lista de columnas de la tabla actualmente visualizada o de la consulta recién ejecutada. Puede seleccionar las columnas que desea usar como ejes X o Y en el gráfico del panel inferior. La tabla muestra el tipo de eje detectado, el cual afectará al gráfico resultante. Para los ejes Y solo se pueden seleccionar columnas numéricas, pero para el eje X se pueden seleccionar :</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Fecha/Hora</span>: texto con formato &quot;aaaa-MM-dd hh:mm:ss&quot; o &quot;aaaa-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Fecha</span>: texto con formato &quot;aaaa-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: texto con formato &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Etiqueta</span>: texto con otros formatos. Seleccionado esta columna como eje X se dibuja un gráfico de barras con los valores de la columna usados como etiquetas de las barras.</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numérico</span>: valores reales o enteros</li></ul><p>Haciendo doble clic sobre las celdas Y se puede cambiar el color usado para la gráfica correspondiente.</p></body></html> + + + + Columns + Columnas + + + + X + X + + + + Y1 + + + + + Y2 + + + + + Axis Type + Tipo de eje + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + Aquí se dibuja un gráfico cuando se seleccionan los valores de X e Y en la parte superior. + +Con un clic sobre los puntos se seleccionan en el gráfico y en la tabla. Con Ctrl+Clic se pueden seleccionar rangos de puntos. + +Use la rueda del ratón para aumentar y disminuir el gráfico y arrastre con el ratón para cambiar el rango del eje. + +Seleccione los ejes o sus etiquetas para arrastrar y aumentar/disminuir solo en esa orientación. + + + + Line type: + Tipo de línea: + + + + + None + Ninguno + + + + Line + Línea + + + + StepLeft + EscalónIzquierda + + + + StepRight + EscalónDerecha + + + + StepCenter + EscalónCentrado + + + + Impulse + Impulso + + + + Point shape: + Forma de punto: + + + + Cross + Aspa es más específico que cruz. El signo más también es una cruz (una cruz griega). + Aspa + + + + Plus + Más + + + + Circle + Circunferencia + + + + Disc + Círculo + + + + Square + Cuadrado + + + + Diamond + Diamante + + + + Star + Estrella + + + + Triangle + Triángulo + + + + TriangleInverted + TriánguloInvertido + + + + CrossSquare + AspaCuadrado + + + + PlusSquare + MásCuadrado + + + + CrossCircle + AspaCircunferencia + + + + PlusCircle + MásCircunferencia + + + + Peace + Paz + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>Guarda la gráfica actual...</p><p>El formato del archivo es elegido por la extensión (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + Guarda la gráfica actual... + + + + + Load all data and redraw plot + Cargar todos los datos y redibujar el gráfico + + + + + + Row # + Nº de línea + + + + Copy + Copiar + + + + Print... + Imprimir... + + + + Help + Ayuda + + + + Show legend + Mostrar leyenda + + + + Stacked bars + Barras apiladas + + + + Fixed number format + Formato de números fijos + + + + Date/Time + Fecha/hora + + + + Date + Fecha + + + + Time + Tiempo + + + + + Numeric + Numérico + + + + Label + Etiqueta + + + + Invalid + Inválido + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + Cargar todos los datos y redibujar el gráfico. +Aviso: aún no se han cargado todos los datos desde la tabla debido al mecanismo de lectura parcial. + + + + Choose an axis color + Elija un color para el eje + + + + Choose a filename to save under + Seleccione un nombre de archivo en el que guardar + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Todos los archivos(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + Existen lazos en este gráfico y el estilo de línea seleccionado solo se puede aplicar a gráficos ordenados por X. Debe ordenar la tabla o consulta por X para eliminar los lazos o seleccionar uno de los estilos soportados por los lazos: Ninguno o Línea. + + + + Loading all remaining data for this table took %1ms. + Cargar todos los datos restantes para esta tabla tardó %1ms. + + + + PreferencesDialog + + + Preferences + Preferencias + + + + &General + &General + + + + Remember last location + Recordar la última ubicación + + + + Always use this location + Usar siempre esta ubicación + + + + Remember last location for session only + Recordar la última ubicación solamente para esta sesión + + + + + + ... + ... + + + + Default &location + &Posición por defecto + + + + Lan&guage + &Idioma + + + + Automatic &updates + &Actualizaciones automáticas + + + + + + + + + + + + + + enabled + activado + + + + Show remote options + Mostrar opciones del remoto + + + + &Database + &Base de datos + + + + Database &encoding + Co&dificación de la base de datos + + + + Open databases with foreign keys enabled. + Abrir base de datos con claves foráneas activadas. + + + + &Foreign keys + Claves &foráneas + + + + Data &Browser + &Hoja de datos + + + + Remove line breaks in schema &view + Elimina los saltos de línea en la &vista del esquema + + + + Prefetch block si&ze + &Tamaño del bloque de precarga + + + + SQ&L to execute after opening database + SQ&L a ejecutar tras abrir la base de datos + + + + Default field type + Tipo de campo por defecto + + + + Font + Tipo de letra + + + + &Font + &Tipo de letra + + + + Content + Contenido + + + + Symbol limit in cell + Límite de símbolos en la celda + + + + NULL + NULL + + + + Regular + Normal + + + + Binary + Binario + + + + Background + Fondo + + + + Filters + Filtros + + + + Toolbar style + Estilo de barra de herramientas + + + + + + + + Only display the icon + Solo mostrar el icono + + + + + + + + Only display the text + Solo mostrar el texto + + + + + + + + The text appears beside the icon + El texto aparece junto al icono + + + + + + + + The text appears under the icon + El texto aparece bajo el icono + + + + + + + + Follow the style + Seguir el estilo predefinido + + + + DB file extensions + Extensiones de archivos de BB.DD. + + + + Manage + Gestionar + + + + Main Window + Ventana principal + + + + Database Structure + Estructura + + + + Browse Data + Hoja de datos + + + + Execute SQL + Ejecutar SQL + + + + Edit Database Cell + Editar celda + + + + When this value is changed, all the other color preferences are also set to matching colors. + Cuando se cambia este valor, también se ajustan con colores a juego todas las otras prefencias de color. + + + + Follow the desktop style + Usa el estilo del escritorio + + + + Dark style + Estilo oscuro + + + + Light style + Estilo claro + + + + Application style + Estilo de la aplicación + + + + This sets the font size for all UI elements which do not have their own font size option. + Esto establece el tamaño de tipografía para todos los elementos de la interfaz de usuario que no tienen su propia opción. + + + + Font size + Tamaño de fuente + + + + Max Recent Files + Máximo de archivos recientes + + + + Prompt to save SQL tabs +in new project file + Preguntar si guardar pestañas SQL +en un nuevo archivo de proyecto + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + Cuando está activado, los cambios hechos en el editor SQL hacen que al cerrar la pestaña del editor SQL se muestre un diálogo de confirmación para guardar el proyecto. + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + Cuando está activado, se omiten los saltos de línea en la columna Esquema, tanto en la pestaña Estructura en pantalla, como al imprimir. + + + + Database structure font size + Tamaño de fuente de la estructura de base de datos + + + + Font si&ze + &Tamaño de fuente + + + + Formatted + Formateado + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + Este es el máximo número ocurrencias permitidos para que algunas funcionalidades computacionalmente costosas sean activadas: +Máximo número de filas en una tabla para activar el autocompletado basado en los valores actuales en la columna. +Máximo número de índices en una selección para calcular la suma y la media. +Pueden ajustarse a 0 parar desactivar las funcionalidades. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + Este el el número máximo de filas en una tabla para activar el autocompletado basado en los valores actuales en la columna. +Se puede poner a 0 para desactivar el autocompletado. + + + + Selection background + Fondo de la selección + + + + Selection foreground + Texto de la selección + + + + Highlight + Resaltado + + + + Use tabs for indentation + Usar tabuladores para indentar + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + Cuando está activado, la tecla Tab insertará tabuladores y espacios para indentar. En caso contrario, para la indentación sólo se insertarán espacios. + + + + Close button on tabs + Botón de cerrar en pestañas + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + Si se habilita, las pestañas del editor SQL tendrán un botón para cerrarlas. En cualquier caso, usted siempre podrá usar el menú contextual o el atajo de teclado para cerrarlas. + + + + Select built-in extensions to load for every database: + Seleccione extensiones incorporadas a cargar para cualquier base de datos: + + + + Proxy + Proxy + + + + Configure + Configurar + + + + Export Settings + Exportar ajustes + + + + Import Settings + Importar ajustes + + + + Field display + Estilo de las celdas + + + + Displayed &text + &Texto presentado + + + + + + + + + + + Click to set this color + Haga clic para ajustar este color + + + + Text color + Color del texto + + + + Background color + Color del fondo + + + + + Preview only (N/A) + Solo vista previa (N/A) + + + + Escape character + Carácter de escape + + + + Delay time (&ms) + Tiempo de retardo (&ms) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + Define el tiempo de espera antes de que se aplique un nuevo valor de filtro. Se puede poner a 0 para desactivar la espera. + + + + &SQL + &SQL + + + + Context + Contexto + + + + Colour + Color + + + + Bold + Negrita + + + + Italic + Cursiva + + + + Underline + Subrayado + + + + Keyword + Palabra clave + + + + Function + Función + + + + Table + Tabla + + + + Comment + Comentario + + + + Identifier + Identificador + + + + String + Cadena + + + + Current line + Línea actual + + + + SQL &editor font size + Tamaño de letra del &editor SQL + + + + Tab size + Tamaño del tabulador + + + + &Wrap lines + Ajuste de líneas + + + + Never + Nunca + + + + At word boundaries + En los límites de palabra + + + + At character boundaries + En los límites de caracteres + + + + At whitespace boundaries + En los límites de espacios en blanco + + + + &Quotes for identifiers + &Comillas para identificadores + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + Elija el mecanismo de entrecomillado usado por la aplicación para los identificadores en el código SQL. + + + + "Double quotes" - Standard SQL (recommended) + "Dobles comillas" - SQL estándar (recomendado) + + + + `Grave accents` - Traditional MySQL quotes + `Acentos graves` - Entrecomillado tradicional de MySQL + + + + [Square brackets] - Traditional MS SQL Server quotes + [Corchetes] - Entrecomillado tradicional de MS SQL Server + + + + Keywords in &UPPER CASE + Palabras claves en &MAYÚSCULAS + + + + When set, the SQL keywords are completed in UPPER CASE letters. + Si se activa, las palabras claves de SQL se completan en letras MAYÚSCULAS. + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + Si se activa, las líneas de código SQL que causaron errores durante la última ejecución se destacan y el marco de resultados indica el error mediante el color del fondo + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite proporciona una función SQL para cargar extensiones desde un archivo de biblioteca compartida. Active esta opción si desea usar la función <span style=" font-style:italic;">load_extension()</span> desde código SQL.</p><p>Por razónes de seguridad, la carga de extensiones está desactivada por defecto y debe ser habilitada usando esta configuración. Siempre puede cargar extensiones a través de la interfaz de usuario, incluso aunque esta opción esté deshabilitada.</p></body></html> + + + + Allow loading extensions from SQL code + Permitir cargar extensiones desde código SQL + + + + Remote + Remoto + + + + CA certificates + Certificados CA + + + + + Subject CN + Sujeto CN + + + + Common Name + Nombre común + + + + Subject O + Sujeto O + + + + Organization + Organización + + + + + Valid from + Válido desde + + + + + Valid to + Válido hasta + + + + + Serial number + Número de serie + + + + Your certificates + Sus certificados + + + + File + Archivo + + + + Subject Common Name + Nombre común del sujeto + + + + Issuer CN + Emisor CN + + + + Issuer Common Name + Nombre común del emisor + + + + Clone databases into + Clonar las bases de datos en + + + + SQL editor &font + &Tipo de letra del editor SQL + + + + Error indicators + Indicadores de error + + + + Hori&zontal tiling + Mosaico hori&zontal + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + Si se activa, el editor de código SQL y la vista de la tabla de resultados se muestran de lado a lado en lugar de una sobre la otra. + + + + Code co&mpletion + Co&mpletar código + + + + Threshold for completion and calculation on selection + Umbral para cálculos al seleccionar y completación + + + + Show images in cell + Mostrar imágenes en la celda + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + Active esta opción para mostrar una previsualización de los BLOBs que contengan datos de imagen en las celdas. Tenga en cuenta que esto puede afectar el desempeño del navegador de la hoja de datos. + + + + Foreground + Texto + + + + SQL &results font size + Tamaño de letra de &resultados + + + + &Extensions + E&xtensiones + + + + Select extensions to load for every database: + Seleccione extensiones a cargar para cualquier base de datos: + + + + Add extension + Añadir extensión + + + + Remove extension + Eliminar extensión + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p> +Aunque SQLite admite el operador REGEXP, no implementa en sí ningún algoritmo de expresiones<br/> +regulares sino que llama a los de la aplicación en ejecución. «DB Browser for SQLite» implementa este<br/> +método para permitirle usar REGEXP de fábrica. Sin embargo, como hay múltiples posibles<br/> +implementaciones y puede querer usar otra, puede desactivar este método y cargar el suyo propio<br/> +usando una extensión. Necesitará reiniciar la aplicación.</p> +</body></html> + + + + Disable Regular Expression extension + Desactivar extensión de expresiones regulares + + + + + Choose a directory + Seleccione una carpeta + + + + + The language will change after you restart the application. + El idioma cambiará al reiniciar la aplicación. + + + + Select extension file + Seleccione archivo de extensión + + + + Extensions(*.so *.dylib *.dll);;All files(*) + Extensiones (*.so *.dll);;Todos los archivos (*) + + + + Import certificate file + Importar archivo de certificado + + + + No certificates found in this file. + No hay certificados en este archivo. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + ¿Está seguro de que quiere eliminar este certificado? ¡Todos los datos del certificado se borrarán de los ajustes de la aplicación! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + ¿Está seguro de que desea borrar todos los ajustes guardadas? +Todas sus preferencias se perderán y se usarán valores predeterminados. + + + + Save Settings File + Guardar archivo de ajustes + + + + + Initialization File (*.ini) + Archivos de inicialización (*.ini) + + + + The settings file has been saved in location : + + Los ajustes se han guardado en la ubicación: - - - SqlExecutionArea - - Form - Formulario + + Open Settings File + Abrir archivo de ajustes + + + + The settings file was loaded properly. + El archivo de ajustes se ha cargado correctamente. + + + + The selected settings file is not a normal settings file. +Please check again. + El archivo de ajustes seleccionado no parece tener el formato esperado. +Por favor compruebe que es correcto. + + + + ProxyDialog + + + Proxy Configuration + Configuración del proxy + + + + Pro&xy Type + Tipo de pro&xy + + + + Host Na&me + No&mbre del host + + + + Port + Puerto + + + + Authentication Re&quired + Autentificación re&querida + + + + &User Name + Nombre de &usuario + + + + Password + Contraseña + + + + None + Ninguno + + + + System settings + Ajustes del sistema + + + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 + + + + QObject + + + Error importing data + Error importando datos + + + + from record number %1 + del registro número %1 + + + + . +%1 + . +%1 + + + + Importing CSV file... + Importando archivo CSV... + + + + Cancel + Cancelar + + + + All files (*) + Todos los archivos (*) + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + Archivos de BB.DD. SQLite (*.db *.sqlite *.sqlite3 *.db3) + + + + Left + Izquierda + + + + Right + Derecha + + + + Center + Centrado + + + + Justify + Justificado + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + Archivos de BB.DD. SQLite (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + Archivos de proyecto de DB Browser for SQLite (*.sqbpro) + + + + SQL Files (*.sql) + Archivos SQL (*.sql) + + + + All Files (*) + Todos los archivos (*) + + + + Text Files (*.txt) + Archivos de texto (*.txt) + + + + Comma-Separated Values Files (*.csv) + Archivos de valores separados por comas (*.csv) + + + + Tab-Separated Values Files (*.tsv) + Archivos de valores separados por tabuladores (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + Archivos de Valores Separados por Delimitador (*.dsv) + + + + Concordance DAT files (*.dat) + Archivos DAT de Concordance (*.dat) + + + + JSON Files (*.json *.js) + Archivos JSON (*.json *.js) + + + + XML Files (*.xml) + Archivos XML (*.xml) + + + + Binary Files (*.bin *.dat) + Archivos binarios (*.bin *.dat) + + + + SVG Files (*.svg) + Archivos SVG (*.svg) + + + + Hex Dump Files (*.dat *.bin) + Archivos de volcado Hex (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + Extensiones (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + Archivos de inicialización (*.ini) + + + + QsciCommand + + Paste + Pegar + + + Cancel + Cancelar + + + + QsciLexerCPP + + Default + Por defecto + + + Keyword + Palabra clave + + + Identifier + Identificador + + + + QsciLexerJSON + + Default + Por defecto + + + String + Cadena + + + + QsciLexerJavaScript + + Regular expression + Expresión regular + + + + QsciLexerPython + + Default + Por defecto + + + Comment + Comentario + + + Keyword + Palabra clave + + + Identifier + Identificador + + + + QsciLexerSQL + + Default + Por defecto + + + Comment + Comentario + + + Keyword + Palabra clave + + + Identifier + Identificador + + + + QsciScintilla + + &Undo + &Deshacer + + + Select All + Seleccionar Todo + + + + RemoteCommitsModel + + + Commit ID + ID versión + + + + Message + Mensaje + + + + Date + Fecha + + + + Author + Autor + + + + Size + Tamaño + + + + Authored and committed by %1 + Escrito y registrado por %1 + + + + Authored by %1, committed by %2 + Escrito por %1, registrado por %2 + + + + RemoteDatabase + + + Error opening local databases list. +%1 + Error abriendo la lista de bases de datos locales. +%1 + + + + Error creating local databases list. +%1 + Error creando la lista de bases de datos locales. +%1 + + + + RemoteDock + + + Remote + Remoto + + + + Local + Local + + + + Identity + Identidad + + + + Push currently opened database to server + Cargar la base de datos actualmente abierta al servidor + + + + Upload + Cargar al servidor + + + + DBHub.io + + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>En este panel, las BB.DD. remotas del sitio web dbhub.io se pueden añadir a «DB Browser for SQLite». En primer lugar necesita una identidad:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ingrese en el sitio web dbhub.io (use sus credenciales de GitHub o las que desee)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Haga clic en el botón de crear un certificado de cliente (esa es su identidad). Eso le proporcionará un archivo de certificado (guárdelo en su disco local).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Vaya a la pestaña «Remoto» de las preferencias de «DB Browser for SQLite». Haga clic en el botón para añadir el nuevo certificado a la aplicación y elija el archivo de certificado recién descargado.</li></ol><p>Ahora el panel «Remoto» le mostrará su identidad y podrá añadir BB.DD. remotas.</p></body></html> + + + + Current Database + Base de datos actual + + + + Clone + Clonar + + + + Branch + Rama + + + + Commits + Versiones + + + + Commits for + Versiones para + + + + Delete Database + Borrar base de datos + + + + Delete the local clone of this database + Borrar el clon local de la base de datos + + + + Open in Web Browser + Abrir en el navegador web + + + + Open the web page for the current database in your browser + Abrir la página web de la base de datos actual en su navegador + + + + Clone from Link + Clonar desde enlace + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + Use esto para descargar una base de datos remota y editarla localmente usando una URL provista por la página web de la base de datos. + + + + Refresh + Refrescar + + + + Reload all data and update the views + Recargar todos los datos y actualizar las vistas + + + + Clone Database + Clonar base de datos + + + + Open Database + Abrir base de datos + + + + Open the local copy of this database + Abrir la copia local de esta base de datos + + + + Check out Commit + Obtener versión + + + + Download and open this specific commit + Descargar y abrir esta versión específica + + + + Check out Latest Commit + Obtener la última versión + + + + Check out the latest commit of the current branch + Obtener la última versión de la rama actual + + + + Save Revision to File + Guardar versión en un archivo + + + + Saves the selected revision of the database to another file + Guarda la versión seleccionada de la base de datos a otro archivo + + + + Upload Database + Cargar base de datos + + + + Upload this database as a new commit + Cargar en el servidor esta base de datos como una nueva versión + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>Está usando una identidad integrada de sólo lectura. Para subir su base de datos necesita configurar y usar su cuenta DBHub.io.</p><p>¿Todavía no tiene una cuenta en DBHub.io? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Cree una ahora</span></a> e importe su certificado <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">aquí</span></a> para compartir sus bases de datos.</p><p>Tiene ayuda en línea <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">aquí</span></a>.</p></body></html> + + + + &User + &Usuario + + + + &Database + &Base de datos + + + + Back + Retroceder + + + + Select an identity to connect + Seleccione una identidad para conectar + + + + Public + Pública + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + Esto descarga una base de datos desde un servidor remoto para edición local. +Por favor, introduzca la URL desde la que clonar. Puede obtener esta URL +haciendo clic en el botón «Clonar base de datos en DB4S» de la página web +de la base de datos. + + + + Invalid URL: The host name does not match the host name of the current identity. + URL inválida: El nombre de «host» no encaja con el de la identidad actual. + + + + Invalid URL: No branch name specified. + URL inválida: No se ha especificado el nombre de rama. + + + + Invalid URL: No commit ID specified. + URL inválida: No se ha especificado el ID de versión. + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + Ha realizado cambios en el clon local de la base de datos. Al obtener esta versión sobreescribiría los cambios locales. +¿Está seguro de querer proceder? + + + + The database has unsaved changes. Are you sure you want to push it before saving? + La base de datos tiene cambios sin guardar. ¿Está seguro de enviarlos sin guardar? + + + + The database you are trying to delete is currently opened. Please close it before deleting. + La base de datos que pretende borrar está actualmente abierta. Por favor, ciérrela antes de borrarla. + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + Esto borra la versión local de esta base de datos con todos los cambios que aún no ha registrado. ¿Está seguro de querer borrarla? + + + + RemoteLocalFilesModel + + + Name + Nombre + + + + Branch + Rama + + + + Last modified + Última modificación + + + + Size + Tamaño + + + + Commit + Versión + + + + File + Archivo + + + + RemoteModel + + + Name + Nombre + + + + Last modified + Última modificación + + + + Size + Tamaño + + + + Commit + Versión + + + + Size: + Tamaño: + + + + Last Modified: + Última modificación: + + + + Licence: + Licencia: + + + + Default Branch: + Rama por defecto: + + + + RemoteNetwork + + + Choose a location to save the file + Seleccione una ubicación para guardar el archivo + + + + Error opening remote file at %1. +%2 + Error abriendo el archivo remoto en %1. +%2 + + + + Error: Invalid client certificate specified. + Error: El certificado del cliente es inválido. + + + + Please enter the passphrase for this client certificate in order to authenticate. + Por favor, introduzca la frase de contraseña de este certificado de cliente para autenticarse. + + + + Cancel + Cancelar + + + + Uploading remote database to +%1 + Subiendo base de datos remota a +%1 + + + + Downloading remote database from +%1 + Descargando base de datos remota desde +%1 + + + + Error: Cannot open the file for sending. + Error: No se puede abrir el archivo para enviar. + + + + RemotePushDialog + + + Push database + Remitir base de datos + + + + Database na&me to push to + No&mbre de la base de datos de destino + + + + Commit message + Mensaje de versión + + + + Database licence + Licencia de la base de datos + + + + Public + Pública + + + + Branch + Rama + + + + Force push + Forzar remisión + + + + Username + Nombre de usuario + + + + Database will be public. Everyone has read access to it. + La base de datos será pública. Todo el mundo podrá leerla. + + + + Database will be private. Only you have access to it. + La base de datos será privada. Sólo usted tendrá acceso. + + + + Use with care. This can cause remote commits to be deleted. + Usar con cuidado. Esto puede provocar borrados de versiones remotas. + + + + RunSql + + + Execution aborted by user + Ejecución abortada por el usuario + + + + , %1 rows affected + , %1 filas afectadas + + + + query executed successfully. Took %1ms%2 + consulta ejecutada con éxito. Tardó %1ms%2 + + + + executing query + ejecutando consulta + + + + SelectItemsPopup + + + A&vailable + &Disponible + + + + Sele&cted + &Seleccionado + + + + SqlExecutionArea + + + Form + Formulario + + + + Find previous match [Shift+F3] + Buscar la siguiente ocurrencia [Shift+F3] + + + + Find previous match with wrapping + Buscar la siguiente ocurrencia + + + + Shift+F3 + + + + + The found pattern must be a whole word + El patrón de búsqueda debe ser una palabra completa + + + + Whole Words + Palabras completas + + + + Text pattern to find considering the checks in this frame + El patrón de texto buscado considerando las opciones de este marco + + + + Find in editor + Buscar en el editor + + + + The found pattern must match in letter case + El patrón de búsqueda debe coincidir en mayúsculas y minúsculas + + + + Case Sensitive + Distinguir mayús./minús. + + + + Find next match [Enter, F3] + Buscar la siguiente ocurrencia [Enter, F3] + + + + Find next match with wrapping + Encontrar la siguiente ocurrencia volviendo al principio si es necesario + + + + F3 + + + + + Interpret search pattern as a regular expression + Interpretar el patrón de búsqueda como una expresión regular + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Si se activa, el patrón de búsqueda se interpreta como una expresión regular UNIX. Véase <a href="https://es.wikipedia.org/wiki/Expresi%C3%B3n_regular">«Expresión regular» en Wikipedia</a>.</p></body></html> + + + + Regular Expression + Expresión regular + + + + + Close Find Bar + Cerrar la barra de búsqueda + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>Resultados de las útimas sentencias ejecutadas.</p><p>Puede que prefiera colapsar este panel y en su lugar usar el <span style=" font-style:italic;">Registro SQL</span> con selección de <span style=" font-style:italic;">Usuario</span>.</p></body></html> + + + + Results of the last executed statements + Resultados de las últimas sentencias ejecutadas + + + + This field shows the results and status codes of the last executed statements. + Este campo muestra los resultados y códigos de estado de las últimas sentencias ejecutadas. + + + + Ctrl+PgUp + + + + + Ctrl+PgDown + + + + + Couldn't read file "%1": %2. + No se pudo leer el archivo "%1": %2. + + + + + Couldn't save file: %1. + No se pudo guardar el archivo: %1. + + + + Your changes will be lost when reloading it! + ¡Los cambios se perderán al recargarlo! + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + El archivo "%1" ha sido modificado por otro programa. ¿Quiere recargarlo?%2 + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + Responda "Sí a todo" para recargar el archivo sin pedir confirmación ante cualquier actualizacion externa. + + + + Answer "No to All" to ignore any external update without further prompting. + Responda "No a todo" para ignorar cualquier actualizacion externa sin antes pedir confirmación. + + + + Modifying and saving the file will restore prompting. + Modificando y guardando el archivo se restaurarán los avisos de petición de confirmacións. + + + + SqlTextEdit + + + Ctrl+/ + + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) La función abs(X) devuelve el valor absoluto del argumento numérico X. + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () La función changes() devuelve el número de líneas de la base de datos que se modificaron, insertaron o borraron por la consulta INSERT, DELETE, o UPDATE más reciente. + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) La función char(X1,X2,...,XN) devuelve una cadena compuesta por caracteres que tienen el valor numérico del código de punto unicode los enteros X1 hasta XN, respectivamente. + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) La función coalesce() devuelve una copia de su primer argumento no nulo, o NULL si todos los argumentos son NULL + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) La función glob(X,Y) es equivalente a la expresión "Y GLOB X". + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) La función ifnull() devuelve una copia de su primer argumento no nulo, o NULL si ambos argumentos son NULL. + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) La función instr(X,Y) busca la primera coincidencia de la cadena Y en la cadena X y devuelve el número de caracteres precedentes más 1, ó 0 si Y no se encuentra en X. + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) La función hex() interpreta su argumento como un BLOB y devuelve una cadena que es el equivalente codificado en hexadecimal en mayúsculas del contenido del BLOB. + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) La función iif(X,Y,Z) devuelve el valor Y si X es verdadero, y Z en caso contrario. + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () La función last_insert_rowid() devuelve el ROWID del la última línea insertada desde la conexión de la base de datos que invocó la función. + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) La función length(X) devuelve el número de caracteres (no bytes) en X anteriores al primer carácter NUL. + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) La función like() se usa para implementar la expresión "Y LIKE X". + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) La función like() se usa para implementar la expresión "Y LIKE X ESCAPE Z". + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) La función load_extension(X) carga extensiones SQLite del archivo de la biblioteca compartida llamada X usando el punto de entrada Y. +El uso de esta función tiene que ser autorizado desde las Preferencias. + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) La función load_extension(X,Y) carga extensiones SQLite del archivo de la biblioteca compartida llamado X usando el punto de entrada Y. +El uso de esta función tiene que ser autorizado desde las Preferencias. + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) La función lower(X) devuelve una copia de la cadena X con todos los caracteres ASCII convertidos a minúsculas. + + + + (X) ltrim(X) removes spaces from the left side of X. + (X) La función ltrim(X) quita los espacios a la izquierda de X. + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) La función ltrim(X,Y) devuelve una cadena formada quitando todos los caracteres que aparecen en Y de la izquierda de X. + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) La función multi-argumento max() devuelve el argumento con el valor máximo, o NULL si cualquier argumento es NULL. + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) La función multi-argumento max() devuelve el argumento con el valor mínimo. + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) La función nullif(X,Y) devuelve su primer argumento si los argumentos son diferentes y NULL si los argumentos son el mismo. + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) La función SQL printf(FORMAT,...) funciona como la función de lenguaje C sqlite3_mprintf() y la función printf() de la biblioteca C estándar. + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) La función quote(X) devuelve el texto de un literal SQL, que es el valor de su argumento, apropiado para la inclusión en una sentencia SQL. + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () La función random() devuelve un entero pseudo-aleatorio entre -9223372036854775808 y +9223372036854775807. + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) La función randomblob(N) devuelve un BLOB de N bytes que contiene bytes pseudo-aleatorios. + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) La función replace(X,Y,Z) devuelve una cadena formada substituyendo en la cadena Z cada coincidencia con la subcadena Y por la subcadena X. + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) La función round(X) devuelve un valor en coma flotante X redondeado a cero dígitos a la derecha de la coma decimal. + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) La función round(X,Y) devuelve un valor en coma flotante X redondeado a Y dígitos a la derecha de la coma decimal. + + + + (X) rtrim(X) removes spaces from the right side of X. + (X) La función rtrim(X) quita los espacios a la derecha de X. + + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) La función rtrim(X,Y) devuelve una cadena formada quitando todos los caracteres que aparecen en Y de la derecha de X. + + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) La función soundex(X) devuelve una cadena que es la codificación soundex de la cadena X. + + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) La función substr(X,Y) devuelve una subcadena con todos los caracteres de la cadena X desde el Y-ésimo hasta el último. + + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) La función substr(X,Y,Z) devuelve una subcadena de la cadena X desde el Y-ésimo carácter y que es Z caracteres de largo. + + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () La función total_changes() devuelve el número de cambios en las líneas causadas por sentencias INSERT, UPDATE o DELETE desde que la conexión con la base de datos actual se abrió. + + + + (X) trim(X) removes spaces from both ends of X. + (X) La función trim(X) quita los espacios de ambos lados de X. + + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) La función trim(X,Y) devuelve una cadena formada quitando todos los caracteres que aparecen en Y de ambos lados de X. + + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) La función typeof(X) devuelve una cadena que indica el tipo de datos de la expresión X. + + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) La función unicode(X) devuelve el valor numérico del código de punto unicode correspondiente al primer carácter de la cadena X. + + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) La función upper(X) devuelve una copia de la cadena X con todos los caracteres ASCII convertidos a mayúsculas. + + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) La función zeroblob(N) devuelve un BLOB consistente en N bytes de 0x00. + + + + + + + (timestring,modifier,modifier,...) + (timestring,modificador,modificador,...) + + + + (format,timestring,modifier,modifier,...) + (formato,timestring,modificador,modificador,...) + + + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) La función avg() devuelve el valor medio de todos los valores no nulos del grupo X. + + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) La función count(X) devuelve el conteo del número de veces que X no es nulo en un grupo. + + + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) La función group_concat() devuelve una cadena que es la concatenación de todos los valores no nulos X. + + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) La función group_concat() devuelve una cadena que es la concatenación de todos los valores no nulos X, usando el parámetro Y como separador entre las instancias de X. + + + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) La función agregada max() devuelve el máximo valor de entre todos los valores en el grupo. + + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) La función agregada min() devuelve el mínimo valor no NULO de entre todos los valores en el grupo. + + + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) Las funciones agregadas sum() y total() devuelven la suma de todos los valores no NULOS en el grupo. + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () El número de fila dentro de la partición actual. Las filas se numeran empezando por 1 en el orden definido por la cláusula ORDER BY en la ventana de definición, o sino en un orden arbitrario. + + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () El row_number() del primer par (igual) en cada grupo - el rango de la fila actual con huecos. Si no hay una cláusula ORDER BY, entonces todas las filas son consideradas pares y esta función siempre devuelve 1. + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () El número del grupo de pares de la fila actual dentro de su partición - el rango de la fila actual sin huecos. Las particiones se numeran empezando por 1 en el orden definido por la cláusula ORDER BY en la ventana de definición. Si no hay una cláusula ORDER BY, entonces todas las filas son consideradas pares y esta función siempre devuelve 1. + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () A pesar del nombre, esta función siempre devuelve un valor entre 0.0 y 1.0 igual a (rank - 1)/(partition-rows - 1), donde rank es el valor devuelto por la función de ventana incorporada rank() y partition-rows es el número total de filas en la partición. Si la partición contiene sólo una fila, esta función devuelve 0.0. + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () La distribución acumulada. Calculada como row-number/partition-rows, donde row-number es el valor devuelto por row_number() para el último par (igual) en el grupo y partition-rows el número de filas en la partición. + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) El argumento N es tratado como un entero. Esta función divide la partición en N grupos tan equitativamente como sea posible y asigna un entero entre 1 y N a cada grupo, en el orden definido por la cláusula ORDER BY, o sino en un orden arbitrario. Si es necesario, los grupos mayores aparecen primero. Esta función devuelve un valor entero asignado al grupo del que la fila actual es parte. + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) Devuelve el resultado de evaluar la expresión expr con la fila anterior en la partición. Si no hay fila anterior (porque la fila actual es la primera) devuelve NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr,offset) Si se proporciona un offset, éste debe ser un entero no negativo. En este caso el valor devuelto es el resultado de evaluar expr con la fila offset veces anterior a la fila actual dentro de la partición. Si offset es 0, entonces expr se evalua con la fila actual. Si no hay fila offset veces anterior devuelve NULL. + + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,offset,default) Si también se proporciona un default, entonces éste es devuelto en lugar de NULL si no existe la fila identificada por offet. + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) Devuelve el resultado de evaluar la expresión expr con la siguiente fila en la partición. Si no hay fila siguiente (porque la fila actual es la última) devuelve NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,offset) Si se proporciona un offset, éste debe ser un entero no negativo. En este caso el valor devuelto es el resultado de evaluar expr con la fila offset veces posterior a la fila actual dentro de la partición. Si offset es 0, entonces expr se evalua con la fila actual. Si no hay fila offset veces siguiente devuelve NULL. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) Esta función de ventana incorporada calcula el marco de la ventana para cada fila de la misma forma que una función agregada de ventana. Devuelve el valor de expr evaluada con la primera fila en el marco de la ventana para cada fila. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) Esta función de ventana incorporada calcula el marco de la ventana para cada fila de la misma forma que una función agregada de ventana. Devuelve el valor de expr evaluada con la última fila en el marco de la ventana para cada fila. + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr,N) Esta función de ventana incorporada calcula el marco de la ventana para cada fila de la misma forma que una función agregada de ventana. Devuelve el valor de expr evaluada con la fila N del marco de la ventana. Las columnas se numeran dentro del marco de la ventana empezando por 1 en el orden definico por la cláusula ORDER BY, o sino en orden arbitrario. Si no hay fila N-ava en la partición, entonces devuelve NULL. + + + + (X) Return the arccosine of X. The result is in radians. + (X) Devuelve el arcocoseno de X. El resultado es en radianes. + + + + (X) Return the hyperbolic arccosine of X. + (X) Devuelve el arcocoseno hiperbólico de X. + + + + (X) Return the arcsine of X. The result is in radians. + (X) Devuelve el arcoseno de X. El resultado es en radianes. + + + + (X) Return the hyperbolic arcsine of X. + (X) Devuelve el arcoseno hiperbólico de X. + + + + (X) Return the arctangent of X. The result is in radians. + (X) Devuelve la arcotangente de X. El resultado es en radianes. + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + (X,Y) Devuelve la arcotangente de Y/X. El resultado es en radianes. El resultado se coloca en el cuadrante correcto en función de los signos de X e Y. + + + + (X) Return the hyperbolic arctangent of X. + (X) Devuelve la arcotangente hiperbólica de X. + + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + (X) Devuelve el valor del primer entero representable mayor o igual que X. Para números positivos esta función redondea en sentido contrario a 0. Para números negativos esta función redondea hacia 0. + + + + (X) Return the cosine of X. X is in radians. + (X) Devuelve el coseno de X. X es en radianes. + + + + (X) Return the hyperbolic cosine of X. + (X) Devuelve el coseno hiperbólico de X. + + + + (X) Convert value X from radians into degrees. + (X) Convierte el valor de X de radianes a grados sexagesimales. + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + (X) Calcula e (número de Euler, aproximadamente 2.71828182845905) elevado a X. + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + (X) Devuelve el valor del primer entero representable menor o igual que X. Para números positivos esta función redondea hacia 0. Para números negativos esta función redondea en sentido contrario a 0. + + + + (X) Return the natural logarithm of X. + (X) Devuelve el logaritmo natural de X. + + + + (B,X) Return the base-B logarithm of X. + (B,X) Devuelve el logaritmo en base B de X. + + + + + (X) Return the base-10 logarithm for X. + (X) Devuelve el logaritmo en base 10 de X. + + + + (X) Return the logarithm base-2 for the number X. + (X) Devuelve el logaritmo en base 2 de X. + + + + (X,Y) Return the remainder after dividing X by Y. + (X,Y) Devuelve el resto de dividir X entre Y. + + + + () Return an approximation for Ï€. + () Devuelve una aproximación para Ï€. + + + + + (X,Y) Compute X raised to the power Y. + (X,Y) Devuelve X elevado a Y. + + + + (X) Convert X from degrees into radians. + (X) Convierte X de grados sexagesimales a radianes + + + + (X) Return the sine of X. X is in radians. + (X) Devuelve el seno de X. X es en radianes. + + + + (X) Return the hyperbolic sine of X. + (X) Devuelve el seno hiperbólico de X. + + + + (X) Return the square root of X. NULL is returned if X is negative. + (X) Devuelve la raiz cuadrada de X. Devuelve NULL si X es negativo. + + + + (X) Return the tangent of X. X is in radians. + (X) Devuelve la tangente de X. X es en radianes. + + + + (X) Return the hyperbolic tangent of X. + (X) Devuelve la tangente hiperbólica de X. + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + (X) Devuelve el entero representable entre X y 0 (incluído) que está más lejos de 0. En otras palabras, devuelve la parte entera de X, redondeando hacia 0. + + + + SqliteTableModel + + + reading rows + leyendo filas + + + + loading... + cargando... + + + + References %1(%2) +Hold %3Shift and click to jump there + Referencia %1(%2) +Mantenga pulsado %3Mayús. y haga clic para ir ahí + + + + Error changing data: +%1 + Error modificando datos: +%1 + + + + retrieving list of columns + obteniendo lista de columnas + + + + Fetching data... + Obteniendo datos... + + + + + Cancel + Cancelar + + + + TableBrowser + + + Browse Data + Hoja de datos + + + + &Table: + &Tabla: + + + + Select a table to browse data + Seleccione una tabla para ver sus datos + + + + Use this list to select a table to be displayed in the database view + Use esta lista para seleccionar la tabla a mostrar en la vista de la base de datos + + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + Este es el visor de la tabla de la base de datos. Puede realizar lo siguiente: + - Escribir y editar valores. + - Doble-clic en cualquier registro para editar su contenido en la ventana del editor de celdas. + - Alt+Supr para borrar el contenido de la celda a NULL. + - Ctrl+" para duplicar el registro actual. + - Ctrl+' para copiar el valor de la celda de arriba. + - Las operaciones de copiar y pegar usuales. + + + + Text pattern to find considering the checks in this frame + El patrón de texto a buscar según las opciones seleccionadas en este marco + + + + Find in table + Buscar en la tabla + + + + Find previous match [Shift+F3] + Buscar la anterior ocurrencia [Mayús.+F3] + + + + Find previous match with wrapping + Buscar la anterior ocurrencia volviendo al final si es necesario + + + + Shift+F3 + + + + + Find next match [Enter, F3] + Buscar la siguiente ocurrencia [Intro, F3] + + + + Find next match with wrapping + Buscar la siguiente ocurrencia volviendo al principio si es necesario + + + + F3 + + + + + The found pattern must match in letter case + El patrón de búsqueda tiene que coincidir en mayúsculas y minúsculas + + + + Case Sensitive + Distinguir mayús./minús. + + + + The found pattern must be a whole word + El patrón de búsqueda tiene que ser una palabra completa + + + + Whole Cell + Toda la celda + + + + Interpret search pattern as a regular expression + Interpretar el patrón de búsqueda como una expresión regular + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Si se marca, el patrón de búsqueda se interpreta como una expresión regular UNIX. Véase <a href="https://es.wikipedia.org/wiki/Expresi%C3%B3n_regular">«Expresión regular» en Wikipedia</a>.</p></body></html> + + + + Regular Expression + Expresión regular + + + + + Close Find Bar + Cerrar la barra de búsqueda + + + + Text to replace with + Texto con el que reemplazar + + + + Replace with + Reemplazar con + + + + Replace next match + Reemplazar la siguiente coincidencia + + + + + Replace + Reemplazar + + + + Replace all matches + Reemplazar todas las coincidencias + + + + Replace all + Reemplazar todo + + + + Export to &JSON + Exportar a &JSON + + + + + Export the filtered data to JSON + Exportar los datos filtrados a JSON + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + Este botón exporta los datos de la tabla que está navegando tal y como se muestran (tras aplicar filtros, formatos de visualización y orden de las columnas) como un archivo JSON. + + + + Copy column name + Copiar el nombre de la columna + + + + Copy the database table column name to your clipboard + Copia el nombre de la columna de la base de datos al portapapeles + + + + New Data Browser + Nueva hoja de datos + + + + + Add a new docked Data Browser + Añadir una nueva hoja de datos anclada + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + Este botón añade una nueva hoja de datos anclada, que se puede desanclar y mostrar una presentación diferente. + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>Desplazarse hasta el principio</p></body></html> + + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>Pulsando este botón se mueve hasta el principio en la vista de tabla de arriba.</p></body></html> + + + + |< + |< + + + + Scroll one page upwards + Retroceder una página + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>Pulsando este botón se retrocede una página de registros en la vista de tabla de arriba.</p></body></html> + + + + < + < + + + + 0 - 0 of 0 + 0 - 0 de 0 + + + + Scroll one page downwards + Avanzar una página + + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>Pulsando este botón se avanza una página de registros en la vista de tabla de arriba.</p></body></html> + + + + > + > + + + + Scroll to the end + Desplazarse hasta el final + + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>Pulsando este botón se mueve al final de la vista de tabla de arriba.</p></body></html> + + + + >| + >| + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>Pulse aquí para saltar al registro especificado</p></body></html> + + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>Este botón se usa para moverse al número de registro especificado en la casilla Ir a.</p></body></html> + + + + Go to: + Ir a: + + + + Enter record number to browse + Introduzca el número de registro al que navegar + + + + Type a record number in this area and click the Go to: button to display the record in the database view + Escriba un número de registro en esta casilla y haga clic en el botón «Ir a:» para mostrar el registro en la vista de la base de datos + + + + 1 + 1 - - Results of the last executed statements - Resultados de los últimos comandos ejecutados + + Show rowid column + Mostrar la columna rowid - - This field shows the results and status codes of the last executed statements. - Este campo muestra los resultados y códigos de estado de los últimos comandos ejecutados. + + Toggle the visibility of the rowid column + Cambia la visibilidad de la columna rowid + + + + Unlock view editing + Desbloquear edición de vistas + + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + Esto desbloquea la vista actual para edición. Aunque para la edición se necesitarán los disparadores adecuados. + + + + Edit display format + Editar el formato de presentación + + + + Edit the display format of the data in this column + Editar el formato de presentación de los datos en esta columna + + + + + New Record + Nuevo registro + + + + + Insert a new record in the current table + Inserta un nuevo registro en la tabla actual + + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>Este botón crea un nuevo registro en la base de datos. Mantenga pulsado el botón del ratón para abrir un menú emergente con varias opciones:</p><ul><li><span style=" font-weight:600;">Nuevo Registro</span>: inserta en la base de datos un nuevo registro con valores por defecto.</li><li><span style=" font-weight:600;">Introduce Valores...</span>: abre un diálogo para introducir valores antes de insertarlos en la base de datos. Esto permite introducir valores que cumplan con las restricciones. Este diálogo también se abre si la opción de <span style=" font-weight:600;">Nuevo Registro</span> falla debido a esas restricciones.</li></ul></body></html> + + + + + Delete Record + Borrar registro + + + + Delete the current record + Borra el registro actual + + + + + This button deletes the record or records currently selected in the table + Este botón borra el registro seleccionado (o los registros seleccionados) actualmente en la base de datos + + + + + Insert new record using default values in browsed table + Inserta un nuevo registro usando valores por defecto en la tabla visualizada + + + + Insert Values... + Introducir valores... + + + + + Open a dialog for inserting values in a new record + Abre un diálogo para introducir valores en un nuevo registro - + Export to &CSV Exportar a &CSV - + + + Export the filtered data to CSV + Exportar los datos filtrados a CSV + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + Este botón exporta los datos de la tabla mostrada tal como se presentan (después de filtros, formatos de presentación y columna de orden) como un archivo CSV. + + + Save as &view Guardar como &vista - - Save as view - Guardar como vista + + + Save the current filter, sort column and display formats as a view + Guardar el filtro actual, la columna de orden y los formatos de presentación como una vista - - Please specify the view name - Por favor, especifique el nombre de la vista + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + Este botón guarda los ajustes actuales de la tabla visualizada (filtros, formatos de presentación y la columna de orden) como una vista SQL que más tarde puede visualizar o usar en sentencias SQL. - - There is already an object with that name. Please choose a different name. - Ya hay un objeto con ese nombre. Por favor, elija un nombre diferente. + + Save Table As... + Guardar tabla como... - - View successfully created. - Vista creada satisfactoriamente. + + + Save the table as currently displayed + Guarda la tabla tal como se presenta - - Error creating view: %1 - Error creando la vista: %1 + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>Este menú contextual provee las siguientes opciones que se aplican a la tabla actualmente visualizada y filtrada:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Exportar a CSV: esta opción exporta los datas de la tabla tal cual se presentan actualmente (después de filtros, formatos de presentación y columna de orden) a un archivo CSV.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Guardar como vista: esta opción guarda la configuración actual de la tabla visualizada (filtros, formatos de presentación y columna de orden) como una vista SQL que luego puede visualizar o usar en sentencias SQL.</li></ul></body></html> - - - SqlUiLexer - - (X) The abs(X) function returns the absolute value of the numeric argument X. - (X) La función abs(X) devuelve el valor absoluto del argumento numérico X. + + Hide column(s) + Ocultar columna(s) - - () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. - () La función changes() devuelve el número de líneas de la base de datos que se modificaron, insertaron o borraron por la consulta INSERT, DELETE, o UPDATE más reciente. + + Hide selected column(s) + Ocultar columna(s) seleccionada(s) - - (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. - (X1,X2,...) La función char(X1,X2,...,XN) devuelve una cadena compuesta por caracteres que tienen el valor numérico del código de punto unicode los enteros X1 hasta XN, respectivamente. + + Show all columns + Mostrar todas las columnas - - (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL - (X,Y,...) La función coalesce() devuelve una copia de su primer argumento no nulo, o NULL si todos los argumentos son NULL + + Show all columns that were hidden + Mostrar todas las columnas que están ocultas - - (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". - (X,Y) La función glob(X,Y) es equivalente a la expresión "Y GLOB X". + + + Set encoding + Definir codificación - - (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. - (X,Y) La función ifnull() devuelve una copia de su primer argumento no nulo, o NULL si ambos argumentos son NULL + + Change the encoding of the text in the table cells + Cambia la codificación del texto de las celdas de la tabla - - (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. - (X,Y) La función instr(X,Y) busca la primera coincidencia de la cadena Y en la cadena X y devuelve el número de caracteres precendentes más 1, ó 0 si Y no se encuentra en X. + + Set encoding for all tables + Definir la codificación para todas las tablas - - (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. - (X) La función hex() interpreta su argumento como un BLOB y devuelve una cadena que es el equivalente codificado en hexadecimal en mayúsculas del contenido del BLOB. + + Change the default encoding assumed for all tables in the database + Cambia la codificación por defecto para todas las tablas en la base de datos - - () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. - () La función last_insert_rowid() devuelve el ROWID del la última línea insertada desde la conexión de la base de datos que invocó la función. + + Clear Filters + Borrar Filtros - - (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. - (X) La función length(X) devuelve el número de caracteres (no bytes) en X anteriores al primer caracter NUL. + + Clear all filters + Borra todos los filtros - - (X,Y) The like() function is used to implement the "Y LIKE X" expression. - X,Y) La función like() se usa para implementar la expresión "Y LIKE X". + + + This button clears all the filters set in the header input fields for the currently browsed table. + Este botón elimina todos los filtros establecidos en la cabecera para la tabla mostrada actualmente. - - (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. - (X,Y,Z) La función like() se usa para implementar la expresión "Y LIKE X ESCAPE Z". + + Clear Sorting + Eliminar ordenación - - (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. - (X) La función load_extension(X) carga extensiones SQLite del archivo de la biblioteca compartida llamada X. + + Reset the order of rows to the default + Reinicia el orden de las filas al orden por defecto - - (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. - (X) La función load_extension(X) carga extensiones SQLite del archivo de la biblioteca compartida llamada X usando el punto de entrada Y. + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + Este botón elimina la ordenación de las columnas especificadas para la tabla mostrada actualmente y vuelve al orden por defecto. - - (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. - (X) La función lower(X) devuelve una copia de la cadena X con todos los caracteres ASCII convertidos a minúsculas. + + Print + Imprimir - - (X) ltrim(X) removes spaces from the left side of X. - (X) La función ltrim(X) quita los espacios a la izquierda de X. + + Print currently browsed table data + Imprime los datos de la tabla mostrada actualmente - - (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. - (X,Y) La función ltrim(X,Y) devuelve una cadena formada quitando todos los caracteres que aparecen en Y de la izquierda de X. + + Print currently browsed table data. Print selection if more than one cell is selected. + Imprime los datos de la tabla mostrada actualmente. Imprime la selección si se ha seleccionado más de una celda. - - (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. - (X,Y,...) La función multi-argumento max() devuelve el argumento con el valor máximo, o NULL si cualquier argumento es NULL. + + Ctrl+P + - - (X,Y,...) The multi-argument min() function returns the argument with the minimum value. - (X,Y,...) La función multi-argumento max() devuelve el argumento con el valor mínimo. + + Refresh + Refrescar - - (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. - (X,Y) La función nullif(X,Y) devuelve su primer argumento si los argumentos son diferentes y NULL si los argumentos son el mismo. + + Refresh the data in the selected table + Refresca los datos en la tabla seleccionada - - (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. - (FORMAT,...) La función SQL printf(FORMAT,...) funciona como la función de lenguaje C sqlite3_mprintf() y la función printf() de la biblioteca C estandar. + + This button refreshes the data in the currently selected table. + Este botón refresca los datos de la tabla seleccionada actualmente. - - (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. - (X) La función quote(X) devuelve el texto de un literal SQL, que es el valor de su argumento, apropiado para la inclusión en una consulta SQL. + + F5 + - - () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. - () La función random() devuelve un entero pseudo-aleatorio entre -9223372036854775808 y +9223372036854775807. + + Find in cells + Buscar en celdas - - (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. - (N) La función randomblob(N) devuelve un BLOB de N bytes que contiene bytes pseudo-aleatorios. + + Open the find tool bar which allows you to search for values in the table view below. + Abre la barra de búsqueda que permite buscar valores en la vista de la tabla de abajo. - - (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. - (X,Y,Z) La función replace(X,Y,Z) devuelve una cadena formada substituyendo en la cadena Z cada coincidencia con la subcadena Y por la subcadena X. + + Freeze columns + Congelar las columnas - - (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. - (X) La función round(X) devuelve un valor en coma flotante X redondeado a cero dígitos a la derecha de la coma decimal. + + Make all columns from the first column up to this column not move when scrolling horizontally + Hace que no se muevan las columnas, desde la primera hasta esta, cuando se hace scroll horizontal - - (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. - (X,Y) La función round(X,Y) devuelve un valor en coma flotante X redondeado a Y dígitos a la derecha de la coma decimal. + + + Bold + Negrita - - (X) rtrim(X) removes spaces from the right side of X. - (X) La función rtrim(X) quita los espacios a la derecha de X. + + Ctrl+B + - - (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. - (X,Y) La función rtrim(X,Y) devuelve una cadena formada quitando todos los caracteres que aparecen en Y de la derecha de X. + + + Italic + Cursiva - - (X) The soundex(X) function returns a string that is the soundex encoding of the string X. - (X) La función soundex(X) devuelve una cadena que es la codificación soundex de la cadena X. + + + Underline + Subrayado - - (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. - (X,Y) La función substr(X,Y) devuelve una subcadena con todos los caracteres de la cadena X desde el Y-ésimo hasta el último. + + Ctrl+U + - - (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. - (X,Y) La función substr(X,Y) devuelve una subcadena de la cadena X desde el Y-ésimo y que es Z caracteres de largo. + + + Align Right + Alineado derecha - - () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. - () La función total_changes() devuelve el número de cambios en las líneas causadas por consultas INSERT, UPDATE o DELETE desde que la conexión con la base de datos actual se abrió. + + + Align Left + Alineado izquierda - - (X) trim(X) removes spaces from both ends of X. - (X) La función trim(X) quita los espacios de ambos lados de X. + + + Center Horizontally + Centrado horizontal - - (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. - (X,Y) La función trim(X,Y) devuelve una cadena formada quitando todos los caracteres que aparecen en Y de ambos lados de X. + + + Justify + Justificar - - (X) The typeof(X) function returns a string that indicates the datatype of the expression X. - (X) La función typeof(X) devuelve una cadena que indica el tipo de datos de la expresión X. + + + Edit Conditional Formats... + Editar formatos condicionales... - - (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. - (X) La función unicode(X) devuelve el valor numérico del código de punto unicode correspondiente al primer caracter de la cadena X. + + Edit conditional formats for the current column + Edita formatos condicionales para la columna actual - - (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. - (X) La función upper(X) devuelve una copia de la cadena X con todos los caracteres ASCII convertidos a mayúsculas. + + Clear Format + Eliminar formato - - (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. - (N) La función zeroblob(N) devuelve un BLOB consistente en N bytes de 0x00. + + Clear All Formats + Eliminar todos los formatos - - - - - (timestring,modifier,modifier,...) - (timestring,modificador,modificador,...) + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + Elimina todo el formato de las celdas seleccionadas y los formatos condicionales de las columnas seleccionadas - - (format,timestring,modifier,modifier,...) - (formato,timestring,modificador,modificador,...) + + + Font Color + Color del texto - - (X) The avg() function returns the average value of all non-NULL X within a group. - (X) La función avg() devuelve el valor medio de todos los valores no nulos del grupo X. + + + Background Color + Color del fondo - - (X) The count(X) function returns a count of the number of times that X is not NULL in a group. - (X) La función count(X) devuelve el conteo del número de veces que X no es nulo en un grupo. + + Toggle Format Toolbar + Conmutar barra de formato - - (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. - (X) La función group_concat() devuelve una cadena que es la concatenación de todos los valores no nulos X. + + Show/hide format toolbar + Mostrar/ocultar la barra de formato - - (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. - (X,Y) La función group_concat() devuelve una cadena que es la concatenación de todos los valores no nulos X, usando el parámetro Y como separador entre las instancias de X. + + + This button shows or hides the formatting toolbar of the Data Browser + Este botón muestra u oculta la barra de formato de la Hoja de Datos - - (X) The max() aggregate function returns the maximum value of all values in the group. - (X) La función max() devuelve el máximo valor de entre todos los valores en el grupo. + + Select column + Seleccionar columna - - (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. - (X) La función min() devuelve el mínimo valor no NULO de entre todos los valores en el grupo. + + Ctrl+Space + - - - (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. - (X) Las funciones sum() y total() devuelven la suma de todos los valores no NULOS en el grupo. + + Replace text in cells + Reemplazar texto en las celdas - - - SqliteTableModel - - Error changing data: + + Filter in any column + Filtrar en cualquier columna + + + + Ctrl+R + + + + + %n row(s) + + %n fila + %n filas + + + + + , %n column(s) + + , %n columna + , %n columnas + + + + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . Suma: %1; Media: %2; Mín: %3; Máx: %4 + + + + Conditional formats for "%1" + Formatos condicionales para "%1" + + + + determining row count... + determinando nº de filas... + + + + %L1 - %L2 of >= %L3 + %L1 - %L2 de >= %L3 + + + + %L1 - %L2 of %L3 + %L1 - %L2 de %L3 + + + + (clipped at %L1 rows) + (truncado a %L1 filas) + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + Introduzca una clave pseudo-primaria para activar la edición en esta vista. Esta debería ser el nombre de una columna única en la vista. + + + + Delete Records + Borrar registros + + + + Duplicate records + Duplicar registros + + + + Duplicate record + Duplicar registro + + + + Ctrl+" + + + + + Adjust rows to contents + Ajustar las filas al contenido + + + + Error deleting record: %1 - Error modificando datos: + Error borrando registro: %1 + + + Please select a record first + Por favor, antes seleccione un registro + + + + Please choose a new encoding for all tables. + Por favor, elija una nueva codificación para todas las tablas. + + + + Please choose a new encoding for this table. + Por favor, elija una nueva codificación para esta tabla. + + + + %1 +Leave the field empty for using the database encoding. + %1 +Deje este campo vacío para usar la codificación de la base de datos. + + + + This encoding is either not valid or not supported. + Esta codificación no es válida o no está soportada. + + + + %1 replacement(s) made. + Se realizaron %1 sustitucion(es). + + + + TableBrowserDock + + + New Data Browser + Nueva hoja de datos + + + + Rename Data Browser + Renombrar hoja de datos + + + + Close Data Browser + Cerrar hoja de datos + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + Pone un nuevo nombre a la hoja de datos. Use el carácter «&&» para que el carácter siguiente se use como atajo de teclado. + VacuumDialog Compact Database - Compactar Base de Datos + Compactar base de datos - Warning: Compacting the database will commit all changes you made. - Cuidado: Al compactar la base de datos se confirmarán todos los cambios hechos. + Warning: Compacting the database will commit all of your changes. + Aviso: compactar la base de datos provocará la consolidación de todos sus cambios. - Please select the objects to compact: - Por favor, seleccione los objetos a compactar: + Please select the databases to co&mpact: + Seleccione las bases de datos que desea co&mpactar: diff --git a/src/translations/sqlb_fa.ts b/src/translations/sqlb_fa.ts new file mode 100644 index 000000000..a65e3cdd4 --- /dev/null +++ b/src/translations/sqlb_fa.ts @@ -0,0 +1,7853 @@ + + + + + AboutDialog + + + About DB Browser for SQLite + + + + + Version + + + + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + + + + + AddRecordDialog + + + Add New Record + + + + + Enter values for the new record considering constraints. Fields in bold are mandatory. + + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + + + + + Name + + + + + Type + + + + + Value + + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + + + + + Auto-increment + + + + + + Unique constraint + + + + + + Check constraint: %1 + + + + + + Foreign key: %1 + + + + + + Default value: %1 + + + + + + Error adding record. Message from database engine: + +%1 + + + + + Are you sure you want to restore all the entered values to their defaults? + + + + + Application + + + Possible command line arguments: + + + + + The user settings file location is replaced with the argument value instead of the environment variable value. + + + + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + + + + + + The file %1 does not exist + + + + + Usage + + + + + options + + + + + + database + + + + + + project + + + + + + csv-file + + + + + Show command line options + + + + + Exit application after running scripts + + + + + + file + + + + + Execute this SQL file after opening the DB + + + + + Import this CSV file into the passed DB or into a new DB + + + + + table + + + + + Browse this table, or use it as target of a data import + + + + + Open database in read-only mode + + + + + settings_file + + + + + Run application based on this settings file + + + + + + group + + + + + + settings + + + + + + value + + + + + Run application with this setting temporarily set to value + + + + + Run application saving this value for this setting + + + + + Display the current version + + + + + Open this SQLite database + + + + + Open this project file (*.sqbpro) + + + + + Import this CSV file into an in-memory database + + + + + + + The %1 option requires an argument + + + + + The -S/--settings option requires an argument. The option is ignored. + + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + + + + + SQLite Version + + + + + SQLCipher Version %1 (based on SQLite %2) + + + + + DB Browser for SQLite Version %1. + + + + + Last commit hash when built: %1 + + + + + Built for %1, running on %2 + + + + + Qt Version %1 + + + + + Invalid option/non-existent file: %1 + + + + + CipherDialog + + + SQLCipher encryption + + + + + &Password + + + + + &Reenter password + + + + + Passphrase + + + + + Raw key + + + + + Encr&yption settings + + + + + SQLCipher &3 defaults + + + + + SQLCipher &4 defaults + + + + + Custo&m + + + + + Page si&ze + + + + + &KDF iterations + + + + + HMAC algorithm + + + + + KDF algorithm + + + + + Plaintext Header Size + + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + + + + + ColumnDisplayFormatDialog + + + Choose display format + + + + + Display format + + + + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + + + + + Default + + + + + Decimal number + + + + + Exponent notation + + + + + Hex blob + + + + + Hex number + + + + + Octal number + + + + + Round number + + + + + Apple NSDate to date + + + + + Java epoch (milliseconds) to date + + + + + .NET DateTime.Ticks to date + + + + + Julian day to date + + + + + Unix epoch to date + + + + + Unix epoch to local time + + + + + WebKit / Chromium epoch to date + + + + + WebKit / Chromium epoch to local time + + + + + Windows DATE to date + + + + + Date as dd/mm/yyyy + + + + + Lower case + + + + + Upper case + + + + + Binary GUID to text + + + + + SpatiaLite Geometry to SVG + + + + + Custom + + + + + Custom display format must contain a function call applied to %1 + + + + + Error in custom display format. Message from database engine: + +%1 + + + + + Custom display format must return only one column but it returned %1. + + + + + CondFormatManager + + + Conditional Format Manager + + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + + + + + Add new conditional format + + + + + &Add + + + + + Remove selected conditional format + + + + + &Remove + + + + + Move selected conditional format up + + + + + Move &up + + + + + Move selected conditional format down + + + + + Move &down + + + + + Foreground + + + + + Text color + + + + + Background + + + + + Background color + + + + + Font + + + + + Size + + + + + Bold + + + + + Italic + + + + + Underline + + + + + Alignment + + + + + Condition + + + + + + Click to select color + + + + + Are you sure you want to clear all the conditional formats of this field? + + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + + + + + Invalid file format + + + + + Do you really want to close this temporary database? All data will be lost. + + + + + Do you want to save the changes made to the database file %1? + + + + + Database didn't close correctly, probably still busy + + + + + Cannot open destination file: '%1' + + + + + + Cannot backup to file: '%1'. Message: %2 + + + + + The database is currently busy: + + + + + Do you want to abort that other operation? + + + + + Exporting database to SQL file... + + + + + + Cancel + + + + + + No database file opened + + + + + Executing SQL... + + + + + Action cancelled. + + + + + + Error in statement #%1: %2. +Aborting execution%3. + + + + + + and rolling back + + + + + didn't receive any output from %1 + + + + + could not execute command: %1 + + + + + Cannot delete this object + + + + + Cannot set data on this object + + + + + + A table with the name '%1' already exists in schema '%2'. + + + + + No table with name '%1' exists in schema '%2'. + + + + + + Cannot find column %1. + + + + + Creating savepoint failed. DB says: %1 + + + + + Renaming the column failed. DB says: +%1 + + + + + + Releasing savepoint failed. DB says: %1 + + + + + Creating new table failed. DB says: %1 + + + + + Copying data to new table failed. DB says: +%1 + + + + + Deleting old table failed. DB says: %1 + + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + + + + + could not get list of db objects: %1 + + + + + could not get list of databases: %1 + + + + + Error setting pragma %1 to %2: %3 + + + + + File not found. + + + + + Error loading extension: %1 + + + + + Error loading built-in extension: %1 + + + + + could not get column information + + + + + DbStructureModel + + + Name + + + + + Object + + + + + Type + + + + + Schema + + + + + Database + + + + + Browsables + + + + + All + + + + + Temporary + + + + + Tables (%1) + + + + + Indices (%1) + + + + + Views (%1) + + + + + Triggers (%1) + + + + + EditDialog + + + Edit database cell + + + + + Mode: + + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + + + + + Text + + + + + RTL Text + + + + + Binary + + + + + + Image + + + + + JSON + + + + + XML + + + + + Evaluation + + + + + + Automatically adjust the editor mode to the loaded data type + + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + + + + + Auto-switch + + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + + + + + Identification of the cell currently in the editor + + + + + Type and size of data currently in table + + + + + Open preview dialog for printing the data currently stored in the cell + + + + + Auto-format: pretty print on loading, compact on saving. + + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + + + + + Word Wrap + + + + + Wrap lines on word boundaries + + + + + + Open in default application or browser + + + + + Open in application + + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + + + + + Save file reference... + + + + + Save reference to file + + + + + + Open in external application + + + + + Autoformat + + + + + &Export... + + + + + + &Import... + + + + + + Import from file + + + + + + Opens a file dialog used to import any kind of data to this database cell. + + + + + Export to file + + + + + Opens a file dialog used to export the contents of this database cell to a file. + + + + + Erases the contents of the cell + + + + + Set as &NULL + + + + + This area displays information about the data present in this database cell + + + + + Apply data to cell + + + + + This button saves the changes performed in the cell editor to the database cell. + + + + + Apply + + + + + Print... + + + + + Ctrl+P + + + + + Open preview dialog for printing displayed text + + + + + Copy Hex and ASCII + + + + + Copy selected hexadecimal and ASCII columns to the clipboard + + + + + Ctrl+Shift+C + + + + + + Image data can't be viewed in this mode. + + + + + + Try switching to Image or Binary mode. + + + + + + Binary data can't be viewed in this mode. + + + + + + Try switching to Binary mode. + + + + + + Image files (%1) + + + + + Binary files (*.bin) + + + + + Choose a file to import + + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + + + + + Unsaved data in the cell editor + + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + + + + + Editing row=%1, column=%2 + + + + + No cell active. + + + + + %1 Image + + + + + Choose a filename to export data + + + + + Invalid data for this mode + + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + + + + + + Type: NULL; Size: 0 bytes + + + + + + Type: Text / Numeric; Size: %n character(s) + + + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + + + + + Type: Valid JSON; Size: %n character(s) + + + + + + + Type: Binary; Size: %n byte(s) + + + + + + + Couldn't save file: %1. + + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + + + + + EditIndexDialog + + + Edit Index Schema + + + + + &Name + + + + + &Table + + + + + &Unique + + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + + + + + Partial inde&x clause + + + + + Colu&mns + + + + + Table column + + + + + Type + + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + + + + + Index column + + + + + Order + + + + + Deleting the old index failed: +%1 + + + + + Creating the index failed: +%1 + + + + + EditTableDialog + + + Edit table definition + + + + + Table + + + + + Advanced + + + + + Without Rowid + + + + + Fields + + + + + + + + Name + + + + + + Type + + + + + NN + + + + + Not null + + + + + PK + + + + + Database sche&ma + + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + + + + + On Conflict + + + + + Strict + + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + + + + + + + Add + + + + + + + Remove + + + + + Move to top + + + + + Move up + + + + + Move down + + + + + Move to bottom + + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + + + + + AI + + + + + Autoincrement + + + + + U + + + + + + + Unique + + + + + Default + + + + + Default value + + + + + + Check + + + + + Check constraint + + + + + Collation + + + + + Foreign Key + + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + + + + + Index Constraints + + + + + Add constraint + + + + + Remove constraint + + + + + + Columns + + + + + + + SQL + + + + + Foreign Keys + + + + + References + + + + + Check Constraints + + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + + + + + + Primary Key + + + + + Add a primary key constraint + + + + + Add a unique constraint + + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + + + + + Error creating table. Message from database engine: +%1 + + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + + + + + Column '%1' has duplicate data. + + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + + + + + ExportDataDialog + + + Export data as CSV + + + + + Tab&le(s) + + + + + Colu&mn names in first line + + + + + Fie&ld separator + + + + + , + + + + + ; + + + + + Tab + + + + + | + + + + + + + Other + + + + + &Quote character + + + + + " + + + + + ' + + + + + New line characters + + + + + Windows: CR+LF (\r\n) + + + + + Unix: LF (\n) + + + + + Pretty print + + + + + Export data as JSON + + + + + exporting CSV + + + + + + Error while writing the file '%1': %2 + + + + + + Could not open output file: %1 + + + + + exporting JSON + + + + + + Choose a filename to export data + + + + + Please select at least 1 table. + + + + + Choose a directory + + + + + Export completed. + + + + + Export finished with errors. + + + + + ExportSqlDialog + + + Export SQL... + + + + + Tab&le(s) + + + + + Select All + + + + + Deselect All + + + + + &Options + + + + + Keep column names in INSERT INTO + + + + + Multiple rows (VALUES) per INSERT statement + + + + + Export everything + + + + + Export schema only + + + + + Export data only + + + + + Keep original CREATE statements + + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + + + + + Please select at least one table. + + + + + Choose a filename to export + + + + + Export completed. + + + + + Export cancelled or failed. + + + + + ExtendedScintilla + + + + Ctrl+H + + + + + Ctrl+F + + + + + + Ctrl+P + + + + + Find... + + + + + Find and Replace... + + + + + Print... + + + + + ExtendedTableWidget + + + Use as Exact Filter + + + + + Containing + + + + + Not containing + + + + + Not equal to + + + + + Greater than + + + + + Less than + + + + + Greater or equal + + + + + Less or equal + + + + + Between this and... + + + + + Regular expression + + + + + Edit Conditional Formats... + + + + + Set to NULL + + + + + Cut + + + + + Copy + + + + + Copy with Headers + + + + + Copy as SQL + + + + + Paste + + + + + Print... + + + + + Use in Filter Expression + + + + + Alt+Del + + + + + Ctrl+Shift+C + + + + + Ctrl+Alt+C + + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + + + + + FileExtensionManager + + + File Extension Manager + + + + + &Up + + + + + &Down + + + + + &Add + + + + + &Remove + + + + + + Description + + + + + Extensions + + + + + *.extension + + + + + FilterLineEdit + + + Filter + + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + + + + + Clear All Conditional Formats + + + + + Use for Conditional Format + + + + + Set Filter Expression + + + + + What's This? + + + + + Is NULL + + + + + Is not NULL + + + + + Is empty + + + + + Is not empty + + + + + Not containing... + + + + + Equal to... + + + + + Not equal to... + + + + + Greater than... + + + + + Less than... + + + + + Greater or equal... + + + + + Less or equal... + + + + + In range... + + + + + Regular expression... + + + + + Edit Conditional Formats... + + + + + FindReplaceDialog + + + Find and Replace + + + + + Fi&nd text: + + + + + Re&place with: + + + + + Match &exact case + + + + + Match &only whole words + + + + + When enabled, the search continues from the other end when it reaches one end of the page + + + + + &Wrap around + + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + + + + + Search &backwards + + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + + + + + &Selection only + + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + + Use regular e&xpressions + + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + + + + + &Find Next + + + + + F3 + + + + + &Replace + + + + + Highlight all the occurrences of the text in the page + + + + + F&ind All + + + + + Replace all the occurrences of the text in the page + + + + + Replace &All + + + + + The searched text was not found + + + + + The searched text was not found. + + + + + The searched text was replaced one time. + + + + + The searched text was found one time. + + + + + The searched text was replaced %1 times. + + + + + The searched text was found %1 times. + + + + + ForeignKeyEditor + + + &Reset + + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + + + + + ImageViewer + + + Image Viewer + + + + + Reset the scaling to match the original size of the image. + + + + + Set the scaling to match the size of the viewport. + + + + + Print... + + + + + Open preview dialog for printing displayed image + + + + + Ctrl+P + + + + + ImportCsvDialog + + + Import CSV file + + + + + Table na&me + + + + + &Column names in first line + + + + + Field &separator + + + + + , + + + + + ; + + + + + + Tab + + + + + | + + + + + Other + + + + + &Quote character + + + + + + Other (printable) + + + + + + Other (code) + + + + + " + + + + + ' + + + + + &Encoding + + + + + UTF-8 + + + + + UTF-16 + + + + + ISO-8859-1 + + + + + Trim fields? + + + + + Separate tables + + + + + Advanced + + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + + + + + Ignore default &values + + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + + + + + Fail on missing values + + + + + Disable data type detection + + + + + Disable the automatic data type detection when creating a new table. + + + + + Use local number conventions + + + + + Use decimal and thousands separators according to the system locale. + + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + + + + + Abort import + + + + + Ignore row + + + + + Replace existing row + + + + + Conflict strategy + + + + + + Deselect All + + + + + Match Similar + + + + + Select All + + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + + + + + There is already a table named '%1'. Do you want to import the data into it? + + + + + Creating restore point failed: %1 + + + + + Creating the table failed: %1 + + + + + importing CSV + + + + + Could not prepare INSERT statement: %1 + + + + + Inserting row failed: %1 + + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + + + + + MainWindow + + + DB Browser for SQLite + + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + + + + + toolBar1 + + + + + &File + + + + + &Import + + + + + &Export + + + + + &Edit + + + + + &View + + + + + &Help + + + + + Too&ls + + + + + DB Toolbar + + + + + Edit Database &Cell + + + + + SQL &Log + + + + + Show S&QL submitted by + + + + + User + + + + + Application + + + + + Error Log + + + + + This button clears the contents of the SQL logs + + + + + &Clear + + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + + + + + &Plot + + + + + DB Sche&ma + + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + + + + + &Remote + + + + + + Project Toolbar + + + + + Extra DB toolbar + + + + + + + Close the current database file + + + + + &New Database... + + + + + + Create a new database file + + + + + This option is used to create a new database file. + + + + + Ctrl+N + + + + + + &Open Database... + + + + + + + + + Open an existing database file + + + + + + + This option is used to open an existing database file. + + + + + Ctrl+O + + + + + &Close Database + + + + + This button closes the connection to the currently open database file + + + + + + Ctrl+W + + + + + &Revert Changes + + + + + + Revert database to last saved state + + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + + + + + &Write Changes + + + + + + Write changes to the database file + + + + + This option is used to save changes to the database file. + + + + + Ctrl+S + + + + + Compact &Database... + + + + + Compact the database file, removing space wasted by deleted records + + + + + + Compact the database file, removing space wasted by deleted records. + + + + + E&xit + + + + + Ctrl+Q + + + + + &Database from SQL file... + + + + + Import data from an .sql dump text file into a new or existing database. + + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + + + + + &Table from CSV file... + + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + + + + + &Database to SQL file... + + + + + Export a database to a .sql dump text file. + + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + + + + + &Table(s) as CSV file... + + + + + Export a database table as a comma separated text file. + + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + + + + + &Create Table... + + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + + + + + &Delete Table... + + + + + + Delete Table + + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + + + + + &Modify Table... + + + + + Create &Index... + + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + + + + + &Preferences... + + + + + + Open the preferences window. + + + + + &DB Toolbar + + + + + Shows or hides the Database toolbar. + + + + + New &tab + + + + + Ctrl+T + + + + + Open SQL file(s) + + + + + This button opens files containing SQL statements and loads them in new editor tabs + + + + + Sa&ve Project + + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + + + + + This button lets you open a DB Browser for SQLite project file + + + + + Ctrl+Shift+O + + + + + &Save Project As... + + + + + + + Save the project in a file selected in a dialog + + + + + Save A&ll + + + + + + + Save DB file, project file and opened SQL files + + + + + Ctrl+Shift+S + + + + + Browse Table + + + + + Close Pro&ject + + + + + + Close project and database files and return to the initial state + + + + + Ctrl+Shift+F4 + + + + + + Detach Database + + + + + + Detach database file attached to the current database connection + + + + + W&hat's This? + + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + + + + + Temp Store + + + + + Secure Delete + + + + + Case Sensitive Like + + + + + Journal Mode + + + + + Journal Size Limit + + + + + Recursive Triggers + + + + + Page Size + + + + + Foreign Keys + + + + + Auto Vacuum + + + + + Max Page Count + + + + + Checkpoint Full FSYNC + + + + + + Off + + + + + + Normal + + + + + + Full + + + + + Default + + + + + File + + + + + + Memory + + + + + Delete + + + + + Truncate + + + + + Persist + + + + + WAL + + + + + Exclusive + + + + + Automatic Index + + + + + Ignore Check Constraints + + + + + Full FSYNC + + + + + WAL Auto Checkpoint + + + + + User Version + + + + + Synchronous + + + + + None + + + + + Incremental + + + + + Locking Mode + + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + + + + + &Recent Files + + + + + &New Database + + + + + + Ctrl+F4 + + + + + &Undo + + + + + + Undo last change to the database + + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + + + + + Shift+F1 + + + + + &About + + + + + &Recently opened + + + + + This button opens a new tab for the SQL editor + + + + + &Execute SQL + + + + + Execute all/selected SQL + + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + + + + + Ctrl+Return + + + + + Ctrl+Shift+T + + + + + + + Save SQL file + + + + + &Load Extension... + + + + + + Execute current line + + + + + Execute line + + + + + This button executes the SQL statement present in the current editor line + + + + + Shift+F5 + + + + + Export as CSV file + + + + + Export table as comma separated values file + + + + + &Wiki + + + + + F1 + + + + + Bug &Report... + + + + + Feature Re&quest... + + + + + Web&site + + + + + &Donate on Patreon... + + + + + &Save Project + + + + + + Save the current session to a file + + + + + Open &Project... + + + + + Open &Project + + + + + + Load a working session from a file + + + + + &Attach Database... + + + + + + Add another database file to the current database connection + + + + + This button lets you add another database file to the current database connection + + + + + &Set Encryption... + + + + + + Save SQL file as + + + + + This button saves the content of the current SQL editor tab to a file + + + + + &Browse Table + + + + + Copy Create statement + + + + + Copy the CREATE statement of the item to the clipboard + + + + + SQLCipher &FAQ + + + + + Opens the SQLCipher FAQ in a browser window + + + + + Table(&s) to JSON... + + + + + Export one or more table(s) to a JSON file + + + + + Open Data&base Read Only... + + + + + Open an existing database file in read only mode + + + + + Save results + + + + + Save the results view + + + + + This button lets you save the results of the last executed query + + + + + + Find text in SQL editor + + + + + Find + + + + + This button opens the search bar of the editor + + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + + + + + Find or replace + + + + + This button opens the find/replace dialog for the current editor tab + + + + + Ctrl+H + + + + + Export to &CSV + + + + + Export to &JSON + + + + + Save as &view + + + + + Save as view + + + + + Shows or hides the Project toolbar. + + + + + Extra DB Toolbar + + + + + &Open Database + + + + + New In-&Memory Database + + + + + Drag && Drop SELECT Query + + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + + + + + Drag && Drop Qualified Names + + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + + + + + Drag && Drop Enquoted Names + + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + + + + + &Integrity Check + + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + + + + + &Foreign-Key Check + + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + + + + + &Quick Integrity Check + + + + + Run a quick integrity check over the open DB + + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + + + + + &Optimize + + + + + Attempt to optimize the database + + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + + + + + + Print + + + + + Print text from current SQL editor tab + + + + + Open a dialog for printing the text in the current SQL editor tab + + + + + + Ctrl+P + + + + + Print the structure of the opened database + + + + + Open a dialog for printing the structure of the opened database + + + + + Un/comment block of SQL code + + + + + Un/comment block + + + + + Comment or uncomment current line or selected block of code + + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + + + + + Ctrl+/ + + + + + Stop SQL execution + + + + + Stop execution + + + + + Stop the currently running SQL script + + + + + + Ctrl+Shift+W + + + + + Table from CSV data in Clipboard... + + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + + + + + Show &Row Counts + + + + + This shows the number of rows for each table and view in the database. + + + + + Save Database &As... + + + + + Save the current database as a different file + + + + + Refresh + + + + + Reload the database structure + + + + + Ctrl+L + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Ctrl+E + + + + + Ctrl+0 + + + + + The database is currently busy. + + + + + Click here to interrupt the currently running query. + + + + + Encrypted + + + + + Database is encrypted using SQLCipher + + + + + Read only + + + + + Database file is read only. Editing the database is disabled. + + + + + Database encoding + + + + + Alt+Shift+W + + + + + + Choose a database file + + + + + Could not open database file. +Reason: %1 + + + + + + + Choose a filename to save under + + + + + In-Memory database + + + + + Choose a database file to save under + + + + + Error while saving the database to the new file. + + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + + + + + Are you sure you want to delete the view '%1'? + + + + + Are you sure you want to delete the trigger '%1'? + + + + + Are you sure you want to delete the index '%1'? + + + + + Error: could not delete the table. + + + + + Error: could not delete the view. + + + + + Error: could not delete the trigger. + + + + + Error: could not delete the index. + + + + + Message from database engine: +%1 + + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + + + + + Error checking foreign keys after table modification. The changes will be reverted. + + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + + + + + -- EXECUTING SELECTION IN '%1' +-- + + + + + -- EXECUTING LINE IN '%1' +-- + + + + + -- EXECUTING ALL IN '%1' +-- + + + + + %1 rows returned in %2ms + + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + + + + + Execution finished with errors. + + + + + Execution finished without errors. + + + + + Choose text files + + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + + + + + Choose a file to import + + + + + Opened '%1' in read-only mode from recent file list + + + + + Opened '%1' from recent file list + + + + + &%1 %2%3 + + + + + (read only) + + + + + Open Database or Project + + + + + Attach Database... + + + + + Import CSV file(s)... + + + + + Do you want to save the changes made to SQL tabs in a new project file? + + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + + + + + Do you want to save the changes made to the SQL file %1? + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + + + + + Text files(*.sql *.txt);;All files(*) + + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + + + + + Ctrl+Tab + + + + + Ctrl+Shift+Tab + + + + + Clear List + + + + + Window Layout + + + + + Reset Window Layout + + + + + Simplify Window Layout + + + + + Alt+Shift+0 + + + + + Dock Windows at Bottom + + + + + Dock Windows at Left Side + + + + + Dock Windows at Top + + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + + + + + Do you want to save the changes made to the project file '%1'? + + + + + Edit View %1 + + + + + Edit Trigger %1 + + + + + + At line %1: + + + + + Result: %1 + + + + + Result: %2 + + + + + File %1 already exists. Please choose a different name. + + + + + Error importing data: %1 + + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + + + + + Import completed. + + + + + Delete View + + + + + Modify View + + + + + Delete Trigger + + + + + Modify Trigger + + + + + Delete Index + + + + + Modify Index + + + + + Modify Table + + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + + + + + + DB file '%1' could not be opened + + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + + + + + Table '%1' not found; settings ignored + + + + + Could not open project file for writing. +Reason: %1 + + + + + -- Reference to file "%1" (not supported by this version) -- + + + + + Project saved to file '%1' + + + + + Yes. Don't ask again + + + + + Rename Tab + + + + + Duplicate Tab + + + + + Close Tab + + + + + Opening '%1'... + + + + + There was an error opening '%1'... + + + + + Value is not a valid URL or filename: %1 + + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + + + + + Automatically load the last opened DB file at startup + + + + + Select SQL file to open + + + + + Select file name + + + + + Select extension file + + + + + Extension successfully loaded. + + + + + Error loading extension: %1 + + + + + Could not find resource file: %1 + + + + + + Don't show again + + + + + New version available. + + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + + + + + Choose a project file to open + + + + + DB Browser for SQLite project file (*.sqbpro) + + + + + Collation needed! Proceed? + + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + + + + + creating collation + + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + + + + + Please specify the view name + + + + + There is already an object with that name. Please choose a different name. + + + + + View successfully created. + + + + + Error creating view: %1 + + + + + This action will open a new SQL tab for running: + + + + + This action will open a new SQL tab with the following statements for you to edit and run: + + + + + Press Help for opening the corresponding SQLite reference page. + + + + + Busy (%1) + + + + + NullLineEdit + + + Set to NULL + + + + + Alt+Del + + + + + PlotDock + + + Plot + + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + + + + + Columns + + + + + X + + + + + Y1 + + + + + Y2 + + + + + Axis Type + + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + + + + + Line type: + + + + + + None + + + + + Line + + + + + StepLeft + + + + + StepRight + + + + + StepCenter + + + + + Impulse + + + + + Point shape: + + + + + Cross + + + + + Plus + + + + + Circle + + + + + Disc + + + + + Square + + + + + Diamond + + + + + Star + + + + + Triangle + + + + + TriangleInverted + + + + + CrossSquare + + + + + PlusSquare + + + + + CrossCircle + + + + + PlusCircle + + + + + Peace + + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + + + + + Save current plot... + + + + + + Load all data and redraw plot + + + + + Copy + + + + + Print... + + + + + Help + + + + + Show legend + + + + + Stacked bars + + + + + Fixed number format + + + + + Date/Time + + + + + Date + + + + + Time + + + + + + Numeric + + + + + Label + + + + + Invalid + + + + + + + Row # + + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + + + + + Choose an axis color + + + + + Choose a filename to save under + + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + + + + + Loading all remaining data for this table took %1ms. + + + + + PreferencesDialog + + + Preferences + + + + + &General + + + + + Default &location + + + + + Remember last location + + + + + Always use this location + + + + + Remember last location for session only + + + + + + + ... + + + + + Lan&guage + + + + + Toolbar style + + + + + + + + + Only display the icon + + + + + + + + + Only display the text + + + + + + + + + The text appears beside the icon + + + + + + + + + The text appears under the icon + + + + + + + + + Follow the style + + + + + + + + + + + + + + + enabled + + + + + Automatic &updates + + + + + DB file extensions + + + + + Manage + + + + + Show remote options + + + + + &Database + + + + + Database &encoding + + + + + Open databases with foreign keys enabled. + + + + + &Foreign keys + + + + + Remove line breaks in schema &view + + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + + + + + Prefetch block si&ze + + + + + SQ&L to execute after opening database + + + + + Default field type + + + + + Main Window + + + + + Database Structure + + + + + Browse Data + + + + + Execute SQL + + + + + Edit Database Cell + + + + + When this value is changed, all the other color preferences are also set to matching colors. + + + + + Follow the desktop style + + + + + Dark style + + + + + Application style + + + + + This sets the font size for all UI elements which do not have their own font size option. + + + + + Font size + + + + + Max Recent Files + + + + + Prompt to save SQL tabs +in new project file + + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + + + + + Database structure font size + + + + + Data &Browser + + + + + Font + + + + + &Font + + + + + Font si&ze + + + + + Content + + + + + Symbol limit in cell + + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + + + + + Threshold for completion and calculation on selection + + + + + Show images in cell + + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + + + + + Field display + + + + + Displayed &text + + + + + Binary + + + + + NULL + + + + + Regular + + + + + + + + + + + + Click to set this color + + + + + Text color + + + + + Background color + + + + + + Preview only (N/A) + + + + + Filters + + + + + Escape character + + + + + Delay time (&ms) + + + + + Light style + + + + + Formatted + + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + + + + + &SQL + + + + + Context + + + + + Colour + + + + + Bold + + + + + Italic + + + + + Underline + + + + + Keyword + + + + + Function + + + + + Table + + + + + Comment + + + + + Identifier + + + + + String + + + + + Current line + + + + + Background + + + + + Foreground + + + + + Selection background + + + + + Selection foreground + + + + + Highlight + + + + + SQL editor &font + + + + + SQL &editor font size + + + + + SQL &results font size + + + + + Tab size + + + + + Use tabs for indentation + + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + + + + + &Wrap lines + + + + + Never + + + + + At word boundaries + + + + + At character boundaries + + + + + At whitespace boundaries + + + + + &Quotes for identifiers + + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + + + + + "Double quotes" - Standard SQL (recommended) + + + + + `Grave accents` - Traditional MySQL quotes + + + + + [Square brackets] - Traditional MS SQL Server quotes + + + + + Code co&mpletion + + + + + Keywords in &UPPER CASE + + + + + When set, the SQL keywords are completed in UPPER CASE letters. + + + + + Error indicators + + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + + + + + Hori&zontal tiling + + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + + + + + Close button on tabs + + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + + + + + &Extensions + + + + + Select extensions to load for every database: + + + + + Add extension + + + + + Remove extension + + + + + Select built-in extensions to load for every database: + + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + + + + + Disable Regular Expression extension + + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + + + + + Allow loading extensions from SQL code + + + + + Remote + + + + + Your certificates + + + + + File + + + + + + Subject CN + + + + + Subject Common Name + + + + + Issuer CN + + + + + Issuer Common Name + + + + + + Valid from + + + + + + Valid to + + + + + + Serial number + + + + + CA certificates + + + + + Common Name + + + + + Subject O + + + + + Organization + + + + + Clone databases into + + + + + Proxy + + + + + Configure + + + + + Export Settings + + + + + Import Settings + + + + + + Choose a directory + + + + + + The language will change after you restart the application. + + + + + Select extension file + + + + + Extensions(*.so *.dylib *.dll);;All files(*) + + + + + Import certificate file + + + + + No certificates found in this file. + + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + + + + + Save Settings File + + + + + + Initialization File (*.ini) + + + + + The settings file has been saved in location : + + + + + + Open Settings File + + + + + The settings file was loaded properly. + + + + + The selected settings file is not a normal settings file. +Please check again. + + + + + ProxyDialog + + + Proxy Configuration + + + + + Pro&xy Type + + + + + Host Na&me + + + + + Port + + + + + Authentication Re&quired + + + + + &User Name + + + + + Password + + + + + None + + + + + System settings + + + + + HTTP + + + + + SOCKS5 + + + + + QObject + + + All files (*) + + + + + Error importing data + + + + + from record number %1 + + + + + . +%1 + + + + + Importing CSV file... + + + + + Cancel + + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + + + + + Left + + + + + Right + + + + + Center + + + + + Justify + + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + + + + + DB Browser for SQLite Project Files (*.sqbpro) + + + + + SQL Files (*.sql) + + + + + All Files (*) + + + + + Text Files (*.txt) + + + + + Comma-Separated Values Files (*.csv) + + + + + Tab-Separated Values Files (*.tsv) + + + + + Delimiter-Separated Values Files (*.dsv) + + + + + Concordance DAT files (*.dat) + + + + + JSON Files (*.json *.js) + + + + + XML Files (*.xml) + + + + + Binary Files (*.bin *.dat) + + + + + SVG Files (*.svg) + + + + + Hex Dump Files (*.dat *.bin) + + + + + Extensions (*.so *.dylib *.dll) + + + + + Initialization File (*.ini) + + + + + RemoteCommitsModel + + + Commit ID + + + + + Message + + + + + Date + + + + + Author + + + + + Size + + + + + Authored and committed by %1 + + + + + Authored by %1, committed by %2 + + + + + RemoteDatabase + + + Error opening local databases list. +%1 + + + + + Error creating local databases list. +%1 + + + + + RemoteDock + + + Remote + + + + + Identity + + + + + Upload + + + + + DBHub.io + + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + + + + + Local + + + + + Current Database + + + + + Clone + + + + + &User + + + + + &Database + + + + + Branch + + + + + Commits + + + + + Commits for + + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + + + + + Back + + + + + Delete Database + + + + + Delete the local clone of this database + + + + + Open in Web Browser + + + + + Open the web page for the current database in your browser + + + + + Clone from Link + + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + + + + + Refresh + + + + + Reload all data and update the views + + + + + Clone Database + + + + + Open Database + + + + + Open the local copy of this database + + + + + Check out Commit + + + + + Download and open this specific commit + + + + + Check out Latest Commit + + + + + Check out the latest commit of the current branch + + + + + Save Revision to File + + + + + Saves the selected revision of the database to another file + + + + + Upload Database + + + + + Upload this database as a new commit + + + + + Push currently opened database to server + + + + + Select an identity to connect + + + + + Public + + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + + + + + Invalid URL: The host name does not match the host name of the current identity. + + + + + Invalid URL: No branch name specified. + + + + + Invalid URL: No commit ID specified. + + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + + + + + The database has unsaved changes. Are you sure you want to push it before saving? + + + + + The database you are trying to delete is currently opened. Please close it before deleting. + + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + + + + + RemoteLocalFilesModel + + + Name + + + + + Branch + + + + + Last modified + + + + + Size + + + + + Commit + + + + + File + + + + + RemoteModel + + + Name + + + + + Commit + + + + + Last modified + + + + + Size + + + + + Size: + + + + + Last Modified: + + + + + Licence: + + + + + Default Branch: + + + + + RemoteNetwork + + + Choose a location to save the file + + + + + Error opening remote file at %1. +%2 + + + + + Error: Invalid client certificate specified. + + + + + Please enter the passphrase for this client certificate in order to authenticate. + + + + + Cancel + + + + + Uploading remote database to +%1 + + + + + Downloading remote database from +%1 + + + + + Error: Cannot open the file for sending. + + + + + RemotePushDialog + + + Push database + + + + + Database na&me to push to + + + + + Commit message + + + + + Database licence + + + + + Public + + + + + Branch + + + + + Force push + + + + + Username + + + + + Database will be public. Everyone has read access to it. + + + + + Database will be private. Only you have access to it. + + + + + Use with care. This can cause remote commits to be deleted. + + + + + RunSql + + + Execution aborted by user + + + + + , %1 rows affected + + + + + query executed successfully. Took %1ms%2 + + + + + executing query + + + + + SelectItemsPopup + + + A&vailable + + + + + Sele&cted + + + + + SqlExecutionArea + + + Form + + + + + Find previous match [Shift+F3] + + + + + Find previous match with wrapping + + + + + Shift+F3 + + + + + The found pattern must be a whole word + + + + + Whole Words + + + + + Text pattern to find considering the checks in this frame + + + + + Find in editor + + + + + The found pattern must match in letter case + + + + + Case Sensitive + + + + + Find next match [Enter, F3] + + + + + Find next match with wrapping + + + + + F3 + + + + + Interpret search pattern as a regular expression + + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + + Regular Expression + + + + + + Close Find Bar + + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + + + + + Results of the last executed statements + + + + + This field shows the results and status codes of the last executed statements. + + + + + Ctrl+PgUp + + + + + Ctrl+PgDown + + + + + Couldn't read file "%1": %2. + + + + + + Couldn't save file: %1. + + + + + Your changes will be lost when reloading it! + + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + + + + + Answer "No to All" to ignore any external update without further prompting. + + + + + Modifying and saving the file will restore prompting. + + + + + SqlTextEdit + + + Ctrl+/ + + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + + + + + (X) ltrim(X) removes spaces from the left side of X. + + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + + + + + (X) rtrim(X) removes spaces from the right side of X. + + + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + + + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + + + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + + + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + + + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + + + + + (X) trim(X) removes spaces from both ends of X. + + + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + + + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + + + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + + + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + + + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + + + + + + + + (timestring,modifier,modifier,...) + + + + + (format,timestring,modifier,modifier,...) + + + + + (X) The avg() function returns the average value of all non-NULL X within a group. + + + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + + + + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + + + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + + + + + (X) The max() aggregate function returns the maximum value of all values in the group. + + + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + + + + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + + + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + + + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + + + + + (X) Return the arccosine of X. The result is in radians. + + + + + (X) Return the hyperbolic arccosine of X. + + + + + (X) Return the arcsine of X. The result is in radians. + + + + + (X) Return the hyperbolic arcsine of X. + + + + + (X) Return the arctangent of X. The result is in radians. + + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + + + + + (X) Return the hyperbolic arctangent of X. + + + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + + + + + (X) Return the cosine of X. X is in radians. + + + + + (X) Return the hyperbolic cosine of X. + + + + + (X) Convert value X from radians into degrees. + + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + + + + + (X) Return the natural logarithm of X. + + + + + (B,X) Return the base-B logarithm of X. + + + + + + (X) Return the base-10 logarithm for X. + + + + + (X) Return the logarithm base-2 for the number X. + + + + + (X,Y) Return the remainder after dividing X by Y. + + + + + () Return an approximation for Ï€. + + + + + + (X,Y) Compute X raised to the power Y. + + + + + (X) Convert X from degrees into radians. + + + + + (X) Return the sine of X. X is in radians. + + + + + (X) Return the hyperbolic sine of X. + + + + + (X) Return the square root of X. NULL is returned if X is negative. + + + + + (X) Return the tangent of X. X is in radians. + + + + + (X) Return the hyperbolic tangent of X. + + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + + + + + SqliteTableModel + + + reading rows + + + + + loading... + + + + + References %1(%2) +Hold %3Shift and click to jump there + + + + + Error changing data: +%1 + + + + + retrieving list of columns + + + + + Fetching data... + + + + + + Cancel + + + + + TableBrowser + + + Browse Data + + + + + &Table: + + + + + Select a table to browse data + + + + + Use this list to select a table to be displayed in the database view + + + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + + + + + Text pattern to find considering the checks in this frame + + + + + Find in table + + + + + Find previous match [Shift+F3] + + + + + Find previous match with wrapping + + + + + Shift+F3 + + + + + Find next match [Enter, F3] + + + + + Find next match with wrapping + + + + + F3 + + + + + The found pattern must match in letter case + + + + + Case Sensitive + + + + + The found pattern must be a whole word + + + + + Whole Cell + + + + + Interpret search pattern as a regular expression + + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + + Regular Expression + + + + + + Close Find Bar + + + + + Text to replace with + + + + + Replace with + + + + + Replace next match + + + + + + Replace + + + + + Replace all matches + + + + + Replace all + + + + + Export to &JSON + + + + + + Export the filtered data to JSON + + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + + + + + Copy column name + + + + + Copy the database table column name to your clipboard + + + + + New Data Browser + + + + + + Add a new docked Data Browser + + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + + + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + + + + + |< + + + + + Scroll one page upwards + + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + + + + + < + + + + + 0 - 0 of 0 + + + + + Scroll one page downwards + + + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + + + + + > + + + + + Scroll to the end + + + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + + + + + >| + + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + + + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + + + + + Go to: + + + + + Enter record number to browse + + + + + Type a record number in this area and click the Go to: button to display the record in the database view + + + + + 1 + + + + + Show rowid column + + + + + Toggle the visibility of the rowid column + + + + + Unlock view editing + + + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + + + + + Edit display format + + + + + Edit the display format of the data in this column + + + + + + New Record + + + + + + Insert a new record in the current table + + + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + + + + + + Delete Record + + + + + Delete the current record + + + + + + This button deletes the record or records currently selected in the table + + + + + + Insert new record using default values in browsed table + + + + + Insert Values... + + + + + + Open a dialog for inserting values in a new record + + + + + Export to &CSV + + + + + + Export the filtered data to CSV + + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + + + + + Save as &view + + + + + + Save the current filter, sort column and display formats as a view + + + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + + + + + Save Table As... + + + + + + Save the table as currently displayed + + + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + + + + + Hide column(s) + + + + + Hide selected column(s) + + + + + Show all columns + + + + + Show all columns that were hidden + + + + + + Set encoding + + + + + Change the encoding of the text in the table cells + + + + + Set encoding for all tables + + + + + Change the default encoding assumed for all tables in the database + + + + + Clear Filters + + + + + Clear all filters + + + + + + This button clears all the filters set in the header input fields for the currently browsed table. + + + + + Clear Sorting + + + + + Reset the order of rows to the default + + + + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + + + + + Print + + + + + Print currently browsed table data + + + + + Print currently browsed table data. Print selection if more than one cell is selected. + + + + + Ctrl+P + + + + + Refresh + + + + + Refresh the data in the selected table + + + + + This button refreshes the data in the currently selected table. + + + + + F5 + + + + + Find in cells + + + + + Open the find tool bar which allows you to search for values in the table view below. + + + + + + Bold + + + + + Ctrl+B + + + + + + Italic + + + + + + Underline + + + + + Ctrl+U + + + + + + Align Right + + + + + + Align Left + + + + + + Center Horizontally + + + + + + Justify + + + + + + Edit Conditional Formats... + + + + + Edit conditional formats for the current column + + + + + Clear Format + + + + + Clear All Formats + + + + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + + + + + + Font Color + + + + + + Background Color + + + + + Toggle Format Toolbar + + + + + Show/hide format toolbar + + + + + + This button shows or hides the formatting toolbar of the Data Browser + + + + + Select column + + + + + Ctrl+Space + + + + + Replace text in cells + + + + + Freeze columns + + + + + Make all columns from the first column up to this column not move when scrolling horizontally + + + + + Filter in any column + + + + + Ctrl+R + + + + + %n row(s) + + + + + + + , %n column(s) + + + + + + + . Sum: %1; Average: %2; Min: %3; Max: %4 + + + + + Conditional formats for "%1" + + + + + determining row count... + + + + + %L1 - %L2 of >= %L3 + + + + + %L1 - %L2 of %L3 + + + + + (clipped at %L1 rows) + + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + + + + + Delete Records + + + + + Duplicate records + + + + + Duplicate record + + + + + Ctrl+" + + + + + Adjust rows to contents + + + + + Error deleting record: +%1 + + + + + Please select a record first + + + + + Please choose a new encoding for all tables. + + + + + Please choose a new encoding for this table. + + + + + %1 +Leave the field empty for using the database encoding. + + + + + This encoding is either not valid or not supported. + + + + + %1 replacement(s) made. + + + + + TableBrowserDock + + + New Data Browser + + + + + Rename Data Browser + + + + + Close Data Browser + + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + + + + + VacuumDialog + + + Compact Database + + + + + Warning: Compacting the database will commit all of your changes. + + + + + Please select the databases to co&mpact: + + + + diff --git a/src/translations/sqlb_fr.ts b/src/translations/sqlb_fr.ts index 1e9490cb4..da65c6d50 100644 --- a/src/translations/sqlb_fr.ts +++ b/src/translations/sqlb_fr.ts @@ -1,2048 +1,8093 @@ - + AboutDialog - About SqliteBrowser - A propos de SQLiteBrowser + About DB Browser for SQLite + À propos de DB Browser for SQLite - + Version Version - - Qt Version - Version de Qt + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + <html><head/><body><p>DB Browser for SQLite est une interface graphique libre et open source utilisée pour créer, concevoir et éditer des fichiers de base de données SQLite.</p><p>Il est placé sous la double licence Mozilla Public License Version 2 ainsi que GNU General Public License Version 3 ou ultérieure. Vous pouvez le modifier ou le redistribuer en respectant les conditions de ces licences.</p><p>Voir <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> et <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> pour les détails.</p><p>Pour plus d'informations sur ce programme, veuillez consulter notre site Internet <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">Ce logiciel utilise le GPL/LGPL Qt Toolkit fourni par </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;">.<br/> Voir </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> pour les conditions de licence et toute autre information.</span></p><p><span style=" font-size:8pt;">Nous utilisons la bibliothèque nalgeon/sqlean pour la reconnaissance des extensions SQLite.<br/>Cette bibliothèque est sous la licence MIT. Pour davantage d'informations voir <br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">Il utilise aussi le jeu d'icones Pastel SVG de Michael Buckley sous la licence Creative Commons Attribution Share Alike 4.0.<br/>Voir </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> pour les détails.</span></p></body></html> + + + AddRecordDialog - - SQLite Version - Version de SQLite + + Add New Record + Ajouter un nouvel enregistrement - - &lt;html><head/><body><p>SQLite Database Browser is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:small;">It also uses the Silk icon set by Mark James licensed under a Creative Commons Attribution 2.5 and 3.0 license.<br/>See </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> - &lt;head/><meta charset="UTF-8"><body><p>SQLite Database Browser est un outil visuel, libre et open-source, pour créer, définir et éditer des bases de données SQLite.</p><p>Il est fourni sous une double licence, la licence Mozilla Public License Version 2 et la licence GNU General Public License Version 3 ou ultérieure. Vous pouvez modifier ou redistribuer de programme dans les mêmes conditions de licence.</p><p>Pour plus de détails, voir : <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> et <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a>.</p><p>Pour plus d'information à propos de ce programme, merci de visiter notre site Internet à l'adresse suivante : <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a>.</p><p><span style=" font-size:small;">Ce logiciel utilise le boite à outils GPL/LGPL Qt Toolkit de </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a>.<span style=" font-size:small;"><br/>Pour toute information et licences, voir : </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a>.</p><p><span style=" font-size:small;">Il utilise aussi le jeu d'icônes Silk créé par Mark James, qui est sous licence Creative Commons Attribution 2.5 et 3.0.<br/>Pour plus de détails, voir : </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a>.</p></body></html> + + Enter values for the new record considering constraints. Fields in bold are mandatory. + Saisissez les valeurs en tenant compte des contraintes. Les champs en gras sont obligatoires. + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + Dans la colonne Valeur, vous pouvez spécifier la valeur du champ identifié dans la colonne Nom. La colonne Type indique le type du champ. Les valeurs par défaut sont affichées dans le même style que les valeurs NULL. + + + + Name + Nom + + + + Type + Type + + + + Value + Valeur + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + Valeurs à insérer. Les valeurs par défaut pré-remplies sont insérées automatiquement à moins qu'elles soient modifiées. + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + Lorsque vous éditez les valeurs dans le cadre supérieur, la requête SQL d'insertion du nouvel enregistrement est affichée ici. Vous pouvez l'éditer manuellement avant de l'enregistrer. + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Enregistrer</span> soumettra l'instruction SQL affichée à la base de données pour créer le nouvel enregistrement.</p><p><span style=" font-weight:600;">Restaurer les valeurs par défaut</span> restaurera les valeurs par défaut dans la <span style=" font-weight:600;">colonne</span> Valeur.</p><p><span style=" font-weight:600;">Annuler</span> fermera cette boîte de dialogue sans exécuter la requête.</p></body></html> + + + + Auto-increment + + Incrément automatique + - - - Application - - Usage: %1 [options] [db] + + Unique constraint - Usage: %1 [options] [db]> + Contrainte unique + - - Possible command line arguments: - Arguments utilisables en ligne de commande : + + Check constraint: %1 + + Vérifier les contraintes : %1 + - - -h, --help Show command line options - -h, --help Affiche les options en mode ligne de commande + + Foreign key: %1 + + Clé étrangère : %1 + + + + + Default value: %1 + + Valeur par défaut : %1 + + + + + Error adding record. Message from database engine: + +%1 + Erreur lors de l'ajout d'un enregistrement. Message du moteur de base de données : + +%1 - - -s, --sql [file] Execute this SQL file after opening the DB - -s, --sql [fichier] Exécute ce fichier de commande SQL après l'ouverture de la base de données + + Are you sure you want to restore all the entered values to their defaults? + Êtes-vous sûr de vouloir restaurer toutes les valeurs saisies à leurs valeurs par défaut ? + + + + Application + + + Possible command line arguments: + Arguments utilisables en ligne de commande : - - -q, --quit Exit application after running scripts - -q, --quit Quitte l'application après l'exécution du script + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + Les options de commande -o/--option et -O/--save-option nécessitent un argument sous la forme groupe/paramètre=valeur - - [file] Open this SQLite database - [fichier] Ouvre cette base de données SQLite + + The user settings file location is replaced with the argument value instead of the environment variable value. + L'emplacement du fichier de configuration de l'utilisateur est remplacé par la valeur de l'argument au lieu de la valeur de la variable d'environnement. - - The -s/--sql option requires an argument - l'option -s/--sql nécessite un argument + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + Valeur ignorée de la variable d'environnement (DB4S_SETTINGS_FILE) : - + + The file %1 does not exist Le fichier %1 n'existe pas - - Invalid option/non-existant file: %1 - Option invalide ou fichier %1 inexistant + + Usage + Utilisation - - - CreateIndexDialog - - Create New Index - Créer un Nouvel Index + + options + options - - &Name - &Nom + + + database + base de données - - &Columns - &Colonnes + + + project + projet - - Column - Colonne + + + csv-file + fichier-csv - - Use in Index - Utiliser dans l'index + + Show command line options + Afficher les options de la ligne de commande - - Order - Ordre + + Exit application after running scripts + Quitter l'application après l'exécution des scripts - - &Table - &Table + + + file + fichier - - &Unique - &Unique + + Execute this SQL file after opening the DB + Exécuter ce fichier SQL après avoir ouvert la base de données - - Creating the index failed: -%1 - La création de l'index a échoué -%1 + + Import this CSV file into the passed DB or into a new DB + Importer ce fichier CSV dans la base de données existante ou dans une nouvelle base de données + + + + table + table + + + + Browse this table, or use it as target of a data import + Parcourir cette table ou l'utiliser comme cible d'une importation de données + + + + Open database in read-only mode + Ouvrir la base de données en Lecture seule + + + + settings_file + fichier paramètres + + + + Run application based on this settings file + Lancer l'application avec ce fichier de paramètres + + + + + group + groupe + + + + + settings + paramètres + + + + + value + valeur + + + + Run application with this setting temporarily set to value + Lancer l'application en utilisant temporairement la valeur de ce paramètre + + + + Run application saving this value for this setting + Lancer l'application en sauvegardant la valeur de ce paramètre + + + + Display the current version + Afficher la version en cours + + + + Open this SQLite database + Ouvrir cette base de données SQLite + + + + Open this project file (*.sqbpro) + Ouvrir ce fichier projet (*.sqbpro) + + + + Import this CSV file into an in-memory database + Importer ce fichier CSV dans une base de données en mémoire + + + + + + The %1 option requires an argument + L'option %1 nécessite un argument + + + + The -S/--settings option requires an argument. The option is ignored. + L'option -S/--settings nécessite un argument. L'option est ignorée. + + + + Invalid option/non-existent file: %1 + Option invalide ou fichier %1 inexistant + + + + SQLite Version + Version de SQLite + + + + SQLCipher Version %1 (based on SQLite %2) + SQLCipher Version %1 (basé sur SQLite %2) + + + + DB Browser for SQLite Version %1. + DB Browser for SQLite Version %1. + + + + Last commit hash when built: %1 + Corriger cette phrase. A voir en fonction du contexte MVT + Dernier hachage du commit lors de la construction : %1 + + + + Built for %1, running on %2 + Compilé pour %1, fonctionnant sur %2 + + + + Qt Version %1 + Version de Qt %1 - DbStructureModel + CipherDialog - - Name - Nom + + SQLCipher encryption + Chiffrement par SQLCipher - - Object - Objet + + &Password + Mot de &Passe - - Type - Type + + &Reenter password + &Retaper le mot de passe - - Schema - Schéma + + Encr&yption settings + Para&mètre de chiffrement - - Tables (%1) - Tables (%1) + + SQLCipher &3 defaults + SQLCipher &3 par défaut - - Indices (%1) - Index (%1) + + SQLCipher &4 defaults + SQLCipher &4 par défaut - - Views (%1) - Vues (%1) + + Custo&m + Pers&onnalisé - - Triggers (%1) - Déclencheurs (%1) + + Page si&ze + &Taille de page + + + + &KDF iterations + Itérations &KDF + + + + HMAC algorithm + Algorithme HMAC + + + + KDF algorithm + Algorithme KDF + + + + Plaintext Header Size + Taille En-tête texte en clair + + + + Passphrase + The button size is not large enought to handle the whole "french text", if #Passphrase must be translate + Phrase secrète + + + + Raw key + Same comment as for Passphrase + Clé de chiffrement + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + Veuillez définir une clé pour chiffrer la base de données. +Notez que si vous modifiez les autres paramètres, optionnels, vous devrez les ressaisir chaque fois que vous ouvrirez la base de données. +Laisser les champs Mot de passe vides pour désactiver le chiffrement. +Le processus de chiffrement peut prendre un certain temps. Vous devriez avoir une copie de sauvegarde de votre base de données ! +Les modifications non enregistrées seront appliquées avant la modification du chiffrement. + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + Veuillez entrer la clé utilisée pour le chiffrement de la base de données. +Si d'autres paramètres ont été modifiés pour cette base de données, vous devrez aussi fournir ces informations. - EditDialog + ColumnDisplayFormatDialog - - Edit database cell - Éditer le contenu d'une cellule de la base de données + + Choose display format + Choisir un format d'affichage - - Import text - Importer du texte + + Display format + Format d'affichage - - Opens a file dialog used to import text to this database cell. - Ouvrir la boîte de dialogue permettant d'importer du texte dans cette cellule de la base de données. + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + Choisissez le format d'affichage pour la colonne '%1'. +Il sera appliqué à chaque valeur avant son affichage. - - &Import - &Importer + + Default + Défaut - - Export text - Exporter du texte + + Decimal number + Nombre entier (tronqué) - - Opens a file dialog used to export the contents of this database cell to a text file. - Ouvrir la boîte de dialogue permettant d'exporter le contenu de la cellule de la base de données vers un fichier texte. + + Exponent notation + Notation scientifique - - &Export - &Exporter + + Hex blob + Blob hexadécimal - - Text - Texte + + Hex number + Nombre hexadécimal - - Binary - Binaire + + Apple NSDate to date + NSDate Apple vers date & heure - - Clear cell data - Effacer les données de la cellule + + Java epoch (milliseconds) to date + Époque Java vers date et heure (milliseconde) - - Erases the contents of the cell - Effacer le contenu de la cellule + + .NET DateTime.Ticks to date + DateTime.Ticks .NET vers date & heure - - &Clear - &Effacer + + Julian day to date + Jour julien vers date & heure - - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Warning: Editing binary content in text mode may result in corrupted data!</span></p></body></html> - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Attention : Éditer un contenu binaire en mode texte peut corrompre les données!</span></p></body></html> + + Unix epoch to local time + Époque Unix vers date & heure locales - - This area displays information about the data present in this database cell - Cette zone affiche des informations à propos des données contenues dans la cellule de la base de données + + WebKit / Chromium epoch to date + Époque WebKit/Chromium vers date & heure - - Type of data currently in cell - Type des données actuellement dans la cellule + + WebKit / Chromium epoch to local time + Époque WebKit/Chromium vers date & heure locales - - Size of data currently in table - Taille des données actuellement dans la table + + Date as dd/mm/yyyy + Date au format JJ/MM/AAAA - - Choose a file - Choisir un fichier + + Lower case + Minuscules - - Text files(*.txt);;Image files(%1);;All files(*) - Fichiers Texte (*.txt);;Fichiers Image(%1);;Tous les fichiers(*) + + Binary GUID to text + GUID binaire vers texte - - Choose a filename to export data - Choisir un nom de fichier pour exporter les données + + SpatiaLite Geometry to SVG + Geometrie SpatiaLite vers SVG - - Text files(*.txt);;All files(*) - Fichiers Texte (*.txt);;Tous les fichiers(*) + + Custom display format must contain a function call applied to %1 + Le format d'affichage personnalisé doit contenir un appel de fonction appliqué à %1 - - Type of data currently in cell: Text / Numeric - Type des données actuellement dans la cellule : Texte / Numérique + + Error in custom display format. Message from database engine: + +%1 + Erreur dans le format d'affichage personnalisé. Message du moteur de base de données : + +%1 - - - %n char(s) - - %n caractère(s) - + + + Custom display format must return only one column but it returned %1. + Le format d'affichage personnalisé ne doit renvoyer qu'une seule colonne, mais il a renvoyé %1. - - Type of data currently in cell: Image - Type des données actuellement dans la cellule : Image + + Octal number + Nombre octal - - %1x%2 pixel - %1x%2 pixel + + Round number + Nombre arrondi (entier le plus proche) - - Type of data currently in cell: Binary - Type des données actuellement dans la cellule : Binaire + + Unix epoch to date + Époque Unix vers date & heure - - - %n byte(s) - - %n octet(s) - + + + Upper case + Majuscules + + + + Windows DATE to date + DATE Windows vers date & heure + + + + Custom + Personnalisé - EditTableDialog + CondFormatManager - - Edit table definition - Éditer la définition de la table + + Conditional Format Manager + Gestion des formats conditionnels - - Table - Table + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + Cette fenêtre de dialogue permet de créer et de modifier des formats conditionnels. Chaque style de cellule sera sélectionné par la première condition remplie pour les données de cette cellule. Les formats conditionnels peuvent être déplacés vers le haut et vers le bas. Ceux des rangées supérieures ont la priorité sur ceux des rangées inférieures. La syntaxe des conditions est la même que celle des filtres et une condition vide s'applique à toutes les valeurs. - - Fields - Champs + + Add new conditional format + Ajouter un nouveau format conditionnel - - Add field - Ajouter un champ + + &Add + &Ajouter - - Remove field - Supprimer un champ + + Remove selected conditional format + Supprime le format conditionnel sélectionné - - Move field up - Remonter le champ + + &Remove + &Supprimer - - Move field down - Descendre le champ + + Move selected conditional format up + Déplace le format conditionnel vers le haut - - Name - Nom + + Move &up + &Monter - - Type - Type + + Move selected conditional format down + Déplace le format conditionnel vers le bas - - - Not null - Non Null + + Move &down + &Descendre - - PK - CP + + Foreground + Avant-plan - - Primary key - Clé primaire + + Text color + Couleur de texte - - AI - IA + + Background + Arrière-plan - - Autoincrement - Incrément automatique + + Background color + Couleur d'arrière-plan - - Default - Défaut + + Font + Police - - Default value - Valeur par défaut + + Size + Taille - - Check - Vérifier + + Bold + Gras - - Check constraint - Vérifier les contraintes + + Italic + Italique + + + + Underline + Souligné + + + + Alignment + Alignement + + + + Condition + Condition + + + + + Click to select color + Cliquer pour sélectionner une couleur + + + + Are you sure you want to clear all the conditional formats of this field? + Êtes-vous sûr de vouloir effacer tous les formats conditionnels de ce champ ? + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + Veuillez spécifier le nom de la base de données sous laquelle vous voulez accéder à la base de données attachée + + + + Invalid file format + Format de fichier invalide + + + + Do you want to save the changes made to the database file %1? + Voulez-vous enregistrer les changements effectués dans la base de données %1 ? + + + + Exporting database to SQL file... + Exporter la base de données dans un fichier SQL... + + + + + Cancel + Annuler + + + + Executing SQL... + Exécution du SQL... + + + + Action cancelled. + Action annulée. + + + + Do you really want to close this temporary database? All data will be lost. + Voulez-vous vraiment fermer cette base de données temporaire ? Toutes les données seront perdues. + + + + Database didn't close correctly, probably still busy + La base de données ne s'est pas fermée correctement ; elle est probablement encore occupée + + + + Cannot open destination file: '%1' + Le fichier de destination %1 ne peut être ouvert + + + + + Cannot backup to file: '%1'. Message: %2 + Impossible de sauvegarder dans le fichier : '%1'. Message : %2 + + + + The database is currently busy: + La base de données est actuellement occupée : + + + + Do you want to abort that other operation? + Voulez-vous annuler cette autre opération ? + + + + + No database file opened + Aucun fichier de base de données ouvert + + + + + Error in statement #%1: %2. +Aborting execution%3. + Erreur dans le traitement #%1 : %2. +Exécution de %3 abandonnée. + + + + + and rolling back + et annulation des changements + + + + didn't receive any output from %1 + n'a pas reçu toutes les sorties de %1 + + + + could not execute command: %1 + ne peut pas exécuter les commandes : %1 + + + + Cannot delete this object + Impossible de supprimer cet objet + + + + Cannot set data on this object + 170726 MVT Has to be checked in real context + Définition des données impossible pour cet objet + + + + + A table with the name '%1' already exists in schema '%2'. + Une table portant le nom " %1 " existe déjà dans le schéma " %2 ". + + + + No table with name '%1' exists in schema '%2'. + Il n'existe pas de table nommée " %1 " dans le schéma " %2 ". + + + + + Cannot find column %1. + La colonne %1 n'a pas été trouvée. + + + + Creating savepoint failed. DB says: %1 + La création du point de restauration a échoué. DB indique : %1 + + + + Renaming the column failed. DB says: +%1 + Le changement de nom de la colonne a échoué. DB indique : +%1 + + + + + Releasing savepoint failed. DB says: %1 + La libération du point de sauvegarde a échoué. DB indique : %1 + + + + Creating new table failed. DB says: %1 + La création d'une nouvelle table a échoué. DB indique : %1 + + + + Copying data to new table failed. DB says: +%1 + La copie des données dans une nouvelle table a échoué. DB indique : %1 + + + + Deleting old table failed. DB says: %1 + La suppression d'une ancienne table a échoué. DB indique : %1 + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + Erreur lors du changement de nom de la table %1 vers %2. +Message du moteur de base de données : +%3 + + + + could not get list of db objects: %1 + La liste des objets de la base de données ne peut être obtenue : %1 + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + La restauration de certains des objets associés à cette table a échoué. Cela est le plus souvent dû au changement du nom de certaines colonnes. Voici l'instruction SQL que vous pourrez corriger et exécuter manuellement : + + + + + + could not get list of databases: %1 + n'a pas pu obtenir la liste des bases de données : %1 + + + + Error loading extension: %1 + Erreur lors du chargement de l'extension %1 + + + + Error loading built-in extension: %1 + Erreur lors du chargement de l'extension intégrée %1 + + + + could not get column information + 170726 MVT Has to be checked in real context + ne peut obtenir les informations sur la colonne + + + + Error setting pragma %1 to %2: %3 + Erreur dans les paramètres des pragma %1 à %2 : %3 + + + + File not found. + Fichier non trouvé. + + + + DbStructureModel + + + Name + Nom + + + + Object + Objet + + + + Type + Type + + + + Schema + Schéma + + + + Database + Base de données + + + + Browsables + Consultables + + + + All + Tout + + + + Temporary + Temporaire + + + + Tables (%1) + Tables (%1) + + + + Indices (%1) + Index (%1) + + + + Views (%1) + Vues (%1) + + + + Triggers (%1) + Déclencheurs (%1) + + + + EditDialog + + + Edit database cell + Éditer le contenu d'une cellule + + + + Mode: + Mode : + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + Voici la liste des modes pris en charge par l'éditeur de cellules. Choisissez un mode d'affichage ou d'édition des données de la cellule courante. + + + + RTL Text + Remark : there is not acronym in french for Right to Left Text (DàG : Droite à Gauche ?). If DçG is not correct, we should use the HTML dir parameter RTL + Texte DàG + + + + + Image + Image + + + + JSON + JSON + + + + XML + XML + + + + Evaluation + Évaluation + + + + + Automatically adjust the editor mode to the loaded data type + Ajuster automatiquement le mode éditeur au type de données chargé + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + Ce bouton à cocher active ou désactive le changement automatique du mode éditeur. Lorsqu'une nouvelle cellule est sélectionnée ou de nouvelles données sont importées et que la commutation automatique est activée, le mode s'adapte au type de données détecté. Vous pouvez ensuite changer le mode éditeur manuellement. Si vous souhaitez conserver ce mode de commutation manuelle pendant que vous vous déplacez dans les cellules, éteignez le bouton. + + + + Auto-switch + Auto-switch + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + Cet éditeur Qt est utilisé pour les scripts écrits de droite à gauche. Ils ne sont pas pris en charge par l'éditeur de texte par défaut. La présence de caractères de droite à gauche est détectée et ce mode d'édition est automatiquement sélectionné. + + + + Identification of the cell currently in the editor + Identification de la cellule dans l'éditeur + + + + Type and size of data currently in table + Type et taille des données figurant actuellement dans la table + + + + Open preview dialog for printing the data currently stored in the cell + Ouvrir la fenêtre de prévisualisation pour imprimer les données actuellement stockées dans la cellule + + + + Auto-format: pretty print on loading, compact on saving. + Auto-format : formater au chargement, compacter à l'enregistrement. + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + Lorsqu'elle est activée, la fonction de formatage automatique met en forme les données lors du chargement, transforme le texte en lignes et ajoute des retraits pour une lisibilité maximale. Lors de la sauvegarde des données, la fonction de formatage automatique compacte les données en supprimant les fins des lignes et les espaces inutiles. + + + + Word Wrap + Coupure des mots + + + + Wrap lines on word boundaries + Coupe les lignes aux limites des mots + + + + + Open in default application or browser + Ouvrir dans l'application ou le navigateur par défaut + + + + Open in application + Ouvrir dans l'application + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + La valeur est interprétée comme étant un fichier ou une URL. Elle sera ouverte dans l'application ou le navigateur web par défaut. + + + + Save file reference... + Enregistrer la référence du fichier... + + + + Save reference to file + Enregistre la référence au fichier + + + + + Open in external application + Ouvrir dans une application externe + + + + Autoformat + Format automatique + + + + &Export... + &Exporter... + + + + + &Import... + &Importer... + + + + + Import from file + Importer depuis un fichier + + + + + Opens a file dialog used to import any kind of data to this database cell. + Ouvre une boîte de dialogue pour importer n'importe quel type de données dans cette cellule de base de données. + + + + Export to file + Exporter vers un fichier + + + + Opens a file dialog used to export the contents of this database cell to a file. + Ouvrir la boîte de dialogue pour exporter le contenu de cette cellule de la base de données vers un fichier. + + + + Print... + Imprimer... + + + + Ctrl+P + + + + + Open preview dialog for printing displayed text + Ouvrir un aperçu du texte avant son impression + + + + Copy Hex and ASCII + Copier l'Hex et l'ASCII + + + + Copy selected hexadecimal and ASCII columns to the clipboard + Copier les colonnes hexadécimales et ASCII sélectionnées dans le presse-papiers + + + + Ctrl+Shift+C + + + + + Set as &NULL + Définir comme &NULL + + + + Apply data to cell + Appliquer les données à la cellule + + + + This button saves the changes performed in the cell editor to the database cell. + Ce bouton permet d'enregistrer les modifications effectuées dans l'éditeur de cellule dans la cellule de base de données. + + + + Apply + Appliquer + + + + Text + Texte + + + + Binary + Binaire + + + + Erases the contents of the cell + Effacer le contenu de la cellule + + + + This area displays information about the data present in this database cell + Cette zone affiche des informations à propos des données contenues dans la cellule de la base de données + + + + Choose a filename to export data + Choisir un nom de fichier pour exporter les données + + + + + Image data can't be viewed in this mode. + L'image ne peut être affichée dans ce mode. + + + + + Try switching to Image or Binary mode. + Essayez de basculer vers le mode Image ou le mode Binaire. + + + + + Binary data can't be viewed in this mode. + Les données Binaires ne peuvent être affichées dans ce mode. + + + + + Try switching to Binary mode. + Essayez de basculer vers le mode Binaire. + + + + + Type: NULL; Size: 0 bytes + Type : NULL ; Taille : 0 octet + + + + + Type: Text / Numeric; Size: %n character(s) + + Type : Texte / Numérique ; Taille : %n caractère + Type : Texte / Numérique ; Taille : %n caractères + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + Type : %1 Image ; Taille : %2x%3 pixel(s) + + + + Type: Valid JSON; Size: %n character(s) + + Type : JSON valide ; Taille : %n caractère + Type : JSON valide ; Taille : %n caractères + + + + + Type: Binary; Size: %n byte(s) + + Type : Binaire ; Taille : %n octet + Type : Binaire ; Taille : %n octets + + + + + Couldn't save file: %1. + Le fichier %1 ne peut être sauvegardé. + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + Les données ont été enregistrées dans un fichier temporaire et ont été ouvertes avec l'application par défaut. Vous pouvez maintenant modifier le fichier et, lorsque vous êtes prêt, appliquer les nouvelles données enregistrées à la cellule ou annuler les modifications. + + + + + Image files (%1) + Fichiers image (%1) + + + + Binary files (*.bin) + Fichiers Binaires (*.bin) + + + + Choose a file to import + Choisir un fichier à importer + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + Les modes de l'éditeur de texte vous permettent de modifier du texte brut, ainsi que des données JSON ou XML, avec mise en évidence de la syntaxe, formatage automatique et validation avant enregistrement. + +Les erreurs sont signalées par un trait de soulignement rouge. + +Dans le mode Évaluation, les expressions SQLite saisies sont évaluées et le résultat est appliqué à la cellule. + + + + Unsaved data in the cell editor + Données non enregistrées dans l'éditeur de cellules + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + L'éditeur de cellules contient des données qui n'ont pas encore été appliquées à la base de données. +Voulez-vous appliquer les données modifiées à la ligne=%1, colonne=%2 ? + + + + Editing row=%1, column=%2 + Modification de la ligne=%1, colonne=%2 + + + + No cell active. + Pas de cellule active. + + + + %1 Image + %1 Image + + + + Invalid data for this mode + Les données sont invalides pour ce mode + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + La cellule contient des données %1 invalides. Raison : %2. Voulez-vous vraiment l'appliquer à la cellule ? + + + + EditIndexDialog + + + &Name + &Nom + + + + Order + Ordre + + + + &Table + &Table + + + + Edit Index Schema + Éditer le schéma d'index + + + + &Unique + &Unique + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + Pour restreindre l'index à un sous-ensemble de la table, vous pouvez spécifier une clause WHERE ici. Elle sélectionnera le sous-ensemble de la table qui sera indexé + + + + Partial inde&x clause + Clause d'inde&x partiel + + + + Colu&mns + &Colonnes + + + + Table column + Colonne de table + + + + Type + Type + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + 170726 MVT Has to be checked in real context + Ajouter une nouvelle expression de colonne à l'index. Les expressions de colonnes contiennent des expressions SQL plutôt que des noms de colonnes. + + + + Index column + Colonne d'index + + + + Deleting the old index failed: +%1 + La suppression de l'ancien index a échoué : +%1 + + + + Creating the index failed: +%1 + La création de l'index a échoué : +%1 + + + + EditTableDialog + + + Edit table definition + Éditer la définition de la table + + + + Table + Table + + + + Advanced + Avancé + + + + Without Rowid + Sans RowId + + + + Fields + Champs + + + + Database sche&ma + Sché&ma de la base de données + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + Rendre cette table "WITHOUT ROWID". Activer ce paramètre requiert de spécifier une PRIMARY KEY (qui peut être de type quelconque, voire composite) et interdit le paramètre AUTOINCREMENT. + + + + On Conflict + Sur conflit + + + + Strict + Strict + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + Lorsque l'option strict est activée, SQLite respecte les types de données de chaque colonne lors de la mise à jour ou de l'insertion de données. + + + + + + Add + Ajouter + + + + + + Remove + Supprimer + + + + Move to top + Monter au début + + + + Move up + Monter + + + + Move down + Descendre + + + + Move to bottom + Descendre à la fin + + + + + + + Name + Nom + + + + + Type + Type + + + + NN + NN + + + + Not null + Non-Null + + + + PK + CP + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> Clé primaire</p></body></html> + + + + AI + IA + + + + Autoincrement + Incrément automatique + + + + U + U + + + + + + Unique + Unique + + + + Default + Défaut + + + + Default value + Valeur par défaut + + + + + Check + Vérifier + + + + Check constraint + Vérifier les contraintes + + + + Collation + Séquence + + + + Foreign Key + Clé étrangère + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_fk"/> Clé étrangère</p></body></html> + + + + Index Constraints + Contraintes d'index + + + + Add constraint + Ajouter une contrainte + + + + Remove constraint + Supprimer une contrainte + + + + + Columns + Colonnes + + + + + + SQL + SQL + + + + Foreign Keys + Clés étrangères + + + + References + Références + + + + Check Constraints + Vérifier les contraintes + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Attention&nbsp;: </span>Il y a quelque chose dans la définition de cette table que notre analyseur syntaxique n'a pas complètement compris. La modification et l'enregistrement de cette table peuvent créer des problèmes.</p></body></html> + + + + + Primary Key + Clé primaire + + + + Add a primary key constraint + Ajoute une clé primaire à la contrainte + + + + Add a unique constraint + Ajoute une contrainte unique + + + + Error creating table. Message from database engine: +%1 + Erreur lors de la création de la table. Message du moteur de la base de données : +%1 + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + Il existe déjà un champ avec ce nom. Veuillez le renommer avant ou choisir un autre nom pour ce champ. + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + Une table ne peut avoir qu'une seule clé primaire. Veuillez modifier la clé primaire existante à la place. + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + Cette colonne est référencée dans une clé étrangère dans la table %1. Son nom ne peut être changé. + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + Il existe au moins un enregistrement avec ce champ autorisant des valeurs nulles (NULL). Il est donc impossible de définir cet indicateur. Veuillez modifier les données de la table au préalable. + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + Il existe au moins un enregistrement avec une valeur qui n'est pas un nombre entier dans ce champ. Il est donc impossible de définir l'indicateur AI (Incrément automatique) sur ce champ. Veuillez modifier les données de la table au préalable. + + + + Column '%1' has duplicate data. + + La colonne %1 a des des données en double. + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + Il est donc impossible d'activer l'indicateur "Unique". Veuillez supprimer les données en double, cela vous permettra d'activer l'indicateur "Unique". + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + Êtes-vous sûr de vouloir supprimer le champ "%1" ? +Toutes les données contenues dans ce champ seront perdues. + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + Veuillez ajouter un champ ayant les caractéristiques suivant avant de positionner l'option Sans RowId : +- Défini comme clé primaire ; +- Incrément automatique désactivé + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + Veuillez ajouter un champ qui répond aux critères suivants avant de définir l'action sur le conflit : + - Indicateur de clé primaire activé + + + + ExportDataDialog + + + Export data as CSV + Exporter au format CSV + + + + Tab&le(s) + &Table(s) + + + + Colu&mn names in first line + Nom des &col. en 1ère ligne + + + + Fie&ld separator + &Séparateur de champ + + + + , + , + + + + ; + ; + + + + Tab + Tabulation + + + + | + | + + + + + + Other + Autre + + + + &Quote character + T&ype de guillemet + + + + " + " + + + + ' + ' + + + + New line characters + Saut de ligne + + + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) + + + + Unix: LF (\n) + Unix: LF (\n) + + + + Pretty print + "Indenter" is more clear to me than the previous "Formater" + Indenter + + + + + Could not open output file: %1 + Le fichier de destination %1 ne peut être ouvert + + + + + Choose a filename to export data + Choisir un nom de fichier pour exporter les données + + + + Export data as JSON + Exporter au format JSON + + + + exporting CSV + Exporter au format CSV + + + + + Error while writing the file '%1': %2 + Erreur lors de l'écriture du fichier %1 : %2 + + + + exporting JSON + Exporter au format JSON + + + + Please select at least 1 table. + Veuillez sélectionner au moins une table. + + + + Choose a directory + Choisir un répertoire + + + + Export completed. + Export terminé. + + + + Export finished with errors. + L'export s'est terminé avec des erreurs. + + + + ExportSqlDialog + + + Export SQL... + Same as defined in English... But converted to uniformize with other dialog boxes. + Exporter au format SQL... + + + + Tab&le(s) + Tab&le(s) + + + + Select All + Sélectionner tout + + + + Deselect All + Désélectionner tout + + + + &Options + &Options + + + + Keep column names in INSERT INTO + Conserver les noms des colonnes dans INSERT INTO + + + + Multiple rows (VALUES) per INSERT statement + Plusieurs enregistrements (VALUES) par INSERT + + + + Export everything + Exporter tout + + + + Export schema only + Exporter uniquement le schéma + + + + Export data only + Exporter uniquement les données + + + + Keep original CREATE statements + Conserver les déclarations CREATE d'origine + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + Conserver l'ancien schéma (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + Écraser l'ancien schéma (DROP TABLE, puis CREATE TABLE) + + + + Please select at least one table. + Veuillez sélectionner au moins une table. + + + + Choose a filename to export + Choisir un nom de fichier pour l'export + + + + Export completed. + Export terminé. + + + + Export cancelled or failed. + L'export a été annulé ou a échoué. + + + + ExtendedScintilla + + + + Ctrl+H + + + + + Ctrl+F + + + + + + Ctrl+P + + + + + Find... + Rechercher... + + + + Find and Replace... + Chercher et remplacer... + + + + Print... + Imprimer... + + + + ExtendedTableWidget + + + Use as Exact Filter + Utiliser comme filtre exact + + + + Containing + Contenant + + + + Not containing + Ne contenant pas + + + + Not equal to + Différent de + + + + Greater than + Plus grand que + + + + Less than + Plus petit que + + + + Greater or equal + Plus grand ou égal à + + + + Less or equal + Plus petit ou égal à + + + + Between this and... + Entre ceci et... + + + + Regular expression + Expression régulière + + + + Edit Conditional Formats... + Éditer les formats conditionnels... + + + + Set to NULL + Définir comme NULL + + + + Cut + Couper + + + + Copy + Copier + + + + Copy with Headers + Copier avec les entêtes + + + + Copy as SQL + Copier comme du SQL + + + + Paste + Coller + + + + Print... + Imprimer... + + + + Use in Filter Expression + Utiliser dans l'expression du filtre + + + + Alt+Del + + + + + Ctrl+Shift+C + + + + + Ctrl+Alt+C + + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + Le contenu du presse-papier est plus grand que la plage sélectionnée. +Voulez-vous poursuivre l'insertion malgré tout ? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>Toutes les données n'ont pas été chargées. <b>Voulez-vous charger toutes les données avant de sélectionner toutes les lignes ? </b><p><p>Répondre <b>Non</b> signifie qu'aucune autre donnée ne sera chargée et que la sélection ne sera pas effectuée.<br/>Répondre <b>Oui</b> peut prendre un certain temps pendant le chargement des données mais la sélection sera complète.</p>Avertissement : Le chargement de toutes les données peut nécessiter une grande quantité de mémoire pour les grandes tables. + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + La sélection ne peut être à NULL. La colonne %1 à une contrainte NOT NULL. + + + + FileExtensionManager + + + File Extension Manager + Gestionnaire d'extension de fichier + + + + &Up + &Monter + + + + &Down + &Descendre + + + + &Add + &Ajouter + + + + &Remove + &Supprimer + + + + + Description + Description + + + + Extensions + Extensions + + + + *.extension + *.extension + + + + FilterLineEdit + + + Filter + Filtre + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + Ces champs de saisie vous permettent d'effectuer des filtres rapides dans le tableau actuellement sélectionné. +Par défaut, les lignes contenant le texte de saisie sont filtrées. +Les opérateurs suivants sont également pris en charge : +% Joker (métacaractère) +> Supérieur à +< Inférieur à +>= Supérieur ou égal à +<= Inférieur ou égal à += Égal à : correspondance exacte +<> Différent de: correspondance inverse exacte +x~y Fourchette : valeurs entre x et y +/regexp/ Valeurs correspondant à l'expression régulière + + + + Clear All Conditional Formats + Effacer tous les formats conditionnels + + + + Use for Conditional Format + Utiliser pour le format conditionnel + + + + Edit Conditional Formats... + Éditer un format conditionnel... + + + + Set Filter Expression + Définir l'expression du filtre + + + + What's This? + Qu'est-ce que c'est ? + + + + Is NULL + Est NULL + + + + Is not NULL + Est non NULL + + + + Is empty + Est vide + + + + Is not empty + Est non vide + + + + Not containing... + Ne contenant pas... + + + + Equal to... + Égal à... + + + + Not equal to... + Différent de... + + + + Greater than... + Plus grand que... + + + + Less than... + Plus petit que... + + + + Greater or equal... + Plus grand ou égal à... + + + + Less or equal... + Plus petit ou égal à... + + + + In range... + Peut être aussi traduit par "dans la plage..." ou "Entre..." + Entre les valeurs... + + + + Regular expression... + Expression régulière... + + + + FindReplaceDialog + + + Find and Replace + Chercher et remplacer + + + + Fi&nd text: + &Rechercher : + + + + Re&place with: + Re&mplacer avec : + + + + Match &exact case + &Expression exacte + + + + Match &only whole words + M&ots entiers uniquement + + + + When enabled, the search continues from the other end when it reaches one end of the page + Lorsque la Recherche circulaire est activée, la recherche recommence au début une fois la fin de la page atteinte + + + + &Wrap around + Recherche &circulaire + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + Lorsqu'elle est activée, la recherche s'effectue en remontant à partir de la position du curseur, sinon elle se fait en descendant + + + + Search &backwards + Rechercher vers le &haut + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>Lorsque cette case est cochée, la recherche ne se fait que dans la sélection actuelle.</p></body></html> + + + + &Selection only + &Sélection uniquement + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + La version française de https://en.wikibooks.org/wiki/Regular_Expressions n'existe pas + <html><head/><body><p>Lorsqu'elle est cochée, le motif à trouver est interprété comme une expression régulière UNIX. Voir <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + Use regular e&xpressions + Utiliser les e&xpressions régulières + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + Trouver l'occurrence suivante à partir de la position du curseur et dans la direction définie par "Rechercher vers le haut" + + + + &Find Next + &Suivant + + + + F3 + + + + + &Replace + Rem&placer + + + + Highlight all the occurrences of the text in the page + Surligner toutes les occurrences du texte dans la page + + + + F&ind All + Rechercher &tout + + + + Replace all the occurrences of the text in the page + Remplace toutes les occurrences du texte dans la page + + + + Replace &All + Remplacer to&ut + + + + The searched text was not found + Le texte recherché n'a pas été trouvé + + + + The searched text was not found. + Le texte recherché n'a pas été trouvé. + + + + The searched text was found one time. + Le texte recherché a été trouvé une fois. + + + + The searched text was found %1 times. + Le texte recherché a été trouvé %1 fois. + + + + The searched text was replaced one time. + Le texte recherché a été remplacé une fois. + + + + The searched text was replaced %1 times. + Le texte recherché a été remplacé %1 fois. + + + + ForeignKeyEditor + + + &Reset + &Réinitialiser + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + Clauses de clé étrangère (ON UPDATE, ON DELETE etc.) + + + + ImageViewer + + + Image Viewer + Visionneuse d'images + + + + Reset the scaling to match the original size of the image. + Réinitialise la mise à l'échelle pour qu'elle corresponde à la taille originale de l'image. + + + + Set the scaling to match the size of the viewport. + Régler l'échelle pour qu'elle corresponde à la taille de la fenêtre de visualisation. + + + + Print... + Imprimer... + + + + Open preview dialog for printing displayed image + Ouvrir un aperçu de l'image pour son impression + + + + Ctrl+P + Ctrl+P + + + + ImportCsvDialog + + + Import CSV file + Importer un fichier CSV + + + + Table na&me + No&m de la table + + + + &Column names in first line + Nom des &col. en 1ère ligne + + + + Field &separator + &Séparateur de champ + + + + , + , + + + + ; + ; + + + + + Tab + Tabulation + + + + | + | + + + + Other + Autre + + + + &Quote character + T&ype de guillemet + + + + + Other (printable) + Autre (imprimable) + + + + + Other (code) + Autre (code) + + + + " + " + + + + ' + ' + + + + &Encoding + &Encodage + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Trim fields? + Réduire les champs ? + + + + Separate tables + Tables distinctes + + + + Advanced + Avancé + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + Lorsque vous importez une valeur vide du fichier CSV dans une table existante avec une valeur par défaut pour cette colonne, cette valeur par défaut est insérée. Activez cette option pour insérer une valeur vide à la place. + + + + Ignore default &values + Ignorer les &valeurs par défaut + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + Activez cette option pour arrêter l'importation lorsque vous essayez d'importer une valeur vide dans une colonne NON NULL sans valeur par défaut. + + + + Fail on missing values + Erreur sur les valeurs manquantes + + + + Disable data type detection + Désactiver la détection du type de données + + + + Disable the automatic data type detection when creating a new table. + Désactive la détection automatique du type de données lors de la création d'une nouvelle table. + + + + Use local number conventions + Utiliser les conventions locales pour les nombres + + + + Use decimal and thousands separators according to the system locale. + Utiliser les séparateurs décimaux et de milliers en fonction des paramètres locaux du système. + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + Lors de l'importation dans une table existante possédant une clé primaire, des contraintes uniques ou un index unique, il y a un risque de conflit. Cette option vous permet de sélectionner une stratégie pour ce cas : Par défaut, l'importation est interrompue et annulée, mais vous pouvez également choisir d'ignorer et de ne pas importer les lignes en conflit ou de remplacer la ligne existante dans la table. + + + + Abort import + Abandonner l'import + + + + Ignore row + Ignorer l'enregistrement + + + + Replace existing row + Remplacer l'enregistrement existant + + + + Conflict strategy + En conflit avec la stratégie + + + + + Deselect All + Désélectionner tout + + + + Match Similar + 170726 MVT Has to be checked in real context or after explanation of this function. I suppose this function permits, with data names on the first line to "prefill a corresponding names" in an existing object ? + Appairer + + + + Select All + Sélectionner tout + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + Il existe déjà une table nommée '%1' et une importation dans une table existante n'est possible que si le nombre de colonnes correspond. + + + + There is already a table named '%1'. Do you want to import the data into it? + Il existe déjà une table appelée "%1". Voulez-vous y importer les données ? + + + + Creating restore point failed: %1 + La création du point de restauration a échoué : %1 + + + + Creating the table failed: %1 + La création de la table a échoué %1 + + + + importing CSV + Importer au format CSV + + + + Could not prepare INSERT statement: %1 + Impossible de préparer l'instruction INSERT : %1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + Fin de fichier inattendue. Veuillez vous assurer que vous avez configuré les bons guillemets et que le fichier n'est pas défectueux. + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + L'importation du fichier'%1' a pris %2 ms. %3 ms ont été utilisés par la fonction enregistrement. + + + + Inserting row failed: %1 + L'insertion de l'enregistrement a échoué : %1 + + + + MainWindow + + + toolBar1 + Barre d'outils1 + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + Attention : ce pragma n'est pas lisible et cette valeur a été déduite. Écrire le pragma pourrait écraser un LIKE redéfini fourni par une extension SQLite. + + + + Too&ls + &Outils + + + + Edit Database &Cell + Éditer le contenu d'une &cellule + + + + Opens the SQLCipher FAQ in a browser window + Ouvre la FAQ de SQLCipher dans la fenêtre d'un navigateur + + + + Export one or more table(s) to a JSON file + Exporter une ou plusieurs tables vers un fichier JSON + + + + DB Browser for SQLite + DB Browser for SQLite + + + + &File + &Fichier + + + + &Import + &Importer + + + + &Export + &Exporter + + + + &Edit + É&dition + + + + &View + &Vue + + + + &Help + &Aide + + + + User + Utilisateur + + + + Application + Application + + + + This button clears the contents of the SQL logs + Ce bouton supprime le contenu des logs SQL + + + + &Clear + &Effacer + + + + &New Database... + &Nouvelle base de données... + + + + + Create a new database file + Créer une nouvelle base de données + + + + This option is used to create a new database file. + Cette option est utilisée pour créer un nouveau fichier de base de données. + + + + Ctrl+N + + + + + + &Open Database... + &Ouvrir une base de données... + + + + + + + + Open an existing database file + Ouvre une base de données existante + + + + + + This option is used to open an existing database file. + Cette option est utilisée pour ouvrir une base de données existante. + + + + Ctrl+O + + + + + &Close Database + &Fermer la base de données + + + + This button closes the connection to the currently open database file + Ce bouton ferme la connexion à la base de données actuellement ouverte + + + + + Ctrl+W + + + + + &Revert Changes + &Annuler les modifications + + + + + Revert database to last saved state + Revenir à la dernière version sauvegardée de la base de données + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + Cette option permet de restaurer la base de données dans l'état de sa dernière sauvegarde. Tous les changements effectués depuis cette dernière sauvegarde seront perdus. + + + + &Undo + Ann&uler + + + + + Undo last change to the database + Annuler la dernière modification apportée à la base de données + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + Cette action annule la dernière modification apportée à la base de données dans le navigateur de bases de données ou dans l'onglet Exécuter le SQL. Il n'est pas possible d'annuler à nouveau. + + + + &Write Changes + Enregistrer les &modifications + + + + + Write changes to the database file + Enregistrer les modifications dans la base de données + + + + This option is used to save changes to the database file. + Cette option est utilisée pour enregistrer les modifications dans la base de données. + + + + Ctrl+S + + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + Ouvrir l'assistant de modification d'une table où il sera possible de renommer une table existante. Il est aussi possible d'ajouter ou de supprimer des champs de la table, tout comme modifier le nom des champs et leur type. + + + + Execute all/selected SQL + Exécuter tout ou seulement le SQL sélectionné + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + Ce bouton lance l'exécution des commandes SQL actuellement sélectionnées. Si aucun texte n'est sélectionné, toutes les commandes SQL seront exécutées. + + + + Ctrl+Shift+T + Ctrl+Maj+T + + + + Execute line + Exécuter la ligne + + + + &Wiki + &Wiki + + + + F1 + + + + + Bug &Report... + &Rapport d'erreur... + + + + Feature Re&quest... + &Demande de fonctionnalités... + + + + Web&site + &Site Internet + + + + &Donate on Patreon... + Faire une &donation sur Patreon... + + + + &Save Project + Enre&gistrer le projet + + + + Open &Project... + Ouvrir un &projet... + + + + Open &Project + Ouvrir un &projet + + + + &Attach Database... + Attac&her une base de données... + + + + + Add another database file to the current database connection + Ajouter un autre fichier de base de données à la connexion de la base de données en cours + + + + This button lets you add another database file to the current database connection + Ce bouton vous permet d'ajouter un autre fichier de base de données à la connexion de la base de données en cours + + + + &Set Encryption... + Chi&ffrer... + + + + SQLCipher &FAQ + &FAQ SQLCipher + + + + Table(&s) to JSON... + Table(&s) vers JSON... + + + + Open Data&base Read Only... + Ouvrir une base de données en &lecture seule... + + + + Ctrl+Shift+O + + + + + Save results + Enregistrer les résultats + + + + Save the results view + Enregistrer la vue des résultats + + + + This button lets you save the results of the last executed query + Ce bouton vous permet d'enregistrer les résultats de la dernière requête exécutée + + + + + Find text in SQL editor + Rechercher du texte dans l'éditeur SQL + + + + Find + Rechercher + + + + This button opens the search bar of the editor + Ce bouton ouvre la barre de recherche dans l'éditeur + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + Rechercher ou remplacer du texte dans l'éditeur SQL + + + + Find or replace + Chercher et remplacer + + + + This button opens the find/replace dialog for the current editor tab + Ce bouton ouvre la boîte de dialogue Rechercher/Remplacer pour l'onglet en cours de l'éditeur + + + + Ctrl+H + + + + + Export to &CSV + Exporter au format &CSV + + + + Export to &JSON + Exporter au format &JSON + + + + Save as &view + Enregistrer comme une &vue + + + + Save as view + Enregistrer comme une vue + + + + &Open Database + &Ouvrir une base de données + + + + Drag && Drop SELECT Query + Glisser && Déposer la requête SELECT + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + Lorsque vous faites glisser des champs d'une même table ou d'une table unique, déposez une requête SELECT dans l'éditeur + + + + Browse Table + Parcourir la table + + + + + Ctrl+Shift+W + Ctrl+Maj+W + + + + Table from CSV data in Clipboard... + Table depuis les données CSV du Presse-papiers... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + Cette opération traite le contenu actuel du presse-papiers comme un fichier CSV et ouvre le même assistant d'importation que celui utilisé pour importer des données CSV à partir d'un fichier. + + + + Show &Row Counts + Afficher le nomb&re de lignes + + + + This shows the number of rows for each table and view in the database. + Indique le nombre de lignes pour chaque table et vue de la base de données. + + + + Save Database &As... + Enregistrer la b&ase de données sous... + + + + Save the current database as a different file + Enregistrer la base de données en cours dans un autre fichier + + + + Refresh + Rafraîchir + + + + Reload the database structure + Recharger la structure de la base de données + + + + Shows or hides the Project toolbar. + Afficher ou masquer la barre d'outil Projet. + + + + Extra DB Toolbar + Extra DB Toolbar + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + Ce bouton vous permet d'enregistrer tous les paramètres associés à la base de données ouverte dans un fichier de projet DB Browser for SQLite + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + Structure de la base de &données + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + &Parcourir les données + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + Éditer les p&ragmas + + + + Temp Store + Stockage temporaire + + + + Secure Delete + Suppression sécurisée + + + + Case Sensitive Like + Uppercase LIKE (SQL language) + LIKE sensble à la casse + + + + Journal Mode + Mode de journal + + + + Journal Size Limit + Taille limite du journal + + + + Recursive Triggers + Uppercase TRIGGER (SQL language) + TRIGGERs récursifs + + + Delete + pragma + Supprimer + + + Truncate + pragma + Tronquer + + + Persist + pragma + Persister + + + Memory + pragma + Mémoire + + + Off + pragma + Désactivé + + + + Page Size + Taille de page + + + + Foreign Keys + Clés étrangères + + + + Auto Vacuum + Uppercase VACUUM (SQL language) + VACUUM automatique + + + + Max Page Count + Nombre maximum de pages + + + Normal + pragma + Normal + + + Exclusive + pragma + Exclusif + + + + Checkpoint Full FSYNC + Uppercase FULLSYNC (SQL language) + Checkpoint avec FULLFSYNC + + + + + Off + Désactivé + + + + + Normal + Normal + + + + + Full + Complète + + + + Default + Par défaut + + + + File + Fichier + + + + + Memory + Mémoire + + + + Delete + Supprimer + + + + Truncate + Tronquer + + + + Persist + Persister + + + + WAL + + + + + Exclusive + Exclusif + + + + Automatic Index + Index automatique + + + + Ignore Check Constraints + Ignorer les contraintes CHECK + + + + Full FSYNC + Uppercase FULLFSYNC (SQL language) + Utiliser FULLFSYNC + + + + WAL Auto Checkpoint + Pages du WAL avant checkpoint automatique + + + + User Version + Version utilisateur + + + + Synchronous + Synchronisation + + + + None + Aucun + + + + Incremental + Incrémental + + + + Locking Mode + Mode de verrouillage + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + E&xécuter le SQL + + + + &Recent Files + Fichiers &récents + + + + &New Database + &Nouvelle base de données + + + + This button lets you open a DB Browser for SQLite project file + Ce bouton vous permet d'ouvrir un fichier de projet DB Browser for SQLite + + + + New In-&Memory Database + Nouvelle base de données en &mémoire + + + + Drag && Drop Qualified Names + Glisser && Déposer les noms qualifiés + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + Utilisez des noms qualifiés (par ex. "Table", "Champ") lorsque vous faites glisser les objets et pour les déposez dans l'éditeur + + + + Drag && Drop Enquoted Names + Glisser && Déposer les noms indiqués + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + Utiliser les identificateurs par défaut (par ex. "Table1") lors du glisser-déposer des objets dans l'éditeur + + + + &Integrity Check + Vérifier l'&intégrité + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + Exécute le pragma integrity_check sur la base de données ouverte et retourne les résultats dans l'onglet Exécuter le SQL. Ce pragma effectue un contrôle d'intégrité de l'ensemble de la base de données. + + + + &Foreign-Key Check + Vérifier les clés &étrangères + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + Exécute le pragma foreign_key_check_check sur la base de données ouverte et retourne les résultats dans l'onglet Exécuter SQL + + + + &Quick Integrity Check + Vérification &rapide de l'intégrité + + + + Run a quick integrity check over the open DB + Effectuer un rapide contrôle d'intégrité sur la base de données ouverte + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + Exécute le pragma quick_check sur la base de données ouverte et retourne les résultats dans l'onglet Exécuter SQL. Cette commande effectue la plupart des vérifications de PRAGMA integrity_check mais s'exécute beaucoup plus rapidement. + + + + &Optimize + &Optimiser + + + + Attempt to optimize the database + Tente d'optimiser la base de données + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + Exécute le pragma d'optimisation sur la base de données ouverte. Ce pragma pourrait effectuer des optimisations qui amélioreront la performance des requêtes futures. + + + + + Print + Imprimer + + + + Print text from current SQL editor tab + Imprime le contenu de l'onglet en cours de l'éditeur SQL [Ctrl+P] + + + + Open a dialog for printing the text in the current SQL editor tab + Ouvre une boite de dialogue pour imprimer le contenu de l'onglet en cours de l'éditeur SQL + + + + Print the structure of the opened database + Imprime la structure de la base de données ouverte + + + + Open a dialog for printing the structure of the opened database + Ouvre une boite de dialogue pour imprimer la structure de la base de données ouverte + + + + &Save Project As... + Enr&egistrer le projet sous... + + + + + + Save the project in a file selected in a dialog + Enregistrer le projet dans un fichier sélectionné dans une boite de dialogue + + + + Save A&ll + Enregistrer &tout + + + + + + Save DB file, project file and opened SQL files + Enregistre la base de données, le fichier projet et les fichiers SQL ouverts + + + + Ctrl+Shift+S + + + + + Close Pro&ject + Fermer le pro&jet + + + + + Close project and database files and return to the initial state + Fermer les fichiers du projet et de la base de données et revenir à l'état initial + + + + Ctrl+Shift+F4 + Ctrl+Maj+F4 + + + + + Detach Database + Détacher une base de données + + + + + Detach database file attached to the current database connection + Détacher le fichier de base de données attaché à la connexion actuelle à la base de données + + + + Compact the database file, removing space wasted by deleted records + Compacter la base de donnée, récupérer l'espace perdu par les enregistrements supprimés + + + + + Compact the database file, removing space wasted by deleted records. + Compacter la base de donnée, récupérer l'espace perdu par les enregistrements supprimés. + + + + E&xit + &Quitter + + + + Ctrl+Q + + + + + Import data from an .sql dump text file into a new or existing database. + Importer les données depuis un fichier SQL résultant d'un vidage (sql dump) dans une nouvelle base de données ou une base existante. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + Cette option vous permet d'importer un fichier SQL de vidage d'une base de données (SQL dump) dans une nouvelle base de données ou une base existante. Ce fichier peut être créé par la plupart des moteurs de base de données, y compris MySQL et PostgreSQL. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Ouvrir un assistant vous permettant d'importer des données dans une table de la base de données à partir d'un fichier texte séparé par des virgules (csv). + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Ouvre un assistant vous permettant d'importer des données dans une table de la base de données à partir d'un fichier texte séparé par des virgules (csv). Les fichiers CSV peuvent être créés par la plupart des outils de gestion de base de données et les tableurs. + + + + Export a database to a .sql dump text file. + Exporter la base de données vers un fichier de vidage SQL (SQL dump) au format texte. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + Exporter la base de données vers un fichier de vidage SQL (SQL dump) au format texte. Ce fichier (SQL dump) contient toutes les informations nécessaires pour recréer une base de données par la plupart des moteurs de base de données, y compris MySQL et PostgreSQL. + + + + Export a database table as a comma separated text file. + Exporter la table vers un fichier texte séparé par des virgules (CSV). + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + Exporter la table vers un fichier texte séparé par des virgules (CSV), prêt à être importé dans une autre base de données ou un tableur. + + + + &Create Table... + &Créer une table... + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Ouvrir l'assistant de création d'une table dans lequel il sera possible de définir les noms et les champs d'une nouvelle table dans la base de données + + + + &Delete Table... + &Supprimer la table... + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Ouvrir l'assistant de suppression d'une table avec lequel vous pourrez sélectionner la table à supprimer. + + + + &Modify Table... + &Modifier la table... + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + Ouvrir l'assistant de création d'un index avec lequel il sera possible de définir un nouvel index dans une table préexistante de la base de données. + + + + &Preferences... + &Préférences... + + + + + Open the preferences window. + Ouvrir la fenêtre des préférences. + + + + &DB Toolbar + &Barre d'outils BDD + + + + Shows or hides the Database toolbar. + Affiche ou masque la barre d'outils Base de données. + + + + Shift+F1 + + + + + &Recently opened + Ouvert &récemment + + + + Ctrl+T + + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + Ceci est la structure de la base de données ouverte. +Vous pouvez faire glisser plusieurs noms d'objets de la colonne Nom et les déposer dans l'éditeur SQL et vous pouvez ajuster les propriétés des noms déposés en utilisant le menu contextuel. Cela pourrait vous aider à composer des instructions SQL. +Vous pouvez faire glisser les instructions SQL de la colonne Schéma et les déposer dans l'éditeur SQL ou dans d'autres applications. + + + + + + Project Toolbar + Barre d'outil Projet + + + + Extra DB toolbar + Extra DB Toolbar + + + + + + Close the current database file + Fermer la base de données en cours + + + + + Ctrl+F4 + + + + + Compact &Database... + Compacter la base de &données... + + + + &About + À &propos + + + + This button opens a new tab for the SQL editor + Ce bouton ouvre un nouvel onglet dans l'éditeur SQL + + + + &Execute SQL + &Exécuter le SQL + + + + + Save the current session to a file + Enregistrer la session courante dans un fichier + + + + + Load a working session from a file + Charger une session de travail depuis un fichier + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + Ceci est la structure de la base de données ouverte. +Vous pouvez faire glisser les instructions SQL d'une ligne d'objet et les déposer dans d'autres applications ou dans une autre instance de 'DB Browser for SQLite'. + + + + + Error Log + Journal des erreurs + + + + Un/comment block of SQL code + Dé/commenter un bloc de code SQL + + + + Un/comment block + Dé/commenter un bloc + + + + Comment or uncomment current line or selected block of code + Commenter ou décommenter la ligne actuelle ou le bloc de code sélectionné + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + Commenter ou décommenter les lignes sélectionnées ou la ligne en cours, lorsqu'il n'y a pas de sélection. Tout le bloc est basculé en fonction de la première ligne. + + + + Ctrl+/ + + + + + Stop SQL execution + Arrête l'exécution du SQL + + + + Stop execution + Arrêter l'exécution + + + + Stop the currently running SQL script + Arrête le script SQL en cours d'exécution + + + + DB Toolbar + Barre d'outils BDD + + + + SQL &Log + &Journal SQL + + + + Show S&QL submitted by + A&fficher le SQL soumis par + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + Ce panneau vous permet d'examiner un journal de toutes les commandes SQL émises par l'application ou par vous-même + + + + &Plot + Gra&phique + + + + DB Sche&ma + DB Sche&ma + + + + &Remote + Serveur &distant + + + + &Database from SQL file... + &Base de données à partir du fichier SQL... + + + + &Table from CSV file... + &Table depuis un fichier CSV... + + + + &Database to SQL file... + Base de &données vers un fichier SQL... + + + + &Table(s) as CSV file... + &Table vers un fichier CSV... + + + + Create &Index... + Créer un &index... + + + + W&hat's This? + &Qu'est-ce que c'est ? + + + + New &tab + Nouvel ongle&t + + + + Open SQL file(s) + Ouvrir un fichier SQL + + + + This button opens files containing SQL statements and loads them in new editor tabs + Ce bouton ouvre un fichier contenant des instructions SQL et le charge dans un nouvel onglet de l'éditeur + + + + + + Save SQL file + Enregistrer le fichier SQL + + + + &Load Extension... + Charger l'&extension... + + + + + Execute current line + Exécuter la ligne courante (Maj+F5) + + + + This button executes the SQL statement present in the current editor line + Ce bouton exécute l'instruction SQL présente dans la ligne courante de l'éditeur + + + + Shift+F5 + + + + + Sa&ve Project + Enre&gistrer le projet + + + + + Save SQL file as + Enregistrer le fichier SQL comme + + + + This button saves the content of the current SQL editor tab to a file + Ce bouton enregistre le contenu de l'onglet actuel de l'éditeur SQL dans un fichier + + + + &Browse Table + &Parcourir la table + + + + Copy Create statement + Copier l'instruction CREATE + + + + Copy the CREATE statement of the item to the clipboard + Copie l'instruction CREATE de cet item dans le presse-papier + + + + Open an existing database file in read only mode + Ouvrir une base de données existante en lecture seule + + + + Ctrl+E + + + + + Export as CSV file + Exporter les données au format CSV + + + + Export table as comma separated values file + Exporter la table vers un fichier texte séparé par des virgules (CSV) + + + + Ctrl+L + + + + + + Ctrl+P + + + + + Database encoding + Encodage de la base de données + + + + + Choose a database file + Choisir une base de données + + + + Ctrl+Return + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Reset Window Layout + Rétablir la disposition des fenêtres + + + + The database is currently busy. + La base de données est actuellement occupée. + + + + Click here to interrupt the currently running query. + Cliquez ici pour interrompre la requête en cours. + + + + Encrypted + Chiffré + + + + Database is encrypted using SQLCipher + La base de données a été chiffrée avec SQLCipher + + + + Read only + Lecture seule + + + + Database file is read only. Editing the database is disabled. + La base de données est ouverte en lecture seule. Il n'est pas possible de la modifier. + + + + Could not open database file. +Reason: %1 + La base de données ne peut être ouverte. +Motif : %1 + + + + + + Choose a filename to save under + Choisir un nom de fichier pour enregistrer sous + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + Erreur lors de l'enregistrement de la base de données. Les changements n'ont pas tous été sauvegardés. Vous devez corriger au préalable l'erreur suivante : + +%1 + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + Voulez-vous enregistrer les modifications apportées aux onglets SQL dans le fichier du projet '%1' ? + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + Une nouvelle version de DB Browser for SQLite est disponible (%1.%2.%3).<br/><br/>Vous pouvez la télécharger sur <a href='%4'>%4</a>. + + + + DB Browser for SQLite project file (*.sqbpro) + Fichier de projet DB Browser for SQLite (*.sqbpro) + + + + Error checking foreign keys after table modification. The changes will be reverted. + Erreur de vérification des clés étrangères après modification de la table. Les modifications seront annulées. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + Cette table n'a pas passé avec succès un contrôle de clé étrangère.<br/>Vous devez exécuter l'Outil | Contrôle des clés étrangères' et corriger les problèmes rapportés. + + + + Execution finished with errors. + L'exécution s'est terminée avec des erreurs. + + + + Execution finished without errors. + L'exécution s'est terminée sans erreur. + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + Êtes-vous sûr de vouloir annuler tous les changements effectués dans la base de données %1 depuis la dernière sauvegarde ? + + + + Choose a file to import + Choisir un fichier à importer + + + + Text files(*.sql *.txt);;All files(*) + Fichiers texte (*.sql *.txt);;Tous les fichiers(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + Voulez vous créer une nouvelle base de donnée pour gérer les données importées ? +Si vous répondez non, nous essaierons d'importer les données du fichier SQL dans la base de données courante. + + + + Ctrl+Tab + Ctrl+Tab + + + + Ctrl+Shift+Tab + Ctrl+Maj+Tab + + + + Clear List + Effacer la liste + + + + Window Layout + Disposition des fenêtres + + + + Simplify Window Layout + Simplifier la disposition des fenêtres + + + + Alt+Shift+0 + Maj+Alt+0 + + + + Dock Windows at Bottom + Ancrer les fenêtres en bas + + + + Dock Windows at Left Side + Ancrer les fenêtres à gauche + + + + Dock Windows at Top + Ancrer les fenêtres en haut + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + Des traitements SQL sont en cours d'exécution. Fermer la base de données maintenant arrêtera ces traitements. Cela risque de laisser la base de données dans un état incohérent. Êtes-vous sûr de vouloir fermer la base de données ? + + + + Do you want to save the changes made to the project file '%1'? + Voulez-vous enregistrer les changements effectués dans le fichier projet '%1' ? + + + + File %1 already exists. Please choose a different name. + Le fichier %1 existe déjà. Veuillez choisir un nom de fichier différent. + + + + Error importing data: %1 + Erreur lors de l'import des données : %1 + + + + Import completed. + Import terminé. + + + + Delete View + Supprimer la vue + + + + Delete Trigger + Supprimer le déclencheur + + + + Delete Index + Supprimer l'index + + + + + Delete Table + Supprimer la table + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + Paramétrer les valeurs du PRAGMA enregistrera les actions de votre transaction courante. +Êtes-vous sûr ? + + + + In-Memory database + Base de données en mémoire + + + + Automatically load the last opened DB file at startup + Au démarrage, rouvrir la dernière base de données utilisée + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + Êtes-vous sûr de vouloir supprimer la table %1 ? +Toutes les données de la table seront perdues. + + + + Are you sure you want to delete the view '%1'? + Êtes-vous sûr de vouloir supprimer la vue %1 ? + + + + Are you sure you want to delete the trigger '%1'? + Êtes-vous sûr de vouloir supprimer le déclencheur %1 ? + + + + Are you sure you want to delete the index '%1'? + Êtes-vous sûr de vouloir supprimer l'index %1 ? + + + + Error: could not delete the table. + Erreur : suppression de la table impossible. + + + + Error: could not delete the view. + Erreur : suppression de la vue impossible. + + + + Error: could not delete the trigger. + Erreur : suppression du déclencheur impossible. + + + + Error: could not delete the index. + Erreur : suppression de l'index impossible. + + + + Message from database engine: +%1 + Message depuis le moteur de la base de données : +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + La modification de la table nécessite d'enregistrer toutes les modifications en attente maintenant. +Êtes-vous sûr de vouloir enregistrer la base de données ? + + + + Edit View %1 + Éditer la vue %1 + + + + Edit Trigger %1 + Éditer le déclencheur %1 + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + Vous avez des instructions SQL en cours d'exécution. Voulez-vous les arrêter afin d'exécuter les instructions en cours à la place ? Cela pourrait laisser la base de données dans un état incohérent. + + + + -- EXECUTING SELECTION IN '%1' +-- + -- EXÉCUTION DE LA SELECTION DANS '%1' +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- EXÉCUTION DE LA LIGNE DANS '%1' +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- EXÉCUTER TOUT DANS '%1' +-- + + + + + At line %1: + À la ligne %1 : + + + + Result: %1 + Résultat : %1 + + + + Result: %2 + Résultat : %2 + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + Le réglage des valeurs PRAGMA ou du "vacuuming" validera votre transaction en cours. +Êtes-vous sûr ? + + + + Opened '%1' in read-only mode from recent file list + Ouverture de '%1' en lecture seule depuis la liste des fichiers récents + + + + Opened '%1' from recent file list + Ouverture de '%1' depuis la liste des fichiers récents + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + Sélectionnez l'action à appliquer au fichier déposé.<br>Note : seule l'action "Importer" permet de traiter plus d'un fichier. + Sélectionnez l'action à appliquer aux fichiers déposés.<br>Note : seule l'action "Importer" permet de traiter plus d'un fichier. + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + Les traitements de l'onglet '%1' sont toujours en cours d'exécution. La fermeture de l'onglet arrêtera l'exécution. Cela pourrait laisser la base de données dans un état incohérent. Êtes-vous sûr de vouloir fermer l'onglet ? + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + Ce fichier de projet utilise un ancien format de fichier car il a été créé à l'aide de DB Browser for SQLite version 3.10 ou inférieure. Le chargement de ce format de fichier n'est plus entièrement pris en charge. Si vous souhaitez le charger complètement, veuillez utiliser DB Browser for SQLite version 3.12 pour le convertir au nouveau format de fichier. + + + + Project saved to file '%1' + Projet enregistré dans le fichier '%1' + + + + Yes. Don't ask again + Oui. Ne plus demander + + + + This action will open a new SQL tab with the following statements for you to edit and run: + Need to verify if following statements ore shown bellow ou above or on the open action + Cette action ouvrira un nouvel onglet SQL avec les instructions suivantes que vous pourrez modifier et exécuter : + + + + Rename Tab + Renommer l'onglet + + + + Duplicate Tab + Dupliquer l'onglet + + + + Close Tab + Fermer l'onglet + + + + Opening '%1'... + Ouverture de '%1'... + + + + There was an error opening '%1'... + Il y a eu une erreur lors de l'ouverture de '%1'... + + + + Value is not a valid URL or filename: %1 + Le valeur n'est pas une URL valide ou un nom de fichier : %1 + + + + %1 rows returned in %2ms + %1 enregistrements ramenés en %2ms + + + + Ctrl+0 + Ctrl+0 + + + + Alt+Shift+W + Alt+Shift+W + + + + Choose a database file to save under + Choisissez un fichier de base de donnés pour enregistrer sous + + + + Error while saving the database to the new file. + Erreur lors de l'enregistrement de la base de données dans le nouveau fichier. + + + + Choose text files + Choisir des fichiers texte + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + Importation terminée. Certaines contraintes clés étrangères sont violées. Veuillez les corriger avant de les enregistrer. + + + + Modify View + Modifier la vue + + + + Modify Trigger + Modifier le déclencheur + + + + Modify Index + Modifier l'index + + + + Modify Table + Modifier la table + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (lecture seule) + + + + Open Database or Project + Ouvrir une base de données ou un projet + + + + Attach Database... + Attacher une base de données... + + + + Import CSV file(s)... + Importer un ou des fichiers CSV... + + + + Do you want to save the changes made to SQL tabs in a new project file? + Voulez-vous enregistrer les changements effectués dans l'onglet SQL dans un nouveau fichier projet ? + + + + Do you want to save the changes made to the SQL file %1? + Voulez-vous enregistrer les changements effectués dans le fichier SQL %1 ? + + + + Select SQL file to open + Sélectionner un fichier SQL à ouvrir + + + + Select file name + Sélectionner un nom de fichier + + + + Select extension file + Sélectionner une extension de fichier + + + + Extension successfully loaded. + L'extension a été chargée avec succès. + + + + Error loading extension: %1 + Erreur lors du chargement de l'extension %1 + + + + Could not find resource file: %1 + Le fichier de ressources %1 ne peut être ouvert + + + + + Don't show again + Ne plus afficher + + + + New version available. + Une nouvelle version est disponible. + + + + Choose a project file to open + Choisir un fichier de projet à ouvrir + + + + DB file '%1' could not be opened + Le fichier DB '%1' n'a pu être ouvert + + + + Table '%1' not found; settings ignored + Table "%1" introuvable ; paramètres ignorés + + + + Could not open project file for writing. +Reason: %1 + Le fichier projet ne peut être ouvert en écriture. +Raison : %1 + + + + -- Reference to file "%1" (not supported by this version) -- + -- Référence au fichier "%1" (non supporté par cette version) -- + + + + Collation needed! Proceed? + Classement nécessaire ! Continuer ? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + Une table de cette base de données nécessite la fonction spéciale de classement '%1' que cette application ne peut fournir sans connaissances complémentaires. +Si vous choisissez de continuer, ayez à l'esprit que des choses non souhaitées peuvent survenir dans votre base de données. +Faites une sauvegarde ! + + + + creating collation + Créer un classement + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + Définissez un nouveau nom pour l'onglet SQL. Utilisez le caractère '&&' pour permettre d'utiliser le caractère suivant comme raccourci clavier. + + + + Please specify the view name + Veuillez spécifier le nom de la vue + + + + There is already an object with that name. Please choose a different name. + Il existe déjà un objet avec ce nom. Veuillez choisir un autre nom. + + + + View successfully created. + La vue a été crée avec succès. + + + + Error creating view: %1 + Erreur lors de la création de la vue : %1 + + + + This action will open a new SQL tab for running: + Cette action ouvrira un nouvel onglet SQL pour son exécution : + + + + Press Help for opening the corresponding SQLite reference page. + Cliquez sur Aide pour ouvrir la page de référence correspondante de SQLite. + + + + Busy (%1) + Occupé (%1) + + + + NullLineEdit + + + Set to NULL + Définir comme NULL + + + + Alt+Del + + + + + PlotDock + + + Plot + Graphique + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>Ce volet affiche la liste des colonnes de la table actuellement parcourue ou de la requête qui vient d'être exécutée. Vous pouvez sélectionner les colonnes que vous voulez utiliser comme axe X ou Y pour le volet de tracé ci-dessous. Le tableau montre le type d'axe détecté qui affectera le tracé résultant. Pour l'axe Y, vous ne pouvez sélectionner que des colonnes numériques, mais pour l'axe X, vous pourrez sélectionner&nbsp;:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Heure</span>&nbsp;: chaînes au format &quot;aaaa-MM-jj hh:mm:ss&quot; ou &quot;aaaa-MM-jjThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>&nbsp;: chaînes au format &quot;aaaa-MM-jj&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Heures</span>&nbsp;: chaînes au format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>&nbsp;: autres formats de chaînes. Sélectionner cette colonne comme axe X produira un diagramme en barres avec les valeurs de la colonne comme étiquettes pour les barres</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numerique</span>&nbsp;: Nombres entiers ou Réels</li></ul><p>En double-cliquant sur une cellule Y, vous pouvez changer la couleur utilisée dans le graphique.</p></body></html> + + + + Columns + Colonnes + + + + X + X + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + Type d'axe + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + Voici le graphique qui sera dessiné lorsque vous sélectionnerez les valeurs x et y ci-dessus. + +Cliquez sur les points pour les sélectionner dans le graphique et dans le tableau. Ctrl+Clic pour sélectionner une plage de points. + +Utilisez la molette de la souris pour zoomer et faites glisser la souris pour modifier la plage des axes. + +Sélectionnez les axes ou les étiquettes d'axes à faire glisser et à zoomer uniquement dans cette orientation. + + + + Line type: + Type de ligne : + + + + + None + Aucun + + + + Line + Ligne + + + + StepLeft + À gauche + + + + StepRight + À droite + + + + StepCenter + Centré + + + + Impulse + Impulsion + + + + Point shape: + Forme du point : + + + + Cross + Croix + + + + Plus + Plus + + + + Circle + Cercle + + + + Disc + Disque + + + + Square + Carré + + + + Diamond + Diamant + + + + Star + Étoile + + + + Triangle + Triangle + + + + TriangleInverted + Triangle inversé + + + + CrossSquare + Carré et Croix + + + + PlusSquare + Carré et Plus + + + + CrossCircle + Cercle et Croix + + + + PlusCircle + Cercle et Plus + + + + Peace + Paix + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>Enregistrer le graphique actuel...</p><p>Choisir le format de fichier parmi ces extensions (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + Enregistrer le tracé actuel... + + + + + Load all data and redraw plot + Charger toutes les données et redessiner le graphique + + + + + + Row # + # Ligne + + + + Copy + Copier + + + + Print... + Imprimer... + + + + Help + + + + + Show legend + Afficher la légende + + + + Stacked bars + Diagramme à barres empilées + + + + Fixed number format + Format des nombres fixes + + + + Date/Time + Date/Heure + + + + Date + Date + + + + Time + Heure + + + + + Numeric + Numérique + + + + Label + Label + + + + Invalid + Invalide + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + Charger toutes les données et redessiner le tracé. +Attention : toutes les données n'ont pas encore été extraites du tableau en raison du mécanisme d'extraction partielle. + + + + Choose an axis color + Choisir une couleur d'axe + + + + Choose a filename to save under + Choisir un nom de fichier pour enregistrer sous + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + Il y a des courbes dans ce graphique et le style de ligne sélectionné ne peut être appliqué qu'aux graphiques triés par X. Triez la table ou la requête par X pour supprimer les courbes ou sélectionnez un des styles pris en charge par les courbes : Aucun ou Ligne. + + + + Loading all remaining data for this table took %1ms. + Le chargement de toutes les données restantes pour ce tableau a pris %1 ms. + + + + PreferencesDialog + + + Preferences + Préférences + + + + &General + &Général + + + + Remember last location + Se souvenir du dernier emplacement + + + + Always use this location + Toujours utiliser cet emplacement + + + + Remember last location for session only + Dernier emplac. pour cette session uniquement + + + + Lan&guage + Lan&gue + + + + Show remote options + Afficher options serv. distant + + + + Automatic &updates + Mises à jour a&utomatiques + + + + &Database + Base de &Données + + + + Database &encoding + &Encodage de la base de données + + + + Open databases with foreign keys enabled. + Ouvrir une base de données en activant les clés étrangères. + + + + &Foreign keys + &Clés étrangères + + + + + + + + + + + + + + enabled + Autoriser + + + + Default &location + Emp&lacement par défaut + + + + + + ... + ... + + + + Remove line breaks in schema &view + Suppr. les sauts de ligne dans la &vue du schéma + + + + Prefetch block si&ze + &Taille du bloc de préfetch + + + + SQ&L to execute after opening database + Fichier SQ&L à exécuter à l'ouverture +de la base de données + + + + Default field type + Type de champ par défaut + + + + Data &Browser + &Navigateur des données + + + + Font + Police + + + + &Font + &Police + + + + Content + Contenu + + + + Symbol limit in cell + Texte : Nb. max. de caractères + + + + NULL + NULL + + + + Regular + Standard + + + + Binary + Binaire + + + + Background + Arrière plan + + + + Filters + Filtres + + + + Threshold for completion and calculation on selection + Seuil d'achèvement et calcul lors de la sélection + + + + Show images in cell + Afficher les images dans la cellule + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + Activez cette option pour afficher un aperçu des BLOBs contenant des images dans les cellules. Cela peut toutefois affecter les performances du navigateur de données. + + + + Escape character + Caractère d'échappement + + + + Delay time (&ms) + Délai (&ms) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + Définit le temps d'attente avant qu'une nouvelle valeur de filtre est appliquée. Peut être renseigné à 0 pour supprimer le temps d'attente. + + + + &SQL + &SQL + + + + Context + Contexte + + + + Colour + Couleur + + + + Bold + Gras + + + + Italic + Italique + + + + Underline + Souligné + + + + Keyword + Mot clé + + + + Function + Fonction + + + + Table + Table + + + + Comment + Commentaire + + + + Identifier + Identifiant + + + + String + Chaîne de caractères + + + + Current line + Ligne courante + + + + SQL &editor font size + &Taille de la police : Éditeur SQL + + + + Tab size + Largeur de tabulation + + + + SQL editor &font + &Police de l'éditeur SQL + + + + Error indicators + Indicateur d'erreur + + + + Hori&zontal tiling + Division hori&zontale + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + Si elle est activée, l'éditeur de code SQL et l'affichage du tableau de résultats sont présentés côte à côte au lieu d'être l'un sur l'autre. + + + + Code co&mpletion + Co&mplétion de code + + + + Toolbar style + Style de la barre d'outil + + + + + + + + Only display the icon + Afficher uniquement les icones + + + + + + + + Only display the text + Afficher uniquement le texte + + + + + + + + The text appears beside the icon + Le texte sera affiché à côté des icones + + + + + + + + The text appears under the icon + Le texte sera affiché sous les icones + + + + + + + + Follow the style + Suivre le style + + + + DB file extensions + Extensions de fichiers DB + + + + Manage + Gestion + + + + Main Window + Fenêtre principale + + + + Database Structure + Structure de la base de données + + + + Browse Data + Parcourir les données + + + + Execute SQL + Exécuter le SQL + + + + Edit Database Cell + Éditer le contenu d'une cellule de la BDD + + + + When this value is changed, all the other color preferences are also set to matching colors. + Lorsque cette valeur est modifiée, toutes les autres préférences de couleur sont également réglées sur les couleurs correspondantes. + + + + Follow the desktop style + Suit le style du bureau + + + + Dark style + Style sombre + + + + Application style + Style de l'application + + + + This sets the font size for all UI elements which do not have their own font size option. + Définit la taille de la police pour tous les éléments de l'interface utilisateur qui n'ont pas leur propre option de taille de police. + + + + Font size + Taille de police + + + + Max Recent Files + Nb. max. fichiers récents + + + + Prompt to save SQL tabs +in new project file + Invite à sauvegarder les onglets SQL +dans un nouveau fichier de projet + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + Si cette option est activée, les modifications apportées à l'éditeur SQL génèrent une boîte de dialogue de confirmation de l'enregistrement du projet lors de la fermeture de l'onglet de l'éditeur SQL. + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + Lorsque cette option est activée, les sauts de ligne de la colonne Schéma de l'onglet Structure de la base de données, du dock et de la sortie imprimée sont supprimés. + + + + Database structure font size + Taille de la police pour la structure de la base de données + + + + Font si&ze + T&aille de police + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + Il s'agit du nombre maximum d'éléments autorisés pour l'activation de certaines fonctionnalités coûteuses en termes de calcul : +Nombre maximal de lignes dans un tableau pour permettre la complétion des valeurs sur la base des valeurs actuelles de la colonne. +Nombre maximum d'index dans une sélection pour le calcul de la somme et de la moyenne. +Peut être fixé à 0 pour la désactivation des fonctionnalités. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + Il s'agit du nombre maximum de lignes dans une table pour permettre la complétion de la valeur en fonction des valeurs actuelles dans la colonne. +Peut être mis à 0 pour désactiver la complétion. + + + + Field display + Affichage des champs + + + + Light style + Style clair + + + + Displayed &text + &Texte affiché + + + + Formatted + Formaté + + + + + + + + + + + Click to set this color + Cliquez pour définir cette couleur + + + + Text color + Couleur de texte + + + + Background color + Couleur d'arrière plan + + + + + Preview only (N/A) + Préaffichage uniquement (N/A) + + + + Foreground + Avant-plan + + + + Selection background + Sélection de l'arrière-plan + + + + Selection foreground + Sélection de l'avant-plan + + + + Highlight + Souligner + + + + SQL &results font size + Taille police &résultats SQL + + + + Use tabs for indentation + Utiliser les tabulations pour l'indentation + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + Lorsqu'elle est activée, la touche Tab insère des caractères de tabulation et d'espacement pour l'indentation. Dans le cas contraire, seuls les espaces seront utilisés. + + + + &Wrap lines + &Retour à la ligne + + + + Never + Jamais + + + + At word boundaries + Aux limites des mots + + + + At character boundaries + Aux limites des caractères + + + + At whitespace boundaries + Aux limites des espaces + + + + &Quotes for identifiers + &Guillemets pour les identifiants + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + Choisissez le système de guillemets utilisés par l'application pour les identificateurs dans le code SQL. + + + + "Double quotes" - Standard SQL (recommended) + "Double guillemet" - Standard SQL (recommandé) + + + + `Grave accents` - Traditional MySQL quotes + `Accent Grave` - Guillemets standards MySQL + + + + [Square brackets] - Traditional MS SQL Server quotes + [Crochets] - Guillemets traditionnels de MS SQL Server + + + + Keywords in &UPPER CASE + Mots clé en &MAJUSCULES + + + + When set, the SQL keywords are completed in UPPER CASE letters. + Si cette case est cochée, les mots clé SQL sont transformés en MAJUSCULES. + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + Si cette option est activée, les lignes de code SQL qui ont causé des erreurs lors de la dernière exécution sont mises en surbrillance et le cadre des résultats indique l'erreur en arrière-plan + + + + Close button on tabs + Bouton de fermeture des onglets + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + Si cette option est activée, les onglets de l'éditeur SQL comporteront un bouton de fermeture. Dans tous les cas, vous pouvez utiliser le menu contextuel ou le raccourci clavier pour les fermer. + + + + &Extensions + E&xtensions + + + + Select extensions to load for every database: + Sélectionner les extensions à charger pour toutes les bases de données : + + + + Add extension + Ajouter une extension + + + + Remove extension + Enlever une extension + + + + Select built-in extensions to load for every database: + Sélectionner les extensions intégrées à charger pour toutes les bases de données : + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>Bien que SQLite supporte l'opérateur REGEXP, aucun algorithme<br>d'expression régulière n'est implémenté : l'application doit fournir le sien. DB Browser for SQLite implémente<br/>cet algorithme pour vous permettre d'utiliser REGEXP. Cependant, comme il existe plusieurs implémentations possibles<br/>et que vous souhaitez peut-être utiliser autre chose, vous êtes libre de désactiver cette implémentation dans l'application<br/>pour utiliser la vôtre en utilisant une extension. Cela nécessite le redémarrage de l'application.</p></body></html> + + + + Disable Regular Expression extension + Désactiver l'extension "Expression Régulière" + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite fournit une fonction SQL pour charger des extensions à partir d'un fichier de bibliothèque partagé. Activez cette option si vous souhaitez utiliser la fonction <span style=" font-style:italic;">load_extension()</span> depuis le code SQL.</p><p>Pour des raisons de sécurité, le chargement des extensions est désactivé par défaut et doit être activé par ce paramètre. Vous pouvez toujours charger des extensions via l'interface graphique, même si cette option est désactivée.</p></body></html> + + + + Allow loading extensions from SQL code + Autoriser le chargement des extensions depuis le code SQL + + + + Remote + Serveur distant + + + + CA certificates + Certificats CA + + + + Proxy + Proxy + + + + Configure + Configurer + + + + Export Settings + Exporter les paramètres + + + + Import Settings + Importer les paramètres + + + + + Subject CN + Sujet CN + + + + Common Name + Nom Commun - CN + + + + Subject O + Sujet O + + + + Organization + Organisation + + + + + Valid from + Valide de + + + + + Valid to + Valide jusqu'à + + + + + Serial number + Numéro de série + + + + Your certificates + Vos certificats + + + + File + Fichier + + + + Subject Common Name + Sujet Common Name + + + + Issuer CN + Émetteur CN + + + + Issuer Common Name + + + + + Clone databases into + Cloner la base de données dans + + + + + Choose a directory + Choisir un répertoire + + + + + The language will change after you restart the application. + La langue ne changera qu'après le redémarrage de l'application. + + + + Select extension file + Sélectionner un fichier d'extension + + + + Extensions(*.so *.dylib *.dll);;All files(*) + Extensions (*.so *.dylib *.dll);;Tous les fichiers (*) + + + + Import certificate file + Importer un fichier de certificat + + + + No certificates found in this file. + Aucun certificat n'a été trouvé dans ce fichier. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + Êtes-vous sûr de vouloir supprimer ce certificat ? Toutes les données de ce certificat seront supprimées des paramètres de l'application! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + Êtes-vous sûr de vouloir effacer tous les réglages sauvegardés ? +Toutes vos préférences seront perdues et les valeurs par défaut seront utilisées. + + + + Save Settings File + Enregistrer le fichier de paramètres + + + + + Initialization File (*.ini) + Fichier d'initialisation (*.ini) + + + + The settings file has been saved in location : + + Le fichier de paramètres a été enregistré à l'emplacement : + + + + Open Settings File + Ouvrir le fichier de paramètres + + + + The settings file was loaded properly. + Le fichier de configuration a été chargé correctement. + + + + The selected settings file is not a normal settings file. +Please check again. + Le fichier de paramètres sélectionné n'est pas un fichier de paramètres normal. +Veuillez vérifier à nouveau. + + + + ProxyDialog + + + Proxy Configuration + Configuration du proxy + + + + Pro&xy Type + Type de pro&xy + + + + Host Na&me + No&m de l'hôte + + + + Port + Port + + + + Authentication Re&quired + Authentification re&quise + + + + &User Name + Nom d'&utilisateur + + + + Password + Mot de passe + + + + None + Aucun + + + + System settings + Paramètres système + + + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 + + + + QObject + + + Error importing data + Erreur lors de l'import des données + + + + from record number %1 + pour l'enregistrement numéro %1 + + + + . +%1 + . +%1 + + + + Importing CSV file... + Import du fichier CSV... + + + + Cancel + Annuler + + + + All files (*) + Tous les fichiers (*) + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + Base de données SQLite (*.db *.sqlite *.sqlite3 *.db3) + + + + Left + Gauche + + + + Right + Droite + + + + Center + Centré + + + + Justify + Justifié + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + Fichier de BDD SQLite (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + Fichiers projet DB Browser for SQLite (*.sqbpro) + + + + SQL Files (*.sql) + Fichiers SQL (*.sql) + + + + All Files (*) + Tous les fichiers (*) + + + + Text Files (*.txt) + Fichiers texte (*.txt) + + + + Comma-Separated Values Files (*.csv) + Valeurs séparées par des virgules (*.csv) + + + + Tab-Separated Values Files (*.tsv) + Valeurs séparées par des tabulations (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + Valeurs séparées par des délimiteurs (*.dsv) + + + + Concordance DAT files (*.dat) + Fichiers de concordance (*.dat) + + + + JSON Files (*.json *.js) + Fichiers JSON (*.json *.js) + + + + XML Files (*.xml) + Fichiers XML (*.xml) + + + + Binary Files (*.bin *.dat) + Fichiers binaires (*.bin *.dat) + + + + SVG Files (*.svg) + Fichiers SVG (*.svg) + + + + Hex Dump Files (*.dat *.bin) + Fichiers de dump hexadécimal (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + Extensions (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + Fichier d'initialisation (*.ini) + + + + QsciCommand + + Paste + Coller + + + Cancel + Annuler + + + + QsciLexerCPP + + Default + Défaut + + + Keyword + Mot clé + + + Identifier + Identifiant + + + + QsciLexerJSON + + Default + Défaut + + + String + Chaîne de caractère + + + + QsciLexerJavaScript + + Regular expression + Expression régulière + + + + QsciLexerPython + + Default + Défaut + + + Comment + Commentaire + + + Keyword + Mot clé + + + Identifier + Identifiant + + + + QsciLexerSQL + + Default + Défaut + + + Comment + Commentaire + + + Keyword + Mot clé + + + Identifier + Identifiant + + + + QsciScintilla + + &Undo + Ann&uler + + + Select All + Sélectionner tout + + + + RemoteCommitsModel + + + Commit ID + ID de commit + + + + Message + Message + + + + Date + Date + + + + Author + Auteur + + + + Size + Taille + + + + Authored and committed by %1 + Need to see the context Authored can be translated by "Publié" (published) too as the main author + Créé et validé par %1 + + + + Authored by %1, committed by %2 + Créé par %1, validé par %2 + + + + RemoteDatabase + + + Error opening local databases list. +%1 + Erreur lors de l'ouverture de la liste des bases de données locales. +%1 + + + + Error creating local databases list. +%1 + Erreur lors de la création de la liste des bases de données locales. +%1 + + + + RemoteDock + + + Remote + Serveur distant + + + + Local + Local + + + + Identity + Identité + + + + Push currently opened database to server + Déplacer la base de données en cours sur le serveur + + + + Upload + Télécharger + + + + DBHub.io + DBHub.io + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>Dans ce volet, les bases de données distantes du site Web dbhub.io peuvent être ajoutées à DB Browser for SQLite. Il faut d'abord vous identifier&nbsp;:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Connectez-vous sur le site dbhub.io (utilisez vos identifiants GitHub ou ce que vous voulez)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Cliquez sur le bouton &quot;Generate client certificate&quot; (c'est votre identité). Cela vous fournira un fichier de certificat (enregistrez-le sur votre disque local).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Allez dans l'onglet Serveur distant des Préférences DB Browser for SQLite. Cliquez sur le bouton pour ajouter un nouveau certificat à DB Browser for SQLite et choisissez le fichier de certificat que vous venez de télécharger.</li></ol><p>Maintenant, le panneau Serveur distant affiche votre identité et vous pouvez ajouter des bases de données distantes..</p></body></html> + + + + Current Database + Base de données en cours + + + + Clone + Cloner + + + + Branch + Branche + + + + Commits + Commits + + + + Commits for + Commits pour + + + + Delete Database + Supprime la base de données + + + + Delete the local clone of this database + Supprime le clone local de la base de données + + + + Open in Web Browser + Ouvre dans un navigateur Internet + + + + Open the web page for the current database in your browser + Ouvre la page web de la base de données en cours dans votre navigateur + + + + Clone from Link + Cloner depuis un lien + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + Utilisez ceci pour télécharger une base de données distante pour l'éditer localement en utilisant une URL telle que fournie sur la page web de la base de données. + + + + Refresh + Rafraîchir + + + + Reload all data and update the views + Recharge toutes les données et met à jour les vues + + + + Clone Database + Cloner une base de données + + + + Open Database + Ouvrir une base de données + + + + Open the local copy of this database + Ouvrir la copie locale de la base de données + + + + Check out Commit + Vérifier le commit + + + + Download and open this specific commit + Télécharger et ouvrir ce commit particulier + + + + Check out Latest Commit + Vérifier le dernier commit + + + + Check out the latest commit of the current branch + Vérifie le dernier commit de la branche en cours + + + + Save Revision to File + Enregistrer la révision dans un fichier + + + + Saves the selected revision of the database to another file + Enregistre la révision sélectionnée de la base de données dans un autre fichier + + + + Upload Database + Télécharger la base de données + + + + Upload this database as a new commit + Téléchargez cette base de données en tant que nouveau commit + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>Vous utilisez actuellement une identité intégrée, en lecture seule. Pour télécharger votre base de données, vous devez configurer et utiliser votre compte DBHub.io. </p><p>Vous n'avez pas encore de compte DBHub.io&nbsp;? <a href="https://dbhub.io/"><span style=" text-decoration : underline ; color:#007af4 ;">Créez-en un maintenant</span></a> et importez votre certificat <a href="#preferences"><span style=" text-decoration : underline ; color:#007af4 ;">ici</span></a> pour partager vos bases de données.</p><p>Pour l'aide en ligne, visitez <a href="https://dbhub.io/about"><span style=" text-decoration : underline ; color:#007af4 ;">ici</span></a>.</p></body></html> + + + + &User + &Utilisateur + + + + &Database + Base de &données + + + + Back + Retour + + + + Select an identity to connect + Sélectionner une identité pour se connecter + + + + Public + Public + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + Cela télécharge une base de données à partir d'un serveur distant pour l'éditer localement. +Veuillez entrer l'URL à partir de laquelle vous souhaitez la cloner. Vous pouvez générer cette URL +en cliquant sur le bouton "Cloner la base de données dans DB4S" sur la page web +de la base de données. + + + + Invalid URL: The host name does not match the host name of the current identity. + URL invalide : Le nom de l'hôte ne correspond pas au nom de l'hôte de l'identité actuelle. + + + + Invalid URL: No branch name specified. + URL invalide : Nom de branche non spécifié. + + + + Invalid URL: No commit ID specified. + URL invalide : Commit ID non spécifié. + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + Vous avez modifié le clone local de la base de données. La récupération de ce commit annule ces modifications locales. +Êtes-vous sûr de vouloir continuer ? + + + + The database has unsaved changes. Are you sure you want to push it before saving? + La base de données contient des modifications non sauvegardées. Êtes-vous sûr de vouloir la pousser avant de la sauvegarder ? + + + + The database you are trying to delete is currently opened. Please close it before deleting. + La base de données que vous essayez de supprimer est actuellement ouverte. Veuillez la fermer avant de la supprimer. + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + Cela va supprimer la version locale de cette base de données avec tous les changements pour lesquels vous n'avez pas fait de commit. Êtes-vous sûr de vouloir supprimer cette base de données ? + + + + RemoteLocalFilesModel + + + Name + Nom + + + + Branch + Branche - - Error creating table. Message from database engine: -%1 - Erreur lors de la création de la table. Message du moteur de la base de données : -%1 + + Last modified + Dernière modification - - There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. - Il existe au moins un enregistrement avec ce champ autorisant des valeurs nulles (NULL). Il est donc impossible de définir cet indicateur. Veuillez modifier les données de la table au préalable. + + Size + Taille - - There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. - Il existe au moins un enregistrement avec une valeur qui n'est pas un nombre entier dans ce champ. Il est donc impossible de définir l'indicateur AI (Incrément automatique) sur ce champ. Veuillez modifier les données de la table au préalable. + + Commit + Commit - - Are you sure you want to delete the field '%1'? -All data currently stored in this field will be lost. - Êtes-vous sûr de vouloir supprimer le champ "%1" ? -Toutes les données contenues dans ce champ seront perdues. + + File + Fichier - ExportCsvDialog + RemoteModel - - Export data as CSV - Exporter les données au format CSV + + Name + Nom - - &Table - &Table + + Last modified + Dernière modification - - &Column names in first line - Afficher le nom des &Colonnes dans la première ligne + + Size + Taille - - Field &separator - &Séparateur de champ + + Commit + Commit - - , - , + + Size: + Taille : - - ; - ; + + Last Modified: + Dernière modification : - - - Tab - Tabulation + + Licence: + Licence : - - | - | + + Default Branch: + Branche par défaut : + + + RemoteNetwork - - - Other - Autre + + Choose a location to save the file + Choisissez un emplacement pour enregistrer le fichier - - &Quote character - T&ype de guillemet + + Error opening remote file at %1. +%2 + Erreur lors de l'ouverture du fichier distant %1. +%2 - - " - " + + Error: Invalid client certificate specified. + Erreur : Le certificat du client spécifié est invalide. - - ' - ' + + Please enter the passphrase for this client certificate in order to authenticate. + Pour vous authentifier, veuillez entrer la phrase secrète pour ce certificat client. - - Choose a filename to export data - Choisir un nom de fichier pour exporter les données + + Cancel + Annuler - - Text files(*.csv *.txt) - Fichiers Texte (*.csv *.txt) + + Uploading remote database to +%1 + Téléchargement de la base distante dans +%1 - - Export completed. - Export terminé. + + Downloading remote database from +%1 + Télécharger une base de données distante depuis +%1 - - Could not open output file. - Le fichier de destination ne peut être ouvert. + + Error: Cannot open the file for sending. + Erreur : le fichier à envoyer ne peut être ouvert. - FilterTableHeader + RemotePushDialog - - Filter - Filtre + + Push database + Je ne pense pas que Push soir le bon terme. Est-ce que cela fonctionne comme un serveur de version ? + Pousser une base de données - - - ImportCsvDialog - - Import CSV file - Importer un fichier CSV + + Database na&me to push to + &Nom de la base de données à pousser vers - - &Table name - Nom de la &Table + + Commit message + Message de commit - - &Column names in first line - La première ligne contient le nom des &Colonnes + + Database licence + Licence de la base de données - - Field &separator - &Séparateur de champ + + Public + Publique - - , - , + + Branch + Branche - - ; - ; + + Force push + Forcer le "push" - - - Tab - Tabulation + + Username + Nom d'utilisateur - - | - | + + Database will be public. Everyone has read access to it. + La base de données sera publique. Tout le monde a un accès en lecture. - - - Other - Autre + + Database will be private. Only you have access to it. + La base de données sera privée. Vous seul y avez accès. - - &Quote character - T&ype de guillemet + + Use with care. This can cause remote commits to be deleted. + À utiliser avec précaution. Cela peut entraîner la suppression des commit distants. + + + RunSql - - " - " + + Execution aborted by user + Exécution annulée par l'utilisateur - - ' - ' + + , %1 rows affected + , %1 enregistrements affectés - - Inserting data... - Ajout des données... + + query executed successfully. Took %1ms%2 + Requête exécutée avec succès. Elle a pris %1 ms %2 - - Cancel - Annuler + + executing query + Exécution de la requête + + + SelectItemsPopup - - There is already a table of that name and an import into an existing table is only possible if the number of columns match. - Il existe déjà une table portant ce nom. Importer des données dans une table existante n'est possible que si le nombre de colonnes correspond. + + A&vailable + &Disponible - - There is already a table of that name. Do you want to import the data into it? - Il existe déjà une table portant ce nom. Voulez-vous y importer les données ? + + Sele&cted + Séle&ctionné - MainWindow + SqlExecutionArea - - SQLiteBrowser - SQLiteBrowser + + Form + Formulaire - - Database &Structure - &Structure de la base de données + + Find previous match [Shift+F3] + Trouver la correspondance précédente [Maj+F3] - - - toolBar1 - Barre d'outils1 + + Find previous match with wrapping + Trouver la correspondance précédente avec le modèle - - &Browse Data - &Parcourir les données + + Shift+F3 + - - Table: - Table : + + The found pattern must be a whole word + Le motif trouvé doit être un mot entier - - Select a table to browse data - Sélectionner une table pour parcourir son contenu + + Whole Words + Mots entiers - - Use this list to select a table to be displayed in the database view - Utiliser cette liste pour sélectionner la table à afficher dans la vue Base de données + + Text pattern to find considering the checks in this frame + Modèle de texte à trouver en tenant compte des contrôles de ce cadre - - Refresh the data in the selected table. - Rafraîchir les données de la table sélectionnée. + + Find in editor + Chercher dans l'éditeur - - This button refreshes the data in the currently selected table. - Ce bouton permet de rafraîchir les données de la table actuellement sélectionnée. + + The found pattern must match in letter case + Le motif recherché doit respecter la casse des lettres - - - F5 - F5 + + Case Sensitive + Sensible à la casse - - Insert a new record in the current table - Insérer un nouvel enregistrement dans la table en cours + + Find next match [Enter, F3] + Trouver la correspondance suivante [Entrée, F3] - - This button creates a new, empty record in the database - Ce bouton permet de créer un nouvel enregistrement, vide, dans la base de données + + Find next match with wrapping + Trouver la correspondance suivante avec le modèle - - New Record - Nouvel Enregistrement + + F3 + F3 - - Delete the current record - Supprimer l'enregistrement courant + + Interpret search pattern as a regular expression + Interpréter le modèle de recherche comme une expression régulière - - This button deletes the record currently selected in the database - Ce bouton permet de supprimer l'enregistrement sélectionné de la base de données + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Lorsqu'elle est cochée, le motif à trouver est interprété comme une expression régulière UNIX. Voir <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> - - Delete Record - Supprimer l'enregistrement + + Regular Expression + Expression régulière - - This is the database view. You can double-click any record to edit its contents in the cell editor window. - Ceci est la vue Base de données. Vous pouvez, en double-cliquant sur un enregistrement, modifier son contenu dans la fenêtre Éditeur de cellule. + + + Close Find Bar + Fermer la barre de recherche - - < - < + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>Résultats des derniers traitements exécutées.</p><p>Vous pouvez réduire ce panneau et utiliser le <span style=" font-style:italic ;">dock SQL Log</span> avec la sélection de l'<span style=" font-style:italic ;">utilisateur</span> à la place.</p></body></html> - - 0 - 0 of 0 - 0 - 0 de 0 + + Results of the last executed statements + Résultats du dernier traitement exécuté - - > - > + + This field shows the results and status codes of the last executed statements. + Ce champ affiche les résultats et les codes de statut du dernier traitement exécuté. - - Scroll 100 records upwards - Faire défiler de 100 enregistrements vers le haut + + Ctrl+PgUp + Ctrl+Page Haut - - <html><head/><body><p>Clicking this button navigates 100 records upwards in the table view above.</p></body></html> - <html><head/><body><p>Cliquer sur ce bouton permet de remonter de 100 enregistrements dans l'affichage de la table ci dessous.</p></body></html> + + Ctrl+PgDown + Ctrl+Page Bas - - <html><head/><body><p>Scroll 100 records downwards</p></body></html> - <html><head/><body><p>Faire défiler de 100 enregistrements vers le bas</p></body></html> + + Couldn't read file "%1": %2. + Le fichier %1 ne peut être lu : %2. - - <html><head/><body><p>Clicking this button navigates 100 records downwards in the table view above.</p></body></html> - <html><head/><body><p>Cliquer sur ce bouton permet de descendre de 100 enregistrements dans l'affichage de la table ci dessous.</p></body></html> + + + Couldn't save file: %1. + Le fichier %1 ne peut être sauvegardé. - - <html><head/><body><p>Click here to jump to the specified record</p></body></html> - <html><head/><body><p>Cliquer ici pour vous déplacer sur l'enregistrement défini</p></body></html> + + Your changes will be lost when reloading it! + Vos modifications seront perdues lors du rechargement ! - - <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> - <html><head/><body><p>Ce bouton est utilisé pour aller directement à l'enregistrement défini dans le champ Aller à.</p></body></html> + + The file "%1" was modified by another program. Do you want to reload it?%2 + Le fichier "%1" a été modifié par un autre programme. Voulez-vous le recharger ? %2 - - Go to: - Aller à : + + Answer "Yes to All" to reload the file on any external update without further prompting. + Répondez "Oui pour tous" pour recharger le fichier lors de toute mise à jour externe sans autre question. - - Enter record number to browse - Entrez le nombre d'enregistrements à parcourir + + Answer "No to All" to ignore any external update without further prompting. + Répondez "Non à tous" pour ignorer toute mise à jour externe sans autre question. - - Type a record number in this area and click the Go to: button to display the record in the database view - Entrez un numéro d'enregistrement dans ce champ et cliquez sur le bouton "Aller à" pour afficher l'enregistrement dans la vue Base de données + + Modifying and saving the file will restore prompting. + A voir selon le contexte MVT + La modification et l'enregistrement du fichier rétabliront la demande d'information. + + + + SqlTextEdit + + + Ctrl+/ + + + + SqlUiLexer - - 1 - 1 + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) La fonction abs(X) renvoie la valeur absolue de l'argument numérique X. - - Edit &Pragmas - Éditer les &Pragmas + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () La fonction changes() renvoie le nombre de lignes de la base de données qui ont été modifiées, insérées ou supprimées par les instructions UPDATE, INSERT ou DELETE terminées dernièrement. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum""><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum""><span style=" text-decoration: underline; color:#0000ff;">Vidage automatique</span></a></p></body></html> + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1, X2,...) La fonction char(X1,X2,...,XN) renvoie une chaîne composée des caractères ayant les valeurs des points de code unicode des entiers allant de X1 à XN, respectivement. - - None - Aucun + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X, Y, ...) La fonction coalesce () renvoie une copie de son premier argument non-NULL, ou NULL si tous les arguments sont NULL - - - Full - Complet + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X, Y) La fonction glob(X, Y) est équivalente à l'expression « Y GLOB X ». - - Incremental - Incrémental + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X, Y) La fonction ifnull() renvoie une copie de son premier argument non-NULL, ou NULL si les deux arguments sont NULL. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index""><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index""><span style=" text-decoration: underline; color:#0000ff;">Index Automatique</span></a></p></body></html> + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X, Y) La fonction instr(X, Y) trouve la première occurrence de la chaîne Y dans la chaîne X. Elle renvoie le nombre de caractères précédents plus 1 ou 0 si Y n'est pas dans X. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync""><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync""><span style=" text-decoration: underline; color:#0000ff;">Point de contrôle FSYNC intégral</span></a></p></body></html> + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) La fonction hex() interprète son argument comme un BLOB et renvoie une chaîne qui est le rendu hexadécimal en majuscules du contenu de ce blob. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys""><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys""><span style=" text-decoration: underline; color:#0000ff;">Clés étrangères</span></a></p></body></html> + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) La fonction iif(X,Y,Z) renvoie la valeur Y si X est vrai, Z sinon. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync""><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync""><span style=" text-decoration: underline; color:#0000ff;">FSYNC intégral</span></a></p></body></html> + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () La fonction last_insert_rowid () renvoie le ROWID de la dernière ligne insérée par la connexion de la base de données qui a invoqué la fonction. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints""><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints""><span style=" text-decoration: underline; color:#0000ff;">Ignorer le contrôle des contraintes</span></a></p></body></html> + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) Pour une valeur de chaîne X, la fonction length(X) renvoie le nombre de caractères (pas d'octets) dans X avant le premier caractère NULL. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode""><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode""><span style=" text-decoration: underline; color:#0000ff;">Mode de journalisation</span></a></p></body></html> + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X, Y) La fonction like() est utilisée pour mettre en Å“uvre de l’expression « Y LIKE X ». - - Delete - Supprimer + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X, Y, Z) La fonction like() est utilisée pour mettre en Å“uvre de l’expression « Y LIKE X ESCAPE Z ». - - Truncate - Tronquer + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) La fonction load_extension(X) charge les extensions SQLite à partir du fichier de bibliothèque partagé nommé X. +L'utilisation de cette fonction doit être autorisée à partir des Préférences. - - Persist - Persistant + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) La fonction load_extension(X) charge les extensions SQLite à partir du fichier de bibliothèque partagée nommé X en utilisant le point d'entrée Y. +L'utilisation de cette fonction doit être autorisée à partir des Préférences. - - - Memory - Mémoire + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) La fonction lower(X) renvoie une copie de la chaîne X avec tous ses caractères ASCII convertis en minuscules. - - WAL - WAL + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) supprime les espaces gauche de X. - - - Off - Arrêté + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X, Y) La fonction ltrim(X,Y) renvoie une chaîne résultant de la suppression de tous les caractères qui apparaissent en Y à gauche de X. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit""><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit""><span style=" text-decoration: underline; color:#0000ff;">Taille maximale du Journal</span></a></p></body></html> + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) La fonction à arguments multiples max() renvoie l'argument ayant la plus grande valeur ou renvoie NULL si tous les arguments sont NULL. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode""><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode""><span style=" text-decoration: underline; color:#0000ff;">Mode de recherche</span></a></p></body></html> + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) La fonction à arguments multiples min() renvoie l'argument ayant la plus petite valeur. - - - Normal - Normal + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X, Y) La fonction nullif(X,Y) renvoie le premier argument, si les arguments sont différents et NULL si les X et Y sont les mêmes. - - Exclusive - Exclusif + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) La fonction SQL printf(FORMAT,...) fonctionne comme la fonction de sqlite3_mprintf() en langage C et la fonction printf() de la bibliothèque C standard. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count""><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count""><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) La fonction quote(X) renvoie le texte d'un litéral SQL qui est la valeur appropriée de l'argument pour son inclusion dans une requête SQL. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size""><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size""><span style=" text-decoration: underline; color:#0000ff;">Taille de la Page</span></a></p></body></html> + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () La fonction random() renvoie un nombre entier pseudo-aléatoire entre -9223372036854775808 et +9223372036854775807. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers""><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers""><span style=" text-decoration: underline; color:#0000ff;">Déclencheurs récursifs</span></a></p></body></html> + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) La fonction randomblob(N) renvoie un blob de N octets contenant des octets pseudo-aléatoires. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete""><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete""><span style=" text-decoration: underline; color:#0000ff;">Suppression sécurisée</span></a></p></body></html> + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X, Y, Z) La fonction replace(X,Y,Z) renvoie une chaîne formée en substituant par la chaîne Z chaque occurrence de la chaîne Y présente dans la chaîne X. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous""><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous""><span style=" text-decoration: underline; color:#0000ff;">Synchronisation</span></a></p></body></html> + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) La fonction round(X) renvoie une valeur à virgule flottante X arrondie à zéro chiffres à droite de la virgule décimale. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store""><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store""><span style=" text-decoration: underline; color:#0000ff;">Stockage temporaire</span></a></p></body></html> + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X, Y) La fonction round(X,Y) renvoie une valeur à virgule flottante X arrondie à Y chiffres à droite de la virgule décimale. - - Default - Défaut + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X) supprime les espaces droite de X. - - File - Fichier + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X, Y) La fonction rtrim(X,Y) renvoie une chaîne formée en supprimant tous les caractères qui apparaissent en Y, à droite de X. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version""><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version""><span style=" text-decoration: underline; color:#0000ff;">Version utilisateur</span></a></p></body></html> + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) La fonction soundex(X) renvoie une chaîne qui est l'encodage soundex de la chaîne X. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint""><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint""><span style=" text-decoration: underline; color:#0000ff;">Point de contrôle WAL automatique</span></a></p></body></html> + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X, Y) substr(X,Y) renvoie tous les caractères à partir du n-ième Y jusqu'à la fin de la chaîne X. - - E&xecute SQL - E&xécuter le SQL + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X, Y, Z) La fonction substr(X,Y,Z) renvoie une sous-chaîne de la chaîne X à partie du n-ième caractère Y, de longueur Z. - - &File - &Fichier + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () La fonction total_changes() renvoie le nombre d'enregistrements altérés par les instructions INSERT, UPDATE ou DELETE depuis l'ouverture de la connexion de base de données courante. - - &Import - &Importer + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) supprime les espaces aux deux extrémités de X. - - &Export - &Exporter + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X, Y) La fonction trim(X,Y) renvoie une chaîne formée en supprimant tous les caractères de Y présents aux deux extrémités de X. - - &Edit - &Editer + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) La fonction typeof(X) renvoie une chaîne qui indique le type de données de l'expression X. - - &View - &Vue + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) La fonction unicode(X) renvoie le point de code unicode numérique correspondant au premier caractère de la chaîne X. - - &Help - &Aide + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) La fonction upper(X) renvoie une copie de la chaîne X dans laquelle tous les caractères ASCII en minuscules sont convertis en leurs équivalents en majuscules. - - toolBar - Barre d'outils + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) La fonction zeroblob(N) renvoie un BLOB composé de N octets de valeur 0x00. - - SQL Log - Journal SQL + + + + + (timestring,modifier,modifier,...) + (timestring,modifier,modifier,...) - - &Show SQL submitted by - A&fficher le SQL soumis par + + (format,timestring,modifier,modifier,...) + (format,timestring,modifier,modifier,...) - - User - Utilisateur + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) La fonction avg() renvoie la valeur moyenne de tous les X non-NULL dans d'un groupe. - - Application - Application + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) La fonction count(X) renvoie le nombre de fois où X n'est pas NULL dans un groupe. - - &Clear - &Effacer + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) la fonction group_concat() renvoie une chaîne qui est la concaténation de toutes les valeurs non-NULL de X. - - Plot - Voir le contexte d'utilisation - Graphique + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X, Y) La fonction group_concat() renvoie une chaîne qui est la concaténation de toutes les valeurs non-NULL de X. Si le paramètre Y est présent, il est utilisé comme séparateur entre chaque instances de X. - - Columns - Colonnes + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) La fonction d'agrégat max() renvoie la valeur maximale de toutes les valeurs du groupe. - - X - X + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) La fonction d'agrégation min() renvoie la valeur non-NULL minimale de toutes les valeurs du groupe. - - Y - Y + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) Les fonctions d'agrégation sum() et total() renvoient la somme de toutes les valeurs non-NULL du groupe. - - _ - _ + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () Le numéro de l'enregistrement dans la partition courante. Les lignes sont numérotées à partir de 1 dans l'ordre défini par la clause ORDER BY dans la définition de la fenêtre, ou, sinon, dans un ordre arbitraire. - - Save current plot... - Voir le contexte d'utilisation - Enregistrer le tracé actuel... + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () Le row_number() enregistrement homologue de chaque groupe - le rang de l'enregistrement courant avec les écarts. S'il n'y a pas de clause ORDER BY, alors tous les enregistrements sont considérées comme homologues et cette fonction renvoie toujours 1. - - &New Database... - &Nouvelle base de données... + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () Le numéro du groupe d'enregistrements homologues de la rangée courante dans sa partition - le rang de la rangée courante sans espaces. Les partitions sont numérotées à partir de 1 dans l'ordre défini par la clause ORDER BY dans la définition de la fenêtre. S'il n'y a pas de clause ORDER BY, alors toutes les lignes sont considérées comme homologues et cette fonction renvoie toujours 1. - - - Create a new database file - Créer une nouvelle base de données + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () Malgré le nom, cette fonction retourne toujours une valeur comprise entre 0.0 et 1.0 égale à (rang - 1)/(rangées de partitions - 1), où rang est la valeur retournée par la fonction de fenêtre intégrée rank() et rangées de partitions est le nombre total de rangées dans la partition. Si la partition ne contient qu'une seule ligne, cette fonction renvoie 0.0. - - This option is used to create a new database file. - Cette option est utilisée pour créer un nouveau fichier de base de données. + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () Répartition cumulée. Calculée en tant que ligne-numéro/rangées-partition, où ligne-numéro est la valeur retournée par row_number() pour le dernier homologue dans le groupe et ligne-partition le nombre de lignes dans la partition. - - Ctrl+N - Ctrl+N + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) L'argument N est traité comme un entier. Cette fonction divise la partition en N groupes le plus uniformément possible et attribue un entier compris entre 1 et N à chaque groupe, dans l'ordre défini par la clause ORDER BY, ou, sinon, dans un ordre arbitraire. Si nécessaire, les plus grands groupes se forment en premier. Cette fonction retourne la valeur entière assignée au groupe dont la ligne courante fait partie. - - &Open Database... - &Ouvrir une base de données... + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) Retourne le résultat de l'évaluation de l'expression expr par rapport à la ligne précédente de la partition. Ou NULL s'il n'y a pas de ligne précédente (parce que la ligne courante est la première). - - - Open an existing database file - Ouvrir une base de données existante + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr,offset) Si l'argument offset est fourni, alors il doit être un entier non négatif. Dans ce cas, la valeur retournée est le résultat de l'évaluation de expr par rapport au décalage des lignes avant la ligne courante dans la partition. Si l'offset est égal à 0, alors expr est évalué par rapport à la ligne courante. S'il n'y a pas de lignes de décalage de ligne avant la ligne courante, NULL est retourné. - - This option is used to open an existing database file. - Cette option est utilisée pour ouvrir une base de données existante. + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,offset,default) Si la valeur par défaut est aussi renseignée, cette valeur sera retournée au lieu de NULL si la ligne identifiée par offset n'existe pas. - - Ctrl+O - Ctrl+O + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) Retourne le résultat de l'évaluation de l'expression expr par rapport à la ligne suivante de la partition. Ou NULL s'il n'y a pas de ligne suivante (parce que la ligne courante est la dernière). - - &Close Database - &Fermer la base de données + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,offset) Si l'argument offset est fourni, alors il doit être un entier non négatif. Dans ce cas, la valeur retournée est le résultat de l'évaluation de expr par rapport par rapport au décalage des lignes après la ligne courante dans la partition. Si l'offset est égal à 0, alors expr est évalué par rapport à la ligne courante. S'il n'y a pas de lignes de décalage de ligne après la ligne courante, NULL est retourné. - - Ctrl+W - Ctrl+W + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) Cette fonction de fenêtrage intégrée calcule le cadre de la fenêtre pour chaque rangée de la même manière qu'une fonction de fenêtrage agrégée. Elle retourne la valeur de expr évaluée par rapport à la première ligne du cadre de la fenêtre pour chaque ligne. - - Revert Changes - Annuler les modifications + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) Cette fonction de fenêtrage intégrée calcule le cadre de la fenêtre pour chaque rangée de la même manière qu'une fonction de fenêtrage agrégée. Elle retourne la valeur de expr évaluée par rapport à la dernière ligne du cadre de la fenêtre pour chaque ligne. - - Revert database to last saved state - Revenir à la dernière sauvegarde de la base de données + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr,N) Cette fonction de fenêtrage intégrée calcule le cadre de la fenêtre pour chaque rangée de la même manière qu'une fonction de fenêtrage agrégée. Elle retourne la valeur de expr évaluée par rapport à la ligne N du cadre de la fenêtre. Les rangées sont numérotées à l'intérieur du cadre de la fenêtre à partir de 1 dans l'ordre défini par la clause ORDER BY si elle est présente, ou dans un ordre arbitraire sinon. S'il n'y a pas de n-ième ligne dans la partition, alors NULL est retourné. - - This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. - Cette option permet de remettre la base de données dans l'état de sa dernière sauvegarde. Tous les changements effectués depuis cette dernière sauvegarde seront perdus. + + (X) Return the arccosine of X. The result is in radians. + (X) Retourne l'arc cosinus de X. Le résultat est en radians. - - Write Changes - Enregistrer les modifications + + (X) Return the hyperbolic arccosine of X. + (X) Renvoie le cosinus de l'arc hyperbolique de X. - - Write changes to the database file - Enregistrer les modifications dans la base de données + + (X) Return the arcsine of X. The result is in radians. + (X) Renvoie l'arcsinus de X. Le résultat est en radians. - - This option is used to save changes to the database file. - Cette option est utilisée pour enregistrer les modifications dans la base de données. + + (X) Return the hyperbolic arcsine of X. + (X) Renvoie l'arcsinus hyperbolique de X. - - Ctrl+S - Ctrl+S + + (X) Return the arctangent of X. The result is in radians. + (X) Renvoie l'arctangente de X. Le résultat est en radians. - - Compact Database - Compacter la base de données + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + (X,Y) Renvoie l'arctangente de Y/X. Le résultat est en radians. Le résultat est placé dans le bon quadrant en fonction des signes de X et Y. - - Compact the database file, removing space wasted by deleted records - Compacter la base de donnée, récupérer l'espace perdu par les enregistrements supprimés + + (X) Return the hyperbolic arctangent of X. + (X) Renvoie l'arctangente hyperbolique de X. - - - Compact the database file, removing space wasted by deleted records. - Compacter la base de donnée, récupérer l'espace perdu par les enregistrements supprimés. + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + (X) Renvoie la première valeur entière représentable supérieure ou égale à X. Pour les valeurs positives de X, cette routine arrondit à l'écart de zéro. Pour les valeurs négatives de X, cette routine arrondit vers zéro. - - E&xit - &Quitter + + (X) Return the cosine of X. X is in radians. + (X) Renvoie le cosinus de X. X est exprimé en radians. - - Ctrl+Q - Ctrl+Q + + (X) Return the hyperbolic cosine of X. + (X) Renvoie le cosinus hyperbolique de X. - - Database from SQL file... - Base de données à partir du fichier SQL... + + (X) Convert value X from radians into degrees. + (X) Convertit la valeur X de radians en degrés. - - Import data from an .sql dump text file into a new or existing database. - Importer les données depuis un fichier sql résultant d'un vidage (sql dump) dans une nouvelle base de données ou une base existante. + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + (X) Calculer le (le nombre d'Euler, environ 2,71828182845905) élevé à la puissance X. - - This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. - Cette option vous permet d'importer un fichier sql de vidage d'une base de données (SQL dump) dans une nouvelle base de données ou une base existante. Ce fichier peut être créé par la plupart des moteurs de base de données, y compris MySQL et PostgreSQL. + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + (X) Renvoie la première valeur entière représentable inférieure ou égale à X. Pour les nombres positifs, cette fonction arrondit vers zéro. Pour les nombres négatifs, cette fonction arrondit à l'opposé de zéro. - - Table from CSV file... - Table à partir d'un fichier CSV... + + (X) Return the natural logarithm of X. + (X) Renvoie le logarithme naturel de X. - - Open a wizard that lets you import data from a comma separated text file into a database table. - Ouvrir un Assistant vous permettant d'importer des données dans une table de la base de données à partir d'un fichier texte séparé par des virgules (csv). + + (B,X) Return the base-B logarithm of X. + (B,X) Renvoie le logarithme en base B de X. - - Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. - Ouvre un Assistant vous permettant d'importer des données dans une table de la base de données à partir d'un fichier texte séparé par des virgules (csv). Les fichiers CSV peuvent être créés par la plupart des outils de gestion de base de données et les tableurs. + + + (X) Return the base-10 logarithm for X. + (X) Renvoie le logarithme en base 10 de X. - - Database to SQL file... - Base de données vers un fichier SQL... + + (X) Return the logarithm base-2 for the number X. + (X) Renvoie le logarithme en base 2 de X. - - Export a database to a .sql dump text file. - Exporter la base de données vers un fichier de vidage sql (SQL dump) au format texte. + + (X,Y) Return the remainder after dividing X by Y. + (X,Y) Renvoie le reste après avoir divisé X par Y. - - This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. - Exporter la base de données vers un fichier de vidage sql (SQL dump) au format texte. Ce fichier (SQL dump) contient toutes les informations nécessaires pour recréer une base de données par la plupart des moteurs de base de données, y compris MySQL et PostgreSQL. + + () Return an approximation for Ï€. + () Renvoie une approximation de Ï€. - - Table as CSV file... - Table vers un fichier CSV... + + + (X,Y) Compute X raised to the power Y. + (X,Y) Calculer X élevé à la puissance Y. - - Export a database table as a comma separated text file. - Exporter la table vers un fichier texte séparé par des virgules (CSV). + + (X) Convert X from degrees into radians. + (X) Convertir X de degrés en radians. - - Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. - Exporter la table vers un fichier texte séparé par des virgules (CSV), prêt à être importé dans une autre base de données ou un tableur. + + (X) Return the sine of X. X is in radians. + (X) Renvoie le sinus de X. X est en radians. - - Create Table... - Créer une table... + + (X) Return the hyperbolic sine of X. + (X) Renvoie le sinus hyperbolique de X. - - Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database - Ouvrir l'assistant de création d'une table dans lequel il sera possible de définir les noms et les champs d'une nouvelle table dans la base de données + + (X) Return the square root of X. NULL is returned if X is negative. + (X) Renvoie la racine carrée de X. NULL est renvoyé si X est négatif. - - Delete Table... - Supprimer la table... + + (X) Return the tangent of X. X is in radians. + (X) Renvoie la tangente de X. X est en radians. - - Open the Delete Table wizard, where you can select a database table to be dropped. - Ouvrir l'assistant de suppression d'une table dans lequel vous pourrez sélectionner la base de données dans laquelle cette table sera supprimée. + + (X) Return the hyperbolic tangent of X. + (X) Renvoie la tangente hyperbolique de X. - - Modify Table... - Modifier une table... + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + (X) Renvoie l'entier représentable compris entre X et 0 (inclus) qui est le plus éloigné de zéro. Ou, en d'autres termes, retourner la partie entière de X, en l'arrondissant vers zéro. + + + SqliteTableModel - - Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields form a table, as well as modify field names and types. - Ouvrir l'assistant de modification d'une table dans lequel il sera possible de renommer une table existante. Il est aussi possible d'ajouter ou de supprimer des champs de la table, tout comme modifier le nom des champs et leur type. + + reading rows + Lecture des enregistrements - - Create Index... - Créer un index... + + loading... + chargement... - - Open the Create Index wizard, where it is possible to define a new index on an existing database table. - Ouvrir l'assistant de création d'un index dans lequel il sera possible de définir un nouvel index dans une table préexistante de la base de données. + + References %1(%2) +Hold %3Shift and click to jump there + Références %1(%2) +Appuyez simultanément sur %3+Maj et cliquez pour arriver ici - - &Preferences... - &Préférences... + + Error changing data: +%1 + Erreur lors du changement des données : +%1 - - - Open the preferences window. - Ouvrir la fenêtre des préférences. + + retrieving list of columns + récupération de la liste des colonnes - - &DB Toolbar - &Barre d'outils BdD + + Fetching data... + Récupération des données... - - Shows or hides the Database toolbar. - Affiche ou masque la barre d'outils Base de données. + + + Cancel + Annuler + + + + TableBrowser + + + Browse Data + Parcourir les données + + + + &Table: + &Table : + + + + Select a table to browse data + Sélectionner une table pour parcourir son contenu - - What's This? - Qu'est-ce que c'est ? + + Use this list to select a table to be displayed in the database view + Utiliser cette liste pour sélectionner la table à afficher dans la vue Base de données - - Shift+F1 - Maj+F1 + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + Ceci est la vue des tables de la base de données. Vous pouvez effectuer les actions suivantes : + - Commencez à écrire pour éditer en ligne la valeur. + - Double-cliquez sur n'importe quel enregistrement pour éditer son contenu dans la fenêtre de l'éditeur de cellule. + - Alt+Supp pour supprimer le contenu de la cellule et la met à NULL. + - Ctrl+" pour dupliquer l'enregistrement en cours. + - Ctrl+' pour copier la valeur de la cellule ci-dessus. + - Sélection standard et opérations de copier/coller. - - &About... - &A propos... + + Text pattern to find considering the checks in this frame + Modèle de texte à trouver en tenant compte des contrôles de ce cadre - - &Recently opened - Ouvert &récemment + + Find in table + Chercher dans la table - - Open &tab - vérifier le contexte - Ouvrir un on&glet + + Find previous match [Shift+F3] + Trouver la correspondance précédente [Maj+F3] - - Ctrl+T - Ctrl+T + + Find previous match with wrapping + Trouver la correspondance précédente avec le modèle - - &Execute SQL - &Excuter le SQL + + Shift+F3 + - - Execute SQL [F5, Ctrl+Return] - Exécuter le SQL [F5 ou Ctrl+Entrée] + + Find next match [Enter, F3] + Trouver la correspondance suivante [Entrée, F3] - - &Wiki... - &Wiki... + + Find next match with wrapping + Trouver la correspondance suivante avec le modèle - - Bug &report... - &Rapport d'anomalie... + + F3 + - - Web&site... - &Site Internet... + + The found pattern must match in letter case + Le motif recherché doit respecter la casse des lettres - - Save Project - Sauvegarder le projet + + Case Sensitive + Sensible à la casse - - - Save the current session to a file - Sauvegarder la session courante dans un fichier + + The found pattern must be a whole word + Le motif trouvé doit être un mot entier - - Open Project - Ouvrir un projet + + Whole Cell + Ensemble de la cellule - - - Load a working session from a file - Charger une session de travail depuis un fichier + + Interpret search pattern as a regular expression + Interpréter le modèle de recherche comme une expression régulière - - Open SQL file - Ouvrir un fichier SQL + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Lorsque cette case est cochée, le motif à trouver est interprété comme une expression régulière UNIX. Voir <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> - - <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> - <html><head/><body><p>Sauvegarder le graphique actuel...</p><p>Choisir le format de fichier parmi les extensions (png, jpg, pdf, bmp)</p></body></html> + + Regular Expression + Expression régulière - - Save SQL file - Sauvegarder le fichier SQL + + + Close Find Bar + Fermer la barre de recherche - - Load extension - Charger une extension + + Text to replace with + Texte à remplacer par - - Execute current line - Exécuter la ligne courante + + Replace with + Remplacer par - - Execute current line [Ctrl+E] - Exécuter la ligne courante (Ctrl+E) + + Replace next match + Remplacer la prochaine correspondance - - Ctrl+E - Ctrl+E + + + Replace + Remplacer - - Export as CSV file - Exporter les données au format CSV + + Replace all matches + Remplacer toutes les correspondances - - Export table as comma separated values file - Exporter la table vers un fichier texte séparé par des virgules (CSV) + + Replace all + Remplacer tout - - Ctrl+L - Ctrl+L + + Export to &JSON + Exporter au format &JSON - - Ctrl+P - Ctrl+P + + + Export the filtered data to JSON + Exporte les données filtrées au format JSON - - Database encoding - Encodage de la base de données + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + Ce bouton exporte les données de la table parcourue telles qu'elles sont actuellement affichées (après les filtres, les formats d'affichage et la colonne d'ordre) dans un fichier JSON. - - Choose a database file - Choisir une base de données + + Copy column name + Copier le nom de la colonne - - Ctrl+Return - Ctrl+Entrée + + Copy the database table column name to your clipboard + Copie le nom de la colonne de la table de la base de données dans le presse-papiers - - - - - Choose a filename to save under - Choisir un nom de fichier pour enregistrer sous + + New Data Browser + Nouveau navigateur de données - - Error adding record: - - Erreur dans l'ajout d'un enregistrement : + + + Add a new docked Data Browser + Ajouter un nouveau navigateur de données ancré - - Error deleting record: -%1 - Erreur dans la suppression d'un enregistrement : -%1 + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + Ce bouton ajoute un nouveau navigateur de données ancré, que vous pouvez détacher et organiser selon différentes dispositions. - - Please select a record first - Veuillez sélectionner au préalable un enregistrement + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>Aller au début</p></body></html> - - %1 - %2 of %3 - %1 - %2 de %3 + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>Cliquer sur ce bouton permet d'aller au début de la table ci-dessus.</p></body></html> - - - There is no database opened. Please open or create a new database file. - Il n'y a pas de base de données ouverte. Veuillez ouvrir ou créer une nouvelle base de données. + + |< + |< - - Are you sure you want to delete the %1 '%2'? -All data associated with the %1 will be lost. - Êtes-vous sûr de vouloir supprimer le %1 '%2'? -Toutes les données associées à %1 seront perdues. + + Scroll one page upwards + Remonter d'une page - - Error: could not delete the %1. Message from database engine: -%2 - Erreur : Suppression impossible de %1. Message du moteur de base de données : -%2 + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>Cliquer sur ce bouton permet d'afficher la page précédente des enregistrements de la table ci dessus.</p></body></html> - - There is no database opened. - Il n'y a pas de base de données ouverte. + + < + < - - %1 Rows returned from: %2 (took %3ms) - %1 enregistrements ramenés depuis %2 (en %3ms) + + 0 - 0 of 0 + 0 - 0 de 0 - - Error executing query: %1 - Erreur lors de l'exécution de la requête : %1 + + Scroll one page downwards + Descendre d'une page - - Query executed successfully: %1 (took %2ms) - Requête exécutée avec succès : %1 (en %2 ms) + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>Cliquer sur ce bouton permet d'afficher la page suivante des enregistrements de la table ci dessus.</p></body></html> - - Choose a text file - Choisir un fichier texte + + > + > - - Text files(*.csv *.txt);;All files(*) - Fichiers Texte (*.txt);;Tous les fichiers(*) + + Scroll to the end + Aller à la fin - - Import completed - Import terminé + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>Cliquer sur ce bouton permet d'aller à la fin de la table ci-dessus.</p></body></html> - - Are you sure you want to undo all changes made to the database file '%1' since the last save? - Êtes-vous sûr de vouloir annuler tous les changements effectués dans la base de données %1 depuis la dernière sauvegarde ? + + >| + >| - - Choose a filename to export - Choisir un nom de fichier pour l'export + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>Cliquer ici pour vous déplacer sur l'enregistrement indiqué</p></body></html> - - Text files(*.sql *.txt) - Fichiers Texte (*.sql *.txt) + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>Ce bouton est utilisé pour aller directement à l'enregistrement indiqué dans le champ Aller à.</p></body></html> - - Export cancelled or failed. - l'export a été annulé ou a échoué. + + Go to: + Aller à : - - Export completed. - Export terminé. + + Enter record number to browse + Entrez le nombre d'enregistrements à parcourir - - Choose a file to import - Choisir un fichier à importer + + Type a record number in this area and click the Go to: button to display the record in the database view + Entrez un numéro d'enregistrement dans ce champ et cliquez sur le bouton "Aller à" pour afficher l'enregistrement dans la vue base de données - - - - Text files(*.sql *.txt);;All files(*) - Fichiers Texte (*.sql *.txt);;Tous les fichiers(*) + + 1 + 1 - - Do you want to create a new database file to hold the imported data? -If you answer no we will attempt to import the data in the SQL file to the current database. - Voulez vous créer une nouvelle base de donnée pour gérer les données importées ? -Si vous répondez non, nous essaierons d'importer les données du fichier SQL dans la base de données courante. + + Show rowid column + Afficher la colonne RowId - - File %1 already exists. Please choose a different name. - Le fichier %1 existe déjà. Choisir un nom de fichier différent. + + Toggle the visibility of the rowid column + Permet d'afficher ou non la colonne RowId - - Error importing data: %1 - Erreur lors de l'import des données : %1 + + Unlock view editing + Déverrouiller l'éditeur de vues - - Import completed. - Import terminé. + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + Permet de déverrouiller la vue courante pour l'éditer. Cependant, vous aurez besoin de déclencheurs appropriés pour faire cela. - - Delete View - Supprimer la Vue + + Edit display format + Modifier le format d'affichage - - Delete Trigger - Supprimer le Déclencheur + + Edit the display format of the data in this column + Modifie le format d'affichage des données contenues dans cette colonne - - Delete Index - Supprimer l'Index + + + New Record + Nouvel enregistrement - - - Delete Table - Supprimer la Table + + + Insert a new record in the current table + Insérer un nouvel enregistrement dans la table en cours - - &%1 %2 - &%1 %2 + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>Ce bouton crée un nouvel enregistrement dans la base de données. Maintenez le bouton de la souris enfoncé pour ouvrir un menu contextuel de différentes options&nbsp;:</p><ul><li><span style=" font-weight:600;">Nouvel enregistrement</span>&nbsp;: Insère un nouvel enregistrement avec les valeurs par défaut dans la base de données.</li><li><span style=" font-weight:600;">Insérer des valeurs...</span>&nbsp;: ouvre une boite de dialogue pour saisir des valeurs avant leur insertion dans la base de données. Ceci permet de saisir des valeurs correspondant aux différentes contraintes. Cette boîte de dialogue est également ouverte si l'option <span style=" font-weight:600;">Nouvel enregistrement </span> est en erreur à cause de ces contraintes.</li></ul></body></html> - - Setting PRAGMA values will commit your current transaction. -Are you sure? - Paramétrer les valeurs du PRAGMA enregistrera les actions de votre transaction courante. -Êtes-vous sûr ? + + + Delete Record + Supprimer l'enregistrement - - Select SQL file to open - Sélectionner un fichier SQL à ouvrir + + Delete the current record + Supprimer l'enregistrement courant - - Select file name - Sélectionner un nom de fichier + + + This button deletes the record or records currently selected in the table + Ce bouton permet de supprimer l'enregistrement sélectionné dans la table - - Select extension file - Sélectionner une extension de fichier + + + Insert new record using default values in browsed table + Insérer un nouvel enregistrement en utilisant les valeurs par défaut de la table parcourue - - Extensions(*.so *.dll);;All files(*) - Extensions (*.so *.dll);;Tous les fichiers (*) + + Insert Values... + Ajouter des valeurs... - - Extension successfully loaded. - l'extension a été chargée avec succès. + + + Open a dialog for inserting values in a new record + Ouvre une fenêtre de dialogue permettant l'insertion de valeurs dans un nouvel enregistrement - - - Error loading extension: %1 - Erreur lors du chargement de l'extension %1 + + Export to &CSV + Exporter au format &CSV - - Don't show again - Ne plus afficher + + + Export the filtered data to CSV + Exporte les données filtrées au format CSV - - New version available. - Une nouvelle version est disponible. + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + Ce bouton exporte les données de la table parcourue telles qu'elles sont actuellement affichées (après les filtres, les formats d'affichage et la colonne d'ordre) dans un fichier CSV. - - A new sqlitebrowser version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. - Une nouvelle version de SQLiteBrowser est disponible (%1.%2.%3).<br/><br/>Vous pouvez la télécharger sur <a href='%4'>%4</a>. + + Save as &view + Enregistrer comme une &vue - - Choose a axis color - Choisir la couleur de l'axe + + + Save the current filter, sort column and display formats as a view + Enregistrer le filtre, la colonne de tri et les formats d'affichage actuels sous la forme d'une vue - - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + Ce bouton permet d'enregistrer les paramètres actuels de la table parcourue (filtres, formats d'affichage et colonne d'ordre) sous forme de vue SQL que vous pourrez ensuite parcourir ou utiliser dans les instructions SQL. - - Choose a file to open - Choisir un fichier à ouvrir + + Save Table As... + Enregistrer la table sous... - - - SQLiteBrowser project(*.sqbpro) - Projet SQLiteBrowser (*.sqbpro) + + + Save the table as currently displayed + Enregistrer la table comme affichée actuellement - - Invalid file format. - Format de fichier invalide. + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>Ce menu déroulant fournit les options suivantes s'appliquant à la table actuellement parcourue et filtrée:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Exporter au format CSV&nbsp;: cette option exporte les données de la table parcourue telles qu'elles sont actuellement affichées (après filtres, formats d'affichage et colonne d'ordre) vers un fichier CSV.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enregistrer comme vue&nbsp;: cette option permet d'enregistrer les paramètres actuels de la table parcourue (filtres, formats d'affichage et colonne d'ordre) dans une vue SQL que vous pourrez ensuite parcourir ou utiliser dans les instructions SQL.</li></ul></body></html> - - - PreferencesDialog - - Preferences - Préférences + + Hide column(s) + Masquer une/des colonnes - - &Database - &Base de données + + Hide selected column(s) + Maquer la/les colonnes sélectionnées - - Database &encoding - &Encodage de la base de données + + Show all columns + Afficher toutes les colonnes - - Open databases with foreign keys enabled. - Ouvrir une base de données en autorisant les clés étrangères. + + Show all columns that were hidden + Permet d'afficher toutes les colonnes qui ont été masquées - - &Foreign keys - &Clés étrangères + + + Set encoding + Définir l'encodage - - enabled - autorisé + + Change the encoding of the text in the table cells + Change l'encodage du texte des cellules de la table - - Default &location - Emp&lacement par défaut + + Set encoding for all tables + Définir l'encodage pour toutes les tables - - ... - ... + + Change the default encoding assumed for all tables in the database + Change l'encodage par défaut choisi pour l'ensemble des tables de la base de données - - &Prefetch block size - Taille du bloc &Prefetch + + Clear Filters + Effacer les filtres - - &SQL - &SQL + + Clear all filters + Effacer tous les filtres - - Settings name - Définir le nom + + + This button clears all the filters set in the header input fields for the currently browsed table. + Ce bouton efface tous les filtres définis dans les champs de saisie de l'en-tête de la table actuellement parcourue. - - Context - Contexte + + Clear Sorting + Effacer le tri - - Colour - Couleur + + Reset the order of rows to the default + Rétablit l'ordre des lignes aux valeurs par défaut - - Bold - Gras + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + Ce bouton efface les critères de tri définis pour les colonnes de la table actuellement parcourue et revient à l'ordre par défaut. - - Italic - Italique + + Print + Imprimer - - Underline - Souligné + + Print currently browsed table data + Imprimer les données de la table actuelle - - Keyword - Mot Clé + + Print currently browsed table data. Print selection if more than one cell is selected. + Imprime les données de la table actuelle. Imprime la sélection si plus d'une cellule est sélectionnée. - - function - fonction + + Ctrl+P + - - Function - Fonction + + Refresh + Rafraîchir - - Table - Table + + Refresh the data in the selected table + Rafraîchir les données de la table sélectionnée - - Comment - Commentaire + + This button refreshes the data in the currently selected table. + Ce bouton permet de rafraîchir les données de la table actuellement sélectionnée. - - Identifier - Identifiant + + F5 + - - String - Chaîne de caractère + + Find in cells + Rechercher dans les cellules - - currentline - Ligne courante + + Open the find tool bar which allows you to search for values in the table view below. + Ouvre la barre d'outils de recherche qui vous permet de rechercher des valeurs dans la table ci-dessous. - - Current line - Ligne courante + + Freeze columns + Figer les colonnes - - SQL &editor font size - Taille de la police de l'&éditeur SQL + + Make all columns from the first column up to this column not move when scrolling horizontally + Fige toutes les colonnes de la première colonne jusqu'à cette colonne lors d'un défilement horizontal - - SQL &log font size - Taille de la police du fichier &journal SQL + + + Bold + Gras - - &Extensions - E&xtensions + + Ctrl+B + - - Select extensions to load for every database: - Sélectionner une extension à charger pour toutes les bases de données : + + + Italic + Italique - - Add extension - Ajouter une extension + + + Underline + Souligné - - Remove extension - Enlever une extension + + Ctrl+U + - - Choose a directory - Choisir un répertoire + + + Align Right + Aligner à droite - - Select extension file - Sélectionner un fichier d'extension + + + Align Left + Aligner à gauche - - Extensions(*.so *.dll);;All files(*) - Extensions (*.so *.dll);;Tous les fichiers (*) + + + Center Horizontally + Centrer horizontalement - - - QObject - - Error importing data. Message from database engine: %1 - Erreur lors de l'import des données. Message du moteur de base de données : -%1 + + + Justify + Justifié - - File is not a SQLite 3 database - Ce fichier n'est pas une base de données SQLite3 + + + Edit Conditional Formats... + Éditer les formats conditionnels... - - File could not be read - Le fichier ne peut être lu + + Edit conditional formats for the current column + Éditer les formats conditionnels de la colonne en cours - - - - no error - pas d'erreur + + Clear Format + Effacer les formats - - Do you want to save the changes made to the database file %1? - Voulez-vous enregistrer les changements effectués dans la base de données %1 ? + + Clear All Formats + Effacer tous les formats - - Exporting database to SQL file... - Exporter la base de données dans un fichier SQL... + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + Effacer tous les formats de cellule des cellules sélectionnées et tous les formats conditionnels des colonnes sélectionnées - - - - Cancel - Annuler + + + Font Color + Couleur de police - - Executing SQL... - Exécution du SQL... + + + Background Color + Couleur d'arrière-plan - - Action cancelled. - Action annulée. + + Toggle Format Toolbar + Changer le format de la barre d'outils - - - Error in statement #%1: %2. -Aborting execution. - Erreur dans le traitement #%1 : %2. -l'exécution est abandonnée. + + Show/hide format toolbar + Afficher/Cacher la barre des formats - - renameColumn: cannot find table %1. - Renommer les Colonnes : La table %1 ne peut être trouvée. + + + This button shows or hides the formatting toolbar of the Data Browser + Ce bouton permet d'afficher ou de masquer la barre d'outils de formatage du navigateur de données - - renameColumn: cannot find column %1. - Renommer les Colonnes : La colonne %1 ne peut être trouvée. + + Select column + Sélectionner une colonne - - renameColumn: creating savepoint failed. DB says: %1 - Renommer les Colonnes : La création d'un point de sauvegarde a échoué. Message du moteur de base de données : -%1 + + Ctrl+Space + - - renameColumn: creating new table failed. DB says: %1 - Renommer les Colonnes : La création de la table a échoué. Message du moteur de base de données : -%1 + + Replace text in cells + Remplace du texte dans les cellules - - renameColumn: copying data to new table failed. DB says: -%1 - Renommer les Colonnes : La copie des données dans une nouvelle table a échoué. Message du moteur de base de données : -%1 + + Filter in any column + Filtrer dans n'importe quelle colonne - - renameColumn: deleting old table failed. DB says: %1 - Renommer les Colonnes : La suppression de l'ancienne table a échoué. Message du moteur de base de données : -%1 + + Ctrl+R + + + + + %n row(s) + + %n ligne + %n lignes + + + + + , %n column(s) + + , %n colonne + , %n colonnes + - - Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: - - - La restauration de certains des objets associés à cette table a échoué. Cela est le plus souvent dû au changement du nom de certaines colonnes. Voici l'instruction SQL que vous pourrez corriger et exécuter manuellement : - + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . Somme: %1; Moyenne: %2; Min: %3; Max: %4 - - renameColumn: releasing savepoint failed. DB says: %1 - Renommer les Colonnes : La libération d'un point de sauvegarde a échoué. Message du moteur de base de données : -%1 + + Conditional formats for "%1" + Format conditionnel pour "%1" - - Error renaming table '%1' to '%2'.Message from database engine: -%3 - Erreur lors du changement de nom de la table %1 vers %2. Message du moteur de base de données : -%3 + + determining row count... + Détermination du nombre d'enregistrements... - - ... <string can not be logged, contains binary data> ... - ... <la Chaîne de caractère ne peut être journalisée. Elle contient des données binaires> ... + + %L1 - %L2 of >= %L3 + %L1 - %L2 of >= %L3 - - unknown object type %1 - Type d'objet %1 inconnu + + %L1 - %L2 of %L3 + %L1 - %L2 of %L3 - - could not get list of db objects: %1, %2 - la liste des objets de la base de données ne peut être obtenue : %1, %2 + + (clipped at %L1 rows) + (coupé à %L1 lignes) - - could not get types - la liste des types ne peut être obtenue + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + Veuillez entrer une pseudo clé primaire pour permettre l'édition de la vue. Ce devrait être le nom d'une colonne unique dans la vue. - - Decoding CSV file... - Décodage du fichier CSV... + + Delete Records + Supprimer les enregistrements - - didn't receive any output from pragma %1 - n'a pas reçu toutes les sorties du pragma %1 + + Duplicate records + Enregistrement en double - - could not execute pragma command: %1, %2 - ne peut pas exécuter les commandes du pragme : %1, %2 + + Duplicate record + Dupliquer l'enregistrement - - Error setting pragma %1 to %2: %3 - Erreur dans les paramètres du pragma %1 à %2 : %3 + + Ctrl+" + - - File not found. - Fichier non trouvé. + + Adjust rows to contents + Ajuster les lignes au contenu - - - SqlExecutionArea - - Form - Formulaire + + Error deleting record: +%1 + Erreur dans la suppression d'un enregistrement : +%1 - - Results of the last executed statements - Résultats du dernier traitement exécuté + + Please select a record first + Veuillez sélectionner au préalable un enregistrement - - This field shows the results and status codes of the last executed statements. - Ce champ affiche les résultats et les codes de statut du dernier traitement exécuté. + + Please choose a new encoding for all tables. + Veuillez choisir un nouvel encodage pour toutes les tables. - - Export to &CSV - Exporter au format &CSV + + Please choose a new encoding for this table. + Veuillez choisir un nouvel encodage pour cette table. - - Save as &view - Enregistrer comme une &vue + + %1 +Leave the field empty for using the database encoding. + %1 +Laissez le champ vide pour utiliser l'encodage de la base de données. - - Save as view - Enregistrer comme une vue + + This encoding is either not valid or not supported. + Cet encodage est invalide ou non supporté. - - Please specify the view name - Veuillez spécifier le nom de la vue + + %1 replacement(s) made. + %1 remplacement(s) effectué(s). + + + TableBrowserDock - - There is already an object with that name. Please choose a different name. - Il existe déjà un objet avec ce nom. Veuillez choisir un autre nom. + + New Data Browser + Nouveau navigateur de données - - View successfully created. - La vue a été crée avec succès. + + Rename Data Browser + Renommer le navigateur de données - - Error creating view: %1 - Erreur lors de la création de la vue : %1 + + Close Data Browser + Fermer le navigateur de données - - - SqliteTableModel - - Error changing data: -%1 - Erreur lors du changement des données : -%1 + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + Donnez un nouveau nom à l'explorateur de données. Utilisez le caractère "&&" pour permettre l'utilisation du caractère suivant comme raccourci clavier. @@ -2054,13 +8099,13 @@ l'exécution est abandonnée. - Warning: Compacting the database will commit all changes you made. + Warning: Compacting the database will commit all of your changes. Attention : compacter la base de donnée entraînera l'enregistrement de tous les changements effectués. - Please select the objects to compact: - Veuillez sélectionner les objets à compacter : + Please select the databases to co&mpact: + Veuillez sélectionner les bases de données à co&mpacter : diff --git a/src/translations/sqlb_id.ts b/src/translations/sqlb_id.ts new file mode 100644 index 000000000..e9ed47432 --- /dev/null +++ b/src/translations/sqlb_id.ts @@ -0,0 +1,8049 @@ + + + + + AboutDialog + + + About DB Browser for SQLite + Tentang Peramban DB untuk SQLite + + + + Version + Versi + + + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + <html><head/><body><p>Peramban DB untuk SQLite adalah alat visual sumber terbuka dan perangkat lunak bebas yang digunakan untuk membuat, mendesain, dan mengedit berkas basis data SQLite.</p><p>Alat ini memiliki dua lisensi yaitu Lisensi Publik Mozilla Versi 2, dan Lisensi Publik Umum GNU Versi 3 atau yang lebih baru. Anda dapat memodifikasi atau mendistribusikannya kembali berdasarkan ketentuan lisensi ini.</p><p>Lihat <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> dan <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> untuk detailnya.</p><p>Untuk informasi lebih lanjut tentang program ini, silakan kunjungi situs web kami di: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; warna:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">Perangkat lunak ini menggunakan GPL/LGPL Qt Toolkit dari </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; warna:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>Lihat </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> untuk ketentuan dan informasi lisensi.</span></p><p><span style=" font-size:8pt;">Kami menggunakan pustaka nalgeon/sqlean untuk dukungan ekstensi SQLite.<br/>Pustaka ini dilisensikan di bawah lisensi MIT, lihat berikut ini untuk informasi lebih lanjut:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">Ini juga menggunakan set ikon SVG Pastel yang dibuat oleh Michael Buckley di bawah lisensi Creative Commons Attribution Share Alike 4.0.<br/>Lihat </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> untuk detailnya.</span></p></body></html> + + + + AddRecordDialog + + + Add New Record + Menambah Record Baru + + + + Enter values for the new record considering constraints. Fields in bold are mandatory. + Masukkan nilai bagi record baru dengan mempertimbangkan batasan. Ruas yang dicetak tebal adalah wajib. + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + Dalam kolom Nilai Anda dapat menyatakan nilai bagi ruas yang diidentifikasi dalam kolom Nama. Kolom Tipe mengindikasikan tipe ruas. Nilai baku ditampilkan dengan gaya yang sama dengan nilai NULL. + + + + Name + Nama + + + + Type + Tipe + + + + Value + Nilai + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + Nilai yang akan disisipkan. Nilai baku yang terpraisi disisipkan secara otomatis kecuali bila mereka diubah. + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + Ketika Anda menyunting nilai-nilai dalam kerangka atas, query SQL untuk menyisipkan record baru ini ditampilkan di sini. Anda dapat menyunting query secara manual sebelum menyimpan. + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Simpan</span> akan mengirim pernyataan SQL yang ditunjukkan ke basis data untuk menyisipkan record baru.</p><p><span style=" font-weight:600;">Pulihkan Baku</span> akan memulihkan nilai-nilai awal dalam kolom <span style=" font-weight:600;">Nilai</span>.</p><p><span style=" font-weight:600;">Batal</span> akan menutup dialog ini tanpa mengeksekusi query.</p></body></html> + + + + Auto-increment + + Inkremen otomatis + + + + + Unique constraint + + Batasan unik + + + + + Check constraint: %1 + + Periksa konstrain: %1 + + + + + Foreign key: %1 + + Foreign key: %1 + + + + + Default value: %1 + + Nilai baku: %1 + + + + + Error adding record. Message from database engine: + +%1 + Kesalahan saat menambah record. Pesan dari mesin basis data: + +%1 + + + + Are you sure you want to restore all the entered values to their defaults? + Anda yakin hendak memulihkan semua nilai yang dimasukkan ke nilai baku mereka? + + + + Application + + + Possible command line arguments: + Argumen baris perintah yang mungkin: + + + + The user settings file location is replaced with the argument value instead of the environment variable value. + Lokasi berkas pengaturan pengguna digantikan dengan nilai argumen bukan nilai variabel lingkungan. + + + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + Nilai variabel lingkungan (DB4S_SETTINGS_FILE) yang diabaikan: + + + + + The file %1 does not exist + Berkas %1 tidak ada + + + + Usage + Cara pakai + + + + options + opsi + + + + + database + basis_data + + + + + project + proyek + + + + + csv-file + berkas-csv + + + + Show command line options + Tampilkan opsi baris perintah + + + + Exit application after running scripts + Keluar aplikasi setelah menjalankan skrip + + + + + file + berkas + + + + Execute this SQL file after opening the DB + Jalankan berkas SQL ini setelah membuka DB + + + + Import this CSV file into the passed DB or into a new DB + Impor berkas CSV ini ke dalam DB yang diberikan atau ke dalam suatu DB baru + + + + table + tabel + + + + Browse this table, or use it as target of a data import + Ramban tabel ini, atau gunakan itu sebagai target dari suatu impor data + + + + Open database in read-only mode + Buka basis data dalam mode hanya baca + + + + settings_file + berkas_pengaturan + + + + Run application based on this settings file + Jalankan aplikasi berbasis pada berkas pengaturan ini + + + + + group + grup + + + + + settings + pengaturan + + + + + value + nilai + + + + Run application with this setting temporarily set to value + Menjalankan aplikasi dengan pengaturan ini sementara ditata ke nilai + + + + Run application saving this value for this setting + Menjalankan aplikasi dengan menyimpan nilai bagi pengaturan ini + + + + Display the current version + Menampilkan versi saat ini + + + + Open this SQLite database + Buka basis data SQLite ini + + + + Open this project file (*.sqbpro) + Buka berkas proyek ini (*.sqbpro) + + + + Import this CSV file into an in-memory database + Impor berkas CSV ini ke dalam suatu basis data dalam memori + + + + + + The %1 option requires an argument + Opsi %1 memerlukan sebuah argumen + + + + The -S/--settings option requires an argument. The option is ignored. + Opsi -S/--settings memerlukan sebuah argumen. Opsi diabaikan. + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + Opsi -o/--option dan -O/--save-option memerlukan sebuah argumen dalam bentuk grup/pengaturan=nilai + + + + Invalid option/non-existent file: %1 + Opsi tidak valid/berkas tidak ada: %1 + + + + SQLite Version + Versi SQLite + + + + SQLCipher Version %1 (based on SQLite %2) + SQLCipher Versi %1 (berbasis SQLite %2) + + + + DB Browser for SQLite Version %1. + Peramban DB untuk SQLite Versi %1. + + + + Last commit hash when built: %1 + Hash commit terakhir ketika dibangun: %1 + + + + Built for %1, running on %2 + Dibangun untuk %1, dijalankan pada %2 + + + + Qt Version %1 + Qt Versi %1 + + + + CipherDialog + + + SQLCipher encryption + Enkripsi SQLCipher + + + + &Password + Kata &Sandi + + + + &Reenter password + Masu&kkan lagi kata sandi + + + + Encr&yption settings + Pengaturan enkr&ipsi + + + + SQLCipher &3 defaults + Baku SQLCipher &3 + + + + SQLCipher &4 defaults + Baku SQLCipher &4 + + + + Custo&m + Ubaha&n + + + + Page si&ze + Uk&uran halaman + + + + &KDF iterations + Iterasi &KDF + + + + HMAC algorithm + Algoritme HMAC + + + + KDF algorithm + Algoritme KDF + + + + Plaintext Header Size + Ukuran Header Teks Polos + + + + Passphrase + Frasa Sandi + + + + Raw key + Kunci mentah + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + Harap atur kunci untuk mengenkripsi basis data. +Catat bahwa bila Anda mengubah sebarang pengaturan opsional lain, Anda akan perlu memasukkan ulang mereka juga setiap kali Anda membuka berkas basis data. +Biarkan ruas kata sandi kosong untuk menonaktifkan enkripsi. +Proses enkripsi mungkin perlu beberapa waktu dan Anda mesti memiliki salinan cadangan dari basis data Anda! Perubahan yang belum tersimpan diterapkan sebelum mengubah enkripsi. + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + Harap masukkan kunci yang dipakai untuk mengenkripsi basis data. +Bila sebarang pengaturan lain diubah untuk berkas basis data ini, Anda perlu menyediakan informasi ini juga. + + + + ColumnDisplayFormatDialog + + + Choose display format + Pilih format tampilan + + + + Display format + Format tampilan + + + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + Pilih suatu format tampilan bagi kolom '%1' yang diterapkan ke setiap nilai sebelum menunjukkannya. + + + + Default + Baku + + + + Decimal number + Bilangan desimal + + + + Exponent notation + Notasi eksponensial + + + + Hex blob + Blob heksa + + + + Hex number + Bilangan heksa + + + + Apple NSDate to date + NSDate Apple ke tanggal + + + + Java epoch (milliseconds) to date + Epos Java (milidetik) ke tanggal + + + + .NET DateTime.Ticks to date + DateTime.Ticks .NET ke tanggal + + + + Julian day to date + Hari Julian ke tanggal + + + + Unix epoch to local time + Epos Unix ke waktu lokal + + + + WebKit / Chromium epoch to date + Epos Webkit / Chromium ke tanggal + + + + WebKit / Chromium epoch to local time + Epos Webkit / Chromium ke waktu lokal + + + + Date as dd/mm/yyyy + Tanggal sebagai dd/mm/yyyy + + + + Lower case + Huruf kecil + + + + Binary GUID to text + GUID biner ke teks + + + + SpatiaLite Geometry to SVG + SpatiaLite Geometry ke SVG + + + + Custom display format must contain a function call applied to %1 + Format tampilan ubahan mesti memuat suatu pemanggilan fungsi yang diterapkan ke %1 + + + + Error in custom display format. Message from database engine: + +%1 + Kesalahan dalam format tampilan ubahan. Pesan dari mesin basis data: + +%1 + + + + Custom display format must return only one column but it returned %1. + Format tampilan ubahan mesti mengembalikan hanya satu kolom tapi itu mengembalikan %1. + + + + Octal number + Bilangan oktal + + + + Round number + Bilangan bulat + + + + Unix epoch to date + Epos Unix ke tanggal + + + + Upper case + Huruf besar + + + + Windows DATE to date + DATE Windows ke tanggal + + + + Custom + Ubahan + + + + CondFormatManager + + + Conditional Format Manager + Manajer Format Bersyarat + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + Dialog ini memungkinkan pembuatan dan penyuntingan format bersyarat. Setiap gaya sel akan dipilih berdasarkan syarat yang pertama terpenuhi untuk data sel itu. Format bersyarat dapat dipindah naik dan turun, yang ada pada baris lebih tinggi lebih diutamakan dari pada yang lebih rendah. Sintaks untuk syarat sama dengan bagi filter dan suatu syarat kosong berlaku untuk semua nilai. + + + + Add new conditional format + Tambahkan format bersyarat yang baru + + + + &Add + T&ambah + + + + Remove selected conditional format + Hapus format bersyarat yang dipilih + + + + &Remove + &Hapus + + + + Move selected conditional format up + Pindahkan ke atas format bersyarat yang dipilih + + + + Move &up + &Naikkan + + + + Move selected conditional format down + Pindahkan ke bawah format bersyarat yang dipilih + + + + Move &down + &Turunkan + + + + Foreground + Latar depan + + + + Text color + Warna teks + + + + Background + Latar belakang + + + + Background color + Warna latar belakang + + + + Font + Fonta + + + + Size + Ukuran + + + + Bold + Tebal + + + + Italic + Miring + + + + Underline + Garis bawah + + + + Alignment + Perataan + + + + Condition + Syarat + + + + + Click to select color + Klik untuk memilih warna + + + + Are you sure you want to clear all the conditional formats of this field? + Anda yakin hendak membersihkan semua format bersyarat atas ruas ini? + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + Harap nyatakan nama basis data yang akan dipakai untuk mengakses basis data yang dicantol + + + + Invalid file format + Format berkas tidak valid + + + + Do you really want to close this temporary database? All data will be lost. + Anda yakin hendak menutup basis data temporer ini? Semua data akan hilang. + + + + Do you want to save the changes made to the database file %1? + Apakah Anda ingin menyimpan perubahan yang dibuat ke berkas basis data %1? + + + + Database didn't close correctly, probably still busy + Basis data tidak ditutup secara benar, mungkin masih sibuk + + + + Cannot open destination file: '%1' + Tidak bisa membuka berkas tujuan: '%1' + + + + + Cannot backup to file: '%1'. Message: %2 + Tidak bisa mencadangkan ke berkas: '%1'. Pesan %2 + + + + The database is currently busy: + Basis data saat ini sibuk: + + + + Do you want to abort that other operation? + Apakah Anda ingin menggugurkan operasi lain itu? + + + + Exporting database to SQL file... + Mengekspor basis data ke berkas SQL... + + + + + Cancel + Batal + + + + + No database file opened + Tidak ada berkas basis data yang dibuka + + + + Executing SQL... + Mengeksekusi SQL... + + + + Action cancelled. + Aksi dibatalkan. + + + + + Error in statement #%1: %2. +Aborting execution%3. + Kesalahan dalam pernyataan #%1: %2. +Menggugurkan eksekusi %3. + + + + + and rolling back + dan me-roll back + + + + didn't receive any output from %1 + tak menerima keluaran apa pun dari %1 + + + + could not execute command: %1 + tidak bisa mengeksekusi perintah: %1 + + + + Cannot delete this object + Tidak bisa menghapus objek ini + + + + Cannot set data on this object + Tidak bisa menata data pada objek ini + + + + + A table with the name '%1' already exists in schema '%2'. + Sebuah tabel dengan nama '%1' sudah ada dalam skema '%2'. + + + + No table with name '%1' exists in schema '%2'. + Tidak ada tabel dengan nama '%1' ada dalam skema '%2'. + + + + + Cannot find column %1. + Tidak bisa temukan kolom %1. + + + + Creating savepoint failed. DB says: %1 + Gagal membuat savepoint. Pesan DB: %1 + + + + Renaming the column failed. DB says: +%1 + Gagal mengubah nama kolom. Pesan DB: +%1 + + + + + Releasing savepoint failed. DB says: %1 + Gagal melepas savepoint. Pesan DB: %1 + + + + Creating new table failed. DB says: %1 + Gagal membuat tabel baru. Pesan DB: %1 + + + + Copying data to new table failed. DB says: +%1 + Gagal menyalin data ke tabel baru. Pesan DB: +%1 + + + + Deleting old table failed. DB says: %1 + Gagal menghapus tabel lama. Pesan DB: %1 + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + Gagal memulihkan beberapa objek yang terkait dengan tabel ini. Ini sangat boleh jadi karena beberapa nama kolom berubah. Ini pernyataan SQL yang mungkin ingin Anda perbaiki dan eksekusi secara manual: + + + + + + could not get list of databases: %1 + tidak bisa memperoleh daftar basis data: %1 + + + + Error loading extension: %1 + Kesalahan saat memuat ekstensi: %1 + + + + Error loading built-in extension: %1 + Kesalahan saat memuat ekstens bawaani: %1 + + + + could not get column information + tidak bisa memperoleh informasi kolom + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + Kesalahan saat mengubah nama tabel '%1' menjadi '%2'. +Pesan dari mesin basis data: +%3 + + + + could not get list of db objects: %1 + tidak bisa memperoleh daftar obyek db: %1 + + + + Error setting pragma %1 to %2: %3 + Kesalahan saat mengatur pragma %1 ke %2: %3 + + + + File not found. + Berkas tidak ditemukan. + + + + DbStructureModel + + + Name + Nama + + + + Object + Objek + + + + Type + Tipe + + + + Schema + Skema + + + + Database + Basis data + + + + Browsables + Dapat diramban + + + + All + Semua + + + + Temporary + Sementara + + + + Tables (%1) + Tabel (%1) + + + + Indices (%1) + Indeks (%1) + + + + Views (%1) + View (%1) + + + + Triggers (%1) + Trigger (%1) + + + + EditDialog + + + Edit database cell + Sunting sel basis data + + + + Mode: + Mode: + + + + + Image + Gambar + + + + Set as &NULL + Atur sebagai &NULL + + + + Apply data to cell + Terapkan data ke sel + + + + This button saves the changes performed in the cell editor to the database cell. + Tombol ini menyimpan perubahan yang dilakukan dalam penyunting sel ke sel basis data. + + + + Apply + Terapkan + + + + Text + Teks + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + Ini adalah daftar mode yang didukung untuk penyunting sel. Pilih suatu mode untuk menilik atau menyunting data dari sel saat ini. + + + + RTL Text + Teks RTL + + + + Binary + Biner + + + + JSON + JSON + + + + XML + XML + + + + Evaluation + Evaluasi + + + + + Automatically adjust the editor mode to the loaded data type + Secara otomatis menyetel mode penyunting ke tipe data yang dimuat + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + Tombol yang dapat dicentang ini memfungsikan atau menonaktifkan pemindahan otomatis mode penyunting. Ketika sebuah sel baru dipilih atau data baru diimpor dan pemindahan otomatis difungsikan, mode disesuaikan ke tipe data yang terdeteksi. Anda kemudian dapat mengubah mode penyunting secara manual. Bila Anda ingin mempertahankan mode yang berpindah manual ini ketika bergerak melalui sel, matikan tombol. + + + + Auto-switch + Berpindah otomatis + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + Penyunting Qt ini dipakai untuk skrip kanan ke kiri, yang tidak didukung oleh penyunting Teks baku. Keberadaan karakter kanan ke kiri terdeteksi dan mode penyunting ini dipilih secara otomatis. + + + + Identification of the cell currently in the editor + Identifikasi dari sel yang saat ini dalam penyunting + + + + Type and size of data currently in table + Tipe dan ukuran data yang saat ini dalam tabel + + + + Open preview dialog for printing the data currently stored in the cell + Buka dialog pratinjau untuk mencetak data yang saat ini disimpan dalam sel + + + + Auto-format: pretty print on loading, compact on saving. + Format otomatis: cetak cantik saat memuat, padatkan saat menyimpan. + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + Ketika difungsikan, fitur format otomatis memformat data saat memuat, memecah teks dalam baris-baris, dan mengindentasi untuk keterbacaan maksimal. Saat menyimpan data, fitur format otomatis memampatkan data menghapus akhir baris, dan ruang spasi yang tak perlu. + + + + Word Wrap + Lipat Kata + + + + Wrap lines on word boundaries + Lipat baris pada perbatasan kata + + + + + Open in default application or browser + Buka dalam aplikasi baku atau peramban + + + + Open in application + Buka dalam aplikasi + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + Nilai diinterpretasi sebagai suatu berkas atau URL dan dibuka dalam aplikasi baku atau peramban web. + + + + Save file reference... + Simpan acuan berkas... + + + + Save reference to file + Simpan acuan ke berkas + + + + + Open in external application + Buka dalam aplikasi eksternal + + + + Autoformat + Format otomatis + + + + &Export... + &Ekspor... + + + + + &Import... + &Impor... + + + + + Import from file + Impor dari berkas + + + + + Opens a file dialog used to import any kind of data to this database cell. + Membuka sebuah dialog berkas yang dipakai untuk mengimpor sebarang jenis data ke sel basis data ini. + + + + Export to file + Ekspor ke berkas + + + + Opens a file dialog used to export the contents of this database cell to a file. + Membuka sebuah dialog berkas yang dipakai untuk mengekspor ini sel basis data ini ke suatu berkas. + + + + Erases the contents of the cell + Menghapus isi sel + + + + This area displays information about the data present in this database cell + Wilayah ini menampilkan informasi tentang data yang ada dalam sel basis data ini + + + + Print... + Cetak... + + + + Ctrl+P + Ctrl+P + + + + Open preview dialog for printing displayed text + Membuka dialog pratinjau untuk mencetak teks yang ditampilkan + + + + Copy Hex and ASCII + Salin Heksa dan ASCII + + + + Copy selected hexadecimal and ASCII columns to the clipboard + Menyalin kolom-kolom ASCII dan heksadesimal yang dipilih ke papan klip + + + + Ctrl+Shift+C + Ctrl+Shift+C + + + + Choose a filename to export data + Pilih suatu nama berkas untuk mengekspor data + + + + + Image data can't be viewed in this mode. + Data gambar tak bisa dilihat dalam mode ini. + + + + + Try switching to Image or Binary mode. + Cobalah beralih ke mode Gambar atau Biner. + + + + + Binary data can't be viewed in this mode. + Data biner tak dapat dilihat dalam mode ini. + + + + + Try switching to Binary mode. + Cobalah beralih ke mode Biner. + + + + + Image files (%1) + Berkas gambar (%1) + + + + Binary files (*.bin) + Berkas biner (*.bin) + + + + + Type: NULL; Size: 0 bytes + Tipe: NULL; Ukuran: 0 byte + + + + + Type: Text / Numeric; Size: %n character(s) + + Tipe: Teks/Numerik; Ukuran: %n karakter + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + Tipe: Citra %1; Ukuran: %2x%3 piksel + + + + Type: Valid JSON; Size: %n character(s) + + Tipe: JSON yang Valid; Ukuran: %n karakter + + + + + Type: Binary; Size: %n byte(s) + + Tipe: Biner; Ukuran: %n byte + + + + + Couldn't save file: %1. + Tak bisa menyimpan berkas: %1. + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + Data telah disimpan ke suatu berkas temporer dan telah dibuka dengan aplikasi baku. Kini Anda dapat menyunting berkas, dan ketika Anda siap, menerapkan data baru yang disimpanke sel atau membatalkan perubahan apa pun. + + + + Choose a file to import + Pilih suatu berkas untuk diimpor + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + Mode penyunting teks memungkinkan Anda menyunting berkas polos, maupun data XML atau JSON dengan penyorotan sintaks, pemformatan otomatis, dan validasi sebelum menyimpan. + +Kesalahan diindikasikan dengan garis bawah cacing merah. + +Dalam mode Evaluasi, ekspresi SQLite yang dimasukkan dievaluasi dan hasilnya diterapkan ke sel. + + + + Unsaved data in the cell editor + Data belum disimpan dalam penyunting sel + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + Penyunting sel memuat data yang belum diterapkan ke basis data. +Apakah Anda hendak menerapkan data yang disunting ke baris=%1, kolom=%2? + + + + Editing row=%1, column=%2 + Menyunting baris=%1, kolom=%2 + + + + No cell active. + Tidak ada sel yang aktif. + + + + %1 Image + Gambar %1 + + + + Invalid data for this mode + Data tidak valid bagi mode ini + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + Sel memuat data %1 yang tidak valid. Alasan: %2. Anda yakin ingin menerapkannya ke sel? + + + + EditIndexDialog + + + &Name + &Nama + + + + Order + Urutan + + + + &Table + &Tabel + + + + Edit Index Schema + Sunting Skema Indeks + + + + &Unique + &Unik + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + Untuk membatasi indeks hanya ke suatu bagian dari tabel Anda dapat menyatakan suatu klausa WHERE di sini yang memilih bagian dari tabel yang mesti diindeks + + + + Partial inde&x clause + &Klausa indeks parsial + + + + Colu&mns + Kolo&m + + + + Table column + Kolom tabel + + + + Type + Tipe + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + Menambah sebuah kolom ekspresi baru ke indeks. Kolom ekspresi memuat pernyataan SQL, bukan nama-nama kolom. + + + + Index column + Kolom indeks + + + + Deleting the old index failed: +%1 + Menghapus indeks lama gagal: +%1 + + + + Creating the index failed: +%1 + Membuat indeks gagal: +%1 + + + + EditTableDialog + + + Edit table definition + Sunting definisi tabel + + + + Table + Tabel + + + + Advanced + Tingkat lanjut + + + + Without Rowid + Tanpa Rowid + + + + Database sche&ma + Ske&ma basis data + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + Jadikan ini suatu tabel 'WITHOUT ROWID'. Menetapkan flag ini memerlukan penentuan PRIMARY KEY (yang dapat berupa jenis apa pun, dan dapat berupa komposit), dan melarang flag AUTOINCREMENT. + + + + On Conflict + Saat Konflik + + + + Strict + Ketat + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + Ketika opsi ketat difungsikan, SQLite memaksakan tipe data dari setiap kolom ketika memperbarui atau menyisipkan data. + + + + Fields + Ruas + + + + + + Add + Tambah + + + + + + Remove + Hapus + + + + Move to top + Pindah ke puncak + + + + Move up + Naikkan + + + + Move down + Turunkan + + + + Move to bottom + Pindah ke dasar + + + + + + + Name + Nama + + + + + Type + Tipe + + + + NN + NN + + + + Not null + Tidak null + + + + PK + PK + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> Kunci primer</p></body></html> + + + + AI + AI + + + + Autoincrement + Inkremen otomatis + + + + U + U + + + + + + Unique + Unik + + + + Default + Baku + + + + Default value + Nilai baku + + + + + Check + Periksa + + + + Check constraint + Periksa konstrain + + + + Collation + Kolasi + + + + Foreign Key + Foreign Key + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + + + + Index Constraints + Konstrain Indeks + + + + Add constraint + Tambah konstrain + + + + Remove constraint + Hapus konstrain + + + + + Columns + Kolom + + + + + + SQL + SQL + + + + Foreign Keys + Foreign Key + + + + References + Referensi + + + + Check Constraints + Periksa Konstrain + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Peringatan: </span>Ada sesuatu pada definisi tabel ini yang parser kami tidak sepenuhnya paham. Mengubah dan menyimpan tabel ini dapat menyebabkan masalah.</p></body></html> + + + + + Primary Key + Kunci Primer + + + + Add a primary key constraint + Tambahkan konstrain kunci primer + + + + Add a unique constraint + Tambahkan konstrain unik + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + Hanya boleh ada satu kunci primer bagi setiap tabel. Harap ubah kunci primer yang ada sebagai pengganti. + + + + Error creating table. Message from database engine: +%1 + Kesalahan saat membuat tabel. Pesan dari mesin basis data: +%1 + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + Sudah ada ruas dengan nama itu. Harap terlebih dahulu ubah namanya atau pilih suatu nama lain untuk ruas ini. + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + Kolom ini diacu dalam suatu foreign key dalam tabel %1 sehingga namanya tidak dapat diubah. + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + Ada paling tidak satu baris dengan ruas ini diatur ke NULL. Menjadi tidak mungkin menata flag ini. Harap ubah data tabel terlebih dahulu. + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + Ada paling tidak satu baris dengan nilai non integer dalam ruas ini. Menjadi tidak mungkin menata flag AI. Harap ubah data tabel terlebih dahulu. + + + + Column '%1' has duplicate data. + + Kolom '%1' punya data duplikat. + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + Menjadi tidak mungkin memfungsikan flag 'Unik'. Harap hapus data duplikat, yang akan mengizinkan flag 'Unik' untuk difungsikan. + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + Anda yakin ingin menghapus ruas '%1'? +Semua data yang saat ini disimpan dalam ruas ini akan hilang. + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + Harap tambahkan suatu ruas yang memenuhi kriteria berikut sebelum menata flag tanpa rowid: + - Flag kunci primer ditata + - Inkremen otomatis dinonaktifkan + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + Harap tambahkan suatu ruas yang memenuhi kriteria berikut sebelum menata aksi saat konflik: + - Flag kunci primer ditata + + + + ExportDataDialog + + + Export data as CSV + Ekspor data sebagai CSV + + + + Tab&le(s) + Tabe&l + + + + Colu&mn names in first line + Nama-nama kolo&m dalam baris pertama + + + + Fie&ld separator + Pemisah rua&s + + + + , + , + + + + ; + ; + + + + Tab + Tab + + + + | + | + + + + + + Other + Lainnya + + + + &Quote character + Karakter &kutip + + + + " + " + + + + ' + ' + + + + New line characters + Karakter baris baru + + + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) + + + + Unix: LF (\n) + Unix: LF (\n) + + + + Pretty print + Cetak cantik + + + + + Could not open output file: %1 + Tidak bisa membuka berkas keluaran: %1 + + + + + Choose a filename to export data + Pilih suatu nama berkas untuk mengekspor data + + + + Export data as JSON + Ekspor data sebagai JSON + + + + exporting CSV + mengekspor CSV + + + + + Error while writing the file '%1': %2 + Kesalahan saat menulis berkas '%1': %2 + + + + exporting JSON + mengekspor JSON + + + + Please select at least 1 table. + Harap pilih setidaknya 1 tabel. + + + + Choose a directory + Pilih suatu direktori + + + + Export completed. + Ekspor selesai. + + + + Export finished with errors. + Ekspor selesai dengan kesalahan. + + + + ExportSqlDialog + + + Export SQL... + Ekspor SQL... + + + + Tab&le(s) + Tabe&l + + + + Select All + Pilih Semua + + + + Deselect All + Pilih Tak Satu Pun + + + + &Options + &Opsi + + + + Keep column names in INSERT INTO + Pertahankan nama-nama kolom dalam INSERT INTO + + + + Multiple rows (VALUES) per INSERT statement + Beberapa baris (VALUES) per pernyataan INSERT + + + + Export everything + Ekspor semuanya + + + + Export data only + Hanya ekspor data + + + + Keep original CREATE statements + Pertahankan pernyataan CREATE asli + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + Pertahankan skema lama (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + Timpa skema lama (DROP TABLE, lalu CREATE TABLE) + + + + Export schema only + Ekspor skema saja + + + + Please select at least one table. + Harap pilih paling tidak satu tabel. + + + + Choose a filename to export + Pilih suatu nama berkas untuk ekspor + + + + Export completed. + Ekspor selesai. + + + + Export cancelled or failed. + Ekspor dibatalkan atau gagal. + + + + ExtendedScintilla + + + + Ctrl+H + Ctrl+H + + + + Ctrl+F + Ctrl+F + + + + + Ctrl+P + Ctrl+P + + + + Find... + Cari... + + + + Find and Replace... + Cari dan Ganti... + + + + Print... + Cetak... + + + + ExtendedTableWidget + + + Use as Exact Filter + Gunakan sebagai Filter Eksak + + + + Containing + Memuat + + + + Not containing + Tidak memuat + + + + Not equal to + Tidak sama dengan + + + + Greater than + Lebih dari + + + + Less than + Kurang dari + + + + Greater or equal + Lebih dari atau sama dengan + + + + Less or equal + Kurang dari atau sama dengan + + + + Between this and... + Antara ini dan... + + + + Regular expression + Ekspresi reguler + + + + Edit Conditional Formats... + Sunting Format Bersyarat... + + + + Set to NULL + Atur ke NULL + + + + Cut + Potong + + + + Copy + Salin + + + + Copy with Headers + Salin dengan Header + + + + Copy as SQL + Salin sebagai SQL + + + + Paste + Tempel + + + + Print... + Cetak... + + + + Use in Filter Expression + Pakai dalam Ekspresi Filter + + + + Alt+Del + Alt+Del + + + + Ctrl+Shift+C + Ctrl+Shift+C + + + + Ctrl+Alt+C + Ctrl+Alt+C + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + Konten papan klip lebih besar daripada rentang yang dipilih. +Tetap disisipkan? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>Belum semua data dimuat. <b>Apakah Anda ingin memuat semua data sebelum memilih semua baris?</b><p><p>Menjawab <b>Tidak</b> berarti tidak ada lagi data yang akan dimuat dan pemilihan tidak akan dilaksanakan.<br/>Menjawab <b>Ya</b> mungkin akan makan waktu ketika data dimuat tapi pemilihan akan lengkap.</p>Peringatan: Memuat semua data mungkin memerlukan sejumlah besar memori untuk tabel-tabel besar. + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + Tidak bisa menata pilihan ke NULL. Kolom %1 memiliki konstrain NOT NULL. + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + + + + FileExtensionManager + + + File Extension Manager + Manajer Ekstensi Berkas + + + + &Up + &Naik + + + + &Down + &Turun + + + + &Add + T&ambah + + + + &Remove + &Hapus + + + + + Description + Deskripsi + + + + Extensions + Ekstensi + + + + *.extension + *.extension + + + + FilterLineEdit + + + Filter + Filter + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + Ruas masukan ini memungkinkan Anda melakukan penyaringan cepat dalam tabel +yang saat ini sedang dipilih. Secara baku, baris yang memuat teks masukan disaring. +Operator berikut juga didukung: +% Wildcard +> Lebih dari +< Kurang dari +>= Sama dengan atau lebih dari +<= Sama dengan atau kurang dari += Sama dengan: cocok eksak +<> Tidak sama dengan: ketidakcocokan eksak +x~y Rentang: nilai antara x dan y +/regexp/ Nilai yang cocok dengan ekspresi reguler + + + + Clear All Conditional Formats + Bersihkan Semua Format Bersyarat + + + + Use for Conditional Format + Gunakan untuk Format Bersyarat + + + + Edit Conditional Formats... + Sunting Format Bersyarat... + + + + Set Filter Expression + Atur Ekspresi Filter + + + + What's This? + Apa Ini? + + + + Is NULL + NULL + + + + Is not NULL + Bukan NULL + + + + Is empty + Kosong + + + + Is not empty + Tidak kosong + + + + Not containing... + Tidak memuat... + + + + Equal to... + Sama dengan... + + + + Not equal to... + Tidak sama dengan... + + + + Greater than... + Lebih dari... + + + + Less than... + Kurang dari... + + + + Greater or equal... + Lebih dari atau sama dengan... + + + + Less or equal... + Kurang dari atau sama dengan... + + + + In range... + Dalam rentang... + + + + Regular expression... + Ekspresi reguler... + + + + FindReplaceDialog + + + Find and Replace + Cari dan Ganti + + + + Fi&nd text: + &Cari teks: + + + + Re&place with: + &Ganti dengan: + + + + Match &exact case + Cocok b&esar kecil huruf + + + + Match &only whole words + C&ocok hanya ke kata lengkap + + + + When enabled, the search continues from the other end when it reaches one end of the page + Saat difungsikan, pencarian berlanjut dari ujung lain ketika itu mencapai suatu ujung dari halaman + + + + &Wrap around + Putar &balik + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + Saat ditata, pencarian dilakukan ke arah mundur dari posisi kursor, bila tidak itu ke arah maju + + + + Search &backwards + Cari &mundur + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>Saat dicentang, pola yang akan dicari hanya dicari pada pilihan saat ini.</p></body></html> + + + + &Selection only + &Hanya pilihan + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Saat dicentang, pola yang akan dicari diinterpretasikan sebagai suatu ekspresi reguler UNIX. Lihat <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Ekspresi Reguler dalam Wikibook</a>.</p></body></html> + + + + Use regular e&xpressions + Pakai e&kspresi reguler + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + Cari kemunculan berikutnya dari posisi kursor dan dalam arah yang diatur oleh "Cari mundur" + + + + &Find Next + &Cari Selanjutnya + + + + F3 + F3 + + + + &Replace + &Ganti + + + + Highlight all the occurrences of the text in the page + Soroti semua kemunculan teks dalam halaman + + + + F&ind All + Car&i Semua + + + + Replace all the occurrences of the text in the page + Ganti semua kemunculan teks dalam halaman + + + + Replace &All + Ganti Semu&a + + + + The searched text was not found + Teks yang dicari tidak ditemukan + + + + The searched text was not found. + Teks yang dicari tidak ditemukan. + + + + The searched text was found one time. + Teks yang dicari ditemukan satu kali. + + + + The searched text was found %1 times. + Teks yang dicari ditemukan %1 kali. + + + + The searched text was replaced one time. + Teks yang dicari diganti satu kali. + + + + The searched text was replaced %1 times. + Teks yang dicari diganti %1 kali. + + + + ForeignKeyEditor + + + &Reset + &Reset + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + Klausa foreign key (ON UPDATE, ON DELETE dsb.) + + + + ImageViewer + + + Image Viewer + Penampil Citra + + + + Reset the scaling to match the original size of the image. + Reset skala agar cocok dengan ukuran asli citra. + + + + Set the scaling to match the size of the viewport. + Tata skala agar cocok dengan ukuran viewport. + + + + Print... + Cetak... + + + + Open preview dialog for printing displayed image + Buka dialog pratinjau untuk mencetak citra yang ditampilkan + + + + Ctrl+P + Ctrl+P + + + + ImportCsvDialog + + + Import CSV file + Impor berkas CSV + + + + Table na&me + Na&ma tabel + + + + &Column names in first line + Nama &kolom pada baris pertama + + + + Field &separator + Pemi&sah ruas + + + + , + , + + + + ; + ; + + + + + Tab + Tab + + + + | + | + + + + Other + Lainnya + + + + &Quote character + Karakter kuti&p + + + + + Other (printable) + Lainnya (dapat dicetak) + + + + + Other (code) + Lainnya (kode) + + + + " + " + + + + ' + ' + + + + &Encoding + P&engkodean + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Trim fields? + Pangkas ruas? + + + + Separate tables + Pisahkan tabel-tabel + + + + Advanced + Tingkat lanjut + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + Ketika mengimpor suatu nilai kosong dari berkas CSV ke dalam tabel yang telah ada dengan suatu nilai baku bagi kolom ini, nilai baku tersebut disisipkan. Aktifkan opsi ini untuk menyisipkan nilai kosong sebagai pengganti. + + + + Ignore default &values + Abaikan nilai-nilai &baku + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + Aktifkan opsi ini untuk menghentikan impor ketika mencoba mengimpor suatu nilai kosong ke dalam kolom NOT NULL tanpa suatu nilai baku. + + + + Fail on missing values + Gagal saat ada nilai yang hilang + + + + Disable data type detection + Nonaktifkan deteksi tipe data + + + + Disable the automatic data type detection when creating a new table. + Nonaktifkan deteksi tipe data otomatis ketika membuat sebuah tabel baru. + + + + Use local number conventions + Gunakan konvensi bilangan lokal + + + + Use decimal and thousands separators according to the system locale. + Gunakan pemisah desimal dan ribuan sesuai dengan lokal sistem. + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + Ketika mengimpor ke dalam suatu tabel yang telah ada dengan sebuah kunci primer, konstrain unik, atau suatu indeks unik, ada kemungkinan konflik. Opsi ini memungkinkan Anda memilih suatu strategi untuk kasus tersebut. Secara baku impor digugurkan dan di-roll back tapi Anda bisa juga memilih untuk mengabaikan dan tidak mengimpor baris-baris yang konflik atau untuk menggantikan baris yang ada dalam tabel. + + + + Abort import + Tentang impor + + + + Ignore row + Abaikan baris + + + + Replace existing row + Gantikan baris saat ini + + + + Conflict strategy + Strategi konflik + + + + + Deselect All + Hapus Semua Pilihan + + + + Match Similar + Cocok Serupa + + + + Select All + Pilih Semua + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + Sudah ada tabel bernama '%1' dan suatu impor ke tabel yang telah ada hanya mungkin bila cacah kolom cocok. + + + + There is already a table named '%1'. Do you want to import the data into it? + Sudah ada tabel bernama '%1'. Apakah Anda ingin mengimpor data ke dalamnya? + + + + Creating restore point failed: %1 + Gagal membuat titik pemulihan: %1 + + + + Creating the table failed: %1 + Gagal membuat tabel: %1 + + + + importing CSV + mengimpor CSV + + + + Could not prepare INSERT statement: %1 + Tidak bisa mempersiapkan pernyataan INSERT: %1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + Akhir berkas yang tak diduga. Harap pastikan bahwa Anda telah mengonfigurasi karakter kutip yang benar dan berkas tidak salah bentuk. + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + Mengimpor berkas '%1' makan waktu %2 ms. %3 ms dari total itu dihabiskan dalam fungsi baris. + + + + Inserting row failed: %1 + Gagal menyisipkan baris: %1 + + + + MainWindow + + + DB Browser for SQLite + Peramban DB untuk SQLite + + + + toolBar1 + bilahAlat1 + + + + Opens the SQLCipher FAQ in a browser window + Membuka FAQ SQL Cipher dalam sebuah jendela peramban + + + + Export one or more table(s) to a JSON file + Ekspor satu tabel atau lebih ke berkas JSON + + + + &File + &Berkas + + + + &Import + &Impor + + + + &Export + &Ekspor + + + + &Edit + &Sunting + + + + &View + &Tilik + + + + &Help + B&antuan + + + + DB Toolbar + Bilah Alat DB + + + + Edit Database &Cell + &Sunting Sel Basis Data + + + + DB Sche&ma + Ske&ma DB + + + + &Remote + &Remote + + + + + Execute current line + Eksekusi baris kini + + + + This button executes the SQL statement present in the current editor line + Tombol ini mengeksekusi pernyataan SQL yang ada dalam baris penyunting saat ini + + + + Shift+F5 + Shift+F5 + + + + Sa&ve Project + Simpan Pro&yek + + + + Open an existing database file in read only mode + Buka berkas basis data yang ada dalam mode hanya baca + + + + User + Pengguna + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + Ini adalah struktur dari basis data yang dibuka. +Anda dapat menyeret pernyataan SQL dari suatu baris objek dan menjatuhkan mereka ke dalam aplikasi lain atau ke dalam instansi lain dari 'Peramban DB untuk SQLite'. + + + + + Un/comment block of SQL code + Jadikan komentar/bukan komentar blok kode SQL + + + + Un/comment block + Jadikan komentar/bukan komentar blok + + + + Comment or uncomment current line or selected block of code + Jadikan komentar/bukan komentar baris saat ini atau blok kode yang dipilih + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + Jadikan komentar/bukan komentar baris yang dipilih atau baris saat ini, bila tidak ada yang dipilih. Seluruh blok dijungkitkan menurut baris pertama. + + + + Ctrl+/ + Ctrl+/ + + + + Stop SQL execution + Hentikan eksekusi SQL + + + + Stop execution + Hentikan eksekusi + + + + Stop the currently running SQL script + Hentikan skrip SQL yang saat ini sedang berjalan + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + Peringatan: pragma ini tidak dapat dibaca dan nilai ini telah disimpulkan. Menulis pragma mungkin menimpa suatu LIKE yang didefinisikan ulang yang disediakan oleh sebuah ekstensi SQLite. + + + + Too&ls + Pera&latan + + + + Application + Aplikasi + + + + Error Log + Log Kesalahan + + + + This button clears the contents of the SQL logs + Tombol ini membersihkan isi log SQL + + + + &Clear + &Bersihkan + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + Panel ini memungkinkan Anda memeriksa log dari semua perintah SQL yang diberikan oleh aplikasi atau oleh Anda sendiri + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + Ini adalah struktur dari basis data yang dibuka. +Anda dapat menyeret beberapa nama obyek dari kolom Nama dan menjatuhkan mereka ke dalam penyunting SQL dan Anda dapat menyetel properti dari nama-nama yang dijatuhkan memakai menu konteks. Ini akan membantu Anda dalam menyusun pernyataan SQL. +Anda dapat menyeret pernyataan SQL dari kolom Skema dan menjatuhkan mereka ke dalam penyunting SQL atau ke dalam aplikasi lain. + + + + + + Project Toolbar + Bilah Alat Proyek + + + + Extra DB toolbar + Bilah alat DB ekstra + + + + + + Close the current database file + Tutup berkas basis data saat ini + + + + &New Database... + &Basis Data Baru... + + + + + Create a new database file + Buat suatu berkas basis data baru + + + + This option is used to create a new database file. + Opsi ini dipakai untuk membuat sebuah berkas basis data baru. + + + + Ctrl+N + Ctrl+N + + + + + &Open Database... + Buk&a Basis Data... + + + + + + + + Open an existing database file + Buka sebuah berkas basis data yang ada + + + + + + This option is used to open an existing database file. + Opsi ini dipakai untuk membuka sebuah berkas basis data yang ada. + + + + Ctrl+O + Ctrl+O + + + + &Close Database + &Tutup Basis Data + + + + This button closes the connection to the currently open database file + Tombol ini menutup koneksi ke berkas basis data yang saat ini terbuka + + + + + Ctrl+W + Ctrl+W + + + + + Revert database to last saved state + Pulihkan basis data ke keadaan tersimpan terakhir + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + Opsi ini dipakai untuk memulihkan berkas basis data saat ini ke keadaan tersimpan terakhir. Semua perubahan yang dibuat sejak operasi simpan terakhir hilang. + + + + + Write changes to the database file + Tulis perubahan ke berkas basis data + + + + This option is used to save changes to the database file. + Opsi ini dipakai untuk menyimpan perubahan ke berkas basis data. + + + + Ctrl+S + Ctrl+S + + + + Compact &Database... + Mampatkan Basis &Data... + + + + Compact the database file, removing space wasted by deleted records + Memampatkan berkas basis data, menghapus ruang yang terbuang oleh record yang dihapus + + + + + Compact the database file, removing space wasted by deleted records. + Memampatkan berkas basis data, menghapus ruang yang terbuang oleh record yang dihapus. + + + + E&xit + &Keluar + + + + Ctrl+Q + Ctrl+Q + + + + Import data from an .sql dump text file into a new or existing database. + Impor data dari sebuah berkas teks dump sql ke dalam basis data baru atau yang ada. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + Opsi ini memungkinkan Anda mengimpor data dari berkas teks curah .sql ke dalam basis data baru atau yang ada. Berkas curah SQL dapat dibuat pada kebanyakan mesin basis data, termasuk MySQL dan PostgreSQL. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Membuka suatu wahana pandu yang mengizinkan Anda mengimpor data dari berkas teks dengan pemisah koma ke dalam tabel basis data. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Opsi ini membuka suatu wahana pandu yang memungkinkan Anda mengimpor data dari berkas teks dipisah koma ke dalam tabel basis data. Berkas CSV dapat dibuat pada kebanyakan aplikasi basis data dan lembar kerja. + + + + Export a database to a .sql dump text file. + Ekspor suatu basis data ke sebuah berkas teks curah .sql. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + Opsi ini memungkinkan Anda mengekspor sebuah basis data ke suatu berkas teks curah .sql. Berkas curah SQL memuat semua data yang diperlukan untuk mencipta ulang basis data pada kebanyakan mesin basis data, termasuk MySQL dan PostgreSQL. + + + + Export a database table as a comma separated text file. + Ekspor suatu tabel basis data sebagai sebuah berkas teks yang dipisah koma. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + Ekspor suatu tabel basis data sebagai berkas teks yang dipisah koma, siap untuk diimpor ke dalam aplikasi lembar kerja atau basis data lain. + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Membuka wahana pandu Buat Tabel, dimana mungkin untuk mendefinisikan nama dan ruas bagi suatu tabel baru dalam basis data + + + + + Delete Table + Hapus Tabel + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Membuka wahana pandu Hapus Tabel, dimana Anda dapat memilih sebuah tabel basis data yang akan di-drop. + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + Membuka wahana pandu Buat Indeks, dimana mungkin untuk mendefinisikan sebuah indeks baru pada tabel basis data yang ada. + + + + &Preferences... + &Preferensi... + + + + + Open the preferences window. + Buka jendela preferensi. + + + + &DB Toolbar + Bilah Alat &DB + + + + Shows or hides the Database toolbar. + Menampilkan atau menyembunyikan bilah alat Basis Data. + + + + Shift+F1 + Shift+F1 + + + + New &tab + &Tab baru + + + + Open SQL file(s) + Buka berkas SQL + + + + This button opens files containing SQL statements and loads them in new editor tabs + Tombol ini membuka berkas yang memuat pernyataan SQL dan memuat mereka dalam tab penyunting baru + + + + Execute line + Eksekusi baris + + + + &Wiki + &Wiki + + + + F1 + F1 + + + + Bug &Report... + Lapo&ran Bug... + + + + Feature Re&quest... + Per&mintaan Fitur... + + + + Web&site + &Situs Web + + + + &Donate on Patreon... + &Donasi di Patreon... + + + + &Save Project + &Simpan Proyek + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + Tombol ini memungkinkan Anda menyimpan semua pengaturan terkait DB yang terbuka ke suatu berkas proyek Peramban DB untuk SQLite + + + + Open &Project + Buka &Proyek + + + + This button lets you open a DB Browser for SQLite project file + Tombol ini memungkinkan Anda membuka suatu berkas proyek Peramban DB untuk SQLite + + + + Ctrl+Shift+O + Ctrl+Shift+O + + + + &Save Project As... + &Simpan Proyek Sebagai... + + + + + + Save the project in a file selected in a dialog + Simpan proyek dalam suatu berkas yang dipilih dalam sebuah dialog + + + + Save A&ll + Simpan Se&mua + + + + + + Save DB file, project file and opened SQL files + Simpan berkas DB, berkas proyek, dan berkas SQL yang dibuka + + + + Ctrl+Shift+S + Ctrl+Shift+S + + + + Browse Table + Ramban Tabel + + + + Close Pro&ject + Tutup Pro&yek + + + + + Close project and database files and return to the initial state + Tutup berkas basis data dan proyek, dan kembali ke keadaan awal + + + + Ctrl+Shift+F4 + Ctrl+Shift+F4 + + + + + Detach Database + Lepas Cantolan Basis Data + + + + + Detach database file attached to the current database connection + Lepas cantolan berkas basis data yang tercantol ke koneksi basis data saat ini + + + + &Attach Database... + C&antol Basis Data... + + + + Temp Store + Penyimpanan Sementara + + + + Secure Delete + Penghapusan Aman + + + + Case Sensitive Like + Like Peka Huruf Besar Kecil + + + + Journal Mode + Mode Jurnal + + + + Journal Size Limit + Batas Ukuran Jurnal + + + + Recursive Triggers + Trigger Rekursif + + + + Page Size + Ukuran Halaman + + + + Foreign Keys + Foreign Key + + + + Auto Vacuum + Vacuum Otomatis + + + + Max Page Count + Cacah Halaman Maks + + + + Checkpoint Full FSYNC + FSYNC Penuh Checkpoint + + + + + Off + Mati + + + + + Normal + Normal + + + + + Full + Penuh + + + + Default + Baku + + + + File + Berkas + + + + + Memory + Memori + + + + Delete + Hapus + + + + Truncate + Truncate + + + + Persist + Persist + + + + WAL + WAL + + + + Exclusive + Eksklusif + + + + Automatic Index + Indeks Otomatis + + + + Ignore Check Constraints + Abaikan Periksa Konstrain + + + + Full FSYNC + FSYNC Penuh + + + + WAL Auto Checkpoint + Checkpoint Otomatis WAL + + + + User Version + Versi Pengguna + + + + Synchronous + Sinkron + + + + None + Nihil + + + + Incremental + Inkremental + + + + Locking Mode + Mode Penguncian + + + + + Add another database file to the current database connection + Tambahkan berkas basis data lain ke koneksi basis data saat ini + + + + This button lets you add another database file to the current database connection + Tombol ini memungkinkan Anda menambah berkas basis data lain ke koneksi basis data saat ini + + + + &Set Encryption... + Atur Enkrip&si... + + + + SQLCipher &FAQ + &FAQ SQLCipher + + + + Table(&s) to JSON... + Tabel ke J&SON... + + + + Open Data&base Read Only... + &Buka Basis Data Hanya-Baca... + + + + Save results + Simpan hasil + + + + Save the results view + Simpan view hasil + + + + This button lets you save the results of the last executed query + Tombol ini memungkinkan Anda menyimpan hasil dari query yang terakhir dieksekusi + + + + + Find text in SQL editor + Cari teks dalam penyunting SQL + + + + Find + Cari + + + + This button opens the search bar of the editor + Tombol ini membuka bilah pencarian dari penyunting + + + + Ctrl+F + Ctrl+F + + + + + Find or replace text in SQL editor + Cari atau ganti teks dalam penyunting SQL + + + + Find or replace + Cari atau ganti + + + + This button opens the find/replace dialog for the current editor tab + Tombol ini membuka dialog cari/ganti untuk tab penyunting saat ini + + + + Ctrl+H + Ctrl+H + + + + Export to &CSV + Ekspor ke &CSV + + + + Export to &JSON + Ekspor ke &JSON + + + + Save as &view + Simpan sebagai &view + + + + Save as view + Simpan sebagai view + + + + Shows or hides the Project toolbar. + Menampilkan atau menyembunyikan bilah alat Proyek. + + + + Extra DB Toolbar + Bila Alat DB Ekstra + + + + &Open Database + Buk&a Basis Data + + + + New In-&Memory Database + Basis Data Dalam &Memori Baru + + + + Drag && Drop SELECT Query + Seret && Jatuhkan Query SELECT + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + Ketika menyeret ruas dari tabel yang sama atau suatu tabel tunggal, menjatuhkan suatu query SELECT ke dalam penyunting + + + + Drag && Drop Qualified Names + Seret && Jatuhkan Qualified Name + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + Pakai qualified name (mis. "Table"."Field") ketika menyeret objek dan menjatuhkan mereka ke dalam penyunting + + + + Drag && Drop Enquoted Names + Seret && Jatuhkan Nama Berkutip + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + Pakai identifier berkutip (mis. "Table1") ketika menyeret objek dan menjatuhkan mereka ke dalam penyunting + + + + &Integrity Check + Pemeriksaan &Integritas + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + Menjalankan pragma integrity_check atas basis data yang terbuka dan mengembalikan hasil dalam tab Jalankan SQL. Pragma ini melakukan pemeriksaan integritas dari seluruh basis data. + + + + &Foreign-Key Check + Pemeriksaan &Foreign-Key + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + Menjalankan pragma foreign_key_check atas basis data yang terbuka dan mengembalikan hasil dalam tab Jalankan SQL + + + + &Quick Integrity Check + Pemeri&ksaan Cepat Integritas + + + + Run a quick integrity check over the open DB + Menjalankan pemeriksaan cepat atas integritas pada DB yang terbuka + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + Menjalankan pragma quick_check atas basis data yang terbuka dan mengembalikan hasil dalam tab Jalankan SQL. Perintah ini melakukan hampir seluruh pemeriksaan dari PRAGMA integrity_check tapi berjalan jauh lebih cepat. + + + + &Optimize + &Optimasikan + + + + Attempt to optimize the database + Mencoba mengoptimasi basis data + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + Menjalankan pragma optimasi atas basis data yang dibuka. Pragma ini mungkin melakukan optimasi yang akan memperbaiki kinerja dari query di masa mendatang. + + + + + Print + Cetak + + + + Print text from current SQL editor tab + Cetak teks dari tab penyunting SQL saat ini + + + + Open a dialog for printing the text in the current SQL editor tab + Membuka suatu dialog untuk mencetak teks dalam tab penyunting SQL saat ini + + + + Print the structure of the opened database + Cetak struktur dari basis data yang dibuka + + + + Open a dialog for printing the structure of the opened database + Membuka suatu dialog untuk mencetak struktur dari basis data yang dibuka + + + + + Ctrl+Shift+W + Ctrl+Shift+W + + + + Table from CSV data in Clipboard... + Tabel dari data CSV dalam Papan Klip... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + Ini memperlakukan konten papan klip saat ini sebagai suatu berkas CSV dan membuka wahana pandu impor yang sama dengan yang dipakai untuk mengimpor data CSV dari suatu berkas. + + + + Show &Row Counts + Tampilkan Cacah Ba&ris + + + + This shows the number of rows for each table and view in the database. + Ini menampilkan cacah baris bagi setiap tabel dan view dalam basis data. + + + + Save Database &As... + Simpan Basis Data Seb&agai... + + + + Save the current database as a different file + Menyimpan basis data saat ini sebagai suatu berkas yang berbeda + + + + Refresh + Segarkan + + + + Reload the database structure + Memuat ulang struktur basis data + + + + &Recently opened + Ba&ru-baru ini dibuka + + + + Ctrl+T + Ctrl+T + + + + SQL &Log + &Log SQL + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + Struktur Basis &Data + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + Ram&ban Data + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + Sunting P&ragma + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + Jalan&kan SQL + + + + &Recent Files + Be&rkas Baru-baru Ini + + + + Show S&QL submitted by + Tampilkan S&QL yang dikirim oleh + + + + &Plot + &Plot + + + + &New Database + &Basis Data Baru + + + + + Ctrl+F4 + Ctrl+F4 + + + + &Revert Changes + Balikkan Pe&rubahan + + + + &Undo + Tak Ja&di + + + + + Undo last change to the database + Batalkan perubahan terakhir ke basis data + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + Aksi ini membatalkan perubahan terakhir yang dilakukan ke basis data dalam Peramban Basis Data atau dalam Jalankan SQL. Menjalankan ulang tidak mungkin. + + + + &Write Changes + &Tulis Perubahan + + + + &Database from SQL file... + Basis &data dari berkas SQL... + + + + &Table from CSV file... + &Tabel dari berkas CSV... + + + + &Database to SQL file... + Basis &data ke berkas SQL... + + + + &Table(s) as CSV file... + &Tabel sebagai berkas CSV... + + + + &Create Table... + &Buat Tabel... + + + + &Delete Table... + &Hapus Tabel... + + + + &Modify Table... + &Ubah Tabel... + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + Membuka wahana pandu Ubah Tabel, dimana dimungkinkan mengubah nama suatu tabel yang ada. Juga mungkin untuk menambah atau menghapus ruas dari suatu tabel, maupun mengubah nama dan tipe ruas. + + + + Create &Index... + Buat &Indeks... + + + + W&hat's This? + Apa &Ini? + + + + &About + Perih&al + + + + This button opens a new tab for the SQL editor + Tombol ini membuka suatu tab baru bagi penyunting SQL + + + + &Execute SQL + &Eksekusi SQL + + + + Execute all/selected SQL + Eksekusi semua/SQL yang dipilih + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + Tombol ini mengeksekusi pernyataan SQL yang saat ini dipilih. Bila tidak ada teks yang dipilih, semua pernyataan dieksekusi. + + + + Ctrl+Shift+T + Ctrl+Shift+T + + + + + + Save SQL file + Simpan berkas SQL + + + + &Load Extension... + &Muat Ekstensi... + + + + Ctrl+E + Ctrl+E + + + + Export as CSV file + Ekspor sebagai berkas CSV + + + + Export table as comma separated values file + Ekspor tabel sebagai berkas nilai yang dipisah koma + + + + + Save the current session to a file + Simpan sesi saat ini ke suatu berkas + + + + Open &Project... + Buka &Proyek... + + + + + Load a working session from a file + Muat suatu sesi kerja dari sebuah berkas + + + + + Save SQL file as + Simpan berkas SQL sebagai + + + + This button saves the content of the current SQL editor tab to a file + Tombol ini menyimpan isi dari tab penyunting SQL saat ini ke sebuah berkas + + + + &Browse Table + Ram&ban Tabel + + + + Copy Create statement + Salin pernyataan Create + + + + Copy the CREATE statement of the item to the clipboard + Salin pernyataan CREATE dari butir ke papan klip + + + + Ctrl+Return + Ctrl+Return + + + + Ctrl+L + Ctrl+L + + + + + Ctrl+P + Ctrl+P + + + + Ctrl+D + Ctrl+D + + + + Ctrl+I + Ctrl+I + + + + Encrypted + Terenkripsi + + + + Read only + Hanya baca + + + + Database file is read only. Editing the database is disabled. + Berkas basis data hanya baca. Menyunting basis data dinonaktifkan. + + + + Database encoding + Pengkodean basis data + + + + Database is encrypted using SQLCipher + Basis data terenkripsi memakai SQLCipher + + + + + Choose a database file + Pilh suatu berkas basis data + + + + + + Choose a filename to save under + Pilih suatu nama berkas untuk tempat menyimpan + + + + Error checking foreign keys after table modification. The changes will be reverted. + Kesalahan saat memeriksa foreign key setelah modifikasi tabel. Perubahan akan dibalikkan. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + Tabel ini tidak lolos pemeriksaan foreign key.<br/>Anda mesti menjalankan 'Alat | Pemeriksaan Foreign Key' dan memperbaiki masalah-masalah yang dilaporkan. + + + + + At line %1: + Pada baris %1: + + + + Result: %2 + Hasil: %2 + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + Menata nilai PRAGMA atau mem-vacuum akan meng-commit transaksi Anda saat ini. +Anda yakin? + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + Kesalahan saat menyimpan berkas basis data. Ini berarti bahwa tidak semua perubahan ke basis data disimpan. Anda perlu terlebih dahulu menyelesaikan kesalahan berikut. + +%1 + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + Anda yakin ingin membatalkan semua perubahan yang dibuat ke berkas basis data '%1' sejak penyimpanan terakhir? + + + + Choose a file to import + Pilih suatu berkas yang akan diimpor + + + + Text files(*.sql *.txt);;All files(*) + Berkas teks(*.sql *.txt);;Semua berkas(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + Apakah Anda ingin membuat suatu berkas basis data baru untuk menampung data yang diimpor? +Bila Anda menjawab tidak kami akan mencoba mengimpor data dalam berkas SQL ke basis data saat ini. + + + + Automatically load the last opened DB file at startup + Secara otomatis muat berkas DB yang terakhir dibuka saat awal mula + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + Anda masih mengeksekusi pernyataan SQL. Menutup basis data sekarang akan menghentikan eksekusi mereka, kemungkinkan meninggalkan basis data dalam keadaan tidak konsisten. Anda yakin hendak menutup basis data? + + + + Do you want to save the changes made to the project file '%1'? + Apakah Anda ingin menyimpan perubahan yang dibuat ke berkas proyek '%1'? + + + + File %1 already exists. Please choose a different name. + Berkas %1 sudah ada. Harap pilih nama lain. + + + + Error importing data: %1 + Kesalahan saat mengimpor data: %1 + + + + Import completed. + Impor selesai. + + + + Delete View + Hapus View + + + + Modify View + Ubah View + + + + Delete Trigger + Hapus Trigger + + + + Modify Trigger + Ubah Trigger + + + + Delete Index + Hapus Indeks + + + + Modify Index + Ubah Indeks + + + + Modify Table + Ubah Tabel + + + + Do you want to save the changes made to SQL tabs in a new project file? + Apakah Anda ingin menyimpan perubahan yang dibuat ke tab SQL dalam suatu berkas proyek baru? + + + + Do you want to save the changes made to the SQL file %1? + Apakah Anda ingin menyimpan perubahan yang dibuat ke berkas SQL %1? + + + + Could not find resource file: %1 + Tidak bisa menemukan berkas sumber daya: %1 + + + + Choose a project file to open + Pilih sebuah berkas proyek untuk dibuka + + + + Could not open project file for writing. +Reason: %1 + Tidak bisa membuka berkas proyek untuk ditulisi. +Alasan: %1 + + + + Busy (%1) + Sibuk (%1) + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + Menata nilai PRAGMA akan meng-commit transaksi Anda saat ini. +Anda yakin? + + + + Reset Window Layout + Reset Tata Letak Jendela + + + + The database is currently busy. + Basis data saat ini sibuk. + + + + Click here to interrupt the currently running query. + Klik di sini untuk mengiterupsi query yang sedang berjalan. + + + + Alt+Shift+W + Alt+Shift+W + + + + Could not open database file. +Reason: %1 + Tidak bisa membuka berkas basis data. +Alasan: %1 + + + + In-Memory database + Basis data dalam memori + + + + Choose a database file to save under + Pilih suatu berkas basis data tempat menyimpan + + + + Error while saving the database to the new file. + Kesalahan saat menyimpan basis data ke berkas baru. + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + Anda yakin ingin menghapus tabel '%1'? +Semua data terkait dengan tabel akan hilang. + + + + Are you sure you want to delete the view '%1'? + Anda yakin ingin menghapus view '%1'? + + + + Are you sure you want to delete the trigger '%1'? + Anda yakin ingin menghapus trigger '%1'? + + + + Are you sure you want to delete the index '%1'? + Anda yakin ingin menghapus indeks '%1'? + + + + Error: could not delete the table. + Kesalahan: tidak bisa menghapus tabel. + + + + Error: could not delete the view. + Kesalahan: tidak bisa menghapus view. + + + + Error: could not delete the trigger. + Kesalahan: tidak bisa menghapus trigger. + + + + Error: could not delete the index. + Kesalahan: tidak bisa menghapus indeks. + + + + Message from database engine: +%1 + Pesan dari mesin basis data: +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + Menyunting tabel memerlukan menyimpan semua perubahan tertunda sekarang. +Anda yakin ingin menyimpan basis data? + + + + Edit View %1 + Sunting View %1 + + + + Edit Trigger %1 + Sunting Trigger %1 + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + Anda telah sedang mengeksekusi pernyataan SQL. Apakah Anda ingin menghentikan mereka untuk mengeksekusi pernyataan saat ini sebagai pengganti? Perhatikan bahwa ini mungkin meninggalkan basis data dalam keadaan yang tidak konsisten. + + + + -- EXECUTING SELECTION IN '%1' +-- + -- MENGEKSEKUSI PILIHAN DALAM '%1' +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- MENGEKSEKUSI BARIS DALAM '%1' +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- MENGEKSEKUSI SEMUA DALAM '%1' +-- + + + + Result: %1 + Hasil: %1 + + + + %1 rows returned in %2ms + %1 baris dikembalikan dalam %2 ms + + + + Choose text files + Pilih berkas teks + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + Impor selesai. Beberapa konstrain foreign key dilanggar. Harap perbaiki mereka sebelum menyimpan. + + + + Opened '%1' in read-only mode from recent file list + Membuka '%1' dalam mode hanya baca dari daftar berkas terkini + + + + Opened '%1' from recent file list + Membuka '%1' dari daftar berkas terkini + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (hanya baca) + + + + Open Database or Project + Buka Basis Data atau Proyek + + + + Attach Database... + Cantol Basis Data... + + + + Import CSV file(s)... + Impor berkas CSV... + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + Apakah Anda ingin menyimpan perubahan yang dibuat ke tab SQL dalam berkas proyek '%1'? + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + Pernyataan dalam tab '%1' masih sedang dieksekusi. Menutup tab akan menghentikan eksekusi. Ini mungkin membuat basis data dalam keadaan tidak konsisten. Anda yakin ingin menutup tab? + + + + Select SQL file to open + Pilih berkas SQL yang akan dibuka + + + + DB file '%1' could not be opened + Berkas DB '%1' tidak dapat dibuka + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + Berkas proyek ini memakai format berkas lama karena itu dibuat memakai Peramban DB untuk SQLite versi 3.10 atau sebelumnya. Memuat format berkas ini tidak lagi didukung sepenuhnya. Bila Anda ingin memuatnya secara lengkap, harap gunakan Peramban DB untuk SQLite versi 3.12 untuk mengubahnya ke format berkas baru. + + + + Table '%1' not found; settings ignored + Tabel '%1' tidak ditemukan, pengaturan diabaikan + + + + -- Reference to file "%1" (not supported by this version) -- + -- Referensi ke berkas "%1" (tidak didukung oleh versi ini) -- + + + + Yes. Don't ask again + Ya. Jangan tanyakan lagi + + + + This action will open a new SQL tab with the following statements for you to edit and run: + Aksi ini akan membuka sebuah tab SQL baru dengan pernyataan berikut untuk Anda sunting dan jalankan: + + + + Rename Tab + Ubah Nama Tab + + + + Duplicate Tab + Duplikatkan Tab + + + + Close Tab + Tutup Tab + + + + Opening '%1'... + Membuka '%1'... + + + + There was an error opening '%1'... + Ada kesalahan saat membuka '%1'... + + + + Value is not a valid URL or filename: %1 + Nilai bukanlah URL atau nama berkas yang valid: %1 + + + + Select file name + Pilih nama berkas + + + + Ctrl+Tab + Ctrl+Tab + + + + Ctrl+Shift+Tab + Ctrl+Shift+Tab + + + + Clear List + Bersihkan Daftar + + + + Window Layout + Tata Letak Jendela + + + + Ctrl+0 + Ctrl+0 + + + + Simplify Window Layout + Sederhanakan Tata Letak Jendela + + + + Alt+Shift+0 + Alt+Shift+0 + + + + Dock Windows at Bottom + Tambatkan Jendela ke Bawah + + + + Dock Windows at Left Side + Tambatkan Jendela ke Sisi Kiri + + + + Dock Windows at Top + Tambatkan Jendela ke Atas + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + Pilih aksi yang akan diterapkan ke berkas yang dijatuhkan. <br/>Catatan: hanya 'Impor' yang akan memroses lebih dari %n berkas. + + + + + Select extension file + Pilih berkas ekstensi + + + + Extension successfully loaded. + Ekstensi sukses dimuat. + + + + Error loading extension: %1 + Kesalahan saat memuat ekstensi: %1 + + + + + Don't show again + Jangan tampilkan lagi + + + + New version available. + Tersedia versi baru. + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + Tersedia sebuah versi baru Peramban DB bagi SQLite (%1.%2.%3).<br/><br/>Harap unduh di <a href='%4'>%4</a>. + + + + Project saved to file '%1' + Proyek disimpan ke berkas '%1' + + + + Collation needed! Proceed? + Perlu kolasi! Lanjutkan? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + Sebuah tabel dalam basis data ini memerlukan suatu fungsi kolasi khusus '%1' yang aplikasi ini tak bisa sediakan tanpa pengetahuan lebih jauh. +Bila Anda memilih melanjutkan, sadari bahwa hal-hal buruk dapat terjadi ke basis data Anda. +Buat suatu cadangan! + + + + creating collation + membuat kolasi + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + Menata sebuah nama baru bagi tab SQL. Gunakan karakter '&&' untuk mengizinkan memakai karakter berikut sebagai suatu pintasan papan ketik. + + + + Please specify the view name + Harap tentukan nama view + + + + There is already an object with that name. Please choose a different name. + Sudah ada objek dengan nama itu. Harap pilih nama lain. + + + + View successfully created. + View sukses dibuat. + + + + Error creating view: %1 + Kesalahan saat membuat view: %1 + + + + This action will open a new SQL tab for running: + Aksi ini akan membuka sebuah tab SQL baru untuk menjalankan: + + + + Press Help for opening the corresponding SQLite reference page. + Tekan Bantuan untuk membuka halaman referensi SQLite yang terkait. + + + + DB Browser for SQLite project file (*.sqbpro) + Berkas proyek Peramban DB bagi SQLite (*.sqbpro) + + + + Execution finished with errors. + Eksekusi selesai dengan kesalahan. + + + + Execution finished without errors. + Eksekusi selesai tanpa kesalahan. + + + + NullLineEdit + + + Set to NULL + Tata ke NULL + + + + Alt+Del + Alt+Del + + + + PlotDock + + + Plot + Plot + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>Panel ini menunjukkan daftar kolom dari tabel yang saat ini diramban atau query yang baru saja dieksekusi. Anda dapat memilih kolom yang ingin Anda pakai sebagai sumbu X atau Y bagi panel plot di bawah. Tabel menunjukkan tipe sumbu yang terdeteksi yang akan memengaruhi plot yang dihasilkan. Untuk sumbu Y Anda hanya dapat memilih kolom-kolom numerik, tapi untuk sumbu X Anda akan dapat memilih:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Tanggal/Waktu</span>: string dengan format &quot;yyyy-MM-dd hh:mm:ss&quot; atau &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Tanggal</span>: string dengan format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Waktu</span>: string dengan format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: format string lain. Memilih kolom ini sebagai sumbu X akan menghasilkan plot Batang dengan nilai-nilai kolom sebagai label batang.</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numerik</span>: nilai bilangan bulat atau riil</li></ul><p>Mengklik ganda sel Y Anda dapat mengubah warna yang dipakai untuk grafik itu.</p></body></html> + + + + Columns + Kolom + + + + X + X + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + Tipe Sumbu + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + Di sini suatu plot digambar ketika Anda memilih nilai-nilai x dan y di atas. + +Klik pada titik-titik untuk memilih mereka dalam plot dan dalam tabel. Ctrl+Klik untuk memilih suatu rentang titik. + +Gunakan roda tetikus untuk mengubah pembesaran dan penyeretan tetikus untuk mengubah rentang sumbu. + +Pilih sumbu atau label sumbu untuk menyeret dan memperbesar hanya dalam orientasi itu. + + + + Line type: + Tipe garis: + + + + + None + Nihil + + + + Line + Garis + + + + StepLeft + LangkahKiri + + + + StepRight + LangkahKanan + + + + StepCenter + LangkahPusat + + + + Impulse + Impuls + + + + Point shape: + Bentuk titik: + + + + Cross + Silang + + + + Plus + Plus + + + + Circle + Lingkaran + + + + Disc + Cakram + + + + Square + Bujur Sangkar + + + + Diamond + Permata + + + + Star + Bintang + + + + Triangle + Segi Tiga + + + + TriangleInverted + SegiTigaTerbalik + + + + CrossSquare + SilangKotak + + + + PlusSquare + PlusKotak + + + + CrossCircle + SilangLingkar + + + + PlusCircle + PlusLingkar + + + + Peace + Damai + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>Simpan plot saat ini...</p><p>Format berkas dipilih oleh ekstensi (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + Simpan plot saat ini... + + + + + Load all data and redraw plot + Muat semua data dan gambar ulang plot + + + + + + Row # + Baris # + + + + Copy + Salin + + + + Print... + Cetak... + + + + Help + Bantuan + + + + Show legend + Tampilkan legenda + + + + Stacked bars + Batang bertumpuk + + + + Fixed number format + Format bilangan tetap + + + + Date/Time + Tanggal/Waktu + + + + Date + Tanggal + + + + Time + Waktu + + + + + Numeric + Numerik + + + + Label + Label + + + + Invalid + Tidak valid + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + Muat semua data dan gambar ulang plot. +Peringatan: belum semua data diambil dari tabel karena mekanisme pengambilan parsial. + + + + Choose an axis color + Pilih suatu warna sumbu + + + + Choose a filename to save under + Pilih suatu nama berkas untuk tempat menyimpan + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Semua Berkas(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + Ada kurva dalam plot ini dan gaya garis yang dipilih hanya bisa diterapkan ke grafik yang diurut berdasarkan X. Urutkan tabel atau query berdasarkan X untuk menghapus kurva atau pilih satu dari gaya yang didukung oleh kurva: Nihil atau Garis. + + + + Loading all remaining data for this table took %1ms. + Memuat semua sisa data dari tabel ini makan waktu %1 ms. + + + + PreferencesDialog + + + Preferences + Preferensi + + + + &General + &Umum + + + + Remember last location + Ingat lokasi terakhir + + + + Always use this location + Selalu pakai lokasi ini + + + + Remember last location for session only + Ingat lokasi terakhir hanya untuk sesi + + + + + + ... + ... + + + + Default &location + &Lokasi baku + + + + Lan&guage + &Bahasa + + + + Automatic &updates + Pembar&uan otomatis + + + + + + + + + + + + + + enabled + difungsikan + + + + Show remote options + Tampilkan opsi remote + + + + &Database + Basis &data + + + + Database &encoding + P&engodean basis data + + + + Open databases with foreign keys enabled. + Membuka basis data dengan foreign key difungsikan. + + + + &Foreign keys + &Foreign key + + + + SQ&L to execute after opening database + SQ&L yang akan dieksekusi setelah membuka basis data + + + + Data &Browser + Peram&ban Data + + + + Remove line breaks in schema &view + Buang putus baris dalam &tampilan skema + + + + Prefetch block si&ze + &Ukuran blok prefetch + + + + Default field type + Tipe ruas baku + + + + Font + Fonta + + + + &Font + &Fonta + + + + Content + Isi + + + + Symbol limit in cell + Batas simbol dalam sel + + + + NULL + NULL + + + + Regular + Biasa + + + + Binary + Biner + + + + Background + Latar belakang + + + + Filters + Filter + + + + Threshold for completion and calculation on selection + Ambang batas bagi penyelesaian dan kalkulasi saat dipilih + + + + Escape character + Karakter escape + + + + Delay time (&ms) + Waktu tunda (&ms) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + Mengatur waktu tunggu sebelum suatu nilai filter baru diterapkan. Dapat diatur ke 0 untuk menonaktifkan menunggu. + + + + &SQL + &SQL + + + + Context + Konteks + + + + Colour + Warna + + + + Bold + Tebal + + + + Italic + Miring + + + + Underline + Garis bawah + + + + Keyword + Kata kunci + + + + Function + Fungsi + + + + Table + Tabel + + + + Comment + Komentar + + + + Identifier + Identifier + + + + String + String + + + + Current line + Baris saat ini + + + + SQL &editor font size + Ukuran fonta p&enyunting SQL + + + + Tab size + Ukuran tab + + + + SQL editor &font + &Fonta penyunting SQL + + + + Error indicators + Indikator kesalahan + + + + Hori&zontal tiling + Pengubinan hori&zontal + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + Bila difungsikan penyunting kode SQL dan view tabel hasilnya ditampilkan bersisian sebagai ganti satu di atas yang lain. + + + + Code co&mpletion + Pele&ngkapan kode + + + + Toolbar style + Gaya bilah alat + + + + + + + + Only display the icon + Hanya tampilkan ikon + + + + + + + + Only display the text + Hanya tampilkan teks + + + + + + + + The text appears beside the icon + Teks muncul di sebelah ikon + + + + + + + + The text appears under the icon + Teks muncul di bawah ikon + + + + + + + + Follow the style + Ikuti gaya + + + + DB file extensions + Ekstensi berkas DB + + + + Manage + Kelola + + + + Main Window + Jendela Utama + + + + Database Structure + Struktur Basis Data + + + + Browse Data + Ramban Data + + + + Execute SQL + Jalankan SQL + + + + Edit Database Cell + Sunting Sel Basis Data + + + + When this value is changed, all the other color preferences are also set to matching colors. + Saat nilai ini diubah, semua preferensi warna lain juga diatur ke warna yang cocok. + + + + Follow the desktop style + Ikuti gaya desktop + + + + Dark style + Gaya gelap + + + + Application style + Gaya aplikasi + + + + This sets the font size for all UI elements which do not have their own font size option. + Ini menata ukuran fonta bagi semua elemen UI yang tidak punya opsi ukuran fonta sendiri. + + + + Font size + Ukuran fonta + + + + Max Recent Files + Maks Berkas Baru-baru Ini + + + + Prompt to save SQL tabs +in new project file + Tanyakan untuk menyimpan tab SQL +dalam berkas proyek baru + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + Bila ini dinyalakan, maka perubahan ke penyunting SQL membangkitkan sebuah dialog konfirmasi simpan proyek ketika menutup tab penyunting SQL. + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + Ketika difungsikan, putus baris dalam kolom Skema dari tab Struktur DB, dok, dan keluaran tercetak dihapus. + + + + Database structure font size + Ukuran fonta struktur basis data + + + + Font si&ze + &Ukuran fonta + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + Ini adalah cacah maksimum butir yang diizinkan bagi beberapa fungsionalitas yang mahal secara komputasi untuk difungsikan: +Banyaknya baris maksimum dalam suatu tabel untuk memfungsikan pelengkapan nilai berdasarkan nilai saat ini dalam kolom. +Banyaknya indeks maksimum dalam suatu seleksi untuk menghitung jumlah dan rerata. +Dapat diatur ke 0 untuk menonaktifkan fungsionalitas. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + Ini adalah cacah baris maksimum dalam suatu tabel untuk memfungsikan pelengkapan nilai berbasis nilai saat ini dalam kolom. +Dapat diatur ke 0 untuk menonaktifkan pelengkapan. + + + + Show images in cell + Tampilkan gambar dalam sel + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + Fungsikan opsi ini untuk menampilkan suatu pratinjau dari BLOB yang memuat data citra dalam sel. Namun ini dapat mempengaruhi kinerja peramban data. + + + + Field display + Tampilan ruas + + + + Light style + Gaya terang + + + + Displayed &text + &Teks yang ditampilkan + + + + Formatted + Diformat + + + + + + + + + + + Click to set this color + Klik untuk menata warna ini + + + + Text color + Warna teks + + + + Background color + Warna latar belakang + + + + + Preview only (N/A) + Hanya pratinjau (T/T) + + + + Foreground + Latar depan + + + + Selection background + Latar belakang pilihan + + + + Selection foreground + Latar depan pilihan + + + + Highlight + Penyorotan + + + + SQL &results font size + Ukuran fonta &hasil SQL + + + + Use tabs for indentation + Gunakan tab untuk indentasi + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + Ketika ditata, tombol Tab akan menyisipkan karakter tab dan spasi untuk indentasi. Bila tidak, hanya spasi yang akan dipakai. + + + + &Wrap lines + &Lipat baris + + + + Never + Tak Pernah + + + + At word boundaries + Di perbatasan kata + + + + At character boundaries + Di perbatasan karakter + + + + At whitespace boundaries + Di perbatasan ruang putih + + + + &Quotes for identifiers + &Kutip untuk identifier + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + Pilih mekanisme pengutipan yang dipakai oleh aplikasi bagi identifier dalam kode SQL. + + + + "Double quotes" - Standard SQL (recommended) + "Kutip ganda" - SQL Standar (disarankan) + + + + `Grave accents` - Traditional MySQL quotes + `Aksen grave` - Kutip tradisional MySQL + + + + [Square brackets] - Traditional MS SQL Server quotes + [Kurung siku] - Kutip tradisional MS SQL Server + + + + Keywords in &UPPER CASE + Kata kunci dalam H&URUF BESAR + + + + When set, the SQL keywords are completed in UPPER CASE letters. + Saat ditata, kata kunci SQL dilengkapkan dalam HURUF BESAR. + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + Ketika ditata, baris kode SQL yang menyebabkan kesalahan saat eksekusi terakhir disorot dan bingkai hasil mengindikasikan kesalahan dalam latar belakang + + + + Close button on tabs + Tutup tombol pada tab + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + Bila difungsikan, tab penyunting SQL akan memiliki tombol tutup. Apapun keadaannya, Anda dapat memakai menu kontekstual atau pintasan papan ketik untuk menutup mereka. + + + + &Extensions + &Ekstensi + + + + Select extensions to load for every database: + Pilih ekstensi yang akan dimuat untuk setiap basis data: + + + + Add extension + Tambah ekstensi + + + + Remove extension + Hapus ekstensi + + + + Select built-in extensions to load for every database: + Pilih ekstensi bawaan yang akan dimuat untuk setiap basis data: + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>Walaupun mendukung operator REGEXP SQLite tidak mengimplementasikan algoritma<br/>ekspresi reguler apa pun tapi memanggil balik aplikasi yang berjalan. Peramban DB bagi SQLite<br/>mengimplementasi algoritma ini bagi Anda agar memungkinkan Anda langsung memakai REGEXP.<br/>Namun, karena ada beberapa implementasi yang mungkin<br/> dan Anda mungkin ingin memakai yang lain,<br/>Anda bebas untuk menonaktifkan implementasi aplikasi dan memuat milik Anda sendiri memakai ekstensi.<br/>Memerlukan memulai ulang aplikasi.</p></body></html> + + + + Disable Regular Expression extension + Nonaktifkan ekstensi Ekspresi Reguler + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite menyediakan sebuah fungsi SQL untul memuat ekstensi dari suatu berkas pustaka bersama. Aktifkan ini bila Anda ingin memakai fungsi <span style=" font-style:italic;">load_extension()</span> dari kode SQL.</p><p>Untuk alasan keamanan, pemuatan ekstensi dimatikan secara baku dan harus difungsikan melalui pengaturan ini. Anda selalu dapat memuat ekstensi melalui GUI, walaupun opsi ini dinonaktifkan.</p></body></html> + + + + Allow loading extensions from SQL code + Izinkan memuat ekstensi dari kode SQL + + + + Remote + Remote + + + + CA certificates + Sertifikat CA + + + + Proxy + Proksi + + + + Configure + Konfigurasikan + + + + Export Settings + Ekspor Pengaturan + + + + Import Settings + Impor Pengaturan + + + + + Subject CN + CN Subjek + + + + Common Name + Common Name + + + + Subject O + O Subjek + + + + Organization + Organisasi + + + + + Valid from + Valid sejak + + + + + Valid to + Valid sampai + + + + + Serial number + Nomor seri + + + + Your certificates + Sertifikat Anda + + + + File + Berkas + + + + Subject Common Name + Common Name Subjek + + + + Issuer CN + CN Penerbit + + + + Issuer Common Name + Common Name Penerbit + + + + Clone databases into + Klon basis data ke + + + + + Choose a directory + Pilih suatu direktori + + + + + The language will change after you restart the application. + Bahasa akan berubah setelah Anda menjalankan ulang aplikasi. + + + + Select extension file + Pilih berkas ekstensi + + + + Extensions(*.so *.dylib *.dll);;All files(*) + Ekstensi(*.so *.dylib *.dll);;Semua berkas(*) + + + + Import certificate file + Impor berkas sertifikat + + + + No certificates found in this file. + Tidak ditemukan sertifikat dalam berkas ini. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + Anda yakin hendak menghapus sertifikat ini? Semua data sertifikat akan dihapus dari pengaturan aplikasi! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + Anda yakin hendak membersihkan semua pengaturan yang disimpan? +Semua preferensi Anda akan hilang dan nilai-nilai baku akan dipakai. + + + + Save Settings File + Simpan Berkas Pengaturan + + + + + Initialization File (*.ini) + Berkas Inisialisasi (*.ini) + + + + The settings file has been saved in location : + + Berkas pengaturan telah disimpan di lokasi : + + + + + Open Settings File + Buka Berkas Pengaturan + + + + The settings file was loaded properly. + Berkas pengaturan dimuat secara benar. + + + + The selected settings file is not a normal settings file. +Please check again. + Berkas pengaturan yang dipilih bukanlah berkas pengaturan yang normal. +Harap periksa lagi. + + + + ProxyDialog + + + Proxy Configuration + Konfigurasi Proksi + + + + Pro&xy Type + Tipe Pro&ksi + + + + Host Na&me + Na&ma Host + + + + Port + Port + + + + Authentication Re&quired + &Perlu Autentikasi + + + + &User Name + Nama Pengg&una + + + + Password + Kata Sandi + + + + None + Nihil + + + + System settings + Pengaturan sistem + + + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 + + + + QObject + + + Error importing data + Kesalahan saat mengimpor data + + + + from record number %1 + dari record nomor %1 + + + + . +%1 + . +%1 + + + + Importing CSV file... + Mengimpor berkas CSV... + + + + Cancel + Batal + + + + All files (*) + Semua berkas (*) + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + Berkas basis data SQLite (*.db *.sqlite *.sqlite3 *.db3) + + + + Left + Kiri + + + + Right + Kanan + + + + Center + Tengah + + + + Justify + Rata Kiri Kanan + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + Berkas Basis Data SQLite (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + Berkas proyek Peramban DB bagi SQLite (*.sqbpro) + + + + SQL Files (*.sql) + Berkas SQL (*.sql) + + + + All Files (*) + Semua Berkas (*) + + + + Text Files (*.txt) + Berkas Teks (*.txt) + + + + Comma-Separated Values Files (*.csv) + Berkas Nilai yang Dipisah Koma (*.csv) + + + + Tab-Separated Values Files (*.tsv) + Berkas Nilai yang Dipisah Tab (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + Berkas Nilai yang Dipisah Pembatas (*.dsv) + + + + Concordance DAT files (*.dat) + Berkas DAT Concordance (*.dat) + + + + JSON Files (*.json *.js) + Berkas JSON (*.json *.js) + + + + XML Files (*.xml) + Berkas XML (*.xml) + + + + Binary Files (*.bin *.dat) + Berkas Biner (*.bin *.dat) + + + + SVG Files (*.svg) + Berkas SVG (*.svg) + + + + Hex Dump Files (*.dat *.bin) + Berkas Hex Dump (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + Ekstensi (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + Berkas Inisialisasi (*.ini) + + + + QsciCommand + + Paste + Tempel + + + Cancel + Batal + + + + QsciLexerCPP + + Default + Baku + + + Keyword + Kata kunci + + + Identifier + Identifier + + + + QsciLexerJSON + + Default + Baku + + + String + String + + + + QsciLexerJavaScript + + Regular expression + Ekspresi reguler + + + + QsciLexerPython + + Default + Baku + + + Comment + Komentar + + + Keyword + Kata kunci + + + Identifier + Identifier + + + + QsciLexerSQL + + Default + Baku + + + Comment + Komentar + + + Keyword + Kata kunci + + + Identifier + Identifier + + + + QsciScintilla + + &Undo + Tak Ja&di + + + Select All + Pilih Semua + + + + RemoteCommitsModel + + + Commit ID + ID Commit + + + + Message + Pesan + + + + Date + Tanggal + + + + Author + Penulis + + + + Size + Ukuran + + + + Authored and committed by %1 + Dibuat dan di-commit oleh %1 + + + + Authored by %1, committed by %2 + Dibuat oleh %1, di-commit oleh %2 + + + + RemoteDatabase + + + Error opening local databases list. +%1 + Kesalahan saat membuka daftar basis data lokal. +%1 + + + + Error creating local databases list. +%1 + Kesalahan saat membuat daftar basis data lokal. +%1 + + + + RemoteDock + + + Remote + Remote + + + + Identity + Identitas + + + + Push currently opened database to server + Push basis data yang saat ini dibuka ke server + + + + Upload + Unggah + + + + DBHub.io + DBHub.io + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>Dalam panel ini, basis data remote dari situs web dbhub.io dapat ditambahkan ke Peramban DB untuk SQLite. Pertama Anda perlu suatu identitas:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Log masuk ke situs web dbhub.io (gunakan kredensial GitHub Anda atau apa pun yang Anda inginkan)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Klik tombol untuk &quot;Membuat sertifikat klien&quot; (itu adalah identitas Anda). Itu Akan memberi Anda suatu berkas sertifikat (simpan itu ke disk lokal Anda).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Pergi ke tab Remote dalam Preferensi Peramban DB untuk SQLite. Klik tombol untuk menambahkan sertifikat baru ke Peramban DB untuk SQLite dan pilih berkas sertifikat yang baru saja diunduh.</li></ol><p>Kini panel Remote menampilkan identitas Anda dan Anda dapat menambah basis data remote.</p></body></html> + + + + Local + Lokal + + + + Current Database + Basis Data Saat Ini + + + + Clone + Klon + + + + &User + Pengg&una + + + + &Database + Basis &data + + + + Branch + Branch + + + + Commits + Commit + + + + Commits for + Commit untuk + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>Anda kini sedang memakai identitas bawaan, hanya-baca. Untuk mengunggah basis data Anda, Anda perlu mengonfigurasi dan memakai akun DBHub.io milik Anda.</p><p>Belum punya akun DBHub.io? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Buat baru sekarang</span></a> dan impor sertifikat Anda <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">di sini</span></a> untuk berbagi basis data Anda.</p><p>Untuk bantuan daring kunjungi <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">ini</span></a>.</p></body></html> + + + + Back + Mundur + + + + Delete Database + Hapus Basis Data + + + + Delete the local clone of this database + Menghapus klon lokal dari basis data ini + + + + Open in Web Browser + Buka dalam Peramban Web + + + + Open the web page for the current database in your browser + Membuka halaman web bagi basis data saat ini dalam peramban Anda + + + + Clone from Link + Klon dari Tautan + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + Gunakan ini untuk mengunduh suatu basis data remote untuk penyuntingan lokal memakai suatu URL yang diberikan pada halaman web dari basis data. + + + + Refresh + Segarkan + + + + Reload all data and update the views + Muat ulang semua data dan perbarui view + + + + Clone Database + Klon Basis Data + + + + Open Database + Buka Basis Data + + + + Open the local copy of this database + Membuka salinan lokal dari basis data ini + + + + Check out Commit + Check out Commit + + + + Download and open this specific commit + Unduh dan buka commit spesifik ini + + + + Check out Latest Commit + Check out Commit Terakhir + + + + Check out the latest commit of the current branch + Check out commit terakhir dari branch saat ini + + + + Save Revision to File + Simpan Revisi ke Berkas + + + + Saves the selected revision of the database to another file + Menyimpan revisi basis data yang dipilih ke berkas lain + + + + Upload Database + Unggah Basis Data + + + + Upload this database as a new commit + Unggah basis data ini sebagi suatu commit baru + + + + Select an identity to connect + Pilih sebuah identitas untuk menyambung + + + + Public + Publik + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + Ini mengunduh sebuah basis data dari suatu server remote untuk +penyuntingan lokal. Harap masukkan URL sumber klon. Anda +dapat membangkitkan URL ini dengan mengklik tombol +'Klon Basis Data dalam DB4S' pada halaman web dari basis data. + + + + Invalid URL: The host name does not match the host name of the current identity. + URL tidak valid: Nama host tidak cocok dengan nama host dari identitas saat ini. + + + + Invalid URL: No branch name specified. + URL tidak valid: Tidak ada nama branch yang dinyatakan. + + + + Invalid URL: No commit ID specified. + URL tidak valid: Tidak ada ID commit yang dinyatakan. + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + Anda telah mengubah klon lokal dari basis data. Mengambil commit ini menimpa perubahan lokal ini. +Anda yakin ingin melanjutkan? + + + + The database has unsaved changes. Are you sure you want to push it before saving? + Basis data memiliki perubahan yang belum disimpan. Anda yakin ingin mem-push itu sebelum menyimpan? + + + + The database you are trying to delete is currently opened. Please close it before deleting. + Basis data yang Anda coba hapus saat ini sedang dibuka. Harap tutup itu sebelum menghapus. + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + Ini menghapus versi lokal dari basis data ini dengan semua perubahan yang belum Anda commit. Anda yakin ingin menghapus basis data ini? + + + + RemoteLocalFilesModel + + + Name + Nama + + + + Branch + Branch + + + + Last modified + Terakhir diubah + + + + Size + Ukuran + + + + Commit + Commit + + + + File + Berkas + + + + RemoteModel + + + Name + Nama + + + + Commit + Commit + + + + Last modified + Terakhir diubah + + + + Size + Ukuran + + + + Size: + Ukuran: + + + + Last Modified: + Terakhir Diubah: + + + + Licence: + Lisensi: + + + + Default Branch: + Branch Baku: + + + + RemoteNetwork + + + Choose a location to save the file + Pilih suatu lokasi untuk menyimpan berkas + + + + Error opening remote file at %1. +%2 + Kesalahan saat membuka berkas remote pada %1. +%2 + + + + Error: Invalid client certificate specified. + Kesalahan: Sertifikat klien yang ditentukan tidak valid. + + + + Please enter the passphrase for this client certificate in order to authenticate. + Harap masukkan frasa sandi bagi sertifikat klien ini untuk mengautentikasi. + + + + Cancel + Batal + + + + Uploading remote database to +%1 + Mengunggah basis data remote ke +%1 + + + + Downloading remote database from +%1 + Mengunduh basis data remote dari +%1 + + + + Error: Cannot open the file for sending. + Kesalahan: Tidak bisa membuka berkas untuk pengiriman. + + + + RemotePushDialog + + + Push database + Push basis data + + + + Database na&me to push to + Na&ma basis data tujuan push + + + + Commit message + Pesan commit + + + + Database licence + Lisensi basis data + + + + Public + Publik + + + + Branch + Branch + + + + Force push + Paksa push + + + + Username + Nama pengguna + + + + Database will be public. Everyone has read access to it. + Basis data akan menjadi publik. Semua orang punya akses baca ke sana. + + + + Database will be private. Only you have access to it. + Basis data akan menjadi privat. Hanya Anda yang punya akses ke sana. + + + + Use with care. This can cause remote commits to be deleted. + Gunakan dengan hati-hati. Ini bisa menyebabkan commit remote terhapus. + + + + RunSql + + + Execution aborted by user + Eksekusi digugurkan oleh pengguna + + + + , %1 rows affected + , %1 baris tedampak + + + + query executed successfully. Took %1ms%2 + query sukses dieksekusi. Makan waktu %1ms%2 + + + + executing query + mengeksekusi query + + + + SelectItemsPopup + + + A&vailable + &Tersedia + + + + Sele&cted + &Dipilih + + + + SqlExecutionArea + + + Form + Bentuk + + + + Find previous match [Shift+F3] + Cari kecocokan sebelumnya [Shift+F3] + + + + Find previous match with wrapping + Cari kecocokan sebelumnya dan teruskan dari akhir setelah mencapai awal + + + + Shift+F3 + Shift+F3 + + + + The found pattern must be a whole word + Pola yang ditemukan mesti berupa kata utuh + + + + Whole Words + Kata Lengkap + + + + Text pattern to find considering the checks in this frame + Pola teks yang akan dicari dengan mempertimbangkan pemeriksaan dalam bingkai ini + + + + Find in editor + Cari dalam penyunting + + + + The found pattern must match in letter case + Pola yang ditemukan mesti cocok besar kecil hurufnya + + + + Case Sensitive + Peka Huruf Besar Kecil + + + + Find next match [Enter, F3] + Cari kecocokan selanjutnya [Enter, F3] + + + + Find next match with wrapping + Cari kecocokan selanjutnya dan putar balik + + + + F3 + F3 + + + + Interpret search pattern as a regular expression + Interpretasikan pola pencarian sebagai ekspresi reguler + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Bila dicentang, pola yang akan dicari diinterpretasikan sebagi suatu ekspresi reguler UNIX. Lihat <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Ekspresi Reguler dalam Wikibook</a>.</p></body></html> + + + + Regular Expression + Ekspresi Reguler + + + + + Close Find Bar + Tutup Bilah Pencarian + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>Hasil dari pernyataan yang terakhir dieksekusi.</p><p>Anda mungkin ingin melipat panel ini dan memakai dok <span style=" font-style:italic;">Log SQL</span> dengan pilihan <span style=" font-style:italic;">Pengguna</span> sebagai pengganti.</p></body></html> + + + + Results of the last executed statements + Hasil dari pernyataan yang terakhir dieksekusi + + + + This field shows the results and status codes of the last executed statements. + Ruas ini menunjukkan hasil dan kode status dari pernyataan yang terakhir dieksekusi. + + + + Ctrl+PgUp + Ctrl+PgUp + + + + Ctrl+PgDown + Ctrl+PgDown + + + + Couldn't read file "%1": %2. + Tak bisa membaca berkas "%1": %2. + + + + + Couldn't save file: %1. + Tak bisa menyimpan berkas: %1. + + + + Your changes will be lost when reloading it! + Perubahan Anda akan hilang ketika dimuat ulang! + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + Berkas "%1" diubah oleh program lain. Apakah Anda hendak memuat ulang itu?%2 + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + Jawab "Ya ke Semua" untuk memuat ulang berkas saat pembaruan eksternal apa pun tanpa bertanya lebih jauh. + + + + Answer "No to All" to ignore any external update without further prompting. + Jawab "Tidak ke Semua" untuk mengabaikan pembaruan eksternal apa pun tanpa bertanya lebih jauh. + + + + Modifying and saving the file will restore prompting. + Mengubah dan menyimpan berkas akan memulihkan bertanya. + + + + SqlTextEdit + + + Ctrl+/ + Ctrl+/ + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) Fungsi abs(X) mengembalikan nilai absolut dari argumen numerik X. + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () Fungsi changes() mengembalikan banyaknya baris basis data yang diubah atau disisipkan atau dihapus oleh pernyataan INSERT, DELETE, atau UPDATE yang terakhir selesai. + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) Fungsi char(X1,X2,...,XN) mengembalikan suatu string yang tersusun dari karakter yang memiliki nilai-nilai titik kode unicode dari bilangan bulat X1 sampai XN. + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) Fungsi coalesce() mengembalikan suatu salinan dari argumen bukan NULL pertamanya, atau NULL bila semua argumen adalah NULL + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) Fungsi glob(X,Y) ekuivalen dengan ekspresi "Y GLOB X". + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) Fungsi ifnull() mengembalikan suatu salinan dari argumen bukan NULL pertama, atau NULL bila kedua argumen adalah NULL. + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) Fungsi instr(X,Y) mencari kemunculan pertama dari string Y di dalam string X dan mengembalikan banyaknya karakter sebelumnya tambah 1, atau 0 bila Y tidak ditemukan dalam X. + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) Fungsi hex() menginterpretasi argumennya sebagai sebuah BLOB dan mengembalikan suatu string yang merupakan perenderan heksadesimal huruf besar dari konten blob tersebut. + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) Fungsi iif(X,Y,Z) mengembalikan nilai Y bila X benar, dan Z bila tidak. + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () Fungsi last_insert_rowid() mengembalikan ROWID dari baris terakhir sisip dari koneksi basis data yang memanggil fungsi. + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) Untuk suatu nilai string X, fungsi length(X) mengembalikan banyaknya karakter (bukan byte) dalam X sebelum karakter NUL pertama. + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) Fungsi like() dipakai untuk mengimplementasikan ekspresi "Y LIKE X". + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) Fungsi like() dipakai untuk mengimplementasikan ekspresi "Y LIKE X ESCAPE Z". + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) Fungsi load_extension(X) memuat ekstensi SQLite dari berkas pustaka bersama bernama X. +Penggunaan fungsi ini mesti diotorisasi dari Preferensi. + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) Fungsi load_extension(X) memuat ekstensi SQLite dari berkas pustaka bersama bernama X memakai titik masuk Y. +Penggunaan fungsi ini mesti diotorisasi dari Preferensi. + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) Fungsi lower(X) mengembalikan suatu salinan dari string X dengan semua karakter ASCII dikonversi ke huruf kecil. + + + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) menghapus spasi dari sisi kiri X. + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) Fungsi ltrim(X,Y) mengembalikan suatu string yang dibentuk dengan menghapus sebarang dan semua karakter yang muncul dalam Y di sisi kiri X. + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) Fungsi multi-argumen max() mengembalikan argumen dengan nilai maksimum, atau mengembalikan NULL bila sebarang argumen adalah NULL. + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) Fungsi multi-argumen min() mengembalikan argumen dengan nilai minimum. + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) Fungsi nullif(X,Y) mengembalikan argumen pertamanya bila argumen-argumen berbeda dan NULL bila argumen-argumen adalah sama. + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) Fungsi SQL printf(FORMAT,...) bekerja seperti fungsi bahasa C sqlite3_mprintf() dan fungsi printf() dari pustaka standar C. + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) Fungsi quote(X) mengembalikan teks dari suatu literal SQL yang merupakan nilai dari argumennya, cocok untuk disertakan ke dalam suatu pernyataan SQL. + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () Fungsi random() mengembalikan suatu bilang bulat pseudo-random antara -9223372036854775808 dan +9223372036854775807. + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) Fungsi randomblob(N) mengembalikan suatu blob N byte yang memuat byte pseudo random. + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) Fungsi replace(X,Y,Z) mengembalikan sebuah string yang dibentuk dengan memasang pengganti string Z bagi setiap kemunculan string Y dalam string X. + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) Fungsi round(X) mengembalikan suatu nilai floating point X yang dibulatkan ke nol digit di sisi kanan titik desimal. + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) Fungsi round(X,Y) mengembalikan suatu nilai floating point X yang dibulatkan ke Y digit di sisi kanan titik desimal. + + + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X) menghapus spasi dari sisi kanan X. + + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) Fungsi rtrim(X,Y) mengembalikan suatu string yang dibentuk dengan menghapus sebarang dan semua karakter yang muncul dalam Y di sisi kanan X. + + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) Fungsi soundex(X) mengembalikan suatu string yang berupa enkoding soundex dari string X. + + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) substr(X,Y) mengembalikan semua karakter sampai di akhir string X dimulai dari yang ke Y. + + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) Fungsi substr(X,Y,Z) mengembalikan sebuah sub string dari string masukan X yang dimulai dengan karakter ke-Y sepanjang Z karakter. + + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () Fungsi total_changes() mengembalikan banyaknya baris yang berubah karena pernyataan INSERT, UPDATE, atau DELETE sejak koneksi basis data saat ini dibuka. + + + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) menghapus spasi di kedua ujung X. + + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) Fungsi trim(X,Y) mengembalikan suatu string yang dibentuk dengan menghapus sebarang dan semua karakter yang muncul dalam Y di kedua ujung X. + + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) Fungsi typeof(X) mengembalikan sebuah string yang mengindikasikan tipe data dari ekspresi X. + + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) Fungsi unicode(X) mengembalikan titik kode unicode numerik yang bersesuaian dengan karakter pertama dari string X. + + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) Fungsi upper(X) mengembalikan suatu salinan dari string masukan X dimana semua karakter ASCII huruf kecil dikonversi ke ekuivalen huruf besar mereka. + + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) Fungsi zeroblob(N) mengembalikan suatu BLOB yang terdiri dari N byte 0x00. + + + + + + + (timestring,modifier,modifier,...) + (timestring,modifier,modifier,...) + + + + (format,timestring,modifier,modifier,...) + (format,timestring,modifier,modifier,...) + + + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) Fungsi avg() mengembalikan nilai rerata dari semua X bukan NULL dalam suatu grup. + + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) Fungsi count(X) mengembalikan suatu cacah dari banyaknya X adalah bukan NULL dalam sebuah grup. + + + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) Fungsi group_concat() mengembalikan suatu string yang merupakan konkatenasi dari semua nilai bukan NULL dari X. + + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) Fungsi group_concat() mengembalikan suatu string yang merupakan konkatenasi dari semua nilai bukan NULL dari X. Bila parameter Y ada maka itu dipakai sebagai pemisah antara instansi-instansi X. + + + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) Fungsi agregasi max() mengembalikan nilai maksimum dari semua nilai dalam grup. + + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) Fungsi agregasi min() mengembalikan nilai bukan NULL minimum dari semua nilai dalam grup. + + + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) Fungsi agregat sum() dan total() mengembalikan jumlah dari semua nilai bukan NULL dalam grup. + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () Banyaknya baris di dalam partisi saat ini. Baris dinomori mulai dari 1 dalam urutan yang ditentukan oleh klausul ORDER BY dalam definisi jendela, atau dalam urutan sebarang bila tidak. + + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () row_number() dari peer pertama dalam setiap grup - ranking dari baris saat ini dengan celah. Bila tidak ada klausul ORDER BY, maka semua baris dianggap peer dan fungsi ini selalu mengembalikan 1. + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () Banyaknya grup peer dari baris saat ini di dalam partisinya - ranking dari baris saat ini tanpa celah. Partisi dinomori mulai dari 1 dalam urutan yang ditentukan oleh klausul ORDER BY dalam definisi jendela. Bila tidak ada klausul ORDER BY, maka semua baris dianggap peer dan fungsi ini selalu mengembalikan 1. + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () Walaupaun namanya begitu, fungsi ini selalu mengembalikan suatu nilai antara 0,0 dan 1,0 sama dengan (ranking - 1)/(baris partisi - 1), dimana ranking adalah nilai yang dikembalikan oleh fungsi jendela bawaan rank() dan baris-partisi adalah cacah total baris dalam partisi. Bila partisi hanya memuat satu baris, fungsi ini mengembalikan 0,0. + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () Distribusi kumulatif. Dihitung sebagai nomor-baris/baris-partisi, dimana nomor-baris adalah nilai yang dikembalikan oleh row_number() bagi peer terakhir dalam grup dan baris-partisi adalah banyaknya baris dalam partisi. + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) Argumen N ditangani sebagai sebuah bilangan bulat. Fungsi ini membagi partisi ke dalam N grup serata mungkin dan menugaskan suatu bilangan bulat antara 1 dan N ke setiap grup, dalam urutan yang ditentukan oleh klausul ORDER BY, atau dalam urutan sebarang bila tidak. Kalau perlu, grup-grup yang lebih besar muncul pertama. Fungsi ini mengembalikan nilai bilangan bulat yang ditugaskan ke ke grup dimana baris saat ini adalah bagian darinya. + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) Mengembalikan hasil mengevaluasi ekspresi expr terhadap baris sebelumnya dalam partisi. Atau bila tidak ada baris sebelumnya (karena baris saat ini adalah yg pertama), NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr,offset) Bila argumen offset diberikan, maka itu mesti berupa bilangan bulat tidak negatif. Dalam kasus ini nilai yang dikembalikan adalah hasil dari mengevaluasi expr terhadap baris-baris ofset baris sebelum baris saat ini dalam partisi. Bila offset adalah 0, maka expr dievaluasi terhadap baris saat ini. Bila tidak ada baris-baris ofset baris sebelum baris saat ini, dikembalikan NULL. + + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,offset,default) Bila default juga diberikan, maka itu dikembalikan sebagai pengganti dari NULL bila baris yang diidentifikasi oleh offset tidak ada. + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) Mengembalikan hasil dari mengevaluasi ekspresi expr terhadap baris selanjutnya dalam partisi. Atau bila tidak ada baris selanjutnya (karena baris saat ini adalah terakhir), NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,offset) Bila argumen offset diberikan, maka itu mesti berupa bilangan bulat tidak negatif. Dalam kasus ini nilai yang dikembalikan adalah hasil dari mengevaluasi expr terhadap baris-baris ofset baris setelah baris saat ini dalam partisi. Bila offset adalah 0, maka expr dievaluasi terhadap baris saat ini. Bila tidak ada baris-baris ofset baris setelah baris saat ini, dikembalikan NULL. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) Fungsi jendela bawaan ini menghitung kerangka jendela bagi setiap baris dengan cara yang sama dengan fungsi jendela agregasi. Itu mengembalikan nilai expr yang dievaluasi terhadap baris pertama dalam kerangka jendela bagi setiap baris. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) Fungsi jendela bawaan ini menghitung kerangka jendela bagi setiap baris dengan cara yang sama dengan fungsi jendela agregasi. Itu mengembalikan nilai expr yang dievaluasi terhadap baris terakhir dalam kerangka jendela bagi setiap baris. + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr,N) Fungsi jendela bawaan ini menghitung kerangka jendela bagi setiap baris dengan cara yang sama dengan fungsi jendela agregasi. Itu mengembalikan nilai expr yang dievaluasi terhadap baris N dari kerangka jendela. Baris-baris dinomori dalam kerangka jendela dimulai dari 1 dalam urutan yang ditentukan oleh klausul ORDER BY bila ada, atau dalam urutan sebarang bila tidak. Bila tidak adan baris ke N dalam partisi, maka NULL dikembalikan. + + + + (X) Return the arccosine of X. The result is in radians. + (X) Mengembalikan arckosinus dari X. Hasil dalam radian. + + + + (X) Return the hyperbolic arccosine of X. + (X) Mengembalikan arckosinus hiperbolik dari X. + + + + (X) Return the arcsine of X. The result is in radians. + (X) Mengembalikan arcsinus dari X. Hasil dalam radian. + + + + (X) Return the hyperbolic arcsine of X. + (X) Mengembalikan arcsinus hiperbolik dari X. + + + + (X) Return the arctangent of X. The result is in radians. + (X) Mengembalikan arctangen dari X. Hasil dalam radian. + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + (X, Y) Mengembalikan arctangen dari Y/X. Hasil dalam radian. Hasil ditempatkan ke dalam kuadran yang benar bergantung pada tanda dari X dan Y. + + + + (X) Return the hyperbolic arctangent of X. + (X) Mengembalikan arctangen hiperbolik dari X. + + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + (X) Mengembalikan nilai bilangan bulat pertama yang dapat direpresentasikan yang lebih dari atau sama dengan X. Untuk nilai X positif, rutin ini membulatkan menjauh dari nol. Untuk nilai negatif X, rutin ini membulatkan menuju nol. + + + + (X) Return the cosine of X. X is in radians. + (X) Mengembalikan kosinus dari X. X dalam radian. + + + + (X) Return the hyperbolic cosine of X. + (X) Mengembalikan kosinus hiperbolik dari X. + + + + (X) Convert value X from radians into degrees. + (X) Mengonversi nilai X dari radian ke derajat. + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + (X) Menghitung e (bilangan Euler, kurang lebih 2.71828182845905) pangkat X. + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + (X) Mengembalikan nilai bilangan bulat pertama yang dapat direpresentasikan yang kurang dari atau sama dengan X. Untuk nilai X positif, rutin ini membulatkan menuju nol. Untuk nilai negatif X, rutin ini membulatkan menjauhi nol. + + + + (X) Return the natural logarithm of X. + (X) Mengembalikan logaritma alami dari X. + + + + (B,X) Return the base-B logarithm of X. + (B, X) Mengembalikan logaritma basis-B dari X. + + + + + (X) Return the base-10 logarithm for X. + (X) Mengembalikan logaritma basis-10 untuk X. + + + + (X) Return the logarithm base-2 for the number X. + (X) Mengembalikan logaritma basis-2 untuk bilangan X. + + + + (X,Y) Return the remainder after dividing X by Y. + (X, Y) Mengembalikan sisa setelah X dibagi Y. + + + + () Return an approximation for Ï€. + () Mengembalikan suatu aproksimasi untuk Ï€. + + + + + (X,Y) Compute X raised to the power Y. + (X,Y) Menghitung X pangkat Y. + + + + (X) Convert X from degrees into radians. + (X) Mengonversi X dari derajat ke radian. + + + + (X) Return the sine of X. X is in radians. + (X) Mengembalikan sinus X. X dalam radian. + + + + (X) Return the hyperbolic sine of X. + (X) Mengembalikan sinus hiperbolik dari X. + + + + (X) Return the square root of X. NULL is returned if X is negative. + (X) Mengembalikan akar kuadrat dari X. NULL dikembalikan bila X negatif. + + + + (X) Return the tangent of X. X is in radians. + (X) Mengembalikan tangen dari X. X dalam radian. + + + + (X) Return the hyperbolic tangent of X. + (X) Mengembalikan tangen hiperbolik dari X. + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + (X) Mengembalikan bilangan bulat yang dapat direpresentasikan antara X dan 0 (inklusif) yang paling jauh dari nol. Atau, dengan perkataan lain, mengembalikan bagian bilangan bulat dari X, membulatkan menuju nol. + + + + SqliteTableModel + + + reading rows + membaca baris + + + + loading... + memuat... + + + + References %1(%2) +Hold %3Shift and click to jump there + Mengacu %1(%2) +Tahan Shift%3 dan klik untuk melompat ke sana + + + + Error changing data: +%1 + Kesalahan saat mengubah data: +%1 + + + + retrieving list of columns + mengambil daftar kolom + + + + Fetching data... + Mengambil data... + + + + + Cancel + Batal + + + + TableBrowser + + + Browse Data + Ramban Data + + + + &Table: + &Tabel: + + + + Select a table to browse data + Pilih suatu tabel untuk diramban datanya + + + + Use this list to select a table to be displayed in the database view + Gunakan daftar ini untuk memilih suatu tabel yang akan ditampilkan dalam view basis data + + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + Ini adalah view tabel basis data. Anda dapat melakukan aksi berikut: + - Mulai menulis untuk menyunting nilai secara inline. + - Klik ganda sebarang record untuk menyunting isinya dalam jendela penyunting sel. + - Alt+Del untuk menghapus isi sel menjadi NULL. + - Ctrl+" untuk menduplikasi record saat ini. + - Ctrl+' untuk menyalin nilai dari sel di atas. + - Operasi salin/tempel dan pemilihan standar. + + + + Text pattern to find considering the checks in this frame + Pola teks yang akan dicari dengan mempertimbangkan pemeriksaan dalam bingkai ini + + + + Find in table + Cari dalam tabel + + + + Find previous match [Shift+F3] + Cari kecocokan sebelumnya [Shift+F3] + + + + Find previous match with wrapping + Cari kecocokan sebelumnya dan teruskan dari akhir setelah mencapai awal + + + + Shift+F3 + Shift+F3 + + + + Find next match [Enter, F3] + Cari kecocokan selanjutnya [Enter, F3] + + + + Find next match with wrapping + Cari kecocokan selanjutnya dan teruskan dari awal setelah mencapai akhir + + + + F3 + F3 + + + + The found pattern must match in letter case + Pola yang ditemukan mesti cocok besar kecil hurufnya + + + + Case Sensitive + Peka Huruf Besar Kecil + + + + The found pattern must be a whole word + Pola yang ditemukan mesti berupa kata utuh + + + + Whole Cell + Seluruh Sel + + + + Interpret search pattern as a regular expression + Interpretasikan pola pencarian sebagai suatu ekspresi reguler + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Saat dicentang, pola yang akan dicari diinterpretasikan sebagai suatu ekspresi reguler UNIX. Lihat <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Ekspresi Reguler dalam Wikibook</a>.</p></body></html> + + + + Regular Expression + Ekspresi Reguler + + + + + Close Find Bar + Tutup Bilah Pencarian + + + + Text to replace with + Teks pengganti + + + + Replace with + Ganti dengan + + + + Replace next match + Gantikan kecocokan selanjutnya + + + + + Replace + Ganti + + + + Replace all matches + Ganti semua yang cocok + + + + Replace all + Ganti semua + + + + Export to &JSON + Ekspor ke &JSON + + + + + Export the filtered data to JSON + Mengekspor data yang difilter ke JSON + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + Tombol ini mengekspor data dari tabel yang diramban sebagaimana saat ini ditampilkan (setelah filter, format tampilan, dan kolom pengurutan) sebagai suatu berkas JSON. + + + + Copy column name + Salin nama kolom + + + + Copy the database table column name to your clipboard + Menyalin nama kolom tabel basis data ke papan klip Anda + + + + New Data Browser + Peramban Data Baru + + + + + Add a new docked Data Browser + Menambahkan sebuah Peramban Data tertambat yang baru + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + Tombol ini menambahkan suatu Peramban Data tertambat yang baru, yang dapat Anda copot dan atur dalam tata letak yang berbeda-beda. + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>Menggulir ke awal</p></body></html> + + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>Mengklik tombol ini menavigasi ke awal dalam view tabel di atas.</p></body></html> + + + + |< + |< + + + + Scroll one page upwards + Gulir satu halaman naik + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>Mengklik tombol ini menavigasi naik satu halaman record dalam view tabel di atas.</p></body></html> + + + + < + < + + + + 0 - 0 of 0 + 0 - 0 dari 0 + + + + Scroll one page downwards + Gulir satu halaman turun + + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>Mengklik tombol ini menavigasi turun satu halaman record dalam view tabel di atas.</p></body></html> + + + + > + > + + + + Scroll to the end + Gulir ke akhir + + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>Mengklik tombol ini menavigasi ke akhir dalam view tabel di atas.</p></body></html> + + + + >| + >| + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>Klik di sini untuk melompat ke record tertentu</p></body></html> + + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>Tombol ini dipakai untuk menavigasi ke nomor record yang dinyatakan dalam area Ke.</p></body></html> + + + + Go to: + Ke: + + + + Enter record number to browse + Masukkan nomor record yang akan diramban + + + + Type a record number in this area and click the Go to: button to display the record in the database view + Ketikkan suatu nomor record dalam area ini klik tombol Ke: untuk menampilkan record dalam view basis data + + + + 1 + 1 + + + + Show rowid column + Tampilkan kolom rowid + + + + Toggle the visibility of the rowid column + Jungkitkan kenampakan kolom rowid + + + + Unlock view editing + Buka kunci penyuntingan view + + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + Ini membuka view saat ini untuk disunting. Namun Anda akan perlu trigger yang sesuai untuk penyuntingan. + + + + Edit display format + Sunting format tampilan + + + + Edit the display format of the data in this column + Sunting format tampilan data dalam kolom ini + + + + + New Record + Record Baru + + + + + Insert a new record in the current table + Sisipkan suatu record baru dalam tabel saat ini + + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>Tombol ini membuat sebuah record baru dalam basis data. Tahan tombol tetikus untuk membuka sebuah menu pop-up dengan opsi-opsi berbeda:</p><ul><li><span style=" font-weight:600;">Record Baru</span>: menyisipkan sebuah record baru dengan nilai-nilai baku dalam basis data.</li><li><span style=" font-weight:600;">Sisipkan Nilai...</span>: membuka suatu dialog untuk memasukkan nilai-nilai sebelum mereka disisipkan dalam basis data. Ini memungkinkan memasukkan nilai-nilai yang memenuhi konstrain lain. Dialog ini juga dibuka bila opsi <span style=" font-weight:600;">Record Baru</span> gagal karena konstrain ini.</li></ul></body></html> + + + + + Delete Record + Hapus Record + + + + Delete the current record + Hapus record saat ini + + + + + This button deletes the record or records currently selected in the table + Tombol ini menghapus record atau record yang saat ini dipilih dalam tabel + + + + + Insert new record using default values in browsed table + Sisipkan record baru memakai nilai-nilai baku dalam tabel yang diramban + + + + Insert Values... + Sisipkan Nilai... + + + + + Open a dialog for inserting values in a new record + Membuka suatu dialog untuk menyisipkan nilai-nilai dalam sebuah record baru + + + + Export to &CSV + Ekspor ke &CSV + + + + + Export the filtered data to CSV + Ekspor data yang difilter ke CSV + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + Tombol ini mengekspor data dari tabel yang diramban yang saat ini ditampilkan (setelah filter, format tampilan, dan kolom urutan) sebagai suatu berkas CSV. + + + + Save as &view + Simpan sebagai &view + + + + + Save the current filter, sort column and display formats as a view + Simpan filter saat ini, kolom pengurutan, dan format tampilan sebagai suatu view + + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + Tombol ini menyimpan pengaturan saat ini dari tabel yang diramban (filter, format tampilan, dan kolom pengurutan) sebagai suatu view SQL yang nanti Anda dapat ramban atau pakai dalam pernyataan SQL. + + + + Save Table As... + Simpan Tabel Sebagai... + + + + + Save the table as currently displayed + Menyimpan tabel sebagai yang saat ini ditampilkan + + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>Menu pop-up ini menyediakan opsi-opsi berikut yang diterapkan ke tabel yang saat ini diramban dan disaring:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ekspor ke CSV: opsi ini mengekspor data dari tabel yang diramban sebagaimana saat ini ditampilkan (setelah penyaring, format tampilan, dan urutan kolom) ke sebuah berkas CSV.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Simpan sebagai view: opsi ini menyimpan pengaturan saat ini dari tabel yang diramban (penyaring, format tampilan, dan urutan kolom) sebagai sebuah view SQL yang nanti akan dapat Anda ramban atau pakai dalam pernyataan SQL.</li></ul></body></html> + + + + Hide column(s) + Sembunyikan kolom + + + + Hide selected column(s) + Sembunyikan kolom yang dipilih + + + + Show all columns + Tampilkan semua kolom + + + + Show all columns that were hidden + Tampilkan semua kolom yang disembunyikan + + + + + Set encoding + Atur pengkodean + + + + Change the encoding of the text in the table cells + Ubah pengkodean teks dalam sel tabel + + + + Set encoding for all tables + Atur pengkodean untuk semua tabel + + + + Change the default encoding assumed for all tables in the database + Ubah pengkodean baku yang diasumsikan bagi semua tabel dalam basis data + + + + Clear Filters + Bersihkan Filter + + + + Clear all filters + Bersihkan semua filter + + + + + This button clears all the filters set in the header input fields for the currently browsed table. + Tombol ini membersihkan semua filter yang diatur dalam ruas masukan header bagi tabel yang saat ini diramban. + + + + Clear Sorting + Bersihkan Pengurutan + + + + Reset the order of rows to the default + Reset urutan baris ke baku + + + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + Tombol ini membersihkan kolom pengurutan yang dinyatakan bagi tabel yang saat ini diramban dan mengembalikan ke urutan baku. + + + + Print + Cetak + + + + Print currently browsed table data + Cetak data tabel yang saat ini diramban + + + + Print currently browsed table data. Print selection if more than one cell is selected. + Mencetak data tabel yang saat ini diramban. Mencetak pilihan bila lebih dari satu sel yang dipilih. + + + + Ctrl+P + Ctrl+P + + + + Refresh + Segarkan + + + + Refresh the data in the selected table + Segarkan data dalam tabel yang dipilih + + + + This button refreshes the data in the currently selected table. + Tombol ini menyegarkan data dalam tabel yang saat ini dipilih. + + + + F5 + F5 + + + + Find in cells + Cari dalam sel + + + + Open the find tool bar which allows you to search for values in the table view below. + Membuka bilah alat pencarian yang memungkinkan Anda mencari nilai dalam view tabel di bawah. + + + + + Bold + Tebal + + + + Ctrl+B + Ctrl+B + + + + + Italic + Miring + + + + + Underline + Garis bawah + + + + Ctrl+U + Ctrl+U + + + + + Align Right + Rata Kanan + + + + + Align Left + Rata Kiri + + + + + Center Horizontally + Tengahkan Arah Horizontal + + + + + Justify + Rata Kiri Kanan + + + + + Edit Conditional Formats... + Sunting Format Bersyarat... + + + + Edit conditional formats for the current column + Sunting format bersyarat bagi kolom saat ini + + + + Clear Format + Bersihkan Format + + + + Clear All Formats + Bersihkan Semua Format + + + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + Membersihkan semua pemformatan sel dari sel yang dipilih dan semua format bersyarat dari kolom-kolom yang dipilih + + + + + Font Color + Warna Fonta + + + + + Background Color + Warna Latar + + + + Toggle Format Toolbar + Jungkitkan Bilah Alat Format + + + + Show/hide format toolbar + Tampilkan/sembunyikan bilah alat format + + + + + This button shows or hides the formatting toolbar of the Data Browser + Tombol ini menampilkan atau menyembunyikan bilah alat pemformatan dari Peramban Data + + + + Select column + Pilih kolom + + + + Ctrl+Space + Ctrl+Space + + + + Replace text in cells + Gantikan teks dalam sel + + + + Freeze columns + Bekukan kolom + + + + Make all columns from the first column up to this column not move when scrolling horizontally + Buat semua kolom dari kolom pertama sampai dengan kolom ini tidak bergerak ketika menggulir ke arah horizontal + + + + Filter in any column + Filter dalam sebarang kolom + + + + Ctrl+R + Ctrl+R + + + + %n row(s) + + %n baris + + + + + , %n column(s) + + , %n kolom + + + + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . Jumlah: %1; Rerata: %2; Min: %3; Maks: %4 + + + + Conditional formats for "%1" + Format bersyarat bagi "%1" + + + + determining row count... + menentukan cacah baris... + + + + %L1 - %L2 of >= %L3 + %L1 - %L2 dari >= %L3 + + + + %L1 - %L2 of %L3 + %L1 - %L2 dari %L3 + + + + (clipped at %L1 rows) + (dipangkas pada %L1 baris) + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + Harap masukkan suatu kunci primer pseudo agar memungkinkan penyuntingan pada view ini. Ini mesti berupa nama dari sebuah kolom unik dalam view. + + + + Delete Records + Hapus Record + + + + Duplicate records + Duplikatkan record + + + + Duplicate record + Duplikatkan record + + + + Ctrl+" + Ctrl+" + + + + Adjust rows to contents + Setel baris ke isi + + + + Error deleting record: +%1 + Kesalahan saat menghapus record: +%1 + + + + Please select a record first + Harap pilih suatu record terlebih dahulu + + + + Please choose a new encoding for all tables. + Harap pilih suatu enkoding baru bagi semua tabel. + + + + Please choose a new encoding for this table. + Harap pilih suatu enkoding baru bagi tabel ini. + + + + %1 +Leave the field empty for using the database encoding. + %1 +Biarkan ruas kosong untuk memakai enkoding basis data. + + + + This encoding is either not valid or not supported. + Enkoding ini tidak valid atau tidak didukung. + + + + %1 replacement(s) made. + %1 penggantian dibuat. + + + + TableBrowserDock + + + New Data Browser + Peramban Data Baru + + + + Rename Data Browser + Ubah Nama Peramban Data + + + + Close Data Browser + Tutup Peramban Data + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + Mengatur sebuah nama baru bagi peramban data. Gunakan karakter '&&' untuk mengizinkan penggunaan karakter berikut sebagai pintasan papan ketik. + + + + VacuumDialog + + + Compact Database + Mampatkan Basis Data + + + + Warning: Compacting the database will commit all of your changes. + Peringatan: Memampatkan basis data akan meng-commit semua perubahan Anda. + + + + Please select the databases to co&mpact: + Harap pilih basis data yang akan di&mampatkan: + + + diff --git a/src/translations/sqlb_it.ts b/src/translations/sqlb_it.ts new file mode 100644 index 000000000..46b9a617c --- /dev/null +++ b/src/translations/sqlb_it.ts @@ -0,0 +1,9318 @@ + + + + + AboutDialog + + + About DB Browser for SQLite + Informazioni su DB Browser for SQLite + + + + Version + Versione + + + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + <html><head/><body><p>DB Browser for SQLite è uno strumento visuale open source e freeware utilizzato per creare, progettare ed editare files di database SQLite.</p><p>È licenziato sia sotto la Mozilla Public License Version 2, che la GNU General Public License Version 3 o successive. Puoi modificare o redistribuirlo rispettando le condizioni di queste licenze.</p><p>Visita <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> e <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> per i dettagli.</p><p>Per ulteriori informazioni su questo applicativo si prega di visitare il nostro sito: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">Questo software utilizza la versione GPL/LGPL del Toolkit Qt da: </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>Visita: </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> per i termini della licenza ed informazioni.</span></p><p><span style=" font-size:8pt;">Utilizziamo la libreria nalgeon/sqlean per il supporto alle estensioni SQLite.<br/>Questa libreria è licenziata tramite la licenza MIT, per ulteriori informazioni visita:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">Utilizziamo anche il set di icone Pastel SVG di Michael Buckley tramite la licenza Creative Commons Attribution Share Alike 4.0.<br/>Visita: </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> per i dettagli.</span></p></body></html> + + + + AddRecordDialog + + + Add New Record + Aggiungi un nuovo record + + + + Enter values for the new record considering constraints. Fields in bold are mandatory. + Inserisci i valori per il nuovo record considerando i vincoli. I campi in grassetto sono obbligatori. + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + Nella colonna Valore puoi specificare il valore per il campo identificato dalla colonna Nome. La colonna Tipo indica il tipo del campo. I valori di default sono mostrati nello stesso stile come valori NULL. + + + + Name + Nome + + + + Type + Tipo + + + + Value + Valore + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + Valori da inserire. Sono preinseriti dei valori di default automaticamente a meno che essi non vengano cambiati. + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + Quando modifichi i valori nel riquadro superiore, la query SQL per inserire questo nuovo record è mostrata qui. Puoi modificare manualmente la query prima di salvare. + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Salva</span> invia la richiesta SQL mostrata al database per inserire un nuovo record.</p><p><span style=" font-weight:600;">Ripristina Defaults</span> ripristinerà i valori iniziali della colonna <span style=" font-weight:600;">Valore</span>.</p><p><span style=" font-weight:600;">Annulla</span> chiuderà questa finestra di dialogo senza eseguire la query.</p></body></html> + + + + Auto-increment + + Auto-incrementale + + + + + Unique constraint + + Restrizione univoco + + + + + Check constraint: %1 + + Controlla restrizioni: %1 + + + + + Foreign key: %1 + + Chiave esterna: %1 + + + + + Default value: %1 + + Valore di default: %1 + + + + + Error adding record. Message from database engine: + +%1 + Errore nell'aggiungere il record. Messaggio dal database engine: + +%1 + + + + Are you sure you want to restore all the entered values to their defaults? + Sei sicuro di voler ripristinare tutti i valori inseriti ai loro valori di default? + + + + Application + + + Possible command line arguments: + Possibili argomenti da linea di comando: + + + + The user settings file location is replaced with the argument value instead of the environment variable value. + La posizione del file di configurazione viene rimpiazzata col valore dell'argomento anziché il valore della variabile d'ambiente. + + + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + Ignorato valore variabile d'ambiente(DB4S_SETTINGS_FILE) : + + + + + The file %1 does not exist + Il file %1 non esiste + + + + Usage + Uso + + + + options + opzioni + + + + + database + database + + + + + project + progetto + + + + + csv-file + csv-file + + + + Show command line options + Mostra le opzioni da riga di comando + + + + Exit application after running scripts + Chiudi l'applicazione dopo aver eseguito gli scripts + + + + + file + file + + + + Execute this SQL file after opening the DB + Esegui questo file SQL dopo aver aperto il DB + + + + Import this CSV file into the passed DB or into a new DB + Importa questo file CSV nel DB fornito o in un nuovo DB + + + + table + tabella + + + + Browse this table, or use it as target of a data import + Scorri questa tabella o usala come destinazione per l'importazione di dati + + + + Open database in read-only mode + Apri il database in sola lettura + + + + settings_file + file_impostazioni + + + + Run application based on this settings file + Esegue l'applicazione basandosi su questo file di configurazione + + + + + group + gruppo + + + + + settings + impostazione + + + + + value + valore + + + + Run application with this setting temporarily set to value + Esegue l'applicazione con questa impostazione temporaneamente impostata al valore + + + + Run application saving this value for this setting + Esegue l'applicazione salvando questo valore come impostazione + + + + Display the current version + Mostra la versione corrente + + + + Open this SQLite database + Apre questo database SQLite + + + + Open this project file (*.sqbpro) + Apre questo file di progetto (*.sqbpro) + + + + Import this CSV file into an in-memory database + Importa questo file CSV in un database in memoria + + + + + + The %1 option requires an argument + L'opzione %1 richiede un argomento + + + + The -S/--settings option requires an argument. The option is ignored. + L'opzione -S/--settings richiede un argomento. L'opzione viene ignorata. + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + L'opzioni -o/--option e -O/--save-option richiedono un parametro nel formato gruppo/impostaizione=valore + + + + SQLite Version + Versione SQLite + + + + SQLCipher Version %1 (based on SQLite %2) + Versione SQLCipher %1 (basata su SQLite %2) + + + + DB Browser for SQLite Version %1. + Versione DB Browser for SQLite %1. + + + + Last commit hash when built: %1 + Ultimo hash del commit quando compilata: %1 + + + + Built for %1, running on %2 + Compilato per %1, in esecuzione su %2 + + + + Qt Version %1 + Versione Qt %1 + + + + Invalid option/non-existent file: %1 + Opzione non valida/file inesistente: %1 + + + + CipherDialog + + + SQLCipher encryption + Criptatura SQLCipher + + + + &Password + &Password + + + + &Reenter password + &Reinserire password + + + + Encr&yption settings + I&mpostazioni cifratura + + + + SQLCipher &3 defaults + Predefiniti SQLCipher &3 + + + + SQLCipher &4 defaults + Predefiniti SQLCipher &4 + + + + Custo&m + Personalizzat&i + + + + Page si&ze + Di&mensioni pagina + + + + &KDF iterations + Integrazione &KDF + + + + HMAC algorithm + Algoritmo HMAC + + + + KDF algorithm + Algoritmo KDF + + + + Plaintext Header Size + Dimensione header testuale + + + + Passphrase + Chiave testuale + + + + Raw key + Chiave grezza + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + Perfavore inserisci una chiave per criptare il database. +Nota che se cambi una qualsiasi delle altre impostazioni opzionali, dovrai reinserirle ogni volta che apri il file del database. +Lascia i campi password vuoti per disabilitare la crittografia. +Il processo di crittazione può richiedere del tempo e dovresti avere una copia di backup del database! Modifiche non salvate sono applicate prima di modificare la crittografia. + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + Si prega d'inserire la chiave utilizzata per criptare il database. +Se una qualunque altra impostazione è stata modificata per l'inserimento della criptazione si prega d'impostarla in modo adeguato. + + + + ColumnDisplayFormatDialog + + + Choose display format + Seleziona il formato di visualizzazione + + + + Display format + Formato di visualizzazione + + + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + Seleziona un formato di visualizzazione per la colonna '%1' che è applicato a ciascun valore prima di mostrarlo. + + + + Default + Default + + + + Decimal number + Numero decimale + + + + Exponent notation + Notazione esponenziale + + + + Hex blob + Blob esadecimale + + + + Hex number + Numero esadecimale + + + + Octal number + Numero ottale + + + + Round number + Numero arrotondato + + + + Apple NSDate to date + Apple NSDate ad oggi + + + + Java epoch (milliseconds) to date + Java epoch (millisecondi) ad oggi + + + + .NET DateTime.Ticks to date + .NET DateTime.Ticks ad oggi + + + + Julian day to date + Giorno giuliano ad oggi + + + + Unix epoch to date + Unix epoch ad oggi + + + + Unix epoch to local time + Unix epoch a ora locale + + + + WebKit / Chromium epoch to date + WebKit / Chromium epoch ad oggi + + + + WebKit / Chromium epoch to local time + WebKit / Chromium epoch a ora locale + + + + Windows DATE to date + Windows DATE ad oggi + + + + Date as dd/mm/yyyy + Data come gg/mm/aaaa + + + + Lower case + Minuscolo + + + + Upper case + Maiuscolo + + + + Binary GUID to text + GUID binario in testo + + + + SpatiaLite Geometry to SVG + SpatiaLite Geometry in SVG + + + + Custom + Personalizzato + + + + Custom display format must contain a function call applied to %1 + I formati di visualizzazione personalizzati devono contenere una chiamata a funzione applicata a %1 + + + + Error in custom display format. Message from database engine: + +%1 + Errore nel formato personalizzato di visualizzazione. Messaggio dal motore DB: + +%1 + + + + Custom display format must return only one column but it returned %1. + Il formato di visualizzazione personalizzato deve restituire solo una colonna ma ha restituito %1. + + + + CondFormatManager + + + Conditional Format Manager + Gestore della formattazione condizionale + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + Questa finestra permette la creazione e modifica della formattazione condizionale. Lo stile di ogni cella corrisponde alla prima condizione corrispondente. Le formattazioni condizionali possono essere spostate su e giù, quelle in posizione superiore avranno precedenza su quelle inferiori. La sintassi per le condizioni è la stessa utilizzata per i filtri e una condizione vuota corrisponde a tutti i valori. + + + + Add new conditional format + Aggiunti nuova condizione + + + + &Add + &Aggiungi + + + + Remove selected conditional format + Rimuovi la condizione selezionata + + + + &Remove + &Rimuovi + + + + Move selected conditional format up + Sposta la condizione selezionata in su + + + + Move &up + Sposta &su + + + + Move selected conditional format down + Sposta la condizione selezionata giù + + + + Move &down + Sposta &giù + + + + Foreground + Primo piano + + + + Text color + Colore del testo + + + + Background + Sfondo + + + + Background color + Colore dello sfondo + + + + Font + Testo + + + + Size + Dimensione + + + + Bold + Grassetto + + + + Italic + Corsivo + + + + Underline + Sottolinea + + + + Alignment + Allineamento + + + + Condition + Condizione + + + + + Click to select color + Clicca per scegliere il colore + + + + Are you sure you want to clear all the conditional formats of this field? + Sei sicuro di voler eliminare tutte le formattazioni condizionali di questo campo? + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + Si prega di specificare il nome del database con cui si vuol accedere al database collegato + + + + Invalid file format + Formato file non valido + + + + Do you really want to close this temporary database? All data will be lost. + Vuoi davvero chiudere questo database temporaneo? Tutti i dati andranno persi. + + + + Do you want to save the changes made to the database file %1? + Vuoi salvare le modifiche effettuate al database %1? + + + + Database didn't close correctly, probably still busy + Il database non è stato chiuso correttamente; probabilmente è ancora occupato + + + + Cannot open destination file: '%1' + Impossibile aprire il file di destinazione: '%1' + + + + + Cannot backup to file: '%1'. Message: %2 + Impossibile creare file di backup: '%1'. Messaggio: %2 + + + + The database is currently busy: + Il database è attualmente in uso: + + + + Do you want to abort that other operation? + Vuoi annullare l'altra operazione? + + + + Exporting database to SQL file... + Esportando il database in file SQL... + + + + + Cancel + Annulla + + + + + No database file opened + Nessun database aperto + + + + Executing SQL... + Eseguendo SQL... + + + + Action cancelled. + Azione annullata. + + + + + Error in statement #%1: %2. +Aborting execution%3. + Errore nello statement #%1: %2. +Annullo l'esecuzione %3. + + + + + and rolling back + e ripristino il db + + + + didn't receive any output from %1 + non ho ricevuto alcun ouput da %1 + + + + could not execute command: %1 + impossibile eseguire il comando: %1 + + + + Cannot delete this object + Non posso cancellare questo oggetto + + + + Cannot set data on this object + Non posso impostare i dati in questo oggetto + + + + + A table with the name '%1' already exists in schema '%2'. + Una tabella con il nome '%1' esiste già nello schema '%2'. + + + + No table with name '%1' exists in schema '%2'. + Nessuna tabella col nome '%1' esiste nello schema '%2'. + + + + + Cannot find column %1. + Impossibile trovare la colonna %1. + + + + Creating savepoint failed. DB says: %1 + Creazione del punto di salvataggio fallita. DB log: %1 + + + + Renaming the column failed. DB says: +%1 + Fallimento dell'operazione di rinomina. DB log: %1 + + + + + Releasing savepoint failed. DB says: %1 + Rilascio del salvataggio falitto. DB log: %1 + + + + Creating new table failed. DB says: %1 + Creazione della nuova tabella fallita. DB log: %1 + + + + Copying data to new table failed. DB says: +%1 + Copia dei dati nella nuova tabella fallita. DB log: %1 + + + + Deleting old table failed. DB says: %1 + Eliminazione della vecchia tabella fallita. DB log: %1 + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + Errore durante il rinomino della tabella '%1' in '%2. +Messaggio dal DB: +%3 + + + + could not get list of db objects: %1 + non posso ottenere la listra degli oggetti db: %1 + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + Ripristino di alcuni oggetti associati a questa tabella fallito. Questo è probabilmente dovuto al fatto che i nomi di alcune colonne sono cambiati . Qui c'è la richiesta SQL che potresti voler sistemare ed eseguire manualmente: + + + + + + could not get list of databases: %1 + non è possibile ricavare la lista dei database: %1 + + + + Error setting pragma %1 to %2: %3 + Errore nell'impostare pragma %1 in %2: %3 + + + + File not found. + File non trovato. + + + + Error loading extension: %1 + Errore nel caricamento dell'estensione: %1 + + + + Error loading built-in extension: %1 + Errore nel caricamento dell'esensione inclusa: %1 + + + + could not get column information + non è possibile ricavare informazioni sulla colonna + + + + DbStructureModel + + + Name + Nome + + + + Object + Oggetto + + + + Type + Tipo + + + + Schema + Schema + + + + Database + Database + + + + Browsables + Navigabili + + + + All + Tutti + + + + Temporary + Temporaneo + + + + Tables (%1) + Tabelle (%1) + + + + Indices (%1) + Indici (%1) + + + + Views (%1) + Viste (%1) + + + + Triggers (%1) + Triggers (%1) + + + + EditDialog + + + Edit database cell + Modifica la cella del database + + + + Mode: + Modalità: + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + Questa è la lista delle modalità supportate dall'editor della cella. Scegli una modalità per vedere o modificare i dati della cella corrente. + + + + Text + Testo + + + + RTL Text + Testo RTL + + + + Binary + Binario + + + + + Image + Immagine + + + + JSON + JSON + + + + XML + XML + + + + Evaluation + Valutazione + + + + + Automatically adjust the editor mode to the loaded data type + Seleziona automaticamente la modalità dell'editor in base al tipo di dato caricato + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + Questo bottone spuntabile permette di abilitare o disabilitare l'adattamento automatico della modalità dell'editor. Quando una nuova cella è selezionata o sono importati nuovi dati e la modalità di adattamento automaitco è abilitata, la modalità si aggiusta al tipo di dato rilevato. Puoi cambiare in seguito la modalità dell'editor in modo manuale. Se vuoi mantenere la modalità selezionata manualmente mentre ti muovi tre le celle, togli la spunta a questo bottone. + + + + Auto-switch + Auto-switch + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + Questo editor Qt è utilizzato per le scritture da destra a sinistra, che non sono supportate dall'editor testuale standard. La presenza di caratteri da destra a sinistra è rilevata e la modalità dell'editor viene selezionata automaticamente. + + + + Identification of the cell currently in the editor + Identificatore della cella attualmente nell'editor + + + + Type and size of data currently in table + Tipo e dimensione del dato attualmente nella tabella + + + + Open preview dialog for printing the data currently stored in the cell + Apre una finestra d'anteprima per la stampa dei dati attualmente memorizzati nella cella + + + + Auto-format: pretty print on loading, compact on saving. + Auto-formato: migliore stampa al caricamento, compatta in salvataggio. + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + Quando abilitato, la feature dell'auto-formato formatta i dati al caricamento, rompe il testo in righe e lo indenta per una maggiore leggibilità. Al salvataggio dei dati, la feature dell'auto-formato compatta i dati rimuovendo i fine riga, e spazi bianchi non necessari. + + + + Word Wrap + A capo automatico + + + + Wrap lines on word boundaries + Porta a capo le line di testo al raggiungimento del bordo + + + + + Open in default application or browser + Apri nell'applicazione predefinita o nel browser + + + + Open in application + Apri nell'applicazione + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + Il valore è interpretato come file o URL e aperto nell'applicazione predefinita o nel web browser. + + + + Save file reference... + Salva riferimento file... + + + + Save reference to file + Salva riferimento su file + + + + + Open in external application + Apri in un'applicazione esterna + + + + Autoformat + Autoformato + + + + &Export... + &Esporta... + + + + + &Import... + &Importa... + + + + + Import from file + Importa da file + + + + + Opens a file dialog used to import any kind of data to this database cell. + Apri una finestra di dialogo per importare qualsiasi tipo di dato in questa cella del database. + + + + Export to file + Esporta in un file + + + + Opens a file dialog used to export the contents of this database cell to a file. + Apri una finestra di dialogo utilizzata per esportare i contenuti di questa cella del database in un file. + + + + Apply data to cell + Applica i dati alla cella + + + + Erases the contents of the cell + Cancella i contenuti di questa cella + + + + Set as &NULL + Imposta come &NULL + + + + This area displays information about the data present in this database cell + Quest'area mostra informazioni riguardo i dati presenti in questa cella del database + + + + This button saves the changes performed in the cell editor to the database cell. + Questo bottone salva le modifiche fatte alla cella dell'editor alla cella del database. + + + + Apply + Applica + + + + Print... + Stampa... + + + + Ctrl+P + + + + + Open preview dialog for printing displayed text + Apri la finestra di anteprima per stampare il testo mostrato + + + + Copy Hex and ASCII + Copia HEX e ASCII + + + + Copy selected hexadecimal and ASCII columns to the clipboard + Copia le colonne esadecimali e ASCII selezionate negli appunti + + + + Ctrl+Shift+C + + + + + + Image data can't be viewed in this mode. + I dati immagine non possono essere visualizzati in questa modalità. + + + + + Try switching to Image or Binary mode. + Prova a passare alla modalità Immagine o Binario. + + + + + Binary data can't be viewed in this mode. + I dati binari non possono essere visualizzati in questa modalità. + + + + + Try switching to Binary mode. + Prova a passare alla modalità Binario. + + + + + Image files (%1) + File immagine (%1) + + + + Binary files (*.bin) + File binario (*.bin) + + + + Choose a file to import + Scegli un file da importare + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + La modalità di editor ti permette di modificare testo, JSON o XML con sintassi evidenziata, formattato automaticamente e validato prima del salvataggio. + +Gli errori sono indicati con una sottolineatura rossa ondeggiata. + +In modalità di Valutazione, le espressioni SQLite inserite sono valutate e il risultato applicato alla cella. + + + + Unsaved data in the cell editor + Dati non salvati nell'editor di cella + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + L'editor di cella contiene dati non ancora applicati al database. +Vuoi applicare i dati modificati alla riga=%1, colonna=%2? + + + + Editing row=%1, column=%2 + Modifica riga=%1, colonna=%2 + + + + No cell active. + Nessuna cella attiva. + + + + %1 Image + %1 Immagine + + + + Choose a filename to export data + Scegli un nome del file per esportare i dati + + + + Invalid data for this mode + Dati non validi per questa modalità + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + La cella continete dati %1 non validi. Ragione: %2. Sei davvero sicuro di applicare quello alla cella? + + + + + Type: NULL; Size: 0 bytes + Tipo: NULL; Dimensione: 0 bytes + + + + + Type: Text / Numeric; Size: %n character(s) + + Tipo: Testo / Numerico; Dimensione: %n carattere + Tipo: Testo / Numerico; Dimensione: %n caratteri + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + Tipo: %1 Immagine; Dimensione: %2x%3 pixel(s) + + + + Type: Valid JSON; Size: %n character(s) + + Tipo: JSON Valido; Dimensione: %n carattere + Tipo: JSON Valido; Dimensione: %n caratteri + + + + + Type: Binary; Size: %n byte(s) + + Tipo: Binario; Dimensione %n byte + Tipo: Binario; Dimensione %n bytes + + + + + Couldn't save file: %1. + Impossibile salvare il file: %1. + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + Il dato è stato salvato in un file temporaneo ed è stato aperto con l'applicazione di default. Ora puoi modificare il file e, quando sei pronto, applicare il nuovo dato salvato alla cella o annullare le modifiche. + + + + EditIndexDialog + + + Edit Index Schema + Modifica Indice Schema + + + + &Name + &Nome + + + + &Table + &Tabella + + + + &Unique + &Univoco + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + Per restringere l'indice a solo una parte della tabella puoi specificare una clausula WHERE qui che selezioni la parte della tabella che dovrà essere indicizzata + + + + Partial inde&x clause + Clausola di &indice parziale + + + + Colu&mns + &Colonne + + + + Table column + Colonna della tabella + + + + Type + Tipo + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + Aggiungi una nuova espressione colonna all'indice. Le espressioni colonna contengono espressioni SQL piuttosto che i nomi delle colonne. + + + + Index column + Indice di colonna + + + + Order + Ordine + + + + Deleting the old index failed: +%1 + Cancellazione del vecchio indice fallita: +%1 + + + + Creating the index failed: +%1 + Creazione del vecchio indice fallita: +%1 + + + + EditTableDialog + + + Edit table definition + Modifica la definizione della tabella + + + + Table + Tabella + + + + Advanced + Avanzate + + + + Database sche&ma + Sche&ma database + + + + Without Rowid + Senza id riga + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + Rendi questa tavola 'WITHOUT ROWID'. Abilitare questo flag obbliga a specificare una PRIMARY KEY (che può essere di qualsiasi tipo, anche composita), e vieta il flag AUTOINCREMENT. + + + + On Conflict + In caso di conflitto + + + + Strict + Esatto + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + Quando l'opzione "esatto" è abilitata SQLite forza il tipo di dato di ogni colonna quando si aggiorna o inserice un dato. + + + + Fields + Campi + + + + + + Add + Aggiungi + + + + + + Remove + Rimuovi + + + + Move to top + Muovi in cima + + + + Move up + Muovi su + + + + Move down + Muovi giù + + + + Move to bottom + Muovi al fondo + + + + + + + Name + Nome + + + + + Type + Tipo + + + + NN + NN + + + + Not null + Non null + + + + PK + CP + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> Chiave primaria</p></body></html> + + + + AI + AI + + + + Autoincrement + Autoincremento + + + + U + U + + + + + + Unique + Univoco + + + + Default + Default + + + + Default value + Valore di default + + + + + Check + Controlla + + + + Check constraint + Controlla le restrizioni + + + + Collation + Fascicola + + + + Foreign Key + Chiave esterna + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_fk"/> Chiave esterna</p></body></html> + + + + Index Constraints + Vincoli Indice + + + + Add constraint + Aggiungi vincolo + + + + Remove constraint + Rimuovi vincolo + + + + + Columns + Colonne + + + + + + SQL + SQL + + + + Foreign Keys + Chiavi esterne + + + + References + Riferimenti + + + + Check Constraints + Vincoli di verifica + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Attenzione: </span>C'è qualcosa in questa definizione di tabella che il nostro parser non comprende. Modificare e salvare questa tabella potrebbe creare dei problemi.</p></body></html> + + + + + Primary Key + Chiave primaria + + + + Add a primary key constraint + Aggiungi un vincolo di chiave primaria + + + + Add a unique constraint + Aggiungi un vincolo di unicità + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + Puoi avere solo una chiave primaria per ogni tabella. Si prega di modificare la chiave primaria attuale. + + + + Error creating table. Message from database engine: +%1 + Error nella creazione della tabella. Messaggio dal database engine: +%1 + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + Esiste già un campo con quel nome. Si prega di rinominarlo prima o scegliere un nome differente per questo campo. + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + Questa colonna è referenziata in una chiave esterna nella tabella %1 e quindi il nome non può essere modificato. + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + Esiste almeno una riga con questo campo impostato a NULL. Questo rende impossibile impostare questa opzione. Si prega prima di modificare quel dato. + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + Esiste almeno un riga con un valore non intero in questo campo. Questo rende impossibile impostare l'AI. Si prega prima di cambiare il dato. + + + + Column '%1' has duplicate data. + + La colonna '%1' ha dei dati duplicati. + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + Questo rende impossibile abilitare l'opzionie 'Univoco'. Perfavore rimuovi i dati duplicati, il che permetterà l'abilitazione dell'opzione 'Univoco'. + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + Sei sicuro di voler eliminare il campo '%1'? +Tutti i dati che sono attualmente memorizzati in questo campo andranno persi. + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + Perfavore agginugi un campo che rispetti i seguenti criteri prima di impostare l'opzione senza id di riga: + - Opzione Chiave Primaria impostata + - Autoincremento disabilitato + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + Si prega di aggiungere un campo che rispetti i seguenti criteri prima d'impostare l'azione "In caso di conflitto": + - Impostare chiave primaria + + + + ExportDataDialog + + + Export data as CSV + Esporta i dati come CSV + + + + Tab&le(s) + Tabe&lla(e) + + + + Colu&mn names in first line + Nomi delle &Colonne sulla prima riga + + + + Fie&ld separator + Separatore di ca&mpo + + + + , + , + + + + ; + ; + + + + Tab + Tab + + + + | + | + + + + + + Other + Altro + + + + &Quote character + &Carattere citazione + + + + " + " + + + + ' + ' + + + + New line characters + Carattere di nuova riga + + + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) + + + + Unix: LF (\n) + Unix: LF (\n) + + + + Pretty print + Visualizzazione piacevole + + + + Export data as JSON + Esporta i dati come JSON + + + + exporting CSV + esportando in CSV + + + + + Error while writing the file '%1': %2 + Errore nella scrittura del file '%1': %2 + + + + + Could not open output file: %1 + Impossibile aprire il file di output: %1 + + + + exporting JSON + esportando in JSON + + + + + Choose a filename to export data + Scegliere un nome file per esportare i dati + + + + Please select at least 1 table. + Perfavore seleziona almeno una tabella. + + + + Choose a directory + Scegliere una cartella + + + + Export completed. + Esportazione completata. + + + + Export finished with errors. + Esportazione completata con errori. + + + + ExportSqlDialog + + + Export SQL... + Esporta SQL... + + + + Tab&le(s) + Tabe&lla(e) + + + + Select All + Seleziona tutto + + + + Deselect All + Deseleziona tutto + + + + &Options + &Opzioni + + + + Keep column names in INSERT INTO + Tieni i nomi delle colonne in INSERT INTO + + + + Multiple rows (VALUES) per INSERT statement + Righe multiple (VALUES) per lo statement INSERT + + + + Export everything + Esporta tutto + + + + Export schema only + Esporta solo lo schema + + + + Export data only + Esporta solo i dati + + + + Keep original CREATE statements + Mantieni le dichiarazioni CREATE originali + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + Mantieni lo schema esistente (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + Sovrascrivi schema precedente (DROP TABLE, poi CREATE TABLE) + + + + Please select at least one table. + Perfavore seleziona almeno una tabella. + + + + Choose a filename to export + Scegli un nome del file per esportare + + + + Export completed. + Esportazione completata. + + + + Export cancelled or failed. + Esportazione annullata o fallita. + + + + ExtendedScintilla + + + + Ctrl+H + + + + + Ctrl+F + + + + + + Ctrl+P + + + + + Find... + Trova... + + + + Find and Replace... + Trova e Sostituisci... + + + + Print... + Stampa... + + + + ExtendedTableWidget + + + Use as Exact Filter + Usa come filtro esatto + + + + Containing + Che contiene + + + + Not containing + Non contenuto + + + + Not equal to + Non uguale a + + + + Greater than + Maggiore di + + + + Less than + Minore di + + + + Greater or equal + Maggiore o uguale + + + + Less or equal + Minore o uguale + + + + Between this and... + Tra questo e... + + + + Regular expression + Espressione regolare + + + + Edit Conditional Formats... + Modifica Formattazione Condizionale... + + + + Set to NULL + Imposta a NULL + + + + Cut + Taglia + + + + Copy + Copia + + + + Copy with Headers + Copia con gli Headers + + + + Copy as SQL + Copia come SQL + + + + Paste + Incolla + + + + Print... + Stampa... + + + + Use in Filter Expression + Usa nell'espressione del filtro + + + + Alt+Del + + + + + Ctrl+Shift+C + + + + + Ctrl+Alt+C + + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + Il contenuto degli appunti è più grande del range selezionato. +Vuoi inserirlo comunque? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>Non tutti i dati sono stati caricati. <b>Vuoi caricare tutti i dati prima di selezionare tutte le righe?</b><p><p>Rispondere <b>No</b> significa che non verranno caricati i restanti dati e la selezione non verrà effettuata.<br/>Rispondere <b>Si</b> potrebbe richiedere del tempo per caricare i dati, ma la selezione sarà completa.</p>Attenzione: Caricare tutti i dati potrebbe richiedere un grosso quantitativo di memoria in caso di grandi tabelle. + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + Impossibile modificare la selezione in NULL. La colonna %1 ho un vincolo NOT NULL. + + + + FileExtensionManager + + + File Extension Manager + Gestore delle estensioni dei files + + + + &Up + Porta &su + + + + &Down + Porta &giù + + + + &Add + &Aggiungi + + + + &Remove + &Rimuovi + + + + + Description + Descrizione + + + + Extensions + Estensioni + + + + *.extension + *.estensione + + + + FilterLineEdit + + + Filter + Filtro + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + Questi campi di input permettono di effettuare filtri rapidi nella tabella correntemente selezionata. +er impostazione predefinita, le righe che contengono il testo immesso sono escluse. +Sono inoltre supportati i seguenti operatori: +% Wildcard +> Maggiore di +< Minore di +>= Maggiore o uguale +<= Minore o uguale += Uguale a: corrispondenza esatta +<> Diverso: corrispondenza esatta invertita +x~y Intervallo: valori tra x e y +/regexp/ Valori che corrispondono all'espressione regolare + + + + Use for Conditional Format + Usa per formattazioni condizionali + + + + Clear All Conditional Formats + Elimina tutte le formattazioni condizionali + + + + Edit Conditional Formats... + Modifica Formattazione Condizionale... + + + + Set Filter Expression + Imposta l'espressione del filtro + + + + What's This? + Cos'è questo? + + + + Is NULL + È NULL + + + + Is not NULL + Non è NULL + + + + Is empty + È vuoto + + + + Is not empty + Non è vuoto + + + + Not containing... + Non contenente... + + + + Equal to... + Uguale a... + + + + Not equal to... + Non uguale a... + + + + Greater than... + Maggiore di... + + + + Less than... + Minore di... + + + + Greater or equal... + Maggiore o uguale... + + + + Less or equal... + Minore o uguale... + + + + In range... + Nell'intervallo... + + + + Regular expression... + Espressione regolare... + + + + FindReplaceDialog + + + Find and Replace + Trova e sostituisci + + + + Fi&nd text: + Tr&ova testo: + + + + Re&place with: + So&stituisci con: + + + + Match &exact case + Corrispondenza &esatta + + + + Match &only whole words + Trova solo &parole complete + + + + When enabled, the search continues from the other end when it reaches one end of the page + Quando abilitato, la ricerca contninua dall'altro capo del documento quando si raggiunge una fine del documento + + + + &Wrap around + Senza &limiti + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + Quando abilitato, la ricerca va all'indietro dalla corrente posizione del cursore, altrimenti va in avanti + + + + Search &backwards + Cerca &indietro + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>Quando abilitato, la ricerca viene effettuata solo all'interno della selezione corrente.</p></body></html> + + + + &Selection only + &Solo selezionati + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Quando selezionato, la stringa del testo viene interpretata come una espressione regolare Unix. Vedi <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Espressioni regolari su Wikibooks (in inglese)</a>.</p></body></html> + + + + Use regular e&xpressions + Usa &espressioni regolari + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + Trova la prossima occorrenza dalla corrente posizione del cursore nella direzione impostata da "Cerca indietro" + + + + &Find Next + &Trova successivo + + + + F3 + + + + + &Replace + &Sostituisci + + + + Highlight all the occurrences of the text in the page + Evidenzia tutte le occorrenze del testo nella pagina + + + + F&ind All + T&rova tutti + + + + Replace all the occurrences of the text in the page + Sostituisce tutte le occorrenze del testo nella pagina + + + + Replace &All + Sostituisci &Tutti + + + + The searched text was not found + Il testo cercato non è stato trovato + + + + The searched text was not found. + Il testo cercato non è stato trovato. + + + + The searched text was found one time. + Il testo cercato è stato trovato una volta. + + + + The searched text was found %1 times. + Il testo cercato è stato trovato %1 volte. + + + + The searched text was replaced one time. + Il testo cercato è stato sostituito una volta. + + + + The searched text was replaced %1 times. + Il testo cercato è stato sostituito %1 volte. + + + + ForeignKeyEditor + + + &Reset + &Reimposta + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + Clausule per chiave esterna (ON UPDATE, ON DELETE etc.) + + + + ImageViewer + + + Image Viewer + Visualizzatore immagine + + + + Reset the scaling to match the original size of the image. + Reimposta il fattore di scala per rispettare la dimensione originale dell'immagine. + + + + Set the scaling to match the size of the viewport. + Imposta il fattore di scala per adattare l'immagine all'area di visualizzazione. + + + + Print... + Stampa... + + + + Open preview dialog for printing displayed image + Apri la finestra di anteprima per stampare l'immagine mostrata + + + + Ctrl+P + Ctrl+P + + + + ImportCsvDialog + + + Import CSV file + Imoprta file CSV + + + + Table na&me + No&me tabella + + + + &Column names in first line + Nomi &colonna nella prima riga + + + + Field &separator + &Separatore di campo + + + + , + , + + + + ; + ; + + + + + Tab + Tab + + + + | + | + + + + Other + Altro + + + + &Quote character + &Carattere citazione + + + + + Other (printable) + Altro (stampabile) + + + + + Other (code) + Altro (codice) + + + + " + " + + + + ' + ' + + + + &Encoding + Codific&a + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Trim fields? + Pulizia campi? + + + + Separate tables + Separa tabelle + + + + Advanced + Avanzate + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + Quando importo un campo vuoto dal file CSV dentro una tabella con un valore predefinito per quella colonna, quel valore viene inserito. Attivare quest'opzione per inserire invece un valore vuoto. + + + + Ignore default &values + Ignora valori &predefiniti + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + Attivare quest'opzione per fermare l'importazione quando si prova ad importare un valore vuoto in una colonna "NOT NULL" senza valore predefinito. + + + + Fail on missing values + Fallisci su valori mancanti + + + + Disable data type detection + Disabilita rilevamento tipo dati + + + + Disable the automatic data type detection when creating a new table. + Disabilita il riconoscimento automatico della tipologia di dato quando crea una nuova tabella. + + + + Use local number conventions + Usa convenzioni numeriche locali + + + + Use decimal and thousands separators according to the system locale. + Usa i separatori decimali e di migliaia in accordo col sistema locale. + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + Quando si importano dati all'interno di una tabella esistente con una chiave primaria, potrebbero esserci conflitti. Questa opzione ti permette di selezionare una strategia per quei casi: Di base l'importazione è annullata e viene fatto un rollback, ma puoi anche scegliere d'ignorare e non importare le righe in conflitto o di rimpiazzare quelle presenti nella tabella. + + + + Abort import + Annulla l'importazione + + + + Ignore row + Ignora la riga + + + + Replace existing row + Rimpiazza la riga esistente + + + + Conflict strategy + Strategia di conflitto + + + + + Deselect All + Deseleziona tutte + + + + Match Similar + Seleziona simili + + + + Select All + Seleziona tutte + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + Esiste già una tabella col nome '%1' e l'importazione in una tabella esistente non è possibile se il numero di colonne non corrisponde. + + + + There is already a table named '%1'. Do you want to import the data into it? + Esiste già una tabella col nome '%1'. Vuoi importare i dati al suo interno? + + + + Creating restore point failed: %1 + Creazione del punto di ripristino fallita: %1 + + + + Creating the table failed: %1 + Creazione della tabella fallita: %1 + + + + importing CSV + importo il CSV + + + + Could not prepare INSERT statement: %1 + Non posso preparae la dichiarazione INSERT: %1 + + + + Inserting row failed: %1 + Inserimento della riga fallito: %1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + Fine del file inaspettata. Si prega di verificare l'impostazione corretta dei caratteri di citazione e che il file non sia malformato. + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + Importare il file '%1' ha richiesto %2ms. Di questi %3ms sono stati spesi in funzioni di riga. + + + + MainWindow + + + DB Browser for SQLite + DB Browser for SQLite + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + Questa è la struttura del database aperto. +Puoi trascinare SQL da una riga oggetto e rilasciarli dentro altri applicativi o in altre istanze di àDB Browser for SQLite'. + + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + Attenzione: questo pragma non è leggibile e questo valore è stato dedotto. Scrivere i pragma può sovrascrivere un LIKE ridefinito provvisto da un'estensione di SQLite. + + + + toolBar1 + + + + + &File + &File + + + + &Import + &Importa + + + + &Export + &Esporta + + + + &Edit + &Modifica + + + + &View + &Visualizza + + + + &Help + &Aiuto + + + + Too&ls + &Strumenti + + + + DB Toolbar + Barra degli strumenti del DB + + + + Edit Database &Cell + Modifica &cella + + + + SQL &Log + &Log SQL + + + + Show S&QL submitted by + Mostra l'S&QL inviato da + + + + User + Utente + + + + Application + Applicazione + + + + Error Log + Registro errori + + + + This button clears the contents of the SQL logs + Questo pulsante cancella il contenuto del log SQL + + + + &Clear + &Pulisci + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + Questo pannello ti permette di esaminare il log di tutti i comandi SQL inviati dall'applicazione o da te stesso + + + + &Plot + &Grafica + + + + DB Sche&ma + Sche&ma DB + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + Questa è la struttura del database aperto. +Puoi trascinare nomi d'oggetto multipli dalla colonna "Nome" e rilasciarli all'interno dell'editor SQL e puoi modificare le proprietà dei nomi rilasciati utilizzando il menù contestuale. Questo può aiutarti nel comporre statement SQL. +Puoi trascinare statement SQL dalla colonna Schema e rilasciarli dentro l'editor SQL o all'interno di altre applicazioni. + + + + + &Remote + &Remoto + + + + + Project Toolbar + Barra degli strumenti di progetto + + + + Extra DB toolbar + Barra degli strumenti extra DB + + + + + + Close the current database file + Chiudi il file di database corrente + + + + &New Database... + &Nuovo Database... + + + + + Create a new database file + Crea un nuovo file di database + + + + This option is used to create a new database file. + Questa opzione è utilizzata per creare un nuovo file di database. + + + + Ctrl+N + + + + + + &Open Database... + &Apri Database... + + + + + + + + Open an existing database file + Apre un file di database esistente + + + + + + This option is used to open an existing database file. + Questa opzione è utilizzata per aprire un file esistente di database. + + + + Ctrl+O + + + + + &Close Database + &Chiudi Database + + + + This button closes the connection to the currently open database file + Questo pulsnate chiude la connessione al file di database attualmente aperto + + + + + Ctrl+W + + + + + &Revert Changes + &Ripristina le modifiche + + + + + Revert database to last saved state + Ripristina il database all'ultimo stato salvato + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + Questa opzione è utilizzata per ripristinare il file di database al suo ultimo stato salvato. Tutte le modifiche fatte dall'ultima opzione di salvataggio sono perse. + + + + &Write Changes + &Salva le modifiche + + + + + Write changes to the database file + Scrive le modifiche sul file di database + + + + This option is used to save changes to the database file. + Questa opzione è utilizzata per salvare le modifiche sul file di database. + + + + Ctrl+S + + + + + Compact &Database... + &Compatta Database... + + + + Compact the database file, removing space wasted by deleted records + Compatta il file di database, rimuovendo lo spazio sprecato dalle righe eliminate + + + + + Compact the database file, removing space wasted by deleted records. + Compatta il file di database rimuovendo lo spazio sprecato dalle righe eliminate. + + + + E&xit + &Esci + + + + Ctrl+Q + + + + + &Database from SQL file... + &Database dal file SQL... + + + + Import data from an .sql dump text file into a new or existing database. + Importa i dati da un file di testo di dump .sql all'interno di un database nuovo o esistente. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + Questa opzione ti permette d'importare i dati da un file di testo di dump .sql all'interno di un database nuovo o esistente. I file di dump SQL possono essere creati dalla maggiorparte dei motori SQL, inclusi MySQL e PostgreSQL. + + + + &Table from CSV file... + &Tabella da file CSV... + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Apre un wizard che ti permette d'importare dati da un file CSV all'interno di una tabella del database. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Apre un wizard che ti permette d'importare dati da un file CSV all'interno di una tabella del database. I file CSV possono essere creati dalla maggiorparte delle applicazioni database o foglio di calcolo. + + + + &Database to SQL file... + &Database in file SQL... + + + + Export a database to a .sql dump text file. + Esporta un database in un file di testo di dump .sql. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + Questa opzione ti permette di esportare un database in un file di testo di dump .sql. Il file di dump SQL contiene tutti i dati necessari per ricreare il database sulla maggiorparte di motori di database, inclusi MySQL e PostgreSQL. + + + + &Table(s) as CSV file... + &Tabella(e) come file CSV... + + + + Export a database table as a comma separated text file. + Esporta la tabella del database come un file di testo CSV. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + Esporta la tabella del database come un file di testo CSV, pronto per essere importato in un altro database o foglio di calcolo. + + + + &Create Table... + &Crea tabella... + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Apre un wizard per la creazione di una tabella, dov'è possibile definire il nome e i campi di una nuova tabella del database + + + + &Delete Table... + &Elimina tabella... + + + + + Delete Table + Elimina Tabella + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Apre un wizard per la cancellazione della tabella, da qui puoi selezionare la tabella del database da eliminare. + + + + &Modify Table... + &Modifica Tabella... + + + + Create &Index... + Crea &Indice... + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + Apre un wizard per la crazione di un indice, da qui è possibile definire un nuovo indice s'una tabella di database pre-esistente. + + + + &Preferences... + &Preferenze... + + + + + Open the preferences window. + Apre la finestra delle preferenze. + + + + &DB Toolbar + &Barra degli strumenti + + + + Shows or hides the Database toolbar. + Mostra o nasconde la barra degli strumenti del database. + + + + New &tab + Nuovo &tab + + + + Ctrl+T + + + + + Open SQL file(s) + Apri file(s) SQL + + + + This button opens files containing SQL statements and loads them in new editor tabs + Questo pulsante apre files contenenti dichiarazioni SQL e le carica in un nuova scheda dell'editor + + + + Execute line + Esegui riga + + + + F1 + + + + + Sa&ve Project + Sal&va Progetto + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + Questo pulsante ti permette di salvare tutte le impostazioni associate all'apertura di un DB in un nuovo file di progetto DB Browser for SQLite + + + + This button lets you open a DB Browser for SQLite project file + Questo pulsante ti permette di aprire un file di progetto DB Browser for SQLite + + + + Ctrl+Shift+O + + + + + Find + Trova + + + + Find or replace + Trova o sostituisci + + + + Print text from current SQL editor tab + Stampa testo dalla scheda corrente dell'editor SQL + + + + Print the structure of the opened database + Stampa la struttura del database aperto + + + + Un/comment block of SQL code + De/Commenta il blocco di codice SQL + + + + Un/comment block + De/Commenta il blocco + + + + Comment or uncomment current line or selected block of code + Commenta o decommenta la riga corrente o il blocco selezionato di codice + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + Commenta o decommenta le righe selezionate o la riga corrente, quando non c'è nessuna selezione. Tutti i blocchi sono modificati in accordo alla prima riga. + + + + Ctrl+/ + + + + + Stop SQL execution + Ferma esecuzione SQL + + + + Stop execution + Ferma esecuzione + + + + Stop the currently running SQL script + Ferma lo script SQL attualmente in esecuzione + + + + &Save Project As... + Salva Progetto C&ome... + + + + + + Save the project in a file selected in a dialog + Salva il progetto in un file selezionato tramite una finestra di dialogo + + + + Save A&ll + Salva T&utto + + + + + + Save DB file, project file and opened SQL files + Salva il file DB, file di progetto e tutti i file SQL aperti + + + + Ctrl+Shift+S + + + + + Browse Table + Naviga nei dati + + + + Close Pro&ject + Chiudi Pro&getto + + + + + Close project and database files and return to the initial state + Chiude il progetto e i file di database e ritorna allo stato iniziale + + + + Ctrl+Shift+F4 + Ctrl+Shift+F4 + + + + + Detach Database + Scollega Database + + + + + Detach database file attached to the current database connection + Scollega il file di database associato alla connessione corrente + + + + W&hat's This? + Cos'è &questo? + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + Struttura &Database + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + &Visualizza Dati + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + Modifica P&ragmas + + + + Temp Store + + + + + Secure Delete + + + + + Case Sensitive Like + + + + + Journal Mode + + + + + Journal Size Limit + + + + + Recursive Triggers + + + + Delete + pragma + Elimina + + + + Page Size + + + + + Foreign Keys + Chiavi esterne + + + + Auto Vacuum + + + + + Max Page Count + + + + + Checkpoint Full FSYNC + + + + + + Off + + + + + + Normal + + + + + + Full + + + + + Default + Default + + + + File + File + + + + + Memory + + + + + Delete + Elimina + + + + Truncate + + + + + Persist + + + + + WAL + + + + + Exclusive + + + + + Automatic Index + + + + + Ignore Check Constraints + + + + + Full FSYNC + + + + + WAL Auto Checkpoint + + + + + User Version + + + + + Synchronous + + + + + None + Nessuna + + + + Incremental + + + + + Locking Mode + + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + &Esegui SQL + + + + &Recent Files + F&iles Recenti + + + + &New Database + &Nuovo Database + + + + &Undo + A&nnulla + + + + + Undo last change to the database + Annulla l'ultima modifica al database + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + Questa azione annulla l'ultima modifica effettuata al database in "Visualizza Dati" o in "Esegui SQL". Riapplicarla non è possibile. + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + Apre il wizard per Modificare la Tabella, in cui è possibile rinominare una tabella esistente. Si può anche aggiungere o eliminare campi da una tabella così come modificarne nome e tipo. + + + + Shift+F1 + + + + + &About + &Informazioni + + + + &Recently opened + &Aperti di recente + + + + This button opens a new tab for the SQL editor + Questo pulsante apre una nuova schede dell'editor SQL + + + + &Execute SQL + &Esegui SQL + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + Questo pulsante esegue gli statement SQL evidenziati. Se nessun testo è selezionato, tutti gli statement SQL vengono eseguiti. + + + + Ctrl+Shift+T + Ctrl+Shift+T + + + + + + Save SQL file + Salva file SQL + + + + &Load Extension... + &Carica Estensioni... + + + + + Execute current line + Esegue la riga corrente + + + + This button executes the SQL statement present in the current editor line + Questo pulsante esegue lo statement SQL presente nella riga corrente dell'editor + + + + Shift+F5 + + + + + Export as CSV file + Esporta come file CSV + + + + Export table as comma separated values file + Esporta la tabella come file CSV + + + + &Wiki + &Wiki + + + + Bug &Report... + Bug &Report... + + + + Feature Re&quest... + Richiesta &Funzionalità... + + + + Web&site + Sito &Web + + + + &Donate on Patreon... + &Dona su Patreon... + + + + &Save Project + &Salva Progetto + + + + + Save the current session to a file + Salva la sessione correte in un file + + + + Open &Project... + Apri &Progetto... + + + + Open &Project + Apri &Progetto + + + + + Load a working session from a file + Carica una sessione di lavoro da file + + + + &Attach Database... + Co&llega Database... + + + + + Add another database file to the current database connection + Aggiunge un altro file di database alla connessione corrente + + + + This button lets you add another database file to the current database connection + Questo pulsante ti permette di aggiungere un altro file alla connessione corrente + + + + &Set Encryption... + &Imposta cifratura... + + + + + Save SQL file as + Salva file SQL come + + + + This button saves the content of the current SQL editor tab to a file + Questo pulsante salva il contenuto della scheda di editor SQL in un file + + + + &Browse Table + &Naviga Tabella + + + + Copy Create statement + Copia statement CREATE + + + + Copy the CREATE statement of the item to the clipboard + Copia lo statement CREATE negli appunti + + + + SQLCipher &FAQ + SLQCipher &FAQ + + + + Opens the SQLCipher FAQ in a browser window + Apre le SQLCipher FAQ in una finestra del browser + + + + Table(&s) to JSON... + Tabella(&e) in JSON... + + + + Export one or more table(s) to a JSON file + Esporta una o più tabelle in un file JSON + + + + Open Data&base Read Only... + Apri un Data&base in Sola Lettura... + + + + Open an existing database file in read only mode + Apre un file databse esistente in modalità sola lettura + + + + Save results + Salva risultati + + + + Save the results view + Salva i risultati della vista + + + + This button lets you save the results of the last executed query + Questo pulsante ti permette di salvare i risultati dell'ultima query eseguita + + + + + Find text in SQL editor + Trova testo nell'editor SQL + + + + This button opens the search bar of the editor + Questo pulsante apre la barra di ricerca dell'editor + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + Trova e/o sostituisci testo nell'editor SQL + + + + This button opens the find/replace dialog for the current editor tab + Questo pulsante apre la finestra di ricerca/sostituzione testo per la scheda corrente dell'editor + + + + Ctrl+H + + + + + Export to &CSV + Esporta in &CSV + + + + Export to &JSON + Esporta in &JSON + + + + Save as &view + Salva come &vista + + + + Save as view + Salva come vista + + + + Shows or hides the Project toolbar. + Mostra o nasconde la barra degli strumenti di progetto. + + + + Extra DB Toolbar + Barra degli strumenti DB estesa + + + + &Open Database + &Apri Database + + + + New In-&Memory Database + Nuovo Database In M&emoria + + + + Drag && Drop SELECT Query + Trascina && Rilascia Query SELECT + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + Quando si trascinano campi da una stessa tabella o una singola tabella, rilascia una query SELECT nell'editor + + + + Drag && Drop Qualified Names + Trascina && Rilascia Nomi Qualificati + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + Usa nomi qualificati (es. "Table"."Campo") quando trascini gli oggetti e li rilasci all'interno dell'editor + + + + Drag && Drop Enquoted Names + Trascina && Rilascia Nomi Quotati + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + Usa gl'identificatori di citazione (es. "Tabella1") quando trascini e rilasci gli oggetti nell'editor + + + + &Integrity Check + Controllo &Integrità + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + Avvia il controllo integrità (integrity check pragma) sul database aperto e riporta il risultato nella scheda "Esegui SQL". Questa operazione esegue un controllo d'integrità sull'intero database. + + + + &Foreign-Key Check + Controlla Chiave &Esterna + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + Avvia il controllo chiavi esterne (foreign_key_check pragma) nel database aperto e riporta il risultato nella scheda "Esegui SQL" + + + + &Quick Integrity Check + Controllo Integrità &Veloce + + + + Run a quick integrity check over the open DB + Avvia un controllo veloce d'integrità sul DB aperto + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + Avvia un controllo veloce d'integrità (quick_check pragma) sul database e riporta il risultato nella scheda "Esegui SQL". Quest comando esegue la maggiorparte dei controlli d'integrità del controllo completo, ma in modo molto più veloce. + + + + &Optimize + &Ottimizza + + + + Attempt to optimize the database + Prova ad ottimizzare il database + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + Avvia l'ottimizzazione del database aperto. Questa operazione potrebbe eseguire delle ottimizzazione che miglioreranno le performance delle query future. + + + + + Print + Stampa + + + + Open a dialog for printing the text in the current SQL editor tab + Apre una finetra per la stampa del testo nella scheda dell'editor SQL + + + + Open a dialog for printing the structure of the opened database + Apre una finestra per la stampa della struttura del database aperto + + + + + Ctrl+Shift+W + Ctrl+Shift+W + + + + Table from CSV data in Clipboard... + Tabella da dati CSV negli Appunti... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + Questo tratta il contenuto attuale degli Appunti come un file CSV e apre lo stesso wizard d'importazione che viene utilizzato per importare dati da un file CSV. + + + + Show &Row Counts + Mostra Numero &Righe + + + + This shows the number of rows for each table and view in the database. + Questo mostra il numero di righe per ogni tabella e vista del database. + + + + Save Database &As... + Salva Database Co&me... + + + + Save the current database as a different file + Salva il database corrente in un diverso file + + + + Refresh + Aggiorna + + + + Reload the database structure + Aggiorna la struttura del database + + + + + Ctrl+P + + + + + + Ctrl+F4 + + + + + Execute all/selected SQL + Esegui tutti gli SQL o quelli selezionati + + + + Ctrl+Return + + + + + Ctrl+L + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Ctrl+E + + + + + Reset Window Layout + Ripristina disposizione finestra + + + + The database is currently busy. + Il database è occupato. + + + + Click here to interrupt the currently running query. + Clicca qui per interrompere la query in esecuzione. + + + + Encrypted + Criptato + + + + Database is encrypted using SQLCipher + Il database è stato criptato utilizzando SQLCipher + + + + Read only + Sola lettura + + + + Database file is read only. Editing the database is disabled. + Il file di database è in sola lettura. Le modifiche al database sono disabilitate. + + + + Database encoding + Codifica Database + + + + + Choose a database file + Seleziona un file di database + + + + Could not open database file. +Reason: %1 + Impossibile aprire il file di database. +Motivo: %1 + + + + + + Choose a filename to save under + Seleziona un nome file per il salvataggio + + + + In-Memory database + Database In-Memoria + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + Sei sicuro di voler eliminare la tabella '%1'? +Tutti i dati associati alla tabella andranno perduti. + + + + Are you sure you want to delete the view '%1'? + Sei sicuro di voler eliminare la vista '%1'? + + + + Are you sure you want to delete the trigger '%1'? + Sei sicuro di voler eliminare il trigger '%1'? + + + + Are you sure you want to delete the index '%1'? + Sei sicuro di voler eliminare l'indice '%1'? + + + + Error: could not delete the table. + Errore: impssibile eliminare la tabella. + + + + Error: could not delete the view. + Errore: impossibile eliminare la vista. + + + + Error: could not delete the trigger. + Errore: impossibile eliminare il trigger. + + + + Error: could not delete the index. + Errore: impossibile eliminare l'indice. + + + + Message from database engine: +%1 + Messaggio dal database: +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + Per modificare la tabella bisogna salvare tutte le modifiche pendenti. +Sei sicuro di voler salvare il database? + + + + Error checking foreign keys after table modification. The changes will be reverted. + Errore nel controllo delle chiavi esterne dopo le modifiche alla tabella. Le modifiche saranno eliminate. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + Questa tabella non ha passato il controllo sulle chiavi esterne.<br/>Dovresti avviare 'Strumenti | Controllo Chiavi Esterne' e correggere i problemi riportati. + + + + Edit View %1 + Modifica Vista %1 + + + + Edit Trigger %1 + Modifica Trigger %1 + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + Sto eseguendo degli SQL. Vuoi fermarli per poter eseguire invece l'SQL corrente? Nota che questo potrebbe lasciare il database in uno stato inconsistente. + + + + -- EXECUTING SELECTION IN '%1' +-- + -- ESEGUO LA SELEZIONE IN '%1' +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- ESEGUO LINEA IN '%1' +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- ESEGUO TUTTO IN '%1' +-- + + + + + At line %1: + Alla riga %1: + + + + Result: %1 + Risultato: %1 + + + + Result: %2 + Risultato: %2 + + + + Opened '%1' in read-only mode from recent file list + Aperto '%1' in modalità sola lettura dalla lista dei files recenti + + + + Opened '%1' from recent file list + Aperto '%1' dalla lista dei files recenti + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + Le dichiarazioni nella scheda '%1' sono ancora in esecuzione. Chiudere la scheda fermerà l'esecuzione. Questo potrebbe lasciare il database in uno stato inconsistente. Sei sicuro di voler chiudere la scheda? + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + Questo file di progetto utilizza un vecchio formato perché è stato creato con DB Browser for SQLite versione 3.10 o precedente. Il caricamento di questo formato non è più pienamente supportato. Se vuoi caricarlo completamente, si prega di utilizzare DB Browser for SQLite versione 3.12 per convertirlo al nuovo formato. + + + + Project saved to file '%1' + Progetto salvato sul file '%1' + + + + Yes. Don't ask again + Si, non chiedere di nuovo + + + + This action will open a new SQL tab with the following statements for you to edit and run: + Questa azione apre una nuova scheda SQL con le seguenti dichiarazioni per te da editare ed eseguire: + + + + Rename Tab + Rinomina il Tab + + + + Duplicate Tab + Duplica il Tab + + + + Close Tab + Chiudi il Tab + + + + Opening '%1'... + Apro '%1'... + + + + There was an error opening '%1'... + Errore durante l'apertura di '%1'... + + + + Value is not a valid URL or filename: %1 + Il valore non è un URL valida o nome file: %1 + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + Impostare i valori PRAGMA o pulizia chiuderanno la transazione corrente. +Sei sicuro? + + + + Execution finished with errors. + Esecuzione completata con errori. + + + + Execution finished without errors. + Esecuzione completata senza errori. + + + + %1 rows returned in %2ms + %1 righe ritornate in %2ms + + + + Automatically load the last opened DB file at startup + Carica automaticamente l'ultimo file DB aperto all'avvio + + + + Choose text files + Seleziona i file di testo + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + Errore nel salvataggio del database. Questo significa che non tutte le modifiche del database sono state salvate. Avrai bisogno di risolvere prima il seguente errore. + +%1 + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + Sei sicuro di voler annullare tutte le modifiche effettuate al database '%1' dall'ultimo salvataggio? + + + + Choose a file to import + Seleziona un file da importare + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (sola lettura) + + + + Open Database or Project + Apri Database o Progetto + + + + Attach Database... + Collega Database... + + + + Import CSV file(s)... + Importa file(s) CSV... + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + Vuoi salvare le modifiche effettuate ai tabs SQL nel file di progetto '%1'? + + + + Text files(*.sql *.txt);;All files(*) + File di testo(*.sql *.txt);;Tutti i files(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + Vuoi creare un nuovo file di database per mantenere i dati importati? +Se rispondi di no proveremo ad importare i dati del file SQL all'interno del database corrente. + + + + Ctrl+Tab + Ctrl+Tab + + + + Ctrl+Shift+Tab + Ctrl+Shift+Tab + + + + Clear List + Pulisci la Lista + + + + Window Layout + Disposizione finestra + + + + Ctrl+0 + Ctrl+0 + + + + Simplify Window Layout + Semplifica Disposizione Finestra + + + + Alt+Shift+0 + Alt+Shift+0 + + + + Dock Windows at Bottom + Posiziona Finestre nel Basso + + + + Dock Windows at Left Side + Posiziona Finestre sul Lato Sinistro + + + + Dock Windows at Top + Posiziona Finestre in Alto + + + + Alt+Shift+W + Alt+Shift+W + + + + Choose a database file to save under + Scegli il file database in cui salvare + + + + Error while saving the database to the new file. + Errore nel salvataggio in un nuovo file di database. + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + Sto ancora eseguendo comandi SQL. Se chiudi il database ora non verrano eseguiti, il database potrebbe rimanere in uno stato inconsistente. Sei sicuro di voler chiudere il database? + + + + Do you want to save the changes made to the project file '%1'? + Vuoi salvare le modifiche fatte al file di progetto '%1'? + + + + File %1 already exists. Please choose a different name. + Il file %1 esiste già. Si prega di scegliere un nome differente. + + + + Error importing data: %1 + Errore nell'importazione: %1 + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + Importaizone completata. Alcuni vincoli per le chiavi esterne non sono rispettati. Si prega di correggerli prima di salvare. + + + + Import completed. + Import completato. + + + + Delete View + Elimina Vista + + + + Modify View + Modifica Vista + + + + Delete Trigger + Elimina Trigger + + + + Modify Trigger + Modifica Trigger + + + + Delete Index + Elimina Indice + + + + Modify Index + Modifica Indice + + + + Modify Table + Modifica Tabella + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + Seleziona l'azione da applicare al file scartato. <br/>Nota: solo 'Importa' processa più di un file. + Seleziona l'azione da applicare ai files scartati. <br/>Nota: solo 'Importa' processa più di un file. + + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + Impostare i valori di PRAGMA chiuderà la transaione corrente. +Sei sicuro? + + + + Do you want to save the changes made to SQL tabs in a new project file? + Vuoi salvare le modifiche effettuate alle schede SQL in un nuovo file di progetto? + + + + Do you want to save the changes made to the SQL file %1? + Vuoi salvare le modifiche fatte al file SQL %1? + + + + Select SQL file to open + Selezionare il file SQL da aprire + + + + Select file name + Seleziona il nome del file + + + + Select extension file + Seleziona l'estensione del file + + + + Extension successfully loaded. + Estensione caricata con successo. + + + + Error loading extension: %1 + Errore nel caricamento dell'estensione: %1 + + + + Could not find resource file: %1 + Non posso aprire il file di risorse: %1 + + + + + Don't show again + Non mostrare di nuovo + + + + New version available. + Nuova versione disponibile. + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + Una nuova versione di DB Browser for SQLite è disponibile (%1.%2.%3).<br/><br/>Si prega di scaricarla da <a href='%4'>%4</a>. + + + + Choose a project file to open + Seleziona un file di progetto da aprire + + + + DB Browser for SQLite project file (*.sqbpro) + File di progetto DB Browser for SQLite (*.sqbpro) + + + + DB file '%1' could not be opened + Il file DB '%1' non può essere aperto + + + + Table '%1' not found; settings ignored + Tabella '%1' non trovata; impostazioni ignorate + + + + Could not open project file for writing. +Reason: %1 + Non posso scrivere nel file di progetto. +Motivo: %1 + + + + -- Reference to file "%1" (not supported by this version) -- + -- Riferimento al file "%1" (non supportato in questa versione) -- + + + + Collation needed! Proceed? + Necessario confronto! Procedo? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + Una tabella di questo database richiede una funzione di confronto speciale '%1' che questa applicazione non può fornire senza ulteriori informazioni. +Se scegli di proseguire, sappi che potrebbero generarsi problemi nel tuo database. +Crea un backup! + + + + creating collation + creo confronto + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + Imposta un nuovo nome per la scheda SQL. Usa il carattere '&&' per utilizzare il carattere succesivo come scorciatoia da tastiera. + + + + Please specify the view name + Si prega di specificare il nome della vista + + + + There is already an object with that name. Please choose a different name. + Esiste già un oggetto con quel nome. Si prega di scegliere un nome diverso. + + + + View successfully created. + Vista creata con successo. + + + + Error creating view: %1 + Errore nella creazione della vista: %1 + + + + This action will open a new SQL tab for running: + Questa azione aprirà una nuova scheda SQL per eseguire: + + + + Press Help for opening the corresponding SQLite reference page. + Premi Aiuto per aprire la pagina di riferimento SQLite corrispondente. + + + + Busy (%1) + Occupato (%1) + + + + NullLineEdit + + + Set to NULL + Imposta a NULL + + + + Alt+Del + + + + + PlotDock + + + Plot + Grafico + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>Questo pannello mostra la lista delle colonne della tabella corrente o della query eseguita. Puoi selezionare la colonna che vuoi utilizzare come asse X o Y per il grafico sottostante. La tabella mostra i tipi d'asse rilevati. Per l'asse Y puoi selezionare solo colonne numeriche, ma per l'asse X potrai selezionare:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Data/Ora</span>: stringhe col formato &quot;aaaa-MM-gg hh:mm:ss&quot; o &quot;aaaa-MM-ggThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Data</span>: stringhe col formato &quot;aaaa-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Orario</span>: stringhe col formato &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Etichette</span>: altri formati di stringa. Selezionando queste colonne come X verrà visualizzato un grafico a barre</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeri</span>: interi or valori reali</li></ul><p>Cliccando due volte sulle celle Y potrai cambiare il colore utilizzato per il grafico.</p></body></html> + + + + Columns + Colonne + + + + X + + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + Tipo asse + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + Qui compare il grafico quando vengono selezionati i valori x e y. + +Clicca s'un punto per selezionarl sul grafico e nella tabella. Ctrl+Click per selezionare un intervallo di punti. + +Usa la rotella del mouse per ingrandire e trascina col mouse per cambiare l'intervallo degli assi. + +Seleziona le etichette dell'asse o degli assi per trascinare o ingrandire solo in quella direzione. + + + + Line type: + Tipo linea: + + + + + None + Nessuna + + + + Line + Linea + + + + StepLeft + Salto sinistro + + + + StepRight + Salto destro + + + + StepCenter + Salto centrato + + + + Impulse + Impulso + + + + Point shape: + Tipo punta: + + + + Cross + Croce + + + + Plus + Più + + + + Circle + Cerchio + + + + Disc + Disco + + + + Square + Quadrato + + + + Diamond + Rombo + + + + Star + Stella + + + + Triangle + Triangolo + + + + TriangleInverted + Triangolo inverso + + + + CrossSquare + Croce quadrato + + + + PlusSquare + Più quadrato + + + + CrossCircle + Croce cerchio + + + + PlusCircle + Più cerchio + + + + Peace + Pace + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>Salva il grafico corrente...</p><p>Formato file selezionato dall'estensione (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + Salva il grafico corrente... + + + + + Load all data and redraw plot + Carica tutti i dati e ridisegna grafico + + + + Copy + Copia + + + + Print... + Stampa... + + + + Help + + + + + Show legend + Mostra legenda + + + + Stacked bars + Barre impilate + + + + Fixed number format + Formato numero fisso + + + + Date/Time + Data/Ora + + + + Date + Data + + + + Time + Ora + + + + + Numeric + Numerico + + + + Label + Etichetta + + + + Invalid + Invalido + + + + + + Row # + Riga # + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + Carica tutti i dati e ridisegna grafico. +Attenzione: non sono ancora stati recuperati tutti i dati dalla tabella a causa del meccanismo di recupero. + + + + Choose an axis color + Scegli il colore per l'asse + + + + Choose a filename to save under + Scegli il nome di salvataggio + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + Ci sono delle curve in questo grafico e lo stile di line selezionato può essere applicato solo a grafici ordinati per X. Riordina la tabella o seleziona per X per rimuovere le curve o seleziona uno degli stili supportati dalle curve: Nessuno o Linea. + + + + Loading all remaining data for this table took %1ms. + Caricare tutti i dati restanti per questa tabella ha richiesto %1ms. + + + + PreferencesDialog + + + Preferences + Preferenze + + + + &General + &Generale + + + + Default &location + &Posizione di default + + + + Remember last location + Ricorda l'ultima posizione + + + + Always use this location + Usa sempre questa posizione + + + + Remember last location for session only + Ricorda l'ultima posizione solo per questa sessione + + + + + + ... + + + + + Lan&guage + Lin&gua + + + + Toolbar style + Stile barra degli strumenti + + + + + + + + Only display the icon + Mostra solo le icone + + + + + + + + Only display the text + Mostra solo il testo + + + + + + + + The text appears beside the icon + Mostra il testo a lato delle icone + + + + + + + + The text appears under the icon + Mostra il testo sotto le icone + + + + + + + + Follow the style + Segui lo stile + + + + Show remote options + Mostra opzioni remote + + + + + + + + + + + + + + enabled + abilitato + + + + Automatic &updates + Aggiornamenti a&utomatici + + + + DB file extensions + Estensioni file DB + + + + Manage + Gestisci + + + + Main Window + Finestra principale + + + + Database Structure + Struttura database + + + + Browse Data + Naviga nei dati + + + + Execute SQL + Esegui SQL + + + + Edit Database Cell + Modifica Cella Database + + + + When this value is changed, all the other color preferences are also set to matching colors. + Quando questo valore viene modificato, tutte le altre preferenze di colore vengono impostate al colore corrispondente. + + + + Follow the desktop style + Segui lo stile del desktop + + + + Dark style + Stile scuro + + + + Application style + Stile Applicazione + + + + This sets the font size for all UI elements which do not have their own font size option. + Imposta la dimensione del carattere per tutti gli elementi dell'interfaccia che non hanno una loro opzione dedicata. + + + + Font size + Dimensione testo + + + + Max Recent Files + Numero di files recenti + + + + Prompt to save SQL tabs +in new project file + Chiedi di salvare schede SQL +in un nuovo file di progetto + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + Se questo è abilitato, quando ci sono modifiche nell'editor SQL genera una finestra per salvarle in un file di progetto quando si chiude la scheda dell'editor SQL. + + + + &Database + + + + + Database &encoding + &Codifica Database + + + + Open databases with foreign keys enabled. + Apri database contenenti chiavi esterne. + + + + &Foreign keys + Chiavi &Esterne + + + + Remove line breaks in schema &view + Rimuovi a-capo nella &vista dello schema + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + Quando abilitato, vengono rimossi gli a-capo nella colonna dello Schema del tab "Struttura DB", dock e stampa. + + + + Prefetch block si&ze + &Dimensione blocco di prefetch + + + + SQ&L to execute after opening database + SQ&L da eseguire dopo aver aperto il database + + + + Default field type + Tipo di campo di default + + + + Database structure font size + Dimensione carattere struttura DB + + + + Data &Browser + + + + + Font + + + + + &Font + + + + + Font si&ze + Dimensione te&sto + + + + Content + Contenuto + + + + Symbol limit in cell + Limite simboli nella cella + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + Questo è il numero massimo di oggetti permessi per l'esecuzione di alcune funzioni computazionalmente intense: +Massimo numero di righe in una tabella per abilitare l'autocompletamento basato sui valori correnti di una colonna. +Massimo numero di indici in una selezione per calcolare somma e media. +Può essere impostato a 0 per disabilitare le funzionalità. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + Questo è il numero massimo di righe in una tabella per abilitare il completamento dei valori basandosi su quelli attualmente nella colonna. +Può essere impostato a 0 per disabilitare il completamento. + + + + Field display + Visualizzazione campi + + + + Displayed &text + &Testo visualizzato + + + + Binary + Binario + + + + NULL + + + + + Regular + Normale + + + + + + + + + + + Click to set this color + Clicca per impostare questo colore + + + + Text color + Colore del testo + + + + Background color + Colore dello sfondo + + + + + Preview only (N/A) + Solo anteprima (N/A) + + + + Filters + Filtri + + + + Escape character + Carattere di escape + + + + Delay time (&ms) + Ritardo (&ms) + + + + Light style + Stile chiaro + + + + Formatted + Formattato + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + Imposta il tempo d'attesa prima che un nuovo filtro venga applicato. Può essere impostato a 0 per disabilitare l'attesa. + + + + &SQL + &SQL + + + + Context + Contesto + + + + Colour + Colore + + + + Bold + Grassetto + + + + Italic + Corsivo + + + + Underline + Sottolinea + + + + Keyword + Parola chiave + + + + Function + Funzione + + + + Table + Tabella + + + + Comment + Commento + + + + Identifier + Identificatore + + + + String + Stringa + + + + Current line + Linea corrente + + + + Background + Sfondo + + + + Foreground + Primo piano + + + + Selection background + Sfondo selezione + + + + Selection foreground + Primo piano selezione + + + + Highlight + Evidenziato + + + + SQL editor &font + &Font editor SQL + + + + SQL &editor font size + Dimensione font &editor SQL + + + + SQL &results font size + Dimensione font &risultati SQL + + + + Tab size + Dimensione tabulazione + + + + Use tabs for indentation + Utilizza tabulatura per l'indentazione + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + Quando impostato, il tasto Tab inserisce un carattere tab per l'indentazione. Altrimenti verrannu utilizzati gli spazi. + + + + &Wrap lines + &A-capo automatico + + + + Never + Mai + + + + At word boundaries + Al limite della parola + + + + At character boundaries + Al limite del carattere + + + + At whitespace boundaries + Al limite del carattere vuoto + + + + &Quotes for identifiers + Identificatori per &citazioni + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + Scegli il tipo meccanismo di citazione utilizzato per il codice SQL. + + + + "Double quotes" - Standard SQL (recommended) + "Doppie virgolette" - Standard SQL (raccomandato) + + + + `Grave accents` - Traditional MySQL quotes + `Apice inverso` - Citazione tradizionale MySQL + + + + [Square brackets] - Traditional MS SQL Server quotes + [Parentesi quadre] - Citazione tradizionale MS SQL Server + + + + Code co&mpletion + Auto co&mpletamento + + + + Keywords in &UPPER CASE + Parole chiave &MAIUSCOLE + + + + When set, the SQL keywords are completed in UPPER CASE letters. + Quando impostato, le parole chiave vengono completate in MAIUSCOLO. + + + + Error indicators + Indicatori d'errore + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + Quando impostato, le righe di codice SQL che causano errori durante l'ultima esecuzione sono evidenziate e il campo del risultato indica l'errore sullo sfondo + + + + Hori&zontal tiling + Affianca &orizzontalmente + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + Se abilitato l'editor di codice SQL e la tabella del risultato sono mostrate una accanto all'altra anzichè una sopra l'altra. + + + + Close button on tabs + Pulsante di chiusura sulle schede + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + Se abilitato, le schede dell'editor SQL avranno un pulsante per la chiusura. In ogni caso, puoi utilizzare il menù contestuale o le scorciatoie da tastiera per chiuderle. + + + + &Extensions + &Estensioni + + + + Select extensions to load for every database: + Seleziona le estensioni da caricare per ogni database: + + + + Add extension + Aggiungi estensione + + + + Remove extension + Rimuovi estensione + + + + Select built-in extensions to load for every database: + Seleziona quali estensioni incluse caricare per ogni database: + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>Anche se SQLite supporta l'operatore REGEXP non implementa alcun algoritmo<br/>di espressione regolare, ma richiama l'applicativo in esecuzione. DB Browser for SQLite implementa questo<br/>algoritmo per te per permetterti di usare le REGEXP immediatamente. Ci sono però multiple implementazioni<br/>possibili e potresti voler utilizzare una o l'altra, sei libero di disabilitare l'implementazione<br/>dell'applicativo e caricare la tua utilizzando un'estensione. Richiede il riavvio dell'applicativo.</p></body></html> + + + + Disable Regular Expression extension + Disabilita l'estensione per l'Espressione regolare + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite fornisce una funzione SQL per il cariamento di estensioni da una libreria dinamica condivisa. Attiva questa opzione se vuoi utilizzare la funzione<span style=" font-style:italic;">load_extension()</span> dal codice SQL.</p><p>Per motivi di sicurezza, il caricamento delle estensioni è disabilitato di default e dev'essere abilitato tramite questa impostazione. Puoi sempre caricare le estensioni attraverso l'interfaccia grafica, anche se quest'opzione è disabilitata.</p></body></html> + + + + Allow loading extensions from SQL code + Permetti il caricamento di estensioni dal codice SQL + + + + Remote + Remoto + + + + CA certificates + Certificati CA + + + + Proxy + Proxy + + + + Configure + Configura + + + + Export Settings + Esporta Impostazioni + + + + Import Settings + Importa Impostazioni + + + + + Subject CN + Soggetto CN + + + + Common Name + Nome comune + + + + Subject O + Soggetto O + + + + Organization + Organizzazione + + + + + Valid from + Valido dal + + + + + Valid to + Valido al + + + + + Serial number + Numero di serie + + + + Your certificates + Tuo certificato + + + + Threshold for completion and calculation on selection + Soglia per l'autocompletamento e il calcolo sulla selezione + + + + Show images in cell + Mostra immagini nella cella + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + Abilita questa opzione per mostrare un'anteprima dei BLOBs contenti dati immagine nella cella. Questo potrebbe impattare sulle performance. + + + + File + File + + + + Subject Common Name + Nome comune del soggetto + + + + Issuer CN + CN emittente + + + + Issuer Common Name + Nome comune emittente + + + + Clone databases into + Clona il database in + + + + + Choose a directory + Seleziona una cartella + + + + + The language will change after you restart the application. + La lingua verrà modificata dopo il riavvio dell'applicativo. + + + + Select extension file + Seleziona il file d'estensione + + + + Extensions(*.so *.dylib *.dll);;All files(*) + Estensioni(*.so *.dylib *.dll);;Tutti i files(*) + + + + Import certificate file + Importa il file di certificato + + + + No certificates found in this file. + Nessun certificato trovato in questo file. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + Sei sicuro di voler rimuovere questo certificato? Tutti i dati del certificato saranno eliminati dalle impostazioni dell'applicativo! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + Sei sicuro di voler pulire tutte le impostazioni salvate? +Tutte le tue preferenze andranno perse e verranno utilizzati i valori predefiniti. + + + + Save Settings File + Salva file Impostazioni + + + + + Initialization File (*.ini) + File Inizializzazione (*.ini) + + + + The settings file has been saved in location : + + Il file delle impostazioni è stato salvato in : + + + + + Open Settings File + Apri file impostazioni + + + + The settings file was loaded properly. + Il file delle impostazioni è stato caricato correttamente. + + + + The selected settings file is not a normal settings file. +Please check again. + Il file delle impostazioni selezionato non è un file corretto. +Si prega di ricontrollare. + + + + ProxyDialog + + + Proxy Configuration + Configurazione proxy + + + + Pro&xy Type + Tipo Pro&xy + + + + Host Na&me + No&me host + + + + Port + Porta + + + + Authentication Re&quired + Autenticazione ri&chiesta + + + + &User Name + Nome &Utente + + + + Password + Password + + + + None + Nessuna + + + + System settings + Impostazioni di sistema + + + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 + + + + QObject + + + All files (*) + Tutti i files (*) + + + + Error importing data + Errore nell'import dei dati + + + + from record number %1 + dalla riga numero %1 + + + + . +%1 + . +%1 + + + + Importing CSV file... + Importa file CSV... + + + + Cancel + Annulla + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + File database SQLite (*.db *.sqlite *.sqlite3 *.db3) + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + File di progetto DB Browser for SQLite (*.sqbpro) + + + + SQL Files (*.sql) + SQL Files (*.sql) + + + + All Files (*) + Tutti i files (*) + + + + Text Files (*.txt) + File testuali (*.txt) + + + + Comma-Separated Values Files (*.csv) + File con valori separati da virgola (*.csv) + + + + Tab-Separated Values Files (*.tsv) + Files con valori separati da tabulazione (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + Files con valori separati da delimitatore (*.dsv) + + + + Concordance DAT files (*.dat) + File DAT Concordance (*.dat) + + + + JSON Files (*.json *.js) + JSON Files (*.json *.js) + + + + XML Files (*.xml) + XML Files (*.xml) + + + + Binary Files (*.bin *.dat) + Files binari (*.bin *.dat) + + + + SVG Files (*.svg) + SVG Files (*.svg) + + + + Hex Dump Files (*.dat *.bin) + Hex Dump Files (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + Estensioni (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + File inizializzazione (*.ini) + + + + Left + Sinistra + + + + Right + Destra + + + + Center + Centrato + + + + Justify + Giustificato + + + + QsciCommand + + Move down one line + Sposta in basso di una riga + + + Extend selection down one line + Estendi la selezione in basso di una riga + + + Extend rectangular selection down one line + Estendi la selezione rettangolare in basso di una riga + + + Scroll view down one line + Scorri la vista in basso di una riga + + + Move up one line + Muovi in alto di una riga + + + Extend selection up one line + Estendi la selezione in alto di una riga + + + Extend rectangular selection up one line + Estendi la selezione rettangolare in alto di una riga + + + Scroll view up one line + Scorri la vista in alto di una riga + + + Scroll to start of document + Scorri all'inizio del documento + + + Scroll to end of document + Scorri alla fine del documento + + + Scroll vertically to centre current line + Scorri verticalmente per centrare la riga corrente + + + Move down one paragraph + Muovi in basso di un paragrafo + + + Extend selection down one paragraph + Estendi la selezione in basso di un paragrafo + + + Move up one paragraph + Muovi in alto di un paragrafo + + + Extend selection up one paragraph + Estendi la selezione in alto di un paragrafo + + + Move left one character + Muovi a sinistra di un carattere + + + Extend selection left one character + Estendi la selezione a sinistra di un carattere + + + Extend rectangular selection left one character + Estendi la selezione rettangolare a sinistra di un carattere + + + Move right one character + Muovi a destra di un carattere + + + Extend selection right one character + Estendi la selezione a destra di un carattere + + + Extend rectangular selection right one character + Estendi la selezione rettangolare a destra di un carattere + + + Move left one word + Muovi a sinistra di una parola + + + Extend selection left one word + Estendi la selezione a sinistra di una parola + + + Move right one word + Muovi a destra di una parola + + + Extend selection right one word + Estendi la selezione a destra di una parola + + + Move to end of previous word + Muovi alla fine della parola precedente + + + Extend selection to end of previous word + Estendi la selezione alla fine della parola precedente + + + Move to end of next word + Muovi alla fine della prossima parola + + + Extend selection to end of next word + Estendi la selezione alla fine della prossima parola + + + Move left one word part + Muovi a sinistra di una parte di parola + + + Extend selection left one word part + Estendi la selezione a sinistra di una parte di parola + + + Move right one word part + Muovi a destra di una parte di parola + + + Extend selection right one word part + Estendi la selezione a destra di una parte di parola + + + Move to start of document line + Muovi all'inizio della riga + + + Extend selection to start of document line + Estendi la selezione all'inizio della riga + + + Extend rectangular selection to start of document line + Estendi la selezione rettangolare all'inizio della riga + + + Move to start of display line + Muovi all'inizio della riga mostrata + + + Extend selection to start of display line + Estendi la selezione all'inizio della riga mostrata + + + Move to start of display or document line + Muovi all'inizio della riga mostrata o del documento + + + Extend selection to start of display or document line + Estendi la selezione all'inizio della riga mostrata o del documento + + + Move to first visible character in document line + Muovi al primo carattere visibile nella riga + + + Extend selection to first visible character in document line + Estendi la selezione al primo carattere visibile della riga + + + Extend rectangular selection to first visible character in document line + Estendi la selezione rettangolare al primo carattere visibile nella riga + + + Move to first visible character of display in document line + Muovi al primo carattere visibile nella riga mostrata + + + Extend selection to first visible character in display or document line + Estendi la selezione al primo carattere visibile nella riga mostrata + + + Move to end of document line + Muovi alla fine della riga + + + Extend selection to end of document line + Estendi la selezione alla fine della riga + + + Extend rectangular selection to end of document line + Estendi la selezione rettangolare alla fine della riga + + + Move to end of display line + Muovi alla fine della riga mostrata + + + Extend selection to end of display line + Estendi la selezione alla fine della riga mostrata + + + Move to end of display or document line + Muovi alla fine della riga mostrata o del documento + + + Extend selection to end of display or document line + Estendi la selezione alla fine della riga mostrata o del documento + + + Move to start of document + Muovi all'inizio del documento + + + Extend selection to start of document + Estendi la selezione all'inizio del documento + + + Move to end of document + Muovi alla fine del documento + + + Extend selection to end of document + Estendi la selezione alla fine del documento + + + Move up one page + Muovi su di una pagina + + + Extend selection up one page + Estendi la selezione in su di una pagina + + + Extend rectangular selection up one page + Estendi la selezione rettangolare in su di una pagina + + + Move down one page + Muovi in basso di una pagina + + + Extend selection down one page + Estendi la selezione in basso di una pagina + + + Extend rectangular selection down one page + Estendi la selezione rettangolare in basso di una pagina + + + Stuttered move up one page + Muovi in alto a scatti di una pagina + + + Stuttered extend selection up one page + Estendi la selezione in alto a scatti di una pagina + + + Stuttered move down one page + Muovi in basso a scatti di una pagina + + + Stuttered extend selection down one page + Estendi la selezione in basso a scatti di una pagina + + + Delete current character + Elimina il carattere corrente + + + Delete previous character + Elimina il carattere precedente + + + Delete previous character if not at start of line + Elimina il carattere precedente se non corrisponde all'inizio di riga + + + Delete word to left + Elimina la parola a sinistra + + + Delete word to right + Elimina la parola a destra + + + Delete right to end of next word + Elimina da destra alla fine della prossima parola + + + Delete line to left + Elimina la riga a sinsitra + + + Delete line to right + Elimina la riga a destra + + + Delete current line + Elimina la riga corrente + + + Cut current line + Taglia la riga corrente + + + Copy current line + Copia la riga corrente + + + Transpose current and previous lines + Trasponi la riga corrente e quella precedente + + + Duplicate the current line + Duplica la riga corrente + + + Select all + Seleziona tutto + + + Move selected lines up one line + Muovi le righe selezionate in alto di una riga + + + Move selected lines down one line + Muovi le righe selezionate in basso di una riga + + + Duplicate selection + Duplica la selezione + + + Convert selection to lower case + Converti la selezione in minuscolo + + + Convert selection to upper case + Converti la selezione in maiuscolo + + + Cut selection + Taglia la selezione + + + Copy selection + Copia la selezione + + + Paste + Incolla + + + Toggle insert/overtype + Alterna inserisci/sovrascrivi + + + Insert newline + Inserisci una nuova riga + + + Formfeed + Separatore di pagina + + + Indent one level + Indenta di un livello + + + De-indent one level + Rimuovi l'indentazione di un livello + + + Cancel + Annulla + + + Undo last command + Annulla l'ultimo comando + + + Redo last command + Ripristina l'ultimo comando + + + Zoom in + Ingrandisci + + + Zoom out + Rimpicciolisci + + + + QsciLexerCPP + + Default + Default + + + Inactive default + Default inattivo + + + C comment + Commento C + + + Inactive C comment + Commento C inattivo + + + C++ comment + Commento C++ + + + Inactive C++ comment + Commento C++ inattivo + + + JavaDoc style C comment + Commento JavaDoc in stile C + + + Inactive JavaDoc style C comment + Commento JavaDoc in stile C inattivo + + + Number + Numero + + + Inactive number + Numero inattivo + + + Keyword + Parola chiave + + + Inactive keyword + Parola chiave inattiva + + + Double-quoted string + Stringa tra virgolette + + + Inactive double-quoted string + Stringa tra virgolette inattiva + + + Single-quoted string + Stringa tra singoli apici + + + Inactive single-quoted string + Stringa tra singoli apici inattiva + + + IDL UUID + IDL UUID + + + Inactive IDL UUID + IDL UUID inattivo + + + Pre-processor block + Blocco di pre-processore + + + Inactive pre-processor block + Blocco di pre-processore inattivo + + + Operator + Operatore + + + Inactive operator + Operatore inattivo + + + Identifier + Identificatore + + + Inactive identifier + Identificatore inattivo + + + Unclosed string + Stringa non terminata + + + Inactive unclosed string + Stringa non terminata inattiva + + + C# verbatim string + Stringa verbatim in C# + + + Inactive C# verbatim string + Stringa verbatim in C# inattiva + + + JavaScript regular expression + Espressione regolare JavaScript + + + Inactive JavaScript regular expression + Espressione regolare JavaScript inattiva + + + JavaDoc style C++ comment + Commmento JavaDoc in stile C++ + + + Inactive JavaDoc style C++ comment + Commento JavaDoc in stile C++ inattivo + + + Secondary keywords and identifiers + Parole chiave e identificatori secondari + + + Inactive secondary keywords and identifiers + Parole chiave e identificatori secondari inattivi + + + JavaDoc keyword + Parola chiave JavaDoc + + + Inactive JavaDoc keyword + Parola chiave JavaDoc inattiva + + + JavaDoc keyword error + Parola chiave JavaDoc errata + + + Inactive JavaDoc keyword error + Parola chiava JavaDoc errata inattiva + + + Global classes and typedefs + Classi globali e typedefs + + + Inactive global classes and typedefs + Classi globali e typedefs inattive + + + C++ raw string + Stringa grezza C++ + + + Inactive C++ raw string + Stringa grezza C++ inattiva + + + Vala triple-quoted verbatim string + Stringa Vala tri-apicata verbatim + + + Inactive Vala triple-quoted verbatim string + Stringa Vala tri-apicata verbatim inattiva + + + Pike hash-quoted string + Stringa Pike tra hash + + + Inactive Pike hash-quoted string + Stringa Pike tra hash inattiva + + + Pre-processor C comment + Commento di pre-processore C + + + Inactive pre-processor C comment + Commento di pre-processore C inattivo + + + JavaDoc style pre-processor comment + Commento di pre-processore in stile JavaDoc + + + Inactive JavaDoc style pre-processor comment + Commento di pre-processore in stile JavaDoc inattivo + + + User-defined literal + Letterale definito dall'utente + + + Inactive user-defined literal + Letterale definito dall'utente inattivo + + + Task marker + Segno di Task + + + Inactive task marker + Segno di Task inattivo + + + Escape sequence + Sequenza di escape + + + Inactive escape sequence + Sequenza di escape inattiva + + + + QsciLexerHTML + + HTML default + Default HTML + + + Tag + Tag + + + Unknown tag + Tag sconosciuto + + + Attribute + Attributo + + + Unknown attribute + Attributo sconosciuto + + + HTML number + Numero HTML + + + HTML double-quoted string + Stringa tra virgolette in HTML + + + HTML single-quoted string + Stringa tra apici in HTML + + + Other text in a tag + Altro test in un tag + + + HTML comment + Commento HTML + + + Entity + Entità + + + End of a tag + Fine di un tag + + + Start of an XML fragment + Inizio di un frammento XML + + + End of an XML fragment + Fine di un frammento XML + + + Script tag + Tag di script + + + Start of an ASP fragment with @ + Inizio di un frammento ASP con @ + + + Start of an ASP fragment + Inizio di un frammento ASP + + + CDATA + CDATA + + + Start of a PHP fragment + Inizio di un frammento PHP + + + Unquoted HTML value + Valore HTML senza apici + + + ASP X-Code comment + Commento di codice ASP X + + + SGML default + Default SGML + + + SGML command + Comando SGML + + + First parameter of an SGML command + Primo parametro di un comando SGML + + + SGML double-quoted string + Stringa tra virgolette SGML + + + SGML single-quoted string + Stringa tra apici SGML + + + SGML error + Errore SGML + + + SGML special entity + Entità speciale SGML + + + SGML comment + Commento SGML + + + First parameter comment of an SGML command + Primo parametro di un comando SGML + + + SGML block default + Blocco di default SGML + + + Start of a JavaScript fragment + Inizio di un frammento JavaScript + + + JavaScript default + Default JavaScript + + + JavaScript comment + Commento JavaScript + + + JavaScript line comment + Commento di riga JavaScript + + + JavaDoc style JavaScript comment + Commento JavaScript in stile JavaDoc + + + JavaScript number + Numero JavaScript + + + JavaScript word + Parola JavaScript + + + JavaScript keyword + Parola chiave JavaScript + + + JavaScript double-quoted string + Stringa tra virgolette JavaScript + + + JavaScript single-quoted string + Stringa tra apici JavaScript + + + JavaScript symbol + Simbolo JavaScript + + + JavaScript unclosed string + Stringa non delimitata JavaScript + + + JavaScript regular expression + Espressione regolare JavaScript + + + Start of an ASP JavaScript fragment + Inizio di un frammento ASP in JavaScript + + + ASP JavaScript default + Default ASP JavaScript + + + ASP JavaScript comment + Commento ASP JavaScript + + + ASP JavaScript line comment + Line di commento ASP JavaScript + + + JavaDoc style ASP JavaScript comment + Commento ASP JavaScript in stile JavaDoc + + + ASP JavaScript number + Numero ASP JavaScript + + + ASP JavaScript word + Parola ASP JavaScript + + + ASP JavaScript keyword + Parola chiave ASP JavaScript + + + ASP JavaScript double-quoted string + Stringa ASP JavaScript tra virgolette + + + ASP JavaScript single-quoted string + Stringa ASP JavaScript tra apici + + + ASP JavaScript symbol + Simbolo ASP JavaScript + + + ASP JavaScript unclosed string + Stringa non delimitata ASP JavaScript + + + ASP JavaScript regular expression + Espressione regolare ASP JavaScript + + + Start of a VBScript fragment + Inizio di un frammento VBScript + + + VBScript default + Default VBScript + + + VBScript comment + Commento VBScript + + + VBScript number + Numero VBScript + + + VBScript keyword + Parola chiave VBScript + + + VBScript string + Stringa VBScript + + + VBScript identifier + Identificatore VBScript + + + VBScript unclosed string + Stringa non delimitata VBScript + + + Start of an ASP VBScript fragment + Inizio di un frammento ASP VBScript + + + ASP VBScript default + Default ASP VBScript + + + ASP VBScript comment + Commento ASP VBScript + + + ASP VBScript number + Numero ASP VBScript + + + ASP VBScript keyword + Parola chiave ASP VBScript + + + ASP VBScript string + Stringa ASP VBScript + + + ASP VBScript identifier + Identificatore ASP VBScript + + + ASP VBScript unclosed string + Stringa non delimitata ASP VBScript + + + Start of a Python fragment + Inizio di un frammento Python + + + Python default + Default Python + + + Python comment + Commento Python + + + Python number + Numero Python + + + Python double-quoted string + Stringa tra virgolette Python + + + Python single-quoted string + Stringa tra apici Python + + + Python keyword + Parola chiave Python + + + Python triple double-quoted string + Stringa tra tripilci virgolette Python + + + Python triple single-quoted string + Stringa tra triplici apici Python + + + Python class name + Nome di classe Python + + + Python function or method name + Funzione o nome di metodo Python + + + Python operator + Operatore Python + + + Python identifier + Identificatore Python + + + Start of an ASP Python fragment + Inizio di un frammento ASP Python + + + ASP Python default + Default ASP Python + + + ASP Python comment + Commento ASP Python + + + ASP Python number + Numero ASP Python + + + ASP Python double-quoted string + Stringa tra virgolette ASP Python + + + ASP Python single-quoted string + Stringa tra apici ASP Python + + + ASP Python keyword + Parola chiave ASP Python + + + ASP Python triple double-quoted string + Stringa tra triplici virgolette ASP Python + + + ASP Python triple single-quoted string + Stringa tra triplici apici ASP Python + + + ASP Python class name + Nome di classe ASP Python + + + ASP Python function or method name + Nome di funzione o metodo ASP Python + + + ASP Python operator + Operatore ASP Python + + + ASP Python identifier + Identificatore ASP Python + + + PHP default + Default PHP + + + PHP double-quoted string + Stringa tra virgolette PHP + + + PHP single-quoted string + Stringa tra apici PHP + + + PHP keyword + Parola chiave PHP + + + PHP number + Numero PHP + + + PHP variable + Variabile PHP + + + PHP comment + Commento PHP + + + PHP line comment + Commento di linea PHP + + + PHP double-quoted variable + Variabile tra virgolette PHP + + + PHP operator + Operatore PHP + + + + QsciLexerJSON + + Default + Default + + + Number + Numero + + + String + Stringa + + + Unclosed string + Stringa non delimitata + + + Property + Proprietà + + + Escape sequence + Sequenza di escape + + + Line comment + Commento di linea + + + Block comment + Commento in blocco + + + Operator + Operatore + + + IRI + IRI + + + JSON-LD compact IRI + JSON-LD IRI compatto + + + JSON keyword + Parola chiave JSON + + + JSON-LD keyword + Parola chiave JSON-LD + + + Parsing error + Errore di analisi + + + + QsciLexerJavaScript + + Regular expression + Espressione regolare + + + + QsciLexerPython + + Default + Default + + + Comment + Commento + + + Number + Numero + + + Double-quoted string + Stringa tra virgolette + + + Single-quoted string + Stringa tra apici + + + Keyword + Parola chiave + + + Triple single-quoted string + Stringa tra triplici apici + + + Triple double-quoted string + Stringa tra triplici virgolette + + + Class name + Nome di classe + + + Function or method name + Nome di funzione o metodo + + + Operator + Operatore + + + Identifier + Identificatore + + + Comment block + Commento in blocco + + + Unclosed string + Stringa non delimitata + + + Highlighted identifier + Identificatore evidenziato + + + Decorator + Decoratore + + + Double-quoted f-string + Stringa-f tra virgolette + + + Single-quoted f-string + Stringa-f tra singoli apici + + + Triple single-quoted f-string + Stringa-f tra triplici apici + + + Triple double-quoted f-string + Stringa-f tra triplici virgolette + + + + QsciLexerSQL + + Default + Default + + + Comment + Commento + + + Comment line + Commento di linea + + + JavaDoc style comment + Commento in stile JavaDoc + + + Number + Numero + + + Keyword + Parola chiave + + + Double-quoted string + Stringa tra virgolette + + + Single-quoted string + Stringa tra apici + + + SQL*Plus keyword + Parola chiave SQL*Plus + + + SQL*Plus prompt + Richiesta SQL*Plus + + + Operator + Operatore + + + Identifier + Identificatore + + + SQL*Plus comment + Commento SQL*Plus + + + # comment line + # commento di linea + + + JavaDoc keyword + Parola chiave JavaDoc + + + JavaDoc keyword error + Errore parola chiave JavaDoc + + + User defined 1 + Definito dall'utente 1 + + + User defined 2 + Definito dall'utente 2 + + + User defined 3 + Definito dall'utente 3 + + + User defined 4 + Definito dall'utente 4 + + + Quoted identifier + Identificatore di citazione + + + Quoted operator + Operatore di citazione + + + + QsciScintilla + + &Undo + A&nnulla + + + &Redo + &Ripristina + + + Cu&t + &Taglia + + + &Copy + &Copia + + + &Paste + &Incolla + + + Delete + Elimina + + + Select All + Seleziona tutto + + + + RemoteCommitsModel + + + Commit ID + ID Commit + + + + Message + Messaggio + + + + Date + Data + + + + Author + Autore + + + + Size + Dimensione + + + + Authored and committed by %1 + Creato e inviato da %1 + + + + Authored by %1, committed by %2 + Creato da %1, inviato da %2 + + + + RemoteDatabase + + + Error opening local databases list. +%1 + Errore nell'apertura della lista di database locale. +%1 + + + + Error creating local databases list. +%1 + Errore nella creazione della lista di database locale. +%1 + + + + RemoteDock + + + Remote + Remoto + + + + Identity + Identità + + + + Push currently opened database to server + Invia il database corrente al server + + + + Upload + Carica + + + + DBHub.io + DBHub.io + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>In questo pannello, si possono aggiungere database dal sito web dbhub.io a DB Browser for SQLite. Prima hai bisogno di un'identità:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Collegati al sito web dbhub.io (usa le tue credenziali GitHub o quello che preferisci)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Clicca il pulsante per &quot;Generare certificato client&quot; (è la tua identità). Che ti fornirà un file di certificato (salvalo sul tuo disco locale).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Vai alla scheda "Remoto" nelle preferenze di DB Browser for SQLite. Clicca il pulsante per aggiungere un nuovo certificato a DB Browser for SQLite e seleziona il file di certificato appena scaricato.</li></ol><p>Ora il pannello "Remoto" mostra la tua identità e tu puoi aggiungere database remoti.</p></body></html> + + + + Local + Locale + + + + Current Database + Database Corrente + + + + Clone + Clona + + + + Branch + Ramo + + + + Commits + Commits + + + + Commits for + Commits per + + + + Delete Database + Elimina Database + + + + Delete the local clone of this database + Elimina la copia locale di questo database + + + + Open in Web Browser + Apri nel Browser Web + + + + Open the web page for the current database in your browser + Apre una pagina web per il database corrente nel tuo browser + + + + Clone from Link + Clona da Collegamento + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + Usa questo per scaricare un database remoto per modificarlo localmente utilizzando una URL fornita dalla pagina web del database. + + + + Refresh + Aggiorna + + + + Reload all data and update the views + Ricarica tutti i dati e aggiornal le viste + + + + Clone Database + Clona Database + + + + Open Database + Apri Database + + + + Open the local copy of this database + Apre una copia locale di questo database + + + + Check out Commit + Passare a Commit + + + + Download and open this specific commit + Scarica ed apre questo commit specifico + + + + Check out Latest Commit + Passare all'ultimo Commit + + + + Check out the latest commit of the current branch + Passa all'ultimo comit del ramo corrente + + + + Save Revision to File + Salva revisione su File + + + + Saves the selected revision of the database to another file + Salva la revisione selezionata del database in un altro file + + + + Upload Database + Carica Database + + + Paste + Incolla + + + Cancel + Annulla + + + + Upload this database as a new commit + Carica questo database come un nuovo commit + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>Stai attulamente utilizzando un profilo interno in sola lettura. Per caricare i tuoi database, devi configurare e usare un account DBHub.io.</p><p>Non hai ancora un account DBHub.io? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Creane uno adesso</span></a> e importa il tuo certificato <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">qui</span></a> per condividere i tuoi databases.</p><p>Per aiuto online clicca <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">qui</span></a>.</p></body></html> + + + + &User + &Utente + + + + &Database + &Database + + + + Back + Indietro + + + + Select an identity to connect + Seleziona una identità da connettere + + + + Public + Pubblico + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + Questo scarica un database da un server remoto per modifiche locali. +Si prega d'inserire l'URL da cui effettuare il clone. Puoi generare l'URL +cliccando il pulsante 'Clona Database in DB4S' sulla pagina web del database. + + + + Invalid URL: The host name does not match the host name of the current identity. + URL Invalida: Il nome host non corrisponde a quello dell'identità corrente. + + + + Invalid URL: No branch name specified. + URL Invalida: Nessun ramo specificato. + + + + Invalid URL: No commit ID specified. + URL Invalida: Nessun commit ID specificato. + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + Hai modificato la copia locale del database. Caricare questo commit sovrascriverà le modifiche locali. +Sei sicuro di voler procedere? + + + + The database has unsaved changes. Are you sure you want to push it before saving? + Il database ha modifiche non salvate. Sei sicuro di volerlo inviare prima di salvare? + + + + The database you are trying to delete is currently opened. Please close it before deleting. + Il database che stai provando ad eliminare è attualmente aperto. Si prega di chiuderlo prima di eliminarlo. + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + Questo elimina la versione locale di questo database con tutte le modifiche che non hai ancora committato. Sei sicuro di voler eliminare questo database? + + + + RemoteLocalFilesModel + + + Name + Nome + + + + Branch + Ramo + + + + Last modified + Ultima modifica + + + + Size + Dimensione + + + + Commit + Commit + + + + File + File + + + + RemoteModel + + + Name + Nome + + + + Commit + Commit + + + + Last modified + Ultima modifica + + + + Size + Dimensione + + + + Size: + Dimensione: + + + + Last Modified: + Ultima Modifica: + + + + Licence: + Licenza: + + + + Default Branch: + Ramo di Default: + + + + RemoteNetwork + + + Choose a location to save the file + Sceli dove salvare il file + + + + Error opening remote file at %1. +%2 + Errore aprendo il file remoto a %1. +%2 + + + + Error: Invalid client certificate specified. + Errore: specificato certificato invalido per il client. + + + + Please enter the passphrase for this client certificate in order to authenticate. + Si prega d'inserire la passphrase per questo certificato di client in modo da permetterne l'autenticazione. + + + + Cancel + Annulla + + + + Uploading remote database to +%1 + Carico il database remoto in +%1 + + + + Downloading remote database from +%1 + Scarico il database remoto da +%1 + + + + Error: Cannot open the file for sending. + Errore: Impossibile aprire il file per l'invio. + + + + RemotePushDialog + + + Push database + Invia database + + + + Database na&me to push to + No&me del database a cui inviare + + + + Commit message + Messaggio di commit + + + + Database licence + Licenza database + + + + Public + Pubblico + + + + Branch + Branch + + + + Force push + Forza invio + + + + Username + Nome utente + + + + Database will be public. Everyone has read access to it. + Il database sarà pubblico. Chiunque potrà accedere in lettura. + + + + Database will be private. Only you have access to it. + Il database sarà privato. Solo tu potrai accedervi. + + + + Use with care. This can cause remote commits to be deleted. + Usa con cautela. Questo può eliminare dei commit remoti. + + + + RunSql + + + Execution aborted by user + Esecuzione terminata dall'utente + + + + , %1 rows affected + , %1 righe modificate + + + + query executed successfully. Took %1ms%2 + query eseguita con successo. Impiegati %1ms%2 + + + + executing query + query in esecuzione + + + + SelectItemsPopup + + + A&vailable + &Disponibile + + + + Sele&cted + Se&lezionato + + + + SqlExecutionArea + + + Form + + + + + Find previous match [Shift+F3] + Trova corrispondenza precedente [Shift+F3] + + + + Find previous match with wrapping + Trova la corrispondenza precedente con reinizio + + + + Shift+F3 + + + + + The found pattern must be a whole word + Il pattern trovato deve essere una parola intera + + + + Whole Words + Parole intere + + + + Text pattern to find considering the checks in this frame + Il pattern da cercare considerando le spunte in quest'area + + + + Find in editor + Trova nell'editor + + + + The found pattern must match in letter case + Il patter trovato deve corrispondere esattamente (maiuscole/minuscole) incluse + + + + Case Sensitive + Case Sensitive + + + + Find next match [Enter, F3] + Trova la prossima corrispondenza [Invio, F3] + + + + Find next match with wrapping + Trova la prossima corrispondenza con reinizio + + + + F3 + + + + + Interpret search pattern as a regular expression + Interpreta il pattern di ricerca come un'espressione regolare + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Quando selezionato, la stringa del testo viene interpretata come una RegExp Unix. Vedi <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Espressioni regolari su Wikibooks (in inglese)</a>.</p></body></html> + + + + Regular Expression + Espressione regolare + + + + + Close Find Bar + Chiudi la barra di ricerca + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>Risultati degli ultimi statements eseguiti.</p><p>Potresti voler rimpicciolire questo pannello e usare la casella <span style=" font-style:italic;">SQL Log</span> con la selezione dell'<span style=" font-style:italic;">Utente</span>.</p></body></html> + + + + Results of the last executed statements + Risultato degli 'ultimi statement eseguiti + + + + This field shows the results and status codes of the last executed statements. + Questo campo mostra i risultati e i codici di stato degli ultimi statements eseguiti. + + + + Ctrl+PgUp + Ctrl+PgUp + + + + Ctrl+PgDown + Ctrl+PgDown + + + + Couldn't read file "%1": %2. + Impossibile leggere file "%1": %2. + + + + + Couldn't save file: %1. + Impossibile salvare il file: %1. + + + + Your changes will be lost when reloading it! + Le tue modifiche andranno perse quando ricaricherai! + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + Il file "%1" è stato modificato da un altro programma. Vuoi ricaricarlo?%2 + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + Rispondere "Si a Tutto" per ricaricare il file ad ogni aggiornamento esterno senza nuove richieste di conferma. + + + + Answer "No to All" to ignore any external update without further prompting. + Rispondere "No a Tutto" per ignorare ogni aggiornamento esterno senza chiedere nuovamente. + + + + Modifying and saving the file will restore prompting. + Modificare e salvare il file ripristinerà le richieste. + + + + SqlTextEdit + + + Ctrl+/ + + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) La funzione abs(X) ritorna il valore assoluto dell'argomento numerico X. + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () La funzione changes() ritorna il numero delle righe di database che sono state modificate o inserite o eliminate dallo statement INSERT, DELETE o UPDATE più recente. + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1, X2,...) La funzione char(X1,X2,...,XN) ritorna una stringa composta dai caratteri unicode rappresentati dai valori interi da X1 a XN. + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) La funzione coalesce(X,Y,...) ritorna una copia del suo primo argomento non NULL oppure NULL se tutti gli argomenti sono NULL + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) La funzione glob(X,Y) è equivalente all'espressione "Y GLOB X". + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) La funzione ifnull(X,Y) ritorno una copia del suo primo argomento non NULL o NULL se entrambi gli argomenti sono NULL. + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) La funzione intstr(X,Y) trova la prima occorrenza della stringa Y all'interno della stringa X e ritorna il numero dei caratteri precedenti più 1 o 0 se Y non si trova all'interno di X. + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) La funzione hex() interpreta i suoi argomenti come un BLOB e ritorna una stringa corrispondente al rendering esadecimale maiuscolo del contenuto di quel blob. + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) La funzione iif(X,Y,Z) restituisce il valore di Y se X è vera e Z altrimenti. + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () La funzione last_insert_rowid() ritorna il ROWID dell'ultima riga inserita nella connessione database che ha invocato la funzione. + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) La funzione lenght(X) ritorna per una stringa X, il numero di caratteri (non bytes) di X prima del primo carattere NUL. + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) La funzione like(X,Y) è utilizzata per implementare l'espressione "Y LIKE X". + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) La funzione like(X,Y,Z) è utilizzata per implementare l'espressione "Y LIKE X ESCAPE Z". + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) La funzione load_extension(X) carica l'estensione SQLite da un file di libreria condivisa di nome X. +L'utilizzo di questa funzione dev'essere permesso tramite le Preferenze. + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) La funzione load_extension(X,Y) carica un'estensione SQLite da un file di libreria condivisa di nome X utilizzando il punto d'ingresso Y. +L'utilizzo di questa funzione dev'essere permesso tramite le Preferenze. + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) La funzione lower(X) ritorna una copia della stringa X con tutti i caratteri ASCII convertiti in minuscolo. + + + + (X) ltrim(X) removes spaces from the left side of X. + (X) La funzione ltrim(X) rimuove gli spazi dal lato sinistro di X. + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) La funzione ltrim(X,Y) ritorna una stringa formata rimuovendo tutti i caratteri che compaiono in Y dal lato sinistro di X. + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) La funzione multi-argomento max(X,Y,...) ritorna l'argomento con valore massimo o ritorna NULL se tutti gli argomenti sono NULL. + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) La funzione multi-argomento min(X,Y,...) ritorna l'argomento con valore minore o NULL se tutti gli argomenti sono NULL. + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) La funzione nullif(X,Y) ritorna il primo argomento se gli argomenti sono diversi e NULL se gli argomenti sono uguali. + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) La funzione SQL printf(FORMAT,...) si comporta come la funzione del linguaggio C sqlite3_mprintf() e la funzione printf() della libreria standard C. + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) La funzione quote(X) ritorna il testo di un literale SQL il cui valore può essere incluso in uno statement SQL. + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () La funzione random() ritorna un numero intero pseudo-casuale tra -9223372036854775808 e +9223372036854775807. + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) La funzione randomblob(N) ritorna un blob di N-bytes contenenti dati pseudo-casuali. + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) La funzione replace(X,Y,Z) ritorna una striga formata sostituendo la stringa Z in ogni occorrenza della stringa Y nella stringa X. + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) La funzione round(X) ritorna un valore in virgola mobile X arrotondato a 0 cifre decimali. + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) La funzione round(X,Y) ritorna un numero in virgola mobile X arrotondato a Y cifre decimali. + + + + (X) rtrim(X) removes spaces from the right side of X. + (X) La funzione rtrim(X) rimuove gli spazi dalla destra di X. + + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) La funzione rtrim(X,Y) ritorna una stringa formata rimuovendo tutti i caratteri che compaiono in Y dal lato destro di X. + + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) La funzione soundex(X) ritorna una stringa che rappresenta la codifica soundex della stringa X. + + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) La funzione substr(X,Y) ritorna tutti i caratteri dalla fine della stringa X iniziando dall'Y-esimo. + + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) La funzione substr(X,Y,Z) ritorna una sotto-stringa di X che inizia dal carattere Y-esimo e lunga Z caratteri. + + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () La funzione total_changes() ritorna il numero di righe modificate da INSERT, UPDATE o DELETE dall'apertura della connessione al database. + + + + (X) trim(X) removes spaces from both ends of X. + (X) La funzione trim(X) rimuove gli spazi da entrambi i lati di X. + + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) La funzione trim(X,Y) ritorna una stringa formata rimuovendo tutti i caratteri che compaiono in Y da entrambi i termini di X. + + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) La funzione typeof(X) ritorna una stringa che indica il tipo di dato dell'espressione X. + + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) La funzione unicode(X) ritorna il valore numerico in unicode corrispondente al primo carattere della stringa X. + + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) La funzione upper(X) ritorna una copia della stringa X in cui tutti i caratteri minuscoli ASCII sono stati converiti in maiuscolo. + + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) La funizione zeroblob(N) ritorna un BLOB di N byte di 0x00. + + + + + + + (timestring,modifier,modifier,...) + (stringa data,modificatore,modificatore,...) + + + + (format,timestring,modifier,modifier,...) + (formato,stringa data-ora,modificatore,modificatore,...) + + + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) La funzione avg(X) ritorna il valore medio di tutti gli X non-NULL in un gruppo. + + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) La funzione count(X) ritorna il numero di volte che X non è NULL in un gruppo. + + + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) La funzione group_concat(X) ritorna una stringa rappresentante la concatenazione di tutti i valori di X non-NULL. + + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) La funzione group_concat(X,Y) ritorna una stringa rappresentate la concatenazione di tutti i valori di X non-NULL. Se il parametro Y è presente allora è utilizzato come separatore tra le istanze di X. + + + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) La funzione aggregata max(X) ritorna il valore massimo di tutti i valori nel gruppo. + + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) La funzione aggregata min(X) ritorna il minore non-NULL tra tutti i valori del gruppo. + + + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) Le funzioni aggregate sum(X) e total(X) ritornano la somma di tutti i valori non-NULL nel gruppo. + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () Il numero di righe all'interno della partizione corrente. Le righe sono numerate partendo da 1 nell'ordine definito dalla clausula ORDER BY nella finestra definizione, o altrimenti in ordine arbitrario. + + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () Il row_number() del primo peer in ogni gruppo - il rango della riga corrente con intervalli. Se non ci sono clausule ORDER BY, allora tutte le righe sono considerate peer e questa funzione ritorna 1. + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () Il numero di peer nel gruppo della riga corrente all'interno della sua partizione - il rango della riga corrente senza intervalli. Le partizioni sono numerate a partire da 1 nell'ordine definito dalla clausula ORDER BY nella finestra definizione. Se non ci sono clausule ORDER BY allora tutte le righe sono considerate peer e questa funzione ritorna 1. + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () A dispetto del nome, questa funzione ritorna sempre un valore tra 0.0 e 1.0 uguale a (rango - 1)/(righe della partizione - 1), dove rango è il valore ritornato dalla funzione interna rank() e le "righe della partizione" sono il numero di righe nella partizione. Se la partizione contiene solo una riga, questa funzione ritorna 0.0. + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () La distribuzione cumulativa. Calcolata come "numero di righe"/"righe della partizione", dove "numero di righe" è il valore ritornato dalla funzione row_number() per l'utimo peer nel gruppo. + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) L'argomento N è gestito come valore intero. Questa funzione divide la partizione in N gruppi il più uniformemente possibile e assegna un'intero tra 1 e N ad ogni gruppo, nell'ordine definito dalla clausula ORDER BY o altrimenti in ordine arbitrario. Se necessario i gruppi più grandi compariranno per primi. Questa funzione ritorna il valore intero assegnato al gruppo di cui fa parte la riga corrente. + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) Ritorna il risultato della valutazione dell'espressione expr sulla riga precedente della partizione o, se non esiste una riga precedente (perché la riga è la prima), NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr, offset) Se l'argomento offset viene fornito, allora dev'essere un intero non negativo. In questo caso il valore ritornato è il risultato della valutazione dell'espressione expr sulla riga "offset" posizioni antecedente nella partizione. Se offset è 0 allora expr viene valutata sulla riga corrente. Se non ci sono offset righe antecedenti viene ritornato NULL. + + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,offset,default) Se viene fornito anche default, allora viene ritornato al posto di NULL se la riga identificata da offset non esiste. + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) Ritorna il risultato della valutazione dell'espressione expr con la riga successiva nella partizione o, se non c'è una riga successiva (perché la riga corrente è l'utlima) NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,offset) Se viene fornito l'argomento offset, dev'essere un intero non negativo. In questo caso il valore ritornato è il risultato della valutazione dell'espressione expr sulla riga "offset" posizioni successiva a quella corrente nella partizione. Se offset è 0, allora expr viene valutata sulla riga corrente. Se non c'è una riga "offset" posizioni successive, NULL viene restituito. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) Questa funzione interna calcola la cornice della finestra di ciascuna riga allo stesso modo di una funzione finestra aggregata. Ritorna il valore della valutazione di expr sulla prima riga nella cornice della finestra per ciascuna riga. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) Questa funzione interna calcola la cornice della finestra per ciascuna riga allo stesso modo della funzione finestra aggregata. Ritorna il valore dell'espressione expr valutata sull'ultima riga della cornice della finestra per ciascuna riga. + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr,N) Questa funzione interna calcola la cornice della finestra per ciascuna riga allo stesso modo della funzione aggregata finestra. Ritorna il valore della valutazione dell'espressione expr sulla riga N della cornice della finestra. Le righe sono numerate dalla cornice della finestra partendo da 1 nell'ordine definito dalla clausula ORDER BY se presente o in modo arbitrario. Se non esiste la riga Nesima nella partizione, viene ritornato NULL. + + + + (X) Return the arccosine of X. The result is in radians. + (X) Restituisce l'arcoseno di X. Il risultato è in radianti. + + + + (X) Return the hyperbolic arccosine of X. + (X) Restituisce l'arcoseno iperbolico di X. + + + + (X) Return the arcsine of X. The result is in radians. + (X) Restituisce l'arcoseno di X. Il risultato è in radianti. + + + + (X) Return the hyperbolic arcsine of X. + (X) Restituisce l'arcoseno iperbolico di X. + + + + (X) Return the arctangent of X. The result is in radians. + (X) Restituisce l'arcotangente di X. Il risultato è in radianti. + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + (X,Y) Restituisce l'arcotangente di Y/X. Il risultato è in radianti. Il risultato è posizionato nel quadrante corretto a seconda dei segni di X e Y. + + + + (X) Return the hyperbolic arctangent of X. + (X) Restituisce l'arcotangente iperbolico di X. + + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + (X) Restituisce il primo valore intero rappresentabile maggiore o uguale ad X. Per valori positivi di X, questa funzione arrotonda per eccesso. Per valori negativi di X, arrotonda per difetto. + + + + (X) Return the cosine of X. X is in radians. + (X) Restituisce il coseno di X. X è in radianti. + + + + (X) Return the hyperbolic cosine of X. + (X) Restituisce il coseno iperbolico di X. + + + + (X) Convert value X from radians into degrees. + (X) Converte il valore di X da radianti in gradi. + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + (X) Calcola e (il numero di Eulero, approssimativamente 2.71828182845905) elevato alla potenza di X. + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + (X) Restituisce il primo valore intero rappresentabile minore o uguale ad X. Per numeri positivi, questa funzione arrotonda per difetto. Per numeri negativi arrotonda per eccesso. + + + + (X) Return the natural logarithm of X. + (X) Restituisce il logaritmo naturale di X. + + + + (B,X) Return the base-B logarithm of X. + (B,X) Restituisce il logaritmo in base B di X. + + + + + (X) Return the base-10 logarithm for X. + (X) Restituisce il logaritmo in base 10 di X. + + + + (X) Return the logarithm base-2 for the number X. + (X) Restituisce il logaritmo in base 2 di X. + + + + (X,Y) Return the remainder after dividing X by Y. + (X,Y) Restituise il resto della divisione di X per Y. + + + + () Return an approximation for Ï€. + () Restituisce un'approssimazione di Ï€. + + + + + (X,Y) Compute X raised to the power Y. + (X,Y) Calcola X alla potenza di Y. + + + + (X) Convert X from degrees into radians. + (X) Converte X da gradi in radianti. + + + + (X) Return the sine of X. X is in radians. + (X) Restituisce il seno di X. X è in radianti. + + + + (X) Return the hyperbolic sine of X. + (X) Restituisce il seno iperbolico di X. + + + + (X) Return the square root of X. NULL is returned if X is negative. + (X) Restituisce la radice quadrata di X. NULL viene restituito se X è negativo. + + + + (X) Return the tangent of X. X is in radians. + (X) Restituisce la tangente di X. X è in radianti. + + + + (X) Return the hyperbolic tangent of X. + (X) Restituisce la tangente iperbolica di X. + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + (X) Restituisce l'intero rappresentabile tra X e 0 (inclusivo) che dista maggiormente da zero. O, in altre parole, restituisce la parte intera di X arrotondando verso zero. + + + + SqliteTableModel + + + reading rows + leggo le righe + + + + loading... + caricamento... + + + + References %1(%2) +Hold %3Shift and click to jump there + Riferimenti %1(%2) +Tieni premuto %3Shift e clicca per saltare lì + + + + Error changing data: +%1 + Errore nella modifica dei dati: +%1 + + + + retrieving list of columns + recupero la lista delle colonne + + + + Fetching data... + Recupero dati... + + + + + Cancel + Annulla + + + + TableBrowser + + + Browse Data + Naviga nei dati + + + + &Table: + &Tabella: + + + + Select a table to browse data + Seleziona una tabella per navigare tra i dati + + + + Use this list to select a table to be displayed in the database view + Usa questa lista per selezionare una tabella da visualizzare nella vista del database + + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + Questa è la vista della tabella del database. Puoi eseguire le seguenti operazioni: + - Inizia a scrivere per modificare i valori. + - Doppio-click su qualsiasi valore per modificarne il contenuto nella finestra di editor della cella. + - Alt+Del per eliminare il contenuto della cella e portarlo a NULL. + - Ctrl+" per duplicare il valore corrente. + - Ctrl+' per copiare il valore dalla cella soprastante. + - Operazioni di selezione e copia/incolla. + + + + Text pattern to find considering the checks in this frame + Il pattern da cercare considerando le spunte in quest'area + + + + Find in table + Trova nella tabella + + + + Find previous match [Shift+F3] + Trova corrispondenza precedente [Shift+F3] + + + + Find previous match with wrapping + Trova la corrispondenza precedente con reinizio + + + + Shift+F3 + + + + + Find next match [Enter, F3] + Trova la prossima corrispondenza [Invio, F3] + + + + Find next match with wrapping + Trova la prossima corrispondenza con reinizio + + + + F3 + + + + + The found pattern must match in letter case + Il pattern trovato deve corrispondere esattamente (maiuscole/minuscole) incluse + + + + Case Sensitive + Case Sensitive + + + + The found pattern must be a whole word + Il pattern trovato deve essere una parola intera + + + + Whole Cell + Cella completa + + + + Interpret search pattern as a regular expression + Interpreta il pattern di ricerca come un'espressione regolare + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Quando selezionata, il pattern da trovare viene interpretato come un'espressione regolare UNIX. Vedi: <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + Regular Expression + Espressione regolare + + + + + Close Find Bar + Chiudi la barra di ricerca + + + + Text to replace with + Testo da usare per la sostituzione + + + + Replace with + Sostituisci con + + + + Replace next match + Sostituisci la prossima corrispondenza + + + + + Replace + Sostituisci + + + + Replace all matches + Sostituisci tutte le corrispondenze + + + + Replace all + Sostituisci tutto + + + + Export to &JSON + Esporta in &JSON + + + + + Export the filtered data to JSON + Esporta i dati filtrati in JSON + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + Questo pulsante esporta i dati della tabella visualizzata così come mostrata correntemente (dopo i filtri, formati di visualizzazione e ordine colonne) in un file JSON. + + + + Copy column name + Copia nome colonna + + + + Copy the database table column name to your clipboard + COpia il nome della colonna del database negli appunti + + + + New Data Browser + Nuovo Browser Dati + + + + + Add a new docked Data Browser + Aggiunge un nuovo Browser Dati + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + Questo pulasnte agggiunge un nuovo Browser Dati, che puoi scollegare e posizionare a piacimento. + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>Scorri all'ìinizio</p></body></html> + + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>Cliccare questo pulsante scorre la vista all'inizio della tabella.</p></body></html> + + + + |< + |< + + + + Scroll one page upwards + Scorri di una pagina in su + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>Cliccando questo pulsante la vista scorre le righe di una pagina verso l'inizio della tabella.</p></body></html> + + + + < + < + + + + 0 - 0 of 0 + 0 - 0 di 0 + + + + Scroll one page downwards + Scorri di una pagina in giù + + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>Cliccando questo pulsante la vista scorre le righe di una pagina verso il fondo della tabella.</p></body></html> + + + + > + > + + + + Scroll to the end + Scorri alla fine + + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>Cliccando questo pulsante la vista scorre al fondo della tabella.</p></body></html> + + + + >| + >| + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>Clicca qui per saltare alla riga specificata</p></body></html> + + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>Questo pulsante è utilizzato per navigare alla riga impostata nell'area "Vai a".</p></body></html> + + + + Go to: + Vai a: + + + + Enter record number to browse + Inserisci il numero di riga a cui scorrere + + + + Type a record number in this area and click the Go to: button to display the record in the database view + Inserisci un numero in quest'area e clicca sul pul pulsante "Vai a" per visualizzare la riga selezionata + + + + 1 + 1 + + + + Show rowid column + Mostra colonna rowid + + + + Toggle the visibility of the rowid column + Mostra/nasconde la colonna rowid + + + + Unlock view editing + Sblocca la modifica della vista + + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + Sblocca la vista corrente per modificarla. Per poterla modificare avrai comunque bisogno degli appropriati trigger. + + + + Edit display format + Modifica formato di visualizzazione + + + + Edit the display format of the data in this column + Modifica il formato di visualizzazione dei dati in questa colonna + + + + + New Record + Nuova Riga + + + + + Insert a new record in the current table + Inserisci un nuovo valore nella tabella corrente + + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>Questo pulsante crea una nuova riga nel database. Mantieni premuto il tasto del mouse per ottenere più opzioni:</p><ul><li><span style=" font-weight:600;">Nuova Riga</span>: inserisce una nuova riga con i valori predefiniti.</li><li><span style=" font-weight:600;">Inserisci Valori...</span>: apre una finestra per inserire i valori prima che vengano immessi nel database. Questo permette che l'immissione dei valori rispetti diversi limiti (constraints). Questa finestra si apre anche se l'opzione <span style=" font-weight:600;">Nuova Riga</span> fallisce a causa di questi limiti (constraints).</li></ul></body></html> + + + + + Delete Record + Elimina Riga + + + + Delete the current record + Elimina il valore corrente + + + + + This button deletes the record or records currently selected in the table + Questo pulsante elimina la/e righe selezionate nella tabella + + + + + Insert new record using default values in browsed table + Inserisce un nuovo record utilizzando i valori di default della tabella + + + + Insert Values... + Inserisci Valori... + + + + + Open a dialog for inserting values in a new record + Apre una finestra per l'inermento di valori all'interno di un nuovo record + + + + Export to &CSV + Esporta in &CSV + + + + + Export the filtered data to CSV + Esporta i dati filtrati in CSV + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + Questo pulsante esporta i dati della tabella così come visualizzati (applicando filtri, formati e ordine delle colonne) in un file CSV. + + + + Save as &view + Salva come &vista + + + + + Save the current filter, sort column and display formats as a view + Salva il filtro corrente, ordine colonne e formati dati come vista + + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + Questo pulsante salva le impostazioni della tabella visualizzata (filtri, formati e ordine colonne) in una vista SQL che puoi successivamente navigare o utilizzare in statement SQL. + + + + Save Table As... + Salva Tabella Come... + + + + + Save the table as currently displayed + Salva la tabella così come visualizzata + + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>Questo menù fornisce le seguenti opzioni applicabili alla tabella filtrata e visualizzata correntemente:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Esporta in CSV: questa opzione esporta i dati della tabella così come visualizzati (con filtri, riordine delle colonne e formati) in un file CSV.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Salva come vista: questa opzione salva le impostazioni correnti della tabella visualizzata (filtri, riordine delle colonne e formati) come vista SQL che puoi successivamente visualizzare o utilizzare come statement.</li></ul></body></html> + + + + Hide column(s) + Nascondi colonna(e) + + + + Hide selected column(s) + Nasconde la(e) colonna(e) selezionata(e) + + + + Show all columns + Mostra tutte le colonne + + + + Show all columns that were hidden + Mostra tutte le colonne nascoste + + + + + Set encoding + Imposta codifica + + + + Change the encoding of the text in the table cells + Modifica la codifica del testo nelle celle della tabella + + + + Set encoding for all tables + Imposta la codifica per tutte le tabelle + + + + Change the default encoding assumed for all tables in the database + Modifica il valore predefinito di codifica per tutte le tabelle del database + + + + Clear Filters + Pulisci Filtri + + + + Clear all filters + Cancella tutti i filtri + + + + + This button clears all the filters set in the header input fields for the currently browsed table. + Questo pulsante pulisce tutti i filtri impostati nella riga d'intestazione per la tabella corrente. + + + + Clear Sorting + Ripristina Ordinamento + + + + Reset the order of rows to the default + Ripristina l'ordine delle righe predefinito + + + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + Questo pulsante ripristina l'ordinamento delle colonne predefinito per la tabella corrente. + + + + Print + Stampa + + + + Print currently browsed table data + Stampa i dati della tabella attualmente in esplorazione + + + + Print currently browsed table data. Print selection if more than one cell is selected. + Stampa i dati visualizzati. Stampa la selezione se più di una cella è selezionata. + + + + Ctrl+P + + + + + Refresh + Aggiorna + + + + Refresh the data in the selected table + Aggiorna i dati della tabella selezionata + + + + This button refreshes the data in the currently selected table. + Questo pulsante aggiorna i dati della tabella selezionata. + + + + F5 + + + + + Find in cells + Trova nelle celle + + + + Open the find tool bar which allows you to search for values in the table view below. + Apre la barra di ricerca che ti permette di cercare valori nella tabella visualizzata qui sotto. + + + + Freeze columns + Blocca colonne + + + + Make all columns from the first column up to this column not move when scrolling horizontally + Blocca tutte le colonne dalla prima a quella attuale nello scorrimento orizzontale + + + + + Bold + Grassetto + + + + Ctrl+B + + + + + + Italic + Corsivo + + + + + Underline + Sottolinea + + + + Ctrl+U + + + + + + Align Right + Allinea a Destra + + + + + Align Left + Allinea a Sinistra + + + + + Center Horizontally + Centra Orizzontalmente + + + + + Justify + Giustifica + + + + + Edit Conditional Formats... + Modifica Formattazione Condizionale... + + + + Edit conditional formats for the current column + Modifica formattazione condizionale per la colonna corrente + + + + Clear Format + Ripristina formattazione + + + + Clear All Formats + Ripristina Tutte le Formattazioni + + + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + Ripristina la formattazione di tutte le celle selezionate e tutte le formattazioni condizionali delle colonne selezionate + + + + + Font Color + Colore Testo + + + + + Background Color + Colore Sfondo + + + + Toggle Format Toolbar + Mostra/Nascondi barra dei formati + + + + Show/hide format toolbar + Mostra/nascondi barra dei formati + + + + + This button shows or hides the formatting toolbar of the Data Browser + Questo pulsante mostra o nasconde la barra dei formati per il Browser dei dati + + + + Select column + Seleziona colonna + + + + Ctrl+Space + + + + + Replace text in cells + Sostituisci testo nelle celle + + + + Filter in any column + Filtra in ogni colonna + + + + Ctrl+R + + + + + %n row(s) + + %n riga + %n righe + + + + + , %n column(s) + + , %n colonna + , %n colonne + + + + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . Somma: %1; Media: %2; Min: %3; Max: %4 + + + + Conditional formats for "%1" + Formattazione condizionale per '%1' + + + + determining row count... + determino il numero di righe... + + + + %L1 - %L2 of >= %L3 + %L1 - %L2 di >= %L3 + + + + %L1 - %L2 of %L3 + %L1 - %L2 di %L3 + + + + (clipped at %L1 rows) + (troncato a %L1 righe) + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + Si prega d'inserire una pseudo-chiave primaria in modo da abilitare le modifiche su questa vista. Deve corrispondere al nome di una colonna univoca nella vista. + + + + Delete Records + Elimina i Records + + + + Duplicate records + Duplica i records + + + + Duplicate record + Duplica il record + + + + Ctrl+" + + + + + Adjust rows to contents + Adatta le righe al contenuto + + + + Error deleting record: +%1 + Errore eliminando le righe: +%1 + + + + Please select a record first + Si prega di selezionare prima un record + + + + Please choose a new encoding for all tables. + Si prega di scegliere una nuova codifica per tutte le tabelle. + + + + Please choose a new encoding for this table. + Si prega di scegliere una nuova codifica per questa tabella. + + + + %1 +Leave the field empty for using the database encoding. + %1 +Lasciare il campo vuoto per utilizzare la codifica del database. + + + + This encoding is either not valid or not supported. + Questa codifica non è valida o non è supportata. + + + + %1 replacement(s) made. + %1 sostituzione(i) effettuata(e). + + + + TableBrowserDock + + + New Data Browser + Nuovo Browser Dati + + + + Rename Data Browser + Rinomina Browser Dati + + + + Close Data Browser + Chiudi Browser Dati + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + Imposta un nuovo nome per il browser dati. Usa il carattere '&&' per utilizzare il carattere successivo come scorciatoia da tastiera. + + + + UndoStack + + Inserting %1 bytes + Inserisco %1 bytes + + + Delete %1 chars + Elimino %1 caratteri + + + Overwrite %1 chars + Sovrascrivo %1 caratteri + + + + VacuumDialog + + + Compact Database + Compatta Database + + + + Warning: Compacting the database will commit all of your changes. + Attenzione: Compattare il database salverà tutte le tue modifiche. + + + + Please select the databases to co&mpact: + Si prega di selezionare il database da co&mpattare: + + + diff --git a/src/translations/sqlb_ja.ts b/src/translations/sqlb_ja.ts new file mode 100644 index 000000000..02913fd5f --- /dev/null +++ b/src/translations/sqlb_ja.ts @@ -0,0 +1,8073 @@ + + + + + AboutDialog + + + About DB Browser for SQLite + DB Browser for SQLite ã«ã¤ã„㦠+ + + + Version + ãƒãƒ¼ã‚¸ãƒ§ãƒ³ + + + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + <html><head/><body><p>DB Browser for SQLite ã¯ã€SQLite データベースファイルを作æˆã€è¨­è¨ˆã€ç·¨é›†ã™ã‚‹ãŸã‚ã®ã€ã‚ªãƒ¼ãƒ—ンソースã§ãƒ•リーウェアãªãƒ´ã‚£ã‚¸ãƒ¥ã‚¢ãƒ«ãƒ„ールã§ã™ã€‚</p><p>ã“れã¯ã€Mozilla Public License Version 2 ã¨ã€GNU General Public License Version 3 ã‹ãれ以é™ã®ã™ã¹ã¦ãƒãƒ¼ã‚¸ãƒ§ãƒ³ ã®ä¸¡æ–¹ã§ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã•れã¦ã„ã¾ã™ã€‚ã‚ãªãŸã¯ã“れらã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®æ¡ä»¶ã®ä¸‹ã§å¤‰æ›´ã‚„å†é…布ãŒã§ãã¾ã™ã€‚</p><p>詳細ã¯<a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> 㨠<a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> ã‚’ã”覧ãã ã•ã„。</p><p>ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã®æ›´ãªã‚‹æƒ…報を得るã«ã¯ã€ç§ãŸã¡ã®ã‚¦ã‚§ãƒ–サイトを訪れã¦ãã ã•ã„:<a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">ã“ã®ã‚½ãƒ•トウェア㯠GPL/LGPL Qt Toolkit を使用ã—ã¦ã„ã¾ã™ã€‚</span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>ライセンスæ¡é …や情報㯠</span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> ã‚’ã”覧ãã ã•ã„。</span></p><p><span style=" font-size:8pt;">ã“ã®ã‚½ãƒ•トウェアã¯SQLite拡張サãƒãƒ¼ãƒˆã®ãŸã‚ã€nalgeon/sqlean library を使用ã—ã¦ã„ã¾ã™ã€‚<br/>ã“ã®ãƒ©ã‚¤ãƒ–ラリã¯MITライセンスã§ã™ã€‚æ›´ãªã‚‹æƒ…å ±ã¯ä»¥ä¸‹ã‚’ã”覧ãã ã•ã„:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">ã¾ãŸã€Michael Buckley ã® Pastel SVG icon set ã‚’ Creative Commons Attribution Share Alike 4.0 license ã®å…ƒã«ä½¿ç”¨ã—ã¦ã„ã¾ã™ã€‚<br/>詳細㯠</span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> ã‚’ã”覧ãã ã•ã„。</span></p></body></html> + + + + AddRecordDialog + + + Add New Record + æ–°ã—ã„レコードを追加 + + + + Enter values for the new record considering constraints. Fields in bold are mandatory. + 制約を考慮ã—ã¦æ–°ã—ã„レコードã«å€¤ã‚’入力ã—ã¾ã™ã€‚太字ã®ãƒ•ィールドã¯å¿…é ˆã§ã™ã€‚ + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + 「値ã€åˆ—ã§ã¯ã€ã€Œåå‰ã€åˆ—ã§è­˜åˆ¥ã•れãŸãƒ•ィールドã®å€¤ã‚’指定ã§ãã¾ã™ã€‚「データ型ã€åˆ—ã¯ãƒ•ィールドã®ãƒ‡ãƒ¼ã‚¿åž‹ã‚’示ã—ã¾ã™ã€‚ デフォルト値ã¯NULL値ã¨åŒã˜ã‚¹ã‚¿ã‚¤ãƒ«ã§è¡¨ç¤ºã•れã¾ã™ã€‚ + + + + Name + åå‰ + + + + Type + データ型 + + + + Value + 値 + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + 挿入ã™ã‚‹å€¤ã€‚変更ã•れãªã„é™ã‚Šã€äº‹å‰å…¥åŠ›ã•れãŸãƒ‡ãƒ•ォルト値ãŒè‡ªå‹•çš„ã«æŒ¿å…¥ã•れã¾ã™ã€‚ + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + 上ã®ãƒ•レームã§å€¤ã‚’編集ã™ã‚‹ã¨ã€ã“ã®æ–°ã—ã„レコードを挿入ã™ã‚‹ SQL クエリーãŒã“ã“ã«è¡¨ç¤ºã•れã¾ã™ã€‚ä¿å­˜ã™ã‚‹å‰ã«ã“ã®ã‚¯ã‚¨ãƒªãƒ¼ã‚’手動ã§ç·¨é›†ã§ãã¾ã™ã€‚ + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">ä¿å­˜</span>ã¯è¡¨ç¤ºã•れã¦ã„ã‚‹æ–°ã—ã„レコードを挿入ã™ã‚‹SQL文をデータベースã«é©ç”¨ã—ã¾ã™ã€‚</p><p><span style=" font-weight:600;">ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã«æˆ»ã™</span>ã¯<span style=" font-weight:600;">「値ã€</span>åˆ—ã‚’åˆæœŸå€¤ã«æˆ»ã—ã¾ã™ã€‚</p><p><span style=" font-weight:600;">キャンセル</span>ã¯ã‚¯ã‚¨ãƒªãƒ¼ã‚’実行ã›ãšã«ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã‚’é–‰ã˜ã¾ã™ã€‚</p></body></html> + + + + Auto-increment + + 自動増加 + + + + + Unique constraint + + ä¸€æ„æ€§åˆ¶ç´„ + + + + + Check constraint: %1 + + ãƒã‚§ãƒƒã‚¯åˆ¶ç´„: %1 + + + + + Foreign key: %1 + + 外部キー: %1 + + + + + Default value: %1 + + デフォルト値: %1 + + + + + Error adding record. Message from database engine: + +%1 + レコード追加ã§ã‚¨ãƒ©ãƒ¼ã€‚データベースエンジンã‹ã‚‰ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸: + +%1 + + + + Are you sure you want to restore all the entered values to their defaults? + 入力ã—ãŸå€¤ã‚’ã™ã¹ã¦ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã«æˆ»ã—ã¾ã™ã‹? + + + + Application + + + Possible command line arguments: + 使用å¯èƒ½ãªã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³å¼•æ•°: + + + + The user settings file location is replaced with the argument value instead of the environment variable value. + ユーザー設定ファイルã®å ´æ‰€ã¯ç’°å¢ƒå¤‰æ•°ã®å€¤ã«ä»£ã‚ã£ã¦ã“ã®å¼•æ•°ã«ç½®ãæ›ãˆã‚‰ã‚Œã¾ã™ã€‚ + + + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + 環境変数(DB4S_SETTINGS_FILE)ã®å€¤ã¯ç„¡è¦–ã•れã¾ã™ : + + + + + The file %1 does not exist + ファイル %1 ãŒå­˜åœ¨ã—ã¾ã›ã‚“ + + + + Usage + ä½¿ã„æ–¹ + + + + options + オプション + + + + + database + データベース + + + + + project + プロジェクト + + + + + csv-file + csvファイル + + + + Show command line options + コマンドラインã®ã‚ªãƒ—ションを表示ã™ã‚‹ + + + + Exit application after running scripts + スクリプト実行後ã«ã‚¢ãƒ—リケーションを終了ã™ã‚‹ + + + + + file + ファイル + + + + Execute this SQL file after opening the DB + DBã‚’é–‹ã„ãŸå¾Œã«ã“ã®SQLを実行ã™ã‚‹ + + + + Import this CSV file into the passed DB or into a new DB + ã“ã®CSVファイルを渡ã•れãŸDBã‹æ–°ã—ã„DBã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ + + + + table + テーブル + + + + Browse this table, or use it as target of a data import + ã“ã®ãƒ†ãƒ¼ãƒ–ルを閲覧ã€ã‚‚ã—ãã¯ã‚¤ãƒ³ãƒãƒ¼ãƒˆã®å¯¾è±¡ã¨ã—ã¦ä½¿ç”¨ã™ã‚‹ + + + + Open database in read-only mode + データベースを読ã¿å–り専用モードã§é–‹ã + + + + settings_file + 設定ファイル + + + + Run application based on this settings file + ã“ã®è¨­å®šãƒ•ァイルを基ã«ã‚¢ãƒ—リケーションを実行ã™ã‚‹ + + + + + group + グループ + + + + + settings + 設定 + + + + + value + 値 + + + + Run application with this setting temporarily set to value + 一時的ã«ã“ã®å€¤ã‚’設定ã—ã¦ã‚¢ãƒ—リケーションを実行ã™ã‚‹ + + + + Run application saving this value for this setting + ã“ã®å€¤ã®è¨­å®šã‚’ä¿å­˜ã—ã¦ã‚¢ãƒ—リケーションを実行ã™ã‚‹ + + + + Display the current version + ç¾åœ¨ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’表示ã™ã‚‹ + + + + Open this SQLite database + ã“ã® SQLite データベースを開ã + + + + Open this project file (*.sqbpro) + ã“ã®ãƒ—ロジェクトファイル(*.sqbpro)ã‚’é–‹ã + + + + Import this CSV file into an in-memory database + ã“ã®CSVファイルをインメモリーデータベースã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ + + + + + + The %1 option requires an argument + %1 オプションã«ã¯å¼•æ•°ãŒå¿…è¦ã§ã™ + + + + The -S/--settings option requires an argument. The option is ignored. + -S/--settings オプションã¯å¼•æ•°ãŒå¿…è¦ã§ã™ã€‚ã“ã®ã‚ªãƒ—ションã¯ç„¡è¦–ã•れã¾ã™ã€‚ + + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + -o/--option 㨠-O/--save-optionオプション㯠グループ/設定=値 ã®å½¢å¼ã§å¼•æ•°ãŒå¿…è¦ã§ã™ + + + + SQLite Version + SQLite ãƒãƒ¼ã‚¸ãƒ§ãƒ³ + + + + SQLCipher Version %1 (based on SQLite %2) + SQLCipher ãƒãƒ¼ã‚¸ãƒ§ãƒ³ %1 (SQLite %2 ãŒãƒ™ãƒ¼ã‚¹) + + + + DB Browser for SQLite Version %1. + DB Browser for SQLite ãƒãƒ¼ã‚¸ãƒ§ãƒ³ %1. + + + + Last commit hash when built: %1 + ビルド時最新コミットã®ãƒãƒƒã‚·ãƒ¥: %1 + + + + Built for %1, running on %2 + %1 å‘ã‘ビルド, %2 ã§å‹•作中 + + + + Qt Version %1 + Qt ãƒãƒ¼ã‚¸ãƒ§ãƒ³ %1 + + + + Invalid option/non-existent file: %1 + 䏿­£ãªã‚ªãƒ—ション/存在ã—ãªã„ファイルã§ã™: %1 + + + + CipherDialog + + + SQLCipher encryption + SQLCipher æš—å·åŒ– + + + + &Password + パスワード(&P) + + + + &Reenter password + パスワードã®å†å…¥åŠ›(&R) + + + + Passphrase + パスフレーズ + + + + Raw key + 生ã®ã‚­ãƒ¼ + + + + Encr&yption settings + æš—å·åŒ–設定(&Y) + + + + SQLCipher &3 defaults + SQLCipher 3 デフォルト(&3) + + + + SQLCipher &4 defaults + SQLCipher 4 デフォルト(&4) + + + + Custo&m + カスタム(&M) + + + + Page si&ze + ページサイズ(&Z) + + + + &KDF iterations + KDFå復回数(&K) + + + + HMAC algorithm + HMACアルゴリズム + + + + KDF algorithm + KDFアルゴリズム + + + + Plaintext Header Size + プレーンテキストヘッダーサイズ + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + データベースを暗å·åŒ–ã™ã‚‹ã‚­ãƒ¼ã‚’設定ã—ã¦ãã ã•ã„。 +ãã®ã»ã‹ã®ä»»æ„ã®è¨­å®šã‚’変更ã™ã‚‹ã¨ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを開ãã¨ãã¯æ¯Žå›žå†å…¥åŠ›ãŒå¿…è¦ã«ãªã‚‹ã“ã¨ã«æ³¨æ„ã—ã¦ãã ã•ã„。 +æš—å·åŒ–を無効ã«ã™ã‚‹ã«ã¯ãƒ‘スワード欄を空白ã«ã—ã¾ã™ã€‚ +æš—å·åŒ–工程ã«ã¯å°‘ã—æ™‚é–“ãŒã‹ã‹ã‚‹ã§ã—ょã†ã€‚データベースã®ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—を作æˆã™ã‚‹ã¹ãã§ã™! ä¿å­˜ã—ã¦ã„ãªã„å¤‰æ›´ã¯æš—å·åŒ–ã®å‰ã«å映ã•れã¾ã™ã€‚ + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æš—å·åŒ–ã«ä½¿ç”¨ã™ã‚‹ã‚­ãƒ¼ã‚’入力ã—ã¦ãã ã•ã„。 +ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®ä»–ã®è¨­å®šãŒå¤‰æ›´ã•れãŸå ´åˆã¯ã€ã“ã®æƒ…報も指定ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚ + + + + ColumnDisplayFormatDialog + + + Choose display format + 表示書å¼ã‚’é¸æŠž + + + + Display format + è¡¨ç¤ºæ›¸å¼ + + + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + カラム '%1' ã®è¡¨ç¤ºå½¢å¼ã‚’é¸æŠžã—ã¦ãã ã•ã„。ã“れã¯è¡¨ç¤ºå‰ã«å„値ã«é©ç”¨ã•れã¾ã™ã€‚ + + + + Default + デフォルト + + + + Decimal number + å進数 + + + + Exponent notation + 指数表記 + + + + Hex blob + å六進Blob + + + + Hex number + å六進数 + + + + Octal number + 八進数 + + + + Round number + 概数 + + + + Apple NSDate to date + Apple NSDate を日付㫠+ + + + Java epoch (milliseconds) to date + Java エãƒãƒƒã‚¯ (ミリ秒) を日付㫠+ + + + .NET DateTime.Ticks to date + .NET DateTime.Ticks を日付㫠+ + + + Julian day to date + ユリウス日を日付㫠+ + + + Unix epoch to date + Unix エãƒãƒƒã‚¯ã‚’日付㫠+ + + + Unix epoch to local time + Unix エãƒãƒƒã‚¯ã‚’地方時㫠+ + + + WebKit / Chromium epoch to date + WebKit / Chromium エãƒãƒƒã‚¯ã‚’日付㫠+ + + + WebKit / Chromium epoch to local time + WebKit / Chromium エãƒãƒƒã‚¯ã‚’地方時㫠+ + + + Windows DATE to date + Windows DATE を日付㫠+ + + + Date as dd/mm/yyyy + 日付(dd/mm/yyyy) + + + + Lower case + å°æ–‡å­— + + + + Upper case + 大文字 + + + + Binary GUID to text + ãƒã‚¤ãƒŠãƒªGUIDをテキスト㫠+ + + + SpatiaLite Geometry to SVG + SpatiaLiteジオメトリーをSVGã« + + + + Custom + カスタム + + + + Custom display format must contain a function call applied to %1 + カスタム表示形å¼ã«ã¯ã€%1 ã«é©ç”¨ã•れる関数呼ã³å‡ºã—ãŒå«ã¾ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚りã¾ã™ + + + + Error in custom display format. Message from database engine: + +%1 + カスタム表示形å¼ã§ã‚¨ãƒ©ãƒ¼ã€‚データベースエンジンã‹ã‚‰ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸: + +%1 + + + + Custom display format must return only one column but it returned %1. + カスタム表示形å¼ã¯ãŸã 1ã¤ã®ã‚«ãƒ©ãƒ ã‚’è¿”ã™å¿…è¦ãŒã‚りã¾ã™ãŒã€%1 ãŒè¿”ã£ã¦ãã¾ã—ãŸã€‚ + + + + CondFormatManager + + + Conditional Format Manager + æ¡ä»¶ä»˜ã書å¼ç®¡ç† + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + ã“ã®ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã§æ¡ä»¶ä»˜ã書å¼ã®ä½œæˆã¨ç·¨é›†ãŒã§ãã¾ã™ã€‚ãれãžã‚Œã®ã‚»ãƒ«ã‚¹ã‚¿ã‚¤ãƒ«ã¯ã‚»ãƒ«ã®ãƒ‡ãƒ¼ã‚¿ãŒæœ€åˆã«ä¸€è‡´ã—ãŸæ¡ä»¶ã®ã‚‚ã®ãŒé¸æŠžã•れã¾ã™ã€‚æ¡ä»¶ä»˜ã書å¼ã¯ä¸Šä¸‹ã«ç§»å‹•ã§ãã€ä¸Šã®è¡Œã¯ä¸‹ã®è¡Œã«å„ªå…ˆã—ã¾ã™ã€‚æ¡ä»¶ã®æ§‹æ–‡ã¯ãƒ•ィルターã¨åŒã˜ã§ã€ç©ºç™½ã®æ¡ä»¶ã¯å…¨ã¦ã®å€¤ã«é©ç”¨ã•れã¾ã™ã€‚ + + + + Add new conditional format + æ–°ã—ã„æ¡ä»¶ä»˜ã書å¼ã‚’追加ã—ã¾ã™ + + + + &Add + 追加(&A) + + + + Remove selected conditional format + é¸æŠžã—ãŸæ¡ä»¶ä»˜ã書å¼ã‚’削除ã—ã¾ã™ + + + + &Remove + 削除(&R) + + + + Move selected conditional format up + é¸æŠžã—ãŸæ¡ä»¶ä»˜ã書å¼ã‚’上ã¸ç§»å‹•ã—ã¾ã™ + + + + Move &up + 上ã¸(&U) + + + + Move selected conditional format down + é¸æŠžã—ãŸæ¡ä»¶ä»˜ã書å¼ã‚’下ã¸ç§»å‹•ã—ã¾ã™ + + + + Move &down + 下ã¸(&D) + + + + Foreground + 剿™¯ + + + + Text color + 文字色 + + + + Background + 背景 + + + + Background color + 背景色 + + + + Font + フォント + + + + Size + サイズ + + + + Bold + 太字 + + + + Italic + イタリック + + + + Underline + 下線 + + + + Alignment + é…ç½® + + + + Condition + æ¡ä»¶ + + + + + Click to select color + クリックã§è‰²ã‚’é¸æŠž + + + + Are you sure you want to clear all the conditional formats of this field? + 本当ã«ã“ã®ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ã®æ¡ä»¶ä»˜ã書å¼ã‚’ã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã‹? + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + 接続ã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹æ™‚ã«ä½¿ç”¨ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åを指定ã—ã¦ãã ã•ã„ + + + + Invalid file format + 䏿­£ãªãƒ•ァイルフォーマット + + + + Do you really want to close this temporary database? All data will be lost. + 本当ã«ã“ã®ä¸€æ™‚データベースを閉ã˜ã¾ã™ã‹? ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã¯å–ªå¤±ã—ã¾ã™ã€‚ + + + + Do you want to save the changes made to the database file %1? + データベースファイル '%1' ã¸ã®å¤‰æ›´ã‚’ä¿å­˜ã—ã¾ã™ã‹? + + + + Database didn't close correctly, probably still busy + ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒæ­£å¸¸ã«é–‰ã˜ã‚‰ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚多分ã¾ã ãƒ“ジー状態ã§ã™ + + + + Cannot open destination file: '%1' + 目的ã®ãƒ•ァイル: '%1' ã‚’é–‹ã‘ã¾ã›ã‚“ + + + + + Cannot backup to file: '%1'. Message: %2 + ファイル: '%1' ã‚’ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ã§ãã¾ã›ã‚“。メッセージ: %2 + + + + The database is currently busy: + データベースã¯ç¾åœ¨ãƒ“ジー状態ã§ã™: + + + + Do you want to abort that other operation? + ä»–ã®æ“作を中断ã—ã¾ã™ã‹? + + + + Exporting database to SQL file... + データベースをSQLファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ... + + + + + Cancel + キャンセル + + + + + No database file opened + データベースファイルを開ã„ã¦ã„ã¾ã›ã‚“ + + + + Executing SQL... + SQLを実行... + + + + Action cancelled. + æ“作をキャンセルã—ã¾ã—ãŸã€‚ + + + + + Error in statement #%1: %2. +Aborting execution%3. + ã“ã®æ–‡ã§ã‚¨ãƒ©ãƒ¼ #%1: %2。 +実行を中断%3。 + + + + + and rolling back + ロールãƒãƒƒã‚¯ã—ã¾ã—㟠+ + + + didn't receive any output from %1 + %1 ã‹ã‚‰å‡ºåŠ›ã‚’å¾—ã‚‰ã‚Œã¾ã›ã‚“ã§ã—㟠+ + + + could not execute command: %1 + コマンド: %1 を実行ã§ãã¾ã›ã‚“ã§ã—㟠+ + + + Cannot delete this object + ã“ã®ã‚ªãƒ–ジェクトã¯å‰Šé™¤ã§ãã¾ã›ã‚“ + + + + Cannot set data on this object + ã“ã®ã‚ªãƒ–ジェクトã«ãƒ‡ãƒ¼ã‚¿è¨­å®šã¯ã§ãã¾ã›ã‚“ + + + + + A table with the name '%1' already exists in schema '%2'. + åå‰ãŒ '%1' ã®ãƒ†ãƒ¼ãƒ–ルã¯ã‚¹ã‚­ãƒ¼ãƒž '%2' ã«æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚ + + + + No table with name '%1' exists in schema '%2'. + スキーマ '%2' ã«åå‰ãŒ '%1' ã®ãƒ†ãƒ¼ãƒ–ルãŒã‚りã¾ã›ã‚“。 + + + + + Cannot find column %1. + カラム %1 ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + + + + Creating savepoint failed. DB says: %1 + セーブãƒã‚¤ãƒ³ãƒˆã®ä½œæˆã«å¤±æ•—。DBã®å応: %1 + + + + Renaming the column failed. DB says: +%1 + カラムå変更ã«å¤±æ•—。DBã®å応: +%1 + + + + + Releasing savepoint failed. DB says: %1 + セーブãƒã‚¤ãƒ³ãƒˆã®è§£æ”¾ã«å¤±æ•—。DBã®å応: %1 + + + + Creating new table failed. DB says: %1 + æ–°ã—ã„テーブルã®ä½œæˆã«å¤±æ•—。DBã®å応: %1 + + + + Copying data to new table failed. DB says: +%1 + æ–°ã—ã„テーブルã¸ã®ãƒ‡ãƒ¼ã‚¿ã®ã‚³ãƒ”ーã«å¤±æ•—。DBã®å応: +%1 + + + + Deleting old table failed. DB says: %1 + å¤ã„テーブルã®å‰Šé™¤ã«å¤±æ•—。DBã®å応: %1 + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + テーブルåã® '%1' ã‹ã‚‰ '%2' ã¸ã®å¤‰æ›´ã§ã‚¨ãƒ©ãƒ¼ã€‚ +データベースエンジンã‹ã‚‰ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸: +%3 + + + + could not get list of db objects: %1 + DBオブジェクトã®ä¸€è¦§ã‚’å–å¾—ã§ãã¾ã›ã‚“: %1 + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + ã“ã®ãƒ†ãƒ¼ãƒ–ルã«é–¢é€£ã™ã‚‹ã‚ªãƒ–ジェクトã®å¾©å…ƒã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã“れã¯ãŠãらã一部ã®ã‚«ãƒ©ãƒ åãŒå¤‰æ›´ã•れãŸãŸã‚ã§ã™ã€‚ã“ã®SQL文を手動ã§ä¿®æ­£ã—実行ã—ã¦ãã ã•ã„。 +Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + + + + could not get list of databases: %1 + データベースã®ä¸€è¦§ã‚’å–å¾—ã§ãã¾ã›ã‚“: %1 + + + + Error setting pragma %1 to %2: %3 + プラグマ %1 ã‚’ %2 ã«è¨­å®šæ™‚ã«ã‚¨ãƒ©ãƒ¼: %3 + + + + File not found. + ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + + + + Error loading extension: %1 + æ‹¡å¼µã®èª­ã¿è¾¼ã¿ã§ã‚¨ãƒ©ãƒ¼: %1 + + + + Error loading built-in extension: %1 + ビルトイン拡張ã®èª­ã¿è¾¼ã¿ã§ã‚¨ãƒ©ãƒ¼: %1 + + + + could not get column information + カラム情報ãŒå–å¾—ã§ãã¾ã›ã‚“ã§ã—㟠+ + + + DbStructureModel + + + Name + åå‰ + + + + Object + オブジェクト + + + + Type + データ型 + + + + Schema + スキーマ + + + + Database + データベース + + + + Browsables + 表示å¯èƒ½ + + + + All + ã™ã¹ã¦ + + + + Temporary + 一時 + + + + Tables (%1) + テーブル (%1) + + + + Indices (%1) + インデックス (%1) + + + + Views (%1) + ビュー (%1) + + + + Triggers (%1) + トリガー (%1) + + + + EditDialog + + + Edit database cell + データベースã®ã‚»ãƒ«ã‚’編集 + + + + Mode: + モード: + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + ã“れã¯ã‚µãƒãƒ¼ãƒˆã—ã¦ã„るセル編集モードã®ä¸€è¦§ã§ã™ã€‚ç¾åœ¨ã®ã‚»ãƒ«ãƒ‡ãƒ¼ã‚¿ã®è¡¨ç¤ºä¿®æ­£ã«ä½¿ç”¨ã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã‚’é¸ã‚“ã§ãã ã•ã„。 + + + + Text + テキスト + + + + RTL Text + RTL テキスト + + + + Binary + ãƒã‚¤ãƒŠãƒªãƒ¼ + + + + + Image + ç”»åƒ + + + + JSON + JSON + + + + XML + XML + + + + Evaluation + 評価 + + + + + Automatically adjust the editor mode to the loaded data type + 編集モードを読ã¿è¾¼ã‚“ã ãƒ‡ãƒ¼ã‚¿åž‹ã«è‡ªå‹•çš„ã«èª¿æ•´ + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + ã“ã®ãƒã‚§ãƒƒã‚¯ãƒœã‚¿ãƒ³ã¯ç·¨é›†ãƒ¢ãƒ¼ãƒ‰ã®è‡ªå‹•切り替ãˆã‚’有効/無効ã«ã—ã¾ã™ã€‚æ–°ã—ã„セルãŒé¸æŠžã•ã‚Œã‚‹ã‹æ–°ã—ã„データãŒã‚¤ãƒ³ãƒãƒ¼ãƒˆã•ã‚ŒãŸæ™‚ã«è‡ªå‹•切り替ãˆãŒæœ‰åйã ã¨ã€æ¤œå‡ºã—ãŸãƒ‡ãƒ¼ã‚¿åž‹ã«ãƒ¢ãƒ¼ãƒ‰ã‚’調整ã—ã¾ã™ã€‚ãã®å¾Œã€ç·¨é›†ãƒ¢ãƒ¼ãƒ‰ã¯æ‰‹å‹•ã§å¤‰æ›´ã§ãã¾ã™ã€‚セル間ã®ç§»å‹•æ™‚ã«æ‰‹å‹•ã§å¤‰æ›´ã—ãŸãƒ¢ãƒ¼ãƒ‰ã‚’ç¶­æŒã—ãŸã„ãªã‚‰ã°ã€ã“ã®ãƒœã‚¿ãƒ³ã‚’オフã«ã—ã¾ã™ã€‚ + + + + Auto-switch + 自動切替 + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + ã“ã®Qtエディターã¯å³æ›¸ãã®æ–‡ç« ã«ä½¿ã‚れã¾ã™ã€‚ã“れã¯ãƒ‡ãƒ•ォルトã®ãƒ†ã‚­ã‚¹ãƒˆã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã§ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“ã€‚å³æ›¸ãã®æ–‡å­—ã®å­˜åœ¨ãŒæ¤œçŸ¥ã•れるã¨ã€ã“ã®ã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ãƒ¢ãƒ¼ãƒ‰ãŒè‡ªå‹•çš„ã«é¸æŠžã•れã¾ã™ã€‚ + + + + Identification of the cell currently in the editor + エディター内ã®ç¾åœ¨ã®ã‚»ãƒ«ã®è­˜åˆ¥å€¤ + + + + Type and size of data currently in table + ç¾åœ¨ãƒ†ãƒ¼ãƒ–ルã«ã‚るデータ型ã¨ã‚µã‚¤ã‚º + + + + Apply data to cell + セルã«ãƒ‡ãƒ¼ã‚¿ã‚’é©ç”¨ + + + + Open preview dialog for printing the data currently stored in the cell + ç¾åœ¨ã‚»ãƒ«ã«ã‚るデータをå°åˆ·ã™ã‚‹ãƒ—レビューダイアログを開ã + + + + Auto-format: pretty print on loading, compact on saving. + 自動整形: ãれã„ã«è¡¨ç¤ºã€åœ§ç¸®ã—ã¦ä¿å­˜ã€‚ + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + 有効ã«ã™ã‚‹ã¨ã€è‡ªå‹•整形機能ã¯èª­ã¿è¾¼ã¿æ™‚ã«ãƒ‡ãƒ¼ã‚¿ã®å¯èª­æ€§ã‚’高ã‚る改行ã¨ã‚¤ãƒ³ãƒ‡ãƒ³ãƒˆã‚’加ãˆã¾ã™ã€‚データã®ä¿å­˜æ™‚ã«ã¯ã€æ”¹è¡Œã¨ä¸è¦ãªç©ºç™½ã‚’å–り除ãデータを圧縮ã—ã¾ã™ã€‚ + + + + Word Wrap + ワードラップ + + + + Wrap lines on word boundaries + å˜èªžå˜ä½ã§ãƒ¯ãƒ¼ãƒ‰ãƒ©ãƒƒãƒ— + + + + + Open in default application or browser + デフォルトã®ã‚¢ãƒ—リケーションã‹ãƒ–ラウザーã§é–‹ã + + + + Open in application + アプリケーションã§é–‹ã + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + 値ã¯ãƒ•ァイルã‹URLã¨è§£é‡ˆã•れã€ãƒ‡ãƒ•ォルトã®ã‚¢ãƒ—リケーションã‹ã‚¦ã‚§ãƒ–ブラウザã§é–‹ã‹ã‚Œã¾ã™ã€‚ + + + + Save file reference... + ファイルå‚ç…§ã‚’ä¿å­˜... + + + + Save reference to file + å‚照をファイルã«ä¿å­˜ + + + + + Open in external application + 外部ã®ã‚¢ãƒ—リケーションã§é–‹ã + + + + Autoformat + 自動整形 + + + + &Export... + エクスãƒãƒ¼ãƒˆ(&E)... + + + + + &Import... + インãƒãƒ¼ãƒˆ(&I)... + + + + + Import from file + ファイルã‹ã‚‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆ + + + + + Opens a file dialog used to import any kind of data to this database cell. + ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ã‚»ãƒ«ã«ä»»æ„ã®ç¨®é¡žã®ãƒ‡ãƒ¼ã‚¿ã‚’インãƒãƒ¼ãƒˆã™ã‚‹ãƒ•ァイルダイアログを開ãã¾ã™ã€‚ + + + + Export to file + ファイルã¸ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ + + + + Opens a file dialog used to export the contents of this database cell to a file. + ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ã‚»ãƒ«ã®å†…容をファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã™ã‚‹ãƒ•ァイルダイアログを開ãã¾ã™ã€‚ + + + + Erases the contents of the cell + セルã®å†…容を削除 + + + + Set as &NULL + NULLã«è¨­å®š(&N) + + + + This area displays information about the data present in this database cell + ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ã‚»ãƒ«ã«å­˜åœ¨ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ã®æƒ…報をã“ã“ã«è¡¨ç¤º + + + + This button saves the changes performed in the cell editor to the database cell. + ã“ã®ãƒœã‚¿ãƒ³ã¯ã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã§è¡Œã‚れãŸå¤‰æ›´ã‚’データベースã®ã‚»ãƒ«ã«ä¿å­˜ã—ã¾ã™ã€‚ + + + + Apply + é©ç”¨ + + + + Print... + å°åˆ·... + + + + Ctrl+P + + + + + Open preview dialog for printing displayed text + 表示ã•れãŸãƒ†ã‚­ã‚¹ãƒˆã‚’å°åˆ·ã™ã‚‹ãƒ—レビューダイアログを開ã + + + + Copy Hex and ASCII + å六進数ã¨ASCIIをコピー + + + + Copy selected hexadecimal and ASCII columns to the clipboard + é¸æŠžã—ãŸå六進数ã¨ASCIIã®ã‚«ãƒ©ãƒ ã‚’クリップボードã«ã‚³ãƒ”ー + + + + Ctrl+Shift+C + + + + + + Image data can't be viewed in this mode. + ç”»åƒãƒ‡ãƒ¼ã‚¿ã¯ã“ã®ãƒ¢ãƒ¼ãƒ‰ã§ã¯è¡¨ç¤ºã§ãã¾ã›ã‚“。 + + + + + Try switching to Image or Binary mode. + ç”»åƒ/ãƒã‚¤ãƒŠãƒªãƒ¼ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã¦ã¿ã¦ãã ã•ã„。 + + + + + Binary data can't be viewed in this mode. + ãƒã‚¤ãƒŠãƒªãƒ¼ãƒ‡ãƒ¼ã‚¿ã¯ã“ã®ãƒ¢ãƒ¼ãƒ‰ã§ã¯è¡¨ç¤ºã§ãã¾ã›ã‚“。 + + + + + Try switching to Binary mode. + ãƒã‚¤ãƒŠãƒªãƒ¼ãƒ¢ãƒ¼ãƒ‰ã«åˆ‡ã‚Šæ›¿ãˆã¦ã¿ã¦ãã ã•ã„。 + + + + + Image files (%1) + ç”»åƒãƒ•ァイル (%1) + + + + Binary files (*.bin) + ãƒã‚¤ãƒŠãƒªãƒ¼ãƒ•ァイル (*.bin) + + + + Choose a file to import + インãƒãƒ¼ãƒˆã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + テキストモードã§ã¯ãƒ—レーンテキストã¨ã—ã¦ç·¨é›†ã§ãã¾ã™ã€‚JSONã‚„XMLã§ã‚‚åŒæ§˜ã§ã™ãŒã€ã‚·ãƒ³ã‚¿ãƒƒã‚¯ã‚¹ãƒã‚¤ãƒ©ã‚¤ãƒˆã€è‡ªå‹•フォーマットã€ä¿å­˜å‰ã®ãƒãƒªãƒ‡ãƒ¼ã‚·ãƒ§ãƒ³ãŒè¡Œã‚れã¾ã™ã€‚ + +エラーã¯èµ¤ã„波下線ã§ç¤ºã•れã¾ã™ã€‚ + +評価モードã§ã¯å…¥åŠ›ã•れãŸSQLiteå¼ãŒè©•価ã•れã€çµæžœãŒã‚»ãƒ«ã«é©ç”¨ã•れã¾ã™ã€‚ + + + + Unsaved data in the cell editor + ã‚»ãƒ«ã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼å†…ã®æœªä¿å­˜ãƒ‡ãƒ¼ã‚¿ + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + データベースã«ã¾ã é©ç”¨ã•れã¦ã„ãªã„データãŒã‚»ãƒ«ã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã«ã‚りã¾ã™ã€‚ +編集中データを行=%1, 列=%2 ã«é©ç”¨ã—ã¾ã™ã‹? + + + + Editing row=%1, column=%2 + 編集中 行=%1, 列=%2 + + + + No cell active. + アクティブãªã‚»ãƒ«ã¯ã‚りã¾ã›ã‚“。 + + + + %1 Image + %1 ç”»åƒ + + + + Choose a filename to export data + エクスãƒãƒ¼ãƒˆãƒ‡ãƒ¼ã‚¿ã®ãƒ•ァイルåã‚’é¸æŠž + + + + Invalid data for this mode + ã“ã®ãƒ¢ãƒ¼ãƒ‰ã§ã¯ä¸æ­£ãªãƒ‡ãƒ¼ã‚¿ + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + セルã«ä¸æ­£ãªãƒ‡ãƒ¼ã‚¿ %1 ãŒã‚りã¾ã™ã€‚ç†ç”±: %2。本当ã«ã‚»ãƒ«ã«é©ç”¨ã—ã¾ã™ã‹? + + + + + Type: NULL; Size: 0 bytes + åž‹: NULL; サイズ: 0 ãƒã‚¤ãƒˆ + + + + + Type: Text / Numeric; Size: %n character(s) + + åž‹: テキスト/数値; サイズ: %n 文字 + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + åž‹: %1 ç”»åƒ; サイズ: %2x%3 ピクセル + + + + Type: Valid JSON; Size: %n character(s) + + åž‹: æ­£è¦ãªJSON; サイズ: %n 文字 + + + + + Type: Binary; Size: %n byte(s) + + åž‹: ãƒã‚¤ãƒŠãƒªâ€•; サイズ: %n ãƒã‚¤ãƒˆ + + + + + Couldn't save file: %1. + ファイルをä¿å­˜ã§ãã¾ã›ã‚“: %1. + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + データã¯ä¸€æ™‚ファイルã«ä¿å­˜ã•れã€ãƒ‡ãƒ•ォルトã®ã‚¢ãƒ—リケーションã§é–‹ã‹ã‚Œã¾ã—ãŸã€‚ã‚ãªãŸã¯ã™ãã«ãƒ•ァイルを編集ã§ãã€æº–å‚™ãŒã§ããŸã‚‰ã€ä¿å­˜ã—ãŸæ–°ã—ã„データをセルã«é©ç”¨ã€ã‚‚ã—ãã¯ã™ã¹ã¦ã®å¤‰æ›´ã‚’キャンセルã§ãã¾ã™ã€‚ + + + + EditIndexDialog + + + Edit Index Schema + インデックスã®ã‚¹ã‚­ãƒ¼ãƒžã‚’編集 + + + + &Name + åå‰(&N) + + + + &Table + テーブル(&T) + + + + &Unique + 一æ„(&U) + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + インデックスをテーブルã®ä¸€éƒ¨ã®ã¿ã«åˆ¶é™ã™ã‚‹å ´åˆã¯ã€ãã®éƒ¨åˆ†ã‚’é¸æŠžã™ã‚‹WHERE節をã“ã“ã«æŒ‡å®šã—ã¾ã™ + + + + Partial inde&x clause + インデックス指定節(&X) + + + + Colu&mns + カラム(&M) + + + + Table column + テーブルã®ã‚«ãƒ©ãƒ  + + + + Type + データ型 + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + æ–°ã—ã„å¼ã‚«ãƒ©ãƒ ã‚’インデックスã«åŠ ãˆã‚‹ã€‚å¼ã‚«ãƒ©ãƒ ã¯ã‚«ãƒ©ãƒ åã§ãªãSQLå¼ã‚’æŒã¡ã¾ã™ã€‚ + + + + Index column + インデックスカラム + + + + Order + 順番 + + + + Deleting the old index failed: +%1 + å¤ã„インデックスã®å‰Šé™¤ã«å¤±æ•—: +%1 + + + + Creating the index failed: +%1 + インデックスã®ä½œæˆã«å¤±æ•—: +%1 + + + + EditTableDialog + + + Edit table definition + テーブルã®å®šç¾©ã‚’編集 + + + + Table + テーブル + + + + Advanced + 高度ãªè¨­å®š + + + + Without Rowid + Rowidãªã— + + + + Fields + フィールド + + + + Database sche&ma + データベーススキーマ(&M) + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + 「ROWIDãªã—ã€ã®ãƒ†ãƒ¼ãƒ–ルを作æˆã—ã¾ã™ã€‚ã“ã®ãƒ•ラグを設定ã™ã‚‹ã«ã¯ä¸»ã‚­ãƒ¼(ä»»æ„ã®åž‹ã€è¤‡åˆã§ã‚‚よã„)ã®è¨­å®šãŒå¿…è¦ã§ã™ã€‚ãã—ã¦ã€è‡ªå‹•増加フラグã¯ä½¿ç”¨ã§ãã¾ã›ã‚“。 + + + + On Conflict + é‡è¤‡æ™‚å‡¦ç† + + + + Strict + åž‹ã«åŽ³æ ¼ + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + åž‹ã«åŽ³æ ¼ã‚ªãƒ—ã‚·ãƒ§ãƒ³ã‚’æœ‰åŠ¹ã«ã™ã‚‹ã¨ã€ãƒ‡ãƒ¼ã‚¿ã®æ›´æ–°è¿½åŠ æ™‚ã«SQLiteã¯ãれãžã‚Œã®ã‚«ãƒ©ãƒ ã®ãƒ‡ãƒ¼ã‚¿åž‹ã‚’強制ã—ã¾ã™ã€‚ + + + + + + Add + 追加 + + + + + + Remove + 削除 + + + + Move to top + 先頭㸠+ + + + Move up + 上㸠+ + + + Move down + 下㸠+ + + + Move to bottom + 末尾㸠+ + + + + + + Name + åå‰ + + + + + Type + データ型 + + + + NN + NN + + + + Not null + éžnull + + + + PK + PK + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> 主キー</p></body></html> + + + + AI + AI + + + + Autoincrement + 自動増加 + + + + U + U + + + + + + Unique + ä¸€æ„ + + + + Default + デフォルト + + + + Default value + デフォルト値 + + + + + Check + 検査 + + + + Check constraint + ãƒã‚§ãƒƒã‚¯åˆ¶ç´„ + + + + Collation + ç…§åˆé †åº + + + + Foreign Key + 外部キー + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_fk"/> 外部キー</p></body></html> + + + + Index Constraints + インデックス制約 + + + + Add constraint + 制約を追加 + + + + Remove constraint + 制約を削除 + + + + + Columns + カラム + + + + + + SQL + SQL + + + + Foreign Keys + 外部キー + + + + References + å‚ç…§ + + + + Check Constraints + ãƒã‚§ãƒƒã‚¯åˆ¶ç´„ + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">警告: </span>ãƒ†ãƒ¼ãƒ–ãƒ«å®šç¾©ã«æ§‹æ–‡è§£æžã§ããªã„ã‚‚ã®ãŒã‚りã¾ã™ã€‚ã“ã®ãƒ†ãƒ¼ãƒ–ルを変更ã—ä¿å­˜ã™ã‚‹ã¨å•題ãŒèµ·ãã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“。.</p></body></html> + + + + + Primary Key + 主キー + + + + Add a primary key constraint + 主キー制約を追加 + + + + Add a unique constraint + ä¸€æ„æ€§åˆ¶ç´„を追加 + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + 主キーã¯å„テーブルã«ä¸€ã¤ã ã‘存在ã§ãã¾ã™ã€‚替ã‚ã‚Šã«æ—¢å­˜ã®ä¸»ã‚­ãƒ¼ã‚’変更ã—ã¦ãã ã•ã„。 + + + + Error creating table. Message from database engine: +%1 + テーブル作æˆã§ã‚¨ãƒ©ãƒ¼ã€‚データベースエンジンã‹ã‚‰ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸: +%1 + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + ã“ã®åå‰ã¯æ—¢ã«åˆ¥ã®ãƒ•ィールドã«ä½¿ç”¨ã•れã¦ã„ã¾ã™ã€‚既存ã®ãƒ•ィールドåを変更ã™ã‚‹ã‹ã€åˆ¥ã®åå‰ã‚’付ã‘ã¦ãã ã•ã„。 + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + ã“ã®ã‚«ãƒ©ãƒ ã¯ãƒ†ãƒ¼ãƒ–ル %1 ã®å¤–部キーã«å‚ç…§ã•れã¦ã„ã‚‹ã®ã§ã€åå‰ã‚’変更ã§ãã¾ã›ã‚“。 + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + å°‘ãªãã¨ã‚‚1ã¤ã®è¡Œã§ã“ã®ãƒ•ィールドã«NULLãŒè¨­å®šã•れã¦ã„ã¾ã™ã€‚ãã®ãŸã‚ã€éžNULLを設定ã™ã‚‹ã®ã¯ä¸å¯èƒ½ã§ã™ã€‚å…ˆã«ãƒ†ãƒ¼ãƒ–ルã®ãƒ‡ãƒ¼ã‚¿ã‚’変更ã—ã¦ãã ã•ã„。 + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + å°‘ãªãã¨ã‚‚1ã¤ã®è¡Œã§ã“ã®ãƒ•ィールドã«INTEGERã§ãªã„値ãŒè¨­å®šã•れã¦ã„ã¾ã™ã€‚ãã®ãŸã‚ã€è‡ªå‹•増加を設定ã™ã‚‹ã®ã¯ä¸å¯èƒ½ã§ã™ã€‚å…ˆã«ãƒ†ãƒ¼ãƒ–ルã®ãƒ‡ãƒ¼ã‚¿ã‚’変更ã—ã¦ãã ã•ã„。 + + + + Column '%1' has duplicate data. + + カラム '%1' ã«é‡è¤‡ãƒ‡ãƒ¼ã‚¿ãŒã‚りã¾ã™ã€‚ + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + 一æ„ã«ã™ã‚‹ã®ã¯ä¸å¯èƒ½ã§ã™ã€‚é‡è¤‡ãƒ‡ãƒ¼ã‚¿ã‚’削除ã™ã‚‹ã¨ã€ä¸€æ„ã«ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚ + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + 本当ã«ãƒ•ィールド '%1' を削除ã—ã¾ã™ã‹? +ç¾åœ¨ã“ã®ãƒ•ィールドã«ã‚ã‚‹ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã¯å¤±ã‚れã¾ã™ã€‚ + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + rowidãªã—ã«ã™ã‚‹å‰ã«ã€ä»¥ä¸‹ã®æ¡ä»¶ã«åˆã†ãƒ•ィールドを追加ã—ã¦ãã ã•ã„。 + - 主キーã§ã‚ã‚‹ + - 自動増加ãªã— + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + é‡è¤‡æ™‚処ç†ã‚’設定ã™ã‚‹å‰ã«ã€ä»¥ä¸‹ã®æ¡ä»¶ã«åˆã†ãƒ•ィールドを追加ã—ã¦ãã ã•ã„: + - 主キーã§ã‚ã‚‹ + + + + ExportDataDialog + + + Export data as CSV + データをCSVã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ + + + + Tab&le(s) + テーブル(&L) + + + + Colu&mn names in first line + 先頭行をカラムåã«(&M) + + + + Fie&ld separator + フィールド区切り(&L) + + + + , + , + + + + ; + ; + + + + Tab + タブ + + + + | + | + + + + + + Other + ãã®ä»– + + + + &Quote character + 引用符文字(&Q) + + + + " + " + + + + ' + ' + + + + New line characters + 改行文字 + + + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) + + + + Unix: LF (\n) + Unix: LF (\n) + + + + Pretty print + æ•´å½¢ + + + + Export data as JSON + データをJSONã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ + + + + exporting CSV + CSVã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ + + + + + Error while writing the file '%1': %2 + ファイル '%1' を書ã込むã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒã‚りã¾ã—ãŸ: %2 + + + + + Could not open output file: %1 + 出力ファイルを開ã‘ã¾ã›ã‚“: %1 + + + + exporting JSON + JSONã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ + + + + + Choose a filename to export data + エクスãƒãƒ¼ãƒˆãƒ‡ãƒ¼ã‚¿ã®ãƒ•ァイルåã‚’é¸æŠž + + + + Please select at least 1 table. + å°‘ãªãã¨ã‚‚1ã¤ã®ãƒ†ãƒ¼ãƒ–ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„。 + + + + Choose a directory + ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãƒ¼ã‚’é¸æŠž + + + + Export completed. + エクスãƒãƒ¼ãƒˆå®Œäº†ã€‚ + + + + Export finished with errors. + エラーãŒã‚りã¾ã™ãŒã€ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆãŒçµ‚了ã—ã¾ã—ãŸã€‚ + + + + ExportSqlDialog + + + Export SQL... + SQLã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ... + + + + Tab&le(s) + テーブル(&L) + + + + Select All + ã™ã¹ã¦é¸æŠž + + + + Deselect All + ã™ã¹ã¦éžé¸æŠž + + + + &Options + オプション(&O) + + + + Keep column names in INSERT INTO + INSERT INTOã«ã‚«ãƒ©ãƒ åã‚’ä¿æŒ + + + + Multiple rows (VALUES) per INSERT statement + INSERTæ–‡ã«è¤‡æ•°è¡Œ(VALUES) + + + + Export everything + ã™ã¹ã¦ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ + + + + Export schema only + スキーマã®ã¿ã‚’エクスãƒãƒ¼ãƒˆ + + + + Export data only + データã®ã¿ã‚’エクスãƒãƒ¼ãƒˆ + + + + Keep original CREATE statements + å…ƒã®CREATEæ–‡ã‚’ä¿æŒ + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + å¤ã„ã‚¹ã‚­ãƒ¼ãƒžã‚’ä¿æŒ (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + å¤ã„スキーマを上書ã (DROP TABLE ã—ãŸå¾Œã« CREATE TABLE) + + + + Please select at least one table. + å°‘ãªãã¨ã‚‚1ã¤ã®ãƒ†ãƒ¼ãƒ–ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„。 + + + + Choose a filename to export + エクスãƒãƒ¼ãƒˆã™ã‚‹ãƒ•ァイルåã‚’é¸æŠž + + + + Export completed. + エクスãƒãƒ¼ãƒˆå®Œäº†ã€‚ + + + + Export cancelled or failed. + エクスãƒãƒ¼ãƒˆã‚’キャンセルã¾ãŸã¯å¤±æ•—ã—ã¾ã—ãŸã€‚ + + + + ExtendedScintilla + + + + Ctrl+H + + + + + Ctrl+F + + + + + + Ctrl+P + + + + + Find... + 検索... + + + + Find and Replace... + 検索ã¨ç½®æ›... + + + + Print... + å°åˆ·... + + + + ExtendedTableWidget + + + Use as Exact Filter + 抽出フィルターã«ä½¿ã† + + + + Containing + å«ã‚€ + + + + Not containing + å«ã¾ãªã„ + + + + Not equal to + ç­‰ã—ããªã„ + + + + Greater than + より大ãã„ + + + + Less than + 未満 + + + + Greater or equal + 以上 + + + + Less or equal + 以下 + + + + Between this and... + ã“れã¨ã®é–“... + + + + Regular expression + æ­£è¦è¡¨ç¾ + + + + Edit Conditional Formats... + æ¡ä»¶ä»˜ã書å¼ã‚’編集... + + + + Set to NULL + NULLã«è¨­å®š + + + + Cut + 切りå–り + + + + Copy + コピー + + + + Copy with Headers + ヘッダーをå«ã‚ã¦ã‚³ãƒ”ー + + + + Copy as SQL + SQLã¨ã—ã¦ã‚³ãƒ”ー + + + + Paste + 貼り付㑠+ + + + Print... + å°åˆ·... + + + + Use in Filter Expression + フィルターå¼ã‚’使用 + + + + Alt+Del + + + + + Ctrl+Shift+C + + + + + Ctrl+Alt+C + + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + クリップボードã®å†…容ã¯é¸æŠžã•れãŸç¯„囲より大ãã„ã§ã™. +ãれã§ã‚‚挿入ã—ã¾ã™ã‹? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>読ã¿è¾¼ã¾ã‚Œã¦ã„ãªã„データãŒã‚りã¾ã™ã€‚<b>ã™ã¹ã¦ã®è¡Œã‚’é¸æŠžã™ã‚‹å‰ã«ã€ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã¿ã¾ã™ã‹?</b><p><p>ç­”ãˆãŒ <b>ã„ã„ãˆ</b> ãªã‚‰ã°ã€ãƒ‡ãƒ¼ã‚¿ã¯èª­ã¿è¾¼ã¾ã‚Œãšã€é¸æŠžã¯å®Ÿè¡Œã•れã¾ã›ã‚“。<br/>ç­”ãˆãŒ <b>ã¯ã„</b> ãªã‚‰ã°ã€æ™‚é–“ãŒã‹ã‹ã‚Šã¾ã™ãŒã€ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã¿ã€é¸æŠžãŒå®Ÿè¡Œã•れã¾ã™ã€‚</p>警告: 大ãã„テーブルã«ã‚ã‚‹ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã®èª­ã¿è¾¼ã¿ã«ã¯ã‹ãªã‚Šã®è¨˜æ†¶é ˜åŸŸã‚’å¿…è¦ã¨ã—ã¾ã™ã€‚ + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + é¸æŠžç¯„å›²ã«NULLを設定ã§ãã¾ã›ã‚“。カラム %1 ã«ã¯éžNULL制約ãŒã‚りã¾ã™ã€‚ + + + + FileExtensionManager + + + File Extension Manager + ファイル拡張å­ç®¡ç† + + + + &Up + 上ã¸(&U) + + + + &Down + 下ã¸(&D) + + + + &Add + 追加(&A) + + + + &Remove + 削除(&R) + + + + + Description + 説明 + + + + Extensions + æ‹¡å¼µå­ + + + + *.extension + *.æ‹¡å¼µå­ + + + + FilterLineEdit + + + Filter + フィルター + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + ã“ã®å…¥åŠ›æ¬„ã¯ç¾åœ¨é¸æŠžã—ãŸãƒ†ãƒ¼ãƒ–ルã®å³å¸­ãƒ•ィルターã«ãªã‚Šã¾ã™ã€‚ +デフォルトã§ã¯å…¥åŠ›ãƒ†ã‚­ã‚¹ãƒˆãŒå«ã¾ã‚Œã‚‹è¡ŒãŒæŠ½å‡ºã•れã¾ã™ã€‚ +ä»¥ä¸‹ã®æ¼”ç®—å­ã«ã‚‚対応ã—ã¦ã„ã¾ã™ã€‚: +% ワイルドカード +> より大ãã„ +< 未満 +>= 以上 +<= 以下 += ç­‰ã—ã„: 完全ã«ä¸€è‡´ +<> ç­‰ã—ããªã„: ä¸ä¸€è‡´ +x~y 範囲: xã¨yã®é–“ +/regexp/ æ­£è¦è¡¨ç¾ã«ä¸€è‡´ã™ã‚‹å€¤ + + + + Set Filter Expression + フィルターå¼ã‚’設定 + + + + What's This? + ã“れã¯ä½•? + + + + Is NULL + NULL + + + + Is not NULL + NULLã§ãªã„ + + + + Is empty + 空文字 + + + + Is not empty + 空文字ã§ãªã„ + + + + Not containing... + å«ã¾ãªã„... + + + + Equal to... + ç­‰ã—ã„... + + + + Not equal to... + ç­‰ã—ããªã„... + + + + Greater than... + より大ãã„... + + + + Less than... + 未満... + + + + Greater or equal... + 以上... + + + + Less or equal... + 以下... + + + + In range... + 範囲内... + + + + Regular expression... + æ­£è¦è¡¨ç¾... + + + + Clear All Conditional Formats + ã™ã¹ã¦ã®æ¡ä»¶ä»˜ã書å¼ã‚’削除 + + + + Use for Conditional Format + æ¡ä»¶ä»˜ã書å¼ã‚’使ㆠ+ + + + Edit Conditional Formats... + æ¡ä»¶ä»˜ã書å¼ã‚’編集... + + + + FindReplaceDialog + + + Find and Replace + 検索ã¨ç½®æ› + + + + Fi&nd text: + 検索文字列(&N): + + + + Re&place with: + ç½®æ›æ–‡å­—列(&P): + + + + Match &exact case + 大/å°æ–‡å­—を区別(&E) + + + + Match &only whole words + å˜èªžä¸€è‡´ã®ã¿(&O) + + + + When enabled, the search continues from the other end when it reaches one end of the page + 有効ã«ã™ã‚‹ã¨ã€ãƒšãƒ¼ã‚¸ã®æœ€å¾Œã«åˆ°é”ã™ã‚‹ã¨å…ˆé ­ã«æˆ»ã£ã¦æ¤œç´¢ã—ã¾ã™ + + + + &Wrap around + 折り返ã—ã‚り(&W) + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + 設定ã™ã‚‹ã¨ã‚«ãƒ¼ã‚½ãƒ«ä½ç½®ã‹ã‚‰æˆ»ã£ã¦æ¤œç´¢ã—ã¾ã™ã€‚設定ã—ãªã„ã¨ã‚«ãƒ¼ã‚½ãƒ«ä½ç½®ã®å…ˆã‚’検索ã—ã¾ã™ + + + + Search &backwards + 戻ã£ã¦æ¤œç´¢(&B) + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>設定ã™ã‚‹ã¨ã€ç¾åœ¨é¸æŠžã—ãŸç¯„囲ã®ã¿ã‚’検索ã—ã¾ã™ã€‚</p></body></html> + + + + &Selection only + é¸æŠžç¯„å›²ã®ã¿(&S) + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + URLã®ãŸã‚%ã®æ•°ã¯ä¸€è‡´ã—ãªã„ + <html><head/><body><p>設定ã™ã‚‹ã¨ã€æ¤œç´¢æ¡ä»¶ã¯UNIXæ­£è¦è¡¨ç¾ã¨è§£é‡ˆã•れã¾ã™ã€‚以下をå‚ç…§ <a href="https://ja.wikibooks.org/wiki/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE">Wikibooksã®æ­£è¦è¡¨ç¾</a>。</p></body></html> + + + + Use regular e&xpressions + æ­£è¦è¡¨ç¾ã‚’使用(&X) + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + カーソルä½ç½®ã‹ã‚‰"戻ã£ã¦æ¤œç´¢"ã§è¨­å®šã—ãŸæ–¹å‘ã«ã‚ã‚‹ã€æ¬¡ã«ä¸€è‡´ã™ã‚‹æ–‡å­—列を検索ã—ã¾ã™ + + + + &Find Next + 次を検索(&F) + + + + F3 + + + + + &Replace + ç½®æ›(&R) + + + + Highlight all the occurrences of the text in the page + ページ内ã®ã™ã¹ã¦ã®ä¸€è‡´ã™ã‚‹æ–‡å­—列を強調 + + + + F&ind All + ã™ã¹ã¦æ¤œç´¢(&I) + + + + Replace all the occurrences of the text in the page + ページ内ã®ã™ã¹ã¦ã®ä¸€è‡´ã™ã‚‹æ–‡å­—åˆ—ã‚’ç½®æ› + + + + Replace &All + ã™ã¹ã¦ç½®æ›(&A) + + + + The searched text was not found + 検索文字列ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—㟠+ + + + The searched text was not found. + 検索文字列ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚ + + + + The searched text was found one time. + 検索文字列ãŒ1ã¤ã‚りã¾ã—ãŸã€‚ + + + + The searched text was found %1 times. + 検索文字列ãŒ%1ã¤ã‚りã¾ã—ãŸã€‚ + + + + The searched text was replaced one time. + 検索文字列を1ã¤ç½®ãæ›ãˆã¾ã—ãŸã€‚ + + + + The searched text was replaced %1 times. + 検索文字列を%1ã¤ç½®ãæ›ãˆã¾ã—ãŸã€‚ + + + + ForeignKeyEditor + + + &Reset + リセット(&R) + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + 外部キー節 (ON UPDATE, ON DELETE ãªã©ã€‚) + + + + ImageViewer + + + Image Viewer + ç”»åƒãƒ“ューアー + + + + Reset the scaling to match the original size of the image. + ç”»åƒã®å…ƒã®ã‚µã‚¤ã‚ºã«åˆã‚ã›ã¦æ‹¡å¤§çŽ‡ã‚’ãƒªã‚»ãƒƒãƒˆã™ã‚‹ã€‚ + + + + Set the scaling to match the size of the viewport. + 拡大率を表示領域ã®ã‚µã‚¤ã‚ºã«åˆã‚ã›ã‚‹ã€‚ + + + + Print... + å°åˆ·... + + + + Open preview dialog for printing displayed image + 表示ã•れãŸç”»åƒã‚’å°åˆ·ã™ã‚‹ãƒ—レビューダイアログを開ã + + + + Ctrl+P + + + + + ImportCsvDialog + + + Import CSV file + CSVファイルをインãƒãƒ¼ãƒˆ + + + + Table na&me + テーブルå(&M) + + + + &Column names in first line + 先頭行をカラムåã«(&C) + + + + Field &separator + フィールド区切り(&S) + + + + , + , + + + + ; + ; + + + + + Tab + タブ + + + + | + | + + + + Other + ãã®ä»– + + + + &Quote character + 引用符文字(&Q) + + + + + Other (printable) + ãã®ä»– (å°åˆ·å¯èƒ½) + + + + + Other (code) + ãã®ä»– (文字コード) + + + + " + " + + + + ' + ' + + + + &Encoding + エンコード(&E) + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Trim fields? + フィールドをトリムã™ã‚‹? + + + + Separate tables + テーブルを分ã‘ã‚‹ + + + + Advanced + 高度ãªè¨­å®š + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + 空値をCSVファイルã‹ã‚‰æ—¢å­˜ã®ãƒ†ãƒ¼ãƒ–ルã®ãƒ‡ãƒ•ォルト値ãŒã‚るカラムã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ã¨ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå€¤ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションを有効ã«ã™ã‚‹ã¨ä»£ã‚りã«ç©ºå€¤ãŒæŒ¿å…¥ã•れã¾ã™ã€‚ + + + + Ignore default &values + デフォルト値を無視(&V) + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + ã“ã®ã‚ªãƒ—ションを有効ã«ã™ã‚‹ã¨ã€ãƒ‡ãƒ•ォルト値ãŒãªã NOT NULL ãªã‚«ãƒ©ãƒ ã«ç©ºå€¤ã‚’インãƒãƒ¼ãƒˆã—よã†ã¨ã—ãŸã¨ãã«ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã‚’中止ã—ã¾ã™ã€‚ + + + + Fail on missing values + 値ãŒãªã„å ´åˆä¸­æ­¢ + + + + Disable data type detection + データ型検出を無効 + + + + Disable the automatic data type detection when creating a new table. + æ–°ã—ã„テーブルを作るã¨ãã«è‡ªå‹•データ型検出を無効ã«ã—ã¾ã™ã€‚ + + + + Use local number conventions + åœ°åŸŸã®æ•°å€¤å¤‰æ›ã‚’使用 + + + + Use decimal and thousands separators according to the system locale. + システムã®åœ°åŸŸè¨­å®šã«å¾“ã„ã€å°æ•°ç‚¹ã¨æ¡åŒºåˆ‡ã‚Šã‚’使用ã™ã‚‹ã€‚ + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + 主キーã€ä¸€æ„性制約ã€ä¸€æ„ãªã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãŒã‚る既存ã®ãƒ†ãƒ¼ãƒ–ルã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ã¨ã€ç«¶åˆãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションã§ã€ç«¶åˆã®è§£æ±ºæ–¹æ³•ã‚’é¸æŠžã§ãã¾ã™ã€‚デフォルトã§ã¯ã‚¤ãƒ³ãƒãƒ¼ãƒˆã‚’中止ã—ロールãƒãƒƒã‚¯ã—ã¾ã™ãŒã€ç„¡è¦–ã‚’é¸æŠžã—ã¦ç«¶åˆã—ãŸè¡Œã‚’インãƒãƒ¼ãƒˆã—ãªã„ã€ã‚‚ã—ãã¯ã€ãƒ†ãƒ¼ãƒ–ãƒ«å†…ã®æ—¢å­˜ã®è¡Œã‚’ç½®ãæ›ãˆã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ + + + + Abort import + インãƒãƒ¼ãƒˆã‚’中止 + + + + Ignore row + 行を無視 + + + + Replace existing row + 既存ã®è¡Œã‚’ç½®ãæ›ãˆ + + + + Conflict strategy + ç«¶åˆã®è§£æ±ºæ–¹æ³• + + + + + Deselect All + ã™ã¹ã¦éžé¸æŠž + + + + Match Similar + 類似ã«ä¸€è‡´ + + + + Select All + ã™ã¹ã¦é¸æŠž + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + åå‰ãŒ '%1' ã®ãƒ†ãƒ¼ãƒ–ãƒ«ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚既存ã®ãƒ†ãƒ¼ãƒ–ルã¸ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã¯ã‚«ãƒ©ãƒ ã®æ•°ãŒä¸€è‡´ã™ã‚‹å ´åˆã®ã¿å¯èƒ½ã§ã™ã€‚ + + + + There is already a table named '%1'. Do you want to import the data into it? + åå‰ãŒ '%1' ã®ãƒ†ãƒ¼ãƒ–ãƒ«ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚データをã“れã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ã¾ã™ã‹? + + + + Creating restore point failed: %1 + 復元ãƒã‚¤ãƒ³ãƒˆã®ä½œæˆã«å¤±æ•—: %1 + + + + Creating the table failed: %1 + テーブルã®ä½œæˆã«å¤±æ•—: %1 + + + + importing CSV + CSVã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ + + + + Could not prepare INSERT statement: %1 + INSERT文を準備ã§ãã¾ã›ã‚“ã§ã—ãŸ: %1 + + + + Inserting row failed: %1 + è¡Œã®æŒ¿å…¥ã«å¤±æ•—: %1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + 予想外ã®EoF。正ã—ãクォートã•れã¦ã„ã‚‹ã‹ã€ãƒ•ァイル形å¼ãŒä¸æ­£ã§ãªã„ã‹ç¢ºèªã—ã¦ãã ã•ã„。 + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + ファイル '%1' ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã« %2msã‹ã‹ã‚Šã¾ã—ãŸã€‚内 %3ms ã¯è¡Œé–¢æ•°ã«è²»ã‚„ã•れã¾ã—ãŸã€‚ + + + + MainWindow + + + DB Browser for SQLite + DB Browser for SQLite + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + ã“れã¯é–‹ã„ã¦ã„ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ§‹é€ ã§ã™ã€‚ +SQL文をオブジェクト行ã‹ã‚‰ãƒ‰ãƒ©ãƒƒã‚°ã—ã»ã‹ã®ã‚¢ãƒ—リケーションや'DB Browser for SQLite'ã®ä»–ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã«ãƒ‰ãƒ­ãƒƒãƒ—ã§ãã¾ã™ã€‚ + + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + 警告: ã“ã®ãƒ—ラグマã¯èª­ã¿å–りå¯èƒ½ã§ãªãã€ã“ã®å€¤ã¯æŽ¨å®šã§ã™ã€‚プラグマを書ã込んã§ã‚‚ã€SQLite æ‹¡å¼µãªã©ã§ä¸Šæ›¸ãã•れるã‹ã‚‚ã—れã¾ã›ã‚“。 + + + + toolBar1 + ツールãƒãƒ¼1 + + + + &File + ファイル(&F) + + + + &Import + インãƒãƒ¼ãƒˆ(&I) + + + + &Export + エクスãƒãƒ¼ãƒˆ(&E) + + + + &Edit + 編集(&E) + + + + &View + ビュー(&V) + + + + &Help + ヘルプ(&H) + + + + Too&ls + ツール(&L) + + + + DB Toolbar + DBツールãƒãƒ¼ + + + + Edit Database &Cell + データベースã®ã‚»ãƒ«ã‚’編集(&C) + + + + SQL &Log + SQLログ(&L) + + + + Show S&QL submitted by + 表示ã™ã‚‹SQLã®é€ä¿¡å…ƒã¯(&Q) + + + + User + ユーザー + + + + Application + アプリケーション + + + + Error Log + エラーログ + + + + This button clears the contents of the SQL logs + ã“ã®ãƒœã‚¿ãƒ³ã§SQLログã®å†…容を消去ã—ã¾ã™ + + + + &Clear + 消去(&C) + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + ã“ã®ãƒ‘ãƒãƒ«ã§ã‚¢ãƒ—リケーションやã‚ãªãŸãŒç™ºè¡Œã—ãŸå…¨ã¦ã®SQLコマンドã®ãƒ­ã‚°ã‚’調査ã§ãã¾ã™ + + + + &Plot + プロット(&P) + + + + DB Sche&ma + DBスキーマ(&M) + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + ã“れã¯é–‹ã„ã¦ã„ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ§‹é€ ã§ã™ã€‚ +複数ã®ã‚ªãƒ–ジェクトåã‚’åå‰ã‚«ãƒ©ãƒ ã‹ã‚‰ãƒ‰ãƒ©ãƒƒã‚°ã—SQLエディターã«ãƒ‰ãƒ­ãƒƒãƒ—ã§ãã¾ã™ã€‚ドロップã—ãŸåå‰ã®ãƒ—ロパティã¯ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆãƒ¡ãƒ‹ãƒ¥ãƒ¼ã§èª¿ç¯€ã§ãã¾ã™ã€‚ã“れã¯SQLæ–‡ã®ä½œæˆã«å½¹ç«‹ã¡ã¾ã™ã€‚ +SQL文をスキーマカラムã‹ã‚‰SQLエディターや他ã®ã‚¢ãƒ—リケーションã«ãƒ‰ãƒ­ãƒƒãƒ—ã§ãã¾ã™ã€‚ + + + + + &Remote + リモート(&R) + + + + + Project Toolbar + プロジェクトツールãƒãƒ¼ + + + + Extra DB toolbar + 追加DBツールãƒãƒ¼ + + + + + + Close the current database file + ç¾åœ¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを閉ã˜ã¾ã™ + + + + &New Database... + æ–°ã—ã„データベース(&N)... + + + + + Create a new database file + æ–°ã—ã„データベースファイルを作æˆã—ã¾ã™ + + + + This option is used to create a new database file. + ã“ã®ã‚ªãƒ—ã‚·ãƒ§ãƒ³ã¯æ–°ã—ã„データベースファイルを作æˆã™ã‚‹ãŸã‚ã«ä½¿ã„ã¾ã™ã€‚ + + + + Ctrl+N + + + + + + &Open Database... + データベースを開ã(&O)... + + + + + + + + Open an existing database file + 既存ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを開ãã¾ã™ + + + + + + This option is used to open an existing database file. + ã“ã®ã‚ªãƒ—ã‚·ãƒ§ãƒ³ã¯æ—¢å­˜ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを開ããŸã‚ã«ä½¿ã„ã¾ã™ã€‚ + + + + Ctrl+O + + + + + &Close Database + データベースを閉ã˜ã‚‹(&C) + + + + This button closes the connection to the currently open database file + ã“ã®ãƒœã‚¿ãƒ³ã§ç¾åœ¨é–‹ã„ã¦ã„るデータベースファイルã¨ã®æŽ¥ç¶šã‚’é–‰ã˜ã¾ã™ + + + + New &tab + æ–°ã—ã„タブ(&T) + + + + Open SQL file(s) + SQLファイルを開ã + + + + This button opens files containing SQL statements and loads them in new editor tabs + ã“ã®ãƒœã‚¿ãƒ³ã¯SQL文をå«ã‚€ãƒ•ァイルを開ãã€æ–°ã—ã„編集タブã«èª­ã¿è¾¼ã¿ã¾ã™ + + + + Execute line + 行を実行 + + + + Sa&ve Project + プロジェクトをä¿å­˜(&V) + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + ã“ã®ãƒœã‚¿ãƒ³ã¯DBã‚’é–‹ãã“ã¨ã«é–¢ä¿‚ã™ã‚‹ã™ã¹ã¦ã®è¨­å®šã‚’DB Browser for SQLite プロジェクトファイルã«ä¿å­˜ã—ã¾ã™ + + + + This button lets you open a DB Browser for SQLite project file + ã“ã®ãƒœã‚¿ãƒ³ã¯DB Browser for SQLite プロジェクトファイルを開ãã¾ã™ + + + + Ctrl+Shift+O + + + + + Find + 検索 + + + + Find or replace + 検索ã¨ç½®æ› + + + + Print text from current SQL editor tab + ç¾åœ¨ã®SQLエディタータブã®ãƒ†ã‚­ã‚¹ãƒˆã‚’å°åˆ·ã—ã¾ã™ + + + + Print the structure of the opened database + é–‹ã„ã¦ã„ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ§‹é€ ã‚’å°åˆ·ã—ã¾ã™ + + + + Un/comment block of SQL code + SQLコードã®ãƒ–ロックをコメント/éžã‚³ãƒ¡ãƒ³ãƒˆã« + + + + Un/comment block + ブロックをコメント/éžã‚³ãƒ¡ãƒ³ãƒˆ + + + + Comment or uncomment current line or selected block of code + ç¾åœ¨è¡Œã‹ã‚³ãƒ¼ãƒ‰ã®é¸æŠžã•れãŸãƒ–ロックをコメント/éžã‚³ãƒ¡ãƒ³ãƒˆã«ã—ã¾ã™ + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + é¸æŠžã•れãŸè¡Œã‹ã€é¸æŠžãŒãªã„ãªã‚‰ã°ç¾åœ¨è¡Œã‚’コメント/éžã‚³ãƒ¡ãƒ³ãƒˆã«ã—ã¾ã™ã€‚ブロック全体ã¯ãã®å…ˆé ­è¡Œã«å¾“ã„コメント/éžã‚³ãƒ¡ãƒ³ãƒˆã•れã¾ã™ã€‚ + + + + Ctrl+/ + + + + + Stop SQL execution + SQLã®å®Ÿè¡Œã‚’中止 + + + + Stop execution + 実行を中止 + + + + Stop the currently running SQL script + ç¾åœ¨å®Ÿè¡Œä¸­ã® SQL スクリプトを中止ã—ã¾ã™ + + + + &Save Project As... + プロジェクトã«åå‰ã‚’付ã‘ã¦ä¿å­˜(&S)... + + + + + + Save the project in a file selected in a dialog + ダイアログã§é¸æŠžã—ãŸãƒ•ァイルã«ãƒ—ロジェクトをä¿å­˜ã—ã¾ã™ + + + + Save A&ll + ã™ã¹ã¦ä¿å­˜(&L) + + + + + + Save DB file, project file and opened SQL files + DBファイルã€ãƒ—ロジェクトファイルã€é–‹ã„ã¦ã„ã‚‹SQLファイルをä¿å­˜ã—ã¾ã™ + + + + Ctrl+Shift+S + + + + + Browse Table + テーブルを閲覧 + + + + Close Pro&ject + プロジェクトを閉ã˜ã‚‹(&J) + + + + + Close project and database files and return to the initial state + プロジェクトã¨ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‰ã˜ã¦åˆæœŸçŠ¶æ…‹ã«æˆ»ã—ã¾ã™ + + + + Ctrl+Shift+F4 + + + + + + Detach Database + データベースを切断 + + + + + Detach database file attached to the current database connection + ç¾åœ¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹æŽ¥ç¶šã‹ã‚‰ä½¿ç”¨ä¸­ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを切り離ã—ã¾ã™ + + + + + Ctrl+W + + + + + &Revert Changes + 変更をå–り消ã—(&R) + + + + + Revert database to last saved state + 最後ã«ä¿å­˜ã—ãŸçŠ¶æ…‹ã¸ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’戻ã—ã¾ã™ + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + ã“ã®ã‚ªãƒ—ションã¯ç¾åœ¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを最後ã«ä¿å­˜ã—ãŸçŠ¶æ…‹ã«æˆ»ã™ãŸã‚ã«ä½¿ã„ã¾ã™ã€‚最後ã®ä¿å­˜ã®å¾Œã«è¡Œã‚れãŸã™ã¹ã¦ã®å¤‰æ›´ã¯å¤±ã‚れã¾ã™ã€‚ + + + + &Write Changes + 変更を書ãè¾¼ã¿(&W) + + + + + Write changes to the database file + データベースファイルã«å¤‰æ›´ã‚’書ãè¾¼ã¿ã¾ã™ + + + + This option is used to save changes to the database file. + ã“ã®ã‚ªãƒ—ションã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã«å¤‰æ›´ã‚’ä¿å­˜ã™ã‚‹ãŸã‚ã«ä½¿ã„ã¾ã™ã€‚ + + + + Ctrl+S + + + + + Compact &Database... + データベースを圧縮(&D)... + + + + Compact the database file, removing space wasted by deleted records + 削除ã•れãŸãƒ¬ã‚³ãƒ¼ãƒ‰ãŒæ®‹ã£ã¦ã„るスペースをå–り除ãã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを圧縮ã—ã¾ã™ + + + + + Compact the database file, removing space wasted by deleted records. + 削除ã•れãŸãƒ¬ã‚³ãƒ¼ãƒ‰ãŒæ®‹ã£ã¦ã„るスペースをå–り除ãã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを圧縮ã—ã¾ã™ã€‚ + + + + E&xit + 終了(&X) + + + + Ctrl+Q + + + + + &Database from SQL file... + SQLファイルã‹ã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¸(&D)... + + + + Import data from an .sql dump text file into a new or existing database. + SQLダンプテキストファイルã‹ã‚‰ãƒ‡ãƒ¼ã‚¿ã‚’ã€æ–°ã—ã„ã‚‚ã—ãã¯æ—¢å­˜ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚ + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + ã“ã®ã‚ªãƒ—ションã§SQLダンプテキストファイルã‹ã‚‰ãƒ‡ãƒ¼ã‚¿ã‚’ã€æ–°ã—ã„ã‚‚ã—ãã¯æ—¢å­˜ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ãã¾ã™ã€‚SQLダンプファイルã¯ã€MySQLã‚„PostgreSQLãªã©ã€ã»ã¨ã‚“ã©ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚¨ãƒ³ã‚¸ãƒ³ã§ä½œæˆã§ãã¾ã™ã€‚ + + + + &Table from CSV file... + CSVファイルã‹ã‚‰ãƒ†ãƒ¼ãƒ–ルã¸(&T)... + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + カンマ区切りã®ãƒ†ã‚­ã‚¹ãƒˆãƒ•ァイルã®ãƒ‡ãƒ¼ã‚¿ã‚’データベースã®ãƒ†ãƒ¼ãƒ–ルã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã‚’é–‹ãã¾ã™ã€‚ + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + カンマ区切りã®ãƒ†ã‚­ã‚¹ãƒˆãƒ•ァイルã®ãƒ‡ãƒ¼ã‚¿ã‚’データベースã®ãƒ†ãƒ¼ãƒ–ルã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã‚’é–‹ãã¾ã™ã€‚CSVファイルã¯ã»ã¨ã‚“ã©ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚„表計算アプリケーションã§ä½œæˆã§ãã¾ã™ã€‚ + + + + &Database to SQL file... + データベースをSQLファイルã¸(&D)... + + + + Export a database to a .sql dump text file. + データベースを .sql ダンプテキストファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚ + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + ã“ã®ã‚ªãƒ—ションã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’ .sql ダンプテキストファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã§ãã¾ã™ã€‚SQLダンプファイルã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å†ä½œæˆã«å¿…è¦ãªã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’å«ã¿ã€MySQLã‚„PostgreSQLãªã©ã€ã»ã¨ã‚“ã©ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚¨ãƒ³ã‚¸ãƒ³ã§åˆ©ç”¨ã§ãã¾ã™ã€‚ + + + + &Table(s) as CSV file... + テーブルをCSVファイルã¸(&T)... + + + + Export a database table as a comma separated text file. + データベースã®ãƒ†ãƒ¼ãƒ–ルをカンマ区切りã®ãƒ†ã‚­ã‚¹ãƒˆãƒ•ァイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚ + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + データベースã®ãƒ†ãƒ¼ãƒ–ルをカンマ区切りã®ãƒ†ã‚­ã‚¹ãƒˆãƒ•ァイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚ä»–ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚„表計算アプリケーションã§ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ãã¾ã™ã€‚ + + + + &Create Table... + テーブルを作æˆ(&C)... + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ–°ã—ã„テーブルã®åå‰ã¨ãƒ•ィールドを定義ã§ãã‚‹ã€ãƒ†ãƒ¼ãƒ–ル作æˆã‚¦ã‚¤ã‚¶ãƒ¼ãƒ‰ã‚’é–‹ãã¾ã™ + + + + &Delete Table... + テーブルを削除(&D)... + + + + + Delete Table + テーブルを削除 + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + 削除ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ†ãƒ¼ãƒ–ãƒ«ã‚’é¸æŠžã§ãã‚‹ã€ãƒ†ãƒ¼ãƒ–ル削除ウィザードをã²ã‚‰ãã¾ã™ã€‚ + + + + &Modify Table... + テーブルを変更(&M)... + + + + Create &Index... + インデックスã®ä½œæˆ(&I)... + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + 既存ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ†ãƒ¼ãƒ–ãƒ«ã«æ–°ã—ã„インデックスを定義ã§ãã‚‹ã€ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã‚’é–‹ãã¾ã™ã€‚ + + + + &Preferences... + 設定(&P)... + + + + + Open the preferences window. + 設定ウィンドウを開ãã¾ã™ã€‚ + + + + &DB Toolbar + DBツールãƒãƒ¼(&D) + + + + Shows or hides the Database toolbar. + データベースツールãƒãƒ¼ã‚’表示/éžè¡¨ç¤ºã—ã¾ã™ã€‚ + + + + Ctrl+T + + + + + W&hat's This? + ã“れã¯ä½•(&H)? + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + データベース構造(&D) + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + データ閲覧(&B) + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + プラグマ編集(&R) + + + + Temp Store + 一時ä¿ç®¡ + + + + Secure Delete + セキュアãªå‰Šé™¤ + + + + Case Sensitive Like + å¤§æ–‡å­—å°æ–‡å­—を区別ã—ãŸLike + + + + Journal Mode + ジャーナルモード + + + + Journal Size Limit + ã‚¸ãƒ£ãƒ¼ãƒŠãƒ«ã‚µã‚¤ã‚ºä¸Šé™ + + + + Recursive Triggers + å†å¸°ãƒˆãƒªã‚¬ãƒ¼ + + + + Delete + pragma + 削除 + + + + Truncate + pragma + 切りæ¨ã¦ + + + + Persist + pragma + ä¿æŒ + + + + Memory + pragma + メモリー + + + + WAL + pragma + WAL + + + + + Off + pragma + オフ + + + + Page Size + ページサイズ + + + + Foreign Keys + 外部キー + + + + Auto Vacuum + 自動開放 + + + + Max Page Count + 最大ページ数 + + + + Normal + pragma + 通常 + + + + Exclusive + pragma + 排他 + + + + Checkpoint Full FSYNC + ãƒã‚§ãƒƒã‚¯ãƒã‚¤ãƒ³ãƒˆã§å®Œå…¨ãª FSYNC を行ㆠ+ + + + Off + オフ + + + + Normal + 通常 + + + + + Full + 完全 + + + + Default + デフォルト + + + + File + ファイル + + + + Memory + メモリー + + + + Automatic Index + 自動的ãªã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ + + + + Ignore Check Constraints + ãƒã‚§ãƒƒã‚¯åˆ¶ç´„を無視 + + + + Full FSYNC + 完全㪠FSYNC + + + + WAL Auto Checkpoint + WAL ã®è‡ªå‹•ãƒã‚§ãƒƒã‚¯ãƒã‚¤ãƒ³ãƒˆ + + + + User Version + ユーザーãƒãƒ¼ã‚¸ãƒ§ãƒ³ + + + + Synchronous + åŒæœŸ + + + + None + ãªã— + + + + Incremental + インクリメンタル + + + + Locking Mode + ロックモード + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + SQL実行(&X) + + + + &Recent Files + 最近使用ã—ãŸãƒ•ァイル(&R) + + + + &New Database + æ–°ã—ã„データベース(&N) + + + + + Ctrl+F4 + + + + + &Undo + å…ƒã«æˆ»ã™(&U) + + + + + Undo last change to the database + データベースã¸ã®æœ€å¾Œã®å¤‰æ›´ã‚’å…ƒã«æˆ»ã—ã¾ã™ + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + ã“ã®æ“作ã¯ãƒ‡ãƒ¼ã‚¿é–²è¦§ã‹SQLå®Ÿè¡Œã§æœ€å¾Œã«è¡Œã£ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¸ã®å¤‰æ›´ã‚’å…ƒã«æˆ»ã—ã¾ã™ã€‚やり直ã—ã¯ã§ãã¾ã›ã‚“。 + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + 既存ã®ãƒ†ãƒ¼ãƒ–ルåを変更ã§ãるテーブル変更ウィザードを開ãã¾ã™ã€‚ã“れã¯ãƒ†ãƒ¼ãƒ–ルã«å¯¾ã—フィ―ルドã®è¿½åŠ ã‚„å‰Šé™¤ã€ãƒ•ィールドåやデータ型ã®å¤‰æ›´ãŒã§ãã¾ã™ã€‚ + + + + Shift+F1 + + + + + &About + DB Browser for SQLite ã«ã¤ã„ã¦(&A) + + + + &Recently opened + 最近開ã„ãŸãƒ•ァイル(&R) + + + + This button opens a new tab for the SQL editor + ã“ã®ãƒœã‚¿ãƒ³ã§SQLã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã®æ–°ã—ã„タブを開ãã¾ã™ + + + + &Execute SQL + SQL実行(&E) + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + ã“ã®ãƒœã‚¿ãƒ³ã§ç¾åœ¨é¸æŠžã—ã¦ã„ã‚‹SQL文を実行ã—ã¾ã™ã€‚テキストãŒé¸æŠžã•れã¦ã„ãªã„å ´åˆã€ã™ã¹ã¦ã®SQLæ–‡ãŒå®Ÿè¡Œã•れã¾ã™ã€‚ + + + + Ctrl+Shift+T + + + + + + + Save SQL file + SQLファイルをä¿å­˜ + + + + &Load Extension... + 拡張を読ã¿è¾¼ã¿(&L)... + + + + + Execute current line + ç¾åœ¨è¡Œã‚’実行 + + + + This button executes the SQL statement present in the current editor line + ã“ã®ãƒœã‚¿ãƒ³ã¯ç¾åœ¨ã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã®è¡Œã«ã‚ã‚‹SQL文を実行ã—ã¾ã™ + + + + Shift+F5 + + + + + Export as CSV file + CSVファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ + + + + Export table as comma separated values file + テーブルをカンマ区切りã®ãƒ•ァイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ + + + + &Wiki + ウィキ(&W) + + + + F1 + + + + + Bug &Report... + ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆ(&R)... + + + + Feature Re&quest... + æ©Ÿèƒ½ã‚’è¦æ±‚(&Q)... + + + + Web&site + ウェブサイト(&S) + + + + &Donate on Patreon... + Patreonã§å¯„付(&D)... + + + + &Save Project + プロジェクトをä¿å­˜(&S) + + + + + Save the current session to a file + ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’ファイルã«ä¿å­˜ã—ã¾ã™ + + + + Open &Project... + プロジェクトを開ã(&P)... + + + + Open &Project + プロジェクトを開ã(&P) + + + + + Load a working session from a file + 作業中ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’ファイルã‹ã‚‰èª­ã¿è¾¼ã¿ã¾ã™ + + + + &Attach Database... + ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æŽ¥ç¶š(&A)... + + + + + Add another database file to the current database connection + ä»–ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルをç¾åœ¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹æŽ¥ç¶šã«åŠ ãˆã¾ã™ + + + + This button lets you add another database file to the current database connection + ã“ã®ãƒœã‚¿ãƒ³ã§ä»–ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルをç¾åœ¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹æŽ¥ç¶šã«åŠ ãˆã¾ã™ + + + + &Set Encryption... + æš—å·åŒ–を設定(&S)... + + + + + Save SQL file as + åå‰ã‚’付ã‘ã¦SQLファイルをä¿å­˜ + + + + This button saves the content of the current SQL editor tab to a file + ã“ã®ãƒœã‚¿ãƒ³ã¯ç¾åœ¨ã®SQLエディタータブã®å†…容をファイルã«ä¿å­˜ã—ã¾ã™ + + + + &Browse Table + テーブルを閲覧(&B) + + + + Copy Create statement + CREATE文をコピー + + + + Copy the CREATE statement of the item to the clipboard + ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã®CREATE文をクリップボードã«ã‚³ãƒ”ーã—ã¾ã™ + + + + SQLCipher &FAQ + SQLCipher FAQ(&F) + + + + Opens the SQLCipher FAQ in a browser window + SQLCipher ã® FAQ をブラウザã§é–‹ãã¾ã™ + + + + Table(&s) to JSON... + テーブルをJSONã¸(&S)... + + + + Export one or more table(s) to a JSON file + 1ã¤ä»¥ä¸Šã®ãƒ†ãƒ¼ãƒ–ルをJSONファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ + + + + Open Data&base Read Only... + データベースを読ã¿å–り専用ã§é–‹ã(&B)... + + + + Open an existing database file in read only mode + 既存ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを読ã¿å–り専用モードã§é–‹ãã¾ã™ + + + + Save results + çµæžœã‚’ä¿å­˜ + + + + Save the results view + çµæžœã®ãƒ“ューをä¿å­˜ + + + + This button lets you save the results of the last executed query + ã“ã®ãƒœã‚¿ãƒ³ã§æœ€å¾Œã«å®Ÿè¡Œã—ãŸã‚¯ã‚¨ãƒªãƒ¼ã®çµæžœã‚’ä¿å­˜ã—ã¾ã™ + + + + + Find text in SQL editor + SQLã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã®æ–‡å­—列を検索 + + + + This button opens the search bar of the editor + ã“ã®ãƒœã‚¿ãƒ³ã¯ã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã®æ¤œç´¢ãƒãƒ¼ã‚’é–‹ãã¾ã™ + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + SQLã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã®æ–‡å­—列を検索/ç½®æ›ã—ã¾ã™ + + + + This button opens the find/replace dialog for the current editor tab + ã“ã®ãƒœã‚¿ãƒ³ã¯ç¾åœ¨ã®ã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã‚¿ãƒ–ã®æ¤œç´¢/ç½®æ›ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã‚’é–‹ãã¾ã™ + + + + Ctrl+H + + + + + Export to &CSV + CSVã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ(&C) + + + + Export to &JSON + JSONã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ(&J) + + + + Save as &view + ビューã¨ã—ã¦ä¿å­˜(&V) + + + + Save as view + ビューã¨ã—ã¦ä¿å­˜ + + + + Shows or hides the Project toolbar. + プロジェクトツールãƒãƒ¼ã‚’表示/éžè¡¨ç¤ºã—ã¾ã™ã€‚ + + + + Extra DB Toolbar + 追加DBツールãƒãƒ¼ + + + + &Open Database + データベースを開ã(&O) + + + + New In-&Memory Database + æ–°ã—ã„インメモリーデータベース(&M) + + + + Drag && Drop SELECT Query + SELECT クエリーをドラッグ&&ドロップ + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + åŒã˜ãƒ†ãƒ¼ãƒ–ルã€ã‚‚ã—ãã¯ã€å˜ç‹¬ã®ãƒ†ãƒ¼ãƒ–ルã‹ã‚‰ãƒ•ィールドをドラッグã™ã‚‹ã¨ã€ã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼å†…ã«SELECTクエリーãŒãƒ‰ãƒ­ãƒƒãƒ—ã—ã¾ã™ + + + + Drag && Drop Qualified Names + æ­£è¦åŒ–åå‰ã‚’ドラッグ&&ドロップ + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + オブジェクトをドラッグã—エディターã«ãƒ‰ãƒ­ãƒƒãƒ—ã—ãŸã¨ãã«ã€æ­£è¦åŒ–åç§°(例 "Table"."Field")を使ã„ã¾ã™ + + + + Drag && Drop Enquoted Names + クォートã•れãŸåå‰ã‚’ドラッグ&&ドロップ + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + オブジェクトをドラッグã—エディターã«ãƒ‰ãƒ­ãƒƒãƒ—ã—ãŸã¨ãã«ã€ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—ã•れãŸåå‰(例 "Table1")を使ã„ã¾ã™ + + + + &Integrity Check + æ•´åˆæ€§æ¤œæŸ»(&I) + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + é–‹ã„ã¦ã„ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ•´åˆæ€§æ¤œæŸ»ãƒ—ラグマを実行ã—ã€çµæžœã‚’SQL実行タブã«å‡ºåŠ›ã—ã¾ã™ã€‚ã“ã®ãƒ—ラグマã¯ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ•´åˆæ€§æ¤œæŸ»ã‚’行ã„ã¾ã™ã€‚ + + + + &Foreign-Key Check + 外部キー検査(&F) + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + é–‹ã„ã¦ã„るデータベースã®å¤–部キー検査プラグマを実行ã—ã€çµæžœã‚’SQL実行タブã«å‡ºåŠ›ã—ã¾ã™ + + + + &Quick Integrity Check + 峿™‚æ•´åˆæ€§æ¤œæŸ»(&Q) + + + + Run a quick integrity check over the open DB + é–‹ã„ã¦ã„ã‚‹DBã®é«˜é€Ÿæ•´åˆæ€§æ¤œæŸ»ã‚’実行ã—ã¾ã™ + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + é–‹ã„ã¦ã„るデータベースã®é«˜é€Ÿæ•´åˆæ€§æ¤œæŸ»ãƒ—ラグマを実行ã—ã€çµæžœã‚’SQL実行タブã«å‡ºåŠ›ã—ã¾ã™ã€‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯(通常ã®)æ•´åˆæ€§æ¤œæŸ»PRAGMAã®å¤§éƒ¨åˆ†ã‚’行ã„ã¾ã™ãŒã€ã‚ˆã‚Šé«˜é€Ÿã«å‹•作ã—ã¾ã™ã€‚ + + + + &Optimize + 最é©åŒ–(&O) + + + + Attempt to optimize the database + ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æœ€é©åŒ–を試ã¿ã¾ã™ + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + é–‹ã„ã¦ã„ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æœ€é©åŒ–プラグマを実行ã—ã¾ã™ã€‚ã“ã®ãƒ—ラグマã¯å°†æ¥ã®ã‚¯ã‚¨ãƒªãƒ¼ã®æ€§èƒ½ã‚’改善ã•ã›ã¾ã™ã€‚ + + + + + Print + å°åˆ· + + + + Open a dialog for printing the text in the current SQL editor tab + ç¾åœ¨ã®SQLã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã‚¿ãƒ–ã®æ–‡å­—列をå°åˆ·ã™ã‚‹ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã‚’é–‹ãã¾ã™ + + + + Open a dialog for printing the structure of the opened database + é–‹ã„ã¦ã„ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ§‹é€ ã‚’å°åˆ·ã™ã‚‹ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã‚’é–‹ãã¾ã™ + + + + + Ctrl+Shift+W + + + + + Table from CSV data in Clipboard... + クリップボードã®CSVデータã‹ã‚‰ãƒ†ãƒ¼ãƒ–ル... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + ã“ã®å‡¦ç†ã¯ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—ボードã®å†…容をCSVファイルã¨ã¿ãªã—ã¦ã€å®Ÿéš›ã®CSVファイルã¨åŒã˜ã‚ˆã†ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã‚¦ã‚£ã‚¶ãƒ¼ãƒ‰ã‚’é–‹ãã¾ã™ã€‚ + + + + Show &Row Counts + 行数を表示(&R) + + + + This shows the number of rows for each table and view in the database. + データベース内ã«ã‚るテーブルã¨ãƒ“ューãれãžã‚Œã®è¡Œæ•°ã‚’表示ã—ã¾ã™ã€‚ + + + + Save Database &As... + åå‰ã‚’付ã‘ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’ä¿å­˜(&A)... + + + + Save the current database as a different file + ç¾åœ¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’別ã®ãƒ•ァイルã«ä¿å­˜ã—ã¾ã™ + + + + Refresh + æ›´æ–° + + + + Reload the database structure + データベース構造をå†èª­ã¿è¾¼ã¿ + + + + + Ctrl+P + + + + + Execute all/selected SQL + ã™ã¹ã¦/é¸æŠžã—ãŸSQLを実行 + + + + Ctrl+Return + + + + + Ctrl+L + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Ctrl+E + + + + + Reset Window Layout + ウィンドウレイアウトをリセット + + + + Ctrl+Tab + + + + + Ctrl+Shift+Tab + + + + + Clear List + リストを削除 + + + + Window Layout + ウィンドウレイアウト + + + + Ctrl+0 + + + + + Simplify Window Layout + ウィンドウレイアウトをシンプル㫠+ + + + Alt+Shift+0 + + + + + Dock Windows at Bottom + ウィンドウを下ã«ãƒ‰ãƒƒã‚­ãƒ³ã‚° + + + + Dock Windows at Left Side + ウィンドウを左ã«ãƒ‰ãƒƒã‚­ãƒ³ã‚° + + + + Dock Windows at Top + ウィンドウを上ã«ãƒ‰ãƒƒã‚­ãƒ³ã‚° + + + + The database is currently busy. + データベースã¯ç¾åœ¨ãƒ“ジー状態ã§ã™ã€‚ + + + + Click here to interrupt the currently running query. + ã“ã“をクリックã—ã¦ã€ç¾åœ¨å®Ÿè¡Œä¸­ã®ã‚¯ã‚¨ãƒªãƒ¼ã‚’中断ã—ã¾ã™ã€‚ + + + + Encrypted + æš—å·åŒ– + + + + Database is encrypted using SQLCipher + データベースã¯SQLCipherã§æš—å·åŒ–ã•れã¦ã„ã¾ã™ + + + + Read only + 読ã¿å–り専用 + + + + Database file is read only. Editing the database is disabled. + データベースã¯èª­ã¿å–り専用ã§ã™ã€‚データベースã®ç·¨é›†ã¯ã§ãã¾ã›ã‚“。 + + + + Database encoding + データベースã®ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ + + + + Alt+Shift+W + + + + + + Choose a database file + ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž + + + + Could not open database file. +Reason: %1 + データベースファイルを開ã‘ã¾ã›ã‚“。 +ç†ç”±: %1 + + + + + + Choose a filename to save under + ä¿å­˜ã™ã‚‹ãƒ•ァイルåを下ã‹ã‚‰é¸æŠž + + + + In-Memory database + インメモリーデータベース + + + + Choose a database file to save under + ä¿å­˜ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを下ã‹ã‚‰é¸æŠž + + + + Error while saving the database to the new file. + データベースを新ã—ã„ファイルã¸ä¿å­˜æ™‚ã«ã‚¨ãƒ©ãƒ¼ã€‚ + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + ã¾ã SQL文を実行中ã§ã™ã€‚今ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‰ã˜ã‚‹ã¨ã€å®Ÿè¡ŒãŒä¸­æ­¢ã•れã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ä¸€è²«æ€§ãŒãªã„状態を残ã™ã‹ã‚‚ã—れã¾ã›ã‚“。本当ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‰ã˜ã¾ã™ã‹? + + + + Edit View %1 + ビューを編集 %1 + + + + Edit Trigger %1 + トリガーを編集 %1 + + + + Opened '%1' in read-only mode from recent file list + 最近使ã£ãŸãƒ•ァイルリストã‹ã‚‰èª­ã¿å–り専用モード㧠'%1' ã‚’é–‹ãã¾ã—㟠+ + + + Opened '%1' from recent file list + 最近使ã£ãŸãƒ•ァイルリストã‹ã‚‰ '%1' ã‚’é–‹ãã¾ã—㟠+ + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + ドロップã•れãŸãƒ•ァイルã«å¯¾ã—ã¦è¡Œã†æ“ä½œã‚’é¸æŠžã—ã¦ãã ã•ã„。 <br/>注æ„: 'インãƒãƒ¼ãƒˆ' ã®ã¿ãŒè¤‡æ•°ãƒ•ァイルを処ç†ã§ãã¾ã™ã€‚ + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + タブ '%1' ã®æ–‡ã¯ã¾ã å®Ÿè¡Œä¸­ã§ã™ã€‚タブを閉ã˜ã‚‹ã¨å®Ÿè¡ŒãŒåœæ­¢ã—ã¾ã™ã€‚ã“れã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ä¸€è²«æ€§ãŒãªããªã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚本当ã«ã‚¿ãƒ–ã‚’é–‰ã˜ã¾ã™ã‹? + + + + Could not find resource file: %1 + リソースファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“: %1 + + + + DB file '%1' could not be opened + DBファイル '%1' ã‚’é–‹ã‘ã¾ã›ã‚“ã§ã—㟠+ + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + ã“ã®ãƒ—ロジェクトファイルã¯DB Browser for SQLite ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 3.10 以å‰ã§ä½œã‚‰ã‚ŒãŸå¤ã„ファイルフォーマットを使用ã—ã¦ã„ã¾ã™ã€‚ã“ã®ãƒ•ァイルフォーマットã®èª­ã¿è¾¼ã¿ã¯æ—¢ã«å®Œå…¨ã«ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“。もã—完全ã«èª­ã¿è¾¼ã¿ãŸã„å ´åˆã¯ã€DB Browser for SQLite ãƒãƒ¼ã‚¸ãƒ§ãƒ³3.12 を使ã£ã¦æ–°ã—ã„ファイルフォーマットã«å¤‰æ›ã—ã¦ãã ã•ã„。 + + + + Table '%1' not found; settings ignored + テーブル '%1' ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“; 設定ã¯ç„¡è¦–ã•れã¾ã™ + + + + Could not open project file for writing. +Reason: %1 + 書ã込むプロジェクトファイルを開ãã“ã¨ãŒã§ãã¾ã›ã‚“。 +ç†ç”±: %1 + + + + -- Reference to file "%1" (not supported by this version) -- + -- ファイル "%1" ã¸ã®å‚ç…§ (ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“) -- + + + + Project saved to file '%1' + プロジェクトをファイル '%1' ã«ä¿å­˜ã—ã¾ã—㟠+ + + + Yes. Don't ask again + ã¯ã„。もã†èžã‹ãªã„ã§ + + + + This action will open a new SQL tab with the following statements for you to edit and run: + ã“ã®æ“作ã¯ä»¥ä¸‹ã®æ–‡ã‚’編集実行ã§ãã‚‹æ–°ã—ã„SQLタブを開ãã¾ã™: + + + + Busy (%1) + ビジー (%1) + + + + Rename Tab + タブåを変更 + + + + Duplicate Tab + タブを複製 + + + + Close Tab + タブを閉ã˜ã‚‹ + + + + Opening '%1'... + '%1' ã‚’é–‹ã„ã¦ã„ã¾ã™... + + + + There was an error opening '%1'... + '%1' ã‚’é–‹ãã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒã‚りã¾ã—ãŸ... + + + + Value is not a valid URL or filename: %1 + å€¤ã¯æ­£è¦ã®URLã‚‚ã—ãã¯ãƒ•ァイルåã§ã‚りã¾ã›ã‚“: %1 + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + 本当ã«ãƒ†ãƒ¼ãƒ–ル '%1' を削除ã—ã¾ã™ã‹? +テーブルã«é–¢é€£ã™ã‚‹ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã¯å¤±ã‚れã¾ã™ã€‚ + + + + Are you sure you want to delete the view '%1'? + 本当ã«ãƒ“ュー '%1' を削除ã—ã¾ã™ã‹? + + + + Are you sure you want to delete the trigger '%1'? + 本当ã«ãƒˆãƒªã‚¬ãƒ¼ '%1' を削除ã—ã¾ã™ã‹? + + + + Are you sure you want to delete the index '%1'? + 本当ã«ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ '%1' を削除ã—ã¾ã™ã‹? + + + + Error: could not delete the table. + エラー: テーブルを削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ + + + + Error: could not delete the view. + エラー: ビューを削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ + + + + Error: could not delete the trigger. + エラー: トリガーを削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ + + + + Error: could not delete the index. + エラー: インデックスを削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ + + + + Message from database engine: +%1 + データベースエンジンã‹ã‚‰ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã€‚ +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + テーブルã®ç·¨é›†ã«ã¯ä¿ç•™ä¸­ã®ã™ã¹ã¦ã®å¤‰æ›´ã‚’今ä¿å­˜ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚ +本当ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’ä¿å­˜ã—ã¾ã™ã‹? + + + + Error checking foreign keys after table modification. The changes will be reverted. + デーブル変更後ã®å¤–部キー検査ã§ã‚¨ãƒ©ãƒ¼ã€‚変更ã¯å…ƒã«æˆ»ã‚Šã¾ã™ã€‚ + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + ã“ã®ãƒ†ãƒ¼ãƒ–ルã¯å¤–部キー検査ã«åˆæ ¼ã—ã¾ã›ã‚“ã§ã—ãŸã€‚<br/>'ツール | 外部キー検査' を実行ã—ã€å ±å‘Šã•れãŸå•題を解決ã—ã¾ã™ã€‚ + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + SQLæ–‡ã¯æ—¢ã«å®Ÿè¡Œä¸­ã§ã™ã€‚替ã‚りã«ç¾åœ¨ã®æ–‡ã‚’実行ã™ã‚‹ãŸã‚ã€ä¸­æ­¢ã—ã¾ã™ã‹? 注æ„: ã“れã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ä¸€è²«æ€§ãŒãªã„状態を残ã™ã‹ã‚‚ã—れã¾ã›ã‚“。 + + + + -- EXECUTING SELECTION IN '%1' +-- + -- '%1 内ã®é¸æŠžéƒ¨åˆ†ã‚’実行中' +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- '%1 内ã®è¡Œã‚’実行中' +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- '%1 内をã™ã¹ã¦å®Ÿè¡Œä¸­' +-- + + + + Result: %1 + çµæžœ: %1 + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + PRAGMA 値ã®è¨­å®šã‚„ãƒã‚­ãƒ¥ãƒ¼ãƒ ã¯ç¾åœ¨ã®ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³ã‚’コミットã—ã¾ã™ã€‚ +本当ã«è¡Œã„ã¾ã™ã‹? + + + + %1 rows returned in %2ms + %1 行㌠%2ms ã§è¿”ã•れã¾ã—㟠+ + + + + At line %1: + %1 行目: + + + + Result: %2 + çµæžœ: %2 + + + + Choose text files + ãƒ†ã‚­ã‚¹ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + データベースã®ä¿å­˜ä¸­ã«ã‚¨ãƒ©ãƒ¼ã€‚ã“れã¯å…¨ã¦ã®å¤‰æ›´ãŒãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ä¿å­˜ã•れã¦ã„ãªã‹ã£ãŸãŸã‚ã§ã™ã€‚ã¾ãšã€ä»¥ä¸‹ã®ã‚¨ãƒ©ãƒ¼ã‚’解決ã—ã¦ãã ã•ã„。 + +%1 + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + 本当ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイル '%1' ã¸ã®æœ€å¾Œã®ä¿å­˜å¾Œã«è¡Œã‚れãŸã™ã¹ã¦ã®å¤‰æ›´ã‚’å…ƒã«æˆ»ã—ã¾ã™ã‹? + + + + Choose a file to import + インãƒãƒ¼ãƒˆã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (読ã¿å–り専用) + + + + Open Database or Project + データベース化プロジェクトを開ã + + + + Attach Database... + ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æŽ¥ç¶š... + + + + Import CSV file(s)... + CSVファイルをインãƒãƒ¼ãƒˆ... + + + + Do you want to save the changes made to SQL tabs in a new project file? + æ–°ã—ã„プロジェクトファイルã«SQLタブã§è¡Œã‚れãŸå¤‰æ›´ã‚’ä¿å­˜ã—ã¾ã™ã‹? + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + プロジェクトファイル '%1' ã«SQLタブã§è¡Œã‚れãŸå¤‰æ›´ã‚’ä¿å­˜ã—ã¾ã™ã‹? + + + + Do you want to save the changes made to the SQL file %1? + 変更をSQLファイル %1 ã«ä¿å­˜ã—ã¾ã™ã‹? + + + + Text files(*.sql *.txt);;All files(*) + テキストファイル(*.sql *.txt);;ã™ã¹ã¦ã®ãƒ•ァイル(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + インãƒãƒ¼ãƒˆã—ãŸãƒ‡ãƒ¼ã‚¿ã‚’ä¿æŒã™ã‚‹æ–°ã—ã„データベースを作æˆã—ã¾ã™ã‹ +ã„ã„ãˆã‚’é¸æŠžã™ã‚‹ã¨ã€SQLファイルã‹ã‚‰ã®ãƒ‡ãƒ¼ã‚¿ã‚’ç¾åœ¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆã—よã†ã¨ã—ã¾ã™ã€‚ + + + + Automatically load the last opened DB file at startup + 最後ã«é–‹ã„ãŸDBファイルを起動時ã«è‡ªå‹•çš„ã«èª­ã¿è¾¼ã‚€ + + + + Do you want to save the changes made to the project file '%1'? + プロジェクトファイル '%1' ã«å¤‰æ›´ã‚’ä¿å­˜ã—ã¾ã™ã‹? + + + + Execution finished with errors. + エラーãŒã‚りã¾ã™ãŒã€å®Ÿè¡ŒãŒçµ‚了ã—ã¾ã—ãŸã€‚ + + + + Execution finished without errors. + エラーãªã—ã§å®Ÿè¡ŒãŒçµ‚了ã—ã¾ã—ãŸã€‚ + + + + File %1 already exists. Please choose a different name. + ファイル %1 ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™ã€‚é•ã†åå‰ã‚’é¸ã‚“ã§ãã ã•ã„。 + + + + Error importing data: %1 + データã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ã‚¨ãƒ©ãƒ¼: %1 + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + インãƒãƒ¼ãƒˆãŒçµ‚了ã—ã¾ã—ãŸã€‚ã„ãã¤ã‹ã®å¤–部キー制約ã«é•åãŒã‚りã¾ã™ã€‚ä¿å­˜å‰ã«ä¿®æ­£ã—ã¦ãã ã•ã„。 + + + + Import completed. + インãƒãƒ¼ãƒˆå®Œäº†ã€‚ + + + + Delete View + ビューを削除 + + + + Modify View + ビューを変更 + + + + Delete Trigger + トリガーを削除 + + + + Modify Trigger + トリガーを変更 + + + + Delete Index + インデックスを削除 + + + + Modify Index + インデックスを変更 + + + + Modify Table + テーブルを変更 + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + PRAGMA 値ã®è¨­å®šã¯ç¾åœ¨ã®ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³ã‚’コミットã—ã¾ã™ã€‚ +本当ã«è¡Œã„ã¾ã™ã‹? + + + + Select SQL file to open + é–‹ãSQLãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž + + + + Select file name + ファイルåã‚’é¸æŠž + + + + Select extension file + æ‹¡å¼µãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž + + + + Extension successfully loaded. + æ‹¡å¼µã®èª­ã¿è¾¼ã¿ã«æˆåŠŸã—ã¾ã—ãŸã€‚ + + + + Error loading extension: %1 + æ‹¡å¼µã®èª­ã¿è¾¼ã¿ã§ã‚¨ãƒ©ãƒ¼: %1 + + + + + Don't show again + 二度ã¨è¡¨ç¤ºã—ãªã„ + + + + New version available. + æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã‚りã¾ã™ã€‚ + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® DB Browser for SQLite (%1.%2.%3)ãŒã‚りã¾ã™ã€‚<br/><br/><a href='%4'>%4</a>ã‹ã‚‰ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¦ãã ã•ã„。 + + + + Choose a project file to open + é–‹ããƒ—ãƒ­ã‚¸ã‚§ã‚¯ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž + + + + DB Browser for SQLite project file (*.sqbpro) + DB Browser for SQLite プロジェクトファイル (*.sqbpro) + + + + Collation needed! Proceed? + ç…§åˆé †åºãŒå¿…è¦ã§ã™!続行ã—ã¾ã™ã‹? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ã‚るテーブルã¯ç‰¹åˆ¥ãªç…§åˆé †åºé–¢æ•° '%1' ãŒå¿…è¦ã§ã™ãŒã€ã“ã®ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã¯æ›´ãªã‚‹çŸ¥è­˜ãªã—ã§ã¯æä¾›ã§ãã¾ã›ã‚“。 +続行ã™ã‚‹ã¨ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ä½•ã‹æ‚ªã„ã“ã¨ãŒã‚ã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“。 +ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—を作æˆã—ã¦ãã ã•ã„! + + + + creating collation + ç…§åˆé †åºã®ä½œæˆä¸­ + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + SQLã‚¿ãƒ–ã«æ–°ã—ã„åå‰ã‚’設定ã—ã¦ãã ã•ã„。'&&'ã®æ–‡å­—を使ã†ã¨ã€ãã®æ¬¡ã®æ–‡å­—をキーボードショートカットã«ã§ãã¾ã™ã€‚ + + + + Please specify the view name + ビューã®åå‰ã‚’指定ã—ã¦ãã ã•ã„ + + + + There is already an object with that name. Please choose a different name. + ãã®åå‰ã®ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚別ã®åå‰ã‚’é¸ã‚“ã§ãã ã•ã„。 + + + + View successfully created. + ビューã®ä½œæˆã«æˆåŠŸã—ã¾ã—ãŸã€‚ + + + + Error creating view: %1 + ビューã®ä½œæˆã§ã‚¨ãƒ©ãƒ¼: %1 + + + + This action will open a new SQL tab for running: + ã“ã®æ“作ã¯å®Ÿè¡Œã®ãŸã‚æ–°ã—ã„SQLタブを開ãã¾ã™: + + + + Press Help for opening the corresponding SQLite reference page. + ヘルプを押ã™ã¨ã€å¯¾å¿œã™ã‚‹ SQLite ã®ãƒªãƒ•ァレンスページを開ãã¾ã™ã€‚ + + + + NullLineEdit + + + Set to NULL + NULL ã«è¨­å®š + + + + Alt+Del + + + + + PlotDock + + + Plot + プロット + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>ã“ã®ãƒšã‚¤ãƒ³ã¯ç¾åœ¨é–²è¦§ä¸­ã®ãƒ†ãƒ¼ãƒ–ルã‹ç›´å‰ã«å®Ÿè¡Œã—ãŸã‚¯ã‚¨ãƒªãƒ¼ã®ã‚«ãƒ©ãƒ ã®ä¸€è¦§ã‚’表示ã—ã¾ã™ã€‚下ã®ãƒ—ロットペインã§Xã‚‚ã—ãã¯Y軸ã¨ã—ã¦ä½¿ç”¨ã•ã‚Œã‚‹ã‚«ãƒ©ãƒ ã‚’é¸æŠžã§ãã¾ã™ã€‚表ã¯çµæžœã®ãƒ—ロットã«ä½¿ç”¨ã§ãる軸ã®ç¨®é¡žã‚’表示ã—ã¾ã™ã€‚Y軸ã«ã¯æ•°å€¤ã®ã‚«ãƒ©ãƒ ã®ã¿é¸æŠžã§ãã¾ã™ãŒã€X軸ã«ã¯ã“れらãŒé¸æŠžã§ãã¾ã™:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">日時</span>: &quot;yyyy-MM-dd hh:mm:ss&quot; ã‚‚ã—ã㯠&quot;yyyy-MM-ddThh:mm:ss&quot; å½¢å¼ã®æ–‡å­—列</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">日付</span>: &quot;yyyy-MM-dd&quot; å½¢å¼ã®æ–‡å­—列</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">時刻</span>: &quot;hh:mm:ss&quot; å½¢å¼ã®æ–‡å­—列</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">ラベル</span>: ãã®ä»–ã®å½¢å¼ã®æ–‡å­—列。ã“れをX軸ã«é¸æŠžã™ã‚‹ã¨ã€ã‚«ãƒ©ãƒ ã®å€¤ã‚’棒グラフã®ãƒ©ãƒ™ãƒ«ã¨ã—ã¦è¡¨ç¤ºã—ã¾ã™</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">数値</span>: INTEGER ã‹ REAL ã®å€¤</li></ul><p>Yã®ã‚»ãƒ«ã‚’ダブルクリックã™ã‚‹ã¨ã€ã‚°ãƒ©ãƒ•ã«ä½¿ç”¨ã™ã‚‹è‰²ã‚’変更ã§ãã¾ã™ã€‚</p></body></html> + + + + Columns + カラム + + + + X + X + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + 軸ã®ãƒ‡ãƒ¼ã‚¿åž‹ + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + 上ã§Xã¨Yè»¸ã‚’é¸æŠžã™ã‚‹ã¨ã€ã“ã“ã«ã‚°ãƒ©ãƒ•ãŒæç”»ã•れã¾ã™ã€‚ + +点をクリックã™ã‚‹ã¨ã€ç‚¹ã¨è©²å½“ã™ã‚‹ãƒ†ãƒ¼ãƒ–ルã®å€¤ãŒé¸æŠžã§ãã¾ã™ã€‚Ctrl+クリックã§ç‚¹ã‚’ç¯„å›²é¸æŠžã§ãã¾ã™ã€‚ + +マウスホイールã§ã‚ºãƒ¼ãƒ ã€ãƒ‰ãƒ©ãƒƒã‚°ã§è»¸ã®ç¯„囲を変更ã§ãã¾ã™ã€‚ + +軸ã‹è»¸ã®ãƒ©ãƒ™ãƒ«ã‚’é¸æŠžã™ã‚‹ã¨ã€ã‚ºãƒ¼ãƒ ã‚„ãƒ‰ãƒ©ãƒƒã‚°ã®æ–¹å‘ã‚’é™å®šã§ãã¾ã™ã€‚ + + + + Line type: + ç·šã®ç¨®é¡ž: + + + + + None + ãªã— + + + + Line + ç›´ç·š + + + + StepLeft + 階段(左値) + + + + StepRight + 階段(å³å€¤) + + + + StepCenter + 階段(最近値) + + + + Impulse + インパルス + + + + Point shape: + 点ã®å½¢çж: + + + + Cross + × + + + + Plus + + + + + + Circle + â—‹ + + + + Disc + â— + + + + Square + â–¡ + + + + Diamond + â—‡ + + + + Star + * + + + + Triangle + â–³ + + + + TriangleInverted + â–½ + + + + CrossSquare + ×+â–¡ + + + + PlusSquare + ++â–¡ + + + + CrossCircle + ×+â—‹ + + + + PlusCircle + ++â—‹ + + + + Peace + é™è¬ + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>ç¾åœ¨ã®ãƒ—ロットをä¿å­˜...</p><p>ãƒ•ã‚¡ã‚¤ãƒ«ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã¯æ‹¡å¼µå­ (png, jpg, pdf, bmp) ã‹ã‚‰é¸æŠžã•れã¾ã™</p></body></html> + + + + Save current plot... + ç¾åœ¨ã®ãƒ—ロットをä¿å­˜... + + + + + Load all data and redraw plot + ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã¿å†æç”» + + + + Copy + コピー + + + + Print... + å°åˆ·... + + + + Help + + + + + Show legend + 凡例を表示 + + + + Stacked bars + 値をç©ã¿é‡ã­ã‚‹ + + + + Fixed number format + å›ºå®šã®æ•°å€¤ãƒ•ォーマット + + + + Date/Time + 日時 + + + + Date + 日付 + + + + Time + 時刻 + + + + + Numeric + 数値 + + + + Label + ラベル + + + + Invalid + 䏿­£ + + + + + + Row # + 行 # + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã¿å†æç”»ã—ã¾ã™ã€‚ +警告: 部分的ãªãƒ•ã‚§ãƒƒãƒæ©Ÿæ§‹ã«ã‚ˆã‚Šã€ã¾ã ãƒ†ãƒ¼ãƒ–ルã‹ã‚‰ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ãŒãƒ•ェッãƒã•れã¦ã„ã‚‹ã‚ã‘ã§ã¯ã‚りã¾ã›ã‚“。 + + + + Choose an axis color + 軸ã®è‰²ã‚’é¸æŠž + + + + Choose a filename to save under + ä¿å­˜ã™ã‚‹ãƒ•ァイルåを下ã‹ã‚‰é¸æŠž + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;ã™ã¹ã¦ã®ãƒ•ァイル(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + ã“ã®ãƒ—ロットã«ã¯æœªã‚½ãƒ¼ãƒˆãªãƒ‡ãƒ¼ã‚¿ãŒã‚りã¾ã™ã€‚é¸æŠžã—ãŸç·šã®ç¨®é¡žã¯X軸ã§ã‚½ãƒ¼ãƒˆã•れãŸãƒ‡ãƒ¼ã‚¿ã®ã¿ã«é©ç”¨ã§ãã¾ã™ã€‚テーブルやクエリーをX軸ã§ã‚½ãƒ¼ãƒˆã™ã‚‹ã‹ã€æœªã‚½ãƒ¼ãƒˆã®ãƒ‡ãƒ¼ã‚¿ã§ã‚‚使用ã§ãる〠ãªã— ã‚„ ç›´ç·š å½¢å¼ã‚’é¸æŠžã—ã¦ãã ã•ã„。 + + + + Loading all remaining data for this table took %1ms. + ã“ã®ãƒ†ãƒ¼ãƒ–ãƒ«ã®æ®‹ã£ã¦ã„るデータã™ã¹ã¦ã®èª­ã¿è¾¼ã¿ã« %1ms ã‹ã‹ã‚Šã¾ã—ãŸã€‚ + + + + PreferencesDialog + + + Preferences + 設定 + + + + &General + 全般(&G) + + + + Default &location + デフォルトã®ãƒ•ォルダー(&L) + + + + Remember last location + 最後ã«ä½¿ç”¨ã—ãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãƒ¼ã‚’記憶 + + + + Always use this location + 常ã«ã“ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãƒ¼ã‚’使用 + + + + Remember last location for session only + セッションã ã‘ã§æœ€å¾Œã«ä½¿ç”¨ã—ãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãƒ¼ã‚’記憶 + + + + + + ... + ... + + + + Lan&guage + 言語(&L) + + + + Toolbar style + ツールãƒãƒ¼å½¢å¼ + + + + + + + + Only display the icon + アイコンã®ã¿è¡¨ç¤º + + + + + + + + Only display the text + 文字ã®ã¿è¡¨ç¤º + + + + + + + + The text appears beside the icon + ã‚¢ã‚¤ã‚³ãƒ³ã®æ¨ªã«æ–‡å­—を表示 + + + + + + + + The text appears under the icon + アイコンã®ä¸‹ã«æ–‡å­—を表示 + + + + + + + + Follow the style + スタイルã«å¾“ㆠ+ + + + Show remote options + リモートオプションを表示ã™ã‚‹ + + + + + + + + + + + + + + enabled + 有効 + + + + Automatic &updates + 自動アップデート(&U) + + + + DB file extensions + DBãƒ•ã‚¡ã‚¤ãƒ«æ‹¡å¼µå­ + + + + Manage + ç®¡ç† + + + + Main Window + メインウィンドウ + + + + Database Structure + データベース構造 + + + + Browse Data + データ閲覧 + + + + Execute SQL + SQL実行 + + + + Edit Database Cell + データベースセル編集 + + + + When this value is changed, all the other color preferences are also set to matching colors. + ã“ã®å€¤ãŒå¤‰æ›´ã•れるã¨ã€ä»–ã®è‰²è¨­å®šã™ã¹ã¦ã‚‚一致ã™ã‚‹è‰²ã«è¨­å®šã•れã¾ã™ã€‚ + + + + Follow the desktop style + デスクトップスタイルã«å¾“ㆠ+ + + + Dark style + ダークスタイル + + + + Application style + アプリケーションスタイル + + + + This sets the font size for all UI elements which do not have their own font size option. + ã“れã¯ç‹¬è‡ªã®ãƒ•ォントサイズオプションをæŒãŸãªã„å…¨ã¦ã®UIè¦ç´ ã®ãƒ•ォントサイズを設定ã—ã¾ã™ã€‚ + + + + Font size + フォントサイズ + + + + Max Recent Files + ファイル使用履歴最大数 + + + + Prompt to save SQL tabs +in new project file + æ–°ã—ã„プロジェクトファイル㫠+SQLタブをä¿å­˜ã™ã‚‹ã¨ãã«å°‹ã­ã‚‹ + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + 有効ã«ã™ã‚‹ã¨ã€SQL編集タブを閉ã˜ã‚‹ã¨ãã«ã€å¤‰æ›´ãŒã‚ã‚‹ã¨ãƒ—ロジェクトä¿å­˜ç¢ºèªãƒ€ã‚¤ã‚¢ãƒ«å…·ãŒè¡¨ç¤ºã•れã¾ã™ã€‚ + + + + &Database + データベース(&D) + + + + Database &encoding + データベースã®ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰(&E) + + + + Open databases with foreign keys enabled. + 外部キーを有効ã«ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ã。 + + + + &Foreign keys + 外部キー(&F) + + + + Remove line breaks in schema &view + スキーマビューã‹ã‚‰æ”¹è¡Œã‚’å–り除ã(&V) + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + 有効ã«ã™ã‚‹ã¨ã€DB構造タブã®ã‚«ãƒ©ãƒ ã‚¹ã‚­ãƒ¼ãƒžã€ãƒ‰ãƒƒã‚¯ã‚„å°åˆ·ã•れãŸå‡ºåŠ›ã«ã‚る改行ãŒå–り除ã‹ã‚Œã¾ã™ã€‚ + + + + Prefetch block si&ze + 先読ã¿ãƒ–ロックサイズ(&Z) + + + + SQ&L to execute after opening database + データベースを開ã„ãŸå¾Œã«å®Ÿè¡Œã™ã‚‹SQL(&L) + + + + Default field type + デフォルトã®ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ãƒ‡ãƒ¼ã‚¿å½¢å¼ + + + + Database structure font size + データベース構造ã®ãƒ•ォントサイズ + + + + Data &Browser + データ閲覧(&B) + + + + Font + フォント + + + + &Font + フォント(&F) + + + + Font si&ze + フォントサイズ(&Z) + + + + Content + 内容 + + + + Symbol limit in cell + セル内ã®ã‚·ãƒ³ãƒœãƒ«ä¸Šé™ + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + ã“れã¯ã„ãã¤ã‹ã®è¨ˆç®—è² è·ã®é«˜ã„機能を有効ã«ã§ãã‚‹é …ç›®ã®æœ€å¤§æ•°ã§ã™ã€‚ +カラム内ã®ç¾åœ¨å€¤ã«åŸºã¥ã„ãŸå€¤è£œå®Œã‚’有効ã«ã™ã‚‹ã€ãƒ†ãƒ¼ãƒ–ル内ã®è¡Œã®æœ€å¤§æ•°ã€‚ +é¸æŠžå†…ã®åˆè¨ˆã¨å¹³å‡ã‚’計算ã™ã‚‹ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®æœ€å¤§æ•°ã€‚ +0ã«è¨­å®šã™ã‚‹ã¨ã“ã®æ©Ÿèƒ½ã‚’無効ã«ã§ãã¾ã™ã€‚ + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + ã“れã¯ç¾åœ¨ã®å€¤ã‚’基ã«ã—ãŸã‚«ãƒ©ãƒ ã®å€¤è£œå®Œã‚’有効ã«ã—ãŸã¨ãã®ãƒ†ãƒ¼ãƒ–ル内ã®è¡Œæ•°ã®æœ€å¤§å€¤ã§ã™ã€‚ + + + + Field display + フィールド表示 + + + + Displayed &text + 表示ã•れãŸãƒ†ã‚­ã‚¹ãƒˆ(&T) + + + + Binary + ãƒã‚¤ãƒŠãƒªãƒ¼ + + + + NULL + NULL + + + + Regular + 通常 + + + + + + + + + + + Click to set this color + クリックã§ã“ã®è‰²ã‚’設定 + + + + Text color + 文字色 + + + + Background color + 背景色 + + + + + Preview only (N/A) + 閲覧ã®ã¿(設定ä¸å¯) + + + + Filters + フィルター + + + + Escape character + エスケープ文字 + + + + Delay time (&ms) + é…延時間 (ms) (&M) + + + + Light style + ライトスタイル + + + + Formatted + 整形済㿠+ + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + æ–°ã—ã„フィルターã®å€¤ãŒé©ç”¨ã•れるå‰ã®å¾…機時間を設定ã—ã¾ã™ã€‚0ã«ã™ã‚‹ã¨å¾…機ã—ã¾ã›ã‚“。 + + + + &SQL + SQL(&S) + + + + Context + 内容 + + + + Colour + 色 + + + + Bold + 太字 + + + + Italic + イタリック + + + + Underline + 下線 + + + + Keyword + キーワード + + + + Function + 関数 + + + + Table + テーブル + + + + Comment + コメント + + + + Identifier + è­˜åˆ¥å­ + + + + String + 文字列 + + + + Current line + ç¾åœ¨è¡Œ + + + + Background + 背景 + + + + Foreground + 剿™¯ + + + + Selection background + é¸æŠžä¸­èƒŒæ™¯ + + + + Selection foreground + é¸æŠžä¸­å‰æ™¯ + + + + Highlight + 強調 + + + + SQL editor &font + SQLエディターフォント(&F) + + + + SQL &editor font size + SQLエディターフォントサイズ(&E) + + + + SQL &results font size + SQLçµæžœãƒ•ォントサイズ(&R) + + + + Tab size + タブサイズ + + + + Use tabs for indentation + インデントã«ã‚¿ãƒ–を使ㆠ+ + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + 設定ã™ã‚‹ã¨ã€ã‚¿ãƒ–キーã¯ã‚¤ãƒ³ãƒ‡ãƒ³ãƒˆã«ã‚¿ãƒ–ã¨ç©ºç™½æ–‡å­—を挿入ã—ã¾ã™ã€‚ãã†ã§ãªã‘れã°ã€ç©ºç™½æ–‡å­—ã ã‘を使用ã—ã¾ã™ã€‚ + + + + &Wrap lines + ワードラップ(&W) + + + + Never + ã—ãªã„ + + + + At word boundaries + å˜èªžã§ + + + + At character boundaries + 文字㧠+ + + + At whitespace boundaries + 空白㧠+ + + + &Quotes for identifiers + 識別å­ã®ã‚¯ã‚©ãƒ¼ãƒˆ(&Q) + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + アプリケーションãŒSQLコード内ã§è­˜åˆ¥å­ã‚’クォートã™ã‚‹ä»•組ã¿ã‚’é¸æŠžã—ã¾ã™ã€‚ + + + + "Double quotes" - Standard SQL (recommended) + "ダブルクォート" - 一般的㪠SQL (推奨) + + + + `Grave accents` - Traditional MySQL quotes + `グレイヴアクセント` - ä¼çµ±çš„㪠MySQL ã®ã‚¯ã‚©ãƒ¼ãƒˆ + + + + [Square brackets] - Traditional MS SQL Server quotes + [角括弧] - ä¼çµ±çš„㪠MS SQL Server ã®ã‚¯ã‚©ãƒ¼ãƒˆ + + + + Code co&mpletion + コード補完(&M) + + + + Keywords in &UPPER CASE + キーワードを大文字ã«(&U) + + + + When set, the SQL keywords are completed in UPPER CASE letters. + 設定ã™ã‚‹ã¨ã€SQLキーワードを大文字ã«è£œå®Œã—ã¾ã™ã€‚ + + + + Error indicators + エラー指摘 + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + 設定ã™ã‚‹ã¨ã€æœ€å¾Œã®å®Ÿè¡Œã§ã‚¨ãƒ©ãƒ¼ãŒèµ·ããŸSQLコードã®è¡ŒãŒå¼·èª¿ã•れã€çµæžœãƒ•レームãŒãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã§ã‚¨ãƒ©ãƒ¼ã‚’指摘ã—ã¾ã™ + + + + Hori&zontal tiling + 横ã«ä¸¦ã¹ã‚‹(&Z) + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + 有効ã«ã™ã‚‹ã¨ã€é‡ã­ã‚‹ä»£ã‚りã«ã€SQLコードエディターã¨çµæžœã‚¿ãƒ–ビューãŒä¸¦ã‚“ã§è¡¨ç¤ºã•れã¾ã™ã€‚ + + + + Close button on tabs + タブã«é–‰ã˜ã‚‹ãƒœã‚¿ãƒ³ã‚’表示 + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + 有効ã«ã™ã‚‹ã¨SQL編集タブã«é–‰ã˜ã‚‹ãƒœã‚¿ãƒ³ã‚’表示ã—ã¾ã™ã€‚ã©ã®ã‚ˆã†ãªå ´åˆã§ã‚‚コンテキストメニューやキーボードショートカットã‹ã‚‰ã‚¿ãƒ–ã‚’é–‰ã˜ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ + + + + &Extensions + æ‹¡å¼µ(&E) + + + + Select extensions to load for every database: + ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã§èª­ã¿è¾¼ã‚€æ‹¡å¼µã‚’é¸æŠž: + + + + Add extension + 拡張を追加 + + + + Remove extension + 拡張を削除 + + + + Select built-in extensions to load for every database: + ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã§èª­ã¿è¾¼ã‚€ãƒ“ãƒ«ãƒˆã‚¤ãƒ³æ‹¡å¼µã‚’é¸æŠž + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>REGEXP演算å­ãŒã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã‚‹é–“ã€SQLite ã¯æ­£è¦è¡¨ç¾ã‚’実装ã—ã¾ã›ã‚“ãŒã€å®Ÿè¡Œä¸­ã®ã‚¢ãƒ—リケーションをコールãƒãƒƒã‚¯ã—ã¾ã™ã€‚DB Browser for SQLite ã¯ã“れを実装ã—ã¦ã„ã‚‹ã®ã§ã€REGEXP ã‚’ã™ãã«ä½¿ãˆã¾ã™ã€‚ã—ã‹ã—ã€ã“れã«ã¯è¤‡æ•°ã®å®Ÿè£…ãŒã‚りã€ã‚¢ãƒ—リケーションã®å®Ÿè£…を無効ã«ã—拡張を使ã£ã¦ä»–ã®å®Ÿè£…を読ã¿è¾¼ã‚€ã“ã¨ãŒè‡ªç”±ã«ã§ãã¾ã™ã€‚アプリケーションã®å†èµ·å‹•ãŒå¿…è¦ã§ã™ã€‚</p></body></html> + + + + Disable Regular Expression extension + æ­£è¦è¡¨ç¾æ‹¡å¼µã‚’無効 + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite ã¯å…±æœ‰ãƒ©ã‚¤ãƒ–ラリファイルã‹ã‚‰æ‹¡å¼µã‚’読ã¿è¾¼ã‚€SQL関数をæä¾›ã—ã¾ã™ã€‚SQLコードã‹ã‚‰<span style=" font-style:italic;">load_extension()</span>関数を使ã„ãŸã„ãªã‚‰ã°ã€.ã“れを有効ã«ã—ã¾ã™ã€‚</p><p>セキュリティー上ã®ç†ç”±ã‹ã‚‰ã€æ‹¡å¼µã®èª­ã¿è¾¼ã¿ã¯ãƒ‡ãƒ•ォルトã§ç„¡åйã«ãªã£ã¦ãŠã‚Šã€ä½¿ç”¨ã™ã‚‹ã«ã¯ã“ã®è¨­å®šã‚’有効ã«ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションãŒç„¡åйã§ã‚‚ã€GUIを通ã˜ã¦æ‹¡å¼µã‚’読ã¿è¾¼ã‚€ã“ã¨ã¯å¸¸ã«ã§ãã¾ã™ã€‚</p></body></html> + + + + Allow loading extensions from SQL code + SQLã‚³ãƒ¼ãƒ‰ã§æ‹¡å¼µã®èª­ã¿è¾¼ã¿ã‚’許å¯ã™ã‚‹ + + + + Remote + リモート + + + + CA certificates + èªè¨¼å±€è¨¼æ˜Žæ›¸ + + + + Proxy + プロキシ + + + + Configure + 設定 + + + + Export Settings + 設定をエクスãƒãƒ¼ãƒˆ + + + + Import Settings + 設定をインãƒãƒ¼ãƒˆ + + + + + Subject CN + 対象CN + + + + Common Name + Common Name + + + + Subject O + 対象O + + + + Organization + Organization + + + + + Valid from + 証明開始 + + + + + Valid to + 証明終了 + + + + + Serial number + ã‚·ãƒªã‚¢ãƒ«ç•ªå· + + + + Your certificates + ã‚ãªãŸã®è¨¼æ˜Žæ›¸ + + + + Threshold for completion and calculation on selection + 補完ã¨é¸æŠžç¯„囲内ã®è¨ˆç®—ã®é–¾å€¤ + + + + Show images in cell + セル内ã«ç”»åƒã‚’表示 + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + ã“ã®ã‚ªãƒ—ションを有効ã«ã™ã‚‹ã¨ã€ã‚»ãƒ«å†…ã®ç”»åƒãƒ‡ãƒ¼ã‚¿ã‚’å«ã‚€ BLOB ã®ãƒ—レビューãŒã§ãã¾ã™ã€‚ã—ã‹ã—ã€ã“れã¯ãƒ‡ãƒ¼ã‚¿é–²è¦§ã®æ€§èƒ½ã«å½±éŸ¿ã—ã¾ã™ã€‚ + + + + File + ファイル + + + + Subject Common Name + 対象Common Name + + + + Issuer CN + 発行者CN + + + + Issuer Common Name + 発行者Common Name + + + + Clone databases into + ã“ã“ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’複製 + + + + + Choose a directory + ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãƒ¼ã‚’é¸æŠž + + + + + The language will change after you restart the application. + アプリケーションをå†èµ·å‹•ã™ã‚‹ã¨ã€è¨€èªžãŒå¤‰æ›´ã•れã¾ã™ã€‚ + + + + Select extension file + æ‹¡å¼µãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž + + + + Extensions(*.so *.dylib *.dll);;All files(*) + æ‹¡å¼µ(*.so *.dylib *.dll);;ã™ã¹ã¦ã®ãƒ•ァイル(*) + + + + Import certificate file + 証明書ファイルをインãƒãƒ¼ãƒˆ + + + + No certificates found in this file. + ã“ã®ãƒ•ァイルã«è¨¼æ˜Žæ›¸ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。 + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + 本当ã«ã“ã®è¨¼æ˜Žæ›¸ã‚’削除ã—ã¾ã™ã‹? ã™ã¹ã¦ã®è¨¼æ˜Žæ›¸ãƒ‡ãƒ¼ã‚¿ã¯ã“ã®ã‚¢ãƒ—リケーション設定ã‹ã‚‰å‰Šé™¤ã•れã¾ã™! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + 本当ã«ä¿å­˜ã•れãŸè¨­å®šã‚’削除ã—ã¾ã™ã‹? +ã™ã¹ã¦ã®è¨­å®šã¯å¤±ã‚れã€ãƒ‡ãƒ•ォルト値ãŒä½¿ç”¨ã•れã¾ã™ã€‚ + + + + Save Settings File + 設定ファイルをä¿å­˜ + + + + + Initialization File (*.ini) + INIファイル (*.ini) + + + + The settings file has been saved in location : + + 設定ファイルをã“ã“ã«ä¿å­˜ã—ã¾ã—ãŸ: + + + + + Open Settings File + 設定ファイルを開ã + + + + The settings file was loaded properly. + è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ãŒæ­£ã—ã読ã¿è¾¼ã¾ã‚Œã¾ã—ãŸã€‚ + + + + The selected settings file is not a normal settings file. +Please check again. + é¸æŠžã•れãŸè¨­å®šãƒ•ァイルã«ç•°å¸¸ãŒã‚りã¾ã™ã€‚ +å†åº¦ç¢ºèªã—ã¦ãã ã•ã„。 + + + + ProxyDialog + + + Proxy Configuration + プロキシ設定 + + + + Pro&xy Type + プロキシタイプ(&X) + + + + Host Na&me + ホストå(&M) + + + + Port + ãƒãƒ¼ãƒˆ + + + + Authentication Re&quired + èªè¨¼ãŒå¿…è¦(&Q) + + + + &User Name + ユーザーå(&U) + + + + Password + パスワード + + + + None + ãªã— + + + + System settings + システム設定 + + + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 + + + + QObject + + + All files (*) + ã™ã¹ã¦ã®ãƒ•ァイル (*) + + + + Error importing data + データã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ã‚¨ãƒ©ãƒ¼ + + + + from record number %1 + ãƒ¬ã‚³ãƒ¼ãƒ‰ç•ªå· %1 ã§ + + + + . +%1 + . +%1 + + + + Importing CSV file... + CSVファイルをインãƒãƒ¼ãƒˆä¸­... + + + + Cancel + キャンセル + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + SQLite データベースファイル (*.db *.sqlite *.sqlite3 *.db3) + + + + Left + å·¦ + + + + Right + å³ + + + + Center + 中央 + + + + Justify + å‡ç­‰ + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + SQLite データベースファイル (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + DB Browser for SQLite プロジェクトファイル (*.sqbpro) + + + + SQL Files (*.sql) + SQL ファイル (*.sql) + + + + All Files (*) + ã™ã¹ã¦ã®ãƒ•ァイル (*) + + + + Text Files (*.txt) + テキストファイル (*.txt) + + + + Comma-Separated Values Files (*.csv) + カンマ区切りファイル (*.csv) + + + + Tab-Separated Values Files (*.tsv) + タブ区切りファイル (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + 区切りファイル (*.dsv) + + + + Concordance DAT files (*.dat) + 用語索引 DAT ファイル (*.dat) + + + + JSON Files (*.json *.js) + JSONファイル (*.json *.js) + + + + XML Files (*.xml) + XMLファイル (*.xml) + + + + Binary Files (*.bin *.dat) + ãƒã‚¤ãƒŠãƒªãƒ¼ãƒ•ァイル (*.bin *.dat) + + + + SVG Files (*.svg) + SVG ファイル (*.svg) + + + + Hex Dump Files (*.dat *.bin) + å六進ダンプファイル (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + æ‹¡å¼µ (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + INIファイル (*.ini) + + + + QsciCommand + + Paste + 貼り付㑠+ + + Cancel + キャンセル + + + + QsciLexerCPP + + Default + デフォルト + + + Keyword + キーワード + + + Identifier + è­˜åˆ¥å­ + + + + QsciLexerJSON + + Default + デフォルト + + + String + 文字列 + + + + QsciLexerJavaScript + + Regular expression + æ­£è¦è¡¨ç¾ + + + + QsciLexerPython + + Default + デフォルト + + + Comment + コメント + + + Keyword + キーワード + + + Identifier + è­˜åˆ¥å­ + + + + QsciLexerSQL + + Default + デフォルト + + + Comment + コメント + + + Keyword + キーワード + + + Identifier + è­˜åˆ¥å­ + + + + QsciScintilla + + &Undo + å…ƒã«æˆ»ã™(&U) + + + Select All + ã™ã¹ã¦é¸æŠž + + + + RemoteCommitsModel + + + Commit ID + コミットID + + + + Message + メッセージ + + + + Date + 日付 + + + + Author + 作者 + + + + Size + サイズ + + + + Authored and committed by %1 + %1 ãŒä½œæˆã€ã‚³ãƒŸãƒƒãƒˆã—ã¾ã—㟠+ + + + Authored by %1, committed by %2 + %1 ãŒä½œæˆ, %2 ãŒã‚³ãƒŸãƒƒãƒˆã—ã¾ã—㟠+ + + + RemoteDatabase + + + Error opening local databases list. +%1 + ローカルデータベースã®ä¸€è¦§ã‚’é–‹ãã¨ãã«ã‚¨ãƒ©ãƒ¼ã€‚ +%1 + + + + Error creating local databases list. +%1 + ローカルデータベースã®ä¸€è¦§ã®ä½œæˆã§ã‚¨ãƒ©ãƒ¼ã€‚ +%1 + + + + RemoteDock + + + Remote + リモート + + + + Identity + アイデンティティー + + + + Push currently opened database to server + ç¾åœ¨é–‹ã„ã¦ã„るデータベースをサーãƒãƒ¼ã«ãƒ—ッシュã—ã¾ã™ + + + + Upload + アップロード + + + + DBHub.io + DBHub.io + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>ã“ã®ç”»é¢ã§ã¯ã€dbhub.io ウェブサイトã®ãƒªãƒ¢ãƒ¼ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’ DB Browser for SQLite ã«è¿½åŠ ã§ãã¾ã™ã€‚最åˆã«èªè¨¼ãŒå¿…è¦ã§ã™:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">dbhub.io ã«ãƒ­ã‚°ã‚¤ãƒ³ (GitHub èªè¨¼ã‹ã‚ãªãŸã®æœ›ã‚€ã‚‚ã®ã‚’使ã„ã¾ã™)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).&quot;Generate client certificate&quot ボタンをクリック; (ã“れãŒã‚ãªãŸã®èªè¨¼æƒ…å ±ã§ã™) ã“れã§è¨¼æ˜Žæ›¸ãƒ•ァイルãŒå…¥æ‰‹ã§ãã¾ã™(ã“れをã‚ãªãŸã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒ‡ã‚£ã‚¹ã‚¯ã«ä¿å­˜ã—ã¾ã™)。</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">DB Browser for SQLite ã®è¨­å®šã«ã‚るリモートタブã¸ç§»å‹•ã—ã¾ã™ã€‚ボタンをクリックã€ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ãŸè¨¼æ˜Žæ›¸ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—〠DB Browser for SQLite ã«æ–°ã—ã„èªè¨¼æƒ…報を追加ã—ã¾ã™ã€‚</li></ol><p>ã“れã§ãƒªãƒ¢ãƒ¼ãƒˆãƒ‘ãƒãƒ«ã«ã‚ãªãŸã®èªè¨¼æƒ…å ±ãŒè¡¨ç¤ºã•れã€ã‚Šã‚‚ーã¨ã§ãƒ¼ãŸã¹ãƒ¼ã™ãŒã¤ã„ã‹ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚</p></body></html> + + + + Local + ローカル + + + + Current Database + ç¾åœ¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ + + + + Clone + クローン + + + + Branch + ブランム+ + + + Commits + コミット + + + + Commits for + ã“れã«ã‚³ãƒŸãƒƒãƒˆ + + + + Delete Database + データベースを削除 + + + + Delete the local clone of this database + ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒ­ãƒ¼ã‚«ãƒ«ã‚¯ãƒ­ãƒ¼ãƒ³ã‚’削除 + + + + Open in Web Browser + ウェブブラウザーã§é–‹ã + + + + Open the web page for the current database in your browser + ブラウザã§ç¾åœ¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ã‚¦ã‚§ãƒ–ページを開ã + + + + Clone from Link + リンクã‹ã‚‰ã‚¯ãƒ­ãƒ¼ãƒ³ + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + データベースã®ã‚¦ã‚§ãƒ–ãƒšãƒ¼ã‚¸ã§æä¾›ã•れるURLを使ã£ã¦ã€ãƒ­ãƒ¼ã‚«ãƒ«ç·¨é›†ç”¨ã®ãƒªãƒ¢ãƒ¼ãƒˆãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’ダウンロードã™ã‚‹ã«ã¯ã€ã“れを使ã„ã¾ã™ã€‚ + + + + Refresh + æ›´æ–° + + + + Reload all data and update the views + å…¨ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’å†èª­ã¿è¾¼ã¿ã—ビューを更新ã™ã‚‹ + + + + Clone Database + データベースをクローン + + + + Open Database + データベースを開ã + + + + Open the local copy of this database + ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒ­ãƒ¼ã‚«ãƒ«ã‚³ãƒ”ーを開ã + + + + Check out Commit + コミットをãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ + + + + Download and open this specific commit + ã“ã®ç‰¹å®šã®ã‚³ãƒŸãƒƒãƒˆã‚’ダウンロードã—é–‹ã + + + + Check out Latest Commit + 最新ã®ã‚³ãƒŸãƒƒãƒˆã‚’ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ + + + + Check out the latest commit of the current branch + ç¾åœ¨ã®ãƒ–ランãƒã®æœ€æ–°ã®ã‚³ãƒŸãƒƒãƒˆã‚’ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ + + + + Save Revision to File + リヴィジョンをファイルã«ä¿å­˜ + + + + Saves the selected revision of the database to another file + データベースã®é¸æŠžã—ãŸãƒªãƒ´ã‚£ã‚¸ãƒ§ãƒ³ã‚’ã»ã‹ã®ãƒ•ァイルã«ä¿å­˜ + + + + Upload Database + データベースをアップロード + + + + Upload this database as a new commit + ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’æ–°ã—ã„コミットã¨ã—ã¦ã‚¢ãƒƒãƒ—ロード + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>ã‚ãªãŸã¯ç¾åœ¨çµ„ã¿è¾¼ã¿ã®èª­ã¿è¾¼ã¿å°‚用ã®ã‚¢ã‚¤ãƒ‡ãƒ³ãƒ†ã‚£ãƒ†ã‚£ãƒ¼ã‚’使用ã—ã¦ã„ã¾ã™ã€‚ã‚ãªãŸã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’アップロードã™ã‚‹ã«ã¯ã€ã‚ãªãŸã® DBHub.io アカウントを設定ã—使ã†å¿…è¦ãŒã‚りã¾ã™ã€‚</p><p>DBHub.io ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒã¾ã ãªã„? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">今ã™ãアカウントを作り</span></a>ã€ã‚ãªãŸã®è¨¼æ˜Žæ›¸ã‚’<a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">ã“ã“ã‹ã‚‰</span></a>インãƒãƒ¼ãƒˆã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’共有ã—ã¦ãã ã•ã„。</p><p>オンラインã®ãƒ˜ãƒ«ãƒ—ã¯<a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">ã“ã“</span></a>を見ã¦ãã ã•ã„。</p></body></html> + + + + &User + ユーザー(&U) + + + + &Database + データベース(&D) + + + + Back + 戻る + + + + Select an identity to connect + 接続ã™ã‚‹ã‚¢ã‚¤ãƒ‡ãƒ³ãƒ†ã‚£ãƒ†ã‚£ãƒ¼ã‚’é¸æŠž + + + + Public + 公開 + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + ã“れã¯ãƒ­ãƒ¼ã‚«ãƒ«ç·¨é›†ç”¨ã«ãƒªãƒ¢ãƒ¼ãƒˆã‚µãƒ¼ãƒãƒ¼ã‹ã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’ダウンロードã—ã¾ã™ã€‚ +クローン元ã®URLを入力ã—ã¦ãã ã•ã„。ã“ã®URLã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã® +ウェブページã«ã‚ã‚‹ 'Clone Database in DB4S' ボタンを +クリックã—ã¦ç”Ÿæˆã§ãã¾ã™ã€‚ + + + + Invalid URL: The host name does not match the host name of the current identity. + 䏿­£ãªURL: ホストåãŒç¾åœ¨ã®ã‚¢ã‚¤ãƒ‡ãƒ³ãƒ†ã‚£ãƒ†ã‚£ãƒ¼ã®ãƒ›ã‚¹ãƒˆåã¨ä¸€è‡´ã—ã¾ã›ã‚“。 + + + + Invalid URL: No branch name specified. + 䏿­£ãªURL: ブランãƒåãŒæŒ‡å®šã•れã¦ã„ã¾ã›ã‚“。 + + + + Invalid URL: No commit ID specified. + 䏿­£ãªURL: コミットIDãŒæŒ‡å®šã•れã¦ã„ã¾ã›ã‚“。 + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + データベースã®ãƒ­ãƒ¼ã‚«ãƒ«ã‚¯ãƒ­ãƒ¼ãƒ³ãŒç·¨é›†ã•れã¦ã„ã¾ã™ã€‚ã“ã®ã‚³ãƒŸãƒƒãƒˆã‚’フェッãƒã™ã‚‹ã¨ãƒ­ãƒ¼ã‚«ãƒ«ã®å¤‰æ›´ãŒç„¡è¦–ã•れã¾ã™ã€‚ +本当ã«å®Ÿè¡Œã—ã¾ã™ã‹? + + + + The database has unsaved changes. Are you sure you want to push it before saving? + データベースã«ä¿å­˜ã•れã¦ã„ãªã„変更ãŒã‚りã¾ã™ã€‚本当ã«ä¿å­˜å‰ã«ãƒ—ッシュã—ã¾ã™ã‹? + + + + The database you are trying to delete is currently opened. Please close it before deleting. + 削除ã—よã†ã¨ã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¯ç¾åœ¨é–‹ã‹ã‚Œã¦ã„ã¾ã™ã€‚削除å‰ã«é–‰ã˜ã¦ãã ã•ã„。 + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + ã“れã¯ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ã¾ã ã‚³ãƒŸãƒƒãƒˆã—ã¦ã„ãªã„変更ã¨å…±ã«å‰Šé™¤ã—ã¾ã™ã€‚本当ã«ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’削除ã—ã¾ã™ã‹? + + + + RemoteLocalFilesModel + + + Name + åå‰ + + + + Branch + ブランム+ + + + Last modified + 最終変更 + + + + Size + サイズ + + + + Commit + コミット + + + + File + ファイル + + + + RemoteModel + + + Name + åå‰ + + + + Commit + コミット + + + + Last modified + 最終変更 + + + + Size + サイズ + + + + Size: + サイズ: + + + + Last Modified: + 最終変更: + + + + Licence: + ライセンス: + + + + Default Branch: + デフォルトブランãƒ: + + + + RemoteNetwork + + + Choose a location to save the file + ファイルをä¿å­˜ã™ã‚‹å ´æ‰€ã‚’é¸æŠž + + + + Error opening remote file at %1. +%2 + %1 ã®ãƒªãƒ¢ãƒ¼ãƒˆãƒ•ァイルを開ãã¨ãã«ã‚¨ãƒ©ãƒ¼. +%2 + + + + Error: Invalid client certificate specified. + エラー: 䏿­£ãªã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆè¨¼æ˜Žæ›¸ãŒæŒ‡å®šã•れã¾ã—ãŸã€‚ + + + + Please enter the passphrase for this client certificate in order to authenticate. + ã“ã®ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆè¨¼æ˜Žæ›¸ã‚’確èªã™ã‚‹ãŸã‚パスフレーズを入力ã—ã¦ãã ã•ã„。 + + + + Cancel + キャンセル + + + + Uploading remote database to +%1 + リモートデータベースをã“ã“ã«ã‚¢ãƒƒãƒ—ロード中 +%1 + + + + Downloading remote database from +%1 + リモートデータベースをã“ã“ã‹ã‚‰ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ä¸­ +%1 + + + + Error: Cannot open the file for sending. + エラー: é€ä¿¡ã™ã‚‹ãƒ•ァイルを開ã‘ã¾ã›ã‚“。 + + + + RemotePushDialog + + + Push database + データベースをプッシュ + + + + Database na&me to push to + プッシュã™ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®åå‰(&M) + + + + Commit message + コミットメッセージ + + + + Database licence + データベースライセンス + + + + Public + 公開 + + + + Branch + ブランム+ + + + Force push + 強制プッシュ + + + + Username + ユーザーå + + + + Database will be public. Everyone has read access to it. + データベースを公開ã«ã—ã¾ã™ã€‚ã™ã¹ã¦ã®äººãŒã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚ + + + + Database will be private. Only you have access to it. + データベースをéžå…¬é–‹ã«ã—ã¾ã™ã€‚ã‚ãªãŸã ã‘ãŒã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚ + + + + Use with care. This can cause remote commits to be deleted. + 注æ„ã—ã¦ä½¿ç”¨ã—ã¦ãã ã•ã„。ã“れã¯ãƒªãƒ¢ãƒ¼ãƒˆã‚³ãƒŸãƒƒãƒˆãŒå‰Šé™¤ã•れるå¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚ + + + + RunSql + + + Execution aborted by user + 実行ã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ã‚ˆã‚Šä¸­æ­¢ã•れã¾ã—㟠+ + + + , %1 rows affected + , %1 行ã«å½±éŸ¿ã‚’与ãˆã¾ã—㟠+ + + + query executed successfully. Took %1ms%2 + クエリーã®å®Ÿè¡Œã«æˆåŠŸã—ã¾ã—ãŸã€‚ %1ms%2 ã‹ã‹ã‚Šã¾ã—㟠+ + + + executing query + 実行クエリー + + + + SelectItemsPopup + + + A&vailable + 使用å¯èƒ½(&V) + + + + Sele&cted + é¸æŠžæ¸ˆ(&C) + + + + SqlExecutionArea + + + Form + フォーム + + + + Find previous match [Shift+F3] + å‰ã‚’検索 [Shift+F3] + + + + Find previous match with wrapping + ワードラップ込ã¿ã§å‰ã‚’検索 + + + + Shift+F3 + + + + + The found pattern must be a whole word + å˜èªžå˜ä½ã§æ¤œç´¢ã—ã¾ã™ + + + + Whole Words + å˜èªžå˜ä½ + + + + Text pattern to find considering the checks in this frame + ã“ã®ãƒ•レームã§ã®ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã‚’考慮ã—ãŸæ¤œç´¢æ–‡å­—列 + + + + Find in editor + エディター内を検索 + + + + The found pattern must match in letter case + 大/å°æ–‡å­—を区別ã—ã¾ã™ + + + + Case Sensitive + 大/å°æ–‡å­—を区別 + + + + Find next match [Enter, F3] + 次を検索 [Enter, F3] + + + + Find next match with wrapping + ãƒžãƒƒãƒ”ãƒ³ã‚°ã§æ¬¡ã‚’検索 + + + + F3 + + + + + Interpret search pattern as a regular expression + æ­£è¦è¡¨ç¾ã§æ¤œç´¢ + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + URLã®ãŸã‚%ã®æ•°ãŒä¸€è‡´ã—ãªã„。 + <html><head/><body><p>設定ã™ã‚‹ã¨ã€æ¤œç´¢æ¡ä»¶ã¯UNIXæ­£è¦è¡¨ç¾ã¨è§£é‡ˆã•れã¾ã™ã€‚以下をå‚ç…§ <a href="https://ja.wikibooks.org/wiki/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE">Wikibooksã®æ­£è¦è¡¨ç¾</a>。</p></body></html> + + + + Regular Expression + æ­£è¦è¡¨ç¾ + + + + + Close Find Bar + 検索ãƒãƒ¼ã‚’é–‰ã˜ã‚‹ + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>最後ã«å®Ÿè¡Œã—ãŸæ–‡ã®çµæžœã€‚</p><p>ã“ã®ãƒ‘ãƒãƒ«ã‚’折りãŸãŸã‚“ã§ã€<span style=" font-style:italic;">SQL Log</span>ドックã§<span style=" font-style:italic;">ユーザー</span>ã‚’é¸æŠžã—ã¦è¡¨ç¤ºã•ã›ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚</p></body></html> + + + + This field shows the results and status codes of the last executed statements. + ã“ã®ãƒ•ィールドã«ã¯æœ€å¾Œã«å®Ÿè¡Œã—ãŸæ–‡ã®çµæžœã¨ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚³ãƒ¼ãƒ‰ãŒè¡¨ç¤ºã•れã¾ã™ã€‚ + + + + Results of the last executed statements + 最後ã«å®Ÿè¡Œã—ãŸæ–‡ã®çµæžœ + + + + Ctrl+PgUp + + + + + Ctrl+PgDown + + + + + Couldn't read file "%1": %2. + ファイル "%1" を読ã‚ã¾ã›ã‚“: %2。 + + + + + Couldn't save file: %1. + ファイルをä¿å­˜ã§ãã¾ã›ã‚“: %1. + + + + Your changes will be lost when reloading it! + å†èª­ã¿è¾¼ã¿ã™ã‚‹ã¨å¤‰æ›´ãŒå¤±ã‚れã¾ã™! + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + ファイル "%1" ã¯ä»–ã®ãƒ—ログラムã«ã‚ˆã£ã¦å¤‰æ›´ã•れã¾ã—ãŸã€‚å†èª­ã¿è¾¼ã¿ã—ã¾ã™ã‹?%2 + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + "ã™ã¹ã¦ã¯ã„"ã‚’é¸æŠžã™ã‚‹ã¨ã€å¤–部ã§è¡Œã‚ã‚ŒãŸæ›´æ–°ã‚’ã€ç¢ºèªã›ãšã«ã™ã¹ã¦å†èª­ã¿è¾¼ã¿ã—ã¾ã™ã€‚ + + + + Answer "No to All" to ignore any external update without further prompting. + "ã™ã¹ã¦ã„ã„ãˆ"ã‚’é¸æŠžã™ã‚‹ã¨ã€å¤–部ã§è¡Œã‚れãŸå¤‰æ›´ã‚’確èªã›ãšã«ã™ã¹ã¦ç„¡è¦–ã—ã¾ã™ã€‚ + + + + Modifying and saving the file will restore prompting. + ファイルを変更・ä¿å­˜ã™ã‚‹ã¨ã€ç¢ºèªãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã¯å¾©æ´»ã—ã¾ã™ã€‚ + + + + SqlTextEdit + + + Ctrl+/ + + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) abs(X) 関数ã¯ã€æ•°å€¤ã§ã‚る引数 X ã®çµ¶å¯¾å€¤ã‚’è¿”ã—ã¾ã™ã€‚ + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () changes() 関数ã¯ã€æœ€å¾Œã«æˆåŠŸã—㟠INSERT, DELETE, UPDATE æ–‡ã§ã€å¤‰æ›´ã€æŒ¿å…¥ã€å‰Šé™¤ã•れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®è¡Œæ•°ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) char(X1,X2,...,XN) 関数ã¯ã€ãれãžã‚Œã®æ–‡å­—㌠Unicode 符å·ä½ç½®ã§æ•´æ•°å€¤ X1 ã‹ã‚‰ XN ã‚’æŒã¤æ–‡å­—列を返ã—ã¾ã™ã€‚ + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) coalesce() 関数㯠NULL ã§ãªã„引数ã®ã†ã¡ã€æœ€ã‚‚å·¦ã®å¼•æ•°ã®ã‚³ãƒ”ーを返ã—ã¾ã™ã€‚ã™ã¹ã¦ã®å¼•数㌠NULL ãªã‚‰ã°ã€NULL ã‚’è¿”ã—ã¾ã™ + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) glob(X,Y) é–¢æ•°ã¯æ¬¡ã®å¼ã¨åŒå€¤ã§ã™ã€‚ "Y GLOB X". + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) ifnull() 関数㯠NULL ã§ãªã„引数ã®ã†ã¡ã€æœ€ã‚‚å·¦ã®å¼•æ•°ã®ã‚³ãƒ”ーを返ã—ã¾ã™ã€‚両方ã®å¼•数㌠NULL ãªã‚‰ã°ã€NULL ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) instr(X,Y) é–¢æ•°ã¯æ–‡å­—列 X 内ã«ã‚る最åˆã®æ–‡å­—列 Y を検索ã—ã€ãã®å‰ã®æ–‡å­—æ•°ã«1を加ãˆãŸå€¤ã‚’è¿”ã—ã¾ã™ã€‚X ã« Y ãŒãªã„å ´åˆã¯0ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) hex() 関数ã¯å¼•æ•°ã‚’ BLOB ã¨è§£é‡ˆã—ã€ãã®ä¸­èº«ã‚’大文字ã®åå…­é€²æ•°ã®æ–‡å­—列ã¨ã—ã¦è¿”ã—ã¾ã™ã€‚ + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) iif(X,Y,Z) 関数ã¯XãŒçœŸãªã‚‰ã°Yã‚’ã€ãã†ã§ãªã‘れã°Zã‚’è¿”ã—ã¾ã™ã€‚ + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () last_insert_rowid() 関数ã¯ã€ã“ã®é–¢æ•°ã‚’呼ã³å‡ºã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹æŽ¥ç¶šãŒæœ€å¾Œã« INSERT ã—ãŸè¡Œã® ROWID ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) 文字列 X ã«å¯¾ã—ã€length(X) 関数ã¯ã€æœ€åˆã® NULL 文字ã®å‰ã«ã‚る文字数(ãƒã‚¤ãƒˆæ•°ã§ãªã)ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) like() 関数㯠"Y LIKE X" å¼ã¨åŒå€¤ã§ã™ã€‚ + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) like() 関数㯠"Y LIKE X ESCAPE Z" å¼ã¨åŒå€¤ã§ã™ã€‚ + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) load_extension(X) 関数ã¯ã€åå‰ãŒ X ã®å…±æœ‰ãƒ©ã‚¤ãƒ–ラリã‹ã‚‰ã™ãã« SQLite 拡張を読ã¿è¾¼ã¿ã¾ã™ã€‚. +ã“ã®é–¢æ•°ã®ä½¿ç”¨ã«ã¯ã€è¨­å®šãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã‹ã‚‰ã®èªè¨¼ãŒå¿…è¦ã§ã™ã€‚ + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X) load_extension(X,Y) 関数ã¯ã€åå‰ãŒ X ã®å…±æœ‰ãƒ©ã‚¤ãƒ–ラリã®ã‚¨ãƒ³ãƒˆãƒªãƒ¼ãƒã‚¤ãƒ³ãƒˆ Y ã‹ã‚‰ã™ãã« SQLite 拡張を読ã¿è¾¼ã¿ã¾ã™ã€‚. +ã“ã®é–¢æ•°ã®ä½¿ç”¨ã«ã¯ã€è¨­å®šãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã‹ã‚‰ã®èªè¨¼ãŒå¿…è¦ã§ã™ã€‚ + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) lower(X) 関数ã¯ã€ã™ã¹ã¦ ASCII 文字ã§ã‚る文字列 X ã‚’ã€ã™ã¹ã¦å°æ–‡å­—ã«å¤‰æ›ã—ãŸæ–‡å­—列を返ã—ã¾ã™ã€‚ + + + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) 関数ã¯ã€X ã®å·¦ç«¯ã«ã‚る空白をå–り除ãã¾ã™ã€‚ + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) ltrim(X,Y)関数ã¯ã€X ã®å·¦ç«¯ã‹ã‚‰ã€ Y ã«å«ã¾ã‚Œã‚‹æ–‡å­—ã‚’ã™ã¹ã¦å–り除ã„ãŸæ–‡å­—列を返ã—ã¾ã™ã€‚ + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) 複数ã®å¼•æ•°ã‚’æŒã¤ max() 関数ã¯å¼•æ•°ã®æœ€å¤§å€¤ã‚’è¿”ã—ã¾ã™ã€‚引数㫠NULL ãŒå«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã¯ NULL ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) 複数ã®å¼•æ•°ã‚’æŒã¤ min() 関数ã¯å¼•æ•°ã®æœ€å°å€¤ã‚’è¿”ã—ã¾ã™ã€‚引数㫠NULL ãŒå«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã¯ NULL ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) nullif(X,Y) 関数ã¯ã€äºŒã¤ã®å¼•æ•°ãŒé•ã†å ´åˆç¬¬ä¸€å¼•æ•°ã‚’ã€åŒã˜å ´åˆã¯ NULL ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) printf(FORMAT,...) SQL 関数ã¯ã€C言語㮠sqlite3_mprintf() é–¢æ•°ã‚„ã€æ¨™æº–Cライブラリー㮠printf() 関数ã®ã‚ˆã†ã«å‹•作ã—ã¾ã™ã€‚ + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) quote(X) 関数ã¯ã€å¼•æ•°ã‚’SQLæ–‡ã«å«ã‚ã‚‹ã®ã«é©ã—ãŸSQLãƒªãƒ†ãƒ©ãƒ«ã®æ–‡å­—ã«ã—ã¦è¿”ã—ã¾ã™ã€‚ + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () random() 関数ã¯ã€ç¯„囲㌠-9223372036854775808 ã‹ã‚‰ +9223372036854775807 ã®æ•´æ•°ã§ã‚る疑似乱数を返ã—ã¾ã™ã€‚ + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) randomblob(N) 関数ã¯ã€ç–‘ä¼¼ä¹±æ•°ã§æ§‹æˆã•れ㟠N ãƒã‚¤ãƒˆã® BLOB ã‚’è¿”ã—ã¾ã™ã€‚function return an N-byte blob containing pseudo-random bytes. + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) replace(X,Y,Z) 関数ã¯ã€æ–‡å­—列 X ã«å«ã¾ã‚Œã‚‹æ–‡å­—列 Y ã‚’ã™ã¹ã¦æ–‡å­—列 Z ã«ç½®ãæ›ãˆã¦è¿”ã—ã¾ã™ã€‚ + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) round(X) 関数ã¯ã€æµ®å‹•å°æ•°ç‚¹æ•° X ã®å°æ•°ç‚¹ä»¥ä¸‹ã‚’å››æ¨äº”å…¥ã—ã¦è¿”ã—ã¾ã™ã€‚ + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) round(X,Y) 関数ã¯ã€æµ®å‹•å°æ•°ç‚¹æ•° X ã‚’å°æ•°ç‚¹ç¬¬ Y ä½ã¾ã§ã«ãªã‚‹ã‚ˆã†ã«å››æ¨äº”å…¥ã—ã¦è¿”ã—ã¾ã™ã€‚ + + + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X) 関数ã¯ã€X ã®å³ç«¯ã«ã‚る空白をå–り除ãã¾ã™ã€‚ + + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) rtrim(X,Y) 関数ã¯ã€X ã®å³ç«¯ã‹ã‚‰ã€ Y ã«å«ã¾ã‚Œã‚‹æ–‡å­—ã‚’ã™ã¹ã¦å–り除ã„ãŸæ–‡å­—列を返ã—ã¾ã™ã€‚ + + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) soundex(X) 関数ã¯ã€æ–‡å­—列 X ã‚’ soundex ã«ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã—ãŸæ–‡å­—列を返ã—ã¾ã™ã€‚ + + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) substr(X,Y) 関数ã¯ã€æ–‡å­—列 Xã®ã€å…ˆé ­ã‹ã‚‰ Y 番目ã‹ã‚‰æœ«å°¾ã¾ã§ã®æ–‡å­—列を返ã—ã¾ã™ã€‚ + + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) substr(X,Y,Z) 関数ã¯ã€æ–‡å­—列 X ã®ã€å…ˆé ­ã‹ã‚‰ Y 番目ã‹ã‚‰ Z æ–‡å­—ã®æ–‡å­—列を返ã—ã¾ã™ã€‚ + + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () total_changes() 関数ã¯ã€ç¾åœ¨é–‹ã‹ã‚ŒãŸæŽ¥ç¶šã®ã‚るデータベースã«ãŠã„ã¦ã€INSERTã€UPDATEã€DELETEã§å¤‰æ›´ã•れãŸè¡Œæ•°ã‚’è¿”ã—ã¾ã™ã€‚ returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + + + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) 関数ã¯ã€X ã®ä¸¡ç«¯ã«ã‚る空白をå–り除ãã¾ã™ã€‚ + + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) trim(X,Y) 関数ã¯ã€X ã®ä¸¡ç«¯ã‹ã‚‰ã€ Y ã«å«ã¾ã‚Œã‚‹æ–‡å­—ã‚’ã™ã¹ã¦å–り除ã„ãŸæ–‡å­—列を返ã—ã¾ã™ã€‚ + + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) typeof(X) 関数ã¯ã€å¼ X ã®ãƒ‡ãƒ¼ã‚¿åž‹ã‚’ç¤ºã™æ–‡å­—列を返ã—ã¾ã™ã€‚ + + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) unicode(X) 関数ã¯ã€æ–‡å­—列 X ã®æœ€åˆã®æ–‡å­—ã«å¯¾å¿œã™ã‚‹ Unicode 符å·ä½ç½®ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) upper(X) 関数ã¯ã€ã™ã¹ã¦ ASCII 文字ã§ã‚る文字列 X ã‚’ã€ã™ã¹ã¦å¤§æ–‡å­—ã«å¤‰æ›ã—ãŸæ–‡å­—列を返ã—ã¾ã™ã€‚ + + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) zeroblob(N) 関数ã¯ã€ã™ã¹ã¦ 0x00 ã§åŸ‹ã‚られãŸã€N ãƒã‚¤ãƒˆã® BLOB ã‚’è¿”ã—ã¾ã™ã€‚ + + + + + + + (timestring,modifier,modifier,...) + (時刻文字列, 修飾å­, 修飾å­,...) + + + + (format,timestring,modifier,modifier,...) + (フォーマット, 時刻文字列, 修飾å­, 修飾å­,...) + + + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) avg() 関数ã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—内ã®éžNULLãªå€¤ã®å¹³å‡ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) count(X) 関数ã¯ã‚°ãƒ«ãƒ¼ãƒ—内ã«ã‚ã‚‹ã€NULLã§ãªã„ X ã®ä»¶æ•°ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) group_concat() 関数ã¯ã€éžNULLãªã™ã¹ã¦ã® X を連çµã—ãŸæ–‡å­—列を返ã—ã¾ã™ã€‚ + + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) group_concat() 関数ã¯ã€éžNULLãªã™ã¹ã¦ã® X を連çµã—ãŸæ–‡å­—列を返ã—ã¾ã™ã€‚ã‚‚ã—ã€å¼•æ•° Y ãŒå­˜åœ¨ã™ã‚‹ãªã‚‰ã°ã€X を連çµã™ã‚‹ã¨ãã®åŒºåˆ‡ã‚Šæ–‡å­—ã¨ã—ã¦ä½¿ç”¨ã—ã¾ã™ã€‚ + + + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) max() 集計関数ã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—内ã®(éžNULLã§ã‚ã‚‹)最大値を返ã—ã¾ã™ã€‚ + + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) min() 集計関数ã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—内ã®(éžNULLã§ã‚ã‚‹)最å°å€¤ã‚’è¿”ã—ã¾ã™ã€‚ + + + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) sum() 㨠total() 集計関数ã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—内ã®éžNULLãªå€¤ã®åˆè¨ˆã‚’è¿”ã—ã¾ã™ã€‚ + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () ç¾åœ¨ã®åˆ†å‰²å†…ã®è¡Œç•ªå·ã€‚行ã¯ã€ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦å®šç¾©ã® ORDER BY å¥ã‚„ãれ以外ã®ä»»æ„ã®é †åºã«å¾“ã„ã€1 ã‹ã‚‰é †ã«ç•ªå·ä»˜ã‘ã•れã¾ã™ã€‚ + + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () å„グループã®é †ä½ - åŒå€¤ã¯åŒé †ä½ã§ã€æ¬¡ã®å€¤ã¯é‡è¤‡åˆ†ã ã‘é †ä½ãŒãšã‚Œã¾ã™ã€‚ã‚‚ã—ã€ORDER BY å¥ãŒãªã‘れã°ã€ã™ã¹ã¦ã®è¡Œã‚’åŒé †ä½ã¨ã¿ãªã—ã€å¸¸ã« 1 ã‚’è¿”ã—ã¾ã™ã€‚ + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () å„グループã®é †ä½ - åŒå€¤ã¯åŒé †ä½ã§ã€æ¬¡ã®å€¤ã¯é‡è¤‡ã«é–¢ã‚らãšå‰ã®é †ä½+1ã«ãªã‚Šã¾ã™ã€‚パーティションã¯ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦å®šç¾©ã® ORDER BY å¥ã‚„ãれ以外ã®ä»»æ„ã®é †åºã«å¾“ã„ã€1 ã‹ã‚‰é †ã«ç•ªå·ä»˜ã‘ã•れã¾ã™ã€‚ã‚‚ã—ã€ORDER BY å¥ãŒãªã‘れã°ã€ã™ã¹ã¦ã®è¡Œã‚’åŒé †ä½ã¨ã¿ãªã—ã€å¸¸ã« 1 ã‚’è¿”ã—ã¾ã™ã€‚ + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () ãã®åå‰ã«ã‚‚é–¢ã‚らãšã€ã“ã®é–¢æ•°ã¯å¸¸ã« 0.0 ã‹ã‚‰ 1.0 ã®å€¤ã‚’è¿”ã—ã¾ã™ã€‚ã“ã®å€¤ã¯ã€(rank - 1)/(パーティション行数 - 1) ã§ã™ã€‚ã“ã“ã§ã€rank ã¯çµ„ã¿è¾¼ã¿ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦é–¢æ•°ã® rank()ã€ãƒ‘ーティション行数ã¯ãƒ‘ーティション内ã®è¡Œã®æ•°ã§ã™ã€‚ã‚‚ã—ã€ãƒ‘ーティションã«1行ã—ã‹å«ã¾ã‚Œã¦ã„ãªã‘れã°ã€ã“ã®é–¢æ•°ã¯ 0.0 ã‚’è¿”ã—ã¾ã™ã€‚ + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () ç´¯ç©åˆ†å¸ƒã€‚(行番å·)/(パーティション行数) ã§è¨ˆç®—ã•れã¾ã™ã€‚ã“ã“ã§è¡Œç•ªå·ã¯ã‚°ãƒ«ãƒ¼ãƒ—内㧠row_number() ã§è¿”ã•れãŸå€¤ã€ãƒ‘ーティション行数ã¯ãƒ‘ーティション内ã®è¡Œã®æ•°ã§ã™ã€‚ + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) 引数 N ã¯INTEGERã¨ã—ã¦æ‰±ã‚れã¾ã™ã€‚ã“ã®é–¢æ•°ã¯ãƒ‘ーティションを ORDER BY å¥ã‚„ãれ以外ã®ä»»æ„ã®é †åºã«å¾“ã„ N 個ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å¯èƒ½ãªé™ã‚Šç­‰åˆ†ã—ã€ãれãžã‚Œã®ã‚°ãƒ«ãƒ¼ãƒ—ã« 1 ã‹ã‚‰ N ã®INTEGERã‚’ã¤ã‘ã¾ã™ã€‚å¿…è¦ãŒã‚れã°ã€å…ˆé ­ã®ã»ã†ã«ã‚るグループã®ä»¶æ•°ã‚’多ãã™ã‚‹ã‚ˆã†ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¾ã™ã€‚ã“ã®é–¢æ•°ã¯ç¾åœ¨ã®è¡ŒãŒå«ã¾ã‚Œã‚‹ã‚°ãƒ«ãƒ¼ãƒ—ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸINTEGERã‚’è¿”ã—ã¾ã™ã€‚ + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) パーティション内ã®å‰ã®è¡Œã«å¯¾ã—ã¦å¼ expr を評価ã—ãŸçµæžœã‚’è¿”ã—ã¾ã™ã€‚(先頭行ã®ãŸã‚)å‰ã®è¡ŒãŒãªã‘れã°ã€NULLã‚’è¿”ã—ã¾ã™ã€‚ + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr,offset) 引数 offset ãŒä¸Žãˆã‚‰ã‚Œã‚‹å ´åˆã€éžè² ã®INTEGERã§ã‚ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚ã“ã®å ´åˆã€ãƒ‘ーティション内㮠offset ã ã‘å‰ã®è¡Œã«å¯¾ã—ã¦å¼ expr を評価ã—ãŸçµæžœã‚’è¿”ã—ã¾ã™ã€‚offset ㌠0 ãªã‚‰ã°ã€ç¾åœ¨è¡Œã«å¯¾ã—ã¦è©•価ã—ã¾ã™ã€‚å‰ã®è¡ŒãŒãªã‘れã°ã€NULLã‚’è¿”ã—ã¾ã™ã€‚ + + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,offset,default) default ãŒä¸Žãˆã‚‰ã‚Œã‚‹å ´åˆã€è©²å½“ã®è¡ŒãŒãªã‘れã°ã€NULL ã®ä»£ã‚り㫠defaul 値を返ã—ã¾ã™ã€‚ + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) ãƒ‘ãƒ¼ãƒ†ã‚£ã‚·ãƒ§ãƒ³å†…ã®æ¬¡ã®è¡Œã«å¯¾ã—ã¦å¼ expr を評価ã—ãŸçµæžœã‚’è¿”ã—ã¾ã™ã€‚(最終行ã®ãŸã‚)次ã®è¡ŒãŒãªã‘れã°ã€NULLã‚’è¿”ã—ã¾ã™ã€‚ + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,offset) 引数 offset ãŒä¸Žãˆã‚‰ã‚Œã‚‹å ´åˆã€éžè² ã®INTEGERã§ã‚ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚ã“ã®å ´åˆã€ãƒ‘ーティション内㮠offset ã ã‘次ã®è¡Œã«å¯¾ã—ã¦å¼ expr を評価ã—ãŸçµæžœã‚’è¿”ã—ã¾ã™ã€‚offset ㌠0 ãªã‚‰ã°ã€ç¾åœ¨è¡Œã«å¯¾ã—ã¦è©•価ã—ã¾ã™ã€‚次ã®è¡ŒãŒãªã‘れã°ã€NULLã‚’è¿”ã—ã¾ã™ã€‚ + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) ã“ã®çµ„ã¿è¾¼ã¿ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦é–¢æ•°ã¯ã€åŒã˜é›†è¨ˆã‚¦ã‚£ãƒ³ãƒ‰ã‚¦é–¢æ•°ã‚’使ã£ã¦ãれãžã‚Œã®è¡Œã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãƒ•レームを計算ã—ã¾ã™ã€‚å„行ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãƒ•ãƒ¬ãƒ¼ãƒ ã®æœ€åˆã®è¡Œã«å¯¾ã—ã¦è©•価ã•れる expr ã®å€¤ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) ã“ã®çµ„ã¿è¾¼ã¿ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦é–¢æ•°ã¯ã€åŒã˜é›†è¨ˆã‚¦ã‚£ãƒ³ãƒ‰ã‚¦é–¢æ•°ã‚’使ã£ã¦ãれãžã‚Œã®è¡Œã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãƒ•レームを計算ã—ã¾ã™ã€‚å„行ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãƒ•ãƒ¬ãƒ¼ãƒ ã®æœ€å¾Œã®è¡Œã«å¯¾ã—ã¦è©•価ã•れる expr ã®å€¤ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr,N) ã“ã®çµ„ã¿è¾¼ã¿ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦é–¢æ•°ã¯ã€åŒã˜é›†è¨ˆã‚¦ã‚£ãƒ³ãƒ‰ã‚¦é–¢æ•°ã‚’使ã£ã¦ãれãžã‚Œã®è¡Œã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãƒ•レームを計算ã—ã¾ã™ã€‚å„行ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ãƒ•レーム㮠N 番目ã®è¡Œã«å¯¾ã—ã¦è©•価ã•れる expr ã®å€¤ã‚’è¿”ã—ã¾ã™ã€‚行ã¯ã€ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦å®šç¾©ã® ORDER BY å¥ã‚„ãれ以外ã®ä»»æ„ã®é †åºã«å¾“ã„ã€1 ã‹ã‚‰é †ã«ç•ªå·ä»˜ã‘ã•れã¾ã™ã€‚ N 番目ã®è¡ŒãŒãƒ‘ーティションã«ãªã„å ´åˆã€NULL ãŒè¿”ã•れã¾ã™ã€‚ + + + + (X) Return the arccosine of X. The result is in radians. + (X) Xã®é€†ä½™å¼¦(arccos)ã‚’è¿”ã—ã¾ã™ã€‚çµæžœã¯ãƒ©ã‚¸ã‚¢ãƒ³å˜ä½ã§ã™ã€‚ + + + + (X) Return the hyperbolic arccosine of X. + (X) Xã®é€†åŒæ›²ç·šä½™å¼¦(arcosh)ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X) Return the arcsine of X. The result is in radians. + (X) Xã®é€†æ­£å¼¦(arcsin)ã‚’è¿”ã—ã¾ã™ã€‚çµæžœã¯ãƒ©ã‚¸ã‚¢ãƒ³å˜ä½ã§ã™ã€‚ + + + + (X) Return the hyperbolic arcsine of X. + (X) Xã®é€†åŒæ›²ç·šæ­£å¼¦(arsinh)ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X) Return the arctangent of X. The result is in radians. + (X) Xã®é€†æ­£æŽ¥(arctan)ã‚’è¿”ã—ã¾ã™ã€‚çµæžœã¯ãƒ©ã‚¸ã‚¢ãƒ³å˜ä½ã§ã™ã€‚ + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + (X,Y) Y/Xã®é€†æ­£æŽ¥(arctan)ã‚’è¿”ã—ã¾ã™ã€‚ çµæžœã¯ãƒ©ã‚¸ã‚¢ãƒ³å˜ä½ã§ã™ã€‚çµæžœã¯Xã¨Yã®ç¬¦å·ã«ã‚ˆã‚Šæ­£ã—ã„象é™ã«é…ç½®ã•れã¾ã™ã€‚ + + + + (X) Return the hyperbolic arctangent of X. + (X) Xã®é€†åŒæ›²ç·šæ­£æŽ¥(artanh)ã‚’è¿”ã—ã¾ã™ã€‚ + + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + (X) Xä»¥ä¸Šã§æœ€å°ã®æ•´æ•°ã‚’è¿”ã—ã¾ã™ã€‚XãŒæ­£ãªã‚‰ã°0ã‹ã‚‰é ã–ã‹ã‚‹ã‚ˆã†ã«ä¸¸ã‚ã¾ã™ã€‚XãŒè² ãªã‚‰ã°0ã«è¿‘ã¥ãよã†ã«ä¸¸ã‚ã¾ã™ã€‚ + + + + (X) Return the cosine of X. X is in radians. + (X) Xã®ä½™å¼¦ã‚’è¿”ã—ã¾ã™ã€‚Xã¯ãƒ©ã‚¸ã‚¢ãƒ³å˜ä½ã§ã™ã€‚ + + + + (X) Return the hyperbolic cosine of X. + (X) Xã®åŒæ›²ç·šä½™å¼¦ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X) Convert value X from radians into degrees. + (X) Xをラジアンã‹ã‚‰åº¦ã«å¤‰æ›ã—ã¾ã™ã€‚ + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + (X) e (オイラー数ã€ç´„2.71828182845905) ã®X乗を計算ã—ã¾ã™ã€‚ + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + (X) Xä»¥ä¸‹ã§æœ€å¤§ã®æ•´æ•°ã‚’è¿”ã—ã¾ã™ã€‚XãŒæ­£ãªã‚‰ã°0ã«è¿‘ã¥ãよã†ã«ä¸¸ã‚ã¾ã™ã€‚XãŒè² ãªã‚‰ã°0ã‹ã‚‰é ã–ã‹ã‚‹ã‚ˆã†ã«ä¸¸ã‚ã¾ã™ã€‚ + + + + (X) Return the natural logarithm of X. + (X) Xã®è‡ªç„¶å¯¾æ•°ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (B,X) Return the base-B logarithm of X. + (B,X) 底をBã¨ã—ã¦Xã®å¯¾æ•°ã‚’è¿”ã—ã¾ã™ã€‚ + + + + + + (X) Return the base-10 logarithm for X. + (X) 底を10ã¨ã—ã¦Xã®å¯¾æ•°ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X) Return the logarithm base-2 for the number X. + (X) 底を2ã¨ã—ã¦Xã®å¯¾æ•°ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X,Y) Return the remainder after dividing X by Y. + (X,Y) Xã‚’Yã§å‰²ã£ãŸã¨ãã®å‰°ä½™ã‚’è¿”ã—ã¾ã™ã€‚ + + + + () Return an approximation for Ï€. + () Ï€ã®è¿‘似値を返ã—ã¾ã™ã€‚ + + + + + (X,Y) Compute X raised to the power Y. + (X,Y) Xã®Y情を計算ã—ã¾ã™ã€‚ + + + + (X) Convert X from degrees into radians. + (X) Xを度ã‹ã‚‰ãƒ©ã‚¸ã‚¢ãƒ³ã«å¤‰æ›ã—ã¾ã™ã€‚ + + + + (X) Return the sine of X. X is in radians. + (X) Xã®æ­£å¼¦ã‚’è¿”ã—ã¾ã™ã€‚Xã¯ãƒ©ã‚¸ã‚¢ãƒ³å˜ä½ã§ã™ã€‚ + + + + (X) Return the hyperbolic sine of X. + (X) Xã®åŒæ›²ç·šæ­£å¼¦ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X) Return the square root of X. NULL is returned if X is negative. + (X) Xã®å¹³æ–¹æ ¹ã‚’è¿”ã—ã¾ã™ã€‚XãŒè² ãªã‚‰ã°NULLã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X) Return the tangent of X. X is in radians. + (X) Xã®æ­£æŽ¥ã‚’è¿”ã—ã¾ã™ã€‚Xã¯ãƒ©ã‚¸ã‚¢ãƒ³å˜ä½ã§ã™ã€‚ + + + + (X) Return the hyperbolic tangent of X. + (X) Xã®åŒæ›²ç·šæ­£æŽ¥ã‚’è¿”ã—ã¾ã™ã€‚ + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + (X) Xã¨0ã®é–“ã«ã‚ã‚‹ã€0ã‹ã‚‰æœ€ã‚‚é ã„æ•´æ•°ã‚’è¿”ã—ã¾ã™ã€‚è¨€ã„æ›ãˆã‚‹ã¨ã€Xã‚’0ã«è¿‘ã¥ãよã†ã«ä¸¸ã‚ã¾ã™ã€‚ + + + + SqliteTableModel + + + reading rows + 行を読ã¿è¾¼ã¿ä¸­ + + + + loading... + 読ã¿è¾¼ã¿ä¸­... + + + + References %1(%2) +Hold %3Shift and click to jump there + ã“れをå‚ç…§ %1(%2) +%3Shift ã‚’ä¿æŒã—クリックã§ã‚¸ãƒ£ãƒ³ãƒ— + + + + Error changing data: +%1 + データã®å¤‰æ›´ã§ã‚¨ãƒ©ãƒ¼: +%1 + + + + retrieving list of columns + カラムã®ä¸€è¦§ã‚’å–得中 + + + + Fetching data... + データをå–得中... + + + + + Cancel + キャンセル + + + + TableBrowser + + + Browse Data + データ閲覧 + + + + &Table: + テーブル(&T): + + + + Select a table to browse data + 閲覧ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ã®ãƒ†ãƒ¼ãƒ–ãƒ«ã‚’é¸æŠž + + + + Use this list to select a table to be displayed in the database view + ã“ã®ä¸€è¦§ã‚’使ã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ“ューã«è¡¨ç¤ºã™ã‚‹ãƒ†ãƒ¼ãƒ–ãƒ«ã‚’é¸æŠž + + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + ã“れã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ†ãƒ¼ãƒ–ルã®ãƒ“ューã§ã™ã€‚ä»¥ä¸‹ã®æ“作ãŒã§ãã¾ã™: + - 値をインライン編集ã§ãã¾ã™ã€‚ + - レコードをダブルクリックã™ã‚‹ã¨ã€ã‚»ãƒ«ç·¨é›†ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§å†…容を編集ã§ãã¾ã™ã€‚ + - Alt+Del ã§ã‚»ãƒ«ã®å†…容をNULLã«ã§ãã¾ã™ã€‚ + - Ctrl+" ã§ç¾åœ¨ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’複製ã§ãã¾ã™ã€‚ + - Ctrl+' ã§ä¸Šã®ã‚»ãƒ«ã®å€¤ã‚’コピーã§ãã¾ã™ã€‚ + - é€šå¸¸ã®æ“作ã§ã€é¸æŠž/コピー/貼り付ã‘ãŒã§ãã¾ã™ã€‚ + + + + Text pattern to find considering the checks in this frame + ã“ã®ãƒ•レームã§ã®ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã‚’考慮ã—ãŸæ¤œç´¢æ–‡å­—列 + + + + Find in table + テーブルを検索 + + + + Find previous match [Shift+F3] + å‰ã‚’検索 [Shift+F3] + + + + Find previous match with wrapping + 折り返ã—ã¦å‰ã‚’検索 + + + + Shift+F3 + + + + + Find next match [Enter, F3] + 次を検索 [Enter, F3] + + + + Find next match with wrapping + 折り返ã—ã¦æ¬¡ã‚’検索 + + + + F3 + + + + + The found pattern must match in letter case + 大/å°æ–‡å­—を区別ã—ã¾ã™ + + + + Case Sensitive + 大/å°æ–‡å­—を区別 + + + + The found pattern must be a whole word + å˜èªžå˜ä½ã§æ¤œç´¢ã—ã¾ã™ + + + + Whole Cell + セル全体ã«ä¸€è‡´ + + + + Interpret search pattern as a regular expression + æ­£è¦è¡¨ç¾ã§æ¤œç´¢ + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>設定ã™ã‚‹ã¨ã€æ¤œç´¢æ¡ä»¶ã¯UNIXæ­£è¦è¡¨ç¾ã¨è§£é‡ˆã•れã¾ã™ã€‚以下をå‚ç…§ <a href="https://ja.wikibooks.org/wiki/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE">Wikibooksã®æ­£è¦è¡¨ç¾</a>。</p></body></html> + + + + Regular Expression + æ­£è¦è¡¨ç¾ + + + + + Close Find Bar + 検索ãƒãƒ¼ã‚’é–‰ã˜ã‚‹ + + + + Text to replace with + ã“ã®æ–‡å­—列ã§ç½®ãæ›ãˆã‚‹ + + + + Replace with + ç½®æ› + + + + Replace next match + 次ã«ä¸€è‡´ã—ãŸã‚‚ã®ã‚’ç½®ãæ›ãˆ + + + + + Replace + ç½®æ› + + + + Replace all matches + 一致ã—ãŸã‚‚ã®ã™ã¹ã¦ã‚’ç½®ãæ›ãˆ + + + + Replace all + ã™ã¹ã¦ç½®æ› + + + + Export to &JSON + JSONã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ(&J) + + + + + Export the filtered data to JSON + フィルターã•れãŸãƒ‡ãƒ¼ã‚¿ã‚’JSONã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + ã“ã®ãƒœã‚¿ãƒ³ã¯é–²è¦§ä¸­ã®ãƒ†ãƒ¼ãƒ–ルデータをç¾åœ¨ã®è¡¨ç¤ºé€šã‚Šã«(フィルターã€è¡¨ç¤ºãƒ•ォーマットã€ã‚«ãƒ©ãƒ ã®é †ç•ªã‚’ç¶­æŒã—ã¦)JSONファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚ + + + + Copy column name + カラムåをコピー + + + + Copy the database table column name to your clipboard + データベース テーブル カラムåをクリップボードã«ã‚³ãƒ”ー + + + + New Data Browser + æ–°ã—ã„データ閲覧 + + + + + Add a new docked Data Browser + æ–°ã—ãドッキングã—ãŸãƒ‡ãƒ¼ã‚¿é–²è¦§ã‚’追加 + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + ã“ã®ãƒœã‚¿ãƒ³ã¯æ–°ã—ãドッキングã—ãŸãƒ‡ãƒ¼ã‚¿é–²è¦§ã‚’追加ã—ã¾ã™ã€‚ã“れã¯é•ã†ãƒ¬ã‚¤ã‚¢ã‚¦ãƒˆã§åˆ‡ã‚Šé›¢ã—ã¦é…ç½®ã§ãã¾ã™ã€‚ + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + 先頭㸠+ + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>ã“ã®ãƒœã‚¿ãƒ³ã‚’クリックã™ã‚‹ã¨ã€ä¸Šã®ãƒ†ãƒ¼ãƒ–ルビューを先頭ã¾ã§ç§»å‹•ã—ã¾ã™ã€‚</p></body></html> + + + + |< + |< + + + + Scroll one page upwards + 1ページå‰ã¸ + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>ã“ã®ãƒœã‚¿ãƒ³ã‚’クリックã™ã‚‹ã¨ã€ä¸Šã®ãƒ†ãƒ¼ãƒ–ルビューを1ページå‰ã¸ç§»å‹•ã—ã¾ã™ã€‚</p></body></html> + + + + < + < + + + + 0 - 0 of 0 + 0 - 0 of 0 + + + + Scroll one page downwards + 1ページ後㸠+ + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>ã“ã®ãƒœã‚¿ãƒ³ã‚’クリックã™ã‚‹ã¨ã€ä¸Šã®ãƒ†ãƒ¼ãƒ–ルビューを1ページ後ã¸ç§»å‹•ã—ã¾ã™ã€‚</p></body></html> + + + + > + > + + + + Scroll to the end + 末尾㸠+ + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>ã“ã®ãƒœã‚¿ãƒ³ã‚’クリックã™ã‚‹ã¨ã€ä¸Šã®ãƒ†ãƒ¼ãƒ–ãƒ«ãƒ“ãƒ¥ãƒ¼ã®æœ«å°¾ã¾ã§ç§»å‹•ã—ã¾ã™ã€‚</p></body></html> + + + + >| + >| + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>ã“ã“をクリックã—ã¦æŒ‡å®šã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¾ã§ç§»å‹•</p></body></html> + + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>ã“ã®ãƒœã‚¿ãƒ³ã¯ ã“ã“ã¸ç§»å‹• ã®å…¥åŠ›æ¬„ã§æŒ‡å®šã•れãŸç•ªå·ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¸ç§»å‹•ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã—ã¾ã™ã€‚</p></body></html> + + + + Go to: + ã“ã“ã¸ç§»å‹•: + + + + Enter record number to browse + 閲覧ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ç•ªå·ã‚’入力 + + + + Type a record number in this area and click the Go to: button to display the record in the database view + ã“ã®æ¬„ã«ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ç•ªå·ã‚’入力ã—ã€ã“ã“ã¸ç§»å‹•ボタンをクリックã™ã‚‹ã¨ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ“ューã«ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒè¡¨ç¤ºã•れã¾ã™ + + + + 1 + 1 + + + + Show rowid column + rowidカラムを表示 + + + + Toggle the visibility of the rowid column + rowidカラムã®è¡¨ç¤ºã‚’切り替ãˆã¾ã™ + + + + Unlock view editing + ビューã®ç·¨é›†ã‚’開放 + + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + ã“れã¯ç¾åœ¨ã®ãƒ“ューã§ç·¨é›†ã§ãるよã†ã«ã—ã¾ã™ã€‚ã—ã‹ã—ã€ç·¨é›†æ™‚ã®ãƒˆãƒªã‚¬ãƒ¼ã«å¯¾å¿œã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚ + + + + Edit display format + 表示書å¼ã‚’編集 + + + + Edit the display format of the data in this column + ã“ã®ã‚«ãƒ©ãƒ ã®ãƒ‡ãƒ¼ã‚¿ã®è¡¨ç¤ºæ›¸å¼ã‚’編集ã—ã¾ã™ + + + + + New Record + æ–°ã—ã„レコード + + + + + Insert a new record in the current table + æ–°ã—ã„レコードをç¾åœ¨ã®ãƒ†ãƒ¼ãƒ–ãƒ«ã«æŒ¿å…¥ + + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>ã“ã®ãƒœã‚¿ãƒ³ã¯æ–°ã—ã„レコードをデータベースã«ä½œæˆã—ã¾ã™ã€‚マウスボタンを押ã—ãŸã¾ã¾ã«ã™ã‚‹ã¨ã€é•ã†ã‚ªãƒ—ションã®ãƒãƒƒãƒ—アップメニューãŒé–‹ãã¾ã™:</p><ul><li><span style=" font-weight:600;">æ–°ã—ã„レコード</span>: データベースã«ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå€¤ã§æ–°ã—ã„レコードを挿入ã—ã¾ã™ã€‚</li><li><span style=" font-weight:600;">値を挿入...</span>: ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æŒ¿å…¥ã™ã‚‹å‰ã«ãƒ‡ãƒ¼ã‚¿ã‚’入力ã™ã‚‹ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã‚’é–‹ãã¾ã™ã€‚ã“れã§ä»–ã®åˆ¶ç´„を満ãŸã™å€¤ãŒå…¥åŠ›ã§ãã¾ã™ã€‚ã“ã®ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã¯<span style=" font-weight:600;">æ–°ã—ã„レコード</span>オプションãŒãれらã®åˆ¶ç´„ã®ã›ã„ã§å¤±æ•—ã—ãŸã¨ãã«ã‚‚é–‹ãã¾ã™ã€‚</li></ul></body></html> + + + + + Delete Record + レコードを削除 + + + + Delete the current record + ç¾åœ¨ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除 + + + + + This button deletes the record or records currently selected in the table + ã“ã®ãƒœã‚¿ãƒ³ã¯ãƒ†ãƒ¼ãƒ–ルã«ã‚ã‚‹ç¾åœ¨é¸æŠžä¸­ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã—ã¾ã™ + + + + + Insert new record using default values in browsed table + 閲覧中ã®ãƒ†ãƒ¼ãƒ–ルã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå€¤ã‚’ä½¿ã„æ–°ã—ã„レコードを挿入ã—ã¾ã™ + + + + Insert Values... + 値を挿入... + + + + + Open a dialog for inserting values in a new record + æ–°ã—ã„レコードã«å€¤ã‚’挿入ã™ã‚‹ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã‚’é–‹ãã¾ã™ + + + + Export to &CSV + CSVã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ(&C) + + + + + Export the filtered data to CSV + フィルターã•れãŸãƒ‡ãƒ¼ã‚¿ã‚’CSVã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + ã“ã®ãƒœã‚¿ãƒ³ã¯é–²è¦§ä¸­ã®ãƒ†ãƒ¼ãƒ–ルã®ãƒ‡ãƒ¼ã‚¿ã‚’ç¾åœ¨ã®è¡¨ç¤ºé€šã‚Š(フィルターã€è¡¨ç¤ºå½¢å¼ã€ã‚«ãƒ©ãƒ é †ç•ª)ã«CSVファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚ + + + + Save as &view + ビューã¨ã—ã¦ä¿å­˜(&V) + + + + + Save the current filter, sort column and display formats as a view + ç¾åœ¨ã®ãƒ•ィルターã€ã‚«ãƒ©ãƒ é †ç•ªã€è¡¨ç¤ºå½¢å¼ã‚’ビューã«ä¿å­˜ + + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + ã“ã®ãƒœã‚¿ãƒ³ã¯é–²è¦§ä¸­ã®ãƒ†ãƒ¼ãƒ–ルã®ç¾åœ¨ã®è¡¨ç¤ºè¨­å®š(フィルターã€è¡¨ç¤ºå½¢å¼ã€ã‚«ãƒ©ãƒ é †ç•ª)ã‚’SQLビューã¨ã—ã¦ä¿å­˜ã—ã€ã‚ã¨ã§é–²è¦§ã‚„SQLæ–‡ã¨ã—ã¦ä½¿ç”¨ã§ãるよã†ã«ã—ã¾ã™ã€‚ + + + + Save Table As... + テーブルã«åå‰ã‚’付ã‘ã¦ä¿å­˜... + + + + + Save the table as currently displayed + ç¾åœ¨è¡¨ç¤ºã•れã¦ã„ã‚‹ã‚‚ã®ã‚’テーブルã«ä¿å­˜ + + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>ã“ã®ãƒãƒƒãƒ—アップメニューã¯ç¾åœ¨é–²è¦§ã—ã¦ã„るテーブルã«é©ç”¨ã•れる以下ã®ã‚ªãƒ—ションをæä¾›ã—ã¾ã™ã€‚:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">CSVã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ: ã“ã®ã‚ªãƒ—ションã¯é–²è¦§ä¸­ã®ãƒ†ãƒ¼ãƒ–ルã®ãƒ‡ãƒ¼ã‚¿ã‚’ç¾åœ¨ã®è¡¨ç¤ºé€šã‚Š(フィルターã€è¡¨ç¤ºå½¢å¼ã€ã‚«ãƒ©ãƒ é †ç•ª)ã«CSVファイルã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ビューã¨ã—ã¦ä¿å­˜: ã“ã®ã‚ªãƒ—ションã¯é–²è¦§ä¸­ã®ãƒ†ãƒ¼ãƒ–ルã®ç¾åœ¨ã®è¡¨ç¤ºè¨­å®š(フィルターã€è¡¨ç¤ºå½¢å¼ã€ã‚«ãƒ©ãƒ é †ç•ª)ã‚’SQLビューã¨ã—ã¦ä¿å­˜ã—ã€ã‚ã¨ã§é–²è¦§ã‚„SQLæ–‡ã¨ã—ã¦ä½¿ç”¨ã§ãるよã†ã«ã—ã¾ã™ã€‚</li></ul></body></html> + + + + Hide column(s) + カラムを隠㙠+ + + + Hide selected column(s) + é¸æŠžã—ãŸã‚«ãƒ©ãƒ ã‚’éš ã™ + + + + Show all columns + ã™ã¹ã¦ã®ã‚«ãƒ©ãƒ ã‚’表示 + + + + Show all columns that were hidden + éš ã•れãŸã™ã¹ã¦ã®ã‚«ãƒ©ãƒ ã‚’表示 + + + + + Set encoding + エンコードã®è¨­å®š + + + + Change the encoding of the text in the table cells + テーブルã®ã‚»ãƒ«ã«ã‚るテキストã®ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã‚’変更ã—ã¾ã™ + + + + Set encoding for all tables + ã™ã¹ã¦ã®ãƒ†ãƒ¼ãƒ–ルã®ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã®è¨­å®š + + + + Change the default encoding assumed for all tables in the database + データベース内ã®ã™ã¹ã¦ã®ãƒ†ãƒ¼ãƒ–ルã®ãƒ‡ãƒ•ォルトエンコードを変更ã—ã¾ã™ + + + + Clear Filters + フィルターを削除 + + + + Clear all filters + ã™ã¹ã¦ã®ãƒ•ィルターを消去 + + + + + This button clears all the filters set in the header input fields for the currently browsed table. + ã“ã®ãƒœã‚¿ãƒ³ã§ç¾åœ¨é–²è¦§ã—ã¦ã„るテーブルã®ãƒ˜ãƒƒãƒ€ãƒ¼å…¥åŠ›æ¬„ã«è¨­å®šã•れãŸã™ã¹ã¦ã®ãƒ•ィルターを消去ã—ã¾ã™ã€‚ + + + + Clear Sorting + ä¸¦ã¹æ›¿ãˆã‚’解除 + + + + Reset the order of rows to the default + 行ã®é †ç•ªã‚’デフォルトã«ãƒªã‚»ãƒƒãƒˆã—ã¾ã™ + + + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + ã“ã®ãƒœã‚¿ãƒ³ã¯ã€ç¾åœ¨é–²è¦§ä¸­ã®ãƒ†ãƒ¼ãƒ–ルã«ã‚ã‚‹ä¸¦ã³æ›¿ãˆãŸã‚«ãƒ©ãƒ ã‚’デフォルトã®é †ç•ªã«æˆ»ã—ã¾ã™ã€‚ + + + + Print + å°åˆ· + + + + Print currently browsed table data + ç¾åœ¨é–²è¦§ä¸­ã®ãƒ†ãƒ¼ãƒ–ルデータをå°åˆ· + + + + Print currently browsed table data. Print selection if more than one cell is selected. + ç¾åœ¨é–²è¦§ä¸­ã®ãƒ†ãƒ¼ãƒ–ルデータをå°åˆ·ã—ã¾ã™ã€‚複数ã®ã‚»ãƒ«ã‚’é¸æŠžã—ã¦ã„ã‚‹å ´åˆã€é¸æŠžç¯„囲をå°åˆ·ã—ã¾ã™ã€‚ + + + + Ctrl+P + + + + + Refresh + æ›´æ–° + + + + Refresh the data in the selected table + é¸æŠžã—ãŸãƒ†ãƒ¼ãƒ–ルã®ãƒ‡ãƒ¼ã‚¿ã‚’æ›´æ–° + + + + This button refreshes the data in the currently selected table. + ã“ã®ãƒœã‚¿ãƒ³ã§ç¾åœ¨é¸æŠžã—ã¦ã„るテーブルã®ãƒ‡ãƒ¼ã‚¿ã‚’æ›´æ–°ã—ã¾ã™ã€‚ + + + + F5 + + + + + Find in cells + セル内を検索 + + + + Open the find tool bar which allows you to search for values in the table view below. + テーブルビューã®ä¸‹ã«å€¤ã‚’検索ã™ã‚‹ãŸã‚ã®æ¤œç´¢ãƒ„ールãƒãƒ¼ã‚’é–‹ãã¾ã™ã€‚ + + + + Freeze columns + カラムを固定ã™ã‚‹ + + + + Make all columns from the first column up to this column not move when scrolling horizontally + 水平方å‘ã«ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«ã—ã¦ã‚‚ã€å…ˆé ­ã‹ã‚‰ã“ã®ã‚«ãƒ©ãƒ ã¾ã§ã‚’移動ã—ãªã„よã†ã«ã—ã¾ã™ + + + + + Bold + 太字 + + + + Ctrl+B + + + + + + Italic + イタリック + + + + + Underline + 下線 + + + + Ctrl+U + + + + + + Align Right + 峿ƒãˆ + + + + + Align Left + å·¦æƒãˆ + + + + + Center Horizontally + 中央æƒãˆ + + + + + Justify + å‡ç­‰å‰²ä»˜ + + + + + Edit Conditional Formats... + æ¡ä»¶ä»˜ã書å¼ã‚’編集... + + + + Edit conditional formats for the current column + ç¾åœ¨ã®ã‚«ãƒ©ãƒ ã®æ¡ä»¶ä»˜ã書å¼ã‚’編集ã—ã¾ã™ + + + + Clear Format + 書å¼ã‚’削除 + + + + Clear All Formats + ã™ã¹ã¦ã®æ›¸å¼ã‚’削除 + + + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + é¸æŠžã—ãŸã‚»ãƒ«ã®ã™ã¹ã¦ã®æ›¸å¼ã‚’削除ã—ã€é¸æŠžã—ãŸã‚«ãƒ©ãƒ ã®ã™ã¹ã¦ã®æ¡ä»¶ä»˜ã書å¼ã‚’削除ã—ã¾ã™ + + + + + Font Color + フォント色 + + + + + Background Color + 背景色 + + + + Toggle Format Toolbar + フォーマットツールãƒãƒ¼ã‚’切り替㈠+ + + + Show/hide format toolbar + フォーマットツールãƒãƒ¼ã‚’表示/éžè¡¨ç¤ºã—ã¾ã™ + + + + + This button shows or hides the formatting toolbar of the Data Browser + ã“ã®ãƒœã‚¿ãƒ³ã§ãƒ‡ãƒ¼ã‚¿é–²è¦§ã®æ›¸å¼ãƒ„ールãƒãƒ¼ã‚’表示/éžè¡¨ç¤ºã—ã¾ã™ + + + + Select column + ã‚«ãƒ©ãƒ ã‚’é¸æŠž + + + + Ctrl+Space + + + + + Replace text in cells + セル内ã®ãƒ†ã‚­ã‚¹ãƒˆã‚’ç½®ãæ›ãˆ + + + + Filter in any column + ä»»æ„ã®ã‚«ãƒ©ãƒ ã‚’フィルター + + + + Ctrl+R + + + + + %n row(s) + + %n 行 + + + + + , %n column(s) + + , %n カラム + + + + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . åˆè¨ˆ: %1; å¹³å‡: %2; 最低: %3; 最高: %4 + + + + Conditional formats for "%1" + "%1" ã®æ¡ä»¶ä»˜ãæ›¸å¼ + + + + determining row count... + 行数を計算中... + + + + %L1 - %L2 of >= %L3 + %L1 - %L2 of >= %L3 + + + + %L1 - %L2 of %L3 + %L1 - %L2 of %L3 + + + + (clipped at %L1 rows) + (%L1 行を抜ã出ã—) + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + ã“ã®ãƒ“ューã§ã®ç·¨é›†ã‚’有効ã«ã™ã‚‹ãŸã‚ã€ç–‘似主キーを入力ã—ã¦ãã ã•ã„。ビューã«ä¸€æ„ãªã‚«ãƒ©ãƒ ã®åå‰ãŒå¿…è¦ã§ã™ã€‚ + + + + Delete Records + レコードを削除 + + + + Duplicate records + レコードを複製 + + + + Duplicate record + レコードを複製 + + + + Ctrl+" + + + + + Adjust rows to contents + 行を内容ã«åˆã‚ã›èª¿æ•´ + + + + Error deleting record: +%1 + レコードã®å‰Šé™¤ã§ã‚¨ãƒ©ãƒ¼: +%1 + + + + Please select a record first + 最åˆã«ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’é¸æŠžã—ã¦ãã ã•ã„ + + + + Please choose a new encoding for all tables. + ã™ã¹ã¦ã®ãƒ†ãƒ¼ãƒ–ãƒ«ã®æ–°ã—ã„ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã‚’é¸æŠžã—ã¦ãã ã•ã„。 + + + + Please choose a new encoding for this table. + ã™ã¹ã¦ã®ãƒ†ãƒ¼ãƒ–ãƒ«ã®æ–°ã—ã„ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã‚’é¸æŠžã—ã¦ãã ã•ã„。 + + + + %1 +Leave the field empty for using the database encoding. + %1 +データベースã®ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã‚’使ã†ãŸã‚ã€ãƒ•ィールドを空ã«ã—ã¾ã™ã€‚ + + + + This encoding is either not valid or not supported. + ã“ã®ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã¯ä¸æ­£ã‹ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“。 + + + + %1 replacement(s) made. + %1 ã¤ç½®ãæ›ãˆã¾ã—ãŸã€‚ + + + + TableBrowserDock + + + New Data Browser + æ–°ã—ã„データ閲覧 + + + + Rename Data Browser + データ閲覧ã®åå‰ã‚’変ãˆã‚‹ + + + + Close Data Browser + データ閲覧を閉ã˜ã‚‹ + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + ãƒ‡ãƒ¼ã‚¿é–²è¦§ã«æ–°ã—ã„åå‰ã‚’付ã‘ã¾ã™ã€‚'&&'を付ã‘ã‚‹ã¨ãã®æ¬¡ã®æ–‡å­—をキーボードã®ã‚·ãƒ§ãƒ¼ãƒˆã‚«ãƒƒãƒˆã«ã§ãã¾ã™ã€‚ + + + + VacuumDialog + + + Compact Database + データベースを圧縮 + + + + Warning: Compacting the database will commit all of your changes. + 警告: データベースã®åœ§ç¸®ã¯ã‚ãªãŸã®å¤‰æ›´ã‚’ã™ã¹ã¦ã‚³ãƒŸãƒƒãƒˆã—ã¾ã™ã€‚ + + + + Please select the databases to co&mpact: + 圧縮ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é¸æŠžã—ã¦ãã ã•ã„(&M): + + + diff --git a/src/translations/sqlb_ko_KR.qph b/src/translations/sqlb_ko_KR.qph deleted file mode 100644 index 9db493f15..000000000 --- a/src/translations/sqlb_ko_KR.qph +++ /dev/null @@ -1,439 +0,0 @@ - - - - file - íŒŒì¼ - - - version - 버전 - - - invalid - ìž˜ëª»ëœ - - - option - 옵션 - - - argument - 매개변수 - - - filter - í•„í„° - - - import - 가져오기 - - - export - 내보내기 - - - column - 필드 - - - first - 최초, ì²˜ìŒ - - - line - í–‰ - - - field - 필드 - - - separator - êµ¬ë¶„ìž - - - tab - 탭 - - - encoding - ì¸ì½”딩 - - - trim - 앞뒤 공백제거 - - - insert - 추가하기 - - - data - ë°ì´í„° - - - cancel - 취소 - - - already - ì´ë¯¸ - - - table - í…Œì´ë¸” - - - record - 레코드 - - - row - í–‰ - - - execute - 실행하다 - - - browse - 보다 - - - view - ë·° - - - index - ì¸ë±ìФ - - - indice - ì¸ë±ìФ - - - application - 애플리케ì´ì…˜ - - - order - 정렬순서 - - - unique - ìœ ë‹ˆí¬ - - - name - ì´ë¦„ - - - create - ìƒì„±í•˜ê¸° - - - error - ì—러 - - - pragma - pragma - - - executing - 실행중 - - - unknown - 알 수 없는 - - - object - ê°ì²´ - - - type - 타입 - - - SQL - SQL - - - action - 실행 - - - database - ë°ì´í„°ë² ì´ìФ - - - warning - ì£¼ì˜ - - - compact - 용량 줄ì´ê¸° - - - preferences - 환경설정 - - - enable - 사용하기 - - - language - 언어 - - - automatic - ìžë™ - - - update - ì—…ë°ì´íЏ - - - default - 기본 - - - default - 기본값 - - - location - 위치 - - - foreign key - 외래키 - - - colour - 색깔 - - - general - ì¼ë°˜ - - - open - 열다 - - - setting - 설정 - - - bold - 볼드 - - - italic - ì´íƒ¤ë¦­ - - - underline - 밑줄 - - - enabled - 사용하기 - - - setting - 설정 - - - tables - í…Œì´ë¸” - - - updates - ì—…ë°ì´íЏ - - - update - ì—…ë°ì´íЏ - - - browser - 보기 - - - log - 로그 - - - logs - 로그 - - - editor - 편집기 - - - font - í°íЏ - - - size - í¬ê¸° - - - string - 문ìžì—´ - - - comment - ì£¼ì„ - - - current - 현재 - - - identifier - ì‹ë³„ìž - - - function - 함수 - - - function - 기능 - - - keyword - 키워드 - - - extension - 확장기능 - - - select - ì„ íƒí•˜ë‹¤ - - - choice - 고르다 - - - disable - 사용하지않기 - - - directory - 디렉토리 - - - all files - 모든 íŒŒì¼ - - - information - ì •ë³´ - - - view - ë·° - - - show - 보기 - - - user - ì‚¬ìš©ìž - - - clear - 지우기 - - - edit - 편집 - - - help - ë„ì›€ë§ - - - columns - 필드 - - - DB Browser for SQLite - DB Browser for SQLite - - - usage - 사용법 - - - db - ë°ì´í„°ë² ì´ìФ - - - command line - 커맨드ë¼ì¸ - - - arguments - 옵션 - - - argument - 옵션 - - - page - 페ì´ì§€ - - - encryption - 암호화 - - - SQLCipher - SQLCipher - - - process - 작업 - - - savepoint - 세ì´ë¸Œí¬ì¸íЏ - - - failed - 실패했습니다 - - - aborting - 취소 - - - attache - 합치다 - - - associated - ì—°ê´€ëœ - - - cell - ë°ì´í„° ê°’ - - - name - 필드명 - - diff --git a/src/translations/sqlb_ko_KR.ts b/src/translations/sqlb_ko_KR.ts index 2507d5167..fa695b650 100644 --- a/src/translations/sqlb_ko_KR.ts +++ b/src/translations/sqlb_ko_KR.ts @@ -1,6 +1,6 @@ - + AboutDialog @@ -10,2799 +10,8029 @@ DB Browser for SQLite ì •ë³´ - + Version 버전 - - <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:small;">It also uses the Silk icon set by Mark James licensed under a Creative Commons Attribution 2.5 and 3.0 license.<br/>See </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> - <html><head/><body><p>DB Browser for SQLite는 오픈소스, 프리웨어 시ê°í™” 툴로 SQLite ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ìƒì„±í•˜ê³ , 설계하고 수정할 수 있습니다.</p><p>ì´ í”„ë¡œê·¸ëž¨ì€ ë‘ ê°€ì§€ ë¼ì´ì„¼ìŠ¤ë¥¼ ë”°ë¥´ëŠ”ë° Mozilla Public License Version 2와 GNU General Public License Version 3 ë˜ëŠ” ê·¸ ì´í›„ ë²„ì „ì˜ ë¼ì´ì„¼ìŠ¤ë¥¼ 따릅니다. ì—¬ëŸ¬ë¶„ì€ ì´ ë¼ì´ì„¼ìФ 하ì—서 수정하거나 ìž¬ë°°í¬ í•  수 있습니다.</p><p>ìžì„¸í•œ ë‚´ìš©ì€ <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> ê³¼ <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> 를 참고하시기 ë°”ëžë‹ˆë‹¤.</p><p>ì´ í”„ë¡œê·¸ëž¨ì— ëŒ€í•œ 추가 정보를 알고 싶으시면 우리 웹사ì´íŠ¸ì— ë°©ë¬¸í•˜ì„¸ìš”: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">ì´ ì†Œí”„íŠ¸ì›¨ì–´ëŠ” </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;">ì˜ GPL/LGPL Qt Toolkitì„ ì‚¬ìš©í•©ë‹ˆë‹¤.</span><span style=" font-size:small;"><br/>ë¼ì´ì„¼ìФ ì¡°ê±´ê³¼ 정보는 </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> ì—서 보실 수 있습니다.</span></p><p><span style=" font-size:small;">ë˜í•œ ì´ í”„ë¡œê·¸ëž¨ì€ Mark Jamesê°€ 제작한 ì‹¤í¬ ì•„ì´ì½˜ 세트를 Creative Commons Attribution 2.5와 3.0 버전 ë¼ì´ì„¼ìФ 하ì—서 사용하고 있습니다.<br/>ìžì„¸í•œ ê²ƒì€ </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> 를 참고하세요.</span></p></body></html> + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + <html><head/><body><p>DB Browser for SQLite는 ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ìƒì„±, ë””ìžì¸ ë° íŽ¸ì§‘í•˜ëŠ” ë° ì‚¬ìš©ë˜ëŠ” 오픈 소스 프리웨어 ì‹œê° ë„구입니다.</p><p>Mozilla Public License 버전 2와 GNU General Public License 버전 3 ì´ìƒì— ë”°ë¼ ì´ì¤‘ ë¼ì´ì„ ìŠ¤ê°€ ì ìš©ë©ë‹ˆë‹¤. ì´ëŸ¬í•œ ë¼ì´ì„ ìФ ì¡°ê±´ì— ë”°ë¼ ìˆ˜ì •í•˜ê±°ë‚˜ 재배í¬í•  수 있습니다.</p><p>ìžì„¸í•œ ì‚¬í•­ì€ <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> ë° <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a>ì„ í™•ì¸í•˜ì„¸ìš”.</p><p>ì´ í”„ë¡œê·¸ëž¨ì— ëŒ€í•œ ìžì„¸í•œ ë‚´ìš©ì€ ì›¹ì‚¬ì´íЏì—서 확ì¸í•˜ì„¸ìš”: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">ì´ ì†Œí”„íŠ¸ì›¨ì–´ëŠ” 다ìŒì˜ GPL/LGPL Qt íˆ´í‚·ì„ ì‚¬ìš©í•©ë‹ˆë‹¤.</span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;"> https://qt-project.org/</span></a><span style=" font-size:small;"><br/>ìžì„¸í•œ ë¼ì´ì„¼ìФ 약관 ë° ì •ë³´ëŠ” </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;">를 확ì¸í•˜ì„¸ìš”.</span></p><p><span style=" font-size:8pt;">ì €í¬ëŠ” SQLite 확장 ì§€ì›ì„ 위해 nalgeon/sqlean ë¼ì´ë¸ŒëŸ¬ë¦¬ë¥¼ 사용합니다.<br/>ì´ ë¼ì´ë¸ŒëŸ¬ë¦¬ëŠ” MIT ë¼ì´ì„ ìŠ¤ì— ë”°ë¼ ë¼ì´ì„ ìŠ¤ê°€ 부여ë˜ë©°, ìžì„¸í•œ ë‚´ìš©ì€ ë‹¤ìŒì„ 참조하세요:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">ë˜í•œ í¬ë¦¬ì—ì´í‹°ë¸Œ 커먼즈 저작ìží‘œì‹œ ë™ì¼ì¡°ê±´ë³€ê²½í—ˆë½ 4.0 ë¼ì´ì„ ìŠ¤ì— ë”°ë¼ Michael Buckleyê°€ 설정한 파스텔 SVG ì•„ì´ì½˜ì„ 사용합니다.<br/>ìžì„¸í•œ ì‚¬í•­ì€ </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> ì„ í™•ì¸í•˜ì„¸ìš”.</span></p></body></html> + + + AddRecordDialog - - Version - 버전 + + Add New Record + 새 레코드 추가 - - Qt Version - Qt 버전 + + Enter values for the new record considering constraints. Fields in bold are mandatory. + 제약 ì¡°ê±´ì„ ê³ ë ¤í•˜ì—¬ 새 레코드를 위한 ê°’ì„ ìž…ë ¥í•˜ì„¸ìš”. 진하게 ì²˜ë¦¬ëœ í•„ë“œëŠ” 반드시 입력해야 합니다. - - SQLCipher Version - SQLCipher 버전 + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + ê°’ 필드ì—는 ì´ë¦„ í•„ë“œì— ëŒ€ì‘하는 ê°’ì„ ìž…ë ¥ í•  수 있습니다. 타입 필드는 í•„ë“œì˜ íƒ€ìž…ì„ ì˜ë¯¸í•©ë‹ˆë‹¤. 기본 ê°’ì€ NULLê°’ê³¼ ê°™ì€ ìŠ¤íƒ€ì¼ë¡œ 표시ë©ë‹ˆë‹¤. - - SQLite Version - SQLite 버전 + + Name + ì´ë¦„ - - - Application - - Usage: %1 [options] [db] - - 사용법: %1 [옵션] [ë°ì´í„°ë² ì´ìФ] - + + Type + 타입 - - Possible command line arguments: - 사용할 수 있는 커맨드ë¼ì¸ 매개변수: + + Value + ê°’ - - -h, --help Show command line options - -h, --help 커맨드ë¼ì¸ ì˜µì…˜ì„ ë³´ì—¬ì¤ë‹ˆë‹¤ + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + 추가할 값들입니다. 기본 ê°’ë“¤ì´ ë¯¸ë¦¬ ìž…ë ¥ë˜ì–´ 있어 수정하지 않는다면 ìžë™ì ìœ¼ë¡œ 들어갑니다. - - -s, --sql [file] Execute this SQL file after opening the DB - -s, --sql [file] ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ì—° í›„ì— SQL íŒŒì¼ ë‚´ìš©ì„ ì‹¤í–‰í•©ë‹ˆë‹¤ + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + 위 í”„ë ˆìž„ì˜ ê°’ì„ ìˆ˜ì •í•˜ë©´, ìˆ˜ì •ì‚¬í•­ì´ ë°˜ì˜ëœ 레코드 추가 SQL쿼리가 ì—¬ê¸°ì— ë‚˜íƒ€ë‚©ë‹ˆë‹¤. 저장하기 ì „ì´ë¼ë©´ ì§ì ‘ 쿼리를 수정할 ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. - - -q, --quit Exit application after running scripts - -q, --quit 스í¬ë¦½íŠ¸ë¥¼ 실행한 í›„ì— ì• í”Œë¦¬ì¼€ì´ì…˜ì„ 종료합니다 + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">저장하기</span>는 새 레코드를 ë°ì´í„°ë² ì´ìŠ¤ì— ì¶”ê°€í•˜ê¸° 위해 작성ë˜ì–´ 나타나 있는 SQL êµ¬ë¬¸ì„ ë°˜ì˜í•©ë‹ˆë‹¤.</p><p><span style=" font-weight:600;">초기값 ë³µì›í•˜ê¸°</span>는 <span style=" font-weight:600;">ê°’</span> 필드를 초기 값으로 ë³µì›í•©ë‹ˆë‹¤.</p><p><span style=" font-weight:600;">취소하기</span>는 ì¿¼ë¦¬ì˜ ì‹¤í–‰ ì—†ì´ ì´ ì°½ì„ ë‹«ìŠµë‹ˆë‹¤.</p></body></html> - - [file] Open this SQLite database - [파ì¼] 지정한 SQLite ë°ì´í„°ë² ì´ìФ 파ì¼ì„ 엽니다 + + Auto-increment + + ìžë™ ì¦ê°€(Auto-increment) + - - The -s/--sql option requires an argument - -s/--sql ì˜µì…˜ì€ ì‹¤í–‰í•  SQL 파ì¼ëª…ì„ ê°™ì´ ì§€ì •í•´ì£¼ì–´ì•¼ 합니다 + + Unique constraint + + ìœ ë‹ˆí¬ ì œì•½ + - - The file %1 does not exist - %1 파ì¼ì´ 존재하지 않습니다 + + Check constraint: %1 + + 제약 ì¡°ê±´: %1 + - - Invalid option/non-existant file: %1 - ìž˜ëª»ëœ ì˜µì…˜ì„ ì‚¬ìš©í•˜ì˜€ê±°ë‚˜/파ì¼ì´ 존재하지 않습니다: %1 + + Foreign key: %1 + + 외래키: %1 + - - - CipherDialog - - SQLCipher encryption - SQLCipher 암호화 + + Default value: %1 + + 기본 ê°’: %1 + - - &Password - 암호(&P) + + Error adding record. Message from database engine: + +%1 + 레코드 추가 ë„중 ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. ë°ì´í„°ë² ì´ìФ 엔진 메시지: + +%1 - - &Reenter password - 암호 재입력(&R) + + Are you sure you want to restore all the entered values to their defaults? + ì •ë§ë¡œ 모든 입력한 ê°’ë“¤ì„ ì´ˆê¸° 값으로 ë³µì›í•©ë‹ˆê¹Œ? + + + Application - - Page &size - 페ì´ì§€ í¬ê¸°(&S) + + Possible command line arguments: + 사용할 수 있는 명령줄 매개변수: - - Please set a key to encrypt the database. -Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. -Leave the password fields empty to disable the encryption. -The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. - ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 암호화할 때 사용할 키를 지정해주세요. -[주ì˜] ì—¬ëŸ¬ë¶„ì´ ì¶”ê°€ì ì¸ ì„¸íŒ…ì„ ë³€ê²½í•œë‹¤ë©´, ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ì—´ 때마다 암호를 매번 입력해야합니다. -그러한 ë¶ˆíŽ¸í•¨ì„ í”¼í•˜ê¸° 위해 암호화를 하지 않으려면 암호 필드를 비워ë‘세요 -암호화 ìž‘ì—…ì€ ì‹œê°„ì´ ì¢€ 걸릴 수 있습니다. 그리고 ê¼­ ì—¬ëŸ¬ë¶„ì˜ ë°ì´í„°ë² ì´ìФ ë°±ì—…ë³¸ì„ ë°˜ë“œì‹œ 만들어ë‘세요! 암호화 작업 ì´ì „ì— í•œ 저장ë˜ì§€ ì•Šì€ ë³€ê²½ ì‚¬í•­ë„ ë°˜ì˜ë˜ë‹ˆ 주ì˜í•˜ì„¸ìš”. + + The user settings file location is replaced with the argument value instead of the environment variable value. + ì‚¬ìš©ìž í™˜ê²½ì„¤ì • íŒŒì¼ ìœ„ì¹˜ëŠ” 환경 변수 ê°’ 대신 ì¸ìž 값으로 대체ë©ë‹ˆë‹¤. - - Please enter the key used to encrypt the database. -If any of the other settings were altered for this database file you need to provide this information as well. - ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 암호화기 위해 사용할 키를 다시 입력해주세요. -ë°ì´í„°ë² ì´ìФ 파ì¼ì„ 변경하기 위해서는 ì´ ì •ë³´ë¥¼ 다시 입력해야만 합니다. + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + 무시ë˜ëŠ” 환경변수(DB4S_SETTINGS_FILE) ê°’ : - - - CreateIndexDialog - - Create New Index - 새 ì¸ë±ìФ ìƒì„±í•˜ê¸° + + + The file %1 does not exist + %1 파ì¼ì´ 존재하지 않습니다 - - &Name - ì´ë¦„(&N) + + Usage + 사용법 - - &Columns - 필드(&C) + + options + 옵션 - - Column - 필드 + + + database + ë°ì´í„°ë² ì´ìФ - - Use in Index - ì¸ë±ìФ 사용 + + + project + 프로ì íЏ - - Order - 정렬순서 + + + csv-file + CSV íŒŒì¼ - - &Table - í…Œì´ë¸”(&T) + + Show command line options + 명령줄 옵션 출력 - - &Unique - 유니í¬(&U) + + Exit application after running scripts + 스í¬ë¦½íЏ 실행 후 ì‘ìš© 프로그램 종료 - - Creating the index failed: -%1 - ì¸ë±ìФ ìƒì„±ì— 실패했습니다: -%1 + + + file + íŒŒì¼ - - - DBBrowserDB - - - - - no error - ì—러 ì—†ìŒ + + Execute this SQL file after opening the DB + DB를 ì—° 후 ì´ SQL 파ì¼ì„ 실행합니다 - - Please specify the database name under which you want to access the attached database - ë°ì´í„°ë² ì´ìФ 합치기를 합치기 위해 불러올 ë°ì´í„°ë² ì´ìŠ¤ì˜ ë³„ëª…ì„ ì§€ì •í•´ì£¼ì„¸ìš” + + Import this CSV file into the passed DB or into a new DB + CSV 파ì¼ì„ 불러온 후 기존 DB ë˜ëŠ” 새 DBì— ë°˜ì˜í•©ë‹ˆë‹¤ - - Do you want to save the changes made to the database file %1? - %1 ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ìƒì„±í•˜ê¸° 위해 ë³€ê²½ì‚¬í•­ì„ ì €ìž¥í•˜ê² ìŠµë‹ˆê¹Œ? + + table + í…Œì´ë¸” - - Exporting database to SQL file... - ë°ì´í„°ë² ì´ìŠ¤ë¥¼ SQL 파ì¼ë¡œ 내보내기 중... + + Browse this table, or use it as target of a data import + 해당 í…Œì´ë¸”ì„ íƒìƒ‰í•˜ê±°ë‚˜, ë°ì´í„°ë¥¼ 가져올 ëŒ€ìƒ í…Œì´ë¸”로 ì„ íƒí•©ë‹ˆë‹¤ - - - Cancel - 취소 + + Open database in read-only mode + ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ì½ê¸° ì „ìš© 모드로 엽니다 - - Executing SQL... - SQL 실행중... + + settings_file + 설정 íŒŒì¼ - - Action cancelled. - 실행 취소ë˜ì—ˆìŠµë‹ˆë‹¤. + + Run application based on this settings file + ì´ ì„¤ì • 파ì¼ì„ 기반으로 ì‘ìš© í”„ë¡œê·¸ëž¨ì„ ì‹¤í–‰í•©ë‹ˆë‹¤ - - - Error in statement #%1: %2. -Aborting execution. - 구문 ì—러 #%1: %2. -ì‹¤í–‰ì´ ì·¨ì†Œë˜ì—ˆìŠµë‹ˆë‹¤. + + + group + 그룹 - - renameColumn: cannot find table %1. - 필드ì´ë¦„ 변경: %1 í…Œì´ë¸”ì„ ë°œê²¬í•  수 없습니다. + + + settings + 설정 - - renameColumn: cannot find column %1. - 필드ì´ë¦„ 변경: %1 필드를 발견할 수 없습니다. + + + value + ê°’ - - renameColumn: creating savepoint failed. DB says: %1 - 필드ì´ë¦„ 변경: 세ì´ë¸Œí¬ì¸íŠ¸ë¥¼ ìƒì„±í•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤. ë°ì´í„°ë² ì´ìФ 메시지: %1 + + Run application with this setting temporarily set to value + 임시ì ìœ¼ë¡œ 해당 설정 ê·¸ë£¹ì„ ì§€ì • 값으로 설정한 후, ì‘ìš© í”„ë¡œê·¸ëž¨ì„ ì‹¤í–‰í•©ë‹ˆë‹¤ - - renameColumn: creating new table failed. DB says: %1 - 필드ì´ë¦„ 변경: 새 í…Œì´ë¸”ì„ ìƒì„±í•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤. ë°ì´í„°ë² ì´ìФ 메시지: %1 + + Run application saving this value for this setting + ì‘ìš© í”„ë¡œê·¸ëž¨ì„ ì‹¤í–‰í•˜ë©° ì´ ì„¤ì • ê°’ì„ ì €ìž¥í•©ë‹ˆë‹¤ - - renameColumn: copying data to new table failed. DB says: -%1 - 필드ì´ë¦„ 변경: 새 í…Œì´ë¸”로 ë°ì´í„°ë¥¼ ë³µì‚¬í•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤. ë°ì´í„°ë² ì´ìФ 메시지: %1 + + Display the current version + 현재 ë²„ì „ì„ ì¶œë ¥í•©ë‹ˆë‹¤ - - renameColumn: deleting old table failed. DB says: %1 - 필드ì´ë¦„ 변경: ì´ì „ í…Œì´ë¸”ì„ ì‚­ì œí•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤. ë°ì´í„°ë² ì´ìФ 메시지: %1 + + Open this SQLite database + SQLite ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 엽니다 - - Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: - - - ì´ í…Œì´ë¸”ì— ê´€ë ¨ëœ ëª‡ ê°œì˜ ê°ì²´ë¥¼ ë³µì›í•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤. ì´ëŸ¬í•œ 경우는 대부분 몇 ê°œì˜ í•„ë“œëª…ì´ ë³€ê²½ë˜ì„œ ì¼ì–´ë‚¬ì„ ê°€ëŠ¥ì„±ì´ í½ë‹ˆë‹¤. 아래 SQL êµ¬ë¬¸ì„ ì°¸ê³ í•˜ë©´ ì§ì ‘ 수ë™ìœ¼ë¡œ ê³ ì³ì„œ 실행할 수 ìžˆì„ ê²ƒìž…ë‹ˆë‹¤: - - + + Open this project file (*.sqbpro) + 프로ì íЏ íŒŒì¼ (*.sqbpro)를 엽니다 - - renameColumn: releasing savepoint failed. DB says: %1 - 필드ì´ë¦„ 변경: 세ì´ë¸Œí¬ì¸íŠ¸ë¥¼ í•´ì œí•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤. ë°ì´í„°ë² ì´ìФ 메시지: %1 + + Import this CSV file into an in-memory database + 메모리 ë°ì´í„°ë² ì´ìŠ¤ì— ì´ CSV 파ì¼ì„ 가져옵니다 - - Error renaming table '%1' to '%2'.Message from database engine: -%3 - í…Œì´ë¸”ëª…ì„ '%1'ì—서 '%2'로 ë³€ê²½í•˜ëŠ”ë° ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. ë°ì´ë² ì´ìФ 메시지: -%3 + + + + The %1 option requires an argument + %1 ì˜µì…˜ì€ ì¸ìž ê°’ì„ í•„ìš”ë¡œ 합니다 - - ... <string can not be logged, contains binary data> ... - ... <문ìžì—´ì´ ë°”ì´ë„ˆë¦¬ ë°ì´í„°ë¥¼ í¬í•¨í•˜ì—¬ ë¡œê¹…ë  ìˆ˜ 없습니다.> ... + + The -S/--settings option requires an argument. The option is ignored. + -S/--settings ì˜µì…˜ì€ ì¸ìž ê°’ì´ í•„ìš”í•©ë‹ˆë‹¤. ë”°ë¼ì„œ ì´ ì˜µì…˜ì€ ë¬´ì‹œë©ë‹ˆë‹¤. - - unknown object type %1 - %1 ì€(는) 알 수 없는 ê°ì²´ 타입입니다 + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + -o/--option ë˜ëŠ” -O/--save-option ì˜µì…˜ì€ group/setting=value 형ì‹ì˜ ì¸ìˆ˜ê°€ 필요합니다 - - could not get list of db objects: %1, %2 - ë°ì´í„°ë² ì´ìФ ê°ì²´ 목ë¡ì„ 가져올 수 없습니다: %1, %2 + + Invalid option/non-existent file: %1 + ìž˜ëª»ëœ ì˜µì…˜ì„ ì‚¬ìš©í•˜ì˜€ê±°ë‚˜ 파ì¼ì´ 존재하지 않습니다: %1 - - could not get types - íƒ€ìž…ì„ ì–»ì–´ì˜¬ 수 없습니다 + + SQLite Version + SQLite 버전 - - didn't receive any output from pragma %1 - pragma %1 ì—서 출력결과를 받아올 수 없습니다 + + SQLCipher Version %1 (based on SQLite %2) + SQLCipher 버전 %1 (SQLite %2 기반) - - could not execute pragma command: %1, %2 - pragma ëª…ë ¹ì„ ì‹¤í–‰í•  수 없습니다: %1, %2 + + DB Browser for SQLite Version %1. + DB Browser for SQLite 버전 %1. - - Error setting pragma %1 to %2: %3 - pragma ì„¸íŒ…ì„ %1ì—서 %2로 ë³€ê²½í•˜ëŠ”ë° ì—러: %3 + + Last commit hash when built: %1 + 빌드 당시 최종 깃 해시 ê°’: %1 - - File not found. - 파ì¼ì´ 없습니다. + + Built for %1, running on %2 + %1 í™˜ê²½ì„ ìœ„í•´ 빌드ë¨, %2 환경ì—서 실행 중 + + + + Qt Version %1 + Qt 버전 %1 - DbStructureModel + CipherDialog - - Name - ì´ë¦„ + + SQLCipher encryption + SQLCipher 암호화 - - Object - ê°ì²´ + + &Password + 암호(&P) - - Type - 타입 + + &Reenter password + 암호 재입력(&R) - - Schema - 스키마 + + Encr&yption settings + 암호화 설정(&Y) - - Tables (%1) - í…Œì´ë¸” (%1) + + SQLCipher &3 defaults + SQLCipher &3 기본값 - - Indices (%1) - ì¸ë±ìФ (%1) + + SQLCipher &4 defaults + SQLCipher &4 기본값 - - Views (%1) - ë·° (%1) + + Custo&m + 수ë™(&M) - - Triggers (%1) - 트리거 (%1) + + Page si&ze + 페ì´ì§€ í¬ê¸°(&Z) - - - EditDialog - - Edit database cell - ë°ì´í„°ë² ì´ìФ ë°ì´í„° ê°’ì„ ìˆ˜ì •í•˜ê¸° + + &KDF iterations + &KDF 반복 횟수 - - Import text - 문ìžì—´ 가져오기 + + HMAC algorithm + HMAC 알고리즘 - - Opens a file dialog used to import text to this database cell. - ì´ ë°ì´í„°ë² ì´ìФ ë°ì´í„° 값으로 문ìžì—´ì„ 가져오기 위하여 íŒŒì¼ ëŒ€í™”ìƒìžë¥¼ 엽니다. + + KDF algorithm + KDF 알고리즘 - - &Import - 가져오기(&I) + + Plaintext Header Size + í‰ë¬¸ í—¤ë” í¬ê¸° - - Export text - 문ìžì—´ 내보내기 + + Passphrase + 암호 - - Opens a file dialog used to export the contents of this database cell to a text file. - ì´ ë°ì´í„°ë² ì´ìФ ë°ì´í„° ê°’ì„ ë¬¸ìžì—´ 파ì¼ë¡œ 내보내기 위하여 대화ìƒìžë¥¼ 엽니다. + + Raw key + Raw 키 - - &Export - 내보내기(&E) + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 암호화할 때 사용할 키를 지정해주세요. +[주ì˜] ì—¬ëŸ¬ë¶„ì´ ì¶”ê°€ì ì¸ ì„¤ì •ì„ ë³€ê²½í•œë‹¤ë©´, ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ì—´ 때마다 암호를 매번 입력해야합니다. +그러한 ë¶ˆíŽ¸í•¨ì„ í”¼í•˜ê¸° 위해 암호화를 하지 않으려면 암호 필드를 비워ë‘세요 +암호화 ìž‘ì—…ì€ ì‹œê°„ì´ ì¢€ 걸릴 수 있습니다. 그리고 ê¼­ ì—¬ëŸ¬ë¶„ì˜ ë°ì´í„°ë² ì´ìФ ë°±ì—…ë³¸ì„ ë°˜ë“œì‹œ 만들어ë‘세요! 암호화 작업 ì´ì „ì— í•œ 저장ë˜ì§€ ì•Šì€ ë³€ê²½ ì‚¬í•­ë„ ë°˜ì˜ë˜ë‹ˆ 주ì˜í•˜ì„¸ìš”. - - Text - 문ìžì—´ + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 암호화기 위해 사용할 키를 다시 입력해주세요. +ë°ì´í„°ë² ì´ìФ 파ì¼ì„ 변경하기 위해서는 ì´ ì •ë³´ë¥¼ 다시 입력해야만 합니다. + + + ColumnDisplayFormatDialog - - Binary - ë°”ì´ë„ˆë¦¬ + + Choose display format + 표시 형ì‹ì„ ì„ íƒí•˜ì„¸ìš” - - Clear cell data - ë°ì´í„° ê°’ 지우기 + + Display format + 표시 í˜•ì‹ - - Erases the contents of the cell - ë°ì´í„° ê°’ì„ ì‚­ì œí•©ë‹ˆë‹¤ + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + '%1' ì»¬ëŸ¼ì˜ í‘œì‹œ 형ì‹ì„ ì„ íƒí•˜ì„¸ìš”. - - &Clear - 지우기(&C) + + Default + ì¼ë°˜ - - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Warning: Editing binary content in text mode may result in corrupted data!</span></p></body></html> - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">주ì˜: í…스트 모드ì—서 ë°”ì´ë„ˆë¦¬ 콘í…츠를 수정하면 ë°ì´í„°ê°€ 깨질 수 있습니다!</span></p></body></html> + + Decimal number + ìˆ«ìž - - This area displays information about the data present in this database cell - ì´ ì˜ì—­ì€ ì´ ë°ì´í„°ë² ì´ìФ ë°ì´í„° ê°’ì— ëŒ€í•œ 정보를 ë³´ì—¬ì¤ë‹ˆë‹¤ + + Exponent notation + 지수 - - Type of data currently in cell - ë°ì´í„° ê°’ í¬ê¸° + + Hex blob + ì´ì§„ ë°ì´í„° - - Size of data currently in table - í…Œì´ë¸”ì—서 현재 ë°ì´í„° í¬ê¸° + + Hex number + 16진수 - - Choose a file - 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” + + Apple NSDate to date + Apple NSDate ë‚ ì§œ - - Text files(*.txt);;Image files(%1);;All files(*) - 문ìžì—´ 파ì¼(*.txt);;ì´ë¯¸ì§€ 파ì¼(%1);;모든 파ì¼(*) + + Java epoch (milliseconds) to date + Java 시간(밀리초)ì„ ë‚ ì§œë¡œ - - Choose a filename to export data - 내보내기 í•  ë°ì´í„°ì˜ 파ì¼ì´ë¦„ì„ ì„ íƒí•˜ì„¸ìš” + + .NET DateTime.Ticks to date + .NET DateTime Ticks를 날짜로 - - Text files(*.txt);;All files(*) - 문ìžì—´ 파ì¼(*.txt);;모든 파ì¼(*) + + Julian day to date + ë‚ ì§œ - - Type of data currently in cell: Null - 현재 ë°ì´í„° 타입: ë„ + + Unix epoch to local time + 유닉스 시간(타임스탬프)ì„ ì§€ì—­ 시간으로 - - Type of data currently in cell: Text / Numeric - 현재 ë°ì´í„° 타입: 문ìžì—´ / ìˆ«ìž + + WebKit / Chromium epoch to date + WebKit / Chromiumì„ ë‚ ì§œë¡œ - - - %n char(s) - - %n ë¬¸ìž - + + + WebKit / Chromium epoch to local time + 로WebKit / Chromium ì‹œê°„ì„ ì§€ì—­ 시간으로 - - Type of data currently in cell: Image - 현재 ë°ì´í„° 타입: ì´ë¯¸ì§€ + + Date as dd/mm/yyyy + 날짜를 dd/mm/yyyy 형태로 - - %1x%2 pixel - %1x%2 픽셀 + + Lower case + ì†Œë¬¸ìž - - Type of data currently in cell: Binary - 현재 ë°ì´í„° 타입: ë°”ì´ë„ˆë¦¬ + + Binary GUID to text + ë°”ì´ë„ˆë¦¬ GUID를 í…스트로 - - - %n byte(s) - - %n ë°”ì´íЏ - + + + SpatiaLite Geometry to SVG + SpatiaLite Geometry를 SVG로 - - - EditTableDialog - - Edit table definition - í…Œì´ë¸” ì •ì˜ ë³€ê²½ + + Custom display format must contain a function call applied to %1 + ì‚¬ìš©ìž ì •ì˜ í‘œì‹œ 형ì‹ì€ %1ì— ì ìš©ëœ 함수 í˜¸ì¶œì„ í¬í•¨í•´ì•¼ 합니다 - - Table - í…Œì´ë¸” + + Error in custom display format. Message from database engine: + +%1 + ì‚¬ìš©ìž ì •ì˜ í‘œì‹œ 형ì‹ì—서 ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. ë°ì´í„°ë² ì´ìФ ì—”ì§„ì˜ ë©”ì‹œì§€: +%1 - - Advanced - 고급 + + Custom display format must return only one column but it returned %1. + ì‚¬ìš©ìž ì§€ì • 표시 형ì‹ì€ í•˜ë‚˜ì˜ ì—´ë§Œ 반환해야 하지만 %1개를 반환했습니다. - - Make this a 'WITHOUT rowid' table. Setting this flag requires a field of type INTEGER with the primary key flag set and the auto increment flag unset. - ì´ í…Œì´ë¸”ì„ 'rowidê°€ 없는' í…Œì´ë¸”로 ìƒì„±í•©ë‹ˆë‹¤. ì´ ì„¤ì •ì„ ì‚¬ìš©í•˜ë ¤ë©´ 주 키(Primary Key)로 설정ë˜ê³  ìžë™ ì¦ê°€(Auto Increment)ê°€ í•´ì œëœ INTEGER íƒ€ìž…ì˜ í•„ë“œ 하나가 필요합니다. + + Octal number + 8진수 - - Without Rowid - Rowid 필드 ì—†ìŒ + + Round number + ë¼ìš´ë“œ 수 - - Fields - 필드 + + Unix epoch to date + 유닉스 시간(타임스탬프)ì„ ë‚ ì§œë¡œ - - Add field - 필드 추가 + + Upper case + ëŒ€ë¬¸ìž - - Remove field - 필드 ì‚­ì œ + + Windows DATE to date + Windows ë‚ ì§œ - - Move field up - 필드를 위로 올리기 + + Custom + ì‚¬ìš©ìž ì§€ì • + + + CondFormatManager - - Move field down - 필드를 아래로 내리기 + + Conditional Format Manager + ì¡°ê±´ë¶€ ì„œì‹ ê´€ë¦¬ìž - - Name - 필드명 + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + ì´ ëŒ€í™”ìƒìžì—서는 ì¡°ê±´ë¶€ 형ì‹ì„ 추가하고 수정할 수 있습니다. ê° ì…€ 스타ì¼ì€ 해당 ì…€ ë°ì´í„°ì˜ 첫번째 ì¡°ê±´ì— ì˜í•´ 지정ë©ë‹ˆë‹¤. ì¡°ê±´ë¶€ 서ì‹ì€ 위/아래로 ì´ë™í•  수 있으며, ìƒìœ„ í–‰ì— ìžˆëŠ” 형ì‹ì€ 하위 í–‰ì— ìžˆëŠ” 형ì‹ë³´ë‹¤ ìš°ì„ ë©ë‹ˆë‹¤. ì¡°ê±´ êµ¬ë¬¸ì€ í•„í„°ì™€ ë™ì¼í•˜ë©° 빈 ì¡°ê±´ì€ ëª¨ë“  ê°’ì— ëŒ€í•´ ì ìš©ë©ë‹ˆë‹¤. - - Type - 타입 + + Add new conditional format + 새 ì¡°ê±´ë¶€ 서ì‹ì„ 추가합니다 - - - Not null - Not null + + &Add + 추가(&A) - - PK - PK + + Remove selected conditional format + ì„ íƒí•œ ì¡°ê±´ë¶€ 서ì‹ì„ 삭제합니다 - - Primary key - 주 키(Primary key) + + &Remove + ì‚­ì œ(&R) - - AI - AI + + Move selected conditional format up + ì„ íƒí•œ ì¡°ê±´ë¶€ 서ì‹ì„ 위로 ì´ë™í•©ë‹ˆë‹¤ - - Autoincrement - ìžë™ì¦ê°€(Autoincrement) + + Move &up + 위로 올리기(&U) - - U - U + + Move selected conditional format down + ì„ íƒí•œ ì¡°ê±´ë¶€ 서ì‹ì„ 아래로 ì´ë™í•©ë‹ˆë‹¤ - - Unique - 유니í¬(Unique) + + Move &down + 아래로 내리기(&D) - - Default - 기본값 + + Foreground + 전경색 - - Default value - 기본값 + + Text color + 글ìžìƒ‰ - - Check - 제약 + + Background + 배경색 - - Check constraint - 제약조건(Check constraint) + + Background color + 배경색 - - Foreign Key - 외래키 + + Font + 글꼴 - - Error creating table. Message from database engine: -%1 - í…Œì´ë¸” ìƒì„± ì—러. ë°ì´í„°ë² ì´ìФ 메시지: -%1 + + Size + í¬ê¸° - - There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. - ì´ í•„ë“œ ê°’ì´ NULL로 ë˜ì–´ìžˆëŠ”ëŠ” 레코드가 최소한 하나 ì´ìƒ 존재합니다. ì´ëŸ¬í•œ ìƒíƒœì—서는 ë³€ê²½ì´ ë¶ˆê°€ëŠ¥í•˜ë‹ˆ í…Œì´ë¸”ì˜ ë°ì´í„°ë¥¼ 먼저 수정해서 NULL ê°’ì„ ì‚­ì œì£¼ì„¸ìš”. + + Bold + 진하게 - - There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. - ì´ í•„ë“œ ê°’ì´ ìˆ«ìžê°€ 아닌 값으로 ë˜ì–´ìžˆëŠ”ëŠ” 레코드가 최소한 하나 ì´ìƒ 존재합니다. ì´ëŸ¬í•œ ìƒíƒœì—서는 ë³€ê²½ì´ ë¶ˆê°€ëŠ¥í•˜ë‹ˆ í…Œì´ë¸”ì˜ ë°ì´í„° ê°’ì„ ë¨¼ì € 변경해주세요. + + Italic + 기울임 - - Column `%1` has no unique data. - - 필드 '%1'ì´(ê°€) 중복ë˜ëŠ” ê°’ì„ ê°€ì§€ê³  있어 유니í¬ë¡œ 변경할 수 없습니다. - + + Underline + 밑줄 - - This makes it impossible to set this flag. Please change the table data first. - ì´ëŸ¬í•œ ìƒíƒœì—서는 ë³€ê²½ì´ ë¶ˆê°€ëŠ¥í•˜ë‹ˆ í…Œì´ë¸”ì˜ ë°ì´í„° ê°’ì„ ë¨¼ì € 변경해주세요. + + Alignment + ì •ë ¬ - - Are you sure you want to delete the field '%1'? -All data currently stored in this field will be lost. - ì •ë§ë¡œ '%1' 필드를 삭제하시려는 건가요? -ì´ í•„ë“œì— ì €ìž¥ëœ ëª¨ë“  ë°ì´í„°ê°€ ê°™ì´ ì‚­ì œë©ë‹ˆë‹¤. + + Condition + ì¡°ê±´ - - Please add a field which meets the following criteria before setting the without rowid flag: - - Primary key flag set - - Auto increment disabled - 'rowid 사용하지 않ìŒ'ì„ ì‚¬ìš©í•˜ê¸° 위해서는 아래 ë‘ ê°€ì§€ ì‚¬í•­ì„ ë§Œì¡±ì‹œí‚¤ëŠ” 필드를 추가해주세요: - - 주 키(Primary Key) 사용 - - ìžë™ì¦ê°€(Auto Increment) 사용하지 ì•ŠìŒ + + + Click to select color + 색ìƒì„ ì„ íƒí•˜ì„¸ìš” + + + + Are you sure you want to clear all the conditional formats of this field? + ì´ í•„ë“œì˜ ëª¨ë“  ì¡°ê±´ë¶€ 서ì‹ì„ ì •ë§ë¡œ 삭제하시겠습니까? - ExportCsvDialog + DBBrowserDB - - Export data as CSV - ë°ì´í„°ë¥¼ CSV 파ì¼ë¡œ 내보내기 + + Please specify the database name under which you want to access the attached database + ë°ì´í„°ë² ì´ìФ ì—°ê²°ì„ ìœ„í•´ 불러올 ë°ì´í„°ë² ì´ìŠ¤ì˜ ë³„ì¹­ì„ ì§€ì •í•´ì£¼ì„¸ìš” - - &Table(s) - í…Œì´ë¸”(&T) + + Invalid file format + ìž˜ëª»ëœ íŒŒì¼ í¬ë§·ìž…니다 - - &Column names in first line - 첫 í–‰ì— í•„ë“œ ì´ë¦„ í¬í•¨(&C) + + Do you want to save the changes made to the database file %1? + %1 ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ìƒì„±í•˜ê¸° 위해 ë³€ê²½ì‚¬í•­ì„ ì €ìž¥í•˜ê² ìŠµë‹ˆê¹Œ? - - Field &separator - 필드 구분ìž(&S) + + Exporting database to SQL file... + ë°ì´í„°ë² ì´ìŠ¤ë¥¼ SQL 파ì¼ë¡œ 내보내는 중... - - , - , + + + Cancel + 취소 - - ; - ; + + Executing SQL... + SQL 실행 중... - - - Tab - 탭 + + Action cancelled. + ì‹¤í–‰ì´ ì·¨ì†Œë˜ì—ˆìŠµë‹ˆë‹¤. - - | - | + + Do you really want to close this temporary database? All data will be lost. + ì´ ìž„ì‹œ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ë‹«ì„까요? 모든 ë°ì´í„°ê°€ 사ë¼ì§‘니다. - - - Other - 기타 + + Database didn't close correctly, probably still busy + ë°ì´í„°ë² ì´ìŠ¤ê°€ 제대로 닫히지 않았습니다, ì•„ë§ˆë„ ì•„ì§ ì‚¬ìš© ì¤‘ì¼ ê²ƒìž…ë‹ˆë‹¤ - - &Quote character - 문ìžì—´ ë¬¶ìŒ ê¸°í˜¸(&Q) + + Cannot open destination file: '%1' + ëŒ€ìƒ íŒŒì¼ì„ ì—´ 수 없습니다.: '%1' - - " - " + + + Cannot backup to file: '%1'. Message: %2 + 파ì¼ë¡œ 백업할 수 없습니다.: '%1'. 메시지: %2 - - ' - ' + + The database is currently busy: + ì´ ë°ì´í„°ë² ì´ìŠ¤ëŠ” 현재 사용 중입니다: - - Could not open output file: %1 - 내보낸 파ì¼ì„ ì—´ 수 없습니다: %1 + + Do you want to abort that other operation? + ì´ ëª…ë ¹ì„ ì·¨ì†Œí•˜ì‹œê² ìŠµë‹ˆê¹Œ? - - - Choose a filename to export data - ë°ì´í„°ë¥¼ 내보낼 íŒŒì¼ ì´ë¦„ì„ ì •í•˜ì„¸ìš” + + + No database file opened + 열린 ë°ì´í„°ë² ì´ìФ 파ì¼ì´ 없습니다 - - - Text files(*.csv *.txt) - 문ìžì—´ 파ì¼(*.csv *.txt) + + + Error in statement #%1: %2. +Aborting execution%3. + #%1: %2 êµ¬ë¬¸ì— ì—러가 있어 ì‹¤í–‰ì´ ì¤‘ë‹¨ë˜ì—ˆìŠµë‹ˆë‹¤%3. - - Please select at least 1 table. - 최소한 í…Œì´ë¸” 1개는 ì„ íƒí•˜ì„¸ìš”. + + + and rolling back + 그리고 롤백합니다 - - Choose a directory - 디렉토리를 ì„ íƒí•˜ì„¸ìš” + + didn't receive any output from %1 + %1ì—서 아무런 ì¶œë ¥ì„ ë°›ì§€ 못했습니다 - - Export completed. - 내보내기가 완료ë˜ì—ˆìŠµë‹ˆë‹¤. + + could not execute command: %1 + ëª…ë ¹ì„ ì‹¤í–‰í•  수 없습니다: %1 - - - ExportSqlDialog - - Export SQL... - SQL로 내보내기... + + Cannot delete this object + ì´ ê°ì²´ë¥¼ 삭제할 수 없습니다 - - &Table(s) - í…Œì´ë¸”(&T) + + Cannot set data on this object + ì´ ê°ì²´ì—는 ë°ì´í„°ë¥¼ 저장할 수 없습니다 - - &Options - 옵션(&O) + + + A table with the name '%1' already exists in schema '%2'. + '%1' ì´ë¦„ì˜ í…Œì´ë¸”ì´ ì´ë¯¸ 스키마 '%2'ì— ì¡´ìž¬í•©ë‹ˆë‹¤. - - Keep column names in INSERT INTO - INSERT INTOì—서 필드명 유지하기 + + No table with name '%1' exists in schema '%2'. + 스키마 '%2'ì— ì´ë¦„ì´ '%1'ì¸ í…Œì´ë¸”ì´ ì—†ìŠµë‹ˆë‹¤. - - New INSERT INTO syntax (multiple rows in VALUES) - 새 INSERT INTO 문법 사용(VALUESì—서 다중 í–‰ 사용) + + + Cannot find column %1. + %1 ì»¬ëŸ¼ì„ ì°¾ì„ ìˆ˜ 없습니다. - - Export schema only - 스키만 내보내기 + + Creating savepoint failed. DB says: %1 + 세ì´ë¸Œ í¬ì¸íŠ¸ë¥¼ ìƒì„±í•˜ì§€ 못했습니다. DB 메시지: %1 - - Please select at least 1 table. - 최소한 1 ê°œì˜ í…Œì´ë¸”ì„ . + + Renaming the column failed. DB says: +%1 + ì—´ ì´ë¦„ì„ ë³€ê²½í•˜ì§€ 못했습니다. DB 메시지: +%1 - - Choose a filename to export - 내보내기 í•  파ì¼ëª…ì„ ê³ ë¥´ì„¸ìš” + + + Releasing savepoint failed. DB says: %1 + 세ì´ë¸Œ í¬ì¸íŠ¸ë¥¼ 해제하지 못했습니다. DB 메시지: %1 - - Text files(*.sql *.txt) - í…스트 파ì¼(*.sql *.txt) + + Creating new table failed. DB says: %1 + 새 í…Œì´ë¸”ì„ ìƒì„±í•˜ì§€ 못했습니다. DB 메시지: %1 - - Export completed. - 내보내기가 완료ë˜ì—ˆìŠµë‹ˆë‹¤. + + Copying data to new table failed. DB says: +%1 + 새 í…Œì´ë¸”ì— ë°ì´í„°ë¥¼ 복사하지 못했습니다. DB 메시지: +%1 - - Export cancelled or failed. - 내보내기가 취소ë˜ì—ˆê±°ë‚˜ 실패했습니다. + + Deleting old table failed. DB says: %1 + ì´ì „ í…Œì´ë¸”ì„ ì‚­ì œí•˜ì§€ 못했습니다. DB 메시지: %1 - - - FilterLineEdit - - Filter - í•„í„° + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + í…Œì´ë¸” '%1'ì˜ ì´ë¦„ì„ '%2'(으)로 변경하는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. +ë°ì´í„°ë² ì´ìФ 엔진 메시지: +%3 - - - ImportCsvDialog - - Import CSV file - CSV íŒŒì¼ ê°€ì ¸ì˜¤ê¸° + + could not get list of db objects: %1 + DB 개체 목ë¡ì„ 가져알 수 없습니다: %1 - - &Table name - í…Œì´ë¸” ì´ë¦„(&T) + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + ì´ í…Œì´ë¸”ì— ê´€ë ¨ëœ ëª‡ ê°œì˜ ê°ì²´ë¥¼ ë³µì›í•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤. ì´ëŸ¬í•œ 경우는 대부분 몇 ê°œì˜ í•„ë“œëª…ì´ ë³€ê²½ë˜ì–´ì„œ ë°œìƒ í–ˆì„ ê°€ëŠ¥ì„±ì´ í½ë‹ˆë‹¤. 아래 SQL êµ¬ë¬¸ì„ ì°¸ê³ í•˜ë©´ ì§ì ‘ 수ë™ìœ¼ë¡œ ê³ ì³ì„œ 실행할 수 ìžˆì„ ê²ƒìž…ë‹ˆë‹¤: + + - - &Column names in first line - 첫 í–‰ì— í•„ë“œ ì´ë¦„ í¬í•¨(&C) + + could not get list of databases: %1 + ë°ì´í„°ë² ì´ìФ 목ë¡ì„ 가져올 수 없습니다: %1 - - Field &separator - 필드 구분ìž(&S) + + Error loading extension: %1 + í™•ìž¥ê¸°ëŠ¥ì„ ë¶ˆëŸ¬ì˜¤ê¸° ì—러: %1 - - , - , + + Error loading built-in extension: %1 + 내장 í™•ìž¥ê¸°ëŠ¥ì„ ë¶ˆëŸ¬ì˜¤ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤: %1 - - ; - ; + + could not get column information + ì—´ 정보를 가져올 수 없습니다 - - - Tab - 탭 + + Error setting pragma %1 to %2: %3 + pragma ì„¤ì •ì„ %1ì—서 %2로 ë³€ê²½í•˜ëŠ”ë° ì—러: %3 - - | - | + + File not found. + 파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다. + + + DbStructureModel - - - - Other - 기타 + + Name + ì´ë¦„ - - &Quote character - 문ìžì—´ ë¬¶ìŒ ê¸°í˜¸(&Q) + + Object + ê°ì²´ - - " - " + + Type + 타입 - - ' - ' + + Schema + 스키마 - - &Encoding - ì¸ì½”딩(&E) + + Database + ë°ì´í„°ë² ì´ìФ - - UTF-8 - UTF-8 + + Browsables + 열기 - - UTF-16 - UTF-16 + + All + ëª¨ë‘ ì„ íƒ - - ISO-8859-1 - ISO-8859-1 + + Temporary + 임시 - - Trim fields? - 필드 앞뒤 공백제거(트림)? + + Tables (%1) + í…Œì´ë¸” (%1) - - Inserting data... - ë°ì´í„° 추가하는 중... + + Indices (%1) + ì¸ë±ìФ (%1) - - Cancel - 취소 + + Views (%1) + ë·° (%1) - - There is already a table of that name and an import into an existing table is only possible if the number of columns match. - 가져오려는 í…Œì´ë¸”ì˜ ì´ë¦„ì´ ê°™ê³  í•„ë“œì˜ ìˆ˜ê°€ ê°™ì€ ê²½ìš°ì—ë§Œ 가능합니다. + + Triggers (%1) + 트리거 (%1) + + + EditDialog - - There is already a table of that name. Do you want to import the data into it? - ê°™ì€ ì´ë¦„ì˜ í…Œì´ë¸”ì´ ì´ë¯¸ 존재합니다. ë°ì´í„°ë§Œì´ë¼ë„ 가져올까요? + + Edit database cell + ë°ì´í„°ë² ì´ìФ ë°ì´í„° ê°’ì„ ìˆ˜ì •í•˜ê¸° - - Creating restore point failed: %1 - ë³µì› í¬ì¸íŠ¸ë¥¼ ìƒì„±í•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤: %1 + + Mode: + 모드: - - Creating the table failed: %1 - í…Œì´ë¸” ìƒì„±ì— 실패했습니다: %1 + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + ì…€ ì—디터ì—서 ì§€ì›ë˜ëŠ” 모ë¸ë“¤ 목ë¡ìž…니다. 현재 ì…€ì˜ ë°ì´í„°ë¥¼ 보거나 수정하기 위한 모드를 ì„ íƒí•˜ì„¸ìš”. - - Missing field for record %1 - ë ˆì½”ë“œì— %1 필드가 빠져있습니다 + + RTL Text + RTL Text - - Inserting row failed: %1 - í–‰ ì¶”ê°€ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤: %1 + + + Image + ì´ë¯¸ì§€ - - - MainWindow - - DB Browser for SQLite - DB Browser for SQLite + + JSON + JSON - - Database &Structure - ë°ì´í„°ë² ì´ìФ 구조(&S) + + XML + XML - - - toolBar1 - toolBar1 + + Evaluation + í‰ê°€ - - &Browse Data - ë°ì´í„° 보기(&B) + + + Automatically adjust the editor mode to the loaded data type + 불러온 ë°ì´í„° íƒ€ìž…ì„ ì—디터 ëª¨ë“œì— ìžë™ ì ìš© - - Table: - í…Œì´ë¸”: + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + ì´ ì²´í¬ ë²„íŠ¼ì€ ì—디터 모드를 ìžë™ìœ¼ë¡œ 변경하는 ê¸°ëŠ¥ì„ í‚¤ê±°ë‚˜ ë•니다. 새 ì…€ì´ ì„ íƒë˜ê±°ë‚˜ 새로운 ë°ì´í„°ê°€ 가져와지면 ìžë™ 변경 ê¸°ëŠ¥ì´ ì¼œì ¸ì„œ ë°ì´í„° íƒ€ìž…ì„ ì¸ì‹í•˜ì—¬ ì ì ˆí•œ 모드를 ì ìš©í•©ë‹ˆë‹¤. ê·¸ í›„ì— ì—¬ëŸ¬ë¶„ì€ ëª¨ë“œë¥¼ 수ë™ìœ¼ë¡œ 변경할 수 있습니다. 만약 ì…€ë“¤ì„ ì´ë™í•  때 모드를 ì§ì ‘ ë³€ê²½í•˜ê³ ìž í•œë‹¤ë©´, ì´ ë²„íŠ¼ì„ ë¹„í™œì„±í™”í•˜ì„¸ìš”. - - Select a table to browse data - 보려는 ë°ì´í„°ê°€ 있는 í…Œì´ë¸”ì„ ì„ íƒí•˜ì„¸ìš” + + Auto-switch + ìžë™ 전환 - - Use this list to select a table to be displayed in the database view - 리스트ì—서 í…Œì´ë¸”ì„ ì„ íƒí•˜ë©´ ë°ì´í„°ë² ì´ìФ ë·°ì—서 ë³¼ 수 있습니다 + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + ì´ Qt 편집기는 기본 í…스트 편집기ì—서 ì§€ì›í•˜ì§€ 않는 오른쪽ì—서 왼쪽으로 쓰는 스í¬ë¦½íŠ¸ì— ì‚¬ìš©ë©ë‹ˆë‹¤. 오른쪽ì—서 왼쪽으로 작성ë˜ëŠ” 문ìžê°€ ê°ì§€ë˜ë©´ ì´ íŽ¸ì§‘ê¸° 모드가 ìžë™ìœ¼ë¡œ ì„ íƒë©ë‹ˆë‹¤. - - Refresh the data in the selected table. - ì„ íƒëœ í…Œì´ë¸”ì˜ ë°ì´í„°ë¥¼ 다시 불러옵니다. + + Identification of the cell currently in the editor + 현재 íŽ¸ì§‘ê¸°ì— ìžˆëŠ” ì…€ì˜ ì •ì˜ - - This button refreshes the data in the currently selected table. - ì´ ë²„íŠ¼ì€ í˜„ìž¬ ì„ íƒëœ í…Œì´ë¸”ì˜ ë°ì´í„°ë¥¼ 다시 불러옵니다. + + Type and size of data currently in table + 현재 í…Œì´ë¸”ì— ìžˆëŠ” ë°ì´í„°ì˜ 유형 ë° í¬ê¸° - - - F5 - F5 + + Apply data to cell + ì…€ì— ë°ì´í„° ì ìš© - - Clear all filters - 모든 í•„í„° 지우기 + + Open preview dialog for printing the data currently stored in the cell + 현재 ì…€ì— ì €ìž¥ëœ ë°ì´í„°ì— 대한 ì¸ì‡„ 미리보기 대화ìƒìž 열기 - - Insert a new record in the current table - 현재 í…Œì´ë¸”ì— ìƒˆ 레코드를 추가합니다 + + Auto-format: pretty print on loading, compact on saving. + ìžë™í¬ë§·: 불러올 때 예ì˜ê²Œ 프린트ë˜ê³ , 저장할 때 ìš©ëŸ‰ì„ ì¤„ìž…ë‹ˆë‹¤. - - This button creates a new, empty record in the database - ì´ ë²„íŠ¼ì€ ìƒˆë¡œìš´ 비어있는 레코드를 ë°ì´í„°ë² ì´ìŠ¤ì— ìƒì„±í•©ë‹ˆë‹¤ + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + 활성화ë˜ë©´, ìžë™í¬ë§· ê¸°ëŠ¥ì´ ë°ì´í„°ë¥¼ 불러올 때 í¬ë§·ì„ 지정하여 긴 ë¬¸ìž¥ì„ ì—¬ëŸ¬ 행으로 만들고 들여쓰기를 해서 ê°€ë…ì„±ì„ í–¥ìƒí•©ë‹ˆë‹¤. ë°ì´í„°ë¥¼ 저장할 때는 ìžë™í¬ë§· ê¸°ëŠ¥ì€ ê°œí–‰ 문ìžë¥¼ 제거하여 ë°ì´í„°ë¥¼ 줄ì´ê³  í•„ìš” 없는 ê³µë°±ì„ ì‚­ì œí•©ë‹ˆë‹¤. - - New Record - 새 레코드 + + Word Wrap + 개행 - - Delete the current record - 현재 레코드 삭제하기 + + Wrap lines on word boundaries + 단어 경계마다 개행 - - This button deletes the record currently selected in the database - ì´ ë²„íŠ¼ì€ ë°ì´í„°ë² ì´ìФì—서 현재 ì„ íƒë˜ì–´ìžˆëŠ” 레코드를 삭제합니다 + + + Open in default application or browser + 기본 ì‘ìš© 프로그램 ë˜ëŠ” 브ë¼ìš°ì €ì—서 열기 - - Delete Record - 레코드 ì‚­ì œ + + Open in application + ì‘ìš© 프로그램ì—서 열기 - - This is the database view. You can double-click any record to edit its contents in the cell editor window. - 여기는 ë°ì´í„°ë² ì´ìФ 뷰입니다. 레코드를 ë”블í´ë¦­í•˜ë©´ 편집기창ì—서 ê°’ì„ ìˆ˜ì •í•  수 있습니다. + + The value is interpreted as a file or URL and opened in the default application or web browser. + ê°’ì€ íŒŒì¼ ë˜ëŠ” URL로 í•´ì„ë˜ë©° 기본 애플리케ì´ì…˜ ë˜ëŠ” 웹 브ë¼ìš°ì €ì—서 열립니다. - - <html><head/><body><p>Scroll to the beginning</p></body></html> - <html><head/><body><p>맨 위로 스í¬ë¡¤í•˜ê¸°</p></body></html> + + Save file reference... + 참조를 파ì¼ì— 저장... - - <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> - <html><head/><body><p>í…Œì´ë¸” ë·° 맨 위로 가기 위해서는 ë²„íŠ¼ì„ í´ë¦­í•˜ì„¸ìš”.</p></body></html> + + Save reference to file + 파ì¼ì— 참조 저장 - - |< - |< + + + Open in external application + 외부 프로그램ì—서 열기 - - Scroll 100 records upwards - <html><head/><body><p>100 레코드 스í¬ë¡¤ 올리기</p></body></html> + + Autoformat + ìžë™í¬ë§· - - <html><head/><body><p>Clicking this button navigates 100 records upwards in the table view above.</p></body></html> - <html><head/><body><p>í…Œì´ë¸” ë·°ì—서 100 레코드 위로 스í¬ë¡¤í•˜ë ¤ë©´ ì´ ë²„íŠ¼ì„ í´ë¦­í•˜ì„¸ìš”.</p></body></html> + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + í…스트 편집기 모드를 사용하면 저장하기 ì „ì— êµ¬ë¬¸ ê°•ì¡°, ìžë™ ì„œì‹ ë° ìœ íš¨ì„± 검사를 통해 ì¼ë°˜ í…스트는 물론 JSON ë˜ëŠ” XML ë°ì´í„°ë¥¼ 편집할 수 있습니다. + +오류는 빨간색 물결선 밑줄로 표시ë©ë‹ˆë‹¤. + +í‰ê°€ 모드ì—서 입력한 SQLite 표현ì‹ì´ í‰ê°€ë˜ê³  결과가 ì…€ì— ì ìš©ë©ë‹ˆë‹¤. - - < - < + + &Export... + 내보내기(&E)... - - 0 - 0 of 0 - 0 - 0 of 0 + + + &Import... + 가져오기(&I)... - - <html><head/><body><p>Scroll 100 records downwards</p></body></html> - <html><head/><body><p>100 레코드 스í¬ë¡¤ 내리기</p></body></html> + + + Import from file + 파ì¼ì—서 가져오기 - - <html><head/><body><p>Clicking this button navigates 100 records downwards in the table view above.</p></body></html> - <html><head/><body><p>í…Œì´ë¸”ë·°ì—서 100 레코드 아래로 스í¬ë¡¤í•˜ë ¤ë©´ ì´ ë²„íŠ¼ì„ í´ë¦­í•˜ì„¸ìš”.</p></body></html> + + + Opens a file dialog used to import any kind of data to this database cell. + ì´ ë°ì´í„°ë² ì´ìФ 셀로 ë°ì´í„°ë¥¼ 가져오기 위하여 대화ìƒìžë¥¼ 엽니다. - - > - > + + Export to file + 파ì¼ë¡œ 내보내기 - - Scroll to the end - <html><head/><body><p>맨 아래로 스í¬ë¡¤í•˜ê¸°</p></body></html> + + Opens a file dialog used to export the contents of this database cell to a file. + ì´ ë°ì´í„°ë² ì´ìФ ì…€ì˜ ë‚´ìš©ì„ íŒŒì¼ë¡œ ë‚´ë³´ë‚´ëŠ”ë° ì‚¬ìš©ë˜ëŠ” 대화 ìƒìžë¥¼ 엽니다. - - <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> - <html><head/><body><p>í…Œì´ë¸” ë·° 맨 아래로 가기 위해서는 ì´ ë²„íŠ¼ì„ í´ë¦­í•˜ì„¸ìš”.</p></body></html> + + Print... + - - >| - >| + + Ctrl+P + - - <html><head/><body><p>Click here to jump to the specified record</p></body></html> - <html><head/><body><p>특정 레코드로 ì í”„하려면 여기를 í´ë¦­í•˜ì„¸ìš”</p></body></html> + + Open preview dialog for printing displayed text + ì¶œë ¥ëœ í…스트를 ì¸ì‡„하기 위한 ì¸ì‡„ 미리보기 ì°½ì„ ì—½ë‹ˆë‹¤ - - <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> - <html><head/><body><p>ì´ ë²„íŠ¼ì€ íŠ¹ì • ìœ„ì¹˜ì˜ ë ˆì½”ë“œ 넘버로 가기 위해서 사용합니다.</p></body></html> + + Copy Hex and ASCII + Hex와 ASCII를 복사합니다 - - Go to: - 특정 레코드 행으로 가기: + + Copy selected hexadecimal and ASCII columns to the clipboard + ì„ íƒëœ 16진수와 ASCII 필드를 í´ë¦½ë³´ë“œë¡œ 복사합니다 - - Enter record number to browse - 레코드 í–‰ 번호를 입력하세요 + + Ctrl+Shift+C + - - Type a record number in this area and click the Go to: button to display the record in the database view - 레코드 행번호를 입력하고 '특정 레코드 행으로 가기:' ë²„íŠ¼ì„ í´ë¦­í•˜ë©´ ë°ì´í„°ë² ì´ìФ ë·°ì— ë ˆì½”ë“œê°€ 표시ë©ë‹ˆë‹¤ + + Set as &NULL + NULL로 만들기(&N) - - 1 - 1 + + This button saves the changes performed in the cell editor to the database cell. + ì´ ë²„íŠ¼ì€ ë°ì´í„° ì…€ì— ì…€ ì—ë””í„°ì˜ ë³€ê²½ ì‚¬í•­ì„ ì ìš©í•˜ì—¬ 저장하는 버튼입니다. - - Edit &Pragmas - Pragmas 수정하기(&P) + + Apply + ì ìš© - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> + + Text + 문ìžì—´ - - - - None - 사용하지 ì•ŠìŒ + + Binary + ë°”ì´ë„ˆë¦¬ - - - Full - Full + + Erases the contents of the cell + ì…€ì˜ ë°ì´í„° ê°’ì„ ì‚­ì œí•©ë‹ˆë‹¤ - - Incremental - ì¦ë¶„(Incremental) + + This area displays information about the data present in this database cell + ì´ ì˜ì—­ì€ ì´ ë°ì´í„°ë² ì´ìФ ë°ì´í„° ê°’ì— ëŒ€í•œ 정보를 ë³´ì—¬ì¤ë‹ˆë‹¤ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">ìžë™ ì¸ë±ìФ</span></a></p></body></html> + + Choose a filename to export data + 내보내기 í•  ë°ì´í„°ì˜ íŒŒì¼ ì´ë¦„ì„ ì„ íƒí•˜ì„¸ìš” - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> + + + Image data can't be viewed in this mode. + ì´ë¯¸ì§€ ë°ì´í„°ëŠ” ì´ ëª¨ë“œì—서는 ë³¼ 수 없습니다. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">외래키</span></a></p></body></html> + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + ì…€ íŽ¸ì§‘ê¸°ì— ì•„ì§ ë°ì´í„°ë² ì´ìŠ¤ì— ì ìš©ë˜ì§€ ì•Šì€ ë°ì´í„°ê°€ 있습니다. +편집한 ë°ì´í„°ë¥¼ row=%1, column=%2ì— ì ìš©í•˜ì‹œê² ìŠµë‹ˆê¹Œ? - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> + + Editing row=%1, column=%2 + í–‰=%1, ì—´=%2 편집 중 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">제약조건 무시</span></a></p></body></html> + + No cell active. + í™œì„±í™”ëœ ì…€ì´ ì—†ìŒ. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">ì €ë„ ëª¨ë“œ</span></a></p></body></html> + + + Try switching to Image or Binary mode. + ì´ë¯¸ì§€ë‚˜ ë°”ì´ë„ˆë¦¬ 모드로 바꿔보세요. - - Delete - ì‚­ì œ + + + Binary data can't be viewed in this mode. + ë°”ì´ë„ˆë¦¬ ë°ì´í„°ëŠ” ì´ ëª¨ë“œì—서 ë³¼ 수 없습니다. - - Truncate - 비우기 + + + Try switching to Binary mode. + ë°”ì´ë„ˆë¦¬ 모드로 바꿔보세요. - - Persist - Persist + + + Image files (%1) + ì´ë¯¸ì§€ íŒŒì¼ (%1) - - - Memory - 메모리 + + Binary files (*.bin) + ë°”ì´ë„ˆë¦¬ íŒŒì¼ (*.bin) - - WAL - WAL + + + Type: NULL; Size: 0 bytes + 타입: NULL; í¬ê¸°: 0 ë°”ì´íЏ - - - - Off - 사용안함 + + + + Type: Text / Numeric; Size: %n character(s) + + 타입: í…스트/숫ìž; í¬ê¸°: %nìž + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">ì €ë„ í¬ê¸° 제한</span></a></p></body></html> + + Type: %1 Image; Size: %2x%3 pixel(s) + 타입: %1 ì´ë¯¸ì§€; í¬ê¸°: %2x%3픽셀 - - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">잠금(Locking) 모드</span></a></p></body></html> + + + Type: Valid JSON; Size: %n character(s) + + 타입: 유효한 JSON; í¬ê¸°: %nìž + + + + + Type: Binary; Size: %n byte(s) + + 타입: ë°”ì´ë„ˆë¦¬; í¬ê¸°: %n ë°”ì´íЏ + - - - Normal - ì¼ë°˜ + + Choose a file to import + 가져올 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” - - Exclusive - ë…ì (Exclusive) + + Unsaved data in the cell editor + ì…€ íŽ¸ì§‘ê¸°ì— ì €ìž¥ë˜ì§€ ì•Šì€ ë°ì´í„° - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">최대 페ì´ì§€ 수</span></a></p></body></html> + + %1 Image + %1 ì´ë¯¸ì§€ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">페ì´ì§€ í¬ê¸°</span></a></p></body></html> + + Invalid data for this mode + ì´ ëª¨ë“œì— ë§žì§€ 않는 ë°ì´í„° - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">재귀 트리거</span></a></p></body></html> + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + ì´ ì…€ì—는 올바르지 ì•Šì€ %1 ë°ì´í„°ë¥¼ í¬í•¨í•˜ê³  있습니다. ì´ìœ : %2. ì´ ì…€ì„ ì •ë§ë¡œ ì ìš©í• ê¹Œìš”? - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">보안(Secure) ì‚­ì œ</span></a></p></body></html> + + Couldn't save file: %1. + 파ì¼ì„ 저장할 수 없습니다: %1. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">ë™ê¸°í™”(Synchronous)</span></a></p></body></html> + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + ë°ì´í„°ëŠ” 임시 파ì¼ì— 저장ë˜ì—ˆìœ¼ë©° 기본 ì‘ìš© 프로그램으로 열렸습니다. ì´ì œ 파ì¼ì„ 편집할 수 있으며 ìž‘ì—…ì´ ì™„ë£Œë˜ë©´ ì €ìž¥ëœ ìƒˆ ë°ì´í„°ë¥¼ ì…€ì— ì ìš©í•˜ê±°ë‚˜ ë³€ê²½ì‚¬í•­ì„ ì·¨ì†Œí•  수 있습니다. + + + EditIndexDialog - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">임시 저장소(Temp Store)</span></a></p></body></html> + + &Name + ì´ë¦„(&N) - - Default - 기본 + + Order + ì •ë ¬ 순서 - - File - íŒŒì¼ + + &Table + í…Œì´ë¸”(&T) - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">ì‚¬ìš©ìž ë²„ì „</span></a></p></body></html> + + Edit Index Schema + ì¸ë±ìФ 스키마 수정 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL ìžë™ ì²´í¬í¬ì¸íЏ</span></a></p></body></html> + + &Unique + 유니í¬(&U) - - E&xecute SQL - SQL 실행하기(&X) + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + ì¸ë±ìŠ¤ë¥¼ í…Œì´ë¸”ì˜ ì¼ë¶€ë¡œë§Œ 제한하기 위해서 ì¸ë±ì‹± 해야하는 í…Œì´ë¸”ì˜ ì¼ë¶€ë¥¼ 지정하는 WHERE ì ˆì„ ì§€ì •í•  수 있습니다 - - &File - 파ì¼(&F) + + Partial inde&x clause + 부분(Partial) ì¸ë±ìŠ¤ì ˆ(&X) - - &Import - 가져오기(&I) + + Colu&mns + ì—´(&M) - - &Export - 내보내기(&E) + + Table column + í…Œì´ë¸” ì—´ - - &Edit - 편집(&E) + + Type + 타입 - - &View - ë·°(&V) + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + ì¸ë±ìŠ¤ì— ìƒˆ í‘œí˜„ì‹ ì»¬ëŸ¼ì„ ì¶”ê°€í•˜ì„¸ìš”. í‘œí˜„ì‹ ì»¬ëŸ¼ì€ ì»¬ëŸ¼ ì´ë¦„ 대신 SQL 표현ì‹ì´ 들어갑니다. - - &Help - ë„움ë§(&H) + + Index column + ì¸ë±ìФ 컬럼 - - DB Toolbar - DB 툴바 + + Deleting the old index failed: +%1 + ì´ì „ ì¸ë±ìŠ¤ë¥¼ ì‚­ì œí•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤: %1 - - SQL Log - SQL 로그 + + Creating the index failed: +%1 + ì¸ë±ìФ ìƒì„±ì— 실패했습니다: +%1 + + + EditTableDialog - - &Show SQL submitted by - SQL 보기(&S) by + + Edit table definition + í…Œì´ë¸” ì •ì˜ ë³€ê²½ - - User - ì‚¬ìš©ìž + + Table + í…Œì´ë¸” - - Application - 애플리케ì´ì…˜ + + Advanced + 고급 - - &Clear - 지우기(&C) + + Without Rowid + Rowid 필드 ì—†ìŒ - - Plot - 플롯 + + Fields + 필드 + + + + Database sche&ma + ë°ì´í„°ë² ì´ìФ 스키마(&M) + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + ì´ í…Œì´ë¸”ì„ 'WITHOUT ROWID' í…Œì´ë¸”로 만듭니다. ì´ í”Œëž˜ê·¸ë¥¼ 설정하려면 PRIMARY KEY(모든 ìœ í˜•ì´ ë  ìˆ˜ 있으며 ë³µí•©í˜•ì¼ ìˆ˜ 있ìŒ)를 지정해야 하며 AUTOINCREMENT 플래그는 금지ë©ë‹ˆë‹¤. + + + + On Conflict + ì¶©ëŒ ì‹œ + + + + Strict + 엄격 모드 + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + 엄격 모드 ì˜µì…˜ì´ í™œì„±í™”ë˜ë©´ SQLite는 ë°ì´í„°ë¥¼ ì—…ë°ì´íŠ¸í•˜ê±°ë‚˜ 삽입할 때 ê° ì—´ì˜ ë°ì´í„° ìœ í˜•ì„ ì ìš©í•©ë‹ˆë‹¤. + + + + + + Add + 추가 + + + + + + Remove + ì‚­ì œ + + + + Move to top + 최ìƒë‹¨ìœ¼ë¡œ 올리기 + + + + Move up + 위로 올리기 + + + + Move down + 아래로 내리기 + + + + Move to bottom + 최하단으로 내리기 + + + + + + + Name + 필드명 + + + + + Type + 타입 + + + + NN + NN + + + + Not null + Not null + + + + PK + PK + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> 기본 키</p></body></html> + + + + AI + AI + + + + Autoincrement + ìžë™ ì¦ê°€(Autoincrement) + + + + U + U + + + + + + Unique + 유니í¬(Unique) + + + + Default + 기본값 - + + Default value + 기본값 + + + + + Check + ì²´í¬ + + + + Check constraint + 제약조건(Check constraint) + + + + Collation + 콜레ì´ì…˜ + + + + Foreign Key + 외래키 + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_fk"/> 외래 키</p></body></html> + + + + Index Constraints + ì¸ë±ìФ 제약 + + + + Add constraint + 제약 ì¡°ê±´ 추가 + + + + Remove constraint + 제약 ì¡°ê±´ ì‚­ì œ + + + + Columns 필드 - - X - X + + + + SQL + SQL - - Y - Y + + Foreign Keys + 외래 키 제약 - - _ - _ + + References + 참조 - - Line type: - í–‰ 타입: + + Check Constraints + ì²´í¬ ì œì•½ - - Line - í–‰ + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>ì´ í…Œì´ë¸” ì •ì˜ ì¤‘ì— íŒŒì„œê°€ í•´ì„í•  수 없는 ë¶€ë¶„ì´ ìžˆìŠµë‹ˆë‹¤. ì´ í…Œì´ë¸”ì„ ìˆ˜ì •í•˜ê±°ë‚˜ 저장하면 문제가 ë°œìƒí•  수 있습니다.</p></body></html> - - StepLeft - 왼쪽으로 + + + Primary Key + 기본 키 - - StepRight - 오른쪽으로 + + Add a primary key constraint + 기본 키 제약 ì¡°ê±´ 추가 - - StepCenter - 중앙으로 + + Add a unique constraint + ìœ ë‹ˆí¬ ì œì•½ ì¡°ê±´ 추가 - - Impulse - 임펄스 + + Error creating table. Message from database engine: +%1 + í…Œì´ë¸” ìƒì„± ì—러. ë°ì´í„°ë² ì´ìФ 메시지: +%1 - - Point shape: - í¬ì¸íЏ 모양: + + There already is a field with that name. Please rename it first or choose a different name for this field. + ì´ë¯¸ 다른 필드ì—서 ì‚¬ìš©ì¤‘ì¸ ì´ë¦„입니다. 다른 ì´ë¦„ì„ ì‚¬ìš©í•˜ê±°ë‚˜ 사용 ì¤‘ì¸ í•„ë“œ ì´ë¦„ì„ ë°”ê¾¸ì„¸ìš”. - - Cross - ì‹­ìžê°€ + + + There can only be one primary key for each table. Please modify the existing primary key instead. + ê° í…Œì´ë¸”마다 í•˜ë‚˜ì˜ ê¸°ë³¸ 키만 ìžˆì„ ìˆ˜ 있습니다. 기존 기본 키를 대신 수정하세요. - - Plus - ë”하기 + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + ì´ í•„ë“œëŠ” í…Œì´ë¸” %1 ì— ìžˆëŠ” ì™¸ëž˜í‚¤ì— ì°¸ì¡°ë˜ì–´ 있기 ë•Œë¬¸ì— ì´ë¦„ì„ ë³€ê²½í•  수 없습니다. - - Circle - ì› + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + ì´ í•„ë“œ ê°’ì´ NULL로 ë˜ì–´ 있는 레코드가 최소한 하나 ì´ìƒ 존재합니다. ì´ëŸ¬í•œ ìƒíƒœì—서는 ë³€ê²½ì´ ë¶ˆê°€ëŠ¥í•˜ë‹ˆ í…Œì´ë¸”ì˜ ë°ì´í„°ë¥¼ 먼저 수정해서 NULL ê°’ì„ ì‚­ì œì£¼ì„¸ìš”. - - Disc - ë””ìŠ¤í¬ + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + ì´ í•„ë“œ ê°’ì´ ìˆ«ìžê°€ 아닌 값으로 ë˜ì–´ 있는 레코드가 최소 하나 ì´ìƒ 존재합니다. ì´ëŸ¬í•œ ìƒíƒœì—서는 ë³€ê²½ì´ ë¶ˆê°€ëŠ¥í•˜ë‹ˆ í…Œì´ë¸”ì˜ ë°ì´í„° ê°’ì„ ë¨¼ì € 변경해주세요. - - Square - 정사ê°í˜• + + Column '%1' has duplicate data. + + %1 ì—´ì— ì¤‘ë³µëœ ë°ì´í„°ê°€ 있습니다. + - - Diamond - 마름모 + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + ì´ë¡œ ì¸í•´ ìœ ë‹ˆí¬ í”Œëž˜ê·¸ë¥¼ 설정할 수 없습니다. 중복 ë°ì´í„°ë¥¼ 제거하여야 ìœ ë‹ˆí¬ í”Œëž˜ê·¸ë¥¼ 설정할 수 있습니다. - - Star - 별 + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + ì •ë§ë¡œ '%1' 필드를 삭제하시겠습니까? +ì´ í•„ë“œì— ì €ìž¥ëœ ëª¨ë“  ë°ì´í„°ê°€ ê°™ì´ ì‚­ì œë©ë‹ˆë‹¤. - - Triangle - 삼ê°í˜• + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + 'rowid 사용하지 않ìŒ'ì„ ì‚¬ìš©í•˜ê¸° 위해서는 아래 ë‘ ê°€ì§€ ì‚¬í•­ì„ ë§Œì¡±ì‹œí‚¤ëŠ” 필드를 추가해주세요: + - 기본 키(Primary Key) 사용 + - ìžë™ ì¦ê°€(Auto Increment) 사용하지 ì•ŠìŒ - - TriangleInverted - 역삼ê°í˜• + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + ì¶©ëŒ ì‹œ 조치를 설정하기 ì „ì— ë‹¤ìŒ ê¸°ì¤€ì„ ì¶©ì¡±í•˜ëŠ” 필드를 추가하십시오. + - 기본 키(Primary Key) 플래그 + + + ExportDataDialog - - CrossSquare - CrossSquare + + Export data as CSV + ë°ì´í„°ë¥¼ CSV 파ì¼ë¡œ 내보내기 - - PlusSquare - PlusSquare + + Tab&le(s) + í…Œì´ë¸”(&l) - - CrossCircle - CrossCircle + + Colu&mn names in first line + 첫 í–‰ì´ í•„ë“œ ì´ë¦„(&M) - - PlusCircle - PlusCircle + + Fie&ld separator + 필드 구분ìž(&l) - - Peace - Peace + + , + , - - <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> - <html><head/><body><p>현재 플롯 저장하기...</p><p>íŒŒì¼ í¬ë§· 확장ìžë¥¼ 고르세요 (png, jpg, pdf, bmp)</p></body></html> + + ; + ; - - Save current plot... - 현재 플롯 저장하기... + + Tab + 탭 + + + + | + | - - DB Schema - DB 스키마 + + + + Other + 기타 - - &New Database... - 새 ë°ì´í„°ë² ì´ìФ(&N)... + + &Quote character + 문ìžì—´ ë¬¶ìŒ ê¸°í˜¸(&Q) - - - Create a new database file - 새 ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ìƒì„±í•©ë‹ˆë‹¤ + + " + " - - This option is used to create a new database file. - ì´ ì˜µì…˜ì€ ìƒˆ ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ìƒì„±í•˜ë ¤ê³  í•  때 사용합니다. + + ' + ' - - Ctrl+N - Ctrl+N + + New line characters + ê°œí–‰ë¬¸ìž + + + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) + + + + Unix: LF (\n) + Unix: LF (\n) + + + + Pretty print + ì¸ì‡„하기 ì¢‹ì€ ìŠ¤íƒ€ì¼ + + + + + Could not open output file: %1 + 내보낸 파ì¼ì„ ì—´ 수 없습니다: %1 + + + + + Choose a filename to export data + ë°ì´í„°ë¥¼ 내보낼 íŒŒì¼ ì´ë¦„ì„ ì •í•˜ì„¸ìš” + + + + Export data as JSON + JSON으로 내보내기 + + + + exporting CSV + CSV로 내보내기 + + + + + Error while writing the file '%1': %2 + '%1' 파ì¼ì„ 쓰는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤: %2 + + + + exporting JSON + JSON으로 내보내기 + + + + Please select at least 1 table. + 최소한 í…Œì´ë¸” 1개는 ì„ íƒí•˜ì„¸ìš”. + + + + Choose a directory + 디렉터리를 ì„ íƒí•˜ì„¸ìš” + + + + Export completed. + 내보내기가 완료ë˜ì—ˆìŠµë‹ˆë‹¤. + + + + Export finished with errors. + 내보내기가 오류와 함께 완료ë˜ì—ˆìŠµë‹ˆë‹¤. + + + + ExportSqlDialog + + + Export SQL... + SQL로 내보내기... + + + + Tab&le(s) + í…Œì´ë¸”(&l) + + + + Select All + ëª¨ë‘ ì„ íƒ + + + + Deselect All + ëª¨ë‘ ì„ íƒ í•´ì œ + + + + &Options + 옵션(&O) + + + + Keep column names in INSERT INTO + INSERT INTOë¬¸ì— í•„ë“œëª… 넣기 + + + + Multiple rows (VALUES) per INSERT statement + í•˜ë‚˜ì˜ INSERTë¬¸ì— ì—¬ëŸ¬ì¤„ (VALUES) 사용하기 + + + + Export everything + ëª¨ë‘ ë‚´ë³´ë‚´ê¸° + + + + Export data only + ë°ì´í„°ë§Œ 내보내기 + + + + Keep original CREATE statements + ì›ë³¸ CREATE ë¬¸ì„ ìœ ì§€ + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + ì´ì „ 스키마 유지하기 (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + ì´ì „ 스키마 ë®ì–´ì“°ê¸° (DROP TABLE, then CREATE TABLE) + + + + Export schema only + 스키마만 내보내기 + + + + Please select at least one table. + 최소한 한 ê°œì˜ í…Œì´ë¸”ì„ ì„ íƒí•´ì£¼ì„¸ìš”. + + + + Choose a filename to export + 내보내기 í•  파ì¼ëª…ì„ ê³ ë¥´ì„¸ìš” + + + + Export completed. + 내보내기가 완료ë˜ì—ˆìŠµë‹ˆë‹¤. + + + + Export cancelled or failed. + 내보내기가 취소ë˜ì—ˆê±°ë‚˜ 실패했습니다. + + + + ExtendedScintilla + + + + Ctrl+H + + + + + Ctrl+F + + + + + + Ctrl+P + + + + + Find... + 찾기... + + + + Find and Replace... + 검색과 바꾸기... + + + + Print... + ì¸ì‡„하기... + + + + ExtendedTableWidget + + + Use as Exact Filter + 정확한 필터로 ì ìš©í•˜ê¸° + + + + Containing + í¬í•¨í•˜ëŠ” + + + + Not containing + í¬í•¨í•˜ì§€ 않는 + + + + Not equal to + 같지 ì•Šì€ + + + + Greater than + 초과 + + + + Less than + 미만 + + + + Greater or equal + ì´ìƒ + + + + Less or equal + ì´í•˜ + + + + Between this and... + ì´ ê°’ê³¼ 사ì´ì—... + + + + Regular expression + ì •ê·œ í‘œí˜„ì‹ + + + + Edit Conditional Formats... + ì¡°ê±´ë¶€ ì„œì‹ íŽ¸ì§‘... + + + + Set to NULL + NULL로 변경하기 + + + + Cut + 잘ë¼ë‚´ê¸° + + + + Copy + 복사하기 + + + + Copy with Headers + í—¤ë” í¬í•¨ 복사하기 + + + + Copy as SQL + SQL로 복사하기 + + + + Paste + 붙여넣기 + + + + Print... + ì¸ì‡„하기... + + + + Use in Filter Expression + í•„í„° í‘œí˜„ì‹ ì ìš©í•˜ê¸° + + + + Alt+Del + + + + + Ctrl+Shift+C + + + + + Ctrl+Alt+C + + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + í´ë¦½ë³´ë“œì˜ ë‚´ìš©ì´ ì„ íƒí•œ 범위보다 í½ë‹ˆë‹¤. 어쨌든 추가할까요? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>모든 ë°ì´í„°ê°€ 로드ë˜ì§€ 않았습니다. <b>모든 í–‰ì„ ì„ íƒí•˜ê¸° ì „ì— ëª¨ë“  ë°ì´í„°ë¥¼ 로드하시겠습니까?</b><p><p><b> 아니요</b>를 ì„ íƒí•˜ë©´ ë” ì´ìƒ ë°ì´í„°ê°€ 로드ë˜ì§€ 않고 ì„ íƒì´ 수행ë˜ì§€ 않습니다.<br/><b>예</b> 를 ì„ íƒí•˜ë©´ ë°ì´í„°ê°€ 로드ë˜ëŠ” ë™ì•ˆ ì‹œê°„ì´ ë‹¤ì†Œ 걸릴 수 있지만 ì„ íƒì´ 완료ë©ë‹ˆë‹¤.</p>경고: 모든 ë°ì´í„°ë¥¼ 로드하려면 í° í…Œì´ë¸”ì„ ìœ„í•´ ë§Žì€ ì–‘ì˜ ë©”ëª¨ë¦¬ê°€ 필요할 수 있습니다. + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + ì„ íƒ ì‚¬í•­ì„ NULL로 설정할 수 없습니다. ì—´ %1ì— NOT NULL 제약 ì¡°ê±´ì´ ìžˆìŠµë‹ˆë‹¤. + + + + FileExtensionManager + + + File Extension Manager + íŒŒì¼ í™•ìž¥ìž ê´€ë¦¬ìž + + + + &Up + 위로(&U) + + + + &Down + 아래로(&D) + + + + &Add + 추가하기(&A) + + + + &Remove + 삭제하기(&R) + + + + + Description + 설명 + + + + Extensions + í™•ìž¥ìž + + + + *.extension + *.í™•ìž¥ìž + + + + FilterLineEdit + + + Filter + í•„í„° + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + ì´ ìž…ë ¥ 필드는 현재 ì„ íƒëœ í…Œì´ë¸”ì— ë¹ ë¥´ê²Œ 필터를 ì ìš©í•  수 있게 í•´ì¤ë‹ˆë‹¤. +기본ì ìœ¼ë¡œ ìž…ë ¥ ë°•ìŠ¤ì— ë“¤ì–´ê°€ìžˆëŠ” ì¡°ê±´ì— ë§žëŠ” í–‰ë“¤ì´ í‘œì‹œë©ë‹ˆë‹¤. +아래와 ê°™ì€ ì—°ì‚°ìžë“¤ì„ 사용할 수 있습니다: +% 와ì¼ë“œì¹´ë“œ +> 초과 +< 미만 +>= ì´ìƒ +<= ì´í•˜ += ê°™ìŒ: 정확히 ì¼ì¹˜ +<> 같지않ìŒ: 정확히 불ì¼ì¹˜ +x~y 범위: x와 yê°’ ì‚¬ì´ ê°’ +/regexp/ ì •ê·œ 표현ì‹ì— ì¼ì¹˜í•˜ëŠ” ê°’ + + + + Clear All Conditional Formats + 모든 ì¡°ê±´ë¶€ ì„œì‹ ì§€ìš°ê¸° + + + + Use for Conditional Format + ì¡°ê±´ë¶€ ì„œì‹ ì‚¬ìš© + + + + Edit Conditional Formats... + ì¡°ê±´ë¶€ ì„œì‹ íŽ¸ì§‘... + + + + Set Filter Expression + í•„í„° í‘œí˜„ì‹ ì„¤ì •í•˜ê¸° + + + + What's This? + ì´ê±´ 무엇ì¸ê°€ìš”? + + + + Is NULL + NULLìž„ + + + + Is not NULL + NULLì´ ì•„ë‹˜ + + + + Is empty + ë¹„ì–´ìžˆìŒ + + + + Is not empty + 비어있지 ì•ŠìŒ + + + + Not containing... + í¬í•¨í•˜ì§€ 않는... + + + + Equal to... + ê°™ì€... + + + + Not equal to... + 같지 않ì€... + + + + Greater than... + 초과... + + + + Less than... + 미만... + + + + Greater or equal... + ì´ìƒ... + + + + Less or equal... + ì´í•˜... + + + + In range... + 범위... + + + + Regular expression... + ì •ê·œ 표현ì‹... + + + + FindReplaceDialog + + + Find and Replace + 찾기와 바꾸기 + + + + Fi&nd text: + ì°¾ì„ í…스트(&N): + + + + Re&place with: + 바꾸려는 í…스트(&P): + + + + Match &exact case + ëŒ€ì†Œë¬¸ìž ì¼ì¹˜ 시(&E) + + + + Match &only whole words + ì „ì²´ 단어 ì¼ì¹˜ 시(&O) + + + + When enabled, the search continues from the other end when it reaches one end of the page + 활성화ë˜ë©´ 페ì´ì§€ì˜ 한쪽 ëì— ë„ë‹¬í–ˆì„ ë•Œ 다른 쪽 ëì—서 ê²€ìƒ‰ì´ ê³„ì†ë©ë‹ˆë‹¤ + + + + &Wrap around + ì „ì²´ 페ì´ì§€ 검색(&W) + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + 활성화ë˜ë©´ 커서 위치 뒤로 검색합니다. 그렇지 않으면 앞으로 검색합니다 + + + + Search &backwards + 뒤로 찾기(&B) + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>할성화ë˜ë©´ 현재 ì„ íƒ í•­ëª©ì—서만 찾습니다.</p></body></html> + + + + &Selection only + ì„ íƒ í•­ëª©ë§Œ(&S) + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>ì„ íƒí•˜ë©´ ì°¾ì„ íŒ¨í„´ì´ UNIX ì •ê·œ 표현ì‹ìœ¼ë¡œ í•´ì„ë©ë‹ˆë‹¤. <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>를 참고하십시오.</p></body></html> + + + + Use regular e&xpressions + ì •ê·œ í‘œí˜„ì‹ ì‚¬ìš©(&X) + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + 커서 위치ì—서 "뒤로 찾기"ì—서 설정한 ë°©í–¥ì— ë”°ë¼ ë‹¤ìŒ í•­ëª©ì„ ì°¾ìŠµë‹ˆë‹¤ + + + + &Find Next + ë‹¤ìŒ ì°¾ê¸°(&F) + + + + F3 + + + + + &Replace + 바꾸기(&R) + + + + Highlight all the occurrences of the text in the page + 페ì´ì§€ ë‚´ 찾으려는 í…스트를 ëª¨ë‘ ê°•ì¡° 표시합니다 + + + + F&ind All + ëª¨ë‘ ì°¾ê¸°(&I) + + + + Replace all the occurrences of the text in the page + 페ì´ì§€ ë‚´ ì¼ì¹˜í•˜ëŠ” 모든 í…스트를 바꿉니다 + + + + Replace &All + ëª¨ë‘ ë°”ê¾¸ê¸°(&A) + + + + The searched text was not found + 찾으려는 í…스트를 ì°¾ì„ ìˆ˜ 없습니다 + + + + The searched text was not found. + 찾으려는 í…스트를 ì°¾ì„ ìˆ˜ 없습니다. + + + + The searched text was found one time. + 찾으려는 í…스트를 한 번 발견ë˜ì—ˆìŠµë‹ˆë‹¤. + + + + The searched text was found %1 times. + 찾으려는 í…스트가 %1번 발견ë˜ì—ˆìŠµë‹ˆë‹¤. + + + + The searched text was replaced one time. + í…스트가 한 번 바뀌었습니다. + + + + The searched text was replaced %1 times. + %1ê°œì˜ í…스트가 바뀌었습니다. + + + + ForeignKeyEditor + + + &Reset + 초기화(&R) + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + 외부 키(ON UPDATE, ON DELETE 등.) + + + + ImageViewer + + + Image Viewer + ì´ë¯¸ì§€ ë·°ì–´ + + + + Reset the scaling to match the original size of the image. + ì´ë¯¸ì§€ì˜ ì›ëž˜ í¬ê¸°ì™€ ì¼ì¹˜í•˜ë„ë¡ ë°°ìœ¨ì„ ìž¬ì„¤ì •í•©ë‹ˆë‹¤. + + + + Set the scaling to match the size of the viewport. + ë·°í¬íЏ(Viewport)ì˜ í¬ê¸°ì™€ ì¼ì¹˜í•˜ë„ë¡ ë°°ì—´ì„ ì„¤ì •í•©ë‹ˆë‹¤. + + + + Print... + ì¸ì‡„... + + + + Open preview dialog for printing displayed image + í‘œì‹œëœ ì´ë¯¸ì§€ì— 대한 ì¸ì‡„ 미리보기 ì°½ì„ ì—½ë‹ˆë‹¤ + + + + Ctrl+P + + + + + ImportCsvDialog + + + Import CSV file + CSV íŒŒì¼ ê°€ì ¸ì˜¤ê¸° + + + + Table na&me + í…Œì´ë¸” ì´ë¦„(&M) + + + + &Column names in first line + 첫 í–‰ì— í•„ë“œëª… í¬í•¨(&C) + + + + Field &separator + 필드 구분ìž(&S) + + + + , + , + + + + ; + ; + + + + + Tab + 탭 + + + + | + | + + + + Other + 기타 + + + + &Quote character + 문ìžì—´ ë¬¶ìŒ ê¸°í˜¸(&Q) + + + + + Other (printable) + 기타 (ì¸ì‡„ìš©) + + + + + Other (code) + 기타 (코드) + + + + " + " + + + + ' + ' + + + + &Encoding + ì¸ì½”딩(&E) + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Trim fields? + 필드 앞뒤 공백 제거? + + + + Separate tables + í…Œì´ë¸” 나누기 + + + + Advanced + 고급 + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + CSV 파ì¼ì˜ 빈 ê°’ì„ ì´ ì—´ì˜ ê¸°ë³¸ ê°’ì´ ìžˆëŠ” 기존 í…Œì´ë¸”로 가져올 때 해당 ê¸°ë³¸ê°’ì´ ì‚½ìž…ë©ë‹ˆë‹¤. 대신 빈 ê°’ì„ ì‚½ìž…í•˜ë ¤ë©´ ì´ ì˜µì…˜ì„ í™œì„±í™”í•˜ì„¸ìš”. + + + + Ignore default &values + 기본 ê°’ì„ ë¬´ì‹œ(&V) + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + 기본 ê°’ ì—†ì´ ë¹„ì–´ 있는 ê°’ì„ NOT NULL 열로 가져오려고 í•  때 가져오기를 중단하려면 ì´ ì˜µì…˜ì„ í™œì„±í™”í•˜ì„¸ìš”. + + + + Fail on missing values + ê°’ ëˆ„ë½ ì‹œ 실패 + + + + Disable data type detection + ë°ì´í„° 타입 ì¸ì‹ ë„기 + + + + Disable the automatic data type detection when creating a new table. + 새 í…Œì´ë¸”ì„ ìƒì„±í•  때 ìžë™ ë°ì´í„° 타입 ì¸ì‹ ê¸°ëŠ¥ì„ ë•니다. + + + + Use local number conventions + 시스템 로케ì¼ì— ë”°ë¼ ìˆ«ìž ê°’ 처리 + + + + Use decimal and thousands separators according to the system locale. + 시스템 로케ì¼ì— ë”°ë¼ ì†Œìˆ˜ ë° ì²œ 단위 구분 기호를 사용합니다. + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + 기본 키, 고유 제약 ì¡°ê±´ ë˜ëŠ” 고유 ì¸ë±ìŠ¤ë¥¼ 사용하여 기존 í…Œì´ë¸”로 가져올 때 ì¶©ëŒ ê°€ëŠ¥ì„±ì´ ìžˆìŠµë‹ˆë‹¤. ì´ ì˜µì…˜ì„ ì‚¬ìš©í•˜ë©´ 해당 ê²½ìš°ì— ëŒ€í•œ 대처 ë°©ì•ˆì„ ì„ íƒí•  수 있습니다. 기본ì ìœ¼ë¡œëŠ” 가져오기가 중단ë˜ê³  롤백ë˜ì§€ë§Œ ì¶©ëŒí•˜ëŠ” í–‰ì„ ë¬´ì‹œí•˜ê³  가져오지 않거나 í…Œì´ë¸”ì˜ ê¸°ì¡´ í–‰ì„ ë°”ê¾¸ë„ë¡ ì„ íƒí•  ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. + + + + Abort import + 가져오기 취소 + + + + Ignore row + ì—´ 무시 + + + + Replace existing row + 기존 í–‰ 바꾸기 + + + + Conflict strategy + ì¶©ëŒ ë°œìƒ ì‹œ + + + + + Deselect All + ëª¨ë‘ ì„ íƒ í•´ì œ + + + + Match Similar + 비슷한거 찾기 + + + + Select All + ëª¨ë‘ ì„ íƒ + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + ì´ë¯¸ '%1'ì´ë¼ëŠ” ì´ë¦„ì„ ê°€ì§„ í…Œì´ë¸”ì´ ì¡´ìž¬í•˜ë©° 기존 í…Œì´ë¸”로 ë°ì´í„°ë¥¼ 가져오는 ê²ƒì€ í•„ë“œì˜ ìˆ˜ê°€ ê°™ì„ ë•Œë§Œ 가능합니다. + + + + There is already a table named '%1'. Do you want to import the data into it? + ì´ë¯¸ '%1'ë¼ëŠ” ì´ë¦„ì˜ í…Œì´ë¸”ì´ ì¡´ìž¬í•©ë‹ˆë‹¤. ë°ì´í„°ë¥¼ ì´ í…Œì´ë¸”로 가져올까요? + + + + Creating restore point failed: %1 + ë³µì› í¬ì¸íŠ¸ë¥¼ ìƒì„±í•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤: %1 + + + + Creating the table failed: %1 + í…Œì´ë¸” ìƒì„±ì— 실패했습니다: %1 + + + + importing CSV + CSV 가져오기 + + + + Could not prepare INSERT statement: %1 + INSERT ë¬¸ì„ ì¤€ë¹„í•  수 없습니다: %1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + 예기치 ì•Šì€ íŒŒì¼ì˜ ë(EOF)입니다. 올바른 따옴표를 구성했는지, íŒŒì¼ í˜•ì‹ì´ 잘못ë˜ì§€ 않았는지 확ì¸í•˜ì„¸ìš”. + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + íŒŒì¼ '%1' ê°€ì ¸ì˜¤ëŠ”ë° %2msê°€ 걸렸습니다. ì´ ì¤‘ì—서 í–‰ ê¸°ëŠ¥ì„ ì ìš©í•˜ëŠ”ë° %3msê°€ 걸렸습니다. + + + + Inserting row failed: %1 + í–‰ ì¶”ê°€ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤: %1 + + + + MainWindow + + + DB Browser for SQLite + DB Browser for SQLite + + + + toolBar1 + toolBar1 + + + + Opens the SQLCipher FAQ in a browser window + SQLCipher FAQ를 봅니다 + + + + Export one or more table(s) to a JSON file + í…Œì´ë¸”ì„ JSON 파ì¼ë¡œ 내보냅니다 + + + + Find + 찾기 + + + + Find or replace + 검색과 바꾸기 + + + + Print text from current SQL editor tab + 현재 SQL 편집기 íƒ­ì˜ í…스트 ì¸ì‡„ + + + + Print the structure of the opened database + 현재 ì—´ë ¤ 있는 ë°ì´í„°ë² ì´ìŠ¤ì˜ êµ¬ì¡° ì¸ì‡„ + + + + Un/comment block of SQL code + SQL 코드 블럭 ì£¼ì„ ì²˜ë¦¬/í•´ì œ + + + + Un/comment block + 블럭 ì£¼ì„ ì²˜ë¦¬/í•´ì œ + + + + Comment or uncomment current line or selected block of code + 현재 줄 ë˜ëŠ” ì„ íƒëœ ë¸”ëŸ­ì„ ì£¼ì„ ì²˜ë¦¬ ë˜ëŠ” 해제합니다 + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + ì„ íƒëœ ì¤„ì„ ì£¼ì„ ì²˜ë¦¬ ë˜ëŠ” 해제합니다. ì„ íƒ í•­ëª©ì´ ì—†ëŠ” 경우 현재 ì¤„ì„ ì²˜ë¦¬í•©ë‹ˆë‹¤. 모든 ë¸”ëŸ­ì€ ì²«ë²ˆì§¸ ì¤„ì„ í†µí•´ 토글 í•  수 있습니다. + + + + Ctrl+/ + + + + + Stop SQL execution + SQL 실행 중단 + + + + Stop execution + 실행 중단 + + + + Stop the currently running SQL script + 현재 실행 ì¤‘ì¸ SQL 스í¬ë¦½íЏ 중단 + + + + Execute all/selected SQL + ì „ì²´ ë˜ëŠ” ì„ íƒí•œ SQL 실행 + + + + Open an existing database file in read only mode + ì½ê¸° ì „ìš© 모드로 존재하는 ë°ì´í„°ë² ì´ìФ 파ì¼ì„ 엽니다 + + + + &File + 파ì¼(&F) + + + + &Import + 가져오기(&I) + + + + &Export + 내보내기(&E) + + + + &Edit + 편집(&E) + + + + &View + 보기(&V) + + + + &Help + ë„움ë§(&H) + + + + Too&ls + ë„구(&L) + + + + DB Toolbar + DB 툴바 + + + + Edit Database &Cell + ë°ì´í„°ë² ì´ìФ ì…€ 수정하기(&C) + + + + Error Log + ì—러 로그 + + + + This button clears the contents of the SQL logs + ì´ ë²„íŠ¼ì€ SQL 로그 ë‚´ìš©ì„ ì§€ì›ë‹ˆë‹¤ + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + ì´ íŒ¨ë„ì—서 ì‘ìš© 프로그램 ë˜ëŠ” 사용ìžê°€ 실행한 모든 SQL ëª…ë ¹ì˜ ê¸°ë¡ì„ 확ì¸í•  수 있습니다 + + + + DB Sche&ma + DB 스키마(&M) + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + ì´ê²ƒì€ 열린 ë°ì´í„°ë² ì´ìŠ¤ì˜ êµ¬ì¡°ìž…ë‹ˆë‹¤. +ì´ë¦„ ì—´ì—서 여러 개체 ì´ë¦„ì„ ëŒì–´ì„œ SQL íŽ¸ì§‘ê¸°ì— ë†“ì„ ìˆ˜ 있으며 컨í…스트 메뉴를 사용하여 ëŒì–´ì„œ ë†“ì€ ì´ë¦„ì˜ ì†ì„±ì„ 변경할 수 있습니다. +ì´ê²ƒì€ SQL ë¬¸ì„ ìž‘ì„±í•˜ëŠ”ë° ë„ì›€ì´ ë©ë‹ˆë‹¤. +스키마 ì—´ì—서 SQL ë¬¸ì„ ëŒì–´ì„œ SQL 편집기나 다른 ì‘ìš© í”„ë¡œê·¸ëž¨ì— ë†“ì„ ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. + + + + + &Remote + ì›ê²©(&R) + + + + This button executes the SQL statement present in the current editor line + ì´ ë²„íŠ¼ì€ í˜„ìž¬ 편집기 í–‰ì— ìžˆëŠ” SQL ë¬¸ì„ ì‹¤í–‰í•©ë‹ˆë‹¤ + + + + Shift+F5 + + + + + Sa&ve Project + 프로ì íЏ 저장하기(&V) + + + + User + ì‚¬ìš©ìž + + + + Application + 애플리케ì´ì…˜ + + + + &Clear + 지우기(&C) + + + + &New Database... + 새 ë°ì´í„°ë² ì´ìФ(&N)... + + + + + Create a new database file + 새 ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ìƒì„±í•©ë‹ˆë‹¤ + + + + This option is used to create a new database file. + ì´ ì˜µì…˜ì€ ìƒˆ ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ìƒì„±í•˜ë ¤ê³  í•  때 사용합니다. + + + + Ctrl+N + + + + + + &Open Database... + ë°ì´í„°ë² ì´ìФ 열기(&O)... + + + + + + + + Open an existing database file + 기존 ë°ì´í„°ë² ì´ìФ 파ì¼ì„ 엽니다 + + + + + + This option is used to open an existing database file. + ì´ ì˜µì…˜ì€ ê¸°ì¡´ ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ì—´ 때 사용합니다. + + + + Ctrl+O + + + + + &Close Database + ë°ì´í„°ë² ì´ìФ 닫기(&C) + + + + This button closes the connection to the currently open database file + ì´ ë²„íŠ¼ì€ í˜„ìž¬ ì—´ë ¤ 있는 ë°ì´í„°ë² ì´ìФ 파ì¼ì— 대한 ì—°ê²°ì„ ë‹«ìŠµë‹ˆë‹¤ + + + + + Ctrl+W + + + + + + Revert database to last saved state + 마지막 ì €ìž¥ëœ ìƒíƒœë¡œ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ë˜ëŒë¦½ë‹ˆë‹¤ + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + ì´ ì˜µì…˜ì€ í˜„ìž¬ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 마지막 ì €ìž¥ëœ ìƒíƒœë¡œ ë˜ëŒë¦´ 때 사용합니다. 저장 ì´í›„ì— ì´ë£¨ì–´ì§„ 모든 변경 ì‚¬í•­ì„ ë˜ëŒë¦½ë‹ˆë‹¤. + + + + + Write changes to the database file + 변경 ì‚¬í•­ì„ ë°ì´í„°ë² ì´ìФ 파ì¼ì— ë°˜ì˜í•©ë‹ˆë‹¤ + + + + This option is used to save changes to the database file. + ì´ ì˜µì…˜ì€ ë°ì´í„°ë² ì´ìФ 파ì¼ì— 변경 ì‚¬í•­ì„ ì €ìž¥í•˜ê¸° 위해 사용ë©ë‹ˆë‹¤. + + + + Ctrl+S + + + + + Compact the database file, removing space wasted by deleted records + ì‚­ì œëœ ë ˆì½”ë“œë¡œ 낭비ë˜ëŠ” ê³µê°„ì„ ì œê±°í•˜ì—¬ ë°ì´í„°ë² ì´ìФ íŒŒì¼ ì••ì¶• + + + + + Compact the database file, removing space wasted by deleted records. + ì‚­ì œëœ ë ˆì½”ë“œë¡œ 낭비ë˜ëŠ” ê³µê°„ì„ ì œê±°í•˜ì—¬ ë°ì´í„°ë² ì´ìФ íŒŒì¼ ì••ì¶•. + + + + E&xit + 종료(&X) + + + + Ctrl+Q + + + + + Import data from an .sql dump text file into a new or existing database. + .sql ë¤í”„ 문ìžì—´ 파ì¼ì—서 ë°ì´í„°ë¥¼ 새 ë°ì´í„°ë² ì´ìŠ¤ë‚˜ 기존 ë°ì´í„°ë² ì´ìŠ¤ë¡œ 가져옵니다. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + ì´ ì˜µì…˜ì€ .sql ë¤í”„ 문ìžì—´ 파ì¼ì—서 ë°ì´í„°ë¥¼ 새 ë°ì´í„°ë² ì´ìŠ¤ë‚˜ 기존 ë°ì´í„°ë² ì´ìŠ¤ë¡œ 가져옵니다. SQL ë¤í”„ 파ì¼ì€ MySQLì´ë‚˜ PostgreSQL 등 ëŒ€ë¶€ë¶„ì˜ ë°ì´í„°ë² ì´ìФ 엔진ì—서 ìƒì„±í•  수 있습니다. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + 마법사를 사용하여 CSV 파ì¼(쉼로 필드가 나누어진 문ìžì—´ 파ì¼)ì—서 ë°ì´í„°ë² ì´ìФ í…Œì´ë¸”로 ë°ì´í„°ë¥¼ 가져올 수 있습니다. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + 마법사를 사용하여 CSV 파ì¼(쉼표로 필드가 나누어진 문ìžì—´ 파ì¼)ì—서 ë°ì´í„°ë² ì´ìФ í…Œì´ë¸”로 ë°ì´í„°ë¥¼ 가져올 수 있습니다. CSV 파ì¼ì€ ëŒ€ë¶€ë¶„ì˜ ë°ì´í„°ë² ì´ìŠ¤ì™€ 스프레드시트 애플리케ì´ì…˜ì—서 ìƒì„±í•  수 있습니다. + + + + Export a database to a .sql dump text file. + ë°ì´í„°ë² ì´ìŠ¤ë¥¼ .sql ë¤í”„ 문ìžì—´ 파ì¼ë¡œ 내보내기. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + ì´ ì˜µì…˜ì€ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ .sql ë¤í”„ 문ìžì—´ 파ì¼ë¡œ 내보낼 수 있습니다. SQL ë¤í”„ 파ì¼ì€ MySQLê³¼ PostgreSQL 등 ëŒ€ë¶€ë¶„ì˜ ë°ì´í„°ë² ì´ìФ 엔진ì—서 ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 재ìƒì„±í•˜ê¸° 위한 모든 필요한 ë°ì´í„°ë¥¼ í¬í•¨í•˜ê³  있습니다. + + + + Export a database table as a comma separated text file. + ë°ì´í„°ë² ì´ìФ í…Œì´ë¸”ì„ CSV(쉼표로 ë¶„ë¦¬ëœ ë¬¸ìžì—´ 파ì¼)로 내보내기. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + ë°ì´í„°ë² ì´ìФ í…Œì´ë¸”ì„ CSV(쉼표로 ë¶„ë¦¬ëœ ë¬¸ìžì—´ 파ì¼)로 내보내기. 다른 ë°ì´í„°ë² ì´ìŠ¤ë‚˜ 스프레드시트 애플리케ì´ì…˜ì—서 가져와서 사용할 수 있습니다. + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + í…Œì´ë¸” ìƒì„± 마법사를 사용하여 ë°ì´í„°ë² ì´ìФì—서 새 í…Œì´ë¸”ì„ ìœ„í•œ ì´ë¦„ê³¼ 필드를 ì •ì˜í•  수 있습니다 + + + + + Delete Table + í…Œì´ë¸” 삭제하기 + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + í…Œì´ë¸” ì‚­ì œ 마법사를 사용하여 ì„ íƒí•œ ë°ì´í„°ë² ì´ìФ í…Œì´ë¸”ì„ ì‚­ì œí•  수 있습니다. + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + ì¸ë±ìФ ìƒì„± 마법사를 사용하여 기존 ë°ì´í„°ë² ì´ìФ í…Œì´ë¸”ì— ìƒˆ ì¸ë±ìŠ¤ë¥¼ ì •ì˜í•  수 있습니다. + + + + &Preferences... + 환경설정(&P)... + + + + + Open the preferences window. + 환경설정 ì°½ì„ ì—½ë‹ˆë‹¤. + + + + &DB Toolbar + DB 툴바(&D) + + + + Shows or hides the Database toolbar. + ë°ì´í„°ë² ì´ìФ 툴바를 ë³´ì´ê±°ë‚˜ 숨ê¹ë‹ˆë‹¤. + + + + Shift+F1 + + + + + &Recently opened + 최근 ì—´ì—ˆë˜ íŒŒì¼ë“¤(&R) + + + + Ctrl+T + + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + ì´ê²ƒì€ 열려있는 ë°ì´í„°ë² ì´ìŠ¤ì˜ êµ¬ì¡°ìž…ë‹ˆë‹¤. +개체 í–‰ì—서 SQL ë¬¸ì„ ëŒì–´ì„œ 다른 ì‘ìš© 프로그램ì´ë‚˜ 'DB Browser for SQLite'ì˜ ë‹¤ë¥¸ ì¸ìŠ¤í„´ìŠ¤ì— ë†“ì„ ìˆ˜ 있습니다. + + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + 경고: ì´ pragma는 ì½ê¸° ì „ìš©ì´ ì•„ë‹ˆë©° ì´ ê°’ì€ ì¶”ì¸¡ëœ ê°’ìž…ë‹ˆë‹¤. pragma를 작성하면 SQLiteì—서 제공하는 ìž¬ì •ì˜ ëœ LIKE를 ë®ì–´ 쓸 수 있습니다. + + + + &Recent Files + 최근 íŒŒì¼ ì—´ê¸°(&R) + + + + + Ctrl+F4 + + + + + Compact &Database... + ë°ì´í„°ë² ì´ìФ ì••ì¶•(&D)... + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + 기존 í…Œì´ë¸”ì˜ ì´ë¦„ì„ ë°”ê¿€ 수 있는 í…Œì´ë¸” 수정 마법사를 엽니다. í…Œì´ë¸”ì—서 필드를 추가 ë˜ëŠ” 삭제하고 필드 ì´ë¦„ ë° ìœ í˜•ì„ ìˆ˜ì •í•  ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + ì´ ë²„íŠ¼ì€ í˜„ìž¬ ì„ íƒë˜ì–´ 있는 SQL ëª…ë ¹ë¬¸ì„ ì‹¤í–‰í•©ë‹ˆë‹¤. 만약 ì„ íƒ í•­ëª©ì´ ì—†ìœ¼ë©´ 모든 SQL ëª…ë ¹ë¬¸ì´ ì‹¤í–‰ë©ë‹ˆë‹¤. + + + + &Load Extension... + 확장ë„구 불러오기(&L)... + + + + Execute line + 줄 실행 + + + + &Wiki + 위키(&W) + + + + F1 + + + + + Bug &Report... + 버그 ë³´ê³ (&R)... + + + + Feature Re&quest... + 기능 제안(&Q)... + + + + Web&site + 웹 사ì´íЏ(&S) + + + + &Donate on Patreon... + 후ì›í•˜ê¸°(&D)... + + + + Open &Project... + 프로ì íЏ 열기(&P)... + + + + &Attach Database... + ë°ì´í„°ë² ì´ìФ ì—°ê²°(&A)... + + + + + Add another database file to the current database connection + 현재 ë°ì´í„°ë² ì´ìФ ì—°ê²°ì— ë‹¤ë¥¸ ë°ì´í„°ë² ì´ìФ ì—°ê²°ì„ ì¶”ê°€í•©ë‹ˆë‹¤ + + + + This button lets you add another database file to the current database connection + ì´ ë²„íŠ¼ì„ ì‚¬ìš©í•˜ë©´ 현재 ë°ì´í„°ë² ì´ìФ ì—°ê²°ì— ë‹¤ë¥¸ ë°ì´í„°ë² ì´ìФ 파ì¼ì„ 추가할 수 있습니다 + + + + &Set Encryption... + 암호화 설정(&S)... + + + + SQLCipher &FAQ + SQLCipher FAQ(&F) + + + + Table(&s) to JSON... + í…Œì´ë¸”ì„ JSON으로 내보내기(&S)... + + + + Browse Table + í…Œì´ë¸” íƒìƒ‰ + + + + Open Data&base Read Only... + ì½ê¸° 전용으로 ë°ì´í„°ë² ì´ìФ 열기(&B)... + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + ë°ì´í„°ë² ì´ìФ 구조(&D) + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + ë°ì´í„° íƒìƒ‰ (&B) + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + Pragma 수정(&R) + + + + Temp Store + + + + + Secure Delete + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Secure Delete + + + + Case Sensitive Like + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Case Sensitive Like + + + + Journal Mode + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Journal Mode + + + + Journal Size Limit + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Journal Size Limit + + + + Recursive Triggers + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Resursive Triggers + + + + Page Size + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Page Size + + + + Foreign Keys + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Foreign Keys + + + + Auto Vacuum + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Auto Vaccum + + + + Max Page Count + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Max Page Count + + + + Checkpoint Full FSYNC + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Checkpoint FULL FSYNC + + + + + Off + + + + + + Normal + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Normal + + + + + Full + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Full + + + + Default + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + 기본값 + + + + File + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + File + + + + + Memory + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Memory + + + + Delete + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Delete + + + + Truncate + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Truncate + + + + Persist + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Persist + + + + WAL + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + WAL + + + + Exclusive + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Exclusive + + + + Automatic Index + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Automatic Index + + + + Ignore Check Constraints + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Ignore Check Constraints + + + + Full FSYNC + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Full FSYNC + + + + WAL Auto Checkpoint + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + WAL Auto Checkpoint + + + + User Version + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + User Version + + + + Synchronous + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Synchronous + + + + None + 사용하지 ì•ŠìŒ + + + + Incremental + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Incremental + + + + Locking Mode + I didn't translate it because I think it's better for users to understand it without it. If you disagree, please open a discussion. + Locking Mode + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + SQL 실행(&E) + + + + &New Database + 새 ë°ì´í„°ë² ì´ìФ(&N) + + + + &Undo + 실행 취소(&U) + + + + + Undo last change to the database + ë°ì´í„°ë² ì´ìŠ¤ì— ëŒ€í•œ 마지막 변경 사항 실행 취소합니다 + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + ì´ ìž‘ì—…ì€ ë°ì´í„°ë² ì´ìФ 브ë¼ìš°ì € ë˜ëŠ” SQL 실행ì—서 ë°ì´í„°ë² ì´ìŠ¤ì— ë§ˆì§€ë§‰ìœ¼ë¡œ 수행한 변경 ì‚¬í•­ì„ ì‹¤í–‰ 취소합니다. 다시 실행할 수 없습니다. + + + + New &tab + 새 탭(&T) + + + + Open SQL file(s) + SQL íŒŒì¼ ì—´ê¸° + + + + This button opens files containing SQL statements and loads them in new editor tabs + ì´ ë²„íŠ¼ì€ SQL ë¬¸ì´ í¬í•¨ëœ 파ì¼ì„ ì—´ê³  새 편집기 íƒ­ì— ë¡œë“œí•©ë‹ˆë‹¤ + + + + Ctrl+Shift+T + + + + + &Save Project + 프로ì íЏ 저장하기(&S) + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + ì´ ë²„íŠ¼ì„ ì‚¬ìš©í•˜ë©´ 열린 DB와 ê´€ë ¨ëœ ëª¨ë“  ì„¤ì •ì„ DB Browser for SQLite 프로ì íЏ 파ì¼ë¡œ 저장할 수 있습니다 + + + + Open &Project + 프로ì íЏ 열기(&P) + + + + This button lets you open a DB Browser for SQLite project file + ì´ ë²„íŠ¼ì„ ì‚¬ìš©í•˜ë©´ DB Browser for SQLite 프로ì íЏ 파ì¼ì„ ì—´ 수 있습니다 + + + + Ctrl+Shift+O + + + + + Save results + ê²°ê³¼ 저장 + + + + Save the results view + ê²°ê³¼ ë·° 저장 + + + + This button lets you save the results of the last executed query + ì´ ë²„íŠ¼ì€ ë§ˆì§€ë§‰ìœ¼ë¡œ 실행한 ì¿¼ë¦¬ì˜ ê²°ê³¼ê°’ì„ ì €ìž¥í•©ë‹ˆë‹¤ + + + + + Find text in SQL editor + SQL 편집기ì—서 í…스트 찾기 + + + + This button opens the search bar of the editor + ì´ ë²„íŠ¼ì€ íŽ¸ì§‘ê¸°ì˜ ê²€ìƒ‰ì°½ì„ ì—½ë‹ˆë‹¤ + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + SQL 편집기ì—서 í…스트 찾아 바꾸기 + + + + This button opens the find/replace dialog for the current editor tab + ì´ ë²„íŠ¼ì€ í˜„ìž¬ ì—´ë ¤ 있는 íŽ¸ì§‘ê¸°ì˜ ì°¾ê¸° 바꾸기 대화ìƒìžë¥¼ 엽니다 + + + + Ctrl+H + + + + + Export to &CSV + CSV로 내보내기(&C) + + + + Export to &JSON + &JSON으로 내보내기 + + + + Save as &view + 뷰로 저장하기(&V) + + + + Save as view + 다른 ì´ë¦„ì˜ ë·°ë¡œ 저장하기 + + + + Shows or hides the Project toolbar. + 프로ì íЏ 툴바를 표시하거나 숨ê¹ë‹ˆë‹¤. + + + + Extra DB Toolbar + 확장 DB 툴바 + + + + &Open Database + ë°ì´í„°ë² ì´ìФ 열기(&O) + + + + New In-&Memory Database + In-Memory ë°ì´í„°ë² ì´ìФ ìƒì„±(&M) + + + + Drag && Drop SELECT Query + 드래그 앤 드롭 SELECT 쿼리 + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + ë™ì¼í•œ í…Œì´ë¸” ë˜ëŠ” ë‹¨ì¼ í…Œì´ë¸”ì—서 필드를 드래그할 때 SELECT 쿼리를 íŽ¸ì§‘ê¸°ì— ë“œë¡­í•©ë‹ˆë‹¤ + + + + Drag && Drop Qualified Names + ì •ê·œí™”ëœ ì´ë¦„ì„ ëŒì–´ì„œ 놓기 + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + 개체를 ëŒì–´ì„œ íŽ¸ì§‘ê¸°ì— ë†“ì„ ë•Œ ì •ê·œí™”ëœ ì´ë¦„(예: "Table", "Field")ì„ ì‚¬ìš©í•©ë‹ˆë‹¤ + + + + Drag && Drop Enquoted Names + ì¸ìš©ëœ ì´ë¦„ì„ ëŒì–´ì„œ 놓기 + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + 개체를 ëŒì–´ì„œ íŽ¸ì§‘ê¸°ì— ë†“ì„ ë•Œ ì´ìŠ¤ì¼€ì´í”„ëœ ì‹ë³„ìž(예: "Table1")ì„ ì‚¬ìš©í•©ë‹ˆë‹¤ + + + + &Integrity Check + 무결성 검사(&I) + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + 열린 ë°ì´í„°ë² ì´ìŠ¤ì— ëŒ€í•´ integrity_check pragma를 실행하고 SQL 실행 íƒ­ì— ê²°ê³¼ë¥¼ 반환합니다. ì´ pragma는 ì „ì²´ ë°ì´í„°ë² ì´ìŠ¤ì˜ ë¬´ê²°ì„± 검사를 수행합니다. + + + + &Foreign-Key Check + 외래키 검사(&F) + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + 열린 ë°ì´í„°ë² ì´ìŠ¤ì— ëŒ€í•´ foreign_key_check pragma를 실행하고 SQL 실행 íƒ­ì— ê²°ê³¼ë¥¼ 반환합니다 + + + + &Quick Integrity Check + 빠른 무결성 검사(&Q) + + + + Run a quick integrity check over the open DB + 열린 ë°ì´í„°ë² ì´ìФ 대해 빠른 무결성 검사 실행 + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + 열린 ë°ì´í„°ë² ì´ìŠ¤ì— ëŒ€í•´ quick_check pragma를 실행하고 SQL 실행 íƒ­ì— ê²°ê³¼ë¥¼ 반환합니다. ì´ ëª…ë ¹ì€ ëŒ€ë¶€ë¶„ì˜ PRAGMA integrity_check 검사를 수행하지만 훨씬 빠르게 실행ë©ë‹ˆë‹¤. + + + + &Optimize + 최ì í™”(&O) + + + + Attempt to optimize the database + ë°ì´í„°ë² ì´ìФ 최ì í™” + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + 열린 ë°ì´í„°ë² ì´ìŠ¤ì— ëŒ€í•´ 최ì í™” pragma를 실행합니다. ì´ pragma는 향후 ì¿¼ë¦¬ì˜ ì„±ëŠ¥ì„ í–¥ìƒì‹œí‚¤ëŠ” 최ì í™”를 수행할 수 있습니다. + + + + + Print + ì¸ì‡„하기 + + + + &Save Project As... + 다른 ì´ë¦„으로 프로ì íЏ 저장(&S)... + + + + + + Save the project in a file selected in a dialog + 대화ìƒìžì—서 ì„ íƒí•œ 파ì¼ì— 프로ì íЏ 저장 + + + + Save A&ll + ëª¨ë‘ ì €ìž¥(&l) + + + + + + Save DB file, project file and opened SQL files + DB 파ì¼, 프로ì íЏ íŒŒì¼ ë° ì—´ë¦° SQL íŒŒì¼ ì €ìž¥ + + + + Ctrl+Shift+S + + + + + Close Pro&ject + 프로ì íЏ 닫기(&J) + + + + + Close project and database files and return to the initial state + 프로ì íЏ ë° í”„ë¡œì íЏ 파ì¼ì„ ë‹«ê³  초기 ìƒíƒœë¡œ ëŒì•„갑니다 + + + + + Ctrl+Shift+W + + + + + Table from CSV data in Clipboard... + í´ë¦½ë³´ë“œì— ì €ìž¥ëœ CSV ë°ì´í„°ì—서 í…Œì´ë¸” 가져오기... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + 현재 í´ë¦½ë³´ë“œì— ì €ìž¥ëœ ë‚´ìš©ì„ CSV파ì¼ë¡œ 간주하여 파ì¼ë¡œë¶€í„° CSVë°ì´í„°ë¥¼ 불러올때 사용ë˜ëŠ” 불러오기 마법사를 엽니다. + + + + Show &Row Counts + í–‰ 개수 보기 (&R) + + + + This shows the number of rows for each table and view in the database. + ë°ì´í„°ë² ì´ìŠ¤ì˜ ê° í…Œì´ë¸”ê³¼ ë·°ì— ì €ìž¥ëœ í–‰ì˜ ê°œìˆ˜ë¥¼ 표시합니다. + + + + Save Database &As... + 다른 ì´ë¦„으로 저장하기...(&A) + + + + Save the current database as a different file + 현재 ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 다른 파ì¼ë¡œ 저장하기 + + + + Refresh + 새로고침 + + + + Reload the database structure + ë°ì´í„°ë² ì´ìФ 구조를 다시 로드합니다 + + + + Ctrl+Shift+F4 + + + + + + Detach Database + ë°ì´í„°ë² ì´ìФ 분리 + + + + + Detach database file attached to the current database connection + 현재 ë°ì´í„°ë² ì´ìФ ì—°ê²°ì— ì—°ê²°ë˜ì–´ 있는 ë°ì´í„°ë² ì´ìФ íŒŒì¼ ë¶„ë¦¬ + + + + Open a dialog for printing the text in the current SQL editor tab + 현재 SQL 편집기 탭ì—서 í…스트를 ì¸ì‡„하기 위한 대화ìƒìžë¥¼ 엽니다 + + + + Open a dialog for printing the structure of the opened database + 열린 ë°ì´í„°ë² ì´ìŠ¤ì˜ êµ¬ì¡°ë¥¼ ì¸ì‡„하기 위한 대화ìƒìžë¥¼ 엽니다 + + + + SQL &Log + SQL 로그(&L) + + + + Show S&QL submitted by + ~ì— ì˜í•´ ì‹¤í–‰ëœ SQL 보기(&Q) + + + + &Plot + 플롯(&P) + + + + + Project Toolbar + 프로ì íЏ 툴바 + + + + Extra DB toolbar + 확장 DB 툴바 + + + + + + Close the current database file + 현재 ë°ì´í„°ë² ì´ìФ íŒŒì¼ ë‹«ê¸° + + + + &Revert Changes + 변경사항 취소하기(&R) + + + + &Write Changes + 변경사항 저장하기(&W) + + + + &Database from SQL file... + SQL 파ì¼ë¡œë¶€í„° ë°ì´í„°ë² ì´ìФ 가져오기(&D)... + + + + &Table from CSV file... + CSV 파ì¼ì—서 í…Œì´ë¸” 가져오기(&T)... + + + + &Database to SQL file... + ë°ì´í„°ë² ì´ìŠ¤ë¥¼ SQL로 내보내기(&D)... + + + + &Table(s) as CSV file... + í…Œì´ë¸”ì„ CSV 파ì¼ë¡œ 내보내기(&T)... + + + + &Create Table... + í…Œì´ë¸” ìƒì„±í•˜ê¸°(&C)... + + + + &Delete Table... + í…Œì´ë¸” 삭제하기(&D)... + + + + &Modify Table... + í…Œì´ë¸” 수정하기(&M)... + + + + Create &Index... + ì¸ë±ìФ ìƒì„±í•˜ê¸°(&I)... + + + + W&hat's This? + ì´ê±´ 무엇ì¸ê°€ìš”?(&H) + + + + &About + ì •ë³´(&A) + + + + This button opens a new tab for the SQL editor + ì´ ë²„íŠ¼ì€ SQL íŽ¸ì§‘ê¸°ì˜ ìƒˆë¡œìš´ íƒ­ì„ ì—½ë‹ˆë‹¤ + + + + &Execute SQL + SQL 실행하기(&E) + + + + + + Save SQL file + SQL íŒŒì¼ ì €ìž¥í•˜ê¸° + + + + + Execute current line + 현재 í–‰ 실행하기 + + + + Ctrl+E + + + + + Export as CSV file + CSV 파ì¼ë¡œ 내보내기 + + + + Export table as comma separated values file + í…Œì´ë¸”ì„ CSV 파ì¼ë¡œ 내보내기 + + + + + Save the current session to a file + 현재 ì„¸ì…˜ì„ íŒŒì¼ë¡œ 저장하기 + + + + + Load a working session from a file + 파ì¼ì—서 작업 세션 불러오기 + + + + + Save SQL file as + SQL íŒŒì¼ ë‹¤ë¦„ ì´ë¦„으로 저장하기 + + + + This button saves the content of the current SQL editor tab to a file + ì´ ë²„íŠ¼ì€ í˜„ìž¬ SQL íŽ¸ì§‘ê¸°ì˜ ë‚´ìš©ì„ íŒŒì¼ë¡œ 저장합니다 + + + + &Browse Table + í…Œì´ë¸” 보기(&B) + + + + Copy Create statement + ìƒì„± 구문 복사하기 + + + + Copy the CREATE statement of the item to the clipboard + í•­ëª©ì˜ ìƒì„± êµ¬ë¬¸ì„ í´ë¦½ë³´ë“œì— 복사합니다 + + + + Ctrl+Return + + + + + Ctrl+L + + + + + + Ctrl+P + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Encrypted + ì•”í˜¸í™”ë¨ + + + + Read only + ì½ê¸° ì „ìš© + + + + Database file is read only. Editing the database is disabled. + ë°ì´í„°ë² ì´ìФ 파ì¼ì´ ì½ê¸° 전용입니다. ë°ì´í„°ë² ì´ìФ 수정 ê¸°ëŠ¥ì´ ë¹„í™œì„±í™”ë©ë‹ˆë‹¤. + + + + Database encoding + ë°ì´í„°ë² ì´ìФ ì¸ì½”딩 + + + + Database is encrypted using SQLCipher + ë°ì´í„°ë² ì´ìŠ¤ëŠ” SQLCipher를 통해 암호화ë©ë‹ˆë‹¤ + + + + + Choose a database file + ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” + + + + + + Choose a filename to save under + 저장하려는 파ì¼ëª…ì„ ì„ íƒí•˜ì„¸ìš” + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ì €ìž¥í•˜ë˜ ì¤‘ ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. ì´ ë§ì€ 모든 ë³€ê²½ì‚¬í•­ë“¤ì´ ë°ì´í„°ë² ì´ìŠ¤ì— ì €ìž¥ë˜ì§€ 못했ìŒì„ ì˜ë¯¸í•©ë‹ˆë‹¤. 다ìŒì— 나오는 ì—러를 먼저 해결하세요. +%1 + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + ì •ë§ë¡œ ë°ì´í„°ë² ì´ìФ íŒŒì¼ '%1'ì˜ ëª¨ë“  변경 ì‚¬í•­ì„ ë§ˆì§€ë§‰ ì €ìž¥ëœ ìƒíƒœë¡œ ë˜ëŒë¦½ë‹ˆê¹Œ? + + + + Choose a file to import + 가져올 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (ì½ê¸° ì „ìš©) + + + + Open Database or Project + ë°ì´í„°ë² ì´ìФ ë˜ëŠ” 프로ì íЏ 열기 + + + + Attach Database... + ë°ì´í„°ë² ì´ìФ ì—°ê²°... + + + + Import CSV file(s)... + CSV íŒŒì¼ ê°€ì ¸ì˜¤ê¸°... + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + '%1' 프로ì íЏ 파ì¼ì— SQL íƒ­ì„ ì¶”ê°€í•˜ê¸° 위해 ë³€ê²½ì‚¬í•­ì„ ì €ìž¥í•˜ì‹œê² ìŠµë‹ˆê¹Œ? + + + + Text files(*.sql *.txt);;All files(*) + 문ìžì—´ 파ì¼(*.sql *.txt);;모든 파ì¼(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + ë°ì´í„°ë¥¼ 가져와서 새 ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ìƒì„±í•˜ê³  ì‹¶ì€ì‹ ê°€ìš”? +아니ë¼ë©´ SQL 파ì¼ì˜ ë°ì´í„°ë¥¼ 현재 ë°ì´í„°ë² ì´ìŠ¤ë¡œ 가져오기를 í•  것입니다. + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + ì•„ì§ SQL ëª…ë ¹ë¬¸ì´ ì‹¤í–‰ë˜ëŠ” 중입니다. ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 닫으면 ì‹¤í–‰ì´ ì¤‘ë‹¨ë˜ì–´ ë°ì´í„°ë² ì´ìŠ¤ê°€ ì¼ê´€ì„±ì´ 없어질 수 있습니다. ì •ë§ë¡œ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 닫으시겠습니까? + + + + Do you want to save the changes made to the project file '%1'? + %1 ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ìƒì„±í•˜ê¸° 위해 ë³€ê²½ì‚¬í•­ì„ ì €ìž¥í•˜ì‹œê² ìŠµë‹ˆê¹Œ? + + + + File %1 already exists. Please choose a different name. + íŒŒì¼ %1ì´ ì´ë¯¸ 존재합니다. 다른 파ì¼ëª…ì„ ì„ íƒí•˜ì„¸ìš”. + + + + Error importing data: %1 + ë°ì´í„° 가져오기 ì—러: %1 + + + + Import completed. + 가져오기가 완료ë˜ì—ˆìŠµë‹ˆë‹¤. + + + + Delete View + ë·° 삭제하기 + + + + Modify View + ë·° 수정하기 + + + + Delete Trigger + 트리거 삭제하기 + + + + Modify Trigger + 트리거 수정하기 + + + + Delete Index + ì¸ë±ìФ 삭제하기 + + + + Modify Index + ì¸ë±ìФ 수정하기 + + + + Modify Table + í…Œì´ë¸” 수정하기 + + + + Do you want to save the changes made to SQL tabs in a new project file? + 새 프로ì íЏ 파ì¼ì— SQL íƒ­ì„ ì¶”ê°€í•˜ê¸° 위해 ë³€ê²½ì‚¬í•­ì„ ì €ìž¥í•˜ì‹œê² ìŠµë‹ˆê¹Œ? + + + + Do you want to save the changes made to the SQL file %1? + %1 SQL 파ì¼ì„ ìƒì„±í•˜ê¸° 위해 ë³€ê²½ì‚¬í•­ì„ ì €ìž¥í•˜ì‹œê² ìŠµë‹ˆê¹Œ? + + + + Could not find resource file: %1 + 리소스 파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다: %1 + + + + Choose a project file to open + 불러올 프로ì íЏ 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” + + + + Could not open project file for writing. +Reason: %1 + 쓰기 모드로 프로ì íЏ 파ì¼ì„ ì—´ 수 없습니다. +ì›ì¸: %1 + + + + Busy (%1) + 사용 중 (%1) + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + PRAGMA ì„¤ì •ì„ ë³€ê²½í•˜ë ¤ë©´ ì—¬ëŸ¬ë¶„ì˜ í˜„ìž¬ íŠ¸ëžœìž­ì…˜ì„ ì»¤ë°‹í•´ì•¼í•©ë‹ˆë‹¤. +ë™ì˜í•˜ì‹­ë‹ˆê¹Œ? + + + + Ctrl+Tab + + + + + Ctrl+Shift+Tab + + + + + Clear List + ëª©ë¡ ì§€ìš°ê¸° + + + + Window Layout + ì°½ ë ˆì´ì•„웃 + + + + Reset Window Layout + ì°½ ë ˆì´ì•„웃 초기화 + + + + Simplify Window Layout + ì°½ ë ˆì´ì•„웃 단순화 + + + + Alt+Shift+0 + + + + + Dock Windows at Bottom + í•˜ë‹¨ì— ì°½ ê³ ì • + + + + Dock Windows at Left Side + ì¢Œì¸¡ì— ì°½ ê³ ì • + + + + Dock Windows at Top + ìƒë‹¨ì— ì°½ ê³ ì • + + + + The database is currently busy. + ì´ ë°ì´í„°ë² ì´ìŠ¤ëŠ” 현재 사용 중입니다. + + + + Click here to interrupt the currently running query. + 여기를 눌러 현재 실행 ì¤‘ì¸ ì¿¼ë¦¬ë¥¼ ê°•ì œ 중단합니다. + + + + Alt+Shift+W + + + + + Could not open database file. +Reason: %1 + ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ì—´ 수 없습니다. +ì›ì¸: %1 + + + + In-Memory database + In-Memory ë°ì´í„°ë² ì´ìФ + + + + Choose a database file to save under + 저장하려는 파ì¼ëª…ì„ ì„ íƒí•˜ì„¸ìš” + + + + Error while saving the database to the new file. + ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 새 파ì¼ì— 저장할 때 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + ì •ë§ë¡œ í…Œì´ë¸” '%1'ì„ ì‚­ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ? +í…Œì´ë¸”ì˜ ëª¨ë“  ë°ì´í„°ê°€ ì‚­ì œë©ë‹ˆë‹¤. + + + + Are you sure you want to delete the view '%1'? + ì •ë§ë¡œ '%1' 뷰를 삭제할까요? + + + + Are you sure you want to delete the trigger '%1'? + ì •ë§ë¡œ '%1' 트리거를 삭제할까요? + + + + Are you sure you want to delete the index '%1'? + ì •ë§ë¡œ '%1' ì¸ë±ìŠ¤ë¥¼ 삭제할까요? + + + + Error: could not delete the table. + ì—러: í…Œì´ë¸”ì„ ì‚­ì œí•  수 없습니다. + + + + Error: could not delete the view. + ì—러: 뷰를 삭제할 수 없습니다. + + + + Error: could not delete the trigger. + ì—러: 트리거를 삭제할 수 없습니다. + + + + Error: could not delete the index. + ì—러: ì¸ë±ìŠ¤ë¥¼ 삭제할 수 없습니다. + + + + Message from database engine: +%1 + ë°ì´í„°ë² ì´ìФ 엔진 메시지: +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + 'pending'ì˜ ëœ»ì´ ë³´ë¥˜ìž…ë‹ˆë‹¤ë§Œ, 여기서는 작업 중ì´ë˜ì´ ë” ë§žë‹¤ê³  íŒë‹¨í–ˆìŠµë‹ˆë‹¤. + í…Œì´ë¸”ì„ íŽ¸ì§‘í•˜ë ¤ë©´ 작업 중ì´ë˜ 모든 변경 ì‚¬í•­ì„ ì €ìž¥í•´ì•¼í•©ë‹ˆë‹¤. +ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 저장하시겠습니까? + + + + Edit View %1 + ë·° 편집 %1 + + + + Edit Trigger %1 + 트리거 편집 %1 + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + ì´ë¯¸ SQL ëª…ë ¹ë¬¸ì„ ì‹¤í–‰í•˜ì˜€ìŠµë‹ˆë‹¤. 현재 ëª…ë ¹ë¬¸ì„ ëŒ€ì‹  실행하기 위해 기존 ì‹¤í–‰ì„ ì¤‘ë‹¨í•˜ì‹œê² ìŠµë‹ˆê¹Œ? ì´ë¡œ ì¸í•´ ë°ì´í„°ë² ì´ìŠ¤ê°€ ì¼ê´€ì„±ì´ 없는 ìƒíƒœê°€ ë  ìˆ˜ 있습니다. + + + + -- EXECUTING SELECTION IN '%1' +-- + -- '%1ì˜ ì„ íƒ í•­ëª© 실행 +-- + + + + -- EXECUTING LINE IN '%1' +-- + --'%1'ì—서 ë¼ì¸ 실행 중 +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- '%1'로부터 ì „ì²´ 실행 +-- + + + + + At line %1: + %1번째 줄: + + + + Result: %1 + ê²°ê³¼: %1 + + + + Result: %2 + ê²°ê³¼: %2 + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + PRAGMA ê°’ì„ ì§€ì •í•˜ì§€ 않으면 현재 íŠ¸ëžœìž­ì…˜ì— DB íŒŒì¼ ì²­ì†Œ 작업(Vacuum)ì´ ì»¤ë°‹ë©ë‹ˆë‹¤. 진행할까요? + + + + Opened '%1' in read-only mode from recent file list + 최근 íŒŒì¼ ëª©ë¡ì—서 ì½ê¸° ì „ìš© 모드로 '%1'ì„(를) 열었습니다 + + + + Opened '%1' from recent file list + 최근 íŒŒì¼ ëª©ë¡ì—서 '%1'ì„(를) 열었습니다 + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + ë“œë¡­ëœ íŒŒì¼ì— ì ìš©í•  ìž‘ì—…ì„ ì„ íƒí•©ë‹ˆë‹¤. <br/>참고: '가져오기'ë§Œ ë‘ ê°œ ì´ìƒì˜ 파ì¼ì„ 처리합니다. + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + %1 íƒ­ì˜ ë¬¸ì´ ì—¬ì „ížˆ 실행 중입니다. íƒ­ì„ ë‹«ìœ¼ë©´ ì‹¤í–‰ì´ ì¤‘ë‹¨ë©ë‹ˆë‹¤. ì´ë¡œ ì¸í•´ ë°ì´í„°ë² ì´ìŠ¤ê°€ ì¼ê´€ì„±ì´ 없는 ìƒíƒœê°€ ë  ìˆ˜ 있습니다. ì •ë§ë¡œ íƒ­ì„ ë‹«ìœ¼ì‹œê² ìŠµë‹ˆê¹Œ? + + + + DB file '%1' could not be opened + DB íŒŒì¼ '%1'ì„(를) ì—´ 수 없습니다 + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + ì´ í”„ë¡œì íЏ 파ì¼ì€ DB Browser for SQLite 버전 3.10 ì´í•˜ë¥¼ 사용하여 ìƒì„±ë˜ì—ˆê¸° ë•Œë¬¸ì— ì´ì „ íŒŒì¼ í˜•ì‹ì„ 사용하고 있습니다. ì´ íŒŒì¼ í˜•ì‹ì„ 로드하는 ê²ƒì€ ë” ì´ìƒ 완전히 ì§€ì›ë˜ì§€ 않습니다. 완벽하게 로드하려면 DB Browser for SQLite 버전 3.12를 사용하여 새 íŒŒì¼ í˜•ì‹ìœ¼ë¡œ 변환하세요. + + + + Table '%1' not found; settings ignored + í…Œì´ë¸” '%1'ì„(를) ì°¾ì„ ìˆ˜ 없습니다. ì„¤ì •ì´ ë¬´ì‹œë©ë‹ˆë‹¤ + + + + -- Reference to file "%1" (not supported by this version) -- + -- "%1" 파ì¼ì— 대한 참조(ì´ ë²„ì „ì—서는 ì§€ì›ë˜ì§€ 않ìŒ) -- + + + + Yes. Don't ask again + 예. 다시 묻지 않습니다 + + + + This action will open a new SQL tab with the following statements for you to edit and run: + ì´ ìž‘ì—…ì„ ìˆ˜í–‰í•˜ë©´ 편집하거나 실행할 수 있는 ë‹¤ìŒ ëª…ë ¹ë¬¸ì´ í¬í•¨ëœ 새 SQL íƒ­ì´ ì—´ë¦½ë‹ˆë‹¤: + + + + Rename Tab + 탭 ì´ë¦„ 변경 + + + + Duplicate Tab + 탭 복제 + + + + Close Tab + 탭 닫기 + + + + Opening '%1'... + '%1' 여는 중... + + + + There was an error opening '%1'... + '%1'ì„ ì—¬ëŠ” 중 ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤... + + + + Value is not a valid URL or filename: %1 + 올바른 URL ë˜ëŠ” íŒŒì¼ ì´ë¦„ì´ ì•„ë‹™ë‹ˆë‹¤: %1 + + + + %1 rows returned in %2ms + %2msì˜ ì‹œê°„ì´ ê±¸ë ¤ì„œ %1 í–‰ì´ ë°˜í™˜ë˜ì—ˆìŠµë‹ˆë‹¤ + + + + Automatically load the last opened DB file at startup + 시작 시 마지막으로 ì—° DB íŒŒì¼ ìžë™ìœ¼ë¡œ 불러오기 + + + + Ctrl+0 + + + + + Choose text files + í…스트 íŒŒì¼ ì„ íƒ + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + 가져오기가 완료ë˜ì—ˆìŠµë‹ˆë‹¤. ì¼ë¶€ 외래 í‚¤ì˜ ì œì•½ ì¡°ê±´ì´ ìœ„ë°˜ë˜ì—ˆìŠµë‹ˆë‹¤. 저장 하기 ì „ì— ìˆ˜ì •í•˜ì‹­ì‹œì˜¤. + + + + Select SQL file to open + ì—´ SQL 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” + + + + Select file name + íŒŒì¼ ì´ë¦„ì„ ì„ íƒí•˜ì„¸ìš” + + + + Select extension file + íŒŒì¼ í™•ìž¥ìžë¥¼ ì„ íƒí•˜ì„¸ìš” + + + + Extension successfully loaded. + í™•ìž¥ê¸°ëŠ¥ì„ ì„±ê³µì ìœ¼ë¡œ 불러왔습니다. + + + + Error loading extension: %1 + 확장기능 불러오기 ì—러: %1 + + + + + Don't show again + 다시 ë³´ì§€ 않기 + + + + New version available. + ì´ìš© 가능한 새 ë²„ì „ì´ ìžˆìŠµë‹ˆë‹¤. + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + ì´ìš© 가능한 새 ë²„ì „ì´ ìžˆìŠµë‹ˆë‹¤ (%1.%2.%3).<br/><br/><a href='%4'>%4</a>ì—서 다운로드하세요. + + + + Project saved to file '%1' + '%1' 파ì¼ë¡œ 프로ì íŠ¸ê°€ 저장ë˜ì—ˆìŠµë‹ˆë‹¤ + + + + Collation needed! Proceed? + 콜레ì´ì…˜ì´ 필요합니다! 진행할까요? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + ì´ ë°ì´í„°ë² ì´ìŠ¤ì˜ í…Œì´ë¸”ì€ ì´ ì• í”Œë¦¬ì¼€ì´ì…˜ì—서 잘 알지 못하는 특별한 함수 '%1'ê°€ 필요합니다. +ì´ëŒ€ë¡œ ê³„ì† ì§„í–‰í•  수는 있습니다만 ì—¬ëŸ¬ë¶„ì˜ ë°ì´í„°ë² ì´ìŠ¤ì— ë‚˜ìœ ì˜í–¥ì´ ê°ˆ ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. +ë°±ì—…ì„ ìƒì„±í•˜ì„¸ìš”! + + + + creating collation + 콜레ì´ì…˜ ìƒì„± + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + SQL íƒ­ì˜ ìƒˆ ì´ë¦„ì„ ì„¤ì •í•˜ì„¸ìš”. '&&' 문ìžë¥¼ 사용하여 다ìŒì— ë”°ë¼ì˜¤ëŠ” 문ìžë¥¼ 키보드 단축키로서 사용할 수 있습니다. + + + + Please specify the view name + ë·° ì´ë¦„ì„ ì§€ì •í•´ì£¼ì„¸ìš” + + + + There is already an object with that name. Please choose a different name. + ì´ë¯¸ ê°™ì€ ì´ë¦„ì˜ ê°ì²´ê°€ 존재합니다. 다른 ì´ë¦„ì„ ê³ ë¥´ì„¸ìš”. + + + + View successfully created. + ë·°ê°€ 성공ì ìœ¼ë¡œ ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤. + + + + Error creating view: %1 + ë·° ìƒì„± ì—러: %1 + + + + This action will open a new SQL tab for running: + ì´ ìž‘ì—…ì€ ë‹¤ìŒì„ 실행하는 새 SQL íƒ­ì„ ì—½ë‹ˆë‹¤: + + + + Press Help for opening the corresponding SQLite reference page. + 해당 SQLite 참조 페ì´ì§€ë¥¼ 열려면 ë„움ë§ì„ 누르십시오. + + + + DB Browser for SQLite project file (*.sqbpro) + DB Browser for SQLite 프로ì íЏ íŒŒì¼ (*.sqbpro) + + + + Error checking foreign keys after table modification. The changes will be reverted. + í…Œì´ë¸” 수정 후 외래 키를 확ì¸í•˜ëŠ” 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤. 변경 ì‚¬í•­ì´ ë˜ëŒë ¤ì§‘니다. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + ì´ í…Œì´ë¸”ì€ ì™¸ëž˜ 키 검사를 통과하지 못했습니다.<br/>'ë„구 -> 외래 키 검사'를 실행하여 ë³´ê³ ëœ ë¬¸ì œë¥¼ 해결하십시오. + + + + Execution finished with errors. + ì—러가 ë°œìƒí•˜ì—¬ 실행 중단ë¨. + + + + Execution finished without errors. + ì—러 ì—†ì´ ì‹¤í–‰ 완료. + + + + NullLineEdit + + + Set to NULL + NULL로 변경하기 + + + + Alt+Del + + + + + PlotDock + + + Plot + 플롯 + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>ì´ í™”ë©´ì€ í˜„ìž¬ ë³´ê³  있는 í…Œì´ë¸” ë˜ëŠ” 방금 실행한 ì¿¼ë¦¬ì˜ í•„ë“œ 목ë¡ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. 아래 플롯 í™”ë©´ì— Xì¶• ë˜ëŠ” Y축으로 사용할 필드를 ì„ íƒí•  수 있습니다. ì´ í‘œëŠ” ê²°ê³¼ í”Œë¡¯ì— ì˜í–¥ì„ 줄 수 있다고 ì¸ì‹ëœ ì¶•ì˜ ì¢…ë¥˜ë¥¼ ë³´ì—¬ì¤ë‹ˆë‹¤. Yì¶•ì€ ìˆ«ìž íƒ€ìž… 필드만 ì„ íƒí•  수 있지만 Xì¶•ì€ ë‹¤ìŒê³¼ ê°™ì€ í•„ë“œ íƒ€ìž…ì„ ì„ íƒí•  수 있습니다:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">ë‚ ì§œ</span>: 문ìžì—´ í¬ë§· &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">시간</span>: 문ìžì—´ í¬ë§· &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">ë¼ë²¨</span>: ì´ í•„ë“œë¥¼ X축으로 ì„ íƒí•˜ë©´ 필드 ê°’ì´ ë§‰ëŒ€ì˜ ë ˆì´ë¸”로 í‘œì‹œëœ ë§‰ëŒ€ 그래프가 ìƒì„±ë©ë‹ˆë‹¤.</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">숫ìž</span>: 정수 ë˜ëŠ” 실수</li></ul><p>Y ì…€ì„ ë”블 í´ë¦­í•˜ë©´ ê·¸ëž˜í”„ì— ì‚¬ìš©ëœ ìƒ‰ì„ ë³€ê²½í•  수 있습니다.</p></body></html> + + + + Columns + 필드 + + + + X + X + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + ì¶• 타입 + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + 위ì—서 x와 y ê°’ì„ ì„ íƒí•˜ë©´ ì—¬ê¸°ì— í”Œë¡¯ì´ ê·¸ë ¤ì§‘ë‹ˆë‹¤. + +플롯과 í…Œì´ë¸”ì—서 í•­ëª©ì„ í´ë¦­í•˜ë©´ ì„ íƒë©ë‹ˆë‹¤. 여러 ë²”ìœ„ì˜ í•­ëª©ì„ ì„ íƒí•˜ë ¤ë©´ Control+í´ë¦­ì„ 하세요. + +확대/축소를 하려면 마우스 íœ ì„ ì´ìš©í•˜ê³  ì¶• 범위를 바꾸려면 마우스를 드래그하세요. + +한 방향으로만 드래그 ë˜ëŠ” 확대/축소를 하고 싶다면 ì¶• ë˜ëŠ” ì¶• ë¼ë²¨ì„ ì„ íƒí•˜ì„¸ìš”. + + + + Line type: + í–‰ 타입: + + + + + None + 사용하지 ì•ŠìŒ + + + + Line + í–‰ + + + + StepLeft + 왼쪽으로 + + + + StepRight + 오른쪽으로 + + + + StepCenter + 중앙으로 + + + + Impulse + 임펄스(Impulse) + + + + Point shape: + í¬ì¸íЏ 모양: + + + + Cross + ì‹­ìžê°€ + + + + Plus + ë”하기 + + + + Circle + ì› + + + + Disc + 디스í¬(Disc) + + + + Square + 정사ê°í˜• + + + + Diamond + 마름모 + + + + Star + 별 + + + + Triangle + 삼ê°í˜• + + + + TriangleInverted + 역삼ê°í˜• + + + + CrossSquare + CrossSquare + + + + PlusSquare + PlusSquare + + + + CrossCircle + CrossCircle + + + + PlusCircle + PlusCircle + + + + Peace + Peace + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>현재 플롯 저장하기...</p><p>íŒŒì¼ í¬ë§· 확장ìžë¥¼ ì„ íƒí•˜ì„¸ìš” (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + 현재 플롯 저장하기... + + + + + Load all data and redraw plot + 모든 ë°ì´í„°ë¥¼ 불러와서 í”Œë¡¯ì„ ë‹¤ì‹œ 그립니다 + + + + + + Row # + í–‰ # + + + + Copy + 복사 + + + + Print... + ì¸ì‡„하기... + + + + Help + ë„ì›€ë§ + + + + Show legend + 범례 표시 + + + + Stacked bars + ëˆ„ì  ë§‰ëŒ€ + + + + Fixed number format + ê³ ì • ìˆ«ìž í˜•ì‹ + + + + Date/Time + ë‚ ì§œ/시간 + + + + Date + ë‚ ì§œ + + + + Time + 시간 + + + + + Numeric + ìˆ«ìž + + + + Label + ë ˆì´ë¸” + + + + Invalid + 올바르지 ì•ŠìŒ + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + 모든 ë°ì´í„°ë¥¼ 불러와서 í”Œë¡¯ì„ ë‹¤ì‹œ 그립니다. +주ì˜: ì´ ê¸°ëŠ¥ì€ ë¶€ë¶„ë§Œ 가져오는 메커니즘으로 ì¸í•˜ì—¬ í…Œì´ë¸”ì—서 모든 ë°ì´í„°ê°€ 가져와지지는 않습니다. + + + + Choose an axis color + ì¶• ìƒ‰ê¹”ì„ ì„ íƒí•˜ì„¸ìš” + + + + Choose a filename to save under + 저장하려는 파ì¼ëª…ì„ ì„ íƒí•˜ì„¸ìš” + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;모든 파ì¼(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + í”Œë¡¯ì— ìžˆëŠ” 곡선들 ì¤‘ì— X축으로 ì •ë ¬ëœ ê·¸ëž˜í”„ë§Œ ì„ íƒí•œ ì„ ì˜ ìŠ¤íƒ€ì¼ì„ 변경할 수 있습니다. X로 표 ë˜ëŠ” 쿼리를 정렬하여 ê³¡ì„ ì„ ì œê±°í•˜ë ¤ë©´ '사용하지 않ìŒ'ì„, ê³¡ì„ ì´ ì§€ì›í•˜ëŠ” ìŠ¤íƒ€ì¼ ì¤‘ 하나를 ì„ íƒí•˜ë ¤ë©´ 'í–‰'ì„ ì„ íƒí•˜ì„¸ìš”. + + + + Loading all remaining data for this table took %1ms. + í…Œì´ë¸”ì˜ ë‚˜ë¨¸ì§€ ë°ì´í„°ë¥¼ ë¶ˆëŸ¬ì˜¤ëŠ”ë° %1msê°€ 소요ë˜ì—ˆìŠµë‹ˆë‹¤. + + + + PreferencesDialog + + + Preferences + 환경설정 + + + + &General + ì¼ë°˜(&G) + + + + Remember last location + 마지막 위치를 기억 + + + + Always use this location + í•­ìƒ ì´ ìœ„ì¹˜ë¥¼ 사용 + + + + Remember last location for session only + ê°™ì€ ì„¸ì…˜ì—서만 마지막 위치를 기억 + + + + + + ... + ... + + + + Default &location + 기본 위치(&L) + + + + Lan&guage + 언어(&G) + + + + Automatic &updates + ìžë™ ì—…ë°ì´íЏ(&U) + + + + + + + + + + + + + + enabled + 사용하기 + + + + Show remote options + ì›ê²© 옵션 보기 + + + + &Database + ë°ì´í„°ë² ì´ìФ(&D) + + + + Database &encoding + ë°ì´í„°ë² ì´ìФ ì¸ì½”딩(&E) + + + + Open databases with foreign keys enabled. + 외래키 ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ë©° ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 엽니다. + + + + &Foreign keys + 외래키(&F) + + + + Data &Browser + ë°ì´í„° 보기(&B) + + + + Remove line breaks in schema &view + 스키마 ë·°ì—서 ê°œí–‰ì„ ì œê±°í•©ë‹ˆë‹¤(&V) + + + + Prefetch block si&ze + 프리패치 í•  블럭 í¬ê¸°(&Z) + + + + SQ&L to execute after opening database + ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ì—° 후 SQLì„ ì‹¤í–‰(&L) + + + + Default field type + 기본 필드 타입 + + + + Font + 글꼴 + + + + &Font + 글꼴(&F) + + + + Content + ë‚´ìš© + + + + Symbol limit in cell + ì…€ 안 심볼 한계 + + + + NULL + NULL + + + + Regular + 보통 + + + + Binary + ë°”ì´ë„ˆë¦¬ + + + + Background + 배경색 + + + + Filters + í•„í„° + + + + Toolbar style + 툴바 ìŠ¤íƒ€ì¼ + + + + + + + + Only display the icon + ì•„ì´ì½˜ë§Œ 표시 + + + + + + + + Only display the text + í…스트만 표시 + + + + + + + + The text appears beside the icon + í…스트를 ì•„ì´ì½˜ 옆으로 + + + + + + + + The text appears under the icon + í…스트가 ì•„ì´ì½˜ 아래로 + + + + + + + + Follow the style + 애플리케ì´ì…˜ ìŠ¤íƒ€ì¼ ì ìš© + + + + DB file extensions + ë°ì´í„°ë² ì´ìФ íŒŒì¼ í™•ìž¥ìž + + + + Manage + 관리 + + + + Main Window + ë©”ì¸ ì°½ + + + + Database Structure + ë°ì´í„°ë² ì´ìФ 구조 + + + + Browse Data + ë°ì´í„° 보기 + + + + Execute SQL + SQL 실행 + + + + Edit Database Cell + ë°ì´í„°ë² ì´ìФ ì…€ 수정 + + + + When this value is changed, all the other color preferences are also set to matching colors. + ì´ ê°’ì´ ë³€ê²½ë˜ë©´ 다른 모든 색ìƒë“¤ë„ ì´ì— ì¼ì¹˜í•˜ëŠ” 색ìƒìœ¼ë¡œ 설정ë©ë‹ˆë‹¤. + + + + Follow the desktop style + ë°ìФí¬í†± ìŠ¤íƒ€ì¼ ì ìš© + + + + Dark style + 어둡게 + + + + Application style + 애플리케ì´ì…˜ ìŠ¤íƒ€ì¼ + + + + This sets the font size for all UI elements which do not have their own font size option. + 개별 글꼴 í¬ê¸° ì˜µì…˜ì´ ì—†ëŠ” 모든 UI ìš”ì†Œì˜ ê¸€ê¼´ í¬ê¸°ë¥¼ 설정합니다. + + + + Font size + 글꼴 í¬ê¸° + + + + Prompt to save SQL tabs +in new project file + 새 프로ì íЏ 파ì¼ì—서 +SQL íƒ­ì„ ì €ìž¥í•˜ë¼ëŠ” 메시지 출력 + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + ì´ ê¸°ëŠ¥ì„ ì¼œë©´ SQL편집기 íƒ­ì„ ë‹«ì„ ë•Œ 코드 ë³€ê²½ì‚¬í•­ì„ í”„ë¡œì íŠ¸ì— ì €ìž¥í•  ì§€ 물어봅니다. + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + 활성화ë˜ë©´ DB 구조 íƒ­ì˜ ìŠ¤í‚¤ë§ˆ ì—´ì—서 줄 바꿈, ë… ë° ì¸ì‡„ëœ ì¶œë ¥ì´ ì œê±°ë©ë‹ˆë‹¤. + + + + Database structure font size + ë°ì´í„°ë² ì´ìФ 구조 글꼴 í¬ê¸° + + + + Font si&ze + 글꼴 í¬ê¸°(&Z) + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + ì—°ì‚°ì´ ë§Žì´ ê±¸ë¦¬ëŠ” ì¼ë¶€ ê¸°ëŠ¥ì„ í™œì„±í™”í•˜ëŠ”ë° í—ˆìš©ë˜ëŠ” 최대 항목 수입니다. +ì—´ì˜ í˜„ìž¬ ê°’ì„ ê¸°ë°˜ìœ¼ë¡œ ê°’ ì™„ì„±ì„ í™œì„±í™”í•˜ê¸° 위한 í…Œì´ë¸”ì˜ ìµœëŒ€ í–‰ì˜ ê°¯ìˆ˜ìž…ë‹ˆë‹¤. +합계 ë° í‰ê· ì„ 계산하려는 ì„ íƒ í•­ëª©ì˜ ìµœëŒ€ ì¸ë±ìФ 수입니다. +기능 비활성화하려면 0으로 설정하세요. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + ì—´ì˜ í˜„ìž¬ ê°’ì„ ê¸°ë°˜ìœ¼ë¡œ ê°’ ì™„ì„±ì„ í™œì„±í™”í•˜ê¸° 위한 í…Œì´ë¸”ì˜ ìµœëŒ€ í–‰ 수입니다. +비활성화하려면 0으로 설정하세요. + + + + Close button on tabs + íƒ­ì— ë‹«ê¸° 버튼 + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + 활성화ë˜ë©´ SQL 편집기 íƒ­ì— ë‹«ê¸° ë²„íŠ¼ì´ ìƒê¹ë‹ˆë‹¤. ì–´ë–¤ 경우든 컨í…스트 메뉴나 키보드 단축기를 사용하여 ë‹«ì„ ìˆ˜ 있습니다. + + + + Select built-in extensions to load for every database: + 모든 ë°ì´í„°ë² ì´ìŠ¤ì— ëŒ€í•´ 불러 올 내장 확장기능: + + + + Proxy + 프ë¡ì‹œ + + + + Configure + 설정 + + + + Field display + 필드 출력 + + + + Light style + ë°ì€ 테마 + + + + Max Recent Files + 최근 ì—° íŒŒì¼ ëª©ë¡ ìµœëŒ€ê°’ + + + + Displayed &text + 출력 í…스트(&T) + + + + + + + + + + + Click to set this color + ì„ íƒí•˜ì—¬ ì´ ìƒ‰ìƒì„ ì„ íƒí•˜ì„¸ìš” + + + + Text color + 글ìžìƒ‰ + + + + Background color + 배경색 + + + + + Preview only (N/A) + 미리보기만 출력 (N/A) + + + + Escape character + ì´ìŠ¤ì¼€ì´í”„ ë¬¸ìž + + + + Delay time (&ms) + 대기 시간 (&ms) + + + + Formatted + ì„œì‹ + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + 새로운 í•„í„° ê°’ì„ ì ìš©í•˜ê¸° ì „ì— ëŒ€ê¸°í•  ì‹œê°„ì„ ì„¤ì •í•˜ì„¸ìš”. 대기 ì‹œê°„ì„ 0으로 하면 대기하지 않습니다. + + + + &SQL + SQL(&S) + + + + Context + ë‚´ìš© + + + + Colour + 색깔 + + + + Bold + 진하게 + + + + Italic + 기울게 + + + + Underline + 밑줄 + + + + Keyword + 키워드 + + + + Function + 함수 + + + + Table + í…Œì´ë¸” + + + + Comment + ì£¼ì„ + + + + Identifier + ì‹ë³„ìž + + + + String + 문ìžì—´ + + + + Current line + 현재 í–‰ + + + + Selection background + ì„ íƒëœ 배경색 + + + + Selection foreground + ì„ íƒëœ 전경색 + + + + Highlight + ê°•ì¡° + + + + SQL &editor font size + SQL ì—디터 글꼴 í¬ê¸°(&E) + + + + Tab size + 탭 í¬ê¸° + + + + Use tabs for indentation + ë“¤ì—¬ì“°ê¸°ì— íƒ­ 사용 + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + 설정하면 Tab 키는 들여쓰기를 위해 탭 ë° ê³µë°± 문ìžë¥¼ 삽입합니다. 그렇지 않으면 공백만 사용ë©ë‹ˆë‹¤. + + + + &Wrap lines + 줄 바꿈(&W) + + + + Never + 사용 안 함 + + + + At word boundaries + 단어 경계ì—서 + + + + At character boundaries + ë¬¸ìž ê²½ê³„ì—서 + + + + At whitespace boundaries + 공백ì—서 + + + + &Quotes for identifiers + ì‹ë³„ìž êµ¬ë¶„ 기호(&Q) + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + SQL ì½”ë“œì˜ ì‹ë³„ìžì— 대해 ì‘ìš© 프로그램ì—서 사용하는 기호를 ì„ íƒí•©ë‹ˆë‹¤. + + + + "Double quotes" - Standard SQL (recommended) + "í° ë”°ì˜´í‘œ" - SQL 표준 (권장ë¨) + + + + `Grave accents` - Traditional MySQL quotes + 'ìž‘ì€ ë”°ì˜´í‘œ' - MySQL 전통 ì¸ìš© 부호 + + + + [Square brackets] - Traditional MS SQL Server quotes + [대괄호] - MS SQL 전통 ì¸ìš© 부호 + + + + Keywords in &UPPER CASE + í‚¤ì›Œë“œì— ëŒ€í•´ 대문ìž(&U) + + + + When set, the SQL keywords are completed in UPPER CASE letters. + 활성화ë˜ë©´ SQL 키워드가 대문ìžë¡œ 완성ë©ë‹ˆë‹¤. + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + 활성화ë˜ë©´ 마지막 실행 ì¤‘ì— ì˜¤ë¥˜ë¥¼ ì¼ìœ¼í‚¨ SQL 코드 ì¤„ì´ ê°•ì¡° 표시ë˜ê³  ê²°ê³¼ í”„ë ˆìž„ì€ ë°±ê·¸ë¼ìš´ë“œì— 오류를 나타냅니다 + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite는 공유 ë¼ì´ë¸ŒëŸ¬ë¦¬ 파ì¼ì—서 í™•ìž¥ì„ ë¡œë“œí•˜ê¸° 위한 SQL 함수를 제공합니다. SQL 코드ì—서 <span style=" font-style:italic;">load_extension()</span> 함수를 사용하려면 ì´ ê¸°ëŠ¥ì„ í™œì„±í™”í•˜ì‹­ì‹œì˜¤.</p><p>보안 ìƒì˜ ì´ìœ ë¡œ 확장 로드는 기본ì ìœ¼ë¡œ 비활성화ë˜ì–´ 있으며 ì„¤ì •ì„ í†µí•´ 활성화해야 합니다. ì´ ì˜µì…˜ì´ ë¹„í™œì„±í™”ë˜ì–´ 있ë”ë¼ë„ í•­ìƒ GUI를 통해 í™•ìž¥ì„ ë¡œë“œí•  수 있습니다.</p></body></html> + + + + Allow loading extensions from SQL code + SQL 코드ì—서 í™•ìž¥ê¸°ëŠ¥ì„ ë¶ˆëŸ¬ì˜¤ëŠ” ê²ƒì„ í—ˆìš© + + + + Remote + ì›ê²© + + + + CA certificates + CA ì¸ì¦ì„œ + + + + + Subject CN + 제목 CN + + + + Common Name + ì¼ë°˜ ì´ë¦„ + + + + Subject O + 제목 O + + + + Organization + 기관 + + + + + Valid from + 유효날짜(시작) + + + + + Valid to + 유효날짜(ë) + + + + + Serial number + 시리얼 넘버 + + + + Your certificates + ë‹¹ì‹ ì˜ ì¸ì¦ì„œ + + + + File + íŒŒì¼ + + + + Subject Common Name + 주제 ì¼ë°˜ ì´ë¦„ + + + + Issuer CN + ì´ìŠˆ 등ë¡ìž CN + + + + Issuer Common Name + ì´ìŠˆ 등ë¡ìž ì¼ë°˜ ì´ë¦„ + + + + Clone databases into + ë°ì´í„°ë² ì´ìФ 복제하기 + + + + SQL editor &font + SQL 편집기 글꼴(&F) + + + + Error indicators + ì—러 표시 + + + + Hori&zontal tiling + 화면 ìˆ˜í‰ ë‚˜ëˆ„ê¸°(&Z) + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + 활성화ë˜ë©´ SQL 코드 편집기와 ê²°ê³¼ í…Œì´ë¸” ë·°ê°€ 나란히 표시ë©ë‹ˆë‹¤. + + + + Code co&mpletion + 코드 완성(&M) + + + + Threshold for completion and calculation on selection + ì„ íƒì— 대한 완료 ë° ì—°ì‚° 임계 ê°’ + + + + Show images in cell + ì…€ì— ì´ë¯¸ì§€ 표시 + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + ì…€ì— ì´ë¯¸ì§€ ë°ì´í„°ê°€ í¬í•¨ëœ BLOBì˜ ë¯¸ë¦¬ë³´ê¸°ë¥¼ 표시하려면 ì´ ì˜µì…˜ì„ í™œì„±í™”í•©ë‹ˆë‹¤. 그러나 ì´ëŠ” ë°ì´í„° 브ë¼ìš°ì €ì˜ ì„±ëŠ¥ì— ì˜í–¥ì„ ë¼ì¹  수 있습니다. + + + + Foreground + 전경색 + + + + SQL &results font size + SQL ê²°ê³¼ 글꼴 í¬ê¸°(&R) + + + + &Extensions + 확장기능(&E) + + + + Select extensions to load for every database: + 불러올 í™•ìž¥ê¸°ëŠ¥ì„ ì„ íƒí•˜ì„¸ìš”(í™•ìž¥ê¸°ëŠ¥ì€ ëª¨ë“  ë°ì´í„°ë² ì´ìŠ¤ì— ë°˜ì˜ë©ë‹ˆë‹¤): + + + + Add extension + 확장기능 추가 + + + + Remove extension + 확장기능 제거 + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>SQLiteì—서는 기본ì ìœ¼ë¡œ ì •ê·œ í‘œí˜„ì‹ ê¸°ëŠ¥ì„ ì œê³µí•˜ì§€ 않습니다만 애플리케ì´ì…˜ì„ 실행하여 호출하는 ê²ƒì€ ê°€ëŠ¥í•©ë‹ˆë‹¤. DB Browser for SQLiteì—서는 ì´ ì•Œê³ ë¦¬ì¦˜ì„ ë°•ìŠ¤ ë°–ì—ì„œë„ ì •ê·œ 표현ì‹ì„ 사용할 수 있ë„ë¡ ì´ ì•Œê³ ë¦¬ì¦˜ì„ êµ¬í˜„í•´ì¤ë‹ˆë‹¤. 하지만 í™•ìž¥ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ì—¬ 외부ì—서 만든 알고리즘 êµ¬í˜„ì„ ì‚¬ìš©í•˜ê³ ìž í•œë‹¤ë©´ DB Browser for SQLiteì—서 제공하는 구현 ì‚¬ìš©ì„ ìžìœ ë¡­ê²Œ ëŒ ìˆ˜ 있습니다. ì´ ê¸°ëŠ¥ì€ ì• í”Œë¦¬ì¼€ì´ì…˜ì„ 재시작해야 합니다.</p></body></html> + + + + Disable Regular Expression extension + ì •ê·œ í‘œí˜„ì‹ í™•ìž¥ê¸°ëŠ¥ 비활성화 + + + + Export Settings + 환경설정 내보내기 + + + + Import Settings + 환경설정 불러오기 + + + + + Choose a directory + 디렉터리를 ì„ íƒí•˜ì„¸ìš” + + + + + The language will change after you restart the application. + 언어 ë³€ê²½ì€ ì• í”Œë¦¬ì¼€ì´ì…˜ì„ 재시작해야 ë°˜ì˜ë©ë‹ˆë‹¤. + + + + Select extension file + 확장기능 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” + + + + Extensions(*.so *.dylib *.dll);;All files(*) + 확장기능(*.so *.dylib *dll);;모든 파ì¼(*) + + + + Import certificate file + ì¸ì¦ì„œ íŒŒì¼ ê°€ì ¸ì˜¤ê¸° + + + + No certificates found in this file. + ì´ íŒŒì¼ì—는 ì¸ì¦ì„œê°€ 없습니다. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + ì •ë§ë¡œ ì´ ì¸ì¦ì„œë¥¼ 삭제하겠습니까? 애플리케ì´ì…˜ 설정ì—서 모든 ì¦ëª… ë°ì´í„°ê°€ ì‚­ì œë  ê²ƒìž…ë‹ˆë‹¤! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + ì €ìž¥ëœ ëª¨ë“  ì„¤ì •ì„ ì •ë§ë¡œ 초기화하시겠습니까? +모든 ì„¤ì •ì´ ì´ˆê¸°í™”ë˜ê³  기본값으로 대체ë©ë‹ˆë‹¤. + + + + Save Settings File + í™˜ê²½ì„¤ì •ì„ ë‚´ë³´ë‚¼ 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” + + + + + Initialization File (*.ini) + 환경설정 íŒŒì¼ (*.ini) + + + + The settings file has been saved in location : + + 환경설정 파ì¼ì´ ë‹¤ìŒ ê²½ë¡œì— ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤ : + + + + + Open Settings File + 가져오려는 환경설정 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” + + + + The settings file was loaded properly. + 환경설정 파ì¼ì„ ì •ìƒì ìœ¼ë¡œ 불러 왔습니다. + + + + The selected settings file is not a normal settings file. +Please check again. + ì„ íƒí•˜ì‹  환경설정 파ì¼ì€ ì •ìƒì ì¸ 환경설정 파ì¼ì´ 아닙니다. +다시 확ì¸í•´ì£¼ì„¸ìš”. + + + + ProxyDialog + + + Proxy Configuration + 프ë¡ì‹œ 설정 + + + + Pro&xy Type + 프ë¡ì‹œ 종류(&X) + + + + Host Na&me + 서버 주소(&M) + + + + Port + í¬íЏ + + + + Authentication Re&quired + ì¸ì¦ ì •ë³´ í•„ìš”(&Q) + + + + &User Name + 사용ìžëª…(&U) + + + + Password + 암호 + + + + None + 사용하지 ì•ŠìŒ + + + + System settings + 시스템 설정 + + + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 + + + + QObject + + + Error importing data + ë°ì´í„° 가져오기 ì—러 + + + + from record number %1 + 레코드 넘버: %1 + + + + . +%1 + . +%1 + + + + Importing CSV file... + CSV íŒŒì¼ ê°€ì ¸ì˜¤ê¸°... + + + + Cancel + 취소 + + + + All files (*) + 모든 파ì¼(*) + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + SQLite ë°ì´í„°ë² ì´ìФ 파ì¼(*.db *.sqlite *.sqlite3 *.db3) + + + + Left + 왼쪽 + + + + Right + 오른쪽 + + + + Center + 중앙 + + + + Justify + ì •ë ¬ + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + SQLite ë°ì´í„°ë² ì´ìФ íŒŒì¼ (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + DB Browser for SQLite 프로ì íЏ íŒŒì¼ (*.sqbpro) + + + + SQL Files (*.sql) + SQL íŒŒì¼ (*.sql) + + + + All Files (*) + 모든 íŒŒì¼ (*) + + + + Text Files (*.txt) + í…스트 íŒŒì¼ (*.txt) + + + + Comma-Separated Values Files (*.csv) + 쉼표로 êµ¬ë¶„ëœ íŒŒì¼ (*.csv) + + + + Tab-Separated Values Files (*.tsv) + 탭으로 ë¶„ë¦¬ëœ íŒŒì¼ (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + 구분ìžë¡œ êµ¬ë¶„ëœ íŒŒì¼ (*.dsv) + + + + Concordance DAT files (*.dat) + Concordance DAT íŒŒì¼ (*.dat) + + + + JSON Files (*.json *.js) + JSON íŒŒì¼ (*.json *.js) + + + + XML Files (*.xml) + XML íŒŒì¼ (*.xml) + + + + Binary Files (*.bin *.dat) + ë°”ì´ë„ˆë¦¬ íŒŒì¼ (*bin *.dat) + + + + SVG Files (*.svg) + SVG íŒŒì¼ (*.svg) + + + + Hex Dump Files (*.dat *.bin) + Hex ë¤í”„ íŒŒì¼ (*.dat *bin) + + + + Extensions (*.so *.dylib *.dll) + 확장기능 (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + 환경설정 íŒŒì¼ (*.ini) + + + + QsciCommand + + Paste + 붙여넣기 + + + Cancel + 취소 + + + + QsciLexerCPP + + Keyword + 키워드 + + + Identifier + ì‹ë³„ìž + + + + QsciLexerJSON + + String + 문ìžì—´ + + + + QsciLexerJavaScript + + Regular expression + ì •ê·œ í‘œí˜„ì‹ + + + + QsciLexerPython + + Comment + ì£¼ì„ + + + Keyword + 키워드 + + + Identifier + ì‹ë³„ìž + + + + QsciLexerSQL + + Comment + ì£¼ì„ + + + Keyword + 키워드 + + + Identifier + ì‹ë³„ìž + + + + QsciScintilla + + &Undo + 실행 취소(&U) + + + Select All + ëª¨ë‘ ì„ íƒ + + + + RemoteCommitsModel + + + Commit ID + 커밋 ID + + + + Message + 메시지 + + + + Date + ë‚ ì§œ + + + + Author + ì €ìž + + + + Size + í¬ê¸° + + + + Authored and committed by %1 + %1ì— ì˜í•´ 작성ë˜ê³  ì»¤ë°‹ë¨ + + + + Authored by %1, committed by %2 + %1ì— ì˜í•´ 작성ë˜ê³ , %2ì— ì˜í•´ ì»¤ë°‹ë¨ + + + + RemoteDatabase + + + Error opening local databases list. +%1 + 로컬 ë°ì´í„°ë² ì´ìФ 목ë¡ì„ ì—´ë˜ ì¤‘ ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. %1 + + + + Error creating local databases list. +%1 + 로컬 ë°ì´í„°ë² ì´ìФ 목ë¡ì„ ìƒì„±í•˜ë˜ 중 ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. %1 + + + + RemoteDock + + + Remote + ì›ê²© + + + + Local + 로컬 + + + + Identity + ì‹ ì› + + + + Push currently opened database to server + 현재 열린 ë°ì´ë² ì´ìŠ¤ë¥¼ 서버로 ë°˜ì˜í•©ë‹ˆë‹¤ + + + + Upload + 업로드 + + + + DBHub.io + DBHub.io + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>ì´ ì°½ì—서는 DBHub.io 웹 사ì´íŠ¸ì˜ ì›ê²© ë°ì´í„°ë² ì´ìŠ¤ë¥¼ DB Browser for SQLiteì— ì¶”ê°€í•  수 있습니다.</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">DBHub.io 웹 사ì´íŠ¸ì— ë¡œê·¸ì¸(ì›í•˜ì‹œë©´ GitHub ìžê²© ì¦ëª…ì„ ì‚¬ìš©í•  수 있습니다)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ë²„íŠ¼ì„ í´ë¦­í•˜ì—¬ &quot;í´ë¼ì´ì–¸íЏ ì¸ì¦ì„œ ìƒì„±&quot; (ë‹¹ì‹ ì˜ ì‹ ì› ì •ë³´). 그러면 ì¸ì¦ì„œ 파ì¼ì´ 제공ë©ë‹ˆë‹¤(로컬 디스í¬ì— 저장)</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">DB Browser for SQLite ì„¤ì •ì˜ ì›ê²© 탭으로 ì´ë™í•©ë‹ˆë‹¤. ë²„íŠ¼ì„ í´ë¦­í•˜ì—¬ DB Browser for SQLiteì— ìƒˆ ì¸ì¦ì„œë¥¼ 추가하고 방금 다운로드한 ì¸ì¦ì„œ 파ì¼ì„ ì„ íƒí•©ë‹ˆë‹¤.</li></ol><p>ì´ì œ ì›ê²© 패ë„ì— IDê°€ 표시ë˜ê³  ì›ê²© ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 추가할 수 있습니다.</p></body></html> + + + + Current Database + 현재 ë°ì´í„°ë² ì´ìФ + + + + Clone + 복제 + + + + Branch + 브랜치 + + + + Commits + 커밋 + + + + Commits for + 커밋 조회할 브랜치 + + + + Delete Database + ë°ì´í„°ë² ì´ìФ ì‚­ì œ + + + + Delete the local clone of this database + ì´ ë°ì´í„°ë² ì´ìŠ¤ì˜ ë¡œì»¬ 복제본 ì‚­ì œ + + + + Open in Web Browser + 웹 브ë¼ìš°ì €ì—서 열기 + + + + Open the web page for the current database in your browser + 브ë¼ìš°ì €ì—서 현재 ë°ì´í„°ë² ì´ìŠ¤ì˜ ì›¹ 페ì´ì§€ë¥¼ 엽니다 + + + + Clone from Link + 주소로부터 복제 + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + ì´ë¥¼ 사용하여 로컬 íŽ¸ì§‘ì„ ìœ„í•´ ë°ì´í„°ë² ì´ìŠ¤ì˜ ì›¹ 페ì´ì§€ì—서 ì œê³µëœ URLì„ ì‚¬ìš©í•˜ì—¬ ì›ê²© ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 다운로드 합니다. + + + + Refresh + 새로고침 + + + + Reload all data and update the views + 모든 ë°ì´í„°ë¥¼ 다시 로드하고 뷰를 ì—…ë°ì´íŠ¸í•©ë‹ˆë‹¤ + + + + Clone Database + ë°ì´í„°ë² ì´ìФ 복제 + + + + Open Database + ë°ì´í„°ë² ì´ìФ 열기 + + + + Open the local copy of this database + ì´ ë°ì´í„°ë² ì´ìŠ¤ì˜ ë¡œì»¬ ë³µì œë³¸ì„ ì—½ë‹ˆë‹¤ + + + + Check out Commit + 커밋 ì²´í¬ì•„웃 + + + + Download and open this specific commit + ì´ íŠ¹ì • ì»¤ë°‹ì„ ë‹¤ìš´ë¡œë“œí•˜ì—¬ 엽니다 + + + + Check out Latest Commit + 최신 커밋 í™•ì¸ + + + + Check out the latest commit of the current branch + ì´ ë¸Œëžœì¹˜ì˜ ìµœì‹  커밋 í™•ì¸ + + + + Save Revision to File + ë¦¬ë¹„ì „ì„ íŒŒì¼ì— 저장 + + + + Saves the selected revision of the database to another file + ë°ì´í„°ë² ì´ìŠ¤ì˜ ì„ íƒí•œ ë¦¬ë¹„ì „ì„ ë‹¤ë¥¸ 파ì¼ì— 저장합니다 + + + + Upload Database + ë°ì´í„°ë² ì´ìФ 업로드 + + + + Upload this database as a new commit + ì´ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 새 커밋으로 업로드 + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>현재 기본으로 제공ë˜ëŠ” ì½ê¸° ì „ìš© ID를 사용하고 있습니다. ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 업로드하려면 DBHub.io ê³„ì •ì„ êµ¬ì„±í•˜ê³  사용해야 합니다.</p><p>ì•„ì§ DBHub.io ê³„ì •ì´ ì—†ìœ¼ì‹­ë‹ˆê¹Œ? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">지금 만들어</span></a> ì¸ì¦ì„œë¥¼ 가져옵니다. <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">여기</span></a>ì—서 ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 공유하세요.</p><p>온ë¼ì¸ ë„움ë§ì„ 보려면 <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">여기</span></a>를 방문하세요.</p></body></html> + + + + &User + 사용ìž(&U) + + + + &Database + ë°ì´í„°ë² ì´ìФ(&D) + + + + Back + 뒤로가기 + + + + Select an identity to connect + ì—°ê²°í•  ID를 ì„ íƒí•˜ì„¸ìš” + + + + Public + 공개 + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + 로컬 íŽ¸ì§‘ì„ ìœ„í•´ ì›ê²© 서버ì—서 ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 다운로드합니다. +복제하려는 URLì„ ìž…ë ¥í•˜ì„¸ìš”. ë°ì´í„°ë² ì´ìŠ¤ì˜ ì›¹ 페ì´ì§€ì—서 +'DB4Sì—서 ë°ì´í„°ë² ì´ìФ 복제' ë²„íŠ¼ì„ í´ë¦­í•˜ì—¬ +ì´ëŸ¬í•œ URLì„ ìƒì„±í•  수 있습니다. + + + + Invalid URL: The host name does not match the host name of the current identity. + ìž˜ëª»ëœ URL: 호스트 ì´ë¦„ì´ í˜„ìž¬ IDì˜ í˜¸ìŠ¤íŠ¸ ì´ë¦„ê³¼ ì¼ì¹˜í•˜ì§€ 않습니다. + + + + Invalid URL: No branch name specified. + ìž˜ëª»ëœ URL: ì§€ì •ëœ ë¸Œëžœì¹˜ ì´ë¦„ì´ ì—†ìŠµë‹ˆë‹¤. + + + + Invalid URL: No commit ID specified. + ìž˜ëª»ëœ URL: 커밋 IDê°€ 지정ë˜ì§€ 않았습니다. + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + ë°ì´í„°ë² ì´ìŠ¤ì˜ ë¡œì»¬ ë³µì œë³¸ì„ ìˆ˜ì •í–ˆìŠµë‹ˆë‹¤. ì´ ì»¤ë°‹ì„ ê°€ì ¸ì˜¤ë©´ ì´ëŸ¬í•œ 로컬 변경 ì‚¬í•­ì´ ë¬´ì‹œë©ë‹ˆë‹¤. +계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ? + + + + The database has unsaved changes. Are you sure you want to push it before saving? + ë°ì´í„°ë² ì´ìŠ¤ì— ì €ìž¥ë˜ì§€ ì•Šì€ ë³€ê²½ ì‚¬í•­ì´ ìžˆìŠµë‹ˆë‹¤. 저장하기 ì „ì— í‘¸ì‹œí•˜ì‹œê² ìŠµë‹ˆê¹Œ? + + + + The database you are trying to delete is currently opened. Please close it before deleting. + 삭제하려는 ë°ì´í„°ë² ì´ìŠ¤ê°€ 현재 열려있습니다. 삭제하기 ì „ì— ë‹«ìœ¼ì‹­ì‹œì˜¤. + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + ì´ë ‡ê²Œí•˜ë©´ ì•„ì§ ì»¤ë°‹í•˜ì§€ ì•Šì€ ëª¨ë“  변경 사항과 함께 ì´ ë°ì´í„°ë² ì´ìŠ¤ì˜ ë¡œì»¬ ë²„ì „ì´ ì‚­ì œë©ë‹ˆë‹¤. ì •ë§ë¡œ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 삭제하시겠습니까? + + + + RemoteLocalFilesModel + + + Name + ì´ë¦„ + + + + Branch + 브랜치 + + + + Last modified + 마지막 ìˆ˜ì •ì¼ + + + + Size + í¬ê¸° + + + + Commit + 커밋 + + + + File + íŒŒì¼ + + + + RemoteModel + + + Name + ì´ë¦„ + + + + Last modified + 마지막 수정 + + + + Size + í¬ê¸° + + + + Commit + 커밋 + + + + Size: + í¬ê¸°: + + + + Last Modified: + 마지막 수정: + + + + Licence: + ë¼ì´ì„¼ìФ: + + + + Default Branch: + 기본 브랜치: + + + + RemoteNetwork + + + Choose a location to save the file + 파ì¼ì„ 저장할 위치를 ì„ íƒí•˜ì„¸ìš” + + + + Error opening remote file at %1. +%2 + %1 ì— ìžˆëŠ” ì›ê²© 파ì¼ì„ ì—´ë˜ ì¤‘ ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. +%2 + + + + Error: Invalid client certificate specified. + ì—러: 올바르지 ì•Šì€ í´ë¼ì´ì–¸íЏ ì¸ì¦ì„œìž…니다. + + + + Please enter the passphrase for this client certificate in order to authenticate. + ì¸ì¦ì„ 위한 í´ë¼ì´ì–¸íЏ ì¸ì¦ì„œ 암호를 입력해주세요. + + + + Cancel + 취소 + + + + Uploading remote database to +%1 + %1로 +ì›ê²© ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 업로드 중입니다 + + + + Downloading remote database from +%1 + %1 ì—서 ì›ê²© ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 다운로드 중입니다. {1?} + + + + Error: Cannot open the file for sending. + ì—러: 보내려는 파ì¼ì„ ì—´ 수 없습니다. + + + + RemotePushDialog + + + Push database + ë°ì´í„°ë² ì´ìФ 푸시(Push) + + + + Database na&me to push to + 푸시할 ë°ì´í„°ë² ì´ìФ ì´ë¦„(&M) + + + + Commit message + 커밋 메시지 + + + + Database licence + ë°ì´í„°ë² ì´ìФ ë¼ì´ì„¼ìФ + + + + Public + 공개 + + + + Branch + 브랜치 + + + + Force push + ê°•ì œ 푸시 + + + + Username + 사용ìžëª… + + + + Database will be public. Everyone has read access to it. + 공개 ë°ì´í„°ë² ì´ìŠ¤ë¡œ 지정합니다. 누구나 ì½ê¸° ì ‘ê·¼ì´ ê°€ëŠ¥í•©ë‹ˆë‹¤. + + + + Database will be private. Only you have access to it. + 비공개 ë°ì´í„°ë² ì´ìŠ¤ë¡œ 지정합니다. 당신만 접근할 수 있습니다. + + + + Use with care. This can cause remote commits to be deleted. + 주ì˜í•´ì„œ 사용하세요. ì›ê²© ì»¤ë°‹ì„ ì‚­ì œí•˜ëŠ” 결과를 초래할 수 있습니다. + + + + RunSql + + + Execution aborted by user + 사용ìžì— ì˜í•´ì„œ ì‹¤í–‰ì´ ì·¨ì†Œë˜ì—ˆìŠµë‹ˆë‹¤ + + + + , %1 rows affected + , %1 í–‰ì´ ì˜í–¥ 받았습니다 + + + + query executed successfully. Took %1ms%2 + %2 ë°ì´í„°ë² ì´ìŠ¤ì— ì¿¼ë¦¬ê°€ 성공ì ìœ¼ë¡œ 실행ë˜ì—ˆìŠµë‹ˆë‹¤. %1ms 걸렸습니다 + + + + executing query + 쿼리 실행 중 + + + + SelectItemsPopup + + + A&vailable + 사용 가능한(&V) + + + + Sele&cted + ì„ íƒë¨(&C) + + + + SqlExecutionArea + + + Form + í¼ + + + + Find previous match [Shift+F3] + ì´ì „ 찾기 [Shift+F3] + + + + Find previous match with wrapping + 랩핑(Wrapping)ëœ ì´ì „ ì¼ì¹˜ë‚´ì—­ 검색하기 + + + + Shift+F3 + + + + + The found pattern must be a whole word + 온전한 ë‚±ë§ ì¼ì¹˜ 검색패턴 + + + + Whole Words + 온전한 ë‚±ë§ ì¼ì¹˜ + + + + Text pattern to find considering the checks in this frame + ì´ í”„ë ˆìž„ 안ì—서 확ì¸í•˜ê¸° 위해 ê²€ìƒ‰í•˜ê³ ìž í•˜ëŠ” 문ìžì—´ 패턴 + + + + Find in editor + 편집기 ë‚´ì—서 찾기 + + + + The found pattern must match in letter case + ëŒ€ì†Œë¬¸ìž ì¼ì¹˜ 검색패턴 + + + + Case Sensitive + ëŒ€ì†Œë¬¸ìž ì¼ì¹˜ + + + + Find next match [Enter, F3] + ë‹¤ìŒ ì°¾ê¸° [Enter,F3] + + + + Find next match with wrapping + 랩핑(Wrapping)으로 ë‹¤ìŒ ì°¾ê¸° + + + + F3 + + + + + Interpret search pattern as a regular expression + 검색 패턴 ì •ê·œ í‘œí˜„ì‹ ì‚¬ìš© + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>ì„ íƒí•˜ë©´ ì°¾ì„ íŒ¨í„´ì´ UNIX ì •ê·œ 표현ì‹ìœ¼ë¡œ í•´ì„ë©ë‹ˆë‹¤. <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>를 참고하십시오.</p></body></html> + + + + Regular Expression + ì •ê·œ í‘œí˜„ì‹ + + + + + Close Find Bar + 검색바 닫기 + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>마지막으로 ì‹¤í–‰ëœ ëª…ë ¹ë¬¸ì˜ ê²°ê³¼ìž…ë‹ˆë‹¤.</p><p>ì´ íŒ¨ë„ì„ ì¶•ì†Œí•˜ê³  대신 <span style=" font-style:italic;">사용ìž</span> ì„ íƒê³¼ 함께 <span style=" font-style:italic;">SQL 로그</span> ë…ì„ ì‚¬ìš©í•  수 있습니다.</p></body></html> + + + + Results of the last executed statements + 가장 최근 실행 구문 ê²°ê³¼ + + + + This field shows the results and status codes of the last executed statements. + ì´ í•„ë“œëŠ” 가장 ìµœê·¼ì— ì‹¤í–‰ëœ êµ¬ë¬¸ì˜ ê²°ê³¼ì™€ ìƒíƒœ 코드를 ë³´ì—¬ì¤ë‹ˆë‹¤. + + + + Ctrl+PgUp + + + + + Ctrl+PgDown + + + + + Couldn't read file "%1": %2. + "%1" 파ì¼ì„ ì—´ 수 없습니다: %2. + + + + + Couldn't save file: %1. + 파ì¼ì„ 저장할 수 없습니다: %1. + + + + Your changes will be lost when reloading it! + 다시 불러오면 변경 ì‚¬í•­ì„ ìžƒìŠµë‹ˆë‹¤! + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + "%1" 파ì¼ì´ 다른 í”„ë¡œê·¸ëž¨ì— ì˜í•´ 수정ë˜ì—ˆìŠµë‹ˆë‹¤. 다시 불러오겠습니까?%2 + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + 외부 ê°±ì‹ ì´ ìžˆì„때 물어보지 않고 파ì¼ì„ 다시 불러게 하려면 "ëª¨ë‘ ì˜ˆ"를 누르세요. + + + + Answer "No to All" to ignore any external update without further prompting. + 외부 ê°±ì‹ ì´ ìžˆì„ ë•Œ 물어보지 않고 무시하려면 "ëª¨ë‘ ì•„ë‹ˆìš”"로 ì‘답합니다. + + + + Modifying and saving the file will restore prompting. + 파ì¼ì„ 수정하고 저장하면 프롬프트가 ë³µì›ë©ë‹ˆë‹¤. + + + + SqlTextEdit + + + Ctrl+/ + + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) abs(X) 함수는 ìˆ«ìž ë§¤ê°œë³€ìˆ˜ Xì˜ ì ˆëŒ€ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤. + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () changes() 함수는 가장 ìµœê·¼ì— ì‹¤í–‰ëœ INSERT, DELETE, UPDATE 구문ì—서 ë°ì´í„°ë² ì´ìФì—서 변경ë˜ê±°ë‚˜ 추가ë˜ê±°ë‚˜ ì‚­ì œëœ í–‰ 수를 반환합니다. + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) char(X1,X2,...,XN) 함수는 ê°ê°ì˜ X1ì—서 XN ìˆ«ìž ê°’ì˜ ìœ ë‹ˆì½”ë“œ í¬ì¸íЏ ê°’ì„ ê°€ì§„ 문ìžë“¤ë¡œ êµ¬ì„±ëœ ë¬¸ìžì—´ì„ 반환합니다. + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) coalesce() 함수는 첫번째 NULLì´ ì•„ë‹Œ ì¸ìž ê°’ì˜ ì‚¬ë³¸ì„ ë°˜í™˜í•©ë‹ˆë‹¤. 만약 ì¸ìž ê°’ì´ ëª¨ë‘ NULLì´ë¼ë©´ NULLì„ ë°˜í™˜í•©ë‹ˆë‹¤ + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) glob(X,Y) 함수는 "Y GLOB X" 표현ì‹ê³¼ 같습니다. + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) ifnull() 함수는 첫번째 NULLì´ ì•„ë‹Œ ì¸ìž ê°’ì˜ ì‚¬ë³¸ì„ ë°˜í™˜í•©ë‹ˆë‹¤. 만약 ì¸ìžê°’ 둘 다 NULLì´ë¼ë©´ NULLì„ ë°˜í™˜í•©ë‹ˆë‹¤. + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) instr(X,Y) 함수는 문ìžì—´ Xì—서 문ìžì—´ Yê°€ 있다면 첫 ê¸€ìž ìœ„ì¹˜ + 1 ê°’ì„ ë¦¬í„´í•©ë‹ˆë‹¤. 만약 문ìžì—´ Xì—서 문ìžì—´ Yê°€ 발견ë˜ì§€ 않는다면 0ì„ ë°˜í™˜í•©ë‹ˆë‹¤. + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) hex() 함수는 매개변수를 BLOB으로 변환한 후 blobì˜ ë‚´ìš©ì„ ëŒ€ë¬¸ìž 16진수 문ìžì—´ë¡œ 변환하여 반환합니다. + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) The iif(X,Y,Z) 함수는 Xê°€ ì°¸ì´ë©´ Y ê°’ì„ ë°˜í™˜í•˜ê³ , 그렇지 않으면 Z를 반환합니다. - - &Open Database... - ë°ì´í„°ë² ì´ìФ 열기(&O)... + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () last_insert_rowid() 함수는 함수가 í˜¸ì¶œëœ ë°ì´í„°ë² ì´ìФ ì—°ê²°ì—서 가장 ìµœê·¼ì— ì¶”ê°€ëœ í–‰ì˜ ROWID를 반환합니다. - - - Open an existing database file - 기존 ë°ì´í„°ë² ì´ìФ 파ì¼ì„ 엽니다 + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) 문ìžì—´ 변수 X를 위한 것으로 length(X) 함수는 첫 번째 NUL 문ìžë¥¼ 만날 ë•Œê¹Œì§€ì˜ (ë°”ì´íЏ 수가 아닌)ë¬¸ìž ìˆ˜ë¥¼ 반환합니다. - - This option is used to open an existing database file. - ì´ ì˜µì…˜ì€ ê¸°ì¡´ ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ì—´ 때 사용합니다. + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) like() 함수는 "Y LIKE X" 표현ì‹ì„ 구현하기위해 사용합니다. - - Ctrl+O - Ctrl+O + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) like() 함수는 "Y LIKE X ESCAPE Z" 표현ì‹ì„ 구현하기 위해 사용합니다. - - &Close Database - ë°ì´í„°ë² ì´ìФ 닫기(&C) + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) load_extension(X) 함수는 Xë¼ëŠ” 공유 ë¼ì´ë¸ŒëŸ¬ë¦¬ 파ì¼ì—서 SQLite í™•ìž¥ì„ ë¡œë“œí•©ë‹ˆë‹¤. +ì´ ê¸°ëŠ¥ì˜ ì‚¬ìš©ì€ í™˜ê²½ì„¤ì •ì—서 승ì¸í•˜ì—¬ì•¼ 합니다. - - Ctrl+W - Ctrl+W + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) The load_extension(X) 함수는 ì§„ìž…ì  Y를 사용하여 Xë¼ëŠ” 공유 ë¼ì´ë¸ŒëŸ¬ë¦¬ 파ì¼ì—서 SQLite í™•ìž¥ì„ ë¡œë“œí•©ë‹ˆë‹¤. +ì´ ê¸°ëŠ¥ì˜ ì‚¬ìš©ì€ í™˜ê²½ì„¤ì •ì—서 승ì¸ë˜ì–´ì•¼ 합니다. - - Revert Changes - 변경사항 ë˜ëŒë¦¬ê¸° + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) lower(X) 함수는 문ìžì—´ Xì—서 모든 ASCII 문ìžë¥¼ 소문ìžë¡œ 변경한 문ìžì—´ ì‚¬ë³¸ì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - Revert database to last saved state - 마지막 ì €ìž¥ëœ ìƒíƒœë¡œ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ë˜ëŒë¦½ë‹ˆë‹¤ + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) 함수는 Xì˜ ì¢Œì¸¡ì˜ ê³µë°± ì—¬ë°±ì„ ì œê±°í•©ë‹ˆë‹¤. - - This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. - ì´ ì˜µì…˜ì€ í˜„ìž¬ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 마지막 ì €ìž¥ëœ ìƒíƒœë¡œ ë˜ëŒë¦´ 때 사용합니다. 저장 ì´í›„ì— ì´ë£¨ì–´ì§„ 모든 변경 ì‚¬í•­ì„ ë˜ëŒë¦½ë‹ˆë‹¤. + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) ltrim(X,Y) 함수는 Xì˜ ì¢Œì¸¡ì—서 Yì— ìžˆëŠ” 모든 문ìžë¥¼ 제거한 문ìžì—´ì„ 반환합니다. - - Write Changes - 변경사항 ë°˜ì˜í•˜ê¸° + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) 다중 ì¸ìžë¥¼ 제공하는 max() 함수는 주어진 ì¸ìž ê°’ 중ì—서 가장 í° ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤. 만약 주어진 ì¸ìž ì¤‘ì— NULL ê°’ì´ í•˜ë‚˜ë¼ë„ 있으면 NULLì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - Write changes to the database file - 변경 ì‚¬í•­ì„ ë°ì´í„°ë² ì´ìФ 파ì¼ì— ë°˜ì˜í•©ë‹ˆë‹¤ + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) 다중 ì¸ìžë¥¼ 제공하는 min() 함수는 주어진 ì¸ìž ê°’ 중ì—서 가장 ìž‘ì€ ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - This option is used to save changes to the database file. - ì´ ì˜µì…˜ì€ ë°ì´í„°ë² ì´ìФ 파ì¼ì— 변경 ì‚¬í•­ì„ ì €ìž¥í•˜ê¸° 위해 사용ë©ë‹ˆë‹¤. + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + Y) nullif(X,Y) 함수는 ë‘ ì¸ìž ê°’ì´ ì„œë¡œ 다르면 X를 반환하고 ë‘ ì¸ìž ê°’ì´ ê°™ìœ¼ë©´ NULLì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - Ctrl+S - Ctrl+S + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) printf(FORMAT,...) SQL 함수는 sqlite3_mprintf() C-언어 함수와 표준 C ë¼ì´ë¸ŒëŸ¬ë¦¬ì—ì„œì˜ printf() 함수처럼 ë™ìž‘합니다. - - Compact Database - ë°ì´í„°ë² ì´ìФ í¬ê¸° 줄ì´ê¸° + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) quote(X) 함수는 X를 SQL문 ì•ˆì— í¬í•¨ë˜ê¸°ì— ì ì ˆí•˜ë„ë¡ SQL 리터럴 문ìžì—´ë¡œ 반환합니다. - - Compact the database file, removing space wasted by deleted records - ì‚­ì œëœ ë ˆì½”ë“œ 등 ë‚­ë¹„ëœ ê³µê°„ì„ ì‚­ì œí•˜ì—¬ ë°ì´í„°ë² ì´ìФ íŒŒì¼ í¬ê¸°ë¥¼ 줄입니다 + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () random() 함수는 -9223372036854775808와 +9223372036854775807 사ì´ì˜ pseudo-ëžœë¤ ì •ìˆ˜ë¥¼ 반환합니다. - - - Compact the database file, removing space wasted by deleted records. - ì‚­ì œëœ ë ˆì½”ë“œ 등 ë‚­ë¹„ëœ ê³µê°„ì„ ì‚­ì œí•˜ì—¬ ë°ì´í„°ë² ì´ìФ íŒŒì¼ í¬ê¸°ë¥¼ 줄입니다. + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) randomblob(N) 함수는 psedo-ëžœë¤ ë°”ì´íŠ¸ë¥¼ í¬í•¨í•œ N-ë°”ì´íЏ blobì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - E&xit - 종료(&X) + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) replace(X,Y,Z) 함수는 문ìžì—´ Xì— ìžˆëŠ” 모든 문ìžì—´ Y를 Z로 치환한 문ìžì—´ì„ 반환합니다. - - Ctrl+Q - Ctrl+Q + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) round(X) 함수는 ë¶€ë™ì†Œìˆ˜ì  ê°’ X를 0ì˜ ìžë¦¬ì—서 반올림한 ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - Database from SQL file... - SQL 파ì¼ì—서 ë°ì´í„°ë² ì´ìФ 가져오기... + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) round(X,Y) 함수는 ë¶€ë™ì†Œìˆ˜ì  ê°’ X를 ì†Œìˆ˜ì  ìš°ì¸¡ì—서 Yìžë¦¬ì—서 반올림한 ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - Import data from an .sql dump text file into a new or existing database. - .sql ë¤í”„ 문ìžì—´ 파ì¼ì—서 ë°ì´í„°ë¥¼ 새 ë°ì´í„°ë² ì´ìŠ¤ë‚˜ 기존 ë°ì´í„°ë² ì´ìŠ¤ë¡œ 가져옵니다. + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X)ì€ Xì˜ ìš°ì¸¡ ê³µë°±ì„ ì œê±°í•©ë‹ˆë‹¤. - - This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. - ì´ ì˜µì…˜ì€ .sql ë¤í”„ 문ìžì—´ 파ì¼ì—서 ë°ì´í„°ë¥¼ 새 ë°ì´í„°ë² ì´ìŠ¤ë‚˜ 기존 ë°ì´í„°ë² ì´ìŠ¤ë¡œ 가져옵니다. SQL ë¤í”„ 파ì¼ì€ MySQLì´ë‚˜ PostgreSQL 등 ëŒ€ë¶€ë¶„ì˜ ë°ì´í„°ë² ì´ìФ 엔진ì—서 ìƒì„±í•  수 있습니다. + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) rtrim(X,Y) 함수는 Xì˜ ìš°ì¸¡ì—서 Yì— ìžˆëŠ” 모든 문ìžë¥¼ 삭제한 문ìžì—´ì„ 반환합니다. - - Table from CSV file... - í…Œì´ë¸”ì„ CSV 파ì¼ë¡œ 저장하기... + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) soundex(X) 함수는 문ìžì—´ Xì˜ ì‚¬ìš´ë±ìФ(Soundex) ì¸ì½”딩 문ìžì—´ì„ 반환합니다. - - Open a wizard that lets you import data from a comma separated text file into a database table. - 마법사를 사용하여 CSV 파ì¼(콤마로 필드가 나누어진 문ìžì—´ 파ì¼)ì—서 ë°ì´í„°ë² ì´ìФ í…Œì´ë¸”로 ë°ì´í„°ë¥¼ 가져올 수 있습니다. + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) substr(X,Y) 함수는 문ìžì—´ Xì—서 Y번째부터 ë까지 모든 문ìžì—´ì„ 반환합니다. - - Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. - 마법사를 사용하여 CSV 파ì¼(콤마로 필드가 나누어진 문ìžì—´ 파ì¼)ì—서 ë°ì´í„°ë² ì´ìФ í…Œì´ë¸”로 ë°ì´í„°ë¥¼ 가져올 수 있습니다. CSV 파ì¼ì€ ëŒ€ë¶€ë¶„ì˜ ë°ì´í„°ë² ì´ìŠ¤ì™€ 스프래드시트 애플리케ì´ì…˜(ì—‘ì…€ 등)ì—서 ìƒì„±í•  수 있습니다. + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) substr(X,Y,Z) 함수는 문ìžì—´ Xì—서 Y번째 문ìžë¶€í„° Zë¬¸ìž ìˆ˜ë§Œí¼ ë°˜í™˜í•©ë‹ˆë‹¤. - - Database to SQL file... - ë°ì´í„°ë² ì´ìŠ¤ë¥¼ SQL 파ì¼ë¡œ 저장하기... + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () total_changes() 함수는 현재 ë°ì´í„°ë² ì´ìФ ì—°ê²°ì´ ì—´ë¦° 후 INSERT, UPDATE, DELETE êµ¬ë¬¸ì— ì˜í•´ì„œ ë³€ê²½ëœ ë ˆì½”ë“œ í–‰ 수를 반환합니다. - - Export a database to a .sql dump text file. - ë°ì´í„°ë² ì´ìŠ¤ë¥¼ .sql ë¤í”„ 문ìžì—´ 파ì¼ë¡œ 내보내기. + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) 함수는 Xì˜ ì–‘ìª½ ê³µë°±ì„ ì œê±°í•©ë‹ˆë‹¤. - - This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. - ì´ ì˜µì…˜ì€ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ .sql ë¤í”„ 문ìžì—´ 파ì¼ë¡œ 내부낼 수 있습니다. SQL ë¤í”„ 파ì¼ì€ MySQLê³¼ PostgreSQL 등 ëŒ€ë¶€ë¶„ì˜ ë°ì´í„°ë² ì´ìФ 엔진ì—서 ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 재ìƒì„±í•˜ê¸° 위한 모든 필요한 ë°ì´í„°ë¥¼ í¬í•¨í•˜ê³  있습니다. + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) trim(X,Y) 함수는 Xì˜ ì–‘ëì—서 Yì— í•´ë‹¹í•˜ëŠ” 문ìžë“¤ì„ 삭제한 문ìžì—´ì„ 반환합니다. - - Table(s) as CSV file... - í…Œì´ë¸”ì„ CSV 파ì¼ë¡œ 저장하기... + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) typeof(X) 함수는 í‘œí˜„ì‹ Xì˜ ë°ì´í„° íƒ€ìž…ì„ ë‚˜íƒ€ë‚´ëŠ” 문ìžì—´ì„ 반환합니다. - - Export a database table as a comma separated text file. - ë°ì´í„°ë² ì´ìФ í…Œì´ë¸”ì„ CSV(콤마로 ë¶„ë¦¬ëœ ë¬¸ìžì—´ 파ì¼)로 내보내기. + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) unicode(X) 함수는 문ìžì—´ Xì˜ ì²« 글ìžì— 해당하는 ìˆ«ìž ìœ ë‹ˆì½”ë“œ í¬ì¸íŠ¸ë¥¼ 반환합니다. - - Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. - ë°ì´í„°ë² ì´ìФ í…Œì´ë¸”ì„ CSV(콤마로 ë¶„ë¦¬ëœ ë¬¸ìžì—´ 파ì¼)로 내보내기. 다른 ë°ì´í„°ë² ì´ìŠ¤ë‚˜ 스프래드시트 애플리케ì´ì…˜(ì—‘ì…€ 등)ì—서 가져와서 사용할 수 있습니다. + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) upper(X) 함수는 ìž…ë ¥ 문ìžì—´ Xì—서 ASCII 문ìžì— 해당하는 글ìžë¥¼ 대문ìžë¡œ 변경한 문ìžì—´ ì‚¬ë³¸ì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - Create Table... - í…Œì´ë¸” ìƒì„±... + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) zeroblob(N) 함수는 N ë°”ì´íŠ¸ì˜ 0x00으로 ì´ë£¨ì–´ì§„ BLOBì„ êµ¬ì„±í•˜ì—¬ 반환합니다. - - Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database - í…Œì´ë¸” ìƒì„± 마법사를 사용하여 ë°ì´í„°ë² ì´ìФì—서 새 í…Œì´ë¸”ì„ ìœ„í•œ ì´ë¦„ê³¼ 필드를 ì •ì˜í•  수 있습니다 + + + + + (timestring,modifier,modifier,...) + (timestring,modifier,modifier,...) - - Delete Table... - í…Œì´ë¸”ì„ ì‚­ì œ... + + (format,timestring,modifier,modifier,...) + (format,timestring,modifier,modifier,...) - - - Delete Table - í…Œì´ë¸” ì‚­ì œ + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) avg() 함수는 그룹ì—서 모든 NULLì´ ì•„ë‹Œ Xì˜ ê°’ì˜ í‰ê· ì„ 반환합니다. - - Open the Delete Table wizard, where you can select a database table to be dropped. - í…Œì´ë¸” ì‚­ì œ 마법사를 사용하여 ì„ íƒí•œ ë°ì´í„°ë² ì´ìФ í…Œì´ë¸”ì„ ì‚­ì œí•  수 있습니다. + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) count(X) 함수는 그룹ì—서 NULLì´ ì•„ë‹Œ 개수를 세어 반환합니다. - - Modify Table... - í…Œì´ë¸”ì„ ìˆ˜ì •... + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) group_concat() 함수는 Xì˜ ëª¨ë“  NULLì´ ì•„ë‹Œ ê°’ë“¤ì˜ ë¬¸ìžì—´ë¡œ í•©ì³ì„œ 반환합니다. - - Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields form a table, as well as modify field names and types. - í…Œì´ë¸” 편집 마법사를 사용하여 기존 í…Œì´ë¸”ì˜ ì´ë¦„ì„ ë³€ê²½í•˜ê±°ë‚˜ í…Œì´ë¸”ì˜ í•„ë“œë¥¼ 추가, ì‚­ì œ, 필드명 변경 ë° íƒ€ìž… ë³€ê²½ì„ í•  수 있습니다. + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) group_concat() 함수는 Xì˜ ëª¨ë“  NULLì´ ì•„ë‹Œ ê°’ë“¤ì˜ ë¬¸ìžì—´ë¡œ í•©ì³ì„œ 반환합니다. 만약 매개변수 Yê°€ 있다면 ê°’ë“¤ì„ ë¬¸ìžì—´ë¡œ í•©ì¹  때 구분ìžë¡œ 사용합니다. - - Create Index... - ì¸ë±ìФ ìƒì„±í•˜ê¸°... + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) max() 집계 함수는 그룹ì—서 모든 값들 중 가장 í° ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - Open the Create Index wizard, where it is possible to define a new index on an existing database table. - ì¸ë±ìФ ìƒì„± 마법사를 사용하여 기존 ë°ì´í„°ë² ì´ìФ í…Œì´ë¸”ì— ìƒˆ ì¸ë±ìŠ¤ë¥¼ ì •ì˜í•  수 있습니다. + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) min() 집계 함수는 그룹ì—서 NULLì´ ì•„ë‹Œ 모든 값들 중 가장 ìž‘ì€ ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - &Preferences... - 환경설정(&P)... + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) sum(x)ê³¼ total() 집계 함수는 ê·¸ë£¹ì˜ ëª¨ë“  NULLì´ ì•„ë‹Œ ê°’ë“¤ì˜ í•©ì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - - Open the preferences window. - í™˜ê²½ì„¤ì •ì°½ì„ ì—½ë‹ˆë‹¤. + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () 현재 파티션 ë‚´ì˜ í–‰ 번호입니다. í–‰ì€ ì°½ ì •ì˜ì˜ ORDER BY ì ˆì— ì •ì˜ëœ 순서대로 1부터 시작하거나 ìž„ì˜ì˜ 순서로 번호가 지정ë©ë‹ˆë‹¤. - - &DB Toolbar - DB 툴바(&D) + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () ê° ê·¸ë£¹ì˜ ì²« 번째 í”¼ì–´ì˜ row_number ()-ê°„ê²©ì´ ìžˆëŠ” 현재 í–‰ì˜ ìˆœìœ„. ORDER BY ì ˆì´ ì—†ìœ¼ë©´ 모든 í–‰ì´ í”¼ì–´ë¡œ 간주ë˜ê³  ì´ í•¨ìˆ˜ëŠ” í•­ìƒ 1ì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - Shows or hides the Database toolbar. - ë°ì´í„°ë² ì´ìФ 툴바를 ë³´ì´ê±°ë‚˜ 숨ê¹ë‹ˆë‹¤. + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () 파티션 ë‚´ 현재 í–‰ì˜ í”¼ì–´ 그룹 번호 - ê°„ê²©ì´ ì—†ëŠ” 현재 í–‰ì˜ ìˆœìœ„, íŒŒí‹°ì…˜ì€ ì°½ ì •ì˜ì˜ ORDER BYì ˆì— ì •ì˜ëœ 순서대로 1부터 시작ë©ë‹ˆë‹¤. ORDER BY ì ˆì´ ì—†ìœ¼ë©´ 모든 í–‰ì´ í”¼ì–´ë¡œ 간주ë˜ì–´ ì´ í•¨ìˆ˜ëŠ” í•­ìƒ 1ì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - What's This? - ì´ í”„ë¡œê·¸ëž¨ì€? + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () ì´ë¦„ì—ë„ ë¶ˆêµ¬í•˜ê³  ì´ í•¨ìˆ˜ëŠ” í•­ìƒ (rank - 1)/(partition-rows - 1)ê³¼ ê°™ì€ 0.0ì—서 1.0 사ì´ì˜ ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤. 여기서 rank는 내장 ì°½ 함수 rank() ë° partitionì—서 반환한 값입니다. rows는 íŒŒí‹°ì…˜ì˜ ì´ í–‰ 수 입니다. íŒŒí‹°ì…˜ì— í–‰ì´ í•˜ë‚˜ë§Œ í¬í•¨ëœ 경우 ì´ í•¨ìˆ˜ëŠ” 0.0ì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - Shift+F1 - Shift+F1 + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () ëˆ„ì  ë¶„í¬. row-number/partition-rows로 계산ë©ë‹ˆë‹¤. 여기서 row-number는 ê·¸ë£¹ì˜ ë§ˆì§€ë§‰ í”¼ì–´ì— ëŒ€í•´ row_number()ì—서 반환한 ê°’ì´ê³  partition-rows는 íŒŒí‹°ì…˜ì˜ í–‰ 수입니다. - - &About... - ì •ë³´(&A)... + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) ì¸ìž Nì€ ì •ìˆ˜ë¡œ 취급ë©ë‹ˆë‹¤. ì´ í•¨ìˆ˜ëŠ” ORDER BY êµ¬ë¬¸ì´ ìžˆë‹¤ë©´ ê·¸ 순서대로, 없다면 ìž„ì˜ì˜ 순서로 가능하면 균등하게 Nê°œì˜ ê·¸ë£¹ìœ¼ë¡œ 나누고 ê° ê·¸ë£¹ì— 1부터 N 사ì´ì˜ 정수를 할당합니다. 필요한 경우 í° ê·¸ë£¹ì´ ë¨¼ì € 나옵니다. ì´ í•¨ìˆ˜ëŠ” 현재 í–‰ì´ ì†í•´ìžˆëŠ” ê·¸ë£¹ì´ í• ë‹¹ëœ ì •ìˆ˜ë¥¼ 반환합니다. - - &Recently opened - 최근 ì—´ì—ˆë˜ íŒŒì¼ë“¤(&R) + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) íŒŒí‹°ì…˜ì˜ ì´ì „ í–‰ì— ëŒ€í•´ expr 표현ì‹ì„ í‰ê°€í•œ 결과를 반환합니다. ë˜ëŠ” ì´ì „ í–‰ì´ ì—†ëŠ” 경우(현재 í–‰ì´ ì²«ë²ˆì§¸ì¼ ë•Œ) NULL 반환ë©ë‹ˆë‹¤. - - Open &tab - 탭 열기(&T) + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr,offset) offset ì¸ìˆ˜ê°€ 제공ë˜ë©´ ìŒì´ 아닌 정수여야합니다. ì´ ê²½ìš° ë°˜í™˜ëœ ê°’ì€ íŒŒí‹°ì…˜ ë‚´ì˜ í˜„ìž¬ í–‰ ì´ì „ì— í–‰ 오프셋 í–‰ì— ëŒ€í•´ expr를 í‰ê°€í•œ 결과입니다. ì˜¤í”„ì…‹ì´ 0ì´ë©´ exprì´ í˜„ìž¬ í–‰ì— ëŒ€í•´ í‰ê°€ë©ë‹ˆë‹¤. 현재 í–‰ ì•žì— í–‰ 오프셋 í–‰ì´ ì—†ìœ¼ë©´ NULLì´ ë°˜í™˜ë©ë‹ˆë‹¤. - - Ctrl+T - Ctrl+T + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,offset,default) defaultë„ ì œê³µë˜ë©´ offset으로 ì‹ë³„ëœ í–‰ì´ ì¡´ìž¬í•˜ì§€ ì•Šì•˜ì„ ë•Œ NULL 대신 반환ë©ë‹ˆë‹¤. - - &Execute SQL - SQL 실행하기(&E) + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) íŒŒí‹°ì…˜ì˜ ë‹¤ìŒ í–‰ì— ëŒ€í•´ expr 표현ì‹ì„ í‰ê°€í•œ 결과를 반환합니다. ë˜ëŠ” ë‹¤ìŒ í–‰ì´ ì—†ëŠ” 경우(현재 í–‰ì´ ë§ˆì§€ë§‰ í–‰ì¼ ë•Œ) NULLì´ ë°˜í™˜ë©ë‹ˆë‹¤. - - Execute SQL [F5, Ctrl+Return] - SQL 실행하기 [F5, Ctrl+엔터] + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,offset) offset ì¸ìˆ˜ê°€ 제공ë˜ë©´ ìŒì´ 아닌 정수여야 합니다. ì´ ê²½ìš° ë°˜í™˜ëœ ê°’ì€ íŒŒí‹°ì…˜ ë‚´ì—서 현재 í–‰ ë’¤ì— ìžˆëŠ” í–‰ 오프셋 í–‰ì— ëŒ€í•´ exprì„ í‰ê°€í•œ 결과입니다. ì˜¤í”„ì…‹ì´ 0ì´ë©´ exprì´ í˜„ìž¬ í–‰ì— ëŒ€í•´ í‰ê°€ë©ë‹ˆë‹¤. 현재 í–‰ ë’¤ì— í–‰ 오프셋 í–‰ì´ ì—†ìœ¼ë©´ NULLì´ ë°˜í™˜ë©ë‹ˆë‹¤. - - Open SQL file - SQL íŒŒì¼ ì—´ê¸° + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr)ì´ ë‚´ìž¥ ì°½ 함수는 집계 ì°½ 함수와 ë™ì¼í•œ ë°©ì‹ìœ¼ë¡œ ê° í–‰ì˜ ì°½ í”„ë ˆìž„ì„ ê³„ì‚°í•©ë‹ˆë‹¤. ê° í–‰ì˜ ì°½ 프레임ì—서 첫 번째 í–‰ì— ëŒ€í•´ í‰ê°€ëœ exprì˜ ê°’ì„ ë¦¬í„´í•©ë‹ˆë‹¤. - - - - Save SQL file - SQL íŒŒì¼ ì €ìž¥í•˜ê¸° + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr)ì´ ë‚´ìž¥ ì°½ 함수는 집계 ì°½ 함수와 ë™ì¼í•œ ë°©ì‹ìœ¼ë¡œ ê° í–‰ì˜ ì°½ í”„ë ˆìž„ì„ ê³„ì‚°í•©ë‹ˆë‹¤. ê° í–‰ì˜ ì°½ 프레임ì—서 마지막 í–‰ì— ëŒ€í•´ í‰ê°€ ëœ exprì˜ ê°’ì„ ë¦¬í„´í•©ë‹ˆë‹¤. - - Load extension - 확장기능 불러오기 + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr,N)ì´ ë‚´ìž¥ ì°½ 함수는 집계 ì°½ 함수와 ë™ì¼í•œ ë°©ì‹ìœ¼ë¡œ ê° í–‰ì˜ ì°½ í”„ë ˆìž„ì„ ê³„ì‚°í•©ë‹ˆë‹¤. ì°½ í”„ë ˆìž„ì˜ N í–‰ì— ëŒ€í•´ í‰ê°€ ëœ exprì˜ ê°’ì„ ë¦¬í„´í•©ë‹ˆë‹¤. í–‰ì€ ORDER BY ì ˆì— ì •ì˜ ëœ ìˆœì„œëŒ€ë¡œ 1부터 시작하여 ì°½ 프레임 ë‚´ì—서 번호가 매겨집니다. 그렇지 않으면 ìž„ì˜ì˜ 순서로 번호가 매겨집니다. íŒŒí‹°ì…˜ì— N 번째 í–‰ì´ ì—†ìœ¼ë©´ NULLì´ ë°˜í™˜ë©ë‹ˆë‹¤. - - Execute current line - 현재 í–‰ 실행하기 + + (X) Return the arccosine of X. The result is in radians. + (X) Xì˜ ì•„í¬ì½”사ì¸ì„ 반환합니다. 결과는 ë¼ë””안 단위입니다. - - Execute current line [Ctrl+E] - 현재 í–‰ 실행하기 [Ctrl+E] + + (X) Return the hyperbolic arccosine of X. + (X) Xì˜ ìŒê³¡ì„  ì•„í¬ì½”사ì¸ì„ 반환합니다. - - Ctrl+E - Ctrl+E + + (X) Return the arcsine of X. The result is in radians. + (X) Xì˜ ì•„í¬ì‚¬ì¸ì„ 반환합니다. 결과는 ë¼ë””안 단위입니다. - - Export as CSV file - CSV 파ì¼ë¡œ 내보내기 + + (X) Return the hyperbolic arcsine of X. + (X) Xì˜ ìŒê³¡ì„  ì•„í¬ì‚¬ì¸ì„ 반환합니다. - - Export table as comma separated values file - í…Œì´ë¸”ì„ CSV 파ì¼ë¡œ 내보내기 + + (X) Return the arctangent of X. The result is in radians. + (X) Xì˜ ì•„í¬íƒ„젠트를 반환합니다. 결과는 ë¼ë””안 단위입니다. - - &Wiki... - 위키(&W)... + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + (X,Y) Y/Xì˜ ì•„í¬íƒ„젠트를 반환합니다. 결과는 ë¼ë””안입니다. ê·¸ 결과는 X와 Yì˜ ë¶€í˜¸ì— ë”°ë¼ ì˜¬ë°”ë¥¸ ì‚¬ë¶„ë©´ì— ë°°ì¹˜ë©ë‹ˆë‹¤. - - Bug &report... - 버그 ì‹ ê³ (&R)... + + (X) Return the hyperbolic arctangent of X. + (X) Xì˜ ìŒê³¡ì„  ì•„í¬íƒ„젠트를 반환합니다. - - Web&site... - 웹사ì´íЏ(&S)... + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + (X) X보다 í¬ê±°ë‚˜ ê°™ì€ í‘œí˜„ 가능한 첫 번째 정수 ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤. Xì˜ ì–‘ìˆ˜ ê°’ì˜ ê²½ìš° ì´ ë£¨í‹´ì€ 0ì—서 반올림합니다. ìŒìˆ˜ X ê°’ì˜ ê²½ìš° ì´ ë£¨í‹´ì€ 0으로 반올림합니다. - - Save Project - 프로ì íЏ 저장하기 + + (X) Return the cosine of X. X is in radians. + (X) Xì˜ ì½”ì‚¬ì¸ ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤. X는 ë¼ë””안 단위입니다. - - - Save the current session to a file - 현재 ì„¸ì…˜ì„ íŒŒì¼ë¡œ 저장하기 + + (X) Return the hyperbolic cosine of X. + (X) Xì˜ ìŒê³¡ì„  코사ì¸ì„ 반환합니다. - - Open Project - 프로ì íЏ 열기 + + (X) Convert value X from radians into degrees. + (X) ê°’ X를 ë¼ë””안ì—서 ê°ë„로 변환합니다. - - - Load a working session from a file - 파ì¼ì—서 작업 세션 불러오기 + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + (X) 계산 e(오ì¼ëŸ¬ 수, 약 2.71828182845905)를 X로 거듭제곱합니다. - - &Attach Database - ë°ì´í„°ë² ì´ìФ 합치기(&A) + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + (X) X보다 작거나 ê°™ì€ ì²« 번째 표현 가능한 정수 ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤. ì–‘ìˆ˜ì˜ ê²½ìš° ì´ í•¨ìˆ˜ëŠ” 0으로 반올림합니다. ìŒìˆ˜ì˜ 경우 ì´ í•¨ìˆ˜ëŠ” 0ì—서 반올림합니다. - - Set Encryption - 암호화 + + (X) Return the natural logarithm of X. + (X) Xì˜ ìžì—° 로그를 반환합니다. - - - Save SQL file as - SQL íŒŒì¼ ë‹¤ë¦„ì´ë¦„으로 저장하기 + + (B,X) Return the base-B logarithm of X. + (B,X) Xì˜ ë°‘ì´ Bì¸ ë¡œê·¸ë¥¼ 반환합니다. - - &Browse Table - í…Œì´ë¸” 보기(&B) + + + (X) Return the base-10 logarithm for X. + (X) Xì— ëŒ€í•œ ë°‘ì´ 10ì¸ ë¡œê·¸ë¥¼ 반환합니다. - - Copy Create statement - ìƒì„± 구문 복사하기 + + (X) Return the logarithm base-2 for the number X. + (X) ìˆ«ìž Xì— ëŒ€í•´ ë°‘ì´ 2ì¸ ë¡œê·¸ë¥¼ 반환합니다. - - Copy the CREATE statement of the item to the clipboard - í•­ëª©ì˜ ìƒì„± êµ¬ë¬¸ì„ í´ë¦½ë³´ë“œì— 복사합니다 + + (X,Y) Return the remainder after dividing X by Y. + (X,Y) X를 Y로 나눈 나머지를 반환합니다. - - Ctrl+Return - Ctrl+리턴 + + () Return an approximation for Ï€. + () Ï€ì— ëŒ€í•œ ê·¼ì‚¬ê°’ì„ ë°˜í™˜í•©ë‹ˆë‹¤. - - Ctrl+L - Ctrl+L + + + (X,Y) Compute X raised to the power Y. + (X,Y) Xì˜ ê±°ë“­ì œê³±ì„ ê³„ì‚°í•©ë‹ˆë‹¤. - - Ctrl+P - Ctrl+P + + (X) Convert X from degrees into radians. + (X) X를 ë„ì—서 ë¼ë””안으로 변환합니다. - - Ctrl+D - Ctrl+D + + (X) Return the sine of X. X is in radians. + (X) Xì˜ ì‚¬ì¸ì„ 반환합니다. X는 ë¼ë””안 단위입니다. - - Ctrl+I - Ctrl+I + + (X) Return the hyperbolic sine of X. + (X) Xì˜ ìŒê³¡ì„  사ì¸ì„ 반환합니다. - - Database encoding - ë°ì´í„°ë² ì´ìФ ì¸ì½”딩 + + (X) Return the square root of X. NULL is returned if X is negative. + (X) Xì˜ ì œê³±ê·¼ì„ ë°˜í™˜í•©ë‹ˆë‹¤. Xê°€ ìŒìˆ˜ì´ë©´ NULLì´ ë°˜í™˜ë©ë‹ˆë‹¤. - - Database is encrypted using SQLCipher - ë°ì´í„°ë² ì´ìŠ¤ëŠ” SQLCipher를 사용해서 암호화ë©ë‹ˆë‹¤ + + (X) Return the tangent of X. X is in radians. + (X) Xì˜ íƒ„ì  íŠ¸ë¥¼ 반환합니다. X는 ë¼ë””안 단위입니다. - - - Choose a database file - ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” + + (X) Return the hyperbolic tangent of X. + (X) Xì˜ ìŒê³¡íƒ„젠트를 반환합니다. - - SQLite database files (*.db *.sqlite *.sqlite3 *.db3);;All files (*) - SQLite ë°ì´í„°ë² ì´ìФ 파ì¼(*.db *.sqlite *.sqlite3 *.db3);;모든 íŒŒì¼ (*) + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + (X) 0ì—서 가장 멀리 떨어져 있는 X와 0(í¬í•¨) 사ì´ì˜ 표현 가능한 정수를 반환합니다. ë˜ëŠ” 다시 ë§í•´ì„œ Xì˜ ì •ìˆ˜ ë¶€ë¶„ì„ 0으로 반올림하여 반환합니다. + + + SqliteTableModel - - Invalid file format. - 올바르지 ì•Šì€ íŒŒì¼ í¬ë§·ìž…니다. + + reading rows + í–‰ì„ ì½ëŠ” 중 - - - - - Choose a filename to save under - 저장하려는 파ì¼ëª…ì„ ê³ ë¥´ì„¸ìš” + + loading... + 로딩 중... + - - Error adding record: - - 레코드 추가 ì—러: + + References %1(%2) +Hold %3Shift and click to jump there + 참조 %1(%2) +%3Shift를 누른 ìƒíƒœì—서 ì´ë™í•˜ê³ ìž 하는 ê³³ì„ í´ë¦­í•˜ì„¸ìš” - - Error deleting record: + + Error changing data: %1 - 레코드 추가 ì—러: + ë°ì´í„° 수정 ì—러: %1 - - Please select a record first - 레코드를 먼저 ì„ íƒí•˜ì„¸ìš” + + retrieving list of columns + ì»¬ëŸ¼ì€ í•„ë“œë¡œ 표현합니다. + 필드 ëª©ë¡ ê°€ì ¸ì˜¤ê¸° - - %1 - %2 of %3 - %1 - %2 of %3 + + Fetching data... + ë°ì´í„°ë¥¼ 가져오는 중입니다... - - - There is no database opened. Please open or create a new database file. - ë°ì´í„°ë² ì´ìŠ¤ê°€ 열려있지 않습니다. ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ì—´ë˜ê°€ 새 ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ìƒì„±í•˜ì„¸ìš”. + + + Cancel + 취소 + + + TableBrowser - - Are you sure you want to delete the %1 '%2'? -All data associated with the %1 will be lost. - %1 '%2'를 ì •ë§ë¡œ 삭제하나요? -%1와 ê´€ë ¨ëœ ëª¨ë“  ë°ì´í„°ê°€ ì‚­ì œë©ë‹ˆë‹¤. + + Browse Data + ë°ì´í„° íƒìƒ‰ - - Error: could not delete the %1. Message from database engine: -%2 - ì—러: %1ì„(를) 삭제할 수 없습니다. 메시지: -%2 + + &Table: + í…Œì´ë¸”(&T): - - There is no database opened. - 열려있는 ë°ì´í„°ë² ì´ìŠ¤ê°€ 없습니다. + + Select a table to browse data + íƒìƒ‰í•˜ë ¤ëŠ” ë°ì´í„°ê°€ 있는 í…Œì´ë¸”ì„ ì„ íƒí•˜ì„¸ìš” - - %1 Rows returned from: %3 (took %2ms) - %3ì—서 %1 í–‰ì´ ë¦¬í„´ë˜ì—ˆìŠµë‹ˆë‹¤.(%2ms 걸림) + + Use this list to select a table to be displayed in the database view + 리스트ì—서 í…Œì´ë¸”ì„ ì„ íƒí•˜ë©´ ë°ì´í„°ë² ì´ìФ ë·°ì—서 ë³¼ 수 있습니다 - - Error executing query: %1 - 쿼리 실행 ì—러: %1 + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + ì´ê²ƒì€ ë°ì´í„°ë² ì´ìŠ¤ì˜ í…Œì´ë¸” 뷰입니다. ë‹¤ìŒ ìž‘ì—…ì„ ìˆ˜í–‰í•  수 있습니다: + - ê°’ì„ ì¸ë¼ì¸ìœ¼ë¡œ 편집하기 위한 ìž‘ì„±ì„ ì‹œìž‘í•©ë‹ˆë‹¤. + - ì…€ 편집기 ì°½ì—서 ë‚´ìš©ì„ íŽ¸ì§‘í•˜ë ¤ë©´ 레코드를 ë”블 í´ë¦­í•©ë‹ˆë‹¤. + - ì…€ ë‚´ìš©ì„ NULL 값으로 삭제하려면 Alt+Del + - Ctrl + "는 현재 레코드를 복제합니다. + - ìœ„ì˜ ì…€ì—서 ê°’ì„ ë³µì‚¬í•˜ë ¤ë©´ Ctrl + ' + - 표준 ì„ íƒ ë° ë³µì‚¬ / 붙여넣기 작업. - - Query executed successfully: %1 (took %2ms) - 쿼리가 성공ì ìœ¼ë¡œ 실행ë˜ì—ˆìŠµë‹ˆë‹¤: %1 (%2ms 걸림) + + Text pattern to find considering the checks in this frame + ì´ í”„ë ˆìž„ 안ì—서 확ì¸í•˜ê¸° 위해 ê²€ìƒ‰í•˜ê³ ìž í•˜ëŠ” 문ìžì—´ 패턴 - - Choose a text file - 문ìžì—´ 파ì¼ì„ 고르세요 + + Find in table + í…Œì´ë¸”ì—서 찾기 - - Text files(*.csv *.txt);;All files(*) - 문ìžì—´ 파ì¼(*.csv *.txt);;모든 파ì¼(*) + + Find previous match [Shift+F3] + ì´ì „ 찾기 [Shift+F3] - - Import completed - 가져오기가 완료ë˜ì—ˆìŠµë‹ˆë‹¤ + + Find previous match with wrapping + ëž©í•‘ëœ ì´ì „ ì¼ì¹˜ë‚´ì—­ 검색하기 - - Are you sure you want to undo all changes made to the database file '%1' since the last save? - ì •ë§ë¡œ ë°ì´í„°ë² ì´ìФ íŒŒì¼ '%1'ì˜ ëª¨ë“  변경 ì‚¬í•­ì„ ë§ˆì§€ë§‰ ì €ìž¥ëœ ìƒíƒœë¡œ ë˜ëŒë¦½ë‹ˆê¹Œ? + + Shift+F3 + - - Choose a file to import - 가져올 파ì¼ì„ 고르세요 + + Find next match [Enter, F3] + ë‹¤ìŒ ì°¾ê¸° [Enter, F3] - - - - Text files(*.sql *.txt);;All files(*) - 문ìžì—´ 파ì¼(*.csv *.txt);;모든 파ì¼(*) + + Find next match with wrapping + 랩핑(Wrapping)으로 ë‹¤ìŒ ì°¾ê¸° - - Do you want to create a new database file to hold the imported data? -If you answer no we will attempt to import the data in the SQL file to the current database. - ë°ì´í„°ë¥¼ 가져와서 새 ë°ì´í„°ë² ì´ìФ 파ì¼ì„ ìƒì„±í•˜ê³  ì‹¶ì€ê°€ìš”? -아니ë¼ë©´ SQL 파ì¼ì˜ ë°ì´í„°ë¥¼ 현재 ë°ì´í„°ë² ì´ìŠ¤ë¡œ 가져오기를 í•  것입니다. + + F3 + - - File %1 already exists. Please choose a different name. - íŒŒì¼ %1ì´ ì´ë¯¸ 존재합니다. 다른 파ì¼ëª…ì„ ê³ ë¥´ì„¸ìš”. + + The found pattern must match in letter case + ëŒ€ì†Œë¬¸ìž ì¼ì¹˜ 검색패턴 - - Error importing data: %1 - ë°ì´í„° 가져오기 ì—러: %1 + + Case Sensitive + ëŒ€ì†Œë¬¸ìž ì¼ì¹˜ - - Import completed. - 가져오기가 완료ë˜ì—ˆìŠµë‹ˆë‹¤. + + The found pattern must be a whole word + 온전한 ë‚±ë§ ì¼ì¹˜ 검색패턴 - - Delete View - ë·° 삭제하기 + + Whole Cell + ì „ì²´ ì…€ - - Delete Trigger - 트리거 삭제하기 + + Interpret search pattern as a regular expression + 검색 íŒ¨í„´ì„ ì •ê·œ 표현ì‹ìœ¼ë¡œ í•´ì„ - - Delete Index - ì¸ë±ìФ 삭제하기 + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>ì„ íƒí•˜ë©´ 찾으려는 íŒ¨í„´ì´ UNIX ì •ê·œì‹ìœ¼ë¡œ í•´ì„ë©ë‹ˆë‹¤. <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>ì„ ì°¸ê³ í•˜ì„¸ìš”.</p></body></html> - - &%1 %2 - &%1 %2 + + Regular Expression + ì •ê·œ í‘œí˜„ì‹ - - Setting PRAGMA values will commit your current transaction. -Are you sure? - PRAGMA ì„¤ì •ì„ ë³€ê²½í•˜ë ¤ë©´ ì—¬ëŸ¬ë¶„ì˜ í˜„ìž¬ íŠ¸ëžœìž­ì…˜ì„ ì»¤ë°‹í•´ì•¼í•©ë‹ˆë‹¤. -ë™ì˜í•˜ì‹­ë‹ˆê¹Œ? + + + Close Find Bar + 검색바 닫기 - - Select SQL file to open - ì—´ SQL 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” + + Text to replace with + 바꾸려는 í…스트 - - Select file name - íŒŒì¼ ì´ë¦„ì„ ì„ íƒí•˜ì„¸ìš” + + Replace with + ~로 바꾸기 - - Select extension file - íŒŒì¼ í™•ìž¥ìžë¥¼ ì„ íƒí•˜ì„¸ìš” + + Replace next match + ì¼ì¹˜í•˜ëŠ” ë‹¤ìŒ í…스트 바꾸기 - - Extensions(*.so *.dll);;All files(*) - 확장기능 파ì¼ë“¤(*.so *.dll);;모든 파ì¼(*) + + + Replace + 바꾸기 - - Extension successfully loaded. - í™•ìž¥ê¸°ëŠ¥ì„ ì„±ê³µì ìœ¼ë¡œ 불러왔습니다. + + Replace all matches + ì¼ì¹˜í•˜ëŠ” 모든 í…스트 바꾸기 - - - Error loading extension: %1 - í™•ìž¥ê¸°ëŠ¥ì„ ë¶ˆëŸ¬ì˜¤ê¸° ì—러: %1 + + Replace all + ëª¨ë‘ ë°”ê¾¸ê¸° - - Don't show again - 다시 ë³´ì§€ 않기 + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>첫 페ì´ì§€ë¡œ 갑니다.</p></body></html> - - New version available. - ì´ìš© 가능한 새 ë²„ì „ì´ ìžˆìŠµë‹ˆë‹¤. + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>í…Œì´ë¸” ë·° 맨 위로 가기 위해서는 ì´ ë²„íŠ¼ì„ í´ë¦­í•˜ì„¸ìš”.</p></body></html> - - A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. - ì´ìš© 가능한 새 ë²„ì „ì´ ìžˆìŠµë‹ˆë‹¤ (%1.%2.%3).<br/><br/><a href='%4'>%4</a>ì—서 다운로드하세요. + + |< + |< - - Choose a axis color - ì¶•ì˜ ìƒ‰ê¹”ì„ ê³ ë¥´ì„¸ìš” + + Scroll one page upwards + 한 페ì´ì§€ 위로 스í¬ë¡¤í•©ë‹ˆë‹¤ - - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;모든 파ì¼(*) + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>위 í…Œì´ë¸” ë·°ì—서 레코드를 한 페ì´ì§€ 앞으로 가려면 ì´ ë²„íŠ¼ì„ í´ë¦­í•˜ì„¸ìš”.</p></body></html> - - Choose a file to open - 불러올 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” + + < + < - - - DB Browser for SQLite project file (*.sqbpro) - DB Browser for SQLite 프로ì íЏ íŒŒì¼ (*.sqbpro) + + 0 - 0 of 0 + 0 - 0 of 0 - - - PreferencesDialog - - Preferences - 환경설정 + + Scroll one page downwards + 한 페ì´ì§€ 아래로 스í¬ë¡¤í•©ë‹ˆë‹¤ - - &General - ì¼ë°˜(&G) + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>위 í…Œì´ë¸” ë·°ì—서 레코드를 한 페ì´ì§€ 뒤로 가려면 ì´ ë²„íŠ¼ì„ í´ë¦­í•˜ì„¸ìš”.</p></body></html> - - Remember last location - 마지막 위치를 기억 + + > + > - - Always use this location - í•­ìƒ ì´ ìœ„ì¹˜ë¥¼ 사용 + + Scroll to the end + 마지막 페ì´ì§€ë¡œ ì´ë™ - - Remember last location for session only - ê°™ì€ ì„¸ì…˜ì—서만 마지막 위치를 기 ì–µ + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>í…Œì´ë¸” ë·° 맨 아래로 가기 위해서는 ì´ ë²„íŠ¼ì„ í´ë¦­í•˜ì„¸ìš”.</p></body></html> - - ... - ... + + >| + >| - - Default &location - 기본 위치(&L) + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>특정 레코드로 ì´ë™í•˜ë ¤ë©´ 여기를 í´ë¦­í•˜ì„¸ìš”</p></body></html> - - Lan&guage - 언어(&G) + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>ì´ ë²„íŠ¼ì€ íŠ¹ì • ìœ„ì¹˜ì˜ ë ˆì½”ë“œ 넘버로 가기 위해서 사용합니다.</p></body></html> - - Automatic &updates - ìžë™ ì—…ë°ì´íЏ(&U) + + Go to: + 특정 레코드 행으로 가기: - - - enabled - 사용하기 + + Enter record number to browse + ì°¾ì„ ë ˆì½”ë“œ í–‰ 번호를 입력하세요 - - &Database - ë°ì´í„°ë² ì´ìФ(&D) + + Type a record number in this area and click the Go to: button to display the record in the database view + 레코드 í–‰ 번호를 입력하고 '특정 레코드 행으로 가기:' ë²„íŠ¼ì„ í´ë¦­í•˜ë©´ ë°ì´í„°ë² ì´ìФ ë·°ì— ë ˆì½”ë“œê°€ 표시ë©ë‹ˆë‹¤ - - Database &encoding - ë°ì´í„°ë² ì´ìФ ì¸ì½”딩(&E) + + 1 + 1 - - Open databases with foreign keys enabled. - 외래키 ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ë©° ë°ì´í„°ë² ì´ìŠ¤ë¥¼ 엽니다. + + Show rowid column + ì»¬ëŸ¼ì˜ rowid 표시하기 - - &Foreign keys - 외래키(&F) + + Toggle the visibility of the rowid column + rowid ì»¬ëŸ¼ì„ í‘œì‹œí•˜ê±°ë‚˜ 숨ê¹ë‹ˆë‹¤ - - Remove line breaks in schema view - 스키마 ë·°ì—서 í–‰ 나눔 삭제하기 + + Unlock view editing + ë·° 수정 잠금 해제하기 - - &Prefetch block size - 프리패치(&Prefetch) ë¸”ë¡ ì‚¬ì´ì¦ˆ + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + ìˆ˜ì •ì„ ìœ„í•˜ì—¬ 현재 ë·°ì˜ ìž ê¸ˆì„ í•´ì œí•©ë‹ˆë‹¤. 하지만 ìˆ˜ì •ì„ ìœ„í•´ì„œëŠ” ì ì ˆí•œ 트리거가 필요할 것입니다. - - Data &Browser - ë°ì´í„° 보기(&B) + + Edit display format + 표시 í˜•ì‹ ë³€ê²½ - - NULL fields - NULL 필드 + + Edit the display format of the data in this column + ì´ ì»¬ëŸ¼ì— ìžˆëŠ” ë°ì´í„°ì˜ 표시 형ì‹ì„ 수정합니다 - - Text &colour - 글ìžìƒ‰(&C) + + + New Record + 새 레코드 - - &Text - 문ìžì—´(&T) + + + Insert a new record in the current table + 현재 í…Œì´ë¸”ì— ìƒˆ 레코드를 추가합니다 - - Bac&kground colour - 배경색(&K) + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>ì´ ë²„íŠ¼ì€ ë°ì´í„°ë² ì´ìŠ¤ì— ìƒˆ 레코드를 ìƒì„±í•©ë‹ˆë‹¤.</p><ul><li><span style=" font-weight:600;">새 레코드</span>: ë°ì´í„°ë² ì´ìŠ¤ì˜ ê¸°ë³¸ê°’ìœ¼ë¡œ 새 레코드를 ìƒì„±í•©ë‹ˆë‹¤.</li><li><span style=" font-weight:600;">ê°’ 삽입...</span>: ë°ì´í„°ë² ì´ìŠ¤ì— ê°’ì„ ì‚½ìž…í•˜ê¸° ì „ì— ê°’ì„ ìž…ë ¥í•  수 있는 대화ìƒìžë¥¼ 엽니다. ì´ë¥¼ 통해 다양한 제약 ì¡°ê±´ì— ì¶©ì¡±í•˜ëŠ” ê°’ì„ ìž…ë ¥í•  수 있습니다. ì´ëŸ¬í•œ 제약으로 ì¸í•´ <span style=" font-weight:600;">새 레코드</span> ì˜µì…˜ì´ ì‹¤íŒ¨í•œ 경우ì—ë„ ì´ ëŒ€í™”ìƒìžê°€ 열립니다.</li></ul></body></html> - - &SQL - &SQL + + + Delete Record + 레코드 ì‚­ì œ - - Settings name - 설정 ì´ë¦„ + + Delete the current record + 현재 레코드 삭제하기 - - Context - ë‚´ìš© + + + This button deletes the record or records currently selected in the table + ì´ ë²„íŠ¼ì€ í…Œì´ë¸”ì—서 현재 ì„ íƒëœ 레코드를 삭제합니다 - - Colour - 색깔 + + + Insert new record using default values in browsed table + 현재 íƒìƒ‰í•œ í…Œì´ë¸”ì˜ ê¸°ë³¸ê°’ì„ ì‚¬ìš©í•˜ì—¬ 새 레코드 삽입 - - Bold - 볼드 + + Insert Values... + ê°’ 추가... - - Italic - ì´íƒ¤ë¦­ + + + Open a dialog for inserting values in a new record + 새 ë ˆì½”ë“œì˜ ê°’ì„ ì‚½ìž…í•˜ê¸° 위한 대화ìƒìžë¥¼ 엽니다 - - Underline - 밑줄 + + Export to &CSV + CSV로 내보내기(&C) - - Keyword - 키워드 + + + Export the filtered data to CSV + 필러ë§ëœ ë°ì´í„°ë¥¼ CSV로 내보내기 - - function - 기능 + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + ì´ ë²„íŠ¼ì€ í˜„ìž¬ 표시ëœëŒ€ë¡œ(í•„í„°, 표시 í˜•ì‹ ë° ì—´ 순서) íƒìƒ‰ëœ í…Œì´ë¸”ì˜ ë°ì´í„°ë¥¼ CSV 파ì¼ë¡œ 내보냅니다. - - Function - 함수 + + Export to &JSON + &JSON으로 내보내기 - - Table - í…Œì´ë¸” + + + Export the filtered data to JSON + í•„í„°ë§ëœ ë°ì´í„°ë¥¼ JSON으로 내보내기 - - Comment - ì£¼ì„ + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + ì´ ë²„íŠ¼ì€ ê²€ìƒ‰ëœ í…Œì´ë¸”ì˜ ë°ì´í„°ë¥¼ 현재 í‘œì‹œëœ ëŒ€ë¡œ(í•„í„°, 표시 í˜•ì‹ ë° ìˆœì„œ ì—´ ì´í›„) JSON 파ì¼ë¡œ 내보냅니다. - - Identifier - ì‹ë³„ìž + + Save as &view + 뷰로 저장하기(&V) - - String - 문ìžì—´ + + + Save the current filter, sort column and display formats as a view + 현재 í•„í„°, ì—´ ì •ë ¬ ë° í‘œì‹œ 형ì‹ì„ 뷰로 저장 - - currentline - 현재행 + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + ì´ ë²„íŠ¼ì€ ê²€ìƒ‰ëœ í…Œì´ë¸”ì˜ í˜„ìž¬ 설정(í•„í„°, 표시 í˜•ì‹ ë° ì—´ 순서)ì„ ë‚˜ì¤‘ì— SQL 문ì—서 검색하거나 사용할 수 있는 SQL 뷰로 저장합니다. - - Current line - 현재 í–‰ + + Save Table As... + 다른 ì´ë¦„으로 í…Œì´ë¸” 저장... - - SQL &editor font size - SQL ì—디터 í°íЏ í¬ê¸°(&E) + + + Save the table as currently displayed + 현재 ì¶œë ¥ëœ í˜•íƒœë¡œ í…Œì´ë¸” 저장 - - SQL &log font size - SQL 로그 í°íЏ í¬ê¸°(&E) + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>ì´ íŒì—… 메뉴는 현재 íƒìƒ‰ ë° í•„í„°ë§ëœ í‘œì— ì ìš©ë˜ëŠ” ë‹¤ìŒ ì˜µì…˜ì„ ì œê³µí•©ë‹ˆë‹¤.</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">CSV로 내보내기: ì´ ì˜µì…˜ì€ í˜„ìž¬ 표시ëœëŒ€ë¡œ(í•„í„°, 표시 í˜•ì‹ ë° ì—´ 순서) íƒìƒ‰ëœ í…Œì´ë¸”ì˜ ë°ì´í„°ë¥¼ CSV 파ì¼ë¡œ 내보냅니다.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">뷰로 저장: ì´ ì˜µì…˜ì€ ê²€ìƒ‰ëœ í…Œì´ë¸”ì˜ í˜„ìž¬ 설정(í•„í„°, 표시 í˜•ì‹ ë° ì—´ 순서)ì„ ë‚˜ì¤‘ì— SQL 문ì—서 검색하거나 사용할 수 있는 SQL 뷰로 저장합니다.</li></ul></body></html> - - Tab size: - 탭 í¬ê¸°: + + Hide column(s) + 컬럼(들) 숨기기 - - SQL editor &font - SQL 편집기 í°íЏ(&F) + + Hide selected column(s) + ì„ íƒí•œ 컬럼(들)ì„ ìˆ¨ê¸°ê¸° - - &Extensions - 확장기능(&E) + + Show all columns + ì „ì²´ 컬럼 보기 - - Select extensions to load for every database: - 불러올 í™•ìž¥ê¸°ëŠ¥ì„ ì„ íƒí•˜ì„¸ìš”(í™•ìž¥ê¸°ëŠ¥ì€ ëª¨ë“  ë°ì´í„°ë² ì´ìŠ¤ì— ë°˜ì˜ë©ë‹ˆë‹¤): + + Show all columns that were hidden + 숨겨진 ì „ì²´ 컬럼 보기 - - Add extension - 확장기능 추가 + + + Set encoding + ì¸ì½”딩 지정하기 - - Remove extension - 확장기능 제거 + + Change the encoding of the text in the table cells + í…Œì´ë¸” ì…€ ì•ˆì˜ í…스트 ì¸ì½”ë”©ì„ ë³€ê²½í•©ë‹ˆë‹¤ - - <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> - <html><head/><body><p>SQLiteì—서는 기본ì ìœ¼ë¡œ ì •ê·œí‘œí˜„ì‹ ê¸°ëŠ¥ì„ ì œê³µí•˜ì§€ 않습니다만 애플리케ì´ì…˜ì„ 실행하여 호출하는 ê²ƒì€ ê°€ëŠ¥í•©ë‹ˆë‹¤. DB Browser for SQLiteì—서는 ì´ ì•Œê³ ë¦¬ì¦˜ì„ ë°•ìŠ¤ ë°–ì—ì„œë„ ì •ê·œí‘œí˜„ì‹ì„ 사용할 수 있ë„ë¡ ì´ ì•Œê³ ë¦¬ì¦˜ì„ êµ¬í˜„í•´ì¤ë‹ˆë‹¤. 하지만 í™•ìž¥ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ì—¬ 외부ì—서 만든 알고리즘 êµ¬í˜„ì„ ì‚¬ìš©í•˜ê³ ìž í•œë‹¤ë©´ DB Browser for SQLiteì—서 제공하는 구현 ì‚¬ìš©ì„ ìžìœ ë¡­ê²Œ ëŒ ìˆ˜ 있습니다. ì´ ê¸°ëŠ¥ì€ ì• í”Œë¦¬ì¼€ì´ì…˜ì„ 재시작해야 합니다.</p></body></html> + + Set encoding for all tables + 모든 í…Œì´ë¸”ì˜ ì¸ì½”딩 지정하기 - - Disable Regular Expression extension - ì •ê·œì‹í‘œí˜„ì‹ í™•ìž¥ê¸°ëŠ¥ ë„기 + + Change the default encoding assumed for all tables in the database + ë°ì´í„°ë² ì´ìФ ì•ˆì— ìžˆëŠ” 모든 í…Œì´ë¸”ì˜ ê¸°ë³¸ ì¸ì½”ë”©ì„ ë³€ê²½í•©ë‹ˆë‹¤ - - Choose a directory - 디렉토리를 정하세요 + + Copy column name + ì—´ ì´ë¦„ 복사 - - The language will change after you restart the application. - 언어 ë³€ê²½ì€ ì• í”Œë¦¬ì¼€ì´ì…˜ì„ 재시작해야 ë°˜ì˜ë©ë‹ˆë‹¤. + + Copy the database table column name to your clipboard + ë°ì´í„°ë² ì´ìФ í…Œì´ë¸” ì—´ ì´ë¦„ì„ í´ë¦½ë³´ë“œì— 복사 - - Select extension file - 확장기능 파ì¼ì„ ì„ íƒí•˜ì„¸ìš” + + Clear Filters + í•„í„° 지우기 - - Extensions(*.so *.dll);;All files(*) - 확장기능파ì¼(*.so *.dll);;모든 파ì¼(*) + + Clear all filters + 모든 í•„í„° 지우기 - - - QObject - - Error importing data - ë°ì´í„° 가져오기 ì—러 + + + This button clears all the filters set in the header input fields for the currently browsed table. + ì´ ë²„íŠ¼ì€ í˜„ìž¬ íƒìƒ‰ëœ í…Œì´ë¸”ì˜ í—¤ë” ìž…ë ¥ í•„ë“œì— ì„¤ì •ëœ ëª¨ë“  필터를 ì§€ì›ë‹ˆë‹¤. - - from record number %1 - 레코드 넘버: %1 + + Clear Sorting + ì •ë ¬ 초기화 - - . -%1 - . -%1 + + Reset the order of rows to the default + í–‰ 순서를 기본값으로 재설정 - - Decoding CSV file... - CSV íŒŒì¼ ë””ì½”ë”©ì¤‘... + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + ì´ ë²„íŠ¼ì€ í˜„ìž¬ ê²€ìƒ‰ëœ í…Œì´ë¸”ì— ì§€ì •ëœ ì—´ ì •ë ¬ì„ ì§€ìš°ê³  기본 순서로 ëŒì•„갑니다. - - Cancel - 취소 + + Print + ì¸ì‡„하기 - - Collation needed! Proceed? - 콜레ì´ì…˜ì´ 필요합니다! 진행할까요? + + Print currently browsed table data + 현재 íƒìƒ‰í•œ í…Œì´ë¸” ë°ì´í„°ë¥¼ ì¸ì‡„합니다 - - A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. -If you choose to proceed, be aware bad things can happen to your database. -Create a backup! - ì´ ë°ì´í„°ë² ì´ìŠ¤ì˜ í…Œì´ë¸”ì€ ì´ ì• í”Œë¦¬ì¼€ì´ì…˜ì—서 잘 알지못하는 특별한 함수 '%1'ê°€ 필요합니다. -ì´ëŒ€ë¡œ ê³„ì† ì§„í–‰í•  수는 있습니다만 ì—¬ëŸ¬ë¶„ì˜ ë°ì´í„°ë² ì´ìŠ¤ì— ë‚˜ìœ ì˜í–¥ì´ ê°ˆ ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. -ë°±ì—…ì„ ìƒì„±í•˜ì„¸ìš”! + + Print currently browsed table data. Print selection if more than one cell is selected. + 현재 찾아본 í…Œì´ë¸” ë°ì´í„°ë¥¼ ì¸ì‡„합니다. 둘 ì´ìƒì˜ ì…€ì´ ì„ íƒëœ 경우 ì„ íƒ í•­ëª©ë§Œ ì¸ì‡„합니다. - - - SqlExecutionArea - - Form - í¼ + + Ctrl+P + - - Results of the last executed statements - 가장 최근 실행 구문 ê²°ê³¼ + + New Data Browser + 새 ë°ì´í„° íƒìƒ‰ê¸° - - This field shows the results and status codes of the last executed statements. - ì´ í•„ë“œëŠ” 가장 ìµœê·¼ì´ ì‹¤í–‰ëœ êµ¬ë¬¸ì˜ ê²°ê³¼ì™€ ìƒíƒœ 코드를 ë³´ì—¬ì¤ë‹ˆë‹¤. + + + Add a new docked Data Browser + ë„í‚¹ëœ ìƒˆ ë°ì´í„° 브ë¼ìš°ì € 추가 - - Export to &CSV - CSV로 내보내기(&C) + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + ì´ ë²„íŠ¼ì€ ë¶„ë¦¬í•˜ê³  다른 ë ˆì´ì•„웃으로 정렬할 수 있는 ë„í‚¹ëœ ìƒˆ ë°ì´í„° 브ë¼ìš°ì €ë¥¼ 추가합니다. - - Save as &view - 뷰로 저장하기(&V) + + Refresh + 새로고침 - - Save as view - 뷰로 저장하기 + + Refresh the data in the selected table + ì„ íƒí•œ í…Œì´ë¸”ì˜ ë°ì´í„° 새로고치기 - - Please specify the view name - ë·° ì´ë¦„ì„ ì§€ì •í•´ì£¼ì„¸ìš” + + This button refreshes the data in the currently selected table. + ì´ ë²„íŠ¼ì€ í˜„ìž¬ ì„ íƒëœ í…Œì´ë¸”ì˜ ë°ì´í„°ë¥¼ 새로고칩니다. - - There is already an object with that name. Please choose a different name. - ì´ì§€ ê°™ì€ ì´ë¦„ì˜ ê°ì²´ê°€ 존재합니다. 다른 ì´ë¦„ì„ ê³ ë¥´ì„¸ìš”. + + F5 + - - View successfully created. - ë·° ìƒì„± 성공. + + Find in cells + ì…€ì—서 찾기 - - Error creating view: %1 - ë·° ìƒì„± ì—러: %1 + + Open the find tool bar which allows you to search for values in the table view below. + 아래 표 보기ì—서 ê°’ì„ ê²€ìƒ‰í•  수 있는 ë„구 모ìŒì„ 엽니다. - - - SqlUiLexer - - (X) The abs(X) function returns the absolute value of the numeric argument X. - (X) abs(X) 함수는 ìˆ«ìž ë§¤ê°œë³€ìˆ˜ Xì˜ ì ˆëŒ€ê°’ì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + + Bold + 진하게 - - () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. - () changes() 함수는 가장 ìµœê·¼ì— ì‹¤í–‰ëœ INSERT, DELETE, UPDATE 구문ì—서 ë°ì´í„°ë² ì´ìФì—서 변경ë˜ê±°ë‚˜ 추가ë˜ê±°ë‚˜ ì‚­ì œëœ í–‰ 수를 리턴합니다. + + Ctrl+B + - - (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. - (X1,X2,...) char(X1,X2,...,XN) 함수는 ê°ê°ì˜ X1ì—서 XN ìˆ«ìž ê°’ì˜ ìœ ë‹ˆì½”ë“œ í¬ì¸íЏ ê°’ì„ ê°€ì§„ 문ìžë“¤ë¡œ êµ¬ì„±ëœ ë¬¸ìžì—´ì„ 리턴합니다. + + + Italic + 기울임 - - (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL - (X,Y,...) coalesce() 함수는 첫번째 NULLì´ ì•„ë‹Œ ì¸ìžê°’ì˜ ì‚¬ë³¸ì„ ë¦¬í„´í•©ë‹ˆë‹¤. 만약 ì¸ìžê°’ì´ ëª¨ë‘ NULLì´ë¼ë©´ NULLì„ ë¦¬í„´í•©ë‹ˆë‹¤ + + + Underline + 밑줄 - - (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". - (X,Y) glob(X,Y) 함수는 "Y GLOB X" 표현ì‹ê³¼ 같습니다. + + Ctrl+U + - - (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. - (X,Y) ifnull() 함수는 첫번째 NULLì´ ì•„ë‹Œ ì¸ìžê°’ì˜ ì‚¬ë³¸ì„ ë¦¬í„´í•©ë‹ˆë‹¤. 만약 ì¸ìžê°’ 둘 다 NULLì´ë¼ë©´ NULLì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + + Align Right + 우측으로 ì •ë ¬ - - (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. - (X,Y) instr(X,Y) 함수는 문ìžì—´ Xì—서 문ìžì—´ Yê°€ 있다면 첫 ê¸€ìž ìœ„ì¹˜ + 1 ê°’ì„ ë¦¬í„´í•©ë‹ˆë‹¤. 만약 문ìžì—´ Xì—서 문ìžì—´ Yê°€ 발견ë˜ì§€ 않는다면 0ì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + + Align Left + 좌측으로 ì •ë ¬ - - (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. - (X) hex() 함수는 매개변수를 BLOB으로 변환한 후 blobì˜ ë‚´ìš©ì„ ëŒ€ë¬¸ìž 16진수 문ìžì—´ë¡œ 변환하여 리턴합니다. + + + Center Horizontally + ê°€ìš´ë° ì •ë ¬ - - () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. - () last_insert_rowid() 함수는 함수가 í˜¸ì¶œëœ ë°ì´í„°ë² ì´ìФ ì—°ê²°ì—서 가장 ìµœê·¼ì´ ì¶”ê°€ëœ í–‰ì˜ ROWID를 리턴합니다. + + + Justify + ì •ë ¬ - - (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. - (X) 문ìžì—´ 변수 X를 위한 것으로 length(X) 함수는 첫 번째 NUL 문ìžë¥¼ 만날 때 ê¹Œì§€ì˜ (ë°”ì´íЏ 수가 아닌)ë¬¸ìž ìˆ˜ë¥¼ 리턴합니다. + + + Edit Conditional Formats... + ì¡°ê±´ë¶€ ì„œì‹ íŽ¸ì§‘... - - (X,Y) The like() function is used to implement the "Y LIKE X" expression. - (X,Y) like() 함수는 "Y LIKE X" 표현ì‹ì„ 구현하기위해 사용합니다. + + Edit conditional formats for the current column + ì´ ì»¬ëŸ¼ì˜ ì¡°ê±´ë¶€ ì„œì‹ íŽ¸ì§‘ - - (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. - (X,Y,Z) like() 함수는 "Y LIKE X ESCAPE Z" 표현ì‹ì„ 구현하기위해 사용합니다. + + Clear Format + ì„œì‹ ì§€ìš°ê¸° - - (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. - (X) load_extention(X) 함수는 SQLite í™•ìž¥ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ê¸° 위하여 Xë¼ ì´ë¦„지어진 공유ë¼ì´ë¸ŒëŸ¬ë¦¬ 파ì¼ì„ 외부ì—서 불러올 때 사용합니다. + + Clear All Formats + 모든 í•„í„° 지우기 - - (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. - (X, Y) load_extention(X) 함수는 SQLite í™•ìž¥ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ê¸° 위하여 Xë¼ ì´ë¦„지어진 공유ë¼ì´ë¸ŒëŸ¬ë¦¬ 파ì¼ì„ 엔트리 í¬ì¸íЏ Y를 사용하여 외부ì—서 불러올 때 사용합니다. + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + ì„ íƒí•œ ì…€ì˜ ëª¨ë“  ì…€ 서ì‹ê³¼ ì„ íƒí•œ ì—´ì˜ ëª¨ë“  ì¡°ê±´ë¶€ ì„œì‹ ì§€ìš°ê¸° - - (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. - (X) lower(X) 함수는 문ìžì—´ Xì—서 모든 ASCII 문ìžë¥¼ 소문ìžë¡œ 변경한 문ìžì—´ ì‚¬ë³¸ì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + + Font Color + 글ìžìƒ‰ - - (X) ltrim(X) removes spaces from the left side of X. - (X) ltrim(X) 함수는 Xì˜ ì¢Œì¸¡ì˜ ê³µë°±ì—¬ë°±ì„ ì œê±°í•©ë‹ˆë‹¤. + + + Background Color + 배경색 - - (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. - (X,Y) ltrim(X,Y) 함수는 Xì˜ ì¢Œì¸¡ì—서 Yì— ìžˆëŠ” 모든 문ìžë¥¼ 제거한 문ìžì—´ì„ 리턴합니다. + + Toggle Format Toolbar + ì„œì‹ íˆ´ë°” 토글 - - (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. - (X,Y,...) 다중 ì¸ìžë¥¼ 제공하는 max() 함수는 주어진 ì¸ìžê°’ 중ì—서 가장 í° ê°’ì„ ë¦¬í„´í•©ë‹ˆë‹¤. 만약 주어진 ì¸ìž ì¤‘ì— NULLì´ í•˜ë‚˜ë¼ë„ 있으면 NULLì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + Show/hide format toolbar + ì„œì‹ íˆ´ë°” 표시/숨기기 - - (X,Y,...) The multi-argument min() function returns the argument with the minimum value. - (X,Y,...) 다중 ì¸ìžë¥¼ 제공하는 min() 함수는 주어진 ì¸ìžê°’ 중ì—서 가장 ìž‘ì€ ê°’ì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + + This button shows or hides the formatting toolbar of the Data Browser + ì´ ë²„íŠ¼ì€ ë°ì´í„° 브ë¼ìš°ì €ì˜ ì„œì‹ ë„구 모ìŒì„ 표시하거나 숨ê¹ë‹ˆë‹¤ - - (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. - Y) nullif(X,Y) 함수는 ë‘ ì¸ìžê°’ì´ ì„œë¡œ 다르면 X를 리턴하고 ë‘ ì¸ìžê°’ì´ ê°™ìœ¼ë©´ NULLì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + Select column + 컬럼 ì„ íƒ - - (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. - (FORMAT,...) printf(FORMAT,...) SQL 함수는 sqlite3_mprintf() C-언어 함수와 표준 C ë¼ì´ë¸ŒëŸ¬ë¦¬ì—ì„œì˜ printf() 함수처럼 ë™ìž‘합니다. + + Ctrl+Space + - - (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. - (X) quote(X) 함수는 X를 SQL문 ì•ˆì— í¬í•¨ë˜ê¸°ì— ì ì ˆí•˜ë„ë¡ SQL 리터럴 문ìžì—´ë¡œ 리턴합니다. + + Replace text in cells + ì…€ì˜ í…스트 바꾸기 - - () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. - () random() 함수는 -9223372036854775808와 +9223372036854775807 사ì´ì˜ pseudo-ëžœë¤ ì •ìˆ˜ë¥¼ 리턴합니다. + + Freeze columns + 컬럼 잠그기(Freeze) - - (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. - (N) randomblob(N) 함수는 psedo-ëžœë¤ ë°”ì´íŠ¸ë¥¼ í¬í•¨í•œ N-ë°”ì´íЏ blobì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + Make all columns from the first column up to this column not move when scrolling horizontally + 가로로 스í¬ë¡¤í•  때 첫번째 열부터 ì´ ì—´ê¹Œì§€ì˜ ëª¨ë“  ì—´ì´ ì´ë™í•˜ì§€ 않ë„ë¡ í•©ë‹ˆë‹¤ - - (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. - (X,Y,Z) replace(X,Y,Z) 함수는 문ìžì—´ Xì— ìžˆëŠ” 모든 문ìžì—´ Y를 Z로 치환한 문ìžì—´ì„ 리턴합니다. + + Filter in any column + 모든 ì—´ì—서 í•„í„°ë§ - - (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. - (X) round(X) 함수는 ë¶€ë™ì†Œìˆ˜ì  ê°’ X를 0ì˜ ìžë¦¬ì—서 반올림한 ê°’ì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + Ctrl+R + + + + + %n row(s) + + %n ì—´(들) + + + + + , %n column(s) + + , %n 컬럼(들) + - - (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. - (X,Y) round(X,Y) 함수는 ë¶€ë™ì†Œìˆ˜ì  ê°’ X를 ì†Œìˆ˜ì  ìš°ì¸¡ì—서 Yìžë¦¬ì—서 반올림한 ê°’ì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . 합계: %1, í‰ê· : %2, 최소값: %3, 최대값: %4 - - (X) rtrim(X) removes spaces from the right side of X. - (X) rtrim(X)ì€ Xì˜ ìš°ì¸¡ ê³µë°±ì„ ì œê±°í•©ë‹ˆë‹¤. + + Conditional formats for "%1" + "%1"ì— ëŒ€í•œ ì¡°ê±´ë¶€ ì„œì‹ - - (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. - (X,Y) rtrim(X,Y) 함수는 Xì˜ ìš°ì¸¡ì—서 Yì— ìžˆëŠ” 모든 문ìžë¥¼ 삭제한 문ìžì—´ì„ 리턴합니다. + + determining row count... + í–‰ 개수 ê²°ì • 중... - - (X) The soundex(X) function returns a string that is the soundex encoding of the string X. - (X) soundex(X) 함수는 문ìžì—´ Xì˜ ì‚¬ìš´ë±ìФ ì¸ì½”딩 문ìžì—´ì„ 리턴합니다. + + %L1 - %L2 of >= %L3 + L1 - %L2ì˜ >= %L3 - - (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. - (X,Y) substr(X,Y) 함수는 문ìžì—´ Xì—서 Y번째부터 ë까지 모든 문ìžì—´ì„ 리턴합니다. + + %L1 - %L2 of %L3 + %L1 - %L2ì˜ %L3 - - (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. - (X,Y,Z) substr(X,Y,Z) 함수는 문ìžì—´ Xì—서 Y번째 문ìžë¶€í„° Zë¬¸ìž ìˆ˜ë§Œí¼ ë¦¬í„´í•©ë‹ˆë‹¤. + + (clipped at %L1 rows) + (%L1 í–‰ì—서 잘림) - - () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. - () total_changes() 함수는 현재 ë°ì´í„°ë² ì´ìФ ì—°ê²°ì´ ì—´ë¦° 후 INSERT, UPDATE, DELETE êµ¬ë¬¸ì— ì˜í•´ì„œ ë³€ê²½ëœ ë ˆì½”ë“œ í–‰ 수를 리턴합니다. + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + ì´ ë·°ì—서 ìˆ˜ì •ì„ í™œì„±í™”í•˜ê¸° 위하여 pseudo-primary key를 입력하시기 ë°”ëžë‹ˆë‹¤. ì´ê²ƒì€ ë·°ì—서 유ì¼í•œ ì´ë¦„ì´ì–´ì•¼ 합니다. - - (X) trim(X) removes spaces from both ends of X. - (X) trim(X) 함수는 Xì˜ ì–‘ìª½ ê³µë°±ì„ ì œê±°í•©ë‹ˆë‹¤. + + Delete Records + 레코드 ì‚­ì œ - - (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. - (X,Y) trim(X,Y) 함수는 Xì˜ ì–‘ëì—서 Yì— í•´ë‹¹í•˜ëŠ” 문ìžë“¤ì„ 삭제한 문ìžì—´ì„ 리턴합니다. + + Duplicate records + 레코드 복제하기 - - (X) The typeof(X) function returns a string that indicates the datatype of the expression X. - (X) typeof(X) 함수는 í‘œí˜„ì‹ Xì˜ ë°ì´í„°íƒ€ìž…ì„ ë‚˜íƒ€ë‚´ëŠ” 문ìžì—´ì„ 리턴합니다. + + Duplicate record + 레코드 복제하기 - - (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. - (X) unicode(X) 함수는 문ìžì—´ Xì˜ ì²« 글ìžì— 해당하는 ìˆ«ìž ìœ ë‹ˆì½”ë“œ í¬ì¸íŠ¸ë¥¼ 리턴합니다. + + Ctrl+" + - - (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. - (X) upper(X) 함수는 ìž…ë ¥ 문ìžì—´ Xì—서 ASCII 문ìžì— 해당하는 글ìžë¥¼ 대문ìžë¡œ 변경한 문ìžì—´ ì‚¬ë³¸ì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + Adjust rows to contents + ë‚´ìš©ì— ë§žê²Œ í–‰ í¬ê¸° ì¡°ì ˆ - - (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. - (N) zeroblob(N) 함수는 N ë°”ì´íŠ¸ì˜ 0x00으로 ì´ë£¨ì–´ì§„ BLOBì„ êµ¬ì„±í•˜ì—¬ 리턴합니다. + + Error deleting record: +%1 + 레코드 추가 ì—러: +%1 - - - - - (timestring,modifier,modifier,...) - (timestring,modifier,modifier,...) + + Please select a record first + 레코드를 먼저 ì„ íƒí•˜ì„¸ìš” - - (format,timestring,modifier,modifier,...) - (format,timestring,modifier,modifier,...) + + Please choose a new encoding for all tables. + 모든 í…Œì´ë¸”ì— ì„¤ì •í•  새 ì¸ì½”ë”©ì„ ì„ íƒí•˜ì„¸ìš”. - - (X) The avg() function returns the average value of all non-NULL X within a group. - (X) avg() 함수는 그룹ì—서 모든 NULLì´ ì•„ë‹Œ Xì˜ ê°’ì˜ í‰ê· ì„ 리턴합니다. + + Please choose a new encoding for this table. + ì´ í…Œì´ë¸”ì— ì ìš©í•  새 ì¸ì½”ë”©ì„ ì„ íƒí•˜ì„¸ìš”. - - (X) The count(X) function returns a count of the number of times that X is not NULL in a group. - (X) count(X) 함수는 그룹ì—서 NULLì´ ì•„ë‹Œ 개수를 세어 리턴합니다. + + %1 +Leave the field empty for using the database encoding. + %1 +ë°ì´í„°ë² ì´ìФ ì¸ì½”ë”©ì„ ì‚¬ìš©í•˜ê¸° 위해 필드를 비워둡니다. - - (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. - (X) group_concat() 함수는 Xì˜ ëª¨ë“  NULLì´ ì•„ë‹Œ ê°’ë“¤ì˜ ë¬¸ìžì—´ë¡œ í•©ì³ì„œ 리턴합니다. + + This encoding is either not valid or not supported. + ì´ ì¸ì½”ë”©ì€ ì˜¬ë°”ë¥´ì§€ 않거나 ì§€ì›ë˜ì§€ 않습니다. - - (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. - (X,Y) group_concat() 함수는 Xì˜ ëª¨ë“  NULLì´ ì•„ë‹Œ ê°’ë“¤ì˜ ë¬¸ìžì—´ë¡œ í•©ì³ì„œ 리턴합니다. 만약 매개변수 Yê°€ 있다면 ê°’ë“¤ì„ ë¬¸ìžì—´ë¡œ í•©ì¹  때 구분ìžë¡œ 사용합니다. + + %1 replacement(s) made. + %1ê°œì˜ êµì²´ê°€ ì´ë£¨ì–´ì¡ŒìŠµë‹ˆë‹¤. + + + TableBrowserDock - - (X) The max() aggregate function returns the maximum value of all values in the group. - (X) max() 집계 함수는 그룹ì—서 모든 값들 중 가장 í° ê°’ì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + New Data Browser + 새 ë°ì´í„° íƒìƒ‰ê¸° - - (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. - (X) min() 집계 함수는 그룹ì—서 NULLì´ ì•„ 닌모든 값들 중 가장 ìž‘ì€ ê°’ì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + Rename Data Browser + ë°ì´í„° íƒìƒ‰ê¸° ì´ë¦„ 변경 - - - (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. - (X) sum(x)ê³¼ total() 집계 함수는 ê·¸ë£¹ì˜ ëª¨ë“  NULLì´ ì•„ë‹Œ ê°’ë“¤ì˜ í•©ì„ ë¦¬í„´í•©ë‹ˆë‹¤. + + Close Data Browser + ë°ì´í„° íƒìƒ‰ê¸° 닫기 - - - SqliteTableModel - - Error changing data: -%1 - ë°ì´í„° 수정 ì—러: -%1 + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + ë°ì´í„° 브ë¼ìš°ì €ì˜ 새 ì´ë¦„ì„ ì„¤ì •í•˜ì„¸ìš”. '&&' 문ìžë¥¼ 사용하여 다ìŒì— ë”°ë¼ì˜¤ëŠ” 문ìžë¥¼ 키보드 단축키로서 사용할 수 있습니다. @@ -2810,17 +8040,17 @@ Create a backup! Compact Database - ë°ì´í„°ë² ì´ìФ í¬ê¸° 줄ì´ê¸° + ë°ì´í„°ë² ì´ìФ í¬ê¸° 줄ì´ê¸°(Vacuum) - Warning: Compacting the database will commit all changes you made. + Warning: Compacting the database will commit all of your changes. 주ì˜: ë°ì´í„°ë² ì´ìФ í¬ê¸° 줄ì´ê¸°ë¥¼ 하면 저장ë˜ì§€ ì•Šì€ ëª¨ë“  ìˆ˜ì •ì‚¬í•­ì´ ë°˜ì˜ë©ë‹ˆë‹¤. - Please select the objects to compact: - í¬ê¸°ë¥¼ ì¤„ì¼ ê°ì²´ë¥¼ ì„ íƒí•˜ì„¸ìš”: + Please select the databases to co&mpact: + í¬ê¸°ë¥¼ ì¤„ì¼ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ì„ íƒí•˜ì„¸ìš”(&M): diff --git a/src/translations/sqlb_nl.ts b/src/translations/sqlb_nl.ts new file mode 100644 index 000000000..99d39080e --- /dev/null +++ b/src/translations/sqlb_nl.ts @@ -0,0 +1,8096 @@ + + + + + AboutDialog + + + About DB Browser for SQLite + Over DB-browser voor SQLite + + + + Version + Versie + + + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + + + + + AddRecordDialog + + + Add New Record + Nieuw record toevoegen + + + + Enter values for the new record considering constraints. Fields in bold are mandatory. + Voer waarden in voor het nieuwe record, rekening houdend met beperkingen. Vette velden zijn verplicht. + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + In de Waarde-kolom kun je de waarde opgegeven voor het veld geïdentificeerd in de Naam-kolom. De Type-kolom geeft het type van het veld aan. Standaardwaarden worden in dezelfde stijl getoond als NULL-waarden. + + + + Name + Naam + + + + Type + Type + + + + Value + Waarde + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + In te voeren waarden. Vooringevulde standaardwaarden worden automatisch ingevoerd, tenzij ze aanpast worden. + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + Wanneer je waarden in het kader hierboven bewerkt, dan wordt de SQL-opdracht voor het invoegen van een nieuw record hier getoond. Je kunt de opdracht dan nog bewerken, voordat je deze opslaat. + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Opslaan</span> verstuurt de SQL-instructie voor het invoeren van een nieuw record naar de database.</p><p><span style=" font-weight:600;">Standaardwaarden herstellen</span> herstelt de initiële waarden van de <span style=" font-weight:600;">Value</span>-kolom.</p><p><span style=" font-weight:600;">Annuleren</span> sluit dit venster zonder de opdracht uit te voeren.</p></body></html> + + + + Auto-increment + + Automatisch ophogen + + + + + Unique constraint + + Uniciteitsbeperking + + + + + Check constraint: %1 + + Controlebeperking: %1 + + + + + Foreign key: %1 + + Vreemde sleutel: %1 + + + + + Default value: %1 + + Standaardwaarde: %1 + + + + + Error adding record. Message from database engine: + +%1 + Fout bij toevoegen record. Melding van de database: + +%1 + + + + Are you sure you want to restore all the entered values to their defaults? + Weet je zeker dat je alle ingevoerde waarden wilt herstellen naar hun standaardwaarden? + + + + Application + + + The user settings file location is replaced with the argument value instead of the environment variable value. + De bestandslocatie van de gebruikersinstellingen is vervangen door de argumentwaarde in plaats van door de waarde van de omgevingsvariabele. + + + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + Negeerde de waarde van de omgevingsvariabele(DB4S_SETTINGS_FILE): + + + + Possible command line arguments: + Mogelijke opdrachtregelargumenten: + + + + + The file %1 does not exist + Het bestand %1 bestaat niet + + + + Usage + + + + + options + + + + + + database + + + + + + project + + + + + + csv-file + + + + + Show command line options + + + + + Exit application after running scripts + + + + + + file + + + + + Execute this SQL file after opening the DB + + + + + Import this CSV file into the passed DB or into a new DB + + + + + table + + + + + Browse this table, or use it as target of a data import + + + + + Open database in read-only mode + + + + + settings_file + + + + + Run application based on this settings file + + + + + + group + + + + + + settings + + + + + + value + + + + + Run application with this setting temporarily set to value + + + + + Run application saving this value for this setting + + + + + Display the current version + + + + + Open this SQLite database + + + + + Open this project file (*.sqbpro) + + + + + Import this CSV file into an in-memory database + + + + + + + The %1 option requires an argument + + + + + The -S/--settings option requires an argument. The option is ignored. + De -S/--settings optie vereist een argument. De optie wordt genegeerd. + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + De -o/--option and -O/--save-option opties vereisen een argument in de vorm van groep/instelling=waarde + + + + Invalid option/non-existent file: %1 + Ongeldige optie of niet bestaand bestand: %1 + + + + SQLite Version + SQLite-versie + + + + SQLCipher Version %1 (based on SQLite %2) + SQLCipher-versie %1 (gebaseerd op SQLite %2) + + + + DB Browser for SQLite Version %1. + DB-browser voor SQLite versie %1. + + + + Last commit hash when built: %1 + + + + + Built for %1, running on %2 + Gebouwd voor %1, draaiend op %2 + + + + Qt Version %1 + Qt-versie %1 + + + + CipherDialog + + + SQLCipher encryption + SQLCipher encryptie + + + + &Password + &Wachtwoord + + + + &Reenter password + Wa&chtwoord herhalen + + + + Passphrase + Toegangsfrase + + + + Raw key + Onbewerkte sleutel + + + + Encr&yption settings + Encr&yptie-instellingen + + + + SQLCipher &3 defaults + SQLCipher &3 standaardwaarden + + + + SQLCipher &4 defaults + SQLCipher &4 standaardwaarden + + + + Custo&m + &Aangepast + + + + Page si&ze + &Paginagrootte + + + + &KDF iterations + KDF &iteraties + + + + HMAC algorithm + &HMAC-algoritme + + + + KDF algorithm + &KDF-algoritme + + + + Plaintext Header Size + Platte-&tekstheadergrootte + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + Geef een sleutel op om de database mee te versleutelen. +Wees je ervan bewust dat als je een van de andere, optionele, opties wijzigt, je die iedere keer opnieuw moet invoeren als je het databasebestand wilt openen. +Laat wachtwoordvelden leeg om de versleuteling uit te schakelen. +Versleuteling kan wat tijd in beslag nemen en je doet er tevens verstandig aan een backup van je database te hebben! Onopgeslagen wijzigingen worden toegepast voordat de versleuteling aangepast wordt. + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + Voer de sleutel in waarmee database is versleuteld. +Indien enige andere opties voor dit databasebestand gewijzigd waren dan dien je die gegevens hier nu ook opnieuw in te voeren. + + + + ColumnDisplayFormatDialog + + + Choose display format + Kies een opmaak + + + + Display format + Opmaak + + + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + Kies een opmaak voor de kolom '%1' die op iedere waarde wordt toegepast voordat deze getoond wordt. + + + + Default + Standaard + + + + Decimal number + Decimaal getal + + + + Exponent notation + Wetenschappelijke E-notatie + + + + Hex blob + Hexadecimale blob + + + + Hex number + Hexadecimaal getal + + + + Octal number + Octaal getal + + + + Round number + Afgerond getal + + + + Apple NSDate to date + Apple NSDate naar datum + + + + Java epoch (milliseconds) to date + Java-epoch (milliseconden) naar datum + + + + .NET DateTime.Ticks to date + .NET DateTime.Ticks naar datum + + + + Julian day to date + Juliaanse dag naar datum + + + + Unix epoch to date + Unix-epoch naar datum + + + + Unix epoch to local time + Unix-epoch naar lokale tijd + + + + WebKit / Chromium epoch to date + + + + + WebKit / Chromium epoch to local time + + + + + Windows DATE to date + Windows DATE naar datum + + + + Date as dd/mm/yyyy + Datum als dd/mm/jjjj + + + + Lower case + onderkast + + + + Upper case + BOVENKAST + + + + Binary GUID to text + Binair GUID naar datum + + + + SpatiaLite Geometry to SVG + + + + + Custom + Aangepast + + + + Custom display format must contain a function call applied to %1 + Aangepaste opmaak moet bestaan uit een functie-aanroep die toegepast wordt op %1 + + + + Error in custom display format. Message from database engine: + +%1 + Fout in de aangepaste opmaak. Melding van de database: + +%1 + + + + Custom display format must return only one column but it returned %1. + Aangepaste opmaak moet slechts één kolom retourneren, maar retourneerde er %1. + + + + CondFormatManager + + + Conditional Format Manager + Voorwaardelijke-opmaakbeheerder + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + Dit dialoogvenster stelt je in staat om voorwaardelijke opmaakregels te creëren en te bewerken. Iedere celstijl zal worden geselecteerd op basis van de eerst vervulde voorwaarde voor diens celwaarde. De voorwaardelijke opmaakregels kunnen omhoog en omlaag verplaatst worden. Hoger geplaatste regels hebben hogere prioriteit. De syntaxis voor de voorwaarden in dezelfde als voor filters en een lege voorwaarde wordt toegepast op alle waarden. + + + + Add new conditional format + Nieuwe voorwaardelijke-opmaakregel toevoegen + + + + &Add + &Toevoegen + + + + Remove selected conditional format + Verwijder de geselecteerde voorwaardelijke-opmaakregel + + + + &Remove + &Verwijderen + + + + Move selected conditional format up + Verplaats de geselecteerde voorwaardelijke-opmaakregel omhoog + + + + Move &up + Om&hoog verplaatsen + + + + Move selected conditional format down + Verplaats de geselecteerde voorwaardelijke-opmaakregel omlaag + + + + Move &down + Om&laag verplaatsen + + + + Foreground + Voorgrond + + + + Text color + Tekstkleur + + + + Background + Achtergrond + + + + Background color + Achtergrondkleur + + + + Font + Lettertype + + + + Size + Grootte + + + + Bold + Vet + + + + Italic + Cursief + + + + Underline + Onderstreept + + + + Alignment + Uitlijning + + + + Condition + Voorwaarde + + + + + Click to select color + Klik om een kleur te selecteren + + + + Are you sure you want to clear all the conditional formats of this field? + Weet je zeker dat je alle voorwaardelijke-opmaakregels voor dit veld wilt verwijderen? + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + Geef de databasenaam zoals je de gekoppelde database wilt benaderen + + + + Invalid file format + Ongeldig bestandsformaat + + + + Do you really want to close this temporary database? All data will be lost. + Weet je zeker dat je deze tijdelijke database wilt sluiten? Alle gegevens zullen verloren gaan. + + + + Do you want to save the changes made to the database file %1? + Wil je de wijzigingen opslaan die je de gemaakt hebt voor database %1? + + + + Database didn't close correctly, probably still busy + Database is niet goed afgesloten; waarschijnlijk nog steeds bezig + + + + Cannot open destination file: '%1' + + + + + + Cannot backup to file: '%1'. Message: %2 + + + + + The database is currently busy: + De database is momenteel bezig: + + + + Do you want to abort that other operation? + Wil je die andere handeling afbreken? + + + + Exporting database to SQL file... + Database wordt geëxporteerd naar SQL-bestand... + + + + + Cancel + Annuleren + + + + + No database file opened + Er is geen databasebestand open + + + + Executing SQL... + SQL wordt uitgevoerd... + + + + Action cancelled. + Handeling geannuleerd. + + + + + Error in statement #%1: %2. +Aborting execution%3. + Fout in instructie #%1: %2. +Uitvoering wordt afgebroken%3. + + + + + and rolling back + en teruggedraaid + + + + didn't receive any output from %1 + Geen uitvoer ontvangen van %1 + + + + could not execute command: %1 + kon opdracht niet uitvoeren: %1 + + + + Cannot delete this object + Kan dit object niet verwijderen + + + + Cannot set data on this object + Kan de gegevens niet toepassen op dit object + + + + + A table with the name '%1' already exists in schema '%2'. + Er bestaat al een tabel met de naam '%1' in schema '%2'. + + + + No table with name '%1' exists in schema '%2'. + Er bestaat geen tabel met de naam '%1' in schema '%2'. + + + + + Cannot find column %1. + Kan kolom %1 niet vinden. + + + + Creating savepoint failed. DB says: %1 + Het maken van een herstelpunt is niet gelukt. Melding van de database: %1 + + + + Renaming the column failed. DB says: +%1 + Het hernoemen van de kolom is niet gelukt. Melding van de database: %1 + + + + + Releasing savepoint failed. DB says: %1 + Het opheffen van een herstelpunt is niet gelukt. Melding van de database: %1 + + + + Creating new table failed. DB says: %1 + Het maken van de nieuwe tabel is niet gelukt. Melding van de database: %1 + + + + Copying data to new table failed. DB says: +%1 + Het kopiëren van de gegevens naar de nieuwe tabel is niet gelukt. Melding van de database: %1 + + + + Deleting old table failed. DB says: %1 + Het verwijderen van de oude tabel is niet gelukt. Melding van de database: %1 + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + Fout bij het het herstellen van sommige objecten die met deze tabel geassocieerd zijn. Dit gebeurde hoogstwaarschijnlijk omdat kolomnamen gewijzigd zijn. Dit is de SQL-instructie die je wellicht aan wilt passen om het nogmaals mee te proberen: + + + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + Fout bij het hernoemen van tabel '%1' naar '%2'. +Melding van de database: +%3 + + + + could not get list of db objects: %1 + Fout bij het verkrijgen van lijst met database-objecten: %1 + + + + could not get list of databases: %1 + Fout bij het verkrijgen van lijst met databases: %1 + + + + Error setting pragma %1 to %2: %3 + Fout bij het omzetten van pragma %1 naar %2: %3 + + + + File not found. + Bestand niet gevonden. + + + + Error loading extension: %1 + Fout bij het laden van extensie: %1 + + + + Error loading built-in extension: %1 + + + + + could not get column information + Fout bij het verkrijgen van kolominformatie + + + + DbStructureModel + + + Name + Naam + + + + Object + Object + + + + Type + Type + + + + Schema + Schema + + + + Database + Database + + + + Browsables + Doorbladerbare + + + + All + Alle + + + + Temporary + Tijdelijke + + + + Tables (%1) + Tabellen (%1) + + + + Indices (%1) + Indices (%1) + + + + Views (%1) + Views (%1) + + + + Triggers (%1) + Triggers (%1) + + + + EditDialog + + + Edit database cell + Databasecel bewerken + + + + This area displays information about the data present in this database cell + Dit gebied toont informatie over de aanwezige gegevens in de databasecel + + + + Mode: + Modus: + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + Dit is de lijst van ondersteunde modi voor de celbewerker. Kies een modus om de gegevens van de huidige cel te bekijken of te bewerken. + + + + Text + Tekst + + + + RTL Text + Rechts-naar-linkstekst + + + + Binary + Binair + + + + + Image + Afbeelding + + + + JSON + JSON + + + + XML + XML + + + + Evaluation + + + + + + Automatically adjust the editor mode to the loaded data type + De bewerker automatisch aanpassen aan het geladen gegevenstype + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + Deze aanvinkbare knop zet het automatisch wisselen van de bewerkingsmodus aan of uit. Wanneer een nieuwe cel wordt geselecteerd of nieuwe gegevens worden geïmporteerd en automatisch wisselen aangevinkt is, dan verandert de modus naar het gedetecteerde gegevenstype. Je kunt de bewerkingsmodus dan alsnog handmatig aanpassen. Vink de knop uit als je handmatig wisselen wilt gebruiken tijdens het navigeren door de cellen. + + + + Auto-switch + Automatisch wisselen + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + Deze Qt-bewerker wordt voor rechts-naar-linksteksten gebruikt, omdat dit niet ondersteund wordt door de standaard tekstbewerker. Er werden rechts-naar-linkstekens gedetecteerd en daarom is deze bewerkingsmodus automatisch geselecteerd. + + + + Identification of the cell currently in the editor + + + + + Type and size of data currently in table + + + + + Apply data to cell + Gegevens toepassen op cel + + + + This button saves the changes performed in the cell editor to the database cell. + Deze knop slaat de wijzigingen die aangebracht zijn in de celbewerker op in de cel. + + + + Apply + Toepassen + + + + Print... + Afdrukken... + + + + Open preview dialog for printing displayed text + Open voorvertoningsdialoogvenster om getoonde tekst af te drukken + + + + Open preview dialog for printing the data currently stored in the cell + Opent een voorvertoningsdialoogvenster voor het afdrukken van de de huidige gegevens in de cel + + + + Ctrl+P + + + + + Copy Hex and ASCII + HEX en ASCII kopiëren + + + + Copy selected hexadecimal and ASCII columns to the clipboard + De geselecteerde hexadecimale en ASCII kolommen kopiëren naar het klembord + + + + Ctrl+Shift+C + + + + + Autoformat + Auto-opmaak + + + + Auto-format: pretty print on loading, compact on saving. + Auto-opmaak: mooi opmaken bij het laden, comprimeren bij het opslaan. + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + Indien geselecteerd zal de auto-opmaakfunctie de gegevens bij het laden mooi opmaken, door de tekst op te delen in regels en deze dan in te laten springen. Bij het opslaan zal de auto-opmaakfunctie de gegevens comprimeren door regeleinden en onnodige witruimte te verwijderen. + + + + &Export... + &Exporteren... + + + + Export to file + Naar bestand exporteren + + + + Opens a file dialog used to export the contents of this database cell to a file. + Opent een bestandsdialoogvenster om de inhoud van deze databasecel naar een bestand te exporteren. + + + + + &Import... + &Importeren... + + + + + Import from file + Uit bestand importeren + + + + + Opens a file dialog used to import any kind of data to this database cell. + Opent een bestandsdialoogvenster om gegevens van een willekeurig gegevenstype naar deze databasecel te importeren. + + + + Set as &NULL + Omzetten naar &NULL + + + + Erases the contents of the cell + Wist de inhoud van de cel + + + + Word Wrap + Woordterugloop + + + + Wrap lines on word boundaries + Past regelterugloop toe op woordbegrenzingen + + + + + Open in default application or browser + In standaard applicatie of browser openen + + + + Open in application + In applicatie openen + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + De waarde wordt geïnterpreteerd als bestand of URL en wordt geopend in de standaard applicatie of webbrower. + + + + Save file reference... + Bestandsreferentie opslaan... + + + + Save reference to file + Referentie in bestand opslaan + + + + + Open in external application + In externe applicatie openen + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + + + + + Unsaved data in the cell editor + + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + + + + + Editing row=%1, column=%2 + + + + + No cell active. + + + + + + Image data can't be viewed in this mode. + Afbeeldingsgegevens kunnen niet worden getoond in deze modus. + + + + + Try switching to Image or Binary mode. + Probeer te wisselen naar Afbeeldings- of Binaire modus. + + + + + Binary data can't be viewed in this mode. + Binaire gegevens kunnen niet worden getoond in deze modus. + + + + + Try switching to Binary mode. + Probeer te wisselen naar Binaire modus. + + + + + Image files (%1) + Afbeeldingbestanden (%1) + + + + Choose a file to import + Kies een bestand om te importeren + + + + %1 Image + %1 Afbeelding + + + + Binary files (*.bin) + Binaire bestanden (*.bin) + + + + Choose a filename to export data + Kies een bestandsnaam om naar te exporteren + + + + Invalid data for this mode + Ongeldige gegevens voor deze modus + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + De cel bevat ongeldige %1 gegevens. Reden: %2. Weet je zeker dat je het op de cel wilt toepassen? + + + + + Type: NULL; Size: 0 bytes + + + + + + Type: Text / Numeric; Size: %n character(s) + + + + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + + + + + Type: Valid JSON; Size: %n character(s) + + + + + + + + Type: Binary; Size: %n byte(s) + + + + + + + + Couldn't save file: %1. + Kon het bestand niet opslaan: %1. + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + De gegevens zijn in een tijdelijk bestand opgeslagen en is geopend in de standaard applicatie. Je kunt het bestand nu bewerken en, wanneer je klaar bent, de opgeslagen nieuwe gegevens toepassen op de cel of de wijzingen annuleren. + + + + EditIndexDialog + + + Edit Index Schema + Schema-index bewerken + + + + &Name + &Naam + + + + &Table + &Tabel + + + + &Unique + &Uniek + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + Om de index slechts op een gedeelte van de tabel toe te passen kun je hier een WHERE clausule opgeven die slechts dát gedeelte van de tabel selecteert dat geïndexeerd dient te worden + + + + Partial inde&x clause + Gedeeltelijke inde&x-clausule + + + + Colu&mns + &Kolommen + + + + Table column + Tabelkolom + + + + Type + Type + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + Voeg een nieuwe expressiekolom toe aan de index. Expressiekolommen bevatten SQL-expressies in plaats van kolomnamen. + + + + Index column + Indexkolom + + + + Order + Sortering + + + + Deleting the old index failed: +%1 + Het verwijderen van de oude index is mislukt: +%1 + + + + Creating the index failed: +%1 + Het maken van de index is mislukt: +%1 + + + + EditTableDialog + + + Edit table definition + Tabeldefinitie bewerken + + + + Table + Tabel + + + + Advanced + Geavanceerd + + + + Database sche&ma + Database&schema + + + + Without Rowid + Zonder &rowid + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + + + + + On Conflict + + + + + Strict + + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + + + + + Fields + Velden + + + + + + Add + Toevoegen + + + + + + Remove + Verwijderen + + + + Move to top + Bovenaan plaatsen + + + + Move up + Omhoog verplaatsen + + + + Move down + Omlaag verplaatsen + + + + Move to bottom + Onderaan plaatsen + + + + + + + Name + Naam + + + + + Type + Type + + + + NN + NN + + + + Not null + Niet NULL + + + + PK + PS + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> Primaire sleutel</p></body></html> + + + + AI + AO + + + + Autoincrement + Automatisch ophogen + + + + U + U + + + + + + Unique + Uniek + + + + Default + Standaard + + + + Default value + Standaardwaarde + + + + + Check + Controle + + + + Check constraint + Controlebeperking + + + + Collation + Collatie + + + + Foreign Key + Vreemde sleutel + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_fk"/> Vreemde sleutel</p></body></html> + + + + Index Constraints + + + + + Add constraint + Beperking toevoegen + + + + Remove constraint + Beperking verwijderen + + + + + Columns + Kolommen + + + + + + SQL + SQL + + + + Foreign Keys + + + + + References + + + + + Check Constraints + + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Waarschuwing: </span>Er is iets aan deze tabeldefinitie dat onze parser niet volledig begrijpt. Het aanpassen en opslaan van deze tabel kan problemen opleveren.</p></body></html> + + + + + Primary Key + Primaire sleutel + + + + Add a primary key constraint + Voeg een primaire sleutelbeperking toe + + + + Add a unique constraint + Voeg een uniciteitsbeperking toe + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + Er kan maar een primairesleutel per tabel bestaan. Pas in plaats daarvan de al bestaande primaire sleutel aan. + + + + Error creating table. Message from database engine: +%1 + Fout bij maken van de tabel. Melding van de database: +%1 + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + Er bestaat al een veld met die naam. Hernoem dat veld eerst of kies een andere naam voor dit veld. + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + Naar deze kolom wordt verwezen in een vreemde sleutel in tabel %1 en kan daarom niet aangepast worden. + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + Er is tenminste een record waarin de waarde van dit veld NULL is. Dit maakt het onmogelijk om deze optie toe te passen. Pas de tabelgegevens eerst aan. + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + Er is tenminste een record waarin de waarde van dit veld geen geheel getal is. Dit maakt het onmogelijk om de AO-optie toe te passen. Pas de tabelgegevens eerst aan. + + + + Column '%1' has duplicate data. + + Kolom '%1' heeft gedupliceerde waarden. + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + Dit maakt het onmogelijk om de Uniek-optie toe te passen. Verwijder eerst de gedupliceerde waarden, zodat de Uniek-optie toe kan worden gepast. + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + Weet je zeker dat je het veld '%1' wilt verwijderen? +Alle waarden die momenteel opgeslagen zijn in dit veld zullen verloren gaan. + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + Voeg eerste een veld toe dat aan de volgende criteria voldoet, voordat je de 'Zonder rowid' optie toepast: + - Primaire sleutel ingeschakeld + - Automatisch ophogen uitgeschakeld + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + + + + + ExportDataDialog + + + Export data as CSV + Gegevens exporteren als CSV + + + + Tab&le(s) + &Tabel(-len) + + + + Colu&mn names in first line + &Kolomnamen op eerste regel + + + + Fie&ld separator + &Veldscheidingsteken + + + + , + , + + + + ; + ; + + + + Tab + Tab + + + + | + | + + + + + + Other + Anders + + + + &Quote character + &Scheidingsteken tekenreeks + + + + " + " + + + + ' + ' + + + + New line characters + Nieuwe-regeltekens + + + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) + + + + Unix: LF (\n) + Unix: LF (\n) + + + + Pretty print + Mooi opmaken + + + + Export data as JSON + Exporteer de gegevens als JSON + + + + exporting CSV + CSV wordt geëxporteerd + + + + + Error while writing the file '%1': %2 + + + + + + Could not open output file: %1 + Kon het uitvoerbestand niet openen: %1 + + + + exporting JSON + JSON wordt geëxporteerd + + + + + Choose a filename to export data + Kies een bestandsnaam om naar te exporteren + + + + Please select at least 1 table. + Selecteerd tenminste één tabel. + + + + Choose a directory + Kies een map + + + + Export completed. + Het exporteren is voltooid. + + + + Export finished with errors. + + + + + ExportSqlDialog + + + Export SQL... + SQL exporteren... + + + + Tab&le(s) + &Tabel(-len) + + + + Select All + Alles selecteren + + + + Deselect All + Alles deselecteren + + + + &Options + &Opties + + + + Keep column names in INSERT INTO + Kolomnamen behouden in INSERT INTO + + + + Multiple rows (VALUES) per INSERT statement + Meervoudige records (VALUES) per INSERT-instructie + + + + Export everything + Alles exporteren + + + + Export schema only + Alleen het schema exporteren + + + + Export data only + Alleen de gegevens exporteren + + + + Keep original CREATE statements + + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + Ouder schema behouden (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + Ouder schema overschrijven (DROP TABLE, daarna CREATE TABLE) + + + + Please select at least one table. + Selecteer tenminste één tabel. + + + + Choose a filename to export + Kies een bestandsnaam om naar te exporteren + + + + Export completed. + Het exporteren is voltooid. + + + + Export cancelled or failed. + Het exporteren is geannuleerd of niet gelukt. + + + + ExtendedScintilla + + + + Ctrl+H + + + + + Ctrl+F + + + + + + Ctrl+P + + + + + Find... + Zoeken... + + + + Find and Replace... + Zoeken en Vervangen... + + + + Print... + Afdrukken... + + + + ExtendedTableWidget + + + Use as Exact Filter + Als exact filter gebruiken + + + + Containing + Bevat + + + + Not containing + Bevat niet + + + + Not equal to + Niet gelijk aan + + + + Greater than + Groter dan + + + + Less than + Kleiner dan + + + + Greater or equal + Groter dan of gelijk aan + + + + Less or equal + Kleiner dan of gelijk aan + + + + Between this and... + Binnen het bereik van dit en... + + + + Regular expression + Als reguliere expressie + + + + Edit Conditional Formats... + Voorwaardelijke opmaakregels bewerken... + + + + Set to NULL + Omzetten naar NULL + + + + Cut + Knippen + + + + Copy + Kopiëren + + + + Copy with Headers + Kopiëren met kolomnamen + + + + Copy as SQL + Kopiëren als SQL + + + + Paste + Plakken + + + + Print... + Afdrukken... + + + + Use in Filter Expression + Gebruiken in filterexpressie + + + + Alt+Del + + + + + Ctrl+Shift+C + + + + + Ctrl+Alt+C + + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + De inhoud van het klembord is groter dan het geselecteerde bereik. +Wil je het desondanks invoegen? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>Niet alle gegevens zijn geladen. <b>Wil je alle gegevens laden voordat alle records geselecteerd worden?</b><p><p> <b>Nee</b> betekent dat gegevens laden gestopt wordt en de selectie niet toegepast zal worden.<br/> <b>Ja</b> betekent dat het een tijd kan duren totdat alle gegevens geladen zijn, maar de selectie wel toegepast zal worden.</p>Waarschuwing: Alle gegevens laden kan een grote hoeveelheid werkgeheugen vereisen voor grote tabellen. + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + Kan de selectie niet omzetten naar NULL. Kolom %1 heeft een NIET NULL-beperking. + + + + FileExtensionManager + + + File Extension Manager + Bestandsextensiebeheerder + + + + &Up + Om&hoog + + + + &Down + Om&laag + + + + &Add + &Toevoegen + + + + &Remove + &Verwijderen + + + + + Description + Omschrijving + + + + Extensions + Extensies + + + + *.extension + *.extensie + + + + FilterLineEdit + + + Filter + Filter + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + Deze invoervelden stellen je in staat om snelfilters toe te passen op de huidig geselecteerde tabel. +Gewoonlijk worden records die de ingevoerde tekst bevatten gefilterd. +De volgende operatoren worden ook ondersteund: +% Jokerteken +> Groter dan +< Kleiner dan +>= Groter dan of gelijk aan +<= Kleiner dan of gelijk aan += Gelijk aan: exacte overeenkomst +<> Niet gelijk aan: inverse van exacte overeenkomst +x~y Bereik: waarden tussen x en y +/regexp/ Waarden die voldoen aan de reguliere expressie + + + + Set Filter Expression + Filterexpressie toepassen + + + + What's This? + Wat is dit? + + + + Is NULL + Is NULL + + + + Is not NULL + Is niet NULL + + + + Is empty + Is leeg + + + + Is not empty + Is niet leeg + + + + Not containing... + Bevat niet... + + + + Equal to... + Gelijk aan... + + + + Not equal to... + Niet gelijk aan... + + + + Greater than... + Groter dan... + + + + Less than... + Kleiner dan... + + + + Greater or equal... + Groter dan of gelijk aan... + + + + Less or equal... + Kleiner dan of gelijk aan... + + + + In range... + Binnen het bereik... + + + + Regular expression... + Reguliere expressie... + + + + Clear All Conditional Formats + Verwijder alle voorwaardelijke opmaakregels + + + + Use for Conditional Format + Gebruiken voor voorwaardelijke opmaak + + + + Edit Conditional Formats... + Voorwaardelijke opmaakregels bewerken... + + + + FindReplaceDialog + + + Find and Replace + Zoeken en vervangen + + + + Fi&nd text: + Zoek &tekst: + + + + Re&place with: + Vervang &door: + + + + Match &exact case + Identieke onder-/boven&kast + + + + Match &only whole words + Alleen &hele woorden + + + + When enabled, the search continues from the other end when it reaches one end of the page + Indien geselecteerd zal het zoeken aan het andere einde doorgaan zodra een einde bereikt is + + + + &Wrap around + Door&gaan na einde + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + Indien geselecteerd zal, ten opzichte van de cursorpositie, achteruit in plaats van vooruit gezocht worden + + + + Search &backwards + &Omgekeerd zoeken + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>Indien geselecteerd wordt alleen gezocht in de huidige selectie.</p></body></html> + + + + &Selection only + Alleen in &selectie + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Indien geselecteerd wordt de zoekterm geïnterpreteerd als een UNIX reguliere expressie. Zie hiervoor <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Reguliere Expressies in Wikibooks (Engels)</a>.</p></body></html> + + + + Use regular e&xpressions + Gebruik reguliere e&xpressies + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + Zoek de eerstvolgende overeenkomst vanaf de cursorpositie, in de richting aangegeven door de optie "Omgekeerd zoeken" + + + + &Find Next + Volgende &zoeken + + + + F3 + + + + + &Replace + &Vervangen + + + + Highlight all the occurrences of the text in the page + Markeer alle overeenkomsten met de tekst in de pagina + + + + F&ind All + Alles z&oeken + + + + Replace all the occurrences of the text in the page + Vervang alle overeenkomsten met de tekst in de pagina + + + + Replace &All + Alles v&ervangen + + + + The searched text was not found + De gezochte tekst is niet gevonden + + + + The searched text was not found. + De gezochte tekst is niet gevonden. + + + + The searched text was replaced one time. + De gezochte tekst is één keer vervangen. + + + + The searched text was found one time. + De gezochte tekst is één keer gevonden. + + + + The searched text was replaced %1 times. + De gezochte tekst is %1 keer vervangen. + + + + The searched text was found %1 times. + De gezochte tekst is %1 keer gevonden. + + + + ForeignKeyEditor + + + &Reset + &Herstellen + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + Vreemde-sleutelclausules (ON UPDATE, ON DELETE, etc.) + + + + ImageViewer + + + Image Viewer + Afbeeldingenbekijker + + + + Reset the scaling to match the original size of the image. + Schaal de afbeelding terug naar diens oorspronkelijke grootte. + + + + Set the scaling to match the size of the viewport. + Schaal de afbeelding naar de grootte van het venster. + + + + Print... + Afdrukken... + + + + Open preview dialog for printing displayed image + Open voorvertoningsdialoogvenster om getoonde afbeelding af te drukken + + + + Ctrl+P + + + + + ImportCsvDialog + + + Import CSV file + CSV-bestand importeren + + + + Table na&me + &Tabelnaam + + + + &Column names in first line + &Kolomnamen op eerste regel + + + + Field &separator + &Veldscheidingsteken + + + + , + , + + + + ; + ; + + + + + Tab + Tab + + + + | + | + + + + + Other (printable) + Anders (afdrukbaar) + + + + + Other (code) + Anders (code) + + + + &Quote character + &Scheidingsteken tekenreeks + + + + " + " + + + + ' + ' + + + + &Encoding + &Encodering + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Other + Anders + + + + Trim fields? + Velden trimmen? + + + + Separate tables + Tabellen scheiden + + + + Advanced + Geavanceerd + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + Indien geselecteerd dan wordt een lege waarde in plaats van de standaardwaarde ingevoerd voor bestaande tabellen die een standaardwaarde hebben voor deze kolom. + + + + Ignore default &values + &Negeer standaardwaarden + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + Indien geselecteerd dan wordt het importeren afgebroken zodra een lege waarde wordt geprobeerd in te voeren in een NIET NULL veld die geen standaardwaarde kent. + + + + Fail on missing values + Afbreken bij afwezige waarden + + + + Disable data type detection + Gegevenstypedetectie uitschakelen + + + + Disable the automatic data type detection when creating a new table. + Schakel automatische gegevenstypedetectie uit als een nieuwe tabel wordt gemaakt. + + + + Use local number conventions + + + + + Use decimal and thousands separators according to the system locale. + + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + Tijdens het importeren in bestaande tabellen kunnen er conflicten optreden met primaire sleutels, unieke beperkingen en unieke indices. Deze instelling geeft je de keuze om daar een strategie voor te kiezen: standaard wordt het importeren afgebroken en teruggedraaid, maar je kunt ook kiezen om conflicterende records te negeren en dus niet te importeren, of om bestaande records te laten overschrijven door geïmporteerde records. + + + + Abort import + Importeren afbreken + + + + Ignore row + Record negeren + + + + Replace existing row + Bestaand record vervangen + + + + Conflict strategy + Conflictstrategie + + + + + Deselect All + Alles deselecteren + + + + Match Similar + Overeenkomende selecteren + + + + Select All + Alles selecteren + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + Er bestaat al een tabel met de naam '%1' en importeren in een al bestaande tabel is alleen mogelijk als het aantal kolommen overeenkomt. + + + + There is already a table named '%1'. Do you want to import the data into it? + Er bestaat al een tabel met de naam '%1'. Wil je de gegevens hierin importeren? + + + + Creating restore point failed: %1 + Maken van een herstelpunt is mislukt: %1 + + + + Creating the table failed: %1 + Maken van de tabel is mislukt: %1 + + + + importing CSV + CSV wordt geïmporteerd + + + + Could not prepare INSERT statement: %1 + + + + + Inserting row failed: %1 + Invoegen van record is mislukt: %1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + Onverwachts einde van bestand bereikt. Verzeker je ervan dat je de juiste aanhalingstekens ingesteld hebt en dat de bestandsinhoud goed geformuleerd is. + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + Het importeren van het bestand '%1' duurde %2ms. Hiervan werd %3ms gebruikt voor de rijfunctie. + + + + MainWindow + + + DB Browser for SQLite + DB-browser voor SQLite + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + Dit is de structuur van de geopende database. +Je kunt SQL-instructies vanuit een objectrij naar andere applicaties of andere vensters van 'DB-browser voor SQLite' verslepen. + + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + Waarschuwing: dit pragma kan niet uitgelezen worden en de waarde is daarom afgeleid. Dit pragma wijzigen kan ervoor zorgen dat een door een SQLite-extensie hergedefinieerde LIKE overschreven wordt. + + + + toolBar1 + werkbalk1 + + + + &File + &Bestand + + + + &Import + &Importeren + + + + &Export + &Exporteren + + + + &Edit + Be&werken + + + + &View + Bee&ld + + + + &Help + &Help + + + + Too&ls + E&xtra + + + + DB Toolbar + Databasewerkbalk + + + + Edit Database &Cell + Database&cel bewerken + + + + SQL &Log + SQL-&log + + + + Show S&QL submitted by + Toon S&QL van + + + + User + Gebruiker + + + + Application + Applicatie + + + + Error Log + Foutenlog + + + + This button clears the contents of the SQL logs + Deze knop leegt de inhoud van de SQL-logs + + + + &Clear + &Legen + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + In dit kader kun je de logs inspecteren van alle SQL-opdrachten die door de applicatie of door jezelf zijn uitgevoerd + + + + &Plot + &Plot + + + + DB Sche&ma + Databasesche&ma + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + Dit is de structuur van de geopende database. +Je kunt meerdere objectnamen vanuit de Naam-kolom naar de SQL-bewerker verslepen en je kunt hun eigenschappen dan bewerken met behulp van contextmenu's. Dit vergemakkelijkt het opstellen van SQL-instructies. +Je kunt SQL-instructies vanuit de Schema-kolom naar de SQL-bewerker of naar andere applicaties verslepen. + + + + + &Remote + Toegang op &afstand + + + + + Project Toolbar + Projectwerkbalk + + + + Extra DB toolbar + Werkbalk voor gekoppelde databases + + + + + + Close the current database file + Sluit het huidige databasebestand + + + + &New Database... + &Nieuwe database... + + + + + Create a new database file + Maak een nieuw databasebestand + + + + This option is used to create a new database file. + Deze optie wordt gebruikt om een nieuw databasebestand te maken. + + + + Ctrl+N + + + + + + &Open Database... + &Database openen... + + + + + + + + Open an existing database file + Een bestaand databasebestand openen + + + + + + This option is used to open an existing database file. + Deze optie wordt gebruikt om een bestaand databasebestand te openen. + + + + Ctrl+O + + + + + &Close Database + Database &sluiten + + + + This button closes the connection to the currently open database file + Deze knop verbreekt de verbinding met het huidig geopende databasebestand + + + + + Ctrl+F4 + + + + + &Revert Changes + Wijzigingen &terugdraaien + + + + + Revert database to last saved state + Database terugdraaien naar de laatst opgeslagen staat + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + Deze optie wordt gebruikt om het huidig geopende databasebestand terug te draaien naar de laatst opgeslagen staat. Alle wijzigingen die gemaakt zijn sinds de laatste opslag gaan verloren. + + + + &Write Changes + &Wijzigingen opslaan + + + + + Write changes to the database file + Wijzigingen opslaan in het databasebestand + + + + This option is used to save changes to the database file. + Deze optie wordt gebruikt om wijzigingen op te slaan in het databasebestand. + + + + Ctrl+S + + + + + Compact &Database... + &Database comprimeren... + + + + Compact the database file, removing space wasted by deleted records + Comprimeer het databasebestand door lege ruimte van verwijderde records te op te schonen + + + + + Compact the database file, removing space wasted by deleted records. + Comprimeer het databasebestand door lege ruimte van verwijderde records te op te schonen. + + + + E&xit + A&fsluiten + + + + Ctrl+Q + + + + + &Database from SQL file... + &Database vanuit SQL-bestand... + + + + Import data from an .sql dump text file into a new or existing database. + Importeer gegevens vanuit een .sql dump tekstbestand naar een nieuwe of bestaande database. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + Deze optie stelt je in staat om gegevens vanuit een .sql dump tekstbestand te importeren naar een nieuwe of bestaande database. De meeste databaseprogramma's kunnen SQL-dumpbestanden maken, waaronder MySQL en PostgreSQL. + + + + &Table from CSV file... + &Tabel vanuit CSV-bestand... + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Open een assistent om gegevens uit een kommagescheiden tekstbestand te importeren naar een databasetabel. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Open een assistent om gegevens uit een kommagescheiden tekstbestand (CSV) te importeren naar een databasetabel. De meeste database- en spreadsheetprogramma's kunnen CSV-bestanden maken. + + + + &Database to SQL file... + &Database naar SQL-bestand... + + + + Export a database to a .sql dump text file. + Exporteer een database naar een .sql dump tekstbestand. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + Deze optie stelt je in staat om een database te exporteren naar een .sql dump tekstbestand. SQL-dumpbestanden bevatten de benodigde gegevens om de database opnieuw te maken in de meeste databaseprogramma's, waaronder MySQL en PostgreSQL. + + + + &Table(s) as CSV file... + &Tabel(-len) naar CSV-bestand... + + + + Export a database table as a comma separated text file. + Exporteer een databasetabel naar een kommagescheiden tekstbestand. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + Exporteer een databasetabel naar een kommagescheiden tekstbestand, om deze te kunnen importeren in ander database- of spreadsheetprogramma. + + + + &Create Table... + Tabel &maken... + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Open de tabel-makenassistent, waarin je namen en velden voor een nieuwe databasetabel kunt definiëren + + + + &Delete Table... + Tabel &verwijderen... + + + + + Delete Table + Tabel verwijderen + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Open de tabel-verwijderassistent, waarin je databasetabellen kunt selecteren om te verwijderen. + + + + &Modify Table... + Tabel &wijzigen... + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + + + + + Temp Store + + + + + Secure Delete + + + + + Case Sensitive Like + + + + + Journal Mode + + + + + Journal Size Limit + + + + + Recursive Triggers + + + + + Page Size + + + + + Foreign Keys + + + + + Auto Vacuum + + + + + Max Page Count + + + + + Checkpoint Full FSYNC + + + + + + Off + + + + + + Normal + + + + + + Full + + + + + Default + Standaard + + + + File + Bestand + + + + + Memory + + + + + Delete + + + + + Truncate + + + + + Persist + + + + + WAL + + + + + Exclusive + + + + + Automatic Index + + + + + Ignore Check Constraints + + + + + Full FSYNC + + + + + WAL Auto Checkpoint + + + + + User Version + + + + + Synchronous + + + + + None + Geen + + + + Incremental + + + + + Locking Mode + + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + + + + + &Recent Files + + + + + &New Database + + + + + &Undo + + + + + + Undo last change to the database + + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + + + + + Create &Index... + &Index maken... + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + Open de index-makenassistent, waarin je een nieuwe index voor een bestaande databasetabel kunt definiëren. + + + + &Preferences... + I&nstellingen... + + + + + Open the preferences window. + Open het instellingenvenster. + + + + &DB Toolbar + &Databasewerkbalk + + + + Shows or hides the Database toolbar. + Toont of verbergt de databasewerkbalk. + + + + W&hat's This? + W&at is dit? + + + + Shift+F1 + + + + + &About + &Over + + + + &Recently opened + &Recent geopend + + + + New &tab + Nieuw &tabblad + + + + This button opens a new tab for the SQL editor + Deze knop opent een nieuw tabblad in de SQL-bewerker + + + + Ctrl+T + + + + + &Execute SQL + SQL &uitvoeren + + + + Execute all/selected SQL + Voer alle of de geselecteerde SQL uit + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + Deze knop voert de huidig geselecteerde SQL-instructies uit. Indien geen tekst geselecteerd is worden alle SQL-instructies uitgevoerd. + + + + Ctrl+Return + + + + + Open SQL file(s) + SQL-bestand(-en) openen + + + + This button opens files containing SQL statements and loads them in new editor tabs + Deze knop opent bestanden die SQL-instructies bevatten en laadt deze in nieuwe bewerkerstabbladen + + + + Ctrl+Shift+T + + + + + + + Save SQL file + SQL-bestand opslaan + + + + &Load Extension... + Extensie &laden... + + + + + Execute current line + Huidige regel uitvoeren + + + + Execute line + Regel uitvoeren + + + + This button executes the SQL statement present in the current editor line + Deze knop voert de SQL-instructies uit die zich op de huidige bewerkingsregel bevindt + + + + Shift+F5 + + + + + Export as CSV file + Exporteren als CSV-bestand + + + + Export table as comma separated values file + Tabel exporteren als bestand met kommagescheiden waarden + + + + &Wiki + &Wiki + + + + F1 + + + + + Bug &Report... + Bugs &rapporteren... + + + + Feature Re&quest... + Functionaliteit &verzoeken... + + + + Web&site + Web&site + + + + &Donate on Patreon... + &Doneren op Patreon... + + + + Sa&ve Project + P&roject opslaan + + + + &Save Project + + + + + + Save the current session to a file + De huidige sessie oplaan in een bestand + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + Deze knop stelt je in staat om alle instellingen met betrekking tot de geopende database op te slaan in een DB-browser voor SQLite-projectbestand + + + + Open &Project... + &Project openen... + + + + Open &Project + + + + + + Load a working session from a file + Een sessie laden vanuit een bestand + + + + This button lets you open a DB Browser for SQLite project file + Deze knop stelt je in staat om DB-browser voor SQLite-projectbestand te openen + + + + &Attach Database... + Database &koppelen... + + + + + Add another database file to the current database connection + Koppel nog een databasebestand aan de huidige databaseverbinding + + + + This button lets you add another database file to the current database connection + Deze knop stelt je in staat om nog een databasebestand aan de huidige databaseverbinding te koppelen + + + + &Set Encryption... + Encr&yptie instellen... + + + + + Save SQL file as + SQL-bestand opslaan als + + + + This button saves the content of the current SQL editor tab to a file + Deze knop slaat de inhoud van het huidige SQL-bewerkingstabblad op in een bestand + + + + &Browse Table + &Bladeren door tabel + + + + Copy Create statement + CREATE-instructie kopiëren + + + + Copy the CREATE statement of the item to the clipboard + De CREATE-instructie van het item kopiëren naar het klembord + + + + SQLCipher &FAQ + SQLCipher &FAQ + + + + Opens the SQLCipher FAQ in a browser window + Opent de SQLCipher FAQ in een browservenster + + + + Table(&s) to JSON... + Tabel(-&len) naar JSON-bestand... + + + + Export one or more table(s) to a JSON file + Exporteer een of meerdere tabel(-len) naar een JSON-bestand + + + + Open Data&base Read Only... + Database als &alleen-lezen openen... + + + + Open an existing database file in read only mode + Een bestaand databasebestand openen in alleen-lezenmodus + + + + Ctrl+Shift+O + + + + + Save results + Resultaten opslaan + + + + Save the results view + Het resultatenoverzicht opslaan + + + + This button lets you save the results of the last executed query + Deze knop stelt je in staat om de resultaten van de laatst uitgevoerde opdracht op te slaan + + + + + Find text in SQL editor + Tekst zoeken in de SQL-bewerker + + + + Find + Zoeken + + + + This button opens the search bar of the editor + Deze knop opent de zoekbalk van de bewerker + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + Tekst zoeken of vervangen in de SQL-bewerker + + + + Find or replace + Zoeken of vervangen + + + + This button opens the find/replace dialog for the current editor tab + Deze knop opent het zoek-en-vervangdialoogvenster voor het huidige bewerkerstabblad + + + + Ctrl+H + + + + + Export to &CSV + Exporteren naar &CSV + + + + Export to &JSON + + + + + Save as &view + Opslaan als &view + + + + Save as view + Opslaan als view + + + + Shows or hides the Project toolbar. + Toont of verbergt de projectwerkbalk. + + + + Extra DB Toolbar + Gekoppelde-databaseswerkbalk + + + + &Open Database + + + + + New In-&Memory Database + Nieuwe werk&geheugendatabase + + + + Drag && Drop SELECT Query + + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + + + + + Drag && Drop Qualified Names + Gekwalificeerde namen verslepen + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + Gebruik gekwalificeerde namen (bijv. "Tabel"."Veld") wanneer ik objecten versleep naar de bewerker + + + + Drag && Drop Enquoted Names + Aangehaalde namen verslepen + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + Gebruik aangehaalde entiteitsnamen (bijv. "Tabel1") wanneer ik objecten versleep naar de bewerker + + + + &Integrity Check + &Integriteit controleren + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + Voert het pragma integrity_check uit op de geopende database en toont de resultaten in het tabblad SQL uitvoeren. Dit pragma doet een integriteitscontrole over de gehele database. + + + + &Foreign-Key Check + &Vreemde sleutels controleren + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + Voert het pragma foreign_key_check uit op de geopende database en toont de resultaten in het tabblad SQL uitvoeren + + + + &Quick Integrity Check + Integriteit &snel controleren + + + + Run a quick integrity check over the open DB + Voert een snelle integriteitscontrole uit op de geopende database + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + Voert het pragma quick_check uit op de geopende database en toont de resultaten in het tabblad SQL uitvoeren. Dit commando voert veel van de controles uit die het pragma integrity_check ook uitvoert, maar verloopt veel sneller. + + + + &Optimize + &Optimaliseren + + + + Attempt to optimize the database + Probeert de database te optimaliseren + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + Voert het pragma optimize uit op de geopende database. Dit pragma kan optimalisaties uitvoeren die de prestaties van toekomstige SQL-opdrachten mogelijk verbeteren. + + + + + Print + Afdrukken + + + + Print text from current SQL editor tab + Tekst uit het huidige SQL-bewerkerstabblad afdrukken + + + + Open a dialog for printing the text in the current SQL editor tab + Opent een dialoogvenster voor het afdrukken van tekst uit het huidige SQL-bewerkerstabblad + + + + + Ctrl+P + + + + + Print the structure of the opened database + De structuur van de geopende database afdrukken + + + + Open a dialog for printing the structure of the opened database + Opent een dialoogvenster voor het afdrukken van de structuur van de geopende database + + + + Un/comment block of SQL code + Blok SQL-code wel/niet commentaar + + + + Un/comment block + Blok wel/niet commentaar + + + + Comment or uncomment current line or selected block of code + De huidige regel of het geselecteerde codeblok wel/niet markeren als commentaar + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + Markeert het geselecteerde codeblok, of de huidige regel indien er geen selectie is, wel/niet als commentaar. Het gehele blok wordt omgezet op basis van de eerste regel. + + + + Ctrl+/ + + + + + Stop SQL execution + SQL uitvoeren stoppen + + + + Stop execution + Uitvoeren stoppen + + + + Stop the currently running SQL script + Stop het SQL script dat nu uitgevoerd wordt + + + + &Save Project As... + Pr&oject opslaan als... + + + + + + Save the project in a file selected in a dialog + Het project opslaan in een bestand dat je selecteert in een dialoogvenster + + + + Save A&ll + A&lles opslaan + + + + + + Save DB file, project file and opened SQL files + Het databasebestand, projectbestand en alle geopende SQL-bestanden opslaan + + + + Ctrl+Shift+S + + + + + Browse Table + Bladeren door tabel + + + + Close Pro&ject + Pro&ject sluiten + + + + + Close project and database files and return to the initial state + Het project en databasebestanden sluiten en terugkeren naar de oorspronkelijke staat + + + + + Ctrl+Shift+W + + + + + Table from CSV data in Clipboard... + + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + + + + + Show &Row Counts + + + + + This shows the number of rows for each table and view in the database. + + + + + Save Database &As... + + + + + Save the current database as a different file + + + + + Refresh + Verversen + + + + Reload the database structure + + + + + Ctrl+Shift+F4 + + + + + + Detach Database + Database ontkoppelen + + + + + Detach database file attached to the current database connection + Ontkoppel het databasebestand dat aan de huidige databaseverbinding gekoppeld is + + + + + Ctrl+W + + + + + Ctrl+Tab + + + + + Ctrl+Shift+Tab + + + + + Automatically load the last opened DB file at startup + + + + + Clear List + Lijst legen + + + + Ctrl+L + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Ctrl+E + + + + + Window Layout + Vensterindeling + + + + Reset Window Layout + Vensterindeling herstellen + + + + Ctrl+0 + + + + + Simplify Window Layout + Vensterindeling versimpelen + + + + Alt+Shift+0 + + + + + Dock Windows at Bottom + Vensters dokken aan onderzijde + + + + Dock Windows at Left Side + Vensters dokken aan de linkerzijde + + + + Dock Windows at Top + Vensters dokken aan de bovenzijde + + + + The database is currently busy. + De database is momenteel bezig. + + + + Click here to interrupt the currently running query. + Klik hier om het SQL script dat nu uitgevoerd wordt te onderbreken. + + + + Encrypted + Versleuteld + + + + Database is encrypted using SQLCipher + Database is versleuteld met SQLCipher + + + + Read only + Aleen-lezen + + + + Database file is read only. Editing the database is disabled. + Het databasebestand is alleen-lezen. Het bewerken van de database is uitgeschakeld. + + + + Database encoding + Databasecodering + + + + Alt+Shift+W + + + + + + Choose a database file + Kies een databasebestand + + + + Could not open database file. +Reason: %1 + Kon het databasebestand niet openen. +Reden: %1 + + + + + + Choose a filename to save under + Kies een bestandsnaam om in op te slaan + + + + In-Memory database + Werkgeheugendatabase + + + + Choose a database file to save under + + + + + Error while saving the database to the new file. + + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + Je voert nog steeds SQL-instructies uit. Het sluiten van de database zal het uitvoeren stoppen en de database daarmee mogelijk inconsistent maken. Weet je zeker dat je de database wilt sluiten? + + + + Do you want to save the changes made to the project file '%1'? + Wil je de wijzigingen opslaan die je de gemaakt hebt voor projectbestand %1? + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + Weet je zeker dat je de tabel '%1' wilt verwijderen? +Alle gegevens die met deze tabel geassocieerd worden zullen verloren gaan. + + + + Are you sure you want to delete the view '%1'? + Weet je zeker dat je de view '%1' wilt verwijderen? + + + + Are you sure you want to delete the trigger '%1'? + Weet je zeker dat je de trigger '%1' wilt verwijderen? + + + + Are you sure you want to delete the index '%1'? + Weet je zeker dat je de index '%1' wilt verwijderen? + + + + Error: could not delete the table. + Fout: kon de tabel niet verwijderen. + + + + Error: could not delete the view. + Fout: kon de view niet verwijderen. + + + + Error: could not delete the trigger. + Fout: kon de trigger niet verwijderen. + + + + Error: could not delete the index. + Fout: kon de index niet verwijderen. + + + + Message from database engine: +%1 + Melding van de database: +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + Het bewerken van de tabel vereist dat niet-opgeslagen wijzigingen nu opgeslagen worden. +Weet je zeker dat de database op wilt slaan? + + + + Error checking foreign keys after table modification. The changes will be reverted. + Fout bij het controleren van vreemde sleutels na tabelwijzigingen. De wijzigingen zullen teruggedraaid worden. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + Deze tabel kwam niet door de vreemde-sleutelscontrole.<br/>Voer 'Extra | Vreemde sleutels controleren' uit en repareer de gerapporteerde problemen. + + + + Edit View %1 + View %1 bewerken + + + + Edit Trigger %1 + Trigger %1 bewerken + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + Je voert momenteel al SQL-instructies uit. Wil je deze stoppen en in plaats daarvan de huidige instructies uitvoeren? Wees je ervan bewust dat dit ervoor kan zorgen dat de database inconsistent wordt. + + + + -- EXECUTING SELECTION IN '%1' +-- + -- SELECTIE WORDT UITGEVOERD IN '%1' +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- REGEL WORDT UITGEVOERD IN '%1' +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- ALLES WORDT UITGEVOERD IN '%1' +-- + + + + + At line %1: + In regel %1: + + + + Result: %1 + Resultaat: %1 + + + + Result: %2 + Resultaat: %2 + + + + %1 rows returned in %2ms + %1 records geretourneerd in %2ms + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + Vacuümeren of pragma's omzetten zal jouw huidige transactie committeren. +Weet je het zeker? + + + + Execution finished with errors. + Uitvoering voltooid met fouten. + + + + Execution finished without errors. + Uitvoering voltooid zonder fouten. + + + + Choose text files + Kies tekstbestanden + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + Er zijn fouten opgetreden tijdens het opslaan van het databasebestand. Daarom zijn niet alle wijzigingen opgeslagen. Je dient de volgende fouten eerst op te lossen: + +%1 + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + Weet je zeker dat je alle wijzigingen die je gemaakt hebt in databasebestand '%1', nadat je deze voor het laatst opgeslagen hebt, ongedaan wilt maken? + + + + Choose a file to import + Kies een bestand om te importeren + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + Wil je een nieuw databasebestand aanmaken om de geïmporteerde gegevens in te bewaren? +Als je nee antwoordt, wordt geprobeerd om de gegevens uit het SQL-bestand te importeren in de huidige database. + + + + File %1 already exists. Please choose a different name. + Bestand %1 bestaat al. Kies een andere naam. + + + + Error importing data: %1 + Fout bij het importeren van de gegevens: %1 + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + Importeren voltooid. Sommige vreemde-sleutelbeperkingen werden echter geschonden. Repareer deze voordat je opslaat. + + + + Import completed. + Importeren voltooid. + + + + Delete View + View verwijderen + + + + Modify View + View wijzigen + + + + Delete Trigger + Trigger verwijderen + + + + Modify Trigger + Trigger wijzigen + + + + Delete Index + Index verwijderen + + + + Modify Index + Index wijzigen + + + + Modify Table + Tabel wijzigen + + + + Opened '%1' in read-only mode from recent file list + '%1' geopend vanuit recent-geopende-bestandenlijst in alleen-lezenmodus + + + + Opened '%1' from recent file list + '%1' geopend vanuit recent-geopende-bestandenlijst + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (alleen-lezen) + + + + Open Database or Project + Database of project openen + + + + Attach Database... + Database koppelen... + + + + Import CSV file(s)... + CSV-bestand(-en) importeren... + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + Selecteer de handeling die toegepast moet worden op het gesleepte bestand. <br/>Let op: alleen 'Importeren' kan op meerdere bestanden tegelijk toegepast worden. + Selecteer de handeling die toegepast moet worden op de gesleepte bestanden). <br/>Let op: alleen 'Importeren' kan op meerdere bestanden tegelijk toegepast worden. + + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + Pragma's omzetten zal jouw huidige transactie committeren. +Weet je het zeker? + + + + Do you want to save the changes made to SQL tabs in a new project file? + Wil je de wijzigingen die je in de SQL-tabbladen gemaakt hebt opslaan in een nieuw projectbestand? + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + Wil je de wijzigingen die je in de SQL-tabbladen gemaakt hebt opslaan in het projectbestand '%1'? + + + + Do you want to save the changes made to the SQL file %1? + Wil je de wijzigingen die je in SQL-bestand %1 gemaakt hebt opslaan? + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + De instructies in tabblad '%1' worden nog steeds uitgevoerd. Het sluiten van het tabblad zal het uitvoeren stoppen en de database daarmee mogelijk inconsistent maken. Weet je zeker dat je het tabblad wilt sluiten? + + + + Select SQL file to open + Selecteer SQL-bestanden om te openen + + + + Text files(*.sql *.txt);;All files(*) + Tekstbestanden(*.sql *.txt);;Alle bestanden(*) + + + + Select file name + Selecteer bestandsnaam + + + + Select extension file + Selecteer extensiebestand + + + + Extension successfully loaded. + Extensie laden gelukt. + + + + Error loading extension: %1 + Fout bij het laden van extensie: %1 + + + + Could not find resource file: %1 + Kon het bronbestand niet vinden: %1 + + + + + Don't show again + Toon dit niet nogmaals + + + + New version available. + Nieuwe versie beschikbaar. + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + Er is een nieuwe versie van DB-browser voor SQLite beschikbaar (%1.%2.%3).<br/><br/>Je kunt deze downloaden op <a href='%4'>%4</a>. + + + + Choose a project file to open + Kies een projectbestand om te openen + + + + DB Browser for SQLite project file (*.sqbpro) + DB-browser voor SQLite-projectbestanden (*.sqbpro) + + + + DB file '%1' could not be opened + + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + Dit projectbestand gebruikt een oud bestandsformaat omdat het gemaakt is met versie 3.10 of lager van DB-browser voor SQLite. Dit bestandsformaat wordt niet meer volledig ondersteund. Als je het volledig wilt kunnen laden, gebruik dan versie 3.12 van DB-browser voor SQLite om het om te zetten naar het nieuwe bestandsformaat. + + + + Table '%1' not found; settings ignored + + + + + Could not open project file for writing. +Reason: %1 + Kon het projectbestand niet openen om naar te schrijven. +Reden: %1 + + + + -- Reference to file "%1" (not supported by this version) -- + + + + + Project saved to file '%1' + Project opgeslagen in bestand '%1' + + + + Yes. Don't ask again + Ja. Niet nogmaals vragen + + + + Collation needed! Proceed? + Collatie vereist! Doorgaan? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + Een table in deze database vereist een speciale collatiefunctie '%1' die deze applicatie niet kan bieden zonder extra informatie. +Wees je er bewust van dat als je doorgaat er slechte dingen kunnen gebeuren met jouw database. +Maak een backup! + + + + creating collation + collatie aan het maken + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + Geef een nieuwe naam voor het SQL-tabblad. Gebruik het '&&'-teken om de een van de volgende tekens als sneltoets in te stellen. + + + + Please specify the view name + Geef de viewnaam op + + + + There is already an object with that name. Please choose a different name. + Er bestaat al een object met die naam. Kies een andere naam. + + + + View successfully created. + View maken gelukt. + + + + Error creating view: %1 + Fout bij het maken van view: %1 + + + + This action will open a new SQL tab for running: + Deze handeling opent een nieuw SQL-tabblad om het volgende uit te voeren: + + + + This action will open a new SQL tab with the following statements for you to edit and run: + Deze handeling opent een nieuw SQL-tabblad met volgende instructies die je zodoende kunt bewerken en uitvoeren: + + + + Press Help for opening the corresponding SQLite reference page. + Druk op Help om de bijbehorende SQLlite-referentiepagina te openen. + + + + Busy (%1) + Bezig (%1) + + + + Rename Tab + Tabblad hernoemen + + + + Duplicate Tab + Tabblad dupliceren + + + + Close Tab + Tabblad sluiten + + + + Opening '%1'... + Opent '%1'... + + + + There was an error opening '%1'... + Fout bij het openen van '%1'... + + + + Value is not a valid URL or filename: %1 + Waarde is geen geldige URL of bestandsnaam: %1 + + + + NullLineEdit + + + Set to NULL + Omzetten naar NULL + + + + Alt+Del + + + + + PlotDock + + + Plot + Plot + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>Dit paneel toont de lijst van kolommen van de tabel die nu doorgebladerd wordt of van de zojuist uitgevoerde SQL-opdracht. Je kunt de kolommen selecteren die je wilt gebruiken als X- of Y-assen in de plot hieronder. De tabel toont gedetecteerde astypen die de plot zullen beïnvloeden. Voor de Y-as kun je alleen numerieke kolommen gebruiken, maar voor de X-as kun je de volgende gegevenstypen selecteren:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Datum/Tijd</span>: tekenreeksen volgens het formaat &quot;yyyy-MM-dd hh:mm:ss&quot; of &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Datum</span>: tekenreeksen volgens het formaat &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Tijd</span>: tekenreeksen volgens het formaat &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: andersoortige tekenreeksformaten. Als je dit selecteert voor de X-as dan wordt een staafdiagram geplot met de kolomwaarden als labels voor de staven</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeriek</span>: gehele of reële getallen</li></ul><p>Door dubbel te klikken op de Y-cellen kun je de kleur voor die grafiek aanpassen.</p></body></html> + + + + Columns + Kolommen + + + + X + X + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + Astype + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + Hier wordt de plot getekend zodra je hierboven x- en y-waarden selecteert. + +Klik op punten om deze in de plot en in de tabel te selecteren. Ctrl+klik om meerdere punten te selecteren. + +Gebruik het muiswiel om te zoomen en sleep met de muis om het asbereik te veranderen. + +Selecteer de as of aslabels om alleen in die richting te slepen en te zoomen. + + + + Line type: + Lijntype: + + + + + None + Geen + + + + Line + Lijn + + + + StepLeft + Stap links + + + + StepRight + Stap rechts + + + + StepCenter + Stap gecentreerd + + + + Impulse + Impuls + + + + Point shape: + Puntvorm: + + + + Cross + Kruis + + + + Plus + Plus + + + + Circle + Cirkel + + + + Disc + Discus + + + + Square + Vierkant + + + + Diamond + Diamant + + + + Star + Ster + + + + Triangle + Driehoek + + + + TriangleInverted + Geïnverteerde driehoek + + + + CrossSquare + Vierkant met kruis + + + + PlusSquare + Vierkant met plus + + + + CrossCircle + Cirkel met kruis + + + + PlusCircle + Cirkel met plus + + + + Peace + Vredesteken + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>Huidige plot opslaan...</p><p>Bestandsformaat volgens extensie (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + Huidige plot opslaan... + + + + + Load all data and redraw plot + Laad alle gegevens en teken plot opnieuw + + + + Copy + Kopiëren + + + + Print... + Afdrukken... + + + + Help + + + + + Show legend + Legenda tonen + + + + Stacked bars + Gestapelde staven + + + + Fixed number format + + + + + Date/Time + Datum/Tijd + + + + Date + Datum + + + + Time + Tijd + + + + + Numeric + Numeriek + + + + Label + Label + + + + Invalid + Ongeldig + + + + + + Row # + Record # + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + Laad alle gegevens en teken plot opnieuw. +Waarschuwing: door het partiële laadmechanisme zijn nog niet alle gegevens zijn uit de tabel opgehaald. + + + + Choose an axis color + Kies een askleur + + + + Choose a filename to save under + Kies een bestandsnaam om in op te slaan + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Alle bestanden(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + Dit plot bevat curves, maar de geselecteerde lijnstijl kan alleen toegepast worden op diagrammen die gesorteerd worden op X. Sorteer daarom de tabel of SQL-opdracht op X of selecteer een stijl die curves ondersteunt: Geen of Lijn. + + + + Loading all remaining data for this table took %1ms. + Het laden van alle overgebleven gegevens voor deze tabel duurde %1ms. + + + + PreferencesDialog + + + Preferences + Voorkeuren + + + + &General + &Algemeen + + + + Default &location + Standaard&locatie + + + + Remember last location + Onthoud laatste locatie + + + + Always use this location + Gebruik altijd deze locatie + + + + Remember last location for session only + Onthoud laatste locatie alleen gedurende sessie + + + + + + ... + ... + + + + Lan&guage + &Taal + + + + Toolbar style + Werkbalkstijl + + + + + + + + Only display the icon + Toon alleen het icoon + + + + + + + + Only display the text + Toon alleen de tekst + + + + + + + + The text appears beside the icon + Toon de tekst naast het icoon + + + + + + + + The text appears under the icon + Toon de tekst onder het icoon + + + + + + + + Follow the style + Volg de stijl + + + + Show remote options + Toon 'Toegang op afstand'-opties + + + + + + + + + + + + + + enabled + inschakelen + + + + Automatic &updates + Automatische &updates + + + + DB file extensions + Databasebestandsextensies + + + + Manage + Beheren + + + + Main Window + Hoofdvenster + + + + Database Structure + Databasestructuur + + + + Browse Data + Gegevensbrowser + + + + Execute SQL + SQL uitvoeren + + + + Edit Database Cell + Databasecel bewerken + + + + When this value is changed, all the other color preferences are also set to matching colors. + Indien deze waarde aangepast wordt, dan worden alle andere kleurvoorkeuren ook aangepast naar die stijl. + + + + Follow the desktop style + Volg de desktopstijl + + + + Dark style + Donkere stijl + + + + Application style + Applicatiestijl + + + + This sets the font size for all UI elements which do not have their own font size option. + Dit bepaalt het lettertypegrootte voor gebruikersinterface-elementen die geen eigen lettertypegrootte-instelling hebben. + + + + Font size + Lettertypegrootte + + + + Max Recent Files + Grootte recente bestandenlijst + + + + Prompt to save SQL tabs +in new project file + Vraag om SQL-tabbladen op te +slaan in nieuw projectbestand + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + Indien ingeschakeld toont de SQL-bewerker een dialoogvenster om het opslaan van het project mee te bevestigen zodra het SQL-bewerkingtabblad gesloten wordt. + + + + &Database + &Database + + + + Database &encoding + Database&codering + + + + Open databases with foreign keys enabled. + Databases openen met vreemde-sleutelondersteuning ingeschakeld. + + + + &Foreign keys + &Vreemde sleutels + + + + Remove line breaks in schema &view + Verwijder regeleinden in schema&weergave + + + + Prefetch block si&ze + Prefetch-&blokgrootte + + + + Default field type + Standaard veldgegevenstype + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + Indien geselecteerd worden de regeleinden verwijderd uit de schemakolom van het databasestructuurtabblad, -dock en uit geprinte afdrukken. + + + + Database structure font size + Lettertypegrootte databasestructuur + + + + SQ&L to execute after opening database + S&QL uitvoeren na het openen van database + + + + Data &Browser + Gegevens&browser + + + + Font + Lettertype + + + + &Font + &Lettertype + + + + Font si&ze + Lettertype&grootte + + + + Content + Inhoud + + + + Symbol limit in cell + Symboollimiet in cel + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + Dit bepaalt het maximum aantal items dat voor sommige functionaliteiten met intensieve berekeningen toegestaan is: +Het maximum aantal records in een tabel om waarde-aanvulling in te schakelen aan de hand van de huidige invoer in de kolom. +Het maximaal aantal indices in een selectie om sommen en gemiddelden berekenen in te schakelen. +Voer 0 in om deze functionaliteiten uit te schakelen. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + Dit bepaalt het maximum aantal records in een tabel om waarde-aanvulling in te schakelen aan de hand van de huidige invoer in de kolom. +Voer 0 in om waarde-aanvulling uit te schakelen. + + + + Threshold for completion and calculation on selection + Drempelwaarde voor aanvullingen en berekeningen op selecties + + + + Show images in cell + Toon afbeeldingen in cel + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + Indien geselecteerd wordt in de cellen een voorvertoning getoond van BLOBs die afbeeldingsgegevens bevatten. Dit kan de prestaties van de gegevensbrowser echter beïnvloeden. + + + + Field display + Veldweergave + + + + Displayed &text + Weergegeven &tekst + + + + Binary + Binair + + + + NULL + NULL + + + + Regular + Gewoon + + + + + + + + + + + Click to set this color + Klik om een kleur te selecteren + + + + Text color + Tekstkleur + + + + Background color + Achtergrondkleur + + + + + Preview only (N/A) + Enkel voorvertoning (N/B) + + + + Filters + Filters + + + + Escape character + Escape-teken + + + + Delay time (&ms) + Vertragingstijd (&ms) + + + + Light style + + + + + Formatted + + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + Bepaalt de tijd die gewacht wordt voordat een nieuw filter wordt toegepast. Voer 0 in om wachten uit te schakelen. + + + + &SQL + &SQL + + + + Context + Context + + + + Colour + Kleur + + + + Bold + Vet + + + + Italic + Cursief + + + + Underline + Onderstreept + + + + Keyword + Sleutelwoord + + + + Function + Functie + + + + Table + Tabel + + + + Comment + Commentaar + + + + Identifier + Entiteitsnaam + + + + String + Tekenreeks + + + + Current line + Huidige regel + + + + Background + Achtergrond + + + + Foreground + Voorgrond + + + + Selection background + Selectie-achtergrond + + + + Selection foreground + Selectie-voorgrond + + + + Highlight + Markering + + + + SQL editor &font + &Lettertype SQL-bewerker + + + + SQL &editor font size + Lettertypegrootte SQL-b&ewerker + + + + SQL &results font size + Lettertypegrootte SQL-&resultaten + + + + Tab size + Tabbreedte + + + + Use tabs for indentation + + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + + + + + &Wrap lines + Regelteru&gloop toepassen + + + + Never + Nooit + + + + At word boundaries + Op woordbegrenzingen + + + + At character boundaries + Op letterbegrenzingen + + + + At whitespace boundaries + Op witruimtebegrenzingen + + + + &Quotes for identifiers + &Aanhalingstekens voor entiteitsnamen + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + Kies het aanhalingstekensbeleid van de applicatie voor het demarceren van entiteitsnamen in SQL-code. + + + + "Double quotes" - Standard SQL (recommended) + "Dubbele aanhalingstekens" - Standaard SQL (aanbevolen) + + + + `Grave accents` - Traditional MySQL quotes + `Accent graves` - Traditionele MySQL aanhalingstekens + + + + [Square brackets] - Traditional MS SQL Server quotes + [Rechte haakjes] - Traditionele MS SQL-Server aanhalingstekens + + + + Code co&mpletion + Code-aan&vulling + + + + Keywords in &UPPER CASE + Sleutelwoorden in &BOVENKAST + + + + When set, the SQL keywords are completed in UPPER CASE letters. + Indien geselecteerd worden SQL-sleutelwoorden voltooid in BOVENKAST-letters. + + + + Error indicators + Foutindicatoren + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + Indien geselecteerd dan worden de SQL-coderegels die de fouten tijdens de laatste uitvoering veroorzaakten gemarkeerd en het resultatenkader toont de fout op de achtergrond + + + + Hori&zontal tiling + Hori&zontaal tegelen + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + Indien geselecteerd worden de SQL-bewerker en de resultatenweergavetabel naast elkaar, in plaats van over elkaar heen, getoond. + + + + Close button on tabs + Sluitknoppen op tabbladen + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + Indien geselecteerd krijgen SQL-bewerkingstabbladen een sluitknop. Je kunt echter ook altijd het contextmenu of sneltoetsen gebruiken om ze te sluiten. + + + + &Extensions + &Extensies + + + + Select extensions to load for every database: + Selecteer extensies die voor iedere database geladen dienen te worden: + + + + Add extension + Extensie toevoegen + + + + Remove extension + Extensie verwijderen + + + + Select built-in extensions to load for every database: + + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>Hoewel SQLite de REGEXP operator ondersteunt heeft ze geen reguliere-expressiesalgoritme<br/>geïmplementeerd, maar doet ze hiervoor een beroep op de hostapplicatie. DB-browser voor SQLite<br/>implementeert dit algoritme voor jou, zodat je REGEXP direct kunt gebruiken.<br/>Omdat er echter meerdere implementaties mogelijk zijn en je mogelijk een andere implementatie<br/>wilt gebruiken, staat het je vrij om onze implementatie uit te schakelen en je eigen implementatie te laden<br/>via een extensie. Hiervoor is een herstart van de applicatie nodig.</p></body></html> + + + + Disable Regular Expression extension + Schakel extensie voor reguliere expressies uit + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite biedt een SQL-functie om extensies te laden vanuit een gedeelde bibliotheek. Activeer deze optie als je de <span style=" font-style:italic;">load_extension()</span> functie vanuit SQL-code wilt aanroepen.</p><p>Om veiligheidsredenen is deze manier van extensies laden standaard uitgeschakeld en dient via deze optie in te worden geschakeld. Je kunt extensies echter altijd laden via de gebruikersinterface, zelfs als deze optie uitgeschakeld is.</p></body></html> + + + + Allow loading extensions from SQL code + Extensies laden vanuit SQL-code toestaan + + + + Remote + Toegang op afstand + + + + Your certificates + Jouw certificaten + + + + File + Bestand + + + + + Subject CN + Subject GN + + + + Subject Common Name + Subject Gebruikelijk Naam + + + + Issuer CN + Verstrekker GN + + + + Issuer Common Name + Verstrekker Gebruikelijke Naam + + + + + Valid from + Geldig vanaf + + + + + Valid to + Geldig tot + + + + + Serial number + Serienummer + + + + CA certificates + CA-certificaten + + + + Common Name + Gebruikelijke naam + + + + Subject O + Subject O + + + + Organization + Organisatie + + + + Clone databases into + Database klonen naar + + + + Proxy + Proxy + + + + Configure + Instellen + + + + Export Settings + Instellingen exporteren + + + + Import Settings + Instellingen importeren + + + + + Choose a directory + Kies een map + + + + + The language will change after you restart the application. + De taal verandert nadat je de applicatie opnieuw hebt opgestart. + + + + Select extension file + Selecteer extensiebestand + + + + Extensions(*.so *.dylib *.dll);;All files(*) + Extensies(*.so *.dylib *.dll);;Alle bestanden(*) + + + + Import certificate file + Certificaatbestand importeren + + + + No certificates found in this file. + Geen certificaten gevonden in dit bestand. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + Weet je zeker dat je dit certificaat wilt verwijderen? Alle certificaatgegevens zullen worden verwijderd uit de applicatie-instellingen! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + Weet je zeker dat je alle opgeslagen instellingen wilt verwijderen? +Al jouw instellingen zullen worden verwijderd en de standaardinstellingen zullen worden gebruikt. + + + + Save Settings File + Instellingenbestand opslaan + + + + + Initialization File (*.ini) + Initialisatiebestand (*.ini) + + + + The settings file has been saved in location : + + Het instellingenbestand is opgeslagen in: + + + + + Open Settings File + Instellingenbestand openen + + + + The settings file was loaded properly. + Het instellingenbestand is correct geladen. + + + + The selected settings file is not a normal settings file. +Please check again. + Het gekozen instellingenbestand is geen normaal instellingenbestand. Controleer het nogmaals. + + + + ProxyDialog + + + Proxy Configuration + Proxy-instellingen + + + + Pro&xy Type + Pro&xytype + + + + Host Na&me + &Hostnaam + + + + Port + &Poort + + + + Authentication Re&quired + &Authenticatie vereist + + + + &User Name + &Gebruikersnaam + + + + Password + &Wachtwoord + + + + None + Geen + + + + System settings + Systeeminstellingen + + + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 + + + + QObject + + + Left + Links + + + + Right + Rechts + + + + Center + Gecentreerd + + + + Justify + Uitgevuld + + + + All files (*) + Alle bestanden (*) + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + SQLite-databasebestanden (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + DB-browser voor SQLite-projectbestanden (*.sqbpro) + + + + SQL Files (*.sql) + SQL-bestanden (*.sql) + + + + All Files (*) + Alle bestanden (*) + + + + Text Files (*.txt) + Tekstbestanden (*.txt) + + + + Comma-Separated Values Files (*.csv) + Kommagescheiden bestanden (*.csv) + + + + Tab-Separated Values Files (*.tsv) + Tabgescheiden bestanden (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + Scheidingstekengescheiden bestanden (*.dsv) + + + + Concordance DAT files (*.dat) + Concordance-DAT-bestanden (*.dat) + + + + JSON Files (*.json *.js) + JSON-bestanden (*.json *.js) + + + + XML Files (*.xml) + XML-bestanden (*.xml) + + + + Binary Files (*.bin *.dat) + Binaire bestanden (*.bin *.dat) + + + + SVG Files (*.svg) + SVG-bestanden (*.svg) + + + + Hex Dump Files (*.dat *.bin) + Hexdump-bestand (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + Extensies (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + Initialisatiebestand (*.ini) + + + + Error importing data + Fout bij het importeren van de gegevens + + + + from record number %1 + van recordnummer %1 + + + + . +%1 + . +%1 + + + + Importing CSV file... + CSV-bestand importeren... + + + + Cancel + Annuleren + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + SQLite-databasebestanden (*.db *.sqlite *.sqlite3 *.db3) + + + + QsciCommand + + Paste + Plakken + + + Cancel + Annuleren + + + + QsciLexerCPP + + Default + Standaard + + + Keyword + Sleutelwoord + + + Identifier + Entiteitsnaam + + + + QsciLexerJSON + + Default + Standaard + + + String + Tekenreeks + + + + QsciLexerJavaScript + + Regular expression + Als reguliere expressie + + + + QsciLexerPython + + Default + Standaard + + + Comment + Commentaar + + + Keyword + Sleutelwoord + + + Identifier + Entiteitsnaam + + + + QsciLexerSQL + + Default + Standaard + + + Comment + Commentaar + + + Keyword + Sleutelwoord + + + Identifier + Entiteitsnaam + + + + QsciScintilla + + Select All + Alles selecteren + + + + RemoteCommitsModel + + + Commit ID + Commit ID + + + + Message + Bericht + + + + Date + Datum + + + + Author + Auteur + + + + Size + Grootte + + + + Authored and committed by %1 + Geautoriseerd en gecommitteerd door %1 + + + + Authored by %1, committed by %2 + Geautoriseerd door %1, gecommitteerd door %2 + + + + RemoteDatabase + + + Error opening local databases list. +%1 + Fout bij het openen van lijst met lokale databases. +%1 + + + + Error creating local databases list. +%1 + Fout bij het maken van lijst met lokale databases. +%1 + + + + RemoteDock + + + Remote + Toegang op afstand + + + + Identity + Identiteit + + + + Push currently opened database to server + Push huidig geopende database naar server + + + + Upload + Uploaden + + + + DBHub.io + DBHub.io + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>In dit paneel kun je externe databases van de dbhub.io website toevoegen aan DB-browser voor SQLite. Allereerst heb je een identiteit nodig:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Log in op de dbhub.io website (gebruik bijvoorbeeld jouw GitHub account of wat je maar wilt)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Klik de knop &quot;Generate client certificate&quot; (dat is jouw identiteit). Daarmee krijg je een certificaatbestand (sla deze op, op jouw lokale schijf).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ga vervolgens naar het tabblad 'Toegang op afstand', in het instellingenvenster van DB-browser voor SQLite. Klik op de knop om een nieuw certificaat toe te voegen aan DB-browser for SQLite en kies dan het zojuist gedownloade certificaatbestand.</li></ol><p>Nu toont het paneel 'Toegang op afstand' jouw identiteit en kun je externe databases toevoegen.</p></body></html> + + + + Local + Lokaal + + + + Current Database + Huidige database + + + + Clone + Klonen + + + + &User + + + + + &Database + &Database + + + + Branch + Tak + + + + Commits + Commits + + + + Commits for + Commits voor + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>Je gebruikt momenteel een ingebouwde, alleen-lezenindentiteit. Om jouw database te uploaden dien je jouw DBHub.io-account in te stellen en te gebruiken.</p><p>Nog geen DBHub.io account? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Maak er nu een aan</span></a> en importeer jouw certificaat <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">hier</span></a> om jouw databases te delen.</p><p>Bezoek <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">deze link</span></a> voor online hulp.</p></body></html> + + + + Back + Terug + + + + Delete Database + Database verwijderen + + + + Delete the local clone of this database + De lokale kloon van deze database verwijderen + + + + Open in Web Browser + In webbrowser openen + + + + Open the web page for the current database in your browser + De webpagina van de huidige database openen in je browser + + + + Clone from Link + Van link klonen + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + Hiermee download je een externe database om lokaal te bewerken aan de hand van de URL die verstrekt werd op de webpagina van de database. + + + + Refresh + Verversen + + + + Reload all data and update the views + Alle gegevens herladen en de views updaten + + + + Clone Database + Database klonen + + + + Open Database + Database openen + + + + Open the local copy of this database + Lokale kopie van deze database openen + + + + Check out Commit + Commit inladen + + + + Download and open this specific commit + Deze specifieke downloaden en openen + + + + Check out Latest Commit + Laatste commit inladen + + + + Check out the latest commit of the current branch + De laatste commit van de huidige tak inladen + + + + Save Revision to File + Revisie opslaan in bestand + + + + Saves the selected revision of the database to another file + Slaat de geselecteerde revisie van de database op in een ander bestand + + + + Upload Database + Database uploaden + + + + Upload this database as a new commit + Deze database uploaden als een nieuwe commit + + + + Select an identity to connect + Selecteer een identiteit om te verbinden + + + + Public + Openbaar + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + Dit downloadt een database van een externe server om lokaal te bewerken. +Voer een URL in van waaruit gekloond moet worden. Je kunt deze URL +genereren door te klikken op de 'Clone Database in DB4S'-knop op de +webpagina van de database. + + + + Invalid URL: The host name does not match the host name of the current identity. + Ongeldige URL: De hostnaam komt niet overeen met de hostnaam van de huidige identiteit. + + + + Invalid URL: No branch name specified. + Ongeldige URL: Geen taknaam opgegeven. + + + + Invalid URL: No commit ID specified. + Ongeldige URL: Geen commit-ID opgegeven. + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + Je hebt de lokale kloon van de database aangepast. Als je deze commit inlaadt overschrijft dit lokale wijzigingen. +Weet je zeker dat je door wilt gaan? + + + + The database has unsaved changes. Are you sure you want to push it before saving? + De database heeft niet-opgeslagen wijzigingen. Weet je zeker dat je wilt pushen voordat je opslaat? + + + + The database you are trying to delete is currently opened. Please close it before deleting. + De database die je probeert te verwijderen is op het ogenblik geopend. Sluit deze voordat je deze verwijdert. + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + Dit verwijdert de lokale database met alle wijzigingen die je nog niet gecommitteerd hebt. Weet je zeker dat je deze database wilt verwijderen? + + + + RemoteLocalFilesModel + + + Name + Naam + + + + Branch + Tak + + + + Last modified + Laatst gewijzigd + + + + Size + Grootte + + + + Commit + Commit + + + + File + Bestand + + + + RemoteModel + + + Name + Naam + + + + Last modified + Laatst gewijzigd + + + + Size + Grootte + + + + Commit + Commit + + + + Size: + Grootte: + + + + Last Modified: + Laatst gewijzigd: + + + + Licence: + Licentie: + + + + Default Branch: + Standaardtak: + + + + RemoteNetwork + + + Choose a location to save the file + Kies een locatie om het bestand in op te slaan + + + + Error opening remote file at %1. +%2 + Fout bij het openen van extern bestand %1. +%2 + + + + Error: Invalid client certificate specified. + Fout: ongeldig certificaatbestand opgegeven. + + + + Please enter the passphrase for this client certificate in order to authenticate. + Geef de toegangsfrase voor dit client-certificaat op om te authenticeren. + + + + Cancel + Annuleren + + + + Uploading remote database to +%1 + Externe database wordt geüploadt naar +%1 + + + + Downloading remote database from +%1 + Externe database wordt gedownload vanaf +%1 + + + + Error: Cannot open the file for sending. + Fout: kan het te verzenden bestand niet openen. + + + + RemotePushDialog + + + Push database + Database pushen + + + + Database na&me to push to + Database&naam om naar te pushen + + + + Commit message + Commitbericht + + + + Database licence + Databaselicentie + + + + Public + Openbaar + + + + Branch + Tak + + + + Force push + Push forceren + + + + Username + Gebruikersnaam + + + + Database will be public. Everyone has read access to it. + Database wordt openbaar. Iedereen zal leestoegang hebben. + + + + Database will be private. Only you have access to it. + Database wordt privé. Alleen jij zal leestoegang hebben. + + + + Use with care. This can cause remote commits to be deleted. + Wees hier voorzichtig mee; dit kan ervoor zorgen dat externe commits verwijderd worden. + + + + RunSql + + + Execution aborted by user + Uitvoering afgebroken door gebruiker + + + + , %1 rows affected + , %1 records getroffen + + + + query executed successfully. Took %1ms%2 + Opdracht succesvol uitgevoerd. Duurde %1ms%2 + + + + executing query + opdracht wordt uitgevoerd + + + + SelectItemsPopup + + + A&vailable + Beschi&kbaar + + + + Sele&cted + Gese&lecteerd + + + + SqlExecutionArea + + + Form + Formulier + + + + Find previous match [Shift+F3] + Vorige overeenkomst zoeken [Shift+F3] + + + + Find previous match with wrapping + Vorige overeenkomst zoeken met terugloop + + + + Shift+F3 + + + + + The found pattern must be a whole word + Het gevonden patroon moet een heel woord zijn + + + + Whole Words + Hele woorden + + + + Text pattern to find considering the checks in this frame + Zoekterm die gezocht moet worden met de geselecteerde opties in dit kader + + + + Find in editor + Zoek in bewerker + + + + The found pattern must match in letter case + De gevonden overeenkomst moet identiek zijn in onder- en bovenkast + + + + Case Sensitive + Identieke onder-/bovenkast + + + + Find next match [Enter, F3] + Volgende overeenkomst zoeken [Enter, F3] + + + + Find next match with wrapping + Volgende overeenkomst zoeken met terugloop + + + + F3 + + + + + Interpret search pattern as a regular expression + Interpreteer zoekterm als reguliere expressie + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Indien geselecteerd wordt de zoekterm geïnterpreteerd als een UNIX reguliere expressie. Zie hiervoor <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Reguliere Expressies in Wikibooks (Engels)</a>.</p></body></html> + + + + Regular Expression + Reguliere expressie + + + + + Close Find Bar + Zoekbalk sluiten + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>Resultaten van de laatst uitgevoerde opdrachten.</p><p>Je kunt dit paneel ook inklappen en in plaats daarvan het <span style=" font-style:italic;">SQL-log</span>dock gebruiken met <span style=" font-style:italic;">Gebruiker</span> geselecteerd.</p></body></html> + + + + This field shows the results and status codes of the last executed statements. + Dit veld toont de resultaten en statuscodes van de laatst uitgevoerde opdrachten. + + + + Results of the last executed statements + Resultaten van de laatst uitgevoerde opdrachten + + + + Ctrl+PgUp + + + + + Ctrl+PgDown + + + + + Couldn't read file "%1": %2. + + + + + + Couldn't save file: %1. + Kon het bestand niet opslaan: %1. + + + + Your changes will be lost when reloading it! + Jouw wijzigingen zullen verloren gaan als je het opnieuw laadt! + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + Het bestand '%1' is aangepast door een ander programma. Wil je het herladen?%2 + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + + + + + Answer "No to All" to ignore any external update without further prompting. + + + + + Modifying and saving the file will restore prompting. + + + + + SqlTextEdit + + + Ctrl+/ + + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) De abs(X) functie retourneert de absolute waarde van het numerieke argument X. + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () De changes() functie retourneert het aantal databaserecords dat gewijzigd, ingevoegd +of verwijderd is door de meest recent voltooide INSERT-, DELETE- of UPDATE-instructie. + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) De char(X1,X2,...,XN) functie retourneert een tekenreeks bestaande uit tekens +met de respectievelijke unicode-codepuntwaarden van de gehele getallen X1 tot en met XN. + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) De coalesce(X,Y,...) functie retourneert een kopie van het eerste niet-NULL argument, of NULL als alle argument NULL zijn + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) De glob(X,Y) functie is het equivalent van de expressie "Y GLOB X". + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) De ifnull(X,Y) functie retourneert een kopie van het eerste niet-NULL argument, of NULL als beide argumenten NULL zijn. + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) De instr(X,Y) functie zoekt het eerste voorkomen van tekenreeks Y in tekenreeks X +en retourneert het aantal voorgaande tekens plus 1, of 0 als Y niet voorkomt in X. + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) De hex(X) functie interpreteert het argument als een BLOB en retourneert de +hexadecimale voorstelling van de BLOB-inhoud als tekenreeks in bovenkast. + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) De iif(X,Y,Z) functie retourneert de waarde Y als X waar is, en anders Z. + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () De last_insert_rowid() functie retourneert het ROWID van het laatste record dat +door de databaseverbinding die de functie aanriep is ingevoegd. + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) Voor een tekenreeks X, retourneert de length(X) functie het aantal tekens (en niet bytes) in X voor het eerste NUL-teken. + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) De like(X,Y) functie wordt gebruikt als implementatie voor de expressie "Y LIKE X". + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) De like(X,Y,Z) functie wordt gebruikt als implementatie voor de expressie "Y LIKE X ESCAPE Z". + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) De load_extension(X) functie laadt SQLite extensies uit een gedeeld biblitheekbestand genaamd X. +Voor het gebruik van deze functie is autorisatie vanuit Instellingen nodig. + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) De load_extension(X,Y) functie laadt SQLite extensies uit een gedeeld biblitheekbestand +genaamd X gebruikmakend van toegangspunt Y. +Voor het gebruik van deze functie is autorisatie vanuit Instellingen nodig. + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) De lower(X) functie retourneert een kopie van de tekenreeks X waarbij alle ASCII-tekens omgezet worden naar onderkast. + + + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) verwijdert alle spaties aan de linkerkant van X. + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) De ltrim(X,Y) functie retourneert een tekenreeks die gevormd wordt door alle +tekens die in Y voorkomen te verwijderen van de linkerkant van X. + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) De max(X,Y,...) functie accepteert een variabel aantal argumenten en +retourneert het argument met de hoogste waarde, of NULL als enig argument NULL is. + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) De min(X,Y,...) functie accepteert een variabel aantal argumenten en retourneert het argument met de laagste waarde. + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) De nullif(X,Y) functie retourneert het eerste argument als de argumenten +verschillend zijn en NULL als de argumenten hetzelfde zijn. + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) De printf(FORMAT,...) SQL functie werkt zoals de sqlite3_mprintf() functie +in de C-taal en de printf() functie uit de standaard C-bibliotheek. + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) De quote(X) functie retourneert de tekst van een SQL literaal met de waarde van +het argument, geschikt om in te sluiten in een SQL-instructie. + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () De random() functie retourneert een pseudowillekeurig geheel getal tussen -9223372036854775808 en +9223372036854775807. + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) De randomblob(N) functie retourneert een N-byte blob met pseudowillekeurige bytes. + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) De replace(X,Y,Z) functie retourneert een tekenreeks samengesteld door alle +voorvallen van tekenreeks Y in tekenreeks X te vervangen door tekenreeks Z. + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) De round(X) functie retourneert het zwevendekommagetal X afgerond naar nul cijfers achter de komma. + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) De round(X,Y) functie retourneert het zwevendekommagetal X afgerond naar Y cijfers achter de komma. + + + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X) verwijdert alle spaties aan de rechterkant van X. + + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) De rtrim(X,Y) functie retourneert een tekenreeks die gevormd wordt door alle +tekens die in Y voorkomen te verwijderen van de rechterkant van X. + + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) De soundex(X) functie retourneert de soundex-codering van tekenreeks X als tekenreeks. + + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) substr(X,Y) retourneert alle tekens van de tekenreeks X, van het Y-ste teken tot en met het laatste. + + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) De substr(X,Y,Z) functie retourneert het deel van de tekenreeks X, vanaf het Y-ste teken, en met lengte Z. + + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () De total_changes() functie retourneert het aantal databaserecords dat gewijzigd is +door INSERT-, DELETE- of UPDATE-instructies sinds de databaseconnectie geopend werd. + + + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) verwijdert alle spaties aan beide kanten van X. + + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) De trim(X,Y) functie retourneert een tekenreeks die gevormd wordt door alle tekens +die in Y voorkomen te verwijderen van beide kanten van X. + + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) De typeof(X) functie retourneert een tekenreeks die aangeeft wat het gegevenstype van expressie X is. + + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) De unicode(X) functie retourneert het numerieke unicode-codepunt van het eerste teken in de tekenreeks X. + + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) De upper(X) functie retourneert een kopie van de tekenreeks X waarbij alle +onderkast ASCII-tekens omgezet worden naar hun bovenkast equivalent. + + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) De zeroblob(N) functie retourneert een blob met N 0x00 bytes. + + + + + + + (timestring,modifier,modifier,...) + (tijdtekenreeks,modificator,modificator,...) + + + + (format,timestring,modifier,modifier,...) + (formaat,tijdtekenreeks,modificator,modificator,...) + + + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) De avg() functie retourneert de gemiddelde waarde van alle niet-NULL X in een groep. + + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) De count(X) functie retourneert het aantal maal dat X niet NULL is in een groep. + + + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) De group_concat(X) functie retourneert een tekenreeks die de aaneenschakeling is van alle niet-NULL waarden van X. + + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) De group_concat(X,Y) functie retourneert een tekenreeks die de aaneenschakeling +is van alle niet-NULL waarden van X, met Y als scheidingsteken(-reeks). + + + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) De max(X) aggregaatfunctie retourneert de hoogste waarde van alle waarden in de groep. + + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) De min(X) aggregaatfunctie retourneert de laagste niet-NULL waarde van alle waarden in de groep. + + + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) De sum(X) en total(X) aggregaatfuncties retourneren de opsomming van alle niet-NULL waarden in de groep. + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () Het nummer van de rij binnen de huidige partitie. Rijen worden genummerd vanaf 1 +in de volgorde zoals gedefinieerd door de ORDER BY clausule in de vensterdefinitie, +of anders in arbitraire volgorde. + + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () Het row_number() van de eerste peer in elke groep - de rang van de huidige rij +met hiaten. Als er geen ORDER BY clausule is, dan worden alle rijen als peer +beschouwd en retourneert deze functie altijd 1. + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () Het nummer van de peergroep van de huidige rij, binnen diens partitie - de rang +van de huidige rij zonder hiaten. Partities worden genummerd vanaf 1 in de volgorde +zoals gedefinieerd door de ORDER BY clausule in de vensterdefinitie. Als er geen +ORDER BY clausule is, dan worden alle rijen als peer beschouwd en retourneert deze functie altijd 1. + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () Ondanks de naam retourneert deze functie altijd een waarde tussen 0,0 en 1,0 +gelijk aan (rang - 1)/(partitierijen - 1), waarbij rang de waarde is die geretourneerd +wordt door de ingebouwde vensterfunctie rank() en partitierijen het totaal aantal +rijen in de partitie is. Wanneer de partitie maar een rij bevat dan retourneert deze functie 0,0. + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () De cumulatieve distributie. Berekend als rijnummer/partitierijen, waarbij rijnummer +de waarde is die geretourneerd wordt door row_number() voor de laatste peer in de +groep en partitierijen het aantal rijen in de partitie is. + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) Argument N wordt behandeld als geheel getal. Deze functie deelt de partitie zo +evenredig als mogelijk op in N groepen en kent aan elke groep een getal tussen +1 en N toe , in de volgorde zoals gedefinieerd door de ORDER BY clausule, indien +aanwezig, en anders in arbitraire volgorde.. Indien nodig komen grote groepen eerst. +Deze functie retourneert het gehele getal dat toegekend is aan de groep waar de +huidige rij deel van uit maakt. + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) Evalueert de expressie expr tegen de vorige rij in de partitie en retourneert +het resultaat. Of NULL, indien er geen vorige rij bestaat (omdat de huidige rij de eerste is). + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr,verschuiving) Indien het argument verschuiving wordt meegegeven dan dient +deze een niet-negatief geheel getal te zijn. In dat geval wordt de expressie expr tegen +de rij met afstand verschuiving voor de huidige rij in de partitie geëvalueerd en het +resultaat retourneerd. Als verschuiving 0 is dan wordt tegen de huidige rij geëvalueerd. +Indien er geen rij met afstand verschuiving voor de huidige rij bestaat, wordt NULL geretourneerd. + + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,verschuiving,standaardwaarde) Retourneert standaardwaarde als deze meegegeven +is of anders NULL wanneer de rij volgens de verschuiving niet bestaat. + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) Evalueert de expressie expr tegen de volgende rij in de partitie en retourneert +het resultaat. Of NULL, indien er geen volgende rij bestaat (omdat de huidige rij de laatste is). + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,verschuiving) Indien het argument verschuiving wordt meegegeven dan +dient deze een niet-negatief geheel getal te zijn. In dat geval wordt de expressie +expr tegen de rij met afstand verschuiving na de huidige rij in de partitie +geëvalueerd en het resultaat retourneerd. Als verschuiving 0 is dan wordt tegen +de huidige rij geëvalueerd. Indien er geen rij met afstand verschuiving na de +huidige rij bestaat, wordt NULL geretourneerd. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) Deze ingebouwde vensterfunctie berekent het vensterkader voor elke rij, +op dezelfde manier als een geaggregeerde vensterfunctie. Evalueert voor elke rij +de expressie expr tegen de eerste rij in het vensterkader en retourneert de waarde. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) Deze ingebouwde vensterfunctie berekent het vensterkader voor elke rij, +op dezelfde manier als een geaggregeerde vensterfunctie. Evalueert voor elke rij +de expressie expr tegen de laatste rij in het vensterkader en retourneert de waarde. + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr,N) Deze ingebouwde vensterfunctie berekent het vensterkader voor elke rij, +op dezelfde manier als een geaggregeerde vensterfunctie. Evalueert de expressie +expr tegen rij N van het vensterkader en retourneert de waarde. Rijen worden binnen +het vensterkader genummerd vanaf 1 in de volgorde zoals gedefinieerd door de +ORDER BY clausule,indien aanwezig, en anders in arbitraire volgorde. Als rij N niet +bestaat in de partitie dan wordt NULL geretourneerd. + + + + (X) Return the arccosine of X. The result is in radians. + + + + + (X) Return the hyperbolic arccosine of X. + + + + + (X) Return the arcsine of X. The result is in radians. + + + + + (X) Return the hyperbolic arcsine of X. + + + + + (X) Return the arctangent of X. The result is in radians. + + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + + + + + (X) Return the hyperbolic arctangent of X. + + + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + + + + + (X) Return the cosine of X. X is in radians. + + + + + (X) Return the hyperbolic cosine of X. + + + + + (X) Convert value X from radians into degrees. + + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + + + + + (X) Return the natural logarithm of X. + + + + + (B,X) Return the base-B logarithm of X. + + + + + + (X) Return the base-10 logarithm for X. + + + + + (X) Return the logarithm base-2 for the number X. + + + + + (X,Y) Return the remainder after dividing X by Y. + + + + + () Return an approximation for Ï€. + + + + + + (X,Y) Compute X raised to the power Y. + + + + + (X) Convert X from degrees into radians. + + + + + (X) Return the sine of X. X is in radians. + + + + + (X) Return the hyperbolic sine of X. + + + + + (X) Return the square root of X. NULL is returned if X is negative. + + + + + (X) Return the tangent of X. X is in radians. + + + + + (X) Return the hyperbolic tangent of X. + + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + + + + + SqliteTableModel + + + reading rows + records lezen + + + + loading... + aan het laden... + + + + References %1(%2) +Hold %3Shift and click to jump there + Verwijst naar %1(%2) +Houdt %3Shift ingedrukt terwijl je klikt om er naartoe te springen + + + + Error changing data: +%1 + Fout bij het aanpassen van gegevens: +%1 + + + + retrieving list of columns + lijst met kolommen aan het ophalen + + + + Fetching data... + Gegevens aan het ophalen... + + + + + Cancel + Annuleren + + + + TableBrowser + + + Browse Data + Gegevensbrowser + + + + &Table: + &Tabel: + + + + Select a table to browse data + Selecteer een tabel om door gegevens te bladeren + + + + Use this list to select a table to be displayed in the database view + Gebruik deze lijst om een tabel te selecteren die getoond zal worden in de gegevensbrowser + + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + Dit is het databasetabeloverzicht: Je kunt hier de volgende handelingen uitvoeren: + - Beginnen met typen om waarden in de regel te bewerken. + - Dubbelklikken op een willekeurig record om diens inhoud te bewerken in het celbewerkingsvenster. + - Alt-Del om de celinhoud om te zetten naar NULL. + - Ctrl+" om het huidige record te dupliceren. + - Ctrl+' om de celwaarde boven te kopiëren. + - Gebruikelijke kopiëren/plakken handelingen. + + + + Text pattern to find considering the checks in this frame + Zoekterm die gezocht moet worden met de geselecteerde opties in dit kader + + + + Find in table + Zoek in tabel + + + + Find previous match [Shift+F3] + Vorige overeenkomst zoeken [Shift+F3] + + + + Find previous match with wrapping + Vorige overeenkomst zoeken met terugloop + + + + Shift+F3 + + + + + Find next match [Enter, F3] + Volgende overeenkomst zoeken [Enter, F3] + + + + Find next match with wrapping + Volgende overeenkomst zoeken met terugloop + + + + F3 + + + + + The found pattern must match in letter case + De gevonden overeenkomst moet identiek zijn in onder-/bovenkast + + + + Case Sensitive + Identieke onder-/bovenkast + + + + The found pattern must be a whole word + Het gevonden patroon moet een heel woord zijn + + + + Whole Cell + Gehele cel + + + + Interpret search pattern as a regular expression + Interpreteer zoekterm als reguliere expressie + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Indien geselecteerd wordt de zoekterm geïnterpreteerd als een UNIX reguliere expressie. Zie hiervoor <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Reguliere Expressies in Wikibooks (Engels)</a>.</p></body></html> + + + + Regular Expression + Reguliere expressie + + + + + Close Find Bar + Zoekbalk sluiten + + + + Text to replace with + Tekst om mee te vervangen + + + + Replace with + Vervangen met + + + + Replace next match + Vervang volgende overeenkomst + + + + + Replace + Vervangen + + + + Replace all matches + Alle overeenkomsten vervangen + + + + Replace all + Alles vervangen + + + + Export to &JSON + + + + + + Export the filtered data to JSON + + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + + + + + Copy column name + + + + + Copy the database table column name to your clipboard + + + + + New Data Browser + Nieuwe gegevensbrowser + + + + + Add a new docked Data Browser + + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>Blader naar het begin</p></body></html> + + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>Klikken op deze knop brengt je naar het begin van het hierboven getoonde tabeloverzicht.</p></body></html> + + + + |< + |< + + + + Scroll one page upwards + Blader één pagina omhoog + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>Klikken op deze knop bladert één pagina omhoog in het hierboven getoonde tabeloverzicht.</p></body></html> + + + + < + < + + + + 0 - 0 of 0 + 0 - 0 van 0 + + + + Scroll one page downwards + Blader één pagina omlaag + + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>Klikken op deze knop bladert één pagina omlaag in het hierboven getoonde tabeloverzicht.</p></body></html> + + + + > + > + + + + Scroll to the end + Blader naar het einde + + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>Klikken op deze knop brengt je naar het einde van het hierboven getoonde tabeloverzicht.</p></body></html> + + + + >| + >| + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>Klik op deze knop om naar een specifiek record te springen</p></body></html> + + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>Deze knop wordt gebruikt om naar het specifieke record van het Ga-naar-veld te springen.</p></body></html> + + + + Go to: + Ga naar: + + + + Enter record number to browse + Voer een recordnummer in om te browsen + + + + Type a record number in this area and click the Go to: button to display the record in the database view + Voer een specifiek recordnummer in dit veld in en klik op de Ga naar-knop, om het record in het tabeloverzicht te tonen + + + + 1 + 1 + + + + Show rowid column + De rowid-kolom tonen + + + + Toggle the visibility of the rowid column + De zichtbaarheid van de rowid-kolom omschakelen + + + + Unlock view editing + Viewbewerking ontgrendelen + + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + Dit ontgrendelt de huidige view om deze te bewerken. Je hebt echter de juiste triggers nodig om te kunnen bewerken. + + + + Edit display format + Opmaak bewerken + + + + Edit the display format of the data in this column + De opmaak van de gegevens in deze kolom bewerken + + + + + New Record + Nieuw record + + + + + Insert a new record in the current table + Een nieuw record in de huidige tabel invoegen + + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>Deze knop maakt een nieuw record aan in de database. Houd de muis ingedrukt om een pop-upmenu met opties te openen:</p><ul><li><span style=" font-weight:600;">Nieuw record</span>: een nieuw record met standaardwaarden invoegen.</li><li><span style=" font-weight:600;">Waarden invoeren...</span>: opent een dialoogvenster om waarden in te voeren voordat ze in de database worden ingevoegd. Hiermee kun je waarden invoeren die aan de beperkingen voldoen. Dit dialoogvenster wordt tevens geopend als <span style=" font-weight:600;">Nieuw record</span> mislukte door deze beperkingen.</li></ul></body></html> + + + + + Delete Record + Record verwijderen + + + + Delete the current record + Het huidige record verwijderen + + + + + This button deletes the record or records currently selected in the table + Deze knop verwijdert huidig in de tabel geselecteerde records + + + + + Insert new record using default values in browsed table + Nieuw record invoegen met de standaardwaarden die gelden voor de getoonde tabel + + + + Insert Values... + Waarden invoeren... + + + + + Open a dialog for inserting values in a new record + Open een dialoogvenster om waarden voor een nieuw record in te voeren + + + + Export to &CSV + Exporteren als &CSV + + + + + Export the filtered data to CSV + De gefilterde gegevens exporteren naar CSV + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + Deze knop exporteert de gegevens van de tabel zoals deze nu getoond worden (door filters, opmaak en kolomsorteringen) naar een CSV-bestand. + + + + Save as &view + Opslaan als &view + + + + + Save the current filter, sort column and display formats as a view + De huidige filters, kolomsorteringen en opmaak opslaan als view + + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + Deze knop slaat de gegevens van de tabel zoals deze nu getoond worden (door filters, opmaak en kolomsorteringen) op als SQL-view zodat je er later doorheen kunt bladeren of deze in SQL-instructies kunt gebruiken. + + + + Save Table As... + Tabel opslaan als... + + + + + Save the table as currently displayed + Tabel opslaan zoals deze op het ogenblik wordt getoond + + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>Dit pop-upmenu biedt de volgende opties om toe te passen op de huidig getoonde en gefilterde tabel:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Exporteren naar CSV: Deze optie exporteert de gegevens van de tabel zoals deze nu getoond worden (door filters, opmaak en kolomsorteringen) naar een CSV-bestand.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Opslaan als view: Deze optie slaat de gegevens van de tabel zoals deze nu getoond worden (door filters, opmaak en kolomsorteringen) op als SQL-view zodat je er later doorheen kunt bladeren of deze in SQL-instructies kunt gebruiken.</li></ul></body></html> + + + + Hide column(s) + Kolom(-men) verbergen + + + + Hide selected column(s) + Geselecteerde kolom(-men) verbergen + + + + Show all columns + Alle kolommen tonen + + + + Show all columns that were hidden + Alle kolommen tonen die verborgen waren + + + + + Set encoding + Encodering aanpassen + + + + Change the encoding of the text in the table cells + Encodering van de tekst in de tabelcellen aanpassen + + + + Set encoding for all tables + Encodering van alle tabellen aanpassen + + + + Change the default encoding assumed for all tables in the database + De standaard veronderstelde encodering voor alle tabellen aanpassen + + + + Clear Filters + Filters wissen + + + + Clear all filters + Alle filters wissen + + + + + This button clears all the filters set in the header input fields for the currently browsed table. + Deze knop wist alle filters onder de kolomkoppen voor de huidig getoonde tabel. + + + + Clear Sorting + Sortering opheffen + + + + Reset the order of rows to the default + Herstelt de sortering van de records naar de standaardsortering + + + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + Deze knop heft alle sorteringen voor de huidig getoonde tabel op en zet deze terug naar de standaardsortering. + + + + Print + Afdrukken + + + + Print currently browsed table data + De huidig getoonde tabelgegevens afdrukken + + + + Print currently browsed table data. Print selection if more than one cell is selected. + De huidig getoonde tabelgegevens afdrukken. Drukt selectie af als meer dan één cel geselecteerd is. + + + + Ctrl+P + + + + + Refresh + Verversen + + + + Refresh the data in the selected table + Ververs de gegevens van de huidig geselecteerde tabel + + + + This button refreshes the data in the currently selected table. + Deze knop ververst de gegevens van de huidig geselecteerde tabel. + + + + F5 + + + + + Find in cells + In cellen zoeken + + + + Open the find tool bar which allows you to search for values in the table view below. + Open de zoekwerkbalk die je in staat stelt waarden te zoeken in het hieronder getoonde overzicht. + + + + + Bold + Vet + + + + Ctrl+B + + + + + + Italic + Cursief + + + + + Underline + Onderstreept + + + + Ctrl+U + + + + + + Align Right + Rechts uitlijnen + + + + + Align Left + Links uitlijnen + + + + + Center Horizontally + Horizontaal centreren + + + + + Justify + Uitvullen + + + + + Edit Conditional Formats... + Voorwaardelijke opmaakregels bewerken... + + + + Edit conditional formats for the current column + Voorwaardelijke opmaakregels voor de huidige kolom bewerken + + + + Clear Format + Opmaak wissen + + + + Clear All Formats + Alle opmaak wissen + + + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + Wis alle celopmaak van geselecteerde cellen en wis alle voorwaardelijke opmaak van geselecteerde kolommen + + + + + Font Color + Tekstkleur + + + + + Background Color + Achtergrondkleur + + + + Toggle Format Toolbar + Toon/verberg opmaakwerkbalk + + + + Show/hide format toolbar + Toont of verbergt de opmaakwerkbalk + + + + + This button shows or hides the formatting toolbar of the Data Browser + Deze knop toont of verbergt de opmaakwerkbalk van de Gegevensbrowser + + + + Select column + Kolom selecteren + + + + Ctrl+Space + + + + + Replace text in cells + Tekst in cellen vervangen + + + + Freeze columns + Kolommen bevriezen + + + + Make all columns from the first column up to this column not move when scrolling horizontally + Pin alle kolommen vanaf de eerste tot deze vast, zodat deze niet bewegen tijdens het horizontaal scrollen + + + + Filter in any column + Willekeurige kolom filteren + + + + Ctrl+R + + + + + %n row(s) + + %n record + %n records + + + + + , %n column(s) + + , %n kolom + , %n kolommen + + + + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . Som: %1; Gemiddelde: %2; Min.: %3; Max.: %4 + + + + Conditional formats for "%1" + Voorwaardelijke opmaakregels voor "%1" + + + + determining row count... + aantal records bepalen... + + + + %L1 - %L2 of >= %L3 + + + + + %L1 - %L2 of %L3 + + + + + (clipped at %L1 rows) + + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + Voer een pseudo-primaire sleutel in om het bewerken van deze view in te schakelen. Dit dient de naam van een unieke-waardenkolom in de view te zijn. + + + + Delete Records + Records verwijderen + + + + Duplicate records + Records dupliceren + + + + Duplicate record + Record dupliceren + + + + Ctrl+" + + + + + Adjust rows to contents + Rijen aanpassen aan inhoud + + + + Error deleting record: +%1 + Fout bij het verwijderen van record: +%1 + + + + Please select a record first + Selecteer eerst een record + + + + Please choose a new encoding for all tables. + Kies een nieuwe codering voor alle tabellen. + + + + Please choose a new encoding for this table. + Kies een nieuwe codering voor deze tabel. + + + + %1 +Leave the field empty for using the database encoding. + %1 +Laat het veld leeg om de databasecodering te gebruiken. + + + + This encoding is either not valid or not supported. + De codering is niet geldig of wordt niet ondersteund. + + + + %1 replacement(s) made. + %1 vervangin(-en) gedaan. + + + + TableBrowserDock + + + New Data Browser + Nieuwe gegevensbrowser + + + + Rename Data Browser + Gegevensbrowser hernoemen + + + + Close Data Browser + Gegevensbrowser sluiten + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + Geef een nieuwe naam voor de gegevensbrowser. Gebruik het '&&'-teken om de een van de volgende tekens als sneltoets in te stellen. + + + + VacuumDialog + + + Compact Database + Database comprimeren + + + + Warning: Compacting the database will commit all of your changes. + Waarschuwing: wanneer je de database comprimeert zullen al jouw gemaakte wijzigingen gecommitteerd worden. + + + + Please select the databases to co&mpact: + Selecteer de databases om te co&mprimeren: + + + diff --git a/src/translations/sqlb_pl.ts b/src/translations/sqlb_pl.ts new file mode 100644 index 000000000..0c04e4a6f --- /dev/null +++ b/src/translations/sqlb_pl.ts @@ -0,0 +1,8054 @@ + + + + + AboutDialog + + + About DB Browser for SQLite + O PrzeglÄ…darce SQLite + + + + Version + Wersja + + + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + + + + + AddRecordDialog + + + Add New Record + Nowy rekord + + + + Enter values for the new record considering constraints. Fields in bold are mandatory. + Podaj wartoÅ›ci dla nowego rekordu zwracajÄ…c uwagÄ™ na ograniczenia.Pola wytÅ‚usczone sÄ… obowiÄ…zkowe. + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + W kolumnie Wartość możesz podać wartość dla pola identyfikowanego w kolumnie Nazwa. Kolumna Rodzaj wskazuje rodzaj pola. WartoÅ›ci domyÅ›lne sÄ… wyÅ›wietlane w tym samym stylu, co wartoÅ›ci NULL. + + + + Name + Nazwa + + + + Type + Rodzaj + + + + Value + Wartość + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + WartoÅ›ci do wstawienia. Uprzednio wypeÅ‚nione domyÅ›lne wartoÅ›ci sÄ… wstawiane samoczynnie, chyba że zostaÅ‚y zmienione. + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + Tutaj pokazana jest kwerenda SQL dla dodania nowego rekordu zawierajÄ…cego wartoÅ›ci wprowadzone w górnej ramce. Możesz jÄ… rÄ™cznie zmienić przed zapisem rekordu. + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Zapisz</span> przekaże wyÅ›wietlone zapytanie SQL do bazy danych w celu zapisania nowego rekordu</p><p><span style=" font-weight:600;">Przywróć domyÅ›lne</span> przywróci wstÄ™pne wartoÅ›ci domyÅ›lne w kolumnie<span style=" font-weight:600;">Wartość</span></p><p><span style=" font-weight:600;">Zaniechaj</span> zamyka to okno bez robienia zmian.</p></body></html> + + + + Auto-increment + + Samoprzyrost + + + + + Unique constraint + + Ograniczenie niepowtarzalnoÅ›ci + + + + + Check constraint: %1 + + Ograniczenie sprawdzania: %1 + + + + + Foreign key: %1 + + Klucz obcy: %1 + + + + + Default value: %1 + + Wartość domyÅ›lna: %1 + + + + + Error adding record. Message from database engine: + +%1 + Nie można dodać rekordu. Wiadomość z silnika bazy danych: +%1 + + + + Are you sure you want to restore all the entered values to their defaults? + JesteÅ› pewien że chcesz przywrócić domyÅ›lne wartoÅ›ci dla wszystich wpisów? + + + + Application + + + Possible command line arguments: + Dozwolone argumenty wiersza poleceÅ„: + + + + The user settings file location is replaced with the argument value instead of the environment variable value. + PoÅ‚ożenie pliku ustawieÅ„ użytkownika jest zastÄ™powane wartoÅ›ciÄ… argumentu zamiast wartoÅ›ciÄ… zmiennej Å›rodowiskowej. + + + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + Pomijana wartość zmiennej Å›rodowiskowej (DB4S_SETTINGS_FILE): + + + + + The file %1 does not exist + Plik %1 nie istnieje + + + + Usage + Użycie + + + + options + ustawienia + + + + + database + baza danych + + + + + project + projekt + + + + + csv-file + plik csv + + + + Show command line options + Pokaż ustawienia wiersza poleceÅ„ + + + + Exit application after running scripts + Wyjdź z aplikacji po wykonaniu skryptów + + + + + file + plik + + + + Execute this SQL file after opening the DB + Wykonaj to polecenie SQL po otwarciu bazy danych + + + + Import this CSV file into the passed DB or into a new DB + Zaimportuj ten plik CSV do podanej bazy danych lub do nowej bazy danych + + + + table + tabela + + + + Browse this table, or use it as target of a data import + PrzeglÄ…daj tÄ™ tabelÄ™ lub użyj jej jako miejsca docelowego importowania + + + + Open database in read-only mode + Otwórz bazÄ™ danych w trybie tylko do odczytu + + + + settings_file + plik_ustawieÅ„ + + + + Run application based on this settings file + Uruchom tÄ™ aplikacjÄ™ na podstawie tego pliku ustawieÅ„ + + + + + group + grupa + + + + + settings + ustawienia + + + + + value + wartość + + + + Run application with this setting temporarily set to value + Uruchom tÄ™ aplikacjÄ™ z wartoÅ›ciÄ… tego ustawienia tymczasowo na + + + + Run application saving this value for this setting + Uruchom tÄ™ aplikacjÄ™ zapisujÄ…c, tÄ™ wartość w jej ustawieniach + + + + Display the current version + WyÅ›wietl bieżącÄ… wersjÄ™ + + + + Open this SQLite database + Otwórz tÄ™ bazÄ™ danych SQLite + + + + Open this project file (*.sqbpro) + Otwórz ten plik projektu (*.sqbpro) + + + + Import this CSV file into an in-memory database + Zaimportuj ten plik CSV do bazy danych w pamiÄ™ci + + + + + + The %1 option requires an argument + SÅ‚owo kluczowe %1 wymaga argumentu + + + + The -S/--settings option requires an argument. The option is ignored. + Ustawienie -S/-- wymaga argumentu. PominiÄ™to ustawienie. + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + Ustawienia -o/--option oraz -O/--save-option wymagajÄ… argumentu w postaci group/setting=wartość + + + + Invalid option/non-existent file: %1 + NieprawidÅ‚owa opcja lub nieistniejÄ…cy plik: %1 + + + + SQLite Version + Wersja SQLite + + + + SQLCipher Version %1 (based on SQLite %2) + Wersja SQLCipher %1 (oparta na SQLite %2) + + + + DB Browser for SQLite Version %1. + PrzeglÄ…darka BD dla SQLite w wersji %1. + + + + Last commit hash when built: %1 + Skrót zmiany, na której zbudowano: %1 + + + + Built for %1, running on %2 + Zbudowane dla %1, uruchomione na %2 + + + + Qt Version %1 + Wersja Qt %1 + + + + CipherDialog + + + SQLCipher encryption + Szyfrowanie SQLCipher + + + + &Password + &HasÅ‚o + + + + &Reenter password + Powtó&rz hasÅ‚o + + + + Encr&yption settings + Ustawienia sz&yfrowania + + + + SQLCipher &3 defaults + DomyÅ›lne SQLCipher &3 + + + + SQLCipher &4 defaults + DomyÅ›lne SQLCipher &4 + + + + Custo&m + WÅ‚as&ny + + + + Page si&ze + Ro&zmiar strony + + + + &KDF iterations + Powtórzenia &KDF + + + + HMAC algorithm + Algorytm HMAC + + + + KDF algorithm + Algorytm KDF + + + + Plaintext Header Size + Rozmiar nagłówka zwykÅ‚ego tekstu + + + + Passphrase + HasÅ‚o + + + + Raw key + Klucz + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + Ustaw klucz do zaszyfrowania bazy danych. +Zwróć uwagÄ™ na to, że wszelkie zmiany wprowadzone tutaj do opcjonalnych + ustawieÅ„ bÄ™dÄ… wymagane przy każdym otwarciu pliku. +Aby pozbyć siÄ™ szyfrowania, pozostaw pola hasÅ‚a pustymi. +Proces szyfrowania może zabrać dużo czasu w zależnoÅ›ci od wielkoÅ›ci bazy danych.
Zaleca siÄ™ aby przed rozpoczÄ™ciem tego procesu zrobić kopiÄ™ zapasowÄ… pliku. + Wszelkie niezapisane zmiany bÄ™dÄ… wprowadzone do bazy danych zanim szyfrowanie siÄ™ rozpocznie. + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + ProszÄ™ podać hasÅ‚o do zaszyfrowania bazy danych. +JeÅ›li zostaÅ‚y zmienione jakiekolwiek dodatkowe ustawienia dla pliku tej bazy danych bÄ™dziesz musiaÅ‚ również podać tÄ… informacjÄ™. + + + + ColumnDisplayFormatDialog + + + Choose display format + Wybierz format wyÅ›wietlania + + + + Display format + Format wyÅ›wietlania + + + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + Wybierz domyÅ›lny format wyÅ›wietlania dla kolumny '%1', który bÄ™dzie stosowany dla każdej wartoÅ›ci, zanim zostanie ona wyÅ›wietlona. + + + + Default + DomyÅ›lny + + + + Decimal number + Liczba dziesiÄ™tna + + + + Exponent notation + Zapis wykÅ‚adniczy + + + + Hex blob + Blob szestnastkowy + + + + Hex number + Liczba szesnastkowa + + + + Octal number + Liczba ósemkowa + + + + Round number + Liczba zaokrÄ…glona + + + + Apple NSDate to date + Apple NSDate do daty + + + + Java epoch (milliseconds) to date + Java epoch (milisekundy) do daty + + + + .NET DateTime.Ticks to date + .NET DateTime.Ticks na datÄ™ + + + + Julian day to date + Data JuliaÅ„ska do daty + + + + Unix epoch to date + Unix epoch do daty + + + + Unix epoch to local time + Unix epoch do czasu lokalnego + + + + WebKit / Chromium epoch to date + + + + + WebKit / Chromium epoch to local time + + + + + Windows DATE to date + Windows DATE do daty + + + + Date as dd/mm/yyyy + Data w formacie dd/mm/rrrr + + + + Lower case + MaÅ‚e litery + + + + Upper case + Duże litery + + + + Binary GUID to text + Dwójkowy GUID na tekst + + + + SpatiaLite Geometry to SVG + Geometria SpatiaLite do SVG + + + + Custom + Niestandardowy + + + + Custom display format must contain a function call applied to %1 + WÅ‚asny format wyÅ›wietlania musi zawierać wywoÅ‚anie funkcji zastosowanej na %1 + + + + Error in custom display format. Message from database engine: + +%1 + Błąd we wÅ‚asnym formacie wyÅ›wietlania. Wiadomość z silnika bazy danych: + +%1 + + + + Custom display format must return only one column but it returned %1. + WÅ‚asny format wyÅ›wietlania musi zwracać tylko jednÄ… kolumnÄ™, a zwróciÅ‚ %1. + + + + CondFormatManager + + + Conditional Format Manager + ZarzÄ…dzanie formatowaniem warunkowym + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + To okno dialogowe umożliwia tworzenie i zmianÄ™ formatowania warunkowego. WyglÄ…d komórki bÄ™dzie bÄ™dzie okreÅ›lony pierwszym speÅ‚nionym warunkiem dla danych komórki. Formatowania warunkowe można przesunąć w górÄ™ i w dół, gdzie te na górze sÄ… przetwarzane w pierwszej kolejnoÅ›ci. SkÅ‚adnia dla warunków jest taka sama jak dla filtrów, a pusty warunek bÄ™dzie pasowaÅ‚ do wszystkich wartoÅ›ci. + + + + Add new conditional format + Dodaj nowe formatowanie warunkowe + + + + &Add + Dod&aj + + + + Remove selected conditional format + UsuÅ„ wybrane formatowanie warunkowe + + + + &Remove + &UsuÅ„ + + + + Move selected conditional format up + PrzesuÅ„ w górÄ™ wybrane formatowanie warunkowe + + + + Move &up + PrzesuÅ„ w &górÄ™ + + + + Move selected conditional format down + PrzesuÅ„ w dół wybrane formatowanie warunkowe + + + + Move &down + PrzesuÅ„ w &dół + + + + Foreground + Pierwszy plan + + + + Text color + Barwa tekstu + + + + Background + TÅ‚o + + + + Background color + Barwa tÅ‚a + + + + Font + Czcionka + + + + Size + Rozmiar + + + + Bold + Pogrubienie + + + + Italic + Kursywa + + + + Underline + PodkreÅ›lenie + + + + Alignment + Wyrównanie + + + + Condition + Warunek + + + + + Click to select color + Kliknij, aby wybrać barwÄ™ + + + + Are you sure you want to clear all the conditional formats of this field? + Czy na pewno chcesz wyczyÅ›cić wszystkie formatowania warunkowe tego pola? + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + ProszÄ™ podaj nazwÄ™ bazy danych za pomocÄ… której chcesz uzyskać dostÄ™p do załączonej bazy + + + + Invalid file format + NieprawidÅ‚owy format pliku + + + + Do you really want to close this temporary database? All data will be lost. + Czy na pewno chcesz zamknąć tÄ™ tymczasowÄ… bazÄ™ danych? Wszelkie zmiany bedÄ… zapomniane. + + + + Do you want to save the changes made to the database file %1? + Czy na pewno chcesz zapisać zmiany dokonane w pliku bazy danych %1? + + + + Database didn't close correctly, probably still busy + Baza danych nie zostaÅ‚a zamkniÄ™ta poprawnie, prawdopodobnie byÅ‚a nadal zajÄ™ta + + + + Cannot open destination file: '%1' + Nie można otworzyć pliku docelowego: '%1' + + + + + Cannot backup to file: '%1'. Message: %2 + Nie można utworzyć pliku kopii zapasowej: '%1'. Opis: %2 + + + + The database is currently busy: + Baza danych jest obecnie zajÄ™ta: + + + + Do you want to abort that other operation? + Czy na pewno chcesz przerwać tÄ… innÄ… operacjÄ™? + + + + Exporting database to SQL file... + Eksportowanie bazy danych do pliku SQL… + + + + + Cancel + Zaniechaj + + + + + No database file opened + Plik z bazÄ… danych nie jest obecnie otwarty + + + + Executing SQL... + Wykonywanie SQL… + + + + Action cancelled. + Zaniechano dziaÅ‚ania. + + + + + Error in statement #%1: %2. +Aborting execution%3. + Błąd w poleceniu #%1: %2. +Przerywam wykonywanie%3. + + + + + and rolling back + i przywracam + + + + didn't receive any output from %1 + nie otrzymano żadnego wyniku z %1 + + + + could not execute command: %1 + nie można wykonać polecenia: %1 + + + + Cannot delete this object + Nie można usunąć tego obiektu + + + + Cannot set data on this object + Nie można ustawić danych na tym objekcie + + + + + A table with the name '%1' already exists in schema '%2'. + Tabela o nazwie '%1' już istnieje w schemacie '%2'. + + + + No table with name '%1' exists in schema '%2'. + Tabela o nazwie '%1' nie istnieje w schemacie '%2'. + + + + + Cannot find column %1. + Nie można znaleźć kolumny %1. + + + + Creating savepoint failed. DB says: %1 + Nie można utworzyć punktu zapisu. BD zwraca: %1 + + + + Renaming the column failed. DB says: +%1 + Nie można przemianować tej kolumny. BD zwraca: +%1 + + + + + Releasing savepoint failed. DB says: %1 + Nie można zwolnić punktu zapisu. BD zwraca: %1 + + + + Creating new table failed. DB says: %1 + Nie można utworzyć nowej tabeli. BD zwraca: %1 + + + + Copying data to new table failed. DB says: +%1 + Nie można skopiować nowej tabeli. BD zwraca: +%1 + + + + Deleting old table failed. DB says: %1 + Nie można usunąć starej tabeli. BD zwraca: %1 + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + Błąd przemianowywania tabeli z '%1' na '%2'. +Wiadomość z silnika bazy danych: +%3 + + + + could not get list of db objects: %1 + nie można pobrać listy obiektów bd: %1 + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + WystÄ…piÅ‚ błąd przy odtworzeniu niektórych obiektów powiÄ…zanych z tÄ… bazÄ… danych. Błędy tego rodzaju wystÄ™pujÄ… za zwyczaj w przypadku zmiany nazw niektórych kolumn. Sprawdź dokÅ‚adnie nastÄ™pujÄ…cÄ… kwerendÄ™ SQL. Po dokonaniu zmian możesz jÄ… rÄ™cznie uruchomić: + + + + + + could not get list of databases: %1 + nie mogÄ™ odczytać listy baz danych: %1 + + + + Error setting pragma %1 to %2: %3 + Błąd przy ustawianiu pragmy %1 do %2: %3 + + + + File not found. + Nie znaleziono pliku. + + + + Error loading extension: %1 + Nie można wczytać rozszerzenia: %1 + + + + Error loading built-in extension: %1 + + + + + could not get column information + nie można uzyskać informacji o kolumnie + + + + DbStructureModel + + + Name + Nazwa + + + + Object + Obiekt + + + + Type + Rodzaj + + + + Schema + Polecenie tworzÄ…ce + + + + Database + Baza danych + + + + Browsables + Obiekty do przeglÄ…dania + + + + All + Wszystkie + + + + Temporary + Tymczasowa + + + + Tables (%1) + Tabele (%1) + + + + Indices (%1) + Indeksy (%1) + + + + Views (%1) + Widoki (%1) + + + + Triggers (%1) + Wyzwalacze (%1) + + + + EditDialog + + + Edit database cell + Zmiana komórki bazy danych + + + + Mode: + Tryb: + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + To jest lista dostÄ™pnych trybów dla edytora komórek. Wybierz tryb do wyÅ›wietlania lub edycji danych dla tej komórki. + + + + Text + Tekst + + + + RTL Text + Tekst od prawej do lewej + + + + Binary + Zapis dwójkowy + + + + + Image + Obraz + + + + JSON + JSON + + + + XML + XML + + + + Evaluation + Obliczenie + + + + + Automatically adjust the editor mode to the loaded data type + Sam dostosuj tryb edytora w zależnoÅ›ci od wczytanych danych + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + To pole zaznaczane włącza lub wyłącza samoczynne przełączanie do trybu edytora. Po wybraniu nowej komórki lub zaimportowaniu nowych danych i przy włączonym samoczynnym przełączaniu, tryb dostosowuje siÄ™ do wykrytego rodzaju danych. NastÄ™pnie można zmienić tryb edytora rÄ™cznie. Aby zapamiÄ™tać ten try rÄ™czny przy przechodzeniu po komórkach, wystarczy odznaczyć to pole. + + + + Auto-switch + Sam przełączaj + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + Edytor Qt jest używany do pism od-prawej-do-lewej, które nie sÄ… obsÅ‚ugiwane przez domyÅ›lny edytor tekstu. Obecność znaków pism od-prawej-do-lewej jest wykrywana, a edytor sam przełącza siÄ™ do tego trybu. + + + + Identification of the cell currently in the editor + Identyfikator komórki, bÄ™dÄ…cej obecnie w edytorze + + + + Type and size of data currently in table + Rodzaj i rozmiar danych, bÄ™dÄ…cych obecnie w edytorze + + + + Open preview dialog for printing the data currently stored in the cell + Otwiera okno dialogowe do podglÄ…du drukowanych danych z danej komórki + + + + Auto-format: pretty print on loading, compact on saving. + Auto-formatowanie: upiÄ™ksza tekst przy wczytywaniu i Å›ciska przy zapisywaniu. + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + Po zaznaczeniu, dane sÄ… formatowane podczas ich wczytywania, Å‚amiÄ…c tekst w wierszach oraz wcinajÄ…c go dla najlepszej czytelnoÅ›ci. Przed zapisaniem, dane sÄ… oczyszczane poprzez usuniÄ™cie zakoÅ„czeÅ„ wierszy oraz niepotrzebnych biaÅ‚ych znaków. + + + + Word Wrap + Zawijaj wiersze + + + + Wrap lines on word boundaries + Zawijaj wiersze na granicach słów + + + + + Open in default application or browser + Otwórz w domyÅ›lnej aplikacji lub przeglÄ…darce + + + + Open in application + Otwórz w aplikacji + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + Wartość jest traktowana jako plik lub adres URL i otwierana w domyÅ›lnej aplikacji lub przeglÄ…darce sieciowej. + + + + Save file reference... + Zapisz odniesienie pliku... + + + + Save reference to file + Zapisz odniesienie do pliku + + + + + Open in external application + Otwórz w zewnÄ™trznej aplikacji + + + + Autoformat + Sam formatuj + + + + &Export... + Wy&eksportuj... + + + + + &Import... + Za&importuj... + + + + + Import from file + Zaimportuj z pliku + + + + + Opens a file dialog used to import any kind of data to this database cell. + Otwiera okno wyboru pliku z danymi do zaimportowania w tej komórce. + + + + Export to file + Wyeksportuj do pliku + + + + Opens a file dialog used to export the contents of this database cell to a file. + Otwiera okno pozwalajÄ…ce na wyeksportowanie zawartoÅ›ci komórki do pliku. + + + + Erases the contents of the cell + CzyÅ›ci zawartość komórki + + + + Set as &NULL + Ustaw jako &NULL + + + + This area displays information about the data present in this database cell + Tutaj wyÅ›wietlane sÄ… informacje o danych obecnych w tej komórce + + + + Apply data to cell + Zapisz dane w komórce + + + + This button saves the changes performed in the cell editor to the database cell. + Ten przycisk zapisuje zmiany wykonane w edytorze komórki w komórce bazy danych. + + + + Apply + Zastosuj + + + + Print... + Wydrukuj... + + + + Ctrl+P + Ctrl+P + + + + Open preview dialog for printing displayed text + Otwiera okno dialogowe do podglÄ…du wyÅ›wietlanego tekstu + + + + Copy Hex and ASCII + Skopiuj Hex i ASCII + + + + Copy selected hexadecimal and ASCII columns to the clipboard + Skopiuj zaznaczone kolumny szesnastkowe oraz ASCII do schowka + + + + Ctrl+Shift+C + Ctrl+Shift+C + + + + + Image data can't be viewed in this mode. + Obrazy nie mogÄ… zostać wyÅ›wietlone w tym trybie. + + + + + Try switching to Image or Binary mode. + Przejdź do trybu obrazu lub wartoÅ›ci binarnej. + + + + + Binary data can't be viewed in this mode. + Wartość dwójkowa nie może być wyÅ›wietlona w tym trybie. + + + + + Try switching to Binary mode. + Przejdź do trybu wartoÅ›ci binarnej. + + + + + Image files (%1) + Piki graficzne (%1) + + + + Binary files (*.bin) + Pliki Binarne (*.bin) + + + + Choose a file to import + Wybierz plik do zaimportowania + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + Tryby edytora tekstu umożliwiajÄ… zmianÄ™ zwykÅ‚ego tekstu, a także danych JSON, czy XML z jednoczesnym podÅ›wietlaniem skÅ‚adni, formatowaniem oraz sprawdzaniem poprawnoÅ›ci przez zpisem. + +Błędy sÄ… wskazywane czerwone zygzakowate podkreÅ›lenie. + +W trybie Obliczania, wpisane wyrażenia SQLite sÄ… obliczane, a ich wynik jest zapisywany do komórki. + + + + Unsaved data in the cell editor + Niezapisane dane w edytorze komórki + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + Edytor komórki zawiera dane jeszcze niazapisane do bazy danych. +Czy chcesz zapisać zmienione dane w wierszu=%1, kolumnie=%2? + + + + Editing row=%1, column=%2 + Zmienianie wiersza=%1, kolumny=%2 + + + + No cell active. + Nie zostaÅ‚a wybrana żadna komórka. + + + + %1 Image + %1 Grafika + + + + Choose a filename to export data + Wybierz nazwÄ™ pliku dla wyeksportowanych danych + + + + Invalid data for this mode + NieprawidÅ‚owe dane w tym trybie + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + Komórka zawiera nieprawidÅ‚owe dane %1. Powód: %2. Czy na pewno wstawić je do komórki? + + + + + Type: NULL; Size: 0 bytes + Rodzaj: NULL; Rozmiar: 0 bajtów + + + + + Type: Text / Numeric; Size: %n character(s) + + Rodzaj: Tekst / Liczba; Rozmiar: %n znak + Rodzaj: Tekst / Liczba; Rozmiar: %n znaki + Rodzaj: Tekst / Liczba; Rozmiar: %n znaków + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + Rodzaj: Obraz %1; Rozmiar: %2x%3 pikseli + + + + Type: Valid JSON; Size: %n character(s) + + Rodzaj: PrawidÅ‚owy JSON; Rozmiar: %n znak + Rodzaj: PrawidÅ‚owy JSON; Rozmiar: %n znaki + Rodzaj: PrawidÅ‚owy JSON; Rozmiar: %n znaków + + + + + Type: Binary; Size: %n byte(s) + + Rodzaj: Dwójkowe; Rozmiar: %n bajt + Rodzaj: Dwójkowe; Rozmiar: %n bajty + Rodzaj: Dwójkowe; Rozmiar: %n bajtów + + + + + Couldn't save file: %1. + Nie można zapisać pliku: %1. + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + Dane zostaÅ‚y zapisane do pliku tymczasowego i otwarte przy użyciu domyÅ›lnej aplikacji. Możesz teraz edytować plik, a gdy bÄ™dziesz gotowy, to zatwierdź lub wycofaj nowe dane w komórce. + + + + EditIndexDialog + + + Edit Index Schema + Edytor tworzenia indeksu + + + + &Name + &Nazwa + + + + &Table + &Tabela + + + + &Unique + &Niepowtarzalność + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + Aby ograniczyć indeks tylko do części tabeli można dopisać tutaj polecenie WHERE, które +zaznacza część tabeli, która ma zostać zaindeksowana + + + + Partial inde&x clause + Polecenie częściowego &indeksu + + + + Colu&mns + Kolu&mny + + + + Table column + Kolumna tabeli + + + + Type + Rodzaj + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + Dodaj nowÄ… kolumnÄ™ wyrażenia do indeksu. Kolumny wyrażeÅ„ zawierajÄ… raczej wyrażenia SQL niż nazwy kolumn. + + + + Index column + Kolumna indeksu + + + + Order + PorzÄ…dek + + + + Deleting the old index failed: +%1 + Usuwanie starego indeksu nie powiodÅ‚o siÄ™: +%1 + + + + Creating the index failed: +%1 + Tworzenie indeksu nie powiodÅ‚o siÄ™: +%1 + + + + EditTableDialog + + + Edit table definition + Edycja tworzenia tabeli + + + + Table + Tabela + + + + Advanced + Rozszerzone + + + + Without Rowid + Bez ID wiersza + + + + Fields + Pola + + + + Database sche&ma + Sche&mat bazy danych + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + + + + + On Conflict + JeÅ›li sprzeczne + + + + Strict + ÅšcisÅ‚e + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + Po zaznaczeniu pola "Å›cisÅ‚e" SQLite wymusza rodzaje danych na każdej kolumnie przy uaktualnianiu lub wstawianiu do niej danych. + + + + + + Add + Dodaj + + + + + + Remove + UsuÅ„ + + + + Move to top + PrzesuÅ„ na górÄ™ + + + + Move up + PrzesuÅ„ w górÄ™ + + + + Move down + PrzesuÅ„ w dół + + + + Move to bottom + PrzesuÅ„ na dół + + + + + + + Name + Nazwa + + + + + Type + Rodzaj + + + + NN + NN + + + + Not null + Nie NULL + + + + PK + PK + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> Klucz główny</p></body></html> + + + + AI + AI + + + + Autoincrement + Samoprzyrostowa + + + + U + U + + + + + + Unique + Niepowtarzalność + + + + Default + DomyÅ›lna + + + + Default value + DomyÅ›lna wartość + + + + + Check + Sprawdzenie + + + + Check constraint + Ograniczenie sprawdzenia + + + + Collation + Zestawienie + + + + Foreign Key + Klucz obcy + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_fk"/> Klucz obcy</p></body></html> + + + + Index Constraints + Warunki indeksu + + + + Add constraint + Dodaj ograniczenie + + + + Remove constraint + UsuÅ„ ograniczenie + + + + + Columns + Kolumny + + + + + + SQL + SQL + + + + Foreign Keys + Klucze obce + + + + References + Odniesienia + + + + Check Constraints + Warunki sprawdzajÄ…ce + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Uwaga: </span>W okreÅ›leniu tabeli jest coÅ›, czego nasze przetwarzanie skÅ‚adni nie rozumie. Zmiana i zapis tej tabeli może skutkować kÅ‚opotami.</p></body></html> + + + + + Primary Key + Klucz główny + + + + Add a primary key constraint + Dodaj ograniczenie klucza głównego + + + + Add a unique constraint + Dodaj ograniczenie niepowtarzalnoÅ›ci + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + Dla każdej tabeli może być tylko jeden klucz główny. ZmieÅ„ istniejÄ…cy klucz główny. + + + + Error creating table. Message from database engine: +%1 + Nie można utworzyć tabeli. Wiadomość z silnika bazy danych: +%1 + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + Istnieje już pole o tej nazwie. Przemianuj je najpierw lub wybierz innÄ… nazwÄ™ dla tego pola. + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + Kolumna ma odwoÅ‚anie do klucza obcego w tabeli %1 wiÄ™c jej nazwa nie można zmienić jej nazwy. + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + W tym polu istnieje co najmniej jeden wiersz z wartoÅ›ciÄ… równÄ… NULL. Czyni to niemożliwym ustawienie tej flagi. Najpierw zmieÅ„ dane tabeli. + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + W tym polu istnieje co najmniej jeden wiersz z wartoÅ›ciÄ… nie bÄ™dÄ…cÄ… liczbÄ… caÅ‚kowitÄ…. Czyni to niemożliwym ustawienie flagi AI. Najpierw zmieÅ„ dane tabeli. + + + + Column '%1' has duplicate data. + + Kolumna '%1' zawiera powielone dane. + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + Czyni to niemożliwym nadanie flagi 'Unique'. UsuÅ„ powielone dane, aby móc nadać flagÄ™ 'Unique'. + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + Czy na pewno usunąć pole '%1'? +Wszystkie dane przechowywane w tym polu zostanÄ… utracone. + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + Dodaj pola, które speÅ‚niajÄ… dane warunki przed ustawieniem flagi bez rowid: + - Ustawiono flagÄ™ głównego klucza + - Wyłączono samoprzyrost + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + Dodaj pole, które speÅ‚nia nastÄ™pujÄ…ce warunki przed ustawieniem dziaÅ‚ania w-przecznoÅ›ci: + - Ustawiono flagÄ™ głównego klucza + + + + ExportDataDialog + + + Export data as CSV + Eksport danych jako CSV + + + + Tab&le(s) + Tabe&la/e + + + + Colu&mn names in first line + Nazwy kolu&mn w pierwszym wierszu + + + + Fie&ld separator + Znak oddzie&lajÄ…cy pola + + + + , + , + + + + ; + ; + + + + Tab + Tab + + + + | + | + + + + + + Other + Inny + + + + &Quote character + &Znak cytatu + + + + " + " + + + + ' + ' + + + + New line characters + Znak nowego wiersza + + + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) + + + + Unix: LF (\n) + Unix: LF (\n) + + + + Pretty print + UpiÄ™ksz wydruk + + + + Export data as JSON + Eksport danych jako JSON + + + + exporting CSV + eksportowanie CSV + + + + + Error while writing the file '%1': %2 + Błąd przy zapisywaniu pliku '%1': %2 + + + + + Could not open output file: %1 + Nie można otworzyć pliku wyjÅ›ciowego: %1 + + + + exporting JSON + eksportowanie JSON + + + + + Choose a filename to export data + Wybierz nazwÄ™ pliku dla eksportowanych danych + + + + Please select at least 1 table. + Wybierz przynajmniej jednÄ… tabelÄ™. + + + + Choose a directory + Wybierz poÅ‚ożenie + + + + Export completed. + Eksportowanie zakoÅ„czone. + + + + Export finished with errors. + Wyeksportuj ukoÅ„czone z błędami. + + + + ExportSqlDialog + + + Export SQL... + Wyeksportuj SQL... + + + + Tab&le(s) + Tabel&a/e + + + + Select All + Zaznacz wszystkie + + + + Deselect All + Odznacz wszystkie + + + + &Options + &Opcje + + + + Keep column names in INSERT INTO + Pozostaw nazwy kolumn w INSERT INTO + + + + Multiple rows (VALUES) per INSERT statement + Wiele rzÄ™dów (WartoÅ›ci) dla polecenia INSERT + + + + Export everything + Wyeksportuj wszystko + + + + Export schema only + Wyeksportuj tylko schemat + + + + Export data only + Wyeksportuj tylko dane + + + + Keep original CREATE statements + Zachowaj pierwotne polecenia CREATE + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + Zachowaj poprzedni schemat (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + ZastÄ…p poprzedni schemat (DROP TABLE, then CREATE TABLE) + + + + Please select at least one table. + Wybierz przynajmniej jednÄ… tabelÄ™. + + + + Choose a filename to export + Wybierz nazwÄ™ eksportowanego pliku + + + + Export completed. + Eksportowanie zakoÅ„czono. + + + + Export cancelled or failed. + Eksportowanie nie udaÅ‚o siÄ™ lub zostaÅ‚o zaniechane. + + + + ExtendedScintilla + + + + Ctrl+H + Ctrl+H + + + + Ctrl+F + Ctrl+F + + + + + Ctrl+P + Ctrl+P + + + + Find... + Znajdź... + + + + Find and Replace... + Znajdź i zamień… + + + + Print... + Wydrukuj... + + + + ExtendedTableWidget + + + Use as Exact Filter + Użyj jako dokÅ‚adnego filtra + + + + Containing + Zawiera + + + + Not containing + Nie zawiera + + + + Not equal to + Nierówny + + + + Greater than + WiÄ™kszy niż + + + + Less than + Mniejszy niż + + + + Greater or equal + WiÄ™kszy lub równy + + + + Less or equal + Mniejszy lub równy + + + + Between this and... + PomiÄ™dzy tym a... + + + + Regular expression + Wyrażenie regularne + + + + Edit Conditional Formats... + ZmieÅ„ formatowanie warunkowe... + + + + Set to NULL + Ustaw jako NULL + + + + Cut + Wytnij + + + + Copy + Skopiuj + + + + Copy with Headers + Skopiuj wraz z nagłówkami + + + + Copy as SQL + Skopiuj jako SQL + + + + Paste + Wklej + + + + Print... + Wydrukuj... + + + + Use in Filter Expression + Użyj w wyrażeniu filtra + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>Nie wczytano wszystkich danych. <b>Czu chcesz wczytać wszystkie dane przez zaznaczeniem wszystkich wierszy?</b><p><p>Odpowiedź <b>Nie</b> oznacza, że nie +zostanie wczytanych wiÄ™cej danych i nie zostanie nic zaznaczone.<br/>Odpowiedź <b>Tak</b> oznacza, że trochÄ™ czasu może być potrzebne na wczytanie danych za to zaznaczenie bÄ™dzie peÅ‚ne.</p>Uwaga: Wczytanie wszystkich danych może wymagać dużej iloÅ›ci pamiÄ™ci dla dużych tabel. + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + Nie można ustawić zaznaczonych na NULL. Kolumna %1 ma ograniczenie NOT NULL. + + + + Alt+Del + Alt+Del + + + + Ctrl+Shift+C + Ctrl+Shift+C + + + + Ctrl+Alt+C + Ctrl+Alt+C + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + Zawartość schowka jest wiÄ™ksza niż zaznaczony zakres. +Czy chcesz go wstawić mimo tego? + + + + FileExtensionManager + + + File Extension Manager + ZarzÄ…dzanie Rozszerzeniami Plików + + + + &Up + &W górÄ™ + + + + &Down + W &dół + + + + &Add + Dod&aj + + + + &Remove + &UsuÅ„ + + + + + Description + Opis + + + + Extensions + Rozszerzenia + + + + *.extension + *.rozszerzenie + + + + FilterLineEdit + + + Filter + Filtr + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + Te pola wejÅ›ciowe umożliwiajÄ… szybkie filtrowanie na bieżącej tabeli. +DomyÅ›lnie, wiersze zawierajÄ…ce tekst wejÅ›ciowy sÄ… odfiltrowywane. +ObsÅ‚ugiwane sÄ… nastÄ™pujÄ…ce operatory: +% Znak wieloznaczny +> WiÄ™ksze niż +< Mniejsze niż +>= Równe lub wiÄ™ksze +<= Równe lub mniejsze += Równe: dokÅ‚adnie pasuje +<> Nierówne: nie pasuje +x~y Zakres: wartoÅ›ci pomiÄ™dzy x oraz y +/regexp/ WartoÅ›ci pasujÄ…ce do wyrażenia regularnego + + + + Clear All Conditional Formats + Wyczyść wszystkie formatowania warunkowe + + + + Use for Conditional Format + Użyj do formatowania warunkowego + + + + Edit Conditional Formats... + Edytuj formatowanie warunkowe... + + + + Set Filter Expression + Ustaw wyrażenia filtra + + + + What's This? + Co to jest? + + + + Is NULL + Jest NULL + + + + Is not NULL + Nie jest NULL + + + + Is empty + Jest puste + + + + Is not empty + Nie jest puste + + + + Not containing... + Nie zawiera... + + + + Equal to... + Równe... + + + + Not equal to... + Nierówne... + + + + Greater than... + WiÄ™ksze niż... + + + + Less than... + Mniejsze niż... + + + + Greater or equal... + WiÄ™ksze lub równe... + + + + Less or equal... + Mniejsze lub równe... + + + + In range... + W zakresie... + + + + Regular expression... + Wyrażenie regularne... + + + + FindReplaceDialog + + + Find and Replace + Znajdź i zastÄ…p + + + + Fi&nd text: + Z&najdź tekst: + + + + Re&place with: + ZamieÅ„ &z: + + + + Match &exact case + Rozróżniaj wielkość lit&er + + + + Match &only whole words + Tylk&o caÅ‚e wyrazy + + + + When enabled, the search continues from the other end when it reaches one end of the page + Po zaznaczeniu, wyszukiwanie jest wznawiane od przeciwlegÅ‚ego koÅ„ca strony po osiÄ…gniÄ™ciu koÅ„ca strony + + + + &Wrap around + Za&wijaj + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + Po zaznaczeniu, wyszukiwanie postÄ™puje wstecz od poÅ‚ożenia wskaźnika, w przeciwnym przypadku postÄ™puje wprzód + + + + Search &backwards + Szukaj &na odwrót + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>Po zaznaczeniu, wzorzec do znalezienia jest szukany tylko w bieżącym zaznaczeniu.</p></body></html> + + + + &Selection only + Tylko &zaznaczenie + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Po zaznaczeniu, wzorzec do znalezienia jest rozważany jako wyrażenie regularne UNIX. Zajrzyj do <a href="https://en.wikibooks.org/wiki/Regular_Expressions">WyrażeÅ„ Regularnych w Wikibooks</a>.</p></body></html> + + + + Use regular e&xpressions + Stosuj wyrażenie &regularne + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + Szukaj kolejnego wystÄ…pienia od poÅ‚ożenia wskaźnika i w stronÄ™ okreÅ›lonÄ… poprzez +"Wyszukiwanie wstecz" + + + + &Find Next + Z&najdź nastÄ™pne + + + + F3 + F3 + + + + &Replace + &ZastÄ…p + + + + Highlight all the occurrences of the text in the page + PodÅ›wietl wszystkie wystÄ…pienia tekstu na stronie + + + + F&ind All + Znajdź wszystk&ie + + + + Replace all the occurrences of the text in the page + ZastÄ…p wszystkie wystÄ…pienia w tekÅ›cie na stronie + + + + Replace &All + Z&amieÅ„ wszystkie + + + + The searched text was not found + Nie znaleziono szukanego tekstu + + + + The searched text was not found. + Nie znaleziono szukanego tekstu. + + + + The searched text was found one time. + Szukany tekst zostaÅ‚ znaleziony raz. + + + + The searched text was found %1 times. + Szukany tekst zostaÅ‚ znaleziony %1 razy. + + + + The searched text was replaced one time. + Szukany tekst zostaÅ‚ zamieniony raz. + + + + The searched text was replaced %1 times. + Szukany tekst zostaÅ‚ zamieniony %1 razy. + + + + ForeignKeyEditor + + + &Reset + &Resetuj + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + Polecenia obcego klucza (ON UPDATE, ON DELETE itp.) + + + + ImageViewer + + + Image Viewer + PrzeglÄ…darka obrazów + + + + Reset the scaling to match the original size of the image. + Wyzeruj podziaÅ‚kÄ™, aby byÅ‚a równa pierwotnemu rozmiarowi obrazu. + + + + Set the scaling to match the size of the viewport. + Ustaw podziaÅ‚kÄ™, aby obraz zmieÅ›ciÅ‚ siÄ™ w widoku. + + + + Print... + Wydrukuj... + + + + Open preview dialog for printing displayed image + Otwórz okno podglÄ…du do wydrukowania wyÅ›wietlanego obrazu + + + + Ctrl+P + Ctrl+P + + + + ImportCsvDialog + + + Import CSV file + Zaimportuj plik CSV + + + + Table na&me + &Nazwa tabeli + + + + &Column names in first line + &Nazwy kolumn w pierwszej linii + + + + Field &separator + &Znak oddzielajÄ…cy pola + + + + , + , + + + + ; + ; + + + + + Tab + Tab + + + + | + | + + + + Other + Inny + + + + &Quote character + Znak &cytatów + + + + + Other (printable) + Inne (drukowalne) + + + + + Other (code) + Inny (kod) + + + + " + " + + + + ' + ' + + + + &Encoding + Kodowani&e + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Trim fields? + Przycinać pola? + + + + Separate tables + Oddzielaj tabele + + + + Advanced + Rozszerzone + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + Przy importowaniu pustej wartoÅ›ci z pliku CSV do istniejÄ…cej tabeli z domyÅ›lnÄ… wartoÅ›ciÄ… dla tej kolumny, wstawiana jest ta domyÅ›lna wartość. Aby zamiast tego wstawić pustÄ… wartość, wystarczy zaznaczyć to pole. + + + + Ignore default &values + Ignoruj domyÅ›lne &wartoÅ›ci + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + Zaznacz to pole, aby zatrzymać importowanie, podczas importowania pustej wartoÅ›ci do kolumny NOT NULL bez domyÅ›lnej wartoÅ›ci. + + + + Fail on missing values + ZgÅ‚aszaj błąd dla brakujÄ…cych wartoÅ›ci + + + + Disable data type detection + Wyłącz wykrywanie rodzajów danych + + + + Disable the automatic data type detection when creating a new table. + Wyłącz samowykrywanie rodzaju danych przy tworzeniu nowej tabeli. + + + + Use local number conventions + Użyj zapisu liczb z mojego jÄ™zyka + + + + Use decimal and thousands separators according to the system locale. + Użyj znaku dziesiÄ™tnego i do rozdzielania tysiÄ™cy z jÄ™zyka mojego systemu. + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + Przy importowaniu do istniejÄ…cej tabeli o głównym kluczu, ograniczeniu lub indeksie niepowtarzalnoÅ›ci istnieje szansa na sprzeczność. To ustawienie umożliwia wybranie strategii dla tego przypadku. DomyÅ›lnie importowanie jest przerywane, a zmiany wycofywane, lecz można także pominąć wiersze bÄ™dÄ…ce w sprzecznoÅ›ci lub zastÄ…pić istniejÄ…cy wiersz w tabeli. + + + + Abort import + Przerwij importowanie + + + + Ignore row + PomiÅ„ wiersz + + + + Replace existing row + ZastÄ…p istniejÄ…cy wiersz + + + + Conflict strategy + Strategia na sprzecznoÅ›ci + + + + + Deselect All + Odznacz wszystkie + + + + Match Similar + Dopasuj do podobnych + + + + Select All + Zaznacz wszystkie + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + Tabela o nazwie '%1' już istnieje i importowanie do istniejÄ…cej tabeli jest możliwe tylko gdy liczba kolumn zgadza siÄ™. + + + + There is already a table named '%1'. Do you want to import the data into it? + Tabela o nazwie '%1' już istnieje. Czy chcesz zaimportować dane do niej? + + + + Creating restore point failed: %1 + Nie można utworzyć punktu przywracania: %1 + + + + Creating the table failed: %1 + Tworzenie tabeli nie powiodÅ‚o siÄ™: %1 + + + + importing CSV + importowanie CSV + + + + Could not prepare INSERT statement: %1 + Nie można byÅ‚o przygotować polecania INSERT: %1 + + + + Inserting row failed: %1 + Wstawianie rzÄ™du nie powiodÅ‚o siÄ™: %1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + Nieoczekiwany koniec pliku. Upewnij siÄ™, że masz poprawnie ustawione znaki cytowania i że plik nie jest znieksztaÅ‚cony. + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + Importowanie pliku '%1' zajęło %2ms. Z tego %3ms spÄ™dzono na funkcji wiersza. + + + + MainWindow + + + DB Browser for SQLite + PrzeglÄ…darka SQLite + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + Uwaga: to polecenie pragma nie jest czytelne, wiÄ™c ta wartość powstaÅ‚a z domysÅ‚u. Zapisanie polecenie pragma może zastÄ…pić LIKE dostarczony przez rozszerzenie SQLite. + + + + toolBar1 + toolBar1 + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + Oto ukÅ‚ad bieżącej bazy danych. +Można przeciÄ…gać polecenia SQL z wiersza obiektu i upuszczać je na innych aplikacjach lub wstawiać je do innego wystÄ…pienia 'PrzeglÄ…darki SQLite'. + + + + + Execute line + Wykonaj wiersz + + + + Un/comment block of SQL code + Dodaj/UsuÅ„ uwagÄ™ do kawaÅ‚ka kodu SQL + + + + Un/comment block + Dodaj/UsuÅ„ uwagÄ™ do kawaÅ‚ka kodu + + + + Comment or uncomment current line or selected block of code + Dodaj lub usuÅ„ uwagÄ™ do bieżącego wiersza lub zaznaczonego kawaÅ‚ka kodu + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + Dodaj lub usuÅ„ uwagÄ™ do bieżącego wiersza lub zaznaczonych wierszy, gdy jest coÅ› zaznaczone. CaÅ‚y kawaÅ‚ek przełączany jest wg pierwszego wiersza. + + + + Ctrl+/ + Ctrl+/ + + + + Stop SQL execution + Zatrzymaj wykonywanie SQL + + + + Stop execution + Zatrzymaj wykonywanie + + + + Stop the currently running SQL script + Zatrzymaj wykonywanie bieżącego skryptu SQL + + + + &File + &Plik + + + + &Import + Za&importuj + + + + &Export + Wy&eksportuj + + + + &Edit + &Edycja + + + + &View + &Widok + + + + &Help + Po&moc + + + + Too&ls + &NarzÄ™dzia + + + + DB Toolbar + Pasek zadaÅ„ bazy danych + + + + Edit Database &Cell + Zmiana komórki bazy dany&ch + + + + SQL &Log + Dziennik SQ&L + + + + Show S&QL submitted by + Pokaż S&QL wydane przez + + + + User + Użytkownika + + + + Application + AplikacjÄ™ + + + + Error Log + Dziennik błędów + + + + This button clears the contents of the SQL logs + Ten przycisk czyÅ›ci zawartość logów SQL + + + + &Clear + Wy&czyść + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + Ten panel umożliwia przeglÄ…d dziennika wszystkich poleceÅ„ SQL wydanych przez aplikacjÄ™ lub przez ciebie + + + + &Plot + &Wykres + + + + DB Sche&ma + UkÅ‚ad da&nych + + + + &Remote + &Zdalne BD + + + + + Project Toolbar + Pasek zadaÅ„ projektu + + + + Extra DB toolbar + Dodatkowy pasek zadaÅ„ bazy danych + + + + + + Close the current database file + Zamknij obecny plik bazy danych + + + + &New Database... + &Nowa baza danych… + + + + + Create a new database file + Utwórz nowy plik bazy danych + + + + This option is used to create a new database file. + Ta opcja jest wykorzystywana do tworzenia nowego pliku bazy danych. + + + + Ctrl+N + Ctrl+N + + + + + &Open Database... + &Otwórz bazÄ™ danych… + + + + + + + + Open an existing database file + Otwórz istniejÄ…cÄ… bazÄ™ danych + + + + + + This option is used to open an existing database file. + Ta opcja otwiera istniejÄ…cy plik bazy danych. + + + + Ctrl+O + Ctrl+O + + + + &Close Database + Zamknij bazÄ™ dany&ch + + + + This button closes the connection to the currently open database file + Ten przycisk koÅ„czy połączenie z obecnie otwartym plikiem bazy danych + + + + New &tab + Nowa kar&ta + + + + Open SQL file(s) + Otwórz plik(i) SQL + + + + This button opens files containing SQL statements and loads them in new editor tabs + Przycisk ten otwiera pliki, zawierajÄ…ce polecenia SQL oraz wczytuje je do kart nowego edytora + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + Przycisk ten umożliwia zapisanie wszystkich ustawieÅ„ zwiÄ…zanych z otwieraniem bazy danych w PrzeglÄ…darce BD w przypadku pliku projektu + + + + This button lets you open a DB Browser for SQLite project file + Przycisk ten umożliwia ci otwarcie pliku projektu PrzeglÄ…darki BD + + + + &Open Database + &Otwórz bazÄ™ danych + + + + Drag && Drop SELECT Query + PrzeciÄ…gnij && upuść zapytanie SELECT + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + Przy przeciÄ…gniu pól z tej samej tabeli lub pojedynczej tabeli upuść zapytania SELECT na edytor + + + + Browse Table + PrzeglÄ…daj tabelÄ™ + + + + Close Pro&ject + Zamknij pro&jekt + + + + + Close project and database files and return to the initial state + Zamknij plik projektu i bazy danych oraz zwróć poczÄ…tkowy stan + + + + Ctrl+Shift+F4 + Ctrl+Shift+F4 + + + + + Detach Database + Odłącz bazÄ™ danych + + + + + Detach database file attached to the current database connection + Odłącz plik bazy danych dołączony do bieżącego połączenia bazy danych + + + + + Ctrl+W + Ctrl+W + + + + &Revert Changes + &Wycofaj zmiany + + + + + Revert database to last saved state + Przywróć bazÄ™ danych do ostatniego zapisanego stanu + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + Ten dziaÅ‚anie sÅ‚uży do przywrócenia bieżącej bazy danych do ostatnio zapisanego stanu. Wszystkie zmiany od czasu ostatniego zapisu zostanÄ… utracone. + + + + &Write Changes + &Zapisz zmiany + + + + + Write changes to the database file + Zapisz zmiany w pliku bazy danych + + + + This option is used to save changes to the database file. + Ta opcja zapisuje zmiany w pliku bazy danych. + + + + Ctrl+S + Ctrl+S + + + + Ctrl+Shift+O + Ctrl+Shift+O + + + + &Save Project As... + Zapi&sz projekt jako... + + + + + + Save the project in a file selected in a dialog + Zapisuje projekt w pliku wskazanym w dialogu + + + + Save A&ll + Zapisz w&szystko + + + + + + Save DB file, project file and opened SQL files + Zapisuje plik bazy danych, projektu i otwarte pliki SQL + + + + Ctrl+Shift+S + Ctrl+Shift+S + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + Oto ukÅ‚ad bieżącej bazy danych. +Można przeciÄ…gać wiele nazw obiektów z kolumny nazwy i upuszczać je w edytorze SQL. NastÄ™pnie można dostosować wÅ‚aÅ›ciwoÅ›ci upuszczonych nazw poprzez menu podrÄ™czne. To ma na celu pomoc w tworzeniu polecenia SQL. +Można przeciÄ…gać polecenia SQL z kolumny schematu i upuszczać je w edytorze SQL lub innych aplikacjach. + + + + + Compact &Database... + ÅšciÅ›nij bazÄ™ &danych... + + + + Compact the database file, removing space wasted by deleted records + ÅšciÅ›nij plik bazÄ™ danych, usuwajÄ…c przestrzenie marnowane przez usuniÄ™te rekordy + + + + + Compact the database file, removing space wasted by deleted records. + ÅšciÅ›nij plik bazÄ™ danych, usuwajÄ…c przestrzenie marnowane przez usuniÄ™te rekordy. + + + + E&xit + &Wyjdź + + + + Ctrl+Q + Ctrl+Q + + + + &Database from SQL file... + BazÄ™ &danych z pliku SQL… + + + + Import data from an .sql dump text file into a new or existing database. + Zaimportuj dane z pliku tekstowego zrzutu .sql do nowej lub istniejÄ…cej bazy danych. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + To dziaÅ‚anie, umożliwia importowanie danych z pliku tekstowego zrzutu .sql do nowej lub istniejÄ…cej bazy danych. Pliki zrzutu SQL można utworzyć w wiÄ™kszoÅ›ci silników baz danych, włączajÄ…c w to MySQL oraz PostgreSQL. + + + + &Table from CSV file... + &TabelÄ™ z pliku CSV… + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Otwiera okno pomocnika do importowania danych z pliku CSV do tabeli bazy danych. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Otwiera okno pomocnika do importowania danych z pliku CSV do tabeli bazy danych. +Plik CSV można stworzyć na podstawie wiÄ™kszoÅ›ci baz danych i aplikacji arkuszy kalkulacyjnych. + + + + &Database to SQL file... + BazÄ™ &danych do pliku SQL… + + + + Export a database to a .sql dump text file. + Wyeksportuj bazÄ™ danych do pliku tekstowego zrzutu .sql. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + To dziaÅ‚anie umożliwia eksportowanie bazy danych do pliku tekstowego zrzutu .sql. Plik zrzutu SQL zawiera wszystkie dane niezbÄ™dne do odtworzenia bazy danych na wiÄ™kszoÅ›ci silników baz danych, włączajÄ…c w to MySQL oraz PostgreSQL. + + + + &Table(s) as CSV file... + &TabelÄ™ do pliku CSV… + + + + Export a database table as a comma separated text file. + Eksportuje tabelÄ™ bazy danych jako plik tekstowy, oddzielajÄ…c wartoÅ›ci przecinkami. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + Eksportuje tabelÄ™ bazy danych jako plik tekstowym który można zaimportować w innych aplikacjach bazodanowych lub arkuszach kalkulacyjnych; oddzielajÄ…c wartoÅ›ci przecinkami. + + + + &Create Table... + &Utwórz tabelę… + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Otwiera okno tworzenia tabel, gdzie można zdefiniować nazwÄ™ i pola w nowej tabeli w bazie danych + + + + &Delete Table... + U&suÅ„ tabelę… + + + + + Delete Table + UsuÅ„ tabelÄ™ + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Otwiera pomocnika do UsuniÄ™cia Tabeli, gdzie można wybrać tabelÄ™ bazy danych do usuniÄ™cia. + + + + &Modify Table... + &Dostosuj tabelÄ™... + + + + Create &Index... + Utwórz &indeks… + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + Otwiera pomocnika do Tworzenia Indeksu, gdzie można okreÅ›lić nowy indeks na istniejÄ…cej tabeli bazy danych. + + + + &Preferences... + U&stawienia... + + + + + Open the preferences window. + Otwórz okno ustawieÅ„. + + + + &DB Toolbar + Pasek narzÄ™dzi bazy &danych + + + + Shows or hides the Database toolbar. + Pokazuje lub ukrywa pasek narzÄ™dzi od bazy danych. + + + + Ctrl+T + Ctrl+T + + + + W&hat's This? + &Co to jest? + + + + + Ctrl+F4 + Ctrl+F4 + + + + Shift+F1 + Shift+F1 + + + + &About + O progr&amie + + + + &Load Extension... + &Wczytaj rozszerzenia... + + + + &Wiki + &Wiki + + + + F1 + F1 + + + + Bug &Report... + &ZgÅ‚oszenie błędu... + + + + Feature Re&quest... + ZgÅ‚oszenie ż&yczenia... + + + + Web&site + Strona &sieciowa + + + + &Donate on Patreon... + &Darowizna na Patreon... + + + + Open &Project... + Otwórz &projekt... + + + + &Attach Database... + Dołącz bazÄ™ d&anych... + + + + &Set Encryption... + U&staw szyfrowanie... + + + + This button saves the content of the current SQL editor tab to a file + Ten przycisk zapisuje treść bieżącej karty edytora SQL do pliku + + + + SQLCipher &FAQ + &Najczęściej zadawane pytania SQLCipher + + + + New In-&Memory Database + Nowa baza danych w-pa&miÄ™ci + + + + Drag && Drop Qualified Names + PrzeciÄ…gnij && upuść nazwy z ukÅ‚adu + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + Używaj nazw z ukÅ‚adu (np. "Tabela"."Pole") przy przeciÄ…ganiu obiektów i upuszczaniu ich w edytorze + + + + Drag && Drop Enquoted Names + PrzeciÄ…gnij && upuść nazw w cudzysÅ‚owach + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + Używaj nazw w cudzysÅ‚owach (np. "Tabela1") przy przeciÄ…ganiu obiektów i upuszczaniu ich w edytorze + + + + &Integrity Check + Sprawdzanie spójnoÅ›c&i + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + Wykonuje polecenie pragma integrity_check na bieżącej bazie danych i zwraca wynik na karcie Wykonywania SQL. To polecenie pragma wykonuje sprawdzenie spójnoÅ›ci caÅ‚ej bazy danych. + + + + &Foreign-Key Check + &Sprawdzenie obcego klucza + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + Wykonuje polecenie pragma foreign_key_check na bieżącej bazie danych i zwraca wynik na karcie Wykonywania SQL + + + + &Quick Integrity Check + &Szybkie sprawdzenie spójnoÅ›ci + + + + Run a quick integrity check over the open DB + Wykonaj sprawdzenie spójnoÅ›ci bieżącej bazy danych + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + Wykonuje polecenie pragma quick_check na bieżącej bazie danych i zwraca wynik na karcie Wykonywania SQL. To polecenie pragma wykonuje wiÄ™kszość tego, co wykonuje polecenie pragma integrity_check lecz robi to znacznie szybciej. + + + + &Optimize + &Optymalizacja + + + + Attempt to optimize the database + Próba optymalizacji bazy danych + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + Wykonuje polecenie pragma optimize na bieżącej bazie danych. To polecenie może wykonać optymalizacje, które zwiÄ™kszÄ… wydajność przyszÅ‚ych zapytaÅ„. + + + + + Print + Wydrukuj + + + + Print text from current SQL editor tab + Wydrukuj tekst z bieżącej karty edytora SQL + + + + Open a dialog for printing the text in the current SQL editor tab + Otwiera okno dialogowe do drukowania tekstu w bieżącej karcie edytora SQL + + + + Print the structure of the opened database + Wydrukuj ukÅ‚ad bieżącej bazy danych + + + + Open a dialog for printing the structure of the opened database + Otwiera okno do drukowania ukÅ‚adu bieżącej bazy danych + + + + &Recently opened + Ostatnio otwie&rane + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + UkÅ‚ad bazy &danych + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + Prze&glÄ…daj dane + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + Edytuj p&ragmy + + + + Temp Store + + + + + Secure Delete + + + + + Case Sensitive Like + + + + + Journal Mode + + + + + Journal Size Limit + + + + + Recursive Triggers + + + + + Page Size + + + + + Foreign Keys + Klucze obce + + + + Auto Vacuum + + + + + Max Page Count + + + + + Checkpoint Full FSYNC + + + + + + Off + + + + + + Normal + + + + + + Full + + + + + Default + + + + + File + Plik + + + + + Memory + + + + + Delete + + + + + Truncate + + + + + Persist + + + + + WAL + + + + + Exclusive + + + + + Automatic Index + + + + + Ignore Check Constraints + + + + + Full FSYNC + + + + + WAL Auto Checkpoint + + + + + User Version + + + + + Synchronous + + + + + None + Brak + + + + Incremental + + + + + Locking Mode + + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + W&ykonaj SQL + + + + &Recent Files + Os&tatnie pliki + + + + &New Database + &Nowa baza danych + + + + &Undo + &Cofnij + + + + + Undo last change to the database + Wycofaj ostatniÄ… zmianÄ™ w bazie danych + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + To dziaÅ‚anie wycofuje ostatniÄ… zmianÄ™ dokonanÄ… w bazie danych w PrzeglÄ…darce Bazy Danych lub poprzez Wykonanie Polecenia SQL. Ponowienie tego dziaÅ‚ania jest niemożliwe. + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + Otwiera pomocnika Zmiany Tabeli, gdzie można zmienić nazwÄ™ istniejÄ…cej tabeli. +Można także dodawać i usuwać pola z tabeli, a także zmieniać nazwy oraz rodzaje pól. + + + + This button opens a new tab for the SQL editor + Ten przycisk otwiera nowÄ… tabelÄ™ w edytorze SQL + + + + &Execute SQL + &Wykonaj polecenie SQL + + + + Execute all/selected SQL + Wykonaj wszystkie/zaznaczone SQL + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + Ten przycisk wykona obecnie zaznaczone polecenia SQL. JeÅ›li nie zaznaczone tekstu, to zostanÄ… wykonane wszystkie polecenia SQL. + + + + Ctrl+Shift+T + Ctrl+Shift+T + + + + + + Save SQL file + Zapisz plik SQL + + + + + Execute current line + Wykonaj bieżący wiersz + + + + This button executes the SQL statement present in the current editor line + Ten przycisk wykonuje polecenie SQL z obecnego wiersza edytora + + + + Shift+F5 + Shift+F5 + + + + Export as CSV file + Wyeksportuj do pliku CSV + + + + Export table as comma separated values file + Wyeksportuj tabelÄ™ jako plik z wartoÅ›ciami oddzielonymi przecinkami + + + + Sa&ve Project + &Zapisz projekt + + + + &Save Project + Zapi&sz projekt + + + + + Save the current session to a file + Zapisz obecnÄ… sesjÄ™ do pliku + + + + Open &Project + Otwórz &projekt + + + + + Load a working session from a file + Wczytaj otoczenie pracy z pliku + + + + + Add another database file to the current database connection + Dodaj kolejny plik bazy danych do połączenia bieżącej bazy danych + + + + This button lets you add another database file to the current database connection + Ten przycisk umożliwia dodanie kolejnego pliku bazy danych do połączenia bieżącej bazy danych + + + + + Save SQL file as + Zapisz plik SQL jako + + + + &Browse Table + &PrzeglÄ…daj tabelÄ™ + + + + Copy Create statement + Skopiuj polecenie tworzÄ…ce + + + + Copy the CREATE statement of the item to the clipboard + Skopiuj polecenie CREATE elementu do schowka + + + + Opens the SQLCipher FAQ in a browser window + Otwiera FAQ SQLCipher w oknie przeglÄ…darki + + + + Table(&s) to JSON... + Tabele do pliku J&SON… + + + + Export one or more table(s) to a JSON file + Wyeksportuj jednÄ… lub wiÄ™cej tabel do pliku JSON + + + + Open Data&base Read Only... + Otwórz &bazÄ™ danych tylko do odczytu… + + + + Open an existing database file in read only mode + Otwórz istniejÄ…cy plik bazy danych w trybie tylko do odczytu + + + + Save results + Zapisz wyniki + + + + Save the results view + Zapisuje widok wyniku + + + + This button lets you save the results of the last executed query + Ten przycisk umożliwia zapisanie wyników ostatnio wykonanego zapytania + + + + + Find text in SQL editor + Znajdź tekst w edytorze SQL + + + + Find + Znajdź + + + + This button opens the search bar of the editor + Ten przycisk otwiera pasek wyszukiwania edytora + + + + Ctrl+F + Ctrl+F + + + + + Find or replace text in SQL editor + Znajdź lub zastÄ…p tekst w edytorze SQL + + + + Find or replace + Znajdź i zastÄ…p + + + + This button opens the find/replace dialog for the current editor tab + Ten przycisk otwiera okno dialogowe znajdowania/zastÄ™powania dla bieżącej karty edytora + + + + Ctrl+H + Ctrl+H + + + + Export to &CSV + Wyeksportuj do &CSV + + + + Export to &JSON + Wyeksportuj do &JSON + + + + Save as &view + Zapisz jako &widok + + + + Save as view + Zapisz jako widok + + + + Shows or hides the Project toolbar. + Pokazuje lub ukrywa pasek narzÄ™dzi Projekt. + + + + Extra DB Toolbar + Dodatkowy pasek narzÄ™dzi bazy danych + + + + + Ctrl+Shift+W + Ctrl+Shift+W + + + + Table from CSV data in Clipboard... + Tabela z danych CSV ze schowka... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + Traktuje to bieżącÄ… zawartość schowka jako plik CSV i otwiera tego samego pomocnika importowania, co w przypadku importowania danych CSV z pliku. + + + + Show &Row Counts + Pokaż licznik wie&rszy + + + + This shows the number of rows for each table and view in the database. + Pokazuje to liczbÄ™ wierszy dla każdej tabeli i wodku w bazie danych. + + + + Save Database &As... + Z&apisz bazÄ™ danych jako... + + + + Save the current database as a different file + Zapisz bieżącÄ… bazÄ™ danych do innego pliku + + + + Refresh + OdÅ›wież + + + + Reload the database structure + Wczytaj ponownie strukturÄ™ bazy danych + + + + Ctrl+Return + Ctrl+Enter + + + + Ctrl+L + Ctrl+L + + + + + Ctrl+P + Ctrl+P + + + + Ctrl+D + Ctrl+D + + + + Ctrl+I + Ctrl+I + + + + Ctrl+E + Ctrl+E + + + + Reset Window Layout + Wyzeruj ukÅ‚ad okien + + + + The database is currently busy. + Baza danych jest obecnie zajÄ™ta. + + + + Click here to interrupt the currently running query. + NaciÅ›nij tutaj, aby przerwać wykonywanie bieżącego zapytania. + + + + Encrypted + Szyfrowana + + + + Database is encrypted using SQLCipher + Baza danych jest zaszyfrowana z użyciem SQLCipher + + + + Read only + Tylko do odczytu + + + + Database file is read only. Editing the database is disabled. + Plik bazy danych jest tylko do odczytu. Edytowanie bazy danych jest wyłączone. + + + + Database encoding + Kodowanie bazy danych + + + + + Choose a database file + Wybierz plik bazy danych + + + + Could not open database file. +Reason: %1 + Nie można otworzyć pliku bazy danych. +Powód: %1 + + + + + + Choose a filename to save under + Wybierz nazwÄ™ pliku do zapisu + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + Ustawianie wartoÅ›ci PRAGMA lub odkurzanie spowoduje wdrożenie twoich zmian +z bieżącej transakcji. +Czy na pewno? + + + + In-Memory database + Baza danych w-pamiÄ™ci + + + + Automatically load the last opened DB file at startup + + + + + Ctrl+0 + Ctrl+0 + + + + Alt+Shift+W + Alt+Shift+W + + + + Choose a database file to save under + Wybierz plik, do którego zapisać bazÄ™ danych + + + + Error while saving the database to the new file. + Napotkano błąd podczas zapisywania bazy danych do nowego pliku. + + + + Do you want to save the changes made to the project file '%1'? + Czy chcesz zapisać zmiany wprowadzone w plik projektu '%1'? + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + Czy na pewno usunąć tabelÄ™ '%1'? +Wszystkie dane skojarzone z tÄ… tabelÄ… zostanÄ… utracone. + + + + Are you sure you want to delete the view '%1'? + Czy na pewno usunąć widok '%1'? + + + + Are you sure you want to delete the trigger '%1'? + Czy na pewno usunąć wyzwalacz '%1'? + + + + Are you sure you want to delete the index '%1'? + Czy na pewno usunąć indeks '%1'? + + + + Error: could not delete the table. + Błąd: nie można usunąć bazy danych. + + + + Error: could not delete the view. + Błąd: nie można usunąć widoku. + + + + Error: could not delete the trigger. + Błąd: nie można usunąć wyzwalacza. + + + + Error: could not delete the index. + Błąd: nie można usunąć indeksu. + + + + Message from database engine: +%1 + Wiadomość z silnika bazy danych: +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + Zmiana tabeli wymaga zapisania wszystkich oczekujÄ…cych zmian. +Czy na pewno zapisać bazÄ™ danych? + + + + Error checking foreign keys after table modification. The changes will be reverted. + Błąd sprawdzania kluczy obcych po zmianie tabeli. Zmiany zostanÄ… wycofane. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + Tabela nie przeszÅ‚a sprawdzenia klucza obcego.<br/>Należy wykonać 'NarzÄ™dzia | Sprawdzenie obcego klucza' i naprawić zgÅ‚oszone kÅ‚opoty. + + + + Edit View %1 + Edytuj widok %1 + + + + Edit Trigger %1 + Edytuj wyzwalacz %1 + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + Już wykonujesz polecenia SQL. Czy zatrzymać je, aby wykonać bieżące polecenia? DziaÅ‚anie to może spowodować niespójność w bazie danych. + + + + -- EXECUTING SELECTION IN '%1' +-- + -- WYKONYWANIE ZAZNACZENIA W '%1' +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- WYKONYWANIE WIERSZA W '%1' +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- WYKONYWANIE WSZYSTKIEGO W '%1' +-- + + + + + At line %1: + W wierszu %1: + + + + Result: %1 + Wynik: %1 + + + + Result: %2 + Wynik: %2 + + + + %1 rows returned in %2ms + Zwrócono %1 wierszy w czasie %2ms + + + + Choose text files + Wybierz pliki tekstowe + + + + Opened '%1' in read-only mode from recent file list + Otworzono '%1' w trybie tylko do odczytu ze spisu ostatnich plików + + + + Opened '%1' from recent file list + Otwarto '%1' ze spisu ostatnich plików + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + Wybierz dziaÅ‚anie dla upuszczonego pliku. <br/>Uwaga: tylko 'Import' przetworzy wiÄ™cej niż jeden plik. + Wybierz dziaÅ‚anie dla upuszczonych %n plików. <br/>Uwaga: tylko 'Import' przetworzy wiÄ™cej niż jeden plik. + Wybierz dziaÅ‚anie dla upuszczonych %n plików. <br/>Uwaga: tylko 'Import' przetworzy wiÄ™cej niż jeden plik. + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + Polecenia na karcie '%1' nadal sÄ… wykonywane. ZamkniÄ™cie tej karty przerwie ich wykonywanie. Może to pozostawić bazÄ™ danych w niespójnym stanie. Czy na pewno zamknąć tÄ™ kartÄ™? + + + + DB file '%1' could not be opened + Nie można otworzyć pliku BD '%1' + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + Projekt ten używa starego formatu pliku, bo zostaÅ‚ stworzony w PrzeglÄ…darce BD w wersji 3.10 lub wczeÅ›niejszej. Wczytywanie takich formatów plików nie jest już obsÅ‚ugiwane. JeÅ›li chcesz go wczytać caÅ‚kowicie, to użyj PrzeglÄ…darki BD w wersji 3.12 i przekształć go na nowy format pliku. + + + + Table '%1' not found; settings ignored + Nie można byÅ‚o odnaleźć tabeli '%1'; pominiÄ™to ustawienia + + + + -- Reference to file "%1" (not supported by this version) -- + -- Odniesienie do pliku "%1" (nieobsÅ‚ugiwane w tej wersji) -- + + + + Project saved to file '%1' + Projekt zapisano do pliku '%1' + + + + Yes. Don't ask again + Tak. Nie pytaj + + + + This action will open a new SQL tab with the following statements for you to edit and run: + DziaÅ‚anie to otworzy nowÄ… kartÄ™ SQL z nastÄ™pujÄ…cymi poleceniami, które możesz dostosować i wykonać: + + + + Rename Tab + Przemianuj kartÄ™ + + + + Duplicate Tab + Powiel kartÄ™ + + + + Close Tab + Zamknij kartÄ™ + + + + Opening '%1'... + Otwieranie '%1'... + + + + There was an error opening '%1'... + Błąd otwierania '%1'... + + + + Value is not a valid URL or filename: %1 + Wartość nie jest prawidÅ‚owym adresem URL lub nazwÄ… pliku: %1 + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + Nie można zapisać bazy danych. Oznacza to, że nie wszystkie zmiany daÅ‚o siÄ™ zapisać w bazie danych. Najpierw trzeba pozbyć siÄ™ nastÄ™pujÄ…cych kÅ‚opotów. + +%1 + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + Czy na pewno wycofać wszystkie zmiany wprowadzone w pliku bazy danych '%1' od czasu ostatniego zapisu? + + + + Choose a file to import + Wybierz pliki do zaimportowania + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (tylko do odczytu) + + + + Open Database or Project + Otwórz bazÄ™ danych lub projekt + + + + Attach Database... + Dołącz bazÄ™ danych... + + + + Import CSV file(s)... + Zaimportuj plik(i) CSV... + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + Czy chcesz zapisać zmiany wprowadzone w tabelach SQL do pliku projektu '%1'? + + + + Text files(*.sql *.txt);;All files(*) + Pliki tekstowe(*.sql *.txt);;Wszystkie pliki(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + Czy utworzyć plik nowej bazy danych do przechowania zaimportowanych danych? +JeÅ›li nie, to dane zostanÄ… zaimportowane do pliku bieżącej bazy danych. + + + + Ctrl+Tab + Ctrl+Tab + + + + Ctrl+Shift+Tab + Ctrl+Shift+Tab + + + + Clear List + Wyczyść spis + + + + Window Layout + UkÅ‚ad okna + + + + Simplify Window Layout + Uprość ukÅ‚ad okien + + + + Alt+Shift+0 + Alt+Shift+0 + + + + Dock Windows at Bottom + Zadokuj okna na dole + + + + Dock Windows at Left Side + Zadokuj okna po lewej stronie + + + + Dock Windows at Top + Zadokuj okna na górze + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + Nadal wykonujesz polecenia SQL. Wykonywanie tych poleceÅ„ zostanie zatrzymane, po zamkniÄ™ciu bazy danych, co może spowodować w niej niespójnoÅ›ci. Czy na pewno zamknąć tÄ™ bazÄ™ danych? + + + + File %1 already exists. Please choose a different name. + Plik %1 już istnieje. Wybierz innÄ… nazwÄ™. + + + + Error importing data: %1 + Błąd importowania danych: %1 + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + UkoÅ„czono import. NastÄ…piÅ‚o przekroczenie niektórych z ograniczeÅ„ obcego klucza. Napraw je przed zapisaniem. + + + + Import completed. + Importowanie zakoÅ„czone. + + + + Delete View + UsuÅ„ widok + + + + Modify View + ZmieÅ„ widok + + + + Delete Trigger + UsuÅ„ wyzwalacz + + + + Modify Trigger + ZmieÅ„ wyzwalacz + + + + Delete Index + UsuÅ„ indeks + + + + Modify Index + ZmieÅ„ indeks + + + + Modify Table + Dostosuj tabelÄ™ + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + Ustawianie wartoÅ›ci PRAGMA spowoduje wdrożenie twoich zmian +z bieżącej transakcji. +Czy na pewno? + + + + Select SQL file to open + Wybierz plik SQL do otworzenia + + + + Select file name + Wybierz nazwÄ™ pliku + + + + Select extension file + Wybierz plik rozszerzenia + + + + Execution finished with errors. + Wykonano z błędami. + + + + Execution finished without errors. + Wykonano bez błędów. + + + + Do you want to save the changes made to SQL tabs in a new project file? + Czy chcesz zapisać zmiany wprowadzone w tabelach SQL do nowego pliku projektu? + + + + Do you want to save the changes made to the SQL file %1? + Czy chcesz zapisać zmiany wprowadzone w SQL do pliku %1? + + + + Extension successfully loaded. + PomyÅ›lnie wczytano rozszerzenie. + + + + Error loading extension: %1 + Nie można wczytać rozszerzenia: %1 + + + + Could not find resource file: %1 + Nie można znaleźć pliku zasobów: %1 + + + + + Don't show again + Nie pokazuj ponownie + + + + New version available. + Nowa wersja jest dostÄ™pna. + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + DostÄ™pna jest nowa wersja PrzeglÄ…darki SQLite (%1.%2.%3).<br/><br/>Pobierz z <a href='%4'>%4</a>. + + + + Choose a project file to open + Wybierz plik projektu do otworzenia + + + + DB Browser for SQLite project file (*.sqbpro) + Plik projektu PrzeglÄ…darki SQLite (*.sqbpro) + + + + Could not open project file for writing. +Reason: %1 + Nie można otworzyć pliku projektu do zapisu. +Powód: %1 + + + + Collation needed! Proceed? + Potrzebne zestawianie! PostÄ…pić naprzód? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + Tabela w tej bazie danych wymaga wyjÄ…tkowej funkcji zestawienia '%1' której ta aplikacja nie może dostarczyć bez dalszej wiedzy. +PójÅ›cia z tym dalej, może spowodować uszkodzenia w bazie danych. +Stwórz kopiÄ™ zapasowÄ…! + + + + creating collation + tworzenie zestawienia + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + Przemianowuje kartÄ™ SQL. Wstaw znaku '&&' aby móc wykorzystać nastÄ™pujÄ…cy po nim znak jako skrót klawiszowy. + + + + Please specify the view name + OkreÅ›l nazwÄ™ widoku + + + + There is already an object with that name. Please choose a different name. + Istnieje już obiekt o tej nazwie. Nadaj innÄ… nazwÄ™. + + + + View successfully created. + PomyÅ›lnie utworzono widok. + + + + Error creating view: %1 + Błąd tworzenia widoku: %1 + + + + This action will open a new SQL tab for running: + To dziaÅ‚anie otworzy nowÄ… kartÄ™ SQL aby wykonać: + + + + Press Help for opening the corresponding SQLite reference page. + NaciÅ›nij Pomoc, aby otworzyć powiÄ…zanÄ… stronÄ™ w podrÄ™czniku SQLite. + + + + Busy (%1) + ZajÄ™ty (%1) + + + + NullLineEdit + + + Set to NULL + Ustaw na NULL + + + + Alt+Del + Alt+Del + + + + PlotDock + + + Plot + Wykres + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>Ten panel pokazuje listÄ™ kolumn obecnie przeglÄ…danej tabeli lub tylko dla wykonanego zapytania. Możesz wybrać kolumny, których chcesz użyć dla osi X lub Y dla panelu wykresu poniżej. Tabela pokaże wykryty rodzaj osi, który wpÅ‚ynie na wynikowy wykres. Dla osi Y możesz wybrać kolumny tylko liczbowe, a dla osi X możesz wybrać:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Data/Czas</span>: Å‚aÅ„cuchy formatujÄ…ce &quot;yyyy-MM-dd hh:mm:ss&quot; lub &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Data</span>: Å‚aÅ„cuchy formatujÄ…ce &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Czas</span>: Å‚aÅ„cuchy formatujÄ…ce &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Etykieta</span>: formatowanie innymi Å‚aÅ„cuchami. Zaznaczenie tej kolumny jako osi X stworzy wykres sÅ‚upkowy, gdzie wartoÅ›ci kolumn bÄ™dÄ… etykietami dla sÅ‚upków</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Liczba</span>: wartoÅ›ci caÅ‚kowite lub rzeczywiste</li></ul><p>Dwukrotne klikniÄ™cie na komórkach Y zmieni barwÄ™ użytÄ… dla wykresu.</p></body></html> + + + + Columns + Kolumny + + + + X + X + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + Rodzaj osi + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + Tutaj rysowany jest wykres po wybraniu wartoÅ›ci x oraz y powyżej. + +Aby zaznaczyć punkt na wykresie i w tabeli, należy kliknąć na niego. Ctrl+Klik aby zaznaczyć zakres punktów. + +Aby zmienić zakres osi, należy kliknąć i przeciÄ…gnąć myszÄ…. Aby powiÄ™kszyć należy przewinąć rolkÄ… myszy. + +Aby przeciÄ…gnąć i powiÄ™kszyć tylko w jednÄ… stronÄ™, należy wybrać osie lub etykiety osi. + + + + Line type: + Rodzaj linii: + + + + + None + Brak + + + + Line + Linia + + + + StepLeft + Krok w lewo + + + + StepRight + Krok w prawo + + + + StepCenter + Krok do Å›rodka + + + + Impulse + Impuls + + + + Point shape: + KsztaÅ‚t punktu: + + + + Cross + Krzyż + + + + Plus + Plus + + + + Circle + Kółko + + + + Disc + Dysk + + + + Square + Kwadrat + + + + Diamond + Diament + + + + Star + Gwiazda + + + + Triangle + TrójkÄ…t + + + + TriangleInverted + TrójkÄ…t odwrócony + + + + CrossSquare + Krzyż w kwadracie + + + + PlusSquare + Plus w kwadracie + + + + CrossCircle + Krzyż w okrÄ™gu + + + + PlusCircle + Plus w okrÄ™gu + + + + Peace + Znak pokoju + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>Zapisz bieżący wykres...</p><p>Format pliku wybierany na podstawie rozszerzenia (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + Zapisz bieżący wykres… + + + + + Load all data and redraw plot + Wczytaj wszystkie dane i przerysuj wykres + + + + Copy + Skopiuj + + + + Print... + Wydrukuj... + + + + Help + + + + + Show legend + Pokaż legendÄ™ + + + + Stacked bars + SÅ‚upki na stosie + + + + Fixed number format + Format staÅ‚ej liczby + + + + Date/Time + Data/Czas + + + + Date + Data + + + + Time + Czas + + + + + Numeric + Liczbowa + + + + Label + Podpis + + + + Invalid + NieprawidÅ‚owy + + + + + + Row # + Nr wiersza + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + Wczytaj wszystkie dane i przerysuj wykres. +Uwaga: jeszcze nie wczytano wszystkich danych z tabeli ze wzglÄ™du na mechanizm częściowego wczytywania. + + + + Choose an axis color + Wybierz barwÄ™ osi + + + + Choose a filename to save under + Wybierz nazwÄ™ pliku do zapisu + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Wszystkie pliki(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + W tym wykresie wystÄ™pujÄ… krzywe, a wybrany wyglÄ…d linii można zastosować tylko dla wykresów uszeregowanych po X. Uszereguj tabelÄ™ lub zapytaj po X, aby usunąć krzywe lub wybierz jeden z wyglÄ…dów obsÅ‚ugiwanych przez krzywe: Brak lub Linia. + + + + Loading all remaining data for this table took %1ms. + Wczytywanie wszystkich pozostaÅ‚ych danych dla tej tabeli zajęło %1ms. + + + + PreferencesDialog + + + Preferences + Ustawienia + + + + &General + O&gólne + + + + Default &location + DomyÅ›&lne poÅ‚ożenie + + + + Remember last location + PamiÄ™taj ostatnie poÅ‚ożenie + + + + Always use this location + Zawsze używaj poniższego poÅ‚ożenia + + + + Remember last location for session only + Zapomnij ostatnie poÅ‚ożenie, dopiero po zamkniÄ™ciu programu + + + + + + ... + … + + + + Lan&guage + &JÄ™zyk + + + + Toolbar style + WyglÄ…d paska narzÄ™dzi + + + + + + + + Only display the icon + WyÅ›wietl tylko ikonÄ™ + + + + + + + + Only display the text + WyÅ›wietl tylko tekst + + + + + + + + The text appears beside the icon + Tekst obok ikony + + + + + + + + The text appears under the icon + Tekst pod ikonÄ… + + + + + + + + Follow the style + DomyÅ›lnie dla wyglÄ…du + + + + Show remote options + Pokaż ustawienia zdalnych BD + + + + + + + + + + + + + + enabled + włączone + + + + Automatic &updates + Sam &uaktualniaj + + + + DB file extensions + Rozszerzenia plików bazy danych + + + + Manage + ZarzÄ…dzaj + + + + Main Window + Główne okno + + + + Database Structure + UkÅ‚ad bazy danych + + + + Browse Data + PrzeglÄ…darka danych + + + + Execute SQL + Wykonaj polecenie SQL + + + + Edit Database Cell + Zmiana komórki bazy danych + + + + When this value is changed, all the other color preferences are also set to matching colors. + Po zmianie tej wartoÅ›ci, wszystkie inne ustawienia barw zostanÄ… także ustawione na +pasujÄ…ce barwy. + + + + Follow the desktop style + Zgodny z systemem + + + + Dark style + Ciemny + + + + Light style + Jasny + + + + Application style + WyglÄ…d programu + + + + This sets the font size for all UI elements which do not have their own font size option. + Ustawia to rozmiar czcionki dla wszystkich elementów interfejsu, które nie majÄ… swojego wÅ‚asnego ustawienia czcionki. + + + + Font size + Rozmiar czcionki + + + + Max Recent Files + Liczba ostatnich plików + + + + Prompt to save SQL tabs +in new project file + Zapytaj o zapisanie kart SQL +w pliku nowego projektu + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + Po włączeniu tego, zmiany w edytorze SQL wywoÅ‚ujÄ… okno, pytajÄ…ce o zapisanie projektu, przed zamkniÄ™ciem karty edytora SQL. + + + + &Database + Baza &danych + + + + Database &encoding + Kodowani&e bazy danych + + + + Open databases with foreign keys enabled. + Otwiera bazy danych z włączonymi kluczami obcymi. + + + + &Foreign keys + &Obce klucze + + + + Remove line breaks in schema &view + UsuÅ„ podziaÅ‚y wierszy w &widoku schematu + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + Po zaznaczeniu, usuwany jest znak Å‚amania wiersza w kolumnie schematu karty ukÅ‚adu bazy danych, doku oraz drukowanym wyniku. + + + + Formatted + Sformatowane + + + + Use tabs for indentation + Wcinaj tabulatorami + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + Po zaznaczeniu, klawisz Tab bÄ™dzie wstawiaÅ‚ znaki tabulatora oraz odstÄ™pu do wykonania wciÄ™cia. W przeciwnym przypadku bÄ™dÄ… używane tylko znaki odstÄ™pu. + + + + Select built-in extensions to load for every database: + + + + + Export Settings + Wyeksportuj ustawienia + + + + Import Settings + Zaimportuj ustawienia + + + + Prefetch block si&ze + Ro&zmiar obszaru wczytanego z wyprzedzeniem + + + + SQ&L to execute after opening database + SQ&L do wykonania po otworzeniu bazy danych + + + + Default field type + DomyÅ›lny rodzaj pola + + + + Data &Browser + &PrzeglÄ…darka danych + + + + Font + Czcionka + + + + &Font + &Czcionka + + + + Font si&ze + Ro&zmiar czcionki + + + + Content + Zawartość + + + + Symbol limit in cell + Graniczna liczba znaków w komórce + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + Jest to graniczna liczba elementów, która jest dozwolona dla niektórych obliczeniowo pracochÅ‚onnych dziaÅ‚aÅ„: +Graniczna liczba wierszy w tabeli do włączenia uzupeÅ‚niania wartoÅ›ci na podstawie bieżących wartoÅ›ci w kolumnie. +Graniczna liczba indeksów w zaznaczeniu do obliczenia sumy i Å›redniej. +Można ustawić na 0, aby wyłączyć wszystkie te dziaÅ‚ania. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + Jest to graniczna liczba wierszy w tabeli do włączenia uzupeÅ‚niania wartoÅ›ci na podstawie wartoÅ›ci znajdujÄ…cych siÄ™ już w kolumnie. +Można ustawić na 0, aby wyłączyć uzupeÅ‚nianie. + + + + Close button on tabs + Przycisk zamykania na kartach + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + Po włączeniu, karty edytora SQL bÄ™dÄ… zawierać przyciski zamykania. W pozostaÅ‚ych przypadkach, bÄ™dziesz musiaÅ‚ użyć menu podrÄ™cznego lub skrótu klawiszowego do ich zamykania. + + + + Proxy + PoÅ›rednik + + + + Configure + Ustawienia + + + + Field display + WyÅ›wietlanie pola + + + + Displayed &text + WyÅ›wietlany &tekst + + + + Binary + Dane dwójkowe + + + + NULL + WartoÅ›ci NULL + + + + Regular + ZwykÅ‚e dane + + + + + + + + + + + Click to set this color + NaciÅ›nij, aby ustawić tÄ™ barwÄ™ + + + + Text color + Barwa tekstu + + + + Background color + Barwa tÅ‚a + + + + + Preview only (N/A) + Tylko do podglÄ…du (ND) + + + + Filters + Filtry + + + + Escape character + Znak sterujÄ…cy + + + + Delay time (&ms) + Czas opóźnienia (&ms) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + Ustaw czas oczekiwania przed zastosowaniem nowej wartoÅ›ci filtra. Może być ustawiony na 0, aby wyłączyć oczekiwanie. + + + + &SQL + &SQL + + + + Context + WystÄ™powanie + + + + Colour + Barwa + + + + Bold + Pogrubienie + + + + Italic + Pochylenie + + + + Underline + PodkreÅ›lenie + + + + Keyword + SÅ‚owo kluczowe + + + + Function + Funkcja + + + + Table + Tabela + + + + Comment + Uwaga + + + + Identifier + Identyfikator + + + + String + CiÄ…g znaków + + + + Current line + Bieżący wiersz + + + + Background + TÅ‚o + + + + Foreground + Pierwszy plan + + + + Selection background + Drugi plan zaznaczenia + + + + Selection foreground + Pierwszy plan zaznaczenia + + + + Highlight + PodÅ›wietlenie + + + + SQL &editor font size + Rozmiar czcionki &edytora SQL + + + + SQL &results font size + &Rozmiar czcionki wyników SQL + + + + Tab size + Rozmiar tabulatora + + + + SQL editor &font + &Czcionka edytora SQL + + + + Database structure font size + Rozmiar czcionki ukÅ‚adu bazy danych + + + + Threshold for completion and calculation on selection + UzupeÅ‚niaj i obliczaj do tej liczby wierszy + + + + Show images in cell + Pokaż obrazy w komórce + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + Włącz to, aby pokazać podglÄ…d obiektów BLOB zawierajÄ…cych dane obrazów w komórkach. Może to jednak wpÅ‚ynąć na wydajność przeglÄ…darki danych. + + + + &Wrap lines + Za&wijaj wiersze + + + + &Quotes for identifiers + &CudzysÅ‚owy dla identyfikatorów + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + Wybierz zapis cudzysÅ‚owów stosowany w aplikacji do identyfikatorów w kodzie SQL. + + + + "Double quotes" - Standard SQL (recommended) + "Podwójne cudzysÅ‚owy" - Standard SQL (zalecane) + + + + `Grave accents` - Traditional MySQL quotes + `Pojedyncze cudzysÅ‚owy` - Tradycyjne cudzysÅ‚owy MySQL + + + + [Square brackets] - Traditional MS SQL Server quotes + [Nawiasy kwadratowe] - Tradycyjne cudzysÅ‚owy MS SQL Server + + + + Code co&mpletion + UzupeÅ‚nianie &kodu + + + + Keywords in &UPPER CASE + SÅ‚owa kl&uczowe WIELKIMI LITERAMI + + + + When set, the SQL keywords are completed in UPPER CASE letters. + Po zaznaczeniu, polecenia SQL sÄ… uzupeÅ‚niane wielkimi literami. + + + + Error indicators + Wskaźniki błędów + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + Po zaznaczeniu, wiersze kodu SQL, które powodowaÅ‚y błędy podczas ostatniego wykonywania, sÄ… podÅ›wietlana, a okno wyniku pokazuje błąd w tle + + + + Hori&zontal tiling + Kafelki w po&ziomie + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + Po zaznaczeniu, edytor kodu SQL oraz widok tabeli wynikowej bÄ™dÄ… wyÅ›wietlane obok siebie zamiast jedno nad drugim. + + + + Never + Nigdy + + + + At word boundaries + Na granicach słów + + + + At character boundaries + Na granicach znaków + + + + At whitespace boundaries + Na granicach biaÅ‚ych znaków + + + + &Extensions + Rozsz&erzenia + + + + Select extensions to load for every database: + Wybierz rozszerzenia wczytywane dla każdej bazy danych: + + + + Add extension + Dodaj rozszerzenie + + + + Remove extension + UsuÅ„ rozszerzenie + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>Mimo obsÅ‚ugi polecenia REGEXP, SQLite nie implementuje żadnego z algorytmu wyrażeÅ„ regularnych<br/>lecz zwraca siÄ™ z powrotem do aplikacji, która je uruchomiÅ‚a. PrzeglÄ…darka SQLite implementuje ten<br/>algorytm, aby móc od razu korzystać z REGEXP. Jednakże, ze wzglÄ™du na to, że istnieje wiele możliwych<br/>implementacji wyrażeÅ„ regularnych, to można wyłączyć ten wbudowany<br/>i wczytać swój wÅ‚asny. Wymaga to jednak ponownego uruchomienia aplikacji.</p></body></html> + + + + Disable Regular Expression extension + Wyłącz rozszerzenie wyrażeÅ„ regularnych + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite dostarcza funkcjÄ™ SQL do wczytywania rozszerzeÅ„ z pliku biblioteki współdzielonej. Zaznacz to, aby używać funkcji <span style=" font-style:italic;">load_extension()</span> z kodu SQL.</p><p>Ze wzglÄ™du na bezpieczeÅ„stwo, wczytywanie rozszerzeÅ„ jest domyÅ›lnie wyłączone i musi zostać włączone przez to ustawienie. Zawsze można wczytywać rozszerzenia przez interfejs użytkownika, nawet gdy pole to jest odznaczone.</p></body></html> + + + + Allow loading extensions from SQL code + Zezwól na wczytywanie rozszerzeÅ„ z kodu SQL + + + + Remote + Zdalne BD + + + + CA certificates + Certyfikaty UC + + + + + Subject CN + NP podmiotu + + + + Common Name + Nazwa powszechna + + + + Subject O + O podmiotu + + + + Organization + Organizacja + + + + + Valid from + Ważny od + + + + + Valid to + Ważny do + + + + + Serial number + Numer seryjny + + + + Your certificates + Twoje certyfikaty + + + + File + Plik + + + + Subject Common Name + Nazwa powszechna podmiotu + + + + Issuer CN + NP wydawcy + + + + Issuer Common Name + Nazwa powszechna wydawcy + + + + Clone databases into + Pobieraj bazy danych do + + + + + Choose a directory + Wybierz katalog + + + + + The language will change after you restart the application. + JÄ™zyk zmieni siÄ™ po ponownym uruchomieniu aplikacji. + + + + Select extension file + Wybierz plik rozszerzenia + + + + Extensions(*.so *.dylib *.dll);;All files(*) + Rozszerzenia(*.so *.dylib *.dll);;Wszystkie pliki(*) + + + + Import certificate file + Zaimportuj plik certyfikatu + + + + No certificates found in this file. + Nie znaleziono certyfikatów w tym pliku. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + Czy na pewno usunąć ten certyfikat? Wszystkie dane certyfikatu zostanÄ… usuniÄ™te z ustawieÅ„ aplikacji! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + Czy na pewno wyczyÅ›cić wszystkie zapisane ustawienia? +Wszystkie zapisane ustawienia zostanÄ… utracone i zastÄ…pione domyÅ›lnymi. + + + + Save Settings File + Zapisz plik ustawieÅ„ + + + + + Initialization File (*.ini) + Plik przygotowujÄ…cy (*.ini) + + + + The settings file has been saved in location : + + Zapisano plik ustawieÅ„ w miejscu : + + + + + Open Settings File + Otwórz plik ustawieÅ„ + + + + The settings file was loaded properly. + PomyÅ›lnie wczytano plik ustawieÅ„. + + + + The selected settings file is not a normal settings file. +Please check again. + Wybrany plik ustawieÅ„ nie jest zwykÅ‚ym plikiem ustawieÅ„. +Sprawdź go ponownie. + + + + ProxyDialog + + + Proxy Configuration + Ustawienia proxy + + + + Pro&xy Type + &Rodzaj poÅ›rednika + + + + Host Na&me + Nazwa &gospodarza + + + + Port + Port + + + + Authentication Re&quired + &Wymagane uwierzytelnienie + + + + &User Name + Nazwa &użytkownika + + + + Password + HasÅ‚o + + + + None + Brak + + + + System settings + Ustawienia systemowe + + + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 + + + + QObject + + + All files (*) + Wszystkie pliki (*) + + + + Error importing data + Błąd importowania danych + + + + from record number %1 + z rekordu o numerze %1 + + + + . +%1 + . +%1 + + + + Importing CSV file... + Importowanie pliku CSV… + + + + Cancel + Zaniechaj + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + Pliki bazy danych SQLite (*.db *.sqlite *.sqlite3 *.db3) + + + + Left + Do lewej + + + + Right + Do prawej + + + + Center + Do Å›rodka + + + + Justify + Wyjustuj + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + Pliki bazy danych SQLite (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + PrzeglÄ…darka BD dla plików projektu SQLite (*.sqbpro) + + + + SQL Files (*.sql) + Pliki SQL (*.sql) + + + + All Files (*) + Wszystkie pliki (*) + + + + Text Files (*.txt) + Pliki tekstowe (*.txt) + + + + Comma-Separated Values Files (*.csv) + Pliki z wartoÅ›ciami oddzielonymi przecinkiem (*.csv) + + + + Tab-Separated Values Files (*.tsv) + Pliki z wartoÅ›ciami oddzielonymi tabulatorem (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + Pliki z wartoÅ›ciami oddzielonymi rozdzielaczem (*.dsv) + + + + Concordance DAT files (*.dat) + Pliki Concordance DAT (*.dat) + + + + JSON Files (*.json *.js) + Pliki JSON (*.json *.js) + + + + XML Files (*.xml) + Pliki XML (*.xml) + + + + Binary Files (*.bin *.dat) + Pliki dwójkowe (*.bin *.dat) + + + + SVG Files (*.svg) + Pliki SVG (*.svg) + + + + Hex Dump Files (*.dat *.bin) + Pliki zrzutu szesnastkowego (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + Rozszerzenia (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + Plik przygotowujÄ…cy (*.ini) + + + + QsciCommand + + Paste + Wklej + + + Cancel + Zaniechaj + + + + QsciLexerCPP + + Keyword + SÅ‚owo kluczowe + + + Identifier + Identyfikator + + + + QsciLexerJSON + + String + CiÄ…g znaków + + + + QsciLexerJavaScript + + Regular expression + Wyrażenie regularne + + + + QsciLexerPython + + Comment + Uwaga + + + Keyword + SÅ‚owo kluczowe + + + Identifier + Identyfikator + + + + QsciLexerSQL + + Comment + Uwaga + + + Keyword + SÅ‚owo kluczowe + + + Identifier + Identyfikator + + + + QsciScintilla + + &Undo + &Cofnij + + + Select All + Zaznacz wszystkie + + + + RemoteCommitsModel + + + Commit ID + ID zmiany + + + + Message + Wiadomość + + + + Date + Data + + + + Author + Autor + + + + Size + Rozmiar + + + + Authored and committed by %1 + NapisaÅ‚ i wdrożyÅ‚ %1 + + + + Authored by %1, committed by %2 + NapisaÅ‚ %1, wdrożyÅ‚ %2 + + + + RemoteDatabase + + + Error opening local databases list. +%1 + Nie można otworzyć wykazu lokalnych baz danych. +%1 + + + + Error creating local databases list. +%1 + Nie można utworzyć wykazu lokalnych baz danych. +%1 + + + + RemoteDock + + + Remote + Zdalne BD + + + + Identity + Tożsamość + + + + Push currently opened database to server + Wypchnij bieżącÄ… bazÄ™ danych na serwer + + + + Upload + WyÅ›lij + + + + DBHub.io + DBHub.io + + + + Local + Miejscowa + + + + Current Database + Bieżąca baza danych + + + + Clone + Powiel + + + + Branch + Gałąź + + + + Commits + Zmiany + + + + Commits for + Zmiany dla + + + + Delete Database + UsuÅ„ bazÄ™ danych + + + + Delete the local clone of this database + UsuÅ„ miejscowÄ… kopiÄ™ tej bazy danych + + + + Open in Web Browser + Otwórz w przeglÄ…darce sieciowej + + + + Open the web page for the current database in your browser + Otwórz stronÄ™ sieciowÄ… bieżącej bazy danych w swojej przeglÄ…darce + + + + Clone from Link + Powiel z odnoÅ›nika + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + Użyj tego, aby pobrać zdalnÄ… bazÄ™ danych do miejscowego edytowania przy użyciu adresu URL podanego na stronie sieciowej bazy danych. + + + + Refresh + OdÅ›wież + + + + Reload all data and update the views + Wczytaj ponownie wszystkie dane i uaktualnij widoki + + + + Clone Database + Powiel bazÄ™ danych + + + + Open Database + Otwórz bazÄ™ danych + + + + Open the local copy of this database + Otwórz miejscowÄ… kopiÄ™ bazy danych + + + + Check out Commit + Ustaw na zmianie + + + + Download and open this specific commit + Pobierz i otwórz danÄ… zmianÄ™ + + + + Check out Latest Commit + Sprawdź ostatnie zmiany + + + + Check out the latest commit of the current branch + Sprawdź ostatniÄ… zmianÄ™ w bieżącej gałęzi + + + + Save Revision to File + Zapisz wersjÄ™ do pliku + + + + Saves the selected revision of the database to another file + Zapisuje wybranÄ… wersjÄ™ bazy danych do innego pliku + + + + Upload Database + WyÅ›lij bazÄ™ danych + + + + Upload this database as a new commit + WyÅ›lij tÄ™ bazÄ™ danych jako nowÄ… zmianÄ™ + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>Obecnie używasz wbudowanej tożsamoÅ›ci, która jest tylko do odczytu. Aby wysÅ‚ać bazÄ™ danych musisz posÅ‚użyć siÄ™ kontem z DBHub.io.</p><p>Nie masz jeszcze konta DBHub.io? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Utwórz je teraz</span></a> i zaimportuj swój certyfikat<a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">tutaj</span></a>, aby móc dzielić siÄ™ swoimi bazami danych.</p><p>Aby uzyskać pomoc w sieci, zajrzyj <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">tutaj</span></a>.</p></body></html> + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>W tym panelu można dodać zdalne bazy danych ze strony sieciowej dbhub.io do PrzeglÄ…darki Baz Danych SQLite. Jednak najpierw potrzebujesz swojej tożsamoÅ›ci:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Wejdź na stronÄ™ sieciowÄ… dbhub.io (użyj swoich danych dostÄ™powych z GitHuba lub dowolnych innych)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NaciÅ›nij przycisk &quot;Utwórz certyfikat klienta&quot; (oto i ta tożsamość, której potrzebujesz). Dostaniesz plik certyfikatu (zapisz go na swój dysk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Przejdź do karty Zdalnych w PrzeglÄ…darce Baz Danych SQLite i wskaż co dopiero pobrany plik certyfikatu.</li></ol><p>Od teraz panel Zdalnych bÄ™dzie pokazywaÅ‚ twojÄ… tożsamość, a ty bÄ™dziesz mógÅ‚ dodawać zdalne bazy danych.</p></body></html> + + + + &User + &Użytkownik + + + + &Database + Baza &danych + + + + Back + Wstecz + + + + Select an identity to connect + Wybierz tożsamość do połączenia siÄ™ + + + + Public + Publiczna + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + Pobiera to bazÄ™ danych ze zdalnego serwera do edytowania miejscowo. +Wpisz adres URL, z którego jÄ… powielić. Możesz utworzyć taki adres URL, +naciskajÄ…c na przycisk 'Powiel bazÄ™ danych w DB4S' na stronie sieciowej
 bazy danych. + + + + Invalid URL: The host name does not match the host name of the current identity. + NieprawidÅ‚owy adres URL: Nazwa gospodarza nie odpowiada nazwie gospodarza bieżącej tożsamoÅ›ci. + + + + Invalid URL: No branch name specified. + NieprawidÅ‚owy adres URL: Nie podano nazwy gałęzi. + + + + Invalid URL: No commit ID specified. + NieprawidÅ‚owy adres URL: Nie podano ID zmiany. + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + ZmieniÅ‚eÅ› miejscowÄ… bazÄ™ danych. Pobranie tych zmian zastÄ…pi zmiany miejscowe. Czy na pewno chcesz kontynuować? + + + + The database has unsaved changes. Are you sure you want to push it before saving? + Baza danych posiada niezapisane zmiany. Czy na pewno chcesz wypchnąć przed zapisaniem? + + + + The database you are trying to delete is currently opened. Please close it before deleting. + Baza danych, którÄ… próbujesz usunąć, jest obecnie otwarta. Zamknij jÄ… przed jej usuniÄ™ciem. + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + Usuwa to miejscowÄ… wersjÄ™ tej bazy danych wraz ze wszystkimi zmianami, których jeszcze nie wysÅ‚aÅ‚eÅ›. Czy na pewno usunąć tÄ™ bazÄ™ danych? + + + + RemoteLocalFilesModel + + + Name + Nazwa + + + + Branch + Gałąź + + + + Last modified + Ostatnio zmieniana + + + + Size + Rozmiar + + + + Commit + Zmiana + + + + File + Plik + + + + RemoteModel + + + Name + Nazwa + + + + Commit + Wdroż + + + + Last modified + Ostatnia zmiana + + + + Size + Rozmiar + + + + Size: + Rozmiar: + + + + Last Modified: + Ostatnio zmieniania: + + + + Licence: + Licencja: + + + + Default Branch: + DomyÅ›lna gałąź: + + + + RemoteNetwork + + + Choose a location to save the file + Wskaż miejsce do zapisania pliku + + + + Error opening remote file at %1. +%2 + Nie udaÅ‚o siÄ™ otworzyć pliku zdalnego w %1. +%2 + + + + Error: Invalid client certificate specified. + Błąd: Podano nieprawidÅ‚owy certyfikat klienta. + + + + Please enter the passphrase for this client certificate in order to authenticate. + Wpisz hasÅ‚o dla certyfikatu tego klienta, aby siÄ™ uwierzytelnić. + + + + Cancel + Zaniechaj + + + + Uploading remote database to +%1 + WysyÅ‚anie zdalnej bazy danych do +%1 + + + + Downloading remote database from +%1 + Pobieranie zdalnej bazy danych z +%1 + + + + Error: Cannot open the file for sending. + Błąd: Nie można otworzyć pliku do wysÅ‚ania. + + + + RemotePushDialog + + + Push database + Wypchnij bazÄ™ danych + + + + Database na&me to push to + &Nazwa bazy danych, do której wypchnąć + + + + Commit message + Opis wdrożenia + + + + Database licence + Licencja bazy danych + + + + Public + Publiczna + + + + Branch + Gałąź + + + + Force push + WymuÅ› wypchniÄ™cie + + + + Username + Nazwa użytkownika + + + + Database will be public. Everyone has read access to it. + Baza danych bÄ™dzie publiczna. Każdy bÄ™dzie mógÅ‚ uzyskać do niej dostÄ™p. + + + + Database will be private. Only you have access to it. + Baza danych bÄ™dzie prywatna. Tylko Ty bÄ™dziesz mieć do niej dostÄ™p. + + + + Use with care. This can cause remote commits to be deleted. + BÄ…dź ostrożny. Może to usunąć wdrożenia ze zdalnych miejsc. + + + + RunSql + + + Execution aborted by user + Wykonywanie przerwane przez użytkownika + + + + , %1 rows affected + , dotyczyÅ‚o %1 wiersza + + + + query executed successfully. Took %1ms%2 + pomyÅ›lnie wykonano zapytanie. Zajęło to %1ms%2 + + + + executing query + wykonywanie zapytania + + + + SelectItemsPopup + + + A&vailable + &DostÄ™pne + + + + Sele&cted + &Wybrane + + + + SqlExecutionArea + + + Form + Formularz + + + + Find previous match [Shift+F3] + Znajdź poprzednie trafienie [Shift+F3] + + + + Find previous match with wrapping + Znajdź poprzednie pasujÄ…ce z zawijaniem + + + + Shift+F3 + Shift+F3 + + + + The found pattern must be a whole word + Wzorzec do znalezienia musi być caÅ‚ym sÅ‚owem + + + + Whole Words + CaÅ‚e sÅ‚owa + + + + Text pattern to find considering the checks in this frame + Wzorzec tekstu do znalezienia, biorÄ…c pod uwagÄ™ pola zaznaczone w tym oknie + + + + Find in editor + Znajdź w edytorze + + + + The found pattern must match in letter case + Wzorzec do znalezienia musi pasować wielkoÅ›ciÄ… liter + + + + Case Sensitive + Rozróżniaj wielkość znaków + + + + Find next match [Enter, F3] + Znajdź nastÄ™pne trafienie [Enter, F3] + + + + Find next match with wrapping + Znajdź nastÄ™pne pasujÄ…ce z zawijaniem + + + + F3 + F3 + + + + Interpret search pattern as a regular expression + Rozpatrz wzorzec wyszukiwania jako wyrażenie regularne + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Po zaznaczeniu, wzorzec do znalezienia jest rozważany jako wyrażenie regularne UNIX. Zajrzyj do <a href="https://en.wikibooks.org/wiki/Regular_Expressions">WyrażeÅ„ Regularnych w Wikibooks</a>.</p></body></html> + + + + Regular Expression + Wyrażenie regularne + + + + + Close Find Bar + Zamknij pasek wyszukiwania + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>Wynik ostatnio wykonanych poleceÅ„.</p><p>Zalecamy zwiniÄ™cie tego okna i otworzenie doku <span style=" font-style:italic;">Dziennika SQL</span> z wyborem <span style=" font-style:italic;">Użytkownika</span>.</p></body></html> + + + + Results of the last executed statements + Wyniki ostatnio wykonanych poleceÅ„ + + + + This field shows the results and status codes of the last executed statements. + To pole pokazuje wyniki i kody wyjÅ›cia ostatnio wykonanych poleceÅ„. + + + + Ctrl+PgUp + Ctrl+PgUp + + + + Ctrl+PgDown + Ctrl+PgDown + + + + Couldn't read file "%1": %2. + Nie można odczytać pliku "%1": %2. + + + + + Couldn't save file: %1. + Nie można zapisać pliku: %1. + + + + Your changes will be lost when reloading it! + Utracisz swoje zmiany po ponownym wczytaniu! + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + Inny program zmieniÅ‚ plik "%1". Czy chcesz wczytać go ponownie?%2 + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + Odpowiedz "Tak na wszystko", aby bez dalszych pytaÅ„, wczytywać ponownie plik w przypadku dowolnego jego uaktualnienia z zewnÄ…trz. + + + + Answer "No to All" to ignore any external update without further prompting. + Odpowiedz "Nie dla wszystkich", aby pominąć wszelkie zewnÄ™trzne uaktualnienia bez dalszego pytania o nie. + + + + Modifying and saving the file will restore prompting. + Zmiana i zapisanie pliku przywróci pytania. + + + + SqlTextEdit + + + Ctrl+/ + Ctrl+/ + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) Funkcja abs(X) zwraca wartość bezwzglÄ™dnÄ… argumentu liczbowego X. + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () Funkcja changes() zwraca liczbÄ™ wierszy bazy danych, które zostaÅ‚y wstawiony lub usuniÄ™te przez ostatnio ukoÅ„czone polecenie INSERT, DELETE, or UPDATE. + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) Funkcja char(X1,X2,...,XN) zwraca ciÄ…g znaków skÅ‚adajÄ…cy siÄ™ ze znaków majÄ…cych wartoÅ›ci punków kodu unikod bÄ™dÄ…cych liczbami caÅ‚kowitymi w zakresie od X1 do XN, odpowiednio. + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) Funkcja coalesce() zwraca kopiÄ™ swojego pierwszego argumentu nie-NULL lub NULL, jeÅ›li wszystkie argumenty sÄ… NULL + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) Funkcja glob(X,Y) jest tożsama wyrażeniu "Y GLOB X". + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) Funkcja ifnull() zwraca kopiÄ™ swojego pierwszego argumentu nie-NULL lub NULL, jeÅ›li oba argumenty sÄ… NULL. + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) Funkcja instr(X,Y) znajduje pierwsze wystÄ…pienie ciÄ…gu znaków Y wewnÄ…trz ciÄ…gu znaków X i zwraca liczbÄ™ znaków poprzedzajÄ…cych plus 1, lub 0, jeÅ›li nie można znaleźć Y w X. + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) Funkcja hex() interpretuje swoje argumenty jako KAWAÅKI i zwraca ciÄ…gi znaków, które sÄ… przedstawieniem szesnastkowym treÅ›ci kawaÅ‚ka, zapisanym wielkimi literami. + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) Funkcja iif(X,Y,Z) zwraca wartość Y jeÅ›li X jest prawdÄ… lub Z w przeciwnym przypadku. + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () Funkcja last_insert_rowid() zwraca ROWID ostatniego wstawionego wiersza z połączenia bazy danych, która wywoÅ‚aÅ‚a tÄ™ funkcjÄ™. + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) Dla wartoÅ›ci ciÄ…gu znaków X, funkcja length(X) zwraca liczbÄ™ znaków (nie bajtów) w X do chwili napotkania pierwszego znaku NUL. + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) Funkcja like() jest używana do implementacji wyrażenia "Y LIKE X". + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) Funkcja like() jest używana do implementacji wyrażenia "Y LIKE X ESCAPE Z". + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) Funkcja load_extension(X) wczytuje rozszerzenia SQLite z pliku biblioteki współdzielonej o nazwie X. +Aby użyć tej funkcji, należy wyrazić zgodÄ™ w Ustawieniach. + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) Funkcja load_extension(X) wczytuje rozszerzenia SQLite z pliku biblioteki współdzielonej o nazwie X przy użyciu punktu wejÅ›ciowego Y. +Aby użyć tej funkcji, należy wyrazić zgodÄ™ w Ustawieniach. + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) Funkcja lower(X) zwraca kopiÄ™ ciÄ…gu znaków X po przeksztaÅ‚ceniu wszystkich znaków ASCII na pisane maÅ‚ymi literami. + + + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) usuwa odstÄ™py z lewej strony X. + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) Funkcja ltrim(X,Y) zwraca ciÄ…g znaków utworzony po usuniÄ™ciu dowolnego i wszystkich znaków, które ukazujÄ… siÄ™ w Y z lewej strony X. + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) Funkcja wieloargumentowa max() zwraca argument o wartoÅ›ci najwiÄ™kszej lub NULL, jeÅ›li dowolny argument jest NULL. + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) Funkcja wieloargumentowa min() zwraca argument o wartoÅ›ci najmniejszej. + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) Funkcja nullif(X,Y) zwraca swój pierwszy argument, jeÅ›li argumenty sÄ… różne i NULL, jeÅ›li argumenty sÄ… te same. + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) Funkcja SQL printf(FORMAT,...) dziaÅ‚a jak funkcja sqlite3_mprintf() jÄ™zyka C oraz printf() ze standardowej biblioteki C. + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) Funkcja quote(X) zwraca dosÅ‚owny tekst SQL, który jest wartoÅ›ciÄ… jego argumentów +gotowÄ… do wstawienia w polecenie SQL. + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () Funkcja random() zwraca pseudo-losowÄ… liczbÄ™ caÅ‚kowitÄ… z zakresu od -9223372036854775808 do +9223372036854775807. + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) Funkcja randomblob(N) zwraca N-bajtowy kawaÅ‚ek zawierajÄ…cy pseudo-losowe bajty. + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) Funkcja replace(X,Y,Z) zwraca ciÄ…g znaków utworzony poprzez podmianÄ™ ciÄ…gu znaków Z dla każdego wystÄ…pienia ciÄ…gu znaków Y w ciÄ…gu znaków X. + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) Funkcja round(X) zwraca wartość liczby zmiennoprzecinkowej X zaokrÄ…glonej do części caÅ‚kowitej. + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) Funkcja round(X,Y) zwraca wartość liczby zmiennoprzecinkowej X zaokrÄ…glonej do liczby znaków dziesiÄ™tnych okreÅ›lonych przez Y. + + + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X) usuwa odstÄ™py z prawej strony X. + + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) Funkcja rtrim(X,Y) zwraca ciÄ…g znaków utworzony po usuniÄ™ciu dowolnego i wszystkich znaków, które ukazujÄ… siÄ™ w Y z prawej strony X. + + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) Funkcja soundex(X) zwraca ciÄ…g znaków X zakodowany jako soundex. + + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) substr(X,Y) zwraca wszystkie znaki do koÅ„ca ciÄ…gu znaków X zaczynajÄ…c od Y-tego. + + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) Funkcja substr(X,Y,Z) zwraca podciÄ…g znaków ciÄ…gu wejÅ›ciowego znaków X, który zaczyna siÄ™ na Y-tym znaku i który jest dÅ‚ugi na Z znaków. + + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () Funkcja total_changes() zwraca liczbÄ™ zmienionych wierszy przez polecenia INSERT, UPDATE lub DELETE od chwili nawiÄ…zania połączenia z bazÄ… danych. + + + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) usuwa odstÄ™py z obu stron X. + + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) Funkcja trim(X,Y) zwraca ciÄ…g znaków utworzony po usuniÄ™ciu dowolnego i wszystkich znaków, które ukazujÄ… siÄ™ w Y z obu stron X. + + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) Funkcja typeof(X) zwraca ciÄ…g znaków, który wskazuje na rodzaj danych wyrażenia X. + + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) Funkcja unicode(X) zwraca punkt numerycznego kodu unikodu odpowiadajÄ…cy pierwszemu znakowi ciÄ…gu X. + + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) Funkcja upper(X) zwraca kopiÄ™ ciÄ…gu znaków X po przeksztaÅ‚ceniu wszystkich znaków ASCII na pisane wielkimi literami. + + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) Funkcja zeroblob(N) zwraca KAWAÅEK skÅ‚adajÄ…cy siÄ™ z N bajtów 0x00. + + + + + + + (timestring,modifier,modifier,...) + (ciÄ…g_znaków_czasu,zmieniacz,zmieniacz,...) + + + + (format,timestring,modifier,modifier,...) + (format,ciÄ…g_znaków_czasu,zmieniacz,zmieniacz,...) + + + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) Funkcja avg() zwraca wartość Å›redniÄ… wszystkich nie-NULL X wewnÄ…trz grupy. + + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) Funkcja count(X) zwraca liczbÄ™ tego ile razy X nie jest NULL w grupie. + + + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) Funkcja group_concat() zwraca ciÄ…g znaków, który jest złączeniem wszystkich wartoÅ›ci nie-NULL X. + + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) Funkcja group_concat() zwraca ciÄ…g znaków bÄ™dÄ…cy złączeniem wszystkich wartoÅ›ci nie-NULL X. JeÅ›li obecne jest Y, to sÅ‚uży jako znak oddzielajÄ…cy wystÄ…pienia X. + + + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) Funkcja max() zwraca najwyższÄ… wartość z wartoÅ›ci w grupie. + + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) Funkcja min() zwraca najmniejszÄ… wartość nie-NULL z wartoÅ›ci w grupie. + + + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) Funkcje sum() oraz total() zwracajÄ… sumÄ™ wszystkich wartoÅ›ci nie-NULL w grupie. + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () Numer wiersza wewnÄ…trz bieżącej partycji. Partycje sÄ… ponumerowane od 1 w kolejnoÅ›ci okreÅ›lonej przez wyrażenie ORDER BY w okreÅ›leniu okna lub w dowolnej kolejnoÅ›ci. + + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () Numer wiersza row_number() pierwszego czÅ‚onka w każdej grupie - ranga bieżącego wiersza w rozstÄ™pach. JeÅ›li brak polecenia ORDER BY, to wszystkie wiersze sÄ… rozważane jako czÅ‚onkowie i funkcja zawsze zwraca 1. + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () Numer grupy bieżącego wiersza wewnÄ…trz jego partycji - ranga bieżącego wiersza bez przerw. Partycje sÄ… ponumerowane od 1 w kolejnoÅ›ci okreÅ›lonej przez wyrażenie ORDER BY w okreÅ›leniu okna. JeÅ›li brak wyrażenia ORDER BY, to wszystkie wiersze sÄ… rozważane jako leżące obok siebie, a funkcja ta zwraca 1. + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () Pomimo nazwy, funkcja ta zawsze zwraca wartość pomiÄ™dzy 0.0 oraz 1.0 równÄ… (rank - 1)/(wiersze-partycji - 1), gdzie rank jest wartoÅ›ciÄ… zwracanÄ… przez wbudowanÄ… funkcjÄ™ rank() okna, a wiersze-partycji jest caÅ‚kowitÄ… liczbÄ… wierszy w partycji. JeÅ›li partycja zawiera tylko jeden wiersz, to ta funkcja zwraca 0.0. + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () RozkÅ‚ad nagromadzony. Obliczany jako numer-wiersza/wiersze-partycji, gdzie +numer-wiersza jest wartoÅ›ciÄ… zwracanÄ… przez row_number() dla ostatniego +elementu w grupie, a wiersze-partycji to liczba wierszy w partycji. + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) Argument N jest rozważany jako liczba caÅ‚kowita. Ta funkcja dzieli partycjÄ™ na N grup tak równo jak to możliwe i przypisuje liczbÄ™ caÅ‚kowitÄ… z zakresu od 1 do N każdej grupie w kolejnoÅ›ci okreÅ›lonej przez polecenie ORDER BY lub dowolnej. JeÅ›li zajdzie taka potrzeba, to wiÄ™ksze grupy wystÄ…piÄ… jako pierwsze. Ta funkcja zwraca liczbÄ™ caÅ‚kowitÄ… przypisanÄ… do grupy, do której bieżący wiersz należy. + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) Zwraca wynik obliczania wyrażenia expr na poprzednim wierszu w partycji. Lub, jeÅ›li nie ma poprzedniego wiersza (bo bieżący wiersz jest pierwszym), NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr,przesuniÄ™cie) JeÅ›li podano argument przesuniÄ™cia, to musi on być nieujemnÄ… liczbÄ… caÅ‚kowitÄ…. W tym przypadku wartoÅ›ciÄ… zwracanÄ… jest wynik obliczenia wyrażenia na wierszu przesuniÄ™tym o danÄ… liczbÄ™ wierszy wstecz wzglÄ™dem bieżącego wiersza. JeÅ›li nie bÄ™dzie takiego wiersza, to zwracane jest NULL. + + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,przesuniÄ™cie,domyÅ›lne) JeÅ›li podano także domyÅ›lne, to jest to wartoÅ›ci zwracana zamiast NULL, jeÅ›li wiersz okreÅ›lony przez przesuniÄ™cie nie istnieje. + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) Zwraca wynik obliczania wyrażenia expr na nastÄ™pnym wierszu w partycji. Lub, jeÅ›li nie ma nastÄ™pnego wiersza (bo bieżący wiersz jest ostatnim), NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,przesuniÄ™cie) JeÅ›li podano argument przesuniÄ™cia, to musi on być nieujemnÄ… liczbÄ… caÅ‚kowitÄ…. W tym przypadku wartoÅ›ciÄ… zwracanÄ… jest wynik obliczenia wyrażenia na wierszu przesuniÄ™tym o danÄ… liczbÄ™ wierszy wprzód wzglÄ™dem bieżącego wiersza. JeÅ›li nie bÄ™dzie takiego wiersza, to zwracane jest NULL. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) Ta wbudowana funkcja okna oblicza ramÄ™ okna dla każdego wiersza w ten sam sposób jak funkcja okna zÅ‚ożonego. Zwraca wartość expr obliczonÄ… na pierwszym wierszu ramy okna dla każdego wiersza. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) Ta wbudowana funkcja okna oblicza ramÄ™ okna dla każdego wiersza w ten sam sposób jak funkcja okna zÅ‚ożonego. Zwraca wartość expr obliczonÄ… na ostatnim wierszu ramy okna dla każdego wiersza. + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr,N) Ta wbudowana funkcja okna oblicza ramÄ™ okna dla każdego wiersza w ten sam sposób jak funkcja okna zÅ‚ożonego. Zwraca wartość expr obliczonÄ… na N-tym wierszu ramy okna. Wiersze sÄ… numerowane wewnÄ…trz ramy okna poczynajÄ…c od 1 w kolejnoÅ›ci okreÅ›lonej przez polecenie ORDER BY jeÅ›li jest obecne lub w dowolnej kolejnoÅ›ci. JeÅ›li N-ty wiersz nie istnieje w partycji, to zwracane jest NULL. + + + + (X) Return the arccosine of X. The result is in radians. + (X) Zwróć arkus kosinus z X. Wynik bÄ™dzie w radianach. + + + + (X) Return the hyperbolic arccosine of X. + (X) Zwróć hiperboliczny arkus kosinus z X. + + + + (X) Return the arcsine of X. The result is in radians. + (X) Zwróć arkus sinus z X. Wynik bÄ™dzie w radianach. + + + + (X) Return the hyperbolic arcsine of X. + (X) Zwróć hiperboliczny arkus sinus z X. + + + + (X) Return the arctangent of X. The result is in radians. + (X) Zwróć arkus tangens z X. Wynik bÄ™dzie w radianach. + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + (X,Y) Zwróć arkus tangens z Y/X. Wynik bÄ™dzie w radianach. Wynik zostanie umieszony w odpowiednik kwadrancie w zależnoÅ›ci do znaków X oraz Y. + + + + (X) Return the hyperbolic arctangent of X. + (X) Zwróć hiperboliczny arkus tangens z X. + + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + (X) Zwróć pierwszÄ… przedstawialnÄ… liczbÄ™ caÅ‚kowitÄ… wiÄ™kszÄ… niż lub równÄ… X. Dla wartoÅ›ci dodatnich X, nastÄ™puje zaokrÄ…glanie w stronÄ™ od zera. Dla wartoÅ›ci X, nastÄ™puje zaokrÄ…glanie w stronÄ™ do zera. + + + + (X) Return the cosine of X. X is in radians. + (X) Zwróć kosinus z X, gdzie X jest w radianach. + + + + (X) Return the hyperbolic cosine of X. + (X) Zwróć hiperboliczny kosinus z X. + + + + (X) Convert value X from radians into degrees. + (X) Przekształć wartość X z radianów na stopnie. + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + (X) Oblicz e (Liczba Eulera, w przybliżeniu 2.71828182845905) podniesione do potÄ™gi X. + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + (X) Zwróć pierwszÄ… przedstawialnÄ… liczbÄ™ caÅ‚kowitÄ… mniejszÄ… niż lub równÄ… X. Dla wartoÅ›ci dodatnich X, nastÄ™puje zaokrÄ…glanie w stronÄ™ do zera. Dla wartoÅ›ci X, nastÄ™puje zaokrÄ…glanie w stronÄ™ od zera. + + + + (X) Return the natural logarithm of X. + (X) Zwróć logarytm naturalny z X. + + + + (B,X) Return the base-B logarithm of X. + (B, X) Zwróć logarytm o podstawie B z X. + + + + + (X) Return the base-10 logarithm for X. + (X) Zwróć logarytm o podstawie 10 z X. + + + + (X) Return the logarithm base-2 for the number X. + (X) Zwróć logarytm o podstawie 2 z liczby X. + + + + (X,Y) Return the remainder after dividing X by Y. + (X,Y) Zwróć resztÄ™ z dzielenia X przez Y. + + + + () Return an approximation for Ï€. + () Zwróć przybliżenie liczby Ï€. + + + + + (X,Y) Compute X raised to the power Y. + (X,Y) Oblicz X podniesione do potÄ™gi Y. + + + + (X) Convert X from degrees into radians. + (X) Przekształć wartość X ze stopni na radiany. + + + + (X) Return the sine of X. X is in radians. + (X) Zwróć sinus z X, gdzie X jest w radianach. + + + + (X) Return the hyperbolic sine of X. + (X) Zwróć hiperboliczny sinus z X. + + + + (X) Return the square root of X. NULL is returned if X is negative. + (X) Zwróć pierwiastek kwadratowy z X. Zwróci NULL, gdy X bÄ™dzie ujemne. + + + + (X) Return the tangent of X. X is in radians. + (X) Zwróć tangens z X, gdzie X jest w radianach. + + + + (X) Return the hyperbolic tangent of X. + (X) Zwróć hiperboliczny tangens z X. + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + (X) Zwróć pierwszÄ… przedstawialnÄ… liczbÄ™ caÅ‚kowitÄ… pomiÄ™dzy X, a 0 (włącznie), która jest najdalej o zera. Innymi sÅ‚owy, zwróć część caÅ‚kowitÄ… X, zaookrÄ…glajÄ…c jÄ… w stronÄ™ zera. + + + + SqliteTableModel + + + reading rows + czytanie wierszy + + + + loading... + wczytywanie... + + + + References %1(%2) +Hold %3Shift and click to jump there + OdwoÅ‚ania %1(%2) +PrzyciÅ›nij %3Shift i kliknij, aby tu przejść + + + + Error changing data: +%1 + WystÄ…piÅ‚ błąd podczas zmiany danych: +%1 + + + + retrieving list of columns + uzyskiwanie listy kolumn + + + + Fetching data... + Uzyskiwanie danych… + + + + + Cancel + Zaniechaj + + + + TableBrowser + + + Browse Data + PrzeglÄ…daj dane + + + + &Table: + &Tabela: + + + + Select a table to browse data + Wybierz tabelÄ™, aby przeglÄ…dać dane + + + + Use this list to select a table to be displayed in the database view + Użyj tej listy, aby zaznaczyć tabelÄ™ wyÅ›wietlanÄ… w widoku bazy danych + + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + Oto widok tabeli bazy danych. Możliwe sÄ… nastÄ™pujÄ…ce dziaÅ‚ania: + - Pisanie do przeedytowania wartoÅ›ci w-wierszu. + - Dwukrotne klikniÄ™cie na rekordzie, aby edytować jego zawartość w edytorze komórek. + - Alt+Del do usuniÄ™cia treÅ›ci komórki i ustawienia NULL. + - Ctrl+" do powielenia bieżącego rekordu. + - Ctrl+' do skopiowania wartoÅ›ci z komórki powyżej. + - Standardowe zaznaczanie/kopiowanie/wklejanie. + + + + Text pattern to find considering the checks in this frame + Wzorzec tekstu do znalezienia, biorÄ…c pod uwagÄ™ pola zaznaczone w tym oknie + + + + Find in table + Znajdź w tabeli + + + + Find previous match [Shift+F3] + Znajdź poprzednie pasujÄ…ce [Shift+F3] + + + + Find previous match with wrapping + Znajdź poprzednie pasujÄ…ce z mapowaniem + + + + Shift+F3 + Shift+F3 + + + + Find next match [Enter, F3] + Znajdź nastÄ™pne pasujÄ…ce [Enter, F3] + + + + Find next match with wrapping + Znajdź nastÄ™pne pasujÄ…ce z nawracaniem + + + + F3 + F3 + + + + The found pattern must match in letter case + Wzorzec do znalezienia musi pasować wielkoÅ›ciÄ… liter + + + + Case Sensitive + Rozróżniaj wielkość liter + + + + The found pattern must be a whole word + Wzorzec do znalezienia musi być caÅ‚ym sÅ‚owem + + + + Whole Cell + CaÅ‚a komórka + + + + Interpret search pattern as a regular expression + Rozpatrz wzorzec wyszukiwania jako wyrażenie regularne + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Po zaznaczeniu, wzorzec do znalezienia jest rozważany jako wyrażenie regularne UNIX. Zajrzyj do <a href="https://en.wikibooks.org/wiki/Regular_Expressions">WyrażeÅ„ Regularnych w Wikibooks</a>.</p></body></html> + + + + Regular Expression + Wyrażenie regularne + + + + + Close Find Bar + Zamknij pasek wyszukiwania + + + + Text to replace with + Tekst do zastÄ…pienia + + + + Replace with + ZastÄ…p + + + + Replace next match + ZastÄ…p nastÄ™pne pasujÄ…ce wyrażenie + + + + + Replace + ZastÄ…p + + + + Replace all matches + ZastÄ…p wszystkie pasujÄ…ce wyrażenia + + + + Replace all + ZastÄ…p wszystkie + + + + Export to &JSON + Wyeksportuj do &JSON + + + + + Export the filtered data to JSON + Wyeksportuj przefiltrowane dane do JSON + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + Ten przycisk wyeksportuje dane bieżącej tabeli tak jak sÄ… obecnie wyÅ›wietlane (po filtrach, z formatami wyÅ›wietlania i kolejnoÅ›ciÄ… kolumn) jako plik JSON. + + + + Copy column name + Skopiuj nazwÄ™ kolumny + + + + Copy the database table column name to your clipboard + Skopiuj nazwÄ™ kolumny tabeli do swojego schowka + + + + New Data Browser + Nowa przeglÄ…darka danych + + + + + Add a new docked Data Browser + Dodaj nowÄ… zadokowanÄ… przeglÄ…darkÄ™ danych + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + Ten przycisk dodaje nowÄ… zadokowanÄ… PrzeglÄ…darkÄ™ Danych, którÄ… możesz odczepić i wstawić w różne ukÅ‚ady. + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>PrzewiÅ„ do poczÄ…tku</p></body></html> + + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>NaciÅ›niÄ™cie tego przycisku kieruje na poczÄ…tek powyższego widoku tabeli.</p></body></html> + + + + |< + |< + + + + Scroll one page upwards + PrzewiÅ„ jednÄ… stronÄ™ w górÄ™ + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>NaciÅ›niÄ™cie tego przycisku przenosi o jednÄ… stronÄ™ wyżej w powyższym widoku tabeli.</p></body></html> + + + + < + < + + + + 0 - 0 of 0 + 0 - 0 z 0 + + + + Scroll one page downwards + PrzewiÅ„ jednÄ… stronÄ™ w dół + + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>NaciÅ›niÄ™cie tego przycisku przenosi o jednÄ… stronÄ™ niżej w powyższym widoku tabeli.</p></body></html> + + + + > + > + + + + Scroll to the end + PrzewiÅ„ na koniec + + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>NaciÅ›niÄ™cie tego przycisku przenosi na koniec powyższego widoku tabeli.</p></body></html> + + + + >| + >| + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>NaciÅ›nij tutaj, aby przejść do danego rekordu</p></body></html> + + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>Ten przycisk sÅ‚uży to przejÅ›cia do rekordu o numerze podanym w obszarze PrzejÅ›cia.</p></body></html> + + + + Go to: + Przejdź do: + + + + Enter record number to browse + Wprowadź numer rekordu do przejrzenia + + + + Type a record number in this area and click the Go to: button to display the record in the database view + Wpisz numer rekordu w tym obszarze i naciÅ›nij na Przejdź Do, aby wyÅ›wietlić rekord w widoku bazy danych + + + + 1 + 1 + + + + Show rowid column + Pokaż kolumnÄ™ ID wiersza + + + + Toggle the visibility of the rowid column + Pokaż/Ukryj kolumnÄ™ ID wiersza + + + + Unlock view editing + Odblokuj zmianÄ™ widoku + + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + To umożliwia wprowadzanie zmian w bieżącym widoku. Jednakże potrzebne bÄ™dÄ… odpowiednie wyzwalacze do zmiany. + + + + Edit display format + ZmieÅ„ format wyÅ›wietlania + + + + Edit the display format of the data in this column + ZmieÅ„ sposób wyÅ›wietlania danych w tej kolumnie + + + + + New Record + Nowy rekord + + + + + Insert a new record in the current table + Wstaw nowy rekord bieżącej tabeli + + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>Ten przycisk tworzy nowy rekord w bazie danych. PrzyciÅ›nij przycisk myszy, aby otworzyć menu podrÄ™czne z różnymi ustawieniami:</p><ul><li><span style=" font-weight:600;">Nowy rekord</span>: wstawia nowy rekord o domyÅ›lnych wartoÅ›ciach do bazy danych.</li><li><span style=" font-weight:600;">Wstaw wartoÅ›ci...</span>: otwiera okno dialogowe do wpisywania wartoÅ›ci przed ich wstawieniem do bazy danych. Umożliwia to wpisanie wartoÅ›ci przy zachowaniu różnych ograniczeÅ„. To okno dialogowe jest także otwarte, gdy nie powiedzie siÄ™ wykonanie polecenia <span style=" font-weight:600;">Nowy rekord</span> ze wzglÄ™du na te ograniczenia .</li></ul></body></html> + + + + + Delete Record + UsuÅ„ rekord + + + + Delete the current record + UsuÅ„ bieżący rekord + + + + + This button deletes the record or records currently selected in the table + Ten przycisk usuwa obecnie zaznaczony rekord lub rekordy z tabeli + + + + + Insert new record using default values in browsed table + Wstaw nowy rekord przy użyciu domyÅ›lnych wartoÅ›ci bieżącej tabeli + + + + Insert Values... + Wstaw wartoÅ›ci... + + + + + Open a dialog for inserting values in a new record + Otwiera okno dialogowe do wstawiania wartoÅ›ci do nowego rekordu + + + + Export to &CSV + Wyeksportuj do &CSV + + + + + Export the filtered data to CSV + Wyeksportuj przefiltrowane dane do CSV + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + Ten przycisk wyeksportuje dane bieżącej tabeli tak jak sÄ… obecnie wyÅ›wietlane (po filtrach, z formatami wyÅ›wietlania i kolejnoÅ›ciÄ… kolumn) jako plik CSV. + + + + Save as &view + Zapisz jako &widok + + + + + Save the current filter, sort column and display formats as a view + Zapisuje bieżący filtr, kolumnÄ™ do szeregowania oraz formaty wyÅ›wietlania jako widok + + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + Ten przycisk zapisuje bieżące ustawienia oglÄ…danej tabeli (filtry, formaty wyÅ›wietlania i kolejność kolumn) jako widok SQL, który można później przeglÄ…dać lub wstawić do polecenia SQL. + + + + Save Table As... + Zapisz tabelÄ™ jako... + + + + + Save the table as currently displayed + Zapisz tabelÄ™ tak, jak jest obecnie wyÅ›wietlana + + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>To menu podrÄ™czne zawiera nastÄ™pujÄ…ce ustawienie stosujÄ…ce siÄ™ do obecnie oglÄ…danej i filtrowanej tabeli:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Eksportuj do CSV: eksportuje dane oglÄ…danej tabeli tak jak jest obecnie wyÅ›wietlana (po filtrach, z formatami wyÅ›wietlania i kolejnoÅ›ciÄ… kolumn) do pliku CSV.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Zapisz jako widok: zapisuje bieżące ustawienia oglÄ…danej tabeli (filtry, formaty wyÅ›wietlania i kolejność kolumn) jako widok SQL, który można później przeglÄ…dać lub wstawić do polecenia SQL.</li></ul></body></html> + + + + Hide column(s) + Ukryj kolumnÄ™/y + + + + Hide selected column(s) + Ukryj zaznaczonÄ…/e kolumnÄ™/y + + + + Show all columns + Pokaż wszystkie kolumny + + + + Show all columns that were hidden + Pokaż wszystkie ukryte kolumny + + + + + Set encoding + Ustaw kodowanie + + + + Change the encoding of the text in the table cells + ZmieÅ„ kodowanie tekstu w komórkach tabeli + + + + Set encoding for all tables + Ustaw kodowanie dla wszystkich tabel + + + + Change the default encoding assumed for all tables in the database + ZmieÅ„ domyÅ›lne kodowanie przyjÄ™te dla wszystkich table w bazie danych + + + + Clear Filters + Wyczyść filtry + + + + Clear all filters + Wyczyść wszystkie filtry + + + + + This button clears all the filters set in the header input fields for the currently browsed table. + Ten przycisk wyczyÅ›ci wszystkie filtry ustawione na polach wejÅ›ciowych nagłówka dla bieżącej tabeli. + + + + Clear Sorting + Wyczyść szeregowanie + + + + Reset the order of rows to the default + Przywróć porzÄ…dek wierszy do domyÅ›lnego + + + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + Ten przycisk czyÅ›ci kolumny szeregowania dla danej tabeli i powraca do domyÅ›lnego porzÄ…dku. + + + + Print + Wydrukuj + + + + Print currently browsed table data + WyÅ›wietl dane bieżącej tabeli + + + + Print currently browsed table data. Print selection if more than one cell is selected. + Wydrukuj dane bieżącej tabeli. Wydrukuj zaznaczenie, jeÅ›li zaznaczono wiÄ™cej niż jednÄ… komórkÄ™. + + + + Ctrl+P + Ctrl+P + + + + Refresh + OdÅ›wież + + + + Refresh the data in the selected table + OdÅ›wież dane w zaznaczonej tabeli + + + + This button refreshes the data in the currently selected table. + Ten przycisk odÅ›wieża dane w obecnie zaznaczonej tabeli. + + + + F5 + F5 + + + + Find in cells + Znajdź w komórkach + + + + Open the find tool bar which allows you to search for values in the table view below. + Otwórz pasek wyszukiwania, który umożliwi wyszukiwanie wartoÅ›ci w poniższym widoku tabeli. + + + + Freeze columns + Zamroź kolumny + + + + Make all columns from the first column up to this column not move when scrolling horizontally + Nie przesuwaj kolumn w poziomie od pierwszej kolumny do tej kolumny przy przewijaniu + + + + + Bold + Pogrubienie + + + + Ctrl+B + Ctrl+B + + + + + Italic + Kursywa + + + + + Underline + PodkreÅ›lenie + + + + Ctrl+U + Ctrl+U + + + + + Align Right + Wyrównaj do prawej + + + + + Align Left + Wyrównaj do lewej + + + + + Center Horizontally + WyÅ›rodkuj w poziomie + + + + + Justify + Justowanie + + + + + Edit Conditional Formats... + Edytuj formatowanie warunkowe... + + + + Edit conditional formats for the current column + ZmieÅ„ formatowania warunkowe dla bieżącej kolumny + + + + Clear Format + Wyczyść format + + + + Clear All Formats + Wyczyść wszystkie formatowania + + + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + Wyczyść wszystkie formatowania warunkowe dla zaznaczonej komórki i wszystkie formatowania warunkowe dla zaznaczonych kolumn + + + + + Font Color + Barwa czcionki + + + + + Background Color + Barwa tÅ‚a + + + + Toggle Format Toolbar + Pokaż pasek formatowania + + + + Show/hide format toolbar + Pokaż/ukryj pasek formatu + + + + + This button shows or hides the formatting toolbar of the Data Browser + Ten przycisk pokazuje lub ukrywa pasek formatowania dla przeglÄ…darki danych + + + + Select column + Zaznacz kolumnÄ™ + + + + Ctrl+Space + Ctrl+Space + + + + Replace text in cells + ZastÄ…p tekst w komórkach + + + + Filter in any column + Filtruj w dowolnej kolumnie + + + + Ctrl+R + Ctrl+R + + + + %n row(s) + + %n wiersz + %n wiersze + %n wierszy + + + + + , %n column(s) + + , %n kolumna + , %n kolumny + , %n kolumn + + + + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . Suma: %1; Åšrednia: %2; Min: %3; Maks: %4 + + + + Conditional formats for "%1" + Formatowania warunkowe dla "%1" + + + + determining row count... + okreÅ›lanie liczby wierszy… + + + + %L1 - %L2 of >= %L3 + %L1 - %L2 z >= %L3 + + + + %L1 - %L2 of %L3 + %L1 - %L2 z %L3 + + + + (clipped at %L1 rows) + (przyciÄ™ta na %L1 wirszach) + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + Podaj pseudo-główny klucz, aby rozpocząć edytowanie w tym widoku. Powinna to być nazwa niepowtarzalnej kolumny w widoku. + + + + Delete Records + UsuÅ„ rekordy + + + + Duplicate records + Powielone rekordy + + + + Duplicate record + Powiel rekord + + + + Ctrl+" + Ctrl+" + + + + Adjust rows to contents + Dostosuj wiersze do treÅ›ci + + + + Error deleting record: +%1 + Błąd usuwania rekordu: +%1 + + + + Please select a record first + Najpierw wybierz rekord + + + + Please choose a new encoding for all tables. + Wybierz nowe kodowanie dla wszystkich tabel. + + + + Please choose a new encoding for this table. + Wybierz kodowanie dla tej tabeli. + + + + %1 +Leave the field empty for using the database encoding. + %1 +Pozostaw pole pustym, aby użyć kodowania bazy danych. + + + + This encoding is either not valid or not supported. + To kodowanie jest nieprawidÅ‚owe lub nieobsÅ‚ugiwane. + + + + %1 replacement(s) made. + Wykonano %1 zastÄ…pieÅ„. + + + + TableBrowserDock + + + New Data Browser + Nowa przeglÄ…darka danych + + + + Rename Data Browser + Przemianuj przeglÄ…darkÄ™ danych + + + + Close Data Browser + Zamknij przeglÄ…darkÄ™ danych + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + Nadaj nowÄ… nazwÄ™ dla przeglÄ…darki danych. Użyj znaku '&&', aby móc użyć nastÄ™pujÄ…cego znaku jako skrótu klawiszowego. + + + + VacuumDialog + + + Compact Database + ÅšciÅ›nij bazÄ™ danych + + + + Warning: Compacting the database will commit all of your changes. + Uwaga: Åšciskanie bazy danych spowoduje wdrożenie wszystkich twoich zmian. + + + + Please select the databases to co&mpact: + Wybierz bazÄ™ danych do Å›ciÅ›&niÄ™cia: + + + diff --git a/src/translations/sqlb_pt_BR.ts b/src/translations/sqlb_pt_BR.ts index 92a06c7b8..2288f9204 100644 --- a/src/translations/sqlb_pt_BR.ts +++ b/src/translations/sqlb_pt_BR.ts @@ -1,2163 +1,8021 @@ - + AboutDialog + About DB Browser for SQLite Sobre DB Browser para SQLite + Version Versão - <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:small;">It also uses the Silk icon set by Mark James licensed under a Creative Commons Attribution 2.5 and 3.0 license.<br/>See </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> - <html><head/><body><p>DB Browser para SQLite é uma ferramenta visual gratuita utilizada para criar, desenhar e editar bancos de dados SQLite.</p><p>É bilicenciada sob a Mozilla Public License Version 2 e a GNU General Public License Version 3 ou posterior. Você pode modificar ou redistribuí-la sob as condições dessas licenças.</p><p>Veja <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> e <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> para mais detalhes.</p><p>Para mais informação sobre esse programa visite nosso website: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">Esse software utiliza o GPL/LGPL Qt Toolkit de </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>Veja </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> para termos de licença e informação.</span></p><p><span style=" font-size:small;">Também utiliza o Silk icon set de Mark James licenciado sob uma licença Creative Commons Attribution 2.5 e 3.0.<br/>Veja </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> para mais detalhes.</span></p></body></html> + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + + + + AddRecordDialog - Version - Versão + + Add New Record + Adicionar novo registro - Qt Version - Versão do Qt + + Enter values for the new record considering constraints. Fields in bold are mandatory. + Entre valores para o novo registro considerando as restriões. Campos em negrito são obrigatórios. - SQLCipher Version - Versão do SQLCipher + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + Na coluna Valor você pode especificar o valor para o campo identificado na coluna Nome. A coluna Tipo indica qual o tipo do campo. Valores padrão são exibidos no mesmo estilo que valores nulos. - SQLite Version - Versão do SQLite + + Name + Nome - - - Application - Usage: %1 [options] [db] - - Uso: %1 [opções] [bd] + + Type + Tipo - Possible command line arguments: - Possíveis argumentos da linha de comando: + + Value + Valor - -h, --help Show command line options - -h, --help Mostrar opções da linha de comando + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + Valores para inserir. Valores padrão pré-preenchidos são inseridos automaticamente a não ser que sejam alterados. - -s, --sql [file] Execute this SQL file after opening the DB - -s, -sql [arquivo] Executar esse arquivo de SQL após abrir o BD + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + Quando você edita os valores no frame acima, a consulta SQL para inserir esse novo registro é exibida aqui. Você pode editar manualmente a consulta antes de salvar. - -q, --quit Exit application after running scripts - -q, --quit Sair do programa após executar os scripts + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Salvar</span> irá enviar o comando SQL exibido para o banco de dados para a inserção do novo registro.</p><p><span style=" font-weight:600;">Restaurar Padrões</span> irá restaurar os valores iniciais na coluna <span style=" font-weight:600;">Valor</span>.</p><p><span style=" font-weight:600;">Cancelar</span> irá fechar esse diálogo sem executar a consulta.</p></body></html> - [file] Open this SQLite database - [arquivo] Abrir esse banco de dados SQLite + + Auto-increment + + Auto-incremento + - The -s/--sql option requires an argument - A opção -s/--sql requer um argumento + + Unique constraint + + Restrição de unicidade + - The file %1 does not exist - O arquivo %1 não existe + + Check constraint: %1 + + Restrição de condição %1 + - Invalid option/non-existant file: %1 - Opção inválida/arquivo inexistente: %1 + + Foreign key: %1 + + Chave estrangeira: %1 + - - - CipherDialog - SQLCipher encryption - Encriptação SQLCipher + + Default value: %1 + + Valor padrão: %1 + - &Password - &Senha + + Error adding record. Message from database engine: + +%1 + Erro adicionando registro. Mensagem do banco de dados: + +%1 - &Reenter password - &Entre a senha novamente + + Are you sure you want to restore all the entered values to their defaults? + Você tem certeza que deseja restaurar todos os valores inseridos para os seus valores padrão? + + + Application - Page &size - &Tamanho da página + + Possible command line arguments: + Possíveis argumentos da linha de comando: - Please set a key to encrypt the database. -Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. -Leave the password fields empty to disable the encryption. -The encrpytion process might take some time and you should have a backup copy of you database! Unsaved changes are applied before modifying the encryption. - Por favor, selecione uma chave para encriptar o banco de dados. -Note que se você alterar quaisquer configurações opcionais você terá de entrá-las todas as vezes que você abrir o arquivo do banco de dados. -Deixe os campos de senha em branco para desativar a encriptação. -O processo de encriptação pode demorar alguns minutos e você deve ter um backup do seu banco de dados! Alterações não salvas são aplicadas antes de se modificar a encriptação. + + The user settings file location is replaced with the argument value instead of the environment variable value. + - Please enter the key used to encrypt the database. -If any of the other settings were altered for this database file you need to provide this information as well. - Por favor, entre a chave usada para encriptar o banco de dados. -Se quaisquer das outras configurações foram alteradas você terá de prover essas informações também. + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + - - - CreateIndexDialog - Create New Index - Criar novo índice + + Usage + - &Name - &Nome + + options + - &Columns - &Colunas + + + database + - Column - Coluna + + + project + - Use in Index - Usar no Ãndice + + + csv-file + - Order - Ordem + + Show command line options + - &Table - &Tabela + + Exit application after running scripts + - &Unique - &Único + + + file + - Creating the index failed: -%1 - Criação de índice falhou: -%1 + + Execute this SQL file after opening the DB + - - - DBBrowserDB - no error - Nenhum erro + + Import this CSV file into the passed DB or into a new DB + - Please specify the database name under which you want to access the attached database - Por favor, especifique o nome do banco de dados sob o qual você quer acessar o banco de dados anexado + + table + - Do you want to save the changes made to the database file %1? - Você quer salvar as alterações feitas ao arquivo de banco de dados %1? + + Browse this table, or use it as target of a data import + - Exporting database to SQL file... - Exportando banco de dados para arquivo SQL... + + Open database in read-only mode + - Cancel - Cancelar + + settings_file + - Executing SQL... - Executando SQL... + + Run application based on this settings file + - Action cancelled. - Ação cancelada. + + + group + - Error in statement #%1: %2. -Aborting execution. - Erro na consulta #%1: %2. -Abortando execução. + + + settings + - renameColumn: cannot find table %1. - renameColumn: não consegue encontrar a tabela %1. + + + value + - renameColumn: cannot find column %1. - renameColumn: não consegue encontrar a coluna %1. + + Run application with this setting temporarily set to value + - renameColumn: creating savepoint failed. DB says: %1 - renameColumn: criação de savepoint falhou. DB diz: %1 + + Run application saving this value for this setting + - renameColumn: creating new table failed. DB says: %1 - renameColumn: criação de nova tabela falhou. DB diz: %1 + + Display the current version + - renameColumn: copying data to new table failed. DB says: -%1 - renameColumn: cópia de dados para nova tabela falhou. DB diz: %1 + + Open this SQLite database + - renameColumn: deleting old table failed. DB says: %1 - renameColumn: deleção de tabela falhou. DB diz: %1 + + Open this project file (*.sqbpro) + - Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: - - - A restauração de alguns dos objetos associados com essa tabela falhou. Provavelmente porque os nomes de algumas colunas mudaram. Aqui está a consulta que você pode querer corrigir e executar manualmente: - - + + Import this CSV file into an in-memory database + - renameColumn: releasing savepoint failed. DB says: %1 - renameColumn: liberar savepoint falhou. DB diz: %1 + + + + The %1 option requires an argument + - Error renaming table '%1' to '%2'.Message from database engine: -%3 - Erro renomeando tabela '%1' para '%2'. Mensagem do banco de dados: -%3 + + + The file %1 does not exist + O arquivo %1 não existe - ... <string can not be logged, contains binary data> ... - ... <string não pode ser logada, contém dados binários> ... + + The -S/--settings option requires an argument. The option is ignored. + - unknown object type %1 - Tipo de objeto desconhecido %1 + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + As opções -o/--option e -O/--save-option requerem um argumento no formato grupo/configuração=valor - could not get list of db objects: %1, %2 - Não pôde obter lista de objetos de banco de dados: %1, %2 + + Invalid option/non-existent file: %1 + Opção inválida/arquivo inexistente: %1 - could not get types - Não pôde obter tipos + + SQLite Version + Versão do SQLite - didn't receive any output from pragma %1 - Não recebeu qualquer saída do pragma %1 + + SQLCipher Version %1 (based on SQLite %2) + SQLCipher versão %1 (baseado em SQLite %2) - could not execute pragma command: %1, %2 - Não conseguiu executar comando pragma: %1, %2 + + DB Browser for SQLite Version %1. + - Error setting pragma %1 to %2: %3 - Erro definindo pragma %1 para %2: %3 + + Last commit hash when built: %1 + - File not found. - Arquivo não encontrado. + + Built for %1, running on %2 + Compilado para %1, rodando em %2 + + + + Qt Version %1 + - DbStructureModel + CipherDialog - Name - Nome + + SQLCipher encryption + Encriptação SQLCipher - Object - Objeto + + &Password + &Senha - Type - Tipo + + &Reenter password + &Entre a senha novamente - Schema - Esquema + + Encr&yption settings + &Configurações de encriptação - Tables (%1) - Tabelas (%1) + + SQLCipher &3 defaults + Padrões do SQLCipher &3 - Indices (%1) - Ãndices (%1) + + SQLCipher &4 defaults + Padrões do SQLCipher &4 - Views (%1) - Vistas (%1) + + Custo&m + Custo&mizado - Triggers (%1) - Gatilhos (%1) + + &KDF iterations + Iterações &KDF - - - EditDialog - Edit database cell - Editar célula + + HMAC algorithm + Algoritmo de HMAC - Import text - Importar texto + + KDF algorithm + Algoritmo de KDF - Opens a file dialog used to import text to this database cell. - Abre uma janela usada para importar texto para essa célula de banco de dados. + + Plaintext Header Size + Tamanho do cabeçalho de texto - &Import - &Importar + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + Por favor, entre a chave usada para encriptar o banco de dados. +Se quaisquer das outras configurações foram alteradas você terá de prover essas informações também. - Export text - Exportar texto + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + Por favor, selecione uma chave para encriptar o banco de dados. +Note que se você alterar quaisquer configurações opcionais você terá de entrá-las todas as vezes que você abrir o arquivo do banco de dados. +Deixe os campos de senha em branco para desativar a encriptação. +O processo de encriptação pode demorar alguns minutos e você deve ter um backup do seu banco de dados! Alterações não salvas são aplicadas antes de se modificar a encriptação. - Opens a file dialog used to export the contents of this database cell to a text file. - Abre um diálogo de arquivo usado para exportar os conteúdos dessa célula para um arquivo de texto. + + Page si&ze + &Tamanho da página - &Export - &Exportar + + Passphrase + Palavra chave - Text - Texto + + Raw key + Chave desencriptada + + + ColumnDisplayFormatDialog - Binary - Binário + + Choose display format + Escolha um formato de exibição - Clear cell data - Limpar dados de célula + + Display format + Formato de exibição - Erases the contents of the cell - Apaga os conteúdos da célula + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + Escolha um formato de exibição para a coluna '%1' que será aplicado a cada valor antes de exibí-lo. - &Clear - &Limpar + + Default + Padrão - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Warning: Editing binary content in text mode may result in corrupted data!</span></p></body></html> - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Aviso: editar conteúdo binário em modo de texto pode corromper dados!</span></p></body></html> + + Decimal number + Número decimal - This area displays information about the data present in this database cell - Essa área exibe informação sobre os dados presentes nessa célula + + Exponent notation + Notação exponencial - Type of data currently in cell - Tipo de dados atualmente na célula + + Hex blob + BLOB hexadecimal - Size of data currently in table - Tamanho dos dados atualmente na célula + + Hex number + Número hexadecimal - Choose a file - Escolha um arquivo + + .NET DateTime.Ticks to date + - Text files(*.txt);;Image files(%1);;All files(*) - Arquivos de texto(*.txt);;Imagens(%1);;Todos os arquivos(*) + + Julian day to date + Dia juliano para data - Choose a filename to export data - Escolha um arquivo para exportar dados + + WebKit / Chromium epoch to date + - Text files(*.txt);;All files(*) - Arquivos de texto(*.txt);;Todos os arquivos(*) + + WebKit / Chromium epoch to local time + - Type of data currently in cell: Null - Tipo de dados atualmente na célula: Null + + Lower case + Caixa baixa - Type of data currently in cell: Text / Numeric - Tipo de dados atualmente na célula: Texto / Numérico + + Binary GUID to text + - - %n char(s) - - %n char - %n chars - + + + SpatiaLite Geometry to SVG + - Type of data currently in cell: Image - Tipo de dados atualmente na célula: Imagem + + Custom display format must contain a function call applied to %1 + Formato de exibição customizado precisa conter uma função aplicada a %1 - %1x%2 pixel - %1x%2 pixel + + Error in custom display format. Message from database engine: + +%1 + Erro em formato de exibição customizado. Mensagem da engine da base de dados: + +%1 - Type of data currently in cell: Binary - Tipo de dados atualmente na célula: Binário + + Custom display format must return only one column but it returned %1. + Formato de exibição customizado precisa retornar apenas uma coluna mas retornou %1. - - %n byte(s) - - %n byte - %n bytes - + + + Octal number + Octal - - - EditTableDialog - Edit table definition - Editar definição da tabela + + Round number + Número arredondado - Table - Tabela + + Unix epoch to date + Era unix para data - Advanced - Avançado + + Upper case + Caixa alta - Make this a 'WITHOUT rowid' table. Setting this flag requires a field of type INTEGER with the primary key flag set and the auto increment flag unset. - Fazer dessa uma tabela 'SEM rowid'. Definir essa flag requer um campo do tipo INTEGER com a primary key flag definida e a auto increment flag não. + + Windows DATE to date + DATE do Windows para data - Without Rowid - Sem Rowid + + Custom + Personalizado - Fields - Campos + + Apple NSDate to date + NSDate da Apple para date + + + + Java epoch (milliseconds) to date + Época Java (ms) para data - Add field - Adicionar campo + + Unix epoch to local time + Época Unix para tempo local - Remove field - Remover campo + + Date as dd/mm/yyyy + Data como dd/mm/yyyy + + + CondFormatManager - Move field up - Mover campo para cima + + Conditional Format Manager + Gerenciador de formato condicional - Move field down - Mover campo para baixo + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + Esse diálogo permite a criação e edição de formatos condicionais. O estilo de cada célula será escolhido pela primeira condição satisfeita pelo valor daquela célula. Formatos condicionais podem ser movidos para cima e para baixo, tendo precedência os formatos localizados mais acima. A sintaxe para as condições é a mesma utilizada para os filtros e uma condição vazia é sempre satisfeita. - Name - Nome + + Add new conditional format + Adicionar novo formato condicional - Type - Tipo + + &Add + &Adicionar - Not null - Não null + + Remove selected conditional format + Remover formato condicional selecionado - PK - PK + + &Remove + &Remover - Primary key - Primary key + + Move selected conditional format up + Mover formato condicional selecionado para cima - AI - AI + + Move &up + Mover para &cima - Autoincrement - Autoincrement + + Move selected conditional format down + Mover formato condicional selecionado para baixo - U - U + + Move &down + Mover para &baixo - Unique - Unique + + Foreground + Plano de frente - Default - Default + + Text color + Cor do texto - Default value - Default value + + Background + Fundo - Check - Check + + Background color + Cor do plano de fundo - Check constraint - Check constraint + + Font + Fonte - Foreign Key - Foreign Key + + Size + Tamanho - Error creating table. Message from database engine: -%1 - Erro criando tabela. Mensagem do DB: -%1 + + Bold + Negrito - There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. - Há pelo menos uma linha com esse campo definido NULL. Logo, é impossível definir essa flag. Por favor, mude os dados da tabela primeiro. + + Italic + Itálico - There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. - Há pelo menos uma linha com um valor não-inteiro nesse campo. Logo, é impossível definir essa flag. Por favor, mude os dados da tabela primeiro. + + Underline + Sublinhado - Column `%1` has no unique data. - - Coluna `%1` não possui dados únicos. + + Alignment + Alinhamento - This makes it impossible to set this flag. Please change the table data first. - Logo, é impossível definir essa flag. Por favor, mude os dados da tabela primeiro. + + Condition + Condição - Are you sure you want to delete the field '%1'? -All data currently stored in this field will be lost. - Você tem certeza de que deseja deletar o campo '%1? -Todos os dados atualmente armazenados nesse campo serão perdidos. + + + Click to select color + Clique para selecionar a cor - Please add a field which meets the following criteria before setting the without rowid flag: - - Primary key flag set - - Auto incremenct disabled - Por favor adicione um campo que cumpre os seguintes requerimentos antes de definir a flag without rowid: - - Primare key flag definida - - Auto increment desativado + + Are you sure you want to clear all the conditional formats of this field? + Você tem certeza de que deseja limpar todos os formatos condicionais deste campo? - ExportCsvDialog + DBBrowserDB - Export data as CSV - Exportar dados como CSV + + Please specify the database name under which you want to access the attached database + Por favor, especifique o nome do banco de dados sob o qual você quer acessar o banco de dados anexado - &Table(s) - &Tabela(s) + + Do you want to save the changes made to the database file %1? + Você quer salvar as alterações feitas ao arquivo de banco de dados %1? - &Column names in first line - Nomes das &colunas na primeira linha + + Exporting database to SQL file... + Exportando banco de dados para arquivo SQL... - Field &separator - &Separador de campos + + + Cancel + Cancelar - , - , + + Executing SQL... + Executando SQL... - ; - ; + + Action cancelled. + Ação cancelada. - Tab - Tab + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + A restauração de alguns dos objetos associados com essa tabela falhou. Provavelmente porque os nomes de algumas colunas mudaram. Aqui está a consulta que você pode querer corrigir e executar manualmente: + + - | - | + + Error setting pragma %1 to %2: %3 + Erro definindo pragma %1 para %2: %3 - Other - Outro + + File not found. + Arquivo não encontrado. - &Quote character - &Ãspas + + Invalid file format + Formato de arquivo inválido - " - " + + + Error in statement #%1: %2. +Aborting execution%3. + Erro no comando #%1: %2. +Aborting execution%3. - ' - ' + + + and rolling back + e revertendo - Could not open output file: %1 - Não pôde abrir arquivo de saída: %1 + + Cannot set data on this object + Não se pode definir dados nesse objeto - Choose a filename to export data - Escolha um arquivo para exportar dados + + Error loading built-in extension: %1 + - Text files(*.csv *.txt) - Arquivos de texto(*.csv *.txt) + + could not get column information + não pôde obter informação sobre a coluna - Please select at least 1 table. - Por favor, selecione pelo menos uma tabela. + + Do you really want to close this temporary database? All data will be lost. + Você realmente quer fechar esse banco de dados temporário? Todos os dados serão perdidos. - Choose a directory - Escolha um diretório + + Database didn't close correctly, probably still busy + A base de dados não fechou corretamente, provavelmente ainda ocupada - Export completed. - Exportação completa. + + Cannot open destination file: '%1' + - - - ExportSqlDialog - Export SQL... - Exportar SQL... + + + Cannot backup to file: '%1'. Message: %2 + - &Table(s) - &Tabela(s) + + The database is currently busy: + O banco de dados está ocupado: - &Options - &Opções + + Do you want to abort that other operation? + Você quer abortar a outra operação? - Keep column names in INSERT INTO - Manter nomes de colunas em INSERT INTO + + + No database file opened + Não há um arquivo de banco de dados aberto - New INSERT INTO syntax (multiple rows in VALUES) - Nova sintaxe de INSERT INTO (múltiplas linhas em VALUES) + + didn't receive any output from %1 + não recebeu nenhuma saída de %1 - Export schema only - Exportar somente schema + + could not execute command: %1 + não pode executar comando: %1 - Please select at least 1 table. - Por favor, selecione pelo menos uma tabela. + + Cannot delete this object + Não pode deletar esse objeto - Choose a filename to export - Escolha um arquivo para exportar + + + A table with the name '%1' already exists in schema '%2'. + Uma tabela com o nome '%1' já existe no esquema '%2'. - Text files(*.sql *.txt) - Arquivos de texto(*.sql *.txt) + + No table with name '%1' exists in schema '%2'. + Nem uma tabela chamada '%1' existe no esquema '%2'. - Export completed. - Exportação completa. + + + Cannot find column %1. + Não pode encontrar coluna %1. - Export cancelled or failed. - Exportação falhou ou foi cancelada. + + Creating savepoint failed. DB says: %1 + Criação de savepoint falhou. BD diz: %1 - - - FilterLineEdit - Filter - Filtro + + Renaming the column failed. DB says: +%1 + Renomeação de coluna falhou. BD diz: +%1 - - - ImportCsvDialog - Import CSV file - Importar arquivo CSV + + + Releasing savepoint failed. DB says: %1 + Liberação de savepoint falhou. BD diz: %1 - &Table name - &Nome da tabela + + Creating new table failed. DB says: %1 + Criação de tabela falhou. BD diz: %1 - &Column names in first line - Nomes das &colunas na primeira linha + + Copying data to new table failed. DB says: +%1 + Cópia de dados para uma nova tabela falhou. BD diz: +%1 - Field &separator - &Separador de campos + + Deleting old table failed. DB says: %1 + Deletando tabela antiga falhou. BD diz: %1 - , - , + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + Erro renomeando tabela de '%1' para '%2'. +Mensagem da engine do banco de dados: +%3 - ; - ; + + could not get list of db objects: %1 + não conseguiu listar objetos da BD: %1 - Tab - Tab + + could not get list of databases: %1 + não pôde obter a lista de bancos de dados: %1 - | - | + + Error loading extension: %1 + Erro carregado extensão: %1 + + + DbStructureModel - Other - Outro + + Name + Nome - &Quote character - &Ãspas + + Object + Objeto - " - " + + Type + Tipo - ' - ' + + Schema + Esquema - &Encoding - &Encoding + + Tables (%1) + Tabelas (%1) - UTF-8 - UTF-8 + + Indices (%1) + Ãndices (%1) - UTF-16 - UTF-16 + + Views (%1) + Vistas (%1) - ISO-8859-1 - ISO-8859-1 + + Triggers (%1) + Gatilhos (%1) - Trim fields? - Trim fields? + + All + Todos - Inserting data... - Inserindo dados... + + Database + Banco de dados - Cancel - Cancelar + + Browsables + Navegáveis - There is already a table of that name and an import into an existing table is only possible if the number of columns match. - Já existe uma tabela com esse nome e importar em uma tabela existente apenas é possível se o número de colunas for o mesmo. + + Temporary + Temporário + + + EditDialog - There is already a table of that name. Do you want to import the data into it? - Já existe uma tabela com esse nome. Você quer importar os dados nela? + + Edit database cell + Editar célula - Creating restore point failed: %1 - Criação de ponto de restauração falhou: %1 + + Text + Texto - Creating the table failed: %1 - Criação de tabela falhou: %1 + + Binary + Binário - Missing field for record %1 - Campo ou registro faltando %1 + + Erases the contents of the cell + Apaga os conteúdos da célula - Inserting row failed: %1 - Inserir linha falhou: %1 + + This area displays information about the data present in this database cell + Essa área exibe informação sobre os dados presentes nessa célula - - - MainWindow - DB Browser for SQLite - DB Browser para SQLite + + Choose a filename to export data + Escolha um arquivo para exportar dados - Database &Structure - &Estrutura do banco de dados + + Mode: + Modo: - toolBar1 - toolBar1 + + + Image + Imagem - &Browse Data - &Navegar dados + + Set as &NULL + Definir como &NULL - Table: - Tabela: + + Apply + Aplicar - Select a table to browse data - Selecione uma tabela para navegar + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + Essa é a lista de modos suportados pelo editor de célula. Escolha um modo para visualizar ou editar os dados da célula atual. - Use this list to select a table to be displayed in the database view - Use esta lista para selecionar uma tabela para ser exibida na vista do banco de dados + + RTL Text + Texto para a esquerda - Refresh the data in the selected table. - Atualiza os dados na tabela selecionada. + + JSON + JSON - This button refreshes the data in the currently selected table. - Este botão atualiza os dados na tabela atualmente selecionada. + + XML + XML - F5 - F5 + + Evaluation + - Clear all filters - Limpar todos os filtros + + + Automatically adjust the editor mode to the loaded data type + Automaticamente ajustar o modo do editor para o tipo de dado carregado - Insert a new record in the current table - Inserir um novo registro na tabela atual + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + Esse botão assinalável ativa ou desativa a troca automática do modo do editor. Quando uma nova célula é selecionado ou novos dados são importados e a troca automática está habilitada, o modo ajusta para o tipo detectado. Você pode então mudar o modo do editor manualmente. Se você quer manter o modo manualmente escolhido enquanto movendo pelas células, desmarque essa opção. - This button creates a new, empty record in the database - Este botão cria um novo registro em branco no banco de dados + + Auto-switch + Auto-trocar - New Record - Novo Registro + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + Esse editor do QT é usado para scripts da direita para a esquerda, que não são suportados pelo editor de texto padrão. Quando a presença de caracteres da direita para a esquerda é detectada, esse modo é automaticamente selecionado. - Delete the current record - Deletar o registro atual + + Identification of the cell currently in the editor + - This button deletes the record currently selected in the database - Este botão deleta o registro atualmente selecionado no banco de dados + + Type and size of data currently in table + - Delete Record - Deletar Registro + + Open preview dialog for printing the data currently stored in the cell + Abrir diálogo de prévia para impressão dos dados atualmente armazenados na célula - This is the database view. You can double-click any record to edit its contents in the cell editor window. - Esta é a vista do banco de dados. Você pode clicar duas vezes em qualquer registro para editar seus conteúdos na janela de edição de célula. + + Auto-format: pretty print on loading, compact on saving. + Auto-formatar: exibir formatado ao carregar, compactar ao salvar. - <html><head/><body><p>Scroll to the beginning</p></body></html> - <html><head/><body><p>Rolar para o começo</p></body></html> + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + Quando ativado, a funcionalidade de auto-formatar formata os dados ao carregar, quebrando o texto em linhas e indentando ele para melhor legibilidade. Ao salvar os dados, o auto-formatador compacta os dados removendo espaços em branco desnecessários. - <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> - <html><head/><body><p>Clicar nesse botão navega até o começo da vista de tabela acima.</p></body></html> + + Word Wrap + Quebra de linha - |< - |< + + Wrap lines on word boundaries + Quebra de linha em limites de palavras - Scroll 100 records upwards - Rolar 100 registros para baixo + + + Open in default application or browser + Abrir em aplicação padrão ou navegador - <html><head/><body><p>Clicking this button navigates 100 records upwards in the table view above.</p></body></html> - <html><head/><body><p>Clicar nesse botão navega 100 registros para cima na vista de tabela acima.</p></body></html> + + Open in application + Abrir em aplicação - < - < + + The value is interpreted as a file or URL and opened in the default application or web browser. + O valor é interpretado como um arquivo ou URL e aberto na aplicação padrão ou navegador. - 0 - 0 of 0 - 0 - 0 de 0 + + Save file reference... + Salvar referência de arquivo... - <html><head/><body><p>Scroll 100 records downwards</p></body></html> - <html><head/><body><p>Rolar 100 registros para baixo</p></body></html> + + Save reference to file + Salvar referência para arquivo - <html><head/><body><p>Clicking this button navigates 100 records downwards in the table view above.</p></body></html> - <html><head/><body><p>Clicar nesse botão navega 100 registros para baixo na vista de tabela acima.</p></body></html> + + + Open in external application + Abrir em aplicação externa - > - > + + Autoformat + Autoformatar - Scroll to the end - Rolar para o fim + + &Export... + &Exportar... - <html><head/><body><p>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Clicking this button navigates up to the end in the table view above.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html> - <html><head/><body><p>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Clicar nesse botão navega até o fim da vista de tabela acima.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html> + + + &Import... + &Importar... - >| - >| + + + Import from file + Importar do arquivo - <html><head/><body><p>Click here to jump to the specified record</p></body></html> - <html><head/><body><p>Clique aqui para pular para o registro especificado</p></body></html> + + + Opens a file dialog used to import any kind of data to this database cell. + Abre um seletor de arquivos usado para importar qualquer tipo de dado para essa célula. - <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> - <html><head/><body><p>Esse botão navega para o registro especificado na área Ir para.</p></body></html> + + Export to file + Exportar para arquivo - Go to: - Ir para: + + Opens a file dialog used to export the contents of this database cell to a file. + Abre um seletor de arquivo para exportar os conteúdos dessa célula para um arquivo. - Enter record number to browse - Entre o número do registro para navegar + + Apply data to cell + Aplicar dados à célula - Type a record number in this area and click the Go to: button to display the record in the database view - Digite o número de um registro nessa área e clique no botão Ir para: para exibir o registro na vista do banco de dados + + This button saves the changes performed in the cell editor to the database cell. + Esse botão salva as modificações realizadas no editor da célula para a célula do banco de dados. - 1 - 1 + + + Image data can't be viewed in this mode. + Dados de imagem não podem ser visualizados nesse modo. - Edit &Pragmas - Editar &Pragmas + + + Try switching to Image or Binary mode. + Tente mudar para modo de Imagem ou Binário. - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> - + + + Binary data can't be viewed in this mode. + Dados binários não podem ser visualizados nesse modo. - None - None + + + Try switching to Binary mode. + Tente mudar para modo binário. - Full - Full + + + Type: NULL; Size: 0 bytes + - - Incremental - Incremental + + + + Type: Text / Numeric; Size: %n character(s) + + + + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> + + Type: %1 Image; Size: %2x%3 pixel(s) + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> + + + Type: Valid JSON; Size: %n character(s) + + + + + + + + Type: Binary; Size: %n byte(s) + + + + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></a></p></body></html> - + + Couldn't save file: %1. + Não pôde salvar arquivo: %1. - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> + + + Image files (%1) + Arquivos de imagem (%1) - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> + + Binary files (*.bin) + Arquivos binários (*.bin) - Delete - Deletar + + Choose a file to import + Escolha um arquivo para importar - Truncate - Truncar + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + - Persist - Persistir + + Unsaved data in the cell editor + - Memory - Memória + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + - WAL - WAL + + Editing row=%1, column=%2 + - Off - Desligado + + No cell active. + - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> + + %1 Image + %1 Imagem - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a></p></body></html> - + + Invalid data for this mode + Dados inválidos para esse modo - Normal - Normal + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + A célula contém dados inválidos %1. Motivo: %2. Você realmente quer aplicar isso? - Exclusive - Exclusivo + + Print... + Imprimir... - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> + + Ctrl+P - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> + + Open preview dialog for printing displayed text + Abrir diálogo de prévia para imprimir texto exibido - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> + + Copy Hex and ASCII + Copiar Hex e ASCII - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> + + Copy selected hexadecimal and ASCII columns to the clipboard + Copiar colunas hexadecimal e ASCII selecionadas para a área de transferência - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> + + Ctrl+Shift+C + + + + EditIndexDialog - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> + + &Name + &Nome - Default - Padrão + + Order + Ordem - File - Arquivo + + &Table + &Tabela - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> + + &Unique + &Único - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> + + Creating the index failed: +%1 + Criação de índice falhou: +%1 - E&xecute SQL - &Executar SQL + + Edit Index Schema + Editar esquema do índice - &File - &Arquivo + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + Para restringir o índice para somente uma parte da tabela você pode especificar uma cláusula WHERE aqui que seleciona a parte da tabela que deveria ser indexada - &Import - &Importar + + Partial inde&x clause + Cláusula de índi&ce parcial - &Export - E&xportar + + Colu&mns + Colu&nas - &Edit - &Editar + + Table column + Coluna da tabela - &View - &Vista + + Type + Tipo - &Help - A&juda + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + Adicionar uma nova coluna de expressão para o índice. Colunas de expressão contêm expressões SQL em vez de nomes de coluna. - DB Toolbar - DB Toolbar + + Index column + Indexar coluna - SQL Log - Log do SQL + + Deleting the old index failed: +%1 + Deletar o índice antigo falhou: +%1 + + + EditTableDialog - &Show SQL submitted by - E&xibir SQL enviado por + + Edit table definition + Editar definição da tabela - User - Usuário + + Table + Tabela - Application - Aplicativo + + Advanced + Avançado - &Clear - &Limpar + + Database sche&ma + Esque&ma do banco de dados - Plot - Plot + + Without Rowid + Sem Rowid - Columns - Colunas + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + - X - X + + On Conflict + - Y - Y + + Strict + - _ - _ + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + - <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> - <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + + Fields + Campos - Save current plot... - Save current plot... + + + + Add + Adicionar - DB Schema - Esquema do banco de dados + + + + Remove + Remover - &New Database... - &Novo banco de dados... + + Move to top + Mover para o topo - Create a new database file - Criar um novo arquivo de banco de dados + + Move up + Mover para cima - This option is used to create a new database file. - Essa opção e utilizada para criar um novo arquivo de banco de dados. + + Move down + Mover para baixo - Ctrl+N - Ctrl+N + + Move to bottom + Mover para o fundo - &Open Database... - &Abrir banco de dados... + + + + + Name + Nome - Open an existing database file - Abre um arquivo de banco de dados existente + + + Type + Tipo - This option is used to open an existing database file. - Esta opção abre um arquivo de banco de dados existente. + + Not null + Não null - Ctrl+O - Ctrl+O + + PK + PK - &Close Database - &Fechar banco de dados + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + - Ctrl+W - Ctrl+W + + AI + AI - Revert Changes - Reverter mudanças + + Autoincrement + Autoincrement - Revert database to last saved state - Reverter banco de dados para o último estado salvo + + U + U - This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. - Essa opção é usada para reverter o atual arquivo de banco de dados para seu último estado salvo. Todas as modificações feitas desde a última operação de salvamento são perdidas. + + + + Unique + Unique - Write Changes - Escrever Alterações + + Default + Default - Write changes to the database file - Salva modificações para o arquivo de banco de dados + + Default value + Default value - This option is used to save changes to the database file. - Essa opção é usada para salvar modificações para o arquivo de banco de dados. + + + Check + Check - Ctrl+S - Ctrl+S + + Check constraint + Check constraint - Compact Database - Compactar Banco de Dados + + Collation + Agrupamento - Compact the database file, removing space wasted by deleted records - Compactar o arquivo do banco de dados, removendo espaço desperdiçado por registros deletados + + Foreign Key + Foreign Key - Compact the database file, removing space wasted by deleted records. - Compactar o arquivo do banco de dados, removendo espaço desperdiçado por registros deletados. + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + - E&xit - &Sair + + Index Constraints + - Ctrl+Q - Ctrl+Q + + Add constraint + Adicionar restrição - Database from SQL file... - Banco de dados a partir de um arquivo SQL... + + Remove constraint + Remover restrição - Import data from an .sql dump text file into a new or existing database. - Importar dados de um arquivo de texto .sql em um banco de dados. + + + Columns + Colunas - This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. - Essa opção deixa você importar dados de um arquivo SQL em um banco de dados. Arquivos de SQL podem ser criados na maioria dos bancos de dados, como MySQL e PostgreSQL. + + + + SQL + SQL - Table from CSV file... - Tabela a partir de um arquivo CSV... + + Foreign Keys + - Open a wizard that lets you import data from a comma separated text file into a database table. - Abre um assistente que permite você importar dados de um arquivo CSV em uma tabela de banco de dados. + + References + - Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. - Abre um assistente que permite você importar dados de um arquivo CSV em uma tabela de banco de dados. Arquivos CSV podem ser criados pela maioria dos programas de banco de dados e planilhas. + + Check Constraints + - Database to SQL file... - Banco de dados para arquivo SQL... + + + Primary Key + Chave primária - Export a database to a .sql dump text file. - Exportar o banco de dados para um arquivo de texto .sql. + + Add a primary key constraint + Adicionar restrição de chave primária - This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. - Essa opção permite você exportar um banco de dados para um arquivo de texto .sql. Arquivos de despejo SQL contêm todos os dados necessários para recriar o banco de dados na maioria dos motores de banco de dados, incluindo MySQL e PostgreSQL. + + Add a unique constraint + Adicionar uma restrição de unicidade - Table(s) as CSV file... - Tabela(s) como arquivo CSV... + + + There can only be one primary key for each table. Please modify the existing primary key instead. + Cada tabela pode ter apenas uma chave primária. Por favor, modifique a chave primária existente. - Export a database table as a comma separated text file. - Exportar uma tabela de banco de dados como um arquivo CSV. + + Error creating table. Message from database engine: +%1 + Erro criando tabela. Mensagem da engine do banco de dados: +%1 - Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. - Exportar uma tabela de banco de dados como um arquivo CSV, pronto para ser importado por outro banco de dados ou planilhas. + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + Há pelo menos uma linha com esse campo definido NULL. Logo, é impossível definir essa flag. Por favor, mude os dados da tabela primeiro. - Create Table... - Criar Tabela... + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + Há pelo menos uma linha com um valor não-inteiro nesse campo. Logo, é impossível definir essa flag. Por favor, mude os dados da tabela primeiro. - Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database - Abre o assistente de criação de tabelas, em que é possível definir o nome e os campos para uma nova tabela no banco de dados + + Column '%1' has duplicate data. + + Coluna '%1' tem dados duplicados. + - Delete Table... - Deletar Tabela... + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + Isso faz com que seja impossível de se habilitar a flag de unicidade. Por favor, remova os dados duplicados para permitir que a flag seja habilitada. - Delete Table - Deletar Tabela + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + Você tem certeza de que deseja deletar o campo '%1? +Todos os dados atualmente armazenados nesse campo serão perdidos. - Open the Delete Table wizard, where you can select a database table to be dropped. - Abre o assistente de deleção de tabelas, em que você pode selecionar uma tabela para ser eliminada. + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + - Modify Table... - Modificar Tabela... + + There already is a field with that name. Please rename it first or choose a different name for this field. + Já existe um campo com este nome. Por favor, renomeie-o primeiro ou escolha um nome diferente para esse campo. - Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields form a table, as well as modify field names and types. - Abre o assistente de modificação de tabelas, em que você pode renomear uma tabela existente. Também é possível adicionar ou deletar campos de uma tabela, assim como modificar nomes e tipos de campos. + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + Por favor, adicione um campo que atende aos seguintes critérios antes de definir a flag "without rowid": + - Flag "primary key" definida + - Incremento automático desativado - Create Index... - Criar Ãndice... + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + Essa coluna é referenciada em uma chave estrangeira na tabela %1 e portanto seu nome não pode ser alterado. - Open the Create Index wizard, where it is possible to define a new index on an existing database table. - Abre o assistente de criação de índice, em que é possível definir um novo índice em um tabela de banco de dados já existente. + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Alerta: </span>Nosso parser não entende algo dessa definição de tabela. Modificar e salvar essa tabela pode causar problemas.</p></body></html> - &Preferences... - &Configurações... + + NN + NN + + + ExportDataDialog - Open the preferences window. - Abre a janela de configurações. + + Export data as CSV + Exportar dados como CSV - &DB Toolbar - Barra de ferramentas do Banco de &Dados + + , + , - Shows or hides the Database toolbar. - Exibe ou oculta a barra de ferramentas do Banco de Dados. + + ; + ; - What's This? - O que é isso? + + Tab + Tab - Shift+F1 - Shift+F1 + + | + | - &About... - &Sobre... + + + + Other + Outro - &Recently opened - &Recentemente aberto + + &Quote character + &Ãspas - Open &tab - Abrir &aba + + " + " - Ctrl+T - Ctrl+T + + ' + ' - &Execute SQL - &Executar SQL + + + Could not open output file: %1 + Não pôde abrir arquivo de saída: %1 - Execute SQL [F5, Ctrl+Return] - Executar SQL [F5, Ctrl+Return] + + + Choose a filename to export data + Escolha um arquivo para exportar dados - Open SQL file - Abrir arquivo SQL + + Please select at least 1 table. + Por favor, selecione pelo menos uma tabela. - Save SQL file - Salvar arquivo SQL + + Choose a directory + Escolha um diretório - Load extension - Carregar extensão + + Export completed. + Exportação completa. - Execute current line - Executar linha atual + + Export finished with errors. + - Execute current line [Ctrl+E] - Executar linha atual [Ctrl+E] + + New line characters + Caracteres de nova linha - Ctrl+E - Ctrl+E + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) - Export as CSV file - Exportar como arquivo CSV + + Unix: LF (\n) + Unix: LF (\n) - Export table as comma separated values file - Exportar tabela como CSV + + Tab&le(s) + Tabe&las(s) - &Wiki... - &Wiki... + + Colu&mn names in first line + &Nomes das colunas na primeira linha - Bug &report... - &Reportar bug... + + Fie&ld separator + Se&parador de campo - Web&site... - Web&site... + + Pretty print + Otimizar para leitura humana - Save Project - Salvar Projeto + + Export data as JSON + Exportar dados como JSON - Save the current session to a file - Salvar a atual sessão para um arquivo + + exporting CSV + exportando CSV - Open Project - Abrir Projeto + + + Error while writing the file '%1': %2 + - Load a working session from a file - Carregar uma sessão de um arquivo + + exporting JSON + exportando JSON + + + ExportSqlDialog - &Attach Database - Microsoft uses "anexar", thought it was good enough a translation. - &Anexar banco de dados + + Export SQL... + Exportar SQL... - Set Encryption - Definir encriptação + + &Options + &Opções - Save SQL file as - Salvar arquivo SQL como + + Keep column names in INSERT INTO + Manter nomes de colunas em INSERT INTO - &Browse Table - &Navegar tabela + + Export schema only + Exportar somente esquema - Copy Create statement - Copiar comando Create + + Choose a filename to export + Escolha um arquivo para exportar - Copy the CREATE statement of the item to the clipboard - Copia o comando CREATE do item para a área de transferência + + Export completed. + Exportação completa. - Ctrl+Return - Ctrl+ENTER + + Export cancelled or failed. + Exportação falhou ou foi cancelada. - Ctrl+L - Ctrl+L + + Tab&le(s) + Tabe&las(s) - Ctrl+P - Ctrl+P + + Select All + Selecionar tudo - Ctrl+D - Ctrl+D + + Deselect All + Limpar seleção - Ctrl+I - Ctrl+I + + Multiple rows (VALUES) per INSERT statement + Múltiplas linhas (VALUES) por INSERT - Database encoding - Codificação do banco de dados + + Export everything + Exportar tudo - Database is encrypted using SQLCipher - Banco de dados encriptado usando SQLCipher + + Export data only + Exportar somente dados - Choose a database file - Escolha um arquivo de banco de dados + + Keep original CREATE statements + - SQLite database files (*.db *.sqlite *.sqlite3 *.db3);;All files (*) - Arquivos de banco de dados SQL (*.db *.sqlite *.sqlite3 *.db3);;Todos os arquivos (*) + + Keep old schema (CREATE TABLE IF NOT EXISTS) + Manter esquema antigo (CREATE TABLE IF NOT EXISTS) - Invalid file format. - Formato de arquivo inválido. + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + Sobrescrever esquema antigo (DROP TABLE, then CREATE TABLE) - Choose a filename to save under - Escolha um nome de arquivo para salvar + + Please select at least one table. + Por favor selecione pelo menos uma tabela. + + + ExtendedScintilla - Error adding record: - - Erro adicionando registro: + + + Ctrl+H + - Error deleting record: -%1 - Erro adicionando registro: %1 + + Ctrl+F + - Please select a record first - Por favor, selecione um registro primeiro + + + Ctrl+P + - %1 - %2 of %3 - %1 - %2 de %3 + + Find... + Encontrar... - There is no database opened. Please open or create a new database file. - Não há banco de dados aberta. Por favor, abra ou crie um novo arquivo de banco de dados. + + Find and Replace... + Encontrar e substituir... - Are you sure you want to delete the %1 '%2'? -All data associated with the %1 will be lost. - Você tem certeza de que deseja deletar %1 '%2'? -Todos os dados associados com %1 serão perdidos. + + Print... + Imprimir... + + + ExtendedTableWidget - Error: could not delete the %1. Message from database engine: -%2 - Erro: não pôde deletar %1. Mensagem do BD: -%2 + + Set to NULL + Definir como NULL - There is no database opened. - Não há banco de dados aberto. + + Copy + Copiar - %1 Rows returned from: %3 (took %2ms) - %1 Entradas retornadas de %3 (levou %2 ms) + + Paste + Colar - Error executing query: %1 - Erro executando requisição: %1 + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + O conteúdo da área de transferência é maior do que o intervalo selecionado. +Deseja inserir mesmo assim? - Query executed successfully: %1 (took %2ms) - Requisição executada com sucesso: %1 (levou %2ms) + + Use as Exact Filter + Usar como filtro exato - Choose a text file - Escolha um arquivo de texto + + Containing + Contendo - Text files(*.csv *.txt);;All files(*) - Arquivos de texto(*.txt);;Todos os arquivos(*) + + Not containing + Não contendo - Import completed - Importação completa + + Not equal to + Diferente de - Are you sure you want to undo all changes made to the database file '%1' since the last save? - Você tem certeza de que deseja desfazer todas as modificações feitas no arquivo de banco de dados '%1' desde o último salvamento? + + Greater than + Maior que - Choose a file to import - Escolha um arquivo para importar + + Less than + Menor que - Text files(*.sql *.txt);;All files(*) - Arquivos de texto(*.txt);;Todos os arquivos(*) + + Greater or equal + Maior ou igual a - Do you want to create a new database file to hold the imported data? -If you answer no we will attempt to import the data in the SQL file to the current database. - Você deseja criar um novo arquivo de banco de dados para armazenar os dados importados? -Se você disser que não, tentaremos importar os dados do arquivo SQL para o banco de dados atual. + + Less or equal + Menor ou igual a - File %1 already exists. Please choose a different name. - Arquivo %1 já existe. Por favor, escolha um nome diferente. + + Between this and... + Entre isso e... - Error importing data: %1 - Erro importando dados: %1 + + Regular expression + Expressão regular - Import completed. - Importação completa. + + Edit Conditional Formats... + Editar formatos condicionais... - Delete View - Deletar vista + + Cut + Recortar - Delete Trigger - Deletar gatilho + + Copy with Headers + Copiar com cabeçalhos - Delete Index - Deletar índice + + Copy as SQL + Copiar como SQL - &%1 %2 - &%1 %2 + + Print... + Imprimir... - Setting PRAGMA values will commit your current transaction. -Are you sure? - Definir valores de PRAGMA vai cometer sua transação atual. -Você tem certeza? + + Use in Filter Expression + Usar na expressão de filtro - Select SQL file to open - Selecione arquivo SQL para abrir + + Alt+Del + - Select file name - Selecione o nome do arquivo + + Ctrl+Shift+C + - Select extension file - Selecione o arquivo de extensão + + Ctrl+Alt+C + - Extensions(*.so *.dll);;All files(*) - Extensões(*.so *.dll);;Todos os arquivos(*) + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>Nem todos os dados foram carregados. <b>Você quer carregar todos os dados antes de selecionar todas as linhas?</b><p><p>Respondendo <b>Não</b> significa que mais dados não serão carregados e a seleção não será executada.<br/>Respondendo <b>Sim</b> pode levar algum tempo enquanto os dados são carregados mas a seleção será incompleta.</p>Aviso: carregar todos os dados pode exigir uma grande quantidade de memória para tabelas grandes. - Extension successfully loaded. - Extensão carregada com sucesso. + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + Não é possível definir a seleção como NULL. Coluna %1 tem uma restrição de nulidade. + + + FileExtensionManager - Error loading extension: %1 - Erro carregado extensão: %1 + + File Extension Manager + Gerenciador de extensão de arquivo - Don't show again - Não mostrar novamente + + &Up + &Subir - New version available. - Nova versão disponível. + + &Down + &Descer - A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. - Uma nova vesão do DB Browser para SQLite está disponível (%1.%2.%3)<br/><br/>Por favor, baixe em <a href='%4'>%4</a>. + + &Add + &Adicionar - Choose a axis color - Escolha uma cor para o eixo + + &Remove + &Remover - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Todos os arquivos(*) + + + Description + Descrição - Choose a file to open - Escolha um arquivo para abrir + + Extensions + Extensões - DB Browser for SQLite project file (*.sqbpro) - Arquivo de projeto DB Browser para SQLite (*.sqbpro) + + *.extension + *.extensão - PreferencesDialog - - Preferences - Configurações - - - &General - &Geral - + FilterLineEdit - Remember last location - Lembrar do último diretório + + Filter + Filtro - Always use this location - Sempre usar esse diretório + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + Esses campos de entrada permitem você realizar filtros rápidos na tabela atualmente selecionada. +Por padrão, as linhas que contém o texto de entrada são filtradas +Os seguintes operadores também são suportados: +% Curinga +> Maior que +< Menor que +>= Maior ou igual a +<= Menor ou igual a += Igual +<> Diferente +x~y Intervalo: valores entre x e y +/regexp/ Valores satisfazendo a expressão regular - Remember last location for session only - Lembrar do último diretório somente nessa sessão + + Clear All Conditional Formats + Limpar todos os formatos condicionais - ... - ... + + Use for Conditional Format + Usar para formato condicional - Default &location - Diretório &padrão + + Edit Conditional Formats... + Editar formatos condicionais... - Lan&guage - &Idioma + + Set Filter Expression + Definir expressão de filtro - Automatic &updates - &Atualizações automáticas + + What's This? + O que é isso? - enabled - ativado + + Is NULL + É NULL - &Database - &Banco de dados + + Is not NULL + Não é NULL - Database &encoding - &Codificação do banco de dados + + Is empty + É vazio - Open databases with foreign keys enabled. - Abrir bancos de dados com chaves estrangeiras ativado. + + Is not empty + Não é vazio - &Foreign keys - &Chaves estrangeiras + + Not containing... + Não contendo... - Remove line breaks in schema view - Remove line breaks in schema view + + Equal to... + Igual a... - &Prefetch block size - &Prefetch block size + + Not equal to... + Diferente de... - Data &Browser - Data &Browser + + Greater than... + Maior que... - NULL fields - Campos nulos + + Less than... + Menor que... - Text &colour - &Cor do texto + + Greater or equal... + Maior ou igual... - &Text - &Texto + + Less or equal... + Menor ou igual... - Bac&kground colour - Cor de &fundo + + In range... + No intervalo... - &SQL - &SQL + + Regular expression... + Expressão regular... + + + FindReplaceDialog - Settings name - Settings name + + Find and Replace + Encontrar e substituir - Context - Context + + Fi&nd text: + E&ncontrar texto: - Colour - Cor + + Re&place with: + Su&bstituir com: - Bold - Negrito + + Match &exact case + Casar caixa &exata - Italic - Itálico + + Match &only whole words + Casar s&omente palavras inteiras - Underline - Underline + + When enabled, the search continues from the other end when it reaches one end of the page + Quando ativado, a busca continua do outro fim quando ela atinge um fim da página - Keyword - Palavra-chave + + &Wrap around + &Envolver em torno - function - função + + When set, the search goes backwards from cursor position, otherwise it goes forward + Quando ativado, a busca retrocede a partir do cursor em vez de ir para frente - Function - Função + + Search &backwards + Buscar para &trás - Table - Tabela + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>Quando selecionado, o padrão procurado é testado somente na seleção atual.</p></body></html> - Comment - Comentário + + &Selection only + &Somente seleção - Identifier - Identificador + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Quando selecionado, o padrão a ser encontrado é interpretado como uma expressão regular UNIX. Veja <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression nos Wikibooks</a>.</p></body></html> - String - String + + Use regular e&xpressions + Usar e&xpressões regulares - currentline - currentline + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + Encontrar a próxima ocorrência a partir da posição do cursor na direção selecionada por "Buscar para trás" - Current line - Linha atual + + &Find Next + &Encontrar próximo - SQL &editor font size - Tamanho da fonte do &editor de SQL + + F3 + - SQL &log font size - Tamanho da fonte do &log de SQL + + &Replace + &Substituir - Tab size: - Tab size: + + Highlight all the occurrences of the text in the page + Realçar todas as ocorrências do texto na página - SQL editor &font - &Fonte do editor de SQL + + F&ind All + Encontrar &todos - &Extensions - &Extensões + + Replace all the occurrences of the text in the page + Substituir todas as ocorrências do texto na página - Select extensions to load for every database: - Selecione extensões para carregar para todos os bancos de dados: + + Replace &All + Substituir &todos - Add extension - Adicionar extensão + + The searched text was not found + O texto procurado não foi encontrado - Remove extension - Remover extensão + + The searched text was not found. + O texto procurado não foi encontrado. - <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> - <html><head/><body><p>Embora suporte o operador REGEXP, SQLite não implementa expressões regulares mas recorre ao aplicativo em execução.<br/>DB Browser para SQLite implementa esse algoritmo para você poder utilizar REGEXP.<br/>Todavia, como existem múltiplas implementações possíveis desse algoritmo e você pode querer usar outra, você pode desativar a implementação do aplicativo e carregar a sua própria implementação através de uma extensão.<br/>Requer que o programa seja reiniciado.</p></body></html> + + The searched text was found one time. + O texto procurado foi encontrado uma vez. - Disable Regular Expression extension - Desativar extensão de Expressões Regulares + + The searched text was found %1 times. + O texto procurado foi encontrado %1 vezes. - Choose a directory - Escolha um diretório + + The searched text was replaced one time. + O texto procurado foi substituído uma vez. - The language will change after you restart the application. - A linguagem mudará após reiniciar o programa. + + The searched text was replaced %1 times. + O texto procurado foi substituído %1 vezes. + + + ForeignKeyEditor - Select extension file - Selecione arquivo de extensão + + &Reset + &Resetar - Extensions(*.so *.dll);;All files(*) - Extensões(*.so *.dll);;Todos os arquivos(*) + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + Cláusulas de chave estrangeira (ON UPDATE, ON DELETE etc.) - QObject - - Error importing data - Erro importando dados - + ImageViewer - from record number %1 - a partir de registro número %1 + + Image Viewer + - . -%1 - . -%1 + + Reset the scaling to match the original size of the image. + - Decoding CSV file... - Decodificando arquivo CSV... + + Set the scaling to match the size of the viewport. + - Cancel - Cancelar + + Print... + Imprimir... - Collation needed! Proceed? - Função de comparação necessária! Proceder? + + Open preview dialog for printing displayed image + Abrir diálogo de prévia para imprimir imagem exibida - A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. -If you choose to proceed, be aware bad things can happen to your database. -Create a backup! - Uma tabela nesse banco de dados requer uma função de comparação especial '%1' que esse aplicativo não pode prover. -So você optar por proceder, esteja avisado de que coisas ruins podem acontecer para o seu banco de dados. -Crie um backup! + + Ctrl+P + - SqlExecutionArea + ImportCsvDialog - Form - Formulário + + Import CSV file + Importar arquivo CSV - Results of the last executed statements - Resultados dos últimos comandos executados + + &Column names in first line + Nomes das &colunas na primeira linha - This field shows the results and status codes of the last executed statements. - Esse campo mostra os resultados e códigos de status dos últimos comandos executados. + + Field &separator + &Separador de campos - Export to &CSV - Exportar para &CSV + + , + , - Save as &view - Salvar como &vista + + ; + ; - Save as view - Salvar como vista + + + Tab + Tab - Please specify the view name - Por favor, especifique o nome da vista + + | + | - There is already an object with that name. Please choose a different name. - Já existe um objeto com esse nome. Por favor, escolha um nome diferente. + + Other + Outro - View successfully created. - Vista criada com sucesso. + + &Quote character + &Ãspas - Error creating view: %1 - Erro criando vista: %1 + + + Other (printable) + Outro (imprimível) - - - SqlUiLexer - (X) The abs(X) function returns the absolute value of the numeric argument X. - + + + Other (code) + Outro (código) - () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. - + + " + " - (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. - (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + + ' + ' - (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL - (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + + &Encoding + &Encoding - (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". - (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + + UTF-8 + UTF-8 - (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. - (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + + UTF-16 + UTF-16 - (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. - (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + + ISO-8859-1 + ISO-8859-1 - (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. - (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + + Trim fields? + Trim fields? - () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. - () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + + Creating restore point failed: %1 + Criação de ponto de restauração falhou: %1 - (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. - + + Creating the table failed: %1 + Criação de tabela falhou: %1 - (X,Y) The like() function is used to implement the "Y LIKE X" expression. - + + Inserting row failed: %1 + Inserir linha falhou: %1 - (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. - + + Separate tables + Tabelas separadas - (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. - + + Use local number conventions + - (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. - + + Use decimal and thousands separators according to the system locale. + - (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. - + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + Quando importando em uma tabela existente com uma chave primária, restrições de unicidade ou índice único há uma chance para conflitos. Essa opção permite a você selecionar uma estratégia para esse caso. Por padrão, a importação é abortada e revertida, mas você também pode escolher ignorar e não importar linhas conflitantes ou substituir as entradas existentes na tabela. - (X) ltrim(X) removes spaces from the left side of X. - + + Abort import + Abortar importação - (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. - + + Ignore row + Ignorar linha - (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. - + + Replace existing row + Substituir linhas existentes - (X,Y,...) The multi-argument min() function returns the argument with the minimum value. - + + Conflict strategy + Estratégia para conflitos - (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. - + + + Deselect All + Limpar seleção - (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. - + + Match Similar + Detectar similares - (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. - + + Select All + Selecionar tudo - () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + + Table na&me + No&me da tabela + + + + Advanced + Avançado + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + Quando importando um valor em branco do arquivo CSV em uma tabela existente com um valor padrão para essa coluna, aquele valor padrão é inserido. Ative essa opção para inserir um valor em branco em vez. + + + + Ignore default &values + Ignorar &valores padrão + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + Ative essa opção para parar a importação quando tentando importar um valor em branco em uma coluna NOT NULL sem um valor padrão. + + + + Fail on missing values + Falhar em valores faltando + + + + Disable data type detection + Desativar detecção de tipo de dados + + + + Disable the automatic data type detection when creating a new table. + Desativa a detecção automática de tipo de dados quando criando uma nova tabela. + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + Já existe uma tabela chamada '%1' e uma importação em uma tabela existente só é possível se o número de colunas bate. + + + + There is already a table named '%1'. Do you want to import the data into it? + Já existe uma tabela chamada '%1'. Você quer importar os dados nela? + + + + importing CSV + Importando CSV + + + + Could not prepare INSERT statement: %1 + + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + Importando o arquivo '%1' levou %2 ms. Desses, %3 ms foram gastos na função da linha. + + + + MainWindow + + + DB Browser for SQLite + DB Browser para SQLite + + + + toolBar1 + toolBar1 + + + + &File + &Arquivo + + + + &Import + &Importar + + + + &Export + E&xportar + + + + &Edit + &Editar + + + + &View + &Exibir + + + + &Help + A&juda + + + + DB Toolbar + Barra de ferramentas do banco de dados + + + + User + Usuário + + + + Application + Aplicativo + + + + &Clear + &Limpar + + + + &New Database... + &Novo banco de dados... + + + + + Create a new database file + Criar um novo arquivo de banco de dados + + + + This option is used to create a new database file. + Essa opção e utilizada para criar um novo arquivo de banco de dados. + + + + Ctrl+N + + + + + + &Open Database... + Abrir &banco de dados... + + + + + + + + Open an existing database file + Abre um arquivo de banco de dados existente + + + + + + This option is used to open an existing database file. + Esta opção abre um arquivo de banco de dados existente. + + + + Ctrl+O + + + + + &Close Database + &Fechar banco de dados + + + + + Ctrl+W + + + + + + Revert database to last saved state + Reverter banco de dados para o último estado salvo + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + Essa opção é usada para reverter o atual arquivo de banco de dados para seu último estado salvo. Todas as modificações feitas desde a última operação de salvamento são perdidas. + + + + + Write changes to the database file + Salva modificações para o arquivo de banco de dados + + + + This option is used to save changes to the database file. + Essa opção é usada para salvar modificações para o arquivo de banco de dados. + + + + Ctrl+S + + + + + Compact the database file, removing space wasted by deleted records + Compactar o arquivo do banco de dados, removendo espaço desperdiçado por registros deletados + + + + + Compact the database file, removing space wasted by deleted records. + Compactar o arquivo do banco de dados, removendo espaço desperdiçado por registros deletados. + + + + E&xit + Sai&r + + + + Ctrl+Q + + + + + Import data from an .sql dump text file into a new or existing database. + Importar dados de um arquivo de texto .sql em um banco de dados. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + Essa opção deixa você importar dados de um arquivo SQL em um banco de dados. Arquivos de SQL podem ser criados na maioria dos bancos de dados, como MySQL e PostgreSQL. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Abre um assistente que permite você importar dados de um arquivo CSV em uma tabela de banco de dados. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Abre um assistente que permite você importar dados de um arquivo CSV em uma tabela de banco de dados. Arquivos CSV podem ser criados pela maioria dos programas de banco de dados e planilhas. + + + + Export a database to a .sql dump text file. + Exportar o banco de dados para um arquivo de texto .sql. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + Essa opção permite você exportar um banco de dados para um arquivo de texto .sql. Arquivos de despejo SQL contêm todos os dados necessários para recriar o banco de dados na maioria dos motores de banco de dados, incluindo MySQL e PostgreSQL. + + + + Export a database table as a comma separated text file. + Exportar uma tabela de banco de dados como um arquivo CSV. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + Exportar uma tabela de banco de dados como um arquivo CSV, pronto para ser importado por outro banco de dados ou planilhas. + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Abre o assistente de criação de tabelas, em que é possível definir o nome e os campos para uma nova tabela no banco de dados + + + + + Delete Table + Deletar tabela + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Abre o assistente de deleção de tabelas, em que você pode selecionar uma tabela para ser eliminada. + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + Abre o assistente de criação de índice, em que é possível definir um novo índice em um tabela de banco de dados já existente. + + + + &Preferences... + &Configurações... + + + + + Open the preferences window. + Abre a janela de configurações. + + + + &DB Toolbar + Barra de ferramentas do banco de &dados + + + + Shows or hides the Database toolbar. + Exibe ou oculta a barra de ferramentas do banco de dados. + + + + Shift+F1 + + + + + &Recently opened + Re&centemente aberto + + + + Ctrl+T + + + + + &Execute SQL + &Executar SQL + + + + + + Save SQL file + Salvar arquivo SQL + + + + + Execute current line + Executar linha atual + + + + Ctrl+E + + + + + Export as CSV file + Exportar como arquivo CSV + + + + Export table as comma separated values file + Exportar tabela como CSV + + + + + Save the current session to a file + Salvar a atual sessão para um arquivo + + + + + Load a working session from a file + Carregar uma sessão de um arquivo + + + + + Save SQL file as + Salvar arquivo SQL como + + + + &Browse Table + &Navegar tabela + + + + Copy Create statement + Copiar comando Create + + + + Copy the CREATE statement of the item to the clipboard + Copia o comando CREATE do item para a área de transferência + + + + Ctrl+Return + + + + + Ctrl+L + + + + + + Ctrl+P + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Reset Window Layout + Resetar layout da janela + + + + The database is currently busy. + O banco de dados está ocupado. + + + + Click here to interrupt the currently running query. + Clique aqui para interromper a consulta atual. + + + + Database encoding + Codificação do banco de dados + + + + Database is encrypted using SQLCipher + Banco de dados encriptado usando SQLCipher + + + + + Choose a database file + Escolha um arquivo de banco de dados + + + + + + Choose a filename to save under + Escolha um nome de arquivo para salvar + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + Você tem certeza de que deseja desfazer todas as modificações feitas no arquivo de banco de dados '%1' desde o último salvamento? + + + + Choose a file to import + Escolha um arquivo para importar + + + + Text files(*.sql *.txt);;All files(*) + Arquivos de texto(*.sql *.txt);;Todos os arquivos(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + Você deseja criar um novo arquivo de banco de dados para armazenar os dados importados? +Se você disser que não, tentaremos importar os dados do arquivo SQL para o banco de dados atual. + + + + Ctrl+Tab + + + + + Ctrl+Shift+Tab + + + + + Clear List + Limpar Lista + + + + Window Layout + + + + + Ctrl+0 + + + + + Simplify Window Layout + Simplificar layout da janela + + + + Alt+Shift+0 + + + + + Dock Windows at Bottom + + + + + Dock Windows at Left Side + + + + + Dock Windows at Top + + + + + Alt+Shift+W + + + + + Choose a database file to save under + + + + + Error while saving the database to the new file. + + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + Você ainda está executando comandos SQL. Fechar o banco de dados agora fará a execução parar, talvez deixando o banco de dados em um estado inconsistente. Você tem certeza de que deseja fechar o banco de dados? + + + + Do you want to save the changes made to the project file '%1'? + Você quer salvar as modificações feitas para o arquivo de projeto '%1'? + + + + Result: %1 + Resulto: %1 + + + + File %1 already exists. Please choose a different name. + Arquivo %1 já existe. Por favor, escolha um nome diferente. + + + + Error importing data: %1 + Erro importando dados: %1 + + + + Import completed. + Importação completa. + + + + Delete View + Deletar vista + + + + Delete Trigger + Deletar gatilho + + + + Delete Index + Deletar índice + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + Selecione a ação para aplicar ao %n arquivo dropado. <br/>Note que só 'Importar' vai processar mais de um arquivo. + Selecione a ação para aplicar aos %n arquivos dropados. <br/>Note que só 'Importar' vai processar mais de um arquivo. + + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + Definir valores de PRAGMA vai cometer sua transação atual. +Você tem certeza? + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + Você quer salvar as mudanças feitas nas abas de SQL no arquivo de projeto '%1'? + + + + Select SQL file to open + Selecione arquivo SQL para abrir + + + + Select file name + Selecione o nome do arquivo + + + + Select extension file + Selecione o arquivo de extensão + + + + Extension successfully loaded. + Extensão carregada com sucesso. + + + + Error loading extension: %1 + Erro carregado extensão: %1 + + + + + Don't show again + Não mostrar novamente + + + + New version available. + Nova versão disponível. + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + Uma nova vesão do DB Browser para SQLite está disponível (%1.%2.%3)<br/><br/>Por favor, baixe em <a href='%4'>%4</a>. + + + + DB Browser for SQLite project file (*.sqbpro) + Arquivo de projeto DB Browser para SQLite (*.sqbpro) + + + + SQL &Log + &Log do SQL + + + + Show S&QL submitted by + Exibir S&QL enviado por + + + + &Plot + &Plotar + + + + &Revert Changes + &Reverter modificações + + + + &Write Changes + &Escrever modificações + + + + &Database from SQL file... + &Banco de dados a partir de arquivo SQL... + + + + &Table from CSV file... + &Tabela a partir de arquivo CSV... + + + + &Database to SQL file... + &Banco de dados para arquivo SQL... + + + + &Table(s) as CSV file... + &Tabela para arquivo CSV... + + + + &Create Table... + Criar &tabela... + + + + &Delete Table... + &Deletar tabela... + + + + &Modify Table... + &Modificar tabela... + + + + Create &Index... + &Criar índice... + + + + W&hat's This? + O &que é isso? + + + + Sa&ve Project + &Salvar projeto + + + + Encrypted + Encriptado + + + + Read only + Somente leitura + + + + Database file is read only. Editing the database is disabled. + Arquivo de banco de dados é somente leitura. Edição do banco de dados está desativada. + + + + Execution finished with errors. + Execução finalizada com erros. + + + + Execution finished without errors. + Execução finalizada sem erros. + + + + Edit Database &Cell + Editar &célula do banco de dados + + + + DB Sche&ma + Esque&ma do banco de dados + + + + Open SQL file(s) + + + + + This button opens files containing SQL statements and loads them in new editor tabs + + + + + Shift+F5 + + + + + Opens the SQLCipher FAQ in a browser window + Abre o FAQ do SQLCipher em uma janela do navegador + + + + Export one or more table(s) to a JSON file + Exporta uma ou mais tabela(s) para um arquivo JSON + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + Erro enquanto salvava o banco de dados. Isso indica que nem todas as mudanças foram salvas. Você precisa resolver o seguinte erro primeiro. + +%1 + + + + &Remote + &Remoto + + + + Open an existing database file in read only mode + Abre um banco de dados existente em modo somente leitura + + + + Could not open database file. +Reason: %1 + Não pôde abrir arquivo do banco de dados. +Motivo: %1 + + + + Choose text files + Escolha arquivos de texto + + + + Modify View + Modificar vista + + + + Modify Trigger + Modificar gatilho + + + + Modify Index + Modificar índice + + + + Modify Table + Modificar tabela + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + Definir valores de PRAGMA ou fazer vacuum irá commitar sua transação atual. +Deseja continuar? + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + Essa é a estrutura do banco de dados aberto. +Você pode arrastar comandos SQL de uma linha e soltá-los em outras aplicações ou em outra instância do DB Browser para SQLite. + + + + + Temp Store + + + + + Secure Delete + + + + + Case Sensitive Like + + + + + Journal Mode + + + + + Journal Size Limit + + + + + Recursive Triggers + + + + + Page Size + + + + + Foreign Keys + Chaves estrangeiras + + + + Auto Vacuum + + + + + Max Page Count + + + + + Checkpoint Full FSYNC + + + + + + Off + + + + + + Normal + Normal + + + + + Full + + + + + Default + + + + + File + Arquivo + + + + + Memory + Memória + + + + Delete + + + + + Truncate + + + + + Persist + + + + + WAL + + + + + Exclusive + Exclusivo + + + + Automatic Index + Ãndice automático + + + + Ignore Check Constraints + + + + + Full FSYNC + + + + + WAL Auto Checkpoint + + + + + User Version + + + + + Synchronous + Síncrono + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + Alerta: esse pragma não é legível e esse valor foi inferido. Escrever o pragma pode sobrescrever um LIKE redefinido provido por uma extensão SQL. + + + + None + Nenhum + + + + Incremental + Incremental + + + + Locking Mode + + + + + Too&ls + &Ferramentas + + + + Error Log + Log de erros + + + + This button clears the contents of the SQL logs + Esse botão limpa os logs do SQL + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + Esse painel deixa você examinar um log de todos os comandos SQL dados pela aplicação ou por você + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + Essa é a estrutura do banco de dados aberto. +Você pode arrastar múltiplos nomes de objetos da coluna Nome e largá-los no editor SQL e você pode ajustar as propriedades dos nomes largados usando o menu de contexto. Isso ajudaria você a compor comandos SQL. +Você pode arrastar comandos SQL da coluna Esquema e largá-los no editor SQL ou em outras aplicações. + + + + + + Project Toolbar + Barra de ferramentas do projeto + + + + Extra DB toolbar + Barra de ferramentas do banco de dados extra + + + + + + Close the current database file + Fechar o arquivo de banco de dados aberto + + + + &New Database + &Novo banco de dados + + + + This button closes the connection to the currently open database file + Esse botão fecha a conexão com o arquivo aberto + + + + + Ctrl+F4 + + + + + &Undo + &Desfazer + + + + + Undo last change to the database + Desfaz a última mudança feita no banco de dados + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + + + + + Compact &Database... + Compactar banco de &dados... + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + + + + + &About + &Sobre + + + + New &tab + Nova a&ba + + + + This button opens a new tab for the SQL editor + Esse botão abre uma nova aba para o editor SQL + + + + Execute all/selected SQL + Executar todo/selecionado SQL + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + Esse botão executa o SQL selecionado. Se não existe SQL selecionado, todo o SQL é executado. + + + + Ctrl+Shift+T + + + + + &Load Extension... + &Carregar extensão... + + + + Execute line + Executar linha + + + + This button executes the SQL statement present in the current editor line + Esse botão executa o comando SQL presente na linha atual do editor + + + + &Wiki + &Wiki + + + + F1 + + + + + Bug &Report... + &Reportar bug... + + + + Feature Re&quest... + Re&quisitar feature... + + + + Web&site + &Site + + + + &Donate on Patreon... + &Doar no Patreon... + + + + &Save Project + &Salvar Projeto + + + + Open &Project... + Abrir &projeto... + + + + Open &Project + Abrir &projeto + + + + &Attach Database... + A&nexar banco de dados... + + + + + Add another database file to the current database connection + Adiciona outro arquivo de banco de dados para a conexão atual + + + + This button lets you add another database file to the current database connection + Esse botão deixa você adicionar outro banco de dados para a conexão atual com o banco de dados + + + + &Set Encryption... + Definir e&ncriptação... + + + + This button saves the content of the current SQL editor tab to a file + Esse botão salva o conteúdo do editor SQL para um arquivo + + + + SQLCipher &FAQ + &FAQ do SQLCipher + + + + Table(&s) to JSON... + Tabela(&s) para JSON... + + + + Open Data&base Read Only... + Abrir banco de dados somente &leitura... + + + + Ctrl+Shift+O + + + + + Save results + Salvar resultados + + + + Save the results view + Salvar a vista de resultados + + + + This button lets you save the results of the last executed query + Esse botão deixa você salvar os resultados da última consulta executada + + + + + Find text in SQL editor + Encontrar texto no editor SQL + + + + Find + Encontrar + + + + This button opens the search bar of the editor + Esse botão abre a barra de busca do editor + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + Encontrar ou substituir texto no editor SQL + + + + Find or replace + Encontrar ou substituir + + + + This button opens the find/replace dialog for the current editor tab + Esse botão abre o diálogo de encontrar/substituir para a aba atual do editor + + + + Ctrl+H + + + + + Export to &CSV + Exportar para &CSV + + + + Export to &JSON + + + + + Save as &view + Salvar como &vista + + + + Save as view + Salvar como vista + + + + Shows or hides the Project toolbar. + Mostra ou oculta a barra de ferramentos do Projeto. + + + + Extra DB Toolbar + Barra de ferramentas do banco de dados extra + + + + + Ctrl+Shift+W + + + + + Table from CSV data in Clipboard... + Tabela de dados CSV na área de transferência... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + + + + + Show &Row Counts + Mostrar quantidade de &Linhas + + + + This shows the number of rows for each table and view in the database. + + + + + Save Database &As... + Sal&var banco de dados como... + + + + Save the current database as a different file + Salvar o banco de dados atual em um arquivo diferente + + + + Refresh + Atualizar + + + + Reload the database structure + Recarrega a estrutura do banco de dados + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + Este botão lhe permite salvar todas as configurações associadas ao banco de dados aberto a um arquivo de projeto do DB Browser para SQLite + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + &Estrutura do banco de dados + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + &Ver dados + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + Editar &pragmas + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + E&xecutar SQL + + + + &Recent Files + Arquivos &Recentes + + + + This button lets you open a DB Browser for SQLite project file + Este botão lhe permite abrir um arquivo de projeto do DB Browser para SQLite + + + + &Open Database + &Abrir Banco de dados + + + + New In-&Memory Database + Nova tabela em &memória + + + + Drag && Drop SELECT Query + + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + + + + + Drag && Drop Qualified Names + Arrastar e soltar nomes qualificados + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + Use nomes qualificados (p.e. "Tabela"."Campo") quando arrastando objetos e soltando eles no editor + + + + Drag && Drop Enquoted Names + Arrastar e soltar nomes entre áspas + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + Use identificadores escapados (p.e. "Tabela1") quando arrastando e soltando objetos no editor + + + + &Integrity Check + Teste de &integridade + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + Roda o teste de integridade sobre o banco de dados aberto e retorna os resultados na aba Executar SQL. + + + + &Foreign-Key Check + Teste de chave &estrangeira + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + Roda o teste de chave estrangeira sobre o banco de dados aberto e retorna os resultados na aba Executar SQL + + + + &Quick Integrity Check + Teste de integridade &rápido + + + + Run a quick integrity check over the open DB + Roda um teste de integridade rápido sobre o banco de dados aberto + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + Roda um outro pragma para a verificação de integridade do banco de dados. Faz quase tantos testes quando o outro PRAGMA mas executa muito mais rápido. + + + + &Optimize + &Otimizar + + + + Attempt to optimize the database + Tenta otimizar o banco de dados + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + Roda o pragma de otimização sobre o banco de dados aberto. Esse pragma pode realizar otimizações que vão melhorar a performance de consultas futuras. + + + + + Print + Imprimir + + + + Print text from current SQL editor tab + Imprimir texto do editor SQL + + + + Open a dialog for printing the text in the current SQL editor tab + Abre um diálogo para imprimir o texto na aba atual do editor SQL + + + + Print the structure of the opened database + Imprime a estrutura do banco de dados aberto + + + + Open a dialog for printing the structure of the opened database + Abre um diálogo para imprimir a estrutura do banco de dados aberto + + + + Un/comment block of SQL code + Comentar bloco de SQL + + + + Un/comment block + Comentar bloco + + + + Comment or uncomment current line or selected block of code + Comentar ou remover comentário da linha ou bloco atualmente selecionado + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + Comentar ou remover comentários das linhas selecionadas ou da linha atual, se não há seleção. Todo o bloco é alterado de acordo com a primeira linha. + + + + Ctrl+/ + + + + + Stop SQL execution + Parar execução do SQL + + + + Stop execution + Parar execução + + + + Stop the currently running SQL script + Parar o script de SQL atualmente executando + + + + &Save Project As... + &Salvar projeto como... + + + + + + Save the project in a file selected in a dialog + Salvar o projeto em um arquivo selecionado em um diálogo + + + + Save A&ll + Salvar &todos + + + + + + Save DB file, project file and opened SQL files + Salvar arquivo do BD, arquivo do projeto e arquivos SQL abertos + + + + Ctrl+Shift+S + + + + + Browse Table + Navegar tabelas + + + + Close Pro&ject + Fechar pro&jeto + + + + + Close project and database files and return to the initial state + Fecha os arquivos de projeto e banco de dados e retorna para o estado inicial + + + + Ctrl+Shift+F4 + + + + + + Detach Database + + + + + + Detach database file attached to the current database connection + + + + + In-Memory database + Banco de dados em memória + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + Você tem certeza de que deseja deletar a tabela '%1'? +Todos os dados associados com a tabela serão perdidos. + + + + Are you sure you want to delete the view '%1'? + Você tem certeza que deseja deletar a vista '%1'? + + + + Are you sure you want to delete the trigger '%1'? + Você tem certeza que deseja deletar o gatilho '%1'? + + + + Are you sure you want to delete the index '%1'? + Você tem certeza que deseja deletar o índice '%1'? + + + + Error: could not delete the table. + Erro: não pôde deletar a tabela. + + + + Error: could not delete the view. + Erro: não pôde deletar a vista. + + + + Error: could not delete the trigger. + Erro: não pôde deletar o gatilho. + + + + Error: could not delete the index. + Erro: não pôde deletar o índice. + + + + Message from database engine: +%1 + Mensagem do banco de dados: +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + Editar a tabela requer salvar todas as mudanças pendentes agora. +Você tem certeza que quer salvar o banco de dados? + + + + Edit View %1 + Editar Vista %1 + + + + Edit Trigger %1 + Editar gatilho %1 + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + Você já está executando comandos SQL. Você quer pará-los para executar os comandos atuais? Fechar o banco de dados agora pode deixá-lo em um estado inconsistente. + + + + -- EXECUTING SELECTION IN '%1' +-- + -- EXECUTANDO SELEÇÃO EM '%1' +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- EXECUTANDO LINHA EM '%1' +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- EXECUTANDO TUDO EM '%1' +-- + + + + Opened '%1' in read-only mode from recent file list + + + + + Opened '%1' from recent file list + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + + + + + DB file '%1' could not be opened + + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + + + + + Table '%1' not found; settings ignored + + + + + -- Reference to file "%1" (not supported by this version) -- + + + + + Project saved to file '%1' + Projeto salvo no arquivo '%1' + + + + Yes. Don't ask again + Sim. Não perguntar novamente + + + + This action will open a new SQL tab with the following statements for you to edit and run: + Essa ação abrirá uma nova aba de SQL com os seguintes comandos para você editar e executar: + + + + Rename Tab + Renomear aba + + + + Duplicate Tab + Duplicar aba + + + + Close Tab + Fechar aba + + + + Opening '%1'... + Abrindo '%1'... + + + + There was an error opening '%1'... + Houve um erro abrindo '%1'... + + + + Value is not a valid URL or filename: %1 + Valor não é uma URL ou nome de arquivo válido: %1 + + + + %1 rows returned in %2ms + %1 linhas retornadas em %2 ms + + + + Automatically load the last opened DB file at startup + Automaticamente carregar o último BD aberto ao iniciar + + + + + At line %1: + Na linha %1: + + + + Result: %2 + Resultado: %2 + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + Importação completa. Algumas chaves estrangeiras são violadas. Por favor corrija-as antes de salvar. + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (somente leitura) + + + + Open Database or Project + Abrir banco de dados ou projeto + + + + Attach Database... + Anexar banco de dad&os... + + + + Import CSV file(s)... + Importar arquivo(s) CSV... + + + + Do you want to save the changes made to SQL tabs in a new project file? + Você quer salvar as mudanças feitas nas abas de SQL no arquivo de projeto? + + + + Do you want to save the changes made to the SQL file %1? + Você quer salvar as alterações feitas ao arquivo SQL %1? + + + + Could not find resource file: %1 + Não pôde encontrar o arquivo de recursos: %1 + + + + Choose a project file to open + Escolha um arquivo de projeto para abrir + + + + Could not open project file for writing. +Reason: %1 + Não pôde abrir arquivo de projeto para a escrita. +Motivo: %1 + + + + Collation needed! Proceed? + Função de comparação necessária! Proceder? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + Uma tabela nesse banco de dados requer uma função de comparação especial '%1' que esse aplicativo não pode prover. +So você optar por proceder, esteja avisado de que coisas ruins podem acontecer para o seu banco de dados. +Faça um backup! + + + + creating collation + criando função de comparação + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + Defina um novo nome para a aba de SQL. Use o caractere '&&' para poder usar o seguinte caractere como um atalho de teclado. + + + + Please specify the view name + Por favor, especifique o nome da vista + + + + There is already an object with that name. Please choose a different name. + Já existe um objeto com esse nome. Por favor, escolha um nome diferente. + + + + View successfully created. + Vista criada com sucesso. + + + + Error creating view: %1 + Erro criando vista: %1 + + + + This action will open a new SQL tab for running: + Essa ação irá abrir uma nova aba SQL para rodar: + + + + Press Help for opening the corresponding SQLite reference page. + Pressione Help para abrir a página de referência SQL correspondente. + + + + Busy (%1) + Ocupado (%1) + + + + Error checking foreign keys after table modification. The changes will be reverted. + Erro verificando as chaves estrangeiras após modificação. Mudanças serão revertidas. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + Essa tabela não passou um teste de chave estrangeira.<br/>Você deveria rodar 'Ferramentas | Teste de Chave Estrangeira| e corrigir os problemas reportados. + + + + NullLineEdit + + + Set to NULL + Definir como NULL + + + + Alt+Del + + + + + PlotDock + + + Plot + Plotar + + + + Columns + Colunas + + + + X + X + + + + Line type: + Tipo da linha: + + + + + None + Nenhum + + + + Line + Linha + + + + StepLeft + Passo à esquerda + + + + StepRight + Passo à direita + + + + StepCenter + Passo centralizado + + + + Impulse + Impulso + + + + Point shape: + Ponto: + + + + Cross + Cruz + + + + Plus + Mais + + + + Circle + Círculo + + + + Disc + Disco + + + + Square + Quadrado + + + + Diamond + Diamante + + + + Star + Estrela + + + + Triangle + Triângulo + + + + TriangleInverted + Triângulo Invertido + + + + CrossSquare + Cruz Quadrado + + + + PlusSquare + Mais Quadrado + + + + CrossCircle + Cruz Círculo + + + + PlusCircle + Mais Círculo + + + + Peace + Paz + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>Salvar plotagem atual...</p><p>Formato de arquivo definido pela extensão (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + Salvar plotagem atual... + + + + + + Row # + Coluna # + + + + Choose a filename to save under + Escolha um nome de arquivo para salvar + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Todos os arquivos(*) + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>Esse painel mostra a lista de colunas da tabela atualmente exibida ou a consulta recém executada. Você pode selecionar as colunas que você quer que sejam utilizadas como os eixos X e Y para o painel de plotagem abaixo. A tabela mostra o tipo detectado de exio que será utilizado na plotagem. For o eixo Y você só pode selecionar colunas numéricas, mas para o eixo X você pode selecionar:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Data/Hora</span>: strings com o formato &quot;yyyy-MM-dd hh:mm:ss&quot; ou &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Data</span>: strings com o formato &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Hora</span>: strings com o formato &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Rótulo</span>: outros formatos de string. Selecionando essa coluna como X vai produzir um gráfico de barras com as colunas como rótulos para as barras</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numérico</span>: valores inteiros ou reais</li></ul><p>Clicando duas vezes nas células Y você pode mudar a cor usada para aquele gráfico.</p></body></html> + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + Tipo do eixo + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + Aqui está um gráfico feito quando você seleciona os valores X e Y acima. + +Clique nos pontos para selecioná-los no gráfico e na tabela. Ctrl+Clique para selecionar um intervalo de pontos. + +Use o scroll do mouse para dar zoom e arraste o mouse para alterar o intervalo dos eixos. + +Selecione os eixos ou rótulos dos eixos para arrastar e dar zoom somente naquela orientação. + + + + + Load all data and redraw plot + Carregar todos os dados e plotar de novo + + + + Copy + Copiar + + + + Help + + + + + Show legend + Mostrar legenda + + + + Stacked bars + Barras empilhadas + + + + Fixed number format + + + + + Date/Time + Data/Hora + + + + Date + Data + + + + Time + Hora + + + + + Numeric + Numérico + + + + Label + Rótulo + + + + Invalid + Inválido + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + Carregar todos os dados e plotar de novo. +Aviso: nem todos os dados foram obtidos da tabela ainda devido ao mecanismo de obtenção parcial. + + + + Choose an axis color + Escolher a cor do eixo + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + Existem curvas nesse gráfico e o estilo de linha selecionado só pode ser aplicado para gráficos ordenados por X. Ou ordene a tabela ou consulte por X para remover curvas ou selecione um dos estilos suportados por curvas: Nenhum ou Linha. + + + + Loading all remaining data for this table took %1ms. + Carregar os dados restantes para essa tabela levou %1ms. + + + + Print... + Imprimir... + + + + PreferencesDialog + + + Preferences + Configurações + + + + &General + &Geral + + + + Remember last location + Lembrar do último diretório + + + + Always use this location + Sempre usar esse diretório + + + + Remember last location for session only + Lembrar do último diretório somente nessa sessão + + + + + + ... + ... + + + + Default &location + Diretório &padrão + + + + Lan&guage + &Idioma + + + + Automatic &updates + &Atualizações automáticas + + + + + + + + + + + + + + enabled + ativado + + + + &Database + &Banco de dados + + + + Database &encoding + &Codificação do banco de dados + + + + Open databases with foreign keys enabled. + Abrir bancos de dados com chaves estrangeiras ativado. + + + + &Foreign keys + &Chaves estrangeiras + + + + Data &Browser + Navegador de &dados + + + + &SQL + &SQL + + + + Context + Context + + + + Colour + Cor + + + + Bold + Negrito + + + + Italic + Itálico + + + + Underline + Underline + + + + Keyword + Palavra-chave + + + + Function + Função + + + + Table + Tabela + + + + Comment + Comentário + + + + Identifier + Identificador + + + + String + String + + + + Current line + Linha atual + + + + SQL &editor font size + Tamanho da fonte do &editor de SQL + + + + SQL editor &font + &Fonte do editor de SQL + + + + &Extensions + &Extensões + + + + Select extensions to load for every database: + Selecione extensões para carregar para todos os bancos de dados: + + + + Add extension + Adicionar extensão + + + + Remove extension + Remover extensão + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>Embora suporte o operador REGEXP, SQLite não implementa expressões regulares mas recorre ao aplicativo em execução.<br/>DB Browser para SQLite implementa esse algoritmo para você poder utilizar REGEXP.<br/>Todavia, como existem múltiplas implementações possíveis desse algoritmo e você pode querer usar outra, você pode desativar a implementação do aplicativo e carregar a sua própria implementação através de uma extensão.<br/>Requer que o programa seja reiniciado.</p></body></html> + + + + Disable Regular Expression extension + Desativar extensão de expressões regulares + + + + + Choose a directory + Escolha um diretório + + + + + The language will change after you restart the application. + A linguagem mudará após reiniciar o programa. + + + + Select extension file + Selecione arquivo de extensão + + + + Extensions(*.so *.dylib *.dll);;All files(*) + Extensões(*.so *.dylib *.dll);;Todos os arquivos(*) + + + + Save Settings File + Salvar arquivo de configurações + + + + + Initialization File (*.ini) + + + + + The settings file has been saved in location : + + + + + + Open Settings File + Abrir arquivo de configurações + + + + The settings file was loaded properly. + + + + + The selected settings file is not a normal settings file. +Please check again. + + + + + Remove line breaks in schema &view + Remover quebras de linhas em &vista de esquema + + + + Prefetch block si&ze + &Tamanho de bloco de prefetch + + + + Default field type + Tipo padrão de campo + + + + Font + Fonte + + + + &Font + &Fonte + + + + NULL + NULL + + + + Regular + Regular + + + + Binary + Binário + + + + Background + Fundo + + + + Filters + Filtros + + + + Escape character + Caractere de escape + + + + Delay time (&ms) + Tempo de delay (&ms) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + Definir o tempo de espera antes de aplicar um novo filtro de valor. Pode ser definido para zero para desativar espera. + + + + Tab size + Tamanho de tabulação + + + + Error indicators + Indicadores de erro + + + + Hori&zontal tiling + Disposição &horizontal + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + Se ativados, o editor de SQL e a tabela de resultados são exibidos lado a lado em vez de um sobre o outro. + + + + Code co&mpletion + Co&mpletação de código + + + + Show remote options + Mostrar opções remotas + + + + SQ&L to execute after opening database + SQ&L para executar após abrir o banco de dados + + + + Content + Conteúdo + + + + Symbol limit in cell + Limite de símbolos na célula + + + + Threshold for completion and calculation on selection + Limite de compleção e cálculo em seleção + + + + Show images in cell + Mostrar imagens na célula + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + Habilite essa opção para mostrar uma prévia de BLOBs contendo dados de imagens nas células. Isso pode afetar a performance do visualizados de dados. + + + + Remote + Remoto + + + + CA certificates + Certificados CA + + + + + Subject CN + Nome comum do sujeito + + + + Common Name + Nome comum + + + + Subject O + O do sujeito + + + + Organization + Organização + + + + + Valid from + Válido de + + + + + Valid to + Válido para + + + + + Serial number + Número serial + + + + Your certificates + Seus certificados + + + + File + Arquivo + + + + Subject Common Name + Nome comum do sujeito + + + + Issuer CN + CN do emissor + + + + Issuer Common Name + Nome Comum do emissor + + + + Import certificate file + Importar certificado + + + + No certificates found in this file. + Nem um certificado encontrado nesse arquivo. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + Você tem certeza de que deseja remover esse certificado? Todos os dados do certificado serão deletados das configurações da aplicação! + + + + Clone databases into + Clonar bancos de dados em + + + + Toolbar style + Estilo da barra de ferramentas + + + + + + + + Only display the icon + Exibir apenas o ícone + + + + + + + + Only display the text + Exibir apenas o texto + + + + + + + + The text appears beside the icon + O texto aparece ao lado do ícone + + + + + + + + The text appears under the icon + O texto aparece sob o ícone + + + + + + + + Follow the style + Seguir o estilo + + + + DB file extensions + Extensões de arquivo de bancos de dados + + + + Manage + Gerenciar + + + + Main Window + Janela principal + + + + Database Structure + Estrutura do banco de dados + + + + Browse Data + Navegar dados + + + + Execute SQL + Executar SQL + + + + Edit Database Cell + Editar célula do banco de dados + + + + When this value is changed, all the other color preferences are also set to matching colors. + Quando este valor é alterado, todas as outras preferências de cor são definidas para cores compatíveis. + + + + Follow the desktop style + Seguir o estilo do desktop + + + + Dark style + Estilo escuro + + + + Application style + Estilo da aplicação + + + + This sets the font size for all UI elements which do not have their own font size option. + + + + + Font size + + + + + Max Recent Files + + + + + Prompt to save SQL tabs +in new project file + + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + + + + + Database structure font size + + + + + Font si&ze + &Tamanho da fonte + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + Esse é o número máximo de itens permitidos para que algumas funcionalidades computacionalmente caras sejam habilitadas: +Número máximo de linhas em uma tabela para habilitar compleção de valores baseada nos valores atualmente na coluna. +Número máximo de índices em uma seleção para se calcular soma e média. +Pode ser deixado em 0 para se desabilitar as funcionalidades. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + Esse é o número máximo de linhas na tabela para preencher baseado nos valores atualmente na coluna. +Pode ser 0 para desabilitar preenchimento. + + + + Field display + Exibição do campo + + + + Light style + + + + + Displayed &text + &Texto exibido + + + + Formatted + + + + + + + + + + + + Click to set this color + Clique para definir essa cor + + + + Text color + Cor do texto + + + + Background color + Cor do plano de fundo + + + + + Preview only (N/A) + Somente prévia (N/D) + + + + Foreground + Plano de frente + + + + Selection background + + + + + Selection foreground + + + + + Highlight + + + + + SQL &results font size + Tamanho da fonte dos &resultados do SQL + + + + Use tabs for indentation + + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + + + + + &Wrap lines + &Quebra de linhas + + + + Never + Nunca + + + + At word boundaries + Nos limites de palavras + + + + At character boundaries + Nos limites de caractere + + + + At whitespace boundaries + Nos limites de espaço em branco + + + + &Quotes for identifiers + Ãspas &para identificadores + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + Escolha as áspas utilizadas pela aplicação para identificadores no código SQL. + + + + "Double quotes" - Standard SQL (recommended) + "Ãspas duplas" - SQL Padrão (recomendado) + + + + `Grave accents` - Traditional MySQL quotes + `Crases`- MySQL tradicional + + + + [Square brackets] - Traditional MS SQL Server quotes + [Colchetes] - MS SQL Server tradicional + + + + Keywords in &UPPER CASE + Palavras-chave em &CAIXA ALTA + + + + When set, the SQL keywords are completed in UPPER CASE letters. + Quando definido, as palavras-chave SQL serão completadas em CAIXA ALTA. + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + Quando definido, as linhas de código SQL que causaram erros durante a última execução são destacadas e os resultados indicam os erros no fundo + + + + Close button on tabs + + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + + + + + Select built-in extensions to load for every database: + + + + + Proxy + Proxy + + + + Configure + Configurar + + + + Export Settings + + + + + Import Settings + + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + Você tem certeza que deseja limpar as configurações salvas? +Todas as suas preferências serão perdidas e os valores padrão serão utilizados. + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + Quando ativado, as quebras de linha na coluna Esquema da aba Estrutura do banco de dados e nas saídas impressas são removidas. + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite provê uma função SQL para carregar extensões de um arquivo de biblioteca. Ative isso se você quer usar a função <span style=" font-style:italic;">load_extension()</span> a partir de código SQL.</p><p>Por motivos de segurança, carregamento de extensões é desabilitado por padrão e precisa ser habilitado através dessa configuração. Você sempre pode carregar extensões através da interface gráfica, mesmo com essa opção desabilitada.</p></body></html> + + + + Allow loading extensions from SQL code + Permitir o carregamento de extensões a partir de código SQL + + + + ProxyDialog + + + Proxy Configuration + Configuração do proxy + + + + Pro&xy Type + Tipo do pro&xy + + + + Host Na&me + No&me do host + + + + Port + Porta + + + + Authentication Re&quired + Au&tenticação necessária + + + + &User Name + Nome do &usuário + + + + Password + Senha + + + + None + Nenhum + + + + System settings + Configurações do sistema + + + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 + + + + QObject + + + Error importing data + Erro importando dados + + + + from record number %1 + a partir de registro número %1 + + + + . +%1 + . +%1 + + + + Cancel + Cancelar + + + + All files (*) + Todos arquivos (*) + + + + Importing CSV file... + Importando arquivo CSV... + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + Bancos de dados SQLite (*.db *.sqlite *.sqlite3 *.db3) + + + + Left + Esquerda + + + + Right + Direita + + + + Center + Centro + + + + Justify + Justificar + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + Arquivos de banco de dados SQL (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + Arquivo de projeto DB Browser para SQLite (*.sqbpro) + + + + SQL Files (*.sql) + Arquivos SQL (*.sql) + + + + All Files (*) + Todos arquivos (*) + + + + Text Files (*.txt) + Arquivos de texto (*.txt) + + + + Comma-Separated Values Files (*.csv) + Arquivos de valores separados por vírgulas (*.csv) + + + + Tab-Separated Values Files (*.tsv) + Arquivos de valores separados por tabs (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + Arquivos de valores separados por delimitadores (*.dsv) + + + + Concordance DAT files (*.dat) + Arquivos DAT Concordance (*.dat) + + + + JSON Files (*.json *.js) + Arquivos JSON (*.json) + + + + XML Files (*.xml) + Arquivos XML (*.xml) + + + + Binary Files (*.bin *.dat) + Arquivos binários (*.bin) + + + + SVG Files (*.svg) + Arquivos SVG (*.svg) + + + + Hex Dump Files (*.dat *.bin) + Arquivos de dump hexadecimal (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + Extensões (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + + + + + QsciCommand + + Paste + Colar + + + Cancel + Cancelar + + + + QsciLexerCPP + + Keyword + Palavra-chave + + + Identifier + Identificador + + + + QsciLexerJSON + + String + String + + + + QsciLexerJavaScript + + Regular expression + Expressão regular + + + + QsciLexerPython + + Comment + Comentário + + + Keyword + Palavra-chave + + + Identifier + Identificador + + + + QsciLexerSQL + + Comment + Comentário + + + Keyword + Palavra-chave + + + Identifier + Identificador + + + + QsciScintilla + + Select All + Selecionar tudo + + + + RemoteCommitsModel + + + Commit ID + + + + + Message + + + + + Date + Data + + + + Author + + + + + Size + Tamanho + + + + Authored and committed by %1 + + + + + Authored by %1, committed by %2 + + + + + RemoteDatabase + + + Error opening local databases list. +%1 + Erro abrindo lista local de bancos de dados. +%1 + + + + Error creating local databases list. +%1 + Erro criando lista local de bancos de dados. +%1 + + + + RemoteDock + + + Remote + Remoto + + + + Local + Local + + + + Identity + Identidade + + + + Push currently opened database to server + Enviar o banco de dados aberto para o servidor + + + + Upload + + + + + DBHub.io + + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>Neste painel, bancos de dados remotos do dbhub.io podem ser adicionados ao DB Browser para SQLite. Primeiro você precisa adicionar uma identidade:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Entrar no dbhub.io (use suas credenciais do GitHub ou algum outro método)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Clique o botão para &quot;Gerar certificado do cliente&quot; (essa é sua identidade). Isto te dará um certificado (salve-o no disco local).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Vá para a aba Remoto nas configurações do DB Browser para SQLite. Clique no botão para adicionar um novo certificado ao DB Browser para SQLite e escolha o arquivo recém baixado.</li></ol><p>Agora o painel remoto mostra sua identidade e você pode adicionar bancos de dados remotos.</p></body></html> + + + + Current Database + + + + + Clone + + + + + &User + + + + + &Database + &Banco de dados + + + + Branch + Ramo + + + + Commits + + + + + Commits for + + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>Você está utilizando uma identidade somente leitura. Para fazer upload do seu banco de dados, você precisa configurar e usar a sua conta no DBHub.io.</p><p>Se você ainda não tem uma conta no DBHub, <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">crie uma agora</span></a> e importe seu certificado <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">aqui</span></a> para compartilhar os seus bancos de dados.</p><p>Para ajuda online, visite <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">este link</span></a>.</p></body></html> + + + + Back + Voltar + + + + Delete Database + + + + + Delete the local clone of this database + + + + + Open in Web Browser + + + + + Open the web page for the current database in your browser + + + + + Clone from Link + + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + + + + + Refresh + Atualizar + + + + Reload all data and update the views + + + + + Clone Database + + + + + Open Database + + + + + Open the local copy of this database + + + + + Check out Commit + + + + + Download and open this specific commit + + + + + Check out Latest Commit + + + + + Check out the latest commit of the current branch + + + + + Save Revision to File + + + + + Saves the selected revision of the database to another file + + + + + Upload Database + + + + + Upload this database as a new commit + + + + + Select an identity to connect + + + + + Public + Público + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + + + + + Invalid URL: The host name does not match the host name of the current identity. + + + + + Invalid URL: No branch name specified. + + + + + Invalid URL: No commit ID specified. + + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + + + + + The database has unsaved changes. Are you sure you want to push it before saving? + + + + + The database you are trying to delete is currently opened. Please close it before deleting. + + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + + + + + RemoteLocalFilesModel + + + Name + Nome + + + + Branch + Ramo + + + + Last modified + Última modificação + + + + Size + Tamanho + + + + Commit + Commit + + + + File + Arquivo + + + + RemoteModel + + + Name + Nome + + + + Last modified + Última modificação + + + + Size + Tamanho + + + + Size: + + + + + Last Modified: + + + + + Licence: + + + + + Default Branch: + + + + + Commit + Commit + + + + RemoteNetwork + + + Choose a location to save the file + + + + + Error opening remote file at %1. +%2 + Erro abrindo arquivo remoto em %1. +%2 + + + + Error: Invalid client certificate specified. + Erro: Certificado de cliente inválido especificado. + + + + Please enter the passphrase for this client certificate in order to authenticate. + Por favor entre a frase chave para esse certificado de cliente para se autenticar. + + + + Cancel + Cancelar + + + + Uploading remote database to +%1 + Enviando banco de dados remoto para +%1 + + + + Downloading remote database from +%1 + Baixando banco de dados remoto de +%1 + + + + Error: Cannot open the file for sending. + Erro: Não pôde abrir o arquivo para envio. + + + + RemotePushDialog + + + Push database + Enviar banco de dados + + + + Database na&me to push to + No&me do banco de dados para enviar + + + + Commit message + Mensagem de commit + + + + Username + + + + + Database licence + Licença do banco de dados + + + + Public + Público + + + + Database will be public. Everyone has read access to it. + Banco de dados será público. Todos poderão lê-lo. + + + + Database will be private. Only you have access to it. + Banco de dados será privado. Somente você terá acesso a ele. + + + + Branch + Ramo + + + + Force push + Forçar envio + + + + Use with care. This can cause remote commits to be deleted. + Use com cuidado. Isso pode causar a perda de commits remotos. + + + + RunSql + + + Execution aborted by user + Execução abortada pelo usuário + + + + , %1 rows affected + , %1 linhas afetadas + + + + query executed successfully. Took %1ms%2 + consulta executada com sucesso. Levou %1ms%2 + + + + executing query + executando consulta + + + + SelectItemsPopup + + + A&vailable + &Disponível + + + + Sele&cted + &Selecionado + + + + SqlExecutionArea + + + Form + Formulário + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>Resultados dos últimos comandos executados.</p><p>Você pode querer colapsar esse painel e usar o dock <span style=" font-style:italic;">Log SQL</span> com seleção <span style=" font-style:italic;">Usuário</span> em vez disso.</p></body></html> + + + + Results of the last executed statements + Resultados dos últimos comandos executados + + + + This field shows the results and status codes of the last executed statements. + Esse campo mostra os resultados e códigos de status dos últimos comandos executados. + + + + Find previous match [Shift+F3] + Encontrar resultado anterior [Shift+F3] + + + + Find previous match with wrapping + Encontrar resultado anterior com mapeamento + + + + Shift+F3 + + + + + The found pattern must be a whole word + O padrão encontrado precisa ser uma palavra inteira + + + + Whole Words + Palavras inteiras + + + + Text pattern to find considering the checks in this frame + Padrão de texto para encontrar considerando os testes nesse frame + + + + Find in editor + Encontrar no editor + + + + The found pattern must match in letter case + O padrão encontrado precisa casar em capitalização + + + + Case Sensitive + Sensível à capitalização + + + + Find next match [Enter, F3] + Encontrar próxima correspondência [Enter, F3] + + + + Find next match with wrapping + Encontrar próxima correspondência no arquivo inteiro + + + + F3 + + + + + Interpret search pattern as a regular expression + Interpretar padrão de busca como expressão regular + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Quando assinalado, o padrão a ser buscado é interpretado como uma expressão regular UNIX. Veja <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression nos Wikibooks</a>.</p></body></html> + + + + Regular Expression + Expressão Regular + + + + + Close Find Bar + Fechar barra de busca + + + + Ctrl+PgUp + + + + + Ctrl+PgDown + + + + + Couldn't read file "%1": %2. + + + + + + Couldn't save file: %1. + Não pôde salvar arquivo: %1. + + + + Your changes will be lost when reloading it! + Suas modificações serão perdidas quando recarregando! + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + O arquivo "%1" foi modificado por outro programa. Você quer recarregá-lo?%2 + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + + + + + Answer "No to All" to ignore any external update without further prompting. + + + + + Modifying and saving the file will restore prompting. + + + + + SqlTextEdit + + + Ctrl+/ + + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) A função abs(X) retorna o valor absoluto do argumento numérico X. + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + + + + + (X) ltrim(X) removes spaces from the left side of X. + + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + + + + + (X) rtrim(X) removes spaces from the right side of X. + + + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + + + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + + + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + + + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + + + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + + + + + (X) trim(X) removes spaces from both ends of X. + + + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + + + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + + + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + + + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + + + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + + + + + + + + (timestring,modifier,modifier,...) + + + + + (format,timestring,modifier,modifier,...) + + + + + (X) The avg() function returns the average value of all non-NULL X within a group. + + + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + + + + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + + + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + + + + + (X) The max() aggregate function returns the maximum value of all values in the group. + + + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + + + + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () O número de linhas dentro da partição atual. Linhas são numeradas de 1 na ordem definida pela cláusula ORDER BY na definição da janela, ou de forma arbitrária. + + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () O row_number() do primeiro elemento de cada grupo - o rank da linha atual com gaps. Se não há uma cláusula ORDER BY, então todas as linhas são consideradas elementos e essa função sempre retorna 1. + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () O número do grupo de colegas da linha atual dentro da sua partição - o rank da linha atual sem intervalos. Partições são numeradas a partir de 1 na ordem definida pela cláusula ORDER BY na definição. Se não há ORDER BY, então todas as linhas são consideradas colegas e essa função sempre retorna 1. + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () Apesar do nome, essa função sempre retorna um valor entre 0.0 e 1.0 igual a (rank - 1)/(linhas-na-partição - 1), onde rank é o valor retornado pela built-in rank() e linhas-na-partição é o número total de linhas na partição. Se a partição contém somente uma linha, essa função retorna 0. + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () A distribuição cumulativa. Calculada como número-da-linha/linhas-na-partição em que número-da-linha é o valor retornado por row_number() para o último elemento do grupo e linhas-na-partição é o número de linhas na partição. + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) Argumento N é interpretado como um inteiro. Essa função divide a partição em N grupos tão igualmente como possível e atribui um inteiro entre 1 e N para cada grupo, na ordem definida pela cláusula ORDER BY, ou em ordem arbitrária. Se necessário, grupos maiores ocorrem primeiro. Essa função retorna o valor inteiro atribuido ao grupo que a linha atual é parte de. + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) Retorna o resultado de avaliar expressão expr contra a linha anterior na partição. Ou, se não há linha anterior, NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr,offset) Se o offset é fornecido, então ele precisa ser um inteiro não-negativo. Nesse caso, o valor retornado é o resultado de avaliar expr contra a linha offset linhas antes da linha atual dentro da partição. Se offset é 0, então expr é avaliada contra a linha atual. Se não há linha offset linhas antes da linha atual, NULL é retornado. + + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,offset,default) Se default também é fornecido, ele é retornado em vez de NULL se a linha identificada por offset não existe. + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) Retorna o resultado de avaliar a expressão expr contra a próxima linha na partição. Ou, se não há próxima linha, NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,offset) Se o offset é fornecido, então ele precisa ser um inteiro não-negativo. Nesse caso, o valor retornado é o resultado de avaliar expr contra a linha offset linhas após a linha atual dentro da partição. Se offset é 0, então expr é avaliada contra a linha atual. Se não há linha offset linhas após a linha atual, NULL é retornado. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) Essa função de janela built-in calcula o frame da janela para cada linha na mesma forma que uma função de janela agregada. Ela retorna o valor de expr avaliada contra a primeira linha do frame da janela para cada linha. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) Essa função de janela built-in calcula o frame da janela para cada linha na mesma forma que uma função de janela agregada. Ela retorna o valor de expr avaliada contra a última linha do frame da janela para cada linha. + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr) Essa função de janela built-in calcula o frame da janela para cada linha na mesma forma que uma função de janela agregada. Ela retorna o valor de expr avaliada contra a linha N do frame da janela para cada linha.Linhas são numeradas dentro do frame da janela começando em 1 na ordem definida pela cláusula ORDER BY se uma está presente, ou em ordem arbitrária, caso contrário. Se não há uma N-ésima linha na partição, NULL é retornado. + + + + (X) Return the arccosine of X. The result is in radians. + + + + + (X) Return the hyperbolic arccosine of X. + + + + + (X) Return the arcsine of X. The result is in radians. + + + + + (X) Return the hyperbolic arcsine of X. + + + + + (X) Return the arctangent of X. The result is in radians. + + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + + + + + (X) Return the hyperbolic arctangent of X. + + + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + + + + + (X) Return the cosine of X. X is in radians. + + + + + (X) Return the hyperbolic cosine of X. + + + + + (X) Convert value X from radians into degrees. + + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + + + + + (X) Return the natural logarithm of X. + + + + + (B,X) Return the base-B logarithm of X. + + + + + + (X) Return the base-10 logarithm for X. + + + + + (X) Return the logarithm base-2 for the number X. + + + + + (X,Y) Return the remainder after dividing X by Y. + + + + + () Return an approximation for Ï€. + + + + + + (X,Y) Compute X raised to the power Y. + + + + + (X) Convert X from degrees into radians. + + + + + (X) Return the sine of X. X is in radians. + + + + + (X) Return the hyperbolic sine of X. + + + + + (X) Return the square root of X. NULL is returned if X is negative. + + + + + (X) Return the tangent of X. X is in radians. + + + + + (X) Return the hyperbolic tangent of X. + + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) A função load_extension(X) carrega extensões para SQLite a partir de um arquivo chamado X. +Uso dessa função precisa ser autorizado em Preferências. + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) A função load_extension(X) carrega extensões para SQLite a partir de um arquivo chamado X usando o ponto de entrada Y. +Uso dessa função precisa ser autorizado em Preferências. + + + + SqliteTableModel + + + Error changing data: +%1 + Erro modificando dados: +%1 + + + + reading rows + lendo linhas + + + + loading... + carregando... + + + + References %1(%2) +Hold %3Shift and click to jump there + Referencia %1(%2) +Segure %3Shift e clique para ir para lá + + + + retrieving list of columns + obtendo lista de colunas + + + + Fetching data... + Obtendo dados... + + + + + Cancel + Cancelar + + + + TableBrowser + + + Browse Data + Navegar dados + + + + &Table: + &Tabela: + + + + Select a table to browse data + Selecione uma tabela para navegar + + + + Use this list to select a table to be displayed in the database view + Use esta lista para selecionar uma tabela para ser exibida na vista do banco de dados + + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + Essa é a vista de tabela do banco de dados. Você pode fazer as seguintes ações: + - Começar a escrever para editar o valor. + - Clicar duas vezes em qualquer registro para editar seus conteúdos no editor de célula. + - Alt+Del para deletar o conteúdo da célula para NULL. + - Ctrl+" para duplicar o registro atual. + - Ctrl+' para copiar o valor da célula de cima. + - Seleção normal para copiar e colar. + + + + Text pattern to find considering the checks in this frame + Padrão de texto para encontrar considerando os testes nesse frame + + + + Find in table + Encontrar na tabela + + + + Find previous match [Shift+F3] + Encontrar resultado anterior [Shift+F3] + + + + Find previous match with wrapping + Encontrar resultado anterior com mapeamento + + + + Shift+F3 + + + + + Find next match [Enter, F3] + Encontrar próxima correspondência [Enter, F3] + + + + Find next match with wrapping + Encontrar próxima correspondência com quebra de linha + + + + F3 - (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. - + + The found pattern must match in letter case + O padrão encontrado precisa casar em capitalização + + + + Case Sensitive + Sensível à capitalização + + + + The found pattern must be a whole word + O padrão encontrado precisa ser uma palavra inteira + + + + Whole Cell + Célula inteira + + + + Interpret search pattern as a regular expression + Interpretar padrão de busca como expressão regular + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Quando marcado, o padrão para ser encontrado é interpretado como uma expressão regular do UNIX. Veja <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + Regular Expression + Expressão regular + + + + + Close Find Bar + Fechar barra de busca + + + + Text to replace with + Texto para substituir com + + + + Replace with + Substituir com + + + + Replace next match + Substituir próxima correspondência + + + + + Replace + Substituir + + + + Replace all matches + Substituir todas as correspondências + + + + Replace all + Substituir todos + + + + Export to &JSON + Exportar para &JSON + + + + + Export the filtered data to JSON + Exporta os dados filtrados para JSON + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + + + + + Copy column name + Copiar nome da coluna + + + + Copy the database table column name to your clipboard + + + + + New Data Browser + + + + + + Add a new docked Data Browser + Adicionar nova aba de ver dados + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + Este botão adiciona uma nova aba para ver dados, que você pode desacoplar e organizar em layouts diferentes. + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>Rolar para o começo</p></body></html> + + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>Clicar nesse botão navega até o começo da vista de tabela acima.</p></body></html> + + + + |< + |< + + + + Scroll one page upwards + Rolar uma página para cima + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>Clicando nesse botão navega uma página de registros para cima.</p></body></html> + + + + < + < + + + + 0 - 0 of 0 + 0 - 0 de 0 + + + + Scroll one page downwards + Rolar uma página para baixo + + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>Clicando nesse botão navega uma página de registros para baixo.</p></body></html> + + + + > + > + + + + Scroll to the end + Rolar para o fim + + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>Clicar nesse botão navega para o fim da tabela acima.</p></body></html> - (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. - + + >| + >| - (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. - + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>Clique aqui para pular para o registro especificado</p></body></html> - (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. - + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>Esse botão navega para o registro especificado na área Ir para.</p></body></html> - (X) rtrim(X) removes spaces from the right side of X. - + + Go to: + Ir para: - (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. - + + Enter record number to browse + Entre o número do registro para navegar - (X) The soundex(X) function returns a string that is the soundex encoding of the string X. - + + Type a record number in this area and click the Go to: button to display the record in the database view + Digite o número de um registro nessa área e clique no botão Ir para: para exibir o registro na vista do banco de dados - (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. - + + 1 + 1 - (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. - + + Show rowid column + Mostrar coluna rowid - () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. - + + Toggle the visibility of the rowid column + Alternar a visibilidade da coluna rowid - (X) trim(X) removes spaces from both ends of X. - + + Unlock view editing + Liberar edição da vista - (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. - + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + Isso libera a vista atual para edição. Todavia, você vai precisar dos gatilhos apropriados para editar. - (X) The typeof(X) function returns a string that indicates the datatype of the expression X. - + + Edit display format + Editar formato de exibição - (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. - + + Edit the display format of the data in this column + Editar o formato de exibição dos dados nessa coluna - (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. - + + + New Record + Novo registro - (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. - + + + Insert a new record in the current table + Inserir um novo registro na tabela atual - (timestring,modifier,modifier,...) - + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>Esse botão cria um novo registro no banco de dados. Segure o botão do mouse para abrir um menu de opções diferentes:</p><ul><li><span style=" font-weight:600;">Novo Registro</span>: insere um novo registro com valores padrão no banco de dados.</li><li><span style=" font-weight:600;">Inserir Valores...</span>: abre um diálogo para novos valores antes de serem inseridos no banco de dados. Isso permite a entrada de valores de acordo com as restrições. Esse diálogo também é abaerto se a opção<span style=" font-weight:600;">Novo Registro</span> falha devido a essas restrições.</li></ul></body></html> - (format,timestring,modifier,modifier,...) - + + + Delete Record + Deletar registro - (X) The avg() function returns the average value of all non-NULL X within a group. + + Delete the current record + Deletar o registro atual + + + + + This button deletes the record or records currently selected in the table + Esse botão deleta o registro ou registros selecionados + + + + + Insert new record using default values in browsed table + Inserir novo registro usando valores padrão na tabela + + + + Insert Values... + Inserir valores... + + + + + Open a dialog for inserting values in a new record + Abre um diálogo para inserir valores em um novo registro + + + + Export to &CSV + Exportar para &CSV + + + + + Export the filtered data to CSV + Exportar dados filtrados para CSV + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + Esse botão exporta os dados da tabela como atualmente exibidos como um arquivo CSV. + + + + Save as &view + Salvar como &vista + + + + + Save the current filter, sort column and display formats as a view + Salva o filtro, ordenação e formato como uma vista + + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + Esse botão salva as configurações da tabela exibida como uma vista SQL que você pode utilizar em comandos SQL depois. + + + + Save Table As... + Salvar tabela como... + + + + + Save the table as currently displayed + Salva a tabela como atualmente exibida + + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>Esse Menu provê as seguintes opções para a tabela atual:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Exportar para CSV: essa opção exporta os dados como estão exibidos para um arquivo CSV.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Salvar como vista: essa opção salva a configuração atual da tabela como uma vista SQL que você depois pode consultar em comandos SQL.</li></ul></body></html> + + + + Hide column(s) + Ocultar coluna(s) + + + + Hide selected column(s) + Ocultar coluna(s) selecionada(s) + + + + Show all columns + Mostrar todas as colunas + + + + Show all columns that were hidden + Mostrar todas as colunas ocultas + + + + + Set encoding + Definir codificação + + + + Change the encoding of the text in the table cells + Modificar a codificação do texto nas células da tabela + + + + Set encoding for all tables + Modificar codificação para todas as tabelas + + + + Change the default encoding assumed for all tables in the database + Modificar a codificação padrão assumida para todas as tabelas no banco de dados + + + + Clear Filters + Limpar filtros + + + + Clear all filters + Limpar todos os filtros + + + + + This button clears all the filters set in the header input fields for the currently browsed table. + Esse botão limpa todos os filtros definidos no cabeçalho para a tabela atualmente navegada. + + + + Clear Sorting + Limpar ordenamento + + + + Reset the order of rows to the default + Resetar a ordem das linhas para o padrão + + + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + Esse botão limpa o ordenamento especificado para a tabela atual e volta para a ordem padrão. + + + + Print + Imprimir + + + + Print currently browsed table data + Imprimir dados da tabela atual + + + + Print currently browsed table data. Print selection if more than one cell is selected. + Imprimir dados da tabela atual. Imprime a seleção se mais de uma célula está selecionada. + + + + Ctrl+P - (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + + Refresh + Atualizar + + + + Refresh the data in the selected table + Atualizar os dados na tabela selecionada + + + + This button refreshes the data in the currently selected table. + Este botão atualiza os dados na tabela atualmente selecionada. + + + + F5 - (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + + Find in cells + Encontrar em células + + + + Open the find tool bar which allows you to search for values in the table view below. + Abre a barra de ferramentas para buscar que permite que você busque por valores na vista da tabela abaixo. + + + + Freeze columns + + + + + Make all columns from the first column up to this column not move when scrolling horizontally + + + + + + Bold + Negrito + + + + Ctrl+B - (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + + + Italic + Itálico + + + + + Underline + Sublinhado + + + + Ctrl+U - (X) The max() aggregate function returns the maximum value of all values in the group. + + + Align Right + Alinhar à direita + + + + + Align Left + Alinhar à esquerda + + + + + Center Horizontally + Centralizar horizontalmente + + + + + Justify + Justificar + + + + + Edit Conditional Formats... + Editar formatos condicionais... + + + + Edit conditional formats for the current column + Editar os formatos condicionais para a coluna atual + + + + Clear Format + Limpar formato + + + + Clear All Formats + Limpar todos os formatos + + + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + Limpa toda a formatação das células selecionadas e todos os formatos condicionais das colunas selecionadas + + + + + Font Color + Cor do texto + + + + + Background Color + Cor do plano de fundo + + + + Toggle Format Toolbar + Alterar barra de ferramentas de formatação + + + + Show/hide format toolbar + Mostrar/esconder barra de ferramentas de formatação + + + + + This button shows or hides the formatting toolbar of the Data Browser + Esse botão mostra ou esconde a barra de ferramentas de formatação do navegador de dados + + + + Select column + Selecionar coluna + + + + Ctrl+Space - (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + + Replace text in cells + Substituir texto em células + + + + Filter in any column + Filtrar em qualquer coluna + + + + Ctrl+R + + + %n row(s) + + %n linha(s) + %n linhas + + + + + , %n column(s) + + , %n coluna(s) + , %n colunas + + - (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . Soma: %1; Média: %2; Mínimo: %3; Máximo: %4 + + + + Conditional formats for "%1" + Formatos condicionais para "%1" + + + + determining row count... + determinando número de linhas... + + + + %L1 - %L2 of >= %L3 + + + + + %L1 - %L2 of %L3 + + + + + (clipped at %L1 rows) + + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + Por favor, entre uma pseudo-chave primária para habilitar edição nessa vista. Isso deveria ser o nome de uma coluna única na vista. + + + + Delete Records + Deletar registros + + + + Duplicate records + Duplicar registros + + + + Duplicate record + Duplicar registro + + + + Ctrl+" - - - SqliteTableModel - Error changing data: + + Adjust rows to contents + Ajustar linhas aos conteúdos + + + + Error deleting record: %1 - Erro modificando dados: + Erro deletando registro: %1 + + + Please select a record first + Por favor, selecione um registro primeiro + + + + Please choose a new encoding for all tables. + Por favor, escolha uma nova codificação para todas tabelas. + + + + Please choose a new encoding for this table. + Por favor, escolha uma nova codificação para essa tabela. + + + + %1 +Leave the field empty for using the database encoding. + %1 +Deixe o campo em branco para usar a codificação do banco de dados. + + + + This encoding is either not valid or not supported. + Essa codificação é inválida ou não suportada. + + + + %1 replacement(s) made. + %1 substituição(ões) feita(s). + + + + TableBrowserDock + + + New Data Browser + + + + + Rename Data Browser + + + + + Close Data Browser + + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + + VacuumDialog + Compact Database - Compactar Banco de Dados + Compactar banco de dados - Warning: Compacting the database will commit all changes you made. - Alerta: compactar o banco de dados confirmará todas as alterações feitas. + + Warning: Compacting the database will commit all of your changes. + Alerta: compactando o banco de dados irá confirmar todas as suas modificações. - Please select the objects to compact: - Por favor, selecione os objetos que deseja compactar: + + Please select the databases to co&mpact: + Por favor selecione o banco de dados para co&mpactar: diff --git a/src/translations/sqlb_ro.ts b/src/translations/sqlb_ro.ts new file mode 100644 index 000000000..bc45cf82c --- /dev/null +++ b/src/translations/sqlb_ro.ts @@ -0,0 +1,8099 @@ + + + + + AboutDialog + + + About DB Browser for SQLite + Despre DB Browser for SQLite + + + + Version + Versiune + + + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + + + + + AddRecordDialog + + + Add New Record + Adaugă ÃŽnregistrare Nouă + + + + Enter values for the new record considering constraints. Fields in bold are mandatory. + IntroduceÈ›i valori pentru noua înregistrare luând în considerare constrângerile. Câmpurile îngroÈ™ate sunt obligatorii. + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + ÃŽn coloana Valoare puteÈ›i specifica valoarea pentru câmpul identificat în coloana Nume. Coloana Tip indică tipul câmpului. Valorile implicite sunt afiÈ™ate în acelaÈ™i stil ca È™i valorile NULL. + + + + Name + Nume + + + + Type + Tip + + + + Value + Valoare + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + Valori de inserat. Valorile implicite precompletate sunt inserate automat, cu excepÈ›ia cazului în care sunt modificate. + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + Când editaÈ›i valorile din cadrul superior, interogarea SQL pentru inserarea acestei noi înregistrări este afiÈ™ată aici. PuteÈ›i edita manual interogarea înainte de a salva. + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Salvează</span> va trimite instrucÈ›iunea SQL afiÈ™ată către baza de date pentru a insera noua înregistrare.</p><p><span style=" font-weight:600;">Restabilire Implicite</span> va restabili valorile iniÈ›iale din coloana<span style=" font-weight:600;">Valoare</span></p><p><span style=" font-weight:600;">Anulează</span> va închide acest dialog fără a executa interogarea.</p></body></html> + + + + Auto-increment + + Incrementare automată + + + + + Unique constraint + + Constrângere unică + + + + + Check constraint: %1 + + Verificare constrângere: %1 + + + + + Foreign key: %1 + + Cheie străină: %1 + + + + + Default value: %1 + + Valoare implicită: %1 + + + + + Error adding record. Message from database engine: + +%1 + Eroare la adăugarea înregistrării. Mesaj de la motorul bazei de date: + +%1 + + + + Are you sure you want to restore all the entered values to their defaults? + Sigur doriÈ›i să restauraÈ›i toate valorile introduse la valorile implicite? + + + + Application + + + Possible command line arguments: + Posibile argumente ale liniei de comandă: + + + + + The file %1 does not exist + FiÈ™ierul %1 nu există + + + + The user settings file location is replaced with the argument value instead of the environment variable value. + LocaÈ›ia fiÈ™ierului de setări al utilizatorului este înlocuită cu valoarea argumentului în loc de valoarea variabilei de mediu. + + + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + Valoare variabilă de mediu (DB4S_SETTINGS_FILE) ignorată: + + + + Usage + Utilizare + + + + options + opÈ›iuni + + + + + database + bază de date + + + + + project + proiect + + + + + csv-file + fiÈ™ier-csv + + + + Show command line options + AfiÈ™ează opÈ›iunile liniei de comandă + + + + Exit application after running scripts + IeÈ™ire din aplicaÈ›ie după rularea scripturilor + + + + + file + fiÈ™ier + + + + Execute this SQL file after opening the DB + Execută acest fiÈ™ier SQL după deschiderea BD + + + + Import this CSV file into the passed DB or into a new DB + Importă acest fiÈ™ier CSV în baza de date transmisă sau într-o bază de date nouă + + + + table + tabel + + + + Browse this table, or use it as target of a data import + RăsfoieÈ™te acest tabel sau utilizează-l ca È›intă a unui import de date + + + + Open database in read-only mode + Deschide baza de date în modul doar-citire + + + + settings_file + translation? + fiÈ™ier_setări + + + + Run application based on this settings file + Rulează aplicaÈ›ia pe baza acestui fiÈ™ier de setări + + + + + group + grup + + + + + settings + setări + + + + + value + valoare + + + + Run application with this setting temporarily set to value + Rulează aplicaÈ›ia cu această setare temporar setată la valoare + + + + Run application saving this value for this setting + Rulează aplicaÈ›ia salvând această valoare pentru această setare + + + + Display the current version + AfiÈ™ează versiunea curentă + + + + Open this SQLite database + Deschide această bază de date SQLite + + + + Open this project file (*.sqbpro) + Deschide acest fiÈ™ier de proiect (*.sqbpro) + + + + Import this CSV file into an in-memory database + translation? 'in-memory' + Importă acest fiÈ™ier CSV într-o bază de date în-memorie + + + + + + The %1 option requires an argument + OpÈ›iunea %1 necesită un argument + + + + The -S/--settings option requires an argument. The option is ignored. + OpÈ›iunea -S/--settings necesită un argument. Această opÈ›iune este ignorată. + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + OpÈ›iunile -o/--option È™i -O/--save-option necesită un argument în forma grup/setare=valoare + + + + Invalid option/non-existent file: %1 + OpÈ›iune invalidă/fiÈ™ier inexistent: %1 + + + + SQLite Version + Versiune SQLite + + + + SQLCipher Version %1 (based on SQLite %2) + Versiune SQLCipher %1 (bazat pe SQLite %2) + + + + DB Browser for SQLite Version %1. + DB Browser for SQLite Versiunea %1. + + + + Last commit hash when built: %1 + Ultimul hash de comitere când a fost construit: %1 + + + + Built for %1, running on %2 + Construit pentru %1, rulează pe %2 + + + + Qt Version %1 + Versiune Qt %1 + + + + CipherDialog + + + SQLCipher encryption + Criptare SQLCipher + + + + &Password + &Parolă + + + + &Reenter password + &Reintroduce parola + + + + Passphrase + visibility issue + Frază De Acces + + + + Raw key + unclear translation + Cheia brută + + + + Encr&yption settings + Setări de &criptare + + + + SQLCipher &3 defaults + visibility issue + SQLCipher &3 implicite + + + + SQLCipher &4 defaults + visibility issue + SQLCipher &4 implicite + + + + Custo&m + Personaliza&t + + + + Page si&ze + &Mărime pagină + + + + &KDF iterations + IteraÈ›ii &KDF + + + + HMAC algorithm + Algoritm HMAC + + + + KDF algorithm + Algoritm KDF + + + + Plaintext Header Size + Mărime Antet Text Simplu + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + Vă rugăm să setaÈ›i o cheie pentru a cripta baza de date. +ReÈ›ineÈ›i că, dacă modificaÈ›i oricare dintre celelalte setări opÈ›ionale, va trebui să le introduceÈ›i din nou de fiecare dată când deschideÈ›i fiÈ™ierul bazei de date. +LăsaÈ›i câmpurile de parolă goale pentru a dezactiva criptarea. +Procesul de criptare poate dura ceva timp È™i ar trebui să aveÈ›i o copie de rezervă a bazei de date! Modificările nesalvate sunt aplicate înainte de a modifica criptarea. + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + Vă rugăm să introduceÈ›i cheia utilizată pentru criptarea bazei de date. +Dacă oricare dintre celelalte setări au fost modificate pentru acest fiÈ™ier de bază de date, trebuie să furnizaÈ›i È™i aceste informaÈ›ii. + + + + ColumnDisplayFormatDialog + + + Choose display format + Alege format de afiÈ™are + + + + Display format + Format afiÈ™are + + + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + AlegeÈ›i un format de afiÈ™are pentru coloana '%1', care este aplicată fiecărei valori înainte de a o afiÈ™a. + + + + Default + Implicit + + + + Decimal number + Număr zecimal + + + + Exponent notation + NotaÈ›ie exponentă + + + + Hex blob + Blob Hex + + + + Hex number + Număr Hex + + + + Octal number + Numărul octal + + + + Round number + Număr rotund + + + + Apple NSDate to date + Apple NSDate în dată + + + + Java epoch (milliseconds) to date + translation? 'Java epoch' + Epoca Java (milisecunde) în dată + + + + .NET DateTime.Ticks to date + .NET DateTime.Ticks în dată + + + + Julian day to date + translation? 'Julian day' + Zi Iuliană în dată + + + + Unix epoch to date + translation? 'Unix epoch' + Epoca Unix în dată + + + + Unix epoch to local time + translation? 'Unix epoch + Epoca unix în timp local + + + + WebKit / Chromium epoch to date + translation? 'WebKit / Chromium epoch' + Epoca WebKit / Chromium în dată + + + + WebKit / Chromium epoch to local time + translation? 'WebKit / Chromium epoch' + Epoca WebKit / Chromium în oră locală + + + + Windows DATE to date + translation? 'Windows DATE' + Windows DATE în dată + + + + Date as dd/mm/yyyy + Dată ca dd/mm/yyyy + + + + Lower case + Minusculă + + + + Upper case + Majusculă + + + + Binary GUID to text + GUID Binar în text + + + + SpatiaLite Geometry to SVG + Geometrie SpatiaLite în SVG + + + + Custom + Personalizat + + + + Custom display format must contain a function call applied to %1 + unclear translation - 'call' + Formatul de afiÈ™are personalizat trebuie să conÈ›ină un apel de funcÈ›ie aplicat la %1 + + + + Error in custom display format. Message from database engine: + +%1 + Eroare în formatul de afiÈ™are personalizat. Mesaj de la motorul bazei de date: + +%1 + + + + Custom display format must return only one column but it returned %1. + Formatul de afiÈ™are personalizat trebuie să returneze doar o singură coloană, dar a returnat %1. + + + + CondFormatManager + + + Conditional Format Manager + Manager Format CondiÈ›ional + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + Acest dialog permite crearea È™i editarea formatelor condiÈ›ionale. Fiecare stil de celulă va fi selectat prin prima condiÈ›ie realizată pentru datele celulei respective. Formatele condiÈ›ionate pot fi mutate în sus È™i în jos, unde cele din rândurile superioare au prioritate față de cele din cele inferioare. Sintaxa pentru condiÈ›ii este aceeaÈ™i ca È™i pentru filtre È™i o condiÈ›ie goală se aplică tuturor valorilor. + + + + Add new conditional format + Adaugă un nou format condiÈ›ional + + + + &Add + &Adaugă + + + + Remove selected conditional format + Elimină formatul condiÈ›ional selectat + + + + &Remove + &Elimină + + + + Move selected conditional format up + Mută formatul condiÈ›ional selectat în sus + + + + Move &up + Mutare în &sus + + + + Move selected conditional format down + Mută formatul condiÈ›ional selectat în jos + + + + Move &down + Mutare în &jos + + + + Foreground + Prim-plan + + + + Text color + Culoare text + + + + Background + Fundal + + + + Background color + Culoare de fundal + + + + Font + Font + + + + Size + Mărime + + + + Bold + ÃŽngroÈ™at + + + + Italic + ÃŽnclinat + + + + Underline + Subliniat + + + + Alignment + Aliniere + + + + Condition + CondiÈ›ie + + + + + Click to select color + FaceÈ›i clic pentru a selecta culoarea + + + + Are you sure you want to clear all the conditional formats of this field? + SunteÈ›i sigur că doriÈ›i să È™tergeÈ›i toate formatele condiÈ›ionale ale acestui câmp? + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + Vă rugăm să specificaÈ›i numele bazei de date sub care doriÈ›i să accesaÈ›i baza de date ataÈ™ată + + + + Invalid file format + Format fiÈ™ier invalid + + + + Do you really want to close this temporary database? All data will be lost. + Chiar doriÈ›i să închideÈ›i această bază de date temporară? Toate datele vor fi pierdute. + + + + Do you want to save the changes made to the database file %1? + DoriÈ›i să salvaÈ›i modificările aduse fiÈ™ierului bazei de date %1? + + + + Database didn't close correctly, probably still busy + Baza de date nu s-a închis corect, probabil încă este ocupată + + + + Cannot open destination file: '%1' + Nu se poate deschide fiÈ™ierul de destinaÈ›ie: '%1' + + + + + Cannot backup to file: '%1'. Message: %2 + Nu se poate face copie de rezervă în fiÈ™ierul: '%1'. Mesaj: %2 + + + + The database is currently busy: + Baza de date este ocupată în prezent: + + + + Do you want to abort that other operation? + Vrei să întrerupi cealaltă operaÈ›ie? + + + + Exporting database to SQL file... + Exportând baza de date într-un fiÈ™ier SQL... + + + + + Cancel + Anulează + + + + + No database file opened + Nu este deschis niciun fiÈ™ier bază de date + + + + Executing SQL... + Executând SQL... + + + + Action cancelled. + AcÈ›iune anulată. + + + + + Error in statement #%1: %2. +Aborting execution%3. + Eroare în instrucÈ›iunea #%1: %2. +Se anulează execuÈ›ia%3. + + + + + and rolling back + unclear translation + È™i derulând înapoi + + + + didn't receive any output from %1 + nu s-a primit niciun rezultat de la %1 + + + + could not execute command: %1 + nu se poate executa comanda: %1 + + + + Cannot delete this object + Nu se poate È™terge acest obiect + + + + Cannot set data on this object + Nu se pot seta date pe acest obiect + + + + + A table with the name '%1' already exists in schema '%2'. + Un tabel cu numele '%1' există deja în schema '%2'. + + + + No table with name '%1' exists in schema '%2'. + Nu există tabel cu numele '%1' în schema '%2'. + + + + + Cannot find column %1. + Nu se poate găsi coloana %1. + + + + Creating savepoint failed. DB says: %1 + Crearea punctului de salvare a eÈ™uat. BD spune: %1 + + + + Renaming the column failed. DB says: +%1 + Redenumirea coloanei a eÈ™uat. BD spune: +%1 + + + + + Releasing savepoint failed. DB says: %1 + Eliberarea punctului de salvare a eÈ™uat. BD spune: %1 + + + + Creating new table failed. DB says: %1 + Crearea unui nou tabel a eÈ™uat. BD spune: %1 + + + + Copying data to new table failed. DB says: +%1 + Copierea datelor într-un nou tabel a eÈ™uat. BD spune: +%1 + + + + Deleting old table failed. DB says: %1 + Ștergerea tabelului vechi a eÈ™uat. BD spune: %1 + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + Restaurarea unora dintre obiectele asociate cu acest tabel a eÈ™uat. Acest lucru este cel mai probabil pentru că unele nume de coloane s-au schimbat. Aici este instrucÈ›iunea SQL pe care s-ar putea să doriÈ›i să o reparaÈ›i È™i să o executaÈ›i manual: + + + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + Eroare la redenumirea tabelului '%1' la '%2'. +Mesaj de la motorul bazei de date: +%3 + + + + could not get list of db objects: %1 + nu s-a putut obÈ›ine lista obiectelor bd: %1 + + + + could not get list of databases: %1 + nu s-a putut obÈ›ine lista bazelor de date: %1 + + + + Error setting pragma %1 to %2: %3 + Eroare la setarea pragma %1 la %2: %3 + + + + File not found. + FiÈ™ierul nu a fost găsit. + + + + Error loading extension: %1 + Eroare la încărcarea extensiei: %1 + + + + Error loading built-in extension: %1 + + + + + could not get column information + nu s-a putut obÈ›ine informaÈ›ia coloanei + + + + DbStructureModel + + + Name + Nume + + + + Object + Obiect + + + + Type + Tip + + + + Schema + Schemă + + + + Database + Bază De Date + + + + Browsables + Navigabile + + + + All + Toate + + + + Temporary + Temporar + + + + Tables (%1) + Tabele (%1) + + + + Indices (%1) + Indici (%1) + + + + Views (%1) + Vederi (%1) + + + + Triggers (%1) + DeclanÈ™atoare (%1) + + + + EditDialog + + + Edit database cell + Editează celula bazei de date + + + + This area displays information about the data present in this database cell + Această zonă afiÈ™ează informaÈ›ii despre datele prezente în această celulă a bazei de date + + + + Mode: + Mod: + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + Aceasta este lista modurilor suportate pentru editorul de celule. Alege un mod pentru vizualizarea sau editarea datelor celulei curente. + + + + Text + Text + + + + RTL Text + Text RLT + + + + Binary + Binar + + + + + Image + Imagine + + + + JSON + JSON + + + + XML + XML + + + + + Automatically adjust the editor mode to the loaded data type + Ajustează automat modul editorului la tipul de date încărcat + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + Acest buton bifabil activează sau dezactivează comutarea automată a modului editorului. Când este selectată o celulă nouă sau sunt importate date noi È™i comutarea automată este activată, modul se ajustează la tipul de date detectat. Apoi puteÈ›i schimba manual modul editorului. Dacă doriÈ›i să păstraÈ›i acest mod de comutare manuală în timp ce vă deplasaÈ›i prin celule, dezactivaÈ›i butonul. + + + + Auto-switch + Comutare automată + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + Acest editor Qt este utilizat pentru scripturi de la dreapta la stânga, care nu sunt acceptate de editorul de text implicit. PrezenÈ›a caracterelor de la dreapta la stânga este detectată È™i acest mod de editor este selectat automat. + + + + Apply data to cell + Aplică datele în celulă + + + + This button saves the changes performed in the cell editor to the database cell. + Acest buton salvează modificările efectuate în editorul de celule la celula bazei de date. + + + + Apply + Aplică + + + + Print... + Imprimare... + + + + Ctrl+P + Ctrl+P + + + + Open preview dialog for printing displayed text + Deschidere dialog de previzualizare pentru imprimarea textului afiÈ™at + + + + Evaluation + Evaluare + + + + Identification of the cell currently in the editor + Identificarea celulei aflate în prezent în editor + + + + Type and size of data currently in table + Tipul È™i mărimea datelor aflate în prezent în tabel + + + + Open preview dialog for printing the data currently stored in the cell + Deschidere dialog de previzualizare pentru imprimarea datelor stocate în prezent în celulă + + + + Copy Hex and ASCII + Copiază Hex È™i ASCII + + + + Copy selected hexadecimal and ASCII columns to the clipboard + Copiază coloanele hexazecimale È™i ASCII selectate în clipboard + + + + Ctrl+Shift+C + Ctrl+Shift+C + + + + Autoformat + Formatare Automată + + + + Auto-format: pretty print on loading, compact on saving. + Formatare automată: imprimare frumoasă la încărcare, compact la salvare. + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + Când este activată, funcÈ›ia de formatare automată formatează datele la încărcare, împărÈ›ind textul în linii È™i indentându-l pentru o lizibilitate maximă. La salvarea datelor, funcÈ›ia de formatare automată compactează datele, eliminând capetele liniilor È™i spaÈ›iile albe inutile. + + + + &Export... + &Exportă... + + + + Export to file + Exportă în fiÈ™ier + + + + Opens a file dialog used to export the contents of this database cell to a file. + Deschide un dialog de fiÈ™ier utilizat pentru a exporta conÈ›inutul acestei celule a bazei de date într-un fiÈ™ier. + + + + + &Import... + &Importă... + + + + + Import from file + Importă din fiÈ™ier + + + + + Opens a file dialog used to import any kind of data to this database cell. + Deschide un dialog de fiÈ™ier utilizat pentru a importa orice tip de date în această celulă a bazei de date. + + + + Set as &NULL + Setează ca &NULL + + + + Erases the contents of the cell + Șterge conÈ›inutul celulei + + + + Word Wrap + ÃŽnfășurare Cuvânt + + + + Wrap lines on word boundaries + ÃŽnfășoară linii pe limitele cuvintelor + + + + + Open in default application or browser + Deschide în aplicaÈ›ia sau browserul implicit + + + + Open in application + Deschide în aplicaÈ›ie + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + Valoarea este interpretată ca un fiÈ™ier sau o adresă URL È™i deschis în aplicaÈ›ia sau în browserul web implicit. + + + + Save file reference... + Salvează referinÈ›a fiÈ™ierului... + + + + Save reference to file + Salvează referinÈ›a în fiÈ™ier + + + + + Open in external application + Deschide într-o aplicaÈ›ie externă + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + Modurile editorului de text vă permit să editaÈ›i text simplu, precum È™i date JSON sau XML cu evidenÈ›iere a sintaxei, formatare automată È™i validare înainte de salvare. + +Erorile sunt indicate cu o subliniere roÈ™ie. + +ÃŽn modul Evaluare, expresiile SQLite introduse sunt evaluate È™i rezultatul aplicat celulei. + + + + Unsaved data in the cell editor + Date nesalvate în editorul de celule + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + Editorul de celule conÈ›ine date care nu au fost încă aplicate în baza de date. +DoriÈ›i să aplicaÈ›i datele editate la rândul=%1, coloana=%2? + + + + Editing row=%1, column=%2 + Editând rând=%1, coloană=%2 + + + + No cell active. + Nicio celulă activă. + + + + + Image data can't be viewed in this mode. + Datele de imagine nu pot fi vizualizate în acest mod. + + + + + Try switching to Image or Binary mode. + ÃŽncercaÈ›i să comutaÈ›i la modul imagine sau binar. + + + + + Binary data can't be viewed in this mode. + Datele binare nu pot fi vizualizate în acest mod. + + + + + Try switching to Binary mode. + ÃŽncercaÈ›i să comutaÈ›i la modul binar. + + + + + Image files (%1) + FiÈ™iere de imagine (%1) + + + + Choose a file to import + Alege un fiÈ™ier pentru import + + + + %1 Image + %1 Imagine + + + + Binary files (*.bin) + FiÈ™iere binare (*.bin) + + + + Choose a filename to export data + Alege un nume de fiÈ™ier pentru a exporta datele + + + + Invalid data for this mode + Date invalide pentru acest mod + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + Celula conÈ›ine date %1 invalide. Motiv: %2. Chiar doriÈ›i să o aplicaÈ›i celulei? + + + + + Type: NULL; Size: 0 bytes + Tip: NULL; Mărime: 0 octeÈ›i + + + + + Type: Text / Numeric; Size: %n character(s) + + Tip: Text / Numeric; Mărime: %n caracter + Tip: Text / Numeric; Mărime: %n caractere + Tip: Text / Numeric; Mărime: %n caractere + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + Tip: %1 Imagine; Mărime: %2x%3 pixel(i) + + + + Type: Valid JSON; Size: %n character(s) + + Tip: JSON Valid; Mărime: %n caracter + Tip: JSON Valid; Mărime: %n caractere + Tip: JSON Valid; Mărime: %n caractere + + + + + Type: Binary; Size: %n byte(s) + + Tip: Binar; Mărime: %n octet + Tip: Binar; Mărime: %n octeÈ›i + Tip: Binar; Mărime: %n octeÈ›i + + + + + Couldn't save file: %1. + Nu s-a putut salva fiÈ™ierul: %1. + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + Datele au fost salvate într-un fiÈ™ier temporar È™i au fost deschise cu aplicaÈ›ia implicită. Acum puteÈ›i edita fiÈ™ierul È™i, când sunteÈ›i gata, aplicaÈ›i noile date salvate în celulă sau anulaÈ›i orice modificare. + + + + EditIndexDialog + + + Edit Index Schema + Editează Schema Indicelui + + + + &Name + &Nume + + + + &Table + &Tabel + + + + &Unique + &Unic + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + Pentru restricÈ›ionarea indicelui doar la o parte a tabelului, puteÈ›i specifica aici o clauză WHERE care selectează partea din tabel care ar trebui indexată + + + + Partial inde&x clause + Clauză &indice parÈ›ial + + + + Colu&mns + &Coloane + + + + Table column + Coloană tabel + + + + Type + Tip + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + Adăugă o nouă coloană de expresie la indice. Coloanele de expresie conÈ›in expresie SQL mai degrabă decât nume de coloane. + + + + Index column + Coloană indice + + + + Order + Ordine + + + + Deleting the old index failed: +%1 + Ștergerea indicelui vechi a eÈ™uat: +%1 + + + + Creating the index failed: +%1 + Crearea indicelui a eÈ™uat: +%1 + + + + EditTableDialog + + + Edit table definition + Editează definiÈ›ia tabelului + + + + Table + Tabel + + + + Advanced + Avansat + + + + Database sche&ma + &Schemă bază de date + + + + Without Rowid + Without Rowid + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + + + + + On Conflict + ÃŽn Caz De Conflict + + + + Strict + Strict + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + Când opÈ›iunea strict este activată, SQLite aplică tipurile de date ale fiecărei coloane la actualizarea sau inserarea datelor. + + + + Fields + Câmpuri + + + + + + Add + Adăuga + + + + + + Remove + Elimină + + + + Move to top + MutaÈ›i la început + + + + Move up + Mutare în sus + + + + Move down + Mutare în jos + + + + Move to bottom + Mutare la capăt + + + + + + + Name + Nume + + + + + Type + Tip + + + + NN + NN + + + + Not null + Non-null + + + + PK + translation? - clarification needed + CP + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> Cheie primară</p></body></html> + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_fk"/> Cheie Străină</p></body></html> + + + + Index Constraints + Constrângeri Indice + + + + AI + AI + + + + Autoincrement + Incrementare Automată + + + + U + U + + + + + + Unique + Unic + + + + Default + Implicit + + + + Default value + Valoare implicită + + + + + Check + Verificare + + + + Check constraint + Verificare constrângere + + + + Collation + ColaÈ›ionare + + + + Foreign Key + Cheie Străină + + + + Add constraint + Adaugă constrângere + + + + Remove constraint + Elimină constrângere + + + + + Columns + Coloane + + + + + + SQL + SQL + + + + Foreign Keys + Chei Străine + + + + References + ReferinÈ›e + + + + Check Constraints + unclear translation + Verificare Constrângeri + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + tentative translation 'parser' + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Avertisment: </span>Există ceva cu această definiÈ›ie a tabelului pe care analizatorul nostru nu îl înÈ›elege pe deplin. Modificarea È™i salvarea acestui tabel poate duce la probleme.</p></body></html> + + + + + Primary Key + Cheie Primară + + + + Add a primary key constraint + Adaugă o constrângere de cheie primară + + + + Add a unique constraint + Adaugă o constrângere unică + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + Nu poate exista decât o singură cheie primară pentru fiecare tabel. Vă rugăm să modificaÈ›i cheia primară existentă în schimb. + + + + Error creating table. Message from database engine: +%1 + Eroare la crearea tabelului. Mesaj de la motorul de baze de date: +%1 + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + Există deja un câmp cu acest nume. Vă rugăm să îl redenumiÈ›i mai întâi sau să alegeÈ›i un alt nume pentru acest câmp. + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + Această coloană este menÈ›ionată într-o cheie străină în tabelul %1 È™i, prin urmare, numele său nu poate fi schimbat. + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + Există cel puÈ›in un rând cu acest câmp setat la NULL. Acest lucru face imposibilă setarea acestui steag. Vă rugăm să modificaÈ›i mai întâi datele tabelului. + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + Există cel puÈ›in un rând cu o valoare non-întreagă în acest câmp. Acest lucru face imposibilă setarea steagului AI. Vă rugăm să modificaÈ›i mai întâi datele tabelului. + + + + Column '%1' has duplicate data. + + Coloana '%1' are date duplicate. + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + Acest lucru face imposibilă activarea steagului 'Unic'. Vă rugăm să eliminaÈ›i datele duplicate, ceea ce va permite activarea steagului 'Unic'. + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + Sigur doriÈ›i să È™tergeÈ›i câmpul '%1'? +Toate datele stocate în prezent în acest câmp vor fi pierde. + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + Vă rugăm să adăugaÈ›i un câmp care îndeplineÈ™te următoarele criterii înainte de a seta steagul without rowid: + - Steag de cheie primară setat + - Incrementare automată dezactivată + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + Vă rugăm să adăugaÈ›i un câmp care îndeplineÈ™te următoarele criterii înainte de a seta acÈ›iunea on conflict: + - Steag de cheie primară setat + + + + ExportDataDialog + + + Export data as CSV + Exportă date ca CSV + + + + Tab&le(s) + &Tabel(e) + + + + Colu&mn names in first line + Nume coloane în &prima linie + + + + Fie&ld separator + &Separator câmp + + + + , + , + + + + ; + ; + + + + Tab + Tab + + + + | + | + + + + + + Other + Altul + + + + &Quote character + Caracter de &citatre + + + + " + " + + + + ' + ' + + + + New line characters + Caractere linie nouă + + + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) + + + + Unix: LF (\n) + Unix: LF (\n) + + + + Pretty print + Imprimare frumoasă + + + + Export data as JSON + Exportă datele ca JSON + + + + exporting CSV + exportând CSV + + + + + Error while writing the file '%1': %2 + Eroare la scrierea fiÈ™ierului '%1': %2 + + + + + Could not open output file: %1 + Nu s-a putut deschide fiÈ™ierul de ieÈ™ire: %1 + + + + exporting JSON + exportând JSON + + + + + Choose a filename to export data + Alege un nume de fiÈ™ier pentru a exporta date + + + + Please select at least 1 table. + Vă rugăm să selectaÈ›i cel puÈ›in 1 tabel. + + + + Choose a directory + Alege un dosar + + + + Export completed. + Export finalizat. + + + + Export finished with errors. + Exportul finalizat cu erori. + + + + ExportSqlDialog + + + Export SQL... + Exportă SQL... + + + + Tab&le(s) + &Tabel(e) + + + + Select All + Selectează Toate + + + + Deselect All + Deselectează Toate + + + + &Options + &OpÈ›iuni + + + + Keep column names in INSERT INTO + Păstrează numele coloanelor în INSERT INTO + + + + Multiple rows (VALUES) per INSERT statement + Multiple rânduri (VALUES) per instrucÈ›iune INSERT + + + + Export everything + Exportă totul + + + + Export schema only + Exportă doar schema + + + + Export data only + Exportă doar date + + + + Keep original CREATE statements + Păstrează instrucÈ›iunile CREATE originale + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + Păstrează schema veche (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + Suprascrie schema veche (DROP TABLE, apoi CREATE TABLE) + + + + Please select at least one table. + Vă rugăm să selectaÈ›i cel puÈ›in un tabel. + + + + Choose a filename to export + Alege un nume de fiÈ™ier pentru a exporta + + + + Export completed. + Export finalizat. + + + + Export cancelled or failed. + Export anulat sau eÈ™uat. + + + + ExtendedScintilla + + + + Ctrl+H + Ctrl+H + + + + Ctrl+F + Ctrl+F + + + + + Ctrl+P + Ctrl+P + + + + Find... + GăseÈ™te... + + + + Find and Replace... + GăseÈ™te È™i ÃŽnlocuieÈ™te... + + + + Print... + Imprimare... + + + + ExtendedTableWidget + + + Use as Exact Filter + FoloseÈ™te ca Filtru Exact + + + + Containing + ConÈ›inând + + + + Not containing + Nu conÈ›ine + + + + Not equal to + Nu este egal cu + + + + Greater than + Mai mare ca + + + + Less than + Mai mic ca + + + + Greater or equal + Mai mare sau egal + + + + Less or equal + Mai mic sau egal + + + + Between this and... + ÃŽntre asta È™i... + + + + Regular expression + Expresie regulată + + + + Edit Conditional Formats... + Editează Formatele CondiÈ›ionale... + + + + Set to NULL + Setează la NULL + + + + Cut + Taie + + + + Copy + Copiază + + + + Copy with Headers + Copiază cu anteturi + + + + Copy as SQL + Copiază ca SQL + + + + Paste + LipeÈ™te + + + + Print... + Imprimare... + + + + Use in Filter Expression + Utilizează în Filtru Expresie + + + + Alt+Del + Alt+Del + + + + Ctrl+Shift+C + Ctrl+Shift+C + + + + Ctrl+Alt+C + Ctrl+Alt+C + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + ConÈ›inutul clipboard-ului este mai mare decât intervalul selectat. +DoriÈ›i să îl inseraÈ›i oricum? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>Nu toate datele au fost încărcate. <b>DoriÈ›i să încărcaÈ›i toate datele înainte de a selecta toate rândurile?</b><p><p>Răspunzând<b>Nu</b> înseamnă că nu vor mai fi încărcate date È™i selecÈ›ia nu va fi efectuată.<br/>Răspunzând <b>Da</b> ar putea dura ceva timp până când datele sunt încărcate, dar selecÈ›ia va fi completă.</p>Avertisment: ÃŽncărcarea tuturor datelor poate necesita o cantitate mare de memorie pentru tabelele mari. + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + Nu se poate seta selecÈ›ia la NULL. Coloana %1 are o constrângere NOT NULL. + + + + FileExtensionManager + + + File Extension Manager + Manager Extensii De FiÈ™iere + + + + &Up + &Sus + + + + &Down + &Jos + + + + &Add + &Adaugă + + + + &Remove + &Elimină + + + + + Description + Descriere + + + + Extensions + Extensii + + + + *.extension + translation? + *.extensie + + + + FilterLineEdit + + + Filter + Filtru + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + unclear translation - 'wildcard' + Aceste câmpuri de intrare vă permit să efectuaÈ›i filtre rapide în tabelul selectat în prezent. +ÃŽn mod implicit, rândurile care conÈ›in textul de intrare sunt filtrate. +Următorii operatori sunt, de asemenea, suportaÈ›i: +% Șablon +> Mai mare ca +< Mai mic ca +>= Egal cu sau mai mare +<= Egal cu sau mai mic += Egal cu: potrivire exactă +<> Inegal: potrivire exactă inversă +x~y Interval: valori între x È™i y +/ regexp/ Valori care se potrivesc cu expresia regulată + + + + Set Filter Expression + Setează Expresie Filtru + + + + What's This? + Ce este asta? + + + + Is NULL + Este NULL + + + + Is not NULL + Nu este NULL + + + + Is empty + Este gol + + + + Is not empty + Nu este gol + + + + Not containing... + Nu conÈ›ine... + + + + Equal to... + Egal cu... + + + + Not equal to... + Nu este egal cu... + + + + Greater than... + Mai mare ca... + + + + Less than... + Mai mic ca... + + + + Greater or equal... + Mai mare sau egal... + + + + Less or equal... + Mai mic sau egal... + + + + In range... + ÃŽn gamă... + + + + Regular expression... + Expresie regulată... + + + + Clear All Conditional Formats + Șterge Toate Formatele CondiÈ›ionate + + + + Use for Conditional Format + Utilizare pentru Format CondiÈ›ionat + + + + Edit Conditional Formats... + Editează Formatele CondiÈ›ionate... + + + + FindReplaceDialog + + + Find and Replace + GăseÈ™te È™i ÃŽnlocuieÈ™te + + + + Fi&nd text: + &GăseÈ™te text: + + + + Re&place with: + ÃŽn&locuieÈ™te cu: + + + + Match &exact case + visibility issue + Potrivire caz &exact + + + + Match &only whole words + visibility issue + PotrivÈ™ete numai cuvinte în&tregi + + + + When enabled, the search continues from the other end when it reaches one end of the page + Când este activată, căutarea continuă de la celălalt capăt când ajunge la un capăt al paginii + + + + &Wrap around + ÃŽn&fășoară în jur + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + Când este setat, căutarea merge în sens invers din poziÈ›ia cursorului, altfel merge înainte + + + + Search &backwards + Căutare &inversă + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>Când este bifat, modelul de găsit este căutat numai în selecÈ›ia curentă.</p></body></html> + + + + &Selection only + Numai &selecÈ›ie + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Când este bifat, modelul de găsit este interpretat ca o expresie regulată UNIX. Vezi <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + Use regular e&xpressions + visibility issue + FoloseÈ™te expresii &regulate + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + GăseÈ™te următoarea apariÈ›ie din poziÈ›ia cursorului È™i în direcÈ›ia setată de "Căutare inversă" + + + + &Find Next + GăseÈ™te &Următorul + + + + F3 + F3 + + + + &Replace + ÃŽnlo&cuieÈ™te + + + + Highlight all the occurrences of the text in the page + EvidenÈ›iază toate apariÈ›iile textului în pagină + + + + F&ind All + GăseÈ™te T&oate + + + + Replace all the occurrences of the text in the page + ÃŽnlocuieÈ™te toate apariÈ›iile textului în pagină + + + + Replace &All + ÃŽnlocuieÈ™te To&ate + + + + The searched text was not found + Textul căutat nu a fost găsit + + + + The searched text was not found. + Textul căutat nu a fost găsit. + + + + The searched text was replaced one time. + Textul căutat a fost înlocuit o dată. + + + + The searched text was found one time. + Textul căutat a fost găsit o dată. + + + + The searched text was replaced %1 times. + Textul căutat a fost înlocuit de %1 ori. + + + + The searched text was found %1 times. + Textul căutat a fost găsit de %1 ori. + + + + ForeignKeyEditor + + + &Reset + &Resetează + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + Clauze Cheie Externă (ON UPDATE, ON DELETE etc.) + + + + ImageViewer + + + Image Viewer + Vizualizator Imagine + + + + Reset the scaling to match the original size of the image. + Resetează scalarea pentru a se potrivi cu mărimea originală a imaginii. + + + + Set the scaling to match the size of the viewport. + Setează scalarea pentru a se potrivi cu mărimea ferestrei de vizualizare. + + + + Print... + Imprimare... + + + + Open preview dialog for printing displayed image + Deschide dialog de previzualizare pentru imprimarea imaginii afiÈ™ate + + + + Ctrl+P + Ctrl+P + + + + ImportCsvDialog + + + Import CSV file + Importă fiÈ™ier CSV + + + + Table na&me + &Nume tabel + + + + &Column names in first line + Nume de coloane în &prima linie + + + + Field &separator + &Separator câmp + + + + , + , + + + + ; + ; + + + + + Tab + Tab + + + + | + | + + + + + Other (printable) + Altul (imprimabil) + + + + + Other (code) + Altul (cod) + + + + &Quote character + Caracter de c&itare + + + + " + " + + + + ' + ' + + + + &Encoding + &Codificare + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Other + Altul + + + + Trim fields? + Taie câmpurile? + + + + Separate tables + Tabele separate + + + + Advanced + Avansat + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + Atunci când se importă o valoare goală din fiÈ™ierul CSV într-un tabel existent cu o valoare implicită pentru această coloană, valoarea implicită este inserată. ActivaÈ›i această opÈ›iune pentru a insera în schimb o valoare goală. + + + + Ignore default &values + Ignoră &valorile implicite + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + ActivaÈ›i această opÈ›iune pentru a opri importul atunci când încercaÈ›i să importaÈ›i o valoare goală într-o coloană NOT NULL fără o valoare implicită. + + + + Fail on missing values + EÈ™uează la valori lipsă + + + + Disable data type detection + Dezactivează detectarea tipului de date + + + + Disable the automatic data type detection when creating a new table. + DezactivaÈ›i detectarea automată a tipului de date la crearea unui tabel nou. + + + + Use local number conventions + Utilizează convenÈ›iile numerice locale + + + + Use decimal and thousands separators according to the system locale. + Utilizează separatori de zecimale È™i mii în funcÈ›ie de sistemul local. + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + Când importaÈ›i într-un tabel existent cu o cheie primară, constrângeri unice sau un indice unic, există È™ansa unui conflict. Această opÈ›iune vă permite să selectaÈ›i o strategie pentru acest caz: în mod implicit, importul este anulat È™i derulat înapoi, dar puteÈ›i alege, de asemenea, să ignoraÈ›i È™i să nu importaÈ›i rânduri conflictuale sau să înlocuiÈ›i rândul existent în tabel. + + + + Abort import + Anulare import + + + + Ignore row + Ignoră rând + + + + Replace existing row + ÃŽnlocuire rând existent + + + + Conflict strategy + Strategia conflictului + + + + + Deselect All + Deselectează Toate + + + + Match Similar + Potrivire Similară + + + + Select All + Selectează Toate + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + Există deja un tabel numit '%1 ' È™i un import într-un tabel existent este posibil numai dacă numărul de coloane se potriveÈ™te. + + + + There is already a table named '%1'. Do you want to import the data into it? + Există deja un tabel numit '%1'. DoriÈ›i să importaÈ›i datele în el? + + + + Creating restore point failed: %1 + Crearea punctului de restaurare a eÈ™uat: %1 + + + + Creating the table failed: %1 + Crearea tabelului a eÈ™uat: %1 + + + + importing CSV + importând CSV + + + + Could not prepare INSERT statement: %1 + Nu s-a putut pregăti instrucÈ›iunea INSERT: %1 + + + + Inserting row failed: %1 + Inserarea rândului a eÈ™uat: %1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + SfârÈ™it neaÈ™teptat de fiÈ™ier. Vă rugăm să vă asiguraÈ›i că aÈ›i configurat caracterele de citare corecte È™i că fiÈ™ierul nu este malformat. + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + Importarea fiÈ™ierului '%1' a durat %2ms. Din aceasta, %3ms au fost petrecute în funcÈ›ia de rând. + + + + MainWindow + + + DB Browser for SQLite + DB Browser for SQLite + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + Aceasta este structura bazei de date deschise. +PuteÈ›i glisa instrucÈ›iuni SQL dintr-un rând de obiect È™i să le plasaÈ›i în alte aplicaÈ›ii sau într-o altă instanță 'DB Browser for SQLite'. + + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + Avertisment: acest pragma nu poate fi citit È™i această valoare a fost dedusă. Scrierea pragma ar putea suprascrie un LIKE redefinit furnizat de o extensie SQLite. + + + + toolBar1 + barăDeInstrumente1 + + + + &File + &FiÈ™ier + + + + &Import + &Importă + + + + &Export + &Exportă + + + + &Edit + &Editează + + + + &View + &Vizualizare + + + + &Help + &Ajutor + + + + DB Toolbar + Bară de instrumente BD + + + + Edit Database &Cell + Editează &Celula Bazei De Date + + + + SQL &Log + &Jurnal SQL + + + + Show S&QL submitted by + Arată S&QL trimis de + + + + User + Utilizator + + + + Application + AplicaÈ›ie + + + + Error Log + Jurnal De Erori + + + + This button clears the contents of the SQL logs + Acest buton È™terge conÈ›inutul jurnalelor SQL + + + + &Clear + &Golire + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + Acest panou vă permite să examinaÈ›i un jurnal al tuturor comenzilor SQL emise de către aplicaÈ›ie sau de către dumneavoastră + + + + &Plot + G&rafic + + + + DB Sche&ma + Sche&mă BD + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + Aceasta este structura bazei de date deschise. +PuteÈ›i să glisaÈ›i mai multe nume de obiecte din coloana Nume È™i să le plasaÈ›i în editorul SQL È™i puteÈ›i ajusta proprietățile numelor plasate utilizând meniul contextual. Acest lucru v-ar ajuta la compunerea instrucÈ›iunilor SQL. +PuteÈ›i să glisaÈ›i instrucÈ›iunile SQL din coloana Schemă È™i să le plasaÈ›i în editorul SQL sau în alte aplicaÈ›ii. + + + + + &Remote + La &Distanță + + + + + Project Toolbar + Bară De Instrumente Proiect + + + + Extra DB toolbar + Bară de instrumente suplimentară BD + + + + + + Close the current database file + ÃŽnchide fiÈ™ierul bazei de date curente + + + + &New Database... + &Bază De Date Nouă... + + + + + Create a new database file + Creează un nou fiÈ™ier de bază de date + + + + This option is used to create a new database file. + Această opÈ›iune este utilizată pentru a crea un nou fiÈ™ier de bază de date. + + + + Ctrl+N + Ctrl+N + + + + + &Open Database... + &Deschide Bază De Date... + + + + + + + + Open an existing database file + Deschide un fiÈ™ier de bază de date existent + + + + + + This option is used to open an existing database file. + Această opÈ›iune este utilizată pentru a deschide un fiÈ™ier de bază de date existent. + + + + Ctrl+O + Ctrl+O + + + + &Close Database + ÃŽnc&hide Bază De Date + + + + This button closes the connection to the currently open database file + Acest buton închide conexiunea la fiÈ™ierul bazei de date deschis în prezent + + + + + Ctrl+F4 + Ctrl+F4 + + + + &Revert Changes + &Revocare Modificări + + + + + Revert database to last saved state + Revocare bază de date la ultima stare salvată + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + Această opÈ›iune este utilizată pentru a revoca fiÈ™ierul de bază de date curent la ultima sa stare salvată. Toate modificările efectuate de la ultima operaÈ›iune de salvare sunt pierdute. + + + + &Write Changes + Scrie &Modificările + + + + + Write changes to the database file + Scrie modificările în fiÈ™ierul bazei de date + + + + This option is used to save changes to the database file. + Această opÈ›iune este utilizată pentru a salva modificările la fiÈ™ierul bazei de date. + + + + Ctrl+S + Ctrl+S + + + + Compact &Database... + &Compactare Bază De Date... + + + + Compact the database file, removing space wasted by deleted records + Compactează fiÈ™ierul bazei de date, eliminând spaÈ›iu irosit de înregistrări È™terse + + + + + Compact the database file, removing space wasted by deleted records. + Compactează fiÈ™ierul bazei de date, eliminând spaÈ›iu irosit de înregistrări È™terse. + + + + E&xit + IeÈ™i&re + + + + Ctrl+Q + Ctrl+Q + + + + &Database from SQL file... + Bază de date din fiÈ™ier &SQL... + + + + Import data from an .sql dump text file into a new or existing database. + Importă date dintr-un fiÈ™ier text .sql dump într-o bază de date nouă sau existentă. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + Această opÈ›iune vă permite să importaÈ›i date dintr-un fiÈ™ier text .sql dump într-o bază de date nouă sau existentă. FiÈ™ierele SQL dump pot fi create pe majoritatea motoarelor de baze de date, inclusiv MySQL È™i PostgreSQL. + + + + &Table from CSV file... + Tabel din fiÈ™ier &CSV... + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Deschide un asistent care vă permite să importaÈ›i date dintr-un fiÈ™ier text separat prin virgulă într-un tabel de bază de date. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Deschide un asistent care vă permite să importaÈ›i date dintr-un fiÈ™ier text separat prin virgulă într-un tabel de bază de date. FiÈ™ierele CSV pot fi create în majoritatea aplicaÈ›iilor de baze de date È™i foi de calcul. + + + + &Database to SQL file... + Bază de date în fiÈ™ier &SQL... + + + + Export a database to a .sql dump text file. + Exportă o bază de date într-un fiÈ™ier text .sql dump. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + Această opÈ›iune vă permite să exportaÈ›i o bază de date într-un fiÈ™ier text .sql dump. FiÈ™ierele SQL dump conÈ›in toate datele necesare pentru a recrea baza de date pe majoritatea motoarelor de baze de date, inclusiv MySQL È™i PostgreSQL. + + + + &Table(s) as CSV file... + Tabel(e) ca fiÈ™ier &CSV... + + + + Export a database table as a comma separated text file. + Exportă un tabel de bază de date sub forma unui fiÈ™ier text separat prin virgulă. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + Exportă un tabel de bază de date sub forma unui fiÈ™ier text separat prin virgulă, gata să fie importat în alte aplicaÈ›ii de baze de date sau foi de calcul. + + + + &Create Table... + Creează &Tabel... + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Deschide asistentul Creează Tabel, unde este posibilă definirea numelui È™i a câmpurilor pentru un tabel nou în baza de date + + + + &Delete Table... + Șter&ge Tabel... + + + + + Delete Table + Șterge Tabel + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Deschide asistentul Șterge Tabel, unde puteÈ›i selecta un tabel de bază de date pentru a fi È™ters. + + + + &Modify Table... + &Modifică Tabel... + + + + Create &Index... + Creează In&dice... + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + Deschide asistentul Creează Indice, unde este posibil să definiÈ›i un nou indice pe un tabel existent de bază de date. + + + + &Preferences... + &PreferinÅ£e... + + + + + Open the preferences window. + Deschide fereastra de preferinÈ›e. + + + + &DB Toolbar + Bară De Instrumente &BD + + + + Shows or hides the Database toolbar. + AfiÈ™ează sau ascunde bara de instrumente a Bazei De Date. + + + + W&hat's This? + Ce Este &Asta? + + + + Shift+F1 + Shift+F1 + + + + &About + &Despre + + + + &Recently opened + &Deschis recent + + + + This button opens a new tab for the SQL editor + Acest buton deschide o filă nouă pentru editorul SQL + + + + Ctrl+T + Ctrl+T + + + + &Execute SQL + &Execută SQL + + + + Execute all/selected SQL + Execută toate/selectat SQL + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + Acest buton execută instrucÈ›iunile SQL selectate în prezent. Dacă nu este selectat niciun text, sunt executate toate instrucÈ›iunile SQL. + + + + Ctrl+Return + Ctrl+Return + + + + + + Save SQL file + Salvează fiÈ™ier SQL + + + + &Load Extension... + ÃŽncarcă &Extensie... + + + + + Execute current line + Execută linia curentă + + + + Execute line + Execută linia + + + + This button executes the SQL statement present in the current editor line + Acest buton execută instrucÈ›iunea SQL prezentă în linia curentă a editorului + + + + Shift+F5 + Shift+F5 + + + + Export as CSV file + Exportă ca fiÈ™ier CSV + + + + Export table as comma separated values file + Exportă tabelul ca fiÈ™ier cu valori separate prin virgulă + + + + &Wiki + &Wiki + + + + F1 + F1 + + + + Bug &Report... + &Raport De Eroare... + + + + Feature Re&quest... + Cerere &Caracteristică... + + + + Web&site + &Site web + + + + &Donate on Patreon... + Donează pe &Patreon... + + + + Sa&ve Project + Sal&vează Proiect + + + + + Save the current session to a file + Salvează sesiunea curentă într-un fiÈ™ier + + + + Open &Project... + Deschide &Proiect... + + + + + Load a working session from a file + ÃŽncarcă o sesiune de lucru dintr-un fiÈ™ier + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + &Structură BD + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + &Răsfoire Date + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + Editează &Pragmele + + + + Temp Store + + + + + Secure Delete + + + + + Case Sensitive Like + + + + + Journal Mode + + + + + Journal Size Limit + + + + + Recursive Triggers + + + + + Page Size + + + + + Foreign Keys + Chei Străine + + + + Auto Vacuum + + + + + Max Page Count + + + + + Checkpoint Full FSYNC + + + + + + Off + + + + + + Normal + + + + + + Full + + + + + Default + Implicit + + + + File + FiÅŸier + + + + + Memory + + + + + Delete + + + + + Truncate + + + + + Persist + + + + + WAL + + + + + Exclusive + + + + + Automatic Index + + + + + Ignore Check Constraints + + + + + Full FSYNC + + + + + WAL Auto Checkpoint + + + + + User Version + + + + + Synchronous + + + + + None + Niciunul + + + + Incremental + + + + + Locking Mode + + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + &Execută SQL + + + + &Recent Files + &FiÈ™iere Recente + + + + Too&ls + &Instrumente + + + + &New Database + &Bază De Date Nouă + + + + &Undo + &Anulează + + + + + Undo last change to the database + Anulează ultima modificare a bazei de date + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + Această acÈ›iune anulează ultima modificare efectuată în baza de date în Navigator Bază De Date sau în Execută SQL. Refacerea nu este posibilă. + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + Deschide asistentul Modifică Tabel, unde este posibilă redenumirea unui tabel existent. De asemenea, este posibil să se adauge sau să se È™teargă câmpuri dintr-un tabel, precum È™i să se modifice numele È™i tipurile de câmpuri. + + + + New &tab + &Fila nouă + + + + Open SQL file(s) + Deschide fiÈ™ier(e) SQL + + + + This button opens files containing SQL statements and loads them in new editor tabs + Acest buton deschide fiÈ™iere care conÈ›in instrucÈ›iuni SQL È™i le încarcă în file noi ale editorului + + + + Ctrl+Shift+T + Ctrl+Shift+T + + + + &Save Project + &Salvează Proiect + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + Acest buton vă permite să salvaÈ›i toate setările asociate BD deschise într-un fiÈ™ier de proiect DB Browser for SQLite + + + + Open &Project + &Deschide Proiect + + + + This button lets you open a DB Browser for SQLite project file + Acest buton vă permite să deschideÈ›i un fiÈ™ier de proiect DB Browser for SQLite + + + + &Attach Database... + &AtaÈ™ează Baza De Date... + + + + + Add another database file to the current database connection + Adaugă un alt fiÈ™ier de bază de date la conexiunea curentă a bazei de date + + + + This button lets you add another database file to the current database connection + Acest buton vă permite să adăugaÈ›i un alt fiÈ™ier de bază de date la conexiunea curentă a bazei de date + + + + &Set Encryption... + &Setează Criptarea... + + + + + Save SQL file as + Salvează fiÈ™ierul SQL ca + + + + This button saves the content of the current SQL editor tab to a file + Acest buton salvează conÈ›inutul filei curente a editorului SQL într-un fiÈ™ier + + + + &Browse Table + &Răsfoire Tabel + + + + Copy Create statement + Copiază InstrucÈ›iunea De Creare + + + + Copy the CREATE statement of the item to the clipboard + Copiază instrucÈ›iunea CREATE a elementului în clipboard + + + + SQLCipher &FAQ + SQLCipher &FAQ + + + + Opens the SQLCipher FAQ in a browser window + Deschide SQLCipher FAQ într-o fereastră de browser + + + + Table(&s) to JSON... + Tabel(e) în &JSON... + + + + Export one or more table(s) to a JSON file + Exportă unul sau mai multe tabele într-un fiÈ™ier JSON + + + + Open Data&base Read Only... + abbreviated 'database' + Deschide BD ÃŽn Modul Doar-&Citire... + + + + Open an existing database file in read only mode + Deschide un fiÈ™ier de bază de date existent în modul doar-citire + + + + Ctrl+Shift+O + Ctrl+Shift+O + + + + Save results + Salvează rezultatele + + + + Save the results view + Salvează vederea rezultatelor + + + + This button lets you save the results of the last executed query + Acest buton vă permite să salvaÈ›i rezultatele ultimei interogări executate + + + + + Find text in SQL editor + GăseÈ™te text în editorul SQL + + + + Find + GăseÈ™te + + + + This button opens the search bar of the editor + Acest buton deschide bara de căutare a editorului + + + + Ctrl+F + Ctrl+F + + + + + Find or replace text in SQL editor + GăseÈ™te sau înlocuieÈ™te text în editorul SQL + + + + Find or replace + GăseÈ™te sau înlocuieÈ™te + + + + This button opens the find/replace dialog for the current editor tab + Acest buton deschide dialogul de găsire/înlocuire pentru fila curentă a editorului + + + + Ctrl+H + Ctrl+H + + + + Export to &CSV + Exportă în &CSV + + + + Export to &JSON + Exportă în &JSON + + + + Save as &view + Salvează ca &vedere + + + + Save as view + Salvează ca vedere + + + + Shows or hides the Project toolbar. + AfiÈ™ează sau ascunde bara de instrumente Proiect. + + + + Extra DB Toolbar + Bară De Instrumente Suplimentară BD + + + + &Open Database + &Deschide Bază De Date + + + + New In-&Memory Database + translation? 'In-Memory' + Nouă Bază De Date ÃŽn Mem&orie + + + + Drag && Drop SELECT Query + Glisează && Plasează Interogarea SELECT + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + Când glisaÈ›i câmpuri din acelaÈ™i tabel sau dintr-un singur tabel, plasaÈ›i o interogare SELECT în editor + + + + Drag && Drop Qualified Names + Glisează && Plasează Nume Calificate + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + Utilizează nume calificate (ex., "Tabel"." Câmp") atunci când glisaÈ›i obiectele È™i le plasaÈ›i în editor + + + + Drag && Drop Enquoted Names + Glisează && Plasează Nume ÃŽntre Ghilimele + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + Utilizează identificatori scăpaÈ›i (ex., "Tabel1") atunci când glisaÈ›i obiectele È™i le plasaÈ›i în editor + + + + &Integrity Check + Verificare &Integritate + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + Rulează pragma integrity_check peste baza de date deschisă È™i returnează rezultatele în fila Execută SQL. Această pragma efectuează o verificare a integrității întregii baze de date. + + + + &Foreign-Key Check + Verificare C&heie-Străină + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + Rulează pragma foreign_key_check peste baza de date deschisă È™i returnează rezultatele în fila Execută SQL + + + + &Quick Integrity Check + Verificare &Rapidă De Integritate + + + + Run a quick integrity check over the open DB + Rulează o verificare rapidă a integrității peste BD deschisă + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + Rulează pragma quick_check peste baza de date deschisă È™i returnează rezultatele în fila Execută SQL. Această comandă face cea mai mare parte a verificării PRAGMA integrity_check, dar rulează mult mai repede. + + + + &Optimize + &Optimizează + + + + Attempt to optimize the database + ÃŽncercare de optimizare a bazei de date + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + Rulează pragma de optimizare peste baza de date deschisă. Acest pragma ar putea efectua optimizări care vor îmbunătăți performanÈ›a interogărilor viitoare. + + + + + Print + Imprimare + + + + Print text from current SQL editor tab + Imprimare text din fila curentă a editorului SQL + + + + Open a dialog for printing the text in the current SQL editor tab + Deschide un dialog pentru imprimarea textului din fila curentă a editorului SQL + + + + + Ctrl+P + Ctrl+P + + + + Print the structure of the opened database + Imprimează structura bazei de date deschise + + + + Open a dialog for printing the structure of the opened database + Deschide un dialog pentru imprimarea structurii bazei de date deschise + + + + Un/comment block of SQL code + De/comentează blocul de cod SQL + + + + Un/comment block + De/comentează blocul + + + + Comment or uncomment current line or selected block of code + Comentează sau decomentează linia curentă sau blocul de cod selectat + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + Comentează sau decomentează liniile selectate sau linia curentă, atunci când nu există selecÈ›ie. Tot blocul este comutat conform primei linii. + + + + Ctrl+/ + Ctrl+/ + + + + Stop SQL execution + Oprire execuÈ›ie SQL + + + + Stop execution + Oprire execuÈ›ie + + + + Stop the currently running SQL script + Oprire script SQL care rulează în prezent + + + + &Save Project As... + Salvea&ză Proiectul Ca... + + + + + + Save the project in a file selected in a dialog + Salvează proiectul într-un fiÈ™ier selectat într-un dialog + + + + Save A&ll + Salvează &Toate + + + + + + Save DB file, project file and opened SQL files + Salvează fiÈ™ierul BD, fiÈ™ierul de proiect È™i fiÈ™ierele SQL deschise + + + + Ctrl+Shift+S + Ctrl+Shift+S + + + + Browse Table + Răsfoire Tabel + + + + Close Pro&ject + ÃŽ&nchide Proiect + + + + + Close project and database files and return to the initial state + ÃŽnchide fiÈ™ierele proiectului È™i ale bazei de date È™i revenire la starea iniÈ›ială + + + + + Ctrl+Shift+W + Ctrl+Shift+W + + + + + Detach Database + DetaÈ™ează Baza De Date + + + + + Detach database file attached to the current database connection + DetaÈ™ează fiÈ™ierul de bază de date ataÈ™at la conexiunea curentă a bazei de date + + + + Table from CSV data in Clipboard... + Tabel din date CSV din Clipboard... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + Asta tratează conÈ›inutul curent al clipboard-ului ca un fiÈ™ier CSV È™i deschide acelaÈ™i asistent de import care este utilizat pentru importarea datelor CSV dintr-un fiÈ™ier. + + + + Show &Row Counts + AfiÈ™ează &Numărul De Rânduri + + + + This shows the number of rows for each table and view in the database. + Asta arată numărul de rânduri pentru fiecare tabel È™i vedere în baza de date. + + + + Save Database &As... + &Salvare Bază De Date Ca... + + + + Save the current database as a different file + Salvează baza de date curentă ca un fiÈ™ier diferit + + + + Refresh + Reîmprospătează + + + + Reload the database structure + Reîncarcă structura bazei de date + + + + + Ctrl+W + Ctrl+W + + + + Ctrl+Tab + Ctrl+Tab + + + + Ctrl+Shift+Tab + Ctrl+Shift+Tab + + + + Automatically load the last opened DB file at startup + + + + + Clear List + Șterge Listă + + + + Ctrl+L + Ctrl+L + + + + Ctrl+D + Ctrl+D + + + + Ctrl+I + Ctrl+I + + + + Ctrl+E + Ctrl+E + + + + Window Layout + Aspect Fereastră + + + + Reset Window Layout + Resetare Aspect Fereastră + + + + Ctrl+0 + Ctrl+0 + + + + Simplify Window Layout + Simplifică Aspect Fereastră + + + + Alt+Shift+0 + Alt+Shift+0 + + + + Dock Windows at Bottom + Ancorează Ferestrele în Partea De Jos + + + + Dock Windows at Left Side + Ancorează Ferestrele în Partea Stângă + + + + Dock Windows at Top + Ancorează Ferestrele în Partea De Sus + + + + The database is currently busy. + Baza de date este momentan ocupată. + + + + Click here to interrupt the currently running query. + FaceÈ›i clic aici pentru a întrerupe interogarea care rulează în prezent. + + + + Encrypted + Criptat + + + + Database is encrypted using SQLCipher + Baza de date este criptată folosind SQLCipher + + + + Read only + Doar citire + + + + Database file is read only. Editing the database is disabled. + FiÈ™ierul bazei de date este în modul doar-citire Editarea bazei de date este dezactivată. + + + + Database encoding + Codificarea bazei de date + + + + Alt+Shift+W + Alt+Shift+W + + + + Ctrl+Shift+F4 + Ctrl+Shift+F4 + + + + + Choose a database file + Alege un fiÈ™ier de bază de date + + + + Could not open database file. +Reason: %1 + Nu s-a putut deschide fiÈ™ierul bazei de date. +Motiv: %1 + + + + + + Choose a filename to save under + AlegeÈ›i un nume de fiÈ™ier sub care să salvaÈ›i + + + + In-Memory database + translation? 'In-Memory' + Bază de date ÃŽn-Memorie + + + + Choose a database file to save under + Alege un fiÈ™ier de bază de date pentru a salva sub + + + + Error while saving the database to the new file. + Eroare la salvarea bazei de date în fiÈ™ierul nou. + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + ÃŽncă executaÈ›i instrucÈ›iuni SQL. ÃŽnchiderea bazei de date acum va opri executarea lor, lăsând eventual baza de date într-o stare inconsecventă. SunteÈ›i sigur că doriÈ›i să închideÈ›i baza de date? + + + + Do you want to save the changes made to the project file '%1'? + DoriÈ›i să salvaÈ›i modificările făcute la fiÈ™ierul de proiect '%1'? + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + SunteÈ›i sigur că doriÈ›i să È™tergeÈ›i tabelul '%1'? +Toate datele asociate cu tabelul vor fi pierdute. + + + + Are you sure you want to delete the view '%1'? + SunteÈ›i sigur că doriÈ›i să È™tergeÈ›i vederea '%1'? + + + + Are you sure you want to delete the trigger '%1'? + SunteÈ›i sigur că doriÈ›i să È™tergeÈ›i declanÈ™atorul '%1'? + + + + Are you sure you want to delete the index '%1'? + SunteÈ›i sigur că doriÈ›i să È™tergeÈ›i indicele '%1'? + + + + Error: could not delete the table. + Eroare: nu s-a putut È™terge tabelul. + + + + Error: could not delete the view. + Eroare: nu s-a putut È™terge vederea. + + + + Error: could not delete the trigger. + Eroare: nu s-a putut È™terge declanÈ™atorul. + + + + Error: could not delete the index. + Eroare: nu s-a putut È™terge indicele. + + + + Message from database engine: +%1 + Mesaj de la motorul bazei de date: +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + Editarea tabelului necesită salvarea tuturor modificărilor în aÈ™teptare acum. +SunteÈ›i sigur că doriÈ›i să salvaÈ›i baza de date? + + + + Error checking foreign keys after table modification. The changes will be reverted. + Eroare la verificarea cheilor străine după modificarea tabelului. Modificările vor fi anulate. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + Acest tabel nu a trecut o verificare a cheii străine.<br/>Ar trebui să rulaÈ›i 'Instrumente | Verificare Cheie Străină' È™i să remediaÈ›i problemele raportate. + + + + Edit View %1 + Editează Vederea %1 + + + + Edit Trigger %1 + Editează DeclanÈ™atorul %1 + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + ExecutaÈ›i deja instrucÈ›iuni SQL. DoriÈ›i să le opriÈ›i pentru a executa în schimb instrucÈ›iunile curente? ReÈ›ineÈ›i că acest lucru ar putea lăsa baza de date într-o stare inconsecventă. + + + + -- EXECUTING SELECTION IN '%1' +-- + -- EXECUTÂND SELECÈšIA ÃŽN '%1' +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- EXECUTÂND LINIA ÃŽN '%1' +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- EXECUTÂND TOTUL ÃŽN '%1' +-- + + + + + At line %1: + La linia %1: + + + + Result: %1 + Rezultat: %1 + + + + Result: %2 + Rezultat: %2 + + + + %1 rows returned in %2ms + %1 rânduri returnate în %2ms + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + Setarea valorilor PRAGMA sau aspirarea va comite tranzacÈ›ia curentă. +EÈ™ti sigur? + + + + Execution finished with errors. + ExecuÈ›ie terminată cu erori. + + + + Execution finished without errors. + ExecuÈ›ie terminată fără erori. + + + + Choose text files + Alege fiÈ™iere text + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + Eroare la salvarea fiÈ™ierului bazei de date. Asta înseamnă că nu au fost salvate toate modificările aduse bazei de date. Trebuie să rezolvaÈ›i mai întâi următoarea eroare. + +%1 + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + SunteÈ›i sigur că doriÈ›i să anulaÈ›i toate modificările aduse fiÈ™ierului bazei de date '%1 ' de la ultima salvare? + + + + Choose a file to import + Alege un fiÈ™ier pentru a importa + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + DoriÈ›i să creaÈ›i un nou fiÈ™ier de bază de date pentru a stoca datele importate? +Dacă răspundeÈ›i nu, vom încerca să importăm datele din fiÈ™ierul SQL în baza de date curentă. + + + + File %1 already exists. Please choose a different name. + FiÈ™ierul %1 există deja. Vă rugăm să alegeÈ›i un nume diferit. + + + + Error importing data: %1 + Eroare la importarea datelor: %1 + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + Import finalizat. Unele constrângeri de cheie străină sunt încălcate. Vă rugăm să le remediaÈ›i înainte de salvare. + + + + Import completed. + Import finalizat. + + + + Delete View + Șterge Vedere + + + + Modify View + Modifică Vedere + + + + Delete Trigger + Șterge DeclanÈ™ator + + + + Modify Trigger + Modifică DeclanÈ™ator + + + + Delete Index + Șterge Indice + + + + Modify Index + Modifică Indice + + + + Modify Table + Modifică Tabel + + + + Opened '%1' in read-only mode from recent file list + Deschis '%1' în modul doar-citire din lista de fiÈ™iere recente + + + + Opened '%1' from recent file list + Deschis '%1' din lista de fiÈ™iere recente + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (doar-citire) + + + + Open Database or Project + Deschide Bază De Date sau Proiect + + + + Attach Database... + AtaÈ™are Bază De Date... + + + + Import CSV file(s)... + Importă fiÈ™ier(e) CSV... + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + Selectează acÈ›iunea de aplicat fiÈ™ierului plasat. <br/>Notă: numai 'Importă' va procesa mai mult de un fiÈ™ier. + Selectează acÈ›iunea de aplicat fiÈ™ierelor plasate. <br/>Notă: numai 'Importă' va procesa mai multe fiÈ™iere. + Selectează acÈ›iunea de aplicat fiÈ™ierelor plasate. <br/>Notă: numai 'Importă' va procesa mai multe fiÈ™iere. + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + InstrucÈ›iunile din fila '%1' sunt încă în curs de executare. ÃŽnchiderea filei va opri executarea. Acest lucru ar putea lăsa baza de date într-o stare inconsistentă. SunteÈ›i sigur că doriÈ›i să închideÈ›i fila? + + + + DB file '%1' could not be opened + FiÈ™ierul BD '%1' nu a putut fi deschis + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + Acest fiÈ™ier de proiect utilizează un format de fiÈ™ier vechi, deoarece a fost creat utilizând DB Browser for SQLite versiunea 3.10 sau mai mică. ÃŽncărcarea acestui format de fiÈ™ier nu mai este pe deplin suportată. Dacă doriÈ›i să îl încărcaÈ›i complet, vă rugăm să utilizaÈ›i DB Browser for SQLite versiunea 3.12 pentru a-l converti în noul format de fiÈ™ier. + + + + Table '%1' not found; settings ignored + Tabelul '%1' nu a fost găsit; setări ignorate + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + Setarea valorilor PRAGMA va comite tranzacÈ›ia curentă. +EÈ™ti sigur? + + + + Do you want to save the changes made to SQL tabs in a new project file? + DoriÈ›i să salvaÈ›i modificările aduse filelor SQL într-un nou fiÈ™ier de proiect? + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + DoriÈ›i să salvaÈ›i modificările aduse filelor SQL în fiÈ™ierul de proiect '%1'? + + + + Do you want to save the changes made to the SQL file %1? + DoriÈ›i să salvaÈ›i modificările aduse în fiÈ™ierul SQL %1? + + + + Select SQL file to open + Selectează fiÈ™ierul SQL pentru deschidere + + + + Text files(*.sql *.txt);;All files(*) + FiÈ™iere text (*.sql *.txt);;Toate fiÈ™ierele (*) + + + + Select file name + Selectează numele fiÈ™ierului + + + + Select extension file + Selectează fiÈ™ierul de extensie + + + + Extension successfully loaded. + Extensie încărcată cu succes. + + + + Error loading extension: %1 + Eroare la încărcarea extensiei: %1 + + + + Could not find resource file: %1 + Nu s-a putut găsi fiÈ™ierul resursă: %1 + + + + + Don't show again + Nu mai arăta + + + + New version available. + Versiune nouă disponibilă. + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + O nouă versiune DB Browser for SQLite este disponibilă (%1.%2.%3).<br/><br/>Vă rugăm să descărcaÈ›i la <a href='%4'>%4</a>. + + + + Choose a project file to open + Alege un fiÈ™ier de proiect pentru a deschide + + + + DB Browser for SQLite project file (*.sqbpro) + FiÈ™ier de proiect DB Browser for SQLite (*.sqbpro) + + + + Could not open project file for writing. +Reason: %1 + Nu s-a putut deschide fiÈ™ierul de proiect pentru scriere. +Motiv: %1 + + + + -- Reference to file "%1" (not supported by this version) -- + -- Referință la fiÈ™ierul "%1"(nu este suportat de această versiune) -- + + + + Project saved to file '%1' + Proiect salvat în fiÈ™ierul '%1' + + + + Yes. Don't ask again + Da. Nu întreba din nou + + + + Collation needed! Proceed? + ColaÈ›ionare necesară! ContinuaÈ›i? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + Un tabel din această bază de date necesită o funcÈ›ie specială de colaÈ›ionare '%1' pe care această aplicaÈ›ie nu o poate furniza fără cunoÈ™tinÈ›e suplimentare. +Dacă alegeÈ›i să continuaÈ›i, fiÈ›i conÈ™tienÈ›i de faptul că se pot întâmpla lucruri rele cu baza dumneavoastră de date. +Creează o copie de rezervă! + + + + creating collation + creând coloÈ›ionare + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + Setaează un nume nou pentru fila SQL. Utilizează caracterul '&&' pentru a permite utilizarea următorului caracter ca comandă rapidă de la tastatură. + + + + Please specify the view name + Vă rugăm să specificaÈ›i numele vederii + + + + There is already an object with that name. Please choose a different name. + Există deja un obiect cu acest nume. Vă rugăm să alegeÈ›i un nume diferit. + + + + View successfully created. + Vedere creată cu succes. + + + + Error creating view: %1 + Eroare la crearea vederii: %1 + + + + This action will open a new SQL tab for running: + Această acÈ›iune va deschide o nouă filă SQL pentru rulare: + + + + This action will open a new SQL tab with the following statements for you to edit and run: + Această acÈ›iune va deschide o nouă filă SQL cu următoarele instrucÈ›iuni pe care le puteÈ›i edita È™i executa: + + + + Press Help for opening the corresponding SQLite reference page. + Apasă Ajutor pentru a deschide pagina de referință SQLite corespunzătoare. + + + + Busy (%1) + Ocupat (%1) + + + + Rename Tab + Redenumire Filă + + + + Duplicate Tab + Duplicare Filă + + + + Close Tab + ÃŽnchidere Filă + + + + Opening '%1'... + Deschizând '%1'... + + + + There was an error opening '%1'... + A apărut o eroare la deschiderea '%1'... + + + + Value is not a valid URL or filename: %1 + Valoarea nu este o adresă URL sau un nume de fiÈ™ier valid: %1 + + + + NullLineEdit + + + Set to NULL + Setează la NULL + + + + Alt+Del + Alt+Del + + + + PlotDock + + + Plot + Grafic + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>Acest panou afiÈ™ează lista de coloane a tabelului navigat în prezent sau a interogării tocmai executate. PuteÈ›i selecta coloanele pe care doriÈ›i să le utilizaÈ›i ca axă X sau Y pentru panoul grafic de mai jos. Tabelul arată tipul de axă detectat care va afecta graficul rezultat. Pentru axa Y puteÈ›i selecta doar coloane numerice, dar pentru axa X veÈ›i putea selecta:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Dată/Oră</span>: È™iruri cu format &quot;yyyy-MM-dd hh:mm:ss&quot; sau &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Dată</span>: È™iruri cu format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Oră</span>: È™iruri cu format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Etichetă</span>: alte formate de È™ir. selectând această coloană ca axă X va produce un grafic de bare cu valorile coloanei ca etichete pentru bare</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: valori întregi sau reale</li></ul><p>Făcând dublu clic pe celulele Y, puteÈ›i schimba culoarea utilizată pentru graficul respectiv.</p></body></html> + + + + Columns + Coloane + + + + X + X + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + Tip Axă + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + Aici este un grafic desenat atunci când selectaÈ›i valorile x È™i y de mai sus. + +FaceÈ›i clic pe puncte pentru a le selecta în grafic È™i în tabel. Ctrl+Click pentru selectarea unui interval de puncte. + +FoloseÈ™te rotiÈ›a mouse-ului pentru mărire È™i glisează cu mouse-ul pentru a schimba intervalul axei. + +Selectează axele sau etichetele axelor pentru a glisa È™i a mări doar în acea orientare. + + + + Line type: + Tip linie: + + + + + None + Niciunul + + + + Line + Linie + + + + StepLeft + PasStânga + + + + StepRight + PasDreapta + + + + StepCenter + PasCentru + + + + Impulse + Impuls + + + + Point shape: + Forma punctului: + + + + Cross + Cruce + + + + Plus + Plus + + + + Circle + Cerc + + + + Disc + Disc + + + + Square + Pătrat + + + + Diamond + Diamant + + + + Star + Stea + + + + Triangle + Triunghi + + + + TriangleInverted + TriunghiInversat + + + + CrossSquare + CrucePătrat + + + + PlusSquare + PlusPătrat + + + + CrossCircle + CruceCerc + + + + PlusCircle + PlusCerc + + + + Peace + Pace + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>Salvează graficul curent...</p><p>Format de fiÈ™ier ales de extensie (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + Salvează graficul curent... + + + + + Load all data and redraw plot + ÃŽncarcă toate datele È™i redesenează graficul + + + + Copy + Copiază + + + + Print... + Imprimare... + + + + Help + + + + + Show legend + Arată legendă + + + + Stacked bars + Bare suprapuse + + + + Fixed number format + Format număr fix + + + + Date/Time + Dată/Oră + + + + Date + Dată + + + + Time + Timp + + + + + Numeric + Numeric + + + + Label + Etichetă + + + + Invalid + Invalid + + + + + + Row # + Rând # + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + unclear translation - 'fetch' + ÃŽncarcă toate datele È™i redesenează graficul. +Avertisment: nu toate datele au fost preluate din tabel încă din cauza mecanismului de preluare parÈ›ială. + + + + Choose an axis color + Alege o culoare a axei + + + + Choose a filename to save under + Alege un nume de fiÈ™ier sub care să salvezi + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);; JPG (*.jpg);; PDF(*.pdf);; BMP (*.bmp);; Toate FiÈ™ierele (*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + Există curbe în acest grafic È™i stilul de linie selectat poate fi aplicat numai la graficele sortate de X. Fie sortaÈ›i tabelul sau interogarea de X pentru a elimina curbele sau selectaÈ›i unul dintre stilurile suportate de curbe: Niciunul sau Linie. + + + + Loading all remaining data for this table took %1ms. + ÃŽncărcarea tuturor datelor rămase pentru acest tabel a durat %1ms. + + + + PreferencesDialog + + + Preferences + PreferinÅ£e + + + + &General + &General + + + + Default &location + &LocaÈ›ie implicită + + + + Remember last location + ÈšineÈ›i minte ultima locaÈ›ie + + + + Always use this location + Utilizează întotdeauna această locaÈ›ie + + + + Remember last location for session only + ÈšineÈ›i minte ultima locaÈ›ie numai pentru sesiune + + + + + + ... + ... + + + + Lan&guage + Li&mbă + + + + Toolbar style + Stilul barei de instrumente + + + + + + + + Only display the icon + AfiÈ™ează numai pictograma + + + + + + + + Only display the text + AfiÈ™ează numai textul + + + + + + + + The text appears beside the icon + Textul apare lângă pictogramă + + + + + + + + The text appears under the icon + Textul apare sub pictogramă + + + + + + + + Follow the style + Urmează stilul + + + + Show remote options + AfiÈ™ează opÈ›iunile de la distanță + + + + + + + + + + + + + + enabled + activat + + + + Automatic &updates + &Actualizări automate + + + + DB file extensions + Extensii fiÈ™ier BD + + + + Manage + Administrare + + + + Main Window + Fereastră Principală + + + + Database Structure + Structura Bazei De Date + + + + Browse Data + Răsfoire Date + + + + Execute SQL + Execută SQL + + + + Edit Database Cell + Editează Celula Bazei De Date + + + + When this value is changed, all the other color preferences are also set to matching colors. + Atunci când această valoare este modificată, toate celelalte preferinÈ›e de culoare sunt, de asemenea, setate la culori care se potrivesc. + + + + Follow the desktop style + Urmează stilul desktopului + + + + Dark style + Stil întunecat + + + + Light style + Stil luminos + + + + Application style + Stil aplicaÈ›ie + + + + This sets the font size for all UI elements which do not have their own font size option. + Asta setează mărimea fontului pentru toate elementele interfeÈ›ei utilizatorului care nu au propria opÈ›iune de mărime a fontului. + + + + Font size + Mărime font + + + + Max Recent Files + Număr Maxim De FiÈ™iere Recente + + + + Prompt to save SQL tabs +in new project file + Solicitare la salvarea filelor SQL +într-un fiÈ™ier de proiect nou + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + Dacă asta este activat, atunci modificările aduse editorului SQL generează un dialog de confirmare a salvării unui proiect la închiderea filei editorului SQL. + + + + &Database + &Bază De Date + + + + Database &encoding + &Codificare bază de date + + + + Open databases with foreign keys enabled. + Deschide baze de date cu chei străine activate. + + + + &Foreign keys + Chei &străine + + + + Remove line breaks in schema &view + Elimină întreruperile de linie în &vizualizarea schemei + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + Când este activat, întreruperile de linie din coloana Schemă din fila Structură BD, docul È™i ieÈ™irea imprimată sunt eliminate. + + + + Prefetch block si&ze + unclear translation - 'fetch' + Preîncărcare &mărime bloc + + + + SQ&L to execute after opening database + SQ&L de executat după deschiderea bazei de date + + + + Default field type + Tip câmp implicit + + + + Database structure font size + Mărime font structură bază de date + + + + Data &Browser + &Navigator De Date + + + + Font + Font + + + + &Font + &Font + + + + Font si&ze + &Mărime font + + + + Formatted + Formatat + + + + Content + ConÈ›inut + + + + Symbol limit in cell + Limită simbol în celulă + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + Acesta este numărul maxim de elemente permis pentru activarea unor funcÈ›ionalități costisitoare computaÈ›ionale: +Numărul maxim de rânduri dintr-un tabel pentru activarea finalizării valorii pe baza valorilor curente din coloană. +Numărul maxim de indici dintr-o selecÈ›ie pentru calcularea sumei È™i mediei. +Poate fi setat la 0 pentru a dezactiva funcÈ›ionalitățile. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + Acesta este numărul maxim de rânduri dintr-un tabel pentru activarea finalizării valorii pe baza valorilor curente din coloană. +Poate fi setat la 0 pentru dezactivarea finalizării. + + + + Threshold for completion and calculation on selection + Prag pentru finalizare È™i calcul la selecÈ›ie + + + + Show images in cell + AfiÈ™ează imagini în celulă + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + Activează această opÈ›iune pentru a afiÈ™a o previzualizare a BLOB-urilor care conÈ›in date de imagine în celule. TotuÈ™i, acest lucru poate afecta performanÈ›a navigatorului de date. + + + + Field display + AfiÈ™are câmp + + + + Displayed &text + &Text afiÈ™at + + + + Binary + Binar + + + + NULL + NULL + + + + Regular + Regulat + + + + + + + + + + + Click to set this color + Click pentru a seta această culoare + + + + Text color + Culoare text + + + + Background color + Culoare fundal + + + + + Preview only (N/A) + visibility issue + Numai previzualizare (N/A) + + + + Filters + Filtre + + + + Escape character + Caracter de scăpare + + + + Delay time (&ms) + Timp de întâr&ziere (ms) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + Setează timpul de aÈ™teptare înainte ca o nouă valoare a filtrului să fie aplicată. Poate fi setat la 0 pentru dezactivarea aÈ™teptării. + + + + &SQL + &SQL + + + + Context + Context + + + + Colour + Culoare + + + + Bold + ÃŽngroÈ™at + + + + Italic + ÃŽnclinat + + + + Underline + Subliniat + + + + Keyword + Cuvânt Cheie + + + + Function + FuncÅ£ie + + + + Table + Tabel + + + + Comment + Comentariu + + + + Identifier + Identificator + + + + String + Șir + + + + Current line + Linia curentă + + + + Background + Fundal + + + + Foreground + Prim-plan + + + + Selection background + Fundal de selecÈ›ie + + + + Selection foreground + Prim-plan de selecÈ›ie + + + + Highlight + EvidenÈ›iere + + + + SQL editor &font + &Font editor SQL + + + + SQL &editor font size + Mărime font e&ditor SQL + + + + SQL &results font size + Mărime font &rezultate SQL + + + + Tab size + Mărime filă + + + + Use tabs for indentation + Utilizează taburi pentru indentare + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + Când este setat, tasta Tab va introduce caractere de tabulare È™i spaÈ›iu pentru indentare. ÃŽn caz contrar, se vor utiliza doar spaÈ›ii. + + + + &Wrap lines + ÃŽnfășurare &linii + + + + Never + Niciodată + + + + At word boundaries + La limitele cuvintelor + + + + At character boundaries + La limitele caracterelor + + + + At whitespace boundaries + La limitele spaÈ›iilor albe + + + + &Quotes for identifiers + &Ghilimele pentru identificatori + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + AlegeÈ›i mecanismul de citare utilizat de aplicaÈ›ie pentru identificatori în codul SQL. + + + + "Double quotes" - Standard SQL (recommended) + "Ghilimele duble" - SQL standard (recomandat) + + + + `Grave accents` - Traditional MySQL quotes + `Accente grave` - Ghilimele tradiÈ›ionale MySQL + + + + [Square brackets] - Traditional MS SQL Server quotes + [Paranteze pătrate] - Ghilimele tradiÈ›ionale MS SQL Server + + + + Code co&mpletion + Finali&zarea codului + + + + Keywords in &UPPER CASE + Cuvinte cheie în MA&JUSCULE + + + + When set, the SQL keywords are completed in UPPER CASE letters. + Când este setat, cuvintele cheie SQL sunt completate cu litere MAJUSCULE. + + + + Error indicators + Indicatori de eroare + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + Când este setat, liniile de cod SQL care au cauzat erori în timpul ultimei execuÈ›ii sunt evidenÈ›iate È™i cadrul de rezultate indică eroarea în fundal + + + + Hori&zontal tiling + Aranjare &orizontală + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + Dacă este activat, editorul de cod SQL È™i vizualizarea tabelului de rezultate sunt afiÈ™ate una lângă alta, în loc de una peste cealaltă. + + + + Close button on tabs + Buton de închidere pe file + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + Dacă este activat, filele editorului SQL vor avea un buton de închidere. ÃŽn orice caz, puteÈ›i utiliza meniul contextual sau comanda rapidă de la tastatură pentru a le închide. + + + + &Extensions + &Extensii + + + + Select extensions to load for every database: + Selectează extensiile de încărcat pentru fiecare bază de date: + + + + Add extension + Adaugă extensie + + + + Remove extension + Elimină extensie + + + + Select built-in extensions to load for every database: + + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>ÃŽn timp ce suportă operatorul REGEXP, SQLite nu implementează niciun algoritm de expresie regulată,<br/>dar apelează înapoi aplicaÈ›ia care rulează. DB Browser for SQLite implementează acest<br/>algoritm pentru dumneavoastră pentru a vă permite să utilizaÈ›i REGEXP nou scos din cutie. Cu toate acestea, deoarece există mai multe implementări posibile<br/>ale acestui lucru È™i este posibil să doriÈ›i să utilizaÈ›i alta, sunteÈ›i liber să dezactivaÈ›i<br/>implementarea aplicaÈ›iei È™i să vă încărcaÈ›i propria implementare utilizând o extensie. Necesită repornirea aplicaÈ›iei.</p></body></html> + + + + Disable Regular Expression extension + Dezactivează extensia Expresiei Regulate + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite oferă o funcÈ›ie SQL pentru încărcarea extensiilor dintr-un fiÈ™ier de bibliotecă partajat. Activează asta dacă doriÈ›i să utilizezi funcÈ›ia <span style=" font-style:italic;">load_extension()</span> din codul SQL.</p><p>Din motive de securitate, încărcarea extensiei este dezactivată în mod implicit È™i trebuie activată prin această setare. PuteÈ›i încărca întotdeauna extensii prin intermediul interfeÈ›ei grafice, chiar dacă această opÈ›iune este dezactivată.</p></body></html> + + + + Allow loading extensions from SQL code + Permite încărcarea extensiilor din codul SQL + + + + Remote + La Distanță + + + + Your certificates + Certificatele dumneavoastră + + + + File + FiÅŸier + + + + + Subject CN + Subiect NC + + + + Subject Common Name + Subiect Nume Comun + + + + Issuer CN + Emitent NC + + + + Issuer Common Name + Emitent Nume Comun + + + + + Valid from + Valabil din + + + + + Valid to + Valabil la + + + + + Serial number + Număr de serie + + + + CA certificates + Certificate CA + + + + Common Name + Nume Comun + + + + Subject O + Subiect O + + + + Organization + translation? - clarification needed + Organizare + + + + Clone databases into + Clonează bazele de date în + + + + Proxy + Proxy + + + + Configure + Configurează + + + + Export Settings + Exportă Setările + + + + Import Settings + Importă Setările + + + + + Choose a directory + Alege un dosar + + + + + The language will change after you restart the application. + Limba se va schimba după ce reporniÈ›i aplicaÈ›ia. + + + + Select extension file + SelecteazÇŽ fiÈ™ierul de extensie + + + + Extensions(*.so *.dylib *.dll);;All files(*) + Extensii(*.so *.dylib *.dll);;Toate fiÈ™ierele(*) + + + + Import certificate file + Import fiÈ™ier de certificat + + + + No certificates found in this file. + Nu s-au găsit certificate în acest fiÈ™ier. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + SunteÈ›i sigur că doriÈ›i să eliminaÈ›i acest certificat? Toate datele certificatului vor fi È™terse din setările aplicaÈ›iei! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + SunteÈ›i sigur că doriÈ›i să È™tergeÈ›i toate setările salvate? +Toate preferinÈ›ele dumneavoastră vor fi pierdute È™i vor fi utilizate valorile implicite. + + + + Save Settings File + Salvează FiÈ™ierul De Setări + + + + + Initialization File (*.ini) + FiÈ™ier De IniÈ›ializare (*.ini) + + + + The settings file has been saved in location : + + FiÈ™ierul de setări a fost salvat în locaÈ›ia : + + + + + Open Settings File + Deschide FiÈ™ierul De Setări + + + + The settings file was loaded properly. + FiÈ™ierul de setări a fost încărcat corect. + + + + The selected settings file is not a normal settings file. +Please check again. + FiÈ™ierul de setări selectat nu este un fiÈ™ier de setări normal. +Vă rugăm să verificaÈ›i din nou. + + + + ProxyDialog + + + Proxy Configuration + Configurare Proxy + + + + Pro&xy Type + Tip Pro&xy + + + + Host Na&me + Nume &Gazdă + + + + Port + Port + + + + Authentication Re&quired + &Autentificare Necesară + + + + &User Name + Nume &Utilizator + + + + Password + Parolă + + + + None + Niciunul + + + + System settings + Setări sistem + + + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 + + + + QObject + + + Left + Stânga + + + + Right + Dreapta + + + + Center + Centru + + + + Justify + Justifică + + + + All files (*) + Toate fiÈ™ierele (*) + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + FiÈ™iere De Bază De Date SQLite (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + FiÈ™iere Proiect DB Browser for SQLite (*.sqbpro) + + + + SQL Files (*.sql) + FiÈ™iere SQL (*.sql) + + + + All Files (*) + Toate FiÈ™ierele (*) + + + + Text Files (*.txt) + FiÈ™iere Text (*.txt) + + + + Comma-Separated Values Files (*.csv) + FiÈ™iere Cu Valori Separat Prin Virgulă (*.csv) + + + + Tab-Separated Values Files (*.tsv) + FiÈ™iere Cu Valori Separat Prin File (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + FiÈ™iere Cu Valori Separate Prin Delimitator (*.dsv) + + + + Concordance DAT files (*.dat) + FiÈ™iere concordanță DAT (*.dat) + + + + JSON Files (*.json *.js) + FiÈ™iere JSON (*.json *.js) + + + + XML Files (*.xml) + FiÈ™iere XML (*.xml) + + + + Binary Files (*.bin *.dat) + FiÈ™iere Binare (*.bin *.dat) + + + + SVG Files (*.svg) + FiÈ™iere SVG (*.svg) + + + + Hex Dump Files (*.dat *.bin) + FiÈ™iere Hex Dump (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + Extensii (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + FiÈ™ier De IniÈ›ializare (*.ini) + + + + Error importing data + Eroare la importul datelor + + + + from record number %1 + de la numărul de înregistrare %1 + + + + . +%1 + . +%1 + + + + Importing CSV file... + Importând fiÈ™ier CSV... + + + + Cancel + Anulare + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + FiÈ™iere de bază de date SQLite (*.db *.sqlite *.sqlite3 *.db3) + + + + QsciCommand + + Paste + LipeÈ™te + + + + QsciLexerCPP + + Default + Implicit + + + Keyword + Cuvânt Cheie + + + Identifier + Identificator + + + + QsciLexerJSON + + Default + Implicit + + + String + Șir + + + + QsciLexerJavaScript + + Regular expression + Expresie regulată + + + + QsciLexerPython + + Default + Implicit + + + Comment + Comentariu + + + Keyword + Cuvânt Cheie + + + Identifier + Identificator + + + + QsciLexerSQL + + Default + Implicit + + + Comment + Comentariu + + + Keyword + Cuvânt Cheie + + + Identifier + Identificator + + + + QsciScintilla + + &Undo + &Anulează + + + Select All + Selectează Toate + + + + RemoteCommitsModel + + + Commit ID + ID de comitere + + + + Message + Mesaj + + + + Date + Dată + + + + Author + Autor + + + + Size + Mărime + + + + Authored and committed by %1 + Scris È™i comis de %1 + + + + Authored by %1, committed by %2 + Scris de %1, comis de %2 + + + + RemoteDatabase + + + Error opening local databases list. +%1 + Eroare la deschiderea listei de baze de date locale. +%1 + + + + Error creating local databases list. +%1 + Eroare la crearea listei de baze de date locale. +%1 + + + + RemoteDock + + + Remote + La Distanță + + + + Identity + Identitate + + + + Upload + ÃŽncarcă + + + + DBHub.io + DBHub.io + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>ÃŽn acest panou, bazele de date la distanță de pe site-ul web dbhub.io pot fi adăugate la DB Browser for SQLite. Mai întâi aveÈ›i nevoie de o identitate:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ConectaÈ›i-vă la site-ul web dbhub.io (utilizaÈ›i acreditările GitHub sau orice doriÈ›i)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">FaceÈ›i clic pe buton pentru a &quot;Generarea certificatului de client&quot; (aceasta este identitatea dumneavoastră). Asta vă va oferi un fiÈ™ier de certificat (salvaÈ›i-l pe discul local).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">MergeÈ›i la fila La Distanță din PreferinÈ›ele DB Browser for SQLite. FaceÈ›i clic pe buton pentru a adăuga un nou certificat la DB Browser for SQLite È™i alegeÈ›i fiÈ™ierul de certificat tocmai descărcat.</li></ol><p>Acum, panoul La Distanță arată identitatea dumneavoastră È™i puteÈ›i adăuga baze de date la distanță.</p></body></html> + + + + Local + Local + + + + Current Database + Bază De Date Curentă + + + + Clone + Clonează + + + + &User + &Utilizator + + + + &Database + &Bază De Date + + + + Branch + Ramură + + + + Commits + Comiteri + + + + Commits for + Comiteri pentru + + + + Delete Database + Șterge Bază De Date + + + + Delete the local clone of this database + Șterge clona locală a acestei baze de date + + + + Open in Web Browser + Deschide în Browserul Web + + + + Open the web page for the current database in your browser + Deschide pagina web pentru baza de date curentă în browserul dumneavoastră + + + + Clone from Link + Clonează din Link + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + Utilizează asta pentru a descărca o bază de date la distanță pentru editare locală, utilizând o adresă URL furnizată pe pagina web a bazei de date. + + + + Refresh + Reîmprospătează + + + + Reload all data and update the views + Reîncărcă toate datele È™i actualizează vederile + + + + Clone Database + Clonează Bază De Date + + + + Open Database + Deschide Bază De Date + + + + Open the local copy of this database + Deschide copia locală a acestei baze de date + + + + Check out Commit + Verifică Comiterea + + + + Download and open this specific commit + Descarcă È™i deschide acestă comitere specifică + + + + Check out Latest Commit + Verifică Ultima Comitere + + + + Check out the latest commit of the current branch + Verifică ultima comitere a ramurii curente + + + + Save Revision to File + Salvează Revizia în FiÈ™ier + + + + Saves the selected revision of the database to another file + Salvează revizia selectată a bazei de date într-un alt fiÈ™ier + + + + Upload Database + ÃŽncarcă Baza De Date + + + + Upload this database as a new commit + ÃŽncarcă această bază de date ca o comitere nouă + + + + Push currently opened database to server + unclear translation - 'push' + ÃŽmpingeÈ›i baza de date deschisă în prezent la server + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>ÃŽn prezent, utilizaÈ›i o identitate încorporată, în modul doar-citire. Pentru a vă încărca baza de date, trebuie să configuraÈ›i È™i să utilizaÈ›i contul dumneavoastră DBHub.io.</p><p>Nu aveÈ›i încă un cont DBHub.io? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">CreaÈ›i unul acum</span></a> È™i importaÈ›i certificatul dumneavoastră <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">aici</span></a> pentru a vă partaja bazele de date.</p><p>Pentru ajutor online vizitaÈ›i <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">aici</span></a>.</p></body></html> + + + + Back + ÃŽnapoi + + + + Select an identity to connect + Selectează o identitate pentru conectare + + + + Public + Public + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + Asta descarcă o bază de date de pe un server la distanță pentru editare locală. +Vă rugăm să introduceÈ›i adresa URL de la care să se cloneze. PuteÈ›i genera această adresă URL făcând +clic pe butonul 'Clonează Bază De Date în DB4S' de pe pagina web +a bazei de date. + + + + Invalid URL: The host name does not match the host name of the current identity. + Adresă URL invalidă: Numele de gazdă nu se potriveÈ™te cu numele de gazdă al identității curente. + + + + Invalid URL: No branch name specified. + Adresă URL invalidă: Nume de ramură nespecificat. + + + + Invalid URL: No commit ID specified. + Adresă URL invalidă: ID de comitere nespecificat. + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + unclear translation - 'fetch' + AÈ›i modificat clona locală a bazei de date. Preluarea acestei comiteri suprascrie aceste modificări locale. +SunteÈ›i sigur că doriÈ›i să continuaÈ›i? + + + + The database has unsaved changes. Are you sure you want to push it before saving? + unclear translation - 'push' + Baza de date are modificări nesalvate. SunteÈ›i sigur că doriÈ›i să o împingeÈ›i înainte de a salva? + + + + The database you are trying to delete is currently opened. Please close it before deleting. + Baza de date pe care încercaÈ›i să o È™tergeÈ›i este deschisă în prezent. Vă rugăm să o închideÈ›i înainte de a o È™terge. + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + Asta È™terge versiunea locală a acestei baze de date cu toate modificările pe care nu le-aÈ›i comis încă. SunteÈ›i sigur că doriÈ›i să È™tergeÈ›i această bază de date? + + + + RemoteLocalFilesModel + + + Name + Nume + + + + Branch + Ramură + + + + Last modified + Modificat ultima dată + + + + Size + Mărime + + + + Commit + Comite + + + + File + FiÅŸier + + + + RemoteModel + + + Name + Nume + + + + Commit + Comite + + + + Last modified + Modificat ultima dată + + + + Size + Mărime + + + + Size: + Mărime: + + + + Last Modified: + Modificat Ultima Dată: + + + + Licence: + Licență: + + + + Default Branch: + Ramură Implicită: + + + + RemoteNetwork + + + Choose a location to save the file + Alege o locaÈ›ie pentru a salva fiÈ™ierul + + + + Error opening remote file at %1. +%2 + Eroare la deschiderea fiÈ™ierului la distanță la %1. +%2 + + + + Error: Invalid client certificate specified. + Eroare: Certificat de client invalid specificat. + + + + Please enter the passphrase for this client certificate in order to authenticate. + Vă rugăm să introduceÈ›i fraza de acces pentru acest certificat de client pentru a vă autentifica. + + + + Cancel + Anulează + + + + Uploading remote database to +%1 + ÃŽncărcare bază de date la distanță către +%1 + + + + Downloading remote database from +%1 + Descărcare bază de date la distanță de la +%1 + + + + Error: Cannot open the file for sending. + Eroare: Nu se poate deschide fiÈ™ierul pentru trimitere. + + + + RemotePushDialog + + + Push database + unclear translation - 'push' + ÃŽmpingere bază de date + + + + Database na&me to push to + abbreviated 'database', unclear translation - 'push' + &Nume BD pentru a împinge la + + + + Commit message + Mesaj de comitere + + + + Database licence + Licență bază de date + + + + Public + Public + + + + Branch + Ramură + + + + Force push + unclear translation - 'push' + ForÈ›are împingere + + + + Username + Nume utilizator + + + + Database will be public. Everyone has read access to it. + Baza de date va fi publică. Toată lumea are acces de citire la ea. + + + + Database will be private. Only you have access to it. + Baza de date va fi privată. Numai dumneavoastră aveÈ›i acces la ea. + + + + Use with care. This can cause remote commits to be deleted. + Utilizează cu grijă. Acest lucru poate cauza È™tergerea comiterilor de la distanță. + + + + RunSql + + + Execution aborted by user + ExecuÅ£ie întreruptă de utilizator + + + + , %1 rows affected + , %1 rânduri afectate + + + + query executed successfully. Took %1ms%2 + interogare executată cu succes. A luat %1ms%2 + + + + executing query + executând interogare + + + + SelectItemsPopup + + + A&vailable + &Disponibil + + + + Sele&cted + &Selectat + + + + SqlExecutionArea + + + Form + Formular + + + + Find previous match [Shift+F3] + GăseÈ™te potrivirea anterioară [Shift+F3] + + + + Find previous match with wrapping + GăseÈ™te potrivirea anterioară cu înfășurare + + + + Shift+F3 + Shift+F3 + + + + The found pattern must be a whole word + Modelul găsit trebuie să fie un cuvânt întreg + + + + Whole Words + Cuvinte ÃŽntregi + + + + Text pattern to find considering the checks in this frame + Model de text de găsit având în vedere verificările din acest cadru + + + + Find in editor + GăseÈ™te în editor + + + + The found pattern must match in letter case + Modelul găsit trebuie să se potrivească în cazul literelor + + + + Case Sensitive + Caz Sensibil + + + + Find next match [Enter, F3] + GăseÈ™te următoarea potrivire [Enter, F3] + + + + Find next match with wrapping + GăseÈ™te următoarea potrivire cu înfășurare + + + + F3 + F3 + + + + Interpret search pattern as a regular expression + Interpretează modelul de căutare ca expresie regulată + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Când este bifat, modelul de găsit este interpretat ca o expresie regulată UNIX. Vezi <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + Regular Expression + Expresie Regulată + + + + + Close Find Bar + ÃŽnchide Bara De Căutare + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>Rezultatele ultimelor instrucÈ›iuni executate.</p><p>Poate doriÈ›i să restrângeÈ›i acest panou È™i să utilizaÈ›i docul<span style=" font-style:italic;">Jurnal SQL</span> cu selecÈ›ia <span style=" font-style:italic;">Utilizator</span> în schimb.</p></body></html> + + + + This field shows the results and status codes of the last executed statements. + Acest câmp afiÈ™ează rezultatele È™i codurile de stare ale ultimelor instrucÈ›iuni executate. + + + + Results of the last executed statements + Rezultatele ultimelor instrucÈ›iuni executate + + + + Ctrl+PgUp + Ctrl+PgUp + + + + Ctrl+PgDown + Ctrl+PgDown + + + + Couldn't read file "%1": %2. + Nu s-a putut citi fiÈ™ierul "%1": %2. + + + + + Couldn't save file: %1. + Nu s-a putut salva fiÈ™ierul: %1. + + + + Your changes will be lost when reloading it! + Modificările dumneavoastră vor fi pierdute când le reîncărcaÈ›i! + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + FiÈ™ierul "%1" a fost modificat de un alt program. DoriÈ›i să îl reîncărcaÈ›i?%2 + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + Răspunde "Da la Toate" pentru a reîncărca fiÈ™ierul la orice actualizare externă fără alte solicitări. + + + + Answer "No to All" to ignore any external update without further prompting. + Răspunde "Nu la Toate" pentru a ignora orice actualizare externă fără alte solicitări. + + + + Modifying and saving the file will restore prompting. + Modificarea È™i salvarea fiÈ™ierului va restabili solicitarea. + + + + SqlTextEdit + + + Ctrl+/ + Ctrl+/ + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) FuncÈ›ia abs(X) returnează valoarea absolută a argumentului numeric X. + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () FuncÈ›ia changes() returnează numărul de rânduri ale bazei de date care au fost modificate sau inserate sau È™terse de instrucÈ›iunea INSERT, DELETE sau UPDATE completată cel mai recent. + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) FuncÈ›ia char(X1,X2,...,XN) returnează un È™ir compus din caractere care au valorile punctului de cod unicode ale numerelor întregi X1 până la XN, respectiv. + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) FuncÈ›ia coalesce() returnează o copie a primului său argument non-NULL sau NULL dacă toate argumentele sunt NULL + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) FuncÈ›ia glob(X,Y) este echivalentă la expresia "Y GLOB X". + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) FuncÈ›ia ifnull() returnează o copie a primului său argument non-NULL sau NULL dacă ambele argumente sunt NULL. + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) FuncÈ›ia instr(X,Y) găseÈ™te prima apariÈ›ie a È™irului Y în cadrul È™irului X È™i returnează numărul de caractere anterioare plus 1, sau 0 dacă Y nu se găseÈ™te nicăieri în cadrul lui X. + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) FuncÈ›ia hex() își interpretează argumentul ca un BLOB È™i returnează un È™ir care este redarea hexazecimală cu majuscule a conÈ›inutului acelui blob. + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) FuncÈ›ia iif(X,Y,Z) returnează valoarea Y dacă X este adevărat È™i Z în caz contrar. + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () FuncÈ›ia last_insert_rowid() returnează ROWID al ultimului rând inserat din conexiunea bazei de date care a invocat funcÈ›ia. + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) Pentru o valoare de È™ir X, funcÈ›ia length(X) returnează numărul de caractere (nu octeÈ›i) în X înainte de primul caracter NUL. + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) FuncÈ›ia like() este utilizată la implementarea expresiei "Y LIKE X". + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) FuncÈ›ia like() este utilizată la implementarea expresiei "Y LIKE X ESCAPE Z". + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) FuncÈ›ia load_extension(X) încarcă extensiile SQLite din fiÈ™ierul bibliotecii partajate numit X. +Utilizarea acestei funcÈ›ii trebuie autorizată din PreferinÈ›e. + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) FuncÈ›ia load_extension(X) încarcă extensiile SQLite din fiÈ™ierul bibliotecii partajate numit X folosind punctul de intrare Y. +Utilizarea acestei funcÈ›ii trebuie autorizată din PreferinÈ›e. + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) FuncÈ›ia lower(X) returnează o copie a È™irului X cu toate caracterele ASCII convertite în minuscule. + + + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) elimină spaÈ›iile din partea stângă a lui X. + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) FuncÈ›ia ltrim(X,Y) returnează un È™ir format prin eliminarea oricăror È™i tuturor caracterelor care apar în Y din partea stângă a lui X. + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) FuncÈ›ia cu mai multe argumente max() returnează argumentul cu valoarea maximă sau returnează NULL dacă oricare argument este NULL. + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) FuncÈ›ia cu mai multe argumente min() returnează argumentul cu valoare minimă. + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) FuncÈ›ia nullif(X,Y) returnează primul său argument dacă argumentele sunt diferite È™i NULL dacă argumentele sunt la fel. + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + translate? 'C-language' + (FORMAT,...) FuncÈ›ia SQL printf(FORMAT,...) funcÈ›ionează ca funcÈ›ia sqlite3_mprintf() limbaj-C È™i funcÈ›ia printf() din biblioteca standard C. + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) FuncÈ›ia quote(X) returnează textul unui literal SQL care este valoarea argumentului său, potrivit pentru includerea într-o instrucÈ›iune SQL. + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () FuncÈ›ia random() returnează un număr întreg pseudo-aleatoriu între -9223372036854775808 È™i + 9223372036854775807. + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) FuncÈ›ia randomblob(N) returnează un blob de N-octeÈ›i care conÈ›ine octeÈ›i pseudo-aleatori. + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) FuncÈ›ia replace(X,Y,Z) returnează un È™ir format prin înlocuirea È™irului Z pentru fiecare apariÈ›ie a È™irului Y în È™irul X. + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) FuncÈ›ia round(X) returnează o valoare în virgulă mobilă X rotunjită la zero cifre la dreapta punctului zecimal. + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) FuncÈ›ia round(X,Y) returnează o valoare în virgulă mobilă X rotunjită la Y cifre la dreapta punctului zecimal. + + + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X) elimină spaÈ›iile din partea dreaptă a lui X. + + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) FuncÈ›ia rtrim(X,Y) returnează un È™ir format prin eliminarea oricăror È™i tuturor caracterelor care apar în Y din partea dreaptă a lui X. + + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) FuncÈ›ia soundex(X) returnează un È™ir care este codificarea soundex a È™irului X. + + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) substr(X,Y) returnează toate caracterele până la sfârÈ™itul È™irului X începând cu al Y-lea. + + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) FuncÈ›ia substr(X,Y,Z) returnează un subÈ™ir din È™irul de intrare X care începe cu al Y-lea caracter È™i care are o lungime de Z caractere. + + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () FuncÈ›ia total_changes() returnează numărul de modificări de rânduri cauzate de instrucÈ›iunile INSERT, UPDATE sau DELETE de când a fost deschisă conexiunea curentă la baza de date. + + + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) elimină spaÈ›iile de la ambele capete ale lui X. + + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) FuncÈ›ia trim(X,Y) returnează un È™ir format prin eliminarea oricăror È™i tuturor caracterelor care apar în Y de la ambele capete ale lui X. + + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) FuncÈ›ia typeof(X) returnează un È™ir care indică tipul de date al expresiei X. + + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) FuncÈ›ia unicode(X) returnează punctul de cod numeric unicode corespunzător primului caracter al È™irului X. + + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) FuncÈ›ia upper(X) returnează o copie a È™irului de intrare X în care toate caracterele ASCII minuscule sunt convertite în echivalentul lor în majuscule. + + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) FuncÈ›ia zeroblob(N) returnează un BLOB format din N octeÈ›i de 0x00. + + + + + + + (timestring,modifier,modifier,...) + translation in parentheses + (È™ir de timp, modificator, modificator,...) + + + + (format,timestring,modifier,modifier,...) + translation in parentheses + (format, È™ir de timp, modificator, modificator,...) + + + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) FuncÈ›ia avg() returnează valoarea medie a tuturor X non-NULL dintr-un grup. + + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) FuncÈ›ia count(X) returnează o numărătoare a numărului de ori în care X nu este NULL într-un grup. + + + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) FuncÈ›ia group_concat() returnează un È™ir care este concatenarea tuturor valorilor non-NULL ale lui X. + + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) FuncÈ›ia group_concat() returnează un È™ir care este concatenarea tuturor valorilor non-NULL ale lui X. Dacă parametrul Y este prezent, atunci este utilizat ca separator între instanÈ›ele lui X. + + + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) FuncÈ›ia agregată max() returnează valoarea maximă a tuturor valorilor din grup. + + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) FuncÈ›ia agregată min() returnează valoarea minimă non-NULL a tuturor valorilor din grup. + + + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) FuncÈ›iile agregate sum() È™i total() returnează suma tuturor valorilor non-NULL din grup. + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () Numărul rândului din cadrul partiÈ›iei curente. Rândurile sunt numerotate începând de la 1 în ordinea definită de clauza ORDER BY din definiÈ›ia ferestrei sau în ordine arbitrară în caz contrar. + + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + unclear translation - 'peer' + () row_number() al primei egalități din fiecare grup - rangul rândului curent cu goluri. Dacă nu există o clauză ORDER BY, atunci toate rândurile sunt considerate egale È™i această funcÈ›ie returnează întotdeauna 1. + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + unclear translation - 'peer' + () Numărul grupului egal al rândului curent în cadrul partiÈ›iei sale - rangul rândului curent fără goluri. PartiÈ›iile sunt numerotate începând cu 1 în ordinea definită de clauza ORDER BY în definiÈ›ia ferestrei. Dacă nu există o clauză ORDER BY, atunci toate rândurile sunt considerate egale, iar această funcÈ›ie returnează întotdeauna 1. + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () ÃŽn ciuda numelui, această funcÈ›ie returnează întotdeauna o valoare între 0,0 È™i 1,0 egală cu (rang - 1)/(rânduri-partiÈ›ie - 1), unde rang este valoarea returnată de funcÈ›ia rank() încorporată în fereastră, iar rânduri-partiÈ›ie este numărul total de rânduri din partiÈ›ie. Dacă partiÈ›ia conÈ›ine doar un singur rând, această funcÈ›ie returnează 0,0. + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + unclear translation - 'peer' + () DistribuÈ›ia cumulativă. Calculată ca număr-rând/rânduri-partiÈ›ie, unde număr-rând este valoarea returnată de row_number() pentru ultimul egal din grup, iar rânduri-partiÈ›ie, numărul de rânduri din partiÈ›ie. + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) Argumentul N este tratat ca un număr întreg. Această funcÈ›ie împarte partiÈ›ia în N grupuri cât mai uniform posibil È™i atribuie fiecărui grup un număr întreg cuprins între 1 È™i N, în ordinea definită de clauza ORDER BY sau, în caz contrar, în ordine arbitrară. Dacă este necesar, grupurile mai mari apar primele. Această funcÈ›ie returnează valoarea întreagă atribuită grupului din care face parte rândul curent. + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) Returnează rezultatul evaluării expresiei expr în raport cu rândul anterior din partiÈ›ie. Sau, dacă nu există un rând anterior (deoarece rândul curent este primul), NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr,offset) Dacă este furnizat argumentul offset, atunci acesta trebuie să fie un număr întreg non-negativ. ÃŽn acest caz, valoarea returnată este rezultatul evaluării expr împotriva rândurilor row offset înaintea rândului curent din partiÈ›ie. Dacă offset este 0, atunci expr este evaluat împotriva rândului curent. Dacă nu există rânduri row offset înaintea rândului curent, se returnează NULL. + + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,offset,default) Dacă se furnizează È™i default, atunci acesta este returnat în loc de NULL dacă rândul identificat de offset nu există. + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) Returnează rezultatul evaluării expresiei expr în raport cu următorul rând din partiÈ›ie. Sau, dacă nu există un rând următor (deoarece rândul curent este ultimul), NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,offset) Dacă este furnizat argumentul offset, atunci acesta trebuie să fie un număr întreg non-negativ. ÃŽn acest caz, valoarea returnată este rezultatul evaluării expr împotriva rândurilor row offset după rândul curent din partiÈ›ie. Dacă offset este 0, atunci expr este evaluat împotriva rândului curent. Dacă nu există rânduri row offset după rândul curent, se returnează NULL. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) Această funcÈ›ie windows încorporată calculează cadrul ferestrei pentru fiecare rând în acelaÈ™i mod ca o funcÈ›ie windows agregată. Returnează valoarea lui expr evaluată în raport cu primul rând din cadrul ferestrei pentru fiecare rând. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) Această funcÈ›ie windows încorporată calculează cadrul ferestrei pentru fiecare rând în acelaÈ™i mod ca o funcÈ›ie windows agregată. Returnează valoarea lui expr evaluată în raport cu ultimul rând din cadrul ferestrei pentru fiecare rând. + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr,N) Această funcÈ›ie windows încorporată calculează cadrul ferestrei pentru fiecare rând în acelaÈ™i mod ca o funcÈ›ie windows agregată. Returnează valoarea lui expr evaluată în raport cu rândul N din cadrul ferestrei. Rândurile sunt numerotate în cadrul ferestrei începând de la 1 în ordinea definită de clauza ORDER BY, dacă este unul prezent, sau în ordine arbitrară în caz contrar. Dacă nu există al N-lea rând în partiÈ›ie, atunci se returnează NULL. + + + + (X) Return the arccosine of X. The result is in radians. + (X) Returnează arccosinusul lui X. Rezultatul este în radiani. + + + + (X) Return the hyperbolic arccosine of X. + (X) Returnează arccosinusul hiperbolic al lui X. + + + + (X) Return the arcsine of X. The result is in radians. + (X) Returnează arcsinusul lui X. Rezultatul este în radiani. + + + + (X) Return the hyperbolic arcsine of X. + (X) Returnează arcsinusul hiperbolic al lui X. + + + + (X) Return the arctangent of X. The result is in radians. + (X) Returnează arctangenta lui X. Rezultatul este în radiani. + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + (X,Y) Returnează arctangenta lui Y/X. Rezultatul este în radiani. Rezultatul este plasat în cadranul corect în funcÈ›ie de semnele lui X È™i Y. + + + + (X) Return the hyperbolic arctangent of X. + (X) Returnează arctangenta hiperbolică a lui X. + + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + (X) Returnează prima valoare întreagă reprezentabilă mai mare sau egală cu X. Pentru valori pozitive ale lui X, această rutină rotunjeÈ™te de la zero. Pentru valori negative ale lui X, această rutină rotunjeÈ™te spre zero. + + + + (X) Return the cosine of X. X is in radians. + (X) Returnează cosinusul lui X. X este în radiani. + + + + (X) Return the hyperbolic cosine of X. + (X) Returnează cosinusul hiperbolic al lui X. + + + + (X) Convert value X from radians into degrees. + (X) ConverteÈ™te valoarea X din radiani în grade. + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + (X) Calculează e (numărul lui Euler, aproximativ 2.71828182845905) ridicat la puterea X. + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + (X) Returnează prima valoare întreagă reprezentabilă mai mică sau egală cu X. Pentru numere pozitive, această funcÈ›ie rotunjeÈ™te spre zero. Pentru numere negative, această funcÈ›ie rotunjeÈ™te de la zero. + + + + (X) Return the natural logarithm of X. + (X) Returnează logaritmul natural al lui X. + + + + (B,X) Return the base-B logarithm of X. + (B,X) Returnează logaritmul în baza-B al lui X. + + + + + (X) Return the base-10 logarithm for X. + (X) Returnează logaritmul în baza-10 pentru X. + + + + (X) Return the logarithm base-2 for the number X. + (X) Returnează logaritmul în baza-2 pentru numărul X. + + + + (X,Y) Return the remainder after dividing X by Y. + (X,Y) Returnează restul după împărÈ›irea lui X la Y. + + + + () Return an approximation for Ï€. + () Returnează o aproximare pentru Ï€. + + + + + (X,Y) Compute X raised to the power Y. + (X,Y) Calculează X ridicat la puterea Y. + + + + (X) Convert X from degrees into radians. + (X) ConverteÈ™te X din grade în radiani. + + + + (X) Return the sine of X. X is in radians. + (X) Returnează sinusul lui X. X este în radiani. + + + + (X) Return the hyperbolic sine of X. + (X) Returnează sinusul hiperbolic al lui X. + + + + (X) Return the square root of X. NULL is returned if X is negative. + (X) Returnează rădăcina pătrată a lui X. Este returnat NULL dacă X este negativ. + + + + (X) Return the tangent of X. X is in radians. + (X) Returnează tangenta lui X. X este în radiani. + + + + (X) Return the hyperbolic tangent of X. + (X) Returnează tangenta hiperbolică a lui X. + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + (X) Returnează numărul întreg reprezentabil cuprins între X È™i 0 (inclusiv) care este cel mai îndepărtat de zero. Sau, cu alte cuvinte, returnează partea întreagă a lui X, rotunjind spre zero. + + + + SqliteTableModel + + + reading rows + citind rânduri + + + + loading... + încărcare... + + + + References %1(%2) +Hold %3Shift and click to jump there + ReferinÈ›ele %1(%2) +ÈšineÈ›i apăsat %3Shift È™i faceÈ›i clic pentru a sări acolo + + + + Error changing data: +%1 + Eroare la modificarea datelor: +%1 + + + + retrieving list of columns + recuperare listă de coloane + + + + Fetching data... + unclear translation - 'fetch' + Preluarea datelor... + + + + + Cancel + Anulare + + + + TableBrowser + + + Browse Data + Răsfoire Date + + + + &Table: + &Tabel: + + + + Select a table to browse data + Selectează un tabel pentru a răsfoi date + + + + Use this list to select a table to be displayed in the database view + Utilizează această listă pentru a selecta un tabel care să fie afiÈ™at în vizualizarea bazei de date + + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + Aceasta este vizualizarea tabelului bazei de date. PuteÈ›i efectua următoarele acÈ›iuni: + - ÃŽncepeÈ›i să scrieÈ›i pentru editarea în linie a valorii. + - FaceÈ›i dublu clic pe orice înregistrare pentru a edita conÈ›inutul în fereastra editorului de celule. + - Alt+Del pentru È™tergerea conÈ›inutului celulei la NULL. + - Ctrl+" pentru duplicarea înregistrării curente. + - Ctrl+' pentru copierea valorii din celula de mai sus. + - OperaÈ›ii standard de selecÈ›ie È™i copiere/lipire. + + + + Text pattern to find considering the checks in this frame + Model de text de găsit având în vedere verificările din acest cadru + + + + Find in table + GăseÈ™te în tabel + + + + Find previous match [Shift+F3] + GăseÈ™te potrivirea anterioară [Shift+F3] + + + + Find previous match with wrapping + GăseÈ™te potrivirea anterioară cu înfășurare + + + + Shift+F3 + Shift+F3 + + + + Find next match [Enter, F3] + GăseÈ™te următoarea potrivire [Enter, F3] + + + + Find next match with wrapping + GăseÈ™te următoarea potrivire cu înfășurare + + + + F3 + F3 + + + + The found pattern must match in letter case + Modelul găsit trebuie să se potrivească în cazul literelor + + + + Case Sensitive + Caz Sensibil + + + + The found pattern must be a whole word + Modelul găsit trebuie să fie un cuvânt întreg + + + + Whole Cell + ÃŽntreaga Celulă + + + + Interpret search pattern as a regular expression + Interpretează modelul de căutare ca expresie regulată + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>Când este bifat, modelul de găsit este interpretat ca o expresie regulată UNIX. Vezi <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + Regular Expression + Expresie Regulată + + + + + Close Find Bar + ÃŽnchide Bara De Căutare + + + + Text to replace with + Text de înlocuit cu + + + + Replace with + ÃŽnlocuire cu + + + + Replace next match + ÃŽnlocuieÈ™te următoarea potrivire + + + + + Replace + ÃŽnlocuire + + + + Replace all matches + ÃŽnlocuieÈ™te toate potrivirile + + + + Replace all + ÃŽnlocuire toate + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>Derulează până la început</p></body></html> + + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>Făcând clic pe acest buton navighezi la început în vizualizarea tabelului de mai sus.</p></body></html> + + + + |< + |< + + + + Scroll one page upwards + Derulează o pagină în sus + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>Făcând clic pe acest buton navighezi o pagină de înregistrări în sus în vizualizarea tabelului de mai sus.</p></body></html> + + + + < + < + + + + 0 - 0 of 0 + 0 - 0 din 0 + + + + Scroll one page downwards + Derulează o pagină în jos + + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>Făcând clic pe acest buton navighezi o pagină de înregistrări în jos în vizualizarea tabelului de mai sus.</p></body></html> + + + + > + > + + + + Scroll to the end + Derulează până la sfârÈ™it + + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>Făcând clic pe acest buton navighezi până la capăt în vizualizarea tabelului de mai sus.</p></body></html> + + + + >| + >| + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>FaceÈ›i clic aici pentru a trece la înregistrarea specificată</p></body></html> + + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>Acest buton este utilizat pentru a naviga la numărul de înregistrare specificat în zona Mergi la.</p></body></html> + + + + Go to: + Mergi la: + + + + Enter record number to browse + IntroduceÈ›i numărul de înregistrare pentru a naviga + + + + Type a record number in this area and click the Go to: button to display the record in the database view + IntroduceÈ›i un număr de înregistrare în această zonă È™i faceÈ›i clic pe butonul Mergi la: pentru a afiÈ™a înregistrarea în vizualizarea bazei de date + + + + 1 + 1 + + + + Show rowid column + AfiÈ™ează coloana rowid + + + + Toggle the visibility of the rowid column + Comută vizibilitatea coloanei rowid + + + + Unlock view editing + Deblochează editarea vizualizării + + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + Acest lucru deblochează vizualizarea curentă pentru editare. Cu toate acestea, veÈ›i avea nevoie de declanÈ™atoare adecvate pentru editare. + + + + Edit display format + Editează formatul de afiÈ™are + + + + Edit the display format of the data in this column + Editează formatul de afiÈ™are a datelor din această coloană + + + + + New Record + ÃŽnregistrare Nouă + + + + + Insert a new record in the current table + Inserează o înregistrare nouă în tabelul curent + + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>Acest buton creează o înregistrare nouă în baza de date. ÈšineÈ›i apăsat butonul mouse-ului pentru a deschide un meniu pop-up cu diferite opÈ›iuni:</p><ul><li><span style=" font-weight:600;">ÃŽnregistrare Nouă</span>: inserează o înregistrare nouă cu valori implicite în baza de date.</li><li><span style=" font-weight:600;">Inserare Valori...</span>: deschide un dialog pentru introducerea valorilor înainte ca acestea să fie inserate în baza de date. Asta permite introducerea valorilor care îndeplinesc diferitele constrângeri. Acest dialog este, de asemenea, deschis dacă opÈ›iunea <span style=" font-weight:600;">ÃŽnregistrare Nouă</span> nu reuÈ™eÈ™te din cauza acestor constrângeri.</li></ul></body></html> + + + + + Delete Record + Șterge ÃŽnregistrare + + + + Delete the current record + Șterge înregistrarea curentă + + + + + This button deletes the record or records currently selected in the table + Acest buton È™terge înregistrarea sau înregistrările selectate în prezent în tabel + + + + + Insert new record using default values in browsed table + Introduce o înregistrare nouă utilizănd valori implicite în tabelul navigat + + + + Insert Values... + Inserează Valori... + + + + + Open a dialog for inserting values in a new record + Deschide un dialog pentru inserarea valorilor într-o înregistrare nouă + + + + Export to &CSV + Exportă în &CSV + + + + + Export the filtered data to CSV + Exportă datele filtrate la CSV + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + Acest buton exportă datele din tabelul navigat, aÈ™a cum este afiÈ™at în prezent (după filtre, formate de afiÈ™are È™i coloană de ordine), ca fiÈ™ier CSV. + + + + Export to &JSON + Exportă în &JSON + + + + + Export the filtered data to JSON + Exportă datele filtrate în JSON + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + Acest buton exportă datele tabelului navigat, aÈ™a cum este afiÈ™at în prezent (după filtre, formate de afiÈ™are È™i coloană de ordine), ca fiÈ™ier JSON. + + + + Save as &view + Salvează ca &vedere + + + + + Save the current filter, sort column and display formats as a view + Salvează filtrul curent, coloana de sortare È™i formatele de afiÈ™are ca o vedere + + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + Acest buton salvează setarea curentă ale tabelului navigat (filtre, formate de afiÈ™are È™i coloană de ordine) ca vedere SQL pe care o puteÈ›i naviga ulterior sau utiliza în instrucÈ›iuni SQL. + + + + Save Table As... + Salvează Tabelul Ca... + + + + + Save the table as currently displayed + Salvează tabelul aÈ™a cum este afiÈ™at în prezent + + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>Acest meniu pop-up oferă următoarele opÈ›iuni care se aplică tabelului navigat È™i filtrat în prezent:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Exportă în CSV: această opÈ›iune exportă datele din tabelul navigat, aÈ™a cum este afiÈ™ate în prezent (după filtre, formate de afiÈ™are È™i coloană de ordine) într-un fiÈ™ier CSV.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Salvează ca vedere: această opÈ›iune salvează setarea curentă a tabelului navigat (filtre, formate de afiÈ™are È™i coloană de ordine) ca vedere SQL pe care o puteÈ›i răsfoi ulterior sau utiliza în instrucÈ›iuni SQL.</li></ul></body></html> + + + + Hide column(s) + Ascunde coloană(e) + + + + Hide selected column(s) + Ascunde coloana(ele) selectate + + + + Show all columns + AfiÈ™ează toate coloanele + + + + Show all columns that were hidden + AfiÈ™aÈ›i toate coloanele care au fost ascunse + + + + + Set encoding + Setează codificarea + + + + Change the encoding of the text in the table cells + Modifică codificarea textului în celulele tabelului + + + + Set encoding for all tables + Setează codificarea pentru toate tabelele + + + + Change the default encoding assumed for all tables in the database + Modifică codificarea implicită asumată pentru toate tabelele din baza de date + + + + Copy column name + Copiază numele coloanei + + + + Copy the database table column name to your clipboard + Copiază numele coloanei tabelului bazei de date în clipboard-ul dumneavoastră + + + + Clear Filters + Șterge Filtrele + + + + Clear all filters + Șterge toate filtrele + + + + + This button clears all the filters set in the header input fields for the currently browsed table. + Acest buton È™terge toate filtrele setate în câmpurile de introducere a antetului pentru tabelul navigat în prezent. + + + + Clear Sorting + Șterge Sortarea + + + + Reset the order of rows to the default + Resetează ordinea rândurilor la cea implicită + + + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + Acest buton È™terge coloanele de sortare specificate pentru tabelul navigat în prezent È™i revine la ordinea implicită. + + + + Print + Imprimare + + + + Print currently browsed table data + Imprimează datele tabelului navigat în prezent + + + + Print currently browsed table data. Print selection if more than one cell is selected. + Imprimează datele tabelului navigat în prezent. Imprimează selecÈ›ia dacă este selectată mai mult de o celulă. + + + + Ctrl+P + Ctrl+P + + + + New Data Browser + Navigator De Date Nou + + + + + Add a new docked Data Browser + Adaugă un nou Navigator De Date ancorat + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + Acest buton adaugă un nou Navigator De Date ancorat, pe care îl puteÈ›i detaÈ™a È™i aranja în diferite aspecte. + + + + Refresh + Reîmprospătare + + + + Refresh the data in the selected table + Reîmprospătează datele in tabelul selectat + + + + This button refreshes the data in the currently selected table. + Acest buton reîmprospătează datele din tabelul selectat în prezent. + + + + F5 + F5 + + + + Find in cells + GăseÈ™te în celule + + + + Open the find tool bar which allows you to search for values in the table view below. + Deschide bara de instrumente de căutare care vă permite să căutaÈ›i valori în vizualizarea tabelului de mai jos. + + + + + Bold + ÃŽngroÈ™at + + + + Ctrl+B + Ctrl+B + + + + + Italic + ÃŽnclinat + + + + + Underline + Subliniat + + + + Ctrl+U + Ctrl+U + + + + + Align Right + Aliniere La Dreapta + + + + + Align Left + Aliniere La Stânga + + + + + Center Horizontally + Centrare Orizontală + + + + + Justify + Justifică + + + + + Edit Conditional Formats... + Editează formatele condiÈ›ionate ... + + + + Edit conditional formats for the current column + Editează formatele condiÈ›ionate pentru coloana curentă + + + + Clear Format + Șterge Format + + + + Clear All Formats + Șterge Toate Formatele + + + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + Șterge toate formatările de celulă din celulele selectate È™i toate formatele condiÈ›ionate din coloanele selectate + + + + + Font Color + Culoare Font + + + + + Background Color + Culoare Fundal + + + + Toggle Format Toolbar + Comutare Bară De Instrumente De Format + + + + Show/hide format toolbar + AfiÈ™ează/ascunde bara de instrumente de format + + + + + This button shows or hides the formatting toolbar of the Data Browser + Acest buton afiÈ™ează sau ascunde bara de instrumente de formatare a Navigatoruli De Date + + + + Select column + Selectează coloana + + + + Ctrl+Space + Ctrl+Space + + + + Replace text in cells + ÃŽnlocuire text în celule + + + + Freeze columns + ÃŽngheață coloanele + + + + Make all columns from the first column up to this column not move when scrolling horizontally + FaceÈ›i toate coloanele de la prima coloană până la această coloană să nu se miÈ™te atunci când derulaÈ›i orizontal + + + + Ctrl+R + Ctrl+R + + + + %n row(s) + + %n rând + %n rânduri + %n rânduri + + + + + , %n column(s) + + , %n coloană + , %n coloane + , %n coloane + + + + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . Sumă: %1; Medie: %2; Minim: %3; Maxim: %4 + + + + Conditional formats for "%1" + Formate condiÈ›ionate pentru "%1" + + + + determining row count... + determinând numărul de rânduri... + + + + Filter in any column + Filtrează în orice coloană + + + + %L1 - %L2 of >= %L3 + %L1 - %L2 din >= %L3 + + + + %L1 - %L2 of %L3 + %L1 - %L2 din %L3 + + + + (clipped at %L1 rows) + (tăiat la %L1 rânduri) + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + Vă rugăm introduceÈ›i o pseudo-cheie primară pentru a activa editarea în această vedere. Acesta ar trebui să fie numele unei coloane unice în vedere. + + + + Delete Records + Șterge ÃŽnregistrările + + + + Duplicate records + ÃŽnregistrări duplicate + + + + Duplicate record + ÃŽnregistrare duplicată + + + + Ctrl+" + Ctrl+" + + + + Adjust rows to contents + Ajustează rândurile la conÈ›inut + + + + Error deleting record: +%1 + Eroare la È™tergerea înregistrării: +%1 + + + + Please select a record first + Vă rugăm să selectaÈ›i mai întâi o înregistrare + + + + Please choose a new encoding for all tables. + Vă rugăm să alegeÈ›i o nouă codificare pentru toate tabelele. + + + + Please choose a new encoding for this table. + Vă rugăm să alegeÈ›i o nouă codificare pentru acest tabel. + + + + %1 +Leave the field empty for using the database encoding. + %1 +LăsaÈ›i câmpul gol pentru utilizarea codificării bazei de date. + + + + This encoding is either not valid or not supported. + Această codificare nu este validă sau nu este suportată. + + + + %1 replacement(s) made. + %1 înlocuire(i) efectuată. + + + + TableBrowserDock + + + New Data Browser + Navigator De Date Nou + + + + Rename Data Browser + Redenumire Navigator De Date + + + + Close Data Browser + ÃŽnchidere Navigator De Date + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + Setează un nume nou pentru navigatorul de date. Utilizează caracterul '&&' pentru a permite utilizarea următorului caracter ca o comandă rapidă de la tastatură. + + + + VacuumDialog + + + Compact Database + Compactare Bază De Date + + + + Warning: Compacting the database will commit all of your changes. + Avertisment: Compactarea bazei de date va comite toate modificările. + + + + Please select the databases to co&mpact: + Vă rugăm să selectaÈ›i bazele de date pentru co&mpactare: + + + diff --git a/src/translations/sqlb_ru.ts b/src/translations/sqlb_ru.ts old mode 100755 new mode 100644 index 4417b6599..bc4fb6ba8 --- a/src/translations/sqlb_ru.ts +++ b/src/translations/sqlb_ru.ts @@ -1,6 +1,6 @@ - + AboutDialog @@ -9,2796 +9,8017 @@ О программе Обозреватель Ð´Ð»Ñ SQLite - + Version ВерÑÐ¸Ñ - - <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:small;">It also uses the Silk icon set by Mark James licensed under a Creative Commons Attribution 2.5 and 3.0 license.<br/>See </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> - <html><head/><body><p>Обозреватель Ð´Ð»Ñ SQLite - Ñто беÑÐ¿Ð»Ð°Ñ‚Ð½Ð°Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð°, Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ñ‹Ð¼ иÑходным кодом, Ð¿Ñ€ÐµÐ´Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ð°Ñ Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð°Ð· данных SQLite.</p><p>Программа лицензирована по двум лицензиÑм: Mozilla Public License Version 2 и GNU General Public License Version 3 or later. Можно изменÑть или раÑпроÑтранÑть её на уÑловиÑÑ… Ñтих лицензий.</p><p>Лицензии можно проÑмотреть по ÑÑылкам <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> и <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a>.</p><p>Дополнительную информацию о программе можно узнать на веб-Ñайте:<br/><a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">Это программное обеÑпечение иÑпользует GPL/LGPL Qt Toolkit </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>УÑÐ»Ð¾Ð²Ð¸Ñ Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ð¸ на Qt Toolkit </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;">.</span></p><p><span style=" font-size:small;">Эта программа также иÑпользует набор иконок Silk от Марка ДжеймÑа (Mark James), лицензированный под лицензией Creative Commons Attribution 2.5 and 3.0.<br/>ÐŸÐ¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¿Ð¾ адреÑу </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;">.</span></p></body></html> + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + <html><head/><body><p>DB Browser for SQLite Ñто Ñвободно раÑпроÑтранÑÐµÐ¼Ð°Ñ ÑƒÑ‚Ð¸Ð»Ð¸Ñ‚Ð° Ð´Ð»Ñ Ð²Ð¸Ð·ÑƒÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ð¸ разработки, ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð°Ð· данных SQLite Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ñ‹Ð¼ иÑходным кодом.</p><p>Он раÑпроÑтранÑетÑÑ Ð¿Ð¾Ð´ двойной лицензией Mozilla Public License верÑии 2, а также под лицензией GNU General Public License верÑии 3 или более поздней. Ð’Ñ‹ можете изменÑть или раÑпроÑтранÑть его в ÑоответÑтвии Ñ ÑƒÑловиÑми Ñтих лицензий.</p><p>ПоÑетите <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> и <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ñтей.</p><p>Больше информации об Ñтой программе можно получить, поÑетив нашу Ñтраницу: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">Эта программа иÑпользует GPL/LGPL Qt Toolkit от </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>Смотри </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> Ñ Ñ‚Ñ€ÐµÐ±Ð¾Ð²Ð°Ð½Ð¸Ñми лицензии и информацией.</span></p><p><span style=" font-size:8pt;">Мы иÑпользуем библиотеку nalgeon/sqlean Ð´Ð»Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¸ раÑширений SQLite.<br/>Эта библиотека лицензирована по лицензии MIT, Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информации Ñмотри:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">Программа также иÑпользует набор иконок Pastel SVG, Ñозданный Michael Buckley по лицензии Creative Commons Attribution Share Alike 4.0.<br/>Смотри: </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ñтей.</span></p></body></html> + + + AddRecordDialog - - Version - ВерÑÐ¸Ñ + + Add New Record + Добавить новую запиÑÑŒ - - Qt Version - ВерÑÐ¸Ñ Qt + + Enter values for the new record considering constraints. Fields in bold are mandatory. + Введите Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð½Ð¾Ð²Ð¾Ð¹ запиÑи Ñ ÑƒÑ‡ÐµÑ‚Ð¾Ð¼ ограничений. ПолÑ, выделенные жирным шрифтом, ÑвлÑÑŽÑ‚ÑÑ Ð¾Ð±Ñзательными. - - SQLCipher Version - ВерÑÐ¸Ñ SQLCipher + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + Ð’ Ñтолбце "Значение" вы можете указать значение Ð´Ð»Ñ Ð¿Ð¾Ð»Ñ, указанного в Ñтолбце "ИмÑ". Ð’ Ñтолбце "Тип" указываетÑÑ Ñ‚Ð¸Ð¿ полÑ. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию отображаютÑÑ Ð² том же Ñтиле, что и Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ NULL. - - SQLite Version - ВерÑÐ¸Ñ SQLite + + Name + Ð˜Ð¼Ñ - - - Application - - Usage: %1 [options] [db] - - + + Type + Тип - - Possible command line arguments: - + + Value + Значение - - -h, --help Show command line options - + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð²Ñтавки. Предварительно заполненные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию вÑтавлÑÑŽÑ‚ÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки, еÑли они не изменены. - - -s, --sql [file] Execute this SQL file after opening the DB - + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + Когда вы редактируете Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² верхнем окне, здеÑÑŒ отображаетÑÑ Ð·Ð°Ð¿Ñ€Ð¾Ñ SQL Ð´Ð»Ñ Ð²Ñтавки Ñтой новой запиÑи. Ð’Ñ‹ можете вручную отредактировать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð¿ÐµÑ€ÐµÐ´ Ñохранением. - - -q, --quit Exit application after running scripts - + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">Сохранение</span> отправит показанный оператор SQL в БД Ð´Ð»Ñ Ð²Ñтавки новой запиÑи.</p><p><span style=" font-weight:600;">ВоÑÑтановить Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию</span> воÑÑтановит иÑходные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² колонке <span style=" font-weight:600;">Значение</span>.</p><p><span style=" font-weight:600;">Отмена</span> закрывает Ñтот диалог без Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñов.</p></body></html> - - [file] Open this SQLite database - + + Auto-increment + + Ðвтоинкремент + - - The -s/--sql option requires an argument - + + Unique constraint + + УникальноÑÑŒ + - - The file %1 does not exist - + + Check constraint: %1 + + Проверка: %1 + - - Invalid option/non-existant file: %1 - + + Foreign key: %1 + + Внешний ключ: %1 + - - - CipherDialog - - SQLCipher encryption - Шифрование SQLCipher + + Default value: %1 + + Значение по умолчанию: %1 + - - &Password - &Пароль + + Error adding record. Message from database engine: + +%1 + Ошибка Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñи. Сообщение из базы данных: + +%1 - - &Reenter password - Пароль &ещё раз + + Are you sure you want to restore all the entered values to their defaults? + Ð’Ñ‹ дейÑтвительно хотите воÑÑтановить вÑе введенные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию? + + + Application - - Page &size - Размер &Ñтраницы + + Possible command line arguments: + Возможные аргументы коммандной Ñтроки: - - Please set a key to encrypt the database. -Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. -Leave the password fields empty to disable the encryption. -The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. - ПожалуйÑта укажите ключ шифрованиÑ. -ЕÑли вы измените какую-либо опциональную наÑтройку, то ее нужно будет вводить при каждом открытии Ñтого файла базы данных. -ОÑтавьте пароль пуÑтым еÑли шифрование не требуетÑÑ. -ПроцеÑÑ Ð¼Ð¾Ð¶ÐµÑ‚ занÑть некоторое Ð²Ñ€ÐµÐ¼Ñ Ð¸ наÑтоÑтельно рекомендуем Ñоздать резервную копию перед продолжением! Ðе Ñохраненные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки будут Ñохранены. + + The user settings file location is replaced with the argument value instead of the environment variable value. + РаÑположение файла наÑтроек Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð·Ð°Ð¼ÐµÐ½ÑетÑÑ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸ÐµÐ¼ аргумента вмеÑто Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð¾Ð¹ Ñреды. - - Please enter the key used to encrypt the database. -If any of the other settings were altered for this database file you need to provide this information as well. - ПожалуйÑта введите ключ Ð´Ð»Ñ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð°Ð·Ñ‹ данных. -ЕÑли любые другие наÑтройки были изменены Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ базы данный то нужно так же предоÑтавить данную информацию. + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + Игнорируемое значение переменной Ñреды (DB4S_SETTINGS_FILE): - - - CreateIndexDialog - - Create New Index - Создание нового индекÑа + + + The file %1 does not exist + Файл %1 не ÑущеÑтвует - - &Name - &Ð˜Ð¼Ñ + + Usage + ИÑпользование - - &Columns - &Столбцы + + options + опции - - Column - Столбец + + + database + база данных - - Use in Index - ИÑпользовать в индекÑе + + + project + проект - - Order - Сортировка + + + csv-file + csv-файл - - &Table - &Таблица + + Show command line options + Показать опции коммандной Ñтроки - - &Unique - &Уникальный + + Exit application after running scripts + Выход из Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñле Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñкрипта - - Creating the index failed: -%1 - Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа: -%1 + + + file + файл - - - DBBrowserDB - - - - - no error - нет ошибки + + Execute this SQL file after opening the DB + Выполнить Ñтот SQL файл поÑле Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð‘Ð” - - Please specify the database name under which you want to access the attached database - + + Import this CSV file into the passed DB or into a new DB + Импорт Ñтого CSV-файла в ÑущеÑтвующую БД или в новую БД - - Do you want to save the changes made to the database file %1? - Сохранить Ñделанные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² файле базы данных %1? + + table + таблица - - Exporting database to SQL file... - ЭкÑпорт базы данных в файл SQL... + + Browse this table, or use it as target of a data import + ПроÑмотр таблицы или ипользование ее как Ð¿Ð¾Ð»ÑƒÑ‡Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€ÑƒÐµÐ¼Ñ‹Ñ… данных - - - Cancel - Отменить + + Open database in read-only mode + Открыть базу данных только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ - - Executing SQL... - Выполнить код SQL... + + settings_file + файл_наÑтроек - - Action cancelled. - ДейÑтвие отменено. + + Run application based on this settings file + ЗапуÑк на оÑнове Ñтого файла наÑтоек - - - Error in statement #%1: %2. -Aborting execution. - Ошибка в операторе #%1: %2. Прерывание выполнениÑ. + + + group + группа - - renameColumn: cannot find table %1. - переименованиеСтолбца: невозможно найти таблицу %1. + + + settings + уÑтановки - - renameColumn: cannot find column %1. - переименованиеСтолбца: невозможно найти Ñтолбец %1. + + + value + значение - - renameColumn: creating savepoint failed. DB says: %1 - переименованиеСтолбца: ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ‚Ð¾Ñ‡ÐºÐ¸ ÑохранениÑ. БД говорит: %1 + + Run application with this setting temporarily set to value + ЗапуÑк приложениÑ, Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ð¼ значением Ñтого параметра - - renameColumn: creating new table failed. DB says: %1 - переименованиеСтолбца: ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð¹ таблицы. БД говорит: %1 + + Run application saving this value for this setting + ЗапуÑтить приложение, Ñохранив Ñто значение Ð´Ð»Ñ Ñтого параметра - - renameColumn: copying data to new table failed. DB says: -%1 - переименованиеСтолбца: ошибка ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… в новую таблицу. БД говорит: -%1 + + Display the current version + Показать текущую верÑию - - renameColumn: deleting old table failed. DB says: %1 - переименованиеСтолбца: ошибка ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñтарой таблицы. БД говорит: %1 + + Open this SQLite database + Открыть Ñту SQLite базу данных - - Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: - - - Ошибка воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… объектов, аÑÑоциированных Ñ Ñтой таблицей. Ðаиболее вероÑÑ‚Ð½Ð°Ñ Ð¿Ñ€Ð¸Ñ‡Ð¸Ð½Ð° Ñтого - изменение имён некоторых Ñтолбцов таблицы. Вот SQL оператор, который нужно иÑправить и выполнить вручную: + + Open this project file (*.sqbpro) + Открыть Ñтот файл проекта (*.sqbpro) - - renameColumn: releasing savepoint failed. DB says: %1 - переименованиеСтолбца: ошибока оÑÐ²Ð¾Ð±Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ñ‡ÐºÐ¸ ÑохранениÑ. БД говорит: %1 + + Import this CSV file into an in-memory database + Импорт Ñтот CSV файл в базу данных в памÑти - - Error renaming table '%1' to '%2'.Message from database engine: -%3 - Ошибка Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ñ‹ '%1' в '%2'.Сообщение от движка БД: -%3 + + + + The %1 option requires an argument + Ð”Ð»Ñ Ð¾Ð¿Ñ†Ð¸Ð¸ %1 требуетÑÑ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚ + + + + The -S/--settings option requires an argument. The option is ignored. + Параметр -S/--settings требует аргумента. Параметр игнорируетÑÑ. - - ... <string can not be logged, contains binary data> ... - ... <Ñтрока не может быть залогирована, Ñодержит двоичные данные> ... + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + Параметры -o/--option и -O/--save-option требуют аргумент в форме группа/наÑтройка=значение - - unknown object type %1 - неизвеÑтный тип объекта %1 + + Invalid option/non-existent file: %1 + ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð½Ð°Ñтройка/неÑущеÑтвующий файл: %1 - - could not get list of db objects: %1, %2 - невозможно получить ÑпиÑок объекто БД: %1, %2 + + SQLite Version + ВерÑÐ¸Ñ SQLite - - could not get types - невозможно получить типы + + SQLCipher Version %1 (based on SQLite %2) + SQLCipher верÑÐ¸Ñ %1 (на оÑнове SQLite %2) - - didn't receive any output from pragma %1 - не принÑто ни одного выхода из прагмы %1 + + DB Browser for SQLite Version %1. + DB Browser for SQLite ВерÑÐ¸Ñ %1. - - could not execute pragma command: %1, %2 - невозможно выполнить комманду-прагму: %1, %2 + + Last commit hash when built: %1 + ПоÑледний Ñ…Ñш коммита при Ñборке: %1 - - Error setting pragma %1 to %2: %3 - Ошибка уÑтановки прагмы %1 в %2: %3 + + Built for %1, running on %2 + Создано Ð´Ð»Ñ %1, работает на %2 - - File not found. - Файл не найден. + + Qt Version %1 + Qt ВерÑÐ¸Ñ %1 - DbStructureModel + CipherDialog - - Name - Ð˜Ð¼Ñ + + SQLCipher encryption + Шифрование SQLCipher - - Object - Объект + + &Password + &Пароль - - Type - Тип + + &Reenter password + Пароль &ещё раз - - Schema - Схема + + Encr&yption settings + ÐаÑтройки &ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ - - Tables (%1) - Таблицы (%1) + + SQLCipher &3 defaults + SQLCipher &3 - - Indices (%1) - ИндекÑÑ‹ (%1) + + SQLCipher &4 defaults + SQLCipher &4 - - Views (%1) - ПредÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ (%1) + + Custo&m + &Другой - - Triggers (%1) - Триггеры (%1) + + Page si&ze + Размер &Ñтраницы - - - EditDialog - - Edit database cell - Редактирование Ñчейки базы данных + + &KDF iterations + &KDF итераций - - Import text - Импортировать текÑÑ‚ + + HMAC algorithm + HMAC алгоритм - - Opens a file dialog used to import text to this database cell. - ОткрываетÑÑ Ñ„Ð°Ð¹Ð»Ð¾Ð²Ñ‹Ð¹ диалог, чтобы импортировать текÑтв Ñту Ñчейку базы данных. + + KDF algorithm + KDF алгоритм - - &Import - &Импортировать + + Plaintext Header Size + Размер открытого заголовка - - Export text - ЭкÑпортировать текÑÑ‚ + + Passphrase + Фраза - - Opens a file dialog used to export the contents of this database cell to a text file. - ОткрываетÑÑ Ñ„Ð°Ð¹Ð»Ð¾Ð²Ñ‹Ð¹ диалог, чтобы ÑкÑпоритровать Ñодержимое Ñтой Ñчейки базы данных в текÑтовый файл. + + Raw key + Ключ - - &Export - &ЭкÑпортировать + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + ПожалуйÑта укажите ключ шифрованиÑ. +ЕÑли вы измените какую-либо опциональную наÑтройку, то ее нужно будет вводить при каждом открытии Ñтого файла базы данных. +ОÑтавьте пароль пуÑтым еÑли шифрование не требуетÑÑ. +ПроцеÑÑ Ð¼Ð¾Ð¶ÐµÑ‚ занÑть некоторое Ð²Ñ€ÐµÐ¼Ñ Ð¸ наÑтоÑтельно рекомендуем Ñоздать резервную копию перед продолжением! Ðе Ñохраненные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ применены перед изменением шифрованиÑ. - - Text - ТекÑÑ‚ + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + ПожалуйÑта введите ключ Ð´Ð»Ñ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð°Ð·Ñ‹ данных. +ЕÑли любые другие наÑтройки были изменены Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ базы данных то нужно так же предоÑтавить данную информацию. + + + ColumnDisplayFormatDialog - - Binary - Двоичные данные + + Choose display format + Выберите формат Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ - - Clear cell data - ОчиÑтить Ñодержимое Ñчейки + + Display format + Формат Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ - - Erases the contents of the cell - ОчищаетÑÑ Ñодержимое Ñчейки + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + Выберите формат Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ ÐºÐ¾Ð»Ð¾Ð½ÐºÐ¸ '%1', который будет применен к каждому ее значению. - - &Clear - &ОчиÑтить + + Default + По умолчанию - - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Warning: Editing binary content in text mode may result in corrupted data!</span></p></body></html> - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Предупреждение: Редактирование двоичного Ñодержимого в текÑтовом режиме может привеÑти к порче данных!</span></p></body></html> + + Decimal number + ДеÑÑтичное чиÑло - - This area displays information about the data present in this database cell - Эта облаÑть отображает информацию о данных, находÑщихÑÑ Ð² Ñтой Ñчейке базы данных + + Exponent notation + ЭкÑÐ¿Ð¾Ð½ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ - - Type of data currently in cell - Тип данных в Ñчейке + + Hex blob + Бинарные данные - - Size of data currently in table - Размер данных в таблице + + Hex number + ШеÑтнадцатеричное чиÑло - - Choose a file - Выбрать файл + + Apple NSDate to date + Apple NSDate дата - - Text files(*.txt);;Image files(%1);;All files(*) - ТекÑтовые файлы(*.txt);;Файлы изображений(%1);;Ð’Ñе файлы(*) + + Java epoch (milliseconds) to date + Java epoch дата - - Choose a filename to export data - Выбрать Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° Ð´Ð»Ñ ÑкÑпорта данных + + .NET DateTime.Ticks to date + .NET DateTime.Ticks дата - - Text files(*.txt);;All files(*) - ТекÑтовые файлы(*.txt);;Ð’Ñе файлы(*) + + Julian day to date + ЮлианÑÐºÐ°Ñ Ð´Ð°Ñ‚Ð° - - Type of data currently in cell: Null - Тип данных в Ñчейке: Null + + Unix epoch to local time + Unix-локальное Ð²Ñ€ÐµÐ¼Ñ - - Type of data currently in cell: Text / Numeric - Тип данных в Ñчейке: ТекÑÑ‚ / ЧиÑловое + + WebKit / Chromium epoch to date + WebKit / Chromium epoch дата - - - %n char(s) - - %n Ñимвол - %n Ñимвола - %n Ñимволов - + + + WebKit / Chromium epoch to local time + WebKit / Chromium epoch локальное Ð²Ñ€ÐµÐ¼Ñ - - Type of data currently in cell: Image - Тип данных в Ñчейке: Изображение + + Date as dd/mm/yyyy + Дата в формате дд/мм/гггг - - %1x%2 pixel - %1x%2 пикÑелей + + Lower case + Ðижний региÑтр - - Type of data currently in cell: Binary - Тип данных в Ñчейке: Двоичные данные + + Binary GUID to text + Двоичный GUID в текÑÑ‚ - - - %n byte(s) - - %n байт - %n байта - %n байтов - + + + SpatiaLite Geometry to SVG + SpatiaLite Geometry в SVG - - - EditTableDialog - - Edit table definition - Редактирование Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹ + + Custom display format must contain a function call applied to %1 + ПользовательÑкий формат должен Ñодержать вызов функции, примененный к %1 - - Table - Таблица + + Error in custom display format. Message from database engine: + +%1 + Ошибка в пользовательÑком формате. Сообщение от Ñдра базы данных: + +%1 - - Advanced - Дополнительно + + Custom display format must return only one column but it returned %1. + ПользовательÑкий формат должен возвращать только один Ñтолбец, но он вернул %1. - - Make this a 'WITHOUT rowid' table. Setting this flag requires a field of type INTEGER with the primary key flag set and the auto increment flag unset. - Чтобы Ñоздать таблицу 'без rowid', нужно чтобы в ней был INTEGER первичный ключ Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ‹Ð¼ автоинкрементом. + + Octal number + ВоÑьмеричное чиÑло - - Without Rowid - Без rowid + + Round number + Округленное чиÑло - - Fields - ÐŸÐ¾Ð»Ñ + + Unix epoch to date + Unix-дата + + + + Upper case + Верхний региÑтр - - Add field - Добавить поле + + Windows DATE to date + Windows дата - - Remove field - Удалить поле + + Custom + Мой формат + + + CondFormatManager - - Move field up - ПеремеÑтить поле вверх + + Conditional Format Manager + Менеджер Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ - - Move field down - ПеремеÑтить поле вниз + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + Этот диалог позволÑет задавать формат Ñодержимого. Стиль каждой Ñчейки будет выбран в ÑоответÑтвии Ñ Ñодержимым. УÑÐ»Ð¾Ð²Ð¸Ñ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ перемещать вверх и вниз, те, что находÑÑ‚ÑÑ Ð²Ñ‹ÑˆÐµ, имеют приоритет над теми, что находÑÑ‚ÑÑ Ð½Ð¸Ð¶Ðµ. СинтакÑÐ¸Ñ Ð´Ð»Ñ Ñодержимого такой же, как и Ð´Ð»Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð¾Ð², а пуÑтое уÑловие применÑетÑÑ ÐºÐ¾ вÑем значениÑм. - - Name - Ð˜Ð¼Ñ + + Add new conditional format + Добавить новый формат - - Type - Тип + + &Add + &Добавить - - - Not null - Ðе пуÑтое (null) + + Remove selected conditional format + Удалить формат - - PK - ПК + + &Remove + &Удалить - - Primary key - Первичный ключ + + Move selected conditional format up + ПеремеÑтить вверх - - AI - ÐИ + + Move &up + Вверх - - Autoincrement - Ðвтоинкремент + + Move selected conditional format down + ПеремеÑтить вниз - - U - У + + Move &down + Вниз - - Unique - Уникальное + + Foreground + Передний план - - Default - По умолчанию + + Text color + Цвет текÑта - - Default value - Значение по умолчанию + + Background + Фон - - Check - Проверить + + Background color + Цвет фона - - Check constraint - Проверить ограничение + + Font + Шрифт - - Foreign Key - Внешний ключ + + Size + Размер - - Error creating table. Message from database engine: -%1 - Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹. Сообщение от движка базы данных: %1 + + Bold + Жирный - - There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. - СущеÑтвует по крайней мере одна Ñтрока, где Ñто поле уÑтановлено в NULL. УÑтановить Ñтот флаг нельзÑ. Сначала измените данные таблицы. + + Italic + КурÑив - - There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. - СущеÑтвует по крайней мере одна Ñтрока, где Ñто поле Ñодержит нечиÑловое значение. УÑтановить флаг ÐИ нельзÑ. Сначала измените данные таблицы. + + Underline + Подчёркнутый - - Column `%1` has no unique data. - - Столбец `%1` Ñодержит не уникальные данные. + + Alignment + Выравнивание - - This makes it impossible to set this flag. Please change the table data first. - Ðевозможно. Ð”Ð»Ñ Ð½Ð°Ñ‡Ð°Ð»Ð°, измените данные таблицы. + + Condition + Содержимое - - Are you sure you want to delete the field '%1'? -All data currently stored in this field will be lost. - Удалить поле '%1'? -Ð’Ñе данные, которые в наÑтоÑщий момент Ñохранены в Ñтом поле, будут потерÑны. + + + Click to select color + Выбор цвета - - Please add a field which meets the following criteria before setting the without rowid flag: - - Primary key flag set - - Auto increment disabled - Перед тем как применÑть флаг без rowid, пожалуйÑта убедитеÑÑŒ, что ÑущеÑтвует Ñтолбец, который: - - ÑвлÑетÑÑ Ð¿ÐµÑ€Ð²Ð¸Ñ‡Ð½Ñ‹Ð¹ ключом - - Ð´Ð»Ñ Ð½ÐµÐ³Ð¾ отключен автоинкремент + + Are you sure you want to clear all the conditional formats of this field? + Ð’Ñ‹ уверены, что хотите очиÑтить форматирование Ñтого полÑ? - ExportCsvDialog + DBBrowserDB - - Export data as CSV - ЭкÑпортировать данные в формате CSV + + Please specify the database name under which you want to access the attached database + Укажите Ð¸Ð¼Ñ Ð±Ð°Ð·Ñ‹ данных, под которым вы хотите получить доÑтуп к прикрепленной базе данных - - &Table(s) - &Таблица + + Invalid file format + Ошибочный формат файла - - &Column names in first line - &Имена Ñтолбцов в первой Ñтроке + + Do you want to save the changes made to the database file %1? + Сохранить Ñделанные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² файле базы данных %1? - - Field &separator - &Разделитель полей + + Exporting database to SQL file... + ЭкÑпорт базы данных в файл SQL... - - , - , - + + + Cancel + Отменить + - - ; - ; + + Executing SQL... + Выполнить SQL... - - - Tab - ТабулÑÑ†Ð¸Ñ + + Action cancelled. + ДейÑтвие отменено. - - | - | + + Do you really want to close this temporary database? All data will be lost. + Ð’Ñ‹ дейÑтвительно хотите закрыть Ñту временную БД? Ð’Ñе данные будут потерÑны. - - - Other - Другой + + Database didn't close correctly, probably still busy + База данных не закрылаÑÑŒ корректно, возможно, она вÑе еще занÑта - - &Quote character - &Символ кавычки + + Cannot open destination file: '%1' + Ðевозможно открыть целевой файл: '%1' - - " - " + + + Cannot backup to file: '%1'. Message: %2 + Ðевозможно Ñохранить резервную копию в файл: '%1'. Сообщение: %2 - - ' - ' + + The database is currently busy: + БД занÑта: - - Could not open output file: %1 - Ðе удалоÑÑŒ открыть выходной файл: %1 + + Do you want to abort that other operation? + Ð’Ñ‹ хотите отменить Ñту операцию? - - - Choose a filename to export data - Выберите Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° Ð´Ð»Ñ ÑкÑпорта данных + + + No database file opened + Файл БД не открыт - - - Text files(*.csv *.txt) - ТекÑтовые файлы(*.csv *.txt) + + + Error in statement #%1: %2. +Aborting execution%3. + Ошибка в выражении #%1: %2. +Выполнение прервано %3. - - Please select at least 1 table. - ПожалуйÑта, выберите Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одну таблицу. + + + and rolling back + и выполнÑетÑÑ Ð¾Ñ‚ÐºÐ°Ñ‚ - - Choose a directory - Выберать каталог + + didn't receive any output from %1 + не получил никаких выходных данных от %1 - - Export completed. - ЭкÑпорт завершён. + + could not execute command: %1 + не удалоÑÑŒ выполнить команду: %1 - - - ExportSqlDialog - - Export SQL... - ЭкÑпорт SQL.... + + Cannot delete this object + Ðе удаетÑÑ ÑƒÐ´Ð°Ð»Ð¸Ñ‚ÑŒ Ñтот объект - - &Table(s) - &Таблица + + Cannot set data on this object + Ðевозможно уÑтановить данные по Ñтому объекту - - &Options - &Опции + + + A table with the name '%1' already exists in schema '%2'. + Таблица Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ '%1' уже ÑущеÑтвует в Ñхеме '%2'. - - Keep column names in INSERT INTO - Ð˜Ð¼Ñ Ñтолбцов в выражении INSERT INTO + + No table with name '%1' exists in schema '%2'. + Ð’ Ñхеме '%2' нет таблицы Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ '%1'. - - New INSERT INTO syntax (multiple rows in VALUES) - Ðовый ÑинтакÑÐ¸Ñ INSERT INTO (неÑколько Ñтрок в VALUES) + + + Cannot find column %1. + Ðе найден Ñтолбец %1. - - Export schema only - ЭкÑпортировать только Ñхему данных + + Creating savepoint failed. DB says: %1 + Ðе удалоÑÑŒ Ñоздать точку ÑохранениÑ. Сообщение БД: %1 - - Please select at least 1 table. - ПожалуйÑта, выберите Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одну таблицу. + + Renaming the column failed. DB says: +%1 + Переименование колонки не удалоÑÑŒ. Сообщение БД: +%1 - - Choose a filename to export - Выберите Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° Ð´Ð»Ñ ÑкÑпорта + + + Releasing savepoint failed. DB says: %1 + Реализовать точку ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð½Ðµ удалоÑÑŒ. Сообщение БД: %1 - - Text files(*.sql *.txt) - ТекÑтовые файлы(*.sql *.txt) + + Creating new table failed. DB says: %1 + Создание новой таблицы не удалоÑÑŒ. Сообщение БД: %1 - - Export completed. - ЭкÑпорт завершён. + + Copying data to new table failed. DB says: +%1 + Копирование данных в новую таблицу не удалоÑÑŒ. Сообщение БД: %1 - - Export cancelled or failed. - ЭкÑпорт отменён или возникли ошибки. + + Deleting old table failed. DB says: %1 + Удаление Ñтарой таблицы не удалоÑÑŒ. Сообщение БД: %1 - - - FilterLineEdit - - Filter - Фильтр + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + Ошибка Ð¿ÐµÑ€ÐµÐ¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹ '%1' в '%2'. +Сообщение БД: +%3 - - - ImportCsvDialog - - Import CSV file - Импортировать файл в формате CSV + + could not get list of db objects: %1 + не удалоÑÑŒ получить ÑпиÑок объектов базы данных: %1 - - &Table name - &Ð˜Ð¼Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹ + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + Ошибка воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… объектов, аÑÑоциированных Ñ Ñтой таблицей. Ðаиболее вероÑÑ‚Ð½Ð°Ñ Ð¿Ñ€Ð¸Ñ‡Ð¸Ð½Ð° Ñтого - изменение имён некоторых Ñтолбцов таблицы. Вот SQL оператор, который нужно иÑправить и выполнить вручную: + + - - &Column names in first line - И&мена Ñтолбцов в первой Ñтроке + + could not get list of databases: %1 + не могу получить ÑпиÑок БД: %1 - - Field &separator - &Разделитель полей + + Error loading extension: %1 + Ошибка загрузки раÑширениÑ: %1 - - , - + + Error loading built-in extension: %1 + Ошибка загрузки вÑтроенного раÑширениÑ: %1 - - ; - + + could not get column information + не могу получить информацию о колонке - - - Tab - ТабулÑÑ†Ð¸Ñ + + Error setting pragma %1 to %2: %3 + Ошибка уÑтановки прагмы %1 в %2: %3 - - | - + + File not found. + Файл не найден. + + + DbStructureModel - - - - Other - Другой + + Name + Ð˜Ð¼Ñ - - &Quote character - &Символ кавычки + + Object + Объект - - " - + + Type + Тип - - ' - + + Schema + Схема - - &Encoding - &Кодировка + + Database + База данных - - UTF-8 - + + Browsables + ПроÑматриваемые - - UTF-16 - + + All + Ð’Ñе - - ISO-8859-1 - + + Temporary + Временный - - Trim fields? - Обрезать полÑ? + + Tables (%1) + Таблицы (%1) - - Inserting data... - Ð’Ñтавка данных... + + Indices (%1) + ИндекÑÑ‹ (%1) - - Cancel - Отменить + + Views (%1) + ПредÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ (%1) - - There is already a table of that name and an import into an existing table is only possible if the number of columns match. - Уже ÑущеÑтвует таблица Ñ Ñ‚Ð°ÐºÐ¸Ð¼ же именем, и импорт в ÑущеÑтвующую таблицу возможен, только еÑли чиÑло Ñтолбцов Ñовпадает. + + Triggers (%1) + Триггеры (%1) + + + EditDialog - - There is already a table of that name. Do you want to import the data into it? - Уже ÑущеÑтвует таблица Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем. Импортировать данные в неё? + + Edit database cell + Редактирование Ñчейки базы данных - - Creating restore point failed: %1 - Ошибка ÑÐ¾Ð·Ð½Ð°Ð½Ð¸Ñ Ñ‚Ð¾Ñ‡ÐºÐ¸ воÑÑтановлениÑ: %1 + + Mode: + Режим: - - Creating the table failed: %1 - Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹: %1 + + + Image + Изображение - - Missing field for record %1 - Пропущен Ñтолбец Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи %1 + + Set as &NULL + ПриÑвоить &NULL - - Inserting row failed: %1 - Ошибка вÑтавки Ñтроки: %1 + + Apply data to cell + Применить данные к Ñчейке - - - MainWindow - - DB Browser for SQLite - Обозреватель Ð´Ð»Ñ SQLite + + This button saves the changes performed in the cell editor to the database cell. + Ðажав Ñту кнопку, вы Ñохраните Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð½Ñ‹Ðµ в Ñтом редакторе, в ÑоответÑтвующую Ñчейку БД. - - Database &Structure - С&труктура БД + + Apply + Применить - - - toolBar1 - панельИнÑтрументов1 + + Text + ТекÑÑ‚ - - &Browse Data - &Данные + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + Это ÑпиÑок поддерживаемых режимов. Выберите режим Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра или Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… текущей Ñчейки. - - Table: - Таблица: + + RTL Text + RTL текÑÑ‚ - - Select a table to browse data - Выберите таблицу Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра данных + + Binary + Бинарный - - Use this list to select a table to be displayed in the database view - ИÑпользуйте Ñтот ÑпиÑок, чтобы выбрать таблицу, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° быть отображена в предÑтавлении базы данных + + JSON + JSON - - Refresh the data in the selected table. - Обновить данные в выбранной таблице. + + XML + XML - - This button refreshes the data in the currently selected table. - Эта кнопка отновлÑет данные выбранной в данный момент таблицы. + + Evaluation + Оценочный - - - F5 - F5 + + + Automatically adjust the editor mode to the loaded data type + ÐвтоматичеÑки подбор режима редактора на оÑнове данных - - Insert a new record in the current table - Добавить новую запиÑÑŒ в текущую таблицу + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + ПозволÑет включать или отключать автоматичеÑкое переключение режима редактора. Когда выбрана Ð½Ð¾Ð²Ð°Ñ Ñчейка или импортированы новые данные, а автоматичеÑкое переключение включено, режим наÑтраиваетÑÑ Ð½Ð° обнаруженный тип данных. Ð’Ñ‹ можете вручную изменить режим редактора. ЕÑли вы хотите Ñохранить Ñтот режим ручного Ð¿ÐµÑ€ÐµÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ перемещении по Ñчейкам, выключите кнопку. - - This button creates a new, empty record in the database - Эта кнопка Ñоздаёт новую, пуÑтую запиÑÑŒ в таблице + + Auto-switch + Ðвтопереключение - - New Record - Добавить запиÑÑŒ + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + Этот редактор Qt иÑпользуетÑÑ Ð´Ð»Ñ Ñкриптов Ñправа налево, которые не поддерживаютÑÑ Ñ‚ÐµÐºÑтовым редактором по умолчанию. ПриÑутÑтвие Ñимволов Ñправа налево обнаруживаетÑÑ, и Ñтот режим редактора выбираетÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки. - - Delete the current record - Удалить текущую запиÑÑŒ + + Identification of the cell currently in the editor + Ð˜Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ñчейки, находÑщейÑÑ Ð² данный момент в редакторе - - This button deletes the record currently selected in the database - Эта кнопка удалÑет выбранную запиÑÑŒ + + Type and size of data currently in table + Тип и размер данных, находÑщихÑÑ Ð² таблице в данный момент - - Delete Record - Удалить запиÑÑŒ + + Open preview dialog for printing the data currently stored in the cell + Открыть диалоговое окно предварительного проÑмотра Ð´Ð»Ñ Ð¿ÐµÑ‡Ð°Ñ‚Ð¸ данных, которые в данный момент хранÑÑ‚ÑÑ Ð² Ñчейке - - This is the database view. You can double-click any record to edit its contents in the cell editor window. - Это предÑтавление базы данных. Сделайте двойной щелчок по любой запиÑи, чтобы отредактировать её Ñодержимое. + + Auto-format: pretty print on loading, compact on saving. + ÐвтоматичеÑкое форматирование: ÑтилиÑтичеÑкое форматирование при загрузке, компактноÑть при Ñохранении. - - <html><head/><body><p>Scroll to the beginning</p></body></html> - <html><head/><body><p>Прокрутить к началу</p></body></html> + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + Когда включено, автоматичеÑки форматирует данные по мере загрузки, Ñ€Ð°Ð·Ð±Ð¸Ð²Ð°Ñ Ñ‚ÐµÐºÑÑ‚ в Ñтроках и отÑтупы Ð´Ð»Ñ Ð¼Ð°ÐºÑимальной читаемоÑти. При Ñохранении данных Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкого Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð±ÑŠÐµÐ´Ð¸Ð½Ñет данные, удалÑющие конец Ñтрок, и ненужные пробелы. - - <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> - <html><head/><body><p>Ðажатие Ñтой кнопки переводит к началу в таблице выше.</p></body></html> + + Word Wrap + ÐŸÐµÑ€ÐµÐ½Ð¾Ñ Ñлов - - |< - + + Wrap lines on word boundaries + ÐŸÐµÑ€ÐµÐ½Ð¾Ñ Ñтрок по границам Ñлов - - Scroll 100 records upwards - Прокрутить на 100 запиÑей вверх + + + Open in default application or browser + Открыть в приложении по умолчанию или браузере - - <html><head/><body><p>Clicking this button navigates 100 records upwards in the table view above.</p></body></html> - <html><head/><body><p>Ðажатие Ñтой кнопки к перемещению на 100 запиÑей вверх в табличном предÑтавлении выше</p></body></html> + + Open in application + Открыть в приложении - - < - < + + The value is interpreted as a file or URL and opened in the default application or web browser. + Значение интерпретируетÑÑ ÐºÐ°Ðº файл или URL-Ð°Ð´Ñ€ÐµÑ Ð¸ открываетÑÑ Ð² приложении по умолчанию или веб-браузере. - - 0 - 0 of 0 - 0 - 0 из 0 + + Save file reference... + Сохранить ÑÑылку на файл... - - <html><head/><body><p>Scroll 100 records downwards</p></body></html> - <html><head/><body><p>Прокрутить на 100 запиÑей вниз</p></body></html> + + Save reference to file + Сохранить ÑÑылку в файл - - <html><head/><body><p>Clicking this button navigates 100 records downwards in the table view above.</p></body></html> - <html><head/><body><p>Ðажатие Ñтой кнопки к перемещению на 100 запиÑей вниз в табличном предÑтавлении выше</p></body></html> + + + Open in external application + Открыть во внешнем приложении - - > - > + + Autoformat + Ðвтоформатирование - - Scroll to the end - Прокрутить к концу + + &Export... + &ЭкÑпорт... - - <html><head/><body><p>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Clicking this button navigates up to the end in the table view above.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html> - <html><head/><body><p>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ðажатие Ñтой кнопки перемещает в конец таблицы выше.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html> + + + &Import... + &Импорт... - - >| - + + + Import from file + Импортировать из файла - - <html><head/><body><p>Click here to jump to the specified record</p></body></html> - <html><head/><body><p>Ðажмите здеÑÑŒ, чтобы перейти к указанной запиÑи</p></body></html> + + + Opens a file dialog used to import any kind of data to this database cell. + Открывает диалоговое окно файла, иÑпользуемое Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð° любых данных в Ñту Ñчейку базы данных. - - <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> - <html><head/><body><p>Эта кнопка иÑпользуетÑÑ, чтобы перемеÑтитьÑÑ Ðº запиÑи, номер которой указан в облаÑти Перейти к</p></body></html> + + Export to file + ЭкÑпортировать в файл - - Go to: - Перейти к: + + Opens a file dialog used to export the contents of this database cell to a file. + Открывает диалоговое окно файла, иÑпользуемое Ð´Ð»Ñ ÑкÑпорта Ñодержимого Ñтой Ñчейки базы данных в файл. - - Enter record number to browse - Введите номер запиÑи Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра + + Erases the contents of the cell + ОчищаетÑÑ Ñодержимое Ñчейки - - Type a record number in this area and click the Go to: button to display the record in the database view - Ðапечатайте номер запиÑи в Ñтой облаÑти и нажмите кнопку Перейти к:, чтобы отобразить запиÑÑŒ в предÑтавлении базы данных + + This area displays information about the data present in this database cell + Эта облаÑть отображает информацию о данных, находÑщихÑÑ Ð² Ñтой Ñчейке базы данных - - 1 - 1 + + Print... + Печать... - - Edit &Pragmas - &Pragmas + + Ctrl+P + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> + + Open preview dialog for printing displayed text + Открыть диалоговое окно предварительного проÑмотра Ð´Ð»Ñ Ð¿ÐµÑ‡Ð°Ñ‚Ð¸ отображаемого текÑта - - - - None - Ðет + + Copy Hex and ASCII + Копировать HEX и ASCII - - - Full - Полный, целый - Full + + Copy selected hexadecimal and ASCII columns to the clipboard + Копировать выбранные HEX и ASCII Ñтолбцы в буфер обмена - - Incremental - Incremental + + Ctrl+Shift+C + Ctrl+Shift+C - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> + + Choose a filename to export data + Выбрать Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° Ð´Ð»Ñ ÑкÑпорта данных - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> + + + Image data can't be viewed in this mode. + Изображение не может быть отображено в Ñтом режиме. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></a></p></body></html> + + + Try switching to Image or Binary mode. + Попробуйте переключитьÑÑ Ð² Двоичный режим или режим ИзображениÑ. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> + + + Binary data can't be viewed in this mode. + Бинарные данные не могут быть отображены в Ñтом режиме. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> + + + Try switching to Binary mode. + Попробуйте переключитьÑÑ Ð² Бинарный режим. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> + + + Type: NULL; Size: 0 bytes + Тип: NULL; Размер: 0 байт + + + + + Type: Text / Numeric; Size: %n character(s) + + Тип: Text / Numeric; Размер: %n Ñимвол + Тип: Text / Numeric; Размер: %n Ñимвола + Тип: Text / Numeric; Размер: %n Ñимволов + - - Delete - Delete + + Type: %1 Image; Size: %2x%3 pixel(s) + Тип: %1 изображение; Размер: %2x%3 pixel(s) + + + + Type: Valid JSON; Size: %n character(s) + + Тип: ДейÑтвительный JSON; Размер: %n Ñимвол + Тип: ДейÑтвительный JSON; Размер: %n Ñимвола + Тип: ДейÑтвительный JSON; Размер: %n Ñимволов + + + + + Type: Binary; Size: %n byte(s) + + Тип: Binary; Размер: %n байт + Тип: Binary; Размер: %n байта + Тип: Binary; Размер: %n байт + - - Truncate - Truncate + + Couldn't save file: %1. + Ðе удалоÑÑŒ Ñохранить файл:%1. - - Persist - Persist + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + Данные были Ñохранены во временном файле и открыты Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию. Теперь вы можете редактировать файл и, когда будете готовы, применить Ñохраненные новые данные к Ñчейке или отменить любые изменениÑ. - - - Memory - Memory + + + Image files (%1) + Файлы изображений (%1) - - WAL - WAL + + Binary files (*.bin) + Бинарные файлы (*.bin) - - - Off - Off + + Choose a file to import + Выбрать файл Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð° - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + Режимы текÑтового редактора позволÑÑŽÑ‚ редактировать обычный текÑÑ‚, а также данные JSON или XML Ñ Ð¿Ð¾Ð´Ñветкой ÑинтакÑиÑа, автоматичеÑким форматированием и проверкой перед Ñохранением. + +Ошибки обозначаютÑÑ ÐºÑ€Ð°Ñным волниÑтым подчеркиванием. + +Ð’ режиме оценки введенные Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ SQLite оцениваютÑÑ, а результат применÑетÑÑ Ðº Ñчейке. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a></p></body></html> + + Unsaved data in the cell editor + ÐеÑохраненные данные в редакторе Ñчеек - - - Normal - Normal + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + Редактор Ñчеек Ñодержит данные, которые еще не применены к базе данных. +Хотите применить отредактированные данные к Ñтроке=%1, Ñтолбцу=%2? - - Exclusive - Exclusive + + Editing row=%1, column=%2 + Редактирование Ñтроки=%1, Ñтолбца=%2 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> + + No cell active. + Ðи одна Ñчейка не активна. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> + + %1 Image + %1 Изображение - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> + + Invalid data for this mode + Ошибочные данные Ð´Ð»Ñ Ñтого режима - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + Ячейка Ñодержит ошибочные %1 данные. Причина: %2. Ð’Ñ‹ дейÑтвительно хотите применить их? + + + EditIndexDialog - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> + + &Name + &Ð˜Ð¼Ñ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> + + Order + Сортировка - - Default - Default + + &Table + &Таблица - - File - File + + Edit Index Schema + Редактирование индекÑа - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> + + &Unique + &Уникальный - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + Ð”Ð»Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑом только чаÑти таблицы вы можете указать здеÑÑŒ выражение WHERE, которое выбирает чаÑть таблицы, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° быть проиндекÑирована - + + Partial inde&x clause + &ЧаÑтичный Ð¸Ð½Ð´ÐµÐºÑ + + + + Colu&mns + &Колонки + + + + Table column + Колонка +таблицы + + + + Type + Тип + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + Добавить новое колоночное выражение в индекÑ. Колоночное выражение может Ñодержать SQL Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð²Ð¼ÐµÑто имён колонок. + + + + Index column + Колонка +индекÑа + + + + Deleting the old index failed: +%1 + Удаление Ñтарого индекÑа завершилоÑÑŒ Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ¾Ð¹: +%1 + + + + Creating the index failed: +%1 + Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа: +%1 + + + + EditTableDialog + + + Edit table definition + Редактирование Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹ + + + + Table + Таблица + + + + Advanced + Дополнительно + + + + Without Rowid + Без Rowid + + + + Database sche&ma + Схе&ма БД + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + Делает Ñту таблицу «БЕЗ ROWID». УÑтановка Ñтого флага требует ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ ÐŸÐ•Ð Ð’Ð˜Ð§ÐОГО КЛЮЧР(который может быть любого типа и может быть ÑоÑтавным) и запрещает флаг ÐВТОИÐКРЕМЕÐТ. + + + + On Conflict + При конфликте + + + + Strict + Строго + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + ЕÑли включена ÑÑ‚Ñ€Ð¾Ð³Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ñ, SQLite применÑет типы данных каждого Ñтолбца при обновлении или вÑтавке данных. + + + + Fields + ÐŸÐ¾Ð»Ñ + + + + + + Add + Добавить + + + + + + Remove + Удалить + + + + Move to top + Вверх + + + + Move up + Выше + + + + Move down + Ðиже + + + + Move to bottom + Вниз + + + + + + + Name + Ð˜Ð¼Ñ + + + + + Type + Тип + + + + NN + Ðе null + + + + Not null + Ðе пуÑтое (not null) + + + + PK + ПК + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> Первичный ключ</p></body></html> + + + + AI + ÐИ + + + + Autoincrement + Ðвтоинкремент + + + + U + Уникальное + + + + + + Unique + Уникальное + + + + Default + По умолчанию + + + + Default value + Значение по умолчанию + + + + + Check + Проверка + + + + Check constraint + Ограничение проверкой + + + + Collation + Collation + + + + Foreign Key + Внешний ключ + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_fk"/> Внешний ключ</p></body></html> + + + + Index Constraints + Ð˜Ð½Ð´ÐµÐºÑ + + + + Add constraint + Добавить ограничение + + + + Remove constraint + Удалить ограничение + + + + + Columns + Столбцы + + + + + + SQL + SQL + + + + Foreign Keys + Внешний ключ + + + + References + СÑылки + + + + Check Constraints + ÐžÐ³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¾Ð¹ + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Внимание: </span>Ð’ опиÑании Ñтой таблицы еÑть что-то, что наш парÑер не понимает. ÐœÐ¾Ð´Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¸ Ñохранение Ñтой таблицы может породить проблемы.</p></body></html> + + + + + Primary Key + Первичный ключ + + + + Add a primary key constraint + Добавить ограничение первичного ключа + + + + Add a unique constraint + Добавить ограничение уникальноÑти + + + + Error creating table. Message from database engine: +%1 + Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹. Сообщение от движка базы данных: +%1 + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + Поле Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем уже ÑущеÑтвует. ПожалуйÑта переименуйте его, либо выберите другое Ð¸Ð¼Ñ Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ полÑ. + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + Ð”Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ таблицы может быть только один первичный ключ. ВмеÑто Ñтого измените ÑущеÑтвующий первичный ключ. + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + Ðа Ñту колонку ÑÑылаетÑÑ Ð²Ð½ÐµÑˆÐ½Ð¸Ð¹ ключ в таблице %1, поÑтому ее Ð¸Ð¼Ñ Ð½Ðµ может быть изменено. + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + СущеÑтвует по крайней мере одна Ñтрока, где Ñто поле уÑтановлено в NULL. УÑтановить Ñтот флаг нельзÑ. Сначала измените данные таблицы. + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + СущеÑтвует по крайней мере одна Ñтрока, где Ñто поле Ñодержит нечиÑловое значение. УÑтановить флаг ÐИ нельзÑ. Сначала измените данные таблицы. + + + + Column '%1' has duplicate data. + + Столбец '%1' Ñодержит повторÑющиеÑÑ Ð´Ð°Ð½Ð½Ñ‹Ðµ. + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + Это делает невозможным включение флага «Уникальный». ПожалуйÑта, удалите дублирующиеÑÑ Ð´Ð°Ð½Ð½Ñ‹Ðµ, что позволит включить флаг «Уникальный». + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + Удалить поле '%1'? +Ð’Ñе данные, которые в наÑтоÑщий момент Ñохранены в Ñтом поле, будут потерÑны. + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + Перед тем как применÑть флаг без rowid, пожалуйÑта убедитеÑÑŒ, что ÑущеÑтвует Ñтолбец, который: + - ÑвлÑетÑÑ Ð¿ÐµÑ€Ð²Ð¸Ñ‡Ð½Ñ‹Ð¹ ключом + - Ð´Ð»Ñ Ð½ÐµÐ³Ð¾ отключен автоинкремент + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + ПожалуйÑта, добавьте поле, которое ÑоответÑтвует Ñледующим критериÑм, прежде чем уÑтанавливать дейÑтвие при конфликте: +- УÑтановлен флаг первичного ключа + + + + ExportDataDialog + + + Export data as CSV + ЭкÑпортировать данные в формате CSV + + + + Tab&le(s) + &Таблицы + + + + Colu&mn names in first line + &Имена Ñтолбцов в первой Ñтроке + + + + Fie&ld separator + &Разделитель полей + + + + , + , + + + + ; + ; + + + + Tab + ТабулÑÑ†Ð¸Ñ + + + + | + | + + + + + + Other + Другой + + + + &Quote character + &Символ кавычки + + + + " + " + + + + ' + ' + + + + New line characters + Разделитель Ñтрок + + + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) + + + + Unix: LF (\n) + + + + + Pretty print + КраÑивый вывод + + + + + Could not open output file: %1 + Ðе удалоÑÑŒ открыть выходной файл: %1 + + + + + Choose a filename to export data + Выберите Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° Ð´Ð»Ñ ÑкÑпорта данных + + + + Export data as JSON + ЭкÑпортировать данные как JSON + + + + exporting CSV + ÑкÑпортирование CSV + + + + + Error while writing the file '%1': %2 + Ошибка при запиÑи файла '%1': %2 + + + + exporting JSON + ÑкÑпортирование JSON + + + + Please select at least 1 table. + ПожалуйÑта, выберите Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одну таблицу. + + + + Choose a directory + Выберите каталог + + + + Export completed. + ЭкÑпорт завершён. + + + + Export finished with errors. + ЭкÑпорт завершен Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°Ð¼Ð¸. + + + + ExportSqlDialog + + + Export SQL... + ЭкÑпорт SQL.... + + + + Tab&le(s) + &Таблицы + + + + Select All + Выбрать вÑе + + + + Deselect All + Отменить выбор + + + + &Options + &Опции + + + + Keep column names in INSERT INTO + Сохранить Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ñтолбцов в выражении INSERT INTO + + + + Multiple rows (VALUES) per INSERT statement + ÐеÑколько Ñтрок (VALUES) на INSERT выражение + + + + Export everything + ЭкÑпортировать вÑе + + + + Export data only + ЭкÑпортировать только данные + + + + Keep original CREATE statements + Сохранить оригинальные инÑтрукции CREATE + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + СохранÑть Ñхему (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + УдалÑть Ñтарую таблицу перед Ñозданием (DROP TABLE, затем CREATE TABLE) + + + + Export schema only + ЭкÑпортировать только Ñхему данных + + + + Please select at least one table. + ПожалуйÑта, выберите Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одну таблицу. + + + + Choose a filename to export + Выберите Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° Ð´Ð»Ñ ÑкÑпорта + + + + Export completed. + ЭкÑпорт завершён. + + + + Export cancelled or failed. + ЭкÑпорт отменён или возникли ошибки. + + + + ExtendedScintilla + + + + Ctrl+H + Ctrl+H + + + + Ctrl+F + Ctrl+F + + + + + Ctrl+P + Ctrl+P + + + + Find... + ПоиÑк... + + + + Find and Replace... + Ðайти и Заменить... + + + + Print... + Печать... + + + + ExtendedTableWidget + + + Use as Exact Filter + ИÑпользовать как точный фильтр + + + + Containing + Содержит + + + + Not containing + Ðе Ñодержит + + + + Not equal to + Ðе равно + + + + Greater than + Больше чем + + + + Less than + Меньше чем + + + + Greater or equal + Больше или равно + + + + Less or equal + Меньше или равно + + + + Between this and... + Между Ñтим и... + + + + Regular expression + РегулÑрное выражение + + + + Edit Conditional Formats... + Редактировать формат... + + + + Set to NULL + УÑтановить в NULL + + + + Cut + Вырезать + + + + Copy + Копировать + + + + Copy with Headers + Копировать Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ°Ð¼Ð¸ + + + + Copy as SQL + Копировать как SQL + + + + Paste + Ð’Ñтавить + + + + Print... + Печать... + + + + Use in Filter Expression + ИÑпользовать в выражении фильтра + + + + Alt+Del + Alt+Del + + + + Ctrl+Shift+C + Ctrl+Shift+C + + + + Ctrl+Alt+C + Ctrl+Alt+C + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + Содержимое буфера обмена больше чем выделенный диапазон. +Ð’Ñе равно вÑтавить? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>Ðе вÑе данные загружены. <b>Хотите ли вы загрузить вÑе данные перед выбором вÑех Ñтрок?</b><p><p>Ответ<b>Ðет</b> означает, что больше данные загружены не будут и выбор не будет выполнен.<br/>Ответ <b>Да</b> Загрузка данных может занÑть некоторое времÑ, но выборка будет завершена.</p>Предупреждение: загрузка вÑех данных может потребовать большого объема памÑти Ð´Ð»Ñ Ð±Ð¾Ð»ÑŒÑˆÐ¸Ñ… таблиц. + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + Ðевозможно уÑтановить выборку в NULL. Столбец %1 имеет ограничение NOT NULL. + + + + FileExtensionManager + + + File Extension Manager + Менеджер раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð² + + + + &Up + &Выше + + + + &Down + &Ðиже + + + + &Add + &Добавить + + + + &Remove + &Удалить + + + + + Description + ОпиÑание + + + + Extensions + РаÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ + + + + *.extension + *.extension + + + + FilterLineEdit + + + Filter + Фильтр + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + Эти Ð¿Ð¾Ð»Ñ Ð²Ð²Ð¾Ð´Ð° позволÑÑŽÑ‚ выполнÑть быÑтрые фильтры в текущей выбранной таблице. +По умолчанию Ñтроки, Ñодержащие введенный текÑÑ‚, отфильтровываютÑÑ. +ПоддерживаютÑÑ Ñледующие операторы: +% ПодÑтановочный знак +> Больше +< Меньше +>= Равно или больше +<= Равно или меньше += Равно: точное Ñовпадение +<> Ðеравно: точное обратное Ñовпадение +x~y Диапазон: Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ x и y +/regexp/ ЗначениÑ, ÑоответÑтвующие регулÑрному выражению + + + + Clear All Conditional Formats + ОчиÑтить вÑе форматирование + + + + Use for Conditional Format + ИÑпользовать формат + + + + Edit Conditional Formats... + Редактировать форматы... + + + + Set Filter Expression + УÑтановить выражение фильтра + + + + What's This? + Что Ñто? + + + + Is NULL + Is NULL + + + + Is not NULL + Ðе NULL + + + + Is empty + ПуÑто + + + + Is not empty + Ðе пуÑто + + + + Not containing... + Ðе Ñодержит... + + + + Equal to... + Равно... + + + + Not equal to... + Ðе равно... + + + + Greater than... + Больше чем... + + + + Less than... + Меньше чем... + + + + Greater or equal... + Больше или равно... + + + + Less or equal... + Меньше или равно... + + + + In range... + Ð’ диапазоне... + + + + Regular expression... + РегулÑрное выражение... + + + + FindReplaceDialog + + + Find and Replace + ПоиÑк и замена + + + + Fi&nd text: + &ТекÑÑ‚ Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка: + + + + Re&place with: + ТекÑÑ‚ Ð´Ð»Ñ &замены: + + + + Match &exact case + Учитывать &региÑтр + + + + Match &only whole words + Слова &целиком + + + + When enabled, the search continues from the other end when it reaches one end of the page + Когда отмечено, поиÑк продолжаетÑÑ Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð³Ð¾ конца, когда он доÑтигает противоположного конца Ñтраницы + + + + &Wrap around + &Закольцевать + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + Когда отмечено, поиÑк возвращаетÑÑ Ð½Ð°Ð·Ð°Ð´ из Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ÐºÑƒÑ€Ñора, в противном Ñлучае он идет вперед + + + + Search &backwards + ИÑкать в &обратном порÑдке + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>ЕÑли Ñтот флажок уÑтановлен, поиÑк по иÑкомому шаблону выполнÑетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в текущем выделенном фрагменте.</p></body></html> + + + + &Selection only + Только в в&ыделенном + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>При проверке шаблон Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка интерпретируетÑÑ ÐºÐ°Ðº регулÑрное выражение UNIX. <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Узнать больше о РегулÑрных выражениÑÑ… на Wikibooks.org</a>.</p></body></html> + + + + Use regular e&xpressions + &РегулÑрные Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + Ðайдите Ñледующее вхождение из позиции курÑора и в направлении, заданном "ИÑкать назад" + + + + &Find Next + ИÑкать &дальше + + + + F3 + F3 + + + + &Replace + &Замена + + + + Highlight all the occurrences of the text in the page + Выделить вÑе Ð²Ñ…Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ñ‚ÐµÐºÑта на Ñтранице + + + + F&ind All + Ðайти &вÑе + + + + Replace all the occurrences of the text in the page + Заменить вÑе Ð²Ñ…Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ñ‚ÐµÐºÑта на Ñтранице + + + + Replace &All + За&менить вÑе + + + + The searched text was not found + ИÑкомый текÑÑ‚ не найден + + + + The searched text was not found. + ИÑкомый текÑÑ‚ не найден. + + + + The searched text was found one time. + ИÑкомый текÑÑ‚ найден один раз. + + + + The searched text was found %1 times. + ИÑкомый текÑÑ‚ найден %1 раз. + + + + The searched text was replaced one time. + ИÑкомый текÑÑ‚ заменен один раз. + + + + The searched text was replaced %1 times. + ИÑкомый текÑÑ‚ заменен %1 раз. + + + + ForeignKeyEditor + + + &Reset + &Ð¡Ð±Ñ€Ð¾Ñ + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + ДейÑÑ‚Ð²Ð¸Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ³Ð¾ ключа (ON UPDATE, ON DELETE и Ñ‚.д.) + + + + ImageViewer + + + Image Viewer + ПроÑмотр графики + + + + Reset the scaling to match the original size of the image. + Ð¡Ð±Ñ€Ð¾Ñ Ð¼Ð°Ñштаба до иÑходного размера изображениÑ. + + + + Set the scaling to match the size of the viewport. + Подогнать маÑштаб к размеру окна. + + + + Print... + Печать... + + + + Open preview dialog for printing displayed image + Открыть диалоговое окно предварительного проÑмотра Ð´Ð»Ñ Ð¿ÐµÑ‡Ð°Ñ‚Ð¸ отображаемого Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ + + + + Ctrl+P + Ctrl+P + + + + ImportCsvDialog + + + Import CSV file + Импортировать CSV файл + + + + Table na&me + &Ð˜Ð¼Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹ + + + + &Column names in first line + И&мена Ñтолбцов в первой Ñтроке + + + + Field &separator + &Разделитель полей + + + + , + + + + + ; + + + + + + Tab + ТабулÑÑ†Ð¸Ñ + + + + | + + + + + Other + Другой + + + + &Quote character + &Символ кавычки + + + + + Other (printable) + Другой (Ð´Ð»Ñ Ð¿ÐµÑ‡Ð°Ñ‚Ð¸) + + + + + Other (code) + Другой (код) + + + + " + + + + + ' + + + + + &Encoding + &Кодировка + + + + UTF-8 + + + + + UTF-16 + + + + + ISO-8859-1 + + + + + Trim fields? + Обрезать полÑ? + + + + Separate tables + Отдельные таблицы + + + + Advanced + Дополнительно + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + При импорте пуÑтого Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¸Ð· файла CSV в ÑущеÑтвующую таблицу Ð´Ð»Ñ Ñтолбца Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ñ‹Ð¼ значением по умолчанию оно будет вÑтавлено. Ðктивируйте Ñту опцию, чтобы вмеÑто Ñтого вÑтавить пуÑтое значение. + + + + Ignore default &values + Игнорировать значение &по-умолчанию + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + Ðктивируйте Ñту опцию чтобы прекратить импорт при попытке импорта пуÑтого Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² NOT NULL колонку без Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾-умолчанию. + + + + Fail on missing values + Ошибка при отÑутÑтвии значений + + + + Disable data type detection + Отключить определение типа данных + + + + Disable the automatic data type detection when creating a new table. + Отключить автоматичеÑкое определение типа при Ñоздании новой таблицы. + + + + Use local number conventions + ИÑпользовать меÑтные правила нумерации + + + + Use decimal and thousands separators according to the system locale. + ИÑпользуйте деÑÑтичные разделители и разделители тыÑÑч в ÑоответÑтвии Ñ Ñзыковыми наÑтройками ÑиÑтемы. + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + При импорте в ÑущеÑтвующую таблицу Ñ Ð¿ÐµÑ€Ð²Ð¸Ñ‡Ð½Ñ‹Ð¼ ключом, уникальными ограничениÑми или уникальным индекÑом ÑущеÑтвует вероÑтноÑть конфликта. Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет выбрать Ñтратегию Ð´Ð»Ñ Ñтого ÑлучаÑ: по умолчанию импорт прерываетÑÑ Ð¸ откатываетÑÑ, но вы также можете выбрать игнорирование и не импортировать конфликтующие Ñтроки или замену ÑущеÑтвующей Ñтроки в таблице. + + + + Abort import + Прервать импорт + + + + Ignore row + Игнорировать Ñтроку + + + + Replace existing row + Заменить ÑущеÑтвующую Ñтроку + + + + Conflict strategy + ДейÑÑ‚Ð²Ð¸Ñ Ð¿Ñ€Ð¸ конфликте + + + + + Deselect All + СнÑть выделение + + + + Match Similar + Ðайти ÑÐ¾Ð²Ð¿Ð°Ð´ÐµÐ½Ð¸Ñ + + + + Select All + Выбрать Ð’Ñе + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + Уже ÑущеÑтвует таблица Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ '%1' и импорт в ÑущеÑтвующую таблицу возможен, только еÑли чиÑло Ñтолбцов Ñовпадает. + + + + There is already a table named '%1'. Do you want to import the data into it? + Уже ÑущеÑтвует таблица Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ '%1'. Ð’Ñ‹ хотите импортировать данные в нее? + + + + Creating restore point failed: %1 + Ошибка ÑÐ¾Ð·Ð½Ð°Ð½Ð¸Ñ Ñ‚Ð¾Ñ‡ÐºÐ¸ воÑÑтановлениÑ: %1 + + + + Creating the table failed: %1 + Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹: %1 + + + + importing CSV + импортирование CSV + + + + Could not prepare INSERT statement: %1 + Ðе удалоÑÑŒ подготовить оператор INSERT: %1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + Ðеожиданный конец файла. УбедитеÑÑŒ, что вы наÑтроили правильные Ñимволы кавычек и файл не имеет неправильного формата. + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + Импорт файла '%1' занÑл %2мÑ. Из них %3Ð¼Ñ Ð±Ñ‹Ð»Ð¾ потрачено в функции Ñтроки. + + + + Inserting row failed: %1 + Ошибка вÑтавки Ñтроки: %1 + + + + MainWindow + + + DB Browser for SQLite + DB Browser for SQLite + + + + toolBar1 + ПанельИнÑтрументов1 + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + Предупреждение: Ñта прагма не читаетÑÑ, и Ñто значение было выведено. Применение прагмы может перезапиÑать переопределенный LIKE, предоÑтавлÑемый раÑширением SQLite. + + + + Temp Store + Temp Store (Временное хранилище) + + + + Secure Delete + Secure Delete (БезопаÑное удаление) + + + + Case Sensitive Like + Case Sensitive Like (РегиÑтрозавиÑимый Like) + + + + Journal Mode + Journal Mode (Режим журнала) + + + + Journal Size Limit + Journal Size Limit (Лимит размера журнала) + + + + Recursive Triggers + Recursive Triggers (РекурÑивные триггеры) + + + + Page Size + Page Size (Размер Ñтраницы) + + + + Foreign Keys + Foreign Keys (Внешние ключи) + + + + Auto Vacuum + Auto Vacuum (Ðвтовакуум) + + + + Max Page Count + Max Page Count (ÐœÐ°ÐºÑ Ñ‡Ð¸Ñло Ñтраниц) + + + + Checkpoint Full FSYNC + Checkpoint Full FSYNC + + + + + Off + Откл + + + + + Normal + Обычный + + + + + Full + Полный + + + + Default + По умолчанию + + + + File + Файл + + + + + Memory + ПамÑть + + + + Delete + Удаление + + + + Truncate + УÑекать + + + + Persist + Persist + + + + WAL + WAL + + + + Exclusive + ЭкÑклюзив + + + + Automatic Index + Automatic Index (ÐвтоиндекÑирование) + + + + Ignore Check Constraints + Ignore Check Constraints (Игнорировать Check Constraints) + + + + Full FSYNC + Full FSYNC + + + + WAL Auto Checkpoint + WAL Auto Checkpoint + + + + User Version + User Version (ВерÑÐ¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ) + + + + Synchronous + Synchronous (СинхронизациÑ) + + + + None + Ðет + + + + Incremental + Инкремент + + + + Locking Mode + Locking Mode (Режим блокировки) + + + + Too&ls + &ИнÑтрументы + + + + Error Log + Журнал ошибок + + + + This button clears the contents of the SQL logs + Эта кнопка очищает Ñодержимое журналов SQL + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + Эта панель позволÑет вам проÑматривать журнал вÑех SQL-команд, выданных приложением или вами + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + Это Ñтруктура открытой БД. +Ð’Ñ‹ можете перетащить неÑколько имен объектов из Ñтолбца "ИмÑ" в редактор SQL, и вы можете наÑтроить ÑвойÑтва перемещенных имен Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ контекÑтного меню. Это поможет вам при ÑоÑтавлении SQL-инÑтрукций. +Ð’Ñ‹ можете перетаÑкивать операторы SQL из Ñтолбца "Схема" и переноÑить их в редактор SQL или в другие приложениÑ. + + + + + + Project Toolbar + Панель инÑтрументов проекта + + + + Extra DB toolbar + Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ инÑтрументов БД + + + + + + Close the current database file + Закрыть файл текущей БД + + + + &New Database + &ÐÐ¾Ð²Ð°Ñ Ð‘Ð” + + + + + Ctrl+F4 + Ctrl+F4 + + + + &Undo + &Отменить + + + + + Undo last change to the database + Отменить поÑледнее изменение в БД + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + Это дейÑтвие отменÑет поÑледнее изменение, выполненное в базе данных в Database Browser или в Execute SQL. Повтор невозможен. + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + Открывает маÑтер Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹, где можно переименовать ÑущеÑтвующую таблицу. Также можно добавлÑть или удалÑть Ð¿Ð¾Ð»Ñ Ð¸Ð· таблицы, а также изменÑть имена и типы полей. + + + + &About + О &программе + + + + New &tab + ÐÐ¾Ð²Ð°Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ° редактора SQL + + + + This button opens a new tab for the SQL editor + Эта кнопка открывает новую вкладку Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¾Ñ€Ð° SQL + + + + Execute all/selected SQL + Выполнить вÑе/выбранный SQL + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + Эта кнопка выполнÑет текущие выбранные операторы SQL. ЕÑли в текÑтовом редакторе ничего не выбрано , вÑе инÑтрукции SQL выполнÑÑŽÑ‚ÑÑ. + + + + Ctrl+Shift+T + Ctrl+Shift+T + + + + &Load Extension... + &Загрузить раÑширение... + + + + Execute line + Выполнить Ñтроку + + + + This button executes the SQL statement present in the current editor line + Эта кнопка выполнÑет оператор SQL, приÑутÑтвующий в текущей Ñтроке редактора + + + + &Wiki + &Вики + + + + F1 + F1 + + + + Bug &Report... + Баг &репорт... + + + + Feature Re&quest... + ЗапроÑить &функцию... + + + + Web&site + &Веб-Ñайт + + + + &Donate on Patreon... + Сделать &пожертвование в Patreon... + + + + &Save Project + Сохранить проект + + + + Open &Project... + Открыть &проект... + + + + Open &Project + Открыть проект + + + + &Attach Database... + &Прикрепить БД... + + + + + Add another database file to the current database connection + Добавить другой файл БД в текущее Ñоединение + + + + This button lets you add another database file to the current database connection + Эта кнопка позволÑет добавить другой файл БД в текущее Ñоединение Ñ Ð‘Ð” + + + + &Set Encryption... + Ðазначить &шифрование... + + + + This button saves the content of the current SQL editor tab to a file + Эта кнопка ÑохранÑет Ñодержимое текущей вкладки редактора SQL в файл + + + + SQLCipher &FAQ + SQLCipher &FAQ + + + + Table(&s) to JSON... + Таблицы в файл &JSON... + + + + Open Data&base Read Only... + Открыть БД &только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ... + + + + Ctrl+Shift+O + Ctrl+Shift+O + + + + Save results + Сохранить результаты + + + + Save the results view + Сохранить результаты + + + + This button lets you save the results of the last executed query + Эта кнопка позволÑет Ñохранить результаты поÑледнего выполненного запроÑа + + + + + Find text in SQL editor + Ðайти текÑÑ‚ в редакторе SQL + + + + Find + Ðайти + + + + This button opens the search bar of the editor + Эта кнопка открывает панель поиÑка редактора + + + + Ctrl+F + Ctrl+F + + + + + Find or replace text in SQL editor + Ðайти или заменить текÑÑ‚ в редакторе SQL + + + + Find or replace + Ðайти или заменить + + + + This button opens the find/replace dialog for the current editor tab + Эта кнопка открывает диалог поиÑка/замены Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ вкладки редактора + + + + Ctrl+H + Ctrl+H + + + + Export to &CSV + ЭкÑпортировать в &CSV + + + + Export to &JSON + ЭкÑпорт в JSON + + + + Save as &view + Сохранить как &предÑтавление + + + + Save as view + Сохранить как предÑтавление + + + + Shows or hides the Project toolbar. + Показывает или Ñкрывает панель инÑтрументов проекта. + + + + Extra DB Toolbar + Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ инÑтрументов БД + + + + + Ctrl+Shift+W + Ctrl+Shift+W + + + + Table from CSV data in Clipboard... + Таблица из CSV данных в буфере обмена... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + При Ñтом текущее Ñодержимое буфера обмена обрабатываетÑÑ ÐºÐ°Ðº CSV-файл и открываетÑÑ Ñ‚Ð¾Ñ‚ же маÑтер импорта, который иÑпользуетÑÑ Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð° CSV-данных из файла. + + + + Show &Row Counts + Показать Ñчетчик Ñтрок + + + + This shows the number of rows for each table and view in the database. + ЗдеÑÑŒ отображаетÑÑ ÐºÐ¾Ð»Ð¸Ñ‡ÐµÑтво Ñтрок Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ таблицы и предÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð² базе данных. + + + + Save Database &As... + Сохранить БД как... + + + + Save the current database as a different file + Сохранить текущую БД как другой файл + + + + Refresh + Обновить + + + + Reload the database structure + Перезагрузить Ñтруктуру базы данных + + + + Open SQL file(s) + Открыть SQL файл(Ñ‹) + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + Структура БД + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + ПроÑмотр данных + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + Прагмы + + + + E&xecute SQL - &Выполнение SQL + This has to be equal to the tab title in all the main tabs + Редактор SQL + + + + &Recent Files + Ðедавние &файлы + + + + This button opens files containing SQL statements and loads them in new editor tabs + Эта кнопка открывает файлы, Ñодержащие SQL инÑтрукции и загружает их в новую вкладку редактора + + + + This button lets you open a DB Browser for SQLite project file + Эта кнопка позволÑет открыть браузер БД Ð´Ð»Ñ Ñ„Ð°Ð¹Ð»Ð° проекта SQLite + + + + &Open Database + &Открыть БД + + + + New In-&Memory Database + ÐÐ¾Ð²Ð°Ñ Ð‘Ð” в па&мÑти + + + + Drag && Drop SELECT Query + ПеретаÑкивание запроÑа SELECT + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + При перетаÑкивании полей из той же таблицы или из одной таблицы, перетащите Ð·Ð°Ð¿Ñ€Ð¾Ñ SELECT в редактор + + + + Drag && Drop Qualified Names + Квалифицированные имена при перетаÑкивании + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + Квалифицированные имена (например, "Table"."Field") при перетаÑкивании объектов в редактор + + + + Drag && Drop Enquoted Names + Экранированные имена при перетаÑкивании + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + Экранировать имена идентификаторов (например, "Table1"), когда перетаÑкиваютÑÑ Ð¾Ð±ÑŠÐµÐºÑ‚Ñ‹ в редактор + + + + &Integrity Check + Проверка &ЦелоÑтноÑти + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + ВыполнÑет прагму integrity_check Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¾Ð¹ БД и возвращает результаты во вкладке "SQL". Эта прагма выполнÑет проверку целоÑтноÑти вÑей базы данных. + + + + &Foreign-Key Check + Проверка &Внешних ключей + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + ЗапуÑкает прагму foreign_key_check Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¾Ð¹ БД и возвращает результаты во вкладке "SQL" + + + + &Quick Integrity Check + &БыÑÑ‚Ñ€Ð°Ñ ÐŸÑ€Ð¾Ð²ÐµÑ€ÐºÐ° ЦелоÑтноÑти + + + + Run a quick integrity check over the open DB + ЗапуÑк быÑтрой проверки целоÑтноÑти Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ñ‹Ð¹ БД + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + ЗапуÑкает прагму quick_check Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¾Ð¹ БД и возвращает результаты во вкладке "SQL". Эта команда выполнÑет большую чаÑть проверки PRAGMA integrity_check, но работает намного быÑтрее. + + + + &Optimize + &ÐžÐ¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ñ + + + + Attempt to optimize the database + Попытка оптимизации БД + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + ВыполнÑет прагму optimize Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¾Ð¹ БД. Эта прагма может выполнÑть оптимизацию, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ ÑƒÐ»ÑƒÑ‡ÑˆÐ¸Ñ‚ производительноÑть будущих запроÑов. + + + + + Print + Печать + + + + Print text from current SQL editor tab + Печать текÑта из текущей вкладки редактора SQL + + + + Open a dialog for printing the text in the current SQL editor tab + Открывает диалоговое окно Ð´Ð»Ñ Ð¿ÐµÑ‡Ð°Ñ‚Ð¸ текÑта из текущей вкладки редактора SQL + + + + Print the structure of the opened database + Печать Ñтруктуры открытой БД + + + + Open a dialog for printing the structure of the opened database + Открывает диалоговое окно Ð´Ð»Ñ Ð¿ÐµÑ‡Ð°Ñ‚Ð¸ Ñтруктуры текущей БД + + + + Un/comment block of SQL code + РаÑ/комментировать блок SQL кода + + + + Un/comment block + РаÑ/комментировать блок + + + + Comment or uncomment current line or selected block of code + РаÑ/комментировать текущую Ñтроку выбранного блока кода + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + Комментировать или раÑкомментировать выделенные Ñтроки или текущую Ñтроку, еÑли нет выделениÑ. ВеÑÑŒ блок переключаетÑÑ Ð² ÑоответÑтвии Ñ Ð¿ÐµÑ€Ð²Ð¾Ð¹ Ñтрокой. + + + + Ctrl+/ + Ctrl+/ + + + + Stop SQL execution + ОÑтановить выполнение SQL + + + + Stop execution + ОÑтановить выполнение + + + + Stop the currently running SQL script + ОÑтановить выполнÑемый SQL Ñкрипт + + + + Browse Table + ПроÑмотр таблицы + + + + Close Pro&ject + Закрыть проект + + + + + Close project and database files and return to the initial state + Закрыть проект и БД файлы и вернутьÑÑ Ð² иÑходное ÑоÑтоÑние + + + + Ctrl+Shift+F4 + Ctrl+Shift+F4 + + + + + Detach Database + ОтÑоединить БД + + + + + Detach database file attached to the current database connection + ОтÑоединить файл базы данных, прикрепленный к текущему подключению + + + + &Save Project As... + Сохранить проект как... + + + + + + Save the project in a file selected in a dialog + Сохраните проект в файле, выбранном в диалоговом окне + + + + Save A&ll + Сохранить вÑе + + + + + + Save DB file, project file and opened SQL files + Сохранить файл базы данных, файл проекта и открытые файлы SQL + + + + Ctrl+Shift+S + Ctrl+Shift+S + + + + &File + &Файл + + + + &Import + &Импорт + + + + &Export + &ЭкÑпорт + + + + &Edit + &Редактирование + + + + &View + &Вид + + + + &Help + &Справка + + + + DB Toolbar + Панель инÑтрументов БД + + + + Edit Database &Cell + Редактирование &Ñчейки БД + + + + DB Sche&ma + Схе&ма БД + + + + &Remote + &Удаленный Ñервер + + + + + Execute current line + Выполнить текущую Ñтроку + + + + Shift+F5 + Shift+F5 + + + + Sa&ve Project + &Сохранить проект + + + + Open an existing database file in read only mode + Открыть ÑущеÑтвующий файл базы данных в режиме только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ + + + + Opens the SQLCipher FAQ in a browser window + Открыть SQLCiphier FAQ в браузере + + + + Export one or more table(s) to a JSON file + ЭкÑпортировать таблицы в JSON файл + + + + + Save SQL file as + Сохранить файл SQL как + + + + &Browse Table + Пр&оÑмотр данных + + + + User + Пользователем + + + + Application + Приложением + + + + &Clear + О&чиÑтить + + + + &New Database... + &ÐÐ¾Ð²Ð°Ñ Ð±Ð°Ð·Ð° данных... + + + + + Create a new database file + Создать новый файл базы данных + + + + This option is used to create a new database file. + Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¸ÑпользуетÑÑ, чтобы Ñоздать новый файл базы данных. + + + + Ctrl+N + Ctrl+N + + + + + &Open Database... + &Открыть базу данных... + + + + + + + + Open an existing database file + Открыть ÑущеÑтвующий файл базы данных + + + + + + This option is used to open an existing database file. + Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¸ÑпользуетÑÑ, чтобы открыть ÑущеÑтвующий файл базы данных. + + + + Ctrl+O + Ctrl+O + + + + &Close Database + &Закрыть базу данных + + + + This button closes the connection to the currently open database file + Эта кнопка закрывает Ñоединение Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¼ файлом БД + + + + + Ctrl+W + Ctrl+W + + + + + Revert database to last saved state + Вернуть базу данных в поÑледнее Ñохранённое ÑоÑтоÑние + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¸ÑпользуетÑÑ, чтобы вернуть текущий файл базы данных в его поÑледнее Ñохранённое ÑоÑтоÑние. Ð’Ñе изменениÑ, Ñделанные Ñ Ð¿Ð¾Ñледней операции ÑохранениÑ, терÑÑŽÑ‚ÑÑ. + + + + + Write changes to the database file + ЗапиÑать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² файл базы данных + + + + This option is used to save changes to the database file. + Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¸ÑпользуетÑÑ, чтобы Ñохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² файле базы данных. + + + + Ctrl+S + Ctrl+S + + + + Compact &Database... + &Уплотнить базу данных... + + + + Compact the database file, removing space wasted by deleted records + Уплотнить базу данных, удалÑÑ Ð¿Ñ€Ð¾ÑтранÑтво, занимаемое удалёнными запиÑÑми + + + + + Compact the database file, removing space wasted by deleted records. + Уплотнить базу данных, удалÑÑ Ð¿Ñ€Ð¾ÑтранÑтво, занимаемое удалёнными запиÑÑми. + + + + E&xit + &Выход + + + + Ctrl+Q + Ctrl+Q + + + + Import data from an .sql dump text file into a new or existing database. + Импортировать данные из текÑтового файла sql в новую или ÑущеÑтвующую базу данных. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет импортировать данные из текÑтового файла sql в новую или ÑущеÑтвующую базу данных. Файл SQL может быть Ñоздан на большинÑтве движков баз данных, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ MySQL и PostgreSQL. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Открыть маÑтер, который позволÑет импортировать данные из файла CSV в таблицу базы данных. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Открыть маÑтер, который позволÑет импортировать данные из файла CSV в таблицу базы данных. Файлы CSV могут быть Ñозданы в большинÑтве приложений баз данных и Ñлектронных таблиц. + + + + Export a database to a .sql dump text file. + ЭкÑпортировать базу данных в текÑтовый дамп файл .sql. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет ÑкÑпортировать базу данных в текÑтовый файл .sql. Файлы SQL Ñодержат вÑе данные, необходимые Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð±Ð°Ð·Ñ‹ данных в большинÑтве движков баз данных, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ MySQL и PostgreSQL. + + + + Export a database table as a comma separated text file. + ЭкÑпортировать таблицу базы данных как CSV текÑтовый файл. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + ЭкÑпортировать таблицу базы данных как CSV текÑтовый файл, готовый Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² другие базы данных или Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñлектронных таблиц. + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Открыть маÑтер ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†, где возможно определить Ð¸Ð¼Ñ Ð¸ Ð¿Ð¾Ð»Ñ Ð´Ð»Ñ Ð½Ð¾Ð²Ð¾Ð¹ таблицы в базе данных + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Открыть маÑтер ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹, где можно выбрать таблицу базы данных Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ. + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + Открыть маÑтер ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа, в котором можно определить новый Ð¸Ð½Ð´ÐµÐºÑ Ð´Ð»Ñ ÑущеÑтвующей таблиц базы данных. + + + + &Preferences... + &ÐаÑтройки... + + + + + Open the preferences window. + Открыть окно наÑтроек. + + + + &DB Toolbar + &Панель инÑтрументов БД + + + + Shows or hides the Database toolbar. + Показать или Ñкрыть панель инÑтрументов База данных. + + + + Shift+F1 + Shift+F1 + + + + &Recently opened + &Ðедавние файлы + + + + Ctrl+T + Ctrl+T + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + Это Ñтруктура открытой БД. +Ð’Ñ‹ можете перетаÑкивать операторы SQL из Ñтроки "объект" и переноÑить их в другие Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ в другой ÑкземплÑÑ€ "Обозреватель Ð´Ð»Ñ SQLite". + + + + + SQL &Log + &Журнал SQL + + + + Show S&QL submitted by + По&казывать SQL, выполненный + + + + &Plot + &График + + + + &Revert Changes + &Отменить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + + + + &Write Changes + &ЗапиÑать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + + + + &Database from SQL file... + &База данных из файла SQL... + + + + &Table from CSV file... + &Таблицы из файла CSV... + + + + &Database to SQL file... + Базу &данных в файл SQL... + + + + &Table(s) as CSV file... + &Таблицы в файл CSV... + + + + &Create Table... + &Создать таблицу... + + + + &Delete Table... + &Удалить таблицу... + + + + &Modify Table... + &Модифицировать таблицу... + + + + Create &Index... + Создать и&ндекÑ... + + + + W&hat's This? + Что &Ñто такое? + + + + &Execute SQL + Ð’&ыполнить SQL + + + + + + Save SQL file + Сохранить файл SQL + + + + Ctrl+E + Ctrl+E + + + + Export as CSV file + ЭкÑпортировать в файл CSV + + + + Export table as comma separated values file + ЭкÑпортировать таблицу как CSV файл + + + + + Save the current session to a file + Сохранить текущее ÑоÑтоÑние в файл + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + Эта кнопка позволÑет Ñохранить вÑе наÑтройки, ÑвÑзанные Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¾Ð¹ базой данных, в файле проекта браузера баз данных Ð´Ð»Ñ SQLite + + + + + Load a working session from a file + Загрузить рабочее ÑоÑтоÑние из файла + + + + Copy Create statement + Копировать CREATE выражение + + + + Copy the CREATE statement of the item to the clipboard + Копировать CREATE выражение Ñлемента в буфер обмена + + + + Ctrl+Return + Ctrl+Return + + + + Ctrl+L + Ctrl+L + + + + + Ctrl+P + Ctrl+P + + + + Ctrl+D + Ctrl+D + + + + Ctrl+I + Ctrl+I + + + + Reset Window Layout + СброÑить Ñтруктуру окна + + + + The database is currently busy. + База данных ÑÐµÐ¹Ñ‡Ð°Ñ Ð·Ð°Ð½Ñта. + + + + Click here to interrupt the currently running query. + Ðажмите здеÑÑŒ, чтобы прервать текущий выполнÑемый запроÑ. + + + + Encrypted + Зашифровано + + + + Read only + Только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ + + + + Database file is read only. Editing the database is disabled. + База данных только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ. Редактирование запрещено. + + + + Database encoding + Кодировка базы данных + + + + Database is encrypted using SQLCipher + База данных зашифрована Ñ Ð¸Ñпользованием SQLCipher + + + + + Choose a database file + Выбрать файл базы данных + + + + Could not open database file. +Reason: %1 + Ðе удалоÑÑŒ открыть файл базы данных. +Причина:%1 + + + + + + Choose a filename to save under + Выбрать имÑ, под которым Ñохранить данные + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + Вышла Ð½Ð¾Ð²Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ DB Browser for SQLite (%1.%2.%3).<br/><br/>Она доÑтупна Ð´Ð»Ñ ÑÐºÐ°Ñ‡Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ адреÑу <a href='%4'>%4</a>. + + + + DB Browser for SQLite project file (*.sqbpro) + Файл проекта ÐžÐ±Ð¾Ð·Ñ€ÐµÐ²Ð°Ñ‚ÐµÐ»Ñ Ð´Ð»Ñ SQLite (*.sqbpro) + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + Ошибка при Ñохранении файла базы данных. Это означает, что не вÑе Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² базе данных были Ñохранены. Сначала вам необходимо разрешить Ñледующую ошибку. + +%1 + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + Отменить вÑе изменениÑ, Ñделанные в файле базы данных '%1' поÑле поÑледнего ÑохранениÑ? + + + + Choose a file to import + Выберите файл Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð° + + + + Text files(*.sql *.txt);;All files(*) + ТекÑтовые файлы(*.sql *.txt);;Ð’Ñе файлы(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + Создать новый файл базы данных, чтобы Ñохранить импортированные данные? +ЕÑли ответить Ðет, будет выполнена попытка импортировать данные файла SQL в текущую базу данных. + + + + Ctrl+Tab + Ctrl+Tab + + + + Ctrl+Shift+Tab + Ctrl+Shift+Tab + + + + Clear List + ОчиÑтить ÑпиÑок + + + + Window Layout + РаÑположение окон + + + + Ctrl+0 + Ctrl+0 + + + + Simplify Window Layout + УпорÑдочить окна + + + + Alt+Shift+0 + Alt+Shift+0 + + + + Dock Windows at Bottom + Закрепить окна Ñнизу + + + + Dock Windows at Left Side + Закрепить окна Ñлева + + + + Dock Windows at Top + Закрепить окна Ñверху + + + + Alt+Shift+W + Alt+Shift+W + + + + Choose a database file to save under + Выберите файл БД Ð´Ð»Ñ ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ + + + + Error while saving the database to the new file. + Ошибка при Ñохранении БД в новый файл. + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + Ð’Ñ‹ вÑе еще выполнÑете SQL-выражениÑ. Закрытие базы данных ÑÐµÐ¹Ñ‡Ð°Ñ Ð¾Ñтановит их выполнение, возможно, оÑтавив базу данных в неÑоглаÑованном ÑоÑтоÑнии. Ð’Ñ‹ уверены, что хотите закрыть базу данных? + + + + Do you want to save the changes made to the project file '%1'? + Хотите Ñохранить изменениÑ, внеÑенные в файл проекта «%1»? + + + + Edit View %1 + Редактировать предÑтавление %1 + + + + Edit Trigger %1 + Редактировать триггер %1 + + + + File %1 already exists. Please choose a different name. + Файл %1 уже ÑущеÑтвует. Выберите другое имÑ. + + + + Error importing data: %1 + Ошибка Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ…: %1 + + + + Import completed. + Импорт завершён. + + + + Delete View + Удалить предÑтавление + + + + Modify View + Модифицировать предÑтавление + + + + Delete Trigger + Удалить триггер + + + + Modify Trigger + Модифицировать триггер + + + + Delete Index + Удалить Ð¸Ð½Ð´ÐµÐºÑ + + + + Opened '%1' in read-only mode from recent file list + Открыт '%1' в режиме только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð¸Ð· ÑпиÑка поÑледних файлов + + + + Opened '%1' from recent file list + Открыт '%1' из ÑпиÑка поÑледних файлов + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ) + + + + Open Database or Project + + + + + Attach Database... + ПриÑоединить БД... + + + + Import CSV file(s)... + Импорт CSV файла(ов)... + + + + Do you want to save the changes made to SQL tabs in a new project file? + Хотите ли вы Ñохранить изменениÑ, внеÑенные во вкладки SQL, в новом файле проекта? + + + + Do you want to save the changes made to the SQL file %1? + Хотите Ñохранить изменениÑ, внеÑенные в файл SQL %1? + + + + Could not find resource file: %1 + Could not find resource file: %1 + + + + Choose a project file to open + Выберите файл проекта Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ + + + + DB file '%1' could not be opened + Файл базы данных '%1' не может быть открыт + + + + Table '%1' not found; settings ignored + Таблица '%1' не найдена; наÑтройки игнорируютÑÑ + + + + Could not open project file for writing. +Reason: %1 + Ðе удалоÑÑŒ открыть файл проекта Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи. +Причина: %1 + + + + -- Reference to file "%1" (not supported by this version) -- + -- СÑылка на файл "%1" (не поддерживаетÑÑ Ñтой верÑией) -- + + + + Busy (%1) + ЗанÑÑ‚ (%1) + + + + Error checking foreign keys after table modification. The changes will be reverted. + Ошибка проверки внешних ключей поÑле Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹. Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ отменены. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + Эта таблица не прошла проверку внешнего ключа. <br/> Ð’Ñ‹ должны запуÑтить "ИнÑтрументы | Проверка внешнего ключа"и иÑправить Ñообщенные проблемы. + + + + Execution finished with errors. + Выполнено Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°Ð¼Ð¸. + + + + Execution finished without errors. + Выполнено без ошибок. + + + + + Delete Table + Удалить таблицу + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + УÑтановка значений PRAGMA завершит текущую транзакцию. УÑтановить значениÑ? + + + + In-Memory database + БД в памÑти + + + + Automatically load the last opened DB file at startup + ÐвтоматичеÑки загружать поÑледнюю БД при запуÑке + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + Ð’Ñ‹ дейÑтвительно хотите удалить таблицу '%1'? +Ð’Ñе данные, ÑвÑзанные Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†ÐµÐ¹, будут потерÑны. + + + + Are you sure you want to delete the view '%1'? + Ð’Ñ‹ дейÑтвительно хотите удалить предÑтавление '%1'? + + + + Are you sure you want to delete the trigger '%1'? + Ð’Ñ‹ дейÑтвительно хотите удалить триггер '%1'? + + + + Are you sure you want to delete the index '%1'? + Ð’Ñ‹ дейÑтвительно хотите удалить Ð¸Ð½Ð´ÐµÐºÑ '%1'? + + + + Error: could not delete the table. + Ошибка: не удалоÑÑŒ удалить таблицу. + + + + Error: could not delete the view. + Ошибка: не удалоÑÑŒ удалить предÑтавление. + + + + Error: could not delete the trigger. + Ошибка: не удалоÑÑŒ удалить триггер. + + + + Error: could not delete the index. + Ошибка: не удалоÑÑŒ удалить индекÑ. + + + + Message from database engine: +%1 + Сообщение от DB-engine: +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + Ð”Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹ необходимо Ñохранить вÑе ожидающие Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÑейчаÑ. +Ð’Ñ‹ дейÑтвительно хотите Ñохранить БД? + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + Ð’Ñ‹ уже выполнÑете SQL-выражениÑ. Хотите оÑтановить их, чтобы вмеÑто Ñтого выполнить текущие выражениÑ? Обратите внимание, что Ñто может привеÑти базу данных в неÑоглаÑованное ÑоÑтоÑние. + + + + -- EXECUTING SELECTION IN '%1' +-- + -- ВЫПОЛÐЕÐИЕ ВЫБОРКИ Ð’ '%1' +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- ВЫПОЛÐЕÐИЕ СТРОКИ Ð’ '%1' +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- ВЫПОЛÐЕÐИЕ ВСЕГО Ð’ '%1' +-- + + + + + At line %1: + Ðа Ñтроке %1: + + + + Result: %1 + Результат: %1 + + + + Result: %2 + Результат: %2 + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + УÑтановка значений PRAGMA или Ð²Ð°ÐºÑƒÑƒÐ¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¸Ð²ÐµÐ´ÐµÑ‚ к фикÑации текущей транзакции. +Уверены ли вы? + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + + + + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + Операторы на вкладке '%1' вÑе еще выполнÑÑŽÑ‚ÑÑ. Закрытие вкладки оÑтановит выполнение. Это может привеÑти к тому, что база данных окажетÑÑ Ð² неÑоглаÑованном ÑоÑтоÑнии. Ð’Ñ‹ уверены, что хотите закрыть вкладку? + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + Этот файл проекта иÑпользует Ñтарый формат файла, поÑкольку он был Ñоздан Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ DB Browser for SQLite верÑии 3.10 или ниже. Загрузка Ñтого формата файла больше не поддерживаетÑÑ Ð¿Ð¾Ð»Ð½Ð¾Ñтью. ЕÑли вы хотите загрузить его полноÑтью, иÑпользуйте DB Browser for SQLite верÑии 3.12, чтобы преобразовать его в новый формат файла. + + + + Yes. Don't ask again + Да. Ðе Ñпрашивать Ñнова + + + + This action will open a new SQL tab with the following statements for you to edit and run: + Это дейÑтвие откроет новую вкладку SQL Ñо Ñледующими операторами, которые вы можете редактировать и выполнÑть: + + + + Rename Tab + Переименовать вкладку + + + + Duplicate Tab + Дублировать вкладку + + + + Close Tab + Закрыть вкладку + + + + Opening '%1'... + ОткрываетÑÑ '%1'... + + + + There was an error opening '%1'... + Произошла ошибка при открытии '%1'... + + + + Value is not a valid URL or filename: %1 + Значение не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимым URL-адреÑом или именем файла: %1 + + + + %1 rows returned in %2ms + %1 Ñтрок возвращено за %2Ð¼Ñ + + + + Choose text files + Выберите текÑтовые файлы + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + Импорт завершен. Ðарушены некоторые Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð²Ð½ÐµÑˆÐ½Ð¸Ñ… ключей. ПожалуйÑта, иÑправьте их перед Ñохранением. + + + + Modify Index + Модифицировать Ð¸Ð½Ð´ÐµÐºÑ + + + + Modify Table + Модифицировать таблицу + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + Хотите Ñохранить изменениÑ, внеÑенные во вкладки SQL в файле проекта «%1»? + + + + Select SQL file to open + Выбрать файл SQL Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ + + + + Select file name + Выбрать Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° + + + + Select extension file + Выбрать раÑширение файла + + + + Extension successfully loaded. + РаÑширение уÑпешно загружено. + + + + Error loading extension: %1 + Ошибка загрузки раÑширениÑ: %1 + + + + + Don't show again + Ðе показывать Ñнова + + + + New version available. + ДоÑтупна Ð½Ð¾Ð²Ð°Ñ Ð²ÐµÑ€ÑиÑ. + + + + Project saved to file '%1' + Проект Ñохранен в файл '%1' + + + + Collation needed! Proceed? + Ðужно Collation! Продолжить? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + Таблица в базе данных требует Ð½Ð°Ð»Ð¸Ñ‡Ð¸Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¸ ÑопоÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ (Collation)'%1'.чего Ñто приложение не может предоÑтавить без дополнительных знаний +ЕÑли вы продолжите, то возможна порча вашей базы данных. +Создайте резервную копию! + + + + creating collation + Ñоздание Collation + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + Задайте новое Ð¸Ð¼Ñ Ð´Ð»Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ¸ SQL. ИÑпользуйте Ñимвол '&&', чтобы разрешить иÑпользование Ñледующего Ñимвола в качеÑтве ÑÐ¾Ñ‡ÐµÑ‚Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ. + + + + Please specify the view name + Укажите Ð¸Ð¼Ñ Ð¿Ñ€ÐµÐ´ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ + + + + There is already an object with that name. Please choose a different name. + Объект Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ñ‹Ð¼ именем уже ÑущеÑтвует. Выберите другое имÑ. + + + + View successfully created. + ПредÑтавление уÑпешно Ñоздано. + + + + Error creating view: %1 + Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¿Ñ€ÐµÐ´ÑтавлениÑ: %1 + + + + This action will open a new SQL tab for running: + Это дейÑтвие откроет новую вкладку SQL Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑка: + + + + Press Help for opening the corresponding SQLite reference page. + Ðажмите "Справка" Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ ÑоответÑтвующей Ñправочной Ñтраницы SQLite. + + + + NullLineEdit + + + Set to NULL + УÑтановить в NULL + + + + Alt+Del + Alt+Del + + + + PlotDock + + + Plot + График + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>Ðа Ñтой панели отображаетÑÑ ÑпиÑок Ñтолбцов текущей проÑматриваемой таблицы или только что выполненного запроÑа. Ð’Ñ‹ можете выбрать Ñтолбцы, которые вы хотите иÑпользовать в качеÑтве оÑи X или Y Ð´Ð»Ñ Ð³Ñ€Ð°Ñ„Ð¸ÐºÐ° ниже. Ð’ таблице показан тип обнаруженной оÑи, который повлиÑет на итоговый график. Ð”Ð»Ñ Ð¾Ñи Y вы можете выбирать только чиÑловые Ñтолбцы, но Ð´Ð»Ñ Ð¾Ñи X вы можете выбрать:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Дата/ВремÑ</span>: Ñтроки Ñ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¾Ð¼ &quot;гггг-ММ-дд чч:мм:ÑÑ&quot; или &quot;гггг-ММ-ддTчч:мм:ÑÑ&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Дата</span>: Ñтроки Ñ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¾Ð¼ &quot;гггг-ММ-дд&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">ВремÑ</span>: Ñтроки Ñ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¾Ð¼ &quot;чч:мм:ÑÑ&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">ТекÑÑ‚</span>: Ñтроки лубого формата. Выбор Ñтого Ñтолбца по оÑи X приведет к Ñозданию графика Баров, Ñо значениÑми Ñтолбцов в качеÑтве меток Ð´Ð»Ñ Ð±Ð°Ñ€Ð¾Ð²</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">ЧиÑла</span>: целочиÑленные или вещеÑтвенные значениÑ</li></ul><p>Дважды щелкните по Ñчейкам Y, вы можете изменить иÑпользуемый цвет Ð´Ð»Ñ Ñтого графика.</p></body></html> + + + + Columns + Столбцы + + + + X + X + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + Тип оÑи + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + Вот график, нариÑованный, когда вы выбираете Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ x и y выше. + +Ðажмите на пункты, чтобы выбрать их на графике и в таблице. Ctrl + Click Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° диапазона точек. + +ИÑпользуйте колеÑико мыши Ð´Ð»Ñ Ð¼Ð°ÑÑˆÑ‚Ð°Ð±Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸ перетаÑÐºÐ¸Ð²Ð°Ð½Ð¸Ñ Ð¼Ñ‹ÑˆÑŒÑŽ Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð° оÑей. + +Выберите метки оÑей или оÑей Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÑ‚Ð°ÑÐºÐ¸Ð²Ð°Ð½Ð¸Ñ Ð¸ маÑÑˆÑ‚Ð°Ð±Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в Ñтой ориентации. + + + + Line type: + ЛиниÑ: + + + + + None + Ðет + + + + Line + ÐžÐ±Ñ‹Ñ‡Ð½Ð°Ñ + + + + StepLeft + СтупенчатаÑ, Ñлева + + + + StepRight + СтупенчатаÑ, Ñправа + + + + StepCenter + СтупенчатаÑ, по центру + + + + Impulse + Ð˜Ð¼Ð¿ÑƒÐ»ÑŒÑ + + + + Point shape: + ОтриÑовка точек: + + + + Cross + КреÑÑ‚ + + + + Plus + ÐŸÐ»ÑŽÑ + + + + Circle + Круг + + + + Disc + ДиÑк + + + + Square + Квадрат + + + + Diamond + Ромб + + + + Star + Звезда + + + + Triangle + Треугольник + + + + TriangleInverted + Треугольник перевернутый + + + + CrossSquare + КреÑÑ‚ в квадрате + + + + PlusSquare + ÐŸÐ»ÑŽÑ Ð² квадрате + + + + CrossCircle + КреÑÑ‚ в круге + + + + PlusCircle + ÐŸÐ»ÑŽÑ Ð² круге + + + + Peace + Мир + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>Сохранить текущий график...</p><p>Формат файла выбираетÑÑ Ñ€Ð°Ñширением (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + Сохранить текущий график... + + + + + Load all data and redraw plot + Загрузить вÑе данные и перериÑовать + + + + + + Row # + Строка # + + + + Copy + Копировать + + + + Print... + Печать... + + + + Help + Помощь + + + + Show legend + Легенда + + + + Stacked bars + Сложенные панели + + + + Fixed number format + ФикÑированный формат чиÑел + + + + Date/Time + Дата/Ð’Ñ€ÐµÐ¼Ñ + + + + Date + Дата + + + + Time + Ð’Ñ€ÐµÐ¼Ñ + + + + + Numeric + ЧиÑло + + + + Label + ТекÑÑ‚ + + + + Invalid + Ошибка + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + Загружает вÑе данные и перериÑовывает график. +Предупреждение: не вÑе данные были получены из таблицы из-за механизма чаÑтичной выборки. + + + + Choose an axis color + Выберите цвет оÑи + + + + Choose a filename to save under + Выбрать Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°, под которым Ñохранить данные + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Ð’Ñе файлы(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + Ðа Ñтом графике еÑть кривые, и выбранный Ñтиль линии может применÑтьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ к графикам, отÑортированным по X. Либо Ñортируйте таблицу или Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð¿Ð¾ X, чтобы удалить кривые, либо выберите один из Ñтилей, поддерживаемых кривыми: Ðет или ОбычнаÑ. + + + + Loading all remaining data for this table took %1ms. + Загрузка вÑех оÑтавшихÑÑ Ð´Ð°Ð½Ð½Ñ‹Ñ… Ð´Ð»Ñ Ñтой таблицы занÑла %1мÑ. + + + + PreferencesDialog + + + Preferences + ÐаÑтройки + + + + &Database + &База данных + + + + Database &encoding + &Кодировка текÑта БД + + + + Open databases with foreign keys enabled. + Открывать базы данных Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ внешних ключей. + + + + &Foreign keys + &Внешние ключи + + + + + + + + + + + + + + enabled + включены + + + + Default &location + &РаÑположение +по умолчанию + + + + + + ... + ... + + + + &General + &Общие + + + + Remember last location + Запоминать поÑледнюю директорию + + + + Always use this location + Ð’Ñегда открывать указанную + + + + Remember last location for session only + Запоминать поÑледнюю директорию только Ð´Ð»Ñ ÑеÑÑий + + + + Lan&guage + &Язык + + + + Automatic &updates + &Следить за обновлениÑми + + + + SQ&L to execute after opening database + SQL Ð´Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñле Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð±Ð°Ð·Ñ‹ данных + + + + Data &Browser + Обозреватель &данных + + + + Remove line breaks in schema &view + Удалить переводы Ñтроки в &Ñхеме данных + + + + Show remote options + Опции "облака" + + + + Prefetch block si&ze + Размер блока &упреждающей выборки + + + + Default field type + Тип данных по умолчанию + + + + Font + Шрифт + + + + &Font + &Шрифт + + + + Content + Содержимое + + + + Symbol limit in cell + КоличеÑтво Ñимволов в Ñчейке + + + + NULL + + + + + Regular + Обычные + + + + Binary + Двоичные данные + + + + Background + Фон + + + + Filters + Фильтры + + + + Threshold for completion and calculation on selection + Порог Ð´Ð»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð¸ раÑчета по выделенному + + + + Show images in cell + Показывать Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð² Ñчейке + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + Включите Ñту опцию, чтобы отобразить предварительный проÑмотр BLOB-объектов, Ñодержащих данные изображений в Ñчейках. Однако Ñто может повлиÑть на производительноÑть браузера данных. + + + + Escape character + Символ ÑÐºÑ€Ð°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ + + + + Delay time (&ms) + Ð’Ñ€ÐµÐ¼Ñ Ð·Ð°Ð´ÐµÑ€Ð¶ÐºÐ¸ (&мÑ) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + Ð’Ñ€ÐµÐ¼Ñ Ð·Ð°Ð´ÐµÑ€Ð¶ÐºÐ¸ перед применением нового фильтра. Ðулевое значение отключает ожидание. + + + + &SQL + Р&едактор SQL + + + + Context + КонтекÑÑ‚ + + + + Colour + Цвет + + + + Bold + Жирный + + + + Italic + КурÑив + + + + Underline + Подчёркивание + + + + Keyword + Ключевое Ñлово + + + + Function + Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ + + + + Table + Таблица + + + + Comment + Комментарий + + + + Identifier + Идентификатор + + + + String + Строка + + + + Current line + Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ñтрока + + + + SQL &editor font size + Размер шрифта в &редакторе SQL + + + + Tab size + Размер табулÑции + + + + SQL editor &font + &Шрифт в редакторе SQL + + + + Error indicators + Индикаторы ошибок + + + + Hori&zontal tiling + Гори&зонтальное раÑпределение + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + ЕÑли Ð´Ð°Ð½Ð½Ð°Ñ Ð¾Ð¿Ñ†Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°, то SQL редактор и результат запроÑа будут раÑположены Ñ€Ñдом по горизонтали. + + + + Code co&mpletion + Ðвто&дополнение кода + + + + Toolbar style + Стиль тулбара + + + + + + + + Only display the icon + Только иконки + + + + + + + + Only display the text + Только текÑÑ‚ + + + + + + + + The text appears beside the icon + ТекÑÑ‚ Ñ€Ñдом Ñ Ð¸ÐºÐ¾Ð½ÐºÐ¾Ð¹ + + + + + + + + The text appears under the icon + ТекÑÑ‚ под иконкой + + + + + + + + Follow the style + Указано в Ñтиле + + + + DB file extensions + РаÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð² БД + + + + Manage + ÐаÑтроить + + + + Main Window + Главное окно + + + + Database Structure + Структура БД + + + + Browse Data + ПроÑмотр данных + + + + Execute SQL + Редактор SQL + + + + Edit Database Cell + Правка Ñчейки БД + + + + When this value is changed, all the other color preferences are also set to matching colors. + При изменении Ñтого Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñе оÑтальные цветовые наÑтройки также уÑтанавливаютÑÑ Ð½Ð° ÑоответÑтвующие цвета. + + + + Follow the desktop style + Стиль рабочего Ñтола + + + + Dark style + Темный + + + + Application style + Стиль Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ + + + + This sets the font size for all UI elements which do not have their own font size option. + Размер шрифта Ð´Ð»Ñ Ð²Ñех Ñлементов пользовательÑкого интерфейÑа, которые не имеют ÑобÑтвенной опции размера шрифта. + + + + Font size + Размет шрифта + + + + Max Recent Files + Кол. недавних файлов + + + + Prompt to save SQL tabs +in new project file + Предлагать Ñохранение вкладок SQL +в новом файле проекта + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + ЕÑли Ñта Ð¾Ð¿Ñ†Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°, то Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² редакторе SQL при закрытии вкладки редактора SQL будут приводить к поÑвлению диалогового окна Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°. + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + Когда отмечено, переноÑÑ‹ Ñтрок в Ñтолбце 'Схема' во вкладке 'Структура базы данных', 'док' и 'печатный результат' удалÑÑŽÑ‚ÑÑ. + + + + Database structure font size + Рзмер шрифта во вкладке Ñтруктуры БД + + + + Font si&ze + Ра&змер шрифта + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + Это макÑимальное количеÑтво Ñлементов, разрешенное Ð´Ð»Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð½ÐµÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ñ… вычиÑлительно затратных функций: +МакÑимальное количеÑтво Ñтрок в таблице Ð´Ð»Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹ на оÑнове текущих значений в Ñтолбце. +МакÑимальное количеÑтво индекÑов в выборке Ð´Ð»Ñ Ñ€Ð°Ñчета Ñуммы и Ñреднего. +Можно уÑтановить на 0 Ð´Ð»Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¹. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + МакÑимальное количеÑтво Ñтрок в таблице Ð´Ð»Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð½Ð° оÑнове текущих значений в Ñтолбце. +Может быть уÑтановлено в 0 Ð´Ð»Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ. + + + + Field display + Отображение Ð¿Ð¾Ð»Ñ + + + + Light style + Светлый + + + + Displayed &text + Отображаемый &текÑÑ‚ + + + + Formatted + Отформатированный + + + + + + + + + + + Click to set this color + Клик Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° цвета + + + + Text color + Цвет текÑта + + + + Background color + Цвет фона + + + + + Preview only (N/A) + Только проÑмотр + + + + Foreground + Передний план + + + + Selection background + Фон Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ + + + + Selection foreground + Выделение на переднем плане + + + + Highlight + Выделение + + + + SQL &results font size + &Размер шрифта в окне результата SQL + + + + Use tabs for indentation + ТабулÑции Ð´Ð»Ñ Ð¾Ñ‚Ñтупов + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + При уÑтановке, клавишей Tab будут вÑтавлÑтьÑÑ Ñимволы табулÑции и пробела Ð´Ð»Ñ Ð¾Ñ‚Ñтупа. Ð’ противном Ñлучае будут иÑпользоватьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ пробелы. + + + + &Wrap lines + &ÐŸÐµÑ€ÐµÐ½Ð¾Ñ Ñтрок + + + + Never + Ðикогда + + + + At word boundaries + Ðа границах Ñлов + + + + At character boundaries + Ðа границах Ñимволов + + + + At whitespace boundaries + Ðа границах пробелов + + + + &Quotes for identifiers + Обрамление &идентификаторов + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + Выберите механизм обрамлениÑ, иÑпользуемый приложением Ð´Ð»Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð¾Ð² в коде SQL. + + + + "Double quotes" - Standard SQL (recommended) + "Двойные кавычки" - Cтандартный SQL (рекомендуетÑÑ) + + + + `Grave accents` - Traditional MySQL quotes + `ГравиÑ` - Традиционные кавычки MySQL + + + + [Square brackets] - Traditional MS SQL Server quotes + [Квадратные Ñкобки] - традиционные кавычки Ð´Ð»Ñ MS SQL Server + + + + Keywords in &UPPER CASE + Ключевые Ñлова в &ВЕРХÐЕМ РЕГИСТРЕ + + + + When set, the SQL keywords are completed in UPPER CASE letters. + Когда отмечено, ключевые Ñлова SQL будут в ВЕРХÐЕМ РЕГИСТРЕ. + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + Когда уÑтановлено, Ñтроки кода SQL, вызвавшие ошибки во Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ñледнего выполнениÑ, подÑвечиваютÑÑ, а виджет результатов указывает на ошибку в фоновом режиме + + + + Close button on tabs + Кнопка Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ð½Ð° вкладках + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + ЕÑли включено, вкладки редактора SQL будут иметь кнопку закрытиÑ. Ð’ любом Ñлучае, вы можете иÑпользовать контекÑтное меню или Ñочетание клавиш, чтобы закрыть их. + + + + &Extensions + Р&аÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ + + + + Select extensions to load for every database: + Выберите раÑширениÑ, чтобы загружать их Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ базы данных: + + + + Add extension + Добавить раÑширение + + + + Remove extension + Удалить раÑширение + + + + Select built-in extensions to load for every database: + Выбрать вÑтроенные раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ базы данных: + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>Обозреватель Ð´Ð»Ñ SQLite позволÑет иÑпользовать оператор REGEXP 'из коробки'. Ðо тем <br/>не менее, возможны неÑколько различных вариантов реализаций данного оператора и вы Ñвободны <br/>в выборе какую именно иÑпользовать. Можно отключить нашу реализацию и иÑпользовать другую - <br/>путем загрузки ÑоответÑтвующего раÑширениÑ. Ð’ Ñтом Ñлучае требуетÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° приложениÑ.</p></body></html> + + + + Disable Regular Expression extension + Отключить раÑширение РегулÑрных Выражений + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite предоÑтавлÑет функцию SQL Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ раÑширений из файла общей библиотеки. Ðктивируйте ее, еÑли хотите иÑпользовать функцию <span style=" font-style:italic;">load_extension()</span> из кода SQL.</p><p>Ð’ целÑÑ… безопаÑноÑти загрузка раÑширений по умолчанию отключена и должна быть включена Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Ñтого параметра. Ð’Ñ‹ вÑегда можете загружать раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· графичеÑкий интерфейÑ, даже еÑли Ñта Ð¾Ð¿Ñ†Ð¸Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°.</p></body></html> + + + + Allow loading extensions from SQL code + Разрешить загрузку раÑширений из кода SQL + + + + Remote + Удаленный Ñервер + + + + CA certificates + СРÑертификаты + + + + Proxy + ПрокÑи + + + + Configure + ÐаÑтроить + + + + Export Settings + ЭкÑпорт наÑтроек + + + + Import Settings + Импорт наÑтроек + + + + + Subject CN + Субъект + + + + Common Name + ОбщепринÑтое Ð¸Ð¼Ñ + + + + Subject O + ÐžÑ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ + + + + Organization + ÐžÑ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ + + + + + Valid from + ДейÑтвует Ñ + + + + + Valid to + ДейÑтвует по + + + + + Serial number + Серийный â„– + + + + Your certificates + Ваши Ñертификаты + + + + File + Файл + + + + Subject Common Name + ОбщепринÑтое Ð¸Ð¼Ñ Ð¡ÑƒÐ±ÑŠÐµÐºÑ‚Ð° + + + + Issuer CN + Издатель + + + + Issuer Common Name + общепринÑтое Ð¸Ð¼Ñ Ð¸Ð·Ð´Ð°Ñ‚ÐµÐ»Ñ + + + + Clone databases into + Путь Ð´Ð»Ñ ÐºÐ»Ð¾Ð½Ð¸Ñ€ÑƒÐµÐ¼Ñ‹Ñ… БД + + + + + Choose a directory + Выберите каталог + + + + + The language will change after you restart the application. + Язык будет применен поÑле перезапуÑка приложениÑ. + + + + Select extension file + Выберите файл раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ + + + + Extensions(*.so *.dylib *.dll);;All files(*) + РаÑширениÑ(*.so *.dylib *.dll);;All files(*) + + + + Import certificate file + Импорт файла Ñертификата + + + + No certificates found in this file. + Ð’ данном файле не найден Ñертификат. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + Ð’Ñ‹ дейÑтвительно хотите удалить Ñтот Ñертификат? Ð’Ñе данные Ñертификата будут удалены из наÑтроек приложениÑ! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + Ð’Ñ‹ дейÑтвительно хотите удалить вÑе Ñохраненные наÑтройки? +Ð’Ñе ваши Ð¿Ñ€ÐµÐ´Ð¿Ð¾Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ потерÑны, и будут иÑпользоватьÑÑ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию. + + + + Save Settings File + Сохранить файл наÑтроек + + + + + Initialization File (*.ini) + Файл инициализации(*.ini) + + + + The settings file has been saved in location : + + Файл наÑтроек Ñохранен в: + + + + + Open Settings File + Открыть файл наÑтроек + + + + The settings file was loaded properly. + Файл наÑтроек загружен корректно. + + + + The selected settings file is not a normal settings file. +Please check again. + Выбранный файл наÑтроек не ÑвлÑетÑÑ Ð¾Ð±Ñ‹Ñ‡Ð½Ñ‹Ð¼ файлом наÑтроек. +Проверьте еще раз. + + + + ProxyDialog + + + Proxy Configuration + ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¾ÐºÑи-Ñервера + + + + Pro&xy Type + Тип прокÑи + + + + Host Na&me + Ð˜Ð¼Ñ Ñ…Ð¾Ñта + + + + Port + Порт + + + + Authentication Re&quired + ТребуетÑÑ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ + + + + &User Name + Пользователь + + + + Password + Пароль + + + + None + Ðет + + + + System settings + СиÑтемные наÑтройки + + + + HTTP + + + + + SOCKS5 + + + + + QObject + + + Error importing data + Ошибка Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… + + + + from record number %1 + Ñ Ð·Ð°Ð¿Ð¸Ñи номер %1 + + + + . +%1 + + + + + Importing CSV file... + Импортирование CSV файла... + + + + Cancel + Отменить + + + + All files (*) + Ð’Ñе файлы (*) + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + Файлы SQLite баз данных (*.db *.sqlite *.sqlite3 *.db3) + + + + Left + Влево + + + + Right + Вправо + + + + Center + По центру + + + + Justify + По ширине + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + SQLite Database файлы (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + DB Browser for SQLite Project файлы (*.sqbpro) + + + + SQL Files (*.sql) + SQL файлы (*.sql) + + + + All Files (*) + Ð’Ñе файлы (*) + + + + Text Files (*.txt) + ТекÑтовые файлы (*.txt) + + + + Comma-Separated Values Files (*.csv) + Файлы Ñ Ñ€Ð°Ð·Ð´ÐµÐ»Ð¸Ñ‚ÐµÐ»Ñми запÑтой (*.csv) + + + + Tab-Separated Values Files (*.tsv) + Файлы Ñ Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð¸ÐµÐ¼ табулÑцией (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + Файлы Ñ Ñ€Ð°Ð·Ð´ÐµÐ»Ð¸Ñ‚ÐµÐ»Ñми значений + Delimiter-Separated Values Files (*.dsv) + + + + Concordance DAT files (*.dat) + DAT файлы (*.dat) + + + + JSON Files (*.json *.js) + JSON файлы (*.json *.js) + + + + XML Files (*.xml) + XML файлы (*.xml) + + + + Binary Files (*.bin *.dat) + Двоичные файлы (*.bin *.dat) + + + + SVG Files (*.svg) + SVG файлы (*.svg) + + + + Hex Dump Files (*.dat *.bin) + Файлы шеÑтнадцатиричных дампов + + + + Extensions (*.so *.dylib *.dll) + РаÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + Файл инициализации (*.ini) + + + + QsciCommand + + Paste + Ð’Ñтавить + + + Cancel + Отменить + + + + QsciLexerCPP + + Default + По умолчанию + + + Keyword + Ключевое Ñлово + + + Identifier + Идентификатор + + + + QsciLexerJSON + + Default + По умолчанию + + + String + Строка + + + + QsciLexerPython + + Default + По умолчанию + + + Comment + Комментарий + + + Keyword + Ключевое Ñлово + + + Identifier + Идентификатор + + + + QsciLexerSQL + + Default + По умолчанию + + + Comment + Комментарий + + + Keyword + Ключевое Ñлово + + + Identifier + Идентификатор + + + + RemoteCommitsModel + + + Commit ID + Коммит ID + + + + Message + Комментарий + + + + Date + Дата + + + + Author + Ðвтор + + + + Size + Размер + + + + Authored and committed by %1 + Ðвтор и коммит %1 + + + + Authored by %1, committed by %2 + Ðвтор %1, коммит %2 + + + + RemoteDatabase + + + Error opening local databases list. +%1 + Ошибка при открытии ÑпиÑка локальных БД. +%1 + + + + Error creating local databases list. +%1 + Ошибка при Ñоздании ÑпиÑка локальных БД. +%1 + + + + RemoteDock + + + Remote + Удаленный Ñервер + + + + Identity + УдоÑтоверение + + + + Push currently opened database to server + Отправить текущую БД на Ñервер + + + + Upload + Загрузить + + + + DBHub.io + + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>Ðа Ñтой панели БД Ñ dbhub.io может быть добавлена в DB Browser for SQLite. Сначала вам нужно удоÑтоверение:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ÐвторизоватьÑÑ Ð½Ð° dbhub.io (иÑпользуйте ваши учетные данные GitHub или что-то еще, еÑли угодно)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ðажмите кнопку &quot;Generate client certificate&quot; (Ñто ваше удоÑтоверение). Ð’Ñ‹ получите файл Ñертификата (Ñохраните его на локальный диÑк).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Перейдите на вкладку Удаленный Ñервер наÑтроек DB Browser for SQLite. ДобавьтеÑертификат в DB Browser for SQLite и выберите Ñкачанный файл.</li></ol><p>Теперь на панели «Удалённый Ñервер» отображаетÑÑ Ð²Ð°ÑˆÐµ удоÑтоверение, и вы можете добавлÑть удалённые базы данных.</p></body></html> + + + + Local + Локальный + + + + Current Database + Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð‘Ð” + + + + Clone + Клонировать + + + + Branch + Ветка + + + + Commits + Коммиты + + + + Commits for + Коммиты Ð´Ð»Ñ + + + + Delete Database + Удалить БД + + + + Delete the local clone of this database + Удалить локальный клон Ñтой БД + + + + Open in Web Browser + Открыть в Web браузере + + + + Open the web page for the current database in your browser + Открыть веб-Ñтраницу текущей базы данных в вашем браузере + + + + Clone from Link + Клонировать из ÑÑылки + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + ИÑпользуйте Ñто Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ удаленной базы данных Ð´Ð»Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ Ð¸Ñпользованием URL-адреÑа, указанного на веб-Ñтранице базы данных. + + + + Refresh + Обновить + + + + Reload all data and update the views + Перезагрузите вÑе данные и обновите предÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ + + + + Clone Database + Клонировать БД + + + + Open Database + Открыть БД + + + + Open the local copy of this database + Открыть локально копию Ñтой БД + + + + Check out Commit + Проверить коммит + + + + Download and open this specific commit + Загрузить и открыть Ñтот коммит + + + + Check out Latest Commit + Проверить поÑледний коммит + + + + Check out the latest commit of the current branch + Проверить поÑледний коммит текущей ветки + + + + Save Revision to File + Сохранить верÑию в файл + + + + Saves the selected revision of the database to another file + Сохранить выбранную верÑию БД в другой файл + + + + Upload Database + Загрузить БД + + + + Upload this database as a new commit + Загрузить Ñту БД как новый коммит + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>Ð’Ñ‹ иÑпользуете вÑтроенное удоÑтоверение.Ð”Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ БД, нужно наÑтроить аккаунт на DBHub.io.</p><p>Ðет аккаунта на DBHub.io? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Создайте ÑейчаÑ</span></a> и импортируйте ваш Ñертификат <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">Ñюда</span></a> Ð´Ð»Ñ Ð´Ð¾Ñтупа к вашим базам данных.</p><p>ИнÑтрукции можно поÑмотреть здеÑÑŒ <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + + + + &User + Пользователь + + + + &Database + &База данных + + + + Back + Ðазад + + + + Select an identity to connect + Выбрать удоÑтоверение Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ + + + + Public + Публичный + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + Загрузка базы данных Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð½Ð¾Ð³Ð¾ Ñервера Ð´Ð»Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ редактированиÑ. +Введите URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ. Ð’Ñ‹ можете Ñгенерировать Ñтот URL, +нажав кнопку «Клонировать базу данных в DB4S» на веб-Ñтранице +базы данных. + + + + Invalid URL: The host name does not match the host name of the current identity. + Ðеверный URL: Ð¸Ð¼Ñ Ñ…Ð¾Ñта не Ñовпадает Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ хоÑта текущего удоÑтоверениÑ. + + + + Invalid URL: No branch name specified. + Ðеверный URL: не указано Ð¸Ð¼Ñ Ð²ÐµÑ‚ÐºÐ¸. + + + + Invalid URL: No commit ID specified. + Ðеверный URL: не указан идентификатор фикÑации. + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + Ð’Ñ‹ изменили локальный клон базы данных. Извлечение Ñтого коммита переопределит Ñти локальные изменениÑ. +Ð’Ñ‹ уверены, что хотите продолжить? + + + + The database has unsaved changes. Are you sure you want to push it before saving? + Ð’ базе данных еÑть неÑохраненные изменениÑ. Ð’Ñ‹ уверены, что хотите отправить их перед Ñохранением? + + + + The database you are trying to delete is currently opened. Please close it before deleting. + База данных, которую вы пытаетеÑÑŒ удалить, в данный момент открыта. ПожалуйÑта, закройте ее перед удалением. + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + ДейÑтвие удалит локальную верÑию Ñтой базы данных Ñо вÑеми изменениÑми, которые вы еще не зафикÑировали. Ð’Ñ‹ уверены, что хотите удалить Ñту базу данных? + + + + RemoteLocalFilesModel + + + Name + Ð˜Ð¼Ñ + + + + Branch + Ветка + + + + Last modified + Изменен + + + + Size + Размер + + + + Commit + Коммит + + + + File + Файл + + + + RemoteModel + + + Name + Ð˜Ð¼Ñ + + + + Last modified + Изменен + + + + Size + Размер + + + + Commit + Коммит + + + + Size: + Размер: + + + + Last Modified: + Изменен: + + + + Licence: + ЛицензиÑ: + + + + Default Branch: + Ветка по умолчанию: + + + + RemoteNetwork + + + Choose a location to save the file + Выбрать меÑтораÑположение Ð´Ð»Ñ ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° - - &File - &Файл + + Error opening remote file at %1. +%2 + Ошибка отÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð° %1. +%2 - - &Import - &Импорт + + Error: Invalid client certificate specified. + Ошибка: Указан неверный Ñертификат клиента. - - &Export - &ЭкÑпорт + + Please enter the passphrase for this client certificate in order to authenticate. + ПожалуйÑта введите ключевую фразу Ð´Ð»Ñ Ñтого Ñертификата клиента. - - &Edit - &Редактирование + + Cancel + Отменить - - &View - &Вид + + Uploading remote database to +%1 + ЗагружаетÑÑ ÑƒÐ´Ð°Ð»ÐµÐ½Ð½Ð°Ñ Ð‘Ð” в +%1 - - &Help - &Справка + + Downloading remote database from +%1 + СкачиваетÑÑ ÑƒÐ´Ð°Ð»ÐµÐ½Ð½Ð°Ñ Ð‘Ð” из +%1 - - DB Toolbar - Панель инÑтрументов БД + + Error: Cannot open the file for sending. + Ошибка: не удаетÑÑ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚ÑŒ файл Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸. + + + RemotePushDialog - - Table(s) as CSV file... - Таблицу в файл CSV... + + Push database + Отправить БД - - &Attach Database - &Прикрепить базу данных + + Database na&me to push to + &Ð˜Ð¼Ñ Ð‘Ð” - - Set Encryption - Шифрование + + Commit message + Сообщение - - - Save SQL file as - Сохранить файл SQL как + + Database licence + Ð›Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ - - &Browse Table - Пр&оÑмотр данных + + Public + Публичный - - SQL Log - Журнал SQL + + Branch + Ветка - - Clear all filters - ОчиÑтить вÑе фильтры + + Force push + Принудительно - - &Show SQL submitted by - По&казывать SQL, предоÑтавленный + + Username + Пользователь - - User - Пользователем + + Database will be public. Everyone has read access to it. + БД будет публичной. У каждого будет доÑтуп на чтение к ней. - - Application - Приложением + + Database will be private. Only you have access to it. + БД будет конфиденциальной. Только у Ð²Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ доÑтуп к ней. - - &Clear - О&чиÑтить + + Use with care. This can cause remote commits to be deleted. + ИÑпользуйте Ñ Ð¾ÑторожноÑтью. Это может привеÑти к удалению ÑущеÑтвующих коммитов. + + + RunSql - - Plot - График + + Execution aborted by user + Выполнение прервано пользователем - - Columns - Столбцы + + , %1 rows affected + , %1 Ñтрок затронуто - - X - X + + query executed successfully. Took %1ms%2 + Ð·Ð°Ð¿Ñ€Ð¾Ñ ÑƒÑпешно выполнен. ЗанÑло %1мÑ%2 - - Y - Y + + executing query + выполнение запроÑа + + + SelectItemsPopup - - _ - _ + + A&vailable + ДоÑтупные - - Line type: - ЛиниÑ: + + Sele&cted + Выбранные + + + SqlExecutionArea - - Line - ÐžÐ±Ñ‹Ñ‡Ð½Ð°Ñ + + Form + Форма - - StepLeft - СтупенчатаÑ, Ñлева + + Find previous match [Shift+F3] + Ðайти предыдущее Ñовпадение [Shift+F3] - - StepRight - СтупенчатаÑ, Ñправа + + Find previous match with wrapping + Ðайти предыдущее Ñовпадение, закольцевав поиÑк - - StepCenter - СтупенчатаÑ, по центру + + Shift+F3 + Shift+F3 - - Impulse - Ð˜Ð¼Ð¿ÑƒÐ»ÑŒÑ + + The found pattern must be a whole word + Ðайденный шаблон должен быть целым Ñловом - - Point shape: - ОтриÑовка точек: + + Whole Words + Слова ПолноÑтью - - Cross - КреÑÑ‚ + + Text pattern to find considering the checks in this frame + Шаблон Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка, ÑƒÑ‡Ð¸Ñ‚Ñ‹Ð²Ð°Ñ Ð²Ñе проверки - - Plus - ÐŸÐ»ÑŽÑ + + Find in editor + Ðайти в редакторе - - Circle - Круг + + The found pattern must match in letter case + У найденного шаблона должен Ñовпадать региÑтр - - Disc - ДиÑк + + Case Sensitive + Учитывать региÑтр - - Square - Квадрат + + Find next match [Enter, F3] + Ðайти Ñледующее Ñовпадение [Enter, F3] - - Diamond - Ромб + + Find next match with wrapping + Ðайти Ñледующее Ñовпадение, закольцевав поиÑк - - Star - Звезда + + F3 + F3 - - Triangle - Треугольник + + Interpret search pattern as a regular expression + Интерпретировать шаблон поиÑка как регулÑрное выражение - - TriangleInverted - Треугольник перевернутый + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>При проверке шаблон Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка интерпретируетÑÑ ÐºÐ°Ðº регулÑрное выражение UNIX. <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Узнать больше о РегулÑрных выражениÑÑ… на Wikibooks.org</a>.</p></body></html> - - CrossSquare - КреÑÑ‚ в квадрате + + Regular Expression + РегулÑрное выражение - - PlusSquare - ÐŸÐ»ÑŽÑ Ð² квадрате + + + Close Find Bar + Закрыть ПоиÑковую Панель - - CrossCircle - КреÑÑ‚ в круге + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>Результаты Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñледних инÑтрукций.</p><p>Ð’Ñ‹ можете Ñвернуть Ñту панель и иÑпользовать <span style=" font-style:italic;">SQL Log</span> на <span style=" font-style:italic;">Ваш</span> выбор.</p></body></html> - - PlusCircle - ÐŸÐ»ÑŽÑ Ð² круге + + Results of the last executed statements + Результаты поÑледних выполненных операторов - - Peace - Мир + + This field shows the results and status codes of the last executed statements. + Это поле показывает результаты и коды ÑтатуÑов поÑледних выполненных операторов. - - <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> - <html><head/><body><p>Сохранить текущий график...</p><p>Формат файла выбираетÑÑ Ñ€Ð°Ñширением (png, jpg, pdf, bmp)</p></body></html> + + Ctrl+PgUp + Ctrl+PgUp - - Save current plot... - Сохранить текущий график... + + Ctrl+PgDown + Ctrl+PgDown - - DB Schema - Схема БД + + Couldn't read file "%1": %2. + Ðе удалоÑÑŒ прочитать файл "%1": %2. - - &New Database... - &ÐÐ¾Ð²Ð°Ñ Ð±Ð°Ð·Ð° данных... + + + Couldn't save file: %1. + Ðе удалоÑÑŒ Ñохранить файл:%1. - - - Create a new database file - Создать новый файл базы данных + + Your changes will be lost when reloading it! + При повторной загрузке ваши Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ потерÑны! - - This option is used to create a new database file. - Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¸ÑпользуетÑÑ, чтобы Ñоздать новый файл базы данных. + + The file "%1" was modified by another program. Do you want to reload it?%2 + Файл "%1" был изменен другой программой. Хотите перезагрузить его?%2 - - Ctrl+N - Ctrl+N + + Answer "Yes to All" to reload the file on any external update without further prompting. + Ответ «Да Ð´Ð»Ñ Ð²Ñех», чтобы перезагрузить файл при любом внешнем обновлении без дополнительных запроÑов. - - &Open Database... - &Открыть базу данных... + + Answer "No to All" to ignore any external update without further prompting. + Ответ «Ðет Ð´Ð»Ñ Ð²Ñех», чтобы игнорировать любые внешние Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð±ÐµÐ· дальнейших запроÑов. - - - Open an existing database file - Открыть ÑущеÑтвующий файл базы данных + + Modifying and saving the file will restore prompting. + При изменении и Ñохранении файла поÑвитÑÑ Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° воÑÑтановление. + + + SqlTextEdit - - This option is used to open an existing database file. - Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¸ÑпользуетÑÑ, чтобы открыть ÑущеÑтвующий файл базы данных. + + Ctrl+/ + Ctrl+/ + + + SqlUiLexer - - Ctrl+O - Ctrl+O + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ abs(X) возвращает модуль чиÑла аргумента X. - - &Close Database - &Закрыть базу данных + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ changes() возвращает количеÑтво Ñтрок в базе данных, которые были изменены, вÑтавлены или удалены поÑле удачного Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ INSERT, DELETE или UPDATE. - - Ctrl+W - Ctrl+W + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ char(X1,X2,...,XN) возвращает Ñтроку ÑоÑтавленную из Ñимволов, переданных в качеÑтве аргументов. - - Revert Changes - Отменить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ coalesce() возвращает копию первого аргумента не равного NULL иначе еÑли такого нет то возвращаетÑÑ NULL - - Revert database to last saved state - Вернуть базу данных в поÑледнее Ñохранённое ÑоÑтоÑние + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ glob(X,Y) Ñквивалент выражению "Y GLOB X". - - This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. - Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¸ÑпользуетÑÑ, чтобы вернуть текущий файл базы данных в его поÑледнее Ñохранённое ÑоÑтоÑние. Ð’Ñе изменениÑ, Ñделаные Ñ Ð¿Ð¾Ñледней операции ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ñ‚ÐµÑ€ÑÑŽÑ‚ÑÑ. + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ ifnull() возвращает копию первого аргумента не равного NULL иначе еÑли оба аргумента равны NULL то возвращает NULL. - - Write Changes - ЗапиÑать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ instr(X,Y) возвращает количеÑтво Ñимволов, Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ в Ñтроке X найдена подÑтрока Y или 0 еÑли Ñ‚Ð°ÐºÐ¾Ð²Ð°Ñ Ð½Ðµ обнаружена. - - Write changes to the database file - ЗапиÑать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² файл базы данных + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ hex() интерпретирует аргумент как BLOB и возвращает Ñтроку в 16-ричной ÑиÑтеме ÑчиÑÐ»ÐµÐ½Ð¸Ñ Ñ Ñодержимым аргумента. - - This option is used to save changes to the database file. - Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¸ÑпользуетÑÑ, чтобы Ñохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² файле базы данных. + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) iif(уÑловие, значение_1, значение_2) возвращает значение_1 еÑли уÑловие верно, и значение_2 в противном Ñлучае. - - Ctrl+S - Ctrl+S + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ last_insert_rowid() возвращает ROWID поÑледней вÑтавленной Ñтроки. + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) Ð”Ð»Ñ Ñтрокового Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ X, Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ length(X) возвращает количеÑтво Ñимволов (не байт) от начала Ñтроки до первого Ñимвола '\0'. + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ like() Ñквивалент выражению "Y LIKE X". + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ like() Ñквивалент Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ "Y LIKE X ESCAPE Z". + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ load_extension(X) загружает раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ SQLite из файла общей библиотеки Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ X. +ИÑпользование Ñтой функции должно быть разрешено в наÑтройках. + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ load_extension(X) загружает раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ SQLite из файла общей библиотеки Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ X, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ñ‚Ð¾Ñ‡ÐºÑƒ входа Y. +ИÑпользование Ñтой функции должно быть разрешено в наÑтройках. + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ lower(X) возвращает копию Ñтроки X, в которой вÑе ACSII Ñимволы переведены в нижний региÑтр. + + + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) удалÑет Ñимволы пробелов Ñлева Ð´Ð»Ñ Ñтроки X. + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ ltrim(X,Y) возвращает новую Ñтроку путем ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¸Ð· Ñтроки X Ñлева любого Ñимвола из Y. + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ max() возвращает аргумент Ñ Ð¼Ð°ÐºÑимальным значением, либо NULL еÑли Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ один аргумент равен NULL. + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ min() возвращает аргумент Ñ Ð¼Ð¸Ð½Ð¸Ð¼Ð°Ð»ÑŒÐ½Ñ‹Ð¼ значением. + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ nullif(X,Y) возвращает первый аргумент еÑли аргументы различны либо NULL еÑли они одинаковы. + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ printf(FORMAT,...) работает так же как printf() из Ñтандартной библиотеки Ñзыка Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¡Ð¸. + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ quote(X) возвращает измененную Ñтроку X, которую можно иÑпользовать в SQL выражениÑÑ…. + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ random() возвращает пÑевдо Ñлучайное целочиÑленное значение из диапазона от-9223372036854775808 до +9223372036854775807. + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ randomblob(N) возвращает N-байтный BLOB, Ñодержащий пÑевдо Ñлучайные байты. + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ replace(X,Y,Z) возвращает новую Ñтроку на оÑнове Ñтроки X, заменой вÑех подÑтрок Y на Z. + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ round(X) округлÑет X до целого значениÑ. + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ round(X,Y) округлÑет X до Y чиÑел поÑле запÑтой Ñправа. + + + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X) удалÑет Ñимволы пробела Ñправа Ñтроки X. - - Compact Database - Уплотнить базу данных + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ rtrim(X,Y) возвращает новую Ñтроку путем ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¸Ð· Ñтроки X Ñправа любого Ñимвола из Ñтроки Y. - - Compact the database file, removing space wasted by deleted records - Уплотнить базу данных, удалÑÑ Ð¿Ñ€Ð¾ÑтранÑтво, занимаемое удалёнными запиÑÑми + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ soundex(X) возвращает копию Ñтроки X, кодированную в формате soundex. - - - Compact the database file, removing space wasted by deleted records. - Уплотнить базу данных, удалÑÑ Ð¿Ñ€Ð¾ÑтранÑтво, занимаемое удалёнными запиÑÑми. + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) substr(X,Y) возвращает подÑтроку из Ñтроки X, Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ Y-го Ñимвола. - - E&xit - &Выход + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ substr(X,Y,Z) возвращает подÑтроку из Ñтроки X, Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ Y-го Ñимвола, длинной Z-Ñимволов. - - Ctrl+Q - Ctrl+Q + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ total_changes() возвращает количеÑтво Ñтрок измененных Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ INSERT, UPDATE или DELETE, Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ Ñ‚Ð¾Ð³Ð¾ момента как текущее подключение к базе данных было открыто. - - Database from SQL file... - База данных из файла SQL... + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) удалÑет пробелы Ñ Ð¾Ð±Ð¾Ð¸Ñ… Ñторон Ñтроки X. - - Import data from an .sql dump text file into a new or existing database. - Импортировать данные из текÑтового файла sql в новую или ÑущеÑтвующую базу данных. + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ trim(X,Y) Ñоздает новую Ñтроку из X, путем ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñ Ð¾Ð±Ð¾Ð¸Ñ… концов Ñимволов, которые приÑутÑтвуют в Ñтроке Y. - - This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. - Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет импортировать данные из текÑтового файла sql в новую или ÑущеÑтвующую базу данных. Файл SQL может быть Ñоздан на большинÑтве движков баз данных, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ MySQL и PostgreSQL. + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ typeof(X) возвращает Ñтроку Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼ данных Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ X. - - Table from CSV file... - Таблицy из файла CSV... + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ unicode(X) возвращает чиÑловое значение UNICODE кода Ñимвола. - - Open a wizard that lets you import data from a comma separated text file into a database table. - Открыть маÑтер, который позволÑет импортировать данные из файла CSV в таблицу базы данных. + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ upper(X) возвращает копию Ñтроки X, в которой Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ASCII Ñимвола региÑтр будет преобразован из нижнего в верхний. - - Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. - Открыть маÑтер, который позволÑет импортировать данные из файла CSV в таблицу базы данных. Файлы CSV могут быть Ñозданы в большинÑтве приложений баз данных и Ñлектронных таблиц. + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ zeroblob(N) возвращает BLOB размером N байт Ñо значениÑми 0x00. - - Database to SQL file... - Базу данных в файл SQL... + + + + + (timestring,modifier,modifier,...) + - - Export a database to a .sql dump text file. - ЭкÑпортировать базу данных в текÑтовый файл .sql. + + (format,timestring,modifier,modifier,...) + - - This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. - Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет ÑкÑпортировать базу данных в текÑтовый файл .sql. Файлы SQL Ñодержат вÑе данные, необходимые Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð±Ð°Ð·Ñ‹ данных в большиÑтве движков баз данных, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ MySQL и PostgreSQL. + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ avg() возвращает Ñреднее значение Ð´Ð»Ñ Ð²Ñех не равных NULL значений группы. - - Export a database table as a comma separated text file. - ЭкÑпортировать таблицу базы данных как CSV текÑтовый файл. + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ count(X) возвращает количеÑтво Ñтрок, в которых X не равно NULL в группе. - - Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. - ЭкÑпортировать таблицу базы данных как CSV текÑтовый файл, готовый Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² другие базы данных или Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñлектронных таблиц. + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ group_concat() возвращает Ñтроку из вÑех значений X не равных NULL. - - Create Table... - Создать таблицу... + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ group_concat() возвращает Ñтроку из вÑех значений X не равных NULL. Y - разделитель между значениÑми X. - - Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database - Открыть маÑтер ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†, где возможно определить Ð¸Ð¼Ñ Ð¸ Ð¿Ð¾Ð»Ñ Ð´Ð»Ñ Ð½Ð¾Ð²Ð¾Ð¹ таблиы в базе данных + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) ÐÐ³Ñ€ÐµÐ³Ð°Ñ‚Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ max() возвращает макÑимальное значение Ð´Ð»Ñ X. - - Delete Table... - Удалить таблицу... + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) ÐÐ³Ñ€ÐµÐ³Ð°Ñ‚Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ min() возвращает минимальное значение Ð´Ð»Ñ X. - - Open the Delete Table wizard, where you can select a database table to be dropped. - Открыть маÑтер ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹, где можно выбрать таблицу базы данных Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ. + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) Ðгрегатные функции sum() и total() возвращают Ñумму вÑех не NULL значений Ð´Ð»Ñ X. - - Modify Table... - Изменить таблицу... + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () ЧиÑло Ñтрок в текущем разделе. Строки нумеруютÑÑ Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ 1 в порÑдке, определенном выражением ORDER BY, или иначе в произвольном порÑдке. - - Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields form a table, as well as modify field names and types. - Открыть маÑтер Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹, где возможно переименовать ÑущеÑтвующую таблиц. Можно добавить или удалить Ð¿Ð¾Ð»Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ‹, так же изменÑть имена полей и типы. + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ row_number() возвращает номер первой Ñтроки в каждой группе - ранг текущей Ñтроки Ñ Ñ€Ð°Ð·Ñ€Ñ‹Ð²Ð°Ð¼Ð¸. ЕÑли не ÑущеÑтвует Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ORDER BY, вÑе Ñтроки ÑчитаютÑÑ Ð¾Ð´Ð½Ð¾Ñ€Ð°Ð½Ð³Ð¾Ð²Ñ‹Ð¼Ð¸, и Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ñегда возвращает 1. - - Create Index... - Создать индекÑ... + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () ЧиÑло одноранговой группы текущей Ñтроки в Ñвоем разделе - ранг текущей Ñтроки без пробелов. Разделы нумеруютÑÑ, Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ 1 в порÑдке, определенном выражением ORDER BY в определении окна. ЕÑли не ÑущеÑтвует Ð¿Ñ€ÐµÐ´Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ORDER BY, вÑе Ñтроки ÑчитаютÑÑ Ð¾Ð´Ð½Ð¾Ñ€Ð°Ð½Ð³Ð¾Ð²Ñ‹Ð¼Ð¸, и Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ñегда возвращает 1. - - Open the Create Index wizard, where it is possible to define a new index on an existing database table. - Открыть маÑтер ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸Ð½Ñ‚ÐµÐºÑа, в котором можно определить новый Ð¸Ð½Ð´ÐµÐºÑ Ð´Ð»Ñ ÑущеÑтвующей таблиц базы данных. + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () ÐеÑÐ¼Ð¾Ñ‚Ñ€Ñ Ð½Ð° имÑ, Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ñегда возвращает значение между 0.0 и 1.0, равное (rank-1) / (partition-rows-1), где rank - Ñто значение, возвращаемое вÑтроенной функцией window rank () rows - Ñто общее количеÑтво Ñтрок в разделе. ЕÑли раздел Ñодержит только одну Ñтроку, Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‰Ð°ÐµÑ‚ 0.0. - - &Preferences... - &ÐаÑтройки... + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () КумулÑтивное раÑпределение. РаÑÑчитываетÑÑ ÐºÐ°Ðº номер-Ñтроки / Ñтроки-раздела, где номер-Ñтроки - Ñто значение, возвращаемое row_number() Ð´Ð»Ñ Ð¿Ð¾Ñледнего однорангового узла в группе, а Ñтроки-раздела- количеÑтво Ñтрок в разделе. - - - Open the preferences window. - Открыть окно наÑтроек. + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) Ðргумент N обрабатываетÑÑ ÐºÐ°Ðº целое чиÑло. Эта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð´ÐµÐ»Ð¸Ñ‚ раздел на N групп как можно более равномерно и назначает целое чиÑло от 1 до N каждой группе в порÑдке, определенном выражением ORDER BY, или в произвольном порÑдке, при его отÑутÑтвии. При необходимоÑти Ñначала поÑвлÑÑŽÑ‚ÑÑ Ð±Ð¾Ð»ÑŒÑˆÐ¸Ðµ группы. Эта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‰Ð°ÐµÑ‚ целочиÑленное значение, приÑвоенное группе, в которой находитÑÑ Ñ‚ÐµÐºÑƒÑ‰Ð°Ñ Ñтрока. - - &DB Toolbar - &Панель инÑтрументов БД + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) Возвращает результат вычиÑÐ»ÐµÐ½Ð¸Ñ Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ expr в предыдущей Ñтроке раздела. Или, еÑли нет предыдущей Ñтроки (поÑкольку Ñ‚ÐµÐºÑƒÑ‰Ð°Ñ Ñтрока ÑвлÑетÑÑ Ð¿ÐµÑ€Ð²Ð¾Ð¹), NULL. - - Shows or hides the Database toolbar. - Показать или Ñкрыть панель инÑтрументов База данных. + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr, offset) ЕÑли аргумент offset указан, то он должен быть неотрицательным целым чиÑлом. Ð’ Ñтом Ñлучае возвращаемое значение ÑвлÑетÑÑ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ð¾Ð¼ вычиÑÐ»ÐµÐ½Ð¸Ñ expr в Ñтроках ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ñтрок до текущей Ñтроки в разделе. ЕÑли Ñмещение равно 0, то expr вычиÑлÑетÑÑ Ð¾Ñ‚Ð½Ð¾Ñительно текущей Ñтроки. ЕÑли перед текущей Ñтрокой нет Ñтрок ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ñтрок, возвращаетÑÑ NULL. - - What's This? - Что Ñто такое? + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr, offset, default) ЕÑли задано значение по умолчанию, оно возвращаетÑÑ Ð²Ð¼ÐµÑто NULL, еÑли Ñтрока, Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸Ñ†Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ÑмещениÑ, не ÑущеÑтвует. - - Shift+F1 - Shift+F1 + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) Возвращает результат вычиÑÐ»ÐµÐ½Ð¸Ñ Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ expr в Ñледующей Ñтроке раздела. Или, еÑли нет Ñледующей Ñтроки (поÑкольку поÑледнÑÑ Ñтрока ÑвлÑетÑÑ Ð¿Ð¾Ñледней), NULL. - - &About... - О &программе... + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr, offset) ЕÑли аргумент offset указан, то он должен быть неотрицательным целым чиÑлом. Ð’ Ñтом Ñлучае возвращаемое значение ÑвлÑетÑÑ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ð¾Ð¼ вычиÑÐ»ÐµÐ½Ð¸Ñ expr в Ñтроках ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ñтрок поÑле текущей Ñтроки в разделе. ЕÑли Ñмещение равно 0, то expr вычиÑлÑетÑÑ Ð¾Ñ‚Ð½Ð¾Ñительно текущей Ñтроки. ЕÑли поÑле текущей Ñтроки нет Ñтрок ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ñтроки, возвращаетÑÑ NULL. - - &Recently opened - &Ðедавно открываемые + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) Эта вÑÑ‚Ñ€Ð¾ÐµÐ½Ð½Ð°Ñ ÐžÐºÐ¾Ð½Ð½Ð°Ñ Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ñ‹Ñ‡Ð¸ÑлÑет Оконный Кадр Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ Ñтроки так же, как Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ ÐžÐºÐ½Ð° агрегата. Она возвращает значение Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ expr, оцениваемое по отношению к первой Ñтроке в оконном фрейме Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ Ñтроки. - - Open &tab - Открыть &вкладку + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) Эта вÑÑ‚Ñ€Ð¾ÐµÐ½Ð½Ð°Ñ ÐžÐºÐ¾Ð½Ð½Ð°Ñ Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ñ‹Ñ‡Ð¸ÑлÑет Оконный Кадр Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ Ñтроки так же, как Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ ÐžÐºÐ½Ð° агрегата. Она возвращает значение Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ expr, оцениваемое по отношению к поÑледней Ñтроке в оконном фрейме Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ Ñтроки. + (expr) Эта вÑÑ‚Ñ€Ð¾ÐµÐ½Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾ÐºÐ½Ð° вычиÑлÑет оконный кадр Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ Ñтроки так же, как Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾ÐºÐ½Ð° агрегата. Он возвращает значение expr, оцениваемое по поÑледней Ñтроке в оконном фрейме Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ Ñтроки. - - Ctrl+T - Ctrl+T + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr, N) Эта вÑÑ‚Ñ€Ð¾ÐµÐ½Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾ÐºÐ½Ð° вычиÑлÑет оконный фрейм Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ Ñтроки так же, как Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾ÐºÐ½Ð° агрегата. Она возвращает значение Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ expr, оцениваемое по Ñтроке N оконного фрейма. Строки нумеруютÑÑ Ð² рамке окна, Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ 1 в порÑдке, определенном выражением ORDER BY, еÑли оно приÑутÑтвует, или в произвольном порÑдке в противном Ñлучае. ЕÑли в разделе нет N-й Ñтроки, возвращаетÑÑ NULL. - - &Execute SQL - Ð’&ыполнить код SQL + + (X) Return the arccosine of X. The result is in radians. + (X) Возвращает арккоÑÐ¸Ð½ÑƒÑ X. Результат выражаетÑÑ Ð² радианах. - - Execute SQL [F5, Ctrl+Return] - Выполнить код SQL [F5, Ctrl+Return] + + (X) Return the hyperbolic arccosine of X. + (X) Возвращает гиперболичеÑкий арккоÑÐ¸Ð½ÑƒÑ X. - - Open SQL file - Открыть файл SQL + + (X) Return the arcsine of X. The result is in radians. + (X) Возвращает аркÑÐ¸Ð½ÑƒÑ Ñ‡Ð¸Ñла X. Результат выражаетÑÑ Ð² радианах. - - - - Save SQL file - Сохранить файл SQL + + (X) Return the hyperbolic arcsine of X. + (X) Возвращает гиперболичеÑкий аркÑÐ¸Ð½ÑƒÑ X. - - Load extension - Загрузить раÑширение + + (X) Return the arctangent of X. The result is in radians. + (X) Возвращает Ð°Ñ€ÐºÑ‚Ð°Ð½Ð³ÐµÐ½Ñ Ñ‡Ð¸Ñла X. Результат выражаетÑÑ Ð² радианах. - - Execute current line - Выполнить текущую Ñтроку + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + (X,Y) Возвращает Ð°Ñ€ÐºÑ‚Ð°Ð½Ð³ÐµÐ½Ñ Y/X. Результат в радианах. Результат помещаетÑÑ Ð² правильный квадрант в завиÑимоÑти от знаков X и Y. - - Execute current line [Ctrl+E] - Выполнить текущую Ñтроку [Ctrl+E] + + (X) Return the hyperbolic arctangent of X. + (X) Возвращает гиперболичеÑкий Ð°Ñ€ÐºÑ‚Ð°Ð½Ð³ÐµÐ½Ñ X. - - Ctrl+E - Ctrl+E + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + (X) Возвращает первое предÑтавимое целое значение, большее или равное X. Ð”Ð»Ñ Ð¿Ð¾Ð»Ð¾Ð¶Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ñ… значений X Ñта процедура округлÑет от нулÑ. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ñ†Ð°Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ñ… значений X Ñта процедура округлÑет в Ñторону нулÑ. - - Export as CSV file - ЭкÑпортировать в файл CSV + + (X) Return the cosine of X. X is in radians. + (X) Возвращает коÑÐ¸Ð½ÑƒÑ Ñ‡Ð¸Ñла X. X измерÑетÑÑ Ð² радианах. - - Export table as comma separated values file - ЭкÑпортировать таблицу как CSV файл + + (X) Return the hyperbolic cosine of X. + (X) Возвращает гиперболичеÑкий коÑÐ¸Ð½ÑƒÑ X. - - &Wiki... - Ð’&ики... + + (X) Convert value X from radians into degrees. + (X) Преобразует значение X из радиан в градуÑÑ‹. - - Bug &report... - &Отчёт об ошибке... + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + (X) ВычиÑлÑет e (чиÑло Эйлера, приблизительно 2,71828182845905), возведенное в Ñтепень X. - - Web&site... - &Веб-Ñайт... + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + (X) Возвращает первое предÑтавимое целое чиÑло, меньшее или равное X. Ð”Ð»Ñ Ð¿Ð¾Ð»Ð¾Ð¶Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ñ… чиÑел Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾ÐºÑ€ÑƒÐ³Ð»Ñет в Ñторону нулÑ. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ñ†Ð°Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ñ… чиÑел Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾ÐºÑ€ÑƒÐ³Ð»Ñет от нулÑ. - - Save Project - Сохранить проект + + (X) Return the natural logarithm of X. + (X) Возвращает натуральный логарифм X. - - - Save the current session to a file - Сохранить текущее ÑоÑтоÑние в файл + + (B,X) Return the base-B logarithm of X. + (B,X) Возвращает логарифм X по оÑнованию B. - - Open Project - Открыть проект + + + (X) Return the base-10 logarithm for X. + (X) Возвращает логарифм по оÑнованию 10 Ð´Ð»Ñ X. - - - Load a working session from a file - Загрузить рабочее ÑоÑтоÑние из файла + + (X) Return the logarithm base-2 for the number X. + (X) Возвращает логарифм по оÑнованию 2 Ð´Ð»Ñ Ñ‡Ð¸Ñла X. - - Copy Create statement - Копировать CREATE выражение + + (X,Y) Return the remainder after dividing X by Y. + (X,Y) Возвращает оÑтаток поÑле Ð´ÐµÐ»ÐµÐ½Ð¸Ñ X на Y. - - Copy the CREATE statement of the item to the clipboard - Копировать CREATE выражение Ñлемента в буффер обмена + + () Return an approximation for Ï€. + () Возвращает приближенное значение Ð´Ð»Ñ Ï€. - - Ctrl+Return - Ctrl+Return + + + (X,Y) Compute X raised to the power Y. + (X,Y) ВычиÑлить X, возведенное в Ñтепень Y. - - Ctrl+L - Ctrl+L + + (X) Convert X from degrees into radians. + (X) Преобразовать X из градуÑов в радианы. - - Ctrl+P - Ctrl+P + + (X) Return the sine of X. X is in radians. + (X) Возвращает ÑÐ¸Ð½ÑƒÑ Ñ‡Ð¸Ñла X. X измерÑетÑÑ Ð² радианах. - - Ctrl+D - + + (X) Return the hyperbolic sine of X. + (X) Возвращает гиперболичеÑкий ÑÐ¸Ð½ÑƒÑ X. - - Ctrl+I - + + (X) Return the square root of X. NULL is returned if X is negative. + (X) Возвращает квадратный корень из X. ВозвращаетÑÑ NULL, еÑли X отрицательно. - - Database encoding - Кодировка базы данных + + (X) Return the tangent of X. X is in radians. + (X) Возвращает Ñ‚Ð°Ð½Ð³ÐµÐ½Ñ Ñ‡Ð¸Ñла X. X измерÑетÑÑ Ð² радианах. - - Database is encrypted using SQLCipher - База данных зашифрована Ñ Ð¸Ñпользованием SQLCipher + + (X) Return the hyperbolic tangent of X. + (X) Возвращает гиперболичеÑкий Ñ‚Ð°Ð½Ð³ÐµÐ½Ñ X. - - - Choose a database file - Выбрать файл базы данных + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + (X) Возвращает предÑтавимое целое чиÑло между X и 0 (включительно), которое находитÑÑ Ð´Ð°Ð»ÑŒÑˆÐµ вÑего от нулÑ. Или, другими Ñловами, возвращает целую чаÑть X, округлÑÑ ÐµÐµ в Ñторону нулÑ. + + + SqliteTableModel - - SQLite database files (*.db *.sqlite *.sqlite3 *.db3);;All files (*) - Файлы SQLite баз данных (*.db *.sqlite *.sqlite3 *.db3);;Ð’Ñе файлы (*) + + reading rows + читаем Ñтроки - - - - - Choose a filename to save under - Выбрать имÑ, под которым Ñохранить данные + + loading... + загрузка... - - Error adding record: - - Ошибка Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñи: + + References %1(%2) +Hold %3Shift and click to jump there + СÑылаетÑÑ Ð½Ð° %1(%2) +Ðажмите %3Shift и клик чтобы перемеÑтитьÑÑ Ñ‚ÑƒÐ´Ð° - - Error deleting record: + + Error changing data: %1 - Ошибка ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñи: %1 + Ошибка Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ…: +%1 - - Please select a record first - Сначала выберите запиÑÑŒ + + retrieving list of columns + получаем ÑпиÑок колонок - - %1 - %2 of %3 - %1 - %2 из %3 + + Fetching data... + Подгружаем данные... - - - There is no database opened. Please open or create a new database file. - Ðет открытой базы данных. Откройте или Ñоздайте файл новой базы данных. + + + Cancel + Отменить + + + TableBrowser - - Are you sure you want to delete the %1 '%2'? -All data associated with the %1 will be lost. - Хотите удалить %1 '%2'? -Ð’Ñе данные, ÑвÑзанные Ñ %1, будут потерÑны. + + Browse Data + ПроÑмотр данных - - Error: could not delete the %1. Message from database engine: -%2 - Ошибка: невозмножно удалить %1. Сообщение из движка базы данных: %2 + + &Table: + &Таблица: - - There is no database opened. - Ðет открытой базы данных. + + Select a table to browse data + Выберите таблицу Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра данных - - %1 Rows returned from: %3 (took %2ms) - %1 Строки возвращены из: %3 (занÑло %2мÑ) + + Use this list to select a table to be displayed in the database view + ИÑпользуйте Ñтот ÑпиÑок, чтобы выбрать таблицу, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° быть отображена в предÑтавлении базы данных - - A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. - Вышла Ð½Ð¾Ð²Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ ÐžÐ±Ð¾Ð·Ñ€ÐµÐ²Ð°Ñ‚ÐµÐ»Ñ Ð´Ð»Ñ SQLite (%1.%2.%3).<br/><br/>Она доÑтупна Ð´Ð»Ñ ÑÐºÐ°Ñ‡Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ адреÑу <a href='%4'>%4</a>. + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + Это предÑтавление таблицы БД. Ð’Ñ‹ можете выполнить Ñледующие дейÑтвиÑ: + - Ðачните пиÑать Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ, Ð²Ð²ÐµÐ´Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ðµ. + - Дважды щелкните любую запиÑÑŒ, чтобы отредактировать ее Ñодержимое в окне редактора Ñчеек. + - Alt + Del Ð´Ð»Ñ Ð¾Ð±Ð½ÑƒÐ»ÐµÐ½Ð¸Ñ Ñодержимого Ñчейки в NULL. + - Ctrl + " Ð´Ð»Ñ Ð´ÑƒÐ±Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ запиÑи. + - Ctrl + ' Ð´Ð»Ñ ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¸Ð· Ñчейки выше. + - Стандартные операции выбора и копированиÑ/вÑтавки. - - - DB Browser for SQLite project file (*.sqbpro) - Файл проекта ÐžÐ±Ð¾Ð·Ñ€ÐµÐ²Ð°Ñ‚ÐµÐ»Ñ Ð´Ð»Ñ SQLite (*.sqbpro) + + Text pattern to find considering the checks in this frame + Шаблон Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка, ÑƒÑ‡Ð¸Ñ‚Ñ‹Ð²Ð°Ñ Ð²Ñе проверки - - Error executing query: %1 - Ошибка Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа: %1 + + Find in table + ПоиÑк в таблице - - Query executed successfully: %1 (took %2ms) - Ð—Ð°Ð¿Ñ€Ð¾Ñ ÑƒÑпешно выполнен: %1 (занÑло %2мÑ) + + Find previous match [Shift+F3] + Ðайти предыдущее Ñовпадение [Shift+F3] - - Choose a text file - Выбрать текÑтовый файл + + Find previous match with wrapping + Ðайти предыдущее Ñовпадение, закольцевав поиÑк - - Text files(*.csv *.txt);;All files(*) - ТекÑтовые файлы(*.csv *.txt);;Ð’Ñе файлы(*) + + Shift+F3 + Shift+F3 - - Import completed - Импорт завершён + + Find next match [Enter, F3] + Ðайти Ñледующее Ñовпадение [Enter, F3] - - Are you sure you want to undo all changes made to the database file '%1' since the last save? - Отменить вÑе изменениÑ, Ñделанные в файле базы данных '%1' поÑле поÑледнего ÑохранениÑ? + + Find next match with wrapping + Ðайти Ñледующее Ñовпадение, закольцевав поиÑк - - Choose a file to import - Выберать файл Ð´Ð»Ñ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð° + + F3 + F3 - - - - Text files(*.sql *.txt);;All files(*) - ТекÑтовые файлы(*.sql *.txt);;Ð’Ñе файлы(*) + + The found pattern must match in letter case + У шаблона должен Ñовпадать региÑтр - - Do you want to create a new database file to hold the imported data? -If you answer no we will attempt to import the data in the SQL file to the current database. - Создать новый файл базы данных, чтобы Ñохранить импортированные данные? -ЕÑли ответить Ðет, будет выполнена попытка импортировать данные файла SQL в текущую базу данных. + + Case Sensitive + Учитывать региÑтр - - File %1 already exists. Please choose a different name. - Файл %1 уже ÑущеÑтвует. Выберите другое имÑ. + + The found pattern must be a whole word + Шаблон должен быть целым Ñловом - - Error importing data: %1 - Ошибка Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ…: %1 + + Whole Cell + Ячейка целиком - - Import completed. - Импорт завершён. + + Interpret search pattern as a regular expression + Интерпретировать шаблон поиÑка как регулÑрное выражение - - Delete View - Удалить предÑтавление + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>При проверке шаблон Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка интерпретируетÑÑ ÐºÐ°Ðº регулÑрное выражение UNIX. <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Узнать больше о РегулÑрных выражениÑÑ… на Wikibooks.org</a>.</p></body></html> - - Delete Trigger - Удалить триггер + + Regular Expression + РегулÑрное выражение - - Delete Index - Удалить Ð¸Ð½Ð´ÐµÐºÑ + + + Close Find Bar + Закрыть панель поиÑка - - - Delete Table - Удалить таблицу + + Text to replace with + Замена текÑта - - &%1 %2 - &%1 %2 + + Replace with + Заменить на - - Setting PRAGMA values will commit your current transaction. -Are you sure? - УÑтановка значений PRAGMA завершит текущую транзакцию. УÑтановить значениÑ? + + Replace next match + Заменить Ñледуещее Ñовпадение - - Select SQL file to open - Выбрать файл SQL Ð´Ð»Ñ Ð¾ÐºÑ‚Ñ€Ñ‹Ñ‚Ð¸Ñ + + + Replace + Заменить - - Select file name - Выбрать Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° + + Replace all matches + Заменить вÑе ÑÐ¾Ð²Ð¿Ð°Ð´ÐµÐ½Ð¸Ñ - - Select extension file - Выбрать раÑширение файла + + Replace all + Заменить вÑе - - Extensions(*.so *.dll);;All files(*) - РаÑширениÑ(*.so *.dll);;Ð’Ñе файлы(*) + + Export to &JSON + ЭкÑпорт в JSON - - Extension successfully loaded. - РаÑширение уÑпешно загружено. + + + Export the filtered data to JSON + ЭкÑпортировать отфильтрованные данные в JSON - - - Error loading extension: %1 - Ошибка загрузки раÑширениÑ: %1 + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + Эта кнопка ÑкÑпортирует данные проÑматриваемой таблицы в том виде, в котором они отображаютÑÑ Ð² данный момент (поÑле фильтров, форматов Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¸ Ñтолбца порÑдка), в виде файла JSON. - - Don't show again - Ðе показывать Ñнова + + Copy column name + Копировать Ð¸Ð¼Ñ Ñтолбца - - New version available. - ДоÑтупна Ð½Ð¾Ð²Ð°Ñ Ð²ÐµÑ€ÑиÑ. + + Copy the database table column name to your clipboard + Копировать Ð¸Ð¼Ñ Ñтолбца таблицы БД в буфер обмена - - Choose a axis color - Выбрать цвет оÑей + + New Data Browser + ÐÐ¾Ð²Ð°Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ° - - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Ð’Ñе файлы(*) + + + Add a new docked Data Browser + Открыть новую вкладку Ð¾Ð±Ð¾Ð·Ñ€ÐµÐ²Ð°Ñ‚ÐµÐ»Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… - - Choose a file to open - Выбрать файл Ð´Ð»Ñ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ð¸Ñ + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + Эта кнопка добавлÑет новую вкладку проÑмотрщика данных. - - Invalid file format. - Ошибочный формат файла. + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>Прокрутить к началу</p></body></html> - - - PreferencesDialog - - Preferences - ÐаÑтройки + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>Ðажатие Ñтой кнопки переводит к началу в таблице выше.</p></body></html> - - &Database - &База данных + + |< + - - Database &encoding - &Кодировка базы данных + + Scroll one page upwards + Страница вверх - - Open databases with foreign keys enabled. - Открывать базы данных Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ‹Ð¼Ð¸ внешними ключами. + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>Ðажатие Ñтой кнопки перемещает по запиÑÑм на одну Ñтраницу вверх.</p></body></html> - - &Foreign keys - &Внешние ключи + + < + < - - - enabled - включены + + 0 - 0 of 0 + 0 - 0 из 0 - - Default &location - &РаÑположение -по умолчанию + + Scroll one page downwards + Ðа Ñтраницу вниз - - ... - ... + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>Ðажатие Ñтой кнопки перемещает на одну Ñтраницу запиÑей вниз.</p></body></html> - - &General - &Общие + + > + > - - Remember last location - Запоминать поÑледнюю директорию + + Scroll to the end + Прокрутить к концу - - Always use this location - Ð’Ñегда открывать указанную + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>Ðажатие Ñтой кнопки позволÑет перейти к концу таблицы.</p></body></html> - - Remember last location for session only - Запоминать поÑледнюю директорию только Ð´Ð»Ñ ÑеÑÑий + + >| + - - Lan&guage - &Язык + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>Ðажмите здеÑÑŒ, чтобы перейти к указанной запиÑи</p></body></html> - - Automatic &updates - &Следить за обновлениÑми + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>Эта кнопка иÑпользуетÑÑ, чтобы перемеÑтитьÑÑ Ðº запиÑи, номер которой указан в облаÑти Перейти к</p></body></html> - - Remove line breaks in schema view - Удалить переводы Ñтроки в Ñхеме данных + + Go to: + Перейти к: - - &Prefetch block size - Размер блока &упреждающей выборки + + Enter record number to browse + Введите номер запиÑи Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра - - Data &Browser - Обозреватель &данных + + Type a record number in this area and click the Go to: button to display the record in the database view + Ðапечатайте номер запиÑи в Ñтой облаÑти и нажмите кнопку Перейти к:, чтобы отобразить запиÑÑŒ в предÑтавлении базы данных - - NULL fields - NULL Ð¿Ð¾Ð»Ñ + + 1 + 1 - - Text &colour - Цвет &текÑта + + Show rowid column + Отображать колонку rowid - - &Text - &ТекÑÑ‚ + + Toggle the visibility of the rowid column + Переключить видимоÑть Ñтолбца rowid - - Bac&kground colour - Цвет &фона + + Unlock view editing + Разблокировать возможноÑть Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ - - &SQL - Р&едактор SQL + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + Разблокировать текущий вид Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ. Однако Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ð°Ð¼ понадобÑÑ‚ÑÑ ÑоответÑтвующие триггеры. - - Settings name - Ð˜Ð¼Ñ Ð½Ð°Ñтроек + + Edit display format + Изменить формат Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ - - Context - КонтекÑÑ‚ + + Edit the display format of the data in this column + Редактирование формата Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… из Ñтой колонки - - Colour - Цвет + + + New Record + Добавить запиÑÑŒ - - Bold - Жирный + + + Insert a new record in the current table + Ð’Ñтавить новую запиÑÑŒ в текущую таблицу - - Italic - КурÑив + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>Эта кнопка Ñоздает новую запиÑÑŒ в базе данных. Удерживайте кнопку мыши, чтобы открыть вÑплывающее меню различных параметров:</p><ul><li><span style=" font-weight:600;">ÐÐ¾Ð²Ð°Ñ Ð—Ð°Ð¿Ð¸ÑÑŒ</span>: вÑтавлÑет новую запиÑÑŒ Ñо значениÑми по умолчанию.</li><li><span style=" font-weight:600;">Ð’Ñтавить ЗначениÑ...</span>: открывает диалог Ð´Ð»Ñ Ð²Ð²Ð¾Ð´Ð° значений перед тем, как они будут вÑтавлены в БД. Это позволÑет вводить значениÑ, Ð½Ð°Ð·Ð½Ð°Ñ‡Ð°Ñ Ñ€Ð°Ð·Ð»Ð¸Ñ‡Ð½Ñ‹Ðµ ограничениÑ. Этот диалог также открываетÑÑ, еÑли <span style=" font-weight:600;">ÐÐ¾Ð²Ð°Ñ Ð—Ð°Ð¿Ð¸ÑÑŒ</span> Ð¾Ð¿Ñ†Ð¸Ñ Ð½Ðµ Ñрабатывает из-за Ñтих ограничений.</li></ul></body></html> - - Underline - Подчёркивание + + + Delete Record + Удалить запиÑÑŒ - - Keyword - Ключевое Ñлово + + Delete the current record + Удалить текущую запиÑÑŒ - - function - Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ + + + This button deletes the record or records currently selected in the table + Эта кнопка удалÑет запиÑÑŒ или запиÑи, выбранные в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð² таблице - - Function - Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ + + + Insert new record using default values in browsed table + Ð’ÑтавлÑет новую запиÑÑŒ, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию в проÑматриваемой таблице - - Table - Таблица + + Insert Values... + Ð’Ñтавить значениÑ... - - Comment - Комментарий + + + Open a dialog for inserting values in a new record + Открывает диалоговое окно Ð´Ð»Ñ Ð²Ñтавки значений в новую запиÑÑŒ - - Identifier - Идентификатор + + Export to &CSV + ЭкÑпортировать в &CSV - - String - Строка + + + Export the filtered data to CSV + ЭкÑпортировать отфильтрованные данные в CSV - - currentline - текущаÑÑтрока + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + Эта кнопка ÑкÑпортирует данные проÑматриваемой таблицы так как отображаетÑÑ (поÑле обработки фильтрами, форматами Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¸ Ñ‚.д.) в виде файла CSV. - - Current line - Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ñтрока + + Save as &view + Сохранить как &предÑтавление - - SQL &editor font size - Размер шрифта в &редакторе SQL + + + Save the current filter, sort column and display formats as a view + Сохранить текущие фильтры, Ñтолбцы Ñортировки и форматы Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð² виде предÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ - - SQL &log font size - Размер шрифта в &журнале SQL + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + Эта кнопка ÑохранÑет текущие наÑтройки проÑматриваемой таблицы (фильтры, форматы Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¸ Ñтолбец Ñортировки) в виде предÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ SQL, которое вы можете впоÑледÑтвии проÑмотреть или иÑпользовать в операторах SQL. - - Tab size: - Размер табулÑции: + + Save Table As... + Сохранить таблицу как... - - SQL editor &font - &Шрифт в редакторе SQL + + + Save the table as currently displayed + Сохранить таблицу так как ÑÐµÐ¹Ñ‡Ð°Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶Ð°ÐµÑ‚ÑÑ - - &Extensions - Р&аÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>Это вÑплывающее меню предоÑтавлÑет Ñледующие параметры, применÑемые к текущей проÑматриваемой и отфильтрованной таблице:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ЭкÑпортировать в виде CSV: данные проÑматриваемой таблицы ÑохранÑетÑÑ Ñ‚Ð°Ðº как отображаетÑÑ (поÑле Ð¿Ñ€Ð¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð¾Ð², форматов Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¸ порÑдка колонок) в CSV файл.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Сохранить как вид: Ñта Ð¾Ð¿Ñ†Ð¸Ñ ÑохранÑет наÑтройки текущей отображаемой таблицы (фильтры, форматы Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¸ порÑдок колонок) как SQL вид, который вы позже можете проÑматривать или иÑпользовать в SQL выражениÑÑ….</li></ul></body></html> - - Select extensions to load for every database: - Выберите раÑширениÑ, чтобы загружать их Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ базы данных: + + Hide column(s) + Скрыть колонку(и) - - Add extension - Добавить раÑширение + + Hide selected column(s) + Скрыть выбранные колонки - - Remove extension - Удалить раÑширение + + Show all columns + Показать вÑе колонки - - <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> - <html><head/><body><p>Обозреватель Ð´Ð»Ñ SQLite позволÑет иÑпользовать оператор REGEXP 'из коробки'. Ðо тем <br/>не менее, возможны неÑколько различных вариантов реализаций данного оператора и вы Ñвободны <br/>в выборе какую именно иÑпользовать. Можно отключить нашу реализацию и иÑпользовать другую - <br/>путем загрузки ÑоответÑвующего раÑширениÑ. Ð’ Ñтом Ñлучае требуетÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° приложениÑ.</p></body></html> + + Show all columns that were hidden + Показать вÑе колонки, которые были Ñкрыты - - Disable Regular Expression extension - Отключить раÑширение РегулÑрных Выражений + + + Set encoding + Кодировка - - Choose a directory - Выберать каталог + + Change the encoding of the text in the table cells + Изменение кодировки текÑта в данной таблице - - The language will change after you restart the application. - Язык будет применен поÑле перезапуÑка приложениÑ. + + Set encoding for all tables + УÑтановить кодировку Ð´Ð»Ñ Ð²Ñех таблиц - - Select extension file - Выберать файл раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ + + Change the default encoding assumed for all tables in the database + Изменить кодировку по умолчанию Ð´Ð»Ñ Ð²Ñех таблиц в базе данных - - Extensions(*.so *.dll);;All files(*) - РаÑширениÑ(*.so *.dll);;Ð’Ñе файлы(*) + + Clear Filters + ОчиÑтить фильтры - - - QObject - - Error importing data - Ошибка Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… + + Clear all filters + ОчиÑтить вÑе фильтры - - from record number %1 - Ñ Ð·Ð°Ð¿Ð¸Ñи номер %1 + + + This button clears all the filters set in the header input fields for the currently browsed table. + Эта кнопка очищает вÑе фильтры, уÑтановленные в полÑÑ… ввода заголовка Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ проÑматриваемой таблицы. - - . -%1 - + + Clear Sorting + Убрать Ñортировку - - Cancel - Отменить + + Reset the order of rows to the default + СброÑить порÑдок Ñтрок - - Decoding CSV file... - РаÑшифровка CSV файла... + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + Эта кнопка ÑбраÑывает Ñортировку Ñтолбцов в отображаемой таблице. - - Collation needed! Proceed? - Ðужно выполнить ÑопоÑтавление! Продолжить? + + Print + Печать - - A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. -If you choose to proceed, be aware bad things can happen to your database. -Create a backup! - Таблица в базе данных требует Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñпециальной функции ÑопоÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ '%1'. -ЕÑли вы продолжите, то возможна порча вашей базы данных. -Создайте резервную копию! + + Print currently browsed table data + Печатать отображаемую таблицу - - - SqlExecutionArea - - Form - Форма + + Print currently browsed table data. Print selection if more than one cell is selected. + Печать данных текущей таблицы. Печать выделениÑ, еÑли выбрано неÑколько Ñчеек. - - Results of the last executed statements - Результаты поÑледних выполненных операторов + + Ctrl+P + Ctrl+P - - This field shows the results and status codes of the last executed statements. - Это поле показывает результаты и коды ÑтатуÑов поÑледних выполненных операторов. + + Refresh + Обновить - - Export to &CSV - ЭкÑпортировать в &CSV + + Refresh the data in the selected table + Обновить данные в выбранной таблице - - Save as &view - Сохранить как &предÑтавление + + This button refreshes the data in the currently selected table. + Эта кнопка обновлÑет данные выбранной в данный момент таблицы. - - Save as view - Сохранить как предÑтавление + + F5 + F5 - - Please specify the view name - Укажите Ð¸Ð¼Ñ Ð¿Ñ€ÐµÐ´ÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ + + Find in cells + Ðайти в Ñчейках - - There is already an object with that name. Please choose a different name. - Объект Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ñ‹Ð¼ именем уже ÑущеÑтвует. Выберите другое имÑ. + + Open the find tool bar which allows you to search for values in the table view below. + Открыть панель инÑтрументов поиÑка, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет иÑкать Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² предÑтавленной ниже таблице. - - View successfully created. - ПредÑтавление уÑпешно Ñоздано. + + + Bold + Жирный - - Error creating view: %1 - Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¿Ñ€ÐµÐ´ÑтавлениÑ: %1 + + Ctrl+B + Ctrl+B - - - SqlUiLexer - - (X) The abs(X) function returns the absolute value of the numeric argument X. - (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ abs(X) возвращает модуль чиÑла аргумента X. + + + Italic + КурÑив - - () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. - () Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ changes() возвращает количеÑтво Ñтрок в базе данных, которые были изменены, вÑтавлены или удалены поÑле удачного Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ INSERT, DELETE или UPDATE. + + + Underline + Подчёркнутый - - (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. - (X1,X2,...) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ char(X1,X2,...,XN) возвращает Ñтроку ÑоÑтавленную из Ñимволов, переданных в качеÑтве аргументов. + + Ctrl+U + Ctrl+U - - (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL - (X,Y,...) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ coalesce() возвращает копию первого аргумента не равного NULL иначе еÑли такого нет то возвращаетÑÑ NULL + + + Align Right + ВыровнÑть вправо - - (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". - (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ glob(X,Y) Ñквивалент выражению "Y GLOB X". + + + Align Left + ВыровнÑть влево - - (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. - (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ ifnull() возвращает копию первого аргумента не равного NULL иначе еÑли оба аргумента равны NULL то возвращает NULL. + + + Center Horizontally + Центрировать по горизонтали - - (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. - (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ instr(X,Y) возвращает количеÑтво Ñимволов, Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ в Ñтроке X найденна подÑтрока Y или 0 еÑли Ñ‚Ð°ÐºÐ¾Ð²Ð°Ñ Ð½Ðµ обнаружена. + + + Justify + По ширине - - (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. - (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ hex() интерпретирует аргумент как BLOB и возвращает Ñтроку в 16-ричной ÑиÑтеме ÑчиÑÐ»ÐµÐ½Ð¸Ñ Ñ Ñодержимым аргумента. + + + Edit Conditional Formats... + Изменить форматирование... - - () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. - () Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ last_insert_rowid() возвращает ROWID поÑледней вÑтавленной Ñтроки. + + Edit conditional formats for the current column + Изменить форматирование Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ³Ð¾ Ñтолбца - - (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. - (X) Ð”Ð»Ñ Ñтрокового Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ X, Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ length(X) возвращает количеÑтво Ñимволов (не байт) от начала Ñтроки до первого Ñимвола '\0'. + + Clear Format + ОчиÑтить форматирование - - (X,Y) The like() function is used to implement the "Y LIKE X" expression. - (X,Y) Ð¤ÑƒÐºÐ½Ñ†Ð¸Ñ like() Ñквивалент выражению "Y LIKE X". + + Clear All Formats + ОчиÑтить вÑе форматирование - - (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. - (X,Y,Z) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ like() Ñквивалент Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ "Y LIKE X ESCAPE Z". + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + ОчиÑтить фоматирование в выделенном - - (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. - (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ load_extension(X) загружает раÑширение SQLite из файла библиотеки динамичеÑкой компоновки X. + + + Font Color + Цвет шрифта - - (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. - (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ load_extension(X,Y) загружает раÑширение SQLite из файла библиотеки динамичеÑкой компоновки X, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ñ‚Ð¾Ñ‡ÐºÑƒ входа Y. + + + Background Color + Цвет фона - - (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. - (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ lower(X) возвращает копию Ñтроки X, в которой вÑе ACSII Ñимволы переведены в нижний региÑтр. + + Toggle Format Toolbar + Панель Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ - - (X) ltrim(X) removes spaces from the left side of X. - (X) ltrim(X) удалÑет Ñимволы пробелов Ñлева Ð´Ð»Ñ Ñтроки X. + + Show/hide format toolbar + Показать/Ñкрыть панель Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ - - (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. - (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ ltrim(X,Y) возвращает новую Ñтроку путем ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¸Ð· Ñтроки X Ñлева любого Ñимвола из Y. + + + This button shows or hides the formatting toolbar of the Data Browser + Эта кнопка показывает/Ñкрывает панель Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ - - (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. - (X,Y,...) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ max() возвращает аргумент Ñ Ð¼Ð°ÐºÑимальным значением, либо NULL еÑли хотÑбы один аргумент равен NULL. + + Select column + Выделить Ñтолбец - - (X,Y,...) The multi-argument min() function returns the argument with the minimum value. - (X,Y,...) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ min() возвращает аргумент Ñ Ð¼Ð¸Ð½Ð¸Ð¼Ð°Ð»ÑŒÐ½Ñ‹Ð¼ значением. + + Ctrl+Space + - - (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. - (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ nullif(X,Y) возвращает первый аргумент еÑли аргументы различны либо NULL еÑли они одинаковы. + + Replace text in cells + Замена текÑта в Ñчейках - - (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. - (FORMAT,...) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ printf(FORMAT,...) работает так же как printf() из Ñтандартной библиотеки Ñзыка Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¡Ð¸. + + Freeze columns + Заморозить Ñтолбец - - (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. - (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ quote(X) возвращает измененную Ñтроку X, которую можно иÑпользовать в SQL выражениÑÑ…. + + Make all columns from the first column up to this column not move when scrolling horizontally + Сделать так, чтобы вÑе Ñтолбцы, от первого Ñтолбца до Ñтого Ñтолбца, не перемещалиÑÑŒ при горизонтальной прокрутке - - () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. - () Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ random() возвращает пÑевдо Ñлучайное целочиÑленное значение из диапозона от-9223372036854775808 до +9223372036854775807. + + Filter in any column + Фильтр в Ñтолбцах - - (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. - (N) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ randomblob(N) возвращает N-байтный BLOB, Ñодержащий пÑевдо Ñлучайные байты. + + Ctrl+R + Ctrl+R - - - (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. - (X,Y,Z) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ replace(X,Y,Z) возвращает новую Ñтроку на оÑнове Ñтроки X, заменой вÑех подÑтрок Y на Z. + + + %n row(s) + + %n Ñтрока + %n Ñтроки + %n Ñтрок + - - - (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. - (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ round(X) округлÑет X до целого значениÑ. + + + , %n column(s) + + , %n Ñтолбец + , %n Ñтолбца + , %n Ñтолбцов + - - (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. - (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ round(X,Y) округлÑет X до Y чиÑел поÑле запÑтой Ñправа. + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . Сумма: %1; Среднее: %2; Мин: %3; МакÑ: %4 - - (X) rtrim(X) removes spaces from the right side of X. - (X) rtrim(X) удалÑет Ñимволы пробела Ñправа Ñтроки X. + + Conditional formats for "%1" + Форматирование Ð´Ð»Ñ "%1" - - (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. - (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ rtrim(X,Y) возвращает новую Ñтроку путем ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¸Ð· Ñтроки X Ñправа любого Ñимвола из Ñтроки Y. + + determining row count... + определÑем количеÑтво Ñтрок... - - (X) The soundex(X) function returns a string that is the soundex encoding of the string X. - (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ soundex(X) возвращает копию Ñтроки X, кодированную в формате soundex. + + %L1 - %L2 of >= %L3 + - - (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. - (X,Y) substr(X,Y) возвращает подÑтроку из Ñтроки X, Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ Y-го Ñимвола. + + %L1 - %L2 of %L3 + - - (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. - (X,Y,Z) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ substr(X,Y,Z) возвращает подÑтроку из Ñтроки X, Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ Y-го Ñимвола, длинной Z-Ñимволов. + + (clipped at %L1 rows) + (выбрано до %L1 Ñтрок) - - () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. - () Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ total_changes() возвращает количеÑтво Ñтрок измененных Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ INSERT, UPDATE или DELETE, Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ Ñ‚Ð¾Ð³Ð¾ момента как текущее подключение к базе данных было открыто. + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + ПожалуйÑта, введите пÑевдо-первичный ключ, чтобы разрешить редактирование в Ñтом предÑтавлении. Это должно быть Ð¸Ð¼Ñ ÑƒÐ½Ð¸ÐºÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ñтолбца в предÑтавлении. - - (X) trim(X) removes spaces from both ends of X. - (X) trim(X) удалÑет пробелы Ñ Ð¾Ð±Ð¾Ð¸Ñ… Ñторон Ñтроки X. + + Delete Records + Удалить запиÑи - - (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. - (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ trim(X,Y) Ñоздает новую Ñтроку из X, путем ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñ Ð¾Ð±Ð¾Ð¸Ñ… концов Ñимволов, которые приÑутÑвуют в Ñтроке Y. + + Duplicate records + Дублированные запиÑи - - (X) The typeof(X) function returns a string that indicates the datatype of the expression X. - (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ typeof(X) возвращает Ñтроку Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼ данных Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ X. + + Duplicate record + Дубликат запиÑи - - (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. - (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ unicode(X) возвращает чиÑловое значение UNICODE кода Ñимвола. + + Ctrl+" + Ctrl+" - - (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. - (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ upper(X) возвращает копию Ñтроки X, в которой Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ASCII Ñимвола региÑтр будет перобразован из нижнего в верхний. + + Adjust rows to contents + Подогнать по Ñодержимому - - (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. - (N) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ zeroblob(N) возвращает BLOB размером N байт Ñо значениÑми 0x00. + + Error deleting record: +%1 + Ошибка ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñи: %1 - - - - - (timestring,modifier,modifier,...) - + + Please select a record first + Сначала выберите запиÑÑŒ - - (format,timestring,modifier,modifier,...) - + + Please choose a new encoding for all tables. + ПожалуйÑта выберите новую кодировку Ð´Ð»Ñ Ð²Ñех таблиц. - - (X) The avg() function returns the average value of all non-NULL X within a group. - (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ avg() возвращает Ñреднее значение Ð´Ð»Ñ Ð²Ñех не равных NULL значений группы. + + Please choose a new encoding for this table. + ПожалуйÑта выберите новую кодировку Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ таблицы. - - (X) The count(X) function returns a count of the number of times that X is not NULL in a group. - (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ count(X) возвращает количеÑвто Ñтрок, в которых X не равно NULL в группе. + + %1 +Leave the field empty for using the database encoding. + %1 +ОÑтавьте Ñто поле пуÑтым еÑли хотите чтобы иÑпользовалаÑÑŒ кодировка по умолчанию. - - (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. - (X) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ group_concat() возвращает Ñтроку из вÑех значений X не равных NULL. + + This encoding is either not valid or not supported. + ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ ÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²ÐºÐ° либо она не поддерживаетÑÑ. - - (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. - (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ group_concat() возвращает Ñтроку из вÑех значений X не равных NULL. Y - разделитель между значениÑми X. + + %1 replacement(s) made. + %1 замен(а) произведено(а). + + + TableBrowserDock - - (X) The max() aggregate function returns the maximum value of all values in the group. - (X) ÐÐ³Ð³Ñ€ÐµÐ³Ð°Ñ‚Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ max() возвращает макÑимальное значение Ð´Ð»Ñ X. + + New Data Browser + ÐÐ¾Ð²Ð°Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ° Ð¾Ð±Ð¾Ð·Ñ€ÐµÐ²Ð°Ñ‚ÐµÐ»Ñ - - (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. - (X) ÐÐ³Ð³Ñ€ÐµÐ³Ð°Ñ‚Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ min() возвращает минимальное значение Ð´Ð»Ñ X. + + Rename Data Browser + Переименовать обозреватель данных - - - (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. - (X) Ðггрегатные функции sum() и total() возвращают Ñумму вÑех не NULL значений Ð´Ð»Ñ X. + + Close Data Browser + Закрыть обозреватель данных - - - SqliteTableModel - - Error changing data: -%1 - Ошибка Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ…: -%1 + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + Задайте новое Ð¸Ð¼Ñ Ð´Ð»Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ¸ SQL. ИÑпользуйте Ñимвол '&&', чтобы разрешить иÑпользование Ñледующего Ñимвола в качеÑтве ÑÐ¾Ñ‡ÐµÑ‚Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ. @@ -2811,13 +8032,13 @@ Create a backup! - Warning: Compacting the database will commit all changes you made. + Warning: Compacting the database will commit all of your changes. Предупреждение: Уплотнение базы данных зафикÑирует вÑе изменениÑ, которые были Ñделаны. - Please select the objects to compact: - Выберите объекты Ð´Ð»Ñ ÑƒÐ¿Ð»Ð¾Ñ‚Ð½ÐµÐ½Ð¸Ñ: + Please select the databases to co&mpact: + Выберите объекты Ð´Ð»Ñ &уплотнениÑ: diff --git a/src/translations/sqlb_sv.ts b/src/translations/sqlb_sv.ts new file mode 100644 index 000000000..65258f833 --- /dev/null +++ b/src/translations/sqlb_sv.ts @@ -0,0 +1,6273 @@ + + + + + AboutDialog + + About DB Browser for SQLite + Om DB Browser för SQLite + + + Version + Version + + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + + + + + AddRecordDialog + + Add New Record + + + + Enter values for the new record considering constraints. Fields in bold are mandatory. + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + + + + Name + Namn + + + Type + Typ + + + Value + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + + + + Auto-increment + + + + + Unique constraint + + + + + Check constraint: %1 + + + + + Foreign key: %1 + + + + + Default value: %1 + + + + + Error adding record. Message from database engine: + +%1 + + + + Are you sure you want to restore all the entered values to their defaults? + + + + + Application + + Invalid option/non-existent file: %1 + Felaktig parameter/icke existerande fil: %1 + + + Possible command line arguments: + Möjliga argument pÃ¥ kommandoraden: + + + The file %1 does not exist + Filen %1 finns inte + + + The user settings file location is replaced with the argument value instead of the environment variable value. + + + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + + + + Usage + + + + options + + + + database + + + + project + + + + csv-file + + + + Show command line options + + + + Exit application after running scripts + + + + file + + + + Execute this SQL file after opening the DB + + + + Import this CSV file into the passed DB or into a new DB + + + + table + + + + Open database in read-only mode + + + + settings_file + + + + Run application based on this settings file + + + + group + + + + settings + + + + value + + + + Run application with this setting temporarily set to value + + + + Run application saving this value for this setting + + + + Display the current version + + + + Open this SQLite database + + + + Open this project file (*.sqbpro) + + + + Import this CSV file into an in-memory database + + + + The %1 option requires an argument + + + + The -S/--settings option requires an argument. The option is ignored. + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + + + + SQLite Version + SQLite Version + + + SQLCipher Version %1 (based on SQLite %2) + + + + DB Browser for SQLite Version %1. + + + + Built for %1, running on %2 + + + + Qt Version %1 + + + + Browse this table, or use it as target of a data import + + + + Last commit hash when built: %1 + + + + + CipherDialog + + SQLCipher encryption + SQLCipher kryptering + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + Ange en nyckel för att kryptera databasen. +Notera att om du ändrar nÃ¥gon annan valbar inställning sÃ¥ behöver du Ã¥ter igen ange dem igen varje gÃ¥ng du öppnar databasen. +Lämna fältet för lösenord tomt för att avaktivera kryptering. +Krypteringsprocessen behvöer lite tid och se till att ha en backupkopia av din databas! Osparade förändringar appliceras innan modifiering av krypteringen sker. + + + &Password + &Lösenord + + + &Reenter password + Ange lösenord &igen + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + Ange nyckel som används för att kryptera databasen. +Om nÃ¥gon annan inställning ändrades för denna databas behöver du ange och justera även det. + + + Passphrase + + + + Raw key + + + + Encr&yption settings + + + + SQLCipher &3 defaults + + + + SQLCipher &4 defaults + + + + Custo&m + + + + Page si&ze + + + + &KDF iterations + + + + HMAC algorithm + + + + KDF algorithm + + + + Plaintext Header Size + + + + + ColumnDisplayFormatDialog + + Choose display format + + + + Display format + + + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + + + + Default + Förvald + + + Decimal number + + + + Exponent notation + + + + Hex blob + + + + Hex number + + + + Octal number + + + + Round number + + + + Apple NSDate to date + + + + Java epoch (milliseconds) to date + + + + .NET DateTime.Ticks to date + + + + Julian day to date + + + + Unix epoch to date + + + + Unix epoch to local time + + + + Windows DATE to date + + + + Date as dd/mm/yyyy + + + + Lower case + + + + Upper case + + + + Binary GUID to text + + + + Custom + + + + Custom display format must contain a function call applied to %1 + + + + Error in custom display format. Message from database engine: + +%1 + + + + Custom display format must return only one column but it returned %1. + + + + SpatiaLite Geometry to SVG + + + + WebKit / Chromium epoch to date + + + + WebKit / Chromium epoch to local time + + + + + CondFormatManager + + Conditional Format Manager + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + + + + Add new conditional format + + + + &Add + + + + Remove selected conditional format + + + + &Remove + + + + Move selected conditional format up + + + + Move &up + + + + Move selected conditional format down + + + + Move &down + + + + Foreground + + + + Text color + + + + Background + + + + Background color + + + + Font + + + + Size + + + + Bold + Fet + + + Italic + Kursiv + + + Underline + Understrykning + + + Alignment + + + + Condition + + + + Click to select color + + + + Are you sure you want to clear all the conditional formats of this field? + + + + + DBBrowserDB + + Action cancelled. + Aktivitet avbruten. + + + Please specify the database name under which you want to access the attached database + Ange det databasnamn med vilket du vill komma Ã¥t ansluten databas + + + Cancel + Avbryt + + + File not found. + Hittar inte fil. + + + Error setting pragma %1 to %2: %3 + Kunde inte sätta pragma %1 till %2: %3 + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + Kunde inte Ã¥terställa nÃ¥gra objekt som är associerade med denna tabell. Toligast är att nÃ¥gra kolumnnamn ändrats. Här är SQL-uttrycket som du kan behöva Ã¥tgärda och köra manuellt: + + + + + Exporting database to SQL file... + Exporterar databas till SQL-fil... + + + Do you want to save the changes made to the database file %1? + Vill du spara ändringarna som gjorts i databasfilen %1? + + + Executing SQL... + Utför SQL... + + + Invalid file format + + + + Do you really want to close this temporary database? All data will be lost. + + + + Database didn't close correctly, probably still busy + + + + Cannot open destination file: '%1' + + + + Cannot backup to file: '%1'. Message: %2 + + + + The database is currently busy: + + + + Do you want to abort that other operation? + + + + No database file opened + + + + Error in statement #%1: %2. +Aborting execution%3. + + + + and rolling back + + + + didn't receive any output from %1 + + + + could not execute command: %1 + + + + Cannot delete this object + + + + Cannot set data on this object + + + + A table with the name '%1' already exists in schema '%2'. + + + + No table with name '%1' exists in schema '%2'. + + + + Cannot find column %1. + + + + Creating savepoint failed. DB says: %1 + + + + Renaming the column failed. DB says: +%1 + + + + Releasing savepoint failed. DB says: %1 + + + + Creating new table failed. DB says: %1 + + + + Copying data to new table failed. DB says: +%1 + + + + Deleting old table failed. DB says: %1 + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + + + + could not get list of db objects: %1 + + + + could not get list of databases: %1 + + + + Error loading extension: %1 + Fel när tillägg skulle laddas: %1 + + + could not get column information + + + + Error loading built-in extension: %1 + + + + + DbStructureModel + + Name + Namn + + + Type + Typ + + + Triggers (%1) + Utlösare (%1) + + + Object + Objekt + + + Schema + Schema + + + Indices (%1) + Index (%1) + + + Tables (%1) + Tabeller (%1) + + + Views (%1) + Vyer (%1) + + + Database + + + + Browsables + + + + All + + + + Temporary + + + + + EditDialog + + Text + Text + + + Choose a filename to export data + Välj ett filnamn att exportera data till + + + Erases the contents of the cell + Tar bort innehÃ¥llet frÃ¥n cellen + + + Binary + Binär + + + Edit database cell + Redigera databascell + + + This area displays information about the data present in this database cell + Detta omrÃ¥de visar information om data som finns i denna databascell + + + Mode: + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + + + + RTL Text + + + + Image + + + + JSON + + + + XML + + + + Evaluation + + + + Automatically adjust the editor mode to the loaded data type + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + + + + Auto-switch + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + + + + Apply data to cell + + + + This button saves the changes performed in the cell editor to the database cell. + + + + Apply + + + + Print... + + + + Open preview dialog for printing displayed text + + + + Open preview dialog for printing the data currently stored in the cell + + + + Ctrl+P + + + + Copy Hex and ASCII + + + + Copy selected hexadecimal and ASCII columns to the clipboard + + + + Ctrl+Shift+C + + + + Autoformat + + + + Auto-format: pretty print on loading, compact on saving. + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + + + + &Export... + + + + Export to file + + + + Opens a file dialog used to export the contents of this database cell to a file. + + + + &Import... + + + + Import from file + + + + Opens a file dialog used to import any kind of data to this database cell. + + + + Set as &NULL + + + + Word Wrap + + + + Wrap lines on word boundaries + + + + Open in default application or browser + + + + Open in application + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + + + + Save file reference... + + + + Save reference to file + + + + Open in external application + + + + Unsaved data in the cell editor + + + + Image data can't be viewed in this mode. + + + + Try switching to Image or Binary mode. + + + + Binary data can't be viewed in this mode. + + + + Try switching to Binary mode. + + + + Image files (%1) + + + + Choose a file to import + Välj en fil att importera + + + %1 Image + + + + Binary files (*.bin) + + + + Invalid data for this mode + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + + + + Couldn't save file: %1. + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + + + + Identification of the cell currently in the editor + + + + Type and size of data currently in table + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + + + + Editing row=%1, column=%2 + + + + No cell active. + + + + Type: NULL; Size: 0 bytes + + + + Type: Text / Numeric; Size: %n character(s) + + + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + + + + Type: Valid JSON; Size: %n character(s) + + + + + + + Type: Binary; Size: %n byte(s) + + + + + + + + EditIndexDialog + + Edit Index Schema + + + + &Name + &Namn + + + &Table + &Tabell + + + &Unique + &Unik + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + + + + Partial inde&x clause + + + + Colu&mns + + + + Table column + + + + Type + Typ + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + + + + Index column + + + + Order + Ordning + + + Deleting the old index failed: +%1 + + + + Creating the index failed: +%1 + Misslyckades att skapa index: +%1 + + + + EditTableDialog + + U + U + + + AI + AU + + + PK + PN + + + Name + Namn + + + Type + Typ + + + Check + Vald + + + Table + Tabell + + + Autoincrement + Autouppräkning + + + Error creating table. Message from database engine: +%1 + Kunde inte skapa tabell. Meddelande frÃ¥n databasmotorn: +%1 + + + Check constraint + Kontrollera förbehÃ¥ll + + + Fields + Fält + + + Unique + Unik + + + Not null + Inte tom + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + Det finns Ã¥tminstoen en rad med deta fält satt till TOM. Det gör att det inte gÃ¥r markera detta val. Ändra data i tabellen först. + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + Är du säker pÃ¥ att du vill ta bort fältet '%1'? +All sparad data i fältet försvinner. + + + Without Rowid + Utan radid + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + Lägg till ett fält som möter följande kriterier innan radid markeras: + - Primärnyckel är markerad + - Autouppräkning är avmarkerad + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + Det finns Ã¥tminstone en rad med icke-heltalsvärde för detta fält. Det gör att det är omöjligt att markera AU. Ändra data i tabellen först. + + + Default + Förvald + + + Advanced + Avancerad + + + Default value + Förvalt värde + + + Edit table definition + Redigera tabelldefinition + + + Foreign Key + Främmande nyckel + + + Database sche&ma + + + + Add + + + + Remove + + + + Move to top + + + + Move up + + + + Move down + + + + Move to bottom + + + + NN + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + + + + Collation + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + + + + Add constraint + + + + Remove constraint + + + + Columns + Kolumner + + + SQL + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + + + + Primary Key + + + + Add a primary key constraint + + + + Add a unique constraint + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + + + + Column '%1' has duplicate data. + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + + + + On Conflict + + + + Strict + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + + + + Index Constraints + + + + Foreign Keys + + + + References + + + + Check Constraints + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + + + + + ExportDataDialog + + Export data as CSV + Exportera data som CSV + + + Tab&le(s) + + + + Colu&mn names in first line + + + + Fie&ld separator + + + + , + , + + + ; + ; + + + Tab + Tabb + + + | + | + + + Other + Annat + + + &Quote character + &Citattecken + + + " + " + + + ' + ' + + + New line characters + + + + Windows: CR+LF (\r\n) + + + + Unix: LF (\n) + + + + Pretty print + + + + Export data as JSON + + + + exporting CSV + + + + Could not open output file: %1 + Kunde inte öppna fil för utdata: %1 + + + exporting JSON + + + + Choose a filename to export data + Välj ett filnamn att exportera data till + + + Please select at least 1 table. + Välj minst 1 tabell. + + + Choose a directory + Välj en katalog + + + Export completed. + Export slutförd. + + + Error while writing the file '%1': %2 + + + + Export finished with errors. + + + + + ExportSqlDialog + + Export completed. + Export slutförd. + + + Export schema only + Exportera endast schema + + + Export cancelled or failed. + Export avbruten eller mislyckades. + + + &Options + &Val + + + Keep column names in INSERT INTO + BehÃ¥ll kolunnamn i INSERT INTO + + + Export SQL... + Exportera SQL... + + + Choose a filename to export + Välj ett filnamn att exportera + + + Tab&le(s) + + + + Select All + + + + Deselect All + + + + Multiple rows (VALUES) per INSERT statement + + + + Export everything + + + + Export data only + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + + + + Please select at least one table. + + + + Keep original CREATE statements + + + + + ExtendedScintilla + + Ctrl+H + + + + Ctrl+F + + + + Ctrl+P + + + + Find... + + + + Find and Replace... + + + + Print... + + + + + ExtendedTableWidget + + Use as Exact Filter + + + + Containing + + + + Not containing + + + + Not equal to + + + + Greater than + + + + Less than + + + + Greater or equal + + + + Less or equal + + + + Between this and... + + + + Regular expression + + + + Edit Conditional Formats... + + + + Set to NULL + + + + Cut + + + + Copy + + + + Copy with Headers + + + + Copy as SQL + + + + Paste + + + + Print... + + + + Use in Filter Expression + + + + Alt+Del + + + + Ctrl+Shift+C + + + + Ctrl+Alt+C + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + + + + + FileExtensionManager + + File Extension Manager + + + + &Up + + + + &Down + + + + &Add + + + + &Remove + + + + Description + + + + Extensions + + + + *.extension + + + + + FilterLineEdit + + Filter + Filter + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + + + + Set Filter Expression + + + + What's This? + + + + Is NULL + + + + Is not NULL + + + + Is empty + + + + Is not empty + + + + Not containing... + + + + Equal to... + + + + Not equal to... + + + + Greater than... + + + + Less than... + + + + Greater or equal... + + + + Less or equal... + + + + In range... + + + + Regular expression... + + + + Clear All Conditional Formats + + + + Use for Conditional Format + + + + Edit Conditional Formats... + + + + + FindReplaceDialog + + Find and Replace + + + + Fi&nd text: + + + + Re&place with: + + + + Match &exact case + + + + Match &only whole words + + + + When enabled, the search continues from the other end when it reaches one end of the page + + + + &Wrap around + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + + + + Search &backwards + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + + + + &Selection only + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + Use regular e&xpressions + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + + + + &Find Next + + + + F3 + + + + &Replace + + + + Highlight all the occurrences of the text in the page + + + + F&ind All + + + + Replace all the occurrences of the text in the page + + + + Replace &All + + + + The searched text was not found + + + + The searched text was not found. + + + + The searched text was replaced one time. + + + + The searched text was found one time. + + + + The searched text was replaced %1 times. + + + + The searched text was found %1 times. + + + + + ForeignKeyEditor + + &Reset + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + + + + + ImageViewer + + Image Viewer + + + + Reset the scaling to match the original size of the image. + + + + Set the scaling to match the size of the viewport. + + + + Print... + + + + Open preview dialog for printing displayed image + + + + Ctrl+P + + + + + ImportCsvDialog + + " + " + + + ' + ' + + + , + , + + + ; + ; + + + | + | + + + Tab + Tabb + + + Other + Annat + + + UTF-8 + + + + ISO-8859-1 + + + + Creating restore point failed: %1 + Misslyckades att skapa Ã¥terställningspunkt: %1 + + + Inserting row failed: %1 + Misslyckades att infoga rad: %1 + + + &Column names in first line + &%Kolumnnamn pÃ¥ första raden + + + Creating the table failed: %1 + Misslyckades att skapa tabellen: %1 + + + &Encoding + &Teckenkodning + + + Field &separator + Fält&separator + + + UTF-16 + + + + Trim fields? + Beskär fält? + + + &Quote character + &Citattecken + + + Import CSV file + Importera CSV-fil + + + Table na&me + + + + Other (printable) + + + + Other (code) + + + + Separate tables + + + + Advanced + Avancerad + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + + + + Ignore default &values + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + + + + Fail on missing values + + + + Disable data type detection + + + + Disable the automatic data type detection when creating a new table. + + + + Use local number conventions + + + + Use decimal and thousands separators according to the system locale. + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + + + + Abort import + + + + Ignore row + + + + Replace existing row + + + + Conflict strategy + + + + Deselect All + + + + Match Similar + + + + Select All + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + + + + There is already a table named '%1'. Do you want to import the data into it? + + + + importing CSV + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + + + + Could not prepare INSERT statement: %1 + + + + + MainWindow + + User + Användare + + + Import completed. + Import slutförd. + + + &Edit + &Redigera + + + &File + &Fil + + + &Help + &Hjälp + + + &View + &Vy + + + E&xit + A&vsluta + + + Open the preferences window. + Öppna fönster för egenskaper. + + + Export a database to a .sql dump text file. + Exportera databas till en .sql-dump textfil. + + + Error importing data: %1 + Fel vid import av data: %1 + + + &Recently opened + &Nyligen öppnad + + + Ctrl+Return + Ctrl+Retur + + + Load a working session from a file + Ladda en fungerande session frÃ¥n en fil + + + &New Database... + &Ny databas... + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + Detta val används för att Ã¥terställa nuvarande databas till sitt senaste sparade läge. Alla förändringar efter senaste sparning gÃ¥r förlorade. + + + Choose a file to import + Välj en fil att importera + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + Exportera en databastabell som en kommaseparerad textfil, redo at importeras i en annan databas eller program för kalkylark. + + + &Clear + &Rensa + + + Export table as comma separated values file + Exportera tabell som en fil med kommaseparerad värden + + + Copy the CREATE statement of the item to the clipboard + Kopiera CREATE-satsen till urklipp + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + Detta val lÃ¥ter dig importera data frÃ¥n en .sql-dump textfil till en ny eller existerande databas. SQL-dumpfiler kan skapas med de flesta databasmotererna, inklusive MySQL och PostgreSQL. + + + Save the current session to a file + Spara nuvarande session till en fil + + + Delete Index + Ta bort index + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + Om du ställer in värdet för PRAGMA kommer du att genomföra nuvarande transaktion. Är du säker? + + + Delete Table + Ta bort tabell + + + Ctrl+D + + + + Ctrl+E + + + + Ctrl+I + + + + Ctrl+L + + + + Ctrl+N + + + + Ctrl+O + + + + Ctrl+P + + + + Ctrl+Q + + + + Ctrl+S + + + + Ctrl+T + + + + Ctrl+W + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + En ny version av DB Browser för SQLite är tillgänglig (%1.%2.%3).<br/><br/>Ladda ner den frÃ¥n <a href='%4'>%4</a>. + + + Choose a database file + Välj en databasfil + + + Import data from an .sql dump text file into a new or existing database. + Importera data frÃ¥n en .sql-dump textfil till en ny eller existerande databas. + + + Revert database to last saved state + Ã…terställ databasen till senaste sparade läget + + + Shows or hides the Database toolbar. + Visa eller dölj verktygsrad för databas. + + + Compact the database file, removing space wasted by deleted records + Minska storleken pÃ¥ databasfilen genom att ta bort onödigt tomrum som upptas av bortagna poster + + + This option is used to create a new database file. + Detta val används för att skapa en ny databasfil. + + + toolBar1 + Verktygsrad1 + + + Don't show again + Visa inte igen + + + Delete Trigger + Ta bort utlösare + + + Text files(*.sql *.txt);;All files(*) + Textfiler(*.sql *.txt);;Alla filer(*) + + + Copy Create statement + Kopiera CREATE-uttryck + + + Select SQL file to open + Välj SQL-fil att öppna + + + Choose a filename to save under + Visa ett filnamn att spara under + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + Öppna guiden för att skapa index, där finns möjlighet att definiera ett nytt index för en existerande databastabell. + + + Create a new database file + Skapa en ny databasfil + + + &Open Database... + &Öppna databas... + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Öppna guiden för att ta bort tabell, där du kan välja en databastabell att släppa. + + + Select extension file + Välj fil med tillägg + + + DB Browser for SQLite project file (*.sqbpro) + DB Browser för SQLite projektfil (*.sqbpro) + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + Är du säker pÃ¥ att du vill Ã¥ngra alla ändringar som gjorts i databasfilen '%1' sedan den sparades senaste? + + + Select file name + Välj filnamn + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Öppna guiden för att skapa tabell, där det är möjligt att ange filnamn och fält för en ny tabell i databasen + + + Export a database table as a comma separated text file. + Exportera en databastabell som en kommaseparerad textfil. + + + Export as CSV file + Exportera som CSV-fil + + + Extension successfully loaded. + Tillägget har laddats in. + + + Open an existing database file + Öppna en existerande databasfil + + + Delete View + Ta bort vy + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Öppna en guide för att importera data frÃ¥n en kommaseparerad textfil in i en databastabell. CSV-filer kan skapas med de flesta databaser och kalkylprogram. + + + &Export + &Exportera + + + &Import + &Importera + + + File %1 already exists. Please choose a different name. + Filen %1 finns redan. Välj ett annat namn. + + + DB Toolbar + DB Verktygsrad + + + &DB Toolbar + &DB Verktygsrad + + + Save SQL file as + Spara SQL-fil som + + + &Close Database + &Stäng databas + + + This option is used to save changes to the database file. + Detta val används för att spara förändringar till databasfilen. + + + &Preferences... + &Egenskaper... + + + Write changes to the database file + Skriv ändringar till databasfilen + + + Database encoding + Databasteckenkodning + + + Save SQL file + Spara SQL-fil + + + Compact the database file, removing space wasted by deleted records. + Töm databasfilen och ta bort tomrum av borttagna poster. + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Öppna guide för at importera en kommaseparerad textfil till en databastabell. + + + DB Browser for SQLite + DB Browser för SQLite + + + Execute current line + Utför nuvarande rad + + + &Browse Table + &Visa tabell + + + Database is encrypted using SQLCipher + Databasen är krypterad med SQLCipher + + + New version available. + Ny version tillgänglig. + + + &Execute SQL + &Utför SQL + + + This option is used to open an existing database file. + Detta val används för att öppna en existerande databasfil. + + + Error loading extension: %1 + Fel när tillägg skulle laddas: %1 + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + Valet lÃ¥ter dig exportera en databas till en .sql-dump textfil. SQL-dump textfiler innehÃ¥ller all data som behövs för att Ã¥terskapa databasen med de flesta databasmotorer, inklusive MySQL och PostgreSQL. + + + Shift+F1 + Skift+F1 + + + Application + Programvara + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + Vill du skapa en ny databas med det importerade datat? +Försöker importera datat i SQL-filen i nuvarande databas om du svarar nej. + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + + + + &Recent Files + + + + Too&ls + + + + Edit Database &Cell + + + + SQL &Log + + + + Show S&QL submitted by + + + + Error Log + + + + This button clears the contents of the SQL logs + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + + + + &Plot + + + + DB Sche&ma + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + + + + &Remote + + + + Project Toolbar + + + + Extra DB toolbar + + + + Close the current database file + + + + This button closes the connection to the currently open database file + + + + Ctrl+F4 + + + + &Revert Changes + + + + &Write Changes + + + + Compact &Database... + + + + &Database from SQL file... + + + + &Table from CSV file... + + + + &Database to SQL file... + + + + &Table(s) as CSV file... + + + + &Create Table... + + + + &Delete Table... + + + + &Modify Table... + + + + Create &Index... + + + + W&hat's This? + + + + &About + + + + New &tab + + + + This button opens a new tab for the SQL editor + + + + Execute all/selected SQL + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + + + + Open SQL file(s) + + + + This button opens files containing SQL statements and loads them in new editor tabs + + + + &Load Extension... + + + + Execute line + + + + This button executes the SQL statement present in the current editor line + + + + Shift+F5 + Skift+F5 + + + &Wiki + + + + F1 + + + + Bug &Report... + + + + Feature Re&quest... + + + + Web&site + + + + &Donate on Patreon... + + + + Sa&ve Project + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + + + + Open &Project... + + + + This button lets you open a DB Browser for SQLite project file + + + + &Attach Database... + + + + Add another database file to the current database connection + + + + This button lets you add another database file to the current database connection + + + + &Set Encryption... + + + + This button saves the content of the current SQL editor tab to a file + + + + SQLCipher &FAQ + + + + Opens the SQLCipher FAQ in a browser window + + + + Table(&s) to JSON... + + + + Export one or more table(s) to a JSON file + + + + Open Data&base Read Only... + + + + Open an existing database file in read only mode + + + + Ctrl+Shift+O + + + + Save results + + + + Save the results view + + + + This button lets you save the results of the last executed query + + + + Find text in SQL editor + + + + Find + + + + This button opens the search bar of the editor + + + + Ctrl+F + + + + Find or replace text in SQL editor + + + + Find or replace + + + + This button opens the find/replace dialog for the current editor tab + + + + Ctrl+H + + + + Export to &CSV + Exportera till &CSV + + + Export to &JSON + + + + Save as &view + Spara som &vy + + + Save as view + Spara som vy + + + Shows or hides the Project toolbar. + + + + Extra DB Toolbar + + + + New In-&Memory Database + + + + Drag && Drop Qualified Names + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + + + + Drag && Drop Enquoted Names + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + + + + &Integrity Check + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + + + + &Foreign-Key Check + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + + + + &Quick Integrity Check + + + + Run a quick integrity check over the open DB + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + + + + &Optimize + + + + Attempt to optimize the database + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + + + + Print + + + + Print text from current SQL editor tab + + + + Open a dialog for printing the text in the current SQL editor tab + + + + Print the structure of the opened database + + + + Open a dialog for printing the structure of the opened database + + + + Un/comment block of SQL code + + + + Un/comment block + + + + Comment or uncomment current line or selected block of code + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + + + + Ctrl+/ + + + + Stop SQL execution + + + + Stop execution + + + + Stop the currently running SQL script + + + + &Save Project As... + + + + Save the project in a file selected in a dialog + + + + Save A&ll + + + + Save DB file, project file and opened SQL files + + + + Ctrl+Shift+S + + + + Browse Table + + + + Close Pro&ject + + + + Close project and database files and return to the initial state + + + + Ctrl+Shift+W + + + + Detach Database + + + + Detach database file attached to the current database connection + + + + Table from CSV data in Clipboard... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + + + + Show &Row Counts + + + + This shows the number of rows for each table and view in the database. + + + + Save Database &As... + + + + Save the current database as a different file + + + + Ctrl+Tab + + + + Ctrl+Shift+Tab + + + + Clear List + + + + Window Layout + + + + Reset Window Layout + + + + Simplify Window Layout + + + + Alt+Shift+0 + + + + Dock Windows at Bottom + + + + Dock Windows at Left Side + + + + Dock Windows at Top + + + + The database is currently busy. + + + + Click here to interrupt the currently running query. + + + + Encrypted + + + + Read only + + + + Database file is read only. Editing the database is disabled. + + + + Alt+Shift+W + + + + Ctrl+Shift+F4 + + + + Could not open database file. +Reason: %1 + + + + In-Memory database + + + + Choose a database file to save under + + + + Error while saving the database to the new file. + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + + + + Do you want to save the changes made to the project file '%1'? + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + + + + Are you sure you want to delete the view '%1'? + + + + Are you sure you want to delete the trigger '%1'? + + + + Are you sure you want to delete the index '%1'? + + + + Error: could not delete the table. + + + + Error: could not delete the view. + + + + Error: could not delete the trigger. + + + + Error: could not delete the index. + + + + Message from database engine: +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + + + + Error checking foreign keys after table modification. The changes will be reverted. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + + + + Edit View %1 + + + + Edit Trigger %1 + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + + + + -- EXECUTING SELECTION IN '%1' +-- + + + + -- EXECUTING LINE IN '%1' +-- + + + + -- EXECUTING ALL IN '%1' +-- + + + + At line %1: + + + + Result: %1 + + + + Result: %2 + + + + %1 rows returned in %2ms + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + + + + Execution finished with errors. + + + + Execution finished without errors. + + + + Choose text files + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + + + + Modify View + + + + Modify Trigger + + + + Modify Index + + + + Modify Table + + + + Opened '%1' in read-only mode from recent file list + + + + Opened '%1' from recent file list + + + + &%1 %2%3 + + + + (read only) + + + + Open Database or Project + + + + Attach Database... + + + + Import CSV file(s)... + + + + Do you want to save the changes made to SQL tabs in a new project file? + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + + + + Do you want to save the changes made to the SQL file %1? + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + + + + Could not find resource file: %1 + + + + Choose a project file to open + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + + + + Could not open project file for writing. +Reason: %1 + + + + Project saved to file '%1' + + + + Yes. Don't ask again + + + + Collation needed! Proceed? + Sortering behövs! Fortsätt? + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + En tabell i databasen behöver en speciell sorteringsfunktion '%1' som detta program inte tillhandahÃ¥ller utan ytterligare kunskap. +Skadliga skare kan inträffa med din databas om du väljer att fortsätta. +Skapa en backup! + + + creating collation + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + + + + Please specify the view name + Ange namn pÃ¥ vy + + + There is already an object with that name. Please choose a different name. + Det finns redan ett objekt med det namnet. Ange ett annat namn. + + + View successfully created. + Vy skapades. + + + Error creating view: %1 + Misslyckades skapa vy: %1 + + + This action will open a new SQL tab for running: + + + + This action will open a new SQL tab with the following statements for you to edit and run: + + + + Press Help for opening the corresponding SQLite reference page. + + + + Busy (%1) + + + + Rename Tab + + + + Duplicate Tab + + + + Close Tab + + + + Opening '%1'... + + + + There was an error opening '%1'... + + + + Value is not a valid URL or filename: %1 + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + + + + &New Database + + + + &Undo + + + + Undo last change to the database + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + + + + Ctrl+Shift+T + + + + &Save Project + + + + Open &Project + + + + &Open Database + + + + Drag && Drop SELECT Query + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + + + + Refresh + + + + Reload the database structure + + + + Ctrl+0 + + + + DB file '%1' could not be opened + + + + Table '%1' not found; settings ignored + + + + -- Reference to file "%1" (not supported by this version) -- + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + + + + + + Automatically load the last opened DB file at startup + + + + Temp Store + + + + Secure Delete + + + + Case Sensitive Like + + + + Journal Mode + + + + Journal Size Limit + + + + Recursive Triggers + + + + Page Size + + + + Foreign Keys + + + + Auto Vacuum + + + + Max Page Count + + + + Checkpoint Full FSYNC + + + + Automatic Index + + + + Ignore Check Constraints + + + + Full FSYNC + + + + WAL Auto Checkpoint + + + + User Version + + + + Synchronous + + + + Locking Mode + + + + Delete + pragma + Ta bort + + + Off + + + + Normal + + + + Full + + + + Default + Förvald + + + File + Fil + + + Memory + + + + None + Ingen + + + Incremental + + + + Delete + Ta bort + + + Truncate + + + + Persist + + + + WAL + + + + Exclusive + + + + + NullLineEdit + + Set to NULL + + + + Alt+Del + + + + + PlotDock + + Plot + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + + + + Columns + Kolumner + + + X + + + + Y1 + + + + Y2 + + + + Axis Type + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + + + + Line type: + Radtyp: + + + None + Ingen + + + Line + Rad + + + StepLeft + Vänstersteg + + + StepRight + Högersteg + + + StepCenter + Stegcentrum + + + Impulse + Impuls + + + Point shape: + Punktform: + + + Cross + Kors + + + Plus + + + + Circle + Cirkel + + + Disc + Skiva + + + Square + Fyrkant + + + Diamond + Diamant + + + Star + Stjärna + + + Triangle + Triangel + + + TriangleInverted + InverteradTriangel + + + CrossSquare + Korsfyrkant + + + PlusSquare + Plusfyrkant + + + CrossCircle + Korscirkel + + + PlusCircle + Pluscirkel + + + Peace + Fred + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>Spara nuvarande plan...</p><p>Filformat valt utifrÃ¥n filändelse (png, jpg, pdf, bmp)</p></body></html> + + + Save current plot... + Spara nuvarande plan... + + + Load all data and redraw plot + + + + Copy + + + + Print... + + + + Show legend + + + + Stacked bars + + + + Fixed number format + + + + Date/Time + + + + Date + + + + Time + + + + Numeric + + + + Label + + + + Invalid + + + + Row # + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + + + + Choose an axis color + + + + Choose a filename to save under + Visa ett filnamn att spara under + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Alla Filer(*) + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + + + + Loading all remaining data for this table took %1ms. + + + + Help + + + + + PreferencesDialog + + ... + ... + + + &SQL + &SQL + + + Bold + Fet + + + SQL &editor font size + SQL &redigera fontstorlek + + + Automatic &updates + Automatisk &uppdatering + + + Table + Tabell + + + Lan&guage + Spr&Ã¥k + + + Current line + Nuvarande rad + + + Keyword + Nyckelord + + + The language will change after you restart the application. + SprÃ¥ket ändras efter du startar om programmet. + + + SQL editor &font + &Font SQL redigerare + + + Data &Browser + Data&visare + + + Open databases with foreign keys enabled. + Öppna databaser med främmande nycklar aktiverade. + + + Remember last location for session only + Kom endast ihÃ¥g senaste plats för sessionen + + + Colour + Färg + + + Italic + Kursiv + + + Disable Regular Expression extension + Avaktivera tillägg för reguljära uttryck + + + Identifier + Identifierare + + + String + Sträng + + + &Database + &Databas + + + Database &encoding + Databas&teckenkodning + + + &Foreign keys + &Främmande nycklar + + + Select extension file + Välj tilläggsfil + + + Default &location + Förvald &placering + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>SQLite stödjer REGEXP med hanterar inte nÃ¥gra<br/>algoritmer för reguljära uttryck, utan använder det som tillhandahÃ¥lls av programmet som körs. DB Browser för SQLite hanterar <br/>en algoritm Ã¥t dig sÃ¥ du kan använda REGEXP pÃ¥ en gÃ¥ng. Dock finns det en uppsjö möjliga olika varianter att välja mellan<br/> av vilken du kanske vill använda en annan, sÃ¥ är du fri at avaktivera <br/>programmets variant och ladda in din egen genom ett tillägg. Omstart av programmet är dÃ¥ nödvändigt.</p></body></html> + + + Comment + Kommentar + + + Context + Sammanhang + + + Underline + Understrykning + + + Remember last location + Kom ihÃ¥g senaste plats + + + Choose a directory + Välj en katalog + + + Select extensions to load for every database: + Välj tillägg att ladda in för varje databas: + + + enabled + aktiverad + + + Function + Funktion + + + &Extensions + &Tillägg + + + Remove extension + Ta bort tillägg + + + Preferences + Egenskaper + + + Add extension + Lägg till tillägg + + + &General + &Generell + + + Always use this location + Använd alltid den här platsen + + + Toolbar style + + + + Only display the icon + + + + Only display the text + + + + The text appears beside the icon + + + + The text appears under the icon + + + + Follow the style + + + + Show remote options + + + + DB file extensions + + + + Manage + + + + Main Window + + + + Database Structure + + + + Browse Data + + + + Execute SQL + + + + Edit Database Cell + + + + When this value is changed, all the other color preferences are also set to matching colors. + + + + Follow the desktop style + + + + Dark style + + + + Application style + + + + This sets the font size for all UI elements which do not have their own font size option. + + + + Font size + + + + Max Recent Files + + + + Prompt to save SQL tabs +in new project file + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + + + + Remove line breaks in schema &view + + + + Prefetch block si&ze + + + + Default field type + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + + + + Database structure font size + + + + SQ&L to execute after opening database + + + + Font + + + + &Font + + + + Font si&ze + + + + Content + + + + Symbol limit in cell + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + + + + Threshold for completion and calculation on selection + + + + Show images in cell + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + + + + Field display + + + + Displayed &text + + + + Binary + Binär + + + NULL + + + + Regular + + + + Click to set this color + + + + Text color + + + + Background color + + + + Preview only (N/A) + + + + Filters + + + + Escape character + + + + Delay time (&ms) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + + + + Background + + + + Foreground + + + + Selection background + + + + Selection foreground + + + + Highlight + + + + SQL &results font size + + + + Tab size + + + + &Wrap lines + + + + Never + + + + At word boundaries + + + + At character boundaries + + + + At whitespace boundaries + + + + &Quotes for identifiers + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + + + + "Double quotes" - Standard SQL (recommended) + + + + `Grave accents` - Traditional MySQL quotes + + + + [Square brackets] - Traditional MS SQL Server quotes + + + + Code co&mpletion + + + + Keywords in &UPPER CASE + + + + When set, the SQL keywords are completed in UPPER CASE letters. + + + + Error indicators + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + + + + Hori&zontal tiling + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + + + + Close button on tabs + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + + + + Allow loading extensions from SQL code + + + + Remote + + + + Your certificates + + + + File + Fil + + + Subject CN + + + + Subject Common Name + + + + Issuer CN + + + + Issuer Common Name + + + + Valid from + + + + Valid to + + + + Serial number + + + + CA certificates + + + + Common Name + + + + Subject O + + + + Organization + + + + Clone databases into + + + + Proxy + + + + Configure + + + + Export Settings + + + + Import Settings + + + + Extensions(*.so *.dylib *.dll);;All files(*) + + + + Import certificate file + + + + No certificates found in this file. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + + + + Save Settings File + + + + Initialization File (*.ini) + + + + The settings file has been saved in location : + + + + + Open Settings File + + + + The settings file was loaded properly. + + + + The selected settings file is not a normal settings file. +Please check again. + + + + Light style + + + + Formatted + + + + Use tabs for indentation + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + + + + Select built-in extensions to load for every database: + + + + + ProxyDialog + + Proxy Configuration + + + + Pro&xy Type + + + + Host Na&me + + + + Port + + + + Authentication Re&quired + + + + &User Name + + + + Password + + + + None + Ingen + + + System settings + + + + HTTP + + + + SOCKS5 + + + + + QObject + + . +%1 + .%1 + + + from record number %1 + frÃ¥n post nummer %1 + + + Cancel + Avbryt + + + Error importing data + Fel vid import av data + + + Left + + + + Right + + + + Center + + + + Justify + + + + All files (*) + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + + + + SQL Files (*.sql) + + + + All Files (*) + + + + Text Files (*.txt) + + + + Comma-Separated Values Files (*.csv) + + + + Tab-Separated Values Files (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + + + + Concordance DAT files (*.dat) + + + + JSON Files (*.json *.js) + + + + XML Files (*.xml) + + + + Binary Files (*.bin *.dat) + + + + SVG Files (*.svg) + + + + Hex Dump Files (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + + + + Importing CSV file... + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + + + + + QsciCommand + + Cancel + Avbryt + + + + QsciLexerCPP + + Default + Förvald + + + Keyword + Nyckelord + + + Identifier + Identifierare + + + + QsciLexerJSON + + Default + Förvald + + + String + Sträng + + + + QsciLexerPython + + Default + Förvald + + + Comment + Kommentar + + + Keyword + Nyckelord + + + Identifier + Identifierare + + + + QsciLexerSQL + + Default + Förvald + + + Comment + Kommentar + + + Keyword + Nyckelord + + + Identifier + Identifierare + + + + QsciScintilla + + Delete + Ta bort + + + + RemoteCommitsModel + + Commit ID + + + + Message + + + + Date + + + + Author + + + + Size + + + + Authored and committed by %1 + + + + Authored by %1, committed by %2 + + + + + RemoteDatabase + + Error opening local databases list. +%1 + + + + Error creating local databases list. +%1 + + + + + RemoteDock + + Remote + + + + Identity + + + + Push currently opened database to server + + + + Upload + + + + DBHub.io + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + + + + Local + + + + Current Database + + + + Clone + + + + &User + + + + &Database + &Databas + + + Branch + + + + Commits + + + + Commits for + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + + + + Back + + + + Delete Database + + + + Delete the local clone of this database + + + + Open in Web Browser + + + + Open the web page for the current database in your browser + + + + Clone from Link + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + + + + Refresh + + + + Reload all data and update the views + + + + Clone Database + + + + Open Database + + + + Open the local copy of this database + + + + Check out Commit + + + + Download and open this specific commit + + + + Check out Latest Commit + + + + Check out the latest commit of the current branch + + + + Save Revision to File + + + + Saves the selected revision of the database to another file + + + + Upload Database + + + + Upload this database as a new commit + + + + Select an identity to connect + + + + Public + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + + + + Invalid URL: The host name does not match the host name of the current identity. + + + + Invalid URL: No branch name specified. + + + + Invalid URL: No commit ID specified. + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + + + + The database has unsaved changes. Are you sure you want to push it before saving? + + + + The database you are trying to delete is currently opened. Please close it before deleting. + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + + + + + RemoteLocalFilesModel + + Name + Namn + + + Branch + + + + Last modified + + + + Size + + + + Commit + + + + File + Fil + + + + RemoteModel + + Name + Namn + + + Last modified + + + + Size + + + + Commit + + + + Size: + + + + Last Modified: + + + + Licence: + + + + Default Branch: + + + + + RemoteNetwork + + Choose a location to save the file + + + + Error opening remote file at %1. +%2 + + + + Error: Invalid client certificate specified. + + + + Please enter the passphrase for this client certificate in order to authenticate. + + + + Cancel + Avbryt + + + Uploading remote database to +%1 + + + + Downloading remote database from +%1 + + + + Error: Cannot open the file for sending. + + + + + RemotePushDialog + + Push database + + + + Database na&me to push to + + + + Commit message + + + + Database licence + + + + Public + + + + Branch + + + + Force push + + + + Username + + + + Database will be public. Everyone has read access to it. + + + + Database will be private. Only you have access to it. + + + + Use with care. This can cause remote commits to be deleted. + + + + + RunSql + + Execution aborted by user + + + + , %1 rows affected + + + + query executed successfully. Took %1ms%2 + + + + executing query + + + + + SelectItemsPopup + + A&vailable + + + + Sele&cted + + + + + SqlExecutionArea + + Form + Formulär + + + Results of the last executed statements + Resultat av senast utförda uttrycket + + + This field shows the results and status codes of the last executed statements. + Fältet visar resultat och statuskoder av senast utförda uttryck. + + + Find previous match [Shift+F3] + + + + Find previous match with wrapping + + + + Shift+F3 + Skift+F3 + + + The found pattern must be a whole word + + + + Whole Words + + + + Text pattern to find considering the checks in this frame + + + + Find in editor + + + + The found pattern must match in letter case + + + + Case Sensitive + + + + Find next match [Enter, F3] + + + + Find next match with wrapping + + + + F3 + + + + Interpret search pattern as a regular expression + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + Regular Expression + + + + Close Find Bar + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + + + + Couldn't save file: %1. + + + + Your changes will be lost when reloading it! + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + + + + Answer "No to All" to ignore any external update without further prompting. + + + + Modifying and saving the file will restore prompting. + + + + Couldn't read file "%1": %2. + + + + Ctrl+PgUp + + + + Ctrl+PgDown + + + + + SqlTextEdit + + Ctrl+/ + + + + + SqlUiLexer + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) Funktionen group_concat() returnerar en sträng som slÃ¥r samman alla icke-TOMMA värden av X. + + + (timestring,modifier,modifier,...) + (tidssträng,modifierare,modifierare...) + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) Flerargumentsfunktionen max() returnerar argumentet med det största värdet, eller NULL om nÃ¥got argument är TOMT (NULL). + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) Funktioen count(X) returnerar antalet gÃ¥nger somX inte är TOMT (NULL) i en gruppering. + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) Funktionen ifnull() returnerar en kopia av dess första icke-TOMMA argument, eller NULL om bÃ¥da argumenten är TOMMA (NULL). + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) Flerargumentsfunktionen min() returnerar argument med lägst värde. + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) SQL-funktionen printf(FORMAT,...) fungerar som funktionen sqlite3_mprintf() i C-sprÃ¥k och funktionsnamnet printf() kommer frÃ¥n standardbiblioteket för C. + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () Funktionen last_insert_rowid() returnerar radid (ROWID) för senast tillagda rad för ansluten databas som senast använde funktionen. + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) Funktionen coalesce() returnerar en kopia av dess första icke-TOMMA argument, eller NULL om alla argument är TOMMA (NULL) + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) Funktionen group_concat() returnerar en sträng sammanfogad av alla icke-TOMMA värden av X. Parametern Y används som avdelare mellan värden av X om den angivits. + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) Funktionen hex() tolkar argumenten som en BLOB och returnerar en sträng av hexadecimal som versaler som representerar innehÃ¥llet av blob:en. + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) Funktionen quote(X) returnerar texten som innehÃ¥llet av värdet för argumentet sÃ¥ att det kan stättas in i en SQL-stats. + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) funktionen typeof(X) returnerar en sträng som anger datatyp för uttrycket X. + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) Funktionen instr(X,Y) söker efter första förekomsten av strängen Y inom strängen X och returnerar dess början som antal tecken före plus 1, eller 0 om Y inte kan hittas inom X. + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () Funktionen random() returnerar ett nÃ¥gorlunda genererat slumptal som heltal i intervallet -9223372036854775808 och +9223372036854775807. + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) Funktionen lower(X) returnerar en kopia av strängen X med alla ASCII-tecken ändrade till gemener. + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) Funktionen like() används för att Ã¥stadkomma uttrycket "Y LIKE X ESCAPE Z". + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) Funktionen like() används för att Ã¥stadkomma uttrycket "Y LIKE X". + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) Funktionen ltrim(X,Y) returnerar en sträng som rensats pÃ¥ alla tecken som ingÃ¥r i Y frÃ¥n vänstra sidan av X. + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) Funktionen round(X) returnerar et decimaltal X som avrundats till noll decimaler. + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) Funktionen abs(X) returnerar absolutvärdt av det numeriska argumentet X. + + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) tar bort mellanslag frÃ¥n höger sida av X. + + + (format,timestring,modifier,modifier,...) + (format,tidssträng,modifierare,modifierare...) + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () Funtionen total_changes() returnerar antalet rader som ändrats av INSERT, UPDATE eller DELETE sedan databasen öppnades. + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) Aggregat-funktionerna sum() och total() returnerar summan av alla icke-TOMMA värden i en grupp. + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) Funktionen length(X) returnerar antalet tecken (inte byte) som strängen X innehÃ¥ller före det första tom-tecknet (NUL). + + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X) tar bort mellanslag frÃ¥n höger sida av X. + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) Funktionen glob(X,Y) motsvarar uttrycket "Y GLOB X". + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) Funktionen soundex(X) returnerar en sträng som motsvarar uttalet av strängen X. + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) Funktionen upper(X) returnerar en kopia av indatasträngen X där alla gemener av ASCII-tecken görs om till sina motsvarigheter som versaler. + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) Funktionen zeroblob(N) returnerar en BLOB som bestÃ¥r av N byte av 0x00. + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) Funktionen rtrim(X,Y) returnerar en sträng som rensats pÃ¥ alla tecken som ingÃ¥r i Y frÃ¥n högra sidan av X. + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) Aggregatfunktionen min() returnerar mininsta värde som inte är TOMT (NULL) av alla värden i en gruppering. + + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) tar bort mellanslag frÃ¥n bÃ¥da ändar av X. + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) Funktionen replace(X,Y,Z) returnerar en sträng där varje förekomst av strängen Y ersatts med Z i strängen X. + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) Funktionen round(X,Y) returnerar ett decimaltal X avrundat till Y decimaler. + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) Funktionen nullif(X,Y) returnerar dess första argument om argumenten är olika och TOMT (NULL) om argumenten är lika. + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) Funktionen trim(X,Y) returnerar en sträng där alla förekomster av Y tagits bort i bÃ¥da ändar av X. + + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) Aggregatfunktionen max() returnerar det största av värdena i grupperingen. + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) Funktionen randomblob(N) returnerar en blob som är N-byte stor och innehÃ¥ller nÃ¥gorlunda slumpmässiga byte. + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) Funktionen substr(X,Y,Z) returnerar en del av indatasträngen X och börjar pÃ¥ teckenposition Y och är Z tecken lÃ¥ng. + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) Funktionen char(X1,X2,...,XN) returnerar en sträng med tecken skapad av tal för unicode-värden frÃ¥n X1 till XN. + + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) Funktionen avg() returnerar medelvärdet av alla icke-TOMMA X inom en gruppering. + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) Funktionen unicode(X) returnerar det numeriska unicode-värdet som motsvarar det första tecknet i strängen X. + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () Funktionen changes() returnerar antalet rader i databasen som förändrades, infogades eller togs bort av den senast genomförda INSERT, DELETE, eller UPDATE-satsen. + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) substr(X,Y) returnerar alla tecken till slutet av strängen X med början pÃ¥ tecken Y. + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + + + + (X) Return the arccosine of X. The result is in radians. + + + + (X) Return the hyperbolic arccosine of X. + + + + (X) Return the arcsine of X. The result is in radians. + + + + (X) Return the hyperbolic arcsine of X. + + + + (X) Return the arctangent of X. The result is in radians. + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + + + + (X) Return the hyperbolic arctangent of X. + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + + + + (X) Return the cosine of X. X is in radians. + + + + (X) Return the hyperbolic cosine of X. + + + + (X) Convert value X from radians into degrees. + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + + + + (X) Return the natural logarithm of X. + + + + (B,X) Return the base-B logarithm of X. + + + + (X) Return the base-10 logarithm for X. + + + + (X) Return the logarithm base-2 for the number X. + + + + (X,Y) Return the remainder after dividing X by Y. + + + + () Return an approximation for Ï€. + + + + (X,Y) Compute X raised to the power Y. + + + + (X) Convert X from degrees into radians. + + + + (X) Return the sine of X. X is in radians. + + + + (X) Return the hyperbolic sine of X. + + + + (X) Return the square root of X. NULL is returned if X is negative. + + + + (X) Return the tangent of X. X is in radians. + + + + (X) Return the hyperbolic tangent of X. + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + + + + + SqliteTableModel + + Error changing data: +%1 + Misslyckades ändra data: +%1 + + + reading rows + + + + loading... + + + + References %1(%2) +Hold %3Shift and click to jump there + + + + retrieving list of columns + + + + Fetching data... + + + + Cancel + Avbryt + + + + TableBrowser + + Browse Data + + + + &Table: + + + + Select a table to browse data + Välj en tabell för att visa data + + + Use this list to select a table to be displayed in the database view + Använd denna lista för att välja en tabell at visa i databasvyn + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + + + + Text pattern to find considering the checks in this frame + + + + Find in table + + + + Find previous match [Shift+F3] + + + + Find previous match with wrapping + + + + Shift+F3 + Skift+F3 + + + Find next match [Enter, F3] + + + + Find next match with wrapping + + + + F3 + + + + The found pattern must match in letter case + + + + Case Sensitive + + + + The found pattern must be a whole word + + + + Whole Cell + + + + Interpret search pattern as a regular expression + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + Regular Expression + + + + Close Find Bar + + + + Text to replace with + + + + Replace with + + + + Replace next match + + + + Replace + + + + Replace all matches + + + + Replace all + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>Rulla till början</p></body></html> + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>Klicka pÃ¥ denna knapp för att navigera till början av tabellen ovan.</p></body></html> + + + |< + + + + Scroll one page upwards + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + + + + < + + + + 0 - 0 of 0 + 0 - 0 av 0 + + + Scroll one page downwards + + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + + + + > + + + + Scroll to the end + Rulla till slutet + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + + + + >| + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>Klick här för att hoppa till angiven post</p></body></html> + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>Denna knapp används för att navigera till posten med angivet nummer i ytan för GÃ¥ till.</p></body></html> + + + Go to: + GÃ¥ till: + + + Enter record number to browse + Ange post nummer att visa + + + Type a record number in this area and click the Go to: button to display the record in the database view + Ange ett nummer för post i detta fält och klicka pÃ¥ kanppen GÃ¥ till: för att visa posten i databasvyn + + + 1 + + + + Show rowid column + + + + Toggle the visibility of the rowid column + + + + Unlock view editing + + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + + + + Edit display format + + + + Edit the display format of the data in this column + + + + New Record + Ny post + + + Insert a new record in the current table + Infoga en ny post i nuvarande tabell + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + + + + Delete Record + Ta bort post + + + Delete the current record + Ta bort nuvarande post + + + This button deletes the record or records currently selected in the table + + + + Insert new record using default values in browsed table + + + + Insert Values... + + + + Open a dialog for inserting values in a new record + + + + Export to &CSV + Exportera till &CSV + + + Export the filtered data to CSV + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + + + + Export to &JSON + + + + Export the filtered data to JSON + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + + + + Save as &view + Spara som &vy + + + Save the current filter, sort column and display formats as a view + + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + + + + Save Table As... + + + + Save the table as currently displayed + + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + + + + Hide column(s) + + + + Hide selected column(s) + + + + Show all columns + + + + Show all columns that were hidden + + + + Set encoding + + + + Change the encoding of the text in the table cells + + + + Set encoding for all tables + + + + Change the default encoding assumed for all tables in the database + + + + Clear Filters + + + + Clear all filters + Rensa alla filter + + + This button clears all the filters set in the header input fields for the currently browsed table. + + + + Clear Sorting + + + + Reset the order of rows to the default + + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + + + + Print + + + + Print currently browsed table data + + + + Print currently browsed table data. Print selection if more than one cell is selected. + + + + Ctrl+P + + + + Refresh + + + + Refresh the data in the selected table + + + + This button refreshes the data in the currently selected table. + Denna knapp uppdaterar datat i vald tabell. + + + F5 + + + + Find in cells + + + + Open the find tool bar which allows you to search for values in the table view below. + + + + Bold + Fet + + + Ctrl+B + + + + Italic + Kursiv + + + Underline + Understrykning + + + Ctrl+U + + + + Align Right + + + + Align Left + + + + Center Horizontally + + + + Justify + + + + Edit Conditional Formats... + + + + Edit conditional formats for the current column + + + + Clear Format + + + + Clear All Formats + + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + + + + Font Color + + + + Background Color + + + + Toggle Format Toolbar + + + + Show/hide format toolbar + + + + This button shows or hides the formatting toolbar of the Data Browser + + + + Select column + + + + Ctrl+Space + + + + Replace text in cells + + + + Freeze columns + + + + Make all columns from the first column up to this column not move when scrolling horizontally + + + + Filter in any column + + + + Ctrl+R + + + + %n row(s) + + + + + + + , %n column(s) + + + + + + + . Sum: %1; Average: %2; Min: %3; Max: %4 + + + + Conditional formats for "%1" + + + + determining row count... + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + + + + Delete Records + + + + Duplicate records + + + + Duplicate record + + + + Ctrl+" + + + + Adjust rows to contents + + + + Error deleting record: +%1 + Fel när post skulle tas bort: +%1 + + + Please select a record first + Välj en post först + + + Please choose a new encoding for all tables. + + + + Please choose a new encoding for this table. + + + + %1 +Leave the field empty for using the database encoding. + + + + This encoding is either not valid or not supported. + + + + %1 replacement(s) made. + + + + Copy column name + + + + Copy the database table column name to your clipboard + + + + New Data Browser + + + + Add a new docked Data Browser + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + + + + %L1 - %L2 of >= %L3 + + + + %L1 - %L2 of %L3 + + + + (clipped at %L1 rows) + + + + + TableBrowserDock + + New Data Browser + + + + Rename Data Browser + + + + Close Data Browser + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + + + + + VacuumDialog + + Compact Database + Komprimera databas + + + Warning: Compacting the database will commit all of your changes. + + + + Please select the databases to co&mpact: + + + + diff --git a/src/translations/sqlb_tr.ts b/src/translations/sqlb_tr.ts index a37af0b51..ed548917f 100644 --- a/src/translations/sqlb_tr.ts +++ b/src/translations/sqlb_tr.ts @@ -1,6 +1,6 @@ - + AboutDialog @@ -9,2788 +9,8012 @@ SQLite DB Browser Hakkında - + Version - Versiyon + Sürüm - - <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:small;">It also uses the Silk icon set by Mark James licensed under a Creative Commons Attribution 2.5 and 3.0 license.<br/>See </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> - <html><head/><body><p>SQLite DB Browser, SQLite veritabanlarını tasarlamak ve düzenlemek için kullanılan, açık kaynak kodlu, ücretsiz bir görsel araçtır.</p><p>Bu program 'Mozilla Ortak Lisans Versiyon 2' altında lisanslanmasının yanı sıra 'GNU Genel Ortak Lisansı Versiyon 3 veya üzeri' lisansa sahiptir. Bu programı, lisans koÅŸulları çerçevesinde deÄŸiÅŸtirebilir ve yeniden dağıtabilirsiniz.</p><p>Detaylı bilgiler için <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> ve <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> adreslerine bakabilirsiniz.</p><p>Program üzerine daha fazla bilgiye ulaÅŸmak için web sitemizi ziyaret edebilirsiniz: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">Bu program belirtilen adresteki GPL/LGPL Qt Toolkit kullanmaktadır: </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>Lisans koÅŸulları için ÅŸurayı ziyaret edin: </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"></span></p><p><span style=" font-size:small;">Ayrıca bu program, Mark James tarafından saÄŸlanan Creative Commons Attribution 2.5 ve 3.0 lisansına sahip Silk ikon setini kullanmaktadır.<br/>Detaylar için: </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"></span></p></body></html> + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + <html><head/><body><p>DB Browser for SQLite, SQLite veritabanı dosyaları oluÅŸturmak, tasarlamak ve düzenlemek için kullanılan açık kaynaklı, ücretsiz bir görsel araçtır.</p><p>Mozilla Public License Version 2 ve GNU General Public License Version 3 veya sonraki sürümleri altında çift lisanslıdır. Bu lisansların koÅŸulları altında bunu deÄŸiÅŸtirebilir veya yeniden dağıtabilirsiniz.</p><p>Ayrıntılar için <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> ve <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> adreslerine bakın.</p><p>Bu program hakkında daha fazla bilgi için lütfen web sitemizi ziyaret edin: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">Bu yazılım, lisanslama koÅŸulları ve diÄŸer bilgiler için </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> adresine bakın</span><a href="https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> bilgi.</span></p><p><span style=" font-size:8pt;">SQLite uzantılarını desteklemek için nalgeon/sqlean kütüphanesini kullanıyoruz.<br/>Bu kütüphane MIT lisansı altında lisanslanmıştır, daha fazla bilgi için aÅŸağıdakilere bakın:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">Ayrıca, Creative Commons Atıf-Benzer Paylaşım 4.0 lisansı altında Michael Buckley tarafından oluÅŸturulan Pastel SVG simge setini kullanır.<br/>Bkz.</span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> ayrıntılar için.</span></p></body></html> + + + AddRecordDialog - - Version - Versiyon + + Add New Record + Yeni Kayıt Ekle - - Qt Version - Qt Versiyonu + + Enter values for the new record considering constraints. Fields in bold are mandatory. + Yeni kayıt için kısıtlamaları göz önüne alarak yeni deÄŸerleri giriniz. Kalın vurgulu alanlar zorunludur. - - SQLCipher Version - SQLCipher Versiyonu + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + DeÄŸer sütununda, isim sütunuyla belirtilen alan için deÄŸer belirtebilirsiniz. Tip sütunu alanın tipini belirtir. Varsayılan deÄŸerler NULL ile aynı stilde görüntülenir. - - SQLite Version - SQLite Versiyonu + + Name + İsim - - - Application - - Usage: %1 [options] [db] - - Kullanım: %1 [options] [db] + + Type + Tip - - Possible command line arguments: - Muhtemel komut satırı argümanları: + + Value + DeÄŸer - - -h, --help Show command line options - -h, --help Komut satırı seçeneklerini göster + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + Eklenecek deÄŸerler. Varsayılan olarak doldurulmuÅŸ deÄŸerler, deÄŸiÅŸtirilmedikleri takdirde otomatik olarak ekleneceklerdir. - - -s, --sql [file] Execute this SQL file after opening the DB - -s, --sql [file] veritabanını açtıktan sonra SQL dosyasını yürüt + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + Üstteki bölümdeki deÄŸerleri deÄŸiÅŸtirdiÄŸinizde, yeni kaydı eklemek için kullanılacak sorgu burada görüntülenir. Kaydet butonuna basmadan önce manuel olarak bu sorguyu düzenleyebilirsiniz. - - -q, --quit Exit application after running scripts - -q, --quit Scriptleri çalıştırdıktan sonra programı kapat + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html> <head /> <body> <p> <span style=" font-weight:600;">Kaydet</span> butonu yeni kaydı eklemek için ilgili SQL ifadesini veritabanına gönderir. </p> <p> <span style=" font-weight:600;">Varsayılanları Yükle</span> butonu <span style=" font-weight:600;">DeÄŸer</span> sütunundakileri varsayılanlarına yükler. </p> <p> <span style=" font-weight:600;">İptal</span> butonu sorguyu çalıştırmadan bu pencereyi kapatır. </p> </body> </html> - - [file] Open this SQLite database - [file] SQLite veritabanını aç + + Auto-increment + + Otomatik-Artan + - - The -s/--sql option requires an argument - -s/--sql opsiyonu argüman gerektirir + + Unique constraint + + Benzersiz kısıtı + - - The file %1 does not exist - %1 dosyası mevcut deÄŸil + + Check constraint: %1 + + Kısıtlamayı kontrol et: %1 + - - Invalid option/non-existant file: %1 - Geçersiz seçenek veya mevcut olmayan dosya: %1 + + Foreign key: %1 + + Yabancı anahtar: %1 + - - - CipherDialog - - SQLCipher encryption - SQLCipher ÅŸifreleme + + Default value: %1 + + Varsayılan deÄŸer: %1 + - - &Password - &Parola + + Error adding record. Message from database engine: + +%1 + Kayıt eklenirken hata oluÅŸtu. Veritabanı motoru mesajı: + +%1 - - &Reenter password - &Parolayı tekrar girin + + Are you sure you want to restore all the entered values to their defaults? + Girilen bütün deÄŸerleri varsayılanlarına döndürmek istediÄŸinize emin misiniz? + + + Application - - Page &size - &Sayfa boyutu + + Possible command line arguments: + Muhtemel komut satırı argümanları: - - Please set a key to encrypt the database. -Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. -Leave the password fields empty to disable the encryption. -The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. - Lütfen veritabanını ÅŸifrelemek için anahtar ayarlayın. -Unutmayın, bunun dışında isteÄŸe baÄŸlı yapacağınız herhangi deÄŸiÅŸikliklerde, veritabanı dosyasını her açtığınızda ÅŸifrenizi yeniden girmeniz gerekecektir. -Åžifrelemeyi devre dışı bırakmak için parola alanını boÅŸ bırakınız. -Åžifreleme iÅŸlemi biraz zaman alabilir ve bu iÅŸlemi yapmadan önce veritabanınızın yedeÄŸini almalısınız! KaydedilmemiÅŸ deÄŸiÅŸiklikler ÅŸifreniz deÄŸiÅŸtirilmeden önce kaydedilir. - + + The user settings file location is replaced with the argument value instead of the environment variable value. + Kullanıcı ayarları dosyasının konumu, ortam deÄŸiÅŸkeni deÄŸeri yerine argüman deÄŸeriyle deÄŸiÅŸtirilir. - - Please enter the key used to encrypt the database. -If any of the other settings were altered for this database file you need to provide this information as well. - Lütfen veritabanınızı ÅŸifrelemek için kullandığınız anahtarı giriniz. -Bu veritabanı için herhangi bir baÅŸka ayar daha yapılmışsa, bu bilgileri de saÄŸlamalısınız. + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + Yoksayılan ortam deÄŸiÅŸkeni (DB4S_SETTINGS_FILE) deÄŸeri: - - - CreateIndexDialog - - Create New Index - Yeni İndeks OluÅŸtur + + + The file %1 does not exist + %1 dosyası mevcut deÄŸil - - &Name - &İsim + + Usage + Kullanım - - &Columns - &Sütunlar + + options + seçenekler - - Column - Sütun + + + database + veritabanı - - Use in Index - İndeksin içinde Kullan + + + project + proje - - Order - Sırala + + + csv-file + csv dosyası - - &Table - &Tablo + + Show command line options + Komut satırı seçeneklerini göster - - &Unique - Benzersi&z + + Exit application after running scripts + Betikleri çalıştırdıktan sonra uygulamadan çıkın - - Creating the index failed: -%1 - İndeks oluÅŸturma hatası: %1 + + + file + dosya - - - DBBrowserDB - - - - - no error - hata yok + + Execute this SQL file after opening the DB + Veritabanını açtıktan sonra bu SQL dosyasını çalıştırın - - Please specify the database name under which you want to access the attached database - Lütfen veritabanının ismini eriÅŸmek istediÄŸiniz baÄŸlı veritabanının altında belirtin + + Import this CSV file into the passed DB or into a new DB + Bu CSV dosyasını geçirilen veritabanına veya yeni bir veritabanına aktarın - - Do you want to save the changes made to the database file %1? - %1 veritabanı dosyasında yaptığınız deÄŸiÅŸiklikleri kaydetmek istiyor musunuz? + + table + tablo - - Exporting database to SQL file... - veritabanı SQL dosyası olarak dışa aktarılıyor... + + Browse this table, or use it as target of a data import + Bu tabloya göz atın veya bir veri içe aktarımının hedefi olarak kullanın - - - Cancel - İptal + + Open database in read-only mode + Veritabanını salt okunur modunda aç - - Executing SQL... - SQL yürütülüyor... + + settings_file + settings_file - - Action cancelled. - İşlem iptal edildi. + + Run application based on this settings file + Uygulamayı bu ayar dosyasına göre çalıştır - - - Error in statement #%1: %2. -Aborting execution. - Belirtilen ifadelerde hata var: #%1: %2. Yürütme iÅŸlemi iptal edildi. + + + group + grup - - renameColumn: cannot find table %1. - Sütunu Yeniden Adlandırma: %1 tablosu bulunamadı. + + + settings + ayarlar - - renameColumn: cannot find column %1. - Sütunu Yeniden Adlandırma: %1 sütunu bulunamadı. + + + value + deÄŸer - - renameColumn: creating savepoint failed. DB says: %1 - Sütunu Yeniden Adlandırma: Kayıt noktası oluÅŸturma baÅŸarısız. veritabanı mesajı: %1 + + Run application with this setting temporarily set to value + Bu ayarı geçici deÄŸere ayarlayarak uygulamayı çalıştırın - - renameColumn: creating new table failed. DB says: %1 - Sütunu Yeniden Adlandırma: Yeni tablo oluÅŸturma baÅŸarısız. veritabanı mesajı: %1 + + Run application saving this value for this setting + Bu ayar için bu deÄŸeri kaydederek uygulamayı çalıştırın - - renameColumn: copying data to new table failed. DB says: -%1 - Sütunu Yeniden Adlandırma: Verileri yeni veritabanına kopyalama baÅŸarısız. veritabanı mesajı: %1 + + Display the current version + Mevcut sürümü görüntüle - - renameColumn: deleting old table failed. DB says: %1 - Sütunu Yeniden Adlandırma: Eski veritabanı silme iÅŸlemi baÅŸarısız. veritabanı mesajı: %1 + + Open this SQLite database + Bu SQLite veritabanını açın - - Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: - - - Bu tabloyla iliÅŸkili bazı objelerin restore iÅŸlemi baÅŸarısız. Bu hata büyük olasılıkla sütunların isminin deÄŸiÅŸimden kaynaklanıyor. SQL sorgusunu elle düzeltmek ve yürütmek isterseniz: - - + + Open this project file (*.sqbpro) + Bu proje dosyasını açın (*.sqbpro) - - renameColumn: releasing savepoint failed. DB says: %1 - Sütun Yeniden Adlandırma: Kayıt noktası iÅŸlemi sonlandırılırken hata oluÅŸtu. veritabanı mesajı: %1 + + Import this CSV file into an in-memory database + Bu CSV dosyasını bellek içi bir veritabanına aktarın - - Error renaming table '%1' to '%2'.Message from database engine: -%3 - Tablo '%1' isminden '%2' ismine yeniden adlandırılırken hata oluÅŸtu. veritabanı motorunun mesajı: %3 + + + + The %1 option requires an argument + %1 seçeneÄŸi bir argüman gerektirir + + + + The -S/--settings option requires an argument. The option is ignored. + -S/--settings seçeneÄŸi bir argüman gerektirir. Seçenek yok sayılır. - - ... <string can not be logged, contains binary data> ... - ... <dize ikili veri içeriyor, günlüğe yazılamadı> ... + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + -o/--option ve -O/--save-option opsiyonları grup/ayar=deÄŸer formatında bir argüman gerektirir - - unknown object type %1 - bilinmeyen nesne tipi %1 + + Invalid option/non-existent file: %1 + Geçersiz seçenek veya mevcut olmayan dosya: %1 - - could not get list of db objects: %1, %2 - veritabanı nesnelerinin listesi alınamadı: %1, %2 + + SQLite Version + SQLite Versiyonu - - could not get types - tipler alınamadı + + SQLCipher Version %1 (based on SQLite %2) + SQLCipher Sürümü %1 (%2 SQLite'a dayalı) - - didn't receive any output from pragma %1 - %1 pragmasından herhangi bir çıktı alınamadı + + DB Browser for SQLite Version %1. + DB Browser for SQLite Versiyon %1. - - could not execute pragma command: %1, %2 - pragma komutu yürütülemedi: %1, %2 + + Last commit hash when built: %1 + Derleme sırasında son commit karma deÄŸeri: %1 - - Error setting pragma %1 to %2: %3 - Belirtilen pragma ayarlanırken hata oluÅŸtu: %1 > %2: %3 + + Built for %1, running on %2 + %1 için derlendi, %2 üzerinde çalışıyor - - File not found. - Dosya bulunamadı. + + Qt Version %1 + Qt Sürümü %1 - DbStructureModel + CipherDialog - - Name - İsim + + SQLCipher encryption + SQLCipher ÅŸifrelemesi - - Object - Nesne + + &Password + &Parola - - Type - Tip + + &Reenter password + Pa&rolayı tekrar girin - - Schema - Åžema + + Encr&yption settings + Åžifreleme A&yarları - - Tables (%1) - Tablolar (%1) + + SQLCipher &3 defaults + SQLCipher &3 varsayılanları - - Indices (%1) - İndeksler (%1) + + SQLCipher &4 defaults + SQLCipher &4 varsayılanları - - Views (%1) - Görünümler (%1) + + Custo&m + &Özel - - Triggers (%1) - Tetikleyiciler (%1) + + Page si&ze + &Sayfa boyutu - - - EditDialog - - Edit database cell - veritabanı hücresini düzenle + + &KDF iterations + &KDF yinelemeleri - - Import text - Metin aktar + + HMAC algorithm + HMAC algoritması - - Opens a file dialog used to import text to this database cell. - veritabanı hücresine metin aktarmak için dosya diyaloÄŸunu açar. + + KDF algorithm + KDF algoritması - - &Import - &İçe Aktar + + Plaintext Header Size + Düz Metin Üst Bilgi Boyutu - - Export text - Metni dışa aktar + + Passphrase + Parola - - Opens a file dialog used to export the contents of this database cell to a text file. - veritabanı hücresindeki metni metin dosyası olarak dışa aktarmak için dosya diyaloÄŸunu açar. + + Raw key + Ham anahtar - - &Export - &Dışa Aktar + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + Lütfen veritabanını ÅŸifrelemek için anahtar ayarlayın. +Unutmayın, bunun dışında isteÄŸe baÄŸlı yapacağınız herhangi deÄŸiÅŸikliklerde, veritabanı dosyasını her açtığınızda ÅŸifrenizi yeniden girmeniz gerekecektir. +Åžifrelemeyi devre dışı bırakmak için parola alanını boÅŸ bırakınız. +Åžifreleme iÅŸlemi biraz zaman alabilir ve bu iÅŸlemi yapmadan önce veritabanınızın yedeÄŸini almalısınız! KaydedilmemiÅŸ deÄŸiÅŸiklikler ÅŸifreniz deÄŸiÅŸtirilmeden önce kaydedilir. - - Text - Metin + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + Lütfen veritabanınızı ÅŸifrelemek için kullandığınız anahtarı giriniz. +Bu veritabanı için herhangi bir baÅŸka ayar daha yapılmışsa, bu bilgileri de saÄŸlamalısınız. + + + ColumnDisplayFormatDialog - - Binary - İkili + + Choose display format + Görüntüleme formatını seçin - - Clear cell data - Hücredeki veriyi temizle + + Display format + Formatı görüntüle - - Erases the contents of the cell - Hücre içeriÄŸini siler + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + Her deÄŸer gösterilmeden önce, '%1' sütunu için uygulanacak bir görüntüleme biçimi seçin. - - &Clear - &Temizle + + Default + Varsayılan - - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Warning: Editing binary content in text mode may result in corrupted data!</span></p></body></html> - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Uyarı: İkili veriyi metin modunda düzenlemek verinin bozulmasına neden olabilir!</span></p></body></html> + + Decimal number + Ondalık sayı - - This area displays information about the data present in this database cell - Bu alan veritabanı hücresinin içindeki içerik hakkında bilgileri görüntüler + + Exponent notation + Üslü gösterim - - Type of data currently in cell - Åžuan da hücrenin içinde bulunan verinin tipi + + Hex blob + Onaltılık blob - - Size of data currently in table - Åžuan da tablonun içinde bulunan verinin boyutu + + Hex number + Onaltılık sayı - - Choose a file - Dosya seçiniz + + Apple NSDate to date + Apple NSDate tipinden tarih tipine - - Text files(*.txt);;Image files(%1);;All files(*) - Metin dosyaları(*.txt);;Resim dosyaları(%1);;Tüm dosyalar(*) + + Java epoch (milliseconds) to date + Java epoch (milisaniye) tipinden tarih tipine - - Choose a filename to export data - Veriyi dışa aktarmak için dosya ismi seçiniz + + .NET DateTime.Ticks to date + .NET DateTime.Ticks tarihine - - Text files(*.txt);;All files(*) - Metin dosyaları(*.txt);;Tüm dosyalar(*) + + Julian day to date + Julian day tipinden tarih tipine - - Type of data currently in cell: Null - Åžuan da hücresinin içinde bulunan verinin tipi: BoÅŸ + + Unix epoch to local time + Unix epoch tipinden yerel zaman tipine - - Type of data currently in cell: Text / Numeric - Åžuan da hücresinin içinde bulunan verinin tipi: Metin / Nümerik + + WebKit / Chromium epoch to date + WebKit / Chromium'un bugüne kadarki tarihi - - - %n char(s) - - %n karakter - + + + WebKit / Chromium epoch to local time + WebKit / Chromium dönemi yerel zamana göre - - Type of data currently in cell: Image - Åžuan da hücresinin içinde bulunan verinin tipi: Resim + + Date as dd/mm/yyyy + dd/mm/yyyy tarih formatı - - %1x%2 pixel - %1x%2 piksel + + Lower case + Küçük harf - - Type of data currently in cell: Binary - Åžuan da hücresinin içinde bulunan verinin tipi: İkili Veri + + Binary GUID to text + İkili GUID'den metne - - - %n byte(s) - - %n bayt - + + + SpatiaLite Geometry to SVG + SpatiaLite Geometriden SVG'ye - - - EditTableDialog - - Edit table definition - Tablo tanımını düzenle + + Custom display format must contain a function call applied to %1 + Özel görüntüleme formatı, %1 için uygulanan fonksiyon çaÄŸrısı içermelidir - - Table - Tablo + + Error in custom display format. Message from database engine: + +%1 + Özel görüntüleme formatınde hata oluÅŸtu. Veritabanı motoru mesajı: + +%1 - - Advanced - GeliÅŸmiÅŸ + + Custom display format must return only one column but it returned %1. + Özel görüntüleme formatı sadece bir sütun döndürmeli: %1. - - Make this a 'WITHOUT rowid' table. Setting this flag requires a field of type INTEGER with the primary key flag set and the auto increment flag unset. - Tabloyu satır ID'si olmadan ayarlayın. Bu ayar için, Tamsayı(Integer) tipinde otomatik arttır özelliÄŸi olmayan ve birincil anahtar olarak ayarlanmış bir alan gerekli. + + Octal number + Sekizlik sayı - - Without Rowid - Satır ID(Rowid) Kullanma + + Round number + Küsuratsız sayı - - Fields - Alanlar + + Unix epoch to date + Unix epoch tipinden tarih tipine - - Add field - Alan Ekle + + Upper case + Büyük harf - - Remove field - Alanı kaldır + + Windows DATE to date + Windows DATE tipinden tarih tipine - - Move field up - Alanı yukarı taşı + + Custom + Özel + + + CondFormatManager - - Move field down - Alanı aÅŸağı taşı + + Conditional Format Manager + KoÅŸullu Biçim Yöneticisi - - Name - İsim + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + Bu iletiÅŸim kutusu koÅŸullu biçimler oluÅŸturmaya ve düzenlemeye izin verir. Her hücre stili, hücre verisi için ilk saÄŸlanan koÅŸul tarafından seçilecektir. KoÅŸullu biçimler yukarı ve aÅŸağı taşınabilir, üst sıralardakiler alt sıralardakilere göre önceliklidir. KoÅŸullar için sözdizimi, filtreler ile aynıdır ve boÅŸ koÅŸullar tüm hücreler için geçerlidir. - - Type - Tip + + Add new conditional format + Yeni koÅŸullu biçim oluÅŸtur - - - Not null - NULL Olamaz + + &Add + &Ekle - - PK - Birincil Anahtar + + Remove selected conditional format + Seçilen koÅŸullu biçimi sil - - Primary key - Birincil Anahtar + + &Remove + Kaldı&r - - AI - Otomatik Arttırma + + Move selected conditional format up + Seçilen koÅŸullu biçimi yukarı taşı - - Autoincrement - Otomatik Arttırma + + Move &up + Y&ukarı taşı - - U - Benzersiz + + Move selected conditional format down + Seçilen koÅŸullu biçimi aÅŸağı taşı - - Unique - Benzersiz + + Move &down + AÅŸağı &taşı - - Default - Varsayılan + + Foreground + Ön plan - - Default value - Varsayılan deÄŸer + + Text color + Metin rengi - - Check - Kontrol + + Background + Arka plan - - Check constraint - Kısıtlama Kontrol + + Background color + Arka plan rengi - - Foreign Key - Yabancı Anahtar + + Font + Yazı tipi - - Error creating table. Message from database engine: -%1 - Tablo oluÅŸturma hatası. veritabanı motorunun mesajı: %1 + + Size + Boyut - - There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. - Tablonuzun en az bir satırında boÅŸ bırakılmış alan var. Bu sebeple bu özelliÄŸi etkinleÅŸtirmek imkansız. Lütfen ilk önce tablonuzdaki veriyi deÄŸiÅŸtirin. + + Bold + Kalın - - There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. - Tablonuzun en az bir satırında tamsayı dışında deÄŸer içeren alan var. Bu sebeÄŸle otomatik arttır özelliÄŸini etkinleÅŸtirmek imkansız. Lütfen ilk önce tablonuzdaki veriyi deÄŸiÅŸtirin. + + Italic + İtalik - - Column `%1` has no unique data. - - `%1` sütununda benzersiz veri yok + + Underline + Altı çizili - - This makes it impossible to set this flag. Please change the table data first. - Bu sebeple bu özelliÄŸi etkinleÅŸtirmek imkansız. Lütfen ilk önce tablonuzdaki veriyi deÄŸiÅŸtirin. + + Alignment + Hizalama - - Are you sure you want to delete the field '%1'? -All data currently stored in this field will be lost. - Gerçekten '%1' alanını silmek istediÄŸinize emin misiniz? Bu alanda mevcut bütün verilerinizi kaybedeceksiniz. + + Condition + KoÅŸul - - Please add a field which meets the following criteria before setting the without rowid flag: - - Primary key flag set - - Auto increment disabled - Lütfen 'Satır ID(Rowid) Kullanma' özelliÄŸini etkinleÅŸtirmek için öncelikle aÅŸağıdaki ölçütleri karşılayan alan ekleyin: -- Birincil anahtar ayarlayın -- Otomatik arttır ayarını devre dışı bırakın + + + Click to select color + Renk seçmek için tıklayın + + + + Are you sure you want to clear all the conditional formats of this field? + Bu alanın tüm koÅŸullu biçimlerini silmek istediÄŸinizden emin misiniz? - ExportCsvDialog + DBBrowserDB - - Export data as CSV - Veriyi CSV olarak dışa aktar + + Please specify the database name under which you want to access the attached database + Lütfen veritabanının ismini eriÅŸmek istediÄŸiniz baÄŸlı veritabanının altında belirtin - - &Table(s) - &Tablo(lar) + + Invalid file format + Geçersiz dosya formatı - - &Column names in first line - &Sütun isimleri ilk satırda + + Do you want to save the changes made to the database file %1? + %1 veritabanı dosyasında yaptığınız deÄŸiÅŸiklikleri kaydetmek istiyor musunuz? - - Field &separator - Alan &ayracı + + Exporting database to SQL file... + Veritabanı, SQL dosyası olarak dışa aktarılıyor... - - , - , + + + Cancel + İptal - - ; - ; + + Executing SQL... + SQL yürütülüyor... - - - Tab - Tab karakteri + + Action cancelled. + İşlem iptal edildi. - - | - | + + Do you really want to close this temporary database? All data will be lost. + Gerçekten geçici veritabanını kapatmak istiyor musunuz? Bütün veriler kaybedilecek. - - - Other - DiÄŸer... + + Database didn't close correctly, probably still busy + Veritabanı doÄŸru bir ÅŸekilde kapatılamadı, muhtemelen hâlâ kullanımda - - &Quote character - & Tırnak karakteri + + Cannot open destination file: '%1' + Hedef dosya açılamıyor: '%1' - - " - " + + + Cannot backup to file: '%1'. Message: %2 + Dosyaya yedekleme yapılamıyor: '%1'. Mesaj: %2 - - ' - ' + + The database is currently busy: + Veritabanı ÅŸu anda meÅŸgul: - - Could not open output file: %1 - OluÅŸturulan dosya açılamadı: %1 + + Do you want to abort that other operation? + DiÄŸer iÅŸlemi iptal etmek istiyor musunuz? - - - Choose a filename to export data - Verileri dışarı aktarmak için dosya ismi seçiniz + + + No database file opened + Hiçbir veritabanı dosyası açılmamış - - - Text files(*.csv *.txt) - Metin dosyaları(*.csv *.txt) + + + Error in statement #%1: %2. +Aborting execution%3. + Belirtilen ifadede hata oluÅŸtu: #%1: %2 +Yürütme durduruluyor %3. - - Please select at least 1 table. - Lütfen en az 1 tablo seçiniz. + + + and rolling back + ve iÅŸlem geri alınıyor - - Choose a directory - Dizin seçiniz + + didn't receive any output from %1 + %1 sorgusundan herhangi bir çıktı alınamadı - - Export completed. - Dışa aktarma tamamlandı. + + could not execute command: %1 + komut iÅŸletilemedi: %1 - - - ExportSqlDialog - - Export SQL... - SQL dosyasını dışa aktar... + + Cannot delete this object + Bu obje silinemiyor - - &Table(s) - &Tablo(lar) + + Cannot set data on this object + Bu objeye veri atanamıyor - - &Options - &Seçenekler + + + A table with the name '%1' already exists in schema '%2'. + '%2' ÅŸemasında '%1' isimli tablo zaten mevcut. - - Keep column names in INSERT INTO - INSERT ve INTO komutlarında sütun isimlerini tut + + No table with name '%1' exists in schema '%2'. + '%2' ÅŸeması içerisinde '%1' isminde bir tablo yok. - - New INSERT INTO syntax (multiple rows in VALUES) - Çok satırlı veri giriÅŸi için yeni 'INSERT INTO' söz dizimini ekle + + + Cannot find column %1. + %1 sütunu bulunamadı. - - Export schema only - Sadece ÅŸemayı dışa aktar + + Creating savepoint failed. DB says: %1 + Kayıt noktası oluÅŸturulamadı. DB mesajı: %1 - - Please select at least 1 table. - En az 1 tane tablo seçiniz. + + Renaming the column failed. DB says: +%1 + Sütun yeniden adlandırılamadı. DB mesajı: +%1 - - Choose a filename to export - Dışa aktarmak için dosya ismi seçiniz + + + Releasing savepoint failed. DB says: %1 + Kayıt noktasının serbest bırakılması baÅŸarısız. DB mesajı: %1 - - Text files(*.sql *.txt) - Metin dosyaları(*.sql *.txt) + + Creating new table failed. DB says: %1 + Veritabanı oluÅŸturulamadı. DB mesajı: %1 - - Export completed. - Dışa aktarma tamamlandı. + + Copying data to new table failed. DB says: +%1 + Yeni tabloya veri kopyalanamadı. DB mesajı: +%1 - - Export cancelled or failed. - Dışa aktarma iptal edildi veya baÅŸarısız. + + Deleting old table failed. DB says: %1 + Eski tablolar silinemedi: DB mesajı: %1 - - - FilterLineEdit - - Filter - Filtre + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + '%1' tablosu '%2' olarak adlandırılırken hata oluÅŸtu. +Veritabanı motoru mesajı: +%3 - - - ImportCsvDialog - - Import CSV file - CSV dosyasını içe aktar + + could not get list of db objects: %1 + veritabanı objelerinin listesi alınamadı: %1 - - &Table name - &Tablo ismi + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + Bu tabloyla iliÅŸkili bazı objelerin restore iÅŸlemi baÅŸarısız. Bu hata büyük olasılıkla sütunların isminin deÄŸiÅŸimden kaynaklanıyor. SQL sorgusunu elle düzeltmek ve yürütmek isterseniz: + + - - &Column names in first line - &Sütun isimleri ilk satırda + + could not get list of databases: %1 + veritabanı listesi alınamadı: %1 - - Field &separator - Alan &ayracı + + Error loading extension: %1 + Eklenti yüklenirken hata oluÅŸtu: %1 - - , - , + + Error loading built-in extension: %1 + YerleÅŸik uzantı yüklenirken hata oluÅŸtu: %1 - - ; - ; + + could not get column information + sütun bilgisi alınamadı - - - Tab - Tab karakteri + + Error setting pragma %1 to %2: %3 + Belirtilen pragma ayarlanırken hata oluÅŸtu: %1 > %2: %3 - - | - | + + File not found. + Dosya bulunamadı. + + + DbStructureModel - - - - Other - DiÄŸer... + + Name + İsim - - &Quote character - &Tırnak karakteri + + Object + Obje - - " - " + + Type + Tür - - ' - ' + + Schema + Åžema - - &Encoding - &Kodlama + + Database + Veritabanı - - UTF-8 - UTF-8 + + Browsables + Görüntülenebilir olanlar - - UTF-16 - UTF-16 + + All + Tümü - - ISO-8859-1 - ISO-8859-1 + + Temporary + Geçici - - Trim fields? - Alanlar biçimlendirilsin mi? + + Tables (%1) + Tablolar (%1) - - Inserting data... - Veri ekleniyor... + + Indices (%1) + İndeksler (%1) - - Cancel - İptal + + Views (%1) + Görünümler (%1) - - There is already a table of that name and an import into an existing table is only possible if the number of columns match. - Zaten aynı isimde tablo mevcut. Varolan tablonun üstüne yazmak ancak sütunların sayısı eÅŸitse mümkün olabilir. + + Triggers (%1) + Tetikleyiciler (%1) + + + EditDialog - - There is already a table of that name. Do you want to import the data into it? - Zaten aynı isimde tablo mevcut. Verileri bu tablonun içine aktarmak istiyor musunuz? + + Edit database cell + Veritabanı hücresini düzenle - - Creating restore point failed: %1 - Geri yükleme noktası oluÅŸturma baÅŸarısız: %1 + + Mode: + Mod: - - Creating the table failed: %1 - Tablo oluÅŸturma baÅŸarısız: %1 + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + Bu, hücre düzenleyicisi için desteklenen modların listesidir. Geçerli hücrenin verilerini görüntülemek veya düzenlemek için bir mod seçin. - - Missing field for record %1 - %1 kayıtı için eksik alan + + RTL Text + SaÄŸdan Sola Okunan Metin - - Inserting row failed: %1 - Satır ekleme baÅŸarısız: %1 + + + Image + Görüntü - - - MainWindow - - DB Browser for SQLite - SQLite DB Browser + + JSON + JSON - - Database &Structure - Veritabanı &Yapısı + + XML + XML - - - toolBar1 - toolBar1 + + Evaluation + DeÄŸerlendirme - - &Browse Data - &Verileri Görüntüle + + + Automatically adjust the editor mode to the loaded data type + Düzenleyici modunu otomatik olarak yüklenen veri tipine ayarlar - - Table: - Tablo: + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + Bu onay kutusu, editör modunun otomatik olarak deÄŸiÅŸtirilmesini etkinleÅŸtirir veya devre dışı bırakır. Bu kutucuk iÅŸaretliyken, yeni bir hücre seçildiÄŸinde veya yeni veriler içe aktarıldığında, mod algılanan veri türüne göre ayarlanır. Daha sonra editör modunu manuel olarak deÄŸiÅŸtirebilirsiniz. Hücreler arasında hareket ederken bu manuel modu korumak isterseniz, kutucuÄŸun iÅŸaretini kaldırın. - - Select a table to browse data - Verileri görüntülemek için tablo seçiniz + + Auto-switch + Otomatik geçiÅŸ - - Use this list to select a table to be displayed in the database view - Veritabanı görünümünde gösterilecek tabloyu seçmek için bu listeyi kullanın + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + Qt editör, varsayılan metin editörü tarafından desteklenmeyen saÄŸdan sola okunan dillde yazılmış betikler için kullanılır. - - Refresh the data in the selected table. - Seçilen tablodaki verileri yenileyin. + + Identification of the cell currently in the editor + Åžu anda düzenleyicide bulunan hücrenin tanımlanması - - This button refreshes the data in the currently selected table. - Bu buton, seçilen tablodaki verileri yeniler. + + Type and size of data currently in table + Tabloda ÅŸu anda bulunan verilerin türü ve boyutu - - - F5 - F5 + + Open preview dialog for printing the data currently stored in the cell + Åžu anda hücrede saklanan veriyi yazdırmak için ön izleme penceresini aç - - Clear all filters - Tüm filtreleri temizle + + Auto-format: pretty print on loading, compact on saving. + Otomatik format: yüklenirken aÅŸamasında kaliteli baskı, kayıt açısından da tasarrufludur. - - Insert a new record in the current table - Geçerli tabloya yeni kayıt ekle + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + EtkinleÅŸtirildiÄŸinde, otomatik biçimlendirme özelliÄŸi yükleme sırasında verileri biçimlendirir, metni satırlara böler ve maksimum okunabilirlik için girintili yapar. Veri kaydederken otomatik biçimlendirme özelliÄŸi, satır sonu karakterlerini ve gereksiz boÅŸlukları kaldırarak verileri sıkıştırır. - - This button creates a new, empty record in the database - Bu buton, veritabanında yeni bir boÅŸ kayıt oluÅŸturur. + + Word Wrap + Kelime Kaydırma - - New Record - Yeni Kayıt + + Wrap lines on word boundaries + Kelime sınırlarında kelimeyi kaydırır - - Delete the current record - Geçerli kaydı sil + + + Open in default application or browser + Varsayılan program veya görüntüleyicide aç - - This button deletes the record currently selected in the database - Bu buton, veritabanında seçilen geçerli kayıtları siler + + Open in application + Uygualamada aç - - Delete Record - Kaydı Sil + + The value is interpreted as a file or URL and opened in the default application or web browser. + DeÄŸe,r bir dosya veya URL olarak yorumlanır ve varsayılan uygulamada veya web tarayıcısında açılır. - - This is the database view. You can double-click any record to edit its contents in the cell editor window. - Bu veritabanı görünümüdür. Herhangi kayda çift tıklayarak hücre içeriÄŸini hücre editör penceresinde düzenleyebilirsiniz. + + Save file reference... + Dosya referansını kaydet... - - <html><head/><body><p>Scroll to the beginning</p></body></html> - <html><head/><body><p>BaÅŸa sürükle</p></body></html> + + Save reference to file + Referansı dosyaya kaydet - - <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> - <html><head/><body><p>Bu butona basıldığında üstteki tablo görünümünün baÅŸlangıcına kaydırılır.</p></body></html> + + + Open in external application + Harici bir programda aç - - |< - |< + + Autoformat + Otomatik format - - Scroll 100 records upwards - 100 kayıt kadar yukarı kaydır + + &Export... + D&ışa aktar... - - <html><head/><body><p>Clicking this button navigates 100 records upwards in the table view above.</p></body></html> - <html><head/><body><p>Bu butona basıldığında üstteki tablo görünümünün 100 kayıt kadar yukarısına kaydırılır.</p></body></html> + + + &Import... + &İçe aktar... - - < - < + + + Import from file + Dosyadan içe aktar - - 0 - 0 of 0 - 0 - 0 / 0 + + + Opens a file dialog used to import any kind of data to this database cell. + Veritabanı hücresine herhangi bir tipte veri yüklemek için bir dosya iletiÅŸim kutusu açar. - - <html><head/><body><p>Scroll 100 records downwards</p></body></html> - <html><head/><body><p>100 kayıt kadar aÅŸağı kaydır</p></body></html> + + Export to file + Dosyaya aktar - - <html><head/><body><p>Clicking this button navigates 100 records downwards in the table view above.</p></body></html> - <html><head/><body><p>Bu butona basıldığında üstteki tablo görünümünün 100 kayıt kadar aÅŸağısına kaydırılır.</p></body></html> + + Opens a file dialog used to export the contents of this database cell to a file. + Veritabanı hücresinin içeriÄŸini bir dosyaya aktarmak için kullanılan bir dosya iletiÅŸim kutusu açar. - - > - > + + Print... + Yazdır... - - Scroll to the end - Sona sürükle + + Ctrl+P + - - <html><head/><body><p>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Clicking this button navigates up to the end in the table view above.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html> - <html><head/><body><p>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Bu butona basıldığında üstteki tablo görünümünün en sonuna kaydırılır.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html> + + Open preview dialog for printing displayed text + Görüntülenen metni yazdırmak için ön izleme penceresini aç - - >| - >| + + Copy Hex and ASCII + Onaltılık ve ASCII deÄŸerini kopyala - - <html><head/><body><p>Click here to jump to the specified record</p></body></html> - <html><head/><body><p>İstediÄŸiniz kayda atlamak için buraya tıklayın</p></body></html> + + Copy selected hexadecimal and ASCII columns to the clipboard + Seçilen onaltılık ve ASCII sütunlarını panoya kopyala - - <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> - <html><head/><body><p>Bu buton belirtilen kayıt numarasına gitmek için kullanılır.</p></body></html> + + Ctrl+Shift+C + - - Go to: - Bu kayda gidin: + + Set as &NULL + &NULL olarak ayarla - - Enter record number to browse - Görüntülemek için kayıt numarasını giriniz + + Apply data to cell + Veriyi hücreye uygula - - Type a record number in this area and click the Go to: button to display the record in the database view - Bu alana veritabanı görünümünde görüntülemek istediÄŸiniz kayıt numarasını giriniz ve Bu kayda gidin: butonuna tıklayınız + + This button saves the changes performed in the cell editor to the database cell. + Bu buton, hücre editöründe yapılan deÄŸiÅŸiklikleri veritabanı hücresine kaydeder. - - 1 - 1 + + Apply + Uygula - - Edit &Pragmas - &Pragmaları Düzenleyin + + Text + Metin - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> + + Binary + İkili - - - - None - None + + Erases the contents of the cell + Hücre içeriÄŸini siler - - - Full - Full + + This area displays information about the data present in this database cell + Bu alan veritabanı hücresinin içindeki içerik hakkında bilgileri görüntüler - - Incremental - Incremental + + Choose a filename to export data + Veriyi dışa aktarmak için dosya ismi seçiniz - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> + + + Image data can't be viewed in this mode. + Imaj verisi bu modda görüntülenemiyor. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + Metin düzenleyici modları, sözdizimi vurgulama, otomatik biçimlendirme ve kaydetmeden önce doÄŸrulama ile düz metinlerin yanı sıra JSON veya XML verilerini düzenlemenize olanak tanır. + +Hatalar kırmızı kıvrımlı alt çizgiyle gösterilir. + +DeÄŸerlendirme modunda, girilen SQLite ifadeleri deÄŸerlendirilir ve sonuç hücreye uygulanır. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></a></p></body></html> + + Unsaved data in the cell editor + Hücre düzenleyicide kaydedilmemiÅŸ veriler - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + Hücre düzenleyicisi henüz veritabanına uygulanmamış veriler içeriyor. +Düzenlenen verileri satır=%1, sütun=%2'ye uygulamak ister misiniz? - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> + + Editing row=%1, column=%2 + Satır=%1, sütun=%2 düzenleniyor - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> + + No cell active. + Hiçbir hücre aktif deÄŸil. - - Delete - Delete + + + Try switching to Image or Binary mode. + Görüntü veya İkili mod arasında geçiÅŸ yapın. - - Truncate - Truncate + + + Binary data can't be viewed in this mode. + İkili veri bu modda görüntülenemiyor. - - Persist - Persist + + + Try switching to Binary mode. + İkili veri moduna geçmeyi deneyin. - - - Memory - Memory + + + Image files (%1) + Görüntü dosyaları (%1) - - WAL - WAL + + Binary files (*.bin) + İkili dosyalar (*.bin) - - - Off - Off + + + Type: NULL; Size: 0 bytes + Tür: NULL; Boyut: 0 bayt + + + + + Type: Text / Numeric; Size: %n character(s) + + + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> + + Type: %1 Image; Size: %2x%3 pixel(s) + Tür: %1 Görüntü; Boyut: %2x%3 piksel + + + + Type: Valid JSON; Size: %n character(s) + + Tür: Geçerli JSON; Boyut: %n karakter + + + + + Type: Binary; Size: %n byte(s) + + Tür: İkili; Boyut: %n bayt + - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a></p></body></html> + + Choose a file to import + İçe aktarmak için dosya seçin - - - Normal - Normal + + %1 Image + %1 Görüntü - - Exclusive - Exclusive + + Invalid data for this mode + Bu mod için geçersiz veri - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + Hücre geçersiz %1 verisi içeriyor. Sebep: %2. Bu deÄŸiÅŸikliÄŸi hücreye gerçekten uygulamak istiyor musunuz? - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> + + Couldn't save file: %1. + Dosya kaydedilemedi: %1. - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + Veriler geçici bir dosyaya kaydedildi ve varsayılan uygulamayla açıldı. Artık dosyayı düzenleyebilir ve hazır olduÄŸunuzda kaydedilen yeni verileri hücreye uygulayabilir veya deÄŸiÅŸiklikleri iptal edebilirsiniz. + + + EditIndexDialog - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> + + &Name + &İsim - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> + + Order + Sırala - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> + + &Table + &Tablo - - Default - Default + + Edit Index Schema + İndeks Åžemasını Düzenle - - File - File + + &Unique + Benzersi&z - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + İndeksi tablonun yalnızca bir bölümüyle sınırlamak için, burada tablonun dizine alınması gereken kısmını seçen bir WHERE deyimi belirtebilirsiniz - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> + + Partial inde&x clause + Kısmi inde&ks hükmü - - E&xecute SQL - SQL Kodunu &Çalıştır + + Colu&mns + Sütu&nlar - - &File - &Dosya + + Table column + Tablo sütunu - - &Import - &İçe Aktar + + Type + Tür - - &Export - &Dışa Aktar + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + İndeks için yeni bir ifade sütunu ekleyin. İfade sütunları, sütun adları deÄŸil SQL ifadesi içerir. - - &Edit - Düz&enle + + Index column + İndeks sütunu - - &View - &Görünüm + + Deleting the old index failed: +%1 + Eski indeks silinemedi: +%1 - - &Help - &Yardım + + Creating the index failed: +%1 + İndeks oluÅŸturma hatası: %1 + + + EditTableDialog - - DB Toolbar - Veritabanı Araç ÇubuÄŸu + + Edit table definition + Tablo tanımını düzenle - - SQL Log - SQL Günlüğü + + Table + Tablo - - &Show SQL submitted by - &Åžunun tarafından gönderilen SQL kodunu göster: + + Advanced + GeliÅŸmiÅŸ - - User - Kullanıcı + + Without Rowid + Rowid olmadan - - Application - Uygulama + + Database sche&ma + Veritabanı ÅŸe&ması - - &Clear - &Temizle + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + Bunu 'WITHOUT ROWID' tablosu yapın. Bu bayrağı ayarlamak, bir PRIMARY KEY (herhangi bir türde ve bileÅŸik olabilir) belirtmeyi gerektirir ve AUTOINCREMENT bayrağını yasaklar. - - Plot - Plan + + On Conflict + On Conflict + + + + Strict + Strict + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + Strict seçeneÄŸi etkinleÅŸtirildiÄŸinde SQLite, veri güncellerken veya eklerken her sütunun veri türlerini uygular. + + + + Fields + Alanlar + + + + + + Add + Ekle + + + + + + Remove + Kaldır + + + + Move to top + En üste taşı + + + + Move up + Yukarı taşı + + + + Move down + AÅŸağı taşı + + + + Move to bottom + En alta taşı + + + + + + + Name + İsim - + + + Type + Tür + + + + NN + NN + + + + Not null + NULL deÄŸil + + + + PK + PK + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> Birincil anahtar</p></body></html> + + + + AI + Otomatik Arttırma + + + + Autoincrement + Otomatik Arttırma + + + + U + U + + + + + + Unique + Benzersiz + + + + Default + Varsayılan + + + + Default value + Varsayılan deÄŸer + + + + + Check + Kontrol + + + + Check constraint + Kısıtlama kontrolü + + + + Collation + KarşılaÅŸtırma + + + + Foreign Key + Yabancı Anahtar + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_fk"/> Yabancı Anahtar</p></body></html> + + + + Index Constraints + İndeks Kısıtlamaları + + + + Add constraint + Kısıt ekle + + + + Remove constraint + Kısıtı kaldır + + + + Columns - Sütun + Sütunlar - - X - X + + + + SQL + SQL - - Y - Y + + Foreign Keys + Yabancı Anahtarlar - - _ - _ + + References + Referanslar - - Line type: - Çizgi Tipi: + + Check Constraints + Kontrol Kısıtlamaları - - Line - Çizgi + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html> <head /> <body> <p> <span style=" font-weight:600; color:#ff0000;">Uyarı: </span>Bu tablo tanımında ayrıştırıcının tam olarak anlayamadığı bir ÅŸey var. Bu tabloyu deÄŸiÅŸtirmek ve kaydetmek sorunlara neden olabilir. </p> </body> </html> - - StepLeft - Sola Basamakla + + + Primary Key + Birincil Anahtar - - StepRight - SaÄŸa Basamakla + + Add a primary key constraint + Birinci anahtar kısıtlaması ekle - - StepCenter - Merkeze Basamakla + + Add a unique constraint + Benzersiz kısıtı ekle - - Impulse - Kaydırmalı + + + There can only be one primary key for each table. Please modify the existing primary key instead. + Her tabloda yalnızca bir birincil anahtar bulunabilir. Mevcut birincil anahtarı düzenlemeyi denedin. - - Point shape: - Nokta Åžekli: + + Error creating table. Message from database engine: +%1 + Tablo oluÅŸturma hatası. veritabanı motorunun mesajı: %1 - - Cross - Çarpı + + There already is a field with that name. Please rename it first or choose a different name for this field. + Bu isimde bir alan zaten var. Lütfen önce bu alanı yeniden adlandırın veya farklı bir isim seçin. - - Plus - Artı + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + Tablonuzun en az bir satırında boÅŸ bırakılmış alan var. Bu sebeple bu özelliÄŸi etkinleÅŸtirmek imkansız. Lütfen ilk önce tablonuzdaki veriyi deÄŸiÅŸtirin. - - Circle - Daire + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + Tablonuzun en az bir satırında tamsayı dışında deÄŸer içeren alan var. Bu sebeÄŸle otomatik arttır özelliÄŸini etkinleÅŸtirmek imkansız. Lütfen ilk önce tablonuzdaki veriyi deÄŸiÅŸtirin. - - Disc - Disk + + Column '%1' has duplicate data. + + '%1' sütununda yinelenen veriler var. + - - Square - Kare + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + Åžu anda 'Benzersiz' kısıtı eklenmesi imkansız.'Benzersiz' kısıtını ekleyebilmek için lütfen yinelenen deÄŸerleri silin. - - Diamond - Elmas + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + Lütfen çakışma eylemini ayarlamadan önce aÅŸağıdaki ölçütleri karşılayan bir alan ekleyin: + - Birincil anahtar bayrağı ayarı - - Star - Yıldız + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + Bu sütun%1 tablosundaki yabancı bir anahtar tarafından referans alınıyor, bu nedenle adı deÄŸiÅŸtirilemez. - - Triangle - Üçgen + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + Gerçekten '%1' alanını silmek istediÄŸinize emin misiniz? Bu alanda mevcut bütün verilerinizi kaybedeceksiniz. - - TriangleInverted - Ters Üçgen + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + Lütfen 'Satır ID(Rowid) Kullanma' özelliÄŸini etkinleÅŸtirmek için öncelikle aÅŸağıdaki ölçütleri karşılayan alan ekleyin: +- Birincil anahtar ayarlayın +- Otomatik arttır ayarını devre dışı bırakın + + + ExportDataDialog - - CrossSquare - Çapraz Kare + + Export data as CSV + Veriyi CSV olarak dışa aktar - - PlusSquare - Kare İçinde Artı + + Tab&le(s) + Tab&lo(lar) - - CrossCircle - Daire İçinde Çarpı + + Colu&mn names in first line + Sütu&n isimleri ilk satırda - - PlusCircle - Daire İçinde Artı + + Fie&ld separator + A&lan ayracı - - Peace - Barış Simgesi + + , + , - - <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> - <html><head/><body><p>Geçerli planı kaydedin...</p><p>Dosya formatı eklenti tarafından seçilmiÅŸ (png, jpg, pdf, bmp)</p></body></html> + + ; + ; - - Save current plot... - Geçerli planı kaydet... + + Tab + Tab karakteri - - DB Schema - Veritabanı Åžeması + + | + | - - &New Database... - Ye&ni Veritabanı... + + + + Other + DiÄŸer - - - Create a new database file - Yeni bir veritabanı dosyası oluÅŸtur + + &Quote character + &Tırnak karakteri - - This option is used to create a new database file. - Bu seçenek yeni bir veritabanı dosyası oluÅŸturmak için kullanılır. + + " + " - - Ctrl+N - Ctrl+N + + ' + ' - - &Open Database... - &Veritabanı Aç... + + New line characters + Yeni satır karakterleri - - - Open an existing database file - Mevcut veritabanı dosyasını aç + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) - - This option is used to open an existing database file. - Bu seçenek mevcut veritabanı dosyasını açmak için kullanılır. + + Unix: LF (\n) + Unix: LF (\n) - - Ctrl+O - Ctrl+O + + Pretty print + Güzel baskı - - &Close Database - Veritabanı &Kapat + + + Could not open output file: %1 + OluÅŸturulan dosya açılamadı: %1 - - Ctrl+W - Ctrl+W + + + Choose a filename to export data + Verileri dışarı aktarmak için dosya ismi seçiniz - - Revert Changes - DeÄŸiÅŸiklikleri Geri Al + + Export data as JSON + Veriyi JSON olarak dışa aktar - - Revert database to last saved state - Veritabanını en son kaydedilen duruma döndür + + exporting CSV + CSV dışa aktarılıyor - - This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. - Bu seçenek veritabanını en son kaydedilen durumuna döndürür. Geçerli kayıttan sonra yaptığınız tüm deÄŸiÅŸiklikler kaybolacaktır. + + + Error while writing the file '%1': %2 + '%1' dosyası yazılırken hata oluÅŸtu: %2 - - Write Changes - DeÄŸiÅŸiklikleri Kaydet + + exporting JSON + JSON dışa aktarılıyor - - Write changes to the database file - DeÄŸiÅŸiklikleri veritabanı dosyasına kaydet + + Please select at least 1 table. + Lütfen en az 1 tablo seçiniz. - - This option is used to save changes to the database file. - Bu seçenek deÄŸiÅŸiklikleri veritabanı dosyasına kaydetmenizi saÄŸlar. + + Choose a directory + Dizin seçiniz - - Ctrl+S - Ctrl+S + + Export completed. + Dışa aktarma tamamlandı. - - Compact Database - Veritabanını GeniÅŸlet + + Export finished with errors. + Dışa aktarma hatalarla tamamlandı. + + + + ExportSqlDialog + + + Export SQL... + SQL dosyasını dışa aktar... - - Compact the database file, removing space wasted by deleted records - Veritabanı dosyasını geniÅŸletmek, silinen kayıtlardan dolayı meydana gelen boÅŸlukları temizler + + Tab&le(s) + Tab&lo(lar) + + + + Select All + Tümünü Seç + + + + Deselect All + Tüm Seçimi İptal Et + + + + &Options + &Seçenekler + + + + Keep column names in INSERT INTO + INSERT ve INTO komutlarında sütun isimlerini tut + + + + Multiple rows (VALUES) per INSERT statement + Tek INSERT ifadesi için çok satırlı (VALUES) ifade + + + + Export everything + Her ÅŸeyi dışa aktar + + + + Export data only + Sadece veriyi dışa aktar + + + + Keep original CREATE statements + Orijinal CREATE ifadelerini koruyun + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + Eski ÅŸemayı tut (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + Eski ÅŸemanın üzerine yaz (DROP TABLE, then CREATE TABLE) + + + + Export schema only + Sadece ÅŸemayı dışa aktar + + + + Please select at least one table. + Lütfen en az bir tablo seçiniz. + + + + Choose a filename to export + Dışa aktarmak için dosya ismi seçiniz + + + + Export completed. + Dışa aktarma tamamlandı. + + + + Export cancelled or failed. + Dışa aktarma iptal edildi veya baÅŸarısız. + + + + ExtendedScintilla + + + + Ctrl+H + + + + + Ctrl+F + + + + + + Ctrl+P + + + + + Find... + Bul... + + + + Find and Replace... + Bul ve DeÄŸiÅŸtir... + + + + Print... + Yazdır... + + + + ExtendedTableWidget + + + Use as Exact Filter + Tam Filtre Olarak Kullan + + + + Containing + İçersin + + + + Not containing + İçermesin + + + + Not equal to + EÅŸit deÄŸil + + + + Greater than + Büyüktür + + + + Less than + Küçüktür + + + + Greater or equal + Büyük eÅŸit + + + + Less or equal + Küçük eÅŸit + + + + Between this and... + Åžunların arasında... + + + + Regular expression + Düzenli ifadeler (RegEx) + + + + Edit Conditional Formats... + KoÅŸullu Biçimleri Düzenle... + + + + Set to NULL + NULL olarak ayarla + + + + Cut + Kes + + + + Copy + Kopyala + + + + Copy with Headers + Üst BaÅŸlıklarla Kopyala + + + + Copy as SQL + SQL Olarak Kopyala + + + + Paste + Yapıştır + + + + Print... + Yazdır... + + + + Use in Filter Expression + Filtre İfadesinde Kullan + + + + Alt+Del + + + + + Ctrl+Shift+C + + + + + Ctrl+Alt+C + + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + Pano içeriÄŸi seçilen aralıktan daha büyük. + Yine de eklemek istiyor musunuz? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p> Tüm veriler yüklenmedi. <b>Tüm satırları seçmeden önce tüm verileri yüklemek istiyor musunuz?</b> </p> <p></p> <p> <b>Hayır</b> olarak cevaplamak, tüm verileri yüklemeyecek ve seçim iÅŸlemini uygulamayacak. <br /> <b>Evet</b> seçeneÄŸi biraz zaman alabilir ama seçim iÅŸlemini gerçekleÅŸtirecektir. </p> Uyarı: Tüm verilerin yüklenmesi büyük tablolar için büyük miktarda bellek gerektirebilir. + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + Seçim NULL olarak ayarlanamıyor. %1 sütununda NOT NULL kısıtlaması var. + + + + FileExtensionManager + + + File Extension Manager + Dosya Uzantı Yöneticisi + + + + &Up + &Yukarı + + + + &Down + &AÅŸağı + + + + &Add + &Ekle + + + + &Remove + &Kaldır + + + + + Description + Açıklama + + + + Extensions + Uzantılar + + + + *.extension + *.uzantı + + + + FilterLineEdit + + + Filter + Filtre + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + Bu giriÅŸ alanları, seçili tabloda hızlı filtreler gerçekleÅŸtirmenizi saÄŸlar. +Varsayılan olarak, metin içeren satırlar filtrelenir. +Ayrıca aÅŸağıdaki operatörler de destekleniyor: +% Joker +> Büyüktür +< Küçüktür +>= Büyük eÅŸit +<= Küçük eÅŸit += EÅŸittir +<> EÅŸit deÄŸil +x~y Aralık: deÄŸerler x ve y arasında +/regexp/ Kurallı ifadelerle(RegExp) eÅŸleÅŸen deÄŸerler + + + + Clear All Conditional Formats + Tüm KoÅŸullu Biçimleri Temizle + + + + Use for Conditional Format + KoÅŸullu Biçim İçin Kullan + + + + Edit Conditional Formats... + KoÅŸullu Biçimleri Düzenle... + + + + Set Filter Expression + Filtre İfadesi Ayarla + + + + What's This? + Bu nedir? + + + + Is NULL + NULL mu + + + + Is not NULL + NULL deÄŸil mi + + + + Is empty + BoÅŸ mu + + + + Is not empty + BoÅŸ deÄŸil mi + + + + Not containing... + İçermiyor... + + + + Equal to... + Åžuna eÅŸit... + + + + Not equal to... + Åžuna eÅŸit deÄŸil... + + + + Greater than... + Büyüktür... + + + + Less than... + Küçüktür... + + + + Greater or equal... + Büyük eÅŸit... + + + + Less or equal... + Küçük eÅŸit... + + + + In range... + Aralıkta mı... + + + + Regular expression... + Düzenli ifade (RegEx)... + + + + FindReplaceDialog + + + Find and Replace + Bul ve DeÄŸiÅŸtir + + + + Fi&nd text: + Met&ni bul: + + + + Re&place with: + Åžununla d&eÄŸiÅŸtir: + + + + Match &exact case + Büyük/küçük harf tam &eÅŸleÅŸme + + + + Match &only whole words + &Sadece tam kelimeleri eÅŸleÅŸtir + + + + When enabled, the search continues from the other end when it reaches one end of the page + EtkinleÅŸtirildiÄŸinde, arama sayfanın bir ucuna ulaÅŸtığında diÄŸer uçtan devam eder + + + + &Wrap around + Ba&ÅŸa dön + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + Ayarlandığında, arama imleç konumundan geriye doÄŸru gider, aksi takdirde ileri gider + + + + Search &backwards + Geri&ye doÄŸru ara + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>İşaretlendiÄŸinde, girilen desen yalnızca geçerli seçimde aranır.</p></body></html> + + + + &Selection only + Sadece se&çim + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html> <head /> <body> <p> İşaretlendiÄŸinde, girilen desen UNIX düzenli ifadesi olarak yorumlanır. <a href="https://en.wikibooks.org/wiki/Regular_Expressions" >Wikibooks</a > üzerinden düzenli ifadeleri inceleyebilirsiniz. </p> </body> </html> + + + + Use regular e&xpressions + Düzenli ifadeleri &kullan + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + İmleç konumundan itibaren belirtilen yönde bir sonraki eÅŸleÅŸmeyi bulur + + + + &Find Next + Sonrakini &Bul + + + + F3 + F3 + + + + &Replace + &DeÄŸiÅŸtir + + + + Highlight all the occurrences of the text in the page + Sayfadaki metnin tüm oluÅŸumlarını vurgula + + + + F&ind All + Tüm&ünü Bul + + + + Replace all the occurrences of the text in the page + Sayfadaki metnin tüm oluÅŸumlarını deÄŸiÅŸtir + + + + Replace &All + &Tümünü DeÄŸiÅŸtir + + + + The searched text was not found + Aranan metin bulunamadı + + + + The searched text was not found. + Aranan metin bulunamadı. + + + + The searched text was found one time. + Aranan metin bir kez bulundu. + + + + The searched text was found %1 times. + Aranan metin %1 kez bulundu. + + + + The searched text was replaced one time. + Aranan metin bir kez deÄŸiÅŸtirildi. + + + + The searched text was replaced %1 times. + Aranan metin %1 kez deÄŸiÅŸtirildi. + + + + ForeignKeyEditor + + + &Reset + &Sıfırla + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + Yabancı anahtar hükümleri (ON UPDATE, ON DELETE vb.) + + + + ImageViewer + + + Image Viewer + İmaj Görüntüleyici + + + + Reset the scaling to match the original size of the image. + Ölçeklemeyi görüntünün orijinal boyutuna uyacak ÅŸekilde sıfırla. + + + + Set the scaling to match the size of the viewport. + Ölçeklemeyi, görünüm alanının boyutuna uyacak ÅŸekilde ayarla. + + + + Print... + Yazdır... + + + + Open preview dialog for printing displayed image + Görüntülenen resmi yazdırmak için ön izleme penceresini aç + + + + Ctrl+P + Ctrl+P + + + + ImportCsvDialog + + + Import CSV file + CSV dosyasını içe aktar + + + + Table na&me + Tablo is&mi + + + + &Column names in first line + İlk satır &sütun isimleri içeriyor + + + + Field &separator + Alan &ayracı + + + + , + , + + + + ; + ; + + + + + Tab + Tab karakteri + + + + | + | + + + + Other + DiÄŸer + + + + &Quote character + &Tırnak karakteri + + + + + Other (printable) + DiÄŸer (yazdırılabilir) + + + + + Other (code) + DiÄŸer (Kod) + + + + " + " + + + + ' + ' + + + + &Encoding + &Kodlama + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Trim fields? + Alanlar biçimlendirilsin mi? + + + + Separate tables + Tablolar ayrılmış + + + + Advanced + GeliÅŸmiÅŸ + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + CSV dosyasından boÅŸ bir deÄŸer alındığında, sütunun varsayılan deÄŸeri kullanılır. Varsayılan deÄŸer yerine boÅŸ bir deÄŸer eklemek için bu seçeneÄŸi etkinleÅŸtirin. + + + + Ignore default &values + &Varsayılan deÄŸerleri yoksay + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + Varsayılan deÄŸeri olmayan bir NOT NULL sütununa boÅŸ bir deÄŸer aktarmaya çalışırken aktarmayı durdurmak için bu seçeneÄŸi etkinleÅŸtirin. + + + + Fail on missing values + Eksik deÄŸerde iÅŸlemi durdur + + + + Disable data type detection + Veri tipi algılamayı devre dışı bırak + + + + Disable the automatic data type detection when creating a new table. + Yeni bir tablo oluÅŸtururken otomatik veri tipi algılamayı devre dışı bırakın. + + + + Use local number conventions + Yerel numara kurallarını kullanın + + + + Use decimal and thousands separators according to the system locale. + Sistem yerel ayarlarına göre ondalık ve binlik ayraçlarını kullanın. + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + Birincil anahtar, benzersiz kısıtı veya benzersiz index kısıtına sahip mevcut bir tablo içe aktarırken çakışma meydana gelebilir. Bu seçenek, bu durum için bir strateji seçmenize olanak tanır: Varsayılan olarak iÅŸlem iptal edilir ve geri alınır, ancak isterseniz çakışmaları yoksayıp içe aktarmazsınız veya yeni satırları mevcut olanlarla deÄŸiÅŸtirebilirsiniz. + + + + Abort import + İçe aktarmayı iptal et + + + + Ignore row + Satırı yoksay + + + + Replace existing row + Varolan kaydı deÄŸiÅŸtir + + + + Conflict strategy + Çakışma stratejisi + + + + + Deselect All + Tüm seçimi iptal et + + + + Match Similar + Benzerleri EÅŸleÅŸtir + + + + Select All + Tümünü Seç + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + '%1' isminde bir tablo zaten var, var olan bir tablo için içe aktarma, yalnızca sütun sayıları eÅŸitse mümkün olabilir. + + + + There is already a table named '%1'. Do you want to import the data into it? + '%1' adında bir tablo zaten var. Verileri içe aktarmak istiyor musunuz? + + + + Creating restore point failed: %1 + Geri yükleme noktası oluÅŸturma baÅŸarısız: %1 + + + + Creating the table failed: %1 + Tablo oluÅŸturma baÅŸarısız: %1 + + + + importing CSV + CSV İçe Aktarma + + + + Could not prepare INSERT statement: %1 + INSERT ifadesi hazırlanamadı: %1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + Beklenmeyen dosya sonu. Lütfen tırnak iÅŸaretlerini doÄŸru yapılandırdığınızdan ve dosyanın hatalı olmadığından emin olun. + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + '%1' dosyasını içe aktarmak %2ms sürdü. %3ms satır fonksiyonunda harcandı. + + + + Inserting row failed: %1 + Satır ekleme baÅŸarısız: %1 + + + + MainWindow + + + DB Browser for SQLite + SQLite DB Browser + + + + toolBar1 + toolBar1 + + + + Opens the SQLCipher FAQ in a browser window + SQLCipher SSS bölümünü bir tarayıcı penceresinde açar + + + + Export one or more table(s) to a JSON file + Bir veya daha fazla tabloyu JSON dosyası olarak dışa aktarın + + + + Open an existing database file in read only mode + Mevcut bir veritabanı dosyasını salt okunur modda açın + + + + &File + &Dosya + + + + &Import + &İçe Aktar + + + + &Export + &Dışa Aktar + + + + &Edit + Düz&enle + + + + &View + &Görünüm + + + + &Help + &Yardım + + + + DB Toolbar + Veritabanı Araç ÇubuÄŸu + + + + Edit Database &Cell + Veritabanı Hü&cresini Düzenle + + + + DB Sche&ma + Veritabanı Åže&ması + + + + &Remote + &Uzak Bilgisayar + + + + + Execute current line + Geçerli satırı yürüt + + + + This button executes the SQL statement present in the current editor line + Bu buton, geçerli editör satırında bulunan SQL ifadesini yürütür + + + + Shift+F5 + + + + + Sa&ve Project + Projeyi &Kaydet + + + + User + Kullanıcı + + + + Application + Uygulama + + + + &Clear + &Temizle + + + + &New Database... + Ye&ni Veritabanı... + + + + + Create a new database file + Yeni bir veritabanı dosyası oluÅŸtur + + + + This option is used to create a new database file. + Bu seçenek yeni bir veritabanı dosyası oluÅŸturmak için kullanılır. + + + + Ctrl+N + + + + + + &Open Database... + &Veritabanı Aç... + + + + + + + + Open an existing database file + Mevcut veritabanı dosyasını aç + + + + + + This option is used to open an existing database file. + Bu seçenek mevcut veritabanı dosyasını açmak için kullanılır. + + + + Ctrl+O + + + + + &Close Database + Veritabanı &Kapat + + + + + Ctrl+W + + + + + + Revert database to last saved state + Veritabanını en son kaydedilen duruma döndür + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + Bu seçenek veritabanını en son kaydedilen durumuna döndürür. Geçerli kayıttan sonra yaptığınız tüm deÄŸiÅŸiklikler kaybolacaktır. + + + + + Write changes to the database file + DeÄŸiÅŸiklikleri veritabanı dosyasına kaydet + + + + This option is used to save changes to the database file. + Bu seçenek deÄŸiÅŸiklikleri veritabanı dosyasına kaydetmenizi saÄŸlar. + + + + Ctrl+S + + + + + Compact the database file, removing space wasted by deleted records + Veritabanı dosyasını sıkıştırarak silinen kayıtların kapladığı alanı boÅŸaltın + + + + + Compact the database file, removing space wasted by deleted records. + Veritabanı dosyasını geniÅŸletmek, silinen kayıtlardan dolayı meydana gelen boÅŸlukları temizler. + + + + E&xit + &Çıkış + + + + Ctrl+Q + + + + + Import data from an .sql dump text file into a new or existing database. + Verileri .sql uzantılı döküm dosyasından varolan veya yeni veritabanına aktarın. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + Bu seçenek verileri .sql döküm dosyasından varolan veya yeni veritabanına aktarmanıza olanak saÄŸlar. SQL dosyaları MySQL ve PostgreSQL dahil olmak üzere birçok veritabanı motorları tarafından oluÅŸtururlar. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Virgülle ayrılmış metin dosyalarını veritabanınızın içine aktarmanızı saÄŸlayan sihirbazı açar. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Virgülle ayrılmış metin dosyalarını veritabanınızın içine aktarmanızı saÄŸlayan sihirbazı açar. CSV dosyaları çoÄŸu veritabanı motorları ve elektronik tablo uygulamaları tarafından oluÅŸtururlar. + + + + Export a database to a .sql dump text file. + Veritabanını .sql döküm dosyası olarak dışa aktar. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + Bu seçenek veritabanını .sql döküm dosyası olarak dışa aktarmanızı saÄŸlar. SQL döküm dosyaları veritabanını, MySQL ve PostgreSQL dahil birçok veritabanı motorunda yeniden oluÅŸturmak için gereken verilerin tümünü içerir. + + + + Export a database table as a comma separated text file. + Veritabanı tablosunu virgülle ayrılmış metin dosyası olarak dışa aktar. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + Veritabanını virgülle ayrılmış metin dosyası olarak diÄŸer veritabanı veya elektronik tablo uygulamalarına aktarmaya hazır olacak ÅŸekilde dışa aktarın. + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Tablo OluÅŸturma sihirbazı, veritabanı için alanlarını ve ismini ayarlayabileceÄŸiniz, yeni bir tablo oluÅŸturmanızı saÄŸlar + + + + + Delete Table + Tabloyu Sil + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Tablo Silme sihirbazı, seçtiÄŸiniz tabloları silmenizi saÄŸlar. + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + İndeks OluÅŸturma sihirbazı, varolan veritabanı tablosuna yeni indeks tanımlamanıza olanak saÄŸlar. + + + + &Preferences... + &Tercihler... + + + + + Open the preferences window. + Tercihler penceresini açar. + + + + &DB Toolbar + &Veritabanı Araç ÇubuÄŸu + + + + Shows or hides the Database toolbar. + Veritabanı araç çubuÄŸunu gösterir veya gizler. + + + + Shift+F1 + + + + + &Recently opened + En son açılanla&r + + + + Ctrl+T + + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + Bu, açılan veritabanının yapısıdır. +SQL ifadelerini bir nesne satırından sürükleyip baÅŸka uygulamalara veya 'DB Browser for SQLite programının baÅŸka bir penceresine bırakabilirsiniz. + + + + + Un/comment block of SQL code + Kod bloÄŸunu yorum satırına dönüştür/yorum satırını iptal et + + + + Un/comment block + Yorum satırına dönüştür/yorum satırını iptal et + + + + Comment or uncomment current line or selected block of code + Geçerli satırı veya kod bloÄŸunu, yorum satırına dönüştür veya yorum satırını iptal et + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + Geçerli satırı veya kod bloÄŸunu, yorum satırına dönüştür veya yorum satırını iptal et. Hiç seçim yoksa tüm bloklar ilk satır baz alınarak deÄŸiÅŸtirilir. + + + + Ctrl+/ + + + + + Stop SQL execution + SQL yürütmesini durdur + + + + Stop execution + Yürütmeyi durdur + + + + Stop the currently running SQL script + Åžu anda çalışan SQL betiÄŸini durdur + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + Uyarı: Bu pragma okunamaz ve bu deÄŸer çıkartıldı. Bu pragmayı yazmak, bir SQLite eklentisi tarafından saÄŸlanan yeniden tanımlanmış bir LIKE'nin üzerine yazabilir. + + + + Too&ls + Ara&çlar + + + + SQL &Log + SQL &Günlüğü + + + + Show S&QL submitted by + Åžuna ait S&QL'i göster + + + + Error Log + Hata Günlüğü + + + + This button clears the contents of the SQL logs + Bu buton SQL günlüğünün içeriÄŸini temizler + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + Bu panel, uygulama veya kendiniz tarafından verilen tüm SQL komutlarının bir günlüğünü incelemenizi saÄŸlar + + + + &Plot + &Çizim + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + Bu, açılan veritabanının yapısıdır. +Birden çok nesne adını Ad sütunundan sürükleyip SQL editörüne bırakabilir ve bırakılan adların özelliklerini baÄŸlam menüsünü kullanarak ayarlayabilirsiniz. Bu, SQL ifadeleri oluÅŸturmanıza yardımcı olacaktır. +SQL deyimlerini Åžema sütunundan sürükleyip SQL editörüne veya diÄŸer uygulamalara bırakabilirsiniz. + + + + + + Project Toolbar + Proje Araç ÇubuÄŸu + + + + Extra DB toolbar + Ekstra Veritabanı araç çubuÄŸu + + + + + + Close the current database file + Geçerli veritabanı dosyasını kapat + + + + This button closes the connection to the currently open database file + Bu buton, ÅŸu anda açık olan veritabanı dosyasına ait baÄŸlantıyı kapatır + + + + + Ctrl+F4 + + + + + &Revert Changes + DeÄŸiÅŸiklikleri &Geri Al + + + + &Write Changes + DeÄŸiÅŸiklikleri &Kaydet + + + + Compact &Database... + Veritabanını &Sıkıştır... + + + + New &tab + Yeni &sekme + + + + Execute all/selected SQL + Tüm/seçili SQL'i çalıştır + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + Bu düğme seçili olan SQL ifadesini yürütür. Hiçbir metin seçilmezse tüm SQL ifadeleri yürütülür. + + + + Open SQL file(s) + SQL dosyasını/dosyalarını açın + + + + This button opens files containing SQL statements and loads them in new editor tabs + Bu düğme, SQL ifadeleri içeren dosyaları açar ve bunları yeni düzenleyici sekmelerine yükler + + + + &Load Extension... + Ek&lenti Yükle... + + + + Execute line + Satırı yürüt + + + + &Wiki + &Wiki + + + + F1 + + + + + Bug &Report... + Hata &Raporu... + + + + Feature Re&quest... + &Özellik Talebi... + + + + Web&site + Web &sitesi + + + + &Donate on Patreon... + &Patreon üzerinden Bağış Yapın... + + + + Close Pro&ject + Pro&jeyi Kapat + + + + + Close project and database files and return to the initial state + Proje ve veritabanı dosyalarını kapatın ve baÅŸlangıç ​​durumuna dönün + + + + Ctrl+Shift+F4 + Ctrl+Shift+F4 + + + + + Detach Database + Veritabanını Ayır + + + + + Detach database file attached to the current database connection + Geçerli veritabanı baÄŸlantısına baÄŸlı veritabanı dosyasını ayırın + + + + Open &Project... + &Proje Aç... + + + + &Attach Database... + &Veritabanı Ekle... + + + + + Add another database file to the current database connection + Åžu anki veritabanı baÄŸlantısına baÅŸka bir veritabanı dosyası ekle + + + + This button lets you add another database file to the current database connection + Bu buton, geçerli veritabanı baÄŸlantısına baÅŸka bir veritabanı dosyası eklemenizi saÄŸlar + + + + &Set Encryption... + &Åžifreleme Belirtle... + + + + SQLCipher &FAQ + SQLCipher &SSS + + + + Table(&s) to JSON... + Tablodan &JSON dosyasına... + + + + Open Data&base Read Only... + Salt Okunur Verita&banı Aç... + + + + Ctrl+Shift+O + + + + + Save results + Sonuçları kaydet + + + + Save the results view + Sonuç görünümünü kaydet + + + + This button lets you save the results of the last executed query + Bu buton son yürütülen sorgunun sonuçlarını kaydetmenizi saÄŸlar + + + + + Find text in SQL editor + SQL editöründe metin ara + + + + Find + Bul + + + + This button opens the search bar of the editor + Bu buton editörün arama çubuÄŸunu açar + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + SQL editöründe metin bul veya deÄŸiÅŸtir + + + + Find or replace + Bul veya deÄŸiÅŸtir + + + + This button opens the find/replace dialog for the current editor tab + Bu buton, geçerli editör sekmesi için bul / deÄŸiÅŸtir iletiÅŸim kutusunu açar + + + + Ctrl+H + + + + + Export to &CSV + &CSV'ye aktar + + + + Save as &view + &Görünüm olarak kaydet + + + + Save as view + Görünüm olarak kaydet + + + + Browse Table + Tabloyu Görüntüle + + + + Shows or hides the Project toolbar. + Proje araç çubuÄŸunu gösterir veya gizler. + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + &Veritabanı Yapısı + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + Verileri &Görüntüle + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + P&ragmaları Düzenle + + + + Temp Store + Geçici Depo + + + + Secure Delete + Güvenli Silme + + + + Case Sensitive Like + Büyük/Küçük Harfe Duyarlı Like İşleci İle + + + + Journal Mode + Günlük Modu + + + + Journal Size Limit + Günlük Boyut Sınırı + + + + Recursive Triggers + Özyinelemeli Tetikleyiciler + + + + Page Size + Sayfa Boyutu + + + + Foreign Keys + Yabancı Anahtarlar + + + + Auto Vacuum + Otomatik Vakum + + + + Max Page Count + Maksimum Sayfa Sayısı + + + + Checkpoint Full FSYNC + Kontrol Noktası Tam FSYNC + + + + + Off + Kapalı + + + + + Normal + Normal + + + + + Full + Tam + + + + Default + Varsayılan + + + + File + Dosya + + + + + Memory + Bellek + + + + Delete + Sil + + + + Truncate + Kısalt + + + + Persist + Sürdür + + + + WAL + WA + + + + Exclusive + Özel + + + + Automatic Index + Otomatik İndeks + + + + Ignore Check Constraints + Kontrol Kısıtlamalarını Yoksay + + + + Full FSYNC + Tam FSYNC + + + + WAL Auto Checkpoint + WAL Oto Kontrol Noktası + + + + User Version + Kullanıcı Sürümü + + + + Synchronous + EÅŸ zamanlı + + + + None + Hiçbiri + + + + Incremental + Artımlı + + + + Locking Mode + Kilitleme Modu + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + SQL'i &çalıştır + + + + &Recent Files + &Son Dosyalar + + + + &New Database + Ye&ni Veritabanı + + + + &Undo + &Geri Al + + + + + Undo last change to the database + Veritabanındaki son deÄŸiÅŸikliÄŸi geri al + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + Bu iÅŸlem, Veritabanı Tarayıcısı'nda veya SQL Çalıştır'da veritabanında gerçekleÅŸtirilen son deÄŸiÅŸikliÄŸi geri alır. Yeniden yapılması mümkün deÄŸildir. + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + Mevcut bir tablonun adını deÄŸiÅŸtirebileceÄŸiniz Tablo DeÄŸiÅŸtirme sihirbazını açın. Ayrıca, bir tabloya alan ekleyebilir veya silebilir, alan adlarını ve türlerini deÄŸiÅŸtirebilirsiniz. + + + + Ctrl+Shift+T + Ctrl+Shift+T + + + + &Save Project + Projeyi &Kaydet + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + Bu düğme, açık DB ile iliÅŸkili tüm ayarları SQLite proje dosyası için DB Tarayıcısına kaydetmenize olanak tanır + + + + Open &Project + &Proje Aç + + + + This button lets you open a DB Browser for SQLite project file + Bu düğme, SQLite proje dosyası için bir DB Tarayıcısı açmanıza olanak tanır + + + + Export to &JSON + &JSON'a aktar + + + + Extra DB Toolbar + Ekstra Veritabanı Araç ÇubuÄŸu + + + + &Open Database + Veritabanını &Aç + + + + New In-&Memory Database + &Yeni Bellek İçi Veritabanı + + + + Drag && Drop SELECT Query + Sürükle && Bırak SEÇ Sorgusu + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + Aynı tablodan veya tek bir tablodan alanları sürüklerken, düzenleyiciye bir SEÇ sorgusu bırakın + + + + Drag && Drop Qualified Names + Nitelikli İsimleri Sürükle && Bırak + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + Nesneleri sürükleyip düzenleyiciye bırakırken özel isimleri kullanın (örn. "Tablo". "Alan") + + + + Drag && Drop Enquoted Names + İsimleri Sürükle && Bırak + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + Nesneleri sürükleyip düzenleyiciye bırakırken kaçış tanımlayıcıları (örneÄŸin "Tablo1") kullanın + + + + &Integrity Check + &Bütünlük Denetimi + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + integrity_check pragmasını açılan veritabanı üzerinde çalıştırır ve 'SQL Kodunu Yürüt' sekmesinde sonuçları döndürür. Bu pragma veritabanının tamamının bütünlüğünü kontrol eder. + + + + &Foreign-Key Check + &Yabancı anahtar kontrolü + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + Foreign_key_check pragmasını açık veritabanı üzerinde çalıştırır ve 'SQL Kodunu Yürüt' sekmesinde sonuçları döndürür + + + + &Quick Integrity Check + &Hızlı Bütünlük Testi + + + + Run a quick integrity check over the open DB + Açık DB üzerinde hızlı bir bütünlük denetimi yapın + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + quick_check pragmasını açık veritabanı üzerinde çalıştırır ve 'SQL Kodunu Yürüt' sekmesinde sonuçları döndürür. Bu komut PRAGMA integrity_check denetiminin çoÄŸunu yapar, ancak çok daha hızlı çalışır. + + + + &Optimize + &Optimize + + + + Attempt to optimize the database + Veritabanını optimize etmeyi dene + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + Açılan veritabanı üzerinden optimizasyon pragmasını çalıştırır. Bu uygulama gelecekteki sorguların performansını artırmaya yardımcı olabilir. + + + + + Print + Yazdır + + + + Print text from current SQL editor tab + Geçerli SQL düzenleyici sekmesinden metni yazdırın + + + + Open a dialog for printing the text in the current SQL editor tab + Geçerli SQL düzenleyici sekmesindeki metni yazdırmak için bir iletiÅŸim kutusu açın + + + + Print the structure of the opened database + Açılan veritabanının yapısını yazdırın + + + + Open a dialog for printing the structure of the opened database + Açılan veritabanının yapısını yazdırmak için bir bir iletiÅŸim kutusu açın + + + + &Save Project As... + Projeyi Farklı &Kaydet... + + + + + + Save the project in a file selected in a dialog + Projeyi iletiÅŸim kutusunda seçilen bir dosyaya kaydedin + + + + Save A&ll + Tümünü &Kaydet + + + + + + Save DB file, project file and opened SQL files + DB dosyasını, proje dosyasını ve açılan SQL dosyalarını kaydedin + + + + Ctrl+Shift+S + + + + + + Ctrl+Shift+W + Ctrl+Shift+W + + + + Table from CSV data in Clipboard... + Panodaki CSV verilerinden tablo... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + Bu, geçerli panonun içeriÄŸini bir CSV dosyası olarak ele alır ve bir dosyadan CSV verilerini içe aktarmak için kullanılan aynı içe aktarma sihirbazını açar. + + + + Show &Row Counts + &Satır Sayılarını Göster + + + + This shows the number of rows for each table and view in the database. + Bu, veritabanındaki her tablo ve görünüm için satır sayısını gösterir. + + + + Save Database &As... + Veritabanını &Farklı Kaydet... + + + + Save the current database as a different file + Geçerli veritabanını farklı bir dosya olarak kaydedin + + + + Refresh + Yenile + + + + Reload the database structure + Veritabanı yapısını yeniden yükle + + + + &Database from SQL file... + SQL &dosyasından veritabanı... + + + + &Table from CSV file... + CSV dosyasından &tablo... + + + + &Database to SQL file... + Veritabanından SQL &dosyası... + + + + &Table(s) as CSV file... + &Tablodan CSV dosyası olarak... + + + + &Create Table... + &Tablo OluÅŸtur... + + + + &Delete Table... + &Tabloyu Sil... + + + + &Modify Table... + Tabloyu &Düzenle... + + + + Create &Index... + &İndeks OluÅŸtur... + + + + W&hat's This? + Bu &nedir? + + + + &About + &Hakkında + + + + This button opens a new tab for the SQL editor + Bu düğme SQL editörü için yeni bir sekme açar + + + + &Execute SQL + &SQL kodunu yürüt + + + + + + Save SQL file + SQL dosyasını kaydet + + + + Ctrl+E + + + + + Export as CSV file + CSV dosyası olarak dışa aktar + + + + Export table as comma separated values file + Tabloyu virgülle ayrılmış girdiler dosyası olarak dışa aktar + + + + + Save the current session to a file + Geçerli oturumu dosyaya kaydet + + + + + Load a working session from a file + Dosyadan çalışma oturumunu yükle + + + + + Save SQL file as + SQL dosyasını bu ÅŸekilde kaydet + + + + This button saves the content of the current SQL editor tab to a file + Bu buton geçerli SQL editörü sekmesinin içeriÄŸini bir dosyaya kaydeder + + + + &Browse Table + &Tabloyu Görüntüle + + + + Copy Create statement + 'Create' ifadesini kopyala + + + + Copy the CREATE statement of the item to the clipboard + Objenin 'Create' ifadesini panoya kopyala + + + + Ctrl+Return + + + + + Ctrl+L + + + + + + Ctrl+P + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Encrypted + ÅžifrelenmiÅŸ + + + + Read only + Salt okunur + + + + Database file is read only. Editing the database is disabled. + Veritabanı salt okunur. Veritabanı düzenleme devre dışı. + + + + Database encoding + Veritabanı kodlaması + + + + Database is encrypted using SQLCipher + Veritabanı SQLCipher kullanılırak ÅŸifrelendi + + + + + Choose a database file + Veritabanı dosyasını seçiniz + + + + + + Choose a filename to save under + Kaydetmek için dosya ismi seçiniz + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + Veritabanı dosyası kaydedilirken hata oluÅŸtu. Bu, veritabanındaki tüm deÄŸiÅŸikliklerin kaydedilmediÄŸi anlamına gelir. Önce aÅŸağıdaki hatayı çözmeniz gerekir. + +%1 + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + Son kayıttan itibaren '%1' dosyasına yaptığınız deÄŸiÅŸiklikleri geri almak istediÄŸinize emin misiniz? + + + + Choose a file to import + İçe aktarmak için dosya seçiniz + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (salt okunur) + + + + Open Database or Project + Veritabanı veya Proje Açın + + + + Attach Database... + Veritabanı Ekle... + + + + Import CSV file(s)... + CSV dosyalarını içe aktarın... + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + SQL sekmelerinde yapılan deÄŸiÅŸiklikleri '%1' proje dosyasına kaydetmek istiyor musunuz? + + + + Text files(*.sql *.txt);;All files(*) + Metin dosyaları(*.sql *.txt);;Tüm dosyalar(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + İçeri aktarılan verileri tutmak için yeni bir veritabanı dosyası oluÅŸturmak istiyor musunuz? +EÄŸer cevabınız hayır ise biz SQL dosyasındaki verileri geçerli veritabanına aktarmaya baÅŸlayacağız. + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + Åžu anda SQL sorgularını yürütüyorsunuz. Veritabanının ÅŸimdi kapatılması, muhtemelen veritabanını tutarsız bir durumda bırakarak yürütmeyi durduracaktır. Veritabanını kapatmak istediÄŸinizden emin misiniz? + + + + Do you want to save the changes made to the project file '%1'? + '%1' proje dosyasında yapılan deÄŸiÅŸiklikleri kaydetmek istiyor musunuz? + + + + File %1 already exists. Please choose a different name. + %1 dosyası zaten mevcut. Lütfen farklı bir isim seçiniz. + + + + Error importing data: %1 + Dosya içeri aktarılırken hata oluÅŸtu: %1 + + + + Import completed. + İçeri aktarma tamamlandı. + + + + Delete View + Görünümü Sil + + + + Modify View + Görünümü Düzenle + + + + Delete Trigger + Tetikleyiciyi Sil + + + + Modify Trigger + Tetikleyiciyi Düzenle + + + + Delete Index + İndeksi Sil + + + + Modify Index + İndeksi Düzenle + + + + Modify Table + Tabloyu Düzenle + + + + Do you want to save the changes made to SQL tabs in a new project file? + SQL sekmelerinde yapılan deÄŸiÅŸiklikleri yeni bir proje dosyasına kaydetmek istiyor musunuz? + + + + Do you want to save the changes made to the SQL file %1? + %1 SQL dosyasında yapılan deÄŸiÅŸiklikleri kaydetmek istiyor musunuz? + + + + Could not find resource file: %1 + Kaynak dosya bulunamadı: %1 + + + + Choose a project file to open + Açmak için bir proje dosyası seçin + + + + Could not open project file for writing. +Reason: %1 + Proje dosyası yazmaya açılamadı. +Nedeni: %1 + + + + Busy (%1) + MeÅŸgul (%1) + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + PRAGMA deÄŸerlerini ayarlamak geçerli iÅŸleminizi yürütmeye alacaktır. +Bunu yapmak istediÄŸinize emin misiniz? + + + + Ctrl+Tab + Ctrl+Tab + + + + Ctrl+Shift+Tab + Ctrl+Shift+Tab + + + + Clear List + Listeyi Temizle + + + + Window Layout + Pencere Düzeni + + + + Reset Window Layout + Pencere Düzenini Sıfırla + + + + Simplify Window Layout + Pencere Düzenini BasitleÅŸtirin + + + + Alt+Shift+0 + Alt+Shift+0 + + + + Dock Windows at Bottom + Pencereleri Altta Sabitle + + + + Dock Windows at Left Side + Pencereleri Sol Tarafa YerleÅŸtir + + + + Dock Windows at Top + Pencereleri Üstte Sabitle + + + + The database is currently busy. + Veritabanı ÅŸu anda meÅŸgul. + + + + Click here to interrupt the currently running query. + Çalışmakta olan sorguyu kesmek için burayı tıklayın. + + + + Alt+Shift+W + Alt+Shift+W + + + + Could not open database file. +Reason: %1 + Veritabanı dosyası açılamadı. +Nedeni: %1 + + + + In-Memory database + Bellek İçi Veritabanı + + + + Choose a database file to save under + Kaydedilecek bir veritabanı dosyası seçin + + + + Error while saving the database to the new file. + Veritabanını yeni dosyaya kaydederken hata oluÅŸtu. + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + '%1' tablosunu silmek istediÄŸinizden emin misiniz? +Tabloyla iliÅŸkili tüm veriler kaybedilecektir. + + + + Are you sure you want to delete the view '%1'? + '%1' görünümünü silmek istediÄŸinizden emin misiniz? + + + + Are you sure you want to delete the trigger '%1'? + '%1' tetikleyicisini silmek istediÄŸinizden emin misiniz? + + + + Are you sure you want to delete the index '%1'? + '%1' indeksini silmek istediÄŸinizden emin misiniz? + + + + Error: could not delete the table. + Hata: tablo silinemedi. + + + + Error: could not delete the view. + Hata: görünüm silinemedi. + + + + Error: could not delete the trigger. + Hata: tetikleyici silinemedi. + + + + Error: could not delete the index. + Hata: indeks silinemedi. + + + + Message from database engine: +%1 + Veritabanı motorundan mesaj: +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + Tabloyu düzenlemek için bekleyen tüm deÄŸiÅŸikliklerin ÅŸimdi kaydedilmesi gerekir. +Veritabanını kaydetmek istediÄŸinizden emin misiniz? + + + + Edit View %1 + Görünümü Düzenle %1 + + + + Edit Trigger %1 + Tetikleyiciyi Düzenle %1 + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + Åžu anda zaten yürütülen SQL sorguları var. Bunun yerine, ÅŸimdiki sorguları çalıştırmak için ÅŸu anda yürütülen sorguyu durdurmak istiyor musunuz? Bunun veritabanını tutarsız bir durumda bırakabileceÄŸini unutmayın. + + + + -- EXECUTING SELECTION IN '%1' +-- + -- SEÇİM '%1' İÇERİSİNDE YÜRÜTÜLÜYOR +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- SATIR '%1' İÇERİSİNDE YÜRÜTÜLÜYOR +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- TÜMÜ '%1' İÇERİSİNDE YÜRÜTÜLÜYOR +-- + + + + + At line %1: + %1. satırda: + + + + Result: %1 + Sonuç: %1 + + + + Result: %2 + Sonuç: %2 + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + PRAGMA deÄŸerlerini ayarlamak veya vakumlamak mevcut iÅŸleminizi kaydeder. +Emin misiniz? + + + + Opened '%1' in read-only mode from recent file list + Son dosya listesinden '%1' salt okunur modunda açıldı + + + + Opened '%1' from recent file list + Son dosya listesinden '%1' açıldı + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + Bırakılan dosyalara uygulanacak eylemi seçin. %n Not: yalnızca 'İçe Aktar' birden fazla dosyayı iÅŸler. + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + '%1' sekmesindeki ifadeler hâlâ yürütülüyor. Sekmeyi kapatmak yürütmeyi durduracaktır. Bu, veritabanını tutarsız bir durumda bırakabilir. Sekmeyi kapatmak istediÄŸinizden emin misiniz? + + + + DB file '%1' could not be opened + Veritabanı dosyası '%1' açılamadı + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + Bu proje dosyası, DB Browser for SQLite sürüm 3.10 veya daha eski bir sürüm kullanılarak oluÅŸturulduÄŸu için eski bir dosya biçimi kullanıyor. Bu dosya biçiminin yüklenmesi artık tam olarak desteklenmiyor. Dosyayı tamamen yüklemek istiyorsanız lütfen DB Browser for SQLite sürüm 3.12'yi kullanarak yeni dosya biçimine dönüştürün. + + + + Table '%1' not found; settings ignored + '%1' tablosu bulunamadı; ayarlar göz ardı edildi + + + + -- Reference to file "%1" (not supported by this version) -- + -- "%1" dosyasına baÅŸvuru (bu sürüm tarafından desteklenmiyor) -- + + + + Yes. Don't ask again + Evet. Bir daha sorma + + + + This action will open a new SQL tab with the following statements for you to edit and run: + Bu eylem, düzenlemeniz ve çalıştırmanız için aÅŸağıdaki ifadeleri içeren yeni bir SQL sekmesi açacaktır: + + + + Rename Tab + Sekmeyi Yeniden Adlandır + + + + Duplicate Tab + Sekmeyi Klonla + + + + Close Tab + Sekmeyi Kapat + + + + Opening '%1'... + '%1' açılıyor... + + + + There was an error opening '%1'... + '%1' açılırken hata oluÅŸtu... + + + + Value is not a valid URL or filename: %1 + Geçersiz bir URL veya dosya adı: %1 + + + + %1 rows returned in %2ms + %2ms içerisinde %1 tane satır döndürüldü + + + + Automatically load the last opened DB file at startup + BaÅŸlangıçta son açılan DB dosyasını otomatik olarak yükle + + + + Ctrl+0 + Ctrl+0 + + + + Choose text files + Metin dosyaları seçin + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + İçe aktarma tamamlandı. Bazı yabancı anahtar kısıtları ihlal edildi. Lütfen kaydetmeden önce bunları çözün. + + + + Select SQL file to open + Açmak için SQL dosyasını seçiniz + + + + Select file name + Dosya ismi seçiniz + + + + Select extension file + Eklenti dosyasını seçiniz + + + + Extension successfully loaded. + Eklenti baÅŸarıyla yüklendi. + + + + Error loading extension: %1 + Eklenti yüklenirken hata oluÅŸtu: %1 + + + + + Don't show again + Bir daha gösterme + + + + New version available. + Yeni sürüm mevcut. + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + Yeni bir SQLite DB Browser sürümü mevcut (%1.%2.%3).<br/><br/>Lütfen buradan indiriniz: <a href='%4'>%4</a>. + + + + Project saved to file '%1' + Proje '%1' dosyasına kaydedildi + + + + Collation needed! Proceed? + Harmanlama gerekli! Devam edilsin mi? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + Bu veritabanınındaki bir tablo özel '%1' koleksiyon fonksiyonu gerektirmektedir. +Daha fazla bilgi olmadan program bunu saÄŸlayamaz. EÄŸer bu ÅŸekilde devam edecekseniz, veritabanınıza kötü ÅŸeyler olabileceÄŸinin farkında olun ve yedek oluÅŸturun. +Bir yedek oluÅŸturun! + + + + creating collation + harmanlama oluÅŸturuluyor + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + SQL sekmesi için yeni bir ad belirleyin. AÅŸağıdaki karakteri klavye kısayolu olarak kullanmak için '&&' karakterini kullanın. + + + + Please specify the view name + Lütfen görünüm ismini belirtin + + + + There is already an object with that name. Please choose a different name. + Bu isme sahip obje zaten mevcut. Lütfen farklı bir isim seçiniz. + + + + View successfully created. + Görünüm baÅŸarıyla oluÅŸturuldu. + + + + Error creating view: %1 + Görünüm oluÅŸturma hatası: %1 + + + + This action will open a new SQL tab for running: + Bu iÅŸlem, çalıştırmak için yeni bir SQL sekmesi açar: + + + + Press Help for opening the corresponding SQLite reference page. + İlgili SQLite referans sayfasını açmak için Yardım'a basın. + + + + DB Browser for SQLite project file (*.sqbpro) + SQLite DB Browser proje dosyası (*.sqbpro) + + + + Error checking foreign keys after table modification. The changes will be reverted. + Tablo deÄŸiÅŸikliÄŸinden sonra yabancı anahtarlar kontrol edilirken hata oluÅŸtu. DeÄŸiÅŸiklikler geri alınacak. + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + Bu tablo birincil anahtar kontrolünden geçmedi.<br/>'Araçlar | Birinci Anahat Kontrolü' komutunu çalıştırın ve raporlanan sorunları düzeltin. + + + + Execution finished with errors. + Yürütme hatalarla tamamlandı. + + + + Execution finished without errors. + Yürütme hatasız tamamlandı. + + + + NullLineEdit + + + Set to NULL + NULL olarak ayarla + + + + Alt+Del + Alt+Del + + + + PlotDock + + + Plot + Grafik Çizimi + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html> <head /> <body> <p> Bu bölme, o anda taranan tablonun sütunları listesini veya yürütülen sorguyu gösterir. AÅŸağıdaki çizim bölmesi için X veya Y ekseni olarak kullanılmasını istediÄŸiniz sütunları seçebilirsiniz. Tablo, ortaya çıkan grafiÄŸi etkileyecek algılanan eksen tipini gösterir. Y ekseni için yalnızca sayısal sütunlar seçebilirsiniz, ancak X ekseni için aÅŸağıdakileri seçebilirsiniz: </p> <ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;" > <li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;" > <span style=" font-weight:600;">Tarih/Saat</span>: &quot;yyyy-MM-dd hh:mm:ss&quot; veya &quot;yyyy-MM-ddThh:mm:ss&quot; ve string formatında </li> <li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;" > <span style=" font-weight:600;">Tarih</span>: &quot;yyyy-MM-dd&quot; ve string formatında </li> <li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;" > <span style=" font-weight:600;">Saat</span>: &quot;hh:mm:ss&quot; ve string formatında </li> <li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;" > <span style=" font-weight:600;">BaÅŸlık</span>: diÄŸer string formatları. Bu sütunun X ekseni için seçilmesi, sütun deÄŸerlerinin çubukları için etiket oluÅŸturur. </li> <li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;" > <span style=" font-weight:600;">Nümerik</span>: integer veya real tipindeki deÄŸerler </li> </ul> <p> Y hücrelerini çift tıklatarak o grafik için kullanılan rengi deÄŸiÅŸtirebilirsiniz. </p> </body> </html> + + + + Columns + Sütun + + + + X + X + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + Eksen Türü + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + Yukarıdaki x ve y deÄŸerlerini seçtiÄŸinizde çizilen bir grafik. + +Noktaları grafikte ve tabloda seçmek için üzerine tıklayın. Nokta aralığı seçmek için Ctrl+Tıklama yapın. + +YakınlaÅŸtırma için fare tekerleÄŸini ve eksen aralığını deÄŸiÅŸtirmek için fare tekerini kullanın. + +Yalnızca geçerli yönde sürüklemek ve yakınlaÅŸtırmak için eksen veya eksen etiketlerini seçin. + + + + Line type: + Çizgi Tipi: + + + + + None + Hiçbiri + + + + Line + Çizgi + + + + StepLeft + Sola Basamakla + + + + StepRight + SaÄŸa Basamakla + + + + StepCenter + Merkeze Basamakla + + + + Impulse + Kaydırmalı + + + + Point shape: + Nokta ÅŸekli: + + + + Cross + Çarpı + + + + Plus + Artı + + + + Circle + Daire + + + + Disc + Disk + + + + Square + Kare + + + + Diamond + Elmas + + + + Star + Yıldız + + + + Triangle + Üçgen + + + + TriangleInverted + Ters Üçgen + + + + CrossSquare + Çapraz Kare + + + + PlusSquare + Kare İçinde Artı + + + + CrossCircle + Daire İçinde Çarpı + + + + PlusCircle + Daire İçinde Artı + + + + Peace + Barış Simgesi + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>Geçerli çizimi kaydet...</p><p>Uzantıya göre seçilen dosya formatları (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + Geçerli çizimi kaydet... + + + + + Load all data and redraw plot + Tüm verileri yükle ve grafiÄŸi yeniden çiz + + + + + + Row # + Satır # + + + + Copy + Kopyala + + + + Print... + Yazdır... + + + + Help + Yardım + + + + Show legend + Göstergeyi göster + + + + Stacked bars + Yığılmış çubuklar + + + + Fixed number format + Sabit sayı biçimi + + + + Date/Time + Tarih/Saat + + + + Date + Tarih + + + + Time + Saat + + + + + Numeric + Nümerik + + + + Label + Etiket + + + + Invalid + Geçersiz + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + Tüm verileri yükle ve grafiÄŸi yeniden çiz. +Uyarı: Kısmi yükleme mekanizması nedeniyle tüm veriler tablodan henüz alınmadı. + + + + Choose an axis color + Bir eksen rengi seçin + + + + Choose a filename to save under + Altına kaydetmek için dosya ismi seçin + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Tüm dosyalar(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + Bu grafikte eÄŸriler var ve seçilen çizgi stili yalnızca X'e göre sıralanmış grafiklere uygulanabilir. EÄŸrileri kaldırmak için tabloyu veya sorguyu X'e göre sıralayın veya eÄŸriler tarafından desteklenen stillerden birini seçin: 'Hiçbiri' veya 'Çizgi'. + + + + Loading all remaining data for this table took %1ms. + Bu tablo için kalan tüm verilerin yüklenmesi %1ms sürdü. + + + + PreferencesDialog + + + Preferences + Tercihler + + + + &General + &Genel + + + + Remember last location + Son dizini hatırla + + + + Always use this location + Her zaman bu dizini kullan + + + + Remember last location for session only + Aynı oturum için son dizini hatırla + + + + + + ... + ... + + + + Default &location + Varsayılan &dizin + + + + Lan&guage + Di&l + + + + Automatic &updates + Otomatik &güncellemeler + + + + + + + + + + + + + + enabled + etkin + + + + Show remote options + Uzak bilgisayar opsiyonlarını göster + + + + &Database + &Veritabanı + + + + Database &encoding + &Veritabanı kodlaması + + + + Open databases with foreign keys enabled. + Veritabanlarını Yabancı Anahtarlar etkin olacak ÅŸekilde aç. + + + + &Foreign keys + &Yabancı Anahtarlar + + + + Data &Browser + Veri &Görüntüleyici + + + + Remove line breaks in schema &view + Åžema &görünümde satır sonlarını kaldır + + + + Prefetch block si&ze + Önceden getirme blo&k boyutu + + + + SQ&L to execute after opening database + Veritabanı açıldıktan sonra yürütülecek SQ&L + + + + Default field type + Varsayılan alan türü + + + + Font + Yazı Tipi + + + + &Font + &Yazı Tipi + + + + Content + İçerik + + + + Symbol limit in cell + Hücredeki sembol limiti + + + + Threshold for completion and calculation on selection + Seçimdeki tamamlama ve hesaplama eÅŸiÄŸi + + + + Show images in cell + Resimleri hücrede göster + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + Hücrelerde görüntü verileri içeren BLOB tipindeki verilerin ön izlemesini göstermek için bu seçeneÄŸi etkinleÅŸtirin. Ancak bu, veri görüntüleyicisinin performansını etkileyebilir. + + + + NULL + NULL + + + + Regular + Kurallı + + + + Binary + İkili veri + + + + Background + Arka Plan + + + + Filters + Filtreler + + + + Toolbar style + Araç çubuÄŸu stili + + + + + + + + Only display the icon + Sadece simgeyi göster + + + + + + + + Only display the text + Sadece metni göster + + + + + + + + The text appears beside the icon + Metin simgenin yanında görünsün + + + + + + + + The text appears under the icon + Metin simgenin altında görünsün + + + + + + + + Follow the style + Stili baz al + + + + DB file extensions + Veritabanı dosya uzantıları + + + + Manage + Yönet + + + + Main Window + Ana Pencere + + + + Database Structure + Veritabanı Yapısı + + + + Browse Data + Verilere Göz At + + + + Execute SQL + SQL kodunu yürüt + + + + Edit Database Cell + Veritabanı Hücresini Düzenle + + + + When this value is changed, all the other color preferences are also set to matching colors. + Bu deÄŸer deÄŸiÅŸtirildiÄŸinde, diÄŸer tüm renk tercihleri de eÅŸleÅŸen renklere ayarlanır. + + + + Follow the desktop style + Masaüstü stilini baz al + + + + Dark style + Koyu tema + + + + Light style + Aydınlık stil + + + + Application style + Uygulama stili + + + + This sets the font size for all UI elements which do not have their own font size option. + Bu, kendi yazı tipi boyutu seçeneÄŸi olmayan tüm kullanıcı arayüzü ögelerinin yazı tipi boyutunu ayarlar. + + + + Font size + Yazı tipi boyutu + + + + Max Recent Files + En Son Dosyalar + + + + Prompt to save SQL tabs +in new project file + SQL sekmelerini kaydetme istemi +yeni proje dosyasına + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + Bu açıksa SQL düzenleyici sekmesi kapatıldığında SQL düzenleyicide yapılan deÄŸiÅŸiklikler bir proje kaydetme onay iletiÅŸim kutusu oluÅŸturur. + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + EtkinleÅŸtirildiÄŸinde, Veritabanı Yapısı sekmesinin Åžema sütununda satır sonu karakterleri ve yazdırılan çıktılar kaldırılır. + + + + Database structure font size + Veritabanı yapısı yazı tipi boyutu + + + + Font si&ze + Yazı tipi b&oyutu + + + + Formatted + BiçimlendirilmiÅŸ + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + Bu, bazı hesaplama açısından pahalı iÅŸlevlerin etkinleÅŸtirilmesine izin verilen maksimum öge sayısıdır: +Sütundaki geçerli deÄŸerlere dayalı olarak deÄŸer tamamlamayı etkinleÅŸtirmek için bir tablodaki maksimum satır sayısı. +Toplam ve ortalamayı hesaplamak için bir seçimdeki maksimum indeks sayısı. +İşlevleri devre dışı bırakmak için 0 olarak ayarlanabilir. + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + Bu, sütundaki geçerli deÄŸerlere dayalı olarak deÄŸer tamamlamayı etkinleÅŸtirmek için bir tablodaki maksimum satır sayısıdır. +Tamamlamayı devre dışı bırakmak için 0 olarak ayarlanabilir. + + + + Selection background + Seçim arka planı + + + + Selection foreground + Seçim ön planı + + + + Highlight + Vurgu + + + + Use tabs for indentation + Girinti için sekmeleri kullanın + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + Ayarlandığında, Tab tuÅŸu girinti için sekme ve boÅŸluk karakterleri ekler. Aksi takdirde, yalnızca boÅŸluklar kullanılır. + + + + Close button on tabs + Sekmelerdeki düğmeyi kapat + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + EtkinleÅŸtirildiÄŸinde, SQL düzenleyici sekmelerinde bir kapatma düğmesi bulunur. Her durumda, baÄŸlam menüsünü veya klavye kısayolunu kullanarak bunları kapatabilirsiniz. + + + + Select built-in extensions to load for every database: + Her veritabanı için yüklenecek yerleÅŸik uzantıları seçin: + + + + Proxy + Proxy + + + + Configure + Yapılandır + + + + Export Settings + Ayarları Dışa Aktar + + + + Import Settings + Ayarları İçe Aktar + + + + Field display + Alan görünümü + + + + Displayed &text + Görün&tülenen metin + + + + + + + + + + + Click to set this color + Bu rengi ayarlamak için tıklayın + + + + Text color + Metin rengi + + + + Background color + Arka plan rengi + + + + + Preview only (N/A) + Sadece ön izleme (N/A) + + + + Escape character + Kaçış karakteri + + + + Delay time (&ms) + Gecikme süresi (&ms) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + Yeni bir filtre deÄŸeri uygulanmadan önce bekleme süresini ayarla. Beklemeyi devre dışı bırakmak için 0 deÄŸeri ayarlanabilir. + + + + &SQL + &SQL + + + + Context + Özellik + + + + Colour + Renk + + + + Bold + Kalın + + + + Italic + İtalik + + + + Underline + Altı çizili + + + + Keyword + Anahtar Kelime + + + + Function + Fonksiyon + + + + Table + Tablo + + + + Comment + Yorum + + + + Identifier + Kimlik + + + + String + Dize + + + + Current line + Geçerli satır + + + + SQL &editor font size + SQL &editör yazı tipi boyutu + + + + Tab size + TAB karakter boyutu + + + + &Wrap lines + &Satırları kaydır + + + + Never + Asla + + + + At word boundaries + Kelime dahilinde + + + + At character boundaries + Karakter dahilinde + + + + At whitespace boundaries + Beyaz boÅŸluk dahilinde + + + + &Quotes for identifiers + Tanımlayıcılar için &tırnaklar + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + Uygulama tarafından SQL kodundaki tanımlayıcılar için kullanılan tırnak stilini seçin. + + + + "Double quotes" - Standard SQL (recommended) + "Çift tırnak" - Standart SQL (önerilir) + + + + `Grave accents` - Traditional MySQL quotes + `Ters tırnaklar` - Geleneksel MySQL tırnakları + + + + [Square brackets] - Traditional MS SQL Server quotes + [Köşeli parantezler] - Geleneksel MS SQL Server + + + + Keywords in &UPPER CASE + Anahtar kelimeler B&ÜYÜK HARFLİ + + + + When set, the SQL keywords are completed in UPPER CASE letters. + Ayarlandığında, SQL anahtar kelimeleri BÜYÜK HARFLERLE tamamlanır. + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + Ayarlandığında, son yürütme sırasında hatalara neden olan SQL kod satırları vurgulanır ve sonuç çerçevesi arka plandaki hatayı gösterir + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html> <head /> <body> <p> SQLite, paylaşılmış kütüphane dosyasından eklenti yüklemeye yarayan bir fonksiyon sunar. <span style=" font-style:italic;">load_extension()</span> fonksiyonunu SQL kodu içerisinde kullanmak istiyorsanız fonksiyonu aktive edin. </p> <p> Güvenlik nedeniyle, uzantı yüklemesi varsayılan olarak kapalıdır ve bu ayar ile etkinleÅŸtirilmelidir. Bu seçenek devre dışı bırakılmış olsa bile, uzantıları her zaman GUI üzerinden yükleyebilirsiniz. </p> </body> </html> + + + + Allow loading extensions from SQL code + SQL kodundan eklenti yüklemeye izin ver + + + + Remote + Uzak Bilgisayar + + + + CA certificates + CA sertifikaları + + + + + Subject CN + CN Konusu + + + + Common Name + Yaygın İsim + + + + Subject O + O Konusu + + + + Organization + Organizasyon + + + + + Valid from + Åžu tarihten itibaren geçerli + + + + + Valid to + Åžu tarihe kadar geçerli + + + + + Serial number + Seri numarası + + + + Your certificates + Sertifikalarınız + + + + File + Dosya + + + + Subject Common Name + Ortak Konu Adı + + + + Issuer CN + CN SaÄŸlayıcısı + + + + Issuer Common Name + Ortak SaÄŸlayıcı Adı + + + + Clone databases into + Veritabanını ÅŸuraya kopyala + + + + SQL editor &font + SQL editör &yazı tipi + + + + Error indicators + Hata belirteçleri + + + + Hori&zontal tiling + Ya&tay döşeme + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + EtkinleÅŸtirilirse SQL kod düzenleyicisi ve sonuç tablosu görünümü üst üste yerine yan yana gösterilir. + + + + Code co&mpletion + Kod ta&mamlama + + + + Foreground + Ön plan + + + + SQL &results font size + S&QL sonuçları yazı tipi boyutu + + + + &Extensions + &Eklentiler + + + + Select extensions to load for every database: + Her veritabanında kullanmak için eklenti seçiniz: + + + + Add extension + Eklenti Ekle + + + + Remove extension + Eklenti Sil + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>Kurallı ifade(REGEXP) operatörü aktif edildiÄŸinde SQLite, herhangi bir kurallı ifade uygulamaz ama ÅŸuan da çalışan uygulamayı geri çağırır. <br/>SQLite DB Browser kurallı ifadeyi kutunun dışında kullanmanıza izin vermek için bu algoritmayı uygular. <br/>Birden çok muhtemel uygulama olduÄŸu gibi sizde farklı birini kullanabilirsiniz.<br/>Programın uygulamalarını devre dışı bırakmakta ve kendi eklentinizle kendi uygulamanızı yüklemekte özgürsünüz.<br/>Ayrıca uygulamayı yeniden baÅŸlatmak gerekir.</p></body></html> + + + + Disable Regular Expression extension + Kurallı İfade eklentisini devre dışı bırak + + + + + Choose a directory + Dizin seçiniz + + + + + The language will change after you restart the application. + Seçilen dil uygulama yeniden baÅŸlatıldıktan sonra uygulanacaktır. + + + + Select extension file + Eklenti dosyası seçiniz + + + + Extensions(*.so *.dylib *.dll);;All files(*) + Eklentiler(*.so *.dylib *.dll);;Tüm dosyalar(*) + + + + Import certificate file + Sertifika dosyası içe aktar + + + + No certificates found in this file. + Bu dosyada sertifika bulunamadı. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + Bu sertifikayı kaldırmak istediÄŸinizden emin misiniz? Tüm sertifika verileri uygulama ayarlarından silinecektir! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + Kaydedilen tüm ayarları silmek istediÄŸinizden emin misiniz? +Tüm tercihleriniz kaybolacak ve varsayılan deÄŸerler kullanılacak. + + + + Save Settings File + Ayarlar Dosyasını Kaydet + + + + + Initialization File (*.ini) + BaÅŸlatma Dosyası (*.ini) + + + + The settings file has been saved in location : + + Ayarlar dosyası ÅŸu konuma kaydedildi: + + + + + Open Settings File + Ayarlar Dosyasını Aç + + + + The settings file was loaded properly. + Ayarlar dosyası düzgün bir ÅŸekilde yüklendi. + + + + The selected settings file is not a normal settings file. +Please check again. + Seçilen ayar dosyası normal bir ayar dosyası deÄŸil. + Lütfen tekrar kontrol edin. + + + + ProxyDialog + + + Proxy Configuration + Proxy Yapılandırması + + + + Pro&xy Type + Pro&xy Türü + + + + Host Na&me + A&na Bilgisayar Adı + + + + Port + Port + + + + Authentication Re&quired + Kimlik &DoÄŸrulaması Gerekli + + + + &User Name + K&ullanıcı Adı + + + + Password + Parola + + + + None + Hiçbiri + + + + System settings + Sistem ayarları + + + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 + + + + QObject + + + Error importing data + Veriyi içe aktarılırken hata oluÅŸtu + + + + from record number %1 + kayıt numarasından: %1 + + + + . +%1 + . %1 + + + + Importing CSV file... + CSV dosyası içe aktarılıyor... + + + + Cancel + İptal + + + + All files (*) + Tüm dosyalar (*) + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + SQLite veritabanı dosyaları (*.db *.sqlite *.sqlite3 *.db3) + + + + Left + Sola Hizala + + + + Right + SaÄŸa Hizala + + + + Center + Ortala + + + + Justify + İki yana yasla + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + SQLite Veritabanı Dosyaları (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + DB Browser for SQLite Proje Dosyaları (*.sqbpro) + + + + SQL Files (*.sql) + SQL Dosyaları (*.sql) + + + + All Files (*) + Tüm Dosyalar (*) + + + + Text Files (*.txt) + Metin Dosyaları (*.txt) + + + + Comma-Separated Values Files (*.csv) + Virgülle Ayrılmış DeÄŸerler Dosyaları (* .csv) + + + + Tab-Separated Values Files (*.tsv) + Tab ile Ayrılmış DeÄŸerler Dosyaları (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + Sınırlayıcı ile Ayrılmış DeÄŸerler Dosyaları (* .dsv) + + + + Concordance DAT files (*.dat) + Uyumluluk DAT dosyaları (* .dat) + + + + JSON Files (*.json *.js) + JSON Dosyaları (*.json *.js) + + + + XML Files (*.xml) + XML Dosyaları (*.xml) + + + + Binary Files (*.bin *.dat) + İkili Dosyalar (*.bin *.dat) + + + + SVG Files (*.svg) + SVG Dosyaları (*.svg) + + + + Hex Dump Files (*.dat *.bin) + Onaltılık Döküm Dosyaları (* .dat * .bin) + + + + Extensions (*.so *.dylib *.dll) + Eklentiler (* .so * .dylib * .dll) + + + + Initialization File (*.ini) + BaÅŸlatma Dosyası (*.ini) + + + + QsciCommand + + Paste + Yapıştır + + + Cancel + İptal + + + + QsciLexerCPP + + Default + Varsayılan + + + Keyword + Anahtar Kelime + + + Identifier + Kimlik + + + + QsciLexerJSON + + Default + Varsayılan + + + String + String + + + + QsciLexerJavaScript + + Regular expression + Düzenli ifadeler (RegEx) + + + + QsciLexerPython + + Default + Varsayılan + + + Comment + Yorum + + + Keyword + Anahtar Kelime + + + Identifier + Kimlik + + + + QsciLexerSQL + + Default + Varsayılan + + + Comment + Yorum + + + Keyword + Anahtar Kelime + + + Identifier + Kimlik + + + + QsciScintilla + + Select All + Tümünü Seç + + + + RemoteCommitsModel + + + Commit ID + Commit ID + + + + Message + Mesaj + + + + Date + Tarih + + + + Author + Yazar + + + + Size + Boyut + + + + Authored and committed by %1 + %1 tarafından yazıldı ve iÅŸlendi + + + + Authored by %1, committed by %2 + %1 tarafından yazıldı, %2 tarafından iÅŸlendi + + + + RemoteDatabase + + + Error opening local databases list. +%1 + Yerel veritabanı listesi açılamadı. +%1 + + + + Error creating local databases list. +%1 + Yerel veritabanı listesi oluÅŸturulamadı. +%1 + + + + RemoteDock + + + Remote + Uzak Bilgisayar + + + + Identity + Kmlik + + + + Push currently opened database to server + Åžu anda açık olan veritabanını sunucuya aktar + + + + Upload + Yükle + + + + DBHub.io + DBHub.io + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>Bu bölmede, dbhub.io web sitesinden uzak veritabanları SQLite için DB Tarayıcısına eklenebilir. Öncelikle bir kimliÄŸe ihtiyacınız var:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">dbhub.io web sitesine giriÅŸ yapın (GitHub kimlik bilgilerinizi veya istediÄŸiniz herhangi bir ÅŸeyi kullanın)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">"İstemci sertifikası oluÅŸtur" düğmesine tıklayın (bu sizin kimliÄŸinizdir). Bu size bir sertifika dosyası verecektir (bunu yerel diskinize kaydedin).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">SQLite için Veritabanı Tarayıcısı Tercihleri'ndeki Uzak sekmesine gidin. SQLite için Veritabanı Tarayıcısı'na yeni bir sertifika eklemek için düğmeye tıklayın ve az önce indirdiÄŸiniz sertifika dosyasını seçin.</li></ol><p>Artık Uzak paneli kimliÄŸinizi gösterecek ve uzak veritabanları ekleyebilirsiniz.</p></body></html> + + + + Local + Yerel + + + + Current Database + Güncel Veritabanı + + + + Clone + Klonla + + + + Branch + Dal + + + + Commits + Commitler + + + + Commits for + Commitler için + + + + Delete Database + Veritabanını Sil + + + + Delete the local clone of this database + Bu veritabanının yerel klonunu silin + + + + Open in Web Browser + Web Tarayıcısında Aç + + + + Open the web page for the current database in your browser + Tarayıcınızda geçerli veritabanının web sayfasını açın + + + + Clone from Link + BaÄŸlantıdan Klonla + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + Bunu, veritabanının web sayfasında saÄŸlanan bir URL'yi kullanarak yerel düzenleme için uzak bir veritabanını indirmek için kullanın. + + + + Refresh + Yenile + + + + Reload all data and update the views + Tüm verileri yeniden yükle ve görünümleri güncelle + + + + Clone Database + Veritabanını Klonla + + + + Open Database + Veritabanını Aç + + + + Open the local copy of this database + Bu veritabanının yerel kopyasını açın + + + + Check out Commit + Commit'i Kontrol Edin + + + + Download and open this specific commit + Bu özel commiti indirin ve açın + + + + Check out Latest Commit + En Son Commiti Kontrol Edin + + + + Check out the latest commit of the current branch + Mevcut dalın en son commitini kontrol edin + + + + Save Revision to File + Revizyonu Dosyaya Kaydet + + + + Saves the selected revision of the database to another file + Veritabanının seçili revizyonunu baÅŸka bir dosyaya kaydeder + + + + Upload Database + Veritabanını Yükle + + + + Upload this database as a new commit + Bu veritabanını yeni bir commit olarak yükleyin + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html> <head /> <body> <p> Åžu anda dahili, salt okunur kimlik kullanıyorsunuz. Kendi veritabanınızı yüklemek için DBHub.io hesabı kullanıp konfigure etmeniz gerekiyor. </p> <p> Henüz DBHub.io hesabınız yok mu? <a href="https://dbhub.io/" ><span style=" text-decoration: underline; color:#007af4;" >Åžimdi bir tane oluÅŸturun</span ></a > ve veritabanınızı paylaÅŸmak için <a href="#preferences" ><span style=" text-decoration: underline; color:#007af4;" >buradan</span ></a > sertifikanızı içe aktarın. </p> <p> Çevrimiçi yardım için <a href="https://dbhub.io/about" ><span style=" text-decoration: underline; color:#007af4;" >burayı</span ></a > ziyaret edin. </p> </body> </html> + + + + &User + &Kullanıcı + + + + &Database + &Veritabanı + + + + Back + Geri + + + + Select an identity to connect + BaÄŸlanmak için bir kimlik seçin + + + + Public + Genel + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + Bu, yerel düzenleme için uzak bir sunucudan bir veritabanı indirir. +Lütfen klonlanacak URL'yi girin. Bu URL'yi, veritabanının web +sayfasındaki 'DB4S'de Veritabanını Klonla' düğmesine +tıklayarak oluÅŸturabilirsiniz. + + + + Invalid URL: The host name does not match the host name of the current identity. + Geçersiz URL: Ana bilgisayar adı, geçerli kimliÄŸin ana bilgisayar adıyla eÅŸleÅŸmiyor. + + + + Invalid URL: No branch name specified. + Geçersiz URL: Herhangi bir dal adı belirtilmedi. + + + + Invalid URL: No commit ID specified. + Geçersiz URL: Belirtilen bir commit kimliÄŸi yok. + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + Veritabanının yerel klonunu deÄŸiÅŸtirdiniz. Bu commit'i almak, bu yerel deÄŸiÅŸiklikleri geçersiz kılar. +Devam etmek istediÄŸinizden emin misiniz? + + + + The database has unsaved changes. Are you sure you want to push it before saving? + Veritabanında kaydedilmemiÅŸ deÄŸiÅŸiklikler var. Kaydetmeden önce göndermek istediÄŸinizden emin misiniz? + + + + The database you are trying to delete is currently opened. Please close it before deleting. + Silmeye çalıştığınız veritabanı ÅŸu anda açık. Lütfen silmeden önce kapatın. + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + Bu, henüz kaydetmediÄŸiniz tüm deÄŸiÅŸikliklerle birlikte bu veritabanının yerel sürümünü siler. Bu veritabanını silmek istediÄŸinizden emin misiniz? + + + + RemoteLocalFilesModel + + + Name + İsim + + + + Branch + Dal + + + + Last modified + Son deÄŸiÅŸtirilme + + + + Size + Boyut + + + + Commit + Commit + + + + File + Dosya + + + + RemoteModel + + + Name + İsim + + + + Commit + Commit + + + + Last modified + Son deÄŸiÅŸtirilme + + + + Size + Boyut + + + + Size: + Boyut: + + + + Last Modified: + Son DeÄŸiÅŸtirilme: + + + + Licence: + Lisans: + + + + Default Branch: + Varsayılan Dal: + + + + RemoteNetwork + + + Choose a location to save the file + Dosyayı kaydetmek için bir konum seçin + + + + Error opening remote file at %1. +%2 + %1 adresinde bulunan dosya açılamadı. +%2 + + + + Error: Invalid client certificate specified. + Hata: Geçersiz istemci sertifikası belirtildi. + + + + Please enter the passphrase for this client certificate in order to authenticate. + Kimlik doÄŸrulaması için lütfen istemci sertifikasının parolasını girin. + + + + Cancel + İptal + + + + Uploading remote database to +%1 + Uzak veritabanı karşıya yükleniyor +%1 + + + + Downloading remote database from +%1 + Uzaktaki sunucu indiriliyor: +%1 + + + + Error: Cannot open the file for sending. + Hata: Dosya gönderim için açılamadı. + + + + RemotePushDialog + + + Push database + Veritabanını zorla + + + + Database na&me to push to + Gönderilecek veritaba&nı adı + + + + Commit message + Commit mesajı + + + + Database licence + Veritabanı lisansı + + + + Public + Genel + + + + Branch + Dal + + + + Force push + Zorla itme + + + + Username + Kullanıcı adı + + + + Database will be public. Everyone has read access to it. + Veritabanı halka açık olacak. Herkes okuma iznine sahip olacak. + + + + Database will be private. Only you have access to it. + Veritabanı özel olacak. Sadece sizin eriÅŸiminiz olacak. + + + + Use with care. This can cause remote commits to be deleted. + Dikkatlice kullanın. Bu, uzaktaki deÄŸiÅŸikliklerin silinmesine sebep olabilir. + + + + RunSql + + + Execution aborted by user + Yürütme kullanıcı tarafından durduruldu + + + + , %1 rows affected + , %1 satır etkilendi + + + + query executed successfully. Took %1ms%2 + sorgu baÅŸarıyla yürütüldü. %1ms%2 sürdü + + + + executing query + sorgu yürütülüyor + + + + SelectItemsPopup + + + A&vailable + &Kullanılabilir + + + + Sele&cted + &Seçili + + + + SqlExecutionArea + + + Form + Form + + + + Find previous match [Shift+F3] + Önceki eÅŸleÅŸmeyi bul [Shift, F3] + + + + Find previous match with wrapping + Sarmalayarak bir önceki eÅŸleÅŸmeyi bul + + + + Shift+F3 + Shift+F3 + + + + The found pattern must be a whole word + Bulunan desen tam bir kelime olmalıdır + + + + Whole Words + Kelimenin Tamamı + + + + Text pattern to find considering the checks in this frame + Bu alandaki kontrolleri baz alarak bulunacak metin deseni + + + + Find in editor + Editörde ara + + + + The found pattern must match in letter case + Bulunan desen büyük/küçük harfe duyarlı olmalıdır + + + + Case Sensitive + Büyük/küçük harfe duyarı + + + + Find next match [Enter, F3] + Sonraki eÅŸleÅŸmeyi bul [Enter, F3] + + + + Find next match with wrapping + Sarmalayarak bir sonraki eÅŸleÅŸmeyi bul + + + + F3 + F3 + + + + Interpret search pattern as a regular expression + Arama desenini düzenli ifade(RegEx) olarak yorumla + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html> <head /> <body> <p> İşaretlendiÄŸinde, girilen desen UNIX düzenli ifadesi olarak yorumlanır. <a href="https://en.wikibooks.org/wiki/Regular_Expressions" >Wikibooks</a > üzerinden düzenli ifadeleri inceleyebilirsiniz. </p> </body> </html> + + + + Regular Expression + Kurallı İfade (RegEx) + + + + + Close Find Bar + Bulma ÇubuÄŸunu Kapat + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html> <head /> <body> <p>Son yürütülen ifadelerin sonuçları.</p> <p> Bu paneli daraltmak ve bunun yerine <span style=" font-style:italic;">SQL Log Günlüğünü</span> <span style=" font-style:italic;">Kullanıcı</span> seçimi ile kullanmak isteyebilirsiniz. </p> </body> </html> + + + + Results of the last executed statements + Son yürütülen ifadenin sonucu + + + + This field shows the results and status codes of the last executed statements. + Bu alan son yürütülen ifadenin durum kodlarını ve sonuçlarını gösterir. + + + + Ctrl+PgUp + Ctrl+PgUp + + + + Ctrl+PgDown + Ctrl+PgDown + + + + Couldn't read file "%1": %2. + "%1" dosyası okunamadı: %2. + + + + + Couldn't save file: %1. + Dosya kaydedilemedi: %1. + + + + Your changes will be lost when reloading it! + Yeniden yüklerken deÄŸiÅŸiklikleriniz kaybolacak! + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + "%1" dosyası baÅŸka bir program tarafından deÄŸiÅŸtirildi. Yeniden yüklemek istiyor musunuz?%2 + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + Herhangi bir harici güncellemede fazla soru sormadan dosyayı yeniden yüklemek için "Tümüne Evet" yanıtını verin. + + + + Answer "No to All" to ignore any external update without further prompting. + Herhangi bir harici güncellemeyi fazla uyarı almadan yok saymak için "Tümüne Hayır" cevabını verin. + + + + Modifying and saving the file will restore prompting. + Dosyayı düzenleyip kaydettiÄŸinizde istem tekrar aktif olacak. + + + + SqlTextEdit + + + Ctrl+/ + + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) abs(X) fonksiyonu X sayısal argümanının mutlak deÄŸerini döndürür. + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () changes() fonksiyonu en son yürütülen INSERT, DELETE veya UPDATE ifadesinden etkilenen veritabanı satırlarının sayısını döndürür. + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) char(X1,X2,...,XN) fonksiyonu sırasıyla X1'den XN'e kadar olan tamsayıların unicode karakter karşılıklarından oluÅŸan dizeyi döndürür. + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) coalesce() fonksiyonu NULL olmayan ilk argümanı döndürür. EÄŸer tüm argümanlar NULL ise NULL deÄŸerini döndürür + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) glob(X,Y) fonksiyonu "Y GLOB X" ifadesinin eÅŸdeÄŸerini döndürür. + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) ifnull() fonksiyonu NULL olmayan ilk argümanı döndürür. EÄŸer her iki argüman da NULL ise NULL deÄŸerini döndürür. + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) instr(X,Y) fonksiyonu ilk önce X dizesinin içinde Y dizesinin içeriÄŸini arar ve eÅŸleÅŸen yerden önceki karakterlerin sayısının 1 fazlasını döndürür. EÄŸer Y, X içerisinde bulunmazsa 0 deÄŸerini döndürür. + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) hex() fonksiyonu argümanı BLOB olarak yorumlar ve BLOB içeriÄŸinin büyük harf onaltılık kısmını dize olarak döndürür. + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) The iif(X,Y,Z) fonksiyonu, X doÄŸruysa Y deÄŸerini, aksi takdirde Z deÄŸerini döndürür. + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () last_insert_rowid() fonksiyonu çaÄŸrılan veritabanı baÄŸlantısından en son eklenen satırın ROWID deÄŸerini döndürür. + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) length() fonksiyonu X dize deÄŸeri için NULL ifadesine kadar olan karakter sayısını döndürür (bayt olarak deÄŸil). + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) like() fonksiyonu "Y LIKE X" ifadesini uygulamak için kullanılır. + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) like() fonksiyonu "Y LIKE X ESCAPE Z" ifadesini uygulamak için kullanılır. + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) load_extension(X) fonksiyonu, SQLite eklentilerini X adlı paylaşılan kitaplık dosyasından yükler. Bu iÅŸlevin kullanımına Tercihler'den izin verilmelidir. + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X, Y) load_extension(X) iÅŸlevi, Y giriÅŸ noktasını kullanarak X adlı paylaşılan kitaplık dosyasından SQLite eklentilerini yükler. +Bu iÅŸlevin kullanımına Tercihler'den izin verilmelidir. + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) lower(X) fonksiyonu tüm X dizesinin tüm ASCII karakterlerinin küçük harfe dönüştürülmüş karşılığını döndürür. + + + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) fonksiyonu X'in sol tarafındaki boÅŸlukları siler. + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) ltrim(X,Y) fonksiyonu X'in sol tarafındaki Y'de bulunan tüm karakterlerin silinmiÅŸ halini dize halinde döndürür. + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) Çok argümanlı max() fonksiyonu en büyük deÄŸere sahip argümanı döndürür. EÄŸer herhangi bir argüman NULL ise NULL deÄŸerini döndürür. + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) Çok argümanlı min() fonksiyonu en küçük deÄŸere sahip argümanı döndürür. + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) nullif(X,Y) fonksiyonu eÄŸer argümanlar farklı ise ilk argümanı, eÄŸer argümanlar aynı ise NULL döndürür. + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) printf(FORMAT,...) SQL fonksiyonu C dilindeki sqlite3_mprintf() fonksiyonu ve standard C kütüphanesindeki printf() fonksiyonu ile aynı mantıkta çalışır. + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) quote(X) fonksiyonu girilen argümanlardan SQL ifadesi olarak tam anlamıyla dahil edilmeye uygun olanları döndürür. + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () random() fonksiyonu -9223372036854775808 ve +9223372036854775807 tamsayı deÄŸerli arasında rastgele deÄŸer döndürür. + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) randomblob(N) fonksiyonu rastgele bayt içeren N-byte türünde blob döndürür. + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) replace(X,Y,Z) fonksiyonu X içindeki her Y argümanını, Z argümanıyla deÄŸiÅŸtirmesiyle oluÅŸan dizeyi döndürür. - - - Compact the database file, removing space wasted by deleted records. - Veritabanı dosyasını geniÅŸletmek, silinen kayıtlardan dolayı meydana gelen boÅŸlukları temizler. + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) round(X) fonksiyonu X ondalıklı sayısının ondalıklı kısmın sıfıra yuvarlanmasıyla oluÅŸan deÄŸeri döndürür. - - E&xit - &Çıkış + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) round(X,Y) fonksiyonu X ondalıklı sayısının Y kadar sağındaki ondalıklı kısmı sıfıra yuvarlanmasıyla oluÅŸan deÄŸeri döndürür. - - Ctrl+Q - Ctrl+Q + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X) fonksiyonu X'in saÄŸ tarafındaki boÅŸlukları siler. - - Database from SQL file... - SQL dosyasından veritabanı... + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) rtrim(X,Y) fonksiyonu X'in saÄŸ tarafındaki Y'de bulunan tüm karakterlerin silinmiÅŸ halini dize halinde döndürür. - - Import data from an .sql dump text file into a new or existing database. - Verileri .sql uzantılı döküm dosyasından varolan veya yeni veritabanına aktarın. + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) soundex(X) fonksiyonu X dizesinin soundex kodlamasını string olarak döndürür. - - This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. - Bu seçenek verileri .sql döküm dosyasından varolan veya yeni veritabanına aktarmanıza olanak saÄŸlar. SQL dosyaları MySQL ve PostgreSQL dahil olmak üzere birçok veritabanı motorları tarafından oluÅŸtururlar. + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) substr(X,Y) fonksiyonu X dizesinin baÅŸlangıcından Y. indekse kadar olan string bölümünü döndürür. - - Table from CSV file... - CSV dosyasından tablo... + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) substr(X,Y,Z) fonksiyonu X dizesinin Y. indeksinden baÅŸlayarak Z uzunluÄŸu kadar olan string bölümünü döndürür. - - Open a wizard that lets you import data from a comma separated text file into a database table. - Virgülle ayrılmış metin dosyalarını veritabanınızın içine aktarmanızı saÄŸlayan sihirbazı açar. + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () total_changes() fonksiyonu geçerli veritabanı baÄŸlantısı açıldığından itibaren INSERT, UPDATE veya DELETE ifadelerinden etkilenen toplam satır sayısını döndürür. - - Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. - Virgülle ayrılmış metin dosyalarını veritabanınızın içine aktarmanızı saÄŸlayan sihirbazı açar. CSV dosyaları çoÄŸu veritabanı motorları ve elektronik tablo uygulamaları tarafından oluÅŸtururlar. + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) fonksiyonu X'in içinde bulunan boÅŸlukları siler. - - Database to SQL file... - Veritabanından SQL dosyası... + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) trim(X,Y) fonksiyonu X'in içindeki Y'de bulunan tüm karakterlerin silinmiÅŸ halini dize halinde döndürür. - - Export a database to a .sql dump text file. - Veritabanını .sql döküm dosyası olarak dışa aktar. + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) typeof(X) fonksiyonu X ifadesinin veri tipini gösteren dizeyi döndürür. - - This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. - Bu seçenek veritabanını .sql döküm dosyası olarak dışa aktarmanızı saÄŸlar. SQL döküm dosyaları veritabanını, MySQL ve PostgreSQL dahil birçok veritabanı motorunda yeniden oluÅŸturmak için gereken verilerin tümünü içerir. + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) unicode(X) fonksiyonu X'in ilk karakterine karşılık gelen unicode kod noktasını döndürür. - - Table(s) as CSV file... - Tablo(lar)dan CSV dosyası... + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) upper(X) fonksiyonu tüm X dizesinin tüm küçük ASCII karakterlerinin büyük harf karşılığına çevrilmiÅŸ kopyasını döndürür. - - Export a database table as a comma separated text file. - Veritabanı tablosunu virgülle ayrılmış metin dosyası olarak dışa aktar. + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) zeroblob(N) fonksiyonu 0x00'ın N bayt kadar meydana gelmiÅŸ halini BLOB olarak döndürür. - - Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. - Veritabanını virgülle ayrılmış metin dosyası olarak diÄŸer veritabanı veya elektronik tablo uygulamalarına aktarmaya hazır olacak ÅŸekilde dışa aktarın. + + + + + (timestring,modifier,modifier,...) + - - Create Table... - Tablo OluÅŸturun... + + (format,timestring,modifier,modifier,...) + - - Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database - Tablo OluÅŸturma sihirbazı, veritabanı için alanlarını ve ismini ayarlayabileceÄŸiniz, yeni bir tablo oluÅŸturmanızı saÄŸlar. + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) avg() fonksiyonu bir gruptaki NULL olmayan tüm X deÄŸerlerinin ortalama deÄŸerini döndürür. - - Delete Table... - Tabloyu Sil... + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) count(X) fonksiyonu bir gruptaki X'in kaç kere NULL olmadığının sayısını döndürür. - - - Delete Table - Tabloyu Sil + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) group_concat() fonksiyonu X'in NULL olmayan tüm deÄŸerlerle birleÅŸimini dize olarak döndürür. - - Open the Delete Table wizard, where you can select a database table to be dropped. - Tablo Silme sihirbazı, seçtiÄŸiniz tabloları silmenizi saÄŸlar. + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) group_concat() fonksiyonu X'in NULL olmayan tüm deÄŸerlerle birleÅŸimini dize olarak döndürür. EÄŸer Y parametresi mevcutsa X'in örnekleri arasında ayraç olarak kullanılır. - - Modify Table... - Tabloyu Düzenle... + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) max() küme fonksiyonu gruptaki tüm deÄŸerler arasından en büyük deÄŸeri döndürür. - - Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields form a table, as well as modify field names and types. - Tablo Düzenleme sihirbazı, varolan tablonuzu yeniden adlandırmanıza olanak saÄŸlar. Ayrıca yeni alan ekleyebilir, silebilir hatta alanların ismini ve tipini de düzenleyebilirsiniz. + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) min() küme fonksiyonu gruptaki NULL olmayan tüm deÄŸerler arasından en küçük deÄŸeri döndürür. - - Create Index... - İndeks OluÅŸtur... + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) sum() ve total() küme fonksiyonları gruptaki NULL olmayan tüm deÄŸerlerin toplamını döndürür. - - Open the Create Index wizard, where it is possible to define a new index on an existing database table. - İndeks OluÅŸturma sihirbazı, varolan veritabanı tablosuna yeni indeks tanımlamanıza olanak saÄŸlar. + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () Geçerli bölümdeki satır sayısı. Satırlar, 1'den baÅŸlayarak, tanım penceresinde ORDER BY ifadesi tarafından tanımlanan sırada veya aksi takdirde rastgele sırada numaralandırılır. - - &Preferences... - &Tercihler... + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () row_number() her gruptaki ilk eÅŸin - boÅŸlukları olan geçerli satırın sırası. ORDER BY ifadesi yoksa, tüm satırlar eÅŸ olarak kabul edilir ve bu iÅŸlev her zaman 1 deÄŸerini döndürür. - - - Open the preferences window. - Tercihler penceresini açar. + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () Geçerli satırın kendi bölümündeki eÅŸ grubunun sayısı - boÅŸluklar olmadan geçerli satırın sırası. Bölümler, 1'den baÅŸlayarak, tanım penceresindeki ORDER BY ifadesi tarafından tanımlanan sırada numaralandırılır. ORDER BY iifadesi yoksa, tüm satırlar eÅŸ olarak kabul edilir ve bu iÅŸlev her zaman 1 deÄŸerini döndürür. - - &DB Toolbar - &Veritabanı Araç ÇubuÄŸu + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () İsme raÄŸmen, bu iÅŸlev her zaman 0.0 ile 1.0 arasında (sıralama - 1) / (bölüm satırları - 1) deÄŸerine bir deÄŸer döndürür; burada sıralama, yerleÅŸik pencere rank() fonksiyonu ve bölüm- tarafından döndürülen deÄŸerdir. satırlar, bölümdeki toplam satır sayısıdır. Bölüm yalnızca bir satır içeriyorsa, bu iÅŸlev 0,0 deÄŸerini döndürür. - - Shows or hides the Database toolbar. - Veritabanı araç çubuÄŸunu gösterir veya gizler. + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () Kümülatif dağılım. Satır-sayısı/bölüm-satırları olarak hesaplanır; burada satır-sayısı, gruptaki son eÅŸ için row_number() tarafından döndürülen deÄŸerdir ve bölüm-satırdaki bölüm sayısıdır. - - What's This? - Bu nedir? + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) N argümanı bir tamsayı olarak ele alınır. Bu iÅŸlev, bölümü olabildiÄŸince eÅŸit bir ÅŸekilde N gruplarına böler ve ORDER BY ifadesi tarafından tanımlanan sırada veya aksi takdirde rasgele sırayla her gruba 1 ve N arasında bir tam sayı atar. Gerekirse, önce daha büyük gruplar oluÅŸur. Bu iÅŸlev, geçerli satırın parçası olduÄŸu gruba atanan tamsayı deÄŸerini döndürür. - - Shift+F1 - Shift+F1 + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) Bölümdeki önceki satıra göre expr ifade deÄŸerlendirmesinin sonucunu döndürür. Veya, önceki satır yoksa (geçerli satır ilk satır olduÄŸu için), NULL. - - &About... - &Hakkında... + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr,offset) Uzaklık deÄŸiÅŸkeni saÄŸlanırsa negatif olmayan bir tam sayı olmalıdır. Bu durumda, döndürülen deÄŸer, bölüm içindeki geçerli satırdan önce satır ofseti satırlarına göre ifade deÄŸerlendirmesinin sonucudur. Ofset 0 ise ifade geçerli satıra göre deÄŸerlendirilir. Geçerli satırdan önce satır kaydırma satırları yoksa NULL döndürülür. - - &Recently opened - En son açılanla&r + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,offset,default) Varsayılan da saÄŸlanmışsa ofset ile tanımlanan satır yoksa NULL döndürülür. - - Open &tab - Se&kme Aç + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) Bölümdeki bir sonraki satıra göre expr ifade deÄŸerlendirmesinin sonucunu döndürür. Veya, bir sonraki satır yoksa (geçerli satır son olduÄŸu için), NULL. - - Ctrl+T - Ctrl+T + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,offset) Uzaklık deÄŸiÅŸkeni saÄŸlanırsa negatif olmayan bir tam sayı olmalıdır. Bu durumda, döndürülen deÄŸer, bölüm içindeki geçerli satırdan sonra ifade ofset satırlarına göre ifade deÄŸerlendirmesinin sonucudur. Ofset 0 ise ifade geçerli satıra göre deÄŸerlendirilir. Geçerli satırdan sonra satır ofseti satırı yoksa NULL döndürülür. - - &Execute SQL - &SQL kodunu yürüt + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) Bu yerleÅŸik pencere iÅŸlevi, her satır için pencere çerçevesini birleÅŸtirilmiÅŸ pencere iÅŸlevi ile aynı ÅŸekilde hesaplar. Her satır için pencere çerçevesindeki ilk satıra karşı deÄŸerlendirilen ifade deÄŸerini döndürür. - - Execute SQL [F5, Ctrl+Return] - SQL kodunu yürüt [F5, Ctrl+Enter] + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) Bu yerleÅŸik pencere iÅŸlevi, her satır için pencere çerçevesini birleÅŸtirilmiÅŸ pencere iÅŸlevi ile aynı ÅŸekilde hesaplar. Her satır için pencere çerçevesindeki son satıra göre deÄŸerlendirilen ifade deÄŸerini döndürür. - - Open SQL file - SQL dosyası aç + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr,N) Bu yerleÅŸik pencere iÅŸlevi, her satır için pencere çerçevesini birleÅŸtirilmiÅŸ pencere iÅŸlevi ile aynı ÅŸekilde hesaplar. Pencere çerçevesinin N satırına göre deÄŸerlendirilen ifade deÄŸerini döndürür. Satırlar, pencere çerçevesi içinde 1'den baÅŸlayarak, ORDER BY deyimi tarafından varsa veya baÅŸka bir ÅŸekilde rastgele sırada numaralandırılır. Bölümde N'inci satırı yoksa NULL döndürülür. - - - - Save SQL file - SQL dosyasını kaydet + + (X) Return the arccosine of X. The result is in radians. + (X) X'in ark kosinüsünü döndür. Sonuç radyan cinsindendir. - - Load extension - Eklenti yükle + + (X) Return the hyperbolic arccosine of X. + (X) X'in hiperbolik ark kosinüsünü döndür. - - Execute current line - Geçerli satırı yürüt + + (X) Return the arcsine of X. The result is in radians. + (X) X'in ark sinüsünü döndürür. Sonuç radyan cinsindendir. - - Execute current line [Ctrl+E] - Geçerli satırı yürüt [Ctrl+E] + + (X) Return the hyperbolic arcsine of X. + (X) X'in hiperbolik ark sinüsünü döndürür. - - Ctrl+E - Ctrl+E + + (X) Return the arctangent of X. The result is in radians. + (X) X'in ark tanjantını döndürür Sonuç radyan cinsindendir. - - Export as CSV file - CSV dosyası olarak dışa aktar + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + (X,Y) Y/X'in ark tanjantını döndürür. Sonuç radyan cinsindendir. Sonuç, X ve Y'nin iÅŸaretlerine baÄŸlı olarak doÄŸru kadrana yerleÅŸtirilir. - - Export table as comma separated values file - Tabloyu virgülle ayrılmış girdiler dosyası olarak dışa aktar + + (X) Return the hyperbolic arctangent of X. + (X) X'in hiperbolik ark tanjantını döndürür. - - &Wiki... - &Döküman... + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + (X) X'ten büyük veya ona eÅŸit ilk temsil edilebilir tam sayı deÄŸerini döndürür. X'in pozitif deÄŸerleri için bu rutin sıfırdan uzaklaşır. X'in negatif deÄŸerleri için bu rutin sıfıra doÄŸru yuvarlar. - - Bug &report... - Hata Bildi&r... + + (X) Return the cosine of X. X is in radians. + (X) X'in kosinüsünü döndürür. X radyan cinsindendir. - - Web&site... - Web &Sitesi... + + (X) Return the hyperbolic cosine of X. + (X) X'in hiperbolik kosinüsünü döndürür. - - Save Project - Projeyi Kaydet + + (X) Convert value X from radians into degrees. + (X) X deÄŸerini radyandan dereceye dönüştürür. - - - Save the current session to a file - Geçerli oturumu dosyaya kaydet + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + (X) e'nin (Euler sayısı, yaklaşık 2.71828182845905) X kuvvetine yükseltilmiÅŸ halini hesaplayın. - - Open Project - Proeje Aç + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + (X) X'ten küçük veya ona eÅŸit ilk temsil edilebilir tam sayı deÄŸerini döndürür. Pozitif sayılar için bu fonksiyon sıfıra doÄŸru yuvarlar. Negatif sayılar için bu fonksiyon sıfırdan uzaklaşır. - - - Load a working session from a file - Dosyadan çalışma oturumunu yükle + + (X) Return the natural logarithm of X. + X) X'in doÄŸal logaritmasını döndürür. - - &Attach Database - Verit&abanını İliÅŸtir + + (B,X) Return the base-B logarithm of X. + (B,X) X'in B tabanındaki logaritmasını döndürür. - - Set Encryption - Åžifre Ayarla + + + (X) Return the base-10 logarithm for X. + (X) X'in 10 tabanlı logaritmasını döndür. - - - Save SQL file as - SQL dosyasını bu ÅŸekilde kaydet + + (X) Return the logarithm base-2 for the number X. + (X) X sayısının 2 tabanındaki logaritmasını döndürür. - - &Browse Table - &Tabloyu Görüntüle + + (X,Y) Return the remainder after dividing X by Y. + (X,Y) X'i Y'ye böldükten sonra kalanı döndürür. - - Copy Create statement - 'Create' ifadesini kopyala + + () Return an approximation for Ï€. + () Ï€ için bir yaklaşım deÄŸeri döndürür. - - Copy the CREATE statement of the item to the clipboard - Objenin 'Create' ifadesini panoya kopyala + + + (X,Y) Compute X raised to the power Y. + (X,Y) X'in Y'ye yükseltilmiÅŸ deÄŸerini hesaplayın. - - Ctrl+Return - Ctrl+Return + + (X) Convert X from degrees into radians. + (X) X'i dereceden radyana dönüştürün. - - Ctrl+L - Ctrl+L + + (X) Return the sine of X. X is in radians. + (X) X'in sinüsünü döndürür. X radyan cinsindendir. - - Ctrl+P - Ctrl+P + + (X) Return the hyperbolic sine of X. + (X) X'in hiperbolik sinüsünü döndürür. - - Ctrl+D - Ctrl+D + + (X) Return the square root of X. NULL is returned if X is negative. + (X) X'in karekökünü döndürür. X negatifse NULL döndürülür. - - Ctrl+I - Ctrl+I + + (X) Return the tangent of X. X is in radians. + (X) X'in tanjantını döndürür. X radyan cinsindendir. - - Database encoding - Veritabanı kodlaması + + (X) Return the hyperbolic tangent of X. + (X) X'in hiperbolik tanjantını döndürür. - - Database is encrypted using SQLCipher - Veritabanı SQLCipher kullanılırak ÅŸifrelendi + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + (X) X ile 0 (dahil) arasında sıfırdan en uzak olan gösterilebilir tam sayıyı döndürür. Ya da baÅŸka bir deyiÅŸle, X'in tam sayı kısmını sıfıra yuvarlayarak döndürür. + + + SqliteTableModel - - - Choose a database file - Veritabanı dosyasını seçiniz + + reading rows + satırlar okunuyor - - SQLite database files (*.db *.sqlite *.sqlite3 *.db3);;All files (*) - SQLite veritabanı dosyaları (*.db *.sqlite *.sqlite3 *.db3);;Tüm dosyalar (*) + + loading... + yükleniyor... - - Invalid file format. - Geçersiz dosya formatı + + References %1(%2) +Hold %3Shift and click to jump there + Referanslar %1(%2) +Buraya atlamak için %3Shift'e basılı tutun ve tıklayın - - - - - Choose a filename to save under - Kaydetmek için dosya ismi seçiniz + + Error changing data: +%1 + Veri deÄŸiÅŸtirme hatası: %1 - - Error adding record: - - Kayıt ekleme hatası: + + retrieving list of columns + sütunların listesi alınıyor - - Error deleting record: -%1 - Kayıt silme hatası: + + Fetching data... + Veri alınıyor... - - Please select a record first - Lütfen öncelikle kaydı seçiniz + + + Cancel + İptal + + + TableBrowser - - %1 - %2 of %3 - %1 - %2 / %3 + + Browse Data + Veriyi Görüntüle - - - There is no database opened. Please open or create a new database file. - Açılmış veritabanı bulunamadı. Lütfen veritabanı açın veya yeni bir veritabanı oluÅŸturun. + + &Table: + &Tablo: - - Are you sure you want to delete the %1 '%2'? -All data associated with the %1 will be lost. - Gerçekten '%1' türüne ait '%2' nesnesini silmek istediÄŸinize emin misiniz? -'%1' ile iliÅŸkili bütün verileri kaybedeceksiniz. + + Select a table to browse data + Verileri görüntülemek için tablo seçiniz - - Error: could not delete the %1. Message from database engine: -%2 - Hata: '%1' silinemedi. Veritabanı motorunun mesajı: %2 + + Use this list to select a table to be displayed in the database view + Veritabanı görünümünde gösterilecek tabloyu seçmek için bu listeyi kullanın - - There is no database opened. - Açılmış veritabanı bulunamadı. + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + Bu veritabanı tablosu görünümüdür. AÅŸağıdaki iÅŸlemleri yapabilirsiniz: +  - DeÄŸeri satır içi olarak düzenlemek için yazmaya baÅŸlayın. +  - İçeriklerini hücre düzenleyici penceresinde düzenlemek için herhangi bir kaydı çift tıklayın. +  -Hücre içeriÄŸini NULL olarak silmek için Alt+Del tuÅŸlarına basın. +  - Geçerli kaydı kopyalamak için Ctrl + "tuÅŸlarına basın. +  - Yukarıdaki hücreden deÄŸeri kopyalamak için Ctrl + '. +  - Standart seçim ve kopyala / yapıştır iÅŸlemleri. - - %1 Rows returned from: %3 (took %2ms) - %1 tane satır döndürüldü: %3 (yaklaşık %2ms) + + Text pattern to find considering the checks in this frame + Bu çerçevedeki kontrolleri baz alarak bulmak için metin deseni - - Error executing query: %1 - Sorgu yürütme hatası: %1 + + Find in table + Tabloda ara - - Query executed successfully: %1 (took %2ms) - Sorgu baÅŸarıyla yürütüldü: %1 (yaklaşık %2ms) + + Find previous match [Shift+F3] + Önceki eÅŸleÅŸmeyi bul [Shift,F3] - - Choose a text file - Metin dosyası seçiniz + + Find previous match with wrapping + Sarmalayarak bir önceki eÅŸleÅŸmeyi bul - - Text files(*.csv *.txt);;All files(*) - Metin dosyaları(*.csv *.txt);;Tüm dosyalar(*) + + Shift+F3 + - - Import completed - İçe aktarma tamamlandı + + Find next match [Enter, F3] + Sonraki eÅŸleÅŸmeyi bul [Enter, F3] - - Are you sure you want to undo all changes made to the database file '%1' since the last save? - Son kayıttan itibaren '%1' dosyasına yaptığınız deÄŸiÅŸiklikleri geri almak istediÄŸinize emin misiniz? + + Find next match with wrapping + Sarmalayarak bir sonraki eÅŸleÅŸmeyi bul - - Choose a file to import - İçe aktarmak için dosya seçiniz + + F3 + - - - - Text files(*.sql *.txt);;All files(*) - Metin dosyaları(*.sql *.txt);;Tüm dosyalar(*) + + The found pattern must match in letter case + Bulunan desen büyük küçük harfe duyarlı ÅŸekilde eÅŸleÅŸmelidir - - Do you want to create a new database file to hold the imported data? -If you answer no we will attempt to import the data in the SQL file to the current database. - İçeri aktarılan verileri tutmak için yeni bir veritabanı dosyası oluÅŸturmak istiyor musunuz? -EÄŸer cevabınız hayır ise biz SQL dosyasındaki verileri geçerli veritabanına aktarmaya baÅŸlayacağız. + + Case Sensitive + Büyük/Küçük Harfe Duyarlı - - File %1 already exists. Please choose a different name. - %1 dosyası zaten mevcut. Lütfen farklı bir isim seçiniz. + + The found pattern must be a whole word + Bulunan kalıp tam bir kelime olmalıdır - - Error importing data: %1 - Dosya içeri aktarılırken hata oluÅŸtu: %1 + + Whole Cell + Tüm hücre - - Import completed. - İçeri aktarma tamamlandı. + + Interpret search pattern as a regular expression + Arama desenini düzenli ifade olarak yorumla - - Delete View - Görünümü Sil + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html> <head /> <body> <p> İşaretlendiÄŸinde, girilen desen UNIX düzenli ifadesi olarak yorumlanır. <a href="https://en.wikibooks.org/wiki/Regular_Expressions" >Wikibooks</a > üzerinden düzenli ifadeleri inceleyebilirsiniz. </p> </body> </html> - - Delete Trigger - Tetikleyiciyi Sil + + Regular Expression + Düzenli İfade (RegEx) - - Delete Index - İndeksi Sil + + + Close Find Bar + Arama ÇubuÄŸunu Kapat - - &%1 %2 - &%1 %2 + + Text to replace with + DeÄŸiÅŸtirilecek metin - - Setting PRAGMA values will commit your current transaction. -Are you sure? - PRAGMA deÄŸerlerini ayarlamak geçerli iÅŸleminizi yürütmeye alacaktır. -Bunu yapmak istediÄŸinize emin misiniz? + + Replace with + Åžununla deÄŸiÅŸtir - - Select SQL file to open - Açmak için SQL dosyasını seçiniz + + Replace next match + Sonraki eÅŸleÅŸmeyi deÄŸiÅŸtir - - Select file name - Dosya ismi seçiniz + + + Replace + DeÄŸiÅŸtir - - Select extension file - Eklenti dosyasını seçiniz + + Replace all matches + Tüm eÅŸleÅŸenleri deÄŸiÅŸtir - - Extensions(*.so *.dll);;All files(*) - Eklenti dosyaları(*.so *.dll);;Tüm dosyalar(*) + + Replace all + Tümünü DeÄŸiÅŸtir - - Extension successfully loaded. - Eklenti baÅŸarıyla yüklendi. + + Export to &JSON + &JSON'a aktar - - - Error loading extension: %1 - Eklenti yüklenirken hata oluÅŸtu: %1 + + + Export the filtered data to JSON + FiltrelenmiÅŸ verileri JSON'a aktar - - Don't show again - Bir daha gös'terme + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + Bu buton, taranan tablonun verilerini ÅŸu anda görüntülendiÄŸi ÅŸekilde (filtreler, görüntüleme biçimleri ve sıralama sütunundan sonra) JSON dosyası olarak dışa aktarır. - - New version available. - Yeni sürüm güncellemesi mevcut. + + Copy column name + Sütun adını kopyala - - A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. - Yeni bir SQLite DB Browser sürümü mevcut (%1.%2.%3).<br/><br/>Lütfen buradan indiriniz: <a href='%4'>%4</a> + + Copy the database table column name to your clipboard + Veritabanı tablosu sütun adını panonuza kopyalayın - - Choose a axis color - Renk eksenini seçiniz + + New Data Browser + Yeni Veri Tarayıcısı - - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Tüm dosyalar(*) + + + Add a new docked Data Browser + Yeni bir yerleÅŸik Veri Tarayıcısı ekleyin - - Choose a file to open - Açmak için dosya seçiniz + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + Bu düğme, farklı düzenlerde ayırıp düzenleyebileceÄŸiniz yeni bir yerleÅŸik Veri Tarayıcısı ekler. - - - DB Browser for SQLite project file (*.sqbpro) - SQLite DB Browser proje dosyası (*.sqbpro) + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>BaÅŸa sürükle</p></body></html> - - - PreferencesDialog - - Preferences - Tercihler + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>Bu butona basıldığında üstteki tablo görünümünün baÅŸlangıcına kaydırılır.</p></body></html> - - &General - &Genel + + |< + |< - - Remember last location - Son dizini hatırla + + Scroll one page upwards + Bir sayfa yukarı kaydır - - Always use this location - Her zaman bu dizini kullan + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>Bu butona tıklamak, yukarıdaki tablo görünümünde kayıt sayfasını yukarı doÄŸru kaydırır.</p></body></html> - - Remember last location for session only - Aynı oturum için son dizini hatırla + + < + < - - ... - ... + + 0 - 0 of 0 + 0 - 0 / 0 - - Default &location - Varsayılan + + Scroll one page downwards + Bir sayfa aÅŸağı kaydır - - Lan&guage - Di&l + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>Bu butona tıklamak, yukarıdaki tablo görünümünde kayıt sayfasını aÅŸağıya doÄŸru kaydırır.</p></body></html> - - Automatic &updates - Otomatik + + > + > - - - enabled - etkin + + Scroll to the end + Sona sürükle - - &Database - &Veritabanı + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>Bu düğmeye tıklandığında yukarıdaki tablo görünümünde en sona gidilir.</p></body></html> - - Database &encoding - &Veritabanı kodlaması + + >| + >| - - Open databases with foreign keys enabled. - Veritabanlarını Yabancı Anahtarlar etkin olacak ÅŸekilde aç. + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>İstediÄŸiniz kayda atlamak için buraya tıklayın</p></body></html> - - &Foreign keys - &Yabancı Anahtarlar + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>Bu buton belirtilen kayıt numarasına gitmek için kullanılır.</p></body></html> - - Remove line breaks in schema view - Åžema görünümünde satır sonlarını kaldır + + Go to: + Git: - - &Prefetch block size - &Önceden getirilecek blok boyutu + + Enter record number to browse + Görüntülemek için kayıt numarasını giriniz - - Data &Browser - Veri &Görüntüleyici + + Type a record number in this area and click the Go to: button to display the record in the database view + Bu alana veritabanı görünümünde görüntülemek istediÄŸiniz kayıt numarasını giriniz ve Git butonuna tıklayınız - - NULL fields - Geçersiz alanlar + + 1 + 1 - - Text &colour - Yazı &rengi + + Show rowid column + Rowid sütununu göster - - &Text - &Yazı + + Toggle the visibility of the rowid column + Rowid sütununun görünürlüğünü ayarla - - Bac&kground colour - Ar&kaplan rengi + + Unlock view editing + Görünüm düzenlemenin kilidini aç - - &SQL - &SQL + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + Bu, geçerli görünümün düzenleme için kilidini açar. Ancak, düzenleme için uygun tetikleyicilere ihtiyacınız olacaktır. - - Settings name - Ayarlar ismi + + Edit display format + Görüntüleme formatını düzenle - - Context - Özellik + + Edit the display format of the data in this column + Bu sütundaki verilerin görüntüleme biçimini düzenleyin - - Colour - Renk + + + New Record + Yeni Kayıt - - Bold - Kalın + + + Insert a new record in the current table + Geçerli tabloya yeni bir kayıt ekle - - Italic - İtalik + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html> <head /> <body> <p> Bu düğme veritabanında yeni bir kayıt oluÅŸturur. Farklı seçeneklerin olduÄŸu açılır menüsüyü görüntülemek için fare düğmesini basılı tutun: </p> <ul> <li> <span style=" font-weight:600;">Yeni Kayıt</span>: veritabanına varsayılan deÄŸerleri olan yeni bir kayıt ekler. </li> <li> <span style=" font-weight:600;">DeÄŸerler Ekleyin...</span>: veritabanına eklenmeden önce deÄŸerleri girmek için bir iletiÅŸim kutusu açın. Bu, farklı kısıtlamaları karşılayan deÄŸerlerin girilmesine izin verir. Bu iletiÅŸim kutusu, bu kısıtlamalar nedeniyle <span style=" font-weight:600;">Yeni Kayıt</span> seçeneÄŸi baÅŸarısız olursa da açılır. </li> </ul> </body> </html> - - Underline - Altı çizili + + + Delete Record + Kaydı Sil - - Keyword - Anahtar Kelime + + Delete the current record + Geçerli kaydı sil - - function - fonksiyon + + + This button deletes the record or records currently selected in the table + Bu buton tabloda seçili olan kaydı veya kayıtları siler - - Function - Fonksiyon + + + Insert new record using default values in browsed table + Görüntülenen tablosundaki varsayılan deÄŸerleri kullanarak yeni kayıt ekle - - Table - Tablo + + Insert Values... + DeÄŸerler Ekle... - - Comment - Yorum + + + Open a dialog for inserting values in a new record + Yeni bir kayda deÄŸer eklemek için bir iletiÅŸim kutusu açın - - Identifier - Kimlik + + Export to &CSV + &CSV dosyası olarak dışa aktar - - String - String + + + Export the filtered data to CSV + FiltrelenmiÅŸ veriyi CSV olarak dışa aktar - - currentline - currentline + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + Bu buton, görüntülenen tablonun verilerini ÅŸu anda görüntülendiÄŸi ÅŸekliyle (filtrelerden, görüntüleme biçimlerinden ve sütunların sıralamasına kadar) bir CSV dosyası olarak dışa aktarır. - - Current line - Geçerli satır + + Save as &view + &Görünüm olarak kaydet - - SQL &editor font size - SQL &Editör yazı boyutu + + + Save the current filter, sort column and display formats as a view + Geçerli filtreyi, sütunu ve görüntüleme biçimlerini bir görünüm olarak kaydedin - - SQL &log font size - SQL &günlüğü yazı boyutu + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + Bu buton, görüntülenen tablonun geçerli ayarlarını (filtreler, görüntü formatları ve sütunların sırasına kadar) daha sonra göz atabileceÄŸiniz veya SQL ifadelerinde kullanabileceÄŸiniz bir SQL görünümü olarak kaydeder. - - Tab size: - Tab boÅŸluÄŸu: + + Save Table As... + Tabloyu Farklı Kaydet... - - SQL editor &font - SQL Editör &yazı boyutu + + + Save the table as currently displayed + Tabloyu ÅŸu anda gösterilen ÅŸekilde kaydet - - &Extensions - &Eklentiler + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html> <head /> <body> <p> Bu açılır menü, o anda görüntülenen ve filtrelenen tablo için geçerli olan aÅŸağıdaki seçenekleri sunar: </p> <ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;" > <li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;" > CSV olarak Dışa Aktar: Bu seçenek, görüntülenen tablonun verilerini ÅŸu anda görüntülendiÄŸi ÅŸekliyle (filtrelerden, görüntüleme biçimlerinden ve sipariÅŸ sütunun sıralamasına kadar) bir CSV dosyasına aktarır. </li> <li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;" > Görünüm olarak kaydet: Bu seçenek, göz atılan tablonun geçerli ayarlarını (filtreler, görüntü formatları ve sipariÅŸ sütun sıralamasına kadar) daha sonra göz atabileceÄŸiniz veya SQL ifadelerinde kullanabileceÄŸiniz bir SQL görünümü olarak kaydeder. </li> </ul> </body> </html> - - Select extensions to load for every database: - Her veritabanında kullanmak için eklenti seçiniz: + + Hide column(s) + Sütunları gizle - - Add extension - Eklenti Ekle + + Hide selected column(s) + Seçili sütunları gizle - - Remove extension - Eklenti Sil + + Show all columns + Tüm sütunları göster - - <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> - <html><head/><body><p>Kurallı ifade(REGEXP) operatörü aktif edildiÄŸinde SQLite, herhangi bir kurallı ifade uygulamaz ama ÅŸuan da çalışan uygulamayı geri çağırır. <br/>SQLite DB Browser kurallı ifadeyi kutunun dışında kullanmanıza izin vermek için bu algoritmayı uygular. <br/>Birden çok muhtemel uygulama olduÄŸu gibi sizde farklı birini kullanabilirsiniz.<br/>Programın uygulamalarını devre dışı bırakmakta ve kendi eklentinizle kendi uygulamanızı yüklemekte özgürsünüz.<br/>Ayrıca uygulamayı yeniden baÅŸlatmak gerekir.</p></body></html> + + Show all columns that were hidden + Gizlenen tüm sütunları göster - - Disable Regular Expression extension - Kurallı İfade eklentisini devre dışı bırak + + + Set encoding + Kodlamayı ayarla - - Choose a directory - Dizin seçiniz + + Change the encoding of the text in the table cells + Tablo hücrelerindeki metnin kodlamasını deÄŸiÅŸtir - - The language will change after you restart the application. - Seçilen dil uygulama yeniden baÅŸlatıldıktan sonra uygulanacaktır. + + Set encoding for all tables + Tüm tablolar için kodlama ayarla - - Select extension file - Eklenti dosyası seçiniz + + Change the default encoding assumed for all tables in the database + Veritabanındaki tüm tablolar için varsayılan kodlamayı deÄŸiÅŸtir - - Extensions(*.so *.dll);;All files(*) - Eklentiler(*.so *.dll);;Tüm dosyalar(*) + + Clear Filters + Filtreleri Temizle - - - QObject - - Error importing data - Veriyi içe aktarılırken hata oluÅŸtu + + Clear all filters + Tüm filtreleri temizle - - from record number %1 - kayıt numarasından: %1 + + + This button clears all the filters set in the header input fields for the currently browsed table. + Bu buton, o anda görüntülenen tablonun baÅŸlık giriÅŸ alanlarında ayarlanan tüm filtreleri temizler. - - . -%1 - . %1 + + Clear Sorting + Sıralamayı Temizle - - Decoding CSV file... - CSV dosyasının ÅŸifresi çözülüyor... + + Reset the order of rows to the default + Satırların sırasını varsayılana sıfırla - - Cancel - İptal + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + Bu buton, o anda görüntülenen tablo için belirtilen sıralama sütunlarını temizler ve varsayılan sıraya geri döner. - - Collation needed! Proceed? - Harmanlama gerekli! Devam edilsin mi? + + Print + Yazdır - - A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. -If you choose to proceed, be aware bad things can happen to your database. -Create a backup! - Bu veritabanınındaki bir tablo özel '%1' koleksiyon fonksiyonu gerektirmektedir. -Daha fazla bilgi olmadan program bunu saÄŸlayamaz. EÄŸer bu ÅŸekilde devam edecekseniz, veritabanınıza kötü ÅŸeyler olabileceÄŸinin farkında olun ve yedek oluÅŸturun. + + Print currently browsed table data + Åžu anda görüntülenen tablo verilerini yazdır - - - SqlExecutionArea - - Form - Form + + Print currently browsed table data. Print selection if more than one cell is selected. + Åžu anda görüntülenen tablo verilerini yazdır. Birden fazla hücre seçilirse seçimi yazdır. - - Results of the last executed statements - Son yürütülen ifadenin sonucu + + Ctrl+P + - - This field shows the results and status codes of the last executed statements. - Bu alan son yürütülen ifadenin durum kodlarını ve sonuçlarını gösterir. + + Refresh + Yenile - - Export to &CSV - &CSV dosyası olarak dışa aktar + + Refresh the data in the selected table + Seçilen tablodaki verileri yenile - - Save as &view - &Görünümü kaydet + + This button refreshes the data in the currently selected table. + Bu buton, seçilen tablodaki verileri yeniler. - - Save as view - Görünümü kaydet + + F5 + - - Please specify the view name - Lütfen görünümünün ismini belirtin + + Find in cells + Hücrelerde ara - - There is already an object with that name. Please choose a different name. - Bu isme sahip obje zaten mevcut. Lütfen farklı bir isim seçiniz. + + Open the find tool bar which allows you to search for values in the table view below. + AÅŸağıdaki tablo görünümünde deÄŸerleri aramanıza izin veren bul araç çubuÄŸunu açın. - - View successfully created. - Görünüm baÅŸarıyla oluÅŸturuldu. + + Freeze columns + Sütunları dondur - - Error creating view: %1 - Görünüm oluÅŸturma hatası: %1 + + Make all columns from the first column up to this column not move when scrolling horizontally + Yatay kaydırma sırasında ilk sütundan bu sütuna kadar olan tüm sütunların hareket etmemesini saÄŸlayın - - - SqlUiLexer - - (X) The abs(X) function returns the absolute value of the numeric argument X. - (X) abs(X) fonksiyonu X sayısal argümanının mutlak deÄŸerini döndürür. + + + Bold + Kalın - - () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. - () changes() fonksiyonu en son yürütülen INSERT, DELETE veya UPDATE ifadesinden etkilenen veritabanı satırlarının sayısını döndürür. + + Ctrl+B + - - (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. - (X1,X2,...) char(X1,X2,...,XN) fonksiyonu sırasıyla X1'den XN'e kadar olan tamsayıların unicode karakter karşılıklarından oluÅŸan dizeyi döndürür. + + + Italic + İtalik - - (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL - (X,Y,...) coalesce() fonksiyonu NULL olmayan ilk argümanı döndürür. EÄŸer tüm argümanlar NULL ise NULL deÄŸerini döndürür. + + + Underline + Altı çizili - - (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". - (X,Y) glob(X,Y) fonksiyonu "Y GLOB X" ifadesinin eÅŸdeÄŸerini döndürür. + + Ctrl+U + - - (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. - (X,Y) ifnull() fonksiyonu NULL olmayan ilk argümanı döndürür. EÄŸer her iki argüman da NULL ise NULL deÄŸerini döndürür. + + + Align Right + SaÄŸa Hizala - - (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. - (X,Y) instr(X,Y) fonksiyonu ilk önce X dizesinin içinde Y dizesinin içeriÄŸini arar ve eÅŸleÅŸen yerden önceki karakterlerin sayısının 1 fazlasını döndürür. EÄŸer Y, X içerisinde bulunmazsa 0 deÄŸerini döndürür. + + + Align Left + Sola Hizala - - (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. - (X) hex() fonksiyonu argümanı BLOB olarak yorumlar ve BLOB içeriÄŸinin büyük harf onaltılık kısmını dize olarak döndürür. + + + Center Horizontally + Yatayda Ortala - - () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. - () last_insert_rowid() fonksiyonu çaÄŸrılan veritabanı baÄŸlantısından en son eklenen satırın ROWID deÄŸerini döndürür. + + + Justify + İki yana yasla - - (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. - (X) length() fonksiyonu X dize deÄŸeri için NULL ifadesine kadar olan karakter sayısını döndürür (bayt olarak deÄŸil). + + + Edit Conditional Formats... + KoÅŸullu Biçimlendirmeyi Düzenle... - - (X,Y) The like() function is used to implement the "Y LIKE X" expression. - (X,Y) like() fonksiyonu "Y LIKE X" ifadesini uygulamak için kullanılır. + + Edit conditional formats for the current column + Geçerli sütun için koÅŸullu biçimlendirmeyi düzenle - - (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. - (X,Y,Z) like() fonksiyonu "Y LIKE X ESCAPE Z" ifadesini uygulamak için kullanılır. + + Clear Format + Biçimlendirmeleri Temizle - - (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. - (X) load_extension(X) fonksiyonu SQLite eklentilerini paylaşılan kitaplık dışına X ismiyle yükler. + + Clear All Formats + Tüm Biçimlendirmeleri Temizle - - (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. - (X,Y) load_extension(X) fonksiyonu Y baÅŸlangıç noktasını kullanarak SQLite eklentilerini paylaşılan kitaplık dışına X ismiyle yükler. + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + Seçilen hücrelerdeki tüm hücre biçimlendirmelerini ve seçilen sütunlardaki tüm koÅŸullu biçimleri temizle - - (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. - (X) lower(X) fonksiyonu tüm X dizesinin tüm ASCII karakterlerinin küçük harfe dönüştürülmüş karşılığını döndürür. + + + Font Color + Yazı Tipi Rengi - - (X) ltrim(X) removes spaces from the left side of X. - (X) ltrim(X) fonksiyonu X'in sol tarafındaki boÅŸlukları siler. + + + Background Color + Arka Plan Rengi - - (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. - (X,Y) ltrim(X,Y) fonksiyonu X'in sol tarafındaki Y'de bulunan tüm karakterlerin silinmiÅŸ halini dize halinde döndürür. + + Toggle Format Toolbar + Biçim Araç ÇubuÄŸunu Aç/Kapat - - (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. - (X,Y,...) Çok argümanlı max() fonksiyonu en büyük deÄŸere sahip argümanı döndürür. EÄŸer herhangi bir argüman NULL ise NULL deÄŸerini döndürür. + + Show/hide format toolbar + Biçim araç çubuÄŸunu göster/gizle - - (X,Y,...) The multi-argument min() function returns the argument with the minimum value. - (X,Y,...) Çok argümanlı min() fonksiyonu en küçük deÄŸere sahip argümanı döndürür. + + + This button shows or hides the formatting toolbar of the Data Browser + Bu düğme Veri Görüntüleyici'nin biçimlendirme araç çubuÄŸunu gösterir veya gizler - - (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. - (X,Y) nullif(X,Y) fonksiyonu eÄŸer argümanlar farklı ise ilk argümanı, eÄŸer argümanlar aynı ise NULL döndürür. + + Select column + Sütun seç - - (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. - (FORMAT,...) printf(FORMAT,...) SQL fonksiyonu C dilindeki sqlite3_mprintf() fonksiyonu ve standard C kütüphanesindeki printf() fonksiyonu ile aynı mantıkta çalışır. + + Ctrl+Space + - - (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. - (X) quote(X) fonksiyonu girilen argümanlardan SQL ifadesi olarak tam anlamıyla dahil edilmeye uygun olanları döndürür. + + Replace text in cells + Hücrelerdeki metinleri deÄŸiÅŸtir - - () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. - () random() fonksiyonu -9223372036854775808 ve +9223372036854775807 tamsayı deÄŸerli arasında rastgele deÄŸer döndürür. + + Filter in any column + Herhangi bir sütunda filtreleme yapın - - (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. - (N) randomblob(N) fonksiyonu rastgele bayt içeren N-byte türünde blob döndürür. + + Ctrl+R + - - - (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. - (X,Y,Z) replace(X,Y,Z) fonksiyonu X içindeki her Y argümanını, Z argümanıyla deÄŸiÅŸtirmesiyle oluÅŸan dizeyi döndürür. + + + %n row(s) + + %n satır + - - - (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. - (X) round(X) fonksiyonu X ondalıklı sayısının ondalıklı kısmın sıfıra yuvarlanmasıyla oluÅŸan deÄŸeri döndürür. + + + , %n column(s) + + , %n sütun + - - (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. - (X,Y) round(X,Y) fonksiyonu X ondalıklı sayısının Y kadar sağındaki ondalıklı kısmı sıfıra yuvarlanmasıyla oluÅŸan deÄŸeri döndürür. + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . Toplam: %1; Ortalama: %2; Min: %3; Maks: %4 - - (X) rtrim(X) removes spaces from the right side of X. - (X) rtrim(X) fonksiyonu X'in saÄŸ tarafındaki boÅŸlukları siler. + + Conditional formats for "%1" + "%1" için koÅŸullu biçimlendirme - - (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. - (X,Y) rtrim(X,Y) fonksiyonu X'in saÄŸ tarafındaki Y'de bulunan tüm karakterlerin silinmiÅŸ halini dize halinde döndürür. + + determining row count... + satır sayısı belirleniyor... - - (X) The soundex(X) function returns a string that is the soundex encoding of the string X. - (X) soundex(X) fonksiyonu X dizesinin soundex kodlamasını string olarak döndürür. + + %L1 - %L2 of >= %L3 + %L1 - %L2 of >= %L3 - - (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. - (X,Y) substr(X,Y) fonksiyonu X dizesinin baÅŸlangıcından Y. indekse kadar olan string bölümünü döndürür. + + %L1 - %L2 of %L3 + %L1 - %L2 of %L3 - - (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. - (X,Y,Z) substr(X,Y,Z) fonksiyonu X dizesinin Y. indeksinden baÅŸlayarak Z uzunluÄŸu kadar olan string bölümünü döndürür. + + (clipped at %L1 rows) + (%L1 satırlarında kesildi) - - () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. - () total_changes() fonksiyonu geçerli veritabanı baÄŸlantısı açıldığından itibaren INSERT, UPDATE veya DELETE ifadelerinden etkilenen toplam satır sayısını döndürür. + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + Bu görünümde düzenlemeyi etkinleÅŸtirmek için lütfen sözde birincil anahtar girin. Bu, görünümdeki benzersiz bir sütunun adı olmalıdır. - - (X) trim(X) removes spaces from both ends of X. - (X) trim(X) fonksiyonu X'in içinde bulunan boÅŸlukları siler. + + Delete Records + Kayıtları Sil - - (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. - (X,Y) trim(X,Y) fonksiyonu X'in içindeki Y'de bulunan tüm karakterlerin silinmiÅŸ halini dize halinde döndürür. + + Duplicate records + Yinelenen kayıtlar - - (X) The typeof(X) function returns a string that indicates the datatype of the expression X. - (X) typeof(X) fonksiyonu X ifadesinin veri tipini gösteren dizeyi döndürür. + + Duplicate record + Yinelenen kayıt - - (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. - (X) unicode(X) fonksiyonu X'in ilk karakterine karşılık gelen unicode kod noktasını döndürür. + + Ctrl+" + Ctrl+" - - (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. - (X) upper(X) fonksiyonu tüm X dizesinin tüm küçük ASCII karakterlerinin büyük harf karşılığına çevrilmiÅŸ kopyasını döndürür. + + Adjust rows to contents + Satırları içeriklere göre ayarla - - (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. - (N) zeroblob(N) fonksiyonu 0x00'ın N bayt kadar meydana gelmiÅŸ halini BLOB olarak döndürür. + + Error deleting record: +%1 + Kayıt silme hatası: +%1 - - - - - (timestring,modifier,modifier,...) - + + Please select a record first + Lütfen önce bir kayıt seçin - - (format,timestring,modifier,modifier,...) - + + Please choose a new encoding for all tables. + Lütfen tüm tablolar için yeni bir kodlama seçin. - - (X) The avg() function returns the average value of all non-NULL X within a group. - (X) avg() fonksiyonu bir gruptaki NULL olmayan tüm X deÄŸerlerinin ortalama deÄŸerini döndürür. + + Please choose a new encoding for this table. + Lütfen bu tablo için yeni bir kodlama seçin. - - (X) The count(X) function returns a count of the number of times that X is not NULL in a group. - (X) count(X) fonksiyonu bir gruptaki X'in kaç kere NULL olmadığının sayısını döndürür. + + %1 +Leave the field empty for using the database encoding. + %1 +Veritabanı kodlamasını kullanmak için alanı boÅŸ bırakın. - - (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. - (X) group_concat() fonksiyonu X'in NULL olmayan tüm deÄŸerlerle birleÅŸimini dize olarak döndürür. + + This encoding is either not valid or not supported. + Bu kodlama geçerli deÄŸil veya desteklenmiyor. - - (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. - (X,Y) group_concat() fonksiyonu X'in NULL olmayan tüm deÄŸerlerle birleÅŸimini dize olarak döndürür. EÄŸer Y parametresi mevcutsa X'in örnekleri arasında ayraç olarak kullanılır. + + %1 replacement(s) made. + %1 deÄŸiÅŸimi yapıldı. + + + TableBrowserDock - - (X) The max() aggregate function returns the maximum value of all values in the group. - (X) max() küme fonksiyonu gruptaki tüm deÄŸerler arasından en büyük deÄŸeri döndürür. + + New Data Browser + Yeni Veri Tarayıcısı - - (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. - (X) min() küme fonksiyonu gruptaki NULL olmayan tüm deÄŸerler arasından en küçük deÄŸeri döndürür. + + Rename Data Browser + Veri Tarayıcısını Yeniden Adlandır - - - (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. - (X) sum() ve total() küme fonksiyonları gruptaki NULL olmayan tüm deÄŸerlerin toplamını döndürür. + + Close Data Browser + Veri Tarayıcısını Kapat - - - SqliteTableModel - - Error changing data: -%1 - Veri deÄŸiÅŸtirme hatası: %1 + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + Veri tarayıcısı için yeni bir ad belirleyin. AÅŸağıdaki karakteri klavye kısayolu olarak kullanabilmek için '&&' karakterini kullanın. @@ -2798,17 +8022,17 @@ Daha fazla bilgi olmadan program bunu saÄŸlayamaz. EÄŸer bu ÅŸekilde devam edec Compact Database - Veritabanını GeniÅŸlet + Veritabanını Sıkıştır - Warning: Compacting the database will commit all changes you made. - Uyarı: Veritabanını geniÅŸletmek bütün yaptığınız deÄŸiÅŸiklikleri iÅŸleyecektir. + Warning: Compacting the database will commit all of your changes. + Uyarı: Veritabanını sıkıştırmak bütün deÄŸiÅŸikliklerinizi kaydedecektir. - Please select the objects to compact: - Lütfen geniÅŸletilecek objeyi seçiniz: + Please select the databases to co&mpact: + Sıkıştır&mak istediÄŸiniz veritabanını seçin: diff --git a/src/translations/sqlb_uk_UA.ts b/src/translations/sqlb_uk_UA.ts new file mode 100644 index 000000000..1f31f8eef --- /dev/null +++ b/src/translations/sqlb_uk_UA.ts @@ -0,0 +1,7974 @@ + + + + + AboutDialog + + + About DB Browser for SQLite + Про ОглÑдач БД Ð´Ð»Ñ SQLite + + + + Version + ВерÑÑ–Ñ + + + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + + + + + AddRecordDialog + + + Add New Record + + + + + Enter values for the new record considering constraints. Fields in bold are mandatory. + + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + + + + + Name + Ім'Ñ + + + + Type + Тип + + + + Value + + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + + + + + Auto-increment + + + + + + Unique constraint + + + + + + Check constraint: %1 + + + + + + Foreign key: %1 + + + + + + Default value: %1 + + + + + + Error adding record. Message from database engine: + +%1 + + + + + Are you sure you want to restore all the entered values to their defaults? + + + + + Application + + + Possible command line arguments: + ДоÑтупні ключі командного Ñ€Ñдку: + + + + The user settings file location is replaced with the argument value instead of the environment variable value. + + + + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + + + + + Usage + + + + + options + + + + + + database + + + + + + project + + + + + + csv-file + + + + + Show command line options + + + + + Exit application after running scripts + + + + + + file + + + + + Execute this SQL file after opening the DB + + + + + Import this CSV file into the passed DB or into a new DB + + + + + table + + + + + Browse this table, or use it as target of a data import + + + + + Open database in read-only mode + + + + + settings_file + + + + + Run application based on this settings file + + + + + + group + + + + + + settings + + + + + + value + + + + + Run application with this setting temporarily set to value + + + + + Run application saving this value for this setting + + + + + Display the current version + + + + + Open this SQLite database + + + + + Open this project file (*.sqbpro) + + + + + Import this CSV file into an in-memory database + + + + + + + The %1 option requires an argument + + + + + The -S/--settings option requires an argument. The option is ignored. + + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + + + + + Invalid option/non-existent file: %1 + Ðевірна опціÑ/файл не Ñ–Ñнує: %1 + + + + SQLite Version + ВерÑÑ–Ñ SQLite + + + + SQLCipher Version %1 (based on SQLite %2) + + + + + DB Browser for SQLite Version %1. + + + + + Last commit hash when built: %1 + + + + + Built for %1, running on %2 + + + + + Qt Version %1 + + + + + + The file %1 does not exist + Файл %1 не Ñ–Ñнує + + + + CipherDialog + + + SQLCipher encryption + Ð¨Ð¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ SQLCipher + + + + &Password + &Пароль + + + + &Reenter password + &Пароль ще раз + + + + Encr&yption settings + + + + + SQLCipher &3 defaults + + + + + SQLCipher &4 defaults + + + + + Custo&m + + + + + Page si&ze + &Розмір Ñторінки + + + + &KDF iterations + + + + + HMAC algorithm + + + + + KDF algorithm + + + + + Plaintext Header Size + + + + + Passphrase + Парольна фраза + + + + Raw key + Ðеоброблений ключ + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + Будь лаÑка, вкажіть ключ шифруваннÑ. +Якщо Ви зміните будь-Ñке опційне налаштуваннÑ, то його доведетьÑÑ Ð²Ð²Ð¾Ð´Ð¸Ñ‚Ð¸ під Ñ‡Ð°Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ†ÑŒÐ¾Ð³Ð¾ файлу бази даних. +Залиште Ð¿Ð¾Ð»Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŽ порожніми, щоб відімкнути шифруваннÑ. +ÐŸÑ€Ð¾Ñ†ÐµÑ Ð¼Ð¾Ð¶Ðµ тривати деÑкий чаÑ. РекомендуєтьÑÑ Ñтворити резервну копію перед продовженнÑм! Ð’ÑÑ– незбережені зміни збережутьÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾. + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + Будь лаÑка, введіть ключ Ð´Ð»Ñ ÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ð°Ð·Ð¸ даних. +Якщо будь-Ñкі інші Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¸ змінені Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— бази даних, то потрібно надати цю інформацію також. + + + + ColumnDisplayFormatDialog + + + Choose display format + Оберіть формат показу + + + + Display format + Формат показу + + + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + Оберіть формат показу Ð´Ð»Ñ ÐºÐ¾Ð»Ð¾Ð½ÐºÐ¸ '%1'. Формат заÑтоÑуєтьÑÑ Ð´Ð¾ кожного Ñ—Ñ— значеннÑм. + + + + Default + За замовчуваннÑм + + + + Decimal number + ДеÑÑткове чиÑло + + + + Exponent notation + ЕкÑпоненціальний Ð·Ð°Ð¿Ð¸Ñ + + + + Hex blob + Бінарні дані + + + + Hex number + ШіÑтнадцÑткове чиÑло + + + + Apple NSDate to date + Дата Apple NSDate + + + + Java epoch (milliseconds) to date + + + + + .NET DateTime.Ticks to date + + + + + Julian day to date + Дата за ЮліанÑьким календарем + + + + Unix epoch to local time + + + + + WebKit / Chromium epoch to date + + + + + WebKit / Chromium epoch to local time + + + + + Date as dd/mm/yyyy + + + + + Lower case + Ðижній регіÑтр + + + + Binary GUID to text + + + + + SpatiaLite Geometry to SVG + + + + + Custom display format must contain a function call applied to %1 + + + + + Error in custom display format. Message from database engine: + +%1 + + + + + Custom display format must return only one column but it returned %1. + + + + + Octal number + Ð’Ñ–Ñімкове чиÑло + + + + Round number + Округлене чиÑло + + + + Unix epoch to date + Unix-Ñ‡Ð°Ñ + + + + Upper case + Верхній регіÑтр + + + + Windows DATE to date + Windows дата + + + + Custom + Мій формат + + + + CondFormatManager + + + Conditional Format Manager + + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + + + + + Add new conditional format + + + + + &Add + + + + + Remove selected conditional format + + + + + &Remove + + + + + Move selected conditional format up + + + + + Move &up + + + + + Move selected conditional format down + + + + + Move &down + + + + + Foreground + + + + + Text color + + + + + Background + Фон + + + + Background color + + + + + Font + Шрифт + + + + Size + Розмір + + + + Bold + Жирний + + + + Italic + КурÑив + + + + Underline + ПідкреÑÐ»ÐµÐ½Ð½Ñ + + + + Alignment + + + + + Condition + + + + + + Click to select color + + + + + Are you sure you want to clear all the conditional formats of this field? + + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + Будь лаÑка, вкажіть ім'Ñ Ð±Ð°Ð·Ð¸ даних, під Ñким Ви хочете отримати доÑтуп до під'єднаних баз даних + + + + Invalid file format + Ðеправильний формат файлу + + + + Do you really want to close this temporary database? All data will be lost. + + + + + Do you want to save the changes made to the database file %1? + Зберегти зроблені зміни у файлі бази даних %1? + + + + Database didn't close correctly, probably still busy + + + + + Cannot open destination file: '%1' + + + + + + Cannot backup to file: '%1'. Message: %2 + + + + + The database is currently busy: + + + + + Do you want to abort that other operation? + + + + + Exporting database to SQL file... + ЕкÑпорт бази даних у файл SQL... + + + + + Cancel + СкаÑувати + + + + + No database file opened + + + + + Executing SQL... + Виконати код SQL... + + + + Action cancelled. + Дію ÑкаÑовано. + + + + + Error in statement #%1: %2. +Aborting execution%3. + Помилка в операторі #%1: %2. +Ð’Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÑкаÑовано%3. + + + + + and rolling back + Ñ– відкочено + + + + didn't receive any output from %1 + + + + + could not execute command: %1 + + + + + Cannot delete this object + + + + + Cannot set data on this object + Ðе вдаєтьÑÑ Ð²Ñтановити дані в цей об'єкт + + + + + A table with the name '%1' already exists in schema '%2'. + + + + + No table with name '%1' exists in schema '%2'. + + + + + + Cannot find column %1. + + + + + Creating savepoint failed. DB says: %1 + + + + + Renaming the column failed. DB says: +%1 + + + + + + Releasing savepoint failed. DB says: %1 + + + + + Creating new table failed. DB says: %1 + + + + + Copying data to new table failed. DB says: +%1 + + + + + Deleting old table failed. DB says: %1 + + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + + + + + could not get list of db objects: %1 + + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + Ðе вдалоÑÑ ÑкаÑувати Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð´ÐµÑких об'єктів, аÑоційованих із цією таблицею. Ðайімовірніша причина цього - зміна імен деÑких Ñтовпців таблиці. ОÑÑŒ SQL оператор, Ñкий потрібно виправити Ñ– виконати вручну: + + + + could not get list of databases: %1 + + + + + Error loading extension: %1 + Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ: %1 + + + + Error loading built-in extension: %1 + + + + + could not get column information + неможливо отримати інформацію про Ñтовпець + + + + Error setting pragma %1 to %2: %3 + Помилка вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐŸÑ€Ð°Ð³Ð¼Ð¸ %1 в %2: %3 + + + + File not found. + Файл не знайдено. + + + + DbStructureModel + + + Name + Ім'Ñ + + + + Object + Об'єкт + + + + Type + Тип + + + + Schema + Схема + + + + Database + + + + + Browsables + + + + + All + Ð’Ñе + + + + Temporary + + + + + Tables (%1) + Таблиці (%1) + + + + Indices (%1) + ІндекÑи (%1) + + + + Views (%1) + ПереглÑди (%1) + + + + Triggers (%1) + Тригери (%1) + + + + EditDialog + + + Edit database cell + Ð ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ€ÐºÐ¸ бази даних + + + + Mode: + Режим: + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + + + + + RTL Text + + + + + + Image + Ð—Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ + + + + JSON + + + + + XML + + + + + Evaluation + + + + + + Automatically adjust the editor mode to the loaded data type + + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + + + + + Auto-switch + + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + + + + + Identification of the cell currently in the editor + + + + + Type and size of data currently in table + + + + + Open preview dialog for printing the data currently stored in the cell + + + + + Auto-format: pretty print on loading, compact on saving. + + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + + + + + Word Wrap + + + + + Wrap lines on word boundaries + + + + + + Open in default application or browser + + + + + Open in application + + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + + + + + Save file reference... + + + + + Save reference to file + + + + + + Open in external application + + + + + Autoformat + + + + + &Export... + + + + + + &Import... + + + + + + Import from file + + + + + + Opens a file dialog used to import any kind of data to this database cell. + + + + + Export to file + + + + + Opens a file dialog used to export the contents of this database cell to a file. + + + + + Print... + + + + + Ctrl+P + + + + + Open preview dialog for printing displayed text + + + + + Copy Hex and ASCII + + + + + Copy selected hexadecimal and ASCII columns to the clipboard + + + + + Ctrl+Shift+C + + + + + Set as &NULL + ПриÑвоїти &NULL + + + + Apply data to cell + + + + + This button saves the changes performed in the cell editor to the database cell. + + + + + Apply + ЗаÑтоÑувати + + + + Text + ТекÑÑ‚ + + + + Binary + Двійкові дані + + + + Erases the contents of the cell + ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð²Ð¼Ñ–Ñту комірки + + + + This area displays information about the data present in this database cell + Ð¦Ñ Ð·Ð¾Ð½Ð° показує інформацію про дані, що Ñ” в цій комірці бази даних + + + + Choose a filename to export data + Вибрати ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ Ð´Ð»Ñ ÐµÐºÑпорту даних + + + + + Image data can't be viewed in this mode. + + + + + + Try switching to Image or Binary mode. + + + + + + Binary data can't be viewed in this mode. + + + + + + Try switching to Binary mode. + + + + + + Image files (%1) + + + + + Binary files (*.bin) + + + + + + Type: NULL; Size: 0 bytes + + + + + + Type: Text / Numeric; Size: %n character(s) + + + + + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + + + + + Type: Valid JSON; Size: %n character(s) + + + + + + + + + Type: Binary; Size: %n byte(s) + + + + + + + + + Couldn't save file: %1. + Ðеможливо зберегти файл: %1. + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + + + + + Choose a file to import + Оберіть файл Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + + + + + Unsaved data in the cell editor + + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + + + + + Editing row=%1, column=%2 + + + + + No cell active. + + + + + %1 Image + + + + + Invalid data for this mode + + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + + + + + EditIndexDialog + + + &Name + &Ім'Ñ + + + + Order + Ð¡Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ + + + + &Table + &Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ + + + + Edit Index Schema + Ð ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ð´ÐµÐºÑу Ñхеми + + + + &Unique + &Унікальний + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + Ð”Ð»Ñ Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ–Ð½Ð´ÐµÐºÑу чаÑтиною таблиці оберіть пункт WHERE, Ñкий обере чаÑтину таблиці Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐºÑації + + + + Partial inde&x clause + ЧаÑтковий ÐºÐ»Ð°Ñ Ñ–Ð½Ð´Ðµ&кÑа + + + + Colu&mns + Стов&пці + + + + Table column + Стовпець таблиці + + + + Type + Тип + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + Додати новий Ñтовпець виразу до індекÑа. Стовпці виразів міÑÑ‚Ñть SQL вирази, а не імена Ñтовпців + + + + Index column + Стовпець індекÑу + + + + Deleting the old index failed: +%1 + Ðевдале Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñтарого індекÑу: +%1 + + + + Creating the index failed: +%1 + Ðевдале ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ–Ð½Ð´ÐµÐºÑу + + + + EditTableDialog + + + Edit table definition + Ð ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ– + + + + Table + Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ + + + + Advanced + Додатково + + + + Without Rowid + Без ідентифікатора + + + + Fields + ÐŸÐ¾Ð»Ñ + + + + Database sche&ma + + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + + + + + On Conflict + + + + + Strict + + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + + + + + + + Add + + + + + + + Remove + + + + + Move to top + + + + + Move up + + + + + Move down + + + + + Move to bottom + + + + + + + + Name + Ім'Ñ + + + + + Type + Тип + + + + NN + + + + + Not null + Ðе (null) + + + + PK + ПК + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + + + + + AI + ÐІ + + + + Autoincrement + Ðвтоінкремент + + + + U + У + + + + + + Unique + Унікальне + + + + Default + За замовчуваннÑм + + + + Default value + Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм + + + + + Check + Перевірити + + + + Check constraint + Перевірити Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ + + + + Collation + + + + + Foreign Key + Зовнішній ключ + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + + + + + Index Constraints + + + + + Add constraint + + + + + Remove constraint + + + + + + Columns + Стовпці + + + + + + SQL + + + + + Foreign Keys + + + + + References + + + + + Check Constraints + + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + + + + + + Primary Key + + + + + Add a primary key constraint + + + + + Add a unique constraint + + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + Поле з таким ім'Ñм уже Ñ–Ñнує. Будь лаÑка, переіменуйте його або виберіть інше ім'Ñ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ полÑ. + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + + + + + Error creating table. Message from database engine: +%1 + Помилка ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ–. ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ Ñдра бази даних: +%1 + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + Ðа цей Ñтовпець поÑилаєтьÑÑ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ–Ð¹ ключ у таблиці %1, тому Ñ—Ñ— ім'Ñ Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ð¾ змінити. + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + ІÑнує принаймні один Ñ€Ñдок, де це поле вÑтановлено в NULL. Ð’Ñтановити цей прапорець неможливо. Спочатку змініть дані таблиці. + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + ІÑнує принаймні один Ñ€Ñдок, де це поле міÑтить нечиÑлове значеннÑ. Ð’Ñтановити прапорець ÐІ неможливо. Спочатку змініть дані таблиці. + + + + Column '%1' has duplicate data. + + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + Ви впевнені, що хочете видалити поле '%1'? +Ð’ÑÑ– дані, Ñкі міÑÑ‚ÑтьÑÑ Ð² цьому полі, будуть втрачені. + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + Будь лаÑка, перед вÑтановленнÑм Ð¿Ñ€Ð°Ð¿Ð¾Ñ€Ñ†Ñ Ð±ÐµÐ· rowid додайте поле, Ñке має такі критерії: +- вÑтановлено прапорець первинного ключа +- відімкнений автоінкремент + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + + + + + ExportDataDialog + + + Export data as CSV + ЕкÑпортувати дані у форматі CSV + + + + Tab&le(s) + &Таблиці + + + + Colu&mn names in first line + &Імена Ñтовпців у першому Ñ€Ñдку + + + + Fie&ld separator + &Роздільник полів + + + + , + , + + + + ; + ; + + + + Tab + ТабулÑÑ†Ñ–Ñ + + + + | + | + + + + + + Other + Інший + + + + &Quote character + &Символ лапок + + + + " + " + + + + ' + ' + + + + New line characters + Ðовий роздільник Ñ€Ñдків + + + + Windows: CR+LF (\r\n) + Windows: CR+LF (\r\n) + + + + Unix: LF (\n) + Unix: LF (\n) + + + + Pretty print + Гарний виÑновок + + + + + Could not open output file: %1 + Ðе вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ вихідний файл: %1 + + + + + Choose a filename to export data + Виберіть ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ Ð´Ð»Ñ ÐµÐºÑпорту даних + + + + Export data as JSON + ЕкÑпортувати дані у форматі JSON + + + + exporting CSV + + + + + + Error while writing the file '%1': %2 + + + + + exporting JSON + + + + + Please select at least 1 table. + Будь лаÑка, оберіть хоча б 1 таблицю. + + + + Choose a directory + Оберіть каталог + + + + Export completed. + ЕкÑпорт завершено. + + + + Export finished with errors. + + + + + ExportSqlDialog + + + Export SQL... + ЕкÑпорт SQL... + + + + Tab&le(s) + &Таблиці + + + + Select All + Обрати вÑе + + + + Deselect All + СкаÑувати вибір + + + + &Options + &Опції + + + + Keep column names in INSERT INTO + Імена Ñтовпців у виразі INSERT INTO + + + + Multiple rows (VALUES) per INSERT statement + Кілька Ñ€Ñдків (VALUES) на INSERT вираз + + + + Export everything + ЕкÑпортувати вÑÑ– + + + + Export data only + ЕкÑпортувати тільки дані + + + + Keep original CREATE statements + + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + Стара Ñхема (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + ПерезапиÑати Ñтару Ñхему (DROP TABLE, тоді CREATE TABLE) + + + + Export schema only + ЕкÑпортувати тільки Ñхему даних + + + + Please select at least one table. + + + + + Choose a filename to export + Оберіть ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ Ð´Ð»Ñ ÐµÐºÑпорту + + + + Export completed. + ЕкÑпорт завершено. + + + + Export cancelled or failed. + ЕкÑпорт ÑкаÑовано або виникла помилка. + + + + ExtendedScintilla + + + + Ctrl+H + + + + + Ctrl+F + + + + + + Ctrl+P + + + + + Find... + + + + + Find and Replace... + + + + + Print... + + + + + ExtendedTableWidget + + + Use as Exact Filter + + + + + Containing + + + + + Not containing + + + + + Not equal to + + + + + Greater than + + + + + Less than + + + + + Greater or equal + + + + + Less or equal + + + + + Between this and... + + + + + Regular expression + + + + + Edit Conditional Formats... + + + + + Set to NULL + Ð’Ñтановити в NULL + + + + Cut + + + + + Copy + Копіювати + + + + Copy with Headers + + + + + Copy as SQL + + + + + Paste + Ð’Ñтавити + + + + Print... + + + + + Use in Filter Expression + + + + + Alt+Del + + + + + Ctrl+Shift+C + + + + + Ctrl+Alt+C + + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + ВміÑÑ‚ буфера обміну більше ніж обраний діапазон. +Ð’Ñе одно вÑтавити? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + + + + + FileExtensionManager + + + File Extension Manager + + + + + &Up + + + + + &Down + + + + + &Add + + + + + &Remove + + + + + + Description + + + + + Extensions + + + + + *.extension + + + + + FilterLineEdit + + + Filter + Фільтр + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + + + + + Clear All Conditional Formats + + + + + Use for Conditional Format + + + + + Edit Conditional Formats... + + + + + Set Filter Expression + + + + + What's This? + + + + + Is NULL + + + + + Is not NULL + + + + + Is empty + + + + + Is not empty + + + + + Not containing... + + + + + Equal to... + + + + + Not equal to... + + + + + Greater than... + + + + + Less than... + + + + + Greater or equal... + + + + + Less or equal... + + + + + In range... + + + + + Regular expression... + + + + + FindReplaceDialog + + + Find and Replace + + + + + Fi&nd text: + + + + + Re&place with: + + + + + Match &exact case + + + + + Match &only whole words + + + + + When enabled, the search continues from the other end when it reaches one end of the page + + + + + &Wrap around + + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + + + + + Search &backwards + + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + + + + + &Selection only + + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + + Use regular e&xpressions + + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + + + + + &Find Next + + + + + F3 + + + + + &Replace + + + + + Highlight all the occurrences of the text in the page + + + + + F&ind All + + + + + Replace all the occurrences of the text in the page + + + + + Replace &All + + + + + The searched text was not found + + + + + The searched text was not found. + + + + + The searched text was found one time. + + + + + The searched text was found %1 times. + + + + + The searched text was replaced one time. + + + + + The searched text was replaced %1 times. + + + + + ForeignKeyEditor + + + &Reset + &Скинути + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + + + + + ImageViewer + + + Image Viewer + + + + + Reset the scaling to match the original size of the image. + + + + + Set the scaling to match the size of the viewport. + + + + + Print... + + + + + Open preview dialog for printing displayed image + + + + + Ctrl+P + + + + + ImportCsvDialog + + + Import CSV file + Імпортувати файл у форматі CSV + + + + Table na&me + + + + + &Column names in first line + І&мена Ñтовпців у першому Ñ€Ñдку + + + + Field &separator + &Роздільник полів + + + + , + , + + + + ; + ; + + + + + Tab + ТабулÑÑ†Ñ–Ñ + + + + | + | + + + + Other + Інший + + + + &Quote character + &Символ лапок + + + + + Other (printable) + + + + + + Other (code) + + + + + " + " + + + + ' + ' + + + + &Encoding + &ÐšÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Trim fields? + Обрізати полÑ? + + + + Separate tables + Розділити таблиці + + + + Advanced + Додатково + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + + + + + Ignore default &values + + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + + + + + Fail on missing values + + + + + Disable data type detection + + + + + Disable the automatic data type detection when creating a new table. + + + + + Use local number conventions + + + + + Use decimal and thousands separators according to the system locale. + + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + + + + + Abort import + + + + + Ignore row + + + + + Replace existing row + + + + + Conflict strategy + + + + + + Deselect All + СкаÑувати вибір + + + + Match Similar + Ð¡Ð¿Ñ–Ð²Ð¿Ð°Ð´Ñ–Ð½Ð½Ñ + + + + Select All + Обрати вÑе + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + + + + + There is already a table named '%1'. Do you want to import the data into it? + + + + + Creating restore point failed: %1 + Помилка ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð¾Ñ‡ÐºÐ¸ відновленнÑ: %1 + + + + Creating the table failed: %1 + Помилка ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ–: %1 + + + + importing CSV + + + + + Could not prepare INSERT statement: %1 + + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + + + + + Inserting row failed: %1 + Помилка вÑтавки Ñ€Ñдка: %1 + + + + MainWindow + + + DB Browser for SQLite + ОглÑдач Ð´Ð»Ñ SQLite + + + + toolBar1 + панельІнÑтрументів1 + + + + &Remote + &Віддалений + + + + &File + &Файл + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + + + + + &Import + &Імпорт + + + + &Export + &ЕкÑпорт + + + + &Edit + &Ð ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ + + + + &View + &Вид + + + + &Help + &Довідка + + + + Too&ls + + + + + DB Toolbar + Панель інÑтрументів БД + + + + Edit Database &Cell + Ð ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ &комірки БД + + + + Error Log + + + + + This button clears the contents of the SQL logs + + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + + + + + DB Sche&ma + Схе&ма БД + + + + + Execute current line + Виконати поточний Ñ€Ñдок + + + + This button executes the SQL statement present in the current editor line + + + + + Shift+F5 + + + + + Sa&ve Project + &Зберегти проект + + + + Opens the SQLCipher FAQ in a browser window + Відкрити SQLCiphier ЧаПи в браузері + + + + Export one or more table(s) to a JSON file + ЕкÑпортувати таблиці в JSON файл + + + + + Save SQL file as + Зберегти файл SQL Ñк + + + + This button saves the content of the current SQL editor tab to a file + + + + + &Browse Table + Пе&реглÑд таблиці + + + + User + КориÑтувачем + + + + Application + Додатком + + + + &Clear + О&чиÑтити + + + + &New Database... + &Ðова база даних... + + + + + Create a new database file + Створити новий файл бази даних + + + + This option is used to create a new database file. + Ð¦Ñ Ð¾Ð¿Ñ†Ñ–Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑтовуєтьÑÑ Ñ‰Ð¾Ð± Ñтворити новий файл бази даних. + + + + Ctrl+N + + + + + + &Open Database... + &Відкрити базу даних... + + + + + + + + Open an existing database file + Відкрити Ñ–Ñнуючий файл бази даних + + + + + + This option is used to open an existing database file. + Ð¦Ñ Ð¾Ð¿Ñ†Ñ–Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑтовуєтьÑÑ, щоб відкрити Ñ–Ñнуючий файл бази даних. + + + + Ctrl+O + + + + + &Close Database + &Закрити базу даних + + + + This button closes the connection to the currently open database file + + + + + + Ctrl+W + + + + + + Revert database to last saved state + Повернути базу даних до оÑтаннього збереженого Ñтану + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + Ð¦Ñ Ð¾Ð¿Ñ†Ñ–Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑтовуєтьÑÑ, щоб повернути поточний файл бази даних до його оÑтаннього збереженого Ñтану. Ð’ÑÑ– зміни, зроблені з оÑтанньої операції збереженнÑ, буде втрачено. + + + + + Write changes to the database file + ЗапиÑати зміни у файл бази даних + + + + This option is used to save changes to the database file. + Ð¦Ñ Ð¾Ð¿Ñ†Ñ–Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑтовуєтьÑÑ, щоб зберегти зміни у файлі бази даних. + + + + Ctrl+S + + + + + Compact &Database... + + + + + Compact the database file, removing space wasted by deleted records + Ущільнити базу даних, видаливши проÑтір, зайнÑтий видаленими запиÑами + + + + + Compact the database file, removing space wasted by deleted records. + Ущільнити базу даних, видаливши проÑтір, зайнÑтий видаленими запиÑами. + + + + E&xit + &Вихід + + + + Ctrl+Q + + + + + Import data from an .sql dump text file into a new or existing database. + Імпортувати дані з текÑтового файлу .sql в нову або Ñ–Ñнуючу базу даних. + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + Ð¦Ñ Ð¾Ð¿Ñ†Ñ–Ñ Ð´Ð°Ñ” змогу імпортувати дані з текÑтового файлу .sql у нову або Ñ–Ñнуючу базу даних. Файл SQL можна Ñтворити на більшоÑті двигунів баз даних, включно з MySQL Ñ– PostgreSQL. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + Відкрити майÑтер, Ñкий дає змогу імпортувати дані з файлу CSV у таблицю бази даних. + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + Відкрити майÑтер, Ñкий дає змогу імпортувати дані з файлу CSV у таблицю бази даних. Файли CSV можна Ñтворити в більшоÑті програм баз даних Ñ– електронних таблиць. + + + + Export a database to a .sql dump text file. + ЕкÑпортувати базу даних у текÑтовий файл .sql. + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + Ð¦Ñ Ð¾Ð¿Ñ†Ñ–Ñ Ð´Ð°Ñ” змогу екÑпортувати базу даних у текÑтовий файл .sql. Файли SQL міÑÑ‚Ñть вÑÑ– дані, необхідні Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð±Ð°Ð·Ð¸ даних у більшоÑті движків баз даних, включно з MySQL Ñ– PostgreSQL. + + + + &Table(s) as CSV file... + Таблиці у файл CSV... + + + + Export a database table as a comma separated text file. + ЕкÑпортувати таблицю бази даних Ñк CSV текÑтовий файл. + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + ЕкÑпортувати таблицю бази даних Ñк CSV текÑтовий файл, готовий Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð² інші бази даних або програми електронних таблиць. + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + Відкрити майÑтер ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†ÑŒ, де можливо визначити ім'Ñ Ñ– Ð¿Ð¾Ð»Ñ Ð´Ð»Ñ Ð½Ð¾Ð²Ð¾Ñ— таблиці в базі даних + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + Відкрити майÑтер Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ–, де можна вибрати таблицю бази даних Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ. + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + Відкрити майÑтер ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð†Ð½Ð´ÐµÐºÑу, в Ñкому можна визначити новий Ñ–Ð½Ð´ÐµÐºÑ Ð´Ð»Ñ Ñ–Ñнуючої таблиці бази даних. + + + + &Preferences... + &ÐалаштуваннÑ... + + + + + Open the preferences window. + Відкрити вікно налаштувань. + + + + &DB Toolbar + &Панель інÑтрументів БД + + + + Shows or hides the Database toolbar. + Показати або приховати панель інÑтрументів БД. + + + + Shift+F1 + + + + + New &tab + + + + + Execute all/selected SQL + + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + + + + + Open SQL file(s) + + + + + This button opens files containing SQL statements and loads them in new editor tabs + + + + + Ctrl+Shift+T + + + + + Execute line + + + + + &Wiki + + + + + F1 + + + + + Bug &Report... + + + + + Feature Re&quest... + + + + + Web&site + + + + + &Donate on Patreon... + + + + + &Save Project + + + + + Open &Project + + + + + &Attach Database... + + + + + + Add another database file to the current database connection + + + + + This button lets you add another database file to the current database connection + + + + + &Set Encryption... + + + + + SQLCipher &FAQ + + + + + Table(&s) to JSON... + + + + + Open Data&base Read Only... + + + + + Ctrl+Shift+O + + + + + Save results + + + + + Save the results view + + + + + This button lets you save the results of the last executed query + + + + + + Find text in SQL editor + + + + + Find + + + + + This button opens the search bar of the editor + + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + + + + + Find or replace + + + + + This button opens the find/replace dialog for the current editor tab + + + + + Ctrl+H + + + + + Export to &CSV + ЕкÑпортувати в &CSV + + + + Export to &JSON + + + + + Save as &view + Зберегти Ñк &виглÑд + + + + Save as view + Зберегти Ñк виглÑд + + + + &Open Database + + + + + Drag && Drop SELECT Query + + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + + + + + Browse Table + + + + + Close Pro&ject + + + + + + Close project and database files and return to the initial state + + + + + + Ctrl+Shift+W + + + + + Table from CSV data in Clipboard... + + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + + + + + Show &Row Counts + + + + + This shows the number of rows for each table and view in the database. + + + + + Save Database &As... + + + + + Save the current database as a different file + + + + + Refresh + Оновити + + + + Reload the database structure + + + + + Ctrl+Shift+F4 + + + + + + Detach Database + + + + + + Detach database file attached to the current database connection + + + + + Shows or hides the Project toolbar. + + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + + + + + This button lets you open a DB Browser for SQLite project file + + + + + Extra DB Toolbar + + + + + New In-&Memory Database + + + + + Drag && Drop Qualified Names + + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + + + + + Drag && Drop Enquoted Names + + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + + + + + &Integrity Check + + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + + + + + &Foreign-Key Check + + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + + + + + &Quick Integrity Check + + + + + Run a quick integrity check over the open DB + + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + + + + + &Optimize + + + + + Attempt to optimize the database + + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + + + + + + Print + + + + + Print text from current SQL editor tab + + + + + Open a dialog for printing the text in the current SQL editor tab + + + + + Print the structure of the opened database + + + + + Open a dialog for printing the structure of the opened database + + + + + &Save Project As... + + + + + + + Save the project in a file selected in a dialog + + + + + Save A&ll + + + + + + + Save DB file, project file and opened SQL files + + + + + Ctrl+Shift+S + + + + + &Recently opened + &Ðедавно відкриті + + + + Open an existing database file in read only mode + Відкрити Ñ–Ñнуючий файл БД у режимі тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ + + + + Ctrl+T + + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + + + + + Un/comment block of SQL code + + + + + Un/comment block + + + + + Comment or uncomment current line or selected block of code + + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + + + + + Ctrl+/ + + + + + Stop SQL execution + + + + + Stop execution + + + + + Stop the currently running SQL script + + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + + + + + Temp Store + + + + + Secure Delete + + + + + Case Sensitive Like + + + + + Journal Mode + + + + + Journal Size Limit + + + + + Recursive Triggers + + + + + Page Size + + + + + Foreign Keys + + + + + Auto Vacuum + + + + + Max Page Count + + + + + Checkpoint Full FSYNC + + + + + + Off + + + + + + Normal + + + + + + Full + + + + + Default + За замовчуваннÑм + + + + File + Файл + + + + + Memory + + + + + Delete + + + + + Truncate + + + + + Persist + + + + + WAL + + + + + Exclusive + + + + + Automatic Index + + + + + Ignore Check Constraints + + + + + Full FSYNC + + + + + WAL Auto Checkpoint + + + + + User Version + + + + + Synchronous + + + + + None + ÐÑ– + + + + Incremental + + + + + Locking Mode + + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + + + + + &Recent Files + + + + + SQL &Log + &Журнал SQL + + + + Show S&QL submitted by + По&казати SQL, Ñкий виконано + + + + &Plot + &Графік + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + + + + + + Project Toolbar + + + + + Extra DB toolbar + + + + + + + Close the current database file + + + + + &New Database + + + + + + Ctrl+F4 + + + + + &Revert Changes + &СкаÑувати зміни + + + + &Undo + + + + + + Undo last change to the database + + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + + + + + &Write Changes + &ЗапиÑати зміни + + + + &Database from SQL file... + &База даних з файлу SQL... + + + + &Table from CSV file... + &Таблиці з файлу CSV... + + + + &Database to SQL file... + Базу &даних в файл SQL... + + + + &Create Table... + &Створити таблицю... + + + + &Delete Table... + &Видалити таблицю... + + + + &Modify Table... + &Змінити таблицю... + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + + + + + Create &Index... + Створити Ñ–&ндекÑ... + + + + W&hat's This? + Що &це таке? + + + + &About + + + + + This button opens a new tab for the SQL editor + + + + + &Execute SQL + Ви&конати код SQL + + + + + + Save SQL file + Зберегти файл SQL + + + + &Load Extension... + + + + + Ctrl+E + + + + + Export as CSV file + ЕкÑпортувати у файл CSV + + + + Export table as comma separated values file + ЕкÑпортувати таблицю Ñк CSV файл + + + + + Save the current session to a file + Зберегти поточний Ñтан у файл + + + + Open &Project... + + + + + + Load a working session from a file + Завантажити робочий Ñтан із файлу + + + + Copy Create statement + Копіювати CREATE вираз + + + + Copy the CREATE statement of the item to the clipboard + Копіювати CREATE вираз елемента в буффер обміну + + + + Ctrl+Return + + + + + Ctrl+L + + + + + + Ctrl+P + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Encrypted + Зашифрований + + + + Read only + Тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ + + + + Database file is read only. Editing the database is disabled. + База даних тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ. Ð ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð±Ð¾Ñ€Ð¾Ð½ÐµÐ½Ðµ. + + + + Database encoding + ÐšÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ð°Ð·Ð¸ даних + + + + Database is encrypted using SQLCipher + База даних зашифрована з викориÑтаннÑм SQLCipher + + + + + Choose a database file + Вибрати файл бази даних + + + + Could not open database file. +Reason: %1 + Ðеможливо відкрити файл бази даних. +Причина: %1 + + + + + + Choose a filename to save under + Вибрати ім'Ñ, під Ñким зберегти дані + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + Вийшла нова верÑÑ–Ñ Ð¾Ð³Ð»Ñдача Ð´Ð»Ñ SQLite (%1.%2.%3).<br/><br/>Вона доÑтупна Ð´Ð»Ñ ÑÐºÐ°Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° поÑиланнÑм <a href='%4'>%4</a>. + + + + DB Browser for SQLite project file (*.sqbpro) + Файл проекту оглÑдача Ð´Ð»Ñ SQLite (*.sqbpro) + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + СкаÑувати вÑÑ– зміни, зроблені у файлі бази даних '%1' піÑÐ»Ñ Ð¾Ñтаннього збереженнÑ? + + + + Choose a file to import + Оберіть файл Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + Створити новий файл бази даних Ð´Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¾Ð²Ð°Ð½Ð¸Ñ… даних? +Якщо відповідь ÐÑ–, то здійÑнитьÑÑ Ñпроба імпортувати дані файлу SQL в поточну базу даних. + + + + File %1 already exists. Please choose a different name. + Файл %1 вже Ñ–Ñнує. Оберіть інше ім'Ñ. + + + + Error importing data: %1 + Помилка Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ…: %1 + + + + Import completed. + Імпорт завершено. + + + + Delete View + Видалити переглÑд + + + + Delete Trigger + Видалити тригер + + + + Delete Index + Видалити Ñ–Ð½Ð´ÐµÐºÑ + + + + Reset Window Layout + + + + + Automatically load the last opened DB file at startup + + + + + The database is currently busy. + + + + + Click here to interrupt the currently running query. + + + + + Alt+Shift+W + + + + + In-Memory database + + + + + Choose a database file to save under + + + + + Error while saving the database to the new file. + + + + + Do you want to save the changes made to the project file '%1'? + + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + + + + + Are you sure you want to delete the view '%1'? + + + + + Are you sure you want to delete the trigger '%1'? + + + + + Are you sure you want to delete the index '%1'? + + + + + Error: could not delete the table. + + + + + Error: could not delete the view. + + + + + Error: could not delete the trigger. + + + + + Error: could not delete the index. + + + + + Message from database engine: +%1 + + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + + + + + Error checking foreign keys after table modification. The changes will be reverted. + + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + + + + + Edit View %1 + + + + + Edit Trigger %1 + + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + + + + + -- EXECUTING SELECTION IN '%1' +-- + + + + + -- EXECUTING LINE IN '%1' +-- + + + + + -- EXECUTING ALL IN '%1' +-- + + + + + + At line %1: + + + + + Result: %1 + + + + + Result: %2 + + + + + Execution finished with errors. + + + + + Execution finished without errors. + + + + + Opened '%1' in read-only mode from recent file list + + + + + Opened '%1' from recent file list + + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + + + + + Open Database or Project + + + + + Attach Database... + + + + + Import CSV file(s)... + + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + + + + + DB file '%1' could not be opened + + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + + + + + Table '%1' not found; settings ignored + + + + + -- Reference to file "%1" (not supported by this version) -- + + + + + Project saved to file '%1' + + + + + Yes. Don't ask again + + + + + This action will open a new SQL tab with the following statements for you to edit and run: + + + + + Busy (%1) + + + + + Rename Tab + + + + + Duplicate Tab + + + + + Close Tab + + + + + Opening '%1'... + + + + + There was an error opening '%1'... + + + + + Value is not a valid URL or filename: %1 + + + + + %1 rows returned in %2ms + + + + + Ctrl+Tab + + + + + Ctrl+Shift+Tab + + + + + Clear List + + + + + Window Layout + + + + + Ctrl+0 + + + + + Simplify Window Layout + + + + + Alt+Shift+0 + + + + + Dock Windows at Bottom + + + + + Dock Windows at Left Side + + + + + Dock Windows at Top + + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + + + + + + + + Do you want to save the changes made to SQL tabs in a new project file? + + + + + Do you want to save the changes made to the SQL file %1? + + + + + Could not find resource file: %1 + + + + + Choose a project file to open + + + + + Could not open project file for writing. +Reason: %1 + + + + + Collation needed! Proceed? + Потрібно виконати зіÑтавленнÑ! Продовжити? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ Ð² базі даних вимагає Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ñпеціальної функції зіÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð½Ñ '%1'. +Якщо Ви продовжите, то можливе пÑÑƒÐ²Ð°Ð½Ð½Ñ Ð’Ð°ÑˆÐ¾Ñ— бази даних. +Створіть резервну копію! + + + + creating collation + + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + + + + + Please specify the view name + Вкажіть ім'Ñ Ð²Ð¸Ð³Ð»Ñду + + + + There is already an object with that name. Please choose a different name. + Об'єкт із зазначеним ім'Ñм уже Ñ–Ñнує. Виберіть інше ім'Ñ. + + + + View successfully created. + ВиглÑд уÑпішно Ñтворений. + + + + Error creating view: %1 + Помилка ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð¸Ð³Ð»Ñду: %1 + + + + This action will open a new SQL tab for running: + + + + + Press Help for opening the corresponding SQLite reference page. + + + + + + Delete Table + Видалити таблицю + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½ÑŒ PRAGMA завершить поточну транзакцію. Ð’Ñтановити значеннÑ? + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + + + + + Choose text files + Оберіть текÑтові файли + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + Помилка під Ñ‡Ð°Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ бази даних. Це означає, що не вÑÑ– зміни в базу даних було збережено. Спочатку Вам необхідно розв'Ñзати таку помилку. + +%1 + + + + Text files(*.sql *.txt);;All files(*) + ТекÑтові файли(*.sql *.txt);;Ð’ÑÑ– файли(*) + + + + Modify View + Змінити вид + + + + Modify Trigger + Змінити тригер + + + + Modify Index + Змінити Ñ–Ð½Ð´ÐµÐºÑ + + + + Modify Table + Змінити таблицю + + + + Select SQL file to open + Обрати файл SQL Ð´Ð»Ñ Ð²Ñ–Ð´ÐºÑ€Ð¸Ð²Ð°Ð½Ð½Ñ + + + + Select file name + Обрати ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ + + + + Select extension file + Обрати Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ + + + + Extension successfully loaded. + Ð Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ ÑƒÑпішно завантажено. + + + + Error loading extension: %1 + Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ: %1 + + + + + Don't show again + Ðе показувати наÑтупного разу + + + + New version available. + ДоÑтупна нова верÑÑ–Ñ. + + + + NullLineEdit + + + Set to NULL + Ð’Ñтановити в NULL + + + + Alt+Del + + + + + PlotDock + + + Plot + Графік + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + + + + + Columns + Стовпці + + + + X + X + + + + Y1 + + + + + Y2 + + + + + Axis Type + + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + + + + + Line type: + Тип лінії: + + + + + None + ÐÑ– + + + + Line + Звичайна + + + + StepLeft + Ступенева, зліва + + + + StepRight + Ступенева, Ñправа + + + + StepCenter + Ступенева, по центру + + + + Impulse + Ð†Ð¼Ð¿ÑƒÐ»ÑŒÑ + + + + Point shape: + Форма точок: + + + + Cross + ХреÑÑ‚ + + + + Plus + ÐŸÐ»ÑŽÑ + + + + Circle + Коло + + + + Disc + ДиÑк + + + + Square + Квадрат + + + + Diamond + Ромб + + + + Star + Зірка + + + + Triangle + Трикутник + + + + TriangleInverted + Трикутник перевернутий + + + + CrossSquare + ХреÑÑ‚ у квадраті + + + + PlusSquare + ÐŸÐ»ÑŽÑ Ñƒ квадраті + + + + CrossCircle + ХреÑÑ‚ у колі + + + + PlusCircle + ÐŸÐ»ÑŽÑ Ñƒ колі + + + + Peace + Світ + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>Зберегти поточний графік...</p><p>Формат файлу вибираєтьÑÑ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñм (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + Зберегти поточний графік... + + + + + Load all data and redraw plot + + + + + + + Row # + РÑдок # + + + + Copy + Копіювати + + + + Print... + + + + + Help + + + + + Show legend + + + + + Stacked bars + + + + + Fixed number format + + + + + Date/Time + + + + + Date + + + + + Time + + + + + + Numeric + + + + + Label + + + + + Invalid + + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + + + + + Choose an axis color + + + + + Choose a filename to save under + Вибрати ім'Ñ, під Ñким зберегти дані + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;Ð’ÑÑ– файли(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + + + + + Loading all remaining data for this table took %1ms. + + + + + PreferencesDialog + + + Preferences + ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ + + + + &Database + &База даних + + + + Database &encoding + &ÐšÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ð°Ð·Ð¸ даних + + + + Open databases with foreign keys enabled. + Відкривати бази даних з увімкненими зовнішніми ключами. + + + + &Foreign keys + &Зовнішні ключі + + + + + + + + + + + + + + enabled + увімкнені + + + + Default &location + &Ð Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° замовчуваннÑм + + + + + + ... + ... + + + + &General + &Загальні + + + + Remember last location + Запам'Ñтовувати оÑтанню директорію + + + + Always use this location + Завжди відкривати це Ñ€Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ + + + + Remember last location for session only + Запам'Ñтовувати оÑтанню директорію тільки Ð´Ð»Ñ ÑеÑÑ–Ñ— + + + + Lan&guage + &Мова + + + + Toolbar style + + + + + + + + + Only display the icon + + + + + + + + + Only display the text + + + + + + + + + The text appears beside the icon + + + + + + + + + The text appears under the icon + + + + + + + + + Follow the style + + + + + Automatic &updates + &Стежити за оновленнÑми + + + + DB file extensions + + + + + Manage + + + + + SQ&L to execute after opening database + SQ&L,Ñкий треба Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð¿Ñ–ÑÐ»Ñ Ð²Ñ–Ð´ÐºÑ€Ð¸Ð²Ð°Ð½Ð½Ñ Ð±Ð°Ð·Ð¸ даних + + + + Data &Browser + ОглÑдач &даних + + + + Remove line breaks in schema &view + Видалити розрив Ñ€Ñдка в &Ñхемі даних + + + + Show remote options + Показати віддалені опції + + + + Prefetch block si&ze + Розмір блоку &вибірки + + + + Default field type + Тип даних за замовчуваннÑм + + + + Font + Шрифт + + + + &Font + &Шрифт + + + + Content + ВміÑÑ‚ + + + + Symbol limit in cell + КількіÑть Ñимволів у оÑередку + + + + NULL + NULL + + + + Regular + Звичайні + + + + Binary + Двійкові дані + + + + Background + Фон + + + + Filters + Фільтри + + + + Threshold for completion and calculation on selection + + + + + Show images in cell + + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + + + + + Escape character + Символ ÐµÐºÑ€Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ + + + + Delay time (&ms) + Ð§Ð°Ñ Ð·Ð°Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ (&мÑ) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + Ð§Ð°Ñ Ð·Ð°Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ перед заÑтоÑуваннÑм нового фільтра. Ðульове Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÑÑ” очікуваннÑ. + + + + &SQL + Р&едактор SQL + + + + Context + КонтекÑÑ‚ + + + + Colour + Колір + + + + Bold + Жирний + + + + Italic + КурÑив + + + + Underline + ПідкреÑÐ»ÐµÐ½Ð½Ñ + + + + Keyword + Ключове Ñлово + + + + Function + Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ + + + + Table + Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ + + + + Comment + Коментар + + + + Identifier + Ідентифікатор + + + + String + РÑдок + + + + Current line + Поточна Ñ€Ñдок + + + + SQL &editor font size + Розмір шрифту в &редакторі SQL + + + + Tab size + Розмір табулÑції + + + + SQL editor &font + &Шрифт у редакторі SQL + + + + Error indicators + Індикатори помилок + + + + Hori&zontal tiling + Гори&зонтальний розподіл + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + Якщо Ñ†Ñ Ð¾Ð¿Ñ†Ñ–Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð°, то SQL редактор Ñ– результат запиту будуть розташовані поруч по горизонталі. + + + + Code co&mpletion + Ðвто&Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ ÐºÐ¾Ð´Ñƒ + + + + Main Window + + + + + Database Structure + Структура БД + + + + Browse Data + ПереглÑнути дані + + + + Execute SQL + Виконати SQL + + + + Edit Database Cell + Ð ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ€ÐºÐ¸ БД + + + + When this value is changed, all the other color preferences are also set to matching colors. + + + + + Follow the desktop style + + + + + Dark style + + + + + Application style + + + + + This sets the font size for all UI elements which do not have their own font size option. + + + + + Font size + + + + + Max Recent Files + + + + + Prompt to save SQL tabs +in new project file + + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + + + + + Database structure font size + + + + + Font si&ze + + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + + + + + Field display + + + + + Light style + + + + + Displayed &text + + + + + Formatted + + + + + + + + + + + + Click to set this color + + + + + Text color + + + + + Background color + + + + + + Preview only (N/A) + + + + + Foreground + + + + + Selection background + + + + + Selection foreground + + + + + Highlight + + + + + SQL &results font size + + + + + Use tabs for indentation + + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + + + + + &Wrap lines + + + + + Never + + + + + At word boundaries + + + + + At character boundaries + + + + + At whitespace boundaries + + + + + &Quotes for identifiers + + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + + + + + "Double quotes" - Standard SQL (recommended) + + + + + `Grave accents` - Traditional MySQL quotes + + + + + [Square brackets] - Traditional MS SQL Server quotes + + + + + Keywords in &UPPER CASE + + + + + When set, the SQL keywords are completed in UPPER CASE letters. + + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + + + + + Close button on tabs + + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + + + + + &Extensions + Р&Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ + + + + Select extensions to load for every database: + Оберіть розширеннÑ, щоб завантажувати Ñ—Ñ… Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ñ— бази даних: + + + + Add extension + Додати Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ + + + + Remove extension + Видалити Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ + + + + Select built-in extensions to load for every database: + + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>ОглÑдач Ð´Ð»Ñ SQLite дає змогу викориÑтовувати оператор REGEXP 'з коробки'. Ðле попри<br/>це, можливі кілька різних варіантів реалізацій цього оператора й Ви вільні<br/>у виборі, Ñкий Ñаме викориÑтовувати. Можна відімкнути нашу реалізацію та викориÑтовувати іншу -<br/>шлÑхом Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾Ð³Ð¾ розширеннÑ. Ð’ цьому випадку потрібно перезавантажити програму.</p></body></html> + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + + + + + Allow loading extensions from SQL code + + + + + Clone databases into + Клонувати бази даних до + + + + Proxy + + + + + Configure + + + + + Export Settings + + + + + Import Settings + + + + + Disable Regular Expression extension + Відімкнути Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ð ÐµÐ³ÑƒÐ»Ñрних Виразів + + + + Remote + Віддалений Ñервер + + + + CA certificates + СÐ-Ñертифікати + + + + + Subject CN + Об'єкт CN + + + + Common Name + Звичайне ім'Ñ + + + + Subject O + Об'єкт O + + + + Organization + ÐžÑ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ + + + + + Valid from + ДійÑний з + + + + + Valid to + ДійÑний до + + + + + Serial number + Серійний номер + + + + Your certificates + Ваш Ñертифікат + + + + File + Файл + + + + Subject Common Name + Звичайне ім'Ñ Ð¾Ð±'єкта + + + + Issuer CN + РозповÑюдник CN + + + + Issuer Common Name + Звичайне ім'Ñ Ñ€Ð¾Ð·Ð¿Ð¾Ð²Ñюдника + + + + + Choose a directory + Оберіть каталог + + + + + The language will change after you restart the application. + Мова змінитьÑÑ Ð¿Ñ–ÑÐ»Ñ Ð¿ÐµÑ€ÐµÐ·Ð°Ð¿ÑƒÑку програми. + + + + Select extension file + Обираємо файл Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ + + + + Extensions(*.so *.dylib *.dll);;All files(*) + + + + + Import certificate file + Імпортувати файл Ñертифіката + + + + No certificates found in this file. + Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ файлу не знайдено Ñертифікатів. + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + Ви впевнені, що хочете видалити цей Ñертифікат? Ð’ÑÑ– дані Ñертифіката видалÑтьÑÑ Ð· налаштувань програми! + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + + + + + Save Settings File + + + + + + Initialization File (*.ini) + + + + + The settings file has been saved in location : + + + + + + Open Settings File + + + + + The settings file was loaded properly. + + + + + The selected settings file is not a normal settings file. +Please check again. + + + + + ProxyDialog + + + Proxy Configuration + + + + + Pro&xy Type + + + + + Host Na&me + + + + + Port + + + + + Authentication Re&quired + + + + + &User Name + + + + + Password + + + + + None + ÐÑ– + + + + System settings + + + + + HTTP + + + + + SOCKS5 + + + + + QObject + + + Error importing data + Помилка Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… + + + + from record number %1 + з запиÑу номер %1 + + + + . +%1 + . +%1 + + + + Importing CSV file... + + + + + Cancel + СкаÑувати + + + + All files (*) + + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + + + + + Left + + + + + Right + + + + + Center + + + + + Justify + + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + + + + + DB Browser for SQLite Project Files (*.sqbpro) + + + + + SQL Files (*.sql) + + + + + All Files (*) + + + + + Text Files (*.txt) + + + + + Comma-Separated Values Files (*.csv) + + + + + Tab-Separated Values Files (*.tsv) + + + + + Delimiter-Separated Values Files (*.dsv) + + + + + Concordance DAT files (*.dat) + + + + + JSON Files (*.json *.js) + + + + + XML Files (*.xml) + + + + + Binary Files (*.bin *.dat) + + + + + SVG Files (*.svg) + + + + + Hex Dump Files (*.dat *.bin) + + + + + Extensions (*.so *.dylib *.dll) + + + + + Initialization File (*.ini) + + + + + QsciCommand + + Paste + Ð’Ñтавити + + + Cancel + СкаÑувати + + + + QsciLexerCPP + + Default + За замовчуваннÑм + + + Keyword + Ключове Ñлово + + + Identifier + Ідентифікатор + + + + QsciLexerJSON + + Default + За замовчуваннÑм + + + String + РÑдок + + + + QsciLexerPython + + Default + За замовчуваннÑм + + + Comment + Коментар + + + Keyword + Ключове Ñлово + + + Identifier + Ідентифікатор + + + + QsciLexerSQL + + Default + За замовчуваннÑм + + + Comment + Коментар + + + Keyword + Ключове Ñлово + + + Identifier + Ідентифікатор + + + + QsciScintilla + + Select All + Обрати вÑе + + + + RemoteCommitsModel + + + Commit ID + + + + + Message + + + + + Date + + + + + Author + + + + + Size + Розмір + + + + Authored and committed by %1 + + + + + Authored by %1, committed by %2 + + + + + RemoteDatabase + + + Error opening local databases list. +%1 + Помилка Ð²Ñ–Ð´ÐºÑ€Ð¸Ð²Ð°Ð½Ð½Ñ ÑпиÑку локальних баз даних. +%1 + + + + Error creating local databases list. +%1 + Помилка ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÑпиÑку локальних баз даних. +%1 + + + + RemoteDock + + + Remote + Віддалений + + + + Local + Локальний + + + + Identity + Ідентичний + + + + Push currently opened database to server + + + + + Upload + + + + + DBHub.io + + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + + + + + Current Database + + + + + Clone + + + + + &User + + + + + &Database + &База даних + + + + Branch + + + + + Commits + + + + + Commits for + + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + + + + + Back + + + + + Delete Database + + + + + Delete the local clone of this database + + + + + Open in Web Browser + + + + + Open the web page for the current database in your browser + + + + + Clone from Link + + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + + + + + Refresh + Оновити + + + + Reload all data and update the views + + + + + Clone Database + + + + + Open Database + + + + + Open the local copy of this database + + + + + Check out Commit + + + + + Download and open this specific commit + + + + + Check out Latest Commit + + + + + Check out the latest commit of the current branch + + + + + Save Revision to File + + + + + Saves the selected revision of the database to another file + + + + + Upload Database + + + + + Upload this database as a new commit + + + + + Select an identity to connect + + + + + Public + + + + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + + + + + Invalid URL: The host name does not match the host name of the current identity. + + + + + Invalid URL: No branch name specified. + + + + + Invalid URL: No commit ID specified. + + + + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + + + + + The database has unsaved changes. Are you sure you want to push it before saving? + + + + + The database you are trying to delete is currently opened. Please close it before deleting. + + + + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + + + + + RemoteLocalFilesModel + + + Name + Ім'Ñ + + + + Branch + + + + + Last modified + ВоÑтаннє змінений + + + + Size + Розмір + + + + Commit + + + + + File + Файл + + + + RemoteModel + + + Name + Ім'Ñ + + + + Last modified + ВоÑтаннє змінений + + + + Size + Розмір + + + + Commit + + + + + Size: + + + + + Last Modified: + + + + + Licence: + + + + + Default Branch: + + + + + RemoteNetwork + + + Choose a location to save the file + + + + + Error opening remote file at %1. +%2 + Помилка під Ñ‡Ð°Ñ Ð²Ñ–Ð´ÐºÑ€Ð¸Ð²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¾Ð³Ð¾ файлу %1. +%2 + + + + Error: Invalid client certificate specified. + Помилка: Вказано неправильний Ñертифікат клієнта. + + + + Please enter the passphrase for this client certificate in order to authenticate. + Будь лаÑка, введіть парольну фразу Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ñертифіката клієнта, Ð´Ð»Ñ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ— + + + + Cancel + СкаÑувати + + + + Uploading remote database to +%1 + Ð’Ð¸Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¾Ñ— бази даних до +%1. {1?} + + + + Downloading remote database from +%1 + Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð´Ð°Ð»ÐµÐ½Ð¾Ñ— бази даних із +%1. {1?} + + + + Error: Cannot open the file for sending. + Помилка: Ðеможливо відкрити файл Ð´Ð»Ñ Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ. + + + + RemotePushDialog + + + Push database + + + + + Database na&me to push to + + + + + Commit message + + + + + Database licence + + + + + Public + + + + + Branch + + + + + Force push + + + + + Username + + + + + Database will be public. Everyone has read access to it. + + + + + Database will be private. Only you have access to it. + + + + + Use with care. This can cause remote commits to be deleted. + + + + + RunSql + + + Execution aborted by user + Ð’Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÑкаÑовано кориÑтувачем + + + + , %1 rows affected + , %1 Ñ€Ñдків поÑтраждало + + + + query executed successfully. Took %1ms%2 + + + + + executing query + + + + + SelectItemsPopup + + + A&vailable + + + + + Sele&cted + + + + + SqlExecutionArea + + + Form + Форма + + + + Find previous match [Shift+F3] + + + + + Find previous match with wrapping + + + + + Shift+F3 + + + + + The found pattern must be a whole word + + + + + Whole Words + + + + + Text pattern to find considering the checks in this frame + + + + + Find in editor + + + + + The found pattern must match in letter case + + + + + Case Sensitive + + + + + Find next match [Enter, F3] + + + + + Find next match with wrapping + + + + + F3 + + + + + Interpret search pattern as a regular expression + + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + + Regular Expression + + + + + + Close Find Bar + + + + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + + + + + Results of the last executed statements + Результати оÑтанніх виконаних операторів + + + + This field shows the results and status codes of the last executed statements. + Це поле показує результати та коди ÑтатуÑів оÑтанніх виконаних операторів. + + + + Ctrl+PgUp + + + + + Ctrl+PgDown + + + + + Couldn't read file "%1": %2. + + + + + + Couldn't save file: %1. + Ðеможливо зберегти файл: %1. + + + + Your changes will be lost when reloading it! + + + + + The file "%1" was modified by another program. Do you want to reload it?%2 + + + + + Answer "Yes to All" to reload the file on any external update without further prompting. + + + + + Answer "No to All" to ignore any external update without further prompting. + + + + + Modifying and saving the file will restore prompting. + + + + + SqlTextEdit + + + Ctrl+/ + + + + + SqlUiLexer + + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ abs(X) повертає модуль чиÑла аргументу X. + + + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ changes() повертає кількіÑть Ñ€Ñдків у базі даних, Ñкі було змінено, вÑтавлено або видалено піÑÐ»Ñ Ð²Ð´Ð°Ð»Ð¾Ð³Ð¾ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ INSERT, DELETE або UPDATE. + + + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ coalesce() повертає копію першого аргументу не-NULL, Ñкщо такого немає, то повертає NULL + + + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ ifnull() повертає копію першого аргументу не-NULL, або Ñкщо обидва аргумента NULL, то повертає NULL. + + + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ instr(X,Y) повертає кількіÑть Ñимволів, починаючи з Ñкого в Ñ€Ñдку X знайдено підрÑдок Y, або 0, Ñкщо такого не знайдено. + + + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ hex() інтерпретує аргумент Ñк BLOB Ñ– повертає Ñ€Ñдок в 16-ричній ÑиÑтемі чиÑÐ»ÐµÐ½Ð½Ñ Ñ–Ð· вміÑтом аргументу. + + + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + + + + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ last_insert_rowid() повертає ROWID оÑтаннього вÑтавленого Ñ€Ñдка. + + + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) Ð”Ð»Ñ Ñтрокового Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ X, Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ length(X) повертає кількіÑть Ñимволів (ÐЕ байтів) від початку Ñ€Ñдка до першого Ñимволу '\0'. + + + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) Ñ„ÑƒÐºÐ½Ñ†Ñ–Ñ like() еквівалентна виразу "Y LIKE X". + + + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ like() еквівалент Ð²Ð¸Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ "Y LIKE X ESCAPE Z". + + + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ lower(X) повертає копію Ñ€Ñдка X, в Ñкій уÑÑ– ACSII Ñимволи переведені в нижній регіÑтр. + + + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) видалÑÑ” Ñимволи пробілів зліва Ð´Ð»Ñ Ñ€Ñдка X. + + + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ char(X1,X2,...,XN) повертає Ñ€Ñдок, Ñкладений із Ñимволів, переданих Ñк аргументи. + + + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ glob(X,Y) еквівалент Ð²Ð¸Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ "Y GLOB X". + + + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + + + + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + + + + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ ltrim (X,Y) повертає новий Ñ€Ñдок шлÑхом Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð· Ñ€Ñдка X зліва будь-Ñкого Ñимволу з Y. + + + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ max() повертає аргумент з макÑимальним значеннÑм, або NULL, Ñкщо хоча б один аргумент дорівнює NULL. + + + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ min() повертає аргумент з мінімальним значеннÑм. + + + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ nullif(X,Y) повертає перший аргумент, Ñкщо аргументи різні, або NULL, Ñкщо вони однакові. + + + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ printf(FORMAT,...) працює так Ñамо, Ñк printf() зі Ñтандартної бібліотеки мови Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼ÑƒÐ²Ð°Ð½Ð½Ñ Ð¡Ñ–. + + + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ quote(X) повертає змінений Ñ€Ñдок X, Ñкий можна викориÑтовувати в SQL виразах. + + + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ random() повертає пÑевдовипадкове цілочиÑельне Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð· діапозона від -9223372036854775808 до +9223372036854775807. + + + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ randomblob(N) повертає N-байтний BLOB, що міÑтить пÑевдовипадкові байти. + + + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ replace(X,Y,Z) повертає новий Ñ€Ñдок на оÑнові Ñ€Ñдка X, заміною вÑÑ–Ñ… підрÑдків Y на Z. + + + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ round(X) округлює X до цілого значеннÑ. + + + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ round(X,Y) округлює X до Y чиÑел піÑÐ»Ñ ÐºÐ¾Ð¼Ð¸ праворуч. + + + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X) видалÑÑ” Ñимволи пробілу праворуч від Ñ€Ñдка X. + + + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ rtrim(X,Y) повертає новий Ñ€Ñдок шлÑхом Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð· Ñ€Ñдка X праворуч будь-Ñкого Ñимволу з Ñ€Ñдка Y. + + + + + + + (timestring,modifier,modifier,...) + (timestring,modifier,modifier,...) + + + + (format,timestring,modifier,modifier,...) + (format,timestring,modifier,modifier,...) + + + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + + + + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + + + + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + + + + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + + + + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + + + + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + + + + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + + + + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + + + + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + + + + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + + + + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + + + + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + + + + + (X) Return the arccosine of X. The result is in radians. + + + + + (X) Return the hyperbolic arccosine of X. + + + + + (X) Return the arcsine of X. The result is in radians. + + + + + (X) Return the hyperbolic arcsine of X. + + + + + (X) Return the arctangent of X. The result is in radians. + + + + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + + + + + (X) Return the hyperbolic arctangent of X. + + + + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + + + + + (X) Return the cosine of X. X is in radians. + + + + + (X) Return the hyperbolic cosine of X. + + + + + (X) Convert value X from radians into degrees. + + + + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + + + + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + + + + + (X) Return the natural logarithm of X. + + + + + (B,X) Return the base-B logarithm of X. + + + + + + (X) Return the base-10 logarithm for X. + + + + + (X) Return the logarithm base-2 for the number X. + + + + + (X,Y) Return the remainder after dividing X by Y. + + + + + () Return an approximation for Ï€. + + + + + + (X,Y) Compute X raised to the power Y. + + + + + (X) Convert X from degrees into radians. + + + + + (X) Return the sine of X. X is in radians. + + + + + (X) Return the hyperbolic sine of X. + + + + + (X) Return the square root of X. NULL is returned if X is negative. + + + + + (X) Return the tangent of X. X is in radians. + + + + + (X) Return the hyperbolic tangent of X. + + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + + + + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ soundex(X) повертає копію Ñ€Ñдка X, кодовану в форматі soundex. + + + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) substr(X,Y) повертає підрÑдок з Ñ€Ñдка X, починаючи з Y-го Ñимволу. + + + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ substr(X,Y,Z) повертає підрÑдок з Ñ€Ñдка X, починаючи з Y-го Ñимволу, завдовжки Z-Ñимволів. + + + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ total_changes() повертає кількіÑть Ñ€Ñдків, змінених за допомогою INSERT, UPDATE або DELETE, починаючи з того моменту, коли під'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð¾ бази даних було відкрито. + + + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) видалÑÑ” пробіли з обох Ñторін Ñ€Ñдка X. + + + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ trim(X,Y) Ñтворює новий Ñ€Ñдок з X шлÑхом Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð· обох кінців Ñимволів, Ñкі приÑутні в Ñ€Ñдку Y. + + + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ typeof(X) повертає Ñ€Ñдок із типом даних Ð²Ð¸Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ X. + + + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ unicode(X) повертає чиÑлове Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ UNICODE коду Ñимволу. + + + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ upper(X) повертає копію Ñ€Ñдка X, в Ñкій Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ ASCII Ñимволу регіÑтр буде перетворений з нижнього у верхній. + + + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ zeroblob(N) повертає BLOB розміром N байт зі значеннÑми 0x00. + + + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ avg() повертає Ñереднє Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²ÑÑ–Ñ… не-NULL значень групи. + + + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ count(X) повертає кількіÑть Ñ€Ñдків, у Ñких X не-NULL у групі. + + + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ group_concat() повертає Ñ€Ñдок з уÑÑ–Ñ… значень X не-NULL. + + + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ group_concat() повертає Ñ€Ñдок з уÑÑ–Ñ… значень X не-NULL. Y - роздільник між значеннÑми X. + + + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) Ðгрегатна Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ max() повертає макÑимальне Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ X. + + + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) Ðгрегатна Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ min() повертає мінімальне не-NULL Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ X. + + + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) Ðгрегатні функції sum() Ñ– total() повертають Ñуму вÑÑ–Ñ… не-NULL значень Ð´Ð»Ñ X. + + + + SqliteTableModel + + + reading rows + + + + + loading... + + + + + References %1(%2) +Hold %3Shift and click to jump there + + + + + Error changing data: +%1 + Помилка зміни даних: +%1 + + + + retrieving list of columns + + + + + Fetching data... + + + + + + Cancel + СкаÑувати + + + + TableBrowser + + + Browse Data + ПереглÑнути дані + + + + &Table: + &ТаблицÑ: + + + + Select a table to browse data + Оберіть таблицю Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду даних + + + + Use this list to select a table to be displayed in the database view + ВикориÑтовуйте цей ÑпиÑок, щоб вибрати таблицю, Ñку буде показано в переглÑдачі баз даних + + + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + + + + + Text pattern to find considering the checks in this frame + + + + + Find in table + + + + + Find previous match [Shift+F3] + + + + + Find previous match with wrapping + + + + + Shift+F3 + + + + + Find next match [Enter, F3] + + + + + Find next match with wrapping + + + + + F3 + + + + + The found pattern must match in letter case + + + + + Case Sensitive + + + + + The found pattern must be a whole word + + + + + Whole Cell + + + + + Interpret search pattern as a regular expression + + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + + + + + Regular Expression + + + + + + Close Find Bar + + + + + Text to replace with + + + + + Replace with + + + + + Replace next match + + + + + + Replace + + + + + Replace all matches + + + + + Replace all + + + + + Export to &JSON + + + + + + Export the filtered data to JSON + + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + + + + + Copy column name + + + + + Copy the database table column name to your clipboard + + + + + New Data Browser + + + + + + Add a new docked Data Browser + + + + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + + + + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>Прокрутити на початок</p></body></html> + + + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>ÐатиÑÐºÐ°Ð½Ð½Ñ Ñ†Ñ–Ñ”Ñ— кнопки переміщує до початку таблиці.</p></body></html> + + + + |< + |< + + + + Scroll one page upwards + + + + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + + + + + < + < + + + + 0 - 0 of 0 + 0 - 0 з 0 + + + + Scroll one page downwards + + + + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + + + + + > + > + + + + Scroll to the end + Прокрутити до ÐºÑ–Ð½Ñ†Ñ + + + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + + + + + >| + >| + + + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>ÐатиÑніть тут, щоб перейти до зазначеного запиÑу</p></body></html> + + + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>Ð¦Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° викориÑтовуєтьÑÑ, щоб переміÑтитиÑÑ Ð´Ð¾ запиÑу, номер Ñкого зазначений в зоні Перейти до </p></body></html> + + + + Go to: + Перейти до: + + + + Enter record number to browse + Введіть номер запиÑу Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду + + + + Type a record number in this area and click the Go to: button to display the record in the database view + Ðадрукуйте номер запиÑу в цій зоні й натиÑніть кнопку Перейти до:, щоб показати Ð·Ð°Ð¿Ð¸Ñ Ñƒ базі даних + + + + 1 + 1 + + + + Show rowid column + Показати Ñтовпець rowid + + + + Toggle the visibility of the rowid column + Змінити видиміÑть ÑÑ‚Ð¾Ð²Ð¿Ñ†Ñ rowid + + + + Unlock view editing + Розблокувати Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð³Ð»Ñду + + + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + Це розблоковує поточний виглÑд Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ. Проте вам необхідно виділити тригери Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ + + + + Edit display format + Формат показу + + + + Edit the display format of the data in this column + Ð ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ñƒ показу Ð´Ð»Ñ Ð´Ð°Ð½Ð¸Ñ… у цьому Ñтовпці + + + + + New Record + Додати Ð·Ð°Ð¿Ð¸Ñ + + + + + Insert a new record in the current table + Додати новий Ð·Ð°Ð¿Ð¸Ñ Ñƒ поточну таблицю + + + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + + + + + + Delete Record + Видалити Ð·Ð°Ð¿Ð¸Ñ + + + + Delete the current record + Видалити поточний Ð·Ð°Ð¿Ð¸Ñ + + + + + This button deletes the record or records currently selected in the table + + + + + + Insert new record using default values in browsed table + + + + + Insert Values... + + + + + + Open a dialog for inserting values in a new record + + + + + Export to &CSV + ЕкÑпортувати в &CSV + + + + + Export the filtered data to CSV + + + + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + + + + + Save as &view + Зберегти Ñк &виглÑд + + + + + Save the current filter, sort column and display formats as a view + + + + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + + + + + Save Table As... + + + + + + Save the table as currently displayed + + + + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + + + + + Hide column(s) + + + + + Hide selected column(s) + + + + + Show all columns + + + + + Show all columns that were hidden + + + + + + Set encoding + ÐšÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ + + + + Change the encoding of the text in the table cells + Змінити ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐºÑту в цій комірці таблиці + + + + Set encoding for all tables + Ð’Ñтановити ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð²ÑÑ–Ñ… таблиць + + + + Change the default encoding assumed for all tables in the database + Змінити ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° замовчуваннÑм Ð´Ð»Ñ Ð²ÑÑ–Ñ… таблиць у базі даних + + + + Clear Filters + + + + + Clear all filters + ОчиÑтити вÑÑ– фільтри + + + + + This button clears all the filters set in the header input fields for the currently browsed table. + + + + + Clear Sorting + + + + + Reset the order of rows to the default + + + + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + + + + + Print + + + + + Print currently browsed table data + + + + + Print currently browsed table data. Print selection if more than one cell is selected. + + + + + Ctrl+P + + + + + Refresh + Оновити + + + + Refresh the data in the selected table + + + + + This button refreshes the data in the currently selected table. + Ð¦Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° оновлює дані обраної на цей момент таблиці. + + + + F5 + + + + + Find in cells + + + + + Open the find tool bar which allows you to search for values in the table view below. + + + + + + Bold + Жирний + + + + Ctrl+B + + + + + + Italic + КурÑив + + + + + Underline + ПідкреÑÐ»ÐµÐ½Ð½Ñ + + + + Ctrl+U + + + + + + Align Right + + + + + + Align Left + + + + + + Center Horizontally + + + + + + Justify + + + + + + Edit Conditional Formats... + + + + + Edit conditional formats for the current column + + + + + Clear Format + + + + + Clear All Formats + + + + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + + + + + + Font Color + + + + + + Background Color + + + + + Toggle Format Toolbar + + + + + Show/hide format toolbar + + + + + + This button shows or hides the formatting toolbar of the Data Browser + + + + + Select column + + + + + Ctrl+Space + + + + + Replace text in cells + + + + + Freeze columns + + + + + Make all columns from the first column up to this column not move when scrolling horizontally + + + + + Filter in any column + + + + + Ctrl+R + + + + + %n row(s) + + + + + + + + + , %n column(s) + + + + + + + + + . Sum: %1; Average: %2; Min: %3; Max: %4 + + + + + Conditional formats for "%1" + + + + + determining row count... + + + + + %L1 - %L2 of >= %L3 + + + + + %L1 - %L2 of %L3 + + + + + (clipped at %L1 rows) + + + + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + Будь лаÑка, введіть пÑевдо-первинний ключ Ð´Ð»Ñ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ð¾Ñті Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ цьому виді. Це має бути Ñ–'Ð¼Ñ ÑƒÐ½Ñ–ÐºÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ ÑÑ‚Ð¾Ð²Ð¿Ñ†Ñ Ñƒ виді + + + + Delete Records + + + + + Duplicate records + + + + + Duplicate record + Дублікат запиÑу + + + + Ctrl+" + + + + + Adjust rows to contents + + + + + Error deleting record: +%1 + Помилка Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñу: +%1 + + + + Please select a record first + Будь лаÑка, Ñпочатку оберіть Ð·Ð°Ð¿Ð¸Ñ + + + + Please choose a new encoding for all tables. + Оберіть нову ÑиÑтему ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð²ÑÑ–Ñ… таблиць. + + + + Please choose a new encoding for this table. + Оберіть нову ÑиÑтему ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— таблиці. + + + + %1 +Leave the field empty for using the database encoding. + %1 +Залиште це поле порожнім Ñкщо хочете, щоб викориÑтовувалоÑÑ ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° замовчуваннÑм. + + + + This encoding is either not valid or not supported. + ÐšÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ð½ÐµÐ²Ñ–Ñ€Ð½Ðµ або не підтримуєтьÑÑ. + + + + %1 replacement(s) made. + + + + + TableBrowserDock + + + New Data Browser + + + + + Rename Data Browser + + + + + Close Data Browser + + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + + + + + VacuumDialog + + + Compact Database + Ð£Ñ‰Ñ–Ð»ÑŒÐ½ÐµÐ½Ð½Ñ Ð‘Ð” + Ð£Ñ‰Ñ–Ð»ÑŒÐ½ÐµÐ½Ð½Ñ Ð±Ð°Ð·Ð¸ даних + + + + Warning: Compacting the database will commit all of your changes. + + + + + Please select the databases to co&mpact: + + + + diff --git a/src/translations/sqlb_zh.ts b/src/translations/sqlb_zh.ts index 198d2f4a6..fc4f28281 100644 --- a/src/translations/sqlb_zh.ts +++ b/src/translations/sqlb_zh.ts @@ -1,2043 +1,8024 @@ - + AboutDialog - About SqliteBrowser - 关于 SqliteBrowser + About DB Browser for SQLite + 关于 DB Browser for SQLite - + Version 版本 - - Qt Version - Qt 版本 + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + <html><head/><body><p>DB Browser for SQLite 是一个开æºçš„ã€å…费的å¯è§†åŒ–工具,用于创建ã€è®¾è®¡å’Œç¼–辑 SQLite æ•°æ®åº“文件。</p><p>å®ƒæ ¹æ® Mozilla Public License Version 2 å’Œ GNU General Public License Version 3 或更高版本的åŒé‡è®¸å¯è¿›è¡ŒæŽˆæƒã€‚您å¯ä»¥æ ¹æ®è¿™äº›è®¸å¯è¯çš„æ¡ä»¶è¿›è¡Œä¿®æ”¹æˆ–é‡æ–°åˆ†å‘。</p><p>详情请å‚è§ <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> å’Œ <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a>。</p><p>有关此程åºçš„æ›´å¤šä¿¡æ¯ï¼Œè¯·è®¿é—®æˆ‘们的网站:<a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">此软件使用æ¥è‡ª <a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a> çš„ GPL/LGPL Qt Toolkit。<br/>æœ‰å…³è®¸å¯æ¡æ¬¾å’Œä¿¡æ¯ï¼Œè¯·å‚è§ <a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a>。</span></p><p><span style=" font-size:8pt;">我们使用 nalgeon/sqlean åº“æ¥æ”¯æŒ SQLite 扩展。<br/>è¯¥åº“æ ¹æ® MIT 许å¯è¯æŽˆæƒï¼Œæ›´å¤šä¿¡æ¯è¯·å‚è§ï¼š<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">此外,我们使用 Michael Buckley çš„ Pastel SVG å›¾æ ‡é›†ï¼Œè¯¥å›¾æ ‡é›†æ ¹æ® Creative Commons Attribution Share Alike 4.0 许å¯è¯æŽˆæƒã€‚<br/>详情请å‚è§ <a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a>。</span></p></body></html> + + + + AddRecordDialog + + + Add New Record + 新增记录 + + + + Enter values for the new record considering constraints. Fields in bold are mandatory. + 为新增的记录填写满足约æŸçš„值。加粗的字段必须填写。 + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + 在“值â€åˆ—中指定对应“åç§°â€åˆ—çš„å€¼ã€‚â€œç±»åž‹â€æä¾›å­—æ®µçš„ç±»åž‹ã€‚é»˜è®¤å€¼çš„æ˜¾ç¤ºæ ·å¼ç­‰åŒ NULL 值。 + + + + Name + åç§° + + + + Type + 类型 + + + + Value + 值 + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + è¦æ’入的值。ä¸åšä¿®æ”¹åˆ™ä¼šä½¿ç”¨é»˜è®¤å¡«å¥½çš„默认值。 + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + 你在上方编辑值时,这里会显示æ’入新记录所用的 SQL 语å¥ã€‚ä½ å¯ä»¥åœ¨ä¿å­˜å‰æ‰‹åŠ¨ä¿®æ”¹è¯­å¥ã€‚ + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">ä¿å­˜</span> 将会把显示的 SQL è¯­å¥æäº¤åˆ°æ•°æ®åº“以æ’入新记录。</p><p><span style=" font-weight:600;">æ¢å¤é»˜è®¤</span> 将会把 <span style=" font-weight:600;">值</span> 列æ¢å¤ä¸ºåˆå§‹å€¼ã€‚</p><p><span style=" font-weight:600;">å–æ¶ˆ</span> 将会关闭此界é¢ï¼Œä¸æ‰§è¡Œè¯­å¥ã€‚</p></body></html> + + + + Auto-increment + + 自增 + + + + + Unique constraint + + å”¯ä¸€çº¦æŸ + + + + + Check constraint: %1 + + 检查约æŸ: %1 + + + + + Foreign key: %1 + + 外键: %1 + + + + + Default value: %1 + + 默认值: %1 + + + + + Error adding record. Message from database engine: + +%1 + 添加记录失败。æ¥è‡ªæ•°æ®åº“引擎的消æ¯: + +%1 + + + + Are you sure you want to restore all the entered values to their defaults? + ä½ ç¡®å®šè¦æŠŠè¾“å…¥çš„æ‰€æœ‰å€¼éƒ½æ¢å¤æˆé»˜è®¤å€¼å—? + + + + Application + + + Possible command line arguments: + å¯ç”¨å‘½ä»¤è¡Œå‚æ•°: + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + -o/--option å’Œ -O/--save-option é€‰é¡¹éœ€è¦ group/setting=value æ ¼å¼çš„傿•° + + + + The user settings file location is replaced with the argument value instead of the environment variable value. + 用户设置文件的ä½ç½®å°†ä½¿ç”¨å‚数值而éžçŽ¯å¢ƒå˜é‡å€¼ã€‚ + + + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + 忽略的环境å˜é‡ (DB4S_SETTINGS_FILE) 值 : + + + + + The file %1 does not exist + 文件 %1 ä¸å­˜åœ¨ + + + + Usage + 用法 + + + + options + 选项 + + + + + database + æ•°æ®åº“ + + + + + project + 项目 + + + + + csv-file + csv文件 + + + + Show command line options + 显示命令行选项 + + + + Exit application after running scripts + 脚本è¿è¡Œå®Œæ¯•åŽé€€å‡º + + + + + file + 文件 + + + + Execute this SQL file after opening the DB + 打开数æ®åº“åŽæ‰§è¡Œè¯¥ SQL 文件 + + + + Import this CSV file into the passed DB or into a new DB + 将该 CSV 文件导入传递过æ¥çš„æ•°æ®åº“或者新数æ®åº“ + + + + table + 表 + + + + Browse this table, or use it as target of a data import + æµè§ˆè¯¥è¡¨ï¼Œæˆ–用它作为数æ®å¯¼å…¥ç›®æ ‡ + + + + Open database in read-only mode + 用åªè¯»æ¨¡å¼æ‰“开数æ®åº“ + + + + settings_file + 设置文件 + + + + Run application based on this settings file + 基于该设置文件è¿è¡Œç¨‹åº + + + + + group + 组 + + + + + settings + 设置 + + + + + value + 值 + + + + Run application with this setting temporarily set to value + 临时设定该值并è¿è¡Œç¨‹åº + + + + Run application saving this value for this setting + ä¿å­˜è¯¥è®¾ç½®å€¼å¹¶è¿è¡Œç¨‹åº + + + + Display the current version + 显示当å‰ç‰ˆæœ¬ + + + + Open this SQLite database + 打开该 SQLite æ•°æ®åº“ + + + + Open this project file (*.sqbpro) + 打开该项目文件 (*.sqbpro) + + + + Import this CSV file into an in-memory database + 导入该 CSV 文件到一个内存数æ®åº“ + + + + + + The %1 option requires an argument + 选项 %1 需è¦ä¸€ä¸ªå‚æ•° + + + + The -S/--settings option requires an argument. The option is ignored. + -S/--settings 选项需è¦ä¸€ä¸ªå‚数。此选项已忽略。 + + + + Invalid option/non-existent file: %1 + 无效选项/ä¸å­˜åœ¨çš„æ–‡ä»¶: %1 + + + + SQLite Version + SQLite 版本 + + + + SQLCipher Version %1 (based on SQLite %2) + SQLCipher 版本 %1 (基于 SQLite %2) + + + + DB Browser for SQLite Version %1. + DB Browser for SQLite 版本 %1。 + + + + Last commit hash when built: %1 + 构建时的最新æäº¤: %1 + + + + Built for %1, running on %2 + 为 %1 构建,è¿è¡ŒäºŽ %2 + + + + Qt Version %1 + Qt 版本 %1 + + + + CipherDialog + + + SQLCipher encryption + SQLCipher 加密 + + + + &Password + 密ç (&P) + + + + &Reenter password + 确认密ç (&R) + + + + Encr&yption settings + 加密设置(&Y) + + + + SQLCipher &3 defaults + SQLCipher &3 默认 + + + + SQLCipher &4 defaults + SQLCipher &4 默认 + + + + Custo&m + 自定义(&M) + + + + Page si&ze + 页大å°(&Z) + + + + &KDF iterations + KDF迭代(&K) + + + + HMAC algorithm + HMAC算法 + + + + KDF algorithm + KDF算法 + + + + Plaintext Header Size + çº¯æ–‡æœ¬æ–‡ä»¶å¤´å¤§å° + + + + Passphrase + å£ä»¤ + + + + Raw key + 原始密钥 + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + 请设置密ç ä»¥åŠ å¯†æ•°æ®åº“。 +注æ„å¦‚æžœä¿®æ”¹äº†ä»»ä½•å…¶ä»–é€‰é¡¹è®¾ç½®ï¼Œä»¥åŠæ¯æ¬¡æ‰“开数æ®åº“时,您都需è¦é‡æ–°è¾“入此密ç ã€‚ +ä¸å¡«å¯†ç è¡¨ç¤ºç¦ç”¨åŠ å¯†ã€‚ +加密过程将花费一些时间,您应该在加密之å‰å¤‡ä»½æ•°æ®åº“ï¼ä¿®æ”¹åР坆å‰ï¼Œæœªä¿å­˜çš„æ›´æ”¹å°†ä¼šè¢«åº”用。 + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + 请输入加密数æ®åº“的密ç ã€‚ +如果此数æ®åº“的任何其他设置å‘生å˜åŒ–ï¼Œæ‚¨ä¹Ÿéœ€è¦æä¾›æ­¤ä¿¡æ¯ã€‚ + + + + ColumnDisplayFormatDialog + + + Choose display format + é€‰æ‹©æ˜¾ç¤ºæ ¼å¼ + + + + Display format + æ˜¾ç¤ºæ ¼å¼ + + + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + 为列 '%1' 选择显示格å¼ï¼Œå°†åœ¨æ˜¾ç¤ºæ¯ä¸ªå€¼æ—¶ä½¿ç”¨ã€‚ + + + + Default + 默认 + + + + Decimal number + å进制数 + + + + Exponent notation + 指数表示法 + + + + Hex blob + å六进制大型对象 + + + + Hex number + å六进制数 + + + + Apple NSDate to date + 苹果 NSDate 到日期 + + + + Java epoch (milliseconds) to date + Java 时间戳(毫秒)到日期 + + + + .NET DateTime.Ticks to date + .NET DateTime.Ticks 到日期 + + + + Julian day to date + 儒略日 (Julian day) 到日期 + + + + Unix epoch to local time + Unix 时间戳到本地时间 + + + + WebKit / Chromium epoch to date + å°† WebKit / Chromium 纪元转æ¢ä¸ºæ—¥æœŸ + + + + WebKit / Chromium epoch to local time + å°† WebKit / Chromium 纪元转æ¢ä¸ºæœ¬åœ°æ—¶é—´ + + + + Date as dd/mm/yyyy + 日期,格å¼ä¸º dd/mm/yyyy + + + + Lower case + å°å†™ + + + + Binary GUID to text + 二进制 GUID 到文本 + + + + SpatiaLite Geometry to SVG + SpatiaLite Geometry 到 SVG + + + + Custom display format must contain a function call applied to %1 + 自定义显示格å¼å¿…须包å«å¤„ç† %1 的函数 + + + + Error in custom display format. Message from database engine: + +%1 + è‡ªå®šä¹‰æ˜¾ç¤ºæ ¼å¼æœ‰è¯¯ã€‚æ•°æ®åº“引擎æä¾›çš„错误信æ¯ä¸ºï¼š\n\n%1 + + + + Custom display format must return only one column but it returned %1. + 自定义显示格å¼å¿…é¡»åªè¿”回1列,但目å‰è¿”回 %1 。 + + + + Octal number + 八进制数 + + + + Round number + å–æ•´æ•° + + + + Unix epoch to date + Unix 时间到日期 + + + + Upper case + 大写 + + + + Windows DATE to date + Windows 日期到日期 + + + + Custom + 自定义 + + + + CondFormatManager + + + Conditional Format Manager + æ¡ä»¶æ ¼å¼ç®¡ç†å™¨ + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + æ­¤å¯¹è¯æ¡†ç”¨äºŽåˆ›å»ºå’Œç¼–辑æ¡ä»¶æ ¼å¼ã€‚æ¯ä¸ªå•元格的样å¼å°†è¢«è®¾ç½®ä¸ºé¦–ä¸ªåŒ¹é…æ¡ä»¶çš„æ ¼å¼ã€‚æ¡ä»¶æ ¼å¼å¯ä»¥ä¸Šä¸‹ç§»åŠ¨ï¼Œé å‰çš„行优先生效。æ¡ä»¶çš„语法与过滤器相åŒã€‚空æ¡ä»¶å°†é€‚用于所有值。 + + + + Add new conditional format + 创建新的æ¡ä»¶æ ¼å¼ + + + + &Add + 添加(&A) + + + + Remove selected conditional format + 删除选中的æ¡ä»¶æ ¼å¼ + + + + &Remove + 删除(&R) + + + + Move selected conditional format up + 上移选中的æ¡ä»¶æ ¼å¼ + + + + Move &up + 上移(&U) + + + + Move selected conditional format down + 下移选中的æ¡ä»¶æ ¼å¼ + + + + Move &down + 下移(&D) + + + + Foreground + 剿™¯ + + + + Text color + 文本颜色 + + + + Background + 背景 + + + + Background color + 背景颜色 + + + + Font + 字体 + + + + Size + å¤§å° + + + + Bold + 粗体 + + + + Italic + 斜体 + + + + Underline + 下划线 + + + + Alignment + å¯¹é½ + + + + Condition + æ¡ä»¶ + + + + + Click to select color + 点击选择颜色 + + + + Are you sure you want to clear all the conditional formats of this field? + ç¡®å®žè¦æ¸…除全部æ¡ä»¶æ ¼å¼å—? + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + 请指明想è¦é™„加的数æ®åº“å + + + + Invalid file format + æ— æ•ˆçš„æ–‡ä»¶æ ¼å¼ + + + + Do you want to save the changes made to the database file %1? + æ‚¨æ˜¯å¦æƒ³ä¿å­˜å¯¹æ•°æ®åº“文件 %1 åšå‡ºçš„æ›´æ”¹? + + + + Exporting database to SQL file... + 正在导出数æ®åº“到 SQL 文件... + + + + + Cancel + å–æ¶ˆ + + + + Executing SQL... + 正在执行 SQL... + + + + Action cancelled. + æ“ä½œå·²å–æ¶ˆã€‚ + + + + Do you really want to close this temporary database? All data will be lost. + 你确定è¦å…³é—­æ­¤ä¸´æ—¶æ•°æ®åº“å—?所有数æ®éƒ½ä¼šä¸¢å¤±ã€‚ + + + + Database didn't close correctly, probably still busy + æ•°æ®åº“未正确关闭,å¯èƒ½æ­£å¿™ + + + + Cannot open destination file: '%1' + 无法打开目标文件: '%1' + + + + + Cannot backup to file: '%1'. Message: %2 + 无法备份到文件: '%1'。消æ¯: %2 + + + + The database is currently busy: + æ•°æ®åº“正忙: + + + + Do you want to abort that other operation? + ç¡®å®šè¦æ”¾å¼ƒæ“作å—? + + + + + No database file opened + 没有打开数æ®åº“文件 + + + + + Error in statement #%1: %2. +Aborting execution%3. + é”™è¯¯åœ¨è¯­å¥ #%1: %2. +正在放弃执行%3. + + + + + and rolling back + 并回滚 + + + + didn't receive any output from %1 + 未收到æ¥è‡ª %1 的任何输出 + + + + could not execute command: %1 + 未能执行命令: %1 + + + + Cannot delete this object + 无法删除此对象 + + + + Cannot set data on this object + ä¸èƒ½ä¸ºæ­¤æ•°æ®è®¾ç½®å¯¹è±¡ + + + + + A table with the name '%1' already exists in schema '%2'. + 一个与 '%1' åŒå的表已ç»å­˜åœ¨äºŽæž¶æž„ '%2' 中。 + + + + No table with name '%1' exists in schema '%2'. + æž¶æž„ '%2' 中ä¸å­˜åœ¨è¡¨ '%1' 。 + + + + + Cannot find column %1. + 找ä¸åˆ°åˆ— %1 。 + + + + Creating savepoint failed. DB says: %1 + 创建ä¿å­˜ç‚¹å¤±è´¥ã€‚æ•°æ®åº“显示:%1 + + + + Renaming the column failed. DB says: +%1 + é‡å‘½å列失败。数æ®åº“显示:\n%1 + + + + + Releasing savepoint failed. DB says: %1 + 释放ä¿å­˜ç‚¹å¤±è´¥ã€‚æ•°æ®åº“显示:%1 + + + + Creating new table failed. DB says: %1 + 建立新表失败。数æ®åº“显示:%1 + + + + Copying data to new table failed. DB says: +%1 + å¤åˆ¶æ•°æ®åˆ°æ–°è¡¨å¤±è´¥ã€‚æ•°æ®åº“显示:\n%1 + + + + Deleting old table failed. DB says: %1 + 删除旧表失败。数æ®åº“显示:%1 + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + 将表 '%1' é‡å‘½å为 '%2' 时出错。 +æ•°æ®åº“引擎给出的错误信æ¯ï¼š +%1 + + + + could not get list of db objects: %1 + æœªèƒ½èŽ·å–æ•°æ®åº“对象列表:%1 + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + 还原æŸäº›å’Œè¿™ä¸ªè¡¨å…³è”的对象失败。这个最å¯èƒ½æ˜¯å› ä¸ºæŸäº›åˆ—çš„å称更改了。这里是您å¯èƒ½éœ€è¦æ‰‹åŠ¨ä¿®å¤å’Œæ‰§è¡Œçš„ SQL 语å¥: + + + + + + could not get list of databases: %1 + æ— æ³•èŽ·å–æ•°æ®åº“列表: %1 + + + + Error loading extension: %1 + 加载扩展时出错: %1 + + + + Error loading built-in extension: %1 + 加载内置扩展时出错: %1 + + + + could not get column information + 无法获å–åˆ—ä¿¡æ¯ + + + + Error setting pragma %1 to %2: %3 + è®¾ç½®æ‚æ³¨ %1 为 %2 时出错: %3 + + + + File not found. + 文件找ä¸åˆ°ã€‚ + + + + DbStructureModel + + + Name + åç§° + + + + Object + 对象 + + + + Type + 类型 + + + + Schema + æž¶æž„ + + + + Database + æ•°æ®åº“ + + + + Browsables + 坿µè§ˆçš„ + + + + All + 所有 + + + + Temporary + 临时的 + + + + Tables (%1) + 表 (%1) + + + + Indices (%1) + 索引 (%1) + + + + Views (%1) + 视图 (%1) + + + + Triggers (%1) + 触å‘器 (%1) + + + + EditDialog + + + Edit database cell + 编辑数æ®åº“å•元格 + + + + Mode: + 模å¼: + + + + + Image + å›¾åƒ + + + + Set as &NULL + 设为&空 + + + + Apply data to cell + 将数æ®åº”用到å•元格 + + + + This button saves the changes performed in the cell editor to the database cell. + 此按钮把å•元格编辑器中的修改应用到数æ®åº“å•元格中。 + + + + Apply + 应用 + + + + Text + 文本 + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + 这是å•元格编辑器支æŒçš„æ¨¡å¼åˆ—è¡¨ã€‚é€‰æ‹©ä¸€ç§æ¨¡å¼ä»¥æŸ¥çœ‹æˆ–编辑当å‰å•元格的数æ®ã€‚ + + + + RTL Text + å³åˆ°å·¦æ–‡æœ¬ + + + + Binary + 二进制 + + + + JSON + JSON + + + + XML + XML + + + + Evaluation + 求值 + + + + + Automatically adjust the editor mode to the loaded data type + 自动调整编辑器模å¼ä¸ºåŠ è½½çš„æ•°æ®çš„类型 + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + æ­¤å¤é€‰æŒ‰é’®å¯å¯ç”¨æˆ–ç¦ç”¨ç¼–辑器模å¼çš„自动切æ¢ã€‚当新å•元格被选中或新数æ®è¢«å¯¼å…¥æ—¶ï¼Œå¦‚æžœå¯ç”¨äº†è‡ªåŠ¨åˆ‡æ¢ï¼Œæ¨¡å¼ä¼šè°ƒæ•´ä¸ºæ£€æµ‹åˆ°çš„æ•°æ®ç±»åž‹ã€‚之åŽä½ ä¹Ÿæ‰‹åŠ¨åˆ‡æ¢ç¼–辑器的模å¼ã€‚如果你希望æµè§ˆå„å•å…ƒæ ¼çš„æ—¶å€™éƒ½ä¿æŒæ‰‹åŠ¨é€‰æ‹©çš„æ¨¡å¼ï¼Œè¯·æŠŠæ­¤æŒ‰é’®åˆ‡åˆ°å…³é—­çжæ€ã€‚ + + + + Auto-switch + è‡ªåŠ¨åˆ‡æ¢ + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + æ­¤Qt编辑器用于å³åˆ°å·¦çš„æ–‡æœ¬ï¼ˆé»˜è®¤æ–‡æœ¬ç¼–è¾‘å™¨ä¸æ”¯æŒè¿™ç§æ ¼å¼ï¼‰ã€‚当检测到å³åˆ°å·¦å­—符时,会自动选择这ç§ç¼–辑器模å¼ã€‚ + + + + Identification of the cell currently in the editor + ç›®å‰åœ¨ç¼–辑器中展示的å•元格的识别结果 + + + + Type and size of data currently in table + è¡¨ä¸­å½“å‰æ•°æ®çš„ç±»åž‹å’Œå¤§å° + + + + Open preview dialog for printing the data currently stored in the cell + 为此å•元格中目å‰å­˜å‚¨çš„æ•°æ®æ‰“开“打å°é¢„览â€å¯¹è¯æ¡† + + + + Auto-format: pretty print on loading, compact on saving. + 自动格å¼: è¯»å–æ—¶æ ¼å¼åŒ–,存储时紧凑化。 + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + 当å¯ç”¨æ—¶ï¼Œè‡ªåŠ¨æ ¼å¼ç‰¹æ€§å°†åœ¨æ•°æ®åŠ è½½æ—¶æ ¼å¼åŒ–æ•°æ®ï¼Œå¢žåŠ æ¢è¡Œå¹¶ç¼©è¿›ä»¥æé«˜å¯è¯»æ€§ã€‚在ä¿å­˜æ•°æ®æ—¶ï¼Œè‡ªåŠ¨æ ¼å¼ç‰¹æ€§ä¼šé€šè¿‡åˆ é™¤æ¢è¡Œã€ä¸å¿…è¦çš„ç©ºç™½å­—ç¬¦çš„æ–¹å¼æ¥ç´§å‡‘化数æ®ã€‚ + + + + Word Wrap + 自动æ¢è¡Œ + + + + Wrap lines on word boundaries + 在å•è¯è¾¹ç•Œè‡ªåЍæ¢è¡Œ + + + + + Open in default application or browser + ç”¨é»˜è®¤ç¨‹åºæˆ–æµè§ˆå™¨æ‰“å¼€ + + + + Open in application + ç”¨å¤–éƒ¨ç¨‹åºæ‰“å¼€ + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + å°†å•元格的值视为文件路径或URLï¼Œåœ¨é»˜è®¤ç¨‹åºæˆ–æµè§ˆå™¨ä¸­æ‰“开。 + + + + Save file reference... + ä¿ç•™æ–‡ä»¶å¼•用... + + + + Save reference to file + I'm not sure + 将引用ä¿å­˜åˆ°æ–‡ä»¶ + + + + + Open in external application + 在外部程åºä¸­ç¼–辑 + + + + Autoformat + è‡ªåŠ¨æ ¼å¼ + + + + &Export... + 导出(&E)... + + + + + &Import... + 导入(&I)... + + + + + Import from file + 从文件导入 + + + + + Opens a file dialog used to import any kind of data to this database cell. + æ‰“å¼€æ–‡ä»¶é€‰æ‹©å¯¹è¯æ¡†ï¼Œå¯¼å…¥ä»»ä½•类型的数æ®åˆ°æ­¤æ•°æ®åº“å•元格。 + + + + Export to file + 导出到文件 + + + + Opens a file dialog used to export the contents of this database cell to a file. + æ‰“å¼€æ–‡ä»¶é€‰æ‹©å¯¹è¯æ¡†ï¼Œå¯¼å‡ºæ­¤æ•°æ®åº“å•元格的内容到一个文件里。 + + + + Erases the contents of the cell + 删除å•元格的内容 + + + + This area displays information about the data present in this database cell + 这个区域显示存在于这个数æ®åº“å•元格中的数æ®çš„ç›¸å…³ä¿¡æ¯ + + + + Print... + 打å°... + + + + Ctrl+P + + + + + Open preview dialog for printing displayed text + 打开打å°é¢„è§ˆå¯¹è¯æ¡†ï¼Œé¢„览文本 + + + + Copy Hex and ASCII + æ‹·è´å六进制和 ASCII + + + + Copy selected hexadecimal and ASCII columns to the clipboard + æ‹·è´é€‰ä¸­çš„å六进制和 ASCII 列到剪贴æ¿ä¸­ + + + + Ctrl+Shift+C + + + + + Choose a filename to export data + 选择一个导出数æ®çš„æ–‡ä»¶å + + + + + Image data can't be viewed in this mode. + 此模å¼ä¸‹æ— æ³•æŸ¥çœ‹å›¾åƒæ•°æ®ã€‚ + + + + + Try switching to Image or Binary mode. + å°è¯•切æ¢åˆ°å›¾åƒæˆ–二进制模å¼ã€‚ + + + + + Binary data can't be viewed in this mode. + 此模å¼ä¸‹æ— æ³•查看二进制数æ®ã€‚ + + + + + Try switching to Binary mode. + å°è¯•切æ¢åˆ°äºŒè¿›åˆ¶æ¨¡å¼ã€‚ + + + + + Type: NULL; Size: 0 bytes + 类型: NULL; 大å°: 0 字节 + + + + + Type: Text / Numeric; Size: %n character(s) + + 类型: 文本 / æ•°å­—; 大å°: %n 个字符 + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + 类型: %1 图åƒ; 大å°: %2x%3 åƒç´  + + + + Type: Valid JSON; Size: %n character(s) + + 类型: 有效的 JSON; 大å°: %n 个字符 + + + + + Type: Binary; Size: %n byte(s) + + 类型: 二进制; 大å°: %n 字节 + + + + + Couldn't save file: %1. + ä¿å­˜æ–‡ä»¶å¤±è´¥ï¼š%1。 + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + æ•°æ®å·²ä¿å­˜åˆ°ä¸´æ—¶æ–‡ä»¶ï¼Œå¹¶ä½¿ç”¨é»˜è®¤åº”ç”¨ç¨‹åºæ‰“开。您现在å¯ä»¥ç¼–辑该文件,并在准备就绪åŽå°†æ–°æ•°æ®åº”用到å•å…ƒæ ¼æˆ–å–æ¶ˆæ›´æ”¹ã€‚ + + + + + Image files (%1) + å›¾åƒæ–‡ä»¶ (%1) + + + + Binary files (*.bin) + 二进制文件 (*.bin) + + + + Choose a file to import + 选择一个è¦å¯¼å…¥çš„æ–‡ä»¶ + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + 文本编辑器å…è®¸æ‚¨ç¼–è¾‘æ–‡æœ¬ï¼Œå¹¶æ”¯æŒ JSON 或 XML æ•°æ®çš„语法高亮,ä¿å­˜å‰è‡ªåŠ¨æ ¼å¼åŒ–和验è¯ã€‚ + +错误会标记红色波浪下划线。 + +求值模å¼ä¸‹ä¼šè®¡ç®—输入的 SQLite 表达å¼ï¼Œè®¡ç®—结果应用于å•元格。 + + + + Unsaved data in the cell editor + å•元格编辑器中的未ä¿å­˜æ•°æ® + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + å•元格编辑器包å«çš„æ•°æ®å°šæœªåº”用到数æ®åº“。 +是å¦å°†ç¼–辑åŽçš„æ•°æ®åº”用到 行=%1 : 列=%2? + + + + Editing row=%1, column=%2 + 编辑 行=%1 : 列=%2 + + + + No cell active. + 未选中å•元格。 + + + + %1 Image + %1 å›¾åƒ + + + + Invalid data for this mode + æ•°æ®å¯¹æ­¤æ¨¡å¼éžæ³• + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + å•元格中包å«éžæ³•çš„ %1 æ•°æ®ã€‚原因: %2. 你确实想把它应用到å•元格中å—? + + + + EditIndexDialog + + + &Name + åç§°(&N) + + + + Order + é¡ºåº + + + + &Table + 表(&T) + + + + Edit Index Schema + 编辑索引架构 + + + + &Unique + 唯一(&U) + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + 为了将索引范围é™åˆ¶åˆ°è¡¨ä¸­çš„一部分,您å¯ä»¥åœ¨æ­¤æŒ‡å®š WHERE å­å¥æ¥åœ¨è¡¨ä¸­é€‰æ‹©éœ€è¦ç´¢å¼•的部分 + + + + Partial inde&x clause + 部分索引å­å¥(&x) + + + + Colu&mns + 列(&m) + + + + Table column + 表中的列 + + + + Type + 类型 + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + å‘索引中添加一个新的表达å¼åˆ—。表达å¼åˆ—åŒ…å« SQL 表达å¼è€Œä¸æ˜¯åˆ—å。 + + + + Index column + 索引列 + + + + Deleting the old index failed: +%1 + 删除旧索引失败: +%1 + + + + Creating the index failed: +%1 + 创建索引时失败: +%1 + + + + EditTableDialog + + + Edit table definition + 编辑表定义 + + + + Table + 表 + + + + Advanced + 高级 + + + + Without Rowid + æ—  Rowid + + + + Fields + 字段 + + + + Database sche&ma + æ•°æ®åº“æž¶æž„(&M) + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + 将此表设置为 'WITHOUT ROWID' è¡¨ã€‚è®¾ç½®æ­¤æ ‡å¿—éœ€è¦æŒ‡å®šä¸€ä¸ªä¸»é”®ï¼ˆå¯ä»¥æ˜¯ä»»ä½•类型,并且å¯ä»¥æ˜¯å¤åˆçš„ï¼‰ï¼Œå¹¶ç¦æ­¢ä½¿ç”¨AUTOINCREMENT标志。 + + + + On Conflict + å†²çªæ—¶ + + + + Strict + 严格 + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + å¯ç”¨ä¸¥æ ¼é€‰é¡¹åŽï¼ŒSQLite 更新或æ’å…¥æ•°æ®æ—¶ä¼šä¸¥æ ¼æ‰§è¡Œæ¯ä¸ªåˆ—的数æ®ç±»åž‹ã€‚ + + + + + + Add + 增加 + + + + + + Remove + 删除 + + + + Move to top + 移到最上 + + + + Move up + 上移 + + + + Move down + 下移 + + + + Move to bottom + 移到最下 + + + + + + + Name + åç§° + + + + + Type + 类型 + + + + NN + éžç©º + + + + Not null + éžNULL + + + + PK + 主键 + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> 主键</p></body></html> + + + + AI + 自增 + + + + Autoincrement + 自动增值 + + + + U + 唯一 + + + + + + Unique + 唯一 + + + + Default + 默认 + + + + Default value + 默认值 + + + + + Check + 检查 + + + + Check constraint + æ£€æŸ¥çº¦æŸæ¡ä»¶ + + + + Collation + 排åºè§„则 + + + + Foreign Key + 外键 + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_fk"/> 外键</p></body></html> + + + + Index Constraints + ç´¢å¼•çº¦æŸ + + + + Add constraint + å¢žåŠ çº¦æŸ + + + + Remove constraint + åˆ é™¤çº¦æŸ + + + + + Columns + 列 + + + + + + SQL + SQL + + + + Foreign Keys + 外键 + + + + References + 引用 + + + + Check Constraints + æ£€æŸ¥çº¦æŸ + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">警告: </span>表中有一些无法解æžçš„定义。编辑并ä¿å­˜è¡¨å¯èƒ½ä¼šå¸¦æ¥é—®é¢˜ã€‚</p></body></html> + + + + + Primary Key + 主键 + + + + Add a primary key constraint + å¢žåŠ ä¸»é”®çº¦æŸ + + + + Add a unique constraint + å¢žåŠ å”¯ä¸€æ€§çº¦æŸ + + + + Error creating table. Message from database engine: +%1 + 创建表时出错。æ¥è‡ªæ•°æ®åº“引擎的消æ¯: +%1 + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + 已存在åŒå字段。请先é‡å‘½å已有字段,或为此字段选一个ä¸åŒçš„å字。 + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + æ¯ä¸ªè¡¨åªèƒ½æœ‰ä¸€ä¸ªä¸»é”®ã€‚请修改已有的主键。 + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + 此列是表 %1 的外键,因此它的åå­—ä¸èƒ½æ”¹å˜ã€‚ + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + 至少有一行带本字段的记录被设为空。这使得它ä¸å¯èƒ½è®¾ç½®è¿™ä¸ªæ ‡å¿—。请首先更改表数æ®ã€‚ + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + åœ¨è¿™ä¸ªå­—æ®µä¸­è‡³å°‘æœ‰ä¸€è¡Œå¸¦æœ‰ä¸€ä¸ªéžæ•´æ•°çš„值。这使得它ä¸å¯èƒ½è®¾ç½®è‡ªå¢žæ ‡å¿—。请首先更改表数æ®ã€‚ + + + + Column '%1' has duplicate data. + + 列 '%1' 有é‡å¤æ•°æ®ã€‚ + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + 所以无法å¯ç”¨â€œå”¯ä¸€â€æ ‡è®°ã€‚请删除é‡å¤æ•°æ®æ‰èƒ½å¯ç”¨ã€‚ + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + 您是å¦ç¡®è®¤æ‚¨æƒ³åˆ é™¤å­—段 '%1'? +当å‰å­˜å‚¨åœ¨è¿™ä¸ªå­—段中的所有数æ®å°†ä¼šä¸¢å¤±ã€‚ + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + 在设置为无 rowid å‰ï¼Œè¯·å…ˆæ·»åŠ ä¸€ä¸ªæ»¡è¶³ä»¥ä¸‹å‡†åˆ™çš„å­—æ®µ: + - 设置为主键 + - ç¦æ­¢è‡ªå¢ž + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + è®¾å®šå†²çªæ“作å‰ï¼Œè¯·æ·»åŠ æ»¡è¶³ä¸‹åˆ—æ¡ä»¶çš„字段: + - è®¾å®šâ€œä¸»é”®â€æ ‡å¿— + + + + ExportDataDialog + + + Export data as CSV + 导出数æ®ä¸º CSV + + + + Tab&le(s) + 表(&l) + + + + Colu&mn names in first line + 第一行列å(&m) + + + + Fie&ld separator + 字段分隔符(&l) + + + + , + , + + + + ; + ; + + + + Tab + Tab + + + + | + | + + + + + + Other + 其它 + + + + &Quote character + 引å·(&Q) + + + + " + " + + + + ' + ' + + + + New line characters + æ¢è¡Œç¬¦ + + + + Windows: CR+LF (\r\n) + Windows: 回车+æ¢è¡Œ (\r\n) + + + + Unix: LF (\n) + Unix: æ¢è¡Œ (\n) + + + + Pretty print + 美化输出 + + + + + Could not open output file: %1 + 打ä¸å¼€è¾“出文件: %1 + + + + + Choose a filename to export data + 选择导出数æ®çš„æ–‡ä»¶å + + + + Export data as JSON + 导出为 JSON + + + + exporting CSV + 导出 CSV + + + + + Error while writing the file '%1': %2 + 写入文件 '%1' 出错:%2 + + + + exporting JSON + 导出 JSON + + + + Please select at least 1 table. + 请选择至少1个表。 + + + + Choose a directory + 选择一个目录 + + + + Export completed. + 导出完æˆã€‚ + + + + Export finished with errors. + 导出完æˆï¼Œä½†æœ‰é”™è¯¯ã€‚ + + + + ExportSqlDialog + + + Export SQL... + 导出 SQL... + + + + Tab&le(s) + 表(&L) + + + + Select All + 全选 + + + + Deselect All + å…¨ä¸é€‰ + + + + &Options + 选项(&O) + + + + Keep column names in INSERT INTO + 在 INSERT INTO 语å¥ä¸­ä¿ç•™åˆ—å + + + + Multiple rows (VALUES) per INSERT statement + æ¯æ¡ INSERT 语å¥ä¸­åŒ…å«å¤šè¡Œ (VALUES) + + + + Export everything + 导出所有 + + + + Export schema only + 仅导出架构 + + + + Export data only + ä»…å¯¼å‡ºæ•°æ® + + + + Keep original CREATE statements + ä¿ç•™åŽŸå§‹ CREATE è¯­å¥ + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + ä¿æŒæ—§æž¶æž„ (CREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + 覆盖旧架构 (DROP TABLE, ç„¶åŽ CREATE TABLE) + + + + Please select at least one table. + 请至少选一个表。 + + + + Choose a filename to export + 选择è¦å¯¼å‡ºçš„æ–‡ä»¶å + + + + Export completed. + 导出完æˆã€‚ + + + + Export cancelled or failed. + å¯¼å‡ºè¢«å–æ¶ˆæˆ–失败。 + + + + ExtendedScintilla + + + + Ctrl+H + + + + + Ctrl+F + + + + + + Ctrl+P + + + + + Find... + 查找... + + + + Find and Replace... + 查找并替æ¢... + + + + Print... + 打å°... + + + + ExtendedTableWidget + + + Use as Exact Filter + 用于精确过滤 + + + + Containing + åŒ…å« + + + + Not containing + ä¸åŒ…å« + + + + Not equal to + ä¸ç­‰äºŽ + + + + Greater than + 大于 + + + + Less than + å°äºŽ + + + + Greater or equal + 大于等于 + + + + Less or equal + å°äºŽç­‰äºŽ + + + + Between this and... + 在此值和...之间 + + + + Regular expression + æ­£åˆ™è¡¨è¾¾å¼ + + + + Edit Conditional Formats... + 编辑æ¡ä»¶æ ¼å¼... + + + + Set to NULL + 设置为 NULL + + + + Cut + 剪切 + + + + Copy + å¤åˆ¶ + + + + Copy with Headers + å¤åˆ¶ï¼ˆå¸¦è¡¨å¤´ï¼‰ + + + + Copy as SQL + å¤åˆ¶ä¸º SQL + + + + Paste + 粘贴 + + + + Print... + 打å°... + + + + Use in Filter Expression + 在过滤器表达å¼ä¸­ä½¿ç”¨ + + + + Alt+Del + + + + + Ctrl+Shift+C + + + + + Ctrl+Alt+C + + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + 剪贴æ¿ä¸­çš„æ•°æ®èŒƒå›´è¶…过了选择的范围。 +是å¦ä»è¦æ’入? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>éƒ¨åˆ†æ•°æ®æ²¡æœ‰è¢«åŠ è½½ã€‚<b>åœ¨é€‰æ‹©æ‰€æœ‰è¡Œä¹‹å‰æ˜¯å¦è¦åŠ è½½æ‰€æœ‰æ•°æ®ï¼Ÿ</b><p><p>选择<b>å¦</b>表示ä¸åŠ è½½æ•°æ®å¹¶æ”¾å¼ƒå…¨é€‰ã€‚<br/>选择<b>是</b>表示加载所有数æ®ï¼ˆå¯èƒ½èŠ±è´¹ä¸€äº›æ—¶é—´ï¼‰å¹¶è¿›è¡Œå…¨é€‰ã€‚</p>警告:加载所有数æ®å¯¹äºŽå¤§è¡¨æ ¼å¯èƒ½å ç”¨å¤§é‡å†…存。 + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + ä¸èƒ½å°†å½“å‰å•元格设置为 NULL。列 %1 有 NOT NULL 约æŸã€‚ + + + + FileExtensionManager + + + File Extension Manager + 文件扩展å管ç†å™¨ + + + + &Up + 上(&U) + + + + &Down + 下(&D) + + + + &Add + 添加(&A) + + + + &Remove + 删除(&R) + + + + + Description + æè¿° + + + + Extensions + 扩展å + + + + *.extension + *.扩展å + + + + FilterLineEdit + + + Filter + 过滤 + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + è¿™äº›è¾“å…¥æ¡†èƒ½è®©ä½ å¿«é€Ÿåœ¨å½“å‰æ‰€é€‰è¡¨ä¸­è¿›è¡Œè¿‡æ»¤ã€‚ +默认情况下,包å«è¾“入文本的行会被过滤出æ¥ã€‚ +以下æ“作也支æŒ: +% 通é…符 +> 大于 +< å°äºŽ +>= 大于等于 +<= å°äºŽç­‰äºŽ += 等于: ç²¾ç¡®åŒ¹é… +<> ä¸ç­‰äºŽ: 精确åå‘åŒ¹é… +x~y 范围: 值在 x å’Œ y 之间 +/regexp/ å€¼ç¬¦åˆæ­£åˆ™è¡¨è¾¾å¼ + + + + Clear All Conditional Formats + 清除所有æ¡ä»¶æ ¼å¼ + + + + Use for Conditional Format + 用于æ¡ä»¶æ ¼å¼ + + + + Edit Conditional Formats... + 编辑æ¡ä»¶æ ¼å¼... + + + + Set Filter Expression + è®¾ç½®è¿‡æ»¤è¡¨è¾¾å¼ + + + + What's This? + 这是什么? + + + + Is NULL + 为 NULL + + + + Is not NULL + éž NULL + + + + Is empty + 为空 + + + + Is not empty + éžç©º + + + + Not containing... + ä¸åŒ…å«... + + + + Equal to... + 等于... + + + + Not equal to... + ä¸ç­‰äºŽ... + + + + Greater than... + 大于... + + + + Less than... + å°äºŽ... + + + + Greater or equal... + 大于等于... + + + + Less or equal... + å°äºŽç­‰äºŽ... + + + + In range... + 在范围内... + + + + Regular expression... + 正则表达å¼... + + + + FindReplaceDialog + + + Find and Replace + æŸ¥æ‰¾å¹¶æ›¿æ¢ + + + + Fi&nd text: + 查找文本(&N): + + + + Re&place with: + 替æ¢ä¸º(&P): + + + + Match &exact case + 精确匹é…(&E) + + + + Match &only whole words + 全字匹é…(&O) + + + + When enabled, the search continues from the other end when it reaches one end of the page + 如果å¯ç”¨ï¼Œæœç´¢åˆ°æœ«ç«¯æ—¶ï¼Œæœç´¢ç»§ç»­ä»Žå¦ä¸€ç«¯å¼€å§‹ + + + + &Wrap around + 循环查找(&W) + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + 如果å¯ç”¨ï¼Œæœç´¢ä»Žå½“å‰å…‰æ ‡ä½ç½®å‘å‰ã€‚未å¯ç”¨æ—¶å‘åŽ + + + + Search &backwards + å呿Ÿ¥æ‰¾(&B) + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>选中时,åªåœ¨å½“å‰é€‰æ‹©çš„内容中进行æœç´¢ã€‚</p></body></html> + + + + &Selection only + 在所选内容中查找(&S) + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>é€‰ä¸­æ—¶ï¼Œè¦æŸ¥æ‰¾çš„æ¨¡å¼è¢«è§£é‡Šä¸º UNIX 正则表达å¼ã€‚å‚阅 <a href="https://en.wikibooks.org/wiki/Regular_Expressions"> Wikibooks 中的正则表达å¼</a>.</p></body></html> + + + + Use regular e&xpressions + 使用正则表达å¼(&X) + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + 从当å‰ä½ç½®å¼€å§‹æŸ¥æ‰¾ä¸‹ä¸€æ¬¡å‡ºçŽ°çš„ä½ç½®ã€‚查找方å‘éµå¾ªâ€œå呿Ÿ¥æ‰¾â€çš„è®¾ç½®çŠ¶æ€ + + + + &Find Next + 查找下一个(&F) + + + + F3 + + + + + &Replace + 替æ¢(&R) + + + + Highlight all the occurrences of the text in the page + 高亮本页中所有出现的文本 + + + + F&ind All + 全部高亮(&I) + + + + Replace all the occurrences of the text in the page + æ›¿æ¢æœ¬é¡µä¸­æ‰€æœ‰å‡ºçŽ°çš„æ–‡æœ¬ + + + + Replace &All + 全部替æ¢(&A) + + + + The searched text was not found + æ— æ³•æ‰¾åˆ°è¦æŸ¥æ‰¾çš„æ–‡æœ¬ + + + + The searched text was not found. + æ— æ³•æ‰¾åˆ°è¦æŸ¥æ‰¾çš„æ–‡æœ¬ã€‚ + + + + The searched text was found one time. + 查找的文本被找到了 1 次。 + + + + The searched text was found %1 times. + 查找的文本被找到了 %1 次。 + + + + The searched text was replaced one time. + 查找的文本被替æ¢äº† 1 次。 + + + + The searched text was replaced %1 times. + 查找的文本被替æ¢äº† %1 次。 + + + + ForeignKeyEditor + + + &Reset + é‡ç½®(&R) + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + 外键å­å¥ (ON UPDATE, ON DELETE 等等) + + + + ImageViewer + + + Image Viewer + å›¾åƒæŸ¥çœ‹å™¨ + + + + Reset the scaling to match the original size of the image. + é‡ç½®ç¼©æ”¾æ¯”例以匹é…图åƒçš„原始尺寸。 + + + + Set the scaling to match the size of the viewport. + 设定缩放比例以匹é…视界的大å°ã€‚ + + + + Print... + 打å°... + + + + Open preview dialog for printing displayed image + 打开“打å°é¢„览â€å¯¹è¯æ¡†ä»¥æ‰“å°æ˜¾ç¤ºçš„å›¾åƒ + + + + Ctrl+P + Ctrl+P + + + + ImportCsvDialog + + + Import CSV file + 导入 CSV 文件 + + + + Table na&me + 表åç§°(&M) + + + + &Column names in first line + 列å在首行(&C) + + + + Field &separator + 字段分隔符(&S) + + + + , + , + + + + ; + ; + + + + + Tab + Tab + + + + | + ; + + + + Other + 其它 + + + + &Quote character + 引å·(&Q) + + + + + Other (printable) + å…¶ä»–(坿‰“å°) + + + + + Other (code) + å…¶ä»–(代ç ) + + + + " + " + + + + ' + ' + + + + &Encoding + ç¼–ç (&E) + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Trim fields? + 删除字段头尾空白? + + + + Separate tables + 分离表 + + + + Advanced + 高级 + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + 当从 CSV 文件导入空值到已有表中,并且该列有默认值时,默认值会被æ’å…¥ã€‚é€‰ä¸­æ­¤é¡¹ä»¥åœ¨è¿™ç§æƒ…况下æ’入空值。 + + + + Ignore default &values + 忽略默认值(&V) + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + é€‰ä¸­æ­¤é¡¹ä»¥åœ¨å¾€æ²¡æœ‰é»˜è®¤å€¼çš„éž NULL 列导入空值时终止导入。 + + + + Fail on missing values + 缺值时失败 + + + + Disable data type detection + ç¦ç”¨ç±»åž‹æ£€æµ‹ + + + + Disable the automatic data type detection when creating a new table. + ç¦æ­¢åœ¨åˆ›å»ºæ–°è¡¨æ—¶è‡ªåŠ¨æ£€æµ‹æ•°æ®ç±»åž‹ã€‚ + + + + Use local number conventions + 使用本地数字习俗 + + + + Use decimal and thousands separators according to the system locale. + ä½¿ç”¨ç³»ç»ŸåŒºåŸŸè®¾ç½®ä¸­å®šä¹‰çš„å°æ•°ç‚¹å’Œåƒä½åˆ†éš”符。 + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + 当呿œ‰ä¸»é”®çš„è¡¨ä¸­å¯¼å…¥æ•°æ®æ—¶ï¼Œå¯èƒ½ä¼šäº§ç”Ÿå”¯ä¸€æ€§çº¦æŸæˆ–索引的冲çªã€‚此选项å…许你选择处ç†å†²çªçš„ç­–ç•¥ï¼šé»˜è®¤æƒ…å†µä¸‹ä¼šå–æ¶ˆå¯¼å…¥å¹¶å·å›žï¼Œä¹Ÿå¯ä»¥é€‰æ‹©å¿½ç•¥å¹¶è·³è¿‡å†²çªçš„行,或替æ¢è¡¨ä¸­çŽ°æœ‰çš„è¡Œã€‚ + + + + Abort import + å–æ¶ˆå¯¼å…¥ + + + + Ignore row + 忽略冲çªçš„行 + + + + Replace existing row + 替æ¢çŽ°æœ‰çš„è¡Œ + + + + Conflict strategy + 冲çªç­–ç•¥ + + + + + Deselect All + å…¨ä¸é€‰ + + + + Match Similar + 匹é…相似 + + + + Select All + 全选 + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + å·²ç»æœ‰ä¸€å¼ å«åš '%1' çš„è¡¨ã€‚åªæœ‰åˆ—æ•°åŒ¹é…æ—¶ï¼Œæ‰èƒ½å¯¼å…¥åˆ°å·²ç»å­˜åœ¨çš„表中。 + + + + There is already a table named '%1'. Do you want to import the data into it? + å·²ç»æœ‰ä¸€å¼ å«åš '%1' 的表。你想把数æ®å¯¼å…¥åˆ°æ­¤è¡¨ä¸­å—? + + + + Creating restore point failed: %1 + 创建还原点失败: %1 + + + + Creating the table failed: %1 + 创建表失败: %1 + + + + importing CSV + 导入 CSV + + + + Could not prepare INSERT statement: %1 + 无法准备 INSERT 语å¥: %1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + æ„外的文件结æŸã€‚请确认已正确é…置引å·å­—符,并确认文件没有格å¼é”™è¯¯ã€‚ + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + 导入文件 '%1' 用时 %2ms. 其中 %3ms 用在行方程上。 + + + + Inserting row failed: %1 + æ’入行失败: %1 + + + + MainWindow + + + DB Browser for SQLite + DB Browser for SQLite + + + + toolBar1 + 工具æ 1 + + + + &Wiki + 百科(&W) + + + + Bug &Report... + Bug 上报(&R)... + + + + Feature Re&quest... + 特性请求(&Q)... + + + + Web&site + 网站(&S) + + + + &Donate on Patreon... + 在 Patreon 上æèµ (&D)... + + + + Open &Project... + 打开项目(&P)... + + + + &Attach Database... + 附加数æ®åº“(&A)... + + + + + Add another database file to the current database connection + 添加å¦ä¸€ä¸ªæ•°æ®åº“到当å‰çš„æ•°æ®åº“连接中 + + + + This button lets you add another database file to the current database connection + 此按钮能添加å¦ä¸€ä¸ªæ•°æ®åº“到当å‰çš„æ•°æ®åº“连接中 + + + + &Set Encryption... + 设置加密(&S)... + + + + This button saves the content of the current SQL editor tab to a file + æ­¤æŒ‰é’®æŠŠå½“å‰ SQL 编辑器页的内容ä¿å­˜åˆ°ä¸€ä¸ªæ–‡ä»¶ + + + + SQLCipher &FAQ + SQLCipher 常è§é—®é¢˜(&F) + + + + Table(&s) to JSON... + 表到 JSON (&S)... + + + + Export one or more table(s) to a JSON file + 导出一个或多个表到 JSON 文件 + + + + Un/comment block of SQL code + 注释/å–æ¶ˆæ³¨é‡Š SQL ä»£ç  + + + + Un/comment block + 注释/å–æ¶ˆæ³¨é‡Š + + + + Comment or uncomment current line or selected block of code + 注释/å–æ¶ˆæ³¨é‡Šå½“å‰è¡Œæˆ–é€‰ä¸­çš„ä»£ç æ®µ + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + 注释/å–æ¶ˆæ³¨é‡Šé€‰ä¸­çš„ä»£ç æ®µï¼Œæ²¡æœ‰é€‰ä¸­æ—¶ä¸ºå½“å‰è¡Œã€‚ä»£ç æ®µçš„æ³¨é‡Šçжæ€ç”±ç¬¬ä¸€è¡Œå†³å®šã€‚ + + + + Ctrl+/ + + + + + Stop SQL execution + åœæ­¢ SQL 执行 + + + + Stop execution + åœæ­¢æ‰§è¡Œ + + + + Stop the currently running SQL script + åœæ­¢å½“å‰è¿è¡Œçš„ SQL 脚本 + + + + &File + 文件(&F) + + + + &Import + 导入(&I) + + + + &Export + 导出(&E) + + + + &Edit + 编辑(&E) + + + + &View + 查看(&V) + + + + &Help + 帮助(&H) + + + + &Remote + 远程(&R) + + + + Execute all/selected SQL + 执行所有/选中的 SQL + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + 此按钮执行当å‰é€‰ä¸­çš„ SQL 语å¥ã€‚如果没有选中文本,就执行所有的 SQL 语å¥ã€‚ + + + + &Load Extension... + 加载扩展(&L)... + + + + This button executes the SQL statement present in the current editor line + 此按钮执行编辑器当å‰è¡Œä¸­çš„ SQL è¯­å¥ + + + + Shift+F5 + + + + + Sa&ve Project + ä¿å­˜é¡¹ç›®(&V) + + + + + Save SQL file as + SQL 文件å¦å­˜ä¸º + + + + &Browse Table + æµè§ˆè¡¨(&B) + + + + Copy Create statement + å¤åˆ¶ Create è¯­å¥ + + + + Copy the CREATE statement of the item to the clipboard + å¤åˆ¶é€‰ä¸­é¡¹çš„ CREATE 语å¥åˆ°å‰ªè´´æ¿ + + + + Open an existing database file in read only mode + 用åªè¯»æ–¹å¼æ‰“开一个已有的数æ®åº“文件 + + + + Opens the SQLCipher FAQ in a browser window + 用æµè§ˆå™¨çª—壿‰“å¼€ SQLCipher 常è§é—®é¢˜ + + + + User + 用户 + + + + Application + åº”ç”¨ç¨‹åº + + + + &Clear + 清除(&C) + + + + DB Sche&ma + æ•°æ®åº“æž¶æž„(&M) + + + + &New Database... + 新建数æ®åº“(&N)... + + + + + Create a new database file + 创建一个新的数æ®åº“文件 + + + + This option is used to create a new database file. + 这个选项用于创建一个新的数æ®åº“文件。 + + + + Ctrl+N + + + + + + &Open Database... + 打开数æ®åº“(&O)... + + + + + + + + Open an existing database file + 打开一个现有的数æ®åº“文件 + + + + + + This option is used to open an existing database file. + 这个选项用于打开一个现有的数æ®åº“文件。 + + + + Ctrl+O + + + + + &Close Database + 关闭数æ®åº“(&C) + + + + + Ctrl+W + + + + + + Revert database to last saved state + 把数æ®åº“会退到先å‰ä¿å­˜çš„çŠ¶æ€ + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + 这个选项用于倒退当å‰çš„æ•°æ®åº“文件为它最åŽçš„ä¿å­˜çжæ€ã€‚从最åŽä¿å­˜æ“作开始åšå‡ºçš„æ‰€æœ‰æ›´æ”¹å°†ä¼šä¸¢å¤±ã€‚ + + + + + Write changes to the database file + 把更改写入到数æ®åº“文件 + + + + This option is used to save changes to the database file. + 这个选项用于ä¿å­˜æ›´æ”¹åˆ°æ•°æ®åº“文件。 + + + + Ctrl+S + + + + + Compact &Database... + 压缩数æ®åº“(&D)... + + + + Compact the database file, removing space wasted by deleted records + 压缩数æ®åº“文件,去除已删除记录所å ç”¨çš„空间 + + + + + Compact the database file, removing space wasted by deleted records. + 压缩数æ®åº“文件,去除已删除记录所å ç”¨çš„空间。 + + + + E&xit + 退出(&X) + + + + Ctrl+Q + + + + + Import data from an .sql dump text file into a new or existing database. + 从一个 .sql 转储文本文件中导入数æ®åˆ°ä¸€ä¸ªæ–°çš„æˆ–已有的数æ®åº“。 + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + 这个选项让你从一个 .sql 转储文本文件中导入数æ®åˆ°ä¸€ä¸ªæ–°çš„æˆ–现有的数æ®åº“。SQL 转储文件å¯ä»¥åœ¨å¤§å¤šæ•°æ•°æ®åº“引擎上创建,包括 MySQL å’Œ PostgreSQL。 + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + 打开一个å‘导让您从一个逗å·é—´éš”的文本文件导入数æ®åˆ°ä¸€ä¸ªæ•°æ®åº“表中。 + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + 打开一个å‘导让您从一个逗å·é—´éš”的文本文件导入数æ®åˆ°ä¸€ä¸ªæ•°æ®åº“表中。CSV 文件å¯ä»¥åœ¨å¤§å¤šæ•°æ•°æ®åº“和电å­è¡¨æ ¼åº”用程åºä¸Šåˆ›å»ºã€‚ + + + + Export a database to a .sql dump text file. + 导出一个数æ®åº“导一个 .sql 转储文本文件。 + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + 这个选项让你导出一个数æ®åº“导一个 .sql 转储文本文件。SQL 转储文件包å«åœ¨å¤§å¤šæ•°æ•°æ®åº“引擎上(包括 MySQL å’Œ PostgreSQL)釿–°åˆ›å»ºæ•°æ®åº“所需的所有数æ®ã€‚ + + + + Export a database table as a comma separated text file. + 导出一个数æ®åº“表为逗å·é—´éš”的文本文件。 + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + 导出一个数æ®åº“表为逗å·é—´éš”的文本文件,准备好被导入到其他数æ®åº“或电å­è¡¨æ ¼åº”用程åºã€‚ + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + 打开“创建表â€å‘导,在那里å¯ä»¥å®šä¹‰åœ¨æ•°æ®åº“中的一个新表的å称和字段 + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + 打开“删除表â€å‘导,在那里你å¯ä»¥é€‰æ‹©è¦ä¸¢å¼ƒçš„一个数æ®åº“表。 + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + 打开“创建索引â€å‘导,在那里å¯ä»¥åœ¨ä¸€ä¸ªçŽ°æœ‰çš„æ•°æ®åº“表上定义一个新索引。 + + + + &Preferences... + 首选项(&P)... + + + + + Open the preferences window. + 打开首选项窗å£ã€‚ + + + + &DB Toolbar + æ•°æ®åº“工具æ (&D) + + + + Shows or hides the Database toolbar. + 显示或éšè—æ•°æ®åº“工具æ ã€‚ + + + + Shift+F1 + + + + + &Recently opened + 最近打开(&R) + + + + Ctrl+T + + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + 这是打开的数æ®åº“的结构。 +ä½ å¯ä»¥ä»Žä¸€ä¸ªå¯¹è±¡è¡Œä¸­æ‹–动 SQL 语å¥ï¼Œç„¶åŽæ‹–到其他应用中,或者拖到其他 'DB Browser for SQLite' 的实例中。 + + + + + Temp Store + 临时存储 + + + + Secure Delete + 安全删除 + + + + Case Sensitive Like + 区分大å°å†™ + + + + Journal Mode + æ—¥å¿—æ¨¡å¼ + + + + Journal Size Limit + 日志大å°é™åˆ¶ + + + + Recursive Triggers + 递归触å‘器 + + + + Page Size + 页é¢å¤§å° + + + + Foreign Keys + 外键 + + + + Auto Vacuum + è‡ªåŠ¨æ¸…ç† + + + + Max Page Count + 最大页é¢è®¡æ•° + + + + Checkpoint Full FSYNC + 检查点完全 fsync + + + + + Off + 关闭 + + + + + Normal + 普通 + + + + + Full + 完全 + + + + Default + 默认 + + + + File + 文件 + + + + + Memory + 内存 + + + + Delete + 删除 + + + + Truncate + 截断 + + + + Persist + æŒä¹…化 + + + + WAL + WAL + + + + Exclusive + ç‹¬å  + + + + Automatic Index + 自动索引 + + + + Ignore Check Constraints + å¿½ç•¥æ£€æŸ¥çº¦æŸ + + + + Full FSYNC + 完全 FSYNC + + + + WAL Auto Checkpoint + WAL 自动检查点 + + + + User Version + 用户版本 + + + + Synchronous + åŒæ­¥ + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + 警告: æ­¤æ‚æ³¨æ— æ³•读å–ï¼Œæ­¤å€¼ä¸ºæŽ¨æ–­å¾—åˆ°ã€‚ç¼–è¾‘æ‚æ³¨å¯èƒ½ä¼šè¦†ç›–ç”± SQLite 扩展é‡å®šä¹‰çš„ LIKE。 + + + + None + æ—  + + + + Incremental + å¢žé‡ + + + + Locking Mode + é”å®šæ¨¡å¼ + + + + Too&ls + 工具(&T) + + + + DB Toolbar + æ•°æ®åº“å·¥å…·æ  + + + + Edit Database &Cell + 编辑数æ®åº“å•元格(&C) + + + + SQL &Log + SQL 日志(&L) + + + + Show S&QL submitted by + 显示 SQL æäº¤è‡ª(&Q) + + + + Error Log + 错误记录 + + + + This button clears the contents of the SQL logs + 此按钮清除 SQL 日志的内容 + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + æ­¤é¢æ¿å¯ä»¥è®©ä½ è‡ªè¡Œæ£€æŸ¥æœ¬åº”ç”¨ç¨‹åºæ‰§è¡Œçš„æ‰€æœ‰ SQL 命令的日志 + + + + &Plot + 图表(&P) + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + 这是已打开数æ®åº“的结构。 +ä½ å¯ä»¥ä»Žå字列拖拽多个对象å称到 SQL 编辑器中,并å¯ä»¥ç”¨å³é”®èœå•调节所拖拽å称的属性。这å¯ä»¥å¸®åŠ©ä½ ç¼–å†™ SQL 语å¥ã€‚ +ä½ å¯ä»¥ä»Žæž¶æž„列拖拽 SQL 语å¥åˆ° SQL 编辑器或其他的应用程åºã€‚ + + + + + Project Toolbar + é¡¹ç›®å·¥å…·æ  + + + + Extra DB toolbar + å…¶ä»–æ•°æ®åº“å·¥å…·æ  + + + + + + Close the current database file + 关闭当剿•°æ®åº“文件 + + + + &New Database + 新建数æ®åº“(&N) + + + + This button closes the connection to the currently open database file + æ­¤æŒ‰é’®å…³é—­åˆ°å½“å‰æ‰“开的数æ®åº“文件的连接 + + + + + Ctrl+F4 + + + + + &Revert Changes + 倒退更改(&R) + + + + &Undo + 撤销(&U) + + + + + Undo last change to the database + 撤销对数æ®åº“çš„æœ€åŽæ›´æ”¹ + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + æ­¤æ“作将撤销上一次在数æ®åº“æµè§ˆå™¨æˆ– SQL 执行中对数æ®åº“所执行的更改。ä¸èƒ½æ’¤é”€ï¼ˆé‡åšï¼‰æœ¬æ¬¡æ’¤é”€ã€‚ + + + + &Write Changes + 写入更改(&W) + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + 打开修改表å‘导,å¯ä»¥åœ¨é‡Œé¢é‡å‘½å现有表,添加或删除字段,修改字段å称和类型。 + + + + New &tab + 新建标签页(&T) + + + + Open SQL file(s) + 打开 SQL 文件 + + + + This button opens files containing SQL statements and loads them in new editor tabs + æ­¤æŒ‰é’®å¯æ‰“å¼€åŒ…å« SQL 语å¥çš„一个或多个文件,将它们加载到新的编辑器标签页中 + + + + Ctrl+Shift+T + Ctrl+Shift+T + + + + Execute line + 执行行 + + + + F1 + + + + + &Save Project + ä¿å­˜é¡¹ç›®(&S) + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + 此按钮å…许你将与已打开的数æ®åº“相关è”的所有设置ä¿å­˜åˆ°ä¸€ä¸ªæœ¬è½¯ä»¶å¯ç”¨çš„项目文件中 + + + + Open &Project + 打开项目(&P) + + + + This button lets you open a DB Browser for SQLite project file + 此按钮å…许你打开一个 DB Browser for SQLite 的项目文件 + + + + Open Data&base Read Only... + åªè¯»æ‰“开数æ®åº“(&B)... + + + + Ctrl+Shift+O + + + + + Save results + ä¿å­˜ç»“æžœ + + + + Save the results view + ä¿å­˜ç»“果视图 + + + + This button lets you save the results of the last executed query + 此按钮让你ä¿å­˜ä¸Šæ¬¡æ‰§è¡Œçš„æŸ¥è¯¢çš„结果 + + + + + Find text in SQL editor + 在 SQL 编辑器中查找文本 + + + + Find + 查找 + + + + This button opens the search bar of the editor + æ­¤æŒ‰é’®æ‰“å¼€ç¼–è¾‘å™¨çš„æŸ¥æ‰¾æ  + + + + Ctrl+F + + + + + + Find or replace text in SQL editor + 在 SQL ç¼–è¾‘å™¨ä¸­æŸ¥æ‰¾æˆ–æ›¿æ¢æ–‡æœ¬ + + + + Find or replace + æŸ¥æ‰¾æˆ–æ›¿æ¢ + + + + This button opens the find/replace dialog for the current editor tab + 此按钮为当å‰çš„编辑器标签页打开查找/替æ¢å¯¹è¯æ¡† + + + + Ctrl+H + + + + + Export to &CSV + 导出到 &CSV + + + + Export to &JSON + 导出到 &JSON + + + + Save as &view + ä¿å­˜ä¸ºè§†å›¾(&V) + + + + Save as view + ä¿å­˜ä¸ºè§†å›¾ + + + + &Open Database + 打开数æ®åº“(&O) + + + + Drag && Drop SELECT Query + 拖放 SELECT 查询(&&) + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + 在åŒä¸€ä¸ªæˆ–å•ä¸ªè¡¨ä¸­æ‹–æ‹½å­—æ®µï¼Œé‡Šæ”¾æ—¶å°†ä¸€æ¡ SELECT 查询æ’入编辑器 + + + + Browse Table + æµè§ˆè¡¨ + + + + Close Pro&ject + 关闭项目(&J) + + + + + Close project and database files and return to the initial state + 关闭项目和数æ®åº“文件并返回åˆå§‹çŠ¶æ€ + + + + + Ctrl+Shift+W + Ctrl+Shift+W + + + + Table from CSV data in Clipboard... + 剪贴æ¿ä¸­ CSV 的数æ®åˆ¶è¡¨... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + 这会将剪贴æ¿å†…容视作 CSV 文件,打开从文件导入 CSV æ•°æ®çš„å‘导æ¥å¤„ç†å®ƒã€‚ + + + + Show &Row Counts + 显示行数(&R) + + + + This shows the number of rows for each table and view in the database. + 显示数æ®åº“中æ¯ä¸ªè¡¨å’Œè§†å›¾çš„行数。 + + + + Save Database &As... + å¦å­˜ä¸ºæ•°æ®åº“(&A)... + + + + Save the current database as a different file + 将当剿•°æ®åº“ä¿å­˜åˆ°å¦ä¸€ä¸ªæ–‡ä»¶ + + + + Refresh + 刷新 + + + + Reload the database structure + 釿–°è½½å…¥æ•°æ®åº“结构 + + + + Ctrl+Shift+F4 + Ctrl+Shift+F4 + + + + + Detach Database + 断开数æ®åº“ + + + + + Detach database file attached to the current database connection + æ–­å¼€å·²é™„åŠ åˆ°å½“å‰æ•°æ®åº“连接的数æ®åº“文件 + + + + Shows or hides the Project toolbar. + 显示或éšè—项目工具æ ã€‚ + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + æ•°æ®åº“结构(&D) + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + æµè§ˆæ•°æ®(&B) + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + ç¼–è¾‘æ‚æ³¨(&R) + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + 执行 SQL(&X) + + + + &Recent Files + 最近的文件(&R) + + + + Extra DB Toolbar + å…¶ä»–æ•°æ®åº“å·¥å…·æ  + + + + New In-&Memory Database + 新建内存数æ®åº“(&M) + + + + Drag && Drop Qualified Names + 拖拽é™å®šåç§° + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + 当拖拽对象到编辑器中时,使用é™å®šåç§° (例如 "Table"."Field") + + + + Drag && Drop Enquoted Names + 拖拽引用åå­— + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + 当拖拽对象到编辑器中时,使用转义的标识符 (例如 "Table1") + + + + &Integrity Check + 完全性检查(&I) + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + 对打开的数æ®åº“è¿è¡Œ integrity_check æ‚æ³¨å¹¶åœ¨æ‰§è¡Œ SQL æ ‡ç­¾é¡µè¿”å›žç»“æžœã€‚æ­¤æ‚æ³¨å¯¹æ•´ä¸ªæ•°æ®åº“进行完全性检查。 + + + + &Foreign-Key Check + 外键检查(&F) + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + 对打开的数æ®åº“è¿è¡Œ foreign_key_check æ‚æ³¨å¹¶åœ¨â€œæ‰§è¡Œ SQLâ€æ ‡ç­¾é¡µä¸­è¿”回结果 + + + + &Quick Integrity Check + 快速完全性检查(&Q) + + + + Run a quick integrity check over the open DB + 对打开的数æ®åº“执行快速完全性检查 + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + 对打开的数æ®åº“è¿è¡Œ quick_check æ‚æ³¨å¹¶åœ¨æ‰§è¡Œ SQL 标签页返回结果。此命令会执行 integrity_check 的多数检查,但是è¦å¿«å¾—多。 + + + + &Optimize + 优化(&O) + + + + Attempt to optimize the database + å°è¯•优化数æ®åº“ + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + 对打开的数æ®åº“è¿è¡Œ optimize æ‚æ³¨ã€‚å¯èƒ½ä¼šæ‰§è¡Œå¯¹æœªæ¥æŸ¥è¯¢æ€§èƒ½æœ‰å¸®åŠ©çš„ä¼˜åŒ–ã€‚ + + + + + Print + æ‰“å° + + + + Print text from current SQL editor tab + 从当å‰çš„ SQL ç¼–è¾‘å™¨æ ‡ç­¾é¡µæ‰“å°æ–‡æœ¬ + + + + Open a dialog for printing the text in the current SQL editor tab + æ‰“å¼€å¯¹è¯æ¡†ä»¥ä»Žå½“å‰çš„ SQL ç¼–è¾‘å™¨æ ‡ç­¾é¡µæ‰“å°æ–‡ + + + + Print the structure of the opened database + 打å°å½“剿‰“开的数æ®åº“的结构 + + + + Open a dialog for printing the structure of the opened database + æ‰“å¼€å¯¹è¯æ¡†ä»¥æ‰“å°å½“剿‰“开的数æ®åº“的结构 + + + + &Save Project As... + å¦å­˜ä¸ºé¡¹ç›®(&S)... + + + + + + Save the project in a file selected in a dialog + 将项目ä¿å­˜ä¸ºæ–‡ä»¶ + + + + Save A&ll + 全部ä¿å­˜(&L) + + + + + + Save DB file, project file and opened SQL files + ä¿å­˜æ•°æ®åº“文件ã€é¡¹ç›®æ–‡ä»¶å’Œæ‰“开的 SQL 文件 + + + + Ctrl+Shift+S + + + + + &Database from SQL file... + 从 SQL 文件导入数æ®åº“(&D)... + + + + &Table from CSV file... + 从 CSV 文件导入表(&T)... + + + + &Database to SQL file... + 导出数æ®åº“到 SQL 文件(&D)... + + + + &Table(s) as CSV file... + 导出表到 CSV 文件(&T)... + + + + &Create Table... + 创建表(&C)... + + + + &Delete Table... + 删除表(&D)... + + + + &Modify Table... + 修改表(&M)... + + + + Create &Index... + 创建索引(&I)... + + + + W&hat's This? + 这是什么(&W)? + + + + &About + 关于(&A) + + + + This button opens a new tab for the SQL editor + 此按钮打开一个 SQL 编辑器的新标签页 + + + + &Execute SQL + 执行 SQL(&E) + + + + + Save the current session to a file + ä¿å­˜å½“å‰ä¼šè¯åˆ°ä¸€ä¸ªæ–‡ä»¶ + + + + + Load a working session from a file + ä»Žä¸€ä¸ªæ–‡ä»¶åŠ è½½å·¥ä½œä¼šè¯ + + + + + + Save SQL file + ä¿å­˜ SQL 文件 + + + + + Execute current line + 执行当å‰è¡Œ + + + + Ctrl+E + + + + + Export as CSV file + 导出为 CSV 文件 + + + + Export table as comma separated values file + 导出表为逗å·é—´éš”值文件 + + + + Ctrl+L + + + + + + Ctrl+P + + + + + Database encoding + æ•°æ®åº“ç¼–ç  + + + + + Choose a database file + 选择一个数æ®åº“文件 + + + + Ctrl+Return + + + + + Ctrl+D + + + + + Ctrl+I + + + + + Encrypted + 加密的 + + + + Database is encrypted using SQLCipher + æ•°æ®åº“使用 SQLCipher 进行了加密 + + + + Read only + åªè¯» + + + + Database file is read only. Editing the database is disabled. + æ•°æ®åº“是åªè¯»çš„ã€‚ç¼–è¾‘è¢«ç¦æ­¢ã€‚ + + + + Could not open database file. +Reason: %1 + 无法打开数æ®åº“文件。 +原因: %1 + + + + + + Choose a filename to save under + 选择一个文件åä¿å­˜ + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + è®¾ç½®æˆ–æ¸…é™¤æ‚æ³¨å€¼ä¼šæäº¤ä½ çš„当å‰äº‹åŠ¡ã€‚ +你确定å—? + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + ä¿å­˜æ•°æ®åº“æ–‡ä»¶æ—¶å‡ºé”™ã€‚è¿™è¡¨æ˜Žä¸æ˜¯æ‰€æœ‰å¯¹æ•°æ®åº“的更改都被ä¿å­˜äº†ã€‚你需è¦å…ˆè§£å†³ä»¥ä¸‹é”™è¯¯ã€‚ + +%1 + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + 有新版本的 DB Browser for SQLite (%1.%2.%3)å¯ç”¨ã€‚<br/><br/>请从 <a href='%4'>%4</a> 下载。 + + + + DB Browser for SQLite project file (*.sqbpro) + DB Browser for SQLite 项目文件 (*.sqbpro) + + + + Reset Window Layout + é‡ç½®çª—å£å¸ƒå±€ + + + + The database is currently busy. + æ•°æ®åº“正忙。 + + + + Click here to interrupt the currently running query. + 点击此处中断当å‰è¿è¡Œçš„æŸ¥è¯¢ã€‚ + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + 你正在执行SQL语å¥ã€‚关闭数æ®åº“ä¼šåœæ­¢æ‰§è¡Œï¼Œå¯èƒ½ä½¿æ•°æ®åº“处于ä¸å‡†ç¡®çš„状æ€ã€‚确实è¦å…³é—­æ•°æ®åº“å—? + + + + Do you want to save the changes made to the project file '%1'? + 是å¦è¦ä¿å­˜å¯¹é¡¹ç›®æ–‡ä»¶ '%1' 的修改? + + + + Error checking foreign keys after table modification. The changes will be reverted. + 修改表格åŽçš„外键检查错误。修改会被回退。 + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + 此表格没有通过外键检查。<br/>ä½ éœ€è¦æ‰§è¡Œ '工具 | 外键检查' å¹¶ä¿®å¤å‘现的问题。 + + + + Edit View %1 + 编辑视图 %1 + + + + Edit Trigger %1 + 编辑触å‘器 %1 + + + + + At line %1: + 在行 %1: + + + + Result: %1 + 结果: %1 + + + + Result: %2 + 结果: %2 + + + + Execution finished with errors. + 执行已完æˆï¼Œä½†æœ‰é”™è¯¯ã€‚ + + + + Execution finished without errors. + 执行完æˆï¼Œæ— é”™è¯¯ã€‚ + + + + Opened '%1' in read-only mode from recent file list + 已从最近文件列表中打开 '%1' (åªè¯»æ¨¡å¼) + + + + Opened '%1' from recent file list + 已从最近文件列表中打开 '%1' + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (åªè¯») + + + + Open Database or Project + 打开数æ®åº“或项目 + + + + Attach Database... + 附加数æ®åº“... + + + + Import CSV file(s)... + 导入CSV文件... + + + + Do you want to save the changes made to SQL tabs in a new project file? + 是å¦è¦å°†å¯¹ SQL 标签页的修改ä¿å­˜ä¸ºé¡¹ç›®æ–‡ä»¶ï¼Ÿ + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + 标签页 '%1' 中的语å¥ä»åœ¨æ‰§è¡Œã€‚å…³é—­è¯¥æ ‡ç­¾é¡µå°†åœæ­¢æ‰§è¡Œã€‚è¿™å¯èƒ½ä½¿æ•°æ®åº“处于ä¸ä¸€è‡´çжæ€ã€‚确定关闭标签页å—? + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + 此项目文件使用了 DB Browser for SQLite 3.10 或更旧版本使用的旧文件格å¼ã€‚è¿™ç§æ–‡ä»¶æ ¼å¼çš„加载已ä¸å†å……分支æŒã€‚如è¦å®Œå…¨åŠ è½½è¯¥æ–‡ä»¶ï¼Œè¯·ä½¿ç”¨ DB Browser for SQLite 3.12 版本将其转æ¢ä¸ºæ–°åž‹æ–‡ä»¶æ ¼å¼ã€‚ + + + + Yes. Don't ask again + 是,ä¸å†è¯¢é—® + + + + This action will open a new SQL tab with the following statements for you to edit and run: + æ­¤æ“作将打开一个新的 SQL 标签页,其中包å«ä»¥ä¸‹è¯­å¥ä¾›æ‚¨ç¼–辑和è¿è¡Œï¼š + + + + Rename Tab + é‡å‘½å标签 + + + + Duplicate Tab + å¤åˆ¶æ ‡ç­¾ + + + + Close Tab + 关闭标签 + + + + Opening '%1'... + 正在打开 '%1'... + + + + There was an error opening '%1'... + 打开 '%1' 时出错... + + + + Value is not a valid URL or filename: %1 + 䏿˜¯æ­£ç¡®çš„URL或文件å:%1 + + + + Do you want to save the changes made to the SQL file %1? + 是å¦è¦ä¿å­˜å¯¹SQL文件 %1 的修改? + + + + Could not find resource file: %1 + ä¸èƒ½æ‰¾åˆ°èµ„æºæ–‡ä»¶ï¼š%1 + + + + Choose a project file to open + é€‰æ‹©ä¸€ä¸ªè¦æ‰“开的项目文件 + + + + Could not open project file for writing. +Reason: %1 + 未能写入项目文件。 +原因:%1 + + + + Busy (%1) + 正忙 (%1) + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + 您是å¦ç¡®å®šæƒ³æ’¤é”€è‡ªä¸Šæ¬¡ä¿å­˜ä»¥æ¥å¯¹æ•°æ®åº“文件“%1â€æ‰€åšçš„æ‰€æœ‰æ›´æ”¹ï¼Ÿ + + + + Choose a file to import + 选择è¦å¯¼å…¥çš„一个文件 + + + + Text files(*.sql *.txt);;All files(*) + 文本文件(*.sql *.txt);;所有文件(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + 您是å¦ç¡®è®¤æ‚¨æƒ³åˆ›å»ºä¸€ä¸ªæ–°çš„æ•°æ®åº“文件用æ¥å­˜æ”¾å¯¼å…¥çš„æ•°æ®? +如果您会到“å¦â€çš„è¯ï¼Œæˆ‘们将å°è¯•导入 SQL 文件中的数æ®åˆ°å½“剿•°æ®åº“。 + + + + Ctrl+Tab + Ctrl+Tab + + + + Ctrl+Shift+Tab + Ctrl+Shift+Tab + + + + Clear List + 清除列表 + + + + Window Layout + 窗å£å¸ƒå±€ + + + + Simplify Window Layout + 简化窗å£å¸ƒå±€ + + + + Alt+Shift+0 + Alt+Shift+0 + + + + Dock Windows at Bottom + 窗å£åœé åº•部 + + + + Dock Windows at Left Side + 窗å£åœé å·¦ä¾§ + + + + Dock Windows at Top + 窗å£åœé é¡¶éƒ¨ + + + + File %1 already exists. Please choose a different name. + 文件 %1 已存在。请选择一个ä¸åŒçš„å称。 + + + + Error importing data: %1 + å¯¼å…¥æ•°æ®æ—¶å‡ºé”™: %1 + + + + Import completed. + 导入完æˆã€‚ + + + + Delete View + 删除视图 + + + + Modify View + 修改视图 + + + + Delete Trigger + 删除触å‘器 + + + + Modify Trigger + 修改触å‘器 + + + + Delete Index + 删除索引 + + + + + Delete Table + 删除表 + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + 设置 PRAGMA 值将会æäº¤æ‚¨çš„当å‰äº‹åŠ¡ã€‚ +您确定å—? + + + + In-Memory database + 内存数æ®åº“ + + + + Automatically load the last opened DB file at startup + å¯åŠ¨æ—¶è‡ªåŠ¨åŠ è½½ä¸Šæ¬¡æ‰“å¼€çš„æ•°æ®åº“文件 + + + + Ctrl+0 + Ctrl+0 + + + + Alt+Shift+W + Alt+Shift+W + + + + Choose a database file to save under + 选择数æ®åº“文件ä¿å­˜ä½ç½® + + + + Error while saving the database to the new file. + ä¿å­˜æ•°æ®åº“到新文件时出错。 + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + 你确定è¦åˆ é™¤è¡¨ '%1' å—? +所有关è”的数æ®éƒ½ä¼šä¸¢å¤±ã€‚ + + + + Are you sure you want to delete the view '%1'? + 你确定è¦åˆ é™¤è§†å›¾ '%1' å—? + + + + Are you sure you want to delete the trigger '%1'? + 你确定è¦åˆ é™¤è§¦å‘器 '%1' å—? + + + + Are you sure you want to delete the index '%1'? + 你确定è¦åˆ é™¤ç´¢å¼• '%1' å—? + + + + Error: could not delete the table. + 错误: 无法删除表。 + + + + Error: could not delete the view. + 错误: 无法删除视图。 + + + + Error: could not delete the trigger. + 错误: 无法删除触å‘器。 + + + + Error: could not delete the index. + 错误: 无法删除索引。 + + + + Message from database engine: +%1 + æ¥è‡ªæ•°æ®åº“引擎的消æ¯: +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + 编辑表格之å‰éœ€è¦ç«‹åˆ»ä¿å­˜æ‰€æœ‰ä¿®æ”¹ã€‚ +你确定è¦ä¿å­˜æ•°æ®åº“å—? + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + ä½ å·²ç»åœ¨æ‰§è¡ŒSQL语å¥ã€‚是å¦è¦åœæ­¢æ‰§è¡Œå¹¶æ”¹ä¸ºæ‰§è¡Œå½“å‰è¯­å¥ï¼Ÿæ³¨æ„,这å¯èƒ½ä½¿æ•°æ®åº“处于ä¸å‡†ç¡®çš„状æ€ã€‚ + + + + -- EXECUTING SELECTION IN '%1' +-- + -- 执行 '%1' 中所选 +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- 执行 '%1' 中的行 +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- 执行 '%1' 中所有 +-- + + + + %1 rows returned in %2ms + %1 行返回,耗时 %2ms + + + + Choose text files + 选择文本文件 + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + 导入完æˆã€‚一些外键约æŸè¢«è¿å了。请在ä¿å­˜ä¹‹å‰ä¿®å¤ã€‚ + + + + Modify Index + 修改索引 + + + + Modify Table + 修改表 + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + 选择拖放一些文件所è¦åº”用的æ“作。<br/>注æ„ï¼šåªæœ‰â€œå¯¼å…¥â€ä¼šå¤„ç†å¤šä¸ªæ–‡ä»¶ã€‚ + + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + 是å¦è¦å°†å¯¹ SQL 标签页的修改ä¿å­˜åˆ°é¡¹ç›®æ–‡ä»¶ '%1'? + + + + Select SQL file to open + é€‰æ‹©è¦æ‰“开的 SQL 文件 + + + + Select file name + 选择文件å + + + + Select extension file + 选择扩展文件 + + + + Extension successfully loaded. + 扩展æˆåŠŸåŠ è½½ã€‚ + + + + Error loading extension: %1 + 加载扩展时出错: %1 + + + + + Don't show again + ä¸å†æ˜¾ç¤º + + + + New version available. + 新版本å¯ç”¨ã€‚ + + + + DB file '%1' could not be opened + 无法打开数æ®åº“文件 '%1' + + + + Table '%1' not found; settings ignored + 找ä¸åˆ°è¡¨ '%1'; 设置已忽略 + + + + -- Reference to file "%1" (not supported by this version) -- + -- 引用文件 "%1" (æ­¤ç‰ˆæœ¬æš‚ä¸æ”¯æŒ) -- + + + + Project saved to file '%1' + 项目已ä¿å­˜åˆ°æ–‡ä»¶ '%1' + + + + Collation needed! Proceed? + éœ€è¦æ•´ç†! ç»§ç»­? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + æ•°æ®åº“中的一个表需è¦ç‰¹å®šçš„æ•´ç†æ–¹æ³• '%1' 但本应用程åºä¸äº†è§£æ•…无法æä¾›ã€‚ +如果您选择继续,å°å¿ƒå¯èƒ½ä¼šæœ‰ä¸å¥½çš„事情å‘生。 +记得备份! + + + + creating collation + åˆ›å»ºæ•´ç† + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + 为 SQL 标签页设置新å称。使用 '&&' 字符æ¥å…许它作为键盘快æ·é”®ã€‚ + + + + Please specify the view name + 请指定视图åç§° + + + + There is already an object with that name. Please choose a different name. + 已有åŒå的对象。请选择一个ä¸åŒçš„å称。 + + + + View successfully created. + 视图创建æˆåŠŸã€‚ + + + + Error creating view: %1 + 创建视图出错: %1 + + + + This action will open a new SQL tab for running: + 此动作会打开新的 SQL 标签页以è¿è¡Œ: + + + + Press Help for opening the corresponding SQLite reference page. + 按下帮助以打开对应的 SQLite å‚考页。 + + + + NullLineEdit + + + Set to NULL + 设置为 NULL + + + + Alt+Del + + + + + PlotDock + + + Plot + 绘图 + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>æ­¤é¢æ¿æ˜¾ç¤ºå½“å‰è¡¨æˆ–者刚刚执行的查询的列。你å¯ä»¥é€‰æ‹©åˆ—用åšåœ¨ä¸‹é¢ç”»å›¾æ—¶çš„ X è½´å’Œ Y 轴。表中显示检测到的会影å“绘图结果的轴类型。Y è½´åªå…许选择数值类型,但 X è½´å¯ä»¥é€‰æ‹©:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">日期/æ—¶é—´</span>: æ ¼å¼åŒ–的字符串 &quot;yyyy-MM-dd hh:mm:ss&quot; 或 &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">日期</span>: æ ¼å¼åŒ–的字符串 &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">æ—¶é—´</span>: æ ¼å¼åŒ–的字符串 &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">标签</span>: å…¶ä»–æ ¼å¼çš„字符串。选这项作为x轴,会绘制æ¡å½¢å›¾ï¼Œå¹¶ç”¨å€¼ä½œä¸ºæ¡å½¢çš„æ ‡ç­¾</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">数值</span>: 整数或实数值</li></ul><p>åŒå‡» Y å•元格å¯ä»¥æ”¹å˜å›¾ä¸­æ‰€ç”¨çš„颜色。</p></body></html> + + + + Columns + 列 + + + + X + X + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + 轴类型 + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + 这是在你在上é¢é€‰æ‹© x å’Œ y 值åŽç»˜åˆ¶å‡ºçš„图。 + +点击点å¯ä»¥åœ¨å›¾å’Œè¡¨æ ¼ä¸­é€‰ä¸­å®ƒä»¬ã€‚Ctrl+点击以选中一批点。 + +使用鼠标滚轮å¯ä»¥ç¼©æ”¾ï¼Œé¼ æ ‡æ‹–拽å¯ä»¥æ”¹å˜å标轴的范围。 + +选择轴或者轴上的标签并拖拽å¯ä»¥ç¼©æ”¾æ­¤æ–¹å‘。 + + + + Line type: + 线形: + + + + + None + æ—  + + + + Line + 折线 + + + + StepLeft + 左阶梯 + + + + StepRight + å³é˜¶æ¢¯ + + + + StepCenter + 中阶梯 + + + + Impulse + 脉冲 + + + + Point shape: + 点形: + + + + Cross + å‰ + + + + Plus + 加 + + + + Circle + 圈 + + + + Disc + 实心点 + + + + Square + 方形 + + + + Diamond + è±å½¢ + + + + Star + 星 + + + + Triangle + 三角 + + + + TriangleInverted + 倒三角 + + + + CrossSquare + å‰ä¸Žæ–¹å½¢ + + + + PlusSquare + 加与方形 + + + + CrossCircle + å‰ä¸Žåœˆ + + + + PlusCircle + 加与圈 + + + + Peace + å’Œå¹³ç¬¦å· + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>ä¿å­˜å½“å‰å›¾è¡¨...</p><p>æ–‡ä»¶æ ¼å¼æŒ‰æ‰©å±•å选择(png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + ä¿å­˜å½“å‰å›¾è¡¨... + + + + + Load all data and redraw plot + 载入所有数æ®å¹¶é‡æ–°ç»˜å›¾ + + + + + + Row # + 行 # + + + + Copy + å¤åˆ¶ + + + + Print... + 打å°... + + + + Help + 帮助 + + + + Show legend + 显示图例 + + + + Stacked bars + å †å çš„æ¡å½¢ + + + + Fixed number format + å›ºå®šæ•°å­—æ ¼å¼ + + + + Date/Time + 日期/æ—¶é—´ + + + + Date + 日期 + + + + Time + æ—¶é—´ + + + + + Numeric + 数值 + + + + Label + 标签 + + + + Invalid + 无效的 + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + 载入所有数æ®å¹¶é‡æ–°ç»˜å›¾ã€‚ +警告:由于部分加载机制,现在并没有加载所有的数æ®ã€‚ + + + + Choose an axis color + é€‰ä¸€ä¸ªåæ ‡è½´é¢œè‰² + + + + Choose a filename to save under + 选择一个文件åä¿å­˜ + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;所有文件(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + 图中有曲线,选择的线形åªèƒ½ç”¨åˆ°æŒ‰ X 排列的图中。è¦ä¹ˆå¯¹è¡¨æŽ’åºæˆ–者用 X 查询,è¦ä¹ˆé€‰ä¸€ç§æ›²çº¿æ”¯æŒçš„线形:无或者折线。 + + + + Loading all remaining data for this table took %1ms. + 加载表中全部剩余数æ®èŠ±è´¹äº†%1毫秒。 + + + + PreferencesDialog + + + Preferences + 首选项 + + + + &General + 通用(&G) + + + + Remember last location + è®°ä½ä¸Šæ¬¡çš„ä½ç½® + + + + Always use this location + 总是使用此ä½ç½® + + + + Remember last location for session only + 仅在会è¯ä¸­è®°ä½ä¸Šæ¬¡çš„ä½ç½® + + + + Lan&guage + 语言(&G) + + + + Automatic &updates + 自动更新(&A) + + + + &Database + æ•°æ®åº“(&D) + + + + Database &encoding + æ•°æ®åº“ç¼–ç (&E) + + + + Open databases with foreign keys enabled. + 打开å¯ç”¨äº†å¤–键的数æ®åº“。 + + + + &Foreign keys + 外键(&F) + + + + + + + + + + + + + + enabled + å¯ç”¨ + + + + Default &location + 默认ä½ç½®(&L) + + + + + + ... + ... + + + + Remove line breaks in schema &view + 删除架构视图中的æ¢è¡Œ(&V) + + + + Show remote options + 显示远程选项 + + + + Prefetch block si&ze + 预å–å—尺寸(&Z) + + + + SQ&L to execute after opening database + 打开数æ®åº“åŽæ‰§è¡Œçš„ SQL(&L) + + + + Default field type + 默认字段类型 + + + + Data &Browser + æ•°æ®æµè§ˆå™¨(&B) + + + + Font + 字体 + + + + &Font + 字体(&F) + + + + Content + 内容 + + + + Symbol limit in cell + å•元格字符数é™åˆ¶ + + + + NULL + 空 + + + + Regular + 常规 + + + + Binary + 二进制 + + + + Background + 背景 + + + + Filters + 过滤 + + + + Threshold for completion and calculation on selection + 自动完æˆä¸Žæ±‡æ€»é™åˆ¶ + + + + Show images in cell + 显示å•元格中图片 + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + å¯ç”¨æ­¤é€‰é¡¹å¯ä»¥é¢„览å•元格BOLB中包å«çš„å›¾ç‰‡ã€‚ä½†è¿™ä¼šå½±å“æµè§ˆæ•°æ®çš„æ€§èƒ½ã€‚ + + + + Escape character + 转义字符 + + + + Delay time (&ms) + å»¶æ—¶(毫秒)(&M) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + 设置应用新过滤值å‰çš„等待时间。设为0以ç¦ç”¨ç­‰å¾…。 + + + + &SQL + &SQL + + + + Context + 上下文 + + + + Colour + 颜色 + + + + Bold + 粗体 + + + + Italic + 斜体 + + + + Underline + 下划线 + + + + Keyword + 关键字 + + + + Function + 函数 + + + + Table + 表 + + + + Comment + 注释 + + + + Identifier + 识别符 + + + + String + 字符串 + + + + Current line + 当å‰è¡Œ + + + + SQL &editor font size + SQL 编辑器字体大å°(&E) + + + + Tab size + Tab 长度 + + + + SQL editor &font + SQL 编辑器字体(&F) + + + + Error indicators + 显示代ç é”™è¯¯ + + + + Hori&zontal tiling + 水平平铺(&Z) + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + 如果å¯ç”¨ï¼ŒSQL ç¼–è¾‘å™¨å’Œç»“æžœè¡¨è§†å›¾å°†å¹¶æŽ’æ˜¾ç¤ºï¼Œè€Œä¸æ˜¯ä¸Šä¸‹æ˜¾ç¤ºã€‚ + + + + Code co&mpletion + 自动补全(&M) + + + + Toolbar style + 工具æ é£Žæ ¼ + + + + + + + + Only display the icon + 仅显示图标 + + + + + + + + Only display the text + 仅显示文本 + + + + + + + + The text appears beside the icon + æ–‡æœ¬åœ¨å›¾æ ‡æ— + + + + + + + + The text appears under the icon + 文本在图标下 + + + + + + + + Follow the style + éµå¾ªé£Žæ ¼ + + + + DB file extensions + æ•°æ®åº“文件扩展 + + + + Manage + ç®¡ç† + + + + Main Window + ä¸»çª—å£ + + + + Database Structure + æ•°æ®åº“结构 + + + + Browse Data + æµè§ˆæ•°æ® + + + + Execute SQL + 执行 SQL + + + + Edit Database Cell + 编辑数æ®åº“å•元格 + + + + When this value is changed, all the other color preferences are also set to matching colors. + 改å˜è¿™ä¸ªé€‰é¡¹ä¹Ÿä¼šæ”¹å˜å…¶ä»–的颜色风格。 + + + + Follow the desktop style + è·Ÿéšæ¡Œé¢é£Žæ ¼ + + + + Dark style + 黑暗风格 + + + + Application style + 界é¢é£Žæ ¼ + + + + This sets the font size for all UI elements which do not have their own font size option. + 此项设定所有无专门字å·é€‰é¡¹çš„界é¢å…ƒç´ çš„å­—å·ã€‚ + + + + Font size + å­—ä½“å¤§å° + + + + Max Recent Files + “最近的文件â€ä¸Šé™ + + + + Prompt to save SQL tabs +in new project file + 关闭 SQL 标签页时æç¤ºä¿å­˜åˆ°é¡¹ç›®æ–‡ä»¶ + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + 如果å¯ç”¨ï¼Œåœ¨ SQL 编辑器的标签页中åšå‡ºæ›´æ”¹åŽï¼Œå…³é—­é‚£äº›æ ‡ç­¾é¡µå°†å¼•出一个是å¦ä¿å­˜æ–°â€œé¡¹ç›®æ–‡ä»¶â€çš„ç¡®è®¤å¯¹è¯æ¡†ã€‚ + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + 当å¯ç”¨æ—¶ï¼Œæ•°æ®åº“结构标签页中的架构列里的æ¢è¡Œï¼Œæ˜¾ç¤ºã€æ‰“å°æ—¶è¢«ç§»é™¤ã€‚ + + + + Database structure font size + æ•°æ®åº“ç»“æž„å­—ä½“å¤§å° + + + + Font si&ze + 字体大å°(&Z) + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + å¯ç”¨ä¸€äº›è€—费资æºçš„计算的最大行数,包括: +å¯ç”¨è‡ªåŠ¨å®Œæˆçš„表中最大行数。 +自动进行求和与平å‡å€¼çš„æœ€å¤§é€‰æ‹©å•元格数é‡ã€‚ +å¯ä»¥è®¾ç½®ä¸º0以ç¦ç”¨è¿™äº›åŠŸèƒ½ã€‚ + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + 这是表å¯ç”¨æ ¹æ®å½“å‰å€¼çš„自动补完的最大的列数é‡ã€‚ +设置æˆ0以ç¦ç”¨è¡¥å®Œã€‚ + + + + Field display + 字段显示 + + + + Light style + 亮色 + + + + Displayed &text + 显示的文本(&T) + + + + Formatted + æ ¼å¼åŒ–åŽ + + + + + + + + + + + Click to set this color + 点击设置颜色 + + + + Text color + 文本颜色 + + + + Background color + 背景颜色 + + + + + Preview only (N/A) + 仅预览 (N/A) + + + + Foreground + 剿™¯ + + + + Selection background + 选中项背景色 + + + + Selection foreground + 选䏭项剿™¯è‰² + + + + Highlight + 高亮 + + + + SQL &results font size + SQL 结果的字体大å°(&R) + + + + Use tabs for indentation + 使用制表符缩进 + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + å¯ç”¨åŽï¼ŒTab 键将æ’入制表符和空格字符用于缩进。ä¸å¯ç”¨åˆ™åªä½¿ç”¨ç©ºæ ¼ã€‚ + + + + &Wrap lines + æ¢è¡Œ(&W) + + + + Never + æ°¸ä¸ + + + + At word boundaries + 按照è¯è¾¹ç•Œ + + + + At character boundaries + 按照字æ¯è¾¹ç•Œ + + + + At whitespace boundaries + 按照空白字符边界 + + + + &Quotes for identifiers + 标识转义(&Q) + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + 选择 SQL 代ç ä¸­æ ‡è¯†çš„转义方å¼ã€‚ + + + + "Double quotes" - Standard SQL (recommended) + "åŒå¼•å·" - 标准 SQL (推è) + + + + `Grave accents` - Traditional MySQL quotes + `é‡éŸ³ç¬¦` - ç»å…¸çš„ MySQL 转义 + + + + [Square brackets] - Traditional MS SQL Server quotes + [方括å·] - ç»å…¸çš„ MS SQL Server 转义 + + + + Keywords in &UPPER CASE + 关键字大写(&U) + + + + When set, the SQL keywords are completed in UPPER CASE letters. + 设置时,SQL 关键字被自动补全为大写字æ¯ã€‚ + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + 设置时,导致上次执行期间出错的 SQL 代ç è¡Œä¼šè¢«é«˜äº®ï¼Œå¹¶åœ¨ç»“æžœé¢æ¿ä¸­æ ‡äº® + + + + Close button on tabs + 标签页上的关闭按钮 + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + 如果å¯ç”¨ï¼ŒSQL 编辑器的标签页将有一个关闭按钮。无论该项是å¦å¯ç”¨ï¼Œå³é”®èœå•和键盘快æ·é”®éƒ½å¯å…³é—­æ ‡ç­¾é¡µã€‚ + + + + &Extensions + 扩展(&E) + + + + Select extensions to load for every database: + 选择æ¯ä¸ªæ•°æ®åº“è¦åŠ è½½çš„æ‰©å±•: + + + + Add extension + 添加扩展 + + + + Remove extension + 删除扩展 + + + + Select built-in extensions to load for every database: + 选择è¦ä¸ºæ¯ä¸ªæ•°æ®åº“加载的内置扩展: + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>è™½ç„¶æ”¯æŒ REGEXP è¿ç®—符,但是 SQLite 并没有实现任何正则表达å¼ç®—法,<br/>而是回调应用程åºã€‚DB Browser for SQLite 为您实现了算法,以便您å¯ä»¥<br/>打破常规使用 REGEXP。由于算法有多ç§å¯èƒ½çš„实现,您å¯èƒ½æƒ³ç”¨å…¶ä»–的,<br/>所以您å¯ä»¥ç¦ç”¨ç®—法实现并通过扩展加载您的实现。需è¦é‡å¯åº”用程åºã€‚</p></body></html> + + + + Disable Regular Expression extension + ç¦ç”¨æ­£åˆ™è¡¨è¾¾å¼æ‰©å±• + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite æä¾›äº† SQL 函数用于从共享库中加载扩展。å¯ç”¨è¿™ä¸ªé€‰é¡¹ä»¥åœ¨SQL代ç ä¸­ä½¿ç”¨ <span style=" font-style:italic;">load_extension()</span> 函数。</p><p>因安全原因,加载扩展功能默认被关闭,须在此处手动å¯ç”¨ã€‚但å³ä½¿æ­¤é€‰é¡¹æœªå¯ç”¨ï¼Œä»èƒ½é€šè¿‡ä¸Šæ–¹çš„界é¢åŠ è½½æ‰©å±•ã€‚</p></body></html> + + + + Allow loading extensions from SQL code + å…许在SQL代ç é‡ŒåŠ è½½æ‰©å±• + + + + Remote + 远程 + + + + CA certificates + CA è¯ä¹¦ + + + + Proxy + ä»£ç†æœåС噍 + + + + Configure + é…ç½® + + + + Export Settings + 导出设置 + + + + Import Settings + 导入设置 + + + + + Subject CN + 主题 CN (Subject CN) + + + + Common Name + 公用åç§° (Common Name) + + + + Subject O + 主题 O (Subject O) + + + + Organization + 组织 (Organization) + + + + + Valid from + 有效期从 + + + + + Valid to + 有效期到 + + + + + Serial number + åºåˆ—å· + + + + Your certificates + 您的è¯ä¹¦ + + + + File + 文件 + + + + Subject Common Name + 主题公用åç§° (Subject Common Name) + + + + Issuer CN + ç­¾å‘人 CN (Issuer CN) + + + + Issuer Common Name + ç­¾å‘人公用åç§° (Issuer Common Name) + + + + Clone databases into + 克隆数æ®åº“ä¿¡æ¯ + + + + + Choose a directory + 选择一个目录 + + + + + The language will change after you restart the application. + 语言将在é‡å¯åº”用程åºåŽæ”¹å˜ã€‚ + + + + Select extension file + 选择扩展文件 + + + + Extensions(*.so *.dylib *.dll);;All files(*) + 扩展(*.so *.dylib *.dll);;所有文件(*) + + + + Import certificate file + 导入è¯ä¹¦æ–‡ä»¶ + + + + No certificates found in this file. + 在文件中找ä¸åˆ°è¯ä¹¦ã€‚ + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + 您确定è¦åˆ é™¤æ­¤è¯ä¹¦å—?所有的è¯ä¹¦æ•°æ®éƒ½ä¼šè¢«ä»Žåº”ç”¨è®¾ç½®ä¸­åˆ é™¤ï¼ + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + ä½ ç¡®å®šè¦æ¸…除所有ä¿å­˜çš„设置å—? +所有你åšçš„设置都会丢失,并使用默认值。 + + + + Save Settings File + ä¿å­˜è®¾ç½®æ–‡ä»¶ + + + + + Initialization File (*.ini) + åˆå§‹åŒ–文件 (*.ini) + + + + The settings file has been saved in location : + + 设置文件已ä¿å­˜åˆ°ï¼š + + + + Open Settings File + 打开设置文件 + + + + The settings file was loaded properly. + 设置文件æˆåŠŸåŠ è½½ã€‚ + + + + The selected settings file is not a normal settings file. +Please check again. + 所选的设置文件格å¼ä¸æ­£å¸¸ã€‚ +è¯·å¤æŸ¥ã€‚ + + + + ProxyDialog + + + Proxy Configuration + ä»£ç†æœåС噍é…ç½® + + + + Pro&xy Type + ä»£ç†æœåŠ¡å™¨ç±»åž‹(&X) + + + + Host Na&me + 主机å(&M) + + + + Port + ç«¯å£ + + + + Authentication Re&quired + 需è¦èº«ä»½éªŒè¯(&Q) + + + + &User Name + 用户å(&U) + + + + Password + å¯†ç  + + + + None + æ—  + + + + System settings + è·Ÿéšç³»ç»Ÿè®¾ç½® - - SQLite Version - SQLite 版本 + + HTTP + HTTP - - <html><head/><body><p>SQLite Database Browser is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:small;">It also uses the Silk icon set by Mark James licensed under a Creative Commons Attribution 2.5 and 3.0 license.<br/>See </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> - <html><head/><body><p>SQLite Database Browser 是一个开æºçš„å…è´¹å¯è§†åŒ–工具,用于创建ã€è®¾è®¡å’Œç¼–辑 SQLite æ•°æ®åº“文件。</p><p>它是以第 2 版 Mozilla 公共许å¯ï¼Œä»¥åŠç¬¬ 3 版åŠä¹‹åŽç‰ˆæœ¬çš„ GNU é€šç”¨è®¸å¯æ–¹å¼æŽˆæƒã€‚ä½ å¯ä»¥åœ¨éµå¾ªè¿™äº›è®¸å¯çš„æ¡ä»¶ä¸‹ä¿®æ”¹æˆ–é‡æ–°å‘布它。</p><p>å‚阅 <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> å’Œ <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> 了解细节。</p><p>è¦èŽ·å¾—æœ¬ç¨‹åºçš„æ›´å¤šä¿¡æ¯ï¼Œè¯·è®¿é—®æˆ‘们的网站: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">这个软件使用了 GPL/LGPL Qt Toolkit: </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>å‚阅 </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> äº†è§£è®¸å¯æ¡æ¬¾å’Œä¿¡æ¯ã€‚</span></p><p><span style=" font-size:small;">它还是用了由 Mark James æä¾›çš„ Silk 图标集,以第 2.5 å’Œ 3.0 版知识共享署å(CCA)è®¸å¯æ–¹å¼æŽˆæƒã€‚<br/>å‚阅 </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> 了解细节。</span></p></body></html> + + SOCKS5 + SOCKS5 - Application + QObject - - Usage: %1 [options] [db] - - 用法: %1 [选项] [æ•°æ®åº“] - + + Error importing data + å¯¼å…¥æ•°æ®æ—¶å‡ºé”™ - - Possible command line arguments: - å¯ç”¨å‘½ä»¤è¡Œå‚æ•°: + + from record number %1 + è‡ªè®°å½•ç¼–å· %1 - - -h, --help Show command line options - -h, --help 显示命令行选项 + + . +%1 + . +%1 - - -s, --sql [file] Execute this SQL file after opening the DB - -s, --sql [文件] 在打开数æ®åº“åŽæ‰§è¡Œè¿™ä¸ª SQL 文件 + + Importing CSV file... + 导入 CSV 文件... - - -q, --quit Exit application after running scripts - -q, --quit 在è¿è¡Œè„šæœ¬åŽé€€å‡ºåº”ç”¨ç¨‹åº + + Cancel + å–æ¶ˆ - - [file] Open this SQLite database - [文件] 打开这个 SQLite æ•°æ®åº“ + + All files (*) + 所有文件 (*) - - The -s/--sql option requires an argument - -s/--sql 选项需è¦ä¸€ä¸ªå‚æ•° + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + SQLite æ•°æ®åº“文件 (*.db *.sqlite *.sqlite3 *.db3) - - The file %1 does not exist - 文件 %1 ä¸å­˜åœ¨ + + Left + å·¦ - - Invalid option/non-existant file: %1 - 无效选项/ä¸å­˜åœ¨çš„æ–‡ä»¶: %1 + + Right + å³ + + + + Center + 居中 + + + + Justify + 两段 + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + SQLite æ•°æ®åº“文件 (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + DB Browser for SQLite 项目文件 (*.sqbpro) + + + + SQL Files (*.sql) + SQL 文件 (*.sql) + + + + All Files (*) + 所有文件 (*) + + + + Text Files (*.txt) + 纯文本文件 (*.txt) + + + + Comma-Separated Values Files (*.csv) + CSV (逗å·åˆ†éš”)(*.csv) + + + + Tab-Separated Values Files (*.tsv) + TSV (制表符分隔)(*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + DSV (分隔符分隔)(*.dsv) + + + + Concordance DAT files (*.dat) + Concordance DAT 文件 (*.dat) + + + + JSON Files (*.json *.js) + JSON 文件 (*.json *.js) + + + + XML Files (*.xml) + XML 文件 (*.xml) + + + + Binary Files (*.bin *.dat) + 二进制文件 (*.bin *.dat) + + + + SVG Files (*.svg) + SVG 文件 (*.svg) + + + + Hex Dump Files (*.dat *.bin) + å六进制转储文件 (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + 扩展 (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + åˆå§‹åŒ–文件 (*.ini) - CreateIndexDialog + QsciCommand - - Create New Index - 创建新索引 + Paste + 粘贴 - - &Name - åç§°(&N) + Cancel + å–æ¶ˆ + + + QsciLexerCPP - - &Columns - 列(&C) + Default + 默认 - - Column - 列 + Keyword + 关键字 + + + Identifier + 识别符 + + + QsciLexerJSON - - Use in Index - 在索引中使用 + Default + 默认 - - Order - é¡ºåº + String + 字符串 + + + QsciLexerJavaScript - - &Table - 表(&T) + Regular expression + æ­£åˆ™è¡¨è¾¾å¼ + + + QsciLexerPython - - &Unique - 唯一(&U) + Default + 默认 - - Creating the index failed: -%1 - 创建索引时失败: -%1 + Comment + 注释 + + + Keyword + 关键字 + + + Identifier + 识别符 - DbStructureModel + QsciLexerSQL - - Name - åç§° + Default + 默认 - - Object - 对象 + Comment + 注释 - - Type - 类型 + Keyword + 关键字 - - Schema - æž¶æž„ + Identifier + 识别符 + + + QsciScintilla - - Tables (%1) - 表 (%1) + &Undo + 撤销(&U) - - Indices (%1) - 索引 (%1) + Select All + 全选 + + + RemoteCommitsModel - - Views (%1) - 视图 (%1) + + Commit ID + æäº¤ ID - - Triggers (%1) - 触å‘器 (%1) + + Message + æ¶ˆæ¯ + + + + Date + 日期 + + + + Author + 作者 + + + + Size + å¤§å° + + + + Authored and committed by %1 + ç» %1 认è¯å¹¶æäº¤ + + + + Authored by %1, committed by %2 + ç”± %1 认è¯ï¼Œç”± %2 æäº¤ - EditDialog + RemoteDatabase - - Edit database cell - 编辑数æ®åº“å•元格 + + Error opening local databases list. +%1 + 打开本地数æ®åº“列表时出错。 +%1 - - Import text - 导入文本 + + Error creating local databases list. +%1 + 创建本地数æ®åº“列表时出错。 +%1 + + + RemoteDock - - Opens a file dialog used to import text to this database cell. - æ‰“å¼€ä¸€ä¸ªæ–‡ä»¶å¯¹è¯æ¡†ç”¨äºŽå¯¼å…¥æ–‡æœ¬åˆ°è¿™ä¸ªæ•°æ®åº“å•元格。 + + Remote + 远程 - - &Import - 导入(&I) + + Local + 本地 - - Export text - 导出文本 + + Identity + 身份 - - Opens a file dialog used to export the contents of this database cell to a text file. - æ‰“å¼€ä¸€ä¸ªæ–‡ä»¶å¯¹è¯æ¡†ç”¨äºŽå¯¼å‡ºè¿™ä¸ªæ•°æ®åº“å•元格的内容到一个文本文件。 + + Push currently opened database to server + 推é€å½“剿‰“开的数æ®åº“到æœåС噍 - - &Export - 导出(&E) + + Upload + 上传 - - Text - 文本 + + DBHub.io + DBHub.io - - Binary - 二进制 + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>åœ¨æ­¤é¢æ¿ï¼Œæ¥è‡ª dbhub.io 网站的远程数æ®åº“å¯ä»¥è¢«æ·»åŠ åˆ° DB4S。首先你需è¦ä¸€ä¸ªèº«ä»½:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">登录 dbhub.io 网站 (使用你的 GitHub è®¤è¯æˆ–其他什么)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">点击按钮创建 DB4S è¯ä¹¦ (那是你的身份)。 这会给你一个è¯ä¹¦æ–‡ä»¶ (ä¿å­˜åˆ°ä½ çš„æœ¬åœ°ç¡¬ç›˜é‡Œ)。</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">å‰å¾€ DB4S 的设置中的远程选项å¡ã€‚点击添加è¯ä¹¦ï¼Œé€‰æ‹©åˆšæ‰ä¸‹è½½çš„æ–‡ä»¶ã€‚</li></ol><p>è¿™æ ·ï¼Œè¿œç¨‹é¢æ¿å°±ä¼šæ˜¾ç¤ºä½ çš„身份,之åŽå¯ä»¥æ·»åŠ è¿œç¨‹æ•°æ®åº“。</p></body></html> - - Clear cell data - 清除å•å…ƒæ ¼æ•°æ® + + Current Database + 当剿•°æ®åº“ - - Erases the contents of the cell - 删除å•元格的内容 + + Clone + 克隆 - - &Clear - 清除(&C) + + Branch + 分支 - - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Warning: Editing binary content in text mode may result in corrupted data!</span></p></body></html> - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">警告: 在文本模å¼ä¸­ç¼–辑二进制内容å¯èƒ½ä¼šå¯¼è‡´æ•°æ®æŸå!</span></p></body></html> + + Commits + æäº¤ - - This area displays information about the data present in this database cell - 这个区域显示存在于这个数æ®åº“å•元格中的数æ®çš„ç›¸å…³ä¿¡æ¯ + + Commits for + æäº¤äºŽ - - Type of data currently in cell - 当å‰åœ¨å•元格中的数æ®çš„类型 + + Delete Database + 删除数æ®åº“ - - Size of data currently in table - 当å‰åœ¨è¡¨ä¸­çš„æ•°æ®çš„å¤§å° + + Delete the local clone of this database + 删除此数æ®åº“的本地副本 - - Choose a file - 选择一个文件 + + Open in Web Browser + 在网页æµè§ˆå™¨ä¸­æ‰“å¼€ - - Text files(*.txt);;Image files(%1);;All files(*) - 文本文件(*.txt);;å›¾åƒæ–‡ä»¶(%1);;所有文件(*) + + Open the web page for the current database in your browser + 在您的网页æµè§ˆå™¨ä¸­æ‰“å¼€ç½‘é¡µä»¥æŸ¥çœ‹å½“å‰æ•°æ®åº“ - - Choose a filename to export data - 选择一个导出数æ®çš„æ–‡ä»¶å + + Clone from Link + 从链接克隆 - - Text files(*.txt);;All files(*) - 文本文件(*.txt);;所有文件(*) + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + 用它æ¥ä»Žæ•°æ®åº“网页æä¾›çš„链接æ¥ä¸‹è½½ä¸€ä¸ªè¿œç¨‹æ•°æ®åº“以供本地编辑。 - - Type of data currently in cell: Text / Numeric - 当å‰åœ¨å•元格中的数æ®çš„类型: Text 文本/ Numeric 数值 + + Refresh + 刷新 - - - %n char(s) - - %n 个字符 - + + + Reload all data and update the views + 刷新所有数æ®å¹¶æ›´æ–°è§†å›¾ - - Type of data currently in cell: Image - 当å‰åœ¨å•元格中的数æ®çš„类型: Image å›¾åƒ + + Clone Database + 克隆数æ®åº“ - - %1x%2 pixel - %1x%2 åƒç´  + + Open Database + 打开数æ®åº“ - - Type of data currently in cell: Binary - 当å‰åœ¨å•元格中的数æ®çš„类型: Binary 二进制 + + Open the local copy of this database + 打开此数æ®åº“的本地副本 - - - %n byte(s) - - %n 字节 - + + + Check out Commit + 检出æäº¤ - - - EditTableDialog - - Edit table definition - 编辑表定义 + + Download and open this specific commit + 下载并打开此æäº¤ - - Table - 表 + + Check out Latest Commit + 检出最新æäº¤ - - Fields - 字段 + + Check out the latest commit of the current branch + 检出当å‰åˆ†æ”¯çš„æœ€æ–°æäº¤ - - Add field - 添加字段 + + Save Revision to File + ä¿å­˜ä¿®è®¢ç‰ˆæœ¬åˆ°æ–‡ä»¶ - - Remove field - 删除字段 + + Saves the selected revision of the database to another file + ä¿å­˜æ‰€é€‰çš„æ•°æ®åº“修订版本到其他文件 - - Move field up - 上移字段 + + Upload Database + 上传数æ®åº“ - - Move field down - 下移字段 + + Upload this database as a new commit + 上传此数æ®åº“为新的æäº¤ - - Name - åç§° + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>你正在使用内置的,åªè¯»çš„凭æ®ã€‚è¦ä¸Šä¼ ä½ çš„æ•°æ®åº“,你需è¦é…置使用你的 DBHub.io è´¦å·ã€‚</p><p>还没有 DBHub.io è´¦å·ï¼Ÿ<a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">注册一个</span></a> 并在 <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">此处</span></a> 导入你的è¯ä¹¦ã€‚</p><p>è¦èŽ·å¾—åœ¨çº¿å¸®åŠ©ï¼Œç‚¹å‡»<a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">这里</span></a>。</p></body></html> - - Type - 类型 + + &User + 用户(&U) - - - Not null - éžç©º + + &Database + æ•°æ®åº“(&D) - - PK - PK + + Back + 返回 - - Primary key - 主键 + + Select an identity to connect + 选择用æ¥è¿žæŽ¥çš„身份 - - AI - AI + + Public + 公用è¯ä¹¦ - - Autoincrement - 自动增值 + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + 这将从远程æœåŠ¡å™¨ä¸‹è½½æ•°æ®åº“以供本地编辑。 +请输入è¦ä»Žå“ªä¸ªç½‘å€å…‹éš†ã€‚您å¯ä»¥ç»å¦‚下方å¼ç”Ÿæˆæ­¤ç½‘å€ï¼šç‚¹å‡»æ•°æ®åº“的网页所æä¾›çš„“在 DB4S 中克隆数æ®åº“â€ï¼ˆClone Database in DB4S)的按钮。 - - Default - 默认 + + Invalid URL: The host name does not match the host name of the current identity. + 无效网å€ï¼šä¸»æœºå称与当å‰èº«ä»½çš„主机åç§°ä¸åŒ¹é…。 - - Default value - 默认值 + + Invalid URL: No branch name specified. + 无效网å€ï¼šæœªæŒ‡å®šåˆ†æ”¯å称。 - - Check - 检查 + + Invalid URL: No commit ID specified. + 无效网å€ï¼šæœªæŒ‡å®šæäº¤ ID。 - - Check constraint - æ£€æŸ¥çº¦æŸæ¡ä»¶ + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + 您已修改了这个数æ®åº“çš„æœ¬åœ°å‰¯æœ¬ã€‚èŽ·å–æ­¤æäº¤å°†è¦†ç›–本地的更改。 +是å¦ç»§ç»­ï¼Ÿ - - Error creating table. Message from database engine: -%1 - 创建表时出错。æ¥è‡ªæ•°æ®åº“引擎的消æ¯: -%1 + + The database has unsaved changes. Are you sure you want to push it before saving? + æ•°æ®åº“有未ä¿å­˜çš„æ›´æ”¹ã€‚确定è¦åœ¨ä¿å­˜å‰æŽ¨é€å—? - - There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. - 至少有一行带本字段的记录被设为空。这使得它ä¸å¯èƒ½è®¾ç½®è¿™ä¸ªæ ‡å¿—。请首先更改表数æ®ã€‚ + + The database you are trying to delete is currently opened. Please close it before deleting. + 您å°è¯•删除的数æ®åº“ç›®å‰ä»æ˜¯æ‰“开状æ€ã€‚请先关闭,å†å°è¯•删除。 - - There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. - åœ¨è¿™ä¸ªå­—æ®µä¸­è‡³å°‘æœ‰ä¸€è¡Œå¸¦æœ‰ä¸€ä¸ªéžæ•´æ•°çš„值。这使得它ä¸å¯èƒ½è®¾ç½® AI 标志。请首先更改表数æ®ã€‚ + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + 这将删除此数æ®åº“的本地副本,包括其中未æäº¤çš„æ‰€æœ‰æ›´æ”¹ã€‚确定删除å—? + + + RemoteLocalFilesModel - - Are you sure you want to delete the field '%1'? -All data currently stored in this field will be lost. - 您是å¦ç¡®è®¤æ‚¨æƒ³åˆ é™¤å­—段 '%1'? -当å‰å­˜å‚¨åœ¨è¿™ä¸ªå­—段中的所有数æ®å°†ä¼šä¸¢å¤±ã€‚ + + Name + åç§° + + + + Branch + 分支 + + + + Last modified + 上次修改 + + + + Size + å¤§å° + + + + Commit + æäº¤ + + + + File + 文件 - ExportCsvDialog + RemoteModel - - Export data as CSV - 导出数æ®ä¸º CSV + + Name + åç§° - - &Table - 表(&T) + + Last modified + 上次修改 - - &Column names in first line - 列å在首行(&C) + + Size + å¤§å° - - Field &separator - 字段分隔符(&S) + + Commit + æäº¤ - - , - , + + Size: + 大å°: - - ; - ; + + Last Modified: + 上次修改: - - - Tab - Tab + + Licence: + 许å¯åè®®: - - | - | + + Default Branch: + 默认分支: + + + RemoteNetwork - - - Other - 其它 + + Choose a location to save the file + 选择ä¿å­˜è¯¥æ–‡ä»¶çš„ä½ç½® - - &Quote character - 引å·(&Q) + + Error opening remote file at %1. +%2 + 打开远程文件 %1 时出错。 +%2 - - " - " + + Error: Invalid client certificate specified. + 错误:指定的客户端è¯ä¹¦æ— æ•ˆã€‚ - - ' - ' + + Please enter the passphrase for this client certificate in order to authenticate. + 请输入此客户端è¯ä¹¦çš„å£ä»¤ä»¥è¿›è¡Œèº«ä»½éªŒè¯ã€‚ - - Choose a filename to export data - 选择导出数æ®çš„æ–‡ä»¶å + + Cancel + å–æ¶ˆ - - Text files(*.csv *.txt) - 文本文件(*.csv *.txt) + + Uploading remote database to +%1 + 正在上传远程数æ®åº“到 +%1 - - Export completed. - 导出完æˆã€‚ + + Downloading remote database from +%1 + 正在下载远程数æ®åº“自 +%1 - - Could not open output file. - ä¸èƒ½æ‰“开输出文件。 + + Error: Cannot open the file for sending. + 错误:无法打开文件以进行å‘é€ã€‚ - FilterTableHeader + RemotePushDialog - - Filter - 过滤 + + Push database + æŽ¨é€æ•°æ®åº“ - - - ImportCsvDialog - - Import CSV file - 导入 CSV 文件 + + Database na&me to push to + 推é€çš„æ•°æ®åº“å(&m) - - &Table name - 表åç§°(&T) + + Commit message + æäº¤ä¿¡æ¯ - - &Column names in first line - 列å在首行(&C) + + Database licence + æ•°æ®åº“许å¯åè®® - - Field &separator - 字段分隔符(&S) + + Public + 公开 - - , - , + + Branch + 分支 - - ; - ; + + Force push + å¼ºåˆ¶æŽ¨é€ - - - Tab - Tab + + Username + 用户å - - | - ; + + Database will be public. Everyone has read access to it. + æ•°æ®åº“将是公有的。所有人都å¯ä»¥è¯»å–它。 - - - Other - 其它 + + Database will be private. Only you have access to it. + æ•°æ®åº“å°†æ˜¯ç§æœ‰çš„ã€‚åªæœ‰æ‚¨å¯ä»¥è®¿é—®å®ƒã€‚ - - &Quote character - 引å·(&Q) + + Use with care. This can cause remote commits to be deleted. + å°å¿ƒä½¿ç”¨ã€‚è¿™å¯èƒ½ä¼šå¯¼è‡´è¿œç¨‹æäº¤è¢«åˆ é™¤ã€‚ + + + RunSql - - " - ; + + Execution aborted by user + æ“作被用户终止 - - ' - ' + + , %1 rows affected + ,%1 行数æ®å—å½±å“ - - Inserting data... - 正在æ’入数æ®... + + query executed successfully. Took %1ms%2 + 查询执行æˆåŠŸã€‚è€—æ—¶ %1ms%2 - - Cancel - å–æ¶ˆ + + executing query + 执行查询 + + + SelectItemsPopup - - There is already a table of that name and an import into an existing table is only possible if the number of columns match. - 已有åŒåçš„è¡¨ï¼Œå¹¶ä¸”å¯¼å…¥åªæœ‰åœ¨åˆ—数匹é…的情况下æ‰èƒ½å¯¼å…¥åˆ°ä¸€ä¸ªçŽ°æœ‰çš„è¡¨ã€‚ + + A&vailable + å¯ç”¨(&V) - - There is already a table of that name. Do you want to import the data into it? - 已有åŒåçš„è¡¨ã€‚æ‚¨æ˜¯å¦æƒ³å¯¼å…¥æ•°æ®åˆ°å…¶ä¸­? + + Sele&cted + 已选(&C) - MainWindow + SqlExecutionArea - - SQLiteBrowser - SQLiteBrowser + + Form + è¡¨å• - - Database &Structure - æ•°æ®åº“结构(&S) + + Find previous match [Shift+F3] + 查找上一个 [Shift+F3] - - - toolBar1 + + Find previous match with wrapping + æŒ‰é¡ºåºæŸ¥æ‰¾ä¸Šä¸€é¡¹ + + + + Shift+F3 - - &Browse Data - æµè§ˆæ•°æ®(&B) + + The found pattern must be a whole word + æ‰¾åˆ°çš„å¿…é¡»æ˜¯ä¸€ä¸ªå®Œæ•´çš„è¯ - - Table: - 表: + + Whole Words + å…¨å­—åŒ¹é… - - Select a table to browse data - 选择一个表以æµè§ˆæ•°æ® + + Text pattern to find considering the checks in this frame + 符åˆè¿™é‡Œçš„é€‰æ‹©è¦æŸ¥æ‰¾çš„æ–‡æœ¬ - - Use this list to select a table to be displayed in the database view - ä½¿ç”¨è¿™ä¸ªåˆ—è¡¨é€‰æ‹©ä¸€ä¸ªè¦æ˜¾ç¤ºåœ¨æ•°æ®åº“视图中的表 + + Find in editor + 在编辑器中查找 - - Refresh the data in the selected table. - 刷新选择的表中的数æ®ã€‚ + + The found pattern must match in letter case + æœç´¢å¿…须大å°å†™åŒ¹é… - - This button refreshes the data in the currently selected table. - 这个按钮刷新在当å‰é€‰æ‹©çš„表中的数æ®ã€‚ + + Case Sensitive + 大å°å†™æ•感 - - - F5 - F5 + + Find next match [Enter, F3] + 查找下一个 [Enter, F3] - - Insert a new record in the current table - 在当å‰è¡¨ä¸­æ’å…¥ä¸€æ¡æ–°è®°å½• + + Find next match with wrapping + 循环查找下一个 - - This button creates a new, empty record in the database - 这个按钮在数æ®åº“ä¸­åˆ›å»ºä¸€æ¡æ–°çš„空白记录 + + F3 + - - New Record - 新建记录 + + Interpret search pattern as a regular expression + è§£æžæŸ¥æ‰¾ç›®æ ‡ä¸ºæ­£åˆ™è¡¨è¾¾å¼ - - Delete the current record - 删除当å‰è®°å½• + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>é€‰ä¸­æ—¶ï¼Œè¦æŸ¥æ‰¾çš„æ¨¡å¼è¢«è§£é‡Šä¸º UNIX 正则表达å¼ã€‚å‚阅 <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Wikibooks 中的正则表达å¼</a>.</p></body></html> - - This button deletes the record currently selected in the database - 这个按钮删除在数æ®åº“中当å‰é€‰æ‹©çš„记录 + + Regular Expression + æ­£åˆ™è¡¨è¾¾å¼ - - Delete Record - 删除记录 + + + Close Find Bar + å…³é—­æŸ¥æ‰¾æ  - - This is the database view. You can double-click any record to edit its contents in the cell editor window. - 这是数æ®åº“视图。您å¯ä»¥åŒå‡»ä»»ä½•记录,在å•元格编辑器窗å£ä¸­ç¼–辑记录内容。 + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>上次执行的语å¥çš„结果。</p><p>ä½ å¯èƒ½å¸Œæœ›æŠ˜å è¿™ä¸ªçª—格并使用 <span style=" font-style:italic;">SQL 日志</span> 区域查看æäº¤è‡ª <span style=" font-style:italic;">用户</span> 的结果。</p></body></html> - - < - < + + Results of the last executed statements + 上次执行语å¥çš„结果 - - 0 - 0 of 0 - 0 - 0 / 0 + + This field shows the results and status codes of the last executed statements. + è¿™ä¸ªå­—æ®µæ˜¾ç¤ºæœ€åŽæ‰§è¡Œçš„语å¥çš„结果和状æ€ç ã€‚ - - > - > + + Ctrl+PgUp + - - Scroll 100 records upwards - 上滚 100 æ¡è®°å½• + + Ctrl+PgDown + - - <html><head/><body><p>Clicking this button navigates 100 records upwards in the table view above.</p></body></html> - <html><head/><body><p>点击这个按钮在上é¢çš„表视图中å‘上导航 100 æ¡è®°å½•。</p></body></html> + + Couldn't read file "%1": %2. + æ— æ³•è¯»å–æ–‡ä»¶â€œ%1â€ï¼š%2。 - - <html><head/><body><p>Scroll 100 records downwards</p></body></html> - <html><head/><body><p>下滚 100 æ¡è®°å½•</p></body></html> + + + Couldn't save file: %1. + 无法ä¿å­˜æ–‡ä»¶: %1。 - - <html><head/><body><p>Clicking this button navigates 100 records downwards in the table view above.</p></body></html> - <html><head/><body><p>点击这个按钮在上é¢çš„表视图中å‘下导航 100 æ¡è®°å½•。</p></body></html> + + Your changes will be lost when reloading it! + 釿–°åŠ è½½æ—¶ï¼Œä½ çš„æ›´æ”¹å°†ä¼šä¸¢å¤±ï¼ - - <html><head/><body><p>Click here to jump to the specified record</p></body></html> - <html><head/><body><p>点击这里跳到指定的记录</p></body></html> + + The file "%1" was modified by another program. Do you want to reload it?%2 + 文件 "%1" 已被其他程åºä¿®æ”¹ã€‚是å¦è¦é‡æ–°åŠ è½½ï¼Ÿ%2 - - <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> - <html><head/><body><p>这个按钮用于导航到在“转到â€åŒºåŸŸä¸­æŒ‡å®šçš„记录å·ã€‚</p></body></html> + + Answer "Yes to All" to reload the file on any external update without further prompting. + 选择“全是â€å°†è‡ªåЍ釿–°åŠ è½½æœ‰å¤–éƒ¨æ›´æ–°çš„æ–‡ä»¶ï¼Œæ— è¿›ä¸€æ­¥æç¤ºã€‚ - - Go to: - 转到: + + Answer "No to All" to ignore any external update without further prompting. + 选择“全å¦â€å°†å¿½ç•¥æ–‡ä»¶çš„外部更新,无进一步æç¤ºã€‚ - - Enter record number to browse - è¾“å…¥è¦æµè§ˆçš„è®°å½•å· + + Modifying and saving the file will restore prompting. + 修改并ä¿å­˜æ–‡ä»¶å°†é‡æ–°å¼€å¯æç¤ºã€‚ + + + SqlTextEdit - - Type a record number in this area and click the Go to: button to display the record in the database view - 在这个区域中输入一个记录å·ï¼Œå¹¶ç‚¹å‡»â€œè½¬åˆ°:â€æŒ‰é’®ä»¥åœ¨æ•°æ®åº“视图中显示记录 + + Ctrl+/ + + + + SqlUiLexer - - 1 - 1 + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) abs(X) å‡½æ•°è¿”å›žæ•°å­—å‚æ•° X çš„ç»å¯¹å€¼ã€‚ - - Edit &Pragmas - ç¼–è¾‘æ‚æ³¨(&P) + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () changes() 函数返回最åŽå®Œæˆçš„ INSERTã€DELETE 或 UPDATE è¯­å¥æ‰€æ›´æ”¹ã€æ’入或删除的数æ®åº“行数。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">自动真空</span></a></p></body></html> + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) char(X1,X2,...,XN) 函数返回一个字符串,分别由整数 X1 至 XN 所代表的特定 Unicode ç ç‚¹çš„字符组æˆã€‚ - - None - æ—  + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) coalesce() å‡½æ•°è¿”å›žç¬¬ä¸€ä¸ªéž NULL çš„å‚æ•°çš„å‰¯æœ¬ï¼Œæ‰€æœ‰å‚æ•°å‡ä¸º NULL 则返回 NULL - - - Full - 完整 + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) glob(X,Y) å‡½æ•°ç­‰æ•ˆäºŽè¡¨è¾¾å¼ "Y GLOB X"。 - - Incremental - 增加 + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) ifnull() å‡½æ•°è¿”å›žç¬¬ä¸€ä¸ªéž NULL çš„å‚æ•°çš„å‰¯æœ¬ï¼Œä¸¤ä¸ªå‚æ•°å‡ä¸º NULL 则返回 NULL。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">自动化索引</span></a></p></body></html> + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) instr(X,Y) 函数查找字符串 Y 在字符串 X 中的第一处匹é…,返回之å‰å­—符数加 1;如果 X 中找ä¸åˆ° Y,则返回 0。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">检查点完全 FSYNC</span></a></p></body></html> + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) hex() å‡½æ•°å°†å…¶å‚æ•°è§£é‡Šä¸ºä¸€ä¸ª BLOB 并返回一个字符串,该字符串是该 Blob 内容的大写å六进制表现形å¼ã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">外键</span></a></p></body></html> + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) iif(X,Y,Z) 函数在 X 为真(true)时返回 Y,å¦åˆ™è¿”回 Z。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">完全 FSYNC</span></a></p></body></html> + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () last_insert_rowid() 函数返回调用该函数的数æ®åº“连接所æ’入的最åŽä¸€è¡Œçš„ ROWID。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">忽略检查约æŸ</span></a></p></body></html> + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) 对字符串值 X,length(X) 函数返回 X 的字符数(éžå­—节数)(截至首个 NUL 字符)。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">日志模å¼</span></a></p></body></html> + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) like() 函数用于实现"Y LIKE X" 表达å¼ã€‚ - - Delete - 删除 + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) like() 函数用于实现 "Y LIKE X ESCAPE Z" 表达å¼ã€‚ - - Truncate - è£æˆª + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) load_extension(X) 函数从共享库文件 X 加载 SQLite 扩展。 +必须在“首选项â€ä¸­æŽˆæƒä½¿ç”¨æ­¤åŠŸèƒ½ã€‚ - - Persist - 永久 + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) load_extension(X) 函数从共享库文件 X çš„ å…¥å£ç‚¹ Y 加载 SQLite 扩展。 +必须在“首选项â€ä¸­æŽˆæƒä½¿ç”¨æ­¤åŠŸèƒ½ã€‚ - - - Memory - 内存 + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) lower(X) 函数返回字符串 X 的副本,其中将所有 ASCII 字符转æ¢ä¸ºå°å†™ã€‚ - - WAL - WAL + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) 移除 X 中左侧的空白字符。 - - - Off - å…³ + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) ltrim(X,Y) 函数返回一个字符串,该字符串是从 X 中的左侧删除所有 Y 而组æˆã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">日志大å°é™åˆ¶</span></a></p></body></html> + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) å¤šå‚æ•°çš„ max() å‡½æ•°è¿”å›žæœ‰æœ€å¤§å€¼çš„å‚æ•°ï¼Œå¦‚æœ‰ä»»ä½•å‚æ•°ä¸º NULL 则返回 NULL。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">é”定模å¼</span></a></p></body></html> + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) å¤šå‚æ•°çš„ min() 函数返回有最å°å€¼çš„傿•°ã€‚ - - - Normal - 正常 + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) nullif(X,Y) å‡½æ•°åœ¨ä¼ å…¥çš„ä¸¤ä¸ªå‚æ•°ä¸åŒæ—¶è¿”å›žé¦–ä¸ªå‚æ•°ï¼›ä¸¤ä¸ªå‚数相åŒåˆ™è¿”回 NULL。 - - Exclusive - ç‹¬å  + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) printf(FORMAT,...) SQL 函数的功效类似 sqlite3_mprintf() C 语言函数和标准 C 语言库中的 printf() 函数。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">最大页数</span></a></p></body></html> + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) quote(X) 函数返回一个 SQL 语法的文本形å¼ï¼Œé€‚åˆåœ¨å„ç§ SQL 语å¥ä¸­ç”¨ä½œå‚数值。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">页é¢å¤§å°</span></a></p></body></html> + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () random() å‡½æ•°è¿”å›žä¸€ä¸ªä¼ªéšæœºæ•´æ•°ï¼ŒèŒƒå›´åœ¨ -9223372036854775808 至 +9223372036854775807 之间。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">递归触å‘器</span></a></p></body></html> + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) randomblob(N) 函数返回一个长度为 N 字节的 Blob,包å«ä¼ªéšæœºçš„å­—èŠ‚ã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">安全删除</span></a></p></body></html> + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) replace(X,Y,Z) 函数返回一个字符串,其中是将字符串 X 中的æ¯ä¸ª Y 字符串替æ¢ä¸º Z 字符串。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">åŒæ­¥</span></a></p></body></html> + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) round(X) 函数返回一个浮点值,X 被四èˆäº”入为 0 ä¸ªå°æ•°ã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">临时存储</span></a></p></body></html> + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X) round(X) 函数返回一个浮点值,X 被四èˆäº”入为 Y ä¸ªå°æ•°ã€‚ - - Default - 默认 + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X) 移除 X 中å³ä¾§çš„空白字符。 - - File - 文件 + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) rtrim(X,Y) 函数返回一个字符串,该字符串是从 X 中的å³ä¾§åˆ é™¤æ‰€æœ‰ Y 而组æˆã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">用户版本</span></a></p></body></html> + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) soundex(X) 函数返回一个字符串,由字符串 X çš„ soundex ç¼–ç ç»„æˆã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL 自动检查点</span></a></p></body></html> + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) substr(X,Y) 函数返回字符串 X 中第 Y 个字符开始的所有字符。 - - E&xecute SQL - 执行 SQL(&X) + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) substr(X,Y,Z) 函数返回输入字符串 X 中第 Y 个字符开始的 Z 个长字符。 - - &File - 文件(&F) + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () total_changes() å‡½æ•°è¿”å›žå½“å‰æ•°æ®åº“è¿žæŽ¥æ‰“å¼€ä»¥æ¥ INSERTã€UPDATE 或 DELETE è¯­å¥æ›´æ”¹çš„行数总计。 - - &Import - 导入(&I) + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) 移除 X 中左å³ä¸¤ä¾§çš„空白字符。 - - &Export - 导出(&E) + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) trim(X,Y) 函数返回一个字符串,从 X 的左å³ä¸¤ç«¯åˆ é™¤æ‰€æœ‰ Y 字符。 - - &Edit - 编辑(&E) + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) typeof(X) å‡½æ•°è¿”å›žä¸€ä¸ªå­—ç¬¦ä¸²ï¼Œè¡¨ç¤ºè¡¨è¾¾å¼ X 的数æ®ç±»åž‹ã€‚ - - &View - 查看(&V) + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) unicode(X) 函数字符串 X 的第一个字符所对应的 Unicode 代ç ç‚¹æ•°å­—。 - - &Help - 帮助(&H) + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) upper(X) 函数返回输入字符串的副本,其中所有å°å†™ ASCII 字符转æ¢ä¸ºç­‰æ•ˆçš„大写字æ¯ã€‚ - - toolBar - toolBar + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) zeroblob(N) 函数返回一个 BLOB,由 N 个字节的 0x00 组æˆã€‚ - - SQL Log - SQL 日志 + + + + + (timestring,modifier,modifier,...) + (时间字符串,修饰符,修饰符,...) - - &Show SQL submitted by - 显示 SQL æäº¤è‡ª(&S) + + (format,timestring,modifier,modifier,...) + (æ ¼å¼,时间字符串,修饰符,修饰符,...) - - User - 用户 + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) avg() å‡½æ•°è¿”å›žä¸€ä¸ªç»„ä¸­æ‰€æœ‰éž NULL çš„ X 的平å‡å€¼ã€‚ - - Application - åº”ç”¨ç¨‹åº + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) count(X) å‡½æ•°è¿”å›žä¸€ä¸ªç»„ä¸­æ‰€æœ‰éž NULL çš„ X 的数é‡ã€‚ - - &Clear - 清除(&C) + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) group_concat() 函数返回一个字符串,由 X çš„æ‰€æœ‰éž NULL 值串è”而æˆã€‚ - - Plot - 图表 + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) group_concat() 函数返回一个字符串,由 X çš„æ‰€æœ‰éž NULL 值串è”而æˆã€‚如果æä¾›äº† Y,Y ä½œä¸ºä¸²è” X 时的分隔符。 - - Columns - 列列 + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) max() èšåˆå‡½æ•°è¿”回组中所有值的最大值。 - - X - X + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) min() èšåˆå‡½æ•°è¿”å›žç»„ä¸­æ‰€æœ‰å€¼çš„éž NULL 的最å°å€¼ã€‚ - - Y - Y + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) sum() å’Œ total() èšåˆå‡½æ•°è¿”å›žç»„ä¸­æ‰€æœ‰å€¼çš„éž NULL 值的总计。 - - _ - _ + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () 当å‰åˆ†åŒºå†…的行数。行数从 1 开始,以 ORDER BY å­å¥æŒ‡å®šçš„é¡ºåºæŽ’åˆ—ï¼ˆæœªæä¾›åˆ™ä»¥ä»»æ„é¡ºåºæŽ’åˆ—ï¼‰ã€‚ - - Save current plot... - ä¿å­˜å½“å‰å›¾è¡¨... + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () æ¯ç»„中第一个åŒçº§çš„ row_number() - 当å‰è¡Œçš„æŽ’å(有间隙)。如果没有 ORDER BY å­å¥ï¼Œåˆ™æ‰€æœ‰è¡Œéƒ½è¢«è§†ä¸ºåŒçº§ï¼Œå¹¶ä¸”此函数始终返回 1。 - - &New Database... - 新建数æ®åº“(&N)... + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () 当å‰è¡Œæ‰€åœ¨åˆ†åŒºå†…åŒçº§ç»„çš„ç¼–å· - 无间隙的当å‰è¡ŒæŽ’å。分区按窗å£å®šä¹‰ä¸­çš„ ORDER BY å­å¥çš„顺åºä»Ž 1 开始编å·ã€‚如果没有 ORDER BY å­å¥ï¼Œåˆ™æ‰€æœ‰è¡Œéƒ½è¢«è§†ä¸ºåŒçº§ï¼Œå¹¶ä¸”此函数始终返回 1。 - - - Create a new database file - 创建一个新的数æ®åº“文件 + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () 尽管å称如此,此函数始终返回介于 0.0 å’Œ 1.0 之间的值,等于 (rank - 1)/(partition-rows - 1),其中 rank 是内置窗å£å‡½æ•° rank() 返回的值,partition-rows æ˜¯åˆ†åŒºä¸­çš„æ€»è¡Œæ•°ã€‚å¦‚æžœåˆ†åŒºä¸­åªæœ‰ä¸€è¡Œï¼Œåˆ™æ­¤å‡½æ•°è¿”回 0.0。 - - This option is used to create a new database file. - 这个选项用于创建一个新的数æ®åº“文件。 + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () 累积分布。计算方法为 row-number/partition-rows,其中 row-number 是 row_number() 为组中最åŽä¸€ä¸ªåŒçº§è¿”回的值,partition-rows 是分区中的行数。 - - Ctrl+N - Ctrl+N + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) 傿•° N 被视为一个整数。此函数将分区尽å¯èƒ½å‡åŒ€åœ°åˆ’分为 N 个组,并按照 ORDER BY å­—å¥å®šä¹‰çš„顺åºï¼ˆæˆ–ä»»æ„顺åºï¼‰ï¼Œä¸ºæ¯ä¸ªç»„分é…一个 1 至 N 之间的整数。如ä¸å¾—已,较大的组会先出现。此函数返回分é…给当å‰è¡Œçš„代表所属组的整数值。 - - &Open Database... - 打开数æ®åº“(&O)... + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (表达å¼) è¿”å›žå¯¹åˆ†åŒºä¸­ä¸Šä¸€è¡Œçš„è¡¨è¾¾å¼æ±‚值结果。如果当å‰è¡Œæ˜¯ç¬¬ä¸€è¡Œï¼Œè¿”回 NULL。 - - - Open an existing database file - 打开一个现有的数æ®åº“文件 + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (表达å¼,åç§») 如果æä¾›åç§»å‚æ•°ï¼Œå®ƒé¡»æ˜¯éžè´Ÿæ•°æ•´æ•°ã€‚此时返回针对分区中当å‰è¡Œå‡åŽ»è¡Œåç§»æ‰€å¯¹åº”çš„è¡Œæ¥æ±‚值表达å¼çš„结果。如果å移为0,则求值当å‰è¡Œã€‚如果当å‰è¡Œä¹‹å‰æ²¡æœ‰å¯¹åº”å移的行,返回 NULL。 - - This option is used to open an existing database file. - 这个选项用于打开一个现有的数æ®åº“文件。 + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (表达å¼,åç§»,默认值) 如果还æä¾›é»˜è®¤å€¼å‚数,在å移所标定的行ä¸å­˜åœ¨æ—¶ï¼Œè¿”å›žé»˜è®¤å€¼è€Œéž NULL。 - - Ctrl+O - Ctrl+O + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (表达å¼) è¿”å›žå¯¹åˆ†åŒºä¸­ä¸‹ä¸€è¡Œçš„è¡¨è¾¾å¼æ±‚值结果。如果没有下一行,返回 NULL。 - - &Close Database - 关闭数æ®åº“(&C) + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (表达å¼,åç§») 如果æä¾›åç§»å‚æ•°ï¼Œå®ƒé¡»æ˜¯éžè´Ÿæ•°æ•´æ•°ã€‚此时返回针对分区中当å‰è¡ŒåŠ ä¸Šè¡Œåç§»æ‰€å¯¹åº”çš„è¡Œæ¥æ±‚值表达å¼çš„结果。如果å移为0,则求值当å‰è¡Œã€‚如果当å‰è¡Œä¹‹å‰æ²¡æœ‰å¯¹åº”å移的行,返回 NULL。 - - Ctrl+W - Ctrl+W + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (表达å¼) 此内置窗å£å‡½æ•°ä»¥ä¸Žèšåˆçª—å£å‡½æ•°ç›¸åŒçš„æ–¹å¼è®¡ç®—æ¯è¡Œçš„çª—å£æ¡†æž¶ã€‚它返回针对æ¯è¡Œçª—壿¡†æž¶ä¸­çš„第一行计算的表达å¼çš„值。 - - Revert Changes - 倒退更改 + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (表达å¼) 此内置窗å£å‡½æ•°ä»¥ä¸Žèšåˆçª—å£å‡½æ•°ç›¸åŒçš„æ–¹å¼è®¡ç®—æ¯è¡Œçš„çª—å£æ¡†æž¶ã€‚它返回针对æ¯è¡Œçª—壿¡†æž¶ä¸­çš„æœ€åŽä¸€è¡Œè®¡ç®—的表达å¼çš„值。 - - Revert database to last saved state - 把数æ®åº“会退到先å‰ä¿å­˜çš„çŠ¶æ€ + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (表达å¼,N) 此内置窗å£å‡½æ•°ä»¥ä¸Žèšåˆçª—å£å‡½æ•°ç›¸åŒçš„æ–¹å¼è®¡ç®—æ¯è¡Œçš„çª—å£æ¡†æž¶ã€‚å®ƒè¿”å›žé’ˆå¯¹çª—å£æ¡†æž¶ä¸­ç¬¬ N 行计算的表达å¼çš„值。如果存在 ORDER BY å­å¥ï¼Œåˆ™çª—壿¡†æž¶ä¸­çš„行按定义的顺åºä»Ž 1 开始编å·ï¼Œå¦åˆ™æŒ‰ä»»æ„顺åºç¼–å·ã€‚如果分区中没有第 N 行,则返回 NULL。 - - This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. - 这个选项用于倒退当å‰çš„æ•°æ®åº“文件为它最åŽçš„ä¿å­˜çжæ€ã€‚从最åŽä¿å­˜æ“作开始åšå‡ºçš„æ‰€æœ‰æ›´æ”¹å°†ä¼šä¸¢å¤±ã€‚ + + (X) Return the arccosine of X. The result is in radians. + (X) 返回 X çš„å余弦。结果以弧度为å•ä½ã€‚ - - Write Changes - 写入更改 + + (X) Return the hyperbolic arccosine of X. + (X) 返回 X çš„ååŒæ›²ä½™å¼¦ã€‚ - - Write changes to the database file - 把更改写入到数æ®åº“文件 + + (X) Return the arcsine of X. The result is in radians. + (X) 返回 X çš„åæ­£å¼¦ã€‚结果以弧度为å•ä½ã€‚ - - This option is used to save changes to the database file. - 这个选项用于ä¿å­˜æ›´æ”¹åˆ°æ•°æ®åº“文件。 + + (X) Return the hyperbolic arcsine of X. + (X) 返回 X çš„åŒæ›²å正弦值。 - - Ctrl+S - Ctrl+S + + (X) Return the arctangent of X. The result is in radians. + (X) 返回 X çš„åæ­£åˆ‡å€¼ã€‚结果以弧度表示。 - - Compact Database - 压缩数æ®åº“ + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + (X,Y) 返回 Y/X çš„åæ­£åˆ‡å€¼ã€‚ç»“æžœä»¥å¼§åº¦è¡¨ç¤ºã€‚æ ¹æ® X å’Œ Y 的符å·å°†ç»“果放置在正确的象é™ä¸­ã€‚ - - Compact the database file, removing space wasted by deleted records - 压缩数æ®åº“文件,通过删除记录去掉浪费的空间 + + (X) Return the hyperbolic arctangent of X. + (X) 返回 X çš„åŒæ›²å正切值。 - - - Compact the database file, removing space wasted by deleted records. - 压缩数æ®åº“文件,通过删除记录去掉浪费的空间。 + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + (X) 返回大于或等于 X 的第一个å¯è¡¨ç¤ºçš„æ•´æ•°å€¼ã€‚对于正值 X,此例程å‘远离零的方å‘èˆå…¥ã€‚对于负值 Xï¼Œæ­¤ä¾‹ç¨‹å‘æŽ¥è¿‘é›¶çš„æ–¹å‘èˆå…¥ã€‚ - - E&xit - 退出(&X) + + (X) Return the cosine of X. X is in radians. + (X) 返回 X 的余弦。X çš„å•使˜¯å¼§åº¦ã€‚ - - Ctrl+Q - Ctrl+Q + + (X) Return the hyperbolic cosine of X. + (X) 返回 X çš„åŒæ›²ä½™å¼¦å€¼ã€‚ - - Database from SQL file... - æ¥è‡ª SQL 文件的数æ®åº“... + + (X) Convert value X from radians into degrees. + (X) å°† X 值从弧度转æ¢ä¸ºåº¦æ•°ã€‚ - - Import data from an .sql dump text file into a new or existing database. - 从一个 .sql 转储文本文件中导入数æ®åˆ°ä¸€ä¸ªæ–°çš„æˆ–已有的数æ®åº“。 + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + (X) 计算 e(欧拉数,约为 2.71828182845905)的 X 次幂。 - - This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. - 这个选项让你从一个 .sql 转储文本文件中导入数æ®åˆ°ä¸€ä¸ªæ–°çš„æˆ–现有的数æ®åº“。SQL 转储文件å¯ä»¥åœ¨å¤§å¤šæ•°æ•°æ®åº“引擎上创建,包括 MySQL å’Œ PostgreSQL。 + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + (X) 返回å°äºŽæˆ–等于 X 的第一个å¯è¡¨ç¤ºçš„æ•´æ•°å€¼ã€‚对于正数,此函数å‘é›¶èˆå…¥ã€‚对于负数,此函数å‘远离零的方å‘èˆå…¥ã€‚ - - Table from CSV file... - 表æ¥è‡ª CSV 文件... + + (X) Return the natural logarithm of X. + (X) 返回 X 的自然对数。 - - Open a wizard that lets you import data from a comma separated text file into a database table. - 打开一个å‘导让您从一个逗å·é—´éš”的文本文件导入数æ®åˆ°ä¸€ä¸ªæ•°æ®åº“表中。 + + (B,X) Return the base-B logarithm of X. + (B,X) 返回 X 的以 B 为底的对数。 - - Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. - 打开一个å‘导让您从一个逗å·é—´éš”的文本文件导入数æ®åˆ°ä¸€ä¸ªæ•°æ®åº“表中。CSV 文件å¯ä»¥åœ¨å¤§å¤šæ•°æ•°æ®åº“和电å­è¡¨æ ¼åº”用程åºä¸Šåˆ›å»ºã€‚ + + + (X) Return the base-10 logarithm for X. + (X) 返回 X 的以 10 为底的对数。 - - Database to SQL file... - æ•°æ®åº“到 SQL 文件... + + (X) Return the logarithm base-2 for the number X. + (X) 返回数 X 的以 2 为底的对数。 - - Export a database to a .sql dump text file. - 导出一个数æ®åº“导一个 .sql 转储文本文件。 + + (X,Y) Return the remainder after dividing X by Y. + (X,Y) 返回 X 除以 Y åŽçš„余数。 - - This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. - 这个选项让你导出一个数æ®åº“导一个 .sql 转储文本文件。SQL 转储文件包å«åœ¨å¤§å¤šæ•°æ•°æ®åº“引擎上(包括 MySQL å’Œ PostgreSQL)釿–°åˆ›å»ºæ•°æ®åº“所需的所有数æ®ã€‚ + + () Return an approximation for Ï€. + () 返回 Ï€ 的近似值。 - - Table as CSV file... - 表为 CSV 文件... + + + (X,Y) Compute X raised to the power Y. + (X,Y) 计算 X çš„ Y 次方。 - - Export a database table as a comma separated text file. - 导出一个数æ®åº“表为逗å·é—´éš”的文本文件。 + + (X) Convert X from degrees into radians. + (X) å°† X 从角度转æ¢ä¸ºå¼§åº¦ã€‚ - - Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. - 导出一个数æ®åº“表为逗å·é—´éš”的文本文件,准备好被导入到其他数æ®åº“或电å­è¡¨æ ¼åº”用程åºã€‚ + + (X) Return the sine of X. X is in radians. + (X) 返回 X 的正弦值。X çš„å•使˜¯å¼§åº¦ã€‚ - - Create Table... - 创建表... + + (X) Return the hyperbolic sine of X. + (X) 返回 X çš„åŒæ›²æ­£å¼¦å€¼ - - Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database - 打开“创建表â€å‘导,在那里å¯ä»¥å®šä¹‰åœ¨æ•°æ®åº“中的一个新表的å称和字段 + + (X) Return the square root of X. NULL is returned if X is negative. + (X) 返回 X 的平方根。如果 X 为负数,则返回 NULL。 - - Delete Table... - 删除表... + + (X) Return the tangent of X. X is in radians. + (X) 返回 X 的正切值。X 以弧度为å•ä½ã€‚ - - Open the Delete Table wizard, where you can select a database table to be dropped. - 打开“删除表â€å‘导,在那里你å¯ä»¥é€‰æ‹©è¦ä¸¢å¼ƒçš„一个数æ®åº“表。 + + (X) Return the hyperbolic tangent of X. + (X) 返回 X çš„åŒæ›²æ­£åˆ‡å€¼ã€‚ - - Modify Table... - 修改表... + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + (X) 返回 X å’Œ 0(包括 0)之间最远离 0 çš„å¯è¡¨ç¤ºæ•´æ•°ã€‚æ¢å¥è¯è¯´ï¼Œè¿”回 X 的整数部分,å‘é›¶èˆå…¥ã€‚ + + + SqliteTableModel - - Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields form a table, as well as modify field names and types. - 打开“修改表â€å‘导,在其中å¯ä»¥é‡å‘½å一个现有的表。也å¯ä»¥ä»Žä¸€ä¸ªè¡¨ä¸­æ·»åŠ æˆ–åˆ é™¤å­—æ®µï¼Œä»¥åŠä¿®æ”¹å­—段å称和类型。 + + reading rows + 读å–行 - - Create Index... - 创建索引... + + loading... + 正在加载... - - Open the Create Index wizard, where it is possible to define a new index on an existing database table. - 打开“创建索引â€å‘导,在那里å¯ä»¥åœ¨ä¸€ä¸ªçŽ°æœ‰çš„æ•°æ®åº“表上定义一个新索引。 + + References %1(%2) +Hold %3Shift and click to jump there + 引用 %1(%2) +æŒ‰ä½ %3Shift 并点击以跳转 - - &Preferences... - 首选项(&P)... + + Error changing data: +%1 + 更改数æ®åº“时出错: +%1 - - - Open the preferences window. - 打开首选项窗å£ã€‚ + + retrieving list of columns + 正在检索列的列表 - - &DB Toolbar - æ•°æ®åº“工具æ (&D) + + Fetching data... + æ­£åœ¨æ‹‰å–æ•°æ®... - - Shows or hides the Database toolbar. - 显示或éšè—æ•°æ®åº“工具æ ã€‚ + + + Cancel + å–æ¶ˆ + + + TableBrowser - - What's This? - 这是什么? + + Browse Data + æµè§ˆæ•°æ® - - Shift+F1 - Shift+F1 + + &Table: + 表(&T): - - &About... - 关于(&A)... + + Select a table to browse data + 选择一个表以æµè§ˆæ•°æ® - - &Recently opened - 最近打开(&R) + + Use this list to select a table to be displayed in the database view + ä½¿ç”¨è¿™ä¸ªåˆ—è¡¨é€‰æ‹©ä¸€ä¸ªè¦æ˜¾ç¤ºåœ¨æ•°æ®åº“视图中的表 - - Open &tab - 打开标签页(&T) + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + 这是数æ®åº“表视图。你å¯ä»¥è¿›è¡Œä»¥ä¸‹æ“作: + - 直接打字以在这里直接编辑。 + - åŒå‡»è®°å½•以打开å•元格编辑窗å£ã€‚ + - Alt+Del 删除å•å…ƒæ ¼å†…å®¹ï¼Œå˜æˆNULL。 + - Ctrl+" é‡å¤ä¸€ä»½å½“å‰è®°å½•。 + - Ctrl+' 从上é¢çš„å•元格拷è´ã€‚ + - 标准的å¤åˆ¶/粘贴æ“作。 - - Ctrl+T - Ctrl+T + + Text pattern to find considering the checks in this frame + 符åˆè¿™é‡Œçš„é€‰æ‹©è¦æŸ¥æ‰¾çš„æ–‡æœ¬ - - &Execute SQL - 执行 SQL(&E) + + Find in table + 在表中查找 - - Execute SQL [F5, Ctrl+Return] - 执行 SQL [F5, Ctrl+回车] + + Find previous match [Shift+F3] + 查找上一个 [Shift+F3] - - &Wiki... - 维基(&W)... + + Find previous match with wrapping + æŒ‰é¡ºåºæŸ¥æ‰¾ä¸Šä¸€é¡¹ - - Bug &report... - 错误报告(&R)... + + Shift+F3 + - - Web&site... - 网站(&S)... + + Find next match [Enter, F3] + 查找下一个 [Enter, F3] - - Save Project - ä¿å­˜å·¥ç¨‹ + + Find next match with wrapping + 循环查找下一个 - - - Save the current session to a file - ä¿å­˜å½“å‰ä¼šè¯åˆ°ä¸€ä¸ªæ–‡ä»¶ + + F3 + - - Open Project - 打开工程 + + The found pattern must match in letter case + 查找结果须是相åŒçš„大å°å†™å½¢å¼ - - - Load a working session from a file - ä»Žä¸€ä¸ªæ–‡ä»¶åŠ è½½å·¥ä½œä¼šè¯ + + Case Sensitive + 大å°å†™æ•感 - - Open SQL file - 打开 SQL 文件 + + The found pattern must be a whole word + 查找结果需是完整字è¯è€Œéžæ‹†åˆ†å‡ºçš„一部分 - - <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> - <html><head/><body><p>ä¿å­˜å½“å‰å›¾è¡¨...</p><p>æ–‡ä»¶æ ¼å¼æŒ‰æ‰©å±•å选择(png, jpg, pdf, bmp)</p></body></html> + + Whole Cell + å…¨è¯åŒ¹é… - - Save SQL file - ä¿å­˜ SQL 文件 + + Interpret search pattern as a regular expression + 查找内容解æžä¸ºä¸€ä¸ªæ­£åˆ™è¡¨è¾¾å¼ - - Load extension - 加载扩展 + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>选中时,æœç´¢å…³é”®è¯è¢«è§†ä¸ºUNIX正则表达å¼ã€‚å‚阅<a href="https://en.wikibooks.org/wiki/Regular_Expressions">Wikibooks 上对正则表达å¼çš„介ç»</a>。</p></body></html> - - Execute current line - 执行当å‰è¡Œ + + Regular Expression + æ­£åˆ™è¡¨è¾¾å¼ - - Execute current line [Ctrl+E] - 执行当å‰è¡Œ [Ctrl+E] + + + Close Find Bar + å…³é—­æŸ¥æ‰¾æ  - - Ctrl+E - Ctrl+E + + Text to replace with + è¦æ›¿æ¢çš„æ–‡æœ¬ - - Export as CSV file - 导出为 CSV 文件 + + Replace with + æ›¿æ¢ - - Export table as comma separated values file - 导出表为逗å·é—´éš”值文件 + + Replace next match + 替æ¢ä¸‹ä¸ªåŒ¹é…的文本 - - Ctrl+L - Ctrl+L + + + Replace + æ›¿æ¢ - - Ctrl+P - Ctrl+P + + Replace all matches + æ›¿æ¢æ‰€æœ‰åŒ¹é… - - Database encoding - æ•°æ®åº“ç¼–ç  + + Replace all + å…¨éƒ¨æ›¿æ¢ - - Choose a database file - 选择一个数æ®åº“文件 + + Export to &JSON + 导出到 &JSON - - Ctrl+Return - Ctrl+Return + + + Export the filtered data to JSON + å¯¼å‡ºè¿‡æ»¤åŽæ•°æ®åˆ° JSON - - - - - Choose a filename to save under - 选择一个文件åä¿å­˜ + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + 此按钮是将当å‰è¢«æ˜¾ç¤ºã€è¢«æµè§ˆçš„表的数æ®å¯¼å‡ºåˆ°ä¸€ä¸ª JSON 文件。数æ®ç»è¿‡æ»¤å™¨ã€æ˜¾ç¤ºæ ¼å¼å’Œåˆ—顺åºé¡ºåˆ©ã€‚ - - Error adding record: - - 添加记录时出错: - + + Copy column name + å¤åˆ¶åˆ—å - - Error deleting record: -%1 - 删除记录时出错: -%1 + + Copy the database table column name to your clipboard + å¤åˆ¶æ•°æ®åº“表的列ååˆ°ä½ çš„å‰ªè´´æ¿ - - Please select a record first - 请首先选择一æ¡è®°å½• + + New Data Browser + æ–°å»ºæ•°æ®æµè§ˆå™¨ - - %1 - %2 of %3 - %1 - %2 / %3 + + + Add a new docked Data Browser + æ–°å¢žä¸€ä¸ªæ•°æ®æµè§ˆå™¨æ ‡ç­¾é¡µ - - - There is no database opened. Please open or create a new database file. - 没有打开数æ®åº“。请打开或创建一个新的数æ®åº“文件。 + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + æ­¤æŒ‰é’®ä¼šæ·»åŠ ä¸€ä¸ªæ–°çš„æ•°æ®æµè§ˆå™¨æ ‡ç­¾é¡µï¼Œæ‚¨å¯ä»¥å°†å…¶åˆ†ç¦»å¹¶ç½®å…¥å…¶ä»–布局。 - - Are you sure you want to delete the %1 '%2'? -All data associated with the %1 will be lost. - 您是å¦ç¡®è®¤æ‚¨æƒ³åˆ é™¤ %1 '%2'? -所有和 %1 å…³è”的数æ®å°†ä¼šä¸¢å¤±ã€‚ + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>滚动到开始</p></body></html> - - Error: could not delete the %1. Message from database engine: -%2 - 错误: ä¸èƒ½åˆ é™¤ %1ã€‚æ¶ˆæ¯æ¥è‡ªæ•°æ®åº“引擎: -%2 + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>点击这个按钮在上é¢çš„表视图中导航到最å‰ã€‚</p></body></html> - - There is no database opened. - 没有数æ®åº“打开。 + + |< + |< - - %1 Rows returned from: %2 (took %3ms) - %1 行返回自: %2 (耗时 %3毫秒) + + Scroll one page upwards + 上翻一页 - - Error executing query: %1 - 执行查询时出错: %1 + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>点击按钮将表中显示的记录å‘上翻一页。</p></body></html> - - Query executed successfully: %1 (took %2ms) - 查询执行æˆåŠŸ: %1 (耗时 %2毫秒) + + < + < - - Choose a text file - 选择一个文本文件 + + 0 - 0 of 0 + 0 - 0 / 0 - - Text files(*.csv *.txt);;All files(*) - 文本文件(*.csv *.txt);;所有文件(*) + + Scroll one page downwards + 下翻一页 - - Import completed - å¯¼å…¥å®Œæˆ + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>点击按钮将表中显示的记录å‘下翻一页。</p></body></html> - - Are you sure you want to undo all changes made to the database file '%1' since the last save? - 您是å¦ç¡®è®¤æ‚¨æƒ³æ’¤é”€ä»Žä¸Šæ¬¡ä¿å­˜ä»¥æ¥å¯¹æ•°æ®åº“文件‘%1’åšå‡ºçš„æ‰€æœ‰æ›´æ”¹ã€‚? + + > + > - - Choose a filename to export - 选择è¦å¯¼å‡ºçš„æ–‡ä»¶å + + Scroll to the end + æ»šåŠ¨åˆ°ç»“æŸ - - Text files(*.sql *.txt) - 文本文件(*.sql *.txt) + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>点击这个按钮在上é¢çš„表视图中导航到最åŽã€‚</p></body></html> - - Export cancelled or failed. - å¯¼å‡ºå–æ¶ˆæˆ–失败。 + + >| + >| - - Export completed. - 导出完æˆã€‚ + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>点击这里跳到指定的记录</p></body></html> - - Choose a file to import - 选择è¦å¯¼å…¥çš„一个文件 + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>这个按钮用于导航到在“转到â€åŒºåŸŸä¸­æŒ‡å®šçš„记录å·ã€‚</p></body></html> - - - - Text files(*.sql *.txt);;All files(*) - 文本文件(*.sql *.txt);;所有文件(*) + + Go to: + 转到: - - Do you want to create a new database file to hold the imported data? -If you answer no we will attempt to import the data in the SQL file to the current database. - 您是å¦ç¡®è®¤æ‚¨æƒ³åˆ›å»ºä¸€ä¸ªæ–°çš„æ•°æ®åº“文件用æ¥å­˜æ”¾å¯¼å…¥çš„æ•°æ®? -如果您会到“å¦â€çš„è¯ï¼Œæˆ‘们将å°è¯•导入 SQL 文件中的数æ®åˆ°å½“剿•°æ®åº“。 + + Enter record number to browse + è¾“å…¥è¦æµè§ˆçš„è®°å½•å· - - File %1 already exists. Please choose a different name. - 文件 %1 已存在。请选择一个ä¸åŒçš„å称。 + + Type a record number in this area and click the Go to: button to display the record in the database view + 在这个区域中输入一个记录å·ï¼Œå¹¶ç‚¹å‡»â€œè½¬åˆ°:â€æŒ‰é’®ä»¥åœ¨æ•°æ®åº“视图中显示记录 - - Error importing data: %1 - å¯¼å…¥æ•°æ®æ—¶å‡ºé”™: %1 + + 1 + 1 - - Import completed. - 导入完æˆã€‚ + + Show rowid column + 显示 rowid 列 - - Delete View - 删除视图 + + Toggle the visibility of the rowid column + åˆ‡æ¢ rowid 列的å¯è§æ€§ - - Delete Trigger - 删除触å‘器 + + Unlock view editing + è§£é”视图编辑 - - Delete Index - 删除索引 + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + è§£é”当å‰è§†å›¾ä»¥ç¼–辑。然而,你需è¦åˆé€‚的触å‘器æ¥ç¼–辑。 - - - Delete Table - 删除表 + + Edit display format + ç¼–è¾‘æ˜¾ç¤ºæ ¼å¼ - - &%1 %2 - &%1 %2 + + Edit the display format of the data in this column + 编辑列中数æ®çš„æ˜¾ç¤ºæ ¼å¼ - - Setting PRAGMA values will commit your current transaction. -Are you sure? - 设置 PRAGMA 值将会æäº¤æ‚¨çš„当å‰äº‹åŠ¡ã€‚. -您确认å—? + + + New Record + 新建记录 - - Select SQL file to open - é€‰æ‹©è¦æ‰“开的 SQL 文件 + + + Insert a new record in the current table + 在当å‰è¡¨ä¸­æ’å…¥ä¸€æ¡æ–°è®°å½• - - Select file name - 选择文件å + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>此按钮在数æ®åº“中创建新记录。按ä½é¼ æ ‡æŒ‰é’®ä»¥æ‰“å¼€èœå•选择ä¸åŒé€‰é¡¹ï¼š</p><ul><li><span style=" font-weight:600;">新记录</span>: 用默认值æ’å…¥ä¸€æ¡æ–°è®°å½•到数æ®åº“中。</li><li><span style=" font-weight:600;">æ’入值...</span>: æ‰“å¼€å¯¹è¯æ¡†ç¼–è¾‘è¦æ’入的值。å¯ä»¥è¾“入满足约æŸçš„值。如果 <span style=" font-weight:600;">新记录</span> é€‰é¡¹å¤±è´¥ï¼Œå¯¹è¯æ¡†ä¹Ÿä¼šæ‰“开。</li></ul></body></html> - - Select extension file - 选择扩展文件 + + + Delete Record + 删除记录 - - Extensions(*.so *.dll);;All files(*) - 扩展(*.so *.dll);;所有文件(*) + + Delete the current record + 删除当å‰è®°å½• - - Extension successfully loaded. - 扩展æˆåŠŸåŠ è½½ã€‚ + + + This button deletes the record or records currently selected in the table + 此按钮删除表里当å‰é€‰ä¸­çš„记录 - - - Error loading extension: %1 - 加载扩展时出错: %1 + + + Insert new record using default values in browsed table + 用默认值æ’å…¥ä¸€æ¡æ–°è®°å½•åˆ°å½“å‰æµè§ˆçš„表中 - - Don't show again - ä¸å†æ˜¾ç¤º + + Insert Values... + æ’入值... - - New version available. - 新版本å¯ç”¨ã€‚ + + + Open a dialog for inserting values in a new record + æ‰“å¼€å¯¹è¯æ¡†ä»¥æ’入值到新记录中 - - A new sqlitebrowser version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. - 有新版本的 sqlitebrowser (%1.%2.%3)å¯ç”¨ã€‚<br/><br/>请从 <a href='%4'>%4</a> 下载。 + + Export to &CSV + 导出到 &CSV - - Choose a axis color - 选择一个轴的颜色 + + + Export the filtered data to CSV + å¯¼å‡ºå½“å‰æ•°æ®åˆ° CSV - - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;所有文件(*) + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + æ­¤æŒ‰é’®å¯¼å‡ºå½“å‰æµè§ˆã€è¿‡æ»¤çš„è¡¨çš„æ•°æ® (过滤åŽï¼Œæ˜¾ç¤ºæ ¼å¼å’Œåˆ—的顺åº) 到一个CSV文件。 - - Choose a file to open - é€‰æ‹©è¦æ‰“开的一个文件 + + Save as &view + ä¿å­˜ä¸ºè§†å›¾(&V) - - - SQLiteBrowser project(*.sqbpro) - SQLiteBrowser 工程(*.sqbpro) + + + Save the current filter, sort column and display formats as a view + ä¿å­˜å½“å‰è¿‡æ»¤ï¼Œåˆ—排åºå’Œæ˜¾ç¤ºæ ¼å¼ä¸ºè§†å›¾ - - Invalid file format. - 无效文件格å¼ã€‚ + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + 此按钮ä¿å­˜å½“剿µè§ˆè¡¨æ ¼çš„设置 (过滤,显示格å¼å’Œåˆ—的顺åº) 为SQL视图,之åŽå¯ä»¥å†ç”¨SQLè¯­å¥æµè§ˆã€‚ - - - PreferencesDialog - - Preferences - 首选项 + + Save Table As... + 表å¦å­˜ä¸º... - - &Database - æ•°æ®åº“(&D) + + + Save the table as currently displayed + æŒ‰å½“å‰æ˜¾ç¤ºçš„æ ·å­ä¿å­˜è¡¨ - - Database &encoding - æ•°æ®åº“ç¼–ç (&E) + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>æ­¤èœå•æä¾›ä»¥ä¸‹å¯åº”ç”¨åˆ°å½“å‰æµè§ˆã€è¿‡æ»¤çš„表的选项:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">导出到CSV: å¯¼å‡ºå½“å‰æµè§ˆã€è¿‡æ»¤çš„è¡¨çš„æ•°æ® (过滤åŽï¼Œæ˜¾ç¤ºæ ¼å¼å’Œåˆ—的顺åº) 到一个CSV文件。</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ä¿å­˜ä¸ºè§†å›¾: 此选项ä¿å­˜å½“剿µè§ˆè¡¨æ ¼çš„设置 (过滤,显示格å¼å’Œåˆ—的顺åº) 为SQL视图,之åŽå¯ä»¥å†ç”¨SQLè¯­å¥æµè§ˆã€‚</li></ul></body></html> - - Open databases with foreign keys enabled. - 打开å¯ç”¨äº†å¤–键的数æ®åº“。 + + Hide column(s) + éšè—列 - - &Foreign keys - 外键(&F) + + Hide selected column(s) + éšè—选中的列 - - enabled - å¯ç”¨ + + Show all columns + 显示所有列 - - Default &location - 默认ä½ç½®(&L) + + Show all columns that were hidden + 显示所有被éšè—的列 - - ... - ... + + + Set encoding + è®¾ç½®ç¼–ç  - - &Prefetch block size - 预å–å—尺寸(&P) + + Change the encoding of the text in the table cells + 更改表å•å…ƒæ ¼ä¸­æ–‡æœ¬çš„ç¼–ç  - - &SQL - &SQL + + Set encoding for all tables + è®¾ç½®æ‰€æœ‰è¡¨çš„ç¼–ç  - - Settings name - 设置åç§° + + Change the default encoding assumed for all tables in the database + 修改数æ®åº“ä¸­æ‰€æœ‰è¡¨çš„é»˜è®¤ç¼–ç  - - Context - 上下文 + + Clear Filters + 清除过滤 - - Colour - 颜色 + + Clear all filters + 清除所有过滤 - - Bold - 粗体 + + + This button clears all the filters set in the header input fields for the currently browsed table. + æ­¤æŒ‰é’®å°†æ¸…é™¤å½“å‰æµè§ˆè¡¨çš„æ‰€æœ‰åœ¨å¤´éƒ¨è¾“入区的过滤器。 - - Italic - 斜体 + + Clear Sorting + æ¸…é™¤æŽ’åº - - Underline - 下划线 + + Reset the order of rows to the default + 将行的顺åºé‡ç½®ä¸ºé»˜è®¤ - - Keyword - 关键字 + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + æ­¤æŒ‰é’®æ¸…é™¤å½“å‰æµè§ˆçš„表的列排åºï¼Œé‡ç½®ä¸ºé»˜è®¤å€¼ã€‚ - - function - 函数 + + Print + æ‰“å° - - Function - 函数 + + Print currently browsed table data + 打å°å½“剿µè§ˆè¡¨ä¸­çš„æ•°æ® - - Table - 表 + + Print currently browsed table data. Print selection if more than one cell is selected. + 打å°å½“剿­£åœ¨æµè§ˆçš„表中的数æ®ã€‚如果选中了多于一个的å•元格,就打å°é€‰ä¸­åŒºåŸŸã€‚ - - Comment - 注释 + + Ctrl+P + - - Identifier - 识别符 + + Refresh + 刷新 - - String - 字符串 + + Refresh the data in the selected table + åˆ·æ–°é€‰ä¸­è¡¨ä¸­çš„æ•°æ® - - currentline - 当å‰è¡Œ + + This button refreshes the data in the currently selected table. + 这个按钮刷新在当å‰é€‰æ‹©çš„表中的数æ®ã€‚ - - Current line - 当å‰è¡Œ + + F5 + - - SQL &editor font size - SQL 编辑器字体大å°(&E) + + Find in cells + ç¼©å‡æ–‡æœ¬æ ‡ç­¾é•¿åº¦ + å•元格查找 - - SQL &log font size - SQL 日志字体大å°(&L) + + Open the find tool bar which allows you to search for values in the table view below. + 打开查找工具æ ï¼Œä½ å¯ä»¥ç”¨å®ƒæœç´¢å½“å‰è¡¨ä¸­çš„æ•°æ®ã€‚ - - &Extensions - 扩展(&E) + + Freeze columns + 冻结列 - - Select extensions to load for every database: - 选择æ¯ä¸ªæ•°æ®åº“è¦åŠ è½½çš„æ‰©å±•: + + Make all columns from the first column up to this column not move when scrolling horizontally + æ°´å¹³æ»šåŠ¨æ—¶ï¼Œç¬¬ä¸€åˆ—è‡³æ­¤åˆ—çš„æ‰€æœ‰åˆ—ä¿æŒä¸åЍ - - Add extension - 添加扩展 + + + Bold + 粗体 - - Remove extension - 删除扩展 + + Ctrl+B + - - Choose a directory - 选择一个目录 + + + Italic + 斜体 - - Select extension file - 选择扩展文件 + + + Underline + 下划线 - - Extensions(*.so *.dll);;All files(*) - 扩展(*.so *.dll);;所有文件(*) + + Ctrl+U + - - - QObject - - Error importing data. Message from database engine: %1 - 导入数æ®åº“æ—¶å‡ºé”™ã€‚æ¶ˆæ¯æ¥è‡ªæ•°æ®åº“引擎: %1 + + + Align Right + å³å¯¹é½ - - File is not a SQLite 3 database - æ–‡ä»¶ä¸æ˜¯ SQLite 3 æ•°æ®åº“ + + + Align Left + å·¦å¯¹é½ - - File could not be read - 文件ä¸èƒ½è¯»å– + + + Center Horizontally + 垂直居中 - - - - no error - 无错误 + + + Justify + ä¸¤ç«¯å¯¹é½ - - Do you want to save the changes made to the database file %1? - æ‚¨æ˜¯å¦æƒ³ä¿å­˜å¯¹æ•°æ®åº“文件 %1 åšå‡ºçš„æ›´æ”¹? + + + Edit Conditional Formats... + 编辑æ¡ä»¶æ ¼å¼... - - Exporting database to SQL file... - 正在导出数æ®åº“到 SQL 文件... + + Edit conditional formats for the current column + 为当å‰åˆ—设置æ¡ä»¶æ ¼å¼ - - - - Cancel - å–æ¶ˆ + + Clear Format + æ¸…é™¤æ ¼å¼ - - Executing SQL... - 正在执行 SQL... + + Clear All Formats + æ¸…é™¤å…¨éƒ¨æ ¼å¼ - - Action cancelled. - æ“ä½œå·²å–æ¶ˆã€‚ + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + 清除当å‰é€‰æ‹©çš„å•元格的格å¼å’Œå½“å‰é€‰æ‹©çš„列的æ¡ä»¶æ ¼å¼ - - - Error in statement #%1: %2. -Aborting execution. - é”™è¯¯åœ¨è¯­å¥ #%1: %2。 -正在放弃执行。 + + + Font Color + 字体颜色 - - renameColumn: cannot find table %1. - renameColumn: ä¸èƒ½æŸ¥æ‰¾è¡¨ %1。 + + + Background Color + 背景颜色 - - renameColumn: cannot find column %1. - renameColumn: ä¸èƒ½æŸ¥æ‰¾åˆ— %1。 + + Toggle Format Toolbar + ç¼©å‡æ–‡æœ¬æ ‡ç­¾é•¿åº¦ï¼Œä¸å¤±è¯­ä¹‰ + æ ¼å¼å·¥å…·æ  - - renameColumn: creating savepoint failed. DB says: %1 - renameColumn: 创建ä¿å­˜ç‚¹æ—¶å¤±è´¥ã€‚DB 说: %1 + + Show/hide format toolbar + 显示或éšè—æ ¼å¼å·¥å…·æ  - - renameColumn: creating new table failed. DB says: %1 - renameColumn: 创建新表时失败。DB 说: %1 + + + This button shows or hides the formatting toolbar of the Data Browser + 此按钮显示或éšè—æµè§ˆæ•°æ®çª—å£çš„æ ¼å¼å·¥å…·æ  - - renameColumn: copying data to new table failed. DB says: -%1 - renameColumn: å¤åˆ¶æ•°æ®åˆ°æ–°è¡¨æ—¶å¤±è´¥ã€‚DB 说: -%1 + + Select column + 选择列 - - renameColumn: deleting old table failed. DB says: %1 - renameColumn: 删除旧表失败。DB 说: %1 + + Ctrl+Space + - - Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: - - - 还原æŸäº›å’Œè¿™ä¸ªè¡¨å…³è”的对象失败。这个最å¯èƒ½æ˜¯å› ä¸ºæŸäº›åˆ—çš„å称更改了。这里是您å¯èƒ½éœ€è¦æ‰‹åŠ¨ä¿®å¤å’Œæ‰§è¡Œçš„ SQL 语å¥: - - + + Replace text in cells + 在å•å…ƒæ ¼ä¸­æ›¿æ¢ - - renameColumn: releasing savepoint failed. DB says: %1 - renameColumn: 释放ä¿å­˜ç‚¹æ—¶å¤±è´¥ã€‚DB 说: %1 + + Filter in any column + 过滤任何列 - - Error renaming table '%1' to '%2'.Message from database engine: -%3 - é‡å‘½å表 '%1' 为 '%2'æ—¶å¤±è´¥ã€‚æ¶ˆæ¯æ¥è‡ªæ•°æ®åº“引擎: -%3 + + Ctrl+R + + + + + %n row(s) + + %n 行 + + + + + , %n column(s) + + , %n 列 + - - ... <string can not be logged, contains binary data> ... - ... <字符串ä¸èƒ½è®°å½•,包å«äºŒè¿›åˆ¶æ•°æ®> ... + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . 求和: %1; å¹³å‡å€¼: %2; 最å°å€¼: %3; 最大值: %4 + . Sum: %1; Average: %2; Min: %3; Max: %4 - - unknown object type %1 - 未知对象类型 %1 + + Conditional formats for "%1" + "%1" çš„æ¡ä»¶æ ¼å¼ - - could not get list of db objects: %1, %2 - ä¸èƒ½èŽ·å–æ•°æ®åº“对象的列表: %1, %2 + + determining row count... + 正在决定行数... - - could not get types - ä¸èƒ½èŽ·å–类型 + + %L1 - %L2 of >= %L3 + %L1 - %L2 / 至少 %L3 - - Decoding CSV file... - æ­£åœ¨è§£ç  CSV 文件... + + %L1 - %L2 of %L3 + %L1 - %L2 / %L3 - - didn't receive any output from pragma %1 - ä¸èƒ½æŽ¥å—æ¥è‡ªæ‚注 %1 的任何输出 + + (clipped at %L1 rows) + (%L1 行的一部分) - - could not execute pragma command: %1, %2 - ä¸èƒ½æ‰§è¡Œæ‚注命令: %1, %2 + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + 请输入一个伪主键以在当å‰è§†å›¾å¯ç”¨ç¼–è¾‘ã€‚è¿™éœ€è¦æ˜¯è§†å›¾ä¸­çš„一个满足唯一性的列的å字。 - - Error setting pragma %1 to %2: %3 - è®¾ç½®æ‚æ³¨ %1 为 %2 时出错: %3 + + Delete Records + 删除记录 - - File not found. - 文件找ä¸åˆ°ã€‚ + + Duplicate records + é‡å¤è®°å½• - - - SqlExecutionArea - - Form - è¡¨å• + + Duplicate record + é‡å¤çš„记录 - - Results of the last executed statements - æœ€åŽæ‰§è¡Œè¯­å¥çš„结果 + + Ctrl+" + - - This field shows the results and status codes of the last executed statements. - è¿™ä¸ªå­—æ®µæ˜¾ç¤ºæœ€åŽæ‰§è¡Œçš„语å¥çš„结果和状æ€ç ã€‚ + + Adjust rows to contents + 按内容调整行高 - - Export to &CSV - 导出到 &CSV + + Error deleting record: +%1 + 删除记录时出错: +%1 - - Save as &view - ä¿å­˜ä¸ºè§†å›¾(&V) + + Please select a record first + 请首先选择一æ¡è®°å½• - - Save as view - ä¿å­˜ä¸ºè§†å›¾ + + Please choose a new encoding for all tables. + 请为所有表选择新的编ç ã€‚ - - Please specify the view name - 请指定视图åç§° + + Please choose a new encoding for this table. + 请为此表选择新的编ç ã€‚ - - There is already an object with that name. Please choose a different name. - 已有åŒå的对象。请选择一个ä¸åŒçš„å称。 + + %1 +Leave the field empty for using the database encoding. + %1 +留空此字段以使用数æ®åº“默认编ç ã€‚ - - View successfully created. - 视图æˆåŠŸåˆ›å»ºã€‚ + + This encoding is either not valid or not supported. + è¿™ç§ç¼–ç éžæ³•æˆ–è€…ä¸æ”¯æŒã€‚ - - Error creating view: %1 - 创建视图时出错: %1 + + %1 replacement(s) made. + 进行了 %1 次替æ¢ã€‚ - SqliteTableModel + TableBrowserDock - - Error changing data: -%1 - 更改数æ®åº“时出错: -%1 + + New Data Browser + æ–°å»ºæ•°æ®æµè§ˆå™¨ + + + + Rename Data Browser + æ›´åæ•°æ®æµè§ˆå™¨ + + + + Close Data Browser + å…³é—­æ•°æ®æµè§ˆå™¨ + + + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + è®¾å®šæ•°æ®æµè§ˆå™¨çš„æ–°å称。被“&&â€æ ‡è®°çš„字符å¯ä½œä¸ºé”®ç›˜å¿«æ·é”®çš„字符。 @@ -2049,13 +8030,13 @@ Aborting execution. - Warning: Compacting the database will commit all changes you made. - 警告: 压缩数æ®åº“将会æäº¤æ‚¨åšå‡ºçš„æ‰€æœ‰æ›´æ”¹ã€‚ + Warning: Compacting the database will commit all of your changes. + 警告: 压缩数æ®åº“会æäº¤ä½ çš„æ‰€æœ‰ä¿®æ”¹ã€‚ - Please select the objects to compact: - 请选择è¦åŽ‹ç¼©çš„å¯¹è±¡: + Please select the databases to co&mpact: + 请选择è¦åŽ‹ç¼©çš„æ•°æ®åº“(&M): diff --git a/src/translations/sqlb_zh_TW.ts b/src/translations/sqlb_zh_TW.ts index 5e25a07e9..780273d8e 100644 --- a/src/translations/sqlb_zh_TW.ts +++ b/src/translations/sqlb_zh_TW.ts @@ -1,2043 +1,8021 @@ - + AboutDialog - About SqliteBrowser - 關於 SqliteBrowser + About DB Browser for SQLite + 關於 DB Browser for SQLite - + Version 版本 - - Qt Version - Qt 版本 + + <html><head/><body><p>DB Browser for SQLite is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="https://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">https://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="https://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">https://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="https://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="https://doc.qt.io/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://doc.qt.io/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:8pt;">We use the nalgeon/sqlean library for SQLite extensions support.<br/>This library is licensed under the MIT license, see the following for more information:<br/></span><a href="https://github.com/nalgeon/sqlean"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">https://github.com/nalgeon/sqlean</span></a></p><p><span style=" font-size:small;">It also uses the Pastel SVG icon set by Michael Buckley under a Creative Commons Attribution Share Alike 4.0 license.<br/>See </span><a href="https://codefisher.org/pastel-svg/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">https://codefisher.org/pastel-svg/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> + + + + AddRecordDialog - - SQLite Version - SQLite 版本 + + Add New Record + 新增記錄 - - <html><head/><body><p>SQLite Database Browser is an open source, freeware visual tool used to create, design and edit SQLite database files.</p><p>It is bi-licensed under the Mozilla Public License Version 2, as well as the GNU General Public License Version 3 or later. You can modify or redistribute it under the conditions of these licenses.</p><p>See <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> and <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> for details.</p><p>For more information on this program please visit our website at: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">This software uses the GPL/LGPL Qt Toolkit from </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>See </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> for licensing terms and information.</span></p><p><span style=" font-size:small;">It also uses the Silk icon set by Mark James licensed under a Creative Commons Attribution 2.5 and 3.0 license.<br/>See </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> for details.</span></p></body></html> - <html><head/><body><p>SQLite Database Browser 是一個開放原始碼的å…費視覺化工具,用於建立ã€è¨­è¨ˆå’Œç·¨è¼¯ SQLite 資料庫檔案。</p><p>它是以第 2 版 Mozilla 公共許å¯ï¼Œä»¥åŠç¬¬ 3 版åŠä¹‹å¾Œç‰ˆæœ¬çš„ GNU é€šç”¨è¨±å¯æ–¹å¼æŽˆæ¬Šã€‚ä½ å¯ä»¥åœ¨éµå¾ªé€™äº›è¨±å¯çš„æ¢ä»¶ä¸‹ä¿®æ”¹æˆ–é‡æ–°ç™¼ä½ˆå®ƒã€‚</p><p>åƒé–± <a href="http://www.gnu.org/licenses/gpl.html"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/gpl.html</span></a> å’Œ <a href="https://www.mozilla.org/MPL/2.0/index.txt"><span style=" text-decoration: underline; color:#0000ff;">https://www.mozilla.org/MPL/2.0/index.txt</span></a> 瞭解細節。</p><p>è¦ç²å¾—本程å¼çš„æ›´å¤šè³‡è¨Šï¼Œè«‹è¨ªå•我們的網站: <a href="http://sqlitebrowser.org"><span style=" text-decoration: underline; color:#0000ff;">http://sqlitebrowser.org</span></a></p><p><span style=" font-size:small;">這個軟體使用了 GPL/LGPL Qt Toolkit: </span><a href="http://qt-project.org/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/</span></a><span style=" font-size:small;"><br/>åƒé–± </span><a href="http://qt-project.org/doc/qt-5/licensing.html"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://qt-project.org/doc/qt-5/licensing.html</span></a><span style=" font-size:small;"> çž­è§£è¨±å¯æ¢æ¬¾å’Œè³‡è¨Šã€‚</span></p><p><span style=" font-size:small;">它還是用了由 Mark James æä¾›çš„ Silk 圖示集,以第 2.5 å’Œ 3.0 版知識共用署å(CCA)è¨±å¯æ–¹å¼æŽˆæ¬Šã€‚<br/>åƒé–± </span><a href="http://www.famfamfam.com/lab/icons/silk/"><span style=" font-size:small; text-decoration: underline; color:#0000ff;">http://www.famfamfam.com/lab/icons/silk/</span></a><span style=" font-size:small;"> 瞭解細節。</span></p></body></html> + + Enter values for the new record considering constraints. Fields in bold are mandatory. + 輸入新記錄的值,並考慮到æ¢ä»¶ã€‚ç²—é«”çš„æ¬„ä½æ˜¯å¿…填的。 + + + + In the Value column you can specify the value for the field identified in the Name column. The Type column indicates the type of the field. Default values are displayed in the same style as NULL values. + åœ¨ã€Œå€¼ã€æ¬„ä½ä¸­ï¼Œæ‚¨å¯ä»¥ç‚ºã€Œåç¨±ã€æ¬„ä½ä¸­æŒ‡å®šçš„æ¬„使Œ‡å®šå€¼ã€‚ã€Œé¡žåž‹ã€æ¬„ä½è¡¨ç¤ºæ¬„ä½çš„類型。é è¨­å€¼ä»¥èˆ‡ NULL 值相åŒçš„æ¨£å¼é¡¯ç¤ºã€‚ + + + + Name + å稱 + + + + Type + 類型 + + + + Value + 值 + + + + Values to insert. Pre-filled default values are inserted automatically unless they are changed. + è¦æ’入的值。é å¡«çš„é è¨­å€¼æœƒè‡ªå‹•æ’入,除éžå®ƒå€‘被更改。 + + + + When you edit the values in the upper frame, the SQL query for inserting this new record is shown here. You can edit manually the query before saving. + 當您在上方框架中編輯值時,用於æ’入此新記錄的 SQL 查詢將在此處顯示。您å¯ä»¥åœ¨å„²å­˜ä¹‹å‰æ‰‹å‹•編輯查詢。 + + + + <html><head/><body><p><span style=" font-weight:600;">Save</span> will submit the shown SQL statement to the database for inserting the new record.</p><p><span style=" font-weight:600;">Restore Defaults</span> will restore the initial values in the <span style=" font-weight:600;">Value</span> column.</p><p><span style=" font-weight:600;">Cancel</span> will close this dialog without executing the query.</p></body></html> + <html><head/><body><p><span style=" font-weight:600;">儲存</span> 將會æäº¤é¡¯ç¤ºçš„ SQL 陳述å¼åˆ°è³‡æ–™åº«ä»¥æ’入新記錄。</p><p><span style=" font-weight:600;">還原é è¨­å€¼</span> 將會在 <span style=" font-weight:600;">值</span>欄ä½ä¸­é‚„原åˆå§‹å€¼ã€‚</p><p><span style=" font-weight:600;">å–æ¶ˆ</span> 將會關閉此å°è©±æ¡†ï¼Œä¸¦ä¸åŸ·è¡ŒæŸ¥è©¢ã€‚</p></body></html> - - - Application - - Usage: %1 [options] [db] + + Auto-increment - 用法: %1 [é¸é …] [資料庫] + 自動éžå¢ž - - Possible command line arguments: - å¯ç”¨å‘½ä»¤åˆ—åƒæ•¸: + + Unique constraint + + 唯一æ¢ä»¶ + + + + + Check constraint: %1 + + 檢查æ¢ä»¶ï¼š %1 + + + + + Foreign key: %1 + + 外éµï¼š %1 + + + + + Default value: %1 + + é è¨­å€¼ï¼š %1 + - - -h, --help Show command line options - -h, --help 顯示命令列é¸é … + + Error adding record. Message from database engine: + +%1 + 新增記錄時出錯。來自資料庫引擎的訊æ¯ï¼š + +%1 - - -s, --sql [file] Execute this SQL file after opening the DB - -s, --sql [檔] 在打開資料庫後執行這個 SQL 檔案 + + Are you sure you want to restore all the entered values to their defaults? + 您確定è¦å°‡æ‰€æœ‰è¼¸å…¥çš„值還原為é è¨­å€¼å—Žï¼Ÿ + + + Application - - -q, --quit Exit application after running scripts - -q, --quit åœ¨åŸ·è¡Œè…³æœ¬å¾Œé€€å‡ºæ‡‰ç”¨ç¨‹å¼ + + Possible command line arguments: + å¯ç”¨çš„å‘½ä»¤åˆ—åƒæ•¸ï¼š - - [file] Open this SQLite database - [檔] 打開這個 SQLite 資料庫 + + The user settings file location is replaced with the argument value instead of the environment variable value. + 使用者設定檔的ä½ç½®å·²è¢«åƒæ•¸å€¼å–代,而éžç’°å¢ƒè®Šæ•¸çš„值。 - - The -s/--sql option requires an argument - -s/--sql é¸é …需è¦ä¸€å€‹åƒæ•¸ + + Ignored environment variable (DB4S_SETTINGS_FILE) value: + 忽略環境變數 (DB4S_SETTINGS_FILE) 的值: - + + The file %1 does not exist 檔案 %1 ä¸å­˜åœ¨ - - Invalid option/non-existant file: %1 - 無效é¸é …/ä¸å­˜åœ¨çš„æª”案: %1 + + Usage + ä½¿ç”¨æ–¹å¼ - - - CreateIndexDialog - - Create New Index - 建立新索引 + + options + é¸é … - - &Name - å稱(&N) + + + database + 資料庫 - - &Columns - 列(&C) + + + project + 專案 - - Column - 列 + + + csv-file + CSV 檔案 - - Use in Index - 在索引中使用 + + Show command line options + 顯示命令列é¸é … - - Order - é †åº + + Exit application after running scripts + åŸ·è¡ŒæŒ‡ä»¤ç¢¼å¾Œé€€å‡ºæ‡‰ç”¨ç¨‹å¼ - - &Table - 資料表(&T) + + + file + 檔案 - - &Unique - 唯一(&U) + + Execute this SQL file after opening the DB + 開啟資料庫後執行此 SQL 檔案 - - Creating the index failed: -%1 - 建立索引時失敗: -%1 + + Import this CSV file into the passed DB or into a new DB + 將此 CSV 檔案匯入到指定的資料庫或新資料庫 + + + + table + 資料表 + + + + Browse this table, or use it as target of a data import + ç€è¦½æ­¤è³‡æ–™è¡¨ï¼Œæˆ–將其作為資料匯入的目標 + + + + Open database in read-only mode + 以唯讀模å¼é–‹å•Ÿè³‡æ–™åº« + + + + settings_file + 設定檔 + + + + Run application based on this settings file + æ ¹æ“šæ­¤è¨­å®šæª”åŸ·è¡Œæ‡‰ç”¨ç¨‹å¼ + + + + + group + 群組 + + + + + settings + 設定 + + + + + value + 值 + + + + Run application with this setting temporarily set to value + æš«æ™‚å°‡æ­¤è¨­å®šè¨­ç‚ºç‰¹å®šå€¼ä¸¦åŸ·è¡Œæ‡‰ç”¨ç¨‹å¼ + + + + Run application saving this value for this setting + å„²å­˜æ­¤è¨­å®šå€¼ä¸¦åŸ·è¡Œæ‡‰ç”¨ç¨‹å¼ + + + + Display the current version + 顯示目å‰ç‰ˆæœ¬ + + + + Open this SQLite database + 開啟此 SQLite 資料庫 + + + + Open this project file (*.sqbpro) + 開啟此專案檔案(*.sqbpro) + + + + Import this CSV file into an in-memory database + 將此 CSV 檔案匯入到記憶體內部資料庫 + + + + + + The %1 option requires an argument + %1 é¸é …需è¦ä¸€å€‹åƒæ•¸ + + + + The -S/--settings option requires an argument. The option is ignored. + -S/--settings é¸é …需è¦ä¸€å€‹åƒæ•¸ã€‚æ­¤é¸é …已被忽略。 + + + + The -o/--option and -O/--save-option options require an argument in the form group/setting=value + -o/--option å’Œ -O/--save-option é¸é …需è¦ä¸€å€‹ä»¥ group/setting=value å½¢å¼çš„åƒæ•¸ + + + + Invalid option/non-existent file: %1 + 無效é¸é …或ä¸å­˜åœ¨çš„æª”案:%1 + + + + SQLite Version + SQLite 版本 + + + + SQLCipher Version %1 (based on SQLite %2) + SQLCipher 版本 %1(基於 SQLite %2) + + + + DB Browser for SQLite Version %1. + DB Browser for SQLite 版本 %1。 + + + + Last commit hash when built: %1 + 建置時最後æäº¤çš„雜湊:%1 + + + + Built for %1, running on %2 + 為 %1 建置,執行於 %2 + + + + Qt Version %1 + Qt 版本 %1 - DbStructureModel + CipherDialog - - Name - å稱 + + SQLCipher encryption + SQLCipher 加密 - - Object - å°è±¡ + + &Password + &密碼 - - Type - 類型 + + &Reenter password + &釿–°è¼¸å…¥å¯†ç¢¼ - - Schema - æž¶æ§‹ + + Encr&yption settings + 加密設定 - - Tables (%1) - 資料表 (%1) + + SQLCipher &3 defaults + SQLCipher &3 é è¨­ - - Indices (%1) - 索引 (%1) + + SQLCipher &4 defaults + SQLCipher &4 é è¨­ - - Views (%1) - 視圖 (%1) + + Custo&m + 自訂 - - Triggers (%1) - 觸發器 (%1) + + Page si&ze + é é¢å¤§å° + + + + &KDF iterations + &KDF 迭代 + + + + HMAC algorithm + HMAC 演算法 + + + + KDF algorithm + KDF 演算法 + + + + Plaintext Header Size + ç´”æ–‡å­—æ¨™é ­å¤§å° + + + + Passphrase + 密碼 + + + + Raw key + 原始金鑰 + + + + Please set a key to encrypt the database. +Note that if you change any of the other, optional, settings you'll need to re-enter them as well every time you open the database file. +Leave the password fields empty to disable the encryption. +The encryption process might take some time and you should have a backup copy of your database! Unsaved changes are applied before modifying the encryption. + 請設定一個金鑰來加密資料庫。 +請注æ„,如果您更改了任何其他的é¸é …è¨­å®šï¼Œæ¯æ¬¡é–‹å•Ÿè³‡æ–™åº«æª”案時,您都需è¦é‡æ–°è¼¸å…¥å®ƒå€‘。 +將密碼欄ä½ç•™ç©ºä»¥åœç”¨åŠ å¯†ã€‚ +加密éŽç¨‹å¯èƒ½éœ€è¦ä¸€äº›æ™‚é–“ï¼Œæ‚¨æ‡‰è©²è¦æœ‰è³‡æ–™åº«çš„備份ï¼åœ¨ä¿®æ”¹åР坆之å‰ï¼Œæœªå„²å­˜çš„變更將會被套用。 + + + + Please enter the key used to encrypt the database. +If any of the other settings were altered for this database file you need to provide this information as well. + 請輸入用於加密資料庫的金鑰。 +å¦‚æžœæ­¤è³‡æ–™åº«æª”æ¡ˆçš„ä»»ä½•å…¶ä»–è¨­å®šå·²è¢«æ›´æ”¹ï¼Œæ‚¨ä¹Ÿéœ€è¦æä¾›é€™äº›è³‡è¨Šã€‚ - EditDialog + ColumnDisplayFormatDialog - - Edit database cell - 編輯資料庫儲存格 + + Choose display format + 鏿“‡é¡¯ç¤ºæ ¼å¼ - - Import text - 匯入純文字檔案 + + Display format + é¡¯ç¤ºæ ¼å¼ - - Opens a file dialog used to import text to this database cell. - 打開一個檔å°è©±æ–¹å¡Šç”¨æ–¼åŒ¯å…¥ç´”文字檔案到這個資料庫儲存格。 + + Choose a display format for the column '%1' which is applied to each value prior to showing it. + 鏿“‡æ¬„ä½ '%1' 的顯示格å¼ï¼Œè©²æ ¼å¼å°‡åœ¨é¡¯ç¤ºæ¯å€‹å€¼ä¹‹å‰å¥—用。 - - &Import - 匯入(&I) + + Default + é è¨­ - - Export text - 匯出純文字檔案 + + Decimal number + å進使•¸å­— - - Opens a file dialog used to export the contents of this database cell to a text file. - 打開一個檔å°è©±æ–¹å¡Šç”¨æ–¼åŒ¯å‡ºé€™å€‹è³‡æ–™åº«å„²å­˜æ ¼çš„內容到一個文字檔案。 + + Exponent notation + 指數表示法 - - &Export - 匯出(&E) + + Hex blob + å六進ä½åˆ¶ BLOB - - Text - 純文字檔案 + + Hex number + å六進使•¸å­— - - Binary - äºŒé€²ä½ + + Apple NSDate to date + Apple NSDate 轉æ›ç‚ºæ—¥æœŸ - - Clear cell data - 清除儲存格資料 + + Java epoch (milliseconds) to date + Java epoch (毫秒)轉æ›ç‚ºæ—¥æœŸ - - Erases the contents of the cell - 刪除儲存格的內容 + + .NET DateTime.Ticks to date + .NET DateTime.Ticks 轉æ›ç‚ºæ—¥æœŸ - - &Clear - 清除(&C) + + Julian day to date + 儒略日轉æ›ç‚ºæ—¥æœŸ - - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">Warning: Editing binary content in text mode may result in corrupted data!</span></p></body></html> - <html><head/><body><p><span style=" font-weight:600; color:#c00000;">警告: 在文字模å¼ä¸­ç·¨è¼¯äºŒé€²ä½å…§å®¹å¯èƒ½æœƒå°Žè‡´è³‡æ–™æå£ž!</span></p></body></html> + + Unix epoch to local time + Unix epoch 轉æ›ç‚ºæœ¬åœ°æ™‚é–“ - - This area displays information about the data present in this database cell - 這個å€åŸŸé¡¯ç¤ºå­˜åœ¨æ–¼é€™å€‹è³‡æ–™åº«å„²å­˜æ ¼ä¸­çš„資料的相關資訊 + + WebKit / Chromium epoch to date + - - Type of data currently in cell - ç›®å‰åœ¨å„²å­˜æ ¼ä¸­çš„資料的類型 + + WebKit / Chromium epoch to local time + - - Size of data currently in table - ç›®å‰åœ¨è³‡æ–™è¡¨ä¸­çš„è³‡æ–™çš„å¤§å° + + Date as dd/mm/yyyy + 日期格å¼ç‚º dd/mm/yyyy - - Choose a file - 鏿“‡ä¸€å€‹æª”案 + + Lower case + å°å¯« - - Text files(*.txt);;Image files(%1);;All files(*) - 文字檔案(*.txt);;å½±åƒæª”案(%1);;所有擋檔案(*) + + Binary GUID to text + 二進ä½åˆ¶ GUID 轉æ›ç‚ºæ–‡å­— - - Choose a filename to export data - 鏿“‡ä¸€å€‹åŒ¯å‡ºè³‡æ–™çš„æª”案å稱 + + SpatiaLite Geometry to SVG + SpatiaLite 幾何資料轉 SVG - - Text files(*.txt);;All files(*) - 文字檔案(*.txt);;所有擋檔案(*) + + Custom display format must contain a function call applied to %1 + 自訂顯示格å¼å¿…須包å«å¥—用於 %1 的函å¼å‘¼å« - - Type of data currently in cell: Text / Numeric - ç›®å‰åœ¨å„²å­˜æ ¼ä¸­çš„資料的類型: Text 純文字檔案/ Numeric 數值 + + Error in custom display format. Message from database engine: + +%1 + 自訂顯示格å¼éŒ¯èª¤ã€‚來自資料庫引擎的訊æ¯ï¼š + +%1 - - - %n char(s) - - %n 個字元 - + + + Custom display format must return only one column but it returned %1. + 自訂顯示格å¼åªèƒ½å›žå‚³ä¸€å€‹æ¬„ä½ï¼Œä½†å®ƒå›žå‚³äº† %1。 - - Type of data currently in cell: Image - ç›®å‰åœ¨å„²å­˜æ ¼ä¸­çš„資料的類型: Image åœ–åƒ + + Octal number + 八進使•¸å­— - - %1x%2 pixel - %1x%2 圖元 + + Round number + å››æ¨äº”入數字 - - Type of data currently in cell: Binary - ç›®å‰åœ¨å„²å­˜æ ¼ä¸­çš„資料的類型: Binary äºŒé€²ä½ + + Unix epoch to date + Unix epoch 轉æ›ç‚ºæ—¥æœŸ - - - %n byte(s) - - %n ä½å…ƒçµ„ - + + + Upper case + 大寫 + + + + Windows DATE to date + Windows DATE 轉æ›ç‚ºæ—¥æœŸ + + + + Custom + 自訂 - EditTableDialog + CondFormatManager + + + Conditional Format Manager + æ¢ä»¶æ ¼å¼ç®¡ç†å™¨ + + + + This dialog allows creating and editing conditional formats. Each cell style will be selected by the first accomplished condition for that cell data. Conditional formats can be moved up and down, where those at higher rows take precedence over those at lower. Syntax for conditions is the same as for filters and an empty condition applies to all values. + æ­¤å°è©±æ¡†å…許建立和編輯æ¢ä»¶æ ¼å¼ã€‚æ¯å€‹å„²å­˜æ ¼æ¨£å¼å°‡ç”±è©²å„²å­˜æ ¼è³‡æ–™çš„第一個符åˆçš„æ¢ä»¶é¸å®šã€‚æ¢ä»¶æ ¼å¼å¯ä»¥ä¸Šä¸‹ç§»å‹•,其中較高行的優先權高於較低行的。æ¢ä»¶çš„語法與篩é¸å™¨çš„語法相åŒï¼Œç©ºæ¢ä»¶é©ç”¨æ–¼ä¸¦ä¸”空的æ¢ä»¶é©ç”¨æ–¼æ‰€æœ‰å€¼æ‰€æœ‰å€¼ã€‚ + + + + Add new conditional format + 新增æ¢ä»¶æ ¼å¼ + + + + &Add + &新增 + + + + Remove selected conditional format + 移除é¸å®šçš„æ¢ä»¶æ ¼å¼ + + + + &Remove + &移除 + + + + Move selected conditional format up + 上移é¸å®šçš„æ¢ä»¶æ ¼å¼ + + + + Move &up + å‘上移動 + + + + Move selected conditional format down + 下移é¸å®šçš„æ¢ä»¶æ ¼å¼ + + + + Move &down + å‘下移動 + + + + Foreground + 剿™¯ + + + + Text color + 文字é¡è‰² + + + + Background + 背景 + + + + Background color + 背景é¡è‰² + + + + Font + å­—åž‹ + + + + Size + å¤§å° + + + + Bold + ç²—é«” + + + + Italic + 斜體 + + + + Underline + 底線 + + + + Alignment + å°é½Š + + + + Condition + æ¢ä»¶ + + + + + Click to select color + 點é¸ä»¥é¸æ“‡é¡è‰² + + + + Are you sure you want to clear all the conditional formats of this field? + æ‚¨ç¢ºå®šè¦æ¸…除此欄ä½çš„æ‰€æœ‰æ¢ä»¶æ ¼å¼å—Žï¼Ÿ + + + + DBBrowserDB + + + Please specify the database name under which you want to access the attached database + 請指定您è¦å­˜å–附加資料庫的資料庫å稱 + + + + Invalid file format + ç„¡æ•ˆçš„æª”æ¡ˆæ ¼å¼ + + + + Do you want to save the changes made to the database file %1? + æ‚¨æ˜¯å¦æƒ³å„²å­˜å°è³‡æ–™åº«æª”案 %1 åšå‡ºçš„修改? + + + + Exporting database to SQL file... + 正在匯出資料庫到 SQL 檔案... + + + + + Cancel + å–æ¶ˆ + + + + Executing SQL... + 正在執行 SQL... + + + + Action cancelled. + æ“ä½œå·²å–æ¶ˆã€‚ + + + + Do you really want to close this temporary database? All data will be lost. + 您確定è¦é—œé–‰æ­¤è‡¨æ™‚資料庫嗎?所有資料將會éºå¤±ã€‚ + + + + Database didn't close correctly, probably still busy + 資料庫未正確關閉,å¯èƒ½ä»åœ¨å¿™ç¢Œä¸­ + + + + Cannot open destination file: '%1' + 無法開啟目標檔案:'%1' + + + + + Cannot backup to file: '%1'. Message: %2 + 無法備份到檔案:'%1'。訊æ¯ï¼š%2 + + + + The database is currently busy: + 資料庫目å‰å¿™ç¢Œä¸­ï¼š + + + + Do you want to abort that other operation? + 您是å¦è¦ä¸­æ­¢å…¶ä»–æ“作? + + + + + No database file opened + 沒有開啟的資料庫檔案 + + + + + Error in statement #%1: %2. +Aborting execution%3. + é™³è¿°å¼ #%1 中的錯誤:%2。 +正在中止執行%3。 + + + + + and rolling back + 並正在回滾 + + + + didn't receive any output from %1 + 未從 %1 收到任何輸出 + + + + could not execute command: %1 + 無法執行命令:%1 + + + + Cannot delete this object + 無法刪除此物件 + + + + Cannot set data on this object + 無法在此物件上設定資料 + + + + + A table with the name '%1' already exists in schema '%2'. + åœ¨çµæ§‹ '%2' 中已存在å為 '%1' 的資料表。 + + + + No table with name '%1' exists in schema '%2'. + åœ¨çµæ§‹ '%2' 中ä¸å­˜åœ¨å為 '%1' 的資料表。 + + + + + Cannot find column %1. + 找ä¸åˆ°åˆ— %1。 + + + + Creating savepoint failed. DB says: %1 + 建立儲存點失敗。資料庫顯示:%1 + + + + Renaming the column failed. DB says: +%1 + 釿–°å‘½å欄ä½å¤±æ•—。資料庫顯示: +%1 + + + + + Releasing savepoint failed. DB says: %1 + 釋放儲存點失敗。資料庫顯示:%1 + + + + Creating new table failed. DB says: %1 + 建立新資料表失敗。資料庫顯示:%1 + + + + Copying data to new table failed. DB says: +%1 + 複製資料到新資料表失敗。資料庫顯示: +%1 + + + + Deleting old table failed. DB says: %1 + 刪除舊資料表失敗。資料庫顯示:%1 + + + + Error renaming table '%1' to '%2'. +Message from database engine: +%3 + 將資料表 '%1' 釿–°å‘½å為 '%2' 時出ç¾éŒ¯èª¤ã€‚ +來自資料庫引擎的訊æ¯ï¼š +%3 + + + + could not get list of db objects: %1 + 無法å–得資料庫物件的列表:%1 + + + + Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: + + + 還原æŸäº›å’Œé€™å€‹è³‡æ–™è¡¨é—œè¯çš„物件失敗。這個最å¯èƒ½æ˜¯å› ç‚ºæŸäº›åˆ—çš„å稱修改了。這裡是您å¯èƒ½éœ€è¦æ‰‹å‹•修復和執行的 SQL 陳述å¼: + + + + + + could not get list of databases: %1 + 無法å–得資料庫的列表:%1 + + + + Error loading extension: %1 + 載入擴充套件時出ç¾éŒ¯èª¤: %1 + + + + Error loading built-in extension: %1 + + + + + could not get column information + 無法å–得列資訊 + + + + Error setting pragma %1 to %2: %3 + 設定 pragma %1 為 %2 時出ç¾éŒ¯èª¤: %3 + + + + File not found. + 找ä¸åˆ°æª”案。 + + + + DbStructureModel + + + Name + å稱 + + + + Object + 物件 + + + + Type + 類型 + + + + Schema + çµæ§‹ + + + + Database + 資料庫 + + + + Browsables + å¯ç€è¦½çš„ + + + + All + 全部 + + + + Temporary + 臨時的 + + + + Tables (%1) + 資料表 (%1) + + + + Indices (%1) + 索引 (%1) + + + + Views (%1) + 檢視表 (%1) + + + + Triggers (%1) + 觸發器 (%1) + + + + EditDialog + + + Edit database cell + 編輯資料庫儲存格 + + + + Mode: + 模å¼ï¼š + + + + This is the list of supported modes for the cell editor. Choose a mode for viewing or editing the data of the current cell. + 這是儲存格編輯器支æ´çš„æ¨¡å¼åˆ—è¡¨ã€‚é¸æ“‡ä¸€ç¨®æ¨¡å¼ä¾†æª¢è¦–或編輯目å‰å„²å­˜æ ¼çš„資料。 + + + + RTL Text + 從å³åˆ°å·¦çš„æ–‡å­— + + + + + Image + 圖片 + + + + JSON + JSON + + + + XML + XML + + + + Evaluation + è©•ä¼° + + + + + Automatically adjust the editor mode to the loaded data type + 自動調整編輯器模å¼ä»¥é©æ‡‰è¼‰å…¥çš„資料類型 + + + + This checkable button enables or disables the automatic switching of the editor mode. When a new cell is selected or new data is imported and the automatic switching is enabled, the mode adjusts to the detected data type. You can then change the editor mode manually. If you want to keep this manually switched mode while moving through the cells, switch the button off. + 這個å¯é¸æ“‡çš„æŒ‰éˆ•å¯ä»¥å•Ÿç”¨æˆ–åœç”¨ç·¨è¼¯å™¨æ¨¡å¼çš„自動切æ›ã€‚ç•¶é¸æ“‡æ–°çš„å„²å­˜æ ¼æˆ–åŒ¯å…¥æ–°çš„è³‡æ–™ä¸¦å•Ÿç”¨è‡ªå‹•åˆ‡æ›æ™‚,模å¼å°‡èª¿æ•´ç‚ºæª¢æ¸¬åˆ°çš„資料類型。您å¯ä»¥æ‰‹å‹•更改編輯器模å¼ã€‚å¦‚æžœæ‚¨å¸Œæœ›åœ¨ç§»å‹•å„²å­˜æ ¼æ™‚ä¿æŒé€™ç¨®æ‰‹å‹•切æ›çš„æ¨¡å¼ï¼Œè«‹åˆ‡æ›æŒ‰éˆ•至關閉狀態。 + + + + Auto-switch + è‡ªå‹•åˆ‡æ› + + + + This Qt editor is used for right-to-left scripts, which are not supported by the default Text editor. The presence of right-to-left characters is detected and this editor mode is automatically selected. + 這個 Qt 編輯器用於從å³åˆ°å·¦çš„腳本,這些腳本ä¸è¢«é è¨­çš„æ–‡å­—編輯器支æ´ã€‚檢測到從å³åˆ°å·¦çš„å­—å…ƒæ™‚ï¼Œå°‡è‡ªå‹•é¸æ“‡æ­¤ç·¨è¼¯å™¨æ¨¡å¼ã€‚ + + + + Identification of the cell currently in the editor + ç›®å‰åœ¨ç·¨è¼¯å™¨ä¸­çš„儲存格識別資訊 + + + + Type and size of data currently in table + ç›®å‰è¡¨æ ¼ä¸­çš„è³‡æ–™é¡žåž‹å’Œå¤§å° + + + + Open preview dialog for printing the data currently stored in the cell + 開啟é è¦½å°è©±æ¡†ä»¥åˆ—å°ç›®å‰å„²å­˜åœ¨å„²å­˜æ ¼ä¸­çš„資料 + + + + Auto-format: pretty print on loading, compact on saving. + 自動格å¼åŒ–:載入時進行美觀列å°ï¼Œå„²å­˜æ™‚進行壓縮。 + + + + When enabled, the auto-format feature formats the data on loading, breaking the text in lines and indenting it for maximum readability. On data saving, the auto-format feature compacts the data removing end of lines, and unnecessary whitespace. + 當啟用時,自動格å¼åŒ–功能會在載入時格å¼åŒ–資料,將文字分æˆè¡Œä¸¦ç¸®æŽ’以ç²å¾—最大的å¯è®€æ€§ã€‚在儲存資料時,自動格å¼åŒ–功能會壓縮資料,移除行尾和ä¸å¿…è¦çš„空白。 + + + + Word Wrap + 自動æ›è¡Œ + + + + Wrap lines on word boundaries + 在單詞邊界æ›è¡Œ + + + + + Open in default application or browser + 在é è¨­æ‡‰ç”¨ç¨‹å¼æˆ–ç€è¦½å™¨ä¸­é–‹å•Ÿ + + + + Open in application + 在應用程å¼ä¸­é–‹å•Ÿ + + + + The value is interpreted as a file or URL and opened in the default application or web browser. + 該值被解釋為檔案或 URL 並在é è¨­æ‡‰ç”¨ç¨‹å¼æˆ–ç¶²é ç€è¦½å™¨ä¸­é–‹å•Ÿã€‚ + + + + Save file reference... + 儲存檔案åƒè€ƒ... + + + + Save reference to file + 儲存到檔案的åƒè€ƒ + + + + + Open in external application + 在外部應用程å¼ä¸­é–‹å•Ÿ + + + + Autoformat + 自動格å¼åŒ– + + + + &Export... + &匯出... + + + + + &Import... + &匯入... + + + + + Import from file + 從檔案匯入 + + + + + Opens a file dialog used to import any kind of data to this database cell. + 開啟一個檔案å°è©±æ¡†ï¼Œç”¨æ–¼å°‡ä»»ä½•類型的資料匯入到這個資料庫儲存格。 + + + + Export to file + 匯出到檔案 + + + + Opens a file dialog used to export the contents of this database cell to a file. + 開啟一個檔案å°è©±æ¡†ï¼Œç”¨æ–¼å°‡é€™å€‹è³‡æ–™åº«å„²å­˜æ ¼çš„內容匯出到一個檔案。 + + + + Print... + 列å°... + + + + Ctrl+P + Ctrl+P + + + + Open preview dialog for printing displayed text + 開啟é è¦½å°è©±æ¡†ä»¥åˆ—å°é¡¯ç¤ºçš„æ–‡å­— + + + + Copy Hex and ASCII + 複製å六進ä½å’Œ ASCII + + + + Copy selected hexadecimal and ASCII columns to the clipboard + 將鏿“‡çš„å六進ä½å’Œ ASCII 列複製到剪貼簿 + + + + Ctrl+Shift+C + Ctrl+Shift+C + + + + Set as &NULL + 設為 &NULL + + + + Apply data to cell + 將資料套用到儲存格 + + + + This button saves the changes performed in the cell editor to the database cell. + 此按鈕將在儲存格編輯器中進行的更改儲存到資料庫儲存格。 + + + + Apply + 套用 + + + + Text + 純文字檔案 + + + + Binary + äºŒé€²ä½ + + + + Erases the contents of the cell + 刪除儲存格的內容 + + + + This area displays information about the data present in this database cell + 這個å€åŸŸé¡¯ç¤ºå­˜åœ¨æ–¼é€™å€‹è³‡æ–™åº«å„²å­˜æ ¼ä¸­çš„資料的相關資訊 + + + + Choose a filename to export data + 鏿“‡ä¸€å€‹åŒ¯å‡ºè³‡æ–™çš„æª”案å稱 + + + + + Image data can't be viewed in this mode. + 此模å¼ä¸‹ç„¡æ³•檢視圖片資料。 + + + + + Try switching to Image or Binary mode. + 嘗試切æ›åˆ°åœ–ç‰‡æˆ–äºŒé€²ä½æ¨¡å¼ã€‚ + + + + + Binary data can't be viewed in this mode. + 此模å¼ä¸‹ç„¡æ³•檢視二進ä½è³‡æ–™ã€‚ + + + + + Try switching to Binary mode. + 嘗試切æ›åˆ°äºŒé€²ä½æ¨¡å¼ã€‚ + + + + + Image files (%1) + 圖片檔案 (%1) + + + + Binary files (*.bin) + äºŒé€²ä½æª”案 (*.bin) + + + + + Type: NULL; Size: 0 bytes + 類型:NULL;大å°ï¼š0 ä½å…ƒçµ„ + + + + + Type: Text / Numeric; Size: %n character(s) + + 類型:文字 / 數值;大å°ï¼š%n å­—å…ƒ + + + + + Type: %1 Image; Size: %2x%3 pixel(s) + 類型:%1 圖片;大å°ï¼š%2x%3 åƒç´  + + + + Type: Valid JSON; Size: %n character(s) + + 類型:有效的 JSON;大å°ï¼š%n å­—å…ƒ + + + + + Type: Binary; Size: %n byte(s) + + 類型:二進ä½ï¼›å¤§å°ï¼š%n ä½å…ƒçµ„ + + + + + Couldn't save file: %1. + 無法儲存檔案:%1。 + + + + The data has been saved to a temporary file and has been opened with the default application. You can now edit the file and, when you are ready, apply the saved new data to the cell or cancel any changes. + 資料已被儲存到臨時檔案並已用é è¨­æ‡‰ç”¨ç¨‹å¼é–‹å•Ÿã€‚您ç¾åœ¨å¯ä»¥ç·¨è¼¯æª”æ¡ˆï¼Œæº–å‚™å¥½å¾Œï¼Œå°‡å„²å­˜çš„æ–°è³‡æ–™å¥—ç”¨åˆ°å„²å­˜æ ¼æˆ–å–æ¶ˆä»»ä½•更改。 + + + + Choose a file to import + 鏿“‡ä¸€å€‹è¦åŒ¯å…¥çš„æª”案 + + + + The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + +In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell. + 文字編輯器模å¼è®“您å¯ä»¥ç·¨è¼¯ç´”文字,以åŠå…·æœ‰èªžæ³•高亮ã€è‡ªå‹•æ ¼å¼åŒ–和儲存å‰é©—證的 JSON 或 XML 資料。 + +在評估模å¼ä¸­ï¼Œè¼¸å…¥çš„ SQLite 表é”弿œƒè¢«è©•ä¼°ï¼Œä¸¦å°‡çµæžœå¥—用至該儲存格。 + + + + Unsaved data in the cell editor + 儲存格編輯器中有未儲存的資料 + + + + The cell editor contains data not yet applied to the database. +Do you want to apply the edited data to row=%1, column=%2? + 儲存格編輯器內å«å°šæœªå¥—用至資料庫的資料。 +æ‚¨æ˜¯å¦æƒ³å°‡ç·¨è¼¯éŽçš„資料套用到第 %1 行,第 %2 列? + + + + Editing row=%1, column=%2 + 正在編輯第 %1 行,第 %2 列 + + + + No cell active. + 沒有活動的儲存格。 + + + + %1 Image + %1 圖片 + + + + Invalid data for this mode + 此模å¼çš„資料無效 + + + + The cell contains invalid %1 data. Reason: %2. Do you really want to apply it to the cell? + 儲存格包å«ç„¡æ•ˆçš„ %1 資料。原因:%2。您確實è¦å°‡å…¶å¥—用到儲存格嗎? + + + + EditIndexDialog + + + &Name + å稱(&N) + + + + Order + é †åº + + + + &Table + 資料表(&T) + + + + Edit Index Schema + ç·¨è¼¯ç´¢å¼•çµæ§‹ + + + + &Unique + 唯一(&U) + + + + For restricting the index to only a part of the table you can specify a WHERE clause here that selects the part of the table that should be indexed + è‹¥è¦å°‡ç´¢å¼•é™åˆ¶ç‚ºè³‡æ–™è¡¨çš„一部分,您å¯ä»¥åœ¨æ­¤æŒ‡å®š WHERE å­å¥ï¼Œé¸æ“‡æ‡‰è©²è¢«ç´¢å¼•的資料表部分 + + + + Partial inde&x clause + 部分索引å­å¥(&X) + + + + Colu&mns + 欄ä½(&M) + + + + Table column + è³‡æ–™è¡¨æ¬„ä½ + + + + Type + 類型 + + + + Add a new expression column to the index. Expression columns contain SQL expression rather than column names. + å‘索引新增新的表é”弿¬„ä½ã€‚表é”弿¬„ä½åŒ…å« SQL 表é”å¼ï¼Œè€Œä¸æ˜¯æ¬„ä½å稱。 + + + + Index column + ç´¢å¼•æ¬„ä½ + + + + Deleting the old index failed: +%1 + 刪除舊索引失敗: +%1 + + + + Creating the index failed: +%1 + 建立索引失敗: +%1 + + + + EditTableDialog + + + Edit table definition + 編輯資料表定義 + + + + Table + 資料表 + + + + Advanced + 進階 + + + + Without Rowid + ç„¡ Rowid + + + + Database sche&ma + è³‡æ–™åº«çµæ§‹(&M) + + + + Make this a 'WITHOUT ROWID' table. Setting this flag requires specifying a PRIMARY KEY (which can be of any type, and can be composite), and forbids the AUTOINCREMENT flag. + + + + + On Conflict + è¡çªæ™‚ + + + + Strict + åš´æ ¼æ¨¡å¼ + + + + When the strict option is enabled SQLite enforces the data types of each column when updating or inserting data. + 啟用嚴格模å¼å¾Œï¼ŒSQLite 在更新或æ’入資料時會強制執行æ¯ä¸€æ¬„ä½çš„資料型態。 + + + + Fields + æ¬„ä½ + + + + + + Add + 新增 + + + + + + Remove + 移除 + + + + Move to top + 移至頂端 + + + + Move up + 上移 + + + + Move down + 下移 + + + + Move to bottom + 移至底端 + + + + + + + Name + å稱 + + + + + Type + 類型 + + + + NN + NN + + + + Not null + éžç©º + + + + PK + PK + + + + <html><head/><body><p><img src=":/icons/field_key"/> Primary key</p></body></html> + <html><head/><body><p><img src=":/icons/field_key"/> 主éµ</p></body></html> + + + + AI + AI + + + + Autoincrement + 自動éžå¢ž + + + + U + U + + + + + + Unique + 唯一 + + + + Default + é è¨­ + + + + Default value + é è¨­å€¼ + + + + + Check + 檢查 + + + + Check constraint + 檢查æ¢ä»¶ + + + + Collation + 定åºè¦å‰‡ + + + + Foreign Key + å¤–éµ + + + + <html><head/><body><p><img src=":/icons/field_fk"/> Foreign Key</p></body></html> + <html><head/><body><p><img src=":/icons/field_fk"/> 外éµ</p></body></html> + + + + Index Constraints + 索引æ¢ä»¶ç´„æŸ + + + + Add constraint + 新增æ¢ä»¶ + + + + Remove constraint + 移除æ¢ä»¶ + + + + + Columns + æ¬„ä½ + + + + + + SQL + SQL + + + + Foreign Keys + å¤–éµ + + + + References + åƒç…§ + + + + Check Constraints + 檢查æ¢ä»¶ç´„æŸ + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">Warning: </span>There is something with this table definition that our parser doesn't fully understand. Modifying and saving this table might result in problems.</p></body></html> + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">警告:</span>我們的解æžå™¨ç„¡æ³•完全ç†è§£æ­¤è³‡æ–™è¡¨å®šç¾©çš„æŸäº›å…§å®¹ã€‚ä¿®æ”¹ä¸¦å„²å­˜æ­¤è³‡æ–™è¡¨å¯èƒ½æœƒå°Žè‡´å•題。</p></body></html> + + + + + Primary Key + ä¸»éµ + + + + Add a primary key constraint + æ–°å¢žä¸»éµæ¢ä»¶ + + + + Add a unique constraint + 新增唯一æ¢ä»¶ + + + + Error creating table. Message from database engine: +%1 + 建立資料表時出ç¾éŒ¯èª¤ã€‚來自資料庫引擎的訊æ¯: +%1 + + + + There already is a field with that name. Please rename it first or choose a different name for this field. + 已經存在具有該å稱的欄ä½ã€‚è«‹å…ˆé‡æ–°å‘½å它或為此欄ä½é¸æ“‡ä¸€å€‹ä¸åŒçš„å稱。 + + + + There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. + 至少有一行將此欄ä½è¨­å®šç‚º NULL。這使得它無法設定此標記。請先修改資料表資料。 + + + + There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. + 至少有一行在此欄ä½ä¸­å…·æœ‰éžæ•´æ•¸å€¼ã€‚這使得它無法設定 AI 標記。請先修改資料表資料。 + + + + Column '%1' has duplicate data. + + æ¬„ä½ '%1' 有é‡è¤‡çš„資料。 + + + + + This makes it impossible to enable the 'Unique' flag. Please remove the duplicate data, which will allow the 'Unique' flag to then be enabled. + 這使得無法啟用 '唯一' 標記。請移除é‡è¤‡çš„資料,這將å…許然後啟用 '唯一' 標記。 + + + + Please add a field which meets the following criteria before setting the on conflict action: + - Primary key flag set + 在設定è¡çªæ™‚的動作之å‰ï¼Œè«‹æ–°å¢žä¸€å€‹ç¬¦åˆä»¥ä¸‹æ¢ä»¶çš„æ¬„ä½ï¼š + - å·²è¨­å®šä¸»éµæ¨™è¨˜ + + + + This column is referenced in a foreign key in table %1 and thus its name cannot be changed. + 此欄ä½åœ¨è³‡æ–™è¡¨ %1 的外éµä¸­è¢«å¼•用,因此其å稱無法更改。 + + + + + There can only be one primary key for each table. Please modify the existing primary key instead. + æ¯å€‹è³‡æ–™è¡¨åªèƒ½æœ‰ä¸€å€‹ä¸»éµã€‚è«‹æ”¹ç‚ºä¿®æ”¹ç¾æœ‰çš„主éµã€‚ + + + + Are you sure you want to delete the field '%1'? +All data currently stored in this field will be lost. + 您確定è¦åˆªé™¤æ¬„ä½ '%1' 嗎? +ç›®å‰å„²å­˜åœ¨æ­¤æ¬„ä½ä¸­çš„æ‰€æœ‰è³‡æ–™å°‡æœƒéºå¤±ã€‚ + + + + Please add a field which meets the following criteria before setting the without rowid flag: + - Primary key flag set + - Auto increment disabled + 在設定 without rowid 標記之å‰ï¼Œè«‹æ–°å¢žæ»¿è¶³ä»¥ä¸‹æ¢ä»¶çš„æ¬„ä½ï¼š + - è¨­å®šä¸»éµæ¨™è¨˜ + - åœç”¨è‡ªå‹•éžå¢ž + + + + ExportDataDialog + + + Export data as CSV + 將資料匯出為 CSV + + + + Tab&le(s) + 資料表(&L) + + + + Colu&mn names in first line + 在第一行中的欄ä½å稱(&M) + + + + Fie&ld separator + 欄ä½åˆ†éš”符號(&L) + + + + , + , + + + + ; + ; + + + + Tab + Tab + + + + | + | + + + + + + Other + 其它 + + + + &Quote character + 引號字元(&Q) + + + + " + " + + + + ' + ' + + + + New line characters + æ›è¡Œå­—å…ƒ + + + + Windows: CR+LF (\r\n) + Windows:CR+LF (\r\n) + + + + Unix: LF (\n) + Unix:LF (\n) + + + + Pretty print + ç¾Žè§€åˆ—å° + + + + + Could not open output file: %1 + 無法開啟輸出檔案:%1 + + + + + Choose a filename to export data + 鏿“‡ä¸€å€‹åŒ¯å‡ºè³‡æ–™çš„æª”案å稱 + + + + Export data as JSON + 將資料匯出為 JSON + + + + exporting CSV + 正在匯出 CSV + + + + + Error while writing the file '%1': %2 + 寫入檔案 '%1' 時發生錯誤:%2 + + + + exporting JSON + 正在匯出 JSON + + + + Please select at least 1 table. + è«‹è‡³å°‘é¸æ“‡ 1 個資料表。 + + + + Choose a directory + 鏿“‡ä¸€å€‹ç›®éŒ„ + + + + Export completed. + 匯出完æˆã€‚ + + + + Export finished with errors. + 匯出完æˆï¼Œä½†éŽç¨‹ä¸­æœ‰éŒ¯èª¤ã€‚ + + + + ExportSqlDialog + + + Export SQL... + 匯出 SQL... + + + + Tab&le(s) + 資料表(&L) + + + + Select All + å…¨é¸ + + + + Deselect All + å–æ¶ˆå…¨é¸ + + + + &Options + é¸é …(&O) + + + + Keep column names in INSERT INTO + 在 INSERT INTO 中ä¿ç•™æ¬„ä½å稱 + + + + Multiple rows (VALUES) per INSERT statement + æ¯å€‹ INSERT 陳述å¼ä¸­åŒ…å«å¤šå€‹è³‡æ–™åˆ—(VALUES) + + + + Export everything + 匯出全部 + + + + Export schema only + åƒ…åŒ¯å‡ºçµæ§‹ + + + + Export data only + 僅匯出資料 + + + + Keep original CREATE statements + ä¿ç•™åŽŸå§‹çš„ CREATE é™³è¿°å¼ + + + + Keep old schema (CREATE TABLE IF NOT EXISTS) + ä¿ç•™èˆŠçµæ§‹ï¼ˆCREATE TABLE IF NOT EXISTS) + + + + Overwrite old schema (DROP TABLE, then CREATE TABLE) + è¦†è“‹èˆŠçµæ§‹ï¼ˆDROP TABLE,然後 CREATE TABLE) + + + + Please select at least one table. + è«‹è‡³å°‘é¸æ“‡ä¸€å€‹è³‡æ–™è¡¨ã€‚ + + + + Choose a filename to export + 鏿“‡è¦åŒ¯å‡ºçš„æª”案å稱 + + + + Export completed. + 匯出完æˆã€‚ + + + + Export cancelled or failed. + åŒ¯å‡ºå–æ¶ˆæˆ–失敗。 + + + + ExtendedScintilla + + + + Ctrl+H + Ctrl+H + + + + Ctrl+F + Ctrl+F + + + + + Ctrl+P + Ctrl+P + + + + Find... + 尋找... + + + + Find and Replace... + 尋找和å–代... + + + + Print... + 列å°... + + + + ExtendedTableWidget + + + Use as Exact Filter + 作為精確篩é¸ä½¿ç”¨ + + + + Containing + åŒ…å« + + + + Not containing + ä¸åŒ…å« + + + + Not equal to + ä¸ç­‰æ–¼ + + + + Greater than + 大於 + + + + Less than + å°æ–¼ + + + + Greater or equal + 大於或等於 + + + + Less or equal + å°æ–¼æˆ–等於 + + + + Between this and... + 介於此和... + + + + Regular expression + æ­£è¦è¡¨é”å¼ + + + + Edit Conditional Formats... + 編輯æ¢ä»¶æ ¼å¼... + + + + Set to NULL + 設定為 NULL + + + + Cut + 剪下 + + + + Copy + 複製 + + + + Copy with Headers + é€£åŒæ¨™é ­è¤‡è£½ + + + + Copy as SQL + 複製為 SQL + + + + Paste + 貼上 + + + + Print... + 列å°... + + + + Use in Filter Expression + 在篩é¸è¡¨é”å¼ä¸­ä½¿ç”¨ + + + + Alt+Del + Alt+Del + + + + Ctrl+Shift+C + Ctrl+Shift+C + + + + Ctrl+Alt+C + Ctrl+Alt+C + + + + The content of the clipboard is bigger than the range selected. +Do you want to insert it anyway? + 剪貼簿的內容大於所é¸çš„範åœã€‚ +您ä»ç„¶è¦æ’入嗎? + + + + <p>Not all data has been loaded. <b>Do you want to load all data before selecting all the rows?</b><p><p>Answering <b>No</b> means that no more data will be loaded and the selection will not be performed.<br/>Answering <b>Yes</b> might take some time while the data is loaded but the selection will be complete.</p>Warning: Loading all the data might require a great amount of memory for big tables. + <p>並未載入所有資料。<b>您是å¦è¦åœ¨é¸æ“‡æ‰€æœ‰è¡Œä¹‹å‰è¼‰å…¥æ‰€æœ‰è³‡æ–™ï¼Ÿ</b><p><p>回答 <b>å¦</b> 表示將ä¸å†è¼‰å…¥æ›´å¤šè³‡æ–™ï¼Œä¸¦ä¸”䏿œƒé€²è¡Œé¸æ“‡ã€‚<br/>回答 <b>是</b> å¯èƒ½éœ€è¦ä¸€äº›æ™‚é–“ä¾†è¼‰å…¥è³‡æ–™ï¼Œä½†é¸æ“‡å°‡æœƒå®Œæˆã€‚</p>警告:載入所有資料å¯èƒ½éœ€è¦å¤§é‡è¨˜æ†¶é«”來處ç†å¤§åž‹è³‡æ–™è¡¨ã€‚ + + + + Cannot set selection to NULL. Column %1 has a NOT NULL constraint. + ç„¡æ³•å°‡é¸æ“‡è¨­å®šç‚º NULLã€‚æ¬„ä½ %1 有一個 NOT NULL æ¢ä»¶ã€‚ + + + + FileExtensionManager + + + File Extension Manager + 檔案副檔å管ç†å™¨ + + + + &Up + 上移(&U) + + + + &Down + 下移(&D) + + + + &Add + 新增(&A) + + + + &Remove + 移除(&R) + + + + + Description + æè¿° + + + + Extensions + 副檔å + + + + *.extension + *.副檔å + + + + FilterLineEdit + + + Filter + ç¯©é¸ + + + + These input fields allow you to perform quick filters in the currently selected table. +By default, the rows containing the input text are filtered out. +The following operators are also supported: +% Wildcard +> Greater than +< Less than +>= Equal to or greater +<= Equal to or less += Equal to: exact match +<> Unequal: exact inverse match +x~y Range: values between x and y +/regexp/ Values matching the regular expression + 這些輸入欄ä½å…許您在目å‰é¸æ“‡çš„資料表中進行快速篩é¸ã€‚ +é è¨­æƒ…æ³ä¸‹ï¼ŒåŒ…å«è¼¸å…¥æ–‡å­—的行將被篩é¸å‡ºä¾†ã€‚ +也支æ´ä»¥ä¸‹é‹ç®—å­ï¼š +% è¬ç”¨å­—å…ƒ +> 大於 +< å°æ–¼ +>= 大於或等於 +<= å°æ–¼æˆ–等於 += 等於:完全相符 +<> ä¸ç­‰æ–¼ï¼šå®Œå…¨ä¸ç›¸ç¬¦ +x~y 範åœï¼šä»‹æ–¼ x å’Œ y 之間的值 +/regexp/ ç¬¦åˆæ­£è¦è¡¨é”å¼çš„值 + + + + Clear All Conditional Formats + 清除所有æ¢ä»¶æ ¼å¼ + + + + Use for Conditional Format + 用於æ¢ä»¶æ ¼å¼ + + + + Edit Conditional Formats... + 編輯æ¢ä»¶æ ¼å¼... + + + + Set Filter Expression + 設定篩é¸è¡¨é”å¼ + + + + What's This? + 這是什麼? + + + + Is NULL + 是 NULL + + + + Is not NULL + 䏿˜¯ NULL + + + + Is empty + 是空的 + + + + Is not empty + 䏿˜¯ç©ºçš„ + + + + Not containing... + ä¸åŒ…å«... + + + + Equal to... + 等於... + + + + Not equal to... + ä¸ç­‰æ–¼... + + + + Greater than... + 大於... + + + + Less than... + å°æ–¼... + + + + Greater or equal... + 大於或等於... + + + + Less or equal... + å°æ–¼æˆ–等於... + + + + In range... + 在範åœå…§... + + + + Regular expression... + æ­£è¦è¡¨é”å¼... + + + + FindReplaceDialog + + + Find and Replace + 尋找與å–代 + + + + Fi&nd text: + 尋找文字: + + + + Re&place with: + å–代為: + + + + Match &exact case + 符åˆå®Œå…¨å¤§å°å¯« + + + + Match &only whole words + åƒ…ç¬¦åˆæ•´å€‹å–®å­— + + + + When enabled, the search continues from the other end when it reaches one end of the page + 啟用時,æœå°‹åˆ°é”é é¢ä¸€ç«¯å¾Œå°‡å¾žå¦ä¸€ç«¯ç¹¼çºŒ + + + + &Wrap around + 循環æœå°‹ + + + + When set, the search goes backwards from cursor position, otherwise it goes forward + 設定時,æœå°‹å°‡å¾žæ¸¸æ¨™ä½ç½®å‘後進行,å¦å‰‡å°‡å‘å‰é€²è¡Œ + + + + Search &backwards + å‘後æœå°‹ + + + + <html><head/><body><p>When checked, the pattern to find is searched only in the current selection.</p></body></html> + <html><head/><body><p>勾鏿™‚,åªåœ¨ç›®å‰é¸å–的範åœå…§æœå°‹è¦å°‹æ‰¾çš„æ¨¡å¼ã€‚</p></body></html> + + + + &Selection only + 僅é¸å–ç¯„åœ + + + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>勾鏿™‚,將è¦å°‹æ‰¾çš„æ¨¡å¼è§£è®€ç‚º UNIX æ­£è¦è¡¨é”å¼ã€‚è«‹åƒé–± <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Wikibooks 中的正è¦è¡¨é”å¼</a>。</p></body></html> + + + + Use regular e&xpressions + 使用正è¦è¡¨é”å¼ + + + + Find the next occurrence from the cursor position and in the direction set by "Search backwards" + 從游標ä½ç½®ä»¥ã€Œå‘後æœå°‹ã€è¨­å®šçš„æ–¹å‘尋找下一個符åˆçš„æ–‡å­— + + + + &Find Next + 尋找下一個 + + + + F3 + F3 + + + + &Replace + å–代 + + + + Highlight all the occurrences of the text in the page + 在é é¢ä¸­çªé¡¯æ‰€æœ‰å‡ºç¾çš„æ–‡å­— + + + + F&ind All + 尋找所有 + + + + Replace all the occurrences of the text in the page + å–代é é¢ä¸­æ‰€æœ‰å‡ºç¾çš„æ–‡å­— + + + + Replace &All + 全部å–代 + + + + The searched text was not found + 找ä¸åˆ°æœå°‹çš„æ–‡å­— + + + + The searched text was not found. + 找ä¸åˆ°æœå°‹çš„æ–‡å­—。 + + + + The searched text was found one time. + 找到æœå°‹çš„æ–‡å­—一次。 + + + + The searched text was found %1 times. + 找到æœå°‹çš„æ–‡å­— %1 次。 + + + + The searched text was replaced one time. + å–代æœå°‹çš„æ–‡å­—一次。 + + + + The searched text was replaced %1 times. + å–代æœå°‹çš„æ–‡å­— %1 次。 + + + + ForeignKeyEditor + + + &Reset + é‡è¨­ + + + + Foreign key clauses (ON UPDATE, ON DELETE etc.) + 外éµå­å¥ï¼ˆON UPDATEã€ON DELETE 等) + + + + ImageViewer + + + Image Viewer + 圖片檢視器 + + + + Reset the scaling to match the original size of the image. + é‡è¨­ç¸®æ”¾æ¯”例以符åˆåœ–片的原始大å°ã€‚ + + + + Set the scaling to match the size of the viewport. + è¨­å®šç¸®æ”¾æ¯”ä¾‹ä»¥ç¬¦åˆæª¢è¦–å€çš„大å°ã€‚ + + + + Print... + 列å°... + + + + Open preview dialog for printing displayed image + 開啟é è¦½å°è©±æ¡†ä»¥åˆ—å°é¡¯ç¤ºçš„圖片 + + + + Ctrl+P + Ctrl+P + + + + ImportCsvDialog + + + Import CSV file + 匯入 CSV 檔案 + + + + Table na&me + 表格å稱 + + + + &Column names in first line + 首行為欄ä½å稱(&C) + + + + Field &separator + 欄ä½åˆ†éš”符號(&S) + + + + , + , + + + + ; + ; + + + + + Tab + Tab + + + + | + | + + + + Other + 其它 + + + + &Quote character + 引號字元(&Q) + + + + + Other (printable) + 其他(å¯åˆ—å°ï¼‰ + + + + + Other (code) + 其他(代碼) + + + + " + " + + + + ' + ' + + + + &Encoding + 編碼(&E) + + + + UTF-8 + UTF-8 + + + + UTF-16 + UTF-16 + + + + ISO-8859-1 + ISO-8859-1 + + + + Trim fields? + 是å¦ä¿®æ•´æ¬„ä½ï¼Ÿ + + + + Separate tables + 分開表格 + + + + Advanced + 進階 + + + + When importing an empty value from the CSV file into an existing table with a default value for this column, that default value is inserted. Activate this option to insert an empty value instead. + 從 CSV æª”æ¡ˆåŒ¯å…¥ç©ºå€¼åˆ°å·²å­˜åœ¨çš„è¡¨æ ¼ä¸”è©²æ¬„ä½æœ‰é è¨­å€¼æ™‚,將æ’入該é è¨­å€¼ã€‚啟用此é¸é …以æ’入空值。 + + + + Ignore default &values + 忽略é è¨­å€¼(&V) + + + + Activate this option to stop the import when trying to import an empty value into a NOT NULL column without a default value. + 啟用此é¸é …以在嘗試匯入空值到沒有é è¨­å€¼çš„ NOT NULL æ¬„ä½æ™‚åœæ­¢åŒ¯å…¥ã€‚ + + + + Fail on missing values + é‡ç¼ºå¤±å€¼å‰‡å¤±æ•— + + + + Disable data type detection + åœç”¨è³‡æ–™åž‹æ…‹åµæ¸¬ + + + + Disable the automatic data type detection when creating a new table. + 建立新表格時,åœç”¨è‡ªå‹•è³‡æ–™åž‹æ…‹åµæ¸¬ã€‚ + + + + Use local number conventions + ä½¿ç”¨æœ¬åœ°æ•¸å­—æ ¼å¼ + + + + Use decimal and thousands separators according to the system locale. + 根據系統å€åŸŸè¨­å®šä½¿ç”¨å°æ•¸é»žå’Œåƒä½åˆ†éš”符號。 + + + + When importing into an existing table with a primary key, unique constraints or a unique index there is a chance for a conflict. This option allows you to select a strategy for that case: By default the import is aborted and rolled back but you can also choose to ignore and not import conflicting rows or to replace the existing row in the table. + 當匯入到具有主éµã€å”¯ä¸€æ¢ä»¶æˆ–å”¯ä¸€ç´¢å¼•çš„ç¾æœ‰è¡¨æ ¼æ™‚,å¯èƒ½æœƒç™¼ç”Ÿè¡çªã€‚æ­¤é¸é …å…è¨±æ‚¨é¸æ“‡è©²æƒ…æ³çš„策略:é è¨­æƒ…æ³ä¸‹ï¼ŒåŒ¯å…¥å°‡è¢«ä¸­æ­¢ä¸¦å›žæ»¾ï¼Œä½†æ‚¨ä¹Ÿå¯ä»¥é¸æ“‡å¿½ç•¥ä¸¦ä¸åŒ¯å…¥è¡çªçš„資料列,或å–ä»£è¡¨æ ¼ä¸­çš„ç¾æœ‰è³‡æ–™åˆ—。 + + + + Abort import + 終止匯入 + + + + Ignore row + 忽略資料列 + + + + Replace existing row + å–ä»£ç¾æœ‰è³‡æ–™åˆ— + + + + Conflict strategy + è¡çªç­–ç•¥ + + + + + Deselect All + å…¨éƒ¨å–æ¶ˆé¸å– + + + + Match Similar + 符åˆç›¸ä¼¼ + + + + Select All + 全部é¸å– + + + + There is already a table named '%1' and an import into an existing table is only possible if the number of columns match. + 已存在å為 '%1' çš„è¡¨æ ¼ï¼Œåªæœ‰åœ¨æ¬„使•¸é‡ç¬¦åˆçš„æƒ…æ³ä¸‹æ‰èƒ½åŒ¯å…¥åˆ°ç¾æœ‰è¡¨æ ¼ã€‚ + + + + There is already a table named '%1'. Do you want to import the data into it? + 已存在å為 '%1' 的表格。您è¦å°‡è³‡æ–™åŒ¯å…¥å…¶ä¸­å—Žï¼Ÿ + + + + Creating restore point failed: %1 + 建立還原點失敗:%1 + + + + Creating the table failed: %1 + 建立表格失敗:%1 + + + + importing CSV + 正在匯入 CSV + + + + Could not prepare INSERT statement: %1 + 無法準備 INSERT 陳述å¼ï¼š%1 + + + + Unexpected end of file. Please make sure that you have configured the correct quote characters and the file is not malformed. + 檔案æ„å¤–çµæŸã€‚è«‹ç¢ºä¿æ‚¨å·²è¨­å®šæ­£ç¢ºçš„å¼•è™Ÿå­—å…ƒï¼Œä¸¦ä¸”æª”æ¡ˆæ ¼å¼æ­£ç¢ºã€‚ + + + + Importing the file '%1' took %2ms. Of this %3ms were spent in the row function. + 匯入檔案 '%1' 花費了 %2ms。其中 %3ms 花在行函å¼ä¸Šã€‚ + + + + Inserting row failed: %1 + æ’入資料列失敗%1 + + + + MainWindow + + + toolBar1 + 工具列1 + + + + Opens the SQLCipher FAQ in a browser window + 在ç€è¦½å™¨è¦–窗中開啟 SQLCipher 常見å•題 + + + + Export one or more table(s) to a JSON file + 匯出一個或多個資料表到 JSON 檔案 + + + + DB Browser for SQLite + DB Browser for SQLite + + + + Open an existing database file in read only mode + 以唯讀模å¼é–‹å•Ÿç¾æœ‰çš„資料庫檔案 + + + + &File + 檔案(&F) + + + + + &Database Structure + This has to be equal to the tab title in all the main tabs + &è³‡æ–™åº«çµæ§‹ + + + + + &Browse Data + This has to be equal to the tab title in all the main tabs + &ç€è¦½è³‡æ–™ + + + + + Edit P&ragmas + This has to be equal to the tab title in all the main tabs + 編輯 P&ragmas + + + + + E&xecute SQL + This has to be equal to the tab title in all the main tabs + 執&行 SQL + + + + &Import + 匯入(&I) + + + + &Export + 匯出(&E) + + + + &Recent Files + 最近使用的檔案 + + + + &Edit + 編輯(&E) + + + + &View + 檢視(&V) + + + + &Help + 幫助(&H) + + + + Edit Database &Cell + 編輯資料庫儲存格(&C) + + + + DB Sche&ma + è³‡æ–™åº«çµæ§‹(&M) + + + + &Remote + é ç«¯(&R) + + + + + Execute current line + 執行目å‰é€™ä¸€è¡Œ + + + + This button executes the SQL statement present in the current editor line + 這個按鈕執行目å‰ç·¨è¼¯å™¨é€™ä¸€è¡Œçš„ SQL é™³è¿°å¼ + + + + Shift+F5 + Shift+F5 + + + + Sa&ve Project + 儲存專案(&V) + + + + + Save SQL file as + å°‡ SQL 檔案儲存為 + + + + This button saves the content of the current SQL editor tab to a file + é€™å€‹æŒ‰éˆ•å°‡ç›®å‰ SQL 編輯器分é çš„內容儲存到一個檔案 + + + + &Browse Table + ç€è¦½è³‡æ–™è¡¨(&B) + + + + Copy Create statement + è¤‡è£½å»ºç«‹é™³è¿°å¼ + + + + Copy the CREATE statement of the item to the clipboard + 將項目的 CREATE 陳述å¼è¤‡è£½åˆ°å‰ªè²¼ç°¿ + + + + User + 使用者 + + + + Application + æ‡‰ç”¨ç¨‹å¼ + + + + &Clear + 清除(&C) + + + + &New Database... + 新建資料庫(&N)... + + + + + Create a new database file + 建立一個新的資料庫檔 + + + + This option is used to create a new database file. + 這個é¸é …用於建立一個新的資料庫檔案。 + + + + Ctrl+N + Ctrl+N + + + + + &Open Database... + 開啟資料庫(&O)... + + + + + + + + Open an existing database file + é–‹å•Ÿä¸€å€‹ç¾æœ‰çš„資料庫檔 + + + + + + This option is used to open an existing database file. + 這個é¸é …ç”¨æ–¼é–‹å•Ÿä¸€å€‹ç¾æœ‰çš„資料庫檔案。 + + + + Ctrl+O + Ctrl+O + + + + &Close Database + 關閉資料庫(&C) + + + + + Ctrl+W + Ctrl+W + + + + + Revert database to last saved state + 把資料庫退回到先å‰å„²å­˜çš„狀態 + + + + This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. + 這個é¸é …用於倒退目å‰çš„資料庫檔為它最後的儲存狀態。從最後儲存æ“作開始åšå‡ºçš„æ‰€æœ‰ä¿®æ”¹å°‡æœƒéºå¤±ã€‚ + + + + + Write changes to the database file + 把修改寫入到資料庫檔 + + + + This option is used to save changes to the database file. + 這個é¸é …用於儲存修改到資料庫檔案。 + + + + Ctrl+S + Ctrl+S + + + + Compact the database file, removing space wasted by deleted records + 壓縮資料庫檔案,é€éŽåˆªé™¤è¨˜éŒ„去掉浪費的空間 + + + + + Compact the database file, removing space wasted by deleted records. + 壓縮資料庫檔案,é€éŽåˆªé™¤è¨˜éŒ„去掉浪費的空間。 + + + + E&xit + 退出(&X) + + + + Ctrl+Q + Ctrl+Q + + + + Import data from an .sql dump text file into a new or existing database. + 從一個 .sql 轉儲文字檔中匯入資料到一個新的或已有的資料庫。 + + + + This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. + 這個é¸é …讓您從一個 .sql è½‰å„²æ–‡å­—æª”ä¸­åŒ¯å…¥è³‡æ–™åˆ°ä¸€å€‹æ–°çš„æˆ–ç¾æœ‰çš„資料庫。SQL 轉儲檔å¯ä»¥åœ¨å¤§å¤šæ•¸è³‡æ–™åº«å¼•擎上建立,包括 MySQL å’Œ PostgreSQL。 + + + + Open a wizard that lets you import data from a comma separated text file into a database table. + 開啟一個引導精éˆè®“您從一個逗號間隔的文字檔匯入資料到一個資料庫資料表中。 + + + + Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. + 開啟一個引導精éˆè®“您從一個逗號間隔的文字檔匯入資料到一個資料庫資料表中。CSV 檔å¯ä»¥åœ¨å¤§å¤šæ•¸è³‡æ–™åº«å’Œè©¦ç®—資料表應用程å¼ä¸Šå»ºç«‹ã€‚ + + + + Export a database to a .sql dump text file. + 匯出一個資料庫導一個 .sql 轉儲文字檔案。 + + + + This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. + 這個é¸é …讓您匯出一個資料庫導一個 .sql 轉儲文字檔案。SQL 轉儲檔包å«åœ¨å¤§å¤šæ•¸è³‡æ–™åº«å¼•擎上(包括 MySQL å’Œ PostgreSQL)釿–°å»ºç«‹è³‡æ–™åº«æ‰€éœ€çš„æ‰€æœ‰è³‡æ–™ã€‚ + + + + Export a database table as a comma separated text file. + 匯出一個資料庫資料表為逗號間隔的文字檔案。 + + + + Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. + 匯出一個資料庫資料表為逗號間隔的文字檔,準備好被匯入到其他資料庫或試算資料表應用程å¼ã€‚ + + + + Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database + 開啟「建立資料表ã€å¼•å°Žç²¾éˆï¼Œåœ¨é‚£è£¡å¯ä»¥å®šç¾©åœ¨è³‡æ–™åº«ä¸­çš„一個新資料表的åç¨±å’Œæ¬„ä½ + + + + Open the Delete Table wizard, where you can select a database table to be dropped. + 開啟「刪除資料表ã€å¼•å°Žç²¾éˆï¼Œåœ¨é‚£è£¡æ‚¨å¯ä»¥é¸æ“‡è¦ä¸Ÿæ£„的一個資料庫資料表。 + + + + Open the Create Index wizard, where it is possible to define a new index on an existing database table. + 開啟「建立索引ã€å¼•å°Žç²¾éˆï¼Œåœ¨é‚£è£¡å¯ä»¥åœ¨ä¸€å€‹ç¾æœ‰çš„資料庫資料表上定義一個新索引。 + + + + &Preferences... + å好設定(&P)... + + + + + Open the preferences window. + 開啟å好設定視窗。 + + + + &DB Toolbar + 資料庫工具列(&D) + + + + Shows or hides the Database toolbar. + 顯示或隱è—資料庫工具列。 + + + + Shift+F1 + Shift+F1 + + + + &Recently opened + 最近開啟(&R) + + + + Ctrl+T + Ctrl+T + + + + This is the structure of the opened database. +You can drag SQL statements from an object row and drop them into other applications or into another instance of 'DB Browser for SQLite'. + + é€™æ˜¯å·²é–‹å•Ÿè³‡æ–™åº«çš„çµæ§‹ã€‚ +您å¯ä»¥å¾žç‰©ä»¶åˆ—中拖曳 SQL 陳述å¼ï¼Œä¸¦å°‡å®ƒå€‘æ‹–æ›³åˆ°å…¶ä»–æ‡‰ç”¨ç¨‹å¼æˆ–å¦ä¸€å€‹ã€ŒDB Browser for SQLiteã€ä¸­ã€‚ + + + + Un/comment block of SQL code + 註解/å–æ¶ˆè¨»è§£ SQL 程å¼ç¢¼å€å¡Š + + + + Un/comment block + 註解/å–æ¶ˆè¨»è§£å€å¡Š + + + + Comment or uncomment current line or selected block of code + å°é€™ä¸€è¡Œæˆ–é¸å®šå€å¡Šçš„程å¼ç¢¼é€²è¡Œè¨»è§£æˆ–å–æ¶ˆè¨»è§£ + + + + Comment or uncomment the selected lines or the current line, when there is no selection. All the block is toggled according to the first line. + å°é¸å–的行數或目å‰é€™ä¸€è¡Œï¼ˆç•¶æ²’有é¸å–任何æ±è¥¿æ™‚ï¼‰è¨»è§£æˆ–å–æ¶ˆè¨»è§£ã€‚所有的å€å¡Šå°‡æ ¹æ“šç¬¬ä¸€è¡Œé€²è¡Œåˆ‡æ›ã€‚ + + + + Ctrl+/ + Ctrl+/ + + + + Stop SQL execution + åœæ­¢ SQL 執行 + + + + Stop execution + åœæ­¢åŸ·è¡Œ + + + + Stop the currently running SQL script + åœæ­¢ç›®å‰æ­£åœ¨åŸ·è¡Œçš„ SQL 腳本 + + + + Warning: this pragma is not readable and this value has been inferred. Writing the pragma might overwrite a redefined LIKE provided by an SQLite extension. + 警告:這個 pragma 是ä¸å¯è®€çš„,並且這個值已經被推斷出來。寫入 pragma å¯èƒ½æœƒè¦†è“‹ç”± SQLite 擴充套件æä¾›çš„已釿–°å®šç¾©çš„ LIKE。 + + + + Temp Store + + + + + Secure Delete + + + + + Case Sensitive Like + + + + + Journal Mode + + + + + Journal Size Limit + + + + + Recursive Triggers + + + + + Page Size + + + + + Foreign Keys + å¤–éµ + + + + Auto Vacuum + + + + + Max Page Count + + + + + Checkpoint Full FSYNC + + + + + + Off + + + + + + Normal + + + + + + Full + + + + + Default + é è¨­ + + + + File + 檔案 + + + + + Memory + + + + + Delete + + + + + Truncate + + + + + Persist + + + + + WAL + + + + + Exclusive + + + + + Automatic Index + + + + + Ignore Check Constraints + + + + + Full FSYNC + + + + + WAL Auto Checkpoint + + + + + User Version + + + + + Synchronous + + + + + None + ç„¡ + + + + Incremental + + + + + Locking Mode + + + + + Too&ls + 工具(&T) + + + + DB Toolbar + 資料庫工具列 + + + + SQL &Log + SQL 日誌(&L) + + + + Show S&QL submitted by + 顯示æäº¤çš„ SQL(&Q) + + + + Error Log + 錯誤日誌 + + + + This button clears the contents of the SQL logs + 這個按鈕清除 SQL 日誌的內容 + + + + This panel lets you examine a log of all SQL commands issued by the application or by yourself + 這個颿¿è®“æ‚¨æª¢è¦–ç”±æ‡‰ç”¨ç¨‹å¼æˆ–您自己發出的所有 SQL 命令的日誌 + + + + &Plot + 繪圖(&P) + + + + This is the structure of the opened database. +You can drag multiple object names from the Name column and drop them into the SQL editor and you can adjust the properties of the dropped names using the context menu. This would help you in composing SQL statements. +You can drag SQL statements from the Schema column and drop them into the SQL editor or into other applications. + + é€™æ˜¯å·²é–‹å•Ÿè³‡æ–™åº«çš„çµæ§‹ã€‚ +您å¯ä»¥å¾žå稱欄ä½ä¸­æ‹–曳多個物件å稱,並將它們拖曳到 SQL 編輯器,您å¯ä»¥ä½¿ç”¨å³éµé¸å–®èª¿æ•´æ‹–曳的å稱的屬性。這將有助於您撰寫 SQL 陳述å¼ã€‚ +您å¯ä»¥å¾žçµæ§‹æ¬„ä½ä¸­æ‹–曳 SQL 陳述å¼ï¼Œä¸¦å°‡å®ƒå€‘拖曳到 SQL 編輯器或其他應用程å¼ã€‚ + + + + + Project Toolbar + 專案工具列 + + + + Extra DB toolbar + é¡å¤–的資料庫工具列 + + + + + + Close the current database file + 關閉目å‰çš„資料庫檔案 + + + + &New Database + &新建資料庫 + + + + This button closes the connection to the currently open database file + 這個按鈕會關閉目å‰é–‹å•Ÿçš„資料庫檔案的連線 + + + + + Ctrl+F4 + Ctrl+F4 + + + + &Revert Changes + &還原變更 + + + + &Undo + &復原 + + + + + Undo last change to the database + 復原資料庫的最後一次變更 + + + + This action undoes the last change performed to the database in the Database Browser or in Execute SQL. Redoing is not possible. + 這個動作會復原在 Database Browser 或執行 SQL 中å°è³‡æ–™åº«é€²è¡Œçš„æœ€å¾Œä¸€æ¬¡è®Šæ›´ã€‚無法é‡åšã€‚ + + + + &Write Changes + 寫入變更(&W) + + + + Compact &Database... + 壓縮資料庫(&D)... + + + + Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields from a table, as well as modify field names and types. + 開啟「修改表格ã€ç²¾éˆï¼Œåœ¨æ­¤æ‚¨å¯ä»¥é‡æ–°å‘½å已存在的表格。您也å¯ä»¥æ–°å¢žæˆ–刪除表格中的欄ä½ï¼Œä»¥åŠä¿®æ”¹æ¬„ä½å稱和類型。 + + + + Execute all/selected SQL + 執行所有/é¸å–çš„ SQL + + + + This button executes the currently selected SQL statements. If no text is selected, all SQL statements are executed. + 這個按鈕執行目å‰é¸å–çš„ SQL 陳述å¼ã€‚如果沒有é¸å–任何文字,則執行所有 SQL 陳述å¼ã€‚ + + + + Ctrl+Shift+T + Ctrl+Shift+T + + + + &Load Extension... + 載入擴充套件(&L)... + + + + Execute line + 執行這一行 + + + + &Wiki + 維基(&W) + + + + F1 + F1 + + + + Bug &Report... + 錯誤回報(&R)... + + + + Feature Re&quest... + 功能請求(&Q)... + + + + Web&site + 網站(&S) + + + + &Donate on Patreon... + 在 Patreon 上贊助(&D)... + + + + &Save Project + 儲存專案(&S) + + + + Open &Project... + 開啟專案(&P)... + + + + Open &Project + 開啟專案(&P) + + + + &Attach Database... + 附加資料庫(&A)... + + + + + Add another database file to the current database connection + å°‡å¦ä¸€å€‹è³‡æ–™åº«æª”案加到目å‰çš„資料庫連線 + + + + This button lets you add another database file to the current database connection + 這個按鈕讓您將å¦ä¸€å€‹è³‡æ–™åº«æª”案加到目å‰çš„資料庫連線 + + + + &Set Encryption... + 設定加密(&S)... + + + + SQLCipher &FAQ + SQLCipher 常見å•題(&F) + + + + Table(&s) to JSON... + 資料表(&S)轉æ›ç‚º JSON... + + + + Open Data&base Read Only... + 以唯讀模å¼é–‹å•Ÿè³‡æ–™åº«(&B)... + + + + Ctrl+Shift+O + Ctrl+Shift+O + + + + Save results + å„²å­˜çµæžœ + + + + Save the results view + å„²å­˜çµæžœé¡¯ç¤º + + + + This button lets you save the results of the last executed query + é€™å€‹æŒ‰éˆ•è®“æ‚¨å„²å­˜æœ€å¾ŒåŸ·è¡ŒæŸ¥è©¢çš„çµæžœ + + + + + Find text in SQL editor + 在 SQL 編輯器中尋找文字 + + + + Find + 尋找 + + + + This button opens the search bar of the editor + 這個按鈕開啟編輯器的æœå°‹åˆ— + + + + Ctrl+F + Ctrl+F + + + + + Find or replace text in SQL editor + 在 SQL 編輯器中尋找或å–代文字 + + + + Find or replace + 尋找或å–代 + + + + This button opens the find/replace dialog for the current editor tab + 這個按鈕開啟目å‰ç·¨è¼¯å™¨åˆ†é çš„尋找/å–代å°è©±æ¡† + + + + Ctrl+H + Ctrl+H + + + + Export to &CSV + 匯出為 &CSV + + + + Export to &JSON + 匯出為 &JSON + + + + Save as &view + 儲存為檢視表(&V) + + + + Save as view + 儲存為檢視表 + + + + &Open Database + &開啟資料庫 + + + + Drag && Drop SELECT Query + 拖曳 && 放下 SELECT 查詢 + + + + + When dragging fields from the same table or a single table, drop a SELECT query into the editor + 當從åŒä¸€è³‡æ–™è¡¨æˆ–å–®ä¸€è³‡æ–™è¡¨æ‹–æ›³æ¬„ä½æ™‚,將 SELECT 查詢放入編輯器 + + + + Browse Table + ç€è¦½è³‡æ–™è¡¨ + + + + + Ctrl+Shift+W + Ctrl+Shift+W + + + + Table from CSV data in Clipboard... + 從剪貼簿中的 CSV 資料建立資料表... + + + + This treats the current clipboard contents as a CSV file and opens the same import wizard that is used for importing CSV data from a file. + 將目å‰å‰ªè²¼ç°¿çš„內容視為 CSV 檔案,並開啟與從檔案匯入 CSV 資料相åŒçš„匯入精éˆã€‚ + + + + Show &Row Counts + 顯示 &列計數 + + + + This shows the number of rows for each table and view in the database. + 顯示資料庫中æ¯å€‹è³‡æ–™è¡¨å’Œæª¢è¦–表的列數。 + + + + Save Database &As... + å¦å­˜è³‡æ–™åº« &為... + + + + Save the current database as a different file + 將目å‰çš„資料庫å¦å­˜ç‚ºä¸åŒçš„æª”案 + + + + Refresh + 釿–°æ•´ç† + + + + Reload the database structure + 釿–°è¼‰å…¥è³‡æ–™åº«çµæ§‹ + + + + Shows or hides the Project toolbar. + 顯示或隱è—專案工具列。 + + + + New &tab + 新分é (&T) + + + + Open SQL file(s) + 開啟 SQL 檔案 + + + + This button opens files containing SQL statements and loads them in new editor tabs + é€™å€‹æŒ‰éˆ•é–‹å•ŸåŒ…å« SQL 陳述å¼çš„æª”案,並在新的編輯器分é ä¸­è¼‰å…¥å®ƒå€‘ + + + + This button lets you save all the settings associated to the open DB to a DB Browser for SQLite project file + 這個按鈕讓您儲存所有與開啟的資料庫相關的設定到一個 DB Browser for SQLite 的專案檔 + + + + This button lets you open a DB Browser for SQLite project file + 這個按鈕讓您開啟一個 DB Browser for SQLite 的專案檔 + + + + Extra DB Toolbar + é¡å¤–的資料庫工具列 + + + + New In-&Memory Database + 新建記憶體中的資料庫 + + + + Drag && Drop Qualified Names + 拖曳並放下完全é™å®šå稱 + + + + + Use qualified names (e.g. "Table"."Field") when dragging the objects and dropping them into the editor + 在拖曳物件並將其放入編輯器時,使用完全é™å®šå稱(例如「Tableã€.「Fieldã€ï¼‰ + + + + Drag && Drop Enquoted Names + 拖曳並放下引號å稱 + + + + + Use escaped identifiers (e.g. "Table1") when dragging the objects and dropping them into the editor + 在拖曳物件並將其放入編輯器時,使用轉義識別符號(例如「Table1ã€ï¼‰ + + + + &Integrity Check + &完整性檢查 + + + + Runs the integrity_check pragma over the opened database and returns the results in the Execute SQL tab. This pragma does an integrity check of the entire database. + 在已開啟的資料庫上執行 integrity_check pragma,並在執行 SQL æ¨™ç±¤ä¸­å›žå‚³çµæžœã€‚æ­¤ pragma å°æ•´å€‹è³‡æ–™åº«é€²è¡Œå®Œæ•´æ€§æª¢æŸ¥ã€‚ + + + + &Foreign-Key Check + &外鵿ª¢æŸ¥ + + + + Runs the foreign_key_check pragma over the opened database and returns the results in the Execute SQL tab + 在已開啟的資料庫上執行 foreign_key_check pragma,並在執行 SQL æ¨™ç±¤ä¸­å›žå‚³çµæžœ + + + + &Quick Integrity Check + &快速完整性檢查 + + + + Run a quick integrity check over the open DB + å°é–‹å•Ÿçš„資料庫進行快速完整性檢查 + + + + Runs the quick_check pragma over the opened database and returns the results in the Execute SQL tab. This command does most of the checking of PRAGMA integrity_check but runs much faster. + 在已開啟的資料庫上執行 quick_check pragma,並在執行 SQL æ¨™ç±¤ä¸­å›žå‚³çµæžœã€‚此命令執行 PRAGMA integrity_check 的大部分檢查,但執行速度更快。 + + + + &Optimize + &最佳化 + + + + Attempt to optimize the database + 嘗試最佳化資料庫 + + + + Runs the optimize pragma over the opened database. This pragma might perform optimizations that will improve the performance of future queries. + 在已開啟的資料庫上執行 optimize pragma。此 pragma å¯èƒ½æœƒåŸ·è¡Œæœ€ä½³åŒ–,以æé«˜æœªä¾†æŸ¥è©¢çš„æ•ˆèƒ½ã€‚ + + + + + Print + åˆ—å° + + + + Print text from current SQL editor tab + 列å°ç›®å‰ SQL 編輯器標籤中的文字 + + + + Open a dialog for printing the text in the current SQL editor tab + 開啟一個å°è©±æ¡†ä»¥åˆ—å°ç›®å‰ SQL 編輯器標籤中的文字 + + + + Print the structure of the opened database + 列å°å·²é–‹å•Ÿçš„è³‡æ–™åº«çµæ§‹ + + + + Open a dialog for printing the structure of the opened database + 開啟一個å°è©±æ¡†ä»¥åˆ—å°å·²é–‹å•Ÿçš„è³‡æ–™åº«çµæ§‹ + + + + &Save Project As... + &å¦å­˜å°ˆæ¡ˆç‚º... + + + + + + Save the project in a file selected in a dialog + 在å°è©±æ¡†ä¸­é¸æ“‡çš„æª”案中儲存專案 + + + + Save A&ll + 全部儲存 + + + + + + Save DB file, project file and opened SQL files + 儲存資料庫檔案ã€å°ˆæ¡ˆæª”案和已開啟的 SQL 檔案 + + + + Ctrl+Shift+S + Ctrl+Shift+S + + + + Close Pro&ject + 關閉專案 + + + + + Close project and database files and return to the initial state + 關閉專案和資料庫檔案,並返回åˆå§‹ç‹€æ…‹ + + + + Ctrl+Shift+F4 + Ctrl+Shift+F4 + + + + + Detach Database + 分離資料庫 + + + + + Detach database file attached to the current database connection + 分離目å‰è³‡æ–™åº«é€£ç·šæ‰€é™„加的資料庫檔案 + + + + &Database from SQL file... + &從 SQL 檔案建立資料庫... + + + + &Table from CSV file... + &從 CSV 檔案建立資料表... + + + + &Database to SQL file... + &資料庫轉æ›ç‚º SQL 檔案... + + + + &Table(s) as CSV file... + &資料表轉æ›ç‚º CSV 檔案... + + + + &Create Table... + &建立資料表... + + + + &Delete Table... + &刪除資料表... + + + + &Modify Table... + &修改資料表... + + + + Create &Index... + 建立 &索引... + + + + W&hat's This? + 這是什麼? + + + + &About + &關於 + + + + This button opens a new tab for the SQL editor + 此按鈕將開啟 SQL 編輯器的新標籤 + + + + &Execute SQL + 執行 SQL(&E) + + + + + Save the current session to a file + 儲存目å‰å·¥ä½œéšŽæ®µåˆ°æª”案 + + + + + Load a working session from a file + 從一檔案載入工作階段 + + + + + + Save SQL file + 儲存 SQL 檔案 + + + + Ctrl+E + Ctrl+E + + + + Export as CSV file + 匯出為 CSV 檔案 + + + + Export table as comma separated values file + 將資料表匯出為逗號分隔值檔案 + + + + Ctrl+L + Ctrl+L + + + + + Ctrl+P + Ctrl+P + + + + Database encoding + 資料庫編碼 + + + + + Choose a database file + 鏿“‡ä¸€å€‹è³‡æ–™åº«æª”案 + + + + Ctrl+Return + Ctrl+Return + + + + Ctrl+D + Ctrl+D + + + + Ctrl+I + Ctrl+I + + + + Reset Window Layout + é‡è¨­è¦–窗é…ç½® + + + + The database is currently busy. + 資料庫目å‰å¿™ç¢Œä¸­ã€‚ + + + + Click here to interrupt the currently running query. + 點é¸é€™è£¡ä¸­æ–·ç›®å‰æ­£åœ¨åŸ·è¡Œçš„æŸ¥è©¢ã€‚ + + + + Encrypted + 已加密 + + + + Database is encrypted using SQLCipher + 資料庫已使用 SQLCipher 加密 + + + + Read only + 唯讀 + + + + Database file is read only. Editing the database is disabled. + 資料庫檔案是唯讀的。已åœç”¨ç·¨è¼¯è³‡æ–™åº«ã€‚ + + + + Could not open database file. +Reason: %1 + 無法開啟資料庫檔案。 +原因: %1 + + + + + + Choose a filename to save under + 鏿“‡ä¸€å€‹è¦å„²å­˜çš„æª”案å稱 + + + + Error while saving the database file. This means that not all changes to the database were saved. You need to resolve the following error first. + +%1 + 儲存資料庫檔案時出ç¾éŒ¯èª¤ã€‚é€™è¡¨ç¤ºä¸¦éžæ‰€æœ‰å°è³‡æ–™åº«çš„變更都已儲存。您需è¦å…ˆè§£æ±ºä»¥ä¸‹çš„錯誤。 + +%1 + + + + Do you want to save the changes made to SQL tabs in the project file '%1'? + 您是å¦è¦å„²å­˜å°å°ˆæ¡ˆæª”案「%1ã€ä¸­çš„ SQL åˆ†é æ‰€åšçš„變更? + + + + A new DB Browser for SQLite version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. + 有新版的 DB Browser for SQLite å¯ç”¨ (%1.%2.%3)。<br/><br/>請在 <a href='%4'>%4</a> 下載。 + + + + DB Browser for SQLite project file (*.sqbpro) + DB Browser for SQLite 專案檔案 (*.sqbpro) + + + + Error checking foreign keys after table modification. The changes will be reverted. + ä¿®æ”¹è³‡æ–™è¡¨å¾Œæª¢æŸ¥å¤–éµæ™‚出ç¾éŒ¯èª¤ã€‚將會還原變更。 + + + + This table did not pass a foreign-key check.<br/>You should run 'Tools | Foreign-Key Check' and fix the reported issues. + 這個資料表未通éŽå¤–鵿ª¢æŸ¥ã€‚<br/>您應該執行「工具 | 外鵿ª¢æŸ¥ã€ä¸¦ä¿®æ­£å ±å‘Šçš„å•題。 + + + + Execution finished with errors. + 執行完æˆä¸¦å‡ºç¾éŒ¯èª¤ã€‚ + + + + Execution finished without errors. + 執行完æˆä¸¦æœªå‡ºç¾éŒ¯èª¤ã€‚ + + + + Are you sure you want to undo all changes made to the database file '%1' since the last save? + 您是å¦ç¢ºèªæ‚¨æƒ³æ’¤éŠ·å¾žä¸Šæ¬¡å„²å­˜ä»¥ä¾†å°è³‡æ–™åº«æª”‘%1’åšå‡ºçš„æ‰€æœ‰ä¿®æ”¹ã€‚? + + + + Choose a file to import + 鏿“‡è¦åŒ¯å…¥çš„一個檔案 + + + + Text files(*.sql *.txt);;All files(*) + 文字檔案(*.sql *.txt);;所有擋檔案(*) + + + + Do you want to create a new database file to hold the imported data? +If you answer no we will attempt to import the data in the SQL file to the current database. + æ‚¨æ˜¯å¦æƒ³è¦å»ºç«‹ä¸€å€‹æ–°çš„資料庫檔案來儲存匯入的資料? +å¦‚æžœæ‚¨é¸æ“‡ã€Œå¦ã€ï¼Œæˆ‘們將嘗試將 SQL 檔中的資料匯入到目å‰çš„資料庫。 + + + + File %1 already exists. Please choose a different name. + 檔案 %1 å·²å­˜åœ¨ã€‚è«‹é¸æ“‡ä¸€å€‹ä¸åŒçš„å稱。 + + + + Error importing data: %1 + 匯入資料時出ç¾éŒ¯èª¤: %1 + + + + Import completed. + 匯入完æˆã€‚ + + + + Delete View + 刪除檢視表 + + + + Delete Trigger + 刪除觸發器 + + + + Delete Index + 刪除索引 + + + + + Delete Table + 刪除資料表 + + + + Setting PRAGMA values will commit your current transaction. +Are you sure? + 設定 PRAGMA 值將會æäº¤æ‚¨çš„ç›®å‰äº¤æ˜“。. +您確èªå—Ž? + + + + In-Memory database + 記憶體內部資料庫 + + + + Ctrl+Tab + Ctrl+Tab + + + + Ctrl+Shift+Tab + Ctrl+Shift+Tab + + + + Clear List + 清除清單 + + + + Window Layout + 視窗é…ç½® + + + + Ctrl+0 + Ctrl+0 + + + + Simplify Window Layout + 簡化視窗é…ç½® + + + + Alt+Shift+0 + Alt+Shift+0 + + + + Dock Windows at Bottom + 在底端åœé§è¦–窗 + + + + Dock Windows at Left Side + 在左å´åœé§è¦–窗 + + + + Dock Windows at Top + 在頂端åœé§è¦–窗 + + + + Alt+Shift+W + Alt+Shift+W + + + + Choose a database file to save under + 鏿“‡ä¸€å€‹è³‡æ–™åº«æª”案進行儲存 + + + + Error while saving the database to the new file. + 儲存資料庫到新檔案時發生錯誤。 + + + + Are you sure you want to delete the table '%1'? +All data associated with the table will be lost. + 您是å¦ç¢ºèªæ‚¨æƒ³åˆªé™¤è³‡æ–™è¡¨ã€Œ%1ã€? +所有與資料表相關的資料將會éºå¤±ã€‚ + + + + Are you sure you want to delete the view '%1'? + 您是å¦ç¢ºèªæ‚¨æƒ³åˆªé™¤æª¢è¦–表「%1ã€? + + + + Are you sure you want to delete the trigger '%1'? + 您是å¦ç¢ºèªæ‚¨æƒ³åˆªé™¤è§¸ç™¼å™¨ã€Œ%1ã€? + + + + Are you sure you want to delete the index '%1'? + 您是å¦ç¢ºèªæ‚¨æƒ³åˆªé™¤ç´¢å¼•「%1ã€? + + + + Error: could not delete the table. + 錯誤:無法刪除資料表。 + + + + Error: could not delete the view. + 錯誤:無法刪除檢視表。 + + + + Error: could not delete the trigger. + 錯誤:無法刪除觸發器。 + + + + Error: could not delete the index. + 錯誤:無法刪除索引。 + + + + Message from database engine: +%1 + 來自資料庫引擎的訊æ¯ï¼š +%1 + + + + Editing the table requires to save all pending changes now. +Are you sure you want to save the database? + 編輯表格å‰å¿…須先儲存所有尚未完æˆçš„修改。 +您確定è¦å„²å­˜é€™å€‹è³‡æ–™åº«å—Žï¼Ÿ + + + + Edit View %1 + 編輯檢視表 %1 + + + + Edit Trigger %1 + 編輯觸發器 %1 + + + + You are already executing SQL statements. Do you want to stop them in order to execute the current statements instead? Note that this might leave the database in an inconsistent state. + 您已經在執行 SQL 陳述å¼ã€‚您是å¦è¦åœæ­¢å®ƒå€‘,以便改為執行目å‰çš„陳述å¼? 請注æ„,這å¯èƒ½æœƒä½¿è³‡æ–™åº«è™•æ–¼ä¸ä¸€è‡´çš„狀態。 + + + + -- EXECUTING SELECTION IN '%1' +-- + -- 在「%1ã€ä¸­åŸ·è¡Œé¸å–的部份 +-- + + + + -- EXECUTING LINE IN '%1' +-- + -- 在「%1ã€ä¸­åŸ·è¡Œé€™ä¸€è¡Œ +-- + + + + -- EXECUTING ALL IN '%1' +-- + -- 在「%1ã€ä¸­åŸ·è¡Œæ‰€æœ‰ +-- + + + + + At line %1: + 在第 %1 行: + + + + Result: %1 + çµæžœï¼š%1 + + + + Result: %2 + çµæžœï¼š%2 + + + + Setting PRAGMA values or vacuuming will commit your current transaction. +Are you sure? + 設定 PRAGMA 值或清ç†å°‡æœƒæäº¤æ‚¨çš„ç›®å‰äº¤æ˜“。. +您確èªå—Ž? + + + + Opened '%1' in read-only mode from recent file list + 從最近的檔案列表中以唯讀模å¼é–‹å•Ÿ '%1' + + + + Opened '%1' from recent file list + 從最近的檔案列表中開啟 '%1' + + + + Select the action to apply to the dropped file(s). <br/>Note: only 'Import' will process more than one file. + Note for translation: Although there is no %n in the original, you can use the numerus-form to adjust 'files(s)' and remove the note when n = 1. Including %n in the translation will also work. + + 鏿“‡è¦å¥—用於拖放的檔案的動作。 <br/>注æ„ï¼šåªæœ‰ '匯入' 將處ç†å¤šå€‹æª”案。 + + + + + The statements in the tab '%1' are still executing. Closing the tab will stop the execution. This might leave the database in an inconsistent state. Are you sure you want to close the tab? + 標籤 '%1' 中的指令ä»åœ¨åŸ·è¡Œã€‚é—œé–‰æ¨™ç±¤å°‡æœƒåœæ­¢åŸ·è¡Œã€‚這å¯èƒ½æœƒä½¿è³‡æ–™åº«è™•æ–¼ä¸ä¸€è‡´çš„狀態。您確定è¦é—œé–‰æ¨™ç±¤å—Žï¼Ÿ + + + + DB file '%1' could not be opened + 無法開啟資料庫檔案 '%1' + + + + This project file is using an old file format because it was created using DB Browser for SQLite version 3.10 or lower. Loading this file format is no longer fully supported. If you want to load it completely, please use DB Browser for SQLite version 3.12 to convert it to the new file format. + 此專案檔案使用舊的檔案格å¼ï¼Œå› ç‚ºå®ƒæ˜¯ä½¿ç”¨ DB Browser for SQLite 3.10 版或更舊的版本建立的。我們已經ä¸å†å®Œå…¨æ”¯æ´è¼‰å…¥æ­¤æª”案格å¼ã€‚如果您想完全載入,請使用 DB Browser for SQLite 3.12 版將其轉æ›ç‚ºæ–°çš„æª”案格å¼ã€‚ + + + + Table '%1' not found; settings ignored + 找ä¸åˆ°è³‡æ–™è¡¨ '%1';設定已忽略 + + + + -- Reference to file "%1" (not supported by this version) -- + -- æŒ‡å‘æª”案 "%1"ï¼ˆæœ¬ç‰ˆæœ¬ä¸æ”¯æ´ï¼‰-- + + + + Project saved to file '%1' + 專案已儲存到檔案 '%1' + + + + Yes. Don't ask again + 是的。ä¸å†è©¢å• + + + + This action will open a new SQL tab with the following statements for you to edit and run: + 此動作將開啟一個新的 SQL 標籤,供您編輯和執行以下指令: + + + + Rename Tab + 釿–°å‘½å標籤 + + + + Duplicate Tab + 複製標籤 + + + + Close Tab + 關閉標籤 + + + + Opening '%1'... + 正在開啟 '%1'... + + + + There was an error opening '%1'... + 開啟 '%1' 時發生錯誤... + + + + Value is not a valid URL or filename: %1 + 值䏿˜¯æœ‰æ•ˆçš„ URL 或檔案å稱:%1 + + + + %1 rows returned in %2ms + %2ms 內回傳 %1 行 + + + + Automatically load the last opened DB file at startup + + + + + You are still executing SQL statements. Closing the database now will stop their execution, possibly leaving the database in an inconsistent state. Are you sure you want to close the database? + 您ä»åœ¨åŸ·è¡Œ SQL 指令。ç¾åœ¨é—œé–‰è³‡æ–™åº«å°‡æœƒåœæ­¢ä»–們的執行,å¯èƒ½æœƒä½¿è³‡æ–™åº«è™•æ–¼ä¸ä¸€è‡´çš„狀態。您確定è¦é—œé–‰è³‡æ–™åº«å—Žï¼Ÿ + + + + Do you want to save the changes made to the project file '%1'? + 您是å¦è¦å„²å­˜å°å°ˆæ¡ˆæª”案 '%1' 所åšçš„æ›´æ”¹ï¼Ÿ + + + + Choose text files + 鏿“‡æ–‡å­—檔案 + + + + Import completed. Some foreign key constraints are violated. Please fix them before saving. + 匯入完æˆã€‚é•åäº†ä¸€äº›å¤–éµæ¢ä»¶ã€‚請在儲存之å‰ä¿®æ­£å®ƒå€‘。 + + + + Modify View + 修改檢視表 + + + + Modify Trigger + 修改觸發器 + + + + Modify Index + 修改索引 + + + + Modify Table + 修改表格 + + + + &%1 %2%3 + &%1 %2%3 + + + + (read only) + (唯讀) + + + + Open Database or Project + 開啟資料庫或專案 + + + + Attach Database... + 附加資料庫... + + + + Import CSV file(s)... + 匯入 CSV 檔案... + + + + Do you want to save the changes made to SQL tabs in a new project file? + 您是å¦è¦åœ¨æ–°çš„å°ˆæ¡ˆæª”ä¸­å„²å­˜å° SQL åˆ†é æ‰€åšçš„變更? + + + + Do you want to save the changes made to the SQL file %1? + 您是å¦è¦å„²å­˜å° SQL 檔案 %1 所åšçš„變更? + + + + Select SQL file to open + 鏿“‡è¦é–‹å•Ÿçš„ SQL 檔案 + + + + Select file name + 鏿“‡æª”案å稱 + + + + Select extension file + 鏿“‡æ“´å……套件檔案 + + + + Extension successfully loaded. + 擴充套件æˆåŠŸè¼‰å…¥ã€‚ + + + + Error loading extension: %1 + 載入擴充套件時出ç¾éŒ¯èª¤: %1 + + + + Could not find resource file: %1 + 找ä¸åˆ°è³‡æºæª”案: %1 + + + + + Don't show again + ä¸å†é¡¯ç¤º + + + + New version available. + 有新版本å¯ç”¨ã€‚ + + + + Choose a project file to open + 鏿“‡è¦é–‹å•Ÿçš„專案檔 + + + + Could not open project file for writing. +Reason: %1 + 無法開啟專案檔以進行寫入。 +原因:%1 + + + + Collation needed! Proceed? + 需è¦å®šåº! 繼續? + + + + A table in this database requires a special collation function '%1' that this application can't provide without further knowledge. +If you choose to proceed, be aware bad things can happen to your database. +Create a backup! + 這個資料庫中的一個資料表需è¦ä¸€å€‹ç‰¹æ®Šçš„定åºå‡½å¼ã€Œ%1ã€ï¼Œè€Œé€™å€‹æ‡‰ç”¨ç¨‹å¼åœ¨æ²’有進一步的知識下無法æä¾›ã€‚ +å¦‚æžœæ‚¨é¸æ“‡ç¹¼çºŒï¼Œè«‹æ³¨æ„å¯èƒ½æœƒå°æ‚¨çš„資料庫發生å•題。 +建立備份! + + + + creating collation + 建立定åºè¦å‰‡ + + + + Set a new name for the SQL tab. Use the '&&' character to allow using the following character as a keyboard shortcut. + 為 SQL 分é è¨­å®šä¸€å€‹æ–°å稱。使用「&&ã€å­—元以å…許使用後é¢çš„字元作為éµç›¤å¿«æ·éµã€‚ + + + + Please specify the view name + 請指定檢視表å稱 + + + + There is already an object with that name. Please choose a different name. + 已有相åŒåç¨±çš„ç‰©ä»¶ã€‚è«‹é¸æ“‡ä¸€å€‹ä¸åŒçš„å稱。 + + + + View successfully created. + æˆåŠŸå»ºç«‹æª¢è¦–è¡¨ã€‚ + + + + Error creating view: %1 + 建立檢視表時出ç¾éŒ¯èª¤: %1 + + + + This action will open a new SQL tab for running: + 這個動作將會開啟一個新的 SQL 分é ä»¥é€²è¡ŒåŸ·è¡Œï¼š + + + + Press Help for opening the corresponding SQLite reference page. + 按下「說明ã€ä»¥é–‹å•Ÿå°æ‡‰çš„ SQLite åƒè€ƒé é¢ã€‚ + + + + Busy (%1) + 忙碌 (%1) + + + + NullLineEdit + + + Set to NULL + 設定為 NULL + + + + Alt+Del + Alt+Del + + + + PlotDock + + + Plot + 圖表 + + + + <html><head/><body><p>This pane shows the list of columns of the currently browsed table or the just executed query. You can select the columns that you want to be used as X or Y axis for the plot pane below. The table shows detected axis type that will affect the resulting plot. For the Y axis you can only select numeric columns, but for the X axis you will be able to select:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date/Time</span>: strings with format &quot;yyyy-MM-dd hh:mm:ss&quot; or &quot;yyyy-MM-ddThh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Date</span>: strings with format &quot;yyyy-MM-dd&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Time</span>: strings with format &quot;hh:mm:ss&quot;</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Label</span>: other string formats. Selecting this column as X axis will produce a Bars plot with the column values as labels for the bars</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Numeric</span>: integer or real values</li></ul><p>Double-clicking the Y cells you can change the used color for that graph.</p></body></html> + <html><head/><body><p>æ­¤é¢æ¿é¡¯ç¤ºç›®å‰ç€è¦½çš„表格或剛執行的查詢的資料列清單。您å¯ä»¥é¸æ“‡æ‚¨æƒ³è¦ç”¨ä½œä¸‹æ–¹ç¹ªåœ–颿¿çš„ X 或 Y è»¸çš„è³‡æ–™åˆ—ã€‚è¡¨æ ¼é¡¯ç¤ºæœƒå½±éŸ¿çµæžœåœ–è¡¨çš„åµæ¸¬åˆ°çš„åº§æ¨™è»¸é¡žåž‹ã€‚å°æ–¼ Y 軸,您åªèƒ½é¸æ“‡æ•¸å€¼åˆ—ï¼Œä½†å°æ–¼ X è»¸ï¼Œæ‚¨å°‡èƒ½å¤ é¸æ“‡ï¼š</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">日期/時間</span>:格å¼ç‚º &quot;yyyy-MM-dd hh:mm:ss&quot; 或 &quot;yyyy-MM-ddThh:mm:ss&quot; 的字串</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">日期</span>:格å¼ç‚º &quot;yyyy-MM-dd&quot; 的字串</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">時間</span>:格å¼ç‚º &quot;hh:mm:ss&quot; 的字串</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">標籤</span>:其他字串格å¼ã€‚鏿“‡æ­¤åˆ—作為 X 軸將產生一個柱狀圖,列值作為柱å­çš„æ¨™ç±¤</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">數值</span>:整數或實數值</li></ul><p>點é¸å…©ä¸‹ Y 儲存格,您å¯ä»¥æ›´æ”¹è©²åœ–形使用的é¡è‰²ã€‚</p></body></html> + + + + Columns + 列 + + + + X + X + + + + Y1 + Y1 + + + + Y2 + Y2 + + + + Axis Type + 座標軸類型 + + + + Here is a plot drawn when you select the x and y values above. + +Click on points to select them in the plot and in the table. Ctrl+Click for selecting a range of points. + +Use mouse-wheel for zooming and mouse drag for changing the axis range. + +Select the axes or axes labels to drag and zoom only in that orientation. + é€™æ˜¯ç•¶æ‚¨é¸æ“‡ä¸Šæ–¹çš„ x å’Œ y 值時繪製的圖表。 + +在圖表點é¸å®ƒå€‘å’Œåœ¨è¡¨æ ¼ä¸­é¸æ“‡å®ƒå€‘。 使用 Ctrl + 點é¸ä¾†é¸æ“‡ä¸€ç³»åˆ—的點。 + +使用滑鼠滾輪進行縮放,並拖動滑鼠以改變座標軸範åœã€‚ + +åªé¸æ“‡åº§æ¨™è»¸æˆ–座標軸標籤以在該方å‘上拖動和縮放。 + + + + Line type: + 線型: + + + + + None + ç„¡ + + + + Line + ç·šæ¢ + + + + StepLeft + 左步驟 + + + + StepRight + 峿­¥é©Ÿ + + + + StepCenter + 中心步驟 + + + + Impulse + è„ˆè¡ + + + + Point shape: + 點形狀: + + + + Cross + åå­— + + + + Plus + 加號 + + + + Circle + 圓形 + + + + Disc + 圓盤 + + + + Square + 方形 + + + + Diamond + è±å½¢ + + + + Star + 星形 + + + + Triangle + 三角形 + + + + TriangleInverted + 倒三角形 + + + + CrossSquare + å字方形 + + + + PlusSquare + 加號方形 + + + + CrossCircle + å字圓形 + + + + PlusCircle + 加號圓形 + + + + Peace + 和平 + + + + <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> + <html><head/><body><p>儲存目å‰çš„圖表...</p><p>檔案格å¼ç”±å‰¯æª”å鏿“‡ (png, jpg, pdf, bmp)</p></body></html> + + + + Save current plot... + 儲存目å‰çš„圖表... + + + + + Load all data and redraw plot + 載入所有資料並é‡ç¹ªåœ–表 + + + + + + Row # + 列 # + + + + Copy + 複製 + + + + Print... + 列å°... + + + + Help + + + + + Show legend + 顯示圖例 + + + + Stacked bars + 堆疊長æ¢åœ– + + + + Fixed number format + å›ºå®šæ•¸å­—æ ¼å¼ + + + + Date/Time + 日期/時間 + + + + Date + 日期 + + + + Time + 時間 + + + + + Numeric + 數值 + + + + Label + 標籤 + + + + Invalid + 無效 + + + + Load all data and redraw plot. +Warning: not all data has been fetched from the table yet due to the partial fetch mechanism. + 載入所有資料並é‡ç¹ªåœ–表。 +警告:由於部分å–得機制,尚未從表格å–得所有資料。 + + + + Choose an axis color + 鏿“‡åº§æ¨™è»¸é¡è‰² + + + + Choose a filename to save under + 鏿“‡è¦å„²å­˜çš„æª”案å稱 + + + + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) + PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;所有檔案(*) + + + + There are curves in this plot and the selected line style can only be applied to graphs sorted by X. Either sort the table or query by X to remove curves or select one of the styles supported by curves: None or Line. + 此圖表中有曲線,且所é¸çš„ç·šåž‹åªèƒ½å¥—用於按 X 排åºçš„圖形。請按 X 排åºè¡¨æ ¼æˆ–æŸ¥è©¢ä»¥ç§»é™¤æ›²ç·šï¼Œæˆ–é¸æ“‡æ›²ç·šæ”¯æ´çš„其中一種樣å¼ï¼šç„¡æˆ–ç·šæ¢ã€‚ + + + + Loading all remaining data for this table took %1ms. + 載入此表格所有剩餘資料花了 %1ms。 + + + + PreferencesDialog + + + Preferences + å好é¸é … + + + + &General + &一般 + + + + Remember last location + 記ä½ä¸Šæ¬¡çš„ä½ç½® + + + + Always use this location + 總是使用此ä½ç½® + + + + Remember last location for session only + åªè¨˜ä½æ­¤æ¬¡å·¥ä½œéšŽæ®µçš„ä½ç½® + + + + Lan&guage + 語言(&G) + + + + Show remote options + 顯示é ç«¯é¸é … + + + + Automatic &updates + 自動更新(&U) + + + + &Database + 資料庫(&D) + + + + Database &encoding + 資料庫編碼(&E) + + + + Open databases with foreign keys enabled. + 開啟啟用了外éµçš„資料庫。 + + + + &Foreign keys + 外éµ(&F) + + + + + + + + + + + + + + enabled + 啟用 + + + + Default &location + é è¨­ä½ç½®(&L) + + + + + + ... + ... + + + + Remove line breaks in schema &view + åœ¨çµæ§‹æª¢è¦–中移除æ›è¡Œ(&V) + + + + Prefetch block si&ze + é å–å€å¡Šå¤§å°(&Z) + + + + SQ&L to execute after opening database + 開啟資料庫後執行的 SQL(&L) + + + + Default field type + é è¨­æ¬„ä½é¡žåž‹ + + + + Data &Browser + 資料ç€è¦½å™¨(&B) + + + + Font + å­—åž‹ + + + + &Font + å­—åž‹(&F) + + + + Content + 內容 + + + + Symbol limit in cell + 儲存格中的符號é™åˆ¶ + + + + Threshold for completion and calculation on selection + 鏿“‡å®Œæˆèˆ‡è¨ˆç®—的閾值 + + + + Show images in cell + 在儲存格中顯示圖片 + + + + Enable this option to show a preview of BLOBs containing image data in the cells. This can affect the performance of the data browser, however. + 啟用此é¸é …以在儲存格中顯示包å«åœ–片資料的 BLOB é è¦½ã€‚然而,這å¯èƒ½æœƒå½±éŸ¿è³‡æ–™ç€è¦½å™¨çš„æ•ˆèƒ½ã€‚ + + + + NULL + NULL + + + + Regular + 一般 + + + + Binary + äºŒé€²ä½ + + + + Background + 背景 + + + + Filters + 篩é¸å™¨ + + + + Escape character + 跳脫字元 + + + + Delay time (&ms) + 延鲿™‚é–“ (&ms) + + + + Set the waiting time before a new filter value is applied. Can be set to 0 for disabling waiting. + 設定新的篩é¸å€¼æ‡‰ç”¨å‰çš„等待時間。å¯ä»¥è¨­å®šç‚º 0 以åœç”¨ç­‰å¾…。 + + + + &SQL + &SQL + + + + Context + 上下文 + + + + Colour + é¡è‰² + + + + Bold + ç²—é«” + + + + Italic + 斜體 + + + + Underline + 底線 + + + + Keyword + é—œéµå­— + + + + Function + å‡½å¼ + + + + Table + 資料表 + + + + Comment + 注釋 + + + + Identifier + 識別符號 + + + + String + 字串 + + + + Current line + 這一行 + + + + SQL &editor font size + SQL 編輯器字型大å°(&E) + + + + Tab size + æ¨™ç±¤å¤§å° + + + + SQL editor &font + SQL 編輯器字型(&F) + + + + Error indicators + 錯誤指示器 + + + + Hori&zontal tiling + 水平平鋪(&Z) + + + + If enabled the SQL code editor and the result table view are shown side by side instead of one over the other. + 如果啟用,則 SQL 程å¼ç¢¼ç·¨è¼¯å™¨å’Œçµæžœè¡¨æ ¼æª¢è¦–å°‡ä¸¦æŽ’é¡¯ç¤ºï¼Œè€Œä¸æ˜¯ä¸€å€‹åœ¨å¦ä¸€å€‹ä¸Šé¢ã€‚ + + + + Code co&mpletion + 程å¼ç¢¼è£œå®Œ(&M) + + + + Toolbar style + å·¥å…·åˆ—æ¨£å¼ + + + + + + + + Only display the icon + åªé¡¯ç¤ºåœ–示 + + + + + + + + Only display the text + åªé¡¯ç¤ºæ–‡å­— + + + + + + + + The text appears beside the icon + 文字出ç¾åœ¨åœ–示æ—邊 + + + + + + + + The text appears under the icon + 文字出ç¾åœ¨åœ–示下方 + + + + + + + + Follow the style + è·Ÿéš¨æ¨£å¼ + + + + DB file extensions + 資料庫檔案副檔å + + + + Manage + ç®¡ç† + + + + Main Window + 主視窗 + + + + Database Structure + è³‡æ–™åº«çµæ§‹ + + + + Browse Data + ç€è¦½è³‡æ–™ + + + + Execute SQL + 執行 SQL + + + + Edit Database Cell + 編輯資料庫儲存格 + + + + When this value is changed, all the other color preferences are also set to matching colors. + 當此值變更時,所有其他é¡è‰²å好設定也將設定為相符的é¡è‰²ã€‚ + + + + Follow the desktop style + è·Ÿéš¨æ¡Œé¢æ¨£å¼ + + + + Dark style + æ·±è‰²æ¨£å¼ + + + + Application style + æ‡‰ç”¨ç¨‹å¼æ¨£å¼ + + + + This sets the font size for all UI elements which do not have their own font size option. + 此設定為所有沒有自己的字型大å°é¸é …çš„ UI 元素設定字型大å°ã€‚ + + + + Font size + å­—åž‹å¤§å° + + + + Max Recent Files + æœ€è¿‘çš„æª”æ¡ˆæœ€å¤§æ•¸é‡ + + + + Prompt to save SQL tabs +in new project file + æç¤ºå„²å­˜ SQL åˆ†é  +在新的專案檔案中 + + + + If this is turned on, then changes to the SQL editor generate a save a project confirmation dialog when closing the SQL editor tab. + 如果此é¸é …開啟,則在關閉 SQL ç·¨è¼¯å™¨åˆ†é æ™‚ï¼Œå° SQL 編輯器的變更將產生儲存專案的確èªå°è©±æ¡†ã€‚ + + + + When enabled, the line breaks in the Schema column of the DB Structure tab, dock and printed output are removed. + 當啟用時,將移除 DB çµæ§‹åˆ†é ã€ç¢¼é ­å’Œåˆ—å°è¼¸å‡ºä¸­ç¶±è¦æ¬„ä½çš„æ›è¡Œã€‚ + + + + Database structure font size + è³‡æ–™åº«çµæ§‹å­—åž‹å¤§å° + + + + Font si&ze + 字型大å°(&Z) + + + + This is the maximum number of items allowed for some computationally expensive functionalities to be enabled: +Maximum number of rows in a table for enabling the value completion based on current values in the column. +Maximum number of indexes in a selection for calculating sum and average. +Can be set to 0 for disabling the functionalities. + 這是為了啟用一些高密度計算功能所å…許的項目最大數é‡ï¼š +å•Ÿç”¨ä¾æ“šç›®å‰æ¬„ä½å€¼å®Œæˆæ•¸å€¼çš„表格所å…許的最大行數。 +鏿“‡ç¯„åœä¸­ç”¨ä»¥è¨ˆç®—總和和平å‡å€¼çš„索引的最大數é‡ã€‚ +å¯ä»¥è¨­å®šç‚º 0 以åœç”¨é€™äº›åŠŸèƒ½ã€‚ + + + + This is the maximum number of rows in a table for enabling the value completion based on current values in the column. +Can be set to 0 for disabling completion. + é€™æ˜¯ç‚ºäº†å•Ÿç”¨ä¾æ“šç›®å‰æ¬„ä½å€¼çš„自動完æˆåŠŸèƒ½æ‰€å…許的最大行數。 +設定為 0 å¯ä»¥åœç”¨è‡ªå‹•完æˆåŠŸèƒ½ã€‚ + + + + Field display + 欄ä½é¡¯ç¤º + + + + Light style + 淺色風格 + + + + Displayed &text + 顯示的文字(&T) + + + + Formatted + 已格å¼åŒ– + + + + + + + + + + + Click to set this color + 點é¸ä»¥è¨­å®šæ­¤é¡è‰² + + + + Text color + 文字é¡è‰² + + + + Background color + 背景é¡è‰² + + + + + Preview only (N/A) + 僅é è¦½ï¼ˆä¸é©ç”¨ï¼‰ + + + + Foreground + 剿™¯ + + + + Selection background + 鏿“‡çš„背景 + + + + Selection foreground + 鏿“‡çš„剿™¯ + + + + Highlight + 醒目顯示 + + + + SQL &results font size + SQL çµæžœå­—型大å°(&R) + + + + Use tabs for indentation + 使用 Tab 進行縮排 + + + + When set, the Tab key will insert tab and space characters for indentation. Otherwise, just spaces will be used. + 設定後,按下 Tab 鵿œƒç”¨ Tab å’Œç©ºæ ¼é€²è¡Œç¸®æŽ’ï¼›å¦‚æžœæœªè¨­å®šï¼Œå‰‡åªæœƒç”¨ç©ºæ ¼ä¾†ç¸®æŽ’。 + + + + &Wrap lines + æ›è¡Œ(&W) + + + + Never + æ°¸ä¸ + + + + At word boundaries + 在字詞邊界 + + + + At character boundaries + 在字元邊界 + + + + At whitespace boundaries + 在空白邊界 + + + + &Quotes for identifiers + 識別符號的引號(&Q) + + + + Choose the quoting mechanism used by the application for identifiers in SQL code. + 鏿“‡æ‡‰ç”¨ç¨‹å¼åœ¨ SQL 程å¼ç¢¼ä¸­ç”¨æ–¼è­˜åˆ¥ç¬¦è™Ÿçš„引號機制。 + + + + "Double quotes" - Standard SQL (recommended) + "雙引號" - 標準 SQL(推薦) + + + + `Grave accents` - Traditional MySQL quotes + `é‡éŸ³ç¬¦è™Ÿ` - 傳統 MySQL 引號 + + + + [Square brackets] - Traditional MS SQL Server quotes + [方括號] - 傳統 MS SQL Server 引號 + + + + Keywords in &UPPER CASE + é—œéµå­—使用 &大寫 + + + + When set, the SQL keywords are completed in UPPER CASE letters. + 當設定時,SQL é—œéµå­—將以大寫字æ¯å®Œæˆã€‚ + + + + When set, the SQL code lines that caused errors during the last execution are highlighted and the results frame indicates the error in the background + 當設定時,上次執行期間造æˆéŒ¯èª¤çš„ SQL 程å¼ç¢¼è¡Œå°‡è¢«é†’ç›®é¡¯ç¤ºï¼Œä¸¦ä¸”çµæžœæ¡†æž¶åœ¨èƒŒæ™¯ä¸­æŒ‡ç¤ºéŒ¯èª¤ + + + + Close button on tabs + 分é ä¸Šçš„關閉按鈕 + + + + If enabled, SQL editor tabs will have a close button. In any case, you can use the contextual menu or the keyboard shortcut to close them. + 如果啟用,SQL 編輯器分é å°‡æœ‰ä¸€å€‹é—œé–‰æŒ‰éˆ•。無論如何,您都å¯ä»¥ä½¿ç”¨ä¸Šä¸‹æ–‡é¸å–®æˆ–éµç›¤å¿«é€Ÿéµä¾†é—œé–‰å®ƒå€‘。 + + + + &Extensions + 擴充套件(&E) + + + + Select extensions to load for every database: + 鏿“‡æ¯å€‹è³‡æ–™åº«è¦è¼‰å…¥çš„æ“´å……套件: + + + + Add extension + 加入擴充套件 + + + + Remove extension + 移除擴充套件 + + + + Select built-in extensions to load for every database: + + + + + <html><head/><body><p>While supporting the REGEXP operator SQLite doesn't implement any regular expression<br/>algorithm but calls back the running application. DB Browser for SQLite implements this<br/>algorithm for you to let you use REGEXP out of the box. However, as there are multiple possible<br/>implementations of this and you might want to use another one, you're free to disable the<br/>application's implementation and load your own by using an extension. Requires restart of the application.</p></body></html> + <html><head/><body><p>é›–ç„¶ SQLite æ”¯æ´ REGEXP é‹ç®—å­ï¼Œä½†ä¸¦æœªå¯¦ä½œä»»ä½•æ­£è¦è¡¨é”å¼<br/>演算法,而是回呼正在執行的應用程å¼ã€‚DB Browser for SQLite 為您實作了此<br/>演算法,讓您å¯ä»¥ç›´æŽ¥ä½¿ç”¨ REGEXP。然而,由於此有多種å¯èƒ½çš„<br/>實作方å¼ï¼Œæ‚¨å¯èƒ½æƒ³è¦ä½¿ç”¨å¦ä¸€ç¨®ï¼Œæ‚¨å¯ä»¥è‡ªç”±åœ°åœç”¨<br/>應用程å¼çš„實作,並使用擴充套件載入您自己的實作。需è¦é‡æ–°å•Ÿå‹•應用程å¼ã€‚</p></body></html> + + + + Disable Regular Expression extension + åœç”¨æ­£è¦è¡¨é”弿“´å……套件 + + + + <html><head/><body><p>SQLite provides an SQL function for loading extensions from a shared library file. Activate this if you want to use the <span style=" font-style:italic;">load_extension()</span> function from SQL code.</p><p>For security reasons, extension loading is turned off by default and must be enabled through this setting. You can always load extensions through the GUI, even though this option is disabled.</p></body></html> + <html><head/><body><p>SQLite æä¾›äº†ä¸€å€‹ SQL 函å¼ï¼Œç”¨æ–¼å¾žå…±äº«å‡½å¼åº«æª”案載入擴充套件。如果您想è¦å¾ž SQL 程å¼ç¢¼ä½¿ç”¨ <span style=" font-style:italic;">load_extension()</span> 函å¼ï¼Œè«‹å•Ÿç”¨æ­¤é¸é …。</p><p>出於安全考é‡ï¼Œé è¨­æœƒé—œé–‰æ“´å……套件載入,必須é€éŽæ­¤è¨­å®šä¾†å•Ÿç”¨ã€‚å³ä½¿æ­¤é¸é …被åœç”¨ï¼Œæ‚¨ä»ç„¶å¯ä»¥é€éŽ GUI 載入擴充套件。</p></body></html> + + + + Allow loading extensions from SQL code + å…許從 SQL 程å¼ç¢¼è¼‰å…¥æ“´å……套件 + + + + Remote + é ç«¯ + + + + CA certificates + CA 憑證 + + + + Proxy + 代ç†ä¼ºæœå™¨ + + + + Configure + 設定 + + + + Export Settings + 匯出設定 + + + + Import Settings + 匯入設定 + + + + + Subject CN + 主題 CN + + + + Common Name + 一般å稱 + + + + Subject O + 主體 O + + + + Organization + 組織 + + + + + Valid from + 有效期é™å¾ž + + + + + Valid to + 有效期é™è‡³ + + + + + Serial number + åºè™Ÿ + + + + Your certificates + 您的憑證 + + + + File + 檔案 + + + + Subject Common Name + 主體通用å稱 + + + + Issuer CN + 簽發者 CN + + + + Issuer Common Name + 簽發者通用å稱 + + + + Clone databases into + 複製資料庫到 + + + + + Choose a directory + 鏿“‡ä¸€å€‹ç›®éŒ„ + + + + + The language will change after you restart the application. + 釿–°å•Ÿå‹•應用程å¼å¾Œï¼Œèªžè¨€å°‡æœƒè®Šæ›´ã€‚ + + + + Select extension file + 鏿“‡æ“´å……套件檔案 + + + + Extensions(*.so *.dylib *.dll);;All files(*) + 擴充套件(*.so *.dylib *.dll);;所有檔案(*) + + + + Import certificate file + 匯入憑證檔案 + + + + No certificates found in this file. + 在此檔案中未找到憑證。 + + + + Are you sure you want do remove this certificate? All certificate data will be deleted from the application settings! + 您確定è¦ç§»é™¤æ­¤æ†‘證嗎?所有憑證資料將從應用程å¼è¨­å®šä¸­åˆªé™¤ï¼ + + + + Are you sure you want to clear all the saved settings? +All your preferences will be lost and default values will be used. + æ‚¨ç¢ºå®šè¦æ¸…除所有已儲存的設定嗎? +所有的å好設定將會éºå¤±ï¼Œä¸¦ä¸”將使用é è¨­å€¼ã€‚ + + + + Save Settings File + 儲存設定檔 + + + + + Initialization File (*.ini) + åˆå§‹åŒ–檔案(*.ini) + + + + The settings file has been saved in location : + + 設定檔已儲存於以下ä½ç½®ï¼š + + + + + Open Settings File + 開啟設定檔 + + + + The settings file was loaded properly. + 設定檔已正確載入。 + + + + The selected settings file is not a normal settings file. +Please check again. + 所é¸çš„è¨­å®šæª”ä¸¦éžæ­£å¸¸çš„設定檔。 +è«‹å†æ¬¡æª¢æŸ¥ã€‚ + + + + ProxyDialog + + + Proxy Configuration + 代ç†ä¼ºæœå™¨è¨­å®š + + + + Pro&xy Type + 代ç†ä¼ºæœå™¨é¡žåž‹ + + + + Host Na&me + 主機å稱 + + + + Port + 連接埠 + + + + Authentication Re&quired + 需è¦é©—è­‰ + + + + &User Name + 使用者å稱 + + + + Password + 密碼 + + + + None + ç„¡ + + + + System settings + 系統設定 + + + + HTTP + HTTP + + + + SOCKS5 + SOCKS5 + + + + QObject + + + Error importing data + 匯入資料時發生錯誤 + + + + from record number %1 + 從記錄編號 %1 + + + + . +%1 + . +%1 + + + + Importing CSV file... + 正在匯入 CSV 檔案... + + + + Cancel + å–æ¶ˆ + + + + All files (*) + 所有檔案 (*) + + + + SQLite database files (*.db *.sqlite *.sqlite3 *.db3) + SQLite 資料庫檔案 (*.db *.sqlite *.sqlite3 *.db3) + + + + Left + é å·¦ + + + + Right + é å³ + + + + Center + 置中 + + + + Justify + å·¦å³å°é½Š + + + + SQLite Database Files (*.db *.sqlite *.sqlite3 *.db3) + SQLite 資料庫檔案 (*.db *.sqlite *.sqlite3 *.db3) + + + + DB Browser for SQLite Project Files (*.sqbpro) + DB Browser for SQLite 專案檔案 (*.sqbpro) + + + + SQL Files (*.sql) + SQL 檔案 (*.sql) + + + + All Files (*) + 所有檔案 (*) + + + + Text Files (*.txt) + 文字檔案 (*.txt) + + + + Comma-Separated Values Files (*.csv) + 逗點分隔值檔案 (*.csv) + + + + Tab-Separated Values Files (*.tsv) + 定ä½å­—元分隔值檔案 (*.tsv) + + + + Delimiter-Separated Values Files (*.dsv) + 分隔符號分隔值檔案 (*.dsv) + + + + Concordance DAT files (*.dat) + Concordance DAT 檔案 (*.dat) + + + + JSON Files (*.json *.js) + JSON 檔案 (*.json *.js) + + + + XML Files (*.xml) + XML 檔案 (*.xml) + + + + Binary Files (*.bin *.dat) + äºŒé€²ä½æª”案 (*.bin *.dat) + + + + SVG Files (*.svg) + SVG 檔案 (*.svg) + + + + Hex Dump Files (*.dat *.bin) + å六進ä½è½‰å„²æª”案 (*.dat *.bin) + + + + Extensions (*.so *.dylib *.dll) + 擴充套件 (*.so *.dylib *.dll) + + + + Initialization File (*.ini) + åˆå§‹åŒ–檔案 (*.ini) + + + + QsciCommand + + Paste + 貼上 + + + Cancel + å–æ¶ˆ + + + + QsciLexerCPP + + Default + é è¨­ + + + Keyword + é—œéµå­— + + + Identifier + 識別符號 + + + + QsciLexerJSON + + Default + é è¨­ + + + String + 字串 + + + + QsciLexerJavaScript + + Regular expression + æ­£è¦è¡¨é”å¼ + + + + QsciLexerPython + + Default + é è¨­ + + + Comment + 注釋 + + + Keyword + é—œéµå­— + + + Identifier + 識別符號 + + + + QsciLexerSQL + + Default + é è¨­ + + + Comment + 注釋 + + + Keyword + é—œéµå­— + + + Identifier + 識別符號 + + + + QsciScintilla + + &Undo + &復原 + + + + RemoteCommitsModel + + + Commit ID + æäº¤ ID + + + + Message + è¨Šæ¯ + + + + Date + 日期 + + + + Author + 作者 + + + + Size + å¤§å° + + + + Authored and committed by %1 + ç”± %1 撰寫並æäº¤ + + + + Authored by %1, committed by %2 + ç”± %1 撰寫,由 %2 æäº¤ + + + + RemoteDatabase + + + Error opening local databases list. +%1 + 開啟本機資料庫清單時發生錯誤。 +%1 + + + + Error creating local databases list. +%1 + 建立本機資料庫清單時發生錯誤。 +%1 + + + + RemoteDock + + + Remote + é ç«¯ + + + + Identity + 身份 + + + + Push currently opened database to server + 將目å‰é–‹å•Ÿçš„資料庫推é€åˆ°ä¼ºæœå™¨ + + + + Upload + 上傳 + + + + DBHub.io + DBHub.io + + + + <html><head/><body><p>In this pane, remote databases from dbhub.io website can be added to DB Browser for SQLite. First you need an identity:</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Login to the dbhub.io website (use your GitHub credentials or whatever you want)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click the button to &quot;Generate client certificate&quot; (that's your identity). That'll give you a certificate file (save it to your local disk).</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Go to the Remote tab in DB Browser for SQLite Preferences. Click the button to add a new certificate to DB Browser for SQLite and choose the just downloaded certificate file.</li></ol><p>Now the Remote panel shows your identity and you can add remote databases.</p></body></html> + <html><head/><body><p>åœ¨æ­¤é¢æ¿ä¸­ï¼Œæ‚¨å¯ä»¥å°‡ä¾†è‡ª dbhub.io 網站的é ç«¯è³‡æ–™åº«æ–°å¢žè‡³ DB Browser for SQLite。首先,您需è¦ä¸€å€‹èº«ä»½è­˜åˆ¥ï¼š</p><ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">登入 dbhub.io 網站(å¯ä½¿ç”¨æ‚¨çš„ GitHub æ†‘è­‰æˆ–å…¶ä»–æ‚¨é¸æ“‡çš„æ–¹å¼ï¼‰</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">點é¸ã€Œç”¢ç”Ÿå®¢æˆ¶ç«¯æ†‘è­‰ã€æŒ‰éˆ•(這就是您的身份識別)。這會æä¾›æ‚¨ä¸€å€‹æ†‘證檔案(請將其儲存至您的本機ç£ç¢Ÿï¼‰</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">å‰å¾€ DB Browser for SQLite å好設定中的é ç«¯æ¨™ç±¤ã€‚é»žé¸æŒ‰éˆ•以將新的憑證新增至 DB Browser for SQLiteï¼Œä¸¦é¸æ“‡æ‚¨å‰›ä¸‹è¼‰çš„æ†‘證檔案。</li></ol><p>ç¾åœ¨ï¼Œé ç«¯é¢æ¿æœƒé¡¯ç¤ºæ‚¨çš„身份識別,您便å¯ä»¥æ–°å¢žé ç«¯è³‡æ–™åº«ã€‚</p></body></html> + + + + Local + 本機 + + + + Current Database + ç›®å‰çš„資料庫 + + + + Clone + 複製 + + + + &User + 使用者 + + + + &Database + 資料庫(&D) + + + + Branch + 分支 + + + + Commits + æäº¤ + + + + Commits for + æäº¤çµ¦ + + + + <html><head/><body><p>You are currently using a built-in, read-only identity. For uploading your database, you need to configure and use your DBHub.io account.</p><p>No DBHub.io account yet? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">Create one now</span></a> and import your certificate <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">here</span></a> to share your databases.</p><p>For online help visit <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">here</span></a>.</p></body></html> + <html><head/><body><p>æ‚¨ç›®å‰æ­£åœ¨ä½¿ç”¨å…§å»ºçš„唯讀身份。è¦ä¸Šå‚³æ‚¨çš„資料庫,您需è¦è¨­å®šä¸¦ä½¿ç”¨æ‚¨çš„ DBHub.io 帳戶。</p><p>還沒有 DBHub.io 帳戶嗎? <a href="https://dbhub.io/"><span style=" text-decoration: underline; color:#007af4;">ç¾åœ¨å°±å»ºç«‹ä¸€å€‹</span></a>,並將您的憑證匯入 <a href="#preferences"><span style=" text-decoration: underline; color:#007af4;">此處</span></a>,以分享您的資料庫。</p><p>如需線上支æ´ï¼Œè«‹é€ è¨ª <a href="https://dbhub.io/about"><span style=" text-decoration: underline; color:#007af4;">此處</span></a>。</p></body></html> + + + + Back + 返回 + + + + Delete Database + 刪除資料庫 + + + + Delete the local clone of this database + 刪除此資料庫的本機複製 + + + + Open in Web Browser + 在網é ç€è¦½å™¨ä¸­é–‹å•Ÿ + + + + Open the web page for the current database in your browser + 在您的ç€è¦½å™¨ä¸­é–‹å•Ÿç›®å‰è³‡æ–™åº«çš„ç¶²é  + + + + Clone from Link + 從連çµè¤‡è£½ + + + + Use this to download a remote database for local editing using a URL as provided on the web page of the database. + 使用此功能,é€éŽè³‡æ–™åº«ç¶²é ä¸Šæä¾›çš„ URL 下載é ç«¯è³‡æ–™åº«é€²è¡Œæœ¬æ©Ÿç·¨è¼¯ã€‚ + + + + Refresh + 釿–°æ•´ç† + + + + Reload all data and update the views + 釿–°è¼‰å…¥æ‰€æœ‰è³‡æ–™ä¸¦æ›´æ–°æª¢è¦–表 + + + + Clone Database + 複製資料庫 + + + + Open Database + 開啟資料庫 + + + + Open the local copy of this database + 開啟此資料庫的本機複製 + + + + Check out Commit + 查看æäº¤ + + + + Download and open this specific commit + 下載並開啟此特定æäº¤ + - - Edit table definition - 編輯資料表定義 + + Check out Latest Commit + 查看最新æäº¤ - - Table - 資料表 + + Check out the latest commit of the current branch + 查看目å‰åˆ†æ”¯çš„æœ€æ–°æäº¤ - - Fields - æ¬„ä½ + + Save Revision to File + 將修訂版本儲存到檔案 - - Add field - åŠ å…¥æ¬„ä½ + + Saves the selected revision of the database to another file + 將鏿“‡çš„資料庫修訂版本儲存到å¦ä¸€å€‹æª”案 - - Remove field - åˆªé™¤æ¬„ä½ + + Upload Database + 上傳資料庫 - - Move field up - ä¸Šç§»æ¬„ä½ + + Upload this database as a new commit + 將此資料庫作為新的æäº¤ä¸Šå‚³ - - Move field down - ä¸‹ç§»æ¬„ä½ + + Select an identity to connect + 鏿“‡ä¸€å€‹èº«ä»½é€²è¡Œé€£æŽ¥ - - Name - å稱 + + Public + 公開 - - Type - 類型 + + This downloads a database from a remote server for local editing. +Please enter the URL to clone from. You can generate this URL by +clicking the 'Clone Database in DB4S' button on the web page +of the database. + 這將從é ç«¯ä¼ºæœå™¨ä¸‹è¼‰è³‡æ–™åº«é€²è¡Œæœ¬æ©Ÿç·¨è¼¯ã€‚ +請輸入è¦è¤‡è£½çš„ URL。您å¯ä»¥åœ¨è³‡æ–™åº«çš„ç¶²é ä¸Š +點é¸ã€Œåœ¨ DB4S ä¸­è¤‡è£½è³‡æ–™åº«ã€æŒ‰éˆ•來產生此 URL。 - - - Not null - éžç©º + + Invalid URL: The host name does not match the host name of the current identity. + 無效的 URL:主機å稱與目å‰èº«ä»½çš„主機å稱ä¸ç¬¦ã€‚ - - PK - PK + + Invalid URL: No branch name specified. + 無效的 URL:未指定分支å稱。 - - Primary key - ä¸»éµ + + Invalid URL: No commit ID specified. + 無效的 URL:未指定æäº¤ ID。 - - AI - AI + + You have modified the local clone of the database. Fetching this commit overrides these local changes. +Are you sure you want to proceed? + 您已修改資料庫的本機複製版本。å–得這個æäº¤å°‡è¦†è“‹é€™äº›æœ¬æ©Ÿä¿®æ”¹ã€‚ +您確定è¦ç¹¼çºŒå—Žï¼Ÿ - - Autoincrement - 自動增值 + + The database has unsaved changes. Are you sure you want to push it before saving? + 資料庫有未儲存的變更。您確定è¦åœ¨å„²å­˜ä¹‹å‰æŽ¨é€å®ƒå—Žï¼Ÿ - - Default - é è¨­ + + The database you are trying to delete is currently opened. Please close it before deleting. + 您嘗試刪除的資料庫目å‰å·²é–‹å•Ÿã€‚請在刪除之å‰é—œé–‰å®ƒã€‚ - - Default value - é è¨­å€¼ + + This deletes the local version of this database with all the changes you have not committed yet. Are you sure you want to delete this database? + 這將刪除此資料庫的本機版本,包括所有您尚未æäº¤çš„變更。您確定è¦åˆªé™¤æ­¤è³‡æ–™åº«å—Žï¼Ÿ + + + RemoteLocalFilesModel - - Check - 檢查 + + Name + å稱 - - Check constraint - æª¢æŸ¥ç´„æŸæ¢ä»¶ + + Branch + 分支 - - Error creating table. Message from database engine: -%1 - 建立資料表時出ç¾éŒ¯èª¤ã€‚來自資料庫引擎的消æ¯: -%1 + + Last modified + 最後修改 - - There is at least one row with this field set to NULL. This makes it impossible to set this flag. Please change the table data first. - 至少有一行帶本欄ä½çš„記錄被設為空。這使得它ä¸å¯èƒ½è¨­å®šé€™å€‹æ¨™èªŒã€‚請首先修改資料表資料。 + + Size + å¤§å° - - There is at least one row with a non-integer value in this field. This makes it impossible to set the AI flag. Please change the table data first. - 在這個欄ä½ä¸­è‡³å°‘æœ‰ä¸€è¡Œå¸¶æœ‰ä¸€å€‹éžæ•´æ•¸çš„值。這使得它ä¸å¯èƒ½è¨­å®š AI 標誌。請首先修改資料表資料。 + + Commit + æäº¤ - - Are you sure you want to delete the field '%1'? -All data currently stored in this field will be lost. - 您是å¦ç¢ºèªæ‚¨æƒ³åˆªé™¤æ¬„ä½ '%1'? -ç›®å‰å­˜å„²åœ¨é€™å€‹æ¬„ä½ä¸­çš„æ‰€æœ‰è³‡æ–™å°‡æœƒéºå¤±ã€‚ + + File + 檔案 - ExportCsvDialog + RemoteModel - - Export data as CSV - 匯出資料為 CSV + + Name + å稱 - - &Table - 資料表(&T) + + Commit + æäº¤ - - &Column names in first line - 列å在首行(&C) + + Last modified + 最後修改 - - Field &separator - 欄ä½åˆ†éš”符號(&S) + + Size + å¤§å° - - , - , + + Size: + 大å°ï¼š - - ; - ; + + Last Modified: + 最後修改: - - - Tab - Tab + + Licence: + 授權: - - | - | + + Default Branch: + é è¨­åˆ†æ”¯ï¼š + + + RemoteNetwork - - - Other - 其它 + + Choose a location to save the file + 鏿“‡å„²å­˜æª”案的ä½ç½® - - &Quote character - 引號(&Q) + + Error opening remote file at %1. +%2 + 開啟é ç«¯æª”案 %1 錯誤。 +%2 - - " - " + + Error: Invalid client certificate specified. + 錯誤:指定的客戶端憑證無效。 - - ' - ' + + Please enter the passphrase for this client certificate in order to authenticate. + 請輸入此客戶端憑證的密碼以進行驗證。 - - Choose a filename to export data - 鏿“‡åŒ¯å‡ºè³‡æ–™çš„æª”案å稱 + + Cancel + å–æ¶ˆ - - Text files(*.csv *.txt) - 文字檔案(*.csv *.txt) + + Uploading remote database to +%1 + 正在上傳é ç«¯è³‡æ–™åº«åˆ° +%1 - - Export completed. - 匯出完æˆã€‚ + + Downloading remote database from +%1 + 正在從 +%1 下載é ç«¯è³‡æ–™åº« - - Could not open output file. - 無法打開輸出檔案。 + + Error: Cannot open the file for sending. + 錯誤:無法開啟è¦å‚³é€çš„æª”案。 - FilterTableHeader + RemotePushDialog - - Filter - éŽæ¿¾ + + Push database + 推é€è³‡æ–™åº« - - - ImportCsvDialog - - Import CSV file - 匯入 CSV 檔案 + + Database na&me to push to + è¦æŽ¨é€çš„資料庫å稱 - - &Table name - 資料表å稱(&T) + + Commit message + æäº¤è¨Šæ¯ - - &Column names in first line - 列å在首行(&C) + + Database licence + 資料庫授權 - - Field &separator - 欄ä½åˆ†éš”符號(&S) + + Public + 公開 - - , - , + + Branch + 分支 - - ; - ; + + Force push + å¼·åˆ¶æŽ¨é€ - - - Tab - Tab + + Username + 使用者å稱 - - | - ; + + Database will be public. Everyone has read access to it. + 資料庫將會公開。æ¯å€‹äººéƒ½æœ‰è®€å–權é™ã€‚ - - - Other - 其它 + + Database will be private. Only you have access to it. + è³‡æ–™åº«å°‡æœƒç§æœ‰åŒ–ã€‚åªæœ‰æ‚¨æœ‰å­˜å–權é™ã€‚ - - &Quote character - 引號(&Q) + + Use with care. This can cause remote commits to be deleted. + è«‹å°å¿ƒä½¿ç”¨ã€‚這å¯èƒ½æœƒå°Žè‡´é ç«¯çš„æäº¤è¢«åˆªé™¤ã€‚ + + + RunSql - - " - ; + + Execution aborted by user + 使用者已中止執行 - - ' - ' + + , %1 rows affected + ,影響了 %1 行 - - Inserting data... - 正在æ’入資料... + + query executed successfully. Took %1ms%2 + 查詢æˆåŠŸåŸ·è¡Œã€‚èŠ±è²»äº† %1ms%2 - - Cancel - å–æ¶ˆ + + executing query + 正在執行查詢 + + + SelectItemsPopup - - There is already a table of that name and an import into an existing table is only possible if the number of columns match. - 已有åŒåçš„è³‡æ–™è¡¨ï¼Œä¸¦ä¸”åŒ¯å…¥åªæœ‰åœ¨åˆ—數相符的情æ³ä¸‹æ‰èƒ½åŒ¯å…¥åˆ°ä¸€å€‹ç¾æœ‰çš„資料表。 + + A&vailable + å¯ç”¨çš„ - - There is already a table of that name. Do you want to import the data into it? - 已有åŒåçš„è³‡æ–™è¡¨ã€‚æ‚¨æ˜¯å¦æƒ³åŒ¯å…¥è³‡æ–™åˆ°å…¶ä¸­? + + Sele&cted + 已鏿“‡çš„ - MainWindow + SqlExecutionArea - - SQLiteBrowser - SQLiteBrowser + + Form + 表單 - - Database &Structure - è³‡æ–™åº«çµæ§‹(&S) + + Find previous match [Shift+F3] + 尋找å‰ä¸€å€‹ç¬¦åˆ [Shift+F3] - - - toolBar1 - + + Find previous match with wrapping + 尋找上一個符åˆä¸¦æ›è¡Œ - - &Browse Data - ç€è¦½è³‡æ–™(&B) + + Shift+F3 + Shift+F3 - - Table: - 資料表: + + The found pattern must be a whole word + æœå°‹åˆ°çš„字串必須是一個完整的單詞 - - Select a table to browse data - 鏿“‡ä¸€å€‹è³‡æ–™è¡¨ä»¥ç€è¦½è³‡æ–™ + + Whole Words + 完整單詞 - - Use this list to select a table to be displayed in the database view - ä½¿ç”¨é€™å€‹æ¸…å–®é¸æ“‡ä¸€å€‹è¦é¡¯ç¤ºåœ¨è³‡æ–™åº«è¦–圖中的資料表 + + Text pattern to find considering the checks in this frame + è€ƒæ…®æ­¤æ¡†æž¶ä¸­çš„æª¢æŸ¥ä¾†å°‹æ‰¾æ–‡å­—æ¨¡å¼ - - Refresh the data in the selected table. - æ›´æ–°é¸æ“‡çš„資料表中的資料。 + + Find in editor + 在編輯器中尋找 - - This button refreshes the data in the currently selected table. - 這個按鈕更新在目å‰é¸æ“‡çš„資料表中的資料。 + + The found pattern must match in letter case + æœå°‹åˆ°çš„字串必須符åˆå¤§å°å¯« - - - F5 - F5 + + Case Sensitive + å€åˆ†å¤§å°å¯« - - Insert a new record in the current table - 在目å‰è³‡æ–™è¡¨ä¸­æ’å…¥ä¸€æ¢æ–°è¨˜éŒ„ + + Find next match [Enter, F3] + å°‹æ‰¾ä¸‹ä¸€å€‹ç¬¦åˆ [Enter, F3] - - This button creates a new, empty record in the database - é€™å€‹æŒ‰éˆ•åœ¨è³‡æ–™åº«ä¸­å»ºç«‹ä¸€æ¢æ–°çš„空白記錄 + + Find next match with wrapping + 尋找下一個符åˆä¸¦æ›è¡Œ - - New Record - 新建記錄 + + F3 + F3 - - Delete the current record - 刪除目å‰è¨˜éŒ„ + + Interpret search pattern as a regular expression + å°‡æœå°‹æ¨¡å¼è§£é‡‹ç‚ºæ­£è¦è¡¨é”å¼ - - This button deletes the record currently selected in the database - 這個按鈕刪除在資料庫中目å‰é¸æ“‡çš„記錄 + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>ç•¶é¸å–時,將尋找的模å¼è§£é‡‹ç‚º UNIX æ­£è¦è¡¨é”å¼ã€‚è«‹åƒè¦‹ <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Wikibooks 中的正è¦è¡¨é”å¼</a>。</p></body></html> - - Delete Record - 刪除記錄 + + Regular Expression + æ­£è¦è¡¨é”å¼ - - This is the database view. You can double-click any record to edit its contents in the cell editor window. - 這是資料庫視圖。您å¯ä»¥æŒ‰å…©ä¸‹ä»»ä½•記錄,在儲存格編輯器視窗中編輯記錄內容。 + + + Close Find Bar + 關閉尋找工具列 - - < - < + + <html><head/><body><p>Results of the last executed statements.</p><p>You may want to collapse this panel and use the <span style=" font-style:italic;">SQL Log</span> dock with <span style=" font-style:italic;">User</span> selection instead.</p></body></html> + <html><head/><body><p>最後執行陳述å¼çš„çµæžœã€‚</p><p>您å¯èƒ½æƒ³è¦æ‘ºç–Šæ­¤é¢æ¿ï¼Œä¸¦ä½¿ç”¨ <span style=" font-style:italic;">SQL 日誌</span> ç¢¼é ­ï¼Œä¸¦é¸æ“‡ <span style=" font-style:italic;">使用者</span>。</p></body></html> - - 0 - 0 of 0 - 0 - 0 / 0 + + Results of the last executed statements + 最後執行陳述å¼çš„çµæžœ - - > - > + + This field shows the results and status codes of the last executed statements. + 此欄ä½é¡¯ç¤ºæœ€å¾ŒåŸ·è¡Œçš„陳述å¼çš„çµæžœå’Œç‹€æ…‹ç¢¼ã€‚ - - Scroll 100 records upwards - 上滾 100 æ¢è¨˜éŒ„ + + Ctrl+PgUp + Ctrl+PgUp - - <html><head/><body><p>Clicking this button navigates 100 records upwards in the table view above.</p></body></html> - <html><head/><body><p>點擊這個按鈕在上é¢çš„資料表視圖中å‘上導航 100 æ¢è¨˜éŒ„。</p></body></html> + + Ctrl+PgDown + Ctrl+PgDown - - <html><head/><body><p>Scroll 100 records downwards</p></body></html> - <html><head/><body><p>下滾 100 æ¢è¨˜éŒ„</p></body></html> + + Couldn't read file "%1": %2. + ç„¡æ³•è®€å–æª”案「%1ã€ï¼š%2。 - - <html><head/><body><p>Clicking this button navigates 100 records downwards in the table view above.</p></body></html> - <html><head/><body><p>點擊這個按鈕在上é¢çš„資料表視圖中å‘下導航 100 æ¢è¨˜éŒ„。</p></body></html> + + + Couldn't save file: %1. + 無法儲存檔案:%1。 - - <html><head/><body><p>Click here to jump to the specified record</p></body></html> - <html><head/><body><p>點擊這裡跳到指定的記錄</p></body></html> + + Your changes will be lost when reloading it! + 釿–°è¼‰å…¥æ™‚,您的變更將會éºå¤±ï¼ - - <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> - <html><head/><body><p>這個按鈕用於導航到在“轉到â€å€åŸŸä¸­æŒ‡å®šçš„記錄編號。</p></body></html> + + The file "%1" was modified by another program. Do you want to reload it?%2 + 檔案「%1ã€å·²è¢«å…¶ä»–程å¼ä¿®æ”¹ã€‚您è¦é‡æ–°è¼‰å…¥å—Žï¼Ÿ%2 - - Go to: - 轉到: + + Answer "Yes to All" to reload the file on any external update without further prompting. + 回答「全部皆是ã€ä»¥åœ¨ä»»ä½•å¤–éƒ¨æ›´æ–°æ™‚ç„¡éœ€å†æ¬¡æç¤ºä¾¿é‡æ–°è¼‰å…¥æª”案。 - - Enter record number to browse - 輸入è¦ç€è¦½çš„記錄編號 + + Answer "No to All" to ignore any external update without further prompting. + 回答「全部皆å¦ã€ä»¥åœ¨ä»»ä½•å¤–éƒ¨æ›´æ–°æ™‚ç„¡éœ€å†æ¬¡æç¤ºä¾¿å¿½ç•¥ã€‚ - - Type a record number in this area and click the Go to: button to display the record in the database view - 在這個å€åŸŸä¸­è¼¸å…¥ä¸€å€‹è¨˜éŒ„編號,並點擊“轉到:â€æŒ‰éˆ•以在資料庫視圖中顯示記錄 + + Modifying and saving the file will restore prompting. + 修改並儲存檔案將會æ¢å¾©æç¤ºã€‚ + + + SqlTextEdit - - 1 - 1 + + Ctrl+/ + Ctrl+/ + + + SqlUiLexer - - Edit &Pragmas - 編輯雜注(&P) + + (X) The abs(X) function returns the absolute value of the numeric argument X. + (X) abs(X) 函å¼å›žå‚³æ•¸å€¼åƒæ•¸ X 的絕å°å€¼ã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">Auto Vacuum</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_auto_vacuum"><span style=" text-decoration: underline; color:#0000ff;">自動真空</span></a></p></body></html> + + () The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement. + () changes() 函å¼å›žå‚³æœ€è¿‘完æˆçš„ INSERTã€DELETE 或 UPDATE é™³è¿°å¼æ‰€è®Šæ›´ã€æ’入或刪除的資料庫列數。 - - None - ç„¡ + + (X1,X2,...) The char(X1,X2,...,XN) function returns a string composed of characters having the unicode code point values of integers X1 through XN, respectively. + (X1,X2,...) char(X1,X2,...,XN) 函å¼å›žå‚³ä¸€å€‹å­—串,該字串由具有整數 X1 到 XN çš„ unicode 碼點值的字元組æˆã€‚ - - - Full - 完整 + + (X,Y,...) The coalesce() function returns a copy of its first non-NULL argument, or NULL if all arguments are NULL + (X,Y,...) coalesce() 函å¼å›žå‚³å…¶ç¬¬ä¸€å€‹éž NULL åƒæ•¸çš„å‰¯æœ¬ï¼Œå¦‚æžœæ‰€æœ‰åƒæ•¸éƒ½æ˜¯ NULL 則回傳 NULL - - Incremental - 增加 + + (X,Y) The glob(X,Y) function is equivalent to the expression "Y GLOB X". + (X,Y) glob(X,Y) 函å¼ç­‰åŒæ–¼è¡¨é”å¼ã€ŒY GLOB Xã€ã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">Automatic Index</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_automatic_index"><span style=" text-decoration: underline; color:#0000ff;">自動化索引</span></a></p></body></html> + + (X,Y) The ifnull() function returns a copy of its first non-NULL argument, or NULL if both arguments are NULL. + (X,Y) ifnull() 函å¼å›žå‚³å…¶ç¬¬ä¸€å€‹éž NULL åƒæ•¸çš„å‰¯æœ¬ï¼Œå¦‚æžœå…©å€‹åƒæ•¸éƒ½æ˜¯ NULL 則回傳 NULL。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Checkpoint Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_checkpoint_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">檢查點完全 FSYNC</span></a></p></body></html> + + (X,Y) The instr(X,Y) function finds the first occurrence of string Y within string X and returns the number of prior characters plus 1, or 0 if Y is nowhere found within X. + (X,Y) instr(X,Y) 函å¼åœ¨å­—串 X 中找到字串 Y 的第一個出ç¾è™•,並回傳å‰é¢å­—元的數é‡åŠ  1,如果在 X 中找ä¸åˆ° Y 則回傳 0。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">Foreign Keys</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_foreign_keys"><span style=" text-decoration: underline; color:#0000ff;">外éµ</span></a></p></body></html> + + (X) The hex() function interprets its argument as a BLOB and returns a string which is the upper-case hexadecimal rendering of the content of that blob. + (X) hex() 函å¼å°‡å…¶åƒæ•¸è§£é‡‹ç‚º BLOB,並回傳該 BLOB 內容的大寫å六進ä½å‘ˆç¾çš„字串。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">Full FSYNC</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_fullfsync"><span style=" text-decoration: underline; color:#0000ff;">完全 FSYNC</span></a></p></body></html> + + (X,Y,Z) The iif(X,Y,Z) function returns the value Y if X is true, and Z otherwise. + (X,Y,Z) iif(X,Y,Z) 函å¼å¦‚æžœ X 為真,則回傳值 Y,å¦å‰‡å›žå‚³ Z。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">Ignore Check Constraints</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_ignore_check_constraints"><span style=" text-decoration: underline; color:#0000ff;">忽略檢查約æŸ</span></a></p></body></html> + + () The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. + () last_insert_rowid() 函å¼å›žå‚³å¾žå‘¼å«è©²å‡½å¼çš„資料庫連線æ’入的最後一列的 ROWID。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">Journal Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_mode"><span style=" text-decoration: underline; color:#0000ff;">日誌模å¼</span></a></p></body></html> + + (X) For a string value X, the length(X) function returns the number of characters (not bytes) in X prior to the first NUL character. + (X) å°æ–¼å­—串值 X,length(X) 函å¼å›žå‚³ X 中第一個 NUL 字元之å‰çš„字元數é‡ï¼ˆä¸æ˜¯ä½å…ƒçµ„)。 - - Delete - 刪除 + + (X,Y) The like() function is used to implement the "Y LIKE X" expression. + (X,Y) like() 函å¼ç”¨æ–¼å¯¦ç¾ã€ŒY LIKE Xã€è¡¨é”å¼ã€‚ - - Truncate - è£æˆª + + (X,Y,Z) The like() function is used to implement the "Y LIKE X ESCAPE Z" expression. + (X,Y,Z) like() 函å¼ç”¨æ–¼å¯¦ç¾ã€ŒY LIKE X ESCAPE Zã€è¡¨é”å¼ã€‚ - - Persist - 永久 + + (X) The load_extension(X) function loads SQLite extensions out of the shared library file named X. +Use of this function must be authorized from Preferences. + (X) load_extension(X) 函å¼å¾žå為 X 的共享函å¼åº«æª”案中載入 SQLite 擴充功能。 +必須從å好設定中授權使用此函å¼ã€‚ - - - Memory - 記憶體 + + (X,Y) The load_extension(X) function loads SQLite extensions out of the shared library file named X using the entry point Y. +Use of this function must be authorized from Preferences. + (X,Y) load_extension(X) 函å¼ä½¿ç”¨å…¥å£é»ž Y 從å為 X 的共享函å¼åº«æª”案中載入 SQLite 擴充功能。 +必須從å好設定中授權使用此函å¼ã€‚ - - WAL - WAL + + (X) The lower(X) function returns a copy of string X with all ASCII characters converted to lower case. + (X) lower(X) 函å¼å›žå‚³ä¸€å€‹å­—串 X 的副本,其中所有 ASCII 字元都轉æ›ç‚ºå°å¯«ã€‚ - - - Off - é—œ + + (X) ltrim(X) removes spaces from the left side of X. + (X) ltrim(X) 從 X 的左å´ç§»é™¤ç©ºæ ¼ã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">Journal Size Limit</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_journal_size_limit"><span style=" text-decoration: underline; color:#0000ff;">日誌大å°é™åˆ¶</span></a></p></body></html> + + (X,Y) The ltrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the left side of X. + (X,Y) ltrim(X,Y) 函å¼å›žå‚³ä¸€å€‹å­—串,該字串由從 X 的左å´ç§»é™¤åœ¨ Y 中出ç¾çš„任何和所有字元形æˆã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">Locking Mode</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_locking_mode"><span style=" text-decoration: underline; color:#0000ff;">鎖定模å¼</span></a></p></body></html> + + (X,Y,...) The multi-argument max() function returns the argument with the maximum value, or return NULL if any argument is NULL. + (X,Y,...) å¤šåƒæ•¸ max() 函å¼å›žå‚³å…·æœ‰æœ€å¤§å€¼çš„åƒæ•¸ï¼Œå¦‚æžœä»»ä½•åƒæ•¸ç‚º NULL 則回傳 NULL。 - - - Normal - 正常 + + (X,Y,...) The multi-argument min() function returns the argument with the minimum value. + (X,Y,...) å¤šåƒæ•¸ min() 函å¼å›žå‚³å…·æœ‰æœ€å°å€¼çš„åƒæ•¸ã€‚ - - Exclusive - ç¨ä½” + + (X,Y) The nullif(X,Y) function returns its first argument if the arguments are different and NULL if the arguments are the same. + (X,Y) nullif(X,Y) 函å¼å¦‚æžœåƒæ•¸ä¸åŒå‰‡å›žå‚³å…¶ç¬¬ä¸€å€‹åƒæ•¸ï¼Œå¦‚æžœåƒæ•¸ç›¸åŒå‰‡å›žå‚³ NULL。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">Max Page Count</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_max_page_count"><span style=" text-decoration: underline; color:#0000ff;">æœ€å¤§é æ•¸</span></a></p></body></html> + + (FORMAT,...) The printf(FORMAT,...) SQL function works like the sqlite3_mprintf() C-language function and the printf() function from the standard C library. + (FORMAT,...) printf(FORMAT,...) SQL 函å¼çš„工作方å¼é¡žä¼¼æ–¼ C èªžè¨€å‡½å¼ sqlite3_mprintf() 和標準 C 函å¼åº«çš„ printf() 函å¼ã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">Page Size</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_page_size"><span style=" text-decoration: underline; color:#0000ff;">é é¢å¤§å°</span></a></p></body></html> + + (X) The quote(X) function returns the text of an SQL literal which is the value of its argument suitable for inclusion into an SQL statement. + (X) quote(X) 函å¼å›žå‚³ä¸€å€‹ SQL å­—é¢å€¼çš„æ–‡å­—,該值é©åˆåŒ…å«åˆ° SQL 陳述å¼ä¸­ã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">Recursive Triggers</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_recursive_triggers"><span style=" text-decoration: underline; color:#0000ff;">éžè¿´è§¸ç™¼å™¨</span></a></p></body></html> + + () The random() function returns a pseudo-random integer between -9223372036854775808 and +9223372036854775807. + () random() 函å¼å›žå‚³ä¸€å€‹ä»‹æ–¼ -9223372036854775808 å’Œ +9223372036854775807 之間的å½éš¨æ©Ÿæ•´æ•¸ã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">Secure Delete</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_secure_delete"><span style=" text-decoration: underline; color:#0000ff;">安全刪除</span></a></p></body></html> + + (N) The randomblob(N) function return an N-byte blob containing pseudo-random bytes. + (N) randomblob(N) 函å¼å›žå‚³ä¸€å€‹åŒ…å«å½éš¨æ©Ÿä½å…ƒçµ„çš„ N ä½å…ƒçµ„ blob。 - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">åŒæ­¥</span></a></p></body></html> + + (X,Y,Z) The replace(X,Y,Z) function returns a string formed by substituting string Z for every occurrence of string Y in string X. + (X,Y,Z) replace(X,Y,Z) 函å¼å›žå‚³ä¸€å€‹å­—串,該字串由在字串 X 中的æ¯å€‹å­—串 Y 出ç¾è™•å–代為字串 Z å½¢æˆã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">Temp Store</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_temp_store"><span style=" text-decoration: underline; color:#0000ff;">臨時存儲</span></a></p></body></html> + + (X) The round(X) function returns a floating-point value X rounded to zero digits to the right of the decimal point. + (X) round(X) 函å¼å›žå‚³ä¸€å€‹æµ®é»žå€¼ X,該值四æ¨äº”å…¥åˆ°å°æ•¸é»žå³é‚Šçš„零使•¸ã€‚ - - Default - é è¨­ + + (X,Y) The round(X,Y) function returns a floating-point value X rounded to Y digits to the right of the decimal point. + (X,Y) round(X,Y) 函å¼å›žå‚³ä¸€å€‹æµ®é»žå€¼ X,該值四æ¨äº”å…¥åˆ°å°æ•¸é»žå³é‚Šçš„ Y 使•¸ã€‚ - - File - 檔案 + + (X) rtrim(X) removes spaces from the right side of X. + (X) rtrim(X) 從 X çš„å³å´ç§»é™¤ç©ºæ ¼ã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">User Version</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_schema_version"><span style=" text-decoration: underline; color:#0000ff;">用戶版本</span></a></p></body></html> + + (X,Y) The rtrim(X,Y) function returns a string formed by removing any and all characters that appear in Y from the right side of X. + (X,Y) rtrim(X,Y) 函å¼å›žå‚³ä¸€å€‹å­—串,該字串由從 X çš„å³å´ç§»é™¤åœ¨ Y 中出ç¾çš„任何和所有字元形æˆã€‚ - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL Auto Checkpoint</span></a></p></body></html> - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint"><span style=" text-decoration: underline; color:#0000ff;">WAL 自動檢查點</span></a></p></body></html> + + (X) The soundex(X) function returns a string that is the soundex encoding of the string X. + (X) soundex(X) 函å¼å›žå‚³ä¸€å€‹å­—串,該字串是字串 X çš„ soundex 編碼。 - - E&xecute SQL - 執行 SQL(&X) + + (X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. + (X,Y) substr(X,Y) 回傳從字串 X çš„ Y-th é–‹å§‹åˆ°çµæŸçš„æ‰€æœ‰å­—元。 - - &File - 檔案(&F) + + (X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. + (X,Y,Z) substr(X,Y,Z) 函å¼å›žå‚³è¼¸å…¥å­—串 X 的一個å­å­—串,該å­å­—串從 Y-th 字元開始,並且長度為 Z 字元。 - - &Import - 匯入(&I) + + () The total_changes() function returns the number of row changes caused by INSERT, UPDATE or DELETE statements since the current database connection was opened. + () total_changes() 函å¼å›žå‚³è‡ªå¾žç›®å‰çš„資料庫連線被開啟以來,由 INSERTã€UPDATE 或 DELETE é™³è¿°å¼æ‰€é€ æˆçš„資料列變更數é‡ã€‚ - - &Export - 匯出(&E) + + (X) trim(X) removes spaces from both ends of X. + (X) trim(X) 從 X 的兩端移除空格。 - - &Edit - 編輯(&E) + + (X,Y) The trim(X,Y) function returns a string formed by removing any and all characters that appear in Y from both ends of X. + (X,Y) trim(X,Y) 函å¼å›žå‚³ä¸€å€‹å­—串,該字串由從 X 的兩端移除在 Y 中出ç¾çš„任何和所有字元形æˆã€‚ - - &View - 查看(&V) + + (X) The typeof(X) function returns a string that indicates the datatype of the expression X. + (X) typeof(X) 函å¼å›žå‚³ä¸€å€‹å­—串,該字串指示表é”å¼ X 的資料類型。 - - &Help - 幫助(&H) + + (X) The unicode(X) function returns the numeric unicode code point corresponding to the first character of the string X. + (X) unicode(X) 函å¼å›žå‚³èˆ‡å­—串 X çš„ç¬¬ä¸€å€‹å­—å…ƒç›¸å°æ‡‰çš„æ•¸å€¼ unicode 碼點。 - - toolBar - toolBar + + (X) The upper(X) function returns a copy of input string X in which all lower-case ASCII characters are converted to their upper-case equivalent. + (X) upper(X) 函å¼å›žå‚³ä¸€å€‹è¼¸å…¥å­—串 X 的副本,其中所有å°å¯« ASCII 字元都轉æ›ç‚ºå…¶å¤§å¯«ç­‰æ•ˆå­—元。 - - SQL Log - SQL 日誌 + + (N) The zeroblob(N) function returns a BLOB consisting of N bytes of 0x00. + (N) zeroblob(N) 函å¼å›žå‚³ä¸€å€‹ç”± N ä½å…ƒçµ„çš„ 0x00 組æˆçš„ BLOB。 - - &Show SQL submitted by - 顯示 SQL æäº¤è‡ª(&S) + + + + + (timestring,modifier,modifier,...) + (時間字串,修飾符,修飾符,...) - - User - 用戶 + + (format,timestring,modifier,modifier,...) + (æ ¼å¼,時間字串,修飾符,修飾符,...) - - Application - æ‡‰ç”¨ç¨‹å¼ + + (X) The avg() function returns the average value of all non-NULL X within a group. + (X) avg() 函å¼å›žå‚³ç¾¤çµ„å…§æ‰€æœ‰éž NULL X 的平å‡å€¼ã€‚ - - &Clear - 清除(&C) + + (X) The count(X) function returns a count of the number of times that X is not NULL in a group. + (X) count(X) 函å¼å›žå‚³ç¾¤çµ„å…§ X ä¸ç‚º NULL 的次數。 - - Plot - 圖表 + + (X) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. + (X) group_concat() 函å¼å›žå‚³ä¸€å€‹å­—ä¸²ï¼Œè©²å­—ä¸²æ˜¯æ‰€æœ‰éž NULL X 值的連接。 - - Columns - 列列 + + (X,Y) The group_concat() function returns a string which is the concatenation of all non-NULL values of X. If parameter Y is present then it is used as the separator between instances of X. + (X,Y) group_concat() 函å¼å›žå‚³ä¸€å€‹å­—ä¸²ï¼Œè©²å­—ä¸²æ˜¯æ‰€æœ‰éž NULL X å€¼çš„é€£æŽ¥ã€‚å¦‚æžœå­˜åœ¨åƒæ•¸ Y,則將其用作 X 實例之間的分隔符。 - - X - X + + (X) The max() aggregate function returns the maximum value of all values in the group. + (X) max() èšåˆå‡½å¼å›žå‚³ç¾¤çµ„中所有值的最大值。 - - Y - Y + + (X) The min() aggregate function returns the minimum non-NULL value of all values in the group. + (X) min() èšåˆå‡½å¼å›žå‚³ç¾¤çµ„中所有值的最å°éž NULL 值。 - - _ - _ + + + (X) The sum() and total() aggregate functions return sum of all non-NULL values in the group. + (X) sum() å’Œ total() èšåˆå‡½å¼å›žå‚³ç¾¤çµ„ä¸­æ‰€æœ‰éž NULL 值的總和。 - - Save current plot... - 儲存目å‰åœ–表... + + () The number of the row within the current partition. Rows are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition, or in arbitrary order otherwise. + () ç›®å‰åˆ†å€å…§çš„列數。列的編號從 1 開始,按照視窗定義中的 ORDER BY å­å¥æ‰€å®šç¾©çš„é †åºï¼Œæˆ–者以其他任æ„é †åºã€‚ - - &New Database... - 新建資料庫(&N)... + + () The row_number() of the first peer in each group - the rank of the current row with gaps. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () æ¯å€‹ç¾¤çµ„中第一個å°ç­‰çš„ row_number() - ç›®å‰åˆ—çš„æŽ’åæœ‰é–“隔。如果沒有 ORDER BY å­å¥ï¼Œå‰‡æ‰€æœ‰åˆ—都被視為å°ç­‰ï¼Œæ­¤å‡½å¼å§‹çµ‚回傳 1。 - - - Create a new database file - 建立一個新的資料庫檔 + + () The number of the current row's peer group within its partition - the rank of the current row without gaps. Partitions are numbered starting from 1 in the order defined by the ORDER BY clause in the window definition. If there is no ORDER BY clause, then all rows are considered peers and this function always returns 1. + () ç›®å‰åˆ—çš„å°ç­‰ç¾¤çµ„在其分å€å…§çš„æ•¸é‡ - ç›®å‰åˆ—çš„æŽ’åæ²’有間隔。分å€çš„編號從 1 開始,按照視窗定義中的 ORDER BY å­å¥æ‰€å®šç¾©çš„é †åºã€‚如果沒有 ORDER BY å­å¥ï¼Œå‰‡æ‰€æœ‰åˆ—都被視為å°ç­‰ï¼Œæ­¤å‡½å¼å§‹çµ‚回傳 1。 - - This option is used to create a new database file. - 這個é¸é …用於建立一個新的資料庫檔案。 + + () Despite the name, this function always returns a value between 0.0 and 1.0 equal to (rank - 1)/(partition-rows - 1), where rank is the value returned by built-in window function rank() and partition-rows is the total number of rows in the partition. If the partition contains only one row, this function returns 0.0. + () 儘管å稱如此,此函å¼ç¸½æ˜¯å›žå‚³ä¸€å€‹ä»‹æ–¼ 0.0 å’Œ 1.0 之間的值,該值等於 (rank - 1)/(partition-rows - 1),其中 rank æ˜¯å…§å»ºè¦–çª—å‡½å¼ rank() 回傳的值,partition-rows 是分å€ä¸­çš„總列數。如果分å€åªåŒ…å«ä¸€åˆ—,此函å¼å›žå‚³ 0.0。 - - Ctrl+N - Ctrl+N + + () The cumulative distribution. Calculated as row-number/partition-rows, where row-number is the value returned by row_number() for the last peer in the group and partition-rows the number of rows in the partition. + () ç´¯ç©åˆ†ä½ˆã€‚計算為 row-number/partition-rows,其中 row-number 是 row_number() 為群組中的最後一個å°ç­‰å›žå‚³çš„值,partition-rows 是分å€ä¸­çš„列數。 - - &Open Database... - 打開資料庫(&O)... + + (N) Argument N is handled as an integer. This function divides the partition into N groups as evenly as possible and assigns an integer between 1 and N to each group, in the order defined by the ORDER BY clause, or in arbitrary order otherwise. If necessary, larger groups occur first. This function returns the integer value assigned to the group that the current row is a part of. + (N) åƒæ•¸ N 被處ç†ç‚ºæ•´æ•¸ã€‚此函å¼å°‡åˆ†å€åŠƒåˆ†ç‚º N 個群組,盡å¯èƒ½å‡å‹»ï¼Œä¸¦æŒ‰ç…§ ORDER BY å­å¥å®šç¾©çš„é †åºï¼Œæˆ–者以其他任æ„é †åºï¼Œå°‡ 1 到 N 之間的整數分é…給æ¯å€‹ç¾¤çµ„。如果需è¦ï¼Œè¼ƒå¤§çš„群組先出ç¾ã€‚此函å¼å›žå‚³åˆ†é…給目å‰åˆ—所屬的群組的整數值。 - - - Open an existing database file - æ‰“é–‹ä¸€å€‹ç¾æœ‰çš„資料庫檔 + + (expr) Returns the result of evaluating expression expr against the previous row in the partition. Or, if there is no previous row (because the current row is the first), NULL. + (expr) 回傳å°åˆ†å€ä¸­çš„å‰ä¸€åˆ—評估表é”å¼ expr çš„çµæžœã€‚或者,如果沒有å‰ä¸€åˆ—(因為目å‰åˆ—是第一列),則為 NULL。 - - This option is used to open an existing database file. - 這個é¸é …ç”¨æ–¼æ‰“é–‹ä¸€å€‹ç¾æœ‰çš„資料庫檔案。 + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows before the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows before the current row, NULL is returned. + (expr,offset) 如果æä¾›äº† offset åƒæ•¸ï¼Œå‰‡å®ƒå¿…須是éžè² æ•´æ•¸ã€‚在這種情æ³ä¸‹ï¼Œå›žå‚³çš„值是å°åˆ†å€ä¸­çš„ç›®å‰åˆ—之å‰çš„ offset 列評估 expr çš„çµæžœã€‚如果 offset 為 0,則å°ç›®å‰åˆ—è©•ä¼° expr。如果目å‰åˆ—之剿²’有 offset 列,則回傳 NULL。 - - Ctrl+O - Ctrl+O + + + (expr,offset,default) If default is also provided, then it is returned instead of NULL if the row identified by offset does not exist. + (expr,offset,default) 如果也æä¾›äº† default,則如果由 offset 標識的資料列ä¸å­˜åœ¨ï¼Œå‰‡å›žå‚³ default è€Œä¸æ˜¯ NULL。 - - &Close Database - 關閉資料庫(&C) + + (expr) Returns the result of evaluating expression expr against the next row in the partition. Or, if there is no next row (because the current row is the last), NULL. + (expr) 回傳å°åˆ†å€ä¸­çš„下一列評估表é”å¼ expr çš„çµæžœã€‚或者,如果沒有下一列(因為目å‰åˆ—是最後一列),則為 NULL。 - - Ctrl+W - Ctrl+W + + (expr,offset) If the offset argument is provided, then it must be a non-negative integer. In this case the value returned is the result of evaluating expr against the row offset rows after the current row within the partition. If offset is 0, then expr is evaluated against the current row. If there is no row offset rows after the current row, NULL is returned. + (expr,offset) 如果æä¾›äº† offset åƒæ•¸ï¼Œå‰‡å®ƒå¿…須是éžè² æ•´æ•¸ã€‚在這種情æ³ä¸‹ï¼Œå›žå‚³çš„值是å°åˆ†å€ä¸­çš„ç›®å‰åˆ—之後的 offset 列評估 expr çš„çµæžœã€‚如果 offset 為 0,則å°ç›®å‰åˆ—è©•ä¼° expr。如果目å‰åˆ—之後沒有 offset 列,則回傳 NULL。 - - Revert Changes - 復原修改 + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the first row in the window frame for each row. + (expr) 這個內建視窗函å¼ä»¥èˆ‡èšåˆè¦–窗函å¼ç›¸åŒçš„æ–¹å¼è¨ˆç®—æ¯ä¸€åˆ—çš„è¦–çª—æ¡†æž¶ã€‚å®ƒå›žå‚³å°æ¯ä¸€åˆ—的視窗框架中的第一列評估 expr 的值。 - - Revert database to last saved state - 把資料庫退回到先å‰å„²å­˜çš„狀態 + + (expr) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the last row in the window frame for each row. + (expr) 這個內建視窗函å¼ä»¥èˆ‡èšåˆè¦–窗函å¼ç›¸åŒçš„æ–¹å¼è¨ˆç®—æ¯ä¸€åˆ—çš„è¦–çª—æ¡†æž¶ã€‚å®ƒå›žå‚³å°æ¯ä¸€åˆ—的視窗框架中的最後一列評估 expr 的值。 - - This option is used to revert the current database file to its last saved state. All changes made since the last save operation are lost. - 這個é¸é …用於倒退目å‰çš„資料庫檔為它最後的儲存狀態。從最後儲存æ“作開始åšå‡ºçš„æ‰€æœ‰ä¿®æ”¹å°‡æœƒéºå¤±ã€‚ + + (expr,N) This built-in window function calculates the window frame for each row in the same way as an aggregate window function. It returns the value of expr evaluated against the row N of the window frame. Rows are numbered within the window frame starting from 1 in the order defined by the ORDER BY clause if one is present, or in arbitrary order otherwise. If there is no Nth row in the partition, then NULL is returned. + (expr,N) 這個內建視窗函å¼ä»¥èˆ‡èšåˆè¦–窗函å¼ç›¸åŒçš„æ–¹å¼è¨ˆç®—æ¯ä¸€åˆ—的視窗框架。它回傳å°è¦–窗框架的第 N 列評估 expr 的值。如果存在 ORDER BY å­å¥ï¼Œå‰‡è¦–窗框架內的資料列從 1 開始編號,按照由 ORDER BY å­å¥å®šç¾©çš„é †åºï¼Œæˆ–者以其他任æ„é †åºã€‚如果分å€ä¸­æ²’有第 N 列,則回傳 NULL。 - - Write Changes - 寫入修改 + + (X) Return the arccosine of X. The result is in radians. + (X) 回傳 X çš„åé¤˜å¼¦å€¼ã€‚çµæžœä»¥å¼§åº¦ç‚ºå–®ä½ã€‚ - - Write changes to the database file - 把修改寫入到資料庫檔 + + (X) Return the hyperbolic arccosine of X. + (X) 回傳 X 的雙曲å餘弦值。 - - This option is used to save changes to the database file. - 這個é¸é …用於儲存修改到資料庫檔案。 + + (X) Return the arcsine of X. The result is in radians. + (X) 回傳 X çš„åæ­£å¼¦å€¼ã€‚çµæžœä»¥å¼§åº¦ç‚ºå–®ä½ã€‚ - - Ctrl+S - Ctrl+S + + (X) Return the hyperbolic arcsine of X. + (X) 回傳 X çš„é›™æ›²åæ­£å¼¦å€¼ã€‚ - - Compact Database - 壓縮資料庫 + + (X) Return the arctangent of X. The result is in radians. + (X) 回傳 X çš„åæ­£åˆ‡å€¼ã€‚çµæžœä»¥å¼§åº¦ç‚ºå–®ä½ã€‚ - - Compact the database file, removing space wasted by deleted records - 壓縮資料庫檔,通éŽåˆªé™¤è¨˜éŒ„去掉浪費的空間 + + (X,Y) Return the arctangent of Y/X. The result is in radians. The result is placed into correct quadrant depending on the signs of X and Y. + (X,Y) 回傳 Y/X çš„åæ­£åˆ‡å€¼ã€‚çµæžœä»¥å¼§åº¦ç‚ºå–®ä½ã€‚çµæžœæœƒæ ¹æ“š X å’Œ Y 的符號放在正確的象é™ã€‚ - - - Compact the database file, removing space wasted by deleted records. - 壓縮資料庫檔,通éŽåˆªé™¤è¨˜éŒ„去掉浪費的空間。 + + (X) Return the hyperbolic arctangent of X. + (X) 回傳 X çš„é›™æ›²åæ­£åˆ‡å€¼ã€‚ - - E&xit - 退出(&X) + + + (X) Return the first representable integer value greater than or equal to X. For positive values of X, this routine rounds away from zero. For negative values of X, this routine rounds toward zero. + (X) 回傳大於或等於 X 的第一個å¯è¡¨ç¤ºçš„æ•´æ•¸å€¼ã€‚å°æ–¼ X çš„æ­£å€¼ï¼Œæ­¤å‡½å¼æœƒé é›¢é›¶é€²ä½ã€‚å°æ–¼ X çš„è² å€¼ï¼Œæ­¤å‡½å¼æœƒæœå‘零進ä½ã€‚ - - Ctrl+Q - Ctrl+Q + + (X) Return the cosine of X. X is in radians. + (X) 回傳 X 的餘弦值。X 以弧度為單ä½ã€‚ - - Database from SQL file... - 來自 SQL 檔案的資料庫... + + (X) Return the hyperbolic cosine of X. + (X) 回傳 X 的雙曲餘弦值。 - - Import data from an .sql dump text file into a new or existing database. - 從一個 .sql 轉儲文字檔中匯入資料到一個新的或已有的資料庫。 + + (X) Convert value X from radians into degrees. + (X) å°‡ X 從弧度轉æ›ç‚ºåº¦ã€‚ - - This option lets you import data from an .sql dump text file into a new or existing database. SQL dump files can be created on most database engines, including MySQL and PostgreSQL. - 這個é¸é …讓你從一個 .sql è½‰å„²æ–‡å­—æª”ä¸­åŒ¯å…¥è³‡æ–™åˆ°ä¸€å€‹æ–°çš„æˆ–ç¾æœ‰çš„資料庫。SQL 轉儲檔å¯ä»¥åœ¨å¤§å¤šæ•¸è³‡æ–™åº«å¼•擎上建立,包括 MySQL å’Œ PostgreSQL。 + + (X) Compute e (Euler's number, approximately 2.71828182845905) raised to the power X. + (X) 計算 eï¼ˆæ­æ‹‰æ•¸ï¼Œç´„為 2.71828182845905)的 X 次方。 - - Table from CSV file... - 資料表來自 CSV 檔案... + + (X) Return the first representable integer value less than or equal to X. For positive numbers, this function rounds toward zero. For negative numbers, this function rounds away from zero. + (X) å›žå‚³å°æ–¼æˆ–等於 X 的第一個å¯è¡¨ç¤ºçš„æ•´æ•¸å€¼ã€‚å°æ–¼æ­£æ•¸ï¼Œæ­¤å‡½å¼æœƒæœå‘零進ä½ã€‚å°æ–¼è² æ•¸ï¼Œæ­¤å‡½å¼æœƒé é›¢é›¶é€²ä½ã€‚ - - Open a wizard that lets you import data from a comma separated text file into a database table. - 打開一個引導精éˆè®“您從一個逗號間隔的文字檔匯入資料到一個資料庫資料表中。 + + (X) Return the natural logarithm of X. + (X) 回傳 X çš„è‡ªç„¶å°æ•¸ã€‚ - - Open a wizard that lets you import data from a comma separated text file into a database table. CSV files can be created on most database and spreadsheet applications. - 打開一個引導精éˆè®“您從一個逗號間隔的文字檔匯入資料到一個資料庫資料表中。CSV 檔å¯ä»¥åœ¨å¤§å¤šæ•¸è³‡æ–™åº«å’Œè©¦ç®—資料表應用程å¼ä¸Šå»ºç«‹ã€‚ + + (B,X) Return the base-B logarithm of X. + (B,X) 回傳以 B 為底的 X çš„å°æ•¸ã€‚ - - Database to SQL file... - 資料庫到 SQL 檔案... + + + (X) Return the base-10 logarithm for X. + (X) 回傳以 10 為底的 X çš„å°æ•¸ã€‚ - - Export a database to a .sql dump text file. - 匯出一個資料庫導一個 .sql 轉儲文字檔案。 + + (X) Return the logarithm base-2 for the number X. + (X) 回傳以 2 為底的 X çš„å°æ•¸ã€‚ - - This option lets you export a database to a .sql dump text file. SQL dump files contain all data necessary to recreate the database on most database engines, including MySQL and PostgreSQL. - 這個é¸é …讓你匯出一個資料庫導一個 .sql 轉儲文字檔案。SQL 轉儲檔包å«åœ¨å¤§å¤šæ•¸è³‡æ–™åº«å¼•擎上(包括 MySQL å’Œ PostgreSQL)釿–°å»ºç«‹è³‡æ–™åº«æ‰€éœ€çš„æ‰€æœ‰è³‡æ–™ã€‚ + + (X,Y) Return the remainder after dividing X by Y. + (X,Y) 回傳 X 除以 Y 的餘數。 - - Table as CSV file... - 資料表為 CSV 檔案... + + () Return an approximation for Ï€. + () 回傳 Ï€ 的近似值。 - - Export a database table as a comma separated text file. - 匯出一個資料庫資料表為逗號間隔的文字檔案。 + + + (X,Y) Compute X raised to the power Y. + (X,Y) 計算 X çš„ Y 次方。 - - Export a database table as a comma separated text file, ready to be imported into other database or spreadsheet applications. - 匯出一個資料庫資料表為逗號間隔的文字檔,準備好被匯入到其他資料庫或試算資料表應用程å¼ã€‚ + + (X) Convert X from degrees into radians. + (X) å°‡ X 從度數轉æ›ç‚ºå¼§åº¦ã€‚ + + + + (X) Return the sine of X. X is in radians. + (X) 回傳 X 的正弦值。X 是以弧度為單ä½ã€‚ + + + + (X) Return the hyperbolic sine of X. + (X) 回傳 X 的雙曲正弦值。 + + + + (X) Return the square root of X. NULL is returned if X is negative. + (X) 回傳 X 的平方根。如果 X 是負數,則回傳 NULL。 - - Create Table... - 建立資料表... + + (X) Return the tangent of X. X is in radians. + (X) 回傳 X 的正切值。X 是以弧度為單ä½ã€‚ + + + + (X) Return the hyperbolic tangent of X. + (X) 回傳 X 的雙曲正切值。 + + + + (X) Return the representable integer in between X and 0 (inclusive) that is furthest away from zero. Or, in other words, return the integer part of X, rounding toward zero. + (X) 回傳介於 X å’Œ 0(包å«ï¼‰ä¹‹é–“ã€è·é›¢é›¶æœ€é çš„å¯è¡¨ç¤ºæ•´æ•¸ã€‚æ›å¥è©±èªªï¼Œå›žå‚³ X 的整數部分,四æ¨äº”å…¥æœå‘零。 + + + + SqliteTableModel + + + reading rows + æ­£åœ¨è®€å–æ¬„ä½ - - Open the Create Table wizard, where it is possible to define the name and fields for a new table in the database - 打開“建立資料表â€å¼•å°Žç²¾éˆï¼Œåœ¨é‚£è£¡å¯ä»¥å®šç¾©åœ¨è³‡æ–™åº«ä¸­çš„一個新資料表的åç¨±å’Œæ¬„ä½ + + loading... + 正在載入... - - Delete Table... - 刪除資料表... + + References %1(%2) +Hold %3Shift and click to jump there + åƒè€ƒ %1(%2) +æŒ‰ä½ %3Shift 並點é¸ä»¥è·³è‡³è©²è™• - - Open the Delete Table wizard, where you can select a database table to be dropped. - 打開“刪除資料表â€å¼•å°Žç²¾éˆï¼Œåœ¨é‚£è£¡ä½ å¯ä»¥é¸æ“‡è¦ä¸Ÿæ£„的一個資料庫資料表。 + + Error changing data: +%1 + 變更資料時出ç¾éŒ¯èª¤ï¼š +%1 - - Modify Table... - 修改資料表... + + retrieving list of columns + æ­£åœ¨æ“·å–æ¬„使¸…å–® - - Open the Modify Table wizard, where it is possible to rename an existing table. It is also possible to add or delete fields form a table, as well as modify field names and types. - 打開“修改資料表â€å¼•å°Žç²¾éˆï¼Œåœ¨å…¶ä¸­å¯ä»¥é‡å‘½åä¸€å€‹ç¾æœ‰çš„資料表。也å¯ä»¥å¾žä¸€å€‹è³‡æ–™è¡¨ä¸­åŠ å…¥æˆ–åˆªé™¤æ¬„ä½ï¼Œä»¥åŠä¿®æ”¹æ¬„ä½å稱和類型。 + + Fetching data... + 正在擷å–資料... - - Create Index... - 建立索引... + + + Cancel + å–æ¶ˆ + + + TableBrowser - - Open the Create Index wizard, where it is possible to define a new index on an existing database table. - 打開“建立索引â€å¼•å°Žç²¾éˆï¼Œåœ¨é‚£è£¡å¯ä»¥åœ¨ä¸€å€‹ç¾æœ‰çš„資料庫資料表上定義一個新索引。 + + Browse Data + ç€è¦½è³‡æ–™ - - &Preferences... - å好é¸é …(&P)... + + &Table: + &資料表: - - - Open the preferences window. - 打開首é¸é …視窗。 + + Select a table to browse data + 鏿“‡ä¸€å€‹è³‡æ–™è¡¨ä»¥ç€è¦½è³‡æ–™ - - &DB Toolbar - 資料庫工具列(&D) + + Use this list to select a table to be displayed in the database view + ä½¿ç”¨é€™å€‹æ¸…å–®é¸æ“‡ä¸€å€‹è¦é¡¯ç¤ºåœ¨è³‡æ–™åº«æª¢è¦–中的資料表 - - Shows or hides the Database toolbar. - 顯示或隱è—資料庫工具列。 + + This is the database table view. You can do the following actions: + - Start writing for editing inline the value. + - Double-click any record to edit its contents in the cell editor window. + - Alt+Del for deleting the cell content to NULL. + - Ctrl+" for duplicating the current record. + - Ctrl+' for copying the value from the cell above. + - Standard selection and copy/paste operations. + 這是資料庫表格檢視。您å¯ä»¥é€²è¡Œä»¥ä¸‹æ“作: + - 開始編輯值。 + - 點é¸å…©ä¸‹ä»»ä½•記錄以在儲存格編輯器視窗中編輯其內容。 + - Alt+Del 以將儲存格內容刪除為 NULL。 + - Ctrl+" 以複製目å‰è¨˜éŒ„。 + - Ctrl+' 以從上方儲存格複製值。 + - æ¨™æº–é¸æ“‡å’Œè¤‡è£½/貼上æ“作。 - - What's This? - 這是什麼? + + Text pattern to find considering the checks in this frame + è€ƒæ…®æ­¤æ¡†æž¶ä¸­çš„æª¢æŸ¥ä¾†å°‹æ‰¾çš„æ–‡å­—æ¨¡å¼ - - Shift+F1 - Shift+F1 + + Find in table + 在表格中尋找 - - &About... - 關於(&A)... + + Find previous match [Shift+F3] + 尋找å‰ä¸€å€‹ç¬¦åˆ [Shift+F3] - - &Recently opened - 最近打開(&R) + + Find previous match with wrapping + 尋找å‰ä¸€å€‹ç¬¦åˆä¸¦æ›è¡Œ - - Open &tab - 打開標籤é (&T) + + Shift+F3 + Shift+F3 - - Ctrl+T - Ctrl+T + + Find next match [Enter, F3] + å°‹æ‰¾ä¸‹ä¸€å€‹ç¬¦åˆ [Enter, F3] - - &Execute SQL - 執行 SQL(&E) + + Find next match with wrapping + 尋找下一個符åˆä¸¦æ›è¡Œ - - Execute SQL [F5, Ctrl+Return] - 執行 SQL [F5, Ctrl+ Enter] + + F3 + F3 - - &Wiki... - 維基百科(&W)... + + The found pattern must match in letter case + æœå°‹åˆ°çš„字串必須符åˆå¤§å°å¯« - - Bug &report... - 錯誤報告(&R)... + + Case Sensitive + å€åˆ†å¤§å°å¯« - - Web&site... - 網站(&S)... + + The found pattern must be a whole word + æœå°‹åˆ°çš„字串必須是一個完整的單詞 - - Save Project - 儲存專案 + + Whole Cell + 整個儲存格 - - - Save the current session to a file - å„²å­˜ç›®å‰æœƒè©±åˆ°ä¸€å€‹æª”案 + + Interpret search pattern as a regular expression + å°‡æœå°‹æ¨¡å¼è§£é‡‹ç‚ºæ­£è¦è¡¨é”å¼ - - Open Project - 打開專案 + + <html><head/><body><p>When checked, the pattern to find is interpreted as a UNIX regular expression. See <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Regular Expression in Wikibooks</a>.</p></body></html> + <html><head/><body><p>勾鏿™‚,將會將尋找的模å¼è§£é‡‹ç‚º UNIX æ­£è¦è¡¨é”å¼ã€‚è«‹åƒè¦‹ <a href="https://en.wikibooks.org/wiki/Regular_Expressions">Wikibooks 中的正è¦è¡¨é”å¼</a>。</p></body></html> - - - Load a working session from a file - 從一個檔載入工作會話 + + Regular Expression + æ­£è¦è¡¨é”å¼ - - Open SQL file - 打開 SQL 檔案 + + + Close Find Bar + 關閉尋找工具列 - - <html><head/><body><p>Save current plot...</p><p>File format chosen by extension (png, jpg, pdf, bmp)</p></body></html> - <html><head/><body><p>儲存目å‰åœ–表...</p><p>æª”æ¡ˆæ ¼å¼æŒ‰å‰¯æª”å鏿“‡(png, jpg, pdf, bmp)</p></body></html> + + Text to replace with + è¦å–代的文字 - - Save SQL file - 儲存 SQL 檔案 + + Replace with + å–代為 - - Load extension - 載入擴充套件 + + Replace next match + å–ä»£ä¸‹ä¸€å€‹ç¬¦åˆ - - Execute current line - 執行目å‰è¡Œ + + + Replace + å–代 - - Execute current line [Ctrl+E] - 執行目å‰è¡Œ [Ctrl+E] + + Replace all matches + å–ä»£æ‰€æœ‰ç¬¦åˆ - - Ctrl+E - Ctrl+E + + Replace all + 全部å–代 - - Export as CSV file - 匯出為 CSV 檔案 + + Export to &JSON + 匯出為 &JSON - - Export table as comma separated values file - 匯出資料表為逗號間隔值檔案 + + + Export the filtered data to JSON + 將篩é¸å¾Œçš„資料匯出為 JSON - - Ctrl+L - Ctrl+L + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a JSON file. + 此按鈕會將目å‰é¡¯ç¤ºçš„ç€è¦½è¡¨æ ¼è³‡æ–™ï¼ˆç¶“éŽç¯©é¸ã€é¡¯ç¤ºæ ¼å¼å’ŒæŽ’åºåˆ—)匯出為 JSON 檔案。 - - Ctrl+P - Ctrl+P + + Copy column name + 複製欄ä½å稱 - - Database encoding - 資料庫編碼 + + Copy the database table column name to your clipboard + 將資料庫表格的欄ä½å稱複製到剪貼簿 - - Choose a database file - 鏿“‡ä¸€å€‹è³‡æ–™åº«æª”案 + + New Data Browser + 新資料ç€è¦½å™¨ - - Ctrl+Return - Ctrl+Return + + + Add a new docked Data Browser + 新增一個固定的資料ç€è¦½å™¨ - - - - - Choose a filename to save under - 鏿“‡ä¸€å€‹æª”案å稱儲存 + + This button adds a new docked Data Browser, which you can detach and arrange in different layouts. + 這個按鈕å¯ä»¥æ–°å¢žä¸€å€‹å›ºå®šçš„資料ç€è¦½å™¨ï¼Œæ‚¨å¯ä»¥å°‡å…¶è§£é™¤å›ºå®šä¸¦åœ¨ä¸åŒçš„é…ç½®ä¸­é‡æ–°æŽ’列。 - - Error adding record: - - 加入記錄時出ç¾éŒ¯èª¤: - + + <html><head/><body><p>Scroll to the beginning</p></body></html> + <html><head/><body><p>æ²å‹•到開始</p></body></html> - - Error deleting record: -%1 - 刪除記錄時出ç¾éŒ¯èª¤: -%1 + + <html><head/><body><p>Clicking this button navigates to the beginning in the table view above.</p></body></html> + <html><head/><body><p>é»žé¸æ­¤æŒ‰éˆ•會在上方的資料表中移至開始。</p></body></html> - - Please select a record first - è«‹é¦–å…ˆé¸æ“‡ä¸€æ¢è¨˜éŒ„ + + |< + |< - - %1 - %2 of %3 - %1 - %2 / %3 + + Scroll one page upwards + å‘上æ²å‹•ä¸€é  - - - There is no database opened. Please open or create a new database file. - 沒有打開資料庫。請打開或建立一個新的資料庫檔案。 + + <html><head/><body><p>Clicking this button navigates one page of records upwards in the table view above.</p></body></html> + <html><head/><body><p>é»žé¸æ­¤æŒ‰éˆ•會在上方的資料表中å‘上移動一é è¨˜éŒ„。</p></body></html> - - Are you sure you want to delete the %1 '%2'? -All data associated with the %1 will be lost. - 您是å¦ç¢ºèªæ‚¨æƒ³åˆªé™¤ %1 '%2'? -所有和 %1 é—œè¯çš„資料將會éºå¤±ã€‚ + + < + < - - Error: could not delete the %1. Message from database engine: -%2 - 錯誤: 無法刪除 %1。消æ¯ä¾†è‡ªè³‡æ–™åº«å¼•擎: -%2 + + 0 - 0 of 0 + 0 - 0 / 0 - - There is no database opened. - 沒有資料庫打開。 + + Scroll one page downwards + å‘下æ²å‹•ä¸€é  - - %1 Rows returned from: %2 (took %3ms) - %1 行返回自: %2 (耗時 %3毫秒) + + <html><head/><body><p>Clicking this button navigates one page of records downwards in the table view above.</p></body></html> + <html><head/><body><p>é»žé¸æ­¤æŒ‰éˆ•會在上方的資料表中å‘下移動一é è¨˜éŒ„。</p></body></html> - - Error executing query: %1 - 執行查詢時出ç¾éŒ¯èª¤: %1 + + > + > - - Query executed successfully: %1 (took %2ms) - 查詢執行æˆåŠŸ: %1 (耗時 %2毫秒) + + Scroll to the end + æ²å‹•到末端 - - Choose a text file - 鏿“‡ä¸€å€‹æ–‡å­—檔 + + <html><head/><body><p>Clicking this button navigates up to the end in the table view above.</p></body></html> + <html><head/><body><p>é»žé¸æ­¤æŒ‰éˆ•會在上方的資料表中移至末端。</p></body></html> - - Text files(*.csv *.txt);;All files(*) - 文字檔案(*.csv *.txt);;所有擋檔案(*) + + >| + >| - - Import completed - åŒ¯å…¥å®Œæˆ + + <html><head/><body><p>Click here to jump to the specified record</p></body></html> + <html><head/><body><p>點é¸é€™è£¡ä»¥è·³è½‰è‡³æŒ‡å®šçš„記錄</p></body></html> - - Are you sure you want to undo all changes made to the database file '%1' since the last save? - 您是å¦ç¢ºèªæ‚¨æƒ³æ’¤éŠ·å¾žä¸Šæ¬¡å„²å­˜ä»¥ä¾†å°è³‡æ–™åº«æª”‘%1’åšå‡ºçš„æ‰€æœ‰ä¿®æ”¹ã€‚? + + <html><head/><body><p>This button is used to navigate to the record number specified in the Go to area.</p></body></html> + <html><head/><body><p>這個按鈕用於移至「跳轉到ã€å€åŸŸä¸­æŒ‡å®šçš„記錄編號。</p></body></html> - - Choose a filename to export - 鏿“‡è¦åŒ¯å‡ºçš„æª”案å稱 + + Go to: + 跳轉到: - - Text files(*.sql *.txt) - 文字檔案(*.sql *.txt) + + Enter record number to browse + 輸入è¦ç€è¦½çš„記錄編號 - - Export cancelled or failed. - åŒ¯å‡ºå–æ¶ˆæˆ–失敗。 + + Type a record number in this area and click the Go to: button to display the record in the database view + 在這個å€åŸŸä¸­è¼¸å…¥ä¸€å€‹è¨˜éŒ„編號,並點é¸ã€Œè·³è½‰åˆ°:ã€æŒ‰éˆ•以在資料庫檢視中顯示記錄 - - Export completed. - 匯出完æˆã€‚ + + 1 + 1 - - Choose a file to import - 鏿“‡è¦åŒ¯å…¥çš„一個檔案 + + Show rowid column + 顯示 rowid 列 - - - - Text files(*.sql *.txt);;All files(*) - 文字檔案(*.sql *.txt);;所有擋檔案(*) + + Toggle the visibility of the rowid column + åˆ‡æ› rowid 欄ä½çš„å¯è¦‹åº¦ - - Do you want to create a new database file to hold the imported data? -If you answer no we will attempt to import the data in the SQL file to the current database. - 您是å¦ç¢ºèªæ‚¨æƒ³å»ºç«‹ä¸€å€‹æ–°çš„資料庫檔用來存放匯入的資料? -如果您會到“å¦â€çš„話,我們將嘗試匯入 SQL 檔中的資料到目å‰è³‡æ–™åº«ã€‚ + + Unlock view editing + 解鎖檢視表編輯 - - File %1 already exists. Please choose a different name. - 檔案 %1 å·²å­˜åœ¨ã€‚è«‹é¸æ“‡ä¸€å€‹ä¸åŒçš„å稱。 + + This unlocks the current view for editing. However, you will need appropriate triggers for editing. + 這將解鎖目å‰çš„æª¢è¦–表以進行編輯。然而,您將需è¦é©ç•¶çš„觸發器來進行編輯。 - - Error importing data: %1 - 匯入資料時出ç¾éŒ¯èª¤: %1 + + Edit display format + ç·¨è¼¯é¡¯ç¤ºæ ¼å¼ - - Import completed. - 匯入完æˆã€‚ + + Edit the display format of the data in this column + 編輯此欄ä½ä¸­è³‡æ–™çš„é¡¯ç¤ºæ ¼å¼ - - Delete View - 刪除視圖 + + + New Record + 新記錄 - - Delete Trigger - 刪除觸發器 + + + Insert a new record in the current table + 在目å‰çš„資料表中æ’入新記錄 - - Delete Index - 刪除索引 + + <html><head/><body><p>This button creates a new record in the database. Hold the mouse button to open a pop-up menu of different options:</p><ul><li><span style=" font-weight:600;">New Record</span>: insert a new record with default values in the database.</li><li><span style=" font-weight:600;">Insert Values...</span>: open a dialog for entering values before they are inserted in the database. This allows to enter values accomplishing the different constraints. This dialog is also open if the <span style=" font-weight:600;">New Record</span> option fails due to these constraints.</li></ul></body></html> + <html><head/><body><p>æ­¤æŒ‰éˆ•åœ¨è³‡æ–™åº«ä¸­å»ºç«‹æ–°è¨˜éŒ„ã€‚æŒ‰ä½æ»‘鼠按鈕以開啟ä¸åŒé¸é …的彈出å¼é¸å–®ï¼š</p><ul><li><span style=" font-weight:600;">新記錄</span>:在資料庫中æ’入具有é è¨­å€¼çš„æ–°è¨˜éŒ„。</li><li><span style=" font-weight:600;">æ’入值...</span>:在將值æ’入資料庫之å‰ï¼Œé–‹å•Ÿä¸€å€‹å°è©±æ¡†ä»¥è¼¸å…¥å€¼ã€‚這å…許輸入滿足ä¸åŒç´„æŸçš„值。如果 <span style=" font-weight:600;">新記錄</span> é¸é …由於這些約æŸè€Œå¤±æ•—,則也會開啟此å°è©±æ¡†ã€‚</li></ul></body></html> - - - Delete Table - 刪除資料表 + + + Delete Record + 刪除記錄 - - &%1 %2 - &%1 %2 + + Delete the current record + 刪除目å‰çš„記錄 - - Setting PRAGMA values will commit your current transaction. -Are you sure? - 設定 PRAGMA 值將會æäº¤æ‚¨çš„ç›®å‰äº‹å‹™ã€‚. -您確èªå—Ž? + + + This button deletes the record or records currently selected in the table + 此按鈕刪除目å‰åœ¨è³‡æ–™è¡¨ä¸­é¸æ“‡çš„記錄或記錄 - - Select SQL file to open - 鏿“‡è¦æ‰“é–‹çš„ SQL 檔案 + + + Insert new record using default values in browsed table + 在ç€è¦½çš„資料表中使用é è¨­å€¼æ’入新記錄 - - Select file name - 鏿“‡æª”案å稱 + + Insert Values... + æ’入值... - - Select extension file - 鏿“‡æ“´å……套件檔 + + + Open a dialog for inserting values in a new record + 開啟一個å°è©±æ¡†ä»¥åœ¨æ–°è¨˜éŒ„中æ’入值 - - Extensions(*.so *.dll);;All files(*) - 擴充套件(*.so *.dll);;所有擋檔案(*) + + Export to &CSV + 匯出為 &CSV - - Extension successfully loaded. - 擴充套件æˆåŠŸè¼‰å…¥ã€‚ + + + Export the filtered data to CSV + 將篩é¸å¾Œçš„資料匯出為 CSV - - - Error loading extension: %1 - 載入擴充套件時出ç¾éŒ¯èª¤: %1 + + This button exports the data of the browsed table as currently displayed (after filters, display formats and order column) as a CSV file. + 此按鈕將ç€è¦½çš„資料表的資料匯出為 CSV 檔,其內容為目å‰é¡¯ç¤ºçš„內容(篩é¸ã€é¡¯ç¤ºæ ¼å¼å’ŒæŽ’åºæ¬„ä½ä¹‹å¾Œï¼‰ã€‚ - - Don't show again - ä¸å†é¡¯ç¤º + + Save as &view + å¦å­˜ç‚ºæª¢è¦–表(&V) - - New version available. - 新版本å¯ç”¨ã€‚ + + + Save the current filter, sort column and display formats as a view + 將目å‰çš„篩é¸ã€æŽ’åºæ¬„ä½å’Œé¡¯ç¤ºæ ¼å¼å¦å­˜ç‚ºæª¢è¦–表 - - A new sqlitebrowser version is available (%1.%2.%3).<br/><br/>Please download at <a href='%4'>%4</a>. - 有新版本的 sqlitebrowser (%1.%2.%3)å¯ç”¨ã€‚<br/><br/>請從 <a href='%4'>%4</a> 下載。 + + This button saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements. + 此按鈕將ç€è¦½çš„資料表的目å‰è¨­å®šï¼ˆç¯©é¸ã€é¡¯ç¤ºæ ¼å¼å’ŒæŽ’åºæ¬„ä½ï¼‰å¦å­˜ç‚º SQL 檢視表,您ç¨å¾Œå¯ä»¥ç€è¦½æˆ–在 SQL 陳述å¼ä¸­ä½¿ç”¨ã€‚ - - Choose a axis color - 鏿“‡ä¸€å€‹è»¸çš„é¡è‰² + + Save Table As... + 將資料表å¦å­˜ç‚º... - - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;All Files(*) - PNG(*.png);;JPG(*.jpg);;PDF(*.pdf);;BMP(*.bmp);;所有擋檔案(*) + + + Save the table as currently displayed + 將資料表å¦å­˜ç‚ºç›®å‰é¡¯ç¤ºçš„內容 - - Choose a file to open - 鏿“‡è¦æ‰“開的一個檔案 + + <html><head/><body><p>This pop-up menu provides the following options applying to the currently browsed and filtered table:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export to CSV: this option exports the data of the browsed table as currently displayed (after filters, display formats and order column) to a CSV file.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save as view: this option saves the current setting of the browsed table (filters, display formats and order column) as an SQL view that you can later browse or use in SQL statements.</li></ul></body></html> + <html><head/><body><p>此彈出å¼é¸å–®æä¾›ä»¥ä¸‹é©ç”¨æ–¼ç›®å‰ç€è¦½å’Œç¯©é¸çš„資料表的é¸é …:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">匯出至 CSV:此é¸é …å°‡ç€è¦½çš„資料表的資料匯出為 CSV 檔,其內容為目å‰é¡¯ç¤ºçš„內容(篩é¸ã€é¡¯ç¤ºæ ¼å¼å’ŒæŽ’åºæ¬„ä½ä¹‹å¾Œï¼‰ã€‚</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">å¦å­˜ç‚ºæª¢è¦–表:此é¸é …å°‡ç€è¦½çš„資料表的目å‰è¨­å®šï¼ˆç¯©é¸ã€é¡¯ç¤ºæ ¼å¼å’ŒæŽ’åºæ¬„ä½ï¼‰å¦å­˜ç‚º SQL 檢視表,您ç¨å¾Œå¯ä»¥ç€è¦½æˆ–在 SQL 陳述å¼ä¸­ä½¿ç”¨ã€‚</li></ul></body></html> - - - SQLiteBrowser project(*.sqbpro) - SQLiteBrowser 工程(*.sqbpro) + + Hide column(s) + éš±è—æ¬„ä½ - - Invalid file format. - 無效檔案格å¼ã€‚ + + Hide selected column(s) + éš±è—鏿“‡çš„æ¬„ä½ - - - PreferencesDialog - - Preferences - 首é¸é … + + Show all columns + é¡¯ç¤ºæ‰€æœ‰æ¬„ä½ - - &Database - 資料庫(&D) + + Show all columns that were hidden + 顯示所有被隱è—çš„æ¬„ä½ - - Database &encoding - 資料庫編碼(&E) + + + Set encoding + 設定編碼 - - Open databases with foreign keys enabled. - 打開啟用了外éµçš„資料庫。 + + Change the encoding of the text in the table cells + 變更資料表格中的文字編碼 - - &Foreign keys - 外éµ(&F) + + Set encoding for all tables + 設定所有資料表的編碼 - - enabled - 啟用 + + Change the default encoding assumed for all tables in the database + 變更資料庫中所有資料表é è¨­çš„編碼 - - Default &location - é è¨­ä½ç½®(&L) + + Clear Filters + æ¸…é™¤ç¯©é¸ - - ... - ... + + Clear all filters + æ¸…é™¤æ‰€æœ‰ç¯©é¸ - - &Prefetch block size - é å–塊尺寸(&P) + + + This button clears all the filters set in the header input fields for the currently browsed table. + 此按鈕清除目å‰ç€è¦½çš„資料表的標頭輸入欄ä½ä¸­è¨­å®šçš„æ‰€æœ‰ç¯©é¸ã€‚ - - &SQL - &SQL + + Clear Sorting + æ¸…é™¤æŽ’åº - - Settings name - 設定å稱 + + Reset the order of rows to the default + 將列的順åºé‡è¨­ç‚ºé è¨­ - - Context - 上下文 + + + This button clears the sorting columns specified for the currently browsed table and returns to the default order. + 此按鈕清除目å‰ç€è¦½çš„è³‡æ–™è¡¨ä¸­æŒ‡å®šçš„æŽ’åºæ¬„ä½ï¼Œä¸¦å›žåˆ°é è¨­çš„é †åºã€‚ - - Colour - é¡è‰² + + Print + åˆ—å° - - Bold - ç²—é«” + + Print currently browsed table data + 列å°ç›®å‰ç€è¦½çš„資料表資料 - - Italic - 斜體 + + Print currently browsed table data. Print selection if more than one cell is selected. + 列å°ç›®å‰ç€è¦½çš„è³‡æ–™è¡¨è³‡æ–™ã€‚å¦‚æžœé¸æ“‡äº†å¤šå€‹å„²å­˜æ ¼ï¼Œå‰‡åˆ—å°é¸æ“‡çš„內容。 - - Underline - 底線 + + Ctrl+P + Ctrl+P - - Keyword - é—œéµå­— + + Refresh + 釿–°æ•´ç† - - function - 函數 + + Refresh the data in the selected table + 釿–°æ•´ç†é¸æ“‡çš„資料表中的資料 - - Function - 函數 + + This button refreshes the data in the currently selected table. + æ­¤æŒ‰éˆ•é‡æ–°æ•´ç†ç›®å‰é¸æ“‡çš„資料表中的資料。 - - Table - 資料表 + + F5 + F5 - - Comment - 注釋 + + Find in cells + 在儲存格中尋找 - - Identifier - 識別符 + + Open the find tool bar which allows you to search for values in the table view below. + 開啟尋找工具列,讓您å¯ä»¥åœ¨ä¸‹æ–¹çš„資料表檢視表中æœå°‹æ•¸å€¼ã€‚ - - String - 字串 + + + Bold + ç²—é«” - - currentline - ç›®å‰è¡Œ + + Ctrl+B + Ctrl+B - - Current line - ç›®å‰è¡Œ + + + Italic + 斜體 - - SQL &editor font size - SQL 編輯器字體大å°(&E) + + + Underline + 底線 - - SQL &log font size - SQL 日誌字體大å°(&L) + + Ctrl+U + Ctrl+U - - &Extensions - 擴充套件(&E) + + + Align Right + é å³å°é½Š - - Select extensions to load for every database: - 鏿“‡æ¯å€‹è³‡æ–™åº«è¦è¼‰å…¥çš„æ“´å……套件: + + + Align Left + é å·¦å°é½Š - - Add extension - 加入擴充套件 + + + Center Horizontally + 水平置中 - - Remove extension - 刪除擴充套件 + + + Justify + å·¦å³å°é½Š - - Choose a directory - 鏿“‡ä¸€å€‹ç›®éŒ„ + + + Edit Conditional Formats... + 編輯æ¢ä»¶æ ¼å¼... - - Select extension file - 鏿“‡æ“´å……套件檔 + + Edit conditional formats for the current column + ç·¨è¼¯ç›®å‰æ¬„ä½çš„æ¢ä»¶æ ¼å¼ - - Extensions(*.so *.dll);;All files(*) - 擴充套件(*.so *.dll);;所有擋檔案(*) + + Clear Format + æ¸…é™¤æ ¼å¼ - - - QObject - - Error importing data. Message from database engine: %1 - 匯入資料庫時出ç¾éŒ¯èª¤ã€‚消æ¯ä¾†è‡ªè³‡æ–™åº«å¼•擎: %1 + + Clear All Formats + æ¸…é™¤æ‰€æœ‰æ ¼å¼ - - File is not a SQLite 3 database - æª”æ¡ˆä¸æ˜¯ SQLite 3 資料庫 + + + Clear all cell formatting from selected cells and all conditional formats from selected columns + æ¸…é™¤é¸æ“‡çš„儲存格中的所有儲存格格å¼ï¼Œä»¥åŠé¸æ“‡çš„æ¬„ä½ä¸­çš„æ‰€æœ‰æ¢ä»¶æ ¼å¼ - - File could not be read - æª”æ¡ˆç„¡æ³•è®€å– + + + Font Color + å­—åž‹é¡è‰² - - - - no error - 無錯誤 + + + Background Color + 背景é¡è‰² - - Do you want to save the changes made to the database file %1? - æ‚¨æ˜¯å¦æƒ³å„²å­˜å°è³‡æ–™åº«æª”案 %1 åšå‡ºçš„修改? + + Toggle Format Toolbar + åˆ‡æ›æ ¼å¼å·¥å…·åˆ— - - Exporting database to SQL file... - 正在匯出資料庫到 SQL 檔案... + + Show/hide format toolbar + 顯示/éš±è—æ ¼å¼å·¥å…·åˆ— - - - - Cancel - å–æ¶ˆ + + + This button shows or hides the formatting toolbar of the Data Browser + 此按鈕顯示或隱è—資料ç€è¦½å™¨çš„æ ¼å¼å·¥å…·åˆ— - - Executing SQL... - 正在執行 SQL... + + Select column + 鏿“‡æ¬„ä½ - - Action cancelled. - æ“ä½œå·²å–æ¶ˆã€‚ + + Ctrl+Space + Ctrl+ç©ºç™½éµ - - - Error in statement #%1: %2. -Aborting execution. - éŒ¯èª¤åœ¨èªžå¥ #%1: %2。 -正在放棄執行。 + + Replace text in cells + å–代儲存格中的文字 - - renameColumn: cannot find table %1. - renameColumn: 無法查閱資料資料表 %1。 + + Freeze columns + å‡çµæ¬„ä½ - - renameColumn: cannot find column %1. - renameColumn: 無法查詢列 %1。 + + Make all columns from the first column up to this column not move when scrolling horizontally + 讓從第一個欄ä½åˆ°æ­¤æ¬„ä½çš„æ‰€æœ‰æ¬„ä½åœ¨æ°´å¹³æ²å‹•時ä¸ç§»å‹• - - renameColumn: creating savepoint failed. DB says: %1 - renameColumn: 建立ä¿å­˜é»žæ™‚失敗。DB 說: %1 + + Filter in any column + 在任何欄ä½ä¸­ç¯©é¸ - - renameColumn: creating new table failed. DB says: %1 - renameColumn: 建立新資料表時失敗。DB 說: %1 + + Ctrl+R + Ctrl+R - - - renameColumn: copying data to new table failed. DB says: -%1 - renameColumn: 複製資料到新資料表時失敗。DB 說: -%1 + + + %n row(s) + + %n 列 + - - - renameColumn: deleting old table failed. DB says: %1 - renameColumn: 刪除舊資料表失敗。DB 說: %1 + + + , %n column(s) + + ,%n æ¬„ä½ + - - Restoring some of the objects associated with this table failed. This is most likely because some column names changed. Here's the SQL statement which you might want to fix and execute manually: - - - 還原æŸäº›å’Œé€™å€‹è³‡æ–™è¡¨é—œè¯çš„物件失敗。這個最å¯èƒ½æ˜¯å› ç‚ºæŸäº›åˆ—çš„å稱修改了。這裡是您å¯èƒ½éœ€è¦æ‰‹å‹•修復和執行的 SQL 語å¥: - - + + . Sum: %1; Average: %2; Min: %3; Max: %4 + . 總計:%1;平å‡ï¼š%2;最å°å€¼ï¼š%3;最大值:%4 - - renameColumn: releasing savepoint failed. DB says: %1 - renameColumn: 釋放ä¿å­˜é»žæ™‚失敗。DB 說: %1 + + Conditional formats for "%1" + "%1" çš„æ¢ä»¶å¼æ ¼å¼ - - Error renaming table '%1' to '%2'.Message from database engine: -%3 - é‡å‘½å資料表 '%1' 為 '%2'時失敗。消æ¯ä¾†è‡ªè³‡æ–™åº«å¼•擎: -%3 + + determining row count... + 正在計算列數... - - ... <string can not be logged, contains binary data> ... - ... <字串無法記錄,包å«äºŒé€²ä½è³‡æ–™> ... + + %L1 - %L2 of >= %L3 + %L1 - %L2 / 總數 >= %L3 - - unknown object type %1 - 未知å°è±¡é¡žåž‹ %1 + + %L1 - %L2 of %L3 + %L1 - %L2 / 總數 %L3 - - could not get list of db objects: %1, %2 - 無法å–得資料庫物件的列表: %1, %2 + + (clipped at %L1 rows) + (在 %L1 列處截斷) - - could not get types - 無法å–得類型 + + Please enter a pseudo-primary key in order to enable editing on this view. This should be the name of a unique column in the view. + 請輸入一個å½ä¸»éµä»¥å•Ÿç”¨æ­¤æª¢è¦–表的編輯功能。這應該是檢視表中一個唯一欄ä½çš„å稱。 - - Decoding CSV file... - æ­£åœ¨è§£æž CSV 檔... + + Delete Records + 刪除記錄 - - didn't receive any output from pragma %1 - 無法接å—來自雜注 %1 的任何輸出 + + Duplicate records + 複製記錄 - - could not execute pragma command: %1, %2 - 無法執行雜注命令: %1, %2 + + Duplicate record + 複製記錄 - - Error setting pragma %1 to %2: %3 - 設定雜注 %1 為 %2 時出ç¾éŒ¯èª¤: %3 + + Ctrl+" + Ctrl+" - - File not found. - 找ä¸åˆ°æª”案。 + + Adjust rows to contents + èª¿æ•´åˆ—ä»¥é©æ‡‰å…§å®¹ - - - SqlExecutionArea - - Form - 表單 + + Error deleting record: +%1 + 刪除記錄時出ç¾éŒ¯èª¤ï¼š +%1 - - Results of the last executed statements - 最後執行語å¥çš„çµæžœ + + Please select a record first + è«‹å…ˆé¸æ“‡ä¸€ç­†è¨˜éŒ„ - - This field shows the results and status codes of the last executed statements. - 這個欄ä½é¡¯ç¤ºæœ€å¾ŒåŸ·è¡Œçš„語å¥çš„çµæžœå’Œç‹€æ…‹ç¢¼ã€‚ + + Please choose a new encoding for all tables. + è«‹ç‚ºæ‰€æœ‰è³‡æ–™è¡¨é¸æ“‡æ–°çš„編碼。 - - Export to &CSV - 匯出到 &CSV + + Please choose a new encoding for this table. + è«‹ç‚ºæ­¤è³‡æ–™è¡¨é¸æ“‡æ–°çš„編碼。 - - Save as &view - 儲存為視圖(&V) + + %1 +Leave the field empty for using the database encoding. + %1 +留空此欄ä½ä»¥ä½¿ç”¨è³‡æ–™åº«ç·¨ç¢¼ã€‚ - - Save as view - 儲存為視圖 + + This encoding is either not valid or not supported. + 此編碼無效或ä¸è¢«æ”¯æ´ã€‚ - - Please specify the view name - 請指定視圖å稱 + + %1 replacement(s) made. + 已進行 %1 次å–代。 + + + TableBrowserDock - - There is already an object with that name. Please choose a different name. - 已有相åŒå稱的å°è±¡ã€‚è«‹é¸æ“‡ä¸€å€‹ä¸åŒçš„å稱。 + + New Data Browser + 新資料ç€è¦½å™¨ - - View successfully created. - æˆåŠŸå»ºç«‹è¦–åœ–ã€‚ + + Rename Data Browser + 釿–°å‘½å資料ç€è¦½å™¨ - - Error creating view: %1 - 建立視圖時出ç¾éŒ¯èª¤: %1 + + Close Data Browser + 關閉資料ç€è¦½å™¨ - - - SqliteTableModel - - Error changing data: -%1 - 修改資料庫時出ç¾éŒ¯èª¤: -%1 + + Set a new name for the data browser. Use the '&&' character to allow using the following character as a keyboard shortcut. + 為資料ç€è¦½å™¨è¨­å®šæ–°å稱。使用 '&&' 字元以å…許使用後續字元作為éµç›¤å¿«æ·éµã€‚ @@ -2049,13 +8027,13 @@ Aborting execution. - Warning: Compacting the database will commit all changes you made. - 警告: 壓縮資料庫將會æäº¤æ‚¨åšå‡ºçš„æ‰€æœ‰ä¿®æ”¹ã€‚ + Warning: Compacting the database will commit all of your changes. + 警告:壓縮資料庫將會æäº¤æ‰€æœ‰æ‚¨çš„變更。 - Please select the objects to compact: - è«‹é¸æ“‡è¦å£“縮的物件: + Please select the databases to co&mpact: + è«‹é¸æ“‡è¦å£“縮的資料庫: diff --git a/src/translations/translations.qrc b/src/translations/translations.qrc index 3cd65c0f2..5b2b951cd 100644 --- a/src/translations/translations.qrc +++ b/src/translations/translations.qrc @@ -1,14 +1,24 @@ + sqlb_ar_SA.qm + sqlb_cs.qm sqlb_ru.qm sqlb_de.qm sqlb_fr.qm sqlb_zh.qm sqlb_zh_TW.qm + sqlb_pl.qm sqlb_pt_BR.qm sqlb_en_GB.qm sqlb_es_ES.qm sqlb_ko_KR.qm sqlb_tr.qm + sqlb_uk_UA.qm + sqlb_it.qm + sqlb_ja.qm + sqlb_nl.qm + sqlb_id.qm + sqlb_sv.qm + sqlb_ro.qm diff --git a/src/version.h b/src/version.h deleted file mode 100644 index 7f2fd7d54..000000000 --- a/src/version.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef GEN_VERSION_H -#define GEN_VERSION_H -#define MAJOR_VERSION 3 -#define MINOR_VERSION 8 -#define PATCH_VERSION 99 - -#define str(s) #s -#define xstr(s) str(s) -#define APP_VERSION xstr(MAJOR_VERSION) "." xstr(MINOR_VERSION) "." xstr(PATCH_VERSION) -#endif diff --git a/src/version.h.in b/src/version.h.in new file mode 100644 index 000000000..b88870583 --- /dev/null +++ b/src/version.h.in @@ -0,0 +1,15 @@ +// version file to be preprocessed by CMake +#ifndef GEN_VERSION_H +#define GEN_VERSION_H +#define MAJOR_VERSION @PROJECT_VERSION_MAJOR@ +#define MINOR_VERSION @PROJECT_VERSION_MINOR@ +#define PATCH_VERSION @PROJECT_VERSION_PATCH@ + +#define APP_VERSION "@PROJECT_VERSION@" + +// If it is defined by the compiler, then it is a nightly build, and in the YYYYMMDD format. +#ifndef BUILD_VERSION + #define BUILD_VERSION "0" +#endif + +#endif diff --git a/src/winapp.rc b/src/winapp.rc index 3bccc7be2..cc9d3ab10 100644 --- a/src/winapp.rc +++ b/src/winapp.rc @@ -1 +1,30 @@ -IDI_ICON1 ICON DISCARDABLE "iconwin.ico" \ No newline at end of file +#include +#include "version.h" + +VS_VERSION_INFO VERSIONINFO +FILEVERSION MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION, 0 +PRODUCTVERSION MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION, 0 +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_APP +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004B0" + BEGIN + VALUE "FileVersion", APP_VERSION "." BUILD_VERSION + VALUE "ProductVersion", APP_VERSION "." BUILD_VERSION + VALUE "FileDescription", "DB Browser for SQLite" + VALUE "ProductName", "DB Browser for SQLite" + VALUE "InternalName", "DB Browser for SQLite" + VALUE "OriginalFilename", "DB Browser for SQLite.exe" + VALUE "CompanyName", "DB Browser for SQLite Team" + VALUE "LegalCopyright", "Copyright © DB Browser for SQLite Team" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0000, 0x04B0 + END +END + +IDI_DB4S ICON "iconwin.ico"